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