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