Explorar o código

qcacmn: Reset Roam state for link vdev after link switch

After link switch, the assoc vdev and link vdev could change.
So once the link switch is complete, change the roam state to
DEINIT for the link vdevs

Change-Id: I3e583fc1cb5be8d17d8680dab96461b058740c0a
CRs-Fixed: 3581730
Pragaspathi Thilagaraj hai 1 ano
pai
achega
5a0e761ce4

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

@@ -30,6 +30,7 @@
 #include <wlan_cfg80211.h>
 #include <wlan_cfg80211_scan.h>
 #include "wlan_mlo_mgr_sta.h"
+#include "wlan_mlo_mgr_link_switch.h"
 #ifdef CONN_MGR_ADV_FEATURE
 #include "wlan_mlme_ucfg_api.h"
 #endif
@@ -358,7 +359,8 @@ osif_send_roam_auth_mlo_links_event(struct sk_buff *skb,
 	struct nlattr *mlo_links;
 	struct nlattr *mlo_links_info;
 	struct wlan_objmgr_vdev *link_vdev;
-	uint8_t link_vdev_id;
+	uint8_t link_vdev_id, link_id;
+	struct qdf_mac_addr link_addr;
 
 	if (!vdev)
 		return -EINVAL;
@@ -382,6 +384,8 @@ osif_send_roam_auth_mlo_links_event(struct sk_buff *skb,
 			return -EINVAL;
 		}
 
+		osif_debug("send roam auth for partner link:%d",
+			   rsp->ml_parnter_info.partner_link_info[i].link_id);
 		if (nla_put_u8(skb,
 			       QCA_WLAN_VENDOR_ATTR_MLO_LINK_ID,
 			       rsp->ml_parnter_info.partner_link_info[i].link_id)) {
@@ -396,23 +400,42 @@ osif_send_roam_auth_mlo_links_event(struct sk_buff *skb,
 			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;
+		link_vdev_id =
+			rsp->ml_parnter_info.partner_link_info[i].vdev_id;
+		link_id = rsp->ml_parnter_info.partner_link_info[i].link_id;
+
+		/* Standby link */
+		if (link_vdev_id == WLAN_INVALID_VDEV_ID) {
+			struct mlo_link_info *standby_info =
+					mlo_mgr_get_ap_link_by_link_id(vdev,
+								       link_id);
+			if (standby_info) {
+				link_addr = standby_info->link_addr;
+			} else {
+				osif_err("link addr is null for id:%d",
+					 link_id);
+				return -EINVAL;
+			}
+		} else {
+			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;
+			}
+
+			qdf_copy_macaddr(&link_addr,
+					 (struct qdf_mac_addr *)wlan_vdev_mlme_get_macaddr(link_vdev));
+			wlan_objmgr_vdev_release_ref(link_vdev,
+						     WLAN_OSIF_CM_ID);
 		}
 
 		if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_MLO_LINK_MAC_ADDR,
-			    ETH_ALEN, wlan_vdev_mlme_get_macaddr(link_vdev))) {
+			    ETH_ALEN, link_addr.bytes)) {
 			osif_err("nla put fail");
-			wlan_objmgr_vdev_release_ref(link_vdev,
-						     WLAN_OSIF_CM_ID);
 			return -EINVAL;
 		}
-		wlan_objmgr_vdev_release_ref(link_vdev, WLAN_OSIF_CM_ID);
 		nla_nest_end(skb, mlo_links_info);
 	}
 

+ 15 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_link_switch.h

@@ -188,6 +188,21 @@ mlo_mgr_update_link_info_mac_addr(struct wlan_objmgr_vdev *vdev,
  */
 void mlo_mgr_update_link_info_reset(struct wlan_mlo_dev_context *ml_dev);
 
+/**
+ * mlo_mgr_roam_update_ap_link_info() - Update AP links information
+ * @vdev: Object Manager vdev
+ * @link_id: Link id of the AP MLD link
+ * @ap_link_addr: AP link addresses
+ * @channel: wlan channel information of the link
+ *
+ * Update AP link information for each link of AP MLD
+ * Return: void
+ */
+void mlo_mgr_roam_update_ap_link_info(struct wlan_objmgr_vdev *vdev,
+				      uint8_t link_id,
+				      uint8_t *ap_link_addr,
+				      struct wlan_channel channel);
+
 /**
  * mlo_mgr_update_ap_link_info() - Update AP links information
  * @vdev: Object Manager vdev

+ 5 - 1
umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h

@@ -549,6 +549,10 @@ struct mlo_nstr_info {
 	uint16_t nstr_lp_bitmap;
 };
 
+#ifndef WLAN_MAX_ML_BSS_LINKS
+#define WLAN_MAX_ML_BSS_LINKS WLAN_UMAC_MLO_MAX_VDEVS
+#endif
+
 /**
  * struct mlo_partner_info - mlo partner link info
  * @num_partner_links: no. of partner links
@@ -559,7 +563,7 @@ struct mlo_nstr_info {
  */
 struct mlo_partner_info {
 	uint8_t num_partner_links;
-	struct mlo_link_info partner_link_info[WLAN_UMAC_MLO_MAX_VDEVS];
+	struct mlo_link_info partner_link_info[WLAN_MAX_ML_BSS_LINKS];
 #ifdef WLAN_FEATURE_11BE
 	enum wlan_t2lm_enable t2lm_enable_val;
 	struct mlo_nstr_info nstr_info[WLAN_UMAC_MLO_MAX_VDEVS];

+ 57 - 1
umac/mlo_mgr/src/wlan_mlo_mgr_link_switch.c

@@ -23,6 +23,9 @@
 #include <wlan_serialization_api.h>
 #include <wlan_cm_api.h>
 #include <wlan_crypto_def_i.h>
+#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
+#include "wlan_cm_roam_api.h"
+#endif
 
 void mlo_mgr_update_link_info_mac_addr(struct wlan_objmgr_vdev *vdev,
 				       struct wlan_mlo_link_mac_update *ml_mac_update)
@@ -52,6 +55,34 @@ void mlo_mgr_update_link_info_mac_addr(struct wlan_objmgr_vdev *vdev,
 	}
 }
 
+void mlo_mgr_roam_update_ap_link_info(struct wlan_objmgr_vdev *vdev,
+				      uint8_t link_id, uint8_t *ap_link_addr,
+				      struct wlan_channel channel)
+{
+	struct mlo_link_info *link_info;
+	uint8_t iter;
+
+	if (!vdev || !vdev->mlo_dev_ctx || !vdev->mlo_dev_ctx->link_ctx ||
+	    !ap_link_addr)
+		return;
+
+	for (iter = 0; iter < WLAN_MAX_ML_BSS_LINKS; iter++) {
+		link_info = &vdev->mlo_dev_ctx->link_ctx->links_info[iter];
+		if (link_id == link_info->link_id)
+			break;
+	}
+
+	if (iter == WLAN_MAX_ML_BSS_LINKS)
+		return;
+
+	qdf_mem_copy(&link_info->ap_link_addr, ap_link_addr, QDF_MAC_ADDR_SIZE);
+	qdf_mem_copy(link_info->link_chan_info, &channel, sizeof(channel));
+
+	mlo_debug("Update AP Link info for link_id: %d, vdev_id:%d, link_addr:" QDF_MAC_ADDR_FMT,
+		  link_info->link_id, link_info->vdev_id,
+		  QDF_MAC_ADDR_REF(link_info->ap_link_addr.bytes));
+}
+
 void mlo_mgr_update_ap_link_info(struct wlan_objmgr_vdev *vdev, uint8_t link_id,
 				 uint8_t *ap_link_addr,
 				 struct wlan_channel channel)
@@ -75,6 +106,7 @@ void mlo_mgr_update_ap_link_info(struct wlan_objmgr_vdev *vdev, uint8_t link_id,
 		return;
 
 	qdf_mem_copy(&link_info->ap_link_addr, ap_link_addr, QDF_MAC_ADDR_SIZE);
+
 	qdf_mem_copy(link_info->link_chan_info, &channel, sizeof(channel));
 	link_info->link_status_flags = 0;
 	link_info->link_id = link_id;
@@ -139,7 +171,7 @@ void mlo_mgr_reset_ap_link_info(struct wlan_objmgr_vdev *vdev)
 	uint8_t link_info_iter;
 	struct wlan_objmgr_psoc *psoc;
 
-	if (!vdev || !vdev->mlo_dev_ctx)
+	if (!vdev || !vdev->mlo_dev_ctx || !vdev->mlo_dev_ctx->link_ctx)
 		return;
 
 	psoc = wlan_vdev_get_psoc(vdev);
@@ -331,6 +363,28 @@ mlo_mgr_link_switch_get_curr_state(struct wlan_mlo_dev_context *mlo_dev_ctx)
 	return state;
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
+static void
+mlo_mgr_reset_roam_state_for_link_vdev(struct wlan_objmgr_vdev *vdev,
+				       struct wlan_objmgr_vdev *assoc_vdev)
+{
+	QDF_STATUS status;
+
+	status = wlan_cm_roam_state_change(wlan_vdev_get_pdev(vdev),
+					   wlan_vdev_get_id(assoc_vdev),
+					   WLAN_ROAM_DEINIT,
+					   REASON_ROAM_LINK_SWITCH_ASSOC_VDEV_CHANGE);
+	if (QDF_IS_STATUS_ERROR(status))
+		mlo_err("vdev:%d failed to change RSO state to deinit",
+			wlan_vdev_get_id(assoc_vdev));
+}
+#else
+static inline void
+mlo_mgr_reset_roam_state_for_link_vdev(struct wlan_objmgr_vdev *vdev,
+				       struct wlan_objmgr_vdev *assoc_vdev)
+{}
+#endif
+
 QDF_STATUS mlo_mgr_link_switch_notification(struct wlan_objmgr_vdev *vdev,
 					    struct wlan_mlo_link_switch_req *lswitch_req)
 {
@@ -360,6 +414,8 @@ QDF_STATUS mlo_mgr_link_switch_notification(struct wlan_objmgr_vdev *vdev,
 	if (lswitch_req->restore_vdev_flag) {
 		wlan_vdev_mlme_clear_mlo_link_vdev(vdev);
 		wlan_vdev_mlme_set_mlo_link_vdev(assoc_vdev);
+		mlo_mgr_reset_roam_state_for_link_vdev(vdev, assoc_vdev);
+
 		lswitch_req->restore_vdev_flag = false;
 
 		status = cb(assoc_vdev, wlan_vdev_get_id(vdev));