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