瀏覽代碼

qcacmn: Disconnect VDEVs in IDLE_DUE_TO_LINK_SWITCH

Host driver moves VDEV SM to IDLE_DUE_TO_LINK_SWITCH any link
switch failure to handle events such as DISCONNECT_REQ which
gets dropped if the VDEV is in INIT state.

Disconnect request on any ML VDEV initiates disconnect on partner
VDEVs as well if they are either in connected or connecting state
but not if in IDLE_DUE_TO_LINK_SWITCH state. This leaves the VDEV
in this new IDLE_DUE_TO_LINK_SWITCH state instead of in INIT state.

Include VDEVs which are in IDLE_DUE_TO_LINK_SWITCH during partner
VDEV disconnect so that VDEV SM moves to INIT.

Change-Id: I6e715c0bb94562be866e902009b3bfd7d2c60e8a
CRs-Fixed: 3659110
Vinod Kumar Pirla 1 年之前
父節點
當前提交
1bfe0bb643

+ 20 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h

@@ -1065,6 +1065,26 @@ bool cm_is_vdev_disconnecting(struct wlan_objmgr_vdev *vdev);
  */
  */
 bool cm_is_vdev_disconnected(struct wlan_objmgr_vdev *vdev);
 bool cm_is_vdev_disconnected(struct wlan_objmgr_vdev *vdev);
 
 
+#ifdef CONN_MGR_ADV_FEATURE
+/**
+ * cm_is_vdev_idle_due_to_link_switch() - Check if VDEV is in
+ * IDLE state due to link switch
+ * @vdev: VDEV objmgr pointer
+ *
+ * Returns true if the current CM SS is WLAN_CM_SS_IDLE_DUE_TO_LINK_SWITCH or
+ * returns false.
+ *
+ * Return: bool
+ */
+bool cm_is_vdev_idle_due_to_link_switch(struct wlan_objmgr_vdev *vdev);
+#else
+static inline bool
+cm_is_vdev_idle_due_to_link_switch(struct wlan_objmgr_vdev *vdev)
+{
+	return false;
+}
+#endif
+
 /**
 /**
  * cm_is_vdev_roaming() - check if vdev is in roaming state
  * cm_is_vdev_roaming() - check if vdev is in roaming state
  * @vdev: vdev pointer
  * @vdev: vdev pointer

+ 22 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_util.c

@@ -1387,6 +1387,28 @@ bool cm_is_vdev_disconnected(struct wlan_objmgr_vdev *vdev)
 	return false;
 	return false;
 }
 }
 
 
+#ifdef CONN_MGR_ADV_FEATURE
+bool cm_is_vdev_idle_due_to_link_switch(struct wlan_objmgr_vdev *vdev)
+{
+	struct cnx_mgr *cm_ctx;
+	enum wlan_cm_sm_state state;
+	enum wlan_cm_sm_state sub_state;
+
+	cm_ctx = cm_get_cm_ctx(vdev);
+	if (!cm_ctx)
+		return false;
+
+	state = cm_get_state(cm_ctx);
+	sub_state = cm_get_sub_state(cm_ctx);
+
+	if (state == WLAN_CM_S_INIT &&
+	    sub_state == WLAN_CM_SS_IDLE_DUE_TO_LINK_SWITCH)
+		return true;
+
+	return false;
+}
+#endif
+
 bool cm_is_vdev_roaming(struct wlan_objmgr_vdev *vdev)
 bool cm_is_vdev_roaming(struct wlan_objmgr_vdev *vdev)
 {
 {
 	struct cnx_mgr *cm_ctx;
 	struct cnx_mgr *cm_ctx;

+ 9 - 0
umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h

@@ -197,6 +197,15 @@ bool wlan_cm_is_vdev_disconnecting(struct wlan_objmgr_vdev *vdev);
  */
  */
 bool wlan_cm_is_vdev_disconnected(struct wlan_objmgr_vdev *vdev);
 bool wlan_cm_is_vdev_disconnected(struct wlan_objmgr_vdev *vdev);
 
 
+/**
+ * wlan_cm_is_vdev_idle_due_to_link_switch() - Check if VDEV is in IDLE
+ * due to link switch sub-state.
+ * @vdev: VDEV objmgr pointer
+ *
+ * Return: bool
+ */
+bool wlan_cm_is_vdev_idle_due_to_link_switch(struct wlan_objmgr_vdev *vdev);
+
 /**
 /**
  * wlan_cm_is_vdev_roaming() - check if vdev is in roaming state
  * wlan_cm_is_vdev_roaming() - check if vdev is in roaming state
  * @vdev: vdev pointer
  * @vdev: vdev pointer

+ 5 - 0
umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c

@@ -192,6 +192,11 @@ bool wlan_cm_is_vdev_disconnected(struct wlan_objmgr_vdev *vdev)
 	return cm_is_vdev_disconnected(vdev);
 	return cm_is_vdev_disconnected(vdev);
 }
 }
 
 
+bool wlan_cm_is_vdev_idle_due_to_link_switch(struct wlan_objmgr_vdev *vdev)
+{
+	return cm_is_vdev_idle_due_to_link_switch(vdev);
+}
+
 bool wlan_cm_is_vdev_roaming(struct wlan_objmgr_vdev *vdev)
 bool wlan_cm_is_vdev_roaming(struct wlan_objmgr_vdev *vdev)
 {
 {
 	return cm_is_vdev_roaming(vdev);
 	return cm_is_vdev_roaming(vdev);

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

@@ -288,7 +288,8 @@ mlo_send_link_disconnect(struct wlan_objmgr_vdev *vdev,
 		if ((wlan_vdev_list[i] != assoc_vdev) &&
 		if ((wlan_vdev_list[i] != assoc_vdev) &&
 		    (qdf_test_bit(i, sta_ctx->wlan_connected_links) ||
 		    (qdf_test_bit(i, sta_ctx->wlan_connected_links) ||
 		    (wlan_cm_is_vdev_connected(wlan_vdev_list[i]) &&
 		    (wlan_cm_is_vdev_connected(wlan_vdev_list[i]) &&
-		    !wlan_peer_is_mlo(wlan_vdev_get_bsspeer(wlan_vdev_list[i])))))
+		    !wlan_peer_is_mlo(wlan_vdev_get_bsspeer(wlan_vdev_list[i]))) ||
+		    wlan_cm_is_vdev_idle_due_to_link_switch(wlan_vdev_list[i])))
 			wlan_cm_disconnect(wlan_vdev_list[i],
 			wlan_cm_disconnect(wlan_vdev_list[i],
 					   link_source, reason_code,
 					   link_source, reason_code,
 					   NULL);
 					   NULL);
@@ -2331,7 +2332,8 @@ void mlo_internal_disconnect_links(struct wlan_objmgr_vdev *vdev)
 	for (i =  0; i < vdev_count; i++) {
 	for (i =  0; i < vdev_count; i++) {
 		if (wlan_vdev_list[i] != assoc_vdev &&
 		if (wlan_vdev_list[i] != assoc_vdev &&
 		    (wlan_cm_is_vdev_connected(wlan_vdev_list[i]) ||
 		    (wlan_cm_is_vdev_connected(wlan_vdev_list[i]) ||
-		     wlan_cm_is_vdev_connecting(wlan_vdev_list[i])))
+		     wlan_cm_is_vdev_connecting(wlan_vdev_list[i]) ||
+		     wlan_cm_is_vdev_idle_due_to_link_switch(wlan_vdev_list[i])))
 			wlan_cm_disconnect(wlan_vdev_list[i],
 			wlan_cm_disconnect(wlan_vdev_list[i],
 					   CM_MLO_LINK_VDEV_DISCONNECT,
 					   CM_MLO_LINK_VDEV_DISCONNECT,
 					   REASON_UNSPEC_FAILURE,
 					   REASON_UNSPEC_FAILURE,