xref: /wlan-dirver/qca-wifi-host-cmn/hal/wifi3.0/hal_srng.c (revision 0626a4da6c07f30da06dd6747e8cc290a60371d8)
1 /*
2  * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include "hal_hw_headers.h"
20 #include "hal_api.h"
21 #include "target_type.h"
22 #include "wcss_version.h"
23 #include "qdf_module.h"
24 #ifdef QCA_WIFI_QCA8074
25 void hal_qca6290_attach(struct hal_soc *hal);
26 #endif
27 #ifdef QCA_WIFI_QCA8074
28 void hal_qca8074_attach(struct hal_soc *hal);
29 #endif
30 #ifdef QCA_WIFI_QCA8074V2
31 void hal_qca8074v2_attach(struct hal_soc *hal);
32 #endif
33 #ifdef QCA_WIFI_QCA6390
34 void hal_qca6390_attach(struct hal_soc *hal);
35 #endif
36 
37 /**
38  * hal_get_srng_ring_id() - get the ring id of a descriped ring
39  * @hal: hal_soc data structure
40  * @ring_type: type enum describing the ring
41  * @ring_num: which ring of the ring type
42  * @mac_id: which mac does the ring belong to (or 0 for non-lmac rings)
43  *
44  * Return: the ring id or -EINVAL if the ring does not exist.
45  */
46 static int hal_get_srng_ring_id(struct hal_soc *hal, int ring_type,
47 				int ring_num, int mac_id)
48 {
49 	struct hal_hw_srng_config *ring_config =
50 		HAL_SRNG_CONFIG(hal, ring_type);
51 	int ring_id;
52 
53 	if (ring_num >= ring_config->max_rings) {
54 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
55 			  "%s: ring_num exceeded maximum no. of supported rings",
56 			  __func__);
57 		/* TODO: This is a programming error. Assert if this happens */
58 		return -EINVAL;
59 	}
60 
61 	if (ring_config->lmac_ring) {
62 		ring_id = ring_config->start_ring_id + ring_num +
63 			(mac_id * HAL_MAX_RINGS_PER_LMAC);
64 	} else {
65 		ring_id = ring_config->start_ring_id + ring_num;
66 	}
67 
68 	return ring_id;
69 }
70 
71 static struct hal_srng *hal_get_srng(struct hal_soc *hal, int ring_id)
72 {
73 	/* TODO: Should we allocate srng structures dynamically? */
74 	return &(hal->srng_list[ring_id]);
75 }
76 
77 #define HP_OFFSET_IN_REG_START 1
78 #define OFFSET_FROM_HP_TO_TP 4
79 static void hal_update_srng_hp_tp_address(void *hal_soc,
80 					  int shadow_config_index,
81 					  int ring_type,
82 					  int ring_num)
83 {
84 	struct hal_srng *srng;
85 	struct hal_soc *hal = (struct hal_soc *)hal_soc;
86 	int ring_id;
87 	struct hal_hw_srng_config *ring_config =
88 		HAL_SRNG_CONFIG(hal, ring_type);
89 
90 	ring_id = hal_get_srng_ring_id(hal_soc, ring_type, ring_num, 0);
91 	if (ring_id < 0)
92 		return;
93 
94 	srng = hal_get_srng(hal_soc, ring_id);
95 
96 	if (ring_config->ring_dir == HAL_SRNG_DST_RING)
97 		srng->u.dst_ring.tp_addr = SHADOW_REGISTER(shadow_config_index)
98 			+ hal->dev_base_addr;
99 	else
100 		srng->u.src_ring.hp_addr = SHADOW_REGISTER(shadow_config_index)
101 			+ hal->dev_base_addr;
102 }
103 
104 QDF_STATUS hal_set_one_shadow_config(void *hal_soc,
105 				     int ring_type,
106 				     int ring_num)
107 {
108 	uint32_t target_register;
109 	struct hal_soc *hal = (struct hal_soc *)hal_soc;
110 	struct hal_hw_srng_config *srng_config = &hal->hw_srng_table[ring_type];
111 	int shadow_config_index = hal->num_shadow_registers_configured;
112 
113 	if (shadow_config_index >= MAX_SHADOW_REGISTERS) {
114 		QDF_ASSERT(0);
115 		return QDF_STATUS_E_RESOURCES;
116 	}
117 
118 	hal->num_shadow_registers_configured++;
119 
120 	target_register = srng_config->reg_start[HP_OFFSET_IN_REG_START];
121 	target_register += (srng_config->reg_size[HP_OFFSET_IN_REG_START]
122 			    *ring_num);
123 
124 	/* if the ring is a dst ring, we need to shadow the tail pointer */
125 	if (srng_config->ring_dir == HAL_SRNG_DST_RING)
126 		target_register += OFFSET_FROM_HP_TO_TP;
127 
128 	hal->shadow_config[shadow_config_index].addr = target_register;
129 
130 	/* update hp/tp addr in the hal_soc structure*/
131 	hal_update_srng_hp_tp_address(hal_soc, shadow_config_index, ring_type,
132 				      ring_num);
133 
134 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
135 	    "%s: target_reg %x, shadow_index %x, ring_type %d, ring num %d",
136 	    __func__, target_register, shadow_config_index,
137 	    ring_type, ring_num);
138 
139 	return QDF_STATUS_SUCCESS;
140 }
141 
142 qdf_export_symbol(hal_set_one_shadow_config);
143 
144 QDF_STATUS hal_construct_shadow_config(void *hal_soc)
145 {
146 	int ring_type, ring_num;
147 	struct hal_soc *hal = (struct hal_soc *)hal_soc;
148 
149 	for (ring_type = 0; ring_type < MAX_RING_TYPES; ring_type++) {
150 		struct hal_hw_srng_config *srng_config =
151 			&hal->hw_srng_table[ring_type];
152 
153 		if (ring_type == CE_SRC ||
154 		    ring_type == CE_DST ||
155 		    ring_type == CE_DST_STATUS)
156 			continue;
157 
158 		if (srng_config->lmac_ring)
159 			continue;
160 
161 		for (ring_num = 0; ring_num < srng_config->max_rings;
162 		     ring_num++)
163 			hal_set_one_shadow_config(hal_soc, ring_type, ring_num);
164 	}
165 
166 	return QDF_STATUS_SUCCESS;
167 }
168 
169 qdf_export_symbol(hal_construct_shadow_config);
170 
171 void hal_get_shadow_config(void *hal_soc,
172 	struct pld_shadow_reg_v2_cfg **shadow_config,
173 	int *num_shadow_registers_configured)
174 {
175 	struct hal_soc *hal = (struct hal_soc *)hal_soc;
176 
177 	*shadow_config = hal->shadow_config;
178 	*num_shadow_registers_configured =
179 		hal->num_shadow_registers_configured;
180 
181 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
182 			"%s", __func__);
183 }
184 
185 qdf_export_symbol(hal_get_shadow_config);
186 
187 
188 static void hal_validate_shadow_register(struct hal_soc *hal,
189 				  uint32_t *destination,
190 				  uint32_t *shadow_address)
191 {
192 	unsigned int index;
193 	uint32_t *shadow_0_offset = SHADOW_REGISTER(0) + hal->dev_base_addr;
194 	int destination_ba_offset =
195 		((char *)destination) - (char *)hal->dev_base_addr;
196 
197 	index =	shadow_address - shadow_0_offset;
198 
199 	if (index >= MAX_SHADOW_REGISTERS) {
200 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
201 			"%s: index %x out of bounds", __func__, index);
202 		goto error;
203 	} else if (hal->shadow_config[index].addr != destination_ba_offset) {
204 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
205 			"%s: sanity check failure, expected %x, found %x",
206 			__func__, destination_ba_offset,
207 			hal->shadow_config[index].addr);
208 		goto error;
209 	}
210 	return;
211 error:
212 	qdf_print("%s: baddr %pK, desination %pK, shadow_address %pK s0offset %pK index %x",
213 		  __func__, hal->dev_base_addr, destination, shadow_address,
214 		  shadow_0_offset, index);
215 	QDF_BUG(0);
216 	return;
217 }
218 
219 static void hal_target_based_configure(struct hal_soc *hal)
220 {
221 	switch (hal->target_type) {
222 #ifdef QCA_WIFI_QCA6290
223 	case TARGET_TYPE_QCA6290:
224 		hal->use_register_windowing = true;
225 		hal_qca6290_attach(hal);
226 	break;
227 #endif
228 #ifdef QCA_WIFI_QCA6390
229 	case TARGET_TYPE_QCA6390:
230 		hal->use_register_windowing = true;
231 		hal_qca6390_attach(hal);
232 	break;
233 #endif
234 #if defined(QCA_WIFI_QCA8074) && defined(CONFIG_WIN)
235 	case TARGET_TYPE_QCA8074:
236 		hal_qca8074_attach(hal);
237 	break;
238 #endif
239 
240 #if defined(QCA_WIFI_QCA8074V2) && defined(CONFIG_WIN)
241 	case TARGET_TYPE_QCA8074V2:
242 		hal_qca8074v2_attach(hal);
243 	break;
244 #endif
245 	default:
246 	break;
247 	}
248 }
249 
250 uint32_t hal_get_target_type(struct hal_soc *hal)
251 {
252 	struct hif_target_info *tgt_info =
253 		hif_get_target_info_handle(hal->hif_handle);
254 
255 	return tgt_info->target_type;
256 }
257 
258 qdf_export_symbol(hal_get_target_type);
259 
260 /**
261  * hal_attach - Initialize HAL layer
262  * @hif_handle: Opaque HIF handle
263  * @qdf_dev: QDF device
264  *
265  * Return: Opaque HAL SOC handle
266  *		 NULL on failure (if given ring is not available)
267  *
268  * This function should be called as part of HIF initialization (for accessing
269  * copy engines). DP layer will get hal_soc handle using hif_get_hal_handle()
270  *
271  */
272 void *hal_attach(void *hif_handle, qdf_device_t qdf_dev)
273 {
274 	struct hal_soc *hal;
275 	int i;
276 
277 	hal = qdf_mem_malloc(sizeof(*hal));
278 
279 	if (!hal) {
280 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
281 			"%s: hal_soc allocation failed", __func__);
282 		goto fail0;
283 	}
284 	hal->hif_handle = hif_handle;
285 	hal->dev_base_addr = hif_get_dev_ba(hif_handle);
286 	hal->qdf_dev = qdf_dev;
287 	hal->shadow_rdptr_mem_vaddr = (uint32_t *)qdf_mem_alloc_consistent(
288 		qdf_dev, qdf_dev->dev, sizeof(*(hal->shadow_rdptr_mem_vaddr)) *
289 		HAL_SRNG_ID_MAX, &(hal->shadow_rdptr_mem_paddr));
290 	if (!hal->shadow_rdptr_mem_paddr) {
291 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
292 			"%s: hal->shadow_rdptr_mem_paddr allocation failed",
293 			__func__);
294 		goto fail1;
295 	}
296 
297 	hal->shadow_wrptr_mem_vaddr =
298 		(uint32_t *)qdf_mem_alloc_consistent(qdf_dev, qdf_dev->dev,
299 		sizeof(*(hal->shadow_wrptr_mem_vaddr)) * HAL_MAX_LMAC_RINGS,
300 		&(hal->shadow_wrptr_mem_paddr));
301 	if (!hal->shadow_wrptr_mem_vaddr) {
302 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
303 			"%s: hal->shadow_wrptr_mem_vaddr allocation failed",
304 			__func__);
305 		goto fail2;
306 	}
307 
308 	for (i = 0; i < HAL_SRNG_ID_MAX; i++) {
309 		hal->srng_list[i].initialized = 0;
310 		hal->srng_list[i].ring_id = i;
311 	}
312 
313 	qdf_spinlock_create(&hal->register_access_lock);
314 	hal->register_window = 0;
315 	hal->target_type = hal_get_target_type(hal);
316 
317 	hal_target_based_configure(hal);
318 
319 	return (void *)hal;
320 
321 fail2:
322 	qdf_mem_free_consistent(qdf_dev, qdf_dev->dev,
323 		sizeof(*(hal->shadow_rdptr_mem_vaddr)) * HAL_SRNG_ID_MAX,
324 		hal->shadow_rdptr_mem_vaddr, hal->shadow_rdptr_mem_paddr, 0);
325 fail1:
326 	qdf_mem_free(hal);
327 fail0:
328 	return NULL;
329 }
330 qdf_export_symbol(hal_attach);
331 
332 /**
333  * hal_mem_info - Retrieve hal memory base address
334  *
335  * @hal_soc: Opaque HAL SOC handle
336  * @mem: pointer to structure to be updated with hal mem info
337  */
338 void hal_get_meminfo(void *hal_soc, struct hal_mem_info *mem )
339 {
340 	struct hal_soc *hal = (struct hal_soc *)hal_soc;
341 	mem->dev_base_addr = (void *)hal->dev_base_addr;
342         mem->shadow_rdptr_mem_vaddr = (void *)hal->shadow_rdptr_mem_vaddr;
343 	mem->shadow_wrptr_mem_vaddr = (void *)hal->shadow_wrptr_mem_vaddr;
344         mem->shadow_rdptr_mem_paddr = (void *)hal->shadow_rdptr_mem_paddr;
345 	mem->shadow_wrptr_mem_paddr = (void *)hal->shadow_wrptr_mem_paddr;
346 	hif_read_phy_mem_base(hal->hif_handle, (qdf_dma_addr_t *)&mem->dev_base_paddr);
347 	return;
348 }
349 qdf_export_symbol(hal_get_meminfo);
350 
351 /**
352  * hal_detach - Detach HAL layer
353  * @hal_soc: HAL SOC handle
354  *
355  * Return: Opaque HAL SOC handle
356  *		 NULL on failure (if given ring is not available)
357  *
358  * This function should be called as part of HIF initialization (for accessing
359  * copy engines). DP layer will get hal_soc handle using hif_get_hal_handle()
360  *
361  */
362 extern void hal_detach(void *hal_soc)
363 {
364 	struct hal_soc *hal = (struct hal_soc *)hal_soc;
365 
366 	qdf_mem_free_consistent(hal->qdf_dev, hal->qdf_dev->dev,
367 		sizeof(*(hal->shadow_rdptr_mem_vaddr)) * HAL_SRNG_ID_MAX,
368 		hal->shadow_rdptr_mem_vaddr, hal->shadow_rdptr_mem_paddr, 0);
369 	qdf_mem_free_consistent(hal->qdf_dev, hal->qdf_dev->dev,
370 		sizeof(*(hal->shadow_wrptr_mem_vaddr)) * HAL_MAX_LMAC_RINGS,
371 		hal->shadow_wrptr_mem_vaddr, hal->shadow_wrptr_mem_paddr, 0);
372 	qdf_mem_free(hal);
373 
374 	return;
375 }
376 qdf_export_symbol(hal_detach);
377 
378 
379 /**
380  * hal_ce_dst_setup - Initialize CE destination ring registers
381  * @hal_soc: HAL SOC handle
382  * @srng: SRNG ring pointer
383  */
384 static inline void hal_ce_dst_setup(struct hal_soc *hal, struct hal_srng *srng,
385 				    int ring_num)
386 {
387 	uint32_t reg_val = 0;
388 	uint32_t reg_addr;
389 	struct hal_hw_srng_config *ring_config =
390 		HAL_SRNG_CONFIG(hal, CE_DST);
391 
392 	/* set DEST_MAX_LENGTH according to ce assignment */
393 	reg_addr = HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_CTRL_ADDR(
394 			ring_config->reg_start[R0_INDEX] +
395 			(ring_num * ring_config->reg_size[R0_INDEX]));
396 
397 	reg_val = HAL_REG_READ(hal, reg_addr);
398 	reg_val &= ~HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_CTRL_DEST_MAX_LENGTH_BMSK;
399 	reg_val |= srng->u.dst_ring.max_buffer_length &
400 		HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_CTRL_DEST_MAX_LENGTH_BMSK;
401 	HAL_REG_WRITE(hal, reg_addr, reg_val);
402 }
403 
404 /**
405  * hal_reo_remap_IX0 - Remap REO ring destination
406  * @hal: HAL SOC handle
407  * @remap_val: Remap value
408  */
409 void hal_reo_remap_IX0(struct hal_soc *hal, uint32_t remap_val)
410 {
411 	uint32_t reg_offset = HWIO_REO_R0_DESTINATION_RING_CTRL_IX_0_ADDR(
412 				SEQ_WCSS_UMAC_REO_REG_OFFSET);
413 	HAL_REG_WRITE(hal, reg_offset, remap_val);
414 }
415 
416 /**
417  * hal_srng_dst_set_hp_paddr() - Set physical address to dest ring head pointer
418  * @srng: sring pointer
419  * @paddr: physical address
420  */
421 void hal_srng_dst_set_hp_paddr(struct hal_srng *srng,
422 			       uint64_t paddr)
423 {
424 	SRNG_DST_REG_WRITE(srng, HP_ADDR_LSB,
425 			   paddr & 0xffffffff);
426 	SRNG_DST_REG_WRITE(srng, HP_ADDR_MSB,
427 			   paddr >> 32);
428 }
429 
430 /**
431  * hal_srng_dst_init_hp() - Initilaize destination ring head pointer
432  * @srng: sring pointer
433  * @vaddr: virtual address
434  */
435 void hal_srng_dst_init_hp(struct hal_srng *srng,
436 			  uint32_t *vaddr)
437 {
438 	srng->u.dst_ring.hp_addr = vaddr;
439 	SRNG_DST_REG_WRITE(srng, HP, srng->u.dst_ring.cached_hp);
440 	*(srng->u.dst_ring.hp_addr) = srng->u.dst_ring.cached_hp;
441 
442 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
443 		"hp_addr=%pK, cached_hp=%d, hp=%d",
444 		(void *)srng->u.dst_ring.hp_addr, srng->u.dst_ring.cached_hp,
445 		*(srng->u.dst_ring.hp_addr));
446 }
447 
448 /**
449  * hal_srng_hw_init - Private function to initialize SRNG HW
450  * @hal_soc: HAL SOC handle
451  * @srng: SRNG ring pointer
452  */
453 static inline void hal_srng_hw_init(struct hal_soc *hal,
454 	struct hal_srng *srng)
455 {
456 	if (srng->ring_dir == HAL_SRNG_SRC_RING)
457 		hal_srng_src_hw_init(hal, srng);
458 	else
459 		hal_srng_dst_hw_init(hal, srng);
460 }
461 
462 #ifdef CONFIG_SHADOW_V2
463 #define ignore_shadow false
464 #define CHECK_SHADOW_REGISTERS true
465 #else
466 #define ignore_shadow true
467 #define CHECK_SHADOW_REGISTERS false
468 #endif
469 
470 /**
471  * hal_srng_setup - Initialize HW SRNG ring.
472  * @hal_soc: Opaque HAL SOC handle
473  * @ring_type: one of the types from hal_ring_type
474  * @ring_num: Ring number if there are multiple rings of same type (staring
475  * from 0)
476  * @mac_id: valid MAC Id should be passed if ring type is one of lmac rings
477  * @ring_params: SRNG ring params in hal_srng_params structure.
478 
479  * Callers are expected to allocate contiguous ring memory of size
480  * 'num_entries * entry_size' bytes and pass the physical and virtual base
481  * addresses through 'ring_base_paddr' and 'ring_base_vaddr' in
482  * hal_srng_params structure. Ring base address should be 8 byte aligned
483  * and size of each ring entry should be queried using the API
484  * hal_srng_get_entrysize
485  *
486  * Return: Opaque pointer to ring on success
487  *		 NULL on failure (if given ring is not available)
488  */
489 void *hal_srng_setup(void *hal_soc, int ring_type, int ring_num,
490 	int mac_id, struct hal_srng_params *ring_params)
491 {
492 	int ring_id;
493 	struct hal_soc *hal = (struct hal_soc *)hal_soc;
494 	struct hal_srng *srng;
495 	struct hal_hw_srng_config *ring_config =
496 		HAL_SRNG_CONFIG(hal, ring_type);
497 	void *dev_base_addr;
498 	int i;
499 
500 	ring_id = hal_get_srng_ring_id(hal_soc, ring_type, ring_num, mac_id);
501 	if (ring_id < 0)
502 		return NULL;
503 
504 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
505 		  "%s: mac_id %d ring_id %d",
506 		  __func__, mac_id, ring_id);
507 
508 	srng = hal_get_srng(hal_soc, ring_id);
509 
510 	if (srng->initialized) {
511 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
512 			  "%s: Ring (ring_type, ring_num) already initialized",
513 			  __func__);
514 		return NULL;
515 	}
516 
517 	dev_base_addr = hal->dev_base_addr;
518 	srng->ring_id = ring_id;
519 	srng->ring_dir = ring_config->ring_dir;
520 	srng->ring_base_paddr = ring_params->ring_base_paddr;
521 	srng->ring_base_vaddr = ring_params->ring_base_vaddr;
522 	srng->entry_size = ring_config->entry_size;
523 	srng->num_entries = ring_params->num_entries;
524 	srng->ring_size = srng->num_entries * srng->entry_size;
525 	srng->ring_size_mask = srng->ring_size - 1;
526 	srng->msi_addr = ring_params->msi_addr;
527 	srng->msi_data = ring_params->msi_data;
528 	srng->intr_timer_thres_us = ring_params->intr_timer_thres_us;
529 	srng->intr_batch_cntr_thres_entries =
530 		ring_params->intr_batch_cntr_thres_entries;
531 	srng->hal_soc = hal_soc;
532 
533 	for (i = 0 ; i < MAX_SRNG_REG_GROUPS; i++) {
534 		srng->hwreg_base[i] = dev_base_addr + ring_config->reg_start[i]
535 			+ (ring_num * ring_config->reg_size[i]);
536 	}
537 
538 	/* Zero out the entire ring memory */
539 	qdf_mem_zero(srng->ring_base_vaddr, (srng->entry_size *
540 		srng->num_entries) << 2);
541 
542 	srng->flags = ring_params->flags;
543 #ifdef BIG_ENDIAN_HOST
544 		/* TODO: See if we should we get these flags from caller */
545 	srng->flags |= HAL_SRNG_DATA_TLV_SWAP;
546 	srng->flags |= HAL_SRNG_MSI_SWAP;
547 	srng->flags |= HAL_SRNG_RING_PTR_SWAP;
548 #endif
549 
550 	if (srng->ring_dir == HAL_SRNG_SRC_RING) {
551 		srng->u.src_ring.hp = 0;
552 		srng->u.src_ring.reap_hp = srng->ring_size -
553 			srng->entry_size;
554 		srng->u.src_ring.tp_addr =
555 			&(hal->shadow_rdptr_mem_vaddr[ring_id]);
556 		srng->u.src_ring.low_threshold =
557 			ring_params->low_threshold * srng->entry_size;
558 		if (ring_config->lmac_ring) {
559 			/* For LMAC rings, head pointer updates will be done
560 			 * through FW by writing to a shared memory location
561 			 */
562 			srng->u.src_ring.hp_addr =
563 				&(hal->shadow_wrptr_mem_vaddr[ring_id -
564 					HAL_SRNG_LMAC1_ID_START]);
565 			srng->flags |= HAL_SRNG_LMAC_RING;
566 		} else if (ignore_shadow || (srng->u.src_ring.hp_addr == 0)) {
567 			srng->u.src_ring.hp_addr = SRNG_SRC_ADDR(srng, HP);
568 
569 			if (CHECK_SHADOW_REGISTERS) {
570 				QDF_TRACE(QDF_MODULE_ID_TXRX,
571 				    QDF_TRACE_LEVEL_ERROR,
572 				    "%s: Ring (%d, %d) missing shadow config",
573 				    __func__, ring_type, ring_num);
574 			}
575 		} else {
576 			hal_validate_shadow_register(hal,
577 						     SRNG_SRC_ADDR(srng, HP),
578 						     srng->u.src_ring.hp_addr);
579 		}
580 	} else {
581 		/* During initialization loop count in all the descriptors
582 		 * will be set to zero, and HW will set it to 1 on completing
583 		 * descriptor update in first loop, and increments it by 1 on
584 		 * subsequent loops (loop count wraps around after reaching
585 		 * 0xffff). The 'loop_cnt' in SW ring state is the expected
586 		 * loop count in descriptors updated by HW (to be processed
587 		 * by SW).
588 		 */
589 		srng->u.dst_ring.loop_cnt = 1;
590 		srng->u.dst_ring.tp = 0;
591 		srng->u.dst_ring.hp_addr =
592 			&(hal->shadow_rdptr_mem_vaddr[ring_id]);
593 		if (ring_config->lmac_ring) {
594 			/* For LMAC rings, tail pointer updates will be done
595 			 * through FW by writing to a shared memory location
596 			 */
597 			srng->u.dst_ring.tp_addr =
598 				&(hal->shadow_wrptr_mem_vaddr[ring_id -
599 				HAL_SRNG_LMAC1_ID_START]);
600 			srng->flags |= HAL_SRNG_LMAC_RING;
601 		} else if (ignore_shadow || srng->u.dst_ring.tp_addr == 0) {
602 			srng->u.dst_ring.tp_addr = SRNG_DST_ADDR(srng, TP);
603 
604 			if (CHECK_SHADOW_REGISTERS) {
605 				QDF_TRACE(QDF_MODULE_ID_TXRX,
606 				    QDF_TRACE_LEVEL_ERROR,
607 				    "%s: Ring (%d, %d) missing shadow config",
608 				    __func__, ring_type, ring_num);
609 			}
610 		} else {
611 			hal_validate_shadow_register(hal,
612 						     SRNG_DST_ADDR(srng, TP),
613 						     srng->u.dst_ring.tp_addr);
614 		}
615 	}
616 
617 	if (!(ring_config->lmac_ring)) {
618 		hal_srng_hw_init(hal, srng);
619 
620 		if (ring_type == CE_DST) {
621 			srng->u.dst_ring.max_buffer_length = ring_params->max_buffer_length;
622 			hal_ce_dst_setup(hal, srng, ring_num);
623 		}
624 	}
625 
626 	SRNG_LOCK_INIT(&srng->lock);
627 
628 	srng->initialized = true;
629 
630 	return (void *)srng;
631 }
632 qdf_export_symbol(hal_srng_setup);
633 
634 /**
635  * hal_srng_cleanup - Deinitialize HW SRNG ring.
636  * @hal_soc: Opaque HAL SOC handle
637  * @hal_srng: Opaque HAL SRNG pointer
638  */
639 void hal_srng_cleanup(void *hal_soc, void *hal_srng)
640 {
641 	struct hal_srng *srng = (struct hal_srng *)hal_srng;
642 	SRNG_LOCK_DESTROY(&srng->lock);
643 	srng->initialized = 0;
644 }
645 qdf_export_symbol(hal_srng_cleanup);
646 
647 /**
648  * hal_srng_get_entrysize - Returns size of ring entry in bytes
649  * @hal_soc: Opaque HAL SOC handle
650  * @ring_type: one of the types from hal_ring_type
651  *
652  */
653 uint32_t hal_srng_get_entrysize(void *hal_soc, int ring_type)
654 {
655 	struct hal_soc *hal = (struct hal_soc *)hal_soc;
656 	struct hal_hw_srng_config *ring_config =
657 		HAL_SRNG_CONFIG(hal, ring_type);
658 	return ring_config->entry_size << 2;
659 }
660 qdf_export_symbol(hal_srng_get_entrysize);
661 
662 /**
663  * hal_srng_max_entries - Returns maximum possible number of ring entries
664  * @hal_soc: Opaque HAL SOC handle
665  * @ring_type: one of the types from hal_ring_type
666  *
667  * Return: Maximum number of entries for the given ring_type
668  */
669 uint32_t hal_srng_max_entries(void *hal_soc, int ring_type)
670 {
671 	struct hal_soc *hal = (struct hal_soc *)hal_soc;
672 	struct hal_hw_srng_config *ring_config =
673 		HAL_SRNG_CONFIG(hal, ring_type);
674 
675 	return ring_config->max_size / ring_config->entry_size;
676 }
677 qdf_export_symbol(hal_srng_max_entries);
678 
679 enum hal_srng_dir hal_srng_get_dir(void *hal_soc, int ring_type)
680 {
681 	struct hal_soc *hal = (struct hal_soc *)hal_soc;
682 	struct hal_hw_srng_config *ring_config =
683 		HAL_SRNG_CONFIG(hal, ring_type);
684 
685 	return ring_config->ring_dir;
686 }
687 
688 /**
689  * hal_srng_dump - Dump ring status
690  * @srng: hal srng pointer
691  */
692 void hal_srng_dump(struct hal_srng *srng)
693 {
694 	if (srng->ring_dir == HAL_SRNG_SRC_RING) {
695 		qdf_print("=== SRC RING %d ===", srng->ring_id);
696 		qdf_print("hp %u, reap_hp %u, tp %u, cached tp %u",
697 			  srng->u.src_ring.hp,
698 			  srng->u.src_ring.reap_hp,
699 			  *srng->u.src_ring.tp_addr,
700 			  srng->u.src_ring.cached_tp);
701 	} else {
702 		qdf_print("=== DST RING %d ===", srng->ring_id);
703 		qdf_print("tp %u, hp %u, cached tp %u, loop_cnt %u",
704 			  srng->u.dst_ring.tp,
705 			  *srng->u.dst_ring.hp_addr,
706 			  srng->u.dst_ring.cached_hp,
707 			  srng->u.dst_ring.loop_cnt);
708 	}
709 }
710 
711 /**
712  * hal_get_srng_params - Retrieve SRNG parameters for a given ring from HAL
713  *
714  * @hal_soc: Opaque HAL SOC handle
715  * @hal_ring: Ring pointer (Source or Destination ring)
716  * @ring_params: SRNG parameters will be returned through this structure
717  */
718 extern void hal_get_srng_params(void *hal_soc, void *hal_ring,
719 	struct hal_srng_params *ring_params)
720 {
721 	struct hal_srng *srng = (struct hal_srng *)hal_ring;
722 	int i =0;
723 	ring_params->ring_id = srng->ring_id;
724 	ring_params->ring_dir = srng->ring_dir;
725 	ring_params->entry_size = srng->entry_size;
726 
727 	ring_params->ring_base_paddr = srng->ring_base_paddr;
728 	ring_params->ring_base_vaddr = srng->ring_base_vaddr;
729 	ring_params->num_entries = srng->num_entries;
730 	ring_params->msi_addr = srng->msi_addr;
731 	ring_params->msi_data = srng->msi_data;
732 	ring_params->intr_timer_thres_us = srng->intr_timer_thres_us;
733 	ring_params->intr_batch_cntr_thres_entries =
734 		srng->intr_batch_cntr_thres_entries;
735 	ring_params->low_threshold = srng->u.src_ring.low_threshold;
736 	ring_params->flags = srng->flags;
737 	ring_params->ring_id = srng->ring_id;
738 	for (i = 0 ; i < MAX_SRNG_REG_GROUPS; i++)
739 		ring_params->hwreg_base[i] = srng->hwreg_base[i];
740 }
741 qdf_export_symbol(hal_get_srng_params);
742