xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mlme_api.c (revision 70a19e16789e308182f63b15c75decec7bf0b342)
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