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