Jelajahi Sumber

qcacmn: Add host roam preauth handling code for connection manager

Add host roam preauth handling code for connection manager

Change-Id: Ie2ee72bb33fe5706349d1eb13208a0cfcd15aacf
CRs-Fixed: 2954506
Huashan Qu 4 tahun lalu
induk
melakukan
3493643d20

+ 44 - 0
os_if/linux/mlme/inc/osif_cm_util.h

@@ -257,6 +257,40 @@ void osif_cm_unlink_bss(struct wlan_objmgr_vdev *vdev,
 			uint8_t *ssid, uint8_t ssid_len) {}
 #endif
 
+#ifdef WLAN_FEATURE_PREAUTH_ENABLE
+/**
+ * typedef osif_cm_ft_preauth_complete_cb: Callback to send fast
+ * transition event
+ * @vdev: vdev pointer
+ * @rsp: preauth response pointer
+ *
+ * This callback indicates legacy modules to send fast transition event
+ *
+ * Context: Any context.
+ * Return: QDF_STATUS
+ */
+typedef QDF_STATUS
+	(*osif_cm_ft_preauth_complete_cb)(struct wlan_objmgr_vdev *vdev,
+					  struct wlan_preauth_rsp *rsp);
+#ifdef FEATURE_WLAN_ESE
+/**
+ * typedef osif_cm_cckm_preauth_complete_cb: Callback to send cckm preauth
+ * indication to the supplicant via wireless custom event
+ * @vdev: vdev pointer
+ * @rsp: preauth response pointer
+ *
+ * This callback indicates legacy modules to send cckm preauth indication
+ * to the supplicant via wireless custom event
+ *
+ * Context: Any context.
+ * Return: QDF_STATUS
+ */
+typedef QDF_STATUS
+	(*osif_cm_cckm_preauth_complete_cb)(struct wlan_objmgr_vdev *vdev,
+					    struct wlan_preauth_rsp *rsp);
+#endif
+#endif
+
 /**
  * osif_cm_ops: connection manager legacy callbacks
  * @osif_cm_connect_comp_cb: callback for connect complete to legacy
@@ -269,6 +303,10 @@ void osif_cm_unlink_bss(struct wlan_objmgr_vdev *vdev,
  * actions on napi serialization
  * @save_gtk_cb : callback to legacy module to save gtk
  * @set_hlp_data_cb: callback to legacy module to save hlp data
+ * @ft_preauth_complete_cb: callback to legacy module to send fast
+ * transition event
+ * @cckm_preauth_complete_cb: callback to legacy module to send cckm
+ * preauth indication to the supplicant via wireless custom event.
  */
 struct osif_cm_ops {
 	osif_cm_connect_comp_cb connect_complete_cb;
@@ -281,6 +319,12 @@ struct osif_cm_ops {
 #ifdef WLAN_FEATURE_FILS_SK
 	osif_cm_set_hlp_data_cb set_hlp_data_cb;
 #endif
+#ifdef WLAN_FEATURE_PREAUTH_ENABLE
+	osif_cm_ft_preauth_complete_cb ft_preauth_complete_cb;
+#ifdef FEATURE_WLAN_ESE
+	osif_cm_cckm_preauth_complete_cb cckm_preauth_complete_cb;
+#endif
+#endif
 };
 
 /**

+ 30 - 5
os_if/linux/mlme/src/osif_cm_roam_rsp.c

@@ -386,7 +386,6 @@ void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
 	struct cfg80211_bss *bss;
 	struct ieee80211_channel *chan;
 	struct wlan_objmgr_psoc *psoc;
-	bool roam_offload = false;
 
 	if (QDF_IS_STATUS_ERROR(rsp->connect_status))
 		return;
@@ -395,8 +394,6 @@ void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
 	if (!psoc)
 		return;
 
-	ucfg_mlme_is_roam_scan_offload_enabled(psoc, &roam_offload);
-
 	chan = ieee80211_get_channel(osif_priv->wdev->wiphy,
 				     rsp->freq);
 	bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan,
@@ -404,7 +401,7 @@ void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
 				    rsp->ssid.length);
 	if (!bss)
 		osif_warn("not able to find bss");
-	if (!roam_offload || rsp->is_ft)
+	if (rsp->is_ft)
 		osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
 					      &req_len, &req_ie);
 	else
@@ -418,4 +415,32 @@ void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
 
 	osif_update_fils_hlp_data(dev, vdev, rsp);
 }
-#endif
+
+QDF_STATUS
+osif_pmksa_candidate_notify(struct wlan_objmgr_vdev *vdev,
+			    struct qdf_mac_addr *bssid,
+			    int index, bool preauth)
+{
+	struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev);
+	struct wireless_dev *wdev;
+
+	if (!osif_priv) {
+		osif_err("Invalid vdev osif priv");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	wdev = osif_priv->wdev;
+	if (!wdev) {
+		osif_err("wdev is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	osif_debug("is going to notify supplicant of:");
+	osif_info(QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(bssid->bytes));
+
+	cfg80211_pmksa_candidate_notify(wdev->netdev, index,
+					bssid->bytes,
+					preauth, GFP_KERNEL);
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* CONN_MGR_ADV_FEATURE */

+ 14 - 0
os_if/linux/mlme/src/osif_cm_rsp.h

@@ -97,6 +97,20 @@ QDF_STATUS osif_connect_handler(struct wlan_objmgr_vdev *vdev,
 void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
 				   struct vdev_osif_priv *osif_priv,
 				   struct wlan_cm_connect_resp *rsp);
+
+/**
+ * @osif_pmksa_candidate_notify_cb: Roam pmksa candidate notify callback
+ * @vdev: vdev pointer
+ * @bssid: bssid
+ * @index: index
+ * @preauth: preauth flag
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+osif_pmksa_candidate_notify(struct wlan_objmgr_vdev *vdev,
+			    struct qdf_mac_addr *bssid,
+			    int index, bool preauth);
 #else
 static inline void
 osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,

+ 96 - 14
os_if/linux/mlme/src/osif_cm_util.c

@@ -289,6 +289,41 @@ osif_cm_disable_netif_queue(struct wlan_objmgr_vdev *vdev)
 				       WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
 				       WLAN_CONTROL_PATH);
 }
+
+/**
+ * osif_cm_roam_sync_cb() - Roam sync callback
+ * @vdev: vdev pointer
+ *
+ * This callback indicates os_if that roam sync ind received
+ * so that os_if can stop all the activity on this connection
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+osif_cm_roam_sync_cb(struct wlan_objmgr_vdev *vdev)
+{
+	osif_cm_napi_serialize(true);
+	return osif_cm_netif_queue_ind(vdev,
+				       WLAN_STOP_ALL_NETIF_QUEUE,
+				       WLAN_CONTROL_PATH);
+}
+
+/**
+ * @osif_pmksa_candidate_notify_cb: Roam pmksa candidate notify callback
+ * @vdev: vdev pointer
+ * @bssid: bssid
+ * @index: index
+ * @preauth: preauth flag
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+osif_pmksa_candidate_notify_cb(struct wlan_objmgr_vdev *vdev,
+			       struct qdf_mac_addr *bssid,
+			       int index, bool preauth)
+{
+	return osif_pmksa_candidate_notify(vdev, bssid, index, preauth);
+}
 #else
 static inline QDF_STATUS
 osif_cm_disable_netif_queue(struct wlan_objmgr_vdev *vdev)
@@ -350,40 +385,78 @@ osif_cm_roam_abort_cb(struct wlan_objmgr_vdev *vdev)
 }
 
 /**
- * osif_cm_roam_sync_cb() - Roam sync callback
+ * osif_cm_roam_cmpl_cb() - Roam sync complete callback
  * @vdev: vdev pointer
+ * @rsp: connect rsp
  *
- * This callback indicates os_if that roam sync ind received
+ * This callback indicates os_if that roam sync is complete
  * so that os_if can stop all the activity on this connection
  *
  * Return: QDF_STATUS
  */
 
 static QDF_STATUS
-osif_cm_roam_sync_cb(struct wlan_objmgr_vdev *vdev)
+osif_cm_roam_cmpl_cb(struct wlan_objmgr_vdev *vdev)
 {
-	osif_cm_napi_serialize(true);
-	return osif_cm_netif_queue_ind(vdev,
-				       WLAN_STOP_ALL_NETIF_QUEUE,
-				       WLAN_CONTROL_PATH);
+	return osif_cm_napi_serialize(false);
 }
+#endif
 
+#ifdef WLAN_FEATURE_PREAUTH_ENABLE
 /**
- * osif_cm_roam_cmpl_cb() - Roam sync complete callback
+ * osif_cm_ft_preauth_cmpl_cb() - Roam ft preauth complete callback
  * @vdev: vdev pointer
- * @rsp: connect rsp
+ * @rsp: preauth response
  *
- * This callback indicates os_if that roam sync is complete
- * so that os_if can stop all the activity on this connection
+ * This callback indicates os_if that roam ft preauth is complete
+ * so that os_if can send fast transition event
  *
  * Return: QDF_STATUS
  */
 
 static QDF_STATUS
-osif_cm_roam_cmpl_cb(struct wlan_objmgr_vdev *vdev)
+osif_cm_ft_preauth_cmpl_cb(struct wlan_objmgr_vdev *vdev,
+			   struct wlan_preauth_rsp *rsp)
 {
-	return osif_cm_napi_serialize(false);
+	osif_cm_ft_preauth_complete_cb cb = NULL;
+	QDF_STATUS ret = QDF_STATUS_SUCCESS;
+
+	if (osif_cm_legacy_ops)
+		cb = osif_cm_legacy_ops->ft_preauth_complete_cb;
+	if (cb)
+		ret = cb(vdev, rsp);
+
+	return ret;
 }
+
+#ifdef FEATURE_WLAN_ESE
+/**
+ * osif_cm_cckm_preauth_cmpl_cb() - Roam cckm preauth complete callback
+ * @vdev: vdev pointer
+ * @rsp: preauth response
+ *
+ * This callback indicates os_if that roam cckm preauth is complete
+ * so that os_if can send cckm preauth indication to the supplicant
+ * via wireless custom event.
+ *
+ * Return: QDF_STATUS
+ */
+
+static QDF_STATUS
+osif_cm_cckm_preauth_cmpl_cb(struct wlan_objmgr_vdev *vdev,
+			     struct wlan_preauth_rsp *rsp)
+{
+	osif_cm_cckm_preauth_complete_cb cb = NULL;
+	QDF_STATUS ret = QDF_STATUS_SUCCESS;
+
+	if (osif_cm_legacy_ops)
+		cb = osif_cm_legacy_ops->cckm_preauth_complete_cb;
+	if (cb)
+		ret = cb(vdev, rsp);
+
+	return ret;
+}
+#endif
 #endif
 
 static struct mlme_cm_ops cm_ops = {
@@ -392,12 +465,21 @@ static struct mlme_cm_ops cm_ops = {
 	.mlme_cm_update_id_and_src_cb = osif_cm_update_id_and_src_cb,
 	.mlme_cm_disconnect_complete_cb = osif_cm_disconnect_complete_cb,
 	.mlme_cm_disconnect_start_cb = osif_cm_disconnect_start_cb,
+#ifdef CONN_MGR_ADV_FEATURE
+	.mlme_cm_roam_sync_cb = osif_cm_roam_sync_cb,
+	.mlme_cm_pmksa_candidate_notify_cb = osif_pmksa_candidate_notify_cb,
+#endif
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 	.mlme_cm_roam_start_cb = osif_cm_roam_start_cb,
 	.mlme_cm_roam_abort_cb = osif_cm_roam_abort_cb,
-	.mlme_cm_roam_sync_cb = osif_cm_roam_sync_cb,
 	.mlme_cm_roam_cmpl_cb = osif_cm_roam_cmpl_cb,
 #endif
+#ifdef WLAN_FEATURE_PREAUTH_ENABLE
+	.mlme_cm_ft_preauth_cmpl_cb = osif_cm_ft_preauth_cmpl_cb,
+#ifdef FEATURE_WLAN_ESE
+	.mlme_cm_cckm_preauth_cmpl_cb = osif_cm_cckm_preauth_cmpl_cb,
+#endif
+#endif
 };
 
 /**

+ 66 - 33
umac/mlme/connection_mgr/core/src/wlan_cm_host_roam.c

@@ -113,18 +113,21 @@ cm_send_reassoc_start_fail(struct cnx_mgr *cm_ctx,
 	return status;
 }
 
-static void cm_connect_prepare_scan_filter_for_roam(
-		struct wlan_objmgr_pdev *pdev,
-		struct cnx_mgr *cm_ctx, struct cm_roam_req *cm_req,
+#ifdef CONN_MGR_ADV_FEATURE
+static QDF_STATUS
+cm_update_roam_scan_filter(
+		struct wlan_objmgr_vdev *vdev, struct cm_roam_req *cm_req,
+		struct scan_filter *filter, bool security_valid_for_6ghz)
+{
+	return cm_update_advance_roam_scan_filter(vdev, filter);
+}
+#else
+static QDF_STATUS
+cm_update_roam_scan_filter(
+		struct wlan_objmgr_vdev *vdev, struct cm_roam_req *cm_req,
 		struct scan_filter *filter, bool security_valid_for_6ghz)
 {
 	uint16_t rsn_caps;
-	struct wlan_objmgr_vdev *vdev = cm_ctx->vdev;
-
-	if (!qdf_is_macaddr_zero(&cm_req->req.bssid)) {
-		filter->num_of_bssid = 1;
-		qdf_copy_macaddr(&filter->bssid_list[0], &cm_req->req.bssid);
-	}
 
 	filter->num_of_ssid = 1;
 	wlan_vdev_mlme_get_ssid(vdev, filter->ssid_list[0].ssid,
@@ -139,21 +142,6 @@ static void cm_connect_prepare_scan_filter_for_roam(
 	if (!security_valid_for_6ghz)
 		filter->ignore_6ghz_channel = true;
 
-	filter->authmodeset =
-		wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_AUTH_MODE);
-
-	filter->ucastcipherset =
-		wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_UCAST_CIPHER);
-
-	filter->mcastcipherset =
-		wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_MCAST_CIPHER);
-
-	filter->key_mgmt =
-		wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
-
-	filter->mgmtcipherset =
-		wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_MGMT_CIPHER);
-
 	if (!QDF_HAS_PARAM(filter->authmodeset, WLAN_CRYPTO_AUTH_WAPI) &&
 	    !QDF_HAS_PARAM(filter->authmodeset, WLAN_CRYPTO_AUTH_RSNA) &&
 	    !QDF_HAS_PARAM(filter->authmodeset, WLAN_CRYPTO_AUTH_WPA)) {
@@ -169,6 +157,38 @@ static void cm_connect_prepare_scan_filter_for_roam(
 		filter->pmf_cap = WLAN_PMF_CAPABLE;
 	else
 		filter->pmf_cap = WLAN_PMF_DISABLED;
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
+static QDF_STATUS cm_connect_prepare_scan_filter_for_roam(
+		struct cnx_mgr *cm_ctx, struct cm_roam_req *cm_req,
+		struct scan_filter *filter, bool security_valid_for_6ghz)
+{
+	struct wlan_objmgr_vdev *vdev = cm_ctx->vdev;
+
+	if (!qdf_is_macaddr_zero(&cm_req->req.bssid)) {
+		filter->num_of_bssid = 1;
+		qdf_copy_macaddr(&filter->bssid_list[0], &cm_req->req.bssid);
+	}
+
+	filter->authmodeset =
+		wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_AUTH_MODE);
+
+	filter->ucastcipherset =
+		wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_UCAST_CIPHER);
+
+	filter->mcastcipherset =
+		wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_MCAST_CIPHER);
+
+	filter->key_mgmt =
+		wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
+
+	filter->mgmtcipherset =
+		wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_MGMT_CIPHER);
+
+	return cm_update_roam_scan_filter(vdev, cm_req, filter,
+					  security_valid_for_6ghz);
 }
 
 static QDF_STATUS cm_roam_get_candidates(struct wlan_objmgr_pdev *pdev,
@@ -187,7 +207,7 @@ static QDF_STATUS cm_roam_get_candidates(struct wlan_objmgr_pdev *pdev,
 	if (!filter)
 		return QDF_STATUS_E_NOMEM;
 
-	cm_connect_prepare_scan_filter_for_roam(pdev, cm_ctx, cm_req, filter,
+	cm_connect_prepare_scan_filter_for_roam(cm_ctx, cm_req, filter,
 						security_valid_for_6ghz);
 
 	candidate_list = wlan_scan_get_result(pdev, filter);
@@ -222,6 +242,22 @@ static QDF_STATUS cm_roam_get_candidates(struct wlan_objmgr_pdev *pdev,
 }
 
 #ifdef WLAN_FEATURE_PREAUTH_ENABLE
+QDF_STATUS cm_handle_reassoc_timer(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
+{
+	struct cm_req *cm_req;
+
+	if (!cm_id)
+		return QDF_STATUS_E_INVAL;
+
+	cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id);
+	if (!cm_req)
+		return QDF_STATUS_E_INVAL;
+
+	return cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_START_REASSOC,
+					sizeof(cm_req->roam_req),
+					&cm_req->roam_req);
+}
+
 static QDF_STATUS cm_host_roam_start(struct cnx_mgr *cm_ctx,
 				     struct cm_req *cm_req)
 {
@@ -245,10 +281,7 @@ static QDF_STATUS cm_host_roam_start(struct cnx_mgr *cm_ctx,
 	 * all candidate.
 	 */
 	cm_req->roam_req.cur_candidate = NULL;
-
-	/* start preauth process */
-
-	return QDF_STATUS_SUCCESS;
+	return cm_host_roam_preauth_start(cm_ctx, cm_req);
 }
 
 static
@@ -256,10 +289,8 @@ QDF_STATUS cm_host_roam_start_fail(struct cnx_mgr *cm_ctx,
 				   struct cm_req *cm_req,
 				   enum wlan_cm_connect_fail_reason reason)
 {
-	/*
-	 * call API to send WLAN_CM_SM_EV_PREAUTH_FAIL to call preauth complete
-	 * and move SM to CONNECTED state
-	 */
+	cm_send_preauth_start_fail(cm_ctx, cm_req->cm_id, reason);
+
 	return QDF_STATUS_SUCCESS;
 }
 #else
@@ -623,6 +654,8 @@ static QDF_STATUS cm_ser_reassoc_req(struct cnx_mgr *cm_ctx,
 	QDF_STATUS status;
 	uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
 
+	mlme_cm_osif_roam_sync_ind(cm_ctx->vdev);
+
 	status = wlan_objmgr_vdev_try_get_ref(cm_ctx->vdev, WLAN_MLME_CM_ID);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		mlme_err(CM_PREFIX_FMT "unable to get reference",

+ 4 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_main.h

@@ -124,12 +124,16 @@ struct cm_connect_req {
  * @req: roam req from osif
  * @candidate_list: candidate list
  * @cur_candidate: current candidate
+ * @num_preauth_retry: retry times for the same candidate
  */
 struct cm_roam_req {
 	wlan_cm_id cm_id;
 	struct wlan_cm_roam_req req;
 	qdf_list_t *candidate_list;
 	struct scan_cache_node *cur_candidate;
+#ifdef WLAN_FEATURE_PREAUTH_ENABLE
+	uint8_t num_preauth_retry;
+#endif
 };
 
 /**

+ 86 - 2
umac/mlme/connection_mgr/core/src/wlan_cm_roam.h

@@ -202,7 +202,91 @@ cm_send_reassoc_start_fail(struct cnx_mgr *cm_ctx,
 			   enum wlan_cm_connect_fail_reason reason,
 			   bool sync);
 
-#else
+#ifdef CONN_MGR_ADV_FEATURE
+/*
+ * cm_update_advance_roam_scan_filter() - fill scan filter for roam
+ * @vdev: vdev
+ * @filter: scan filter
+ *
+ * Return QDF_STATUS
+ */
+QDF_STATUS cm_update_advance_roam_scan_filter(
+		struct wlan_objmgr_vdev *vdev, struct scan_filter *filter);
+#endif
+
+#ifdef WLAN_FEATURE_PREAUTH_ENABLE
+/*
+ * cm_host_roam_preauth_start() - start preauth process
+ * @cm_ctx: Connection manager context
+ * @cm_req: Struct containing the roam request
+ *
+ * Return QDF_STATUS
+ */
+QDF_STATUS cm_host_roam_preauth_start(struct cnx_mgr *cm_ctx,
+				      struct cm_req *cm_req);
+
+/**
+ * cm_preauth_active() - This API would be called after the preauth
+ * request gets activated in serialization.
+ * @cm_ctx: connection manager context
+ * @cm_id: Connection mgr ID assigned to this preauth request.
+ *
+ * Return: QDF status
+ */
+QDF_STATUS cm_preauth_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id);
+
+/**
+ * cm_preauth_done_resp() - This API would be called when preauth
+ * response msg handling
+ * @cm_ctx: connection manager context
+ * @cm_id: Connection mgr ID assigned to this preauth request.
+ *
+ * Return: void
+ */
+void cm_preauth_done_resp(struct cnx_mgr *cm_ctx, struct wlan_preauth_rsp *rsp);
+
+/**
+ * cm_preauth_success() - Preauth is successfully completed
+ * @cm_ctx: connection manager context
+ * @rsp: Preauth resp
+ *
+ * Return: void
+ */
+void cm_preauth_success(struct cnx_mgr *cm_ctx, struct wlan_preauth_rsp *rsp);
+
+/**
+ * cm_preauth_fail() - This API would be called after the preauth
+ * request gets failed.
+ * @cm_ctx: connection manager context
+ * @preauth_fail_rsp: preauth fail response
+ *
+ * Return: none
+ */
+void cm_preauth_fail(struct cnx_mgr *cm_ctx,
+		     struct wlan_cm_preauth_fail *preauth_fail_rsp);
+
+/**
+ * cm_send_preauth_start_fail() - This API would be called after send preauth
+ * request failed.
+ * @cm_ctx: connection manager context
+ * @cm_id: connection mgr ID assigned to this preauth request.
+ * @reason: connect fail reason
+ *
+ * Return: QDF status
+ */
+QDF_STATUS cm_send_preauth_start_fail(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id,
+				      enum wlan_cm_connect_fail_reason reason);
+
+/**
+ * cm_handle_reassoc_timer() - handle ressoc timer expiry
+ * @cm_ctx: connection manager context
+ * @cm_id: connection mgr ID assigned to this preauth request.
+ *
+ * Return: QDF status
+ */
+QDF_STATUS cm_handle_reassoc_timer(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id);
+#endif /* WLAN_FEATURE_PREAUTH_ENABLE */
+#else /* WLAN_FEATURE_HOST_ROAM */
 
 #ifdef WLAN_POLICY_MGR_ENABLE
 static inline
@@ -231,7 +315,7 @@ QDF_STATUS cm_roam_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
 {
 	return QDF_STATUS_SUCCESS;
 }
-#endif
+#endif /* WLAN_FEATURE_HOST_ROAM */
 
 /**
  * cm_check_and_prepare_roam_req() - Initiate roam request

+ 74 - 2
umac/mlme/connection_mgr/core/src/wlan_cm_roam_sm.c

@@ -177,6 +177,47 @@ void cm_subst_preauth_exit(void *ctx)
 {
 }
 
+#ifdef WLAN_FEATURE_PREAUTH_ENABLE
+static bool
+cm_handle_preauth_event(struct cnx_mgr *cm_ctx, uint16_t event,
+			uint16_t data_len, void *data)
+{
+	bool event_handled = true;
+
+	switch (event) {
+	case WLAN_CM_SM_EV_PREAUTH_ACTIVE:
+		if (!cm_check_cmid_match_list_head(cm_ctx, data)) {
+			event_handled = false;
+			break;
+		}
+		cm_preauth_active(cm_ctx, data);
+		break;
+	case WLAN_CM_SM_EV_PREAUTH_RESP:
+		cm_preauth_done_resp(cm_ctx, data);
+		break;
+	case WLAN_CM_SM_EV_PREAUTH_DONE:
+		cm_sm_transition_to(cm_ctx, WLAN_CM_SS_REASSOC);
+		cm_preauth_success(cm_ctx, data);
+		break;
+	case WLAN_CM_SM_EV_PREAUTH_FAIL:
+		cm_sm_transition_to(cm_ctx, WLAN_CM_S_CONNECTED);
+		cm_preauth_fail(cm_ctx, data);
+		break;
+	default:
+		event_handled = false;
+	}
+
+	return event_handled;
+}
+#else
+static inline bool
+cm_handle_preauth_event(struct cnx_mgr *cm_ctx, uint16_t event,
+			uint16_t data_len, void *data)
+{
+	return false;
+}
+#endif
+
 bool cm_subst_preauth_event(void *ctx, uint16_t event,
 			    uint16_t data_len, void *data)
 {
@@ -201,7 +242,8 @@ bool cm_subst_preauth_event(void *ctx, uint16_t event,
 		cm_reassoc_complete(cm_ctx, data);
 		break;
 	default:
-		event_handled = false;
+		event_handled = cm_handle_preauth_event(cm_ctx, event,
+							data_len, data);
 		break;
 	}
 
@@ -224,6 +266,35 @@ void cm_subst_reassoc_exit(void *ctx)
 {
 }
 
+#ifdef WLAN_FEATURE_PREAUTH_ENABLE
+static bool
+cm_handle_reassoc_event(struct cnx_mgr *cm_ctx, uint16_t event,
+			uint16_t data_len, void *data)
+{
+	bool event_handled = true;
+	QDF_STATUS status;
+
+	switch (event) {
+	case WLAN_CM_SM_EV_REASSOC_TIMER:
+		status = cm_handle_reassoc_timer(cm_ctx, data);
+		if (QDF_IS_STATUS_ERROR(status))
+			event_handled = false;
+		break;
+	default:
+		event_handled = false;
+	}
+
+	return event_handled;
+}
+#else
+static inline bool
+cm_handle_reassoc_event(struct cnx_mgr *cm_ctx, uint16_t event,
+			uint16_t data_len, void *data)
+{
+	return false;
+}
+#endif
+
 bool cm_subst_reassoc_event(void *ctx, uint16_t event,
 			    uint16_t data_len, void *data)
 {
@@ -278,7 +349,8 @@ bool cm_subst_reassoc_event(void *ctx, uint16_t event,
 		cm_handle_reassoc_hw_mode_change(cm_ctx, data, event);
 		break;
 	default:
-		event_handled = false;
+		event_handled = cm_handle_reassoc_event(cm_ctx, event,
+							data_len, data);
 		break;
 	}
 

+ 3 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_sm.c

@@ -1009,6 +1009,9 @@ static const char *cm_sm_event_names[] = {
 	"EV_ROAM_INVOKE",
 	"EV_ROAM_ABORT",
 	"EV_ROAM_DONE",
+	"EV_PREAUTH_ACTIVE",
+	"EV_PREAUTH_RESP",
+	"EV_REASSOC_TIMER",
 };
 
 enum wlan_cm_sm_state cm_get_state(struct cnx_mgr *cm_ctx)

+ 6 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_sm.h

@@ -64,6 +64,9 @@
  * @WLAN_CM_SM_EV_ROAM_INVOKE:            Host initiated LFR3/FW roam req
  * @WLAN_CM_SM_EV_ROAM_ABORT:             Roam abort
  * @WLAN_CM_SM_EV_ROAM_DONE:              Roam done
+ * @WLAN_CM_SM_EV_PREAUTH_ACTIVE:         Preauth active
+ * @WLAN_CM_SM_EV_PREAUTH_RESP:           Preauth response
+ * @WLAN_CM_SM_EV_REASSOC_TIMER:         Reassoc timer expired
  * @WLAN_CM_SM_EV_MAX:                    Max event
  */
 enum wlan_cm_sm_evt {
@@ -100,6 +103,9 @@ enum wlan_cm_sm_evt {
 	WLAN_CM_SM_EV_ROAM_INVOKE = 30,
 	WLAN_CM_SM_EV_ROAM_ABORT = 31,
 	WLAN_CM_SM_EV_ROAM_DONE = 32,
+	WLAN_CM_SM_EV_PREAUTH_ACTIVE = 33,
+	WLAN_CM_SM_EV_PREAUTH_RESP = 34,
+	WLAN_CM_SM_EV_REASSOC_TIMER = 35,
 	WLAN_CM_SM_EV_MAX,
 };
 

+ 52 - 0
umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h

@@ -491,6 +491,58 @@ struct wlan_cm_connect_resp {
 #endif
 };
 
+#ifdef WLAN_FEATURE_PREAUTH_ENABLE
+/**
+ * struct wlan_preauth_req - preauth request
+ * @vdev_id: vdev id
+ * @entry: scan entry for the candidate
+ */
+struct wlan_preauth_req {
+	uint8_t vdev_id;
+	struct scan_cache_entry *entry;
+};
+
+/**
+ * struct wlan_cm_preauth_fail - connection manager preauth fail
+ * @cm_id: connection id
+ * @reason: connect fail reason
+ */
+struct wlan_cm_preauth_fail {
+	wlan_cm_id cm_id;
+	enum wlan_cm_connect_fail_reason reason;
+};
+
+#define CM_MAX_FTIE_SIZE 384
+
+/**
+ * struct wlan_preauth_rsp - preauth response
+ * @psoc: psoc object
+ * @vdev_id: vdev id
+ * @cm_id: connection manager ID
+ * @pre_auth_bssid: bssid to preauth to
+ * @status: QDF_STATUS
+ * @ft_ie_length: ft ie length
+ * @ft_ie: ft ie
+ * @ric_ies_length: ric ies length
+ * @ric_ies: ric ies
+ * @timestamp: time stamp
+ */
+struct wlan_preauth_rsp {
+	struct wlan_objmgr_psoc *psoc;
+	uint8_t vdev_id;
+	wlan_cm_id cm_id;
+	struct qdf_mac_addr pre_auth_bssid;
+	QDF_STATUS status;
+	uint16_t ft_ie_length;
+	uint8_t ft_ie[CM_MAX_FTIE_SIZE];
+	uint16_t ric_ies_length;
+	uint8_t ric_ies[CM_MAX_FTIE_SIZE];
+#ifdef FEATURE_WLAN_ESE
+	uint32_t timestamp[2];
+#endif
+};
+#endif
+
 /**
  * struct wlan_cm_discon_rsp - disconnect resp from VDEV mgr and will be sent to
  * OSIF

+ 91 - 8
umac/mlme/include/wlan_mlme_cmn.h

@@ -52,17 +52,31 @@
  * @mlme_cm_disconnect_start_cb: Disconnect start callback
  * @vdev: vdev pointer
  *
+ * @mlme_cm_roam_sync_cb: Roam sync callback
+ * @vdev: vdev pointer
+ *
+ * @mlme_cm_pmksa_candidate_notify_cb: Roam pmksa candidate notify callback
+ * @vdev: vdev pointer
+ * @bssid: bssid
+ * @index: index
+ * @preauth: preauth flag
+ *
  * @mlme_cm_roam_start_cb: Roam start callback
  * @vdev: vdev pointer
  *
  * @mlme_cm_roam_abort_cb: Roam abort callback
  * @vdev: vdev pointer
  *
- * @mlme_cm_roam_sync_cb: Roam sync callback
+ * @mlme_cm_roam_cmpl_cb: Roam sync complete cb
  * @vdev: vdev pointer
  *
- * @mlme_cm_roam_cmpl_cb: Roam sync complete cb
+ * @mlme_cm_ft_preauth_cmpl_cb: Roam ft preauth complete cb
+ * @vdev: vdev pointer
+ * @rsp: preauth response pointer
+ *
+ * @mlme_cm_cckm_preauth_cmpl_cb: Roam cckm preauth complete cb
  * @vdev: vdev pointer
+ * @rsp: preauth response pointer
  */
 struct mlme_cm_ops {
 	QDF_STATUS (*mlme_cm_connect_complete_cb)(
@@ -80,12 +94,28 @@ struct mlme_cm_ops {
 					struct wlan_cm_discon_rsp *rsp);
 	QDF_STATUS (*mlme_cm_disconnect_start_cb)(
 					struct wlan_objmgr_vdev *vdev);
+#ifdef CONN_MGR_ADV_FEATURE
+	QDF_STATUS (*mlme_cm_roam_sync_cb)(struct wlan_objmgr_vdev *vdev);
+	QDF_STATUS (*mlme_cm_pmksa_candidate_notify_cb)(
+						struct wlan_objmgr_vdev *vdev,
+						struct qdf_mac_addr *bssid,
+						int index, bool preauth);
+#endif
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 	QDF_STATUS (*mlme_cm_roam_start_cb)(struct wlan_objmgr_vdev *vdev);
 	QDF_STATUS (*mlme_cm_roam_abort_cb)(struct wlan_objmgr_vdev *vdev);
-	QDF_STATUS (*mlme_cm_roam_sync_cb)(struct wlan_objmgr_vdev *vdev);
 	QDF_STATUS (*mlme_cm_roam_cmpl_cb)(struct wlan_objmgr_vdev *vdev);
 #endif
+#ifdef WLAN_FEATURE_PREAUTH_ENABLE
+	QDF_STATUS (*mlme_cm_ft_preauth_cmpl_cb)(
+					struct wlan_objmgr_vdev *vdev,
+					struct wlan_preauth_rsp *rsp);
+#ifdef FEATURE_WLAN_ESE
+	QDF_STATUS (*mlme_cm_cckm_preauth_cmpl_cb)(
+					struct wlan_objmgr_vdev *vdev,
+					struct wlan_preauth_rsp *rsp);
+#endif
+#endif
 };
 #endif
 
@@ -612,6 +642,35 @@ mlme_cm_osif_disconnect_complete(struct wlan_objmgr_vdev *vdev,
  */
 QDF_STATUS mlme_cm_osif_disconnect_start_ind(struct wlan_objmgr_vdev *vdev);
 
+#ifdef CONN_MGR_ADV_FEATURE
+/**
+ * mlme_cm_osif_roam_sync_ind() - osif Roam sync indication
+ * @vdev: vdev pointer
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS mlme_cm_osif_roam_sync_ind(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * mlme_cm_osif_pmksa_candidate_notify() - osif roam pmksa candidate notify
+ * @vdev: vdev pointer
+ * @bssid: bssid
+ * @index: index
+ * @preauth: preauth flag
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS mlme_cm_osif_pmksa_candidate_notify(struct wlan_objmgr_vdev *vdev,
+					       struct qdf_mac_addr *bssid,
+					       int index, bool preauth);
+#else
+static inline
+QDF_STATUS mlme_cm_osif_roam_sync_ind(struct wlan_objmgr_vdev *vdev)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 /**
  * mlme_cm_osif_roam_start_ind() - osif Roam start indication
@@ -630,21 +689,45 @@ QDF_STATUS mlme_cm_osif_roam_start_ind(struct wlan_objmgr_vdev *vdev);
 QDF_STATUS mlme_cm_osif_roam_abort_ind(struct wlan_objmgr_vdev *vdev);
 
 /**
- * mlme_cm_osif_roam_sync_ind() - osif Roam sync indication
+ * mlme_cm_osif_roam_complete() - osif Roam sync complete callback
  * @vdev: vdev pointer
  *
  * Return: QDF_STATUS
  */
-QDF_STATUS mlme_cm_osif_roam_sync_ind(struct wlan_objmgr_vdev *vdev);
+QDF_STATUS mlme_cm_osif_roam_complete(struct wlan_objmgr_vdev *vdev);
+#endif
 
+#ifdef WLAN_FEATURE_PREAUTH_ENABLE
 /**
- * mlme_cm_osif_roam_complete() - osif Roam sync complete callback
+ * mlme_cm_osif_ft_preauth_complete() - osif roam ft preauth complete callback
  * @vdev: vdev pointer
+ * @rsp: preauth response pointer
  *
  * Return: QDF_STATUS
  */
-QDF_STATUS mlme_cm_osif_roam_complete(struct wlan_objmgr_vdev *vdev);
-#endif
+QDF_STATUS
+mlme_cm_osif_ft_preauth_complete(struct wlan_objmgr_vdev *vdev,
+				 struct wlan_preauth_rsp *rsp);
+#ifdef FEATURE_WLAN_ESE
+/**
+ * mlme_cm_osif_cckm_preauth_complete() - osif cckm preauth complete callback
+ * @vdev: vdev pointer
+ * @rsp: preauth response pointer
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+mlme_cm_osif_cckm_preauth_complete(struct wlan_objmgr_vdev *vdev,
+				   struct wlan_preauth_rsp *rsp);
+#else
+static inline QDF_STATUS
+mlme_cm_osif_cckm_preauth_complete(struct wlan_objmgr_vdev *vdev,
+				   struct wlan_preauth_rsp *rsp)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* FEATURE_WLAN_ESE */
+#endif /* WLAN_FEATURE_PREAUTH_ENABLE */
 
 /**
  * typedef osif_cm_get_global_ops_cb() - Callback to get connection manager

+ 52 - 6
umac/mlme/mlme_objmgr/dispatcher/src/wlan_cmn_mlme_main.c

@@ -461,6 +461,33 @@ QDF_STATUS mlme_cm_osif_disconnect_start_ind(struct wlan_objmgr_vdev *vdev)
 	return ret;
 }
 
+#ifdef CONN_MGR_ADV_FEATURE
+QDF_STATUS mlme_cm_osif_roam_sync_ind(struct wlan_objmgr_vdev *vdev)
+{
+	QDF_STATUS ret = QDF_STATUS_SUCCESS;
+
+	if (glbl_cm_ops &&
+	    glbl_cm_ops->mlme_cm_roam_sync_cb)
+		ret = glbl_cm_ops->mlme_cm_roam_sync_cb(vdev);
+
+	return ret;
+}
+
+QDF_STATUS mlme_cm_osif_pmksa_candidate_notify(struct wlan_objmgr_vdev *vdev,
+					       struct qdf_mac_addr *bssid,
+					       int index, bool preauth)
+{
+	QDF_STATUS ret = QDF_STATUS_SUCCESS;
+
+	if (glbl_cm_ops &&
+	    glbl_cm_ops->mlme_cm_pmksa_candidate_notify_cb)
+		ret = glbl_cm_ops->mlme_cm_pmksa_candidate_notify_cb(
+						vdev, bssid, index, preauth);
+
+	return ret;
+}
+#endif
+
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 QDF_STATUS mlme_cm_osif_roam_start_ind(struct wlan_objmgr_vdev *vdev)
 {
@@ -484,30 +511,49 @@ QDF_STATUS mlme_cm_osif_roam_abort_ind(struct wlan_objmgr_vdev *vdev)
 	return ret;
 }
 
-QDF_STATUS mlme_cm_osif_roam_sync_ind(struct wlan_objmgr_vdev *vdev)
+QDF_STATUS
+mlme_cm_osif_roam_complete(struct wlan_objmgr_vdev *vdev)
 {
 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
 
 	if (glbl_cm_ops &&
-	    glbl_cm_ops->mlme_cm_roam_sync_cb)
-		ret = glbl_cm_ops->mlme_cm_roam_sync_cb(vdev);
+	    glbl_cm_ops->mlme_cm_roam_cmpl_cb)
+		ret = glbl_cm_ops->mlme_cm_roam_cmpl_cb(vdev);
 
 	return ret;
 }
+#endif
 
+#ifdef WLAN_FEATURE_PREAUTH_ENABLE
 QDF_STATUS
-mlme_cm_osif_roam_complete(struct wlan_objmgr_vdev *vdev)
+mlme_cm_osif_ft_preauth_complete(struct wlan_objmgr_vdev *vdev,
+				 struct wlan_preauth_rsp *rsp)
 {
 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
 
 	if (glbl_cm_ops &&
-	    glbl_cm_ops->mlme_cm_roam_cmpl_cb)
-		ret = glbl_cm_ops->mlme_cm_roam_cmpl_cb(vdev);
+	    glbl_cm_ops->mlme_cm_ft_preauth_cmpl_cb)
+		ret = glbl_cm_ops->mlme_cm_ft_preauth_cmpl_cb(vdev, rsp);
 
 	return ret;
 }
 
+#ifdef FEATURE_WLAN_ESE
+QDF_STATUS
+mlme_cm_osif_cckm_preauth_complete(struct wlan_objmgr_vdev *vdev,
+				   struct wlan_preauth_rsp *rsp)
+{
+	QDF_STATUS ret = QDF_STATUS_SUCCESS;
+
+	if (glbl_cm_ops &&
+	    glbl_cm_ops->mlme_cm_cckm_preauth_cmpl_cb)
+		ret = glbl_cm_ops->mlme_cm_cckm_preauth_cmpl_cb(vdev, rsp);
+
+	return ret;
+}
 #endif
+#endif
+
 void mlme_set_osif_cm_cb(osif_cm_get_global_ops_cb osif_cm_ops)
 {
 	glbl_cm_ops_cb = osif_cm_ops;