xref: /wlan-driver/qca-wifi-host-cmn/dp/wifi3.0/dp_reo.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name #include "dp_types.h"
21*5113495bSYour Name #include "hal_reo.h"
22*5113495bSYour Name #include "dp_internal.h"
23*5113495bSYour Name #include <qdf_time.h>
24*5113495bSYour Name 
25*5113495bSYour Name #define dp_reo_alert(params...) QDF_TRACE_FATAL(QDF_MODULE_ID_DP_REO, params)
26*5113495bSYour Name #define dp_reo_err(params...) QDF_TRACE_ERROR(QDF_MODULE_ID_DP_REO, params)
27*5113495bSYour Name #define dp_reo_warn(params...) QDF_TRACE_WARN(QDF_MODULE_ID_DP_REO, params)
28*5113495bSYour Name #define dp_reo_info(params...) \
29*5113495bSYour Name 	__QDF_TRACE_FL(QDF_TRACE_LEVEL_INFO_HIGH, QDF_MODULE_ID_DP_REO, ## params)
30*5113495bSYour Name #define dp_reo_debug(params...) QDF_TRACE_DEBUG(QDF_MODULE_ID_DP_REO, params)
31*5113495bSYour Name 
32*5113495bSYour Name #ifdef WLAN_FEATURE_DP_EVENT_HISTORY
33*5113495bSYour Name /**
34*5113495bSYour Name  * dp_reo_cmd_srng_event_record() - Record reo cmds posted
35*5113495bSYour Name  * to the reo cmd ring
36*5113495bSYour Name  * @soc: dp soc handle
37*5113495bSYour Name  * @type: reo cmd type
38*5113495bSYour Name  * @post_status: command error status
39*5113495bSYour Name  *
40*5113495bSYour Name  * Return: None
41*5113495bSYour Name  */
42*5113495bSYour Name static
dp_reo_cmd_srng_event_record(struct dp_soc * soc,enum hal_reo_cmd_type type,int post_status)43*5113495bSYour Name void dp_reo_cmd_srng_event_record(struct dp_soc *soc,
44*5113495bSYour Name 				  enum hal_reo_cmd_type type,
45*5113495bSYour Name 				  int post_status)
46*5113495bSYour Name {
47*5113495bSYour Name 	struct reo_cmd_event_history *cmd_event_history =
48*5113495bSYour Name 					&soc->stats.cmd_event_history;
49*5113495bSYour Name 	struct reo_cmd_event_record *record = cmd_event_history->cmd_record;
50*5113495bSYour Name 	int record_index;
51*5113495bSYour Name 
52*5113495bSYour Name 	record_index = (qdf_atomic_inc_return(&cmd_event_history->index)) &
53*5113495bSYour Name 				(REO_CMD_EVENT_HIST_MAX - 1);
54*5113495bSYour Name 
55*5113495bSYour Name 	record[record_index].cmd_type = type;
56*5113495bSYour Name 	record[record_index].cmd_return_status = post_status;
57*5113495bSYour Name 	record[record_index].timestamp  = qdf_get_log_timestamp();
58*5113495bSYour Name }
59*5113495bSYour Name #else
60*5113495bSYour Name static inline
dp_reo_cmd_srng_event_record(struct dp_soc * soc,enum hal_reo_cmd_type type,int post_status)61*5113495bSYour Name void dp_reo_cmd_srng_event_record(struct dp_soc *soc,
62*5113495bSYour Name 				  enum hal_reo_cmd_type type,
63*5113495bSYour Name 				  int post_status)
64*5113495bSYour Name {
65*5113495bSYour Name }
66*5113495bSYour Name #endif /*WLAN_FEATURE_DP_EVENT_HISTORY */
67*5113495bSYour Name 
68*5113495bSYour Name #ifdef DP_UMAC_HW_RESET_SUPPORT
dp_pause_reo_send_cmd(struct dp_soc * soc)69*5113495bSYour Name void dp_pause_reo_send_cmd(struct dp_soc *soc)
70*5113495bSYour Name {
71*5113495bSYour Name 	hal_unregister_reo_send_cmd(soc->hal_soc);
72*5113495bSYour Name }
73*5113495bSYour Name 
dp_resume_reo_send_cmd(struct dp_soc * soc)74*5113495bSYour Name void dp_resume_reo_send_cmd(struct dp_soc *soc)
75*5113495bSYour Name {
76*5113495bSYour Name 	hal_register_reo_send_cmd(soc->hal_soc);
77*5113495bSYour Name }
78*5113495bSYour Name 
79*5113495bSYour Name void
dp_reset_rx_reo_tid_queue(struct dp_soc * soc,void * hw_qdesc_vaddr,uint32_t size)80*5113495bSYour Name dp_reset_rx_reo_tid_queue(struct dp_soc *soc, void *hw_qdesc_vaddr,
81*5113495bSYour Name 			  uint32_t size)
82*5113495bSYour Name {
83*5113495bSYour Name 	hal_reset_rx_reo_tid_queue(soc->hal_soc, hw_qdesc_vaddr, size);
84*5113495bSYour Name }
85*5113495bSYour Name #endif
86*5113495bSYour Name 
dp_reo_send_cmd(struct dp_soc * soc,enum hal_reo_cmd_type type,struct hal_reo_cmd_params * params,void (* callback_fn),void * data)87*5113495bSYour Name QDF_STATUS dp_reo_send_cmd(struct dp_soc *soc, enum hal_reo_cmd_type type,
88*5113495bSYour Name 		     struct hal_reo_cmd_params *params,
89*5113495bSYour Name 		     void (*callback_fn), void *data)
90*5113495bSYour Name {
91*5113495bSYour Name 	struct dp_reo_cmd_info *reo_cmd;
92*5113495bSYour Name 	int num;
93*5113495bSYour Name 
94*5113495bSYour Name 	num = hal_reo_send_cmd(soc->hal_soc, soc->reo_cmd_ring.hal_srng, type,
95*5113495bSYour Name 			       params);
96*5113495bSYour Name 	if (num < 0)
97*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
98*5113495bSYour Name 
99*5113495bSYour Name 	dp_reo_cmd_srng_event_record(soc, type, num);
100*5113495bSYour Name 
101*5113495bSYour Name 	if (num < 0) {
102*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
103*5113495bSYour Name 	}
104*5113495bSYour Name 
105*5113495bSYour Name 	if (callback_fn) {
106*5113495bSYour Name 		reo_cmd = qdf_mem_malloc(sizeof(*reo_cmd));
107*5113495bSYour Name 		if (!reo_cmd) {
108*5113495bSYour Name 			dp_err_log("alloc failed for REO cmd:%d!!",
109*5113495bSYour Name 				   type);
110*5113495bSYour Name 			return QDF_STATUS_E_NOMEM;
111*5113495bSYour Name 		}
112*5113495bSYour Name 
113*5113495bSYour Name 		reo_cmd->cmd = num;
114*5113495bSYour Name 		reo_cmd->cmd_type = type;
115*5113495bSYour Name 		reo_cmd->handler = callback_fn;
116*5113495bSYour Name 		reo_cmd->data = data;
117*5113495bSYour Name 		qdf_spin_lock_bh(&soc->rx.reo_cmd_lock);
118*5113495bSYour Name 		TAILQ_INSERT_TAIL(&soc->rx.reo_cmd_list, reo_cmd,
119*5113495bSYour Name 				  reo_cmd_list_elem);
120*5113495bSYour Name 		qdf_spin_unlock_bh(&soc->rx.reo_cmd_lock);
121*5113495bSYour Name 	}
122*5113495bSYour Name 
123*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
124*5113495bSYour Name }
125*5113495bSYour Name 
dp_reo_status_ring_handler(struct dp_intr * int_ctx,struct dp_soc * soc)126*5113495bSYour Name uint32_t dp_reo_status_ring_handler(struct dp_intr *int_ctx, struct dp_soc *soc)
127*5113495bSYour Name {
128*5113495bSYour Name 	hal_ring_desc_t reo_desc;
129*5113495bSYour Name 	struct dp_reo_cmd_info *reo_cmd = NULL;
130*5113495bSYour Name 	union hal_reo_status reo_status;
131*5113495bSYour Name 	int num;
132*5113495bSYour Name 	int processed_count = 0;
133*5113495bSYour Name 
134*5113495bSYour Name 	if (dp_srng_access_start(int_ctx, soc, soc->reo_status_ring.hal_srng)) {
135*5113495bSYour Name 		return processed_count;
136*5113495bSYour Name 	}
137*5113495bSYour Name 	reo_desc = hal_srng_dst_get_next(soc->hal_soc,
138*5113495bSYour Name 					soc->reo_status_ring.hal_srng);
139*5113495bSYour Name 
140*5113495bSYour Name 	while (reo_desc) {
141*5113495bSYour Name 		uint16_t tlv = HAL_GET_TLV(reo_desc);
142*5113495bSYour Name 		QDF_STATUS status;
143*5113495bSYour Name 
144*5113495bSYour Name 		processed_count++;
145*5113495bSYour Name 
146*5113495bSYour Name 		status = hal_reo_status_update(soc->hal_soc,
147*5113495bSYour Name 					       reo_desc,
148*5113495bSYour Name 					       &reo_status, tlv, &num);
149*5113495bSYour Name 		if (status != QDF_STATUS_SUCCESS)
150*5113495bSYour Name 			goto next;
151*5113495bSYour Name 
152*5113495bSYour Name 		qdf_spin_lock_bh(&soc->rx.reo_cmd_lock);
153*5113495bSYour Name 		TAILQ_FOREACH(reo_cmd, &soc->rx.reo_cmd_list,
154*5113495bSYour Name 			reo_cmd_list_elem) {
155*5113495bSYour Name 			if (reo_cmd->cmd == num) {
156*5113495bSYour Name 				TAILQ_REMOVE(&soc->rx.reo_cmd_list, reo_cmd,
157*5113495bSYour Name 				reo_cmd_list_elem);
158*5113495bSYour Name 				break;
159*5113495bSYour Name 			}
160*5113495bSYour Name 		}
161*5113495bSYour Name 		qdf_spin_unlock_bh(&soc->rx.reo_cmd_lock);
162*5113495bSYour Name 
163*5113495bSYour Name 		if (reo_cmd) {
164*5113495bSYour Name 			reo_cmd->handler(soc, reo_cmd->data,
165*5113495bSYour Name 					&reo_status);
166*5113495bSYour Name 			qdf_mem_free(reo_cmd);
167*5113495bSYour Name 		}
168*5113495bSYour Name 
169*5113495bSYour Name next:
170*5113495bSYour Name 		reo_desc = hal_srng_dst_get_next(soc,
171*5113495bSYour Name 						soc->reo_status_ring.hal_srng);
172*5113495bSYour Name 	} /* while */
173*5113495bSYour Name 
174*5113495bSYour Name 	dp_srng_access_end(int_ctx, soc, soc->reo_status_ring.hal_srng);
175*5113495bSYour Name 	return processed_count;
176*5113495bSYour Name }
177*5113495bSYour Name 
dp_reo_cmdlist_destroy(struct dp_soc * soc)178*5113495bSYour Name void dp_reo_cmdlist_destroy(struct dp_soc *soc)
179*5113495bSYour Name {
180*5113495bSYour Name 	struct dp_reo_cmd_info *reo_cmd = NULL;
181*5113495bSYour Name 	struct dp_reo_cmd_info *tmp_cmd = NULL;
182*5113495bSYour Name 	union hal_reo_status reo_status;
183*5113495bSYour Name 
184*5113495bSYour Name 	reo_status.queue_status.header.status =
185*5113495bSYour Name 		HAL_REO_CMD_DRAIN;
186*5113495bSYour Name 
187*5113495bSYour Name 	qdf_spin_lock_bh(&soc->rx.reo_cmd_lock);
188*5113495bSYour Name 	TAILQ_FOREACH_SAFE(reo_cmd, &soc->rx.reo_cmd_list,
189*5113495bSYour Name 			reo_cmd_list_elem, tmp_cmd) {
190*5113495bSYour Name 		TAILQ_REMOVE(&soc->rx.reo_cmd_list, reo_cmd,
191*5113495bSYour Name 			reo_cmd_list_elem);
192*5113495bSYour Name 		reo_cmd->handler(soc, reo_cmd->data, &reo_status);
193*5113495bSYour Name 		qdf_mem_free(reo_cmd);
194*5113495bSYour Name 	}
195*5113495bSYour Name 	qdf_spin_unlock_bh(&soc->rx.reo_cmd_lock);
196*5113495bSYour Name }
197*5113495bSYour Name 
198*5113495bSYour Name #ifdef DP_UMAC_HW_RESET_SUPPORT
dp_cleanup_reo_cmd_module(struct dp_soc * soc)199*5113495bSYour Name void dp_cleanup_reo_cmd_module(struct dp_soc *soc)
200*5113495bSYour Name {
201*5113495bSYour Name 	dp_reo_cmdlist_destroy(soc);
202*5113495bSYour Name 	dp_reo_desc_freelist_destroy(soc);
203*5113495bSYour Name }
204*5113495bSYour Name #endif
205