1 /* 2 * Copyright (c) 2018-2019, 2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /** 19 * DOC: Implements VDEV MLME public APIs 20 */ 21 22 #include <wlan_objmgr_vdev_obj.h> 23 #include <wlan_mlme_dbg.h> 24 #include "include/wlan_vdev_mlme.h" 25 #include "../../core/src/vdev_mlme_sm.h" 26 #include <wlan_vdev_mlme_api.h> 27 #include <include/wlan_mlme_cmn.h> 28 #include <qdf_module.h> 29 #include "wlan_objmgr_vdev_obj.h" 30 31 struct vdev_mlme_obj *wlan_vdev_mlme_get_cmpt_obj(struct wlan_objmgr_vdev *vdev) 32 { 33 struct vdev_mlme_obj *vdev_mlme; 34 35 if (!vdev) { 36 mlme_err("vdev is NULL"); 37 return NULL; 38 } 39 40 vdev_mlme = wlan_objmgr_vdev_get_comp_private_obj(vdev, 41 WLAN_UMAC_COMP_MLME); 42 if (!vdev_mlme) { 43 mlme_err(" MLME component object is NULL"); 44 return NULL; 45 } 46 47 return vdev_mlme; 48 } 49 50 qdf_export_symbol(wlan_vdev_mlme_get_cmpt_obj); 51 52 void wlan_vdev_mlme_set_ext_hdl(struct wlan_objmgr_vdev *vdev, 53 mlme_vdev_ext_t *ext_hdl) 54 { 55 struct vdev_mlme_obj *vdev_mlme; 56 57 if (!ext_hdl) { 58 mlme_err("Invalid input"); 59 return; 60 } 61 62 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 63 if (vdev_mlme) 64 vdev_mlme->ext_vdev_ptr = ext_hdl; 65 } 66 67 qdf_export_symbol(wlan_vdev_mlme_set_ext_hdl); 68 69 mlme_vdev_ext_t *wlan_vdev_mlme_get_ext_hdl(struct wlan_objmgr_vdev *vdev) 70 { 71 struct vdev_mlme_obj *vdev_mlme; 72 73 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 74 if (vdev_mlme) 75 return vdev_mlme->ext_vdev_ptr; 76 77 return NULL; 78 } 79 80 qdf_export_symbol(wlan_vdev_mlme_get_ext_hdl); 81 82 QDF_STATUS wlan_vdev_mlme_sm_deliver_evt(struct wlan_objmgr_vdev *vdev, 83 enum wlan_vdev_sm_evt event, 84 uint16_t event_data_len, 85 void *event_data) 86 { 87 struct vdev_mlme_obj *vdev_mlme; 88 QDF_STATUS status; 89 enum wlan_vdev_state state_entry, state_exit; 90 enum wlan_vdev_state substate_entry, substate_exit; 91 92 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 93 if (!vdev_mlme) { 94 mlme_err("vdev component object is NULL"); 95 return QDF_STATUS_E_FAILURE; 96 } 97 98 mlme_vdev_sm_spin_lock(vdev_mlme); 99 100 /* store entry state and sub state for prints */ 101 state_entry = wlan_vdev_mlme_get_state(vdev); 102 substate_entry = wlan_vdev_mlme_get_substate(vdev); 103 mlme_vdev_sm_print_state_event(vdev_mlme, event); 104 105 status = mlme_vdev_sm_deliver_event(vdev_mlme, event, event_data_len, 106 event_data); 107 /* Take exit state, exit substate for prints */ 108 state_exit = wlan_vdev_mlme_get_state(vdev); 109 substate_exit = wlan_vdev_mlme_get_substate(vdev); 110 /* If no state and substate change, don't print */ 111 if (!((state_entry == state_exit) && (substate_entry == substate_exit))) 112 mlme_vdev_sm_print_state(vdev_mlme); 113 mlme_vdev_sm_spin_unlock(vdev_mlme); 114 115 return status; 116 } 117 118 qdf_export_symbol(wlan_vdev_mlme_sm_deliver_evt); 119 120 QDF_STATUS wlan_vdev_mlme_sm_deliver_evt_sync(struct wlan_objmgr_vdev *vdev, 121 enum wlan_vdev_sm_evt event, 122 uint16_t event_data_len, 123 void *event_data) 124 { 125 struct vdev_mlme_obj *vdev_mlme; 126 QDF_STATUS status; 127 128 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 129 if (!vdev_mlme) { 130 mlme_err("vdev component object is NULL"); 131 return QDF_STATUS_E_FAILURE; 132 } 133 134 status = mlme_vdev_sm_deliver_event(vdev_mlme, event, event_data_len, 135 event_data); 136 137 return status; 138 } 139 140 qdf_export_symbol(wlan_vdev_mlme_sm_deliver_evt_sync); 141 142 #ifdef SM_ENG_HIST_ENABLE 143 void wlan_vdev_mlme_sm_history_print(struct wlan_objmgr_vdev *vdev) 144 { 145 struct vdev_mlme_obj *vdev_mlme; 146 147 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 148 if (!vdev_mlme) { 149 mlme_err("vdev component object is NULL"); 150 return; 151 } 152 153 mlme_vdev_sm_history_print(vdev_mlme); 154 } 155 #endif 156 157 QDF_STATUS wlan_vdev_allow_connect_n_tx(struct wlan_objmgr_vdev *vdev) 158 { 159 enum wlan_vdev_state state; 160 enum wlan_vdev_state substate; 161 162 state = wlan_vdev_mlme_get_state(vdev); 163 substate = wlan_vdev_mlme_get_substate(vdev); 164 if ((state == WLAN_VDEV_S_UP && substate == WLAN_VDEV_SS_UP_ACTIVE) || 165 ((state == WLAN_VDEV_S_SUSPEND) && 166 (substate == WLAN_VDEV_SS_SUSPEND_CSA_RESTART))) 167 return QDF_STATUS_SUCCESS; 168 169 return QDF_STATUS_E_FAILURE; 170 } 171 172 QDF_STATUS wlan_vdev_mlme_is_active(struct wlan_objmgr_vdev *vdev) 173 { 174 enum wlan_vdev_state state; 175 176 state = wlan_vdev_mlme_get_state(vdev); 177 if ((state == WLAN_VDEV_S_UP) || (state == WLAN_VDEV_S_DFS_CAC_WAIT) || 178 (state == WLAN_VDEV_S_SUSPEND)) 179 return QDF_STATUS_SUCCESS; 180 181 return QDF_STATUS_E_FAILURE; 182 } 183 184 qdf_export_symbol(wlan_vdev_mlme_is_active); 185 186 QDF_STATUS wlan_vdev_chan_config_valid(struct wlan_objmgr_vdev *vdev) 187 { 188 enum wlan_vdev_state state; 189 enum wlan_vdev_state substate; 190 191 state = wlan_vdev_mlme_get_state(vdev); 192 substate = wlan_vdev_mlme_get_substate(vdev); 193 if (!((state == WLAN_VDEV_S_INIT) || (state == WLAN_VDEV_S_STOP))) 194 return QDF_STATUS_SUCCESS; 195 196 return QDF_STATUS_E_FAILURE; 197 } 198 199 qdf_export_symbol(wlan_vdev_chan_config_valid); 200 201 QDF_STATUS wlan_vdev_mlme_is_csa_restart(struct wlan_objmgr_vdev *vdev) 202 { 203 enum wlan_vdev_state state; 204 enum wlan_vdev_state substate; 205 206 state = wlan_vdev_mlme_get_state(vdev); 207 substate = wlan_vdev_mlme_get_substate(vdev); 208 if ((state == WLAN_VDEV_S_SUSPEND) && 209 (substate == WLAN_VDEV_SS_SUSPEND_CSA_RESTART)) 210 return QDF_STATUS_SUCCESS; 211 212 return QDF_STATUS_E_FAILURE; 213 } 214 215 qdf_export_symbol(wlan_vdev_mlme_is_csa_restart); 216 217 QDF_STATUS wlan_vdev_is_going_down(struct wlan_objmgr_vdev *vdev) 218 { 219 enum wlan_vdev_state state; 220 enum wlan_vdev_state substate; 221 222 state = wlan_vdev_mlme_get_state(vdev); 223 substate = wlan_vdev_mlme_get_substate(vdev); 224 if ((state == WLAN_VDEV_S_STOP) || 225 ((state == WLAN_VDEV_S_SUSPEND) && 226 (substate == WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN))) 227 return QDF_STATUS_SUCCESS; 228 229 return QDF_STATUS_E_FAILURE; 230 } 231 232 QDF_STATUS wlan_vdev_is_mlo_peer_create_allowed(struct wlan_objmgr_vdev *vdev) 233 { 234 enum wlan_vdev_state state; 235 enum wlan_vdev_state substate; 236 bool acs_in_progress; 237 QDF_STATUS ret; 238 QDF_STATUS status = QDF_STATUS_E_FAILURE; 239 240 if (!vdev) { 241 mlme_err("vdev is null"); 242 return status; 243 } 244 245 state = wlan_vdev_mlme_get_state(vdev); 246 substate = wlan_vdev_mlme_get_substate(vdev); 247 248 acs_in_progress = false; 249 ret = mlme_ext_hdl_get_acs_in_progress(vdev, &acs_in_progress); 250 if (ret != QDF_STATUS_SUCCESS) { 251 mlme_err("Unable to get ACS in progress status"); 252 return status; 253 } 254 255 if (!acs_in_progress) 256 if ((state == WLAN_VDEV_S_UP) || 257 ((state == WLAN_VDEV_S_SUSPEND) && 258 (substate == WLAN_VDEV_SS_SUSPEND_CSA_RESTART)) || 259 (state == WLAN_VDEV_S_DFS_CAC_WAIT)) 260 status = QDF_STATUS_SUCCESS; 261 262 /* with link rejection feature, this check can be removed */ 263 if (wlan_vdev_mlme_op_flags_get(vdev, WLAN_VDEV_OP_MLO_STOP_LINK_DEL) || 264 wlan_vdev_mlme_op_flags_get(vdev, 265 WLAN_VDEV_OP_MLO_LINK_TBTT_COMPLETE)) 266 status = QDF_STATUS_E_FAILURE; 267 268 return status; 269 } 270 271 QDF_STATUS wlan_vdev_is_restart_progress(struct wlan_objmgr_vdev *vdev) 272 { 273 enum wlan_vdev_state state; 274 enum wlan_vdev_state substate; 275 276 state = wlan_vdev_mlme_get_state(vdev); 277 substate = wlan_vdev_mlme_get_substate(vdev); 278 if ((state == WLAN_VDEV_S_START) && 279 (substate == WLAN_VDEV_SS_START_RESTART_PROGRESS)) 280 return QDF_STATUS_SUCCESS; 281 282 return QDF_STATUS_E_FAILURE; 283 } 284 285 QDF_STATUS wlan_vdev_is_dfs_cac_wait(struct wlan_objmgr_vdev *vdev) 286 { 287 if (wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_DFS_CAC_WAIT) 288 return QDF_STATUS_SUCCESS; 289 290 return QDF_STATUS_E_FAILURE; 291 } 292 293 void wlan_vdev_mlme_cmd_lock(struct wlan_objmgr_vdev *vdev) 294 { 295 struct vdev_mlme_obj *vdev_mlme; 296 297 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 298 if (!vdev_mlme) { 299 mlme_err("vdev component object is NULL"); 300 return; 301 } 302 303 mlme_vdev_cmd_mutex_acquire(vdev_mlme); 304 } 305 306 void wlan_vdev_mlme_cmd_unlock(struct wlan_objmgr_vdev *vdev) 307 { 308 struct vdev_mlme_obj *vdev_mlme; 309 310 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 311 if (!vdev_mlme) { 312 mlme_err("vdev component object is NULL"); 313 return; 314 } 315 316 mlme_vdev_cmd_mutex_release(vdev_mlme); 317 } 318 319 QDF_STATUS wlan_vdev_mlme_is_scan_allowed(struct wlan_objmgr_vdev *vdev) 320 { 321 enum wlan_vdev_state state; 322 enum wlan_vdev_state substate; 323 324 state = wlan_vdev_mlme_get_state(vdev); 325 substate = wlan_vdev_mlme_get_substate(vdev); 326 if ((state == WLAN_VDEV_S_INIT) || 327 (state == WLAN_VDEV_S_UP && substate == WLAN_VDEV_SS_UP_ACTIVE) || 328 (state == WLAN_VDEV_S_STOP)) 329 return QDF_STATUS_SUCCESS; 330 331 return QDF_STATUS_E_FAILURE; 332 } 333 334 QDF_STATUS wlan_vdev_mlme_is_init_state(struct wlan_objmgr_vdev *vdev) 335 { 336 enum wlan_vdev_state state; 337 338 state = wlan_vdev_mlme_get_state(vdev); 339 if (state == WLAN_VDEV_S_INIT) 340 return QDF_STATUS_SUCCESS; 341 342 return QDF_STATUS_E_FAILURE; 343 } 344 345 QDF_STATUS wlan_vdev_is_up_active_state(struct wlan_objmgr_vdev *vdev) 346 { 347 enum wlan_vdev_state state; 348 enum wlan_vdev_state substate; 349 350 state = wlan_vdev_mlme_get_state(vdev); 351 substate = wlan_vdev_mlme_get_substate(vdev); 352 if (state == WLAN_VDEV_S_UP && substate == WLAN_VDEV_SS_UP_ACTIVE) 353 return QDF_STATUS_SUCCESS; 354 355 return QDF_STATUS_E_FAILURE; 356 } 357 358 qdf_export_symbol(wlan_vdev_is_up_active_state); 359 360 #ifdef WLAN_FEATURE_11BE_MLO 361 bool 362 wlan_vdev_mlme_get_is_mlo_link(struct wlan_objmgr_psoc *psoc, 363 uint8_t vdev_id) 364 { 365 struct wlan_objmgr_vdev *vdev; 366 bool is_link = false; 367 368 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 369 WLAN_MLME_OBJMGR_ID); 370 if (!vdev) { 371 mlme_err("vdev object is NULL for vdev %d", vdev_id); 372 return is_link; 373 } 374 375 if (wlan_vdev_mlme_is_mlo_vdev(vdev) && 376 wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 377 is_link = true; 378 379 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 380 381 return is_link; 382 } 383 384 bool 385 wlan_vdev_mlme_get_is_mlo_vdev(struct wlan_objmgr_psoc *psoc, 386 uint8_t vdev_id) 387 { 388 struct wlan_objmgr_vdev *vdev; 389 bool is_mlo_vdev = false; 390 391 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 392 WLAN_MLME_OBJMGR_ID); 393 if (!vdev) { 394 mlme_err("vdev object is NULL for vdev %d", vdev_id); 395 return is_mlo_vdev; 396 } 397 398 if (wlan_vdev_mlme_is_mlo_vdev(vdev) && 399 !wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 400 is_mlo_vdev = true; 401 402 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 403 404 return is_mlo_vdev; 405 } 406 #endif 407 #ifdef WLAN_FEATURE_SR 408 void 409 wlan_mlme_update_sr_data(struct wlan_objmgr_vdev *vdev, int *val, 410 int32_t srg_pd_threshold, int32_t non_srg_pd_threshold, 411 bool is_sr_enable) 412 { 413 uint8_t ap_non_srg_pd_threshold = 0; 414 uint8_t ap_srg_min_pd_threshold_offset = 0; 415 uint8_t ap_srg_max_pd_threshold_offset = 0; 416 uint8_t sr_ctrl; 417 418 sr_ctrl = wlan_vdev_mlme_get_sr_ctrl(vdev); 419 if (!(sr_ctrl & NON_SRG_PD_SR_DISALLOWED) && 420 (sr_ctrl & NON_SRG_OFFSET_PRESENT)) { 421 ap_non_srg_pd_threshold = 422 wlan_vdev_mlme_get_non_srg_pd_offset(vdev) + 423 SR_PD_THRESHOLD_MIN; 424 /* 425 * Update non_srg_pd_threshold with provide 426 * non_srg_pd_threshold for non-srg, if pd threshold is 427 * with in the range else keep the same as 428 * advertised by AP. 429 */ 430 if (!non_srg_pd_threshold || 431 (non_srg_pd_threshold > ap_non_srg_pd_threshold)) 432 non_srg_pd_threshold = ap_non_srg_pd_threshold; 433 434 /* 31st BIT - Enable/Disable Non-SRG based spatial reuse. */ 435 *val |= is_sr_enable << NON_SRG_SPR_ENABLE_POS; 436 } 437 438 if (sr_ctrl & SRG_INFO_PRESENT) { 439 wlan_vdev_mlme_get_srg_pd_offset( 440 vdev, &ap_srg_max_pd_threshold_offset, 441 &ap_srg_min_pd_threshold_offset); 442 /* 443 * Update srg_pd_threshold with provide 444 * srg_pd_threshold, if pd threshold is with in the 445 * SRG range else keep the max of advertised by AP. 446 */ 447 if (!srg_pd_threshold || 448 (srg_pd_threshold > (ap_srg_max_pd_threshold_offset + 449 SR_PD_THRESHOLD_MIN) || 450 srg_pd_threshold < (ap_srg_min_pd_threshold_offset + 451 SR_PD_THRESHOLD_MIN))) 452 srg_pd_threshold = ap_srg_max_pd_threshold_offset + 453 SR_PD_THRESHOLD_MIN; 454 455 /* 30th BIT - Enable/Disable SRG based spatial reuse. */ 456 *val |= is_sr_enable << SRG_SPR_ENABLE_POS; 457 } 458 /* bit | purpose 459 * ----------------- 460 * 0 - 7 | Param Value for non-SRG based Spatial Reuse 461 * 8 - 15| Param value for SRG based Spatial Reuse 462 * 29 | Param value is in dBm units rather than dB units 463 */ 464 QDF_SET_BITS(*val, NON_SRG_MAX_PD_OFFSET_POS, SR_PADDING_BYTE, 465 (uint8_t)non_srg_pd_threshold); 466 QDF_SET_BITS(*val, SRG_THRESHOLD_MAX_PD_POS, SR_PADDING_BYTE, 467 (uint8_t)srg_pd_threshold); 468 *val |= SR_PARAM_VAL_DBM_UNIT << SR_PARAM_VAL_DBM_POS; 469 wlan_vdev_mlme_set_current_non_srg_pd_threshold(vdev, 470 non_srg_pd_threshold); 471 wlan_vdev_mlme_set_current_srg_pd_threshold(vdev, srg_pd_threshold); 472 } 473 #endif 474