Browse Source

qcacmn: Send roam auth mlo links event

After mlo roaming is complete send roam auth mlo links
event to kernel.
Also populate cfg roam info structure with mlo link info.

Change-Id: I8710e3a53f05c50b7b276d87a39411cb43d0983f
CRs-Fixed: 3279967
Amruta Kulkarni 2 years ago
parent
commit
c3051031c5

+ 49 - 52
os_if/linux/mlme/src/osif_cm_connect_rsp.c

@@ -382,30 +382,8 @@ osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params,
 #endif /* WLAN_FEATURE_FILS_SK */
 #endif /* WLAN_FEATURE_FILS_SK */
 #endif
 #endif
 
 
-#if defined(CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT) && defined(WLAN_FEATURE_11BE_MLO)
-#ifndef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
-static struct wlan_objmgr_vdev *osif_get_partner_vdev(struct wlan_objmgr_vdev *vdev,
-						      struct mlo_link_info rsp_partner_info)
-{
-	return mlo_get_vdev_by_link_id(vdev, rsp_partner_info.link_id);
-}
-#endif
-
-static
-void osif_populate_connect_response_for_link(struct wlan_objmgr_vdev *vdev,
-					     struct cfg80211_connect_resp_params *conn_rsp_params,
-					     uint8_t link_id,
-					     struct cfg80211_bss *bss)
-{
-	osif_debug("Link_id :%d", link_id);
-	conn_rsp_params->valid_links |=  BIT(link_id);
-	conn_rsp_params->links[link_id].bssid = bss->bssid;
-	conn_rsp_params->links[link_id].bss = bss;
-	conn_rsp_params->links[link_id].addr =
-					 wlan_vdev_mlme_get_macaddr(vdev);
-}
-
-static QDF_STATUS
+#ifdef WLAN_FEATURE_11BE_MLO
+QDF_STATUS
 osif_get_partner_info_from_mlie(struct wlan_cm_connect_resp *connect_rsp,
 osif_get_partner_info_from_mlie(struct wlan_cm_connect_resp *connect_rsp,
 				struct mlo_partner_info *partner_info)
 				struct mlo_partner_info *partner_info)
 {
 {
@@ -434,38 +412,14 @@ osif_get_partner_info_from_mlie(struct wlan_cm_connect_resp *connect_rsp,
 	qdf_status = util_get_bvmlie_persta_partner_info(ml_ie, ml_ie_len,
 	qdf_status = util_get_bvmlie_persta_partner_info(ml_ie, ml_ie_len,
 							 partner_info);
 							 partner_info);
 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
-		osif_err("Unable to find per-sta profile in ML IE :%d");
+		osif_err("Unable to find per-sta profile in ML IE");
 		return qdf_status;
 		return qdf_status;
 	}
 	}
 
 
 	return qdf_status;
 	return qdf_status;
 }
 }
 
 
-static QDF_STATUS
-osif_fill_peer_mld_mac_connect_resp(struct wlan_objmgr_vdev *vdev,
-				    struct wlan_cm_connect_resp *rsp,
-				    struct cfg80211_connect_resp_params *conn_rsp_params)
-{
-	struct wlan_objmgr_peer *peer_obj;
-	struct wlan_objmgr_psoc *psoc;
-
-	psoc = wlan_vdev_get_psoc(vdev);
-	if (!psoc)
-		return QDF_STATUS_E_INVAL;
-
-	peer_obj = wlan_objmgr_get_peer_by_mac(psoc,
-					       rsp->bssid.bytes, WLAN_OSIF_ID);
-	if (!peer_obj)
-		return QDF_STATUS_E_INVAL;
-
-	conn_rsp_params->ap_mld_addr = wlan_peer_mlme_get_mldaddr(peer_obj);
-
-	wlan_objmgr_peer_release_ref(peer_obj, WLAN_OSIF_ID);
-
-	return QDF_STATUS_SUCCESS;
-}
-
-static QDF_STATUS
+QDF_STATUS
 osif_get_link_id_from_assoc_ml_ie(struct mlo_link_info *rsp_link_info,
 osif_get_link_id_from_assoc_ml_ie(struct mlo_link_info *rsp_link_info,
 				  struct mlo_partner_info *assoc_partner_info,
 				  struct mlo_partner_info *assoc_partner_info,
 				  uint8_t *link_id)
 				  uint8_t *link_id)
@@ -484,7 +438,7 @@ osif_get_link_id_from_assoc_ml_ie(struct mlo_link_info *rsp_link_info,
 	return QDF_STATUS_E_INVAL;
 	return QDF_STATUS_E_INVAL;
 }
 }
 
 
-static struct cfg80211_bss *
+struct cfg80211_bss *
 osif_get_chan_bss_from_kernel(struct wlan_objmgr_vdev *vdev,
 osif_get_chan_bss_from_kernel(struct wlan_objmgr_vdev *vdev,
 			      struct mlo_link_info *rsp_link_info,
 			      struct mlo_link_info *rsp_link_info,
 			      struct wlan_cm_connect_resp *rsp)
 			      struct wlan_cm_connect_resp *rsp)
@@ -498,7 +452,7 @@ osif_get_chan_bss_from_kernel(struct wlan_objmgr_vdev *vdev,
 				     rsp_link_info->chan_freq);
 				     rsp_link_info->chan_freq);
 	if (!chan) {
 	if (!chan) {
 		osif_err("Invalid partner channel");
 		osif_err("Invalid partner channel");
-		NULL;
+		return NULL;
 	}
 	}
 
 
 	partner_bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan,
 	partner_bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan,
@@ -511,6 +465,49 @@ osif_get_chan_bss_from_kernel(struct wlan_objmgr_vdev *vdev,
 
 
 	return partner_bss;
 	return partner_bss;
 }
 }
+#endif
+
+#if defined(CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT) && defined(WLAN_FEATURE_11BE_MLO)
+#ifndef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
+static struct wlan_objmgr_vdev *osif_get_partner_vdev(struct wlan_objmgr_vdev *vdev,
+						      struct mlo_link_info rsp_partner_info)
+{
+	return mlo_get_vdev_by_link_id(vdev, rsp_partner_info.link_id);
+}
+#endif
+
+static
+void osif_populate_connect_response_for_link(struct wlan_objmgr_vdev *vdev,
+					     struct cfg80211_connect_resp_params *conn_rsp_params,
+					     uint8_t link_id,
+					     struct cfg80211_bss *bss)
+{
+	osif_debug("Link_id :%d", link_id);
+	conn_rsp_params->valid_links |=  BIT(link_id);
+	conn_rsp_params->links[link_id].bssid = bss->bssid;
+	conn_rsp_params->links[link_id].bss = bss;
+	conn_rsp_params->links[link_id].addr =
+					 wlan_vdev_mlme_get_macaddr(vdev);
+}
+
+static QDF_STATUS
+osif_fill_peer_mld_mac_connect_resp(struct wlan_objmgr_vdev *vdev,
+				    struct wlan_cm_connect_resp *rsp,
+				    struct cfg80211_connect_resp_params *conn_rsp_params)
+{
+	struct wlan_objmgr_peer *peer_obj;
+
+	peer_obj = wlan_objmgr_get_peer_by_mac(wlan_vdev_get_psoc(vdev),
+					       rsp->bssid.bytes, WLAN_OSIF_ID);
+	if (!peer_obj)
+		return QDF_STATUS_E_INVAL;
+
+	conn_rsp_params->ap_mld_addr = wlan_peer_mlme_get_mldaddr(peer_obj);
+
+	wlan_objmgr_peer_release_ref(peer_obj, WLAN_OSIF_ID);
+
+	return QDF_STATUS_SUCCESS;
+}
 
 
 static void
 static void
 osif_populate_partner_links_mlo_params(struct wlan_objmgr_pdev *pdev,
 osif_populate_partner_links_mlo_params(struct wlan_objmgr_pdev *pdev,

+ 296 - 35
os_if/linux/mlme/src/osif_cm_roam_rsp.c

@@ -80,7 +80,126 @@ void osif_copy_roamed_info(struct cfg80211_roam_info *info,
 	info->bss = bss;
 	info->bss = bss;
 }
 }
 #endif
 #endif
-static void osif_roamed_ind(struct net_device *dev, struct cfg80211_bss *bss,
+
+#if defined(CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT) && defined(WLAN_FEATURE_11BE_MLO)
+static
+void osif_populate_mlo_info_for_link(struct wlan_objmgr_vdev *vdev,
+				     struct cfg80211_roam_info *roam_info_params,
+				     uint8_t link_id,
+				     struct cfg80211_bss *bss)
+{
+	osif_debug("Link_id :%d", link_id);
+	roam_info_params->valid_links |=  BIT(link_id);
+	roam_info_params->links[link_id].bssid = bss->bssid;
+	roam_info_params->links[link_id].bss = bss;
+	roam_info_params->links[link_id].addr =
+					 wlan_vdev_mlme_get_macaddr(vdev);
+}
+
+static void
+osif_populate_partner_links_roam_mlo_params(struct wlan_objmgr_pdev *pdev,
+					    struct wlan_cm_connect_resp *rsp,
+					    struct cfg80211_roam_info *roam_info_params)
+{
+	struct wlan_objmgr_vdev *partner_vdev;
+	struct mlo_link_info *rsp_partner_info;
+	struct mlo_partner_info assoc_partner_info = {0};
+	struct cfg80211_bss *bss = NULL;
+	QDF_STATUS qdf_status;
+	uint8_t link_id = 0, num_links;
+	int i;
+
+	qdf_status = osif_get_partner_info_from_mlie(rsp, &assoc_partner_info);
+	if (QDF_IS_STATUS_ERROR(qdf_status))
+		return;
+
+	num_links = rsp->ml_parnter_info.num_partner_links;
+	for (i = 0 ; i < num_links; i++) {
+		rsp_partner_info = &rsp->ml_parnter_info.partner_link_info[i];
+
+		qdf_status = osif_get_link_id_from_assoc_ml_ie(rsp_partner_info,
+							       &assoc_partner_info,
+							       &link_id);
+		if (QDF_IS_STATUS_ERROR(qdf_status))
+			continue;
+
+		partner_vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev,
+						      rsp_partner_info->vdev_id,
+						      WLAN_MLO_MGR_ID);
+		if (!partner_vdev)
+			continue;
+
+		bss = osif_get_chan_bss_from_kernel(partner_vdev,
+						    rsp_partner_info, rsp);
+		if (!bss) {
+			wlan_objmgr_vdev_release_ref(partner_vdev,
+						     WLAN_MLO_MGR_ID);
+			continue;
+		}
+
+		osif_populate_mlo_info_for_link(partner_vdev,
+						roam_info_params,
+						link_id, bss);
+		wlan_objmgr_vdev_release_ref(partner_vdev, WLAN_MLO_MGR_ID);
+	}
+}
+
+static QDF_STATUS
+osif_fill_peer_mld_mac_roam_info(struct wlan_objmgr_vdev *vdev,
+				 struct wlan_cm_connect_resp *rsp,
+				 struct cfg80211_roam_info *roam_info_params)
+{
+	struct wlan_objmgr_peer *peer_obj;
+
+	peer_obj = wlan_objmgr_get_peer_by_mac(wlan_vdev_get_psoc(vdev),
+					       rsp->bssid.bytes, WLAN_OSIF_ID);
+	if (!peer_obj)
+		return QDF_STATUS_E_INVAL;
+
+	roam_info_params->ap_mld_addr = wlan_peer_mlme_get_mldaddr(peer_obj);
+
+	wlan_objmgr_peer_release_ref(peer_obj, WLAN_OSIF_ID);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static void osif_fill_mlo_roam_params(struct wlan_objmgr_vdev *vdev,
+				      struct wlan_cm_connect_resp *rsp,
+				      struct cfg80211_bss *bss,
+				      struct cfg80211_roam_info *info)
+{
+	QDF_STATUS qdf_status;
+	uint8_t assoc_link_id;
+
+	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
+		return;
+
+	qdf_status = osif_fill_peer_mld_mac_roam_info(vdev, rsp,
+						      info);
+	if (QDF_IS_STATUS_ERROR(qdf_status)) {
+		osif_err("Unable to fill peer mld address: %d", qdf_status);
+		return;
+	}
+
+	assoc_link_id = wlan_vdev_get_link_id(vdev);
+	osif_populate_mlo_info_for_link(vdev, info,
+					assoc_link_id, bss);
+
+	osif_populate_partner_links_roam_mlo_params(wlan_vdev_get_pdev(vdev),
+						    rsp,
+						    info);
+}
+#else
+static void osif_fill_mlo_roam_params(struct wlan_objmgr_vdev *vdev,
+				      struct wlan_cm_connect_resp *rsp,
+				      struct cfg80211_bss *bss,
+				      struct cfg80211_roam_info *info)
+{}
+#endif
+static void osif_roamed_ind(struct net_device *dev,
+			    struct wlan_objmgr_vdev *vdev,
+			    struct wlan_cm_connect_resp *rsp,
+			    struct cfg80211_bss *bss,
 			    const uint8_t *req_ie,
 			    const uint8_t *req_ie,
 			    size_t req_ie_len, const uint8_t *resp_ie,
 			    size_t req_ie_len, const uint8_t *resp_ie,
 			    size_t resp_ie_len)
 			    size_t resp_ie_len)
@@ -92,14 +211,18 @@ static void osif_roamed_ind(struct net_device *dev, struct cfg80211_bss *bss,
 	info.req_ie_len = req_ie_len;
 	info.req_ie_len = req_ie_len;
 	info.resp_ie = resp_ie;
 	info.resp_ie = resp_ie;
 	info.resp_ie_len = resp_ie_len;
 	info.resp_ie_len = resp_ie_len;
+	osif_fill_mlo_roam_params(vdev, rsp, bss, &info);
 	cfg80211_roamed(dev, &info, qdf_mem_malloc_flags());
 	cfg80211_roamed(dev, &info, qdf_mem_malloc_flags());
 }
 }
 #else
 #else
 static inline void osif_roamed_ind(struct net_device *dev,
 static inline void osif_roamed_ind(struct net_device *dev,
-				   struct cfg80211_bss *bss,
-				   const uint8_t *req_ie, size_t req_ie_len,
-				   const uint8_t *resp_ie,
-				   size_t resp_ie_len)
+			    struct wlan_objmgr_vdev *vdev,
+			    struct wlan_cm_connect_resp *rsp,
+			    struct cfg80211_bss *bss,
+			    const uint8_t *req_ie,
+			    size_t req_ie_len, const uint8_t *resp_ie,
+			    size_t resp_ie_len)
+
 {
 {
 	cfg80211_roamed_bss(dev, bss, req_ie, req_ie_len, resp_ie, resp_ie_len,
 	cfg80211_roamed_bss(dev, bss, req_ie, req_ie_len, resp_ie, resp_ie_len,
 			    qdf_mem_malloc_flags());
 			    qdf_mem_malloc_flags());
@@ -190,6 +313,124 @@ static enum qca_roam_reason osif_get_roam_reason(uint16_t roam_scan_trigger)
 	return QCA_ROAM_REASON_UNKNOWN;
 	return QCA_ROAM_REASON_UNKNOWN;
 }
 }
 
 
+#ifdef WLAN_FEATURE_11BE_MLO
+
+static uint8_t *osif_get_bss_mac_addr(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_objmgr_peer *peer;
+
+	peer = wlan_vdev_get_bsspeer(vdev);
+	if (peer)
+		if (wlan_vdev_mlme_is_mlo_vdev(vdev))
+			return wlan_peer_mlme_get_mldaddr(peer);
+		else
+			return wlan_peer_get_macaddr(peer);
+	else
+		return NULL;
+}
+
+/**
+ * osif_send_roam_auth_mlo_links_event() - API to send roam auth mlo
+ * links event response to kernel
+ * @skb : sk buffer pointer
+ * @vdev: vdev pointer
+ * @rsp: Connection manager response
+ *
+ * This is called when wlan driver needs to send the mlo links roaming
+ * information after roaming.
+ *
+ * Context: Any context.
+ * Return: int
+ */
+static int
+osif_send_roam_auth_mlo_links_event(struct sk_buff *skb,
+				    struct wlan_objmgr_vdev *vdev,
+				    struct vdev_osif_priv *osif_priv,
+				    struct wlan_cm_connect_resp *rsp)
+{
+	struct wlan_objmgr_psoc *psoc;
+	bool roam_offload_enable;
+	uint8_t i;
+	struct nlattr *mlo_links;
+	struct nlattr *mlo_links_info;
+	struct wlan_objmgr_vdev *link_vdev;
+	uint8_t link_vdev_id;
+
+	if (!vdev)
+		return -EINVAL;
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	ucfg_mlme_get_roaming_offload(psoc, &roam_offload_enable);
+
+	if (!roam_offload_enable)
+		return -EINVAL;
+
+	mlo_links  = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MLO_LINKS);
+
+	for (i = 0; i < rsp->ml_parnter_info.num_partner_links; i++) {
+		mlo_links_info = nla_nest_start(skb, i);
+		if (!mlo_links_info) {
+			osif_err("nla nest start fail");
+			return -EINVAL;
+		}
+
+		if (nla_put_u8(skb,
+			       QCA_WLAN_VENDOR_ATTR_MLO_LINK_ID,
+			       rsp->ml_parnter_info.partner_link_info[i].link_id)) {
+			osif_err("nla put fail");
+			return -EINVAL;
+		}
+
+		if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_MLO_LINK_BSSID,
+			    ETH_ALEN,
+			    (void *)&rsp->ml_parnter_info.partner_link_info[i].link_addr)) {
+			osif_err("nla put fail");
+			return -EINVAL;
+		}
+
+		link_vdev_id = rsp->ml_parnter_info.partner_link_info[i].vdev_id;
+		link_vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
+								 link_vdev_id,
+								 WLAN_OSIF_CM_ID);
+		if (!link_vdev) {
+			osif_err("link vdev is null");
+			return -EINVAL;
+		}
+
+		if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_MLO_LINK_MAC_ADDR,
+			    ETH_ALEN, wlan_vdev_mlme_get_macaddr(link_vdev))) {
+			osif_err("nla put fail");
+			return -EINVAL;
+		}
+		nla_nest_end(skb, mlo_links_info);
+	}
+
+	nla_nest_end(skb, mlo_links);
+
+	return 0;
+}
+#else
+static uint8_t *osif_get_bss_mac_addr(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_objmgr_peer *peer;
+
+	peer = wlan_vdev_get_bsspeer(vdev);
+	if (peer)
+		return wlan_peer_get_macaddr(peer);
+	else
+		return NULL;
+}
+
+static inline int
+osif_send_roam_auth_mlo_links_event(struct sk_buff *skb,
+				    struct wlan_objmgr_vdev *vdev,
+				    struct vdev_osif_priv *osif_priv,
+				    struct wlan_cm_connect_resp *rsp)
+{
+	return 0;
+}
+#endif
+
 /**
 /**
  * osif_send_roam_auth_event() - API to send roam auth event response to kernel
  * osif_send_roam_auth_event() - API to send roam auth event response to kernel
  * @vdev: vdev pointer
  * @vdev: vdev pointer
@@ -229,6 +470,8 @@ static int osif_send_roam_auth_event(struct wlan_objmgr_vdev *vdev,
 	int status;
 	int status;
 	int32_t akm;
 	int32_t akm;
 	bool roam_offload_enable;
 	bool roam_offload_enable;
+	uint8_t *bss_mac_addr;
+	uint8_t num_of_links = 0;
 
 
 	psoc = wlan_vdev_get_psoc(vdev);
 	psoc = wlan_vdev_get_psoc(vdev);
 	ucfg_mlme_get_roaming_offload(psoc, &roam_offload_enable);
 	ucfg_mlme_get_roaming_offload(psoc, &roam_offload_enable);
@@ -248,24 +491,46 @@ static int osif_send_roam_auth_event(struct wlan_objmgr_vdev *vdev,
 	fils_params_len = roaming_info->pmk_len + PMKID_LEN +
 	fils_params_len = roaming_info->pmk_len + PMKID_LEN +
 			  sizeof(uint16_t) + (3 * NLMSG_HDRLEN);
 			  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,
-			qdf_mem_malloc_flags());
-
+	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
+#ifdef WLAN_FEATURE_11BE_MLO
+		num_of_links = rsp->ml_parnter_info.num_partner_links;
+#endif
+		skb = cfg80211_vendor_event_alloc(osif_priv->wdev->wiphy,
+				osif_priv->wdev,
+				(ETH_ALEN * num_of_links) +
+				(sizeof(uint8_t) * num_of_links) +
+				(ETH_ALEN * num_of_links) +
+				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,
+				qdf_mem_malloc_flags());
+	} else {
+		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,
+				qdf_mem_malloc_flags());
+	}
 	if (!skb) {
 	if (!skb) {
 		osif_err("cfg80211_vendor_event_alloc failed");
 		osif_err("cfg80211_vendor_event_alloc failed");
 		return -1;
 		return -1;
 	}
 	}
 
 
+	bss_mac_addr = osif_get_bss_mac_addr(vdev);
+	if (!bss_mac_addr) {
+		osif_err("Invalid bss mac addr");
+		goto nla_put_failure;
+	}
 	if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
 	if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
-		    ETH_ALEN, rsp->bssid.bytes) ||
+		    ETH_ALEN, bss_mac_addr) ||
 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
 		    req_ie_len, req_ie) ||
 		    req_ie_len, req_ie) ||
 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
@@ -358,6 +623,15 @@ static int osif_send_roam_auth_event(struct wlan_objmgr_vdev *vdev,
 		}
 		}
 	}
 	}
 
 
+	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
+		status = osif_send_roam_auth_mlo_links_event(skb, vdev,
+							     osif_priv,
+							     rsp);
+		if (status) {
+			osif_err("Send mlo link fail");
+			goto nla_put_failure;
+		}
+	}
 	cfg80211_vendor_event(skb, qdf_mem_malloc_flags());
 	cfg80211_vendor_event(skb, qdf_mem_malloc_flags());
 	return 0;
 	return 0;
 
 
@@ -396,7 +670,6 @@ void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
 				   struct wlan_cm_connect_resp *rsp)
 				   struct wlan_cm_connect_resp *rsp)
 {
 {
 	struct net_device *dev = osif_priv->wdev->netdev;
 	struct net_device *dev = osif_priv->wdev->netdev;
-	struct wlan_objmgr_vdev *assoc_vdev;
 	size_t req_len = 0;
 	size_t req_len = 0;
 	const uint8_t *req_ie = NULL;
 	const uint8_t *req_ie = NULL;
 	size_t rsp_len = 0;
 	size_t rsp_len = 0;
@@ -405,6 +678,10 @@ void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
 	struct ieee80211_channel *chan;
 	struct ieee80211_channel *chan;
 	struct wlan_objmgr_psoc *psoc;
 	struct wlan_objmgr_psoc *psoc;
 
 
+	if (wlan_vdev_mlme_is_mlo_vdev(vdev) &&
+	    wlan_vdev_mlme_is_mlo_link_vdev(vdev))
+		return;
+
 	if (QDF_IS_STATUS_ERROR(rsp->connect_status))
 	if (QDF_IS_STATUS_ERROR(rsp->connect_status))
 		return;
 		return;
 
 
@@ -412,22 +689,6 @@ void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
 	if (!psoc)
 	if (!psoc)
 		return;
 		return;
 
 
-	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
-		assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev);
-		if (!assoc_vdev) {
-			osif_err("Assoc vdev is NULL");
-			return;
-		}
-
-		osif_priv = wlan_vdev_get_ospriv(assoc_vdev);
-		if (!osif_priv) {
-			osif_err("osif_priv is null");
-			return;
-		}
-
-		dev = osif_priv->wdev->netdev;
-	}
-
 	chan = ieee80211_get_channel(osif_priv->wdev->wiphy,
 	chan = ieee80211_get_channel(osif_priv->wdev->wiphy,
 				     rsp->freq);
 				     rsp->freq);
 	bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan,
 	bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan,
@@ -443,7 +704,7 @@ void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
 						&req_len, &req_ie);
 						&req_len, &req_ie);
 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
 				      &rsp_len, &rsp_ie);
 				      &rsp_len, &rsp_ie);
-	osif_roamed_ind(dev, bss, req_ie, req_len, rsp_ie, rsp_len);
+	osif_roamed_ind(dev, vdev, rsp, bss, req_ie, req_len, rsp_ie, rsp_len);
 	osif_send_roam_auth_event(vdev, osif_priv, rsp, req_ie, req_len, rsp_ie,
 	osif_send_roam_auth_event(vdev, osif_priv, rsp, req_ie, req_len, rsp_ie,
 				  rsp_len);
 				  rsp_len);
 
 

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

@@ -156,4 +156,52 @@ osif_cm_indicate_disconnect(struct wlan_objmgr_vdev *vdev,
 			    bool locally_generated, const u8 *ie,
 			    bool locally_generated, const u8 *ie,
 			    size_t ie_len, gfp_t gfp);
 			    size_t ie_len, gfp_t gfp);
 
 
+#ifdef WLAN_FEATURE_11BE_MLO
+/**
+ * osif_get_partner_info_from_mlie() - API to get partner information
+ * from basic variant mlo ie
+ * @rsp: Connection manager connect response for the candidate
+ * @partner_info: mlo partner info pointer
+ *
+ * The API is is used get partner information from basic variant ml ie.
+ *
+ * Context: Any context.
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+osif_get_partner_info_from_mlie(struct wlan_cm_connect_resp *connect_rsp,
+				struct mlo_partner_info *partner_info);
+/**
+ * osif_get_link_id_from_assoc_ml_ie() - API to get link id from assoc rsp
+ * ml ie.
+ * @rsp_link_info: pointer to mlo link info
+ * @partner_info: mlo partner info pointer
+ * @link_id: Link id information
+ *
+ * The API is used to get link id from assoc response basic variant mlo ie
+ *
+ * Context: Any context.
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+osif_get_link_id_from_assoc_ml_ie(struct mlo_link_info *rsp_link_info,
+				  struct mlo_partner_info *assoc_partner_info,
+				  uint8_t *link_id);
+
+/**
+ * osif_get_chan_bss_from_kernel() - API to get chan bss from kernel
+ * @vdev: vdev pointer
+ * @rsp_link_info: pointer to mlo link info
+ * @rsp: Connection manager connect response for the candidate
+ *
+ * The API is used to get chan bss from kernel.
+ *
+ * Context: Any context.
+ * Return: QDF_STATUS
+ */
+struct cfg80211_bss *
+osif_get_chan_bss_from_kernel(struct wlan_objmgr_vdev *vdev,
+			      struct mlo_link_info *rsp_link_info,
+			      struct wlan_cm_connect_resp *rsp);
+#endif
 #endif /* __OSIF_CM_RSP_H */
 #endif /* __OSIF_CM_RSP_H */