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