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