瀏覽代碼

qcacmn: Support roam sync ind in CM

Add support for roam sync indication in
connection manager.

Change-Id: I750403aa0dfa6c615f9bca832898c63af608d28d
CRs-Fixed: 2901863
Amruta Kulkarni 4 年之前
父節點
當前提交
5c1ca03ebe

+ 3 - 3
os_if/linux/mlme/inc/osif_cm_util.h

@@ -276,9 +276,9 @@ struct osif_cm_ops {
 #ifdef CONN_MGR_ADV_FEATURE
 	osif_cm_netif_queue_ctrl_cb netif_queue_control_cb;
 	os_if_cm_napi_serialize_ctrl_cb napi_serialize_control_cb;
+	osif_cm_save_gtk_cb save_gtk_cb;
 #endif
 #ifdef WLAN_FEATURE_FILS_SK
-	osif_cm_save_gtk_cb save_gtk_cb;
 	osif_cm_set_hlp_data_cb set_hlp_data_cb;
 #endif
 };
@@ -343,9 +343,7 @@ QDF_STATUS osif_cm_netif_queue_ind(struct wlan_objmgr_vdev *vdev,
  * Return: QDF_STATUS
  */
 QDF_STATUS osif_cm_napi_serialize(bool action);
-#endif
 
-#ifdef WLAN_FEATURE_FILS_SK
 /**
  * osif_cm_save_gtk() - Function to save gtk in legacy module
  * @vdev: vdev pointer
@@ -358,7 +356,9 @@ QDF_STATUS osif_cm_napi_serialize(bool action);
  */
 QDF_STATUS osif_cm_save_gtk(struct wlan_objmgr_vdev *vdev,
 			    struct wlan_cm_connect_resp *rsp);
+#endif
 
+#ifdef WLAN_FEATURE_FILS_SK
 /**
  * osif_cm_set_hlp_data() - Function to set hlp data for dhcp in legacy module
  * @dev: Pointer to net device

+ 305 - 6
os_if/linux/mlme/src/osif_cm_roam_rsp.c

@@ -28,6 +28,10 @@
 #include <osif_cm_util.h>
 #include <wlan_cfg80211.h>
 #include <wlan_cfg80211_scan.h>
+#ifdef CONN_MGR_ADV_FEATURE
+#include "wlan_mlme_ucfg_api.h"
+#endif
+#include "wlan_crypto_global_api.h"
 
 #ifdef CONN_MGR_ADV_FEATURE
 #ifdef WLAN_FEATURE_FILS_SK
@@ -85,6 +89,291 @@ static inline void osif_roamed_ind(struct net_device *dev,
 }
 #endif
 
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+#ifdef WLAN_FEATURE_FILS_SK
+/**
+ * wlan_hdd_add_fils_params_roam_auth_event() - Adds FILS params in roam auth
+ * @skb: SK buffer
+ * @roam_info: Roam info
+ *
+ * API adds fils params[pmk, pmkid, next sequence number] to roam auth event
+ *
+ * Return: zero on success, error code on failure
+ */
+static int
+osif_add_fils_params_roam_auth_event(struct sk_buff *skb,
+				     struct wlan_roam_sync_info *roam_info)
+{
+	if (roam_info->pmk_len &&
+	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK,
+		    roam_info->pmk_len, roam_info->pmk)) {
+		osif_err("pmk send fail");
+		return -EINVAL;
+	}
+
+	if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID,
+		    PMKID_LEN, roam_info->pmkid)) {
+		osif_err("pmkid send fail");
+		return -EINVAL;
+	}
+
+	osif_debug("Update ERP Seq Num %d, Next ERP Seq Num %d",
+		   roam_info->update_erp_next_seq_num,
+		   roam_info->next_erp_seq_num);
+	if (roam_info->update_erp_next_seq_num &&
+	    nla_put_u16(skb,
+			QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM,
+			roam_info->next_erp_seq_num)) {
+		osif_err("ERP seq num send fail");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#else
+static inline int
+osif_add_fils_params_roam_auth_event(struct sk_buff *skb,
+				     struct wlan_roam_sync_info *roam_info)
+{
+	return 0;
+}
+#endif
+
+/**
+ * osif_get_roam_reason() - convert wmi roam reason to
+ * enum qca_roam_reason
+ * @roam_scan_trigger: wmi roam scan trigger ID
+ *
+ * Return: Meaningful qca_roam_reason from enum WMI_ROAM_TRIGGER_REASON_ID
+ */
+static enum qca_roam_reason osif_get_roam_reason(uint16_t roam_scan_trigger)
+{
+	switch (roam_scan_trigger) {
+	case ROAM_TRIGGER_REASON_PER:
+		return QCA_ROAM_REASON_PER;
+	case ROAM_TRIGGER_REASON_BMISS:
+		return QCA_ROAM_REASON_BEACON_MISS;
+	case ROAM_TRIGGER_REASON_LOW_RSSI:
+	case ROAM_TRIGGER_REASON_BACKGROUND:
+		return QCA_ROAM_REASON_POOR_RSSI;
+	case ROAM_TRIGGER_REASON_HIGH_RSSI:
+		return QCA_ROAM_REASON_BETTER_RSSI;
+	case ROAM_TRIGGER_REASON_DENSE:
+		return QCA_ROAM_REASON_CONGESTION;
+	case ROAM_TRIGGER_REASON_FORCED:
+		return QCA_ROAM_REASON_USER_TRIGGER;
+	case ROAM_TRIGGER_REASON_BTM:
+		return QCA_ROAM_REASON_BTM;
+	case ROAM_TRIGGER_REASON_BSS_LOAD:
+		return QCA_ROAM_REASON_BSS_LOAD;
+	default:
+		return QCA_ROAM_REASON_UNKNOWN;
+	}
+
+	return QCA_ROAM_REASON_UNKNOWN;
+}
+
+/**
+ * osif_send_roam_auth_event() - API to send roam auth event response to kernel
+ * @vdev: vdev pointer
+ * @osif_priv: OS private structure of vdev
+ * @rsp: Connection manager response
+ *
+ * This is called when wlan driver needs to send the roaming and
+ * authorization information after roaming.
+ *
+ * The information that would be sent is the request RSN IE, response
+ * RSN IE and BSSID of the newly roamed AP.
+ *
+ * If the Authorized status is authenticated, then additional parameters
+ * like PTK's KCK and KEK and Replay Counter would also be passed to the
+ * supplicant.
+ *
+ * The supplicant upon receiving this event would ignore the legacy
+ * cfg80211_roamed call and use the entire information from this event.
+ * The cfg80211_roamed should still co-exist since the kernel will
+ * make use of the parameters even if the supplicant ignores it.
+ *
+ *
+ * Context: Any context.
+ * Return: int
+ */
+static int osif_send_roam_auth_event(struct wlan_objmgr_vdev *vdev,
+				     struct vdev_osif_priv *osif_priv,
+				     struct wlan_cm_connect_resp *rsp,
+				     const uint8_t *req_ie,
+				     size_t req_ie_len, const uint8_t *resp_ie,
+				     size_t resp_ie_len)
+{
+	struct wlan_objmgr_psoc *psoc;
+	uint32_t fils_params_len;
+	struct sk_buff *skb = NULL;
+	struct wlan_roam_sync_info *roaming_info;
+	int status;
+	int32_t akm;
+	bool roam_offload_enable;
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	ucfg_mlme_get_roaming_offload(psoc, &roam_offload_enable);
+
+	if (!roam_offload_enable)
+		return 0;
+
+	roaming_info = rsp->roaming_info;
+
+	/*
+	 * PMK is sent from FW in Roam Synch Event for FILS Roaming.
+	 * In that case, add three more NL attributes.ie. PMK, PMKID
+	 * and ERP next sequence number. Add corresponding lengths
+	 * with 3 extra NL message headers for each of the
+	 * aforementioned params.
+	 */
+	fils_params_len = roaming_info->pmk_len + PMKID_LEN +
+			  sizeof(uint16_t) + (3 * NLMSG_HDRLEN);
+
+	skb = cfg80211_vendor_event_alloc(osif_priv->wdev->wiphy,
+			osif_priv->wdev,
+			ETH_ALEN + req_ie_len +
+			resp_ie_len +
+			sizeof(uint8_t) + REPLAY_CTR_LEN +
+			KCK_KEY_LEN + roaming_info->kek_len +
+			sizeof(uint16_t) + sizeof(uint8_t) +
+			(9 * NLMSG_HDRLEN) + fils_params_len,
+			QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
+			GFP_KERNEL);
+
+	if (!skb) {
+		osif_err("cfg80211_vendor_event_alloc failed");
+		return -1;
+	}
+
+	if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
+		    ETH_ALEN, rsp->bssid.bytes) ||
+	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
+		    req_ie_len, req_ie) ||
+	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
+		    resp_ie_len, resp_ie)) {
+		osif_err("nla put fail");
+		goto nla_put_failure;
+	}
+
+	if (roaming_info->auth_status == ROAM_AUTH_STATUS_AUTHENTICATED) {
+		osif_debug("Include Auth Params TLV's");
+		if (nla_put_u8(skb,
+			       QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
+			       true)) {
+			osif_err("nla put fail");
+			goto nla_put_failure;
+		}
+		akm = wlan_crypto_get_param(vdev,
+					    WLAN_CRYPTO_PARAM_KEY_MGMT);
+		/* if FT or CCKM connection: dont send replay counter */
+		if (!QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X) &&
+		    !QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_PSK) &&
+		    !QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE) &&
+		    !QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384) &&
+		    !QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_CCKM) &&
+		    nla_put(skb,
+			    QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
+			    REPLAY_CTR_LEN,
+			    roaming_info->replay_ctr)) {
+			osif_err("non FT/non CCKM connection");
+			osif_err("failed to send replay counter");
+			goto nla_put_failure;
+		}
+		if (roaming_info->kek_len > MAX_KEK_LENGTH ||
+		    nla_put(skb,
+			    QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
+			    roaming_info->kck_len, roaming_info->kck) ||
+		    nla_put(skb,
+			    QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
+			    roaming_info->kek_len, roaming_info->kek)) {
+			osif_err("nla put fail, kek_len %d",
+				 roaming_info->kek_len);
+			goto nla_put_failure;
+		}
+
+		if (nla_put_u16(skb,
+				QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REASON,
+				osif_get_roam_reason(roaming_info->roam_reason))) {
+			osif_err("roam reason send failure");
+			goto nla_put_failure;
+		}
+
+		status = osif_add_fils_params_roam_auth_event(skb,
+							      roaming_info);
+		if (status)
+			goto nla_put_failure;
+		/*
+		 * Save the gtk rekey parameters in HDD STA context. They will
+		 * be used next time when host enables GTK offload and goes
+		 * into power save state.
+		 */
+		osif_cm_save_gtk(vdev, rsp);
+		osif_debug("roam_info_ptr->replay_ctr 0x%llx",
+			   *((uint64_t *)roaming_info->replay_ctr));
+
+	} else {
+		osif_debug("No Auth Params TLV's");
+		if (nla_put_u8(skb,
+			       QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
+			       false)) {
+			osif_err("nla put fail");
+			goto nla_put_failure;
+		}
+	}
+
+	osif_debug("Auth Status = %d Subnet Change Status = %d",
+		   roaming_info->auth_status,
+		   roaming_info->subnet_change_status);
+	/*
+	 * Add subnet change status if subnet has changed
+	 * 0 = unchanged
+	 * 1 = changed
+	 * 2 = unknown
+	 */
+	if (roaming_info->subnet_change_status) {
+		if (nla_put_u8(skb,
+			       QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
+			       roaming_info->subnet_change_status)) {
+			osif_err("nla put fail");
+			goto nla_put_failure;
+		}
+	}
+
+	cfg80211_vendor_event(skb, GFP_KERNEL);
+	return 0;
+
+nla_put_failure:
+	kfree_skb(skb);
+	return -1;
+}
+#else
+static inline int
+osif_send_roam_auth_event(struct wlan_objmgr_vdev *vdev,
+			  struct vdev_osif_priv *osif_priv,
+			  struct wlan_cm_connect_resp *rsp,
+			  const uint8_t *req_ie,
+			  size_t req_ie_len, const uint8_t *resp_ie,
+			  size_t resp_ie_len)
+{
+	return 0;
+}
+#endif
+
+static void osif_cm_get_reassoc_req_ie_data(struct element_info *assoc_req,
+					    size_t *ie_data_len,
+					    const uint8_t **ie_data_ptr)
+{
+	/* Validate IE and length */
+	if (!assoc_req->len || !assoc_req->ptr ||
+	    assoc_req->len <= WLAN_REASSOC_REQ_IES_OFFSET)
+		return;
+
+	*ie_data_len = assoc_req->len - WLAN_REASSOC_REQ_IES_OFFSET;
+	*ie_data_ptr = assoc_req->ptr + WLAN_REASSOC_REQ_IES_OFFSET;
+}
+
 void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
 				   struct vdev_osif_priv *osif_priv,
 				   struct wlan_cm_connect_resp *rsp)
@@ -96,10 +385,18 @@ void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
 	const uint8_t *rsp_ie = NULL;
 	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;
 
+	psoc = wlan_vdev_get_psoc(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,
@@ -107,15 +404,17 @@ void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
 				    rsp->ssid.length);
 	if (!bss)
 		osif_warn("not able to find bss");
-	osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
-				      &req_len, &req_ie);
+	if (!roam_offload || rsp->is_ft)
+		osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
+					      &req_len, &req_ie);
+	else
+		osif_cm_get_reassoc_req_ie_data(&rsp->connect_ies.assoc_req,
+						&req_len, &req_ie);
 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
 				      &rsp_len, &rsp_ie);
 	osif_roamed_ind(dev, bss, req_ie, req_len, rsp_ie, rsp_len);
-
-	osif_cm_save_gtk(vdev, rsp);
-
-	/* Add osif_send_roam_auth_event (wlan_hdd_send_roam_auth_event) */
+	osif_send_roam_auth_event(vdev, osif_priv, rsp, req_ie, req_len, rsp_ie,
+				  rsp_len);
 
 	osif_update_fils_hlp_data(dev, vdev, rsp);
 }

+ 42 - 3
os_if/linux/mlme/src/osif_cm_util.c

@@ -336,7 +336,7 @@ osif_cm_roam_start_cb(struct wlan_objmgr_vdev *vdev)
  * @vdev: vdev pointer
  *
  * This callback indicates os_if that roaming has been aborted
- * so that os_if can stop all the activity on this connection
+ * so that os_if can resume all the activity on this connection
  *
  * Return: QDF_STATUS
  */
@@ -348,6 +348,42 @@ osif_cm_roam_abort_cb(struct wlan_objmgr_vdev *vdev)
 				       WLAN_WAKE_ALL_NETIF_QUEUE,
 				       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_cm_roam_cmpl_cb() - Roam sync complete callback
+ * @vdev: vdev pointer
+ * @rsp: connect rsp
+ *
+ * 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_cmpl_cb(struct wlan_objmgr_vdev *vdev)
+{
+	return osif_cm_napi_serialize(false);
+}
 #endif
 
 static struct mlme_cm_ops cm_ops = {
@@ -359,6 +395,8 @@ static struct mlme_cm_ops cm_ops = {
 #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
 };
 
@@ -472,8 +510,7 @@ QDF_STATUS osif_cm_napi_serialize(bool action)
 
 	return ret;
 }
-#endif
-#ifdef WLAN_FEATURE_FILS_SK
+
 QDF_STATUS osif_cm_save_gtk(struct wlan_objmgr_vdev *vdev,
 			    struct wlan_cm_connect_resp *rsp)
 {
@@ -487,7 +524,9 @@ QDF_STATUS osif_cm_save_gtk(struct wlan_objmgr_vdev *vdev,
 
 	return ret;
 }
+#endif
 
+#ifdef WLAN_FEATURE_FILS_SK
 QDF_STATUS osif_cm_set_hlp_data(struct net_device *dev,
 				struct wlan_objmgr_vdev *vdev,
 				struct wlan_cm_connect_resp *rsp)

+ 3 - 0
umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h

@@ -29,6 +29,8 @@
 #define WLAN_ASSOC_RSP_IES_OFFSET 6
 /* Assoc req IE offset - Capability(2) + LI(2) */
 #define WLAN_ASSOC_REQ_IES_OFFSET 4
+/* Assoc req IE offset - Capability(2) + LI(2) + current AP address(6) */
+#define WLAN_REASSOC_REQ_IES_OFFSET 10
 
 #define IEEE80211_CCMP_HEADERLEN    8
 #define IEEE80211_HT_CTRL_LEN       4
@@ -860,6 +862,7 @@ enum wlan_status_code {
 #define MAX_KEK_LENGTH 64
 #define MAX_KCK_LEN 32
 #define REPLAY_CTR_LEN 8
+#define KCK_KEY_LEN 16
 
 #define WLAN_WPA_OUI 0xf25000
 #define WLAN_WPA_OUI_TYPE 0x01

+ 3 - 10
umac/mlme/connection_mgr/core/src/wlan_cm_connect.c

@@ -561,7 +561,7 @@ static inline QDF_STATUS cm_set_fils_key(struct cnx_mgr *cm_ctx,
 }
 #endif /* WLAN_FEATURE_FILS_SK */
 
-static QDF_STATUS
+QDF_STATUS
 cm_inform_blm_connect_complete(struct wlan_objmgr_vdev *vdev,
 			       struct wlan_cm_connect_resp *resp)
 {
@@ -716,12 +716,6 @@ static void cm_set_fils_wep_key(struct cnx_mgr *cm_ctx,
 	cm_set_key(cm_ctx, false, 0, &broadcast_mac);
 }
 #else
-static inline QDF_STATUS
-cm_inform_blm_connect_complete(struct wlan_objmgr_vdev *vdev,
-			       struct wlan_cm_connect_resp *resp)
-{
-	return QDF_STATUS_SUCCESS;
-}
 
 static inline
 bool cm_is_retry_with_same_candidate(struct cnx_mgr *cm_ctx,
@@ -969,9 +963,8 @@ QDF_STATUS cm_if_mgr_validate_candidate(struct cnx_mgr *cm_ctx,
 				    &event_data);
 }
 
-static QDF_STATUS
-cm_if_mgr_inform_connect_complete(struct wlan_objmgr_vdev *vdev,
-				  QDF_STATUS connect_status)
+QDF_STATUS cm_if_mgr_inform_connect_complete(struct wlan_objmgr_vdev *vdev,
+					     QDF_STATUS connect_status)
 {
 	struct if_mgr_event_data *connect_complete;
 

+ 28 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h

@@ -55,6 +55,16 @@
  */
 QDF_STATUS cm_connect_start(struct cnx_mgr *cm_ctx, struct cm_connect_req *req);
 
+/**
+ * cm_if_mgr_inform_connect_complete() - inform ifmanager the connect complete
+ * @vdev: vdev for which connect cmpleted
+ * @connect_status: connect status
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS cm_if_mgr_inform_connect_complete(struct wlan_objmgr_vdev *vdev,
+					     QDF_STATUS connect_status);
+
 /**
  * cm_handle_connect_req_in_non_init_state() - Handle connect request in non
  * init state.
@@ -516,6 +526,17 @@ void cm_store_wep_key(struct cnx_mgr *cm_ctx,
 		      struct wlan_cm_connect_crypto_info *crypto,
 		      wlan_cm_id cm_id);
 
+/**
+ * cm_inform_blm_connect_complete() - inform bsl about connect complete
+ * @vdev: vdev
+ * @resp: connect resp
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+cm_inform_blm_connect_complete(struct wlan_objmgr_vdev *vdev,
+			       struct wlan_cm_connect_resp *resp);
+
 static inline QDF_STATUS
 cm_peer_create_on_bss_select_ind_resp(struct cnx_mgr *cm_ctx,
 				      wlan_cm_id *cm_id)
@@ -535,6 +556,13 @@ static inline void cm_store_wep_key(struct cnx_mgr *cm_ctx,
 				    wlan_cm_id cm_id)
 {}
 
+static inline QDF_STATUS
+cm_inform_blm_connect_complete(struct wlan_objmgr_vdev *vdev,
+			       struct wlan_cm_connect_resp *resp)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
 /**
  * cm_peer_create_on_bss_select_ind_resp() - Called to create peer
  * if bss select inidication's resp was success

+ 29 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_roam.h

@@ -292,6 +292,7 @@ struct cm_roam_req *cm_get_first_roam_command(struct wlan_objmgr_vdev *vdev);
 QDF_STATUS cm_prepare_roam_cmd(struct cnx_mgr *cm_ctx,
 			       struct cm_req **roam_req,
 			       enum wlan_cm_source source);
+
 /**
  * cm_add_fw_roam_cmd_to_list_n_ser() - Add roam req to list and serialize req
  * @cm_ctx: connection mgr context
@@ -303,6 +304,34 @@ QDF_STATUS cm_prepare_roam_cmd(struct cnx_mgr *cm_ctx,
  */
 QDF_STATUS cm_add_fw_roam_cmd_to_list_n_ser(struct cnx_mgr *cm_ctx,
 					    struct cm_req *cm_req);
+
+/**
+ * cm_fw_send_vdev_roam_event() - CM send VDEV ROAM Event
+ * @cm_ctx: connection mgr context
+ * @data_len: data size
+ * @data: event data
+ *
+ * This function sends ROAM Event to vdev manager
+ * state machine
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+cm_fw_send_vdev_roam_event(struct cnx_mgr *cm_ctx, uint16_t data_len,
+			   void *data);
+
+/**
+ * cm_fw_roam_complete() - CM handle roam complete
+ * @cm_ctx: connection mgr context
+ * @data: join rsp data
+ *
+ * This function CM handle roam complete
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+cm_fw_roam_complete(struct cnx_mgr *cm_ctx, void *data);
+
 #else
 static inline bool cm_roam_offload_enabled(struct wlan_objmgr_psoc *psoc)
 {

+ 28 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_roam_sm.c

@@ -71,6 +71,16 @@ bool cm_handle_fw_roaming_event(struct cnx_mgr *cm_ctx, uint16_t event,
 		cm_sm_deliver_event_sync(cm_ctx, event,
 					 data_len, data);
 		break;
+	case WLAN_CM_SM_EV_ROAM_SYNC:
+		status = cm_add_fw_roam_cmd_to_list_n_ser(cm_ctx, data);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			event_handled = false;
+			break;
+		}
+		cm_sm_transition_to(cm_ctx, WLAN_CM_SS_ROAM_SYNC);
+		cm_sm_deliver_event_sync(cm_ctx, event,
+					 data_len, data);
+		break;
 	default:
 		event_handled = false;
 		break;
@@ -314,6 +324,11 @@ bool cm_subst_roam_start_event(void *ctx, uint16_t event,
 		cm_sm_deliver_event_sync(cm_ctx, event,
 					 data_len, data);
 		break;
+	case WLAN_CM_SM_EV_ROAM_SYNC:
+		cm_sm_transition_to(cm_ctx, WLAN_CM_SS_ROAM_SYNC);
+		cm_sm_deliver_event_sync(cm_ctx, event,
+					 data_len, data);
+		break;
 	default:
 		event_handled = false;
 		break;
@@ -349,6 +364,19 @@ bool cm_subst_roam_sync_event(void *ctx, uint16_t event,
 			cm_handle_connect_disconnect_in_roam(cm_ctx, event,
 							     data_len, data);
 		break;
+	case WLAN_CM_SM_EV_ROAM_SYNC:
+		cm_fw_send_vdev_roam_event(cm_ctx, data_len, data);
+		break;
+	case WLAN_CM_SM_EV_ROAM_DONE:
+		cm_sm_transition_to(cm_ctx, WLAN_CM_S_CONNECTED);
+		cm_sm_deliver_event_sync(cm_ctx, event,
+					 data_len, data);
+		break;
+	case WLAN_CM_SM_EV_ROAM_ABORT:
+		cm_sm_transition_to(cm_ctx, WLAN_CM_S_CONNECTED);
+		cm_sm_deliver_event_sync(cm_ctx, event,
+					 data_len, data);
+		break;
 	default:
 		event_handled = false;
 		break;

+ 16 - 5
umac/mlme/connection_mgr/core/src/wlan_cm_sm.c

@@ -229,9 +229,7 @@ bool cm_handle_fw_roam_connected_event(struct cnx_mgr *cm_ctx, uint16_t event,
 	switch (event) {
 	case WLAN_CM_SM_EV_ROAM_INVOKE:
 		cm_sm_transition_to(cm_ctx, WLAN_CM_S_ROAMING);
-		cm_sm_deliver_event_sync(cm_ctx,
-					 WLAN_CM_SM_EV_ROAM_INVOKE,
-					 data_len, data);
+		cm_sm_deliver_event_sync(cm_ctx, event, data_len, data);
 		break;
 	case WLAN_CM_SM_EV_ROAM_ABORT:
 	case WLAN_CM_SM_EV_ROAM_INVOKE_FAIL:
@@ -245,10 +243,22 @@ bool cm_handle_fw_roam_connected_event(struct cnx_mgr *cm_ctx, uint16_t event,
 			break;
 		}
 		cm_sm_transition_to(cm_ctx, WLAN_CM_S_ROAMING);
-		cm_sm_deliver_event_sync(cm_ctx,
-					 WLAN_CM_SM_EV_ROAM_START,
+		cm_sm_deliver_event_sync(cm_ctx, event,
 					 sizeof(*roam_cm_req), roam_cm_req);
 		break;
+	case WLAN_CM_SM_EV_ROAM_SYNC:
+		status = cm_prepare_roam_cmd(cm_ctx, &roam_cm_req,
+					     CM_ROAMING_FW);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			event_handled = false;
+			break;
+		}
+		cm_sm_transition_to(cm_ctx, WLAN_CM_S_ROAMING);
+		cm_sm_deliver_event_sync(cm_ctx, event, data_len, data);
+		break;
+	case WLAN_CM_SM_EV_ROAM_DONE:
+		cm_fw_roam_complete(cm_ctx, data);
+		break;
 	default:
 		event_handled = false;
 		break;
@@ -992,6 +1002,7 @@ static const char *cm_sm_event_names[] = {
 	"EV_ROAM_REQ",
 	"EV_ROAM_INVOKE",
 	"EV_ROAM_ABORT",
+	"EV_ROAM_DONE",
 };
 
 enum wlan_cm_sm_state cm_get_state(struct cnx_mgr *cm_ctx)

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

@@ -63,6 +63,7 @@
  *                                        LFR2/Host roam - Roam req from host/FW
  * @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_MAX:                    Max event
  */
 enum wlan_cm_sm_evt {
@@ -98,6 +99,7 @@ enum wlan_cm_sm_evt {
 	WLAN_CM_SM_EV_ROAM_REQ = 29,
 	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_MAX,
 };
 

+ 5 - 5
umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h

@@ -408,8 +408,8 @@ struct wlan_connect_rsp_ies {
 
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 /**
- * struct wlan_cm_connect_rsp - connect resp from VDEV mgr and will be sent to
- * OSIF
+ * struct wlan_roam_sync_info - roam sync information populated
+ * from roam sync indication struct
  * @auth_status: roam auth status (authenticated or connected)
  * @kck_len: kck length
  * @kck: kck info in roam sync
@@ -436,13 +436,11 @@ struct wlan_roam_sync_info {
 	uint8_t replay_ctr[REPLAY_CTR_LEN];
 	uint8_t subnet_change_status;
 	uint16_t roam_reason;
-#ifdef WLAN_FEATURE_FILS_SK
 	uint32_t pmk_len;
 	uint8_t pmk[MAX_PMK_LEN];
 	uint8_t pmkid[PMKID_LEN];
 	bool update_erp_next_seq_num;
 	uint16_t next_erp_seq_num;
-#endif
 };
 #endif
 
@@ -453,6 +451,7 @@ struct wlan_roam_sync_info {
  * @is_wps_connection: if its wps connection
  * @is_osen_connection: if its osen connection
  * @is_reassoc: if response is for reassoc/roam
+ * @is_ft: is FT reassoc
  * @cm_id: Connect manager id
  * @bssid: BSSID of the ap
  * @ssid: SSID of the connection
@@ -469,7 +468,8 @@ struct wlan_cm_connect_resp {
 	uint8_t vdev_id;
 	uint8_t is_wps_connection:1,
 		is_osen_connection:1,
-		is_reassoc:1;
+		is_reassoc:1,
+		is_ft:1;
 	wlan_cm_id cm_id;
 	struct qdf_mac_addr bssid;
 	struct wlan_ssid ssid;

+ 24 - 0
umac/mlme/include/wlan_mlme_cmn.h

@@ -57,6 +57,12 @@
  *
  * @mlme_cm_roam_abort_cb: Roam abort callback
  * @vdev: vdev pointer
+ *
+ * @mlme_cm_roam_sync_cb: Roam sync callback
+ * @vdev: vdev pointer
+ *
+ * @mlme_cm_roam_cmpl_cb: Roam sync complete cb
+ * @vdev: vdev pointer
  */
 struct mlme_cm_ops {
 	QDF_STATUS (*mlme_cm_connect_complete_cb)(
@@ -77,6 +83,8 @@ struct mlme_cm_ops {
 #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
 };
 #endif
@@ -614,6 +622,22 @@ QDF_STATUS mlme_cm_osif_roam_start_ind(struct wlan_objmgr_vdev *vdev);
  * Return: QDF_STATUS
  */
 QDF_STATUS mlme_cm_osif_roam_abort_ind(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * 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_roam_complete() - osif Roam sync complete callback
+ * @vdev: vdev pointer
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS mlme_cm_osif_roam_complete(struct wlan_objmgr_vdev *vdev);
 #endif
 
 /**

+ 24 - 0
umac/mlme/mlme_objmgr/dispatcher/src/wlan_cmn_mlme_main.c

@@ -481,6 +481,30 @@ 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 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_roam_complete(struct wlan_objmgr_vdev *vdev)
+{
+	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);
+
+	return ret;
+}
+
 #endif
 void mlme_set_osif_cm_cb(osif_cm_get_global_ops_cb osif_cm_ops)
 {