Prechádzať zdrojové kódy

qcacld-3.0: Enhance the 4 VIF concurrency check

Existing check for 4 vif concurrency in policy_mgr_allow_4th_new_freq
is insufficient to handle the case: ML STA on 2412 MHz and
5805 MHz, GO on 5180 MHz, SAP on 5805 MHz. Then user trigger
SAP CSA to 5240 MHz. Driver should reject the CSA because
DBS or SBS both can't meet the requirement that 3 VIFs MCC is not
supported in same mac.
Fix by loop all the hw mode to check vif channel and mode
combination are supported or not. If no one support the combination,
reject the 4th connection.

Change-Id: I67709395f7734d1f636a1410ac112a837cb66e79
CRs-Fixed: 3446747
Liangwei Dong 2 rokov pred
rodič
commit
6bad2014df

+ 35 - 11
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h

@@ -3174,26 +3174,26 @@ policy_mgr_are_3_freq_on_same_mac(struct wlan_objmgr_psoc *psoc,
 
 /**
  * policy_mgr_allow_4th_new_freq() - Function to check whether 4th freq can
- * be allowed wthout leading to 3 home freq on same mac
+ * be allowed with existing 3 vifs
  * @psoc: Pointer to Psoc
- * @freq1: Frequency 1
- * @freq2: Frequency 2
- * @freq3: Frequency 3
- * @new_ch_freq: freq to check with reference to freq1 freq2 and freq3
+ * @ch_freq: new channel frequency
+ * @mode: new device mode
+ * @ext_flags: extended flags for concurrency check
  *
- * Return:True if all 4 freq can be allowed without causing 3 home frequency
- * on same mac
+ * Return:True if 4th freq can be allowed with existing 3 vifs
  */
 #ifdef FEATURE_FOURTH_CONNECTION
 bool
 policy_mgr_allow_4th_new_freq(struct wlan_objmgr_psoc *psoc,
-			      qdf_freq_t freq1, qdf_freq_t freq2,
-			      qdf_freq_t freq3, qdf_freq_t new_ch_freq);
+			      qdf_freq_t ch_freq,
+			      enum policy_mgr_con_mode mode,
+			      uint32_t ext_flags);
 #else
 static inline bool
 policy_mgr_allow_4th_new_freq(struct wlan_objmgr_psoc *psoc,
-			      qdf_freq_t freq1, qdf_freq_t freq2,
-			      qdf_freq_t freq3, qdf_freq_t new_ch_freq)
+			      qdf_freq_t ch_freq,
+			      enum policy_mgr_con_mode mode,
+			      uint32_t ext_flags)
 {
 	return false;
 }
@@ -4560,6 +4560,30 @@ bool policy_mgr_is_mlo_sta_disconnected(struct wlan_objmgr_psoc *psoc,
 					uint8_t vdev_id);
 
 #ifdef WLAN_FEATURE_11BE_MLO
+/*
+ * policy_mgr_get_ml_sta_info_psoc() - Get number of ML STA vdev ids and
+ * freq list
+ * @pm_ctx: pm_ctx ctx
+ * @num_ml_sta: Return number of ML STA present
+ * @num_disabled_ml_sta: Return number of disabled ML STA links
+ * @ml_vdev_lst: Return ML STA vdev id list
+ * @ml_freq_lst: Return ML STA freq list
+ * @num_non_ml: Return number of non-ML STA present
+ * @non_ml_vdev_lst: Return non-ML STA vdev id list
+ * @non_ml_freq_lst: Return non-ML STA freq list
+ *
+ * Return: void
+ */
+void
+policy_mgr_get_ml_sta_info_psoc(struct wlan_objmgr_psoc *psoc,
+				uint8_t *num_ml_sta,
+				uint8_t *num_disabled_ml_sta,
+				uint8_t *ml_vdev_lst,
+				qdf_freq_t *ml_freq_lst,
+				uint8_t *num_non_ml,
+				uint8_t *non_ml_vdev_lst,
+				qdf_freq_t *non_ml_freq_lst);
+
 /**
  * policy_mgr_handle_link_removal_on_vdev() - Handle AP link removal for
  * MLO STA

+ 4 - 5
components/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c

@@ -3839,7 +3839,8 @@ bool policy_mgr_allow_same_mac_same_freq(struct wlan_objmgr_psoc *psoc,
 
 bool policy_mgr_allow_new_home_channel(
 	struct wlan_objmgr_psoc *psoc, enum policy_mgr_con_mode mode,
-	qdf_freq_t ch_freq, uint32_t num_connections, bool is_dfs_ch)
+	qdf_freq_t ch_freq, uint32_t num_connections, bool is_dfs_ch,
+	uint32_t ext_flags)
 {
 	bool status = true;
 	struct policy_mgr_psoc_priv_obj *pm_ctx;
@@ -3858,10 +3859,8 @@ bool policy_mgr_allow_new_home_channel(
 	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
 	if (num_connections == 3) {
 		status = policy_mgr_allow_4th_new_freq(psoc,
-						pm_conc_connection_list[0].freq,
-						pm_conc_connection_list[1].freq,
-						pm_conc_connection_list[2].freq,
-						ch_freq);
+						       ch_freq, mode,
+						       ext_flags);
 	} else if (num_connections == 2) {
 	/* No SCC or MCC combination is allowed with / on DFS channel */
 		on_same_mac = policy_mgr_2_freq_always_on_same_mac(psoc,

+ 247 - 31
components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -2057,51 +2057,235 @@ policy_mgr_are_3_freq_on_same_mac(struct wlan_objmgr_psoc *psoc,
 }
 
 #ifdef FEATURE_FOURTH_CONNECTION
+static void
+policy_mgr_get_mac_freq_list(struct policy_mgr_freq_range *freq_range,
+			     uint8_t mac_id,
+			     uint8_t mac_freq_list[MAX_NUMBER_OF_CONC_CONNECTIONS],
+			     uint8_t mac_mode_list[MAX_NUMBER_OF_CONC_CONNECTIONS],
+			     uint8_t *mac_freq_num,
+			     qdf_freq_t freq_1, enum policy_mgr_con_mode mode_1,
+			     qdf_freq_t freq_2, enum policy_mgr_con_mode mode_2,
+			     qdf_freq_t freq_3, enum policy_mgr_con_mode mode_3,
+			     qdf_freq_t freq_4, enum policy_mgr_con_mode mode_4)
+{
+	uint8_t j = 0;
+
+	if (freq_1 && IS_FREQ_ON_MAC_ID(freq_range, freq_1, mac_id)) {
+		mac_freq_list[j] = freq_1;
+		mac_mode_list[j++] = mode_1;
+	}
+	if (freq_2 && IS_FREQ_ON_MAC_ID(freq_range, freq_2, mac_id)) {
+		mac_freq_list[j] = freq_2;
+		mac_mode_list[j++] = mode_2;
+	}
+	if (freq_3 && IS_FREQ_ON_MAC_ID(freq_range, freq_3, mac_id)) {
+		mac_freq_list[j] = freq_3;
+		mac_mode_list[j++] = mode_3;
+	}
+	if (freq_4 && IS_FREQ_ON_MAC_ID(freq_range, freq_4, mac_id)) {
+		mac_freq_list[j] = freq_4;
+		mac_mode_list[j++] = mode_4;
+	}
+
+	*mac_freq_num = j;
+}
 
-/**
- * policy_mgr_4_freq_always_on_same_mac() - Function to check if 4 freq can
- * lead to 3 home freq on same mac in all modes
- * @psoc: Pointer to Psoc
- * @freq1: Frequency 1
- * @freq2: Frequency 2
- * @freq3: Frequency 3
- * @freq4: Frequency 4
- *
- * Return:true if any 3 freq cause 3 home frequency on same mac in all modes
- *
- */
 static bool
-policy_mgr_4_freq_always_on_same_mac(struct wlan_objmgr_psoc *psoc,
-				     qdf_freq_t freq1, qdf_freq_t freq2,
-				     qdf_freq_t freq3, qdf_freq_t freq4)
-{
-	/* check if any 3 freq are leading to 3 home freq */
-	if (policy_mgr_3_freq_always_on_same_mac(psoc, freq1, freq2, freq3) ||
-	    policy_mgr_3_freq_always_on_same_mac(psoc, freq1, freq2, freq4) ||
-	    policy_mgr_3_freq_always_on_same_mac(psoc, freq1, freq3, freq4) ||
-	    policy_mgr_3_freq_always_on_same_mac(psoc, freq2, freq3, freq4))
+policy_mgr_is_supported_hw_mode(struct wlan_objmgr_psoc *psoc,
+				struct policy_mgr_psoc_priv_obj *pm_ctx,
+				enum policy_mgr_mode hw_mode)
+{
+	if (hw_mode == MODE_SMM)
 		return true;
 
+	if (hw_mode == MODE_DBS)
+		return policy_mgr_is_hw_dbs_capable(psoc);
+
+	if (hw_mode == MODE_SBS_UPPER_SHARE ||
+	    hw_mode == MODE_SBS_LOWER_SHARE)
+		return policy_mgr_is_hw_sbs_capable(psoc) &&
+			pm_ctx->hw_mode.sbs_lower_band_end_freq;
+
+	if (hw_mode == MODE_SBS)
+		return policy_mgr_is_hw_sbs_capable(psoc);
+
 	return false;
 }
 
+static bool
+policy_mgr_mac_freq_list_allow(uint8_t mac_freq_list[MAX_NUMBER_OF_CONC_CONNECTIONS],
+			       uint8_t mac_mode_list[MAX_NUMBER_OF_CONC_CONNECTIONS],
+			       uint8_t mac_freq_num)
+{
+	uint8_t sta = 0, ap = 0, i;
+
+	switch (mac_freq_num) {
+	case 1:
+	case 2:
+		return true;
+	case 3:
+		/* If 3 vifs are active in same mac, target only support:
+		 * 3 vifs are in SCC and 3 vifs are :
+		 * 1 STA + 2 APs, or 3 APs
+		 */
+		if (mac_freq_list[0] != mac_freq_list[1] ||
+		    mac_freq_list[0] != mac_freq_list[2])
+			return false;
+		for (i = 0; i < mac_freq_num; i++) {
+			if (mac_mode_list[i] == PM_STA_MODE ||
+			    mac_mode_list[i] == PM_P2P_CLIENT_MODE)
+				sta++;
+			else
+				ap++;
+		}
+
+		if (sta == 1 && ap == 2)
+			return true;
+		if (ap == 3)
+			return true;
+		return false;
+	default:
+		return false;
+	}
+}
+
+#ifdef WLAN_FEATURE_11BE_MLO
+static void
+policy_mgr_ml_sta_active_freq(struct wlan_objmgr_psoc *psoc,
+			      qdf_freq_t ch_freq,
+			      enum policy_mgr_con_mode mode,
+			      uint32_t ext_flags,
+			      qdf_freq_t *ml_sta_link0_freq,
+			      qdf_freq_t *ml_sta_link1_freq)
+{
+	uint8_t num_ml_sta = 0, num_disabled_ml_sta = 0;
+	uint8_t num_active_ml_sta;
+	uint8_t ml_sta_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
+	qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
+	union conc_ext_flag conc_ext_flags;
+
+	conc_ext_flags.value = ext_flags;
+	/* find the two active ml sta home channels */
+	policy_mgr_get_ml_sta_info_psoc(psoc, &num_ml_sta,
+					&num_disabled_ml_sta,
+					ml_sta_vdev_lst, ml_freq_lst,
+					NULL, NULL, NULL);
+	if (num_ml_sta > MAX_NUMBER_OF_CONC_CONNECTIONS ||
+	    num_disabled_ml_sta > MAX_NUMBER_OF_CONC_CONNECTIONS ||
+	    num_ml_sta <= num_disabled_ml_sta) {
+		policy_mgr_debug("unexpected ml sta num %d %d",
+				 num_ml_sta, num_disabled_ml_sta);
+		return;
+	}
+	num_active_ml_sta = num_ml_sta;
+	if (num_ml_sta >= num_disabled_ml_sta)
+		num_active_ml_sta = num_ml_sta - num_disabled_ml_sta;
+	if (num_active_ml_sta > 1) {
+		*ml_sta_link0_freq = ml_freq_lst[0];
+		*ml_sta_link1_freq = ml_freq_lst[1];
+	} else if (num_active_ml_sta > 0 && conc_ext_flags.mlo &&
+		   mode == PM_STA_MODE) {
+		*ml_sta_link0_freq = ml_freq_lst[0];
+		*ml_sta_link1_freq = ch_freq;
+	}
+}
+#else
+static void
+policy_mgr_ml_sta_active_freq(struct wlan_objmgr_psoc *psoc,
+			      qdf_freq_t ch_freq,
+			      enum policy_mgr_con_mode mode,
+			      uint32_t ext_flags,
+			      qdf_freq_t *ml_sta_link0_freq,
+			      qdf_freq_t *ml_sta_link1_freq)
+{
+}
+#endif
+
 bool
 policy_mgr_allow_4th_new_freq(struct wlan_objmgr_psoc *psoc,
-			      qdf_freq_t freq1, qdf_freq_t freq2,
-			      qdf_freq_t freq3, qdf_freq_t new_ch_freq)
+			      qdf_freq_t ch_freq,
+			      enum policy_mgr_con_mode mode,
+			      uint32_t ext_flags)
 {
+	struct policy_mgr_conc_connection_info *conn = pm_conc_connection_list;
+	uint8_t mac_freq_list[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	uint8_t mac_mode_list[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	uint8_t mac_freq_num;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	qdf_freq_t ml_sta_link0_freq = 0;
+	qdf_freq_t ml_sta_link1_freq = 0;
+	uint8_t i, j;
+	struct policy_mgr_freq_range *freq_range;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return false;
+	}
+
 	/* if HW is not DBS return false */
 	if (!policy_mgr_is_hw_dbs_capable(psoc))
 		return false;
 
-	if (!freq1 || !freq2 || !freq3 || !new_ch_freq) {
-		policy_mgr_info("one or more freq are 0: freq1 %d freq2 %d freq3 %d new_freq %d",
-				freq1, freq2, freq3, new_ch_freq);
-		return false;
+	/* Find the two active ml sta home channels */
+	policy_mgr_ml_sta_active_freq(psoc, ch_freq, mode, ext_flags,
+				      &ml_sta_link0_freq,
+				      &ml_sta_link1_freq);
+
+	/* Check if any hw mode can support the 4th channel frequency
+	 * and device mode.
+	 */
+	for (j = 0; j < MODE_HW_MAX; j++) {
+		if (!policy_mgr_is_supported_hw_mode(psoc, pm_ctx, j))
+			continue;
+		freq_range = pm_ctx->hw_mode.freq_range_caps[j];
+
+		/* If ml sta present, the two links should be in
+		 * different mac always. Skip the hw mode which
+		 * causes they in same mac.
+		 */
+		if (ml_sta_link0_freq && ml_sta_link1_freq &&
+		    policy_mgr_2_freq_same_mac_in_freq_range(pm_ctx,
+							     freq_range,
+							     ml_sta_link0_freq,
+							     ml_sta_link1_freq))
+			continue;
+		for (i = 0; i < MAX_MAC; i++) {
+			/* Get the freq list which are in the MAC
+			 * supported freq range.
+			 */
+			policy_mgr_get_mac_freq_list(
+				freq_range,
+				i,
+				mac_freq_list, mac_mode_list, &mac_freq_num,
+				conn[0].freq, conn[0].mode,
+				conn[1].freq, conn[1].mode,
+				conn[2].freq, conn[2].mode,
+				ch_freq, mode);
+
+			/* Check the freq & mode list support or not in the
+			 * MAC.
+			 */
+			if (!policy_mgr_mac_freq_list_allow(
+				mac_freq_list, mac_mode_list, mac_freq_num))
+				break;
+		}
+
+		/* If the frequency/mode combination meet requirement in the
+		 * hw mode, then the 4th new ch_freq/mode are allowed to start
+		 * in this hw mode.
+		 */
+		if (i == MAX_MAC) {
+			policy_mgr_debug("new freq %d mode %s is allowed in hw mode %s",
+					 ch_freq, device_mode_to_string(mode),
+					 policy_mgr_hw_mode_to_str(j));
+			return true;
+		}
 	}
+	policy_mgr_debug("the 4th new freq %d mode %s is not allowed in any hw mode",
+			 ch_freq, device_mode_to_string(mode));
 
-	return !policy_mgr_4_freq_always_on_same_mac(psoc, freq1, freq2, freq3,
-						     new_ch_freq);
+	return false;
 }
 #endif
 
@@ -3605,6 +3789,34 @@ policy_mgr_get_ml_sta_info(struct policy_mgr_psoc_priv_obj *pm_ctx,
 	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
 }
 
+void
+policy_mgr_get_ml_sta_info_psoc(struct wlan_objmgr_psoc *psoc,
+				uint8_t *num_ml_sta,
+				uint8_t *num_disabled_ml_sta,
+				uint8_t *ml_vdev_lst,
+				qdf_freq_t *ml_freq_lst,
+				uint8_t *num_non_ml,
+				uint8_t *non_ml_vdev_lst,
+				qdf_freq_t *non_ml_freq_lst)
+{
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid pm_ctx");
+		return;
+	}
+
+	return policy_mgr_get_ml_sta_info(pm_ctx,
+					  num_ml_sta,
+					  num_disabled_ml_sta,
+					  ml_vdev_lst,
+					  ml_freq_lst,
+					  num_non_ml,
+					  non_ml_vdev_lst,
+					  non_ml_freq_lst);
+}
+
 uint32_t policy_mgr_get_disabled_ml_links_count(struct wlan_objmgr_psoc *psoc)
 {
 	uint32_t i, count = 0;
@@ -7236,7 +7448,8 @@ bool policy_mgr_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc,
 		 */
 		if (!policy_mgr_allow_new_home_channel(psoc, mode, ch_freq,
 						       num_connections,
-						       is_dfs_ch))
+						       is_dfs_ch,
+						       ext_flags))
 			return status;
 
 		/*
@@ -9825,6 +10038,7 @@ bool policy_mgr_is_ap_ap_mcc_allow(struct wlan_objmgr_psoc *psoc,
 	uint32_t num_connections;
 	bool is_dfs_ch = false;
 	struct ch_params ch_params;
+	union conc_ext_flag conc_ext_flags;
 
 	if (!psoc || !vdev || !pdev) {
 		policy_mgr_debug("psoc or vdev or pdev is NULL");
@@ -9846,11 +10060,13 @@ bool policy_mgr_is_ap_ap_mcc_allow(struct wlan_objmgr_psoc *psoc,
 	 * 2 beaconing entities with STA in SCC.
 	 * 3 beaconing entities in SCC.
 	 */
+	conc_ext_flags.value = policy_mgr_get_conc_ext_flags(vdev, false);
 	num_connections = policy_mgr_get_connection_count(psoc);
 	if (num_connections > 1 &&
 	    (mode == QDF_P2P_GO_MODE || mode == QDF_SAP_MODE) &&
 	    !policy_mgr_allow_new_home_channel(psoc, con_mode, ch_freq,
-					       num_connections, is_dfs_ch))
+					       num_connections, is_dfs_ch,
+					       conc_ext_flags.value))
 		return false;
 
 	policy_mgr_get_mcc_scc_switch(psoc, &mcc_to_scc_switch);

+ 3 - 3
components/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h

@@ -449,7 +449,6 @@ struct policy_mgr_mac_ss_bw_info {
 	bool support_6ghz_band;
 };
 
-#ifdef WLAN_FEATURE_11BE_MLO
 /**
  * union conc_ext_flag - extended flags for concurrency check
  *
@@ -466,7 +465,6 @@ union conc_ext_flag {
 
 	uint32_t value;
 };
-#endif
 
 #ifdef WLAN_FEATURE_SR
 /**
@@ -849,6 +847,7 @@ QDF_STATUS policy_mgr_get_channel_list(struct wlan_objmgr_psoc *psoc,
  * @ch_freq: channel frequency on which new connection is coming up
  * @num_connections: number of current connections
  * @is_dfs_ch: DFS channel or not
+ * @ext_flags: extended flags for concurrency check
  *
  * When a new connection is about to come up check if current
  * concurrency combination including the new connection is
@@ -858,7 +857,8 @@ QDF_STATUS policy_mgr_get_channel_list(struct wlan_objmgr_psoc *psoc,
  */
 bool policy_mgr_allow_new_home_channel(
 	struct wlan_objmgr_psoc *psoc, enum policy_mgr_con_mode mode,
-	uint32_t ch_freq, uint32_t num_connections, bool is_dfs_ch);
+	uint32_t ch_freq, uint32_t num_connections, bool is_dfs_ch,
+	uint32_t ext_flags);
 
 /**
  * policy_mgr_is_5g_channel_allowed() - check if 5g channel is allowed