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