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), ¤t_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), ¤t_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