1 /* 2 * Copyright (c) 2019 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_vdev_mgr_tgt_if_tx_api.c 21 * 22 * This file provides definitions for mlme tgt_if APIs, which will 23 * further call target_if/mlme component using LMAC MLME txops 24 */ 25 #include <wlan_vdev_mgr_tgt_if_tx_api.h> 26 #include <target_if_vdev_mgr_tx_ops.h> 27 #include "include/wlan_vdev_mlme.h" 28 #include <wlan_mlme_dbg.h> 29 #include <cdp_txrx_cmn_struct.h> 30 #include <cdp_txrx_cmn.h> 31 #include <wlan_lmac_if_api.h> 32 #include <wlan_utility.h> 33 #include <cdp_txrx_ctrl.h> 34 #include <wlan_vdev_mlme_api.h> 35 #include <wlan_dfs_utils_api.h> 36 #include <wlan_vdev_mgr_utils_api.h> 37 #include <wlan_vdev_mgr_ucfg_api.h> 38 #include <wlan_vdev_mlme_main.h> 39 40 static inline struct wlan_lmac_if_mlme_tx_ops 41 *wlan_vdev_mlme_get_lmac_txops(struct wlan_objmgr_vdev *vdev) 42 { 43 struct wlan_objmgr_psoc *psoc; 44 45 psoc = wlan_vdev_get_psoc(vdev); 46 47 return target_if_vdev_mgr_get_tx_ops(psoc); 48 } 49 50 QDF_STATUS tgt_vdev_mgr_create_send( 51 struct vdev_mlme_obj *mlme_obj, 52 struct vdev_create_params *param) 53 { 54 QDF_STATUS status = QDF_STATUS_E_FAILURE; 55 struct wlan_lmac_if_mlme_tx_ops *txops; 56 struct wlan_objmgr_psoc *psoc; 57 struct wlan_objmgr_pdev *pdev; 58 struct wlan_objmgr_vdev *vdev; 59 ol_txrx_soc_handle soc_txrx_handle; 60 struct cdp_pdev *pdev_txrx_handle; 61 struct cdp_vdev *vdev_txrx_handle; 62 enum wlan_op_mode cdp_txrx_opmode; 63 uint32_t vdev_id; 64 uint8_t *vdev_addr; 65 struct vdev_response_timer *vdev_rsp; 66 67 if (!param) { 68 mlme_err("Invalid input"); 69 return QDF_STATUS_E_INVAL; 70 } 71 72 vdev = mlme_obj->vdev; 73 vdev_id = wlan_vdev_get_id(vdev); 74 txops = wlan_vdev_mlme_get_lmac_txops(vdev); 75 if (!txops || !txops->vdev_create_send || 76 !txops->vdev_mgr_rsp_timer_init) { 77 mlme_err("VDEV_%d: No Tx Ops", vdev_id); 78 return QDF_STATUS_E_INVAL; 79 } 80 81 status = txops->vdev_create_send(vdev, param); 82 if (QDF_IS_STATUS_SUCCESS(status)) { 83 vdev_rsp = &mlme_obj->vdev_rt; 84 txops->vdev_mgr_rsp_timer_init(vdev, &vdev_rsp->rsp_timer); 85 } else { 86 mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); 87 return status; 88 } 89 90 cdp_txrx_opmode = wlan_util_vdev_get_cdp_txrx_opmode(vdev); 91 vdev_addr = wlan_vdev_mlme_get_macaddr(vdev); 92 psoc = wlan_vdev_get_psoc(vdev); 93 pdev = wlan_vdev_get_pdev(vdev); 94 soc_txrx_handle = wlan_psoc_get_dp_handle(psoc); 95 pdev_txrx_handle = wlan_pdev_get_dp_handle(pdev); 96 if (!soc_txrx_handle || !pdev_txrx_handle) 97 return QDF_STATUS_E_FAILURE; 98 99 vdev_txrx_handle = cdp_vdev_attach(soc_txrx_handle, 100 pdev_txrx_handle, 101 vdev_addr, vdev_id, 102 cdp_txrx_opmode); 103 if (!vdev_txrx_handle) 104 return QDF_STATUS_E_FAILURE; 105 106 wlan_vdev_set_dp_handle(vdev, vdev_txrx_handle); 107 108 return status; 109 } 110 111 QDF_STATUS tgt_vdev_mgr_create_complete(struct vdev_mlme_obj *vdev_mlme) 112 { 113 struct wlan_objmgr_vdev *vdev; 114 enum QDF_OPMODE opmode; 115 struct vdev_set_params param = {0}; 116 struct wlan_lmac_if_mlme_tx_ops *txops; 117 struct vdev_mlme_inactivity_params *inactivity; 118 uint8_t vdev_id; 119 QDF_STATUS status = QDF_STATUS_SUCCESS; 120 121 vdev = vdev_mlme->vdev; 122 vdev_id = wlan_vdev_get_id(vdev); 123 txops = wlan_vdev_mlme_get_lmac_txops(vdev); 124 if (!txops || !txops->vdev_set_param_send) { 125 mlme_err("VDEV_%d: No Tx Ops", vdev_id); 126 return QDF_STATUS_E_INVAL; 127 } 128 129 opmode = wlan_vdev_mlme_get_opmode(vdev); 130 inactivity = &vdev_mlme->mgmt.inactivity_params; 131 if (opmode == QDF_SAP_MODE) { 132 param.vdev_id = wlan_vdev_get_id(vdev); 133 134 param.param_value = vdev_mlme->mgmt.rate_info.bcn_tx_rate; 135 param.param_id = WLAN_MLME_CFG_BCN_TX_RATE; 136 status = txops->vdev_set_param_send(vdev, ¶m); 137 if (QDF_IS_STATUS_ERROR(status)) 138 mlme_err("VDEV_%d: Failed to set beacon rate!", 139 vdev_id); 140 } 141 142 param.param_value = 143 inactivity->keepalive_min_idle_inactive_time_secs; 144 param.param_id = WLAN_MLME_CFG_MIN_IDLE_INACTIVE_TIME; 145 status = txops->vdev_set_param_send(vdev, ¶m); 146 if (QDF_IS_STATUS_ERROR(status)) 147 mlme_err("VDEV_%d: Failed to set min idle inactive time!", 148 vdev_id); 149 150 param.param_value = 151 inactivity->keepalive_max_idle_inactive_time_secs; 152 param.param_id = WLAN_MLME_CFG_MAX_IDLE_INACTIVE_TIME; 153 status = txops->vdev_set_param_send(vdev, ¶m); 154 if (QDF_IS_STATUS_ERROR(status)) 155 mlme_err("VDEV_%d: Failed to set max idle inactive time!", 156 vdev_id); 157 158 param.param_value = 159 inactivity->keepalive_max_unresponsive_time_secs; 160 param.param_id = WLAN_MLME_CFG_MAX_UNRESPONSIVE_INACTIVE_TIME; 161 status = txops->vdev_set_param_send(vdev, ¶m); 162 if (QDF_IS_STATUS_ERROR(status)) 163 mlme_err("VDEV_%d: Failed to set max unresponse inactive time!", 164 vdev_id); 165 166 return status; 167 } 168 169 QDF_STATUS tgt_vdev_mgr_start_send( 170 struct vdev_mlme_obj *mlme_obj, 171 struct vdev_start_params *param) 172 { 173 QDF_STATUS status; 174 struct wlan_lmac_if_mlme_tx_ops *txops; 175 struct wlan_objmgr_vdev *vdev; 176 uint8_t vdev_id; 177 178 if (!param) { 179 mlme_err("Invalid input"); 180 return QDF_STATUS_E_INVAL; 181 } 182 183 vdev = mlme_obj->vdev; 184 vdev_id = wlan_vdev_get_id(vdev); 185 txops = wlan_vdev_mlme_get_lmac_txops(vdev); 186 if (!txops || !txops->vdev_start_send) { 187 mlme_err("VDEV_%d: No Tx Ops", vdev_id); 188 return QDF_STATUS_E_INVAL; 189 } 190 191 status = txops->vdev_start_send(vdev, param); 192 if (QDF_IS_STATUS_ERROR(status)) 193 mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); 194 195 return status; 196 } 197 198 QDF_STATUS tgt_vdev_mgr_delete_send( 199 struct vdev_mlme_obj *mlme_obj, 200 struct vdev_delete_params *param) 201 { 202 QDF_STATUS status; 203 struct wlan_lmac_if_mlme_tx_ops *txops; 204 struct wlan_objmgr_vdev *vdev; 205 struct wlan_objmgr_psoc *psoc; 206 ol_txrx_soc_handle soc_txrx_handle; 207 struct cdp_vdev *vdev_txrx_handle; 208 uint8_t vdev_id; 209 210 if (!param) { 211 mlme_err("Invalid input"); 212 return QDF_STATUS_E_INVAL; 213 } 214 215 vdev = mlme_obj->vdev; 216 vdev_id = wlan_vdev_get_id(vdev); 217 txops = wlan_vdev_mlme_get_lmac_txops(vdev); 218 if (!txops || !txops->vdev_delete_send) { 219 mlme_err("VDEV_%d: No Tx Ops", vdev_id); 220 return QDF_STATUS_E_INVAL; 221 } 222 223 psoc = wlan_vdev_get_psoc(vdev); 224 soc_txrx_handle = wlan_psoc_get_dp_handle(psoc); 225 vdev_txrx_handle = wlan_vdev_get_dp_handle(vdev); 226 if (soc_txrx_handle && vdev_txrx_handle) { 227 wlan_vdev_set_dp_handle(vdev, NULL); 228 cdp_vdev_detach(soc_txrx_handle, vdev_txrx_handle, 229 NULL, NULL); 230 } 231 232 status = txops->vdev_delete_send(vdev, param); 233 if (QDF_IS_STATUS_ERROR(status)) 234 mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); 235 236 return status; 237 } 238 239 QDF_STATUS tgt_vdev_mgr_peer_flush_tids_send( 240 struct vdev_mlme_obj *mlme_obj, 241 struct peer_flush_params *param) 242 { 243 QDF_STATUS status; 244 struct wlan_lmac_if_mlme_tx_ops *txops; 245 struct wlan_objmgr_vdev *vdev; 246 uint8_t vdev_id; 247 248 if (!param) { 249 mlme_err("Invalid input"); 250 return QDF_STATUS_E_INVAL; 251 } 252 253 vdev = mlme_obj->vdev; 254 vdev_id = wlan_vdev_get_id(vdev); 255 txops = wlan_vdev_mlme_get_lmac_txops(vdev); 256 if (!txops || !txops->peer_flush_tids_send) { 257 mlme_err("VDEV_%d: No Tx Ops", vdev_id); 258 return QDF_STATUS_E_INVAL; 259 } 260 261 status = txops->peer_flush_tids_send(vdev, param); 262 if (QDF_IS_STATUS_ERROR(status)) 263 mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); 264 265 return QDF_STATUS_SUCCESS; 266 } 267 268 QDF_STATUS tgt_vdev_mgr_stop_send( 269 struct vdev_mlme_obj *mlme_obj, 270 struct vdev_stop_params *param) 271 { 272 QDF_STATUS status; 273 struct wlan_lmac_if_mlme_tx_ops *txops; 274 struct wlan_objmgr_vdev *vdev; 275 uint8_t vdev_id; 276 277 if (!param) { 278 mlme_err("Invalid input"); 279 return QDF_STATUS_E_INVAL; 280 } 281 282 vdev = mlme_obj->vdev; 283 vdev_id = wlan_vdev_get_id(vdev); 284 txops = wlan_vdev_mlme_get_lmac_txops(vdev); 285 if (!txops || !txops->vdev_stop_send) { 286 mlme_err("VDEV_%d: No Tx Ops", vdev_id); 287 return QDF_STATUS_E_INVAL; 288 } 289 290 status = txops->vdev_stop_send(vdev, param); 291 if (QDF_IS_STATUS_ERROR(status)) 292 mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); 293 294 return status; 295 } 296 297 QDF_STATUS tgt_vdev_mgr_beacon_stop(struct vdev_mlme_obj *mlme_obj) 298 { 299 return QDF_STATUS_SUCCESS; 300 } 301 302 QDF_STATUS tgt_vdev_mgr_beacon_free(struct vdev_mlme_obj *mlme_obj) 303 { 304 return QDF_STATUS_SUCCESS; 305 } 306 307 QDF_STATUS tgt_vdev_mgr_up_send( 308 struct vdev_mlme_obj *mlme_obj, 309 struct vdev_up_params *param) 310 { 311 QDF_STATUS status; 312 struct wlan_lmac_if_mlme_tx_ops *txops; 313 ol_txrx_soc_handle soc_txrx_handle; 314 struct cdp_vdev *vdev_txrx_handle; 315 struct wlan_objmgr_psoc *psoc; 316 struct wlan_objmgr_vdev *vdev; 317 uint8_t vdev_id; 318 319 if (!param) { 320 mlme_err("Invalid input"); 321 return QDF_STATUS_E_INVAL; 322 } 323 324 vdev = mlme_obj->vdev; 325 vdev_id = wlan_vdev_get_id(vdev); 326 txops = wlan_vdev_mlme_get_lmac_txops(vdev); 327 if (!txops || !txops->vdev_up_send) { 328 mlme_err("VDEV_%d: No Tx Ops", vdev_id); 329 return QDF_STATUS_E_INVAL; 330 } 331 332 /* cdp set rx and tx decap type */ 333 psoc = wlan_vdev_get_psoc(vdev); 334 soc_txrx_handle = wlan_psoc_get_dp_handle(psoc); 335 vdev_txrx_handle = wlan_vdev_get_dp_handle(vdev); 336 if (!soc_txrx_handle || !vdev_txrx_handle) 337 return QDF_STATUS_E_INVAL; 338 339 cdp_set_vdev_rx_decap_type(soc_txrx_handle, 340 (struct cdp_vdev *)vdev_txrx_handle, 341 mlme_obj->mgmt.generic.rx_decap_type); 342 cdp_set_tx_encap_type(soc_txrx_handle, 343 (struct cdp_vdev *)vdev_txrx_handle, 344 mlme_obj->mgmt.generic.tx_decap_type); 345 346 status = txops->vdev_up_send(vdev, param); 347 if (QDF_IS_STATUS_ERROR(status)) 348 mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); 349 350 return status; 351 } 352 353 QDF_STATUS tgt_vdev_mgr_down_send( 354 struct vdev_mlme_obj *mlme_obj, 355 struct vdev_down_params *param) 356 { 357 QDF_STATUS status; 358 struct wlan_lmac_if_mlme_tx_ops *txops; 359 struct wlan_objmgr_pdev *pdev; 360 struct wlan_objmgr_vdev *vdev; 361 enum QDF_OPMODE opmode; 362 uint8_t vdev_id; 363 364 if (!param) { 365 mlme_err("Invalid input"); 366 return QDF_STATUS_E_INVAL; 367 } 368 369 vdev = mlme_obj->vdev; 370 vdev_id = wlan_vdev_get_id(vdev); 371 txops = wlan_vdev_mlme_get_lmac_txops(vdev); 372 if (!txops || !txops->vdev_down_send) { 373 mlme_err("VDEV_%d: No Tx Ops", vdev_id); 374 return QDF_STATUS_E_INVAL; 375 } 376 377 pdev = wlan_vdev_get_pdev(vdev); 378 if (!pdev) { 379 mlme_err("PDEV is NULL"); 380 return QDF_STATUS_E_INVAL; 381 } 382 383 opmode = wlan_vdev_mlme_get_opmode(vdev); 384 if (wlan_util_is_vdev_active(pdev, WLAN_VDEV_TARGET_IF_ID) == 385 QDF_STATUS_SUCCESS) { 386 387 if (opmode == QDF_SAP_MODE) 388 utils_dfs_cancel_precac_timer(pdev); 389 } 390 391 status = txops->vdev_down_send(vdev, param); 392 if (QDF_IS_STATUS_ERROR(status)) 393 mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); 394 395 return status; 396 } 397 398 QDF_STATUS tgt_vdev_mgr_set_neighbour_rx_cmd_send( 399 struct vdev_mlme_obj *mlme_obj, 400 struct set_neighbour_rx_params *param) 401 { 402 return QDF_STATUS_SUCCESS; 403 } 404 405 QDF_STATUS tgt_vdev_mgr_nac_rssi_send( 406 struct vdev_mlme_obj *mlme_obj, 407 struct vdev_scan_nac_rssi_params *param) 408 { 409 return QDF_STATUS_SUCCESS; 410 } 411 412 QDF_STATUS tgt_vdev_mgr_sifs_trigger_send( 413 struct vdev_mlme_obj *mlme_obj, 414 struct sifs_trigger_param *param) 415 { 416 QDF_STATUS status = QDF_STATUS_E_FAILURE; 417 struct wlan_lmac_if_mlme_tx_ops *txops; 418 struct wlan_objmgr_vdev *vdev; 419 uint8_t vdev_id; 420 421 if (!param) { 422 mlme_err("Invalid input"); 423 return QDF_STATUS_E_INVAL; 424 } 425 426 vdev = mlme_obj->vdev; 427 vdev_id = wlan_vdev_get_id(vdev); 428 txops = wlan_vdev_mlme_get_lmac_txops(vdev); 429 if (!txops || !txops->vdev_sifs_trigger_send) { 430 mlme_err("VDEV_%d: No Tx Ops", vdev_id); 431 return QDF_STATUS_E_INVAL; 432 } 433 434 status = txops->vdev_sifs_trigger_send(vdev, param); 435 if (QDF_IS_STATUS_ERROR(status)) 436 mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); 437 438 return status; 439 } 440 441 QDF_STATUS tgt_vdev_mgr_set_custom_aggr_size_send( 442 struct vdev_mlme_obj *mlme_obj, 443 struct set_custom_aggr_size_params *param) 444 { 445 QDF_STATUS status; 446 struct wlan_lmac_if_mlme_tx_ops *txops; 447 struct wlan_objmgr_vdev *vdev; 448 uint8_t vdev_id; 449 450 if (!param) { 451 mlme_err("Invalid input"); 452 return QDF_STATUS_E_INVAL; 453 } 454 455 vdev = mlme_obj->vdev; 456 vdev_id = wlan_vdev_get_id(vdev); 457 txops = wlan_vdev_mlme_get_lmac_txops(vdev); 458 if (!txops || !txops->vdev_set_custom_aggr_size_cmd_send) { 459 mlme_err("VDEV_%d: No Tx Ops", vdev_id); 460 return QDF_STATUS_E_INVAL; 461 } 462 463 status = txops->vdev_set_custom_aggr_size_cmd_send(vdev, param); 464 if (QDF_IS_STATUS_ERROR(status)) 465 mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); 466 467 return status; 468 } 469 470 QDF_STATUS tgt_vdev_mgr_config_ratemask_cmd_send( 471 struct vdev_mlme_obj *mlme_obj, 472 struct config_ratemask_params *param) 473 { 474 QDF_STATUS status; 475 struct wlan_lmac_if_mlme_tx_ops *txops; 476 struct wlan_objmgr_vdev *vdev; 477 uint8_t vdev_id; 478 479 vdev = mlme_obj->vdev; 480 vdev_id = wlan_vdev_get_id(vdev); 481 txops = wlan_vdev_mlme_get_lmac_txops(vdev); 482 if (!txops || !txops->vdev_config_ratemask_cmd_send) { 483 mlme_err("VDEV_%d: No Tx Ops", vdev_id); 484 return QDF_STATUS_E_INVAL; 485 } 486 487 status = txops->vdev_config_ratemask_cmd_send(vdev, param); 488 if (QDF_IS_STATUS_ERROR(status)) 489 mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); 490 491 return status; 492 } 493 494 QDF_STATUS tgt_vdev_mgr_beacon_cmd_send( 495 struct vdev_mlme_obj *mlme_obj, 496 struct beacon_params *param) 497 { 498 return QDF_STATUS_SUCCESS; 499 } 500 501 QDF_STATUS tgt_vdev_mgr_beacon_tmpl_send( 502 struct vdev_mlme_obj *mlme_obj, 503 struct beacon_tmpl_params *param) 504 { 505 return QDF_STATUS_SUCCESS; 506 } 507 508 QDF_STATUS tgt_vdev_mgr_multiple_vdev_restart_send( 509 struct wlan_objmgr_pdev *pdev, 510 struct multiple_vdev_restart_params *param) 511 { 512 QDF_STATUS status = QDF_STATUS_SUCCESS; 513 struct wlan_lmac_if_mlme_tx_ops *txops; 514 struct wlan_objmgr_vdev *vdev; 515 516 if (!param) { 517 mlme_err("Invalid input"); 518 return QDF_STATUS_E_INVAL; 519 } 520 521 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, 522 param->vdev_ids[0], 523 WLAN_VDEV_TARGET_IF_ID); 524 if (vdev) { 525 txops = wlan_vdev_mlme_get_lmac_txops(vdev); 526 if (!txops || !txops->multiple_vdev_restart_req_cmd) { 527 mlme_err("VDEV_%d: No Tx Ops", wlan_vdev_get_id(vdev)); 528 wlan_objmgr_vdev_release_ref(vdev, 529 WLAN_VDEV_TARGET_IF_ID); 530 return QDF_STATUS_E_INVAL; 531 } 532 533 status = txops->multiple_vdev_restart_req_cmd(pdev, param); 534 if (QDF_IS_STATUS_ERROR(status)) 535 mlme_err("Tx Ops Error: %d", status); 536 537 wlan_objmgr_vdev_release_ref(vdev, WLAN_VDEV_TARGET_IF_ID); 538 } 539 540 return status; 541 } 542 543 QDF_STATUS tgt_vdev_mgr_set_param_send( 544 struct vdev_mlme_obj *mlme_obj, 545 struct vdev_set_params *param) 546 { 547 QDF_STATUS status; 548 struct wlan_lmac_if_mlme_tx_ops *txops; 549 struct wlan_objmgr_vdev *vdev; 550 uint8_t vdev_id; 551 552 if (!param) { 553 mlme_err("Invalid input"); 554 return QDF_STATUS_E_INVAL; 555 } 556 557 vdev = mlme_obj->vdev; 558 vdev_id = wlan_vdev_get_id(vdev); 559 txops = wlan_vdev_mlme_get_lmac_txops(vdev); 560 if (!txops || !txops->vdev_set_param_send) { 561 mlme_err("VDEV_%d: No Tx Ops", vdev_id); 562 return QDF_STATUS_E_INVAL; 563 } 564 565 status = txops->vdev_set_param_send(vdev, param); 566 if (QDF_IS_STATUS_ERROR(status)) 567 mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); 568 569 return status; 570 } 571 572 QDF_STATUS tgt_vdev_mgr_sta_ps_param_send( 573 struct vdev_mlme_obj *mlme_obj, 574 struct sta_ps_params *param) 575 { 576 QDF_STATUS status; 577 struct wlan_lmac_if_mlme_tx_ops *txops; 578 struct wlan_objmgr_vdev *vdev; 579 uint8_t vdev_id; 580 581 if (!param) { 582 mlme_err("Invalid input"); 583 return QDF_STATUS_E_INVAL; 584 } 585 586 vdev = mlme_obj->vdev; 587 vdev_id = wlan_vdev_get_id(vdev); 588 txops = wlan_vdev_mlme_get_lmac_txops(vdev); 589 if (!txops || !txops->vdev_sta_ps_param_send) { 590 mlme_err("VDEV_%d: No Tx Ops", vdev_id); 591 return QDF_STATUS_E_INVAL; 592 } 593 594 status = txops->vdev_sta_ps_param_send(vdev, param); 595 if (QDF_IS_STATUS_ERROR(status)) 596 mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); 597 598 return status; 599 } 600