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 374 if (!peer) { 375 mgmt_txrx_err("peer passed is NULL"); 376 return QDF_STATUS_E_NULL_VALUE; 377 } 378 379 status = wlan_objmgr_peer_try_get_ref(peer, WLAN_MGMT_NB_ID); 380 if (QDF_IS_STATUS_ERROR(status)) { 381 mgmt_txrx_err("failed to get ref count for peer %pK", peer); 382 return QDF_STATUS_E_NULL_VALUE; 383 } 384 385 vdev = wlan_peer_get_vdev(peer); 386 if (!vdev) { 387 mgmt_txrx_err("vdev unavailable for peer %pK", peer); 388 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID); 389 return QDF_STATUS_E_NULL_VALUE; 390 } 391 392 psoc = wlan_vdev_get_psoc(vdev); 393 if (!psoc) { 394 mgmt_txrx_err("psoc 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 pdev = wlan_vdev_get_pdev(vdev); 401 if (!pdev) { 402 mgmt_txrx_err("pdev unavailable for peer %pK vdev %pK", 403 peer, vdev); 404 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID); 405 return QDF_STATUS_E_NULL_VALUE; 406 } 407 408 txrx_ctx = (struct mgmt_txrx_priv_pdev_context *) 409 wlan_objmgr_pdev_get_comp_private_obj(pdev, 410 WLAN_UMAC_COMP_MGMT_TXRX); 411 if (!txrx_ctx) { 412 mgmt_txrx_err("No txrx context for peer %pK pdev %pK", 413 peer, pdev); 414 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID); 415 return QDF_STATUS_E_NULL_VALUE; 416 } 417 418 desc = wlan_mgmt_txrx_desc_get(txrx_ctx); 419 if (!desc) { 420 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID); 421 return QDF_STATUS_E_RESOURCES; 422 } 423 424 desc->nbuf = buf; 425 desc->tx_ota_cmpl_cb = tx_ota_comp_cb; 426 desc->tx_dwnld_cmpl_cb = tx_comp_cb; 427 desc->peer = peer; 428 desc->vdev_id = wlan_vdev_get_id(vdev); 429 desc->context = context; 430 431 if (!psoc->soc_cb.tx_ops.mgmt_txrx_tx_ops.mgmt_tx_send) { 432 mgmt_txrx_err( 433 "mgmt txrx txop to send mgmt frame is NULL for psoc: %pK", 434 psoc); 435 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID); 436 desc->nbuf = NULL; 437 wlan_mgmt_txrx_desc_put(txrx_ctx, desc->desc_id); 438 return QDF_STATUS_E_FAILURE; 439 } 440 441 if (psoc->soc_cb.tx_ops.mgmt_txrx_tx_ops.mgmt_tx_send( 442 vdev, buf, desc->desc_id, mgmt_tx_params)) { 443 mgmt_txrx_err("Mgmt send fail for peer %pK psoc %pK pdev: %pK", 444 peer, psoc, pdev); 445 wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID); 446 desc->nbuf = NULL; 447 wlan_mgmt_txrx_desc_put(txrx_ctx, desc->desc_id); 448 return QDF_STATUS_E_FAILURE; 449 } 450 return QDF_STATUS_SUCCESS; 451 } 452 453 QDF_STATUS wlan_mgmt_txrx_beacon_frame_tx(struct wlan_objmgr_peer *peer, 454 qdf_nbuf_t buf, 455 enum wlan_umac_comp_id comp_id) 456 { 457 struct wlan_objmgr_vdev *vdev; 458 struct wlan_objmgr_psoc *psoc; 459 460 vdev = wlan_peer_get_vdev(peer); 461 if (!vdev) { 462 mgmt_txrx_err("vdev unavailable for peer %pK", peer); 463 return QDF_STATUS_E_NULL_VALUE; 464 } 465 466 psoc = wlan_vdev_get_psoc(vdev); 467 if (!psoc) { 468 mgmt_txrx_err("psoc unavailable for peer %pK", peer); 469 return QDF_STATUS_E_NULL_VALUE; 470 } 471 472 if (!psoc->soc_cb.tx_ops.mgmt_txrx_tx_ops.beacon_send) { 473 mgmt_txrx_err("mgmt txrx tx op to send beacon frame is NULL for psoc: %pK", 474 psoc); 475 return QDF_STATUS_E_FAILURE; 476 } 477 478 if (psoc->soc_cb.tx_ops.mgmt_txrx_tx_ops.beacon_send(vdev, buf)) { 479 mgmt_txrx_err("Beacon send fail for peer %pK psoc %pK", 480 peer, psoc); 481 return QDF_STATUS_E_FAILURE; 482 } 483 return QDF_STATUS_SUCCESS; 484 } 485 486 #ifdef WLAN_SUPPORT_FILS 487 QDF_STATUS 488 wlan_mgmt_txrx_fd_action_frame_tx(struct wlan_objmgr_vdev *vdev, 489 qdf_nbuf_t buf, 490 enum wlan_umac_comp_id comp_id) 491 { 492 struct wlan_objmgr_psoc *psoc; 493 uint32_t vdev_id; 494 495 if (!vdev) { 496 mgmt_txrx_err("Invalid vdev"); 497 return QDF_STATUS_E_NULL_VALUE; 498 } 499 vdev_id = wlan_vdev_get_id(vdev); 500 psoc = wlan_vdev_get_psoc(vdev); 501 if (!psoc) { 502 mgmt_txrx_err("psoc unavailable for vdev %d", vdev_id); 503 return QDF_STATUS_E_NULL_VALUE; 504 } 505 506 if (!psoc->soc_cb.tx_ops.mgmt_txrx_tx_ops.fd_action_frame_send) { 507 mgmt_txrx_err("mgmt txrx txop to send fd action frame is NULL"); 508 return QDF_STATUS_E_FAILURE; 509 } 510 511 if (psoc->soc_cb.tx_ops.mgmt_txrx_tx_ops.fd_action_frame_send( 512 vdev, buf)) { 513 mgmt_txrx_err("FD send fail for vdev %d", vdev_id); 514 return QDF_STATUS_E_FAILURE; 515 } 516 517 return QDF_STATUS_SUCCESS; 518 } 519 #endif /* WLAN_SUPPORT_FILS */ 520 521 /** 522 * wlan_mgmt_txrx_create_rx_handler() - creates rx handler node for umac comp. 523 * @mgmt_txrx_psoc_ctx: mgmt txrx context 524 * @mgmt_rx_cb: mgmt rx callback to be registered 525 * @comp_id: umac component id 526 * @frm_type: mgmt. frame for which cb to be registered. 527 * 528 * This function creates rx handler node for frame type and 529 * umac component passed in the func. 530 * 531 * Return: QDF_STATUS_SUCCESS - in case of success 532 */ 533 static QDF_STATUS wlan_mgmt_txrx_create_rx_handler( 534 struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx, 535 mgmt_frame_rx_callback mgmt_rx_cb, 536 enum wlan_umac_comp_id comp_id, 537 enum mgmt_frame_type frm_type) 538 { 539 struct mgmt_rx_handler *rx_handler; 540 541 rx_handler = qdf_mem_malloc(sizeof(*rx_handler)); 542 if (!rx_handler) 543 return QDF_STATUS_E_NOMEM; 544 545 rx_handler->comp_id = comp_id; 546 rx_handler->rx_cb = mgmt_rx_cb; 547 548 qdf_spin_lock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); 549 rx_handler->next = mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[frm_type]; 550 mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[frm_type] = rx_handler; 551 qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); 552 553 mgmt_txrx_debug("Callback registered for comp_id: %d, frm_type: %d", 554 comp_id, frm_type); 555 return QDF_STATUS_SUCCESS; 556 } 557 558 /** 559 * wlan_mgmt_txrx_delete_rx_handler() - deletes rx handler node for umac comp. 560 * @mgmt_txrx_psoc_ctx: mgmt txrx context 561 * @mgmt_rx_cb: mgmt rx callback to be deregistered 562 * @comp_id: umac component id 563 * @frm_type: mgmt. frame for which cb to be registered. 564 * 565 * This function deletes rx handler node for frame type and 566 * umac component passed in the func. 567 * 568 * Return: QDF_STATUS_SUCCESS - in case of success 569 */ 570 static QDF_STATUS wlan_mgmt_txrx_delete_rx_handler( 571 struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx, 572 mgmt_frame_rx_callback mgmt_rx_cb, 573 enum wlan_umac_comp_id comp_id, 574 enum mgmt_frame_type frm_type) 575 { 576 struct mgmt_rx_handler *rx_handler = NULL, *rx_handler_prev = NULL; 577 bool delete = false; 578 579 qdf_spin_lock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); 580 rx_handler = mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[frm_type]; 581 while (rx_handler) { 582 if (rx_handler->comp_id == comp_id && 583 rx_handler->rx_cb == mgmt_rx_cb) { 584 if (rx_handler_prev) 585 rx_handler_prev->next = 586 rx_handler->next; 587 else 588 mgmt_txrx_psoc_ctx->mgmt_rx_comp_cb[frm_type] = 589 rx_handler->next; 590 591 qdf_mem_free(rx_handler); 592 delete = true; 593 break; 594 } 595 596 rx_handler_prev = rx_handler; 597 rx_handler = rx_handler->next; 598 } 599 qdf_spin_unlock_bh(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); 600 601 if (!delete) { 602 mgmt_txrx_err("No callback registered for comp_id: %d, frm_type: %d", 603 comp_id, frm_type); 604 return QDF_STATUS_E_FAILURE; 605 } 606 607 mgmt_txrx_debug("Callback deregistered for comp_id: %d, frm_type: %d", 608 comp_id, frm_type); 609 return QDF_STATUS_SUCCESS; 610 } 611 612 QDF_STATUS wlan_mgmt_txrx_register_rx_cb( 613 struct wlan_objmgr_psoc *psoc, 614 enum wlan_umac_comp_id comp_id, 615 struct mgmt_txrx_mgmt_frame_cb_info *frm_cb_info, 616 uint8_t num_entries) 617 { 618 struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx; 619 QDF_STATUS status; 620 uint8_t i, j; 621 622 if (!psoc) { 623 mgmt_txrx_err("psoc context is NULL"); 624 return QDF_STATUS_E_INVAL; 625 } 626 627 if (comp_id >= WLAN_UMAC_MAX_COMPONENTS) { 628 mgmt_txrx_err("Invalid component id %d passed", comp_id); 629 return QDF_STATUS_E_INVAL; 630 } 631 632 if (!num_entries || num_entries >= MGMT_MAX_FRAME_TYPE) { 633 mgmt_txrx_err("Invalid value for num_entries: %d passed", 634 num_entries); 635 return QDF_STATUS_E_INVAL; 636 } 637 638 if (!frm_cb_info) { 639 mgmt_txrx_err("frame cb info pointer is NULL"); 640 return QDF_STATUS_E_INVAL; 641 } 642 643 mgmt_txrx_psoc_ctx = (struct mgmt_txrx_priv_psoc_context *) 644 wlan_objmgr_psoc_get_comp_private_obj(psoc, 645 WLAN_UMAC_COMP_MGMT_TXRX); 646 if (!mgmt_txrx_psoc_ctx) { 647 mgmt_txrx_err("mgmt txrx context is NULL"); 648 return QDF_STATUS_E_FAILURE; 649 } 650 651 for (i = 0; i < num_entries; i++) { 652 status = wlan_mgmt_txrx_create_rx_handler(mgmt_txrx_psoc_ctx, 653 frm_cb_info[i].mgmt_rx_cb, comp_id, 654 frm_cb_info[i].frm_type); 655 if (status != QDF_STATUS_SUCCESS) { 656 for (j = 0; j < i; j++) { 657 wlan_mgmt_txrx_delete_rx_handler( 658 mgmt_txrx_psoc_ctx, 659 frm_cb_info[j].mgmt_rx_cb, 660 comp_id, frm_cb_info[j].frm_type); 661 } 662 return status; 663 } 664 } 665 666 return QDF_STATUS_SUCCESS; 667 } 668 669 QDF_STATUS wlan_mgmt_txrx_deregister_rx_cb( 670 struct wlan_objmgr_psoc *psoc, 671 enum wlan_umac_comp_id comp_id, 672 struct mgmt_txrx_mgmt_frame_cb_info *frm_cb_info, 673 uint8_t num_entries) 674 { 675 struct mgmt_txrx_priv_psoc_context *mgmt_txrx_psoc_ctx; 676 uint8_t i; 677 678 if (!psoc) { 679 mgmt_txrx_err("psoc context is NULL"); 680 return QDF_STATUS_E_INVAL; 681 } 682 683 if (comp_id >= WLAN_UMAC_MAX_COMPONENTS) { 684 mgmt_txrx_err("Invalid component id %d passed", comp_id); 685 return QDF_STATUS_E_INVAL; 686 } 687 688 if (!num_entries || num_entries >= MGMT_MAX_FRAME_TYPE) { 689 mgmt_txrx_err("Invalid value for num_entries: %d passed", 690 num_entries); 691 return QDF_STATUS_E_INVAL; 692 } 693 694 if (!frm_cb_info) { 695 mgmt_txrx_err("frame cb info pointer is NULL"); 696 return QDF_STATUS_E_INVAL; 697 } 698 699 mgmt_txrx_psoc_ctx = (struct mgmt_txrx_priv_psoc_context *) 700 wlan_objmgr_psoc_get_comp_private_obj(psoc, 701 WLAN_UMAC_COMP_MGMT_TXRX); 702 if (!mgmt_txrx_psoc_ctx) { 703 mgmt_txrx_err("mgmt txrx context is NULL"); 704 return QDF_STATUS_E_FAILURE; 705 } 706 707 for (i = 0; i < num_entries; i++) { 708 wlan_mgmt_txrx_delete_rx_handler(mgmt_txrx_psoc_ctx, 709 frm_cb_info[i].mgmt_rx_cb, comp_id, 710 frm_cb_info[i].frm_type); 711 } 712 713 return QDF_STATUS_SUCCESS; 714 } 715 716 QDF_STATUS wlan_mgmt_txrx_psoc_open(struct wlan_objmgr_psoc *psoc) 717 { 718 return QDF_STATUS_SUCCESS; 719 } 720 721 QDF_STATUS wlan_mgmt_txrx_psoc_close(struct wlan_objmgr_psoc *psoc) 722 { 723 return QDF_STATUS_SUCCESS; 724 } 725 726 QDF_STATUS wlan_mgmt_txrx_pdev_open(struct wlan_objmgr_pdev *pdev) 727 { 728 return QDF_STATUS_SUCCESS; 729 } 730 731 QDF_STATUS wlan_mgmt_txrx_pdev_close(struct wlan_objmgr_pdev *pdev) 732 { 733 struct wlan_objmgr_psoc *psoc; 734 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx; 735 struct mgmt_txrx_desc_elem_t *mgmt_desc; 736 uint32_t pool_size; 737 uint32_t index; 738 739 if (!pdev) { 740 mgmt_txrx_err("pdev context is NULL"); 741 return QDF_STATUS_E_INVAL; 742 } 743 744 psoc = wlan_pdev_get_psoc(pdev); 745 if (!psoc) { 746 mgmt_txrx_err("psoc unavailable for pdev %pK", pdev); 747 return QDF_STATUS_E_NULL_VALUE; 748 } 749 750 mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *) 751 wlan_objmgr_pdev_get_comp_private_obj(pdev, 752 WLAN_UMAC_COMP_MGMT_TXRX); 753 754 if (!mgmt_txrx_pdev_ctx) { 755 mgmt_txrx_err("mgmt txrx context is NULL"); 756 return QDF_STATUS_E_FAILURE; 757 } 758 759 pool_size = mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list.max_size; 760 if (!pool_size) { 761 mgmt_txrx_err("pool size is 0"); 762 return QDF_STATUS_E_FAILURE; 763 } 764 765 for (index = 0; index < pool_size; index++) { 766 if (mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[index].in_use) { 767 mgmt_txrx_debug( 768 "mgmt descriptor with desc id: %d not in freelist", 769 index); 770 mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[index]; 771 if (psoc->soc_cb.tx_ops.mgmt_txrx_tx_ops. 772 tx_drain_nbuf_op) 773 psoc->soc_cb.tx_ops.mgmt_txrx_tx_ops. 774 tx_drain_nbuf_op(pdev, mgmt_desc->nbuf); 775 qdf_nbuf_free(mgmt_desc->nbuf); 776 wlan_objmgr_peer_release_ref(mgmt_desc->peer, 777 WLAN_MGMT_NB_ID); 778 wlan_mgmt_txrx_desc_put(mgmt_txrx_pdev_ctx, index); 779 } 780 } 781 782 return QDF_STATUS_SUCCESS; 783 } 784 785 QDF_STATUS wlan_mgmt_txrx_vdev_drain(struct wlan_objmgr_vdev *vdev, 786 mgmt_frame_fill_peer_cb mgmt_fill_peer_cb, 787 void *status) 788 { 789 struct wlan_objmgr_pdev *pdev; 790 struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx; 791 struct mgmt_txrx_desc_elem_t *mgmt_desc; 792 struct wlan_objmgr_peer *peer; 793 struct wlan_objmgr_vdev *peer_vdev; 794 uint32_t pool_size; 795 int i; 796 797 if (!vdev) { 798 mgmt_txrx_err("vdev context is NULL"); 799 return QDF_STATUS_E_INVAL; 800 } 801 802 pdev = wlan_vdev_get_pdev(vdev); 803 if (!pdev) { 804 mgmt_txrx_err("pdev context is NULL"); 805 return QDF_STATUS_E_INVAL; 806 } 807 mgmt_txrx_pdev_ctx = (struct mgmt_txrx_priv_pdev_context *) 808 wlan_objmgr_pdev_get_comp_private_obj(pdev, 809 WLAN_UMAC_COMP_MGMT_TXRX); 810 if (!mgmt_txrx_pdev_ctx) { 811 mgmt_txrx_err("mgmt txrx context is NULL"); 812 return QDF_STATUS_E_FAILURE; 813 } 814 815 pool_size = mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list.max_size; 816 if (!pool_size) { 817 mgmt_txrx_err("pool size is 0"); 818 return QDF_STATUS_E_FAILURE; 819 } 820 821 for (i = 0; i < pool_size; i++) { 822 if (mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i].in_use) { 823 mgmt_desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i]; 824 peer = mgmt_txrx_get_peer(pdev, mgmt_desc->desc_id); 825 if (peer) { 826 peer_vdev = wlan_peer_get_vdev(peer); 827 if (peer_vdev == vdev) { 828 if (mgmt_fill_peer_cb) 829 mgmt_fill_peer_cb(peer, mgmt_desc->nbuf); 830 mgmt_txrx_tx_completion_handler(pdev, 831 mgmt_desc->desc_id, 0, status); 832 } 833 } 834 } 835 } 836 837 return QDF_STATUS_SUCCESS; 838 } 839