Bladeren bron

qcacmn: Fix mlo assoc vdev disconnect before link dev issue

Assoc dev disconnect happened before link vdev for following sequence
1) SB disconnect followed by NB disconnect.
2) SB disconnect queue disconnect on both link and assoc same time.
3) NB disconnect queue link disconnect first and wait for it to complete.

Fix in mlo_sync_disconnect by using sync API only for assoc vdev, for link
vdevs, let the non-sync API post the disconnect, thus all disconnect goes
in 1 instance and wait for assoc disconnect (last) to complete, similar to
SB disconnect.
With this both vdev1 and vdev0 disconnect will be queued at same time, thus
maintain the sequence.

Also optimize the wait time of the assoc vdev in
cm_disconnect_start_req_sync, to include all link disconnect time as well
(DISCONNECT_TIMEOUT * 2 + 5000).

Flush old disconnect only for non-MLO and assoc link, do not flush for link
vdev.

Change-Id: Ibaf4051d6e06a8e8354571e87883ac72b6ac07f0
CRs-Fixed: 3420508
Jianmin Zhu 2 jaren geleden
bovenliggende
commit
b2e038a217

+ 17 - 4
umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c

@@ -641,7 +641,12 @@ cm_handle_discon_req_in_non_connected_state(struct cnx_mgr *cm_ctx,
 		mlme_cm_osif_update_id_and_src(cm_ctx->vdev,
 					       CM_SOURCE_INVALID,
 					       CM_ID_INVALID);
-		cm_flush_pending_request(cm_ctx, DISCONNECT_REQ_PREFIX, false);
+
+		/* Flush for non mlo link vdev only */
+		if (!wlan_vdev_mlme_is_mlo_vdev(cm_ctx->vdev) ||
+		    !wlan_vdev_mlme_is_mlo_link_vdev(cm_ctx->vdev))
+			cm_flush_pending_request(cm_ctx, DISCONNECT_REQ_PREFIX,
+						 false);
 		/*
 		 * Flush failed pending connect req as new req is received
 		 * and its no longer the latest one.
@@ -774,15 +779,18 @@ QDF_STATUS cm_disconnect_start_req_sync(struct wlan_objmgr_vdev *vdev,
 {
 	struct cnx_mgr *cm_ctx;
 	QDF_STATUS status;
+	uint32_t timeout;
+	bool is_assoc_vdev = false;
 
 	cm_ctx = cm_get_cm_ctx(vdev);
 	if (!cm_ctx)
 		return QDF_STATUS_E_INVAL;
 
 	if (wlan_vdev_mlme_is_mlo_vdev(vdev) &&
-	    !wlan_vdev_mlme_is_mlo_link_vdev(vdev))
+	    !wlan_vdev_mlme_is_mlo_link_vdev(vdev)) {
 		req->is_no_disassoc_disconnect = 1;
-
+		is_assoc_vdev = true;
+	}
 	qdf_event_reset(&cm_ctx->disconnect_complete);
 	status = cm_disconnect_start_req(vdev, req);
 	if (QDF_IS_STATUS_ERROR(status)) {
@@ -790,8 +798,13 @@ QDF_STATUS cm_disconnect_start_req_sync(struct wlan_objmgr_vdev *vdev,
 		return status;
 	}
 
+	if (is_assoc_vdev)
+		timeout = CM_DISCONNECT_CMD_TIMEOUT +
+			  CM_DISCONNECT_ASSOC_VDEV_EXTRA_TIMEOUT;
+	else
+		timeout = CM_DISCONNECT_CMD_TIMEOUT;
 	status = qdf_wait_single_event(&cm_ctx->disconnect_complete,
-				       CM_DISCONNECT_CMD_TIMEOUT);
+				       timeout);
 	if (QDF_IS_STATUS_ERROR(status))
 		mlme_err("Disconnect timeout with status %d", status);
 

+ 3 - 0
umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h

@@ -39,6 +39,9 @@ typedef uint32_t wlan_cm_id;
 	((STOP_RESPONSE_TIMER) + (DELETE_RESPONSE_TIMER) +\
 	 (RSO_STOP_RESPONSE_TIMER) + (1000))
 
+#define CM_DISCONNECT_ASSOC_VDEV_EXTRA_TIMEOUT \
+		(STOP_RESPONSE_TIMER + DELETE_RESPONSE_TIMER)
+
 /*
  * Disconnect command wait timeout VDEV timeouts + 5 sec buff for current active
  * command to complete

+ 6 - 2
umac/mlo_mgr/src/wlan_mlo_mgr_sta.c

@@ -1203,10 +1203,14 @@ mlo_send_link_disconnect_sync(struct wlan_mlo_dev_context *mlo_dev_ctx,
 		if (!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
+		 */
 		if (mlo_dev_ctx->wlan_vdev_list[i] !=
 		    mlo_get_assoc_link_vdev(mlo_dev_ctx))
-			wlan_cm_disconnect_sync(mlo_dev_ctx->wlan_vdev_list[i],
-						source, reason_code);
+			wlan_cm_disconnect(mlo_dev_ctx->wlan_vdev_list[i],
+					   source, reason_code, NULL);
 	}
 
 	wlan_cm_disconnect_sync(assoc_vdev,