ソースを参照

qcacmn: Reject link switch if chan_switch is in progress on current MLD

Currently, firmware doesn't send CSA event to host when there is
a link_switch request is given to host. Similarly, it doesn't
send link_switch if CSA is in progress.
Host driver can also initiate channel switch operation when
it detects a change in the Operation IEs(HT_INFO/VHT_OP/HE_OP/
EHT_OP, etc..) from beacon/probe rsp. When link switch is
started by firmware and if host also triggers VDEV_RESTART
due to a change in the beacon at the same time, VDEV_RESTART
timeout happens as vdev lock is held by link switch module
in firmware.
So, host driver can't allow link switch when such VDEV_RESTART
is in progress.

Add an MLD level check when CSA/chan_switch is started and reject
link switch request if it's set.

Change-Id: If5b7fbcbf214684c28d0129546376220a147bce9
CRs-Fixed: 3655049
Srinivas Dasari 1 年間 前
コミット
cc617c7e50

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

@@ -713,6 +713,7 @@ struct wlan_mlo_sta_assoc_pending_list {
  * @emlsr_cap: EMLSR capabilities info
  * @link_force_ctx: set link force mode context
  * @ml_link_control_mode: link control mode configured via user space
+ * @ml_chan_switch_in_progress: Flag to track CSA at MLD level
  */
 struct wlan_mlo_sta {
 	qdf_bitmap(wlan_connect_req_links, WLAN_UMAC_MLO_MAX_VDEVS);
@@ -743,6 +744,7 @@ struct wlan_mlo_sta {
 	struct wlan_link_force_context link_force_ctx;
 #endif
 	uint8_t ml_link_control_mode;
+	bool ml_chan_switch_in_progress;
 };
 
 /**

+ 37 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_sta.h

@@ -1184,6 +1184,31 @@ bool mlo_is_set_key_defered(struct wlan_objmgr_vdev *vdev,
  * Return: boolean value true or false
  */
 bool mlo_is_any_link_disconnecting(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * mlo_set_chan_switch_in_progress: Set/clear the flag upon CSA at MLD level
+ * @vdev: vdev obj
+ * @val: Carries true if CSA is started on any of the ML links. This carries
+ *       false once CSA is completed.
+ *
+ * This API is to set/clear the flag ml_chan_switch_in_progress upon
+ * CSA start/CSA completion on any of the ML links.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+mlo_set_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev, bool val);
+
+/**
+ * mlo_is_chan_switch_in_progress: Check if ML level CSA flag is set
+ * @vdev: vdev obj
+ *
+ * This API is to check the flag ml_chan_switch_in_progress upon
+ * CSA start/CSA completion on any of the ML links.
+ *
+ * Return: True if flag ml_chan_switch_in_progress is set, false otherwise
+ */
+bool mlo_is_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev);
 #else
 static inline
 void mlo_defer_set_keys(struct wlan_objmgr_vdev *vdev,
@@ -1203,5 +1228,17 @@ bool mlo_is_any_link_disconnecting(struct wlan_objmgr_vdev *vdev)
 {
 	return false;
 }
+
+static inline QDF_STATUS
+mlo_set_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev, bool val)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+
+static inline bool
+mlo_is_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev)
+{
+	return false;
+}
 #endif
 #endif

+ 8 - 0
umac/mlo_mgr/src/wlan_mlo_mgr_link_switch.c

@@ -531,6 +531,14 @@ mlo_mgr_link_switch_notification(struct wlan_objmgr_vdev *vdev,
 {
 	QDF_STATUS status;
 
+	if ((notify_reason == MLO_LINK_SWITCH_NOTIFY_REASON_PRE_START_PRE_SER ||
+	     notify_reason ==
+		MLO_LINK_SWITCH_NOTIFY_REASON_PRE_START_POST_SER) &&
+		mlo_is_chan_switch_in_progress(vdev)) {
+		mlo_debug("CSA is in progress on one of ML vdevs, abort link switch");
+		return QDF_STATUS_E_AGAIN;
+	}
+
 	if (notify_reason == MLO_LINK_SWITCH_NOTIFY_REASON_PRE_START_PRE_SER)
 		return QDF_STATUS_SUCCESS;
 

+ 25 - 0
umac/mlo_mgr/src/wlan_mlo_mgr_sta.c

@@ -2875,5 +2875,30 @@ bool mlo_is_any_link_disconnecting(struct wlan_objmgr_vdev *vdev)
 
 	return status;
 }
+
+QDF_STATUS
+mlo_set_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev, bool val)
+{
+	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
+
+	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx)
+		return QDF_STATUS_E_INVAL;
+
+	mlo_dev_ctx->sta_ctx->ml_chan_switch_in_progress = val;
+	mlo_debug("Set ml_chan_switch_in_progress: %d vdev %d",
+		  val, wlan_vdev_get_id(vdev));
+
+	return QDF_STATUS_SUCCESS;
+}
+
+bool mlo_is_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
+
+	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx)
+		return false;
+
+	return mlo_dev_ctx->sta_ctx->ml_chan_switch_in_progress;
+}
 #endif
 #endif