1 /*
2  * Copyright (c) 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 any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /**
19  *  DOC: wlan_mgmt_txrx_rx_re_tgt_api.c
20  *  This file contains mgmt rx re-ordering tgt layer related function
21  *  definitions
22  */
23 #include <wlan_mgmt_txrx_rx_reo_tgt_api.h>
24 #include "../../core/src/wlan_mgmt_txrx_rx_reo_i.h"
25 #include <../../core/src/wlan_mgmt_txrx_main_i.h>
26 
27 QDF_STATUS
28 tgt_mgmt_rx_reo_get_num_active_hw_links(struct wlan_objmgr_psoc *psoc,
29 					int8_t *num_active_hw_links)
30 {
31 	struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops;
32 
33 	mgmt_rx_reo_txops = wlan_psoc_get_mgmt_rx_reo_txops(psoc);
34 	if (!mgmt_rx_reo_txops) {
35 		mgmt_rx_reo_err("mgmt rx reo txops is NULL");
36 		return QDF_STATUS_E_NULL_VALUE;
37 	}
38 
39 	if (!mgmt_rx_reo_txops->get_num_active_hw_links) {
40 		mgmt_rx_reo_err("get num active hw links txops is NULL");
41 		return QDF_STATUS_E_NULL_VALUE;
42 	}
43 
44 	return mgmt_rx_reo_txops->get_num_active_hw_links(psoc,
45 							  num_active_hw_links);
46 }
47 
48 QDF_STATUS
49 tgt_mgmt_rx_reo_get_valid_hw_link_bitmap(struct wlan_objmgr_psoc *psoc,
50 					 uint16_t *valid_hw_link_bitmap)
51 {
52 	struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops;
53 
54 	mgmt_rx_reo_txops = wlan_psoc_get_mgmt_rx_reo_txops(psoc);
55 	if (!mgmt_rx_reo_txops) {
56 		mgmt_rx_reo_err("mgmt rx reo txops is NULL");
57 		return QDF_STATUS_E_NULL_VALUE;
58 	}
59 
60 	if (!mgmt_rx_reo_txops->get_valid_hw_link_bitmap) {
61 		mgmt_rx_reo_err("get valid hw link bitmap txops is NULL");
62 		return QDF_STATUS_E_NULL_VALUE;
63 	}
64 
65 	return mgmt_rx_reo_txops->get_valid_hw_link_bitmap(psoc,
66 						valid_hw_link_bitmap);
67 }
68 
69 QDF_STATUS
70 tgt_mgmt_rx_reo_read_snapshot(
71 			struct wlan_objmgr_pdev *pdev,
72 			struct mgmt_rx_reo_snapshot_info *snapshot_info,
73 			enum mgmt_rx_reo_shared_snapshot_id id,
74 			struct mgmt_rx_reo_snapshot_params *value,
75 			struct mgmt_rx_reo_shared_snapshot (*raw_snapshot)
76 			[MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT])
77 {
78 	struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops;
79 
80 	mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev);
81 	if (!mgmt_rx_reo_txops) {
82 		mgmt_rx_reo_err("mgmt rx reo txops is NULL");
83 		return QDF_STATUS_E_INVAL;
84 	}
85 
86 	if (!mgmt_rx_reo_txops->read_mgmt_rx_reo_snapshot) {
87 		mgmt_rx_reo_err("mgmt rx reo read snapshot txops is NULL");
88 		return QDF_STATUS_E_NULL_VALUE;
89 	}
90 
91 	return mgmt_rx_reo_txops->read_mgmt_rx_reo_snapshot(pdev, snapshot_info,
92 							    id, value,
93 							    raw_snapshot);
94 }
95 
96 /**
97  * tgt_mgmt_rx_reo_enter_algo_without_buffer() - Entry point to the MGMT Rx REO
98  * algorithm when there is no frame buffer
99  * @pdev: pdev for which this frame/event is intended
100  * @reo_params: MGMT Rx REO parameters corresponding to this frame/event
101  * @type: Type of the MGMT Rx REO frame/event descriptor
102  *
103  * Return: QDF_STATUS of operation
104  */
105 static QDF_STATUS
106 tgt_mgmt_rx_reo_enter_algo_without_buffer(
107 				struct wlan_objmgr_pdev *pdev,
108 				struct mgmt_rx_reo_params *reo_params,
109 				enum mgmt_rx_reo_frame_descriptor_type type)
110 {
111 	struct mgmt_rx_event_params mgmt_rx_params = {0};
112 	struct mgmt_rx_reo_frame_descriptor desc = {0};
113 	bool is_frm_queued;
114 	QDF_STATUS status;
115 	int8_t link_id;
116 
117 	if (!pdev) {
118 		mgmt_rx_reo_err("pdev is null");
119 		return QDF_STATUS_E_NULL_VALUE;
120 	}
121 
122 	if (!wlan_mgmt_rx_reo_is_feature_enabled_at_pdev(pdev))
123 		return  QDF_STATUS_SUCCESS;
124 
125 	if (!reo_params) {
126 		mgmt_rx_reo_err("mgmt rx reo params are null");
127 		return QDF_STATUS_E_NULL_VALUE;
128 	}
129 
130 	link_id = wlan_get_mlo_link_id_from_pdev(pdev);
131 	if (link_id < 0) {
132 		mgmt_rx_reo_err("Invalid link %d for the pdev", link_id);
133 		return QDF_STATUS_E_INVAL;
134 	}
135 
136 	if (!reo_params->valid) {
137 		mgmt_rx_reo_err_rl("Invalid MGMT rx REO param for link %u",
138 				   link_id);
139 		return QDF_STATUS_E_INVAL;
140 	}
141 
142 	reo_params->link_id = link_id;
143 
144 	mgmt_rx_params.reo_params = reo_params;
145 
146 	desc.nbuf = NULL; /* No frame buffer */
147 	desc.rx_params = &mgmt_rx_params;
148 	desc.type = type;
149 	desc.ingress_timestamp = qdf_get_log_timestamp();
150 	desc.list_size_rx = -1;
151 	desc.list_insertion_pos = -1;
152 	desc.frame_type = IEEE80211_FC0_TYPE_MGT;
153 	desc.frame_subtype = 0xFF;
154 	desc.reo_required = is_mgmt_rx_reo_required(pdev, &desc);
155 
156 	/* Enter the REO algorithm */
157 	status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_frm_queued);
158 
159 	qdf_assert_always(!is_frm_queued);
160 
161 	return status;
162 }
163 
164 QDF_STATUS
165 tgt_mgmt_rx_reo_fw_consumed_event_handler(struct wlan_objmgr_pdev *pdev,
166 					  struct mgmt_rx_reo_params *params)
167 {
168 	return tgt_mgmt_rx_reo_enter_algo_without_buffer(
169 			pdev, params, MGMT_RX_REO_FRAME_DESC_FW_CONSUMED_FRAME);
170 }
171 
172 QDF_STATUS
173 tgt_mgmt_rx_reo_host_drop_handler(struct wlan_objmgr_pdev *pdev,
174 				  struct mgmt_rx_reo_params *params)
175 {
176 	return tgt_mgmt_rx_reo_enter_algo_without_buffer(
177 			pdev, params, MGMT_RX_REO_FRAME_DESC_ERROR_FRAME);
178 }
179 
180 QDF_STATUS tgt_mgmt_rx_reo_filter_config(struct wlan_objmgr_pdev *pdev,
181 					 struct mgmt_rx_reo_filter *filter)
182 {
183 	struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops;
184 
185 	mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev);
186 	if (!mgmt_rx_reo_txops) {
187 		mgmt_rx_reo_err("MGMT Rx REO txops is NULL");
188 		return QDF_STATUS_E_NULL_VALUE;
189 	}
190 
191 	if (!mgmt_rx_reo_txops->mgmt_rx_reo_filter_config) {
192 		mgmt_rx_reo_err("mgmt_rx_reo_filter_config is NULL");
193 		return QDF_STATUS_E_NULL_VALUE;
194 	}
195 
196 	return mgmt_rx_reo_txops->mgmt_rx_reo_filter_config(pdev, filter);
197 }
198 
199 QDF_STATUS
200 tgt_mgmt_rx_reo_get_snapshot_info
201 			(struct wlan_objmgr_pdev *pdev,
202 			 enum mgmt_rx_reo_shared_snapshot_id id,
203 			 struct mgmt_rx_reo_snapshot_info *snapshot_info)
204 {
205 	struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops;
206 
207 	mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev);
208 	if (!mgmt_rx_reo_txops) {
209 		mgmt_rx_reo_err("mgmt rx reo txops is NULL");
210 		return QDF_STATUS_E_NULL_VALUE;
211 	}
212 
213 	if (!mgmt_rx_reo_txops->get_mgmt_rx_reo_snapshot_info) {
214 		mgmt_rx_reo_err("txops entry for get snapshot info is null");
215 		return QDF_STATUS_E_NULL_VALUE;
216 	}
217 
218 	return mgmt_rx_reo_txops->get_mgmt_rx_reo_snapshot_info(pdev, id,
219 								snapshot_info);
220 }
221 
222 QDF_STATUS tgt_mgmt_rx_reo_frame_handler(
223 				struct wlan_objmgr_pdev *pdev,
224 				qdf_nbuf_t buf,
225 				struct mgmt_rx_event_params *mgmt_rx_params)
226 {
227 	QDF_STATUS status;
228 	struct mgmt_rx_reo_frame_descriptor desc = {0};
229 	bool is_queued;
230 	int8_t link_id;
231 	uint8_t frame_type;
232 	uint8_t frame_subtype;
233 	struct ieee80211_frame *wh;
234 
235 	if (!pdev) {
236 		mgmt_rx_reo_err("pdev is NULL");
237 		status = QDF_STATUS_E_NULL_VALUE;
238 		goto cleanup;
239 	}
240 
241 	if (!wlan_mgmt_rx_reo_is_simulation_in_progress() && !buf) {
242 		mgmt_rx_reo_err("nbuf is NULL");
243 		status = QDF_STATUS_E_NULL_VALUE;
244 		goto cleanup;
245 	}
246 
247 	if (!mgmt_rx_params) {
248 		mgmt_rx_reo_err("MGMT rx params is NULL");
249 		status = QDF_STATUS_E_NULL_VALUE;
250 		goto cleanup;
251 	}
252 
253 	if (!wlan_mgmt_rx_reo_is_feature_enabled_at_pdev(pdev))
254 		return tgt_mgmt_txrx_process_rx_frame(pdev, buf,
255 						      mgmt_rx_params);
256 
257 	if (!mgmt_rx_params->reo_params) {
258 		mgmt_rx_reo_err("MGMT rx REO params is NULL");
259 		status = QDF_STATUS_E_NULL_VALUE;
260 		goto cleanup;
261 	}
262 
263 	link_id = wlan_get_mlo_link_id_from_pdev(pdev);
264 	if (link_id < 0) {
265 		mgmt_rx_reo_err("Invalid link %d for the pdev", link_id);
266 		status = QDF_STATUS_E_INVAL;
267 		goto cleanup;
268 	}
269 
270 	if (!mgmt_rx_params->reo_params->valid) {
271 		mgmt_rx_reo_err_rl("Invalid MGMT rx REO param for link %u",
272 				   link_id);
273 		status = QDF_STATUS_E_INVAL;
274 		goto cleanup;
275 	}
276 
277 	mgmt_rx_params->reo_params->link_id = link_id;
278 
279 	/* Populate frame descriptor */
280 	desc.type = MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME;
281 	desc.nbuf = buf;
282 	desc.rx_params = mgmt_rx_params;
283 	desc.ingress_timestamp = qdf_get_log_timestamp();
284 	desc.list_size_rx = -1;
285 	desc.list_insertion_pos = -1;
286 
287 	wh = (struct ieee80211_frame *)qdf_nbuf_data(buf);
288 	frame_type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
289 	frame_subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
290 
291 	desc.frame_type = frame_type;
292 	desc.frame_subtype = frame_subtype;
293 
294 	if (frame_type != IEEE80211_FC0_TYPE_MGT ||
295 	    !is_mgmt_rx_reo_required(pdev, &desc)) {
296 		desc.reo_required = false;
297 		status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_queued);
298 
299 		if (QDF_IS_STATUS_ERROR(status)) {
300 			mgmt_rx_reo_err_rl("Failed to execute REO algorithm");
301 			goto cleanup;
302 		}
303 
304 		qdf_assert_always(!is_queued);
305 
306 		return tgt_mgmt_txrx_process_rx_frame(pdev, buf,
307 						      mgmt_rx_params);
308 	} else {
309 		desc.reo_required = true;
310 		status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_queued);
311 
312 		if (QDF_IS_STATUS_ERROR(status))
313 			mgmt_rx_reo_err_rl("Failed to execute REO algorithm");
314 
315 		/**
316 		 *  If frame is queued, we shouldn't free up params and
317 		 *  buf pointers.
318 		 */
319 		if (is_queued)
320 			return status;
321 	}
322 cleanup:
323 	qdf_nbuf_free(buf);
324 	free_mgmt_rx_event_params(mgmt_rx_params);
325 
326 	return status;
327 }
328