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