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