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