Răsfoiți Sursa

qcacmn: Add vdev up bitmap for mlo sync wait state handling

In MLO scenario where start/cac response for partner ML AP vdevs are
processed simultaneously on different CPU cores, the order in which
the vdev sm lock is acquired may lead to deadlock.
To fix add change to have vdev up bitmap and process sync complete
only for those vdevs for which the bitmap is set

Change-Id: I9ca8b192edeb7d491be3a7acff30c2d3545a5417
CRs-Fixed: 3403603
Himanshu Batra 2 ani în urmă
părinte
comite
d1d1ea0482

+ 25 - 0
umac/mlme/vdev_mgr/core/src/vdev_mlme_sm.c

@@ -1728,10 +1728,35 @@ static void mlme_vdev_subst_mlo_sync_wait_entry(void *ctx)
  *
  * Return: void
  */
+#ifdef WLAN_FEATURE_11BE_MLO
+static void mlme_vdev_subst_mlo_sync_wait_exit(void *ctx)
+{
+	struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx;
+	struct wlan_objmgr_vdev *vdev = vdev_mlme->vdev;
+	struct wlan_mlo_dev_context *mld_ctx = vdev->mlo_dev_ctx;
+	enum QDF_OPMODE mode;
+	uint8_t idx;
+
+	if (!vdev->mlo_dev_ctx)
+		return;
+
+	idx = mlo_get_link_vdev_ix(mld_ctx, vdev);
+	if (idx == MLO_INVALID_LINK_IDX)
+		return;
+
+	mode = wlan_vdev_mlme_get_opmode(vdev);
+	if (mode != QDF_SAP_MODE)
+		return;
+
+	wlan_util_change_map_index(mld_ctx->ap_ctx->mlo_vdev_up_bmap,
+				   idx, 0);
+}
+#else
 static void mlme_vdev_subst_mlo_sync_wait_exit(void *ctx)
 {
 	/* NONE */
 }
+#endif
 
 /**
  * mlme_vdev_subst_mlo_sync_wait_event() - Event handler API for mlo sync wait

+ 2 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h

@@ -325,6 +325,7 @@ struct wlan_mlo_sta {
  * @ml_aid_mgr: ML AID mgr
  * @mlo_ap_lock: lock to sync VDEV SM event
  * @mlo_vdev_quiet_bmap: Bitmap of vdevs for which quiet ie needs to enabled
+ * @mlo_vdev_up_bmap: Bitmap of vdevs for which sync complete can be dispatched
  *
  * NB: not using kernel-doc format since the kernel-doc script doesn't
  *     handle the qdf_bitmap() macro
@@ -338,6 +339,7 @@ struct wlan_mlo_ap {
 	qdf_mutex_t mlo_ap_lock;
 #endif
 	qdf_bitmap(mlo_vdev_quiet_bmap, WLAN_UMAC_MLO_MAX_VDEVS);
+	qdf_bitmap(mlo_vdev_up_bmap, WLAN_UMAC_MLO_MAX_VDEVS);
 };
 
 /**

+ 35 - 3
umac/mlo_mgr/src/wlan_mlo_mgr_ap.c

@@ -327,27 +327,59 @@ static bool mlo_pre_link_up(struct wlan_objmgr_vdev *vdev)
 static bool mlo_handle_link_ready(struct wlan_objmgr_vdev *vdev)
 {
 	struct wlan_objmgr_vdev *vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {NULL};
+	struct wlan_mlo_dev_context *mld_ctx = NULL;
 	uint16_t num_links = 0;
 	uint8_t i;
+	uint8_t idx;
+	enum wlan_vdev_state state;
+
 
 	if (!vdev || !vdev->mlo_dev_ctx) {
 		mlo_err("Invalid input");
 		return false;
 	}
 
-	if (!mlo_is_ap_vdev_up_allowed(vdev))
+	mld_ctx = vdev->mlo_dev_ctx;
+	mlo_ap_lock_acquire(vdev->mlo_dev_ctx->ap_ctx);
+	state = wlan_vdev_mlme_get_state(vdev);
+	if (state == WLAN_VDEV_S_UP) {
+		idx = mlo_get_link_vdev_ix(mld_ctx, vdev);
+		if (idx == MLO_INVALID_LINK_IDX) {
+			mlo_ap_lock_release(vdev->mlo_dev_ctx->ap_ctx);
+			return false;
+		}
+		wlan_util_change_map_index(mld_ctx->ap_ctx->mlo_vdev_up_bmap,
+					   idx, 1);
+	}
+
+	if (!mlo_is_ap_vdev_up_allowed(vdev)) {
+		mlo_ap_lock_release(vdev->mlo_dev_ctx->ap_ctx);
 		return false;
+	}
 
 	mlo_ap_get_vdev_list(vdev, &num_links, vdev_list);
 	if (!num_links || (num_links > QDF_ARRAY_SIZE(vdev_list))) {
 		mlo_err("Invalid number of VDEVs under AP-MLD");
+		mlo_ap_lock_release(vdev->mlo_dev_ctx->ap_ctx);
 		return false;
 	}
 
-	mlo_ap_lock_acquire(vdev->mlo_dev_ctx->ap_ctx);
 	for (i = 0; i < num_links; i++) {
 		if (mlo_pre_link_up(vdev_list[i])) {
-			if (vdev_list[i] != vdev)
+			if (vdev_list[i] == vdev) {
+				mlo_release_vdev_ref(vdev_list[i]);
+				continue;
+			}
+
+			idx = mlo_get_link_vdev_ix(mld_ctx, vdev_list[i]);
+			if (idx == MLO_INVALID_LINK_IDX) {
+				mlo_release_vdev_ref(vdev_list[i]);
+				continue;
+			}
+
+			if (wlan_util_map_index_is_set(
+				vdev->mlo_dev_ctx->ap_ctx->mlo_vdev_up_bmap,
+				idx))
 				wlan_vdev_mlme_sm_deliver_evt(
 					vdev_list[i],
 					WLAN_VDEV_SM_EV_MLO_SYNC_COMPLETE,