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 30 struct vdev_mlme_obj *wlan_vdev_mlme_get_cmpt_obj(struct wlan_objmgr_vdev *vdev) 31 { 32 struct vdev_mlme_obj *vdev_mlme; 33 34 if (!vdev) { 35 mlme_err("vdev is NULL"); 36 return NULL; 37 } 38 39 vdev_mlme = wlan_objmgr_vdev_get_comp_private_obj(vdev, 40 WLAN_UMAC_COMP_MLME); 41 if (!vdev_mlme) { 42 mlme_err(" MLME component object is NULL"); 43 return NULL; 44 } 45 46 return vdev_mlme; 47 } 48 49 qdf_export_symbol(wlan_vdev_mlme_get_cmpt_obj); 50 51 void wlan_vdev_mlme_set_ext_hdl(struct wlan_objmgr_vdev *vdev, 52 mlme_vdev_ext_t *ext_hdl) 53 { 54 struct vdev_mlme_obj *vdev_mlme; 55 56 if (!ext_hdl) { 57 mlme_err("Invalid input"); 58 return; 59 } 60 61 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 62 if (vdev_mlme) 63 vdev_mlme->ext_vdev_ptr = ext_hdl; 64 } 65 66 qdf_export_symbol(wlan_vdev_mlme_set_ext_hdl); 67 68 mlme_vdev_ext_t *wlan_vdev_mlme_get_ext_hdl(struct wlan_objmgr_vdev *vdev) 69 { 70 struct vdev_mlme_obj *vdev_mlme; 71 72 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 73 if (vdev_mlme) 74 return vdev_mlme->ext_vdev_ptr; 75 76 return NULL; 77 } 78 79 qdf_export_symbol(wlan_vdev_mlme_get_ext_hdl); 80 81 QDF_STATUS wlan_vdev_mlme_sm_deliver_evt(struct wlan_objmgr_vdev *vdev, 82 enum wlan_vdev_sm_evt event, 83 uint16_t event_data_len, 84 void *event_data) 85 { 86 struct vdev_mlme_obj *vdev_mlme; 87 QDF_STATUS status; 88 enum wlan_vdev_state state_entry, state_exit; 89 enum wlan_vdev_state substate_entry, substate_exit; 90 91 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 92 if (!vdev_mlme) { 93 mlme_err("vdev component object is NULL"); 94 return QDF_STATUS_E_FAILURE; 95 } 96 97 mlme_vdev_sm_spin_lock(vdev_mlme); 98 99 /* store entry state and sub state for prints */ 100 state_entry = wlan_vdev_mlme_get_state(vdev); 101 substate_entry = wlan_vdev_mlme_get_substate(vdev); 102 mlme_vdev_sm_print_state_event(vdev_mlme, event); 103 104 status = mlme_vdev_sm_deliver_event(vdev_mlme, event, event_data_len, 105 event_data); 106 /* Take exit state, exit substate for prints */ 107 state_exit = wlan_vdev_mlme_get_state(vdev); 108 substate_exit = wlan_vdev_mlme_get_substate(vdev); 109 /* If no state and substate change, don't print */ 110 if (!((state_entry == state_exit) && (substate_entry == substate_exit))) 111 mlme_vdev_sm_print_state(vdev_mlme); 112 mlme_vdev_sm_spin_unlock(vdev_mlme); 113 114 return status; 115 } 116 117 qdf_export_symbol(wlan_vdev_mlme_sm_deliver_evt); 118 119 QDF_STATUS wlan_vdev_mlme_sm_deliver_evt_sync(struct wlan_objmgr_vdev *vdev, 120 enum wlan_vdev_sm_evt event, 121 uint16_t event_data_len, 122 void *event_data) 123 { 124 struct vdev_mlme_obj *vdev_mlme; 125 QDF_STATUS status; 126 127 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 128 if (!vdev_mlme) { 129 mlme_err("vdev component object is NULL"); 130 return QDF_STATUS_E_FAILURE; 131 } 132 133 status = mlme_vdev_sm_deliver_event(vdev_mlme, event, event_data_len, 134 event_data); 135 136 return status; 137 } 138 139 qdf_export_symbol(wlan_vdev_mlme_sm_deliver_evt_sync); 140 141 #ifdef SM_ENG_HIST_ENABLE 142 void wlan_vdev_mlme_sm_history_print(struct wlan_objmgr_vdev *vdev) 143 { 144 struct vdev_mlme_obj *vdev_mlme; 145 146 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 147 if (!vdev_mlme) { 148 mlme_err("vdev component object is NULL"); 149 return; 150 } 151 152 mlme_vdev_sm_history_print(vdev_mlme); 153 } 154 #endif 155 156 QDF_STATUS wlan_vdev_allow_connect_n_tx(struct wlan_objmgr_vdev *vdev) 157 { 158 enum wlan_vdev_state state; 159 enum wlan_vdev_state substate; 160 161 state = wlan_vdev_mlme_get_state(vdev); 162 substate = wlan_vdev_mlme_get_substate(vdev); 163 if ((state == WLAN_VDEV_S_UP && substate == WLAN_VDEV_SS_UP_ACTIVE) || 164 ((state == WLAN_VDEV_S_SUSPEND) && 165 (substate == WLAN_VDEV_SS_SUSPEND_CSA_RESTART))) 166 return QDF_STATUS_SUCCESS; 167 168 return QDF_STATUS_E_FAILURE; 169 } 170 171 QDF_STATUS wlan_vdev_mlme_is_active(struct wlan_objmgr_vdev *vdev) 172 { 173 enum wlan_vdev_state state; 174 175 state = wlan_vdev_mlme_get_state(vdev); 176 if ((state == WLAN_VDEV_S_UP) || (state == WLAN_VDEV_S_DFS_CAC_WAIT) || 177 (state == WLAN_VDEV_S_SUSPEND)) 178 return QDF_STATUS_SUCCESS; 179 180 return QDF_STATUS_E_FAILURE; 181 } 182 183 qdf_export_symbol(wlan_vdev_mlme_is_active); 184 185 QDF_STATUS wlan_vdev_chan_config_valid(struct wlan_objmgr_vdev *vdev) 186 { 187 enum wlan_vdev_state state; 188 enum wlan_vdev_state substate; 189 190 state = wlan_vdev_mlme_get_state(vdev); 191 substate = wlan_vdev_mlme_get_substate(vdev); 192 if (!((state == WLAN_VDEV_S_INIT) || (state == WLAN_VDEV_S_STOP))) 193 return QDF_STATUS_SUCCESS; 194 195 return QDF_STATUS_E_FAILURE; 196 } 197 198 qdf_export_symbol(wlan_vdev_chan_config_valid); 199 200 QDF_STATUS wlan_vdev_mlme_is_csa_restart(struct wlan_objmgr_vdev *vdev) 201 { 202 enum wlan_vdev_state state; 203 enum wlan_vdev_state substate; 204 205 state = wlan_vdev_mlme_get_state(vdev); 206 substate = wlan_vdev_mlme_get_substate(vdev); 207 if ((state == WLAN_VDEV_S_SUSPEND) && 208 (substate == WLAN_VDEV_SS_SUSPEND_CSA_RESTART)) 209 return QDF_STATUS_SUCCESS; 210 211 return QDF_STATUS_E_FAILURE; 212 } 213 214 qdf_export_symbol(wlan_vdev_mlme_is_csa_restart); 215 216 QDF_STATUS wlan_vdev_is_going_down(struct wlan_objmgr_vdev *vdev) 217 { 218 enum wlan_vdev_state state; 219 enum wlan_vdev_state substate; 220 221 state = wlan_vdev_mlme_get_state(vdev); 222 substate = wlan_vdev_mlme_get_substate(vdev); 223 if ((state == WLAN_VDEV_S_STOP) || 224 ((state == WLAN_VDEV_S_SUSPEND) && 225 (substate == WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN))) 226 return QDF_STATUS_SUCCESS; 227 228 return QDF_STATUS_E_FAILURE; 229 } 230 231 QDF_STATUS wlan_vdev_is_mlo_peer_create_allowed(struct wlan_objmgr_vdev *vdev) 232 { 233 enum wlan_vdev_state state; 234 enum wlan_vdev_state substate; 235 bool acs_in_progress; 236 QDF_STATUS ret; 237 238 if (!vdev) { 239 mlme_err("vdev is null"); 240 return QDF_STATUS_E_FAILURE; 241 } 242 243 state = wlan_vdev_mlme_get_state(vdev); 244 substate = wlan_vdev_mlme_get_substate(vdev); 245 246 acs_in_progress = false; 247 ret = mlme_ext_hdl_get_acs_in_progress(vdev, &acs_in_progress); 248 if (ret != QDF_STATUS_SUCCESS) { 249 mlme_err("Unable to get ACS in progress status"); 250 return QDF_STATUS_E_FAILURE; 251 } 252 253 if (!acs_in_progress) 254 if ((state == WLAN_VDEV_S_UP) || 255 ((state == WLAN_VDEV_S_SUSPEND) && 256 (substate == WLAN_VDEV_SS_SUSPEND_CSA_RESTART)) || 257 (state == WLAN_VDEV_S_DFS_CAC_WAIT)) 258 return QDF_STATUS_SUCCESS; 259 260 return QDF_STATUS_E_FAILURE; 261 } 262 263 QDF_STATUS wlan_vdev_is_restart_progress(struct wlan_objmgr_vdev *vdev) 264 { 265 enum wlan_vdev_state state; 266 enum wlan_vdev_state substate; 267 268 state = wlan_vdev_mlme_get_state(vdev); 269 substate = wlan_vdev_mlme_get_substate(vdev); 270 if ((state == WLAN_VDEV_S_START) && 271 (substate == WLAN_VDEV_SS_START_RESTART_PROGRESS)) 272 return QDF_STATUS_SUCCESS; 273 274 return QDF_STATUS_E_FAILURE; 275 } 276 277 QDF_STATUS wlan_vdev_is_dfs_cac_wait(struct wlan_objmgr_vdev *vdev) 278 { 279 if (wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_DFS_CAC_WAIT) 280 return QDF_STATUS_SUCCESS; 281 282 return QDF_STATUS_E_FAILURE; 283 } 284 285 void wlan_vdev_mlme_cmd_lock(struct wlan_objmgr_vdev *vdev) 286 { 287 struct vdev_mlme_obj *vdev_mlme; 288 289 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 290 if (!vdev_mlme) { 291 mlme_err("vdev component object is NULL"); 292 return; 293 } 294 295 mlme_vdev_cmd_mutex_acquire(vdev_mlme); 296 } 297 298 void wlan_vdev_mlme_cmd_unlock(struct wlan_objmgr_vdev *vdev) 299 { 300 struct vdev_mlme_obj *vdev_mlme; 301 302 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 303 if (!vdev_mlme) { 304 mlme_err("vdev component object is NULL"); 305 return; 306 } 307 308 mlme_vdev_cmd_mutex_release(vdev_mlme); 309 } 310 311 QDF_STATUS wlan_vdev_mlme_is_scan_allowed(struct wlan_objmgr_vdev *vdev) 312 { 313 enum wlan_vdev_state state; 314 enum wlan_vdev_state substate; 315 316 state = wlan_vdev_mlme_get_state(vdev); 317 substate = wlan_vdev_mlme_get_substate(vdev); 318 if ((state == WLAN_VDEV_S_INIT) || 319 (state == WLAN_VDEV_S_UP && substate == WLAN_VDEV_SS_UP_ACTIVE) || 320 (state == WLAN_VDEV_S_STOP)) 321 return QDF_STATUS_SUCCESS; 322 323 return QDF_STATUS_E_FAILURE; 324 } 325 326 QDF_STATUS wlan_vdev_mlme_is_init_state(struct wlan_objmgr_vdev *vdev) 327 { 328 enum wlan_vdev_state state; 329 330 state = wlan_vdev_mlme_get_state(vdev); 331 if (state == WLAN_VDEV_S_INIT) 332 return QDF_STATUS_SUCCESS; 333 334 return QDF_STATUS_E_FAILURE; 335 } 336 337 QDF_STATUS wlan_vdev_is_up_active_state(struct wlan_objmgr_vdev *vdev) 338 { 339 enum wlan_vdev_state state; 340 enum wlan_vdev_state substate; 341 342 state = wlan_vdev_mlme_get_state(vdev); 343 substate = wlan_vdev_mlme_get_substate(vdev); 344 if (state == WLAN_VDEV_S_UP && substate == WLAN_VDEV_SS_UP_ACTIVE) 345 return QDF_STATUS_SUCCESS; 346 347 return QDF_STATUS_E_FAILURE; 348 } 349 350 qdf_export_symbol(wlan_vdev_is_up_active_state); 351 352 #ifdef WLAN_FEATURE_11BE_MLO 353 bool 354 wlan_vdev_mlme_get_is_mlo_link(struct wlan_objmgr_psoc *psoc, 355 uint8_t vdev_id) 356 { 357 struct wlan_objmgr_vdev *vdev; 358 bool is_link = false; 359 360 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 361 WLAN_MLME_OBJMGR_ID); 362 if (!vdev) { 363 mlme_err("vdev object is NULL for vdev %d", vdev_id); 364 return is_link; 365 } 366 367 if (wlan_vdev_mlme_is_mlo_vdev(vdev) && 368 wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 369 is_link = true; 370 371 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 372 373 return is_link; 374 } 375 376 bool 377 wlan_vdev_mlme_get_is_mlo_vdev(struct wlan_objmgr_psoc *psoc, 378 uint8_t vdev_id) 379 { 380 struct wlan_objmgr_vdev *vdev; 381 bool is_mlo_vdev = false; 382 383 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 384 WLAN_MLME_OBJMGR_ID); 385 if (!vdev) { 386 mlme_err("vdev object is NULL for vdev %d", vdev_id); 387 return is_mlo_vdev; 388 } 389 390 if (wlan_vdev_mlme_is_mlo_vdev(vdev) && 391 !wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 392 is_mlo_vdev = true; 393 394 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 395 396 return is_mlo_vdev; 397 } 398 #endif 399