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 239 if (!vdev) { 240 mlme_err("vdev is null"); 241 return QDF_STATUS_E_FAILURE; 242 } 243 244 state = wlan_vdev_mlme_get_state(vdev); 245 substate = wlan_vdev_mlme_get_substate(vdev); 246 247 acs_in_progress = false; 248 ret = mlme_ext_hdl_get_acs_in_progress(vdev, &acs_in_progress); 249 if (ret != QDF_STATUS_SUCCESS) { 250 mlme_err("Unable to get ACS in progress status"); 251 return QDF_STATUS_E_FAILURE; 252 } 253 254 if (!acs_in_progress) 255 if ((state == WLAN_VDEV_S_UP) || 256 ((state == WLAN_VDEV_S_SUSPEND) && 257 (substate == WLAN_VDEV_SS_SUSPEND_CSA_RESTART)) || 258 (state == WLAN_VDEV_S_DFS_CAC_WAIT)) 259 return QDF_STATUS_SUCCESS; 260 261 return QDF_STATUS_E_FAILURE; 262 } 263 264 QDF_STATUS wlan_vdev_is_restart_progress(struct wlan_objmgr_vdev *vdev) 265 { 266 enum wlan_vdev_state state; 267 enum wlan_vdev_state substate; 268 269 state = wlan_vdev_mlme_get_state(vdev); 270 substate = wlan_vdev_mlme_get_substate(vdev); 271 if ((state == WLAN_VDEV_S_START) && 272 (substate == WLAN_VDEV_SS_START_RESTART_PROGRESS)) 273 return QDF_STATUS_SUCCESS; 274 275 return QDF_STATUS_E_FAILURE; 276 } 277 278 QDF_STATUS wlan_vdev_is_dfs_cac_wait(struct wlan_objmgr_vdev *vdev) 279 { 280 if (wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_DFS_CAC_WAIT) 281 return QDF_STATUS_SUCCESS; 282 283 return QDF_STATUS_E_FAILURE; 284 } 285 286 void wlan_vdev_mlme_cmd_lock(struct wlan_objmgr_vdev *vdev) 287 { 288 struct vdev_mlme_obj *vdev_mlme; 289 290 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 291 if (!vdev_mlme) { 292 mlme_err("vdev component object is NULL"); 293 return; 294 } 295 296 mlme_vdev_cmd_mutex_acquire(vdev_mlme); 297 } 298 299 void wlan_vdev_mlme_cmd_unlock(struct wlan_objmgr_vdev *vdev) 300 { 301 struct vdev_mlme_obj *vdev_mlme; 302 303 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 304 if (!vdev_mlme) { 305 mlme_err("vdev component object is NULL"); 306 return; 307 } 308 309 mlme_vdev_cmd_mutex_release(vdev_mlme); 310 } 311 312 QDF_STATUS wlan_vdev_mlme_is_scan_allowed(struct wlan_objmgr_vdev *vdev) 313 { 314 enum wlan_vdev_state state; 315 enum wlan_vdev_state substate; 316 317 state = wlan_vdev_mlme_get_state(vdev); 318 substate = wlan_vdev_mlme_get_substate(vdev); 319 if ((state == WLAN_VDEV_S_INIT) || 320 (state == WLAN_VDEV_S_UP && substate == WLAN_VDEV_SS_UP_ACTIVE) || 321 (state == WLAN_VDEV_S_STOP)) 322 return QDF_STATUS_SUCCESS; 323 324 return QDF_STATUS_E_FAILURE; 325 } 326 327 QDF_STATUS wlan_vdev_mlme_is_init_state(struct wlan_objmgr_vdev *vdev) 328 { 329 enum wlan_vdev_state state; 330 331 state = wlan_vdev_mlme_get_state(vdev); 332 if (state == WLAN_VDEV_S_INIT) 333 return QDF_STATUS_SUCCESS; 334 335 return QDF_STATUS_E_FAILURE; 336 } 337 338 QDF_STATUS wlan_vdev_is_up_active_state(struct wlan_objmgr_vdev *vdev) 339 { 340 enum wlan_vdev_state state; 341 enum wlan_vdev_state substate; 342 343 state = wlan_vdev_mlme_get_state(vdev); 344 substate = wlan_vdev_mlme_get_substate(vdev); 345 if (state == WLAN_VDEV_S_UP && substate == WLAN_VDEV_SS_UP_ACTIVE) 346 return QDF_STATUS_SUCCESS; 347 348 return QDF_STATUS_E_FAILURE; 349 } 350 351 qdf_export_symbol(wlan_vdev_is_up_active_state); 352 353 #ifdef WLAN_FEATURE_11BE_MLO 354 bool 355 wlan_vdev_mlme_get_is_mlo_link(struct wlan_objmgr_psoc *psoc, 356 uint8_t vdev_id) 357 { 358 struct wlan_objmgr_vdev *vdev; 359 bool is_link = false; 360 361 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 362 WLAN_MLME_OBJMGR_ID); 363 if (!vdev) { 364 mlme_err("vdev object is NULL for vdev %d", vdev_id); 365 return is_link; 366 } 367 368 if (wlan_vdev_mlme_is_mlo_vdev(vdev) && 369 wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 370 is_link = true; 371 372 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 373 374 return is_link; 375 } 376 377 bool 378 wlan_vdev_mlme_get_is_mlo_vdev(struct wlan_objmgr_psoc *psoc, 379 uint8_t vdev_id) 380 { 381 struct wlan_objmgr_vdev *vdev; 382 bool is_mlo_vdev = false; 383 384 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 385 WLAN_MLME_OBJMGR_ID); 386 if (!vdev) { 387 mlme_err("vdev object is NULL for vdev %d", vdev_id); 388 return is_mlo_vdev; 389 } 390 391 if (wlan_vdev_mlme_is_mlo_vdev(vdev) && 392 !wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 393 is_mlo_vdev = true; 394 395 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 396 397 return is_mlo_vdev; 398 } 399 #endif 400 #ifdef WLAN_FEATURE_SR 401 void 402 wlan_mlme_update_sr_data(struct wlan_objmgr_vdev *vdev, int *val, 403 int32_t pd_threshold, bool is_sr_enable) 404 { 405 uint8_t non_srg_pd_threshold = 0, srg_pd_threshold = 0; 406 uint8_t srg_min_pd_threshold_offset, srg_max_pd_threshold_offset; 407 uint8_t sr_ctrl; 408 409 sr_ctrl = wlan_vdev_mlme_get_sr_ctrl(vdev); 410 if (!(sr_ctrl & NON_SRG_PD_SR_DISALLOWED) && 411 (sr_ctrl & NON_SRG_OFFSET_PRESENT)) { 412 non_srg_pd_threshold = 413 wlan_vdev_mlme_get_pd_offset(vdev) + NON_SR_PD_THRESHOLD_MIN; 414 /** 415 * Update non_srg_pd_threshold with provide 416 * pd_threshold, if pd threshold is with in the 417 * range else keep the same as advertised by AP. 418 */ 419 if (pd_threshold && non_srg_pd_threshold > pd_threshold) 420 non_srg_pd_threshold = pd_threshold; 421 422 /* 31st BIT - Enable/Disable Non-SRG based spatial reuse. */ 423 *val |= is_sr_enable << NON_SRG_SPR_ENABLE_POS; 424 } 425 426 if (sr_ctrl & SRG_INFO_PRESENT) { 427 wlan_vdev_mlme_get_srg_pd_offset(vdev, 428 &srg_max_pd_threshold_offset, 429 &srg_min_pd_threshold_offset); 430 /** 431 * Update rg_pd_threshold with provide 432 * pd_threshold, if pd threshold is with in the 433 * SRG range else keep the max of advertised by AP. 434 */ 435 if (pd_threshold && 436 pd_threshold < (srg_max_pd_threshold_offset + 437 NON_SR_PD_THRESHOLD_MIN) && 438 pd_threshold > (srg_min_pd_threshold_offset + 439 NON_SR_PD_THRESHOLD_MIN)) 440 srg_pd_threshold = pd_threshold + 441 NON_SR_PD_THRESHOLD_MIN; 442 else 443 srg_pd_threshold = srg_max_pd_threshold_offset + 444 NON_SR_PD_THRESHOLD_MIN; 445 446 /* 30th BIT - Enable/Disable SRG based spatial reuse. */ 447 *val |= is_sr_enable << SRG_SPR_ENABLE_POS; 448 } 449 450 /* bit | purpose 451 * ----------------- 452 * 0 - 7 | Param Value for non-SRG based Spatial Reuse 453 * 8 - 15| Param value for SRG based Spatial Reuse 454 * 29 | Param value is in dBm units rather than dB units 455 */ 456 *val |= 457 (uint8_t)(non_srg_pd_threshold << NON_SRG_MAX_PD_OFFSET_POS); 458 *val |= 459 (uint8_t)(srg_pd_threshold << SRG_THRESHOLD_MAX_PD_POS); 460 *val |= SR_PARAM_VAL_DBM_UNIT << SR_PARAM_VAL_DBM_POS; 461 } 462 #endif 463