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