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