xref: /freebsd/sys/contrib/dev/athk/ath12k/wifi7/dp.c (revision 60bac4d6438b6bcb3d7b439684211d05396d90ce)
1*60bac4d6SBjoern A. Zeeb // SPDX-License-Identifier: BSD-3-Clause-Clear
2*60bac4d6SBjoern A. Zeeb /*
3*60bac4d6SBjoern A. Zeeb  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4*60bac4d6SBjoern A. Zeeb  * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
5*60bac4d6SBjoern A. Zeeb  */
6*60bac4d6SBjoern A. Zeeb #include "../core.h"
7*60bac4d6SBjoern A. Zeeb #include "../debug.h"
8*60bac4d6SBjoern A. Zeeb #include "../dp_rx.h"
9*60bac4d6SBjoern A. Zeeb #include "../dp_tx.h"
10*60bac4d6SBjoern A. Zeeb #include "hal_desc.h"
11*60bac4d6SBjoern A. Zeeb #include "../dp_mon.h"
12*60bac4d6SBjoern A. Zeeb #include "dp_mon.h"
13*60bac4d6SBjoern A. Zeeb #include "../dp_cmn.h"
14*60bac4d6SBjoern A. Zeeb #include "dp_rx.h"
15*60bac4d6SBjoern A. Zeeb #include "dp.h"
16*60bac4d6SBjoern A. Zeeb #include "dp_tx.h"
17*60bac4d6SBjoern A. Zeeb #include "hal.h"
18*60bac4d6SBjoern A. Zeeb 
ath12k_wifi7_dp_service_srng(struct ath12k_dp * dp,struct ath12k_ext_irq_grp * irq_grp,int budget)19*60bac4d6SBjoern A. Zeeb static int ath12k_wifi7_dp_service_srng(struct ath12k_dp *dp,
20*60bac4d6SBjoern A. Zeeb 					struct ath12k_ext_irq_grp *irq_grp,
21*60bac4d6SBjoern A. Zeeb 					int budget)
22*60bac4d6SBjoern A. Zeeb {
23*60bac4d6SBjoern A. Zeeb 	struct napi_struct *napi = &irq_grp->napi;
24*60bac4d6SBjoern A. Zeeb 	int grp_id = irq_grp->grp_id;
25*60bac4d6SBjoern A. Zeeb 	int work_done = 0;
26*60bac4d6SBjoern A. Zeeb 	int i = 0, j;
27*60bac4d6SBjoern A. Zeeb 	int tot_work_done = 0;
28*60bac4d6SBjoern A. Zeeb 	enum dp_monitor_mode monitor_mode;
29*60bac4d6SBjoern A. Zeeb 	u8 ring_mask;
30*60bac4d6SBjoern A. Zeeb 
31*60bac4d6SBjoern A. Zeeb 	if (dp->hw_params->ring_mask->tx[grp_id]) {
32*60bac4d6SBjoern A. Zeeb 		i = fls(dp->hw_params->ring_mask->tx[grp_id]) - 1;
33*60bac4d6SBjoern A. Zeeb 		ath12k_wifi7_dp_tx_completion_handler(dp, i);
34*60bac4d6SBjoern A. Zeeb 	}
35*60bac4d6SBjoern A. Zeeb 
36*60bac4d6SBjoern A. Zeeb 	if (dp->hw_params->ring_mask->rx_err[grp_id]) {
37*60bac4d6SBjoern A. Zeeb 		work_done = ath12k_wifi7_dp_rx_process_err(dp, napi, budget);
38*60bac4d6SBjoern A. Zeeb 		budget -= work_done;
39*60bac4d6SBjoern A. Zeeb 		tot_work_done += work_done;
40*60bac4d6SBjoern A. Zeeb 		if (budget <= 0)
41*60bac4d6SBjoern A. Zeeb 			goto done;
42*60bac4d6SBjoern A. Zeeb 	}
43*60bac4d6SBjoern A. Zeeb 
44*60bac4d6SBjoern A. Zeeb 	if (dp->hw_params->ring_mask->rx_wbm_rel[grp_id]) {
45*60bac4d6SBjoern A. Zeeb 		work_done = ath12k_wifi7_dp_rx_process_wbm_err(dp, napi, budget);
46*60bac4d6SBjoern A. Zeeb 		budget -= work_done;
47*60bac4d6SBjoern A. Zeeb 		tot_work_done += work_done;
48*60bac4d6SBjoern A. Zeeb 
49*60bac4d6SBjoern A. Zeeb 		if (budget <= 0)
50*60bac4d6SBjoern A. Zeeb 			goto done;
51*60bac4d6SBjoern A. Zeeb 	}
52*60bac4d6SBjoern A. Zeeb 
53*60bac4d6SBjoern A. Zeeb 	if (dp->hw_params->ring_mask->rx[grp_id]) {
54*60bac4d6SBjoern A. Zeeb 		i = fls(dp->hw_params->ring_mask->rx[grp_id]) - 1;
55*60bac4d6SBjoern A. Zeeb 		work_done = ath12k_wifi7_dp_rx_process(dp, i, napi, budget);
56*60bac4d6SBjoern A. Zeeb 		budget -= work_done;
57*60bac4d6SBjoern A. Zeeb 		tot_work_done += work_done;
58*60bac4d6SBjoern A. Zeeb 		if (budget <= 0)
59*60bac4d6SBjoern A. Zeeb 			goto done;
60*60bac4d6SBjoern A. Zeeb 	}
61*60bac4d6SBjoern A. Zeeb 
62*60bac4d6SBjoern A. Zeeb 	if (dp->hw_params->ring_mask->rx_mon_status[grp_id]) {
63*60bac4d6SBjoern A. Zeeb 		ring_mask = dp->hw_params->ring_mask->rx_mon_status[grp_id];
64*60bac4d6SBjoern A. Zeeb 		for (i = 0; i < dp->ab->num_radios; i++) {
65*60bac4d6SBjoern A. Zeeb 			for (j = 0; j < dp->hw_params->num_rxdma_per_pdev; j++) {
66*60bac4d6SBjoern A. Zeeb 				int id = i * dp->hw_params->num_rxdma_per_pdev + j;
67*60bac4d6SBjoern A. Zeeb 
68*60bac4d6SBjoern A. Zeeb 				if (ring_mask & BIT(id)) {
69*60bac4d6SBjoern A. Zeeb 					work_done =
70*60bac4d6SBjoern A. Zeeb 					ath12k_wifi7_dp_mon_process_ring(dp, id, napi,
71*60bac4d6SBjoern A. Zeeb 									 budget,
72*60bac4d6SBjoern A. Zeeb 									 0);
73*60bac4d6SBjoern A. Zeeb 					budget -= work_done;
74*60bac4d6SBjoern A. Zeeb 					tot_work_done += work_done;
75*60bac4d6SBjoern A. Zeeb 					if (budget <= 0)
76*60bac4d6SBjoern A. Zeeb 						goto done;
77*60bac4d6SBjoern A. Zeeb 				}
78*60bac4d6SBjoern A. Zeeb 			}
79*60bac4d6SBjoern A. Zeeb 		}
80*60bac4d6SBjoern A. Zeeb 	}
81*60bac4d6SBjoern A. Zeeb 
82*60bac4d6SBjoern A. Zeeb 	if (dp->hw_params->ring_mask->rx_mon_dest[grp_id]) {
83*60bac4d6SBjoern A. Zeeb 		monitor_mode = ATH12K_DP_RX_MONITOR_MODE;
84*60bac4d6SBjoern A. Zeeb 		ring_mask = dp->hw_params->ring_mask->rx_mon_dest[grp_id];
85*60bac4d6SBjoern A. Zeeb 		for (i = 0; i < dp->ab->num_radios; i++) {
86*60bac4d6SBjoern A. Zeeb 			for (j = 0; j < dp->hw_params->num_rxdma_per_pdev; j++) {
87*60bac4d6SBjoern A. Zeeb 				int id = i * dp->hw_params->num_rxdma_per_pdev + j;
88*60bac4d6SBjoern A. Zeeb 
89*60bac4d6SBjoern A. Zeeb 				if (ring_mask & BIT(id)) {
90*60bac4d6SBjoern A. Zeeb 					work_done =
91*60bac4d6SBjoern A. Zeeb 					ath12k_wifi7_dp_mon_process_ring(dp, id, napi,
92*60bac4d6SBjoern A. Zeeb 									 budget,
93*60bac4d6SBjoern A. Zeeb 									 monitor_mode);
94*60bac4d6SBjoern A. Zeeb 					budget -= work_done;
95*60bac4d6SBjoern A. Zeeb 					tot_work_done += work_done;
96*60bac4d6SBjoern A. Zeeb 
97*60bac4d6SBjoern A. Zeeb 					if (budget <= 0)
98*60bac4d6SBjoern A. Zeeb 						goto done;
99*60bac4d6SBjoern A. Zeeb 				}
100*60bac4d6SBjoern A. Zeeb 			}
101*60bac4d6SBjoern A. Zeeb 		}
102*60bac4d6SBjoern A. Zeeb 	}
103*60bac4d6SBjoern A. Zeeb 
104*60bac4d6SBjoern A. Zeeb 	if (dp->hw_params->ring_mask->tx_mon_dest[grp_id]) {
105*60bac4d6SBjoern A. Zeeb 		monitor_mode = ATH12K_DP_TX_MONITOR_MODE;
106*60bac4d6SBjoern A. Zeeb 		ring_mask = dp->hw_params->ring_mask->tx_mon_dest[grp_id];
107*60bac4d6SBjoern A. Zeeb 		for (i = 0; i < dp->ab->num_radios; i++) {
108*60bac4d6SBjoern A. Zeeb 			for (j = 0; j < dp->hw_params->num_rxdma_per_pdev; j++) {
109*60bac4d6SBjoern A. Zeeb 				int id = i * dp->hw_params->num_rxdma_per_pdev + j;
110*60bac4d6SBjoern A. Zeeb 
111*60bac4d6SBjoern A. Zeeb 				if (ring_mask & BIT(id)) {
112*60bac4d6SBjoern A. Zeeb 					work_done =
113*60bac4d6SBjoern A. Zeeb 					ath12k_wifi7_dp_mon_process_ring(dp, id,
114*60bac4d6SBjoern A. Zeeb 									 napi, budget,
115*60bac4d6SBjoern A. Zeeb 									 monitor_mode);
116*60bac4d6SBjoern A. Zeeb 					budget -= work_done;
117*60bac4d6SBjoern A. Zeeb 					tot_work_done += work_done;
118*60bac4d6SBjoern A. Zeeb 
119*60bac4d6SBjoern A. Zeeb 					if (budget <= 0)
120*60bac4d6SBjoern A. Zeeb 						goto done;
121*60bac4d6SBjoern A. Zeeb 				}
122*60bac4d6SBjoern A. Zeeb 			}
123*60bac4d6SBjoern A. Zeeb 		}
124*60bac4d6SBjoern A. Zeeb 	}
125*60bac4d6SBjoern A. Zeeb 
126*60bac4d6SBjoern A. Zeeb 	if (dp->hw_params->ring_mask->reo_status[grp_id])
127*60bac4d6SBjoern A. Zeeb 		ath12k_wifi7_dp_rx_process_reo_status(dp);
128*60bac4d6SBjoern A. Zeeb 
129*60bac4d6SBjoern A. Zeeb 	if (dp->hw_params->ring_mask->host2rxdma[grp_id]) {
130*60bac4d6SBjoern A. Zeeb 		struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
131*60bac4d6SBjoern A. Zeeb 		LIST_HEAD(list);
132*60bac4d6SBjoern A. Zeeb 
133*60bac4d6SBjoern A. Zeeb 		ath12k_dp_rx_bufs_replenish(dp, rx_ring, &list, 0);
134*60bac4d6SBjoern A. Zeeb 	}
135*60bac4d6SBjoern A. Zeeb 
136*60bac4d6SBjoern A. Zeeb 	/* TODO: Implement handler for other interrupts */
137*60bac4d6SBjoern A. Zeeb 
138*60bac4d6SBjoern A. Zeeb done:
139*60bac4d6SBjoern A. Zeeb 	return tot_work_done;
140*60bac4d6SBjoern A. Zeeb }
141*60bac4d6SBjoern A. Zeeb 
142*60bac4d6SBjoern A. Zeeb static struct ath12k_dp_arch_ops ath12k_wifi7_dp_arch_ops = {
143*60bac4d6SBjoern A. Zeeb 	.service_srng = ath12k_wifi7_dp_service_srng,
144*60bac4d6SBjoern A. Zeeb 	.tx_get_vdev_bank_config = ath12k_wifi7_dp_tx_get_vdev_bank_config,
145*60bac4d6SBjoern A. Zeeb 	.reo_cmd_send = ath12k_wifi7_dp_reo_cmd_send,
146*60bac4d6SBjoern A. Zeeb 	.setup_pn_check_reo_cmd = ath12k_wifi7_dp_setup_pn_check_reo_cmd,
147*60bac4d6SBjoern A. Zeeb 	.rx_peer_tid_delete = ath12k_wifi7_dp_rx_peer_tid_delete,
148*60bac4d6SBjoern A. Zeeb 	.reo_cache_flush = ath12k_wifi7_dp_reo_cache_flush,
149*60bac4d6SBjoern A. Zeeb 	.rx_link_desc_return = ath12k_wifi7_dp_rx_link_desc_return,
150*60bac4d6SBjoern A. Zeeb 	.rx_frags_cleanup = ath12k_wifi7_dp_rx_frags_cleanup,
151*60bac4d6SBjoern A. Zeeb 	.peer_rx_tid_reo_update = ath12k_wifi7_peer_rx_tid_reo_update,
152*60bac4d6SBjoern A. Zeeb 	.rx_assign_reoq = ath12k_wifi7_dp_rx_assign_reoq,
153*60bac4d6SBjoern A. Zeeb 	.peer_rx_tid_qref_setup = ath12k_wifi7_peer_rx_tid_qref_setup,
154*60bac4d6SBjoern A. Zeeb 	.peer_rx_tid_qref_reset = ath12k_wifi7_peer_rx_tid_qref_reset,
155*60bac4d6SBjoern A. Zeeb 	.rx_tid_delete_handler = ath12k_wifi7_dp_rx_tid_delete_handler,
156*60bac4d6SBjoern A. Zeeb };
157*60bac4d6SBjoern A. Zeeb 
158*60bac4d6SBjoern A. Zeeb /* TODO: remove export once this file is built with wifi7 ko */
ath12k_wifi7_dp_device_alloc(struct ath12k_base * ab)159*60bac4d6SBjoern A. Zeeb struct ath12k_dp *ath12k_wifi7_dp_device_alloc(struct ath12k_base *ab)
160*60bac4d6SBjoern A. Zeeb {
161*60bac4d6SBjoern A. Zeeb 	struct ath12k_dp *dp;
162*60bac4d6SBjoern A. Zeeb 
163*60bac4d6SBjoern A. Zeeb 	/* TODO: align dp later if cache alignment becomes a bottleneck */
164*60bac4d6SBjoern A. Zeeb 	dp = kzalloc_obj(*dp);
165*60bac4d6SBjoern A. Zeeb 	if (!dp)
166*60bac4d6SBjoern A. Zeeb 		return NULL;
167*60bac4d6SBjoern A. Zeeb 
168*60bac4d6SBjoern A. Zeeb 	dp->ab = ab;
169*60bac4d6SBjoern A. Zeeb 	dp->dev = ab->dev;
170*60bac4d6SBjoern A. Zeeb 	dp->hw_params = ab->hw_params;
171*60bac4d6SBjoern A. Zeeb 	dp->hal = &ab->hal;
172*60bac4d6SBjoern A. Zeeb 
173*60bac4d6SBjoern A. Zeeb 	dp->ops = &ath12k_wifi7_dp_arch_ops;
174*60bac4d6SBjoern A. Zeeb 
175*60bac4d6SBjoern A. Zeeb 	return dp;
176*60bac4d6SBjoern A. Zeeb }
177*60bac4d6SBjoern A. Zeeb 
ath12k_wifi7_dp_device_free(struct ath12k_dp * dp)178*60bac4d6SBjoern A. Zeeb void ath12k_wifi7_dp_device_free(struct ath12k_dp *dp)
179*60bac4d6SBjoern A. Zeeb {
180*60bac4d6SBjoern A. Zeeb 	kfree(dp);
181*60bac4d6SBjoern A. Zeeb }
182