xref: /wlan-driver/qcacld-3.0/components/cmn_services/interface_mgr/src/wlan_if_mgr_roam.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 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: contains interface manager roam public api
20  */
21 #include "wlan_objmgr_psoc_obj.h"
22 #include "wlan_objmgr_pdev_obj.h"
23 #include "wlan_objmgr_vdev_obj.h"
24 #include "wlan_policy_mgr_api.h"
25 #include "wlan_policy_mgr_i.h"
26 #include "wlan_if_mgr_roam.h"
27 #include "wlan_if_mgr_public_struct.h"
28 #include "wlan_cm_roam_api.h"
29 #include "wlan_if_mgr_main.h"
30 #include "wlan_p2p_ucfg_api.h"
31 #include "cds_api.h"
32 #include "sme_api.h"
33 #include "wlan_vdev_mgr_utils_api.h"
34 #include "wni_api.h"
35 #include "wlan_mlme_vdev_mgr_interface.h"
36 #include "wlan_cm_api.h"
37 #include "wlan_scan_api.h"
38 #include "wlan_mlo_mgr_roam.h"
39 #include "wlan_mlo_mgr_sta.h"
40 #include "wlan_mlo_mgr_link_switch.h"
41 #include <wlan_action_oui_main.h>
42 
43 
44 #ifdef WLAN_FEATURE_11BE_MLO
45 static inline bool
if_mgr_is_assoc_link_of_vdev(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,uint8_t cur_vdev_id)46 if_mgr_is_assoc_link_of_vdev(struct wlan_objmgr_pdev *pdev,
47 			     struct wlan_objmgr_vdev *vdev,
48 			     uint8_t cur_vdev_id)
49 {
50 	struct wlan_objmgr_vdev *cur_vdev, *assoc_vdev;
51 
52 	cur_vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, cur_vdev_id,
53 							WLAN_IF_MGR_ID);
54 	if (!cur_vdev)
55 		return false;
56 
57 	assoc_vdev = wlan_mlo_get_assoc_link_vdev(cur_vdev);
58 
59 	wlan_objmgr_vdev_release_ref(cur_vdev, WLAN_IF_MGR_ID);
60 	if (vdev == assoc_vdev)
61 		return true;
62 
63 	return false;
64 }
65 #else
66 static inline bool
if_mgr_is_assoc_link_of_vdev(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,uint8_t cur_vdev_id)67 if_mgr_is_assoc_link_of_vdev(struct wlan_objmgr_pdev *pdev,
68 			     struct wlan_objmgr_vdev *vdev,
69 			     uint8_t cur_vdev_id)
70 {
71 	return false;
72 }
73 #endif
74 
if_mgr_enable_roaming_on_vdev(struct wlan_objmgr_pdev * pdev,void * object,void * arg)75 static void if_mgr_enable_roaming_on_vdev(struct wlan_objmgr_pdev *pdev,
76 					  void *object, void *arg)
77 {
78 	struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
79 	struct change_roam_state_arg *roam_arg = arg;
80 	uint8_t vdev_id, curr_vdev_id;
81 
82 	vdev_id = wlan_vdev_get_id(vdev);
83 	curr_vdev_id = roam_arg->curr_vdev_id;
84 
85 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)
86 		return;
87 
88 	if (wlan_vdev_mlme_is_mlo_link_vdev(vdev) ||
89 	    if_mgr_is_assoc_link_of_vdev(pdev, vdev, curr_vdev_id))
90 		return;
91 
92 	if (curr_vdev_id != vdev_id &&
93 	    vdev->vdev_mlme.mlme_state == WLAN_VDEV_S_UP) {
94 		ifmgr_debug("Enable roaming for vdev_id %d", vdev_id);
95 		wlan_cm_enable_rso(pdev, vdev_id,
96 				   roam_arg->requestor,
97 				   REASON_DRIVER_ENABLED);
98 	}
99 }
100 
if_mgr_enable_roaming(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,enum wlan_cm_rso_control_requestor requestor)101 QDF_STATUS if_mgr_enable_roaming(struct wlan_objmgr_pdev *pdev,
102 				 struct wlan_objmgr_vdev *vdev,
103 				 enum wlan_cm_rso_control_requestor requestor)
104 {
105 	QDF_STATUS status = QDF_STATUS_SUCCESS;
106 	struct change_roam_state_arg roam_arg;
107 	uint8_t vdev_id;
108 
109 	vdev_id = wlan_vdev_get_id(vdev);
110 
111 	roam_arg.requestor = requestor;
112 	roam_arg.curr_vdev_id = vdev_id;
113 
114 	status = wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
115 						if_mgr_enable_roaming_on_vdev,
116 						&roam_arg, 0,
117 						WLAN_IF_MGR_ID);
118 
119 	return status;
120 }
121 
if_mgr_disable_roaming_on_vdev(struct wlan_objmgr_pdev * pdev,void * object,void * arg)122 static void if_mgr_disable_roaming_on_vdev(struct wlan_objmgr_pdev *pdev,
123 					   void *object, void *arg)
124 {
125 	struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
126 	struct change_roam_state_arg *roam_arg = arg;
127 	uint8_t vdev_id, curr_vdev_id;
128 
129 	vdev_id = wlan_vdev_get_id(vdev);
130 	curr_vdev_id = roam_arg->curr_vdev_id;
131 
132 	if (curr_vdev_id == vdev_id ||
133 	    wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE ||
134 	    wlan_cm_is_vdev_roam_sync_inprogress(vdev) ||
135 	    vdev->vdev_mlme.mlme_state != WLAN_VDEV_S_UP)
136 		return;
137 
138 	/*
139 	 * Disable roaming only for the STA vdev which is not is roam sync state
140 	 * and VDEV is in UP state.
141 	 */
142 	ifmgr_debug("Roaming disabled on vdev_id %d", vdev_id);
143 	wlan_cm_disable_rso(pdev, vdev_id, roam_arg->requestor,
144 			    REASON_DRIVER_DISABLED);
145 }
146 
if_mgr_disable_roaming(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,enum wlan_cm_rso_control_requestor requestor)147 QDF_STATUS if_mgr_disable_roaming(struct wlan_objmgr_pdev *pdev,
148 				  struct wlan_objmgr_vdev *vdev,
149 				  enum wlan_cm_rso_control_requestor requestor)
150 {
151 	QDF_STATUS status = QDF_STATUS_SUCCESS;
152 	struct change_roam_state_arg roam_arg;
153 	uint8_t vdev_id;
154 
155 	vdev_id = wlan_vdev_get_id(vdev);
156 
157 	roam_arg.requestor = requestor;
158 	roam_arg.curr_vdev_id = vdev_id;
159 
160 	status = wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
161 						if_mgr_disable_roaming_on_vdev,
162 						&roam_arg, 0,
163 						WLAN_IF_MGR_ID);
164 
165 	return status;
166 }
167 
168 QDF_STATUS
if_mgr_enable_roaming_on_connected_sta(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev)169 if_mgr_enable_roaming_on_connected_sta(struct wlan_objmgr_pdev *pdev,
170 				       struct wlan_objmgr_vdev *vdev)
171 {
172 	struct wlan_objmgr_psoc *psoc;
173 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
174 
175 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)
176 		return QDF_STATUS_E_FAILURE;
177 
178 	/*
179 	 * When link switch is in progress, don't send RSO Enable before vdev
180 	 * is up. RSO Enable will be sent as part of install keys once
181 	 * link switch connect sequence is complete.
182 	 */
183 	if (mlo_mgr_is_link_switch_in_progress(vdev))
184 		return QDF_STATUS_SUCCESS;
185 
186 	psoc = wlan_vdev_get_psoc(vdev);
187 	if (!psoc)
188 		return QDF_STATUS_E_FAILURE;
189 
190 	if (policy_mgr_is_sta_active_connection_exists(psoc) &&
191 	    mlo_is_enable_roaming_on_connected_sta_allowed(vdev)) {
192 		wlan_cm_enable_roaming_on_connected_sta(pdev, vdev_id);
193 		policy_mgr_set_pcl_for_connected_vdev(psoc, vdev_id, true);
194 	}
195 
196 	return QDF_STATUS_SUCCESS;
197 }
198 
if_mgr_enable_roaming_after_p2p_disconnect(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,enum wlan_cm_rso_control_requestor requestor)199 QDF_STATUS if_mgr_enable_roaming_after_p2p_disconnect(
200 				struct wlan_objmgr_pdev *pdev,
201 				struct wlan_objmgr_vdev *vdev,
202 				enum wlan_cm_rso_control_requestor requestor)
203 {
204 	QDF_STATUS status = QDF_STATUS_SUCCESS;
205 	struct wlan_objmgr_psoc *psoc;
206 	struct change_roam_state_arg roam_arg;
207 	uint8_t vdev_id;
208 
209 	psoc = wlan_vdev_get_psoc(vdev);
210 	if (!psoc)
211 		return QDF_STATUS_E_FAILURE;
212 
213 	vdev_id = wlan_vdev_get_id(vdev);
214 
215 	roam_arg.requestor = requestor;
216 	roam_arg.curr_vdev_id = vdev_id;
217 
218 	/*
219 	 * Due to audio share glitch with P2P clients due
220 	 * to roam scan on concurrent interface, disable
221 	 * roaming if "p2p_disable_roam" ini is enabled.
222 	 * Re-enable roaming again once the p2p client
223 	 * gets disconnected.
224 	 */
225 	if (ucfg_p2p_is_roam_config_disabled(psoc) &&
226 	    wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE) {
227 		ifmgr_debug("P2P client disconnected, enable roam");
228 		status = wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
229 					      if_mgr_enable_roaming_on_vdev,
230 					      &roam_arg, 0,
231 					      WLAN_IF_MGR_ID);
232 	}
233 
234 	return status;
235 }
236 
237 /**
238  * if_mgr_calculate_mcc_beacon_interval() - Calculates the new beacon interval
239  * @sta_bi: station beacon interval
240  * @go_given_bi: P2P GO's given beacon interval
241  *
242  * This function has 3 stages. First it modifies the input go_given_bi to be
243  * within 100 to 199. Then it checks if the sta_bi and go_given_bi are multiples
244  * of each other. If they are, that means the 2 values are compatible, and just
245  * return as is, otherwise, find new compatible BI for P2P GO
246  *
247  * Return: valid beacon interval value
248  */
if_mgr_calculate_mcc_beacon_interval(uint16_t sta_bi,uint16_t go_given_bi)249 static uint16_t if_mgr_calculate_mcc_beacon_interval(uint16_t sta_bi,
250 						     uint16_t go_given_bi)
251 {
252 	uint8_t num_beacons, is_multiple;
253 	uint16_t go_calculated_bi, go_final_bi, sta_calculated_bi;
254 
255 	/* ensure BI ranges between 100 and 200 */
256 	if (go_given_bi < 100)
257 		go_calculated_bi = 100;
258 	else
259 		go_calculated_bi = 100 + (go_given_bi % 100);
260 
261 	if (sta_bi == 0) {
262 		/* There is possibility to receive zero as value.
263 		 * Which will cause divide by zero. Hence initialise with 100
264 		 */
265 		sta_bi = 100;
266 		ifmgr_warn("sta_bi 2nd parameter is zero, initialize to %d",
267 			   sta_bi);
268 	}
269 	/* check, if either one is multiple of another */
270 	if (sta_bi > go_calculated_bi)
271 		is_multiple = !(sta_bi % go_calculated_bi);
272 	else
273 		is_multiple = !(go_calculated_bi % sta_bi);
274 
275 	/* if it is multiple, then accept GO's beacon interval
276 	 * range [100,199] as it is
277 	 */
278 	if (is_multiple)
279 		return go_calculated_bi;
280 
281 	/* else , if it is not multiple, then then check for number of beacons
282 	 * to be inserted based on sta BI
283 	 */
284 	num_beacons = sta_bi / 100;
285 	if (num_beacons) {
286 		/* GO's final beacon interval will be aligned to sta beacon
287 		 * interval, but in the range of [100, 199].
288 		 */
289 		sta_calculated_bi = sta_bi / num_beacons;
290 		go_final_bi = sta_calculated_bi;
291 	} else {
292 		/* if STA beacon interval is less than 100, use GO's change
293 		 * beacon interval instead of updating to STA's beacon interval.
294 		 */
295 		go_final_bi = go_calculated_bi;
296 	}
297 
298 	return go_final_bi;
299 }
300 
301 static QDF_STATUS
if_mgr_send_chng_mcc_beacon_interval(struct wlan_objmgr_vdev * vdev,struct beacon_interval_arg * bss_arg)302 if_mgr_send_chng_mcc_beacon_interval(struct wlan_objmgr_vdev *vdev,
303 				     struct beacon_interval_arg *bss_arg)
304 {
305 	struct scheduler_msg msg = {0};
306 	struct wlan_change_bi *p_msg;
307 	uint16_t len = 0;
308 	QDF_STATUS status;
309 	uint8_t *mac_addr;
310 
311 	if (!bss_arg->update_beacon_interval)
312 		return QDF_STATUS_SUCCESS;
313 
314 	bss_arg->update_beacon_interval = false;
315 
316 	len = sizeof(*p_msg);
317 	p_msg = qdf_mem_malloc(len);
318 	if (!p_msg)
319 		return QDF_STATUS_E_NOMEM;
320 
321 	p_msg->message_type = eWNI_SME_CHNG_MCC_BEACON_INTERVAL;
322 	p_msg->length = len;
323 
324 	mac_addr = wlan_vdev_get_hw_macaddr(vdev);
325 	qdf_mem_copy(&p_msg->bssid, mac_addr, QDF_MAC_ADDR_SIZE);
326 	ifmgr_debug(QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(mac_addr));
327 	p_msg->session_id = wlan_vdev_get_id(vdev);
328 	ifmgr_debug("session %d BeaconInterval %d", p_msg->session_id,
329 			bss_arg->bss_beacon_interval);
330 	p_msg->beacon_interval = bss_arg->bss_beacon_interval;
331 
332 	msg.type = eWNI_SME_CHNG_MCC_BEACON_INTERVAL;
333 	msg.bodyval = 0;
334 	msg.bodyptr = p_msg;
335 
336 	status = scheduler_post_message(QDF_MODULE_ID_PE,
337 					QDF_MODULE_ID_PE,
338 					QDF_MODULE_ID_PE, &msg);
339 
340 	if (status != QDF_STATUS_SUCCESS)
341 		qdf_mem_free(p_msg);
342 
343 	return status;
344 }
345 
if_mgr_update_beacon_interval(struct wlan_objmgr_pdev * pdev,void * object,void * arg)346 static void if_mgr_update_beacon_interval(struct wlan_objmgr_pdev *pdev,
347 					  void *object, void *arg)
348 {
349 	struct wlan_objmgr_psoc *psoc;
350 	uint8_t allow_mcc_go_diff_bi;
351 	struct wlan_objmgr_peer *peer;
352 	enum wlan_peer_type bss_persona;
353 	struct beacon_interval_arg *bss_arg = arg;
354 	struct wlan_objmgr_vdev *vdev = object;
355 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
356 
357 	psoc = wlan_pdev_get_psoc(pdev);
358 	if (!psoc)
359 		return;
360 
361 	policy_mgr_get_allow_mcc_go_diff_bi(psoc, &allow_mcc_go_diff_bi);
362 
363 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_IF_MGR_ID);
364 	if (!peer)
365 		return;
366 
367 	bss_persona = wlan_peer_get_peer_type(peer);
368 
369 	wlan_objmgr_peer_release_ref(peer, WLAN_IF_MGR_ID);
370 
371 	/*
372 	 * If GO in MCC support different beacon interval,
373 	 * change the BI of the P2P-GO
374 	 */
375 	if (bss_persona == WLAN_PEER_P2P_GO)
376 		return;
377 	/*
378 	 * Handle different BI scenario based on the
379 	 * configuration set. If Config is not set to 0x04 then
380 	 * Disconnect all the P2P clients associated. If config
381 	 * is set to 0x04 then update the BI without
382 	 * disconnecting all the clients
383 	 */
384 	if (allow_mcc_go_diff_bi == ALLOW_MCC_GO_DIFF_BI_NO_DISCONNECT &&
385 	    bss_arg->update_beacon_interval) {
386 		bss_arg->status =
387 			if_mgr_send_chng_mcc_beacon_interval(vdev, bss_arg);
388 		return;
389 	} else if (bss_arg->update_beacon_interval) {
390 		/*
391 		 * If the configuration of fAllowMCCGODiffBI is set to
392 		 * other than 0x04
393 		 */
394 		bss_arg->status = wlan_sap_disconnect_all_p2p_client(vdev_id);
395 		return;
396 	}
397 }
398 
399 static QDF_STATUS
if_mgr_update_mcc_p2p_beacon_interval(struct wlan_objmgr_vdev * vdev,struct beacon_interval_arg * bss_arg)400 if_mgr_update_mcc_p2p_beacon_interval(struct wlan_objmgr_vdev *vdev,
401 				      struct beacon_interval_arg *bss_arg)
402 {
403 	struct wlan_objmgr_psoc *psoc;
404 	struct wlan_objmgr_pdev *pdev;
405 	uint8_t enable_mcc_mode;
406 
407 	pdev = wlan_vdev_get_pdev(vdev);
408 	if (!pdev)
409 		return QDF_STATUS_E_FAILURE;
410 
411 	psoc = wlan_pdev_get_psoc(pdev);
412 	if (!psoc)
413 		return QDF_STATUS_E_FAILURE;
414 
415 	/* If MCC is not supported just break and return SUCCESS */
416 	wlan_mlme_get_mcc_feature(psoc, &enable_mcc_mode);
417 	if (!enable_mcc_mode)
418 		return QDF_STATUS_E_FAILURE;
419 
420 	wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
421 					  if_mgr_update_beacon_interval,
422 					  bss_arg, 0, WLAN_IF_MGR_ID);
423 
424 	return bss_arg->status;
425 }
426 
if_mgr_validate_sta_bcn_intrvl(struct wlan_objmgr_vdev * vdev,struct beacon_interval_arg * bss_arg)427 static bool if_mgr_validate_sta_bcn_intrvl(struct wlan_objmgr_vdev *vdev,
428 					   struct beacon_interval_arg *bss_arg)
429 {
430 	struct wlan_objmgr_psoc *psoc;
431 	struct vdev_mlme_obj *vdev_mlme;
432 	struct wlan_objmgr_peer *peer;
433 	uint16_t new_bcn_interval;
434 	uint32_t beacon_interval;
435 	struct wlan_channel *chan;
436 	enum QDF_OPMODE curr_persona;
437 	uint8_t allow_mcc_go_diff_bi;
438 	uint8_t conc_rule1 = 0, conc_rule2 = 0;
439 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
440 
441 	psoc = wlan_vdev_get_psoc(vdev);
442 	if (!psoc)
443 		return false;
444 
445 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_IF_MGR_ID);
446 	if (!peer)
447 		return false;
448 
449 	curr_persona = wlan_vdev_mlme_get_opmode(vdev);
450 
451 	wlan_objmgr_peer_release_ref(peer, WLAN_IF_MGR_ID);
452 
453 	if (curr_persona == QDF_STA_MODE ||
454 	    curr_persona == QDF_P2P_CLIENT_MODE) {
455 		ifmgr_debug("Bcn Intrvl validation not require for STA/CLIENT");
456 		return false;
457 	}
458 
459 	chan = wlan_vdev_get_active_channel(vdev);
460 	if (!chan) {
461 		ifmgr_err("failed to get active channel");
462 		return false;
463 	}
464 
465 	vdev_mlme =
466 		wlan_objmgr_vdev_get_comp_private_obj(vdev,
467 						      WLAN_UMAC_COMP_MLME);
468 	if (!vdev_mlme) {
469 		QDF_ASSERT(0);
470 		return false;
471 	}
472 
473 	wlan_util_vdev_mlme_get_param(vdev_mlme, WLAN_MLME_CFG_BEACON_INTERVAL,
474 				      &beacon_interval);
475 
476 	if (curr_persona == QDF_SAP_MODE &&
477 	    (chan->ch_cfreq1 != bss_arg->ch_freq ||
478 	     chan->ch_cfreq2 != bss_arg->ch_freq)) {
479 		ifmgr_debug("*** MCC with SAP+STA sessions ****");
480 		bss_arg->status = QDF_STATUS_SUCCESS;
481 		return true;
482 	}
483 
484 	if (curr_persona == QDF_P2P_GO_MODE &&
485 	    (chan->ch_cfreq1 != bss_arg->ch_freq ||
486 	     chan->ch_cfreq2 != bss_arg->ch_freq) &&
487 	    beacon_interval != bss_arg->bss_beacon_interval) {
488 		policy_mgr_get_allow_mcc_go_diff_bi(psoc,
489 						    &allow_mcc_go_diff_bi);
490 
491 		switch (allow_mcc_go_diff_bi) {
492 		case ALLOW_MCC_GO_DIFF_BI_WFA_CERT:
493 			bss_arg->status = QDF_STATUS_SUCCESS;
494 			return true;
495 		case ALLOW_MCC_GO_DIFF_BI_WORKAROUND:
496 			fallthrough;
497 		case ALLOW_MCC_GO_DIFF_BI_NO_DISCONNECT:
498 			policy_mgr_get_conc_rule1(psoc, &conc_rule1);
499 			policy_mgr_get_conc_rule2(psoc, &conc_rule2);
500 			if (conc_rule1 || conc_rule2)
501 				new_bcn_interval = CUSTOM_CONC_GO_BI;
502 			else
503 				new_bcn_interval =
504 					if_mgr_calculate_mcc_beacon_interval(
505 						bss_arg->bss_beacon_interval,
506 						beacon_interval);
507 
508 			ifmgr_debug("Peer AP BI : %d, new Beacon Interval: %d",
509 				    bss_arg->bss_beacon_interval,
510 				    new_bcn_interval);
511 
512 			/* Update the beacon interval */
513 			if (new_bcn_interval != beacon_interval) {
514 				ifmgr_err("Beacon Interval got changed config used: %d",
515 					  allow_mcc_go_diff_bi);
516 				bss_arg->bss_beacon_interval = new_bcn_interval;
517 				bss_arg->update_beacon_interval = true;
518 				bss_arg->status =
519 					if_mgr_update_mcc_p2p_beacon_interval(
520 								vdev,
521 								bss_arg);
522 				return true;
523 			}
524 			bss_arg->status = QDF_STATUS_SUCCESS;
525 			return true;
526 		case ALLOW_MCC_GO_DIFF_BI_TEAR_DOWN:
527 			bss_arg->update_beacon_interval = false;
528 			bss_arg->status = wlan_sap_stop_bss(vdev_id);
529 			return true;
530 		default:
531 			ifmgr_err("BcnIntrvl is diff can't connect to preferred AP");
532 			bss_arg->status = QDF_STATUS_E_FAILURE;
533 			return true;
534 		}
535 	}
536 	return false;
537 }
538 
if_mgr_validate_p2pcli_bcn_intrvl(struct wlan_objmgr_vdev * vdev,struct beacon_interval_arg * bss_arg)539 static bool if_mgr_validate_p2pcli_bcn_intrvl(struct wlan_objmgr_vdev *vdev,
540 				       struct beacon_interval_arg *bss_arg)
541 {
542 	enum QDF_OPMODE curr_persona;
543 	enum wlan_peer_type bss_persona;
544 	uint32_t beacon_interval;
545 	struct wlan_channel *chan;
546 	struct wlan_objmgr_peer *peer;
547 	struct vdev_mlme_obj *vdev_mlme;
548 
549 	curr_persona = wlan_vdev_mlme_get_opmode(vdev);
550 
551 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_IF_MGR_ID);
552 	if (!peer)
553 		return false;
554 
555 	bss_persona = wlan_peer_get_peer_type(peer);
556 
557 	wlan_objmgr_peer_release_ref(peer, WLAN_IF_MGR_ID);
558 
559 	chan = wlan_vdev_get_active_channel(vdev);
560 	if (!chan) {
561 		ifmgr_err("failed to get active channel");
562 		return false;
563 	}
564 
565 	vdev_mlme =
566 		wlan_objmgr_vdev_get_comp_private_obj(vdev,
567 						      WLAN_UMAC_COMP_MLME);
568 	if (!vdev_mlme) {
569 		QDF_ASSERT(0);
570 		return false;
571 	}
572 
573 	wlan_util_vdev_mlme_get_param(vdev_mlme, WLAN_MLME_CFG_BEACON_INTERVAL,
574 				      &beacon_interval);
575 
576 	if (curr_persona == QDF_STA_MODE) {
577 		ifmgr_debug("Ignore Beacon Interval Validation...");
578 	} else if (bss_persona == WLAN_PEER_P2P_GO) {
579 		if ((chan->ch_cfreq1 != bss_arg->ch_freq ||
580 		     chan->ch_cfreq2 != bss_arg->ch_freq) &&
581 		    beacon_interval != bss_arg->bss_beacon_interval) {
582 			ifmgr_err("BcnIntrvl is diff can't connect to P2P_GO network");
583 			bss_arg->status = QDF_STATUS_E_FAILURE;
584 			return true;
585 		}
586 	}
587 
588 	return false;
589 }
590 
591 static bool
if_mgr_validate_p2pgo_bcn_intrvl(struct wlan_objmgr_vdev * vdev,struct beacon_interval_arg * bss_arg)592 if_mgr_validate_p2pgo_bcn_intrvl(struct wlan_objmgr_vdev *vdev,
593 				 struct beacon_interval_arg *bss_arg)
594 {
595 	struct wlan_objmgr_psoc *psoc;
596 	struct vdev_mlme_obj *vdev_mlme;
597 	enum QDF_OPMODE curr_persona;
598 	uint32_t beacon_interval;
599 	struct wlan_channel *chan;
600 	uint8_t conc_rule1 = 0, conc_rule2 = 0;
601 	uint16_t new_bcn_interval;
602 
603 	curr_persona = wlan_vdev_mlme_get_opmode(vdev);
604 
605 	chan = wlan_vdev_get_active_channel(vdev);
606 	if (!chan) {
607 		ifmgr_err("failed to get active channel");
608 		return false;
609 	}
610 
611 	vdev_mlme =
612 		wlan_objmgr_vdev_get_comp_private_obj(vdev,
613 						      WLAN_UMAC_COMP_MLME);
614 	if (!vdev_mlme) {
615 		QDF_ASSERT(0);
616 		return false;
617 	}
618 
619 	psoc = wlan_vdev_get_psoc(vdev);
620 	if (!psoc)
621 		return false;
622 
623 	wlan_util_vdev_mlme_get_param(vdev_mlme, WLAN_MLME_CFG_BEACON_INTERVAL,
624 				      &beacon_interval);
625 
626 	if ((curr_persona == QDF_P2P_CLIENT_MODE) ||
627 	    (curr_persona == QDF_STA_MODE)) {
628 		/* check for P2P_client scenario */
629 		if ((chan->ch_cfreq1 == 0) && (chan->ch_cfreq2 == 0) &&
630 		    (beacon_interval == 0))
631 			return false;
632 
633 		if (wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_UP &&
634 		    (chan->ch_cfreq1 != bss_arg->ch_freq ||
635 		     chan->ch_cfreq2 != bss_arg->ch_freq) &&
636 		    beacon_interval != bss_arg->bss_beacon_interval) {
637 			/*
638 			 * Updated beaconInterval should be used only when
639 			 * we are starting a new BSS not incase of
640 			 * client or STA case
641 			 */
642 			policy_mgr_get_conc_rule1(psoc, &conc_rule1);
643 			policy_mgr_get_conc_rule2(psoc, &conc_rule2);
644 
645 			/* Calculate beacon Interval for P2P-GO incase of MCC */
646 			if (conc_rule1 || conc_rule2) {
647 				new_bcn_interval = CUSTOM_CONC_GO_BI;
648 			} else {
649 				new_bcn_interval =
650 					if_mgr_calculate_mcc_beacon_interval(
651 						beacon_interval,
652 						bss_arg->bss_beacon_interval);
653 			}
654 			if (new_bcn_interval != bss_arg->bss_beacon_interval)
655 				bss_arg->bss_beacon_interval = new_bcn_interval;
656 			bss_arg->status = QDF_STATUS_SUCCESS;
657 			return true;
658 		}
659 	}
660 	return false;
661 }
662 
if_mgr_validate_beacon_interval(struct wlan_objmgr_pdev * pdev,void * object,void * arg)663 static void if_mgr_validate_beacon_interval(struct wlan_objmgr_pdev *pdev,
664 					    void *object, void *arg)
665 {
666 	struct beacon_interval_arg *bss_arg = arg;
667 	struct wlan_objmgr_vdev *vdev = object;
668 	uint8_t iter_vdev_id = wlan_vdev_get_id(vdev);
669 	bool is_done = false;
670 
671 	if (iter_vdev_id == bss_arg->curr_vdev_id)
672 		return;
673 
674 	if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_UP)
675 		return;
676 
677 	if (bss_arg->is_done)
678 		return;
679 
680 	switch (bss_arg->curr_bss_opmode) {
681 	case QDF_STA_MODE:
682 		is_done = if_mgr_validate_sta_bcn_intrvl(vdev, bss_arg);
683 		break;
684 	case QDF_P2P_CLIENT_MODE:
685 		is_done = if_mgr_validate_p2pcli_bcn_intrvl(vdev, bss_arg);
686 		break;
687 	case QDF_SAP_MODE:
688 	case QDF_IBSS_MODE:
689 		break;
690 	case QDF_P2P_GO_MODE:
691 		is_done = if_mgr_validate_p2pgo_bcn_intrvl(vdev, bss_arg);
692 		break;
693 	default:
694 		ifmgr_err("BSS opmode not supported: %d",
695 			  bss_arg->curr_bss_opmode);
696 	}
697 
698 	if (is_done)
699 		bss_arg->is_done = is_done;
700 }
701 
if_mgr_is_beacon_interval_valid(struct wlan_objmgr_pdev * pdev,uint8_t vdev_id,struct validate_bss_data * candidate)702 bool if_mgr_is_beacon_interval_valid(struct wlan_objmgr_pdev *pdev,
703 				     uint8_t vdev_id,
704 				     struct validate_bss_data *candidate)
705 {
706 	struct wlan_objmgr_psoc *psoc;
707 	struct beacon_interval_arg bss_arg;
708 	uint8_t enable_mcc_mode;
709 	struct wlan_objmgr_vdev *vdev;
710 
711 	psoc = wlan_pdev_get_psoc(pdev);
712 	if (!psoc)
713 		return false;
714 
715 	wlan_mlme_get_mcc_feature(psoc, &enable_mcc_mode);
716 	if (!enable_mcc_mode)
717 		return false;
718 
719 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
720 						    WLAN_IF_MGR_ID);
721 	if (!vdev)
722 		return false;
723 
724 	bss_arg.curr_vdev_id = vdev_id;
725 	bss_arg.curr_bss_opmode = wlan_vdev_mlme_get_opmode(vdev);
726 	bss_arg.ch_freq = candidate->chan_freq;
727 	bss_arg.bss_beacon_interval = candidate->beacon_interval;
728 	bss_arg.is_done = false;
729 
730 	wlan_objmgr_vdev_release_ref(vdev, WLAN_IF_MGR_ID);
731 
732 	wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
733 					  if_mgr_validate_beacon_interval,
734 					  &bss_arg, 0,
735 					  WLAN_IF_MGR_ID);
736 
737 	if (!bss_arg.is_done)
738 		return true;
739 
740 	if (bss_arg.is_done && QDF_IS_STATUS_SUCCESS(bss_arg.status))
741 		return true;
742 
743 	return false;
744 }
745 
if_mgr_get_vdev_id_from_bssid(struct wlan_objmgr_pdev * pdev,void * object,void * arg)746 static void if_mgr_get_vdev_id_from_bssid(struct wlan_objmgr_pdev *pdev,
747 					  void *object, void *arg)
748 {
749 	struct bssid_search_arg *bssid_arg = arg;
750 	struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
751 	struct wlan_objmgr_peer *peer;
752 
753 	if (!(wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE ||
754 	      wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE))
755 		return;
756 
757 	/* Need to check the connection manager state when that becomes
758 	 * available
759 	 */
760 	if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_UP)
761 		return;
762 
763 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_IF_MGR_ID);
764 	if (!peer)
765 		return;
766 
767 	if (WLAN_ADDR_EQ(bssid_arg->peer_addr.bytes,
768 			 wlan_peer_get_macaddr(peer)) == QDF_STATUS_SUCCESS)
769 		bssid_arg->vdev_id = wlan_vdev_get_id(vdev);
770 
771 	wlan_objmgr_peer_release_ref(peer, WLAN_IF_MGR_ID);
772 }
773 
774 #ifdef WLAN_FEATURE_11BE_MLO
775 /**
776  * if_mgr_get_conc_ext_flags() - get extended flags for concurrency check
777  * @vdev: pointer to vdev on which new connection is coming up
778  * @candidate_info: interface manager validate candidate data
779  *
780  * Return: extended flags for concurrency check
781  */
782 static inline uint32_t
if_mgr_get_conc_ext_flags(struct wlan_objmgr_vdev * vdev,struct validate_bss_data * candidate_info)783 if_mgr_get_conc_ext_flags(struct wlan_objmgr_vdev *vdev,
784 			  struct validate_bss_data *candidate_info)
785 {
786 	struct qdf_mac_addr *mld_addr;
787 
788 	/* If connection is happening on non-ML VDEV
789 	 * force the ML AP candidate as non-MLO to
790 	 * downgrade connection to 11ax.
791 	 */
792 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
793 	if (qdf_is_macaddr_zero(mld_addr))
794 		return policy_mgr_get_conc_ext_flags(vdev, false);
795 
796 	return policy_mgr_get_conc_ext_flags(vdev, candidate_info->is_mlo);
797 }
798 
if_mgr_update_candidate(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct validate_bss_data * candidate_info)799 static void if_mgr_update_candidate(struct wlan_objmgr_psoc *psoc,
800 				    struct wlan_objmgr_vdev *vdev,
801 				    struct validate_bss_data *candidate_info)
802 {
803 	struct scan_cache_entry *scan_entry = candidate_info->scan_entry;
804 	struct action_oui_search_attr attr = {0};
805 	int8_t i, allowed_partner_links = 0;
806 	uint8_t mlo_support_link_num;
807 
808 	if (!(scan_entry->ie_list.multi_link_bv || scan_entry->ie_list.ehtcap ||
809 	      scan_entry->ie_list.ehtop))
810 		return;
811 
812 	attr.ie_data = util_scan_entry_ie_data(scan_entry);
813 	attr.ie_length = util_scan_entry_ie_len(scan_entry);
814 
815 	if (!mlme_get_bss_11be_allowed(psoc, &candidate_info->peer_addr,
816 				       attr.ie_data, attr.ie_length) ||
817 	    wlan_vdev_mlme_get_user_dis_eht_flag(vdev) ||
818 	    !wlan_reg_phybitmap_support_11be(wlan_vdev_get_pdev(vdev))) {
819 		scan_entry->ie_list.multi_link_bv = NULL;
820 		scan_entry->ie_list.ehtcap = NULL;
821 		scan_entry->ie_list.ehtop = NULL;
822 		qdf_mem_zero(&scan_entry->ml_info, sizeof(scan_entry->ml_info));
823 		candidate_info->is_mlo = false;
824 		return;
825 	}
826 
827 	mlo_support_link_num = wlan_mlme_get_sta_mlo_conn_max_num(psoc);
828 
829 	if (mlo_support_link_num <= WLAN_MAX_ML_DEFAULT_LINK)
830 		return;
831 
832 	if (!wlan_action_oui_search(psoc, &attr,
833 				    ACTION_OUI_RESTRICT_MAX_MLO_LINKS))
834 		return;
835 
836 	for (i = 0; i < scan_entry->ml_info.num_links; i++) {
837 		if (i < WLAN_MAX_ML_DEFAULT_LINK - 1) {
838 			allowed_partner_links++;
839 			continue;
840 		}
841 
842 		scan_entry->ml_info.link_info[i].is_valid_link = false;
843 	}
844 
845 	if (allowed_partner_links != scan_entry->ml_info.num_links)
846 		ifmgr_nofl_debug("Downgrade " QDF_MAC_ADDR_FMT " partner links from %d to %d",
847 				 QDF_MAC_ADDR_REF(scan_entry->ml_info.mld_mac_addr.bytes),
848 				 scan_entry->ml_info.num_links,
849 				 allowed_partner_links);
850 }
851 #else
852 static inline uint32_t
if_mgr_get_conc_ext_flags(struct wlan_objmgr_vdev * vdev,struct validate_bss_data * candidate_info)853 if_mgr_get_conc_ext_flags(struct wlan_objmgr_vdev *vdev,
854 			  struct validate_bss_data *candidate_info)
855 {
856 	return 0;
857 }
858 
if_mgr_update_candidate(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct validate_bss_data * candidate_info)859 static void if_mgr_update_candidate(struct wlan_objmgr_psoc *psoc,
860 				    struct wlan_objmgr_vdev *vdev,
861 				    struct validate_bss_data *candidate_info)
862 {
863 }
864 #endif
865 
if_mgr_validate_candidate(struct wlan_objmgr_vdev * vdev,struct if_mgr_event_data * event_data)866 QDF_STATUS if_mgr_validate_candidate(struct wlan_objmgr_vdev *vdev,
867 				     struct if_mgr_event_data *event_data)
868 {
869 	struct wlan_objmgr_psoc *psoc;
870 	struct wlan_objmgr_pdev *pdev;
871 	enum QDF_OPMODE op_mode;
872 	enum policy_mgr_con_mode mode;
873 	struct bssid_search_arg bssid_arg;
874 	struct validate_bss_data *candidate_info =
875 		&event_data->validate_bss_info;
876 	uint32_t chan_freq = candidate_info->chan_freq;
877 	uint32_t conc_freq = 0, conc_ext_flags;
878 
879 	op_mode = wlan_vdev_mlme_get_opmode(vdev);
880 
881 	pdev = wlan_vdev_get_pdev(vdev);
882 	if (!pdev)
883 		return QDF_STATUS_E_FAILURE;
884 
885 	psoc = wlan_pdev_get_psoc(pdev);
886 	if (!psoc)
887 		return QDF_STATUS_E_FAILURE;
888 
889 	if_mgr_update_candidate(psoc, vdev, candidate_info);
890 	/*
891 	 * Do not allow STA to connect on 6Ghz or indoor channel for non dbs
892 	 * hardware if SAP and skip_6g_and_indoor_freq_scan ini are present
893 	 */
894 	if (op_mode == QDF_STA_MODE &&
895 	    !policy_mgr_is_sta_chan_valid_for_connect_and_roam(pdev,
896 							       chan_freq)) {
897 		ifmgr_debug("STA connection not allowed on bssid: "QDF_MAC_ADDR_FMT" with freq: %d (6Ghz or indoor(%d)), as not valid for connection",
898 			    QDF_MAC_ADDR_REF(candidate_info->peer_addr.bytes),
899 			    chan_freq,
900 			    wlan_reg_is_freq_indoor(pdev, chan_freq));
901 		return QDF_STATUS_E_INVAL;
902 	}
903 
904 	/*
905 	 * This is a temporary check and will be removed once ll_lt_sap CSA
906 	 * support is added.
907 	 */
908 	if (policy_mgr_get_ll_lt_sap_freq(psoc) == chan_freq) {
909 		ifmgr_debug("STA connection not allowed on LL_LT_SAP freq %d",
910 			    chan_freq);
911 		return QDF_STATUS_E_INVAL;
912 	}
913 	/*
914 	 * Ignore the BSS if any other vdev is already connected to it.
915 	 */
916 	qdf_copy_macaddr(&bssid_arg.peer_addr,
917 			 &candidate_info->peer_addr);
918 	bssid_arg.vdev_id = WLAN_INVALID_VDEV_ID;
919 	wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
920 					  if_mgr_get_vdev_id_from_bssid,
921 					  &bssid_arg, 0,
922 					  WLAN_IF_MGR_ID);
923 
924 	if (bssid_arg.vdev_id != WLAN_INVALID_VDEV_ID) {
925 		ifmgr_info("vdev_id %d already connected to "QDF_MAC_ADDR_FMT". select next bss for vdev_id %d",
926 			   bssid_arg.vdev_id,
927 			   QDF_MAC_ADDR_REF(bssid_arg.peer_addr.bytes),
928 			   wlan_vdev_get_id(vdev));
929 		return QDF_STATUS_E_INVAL;
930 	}
931 
932 	/*
933 	 * If concurrency enabled take the concurrent connected channel first.
934 	 * Valid multichannel concurrent sessions exempted
935 	 */
936 	mode = policy_mgr_qdf_opmode_to_pm_con_mode(psoc, op_mode,
937 						    wlan_vdev_get_id(vdev));
938 
939 	/* If concurrency is not allowed select next bss */
940 	conc_ext_flags = if_mgr_get_conc_ext_flags(vdev, candidate_info);
941 	/*
942 	 * Apply concurrency check only for non ML and ML assoc links only
943 	 * For non-assoc ML link if concurrency check fails its will be forced
944 	 * disabled in peer assoc.
945 	 */
946 	if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
947 	    !policy_mgr_is_concurrency_allowed(psoc, mode, chan_freq,
948 					       HW_MODE_20_MHZ, conc_ext_flags,
949 					       NULL)) {
950 		ifmgr_info("Concurrency not allowed for this channel freq %d bssid "QDF_MAC_ADDR_FMT", selecting next",
951 			   chan_freq,
952 			   QDF_MAC_ADDR_REF(bssid_arg.peer_addr.bytes));
953 		return QDF_STATUS_E_INVAL;
954 	}
955 
956 	/*
957 	 * check if channel is allowed for current hw mode, if not fetch
958 	 * next BSS.
959 	 */
960 	if (!policy_mgr_is_hwmode_set_for_given_chnl(psoc, chan_freq)) {
961 		ifmgr_info("HW mode isn't properly set, freq %d BSSID "QDF_MAC_ADDR_FMT,
962 			   chan_freq,
963 			   QDF_MAC_ADDR_REF(bssid_arg.peer_addr.bytes));
964 		return QDF_STATUS_E_INVAL;
965 	}
966 
967 	/* validate beacon interval */
968 	if (policy_mgr_concurrent_open_sessions_running(psoc) &&
969 	    !if_mgr_is_beacon_interval_valid(pdev, wlan_vdev_get_id(vdev),
970 					     candidate_info)) {
971 		conc_freq = wlan_get_conc_freq();
972 		ifmgr_debug("csr Conc Channel freq: %d",
973 			    conc_freq);
974 
975 		if (conc_freq) {
976 			if ((conc_freq == chan_freq) ||
977 			    (policy_mgr_is_hw_sbs_capable(psoc) &&
978 			     policy_mgr_are_sbs_chan(psoc, conc_freq,
979 			     chan_freq)) ||
980 			    (policy_mgr_is_hw_dbs_capable(psoc) &&
981 			    !wlan_reg_is_same_band_freqs(conc_freq,
982 							 chan_freq))) {
983 				/*
984 				 * make this 0 because we do not want the below
985 				 * check to pass as we don't want to connect on
986 				 * other channel
987 				 */
988 				ifmgr_debug("Conc chnl freq match: %d",
989 					    conc_freq);
990 				conc_freq = 0;
991 			}
992 		}
993 	}
994 
995 	if (conc_freq)
996 		return QDF_STATUS_E_INVAL;
997 
998 	/* Check low latency SAP and STA/GC concurrency are valid or not */
999 	if (!policy_mgr_is_ll_sap_concurrency_valid(psoc, chan_freq, mode)) {
1000 		ifmgr_debug("STA connection not allowed on bssid: "QDF_MAC_ADDR_FMT" with freq: %d due to LL SAP present",
1001 			    QDF_MAC_ADDR_REF(candidate_info->peer_addr.bytes),
1002 			    chan_freq);
1003 		return QDF_STATUS_E_INVAL;
1004 	}
1005 
1006 	return QDF_STATUS_SUCCESS;
1007 }
1008