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