浏览代码

qcacmn: Remove the assumption of assoc link's presence post connection

With MLO link removal, AP can remove a link that happens to be the assoc
link for a given Non-AP MLD. So far, the Non-AP MLD has been using the
assoc link to interact with other layers and make various decisions.
Change those behaviors on a case-by-case basis.

CRs-Fixed: 3577559
Change-Id: Iaa001bdd2571bce424a953caa3197a99a6f84180
Shiva Krishna Pittala 1 年之前
父节点
当前提交
f796368068
共有 2 个文件被更改,包括 36 次插入23 次删除
  1. 13 4
      os_if/linux/mlme/src/osif_cm_disconnect_rsp.c
  2. 23 19
      umac/mlo_mgr/src/wlan_mlo_mgr_sta.c

+ 13 - 4
os_if/linux/mlme/src/osif_cm_disconnect_rsp.c

@@ -164,11 +164,20 @@ osif_cm_indicate_disconnect(struct wlan_objmgr_vdev *vdev,
 	}
 
 	if (ucfg_mlo_is_mld_disconnected(vdev)) {
+		/**
+		 * Kernel maintains some extra state on the assoc netdev.
+		 * If the assoc vdev exists, send disconnected event on the
+		 * assoc netdev so that kernel cleans up the extra state.
+		 * If the assoc vdev was already removed, kernel would have
+		 * already cleaned up the extra state while processing the
+		 * disconnected event sent as part of the link removal.
+		 */
 		assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev);
-		if (!assoc_vdev)
-			return;
-		osif_priv  = wlan_vdev_get_ospriv(assoc_vdev);
-		netdev = osif_priv->wdev->netdev;
+		if (assoc_vdev) {
+			osif_priv = wlan_vdev_get_ospriv(assoc_vdev);
+			netdev = osif_priv->wdev->netdev;
+		}
+
 		osif_cm_indicate_disconnect_result(
 				netdev, reason,
 				ie, ie_len,

+ 23 - 19
umac/mlo_mgr/src/wlan_mlo_mgr_sta.c

@@ -295,8 +295,8 @@ mlo_send_link_disconnect(struct wlan_objmgr_vdev *vdev,
 		mlo_release_vdev_ref(wlan_vdev_list[i]);
 	}
 
-	wlan_cm_disconnect(assoc_vdev,
-			   source, reason_code, NULL);
+	if (assoc_vdev)
+		wlan_cm_disconnect(assoc_vdev, source, reason_code, NULL);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -517,8 +517,6 @@ static QDF_STATUS mlo_disconnect_no_lock(struct wlan_objmgr_vdev *vdev,
 			return QDF_STATUS_E_FAILURE;
 
 		assoc_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx);
-		if (!assoc_vdev)
-			return QDF_STATUS_E_FAILURE;
 
 		if (sta_ctx->connect_req) {
 			wlan_cm_free_connect_req(sta_ctx->connect_req);
@@ -545,8 +543,9 @@ static QDF_STATUS mlo_disconnect_no_lock(struct wlan_objmgr_vdev *vdev,
 						   NULL);
 		}
 
-		wlan_cm_disconnect(assoc_vdev,
-				   source, reason_code, NULL);
+		if (assoc_vdev)
+			wlan_cm_disconnect(assoc_vdev, source,
+					   reason_code, NULL);
 	}
 
 	return status;
@@ -1290,28 +1289,33 @@ mlo_send_link_disconnect_sync(struct wlan_mlo_dev_context *mlo_dev_ctx,
 			      struct qdf_mac_addr *bssid)
 {
 	uint8_t i;
-	struct wlan_objmgr_vdev *assoc_vdev =
-			mlo_get_assoc_link_vdev(mlo_dev_ctx);
-
-	if (!assoc_vdev)
-		return QDF_STATUS_E_FAILURE;
+	struct wlan_objmgr_vdev *sync_vdev =
+		mlo_get_assoc_link_vdev(mlo_dev_ctx);
 
 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
 		if (!mlo_dev_ctx->wlan_vdev_list[i])
 			continue;
 
-		/*
+		/**
+		 * If the assoc vdev isn't present, use the first link dev as
+		 * sync candidate.
+		 */
+		if (!sync_vdev) {
+			sync_vdev = mlo_dev_ctx->wlan_vdev_list[i];
+			continue;
+		}
+
+		/**
 		 * To initiate disconnect on all links at once, no need to use
-		 * sync API for link Vdev
+		 * sync API for all link vdevs.
 		 */
-		if (mlo_dev_ctx->wlan_vdev_list[i] !=
-		    mlo_get_assoc_link_vdev(mlo_dev_ctx))
-			wlan_cm_disconnect(mlo_dev_ctx->wlan_vdev_list[i],
-					   source, reason_code, NULL);
+		wlan_cm_disconnect(mlo_dev_ctx->wlan_vdev_list[i],
+				   source, reason_code, NULL);
 	}
 
-	wlan_cm_disconnect_sync(assoc_vdev,
-				source, reason_code);
+	if (sync_vdev)
+		wlan_cm_disconnect_sync(sync_vdev, source, reason_code);
+
 	return QDF_STATUS_SUCCESS;
 }