xref: /wlan-dirver/qcacld-3.0/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c (revision d1e852ef3271bee3c7f0839f8bb34296970a4750)
1 /*
2  * Copyright (c) 2012-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
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * DOC: wlan_cm_roam_fw_sync.c
22  *
23  * Implementation for the FW based roaming sync api interfaces.
24  */
25 #include "qdf_types.h"
26 #include "wlan_objmgr_psoc_obj.h"
27 #include "wlan_objmgr_pdev_obj.h"
28 #include "wlan_objmgr_vdev_obj.h"
29 #include "wlan_cm_roam_i.h"
30 #include "wlan_dlm_api.h"
31 #include "wlan_cm_roam_public_struct.h"
32 #include "wlan_utility.h"
33 #include "wlan_scan_api.h"
34 #include "wlan_crypto_global_api.h"
35 #include "wlan_cm_tgt_if_tx_api.h"
36 #include "wlan_cm_vdev_api.h"
37 #include "wlan_p2p_api.h"
38 #include "wlan_tdls_api.h"
39 #include "wlan_mlme_vdev_mgr_interface.h"
40 #include "wlan_pkt_capture_ucfg_api.h"
41 #include "cds_utils.h"
42 #include "wlan_roam_debug.h"
43 #include "wlan_mlme_twt_api.h"
44 #include "connection_mgr/core/src/wlan_cm_roam.h"
45 #include "connection_mgr/core/src/wlan_cm_main.h"
46 #include "connection_mgr/core/src/wlan_cm_sm.h"
47 #include <wlan_mlo_mgr_sta.h>
48 #include "wlan_mlo_mgr_roam.h"
49 #include "wlan_vdev_mgr_utils_api.h"
50 #include "wlan_mlo_link_force.h"
51 #include <wlan_psoc_mlme_api.h>
52 #include <wma.h>
53 
54 /*
55  * cm_is_peer_preset_on_other_sta() - Check if peer exists on other STA
56  * @psoc: Pointer to psoc
57  * @vdev: pointer to vdev
58  * @vdev_id: vdev id
59  * @event: Roam sync event pointer
60  *
61  * Return: True is peer found on other STA else return false
62  */
63 static bool
64 cm_is_peer_preset_on_other_sta(struct wlan_objmgr_psoc *psoc,
65 			       struct wlan_objmgr_vdev *vdev,
66 			       uint8_t vdev_id, void *event)
67 {
68 	bool peer_exists_other_sta = false;
69 	struct roam_offload_synch_ind *sync_ind;
70 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
71 	uint8_t peer_vdev_id;
72 
73 	if (!wma) {
74 		wma_err("wma_handle is NULL");
75 		return false;
76 	}
77 
78 	sync_ind = (struct roam_offload_synch_ind *)event;
79 
80 	if (wma_objmgr_peer_exist(wma, sync_ind->bssid.bytes, &peer_vdev_id)) {
81 		if ((!wlan_vdev_mlme_is_mlo_vdev(vdev) &&
82 		     vdev_id != peer_vdev_id) ||
83 		    !mlo_check_is_given_vdevs_on_same_mld(psoc, vdev_id,
84 							  peer_vdev_id)) {
85 			wma_debug("Peer " QDF_MAC_ADDR_FMT
86 				" already exists on vdev %d, current vdev %d",
87 				QDF_MAC_ADDR_REF(sync_ind->bssid.bytes),
88 				peer_vdev_id, vdev_id);
89 			peer_exists_other_sta = true;
90 		}
91 	}
92 
93 	return peer_exists_other_sta;
94 }
95 
96 QDF_STATUS cm_fw_roam_sync_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
97 			       void *event, uint32_t event_data_len)
98 {
99 	QDF_STATUS status;
100 	struct wlan_objmgr_vdev *vdev;
101 
102 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
103 						    WLAN_MLME_SB_ID);
104 
105 	if (!vdev) {
106 		mlme_err("vdev object is NULL");
107 		return QDF_STATUS_E_NULL_VALUE;
108 	}
109 
110 	if (mlo_is_mld_disconnecting_connecting(vdev) ||
111 	    cm_is_vdev_connecting(vdev) ||
112 	    cm_is_vdev_disconnecting(vdev) ||
113 	    cm_is_peer_preset_on_other_sta(psoc, vdev, vdev_id, event)) {
114 		mlme_err("vdev %d Roam sync not handled in connecting/disconnecting state",
115 			 vdev_id);
116 		wlan_cm_roam_state_change(wlan_vdev_get_pdev(vdev),
117 					  vdev_id,
118 					  WLAN_ROAM_RSO_STOPPED,
119 					  REASON_ROAM_SYNCH_FAILED);
120 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
121 		return QDF_STATUS_E_INVAL;
122 	}
123 	mlo_sta_stop_reconfig_timer(vdev);
124 	wlan_clear_mlo_sta_link_removed_flag(vdev);
125 
126 	status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_ROAM_SYNC,
127 				     event_data_len, event);
128 
129 	if (QDF_IS_STATUS_ERROR(status)) {
130 		mlme_err("Roam sync was not handled");
131 		wlan_cm_roam_state_change(wlan_vdev_get_pdev(vdev),
132 					  vdev_id, WLAN_ROAM_RSO_STOPPED,
133 					  REASON_ROAM_SYNCH_FAILED);
134 	}
135 
136 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
137 
138 	return status;
139 }
140 
141 QDF_STATUS
142 cm_fw_send_vdev_roam_event(struct cnx_mgr *cm_ctx, uint16_t data_len,
143 			   void *data)
144 {
145 	QDF_STATUS status;
146 	wlan_cm_id cm_id;
147 	struct wlan_objmgr_psoc *psoc;
148 	struct cm_roam_req *roam_req = NULL;
149 
150 	roam_req = cm_get_first_roam_command(cm_ctx->vdev);
151 	if (!roam_req) {
152 		mlme_err("Failed to find roam req from list");
153 		cm_id = CM_ID_INVALID;
154 		status = QDF_STATUS_E_FAILURE;
155 		goto error;
156 	}
157 
158 	cm_id = roam_req->cm_id;
159 	psoc = wlan_vdev_get_psoc(cm_ctx->vdev);
160 	if (!psoc) {
161 		mlme_err(CM_PREFIX_FMT "Failed to find psoc",
162 			 CM_PREFIX_REF(roam_req->req.vdev_id,
163 				       roam_req->cm_id));
164 		status = QDF_STATUS_E_FAILURE;
165 		goto error;
166 	}
167 
168 	status = wlan_vdev_mlme_sm_deliver_evt(cm_ctx->vdev,
169 					       WLAN_VDEV_SM_EV_ROAM,
170 					       data_len,
171 					       data);
172 
173 error:
174 
175 	return status;
176 }
177 
178 QDF_STATUS
179 cm_fw_roam_sync_start_ind(struct wlan_objmgr_vdev *vdev,
180 			  struct roam_offload_synch_ind *sync_ind)
181 {
182 	QDF_STATUS status = QDF_STATUS_SUCCESS;
183 	struct wlan_objmgr_pdev *pdev;
184 	struct qdf_mac_addr connected_bssid;
185 	uint8_t vdev_id;
186 	struct wlan_objmgr_psoc *psoc;
187 	uint8_t good_rssi_cfg;
188 	struct psoc_mlme_obj *mlme_psoc_obj;
189 	struct scoring_cfg *score_config;
190 
191 	pdev = wlan_vdev_get_pdev(vdev);
192 	vdev_id = wlan_vdev_get_id(vdev);
193 	psoc = wlan_pdev_get_psoc(pdev);
194 
195 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
196 	if (!mlme_psoc_obj)
197 		return QDF_STATUS_E_INVAL;
198 
199 	if (wlan_vdev_mlme_is_mlo_link_vdev(vdev)) {
200 		if (!MLME_IS_ROAM_SYNCH_IN_PROGRESS(psoc,
201 					sync_ind->roamed_vdev_id))
202 			status = wlan_cm_roam_state_change(pdev,
203 					sync_ind->roamed_vdev_id,
204 					WLAN_ROAM_SYNCH_IN_PROG,
205 					REASON_ROAM_HANDOFF_DONE);
206 
207 		status = wlan_cm_roam_state_change(pdev,
208 					vdev_id,
209 					WLAN_MLO_ROAM_SYNCH_IN_PROG,
210 					REASON_ROAM_HANDOFF_DONE);
211 		return status;
212 	}
213 
214 	/*
215 	 * Get old bssid as, new AP is not updated yet and do cleanup
216 	 * for old bssid.
217 	 */
218 	wlan_mlme_get_bssid_vdev_id(pdev, vdev_id,
219 				    &connected_bssid);
220 
221 	/* Update the DLM that the previous profile has disconnected */
222 	wlan_dlm_update_bssid_connect_params(pdev,
223 					     connected_bssid,
224 					     DLM_AP_DISCONNECTED);
225 
226 	if (IS_ROAM_REASON_STA_KICKOUT(sync_ind->roam_reason)) {
227 		struct reject_ap_info ap_info;
228 
229 		score_config = &mlme_psoc_obj->psoc_cfg.score_config;
230 		good_rssi_cfg = score_config->rssi_score.good_rssi_threshold;
231 		if (good_rssi_cfg > sync_ind->rssi) {
232 			qdf_mem_zero(&ap_info, sizeof(struct reject_ap_info));
233 			ap_info.bssid = connected_bssid;
234 			ap_info.reject_ap_type = DRIVER_AVOID_TYPE;
235 			ap_info.reject_reason = REASON_STA_KICKOUT;
236 			ap_info.source = ADDED_BY_DRIVER;
237 			wlan_dlm_add_bssid_to_reject_list(pdev, &ap_info);
238 		}
239 	}
240 
241 	cm_update_scan_mlme_on_roam(vdev, &connected_bssid,
242 				    SCAN_ENTRY_CON_STATE_NONE);
243 
244 	if (!MLME_IS_ROAM_SYNCH_IN_PROGRESS(psoc, vdev_id))
245 		status = wlan_cm_roam_state_change(pdev,
246 						   vdev_id,
247 						   WLAN_ROAM_SYNCH_IN_PROG,
248 						   REASON_ROAM_HANDOFF_DONE);
249 
250 	mlme_init_twt_context(wlan_pdev_get_psoc(pdev), &connected_bssid,
251 			      TWT_ALL_SESSIONS_DIALOG_ID);
252 
253 	mlme_cm_osif_roam_sync_ind(vdev);
254 
255 	return status;
256 }
257 
258 void
259 cm_update_scan_mlme_on_roam(struct wlan_objmgr_vdev *vdev,
260 			    struct qdf_mac_addr *connected_bssid,
261 			    enum scan_entry_connection_state state)
262 {
263 	struct wlan_objmgr_pdev *pdev;
264 	struct bss_info bss_info;
265 	struct mlme_info mlme;
266 	struct wlan_channel *chan;
267 	QDF_STATUS status;
268 
269 	pdev = wlan_vdev_get_pdev(vdev);
270 	if (!pdev) {
271 		mlme_err("failed to find pdev");
272 		return;
273 	}
274 
275 	chan = wlan_vdev_get_active_channel(vdev);
276 	if (!chan) {
277 		mlme_err("failed to get active channel");
278 		return;
279 	}
280 
281 	status = wlan_vdev_mlme_get_ssid(vdev, bss_info.ssid.ssid,
282 					 &bss_info.ssid.length);
283 
284 	if (QDF_IS_STATUS_ERROR(status)) {
285 		mlme_err("failed to get ssid");
286 		return;
287 	}
288 
289 	mlme.assoc_state = state;
290 	qdf_copy_macaddr(&bss_info.bssid, connected_bssid);
291 
292 	bss_info.freq = chan->ch_freq;
293 
294 	wlan_scan_update_mlme_by_bssinfo(pdev, &bss_info, &mlme);
295 }
296 
297 #ifdef WLAN_FEATURE_FILS_SK
298 static QDF_STATUS
299 cm_fill_fils_ie(struct wlan_connect_rsp_ies *connect_ies,
300 		struct roam_offload_synch_ind *roam_synch_data)
301 {
302 	struct fils_connect_rsp_params *fils_ie;
303 
304 	if (!roam_synch_data->hlp_data_len)
305 		return QDF_STATUS_SUCCESS;
306 
307 	connect_ies->fils_ie = qdf_mem_malloc(sizeof(*fils_ie));
308 	if (!connect_ies->fils_ie)
309 		return QDF_STATUS_E_NOMEM;
310 
311 	fils_ie = connect_ies->fils_ie;
312 	cds_copy_hlp_info(&roam_synch_data->dst_mac,
313 			  &roam_synch_data->src_mac,
314 			  roam_synch_data->hlp_data_len,
315 			  roam_synch_data->hlp_data,
316 			  &fils_ie->dst_mac,
317 			  &fils_ie->src_mac,
318 			  &fils_ie->hlp_data_len,
319 			  fils_ie->hlp_data);
320 
321 	fils_ie->fils_seq_num = roam_synch_data->next_erp_seq_num;
322 
323 	return QDF_STATUS_SUCCESS;
324 }
325 #else
326 static inline QDF_STATUS
327 cm_fill_fils_ie(struct wlan_connect_rsp_ies *connect_ies,
328 		struct roam_offload_synch_ind *roam_synch_data)
329 {
330 	return QDF_STATUS_SUCCESS;
331 }
332 #endif
333 
334 static QDF_STATUS
335 cm_populate_connect_ies(struct roam_offload_synch_ind *roam_synch_data,
336 			struct cm_vdev_join_rsp *rsp)
337 {
338 	struct wlan_connect_rsp_ies *connect_ies;
339 	uint8_t *bcn_probe_rsp_ptr;
340 	uint8_t *reassoc_rsp_ptr;
341 	uint8_t *reassoc_req_ptr;
342 
343 	connect_ies = &rsp->connect_rsp.connect_ies;
344 
345 	/* Beacon/Probe Rsp frame */
346 	if (roam_synch_data->beacon_probe_resp_length) {
347 		connect_ies->bcn_probe_rsp.len =
348 			roam_synch_data->beacon_probe_resp_length;
349 		bcn_probe_rsp_ptr = (uint8_t *)roam_synch_data +
350 					roam_synch_data->beacon_probe_resp_offset;
351 
352 		connect_ies->bcn_probe_rsp.ptr =
353 			qdf_mem_malloc(connect_ies->bcn_probe_rsp.len);
354 		if (!connect_ies->bcn_probe_rsp.ptr)
355 			return QDF_STATUS_E_NOMEM;
356 		qdf_mem_copy(connect_ies->bcn_probe_rsp.ptr, bcn_probe_rsp_ptr,
357 			     connect_ies->bcn_probe_rsp.len);
358 	}
359 
360 	/* Beacon/Probe Rsp frame */
361 	if (roam_synch_data->link_beacon_probe_resp_length) {
362 		connect_ies->link_bcn_probe_rsp.len =
363 			roam_synch_data->link_beacon_probe_resp_length;
364 		bcn_probe_rsp_ptr = (uint8_t *)roam_synch_data +
365 				roam_synch_data->link_beacon_probe_resp_offset;
366 
367 		connect_ies->link_bcn_probe_rsp.ptr =
368 			qdf_mem_malloc(connect_ies->link_bcn_probe_rsp.len);
369 		if (!connect_ies->link_bcn_probe_rsp.ptr)
370 			return QDF_STATUS_E_NOMEM;
371 		qdf_mem_copy(connect_ies->link_bcn_probe_rsp.ptr,
372 			     bcn_probe_rsp_ptr,
373 			     connect_ies->link_bcn_probe_rsp.len);
374 	}
375 
376 	/* ReAssoc Rsp IE data */
377 	if (roam_synch_data->reassoc_resp_length >
378 	    sizeof(struct wlan_frame_hdr)) {
379 		connect_ies->assoc_rsp.len =
380 				roam_synch_data->reassoc_resp_length -
381 				sizeof(struct wlan_frame_hdr);
382 		reassoc_rsp_ptr = (uint8_t *)roam_synch_data +
383 				  roam_synch_data->reassoc_resp_offset +
384 				  sizeof(struct wlan_frame_hdr);
385 		connect_ies->assoc_rsp.ptr =
386 			qdf_mem_malloc(connect_ies->assoc_rsp.len);
387 		if (!connect_ies->assoc_rsp.ptr)
388 			return QDF_STATUS_E_NOMEM;
389 
390 		qdf_mem_copy(connect_ies->assoc_rsp.ptr, reassoc_rsp_ptr,
391 			     connect_ies->assoc_rsp.len);
392 	}
393 
394 	/* ReAssoc Req IE data */
395 	if (roam_synch_data->reassoc_req_length >
396 	    sizeof(struct wlan_frame_hdr)) {
397 		connect_ies->assoc_req.len =
398 				roam_synch_data->reassoc_req_length -
399 				sizeof(struct wlan_frame_hdr);
400 		reassoc_req_ptr = (uint8_t *)roam_synch_data +
401 				  roam_synch_data->reassoc_req_offset +
402 				  sizeof(struct wlan_frame_hdr);
403 		connect_ies->assoc_req.ptr =
404 			qdf_mem_malloc(connect_ies->assoc_req.len);
405 		if (!connect_ies->assoc_req.ptr)
406 			return QDF_STATUS_E_NOMEM;
407 		qdf_mem_copy(connect_ies->assoc_req.ptr, reassoc_req_ptr,
408 			     connect_ies->assoc_req.len);
409 	}
410 	rsp->connect_rsp.is_assoc = roam_synch_data->is_assoc;
411 
412 	cm_fill_fils_ie(connect_ies, roam_synch_data);
413 
414 	return QDF_STATUS_SUCCESS;
415 }
416 
417 #ifdef FEATURE_WLAN_ESE
418 static QDF_STATUS
419 cm_copy_tspec_ie(struct cm_vdev_join_rsp *rsp,
420 		 struct roam_offload_synch_ind *roam_synch_data)
421 {
422 	if (roam_synch_data->tspec_len) {
423 		rsp->tspec_ie.len = roam_synch_data->tspec_len;
424 		rsp->tspec_ie.ptr =
425 			qdf_mem_malloc(rsp->tspec_ie.len);
426 		if (!rsp->tspec_ie.ptr)
427 			return QDF_STATUS_E_NOMEM;
428 
429 		qdf_mem_copy(rsp->tspec_ie.ptr,
430 			     roam_synch_data->ric_tspec_data +
431 			     roam_synch_data->ric_data_len,
432 			     rsp->tspec_ie.len);
433 	}
434 
435 	return QDF_STATUS_SUCCESS;
436 }
437 #else
438 static inline QDF_STATUS
439 cm_copy_tspec_ie(struct cm_vdev_join_rsp *rsp,
440 		 struct roam_offload_synch_ind *roam_synch_data)
441 {
442 	return QDF_STATUS_SUCCESS;
443 }
444 #endif
445 
446 #ifdef WLAN_FEATURE_FILS_SK
447 static void
448 cm_fils_update_erp_seq_num(struct wlan_objmgr_vdev *vdev,
449 			   uint16_t next_erp_seq_num,
450 			   wlan_cm_id cm_id)
451 {
452 	struct wlan_objmgr_psoc *psoc;
453 	struct wlan_objmgr_pdev *pdev;
454 	struct wlan_fils_connection_info *fils_info;
455 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
456 
457 	pdev = wlan_vdev_get_pdev(vdev);
458 	if (!pdev) {
459 		mlme_err(CM_PREFIX_FMT "Failed to find pdev",
460 			 CM_PREFIX_REF(vdev_id, cm_id));
461 		return;
462 	}
463 
464 	psoc = wlan_pdev_get_psoc(pdev);
465 	if (!psoc) {
466 		mlme_err(CM_PREFIX_FMT "Failed to find psoc",
467 			 CM_PREFIX_REF(vdev_id, cm_id));
468 		return;
469 	}
470 
471 	fils_info = wlan_cm_get_fils_connection_info(psoc, vdev_id);
472 	if (!fils_info)
473 		return;
474 
475 	/*
476 	 * update the erp sequence number to the vdev level
477 	 * FILS cache. This will be sent in the next RSO
478 	 * command.
479 	 */
480 	fils_info->erp_sequence_number = next_erp_seq_num;
481 }
482 #else
483 static inline void
484 cm_fils_update_erp_seq_num(struct wlan_objmgr_vdev *vdev,
485 			   uint16_t next_erp_seq_num, wlan_cm_id cm_id)
486 {}
487 #endif
488 
489 #ifdef WLAN_FEATURE_11BE_MLO
490 static void
491 cm_roam_update_mlo_mgr_info(struct wlan_objmgr_vdev *vdev,
492 			    struct roam_offload_synch_ind *roam_synch_data)
493 {
494 	struct wlan_channel channel = {0};
495 	struct ml_setup_link_param *ml_link;
496 	uint8_t i;
497 
498 	if (!is_multi_link_roam(roam_synch_data))
499 		return;
500 
501 	mlo_mgr_reset_ap_link_info(vdev);
502 	for (i = 0; i < roam_synch_data->num_setup_links; i++) {
503 		ml_link = &roam_synch_data->ml_link[i];
504 
505 		qdf_mem_zero(&channel, sizeof(channel));
506 
507 		channel.ch_freq = ml_link->channel.mhz;
508 		channel.ch_cfreq1 = ml_link->channel.band_center_freq1;
509 		channel.ch_cfreq2 = ml_link->channel.band_center_freq2;
510 
511 		/*
512 		 * Update Link switch context for each vdev with roamed AP link
513 		 * address and self link address for each vdev
514 		 */
515 		mlo_mgr_roam_update_ap_link_info(vdev, ml_link, &channel);
516 	}
517 }
518 
519 static QDF_STATUS
520 cm_fill_bssid_freq_info(uint8_t vdev_id,
521 			struct roam_offload_synch_ind *roam_synch_data,
522 			struct cm_vdev_join_rsp *rsp)
523 {
524 	uint8_t i;
525 	struct ml_setup_link_param *ml_link;
526 
527 	/* The @bssid field in roam synch indication will
528 	 * contain MLD address in case of roaming to ML
529 	 * candidate or else legacy MAC address for non-ML
530 	 * roaming.
531 	 */
532 	if (is_multi_link_roam(roam_synch_data))
533 		qdf_copy_macaddr(&rsp->connect_rsp.mld_addr,
534 				 &roam_synch_data->bssid);
535 	else
536 		qdf_zero_macaddr(&rsp->connect_rsp.mld_addr);
537 
538 	for (i = 0; i < roam_synch_data->num_setup_links; i++) {
539 		ml_link = &roam_synch_data->ml_link[i];
540 		if (vdev_id == ml_link->vdev_id) {
541 			qdf_copy_macaddr(&rsp->connect_rsp.bssid,
542 					 &ml_link->link_addr);
543 			rsp->connect_rsp.freq = ml_link->channel.mhz;
544 
545 			return QDF_STATUS_SUCCESS;
546 		}
547 	}
548 
549 	qdf_copy_macaddr(&rsp->connect_rsp.bssid, &roam_synch_data->bssid);
550 	rsp->connect_rsp.freq = roam_synch_data->chan_freq;
551 
552 	return QDF_STATUS_SUCCESS;
553 }
554 
555 static void
556 cm_mlo_roam_copy_partner_info(struct wlan_cm_connect_resp *connect_rsp,
557 			      struct roam_offload_synch_ind *roam_synch_data)
558 {
559 	mlo_roam_copy_partner_info(&connect_rsp->ml_parnter_info,
560 				   roam_synch_data, WLAN_INVALID_VDEV_ID,
561 				   true);
562 }
563 #else
564 static inline void
565 cm_roam_update_mlo_mgr_info(struct wlan_objmgr_vdev *vdev,
566 			    struct roam_offload_synch_ind *roam_synch_data)
567 {}
568 static QDF_STATUS
569 cm_fill_bssid_freq_info(uint8_t vdev_id,
570 			struct roam_offload_synch_ind *roam_synch_data,
571 			struct cm_vdev_join_rsp *rsp)
572 {
573 	qdf_copy_macaddr(&rsp->connect_rsp.bssid, &roam_synch_data->bssid);
574 	rsp->connect_rsp.freq = roam_synch_data->chan_freq;
575 
576 	return QDF_STATUS_SUCCESS;
577 }
578 
579 static void
580 cm_mlo_roam_copy_partner_info(struct wlan_cm_connect_resp *connect_rsp,
581 			      struct roam_offload_synch_ind *roam_synch_data)
582 {
583 }
584 #endif
585 
586 static void
587 cm_update_assoc_btm_cap(struct wlan_objmgr_vdev *vdev,
588 			struct cm_vdev_join_rsp *rsp)
589 {
590 	struct wlan_connect_rsp_ies *connect_ies;
591 	const uint8_t *ext_cap_ie;
592 	struct s_ext_cap *extcap;
593 	uint8_t offset;
594 
595 	connect_ies = &rsp->connect_rsp.connect_ies;
596 	/*
597 	 * Retain the btm cap from initial assoc if
598 	 * there is no assoc request
599 	 */
600 	if (!connect_ies->assoc_req.ptr ||
601 	    !connect_ies->assoc_req.len)
602 		return;
603 
604 	if (rsp->connect_rsp.is_assoc)
605 		offset = WLAN_ASSOC_REQ_IES_OFFSET;
606 	else
607 		offset = WLAN_REASSOC_REQ_IES_OFFSET;
608 
609 	ext_cap_ie =
610 		wlan_get_ie_ptr_from_eid(WLAN_ELEMID_XCAPS,
611 					 connect_ies->assoc_req.ptr + offset,
612 					 connect_ies->assoc_req.len - offset);
613 
614 	if (!ext_cap_ie) {
615 		mlme_debug("Ext cap is not present, disable btm");
616 		wlan_cm_set_assoc_btm_cap(vdev, false);
617 		return;
618 	}
619 	extcap = (struct s_ext_cap *)&ext_cap_ie[2];
620 	wlan_cm_set_assoc_btm_cap(vdev, extcap->bss_transition);
621 }
622 
623 #ifdef WLAN_FEATURE_11BE_MLO
624 static inline void
625 cm_fill_num_roam_links_info(struct wlan_roam_sync_info *roam_info,
626 			    struct roam_offload_synch_ind *roam_synch_ind)
627 {
628 	roam_info->num_setup_links = roam_synch_ind->num_setup_links;
629 }
630 #else
631 static inline void
632 cm_fill_num_roam_links_info(struct wlan_roam_sync_info *roam_info,
633 			    struct roam_offload_synch_ind *roam_synch_ind)
634 {
635 }
636 #endif
637 
638 static QDF_STATUS
639 cm_fill_roam_info(struct wlan_objmgr_vdev *vdev,
640 		  struct roam_offload_synch_ind *roam_synch_data,
641 		  struct cm_vdev_join_rsp *rsp, wlan_cm_id cm_id)
642 {
643 	struct wlan_roam_sync_info *roaming_info;
644 	QDF_STATUS status = QDF_STATUS_SUCCESS;
645 
646 	rsp->connect_rsp.roaming_info = qdf_mem_malloc(sizeof(*roaming_info));
647 	if (!rsp->connect_rsp.roaming_info)
648 		return QDF_STATUS_E_NOMEM;
649 
650 	rsp->connect_rsp.vdev_id = wlan_vdev_get_id(vdev);
651 	status = cm_fill_bssid_freq_info(wlan_vdev_get_id(vdev),
652 					 roam_synch_data, rsp);
653 	if (QDF_IS_STATUS_ERROR(status)) {
654 		mlme_err(CM_PREFIX_FMT "Failed to get bssid and freq",
655 			 CM_PREFIX_REF(rsp->connect_rsp.vdev_id, cm_id));
656 		return QDF_STATUS_E_FAILURE;
657 	}
658 
659 	if (!util_scan_is_null_ssid(&roam_synch_data->ssid))
660 		wlan_vdev_mlme_set_ssid(vdev,
661 					roam_synch_data->ssid.ssid,
662 					roam_synch_data->ssid.length);
663 
664 	status = wlan_vdev_mlme_get_ssid(vdev,
665 					 rsp->connect_rsp.ssid.ssid,
666 					 &rsp->connect_rsp.ssid.length);
667 	if (QDF_IS_STATUS_ERROR(status)) {
668 		mlme_err(CM_PREFIX_FMT "Failed to get ssid",
669 			 CM_PREFIX_REF(rsp->connect_rsp.vdev_id, cm_id));
670 		return QDF_STATUS_E_FAILURE;
671 	}
672 
673 	rsp->connect_rsp.is_reassoc = true;
674 	rsp->connect_rsp.connect_status = QDF_STATUS_SUCCESS;
675 	rsp->connect_rsp.cm_id = cm_id;
676 	rsp->nss = roam_synch_data->nss;
677 
678 	if (roam_synch_data->ric_data_len) {
679 		rsp->ric_resp_ie.len = roam_synch_data->ric_data_len;
680 		rsp->ric_resp_ie.ptr =
681 			qdf_mem_malloc(rsp->ric_resp_ie.len);
682 		if (!rsp->ric_resp_ie.ptr)
683 			return QDF_STATUS_E_NOMEM;
684 
685 		qdf_mem_copy(rsp->ric_resp_ie.ptr,
686 			     roam_synch_data->ric_tspec_data,
687 			     rsp->ric_resp_ie.len);
688 	}
689 	cm_copy_tspec_ie(rsp, roam_synch_data);
690 
691 	status = cm_populate_connect_ies(roam_synch_data, rsp);
692 	if (QDF_IS_STATUS_ERROR(status))
693 		return status;
694 
695 	roaming_info = rsp->connect_rsp.roaming_info;
696 	roaming_info->auth_status = roam_synch_data->auth_status;
697 	cm_fill_num_roam_links_info(roaming_info, roam_synch_data);
698 	roaming_info->kck_len = roam_synch_data->kck_len;
699 	if (roaming_info->kck_len)
700 		qdf_mem_copy(roaming_info->kck, roam_synch_data->kck,
701 			     roam_synch_data->kck_len);
702 	roaming_info->kek_len = roam_synch_data->kek_len;
703 	if (roaming_info->kek_len)
704 		qdf_mem_copy(roaming_info->kek, roam_synch_data->kek,
705 			     roam_synch_data->kek_len);
706 	qdf_mem_copy(roaming_info->replay_ctr, roam_synch_data->replay_ctr,
707 		     REPLAY_CTR_LEN);
708 	roaming_info->roam_reason =
709 		roam_synch_data->roam_reason & ROAM_REASON_MASK;
710 	roaming_info->subnet_change_status =
711 			CM_GET_SUBNET_STATUS(roam_synch_data->roam_reason);
712 	roaming_info->pmk_len = roam_synch_data->pmk_len;
713 	if (roaming_info->pmk_len)
714 		qdf_mem_copy(roaming_info->pmk, roam_synch_data->pmk,
715 			     roaming_info->pmk_len);
716 
717 	qdf_mem_copy(roaming_info->pmkid, roam_synch_data->pmkid,
718 		     PMKID_LEN);
719 	roaming_info->update_erp_next_seq_num =
720 			roam_synch_data->update_erp_next_seq_num;
721 	roaming_info->next_erp_seq_num = roam_synch_data->next_erp_seq_num;
722 
723 	cm_fils_update_erp_seq_num(vdev, roaming_info->next_erp_seq_num, cm_id);
724 	cm_update_assoc_btm_cap(vdev, rsp);
725 
726 	return status;
727 }
728 
729 static QDF_STATUS cm_process_roam_keys(struct wlan_objmgr_vdev *vdev,
730 				       struct cm_vdev_join_rsp *rsp,
731 				       wlan_cm_id cm_id)
732 {
733 	struct wlan_objmgr_psoc *psoc;
734 	struct wlan_objmgr_pdev *pdev;
735 	struct wlan_roam_sync_info *roaming_info;
736 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
737 	struct cm_roam_values_copy config;
738 	uint8_t mdie_present;
739 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
740 	QDF_STATUS status = QDF_STATUS_SUCCESS;
741 	int32_t akm;
742 
743 	pdev = wlan_vdev_get_pdev(vdev);
744 	if (!pdev) {
745 		mlme_err(CM_PREFIX_FMT "Failed to find pdev",
746 			 CM_PREFIX_REF(vdev_id, cm_id));
747 		status = QDF_STATUS_E_FAILURE;
748 		goto end;
749 	}
750 	psoc = wlan_pdev_get_psoc(pdev);
751 	if (!psoc) {
752 		mlme_err(CM_PREFIX_FMT "Failed to find psoc",
753 			 CM_PREFIX_REF(vdev_id, cm_id));
754 		status = QDF_STATUS_E_FAILURE;
755 		goto end;
756 	}
757 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
758 	if (!mlme_obj) {
759 		mlme_err(CM_PREFIX_FMT "Failed to mlme psoc obj",
760 			 CM_PREFIX_REF(vdev_id, cm_id));
761 		status = QDF_STATUS_E_FAILURE;
762 		goto end;
763 	}
764 
765 	roaming_info = rsp->connect_rsp.roaming_info;
766 	akm = wlan_crypto_get_param(vdev,
767 				    WLAN_CRYPTO_PARAM_KEY_MGMT);
768 
769 	/*
770 	 * Encryption keys for new connection are obtained as follows:
771 	 * auth_status = CSR_ROAM_AUTH_STATUS_AUTHENTICATED
772 	 * Open - No keys required.
773 	 * Static WEP - Firmware copies keys from old AP to new AP.
774 	 * Fast roaming authentications e.g. PSK, FT, CCKM - firmware
775 	 *		supplicant obtains them through 4-way handshake.
776 	 *
777 	 * auth_status = CSR_ROAM_AUTH_STATUS_CONNECTED
778 	 * All other authentications - Host supplicant performs EAPOL
779 	 *	with AP after this point and sends new keys to the driver.
780 	 *	Driver starts wait_for_key timer for that purpose.
781 	 * Allow cm_lookup_pmkid_using_bssid() if akm is SAE/OWE since
782 	 * SAE/OWE roaming uses hybrid model and eapol is offloaded to
783 	 * supplicant unlike in WPA2 802.1x case, after 8 way handshake
784 	 * the __wlan_hdd_cfg80211_keymgmt_set_key ->sme_roam_set_psk_pmk()
785 	 * will get called after roam synch complete to update the
786 	 * session->psk_pmk, but in SAE/OWE roaming this sequence is not
787 	 * present and set_pmksa will come before roam synch indication &
788 	 * eapol. So the session->psk_pmk will be stale in PMKSA cached
789 	 * SAE/OWE roaming case.
790 	 */
791 
792 	if (roaming_info->auth_status == ROAM_AUTH_STATUS_AUTHENTICATED ||
793 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE) ||
794 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE) ||
795 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_OWE) ||
796 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE_EXT_KEY) ||
797 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY)) {
798 		struct wlan_crypto_pmksa *pmkid_cache, *pmksa;
799 
800 		cm_csr_set_ss_none(vdev_id);
801 		/*
802 		 * If authStatus is AUTHENTICATED, then we have done successful
803 		 * 4 way handshake in FW using the cached PMKID.
804 		 * However, the session->psk_pmk has the PMK of the older AP
805 		 * as set_key is not received from supplicant.
806 		 * When any RSO command is sent for the current AP, the older
807 		 * AP's PMK is sent to the FW which leads to incorrect PMK and
808 		 * leads to 4 way handshake failure when roaming happens to
809 		 * this AP again.
810 		 * Check if a PMK cache exists for the roamed AP and update
811 		 * it into the session pmk.
812 		 */
813 		pmkid_cache = qdf_mem_malloc(sizeof(*pmkid_cache));
814 		if (!pmkid_cache) {
815 			status = QDF_STATUS_E_NOMEM;
816 			mlme_err(CM_PREFIX_FMT "Mem alloc failed",
817 				 CM_PREFIX_REF(vdev_id, cm_id));
818 			goto end;
819 		}
820 		wlan_vdev_get_bss_peer_mac_for_pmksa(vdev, &pmkid_cache->bssid);
821 		mlme_debug(CM_PREFIX_FMT "Trying to find PMKID for "
822 			   QDF_MAC_ADDR_FMT " AKM Type:%d",
823 			   CM_PREFIX_REF(vdev_id, cm_id),
824 			   QDF_MAC_ADDR_REF(pmkid_cache->bssid.bytes), akm);
825 
826 		wlan_cm_roam_cfg_get_value(psoc, vdev_id,
827 					   MOBILITY_DOMAIN, &config);
828 		mdie_present = config.bool_value;
829 
830 		if (cm_lookup_pmkid_using_bssid(psoc,
831 						vdev_id,
832 						pmkid_cache)) {
833 			/*
834 			 * Consider two APs: AP1, AP2
835 			 * Both APs configured with EAP 802.1x security mode
836 			 * and OKC is enabled in both APs by default. Initially
837 			 * DUT successfully associated with AP1, and generated
838 			 * PMK1 by performing full EAP and added an entry for
839 			 * AP1 in pmk table. At this stage, pmk table has only
840 			 * one entry for PMK1 (1. AP1-->PMK1). Now DUT try to
841 			 * roam to AP2 using PMK1 (as OKC is enabled) but
842 			 * session timeout happens on AP2 just before 4 way
843 			 * handshake completion in FW. At this point of time
844 			 * DUT not in authenticated state. Due to this DUT
845 			 * performs full EAP with AP2 and generates PMK2. As
846 			 * there is no previous entry of AP2 (AP2-->PMK1) in pmk
847 			 * table. When host gets pmk delete command for BSSID of
848 			 * AP2, the BSSID match fails. Hence host will not
849 			 * delete pmk entry of AP1 as well.
850 			 * At this point of time, the PMK table has two entry
851 			 * 1. AP1-->PMK1 and 2. AP2 --> PMK2.
852 			 * Ideally, if OKC is enabled then whenever timeout
853 			 * occurs in a mobility domain, then the driver should
854 			 * clear all APs cache entries related to that domain
855 			 * but as the BSSID doesn't exist yet in the driver
856 			 * cache there is no way of clearing the cache entries,
857 			 * without disturbing the legacy roaming.
858 			 * Now security profile for both APs changed to FT-RSN.
859 			 * DUT first disassociate with AP2 and successfully
860 			 * associated with AP2 and perform full EAP and
861 			 * generates PMK3. DUT first deletes PMK entry for AP2
862 			 * and then adds a new entry for AP2.
863 			 * At this point of time pmk table has two entry
864 			 * AP2--> PMK3 and AP1-->PMK1. Now DUT roamed to AP1
865 			 * using PMK3 but sends stale entry of AP1 (PMK1) to
866 			 * fw via RSO command. This override PMK for both APs
867 			 * with PMK1 (as FW uses mlme session PMK for both APs
868 			 * in case of FT roaming) and next time when FW try to
869 			 * roam to AP2 using PMK1, AP2 rejects PMK1 (As AP2 is
870 			 * expecting PMK3) and initiates full EAP with AP2,
871 			 * which is wrong.
872 			 * To address this issue update pmk table entry for
873 			 * roamed AP1 with pmk3 value comes to host via roam
874 			 * sync indication event. By this host override stale
875 			 * entry (if any) with the latest valid pmk for that AP
876 			 * at a point of time.
877 			 */
878 			if (roaming_info->pmk_len) {
879 				pmksa = qdf_mem_malloc(sizeof(*pmksa));
880 				if (!pmksa) {
881 					status = QDF_STATUS_E_NOMEM;
882 					qdf_mem_zero(pmkid_cache,
883 						     sizeof(*pmkid_cache));
884 					qdf_mem_free(pmkid_cache);
885 					goto end;
886 				}
887 
888 				/*
889 				 * This pmksa buffer is to update the
890 				 * crypto table
891 				 */
892 				wlan_vdev_get_bss_peer_mac_for_pmksa(vdev,
893 								     &pmksa->bssid);
894 				qdf_mem_copy(pmksa->pmkid,
895 					     roaming_info->pmkid, PMKID_LEN);
896 				qdf_mem_copy(pmksa->pmk, roaming_info->pmk,
897 					     roaming_info->pmk_len);
898 				pmksa->pmk_len = roaming_info->pmk_len;
899 				status = wlan_crypto_set_del_pmksa(vdev,
900 								   pmksa, true);
901 				if (QDF_IS_STATUS_ERROR(status)) {
902 					qdf_mem_zero(pmksa, sizeof(*pmksa));
903 					qdf_mem_free(pmksa);
904 				}
905 
906 				/* update the pmkid_cache buffer to
907 				 * update the global session pmk
908 				 */
909 				qdf_mem_copy(pmkid_cache->pmkid,
910 					     roaming_info->pmkid, PMKID_LEN);
911 				qdf_mem_copy(pmkid_cache->pmk,
912 					     roaming_info->pmk,
913 					     roaming_info->pmk_len);
914 				pmkid_cache->pmk_len = roaming_info->pmk_len;
915 			} else {
916 				mlme_debug("PMK not received from fw");
917 			}
918 
919 			wlan_cm_set_psk_pmk(pdev, vdev_id,
920 					    pmkid_cache->pmk,
921 					    pmkid_cache->pmk_len);
922 			mlme_debug(CM_PREFIX_FMT "pmkid found for "
923 				   QDF_MAC_ADDR_FMT " len %d",
924 				   CM_PREFIX_REF(vdev_id, cm_id),
925 				   QDF_MAC_ADDR_REF(pmkid_cache->bssid.bytes),
926 				   pmkid_cache->pmk_len);
927 		} else {
928 			mlme_debug(CM_PREFIX_FMT "PMKID Not found in cache for "
929 				   QDF_MAC_ADDR_FMT,
930 				   CM_PREFIX_REF(vdev_id, cm_id),
931 				   QDF_MAC_ADDR_REF(pmkid_cache->bssid.bytes));
932 			/*
933 			 * In FT roam when the CSR lookup fails then the PMK
934 			 * details from the roam sync indication will be
935 			 * updated to Session/PMK cache. This will result in
936 			 * having multiple PMK cache entries for the same MDID,
937 			 * So do not add the PMKSA cache entry in all the
938 			 * FT-Roam cases.
939 			 */
940 			if (!cm_is_auth_type_11r(mlme_obj, vdev,
941 						 mdie_present) &&
942 			    roaming_info->pmk_len) {
943 				/*
944 				 * This pmksa buffer is to update the
945 				 * crypto table
946 				 */
947 				pmksa = qdf_mem_malloc(sizeof(*pmksa));
948 				if (!pmksa) {
949 					status = QDF_STATUS_E_NOMEM;
950 					qdf_mem_zero(pmkid_cache,
951 						     sizeof(*pmkid_cache));
952 					qdf_mem_free(pmkid_cache);
953 					goto end;
954 				}
955 				wlan_cm_set_psk_pmk(pdev, vdev_id,
956 						    roaming_info->pmk,
957 						    roaming_info->pmk_len);
958 				wlan_vdev_get_bss_peer_mac_for_pmksa(vdev,
959 								     &pmksa->bssid);
960 				qdf_mem_copy(pmksa->pmkid,
961 					     roaming_info->pmkid, PMKID_LEN);
962 				qdf_mem_copy(pmksa->pmk,
963 					     roaming_info->pmk,
964 					     roaming_info->pmk_len);
965 				pmksa->pmk_len = roaming_info->pmk_len;
966 
967 				status = wlan_crypto_set_del_pmksa(vdev,
968 								   pmksa,
969 								   true);
970 				if (QDF_IS_STATUS_ERROR(status)) {
971 					qdf_mem_zero(pmksa, sizeof(*pmksa));
972 					qdf_mem_free(pmksa);
973 				}
974 			}
975 		}
976 		qdf_mem_zero(pmkid_cache, sizeof(*pmkid_cache));
977 		qdf_mem_free(pmkid_cache);
978 	}
979 
980 	if (roaming_info->auth_status != ROAM_AUTH_STATUS_AUTHENTICATED)
981 		cm_update_wait_for_key_timer(vdev, vdev_id,
982 					     WAIT_FOR_KEY_TIMEOUT_PERIOD);
983 end:
984 	return status;
985 }
986 
987 static void
988 cm_update_scan_db_on_roam_success(struct wlan_objmgr_vdev *vdev,
989 				  struct wlan_cm_connect_resp *resp,
990 				  struct roam_offload_synch_ind *roam_synch_ind,
991 				  wlan_cm_id cm_id)
992 {
993 	struct cnx_mgr *cm_ctx;
994 	qdf_freq_t frame_freq;
995 	struct wlan_connect_rsp_ies *ies = &resp->connect_ies;
996 
997 	cm_ctx = cm_get_cm_ctx(vdev);
998 	if (!cm_ctx)
999 		return;
1000 
1001 	if (ies->link_bcn_probe_rsp.len) {
1002 		frame_freq = mlo_roam_get_link_freq_from_mac_addr(
1003 				roam_synch_ind,
1004 				wlan_mlme_get_src_addr_from_frame(
1005 				&ies->link_bcn_probe_rsp));
1006 		cm_inform_bcn_probe(cm_ctx,
1007 				    ies->link_bcn_probe_rsp.ptr,
1008 				    ies->link_bcn_probe_rsp.len,
1009 				    frame_freq,
1010 				    roam_synch_ind->rssi,
1011 				    cm_id);
1012 	}
1013 
1014 	frame_freq = mlo_roam_get_link_freq_from_mac_addr(
1015 				roam_synch_ind,
1016 				wlan_mlme_get_src_addr_from_frame(
1017 				&ies->bcn_probe_rsp));
1018 	/*
1019 	 * Firmware might have roamed to a link but got ML probe
1020 	 * response from the other link. Then the link freq is not
1021 	 * present in roam link info and it returns 0. No need to add
1022 	 * the original probe rsp in such cases as roam sync indication
1023 	 * handling would add it to scan db. Add the entry to scan
1024 	 * db only if valid link freq is found.
1025 	 */
1026 	if (frame_freq)
1027 		cm_inform_bcn_probe(cm_ctx,
1028 				    ies->bcn_probe_rsp.ptr,
1029 				    ies->bcn_probe_rsp.len,
1030 				    frame_freq,
1031 				    roam_synch_ind->rssi,
1032 				    cm_id);
1033 
1034 	cm_update_scan_mlme_on_roam(vdev, &resp->bssid,
1035 				    SCAN_ENTRY_CON_STATE_ASSOC);
1036 
1037 	cm_standby_link_update_mlme_by_bssid(vdev, SCAN_ENTRY_CON_STATE_ASSOC,
1038 					     resp->ssid);
1039 }
1040 
1041 #ifdef WLAN_FEATURE_11BE_MLO
1042 static void
1043 cm_roam_ml_clear_prev_ap_keys(struct wlan_objmgr_vdev *vdev)
1044 {
1045 	struct wlan_mlo_dev_context *ml_dev;
1046 	struct mlo_link_info *link_info;
1047 	uint8_t i;
1048 
1049 	ml_dev = vdev->mlo_dev_ctx;
1050 	if (!ml_dev || !ml_dev->link_ctx)
1051 		return;
1052 
1053 	link_info = &ml_dev->link_ctx->links_info[0];
1054 	for (i = 0; i < WLAN_MAX_ML_BSS_LINKS; i++) {
1055 		if (qdf_is_macaddr_zero(&link_info->ap_link_addr))
1056 			continue;
1057 
1058 		if (qdf_is_macaddr_zero(&link_info->link_addr))
1059 			continue;
1060 
1061 		wlan_crypto_free_key_by_link_id(wlan_vdev_get_psoc(vdev),
1062 						&link_info->link_addr,
1063 						link_info->link_id);
1064 		link_info++;
1065 	}
1066 }
1067 #else
1068 static void
1069 cm_roam_ml_clear_prev_ap_keys(struct wlan_objmgr_vdev *vdev)
1070 {}
1071 #endif
1072 
1073 QDF_STATUS
1074 cm_fw_roam_sync_propagation(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
1075 			    struct roam_offload_synch_ind *roam_synch_data)
1076 {
1077 	QDF_STATUS status;
1078 	struct wlan_objmgr_vdev *vdev;
1079 	struct cnx_mgr *cm_ctx;
1080 	struct cm_roam_req *roam_req = NULL;
1081 	struct cm_vdev_join_rsp *rsp = NULL;
1082 	wlan_cm_id cm_id;
1083 	struct wlan_objmgr_pdev *pdev;
1084 	struct wlan_cm_connect_resp *connect_rsp;
1085 	bool eht_capab = false;
1086 
1087 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
1088 						    WLAN_MLME_SB_ID);
1089 
1090 	if (!vdev) {
1091 		mlme_err("vdev object is NULL");
1092 		return QDF_STATUS_E_NULL_VALUE;
1093 	}
1094 
1095 	pdev = wlan_vdev_get_pdev(vdev);
1096 	if (!pdev) {
1097 		status = QDF_STATUS_E_FAILURE;
1098 		goto rel_ref;
1099 	}
1100 
1101 	cm_ctx = cm_get_cm_ctx(vdev);
1102 	if (!cm_ctx) {
1103 		status = QDF_STATUS_E_FAILURE;
1104 		goto rel_ref;
1105 	}
1106 
1107 	roam_req = cm_get_first_roam_command(vdev);
1108 	if (!roam_req) {
1109 		mlme_err("Failed to find roam req from list");
1110 		cm_id = CM_ID_INVALID;
1111 		status = QDF_STATUS_E_FAILURE;
1112 		goto error;
1113 	}
1114 	wlan_rec_conn_info(vdev_id, DEBUG_CONN_ROAMING,
1115 			   roam_synch_data->bssid.bytes, 0, 0);
1116 
1117 	cm_roam_update_mlo_mgr_info(vdev, roam_synch_data);
1118 	cm_roam_ml_clear_prev_ap_keys(vdev);
1119 
1120 	cm_id = roam_req->cm_id;
1121 	rsp = qdf_mem_malloc(sizeof(struct cm_vdev_join_rsp));
1122 	if (!rsp) {
1123 		status = QDF_STATUS_E_NOMEM;
1124 		goto error;
1125 	}
1126 	status = cm_fill_roam_info(vdev, roam_synch_data, rsp, cm_id);
1127 	if (QDF_IS_STATUS_ERROR(status)) {
1128 		mlme_err(CM_PREFIX_FMT " fail to prepare rsp",
1129 			 CM_PREFIX_REF(vdev_id, cm_id));
1130 		goto error;
1131 	}
1132 
1133 	connect_rsp = &rsp->connect_rsp;
1134 	cm_update_scan_db_on_roam_success(vdev, connect_rsp,
1135 					  roam_synch_data, cm_id);
1136 
1137 	status = cm_csr_connect_rsp(vdev, rsp);
1138 	if (QDF_IS_STATUS_ERROR(status)) {
1139 		mlme_err("Roam sync propagation failed, abort roaming");
1140 		goto error;
1141 	}
1142 
1143 	cm_process_roam_keys(vdev, rsp, cm_id);
1144 	/*
1145 	 * Re-enable the disabled link on roaming as decision
1146 	 * will be taken again to disable the link on roam sync completion.
1147 	 */
1148 	if (wlan_vdev_mlme_is_mlo_vdev(vdev))
1149 		policy_mgr_move_vdev_from_disabled_to_connection_tbl(psoc,
1150 								     vdev_id);
1151 	cm_mlo_roam_copy_partner_info(connect_rsp, roam_synch_data);
1152 	mlo_roam_init_cu_bpcc(vdev, roam_synch_data);
1153 	mlo_roam_set_link_id(vdev, roam_synch_data);
1154 
1155 	/**
1156 	 * Don't send roam_sync complete for MLO link vdevs.
1157 	 * Send only for legacy STA/MLO STA vdev.
1158 	 */
1159 	if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) {
1160 		cm_inform_dlm_connect_complete(cm_ctx->vdev, connect_rsp);
1161 		wlan_p2p_status_connect(vdev);
1162 
1163 		if (!cm_csr_is_ss_wait_for_key(vdev_id)) {
1164 			mlme_debug(CM_PREFIX_FMT "WLAN link up with AP = "
1165 				   QDF_MAC_ADDR_FMT,
1166 				   CM_PREFIX_REF(vdev_id, cm_id),
1167 				   QDF_MAC_ADDR_REF(connect_rsp->bssid.bytes));
1168 			cm_roam_start_init_on_connect(pdev, vdev_id);
1169 		}
1170 		wlan_cm_tgt_send_roam_sync_complete_cmd(psoc, vdev_id);
1171 		mlo_roam_update_connected_links(vdev, connect_rsp);
1172 		mlo_set_single_link_ml_roaming(psoc, vdev_id,
1173 					       false);
1174 	}
1175 	cm_connect_info(vdev, true, &connect_rsp->bssid, &connect_rsp->ssid,
1176 			connect_rsp->freq);
1177 	wlan_tdls_notify_sta_connect(vdev_id,
1178 				     mlme_get_tdls_chan_switch_prohibited(vdev),
1179 				     mlme_get_tdls_prohibited(vdev), vdev);
1180 
1181 	wlan_cm_update_scan_mlme_info(vdev, connect_rsp);
1182 	cm_update_associated_ch_info(vdev, true);
1183 
1184 	status = cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_ROAM_DONE,
1185 					  sizeof(*roam_synch_data),
1186 					  roam_synch_data);
1187 	if (QDF_IS_STATUS_ERROR(status)) {
1188 		mlme_err(CM_PREFIX_FMT " fail to post WLAN_CM_SM_EV_ROAM_DONE",
1189 			 CM_PREFIX_REF(vdev_id, cm_id));
1190 		goto error;
1191 	}
1192 
1193 	if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev))
1194 		mlo_roam_update_connected_links(vdev, connect_rsp);
1195 	mlme_cm_osif_connect_complete(vdev, connect_rsp);
1196 	mlme_cm_osif_roam_complete(vdev);
1197 
1198 	if (wlan_vdev_mlme_is_mlo_vdev(vdev))
1199 		mlo_roam_copy_reassoc_rsp(vdev, connect_rsp);
1200 
1201 	mlme_debug(CM_PREFIX_FMT, CM_PREFIX_REF(vdev_id, cm_id));
1202 	cm_remove_cmd(cm_ctx, &cm_id);
1203 
1204 	wlan_psoc_mlme_get_11be_capab(psoc, &eht_capab);
1205 	if (eht_capab) {
1206 		status = policy_mgr_current_connections_update(
1207 				psoc, vdev_id,
1208 				connect_rsp->freq,
1209 				POLICY_MGR_UPDATE_REASON_LFR3_ROAM,
1210 				POLICY_MGR_DEF_REQ_ID);
1211 		if (status == QDF_STATUS_E_NOSUPPORT)
1212 			status = QDF_STATUS_SUCCESS;
1213 		else if (status == QDF_STATUS_E_FAILURE)
1214 			mlme_err("Failed to take next action LFR3_ROAM");
1215 	}
1216 
1217 error:
1218 	if (rsp)
1219 		wlan_cm_free_connect_rsp(rsp);
1220 
1221 	if (QDF_IS_STATUS_ERROR(status))
1222 		mlo_update_connected_links(vdev, 0);
1223 rel_ref:
1224 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
1225 
1226 	return status;
1227 }
1228 
1229 #ifdef WLAN_FEATURE_11BE_MLO
1230 static void
1231 cm_get_and_disable_link_from_roam_ind(struct wlan_objmgr_psoc *psoc,
1232 				      uint8_t vdev_id,
1233 				      struct roam_offload_synch_ind *synch_data)
1234 {
1235 	uint8_t i;
1236 	struct wlan_objmgr_vdev *vdev;
1237 
1238 	for (i = 0; i < synch_data->num_setup_links; i++) {
1239 		if (synch_data->ml_link[i].vdev_id == vdev_id &&
1240 		    synch_data->ml_link[i].flags & CM_ROAM_LINK_FLAG_DISABLE) {
1241 			mlme_info("Vdev %d: link id %d flags 0x%x, indicate link disable",
1242 				  vdev_id, synch_data->ml_link[i].link_id,
1243 				  synch_data->ml_link[i].flags);
1244 			policy_mgr_move_vdev_from_connection_to_disabled_tbl(
1245 								psoc, vdev_id);
1246 
1247 			vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
1248 								    vdev_id,
1249 								    WLAN_MLME_SB_ID);
1250 			if (!vdev) {
1251 				mlme_debug("no vdev for id %d", vdev_id);
1252 				break;
1253 			}
1254 			ml_nlink_set_curr_force_inactive_state(
1255 				psoc, vdev, 1 << synch_data->ml_link[i].link_id,
1256 				LINK_ADD);
1257 			ml_nlink_init_concurrency_link_request(psoc, vdev);
1258 			wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
1259 			break;
1260 		}
1261 	}
1262 }
1263 #else
1264 static inline void
1265 cm_get_and_disable_link_from_roam_ind(struct wlan_objmgr_psoc *psoc,
1266 				      uint8_t vdev_id,
1267 				      struct roam_offload_synch_ind *synch_data)
1268 {}
1269 #endif
1270 QDF_STATUS cm_fw_roam_complete(struct cnx_mgr *cm_ctx, void *data)
1271 {
1272 	struct roam_offload_synch_ind *roam_synch_data;
1273 	struct wlan_objmgr_pdev *pdev;
1274 	struct wlan_objmgr_psoc *psoc;
1275 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1276 	uint8_t vdev_id;
1277 
1278 	roam_synch_data = (struct roam_offload_synch_ind *)data;
1279 	vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
1280 
1281 	pdev = wlan_vdev_get_pdev(cm_ctx->vdev);
1282 	if (!pdev) {
1283 		mlme_err("Failed to find pdev");
1284 		status = QDF_STATUS_E_FAILURE;
1285 		goto end;
1286 	}
1287 
1288 	psoc = wlan_pdev_get_psoc(pdev);
1289 	if (!pdev) {
1290 		mlme_err("Failed to find psoc");
1291 		status = QDF_STATUS_E_FAILURE;
1292 		goto end;
1293 	}
1294 
1295 	/* Handle one race condition that if candidate is already
1296 	 *selected & FW has gone ahead with roaming or about to go
1297 	 * ahead when set_band comes, it will be complicated for FW
1298 	 * to stop the current roaming. Instead, host will check the
1299 	 * roam sync to make sure the new AP is not on disable freq
1300 	 * or disconnect the AP.
1301 	 */
1302 	if (wlan_reg_is_disable_for_pwrmode(pdev, roam_synch_data->chan_freq,
1303 					    REG_CURRENT_PWR_MODE)) {
1304 		mlo_disconnect(cm_ctx->vdev, CM_ROAM_DISCONNECT,
1305 			       REASON_OPER_CHANNEL_BAND_CHANGE, NULL);
1306 		status = QDF_STATUS_E_FAILURE;
1307 		goto end;
1308 	}
1309 
1310 	/*
1311 	 * Following operations need to be done once roam sync
1312 	 * completion is sent to FW, hence called here:
1313 	 * 1) Firmware has already updated DBS policy. Update connection
1314 	 *	  table in the host driver.
1315 	 * 2) Force SCC switch if needed
1316 	 */
1317 	/* first update connection info from wma interface */
1318 	status = policy_mgr_update_connection_info(psoc, vdev_id);
1319 	if (status == QDF_STATUS_NOT_INITIALIZED)
1320 		policy_mgr_incr_active_session(psoc, QDF_STA_MODE, vdev_id);
1321 
1322 	/* Check if FW as indicated this link as disabled */
1323 	cm_get_and_disable_link_from_roam_ind(psoc, vdev_id, roam_synch_data);
1324 
1325 	/* then update remaining parameters from roam sync ctx */
1326 	if (roam_synch_data->hw_mode_trans_present)
1327 		policy_mgr_hw_mode_transition_cb(
1328 		roam_synch_data->hw_mode_trans_ind.old_hw_mode_index,
1329 		roam_synch_data->hw_mode_trans_ind.new_hw_mode_index,
1330 		roam_synch_data->hw_mode_trans_ind.num_vdev_mac_entries,
1331 		roam_synch_data->hw_mode_trans_ind.vdev_mac_map,
1332 		0, NULL, psoc);
1333 	ml_nlink_conn_change_notify(
1334 			psoc, vdev_id,
1335 			ml_nlink_roam_sync_completion_evt, NULL);
1336 
1337 	if (roam_synch_data->pmk_len) {
1338 		mlme_debug("Received pmk in roam sync. Length: %d",
1339 			   roam_synch_data->pmk_len);
1340 		cm_check_and_set_sae_single_pmk_cap(psoc, vdev_id,
1341 						    roam_synch_data->pmk,
1342 						    roam_synch_data->pmk_len);
1343 	}
1344 
1345 	cm_csr_send_set_ie(cm_ctx->vdev);
1346 
1347 	if (ucfg_pkt_capture_get_pktcap_mode(psoc))
1348 		ucfg_pkt_capture_record_channel(cm_ctx->vdev);
1349 
1350 	/*
1351 	 * Firmware will take care of checking hi_scan rssi delta, take care of
1352 	 * legacy -> legacy hi-rssi roam also if self mld roam supported.
1353 	 */
1354 	if (!wlan_cm_is_self_mld_roam_supported(psoc)) {
1355 		if (WLAN_REG_IS_24GHZ_CH_FREQ(roam_synch_data->chan_freq)) {
1356 			wlan_cm_set_disable_hi_rssi(pdev,
1357 						    vdev_id, false);
1358 		} else {
1359 			wlan_cm_set_disable_hi_rssi(pdev,
1360 						    vdev_id, true);
1361 			mlme_debug("Disabling HI_RSSI, AP freq=%d rssi %d vdev id %d",
1362 				   roam_synch_data->chan_freq,
1363 				   roam_synch_data->rssi, vdev_id);
1364 		}
1365 	}
1366 	policy_mgr_check_n_start_opportunistic_timer(psoc);
1367 
1368 	wlan_cm_handle_sta_sta_roaming_enablement(psoc, vdev_id);
1369 
1370 	if (wlan_vdev_mlme_is_mlo_link_vdev(cm_ctx->vdev)) {
1371 		status = wlan_cm_roam_state_change(pdev,
1372 						   vdev_id,
1373 						   WLAN_ROAM_DEINIT,
1374 						   REASON_ROAM_HANDOFF_DONE);
1375 	}
1376 
1377 	if (roam_synch_data->auth_status == ROAM_AUTH_STATUS_AUTHENTICATED)
1378 		wlan_cm_roam_state_change(pdev, vdev_id,
1379 					  WLAN_ROAM_RSO_ENABLED,
1380 					  REASON_CONNECT);
1381 	else
1382 		/*
1383 		 * STA is just in associated state here, RSO
1384 		 * enable will be sent once EAP & EAPOL will be done by
1385 		 * user-space and after set key response is received.
1386 		 *
1387 		 * When firmware roaming state is connected, EAP/EAPOL will be
1388 		 * done at the supplicant. If EAP/EAPOL fails and supplicant
1389 		 * sends disconnect, then the RSO state machine sends
1390 		 * deinit directly to firmware without RSO stop with roam
1391 		 * scan mode value 0. So to avoid this move state to RSO
1392 		 * stop.
1393 		 */
1394 		wlan_cm_roam_state_change(pdev, vdev_id,
1395 					  WLAN_ROAM_RSO_STOPPED,
1396 					  REASON_DISCONNECTED);
1397 	policy_mgr_check_concurrent_intf_and_restart_sap(psoc,
1398 			wlan_util_vdev_mgr_get_acs_mode_for_vdev(cm_ctx->vdev));
1399 end:
1400 	return status;
1401 }
1402 
1403 static QDF_STATUS
1404 cm_disconnect_roam_invoke_fail(struct wlan_objmgr_vdev *vdev,
1405 			       wlan_cm_id cm_id)
1406 {
1407 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1408 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
1409 	bool nud_disconnect;
1410 	struct wlan_objmgr_psoc *psoc;
1411 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
1412 	struct rso_config *rso_cfg;
1413 
1414 	psoc = wlan_vdev_get_psoc(vdev);
1415 	if (!psoc) {
1416 		mlme_err(CM_PREFIX_FMT "psoc not found",
1417 			 CM_PREFIX_REF(vdev_id, cm_id));
1418 		return QDF_STATUS_E_INVAL;
1419 	}
1420 
1421 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
1422 	if (!mlme_obj)
1423 		return QDF_STATUS_E_NULL_VALUE;
1424 
1425 	rso_cfg = wlan_cm_get_rso_config(vdev);
1426 	if (!rso_cfg) {
1427 		mlme_err(CM_PREFIX_FMT "rso cfg not found",
1428 			 CM_PREFIX_REF(vdev_id, cm_id));
1429 		return QDF_STATUS_E_NULL_VALUE;
1430 	}
1431 
1432 	nud_disconnect = mlme_obj->cfg.lfr.disconnect_on_nud_roam_invoke_fail;
1433 	mlme_debug(CM_PREFIX_FMT "disconnect on NUD %d, source %d forced roaming %d",
1434 		   CM_PREFIX_REF(vdev_id, cm_id),
1435 		   nud_disconnect, rso_cfg->roam_invoke_source,
1436 		   rso_cfg->is_forced_roaming);
1437 
1438 	/*
1439 	 * If reassoc MAC from user space is broadcast MAC as:
1440 	 * "wpa_cli DRIVER FASTREASSOC ff:ff:ff:ff:ff:ff 0",
1441 	 * user space invoked roaming candidate selection will base on firmware
1442 	 * score algorithm, current connection will be kept if current AP has
1443 	 * highest score. It is requirement from customer which can avoid
1444 	 * ping-pong roaming.
1445 	 */
1446 	if (qdf_is_macaddr_broadcast(&rso_cfg->roam_invoke_bssid)) {
1447 		qdf_zero_macaddr(&rso_cfg->roam_invoke_bssid);
1448 		return status;
1449 	}
1450 
1451 	if (rso_cfg->roam_invoke_source == CM_ROAMING_HOST ||
1452 	    (rso_cfg->roam_invoke_source == CM_ROAMING_NUD_FAILURE &&
1453 	    (nud_disconnect || rso_cfg->is_forced_roaming)) ||
1454 	     rso_cfg->roam_invoke_source == CM_ROAMING_LINK_REMOVAL) {
1455 		rso_cfg->roam_invoke_source = CM_SOURCE_INVALID;
1456 		if (rso_cfg->is_forced_roaming)
1457 			rso_cfg->is_forced_roaming = false;
1458 		status = mlo_disconnect(vdev, CM_ROAM_DISCONNECT,
1459 					REASON_USER_TRIGGERED_ROAM_FAILURE,
1460 					NULL);
1461 	}
1462 
1463 	return status;
1464 }
1465 
1466 QDF_STATUS cm_fw_roam_invoke_fail(struct wlan_objmgr_psoc *psoc,
1467 				  uint8_t vdev_id)
1468 {
1469 	QDF_STATUS status;
1470 	struct wlan_objmgr_vdev *vdev;
1471 	wlan_cm_id cm_id = CM_ID_INVALID;
1472 	struct cnx_mgr *cm_ctx;
1473 	struct cm_roam_req *roam_req = NULL;
1474 
1475 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
1476 						    vdev_id,
1477 						    WLAN_MLME_SB_ID);
1478 	if (!vdev) {
1479 		mlme_err("vdev object is NULL");
1480 		return QDF_STATUS_E_NULL_VALUE;
1481 	}
1482 
1483 	cm_ctx = cm_get_cm_ctx(vdev);
1484 	if (!cm_ctx) {
1485 		status = QDF_STATUS_E_NULL_VALUE;
1486 		goto error;
1487 	}
1488 
1489 	roam_req = cm_get_first_roam_command(vdev);
1490 	if (roam_req)
1491 		cm_id = roam_req->cm_id;
1492 
1493 	status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_ROAM_INVOKE_FAIL,
1494 				     sizeof(wlan_cm_id), &cm_id);
1495 	if (QDF_IS_STATUS_ERROR(status))
1496 		cm_remove_cmd(cm_ctx, &cm_id);
1497 
1498 	cm_disconnect_roam_invoke_fail(vdev, cm_id);
1499 error:
1500 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
1501 	return status;
1502 }
1503 
1504 #ifdef FEATURE_WLAN_DIAG_SUPPORT
1505 static void cm_ho_fail_diag_event(void)
1506 {
1507 	WLAN_HOST_DIAG_EVENT_DEF(roam_connection,
1508 				 host_event_wlan_status_payload_type);
1509 	qdf_mem_zero(&roam_connection,
1510 		     sizeof(host_event_wlan_status_payload_type));
1511 
1512 	roam_connection.eventId = DIAG_WLAN_STATUS_DISCONNECT;
1513 	roam_connection.reason = DIAG_REASON_ROAM_HO_FAIL;
1514 	WLAN_HOST_DIAG_EVENT_REPORT(&roam_connection, EVENT_WLAN_STATUS_V2);
1515 }
1516 #else
1517 static inline void cm_ho_fail_diag_event(void) {}
1518 #endif
1519 
1520 #ifdef WLAN_FEATURE_11BE_MLO
1521 static bool
1522 cm_ho_fail_is_avoid_list_candidate(struct wlan_objmgr_vdev *vdev,
1523 				   struct cm_ho_fail_ind *ho_fail_ind)
1524 {
1525 	uint8_t link_info_iter = 0;
1526 	struct qdf_mac_addr peer_macaddr = {0};
1527 	struct mlo_link_info *mlo_link_info;
1528 	uint32_t akm;
1529 
1530 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
1531 		wlan_vdev_get_bss_peer_mac(vdev, &peer_macaddr);
1532 		akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
1533 		if (WLAN_CRYPTO_IS_WPA_WPA2(akm))
1534 			return true;
1535 
1536 		if (qdf_is_macaddr_equal(&peer_macaddr, &ho_fail_ind->bssid))
1537 			return false;
1538 		else
1539 			return true;
1540 	}
1541 
1542 	mlo_link_info = &vdev->mlo_dev_ctx->link_ctx->links_info[0];
1543 	for (link_info_iter = 0; link_info_iter < WLAN_MAX_ML_BSS_LINKS;
1544 	     link_info_iter++, mlo_link_info++) {
1545 		if (qdf_is_macaddr_equal(&mlo_link_info->ap_link_addr,
1546 					 &ho_fail_ind->bssid))
1547 			return false;
1548 	}
1549 
1550 	return true;
1551 }
1552 #else
1553 static bool
1554 cm_ho_fail_is_avoid_list_candidate(struct wlan_objmgr_vdev *vdev,
1555 				   struct cm_ho_fail_ind *ho_fail_ind)
1556 {
1557 	struct qdf_mac_addr peer_macaddr = {0};
1558 	uint32_t akm;
1559 
1560 	akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
1561 	if (WLAN_CRYPTO_IS_WPA_WPA2(akm))
1562 		return true;
1563 
1564 	wlan_vdev_get_bss_peer_mac(vdev, &peer_macaddr);
1565 	if (qdf_is_macaddr_equal(&peer_macaddr, &ho_fail_ind->bssid))
1566 		return false;
1567 	else
1568 		return true;
1569 }
1570 #endif
1571 
1572 static QDF_STATUS cm_handle_ho_fail(struct scheduler_msg *msg)
1573 {
1574 	QDF_STATUS status;
1575 	struct cm_ho_fail_ind *ind = NULL;
1576 	struct wlan_objmgr_vdev *vdev;
1577 	struct wlan_objmgr_pdev *pdev;
1578 	struct cnx_mgr *cm_ctx;
1579 	wlan_cm_id cm_id = CM_ID_INVALID;
1580 	struct reject_ap_info ap_info;
1581 	struct cm_roam_req *roam_req = NULL;
1582 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
1583 	struct wlan_objmgr_psoc *psoc;
1584 
1585 	if (!msg || !msg->bodyptr)
1586 		return QDF_STATUS_E_FAILURE;
1587 
1588 	ind = msg->bodyptr;
1589 
1590 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(ind->psoc, ind->vdev_id,
1591 						    WLAN_MLME_CM_ID);
1592 	if (!vdev) {
1593 		mlme_err("vdev_id: %d : vdev not found", ind->vdev_id);
1594 		qdf_mem_free(ind);
1595 		return QDF_STATUS_E_INVAL;
1596 	}
1597 
1598 	pdev = wlan_vdev_get_pdev(vdev);
1599 	if (!pdev) {
1600 		mlme_err("pdev object is NULL");
1601 		status = QDF_STATUS_E_NULL_VALUE;
1602 		goto error;
1603 	}
1604 
1605 	psoc = wlan_pdev_get_psoc(pdev);
1606 	if (!psoc) {
1607 		mlme_err("psoc object is NULL");
1608 		status = QDF_STATUS_E_NULL_VALUE;
1609 		goto error;
1610 	}
1611 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
1612 	if (!mlme_obj) {
1613 		mlme_err("Failed to mlme psoc obj");
1614 		status = QDF_STATUS_E_FAILURE;
1615 		goto error;
1616 	}
1617 
1618 	cm_ctx = cm_get_cm_ctx(vdev);
1619 	if (!cm_ctx) {
1620 		status = QDF_STATUS_E_NULL_VALUE;
1621 		goto error;
1622 	}
1623 
1624 	roam_req = cm_get_first_roam_command(vdev);
1625 	if (roam_req) {
1626 		mlme_debug("Roam req found, get cm id to remove it, before disconnect");
1627 		cm_id = roam_req->cm_id;
1628 	}
1629 	/* CPU freq is boosted during roam sync to improve roam latency,
1630 	 * upon HO failure reset that request to restore cpu freq back to normal
1631 	 */
1632 	mlme_cm_osif_perfd_reset_cpufreq();
1633 
1634 	cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_ROAM_HO_FAIL,
1635 			    sizeof(wlan_cm_id), &cm_id);
1636 
1637 	qdf_mem_zero(&ap_info, sizeof(struct reject_ap_info));
1638 	if (cm_ho_fail_is_avoid_list_candidate(vdev, ind)) {
1639 		ap_info.bssid = ind->bssid;
1640 		ap_info.reject_ap_type = DRIVER_AVOID_TYPE;
1641 		ap_info.reject_reason = REASON_ROAM_HO_FAILURE;
1642 		ap_info.source = ADDED_BY_DRIVER;
1643 		wlan_dlm_add_bssid_to_reject_list(pdev, &ap_info);
1644 	}
1645 
1646 	cm_ho_fail_diag_event();
1647 	wlan_roam_debug_log(ind->vdev_id,
1648 			    DEBUG_ROAM_SYNCH_FAIL,
1649 			    DEBUG_INVALID_PEER_ID, NULL, NULL, 0, 0);
1650 
1651 	status = mlo_disconnect(vdev, CM_MLME_DISCONNECT,
1652 				REASON_FW_TRIGGERED_ROAM_FAILURE, NULL);
1653 
1654 	if (mlme_obj->cfg.gen.fatal_event_trigger)
1655 		cds_flush_logs(WLAN_LOG_TYPE_FATAL,
1656 			       WLAN_LOG_INDICATOR_HOST_DRIVER,
1657 			       WLAN_LOG_REASON_ROAM_HO_FAILURE, false, false);
1658 
1659 	if (QDF_IS_STATUS_ERROR(status))
1660 		cm_remove_cmd(cm_ctx, &cm_id);
1661 
1662 error:
1663 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
1664 	qdf_mem_free(ind);
1665 
1666 	return QDF_STATUS_SUCCESS;
1667 }
1668 
1669 void cm_fw_ho_fail_req(struct wlan_objmgr_psoc *psoc,
1670 		       uint8_t vdev_id, struct qdf_mac_addr bssid)
1671 {
1672 	QDF_STATUS status;
1673 	struct scheduler_msg ind_msg = {0};
1674 	struct cm_ho_fail_ind *ind = NULL;
1675 
1676 	ind = qdf_mem_malloc(sizeof(*ind));
1677 	if (!ind)
1678 		return;
1679 
1680 	ind->vdev_id = vdev_id;
1681 	ind->psoc = psoc;
1682 	ind->bssid = bssid;
1683 
1684 	ind_msg.bodyptr = ind;
1685 	ind_msg.callback = cm_handle_ho_fail;
1686 
1687 	status = scheduler_post_message(QDF_MODULE_ID_MLME, QDF_MODULE_ID_OS_IF,
1688 					QDF_MODULE_ID_OS_IF, &ind_msg);
1689 
1690 	if (QDF_IS_STATUS_ERROR(status)) {
1691 		mlme_err("Failed to post HO fail indication on vdev_id %d",
1692 			 vdev_id);
1693 		qdf_mem_free(ind);
1694 		return;
1695 	}
1696 }
1697 
1698 QDF_STATUS wlan_cm_free_roam_synch_frame_ind(struct rso_config *rso_cfg)
1699 {
1700 	struct roam_synch_frame_ind *frame_ind;
1701 
1702 	if (!rso_cfg)
1703 		return QDF_STATUS_E_FAILURE;
1704 
1705 	frame_ind = &rso_cfg->roam_sync_frame_ind;
1706 
1707 	if (frame_ind->bcn_probe_rsp) {
1708 		qdf_mem_free(frame_ind->bcn_probe_rsp);
1709 		frame_ind->bcn_probe_rsp_len = 0;
1710 		frame_ind->bcn_probe_rsp = NULL;
1711 	}
1712 	if (frame_ind->link_bcn_probe_rsp) {
1713 		qdf_mem_free(frame_ind->link_bcn_probe_rsp);
1714 		frame_ind->link_bcn_probe_rsp_len = 0;
1715 		frame_ind->link_bcn_probe_rsp = NULL;
1716 	}
1717 	if (frame_ind->reassoc_req) {
1718 		qdf_mem_free(frame_ind->reassoc_req);
1719 		frame_ind->reassoc_req_len = 0;
1720 		frame_ind->reassoc_req = NULL;
1721 	}
1722 	if (frame_ind->reassoc_rsp) {
1723 		qdf_mem_free(frame_ind->reassoc_rsp);
1724 		frame_ind->reassoc_rsp_len = 0;
1725 		frame_ind->reassoc_rsp = NULL;
1726 	}
1727 
1728 	return QDF_STATUS_SUCCESS;
1729 }
1730