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