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