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