1 /*
2 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2023 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 <wlan_mlo_mgr_cmn.h>
25 #include "../../core/src/wlan_mgmt_txrx_rx_reo_i.h"
26 #include <../../core/src/wlan_mgmt_txrx_main_i.h>
27
28 QDF_STATUS
tgt_mgmt_rx_reo_get_num_active_hw_links(struct wlan_objmgr_psoc * psoc,int8_t * num_active_hw_links)29 tgt_mgmt_rx_reo_get_num_active_hw_links(struct wlan_objmgr_psoc *psoc,
30 int8_t *num_active_hw_links)
31 {
32 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops;
33
34 mgmt_rx_reo_txops = wlan_psoc_get_mgmt_rx_reo_txops(psoc);
35 if (!mgmt_rx_reo_txops) {
36 mgmt_rx_reo_err("mgmt rx reo txops is NULL");
37 return QDF_STATUS_E_NULL_VALUE;
38 }
39
40 if (!mgmt_rx_reo_txops->get_num_active_hw_links) {
41 mgmt_rx_reo_err("get num active hw links txops is NULL");
42 return QDF_STATUS_E_NULL_VALUE;
43 }
44
45 return mgmt_rx_reo_txops->get_num_active_hw_links(psoc,
46 num_active_hw_links);
47 }
48
49 QDF_STATUS
tgt_mgmt_rx_reo_get_valid_hw_link_bitmap(struct wlan_objmgr_psoc * psoc,uint16_t * valid_hw_link_bitmap)50 tgt_mgmt_rx_reo_get_valid_hw_link_bitmap(struct wlan_objmgr_psoc *psoc,
51 uint16_t *valid_hw_link_bitmap)
52 {
53 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops;
54
55 mgmt_rx_reo_txops = wlan_psoc_get_mgmt_rx_reo_txops(psoc);
56 if (!mgmt_rx_reo_txops) {
57 mgmt_rx_reo_err("mgmt rx reo txops is NULL");
58 return QDF_STATUS_E_NULL_VALUE;
59 }
60
61 if (!mgmt_rx_reo_txops->get_valid_hw_link_bitmap) {
62 mgmt_rx_reo_err("get valid hw link bitmap txops is NULL");
63 return QDF_STATUS_E_NULL_VALUE;
64 }
65
66 return mgmt_rx_reo_txops->get_valid_hw_link_bitmap(psoc,
67 valid_hw_link_bitmap);
68 }
69
70 QDF_STATUS
tgt_mgmt_rx_reo_read_snapshot(struct wlan_objmgr_pdev * pdev,struct mgmt_rx_reo_snapshot_info * snapshot_info,enum mgmt_rx_reo_shared_snapshot_id id,struct mgmt_rx_reo_snapshot_params * value,struct mgmt_rx_reo_shared_snapshot (* raw_snapshot)[MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT])71 tgt_mgmt_rx_reo_read_snapshot(
72 struct wlan_objmgr_pdev *pdev,
73 struct mgmt_rx_reo_snapshot_info *snapshot_info,
74 enum mgmt_rx_reo_shared_snapshot_id id,
75 struct mgmt_rx_reo_snapshot_params *value,
76 struct mgmt_rx_reo_shared_snapshot (*raw_snapshot)
77 [MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT])
78 {
79 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops;
80
81 mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev);
82 if (!mgmt_rx_reo_txops) {
83 mgmt_rx_reo_err("mgmt rx reo txops is NULL");
84 return QDF_STATUS_E_INVAL;
85 }
86
87 if (!mgmt_rx_reo_txops->read_mgmt_rx_reo_snapshot) {
88 mgmt_rx_reo_err("mgmt rx reo read snapshot txops is NULL");
89 return QDF_STATUS_E_NULL_VALUE;
90 }
91
92 return mgmt_rx_reo_txops->read_mgmt_rx_reo_snapshot(pdev, snapshot_info,
93 id, value,
94 raw_snapshot);
95 }
96
97 /**
98 * tgt_mgmt_rx_reo_enter_algo_without_buffer() - Entry point to the MGMT Rx REO
99 * algorithm when there is no frame buffer
100 * @pdev: pdev for which this frame/event is intended
101 * @reo_params: MGMT Rx REO parameters corresponding to this frame/event
102 * @type: Type of the MGMT Rx REO frame/event descriptor
103 *
104 * Return: QDF_STATUS of operation
105 */
106 static QDF_STATUS
tgt_mgmt_rx_reo_enter_algo_without_buffer(struct wlan_objmgr_pdev * pdev,struct mgmt_rx_reo_params * reo_params,enum mgmt_rx_reo_frame_descriptor_type type)107 tgt_mgmt_rx_reo_enter_algo_without_buffer(
108 struct wlan_objmgr_pdev *pdev,
109 struct mgmt_rx_reo_params *reo_params,
110 enum mgmt_rx_reo_frame_descriptor_type type)
111 {
112 struct mgmt_rx_event_params mgmt_rx_params = {0};
113 struct mgmt_rx_reo_frame_descriptor desc = {0};
114 bool is_frm_queued;
115 QDF_STATUS status;
116 int8_t link_id;
117 uint8_t ml_grp_id;
118
119 if (!pdev) {
120 mgmt_rx_reo_err("pdev is null");
121 return QDF_STATUS_E_NULL_VALUE;
122 }
123
124 if (!wlan_mgmt_rx_reo_is_feature_enabled_at_pdev(pdev))
125 return QDF_STATUS_SUCCESS;
126
127 if (!reo_params) {
128 mgmt_rx_reo_err("mgmt rx reo params are null");
129 return QDF_STATUS_E_NULL_VALUE;
130 }
131
132 link_id = wlan_get_mlo_link_id_from_pdev(pdev);
133 if (link_id < 0) {
134 mgmt_rx_reo_err("Invalid link %d for the pdev", link_id);
135 return QDF_STATUS_E_INVAL;
136 }
137
138 ml_grp_id = wlan_get_mlo_grp_id_from_pdev(pdev);
139 if (ml_grp_id > WLAN_MAX_MLO_GROUPS) {
140 mgmt_rx_reo_err("Invalid MLO Group %d for the pdev",
141 ml_grp_id);
142 return QDF_STATUS_E_INVAL;
143 }
144
145 reo_params->link_id = link_id;
146 reo_params->mlo_grp_id = ml_grp_id;
147 mgmt_rx_params.reo_params = reo_params;
148
149 desc.nbuf = NULL; /* No frame buffer */
150 desc.rx_params = &mgmt_rx_params;
151 desc.reo_params_copy = *mgmt_rx_params.reo_params;
152 desc.type = type;
153 desc.ingress_timestamp = qdf_get_log_timestamp();
154 desc.ingress_list_size_rx = -1;
155 desc.ingress_list_insertion_pos = -1;
156 desc.egress_list_size_rx = -1;
157 desc.egress_list_insertion_pos = -1;
158 desc.frame_type = IEEE80211_FC0_TYPE_MGT;
159 desc.frame_subtype = 0xFF;
160 desc.reo_required = is_mgmt_rx_reo_required(pdev, &desc);
161 desc.queued_list = MGMT_RX_REO_LIST_TYPE_INVALID;
162 desc.drop = false;
163 desc.drop_reason = MGMT_RX_REO_INGRESS_DROP_REASON_INVALID;
164
165 /* Enter the REO algorithm */
166 status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_frm_queued);
167 if (QDF_IS_STATUS_ERROR(status))
168 return status;
169
170 if (is_frm_queued) {
171 mgmt_rx_reo_err("Frame is queued to reo list");
172 return QDF_STATUS_E_FAILURE;
173 }
174
175 return QDF_STATUS_SUCCESS;
176 }
177
178 QDF_STATUS
tgt_mgmt_rx_reo_fw_consumed_event_handler(struct wlan_objmgr_pdev * pdev,struct mgmt_rx_reo_params * params)179 tgt_mgmt_rx_reo_fw_consumed_event_handler(struct wlan_objmgr_pdev *pdev,
180 struct mgmt_rx_reo_params *params)
181 {
182 return tgt_mgmt_rx_reo_enter_algo_without_buffer(
183 pdev, params, MGMT_RX_REO_FRAME_DESC_FW_CONSUMED_FRAME);
184 }
185
186 QDF_STATUS
tgt_mgmt_rx_reo_host_drop_handler(struct wlan_objmgr_pdev * pdev,struct mgmt_rx_reo_params * params)187 tgt_mgmt_rx_reo_host_drop_handler(struct wlan_objmgr_pdev *pdev,
188 struct mgmt_rx_reo_params *params)
189 {
190 return tgt_mgmt_rx_reo_enter_algo_without_buffer(
191 pdev, params, MGMT_RX_REO_FRAME_DESC_ERROR_FRAME);
192 }
193
194 /**
195 * psoc_get_hw_link_id_bmap() - Helper API to get HW link ID bitmap of the
196 * pdevs in a psoc
197 * @psoc: Pointer to psoc object
198 * @obj: Pointer to pdev object
199 * @arg: pointer to void * argument
200 *
201 * Return: void
202 */
203 static void
psoc_get_hw_link_id_bmap(struct wlan_objmgr_psoc * psoc,void * obj,void * arg)204 psoc_get_hw_link_id_bmap(struct wlan_objmgr_psoc *psoc, void *obj, void *arg)
205 {
206 struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj;
207 uint32_t *link_bitmap = (uint32_t *)arg;
208 int8_t cur_link;
209
210 cur_link = wlan_get_mlo_link_id_from_pdev(pdev);
211 if (cur_link < 0 || cur_link >= MAX_MLO_LINKS) {
212 mgmt_rx_reo_err("Invalid link = %d", cur_link);
213 return;
214 }
215
216 *link_bitmap |= (1 << cur_link);
217 }
218
219 QDF_STATUS
tgt_mgmt_rx_reo_release_frames(struct wlan_objmgr_psoc * psoc)220 tgt_mgmt_rx_reo_release_frames(struct wlan_objmgr_psoc *psoc)
221 {
222 uint8_t mlo_grp_id;
223 uint32_t link_bitmap = 0;
224
225 mlo_grp_id = wlan_mlo_get_psoc_group_id(psoc);
226
227 wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
228 psoc_get_hw_link_id_bmap,
229 &link_bitmap, false, WLAN_MGMT_RX_REO_ID);
230
231 return wlan_mgmt_rx_reo_release_frames(mlo_grp_id, link_bitmap);
232 }
233
tgt_mgmt_rx_reo_filter_config(struct wlan_objmgr_pdev * pdev,struct mgmt_rx_reo_filter * filter)234 QDF_STATUS tgt_mgmt_rx_reo_filter_config(struct wlan_objmgr_pdev *pdev,
235 struct mgmt_rx_reo_filter *filter)
236 {
237 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops;
238
239 mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev);
240 if (!mgmt_rx_reo_txops) {
241 mgmt_rx_reo_err("MGMT Rx REO txops is NULL");
242 return QDF_STATUS_E_NULL_VALUE;
243 }
244
245 if (!mgmt_rx_reo_txops->mgmt_rx_reo_filter_config) {
246 mgmt_rx_reo_err("mgmt_rx_reo_filter_config is NULL");
247 return QDF_STATUS_E_NULL_VALUE;
248 }
249
250 return mgmt_rx_reo_txops->mgmt_rx_reo_filter_config(pdev, filter);
251 }
252
253 QDF_STATUS
tgt_mgmt_rx_reo_get_snapshot_info(struct wlan_objmgr_pdev * pdev,enum mgmt_rx_reo_shared_snapshot_id id,struct mgmt_rx_reo_snapshot_info * snapshot_info)254 tgt_mgmt_rx_reo_get_snapshot_info
255 (struct wlan_objmgr_pdev *pdev,
256 enum mgmt_rx_reo_shared_snapshot_id id,
257 struct mgmt_rx_reo_snapshot_info *snapshot_info)
258 {
259 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops;
260
261 mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev);
262 if (!mgmt_rx_reo_txops) {
263 mgmt_rx_reo_err("mgmt rx reo txops is NULL");
264 return QDF_STATUS_E_NULL_VALUE;
265 }
266
267 if (!mgmt_rx_reo_txops->get_mgmt_rx_reo_snapshot_info) {
268 mgmt_rx_reo_err("txops entry for get snapshot info is null");
269 return QDF_STATUS_E_NULL_VALUE;
270 }
271
272 return mgmt_rx_reo_txops->get_mgmt_rx_reo_snapshot_info(pdev, id,
273 snapshot_info);
274 }
275
276 bool
wlan_mgmt_rx_reo_check_simulation_in_progress(struct wlan_objmgr_pdev * pdev)277 wlan_mgmt_rx_reo_check_simulation_in_progress(struct wlan_objmgr_pdev *pdev)
278 {
279 uint8_t ml_grp_id;
280 struct wlan_objmgr_psoc *psoc;
281
282 psoc = wlan_pdev_get_psoc(pdev);
283 if (!psoc)
284 return false;
285
286 if (!wlan_mlo_get_psoc_capable(psoc))
287 return false;
288
289 ml_grp_id = wlan_get_mlo_grp_id_from_pdev(pdev);
290 if (ml_grp_id > WLAN_MAX_MLO_GROUPS) {
291 mgmt_rx_reo_err("INVALID ML Group ID for the PDEV");
292 return false;
293 }
294
295 if (!wlan_mgmt_rx_reo_is_simulation_in_progress(ml_grp_id))
296 return false;
297
298 return true;
299 }
300
tgt_mgmt_rx_reo_frame_handler(struct wlan_objmgr_pdev * pdev,qdf_nbuf_t buf,struct mgmt_rx_event_params * mgmt_rx_params)301 QDF_STATUS tgt_mgmt_rx_reo_frame_handler(
302 struct wlan_objmgr_pdev *pdev,
303 qdf_nbuf_t buf,
304 struct mgmt_rx_event_params *mgmt_rx_params)
305 {
306 QDF_STATUS status;
307 struct mgmt_rx_reo_frame_descriptor desc = {0};
308 bool is_queued;
309 int8_t link_id;
310 uint8_t ml_grp_id;
311 uint8_t frame_type;
312 uint8_t frame_subtype;
313 struct ieee80211_frame *wh;
314
315 if (!pdev) {
316 mgmt_rx_reo_err("pdev is NULL");
317 status = QDF_STATUS_E_NULL_VALUE;
318 goto cleanup;
319 }
320
321 if (!wlan_mgmt_rx_reo_check_simulation_in_progress(pdev) && !buf) {
322 mgmt_rx_reo_err("nbuf is NULL");
323 status = QDF_STATUS_E_NULL_VALUE;
324 goto cleanup;
325 }
326
327 if (!mgmt_rx_params) {
328 mgmt_rx_reo_err("MGMT rx params is NULL");
329 status = QDF_STATUS_E_NULL_VALUE;
330 goto cleanup;
331 }
332
333 if (!wlan_mgmt_rx_reo_is_feature_enabled_at_pdev(pdev))
334 return tgt_mgmt_txrx_process_rx_frame(pdev, buf,
335 mgmt_rx_params);
336
337 if (!mgmt_rx_params->reo_params) {
338 mgmt_rx_reo_err("MGMT rx REO params is NULL");
339 status = QDF_STATUS_E_NULL_VALUE;
340 goto cleanup;
341 }
342
343 link_id = wlan_get_mlo_link_id_from_pdev(pdev);
344 if (link_id < 0) {
345 mgmt_rx_reo_err("Invalid link %d for the pdev", link_id);
346 status = QDF_STATUS_E_INVAL;
347 goto cleanup;
348 }
349
350 ml_grp_id = wlan_get_mlo_grp_id_from_pdev(pdev);
351 if (ml_grp_id > WLAN_MAX_MLO_GROUPS) {
352 mgmt_rx_reo_err("Invalid MGMT rx reo Group id");
353 status = QDF_STATUS_E_INVAL;
354 goto cleanup;
355 }
356
357 mgmt_rx_params->reo_params->link_id = link_id;
358 mgmt_rx_params->reo_params->mlo_grp_id = ml_grp_id;
359
360 /* Populate frame descriptor */
361 desc.type = MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME;
362 desc.nbuf = buf;
363 desc.rx_params = mgmt_rx_params;
364 desc.reo_params_copy = *mgmt_rx_params->reo_params;
365 desc.ingress_timestamp = qdf_get_log_timestamp();
366 desc.ingress_list_size_rx = -1;
367 desc.ingress_list_insertion_pos = -1;
368 desc.egress_list_size_rx = -1;
369 desc.egress_list_insertion_pos = -1;
370 desc.queued_list = MGMT_RX_REO_LIST_TYPE_INVALID;
371 desc.drop = false;
372 desc.drop_reason = MGMT_RX_REO_INGRESS_DROP_REASON_INVALID;
373
374 wh = (struct ieee80211_frame *)qdf_nbuf_data(buf);
375 frame_type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
376 frame_subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
377
378 desc.frame_type = frame_type;
379 desc.frame_subtype = frame_subtype;
380
381 if (frame_type != IEEE80211_FC0_TYPE_MGT ||
382 !is_mgmt_rx_reo_required(pdev, &desc)) {
383 desc.reo_required = false;
384 status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_queued);
385
386 if (QDF_IS_STATUS_ERROR(status)) {
387 mgmt_rx_reo_warn_rl("Failed to execute REO algorithm");
388 goto cleanup;
389 }
390
391 if (is_queued) {
392 mgmt_rx_reo_err("Frame is queued to reo list");
393 return QDF_STATUS_E_FAILURE;
394 }
395
396 return tgt_mgmt_txrx_process_rx_frame(pdev, buf,
397 mgmt_rx_params);
398 } else {
399 desc.reo_required = true;
400 status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_queued);
401
402 if (QDF_IS_STATUS_ERROR(status))
403 mgmt_rx_reo_warn_rl("Failed to execute REO algorithm");
404
405 /**
406 * If frame is queued, we shouldn't free up params and
407 * buf pointers.
408 */
409 if (is_queued)
410 return status;
411 }
412 cleanup:
413 qdf_nbuf_free(buf);
414 free_mgmt_rx_event_params(mgmt_rx_params);
415
416 return status;
417 }
418
419 QDF_STATUS
tgt_mgmt_rx_reo_schedule_delivery(struct wlan_objmgr_psoc * psoc)420 tgt_mgmt_rx_reo_schedule_delivery(struct wlan_objmgr_psoc *psoc)
421 {
422 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops;
423
424 mgmt_rx_reo_txops = wlan_psoc_get_mgmt_rx_reo_txops(psoc);
425 if (!mgmt_rx_reo_txops) {
426 mgmt_rx_reo_err("MGMT Rx REO txops is NULL");
427 return QDF_STATUS_E_NULL_VALUE;
428 }
429
430 if (!mgmt_rx_reo_txops->schedule_delivery) {
431 mgmt_rx_reo_err("mgmt_rx_reo_schedule delivery is NULL");
432 return QDF_STATUS_E_NULL_VALUE;
433 }
434
435 return mgmt_rx_reo_txops->schedule_delivery(psoc);
436 }
437