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 347 if (!mlme_obj) { 348 mlme_err("VDEV_MLME is NULL"); 349 return QDF_STATUS_E_INVAL; 350 } 351 352 vdev = mlme_obj->vdev; 353 if (!vdev) { 354 mlme_err("VDEV is NULL"); 355 return QDF_STATUS_E_INVAL; 356 } 357 358 vdev_mgr_up_param_update(mlme_obj, ¶m); 359 vdev_mgr_bcn_tmpl_param_update(mlme_obj, &bcn_tmpl_param); 360 361 opmode = wlan_vdev_mlme_get_opmode(vdev); 362 if (opmode == QDF_STA_MODE) { 363 vdev_mgr_sta_ps_param_update(mlme_obj, &ps_param); 364 status = tgt_vdev_mgr_sta_ps_param_send(mlme_obj, &ps_param); 365 366 } 367 368 status = tgt_vdev_mgr_beacon_tmpl_send(mlme_obj, &bcn_tmpl_param); 369 if (QDF_IS_STATUS_ERROR(status)) 370 return status; 371 372 status = tgt_vdev_mgr_up_send(mlme_obj, ¶m); 373 374 return status; 375 } 376 377 static QDF_STATUS vdev_mgr_down_param_update( 378 struct vdev_mlme_obj *mlme_obj, 379 struct vdev_down_params *param) 380 { 381 struct wlan_objmgr_vdev *vdev; 382 383 vdev = mlme_obj->vdev; 384 if (!vdev) { 385 mlme_err("VDEV is NULL"); 386 return QDF_STATUS_E_INVAL; 387 } 388 389 param->vdev_id = wlan_vdev_get_id(vdev); 390 391 return QDF_STATUS_SUCCESS; 392 } 393 394 QDF_STATUS vdev_mgr_down_send(struct vdev_mlme_obj *mlme_obj) 395 { 396 QDF_STATUS status; 397 struct vdev_down_params param = {0}; 398 399 if (!mlme_obj) { 400 mlme_err("VDEV_MLME is NULL"); 401 return QDF_STATUS_E_INVAL; 402 } 403 404 status = vdev_mgr_down_param_update(mlme_obj, ¶m); 405 if (QDF_IS_STATUS_ERROR(status)) { 406 mlme_err("Param Update Error: %d", status); 407 return status; 408 } 409 410 status = tgt_vdev_mgr_down_send(mlme_obj, ¶m); 411 412 return status; 413 } 414 415 static QDF_STATUS vdev_mgr_peer_flush_tids_param_update( 416 struct vdev_mlme_obj *mlme_obj, 417 struct peer_flush_params *param, 418 uint8_t *mac, 419 uint32_t peer_tid_bitmap) 420 { 421 struct wlan_objmgr_vdev *vdev; 422 423 vdev = mlme_obj->vdev; 424 if (!vdev) { 425 mlme_err("VDEV is NULL"); 426 return QDF_STATUS_E_INVAL; 427 } 428 429 param->vdev_id = wlan_vdev_get_id(vdev); 430 param->peer_tid_bitmap = peer_tid_bitmap; 431 qdf_mem_copy(param->peer_mac, mac, QDF_MAC_ADDR_SIZE); 432 return QDF_STATUS_SUCCESS; 433 } 434 435 QDF_STATUS vdev_mgr_peer_flush_tids_send(struct vdev_mlme_obj *mlme_obj, 436 uint8_t *mac, 437 uint32_t peer_tid_bitmap) 438 { 439 QDF_STATUS status; 440 struct peer_flush_params param = {0}; 441 442 if (!mlme_obj || !mac) { 443 mlme_err("Invalid input"); 444 return QDF_STATUS_E_INVAL; 445 } 446 447 status = vdev_mgr_peer_flush_tids_param_update(mlme_obj, ¶m, 448 mac, peer_tid_bitmap); 449 if (QDF_IS_STATUS_ERROR(status)) { 450 mlme_err("Param Update Error: %d", status); 451 return status; 452 } 453 454 status = tgt_vdev_mgr_peer_flush_tids_send(mlme_obj, ¶m); 455 456 return status; 457 } 458 459 static QDF_STATUS vdev_mgr_multiple_restart_param_update( 460 struct wlan_objmgr_pdev *pdev, 461 struct mlme_channel_param *chan, 462 uint32_t disable_hw_ack, 463 uint32_t *vdev_ids, 464 uint32_t num_vdevs, 465 struct multiple_vdev_restart_params *param) 466 { 467 param->pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 468 param->requestor_id = MULTIPLE_VDEV_RESTART_REQ_ID; 469 param->disable_hw_ack = disable_hw_ack; 470 param->cac_duration_ms = WLAN_DFS_WAIT_MS; 471 param->num_vdevs = num_vdevs; 472 473 qdf_mem_copy(param->vdev_ids, vdev_ids, 474 sizeof(uint32_t) * (param->num_vdevs)); 475 qdf_mem_copy(¶m->ch_param, chan, 476 sizeof(struct mlme_channel_param)); 477 478 return QDF_STATUS_SUCCESS; 479 } 480 481 QDF_STATUS vdev_mgr_multiple_restart_send(struct wlan_objmgr_pdev *pdev, 482 struct mlme_channel_param *chan, 483 uint32_t disable_hw_ack, 484 uint32_t *vdev_ids, 485 uint32_t num_vdevs) 486 { 487 struct multiple_vdev_restart_params param = {0}; 488 489 vdev_mgr_multiple_restart_param_update(pdev, chan, 490 disable_hw_ack, 491 vdev_ids, num_vdevs, 492 ¶m); 493 494 return tgt_vdev_mgr_multiple_vdev_restart_send(pdev, ¶m); 495 } 496 497 qdf_export_symbol(vdev_mgr_multiple_restart_send); 498 499 static QDF_STATUS vdev_mgr_set_custom_aggr_size_param_update( 500 struct vdev_mlme_obj *mlme_obj, 501 struct set_custom_aggr_size_params *param, 502 bool is_amsdu) 503 { 504 struct wlan_objmgr_vdev *vdev; 505 506 vdev = mlme_obj->vdev; 507 if (!vdev) { 508 mlme_err("VDEV is NULL"); 509 return QDF_STATUS_E_INVAL; 510 } 511 512 param->aggr_type = is_amsdu ? WLAN_MLME_CUSTOM_AGGR_TYPE_AMSDU 513 : WLAN_MLME_CUSTOM_AGGR_TYPE_AMPDU; 514 /* 515 * We are only setting TX params, therefore 516 * we are disabling rx_aggr_size 517 */ 518 param->rx_aggr_size_disable = true; 519 param->tx_aggr_size = is_amsdu ? mlme_obj->mgmt.generic.amsdu 520 : mlme_obj->mgmt.generic.ampdu; 521 param->vdev_id = wlan_vdev_get_id(vdev); 522 523 return QDF_STATUS_SUCCESS; 524 } 525 526 QDF_STATUS vdev_mgr_set_custom_aggr_size_send( 527 struct vdev_mlme_obj *vdev_mlme, 528 bool is_amsdu) 529 { 530 QDF_STATUS status; 531 struct set_custom_aggr_size_params param = {0}; 532 533 status = vdev_mgr_set_custom_aggr_size_param_update(vdev_mlme, 534 ¶m, is_amsdu); 535 if (QDF_IS_STATUS_ERROR(status)) { 536 mlme_err("Param Update Error: %d", status); 537 return status; 538 } 539 540 return tgt_vdev_mgr_set_custom_aggr_size_send(vdev_mlme, ¶m); 541 } 542 543 static QDF_STATUS vdev_mgr_peer_delete_all_param_update( 544 struct vdev_mlme_obj *mlme_obj, 545 struct peer_delete_all_params *param) 546 { 547 struct wlan_objmgr_vdev *vdev; 548 549 vdev = mlme_obj->vdev; 550 if (!vdev) { 551 mlme_err("VDEV is NULL"); 552 return QDF_STATUS_E_INVAL; 553 } 554 555 param->vdev_id = wlan_vdev_get_id(vdev); 556 return QDF_STATUS_SUCCESS; 557 } 558 559 QDF_STATUS vdev_mgr_peer_delete_all_send(struct vdev_mlme_obj *mlme_obj) 560 { 561 QDF_STATUS status; 562 struct peer_delete_all_params param = {0}; 563 564 if (!mlme_obj) { 565 mlme_err("Invalid input"); 566 return QDF_STATUS_E_INVAL; 567 } 568 569 status = vdev_mgr_peer_delete_all_param_update(mlme_obj, ¶m); 570 if (QDF_IS_STATUS_ERROR(status)) { 571 mlme_err("Param Update Error: %d", status); 572 return status; 573 } 574 575 status = tgt_vdev_mgr_peer_delete_all_send(mlme_obj, ¶m); 576 577 return status; 578 } 579 580