1 /*
2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 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 /**
21 * DOC: wlan_mgmt_txrx_utils_api.c
22 * This file contains mgmt txrx public API definitions for umac
23 * converged components.
24 */
25
26 #include "wlan_mgmt_txrx_utils_api.h"
27 #include "wlan_mgmt_txrx_tgt_api.h"
28 #include "../../core/src/wlan_mgmt_txrx_main_i.h"
29 #include "wlan_objmgr_psoc_obj.h"
30 #include "wlan_objmgr_global_obj.h"
31 #include "wlan_objmgr_pdev_obj.h"
32 #include "wlan_objmgr_vdev_obj.h"
33 #include "wlan_objmgr_peer_obj.h"
34 #include "qdf_nbuf.h"
35 #include "wlan_lmac_if_api.h"
36 #include <wlan_mgmt_txrx_rx_reo_utils_api.h>
37
38 /**
39 * wlan_mgmt_txrx_psoc_obj_create_notification() - called from objmgr when psoc
40 * is created
41 * @psoc: psoc context
42 * @arg: argument
43 *
44 * This function gets called from object manager when psoc is being created and
45 * creates mgmt_txrx context, mgmt desc pool.
46 *
47 * Return: QDF_STATUS_SUCCESS - in case of success
48 */
wlan_mgmt_txrx_psoc_obj_create_notification(struct wlan_objmgr_psoc * psoc,void * arg)49 static QDF_STATUS wlan_mgmt_txrx_psoc_obj_create_notification(
50 struct wlan_objmgr_psoc *psoc,
51 void *arg)
52 {
53 struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx;
54 QDF_STATUS status;
55
56 if (!psoc) {
57 mgmt_txrx_err("psoc context passed is NULL");
58 status = QDF_STATUS_E_INVAL;
59 goto err_return;
60 }
61
62 mgmt_txrx_psoc_ctx = qdf_mem_malloc(sizeof(*mgmt_txrx_psoc_ctx));
63 if (!mgmt_txrx_psoc_ctx) {
64 status = QDF_STATUS_E_NOMEM;
65 goto err_return;
66 }
67
68 mgmt_txrx_psoc_ctx->psoc = psoc;
69
70 qdf_spinlock_create(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
71
72 status = wlan_mgmt_rx_reo_psoc_obj_create_notification(psoc);
73 if (QDF_IS_STATUS_ERROR(status)) {
74 mgmt_txrx_err("Failed to run mgmt Rx REO psoc create handler");
75 goto err_psoc_attach;
76 }
77
78 if (wlan_objmgr_psoc_component_obj_attach(psoc,
79 WLAN_UMAC_COMP_MGMT_TXRX,
80 mgmt_txrx_psoc_ctx, QDF_STATUS_SUCCESS)
81 != QDF_STATUS_SUCCESS) {
82 mgmt_txrx_err("Failed to attach mgmt txrx ctx in psoc ctx");
83 status = QDF_STATUS_E_FAILURE;
84 goto err_psoc_attach;
85 }
86
87 mgmt_txrx_debug("Mgmt txrx creation successful, mgmt txrx ctx: %pK, psoc: %pK",
88 mgmt_txrx_psoc_ctx, psoc);
89
90 return QDF_STATUS_SUCCESS;
91
92 err_psoc_attach:
93 qdf_spinlock_destroy(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
94 qdf_mem_free(mgmt_txrx_psoc_ctx);
95 err_return:
96 return status;
97 }
98
99 /**
100 * wlan_mgmt_txrx_psoc_obj_destroy_notification() - called from objmgr when
101 * psoc is destroyed
102 * @psoc: psoc context
103 * @arg: argument
104 *
105 * This function gets called from object manager when psoc is being destroyed
106 * psoc deletes mgmt_txrx context, mgmt desc pool.
107 *
108 * Return: QDF_STATUS_SUCCESS - in case of success
109 */
wlan_mgmt_txrx_psoc_obj_destroy_notification(struct wlan_objmgr_psoc * psoc,void * arg)110 static QDF_STATUS wlan_mgmt_txrx_psoc_obj_destroy_notification(
111 struct wlan_objmgr_psoc *psoc,
112 void *arg)
113 {
114 struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx;
115 QDF_STATUS status;
116
117 if (!psoc) {
118 mgmt_txrx_err("psoc context passed is NULL");
119 return QDF_STATUS_E_INVAL;
120 }
121
122 mgmt_txrx_psoc_ctx = wlan_objmgr_psoc_get_comp_private_obj(
123 psoc, WLAN_UMAC_COMP_MGMT_TXRX);
124 if (!mgmt_txrx_psoc_ctx) {
125 mgmt_txrx_err("mgmt txrx context is already NULL");
126 return QDF_STATUS_E_FAILURE;
127 }
128
129 mgmt_txrx_debug("deleting mgmt txrx psoc obj, mgmt txrx ctx: %pK, psoc: %pK",
130 mgmt_txrx_psoc_ctx, psoc);
131
132 status = wlan_mgmt_rx_reo_psoc_obj_destroy_notification(psoc);
133 if (QDF_IS_STATUS_ERROR(status)) {
134 mgmt_txrx_err("Failed to run mgmt Rx REO psoc destroy handler");
135 return status;
136 }
137
138 if (wlan_objmgr_psoc_component_obj_detach(psoc,
139 WLAN_UMAC_COMP_MGMT_TXRX,
140 mgmt_txrx_psoc_ctx)
141 != QDF_STATUS_SUCCESS) {
142 mgmt_txrx_err("Failed to detach mgmt txrx ctx in psoc ctx");
143 return QDF_STATUS_E_FAILURE;
144 }
145
146 qdf_spinlock_destroy(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
147 qdf_mem_free(mgmt_txrx_psoc_ctx);
148
149 mgmt_txrx_debug("mgmt txrx deletion successful");
150
151 return QDF_STATUS_SUCCESS;
152 }
153
154 /**
155 * wlan_mgmt_txrx_pdev_obj_create_notification() - called from objmgr when pdev
156 * is created
157 * @pdev: pdev context
158 * @arg: argument
159 *
160 * This function gets called from object manager when pdev is being created and
161 * creates mgmt_txrx context, mgmt desc pool.
162 *
163 * Return: QDF_STATUS_SUCCESS - in case of success
164 */
wlan_mgmt_txrx_pdev_obj_create_notification(struct wlan_objmgr_pdev * pdev,void * arg)165 static QDF_STATUS wlan_mgmt_txrx_pdev_obj_create_notification(
166 struct wlan_objmgr_pdev *pdev,
167 void *arg)
168 {
169 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx;
170 struct mgmt_txrx_stats_t *mgmt_txrx_stats;
171 struct wlan_objmgr_psoc *psoc;
172 uint8_t pdev_id;
173 uint8_t psoc_id;
174 QDF_STATUS status;
175
176 if (!pdev) {
177 mgmt_txrx_err("pdev context passed is NULL");
178 status = QDF_STATUS_E_INVAL;
179 goto err_return;
180 }
181
182 psoc = wlan_pdev_get_psoc(pdev);
183
184 if (!psoc) {
185 mgmt_txrx_err("psoc context in pdev is NULL");
186 status = QDF_STATUS_E_INVAL;
187 goto err_return;
188 }
189
190 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
191
192 psoc_id = wlan_psoc_get_id(psoc);
193
194 mgmt_txrx_debug("enter pdev_id:%d psoc_id:%d", pdev_id, psoc_id);
195
196 mgmt_txrx_pdev_ctx = qdf_mem_malloc(sizeof(*mgmt_txrx_pdev_ctx));
197 if (!mgmt_txrx_pdev_ctx) {
198 status = QDF_STATUS_E_NOMEM;
199 goto err_return;
200 }
201
202 mgmt_txrx_pdev_ctx->pdev = pdev;
203
204 mgmt_txrx_debug("pool init pdev_id:%d psoc_id:%d", pdev_id, psoc_id);
205
206 status = wlan_mgmt_txrx_desc_pool_init(mgmt_txrx_pdev_ctx);
207 if (status != QDF_STATUS_SUCCESS) {
208 mgmt_txrx_err(
209 "Failed to initialize mgmt desc. pool with status: %u",
210 status);
211 goto err_desc_pool_init;
212 }
213
214 mgmt_txrx_stats = qdf_mem_malloc(sizeof(*mgmt_txrx_stats));
215 if (!mgmt_txrx_stats) {
216 status = QDF_STATUS_E_NOMEM;
217 goto err_mgmt_txrx_stats;
218 }
219 mgmt_txrx_pdev_ctx->mgmt_txrx_stats = mgmt_txrx_stats;
220
221 mgmt_txrx_debug("lock create pdev_id:%d psoc_id:%d", pdev_id, psoc_id);
222
223 qdf_wake_lock_create(&mgmt_txrx_pdev_ctx->wakelock_tx_cmp,
224 "mgmt_txrx tx_cmp");
225 qdf_runtime_lock_init(&mgmt_txrx_pdev_ctx->wakelock_tx_runtime_cmp);
226
227 mgmt_txrx_debug("notification create pdev_id:%d psoc_id:%d",
228 pdev_id, psoc_id);
229
230 status = wlan_mgmt_rx_reo_pdev_obj_create_notification(
231 pdev, mgmt_txrx_pdev_ctx);
232 if (QDF_IS_STATUS_ERROR(status)) {
233 mgmt_txrx_err("Failed to create mgmt Rx REO pdev object");
234 goto err_mgmt_rx_reo_attach;
235 }
236
237 mgmt_txrx_debug("obj attach pdev_id:%d psoc_id:%d", pdev_id, psoc_id);
238
239 if (wlan_objmgr_pdev_component_obj_attach(pdev,
240 WLAN_UMAC_COMP_MGMT_TXRX,
241 mgmt_txrx_pdev_ctx, QDF_STATUS_SUCCESS)
242 != QDF_STATUS_SUCCESS) {
243 mgmt_txrx_err("Failed to attach mgmt txrx ctx in pdev ctx");
244 status = QDF_STATUS_E_FAILURE;
245 goto err_pdev_attach;
246 }
247
248 mgmt_txrx_debug(
249 "Mgmt txrx creation successful, mgmt txrx ctx: %pK, pdev: %pK",
250 mgmt_txrx_pdev_ctx, pdev);
251
252 return QDF_STATUS_SUCCESS;
253
254 err_pdev_attach:
255 /* Avoiding error check in an error handler */
256 wlan_mgmt_rx_reo_pdev_obj_destroy_notification(pdev,
257 mgmt_txrx_pdev_ctx);
258 err_mgmt_rx_reo_attach:
259 qdf_runtime_lock_deinit(&mgmt_txrx_pdev_ctx->wakelock_tx_runtime_cmp);
260 qdf_wake_lock_destroy(&mgmt_txrx_pdev_ctx->wakelock_tx_cmp);
261 qdf_mem_free(mgmt_txrx_stats);
262 err_mgmt_txrx_stats:
263 wlan_mgmt_txrx_desc_pool_deinit(mgmt_txrx_pdev_ctx);
264 err_desc_pool_init:
265 qdf_mem_free(mgmt_txrx_pdev_ctx);
266 err_return:
267 return status;
268 }
269
270 /**
271 * wlan_mgmt_txrx_pdev_obj_destroy_notification() - called from objmgr when
272 * pdev is destroyed
273 * @pdev: pdev context
274 * @arg: argument
275 *
276 * This function gets called from object manager when pdev is being destroyed
277 * pdev deletes mgmt_txrx context, mgmt desc pool.
278 *
279 * Return: QDF_STATUS_SUCCESS - in case of success
280 */
wlan_mgmt_txrx_pdev_obj_destroy_notification(struct wlan_objmgr_pdev * pdev,void * arg)281 static QDF_STATUS wlan_mgmt_txrx_pdev_obj_destroy_notification(
282 struct wlan_objmgr_pdev *pdev,
283 void *arg)
284 {
285 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx;
286 QDF_STATUS status;
287
288 if (!pdev) {
289 mgmt_txrx_err("pdev context passed is NULL");
290 return QDF_STATUS_E_INVAL;
291 }
292
293 mgmt_txrx_pdev_ctx = wlan_objmgr_pdev_get_comp_private_obj(
294 pdev, WLAN_UMAC_COMP_MGMT_TXRX);
295 if (!mgmt_txrx_pdev_ctx) {
296 mgmt_txrx_err("mgmt txrx context is already NULL");
297 return QDF_STATUS_E_FAILURE;
298 }
299
300 mgmt_txrx_debug("deleting mgmt txrx pdev obj, mgmt txrx ctx: %pK, pdev: %pK",
301 mgmt_txrx_pdev_ctx, pdev);
302
303 status = wlan_mgmt_rx_reo_pdev_obj_destroy_notification(
304 pdev, mgmt_txrx_pdev_ctx);
305 if (QDF_IS_STATUS_ERROR(status)) {
306 mgmt_txrx_err("Failed to destroy mgmt Rx REO pdev object");
307 return QDF_STATUS_E_FAILURE;
308 }
309
310 if (wlan_objmgr_pdev_component_obj_detach(pdev,
311 WLAN_UMAC_COMP_MGMT_TXRX,
312 mgmt_txrx_pdev_ctx)
313 != QDF_STATUS_SUCCESS) {
314 mgmt_txrx_err("Failed to detach mgmt txrx ctx in pdev ctx");
315 return QDF_STATUS_E_FAILURE;
316 }
317
318 wlan_mgmt_txrx_desc_pool_deinit(mgmt_txrx_pdev_ctx);
319 qdf_mem_free(mgmt_txrx_pdev_ctx->mgmt_txrx_stats);
320 qdf_runtime_lock_deinit(&mgmt_txrx_pdev_ctx->wakelock_tx_runtime_cmp);
321 qdf_wake_lock_destroy(&mgmt_txrx_pdev_ctx->wakelock_tx_cmp);
322 qdf_mem_free(mgmt_txrx_pdev_ctx);
323
324 mgmt_txrx_debug("mgmt txrx deletion successful, pdev: %pK", pdev);
325
326 return QDF_STATUS_SUCCESS;
327 }
328
329
wlan_mgmt_txrx_init(void)330 QDF_STATUS wlan_mgmt_txrx_init(void)
331 {
332 QDF_STATUS status = QDF_STATUS_SUCCESS;
333
334 status = wlan_objmgr_register_psoc_create_handler(
335 WLAN_UMAC_COMP_MGMT_TXRX,
336 wlan_mgmt_txrx_psoc_obj_create_notification,
337 NULL);
338 if (status != QDF_STATUS_SUCCESS) {
339 mgmt_txrx_err("Failed to register mgmt txrx psoc create handler");
340 goto err_psoc_create;
341 }
342
343 status = wlan_objmgr_register_psoc_destroy_handler(
344 WLAN_UMAC_COMP_MGMT_TXRX,
345 wlan_mgmt_txrx_psoc_obj_destroy_notification,
346 NULL);
347 if (status != QDF_STATUS_SUCCESS) {
348 mgmt_txrx_err("Failed to register mgmt txrx psoc destroy handler");
349 goto err_psoc_delete;
350 }
351
352 status = wlan_objmgr_register_pdev_create_handler(
353 WLAN_UMAC_COMP_MGMT_TXRX,
354 wlan_mgmt_txrx_pdev_obj_create_notification,
355 NULL);
356 if (status != QDF_STATUS_SUCCESS) {
357 mgmt_txrx_err("Failed to register mgmt txrx pdev obj create handler");
358 goto err_pdev_create;
359 }
360
361 status = wlan_objmgr_register_pdev_destroy_handler(
362 WLAN_UMAC_COMP_MGMT_TXRX,
363 wlan_mgmt_txrx_pdev_obj_destroy_notification,
364 NULL);
365 if (status != QDF_STATUS_SUCCESS) {
366 mgmt_txrx_err("Failed to register mgmt txrx obj destroy handler");
367 goto err_pdev_delete;
368 }
369
370 status = wlan_mgmt_rx_reo_init();
371 if (status != QDF_STATUS_SUCCESS) {
372 mgmt_txrx_err("Failed to initialize mgmt Rx reo module");
373 goto err_reo_init;
374 }
375
376 mgmt_txrx_debug("Successfully registered create and destroy handlers with objmgr");
377 return QDF_STATUS_SUCCESS;
378
379 err_reo_init:
380 wlan_objmgr_unregister_pdev_destroy_handler(
381 WLAN_UMAC_COMP_MGMT_TXRX,
382 wlan_mgmt_txrx_pdev_obj_destroy_notification, NULL);
383 err_pdev_delete:
384 wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_MGMT_TXRX,
385 wlan_mgmt_txrx_pdev_obj_create_notification, NULL);
386 err_pdev_create:
387 wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_MGMT_TXRX,
388 wlan_mgmt_txrx_psoc_obj_destroy_notification, NULL);
389 err_psoc_delete:
390 wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_MGMT_TXRX,
391 wlan_mgmt_txrx_psoc_obj_create_notification, NULL);
392 err_psoc_create:
393 return status;
394 }
395
wlan_mgmt_txrx_deinit(void)396 QDF_STATUS wlan_mgmt_txrx_deinit(void)
397 {
398 if (QDF_IS_STATUS_ERROR(wlan_mgmt_rx_reo_deinit())) {
399 mgmt_txrx_err("Failed to de-initialize mgmt Rx reo module");
400 return QDF_STATUS_E_FAILURE;
401 }
402
403 if (wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_MGMT_TXRX,
404 wlan_mgmt_txrx_psoc_obj_create_notification,
405 NULL)
406 != QDF_STATUS_SUCCESS) {
407 return QDF_STATUS_E_FAILURE;
408 }
409
410 if (wlan_objmgr_unregister_psoc_destroy_handler(
411 WLAN_UMAC_COMP_MGMT_TXRX,
412 wlan_mgmt_txrx_psoc_obj_destroy_notification,
413 NULL)
414 != QDF_STATUS_SUCCESS) {
415 return QDF_STATUS_E_FAILURE;
416 }
417
418 if (wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_MGMT_TXRX,
419 wlan_mgmt_txrx_pdev_obj_create_notification,
420 NULL)
421 != QDF_STATUS_SUCCESS) {
422 return QDF_STATUS_E_FAILURE;
423 }
424
425 if (wlan_objmgr_unregister_pdev_destroy_handler(
426 WLAN_UMAC_COMP_MGMT_TXRX,
427 wlan_mgmt_txrx_pdev_obj_destroy_notification,
428 NULL)
429 != QDF_STATUS_SUCCESS) {
430 return QDF_STATUS_E_FAILURE;
431 }
432
433 mgmt_txrx_debug("Successfully unregistered create and destroy handlers with objmgr");
434 return QDF_STATUS_SUCCESS;
435 }
436
wlan_mgmt_txrx_mgmt_frame_tx(struct wlan_objmgr_peer * peer,void * context,qdf_nbuf_t buf,mgmt_tx_download_comp_cb tx_comp_cb,mgmt_ota_comp_cb tx_ota_comp_cb,enum wlan_umac_comp_id comp_id,void * mgmt_tx_params)437 QDF_STATUS wlan_mgmt_txrx_mgmt_frame_tx(struct wlan_objmgr_peer *peer,
438 void *context,
439 qdf_nbuf_t buf,
440 mgmt_tx_download_comp_cb tx_comp_cb,
441 mgmt_ota_comp_cb tx_ota_comp_cb,
442 enum wlan_umac_comp_id comp_id,
443 void *mgmt_tx_params)
444 {
445 struct mgmt_txrx_desc_elem_t *desc;
446 struct wlan_objmgr_psoc *psoc;
447 struct wlan_objmgr_pdev *pdev;
448 struct mgmt_txrx_priv_pdev_context *txrx_ctx;
449 struct wlan_objmgr_vdev *vdev;
450 QDF_STATUS status;
451 struct wlan_lmac_if_tx_ops *tx_ops;
452 struct ieee80211_frame *wh;
453
454 if (!peer) {
455 mgmt_txrx_err("peer passed is NULL");
456 return QDF_STATUS_E_NULL_VALUE;
457 }
458
459 status = wlan_objmgr_peer_try_get_ref(peer, WLAN_MGMT_NB_ID);
460 if (QDF_IS_STATUS_ERROR(status)) {
461 mgmt_txrx_err("failed to get ref count for peer %pK", peer);
462 return QDF_STATUS_E_NULL_VALUE;
463 }
464
465 vdev = wlan_peer_get_vdev(peer);
466 if (!vdev) {
467 mgmt_txrx_err("vdev unavailable for peer %pK", peer);
468 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID);
469 return QDF_STATUS_E_NULL_VALUE;
470 }
471
472 psoc = wlan_vdev_get_psoc(vdev);
473 if (!psoc) {
474 mgmt_txrx_err("psoc unavailable for peer %pK vdev %pK",
475 peer, vdev);
476 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID);
477 return QDF_STATUS_E_NULL_VALUE;
478 }
479
480 pdev = wlan_vdev_get_pdev(vdev);
481 if (!pdev) {
482 mgmt_txrx_err("pdev unavailable for peer %pK vdev %pK",
483 peer, vdev);
484 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID);
485 return QDF_STATUS_E_NULL_VALUE;
486 }
487
488 wh = (struct ieee80211_frame *)qdf_nbuf_data(buf);
489 if ((wh->i_fc[0] & QDF_IEEE80211_FC0_VERSION_MASK) !=
490 QDF_IEEE80211_FC0_VERSION_0) {
491 mgmt_txrx_err("Incorrect frame control version");
492 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID);
493 return QDF_STATUS_E_NULL_VALUE;
494 }
495
496 txrx_ctx = (struct mgmt_txrx_priv_pdev_context *)
497 wlan_objmgr_pdev_get_comp_private_obj(pdev,
498 WLAN_UMAC_COMP_MGMT_TXRX);
499 if (!txrx_ctx) {
500 mgmt_txrx_err("No txrx context for peer %pK pdev %pK",
501 peer, pdev);
502 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID);
503 return QDF_STATUS_E_NULL_VALUE;
504 }
505
506 desc = wlan_mgmt_txrx_desc_get(txrx_ctx);
507 if (!desc) {
508 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID);
509 return QDF_STATUS_E_RESOURCES;
510 }
511
512 desc->nbuf = buf;
513 desc->tx_ota_cmpl_cb = tx_ota_comp_cb;
514 desc->tx_dwnld_cmpl_cb = tx_comp_cb;
515 desc->peer = peer;
516 desc->vdev_id = wlan_vdev_get_id(vdev);
517 desc->context = context;
518
519 if (QDF_STATUS_E_NULL_VALUE ==
520 iot_sim_mgmt_tx_update(psoc, vdev, buf)) {
521 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID);
522 wlan_mgmt_txrx_desc_put(txrx_ctx, desc->desc_id);
523 return QDF_STATUS_E_NULL_VALUE;
524 }
525
526 tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
527 if (!tx_ops) {
528 mgmt_txrx_err("tx_ops is NULL");
529 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID);
530 wlan_mgmt_txrx_desc_put(txrx_ctx, desc->desc_id);
531 return QDF_STATUS_E_NULL_VALUE;
532 }
533
534 if (!tx_ops->mgmt_txrx_tx_ops.mgmt_tx_send) {
535 mgmt_txrx_err("mgmt txrx txop to send mgmt frame is NULL for psoc: %pK",
536 psoc);
537 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID);
538 desc->nbuf = NULL;
539 wlan_mgmt_txrx_desc_put(txrx_ctx, desc->desc_id);
540 return QDF_STATUS_E_FAILURE;
541 }
542
543 if (tx_ops->mgmt_txrx_tx_ops.mgmt_tx_send(
544 vdev, buf, desc->desc_id, mgmt_tx_params)) {
545 mgmt_txrx_err("Mgmt send fail for peer %pK psoc %pK pdev: %pK",
546 peer, psoc, pdev);
547 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID);
548 desc->nbuf = NULL;
549 wlan_mgmt_txrx_desc_put(txrx_ctx, desc->desc_id);
550 return QDF_STATUS_E_FAILURE;
551 }
552 return QDF_STATUS_SUCCESS;
553 }
554
wlan_mgmt_txrx_beacon_frame_tx(struct wlan_objmgr_peer * peer,qdf_nbuf_t buf,enum wlan_umac_comp_id comp_id)555 QDF_STATUS wlan_mgmt_txrx_beacon_frame_tx(struct wlan_objmgr_peer *peer,
556 qdf_nbuf_t buf,
557 enum wlan_umac_comp_id comp_id)
558 {
559 struct wlan_objmgr_vdev *vdev;
560 struct wlan_objmgr_psoc *psoc;
561 struct wlan_lmac_if_tx_ops *tx_ops;
562
563 vdev = wlan_peer_get_vdev(peer);
564 if (!vdev) {
565 mgmt_txrx_err("vdev unavailable for peer %pK", peer);
566 return QDF_STATUS_E_NULL_VALUE;
567 }
568
569 psoc = wlan_vdev_get_psoc(vdev);
570 if (!psoc) {
571 mgmt_txrx_err("psoc unavailable for peer %pK", peer);
572 return QDF_STATUS_E_NULL_VALUE;
573 }
574
575 tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
576 if (!tx_ops) {
577 mgmt_txrx_err("tx_ops is NULL");
578 return QDF_STATUS_E_NULL_VALUE;
579 }
580
581 if (!tx_ops->mgmt_txrx_tx_ops.beacon_send) {
582 mgmt_txrx_err("mgmt txrx tx op to send beacon frame is NULL for psoc: %pK",
583 psoc);
584 return QDF_STATUS_E_FAILURE;
585 }
586
587 if (tx_ops->mgmt_txrx_tx_ops.beacon_send(vdev, buf)) {
588 mgmt_txrx_err("Beacon send fail for peer %pK psoc %pK",
589 peer, psoc);
590 return QDF_STATUS_E_FAILURE;
591 }
592 return QDF_STATUS_SUCCESS;
593 }
594
wlan_mgmt_is_rmf_mgmt_action_frame(uint8_t action_category)595 bool wlan_mgmt_is_rmf_mgmt_action_frame(uint8_t action_category)
596 {
597 switch (action_category) {
598 case ACTION_CATEGORY_SPECTRUM_MGMT:
599 case ACTION_CATEGORY_QOS:
600 case ACTION_CATEGORY_DLS:
601 case ACTION_CATEGORY_BACK:
602 case ACTION_CATEGORY_RRM:
603 case ACTION_FAST_BSS_TRNST:
604 case ACTION_CATEGORY_SA_QUERY:
605 case ACTION_CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION:
606 case ACTION_CATEGORY_WNM:
607 case ACTION_CATEGORY_MESH_ACTION:
608 case ACTION_CATEGORY_MULTIHOP_ACTION:
609 case ACTION_CATEGORY_DMG:
610 case ACTION_CATEGORY_FST:
611 case ACTION_CATEGORY_RVS:
612 case ACTION_CATEGORY_SIG:
613 case ACTION_CATEGORY_FLOW_CONTROL:
614 case ACTION_CATEGORY_CONTROL_RSP_MCS_NEGO:
615 case ACTION_CATEGORY_FILS:
616 case ACTION_CATEGORY_CDMG:
617 case ACTION_CATEGORY_CMMG:
618 case ACTION_CATEGORY_GLK:
619 case ACTION_CATEGORY_VENDOR_SPECIFIC_PROTECTED:
620 return true;
621 default:
622 break;
623 }
624
625 return false;
626 }
627
628 #ifdef WLAN_SUPPORT_FILS
629 QDF_STATUS
wlan_mgmt_txrx_fd_action_frame_tx(struct wlan_objmgr_vdev * vdev,qdf_nbuf_t buf,enum wlan_umac_comp_id comp_id)630 wlan_mgmt_txrx_fd_action_frame_tx(struct wlan_objmgr_vdev *vdev,
631 qdf_nbuf_t buf,
632 enum wlan_umac_comp_id comp_id)
633 {
634 struct wlan_objmgr_psoc *psoc;
635 uint32_t vdev_id;
636 struct wlan_lmac_if_tx_ops *tx_ops;
637
638 if (!vdev) {
639 mgmt_txrx_err("Invalid vdev");
640 return QDF_STATUS_E_NULL_VALUE;
641 }
642 vdev_id = wlan_vdev_get_id(vdev);
643 psoc = wlan_vdev_get_psoc(vdev);
644 if (!psoc) {
645 mgmt_txrx_err("psoc unavailable for vdev %d", vdev_id);
646 return QDF_STATUS_E_NULL_VALUE;
647 }
648
649 tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
650 if (!tx_ops) {
651 mgmt_txrx_err("tx_ops is NULL");
652 return QDF_STATUS_E_NULL_VALUE;
653 }
654
655 if (!tx_ops->mgmt_txrx_tx_ops.fd_action_frame_send) {
656 mgmt_txrx_err("mgmt txrx txop to send fd action frame is NULL");
657 return QDF_STATUS_E_FAILURE;
658 }
659
660 if (tx_ops->mgmt_txrx_tx_ops.fd_action_frame_send(
661 vdev, buf)) {
662 mgmt_txrx_err("FD send fail for vdev %d", vdev_id);
663 return QDF_STATUS_E_FAILURE;
664 }
665
666 return QDF_STATUS_SUCCESS;
667 }
668 #endif /* WLAN_SUPPORT_FILS */
669
670 /**
671 * wlan_mgmt_txrx_create_rx_handler() - creates rx handler node for umac comp.
672 * @mgmt_txrx_psoc_ctx: mgmt txrx context
673 * @mgmt_rx_cb: mgmt rx callback to be registered
674 * @comp_id: umac component id
675 * @frm_type: mgmt. frame for which cb to be registered.
676 *
677 * This function creates rx handler node for frame type and
678 * umac component passed in the func.
679 *
680 * Return: QDF_STATUS_SUCCESS - in case of success
681 */
wlan_mgmt_txrx_create_rx_handler(struct mgmt_txrx_priv_psoc_context * mgmt_txrx_psoc_ctx,mgmt_frame_rx_callback mgmt_rx_cb,enum wlan_umac_comp_id comp_id,enum mgmt_frame_type frm_type)682 static QDF_STATUS wlan_mgmt_txrx_create_rx_handler(
683 struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx,
684 mgmt_frame_rx_callback mgmt_rx_cb,
685 enum wlan_umac_comp_id comp_id,
686 enum mgmt_frame_type frm_type)
687 {
688 struct mgmt_rx_handler *rx_handler;
689
690 rx_handler = qdf_mem_malloc(sizeof(*rx_handler));
691 if (!rx_handler)
692 return QDF_STATUS_E_NOMEM;
693
694 rx_handler->comp_id = comp_id;
695 rx_handler->rx_cb = mgmt_rx_cb;
696
697 qdf_spin_lock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
698 rx_handler->next = mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[frm_type];
699 mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[frm_type] = rx_handler;
700 qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
701
702 mgmt_txrx_debug("Callback registered for comp_id: %d, frm_type: %d",
703 comp_id, frm_type);
704 return QDF_STATUS_SUCCESS;
705 }
706
707 /**
708 * wlan_mgmt_txrx_delete_rx_handler() - deletes rx handler node for umac comp.
709 * @mgmt_txrx_psoc_ctx: mgmt txrx context
710 * @mgmt_rx_cb: mgmt rx callback to be deregistered
711 * @comp_id: umac component id
712 * @frm_type: mgmt. frame for which cb to be registered.
713 *
714 * This function deletes rx handler node for frame type and
715 * umac component passed in the func.
716 *
717 * Return: QDF_STATUS_SUCCESS - in case of success
718 */
wlan_mgmt_txrx_delete_rx_handler(struct mgmt_txrx_priv_psoc_context * mgmt_txrx_psoc_ctx,mgmt_frame_rx_callback mgmt_rx_cb,enum wlan_umac_comp_id comp_id,enum mgmt_frame_type frm_type)719 static QDF_STATUS wlan_mgmt_txrx_delete_rx_handler(
720 struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx,
721 mgmt_frame_rx_callback mgmt_rx_cb,
722 enum wlan_umac_comp_id comp_id,
723 enum mgmt_frame_type frm_type)
724 {
725 struct mgmt_rx_handler *rx_handler = NULL, *rx_handler_prev = NULL;
726 bool delete = false;
727
728 qdf_spin_lock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
729 rx_handler = mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[frm_type];
730 while (rx_handler) {
731 if (rx_handler->comp_id == comp_id &&
732 rx_handler->rx_cb == mgmt_rx_cb) {
733 if (rx_handler_prev)
734 rx_handler_prev->next =
735 rx_handler->next;
736 else
737 mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[frm_type] =
738 rx_handler->next;
739
740 qdf_mem_free(rx_handler);
741 delete = true;
742 break;
743 }
744
745 rx_handler_prev = rx_handler;
746 rx_handler = rx_handler->next;
747 }
748 qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock);
749
750 if (!delete) {
751 mgmt_txrx_err("No callback registered for comp_id: %d, frm_type: %d",
752 comp_id, frm_type);
753 return QDF_STATUS_E_FAILURE;
754 }
755
756 mgmt_txrx_debug("Callback deregistered for comp_id: %d, frm_type: %d",
757 comp_id, frm_type);
758 return QDF_STATUS_SUCCESS;
759 }
760
wlan_mgmt_txrx_register_rx_cb(struct wlan_objmgr_psoc * psoc,enum wlan_umac_comp_id comp_id,struct mgmt_txrx_mgmt_frame_cb_info * frm_cb_info,uint8_t num_entries)761 QDF_STATUS wlan_mgmt_txrx_register_rx_cb(
762 struct wlan_objmgr_psoc *psoc,
763 enum wlan_umac_comp_id comp_id,
764 struct mgmt_txrx_mgmt_frame_cb_info *frm_cb_info,
765 uint8_t num_entries)
766 {
767 struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx;
768 QDF_STATUS status;
769 uint8_t i, j;
770
771 if (!psoc) {
772 mgmt_txrx_err("psoc context is NULL");
773 return QDF_STATUS_E_INVAL;
774 }
775
776 if (comp_id >= WLAN_UMAC_MAX_COMPONENTS) {
777 mgmt_txrx_err("Invalid component id %d passed", comp_id);
778 return QDF_STATUS_E_INVAL;
779 }
780
781 if (!num_entries || num_entries >= MGMT_MAX_FRAME_TYPE) {
782 mgmt_txrx_err("Invalid value for num_entries: %d passed",
783 num_entries);
784 return QDF_STATUS_E_INVAL;
785 }
786
787 if (!frm_cb_info) {
788 mgmt_txrx_err("frame cb info pointer is NULL");
789 return QDF_STATUS_E_INVAL;
790 }
791
792 mgmt_txrx_psoc_ctx = (struct mgmt_txrx_priv_psoc_context *)
793 wlan_objmgr_psoc_get_comp_private_obj(psoc,
794 WLAN_UMAC_COMP_MGMT_TXRX);
795 if (!mgmt_txrx_psoc_ctx) {
796 mgmt_txrx_err("mgmt txrx context is NULL");
797 return QDF_STATUS_E_FAILURE;
798 }
799
800 for (i = 0; i < num_entries; i++) {
801 status = wlan_mgmt_txrx_create_rx_handler(mgmt_txrx_psoc_ctx,
802 frm_cb_info[i].mgmt_rx_cb, comp_id,
803 frm_cb_info[i].frm_type);
804 if (status != QDF_STATUS_SUCCESS) {
805 for (j = 0; j < i; j++) {
806 wlan_mgmt_txrx_delete_rx_handler(
807 mgmt_txrx_psoc_ctx,
808 frm_cb_info[j].mgmt_rx_cb,
809 comp_id, frm_cb_info[j].frm_type);
810 }
811 return status;
812 }
813 }
814
815 return QDF_STATUS_SUCCESS;
816 }
817
wlan_mgmt_txrx_deregister_rx_cb(struct wlan_objmgr_psoc * psoc,enum wlan_umac_comp_id comp_id,struct mgmt_txrx_mgmt_frame_cb_info * frm_cb_info,uint8_t num_entries)818 QDF_STATUS wlan_mgmt_txrx_deregister_rx_cb(
819 struct wlan_objmgr_psoc *psoc,
820 enum wlan_umac_comp_id comp_id,
821 struct mgmt_txrx_mgmt_frame_cb_info *frm_cb_info,
822 uint8_t num_entries)
823 {
824 struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx;
825 uint8_t i;
826
827 if (!psoc) {
828 mgmt_txrx_err("psoc context is NULL");
829 return QDF_STATUS_E_INVAL;
830 }
831
832 if (comp_id >= WLAN_UMAC_MAX_COMPONENTS) {
833 mgmt_txrx_err("Invalid component id %d passed", comp_id);
834 return QDF_STATUS_E_INVAL;
835 }
836
837 if (!num_entries || num_entries >= MGMT_MAX_FRAME_TYPE) {
838 mgmt_txrx_err("Invalid value for num_entries: %d passed",
839 num_entries);
840 return QDF_STATUS_E_INVAL;
841 }
842
843 if (!frm_cb_info) {
844 mgmt_txrx_err("frame cb info pointer is NULL");
845 return QDF_STATUS_E_INVAL;
846 }
847
848 mgmt_txrx_psoc_ctx = (struct mgmt_txrx_priv_psoc_context *)
849 wlan_objmgr_psoc_get_comp_private_obj(psoc,
850 WLAN_UMAC_COMP_MGMT_TXRX);
851 if (!mgmt_txrx_psoc_ctx) {
852 mgmt_txrx_err("mgmt txrx context is NULL");
853 return QDF_STATUS_E_FAILURE;
854 }
855
856 for (i = 0; i < num_entries; i++) {
857 wlan_mgmt_txrx_delete_rx_handler(mgmt_txrx_psoc_ctx,
858 frm_cb_info[i].mgmt_rx_cb, comp_id,
859 frm_cb_info[i].frm_type);
860 }
861
862 return QDF_STATUS_SUCCESS;
863 }
864
wlan_mgmt_txrx_psoc_open(struct wlan_objmgr_psoc * psoc)865 QDF_STATUS wlan_mgmt_txrx_psoc_open(struct wlan_objmgr_psoc *psoc)
866 {
867 return QDF_STATUS_SUCCESS;
868 }
869
wlan_mgmt_txrx_psoc_close(struct wlan_objmgr_psoc * psoc)870 QDF_STATUS wlan_mgmt_txrx_psoc_close(struct wlan_objmgr_psoc *psoc)
871 {
872 return QDF_STATUS_SUCCESS;
873 }
874
wlan_mgmt_txrx_psoc_enable(struct wlan_objmgr_psoc * psoc)875 QDF_STATUS wlan_mgmt_txrx_psoc_enable(struct wlan_objmgr_psoc *psoc)
876 {
877 return tgt_mgmt_txrx_register_ev_handler(psoc);
878 }
879
wlan_mgmt_txrx_psoc_disable(struct wlan_objmgr_psoc * psoc)880 QDF_STATUS wlan_mgmt_txrx_psoc_disable(struct wlan_objmgr_psoc *psoc)
881 {
882 return tgt_mgmt_txrx_unregister_ev_handler(psoc);
883 }
884
wlan_mgmt_txrx_pdev_open(struct wlan_objmgr_pdev * pdev)885 QDF_STATUS wlan_mgmt_txrx_pdev_open(struct wlan_objmgr_pdev *pdev)
886 {
887 return QDF_STATUS_SUCCESS;
888 }
889
wlan_mgmt_txrx_pdev_close(struct wlan_objmgr_pdev * pdev)890 QDF_STATUS wlan_mgmt_txrx_pdev_close(struct wlan_objmgr_pdev *pdev)
891 {
892 struct wlan_objmgr_psoc *psoc;
893 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx;
894 struct mgmt_txrx_desc_elem_t *mgmt_desc;
895 uint32_t pool_size;
896 uint32_t index;
897 struct wlan_lmac_if_tx_ops *tx_ops;
898
899 if (!pdev) {
900 mgmt_txrx_err("pdev context is NULL");
901 return QDF_STATUS_E_INVAL;
902 }
903
904 psoc = wlan_pdev_get_psoc(pdev);
905 if (!psoc) {
906 mgmt_txrx_err("psoc unavailable for pdev %pK", pdev);
907 return QDF_STATUS_E_NULL_VALUE;
908 }
909
910 tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
911 if (!tx_ops) {
912 mgmt_txrx_err("tx_ops is NULL");
913 return QDF_STATUS_E_NULL_VALUE;
914 }
915
916 mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *)
917 wlan_objmgr_pdev_get_comp_private_obj(pdev,
918 WLAN_UMAC_COMP_MGMT_TXRX);
919
920 if (!mgmt_txrx_pdev_ctx) {
921 mgmt_txrx_err("mgmt txrx context is NULL");
922 return QDF_STATUS_E_FAILURE;
923 }
924
925 pool_size = mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list.max_size;
926 if (!pool_size) {
927 mgmt_txrx_err("pool size is 0");
928 return QDF_STATUS_E_FAILURE;
929 }
930
931 for (index = 0; index < pool_size; index++) {
932 if (mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[index].in_use) {
933 mgmt_txrx_debug(
934 "mgmt descriptor with desc id: %d not in freelist",
935 index);
936 mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[index];
937 if (tx_ops->mgmt_txrx_tx_ops.
938 tx_drain_nbuf_op)
939 tx_ops->mgmt_txrx_tx_ops.
940 tx_drain_nbuf_op(pdev, mgmt_desc->nbuf);
941 qdf_nbuf_free(mgmt_desc->nbuf);
942 wlan_objmgr_peer_release_ref(mgmt_desc->peer,
943 WLAN_MGMT_NB_ID);
944 wlan_mgmt_txrx_desc_put(mgmt_txrx_pdev_ctx, index);
945 }
946 }
947
948 return QDF_STATUS_SUCCESS;
949 }
950
wlan_mgmt_txrx_vdev_drain(struct wlan_objmgr_vdev * vdev,mgmt_frame_fill_peer_cb mgmt_fill_peer_cb,void * status)951 QDF_STATUS wlan_mgmt_txrx_vdev_drain(struct wlan_objmgr_vdev *vdev,
952 mgmt_frame_fill_peer_cb mgmt_fill_peer_cb,
953 void *status)
954 {
955 struct wlan_objmgr_pdev *pdev;
956 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx;
957 struct mgmt_txrx_desc_elem_t *mgmt_desc;
958 struct wlan_objmgr_peer *peer;
959 struct wlan_objmgr_vdev *peer_vdev;
960 uint32_t pool_size;
961 int i;
962
963 if (!vdev) {
964 mgmt_txrx_err("vdev context is NULL");
965 return QDF_STATUS_E_INVAL;
966 }
967
968 pdev = wlan_vdev_get_pdev(vdev);
969 if (!pdev) {
970 mgmt_txrx_err("pdev context is NULL");
971 return QDF_STATUS_E_INVAL;
972 }
973 mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *)
974 wlan_objmgr_pdev_get_comp_private_obj(pdev,
975 WLAN_UMAC_COMP_MGMT_TXRX);
976 if (!mgmt_txrx_pdev_ctx) {
977 mgmt_txrx_err("mgmt txrx context is NULL");
978 return QDF_STATUS_E_FAILURE;
979 }
980
981 pool_size = mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list.max_size;
982 if (!pool_size) {
983 mgmt_txrx_err("pool size is 0");
984 return QDF_STATUS_E_FAILURE;
985 }
986
987 for (i = 0; i < pool_size; i++) {
988 if (mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i].in_use) {
989 mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i];
990 peer = mgmt_txrx_get_peer(pdev, mgmt_desc->desc_id);
991 if (peer) {
992 peer_vdev = wlan_peer_get_vdev(peer);
993 if (peer_vdev == vdev) {
994 if (mgmt_fill_peer_cb)
995 mgmt_fill_peer_cb(peer, mgmt_desc->nbuf);
996 mgmt_txrx_tx_completion_handler(pdev,
997 mgmt_desc->desc_id, 0, status);
998 }
999 }
1000 }
1001 }
1002
1003 return QDF_STATUS_SUCCESS;
1004 }
1005