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