Browse Source

qcacld-3.0: Fetch MLO disconnecting vdev from RSO stop rsp ctx

Host maintains RSO state machine only for assoc vdev as it's
good enough to have only one state machine. Thus host sends RSO
stop request to firmware on assoc vdev though actual disconnect
started on link vdev. Firmware also sends response on the
same vdev. But disconnect has to be resumed for link vdev as
it's paused and waiting for RSO stop response. So, fetch link
vdev from assoc vdev and continue disconnect.

Change-Id: Ib2bc2610a03ba94408d6241d48756872c5ee2ad6
CRs-Fixed: 3135907
Srinivas Dasari 3 years ago
parent
commit
795af8a246

+ 67 - 1
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_disconnect.c

@@ -401,14 +401,80 @@ QDF_STATUS cm_handle_disconnect_resp(struct scheduler_msg *msg)
 	return QDF_STATUS_SUCCESS;
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO
+static QDF_STATUS
+wlan_cm_mlo_update_disconnecting_vdev_id(struct wlan_objmgr_psoc *psoc,
+					 uint8_t *vdev_id)
+{
+	struct wlan_objmgr_vdev *vdev = NULL;
+	struct wlan_objmgr_vdev *vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {NULL};
+	uint16_t num_links = 0, i = 0;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, *vdev_id,
+						    WLAN_MLME_SB_ID);
+	if (!vdev) {
+		mlme_err("vdev_id: %d vdev not found", *vdev_id);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
+		status = QDF_STATUS_SUCCESS;
+		goto done;
+	}
+
+	mlo_get_ml_vdev_list(vdev, &num_links, vdev_list);
+	if (!num_links) {
+		mlme_err("No VDEVs under vdev id: %d", *vdev_id);
+		status = QDF_STATUS_E_NULL_VALUE;
+		goto done;
+	}
+
+	if (num_links > QDF_ARRAY_SIZE(vdev_list)) {
+		mlme_err("Invalid number of VDEVs num_links:%u", num_links);
+		status = QDF_STATUS_E_INVAL;
+		goto release_mlo_ref;
+	}
+
+	for (i = 0; i < num_links; i++) {
+		if (wlan_vdev_mlme_is_mlo_vdev(vdev_list[i]) &&
+		    wlan_cm_is_vdev_disconnecting(vdev_list[i])) {
+			/*
+			 * This is expected to match only once as per current
+			 * design.
+			 */
+			*vdev_id = wlan_vdev_get_id(vdev_list[i]);
+			break;
+		}
+	}
+
+release_mlo_ref:
+	for (i = 0; i < QDF_ARRAY_SIZE(vdev_list); i++)
+		mlo_release_vdev_ref(vdev_list[i]);
+
+done:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
+
+	return status;
+}
+#else
+static QDF_STATUS
+wlan_cm_mlo_update_disconnecting_vdev_id(struct wlan_objmgr_psoc *psoc,
+					 uint8_t *vdev_id)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+#endif /* WLAN_FEATURE_11BE_MLO */
+
 QDF_STATUS
 wlan_cm_rso_stop_continue_disconnect(struct wlan_objmgr_psoc *psoc,
-				     uint8_t vdev_id, bool is_ho_fail)
+				     uint8_t rso_stop_vdev_id, bool is_ho_fail)
 {
 	struct wlan_objmgr_vdev *vdev = NULL;
 	struct wlan_cm_vdev_discon_req *req;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	uint8_t vdev_id = rso_stop_vdev_id;
 
+	wlan_cm_mlo_update_disconnecting_vdev_id(psoc, &vdev_id);
 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
 						    WLAN_MLME_SB_ID);
 	if (!vdev) {