xref: /openbmc/linux/drivers/net/wireless/ath/ath11k/hal.c (revision a61e365d)
1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /*
3  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4  */
5 #include <linux/dma-mapping.h>
6 #include "hal_tx.h"
7 #include "debug.h"
8 #include "hal_desc.h"
9 #include "hif.h"
10 
11 static const struct hal_srng_config hw_srng_config_template[] = {
12 	/* TODO: max_rings can populated by querying HW capabilities */
13 	{ /* REO_DST */
14 		.start_ring_id = HAL_SRNG_RING_ID_REO2SW1,
15 		.max_rings = 4,
16 		.entry_size = sizeof(struct hal_reo_dest_ring) >> 2,
17 		.lmac_ring = false,
18 		.ring_dir = HAL_SRNG_DIR_DST,
19 		.max_size = HAL_REO_REO2SW1_RING_BASE_MSB_RING_SIZE,
20 	},
21 	{ /* REO_EXCEPTION */
22 		/* Designating REO2TCL ring as exception ring. This ring is
23 		 * similar to other REO2SW rings though it is named as REO2TCL.
24 		 * Any of theREO2SW rings can be used as exception ring.
25 		 */
26 		.start_ring_id = HAL_SRNG_RING_ID_REO2TCL,
27 		.max_rings = 1,
28 		.entry_size = sizeof(struct hal_reo_dest_ring) >> 2,
29 		.lmac_ring = false,
30 		.ring_dir = HAL_SRNG_DIR_DST,
31 		.max_size = HAL_REO_REO2TCL_RING_BASE_MSB_RING_SIZE,
32 	},
33 	{ /* REO_REINJECT */
34 		.start_ring_id = HAL_SRNG_RING_ID_SW2REO,
35 		.max_rings = 1,
36 		.entry_size = sizeof(struct hal_reo_entrance_ring) >> 2,
37 		.lmac_ring = false,
38 		.ring_dir = HAL_SRNG_DIR_SRC,
39 		.max_size = HAL_REO_SW2REO_RING_BASE_MSB_RING_SIZE,
40 	},
41 	{ /* REO_CMD */
42 		.start_ring_id = HAL_SRNG_RING_ID_REO_CMD,
43 		.max_rings = 1,
44 		.entry_size = (sizeof(struct hal_tlv_hdr) +
45 			sizeof(struct hal_reo_get_queue_stats)) >> 2,
46 		.lmac_ring = false,
47 		.ring_dir = HAL_SRNG_DIR_SRC,
48 		.max_size = HAL_REO_CMD_RING_BASE_MSB_RING_SIZE,
49 	},
50 	{ /* REO_STATUS */
51 		.start_ring_id = HAL_SRNG_RING_ID_REO_STATUS,
52 		.max_rings = 1,
53 		.entry_size = (sizeof(struct hal_tlv_hdr) +
54 			sizeof(struct hal_reo_get_queue_stats_status)) >> 2,
55 		.lmac_ring = false,
56 		.ring_dir = HAL_SRNG_DIR_DST,
57 		.max_size = HAL_REO_STATUS_RING_BASE_MSB_RING_SIZE,
58 	},
59 	{ /* TCL_DATA */
60 		.start_ring_id = HAL_SRNG_RING_ID_SW2TCL1,
61 		.max_rings = 3,
62 		.entry_size = (sizeof(struct hal_tlv_hdr) +
63 			     sizeof(struct hal_tcl_data_cmd)) >> 2,
64 		.lmac_ring = false,
65 		.ring_dir = HAL_SRNG_DIR_SRC,
66 		.max_size = HAL_SW2TCL1_RING_BASE_MSB_RING_SIZE,
67 	},
68 	{ /* TCL_CMD */
69 		.start_ring_id = HAL_SRNG_RING_ID_SW2TCL_CMD,
70 		.max_rings = 1,
71 		.entry_size = (sizeof(struct hal_tlv_hdr) +
72 			     sizeof(struct hal_tcl_gse_cmd)) >> 2,
73 		.lmac_ring =  false,
74 		.ring_dir = HAL_SRNG_DIR_SRC,
75 		.max_size = HAL_SW2TCL1_CMD_RING_BASE_MSB_RING_SIZE,
76 	},
77 	{ /* TCL_STATUS */
78 		.start_ring_id = HAL_SRNG_RING_ID_TCL_STATUS,
79 		.max_rings = 1,
80 		.entry_size = (sizeof(struct hal_tlv_hdr) +
81 			     sizeof(struct hal_tcl_status_ring)) >> 2,
82 		.lmac_ring = false,
83 		.ring_dir = HAL_SRNG_DIR_DST,
84 		.max_size = HAL_TCL_STATUS_RING_BASE_MSB_RING_SIZE,
85 	},
86 	{ /* CE_SRC */
87 		.start_ring_id = HAL_SRNG_RING_ID_CE0_SRC,
88 		.max_rings = 12,
89 		.entry_size = sizeof(struct hal_ce_srng_src_desc) >> 2,
90 		.lmac_ring = false,
91 		.ring_dir = HAL_SRNG_DIR_SRC,
92 		.reg_start = {
93 			(HAL_SEQ_WCSS_UMAC_CE0_SRC_REG +
94 			 HAL_CE_DST_RING_BASE_LSB),
95 			HAL_SEQ_WCSS_UMAC_CE0_SRC_REG + HAL_CE_DST_RING_HP,
96 		},
97 		.reg_size = {
98 			(HAL_SEQ_WCSS_UMAC_CE1_SRC_REG -
99 			 HAL_SEQ_WCSS_UMAC_CE0_SRC_REG),
100 			(HAL_SEQ_WCSS_UMAC_CE1_SRC_REG -
101 			 HAL_SEQ_WCSS_UMAC_CE0_SRC_REG),
102 		},
103 		.max_size = HAL_CE_SRC_RING_BASE_MSB_RING_SIZE,
104 	},
105 	{ /* CE_DST */
106 		.start_ring_id = HAL_SRNG_RING_ID_CE0_DST,
107 		.max_rings = 12,
108 		.entry_size = sizeof(struct hal_ce_srng_dest_desc) >> 2,
109 		.lmac_ring = false,
110 		.ring_dir = HAL_SRNG_DIR_SRC,
111 		.reg_start = {
112 			(HAL_SEQ_WCSS_UMAC_CE0_DST_REG +
113 			 HAL_CE_DST_RING_BASE_LSB),
114 			HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_RING_HP,
115 		},
116 		.reg_size = {
117 			(HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
118 			 HAL_SEQ_WCSS_UMAC_CE0_DST_REG),
119 			(HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
120 			 HAL_SEQ_WCSS_UMAC_CE0_DST_REG),
121 		},
122 		.max_size = HAL_CE_DST_RING_BASE_MSB_RING_SIZE,
123 	},
124 	{ /* CE_DST_STATUS */
125 		.start_ring_id = HAL_SRNG_RING_ID_CE0_DST_STATUS,
126 		.max_rings = 12,
127 		.entry_size = sizeof(struct hal_ce_srng_dst_status_desc) >> 2,
128 		.lmac_ring = false,
129 		.ring_dir = HAL_SRNG_DIR_DST,
130 		.reg_start = {
131 			(HAL_SEQ_WCSS_UMAC_CE0_DST_REG +
132 			 HAL_CE_DST_STATUS_RING_BASE_LSB),
133 			(HAL_SEQ_WCSS_UMAC_CE0_DST_REG +
134 			 HAL_CE_DST_STATUS_RING_HP),
135 		},
136 		.reg_size = {
137 			(HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
138 			 HAL_SEQ_WCSS_UMAC_CE0_DST_REG),
139 			(HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
140 			 HAL_SEQ_WCSS_UMAC_CE0_DST_REG),
141 		},
142 		.max_size = HAL_CE_DST_STATUS_RING_BASE_MSB_RING_SIZE,
143 	},
144 	{ /* WBM_IDLE_LINK */
145 		.start_ring_id = HAL_SRNG_RING_ID_WBM_IDLE_LINK,
146 		.max_rings = 1,
147 		.entry_size = sizeof(struct hal_wbm_link_desc) >> 2,
148 		.lmac_ring = false,
149 		.ring_dir = HAL_SRNG_DIR_SRC,
150 		.reg_start = {
151 			(HAL_SEQ_WCSS_UMAC_WBM_REG +
152 			 HAL_WBM_IDLE_LINK_RING_BASE_LSB),
153 			(HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_HP),
154 		},
155 		.max_size = HAL_WBM_IDLE_LINK_RING_BASE_MSB_RING_SIZE,
156 	},
157 	{ /* SW2WBM_RELEASE */
158 		.start_ring_id = HAL_SRNG_RING_ID_WBM_SW_RELEASE,
159 		.max_rings = 1,
160 		.entry_size = sizeof(struct hal_wbm_release_ring) >> 2,
161 		.lmac_ring = false,
162 		.ring_dir = HAL_SRNG_DIR_SRC,
163 		.reg_start = {
164 			(HAL_SEQ_WCSS_UMAC_WBM_REG +
165 			 HAL_WBM_RELEASE_RING_BASE_LSB),
166 			(HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_RELEASE_RING_HP),
167 		},
168 		.max_size = HAL_SW2WBM_RELEASE_RING_BASE_MSB_RING_SIZE,
169 	},
170 	{ /* WBM2SW_RELEASE */
171 		.start_ring_id = HAL_SRNG_RING_ID_WBM2SW0_RELEASE,
172 		.max_rings = 4,
173 		.entry_size = sizeof(struct hal_wbm_release_ring) >> 2,
174 		.lmac_ring = false,
175 		.ring_dir = HAL_SRNG_DIR_DST,
176 		.reg_start = {
177 			(HAL_SEQ_WCSS_UMAC_WBM_REG +
178 			 HAL_WBM0_RELEASE_RING_BASE_LSB),
179 			(HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM0_RELEASE_RING_HP),
180 		},
181 		.reg_size = {
182 			(HAL_WBM1_RELEASE_RING_BASE_LSB -
183 			 HAL_WBM0_RELEASE_RING_BASE_LSB),
184 			(HAL_WBM1_RELEASE_RING_HP - HAL_WBM0_RELEASE_RING_HP),
185 		},
186 		.max_size = HAL_WBM2SW_RELEASE_RING_BASE_MSB_RING_SIZE,
187 	},
188 	{ /* RXDMA_BUF */
189 		.start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXDMA0_BUF,
190 		.max_rings = 2,
191 		.entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2,
192 		.lmac_ring = true,
193 		.ring_dir = HAL_SRNG_DIR_SRC,
194 		.max_size = HAL_RXDMA_RING_MAX_SIZE,
195 	},
196 	{ /* RXDMA_DST */
197 		.start_ring_id = HAL_SRNG_RING_ID_WMAC1_RXDMA2SW0,
198 		.max_rings = 1,
199 		.entry_size = sizeof(struct hal_reo_entrance_ring) >> 2,
200 		.lmac_ring = true,
201 		.ring_dir = HAL_SRNG_DIR_DST,
202 		.max_size = HAL_RXDMA_RING_MAX_SIZE,
203 	},
204 	{ /* RXDMA_MONITOR_BUF */
205 		.start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXDMA2_BUF,
206 		.max_rings = 1,
207 		.entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2,
208 		.lmac_ring = true,
209 		.ring_dir = HAL_SRNG_DIR_SRC,
210 		.max_size = HAL_RXDMA_RING_MAX_SIZE,
211 	},
212 	{ /* RXDMA_MONITOR_STATUS */
213 		.start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_STATBUF,
214 		.max_rings = 1,
215 		.entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2,
216 		.lmac_ring = true,
217 		.ring_dir = HAL_SRNG_DIR_SRC,
218 		.max_size = HAL_RXDMA_RING_MAX_SIZE,
219 	},
220 	{ /* RXDMA_MONITOR_DST */
221 		.start_ring_id = HAL_SRNG_RING_ID_WMAC1_RXDMA2SW1,
222 		.max_rings = 1,
223 		.entry_size = sizeof(struct hal_reo_entrance_ring) >> 2,
224 		.lmac_ring = true,
225 		.ring_dir = HAL_SRNG_DIR_DST,
226 		.max_size = HAL_RXDMA_RING_MAX_SIZE,
227 	},
228 	{ /* RXDMA_MONITOR_DESC */
229 		.start_ring_id = HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_DESC,
230 		.max_rings = 1,
231 		.entry_size = sizeof(struct hal_wbm_buffer_ring) >> 2,
232 		.lmac_ring = true,
233 		.ring_dir = HAL_SRNG_DIR_SRC,
234 		.max_size = HAL_RXDMA_RING_MAX_SIZE,
235 	},
236 	{ /* RXDMA DIR BUF */
237 		.start_ring_id = HAL_SRNG_RING_ID_RXDMA_DIR_BUF,
238 		.max_rings = 1,
239 		.entry_size = 8 >> 2, /* TODO: Define the struct */
240 		.lmac_ring = true,
241 		.ring_dir = HAL_SRNG_DIR_SRC,
242 		.max_size = HAL_RXDMA_RING_MAX_SIZE,
243 	},
244 };
245 
246 static int ath11k_hal_alloc_cont_rdp(struct ath11k_base *ab)
247 {
248 	struct ath11k_hal *hal = &ab->hal;
249 	size_t size;
250 
251 	size = sizeof(u32) * HAL_SRNG_RING_ID_MAX;
252 	hal->rdp.vaddr = dma_alloc_coherent(ab->dev, size, &hal->rdp.paddr,
253 					    GFP_KERNEL);
254 	if (!hal->rdp.vaddr)
255 		return -ENOMEM;
256 
257 	return 0;
258 }
259 
260 static void ath11k_hal_free_cont_rdp(struct ath11k_base *ab)
261 {
262 	struct ath11k_hal *hal = &ab->hal;
263 	size_t size;
264 
265 	if (!hal->rdp.vaddr)
266 		return;
267 
268 	size = sizeof(u32) * HAL_SRNG_RING_ID_MAX;
269 	dma_free_coherent(ab->dev, size,
270 			  hal->rdp.vaddr, hal->rdp.paddr);
271 	hal->rdp.vaddr = NULL;
272 }
273 
274 static int ath11k_hal_alloc_cont_wrp(struct ath11k_base *ab)
275 {
276 	struct ath11k_hal *hal = &ab->hal;
277 	size_t size;
278 
279 	size = sizeof(u32) * HAL_SRNG_NUM_LMAC_RINGS;
280 	hal->wrp.vaddr = dma_alloc_coherent(ab->dev, size, &hal->wrp.paddr,
281 					    GFP_KERNEL);
282 	if (!hal->wrp.vaddr)
283 		return -ENOMEM;
284 
285 	return 0;
286 }
287 
288 static void ath11k_hal_free_cont_wrp(struct ath11k_base *ab)
289 {
290 	struct ath11k_hal *hal = &ab->hal;
291 	size_t size;
292 
293 	if (!hal->wrp.vaddr)
294 		return;
295 
296 	size = sizeof(u32) * HAL_SRNG_NUM_LMAC_RINGS;
297 	dma_free_coherent(ab->dev, size,
298 			  hal->wrp.vaddr, hal->wrp.paddr);
299 	hal->wrp.vaddr = NULL;
300 }
301 
302 static void ath11k_hal_ce_dst_setup(struct ath11k_base *ab,
303 				    struct hal_srng *srng, int ring_num)
304 {
305 	struct hal_srng_config *srng_config = &ab->hal.srng_config[HAL_CE_DST];
306 	u32 addr;
307 	u32 val;
308 
309 	addr = HAL_CE_DST_RING_CTRL +
310 	       srng_config->reg_start[HAL_SRNG_REG_GRP_R0] +
311 	       ring_num * srng_config->reg_size[HAL_SRNG_REG_GRP_R0];
312 
313 	val = ath11k_hif_read32(ab, addr);
314 	val &= ~HAL_CE_DST_R0_DEST_CTRL_MAX_LEN;
315 	val |= FIELD_PREP(HAL_CE_DST_R0_DEST_CTRL_MAX_LEN,
316 			  srng->u.dst_ring.max_buffer_length);
317 	ath11k_hif_write32(ab, addr, val);
318 }
319 
320 static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab,
321 					struct hal_srng *srng)
322 {
323 	struct ath11k_hal *hal = &ab->hal;
324 	u32 val;
325 	u64 hp_addr;
326 	u32 reg_base;
327 
328 	reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
329 
330 	if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) {
331 		ath11k_hif_write32(ab, reg_base +
332 				   HAL_REO1_RING_MSI1_BASE_LSB_OFFSET(ab),
333 				   (u32)srng->msi_addr);
334 
335 		val = FIELD_PREP(HAL_REO1_RING_MSI1_BASE_MSB_ADDR,
336 				 ((u64)srng->msi_addr >>
337 				  HAL_ADDR_MSB_REG_SHIFT)) |
338 		      HAL_REO1_RING_MSI1_BASE_MSB_MSI1_ENABLE;
339 		ath11k_hif_write32(ab, reg_base +
340 				       HAL_REO1_RING_MSI1_BASE_MSB_OFFSET(ab), val);
341 
342 		ath11k_hif_write32(ab,
343 				   reg_base + HAL_REO1_RING_MSI1_DATA_OFFSET(ab),
344 				   srng->msi_data);
345 	}
346 
347 	ath11k_hif_write32(ab, reg_base, (u32)srng->ring_base_paddr);
348 
349 	val = FIELD_PREP(HAL_REO1_RING_BASE_MSB_RING_BASE_ADDR_MSB,
350 			 ((u64)srng->ring_base_paddr >>
351 			  HAL_ADDR_MSB_REG_SHIFT)) |
352 	      FIELD_PREP(HAL_REO1_RING_BASE_MSB_RING_SIZE,
353 			 (srng->entry_size * srng->num_entries));
354 	ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_BASE_MSB_OFFSET(ab), val);
355 
356 	val = FIELD_PREP(HAL_REO1_RING_ID_RING_ID, srng->ring_id) |
357 	      FIELD_PREP(HAL_REO1_RING_ID_ENTRY_SIZE, srng->entry_size);
358 	ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_ID_OFFSET(ab), val);
359 
360 	/* interrupt setup */
361 	val = FIELD_PREP(HAL_REO1_RING_PRDR_INT_SETUP_INTR_TMR_THOLD,
362 			 (srng->intr_timer_thres_us >> 3));
363 
364 	val |= FIELD_PREP(HAL_REO1_RING_PRDR_INT_SETUP_BATCH_COUNTER_THOLD,
365 			  (srng->intr_batch_cntr_thres_entries *
366 			   srng->entry_size));
367 
368 	ath11k_hif_write32(ab,
369 			   reg_base + HAL_REO1_RING_PRODUCER_INT_SETUP_OFFSET(ab),
370 			   val);
371 
372 	hp_addr = hal->rdp.paddr +
373 		  ((unsigned long)srng->u.dst_ring.hp_addr -
374 		   (unsigned long)hal->rdp.vaddr);
375 	ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_HP_ADDR_LSB_OFFSET(ab),
376 			   hp_addr & HAL_ADDR_LSB_REG_MASK);
377 	ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_HP_ADDR_MSB_OFFSET(ab),
378 			   hp_addr >> HAL_ADDR_MSB_REG_SHIFT);
379 
380 	/* Initialize head and tail pointers to indicate ring is empty */
381 	reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2];
382 	ath11k_hif_write32(ab, reg_base, 0);
383 	ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_TP_OFFSET(ab), 0);
384 	*srng->u.dst_ring.hp_addr = 0;
385 
386 	reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
387 	val = 0;
388 	if (srng->flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP)
389 		val |= HAL_REO1_RING_MISC_DATA_TLV_SWAP;
390 	if (srng->flags & HAL_SRNG_FLAGS_RING_PTR_SWAP)
391 		val |= HAL_REO1_RING_MISC_HOST_FW_SWAP;
392 	if (srng->flags & HAL_SRNG_FLAGS_MSI_SWAP)
393 		val |= HAL_REO1_RING_MISC_MSI_SWAP;
394 	val |= HAL_REO1_RING_MISC_SRNG_ENABLE;
395 
396 	ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_MISC_OFFSET(ab), val);
397 }
398 
399 static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab,
400 					struct hal_srng *srng)
401 {
402 	struct ath11k_hal *hal = &ab->hal;
403 	u32 val;
404 	u64 tp_addr;
405 	u32 reg_base;
406 
407 	reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
408 
409 	if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) {
410 		ath11k_hif_write32(ab, reg_base +
411 				   HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET(ab),
412 				   (u32)srng->msi_addr);
413 
414 		val = FIELD_PREP(HAL_TCL1_RING_MSI1_BASE_MSB_ADDR,
415 				 ((u64)srng->msi_addr >>
416 				  HAL_ADDR_MSB_REG_SHIFT)) |
417 		      HAL_TCL1_RING_MSI1_BASE_MSB_MSI1_ENABLE;
418 		ath11k_hif_write32(ab, reg_base +
419 				       HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET(ab),
420 				   val);
421 
422 		ath11k_hif_write32(ab, reg_base +
423 				       HAL_TCL1_RING_MSI1_DATA_OFFSET(ab),
424 				   srng->msi_data);
425 	}
426 
427 	ath11k_hif_write32(ab, reg_base, (u32)srng->ring_base_paddr);
428 
429 	val = FIELD_PREP(HAL_TCL1_RING_BASE_MSB_RING_BASE_ADDR_MSB,
430 			 ((u64)srng->ring_base_paddr >>
431 			  HAL_ADDR_MSB_REG_SHIFT)) |
432 	      FIELD_PREP(HAL_TCL1_RING_BASE_MSB_RING_SIZE,
433 			 (srng->entry_size * srng->num_entries));
434 	ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_BASE_MSB_OFFSET(ab), val);
435 
436 	val = FIELD_PREP(HAL_REO1_RING_ID_ENTRY_SIZE, srng->entry_size);
437 	ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_ID_OFFSET(ab), val);
438 
439 	/* interrupt setup */
440 	/* NOTE: IPQ8074 v2 requires the interrupt timer threshold in the
441 	 * unit of 8 usecs instead of 1 usec (as required by v1).
442 	 */
443 	val = FIELD_PREP(HAL_TCL1_RING_CONSR_INT_SETUP_IX0_INTR_TMR_THOLD,
444 			 srng->intr_timer_thres_us);
445 
446 	val |= FIELD_PREP(HAL_TCL1_RING_CONSR_INT_SETUP_IX0_BATCH_COUNTER_THOLD,
447 			  (srng->intr_batch_cntr_thres_entries *
448 			   srng->entry_size));
449 
450 	ath11k_hif_write32(ab,
451 			   reg_base + HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET(ab),
452 			   val);
453 
454 	val = 0;
455 	if (srng->flags & HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN) {
456 		val |= FIELD_PREP(HAL_TCL1_RING_CONSR_INT_SETUP_IX1_LOW_THOLD,
457 				  srng->u.src_ring.low_threshold);
458 	}
459 	ath11k_hif_write32(ab,
460 			   reg_base + HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET(ab),
461 			   val);
462 
463 	if (srng->ring_id != HAL_SRNG_RING_ID_WBM_IDLE_LINK) {
464 		tp_addr = hal->rdp.paddr +
465 			  ((unsigned long)srng->u.src_ring.tp_addr -
466 			   (unsigned long)hal->rdp.vaddr);
467 		ath11k_hif_write32(ab,
468 				   reg_base + HAL_TCL1_RING_TP_ADDR_LSB_OFFSET(ab),
469 				   tp_addr & HAL_ADDR_LSB_REG_MASK);
470 		ath11k_hif_write32(ab,
471 				   reg_base + HAL_TCL1_RING_TP_ADDR_MSB_OFFSET(ab),
472 				   tp_addr >> HAL_ADDR_MSB_REG_SHIFT);
473 	}
474 
475 	/* Initialize head and tail pointers to indicate ring is empty */
476 	reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2];
477 	ath11k_hif_write32(ab, reg_base, 0);
478 	ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_TP_OFFSET, 0);
479 	*srng->u.src_ring.tp_addr = 0;
480 
481 	reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
482 	val = 0;
483 	if (srng->flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP)
484 		val |= HAL_TCL1_RING_MISC_DATA_TLV_SWAP;
485 	if (srng->flags & HAL_SRNG_FLAGS_RING_PTR_SWAP)
486 		val |= HAL_TCL1_RING_MISC_HOST_FW_SWAP;
487 	if (srng->flags & HAL_SRNG_FLAGS_MSI_SWAP)
488 		val |= HAL_TCL1_RING_MISC_MSI_SWAP;
489 
490 	/* Loop count is not used for SRC rings */
491 	val |= HAL_TCL1_RING_MISC_MSI_LOOPCNT_DISABLE;
492 
493 	val |= HAL_TCL1_RING_MISC_SRNG_ENABLE;
494 
495 	ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_MISC_OFFSET(ab), val);
496 }
497 
498 static void ath11k_hal_srng_hw_init(struct ath11k_base *ab,
499 				    struct hal_srng *srng)
500 {
501 	if (srng->ring_dir == HAL_SRNG_DIR_SRC)
502 		ath11k_hal_srng_src_hw_init(ab, srng);
503 	else
504 		ath11k_hal_srng_dst_hw_init(ab, srng);
505 }
506 
507 static int ath11k_hal_srng_get_ring_id(struct ath11k_base *ab,
508 				       enum hal_ring_type type,
509 				       int ring_num, int mac_id)
510 {
511 	struct hal_srng_config *srng_config = &ab->hal.srng_config[type];
512 	int ring_id;
513 
514 	if (ring_num >= srng_config->max_rings) {
515 		ath11k_warn(ab, "invalid ring number :%d\n", ring_num);
516 		return -EINVAL;
517 	}
518 
519 	ring_id = srng_config->start_ring_id + ring_num;
520 	if (srng_config->lmac_ring)
521 		ring_id += mac_id * HAL_SRNG_RINGS_PER_LMAC;
522 
523 	if (WARN_ON(ring_id >= HAL_SRNG_RING_ID_MAX))
524 		return -EINVAL;
525 
526 	return ring_id;
527 }
528 
529 int ath11k_hal_srng_get_entrysize(struct ath11k_base *ab, u32 ring_type)
530 {
531 	struct hal_srng_config *srng_config;
532 
533 	if (WARN_ON(ring_type >= HAL_MAX_RING_TYPES))
534 		return -EINVAL;
535 
536 	srng_config = &ab->hal.srng_config[ring_type];
537 
538 	return (srng_config->entry_size << 2);
539 }
540 
541 int ath11k_hal_srng_get_max_entries(struct ath11k_base *ab, u32 ring_type)
542 {
543 	struct hal_srng_config *srng_config;
544 
545 	if (WARN_ON(ring_type >= HAL_MAX_RING_TYPES))
546 		return -EINVAL;
547 
548 	srng_config = &ab->hal.srng_config[ring_type];
549 
550 	return (srng_config->max_size / srng_config->entry_size);
551 }
552 
553 void ath11k_hal_srng_get_params(struct ath11k_base *ab, struct hal_srng *srng,
554 				struct hal_srng_params *params)
555 {
556 	params->ring_base_paddr = srng->ring_base_paddr;
557 	params->ring_base_vaddr = srng->ring_base_vaddr;
558 	params->num_entries = srng->num_entries;
559 	params->intr_timer_thres_us = srng->intr_timer_thres_us;
560 	params->intr_batch_cntr_thres_entries =
561 		srng->intr_batch_cntr_thres_entries;
562 	params->low_threshold = srng->u.src_ring.low_threshold;
563 	params->flags = srng->flags;
564 }
565 
566 dma_addr_t ath11k_hal_srng_get_hp_addr(struct ath11k_base *ab,
567 				       struct hal_srng *srng)
568 {
569 	if (!(srng->flags & HAL_SRNG_FLAGS_LMAC_RING))
570 		return 0;
571 
572 	if (srng->ring_dir == HAL_SRNG_DIR_SRC)
573 		return ab->hal.wrp.paddr +
574 		       ((unsigned long)srng->u.src_ring.hp_addr -
575 			(unsigned long)ab->hal.wrp.vaddr);
576 	else
577 		return ab->hal.rdp.paddr +
578 		       ((unsigned long)srng->u.dst_ring.hp_addr -
579 			 (unsigned long)ab->hal.rdp.vaddr);
580 }
581 
582 dma_addr_t ath11k_hal_srng_get_tp_addr(struct ath11k_base *ab,
583 				       struct hal_srng *srng)
584 {
585 	if (!(srng->flags & HAL_SRNG_FLAGS_LMAC_RING))
586 		return 0;
587 
588 	if (srng->ring_dir == HAL_SRNG_DIR_SRC)
589 		return ab->hal.rdp.paddr +
590 		       ((unsigned long)srng->u.src_ring.tp_addr -
591 			(unsigned long)ab->hal.rdp.vaddr);
592 	else
593 		return ab->hal.wrp.paddr +
594 		       ((unsigned long)srng->u.dst_ring.tp_addr -
595 			(unsigned long)ab->hal.wrp.vaddr);
596 }
597 
598 u32 ath11k_hal_ce_get_desc_size(enum hal_ce_desc type)
599 {
600 	switch (type) {
601 	case HAL_CE_DESC_SRC:
602 		return sizeof(struct hal_ce_srng_src_desc);
603 	case HAL_CE_DESC_DST:
604 		return sizeof(struct hal_ce_srng_dest_desc);
605 	case HAL_CE_DESC_DST_STATUS:
606 		return sizeof(struct hal_ce_srng_dst_status_desc);
607 	}
608 
609 	return 0;
610 }
611 
612 void ath11k_hal_ce_src_set_desc(void *buf, dma_addr_t paddr, u32 len, u32 id,
613 				u8 byte_swap_data)
614 {
615 	struct hal_ce_srng_src_desc *desc = (struct hal_ce_srng_src_desc *)buf;
616 
617 	desc->buffer_addr_low = paddr & HAL_ADDR_LSB_REG_MASK;
618 	desc->buffer_addr_info =
619 		FIELD_PREP(HAL_CE_SRC_DESC_ADDR_INFO_ADDR_HI,
620 			   ((u64)paddr >> HAL_ADDR_MSB_REG_SHIFT)) |
621 		FIELD_PREP(HAL_CE_SRC_DESC_ADDR_INFO_BYTE_SWAP,
622 			   byte_swap_data) |
623 		FIELD_PREP(HAL_CE_SRC_DESC_ADDR_INFO_GATHER, 0) |
624 		FIELD_PREP(HAL_CE_SRC_DESC_ADDR_INFO_LEN, len);
625 	desc->meta_info = FIELD_PREP(HAL_CE_SRC_DESC_META_INFO_DATA, id);
626 }
627 
628 void ath11k_hal_ce_dst_set_desc(void *buf, dma_addr_t paddr)
629 {
630 	struct hal_ce_srng_dest_desc *desc =
631 		(struct hal_ce_srng_dest_desc *)buf;
632 
633 	desc->buffer_addr_low = paddr & HAL_ADDR_LSB_REG_MASK;
634 	desc->buffer_addr_info =
635 		FIELD_PREP(HAL_CE_DEST_DESC_ADDR_INFO_ADDR_HI,
636 			   ((u64)paddr >> HAL_ADDR_MSB_REG_SHIFT));
637 }
638 
639 u32 ath11k_hal_ce_dst_status_get_length(void *buf)
640 {
641 	struct hal_ce_srng_dst_status_desc *desc =
642 		(struct hal_ce_srng_dst_status_desc *)buf;
643 	u32 len;
644 
645 	len = FIELD_GET(HAL_CE_DST_STATUS_DESC_FLAGS_LEN, desc->flags);
646 	desc->flags &= ~HAL_CE_DST_STATUS_DESC_FLAGS_LEN;
647 
648 	return len;
649 }
650 
651 void ath11k_hal_set_link_desc_addr(struct hal_wbm_link_desc *desc, u32 cookie,
652 				   dma_addr_t paddr)
653 {
654 	desc->buf_addr_info.info0 = FIELD_PREP(BUFFER_ADDR_INFO0_ADDR,
655 					       (paddr & HAL_ADDR_LSB_REG_MASK));
656 	desc->buf_addr_info.info1 = FIELD_PREP(BUFFER_ADDR_INFO1_ADDR,
657 					       ((u64)paddr >> HAL_ADDR_MSB_REG_SHIFT)) |
658 				    FIELD_PREP(BUFFER_ADDR_INFO1_RET_BUF_MGR, 1) |
659 				    FIELD_PREP(BUFFER_ADDR_INFO1_SW_COOKIE, cookie);
660 }
661 
662 u32 *ath11k_hal_srng_dst_peek(struct ath11k_base *ab, struct hal_srng *srng)
663 {
664 	lockdep_assert_held(&srng->lock);
665 
666 	if (srng->u.dst_ring.tp != srng->u.dst_ring.cached_hp)
667 		return (srng->ring_base_vaddr + srng->u.dst_ring.tp);
668 
669 	return NULL;
670 }
671 
672 u32 *ath11k_hal_srng_dst_get_next_entry(struct ath11k_base *ab,
673 					struct hal_srng *srng)
674 {
675 	u32 *desc;
676 
677 	lockdep_assert_held(&srng->lock);
678 
679 	if (srng->u.dst_ring.tp == srng->u.dst_ring.cached_hp)
680 		return NULL;
681 
682 	desc = srng->ring_base_vaddr + srng->u.dst_ring.tp;
683 
684 	srng->u.dst_ring.tp = (srng->u.dst_ring.tp + srng->entry_size) %
685 			      srng->ring_size;
686 
687 	return desc;
688 }
689 
690 int ath11k_hal_srng_dst_num_free(struct ath11k_base *ab, struct hal_srng *srng,
691 				 bool sync_hw_ptr)
692 {
693 	u32 tp, hp;
694 
695 	lockdep_assert_held(&srng->lock);
696 
697 	tp = srng->u.dst_ring.tp;
698 
699 	if (sync_hw_ptr) {
700 		hp = *srng->u.dst_ring.hp_addr;
701 		srng->u.dst_ring.cached_hp = hp;
702 	} else {
703 		hp = srng->u.dst_ring.cached_hp;
704 	}
705 
706 	if (hp >= tp)
707 		return (hp - tp) / srng->entry_size;
708 	else
709 		return (srng->ring_size - tp + hp) / srng->entry_size;
710 }
711 
712 /* Returns number of available entries in src ring */
713 int ath11k_hal_srng_src_num_free(struct ath11k_base *ab, struct hal_srng *srng,
714 				 bool sync_hw_ptr)
715 {
716 	u32 tp, hp;
717 
718 	lockdep_assert_held(&srng->lock);
719 
720 	hp = srng->u.src_ring.hp;
721 
722 	if (sync_hw_ptr) {
723 		tp = *srng->u.src_ring.tp_addr;
724 		srng->u.src_ring.cached_tp = tp;
725 	} else {
726 		tp = srng->u.src_ring.cached_tp;
727 	}
728 
729 	if (tp > hp)
730 		return ((tp - hp) / srng->entry_size) - 1;
731 	else
732 		return ((srng->ring_size - hp + tp) / srng->entry_size) - 1;
733 }
734 
735 u32 *ath11k_hal_srng_src_get_next_entry(struct ath11k_base *ab,
736 					struct hal_srng *srng)
737 {
738 	u32 *desc;
739 	u32 next_hp;
740 
741 	lockdep_assert_held(&srng->lock);
742 
743 	/* TODO: Using % is expensive, but we have to do this since size of some
744 	 * SRNG rings is not power of 2 (due to descriptor sizes). Need to see
745 	 * if separate function is defined for rings having power of 2 ring size
746 	 * (TCL2SW, REO2SW, SW2RXDMA and CE rings) so that we can avoid the
747 	 * overhead of % by using mask (with &).
748 	 */
749 	next_hp = (srng->u.src_ring.hp + srng->entry_size) % srng->ring_size;
750 
751 	if (next_hp == srng->u.src_ring.cached_tp)
752 		return NULL;
753 
754 	desc = srng->ring_base_vaddr + srng->u.src_ring.hp;
755 	srng->u.src_ring.hp = next_hp;
756 
757 	/* TODO: Reap functionality is not used by all rings. If particular
758 	 * ring does not use reap functionality, we need not update reap_hp
759 	 * with next_hp pointer. Need to make sure a separate function is used
760 	 * before doing any optimization by removing below code updating
761 	 * reap_hp.
762 	 */
763 	srng->u.src_ring.reap_hp = next_hp;
764 
765 	return desc;
766 }
767 
768 u32 *ath11k_hal_srng_src_reap_next(struct ath11k_base *ab,
769 				   struct hal_srng *srng)
770 {
771 	u32 *desc;
772 	u32 next_reap_hp;
773 
774 	lockdep_assert_held(&srng->lock);
775 
776 	next_reap_hp = (srng->u.src_ring.reap_hp + srng->entry_size) %
777 		       srng->ring_size;
778 
779 	if (next_reap_hp == srng->u.src_ring.cached_tp)
780 		return NULL;
781 
782 	desc = srng->ring_base_vaddr + next_reap_hp;
783 	srng->u.src_ring.reap_hp = next_reap_hp;
784 
785 	return desc;
786 }
787 
788 u32 *ath11k_hal_srng_src_get_next_reaped(struct ath11k_base *ab,
789 					 struct hal_srng *srng)
790 {
791 	u32 *desc;
792 
793 	lockdep_assert_held(&srng->lock);
794 
795 	if (srng->u.src_ring.hp == srng->u.src_ring.reap_hp)
796 		return NULL;
797 
798 	desc = srng->ring_base_vaddr + srng->u.src_ring.hp;
799 	srng->u.src_ring.hp = (srng->u.src_ring.hp + srng->entry_size) %
800 			      srng->ring_size;
801 
802 	return desc;
803 }
804 
805 u32 *ath11k_hal_srng_src_peek(struct ath11k_base *ab, struct hal_srng *srng)
806 {
807 	lockdep_assert_held(&srng->lock);
808 
809 	if (((srng->u.src_ring.hp + srng->entry_size) % srng->ring_size) ==
810 	    srng->u.src_ring.cached_tp)
811 		return NULL;
812 
813 	return srng->ring_base_vaddr + srng->u.src_ring.hp;
814 }
815 
816 void ath11k_hal_srng_access_begin(struct ath11k_base *ab, struct hal_srng *srng)
817 {
818 	lockdep_assert_held(&srng->lock);
819 
820 	if (srng->ring_dir == HAL_SRNG_DIR_SRC)
821 		srng->u.src_ring.cached_tp =
822 			*(volatile u32 *)srng->u.src_ring.tp_addr;
823 	else
824 		srng->u.dst_ring.cached_hp = *srng->u.dst_ring.hp_addr;
825 }
826 
827 /* Update cached ring head/tail pointers to HW. ath11k_hal_srng_access_begin()
828  * should have been called before this.
829  */
830 void ath11k_hal_srng_access_end(struct ath11k_base *ab, struct hal_srng *srng)
831 {
832 	lockdep_assert_held(&srng->lock);
833 
834 	/* TODO: See if we need a write memory barrier here */
835 	if (srng->flags & HAL_SRNG_FLAGS_LMAC_RING) {
836 		/* For LMAC rings, ring pointer updates are done through FW and
837 		 * hence written to a shared memory location that is read by FW
838 		 */
839 		if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
840 			srng->u.src_ring.last_tp =
841 				*(volatile u32 *)srng->u.src_ring.tp_addr;
842 			*srng->u.src_ring.hp_addr = srng->u.src_ring.hp;
843 		} else {
844 			srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr;
845 			*srng->u.dst_ring.tp_addr = srng->u.dst_ring.tp;
846 		}
847 	} else {
848 		if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
849 			srng->u.src_ring.last_tp =
850 				*(volatile u32 *)srng->u.src_ring.tp_addr;
851 			ath11k_hif_write32(ab,
852 					   (unsigned long)srng->u.src_ring.hp_addr -
853 					   (unsigned long)ab->mem,
854 					   srng->u.src_ring.hp);
855 		} else {
856 			srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr;
857 			ath11k_hif_write32(ab,
858 					   (unsigned long)srng->u.dst_ring.tp_addr -
859 					   (unsigned long)ab->mem,
860 					   srng->u.dst_ring.tp);
861 		}
862 	}
863 
864 	srng->timestamp = jiffies;
865 }
866 
867 void ath11k_hal_setup_link_idle_list(struct ath11k_base *ab,
868 				     struct hal_wbm_idle_scatter_list *sbuf,
869 				     u32 nsbufs, u32 tot_link_desc,
870 				     u32 end_offset)
871 {
872 	struct ath11k_buffer_addr *link_addr;
873 	int i;
874 	u32 reg_scatter_buf_sz = HAL_WBM_IDLE_SCATTER_BUF_SIZE / 64;
875 
876 	link_addr = (void *)sbuf[0].vaddr + HAL_WBM_IDLE_SCATTER_BUF_SIZE;
877 
878 	for (i = 1; i < nsbufs; i++) {
879 		link_addr->info0 = sbuf[i].paddr & HAL_ADDR_LSB_REG_MASK;
880 		link_addr->info1 = FIELD_PREP(
881 				HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32,
882 				(u64)sbuf[i].paddr >> HAL_ADDR_MSB_REG_SHIFT) |
883 				FIELD_PREP(
884 				HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_MATCH_TAG,
885 				BASE_ADDR_MATCH_TAG_VAL);
886 
887 		link_addr = (void *)sbuf[i].vaddr +
888 			     HAL_WBM_IDLE_SCATTER_BUF_SIZE;
889 	}
890 
891 	ath11k_hif_write32(ab,
892 			   HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_R0_IDLE_LIST_CONTROL_ADDR,
893 			   FIELD_PREP(HAL_WBM_SCATTER_BUFFER_SIZE, reg_scatter_buf_sz) |
894 			   FIELD_PREP(HAL_WBM_LINK_DESC_IDLE_LIST_MODE, 0x1));
895 	ath11k_hif_write32(ab,
896 			   HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_R0_IDLE_LIST_SIZE_ADDR,
897 			   FIELD_PREP(HAL_WBM_SCATTER_RING_SIZE_OF_IDLE_LINK_DESC_LIST,
898 				      reg_scatter_buf_sz * nsbufs));
899 	ath11k_hif_write32(ab,
900 			   HAL_SEQ_WCSS_UMAC_WBM_REG +
901 			   HAL_WBM_SCATTERED_RING_BASE_LSB,
902 			   FIELD_PREP(BUFFER_ADDR_INFO0_ADDR,
903 				      sbuf[0].paddr & HAL_ADDR_LSB_REG_MASK));
904 	ath11k_hif_write32(ab,
905 			   HAL_SEQ_WCSS_UMAC_WBM_REG +
906 			   HAL_WBM_SCATTERED_RING_BASE_MSB,
907 			   FIELD_PREP(
908 				HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32,
909 				(u64)sbuf[0].paddr >> HAL_ADDR_MSB_REG_SHIFT) |
910 				FIELD_PREP(
911 				HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_MATCH_TAG,
912 				BASE_ADDR_MATCH_TAG_VAL));
913 
914 	/* Setup head and tail pointers for the idle list */
915 	ath11k_hif_write32(ab,
916 			   HAL_SEQ_WCSS_UMAC_WBM_REG +
917 			   HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0,
918 			   FIELD_PREP(BUFFER_ADDR_INFO0_ADDR,
919 				      sbuf[nsbufs - 1].paddr));
920 	ath11k_hif_write32(ab,
921 			   HAL_SEQ_WCSS_UMAC_WBM_REG +
922 			   HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX1,
923 			   FIELD_PREP(
924 				HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32,
925 				((u64)sbuf[nsbufs - 1].paddr >>
926 				 HAL_ADDR_MSB_REG_SHIFT)) |
927 			   FIELD_PREP(HAL_WBM_SCATTERED_DESC_HEAD_P_OFFSET_IX1,
928 				      (end_offset >> 2)));
929 	ath11k_hif_write32(ab,
930 			   HAL_SEQ_WCSS_UMAC_WBM_REG +
931 			   HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0,
932 			   FIELD_PREP(BUFFER_ADDR_INFO0_ADDR,
933 				      sbuf[0].paddr));
934 
935 	ath11k_hif_write32(ab,
936 			   HAL_SEQ_WCSS_UMAC_WBM_REG +
937 			   HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX0,
938 			   FIELD_PREP(BUFFER_ADDR_INFO0_ADDR,
939 				      sbuf[0].paddr));
940 	ath11k_hif_write32(ab,
941 			   HAL_SEQ_WCSS_UMAC_WBM_REG +
942 			   HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX1,
943 			   FIELD_PREP(
944 				HAL_WBM_SCATTERED_DESC_MSB_BASE_ADDR_39_32,
945 				((u64)sbuf[0].paddr >> HAL_ADDR_MSB_REG_SHIFT)) |
946 			   FIELD_PREP(HAL_WBM_SCATTERED_DESC_TAIL_P_OFFSET_IX1,
947 				      0));
948 	ath11k_hif_write32(ab,
949 			   HAL_SEQ_WCSS_UMAC_WBM_REG +
950 			   HAL_WBM_SCATTERED_DESC_PTR_HP_ADDR,
951 			   2 * tot_link_desc);
952 
953 	/* Enable the SRNG */
954 	ath11k_hif_write32(ab,
955 			   HAL_SEQ_WCSS_UMAC_WBM_REG +
956 			   HAL_WBM_IDLE_LINK_RING_MISC_ADDR, 0x40);
957 }
958 
959 int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
960 			  int ring_num, int mac_id,
961 			  struct hal_srng_params *params)
962 {
963 	struct ath11k_hal *hal = &ab->hal;
964 	struct hal_srng_config *srng_config = &ab->hal.srng_config[type];
965 	struct hal_srng *srng;
966 	int ring_id;
967 	u32 lmac_idx;
968 	int i;
969 	u32 reg_base;
970 
971 	ring_id = ath11k_hal_srng_get_ring_id(ab, type, ring_num, mac_id);
972 	if (ring_id < 0)
973 		return ring_id;
974 
975 	srng = &hal->srng_list[ring_id];
976 
977 	srng->ring_id = ring_id;
978 	srng->ring_dir = srng_config->ring_dir;
979 	srng->ring_base_paddr = params->ring_base_paddr;
980 	srng->ring_base_vaddr = params->ring_base_vaddr;
981 	srng->entry_size = srng_config->entry_size;
982 	srng->num_entries = params->num_entries;
983 	srng->ring_size = srng->entry_size * srng->num_entries;
984 	srng->intr_batch_cntr_thres_entries =
985 				params->intr_batch_cntr_thres_entries;
986 	srng->intr_timer_thres_us = params->intr_timer_thres_us;
987 	srng->flags = params->flags;
988 	srng->msi_addr = params->msi_addr;
989 	srng->msi_data = params->msi_data;
990 	srng->initialized = 1;
991 	spin_lock_init(&srng->lock);
992 
993 	for (i = 0; i < HAL_SRNG_NUM_REG_GRP; i++) {
994 		srng->hwreg_base[i] = srng_config->reg_start[i] +
995 				      (ring_num * srng_config->reg_size[i]);
996 	}
997 
998 	memset(srng->ring_base_vaddr, 0,
999 	       (srng->entry_size * srng->num_entries) << 2);
1000 
1001 	/* TODO: Add comments on these swap configurations */
1002 	if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
1003 		srng->flags |= HAL_SRNG_FLAGS_MSI_SWAP | HAL_SRNG_FLAGS_DATA_TLV_SWAP |
1004 			       HAL_SRNG_FLAGS_RING_PTR_SWAP;
1005 
1006 	reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2];
1007 
1008 	if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
1009 		srng->u.src_ring.hp = 0;
1010 		srng->u.src_ring.cached_tp = 0;
1011 		srng->u.src_ring.reap_hp = srng->ring_size - srng->entry_size;
1012 		srng->u.src_ring.tp_addr = (void *)(hal->rdp.vaddr + ring_id);
1013 		srng->u.src_ring.low_threshold = params->low_threshold *
1014 						 srng->entry_size;
1015 		if (srng_config->lmac_ring) {
1016 			lmac_idx = ring_id - HAL_SRNG_RING_ID_LMAC1_ID_START;
1017 			srng->u.src_ring.hp_addr = (void *)(hal->wrp.vaddr +
1018 						   lmac_idx);
1019 			srng->flags |= HAL_SRNG_FLAGS_LMAC_RING;
1020 		} else {
1021 			srng->u.src_ring.hp_addr =
1022 				(u32 *)((unsigned long)ab->mem + reg_base);
1023 		}
1024 	} else {
1025 		/* During initialization loop count in all the descriptors
1026 		 * will be set to zero, and HW will set it to 1 on completing
1027 		 * descriptor update in first loop, and increments it by 1 on
1028 		 * subsequent loops (loop count wraps around after reaching
1029 		 * 0xffff). The 'loop_cnt' in SW ring state is the expected
1030 		 * loop count in descriptors updated by HW (to be processed
1031 		 * by SW).
1032 		 */
1033 		srng->u.dst_ring.loop_cnt = 1;
1034 		srng->u.dst_ring.tp = 0;
1035 		srng->u.dst_ring.cached_hp = 0;
1036 		srng->u.dst_ring.hp_addr = (void *)(hal->rdp.vaddr + ring_id);
1037 		if (srng_config->lmac_ring) {
1038 			/* For LMAC rings, tail pointer updates will be done
1039 			 * through FW by writing to a shared memory location
1040 			 */
1041 			lmac_idx = ring_id - HAL_SRNG_RING_ID_LMAC1_ID_START;
1042 			srng->u.dst_ring.tp_addr = (void *)(hal->wrp.vaddr +
1043 						   lmac_idx);
1044 			srng->flags |= HAL_SRNG_FLAGS_LMAC_RING;
1045 		} else {
1046 			srng->u.dst_ring.tp_addr =
1047 				(u32 *)((unsigned long)ab->mem + reg_base +
1048 					(HAL_REO1_RING_TP(ab) - HAL_REO1_RING_HP(ab)));
1049 		}
1050 	}
1051 
1052 	if (srng_config->lmac_ring)
1053 		return ring_id;
1054 
1055 	ath11k_hal_srng_hw_init(ab, srng);
1056 
1057 	if (type == HAL_CE_DST) {
1058 		srng->u.dst_ring.max_buffer_length = params->max_buffer_len;
1059 		ath11k_hal_ce_dst_setup(ab, srng, ring_num);
1060 	}
1061 
1062 	return ring_id;
1063 }
1064 
1065 static int ath11k_hal_srng_create_config(struct ath11k_base *ab)
1066 {
1067 	struct ath11k_hal *hal = &ab->hal;
1068 	struct hal_srng_config *s;
1069 
1070 	hal->srng_config = kmemdup(hw_srng_config_template,
1071 				   sizeof(hw_srng_config_template),
1072 				   GFP_KERNEL);
1073 	if (!hal->srng_config)
1074 		return -ENOMEM;
1075 
1076 	s = &hal->srng_config[HAL_REO_DST];
1077 	s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_BASE_LSB(ab);
1078 	s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_HP(ab);
1079 	s->reg_size[0] = HAL_REO2_RING_BASE_LSB(ab) - HAL_REO1_RING_BASE_LSB(ab);
1080 	s->reg_size[1] = HAL_REO2_RING_HP(ab) - HAL_REO1_RING_HP(ab);
1081 
1082 	s = &hal->srng_config[HAL_REO_EXCEPTION];
1083 	s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_TCL_RING_BASE_LSB(ab);
1084 	s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_TCL_RING_HP(ab);
1085 
1086 	s = &hal->srng_config[HAL_REO_REINJECT];
1087 	s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_BASE_LSB;
1088 	s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_HP;
1089 
1090 	s = &hal->srng_config[HAL_REO_CMD];
1091 	s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_RING_BASE_LSB;
1092 	s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_HP;
1093 
1094 	s = &hal->srng_config[HAL_REO_STATUS];
1095 	s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_RING_BASE_LSB(ab);
1096 	s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_HP(ab);
1097 
1098 	s = &hal->srng_config[HAL_TCL_DATA];
1099 	s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB(ab);
1100 	s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_HP;
1101 	s->reg_size[0] = HAL_TCL2_RING_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB(ab);
1102 	s->reg_size[1] = HAL_TCL2_RING_HP - HAL_TCL1_RING_HP;
1103 
1104 	s = &hal->srng_config[HAL_TCL_CMD];
1105 	s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_BASE_LSB(ab);
1106 	s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_HP;
1107 
1108 	s = &hal->srng_config[HAL_TCL_STATUS];
1109 	s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_BASE_LSB(ab);
1110 	s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_HP;
1111 
1112 	return 0;
1113 }
1114 
1115 int ath11k_hal_srng_init(struct ath11k_base *ab)
1116 {
1117 	struct ath11k_hal *hal = &ab->hal;
1118 	int ret;
1119 
1120 	memset(hal, 0, sizeof(*hal));
1121 
1122 	ret = ath11k_hal_srng_create_config(ab);
1123 	if (ret)
1124 		goto err_hal;
1125 
1126 	ret = ath11k_hal_alloc_cont_rdp(ab);
1127 	if (ret)
1128 		goto err_hal;
1129 
1130 	ret = ath11k_hal_alloc_cont_wrp(ab);
1131 	if (ret)
1132 		goto err_free_cont_rdp;
1133 
1134 	return 0;
1135 
1136 err_free_cont_rdp:
1137 	ath11k_hal_free_cont_rdp(ab);
1138 
1139 err_hal:
1140 	return ret;
1141 }
1142 EXPORT_SYMBOL(ath11k_hal_srng_init);
1143 
1144 void ath11k_hal_srng_deinit(struct ath11k_base *ab)
1145 {
1146 	struct ath11k_hal *hal = &ab->hal;
1147 
1148 	ath11k_hal_free_cont_rdp(ab);
1149 	ath11k_hal_free_cont_wrp(ab);
1150 	kfree(hal->srng_config);
1151 }
1152 EXPORT_SYMBOL(ath11k_hal_srng_deinit);
1153 
1154 void ath11k_hal_dump_srng_stats(struct ath11k_base *ab)
1155 {
1156 	struct hal_srng *srng;
1157 	struct ath11k_ext_irq_grp *irq_grp;
1158 	struct ath11k_ce_pipe *ce_pipe;
1159 	int i;
1160 
1161 	ath11k_err(ab, "Last interrupt received for each CE:\n");
1162 	for (i = 0; i < ab->hw_params.ce_count; i++) {
1163 		ce_pipe = &ab->ce.ce_pipe[i];
1164 
1165 		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
1166 			continue;
1167 
1168 		ath11k_err(ab, "CE_id %d pipe_num %d %ums before\n",
1169 			   i, ce_pipe->pipe_num,
1170 			   jiffies_to_msecs(jiffies - ce_pipe->timestamp));
1171 	}
1172 
1173 	ath11k_err(ab, "\nLast interrupt received for each group:\n");
1174 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
1175 		irq_grp = &ab->ext_irq_grp[i];
1176 		ath11k_err(ab, "group_id %d %ums before\n",
1177 			   irq_grp->grp_id,
1178 			   jiffies_to_msecs(jiffies - irq_grp->timestamp));
1179 	}
1180 
1181 	for (i = 0; i < HAL_SRNG_RING_ID_MAX; i++) {
1182 		srng = &ab->hal.srng_list[i];
1183 
1184 		if (!srng->initialized)
1185 			continue;
1186 
1187 		if (srng->ring_dir == HAL_SRNG_DIR_SRC)
1188 			ath11k_err(ab,
1189 				   "src srng id %u hp %u, reap_hp %u, cur tp %u, cached tp %u last tp %u napi processed before %ums\n",
1190 				   srng->ring_id, srng->u.src_ring.hp,
1191 				   srng->u.src_ring.reap_hp,
1192 				   *srng->u.src_ring.tp_addr, srng->u.src_ring.cached_tp,
1193 				   srng->u.src_ring.last_tp,
1194 				   jiffies_to_msecs(jiffies - srng->timestamp));
1195 		else if (srng->ring_dir == HAL_SRNG_DIR_DST)
1196 			ath11k_err(ab,
1197 				   "dst srng id %u tp %u, cur hp %u, cached hp %u last hp %u napi processed before %ums\n",
1198 				   srng->ring_id, srng->u.dst_ring.tp,
1199 				   *srng->u.dst_ring.hp_addr,
1200 				   srng->u.dst_ring.cached_hp,
1201 				   srng->u.dst_ring.last_hp,
1202 				   jiffies_to_msecs(jiffies - srng->timestamp));
1203 	}
1204 }
1205