xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
1 /*
2  * Copyright (c) 2012-2015, 2020, The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  * DOC: Implements connect specific APIs of connection manager
19  */
20 
21 #include "wlan_cm_main_api.h"
22 #include "wlan_cm_bss_score_param.h"
23 #include "wlan_scan_api.h"
24 #include "wlan_cm_sm.h"
25 #ifdef WLAN_POLICY_MGR_ENABLE
26 #include "wlan_policy_mgr_api.h"
27 #endif
28 #include <wlan_serialization_api.h>
29 #ifdef CONN_MGR_ADV_FEATURE
30 #include "wlan_blm_api.h"
31 #include "wlan_cm_roam_api.h"
32 #endif
33 #include <wlan_utility.h>
34 
35 static void
36 cm_fill_failure_resp_from_cm_id(struct cnx_mgr *cm_ctx,
37 				struct wlan_cm_connect_resp *resp,
38 				wlan_cm_id cm_id,
39 				enum wlan_cm_connect_fail_reason reason)
40 {
41 	resp->connect_status = QDF_STATUS_E_FAILURE;
42 	resp->cm_id = cm_id;
43 	resp->vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
44 	resp->reason = reason;
45 	/* Get bssid and ssid and freq for the cm id from the req list */
46 	cm_fill_bss_info_in_connect_rsp_by_cm_id(cm_ctx, cm_id, resp);
47 }
48 
49 static QDF_STATUS cm_connect_cmd_timeout(struct cnx_mgr *cm_ctx,
50 					 wlan_cm_id cm_id)
51 {
52 	struct wlan_cm_connect_resp *resp;
53 	QDF_STATUS status;
54 
55 	resp = qdf_mem_malloc(sizeof(*resp));
56 	if (!resp)
57 		return QDF_STATUS_E_NOMEM;
58 
59 	cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id, CM_SER_TIMEOUT);
60 	status = cm_sm_deliver_event(cm_ctx->vdev,
61 				     WLAN_CM_SM_EV_CONNECT_FAILURE,
62 				     sizeof(*resp), resp);
63 	qdf_mem_free(resp);
64 
65 	if (QDF_IS_STATUS_ERROR(status))
66 		cm_connect_handle_event_post_fail(cm_ctx, cm_id);
67 
68 	return status;
69 }
70 
71 #ifdef WLAN_CM_USE_SPINLOCK
72 static QDF_STATUS cm_activate_connect_req_flush_cb(struct scheduler_msg *msg)
73 {
74 	struct wlan_serialization_command *cmd = msg->bodyptr;
75 
76 	if (!cmd || !cmd->vdev) {
77 		mlme_err("Null input cmd:%pK", cmd);
78 		return QDF_STATUS_E_INVAL;
79 	}
80 
81 	wlan_objmgr_vdev_release_ref(cmd->vdev, WLAN_MLME_CM_ID);
82 	return QDF_STATUS_SUCCESS;
83 }
84 
85 static QDF_STATUS cm_activate_connect_req_sched_cb(struct scheduler_msg *msg)
86 {
87 	struct wlan_serialization_command *cmd = msg->bodyptr;
88 	struct wlan_objmgr_vdev *vdev;
89 	struct cnx_mgr *cm_ctx;
90 	QDF_STATUS ret = QDF_STATUS_E_FAILURE;
91 
92 	if (!cmd) {
93 		mlme_err("cmd is null");
94 		return QDF_STATUS_E_INVAL;
95 	}
96 
97 	vdev = cmd->vdev;
98 	if (!vdev) {
99 		mlme_err("vdev is null");
100 		return QDF_STATUS_E_INVAL;
101 	}
102 
103 	cm_ctx = cm_get_cm_ctx(vdev);
104 	if (!cm_ctx)
105 		return QDF_STATUS_E_INVAL;
106 
107 	ret = cm_sm_deliver_event(vdev,
108 				  WLAN_CM_SM_EV_CONNECT_ACTIVE,
109 				  sizeof(wlan_cm_id),
110 				  &cmd->cmd_id);
111 
112 	/*
113 	 * Called from scheduler context hence posting failure
114 	 */
115 	if (QDF_IS_STATUS_ERROR(ret)) {
116 		mlme_err(CM_PREFIX_FMT "Activation failed for cmd:%d",
117 			 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id),
118 			 cmd->cmd_type);
119 		cm_connect_handle_event_post_fail(cm_ctx, cmd->cmd_id);
120 	}
121 
122 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
123 	return ret;
124 }
125 
126 static QDF_STATUS
127 cm_activate_connect_req(struct wlan_serialization_command *cmd)
128 {
129 	struct wlan_objmgr_vdev *vdev = cmd->vdev;
130 	struct scheduler_msg msg = {0};
131 	QDF_STATUS ret;
132 
133 	msg.bodyptr = cmd;
134 	msg.callback = cm_activate_connect_req_sched_cb;
135 	msg.flush_callback = cm_activate_connect_req_flush_cb;
136 
137 	ret = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_MLME_CM_ID);
138 	if (QDF_IS_STATUS_ERROR(ret))
139 		return ret;
140 
141 	ret = scheduler_post_message(QDF_MODULE_ID_MLME,
142 				     QDF_MODULE_ID_MLME,
143 				     QDF_MODULE_ID_MLME, &msg);
144 
145 	if (QDF_IS_STATUS_ERROR(ret)) {
146 		mlme_err(CM_PREFIX_FMT "Failed to post scheduler_msg",
147 			 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id));
148 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
149 		return ret;
150 	}
151 	mlme_debug(CM_PREFIX_FMT "Cmd act in sched cmd type:%d",
152 		   CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id),
153 		   cmd->cmd_type);
154 
155 	return ret;
156 }
157 #else
158 static QDF_STATUS
159 cm_activate_connect_req(struct wlan_serialization_command *cmd)
160 {
161 	return cm_sm_deliver_event(cmd->vdev,
162 				   WLAN_CM_SM_EV_CONNECT_ACTIVE,
163 				   sizeof(wlan_cm_id),
164 				   &cmd->cmd_id);
165 }
166 #endif
167 
168 static QDF_STATUS
169 cm_ser_connect_cb(struct wlan_serialization_command *cmd,
170 		  enum wlan_serialization_cb_reason reason)
171 {
172 	QDF_STATUS status = QDF_STATUS_SUCCESS;
173 	struct wlan_objmgr_vdev *vdev;
174 	struct cnx_mgr *cm_ctx;
175 
176 	if (!cmd) {
177 		mlme_err("cmd is NULL, reason: %d", reason);
178 		QDF_ASSERT(0);
179 		return QDF_STATUS_E_NULL_VALUE;
180 	}
181 
182 	vdev = cmd->vdev;
183 
184 	cm_ctx = cm_get_cm_ctx(vdev);
185 	if (!cm_ctx)
186 		return QDF_STATUS_E_NULL_VALUE;
187 
188 	switch (reason) {
189 	case WLAN_SER_CB_ACTIVATE_CMD:
190 		/*
191 		 * For pending to active reason, use async api to take lock.
192 		 * For direct activation use sync api to avoid taking lock
193 		 * as lock is already acquired by the requester.
194 		 */
195 		if (cmd->activation_reason == SER_PENDING_TO_ACTIVE)
196 			status = cm_activate_connect_req(cmd);
197 		else
198 			status = cm_sm_deliver_event_sync(cm_ctx,
199 						   WLAN_CM_SM_EV_CONNECT_ACTIVE,
200 						   sizeof(wlan_cm_id),
201 						   &cmd->cmd_id);
202 		if (QDF_IS_STATUS_SUCCESS(status))
203 			break;
204 		/*
205 		 * Handle failure if posting fails, i.e. the SM state has
206 		 * changed or head cm_id doesn't match the active cm_id.
207 		 * connect active should be handled only in JOIN_PENDING. If
208 		 * new command has been received connect activation should be
209 		 * aborted from here with connect req cleanup.
210 		 */
211 		cm_connect_handle_event_post_fail(cm_ctx, cmd->cmd_id);
212 		break;
213 	case WLAN_SER_CB_CANCEL_CMD:
214 		/* command removed from pending list. */
215 		break;
216 	case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
217 		mlme_err(CM_PREFIX_FMT "Active command timeout",
218 			 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id));
219 		QDF_ASSERT(0);
220 
221 		cm_connect_cmd_timeout(cm_ctx, cmd->cmd_id);
222 		break;
223 	case WLAN_SER_CB_RELEASE_MEM_CMD:
224 		cm_reset_active_cm_id(vdev, cmd->cmd_id);
225 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
226 		break;
227 	default:
228 		QDF_ASSERT(0);
229 		status = QDF_STATUS_E_INVAL;
230 		break;
231 	}
232 
233 	return status;
234 }
235 
236 #define CONNECT_TIMEOUT       30000
237 
238 static QDF_STATUS cm_ser_connect_req(struct wlan_objmgr_pdev *pdev,
239 				     struct cnx_mgr *cm_ctx,
240 				     struct cm_connect_req *cm_req)
241 {
242 	struct wlan_serialization_command cmd = {0, };
243 	enum wlan_serialization_status ser_cmd_status;
244 	QDF_STATUS status;
245 	uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
246 
247 	status = wlan_objmgr_vdev_try_get_ref(cm_ctx->vdev, WLAN_MLME_CM_ID);
248 	if (QDF_IS_STATUS_ERROR(status)) {
249 		mlme_err(CM_PREFIX_FMT "unable to get reference",
250 			 CM_PREFIX_REF(vdev_id, cm_req->cm_id));
251 		return status;
252 	}
253 
254 	cmd.cmd_type = WLAN_SER_CMD_VDEV_CONNECT;
255 	cmd.cmd_id = cm_req->cm_id;
256 	cmd.cmd_cb = cm_ser_connect_cb;
257 	cmd.source = WLAN_UMAC_COMP_MLME;
258 	cmd.is_high_priority = false;
259 	cmd.cmd_timeout_duration = CONNECT_TIMEOUT;
260 	cmd.vdev = cm_ctx->vdev;
261 	cmd.is_blocking = cm_ser_get_blocking_cmd();
262 
263 	ser_cmd_status = wlan_serialization_request(&cmd);
264 	switch (ser_cmd_status) {
265 	case WLAN_SER_CMD_PENDING:
266 		/* command moved to pending list.Do nothing */
267 		break;
268 	case WLAN_SER_CMD_ACTIVE:
269 		/* command moved to active list. Do nothing */
270 		break;
271 	default:
272 		mlme_err(CM_PREFIX_FMT "ser cmd status %d",
273 			 CM_PREFIX_REF(vdev_id, cm_req->cm_id), ser_cmd_status);
274 		wlan_objmgr_vdev_release_ref(cm_ctx->vdev, WLAN_MLME_CM_ID);
275 
276 		return QDF_STATUS_E_FAILURE;
277 	}
278 
279 	return QDF_STATUS_SUCCESS;
280 }
281 
282 void
283 cm_connect_handle_event_post_fail(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id)
284 {
285 	struct wlan_cm_connect_resp *resp;
286 
287 	resp = qdf_mem_malloc(sizeof(*resp));
288 	if (!resp)
289 		return;
290 
291 	cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id,
292 					CM_ABORT_DUE_TO_NEW_REQ_RECVD);
293 	cm_connect_complete(cm_ctx, resp);
294 	qdf_mem_free(resp);
295 }
296 
297 QDF_STATUS
298 cm_send_connect_start_fail(struct cnx_mgr *cm_ctx,
299 			   struct cm_connect_req *req,
300 			   enum wlan_cm_connect_fail_reason reason)
301 {
302 	struct wlan_cm_connect_resp *resp;
303 	QDF_STATUS status;
304 
305 	resp = qdf_mem_malloc(sizeof(*resp));
306 	if (!resp)
307 		return QDF_STATUS_E_NOMEM;
308 
309 	resp->connect_status = QDF_STATUS_E_FAILURE;
310 	resp->cm_id = req->cm_id;
311 	resp->vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
312 	resp->reason = reason;
313 	resp->ssid.length = req->req.ssid.length;
314 	qdf_mem_copy(resp->ssid.ssid, req->req.ssid.ssid, resp->ssid.length);
315 	if (req->cur_candidate) {
316 		qdf_copy_macaddr(&resp->bssid,
317 				 &req->cur_candidate->entry->bssid);
318 		resp->freq = req->cur_candidate->entry->channel.chan_freq;
319 	}
320 
321 	status = cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_CONNECT_FAILURE,
322 					  sizeof(*resp), resp);
323 	qdf_mem_free(resp);
324 
325 	return status;
326 }
327 
328 #ifdef WLAN_POLICY_MGR_ENABLE
329 
330 QDF_STATUS cm_handle_hw_mode_change(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id,
331 				    enum wlan_cm_sm_evt event)
332 {
333 	struct cm_req *cm_req;
334 	enum wlan_cm_connect_fail_reason reason = CM_GENERIC_FAILURE;
335 	struct wlan_objmgr_pdev *pdev;
336 	QDF_STATUS status;
337 
338 	if (!cm_id)
339 		return QDF_STATUS_E_FAILURE;
340 
341 	cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id);
342 	if (!cm_req)
343 		return QDF_STATUS_E_INVAL;
344 
345 	pdev = wlan_vdev_get_pdev(cm_ctx->vdev);
346 	if (!pdev) {
347 		mlme_err(CM_PREFIX_FMT "Failed to find pdev",
348 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
349 				       cm_req->cm_id));
350 		goto send_failure;
351 	}
352 
353 	if (event == WLAN_CM_SM_EV_HW_MODE_SUCCESS) {
354 		status = cm_ser_connect_req(pdev, cm_ctx, &cm_req->connect_req);
355 		if (QDF_IS_STATUS_ERROR(status)) {
356 			reason = CM_SER_FAILURE;
357 			goto send_failure;
358 		}
359 		return status;
360 	}
361 
362 	/* Set reason HW mode fail for event WLAN_CM_SM_EV_HW_MODE_FAILURE */
363 	reason = CM_HW_MODE_FAILURE;
364 
365 send_failure:
366 	return cm_send_connect_start_fail(cm_ctx, &cm_req->connect_req, reason);
367 }
368 
369 void cm_hw_mode_change_resp(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
370 			    wlan_cm_id cm_id, QDF_STATUS status)
371 {
372 	struct wlan_objmgr_vdev *vdev;
373 	QDF_STATUS qdf_status;
374 	enum wlan_cm_sm_evt event = WLAN_CM_SM_EV_HW_MODE_SUCCESS;
375 	struct cnx_mgr *cm_ctx;
376 
377 	mlme_debug(CM_PREFIX_FMT "Continue connect after HW mode change, status %d",
378 		   CM_PREFIX_REF(vdev_id, cm_id), status);
379 
380 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
381 						    WLAN_MLME_CM_ID);
382 	if (!vdev)
383 		return;
384 
385 	cm_ctx = cm_get_cm_ctx(vdev);
386 	if (!cm_ctx) {
387 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
388 		return;
389 	}
390 
391 	if (QDF_IS_STATUS_ERROR(status))
392 		event = WLAN_CM_SM_EV_HW_MODE_FAILURE;
393 	qdf_status = cm_sm_deliver_event(vdev, event, sizeof(wlan_cm_id),
394 					 &cm_id);
395 
396 	/*
397 	 * Handle failure if posting fails, i.e. the SM state has
398 	 * changed or head cm_id doesn't match the active cm_id.
399 	 * hw mode change resp should be handled only in JOIN_PENDING. If
400 	 * new command has been received connect should be
401 	 * aborted from here with connect req cleanup.
402 	 */
403 	if (QDF_IS_STATUS_ERROR(status))
404 		cm_connect_handle_event_post_fail(cm_ctx, cm_id);
405 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
406 }
407 
408 static QDF_STATUS cm_check_for_hw_mode_change(struct wlan_objmgr_psoc *psoc,
409 					      qdf_list_t *scan_list,
410 					      uint8_t vdev_id,
411 					      wlan_cm_id connect_id)
412 {
413 	return policy_mgr_change_hw_mode_sta_connect(psoc, scan_list, vdev_id,
414 						     connect_id);
415 }
416 
417 static void
418 cm_get_pcl_chan_weigtage_for_sta(struct wlan_objmgr_pdev *pdev,
419 				 struct pcl_freq_weight_list *pcl_lst)
420 {
421 	enum QDF_OPMODE opmode = QDF_STA_MODE;
422 	enum policy_mgr_con_mode pm_mode;
423 	uint32_t num_entries = 0;
424 	QDF_STATUS status;
425 
426 	if (!pcl_lst)
427 		return;
428 
429 	if (policy_mgr_map_concurrency_mode(&opmode, &pm_mode)) {
430 		status = policy_mgr_get_pcl(wlan_pdev_get_psoc(pdev), pm_mode,
431 					    pcl_lst->pcl_freq_list,
432 					    &num_entries,
433 					    pcl_lst->pcl_weight_list,
434 					    NUM_CHANNELS);
435 		if (QDF_IS_STATUS_ERROR(status))
436 			return;
437 		pcl_lst->num_of_pcl_channels = num_entries;
438 	}
439 }
440 
441 static void cm_calculate_scores(struct wlan_objmgr_pdev *pdev,
442 				struct scan_filter *filter, qdf_list_t *list)
443 {
444 	struct pcl_freq_weight_list *pcl_lst = NULL;
445 
446 	if (!filter->num_of_bssid) {
447 		pcl_lst = qdf_mem_malloc(sizeof(*pcl_lst));
448 		cm_get_pcl_chan_weigtage_for_sta(pdev, pcl_lst);
449 		if (pcl_lst && !pcl_lst->num_of_pcl_channels) {
450 			qdf_mem_free(pcl_lst);
451 			pcl_lst = NULL;
452 		}
453 	}
454 	wlan_cm_calculate_bss_score(pdev, pcl_lst, list, &filter->bssid_hint);
455 	if (pcl_lst)
456 		qdf_mem_free(pcl_lst);
457 }
458 #else
459 
460 static inline
461 QDF_STATUS cm_check_for_hw_mode_change(struct wlan_objmgr_psoc *psoc,
462 				       qdf_list_t *scan_list, uint8_t vdev_id,
463 				       uint8_t connect_id)
464 {
465 	return QDF_STATUS_E_ALREADY;
466 }
467 
468 static inline
469 void cm_calculate_scores(struct wlan_objmgr_pdev *pdev,
470 			 struct scan_filter *filter, qdf_list_t *list)
471 {
472 	wlan_cm_calculate_bss_score(pdev, NULL, list, &filter->bssid_hint);
473 }
474 #endif /* WLAN_POLICY_MGR_ENABLE */
475 
476 static inline void cm_delete_pmksa_for_bssid(struct cnx_mgr *cm_ctx,
477 					     struct qdf_mac_addr *bssid)
478 {
479 	struct wlan_crypto_pmksa pmksa;
480 
481 	qdf_mem_zero(&pmksa, sizeof(pmksa));
482 	qdf_copy_macaddr(&pmksa.bssid, bssid);
483 	wlan_crypto_set_del_pmksa(cm_ctx->vdev, &pmksa, false);
484 }
485 
486 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
487 static inline
488 void cm_delete_pmksa_for_single_pmk_bssid(struct cnx_mgr *cm_ctx,
489 					  struct qdf_mac_addr *bssid)
490 {
491 	cm_delete_pmksa_for_bssid(cm_ctx, bssid);
492 }
493 #else
494 static inline
495 void cm_delete_pmksa_for_single_pmk_bssid(struct cnx_mgr *cm_ctx,
496 					  struct qdf_mac_addr *bssid)
497 {
498 }
499 #endif /* WLAN_SAE_SINGLE_PMK && WLAN_FEATURE_ROAM_OFFLOAD */
500 
501 static inline void
502 cm_set_pmf_caps(struct wlan_cm_connect_req *req, struct scan_filter *filter)
503 {
504 	if (req->crypto.rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)
505 		filter->pmf_cap = WLAN_PMF_REQUIRED;
506 	else if (req->crypto.rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)
507 		filter->pmf_cap = WLAN_PMF_CAPABLE;
508 	else
509 		filter->pmf_cap = WLAN_PMF_DISABLED;
510 }
511 
512 #ifdef CONN_MGR_ADV_FEATURE
513 #ifdef WLAN_FEATURE_FILS_SK
514 /*
515  * cm_create_fils_realm_hash: API to create hash using realm
516  * @fils_info: fils connection info obtained from supplicant
517  * @tmp_hash: pointer to new hash
518  *
519  * Return: QDF_STATUS
520  */
521 static QDF_STATUS
522 cm_create_fils_realm_hash(struct wlan_fils_con_info *fils_info,
523 			  uint8_t *tmp_hash)
524 {
525 	uint8_t *hash;
526 	uint8_t *data;
527 
528 	if (!fils_info->realm_len)
529 		return QDF_STATUS_E_NOSUPPORT;
530 
531 	hash = qdf_mem_malloc(SHA256_DIGEST_SIZE);
532 	if (!hash)
533 		return QDF_STATUS_E_NOMEM;
534 
535 	data = fils_info->realm;
536 	qdf_get_hash(SHA256_CRYPTO_TYPE, 1, &data, &fils_info->realm_len, hash);
537 	qdf_mem_copy(tmp_hash, hash, REALM_HASH_LEN);
538 	qdf_mem_free(hash);
539 
540 	return QDF_STATUS_SUCCESS;
541 }
542 
543 static void cm_update_fils_scan_filter(struct scan_filter *filter,
544 				       struct cm_connect_req *cm_req)
545 
546 {
547 	uint8_t realm_hash[REALM_HASH_LEN];
548 	QDF_STATUS status;
549 
550 	if (!cm_req->req.fils_info.is_fils_connection)
551 		return;
552 
553 	status = cm_create_fils_realm_hash(&cm_req->req.fils_info, realm_hash);
554 	if (QDF_IS_STATUS_ERROR(status))
555 		return;
556 
557 	filter->fils_scan_filter.realm_check = true;
558 	mlme_debug(CM_PREFIX_FMT "creating realm based on fils info",
559 		   CM_PREFIX_REF(cm_req->req.vdev_id, cm_req->cm_id));
560 	qdf_mem_copy(filter->fils_scan_filter.fils_realm, realm_hash,
561 		     REALM_HASH_LEN);
562 }
563 
564 static inline bool cm_is_fils_connection(struct cnx_mgr *cm_ctx,
565 					 struct wlan_cm_connect_resp *resp)
566 {
567 	int32_t key_mgmt;
568 
569 	key_mgmt = wlan_crypto_get_param(cm_ctx->vdev,
570 					 WLAN_CRYPTO_PARAM_KEY_MGMT);
571 
572 	if (!(key_mgmt & (1 << WLAN_CRYPTO_KEY_MGMT_FILS_SHA256 |
573 			  1 << WLAN_CRYPTO_KEY_MGMT_FILS_SHA384 |
574 			  1 << WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256 |
575 			  1 << WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384)))
576 		return false;
577 
578 	resp->is_fils_connection = true;
579 
580 	return true;
581 }
582 
583 static QDF_STATUS cm_set_fils_key(struct cnx_mgr *cm_ctx,
584 				  struct wlan_cm_connect_resp *resp)
585 {
586 	struct fils_connect_rsp_params *fils_ie;
587 
588 	fils_ie = resp->connect_ies.fils_ie;
589 
590 	if (!fils_ie)
591 		return QDF_STATUS_E_INVAL;
592 
593 	cm_store_fils_key(cm_ctx, true, 0, fils_ie->tk_len, fils_ie->tk,
594 			  &resp->bssid, resp->cm_id);
595 	cm_store_fils_key(cm_ctx, false, 2, fils_ie->gtk_len, fils_ie->gtk,
596 			  &resp->bssid, resp->cm_id);
597 	cm_set_key(cm_ctx, true, 0, &resp->bssid);
598 	cm_set_key(cm_ctx, false, 2, &resp->bssid);
599 
600 	return QDF_STATUS_SUCCESS;
601 }
602 
603 #else
604 static inline void cm_update_fils_scan_filter(struct scan_filter *filter,
605 					      struct cm_connect_req *cm_req)
606 { }
607 
608 static inline bool cm_is_fils_connection(struct cnx_mgr *cm_ctx,
609 					 struct wlan_cm_connect_resp *resp)
610 {
611 	return false;
612 }
613 
614 static inline QDF_STATUS cm_set_fils_key(struct cnx_mgr *cm_ctx,
615 					 struct wlan_cm_connect_resp *resp)
616 {
617 	return QDF_STATUS_SUCCESS;
618 }
619 #endif /* WLAN_FEATURE_FILS_SK */
620 
621 static QDF_STATUS
622 cm_inform_blm_connect_complete(struct wlan_objmgr_vdev *vdev,
623 			       struct wlan_cm_connect_resp *resp)
624 {
625 	struct wlan_objmgr_pdev *pdev;
626 
627 	pdev = wlan_vdev_get_pdev(vdev);
628 	if (!pdev) {
629 		mlme_err(CM_PREFIX_FMT "Failed to find pdev",
630 			 CM_PREFIX_REF(wlan_vdev_get_id(vdev), resp->cm_id));
631 		return QDF_STATUS_E_FAILURE;
632 	}
633 
634 	if (QDF_IS_STATUS_SUCCESS(resp->connect_status))
635 		wlan_blm_update_bssid_connect_params(pdev, resp->bssid,
636 						     BLM_AP_CONNECTED);
637 
638 	return QDF_STATUS_SUCCESS;
639 }
640 
641 /**
642  * cm_is_retry_with_same_candidate() - This API check if reconnect attempt is
643  * required with the same candidate again
644  * @cm_ctx: connection manager context
645  * @req: Connect request.
646  * @resp: connect resp from previous connection attempt
647  *
648  * This function return true if same candidate needs to be tried again
649  *
650  * Return: bool
651  */
652 static bool cm_is_retry_with_same_candidate(struct cnx_mgr *cm_ctx,
653 					    struct cm_connect_req *req,
654 					    struct wlan_cm_connect_resp *resp)
655 {
656 	uint8_t max_retry_count = CM_MAX_CANDIDATE_RETRIES;
657 	uint32_t key_mgmt;
658 	struct wlan_objmgr_psoc *psoc;
659 	bool sae_connection;
660 
661 	psoc = wlan_pdev_get_psoc(wlan_vdev_get_pdev(cm_ctx->vdev));
662 	key_mgmt = req->cur_candidate->entry->neg_sec_info.key_mgmt;
663 
664 	/* Try once again for the invalid PMKID case without PMKID */
665 	if (resp->status_code == STATUS_INVALID_PMKID)
666 		goto use_same_candidate;
667 
668 	/* Try again for the JOIN timeout if only one candidate */
669 	if (resp->reason == CM_JOIN_TIMEOUT &&
670 	    qdf_list_size(req->candidate_list) == 1) {
671 		/* Get assoc retry count */
672 		wlan_mlme_get_sae_assoc_retry_count(psoc, &max_retry_count);
673 		goto use_same_candidate;
674 	}
675 
676 	/*
677 	 * Try again for the ASSOC timeout in SAE connection or
678 	 * AP has reconnect on assoc timeout OUI.
679 	 */
680 	sae_connection = key_mgmt & (1 << WLAN_CRYPTO_KEY_MGMT_SAE |
681 				     1 << WLAN_CRYPTO_KEY_MGMT_FT_SAE);
682 	if (resp->reason == CM_ASSOC_TIMEOUT && (sae_connection ||
683 	    (mlme_get_reconn_after_assoc_timeout_flag(psoc, resp->vdev_id)))) {
684 		/* For SAE use max retry count from INI */
685 		if (sae_connection)
686 			wlan_mlme_get_sae_assoc_retry_count(psoc,
687 							    &max_retry_count);
688 		goto use_same_candidate;
689 	}
690 
691 	return false;
692 
693 use_same_candidate:
694 	if (req->cur_candidate_retries >= max_retry_count)
695 		return false;
696 
697 	mlme_info(CM_PREFIX_FMT "Retry again with " QDF_MAC_ADDR_FMT ", status code %d reason %d key_mgmt 0x%x retry count %d max retry %d",
698 		  CM_PREFIX_REF(resp->vdev_id, resp->cm_id),
699 		  QDF_MAC_ADDR_REF(resp->bssid.bytes), resp->status_code,
700 		  resp->reason, key_mgmt, req->cur_candidate_retries,
701 		  max_retry_count);
702 
703 	req->cur_candidate_retries++;
704 
705 	return true;
706 }
707 
708 static inline void cm_update_advance_filter(struct wlan_objmgr_pdev *pdev,
709 					    struct cnx_mgr *cm_ctx,
710 					    struct scan_filter *filter,
711 					    struct cm_connect_req *cm_req)
712 {
713 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
714 
715 	filter->enable_adaptive_11r =
716 		wlan_mlme_adaptive_11r_enabled(psoc);
717 	if (wlan_vdev_mlme_get_opmode(cm_ctx->vdev) != QDF_STA_MODE)
718 		return;
719 
720 	wlan_cm_dual_sta_roam_update_connect_channels(psoc, filter);
721 	filter->dot11mode = cm_req->req.dot11mode_filter;
722 	cm_update_fils_scan_filter(filter, cm_req);
723 }
724 
725 static void cm_update_security_filter(struct scan_filter *filter,
726 				      struct wlan_cm_connect_req *req)
727 {
728 	uint8_t wsc_oui[OUI_LENGTH];
729 	uint8_t osen_oui[OUI_LENGTH];
730 	uint32_t oui_cpu;
731 
732 	oui_cpu = qdf_be32_to_cpu(WSC_OUI);
733 	qdf_mem_copy(wsc_oui, &oui_cpu, OUI_LENGTH);
734 	oui_cpu = qdf_be32_to_cpu(OSEN_OUI);
735 	qdf_mem_copy(osen_oui, &oui_cpu, OUI_LENGTH);
736 
737 	/* Ignore security match for rsn override, OSEN and WPS connection */
738 	if (req->force_rsne_override ||
739 	    wlan_get_vendor_ie_ptr_from_oui(wsc_oui, OUI_LENGTH,
740 					    req->assoc_ie.ptr,
741 					    req->assoc_ie.len) ||
742 	    wlan_get_vendor_ie_ptr_from_oui(osen_oui, OUI_LENGTH,
743 					    req->assoc_ie.ptr,
744 					    req->assoc_ie.len)) {
745 		filter->ignore_auth_enc_type = 1;
746 		return;
747 	}
748 
749 	filter->authmodeset = req->crypto.auth_type;
750 	filter->ucastcipherset = req->crypto.ciphers_pairwise;
751 	filter->key_mgmt = req->crypto.akm_suites;
752 	filter->mcastcipherset = req->crypto.group_cipher;
753 	filter->mgmtcipherset = req->crypto.mgmt_ciphers;
754 	cm_set_pmf_caps(req, filter);
755 }
756 
757 /**
758  * cm_set_fils_wep_key() - check and set wep or fils keys if required
759  * @cm_ctx: connection manager context
760  * @resp: connect resp
761  *
762  * Context: Can be called from any context and to be used only after posting a
763  * msg to SM (ie holding the SM lock) i.e. on successful connection.
764  */
765 static void cm_set_fils_wep_key(struct cnx_mgr *cm_ctx,
766 				struct wlan_cm_connect_resp *resp)
767 {
768 	int32_t cipher;
769 	struct qdf_mac_addr broadcast_mac = QDF_MAC_ADDR_BCAST_INIT;
770 
771 	/* Check and set FILS keys */
772 	if (cm_is_fils_connection(cm_ctx, resp)) {
773 		cm_set_fils_key(cm_ctx, resp);
774 		return;
775 	}
776 	/* Check and set WEP keys */
777 	cipher = wlan_crypto_get_param(cm_ctx->vdev,
778 				       WLAN_CRYPTO_PARAM_UCAST_CIPHER);
779 	if (cipher < 0)
780 		return;
781 
782 	if (!(cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_40 |
783 			1 << WLAN_CRYPTO_CIPHER_WEP_104)))
784 		return;
785 
786 	cm_set_key(cm_ctx, true, 0, &resp->bssid);
787 	cm_set_key(cm_ctx, false, 0, &broadcast_mac);
788 }
789 #else
790 static inline QDF_STATUS
791 cm_inform_blm_connect_complete(struct wlan_objmgr_vdev *vdev,
792 			       struct wlan_cm_connect_resp *resp)
793 {
794 	return QDF_STATUS_SUCCESS;
795 }
796 
797 static inline
798 bool cm_is_retry_with_same_candidate(struct cnx_mgr *cm_ctx,
799 				     struct cm_connect_req *req,
800 				     struct wlan_cm_connect_resp *resp)
801 {
802 	return false;
803 }
804 
805 static inline void cm_update_advance_filter(struct wlan_objmgr_pdev *pdev,
806 					    struct cnx_mgr *cm_ctx,
807 					    struct scan_filter *filter,
808 					    struct cm_connect_req *cm_req)
809 { }
810 
811 static void cm_update_security_filter(struct scan_filter *filter,
812 				      struct wlan_cm_connect_req *req)
813 {
814 	if (!QDF_HAS_PARAM(req->crypto.auth_type, WLAN_CRYPTO_AUTH_WAPI) &&
815 	    !QDF_HAS_PARAM(req->crypto.auth_type, WLAN_CRYPTO_AUTH_RSNA) &&
816 	    !QDF_HAS_PARAM(req->crypto.auth_type, WLAN_CRYPTO_AUTH_WPA)) {
817 		filter->ignore_auth_enc_type = 1;
818 		return;
819 	}
820 
821 	filter->authmodeset = req->crypto.auth_type;
822 	filter->ucastcipherset = req->crypto.ciphers_pairwise;
823 	filter->key_mgmt = req->crypto.akm_suites;
824 	filter->mcastcipherset = req->crypto.group_cipher;
825 	filter->mgmtcipherset = req->crypto.mgmt_ciphers;
826 	cm_set_pmf_caps(req, filter);
827 }
828 static inline void cm_set_fils_wep_key(struct cnx_mgr *cm_ctx,
829 				       struct wlan_cm_connect_resp *resp)
830 {}
831 
832 #endif /* CONN_MGR_ADV_FEATURE */
833 
834 static void cm_connect_prepare_scan_filter(struct wlan_objmgr_pdev *pdev,
835 					   struct cnx_mgr *cm_ctx,
836 					   struct cm_connect_req *cm_req,
837 					   struct scan_filter *filter,
838 					   bool security_valid_for_6ghz)
839 {
840 	if (!qdf_is_macaddr_zero(&cm_req->req.bssid)) {
841 		filter->num_of_bssid = 1;
842 		qdf_copy_macaddr(&filter->bssid_list[0], &cm_req->req.bssid);
843 	}
844 
845 	qdf_copy_macaddr(&filter->bssid_hint, &cm_req->req.bssid_hint);
846 	filter->num_of_ssid = 1;
847 	qdf_mem_copy(&filter->ssid_list[0], &cm_req->req.ssid,
848 		     sizeof(struct wlan_ssid));
849 
850 	if (cm_req->req.chan_freq) {
851 		filter->num_of_channels = 1;
852 		filter->chan_freq_list[0] = cm_req->req.chan_freq;
853 	}
854 
855 	/* Security is not valid for 6Ghz so ignore 6Ghz APs */
856 	if (!security_valid_for_6ghz)
857 		filter->ignore_6ghz_channel = true;
858 
859 	cm_update_security_filter(filter, &cm_req->req);
860 	cm_update_advance_filter(pdev, cm_ctx, filter, cm_req);
861 }
862 
863 static QDF_STATUS cm_connect_get_candidates(struct wlan_objmgr_pdev *pdev,
864 					    struct cnx_mgr *cm_ctx,
865 					    struct cm_connect_req *cm_req)
866 {
867 	struct scan_filter *filter;
868 	uint32_t num_bss = 0;
869 	enum QDF_OPMODE op_mode;
870 	qdf_list_t *candidate_list;
871 	uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
872 	bool security_valid_for_6ghz;
873 	const uint8_t *rsnxe;
874 
875 	filter = qdf_mem_malloc(sizeof(*filter));
876 	if (!filter)
877 		return QDF_STATUS_E_NOMEM;
878 
879 	rsnxe = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSNXE,
880 					 cm_req->req.assoc_ie.ptr,
881 					 cm_req->req.assoc_ie.len);
882 	security_valid_for_6ghz =
883 		wlan_cm_6ghz_allowed_for_akm(wlan_pdev_get_psoc(pdev),
884 					     cm_req->req.crypto.akm_suites,
885 					     cm_req->req.crypto.rsn_caps,
886 					     rsnxe, cm_req->req.sae_pwe);
887 
888 	/*
889 	 * Ignore connect req if the freq is provided and its 6Ghz and
890 	 * security is not valid for 6Ghz
891 	 */
892 	if (cm_req->req.chan_freq && !security_valid_for_6ghz &&
893 	    WLAN_REG_IS_6GHZ_CHAN_FREQ(cm_req->req.chan_freq)) {
894 		mlme_info(CM_PREFIX_FMT "6ghz freq (%d) given and 6Ghz not allowed for the security in connect req",
895 			  CM_PREFIX_REF(vdev_id, cm_req->cm_id),
896 			  cm_req->req.chan_freq);
897 		return QDF_STATUS_E_INVAL;
898 	}
899 	cm_connect_prepare_scan_filter(pdev, cm_ctx, cm_req, filter,
900 				       security_valid_for_6ghz);
901 
902 	candidate_list = wlan_scan_get_result(pdev, filter);
903 	if (candidate_list) {
904 		num_bss = qdf_list_size(candidate_list);
905 		mlme_debug(CM_PREFIX_FMT "num_entries found %d",
906 			   CM_PREFIX_REF(vdev_id, cm_req->cm_id), num_bss);
907 	}
908 
909 	op_mode = wlan_vdev_mlme_get_opmode(cm_ctx->vdev);
910 	if (num_bss && op_mode == QDF_STA_MODE)
911 		cm_calculate_scores(pdev, filter, candidate_list);
912 	qdf_mem_free(filter);
913 
914 	if (!candidate_list || !qdf_list_size(candidate_list)) {
915 		QDF_STATUS status;
916 
917 		if (candidate_list)
918 			wlan_scan_purge_results(candidate_list);
919 		mlme_info(CM_PREFIX_FMT "no valid candidate found, num_bss %d scan_id %d",
920 			  CM_PREFIX_REF(vdev_id, cm_req->cm_id), num_bss,
921 			  cm_req->scan_id);
922 
923 		/*
924 		 * If connect scan was already done OR candidate were found
925 		 * but none of them were valid return QDF_STATUS_E_EMPTY.
926 		 */
927 		if (cm_req->scan_id || num_bss)
928 			return QDF_STATUS_E_EMPTY;
929 
930 		/* Try connect scan to search for any valid candidate */
931 		status = cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_SCAN,
932 						  sizeof(*cm_req), cm_req);
933 		/*
934 		 * If connect scan is initiated, return pending, so that
935 		 * connect start after scan complete
936 		 */
937 		if (QDF_IS_STATUS_SUCCESS(status))
938 			status = QDF_STATUS_E_PENDING;
939 
940 		return status;
941 	}
942 	cm_req->candidate_list = candidate_list;
943 
944 	return QDF_STATUS_SUCCESS;
945 }
946 
947 #ifdef WLAN_FEATURE_INTERFACE_MGR
948 static QDF_STATUS cm_validate_candidate(struct cnx_mgr *cm_ctx,
949 					struct scan_cache_entry *scan_entry)
950 {
951 	struct if_mgr_event_data event_data = {0};
952 
953 	event_data.validate_bss_info.chan_freq = scan_entry->channel.chan_freq;
954 	qdf_copy_macaddr(&event_data.validate_bss_info.peer_addr,
955 			 &scan_entry->bssid);
956 
957 	return if_mgr_deliver_event(cm_ctx->vdev,
958 				    WLAN_IF_MGR_EV_VALIDATE_CANDIDATE,
959 				    &event_data);
960 }
961 
962 static QDF_STATUS
963 cm_inform_if_mgr_connect_complete(struct wlan_objmgr_vdev *vdev,
964 				  QDF_STATUS connect_status)
965 {
966 	struct if_mgr_event_data *connect_complete;
967 
968 	connect_complete = qdf_mem_malloc(sizeof(*connect_complete));
969 	if (!connect_complete)
970 		return QDF_STATUS_E_NOMEM;
971 
972 	connect_complete->status = connect_status;
973 	if_mgr_deliver_event(vdev, WLAN_IF_MGR_EV_CONNECT_COMPLETE,
974 			     connect_complete);
975 	qdf_mem_free(connect_complete);
976 
977 	return QDF_STATUS_SUCCESS;
978 }
979 
980 static QDF_STATUS
981 cm_inform_if_mgr_connect_start(struct wlan_objmgr_vdev *vdev)
982 {
983 	return if_mgr_deliver_event(vdev, WLAN_IF_MGR_EV_CONNECT_START, NULL);
984 }
985 
986 #else
987 static inline
988 QDF_STATUS cm_validate_candidate(struct cnx_mgr *cm_ctx,
989 				 struct scan_cache_entry *scan_entry)
990 {
991 	return QDF_STATUS_SUCCESS;
992 }
993 
994 static inline QDF_STATUS
995 cm_inform_if_mgr_connect_complete(struct wlan_objmgr_vdev *vdev,
996 				  QDF_STATUS connect_status)
997 {
998 	return QDF_STATUS_SUCCESS;
999 }
1000 
1001 static inline QDF_STATUS
1002 cm_inform_if_mgr_connect_start(struct wlan_objmgr_vdev *vdev)
1003 {
1004 	return QDF_STATUS_SUCCESS;
1005 }
1006 
1007 #endif
1008 
1009 QDF_STATUS
1010 cm_handle_connect_req_in_non_init_state(struct cnx_mgr *cm_ctx,
1011 					struct cm_connect_req *cm_req,
1012 					enum wlan_cm_sm_state cm_state_substate)
1013 {
1014 	switch (cm_state_substate) {
1015 	case WLAN_CM_S_CONNECTED:
1016 	case WLAN_CM_SS_JOIN_ACTIVE:
1017 		/*
1018 		 * In connected state, there would be no pending command, so
1019 		 * for new connect request, queue internal disconnect
1020 		 *
1021 		 * In join active state there would be only one active connect
1022 		 * request in the cm req list, so to abort at certain stages and
1023 		 * to cleanup after its completion, queue internal disconnect.
1024 		 */
1025 		cm_initiate_internal_disconnect(cm_ctx);
1026 		break;
1027 	case WLAN_CM_SS_SCAN:
1028 		/* In the scan state abort the ongoing scan */
1029 		cm_vdev_scan_cancel(wlan_vdev_get_pdev(cm_ctx->vdev),
1030 				    cm_ctx->vdev);
1031 		/* fallthrough */
1032 	case WLAN_CM_SS_JOIN_PENDING:
1033 		/*
1034 		 * In case of scan or join pending there could be 2 scenarios:-
1035 		 *
1036 		 * 1. There is a connect request pending, so just remove
1037 		 *    the pending connect req. As we will queue a new connect
1038 		 *    req, all resp for pending connect req will be dropped.
1039 		 * 2. There is a connect request in active and
1040 		 *    and a internal disconnect followed by a connect req in
1041 		 *    pending. In this case the disconnect will take care of
1042 		 *    cleaning up the active connect request and thus only
1043 		 *    remove the pending connect.
1044 		 */
1045 		cm_flush_pending_request(cm_ctx, CONNECT_REQ_PREFIX, false);
1046 		break;
1047 	case WLAN_CM_S_DISCONNECTING:
1048 		/*
1049 		 * Flush failed pending connect req as new req is received
1050 		 * and its no longer the latest one.
1051 		 */
1052 		if (cm_ctx->connect_count)
1053 			cm_flush_pending_request(cm_ctx, CONNECT_REQ_PREFIX,
1054 						 true);
1055 		/*
1056 		 * In case of disconnecting state, there could be 2 scenarios:-
1057 		 * In both case no state specific action is required.
1058 		 * 1. There is disconnect request in the cm_req list, no action
1059 		 *    required to cleanup.
1060 		 *    so just add the connect request to the list.
1061 		 * 2. There is a connect request activated, followed by
1062 		 *    disconnect in pending queue. So keep the disconenct
1063 		 *    to cleanup the active connect and no action required to
1064 		 *    cleanup.
1065 		 */
1066 		break;
1067 	default:
1068 		mlme_err("Vdev %d Connect req in invalid state %d",
1069 			 wlan_vdev_get_id(cm_ctx->vdev),
1070 			 cm_state_substate);
1071 		return QDF_STATUS_E_FAILURE;
1072 	};
1073 
1074 	/* Queue the new connect request after state specific actions */
1075 	return cm_add_connect_req_to_list(cm_ctx, cm_req);
1076 }
1077 
1078 QDF_STATUS cm_connect_start(struct cnx_mgr *cm_ctx,
1079 			    struct cm_connect_req *cm_req)
1080 {
1081 	struct wlan_objmgr_pdev *pdev;
1082 	struct wlan_objmgr_psoc *psoc;
1083 	enum wlan_cm_connect_fail_reason reason = CM_GENERIC_FAILURE;
1084 	QDF_STATUS status;
1085 	uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
1086 
1087 	/* Interface event */
1088 	pdev = wlan_vdev_get_pdev(cm_ctx->vdev);
1089 	if (!pdev) {
1090 		mlme_err(CM_PREFIX_FMT "Failed to find pdev",
1091 			 CM_PREFIX_REF(vdev_id, cm_req->cm_id));
1092 		goto connect_err;
1093 	}
1094 
1095 	psoc = wlan_pdev_get_psoc(pdev);
1096 	if (!psoc) {
1097 		mlme_err(CM_PREFIX_FMT "Failed to find psoc",
1098 			 CM_PREFIX_REF(vdev_id, cm_req->cm_id));
1099 		goto connect_err;
1100 	}
1101 
1102 	cm_inform_if_mgr_connect_start(cm_ctx->vdev);
1103 	mlme_cm_connect_start_ind(cm_ctx->vdev, &cm_req->req);
1104 
1105 	status = cm_connect_get_candidates(pdev, cm_ctx, cm_req);
1106 	/* In case of status pending connect will continue after scan */
1107 	if (status == QDF_STATUS_E_PENDING)
1108 		return QDF_STATUS_SUCCESS;
1109 	if (QDF_IS_STATUS_ERROR(status)) {
1110 		reason = CM_NO_CANDIDATE_FOUND;
1111 		goto connect_err;
1112 	}
1113 
1114 	status = cm_check_for_hw_mode_change(psoc, cm_req->candidate_list,
1115 					     vdev_id, cm_req->cm_id);
1116 	if (QDF_IS_STATUS_ERROR(status) && status != QDF_STATUS_E_ALREADY) {
1117 		reason = CM_HW_MODE_FAILURE;
1118 		mlme_err(CM_PREFIX_FMT "Failed to set HW mode change",
1119 			 CM_PREFIX_REF(vdev_id, cm_req->cm_id));
1120 		goto connect_err;
1121 	} else if (QDF_IS_STATUS_SUCCESS(status)) {
1122 		mlme_debug(CM_PREFIX_FMT "Connect will continue after HW mode change",
1123 			   CM_PREFIX_REF(vdev_id, cm_req->cm_id));
1124 		return QDF_STATUS_SUCCESS;
1125 	}
1126 
1127 	status = cm_ser_connect_req(pdev, cm_ctx, cm_req);
1128 	if (QDF_IS_STATUS_ERROR(status)) {
1129 		reason = CM_SER_FAILURE;
1130 		goto connect_err;
1131 	}
1132 
1133 	return QDF_STATUS_SUCCESS;
1134 
1135 connect_err:
1136 	return cm_send_connect_start_fail(cm_ctx, cm_req, reason);
1137 }
1138 
1139 /**
1140  * cm_get_valid_candidate() - This API will be called to get the next valid
1141  * candidate
1142  * @cm_ctx: connection manager context
1143  * @cm_req: Connect request.
1144  * @resp: connect resp from previous connection attempt
1145  * @same_candidate_used: this will be set if same candidate used
1146  *
1147  * This function return a valid candidate to try connection. It return failure
1148  * if no valid candidate is present or all valid candidate are tried.
1149  *
1150  * Return: QDF status
1151  */
1152 static QDF_STATUS cm_get_valid_candidate(struct cnx_mgr *cm_ctx,
1153 					 struct cm_req *cm_req,
1154 					 struct wlan_cm_connect_resp *resp,
1155 					 bool *same_candidate_used)
1156 {
1157 	struct scan_cache_node *scan_node = NULL;
1158 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1159 	struct scan_cache_node *new_candidate = NULL, *prev_candidate;
1160 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1161 	uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
1162 	bool use_same_candidate = false;
1163 
1164 	prev_candidate = cm_req->connect_req.cur_candidate;
1165 	if (cm_req->connect_req.connect_attempts >=
1166 	    cm_ctx->max_connect_attempts) {
1167 		mlme_info(CM_PREFIX_FMT "%d attempts tried, max %d",
1168 			  CM_PREFIX_REF(vdev_id, cm_req->cm_id),
1169 			  cm_req->connect_req.connect_attempts,
1170 			  cm_ctx->max_connect_attempts);
1171 		status = QDF_STATUS_E_FAILURE;
1172 		goto flush_single_pmk;
1173 	}
1174 
1175 	if (prev_candidate && resp &&
1176 	    cm_is_retry_with_same_candidate(cm_ctx, &cm_req->connect_req,
1177 					    resp)) {
1178 		new_candidate = prev_candidate;
1179 		use_same_candidate = true;
1180 		goto try_same_candidate;
1181 	}
1182 
1183 	/*
1184 	 * Get next candidate if prev_candidate is not NULL, else get
1185 	 * the first candidate
1186 	 */
1187 	if (prev_candidate)
1188 		qdf_list_peek_next(cm_req->connect_req.candidate_list,
1189 				   &prev_candidate->node, &cur_node);
1190 	else
1191 		qdf_list_peek_front(cm_req->connect_req.candidate_list,
1192 				    &cur_node);
1193 
1194 	while (cur_node) {
1195 		qdf_list_peek_next(cm_req->connect_req.candidate_list,
1196 				   cur_node, &next_node);
1197 		scan_node = qdf_container_of(cur_node, struct scan_cache_node,
1198 					     node);
1199 		status = cm_validate_candidate(cm_ctx, scan_node->entry);
1200 		if (QDF_IS_STATUS_SUCCESS(status)) {
1201 			new_candidate = scan_node;
1202 			break;
1203 		}
1204 
1205 		cur_node = next_node;
1206 		next_node = NULL;
1207 	}
1208 
1209 	/*
1210 	 * If cur_node is NULL prev candidate was last to be tried so no more
1211 	 * candidates left for connect now.
1212 	 */
1213 	if (!cur_node) {
1214 		mlme_debug(CM_PREFIX_FMT "No more candidates left",
1215 			   CM_PREFIX_REF(vdev_id, cm_req->cm_id));
1216 		cm_req->connect_req.cur_candidate = NULL;
1217 		status = QDF_STATUS_E_FAILURE;
1218 		goto flush_single_pmk;
1219 	}
1220 
1221 	/* Reset current candidate retries when a new candidate is tried */
1222 	cm_req->connect_req.cur_candidate_retries = 0;
1223 
1224 try_same_candidate:
1225 	cm_req->connect_req.connect_attempts++;
1226 	cm_req->connect_req.cur_candidate = new_candidate;
1227 
1228 flush_single_pmk:
1229 	/*
1230 	 * If connection fails with Single PMK bssid (prev candidate),
1231 	 * clear the pmk entry. Flush only in case if we are not trying again
1232 	 * with same candidate again.
1233 	 */
1234 	if (prev_candidate && !use_same_candidate &&
1235 	    util_scan_entry_single_pmk(prev_candidate->entry))
1236 		cm_delete_pmksa_for_single_pmk_bssid(cm_ctx,
1237 						&prev_candidate->entry->bssid);
1238 
1239 	if (same_candidate_used)
1240 		*same_candidate_used = use_same_candidate;
1241 
1242 	return status;
1243 }
1244 
1245 static void cm_create_bss_peer(struct cnx_mgr *cm_ctx,
1246 			       struct cm_connect_req *req)
1247 {
1248 	QDF_STATUS status;
1249 	struct qdf_mac_addr *bssid;
1250 
1251 	bssid = &req->cur_candidate->entry->bssid;
1252 	status = mlme_cm_bss_peer_create_req(cm_ctx->vdev, bssid);
1253 	if (QDF_IS_STATUS_ERROR(status)) {
1254 		struct wlan_cm_connect_resp *resp;
1255 		uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
1256 
1257 		/* In case of failure try with next candidate */
1258 		mlme_err(CM_PREFIX_FMT "peer create request failed %d",
1259 			 CM_PREFIX_REF(vdev_id, req->cm_id), status);
1260 
1261 		resp = qdf_mem_malloc(sizeof(*resp));
1262 		if (!resp)
1263 			return;
1264 
1265 		cm_fill_failure_resp_from_cm_id(cm_ctx, resp, req->cm_id,
1266 						CM_PEER_CREATE_FAILED);
1267 		cm_sm_deliver_event_sync(cm_ctx,
1268 				WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
1269 				sizeof(*resp), resp);
1270 		qdf_mem_free(resp);
1271 	}
1272 }
1273 
1274 static QDF_STATUS
1275 cm_send_bss_select_ind(struct cnx_mgr *cm_ctx, struct cm_connect_req *req)
1276 {
1277 	QDF_STATUS status;
1278 	struct wlan_cm_vdev_connect_req vdev_req;
1279 	struct wlan_cm_connect_resp *resp;
1280 
1281 	vdev_req.vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
1282 	vdev_req.cm_id = req->cm_id;
1283 	vdev_req.bss = req->cur_candidate;
1284 
1285 	status = mlme_cm_bss_select_ind(cm_ctx->vdev, &vdev_req);
1286 	if (QDF_IS_STATUS_SUCCESS(status) ||
1287 	    status == QDF_STATUS_E_NOSUPPORT)
1288 		return status;
1289 
1290 	/* In supported and failure try with next candidate */
1291 	mlme_err(CM_PREFIX_FMT "mlme candidate select indication failed %d",
1292 		 CM_PREFIX_REF(vdev_req.vdev_id, req->cm_id), status);
1293 	resp = qdf_mem_malloc(sizeof(*resp));
1294 	if (!resp)
1295 		return QDF_STATUS_E_FAILURE;
1296 
1297 	cm_fill_failure_resp_from_cm_id(cm_ctx, resp, req->cm_id,
1298 					CM_BSS_SELECT_IND_FAILED);
1299 	cm_sm_deliver_event_sync(cm_ctx,
1300 				 WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
1301 				 sizeof(*resp), resp);
1302 	qdf_mem_free(resp);
1303 
1304 	return QDF_STATUS_SUCCESS;
1305 }
1306 
1307 QDF_STATUS cm_try_next_candidate(struct cnx_mgr *cm_ctx,
1308 				 struct wlan_cm_connect_resp *resp)
1309 {
1310 	QDF_STATUS status;
1311 	struct cm_req *cm_req;
1312 	bool same_candidate_used = false;
1313 
1314 	cm_req = cm_get_req_by_cm_id(cm_ctx, resp->cm_id);
1315 	if (!cm_req)
1316 		return QDF_STATUS_E_FAILURE;
1317 
1318 	status = cm_get_valid_candidate(cm_ctx, cm_req, resp,
1319 					&same_candidate_used);
1320 	if (QDF_IS_STATUS_ERROR(status))
1321 		goto connect_err;
1322 
1323 	/*
1324 	 * Do not indicate to OSIF if same candidate is used again as we are not
1325 	 * done with this candidate. So inform once we move to next candidate.
1326 	 * This will also avoid flush for the scan entry.
1327 	 */
1328 	if (!same_candidate_used)
1329 		mlme_cm_osif_failed_candidate_ind(cm_ctx->vdev, resp);
1330 
1331 	status = cm_send_bss_select_ind(cm_ctx, &cm_req->connect_req);
1332 	/*
1333 	 * If candidate select indication is not supported continue with bss
1334 	 * peer create, else peer will be created after resp.
1335 	 */
1336 	if (status == QDF_STATUS_E_NOSUPPORT)
1337 		cm_create_bss_peer(cm_ctx, &cm_req->connect_req);
1338 	else if (QDF_IS_STATUS_ERROR(status))
1339 		goto connect_err;
1340 
1341 	return QDF_STATUS_SUCCESS;
1342 
1343 connect_err:
1344 	return cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_CONNECT_FAILURE,
1345 					sizeof(*resp), resp);
1346 
1347 }
1348 
1349 bool cm_connect_resp_cmid_match_list_head(struct cnx_mgr *cm_ctx,
1350 					  struct wlan_cm_connect_resp *resp)
1351 {
1352 	return cm_check_cmid_match_list_head(cm_ctx, &resp->cm_id);
1353 }
1354 
1355 static void cm_fill_vdev_crypto_params(struct cnx_mgr *cm_ctx,
1356 				       struct wlan_cm_connect_req *req)
1357 {
1358 	/* fill vdev crypto from the connect req */
1359 	wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_AUTH_MODE,
1360 				   req->crypto.auth_type);
1361 	wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT,
1362 				   req->crypto.akm_suites);
1363 	wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_UCAST_CIPHER,
1364 				   req->crypto.ciphers_pairwise);
1365 	wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_MCAST_CIPHER,
1366 				   req->crypto.group_cipher);
1367 	wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_MGMT_CIPHER,
1368 				   req->crypto.mgmt_ciphers);
1369 	wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_RSN_CAP,
1370 				   req->crypto.rsn_caps);
1371 }
1372 
1373 QDF_STATUS cm_connect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
1374 {
1375 	struct cm_req *cm_req;
1376 	QDF_STATUS status;
1377 	struct wlan_cm_connect_req *req;
1378 
1379 	cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id);
1380 	if (!cm_req)
1381 		return QDF_STATUS_E_INVAL;
1382 
1383 	cm_ctx->active_cm_id = *cm_id;
1384 	req = &cm_req->connect_req.req;
1385 	wlan_vdev_mlme_set_ssid(cm_ctx->vdev, req->ssid.ssid, req->ssid.length);
1386 	cm_fill_vdev_crypto_params(cm_ctx, req);
1387 	cm_store_wep_key(cm_ctx, &req->crypto, *cm_id);
1388 
1389 	status = cm_get_valid_candidate(cm_ctx, cm_req, NULL, NULL);
1390 	if (QDF_IS_STATUS_ERROR(status))
1391 		goto connect_err;
1392 
1393 	status = cm_send_bss_select_ind(cm_ctx, &cm_req->connect_req);
1394 	/*
1395 	 * If candidate select indication is not supported continue with bss
1396 	 * peer create, else peer will be created after resp.
1397 	 */
1398 	if (status == QDF_STATUS_E_NOSUPPORT)
1399 		cm_create_bss_peer(cm_ctx, &cm_req->connect_req);
1400 	else if (QDF_IS_STATUS_ERROR(status))
1401 		goto connect_err;
1402 
1403 	return QDF_STATUS_SUCCESS;
1404 
1405 connect_err:
1406 	return cm_send_connect_start_fail(cm_ctx,
1407 					  &cm_req->connect_req, CM_JOIN_FAILED);
1408 }
1409 
1410 QDF_STATUS
1411 cm_peer_create_on_bss_select_ind_resp(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
1412 {
1413 	struct cm_req *cm_req;
1414 
1415 	cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id);
1416 	if (!cm_req)
1417 		return QDF_STATUS_E_FAILURE;
1418 
1419 	cm_create_bss_peer(cm_ctx, &cm_req->connect_req);
1420 
1421 	return QDF_STATUS_SUCCESS;
1422 }
1423 
1424 #ifdef WLAN_FEATURE_FILS_SK
1425 static void cm_copy_fils_info(struct wlan_cm_vdev_connect_req *req,
1426 			      struct cm_req *cm_req)
1427 {
1428 	req->fils_info = &cm_req->connect_req.req.fils_info;
1429 }
1430 #else
1431 static inline void cm_copy_fils_info(struct wlan_cm_vdev_connect_req *req,
1432 				     struct cm_req *cm_req)
1433 {
1434 }
1435 #endif
1436 
1437 QDF_STATUS
1438 cm_resume_connect_after_peer_create(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
1439 {
1440 	struct wlan_cm_vdev_connect_req req;
1441 	struct cm_req *cm_req;
1442 	QDF_STATUS status;
1443 	struct security_info *neg_sec_info;
1444 	uint16_t rsn_caps;
1445 	uint8_t country_code[REG_ALPHA2_LEN + 1];
1446 	struct wlan_objmgr_psoc *psoc;
1447 
1448 	psoc = wlan_pdev_get_psoc(wlan_vdev_get_pdev(cm_ctx->vdev));
1449 
1450 	cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id);
1451 	if (!cm_req)
1452 		return QDF_STATUS_E_FAILURE;
1453 
1454 	/*
1455 	 * Some non PMF AP misbehave if in assoc req RSN IE contain PMF capable
1456 	 * bit set. Thus only if AP and self are capable, try PMF connection
1457 	 * else set PMF as 0. The PMF filtering is already taken care in
1458 	 * get scan results.
1459 	 */
1460 	neg_sec_info = &cm_req->connect_req.cur_candidate->entry->neg_sec_info;
1461 	rsn_caps = cm_req->connect_req.req.crypto.rsn_caps;
1462 	if (!(neg_sec_info->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED &&
1463 	      rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)) {
1464 		rsn_caps &= ~WLAN_CRYPTO_RSN_CAP_MFP_ENABLED;
1465 		rsn_caps &= ~WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED;
1466 		rsn_caps &= ~WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED;
1467 		wlan_crypto_set_vdev_param(cm_ctx->vdev,
1468 					   WLAN_CRYPTO_PARAM_RSN_CAP,
1469 					   rsn_caps);
1470 	}
1471 
1472 	req.vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
1473 	req.cm_id = *cm_id;
1474 	req.force_rsne_override = cm_req->connect_req.req.force_rsne_override;
1475 	req.assoc_ie = cm_req->connect_req.req.assoc_ie;
1476 	req.scan_ie = cm_req->connect_req.req.scan_ie;
1477 	req.bss = cm_req->connect_req.cur_candidate;
1478 	cm_copy_fils_info(&req, cm_req);
1479 	req.ht_caps = cm_req->connect_req.req.ht_caps;
1480 	req.ht_caps_mask = cm_req->connect_req.req.ht_caps_mask;
1481 	req.vht_caps = cm_req->connect_req.req.vht_caps;
1482 	req.vht_caps_mask = cm_req->connect_req.req.vht_caps_mask;
1483 
1484 	wlan_reg_get_cc_and_src(psoc, country_code);
1485 	mlme_nofl_info(CM_PREFIX_FMT "Connecting to %.*s " QDF_MAC_ADDR_FMT " rssi: %d freq: %d akm 0x%x cipher: uc 0x%x mc 0x%x, CC: %c%c",
1486 		       CM_PREFIX_REF(req.vdev_id, req.cm_id),
1487 		       cm_req->connect_req.req.ssid.length,
1488 		       cm_req->connect_req.req.ssid.ssid,
1489 		       QDF_MAC_ADDR_REF(req.bss->entry->bssid.bytes),
1490 		       req.bss->entry->rssi_raw,
1491 		       req.bss->entry->channel.chan_freq,
1492 		       neg_sec_info->key_mgmt, neg_sec_info->ucastcipherset,
1493 		       neg_sec_info->mcastcipherset, country_code[0],
1494 		       country_code[1]);
1495 
1496 	status = mlme_cm_connect_req(cm_ctx->vdev, &req);
1497 	if (QDF_IS_STATUS_ERROR(status)) {
1498 		mlme_err(CM_PREFIX_FMT "connect request failed",
1499 			 CM_PREFIX_REF(req.vdev_id, req.cm_id));
1500 		status = cm_send_connect_start_fail(cm_ctx,
1501 						    &cm_req->connect_req,
1502 						    CM_JOIN_FAILED);
1503 	}
1504 
1505 	return status;
1506 }
1507 
1508 /**
1509  * cm_update_scan_db_on_connect_success() - update scan db with beacon or
1510  * probe resp
1511  * @cm_ctx: connection manager context
1512  * @resp: connect resp
1513  *
1514  * update scan db, so that kernel and driver do not age out
1515  * the connected AP entry.
1516  *
1517  * Context: Can be called from any context and to be used only if connect
1518  * is successful and SM is in conencted state. i.e. SM lock is hold.
1519  *
1520  * Return: void
1521  */
1522 static void
1523 cm_update_scan_db_on_connect_success(struct cnx_mgr *cm_ctx,
1524 				     struct wlan_cm_connect_resp *resp)
1525 {
1526 	struct element_info *bcn_probe_rsp;
1527 	struct cm_req *cm_req;
1528 	int32_t rssi;
1529 
1530 	if (!cm_is_vdev_connected(cm_ctx->vdev))
1531 		return;
1532 
1533 	cm_req = cm_get_req_by_cm_id(cm_ctx, resp->cm_id);
1534 	if (!cm_req)
1535 		return;
1536 	if (!cm_req->connect_req.cur_candidate)
1537 		return;
1538 
1539 	/*
1540 	 * Get beacon or probe resp from connect response, and if not present
1541 	 * use cur candidate to get beacon or probe resp
1542 	 */
1543 	if (resp->connect_ies.bcn_probe_rsp.ptr)
1544 		bcn_probe_rsp = &resp->connect_ies.bcn_probe_rsp;
1545 	else
1546 		bcn_probe_rsp =
1547 			&cm_req->connect_req.cur_candidate->entry->raw_frame;
1548 
1549 	rssi = cm_req->connect_req.cur_candidate->entry->rssi_raw;
1550 
1551 	cm_inform_bcn_probe(cm_ctx, bcn_probe_rsp->ptr, bcn_probe_rsp->len,
1552 			    resp->freq, rssi, resp->cm_id);
1553 }
1554 
1555 QDF_STATUS cm_connect_complete(struct cnx_mgr *cm_ctx,
1556 			       struct wlan_cm_connect_resp *resp)
1557 {
1558 	enum wlan_cm_sm_state sm_state;
1559 	struct bss_info bss_info;
1560 	struct mlme_info mlme_info;
1561 
1562 	/*
1563 	 * If the entry is not present in the list, it must have been cleared
1564 	 * already.
1565 	 */
1566 	if (!cm_get_req_by_cm_id(cm_ctx, resp->cm_id))
1567 		return QDF_STATUS_SUCCESS;
1568 
1569 	sm_state = cm_get_state(cm_ctx);
1570 	if (QDF_IS_STATUS_SUCCESS(resp->connect_status) &&
1571 	    sm_state == WLAN_CM_S_CONNECTED) {
1572 		cm_update_scan_db_on_connect_success(cm_ctx, resp);
1573 		/* set WEP and FILS key on success */
1574 		cm_set_fils_wep_key(cm_ctx, resp);
1575 	}
1576 
1577 	mlme_cm_connect_complete_ind(cm_ctx->vdev, resp);
1578 	mlme_cm_osif_connect_complete(cm_ctx->vdev, resp);
1579 	cm_inform_if_mgr_connect_complete(cm_ctx->vdev, resp->connect_status);
1580 	cm_inform_blm_connect_complete(cm_ctx->vdev, resp);
1581 
1582 	/* Update scan entry in case connect is success or fails with bssid */
1583 	if (!qdf_is_macaddr_zero(&resp->bssid)) {
1584 		if (QDF_IS_STATUS_SUCCESS(resp->connect_status))
1585 			mlme_info.assoc_state  = SCAN_ENTRY_CON_STATE_ASSOC;
1586 		else
1587 			mlme_info.assoc_state = SCAN_ENTRY_CON_STATE_NONE;
1588 		qdf_copy_macaddr(&bss_info.bssid, &resp->bssid);
1589 		bss_info.freq = resp->freq;
1590 		bss_info.ssid.length = resp->ssid.length;
1591 		qdf_mem_copy(&bss_info.ssid.ssid, resp->ssid.ssid,
1592 			     bss_info.ssid.length);
1593 		wlan_scan_update_mlme_by_bssinfo(
1594 					wlan_vdev_get_pdev(cm_ctx->vdev),
1595 					&bss_info, &mlme_info);
1596 	}
1597 	/*
1598 	 * update fils/wep key and inform legacy, update bcn filter,
1599 	 * start OBSS scan for open mode.
1600 	 */
1601 
1602 	mlme_debug(CM_PREFIX_FMT,
1603 		   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
1604 				 resp->cm_id));
1605 	cm_remove_cmd(cm_ctx, resp->cm_id);
1606 
1607 	return QDF_STATUS_SUCCESS;
1608 }
1609 
1610 QDF_STATUS cm_add_connect_req_to_list(struct cnx_mgr *cm_ctx,
1611 				      struct cm_connect_req *req)
1612 {
1613 	QDF_STATUS status;
1614 	struct cm_req *cm_req;
1615 
1616 	cm_req = qdf_container_of(req, struct cm_req, connect_req);
1617 	req->cm_id = cm_get_cm_id(cm_ctx, req->req.source);
1618 	cm_req->cm_id = req->cm_id;
1619 	status = cm_add_req_to_list_and_indicate_osif(cm_ctx, cm_req,
1620 						      req->req.source);
1621 
1622 	return status;
1623 }
1624 
1625 QDF_STATUS cm_connect_rsp(struct wlan_objmgr_vdev *vdev,
1626 			  struct wlan_cm_connect_resp *resp)
1627 {
1628 	struct cnx_mgr *cm_ctx;
1629 	QDF_STATUS qdf_status;
1630 	wlan_cm_id cm_id;
1631 	uint32_t prefix;
1632 
1633 	cm_ctx = cm_get_cm_ctx(vdev);
1634 	if (!cm_ctx)
1635 		return QDF_STATUS_E_INVAL;
1636 
1637 	cm_id = cm_ctx->active_cm_id;
1638 	prefix = CM_ID_GET_PREFIX(cm_id);
1639 
1640 	if (prefix != CONNECT_REQ_PREFIX || cm_id != resp->cm_id) {
1641 		mlme_err(CM_PREFIX_FMT " Active cm_id 0x%x is different",
1642 			 CM_PREFIX_REF(wlan_vdev_get_id(vdev), resp->cm_id),
1643 			 cm_id);
1644 		qdf_status = QDF_STATUS_E_FAILURE;
1645 		goto post_err;
1646 	}
1647 
1648 	if (QDF_IS_STATUS_SUCCESS(resp->connect_status)) {
1649 		/*
1650 		 * On successful connection to sae single pmk AP,
1651 		 * clear all the single pmk AP.
1652 		 */
1653 		if (cm_is_cm_id_current_candidate_single_pmk(cm_ctx, cm_id))
1654 			wlan_crypto_selective_clear_sae_single_pmk_entries(vdev,
1655 								&resp->bssid);
1656 		qdf_status =
1657 			cm_sm_deliver_event(vdev,
1658 					    WLAN_CM_SM_EV_CONNECT_SUCCESS,
1659 					    sizeof(*resp), resp);
1660 		if (QDF_IS_STATUS_SUCCESS(qdf_status))
1661 			return qdf_status;
1662 		/*
1663 		 * failure mean that the new connect/disconnect is received so
1664 		 * cleanup.
1665 		 */
1666 		goto post_err;
1667 	}
1668 
1669 	/*
1670 	 * Delete the PMKID of the BSSID for which the assoc reject is
1671 	 * received from the AP due to invalid PMKID reason.
1672 	 * This will avoid the driver trying to connect to same AP with
1673 	 * the same stale PMKID. when connection is tried again with this AP.
1674 	 */
1675 	if (resp->status_code == STATUS_INVALID_PMKID)
1676 		cm_delete_pmksa_for_bssid(cm_ctx, &resp->bssid);
1677 
1678 	/* In case of failure try with next candidate */
1679 	qdf_status =
1680 		cm_sm_deliver_event(vdev,
1681 				    WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
1682 				    sizeof(*resp), resp);
1683 
1684 	if (QDF_IS_STATUS_SUCCESS(qdf_status))
1685 		return qdf_status;
1686 	/*
1687 	 * If connection fails with Single PMK bssid, clear this pmk
1688 	 * entry in case of post failure.
1689 	 */
1690 	if (cm_is_cm_id_current_candidate_single_pmk(cm_ctx, cm_id))
1691 		cm_delete_pmksa_for_single_pmk_bssid(cm_ctx, &resp->bssid);
1692 post_err:
1693 	/*
1694 	 * If there is a event posting error it means the SM state is not in
1695 	 * JOIN ACTIVE (some new cmd has changed the state of SM), so just
1696 	 * complete the connect command.
1697 	 */
1698 	cm_connect_complete(cm_ctx, resp);
1699 
1700 	return qdf_status;
1701 }
1702 
1703 QDF_STATUS cm_bss_select_ind_rsp(struct wlan_objmgr_vdev *vdev,
1704 				 QDF_STATUS status)
1705 {
1706 	struct cnx_mgr *cm_ctx;
1707 	QDF_STATUS qdf_status;
1708 	wlan_cm_id cm_id;
1709 	uint32_t prefix;
1710 	struct wlan_cm_connect_resp *resp;
1711 
1712 	cm_ctx = cm_get_cm_ctx(vdev);
1713 	if (!cm_ctx)
1714 		return QDF_STATUS_E_INVAL;
1715 
1716 	cm_id = cm_ctx->active_cm_id;
1717 	prefix = CM_ID_GET_PREFIX(cm_id);
1718 
1719 	if (prefix != CONNECT_REQ_PREFIX) {
1720 		mlme_err(CM_PREFIX_FMT "active req is not connect req",
1721 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id));
1722 		return QDF_STATUS_E_INVAL;
1723 	}
1724 
1725 	if (QDF_IS_STATUS_SUCCESS(status)) {
1726 		qdf_status =
1727 			cm_sm_deliver_event(vdev,
1728 				WLAN_CM_SM_EV_BSS_SELECT_IND_SUCCESS,
1729 				sizeof(wlan_cm_id), &cm_id);
1730 		if (QDF_IS_STATUS_SUCCESS(qdf_status))
1731 			return qdf_status;
1732 
1733 		goto post_err;
1734 	}
1735 
1736 	/* In case of failure try with next candidate */
1737 	resp = qdf_mem_malloc(sizeof(*resp));
1738 	if (!resp) {
1739 		qdf_status = QDF_STATUS_E_NOMEM;
1740 		goto post_err;
1741 	}
1742 
1743 	cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id,
1744 					CM_BSS_SELECT_IND_FAILED);
1745 	qdf_status =
1746 		cm_sm_deliver_event(vdev,
1747 				    WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
1748 				    sizeof(*resp), resp);
1749 	qdf_mem_free(resp);
1750 	if (QDF_IS_STATUS_SUCCESS(qdf_status))
1751 		return qdf_status;
1752 
1753 post_err:
1754 	/*
1755 	 * If there is a event posting error it means the SM state is not in
1756 	 * JOIN ACTIVE (some new cmd has changed the state of SM), so just
1757 	 * complete the connect command.
1758 	 */
1759 	cm_connect_handle_event_post_fail(cm_ctx, cm_id);
1760 	return qdf_status;
1761 }
1762 
1763 QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
1764 				  QDF_STATUS status,
1765 				  struct qdf_mac_addr *peer_mac)
1766 {
1767 	struct cnx_mgr *cm_ctx;
1768 	QDF_STATUS qdf_status;
1769 	wlan_cm_id cm_id;
1770 	uint32_t prefix;
1771 	struct wlan_cm_connect_resp *resp;
1772 
1773 	cm_ctx = cm_get_cm_ctx(vdev);
1774 	if (!cm_ctx)
1775 		return QDF_STATUS_E_INVAL;
1776 
1777 	cm_id = cm_ctx->active_cm_id;
1778 	prefix = CM_ID_GET_PREFIX(cm_id);
1779 
1780 	if (prefix != CONNECT_REQ_PREFIX) {
1781 		mlme_err(CM_PREFIX_FMT "active req is not connect req",
1782 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id));
1783 		mlme_cm_bss_peer_delete_req(vdev);
1784 		return QDF_STATUS_E_INVAL;
1785 	}
1786 
1787 	if (QDF_IS_STATUS_SUCCESS(status)) {
1788 		qdf_status =
1789 			cm_sm_deliver_event(vdev,
1790 					  WLAN_CM_SM_EV_BSS_CREATE_PEER_SUCCESS,
1791 					  sizeof(wlan_cm_id), &cm_id);
1792 		if (QDF_IS_STATUS_SUCCESS(qdf_status))
1793 			return qdf_status;
1794 
1795 		mlme_cm_bss_peer_delete_req(vdev);
1796 		goto post_err;
1797 	}
1798 
1799 	/* In case of failure try with next candidate */
1800 	resp = qdf_mem_malloc(sizeof(*resp));
1801 	if (!resp) {
1802 		qdf_status = QDF_STATUS_E_NOMEM;
1803 		goto post_err;
1804 	}
1805 
1806 	cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id,
1807 					CM_PEER_CREATE_FAILED);
1808 	qdf_status =
1809 		cm_sm_deliver_event(vdev,
1810 				    WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
1811 				    sizeof(*resp), resp);
1812 	qdf_mem_free(resp);
1813 	if (QDF_IS_STATUS_SUCCESS(qdf_status))
1814 		return qdf_status;
1815 
1816 post_err:
1817 	/*
1818 	 * If there is a event posting error it means the SM state is not in
1819 	 * JOIN ACTIVE (some new cmd has changed the state of SM), so just
1820 	 * complete the connect command.
1821 	 */
1822 	cm_connect_handle_event_post_fail(cm_ctx, cm_id);
1823 	return qdf_status;
1824 }
1825 
1826 static void
1827 cm_copy_crypto_prarams(struct wlan_cm_connect_crypto_info *dst_params,
1828 		       struct wlan_crypto_params  *src_params)
1829 {
1830 	dst_params->akm_suites = src_params->key_mgmt;
1831 	dst_params->auth_type = src_params->authmodeset;
1832 	dst_params->ciphers_pairwise = src_params->ucastcipherset;
1833 	dst_params->group_cipher = src_params->mcastcipherset;
1834 	dst_params->mgmt_ciphers = src_params->mgmtcipherset;
1835 	dst_params->rsn_caps = src_params->rsn_caps;
1836 }
1837 
1838 static void
1839 cm_set_crypto_params_from_ie(struct wlan_cm_connect_req *req)
1840 {
1841 	struct wlan_crypto_params crypto_params;
1842 	QDF_STATUS status;
1843 
1844 	if (!req->assoc_ie.ptr)
1845 		return;
1846 
1847 	status = wlan_get_crypto_params_from_rsn_ie(&crypto_params,
1848 						    req->assoc_ie.ptr,
1849 						    req->assoc_ie.len);
1850 	if (QDF_IS_STATUS_SUCCESS(status)) {
1851 		cm_copy_crypto_prarams(&req->crypto, &crypto_params);
1852 		return;
1853 	}
1854 
1855 	status = wlan_get_crypto_params_from_wpa_ie(&crypto_params,
1856 						    req->assoc_ie.ptr,
1857 						    req->assoc_ie.len);
1858 	if (QDF_IS_STATUS_SUCCESS(status)) {
1859 		cm_copy_crypto_prarams(&req->crypto, &crypto_params);
1860 		return;
1861 	}
1862 
1863 	status = wlan_get_crypto_params_from_wapi_ie(&crypto_params,
1864 						     req->assoc_ie.ptr,
1865 						     req->assoc_ie.len);
1866 	if (QDF_IS_STATUS_SUCCESS(status))
1867 		cm_copy_crypto_prarams(&req->crypto, &crypto_params);
1868 }
1869 
1870 static QDF_STATUS
1871 cm_allocate_and_copy_ies_and_keys(struct wlan_cm_connect_req *target,
1872 				  struct wlan_cm_connect_req *source)
1873 {
1874 	/* Reset the copied pointers of target */
1875 	source->assoc_ie.ptr = NULL;
1876 	source->crypto.wep_keys.key = NULL;
1877 	source->crypto.wep_keys.seq = NULL;
1878 	source->scan_ie.ptr = NULL;
1879 
1880 	if (source->scan_ie.ptr) {
1881 		target->scan_ie.ptr = qdf_mem_malloc(source->scan_ie.len);
1882 		if (!target->scan_ie.ptr)
1883 			target->scan_ie.len = 0;
1884 		else
1885 			qdf_mem_copy(target->scan_ie.ptr,
1886 				     source->scan_ie.ptr, source->scan_ie.len);
1887 	}
1888 
1889 	if (source->assoc_ie.ptr) {
1890 		target->assoc_ie.ptr = qdf_mem_malloc(source->assoc_ie.len);
1891 		if (!target->assoc_ie.ptr)
1892 			return QDF_STATUS_E_NOMEM;
1893 
1894 		qdf_mem_copy(target->assoc_ie.ptr, source->assoc_ie.ptr,
1895 			     source->assoc_ie.len);
1896 	}
1897 
1898 	if (source->crypto.wep_keys.key) {
1899 		target->crypto.wep_keys.key =
1900 			qdf_mem_malloc(source->crypto.wep_keys.key_len);
1901 		if (!target->crypto.wep_keys.key)
1902 			return QDF_STATUS_E_NOMEM;
1903 
1904 		qdf_mem_copy(target->crypto.wep_keys.key,
1905 			     source->crypto.wep_keys.key,
1906 			     source->crypto.wep_keys.key_len);
1907 	}
1908 
1909 	if (source->crypto.wep_keys.seq) {
1910 		target->crypto.wep_keys.seq =
1911 			qdf_mem_malloc(source->crypto.wep_keys.seq_len);
1912 		if (!target->crypto.wep_keys.seq)
1913 			return QDF_STATUS_E_NOMEM;
1914 
1915 		qdf_mem_copy(target->crypto.wep_keys.seq,
1916 			     source->crypto.wep_keys.seq,
1917 			     source->crypto.wep_keys.seq_len);
1918 	}
1919 
1920 	return QDF_STATUS_SUCCESS;
1921 }
1922 
1923 QDF_STATUS cm_connect_start_req(struct wlan_objmgr_vdev *vdev,
1924 				struct wlan_cm_connect_req *req)
1925 {
1926 	struct cnx_mgr *cm_ctx;
1927 	struct cm_req *cm_req;
1928 	struct cm_connect_req *connect_req;
1929 	QDF_STATUS status;
1930 
1931 	cm_ctx = cm_get_cm_ctx(vdev);
1932 	if (!cm_ctx)
1933 		return QDF_STATUS_E_INVAL;
1934 
1935 	cm_vdev_scan_cancel(wlan_vdev_get_pdev(cm_ctx->vdev), cm_ctx->vdev);
1936 
1937 	/*
1938 	 * This would be freed as part of removal from cm req list if adding
1939 	 * to list is success after posting WLAN_CM_SM_EV_CONNECT_REQ.
1940 	 */
1941 	cm_req = qdf_mem_malloc(sizeof(*cm_req));
1942 	if (!cm_req)
1943 		return QDF_STATUS_E_NOMEM;
1944 
1945 	connect_req = &cm_req->connect_req;
1946 	connect_req->req = *req;
1947 
1948 	status = cm_allocate_and_copy_ies_and_keys(&connect_req->req, req);
1949 	if (QDF_IS_STATUS_ERROR(status))
1950 		goto err;
1951 
1952 	cm_set_crypto_params_from_ie(&connect_req->req);
1953 
1954 	status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_CONNECT_REQ,
1955 				     sizeof(*connect_req), connect_req);
1956 
1957 err:
1958 	/* free the req if connect is not handled */
1959 	if (QDF_IS_STATUS_ERROR(status)) {
1960 		cm_free_connect_req_mem(connect_req);
1961 		qdf_mem_free(cm_req);
1962 	}
1963 
1964 	return status;
1965 }
1966