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: vdev_mgr_ops.c 21 * 22 * This file provide API definitions for filling data structures 23 * and sending vdev mgmt commands to target_if/mlme 24 */ 25 #include "vdev_mgr_ops.h" 26 #include <wlan_objmgr_vdev_obj.h> 27 #include <wlan_vdev_mlme_api.h> 28 #include <wlan_mlme_dbg.h> 29 #include <wlan_vdev_mgr_tgt_if_tx_api.h> 30 #include <target_if.h> 31 #include <init_deinit_lmac.h> 32 #include <wlan_lmac_if_api.h> 33 #include <wlan_reg_services_api.h> 34 #include <wlan_dfs_tgt_api.h> 35 #include <wlan_dfs_utils_api.h> 36 #include <wlan_vdev_mgr_ucfg_api.h> 37 #include <qdf_module.h> 38 39 static QDF_STATUS vdev_mgr_create_param_update( 40 struct vdev_mlme_obj *mlme_obj, 41 struct vdev_create_params *param) 42 { 43 struct wlan_objmgr_pdev *pdev; 44 struct wlan_objmgr_vdev *vdev; 45 struct vdev_mlme_mbss_11ax *mbss; 46 47 vdev = mlme_obj->vdev; 48 if (!vdev) { 49 mlme_err("VDEV is NULL"); 50 return QDF_STATUS_E_INVAL; 51 } 52 53 pdev = wlan_vdev_get_pdev(vdev); 54 if (!pdev) { 55 mlme_err("PDEV is NULL"); 56 return QDF_STATUS_E_INVAL; 57 } 58 59 mbss = &mlme_obj->mgmt.mbss_11ax; 60 param->pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 61 param->vdev_id = wlan_vdev_get_id(vdev); 62 param->nss_2g = mlme_obj->proto.generic.nss_2g; 63 param->nss_5g = mlme_obj->proto.generic.nss_5g; 64 param->type = mlme_obj->mgmt.generic.type; 65 param->subtype = mlme_obj->mgmt.generic.subtype; 66 param->mbssid_flags = mbss->mbssid_flags; 67 param->vdevid_trans = mbss->vdevid_trans; 68 69 return QDF_STATUS_SUCCESS; 70 } 71 72 QDF_STATUS vdev_mgr_create_send(struct vdev_mlme_obj *mlme_obj) 73 { 74 QDF_STATUS status; 75 struct vdev_create_params param = {0}; 76 77 if (!mlme_obj) { 78 mlme_err("VDEV_MLME is NULL"); 79 return QDF_STATUS_E_INVAL; 80 } 81 82 status = vdev_mgr_create_param_update(mlme_obj, ¶m); 83 if (QDF_IS_STATUS_ERROR(status)) { 84 mlme_err("Param Update Error: %d", status); 85 return status; 86 } 87 88 status = tgt_vdev_mgr_create_send(mlme_obj, ¶m); 89 90 return status; 91 } 92 93 static QDF_STATUS vdev_mgr_start_param_update( 94 struct vdev_mlme_obj *mlme_obj, 95 struct vdev_start_params *param) 96 { 97 struct wlan_channel *des_chan; 98 uint32_t dfs_reg; 99 bool set_agile = false, dfs_set_cfreq2 = false; 100 struct wlan_objmgr_vdev *vdev; 101 struct wlan_objmgr_pdev *pdev; 102 enum QDF_OPMODE op_mode; 103 104 vdev = mlme_obj->vdev; 105 if (!vdev) { 106 mlme_err("VDEV is NULL"); 107 return QDF_STATUS_E_INVAL; 108 } 109 110 pdev = wlan_vdev_get_pdev(vdev); 111 if (!pdev) { 112 mlme_err("PDEV is NULL"); 113 return QDF_STATUS_E_INVAL; 114 } 115 116 if (wlan_objmgr_pdev_try_get_ref(pdev, WLAN_MLME_SB_ID) != 117 QDF_STATUS_SUCCESS) { 118 mlme_err("Failed to get pdev reference"); 119 return QDF_STATUS_E_FAILURE; 120 } 121 122 des_chan = wlan_vdev_mlme_get_des_chan(vdev); 123 param->vdev_id = wlan_vdev_get_id(vdev); 124 125 op_mode = wlan_vdev_mlme_get_opmode(vdev); 126 if ((op_mode == QDF_SAP_MODE || op_mode == QDF_P2P_GO_MODE) && 127 (WLAN_REG_IS_5GHZ_CH_FREQ(des_chan->ch_freq) || 128 WLAN_REG_IS_49GHZ_FREQ(des_chan->ch_freq) || 129 WLAN_REG_IS_6GHZ_CHAN_FREQ(des_chan->ch_freq))) 130 tgt_dfs_set_current_channel_for_freq(pdev, des_chan->ch_freq, 131 des_chan->ch_flags, 132 des_chan->ch_flagext, 133 des_chan->ch_ieee, 134 des_chan->ch_freq_seg1, 135 des_chan->ch_freq_seg2, 136 des_chan->ch_cfreq1, 137 des_chan->ch_cfreq2); 138 139 param->beacon_interval = mlme_obj->proto.generic.beacon_interval; 140 param->dtim_period = mlme_obj->proto.generic.dtim_period; 141 param->disable_hw_ack = mlme_obj->mgmt.generic.disable_hw_ack; 142 param->preferred_rx_streams = 143 mlme_obj->mgmt.chainmask_info.num_rx_chain; 144 param->preferred_tx_streams = 145 mlme_obj->mgmt.chainmask_info.num_tx_chain; 146 147 wlan_reg_get_dfs_region(pdev, &dfs_reg); 148 param->regdomain = dfs_reg; 149 param->he_ops = mlme_obj->proto.he_ops_info.he_ops; 150 151 param->channel.chan_id = des_chan->ch_ieee; 152 param->channel.pwr = mlme_obj->mgmt.generic.tx_power; 153 param->channel.mhz = des_chan->ch_freq; 154 param->channel.half_rate = mlme_obj->mgmt.rate_info.half_rate; 155 param->channel.quarter_rate = mlme_obj->mgmt.rate_info.quarter_rate; 156 param->channel.dfs_set = wlan_reg_is_dfs_for_freq(pdev, 157 des_chan->ch_freq); 158 param->channel.dfs_set_cfreq2 = utils_is_dfs_cfreq2_ch(pdev); 159 param->channel.is_chan_passive = 160 utils_is_dfs_chan_for_freq(pdev, param->channel.mhz); 161 param->channel.allow_ht = mlme_obj->proto.ht_info.allow_ht; 162 param->channel.allow_vht = mlme_obj->proto.vht_info.allow_vht; 163 param->channel.phy_mode = mlme_obj->mgmt.generic.phy_mode; 164 param->channel.cfreq1 = des_chan->ch_cfreq1; 165 param->channel.cfreq2 = des_chan->ch_cfreq2; 166 param->channel.maxpower = mlme_obj->mgmt.generic.maxpower; 167 param->channel.minpower = mlme_obj->mgmt.generic.minpower; 168 param->channel.maxregpower = mlme_obj->mgmt.generic.maxregpower; 169 param->channel.antennamax = mlme_obj->mgmt.generic.antennamax; 170 param->channel.reg_class_id = mlme_obj->mgmt.generic.reg_class_id; 171 param->bcn_tx_rate_code = mlme_obj->mgmt.rate_info.bcn_tx_rate; 172 param->ldpc_rx_enabled = mlme_obj->proto.generic.ldpc; 173 if (mlme_obj->mgmt.generic.type == WLAN_VDEV_MLME_TYPE_AP) { 174 param->hidden_ssid = mlme_obj->mgmt.ap.hidden_ssid; 175 param->cac_duration_ms = mlme_obj->mgmt.ap.cac_duration_ms; 176 } 177 wlan_vdev_mlme_get_ssid(vdev, param->ssid.mac_ssid, 178 ¶m->ssid.length); 179 180 if (des_chan->ch_phymode == WLAN_PHYMODE_11AC_VHT80 || 181 des_chan->ch_phymode == WLAN_PHYMODE_11AXA_HE80) { 182 tgt_dfs_find_vht80_precac_chan_freq(pdev, 183 des_chan->ch_phymode, 184 des_chan->ch_freq_seg1, 185 ¶m->channel.cfreq1, 186 ¶m->channel.cfreq2, 187 ¶m->channel.phy_mode, 188 &dfs_set_cfreq2, 189 &set_agile); 190 param->channel.dfs_set_cfreq2 = dfs_set_cfreq2; 191 param->channel.set_agile = set_agile; 192 } 193 194 wlan_objmgr_pdev_release_ref(pdev, WLAN_MLME_SB_ID); 195 return QDF_STATUS_SUCCESS; 196 } 197 198 QDF_STATUS vdev_mgr_start_send( 199 struct vdev_mlme_obj *mlme_obj, 200 bool restart) 201 { 202 QDF_STATUS status; 203 struct vdev_start_params param = {0}; 204 205 if (!mlme_obj) { 206 mlme_err("VDEV_MLME is NULL"); 207 return QDF_STATUS_E_INVAL; 208 } 209 210 status = vdev_mgr_start_param_update(mlme_obj, ¶m); 211 if (QDF_IS_STATUS_ERROR(status)) { 212 mlme_err("Param Update Error: %d", status); 213 return status; 214 } 215 216 param.is_restart = restart; 217 status = tgt_vdev_mgr_start_send(mlme_obj, ¶m); 218 219 return status; 220 } 221 222 static QDF_STATUS vdev_mgr_delete_param_update( 223 struct vdev_mlme_obj *mlme_obj, 224 struct vdev_delete_params *param) 225 { 226 struct wlan_objmgr_vdev *vdev; 227 228 vdev = mlme_obj->vdev; 229 if (!vdev) { 230 mlme_err("VDEV is NULL"); 231 return QDF_STATUS_E_INVAL; 232 } 233 234 param->vdev_id = wlan_vdev_get_id(vdev); 235 return QDF_STATUS_SUCCESS; 236 } 237 238 QDF_STATUS vdev_mgr_delete_send(struct vdev_mlme_obj *mlme_obj) 239 { 240 QDF_STATUS status; 241 struct vdev_delete_params param; 242 243 if (!mlme_obj) { 244 mlme_err("VDEV_MLME is NULL"); 245 return QDF_STATUS_E_INVAL; 246 } 247 248 status = vdev_mgr_delete_param_update(mlme_obj, ¶m); 249 if (QDF_IS_STATUS_ERROR(status)) { 250 mlme_err("Param Update Error: %d", status); 251 return status; 252 } 253 254 status = tgt_vdev_mgr_delete_send(mlme_obj, ¶m); 255 256 return status; 257 } 258 259 static QDF_STATUS vdev_mgr_stop_param_update( 260 struct vdev_mlme_obj *mlme_obj, 261 struct vdev_stop_params *param) 262 { 263 struct wlan_objmgr_vdev *vdev; 264 265 vdev = mlme_obj->vdev; 266 if (!vdev) { 267 mlme_err("VDEV is NULL"); 268 return QDF_STATUS_E_INVAL; 269 } 270 271 param->vdev_id = wlan_vdev_get_id(vdev); 272 273 return QDF_STATUS_SUCCESS; 274 } 275 276 QDF_STATUS vdev_mgr_stop_send(struct vdev_mlme_obj *mlme_obj) 277 { 278 QDF_STATUS status; 279 struct vdev_stop_params param = {0}; 280 281 if (!mlme_obj) { 282 mlme_err("VDEV_MLME is NULL"); 283 return QDF_STATUS_E_INVAL; 284 } 285 286 status = vdev_mgr_stop_param_update(mlme_obj, ¶m); 287 if (QDF_IS_STATUS_ERROR(status)) { 288 mlme_err("Param Update Error: %d", status); 289 return status; 290 } 291 292 status = tgt_vdev_mgr_stop_send(mlme_obj, ¶m); 293 294 return status; 295 } 296 297 static QDF_STATUS vdev_mgr_bcn_tmpl_param_update( 298 struct vdev_mlme_obj *mlme_obj, 299 struct beacon_tmpl_params *param) 300 { 301 return QDF_STATUS_SUCCESS; 302 } 303 304 static QDF_STATUS vdev_mgr_sta_ps_param_update( 305 struct vdev_mlme_obj *mlme_obj, 306 struct sta_ps_params *param) 307 { 308 struct wlan_objmgr_vdev *vdev; 309 310 vdev = mlme_obj->vdev; 311 param->vdev_id = wlan_vdev_get_id(vdev); 312 param->param_id = WLAN_MLME_CFG_UAPSD; 313 param->value = mlme_obj->proto.sta.uapsd_cfg; 314 return QDF_STATUS_SUCCESS; 315 } 316 317 static QDF_STATUS vdev_mgr_up_param_update( 318 struct vdev_mlme_obj *mlme_obj, 319 struct vdev_up_params *param) 320 { 321 struct vdev_mlme_mbss_11ax *mbss; 322 struct wlan_objmgr_vdev *vdev; 323 324 vdev = mlme_obj->vdev; 325 param->vdev_id = wlan_vdev_get_id(vdev); 326 param->assoc_id = mlme_obj->proto.sta.assoc_id; 327 mbss = &mlme_obj->mgmt.mbss_11ax; 328 if (mbss->profile_idx) { 329 param->profile_idx = mbss->profile_idx; 330 param->profile_num = mbss->profile_num; 331 qdf_mem_copy(param->trans_bssid, mbss->trans_bssid, 332 QDF_MAC_ADDR_SIZE); 333 } 334 335 return QDF_STATUS_SUCCESS; 336 } 337 338 QDF_STATUS vdev_mgr_up_send(struct vdev_mlme_obj *mlme_obj) 339 { 340 QDF_STATUS status; 341 struct vdev_up_params param = {0}; 342 struct sta_ps_params ps_param = {0}; 343 struct beacon_tmpl_params bcn_tmpl_param = {0}; 344 enum QDF_OPMODE opmode; 345 struct wlan_objmgr_vdev *vdev; 346 struct config_fils_params fils_param = {0}; 347 348 if (!mlme_obj) { 349 mlme_err("VDEV_MLME is NULL"); 350 return QDF_STATUS_E_INVAL; 351 } 352 353 vdev = mlme_obj->vdev; 354 if (!vdev) { 355 mlme_err("VDEV is NULL"); 356 return QDF_STATUS_E_INVAL; 357 } 358 359 vdev_mgr_up_param_update(mlme_obj, ¶m); 360 vdev_mgr_bcn_tmpl_param_update(mlme_obj, &bcn_tmpl_param); 361 362 opmode = wlan_vdev_mlme_get_opmode(vdev); 363 if (opmode == QDF_STA_MODE) { 364 vdev_mgr_sta_ps_param_update(mlme_obj, &ps_param); 365 status = tgt_vdev_mgr_sta_ps_param_send(mlme_obj, &ps_param); 366 367 } 368 369 status = tgt_vdev_mgr_beacon_tmpl_send(mlme_obj, &bcn_tmpl_param); 370 if (QDF_IS_STATUS_ERROR(status)) 371 return status; 372 373 status = tgt_vdev_mgr_up_send(mlme_obj, ¶m); 374 if (QDF_IS_STATUS_ERROR(status)) 375 return status; 376 377 if (opmode == QDF_SAP_MODE && mlme_obj->vdev->vdev_mlme.des_chan && 378 WLAN_REG_IS_6GHZ_CHAN_FREQ( 379 mlme_obj->vdev->vdev_mlme.des_chan->ch_freq)) { 380 fils_param.vdev_id = wlan_vdev_get_id(mlme_obj->vdev); 381 fils_param.fd_period = DEFAULT_FILS_DISCOVERY_PERIOD; 382 status = tgt_vdev_mgr_fils_enable_send(mlme_obj, 383 &fils_param); 384 } 385 386 return status; 387 } 388 389 static QDF_STATUS vdev_mgr_down_param_update( 390 struct vdev_mlme_obj *mlme_obj, 391 struct vdev_down_params *param) 392 { 393 struct wlan_objmgr_vdev *vdev; 394 395 vdev = mlme_obj->vdev; 396 if (!vdev) { 397 mlme_err("VDEV is NULL"); 398 return QDF_STATUS_E_INVAL; 399 } 400 401 param->vdev_id = wlan_vdev_get_id(vdev); 402 403 return QDF_STATUS_SUCCESS; 404 } 405 406 QDF_STATUS vdev_mgr_down_send(struct vdev_mlme_obj *mlme_obj) 407 { 408 QDF_STATUS status; 409 struct vdev_down_params param = {0}; 410 411 if (!mlme_obj) { 412 mlme_err("VDEV_MLME is NULL"); 413 return QDF_STATUS_E_INVAL; 414 } 415 416 status = vdev_mgr_down_param_update(mlme_obj, ¶m); 417 if (QDF_IS_STATUS_ERROR(status)) { 418 mlme_err("Param Update Error: %d", status); 419 return status; 420 } 421 422 status = tgt_vdev_mgr_down_send(mlme_obj, ¶m); 423 424 return status; 425 } 426 427 static QDF_STATUS vdev_mgr_peer_flush_tids_param_update( 428 struct vdev_mlme_obj *mlme_obj, 429 struct peer_flush_params *param, 430 uint8_t *mac, 431 uint32_t peer_tid_bitmap) 432 { 433 struct wlan_objmgr_vdev *vdev; 434 435 vdev = mlme_obj->vdev; 436 if (!vdev) { 437 mlme_err("VDEV is NULL"); 438 return QDF_STATUS_E_INVAL; 439 } 440 441 param->vdev_id = wlan_vdev_get_id(vdev); 442 param->peer_tid_bitmap = peer_tid_bitmap; 443 qdf_mem_copy(param->peer_mac, mac, QDF_MAC_ADDR_SIZE); 444 return QDF_STATUS_SUCCESS; 445 } 446 447 QDF_STATUS vdev_mgr_peer_flush_tids_send(struct vdev_mlme_obj *mlme_obj, 448 uint8_t *mac, 449 uint32_t peer_tid_bitmap) 450 { 451 QDF_STATUS status; 452 struct peer_flush_params param = {0}; 453 454 if (!mlme_obj || !mac) { 455 mlme_err("Invalid input"); 456 return QDF_STATUS_E_INVAL; 457 } 458 459 status = vdev_mgr_peer_flush_tids_param_update(mlme_obj, ¶m, 460 mac, peer_tid_bitmap); 461 if (QDF_IS_STATUS_ERROR(status)) { 462 mlme_err("Param Update Error: %d", status); 463 return status; 464 } 465 466 status = tgt_vdev_mgr_peer_flush_tids_send(mlme_obj, ¶m); 467 468 return status; 469 } 470 471 static QDF_STATUS vdev_mgr_multiple_restart_param_update( 472 struct wlan_objmgr_pdev *pdev, 473 struct mlme_channel_param *chan, 474 uint32_t disable_hw_ack, 475 uint32_t *vdev_ids, 476 uint32_t num_vdevs, 477 struct multiple_vdev_restart_params *param) 478 { 479 param->pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 480 param->requestor_id = MULTIPLE_VDEV_RESTART_REQ_ID; 481 param->disable_hw_ack = disable_hw_ack; 482 param->cac_duration_ms = WLAN_DFS_WAIT_MS; 483 param->num_vdevs = num_vdevs; 484 485 qdf_mem_copy(param->vdev_ids, vdev_ids, 486 sizeof(uint32_t) * (param->num_vdevs)); 487 qdf_mem_copy(¶m->ch_param, chan, 488 sizeof(struct mlme_channel_param)); 489 490 return QDF_STATUS_SUCCESS; 491 } 492 493 QDF_STATUS vdev_mgr_multiple_restart_send(struct wlan_objmgr_pdev *pdev, 494 struct mlme_channel_param *chan, 495 uint32_t disable_hw_ack, 496 uint32_t *vdev_ids, 497 uint32_t num_vdevs) 498 { 499 struct multiple_vdev_restart_params param = {0}; 500 501 vdev_mgr_multiple_restart_param_update(pdev, chan, 502 disable_hw_ack, 503 vdev_ids, num_vdevs, 504 ¶m); 505 506 return tgt_vdev_mgr_multiple_vdev_restart_send(pdev, ¶m); 507 } 508 509 qdf_export_symbol(vdev_mgr_multiple_restart_send); 510 511 static QDF_STATUS vdev_mgr_set_custom_aggr_size_param_update( 512 struct vdev_mlme_obj *mlme_obj, 513 struct set_custom_aggr_size_params *param, 514 bool is_amsdu) 515 { 516 struct wlan_objmgr_vdev *vdev; 517 518 vdev = mlme_obj->vdev; 519 if (!vdev) { 520 mlme_err("VDEV is NULL"); 521 return QDF_STATUS_E_INVAL; 522 } 523 524 param->aggr_type = is_amsdu ? WLAN_MLME_CUSTOM_AGGR_TYPE_AMSDU 525 : WLAN_MLME_CUSTOM_AGGR_TYPE_AMPDU; 526 /* 527 * We are only setting TX params, therefore 528 * we are disabling rx_aggr_size 529 */ 530 param->rx_aggr_size_disable = true; 531 param->tx_aggr_size = is_amsdu ? mlme_obj->mgmt.generic.amsdu 532 : mlme_obj->mgmt.generic.ampdu; 533 param->vdev_id = wlan_vdev_get_id(vdev); 534 535 return QDF_STATUS_SUCCESS; 536 } 537 538 QDF_STATUS vdev_mgr_set_custom_aggr_size_send( 539 struct vdev_mlme_obj *vdev_mlme, 540 bool is_amsdu) 541 { 542 QDF_STATUS status; 543 struct set_custom_aggr_size_params param = {0}; 544 545 status = vdev_mgr_set_custom_aggr_size_param_update(vdev_mlme, 546 ¶m, is_amsdu); 547 if (QDF_IS_STATUS_ERROR(status)) { 548 mlme_err("Param Update Error: %d", status); 549 return status; 550 } 551 552 return tgt_vdev_mgr_set_custom_aggr_size_send(vdev_mlme, ¶m); 553 } 554 555 static QDF_STATUS vdev_mgr_peer_delete_all_param_update( 556 struct vdev_mlme_obj *mlme_obj, 557 struct peer_delete_all_params *param) 558 { 559 struct wlan_objmgr_vdev *vdev; 560 561 vdev = mlme_obj->vdev; 562 if (!vdev) { 563 mlme_err("VDEV is NULL"); 564 return QDF_STATUS_E_INVAL; 565 } 566 567 param->vdev_id = wlan_vdev_get_id(vdev); 568 return QDF_STATUS_SUCCESS; 569 } 570 571 QDF_STATUS vdev_mgr_peer_delete_all_send(struct vdev_mlme_obj *mlme_obj) 572 { 573 QDF_STATUS status; 574 struct peer_delete_all_params param = {0}; 575 576 if (!mlme_obj) { 577 mlme_err("Invalid input"); 578 return QDF_STATUS_E_INVAL; 579 } 580 581 status = vdev_mgr_peer_delete_all_param_update(mlme_obj, ¶m); 582 if (QDF_IS_STATUS_ERROR(status)) { 583 mlme_err("Param Update Error: %d", status); 584 return status; 585 } 586 587 status = tgt_vdev_mgr_peer_delete_all_send(mlme_obj, ¶m); 588 589 return status; 590 } 591 592