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