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