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