xref: /wlan-dirver/qcacld-3.0/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c (revision a4715adff446403c8635800dda08025c59945475)
1 /*
2  * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /*
19  * DOC: wlan_cm_roam_api.c
20  *
21  * Implementation for the Common Roaming interfaces.
22  */
23 
24 #include "wlan_cm_roam_api.h"
25 #include "wlan_vdev_mlme_api.h"
26 #include "wlan_mlme_main.h"
27 #include "wlan_policy_mgr_api.h"
28 #include <wmi_unified_priv.h>
29 #include <../../core/src/wlan_cm_vdev_api.h>
30 #include "wlan_crypto_global_api.h"
31 #include <wlan_cm_api.h>
32 #include "connection_mgr/core/src/wlan_cm_roam.h"
33 #include "wlan_cm_roam_api.h"
34 #include "wlan_dlm_api.h"
35 #include <../../core/src/wlan_cm_roam_i.h>
36 #include "wlan_reg_ucfg_api.h"
37 #include "wlan_connectivity_logging.h"
38 #include "target_if.h"
39 #include "wlan_mlo_mgr_roam.h"
40 
41 /* Support for "Fast roaming" (i.e., ESE, LFR, or 802.11r.) */
42 #define BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN 15
43 #define CM_MIN_RSSI 0 /* 0dbm */
44 
45 #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD)
46 QDF_STATUS
47 wlan_cm_enable_roaming_on_connected_sta(struct wlan_objmgr_pdev *pdev,
48 					uint8_t vdev_id)
49 {
50 	uint32_t op_ch_freq_list[MAX_NUMBER_OF_CONC_CONNECTIONS];
51 	uint8_t vdev_id_list[MAX_NUMBER_OF_CONC_CONNECTIONS];
52 	uint32_t sta_vdev_id = WLAN_INVALID_VDEV_ID;
53 	uint32_t count, idx;
54 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
55 
56 	sta_vdev_id = policy_mgr_get_roam_enabled_sta_session_id(psoc, vdev_id);
57 	if (sta_vdev_id != WLAN_UMAC_VDEV_ID_MAX)
58 		return QDF_STATUS_E_FAILURE;
59 
60 	count = policy_mgr_get_mode_specific_conn_info(psoc,
61 						       op_ch_freq_list,
62 						       vdev_id_list,
63 						       PM_STA_MODE);
64 	if (!count)
65 		return QDF_STATUS_E_FAILURE;
66 
67 	/*
68 	 * Loop through all connected STA vdevs and roaming will be enabled
69 	 * on the STA that has a different vdev id from the one passed as
70 	 * input and has non zero roam trigger value.
71 	 */
72 	for (idx = 0; idx < count; idx++) {
73 		if (vdev_id_list[idx] != vdev_id &&
74 		    mlme_get_roam_trigger_bitmap(psoc, vdev_id_list[idx])) {
75 			sta_vdev_id = vdev_id_list[idx];
76 			break;
77 		}
78 	}
79 
80 	if (sta_vdev_id == WLAN_INVALID_VDEV_ID)
81 		return QDF_STATUS_E_FAILURE;
82 
83 	if (mlo_check_is_given_vdevs_on_same_mld(psoc, sta_vdev_id, vdev_id)) {
84 		mlme_debug("RSO_CFG: vdev:%d , vdev:%d are on same MLD skip RSO enable",
85 			   sta_vdev_id, vdev_id);
86 
87 		return QDF_STATUS_E_FAILURE;
88 	}
89 
90 	mlme_debug("ROAM: Enabling roaming on vdev[%d]", sta_vdev_id);
91 
92 	return cm_roam_state_change(pdev,
93 				    sta_vdev_id,
94 				    WLAN_ROAM_RSO_ENABLED,
95 				    REASON_CTX_INIT,
96 				    NULL, false);
97 }
98 
99 QDF_STATUS wlan_cm_roam_state_change(struct wlan_objmgr_pdev *pdev,
100 				     uint8_t vdev_id,
101 				     enum roam_offload_state requested_state,
102 				     uint8_t reason)
103 {
104 	return cm_roam_state_change(pdev, vdev_id, requested_state, reason,
105 				    NULL, false);
106 }
107 
108 QDF_STATUS wlan_cm_roam_send_rso_cmd(struct wlan_objmgr_psoc *psoc,
109 				     uint8_t vdev_id, uint8_t rso_command,
110 				     uint8_t reason)
111 {
112 	return cm_roam_send_rso_cmd(psoc, vdev_id, rso_command, reason);
113 }
114 
115 void wlan_cm_handle_sta_sta_roaming_enablement(struct wlan_objmgr_psoc *psoc,
116 					       uint8_t vdev_id)
117 {
118 	return cm_handle_sta_sta_roaming_enablement(psoc, vdev_id);
119 }
120 
121 QDF_STATUS
122 wlan_roam_update_cfg(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
123 		     uint8_t reason)
124 {
125 	if (!MLME_IS_ROAM_STATE_RSO_ENABLED(psoc, vdev_id)) {
126 		mlme_debug("Update cfg received while ROAM RSO not started");
127 		return QDF_STATUS_E_INVAL;
128 	}
129 
130 	return cm_roam_send_rso_cmd(psoc, vdev_id, ROAM_SCAN_OFFLOAD_UPDATE_CFG,
131 				    reason);
132 }
133 
134 #endif
135 
136 void
137 cm_update_associated_ch_info(struct wlan_objmgr_vdev *vdev, bool is_update)
138 {
139 	struct mlme_legacy_priv *mlme_priv;
140 	struct wlan_channel *des_chan;
141 	struct assoc_channel_info *assoc_chan_info;
142 	struct wlan_objmgr_pdev *pdev;
143 	enum phy_ch_width ch_width;
144 	QDF_STATUS status;
145 	uint8_t band_mask;
146 
147 	pdev = wlan_vdev_get_pdev(vdev);
148 	if (!pdev) {
149 		mlme_err("invalid pdev");
150 		return;
151 	}
152 
153 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
154 	if (!mlme_priv)
155 		return;
156 
157 	assoc_chan_info = &mlme_priv->connect_info.assoc_chan_info;
158 	if (!is_update) {
159 		assoc_chan_info->assoc_ch_width = CH_WIDTH_INVALID;
160 		return;
161 	}
162 
163 	des_chan = wlan_vdev_mlme_get_des_chan(vdev);
164 	if (!des_chan)
165 		return;
166 
167 	/* If operating mode is STA / P2P-CLI then get the channel width
168 	 * from phymode. This is due the reason where actual operating
169 	 * channel width is configured as part of WMI_PEER_ASSOC_CMDID
170 	 * which could be downgraded while the peer associated.
171 	 * If there is a failure or operating mode is not STA / P2P-CLI
172 	 * then get channel width from wlan_channel.
173 	 */
174 	status = wlan_mlme_get_sta_ch_width(vdev, &ch_width);
175 	if (QDF_IS_STATUS_ERROR(status))
176 		assoc_chan_info->assoc_ch_width = des_chan->ch_width;
177 	else
178 		assoc_chan_info->assoc_ch_width = ch_width;
179 
180 	if (WLAN_REG_IS_24GHZ_CH_FREQ(des_chan->ch_freq) &&
181 	    des_chan->ch_width == CH_WIDTH_40MHZ) {
182 		if (des_chan->ch_cfreq1 == des_chan->ch_freq + BW_10_MHZ)
183 			assoc_chan_info->sec_2g_freq =
184 					des_chan->ch_freq + BW_20_MHZ;
185 		if (des_chan->ch_cfreq1 == des_chan->ch_freq - BW_10_MHZ)
186 			assoc_chan_info->sec_2g_freq =
187 					des_chan->ch_freq - BW_20_MHZ;
188 	} else if (des_chan->ch_width == CH_WIDTH_320MHZ) {
189 		if (WLAN_REG_IS_6GHZ_CHAN_FREQ(des_chan->ch_freq))
190 			band_mask = BIT(REG_BAND_6G);
191 		else
192 			band_mask = BIT(REG_BAND_5G);
193 		assoc_chan_info->cen320_freq =
194 			wlan_reg_chan_band_to_freq(pdev,
195 						   des_chan->ch_freq_seg2,
196 						   band_mask);
197 
198 		mlme_debug("ch_freq_seg2: %d, cen320_freq: %d",
199 			   des_chan->ch_freq_seg2,
200 			   assoc_chan_info->cen320_freq);
201 	}
202 
203 	mlme_debug("ch width :%d, ch_freq:%d, ch_cfreq1:%d, sec_2g_freq:%d",
204 		   assoc_chan_info->assoc_ch_width, des_chan->ch_freq,
205 		   des_chan->ch_cfreq1, assoc_chan_info->sec_2g_freq);
206 }
207 
208 char *cm_roam_get_requestor_string(enum wlan_cm_rso_control_requestor requestor)
209 {
210 	switch (requestor) {
211 	case RSO_INVALID_REQUESTOR:
212 	default:
213 		return "No requestor";
214 	case RSO_START_BSS:
215 		return "SAP start";
216 	case RSO_CHANNEL_SWITCH:
217 		return "CSA";
218 	case RSO_CONNECT_START:
219 		return "STA connection";
220 	case RSO_SAP_CHANNEL_CHANGE:
221 		return "SAP Ch switch";
222 	case RSO_NDP_CON_ON_NDI:
223 		return "NDP connection";
224 	case RSO_SET_PCL:
225 		return "Set PCL";
226 	}
227 }
228 
229 QDF_STATUS
230 wlan_cm_rso_set_roam_trigger(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
231 			     struct wlan_roam_triggers *trigger)
232 {
233 	QDF_STATUS status;
234 	struct wlan_objmgr_vdev *vdev;
235 
236 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
237 						    WLAN_MLME_CM_ID);
238 	if (!vdev) {
239 		mlme_err("vdev object is NULL");
240 		return QDF_STATUS_E_INVAL;
241 	}
242 
243 	status = cm_roam_acquire_lock(vdev);
244 	if (QDF_IS_STATUS_ERROR(status))
245 		goto release_ref;
246 
247 	status = cm_rso_set_roam_trigger(pdev, vdev_id, trigger);
248 
249 	cm_roam_release_lock(vdev);
250 
251 release_ref:
252 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
253 
254 	return status;
255 }
256 
257 QDF_STATUS wlan_cm_disable_rso(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
258 			       enum wlan_cm_rso_control_requestor requestor,
259 			       uint8_t reason)
260 {
261 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
262 	QDF_STATUS status;
263 
264 	if (reason == REASON_DRIVER_DISABLED && requestor)
265 		mlme_set_operations_bitmap(psoc, vdev_id, requestor, false);
266 
267 	mlme_debug("ROAM_CONFIG: vdev[%d] Disable roaming - requestor:%s",
268 		   vdev_id, cm_roam_get_requestor_string(requestor));
269 
270 	status = cm_roam_state_change(pdev, vdev_id, WLAN_ROAM_RSO_STOPPED,
271 				      REASON_DRIVER_DISABLED, NULL, false);
272 
273 	return status;
274 }
275 
276 QDF_STATUS wlan_cm_enable_rso(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
277 			      enum wlan_cm_rso_control_requestor requestor,
278 			      uint8_t reason)
279 {
280 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
281 	QDF_STATUS status;
282 
283 	if (reason == REASON_DRIVER_ENABLED && requestor)
284 		mlme_set_operations_bitmap(psoc, vdev_id, requestor, true);
285 
286 	mlme_debug("ROAM_CONFIG: vdev[%d] Enable roaming - requestor:%s",
287 		   vdev_id, cm_roam_get_requestor_string(requestor));
288 
289 	status = cm_roam_state_change(pdev, vdev_id, WLAN_ROAM_RSO_ENABLED,
290 				      REASON_DRIVER_ENABLED, NULL, false);
291 
292 	return status;
293 }
294 
295 bool wlan_cm_host_roam_in_progress(struct wlan_objmgr_psoc *psoc,
296 				   uint8_t vdev_id)
297 {
298 	struct wlan_objmgr_vdev *vdev;
299 	bool host_roam_in_progress = false;
300 
301 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
302 						    WLAN_MLME_CM_ID);
303 	if (!vdev) {
304 		mlme_err("vdev object is NULL for vdev %d", vdev_id);
305 		return host_roam_in_progress;
306 	}
307 
308 	if (wlan_cm_is_vdev_roam_preauth_state(vdev) ||
309 	    wlan_cm_is_vdev_roam_reassoc_state(vdev))
310 		host_roam_in_progress = true;
311 
312 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
313 
314 	return host_roam_in_progress;
315 }
316 
317 bool wlan_cm_roaming_in_progress(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id)
318 {
319 	bool roaming_in_progress = false;
320 	struct wlan_objmgr_vdev *vdev;
321 	enum QDF_OPMODE opmode;
322 
323 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
324 						    WLAN_MLME_CM_ID);
325 	if (!vdev)
326 		return roaming_in_progress;
327 
328 	opmode = wlan_vdev_mlme_get_opmode(vdev);
329 	if (opmode != QDF_STA_MODE && opmode != QDF_P2P_CLIENT_MODE)
330 		goto exit;
331 
332 	roaming_in_progress = wlan_cm_is_vdev_roaming(vdev);
333 
334 exit:
335 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
336 
337 	return roaming_in_progress;
338 }
339 
340 QDF_STATUS wlan_cm_roam_stop_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
341 				 uint8_t reason)
342 {
343 	return cm_roam_stop_req(psoc, vdev_id, reason, NULL, false);
344 }
345 
346 bool wlan_cm_same_band_sta_allowed(struct wlan_objmgr_psoc *psoc)
347 {
348 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
349 	struct dual_sta_policy *dual_sta_policy;
350 
351 	if (!wlan_mlme_get_dual_sta_roaming_enabled(psoc))
352 		return true;
353 
354 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
355 	if (!mlme_obj)
356 		return true;
357 
358 	dual_sta_policy = &mlme_obj->cfg.gen.dual_sta_policy;
359 	if (dual_sta_policy->primary_vdev_id != WLAN_UMAC_VDEV_ID_MAX &&
360 	    dual_sta_policy->concurrent_sta_policy ==
361 	    QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY)
362 		return true;
363 
364 	return false;
365 }
366 
367 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
368 #ifdef FEATURE_RX_LINKSPEED_ROAM_TRIGGER
369 QDF_STATUS wlan_cm_send_roam_linkspeed_state(struct scheduler_msg *msg)
370 {
371 	QDF_STATUS status = QDF_STATUS_SUCCESS;
372 	struct roam_link_speed_cfg *link_speed_cfg;
373 	struct roam_disable_cfg  roam_link_speed_cfg;
374 
375 	if (!msg || !msg->bodyptr)
376 		return QDF_STATUS_E_FAILURE;
377 
378 	link_speed_cfg = msg->bodyptr;
379 	roam_link_speed_cfg.vdev_id = link_speed_cfg->vdev_id;
380 	roam_link_speed_cfg.cfg = link_speed_cfg->is_link_speed_good;
381 	status = wlan_cm_tgt_send_roam_linkspeed_state(link_speed_cfg->psoc,
382 						       &roam_link_speed_cfg);
383 	qdf_mem_free(link_speed_cfg);
384 
385 	return status;
386 }
387 
388 void wlan_cm_roam_link_speed_update(struct wlan_objmgr_psoc *psoc,
389 				    uint8_t vdev_id,
390 				    bool is_link_speed_good)
391 {
392 	QDF_STATUS qdf_status;
393 	struct scheduler_msg msg = {0};
394 	struct roam_link_speed_cfg *link_speed_cfg;
395 
396 	link_speed_cfg = qdf_mem_malloc(sizeof(*link_speed_cfg));
397 	if (!link_speed_cfg)
398 		return;
399 
400 	link_speed_cfg->psoc = psoc;
401 	link_speed_cfg->vdev_id = vdev_id;
402 	link_speed_cfg->is_link_speed_good = is_link_speed_good;
403 
404 	msg.bodyptr = link_speed_cfg;
405 	msg.callback = wlan_cm_send_roam_linkspeed_state;
406 
407 	qdf_status = scheduler_post_message(QDF_MODULE_ID_MLME,
408 					    QDF_MODULE_ID_OS_IF,
409 					    QDF_MODULE_ID_OS_IF, &msg);
410 
411 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
412 		mlme_err("post msg failed");
413 		qdf_mem_free(link_speed_cfg);
414 	}
415 }
416 
417 bool wlan_cm_is_linkspeed_roam_trigger_supported(struct wlan_objmgr_psoc *psoc)
418 {
419 	struct wmi_unified *wmi_handle;
420 
421 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
422 	if (!wmi_handle) {
423 		mlme_debug("Invalid WMI handle");
424 		return false;
425 	}
426 
427 	return wmi_service_enabled(wmi_handle,
428 				   wmi_service_linkspeed_roam_trigger_support);
429 }
430 #endif
431 
432 QDF_STATUS
433 wlan_cm_fw_roam_abort_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
434 {
435 	return cm_fw_roam_abort_req(psoc, vdev_id);
436 }
437 
438 uint32_t wlan_cm_get_roam_band_value(struct wlan_objmgr_psoc *psoc,
439 				     struct wlan_objmgr_vdev *vdev)
440 {
441 	struct cm_roam_values_copy config;
442 	uint32_t band_mask;
443 
444 	wlan_cm_roam_cfg_get_value(psoc, wlan_vdev_get_id(vdev), ROAM_BAND,
445 				   &config);
446 
447 	band_mask = config.uint_value;
448 	mlme_debug("[ROAM BAND] band mask:%d", band_mask);
449 	return band_mask;
450 }
451 
452 void wlan_cm_roam_activate_pcl_per_vdev(struct wlan_objmgr_psoc *psoc,
453 					uint8_t vdev_id, bool pcl_per_vdev)
454 {
455 	struct wlan_objmgr_vdev *vdev;
456 	struct mlme_legacy_priv *mlme_priv;
457 
458 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
459 						    WLAN_MLME_NB_ID);
460 	if (!vdev) {
461 		mlme_err("vdev object is NULL");
462 		return;
463 	}
464 
465 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
466 	if (!mlme_priv) {
467 		mlme_err("vdev legacy private object is NULL");
468 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
469 		return;
470 	}
471 
472 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
473 
474 	/* value - true (vdev pcl) false - pdev pcl */
475 	mlme_priv->cm_roam.pcl_vdev_cmd_active = pcl_per_vdev;
476 	mlme_debug("CM_ROAM: vdev[%d] SET PCL cmd level - [%s]", vdev_id,
477 		   pcl_per_vdev ? "VDEV" : "PDEV");
478 }
479 
480 bool wlan_cm_roam_is_pcl_per_vdev_active(struct wlan_objmgr_psoc *psoc,
481 					 uint8_t vdev_id)
482 {
483 	struct wlan_objmgr_vdev *vdev;
484 	struct mlme_legacy_priv *mlme_priv;
485 
486 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
487 						    WLAN_MLME_NB_ID);
488 	if (!vdev) {
489 		mlme_err("vdev object is NULL");
490 		return false;
491 	}
492 
493 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
494 	if (!mlme_priv) {
495 		mlme_err("vdev legacy private object is NULL");
496 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
497 		return false;
498 	}
499 
500 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
501 
502 	return mlme_priv->cm_roam.pcl_vdev_cmd_active;
503 }
504 
505 /**
506  * wlan_cm_dual_sta_is_freq_allowed() - This API is used to check if the
507  * provided frequency is allowed for the 2nd STA vdev for connection.
508  * @psoc: Pointer to PSOC object
509  * @freq: Frequency in the given frequency list for the STA that is about to
510  * connect
511  * @connected_sta_freq: 1st connected sta freq
512  *
513  * Make sure to validate the STA+STA condition before calling this
514  *
515  * Return: True if this channel is allowed for connection when dual sta roaming
516  * is enabled
517  */
518 static bool
519 wlan_cm_dual_sta_is_freq_allowed(struct wlan_objmgr_psoc *psoc,
520 				 qdf_freq_t freq, qdf_freq_t connected_sta_freq)
521 {
522 	if (!connected_sta_freq)
523 		return true;
524 
525 	if (policy_mgr_2_freq_always_on_same_mac(psoc, freq,
526 						 connected_sta_freq))
527 		return false;
528 
529 	return true;
530 }
531 
532 void
533 wlan_cm_dual_sta_roam_update_connect_channels(struct wlan_objmgr_psoc *psoc,
534 					      struct scan_filter *filter)
535 {
536 	uint32_t i, num_channels = 0;
537 	uint32_t *channel_list;
538 	bool is_ch_allowed;
539 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
540 	struct wlan_mlme_cfg *mlme_cfg;
541 	struct dual_sta_policy *dual_sta_policy;
542 	uint32_t buff_len;
543 	char *chan_buff;
544 	uint32_t len = 0;
545 	uint32_t sta_count;
546 	qdf_freq_t op_ch_freq_list[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
547 	uint8_t vdev_id_list[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
548 
549 	filter->num_of_channels = 0;
550 	sta_count = policy_mgr_get_mode_specific_conn_info(psoc, op_ch_freq_list,
551 							   vdev_id_list,
552 							   PM_STA_MODE);
553 
554 	/* No need to fill freq list, if no other STA is in connected state */
555 	if (!sta_count)
556 		return;
557 
558 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
559 	if (!mlme_obj)
560 		return;
561 	dual_sta_policy = &mlme_obj->cfg.gen.dual_sta_policy;
562 	mlme_cfg = &mlme_obj->cfg;
563 
564 	mlme_debug("sta_count %d, primary vdev is %d dual sta roaming enabled %d",
565 		   sta_count, dual_sta_policy->primary_vdev_id,
566 		   wlan_mlme_get_dual_sta_roaming_enabled(psoc));
567 
568 	if (!wlan_mlme_get_dual_sta_roaming_enabled(psoc))
569 		return;
570 
571 	/*
572 	 * Check if primary iface is configured. If yes,
573 	 * then allow further STA connection to all
574 	 * available bands/channels irrespective of first
575 	 * STA connection band, which allow driver to
576 	 * connect with the best available AP present in
577 	 * environment, so that user can switch to second
578 	 * connection and mark it as primary.
579 	 */
580 	if (wlan_mlme_is_primary_interface_configured(psoc))
581 		return;
582 
583 	/*
584 	 * If an ML STA exists with more than one link, allow further STA
585 	 * connection to all available bands/channels irrespective of existing
586 	 * STA connection/link band. Link that is causing MCC with the second
587 	 * STA can be disabled post connection.
588 	 * TODO: Check if disabling the MCC link is allowed or not. TID to
589 	 * link mapping restricts disabling the link.
590 	 *
591 	 * If only one ML link is present, allow the second STA only on other
592 	 * mac than this link mac. If second STA is allowed on the same mac
593 	 * also, it may result in MCC and the link can't be disabled
594 	 * post connection as only one link is present.
595 	 */
596 	if (policy_mgr_is_mlo_sta_present(psoc) && sta_count > 1) {
597 		mlme_debug("Multi link mlo sta present");
598 		return;
599 	}
600 
601 	/*
602 	 * Get Reg domain valid channels and update to the scan filter
603 	 * if already 1st sta is in connected state. Don't allow channels
604 	 * on which the 1st STA is connected.
605 	 */
606 	num_channels = mlme_cfg->reg.valid_channel_list_num;
607 	channel_list = mlme_cfg->reg.valid_channel_freq_list;
608 
609 	/*
610 	 * Buffer of (num channel * 5) + 1  to consider the 4 char freq,
611 	 * 1 space after it for each channel and 1 to end the string
612 	 * with NULL.
613 	 */
614 	buff_len = (num_channels * 5) + 1;
615 	chan_buff = qdf_mem_malloc(buff_len);
616 	if (!chan_buff)
617 		return;
618 
619 	for (i = 0; i < num_channels; i++) {
620 		is_ch_allowed =
621 			wlan_cm_dual_sta_is_freq_allowed(psoc, channel_list[i],
622 							 op_ch_freq_list[0]);
623 		if (!is_ch_allowed)
624 			continue;
625 
626 		filter->chan_freq_list[filter->num_of_channels] =
627 					channel_list[i];
628 		filter->num_of_channels++;
629 
630 		len += qdf_scnprintf(chan_buff + len, buff_len - len,
631 				     "%d ", channel_list[i]);
632 	}
633 
634 	if (filter->num_of_channels)
635 		mlme_debug("Freq list (%d): %s", filter->num_of_channels,
636 			   chan_buff);
637 
638 	qdf_mem_free(chan_buff);
639 }
640 
641 void
642 wlan_cm_roam_set_vendor_btm_params(struct wlan_objmgr_psoc *psoc,
643 				   struct wlan_cm_roam_vendor_btm_params *param)
644 {
645 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
646 
647 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
648 	if (!mlme_obj)
649 		return;
650 
651 	qdf_mem_copy(&mlme_obj->cfg.lfr.vendor_btm_param, param,
652 		     sizeof(struct wlan_cm_roam_vendor_btm_params));
653 }
654 
655 void
656 wlan_cm_roam_get_vendor_btm_params(struct wlan_objmgr_psoc *psoc,
657 				   struct wlan_cm_roam_vendor_btm_params *param)
658 {
659 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
660 
661 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
662 	if (!mlme_obj)
663 		return;
664 
665 	qdf_mem_copy(param, &mlme_obj->cfg.lfr.vendor_btm_param,
666 		     sizeof(struct wlan_cm_roam_vendor_btm_params));
667 }
668 
669 void wlan_cm_set_psk_pmk(struct wlan_objmgr_pdev *pdev,
670 			 uint8_t vdev_id, uint8_t *psk_pmk,
671 			 uint8_t pmk_len)
672 {
673 	static struct rso_config *rso_cfg;
674 	struct wlan_objmgr_vdev *vdev;
675 
676 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
677 						    WLAN_MLME_CM_ID);
678 	if (!vdev)
679 		return;
680 
681 	rso_cfg = wlan_cm_get_rso_config(vdev);
682 	if (!rso_cfg) {
683 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
684 		return;
685 	}
686 	qdf_mem_zero(rso_cfg->psk_pmk, sizeof(rso_cfg->psk_pmk));
687 	if (psk_pmk)
688 		qdf_mem_copy(rso_cfg->psk_pmk, psk_pmk, pmk_len);
689 	rso_cfg->pmk_len = pmk_len;
690 
691 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_MLME, QDF_TRACE_LEVEL_DEBUG,
692 			   rso_cfg->psk_pmk, WLAN_MAX_PMK_DUMP_BYTES);
693 
694 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
695 }
696 
697 void wlan_cm_get_psk_pmk(struct wlan_objmgr_pdev *pdev,
698 			 uint8_t vdev_id, uint8_t *psk_pmk,
699 			 uint8_t *pmk_len)
700 {
701 	static struct rso_config *rso_cfg;
702 	struct wlan_objmgr_vdev *vdev;
703 
704 	if (!psk_pmk || !pmk_len)
705 		return;
706 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
707 						    WLAN_MLME_CM_ID);
708 	if (!vdev) {
709 		mlme_err("vdev object is NULL");
710 		return;
711 	}
712 	rso_cfg = wlan_cm_get_rso_config(vdev);
713 	if (!rso_cfg) {
714 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
715 		return;
716 	}
717 	qdf_mem_copy(psk_pmk, rso_cfg->psk_pmk, rso_cfg->pmk_len);
718 	*pmk_len = rso_cfg->pmk_len;
719 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
720 }
721 
722 void
723 wlan_cm_roam_get_score_delta_params(struct wlan_objmgr_psoc *psoc,
724 				    struct wlan_roam_triggers *params)
725 {
726 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
727 
728 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
729 	if (!mlme_obj)
730 		return;
731 
732 	params->score_delta_param[IDLE_ROAM_TRIGGER] =
733 			mlme_obj->cfg.trig_score_delta[IDLE_ROAM_TRIGGER];
734 	params->score_delta_param[BTM_ROAM_TRIGGER] =
735 			mlme_obj->cfg.trig_score_delta[BTM_ROAM_TRIGGER];
736 }
737 
738 void
739 wlan_cm_roam_get_min_rssi_params(struct wlan_objmgr_psoc *psoc,
740 				 struct wlan_roam_triggers *params)
741 {
742 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
743 
744 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
745 	if (!mlme_obj)
746 		return;
747 
748 	params->min_rssi_params[DEAUTH_MIN_RSSI] =
749 			mlme_obj->cfg.trig_min_rssi[DEAUTH_MIN_RSSI];
750 	params->min_rssi_params[BMISS_MIN_RSSI] =
751 			mlme_obj->cfg.trig_min_rssi[BMISS_MIN_RSSI];
752 	params->min_rssi_params[MIN_RSSI_2G_TO_5G_ROAM] =
753 			mlme_obj->cfg.trig_min_rssi[MIN_RSSI_2G_TO_5G_ROAM];
754 }
755 #endif
756 
757 QDF_STATUS wlan_cm_roam_cfg_get_value(struct wlan_objmgr_psoc *psoc,
758 				      uint8_t vdev_id,
759 				      enum roam_cfg_param roam_cfg_type,
760 				      struct cm_roam_values_copy *dst_config)
761 {
762 	struct wlan_objmgr_vdev *vdev;
763 	QDF_STATUS status = QDF_STATUS_SUCCESS;
764 	struct rso_config *rso_cfg;
765 	struct rso_cfg_params *src_cfg;
766 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
767 
768 	qdf_mem_zero(dst_config, sizeof(*dst_config));
769 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
770 	if (!mlme_obj)
771 		return QDF_STATUS_E_FAILURE;
772 
773 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
774 						    WLAN_MLME_NB_ID);
775 	if (!vdev) {
776 		mlme_err("vdev object is NULL");
777 		return QDF_STATUS_E_FAILURE;
778 	}
779 
780 	rso_cfg = wlan_cm_get_rso_config(vdev);
781 	if (!rso_cfg) {
782 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
783 		return QDF_STATUS_E_FAILURE;
784 	}
785 	src_cfg = &rso_cfg->cfg_param;
786 	switch (roam_cfg_type) {
787 	case RSSI_CHANGE_THRESHOLD:
788 		dst_config->int_value = rso_cfg->rescan_rssi_delta;
789 		break;
790 	case BEACON_RSSI_WEIGHT:
791 		dst_config->uint_value = rso_cfg->beacon_rssi_weight;
792 		break;
793 	case HI_RSSI_DELAY_BTW_SCANS:
794 		dst_config->uint_value = rso_cfg->hi_rssi_scan_delay;
795 		break;
796 	case EMPTY_SCAN_REFRESH_PERIOD:
797 		dst_config->uint_value = src_cfg->empty_scan_refresh_period;
798 		break;
799 	case SCAN_MIN_CHAN_TIME:
800 		dst_config->uint_value = src_cfg->min_chan_scan_time;
801 		break;
802 	case SCAN_MAX_CHAN_TIME:
803 		dst_config->uint_value = src_cfg->max_chan_scan_time;
804 		break;
805 	case NEIGHBOR_SCAN_PERIOD:
806 		dst_config->uint_value = src_cfg->neighbor_scan_period;
807 		break;
808 	case FULL_ROAM_SCAN_PERIOD:
809 		dst_config->uint_value = src_cfg->full_roam_scan_period;
810 		break;
811 	case ROAM_RSSI_DIFF:
812 		dst_config->uint_value = src_cfg->roam_rssi_diff;
813 		break;
814 	case ROAM_RSSI_DIFF_6GHZ:
815 		dst_config->uint_value = src_cfg->roam_rssi_diff_6ghz;
816 		break;
817 	case NEIGHBOUR_LOOKUP_THRESHOLD:
818 		dst_config->uint_value = src_cfg->neighbor_lookup_threshold;
819 		break;
820 	case SCAN_N_PROBE:
821 		dst_config->uint_value = src_cfg->roam_scan_n_probes;
822 		break;
823 	case SCAN_HOME_AWAY:
824 		dst_config->uint_value = src_cfg->roam_scan_home_away_time;
825 		break;
826 	case NEIGHBOUR_SCAN_REFRESH_PERIOD:
827 		dst_config->uint_value =
828 				src_cfg->neighbor_results_refresh_period;
829 		break;
830 	case ROAM_CONTROL_ENABLE:
831 		dst_config->bool_value = rso_cfg->roam_control_enable;
832 		break;
833 	case UAPSD_MASK:
834 		dst_config->uint_value = rso_cfg->uapsd_mask;
835 		break;
836 	case MOBILITY_DOMAIN:
837 		dst_config->bool_value = rso_cfg->mdid.mdie_present;
838 		dst_config->uint_value = rso_cfg->mdid.mobility_domain;
839 		break;
840 	case IS_11R_CONNECTION:
841 		dst_config->bool_value = rso_cfg->is_11r_assoc;
842 		break;
843 	case ADAPTIVE_11R_CONNECTION:
844 		dst_config->bool_value = rso_cfg->is_adaptive_11r_connection;
845 		break;
846 	case HS_20_AP:
847 		dst_config->bool_value = rso_cfg->hs_20_ap;
848 		break;
849 	case MBO_OCE_ENABLED_AP:
850 		dst_config->uint_value = rso_cfg->mbo_oce_enabled_ap;
851 		break;
852 	case IS_SINGLE_PMK:
853 		dst_config->bool_value = rso_cfg->is_single_pmk;
854 		break;
855 	case LOST_LINK_RSSI:
856 		dst_config->int_value = rso_cfg->lost_link_rssi;
857 		break;
858 	case ROAM_BAND:
859 		dst_config->uint_value = rso_cfg->roam_band_bitmask;
860 		break;
861 	case HI_RSSI_SCAN_RSSI_DELTA:
862 		dst_config->uint_value = src_cfg->hi_rssi_scan_rssi_delta;
863 		break;
864 	case ROAM_CONFIG_ENABLE:
865 		dst_config->bool_value = rso_cfg->roam_control_enable;
866 		break;
867 	default:
868 		mlme_err("Invalid roam config requested:%d", roam_cfg_type);
869 		status = QDF_STATUS_E_FAILURE;
870 		break;
871 	}
872 
873 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
874 
875 	return status;
876 }
877 
878 void wlan_cm_set_disable_hi_rssi(struct wlan_objmgr_pdev *pdev,
879 				 uint8_t vdev_id, bool value)
880 {
881 	static struct rso_config *rso_cfg;
882 	struct wlan_objmgr_vdev *vdev;
883 
884 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
885 						    WLAN_MLME_CM_ID);
886 	if (!vdev) {
887 		mlme_err("vdev object is NULL");
888 		return;
889 	}
890 	rso_cfg = wlan_cm_get_rso_config(vdev);
891 	if (!rso_cfg) {
892 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
893 		return;
894 	}
895 
896 	rso_cfg->disable_hi_rssi = value;
897 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
898 }
899 
900 void wlan_cm_set_country_code(struct wlan_objmgr_pdev *pdev,
901 			      uint8_t vdev_id, uint8_t  *cc)
902 {
903 	static struct rso_config *rso_cfg;
904 	struct wlan_objmgr_vdev *vdev;
905 
906 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
907 						    WLAN_MLME_CM_ID);
908 	if (!vdev) {
909 		mlme_err("vdev object is NULL");
910 		return;
911 	}
912 	rso_cfg = wlan_cm_get_rso_config(vdev);
913 	if (!rso_cfg || !cc)
914 		goto release_vdev_ref;
915 
916 	mlme_debug("Country info from bcn IE:%c%c 0x%x", cc[0], cc[1], cc[2]);
917 
918 	qdf_mem_copy(rso_cfg->country_code, cc, REG_ALPHA2_LEN + 1);
919 
920 release_vdev_ref:
921 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
922 }
923 
924 QDF_STATUS wlan_cm_get_country_code(struct wlan_objmgr_pdev *pdev,
925 				    uint8_t vdev_id, uint8_t *cc)
926 {
927 	static struct rso_config *rso_cfg;
928 	struct wlan_objmgr_vdev *vdev;
929 	QDF_STATUS status = QDF_STATUS_SUCCESS;
930 
931 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
932 						    WLAN_MLME_CM_ID);
933 	if (!vdev) {
934 		mlme_err("vdev object is NULL");
935 		return QDF_STATUS_E_INVAL;
936 	}
937 	rso_cfg = wlan_cm_get_rso_config(vdev);
938 	if (!rso_cfg || !cc) {
939 		status = QDF_STATUS_E_INVAL;
940 		goto release_vdev_ref;
941 	}
942 
943 	qdf_mem_copy(cc, rso_cfg->country_code, REG_ALPHA2_LEN + 1);
944 
945 release_vdev_ref:
946 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
947 	return status;
948 }
949 
950 #ifdef FEATURE_WLAN_ESE
951 void wlan_cm_set_ese_assoc(struct wlan_objmgr_pdev *pdev,
952 			   uint8_t vdev_id, bool value)
953 {
954 	static struct rso_config *rso_cfg;
955 	struct wlan_objmgr_vdev *vdev;
956 
957 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
958 						    WLAN_MLME_CM_ID);
959 	if (!vdev) {
960 		mlme_err("vdev object is NULL");
961 		return;
962 	}
963 	rso_cfg = wlan_cm_get_rso_config(vdev);
964 	if (!rso_cfg) {
965 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
966 		return;
967 	}
968 
969 	rso_cfg->is_ese_assoc = value;
970 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
971 }
972 
973 bool wlan_cm_get_ese_assoc(struct wlan_objmgr_pdev *pdev,
974 			   uint8_t vdev_id)
975 {
976 	static struct rso_config *rso_cfg;
977 	struct wlan_objmgr_vdev *vdev;
978 	bool ese_assoc;
979 
980 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
981 						    WLAN_MLME_CM_ID);
982 	if (!vdev) {
983 		mlme_err("vdev object is NULL");
984 		return false;
985 	}
986 	rso_cfg = wlan_cm_get_rso_config(vdev);
987 	if (!rso_cfg) {
988 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
989 		return false;
990 	}
991 
992 	ese_assoc = rso_cfg->is_ese_assoc;
993 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
994 
995 	return ese_assoc;
996 }
997 #endif
998 
999 static QDF_STATUS
1000 cm_roam_update_cfg(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
1001 		   uint8_t reason)
1002 {
1003 	QDF_STATUS status;
1004 	struct wlan_objmgr_vdev *vdev;
1005 
1006 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
1007 						    WLAN_MLME_CM_ID);
1008 	if (!vdev) {
1009 		mlme_err("vdev object is NULL");
1010 		return QDF_STATUS_E_INVAL;
1011 	}
1012 
1013 	status = cm_roam_acquire_lock(vdev);
1014 	if (QDF_IS_STATUS_ERROR(status))
1015 		goto release_ref;
1016 	if (!MLME_IS_ROAM_STATE_RSO_ENABLED(psoc, vdev_id)) {
1017 		mlme_debug("Update cfg received while ROAM RSO not started");
1018 		cm_roam_release_lock(vdev);
1019 		status = QDF_STATUS_E_INVAL;
1020 		goto release_ref;
1021 	}
1022 
1023 	status = cm_roam_send_rso_cmd(psoc, vdev_id,
1024 				      ROAM_SCAN_OFFLOAD_UPDATE_CFG, reason);
1025 	cm_roam_release_lock(vdev);
1026 
1027 release_ref:
1028 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
1029 
1030 	return status;
1031 }
1032 
1033 void cm_dump_freq_list(struct rso_chan_info *chan_info)
1034 {
1035 	uint8_t *channel_list;
1036 	uint8_t i = 0, j = 0;
1037 	uint32_t buflen = CFG_VALID_CHANNEL_LIST_LEN * 4;
1038 
1039 	channel_list = qdf_mem_malloc(buflen);
1040 	if (!channel_list)
1041 		return;
1042 
1043 	if (chan_info->freq_list) {
1044 		for (i = 0; i < chan_info->num_chan; i++) {
1045 			if (j < buflen)
1046 				j += qdf_scnprintf(channel_list + j, buflen - j,
1047 						   "%d ",
1048 						   chan_info->freq_list[i]);
1049 			else
1050 				break;
1051 		}
1052 	}
1053 
1054 	mlme_debug("frequency list [%u]: %s", i, channel_list);
1055 	qdf_mem_free(channel_list);
1056 }
1057 
1058 static uint8_t
1059 cm_append_pref_chan_list(struct rso_chan_info *chan_info, qdf_freq_t *freq_list,
1060 			 uint8_t num_chan)
1061 {
1062 	uint8_t i = 0, j = 0;
1063 
1064 	for (i = 0; i < chan_info->num_chan; i++) {
1065 		for (j = 0; j < num_chan; j++)
1066 			if (chan_info->freq_list[i] == freq_list[j])
1067 				break;
1068 
1069 		if (j < num_chan)
1070 			continue;
1071 		if (num_chan == CFG_VALID_CHANNEL_LIST_LEN)
1072 			break;
1073 		freq_list[num_chan++] = chan_info->freq_list[i];
1074 	}
1075 
1076 	return num_chan;
1077 }
1078 
1079 /**
1080  * cm_modify_chan_list_based_on_band() - Modify RSO channel list based on band
1081  * @freq_list: Channel list coming from user space
1082  * @num_chan: Number of channel present in freq_list buffer
1083  * @band_bitmap: On basis of this band host modify RSO channel list
1084  *
1085  * Return: valid number of channel as per bandmap
1086  */
1087 static uint8_t
1088 cm_modify_chan_list_based_on_band(qdf_freq_t *freq_list, uint8_t num_chan,
1089 				  uint32_t band_bitmap)
1090 {
1091 	uint8_t i = 0, valid_chan_num = 0;
1092 
1093 	if (!(band_bitmap & BIT(REG_BAND_2G))) {
1094 		mlme_debug("disabling 2G");
1095 		for (i = 0; i < num_chan; i++) {
1096 			if (WLAN_REG_IS_24GHZ_CH_FREQ(freq_list[i]))
1097 				freq_list[i] = 0;
1098 		}
1099 	}
1100 
1101 	if (!(band_bitmap & BIT(REG_BAND_5G))) {
1102 		mlme_debug("disabling 5G");
1103 		for (i = 0; i < num_chan; i++) {
1104 			if (WLAN_REG_IS_5GHZ_CH_FREQ(freq_list[i]))
1105 				freq_list[i] = 0;
1106 		}
1107 	}
1108 
1109 	if (!(band_bitmap & BIT(REG_BAND_6G))) {
1110 		mlme_debug("disabling 6G");
1111 		for (i = 0; i < num_chan; i++) {
1112 			if (WLAN_REG_IS_6GHZ_CHAN_FREQ(freq_list[i]))
1113 				freq_list[i] = 0;
1114 		}
1115 	}
1116 
1117 	for (i = 0; i < num_chan; i++) {
1118 		if (freq_list[i])
1119 			freq_list[valid_chan_num++] = freq_list[i];
1120 	}
1121 
1122 	return valid_chan_num;
1123 }
1124 
1125 static QDF_STATUS cm_create_bg_scan_roam_channel_list(struct rso_chan_info *chan_info,
1126 						const qdf_freq_t *chan_freq_lst,
1127 						const uint8_t num_chan)
1128 {
1129 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1130 	uint8_t i;
1131 
1132 	chan_info->freq_list = qdf_mem_malloc(sizeof(qdf_freq_t) * num_chan);
1133 	if (!chan_info->freq_list)
1134 		return QDF_STATUS_E_NOMEM;
1135 
1136 	chan_info->num_chan = num_chan;
1137 	for (i = 0; i < num_chan; i++)
1138 		chan_info->freq_list[i] = chan_freq_lst[i];
1139 
1140 	return status;
1141 }
1142 
1143 /**
1144  * cm_remove_disabled_channels() - Remove disabled channels as per current
1145  * connected band
1146  * @vdev: vdev common object
1147  * @freq_list: Channel list coming from user space
1148  * @num_chan: Number of channel present in freq_list buffer
1149  *
1150  * Return: Number of channels as per SETBAND mask
1151  */
1152 static uint32_t cm_remove_disabled_channels(struct wlan_objmgr_vdev *vdev,
1153 					    qdf_freq_t *freq_list,
1154 					    uint8_t num_chan)
1155 {
1156 	struct regulatory_channel *cur_chan_list;
1157 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
1158 	uint32_t valid_chan_num = 0;
1159 	enum channel_state state;
1160 	uint32_t freq, i, j;
1161 	QDF_STATUS status;
1162 	uint32_t filtered_lst[NUM_CHANNELS] = {0};
1163 
1164 	cur_chan_list =
1165 	     qdf_mem_malloc(NUM_CHANNELS * sizeof(struct regulatory_channel));
1166 	if (!cur_chan_list)
1167 		return 0;
1168 
1169 	status = wlan_reg_get_current_chan_list(pdev, cur_chan_list);
1170 	if (QDF_IS_STATUS_ERROR(status)) {
1171 		qdf_mem_free(cur_chan_list);
1172 		return 0;
1173 	}
1174 
1175 	for (i = 0; i < NUM_CHANNELS; i++) {
1176 		freq = cur_chan_list[i].center_freq;
1177 		state = wlan_reg_get_channel_state_for_pwrmode(
1178 							pdev, freq,
1179 							REG_CURRENT_PWR_MODE);
1180 		if (state != CHANNEL_STATE_DISABLE &&
1181 		    state != CHANNEL_STATE_INVALID) {
1182 			for (j = 0; j < num_chan; j++) {
1183 				if (freq == freq_list[j]) {
1184 					filtered_lst[valid_chan_num++] =
1185 								freq_list[j];
1186 					break;
1187 				}
1188 			}
1189 		}
1190 	}
1191 
1192 	mlme_debug("[ROAM_BAND]: num channel :%d", valid_chan_num);
1193 	for (i = 0; i < valid_chan_num; i++)
1194 		freq_list[i] = filtered_lst[i];
1195 
1196 	qdf_mem_free(cur_chan_list);
1197 
1198 	return valid_chan_num;
1199 }
1200 
1201 /**
1202  * cm_update_roam_scan_channel_list() - Update channel list as per RSO chan info
1203  * band bitmask
1204  * @psoc: Psoc common object
1205  * @vdev: vdev common object
1206  * @rso_cfg: connect config to be used to send info in RSO
1207  * @vdev_id: vdev id
1208  * @chan_info: hannel list already sent via RSO
1209  * @freq_list: Channel list coming from user space
1210  * @num_chan: Number of channel present in freq_list buffer
1211  * @update_preferred_chan: Decide whether to update preferred chan list or not
1212  *
1213  * Return: QDF_STATUS
1214  */
1215 static QDF_STATUS
1216 cm_update_roam_scan_channel_list(struct wlan_objmgr_psoc *psoc,
1217 				 struct wlan_objmgr_vdev *vdev,
1218 				 struct rso_config *rso_cfg, uint8_t vdev_id,
1219 				 struct rso_chan_info *chan_info,
1220 				 qdf_freq_t *freq_list, uint8_t num_chan,
1221 				 bool update_preferred_chan)
1222 {
1223 	uint16_t pref_chan_cnt = 0;
1224 	uint32_t valid_chan_num = 0;
1225 	struct cm_roam_values_copy config;
1226 	uint32_t current_band;
1227 
1228 	if (chan_info->num_chan) {
1229 		mlme_debug("Current channel num: %d", chan_info->num_chan);
1230 		cm_dump_freq_list(chan_info);
1231 	}
1232 
1233 	if (update_preferred_chan) {
1234 		pref_chan_cnt = cm_append_pref_chan_list(chan_info, freq_list,
1235 							 num_chan);
1236 		num_chan = pref_chan_cnt;
1237 	}
1238 
1239 	num_chan = cm_remove_disabled_channels(vdev, freq_list, num_chan);
1240 	if (!num_chan)
1241 		return QDF_STATUS_E_FAILURE;
1242 
1243 	wlan_cm_roam_cfg_get_value(psoc, vdev_id, ROAM_BAND, &config);
1244 	ucfg_reg_get_band(wlan_vdev_get_pdev(vdev), &current_band);
1245 	/* No need to modify channel list if all channel is allowed */
1246 	if (config.uint_value != current_band) {
1247 		valid_chan_num =
1248 			cm_modify_chan_list_based_on_band(freq_list, num_chan,
1249 							  config.uint_value);
1250 		if (!valid_chan_num) {
1251 			mlme_debug("No valid channels left to send to the fw");
1252 			return QDF_STATUS_E_FAILURE;
1253 		}
1254 		num_chan = valid_chan_num;
1255 	}
1256 
1257 	cm_flush_roam_channel_list(chan_info);
1258 	cm_create_bg_scan_roam_channel_list(chan_info, freq_list, num_chan);
1259 
1260 	mlme_debug("New channel num: %d", num_chan);
1261 	cm_dump_freq_list(chan_info);
1262 
1263 	return QDF_STATUS_SUCCESS;
1264 }
1265 
1266 QDF_STATUS
1267 wlan_cm_roam_cfg_set_value(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
1268 			   enum roam_cfg_param roam_cfg_type,
1269 			   struct cm_roam_values_copy *src_config)
1270 {
1271 	struct wlan_objmgr_vdev *vdev;
1272 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1273 	struct rso_config *rso_cfg;
1274 	struct rso_cfg_params *dst_cfg;
1275 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
1276 
1277 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
1278 	if (!mlme_obj)
1279 		return QDF_STATUS_E_FAILURE;
1280 
1281 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
1282 						    WLAN_MLME_NB_ID);
1283 	if (!vdev) {
1284 		mlme_err("vdev object is NULL");
1285 		return QDF_STATUS_E_FAILURE;
1286 	}
1287 
1288 	rso_cfg = wlan_cm_get_rso_config(vdev);
1289 	if (!rso_cfg) {
1290 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
1291 		return QDF_STATUS_E_FAILURE;
1292 	}
1293 	dst_cfg = &rso_cfg->cfg_param;
1294 	mlme_debug("roam_cfg_type %d, uint val %d int val %d bool val %d num chan %d",
1295 		   roam_cfg_type, src_config->uint_value, src_config->int_value,
1296 		   src_config->bool_value, src_config->chan_info.num_chan);
1297 	switch (roam_cfg_type) {
1298 	case RSSI_CHANGE_THRESHOLD:
1299 		rso_cfg->rescan_rssi_delta  = src_config->uint_value;
1300 		break;
1301 	case BEACON_RSSI_WEIGHT:
1302 		rso_cfg->beacon_rssi_weight = src_config->uint_value;
1303 		break;
1304 	case HI_RSSI_DELAY_BTW_SCANS:
1305 		rso_cfg->hi_rssi_scan_delay = src_config->uint_value;
1306 		break;
1307 	case EMPTY_SCAN_REFRESH_PERIOD:
1308 		dst_cfg->empty_scan_refresh_period = src_config->uint_value;
1309 		if (mlme_obj->cfg.lfr.roam_scan_offload_enabled)
1310 			cm_roam_update_cfg(psoc, vdev_id,
1311 					  REASON_EMPTY_SCAN_REF_PERIOD_CHANGED);
1312 		break;
1313 	case FULL_ROAM_SCAN_PERIOD:
1314 		dst_cfg->full_roam_scan_period = src_config->uint_value;
1315 		if (mlme_obj->cfg.lfr.roam_scan_offload_enabled)
1316 			cm_roam_update_cfg(psoc, vdev_id,
1317 					  REASON_ROAM_FULL_SCAN_PERIOD_CHANGED);
1318 		break;
1319 	case ENABLE_SCORING_FOR_ROAM:
1320 		dst_cfg->enable_scoring_for_roam = src_config->bool_value;
1321 		if (mlme_obj->cfg.lfr.roam_scan_offload_enabled)
1322 			cm_roam_update_cfg(psoc, vdev_id,
1323 					   REASON_SCORING_CRITERIA_CHANGED);
1324 		break;
1325 	case SCAN_MIN_CHAN_TIME:
1326 		mlme_obj->cfg.lfr.neighbor_scan_min_chan_time =
1327 							src_config->uint_value;
1328 		dst_cfg->min_chan_scan_time = src_config->uint_value;
1329 		break;
1330 	case SCAN_MAX_CHAN_TIME:
1331 		dst_cfg->max_chan_scan_time = src_config->uint_value;
1332 		if (mlme_obj->cfg.lfr.roam_scan_offload_enabled)
1333 			cm_roam_update_cfg(psoc, vdev_id,
1334 					   REASON_SCAN_CH_TIME_CHANGED);
1335 		break;
1336 	case NEIGHBOR_SCAN_PERIOD:
1337 		dst_cfg->neighbor_scan_period = src_config->uint_value;
1338 		if (mlme_obj->cfg.lfr.roam_scan_offload_enabled)
1339 			cm_roam_update_cfg(psoc, vdev_id,
1340 					   REASON_SCAN_HOME_TIME_CHANGED);
1341 		break;
1342 	case ROAM_CONFIG_ENABLE:
1343 		rso_cfg->roam_control_enable = src_config->bool_value;
1344 		if (!rso_cfg->roam_control_enable)
1345 			break;
1346 		dst_cfg->roam_inactive_data_packet_count = 0;
1347 		dst_cfg->roam_scan_inactivity_time = 0;
1348 		if (mlme_obj->cfg.lfr.roam_scan_offload_enabled)
1349 			cm_roam_update_cfg(psoc, vdev_id,
1350 					   REASON_ROAM_CONTROL_CONFIG_ENABLED);
1351 		break;
1352 	case ROAM_PREFERRED_CHAN:
1353 		/*
1354 		 * In RSO update command, the specific channel list is
1355 		 * given priority. So flush the Specific channel list if
1356 		 * preferred channel list is received. Else the channel list
1357 		 * type will be filled as static instead of dynamic.
1358 		 */
1359 		cm_flush_roam_channel_list(&dst_cfg->specific_chan_info);
1360 		status = cm_update_roam_scan_channel_list(psoc, vdev, rso_cfg,
1361 					vdev_id, &dst_cfg->pref_chan_info,
1362 					src_config->chan_info.freq_list,
1363 					src_config->chan_info.num_chan, true);
1364 		if (QDF_IS_STATUS_ERROR(status))
1365 			break;
1366 		if (mlme_obj->cfg.lfr.roam_scan_offload_enabled)
1367 			cm_roam_update_cfg(psoc, vdev_id,
1368 					   REASON_CHANNEL_LIST_CHANGED);
1369 		break;
1370 	case ROAM_SPECIFIC_CHAN:
1371 		status = cm_update_roam_scan_channel_list(psoc, vdev, rso_cfg,
1372 					vdev_id, &dst_cfg->specific_chan_info,
1373 					src_config->chan_info.freq_list,
1374 					src_config->chan_info.num_chan,
1375 					false);
1376 		if (QDF_IS_STATUS_ERROR(status))
1377 			break;
1378 		if (mlme_obj->cfg.lfr.roam_scan_offload_enabled)
1379 			cm_roam_update_cfg(psoc, vdev_id,
1380 					   REASON_CHANNEL_LIST_CHANGED);
1381 		break;
1382 	case ROAM_RSSI_DIFF:
1383 		dst_cfg->roam_rssi_diff = src_config->uint_value;
1384 		if (mlme_obj->cfg.lfr.roam_scan_offload_enabled)
1385 			cm_roam_update_cfg(psoc, vdev_id,
1386 					   REASON_RSSI_DIFF_CHANGED);
1387 		break;
1388 	case ROAM_RSSI_DIFF_6GHZ:
1389 		dst_cfg->roam_rssi_diff_6ghz = src_config->uint_value;
1390 		break;
1391 	case NEIGHBOUR_LOOKUP_THRESHOLD:
1392 		dst_cfg->neighbor_lookup_threshold = src_config->uint_value;
1393 		break;
1394 	case SCAN_N_PROBE:
1395 		dst_cfg->roam_scan_n_probes = src_config->uint_value;
1396 		if (mlme_obj->cfg.lfr.roam_scan_offload_enabled)
1397 			cm_roam_update_cfg(psoc, vdev_id,
1398 					   REASON_NPROBES_CHANGED);
1399 		break;
1400 	case SCAN_HOME_AWAY:
1401 		dst_cfg->roam_scan_home_away_time = src_config->uint_value;
1402 		if (mlme_obj->cfg.lfr.roam_scan_offload_enabled &&
1403 		    src_config->bool_value)
1404 			cm_roam_update_cfg(psoc, vdev_id,
1405 					   REASON_HOME_AWAY_TIME_CHANGED);
1406 		break;
1407 	case NEIGHBOUR_SCAN_REFRESH_PERIOD:
1408 		dst_cfg->neighbor_results_refresh_period =
1409 						src_config->uint_value;
1410 		mlme_obj->cfg.lfr.neighbor_scan_results_refresh_period =
1411 				src_config->uint_value;
1412 		if (mlme_obj->cfg.lfr.roam_scan_offload_enabled)
1413 			cm_roam_update_cfg(psoc, vdev_id,
1414 				REASON_NEIGHBOR_SCAN_REFRESH_PERIOD_CHANGED);
1415 		break;
1416 	case UAPSD_MASK:
1417 		rso_cfg->uapsd_mask = src_config->uint_value;
1418 		break;
1419 	case MOBILITY_DOMAIN:
1420 		rso_cfg->mdid.mdie_present = src_config->bool_value;
1421 		rso_cfg->mdid.mobility_domain = src_config->uint_value;
1422 		break;
1423 	case IS_11R_CONNECTION:
1424 		rso_cfg->is_11r_assoc = src_config->bool_value;
1425 		break;
1426 	case ADAPTIVE_11R_CONNECTION:
1427 		rso_cfg->is_adaptive_11r_connection = src_config->bool_value;
1428 		break;
1429 	case HS_20_AP:
1430 		rso_cfg->hs_20_ap  = src_config->bool_value;
1431 		break;
1432 	case MBO_OCE_ENABLED_AP:
1433 		rso_cfg->mbo_oce_enabled_ap  = src_config->uint_value;
1434 		break;
1435 	case IS_SINGLE_PMK:
1436 		rso_cfg->is_single_pmk = src_config->bool_value;
1437 		break;
1438 	case LOST_LINK_RSSI:
1439 		rso_cfg->lost_link_rssi = src_config->int_value;
1440 		break;
1441 	case ROAM_BAND:
1442 		rso_cfg->roam_band_bitmask = src_config->uint_value;
1443 		mlme_debug("[ROAM BAND] Set roam band:%d",
1444 			   rso_cfg->roam_band_bitmask);
1445 		break;
1446 	default:
1447 		mlme_err("Invalid roam config requested:%d", roam_cfg_type);
1448 		status = QDF_STATUS_E_FAILURE;
1449 		break;
1450 	}
1451 
1452 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
1453 
1454 	return status;
1455 }
1456 
1457 void wlan_roam_reset_roam_params(struct wlan_objmgr_vdev *vdev)
1458 {
1459 	struct rso_user_config *rso_usr_cfg;
1460 
1461 	rso_usr_cfg = wlan_cm_get_rso_user_config(vdev);
1462 	if (!rso_usr_cfg)
1463 		return;
1464 
1465 	/*
1466 	 * clear all the allowlist parameters and remaining
1467 	 * needs to be retained across connections.
1468 	 */
1469 	rso_usr_cfg->num_ssid_allowed_list = 0;
1470 	qdf_mem_zero(&rso_usr_cfg->ssid_allowed_list,
1471 		     sizeof(struct wlan_ssid) * MAX_SSID_ALLOWED_LIST);
1472 }
1473 
1474 static void cm_rso_chan_to_freq_list(struct wlan_objmgr_pdev *pdev,
1475 				     qdf_freq_t *freq_list,
1476 				     const uint8_t *chan_list,
1477 				     uint32_t chan_list_len)
1478 {
1479 	uint32_t count;
1480 
1481 	for (count = 0; count < chan_list_len; count++)
1482 		freq_list[count] =
1483 			wlan_reg_legacy_chan_to_freq(pdev, chan_list[count]);
1484 }
1485 
1486 #ifdef WLAN_FEATURE_HOST_ROAM
1487 static QDF_STATUS cm_init_reassoc_timer(struct rso_config *rso_cfg)
1488 {
1489 	QDF_STATUS status;
1490 
1491 	status = qdf_mc_timer_init(&rso_cfg->reassoc_timer, QDF_TIMER_TYPE_SW,
1492 				   cm_reassoc_timer_callback, &rso_cfg->ctx);
1493 
1494 	if (QDF_IS_STATUS_ERROR(status))
1495 		mlme_err("Preauth Reassoc interval Timer allocation failed");
1496 
1497 	return status;
1498 }
1499 
1500 static void cm_deinit_reassoc_timer(struct rso_config *rso_cfg)
1501 {
1502 	/* check if the timer is running */
1503 	if (QDF_TIMER_STATE_RUNNING ==
1504 	    qdf_mc_timer_get_current_state(&rso_cfg->reassoc_timer))
1505 		qdf_mc_timer_stop(&rso_cfg->reassoc_timer);
1506 
1507 	qdf_mc_timer_destroy(&rso_cfg->reassoc_timer);
1508 }
1509 #else
1510 static inline QDF_STATUS cm_init_reassoc_timer(struct rso_config *rso_cfg)
1511 {
1512 	return QDF_STATUS_SUCCESS;
1513 }
1514 static inline void cm_deinit_reassoc_timer(struct rso_config *rso_cfg) {}
1515 #endif
1516 
1517 QDF_STATUS wlan_cm_rso_config_init(struct wlan_objmgr_vdev *vdev,
1518 				   struct rso_config *rso_cfg)
1519 {
1520 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1521 	struct rso_chan_info *chan_info;
1522 	struct rso_cfg_params *cfg_params;
1523 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
1524 	struct wlan_objmgr_pdev *pdev;
1525 	struct wlan_objmgr_psoc *psoc;
1526 	uint32_t current_band = REG_BAND_MASK_ALL;
1527 
1528 	pdev = wlan_vdev_get_pdev(vdev);
1529 	if (!pdev)
1530 		return QDF_STATUS_E_INVAL;
1531 
1532 	psoc = wlan_pdev_get_psoc(pdev);
1533 	if (!psoc)
1534 		return QDF_STATUS_E_INVAL;
1535 
1536 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
1537 	if (!mlme_obj)
1538 		return QDF_STATUS_E_INVAL;
1539 
1540 	status = cm_init_reassoc_timer(rso_cfg);
1541 	if (QDF_IS_STATUS_ERROR(status))
1542 		return status;
1543 
1544 	qdf_mutex_create(&rso_cfg->cm_rso_lock);
1545 	cfg_params = &rso_cfg->cfg_param;
1546 	cfg_params->max_chan_scan_time =
1547 		mlme_obj->cfg.lfr.neighbor_scan_max_chan_time;
1548 	cfg_params->passive_max_chan_time =
1549 		mlme_obj->cfg.lfr.passive_max_channel_time;
1550 	cfg_params->min_chan_scan_time =
1551 		mlme_obj->cfg.lfr.neighbor_scan_min_chan_time;
1552 	cfg_params->neighbor_lookup_threshold =
1553 		mlme_obj->cfg.lfr.neighbor_lookup_rssi_threshold;
1554 	cfg_params->rssi_thresh_offset_5g =
1555 		mlme_obj->cfg.lfr.rssi_threshold_offset_5g;
1556 	cfg_params->opportunistic_threshold_diff =
1557 		mlme_obj->cfg.lfr.opportunistic_scan_threshold_diff;
1558 	cfg_params->roam_rescan_rssi_diff =
1559 		mlme_obj->cfg.lfr.roam_rescan_rssi_diff;
1560 
1561 	cfg_params->roam_bmiss_first_bcn_cnt =
1562 		mlme_obj->cfg.lfr.roam_bmiss_first_bcnt;
1563 	cfg_params->roam_bmiss_final_cnt =
1564 		mlme_obj->cfg.lfr.roam_bmiss_final_bcnt;
1565 
1566 	cfg_params->neighbor_scan_period =
1567 		mlme_obj->cfg.lfr.neighbor_scan_timer_period;
1568 	cfg_params->neighbor_scan_min_period =
1569 		mlme_obj->cfg.lfr.neighbor_scan_min_timer_period;
1570 	cfg_params->neighbor_results_refresh_period =
1571 		mlme_obj->cfg.lfr.neighbor_scan_results_refresh_period;
1572 	cfg_params->empty_scan_refresh_period =
1573 		mlme_obj->cfg.lfr.empty_scan_refresh_period;
1574 	cfg_params->full_roam_scan_period =
1575 		mlme_obj->cfg.lfr.roam_full_scan_period;
1576 	cfg_params->enable_scoring_for_roam =
1577 		mlme_obj->cfg.roam_scoring.enable_scoring_for_roam;
1578 	cfg_params->roam_scan_n_probes =
1579 		mlme_obj->cfg.lfr.roam_scan_n_probes;
1580 	cfg_params->roam_scan_home_away_time =
1581 		mlme_obj->cfg.lfr.roam_scan_home_away_time;
1582 	cfg_params->roam_scan_inactivity_time =
1583 		mlme_obj->cfg.lfr.roam_scan_inactivity_time;
1584 	cfg_params->roam_inactive_data_packet_count =
1585 		mlme_obj->cfg.lfr.roam_inactive_data_packet_count;
1586 
1587 	chan_info = &cfg_params->specific_chan_info;
1588 	chan_info->num_chan =
1589 		mlme_obj->cfg.lfr.neighbor_scan_channel_list_num;
1590 	mlme_debug("number of channels: %u", chan_info->num_chan);
1591 	if (chan_info->num_chan) {
1592 		chan_info->freq_list =
1593 			qdf_mem_malloc(sizeof(qdf_freq_t) *
1594 				       chan_info->num_chan);
1595 		if (!chan_info->freq_list) {
1596 			chan_info->num_chan = 0;
1597 			return QDF_STATUS_E_NOMEM;
1598 		}
1599 		/* Update the roam global structure from CFG */
1600 		cm_rso_chan_to_freq_list(pdev, chan_info->freq_list,
1601 			mlme_obj->cfg.lfr.neighbor_scan_channel_list,
1602 			mlme_obj->cfg.lfr.neighbor_scan_channel_list_num);
1603 	} else {
1604 		chan_info->freq_list = NULL;
1605 	}
1606 
1607 	cfg_params->hi_rssi_scan_max_count =
1608 		mlme_obj->cfg.lfr.roam_scan_hi_rssi_maxcount;
1609 	cfg_params->hi_rssi_scan_rssi_delta =
1610 		mlme_obj->cfg.lfr.roam_scan_hi_rssi_delta;
1611 
1612 	cfg_params->hi_rssi_scan_delay =
1613 		mlme_obj->cfg.lfr.roam_scan_hi_rssi_delay;
1614 
1615 	cfg_params->hi_rssi_scan_rssi_ub =
1616 		mlme_obj->cfg.lfr.roam_scan_hi_rssi_ub;
1617 	cfg_params->roam_rssi_diff =
1618 		mlme_obj->cfg.lfr.roam_rssi_diff;
1619 	cfg_params->roam_rssi_diff_6ghz =
1620 		mlme_obj->cfg.lfr.roam_rssi_diff_6ghz;
1621 	cfg_params->bg_rssi_threshold =
1622 		mlme_obj->cfg.lfr.bg_rssi_threshold;
1623 
1624 	ucfg_reg_get_band(wlan_vdev_get_pdev(vdev), &current_band);
1625 	rso_cfg->roam_band_bitmask = current_band;
1626 
1627 	return status;
1628 }
1629 
1630 void wlan_cm_rso_config_deinit(struct wlan_objmgr_vdev *vdev,
1631 			       struct rso_config *rso_cfg)
1632 {
1633 	struct rso_cfg_params *cfg_params;
1634 
1635 	cfg_params = &rso_cfg->cfg_param;
1636 	if (rso_cfg->assoc_ie.ptr) {
1637 		qdf_mem_free(rso_cfg->assoc_ie.ptr);
1638 		rso_cfg->assoc_ie.ptr = NULL;
1639 		rso_cfg->assoc_ie.len = 0;
1640 	}
1641 	if (rso_cfg->prev_ap_bcn_ie.ptr) {
1642 		qdf_mem_free(rso_cfg->prev_ap_bcn_ie.ptr);
1643 		rso_cfg->prev_ap_bcn_ie.ptr = NULL;
1644 		rso_cfg->prev_ap_bcn_ie.len = 0;
1645 	}
1646 	if (rso_cfg->roam_scan_freq_lst.freq_list)
1647 		qdf_mem_free(rso_cfg->roam_scan_freq_lst.freq_list);
1648 	rso_cfg->roam_scan_freq_lst.freq_list = NULL;
1649 	rso_cfg->roam_scan_freq_lst.num_chan = 0;
1650 
1651 	cm_flush_roam_channel_list(&cfg_params->specific_chan_info);
1652 	cm_flush_roam_channel_list(&cfg_params->pref_chan_info);
1653 
1654 	qdf_mutex_destroy(&rso_cfg->cm_rso_lock);
1655 
1656 	cm_deinit_reassoc_timer(rso_cfg);
1657 }
1658 
1659 struct rso_config *wlan_cm_get_rso_config_fl(struct wlan_objmgr_vdev *vdev,
1660 					     const char *func, uint32_t line)
1661 
1662 {
1663 	struct cm_ext_obj *cm_ext_obj;
1664 	enum QDF_OPMODE op_mode = wlan_vdev_mlme_get_opmode(vdev);
1665 
1666 	/* get only for CLI and STA */
1667 	if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE)
1668 		return NULL;
1669 
1670 	cm_ext_obj = cm_get_ext_hdl_fl(vdev, func, line);
1671 	if (!cm_ext_obj)
1672 		return NULL;
1673 
1674 	return &cm_ext_obj->rso_cfg;
1675 }
1676 
1677 struct rso_user_config *
1678 wlan_cm_get_rso_user_config_fl(struct wlan_objmgr_vdev *vdev,
1679 			       const char *func, uint32_t line)
1680 {
1681 	struct cm_ext_obj *cm_ext_obj;
1682 	enum QDF_OPMODE op_mode = wlan_vdev_mlme_get_opmode(vdev);
1683 
1684 	/* get only for CLI and STA */
1685 	if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE)
1686 		return NULL;
1687 
1688 	cm_ext_obj = cm_get_ext_hdl_fl(vdev, func, line);
1689 	if (!cm_ext_obj)
1690 		return NULL;
1691 
1692 	return &cm_ext_obj->rso_usr_cfg;
1693 }
1694 
1695 QDF_STATUS cm_roam_acquire_lock(struct wlan_objmgr_vdev *vdev)
1696 {
1697 	static struct rso_config *rso_cfg;
1698 
1699 	rso_cfg = wlan_cm_get_rso_config(vdev);
1700 	if (!rso_cfg)
1701 		return QDF_STATUS_E_INVAL;
1702 
1703 	return qdf_mutex_acquire(&rso_cfg->cm_rso_lock);
1704 }
1705 
1706 QDF_STATUS cm_roam_release_lock(struct wlan_objmgr_vdev *vdev)
1707 {
1708 	static struct rso_config *rso_cfg;
1709 
1710 	rso_cfg = wlan_cm_get_rso_config(vdev);
1711 	if (!rso_cfg)
1712 		return QDF_STATUS_E_INVAL;
1713 
1714 	return qdf_mutex_release(&rso_cfg->cm_rso_lock);
1715 }
1716 
1717 QDF_STATUS
1718 wlan_cm_roam_invoke(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
1719 		    struct qdf_mac_addr *bssid, qdf_freq_t chan_freq,
1720 		    enum wlan_cm_source source)
1721 {
1722 	QDF_STATUS status;
1723 	struct wlan_objmgr_psoc *psoc;
1724 	struct wlan_objmgr_vdev *vdev;
1725 
1726 	psoc = wlan_pdev_get_psoc(pdev);
1727 	if (!psoc) {
1728 		mlme_err("Invalid psoc");
1729 		return QDF_STATUS_E_FAILURE;
1730 	}
1731 
1732 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
1733 						    WLAN_MLME_NB_ID);
1734 	if (!vdev) {
1735 		mlme_err("vdev object is NULL");
1736 		return QDF_STATUS_E_NULL_VALUE;
1737 	}
1738 
1739 	mlme_debug("vdev: %d source: %d freq: %d bssid: " QDF_MAC_ADDR_FMT,
1740 		   vdev_id, source, chan_freq, QDF_MAC_ADDR_REF(bssid->bytes));
1741 
1742 	status = cm_start_roam_invoke(psoc, vdev, bssid, chan_freq, source);
1743 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
1744 
1745 	return status;
1746 }
1747 
1748 bool cm_is_fast_roam_enabled(struct wlan_objmgr_psoc *psoc)
1749 {
1750 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
1751 
1752 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
1753 	if (!mlme_obj)
1754 		return false;
1755 
1756 	if (!mlme_obj->cfg.lfr.lfr_enabled)
1757 		return false;
1758 
1759 	if (mlme_obj->cfg.lfr.enable_fast_roam_in_concurrency)
1760 		return true;
1761 	/* return true if no concurrency */
1762 	if (policy_mgr_get_connection_count(psoc) < 2)
1763 		return true;
1764 
1765 	return false;
1766 }
1767 
1768 bool cm_is_rsn_or_8021x_sha256_auth_type(struct wlan_objmgr_vdev *vdev)
1769 {
1770 	int32_t akm;
1771 
1772 	akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
1773 	if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256) ||
1774 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X))
1775 		return true;
1776 
1777 	return false;
1778 }
1779 
1780 #ifdef WLAN_FEATURE_HOST_ROAM
1781 QDF_STATUS wlan_cm_host_roam_start(struct scheduler_msg *msg)
1782 {
1783 	QDF_STATUS status;
1784 	struct cm_host_roam_start_ind *req;
1785 	struct qdf_mac_addr bssid = QDF_MAC_ADDR_ZERO_INIT;
1786 
1787 	if (!msg || !msg->bodyptr)
1788 		return QDF_STATUS_E_FAILURE;
1789 
1790 	req = msg->bodyptr;
1791 	status = wlan_cm_roam_invoke(req->pdev, req->vdev_id, &bssid, 0,
1792 				     CM_ROAMING_FW);
1793 	qdf_mem_free(req);
1794 
1795 	return status;
1796 }
1797 
1798 QDF_STATUS cm_mlme_roam_preauth_fail(struct wlan_objmgr_vdev *vdev,
1799 				     struct wlan_cm_roam_req *req,
1800 				     enum wlan_cm_connect_fail_reason reason)
1801 {
1802 	uint8_t vdev_id, roam_reason;
1803 	struct wlan_objmgr_pdev *pdev;
1804 
1805 	if (!vdev || !req) {
1806 		mlme_err("vdev or req is NULL");
1807 		return QDF_STATUS_E_INVAL;
1808 	}
1809 
1810 	if (reason == CM_NO_CANDIDATE_FOUND)
1811 		roam_reason = REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW;
1812 	else
1813 		roam_reason = REASON_PREAUTH_FAILED_FOR_ALL;
1814 
1815 	pdev = wlan_vdev_get_pdev(vdev);
1816 	vdev_id = wlan_vdev_get_id(vdev);
1817 
1818 	if (req->source == CM_ROAMING_FW)
1819 		cm_roam_state_change(pdev, vdev_id,
1820 				     ROAM_SCAN_OFFLOAD_RESTART,
1821 				     roam_reason, NULL, false);
1822 	else
1823 		cm_roam_state_change(pdev, vdev_id,
1824 				     ROAM_SCAN_OFFLOAD_START,
1825 				     roam_reason, NULL, false);
1826 	return QDF_STATUS_SUCCESS;
1827 }
1828 #endif
1829 
1830 void wlan_cm_fill_crypto_filter_from_vdev(struct wlan_objmgr_vdev *vdev,
1831 					  struct scan_filter *filter)
1832 {
1833 	struct rso_config *rso_cfg;
1834 
1835 	filter->authmodeset =
1836 		wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_AUTH_MODE);
1837 	filter->mcastcipherset =
1838 		wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_MCAST_CIPHER);
1839 	filter->ucastcipherset =
1840 		wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_UCAST_CIPHER);
1841 	filter->key_mgmt =
1842 		wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
1843 	filter->mgmtcipherset =
1844 		wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_MGMT_CIPHER);
1845 
1846 	rso_cfg = wlan_cm_get_rso_config(vdev);
1847 	if (!rso_cfg)
1848 		return;
1849 
1850 	if (rso_cfg->orig_sec_info.rsn_caps &
1851 	    WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)
1852 		filter->pmf_cap = WLAN_PMF_REQUIRED;
1853 	else if (rso_cfg->orig_sec_info.rsn_caps &
1854 		 WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)
1855 		filter->pmf_cap = WLAN_PMF_CAPABLE;
1856 }
1857 
1858 static void cm_dump_occupied_chan_list(struct wlan_chan_list *occupied_ch)
1859 {
1860 	uint8_t idx;
1861 	uint32_t buff_len;
1862 	char *chan_buff;
1863 	uint32_t len = 0;
1864 
1865 	buff_len = (occupied_ch->num_chan * 5) + 1;
1866 	chan_buff = qdf_mem_malloc(buff_len);
1867 	if (!chan_buff)
1868 		return;
1869 
1870 	for (idx = 0; idx < occupied_ch->num_chan; idx++)
1871 		len += qdf_scnprintf(chan_buff + len, buff_len - len, " %d",
1872 				     occupied_ch->freq_list[idx]);
1873 
1874 	mlme_nofl_debug("Occupied chan list[%d]:%s",
1875 			occupied_ch->num_chan, chan_buff);
1876 
1877 	qdf_mem_free(chan_buff);
1878 }
1879 
1880 /**
1881  * cm_should_add_to_occupied_channels() - validates bands of active_ch_freq and
1882  * curr node freq before addition of curr node freq to occupied channels
1883  *
1884  * @active_ch_freq: active channel frequency
1885  * @cur_node_chan_freq: curr channel frequency
1886  * @dual_sta_roam_active: dual sta roam active
1887  *
1888  * Return: True if active_ch_freq and cur_node_chan_freq belongs to same
1889  * bands else false
1890  **/
1891 static bool cm_should_add_to_occupied_channels(qdf_freq_t active_ch_freq,
1892 					       qdf_freq_t cur_node_chan_freq,
1893 					       bool dual_sta_roam_active)
1894 {
1895 	/* all channels can be added if dual STA roam is not active */
1896 	if (!dual_sta_roam_active)
1897 		return true;
1898 
1899 	/* when dual STA roam is active, channels must be in the same band */
1900 	if (WLAN_REG_IS_24GHZ_CH_FREQ(active_ch_freq) &&
1901 	    WLAN_REG_IS_24GHZ_CH_FREQ(cur_node_chan_freq))
1902 		return true;
1903 
1904 	if (!WLAN_REG_IS_24GHZ_CH_FREQ(active_ch_freq) &&
1905 	    !WLAN_REG_IS_24GHZ_CH_FREQ(cur_node_chan_freq))
1906 		return true;
1907 
1908 	/* not in same band */
1909 	return false;
1910 }
1911 
1912 static QDF_STATUS cm_add_to_freq_list_front(qdf_freq_t *ch_freq_lst,
1913 					    int num_chan, qdf_freq_t chan_freq)
1914 {
1915 	int i = 0;
1916 
1917 	/* Check for NULL pointer */
1918 	if (!ch_freq_lst)
1919 		return QDF_STATUS_E_NULL_VALUE;
1920 
1921 	/* Make room for the addition.  (Start moving from the back.) */
1922 	for (i = num_chan; i > 0; i--)
1923 		ch_freq_lst[i] = ch_freq_lst[i - 1];
1924 
1925 	/* Now add the NEW channel...at the front */
1926 	ch_freq_lst[0] = chan_freq;
1927 
1928 	return QDF_STATUS_SUCCESS;
1929 }
1930 
1931 /* Add the channel to the occupied channels array */
1932 static void cm_add_to_occupied_channels(qdf_freq_t ch_freq,
1933 					struct rso_config *rso_cfg,
1934 					bool is_init_list)
1935 {
1936 	QDF_STATUS status;
1937 	uint8_t num_occupied_ch = rso_cfg->occupied_chan_lst.num_chan;
1938 	qdf_freq_t *occupied_ch_lst = rso_cfg->occupied_chan_lst.freq_list;
1939 
1940 	if (is_init_list)
1941 		rso_cfg->roam_candidate_count++;
1942 
1943 	if (wlan_is_channel_present_in_list(occupied_ch_lst,
1944 					    num_occupied_ch, ch_freq))
1945 		return;
1946 
1947 	if (num_occupied_ch >= CFG_VALID_CHANNEL_LIST_LEN)
1948 		num_occupied_ch = CFG_VALID_CHANNEL_LIST_LEN - 1;
1949 
1950 	status = cm_add_to_freq_list_front(occupied_ch_lst,
1951 					   num_occupied_ch, ch_freq);
1952 	if (QDF_IS_STATUS_SUCCESS(status)) {
1953 		rso_cfg->occupied_chan_lst.num_chan++;
1954 		if (rso_cfg->occupied_chan_lst.num_chan >
1955 		    BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN)
1956 			rso_cfg->occupied_chan_lst.num_chan =
1957 				BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN;
1958 	}
1959 }
1960 
1961 void wlan_cm_init_occupied_ch_freq_list(struct wlan_objmgr_pdev *pdev,
1962 					struct wlan_objmgr_psoc *psoc,
1963 					uint8_t vdev_id)
1964 {
1965 	qdf_list_t *list = NULL;
1966 	qdf_list_node_t *cur_lst = NULL;
1967 	qdf_list_node_t *next_lst = NULL;
1968 	struct scan_cache_node *cur_node = NULL;
1969 	struct scan_filter *filter;
1970 	bool dual_sta_roam_active;
1971 	struct wlan_objmgr_vdev *vdev;
1972 	QDF_STATUS status;
1973 	struct rso_config *rso_cfg;
1974 	struct rso_cfg_params *cfg_params;
1975 	struct wlan_ssid ssid;
1976 	qdf_freq_t op_freq, freq;
1977 
1978 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
1979 						    WLAN_MLME_CM_ID);
1980 	if (!vdev) {
1981 		mlme_err("vdev object is NULL for vdev %d", vdev_id);
1982 		return;
1983 	}
1984 	rso_cfg = wlan_cm_get_rso_config(vdev);
1985 	if (!rso_cfg)
1986 		goto rel_vdev_ref;
1987 	op_freq = wlan_get_operation_chan_freq(vdev);
1988 	if (!op_freq) {
1989 		mlme_debug("failed to get op freq");
1990 		goto rel_vdev_ref;
1991 	}
1992 	status = wlan_vdev_mlme_get_ssid(vdev, ssid.ssid, &ssid.length);
1993 	if (QDF_IS_STATUS_ERROR(status)) {
1994 		mlme_err("failed to find SSID for vdev %d", vdev_id);
1995 		goto rel_vdev_ref;
1996 	}
1997 
1998 	cfg_params = &rso_cfg->cfg_param;
1999 
2000 	if (cfg_params->specific_chan_info.num_chan) {
2001 		/*
2002 		 * Ini file contains neighbor scan channel list, hence NO need
2003 		 * to build occupied channel list"
2004 		 */
2005 		mlme_debug("Ini contains neighbor scan ch list");
2006 		goto rel_vdev_ref;
2007 	}
2008 
2009 	filter = qdf_mem_malloc(sizeof(*filter));
2010 	if (!filter)
2011 		goto rel_vdev_ref;
2012 
2013 	wlan_cm_fill_crypto_filter_from_vdev(vdev, filter);
2014 	filter->num_of_ssid = 1;
2015 	qdf_mem_copy(&filter->ssid_list[0], &ssid, sizeof(ssid));
2016 
2017 	/* Empty occupied channels here */
2018 	rso_cfg->occupied_chan_lst.num_chan = 0;
2019 	rso_cfg->roam_candidate_count = 0;
2020 
2021 	cm_add_to_occupied_channels(op_freq, rso_cfg, true);
2022 	list = wlan_scan_get_result(pdev, filter);
2023 	qdf_mem_free(filter);
2024 	if (!list || (list && !qdf_list_size(list)))
2025 		goto err;
2026 
2027 	dual_sta_roam_active =
2028 			wlan_mlme_get_dual_sta_roaming_enabled(psoc);
2029 	dual_sta_roam_active = dual_sta_roam_active &&
2030 			       policy_mgr_mode_specific_connection_count
2031 				(psoc, PM_STA_MODE, NULL) >= 2;
2032 
2033 	qdf_list_peek_front(list, &cur_lst);
2034 	while (cur_lst) {
2035 		cur_node = qdf_container_of(cur_lst, struct scan_cache_node,
2036 					    node);
2037 		freq = cur_node->entry->channel.chan_freq;
2038 		if (cm_should_add_to_occupied_channels(op_freq, freq,
2039 						       dual_sta_roam_active))
2040 			cm_add_to_occupied_channels(freq, rso_cfg, true);
2041 
2042 		qdf_list_peek_next(list, cur_lst, &next_lst);
2043 		cur_lst = next_lst;
2044 		next_lst = NULL;
2045 	}
2046 err:
2047 	cm_dump_occupied_chan_list(&rso_cfg->occupied_chan_lst);
2048 	if (list)
2049 		wlan_scan_purge_results(list);
2050 rel_vdev_ref:
2051 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
2052 }
2053 
2054 #ifdef WLAN_FEATURE_FILS_SK
2055 QDF_STATUS
2056 wlan_cm_update_mlme_fils_info(struct wlan_objmgr_vdev *vdev,
2057 			      struct wlan_fils_con_info *src_fils_info)
2058 {
2059 	struct mlme_legacy_priv *mlme_priv;
2060 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
2061 	struct wlan_fils_connection_info *tgt_info;
2062 
2063 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
2064 	if (!mlme_priv) {
2065 		mlme_err("vdev legacy private object is NULL for vdev %d",
2066 			 vdev_id);
2067 		return QDF_STATUS_E_FAILURE;
2068 	}
2069 
2070 	if (!src_fils_info) {
2071 		mlme_debug("FILS: vdev:%d Clear fils info", vdev_id);
2072 		qdf_mem_free(mlme_priv->connect_info.fils_con_info);
2073 		mlme_priv->connect_info.fils_con_info = NULL;
2074 		return QDF_STATUS_SUCCESS;
2075 	}
2076 
2077 	if (mlme_priv->connect_info.fils_con_info)
2078 		qdf_mem_free(mlme_priv->connect_info.fils_con_info);
2079 
2080 	mlme_priv->connect_info.fils_con_info =
2081 		qdf_mem_malloc(sizeof(struct wlan_fils_connection_info));
2082 	if (!mlme_priv->connect_info.fils_con_info)
2083 		return QDF_STATUS_E_NOMEM;
2084 
2085 	tgt_info = mlme_priv->connect_info.fils_con_info;
2086 	mlme_debug("FILS: vdev:%d update fils info", vdev_id);
2087 	tgt_info->is_fils_connection = src_fils_info->is_fils_connection;
2088 	tgt_info->key_nai_length = src_fils_info->username_len;
2089 	qdf_mem_copy(tgt_info->keyname_nai, src_fils_info->username,
2090 		     tgt_info->key_nai_length);
2091 
2092 	tgt_info->realm_len = src_fils_info->realm_len;
2093 	qdf_mem_copy(tgt_info->realm, src_fils_info->realm,
2094 		     tgt_info->realm_len);
2095 
2096 	tgt_info->r_rk_length = src_fils_info->rrk_len;
2097 	qdf_mem_copy(tgt_info->r_rk, src_fils_info->rrk,
2098 		     tgt_info->r_rk_length);
2099 	tgt_info->erp_sequence_number = src_fils_info->next_seq_num;
2100 	tgt_info->auth_type = src_fils_info->auth_type;
2101 
2102 	return QDF_STATUS_SUCCESS;
2103 }
2104 
2105 void wlan_cm_update_hlp_info(struct wlan_objmgr_psoc *psoc,
2106 			     const uint8_t *gen_ie, uint16_t len,
2107 			     uint8_t vdev_id, bool flush)
2108 {
2109 	struct wlan_objmgr_vdev *vdev;
2110 
2111 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
2112 						    WLAN_MLME_NB_ID);
2113 	if (!vdev) {
2114 		mlme_err("vdev object is NULL for vdev_id %d", vdev_id);
2115 		return;
2116 	}
2117 
2118 	cm_update_hlp_info(vdev, gen_ie, len, flush);
2119 
2120 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
2121 }
2122 
2123 struct wlan_fils_connection_info *wlan_cm_get_fils_connection_info(
2124 				struct wlan_objmgr_psoc *psoc,
2125 				uint8_t vdev_id)
2126 {
2127 	struct wlan_objmgr_vdev *vdev;
2128 	struct mlme_legacy_priv *mlme_priv;
2129 	struct wlan_fils_connection_info *fils_info;
2130 
2131 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
2132 						    WLAN_MLME_NB_ID);
2133 	if (!vdev) {
2134 		mlme_err("vdev object is NULL");
2135 		return NULL;
2136 	}
2137 
2138 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
2139 	if (!mlme_priv) {
2140 		mlme_err("vdev legacy private object is NULL");
2141 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
2142 		return NULL;
2143 	}
2144 
2145 	fils_info = mlme_priv->connect_info.fils_con_info;
2146 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
2147 
2148 	return fils_info;
2149 }
2150 
2151 QDF_STATUS wlan_cm_update_fils_ft(struct wlan_objmgr_psoc *psoc,
2152 				  uint8_t vdev_id, uint8_t *fils_ft,
2153 				  uint8_t fils_ft_len)
2154 {
2155 	struct wlan_objmgr_vdev *vdev;
2156 	struct mlme_legacy_priv *mlme_priv;
2157 
2158 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
2159 						    WLAN_MLME_NB_ID);
2160 	if (!vdev) {
2161 		mlme_err("vdev object is NULL");
2162 		return QDF_STATUS_E_FAILURE;
2163 	}
2164 
2165 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
2166 	if (!mlme_priv) {
2167 		mlme_err("vdev legacy private object is NULL");
2168 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
2169 		return QDF_STATUS_E_FAILURE;
2170 	}
2171 
2172 	if (!mlme_priv->connect_info.fils_con_info || !fils_ft ||
2173 	    !fils_ft_len ||
2174 	    !mlme_priv->connect_info.fils_con_info->is_fils_connection) {
2175 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
2176 		return QDF_STATUS_E_FAILURE;
2177 	}
2178 
2179 	mlme_priv->connect_info.fils_con_info->fils_ft_len = fils_ft_len;
2180 	qdf_mem_copy(mlme_priv->connect_info.fils_con_info->fils_ft, fils_ft,
2181 		     fils_ft_len);
2182 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
2183 
2184 	return QDF_STATUS_SUCCESS;
2185 }
2186 #endif
2187 
2188 #ifdef WLAN_FEATURE_11BE_MLO
2189 static void
2190 wlan_cm_get_mlo_associated_ch_info(struct wlan_objmgr_vdev *vdev,
2191 				   enum phy_ch_width scanned_ch_width,
2192 				   struct assoc_channel_info *assoc_chan_info)
2193 {
2194 	struct mlme_legacy_priv *mlme_priv;
2195 	struct wlan_channel *des_chan;
2196 	struct wlan_mlo_dev_context *mlo_dev_ctx;
2197 	struct wlan_mlo_sta *sta_ctx = NULL;
2198 	uint8_t i;
2199 	struct wlan_objmgr_vdev *mlo_vdev;
2200 	struct assoc_channel_info *temp_assoc_chan_info;
2201 
2202 	mlo_dev_ctx = vdev->mlo_dev_ctx;
2203 	if (!mlo_dev_ctx) {
2204 		mlme_err("vdev %d :mlo_dev_ctx is NULL",
2205 			 vdev->vdev_objmgr.vdev_id);
2206 		return;
2207 	}
2208 
2209 	sta_ctx = mlo_dev_ctx->sta_ctx;
2210 	if (!sta_ctx) {
2211 		mlme_err("vdev %d :mlo_dev_ctx is NULL",
2212 			 vdev->vdev_objmgr.vdev_id);
2213 		return;
2214 	}
2215 
2216 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
2217 		if (!mlo_dev_ctx->wlan_vdev_list[i])
2218 			continue;
2219 		if (qdf_test_bit(i, sta_ctx->wlan_connected_links)) {
2220 			mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
2221 			des_chan = wlan_vdev_mlme_get_des_chan(mlo_vdev);
2222 			if (!des_chan) {
2223 				mlme_debug("NULL des_chan");
2224 				return;
2225 			}
2226 
2227 			if (des_chan->ch_width == scanned_ch_width) {
2228 				mlme_priv =
2229 					wlan_vdev_mlme_get_ext_hdl(mlo_vdev);
2230 				if (!mlme_priv) {
2231 					mlme_legacy_err("mlme_priv is NULL");
2232 					return;
2233 				}
2234 				temp_assoc_chan_info =
2235 				    &mlme_priv->connect_info.assoc_chan_info;
2236 				assoc_chan_info->sec_2g_freq =
2237 					temp_assoc_chan_info->sec_2g_freq;
2238 				mlme_debug("vdev %d: assoc sec_2g_freq:%d",
2239 					   mlo_vdev->vdev_objmgr.vdev_id,
2240 					   assoc_chan_info->sec_2g_freq);
2241 				break;
2242 			}
2243 		}
2244 	}
2245 }
2246 #else
2247 static void
2248 wlan_cm_get_mlo_associated_ch_info(struct wlan_objmgr_vdev *vdev,
2249 				   enum phy_ch_width ch_width,
2250 				   struct assoc_channel_info *chan_info)
2251 {
2252 }
2253 #endif
2254 
2255 void wlan_cm_get_associated_ch_info(struct wlan_objmgr_psoc *psoc,
2256 				    uint8_t vdev_id,
2257 				    enum phy_ch_width scanned_ch_width,
2258 				    struct assoc_channel_info *assoc_chan_info)
2259 {
2260 	struct wlan_objmgr_vdev *vdev;
2261 	struct mlme_legacy_priv *mlme_priv;
2262 
2263 	assoc_chan_info->assoc_ch_width = CH_WIDTH_INVALID;
2264 	assoc_chan_info->sec_2g_freq = 0;
2265 
2266 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
2267 						    WLAN_MLME_NB_ID);
2268 	if (!vdev) {
2269 		mlme_legacy_err("vdev %d: vdev not found", vdev_id);
2270 		return;
2271 	}
2272 
2273 	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
2274 		mlme_debug("vdev %d: get assoc chan info for mlo connection",
2275 			   vdev_id);
2276 		wlan_cm_get_mlo_associated_ch_info(vdev, scanned_ch_width,
2277 						   assoc_chan_info);
2278 		goto release;
2279 	}
2280 
2281 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
2282 	if (!mlme_priv) {
2283 		mlme_legacy_err("mlme_priv is NULL");
2284 		goto release;
2285 	}
2286 
2287 	assoc_chan_info->assoc_ch_width =
2288 		mlme_priv->connect_info.assoc_chan_info.assoc_ch_width;
2289 	assoc_chan_info->sec_2g_freq =
2290 		mlme_priv->connect_info.assoc_chan_info.sec_2g_freq;
2291 
2292 	mlme_debug("vdev %d: associated_ch_width:%d, sec_2g_freq:%d", vdev_id,
2293 		   assoc_chan_info->assoc_ch_width,
2294 		   assoc_chan_info->sec_2g_freq);
2295 
2296 release:
2297 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
2298 }
2299 
2300 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
2301 QDF_STATUS
2302 wlan_cm_update_roam_scan_scheme_bitmap(struct wlan_objmgr_psoc *psoc,
2303 				       uint8_t vdev_id,
2304 				       uint32_t roam_scan_scheme_bitmap)
2305 {
2306 	struct wlan_objmgr_vdev *vdev;
2307 	struct rso_config *rso_cfg;
2308 
2309 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
2310 						    WLAN_MLME_NB_ID);
2311 
2312 	if (!vdev) {
2313 		mlme_err("vdev%d: vdev object is NULL", vdev_id);
2314 		return QDF_STATUS_E_FAILURE;
2315 	}
2316 
2317 	rso_cfg = wlan_cm_get_rso_config(vdev);
2318 	if (!rso_cfg) {
2319 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
2320 		return QDF_STATUS_E_FAILURE;
2321 	}
2322 	rso_cfg->roam_scan_scheme_bitmap = roam_scan_scheme_bitmap;
2323 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
2324 
2325 	return QDF_STATUS_SUCCESS;
2326 }
2327 
2328 QDF_STATUS wlan_cm_set_roam_band_bitmask(struct wlan_objmgr_psoc *psoc,
2329 					 uint8_t vdev_id,
2330 					 uint32_t roam_band_bitmask)
2331 {
2332 	struct cm_roam_values_copy src_config = {};
2333 
2334 	src_config.uint_value = roam_band_bitmask;
2335 	return wlan_cm_roam_cfg_set_value(psoc, vdev_id, ROAM_BAND,
2336 					  &src_config);
2337 }
2338 
2339 QDF_STATUS wlan_cm_set_roam_band_update(struct wlan_objmgr_psoc *psoc,
2340 					uint8_t vdev_id)
2341 {
2342 	return cm_roam_update_cfg(psoc, vdev_id,
2343 				  REASON_ROAM_CONTROL_CONFIG_ENABLED);
2344 }
2345 
2346 uint32_t wlan_cm_get_roam_scan_scheme_bitmap(struct wlan_objmgr_psoc *psoc,
2347 					     uint8_t vdev_id)
2348 {
2349 	struct wlan_objmgr_vdev *vdev;
2350 	uint32_t roam_scan_scheme_bitmap;
2351 	struct rso_config *rso_cfg;
2352 
2353 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
2354 						    WLAN_MLME_NB_ID);
2355 
2356 	if (!vdev) {
2357 		mlme_err("vdev%d: vdev object is NULL", vdev_id);
2358 		return 0;
2359 	}
2360 
2361 	rso_cfg = wlan_cm_get_rso_config(vdev);
2362 	if (!rso_cfg) {
2363 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
2364 		return 0;
2365 	}
2366 
2367 	roam_scan_scheme_bitmap = rso_cfg->roam_scan_scheme_bitmap;
2368 
2369 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
2370 
2371 	return roam_scan_scheme_bitmap;
2372 }
2373 
2374 QDF_STATUS
2375 wlan_cm_update_roam_states(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
2376 			   uint32_t value, enum roam_fail_params states)
2377 {
2378 	struct wlan_objmgr_vdev *vdev;
2379 	struct rso_config *rso_cfg;
2380 
2381 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
2382 						    WLAN_MLME_NB_ID);
2383 
2384 	if (!vdev) {
2385 		mlme_err("vdev%d: vdev object is NULL", vdev_id);
2386 		return QDF_STATUS_E_FAILURE;
2387 	}
2388 
2389 	rso_cfg = wlan_cm_get_rso_config(vdev);
2390 	if (!rso_cfg) {
2391 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
2392 		return QDF_STATUS_E_FAILURE;
2393 	}
2394 
2395 	switch (states) {
2396 	case ROAM_TRIGGER_REASON:
2397 		rso_cfg->roam_trigger_reason = value;
2398 		break;
2399 	case ROAM_INVOKE_FAIL_REASON:
2400 		rso_cfg->roam_invoke_fail_reason = value;
2401 		break;
2402 	case ROAM_FAIL_REASON:
2403 		rso_cfg->roam_fail_reason = value;
2404 		break;
2405 	default:
2406 		break;
2407 	}
2408 
2409 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
2410 
2411 	return QDF_STATUS_SUCCESS;
2412 }
2413 
2414 uint32_t wlan_cm_get_roam_states(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
2415 				 enum roam_fail_params states)
2416 {
2417 	struct wlan_objmgr_vdev *vdev;
2418 	uint32_t roam_states = 0;
2419 	struct rso_config *rso_cfg;
2420 
2421 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
2422 						    WLAN_MLME_NB_ID);
2423 
2424 	if (!vdev) {
2425 		mlme_err("vdev%d: vdev object is NULL", vdev_id);
2426 		return 0;
2427 	}
2428 
2429 	rso_cfg = wlan_cm_get_rso_config(vdev);
2430 	if (!rso_cfg) {
2431 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
2432 		return 0;
2433 	}
2434 
2435 	switch (states) {
2436 	case ROAM_TRIGGER_REASON:
2437 		roam_states = rso_cfg->roam_trigger_reason;
2438 		break;
2439 	case ROAM_INVOKE_FAIL_REASON:
2440 		roam_states = rso_cfg->roam_invoke_fail_reason;
2441 		break;
2442 	case ROAM_FAIL_REASON:
2443 		roam_states = rso_cfg->roam_fail_reason;
2444 		break;
2445 	default:
2446 		break;
2447 	}
2448 
2449 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
2450 
2451 	return roam_states;
2452 }
2453 
2454 QDF_STATUS
2455 wlan_cm_update_roam_rt_stats(struct wlan_objmgr_psoc *psoc,
2456 			     uint8_t value, enum roam_rt_stats_params stats)
2457 {
2458 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
2459 	struct wlan_cm_roam_rt_stats *roam_rt_stats;
2460 
2461 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
2462 	if (!mlme_obj) {
2463 		mlme_legacy_err("Failed to get MLME Obj");
2464 		return QDF_STATUS_E_FAILURE;
2465 	}
2466 
2467 	roam_rt_stats = &mlme_obj->cfg.lfr.roam_rt_stats;
2468 
2469 	switch (stats) {
2470 	case ROAM_RT_STATS_ENABLE:
2471 		roam_rt_stats->roam_stats_enabled = value;
2472 		break;
2473 	case ROAM_RT_STATS_SUSPEND_MODE_ENABLE:
2474 		roam_rt_stats->roam_stats_wow_sent = value;
2475 		break;
2476 	default:
2477 		break;
2478 	}
2479 
2480 	return QDF_STATUS_SUCCESS;
2481 }
2482 
2483 uint8_t wlan_cm_get_roam_rt_stats(struct wlan_objmgr_psoc *psoc,
2484 				  enum roam_rt_stats_params stats)
2485 {
2486 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
2487 	struct wlan_cm_roam_rt_stats *roam_rt_stats;
2488 	uint8_t rstats_value = 0;
2489 
2490 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
2491 	if (!mlme_obj) {
2492 		mlme_legacy_err("Failed to get MLME Obj");
2493 		return QDF_STATUS_E_FAILURE;
2494 	}
2495 
2496 	roam_rt_stats = &mlme_obj->cfg.lfr.roam_rt_stats;
2497 	switch (stats) {
2498 	case ROAM_RT_STATS_ENABLE:
2499 		rstats_value = roam_rt_stats->roam_stats_enabled;
2500 		break;
2501 	case ROAM_RT_STATS_SUSPEND_MODE_ENABLE:
2502 		rstats_value = roam_rt_stats->roam_stats_wow_sent;
2503 		break;
2504 	default:
2505 		break;
2506 	}
2507 
2508 	return rstats_value;
2509 }
2510 #endif
2511 
2512 QDF_STATUS wlan_get_chan_by_bssid_from_rnr(struct wlan_objmgr_vdev *vdev,
2513 					   wlan_cm_id cm_id,
2514 					   struct qdf_mac_addr *link_addr,
2515 					   uint8_t *chan, uint8_t *op_class)
2516 {
2517 	struct reduced_neighbor_report *rnr;
2518 	int i;
2519 	QDF_STATUS status;
2520 
2521 	*chan = 0;
2522 	rnr = qdf_mem_malloc(sizeof(*rnr));
2523 	if (!rnr)
2524 		return QDF_STATUS_E_NOMEM;
2525 
2526 	status = wlan_cm_get_rnr(vdev, cm_id, rnr);
2527 	if (QDF_IS_STATUS_ERROR(status)) {
2528 		qdf_mem_free(rnr);
2529 		return status;
2530 	}
2531 
2532 	for (i = 0; i < MAX_RNR_BSS; i++) {
2533 		if (!rnr->bss_info[i].channel_number)
2534 			continue;
2535 		if (qdf_is_macaddr_equal(link_addr, &rnr->bss_info[i].bssid)) {
2536 			*chan = rnr->bss_info[i].channel_number;
2537 			*op_class = rnr->bss_info[i].operating_class;
2538 			break;
2539 		}
2540 	}
2541 	qdf_mem_free(rnr);
2542 
2543 	return QDF_STATUS_SUCCESS;
2544 }
2545 
2546 #ifdef WLAN_FEATURE_11BE_MLO
2547 /**
2548  * mlo_rnr_link_id_cmp() - compare given link id with link id in rnr
2549  * @rnr_bss_info: rnr bss info
2550  * @link_id: link id
2551  *
2552  * Return: true if given link id is the same with link id in rnr
2553  */
2554 static bool mlo_rnr_link_id_cmp(struct rnr_bss_info *rnr_bss_info,
2555 				uint8_t link_id)
2556 {
2557 	if (rnr_bss_info)
2558 		return link_id == rnr_bss_info->mld_info.link_id;
2559 
2560 	return false;
2561 }
2562 
2563 QDF_STATUS wlan_get_chan_by_link_id_from_rnr(struct wlan_objmgr_vdev *vdev,
2564 					     wlan_cm_id cm_id,
2565 					     uint8_t link_id,
2566 					     uint8_t *chan, uint8_t *op_class)
2567 {
2568 	struct reduced_neighbor_report *rnr;
2569 	int i;
2570 	QDF_STATUS status;
2571 
2572 	*chan = 0;
2573 	rnr = qdf_mem_malloc(sizeof(*rnr));
2574 	if (!rnr)
2575 		return QDF_STATUS_E_NOMEM;
2576 
2577 	status = wlan_cm_get_rnr(vdev, cm_id, rnr);
2578 	if (QDF_IS_STATUS_ERROR(status)) {
2579 		qdf_mem_free(rnr);
2580 		return status;
2581 	}
2582 
2583 	for (i = 0; i < MAX_RNR_BSS; i++) {
2584 		if (!rnr->bss_info[i].channel_number)
2585 			continue;
2586 		if (mlo_rnr_link_id_cmp(&rnr->bss_info[i], link_id)) {
2587 			*chan = rnr->bss_info[i].channel_number;
2588 			*op_class = rnr->bss_info[i].operating_class;
2589 			break;
2590 		}
2591 	}
2592 	qdf_mem_free(rnr);
2593 
2594 	return QDF_STATUS_SUCCESS;
2595 }
2596 #endif
2597 
2598 QDF_STATUS wlan_cm_sta_mlme_vdev_roam_notify(struct vdev_mlme_obj *vdev_mlme,
2599 					     uint16_t data_len, void *data)
2600 {
2601 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2602 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
2603 	status = cm_roam_sync_event_handler_cb(vdev_mlme->vdev, data, data_len);
2604 	if (QDF_IS_STATUS_ERROR(status))
2605 		mlme_err("Failed to process roam synch event");
2606 #endif
2607 	return status;
2608 }
2609 
2610 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
2611 static void
2612 cm_handle_roam_offload_events(struct roam_offload_roam_event *roam_event)
2613 {
2614 	switch (roam_event->reason) {
2615 	case ROAM_REASON_HO_FAILED: {
2616 		struct qdf_mac_addr bssid;
2617 
2618 		bssid.bytes[0] = roam_event->notif_params >> 0 & 0xFF;
2619 		bssid.bytes[1] = roam_event->notif_params >> 8 & 0xFF;
2620 		bssid.bytes[2] = roam_event->notif_params >> 16 & 0xFF;
2621 		bssid.bytes[3] = roam_event->notif_params >> 24 & 0xFF;
2622 		bssid.bytes[4] = roam_event->notif_params1 >> 0 & 0xFF;
2623 		bssid.bytes[5] = roam_event->notif_params1 >> 8 & 0xFF;
2624 		cm_handle_roam_reason_ho_failed(roam_event->vdev_id, bssid,
2625 						roam_event->hw_mode_trans_ind);
2626 	}
2627 	break;
2628 	case ROAM_REASON_INVALID:
2629 		cm_invalid_roam_reason_handler(roam_event->vdev_id,
2630 					       roam_event->notif,
2631 					       roam_event->notif_params);
2632 		break;
2633 	default:
2634 		break;
2635 	}
2636 }
2637 
2638 QDF_STATUS
2639 cm_vdev_disconnect_event_handler(struct vdev_disconnect_event_data *data)
2640 {
2641 	return cm_handle_disconnect_reason(data);
2642 }
2643 
2644 QDF_STATUS
2645 cm_roam_auth_offload_event_handler(struct auth_offload_event *auth_event)
2646 {
2647 	return cm_handle_auth_offload(auth_event);
2648 }
2649 
2650 QDF_STATUS
2651 cm_roam_pmkid_request_handler(struct roam_pmkid_req_event *data)
2652 {
2653 	QDF_STATUS status;
2654 
2655 	status = cm_roam_pmkid_req_ind(data->psoc, data->vdev_id, data);
2656 	if (QDF_IS_STATUS_ERROR(status))
2657 		mlme_err("Pmkid request failed");
2658 
2659 	return status;
2660 }
2661 #else
2662 static void
2663 cm_handle_roam_offload_events(struct roam_offload_roam_event *roam_event)
2664 {
2665 	mlme_debug("Unhandled roam event with reason 0x%x for vdev_id %u",
2666 		   roam_event->reason, roam_event->vdev_id);
2667 }
2668 
2669 QDF_STATUS
2670 cm_vdev_disconnect_event_handler(struct vdev_disconnect_event_data *data)
2671 {
2672 	return QDF_STATUS_SUCCESS;
2673 }
2674 
2675 QDF_STATUS
2676 cm_roam_auth_offload_event_handler(struct auth_offload_event *auth_event)
2677 {
2678 	return QDF_STATUS_SUCCESS;
2679 }
2680 
2681 QDF_STATUS
2682 cm_roam_pmkid_request_handler(struct roam_pmkid_req_event *data)
2683 {
2684 	return QDF_STATUS_SUCCESS;
2685 }
2686 #endif
2687 
2688 #ifdef WLAN_VENDOR_HANDOFF_CONTROL
2689 void
2690 cm_roam_vendor_handoff_event_handler(struct wlan_objmgr_psoc *psoc,
2691 				     struct roam_vendor_handoff_params *data)
2692 {
2693 	struct wlan_objmgr_vdev *vdev;
2694 	struct mlme_legacy_priv *mlme_priv;
2695 	void *vendor_handoff_context;
2696 	QDF_STATUS status;
2697 
2698 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, data->vdev_id,
2699 						    WLAN_MLME_OBJMGR_ID);
2700 	if (!vdev) {
2701 		mlme_err("vdev object is NULL for vdev %d", data->vdev_id);
2702 		return;
2703 	}
2704 
2705 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
2706 	if (!mlme_priv)
2707 		return;
2708 
2709 	vendor_handoff_context =
2710 		mlme_priv->cm_roam.vendor_handoff_param.vendor_handoff_context;
2711 
2712 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
2713 
2714 	status = mlme_cm_osif_get_vendor_handoff_params(psoc,
2715 							vendor_handoff_context);
2716 	if (QDF_IS_STATUS_ERROR(status)) {
2717 		mlme_debug("Failed to free vendor handoff request");
2718 		return;
2719 	}
2720 
2721 	mlme_debug("Reset vendor handoff req in progress context");
2722 	mlme_priv->cm_roam.vendor_handoff_param.req_in_progress = false;
2723 	mlme_priv->cm_roam.vendor_handoff_param.vendor_handoff_context = NULL;
2724 
2725 	status = cm_roam_update_vendor_handoff_config(psoc, data);
2726 	if (QDF_IS_STATUS_ERROR(status))
2727 		mlme_debug("Failed to update params in rso_config struct");
2728 }
2729 #endif
2730 
2731 QDF_STATUS
2732 cm_roam_event_handler(struct roam_offload_roam_event *roam_event)
2733 {
2734 	switch (roam_event->reason) {
2735 	case ROAM_REASON_BTM:
2736 		cm_handle_roam_reason_btm(roam_event->vdev_id);
2737 		break;
2738 	case ROAM_REASON_BMISS:
2739 		cm_handle_roam_reason_bmiss(roam_event->vdev_id,
2740 					    roam_event->rssi);
2741 		break;
2742 	case ROAM_REASON_BETTER_AP:
2743 		cm_handle_roam_reason_better_ap(roam_event->vdev_id,
2744 						roam_event->rssi);
2745 		break;
2746 	case ROAM_REASON_SUITABLE_AP:
2747 		cm_handle_roam_reason_suitable_ap(roam_event->vdev_id,
2748 						  roam_event->rssi);
2749 		break;
2750 	case ROAM_REASON_HO_FAILED:
2751 		/*
2752 		 * Continue disconnect only if RSO_STOP timer is running when
2753 		 * this event is received and stopped as part of this.
2754 		 * Otherwise it's a normal HO_FAIL event and handle it in
2755 		 * legacy way.
2756 		 */
2757 		if (roam_event->rso_timer_stopped)
2758 			wlan_cm_rso_stop_continue_disconnect(roam_event->psoc,
2759 						roam_event->vdev_id, true);
2760 		fallthrough;
2761 	case ROAM_REASON_INVALID:
2762 		cm_handle_roam_offload_events(roam_event);
2763 		break;
2764 	case ROAM_REASON_RSO_STATUS:
2765 		/*
2766 		 * roam_event->rso_timer_stopped is set to true in target_if
2767 		 * only if RSO_STOP timer is running and it's stopped
2768 		 * successfully
2769 		 */
2770 		if (roam_event->rso_timer_stopped &&
2771 		    (roam_event->notif == CM_ROAM_NOTIF_SCAN_MODE_SUCCESS ||
2772 		     roam_event->notif == CM_ROAM_NOTIF_SCAN_MODE_FAIL))
2773 			wlan_cm_rso_stop_continue_disconnect(roam_event->psoc,
2774 						roam_event->vdev_id, false);
2775 		cm_rso_cmd_status_event_handler(roam_event->vdev_id,
2776 						roam_event->notif);
2777 		break;
2778 	case ROAM_REASON_INVOKE_ROAM_FAIL:
2779 		cm_handle_roam_reason_invoke_roam_fail(roam_event->vdev_id,
2780 						roam_event->notif_params,
2781 						roam_event->hw_mode_trans_ind);
2782 		break;
2783 	case ROAM_REASON_DEAUTH:
2784 		cm_handle_roam_reason_deauth(roam_event->vdev_id,
2785 					     roam_event->notif_params,
2786 					     roam_event->deauth_disassoc_frame,
2787 					     roam_event->notif_params1);
2788 		break;
2789 	default:
2790 		mlme_debug("Unhandled roam event with reason 0x%x for vdev_id %u",
2791 			   roam_event->reason, roam_event->vdev_id);
2792 		break;
2793 	}
2794 
2795 	return QDF_STATUS_SUCCESS;
2796 }
2797 
2798 static void
2799 cm_add_bssid_to_reject_list(struct wlan_objmgr_pdev *pdev,
2800 			    struct sir_rssi_disallow_lst *entry)
2801 {
2802 	struct reject_ap_info ap_info;
2803 
2804 	qdf_mem_zero(&ap_info, sizeof(struct reject_ap_info));
2805 
2806 	ap_info.bssid = entry->bssid;
2807 	ap_info.reject_ap_type = DRIVER_RSSI_REJECT_TYPE;
2808 	ap_info.rssi_reject_params.expected_rssi = entry->expected_rssi;
2809 	ap_info.rssi_reject_params.retry_delay = entry->retry_delay;
2810 	ap_info.reject_reason = entry->reject_reason;
2811 	ap_info.source = entry->source;
2812 	ap_info.rssi_reject_params.received_time = entry->received_time;
2813 	ap_info.rssi_reject_params.original_timeout = entry->original_timeout;
2814 	/* Add this ap info to the rssi reject ap type in denylist manager */
2815 	wlan_dlm_add_bssid_to_reject_list(pdev, &ap_info);
2816 }
2817 
2818 QDF_STATUS
2819 cm_btm_denylist_event_handler(struct wlan_objmgr_psoc *psoc,
2820 			      struct roam_denylist_event *list)
2821 {
2822 	uint32_t i, pdev_id;
2823 	struct sir_rssi_disallow_lst entry;
2824 	struct roam_denylist_timeout *denylist;
2825 	struct wlan_objmgr_pdev *pdev;
2826 
2827 	pdev_id = wlan_get_pdev_id_from_vdev_id(psoc, list->vdev_id,
2828 						WLAN_MLME_CM_ID);
2829 	if (pdev_id == WLAN_INVALID_PDEV_ID) {
2830 		mlme_err("Invalid pdev id");
2831 		return QDF_STATUS_E_INVAL;
2832 	}
2833 
2834 	pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_MLME_CM_ID);
2835 	if (!pdev) {
2836 		mlme_err("Invalid pdev");
2837 		return QDF_STATUS_E_INVAL;
2838 	}
2839 
2840 	mlme_debug("Received Denylist event from FW num entries %d",
2841 		   list->num_entries);
2842 	denylist = &list->roam_denylist[0];
2843 	for (i = 0; i < list->num_entries; i++) {
2844 		qdf_mem_zero(&entry, sizeof(struct sir_rssi_disallow_lst));
2845 		entry.bssid = denylist->bssid;
2846 		entry.time_during_rejection = denylist->received_time;
2847 		entry.reject_reason = denylist->reject_reason;
2848 		entry.source = denylist->source ? denylist->source :
2849 						   ADDED_BY_TARGET;
2850 		entry.original_timeout = denylist->original_timeout;
2851 		entry.received_time = denylist->received_time;
2852 		/* If timeout = 0 and rssi = 0 ignore the entry */
2853 		if (!denylist->timeout && !denylist->rssi) {
2854 			continue;
2855 		} else if (denylist->timeout) {
2856 			entry.retry_delay = denylist->timeout;
2857 			/* set 0dbm as expected rssi */
2858 			entry.expected_rssi = CM_MIN_RSSI;
2859 		} else {
2860 			/* denylist timeout as 0 */
2861 			entry.retry_delay = denylist->timeout;
2862 			entry.expected_rssi = denylist->rssi;
2863 		}
2864 
2865 		/* Add this bssid to the rssi reject ap type in denylist mgr */
2866 		cm_add_bssid_to_reject_list(pdev, &entry);
2867 		denylist++;
2868 	}
2869 	wlan_objmgr_pdev_release_ref(pdev, WLAN_MLME_CM_ID);
2870 
2871 	return QDF_STATUS_SUCCESS;
2872 }
2873 
2874 QDF_STATUS
2875 cm_roam_scan_ch_list_event_handler(struct cm_roam_scan_ch_resp *data)
2876 {
2877 	return cm_handle_scan_ch_list_data(data);
2878 }
2879 
2880 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
2881 /**
2882  * cm_roam_stats_get_trigger_detail_str - Return roam trigger string from the
2883  * enum roam_trigger_reason
2884  * @ptr: Pointer to the roam trigger info
2885  * @buf: Destination buffer to write the reason string
2886  * @is_full_scan: Is roam scan partial scan or all channels scan
2887  * @vdev_id: vdev id
2888  *
2889  * Return: None
2890  */
2891 static void
2892 cm_roam_stats_get_trigger_detail_str(struct wmi_roam_trigger_info *ptr,
2893 				     char *buf, bool is_full_scan,
2894 				     uint8_t vdev_id)
2895 {
2896 	uint16_t buf_cons, buf_left = MAX_ROAM_DEBUG_BUF_SIZE;
2897 	char *temp = buf;
2898 
2899 	buf_cons = qdf_snprint(temp, buf_left, "Reason: \"%s\" ",
2900 			       mlme_get_roam_trigger_str(ptr->trigger_reason));
2901 	temp += buf_cons;
2902 	buf_left -= buf_cons;
2903 
2904 	if (ptr->trigger_sub_reason) {
2905 		buf_cons = qdf_snprint(temp, buf_left, "Sub-Reason: %s",
2906 			      mlme_get_sub_reason_str(ptr->trigger_sub_reason));
2907 		temp += buf_cons;
2908 		buf_left -= buf_cons;
2909 	}
2910 
2911 	switch (ptr->trigger_reason) {
2912 	case ROAM_TRIGGER_REASON_PER:
2913 	case ROAM_TRIGGER_REASON_BMISS:
2914 	case ROAM_TRIGGER_REASON_HIGH_RSSI:
2915 	case ROAM_TRIGGER_REASON_MAWC:
2916 	case ROAM_TRIGGER_REASON_DENSE:
2917 	case ROAM_TRIGGER_REASON_BACKGROUND:
2918 	case ROAM_TRIGGER_REASON_IDLE:
2919 	case ROAM_TRIGGER_REASON_FORCED:
2920 	case ROAM_TRIGGER_REASON_UNIT_TEST:
2921 		break;
2922 	case ROAM_TRIGGER_REASON_BTM:
2923 		cm_roam_btm_req_event(&ptr->btm_trig_data, ptr, vdev_id, false);
2924 		buf_cons = qdf_snprint(
2925 				temp, buf_left,
2926 				"Req_mode: %d Disassoc_timer: %d",
2927 				ptr->btm_trig_data.btm_request_mode,
2928 				ptr->btm_trig_data.disassoc_timer / 1000);
2929 		temp += buf_cons;
2930 		buf_left -= buf_cons;
2931 
2932 		buf_cons = qdf_snprint(temp, buf_left,
2933 				"validity_interval: %d candidate_list_cnt: %d resp_status: %d, bss_termination_timeout: %d, mbo_assoc_retry_timeout: %d",
2934 				ptr->btm_trig_data.validity_interval / 1000,
2935 				ptr->btm_trig_data.candidate_list_count,
2936 				ptr->btm_trig_data.btm_resp_status,
2937 				ptr->btm_trig_data.btm_bss_termination_timeout,
2938 				ptr->btm_trig_data.btm_mbo_assoc_retry_timeout);
2939 		buf_left -= buf_cons;
2940 		temp += buf_cons;
2941 		break;
2942 	case ROAM_TRIGGER_REASON_BSS_LOAD:
2943 		buf_cons = qdf_snprint(temp, buf_left, "CU: %d %% ",
2944 				       ptr->cu_trig_data.cu_load);
2945 		temp += buf_cons;
2946 		buf_left -= buf_cons;
2947 		break;
2948 	case ROAM_TRIGGER_REASON_DEAUTH:
2949 		buf_cons = qdf_snprint(temp, buf_left, "Type: %d Reason: %d ",
2950 				       ptr->deauth_trig_data.type,
2951 				       ptr->deauth_trig_data.reason);
2952 		temp += buf_cons;
2953 		buf_left -= buf_cons;
2954 		break;
2955 	case ROAM_TRIGGER_REASON_LOW_RSSI:
2956 	case ROAM_TRIGGER_REASON_PERIODIC:
2957 		/*
2958 		 * Use ptr->current_rssi get the RSSI of current AP after
2959 		 * roam scan is triggered. This avoids discrepancy with the
2960 		 * next rssi threshold value printed in roam scan details.
2961 		 * ptr->rssi_trig_data.threshold gives the rssi threshold
2962 		 * for the Low Rssi/Periodic scan trigger.
2963 		 */
2964 		if (ptr->common_roam)
2965 			buf_cons = qdf_snprint(temp, buf_left,
2966 					       "Cur_Rssi threshold:%d Current AP RSSI: %d",
2967 					       ptr->low_rssi_trig_data.roam_rssi_threshold,
2968 					       ptr->low_rssi_trig_data.current_rssi);
2969 		else
2970 			buf_cons = qdf_snprint(temp, buf_left,
2971 					       "Cur_Rssi threshold:%d Current AP RSSI: %d",
2972 					       ptr->rssi_trig_data.threshold,
2973 					       ptr->current_rssi);
2974 		temp += buf_cons;
2975 		buf_left -= buf_cons;
2976 		break;
2977 	case ROAM_TRIGGER_REASON_WTC_BTM:
2978 		cm_roam_btm_resp_event(ptr, NULL, vdev_id, true);
2979 
2980 		if (ptr->wtc_btm_trig_data.wtc_candi_rssi_ext_present) {
2981 			buf_cons = qdf_snprint(temp, buf_left,
2982 				   "Roaming Mode: %d, Trigger Reason: %d, Sub code:%d, wtc mode:%d, wtc scan mode:%d, wtc rssi th:%d, wtc candi rssi th_2g:%d, wtc_candi_rssi_th_5g:%d, wtc_candi_rssi_th_6g:%d",
2983 				   ptr->wtc_btm_trig_data.roaming_mode,
2984 				   ptr->wtc_btm_trig_data.vsie_trigger_reason,
2985 				   ptr->wtc_btm_trig_data.sub_code,
2986 				   ptr->wtc_btm_trig_data.wtc_mode,
2987 				   ptr->wtc_btm_trig_data.wtc_scan_mode,
2988 				   ptr->wtc_btm_trig_data.wtc_rssi_th,
2989 				   ptr->wtc_btm_trig_data.wtc_candi_rssi_th,
2990 				   ptr->wtc_btm_trig_data.wtc_candi_rssi_th_5g,
2991 				   ptr->wtc_btm_trig_data.wtc_candi_rssi_th_6g);
2992 		} else {
2993 			buf_cons = qdf_snprint(temp, buf_left,
2994 				   "Roaming Mode: %d, Trigger Reason: %d, Sub code:%d, wtc mode:%d, wtc scan mode:%d, wtc rssi th:%d, wtc candi rssi th:%d",
2995 				   ptr->wtc_btm_trig_data.roaming_mode,
2996 				   ptr->wtc_btm_trig_data.vsie_trigger_reason,
2997 				   ptr->wtc_btm_trig_data.sub_code,
2998 				   ptr->wtc_btm_trig_data.wtc_mode,
2999 				   ptr->wtc_btm_trig_data.wtc_scan_mode,
3000 				   ptr->wtc_btm_trig_data.wtc_rssi_th,
3001 				   ptr->wtc_btm_trig_data.wtc_candi_rssi_th);
3002 		}
3003 
3004 		temp += buf_cons;
3005 		buf_left -= buf_cons;
3006 		break;
3007 	default:
3008 		break;
3009 	}
3010 }
3011 
3012 /**
3013  * cm_roam_stats_print_trigger_info  - Roam trigger related details
3014  * @psoc:  Pointer to PSOC object
3015  * @data:  Pointer to the roam trigger data
3016  * @scan_data: Roam scan data pointer
3017  * @vdev_id: Vdev ID
3018  * @is_full_scan: Was a full scan performed
3019  *
3020  * Prints the vdev, roam trigger reason, time of the day at which roaming
3021  * was triggered.
3022  *
3023  * Return: None
3024  */
3025 static void
3026 cm_roam_stats_print_trigger_info(struct wlan_objmgr_psoc *psoc,
3027 				 struct wmi_roam_trigger_info *data,
3028 				 struct wmi_roam_scan_data *scan_data,
3029 				 uint8_t vdev_id, bool is_full_scan)
3030 {
3031 	char *buf;
3032 	char time[TIME_STRING_LEN];
3033 	QDF_STATUS status;
3034 
3035 	buf = qdf_mem_malloc(MAX_ROAM_DEBUG_BUF_SIZE);
3036 	if (!buf)
3037 		return;
3038 
3039 	cm_roam_stats_get_trigger_detail_str(data, buf, is_full_scan, vdev_id);
3040 	mlme_get_converted_timestamp(data->timestamp, time);
3041 
3042 	/* Update roam trigger info to userspace */
3043 	cm_roam_trigger_info_event(data, scan_data, vdev_id, is_full_scan);
3044 
3045 	mlme_nofl_info("%s [ROAM_TRIGGER]: VDEV[%d] %s",
3046 		       time, vdev_id, buf);
3047 	qdf_mem_free(buf);
3048 
3049 	status = wlan_cm_update_roam_states(psoc, vdev_id, data->trigger_reason,
3050 					    ROAM_TRIGGER_REASON);
3051 	if (QDF_IS_STATUS_ERROR(status))
3052 		mlme_err("failed to update rt stats trigger reason");
3053 }
3054 
3055 /**
3056  * cm_roam_stats_print_btm_rsp_info - BTM RSP related details
3057  * @trigger_info:   Roam scan trigger reason
3058  * @data:    Pointer to the btm rsp data
3059  * @vdev_id: vdev id
3060  * @is_wtc: is WTC?
3061  *
3062  * Prints the vdev, btm status, target_bssid and vsie reason
3063  *
3064  * Return: None
3065  */
3066 static void
3067 cm_roam_stats_print_btm_rsp_info(struct wmi_roam_trigger_info *trigger_info,
3068 				 struct roam_btm_response_data *data,
3069 				 uint8_t vdev_id, bool is_wtc)
3070 {
3071 	char time[TIME_STRING_LEN];
3072 
3073 	mlme_get_converted_timestamp(data->timestamp, time);
3074 	mlme_nofl_info("%s [BTM RSP]:VDEV[%d], Status:%d, VSIE reason:%d, BSSID: "
3075 		       QDF_MAC_ADDR_FMT, time, vdev_id, data->btm_status,
3076 		       data->vsie_reason,
3077 		       QDF_MAC_ADDR_REF(data->target_bssid.bytes));
3078 	cm_roam_btm_resp_event(trigger_info, data, vdev_id, is_wtc);
3079 }
3080 
3081 /**
3082  * cm_roam_stats_print_roam_initial_info - Roaming related initial details
3083  * @data:    Pointer to the btm rsp data
3084  * @vdev_id: vdev id
3085  *
3086  * Prints the vdev, roam_full_scan_count, channel and rssi
3087  * utilization threshold and timer
3088  *
3089  * Return: None
3090  */
3091 static void
3092 cm_roam_stats_print_roam_initial_info(struct roam_initial_data *data,
3093 				      uint8_t vdev_id)
3094 {
3095 	mlme_nofl_info("[ROAM INIT INFO]: VDEV[%d], roam_full_scan_count: %d, rssi_th: %d, cu_th: %d, fw_cancel_timer_bitmap: %d",
3096 		       vdev_id, data->roam_full_scan_count, data->rssi_th,
3097 		       data->cu_th, data->fw_cancel_timer_bitmap);
3098 }
3099 
3100 /**
3101  * cm_roam_stats_print_roam_msg_info - Roaming related message details
3102  * @data:    Pointer to the btm rsp data
3103  * @vdev_id: vdev id
3104  *
3105  * Prints the vdev, msg_id, msg_param1, msg_param2 and timer
3106  *
3107  * Return: None
3108  */
3109 static void cm_roam_stats_print_roam_msg_info(struct roam_msg_info *data,
3110 					      uint8_t vdev_id)
3111 {
3112 	char time[TIME_STRING_LEN];
3113 	static const char msg_id1_str[] = "Roam RSSI TH Reset";
3114 
3115 	if (data->msg_id == WMI_ROAM_MSG_RSSI_RECOVERED) {
3116 		mlme_get_converted_timestamp(data->timestamp, time);
3117 		mlme_nofl_info("%s [ROAM MSG INFO]: VDEV[%d] %s, Current rssi: %d dbm, next_rssi_threshold: %d dbm",
3118 			       time, vdev_id, msg_id1_str, data->msg_param1,
3119 			       data->msg_param2);
3120 	}
3121 }
3122 
3123 /**
3124  * cm_stats_log_roam_scan_candidates  - Print roam scan candidate AP info
3125  * @ap:           Pointer to the candidate AP list
3126  * @num_entries:  Number of candidate APs
3127  *
3128  * Print the RSSI, CU load, Cu score, RSSI score, total score, BSSID
3129  * and time stamp at which the candidate was found details.
3130  *
3131  * Return: None
3132  */
3133 static void
3134 cm_stats_log_roam_scan_candidates(struct wmi_roam_candidate_info *ap,
3135 				  uint8_t num_entries)
3136 {
3137 	uint16_t i;
3138 	char time[TIME_STRING_LEN], time2[TIME_STRING_LEN];
3139 
3140 
3141 	mlme_nofl_info("%62s%62s", LINE_STR, LINE_STR);
3142 	mlme_nofl_info("%13s %16s %8s %4s %4s %5s/%3s %3s/%3s %7s %7s %6s %12s %20s",
3143 		       "AP BSSID", "TSTAMP", "CH", "TY", "ETP", "RSSI",
3144 		       "SCR", "CU%", "SCR", "TOT_SCR", "BL_RSN", "BL_SRC",
3145 		       "BL_TSTAMP", "BL_TIMEOUT(ms)");
3146 	mlme_nofl_info("%62s%62s", LINE_STR, LINE_STR);
3147 
3148 	if (num_entries > MAX_ROAM_CANDIDATE_AP)
3149 		num_entries = MAX_ROAM_CANDIDATE_AP;
3150 
3151 	for (i = 0; i < num_entries; i++) {
3152 		mlme_get_converted_timestamp(ap->timestamp, time);
3153 		mlme_get_converted_timestamp(ap->dl_timestamp, time2);
3154 		mlme_nofl_info(QDF_MAC_ADDR_FMT " %17s %4d %-4s %4d %3d/%-4d %2d/%-4d %5d %7d %7d %17s %9d",
3155 			       QDF_MAC_ADDR_REF(ap->bssid.bytes), time,
3156 			  ap->freq,
3157 			  ((ap->type == 0) ? "C_AP" :
3158 			  ((ap->type == 2) ? "R_AP" : "P_AP")),
3159 			  ap->etp, ap->rssi, ap->rssi_score, ap->cu_load,
3160 			  ap->cu_score, ap->total_score, ap->dl_reason,
3161 			  ap->dl_source, time2, ap->dl_original_timeout);
3162 		/* Update roam candidates info to userspace */
3163 		cm_roam_candidate_info_event(ap, i);
3164 		ap++;
3165 	}
3166 }
3167 
3168 /**
3169  * cm_get_roam_scan_type_str() - Get the string for roam scan type
3170  * @roam_scan_type: roam scan type coming from fw via
3171  * wmi_roam_scan_info tlv
3172  *
3173  *  Return: Meaningful string for roam scan type
3174  */
3175 static char *cm_get_roam_scan_type_str(uint32_t roam_scan_type)
3176 {
3177 	switch (roam_scan_type) {
3178 	case ROAM_STATS_SCAN_TYPE_PARTIAL:
3179 		return "PARTIAL";
3180 	case ROAM_STATS_SCAN_TYPE_FULL:
3181 		return "FULL";
3182 	case ROAM_STATS_SCAN_TYPE_NO_SCAN:
3183 		return "NO SCAN";
3184 	case ROAM_STATS_SCAN_TYPE_HIGHER_BAND_5GHZ_6GHZ:
3185 		return "Higher Band: 5 GHz + 6 GHz";
3186 	case ROAM_STATS_SCAN_TYPE_HIGHER_BAND_6GHZ:
3187 		return "Higher Band : 6 GHz";
3188 	default:
3189 		return "UNKNOWN";
3190 	}
3191 }
3192 
3193 /**
3194  * cm_roam_stats_print_scan_info  - Print the roam scan details and candidate AP
3195  * details
3196  * @psoc:      psoc common object
3197  * @scan:      Pointer to the received tlv after sanitization
3198  * @vdev_id:   Vdev ID
3199  * @trigger:   Roam scan trigger reason
3200  * @timestamp: Host timestamp in millisecs
3201  *
3202  * Prinst the roam scan details with time of the day when the scan was
3203  * triggered and roam candidate AP with score details
3204  *
3205  * Return: None
3206  */
3207 static void
3208 cm_roam_stats_print_scan_info(struct wlan_objmgr_psoc *psoc,
3209 			      struct wmi_roam_scan_data *scan, uint8_t vdev_id,
3210 			      uint32_t trigger, uint32_t timestamp)
3211 {
3212 	uint16_t num_ch = scan->num_chan;
3213 	uint16_t buf_cons = 0, buf_left = ROAM_CHANNEL_BUF_SIZE;
3214 	uint8_t i;
3215 	char *buf, *buf1, *tmp;
3216 	char time[TIME_STRING_LEN];
3217 
3218 	/* Update roam scan info to userspace */
3219 	cm_roam_scan_info_event(psoc, scan, vdev_id);
3220 
3221 	buf = qdf_mem_malloc(ROAM_CHANNEL_BUF_SIZE);
3222 	if (!buf)
3223 		return;
3224 
3225 	tmp = buf;
3226 	/* For partial scans, print the channel info */
3227 	if (scan->type == ROAM_STATS_SCAN_TYPE_PARTIAL) {
3228 		buf_cons = qdf_snprint(tmp, buf_left, "{");
3229 		buf_left -= buf_cons;
3230 		tmp += buf_cons;
3231 
3232 		for (i = 0; i < num_ch; i++) {
3233 			buf_cons = qdf_snprint(tmp, buf_left, "%d ",
3234 					       scan->chan_freq[i]);
3235 			buf_left -= buf_cons;
3236 			tmp += buf_cons;
3237 		}
3238 		buf_cons = qdf_snprint(tmp, buf_left, "}");
3239 		buf_left -= buf_cons;
3240 		tmp += buf_cons;
3241 	}
3242 
3243 	buf1 = qdf_mem_malloc(ROAM_FAILURE_BUF_SIZE);
3244 	if (!buf1) {
3245 		qdf_mem_free(buf);
3246 		return;
3247 	}
3248 
3249 	if (trigger == ROAM_TRIGGER_REASON_LOW_RSSI ||
3250 	    trigger == ROAM_TRIGGER_REASON_PERIODIC)
3251 		qdf_snprint(buf1, ROAM_FAILURE_BUF_SIZE,
3252 			    "next_rssi_threshold: %d dBm",
3253 			    scan->next_rssi_threshold);
3254 
3255 	mlme_get_converted_timestamp(timestamp, time);
3256 	mlme_nofl_info("%s [ROAM_SCAN]: VDEV[%d] Scan_type: %s %s %s",
3257 		       time, vdev_id, cm_get_roam_scan_type_str(scan->type),
3258 		       buf1, buf);
3259 	cm_stats_log_roam_scan_candidates(scan->ap, scan->num_ap);
3260 
3261 	qdf_mem_free(buf);
3262 	qdf_mem_free(buf1);
3263 }
3264 
3265 /**
3266  * cm_roam_stats_print_roam_result()  - Print roam result related info
3267  * @psoc: Pointer to psoc object
3268  * @trigger: roam trigger information
3269  * @res:     Roam result structure pointer
3270  * @scan_data: scan data
3271  * @vdev_id: vdev id
3272  *
3273  * Print roam result and failure reason if roaming failed.
3274  *
3275  * Return: None
3276  */
3277 static void
3278 cm_roam_stats_print_roam_result(struct wlan_objmgr_psoc *psoc,
3279 				struct wmi_roam_trigger_info *trigger,
3280 				struct wmi_roam_result *res,
3281 				struct wmi_roam_scan_data *scan_data,
3282 				uint8_t vdev_id)
3283 {
3284 	char *buf;
3285 	char time[TIME_STRING_LEN];
3286 	QDF_STATUS status;
3287 
3288 	/* Update roam result info to userspace */
3289 	cm_roam_result_info_event(psoc, trigger, res, scan_data, vdev_id);
3290 
3291 	buf = qdf_mem_malloc(ROAM_FAILURE_BUF_SIZE);
3292 	if (!buf)
3293 		return;
3294 
3295 	if (res->status == 1)
3296 		qdf_snprint(buf, ROAM_FAILURE_BUF_SIZE, "Reason: %s",
3297 			    mlme_get_roam_fail_reason_str(res->fail_reason));
3298 
3299 	mlme_get_converted_timestamp(res->timestamp, time);
3300 
3301 	if (res->fail_reason == ROAM_FAIL_REASON_CURR_AP_STILL_OK)
3302 		mlme_nofl_info("%s [ROAM_RESULT]: VDEV[%d] %s",
3303 			       time, vdev_id, buf);
3304 	else
3305 		mlme_nofl_info("%s [ROAM_RESULT]: VDEV[%d] %s %s",
3306 			       time, vdev_id,
3307 			       mlme_get_roam_status_str(res->status), buf);
3308 	qdf_mem_free(buf);
3309 
3310 	status = wlan_cm_update_roam_states(psoc, vdev_id, res->fail_reason,
3311 					    ROAM_FAIL_REASON);
3312 	if (QDF_IS_STATUS_ERROR(status))
3313 		mlme_err("failed to update rt stats roam fail reason");
3314 }
3315 
3316 #define WLAN_ROAM_11KV_REQ_TYPE_BTM        1
3317 #define WLAN_ROAM_11KV_REQ_TYPE_NEIGH_RPT  2
3318 
3319 /**
3320  * cm_roam_stats_print_11kv_info  - Print neighbor report/BTM related data
3321  * @psoc: Pointer to psoc object
3322  * @neigh_rpt: Pointer to the extracted TLV structure
3323  * @vdev_id:   Vdev ID
3324  *
3325  * Print BTM/neighbor report info that is sent by firmware after
3326  * connection/roaming to an AP.
3327  *
3328  * Return: none
3329  */
3330 static void
3331 cm_roam_stats_print_11kv_info(struct wlan_objmgr_psoc *psoc,
3332 			      struct wmi_neighbor_report_data *neigh_rpt,
3333 			      uint8_t vdev_id)
3334 {
3335 	char time[TIME_STRING_LEN], time1[TIME_STRING_LEN];
3336 	char *buf, *tmp;
3337 	uint8_t type = neigh_rpt->req_type, i;
3338 	uint16_t buf_left = ROAM_CHANNEL_BUF_SIZE, buf_cons;
3339 	uint8_t num_ch = neigh_rpt->num_freq;
3340 	struct wlan_objmgr_vdev *vdev;
3341 
3342 	if (!type)
3343 		return;
3344 
3345 	buf = qdf_mem_malloc(ROAM_CHANNEL_BUF_SIZE);
3346 	if (!buf)
3347 		return;
3348 
3349 	tmp = buf;
3350 	if (num_ch) {
3351 		buf_cons = qdf_snprint(tmp, buf_left, "{ ");
3352 		buf_left -= buf_cons;
3353 		tmp += buf_cons;
3354 
3355 		for (i = 0; i < num_ch; i++) {
3356 			buf_cons = qdf_snprint(tmp, buf_left, "%d ",
3357 					       neigh_rpt->freq[i]);
3358 			buf_left -= buf_cons;
3359 			tmp += buf_cons;
3360 		}
3361 
3362 		buf_cons = qdf_snprint(tmp, buf_left, "}");
3363 		buf_left -= buf_cons;
3364 		tmp += buf_cons;
3365 	}
3366 
3367 	mlme_get_converted_timestamp(neigh_rpt->req_time, time);
3368 	mlme_nofl_info("%s [%s] VDEV[%d]", time,
3369 		       (type == WLAN_ROAM_11KV_REQ_TYPE_BTM) ?
3370 		       "BTM_QUERY" : "NEIGH_RPT_REQ", vdev_id);
3371 
3372 	if (type == WLAN_ROAM_11KV_REQ_TYPE_BTM)
3373 		cm_roam_btm_query_event(neigh_rpt, vdev_id);
3374 	else if (type == WLAN_ROAM_11KV_REQ_TYPE_NEIGH_RPT) {
3375 		vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
3376 							WLAN_MLME_OBJMGR_ID);
3377 		if (!vdev) {
3378 			mlme_err("vdev pointer not found");
3379 			goto out;
3380 		}
3381 
3382 		cm_roam_neigh_rpt_req_event(neigh_rpt, vdev);
3383 
3384 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
3385 	}
3386 
3387 	if (neigh_rpt->resp_time) {
3388 		mlme_get_converted_timestamp(neigh_rpt->resp_time, time1);
3389 		mlme_nofl_info("%s [%s] VDEV[%d] %s", time1,
3390 			       (type == WLAN_ROAM_11KV_REQ_TYPE_BTM) ?
3391 			       "BTM_REQ" : "NEIGH_RPT_RSP",
3392 			       vdev_id,
3393 			       (num_ch > 0) ? buf : "NO Ch update");
3394 
3395 		if (type == WLAN_ROAM_11KV_REQ_TYPE_NEIGH_RPT)
3396 			cm_roam_neigh_rpt_resp_event(neigh_rpt, vdev_id);
3397 
3398 	} else {
3399 		mlme_nofl_info("%s No response received from AP",
3400 			       (type == WLAN_ROAM_11KV_REQ_TYPE_BTM) ?
3401 			       "BTM" : "NEIGH_RPT");
3402 	}
3403 out:
3404 	qdf_mem_free(buf);
3405 }
3406 
3407 static char *
3408 cm_get_frame_subtype_str(enum mgmt_subtype frame_subtype)
3409 {
3410 	switch (frame_subtype) {
3411 	case MGMT_SUBTYPE_ASSOC_REQ:
3412 		return "ASSOC";
3413 	case MGMT_SUBTYPE_ASSOC_RESP:
3414 		return "ASSOC";
3415 	case MGMT_SUBTYPE_REASSOC_REQ:
3416 		return "REASSOC";
3417 	case MGMT_SUBTYPE_REASSOC_RESP:
3418 		return "REASSOC";
3419 	case MGMT_SUBTYPE_DISASSOC:
3420 		return "DISASSOC";
3421 	case MGMT_SUBTYPE_AUTH:
3422 		return "AUTH";
3423 	case MGMT_SUBTYPE_DEAUTH:
3424 		return "DEAUTH";
3425 	default:
3426 		break;
3427 	}
3428 
3429 	return "Invalid frm";
3430 }
3431 
3432 #define WLAN_SAE_AUTH_ALGO 3
3433 static void
3434 cm_roam_print_frame_info(struct wlan_objmgr_psoc *psoc,
3435 			 struct wlan_objmgr_vdev *vdev,
3436 			 struct roam_frame_stats *frame_data,
3437 			 struct wmi_roam_scan_data *scan_data,
3438 			 struct wmi_roam_result *result)
3439 {
3440 	struct roam_frame_info *frame_info;
3441 	char time[TIME_STRING_LEN];
3442 	uint8_t i, vdev_id, cached_vdev_id;
3443 
3444 	if (!frame_data->num_frame)
3445 		return;
3446 
3447 	vdev_id = wlan_vdev_get_id(vdev);
3448 
3449 	for (i = 0; i < frame_data->num_frame; i++) {
3450 		cached_vdev_id = vdev_id;
3451 		frame_info = &frame_data->frame_info[i];
3452 		/*
3453 		 * For SAE auth frame, since host sends the authentication
3454 		 * frames, its cached in the TX/RX path and the cached
3455 		 * frames are printed from here.
3456 		 */
3457 		if (frame_info->auth_algo == WLAN_SAE_AUTH_ALGO &&
3458 		    wlan_is_sae_auth_log_present_for_bssid(psoc,
3459 							   &frame_info->bssid,
3460 							   &cached_vdev_id)) {
3461 			wlan_print_cached_sae_auth_logs(psoc,
3462 							&frame_info->bssid,
3463 							cached_vdev_id);
3464 			continue;
3465 		}
3466 
3467 		qdf_mem_zero(time, TIME_STRING_LEN);
3468 		mlme_get_converted_timestamp(frame_info->timestamp, time);
3469 
3470 		/* Log the auth & reassoc frames here to driver log */
3471 		if (frame_info->type != ROAM_FRAME_INFO_FRAME_TYPE_EXT)
3472 			mlme_nofl_info("%s [%s%s] VDEV[%d] bssid: " QDF_MAC_ADDR_FMT " status:%d seq_num:%d",
3473 				       time,
3474 				       cm_get_frame_subtype_str(frame_info->subtype),
3475 				       frame_info->subtype ==  MGMT_SUBTYPE_AUTH ?
3476 				       (frame_info->is_rsp ? " RX" : " TX") : "",
3477 				       vdev_id,
3478 				       QDF_MAC_ADDR_REF(frame_info->bssid.bytes),
3479 				       frame_info->status_code,
3480 				       frame_info->seq_num);
3481 
3482 		cm_roam_mgmt_frame_event(vdev, frame_info, scan_data, result);
3483 	}
3484 }
3485 
3486 void cm_report_roam_rt_stats(struct wlan_objmgr_psoc *psoc,
3487 			     uint8_t vdev_id,
3488 			     enum roam_rt_stats_type events,
3489 			     struct roam_stats_event *roam_info,
3490 			     uint32_t value, uint8_t idx, uint32_t reason)
3491 {
3492 	struct roam_stats_event *roam_event = NULL;
3493 
3494 	if (!wlan_cm_get_roam_rt_stats(psoc, ROAM_RT_STATS_ENABLE)) {
3495 		mlme_debug("Roam events stats is disabled");
3496 		return;
3497 	}
3498 
3499 	switch (events) {
3500 	case ROAM_RT_STATS_TYPE_SCAN_STATE:
3501 		roam_event = qdf_mem_malloc(sizeof(*roam_event));
3502 		if (!roam_event)
3503 			return;
3504 
3505 		if (value == WMI_ROAM_NOTIF_SCAN_START) {
3506 			roam_event->roam_event_param.roam_scan_state =
3507 					QCA_WLAN_VENDOR_ROAM_SCAN_STATE_START;
3508 			if (reason) {
3509 				roam_event->trigger[idx].present = true;
3510 				roam_event->trigger[idx].trigger_reason =
3511 							 reason;
3512 			}
3513 		} else if (value == WMI_ROAM_NOTIF_SCAN_END) {
3514 			roam_event->roam_event_param.roam_scan_state =
3515 					QCA_WLAN_VENDOR_ROAM_SCAN_STATE_END;
3516 		}
3517 
3518 		mlme_debug("Invoke HDD roam events callback for roam "
3519 			   "scan notif");
3520 		roam_event->vdev_id = vdev_id;
3521 		mlme_cm_osif_roam_rt_stats(roam_event, idx);
3522 		qdf_mem_free(roam_event);
3523 		break;
3524 	case ROAM_RT_STATS_TYPE_INVOKE_FAIL_REASON:
3525 		roam_event = qdf_mem_malloc(sizeof(*roam_event));
3526 		if (!roam_event)
3527 			return;
3528 
3529 		roam_event->roam_event_param.roam_invoke_fail_reason = value;
3530 
3531 		mlme_debug("Invoke HDD roam events callback for roam "
3532 			   "invoke fail");
3533 		roam_event->vdev_id = vdev_id;
3534 		mlme_cm_osif_roam_rt_stats(roam_event, idx);
3535 		qdf_mem_free(roam_event);
3536 		break;
3537 	case ROAM_RT_STATS_TYPE_ROAM_SCAN_INFO:
3538 		if (roam_info->scan[idx].present ||
3539 		    roam_info->trigger[idx].present ||
3540 		    (roam_info->result[idx].present &&
3541 		     roam_info->result[idx].fail_reason)) {
3542 			mlme_debug("Invoke HDD roam events callback for roam "
3543 				   "stats event");
3544 			roam_info->vdev_id = vdev_id;
3545 			mlme_cm_osif_roam_rt_stats(roam_info, idx);
3546 		}
3547 		break;
3548 	default:
3549 		break;
3550 	}
3551 }
3552 
3553 /**
3554  * cm_roam_handle_btm_stats() - Handle BTM related logging roam stats.
3555  * @psoc: psoc pointer
3556  * @stats_info: Pointer to the roam stats
3557  * @i: TLV indev for BTM roam trigger
3558  * @rem_tlv_len: Remaining TLV length
3559  *
3560  * Return: None
3561  */
3562 static void
3563 cm_roam_handle_btm_stats(struct wlan_objmgr_psoc *psoc,
3564 			 struct roam_stats_event *stats_info, uint8_t i,
3565 			 uint8_t *rem_tlv_len)
3566 {
3567 	bool log_btm_frames_only = false;
3568 	struct wlan_objmgr_vdev *vdev;
3569 
3570 	if (stats_info->data_11kv[i].present)
3571 		cm_roam_stats_print_11kv_info(psoc, &stats_info->data_11kv[i],
3572 					      stats_info->vdev_id);
3573 
3574 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
3575 						    stats_info->vdev_id,
3576 						    WLAN_MLME_CM_ID);
3577 	if (!vdev) {
3578 		mlme_err("vdev: %d vdev not found", stats_info->vdev_id);
3579 		return;
3580 	}
3581 
3582 	/*
3583 	 * If roam trigger is BTM and roam scan type is no scan then
3584 	 * the roam stats event is for BTM frames logging.
3585 	 * So log the BTM frames alone and return.
3586 	 */
3587 	if (stats_info->scan[i].present &&
3588 	    stats_info->scan[i].type == ROAM_STATS_SCAN_TYPE_NO_SCAN) {
3589 		cm_roam_btm_req_event(&stats_info->trigger[i].btm_trig_data,
3590 				      &stats_info->trigger[i],
3591 				      stats_info->vdev_id, false);
3592 		log_btm_frames_only = true;
3593 		goto log_btm_frames_only;
3594 	}
3595 
3596 	if (stats_info->trigger[i].present) {
3597 		bool is_full_scan = stats_info->scan[i].present &&
3598 				    stats_info->scan[i].type;
3599 
3600 		/* BTM request diag log event will be sent from inside below */
3601 		cm_roam_stats_print_trigger_info(psoc, &stats_info->trigger[i],
3602 						 &stats_info->scan[i],
3603 						 stats_info->vdev_id,
3604 						 is_full_scan);
3605 
3606 		if (stats_info->scan[i].present)
3607 			cm_roam_stats_print_scan_info(
3608 				psoc, &stats_info->scan[i],
3609 				stats_info->vdev_id,
3610 				stats_info->trigger[i].trigger_reason,
3611 				stats_info->trigger[i].timestamp);
3612 	}
3613 
3614 	if (stats_info->result[i].present)
3615 		cm_roam_stats_print_roam_result(psoc,
3616 						&stats_info->trigger[i],
3617 						&stats_info->result[i],
3618 						&stats_info->scan[i],
3619 						stats_info->vdev_id);
3620 
3621 	if (stats_info->frame_stats[i].num_frame)
3622 		cm_roam_print_frame_info(psoc, vdev,
3623 					 &stats_info->frame_stats[i],
3624 					 &stats_info->scan[i],
3625 					 &stats_info->result[i]);
3626 
3627 log_btm_frames_only:
3628 
3629 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
3630 
3631 	/*
3632 	 * Print BTM resp TLV info (wmi_roam_btm_response_info) only
3633 	 * when trigger reason is BTM or WTC_BTM. As for other roam
3634 	 * triggers this TLV contains zeros, so host should not print.
3635 	 */
3636 	if (stats_info->btm_rsp[i].present && stats_info->trigger[i].present &&
3637 	    (stats_info->trigger[i].trigger_reason == ROAM_TRIGGER_REASON_BTM ||
3638 	     stats_info->trigger[i].trigger_reason ==
3639 						ROAM_TRIGGER_REASON_WTC_BTM))
3640 		cm_roam_stats_print_btm_rsp_info(&stats_info->trigger[i],
3641 						 &stats_info->btm_rsp[i],
3642 						 stats_info->vdev_id, false);
3643 
3644 	if (log_btm_frames_only)
3645 		return;
3646 
3647 	if (stats_info->roam_init_info[i].present)
3648 		cm_roam_stats_print_roam_initial_info(
3649 				&stats_info->roam_init_info[i],
3650 				stats_info->vdev_id);
3651 
3652 	if (stats_info->roam_msg_info && stats_info->roam_msg_info[i].present &&
3653 	    i < stats_info->num_roam_msg_info) {
3654 		*rem_tlv_len = *rem_tlv_len + 1;
3655 		cm_roam_stats_print_roam_msg_info(
3656 						  &stats_info->roam_msg_info[i],
3657 						  stats_info->vdev_id);
3658 	}
3659 
3660 	cm_report_roam_rt_stats(psoc, stats_info->vdev_id,
3661 				ROAM_RT_STATS_TYPE_ROAM_SCAN_INFO,
3662 				stats_info, 0, i, 0);
3663 }
3664 
3665 #ifdef WLAN_FEATURE_ROAM_INFO_STATS
3666 void mlme_cm_free_roam_stats_info(mlme_vdev_ext_t *ext_hdl)
3667 {
3668 	uint32_t roam_cache_num;
3669 
3670 	roam_cache_num = ext_hdl->roam_cache_num;
3671 
3672 	if (roam_cache_num == 0) {
3673 		mlme_debug("enhanced roam disable, no need free memory");
3674 		return;
3675 	}
3676 
3677 	qdf_mutex_destroy(&ext_hdl->roam_rd_wr_lock);
3678 	qdf_mem_free(ext_hdl->roam_info);
3679 	ext_hdl->roam_info = NULL;
3680 }
3681 
3682 void
3683 mlme_cm_alloc_roam_stats_info(struct vdev_mlme_obj *vdev_mlme)
3684 {
3685 	uint32_t cache_num;
3686 	struct wlan_objmgr_psoc *psoc;
3687 	QDF_STATUS status;
3688 
3689 	if (!vdev_mlme->ext_vdev_ptr) {
3690 		mlme_err("vdev legacy private object is NULL");
3691 		return;
3692 	}
3693 
3694 	psoc = wlan_vdev_get_psoc(vdev_mlme->vdev);
3695 	if (!psoc) {
3696 		mlme_err("Invalid PSOC");
3697 		return;
3698 	}
3699 	status = wlan_mlme_get_roam_info_stats_num(psoc, &cache_num);
3700 	if (QDF_IS_STATUS_ERROR(status)) {
3701 		mlme_err("failed to get groam_info_stats_num");
3702 		return;
3703 	}
3704 
3705 	if (cache_num == 0) {
3706 		mlme_err("groam_info_stats_num = 0, not support enhanced roam");
3707 		return;
3708 	}
3709 
3710 	if (vdev_mlme->ext_vdev_ptr->roam_info) {
3711 		mlme_debug("mlme_priv->enhance_roam_info already malloced");
3712 		return;
3713 	}
3714 
3715 	vdev_mlme->ext_vdev_ptr->roam_info =
3716 		qdf_mem_malloc(cache_num * sizeof(struct enhance_roam_info));
3717 	if (!vdev_mlme->ext_vdev_ptr->roam_info)
3718 		return;
3719 
3720 	vdev_mlme->ext_vdev_ptr->roam_cache_num = cache_num;
3721 	vdev_mlme->ext_vdev_ptr->roam_write_index = 0;
3722 	qdf_mutex_create(&vdev_mlme->ext_vdev_ptr->roam_rd_wr_lock);
3723 }
3724 
3725 /**
3726  * wlan_cm_update_roam_trigger_info() - API to update roam trigger info
3727  * @mlme_priv:    Pointer to vdev mlme legacy priv struct
3728  * @data:  Data from target_if wmi event
3729  *
3730  * Get roam trigger info from target_if wmi event and save in vdev mlme ring
3731  * buffer, it is required that the mlme_priv->roam_rd_wr_lock be held before
3732  * this API is called
3733  *
3734  * Return: void
3735  */
3736 static void
3737 wlan_cm_update_roam_trigger_info(struct mlme_legacy_priv *mlme_priv,
3738 				 struct wmi_roam_trigger_info *data)
3739 {
3740 	uint32_t trigger_reason;
3741 	uint32_t index;
3742 	struct enhance_roam_info *info;
3743 
3744 	index = mlme_priv->roam_write_index;
3745 	info = &mlme_priv->roam_info[index];
3746 
3747 	info->trigger.timestamp = data->timestamp;
3748 	info->trigger.trigger_reason = data->trigger_reason;
3749 	trigger_reason = data->trigger_reason;
3750 
3751 	mlme_debug("roam trigger info: timestamp:%llu, reason:%u,index:%u",
3752 		   info->trigger.timestamp,
3753 		   info->trigger.trigger_reason, index);
3754 
3755 	switch (trigger_reason) {
3756 	case ROAM_TRIGGER_REASON_PER:
3757 		info->trigger.condition.roam_per.tx_rate_thresh_percent =
3758 			data->per_trig_data.tx_rate_thresh_percent;
3759 		info->trigger.condition.roam_per.tx_rate_thresh_percent =
3760 			data->per_trig_data.tx_rate_thresh_percent;
3761 		mlme_debug("roam per: rx:%u, tx:%u",
3762 			   data->per_trig_data.rx_rate_thresh_percent,
3763 			   data->per_trig_data.tx_rate_thresh_percent);
3764 		break;
3765 	case ROAM_TRIGGER_REASON_BMISS:
3766 		info->trigger.condition.roam_bmiss.final_bmiss_cnt =
3767 			data->bmiss_trig_data.final_bmiss_cnt;
3768 		info->trigger.condition.roam_bmiss.consecutive_bmiss_cnt =
3769 			data->bmiss_trig_data.consecutive_bmiss_cnt;
3770 		info->trigger.condition.roam_bmiss.qos_null_success =
3771 			data->bmiss_trig_data.qos_null_success;
3772 		mlme_debug("roam bmiss: final:%u, consecutive:%u, qos:%u",
3773 			   data->bmiss_trig_data.final_bmiss_cnt,
3774 			   data->bmiss_trig_data.consecutive_bmiss_cnt,
3775 			   data->bmiss_trig_data.qos_null_success);
3776 		break;
3777 	case ROAM_TRIGGER_REASON_LOW_RSSI:
3778 		info->trigger.condition.roam_poor_rssi.current_rssi =
3779 			data->low_rssi_trig_data.current_rssi;
3780 		info->trigger.condition.roam_poor_rssi.roam_rssi_threshold =
3781 			data->low_rssi_trig_data.roam_rssi_threshold;
3782 		info->trigger.condition.roam_poor_rssi.rx_linkspeed_status =
3783 			data->low_rssi_trig_data.rx_linkspeed_status;
3784 		mlme_debug("roam low rssi: rssi:%d, rssi_th:%d, rx_linkspeed:%u",
3785 			   data->low_rssi_trig_data.current_rssi,
3786 			   data->low_rssi_trig_data.roam_rssi_threshold,
3787 			   data->low_rssi_trig_data.rx_linkspeed_status);
3788 		break;
3789 	case ROAM_TRIGGER_REASON_HIGH_RSSI:
3790 		info->trigger.condition.roam_better_rssi.current_rssi =
3791 			data->hi_rssi_trig_data.current_rssi;
3792 		info->trigger.condition.roam_better_rssi.hi_rssi_threshold =
3793 			data->hi_rssi_trig_data.hirssi_threshold;
3794 		mlme_debug("roam better rssi: cu_rssi:%d, hi_rssi_th:%d",
3795 			   data->hi_rssi_trig_data.current_rssi,
3796 			   data->hi_rssi_trig_data.hirssi_threshold);
3797 		break;
3798 	case ROAM_TRIGGER_REASON_PERIODIC:
3799 		info->trigger.condition.roam_periodic.periodic_timer_ms =
3800 			data->periodic_trig_data.periodic_timer_ms;
3801 		mlme_debug("roam periodic: periodic_timer:%u",
3802 			   data->periodic_trig_data.periodic_timer_ms);
3803 		break;
3804 
3805 	case ROAM_TRIGGER_REASON_DENSE:
3806 		info->trigger.condition.roam_congestion.rx_tput =
3807 			data->congestion_trig_data.rx_tput;
3808 		info->trigger.condition.roam_congestion.tx_tput =
3809 			data->congestion_trig_data.tx_tput;
3810 		info->trigger.condition.roam_congestion.roamable_count =
3811 			data->congestion_trig_data.roamable_count;
3812 		mlme_debug("roam dense: rx_tput:%u, tx_tput:%u, roamable %u",
3813 			   data->congestion_trig_data.rx_tput,
3814 			   data->congestion_trig_data.tx_tput,
3815 			   data->congestion_trig_data.roamable_count);
3816 		break;
3817 	case ROAM_TRIGGER_REASON_BACKGROUND:
3818 		info->trigger.condition.roam_background.current_rssi =
3819 			data->background_trig_data.current_rssi;
3820 		info->trigger.condition.roam_background.data_rssi =
3821 			data->background_trig_data.data_rssi;
3822 		info->trigger.condition.roam_background.data_rssi_threshold =
3823 			data->background_trig_data.data_rssi_threshold;
3824 		mlme_debug("roam background: rssi:%d, datarssi:%d, rssi_th %d",
3825 			   data->background_trig_data.current_rssi,
3826 			   data->background_trig_data.data_rssi,
3827 			   data->background_trig_data.data_rssi_threshold);
3828 		break;
3829 	case ROAM_TRIGGER_REASON_FORCED:
3830 		info->trigger.condition.roam_user_trigger.invoke_reason =
3831 			data->user_trig_data.invoke_reason;
3832 		mlme_debug("roam force: invoke_reason:%u",
3833 			   data->user_trig_data.invoke_reason);
3834 		break;
3835 	case ROAM_TRIGGER_REASON_BTM:
3836 		info->trigger.condition.roam_btm.btm_request_mode =
3837 			data->btm_trig_data.btm_request_mode;
3838 		info->trigger.condition.roam_btm.disassoc_imminent_timer =
3839 			data->btm_trig_data.disassoc_timer;
3840 		info->trigger.condition.roam_btm.validity_internal =
3841 			data->btm_trig_data.validity_interval;
3842 		info->trigger.condition.roam_btm.candidate_list_count =
3843 			data->btm_trig_data.candidate_list_count;
3844 		info->trigger.condition.roam_btm.btm_response_status_code =
3845 			data->btm_trig_data.btm_resp_status;
3846 		info->trigger.condition.roam_btm.btm_bss_termination_timeout =
3847 			data->btm_trig_data.btm_bss_termination_timeout;
3848 		info->trigger.condition.roam_btm.btm_mbo_assoc_retry_timeout =
3849 			data->btm_trig_data.btm_mbo_assoc_retry_timeout;
3850 		info->trigger.condition.roam_btm.btm_req_dialog_token =
3851 			(uint8_t)data->btm_trig_data.token;
3852 		mlme_debug("roam btm: %u %u %u %u %u %u %u %u",
3853 			   data->btm_trig_data.btm_request_mode,
3854 			   data->btm_trig_data.disassoc_timer,
3855 			   data->btm_trig_data.validity_interval,
3856 			   data->btm_trig_data.candidate_list_count,
3857 			   data->btm_trig_data.btm_resp_status,
3858 			   data->btm_trig_data.btm_bss_termination_timeout,
3859 			   data->btm_trig_data.btm_mbo_assoc_retry_timeout,
3860 			   data->btm_trig_data.token);
3861 		break;
3862 	case ROAM_TRIGGER_REASON_BSS_LOAD:
3863 		info->trigger.condition.roam_bss_load.cu_load =
3864 			(uint8_t)data->cu_trig_data.cu_load;
3865 		mlme_debug("roam bss_load: cu_load:%u",
3866 			   data->cu_trig_data.cu_load);
3867 		break;
3868 	case ROAM_TRIGGER_REASON_DEAUTH:
3869 		info->trigger.condition.roam_disconnection.deauth_type =
3870 			(uint8_t)data->deauth_trig_data.type;
3871 		info->trigger.condition.roam_disconnection.deauth_reason =
3872 			(uint16_t)data->deauth_trig_data.reason;
3873 		mlme_debug("roam disconnection: type:%u reason:%u",
3874 			   data->deauth_trig_data.type,
3875 			   data->deauth_trig_data.reason);
3876 		break;
3877 	case ROAM_TRIGGER_REASON_STA_KICKOUT:
3878 		info->trigger.condition.roam_tx_failures.kickout_threshold =
3879 			data->tx_failures_trig_data.kickout_threshold;
3880 		info->trigger.condition.roam_tx_failures.kickout_reason =
3881 			data->tx_failures_trig_data.kickout_reason;
3882 		mlme_debug("roam tx_failures: kickout_th:%u kickout_reason:%u",
3883 			   data->tx_failures_trig_data.kickout_threshold,
3884 			   data->tx_failures_trig_data.kickout_reason);
3885 		break;
3886 	case ROAM_TRIGGER_REASON_IDLE:
3887 	case ROAM_TRIGGER_REASON_UNIT_TEST:
3888 	case ROAM_TRIGGER_REASON_MAWC:
3889 	default:
3890 		break;
3891 	}
3892 
3893 	info->trigger.roam_scan_type = data->scan_type;
3894 	info->trigger.roam_status = data->roam_status;
3895 	mlme_debug("roam trigger info: scan_type:%u,status:%u",
3896 		   data->scan_type, data->roam_status);
3897 
3898 	if (info->trigger.roam_status) {
3899 		info->trigger.roam_fail_reason = data->fail_reason;
3900 
3901 		if (data->abort_reason.abort_reason_code) {
3902 			info->trigger.abort.abort_reason_code =
3903 				data->abort_reason.abort_reason_code;
3904 			info->trigger.abort.data_rssi =
3905 				data->abort_reason.data_rssi;
3906 			info->trigger.abort.data_rssi_threshold =
3907 				data->abort_reason.data_rssi_threshold;
3908 			info->trigger.abort.rx_linkspeed_status =
3909 				data->abort_reason.rx_linkspeed_status;
3910 		}
3911 
3912 		mlme_debug("abort:reason:%u,rssi:%d,rssit:%d,status:%u,fail:%u",
3913 			   info->trigger.abort.abort_reason_code,
3914 			   info->trigger.abort.data_rssi,
3915 			   info->trigger.abort.data_rssi_threshold,
3916 			   info->trigger.abort.rx_linkspeed_status,
3917 			   info->trigger.roam_fail_reason);
3918 	}
3919 }
3920 
3921 static uint32_t
3922 wlan_cm_get_roam_chn_dwell_time(struct wlan_objmgr_vdev *vdev,
3923 				uint16_t freq,
3924 				enum roam_scan_dwell_type dwell_type)
3925 {
3926 	struct wlan_scan_obj *scan_obj;
3927 
3928 	scan_obj = wlan_vdev_get_scan_obj(vdev);
3929 	if (!scan_obj) {
3930 		mlme_err("scan_obj is NULL");
3931 		return 0;
3932 	}
3933 
3934 	if (WLAN_REG_IS_24GHZ_CH_FREQ(freq)) {
3935 		return scan_obj->scan_def.active_dwell_2g;
3936 	} else if (WLAN_REG_IS_5GHZ_CH_FREQ(freq)) {
3937 		if (dwell_type == WLAN_ROAM_DWELL_PASSIVE_TYPE)
3938 			return scan_obj->scan_def.passive_dwell;
3939 		else
3940 			return scan_obj->scan_def.active_dwell;
3941 	} else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(freq)) {
3942 		if (dwell_type == WLAN_ROAM_DWELL_PASSIVE_TYPE)
3943 			return scan_obj->scan_def.passive_dwell_6g;
3944 		else
3945 			return scan_obj->scan_def.active_dwell_6g;
3946 	}
3947 
3948 	return 0;
3949 }
3950 
3951 /**
3952  * wlan_cm_update_roam_scan_info() - API to update roam scan info
3953  * @vdev:    Pointer to vdev
3954  * @scan:  Scan data from target_if wmi event
3955  *
3956  * Get roam scan info from target_if wmi event and save in vdev mlme ring
3957  * buffer, it is required that the mlme_priv->roam_rd_wr_lock be held before
3958  * this API is called
3959  *
3960  * Return: void
3961  */
3962 static void
3963 wlan_cm_update_roam_scan_info(struct wlan_objmgr_vdev *vdev,
3964 			      struct wmi_roam_scan_data *scan)
3965 {
3966 	struct mlme_legacy_priv *mlme_priv;
3967 	struct enhance_roam_info *info;
3968 	uint32_t freq;
3969 	uint32_t dwell_type;
3970 	uint32_t i, index;
3971 
3972 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
3973 	if (!mlme_priv) {
3974 		mlme_err("vdev legacy private object is NULL");
3975 		return;
3976 	}
3977 
3978 	index = mlme_priv->roam_write_index;
3979 	info = &mlme_priv->roam_info[index];
3980 	info->scan.num_channels = scan->num_chan;
3981 
3982 	if (scan->num_chan) {
3983 		for (i = 0; i < scan->num_chan; i++) {
3984 			info->scan.roam_chn[i].chan_freq =
3985 				scan->chan_freq[i];
3986 			info->scan.roam_chn[i].dwell_type =
3987 				scan->dwell_type[i];
3988 
3989 			freq = scan->chan_freq[i];
3990 			dwell_type = scan->dwell_type[i];
3991 			info->scan.roam_chn[i].max_dwell_time =
3992 				wlan_cm_get_roam_chn_dwell_time(vdev, freq,
3993 								dwell_type);
3994 
3995 			mlme_debug("freq %u dwell_type %u dwell_time:%u",
3996 				   freq, dwell_type,
3997 				   info->scan.roam_chn[i].max_dwell_time);
3998 		}
3999 
4000 		info->scan.total_scan_time =
4001 			scan->scan_complete_timestamp -
4002 			info->trigger.timestamp;
4003 
4004 		mlme_debug("roam scan:chn_num:%u,com:%u,total_time:%u,index:%u",
4005 			   info->scan.num_channels,
4006 			   scan->scan_complete_timestamp,
4007 			   info->scan.total_scan_time, index);
4008 	}
4009 }
4010 
4011 /**
4012  * wlan_cm_roam_frame_subtype() - Convert roam host enum
4013  * @frame: Roam frame info
4014  * @frame_type: roam frame type
4015  *
4016  * Return: Roam frame type defined in host driver
4017  */
4018 static enum eroam_frame_subtype
4019 wlan_cm_roam_frame_subtype(struct roam_frame_info *frame, uint8_t frame_type)
4020 {
4021 	switch (frame_type) {
4022 	case MGMT_SUBTYPE_AUTH:
4023 		if (frame->is_rsp)
4024 			return WLAN_ROAM_STATS_FRAME_SUBTYPE_AUTH_RESP;
4025 		else
4026 			return WLAN_ROAM_STATS_FRAME_SUBTYPE_AUTH_REQ;
4027 	case MGMT_SUBTYPE_REASSOC_REQ:
4028 		return WLAN_ROAM_STATS_FRAME_SUBTYPE_REASSOC_REQ;
4029 	case MGMT_SUBTYPE_REASSOC_RESP:
4030 		return WLAN_ROAM_STATS_FRAME_SUBTYPE_REASSOC_RESP;
4031 	case ROAM_FRAME_SUBTYPE_M1:
4032 		return WLAN_ROAM_STATS_FRAME_SUBTYPE_EAPOL_M1;
4033 	case ROAM_FRAME_SUBTYPE_M2:
4034 		return WLAN_ROAM_STATS_FRAME_SUBTYPE_EAPOL_M2;
4035 	case ROAM_FRAME_SUBTYPE_M3:
4036 		return WLAN_ROAM_STATS_FRAME_SUBTYPE_EAPOL_M3;
4037 	case ROAM_FRAME_SUBTYPE_M4:
4038 		return WLAN_ROAM_STATS_FRAME_SUBTYPE_EAPOL_M4;
4039 	case ROAM_FRAME_SUBTYPE_GTK_M1:
4040 		return WLAN_ROAM_STATS_FRAME_SUBTYPE_EAPOL_GTK_M1;
4041 	case ROAM_FRAME_SUBTYPE_GTK_M2:
4042 		return WLAN_ROAM_STATS_FRAME_SUBTYPE_EAPOL_GTK_M2;
4043 	default:
4044 		return WLAN_ROAM_STATS_FRAME_SUBTYPE_AUTH_REQ;
4045 	}
4046 }
4047 
4048 static bool
4049 wlan_cm_get_valid_frame_type(struct roam_frame_info *frame)
4050 {
4051 	if (frame->subtype == MGMT_SUBTYPE_AUTH ||
4052 	    frame->subtype == MGMT_SUBTYPE_REASSOC_REQ ||
4053 	    frame->subtype == MGMT_SUBTYPE_REASSOC_RESP ||
4054 	    frame->subtype == ROAM_FRAME_SUBTYPE_M1 ||
4055 	    frame->subtype == ROAM_FRAME_SUBTYPE_M2 ||
4056 	    frame->subtype == ROAM_FRAME_SUBTYPE_M3 ||
4057 	    frame->subtype == ROAM_FRAME_SUBTYPE_M4)
4058 		return true;
4059 	else
4060 		return false;
4061 }
4062 
4063 /**
4064  * wlan_cm_update_roam_frame_info() - API to update roam frame info
4065  * @mlme_priv: Pointer to Pointer to vdev mlme legacy priv struct
4066  * @frame_data: Frame data from target_if wmi event
4067  *
4068  * Get roam frame info from target_if wmi event and save in vdev mlme ring
4069  * buffer, it is required that the mlme_priv->roam_rd_wr_lock be held before
4070  * this API is called
4071  *
4072  * Return: void
4073  */
4074 static void
4075 wlan_cm_update_roam_frame_info(struct mlme_legacy_priv *mlme_priv,
4076 			       struct roam_frame_stats *frame_data)
4077 {
4078 	struct enhance_roam_info *info;
4079 	uint32_t index, i, j = 0;
4080 	uint8_t subtype;
4081 
4082 	index = mlme_priv->roam_write_index;
4083 	info = &mlme_priv->roam_info[index];
4084 
4085 	for (i = 0; i < frame_data->num_frame; i++) {
4086 		if (!wlan_cm_get_valid_frame_type(&frame_data->frame_info[i]))
4087 			continue;
4088 		j++;
4089 		if (j >= WLAN_ROAM_MAX_FRAME_INFO)
4090 			break;
4091 		/*
4092 		 * fill frame preauth req/rsp, reassoc req/rsp
4093 		 * and EAPOL-M1/M2/M3/M4 into roam buffer
4094 		 */
4095 		subtype = frame_data->frame_info[i].subtype;
4096 		info->timestamp[j].frame_type =
4097 			wlan_cm_roam_frame_subtype(&frame_data->frame_info[i],
4098 						   subtype);
4099 		info->timestamp[j].timestamp =
4100 			frame_data->frame_info[i].timestamp;
4101 		info->timestamp[j].status =
4102 			frame_data->frame_info[i].status_code;
4103 
4104 		qdf_mem_copy(info->timestamp[j].bssid.bytes,
4105 			     frame_data->frame_info[i].bssid.bytes,
4106 			     QDF_MAC_ADDR_SIZE);
4107 
4108 		mlme_debug("frame:idx:%u subtype:%x time:%llu status:%u AP BSSID" QDF_MAC_ADDR_FMT,
4109 			   j, info->timestamp[j].frame_type,
4110 			   info->timestamp[j].timestamp,
4111 			   info->timestamp[j].status,
4112 			   QDF_MAC_ADDR_REF(info->timestamp[j].bssid.bytes));
4113 	}
4114 }
4115 
4116 /**
4117  * wlan_cm_clear_current_roam_stats_info() - API to clear roam stats buffer date
4118  * @mlme_priv: Pointer to Pointer to vdev mlme legacy priv struct
4119  *
4120  * clear the roam stats buffer data before write
4121  *
4122  * Return: void
4123  */
4124 static void
4125 wlan_cm_clear_current_roam_stats_info(struct mlme_legacy_priv *mlme_priv)
4126 {
4127 	uint32_t index;
4128 
4129 	index = mlme_priv->roam_write_index;
4130 	qdf_mem_set(&mlme_priv->roam_info[index],
4131 		    sizeof(struct enhance_roam_info), 0);
4132 }
4133 
4134 /**
4135  * wlan_cm_update_roam_bssid() - API to get roam stats AP BSSID
4136  * @mlme_priv: Pointer to Pointer to vdev mlme legacy priv struct
4137  * @scan: Scan data from target_if wmi event
4138  *
4139  * get AP BSSID from roam stats info which keep in scan data.
4140  *
4141  * Return: void
4142  */
4143 static void
4144 wlan_cm_update_roam_bssid(struct mlme_legacy_priv *mlme_priv,
4145 			  struct wmi_roam_scan_data *scan)
4146 {
4147 	struct enhance_roam_info *info;
4148 	int16_t i;
4149 	uint16_t index, scan_ap_idx;
4150 	struct wmi_roam_candidate_info *ap = NULL;
4151 
4152 	if (scan->num_ap == 0)
4153 		return;
4154 
4155 	scan_ap_idx = scan->num_ap - 1;
4156 	ap = &scan->ap[scan_ap_idx];
4157 
4158 	index = mlme_priv->roam_write_index;
4159 	info = &mlme_priv->roam_info[index];
4160 
4161 	/* For roam failed, we may get candidate ap list, and only
4162 	 * fetch the last candidate AP bssid.
4163 	 */
4164 
4165 	for (i = scan_ap_idx; i >= 0; i--) {
4166 		if (ap->type == WLAN_ROAM_SCAN_CURRENT_AP)
4167 			qdf_mem_copy(info->scan.original_bssid.bytes,
4168 				     ap->bssid.bytes,
4169 				     QDF_MAC_ADDR_SIZE);
4170 		else if (ap->type == WLAN_ROAM_SCAN_ROAMED_AP)
4171 			qdf_mem_copy(info->scan.roamed_bssid.bytes,
4172 				     ap->bssid.bytes,
4173 				     QDF_MAC_ADDR_SIZE);
4174 		else
4175 			mlme_debug("unknown type:%u of AP", ap->type);
4176 		ap--;
4177 	}
4178 }
4179 
4180 /**
4181  * wlan_cm_update_roam_stats_info() - API to update roam stats info
4182  * @psoc:    Pointer to psoc
4183  * @stats_info:  Roam stats event
4184  * @index:  TLV index in roam stats event
4185  *
4186  * Get roam stats info from target_if wmi event and save in vdev mlme ring
4187  * buffer.
4188  *
4189  * Return: void
4190  */
4191 static void
4192 wlan_cm_update_roam_stats_info(struct wlan_objmgr_psoc *psoc,
4193 			       struct roam_stats_event *stats_info,
4194 			       uint8_t index)
4195 {
4196 	struct wlan_objmgr_vdev *vdev;
4197 	struct mlme_legacy_priv *mlme_priv;
4198 
4199 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, stats_info->vdev_id,
4200 						    WLAN_MLME_SB_ID);
4201 	if (!vdev) {
4202 		mlme_err("vdev%d: vdev object is NULL", stats_info->vdev_id);
4203 		return;
4204 	}
4205 
4206 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
4207 	if (!mlme_priv) {
4208 		mlme_err("vdev legacy private object is NULL");
4209 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
4210 		return;
4211 	}
4212 
4213 	if (mlme_priv->roam_cache_num == 0) {
4214 		mlme_debug("Enhanced roam stats not supported");
4215 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
4216 		return;
4217 	}
4218 
4219 	if (!mlme_priv->roam_info) {
4220 		mlme_err("enhance_roam_info buffer is NULL");
4221 		return;
4222 	}
4223 
4224 	qdf_mutex_acquire(&mlme_priv->roam_rd_wr_lock);
4225 
4226 	if (stats_info->trigger[index].present) {
4227 		wlan_cm_clear_current_roam_stats_info(mlme_priv);
4228 		wlan_cm_update_roam_trigger_info(mlme_priv,
4229 						 &stats_info->trigger[index]);
4230 		if (stats_info->scan[index].present)
4231 			wlan_cm_update_roam_scan_info(vdev,
4232 						      &stats_info->scan[index]);
4233 		if (stats_info->frame_stats[index].num_frame)
4234 			wlan_cm_update_roam_frame_info(mlme_priv,
4235 						       &stats_info->frame_stats[index]);
4236 		if (stats_info->scan[index].present)
4237 			wlan_cm_update_roam_bssid(mlme_priv,
4238 						  &stats_info->scan[index]);
4239 
4240 		mlme_priv->roam_write_index += 1;
4241 		if (mlme_priv->roam_write_index == mlme_priv->roam_cache_num)
4242 			mlme_priv->roam_write_index = 0;
4243 	}
4244 	qdf_mutex_release(&mlme_priv->roam_rd_wr_lock);
4245 
4246 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
4247 }
4248 
4249 QDF_STATUS
4250 wlan_cm_roam_stats_info_get(struct wlan_objmgr_vdev *vdev,
4251 			    struct enhance_roam_info **roam_info,
4252 			    uint32_t *roam_num)
4253 {
4254 	struct mlme_legacy_priv *mlme_priv;
4255 	uint32_t i, src, dst;
4256 	uint32_t index = 0;
4257 	uint32_t valid_cache_num;
4258 	struct enhance_roam_info *eroam_info;
4259 
4260 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
4261 	if (!mlme_priv) {
4262 		mlme_err("vdev legacy private object is NULL");
4263 		return QDF_STATUS_E_INVAL;
4264 	}
4265 
4266 	if (mlme_priv->roam_cache_num == 0) {
4267 		mlme_debug("Enhanced roam stats not supported");
4268 		return QDF_STATUS_E_NOSUPPORT;
4269 	}
4270 
4271 	qdf_mutex_acquire(&mlme_priv->roam_rd_wr_lock);
4272 
4273 	/* get all roam event info from oldest to
4274 	 * latest by timestamp.
4275 	 */
4276 	valid_cache_num = mlme_priv->roam_cache_num;
4277 	for (i = 0; i < mlme_priv->roam_cache_num; i++) {
4278 		if (mlme_priv->roam_info[i].trigger.timestamp == 0) {
4279 			valid_cache_num--;
4280 			continue;
4281 		}
4282 		if (mlme_priv->roam_info[i].trigger.timestamp <
4283 		    mlme_priv->roam_info[index].trigger.timestamp)
4284 			index = i;
4285 	}
4286 	mlme_debug("valid num: %d, start index:%u", valid_cache_num, index);
4287 
4288 	if (valid_cache_num == 0) {
4289 		mlme_debug("Enhanced roam stats not existed");
4290 		qdf_mutex_release(&mlme_priv->roam_rd_wr_lock);
4291 		return QDF_STATUS_E_INVAL;
4292 	}
4293 
4294 	/* Send all driver cached roam info to user space one time,
4295 	 * and don't flush them, since they will be cover by
4296 	 * new roam event info.
4297 	 */
4298 	eroam_info =
4299 		qdf_mem_malloc(valid_cache_num *
4300 			       sizeof(*eroam_info));
4301 	if (!eroam_info) {
4302 		qdf_mutex_release(&mlme_priv->roam_rd_wr_lock);
4303 		return QDF_STATUS_E_NOMEM;
4304 	}
4305 
4306 	dst = 0;
4307 	src = index;
4308 	while (dst < valid_cache_num) {
4309 		if (mlme_priv->roam_info[src].trigger.timestamp == 0) {
4310 			src++;
4311 		} else {
4312 			eroam_info[dst] = mlme_priv->roam_info[src];
4313 			src++;
4314 			dst++;
4315 		}
4316 		if (src == mlme_priv->roam_cache_num)
4317 			src = 0;
4318 	}
4319 
4320 	*roam_num = valid_cache_num;
4321 	*roam_info = eroam_info;
4322 	qdf_mutex_release(&mlme_priv->roam_rd_wr_lock);
4323 
4324 	return QDF_STATUS_SUCCESS;
4325 }
4326 #else
4327 static void
4328 wlan_cm_update_roam_stats_info(struct wlan_objmgr_psoc *psoc,
4329 			       struct roam_stats_event *stats_info,
4330 			       uint8_t index)
4331 {
4332 }
4333 #endif
4334 
4335 QDF_STATUS
4336 cm_roam_stats_event_handler(struct wlan_objmgr_psoc *psoc,
4337 			    struct roam_stats_event *stats_info)
4338 {
4339 	uint8_t i, rem_tlv = 0;
4340 	bool is_wtc = false;
4341 	QDF_STATUS status = QDF_STATUS_SUCCESS;
4342 	struct wlan_objmgr_vdev *vdev;
4343 
4344 	if (!stats_info)
4345 		return QDF_STATUS_E_FAILURE;
4346 
4347 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, stats_info->vdev_id,
4348 						    WLAN_MLME_CM_ID);
4349 	if (!vdev) {
4350 		status = QDF_STATUS_E_FAILURE;
4351 		goto out;
4352 	}
4353 
4354 	for (i = 0; i < stats_info->num_tlv; i++) {
4355 		if (stats_info->trigger[i].present) {
4356 			bool is_full_scan =
4357 				stats_info->scan[i].present &&
4358 				stats_info->scan[i].type;
4359 
4360 			if (stats_info->trigger[i].trigger_reason ==
4361 			    ROAM_TRIGGER_REASON_BTM) {
4362 				cm_roam_handle_btm_stats(psoc, stats_info, i,
4363 							 &rem_tlv);
4364 				if (!stats_info->trigger[i].common_roam)
4365 					continue;
4366 			}
4367 
4368 			cm_roam_stats_print_trigger_info(
4369 					psoc, &stats_info->trigger[i],
4370 					&stats_info->scan[i],
4371 					stats_info->vdev_id, is_full_scan);
4372 
4373 			if (stats_info->scan[i].present)
4374 				cm_roam_stats_print_scan_info(
4375 					psoc, &stats_info->scan[i],
4376 					stats_info->vdev_id,
4377 					stats_info->trigger[i].trigger_reason,
4378 					stats_info->trigger[i].timestamp);
4379 		}
4380 
4381 		if (stats_info->result[i].present)
4382 			cm_roam_stats_print_roam_result(psoc,
4383 							&stats_info->trigger[i],
4384 							&stats_info->result[i],
4385 							&stats_info->scan[i],
4386 							stats_info->vdev_id);
4387 
4388 		if (stats_info->frame_stats[i].num_frame)
4389 			cm_roam_print_frame_info(psoc,
4390 						 vdev,
4391 						 &stats_info->frame_stats[i],
4392 						 &stats_info->scan[i],
4393 						 &stats_info->result[i]);
4394 
4395 		wlan_cm_update_roam_stats_info(psoc, stats_info, i);
4396 
4397 		/*
4398 		 * Print BTM resp TLV info (wmi_roam_btm_response_info) only
4399 		 * when trigger reason is BTM or WTC_BTM. As for other roam
4400 		 * triggers this TLV contains zeros, so host should not print.
4401 		 */
4402 		if (stats_info->btm_rsp[i].present &&
4403 		    stats_info->trigger[i].present &&
4404 		    (stats_info->trigger[i].trigger_reason ==
4405 		     ROAM_TRIGGER_REASON_BTM ||
4406 		     stats_info->trigger[i].trigger_reason ==
4407 		     ROAM_TRIGGER_REASON_WTC_BTM))
4408 			cm_roam_stats_print_btm_rsp_info(
4409 						&stats_info->trigger[i],
4410 						&stats_info->btm_rsp[i],
4411 						stats_info->vdev_id, false);
4412 
4413 		if (stats_info->roam_init_info[i].present)
4414 			cm_roam_stats_print_roam_initial_info(
4415 						 &stats_info->roam_init_info[i],
4416 						 stats_info->vdev_id);
4417 
4418 		if (stats_info->roam_msg_info &&
4419 		    i < stats_info->num_roam_msg_info &&
4420 		    stats_info->roam_msg_info[i].present) {
4421 			rem_tlv++;
4422 			cm_roam_stats_print_roam_msg_info(
4423 						  &stats_info->roam_msg_info[i],
4424 						  stats_info->vdev_id);
4425 		}
4426 
4427 		cm_report_roam_rt_stats(psoc, stats_info->vdev_id,
4428 					ROAM_RT_STATS_TYPE_ROAM_SCAN_INFO,
4429 					stats_info, 0, i, 0);
4430 	}
4431 
4432 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
4433 
4434 	if (!stats_info->num_tlv) {
4435 		/*
4436 		 * wmi_roam_trigger_reason TLV is sent only for userspace
4437 		 * logging of BTM/WTC frame without roam scans.
4438 		 */
4439 
4440 		if (stats_info->data_11kv[0].present)
4441 			cm_roam_stats_print_11kv_info(psoc,
4442 						      &stats_info->data_11kv[0],
4443 						      stats_info->vdev_id);
4444 
4445 		if (stats_info->trigger[0].present &&
4446 		    (stats_info->trigger[0].trigger_reason ==
4447 		     ROAM_TRIGGER_REASON_BTM ||
4448 		     stats_info->trigger[0].trigger_reason ==
4449 		     ROAM_TRIGGER_REASON_WTC_BTM)) {
4450 			if (stats_info->trigger[0].trigger_reason ==
4451 			    ROAM_TRIGGER_REASON_WTC_BTM)
4452 				is_wtc = true;
4453 
4454 			cm_roam_btm_req_event(&stats_info->trigger[0].btm_trig_data,
4455 					      &stats_info->trigger[0],
4456 					      stats_info->vdev_id, is_wtc);
4457 		}
4458 
4459 		if (stats_info->scan[0].present &&
4460 		    stats_info->trigger[0].present)
4461 			cm_roam_stats_print_scan_info(psoc,
4462 					  &stats_info->scan[0],
4463 					  stats_info->vdev_id,
4464 					  stats_info->trigger[0].trigger_reason,
4465 					  stats_info->trigger[0].timestamp);
4466 
4467 		if (stats_info->btm_rsp[0].present)
4468 			cm_roam_stats_print_btm_rsp_info(
4469 					&stats_info->trigger[0],
4470 					&stats_info->btm_rsp[0],
4471 					stats_info->vdev_id, 0);
4472 
4473 		/*
4474 		 * WTC BTM response with reason code
4475 		 * WTC print should be after the normal BTM
4476 		 * response print
4477 		 */
4478 		if (stats_info->trigger[0].present &&
4479 		    stats_info->trigger[0].trigger_reason ==
4480 		    ROAM_TRIGGER_REASON_WTC_BTM)
4481 			cm_roam_btm_resp_event(&stats_info->trigger[0], NULL,
4482 					       stats_info->vdev_id, true);
4483 	}
4484 
4485 	if (stats_info->roam_msg_info && stats_info->num_roam_msg_info &&
4486 	    stats_info->num_roam_msg_info - rem_tlv) {
4487 		for (i = 0; i < (stats_info->num_roam_msg_info-rem_tlv); i++) {
4488 			if (stats_info->roam_msg_info[rem_tlv + i].present)
4489 				cm_roam_stats_print_roam_msg_info(
4490 					&stats_info->roam_msg_info[rem_tlv + i],
4491 					stats_info->vdev_id);
4492 		}
4493 	}
4494 
4495 out:
4496 	wlan_clear_sae_auth_logs_cache(psoc, stats_info->vdev_id);
4497 	qdf_mem_free(stats_info->roam_msg_info);
4498 	qdf_mem_free(stats_info);
4499 
4500 	return status;
4501 }
4502 
4503 bool wlan_cm_is_roam_sync_in_progress(struct wlan_objmgr_psoc *psoc,
4504 				      uint8_t vdev_id)
4505 {
4506 	struct wlan_objmgr_vdev *vdev;
4507 	bool ret;
4508 	enum QDF_OPMODE opmode;
4509 
4510 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
4511 						    WLAN_MLME_CM_ID);
4512 
4513 	if (!vdev)
4514 		return false;
4515 
4516 	opmode = wlan_vdev_mlme_get_opmode(vdev);
4517 
4518 	if (opmode != QDF_STA_MODE) {
4519 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
4520 		return false;
4521 	}
4522 
4523 	ret = cm_is_vdev_roam_sync_inprogress(vdev);
4524 
4525 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
4526 
4527 	return ret;
4528 }
4529 
4530 void
4531 wlan_cm_set_roam_offload_bssid(struct wlan_objmgr_vdev *vdev,
4532 			       struct qdf_mac_addr *bssid)
4533 {
4534 	struct mlme_legacy_priv *mlme_priv;
4535 	struct qdf_mac_addr *mlme_bssid;
4536 
4537 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
4538 	if (!mlme_priv) {
4539 		mlme_err("vdev legacy private object is NULL");
4540 		return;
4541 	}
4542 
4543 	mlme_bssid = &(mlme_priv->cm_roam.sae_offload.bssid);
4544 
4545 	if (!bssid || qdf_is_macaddr_zero(bssid)) {
4546 		mlme_err("NULL BSSID");
4547 		return;
4548 	}
4549 	qdf_mem_copy(mlme_bssid->bytes, bssid->bytes, QDF_MAC_ADDR_SIZE);
4550 }
4551 
4552 void
4553 wlan_cm_get_roam_offload_bssid(struct wlan_objmgr_vdev *vdev,
4554 			       struct qdf_mac_addr *bssid)
4555 {
4556 	struct mlme_legacy_priv *mlme_priv;
4557 	struct qdf_mac_addr *mlme_bssid;
4558 
4559 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
4560 	if (!mlme_priv) {
4561 		mlme_err("vdev legacy private object is NULL");
4562 		return;
4563 	}
4564 
4565 	mlme_bssid = &(mlme_priv->cm_roam.sae_offload.bssid);
4566 
4567 	if (!bssid)
4568 		return;
4569 	qdf_mem_copy(bssid->bytes, mlme_bssid->bytes, QDF_MAC_ADDR_SIZE);
4570 }
4571 
4572 void
4573 wlan_cm_set_roam_offload_ssid(struct wlan_objmgr_vdev *vdev,
4574 			      uint8_t *ssid, uint8_t len)
4575 {
4576 	struct mlme_legacy_priv *mlme_priv;
4577 	struct wlan_ssid *mlme_ssid;
4578 
4579 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
4580 	if (!mlme_priv) {
4581 		mlme_err("vdev legacy private object is NULL");
4582 		return;
4583 	}
4584 
4585 	mlme_ssid = &mlme_priv->cm_roam.sae_offload.ssid;
4586 
4587 	if (len > WLAN_SSID_MAX_LEN)
4588 		len = WLAN_SSID_MAX_LEN;
4589 
4590 	qdf_mem_zero(mlme_ssid, sizeof(struct wlan_ssid));
4591 	qdf_mem_copy(&mlme_ssid->ssid[0], ssid, len);
4592 	mlme_ssid->length = len;
4593 
4594 	mlme_debug("Set roam offload ssid: " QDF_SSID_FMT,
4595 		   QDF_SSID_REF(mlme_ssid->length,
4596 				mlme_ssid->ssid));
4597 }
4598 
4599 void
4600 wlan_cm_get_roam_offload_ssid(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
4601 			      uint8_t *ssid, uint8_t *len)
4602 {
4603 	struct wlan_objmgr_vdev *vdev;
4604 	struct mlme_legacy_priv *mlme_priv;
4605 	struct wlan_ssid *mlme_ssid;
4606 
4607 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
4608 						    WLAN_MLME_CM_ID);
4609 	if (!vdev) {
4610 		mlme_err("VDEV is NULL");
4611 		return;
4612 	}
4613 
4614 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
4615 	if (!mlme_priv) {
4616 		mlme_err("vdev legacy private object is NULL");
4617 		goto ret;
4618 	}
4619 
4620 	mlme_ssid = &mlme_priv->cm_roam.sae_offload.ssid;
4621 
4622 	qdf_mem_copy(ssid, mlme_ssid->ssid, mlme_ssid->length);
4623 	*len = mlme_ssid->length;
4624 
4625 ret:
4626 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
4627 }
4628 
4629 void
4630 wlan_cm_roam_set_ho_delay_config(struct wlan_objmgr_psoc *psoc,
4631 				 uint16_t roam_ho_delay)
4632 {
4633 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
4634 
4635 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
4636 	if (!mlme_obj)
4637 		return;
4638 
4639 	mlme_obj->cfg.lfr.roam_ho_delay_config = roam_ho_delay;
4640 }
4641 
4642 uint16_t
4643 wlan_cm_roam_get_ho_delay_config(struct wlan_objmgr_psoc *psoc)
4644 {
4645 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
4646 
4647 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
4648 	if (!mlme_obj) {
4649 		mlme_legacy_err("Failed to get MLME Obj");
4650 		return 0;
4651 	}
4652 
4653 	return mlme_obj->cfg.lfr.roam_ho_delay_config;
4654 }
4655 
4656 void
4657 wlan_cm_set_exclude_rm_partial_scan_freq(struct wlan_objmgr_psoc *psoc,
4658 					 uint8_t exclude_rm_partial_scan_freq)
4659 {
4660 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
4661 
4662 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
4663 	if (!mlme_obj)
4664 		return;
4665 
4666 	mlme_obj->cfg.lfr.exclude_rm_partial_scan_freq =
4667 						exclude_rm_partial_scan_freq;
4668 }
4669 
4670 uint8_t
4671 wlan_cm_get_exclude_rm_partial_scan_freq(struct wlan_objmgr_psoc *psoc)
4672 {
4673 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
4674 
4675 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
4676 	if (!mlme_obj) {
4677 		mlme_legacy_err("Failed to get MLME Obj");
4678 		return 0;
4679 	}
4680 
4681 	return mlme_obj->cfg.lfr.exclude_rm_partial_scan_freq;
4682 }
4683 
4684 void
4685 wlan_cm_roam_set_full_scan_6ghz_on_disc(struct wlan_objmgr_psoc *psoc,
4686 					uint8_t roam_full_scan_6ghz_on_disc)
4687 {
4688 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
4689 
4690 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
4691 	if (!mlme_obj)
4692 		return;
4693 
4694 	mlme_obj->cfg.lfr.roam_full_scan_6ghz_on_disc =
4695 						roam_full_scan_6ghz_on_disc;
4696 }
4697 
4698 uint8_t wlan_cm_roam_get_full_scan_6ghz_on_disc(struct wlan_objmgr_psoc *psoc)
4699 {
4700 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
4701 
4702 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
4703 	if (!mlme_obj) {
4704 		mlme_legacy_err("Failed to get MLME Obj");
4705 		return 0;
4706 	}
4707 
4708 	return mlme_obj->cfg.lfr.roam_full_scan_6ghz_on_disc;
4709 }
4710 
4711 void
4712 wlan_cm_set_roam_scan_high_rssi_offset(struct wlan_objmgr_psoc *psoc,
4713 				       uint8_t roam_high_rssi_delta)
4714 {
4715 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
4716 
4717 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
4718 	if (!mlme_obj)
4719 		return;
4720 
4721 	mlme_obj->cfg.lfr.roam_high_rssi_delta = roam_high_rssi_delta;
4722 }
4723 
4724 uint8_t
4725 wlan_cm_get_roam_scan_high_rssi_offset(struct wlan_objmgr_psoc *psoc)
4726 {
4727 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
4728 
4729 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
4730 	if (!mlme_obj)
4731 		return 0;
4732 
4733 	return mlme_obj->cfg.lfr.roam_high_rssi_delta;
4734 }
4735 
4736 #else
4737 QDF_STATUS
4738 cm_roam_stats_event_handler(struct wlan_objmgr_psoc *psoc,
4739 			    struct roam_stats_event *stats_info)
4740 {
4741 	return QDF_STATUS_SUCCESS;
4742 }
4743 #endif
4744 
4745 #ifdef WLAN_FEATURE_FIPS
4746 QDF_STATUS cm_roam_pmkid_req_ind(struct wlan_objmgr_psoc *psoc,
4747 				 uint8_t vdev_id,
4748 				 struct roam_pmkid_req_event *src_lst)
4749 {
4750 	QDF_STATUS status = QDF_STATUS_SUCCESS;
4751 	struct wlan_objmgr_vdev *vdev;
4752 	struct qdf_mac_addr *dst_list;
4753 	uint32_t num_entries, i;
4754 
4755 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
4756 						    WLAN_MLME_SB_ID);
4757 	if (!vdev) {
4758 		mlme_err("vdev object is NULL");
4759 		return QDF_STATUS_E_NULL_VALUE;
4760 	}
4761 
4762 	num_entries = src_lst->num_entries;
4763 	mlme_debug("Num entries %d", num_entries);
4764 	for (i = 0; i < num_entries; i++) {
4765 		dst_list = &src_lst->ap_bssid[i];
4766 		status = mlme_cm_osif_pmksa_candidate_notify(vdev, dst_list,
4767 							     1, false);
4768 		if (QDF_IS_STATUS_ERROR(status)) {
4769 			mlme_err("Number %d Notify failed for " QDF_MAC_ADDR_FMT,
4770 				 i, QDF_MAC_ADDR_REF(dst_list->bytes));
4771 			goto rel_ref;
4772 		}
4773 	}
4774 
4775 rel_ref:
4776 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
4777 
4778 	return status;
4779 }
4780 #endif /* WLAN_FEATURE_FIPS */
4781 
4782 QDF_STATUS
4783 cm_cleanup_mlo_link(struct wlan_objmgr_vdev *vdev)
4784 {
4785 	QDF_STATUS status;
4786 
4787 	/* Use MLO roam internal disconnect as this is for cleanup and
4788 	 * no need to inform OSIF, and REASON_FW_TRIGGERED_ROAM_FAILURE will
4789 	 * cleanup host without informing the FW
4790 	 */
4791 	status = wlan_cm_disconnect(vdev,
4792 				    CM_MLO_ROAM_INTERNAL_DISCONNECT,
4793 				    REASON_FW_TRIGGERED_ROAM_FAILURE,
4794 				    NULL);
4795 	if (QDF_IS_STATUS_ERROR(status))
4796 		mlme_debug("Failed to post disconnect for link vdev");
4797 
4798 	return status;
4799 }
4800 
4801 bool wlan_is_rso_enabled(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id)
4802 {
4803 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
4804 	enum roam_offload_state cur_state;
4805 
4806 	cur_state = mlme_get_roam_state(psoc, vdev_id);
4807 	if (cur_state == WLAN_ROAM_RSO_ENABLED ||
4808 	    cur_state == WLAN_ROAMING_IN_PROG ||
4809 	    cur_state == WLAN_ROAM_SYNCH_IN_PROG ||
4810 	    cur_state == WLAN_MLO_ROAM_SYNCH_IN_PROG)
4811 		return true;
4812 
4813 	return false;
4814 }
4815 
4816 bool wlan_is_roaming_enabled(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id)
4817 {
4818 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
4819 
4820 	if (mlme_get_roam_state(psoc, vdev_id) == WLAN_ROAM_DEINIT)
4821 		return false;
4822 
4823 	return true;
4824 }
4825 
4826 QDF_STATUS
4827 wlan_cm_set_sae_auth_ta(struct wlan_objmgr_pdev *pdev,
4828 			uint8_t vdev_id,
4829 			struct qdf_mac_addr sae_auth_ta)
4830 {
4831 	struct mlme_legacy_priv *mlme_priv;
4832 	struct wlan_objmgr_vdev *vdev;
4833 
4834 	if (!pdev)
4835 		return QDF_STATUS_E_INVAL;
4836 
4837 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
4838 						    WLAN_MLME_CM_ID);
4839 	if (!vdev)
4840 		return QDF_STATUS_E_INVAL;
4841 
4842 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
4843 	if (!mlme_priv) {
4844 		mlme_legacy_err("vdev legacy private object is NULL");
4845 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
4846 		return QDF_STATUS_E_INVAL;
4847 	}
4848 	qdf_mem_copy(mlme_priv->mlme_roam.sae_auth_ta.bytes, sae_auth_ta.bytes,
4849 		     QDF_MAC_ADDR_SIZE);
4850 	mlme_priv->mlme_roam.sae_auth_pending = true;
4851 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
4852 
4853 	return QDF_STATUS_SUCCESS;
4854 }
4855 
4856 QDF_STATUS
4857 wlan_cm_get_sae_auth_ta(struct wlan_objmgr_pdev *pdev,
4858 			uint8_t vdev_id,
4859 			struct qdf_mac_addr *sae_auth_ta)
4860 {
4861 	struct mlme_legacy_priv *mlme_priv;
4862 	struct wlan_objmgr_vdev *vdev;
4863 
4864 	if (!pdev)
4865 		return QDF_STATUS_E_INVAL;
4866 
4867 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
4868 						    WLAN_MLME_CM_ID);
4869 	if (!vdev)
4870 		return QDF_STATUS_E_INVAL;
4871 
4872 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
4873 	if (!mlme_priv) {
4874 		mlme_legacy_err("vdev legacy private object is NULL");
4875 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
4876 		return QDF_STATUS_E_INVAL;
4877 	}
4878 
4879 	if (mlme_priv->mlme_roam.sae_auth_pending) {
4880 		qdf_mem_copy(sae_auth_ta->bytes,
4881 			     mlme_priv->mlme_roam.sae_auth_ta.bytes,
4882 			     QDF_MAC_ADDR_SIZE);
4883 		mlme_priv->mlme_roam.sae_auth_pending = false;
4884 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
4885 		return QDF_STATUS_SUCCESS;
4886 	}
4887 
4888 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
4889 
4890 	return QDF_STATUS_E_ALREADY;
4891 }
4892 
4893 void
4894 wlan_cm_set_assoc_btm_cap(struct wlan_objmgr_vdev *vdev, bool val)
4895 {
4896 	struct mlme_legacy_priv *mlme_priv;
4897 
4898 	if (!vdev)
4899 		return;
4900 
4901 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
4902 	if (!mlme_priv)
4903 		return;
4904 
4905 	mlme_priv->connect_info.assoc_btm_cap = val;
4906 }
4907 
4908 bool
4909 wlan_cm_get_assoc_btm_cap(struct wlan_objmgr_vdev *vdev)
4910 {
4911 	struct mlme_legacy_priv *mlme_priv;
4912 
4913 	if (!vdev)
4914 		return true;
4915 
4916 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
4917 	if (!mlme_priv)
4918 		return true;
4919 
4920 	return mlme_priv->connect_info.assoc_btm_cap;
4921 }
4922 
4923 bool wlan_cm_is_self_mld_roam_supported(struct wlan_objmgr_psoc *psoc)
4924 {
4925 	struct wmi_unified *wmi_handle;
4926 
4927 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
4928 	if (!wmi_handle) {
4929 		mlme_debug("Invalid WMI handle");
4930 		return false;
4931 	}
4932 
4933 	return wmi_service_enabled(wmi_handle,
4934 				   wmi_service_self_mld_roam_between_dbs_and_hbs);
4935 }
4936 
4937 void
4938 wlan_cm_set_force_20mhz_in_24ghz(struct wlan_objmgr_vdev *vdev,
4939 				 bool is_40mhz_cap)
4940 {
4941 	struct wlan_objmgr_psoc *psoc;
4942 	struct wlan_mlme_psoc_ext_obj *mlme_obj;
4943 	struct mlme_legacy_priv *mlme_priv;
4944 	uint16_t dot11_mode;
4945 	bool send_ie_to_fw = false;
4946 
4947 	if (!vdev)
4948 		return;
4949 
4950 	psoc = wlan_vdev_get_psoc(vdev);
4951 	if (!psoc)
4952 		return;
4953 
4954 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
4955 	if (!mlme_obj || !mlme_obj->cfg.obss_ht40.is_override_ht20_40_24g)
4956 		return;
4957 
4958 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
4959 	if (!mlme_priv)
4960 		return;
4961 
4962 	/*
4963 	 * Force 20 MHz in 2.4 GHz only if "override_ht20_40_24g" ini
4964 	 * is set and userspace connect req doesn't have 40 MHz HT caps
4965 	 */
4966 	if (mlme_priv->connect_info.force_20mhz_in_24ghz != !is_40mhz_cap)
4967 		send_ie_to_fw = true;
4968 
4969 	mlme_priv->connect_info.force_20mhz_in_24ghz = !is_40mhz_cap;
4970 
4971 	if (cm_is_vdev_connected(vdev) && send_ie_to_fw) {
4972 		dot11_mode =
4973 			cm_csr_get_vdev_dot11_mode(wlan_vdev_get_id(vdev));
4974 		cm_send_ies_for_roam_invoke(vdev, dot11_mode);
4975 	}
4976 }
4977 
4978 bool
4979 wlan_cm_get_force_20mhz_in_24ghz(struct wlan_objmgr_vdev *vdev)
4980 {
4981 	struct mlme_legacy_priv *mlme_priv;
4982 
4983 	if (!vdev)
4984 		return true;
4985 
4986 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
4987 	if (!mlme_priv)
4988 		return true;
4989 
4990 	return mlme_priv->connect_info.force_20mhz_in_24ghz;
4991 }
4992 
4993 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
4994 QDF_STATUS
4995 wlan_cm_update_offload_ssid_from_candidate(struct wlan_objmgr_pdev *pdev,
4996 					   uint8_t vdev_id,
4997 					   struct qdf_mac_addr *ap_bssid)
4998 {
4999 	struct wlan_objmgr_vdev *vdev;
5000 	struct wlan_objmgr_psoc *psoc;
5001 	qdf_list_t *list = NULL;
5002 	struct scan_cache_node *first_node = NULL;
5003 	struct scan_filter *scan_filter;
5004 	struct scan_cache_entry *entry;
5005 	struct qdf_mac_addr cache_bssid;
5006 	QDF_STATUS status = QDF_STATUS_SUCCESS;
5007 
5008 	psoc = wlan_pdev_get_psoc(pdev);
5009 	if (!psoc)
5010 		return QDF_STATUS_E_NULL_VALUE;
5011 
5012 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
5013 						    WLAN_MLME_OBJMGR_ID);
5014 	if (!vdev)
5015 		return QDF_STATUS_E_NULL_VALUE;
5016 
5017 	/*
5018 	 * sae_offload ssid, bssid would have already been cached
5019 	 * from the tx profile of the roam_candidate_frame from FW,
5020 	 * but if the roam offload is received for a non-tx BSSID,
5021 	 * then the ssid stored in mlme_priv would be incorrect.
5022 	 *
5023 	 * If the bssid cached in sae_offload_param doesn't match
5024 	 * with the bssid received in roam_offload_event, then
5025 	 * get the scan entry from scan table to save the proper
5026 	 * ssid, bssid.
5027 	 */
5028 	wlan_cm_get_roam_offload_bssid(vdev, &cache_bssid);
5029 	if (!qdf_mem_cmp(cache_bssid.bytes, ap_bssid->bytes, QDF_MAC_ADDR_SIZE))
5030 		goto end;
5031 
5032 	mlme_debug("Update the roam offload ssid from scan cache");
5033 
5034 	scan_filter = qdf_mem_malloc(sizeof(*scan_filter));
5035 	if (!scan_filter) {
5036 		status = QDF_STATUS_E_NOMEM;
5037 		goto end;
5038 	}
5039 
5040 	scan_filter->num_of_bssid = 1;
5041 	qdf_mem_copy(scan_filter->bssid_list[0].bytes,
5042 		     ap_bssid, sizeof(struct qdf_mac_addr));
5043 
5044 	list = wlan_scan_get_result(pdev, scan_filter);
5045 	qdf_mem_free(scan_filter);
5046 
5047 	if (!list || !qdf_list_size(list)) {
5048 		mlme_err("Scan result is empty, candidate entry not found");
5049 		status = QDF_STATUS_E_FAILURE;
5050 		goto end;
5051 	}
5052 
5053 	qdf_list_peek_front(list, (qdf_list_node_t **)&first_node);
5054 	if (first_node && first_node->entry) {
5055 		entry = first_node->entry;
5056 		wlan_cm_set_roam_offload_ssid(vdev,
5057 					      &entry->ssid.ssid[0],
5058 					      entry->ssid.length);
5059 		wlan_cm_set_roam_offload_bssid(vdev, ap_bssid);
5060 	}
5061 
5062 end:
5063 	if (list)
5064 		wlan_scan_purge_results(list);
5065 
5066 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
5067 	return status;
5068 }
5069 
5070 QDF_STATUS
5071 wlan_cm_add_frame_to_scan_db(struct wlan_objmgr_psoc *psoc,
5072 			     struct roam_scan_candidate_frame *frame)
5073 {
5074 	struct wlan_objmgr_vdev *vdev;
5075 	struct wlan_objmgr_pdev *pdev;
5076 	struct cnx_mgr *cm_ctx;
5077 	uint32_t ie_offset, ie_len;
5078 	uint8_t *ie_ptr = NULL;
5079 	uint8_t *extracted_ie = NULL;
5080 	uint8_t primary_channel, band;
5081 	qdf_freq_t op_freq;
5082 	struct wlan_frame_hdr *wh;
5083 	struct qdf_mac_addr bssid;
5084 
5085 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, frame->vdev_id,
5086 						    WLAN_MLME_CM_ID);
5087 	if (!vdev) {
5088 		mlme_err("vdev object is NULL");
5089 		return QDF_STATUS_E_NULL_VALUE;
5090 	}
5091 
5092 	pdev = wlan_vdev_get_pdev(vdev);
5093 	if (!pdev) {
5094 		mlme_err("pdev object is NULL");
5095 		goto err;
5096 	}
5097 
5098 	cm_ctx = cm_get_cm_ctx(vdev);
5099 	if (!cm_ctx) {
5100 		mlme_err("cm ctx is NULL");
5101 		goto err;
5102 	}
5103 
5104 	/* Fixed parameters offset */
5105 	ie_offset = sizeof(struct wlan_frame_hdr) + MAC_B_PR_SSID_OFFSET;
5106 
5107 	if (frame->frame_length <= ie_offset) {
5108 		mlme_err("Invalid frame length");
5109 		goto err;
5110 	}
5111 
5112 	ie_ptr = frame->frame + ie_offset;
5113 	ie_len = frame->frame_length - ie_offset;
5114 
5115 	extracted_ie = (uint8_t *)wlan_get_ie_ptr_from_eid(WLAN_ELEMID_SSID,
5116 							   ie_ptr, ie_len);
5117 	/*
5118 	 * Roam offload ssid/bssid needs to be set only for SAE roam offload
5119 	 * candidate frames for supporting cross-ssid roaming.
5120 	 * This update is not needed for probe/beacons received from the
5121 	 * roam sync frame event.
5122 	 */
5123 	if (frame->roam_offload_candidate_frm &&
5124 	    extracted_ie && extracted_ie[0] == WLAN_ELEMID_SSID) {
5125 		wh = (struct wlan_frame_hdr *)frame->frame;
5126 		WLAN_ADDR_COPY(&bssid.bytes[0], wh->i_addr2);
5127 
5128 		mlme_debug("SSID of the candidate is " QDF_SSID_FMT,
5129 			   QDF_SSID_REF(extracted_ie[1], &extracted_ie[2]));
5130 		wlan_cm_set_roam_offload_ssid(vdev, &extracted_ie[2],
5131 					      extracted_ie[1]);
5132 		wlan_cm_set_roam_offload_bssid(vdev, &bssid);
5133 	}
5134 
5135 	/* For 2.4GHz,5GHz get channel from DS IE */
5136 	extracted_ie = (uint8_t *)wlan_get_ie_ptr_from_eid(WLAN_ELEMID_DSPARMS,
5137 							   ie_ptr, ie_len);
5138 	if (extracted_ie && extracted_ie[0] == WLAN_ELEMID_DSPARMS &&
5139 	    extracted_ie[1] == WLAN_DS_PARAM_IE_MAX_LEN) {
5140 		band = BIT(REG_BAND_2G) | BIT(REG_BAND_5G);
5141 		primary_channel = *(extracted_ie + 2);
5142 		mlme_debug("Extracted primary channel from DS : %d",
5143 			   primary_channel);
5144 		goto update_beacon;
5145 	}
5146 
5147 	/* For HT, VHT and non-6GHz HE, get channel from HTINFO IE */
5148 	extracted_ie = (uint8_t *)
5149 			wlan_get_ie_ptr_from_eid(WLAN_ELEMID_HTINFO_ANA,
5150 						 ie_ptr, ie_len);
5151 	if (extracted_ie && extracted_ie[0] == WLAN_ELEMID_HTINFO_ANA &&
5152 	    extracted_ie[1] == sizeof(struct wlan_ie_htinfo_cmn)) {
5153 		band = BIT(REG_BAND_2G) | BIT(REG_BAND_5G);
5154 		primary_channel =
5155 			((struct wlan_ie_htinfo *)extracted_ie)->
5156 						hi_ie.hi_ctrlchannel;
5157 		mlme_debug("Extracted primary channel from HT INFO : %d",
5158 			   primary_channel);
5159 		goto update_beacon;
5160 	}
5161 	/* For 6GHz, get channel from HE OP IE */
5162 	extracted_ie = (uint8_t *)
5163 			wlan_get_ext_ie_ptr_from_ext_id(WLAN_HEOP_OUI_TYPE,
5164 							(uint8_t)
5165 							WLAN_HEOP_OUI_SIZE,
5166 							ie_ptr, ie_len);
5167 	if (extracted_ie && !qdf_mem_cmp(&extracted_ie[2], WLAN_HEOP_OUI_TYPE,
5168 					 WLAN_HEOP_OUI_SIZE) &&
5169 	    extracted_ie[1] <= WLAN_MAX_HEOP_IE_LEN) {
5170 		band = BIT(REG_BAND_6G);
5171 		primary_channel = util_scan_get_6g_oper_channel(extracted_ie);
5172 		mlme_debug("Extracted primary channel from HE OP : %d",
5173 			   primary_channel);
5174 		if (primary_channel)
5175 			goto update_beacon;
5176 	}
5177 
5178 	mlme_err("Ignore beacon, Primary channel was not found in the candidate frame");
5179 	goto err;
5180 
5181 update_beacon:
5182 	op_freq = wlan_reg_chan_band_to_freq(pdev, primary_channel, band);
5183 	cm_inform_bcn_probe(cm_ctx, frame->frame, frame->frame_length,
5184 			    op_freq,
5185 			    frame->rssi,
5186 			    cm_ctx->active_cm_id);
5187 
5188 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
5189 	return QDF_STATUS_SUCCESS;
5190 err:
5191 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
5192 	return QDF_STATUS_E_FAILURE;
5193 }
5194 #endif
5195 
5196 #ifdef WLAN_FEATURE_11BE_MLO
5197 bool wlan_cm_is_sae_auth_addr_conversion_required(struct wlan_objmgr_vdev *vdev)
5198 {
5199 	if (!wlan_vdev_get_mlo_external_sae_auth_conversion(vdev))
5200 		return false;
5201 
5202 	if (wlan_cm_is_vdev_roaming(vdev)) {
5203 		if (!wlan_cm_roam_is_mlo_ap(vdev))
5204 			return false;
5205 	} else if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
5206 		return false;
5207 	}
5208 
5209 	return true;
5210 }
5211 #endif /* WLAN_FEATURE_11BE_MLO */
5212 
5213 #if defined(WLAN_FEATURE_ROAM_OFFLOAD) && defined(WLAN_FEATURE_11BE_MLO)
5214 /**
5215  * wlan_cm_reset_mlo_roam_peer_address() - this API reset the sae_roam_auth
5216  * structure values to zero.
5217  * @rso_config: pointer to struct rso_config
5218  *
5219  * Return: void
5220  */
5221 static void wlan_cm_reset_mlo_roam_peer_address(struct rso_config *rso_config)
5222 {
5223 	qdf_mem_zero(&rso_config->sae_roam_auth.peer_mldaddr,
5224 		     QDF_MAC_ADDR_SIZE);
5225 	qdf_mem_zero(&rso_config->sae_roam_auth.peer_linkaddr,
5226 		     QDF_MAC_ADDR_SIZE);
5227 }
5228 
5229 void wlan_cm_store_mlo_roam_peer_address(struct wlan_objmgr_pdev *pdev,
5230 					 struct auth_offload_event *auth_event)
5231 {
5232 	struct wlan_objmgr_vdev *vdev;
5233 	struct rso_config *rso_config;
5234 	struct qdf_mac_addr mld_addr;
5235 	QDF_STATUS status;
5236 
5237 	if (!pdev) {
5238 		mlme_err("pdev is NULL");
5239 		return;
5240 	}
5241 
5242 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, auth_event->vdev_id,
5243 						    WLAN_LEGACY_MAC_ID);
5244 	if (!vdev) {
5245 		mlme_err("vdev %d not found", auth_event->vdev_id);
5246 		return;
5247 	}
5248 
5249 	if (!wlan_vdev_get_mlo_external_sae_auth_conversion(vdev))
5250 		goto rel_ref;
5251 
5252 	if (!wlan_cm_is_vdev_roaming(vdev))
5253 		goto rel_ref;
5254 
5255 	rso_config = wlan_cm_get_rso_config(vdev);
5256 	if (!rso_config)
5257 		goto rel_ref;
5258 
5259 	if (qdf_is_macaddr_zero(&auth_event->ta)) {
5260 		/* ta have zero value for non-ML AP */
5261 		rso_config->sae_roam_auth.is_mlo_ap = false;
5262 		wlan_cm_reset_mlo_roam_peer_address(rso_config);
5263 		goto rel_ref;
5264 	}
5265 
5266 	status = scm_get_mld_addr_by_link_addr(pdev, &auth_event->ap_bssid,
5267 					       &mld_addr);
5268 
5269 	rso_config->sae_roam_auth.is_mlo_ap = true;
5270 
5271 	if (QDF_IS_STATUS_ERROR(status)) {
5272 		wlan_cm_reset_mlo_roam_peer_address(rso_config);
5273 		goto rel_ref;
5274 	}
5275 
5276 	qdf_mem_copy(rso_config->sae_roam_auth.peer_mldaddr.bytes,
5277 		     mld_addr.bytes, QDF_MAC_ADDR_SIZE);
5278 	qdf_mem_copy(rso_config->sae_roam_auth.peer_linkaddr.bytes,
5279 		     &auth_event->ap_bssid, QDF_MAC_ADDR_SIZE);
5280 
5281 	mlme_debug("mld addr " QDF_MAC_ADDR_FMT "link addr " QDF_MAC_ADDR_FMT,
5282 		   QDF_MAC_ADDR_REF(rso_config->sae_roam_auth.peer_mldaddr.bytes),
5283 		   QDF_MAC_ADDR_REF(rso_config->sae_roam_auth.peer_linkaddr.bytes));
5284 rel_ref:
5285 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
5286 }
5287 
5288 struct qdf_mac_addr *
5289 wlan_cm_roaming_get_peer_mld_addr(struct wlan_objmgr_vdev *vdev)
5290 {
5291 	struct rso_config *rso_config;
5292 
5293 	rso_config = wlan_cm_get_rso_config(vdev);
5294 	if (!rso_config)
5295 		return NULL;
5296 
5297 	if (qdf_is_macaddr_zero(&rso_config->sae_roam_auth.peer_mldaddr))
5298 		return NULL;
5299 
5300 	return &rso_config->sae_roam_auth.peer_mldaddr;
5301 }
5302 
5303 struct qdf_mac_addr *
5304 wlan_cm_roaming_get_peer_link_addr(struct wlan_objmgr_vdev *vdev)
5305 {
5306 	struct rso_config *rso_config;
5307 
5308 	rso_config = wlan_cm_get_rso_config(vdev);
5309 	if (!rso_config)
5310 		return NULL;
5311 
5312 	if (qdf_is_macaddr_zero(&rso_config->sae_roam_auth.peer_linkaddr))
5313 		return NULL;
5314 
5315 	return &rso_config->sae_roam_auth.peer_linkaddr;
5316 }
5317 
5318 bool wlan_cm_roam_is_mlo_ap(struct wlan_objmgr_vdev *vdev)
5319 {
5320 	struct rso_config *rso_config;
5321 
5322 	rso_config = wlan_cm_get_rso_config(vdev);
5323 	if (!rso_config)
5324 		return false;
5325 
5326 	return rso_config->sae_roam_auth.is_mlo_ap;
5327 }
5328 
5329 QDF_STATUS
5330 cm_roam_candidate_event_handler(struct wlan_objmgr_psoc *psoc,
5331 				struct roam_scan_candidate_frame *candidate)
5332 {
5333 	return mlo_add_all_link_probe_rsp_to_scan_db(psoc, candidate);
5334 }
5335 
5336 QDF_STATUS
5337 wlan_cm_add_all_link_probe_rsp_to_scan_db(struct wlan_objmgr_psoc *psoc,
5338 				struct roam_scan_candidate_frame *candidate)
5339 {
5340 	return mlo_add_all_link_probe_rsp_to_scan_db(psoc, candidate);
5341 }
5342 
5343 #elif defined(WLAN_FEATURE_ROAM_OFFLOAD) /* end WLAN_FEATURE_11BE_MLO */
5344 QDF_STATUS
5345 cm_roam_candidate_event_handler(struct wlan_objmgr_psoc *psoc,
5346 				struct roam_scan_candidate_frame *candidate)
5347 {
5348 	return wlan_cm_add_frame_to_scan_db(psoc, candidate);
5349 }
5350 
5351 QDF_STATUS
5352 wlan_cm_add_all_link_probe_rsp_to_scan_db(struct wlan_objmgr_psoc *psoc,
5353 				struct roam_scan_candidate_frame *candidate)
5354 {
5355 	return wlan_cm_add_frame_to_scan_db(psoc, candidate);
5356 }
5357 
5358 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
5359 
5360 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
5361 QDF_STATUS wlan_cm_link_switch_notif_cb(struct wlan_objmgr_vdev *vdev,
5362 					struct wlan_mlo_link_switch_req *req,
5363 					enum wlan_mlo_link_switch_notify_reason notify_reason)
5364 {
5365 	QDF_STATUS status = QDF_STATUS_SUCCESS;
5366 
5367 	if (notify_reason != MLO_LINK_SWITCH_NOTIFY_REASON_PRE_START_PRE_SER)
5368 		return status;
5369 
5370 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
5371 		return status;
5372 
5373 	/* Only send RSO stop for assoc vdev */
5374 	if (wlan_vdev_mlme_is_mlo_link_vdev(vdev))
5375 		return status;
5376 
5377 	status = cm_roam_state_change(wlan_vdev_get_pdev(vdev),
5378 				      wlan_vdev_get_id(vdev),
5379 				      WLAN_ROAM_RSO_STOPPED,
5380 				      REASON_DISCONNECTED, NULL, false);
5381 	if (QDF_IS_STATUS_ERROR(status))
5382 		mlme_err("vdev:%d switch to RSO Stop failed",
5383 			 wlan_vdev_get_id(vdev));
5384 
5385 	return status;
5386 }
5387 #endif
5388 
5389