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