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