Browse Source

qcacld-3.0: STA+SAP 6Ghz concurrency

When SAP is on 5G and STA connects to 6Ghz AP, the "force
SCC" logic will move SAP to STA home channel if SAP is 6Ghz capable.
If SAP is not 6Ghz capable, SAP will be moved to 2G (DBS) to
avoid MCC(5G+6G) for DBS HW and SAP will stay on 5G for non-DBS HW.
SAP is 6Ghz capable only when all of below statements are true:
a. SAP config includes WPA3 security - SAE,OWE,SuiteB.
b. SAP is configured by ACS range which includes any 6G channel or
   configured by 6G Fixed channel.
c. SAP has no legacy clients (client doesn't support 6G band).
   legacy client (non 6ghz capable): association request frame has no
   6G band global operating Class.

Change-Id: I7e9723fd1b679326a3df61932850589e6e503f3d
CRs-Fixed: 2593569
Liangwei Dong 5 years ago
parent
commit
0527617342

+ 75 - 1
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h

@@ -1338,6 +1338,7 @@ struct policy_mgr_sme_cbacks {
  * @hdd_is_chan_switch_in_progress: Check if in any adater channel switch is in
  * progress
  * @wlan_hdd_set_sap_csa_reason: Set the sap csa reason in cases like NAN.
+ * @hdd_get_ap_6ghz_capable: get ap vdev 6ghz capable info from hdd ap adapter.
  */
 struct policy_mgr_hdd_cbacks {
 	void (*sap_restart_chan_switch_cb)(struct wlan_objmgr_psoc *psoc,
@@ -1356,6 +1357,8 @@ struct policy_mgr_hdd_cbacks {
 	bool (*hdd_is_cac_in_progress)(void);
 	void (*wlan_hdd_set_sap_csa_reason)(struct wlan_objmgr_psoc *psoc,
 					    uint8_t vdev_id, uint8_t reason);
+	uint32_t (*hdd_get_ap_6ghz_capable)(struct wlan_objmgr_psoc *psoc,
+					    uint8_t vdev_id);
 };
 
 
@@ -3162,18 +3165,89 @@ QDF_STATUS policy_mgr_get_hw_mode_from_idx(
  * @psoc: Pointer to soc
  * @mode: new connection mode
  *
- * Current PORed 6ghz connection is STA, SAP.
+ * Current PORed 6ghz connection modes are STA, SAP.
  *
  * Return: true if supports else false.
  */
 bool policy_mgr_is_6ghz_conc_mode_supported(
 	struct wlan_objmgr_psoc *psoc, enum policy_mgr_con_mode mode);
+
+/**
+ * policy_mgr_init_ap_6ghz_capable - Init 6Ghz capable flags
+ * @psoc: PSOC object information
+ * @vdev_id: vdev id
+ * @ap_6ghz_capable: vdev 6ghz capable flag
+ *
+ * Init 6Ghz capable flags for active connection in policy mgr conn table
+ *
+ * Return: void
+ */
+void policy_mgr_init_ap_6ghz_capable(struct wlan_objmgr_psoc *psoc,
+				     uint8_t vdev_id,
+				     enum conn_6ghz_flag ap_6ghz_capable);
+
+/**
+ * policy_mgr_set_ap_6ghz_capable - Set 6Ghz capable flags to connection list
+ * @psoc: PSOC object information
+ * @vdev_id: vdev id
+ * @set: set or clear
+ * @ap_6ghz_capable: vdev 6ghz capable flag
+ *
+ * Set/Clear 6Ghz capable flags for active connection in policy mgr conn table
+ *
+ * Return: void
+ */
+void policy_mgr_set_ap_6ghz_capable(struct wlan_objmgr_psoc *psoc,
+				    uint8_t vdev_id,
+				    bool set,
+				    enum conn_6ghz_flag ap_6ghz_capable);
+
+/**
+ * policy_mgr_get_ap_6ghz_capable - Get 6Ghz capable info for a vdev
+ * @psoc: PSOC object information
+ * @vdev_id: vdev id
+ * @conn_flag: output conntion flags
+ *
+ * Get 6Ghz capable flag for ap vdev (SAP). When SAP on 5G, for same reason
+ * the AP needs to be moved to 6G and this API will be called to check whether
+ * AP is 6Ghz capable or not.
+ * AP is allowed on 6G band only when all of below statements are true:
+ * a. SAP config includes WPA3 security - SAE,OWE,SuiteB.
+ * b. SAP is configured by ACS range which includes any 6G channel or
+      configured by 6G Fixed channel.
+ * c. SAP has no legacy clients (client doesn't support 6G band).
+ *    legacy client (non 6ghz capable): association request frame has no
+ *    6G band global operating Class.
+ *
+ * Return: true if AP is 6ghz capable
+ */
+bool policy_mgr_get_ap_6ghz_capable(
+	struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint32_t *conn_flag);
 #else
 static inline bool policy_mgr_is_6ghz_conc_mode_supported(
 	struct wlan_objmgr_psoc *psoc, enum policy_mgr_con_mode mode)
 {
 	return false;
 }
+
+static inline void policy_mgr_init_ap_6ghz_capable(
+	struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
+	enum conn_6ghz_flag ap_6ghz_capable)
+{}
+
+static inline
+void policy_mgr_set_ap_6ghz_capable(struct wlan_objmgr_psoc *psoc,
+				    uint8_t vdev_id,
+				    bool set,
+				    enum conn_6ghz_flag ap_6ghz_capable)
+{}
+
+static inline bool policy_mgr_get_ap_6ghz_capable(
+	struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint32_t *conn_flag)
+{
+	return false;
+}
+
 #endif
 
 /**

+ 29 - 0
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h

@@ -1013,6 +1013,31 @@ enum dbs_support {
 	ENABLE_DBS_CXN_AND_DISABLE_SIMULTANEOUS_SCAN,
 };
 
+/**
+ * enum conn_6ghz_flag - structure to define connection 6ghz capable info
+ * in policy mgr conn info struct
+ *
+ * @CONN_6GHZ_FLAG_VALID: The 6ghz flag is valid (has been initialized)
+ * @CONN_6GHZ_FLAG_ACS_OR_USR_ALLOWED: AP is configured in 6ghz band capable
+ *   by user:
+ *   a. ACS channel range includes 6ghz.
+ *   b. SAP is started in 6ghz fix channel.
+ * @CONN_6GHZ_FLAG_SECURITY_ALLOWED: AP has security mode which is permitted in
+ *   6ghz band.
+ * @CONN_6GHZ_FLAG_NO_LEGACY_CLIENT: AP has no legacy client connected
+ */
+enum conn_6ghz_flag {
+	CONN_6GHZ_FLAG_VALID = 0x0001,
+	CONN_6GHZ_FLAG_ACS_OR_USR_ALLOWED = 0x0002,
+	CONN_6GHZ_FLAG_SECURITY_ALLOWED = 0x0004,
+	CONN_6GHZ_FLAG_NO_LEGACY_CLIENT = 0x0008,
+};
+
+#define CONN_6GHZ_CAPABLIE (CONN_6GHZ_FLAG_VALID | \
+			     CONN_6GHZ_FLAG_ACS_OR_USR_ALLOWED | \
+			     CONN_6GHZ_FLAG_SECURITY_ALLOWED | \
+			     CONN_6GHZ_FLAG_NO_LEGACY_CLIENT)
+
 /**
  * struct policy_mgr_conc_connection_info - information of all existing
  * connections in the wlan system
@@ -1026,6 +1051,7 @@ enum dbs_support {
  * @vdev_id: vdev id of the connection
  * @in_use: if the table entry is active
  * @ch_flagext: Channel extension flags.
+ * @conn_6ghz_flag: connection 6ghz capable flags
  */
 struct policy_mgr_conc_connection_info {
 	enum policy_mgr_con_mode mode;
@@ -1037,6 +1063,7 @@ struct policy_mgr_conc_connection_info {
 	uint32_t      vdev_id;
 	bool          in_use;
 	uint16_t      ch_flagext;
+	enum conn_6ghz_flag conn_6ghz_flag;
 };
 
 /**
@@ -1233,10 +1260,12 @@ struct dbs_nss {
  * @mac_id: The HW mac it is running
  * @vdev_id: vdev id
  * @channel: channel of the connection
+ * @ch_freq: channel freq in Mhz
  */
 struct connection_info {
 	uint8_t mac_id;
 	uint8_t vdev_id;
 	uint8_t channel;
+	uint32_t ch_freq;
 };
 #endif /* __WLAN_POLICY_MGR_PUBLIC_STRUCT_H */

+ 84 - 2
components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c

@@ -1852,6 +1852,84 @@ static bool policy_mgr_valid_sta_channel_check(struct wlan_objmgr_psoc *psoc,
 		return true;
 }
 
+/**
+ * policy_mgr_select_2g_chan() - select 2G usable channel for SAP
+ * @psoc: psoc object
+ *
+ * Select active 2G home channel or select safe 2G channel.
+ *
+ * return: uint32 chan freq
+ */
+static uint32_t policy_mgr_select_2g_chan(struct wlan_objmgr_psoc *psoc)
+{
+	uint8_t count, i;
+	struct connection_info info[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	struct regulatory_channel band_2g_list[NUM_24GHZ_CHANNELS];
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid context");
+		return 0;
+	}
+
+	count = policy_mgr_get_connection_info(psoc, info);
+	for (i = 0; i  < count; i++) {
+		if (WLAN_REG_IS_24GHZ_CH_FREQ(info[i].ch_freq))
+			return info[i].ch_freq;
+	}
+
+	count = wlan_reg_get_band_channel_list(pm_ctx->pdev, BIT(REG_BAND_2G),
+					       band_2g_list);
+	for (i = 0; i  < count; i++) {
+		if (policy_mgr_is_safe_channel(psoc,
+					       band_2g_list[i].center_freq))
+			return band_2g_list[i].center_freq;
+	}
+
+	return PM_24_GHZ_CH_FREQ_6;
+}
+
+/**
+ * policy_mgr_check_6ghz_sap_conc() - check sap force scc to 6ghz
+ * @psoc: psoc object
+ * @con_ch_freq: concurrency channel
+ * @sap_ch_freq: SAP starting channel
+ * @sap_vdev_id: sap vdev id
+ *
+ * Validate whether SAP can be forced scc to 6ghz band or not.
+ * If not, select 2G band channel for DBS hw
+ * or keep SAP starting channel not changed for non-DBS hw.
+ *
+ * return: QDF_STATUS_SUCCESS
+ */
+static QDF_STATUS policy_mgr_check_6ghz_sap_conc(
+	struct wlan_objmgr_psoc *psoc, uint32_t *con_ch_freq,
+	uint32_t sap_ch_freq, uint8_t sap_vdev_id)
+{
+	uint32_t ch_freq = *con_ch_freq;
+
+	if (ch_freq && WLAN_REG_IS_6GHZ_CHAN_FREQ(ch_freq) &&
+	    !WLAN_REG_IS_6GHZ_CHAN_FREQ(sap_ch_freq) &&
+	    !policy_mgr_get_ap_6ghz_capable(psoc, sap_vdev_id, NULL)) {
+		policy_mgr_debug("sap %d not support 6ghz freq %d",
+				 sap_vdev_id, ch_freq);
+		if (policy_mgr_is_hw_dbs_capable(psoc)) {
+			ch_freq = policy_mgr_select_2g_chan(psoc);
+			policy_mgr_debug("select 2G ch %d to achieve DBS",
+					 ch_freq);
+		} else {
+			/* Keep MCC 2G(or 5G) + 6G for non-DBS chip*/
+			ch_freq = 0;
+			policy_mgr_debug("do not force SCC for non-dbs hw");
+		}
+	}
+	if (ch_freq != sap_ch_freq)
+		*con_ch_freq = ch_freq;
+
+	return QDF_STATUS_SUCCESS;
+}
+
 QDF_STATUS policy_mgr_valid_sap_conc_channel_check(
 	struct wlan_objmgr_psoc *psoc, uint32_t *con_ch_freq,
 	uint32_t sap_ch_freq, uint8_t sap_vdev_id)
@@ -1883,10 +1961,14 @@ QDF_STATUS policy_mgr_valid_sap_conc_channel_check(
 	 */
 	if (!ch_freq &&
 	    sap_ch_freq != policy_mgr_mode_specific_get_channel(psoc,
-	    PM_STA_MODE))
+	    PM_STA_MODE)) {
 		return QDF_STATUS_SUCCESS;
-	else if (!ch_freq)
+	} else if (!ch_freq) {
 		ch_freq = sap_ch_freq;
+	} else if (ch_freq && WLAN_REG_IS_6GHZ_CHAN_FREQ(ch_freq)) {
+		return policy_mgr_check_6ghz_sap_conc(
+			psoc, con_ch_freq, sap_ch_freq, sap_vdev_id);
+	}
 
 	sta_sap_scc_on_dfs_chan =
 		policy_mgr_is_sta_sap_scc_allowed_on_dfs_chan(psoc);

+ 189 - 1
components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -1634,6 +1634,7 @@ void policy_mgr_incr_active_session(struct wlan_objmgr_psoc *psoc,
 				uint8_t session_id)
 {
 	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	uint32_t conn_6ghz_flag = 0;
 
 	pm_ctx = policy_mgr_get_context(psoc);
 	if (!pm_ctx) {
@@ -1661,6 +1662,9 @@ void policy_mgr_incr_active_session(struct wlan_objmgr_psoc *psoc,
 
 	if (mode != QDF_NAN_DISC_MODE && pm_ctx->dp_cbacks.hdd_v2_flow_pool_map)
 		pm_ctx->dp_cbacks.hdd_v2_flow_pool_map(session_id);
+	if (mode == QDF_SAP_MODE)
+		policy_mgr_get_ap_6ghz_capable(psoc, session_id,
+					       &conn_6ghz_flag);
 
 	policy_mgr_debug("No.# of active sessions for mode %d = %d",
 		mode, pm_ctx->no_of_active_sessions[mode]);
@@ -1696,6 +1700,9 @@ void policy_mgr_incr_active_session(struct wlan_objmgr_psoc *psoc,
 		if (pm_ctx->dp_cbacks.hdd_set_rx_mode_rps_cb)
 			pm_ctx->dp_cbacks.hdd_set_rx_mode_rps_cb(true);
 	}
+	if (mode == QDF_SAP_MODE)
+		policy_mgr_init_ap_6ghz_capable(psoc, session_id,
+						conn_6ghz_flag);
 
 	policy_mgr_dump_current_concurrency(psoc);
 
@@ -2198,6 +2205,62 @@ bool policy_mgr_is_6ghz_conc_mode_supported(
 }
 #endif
 
+/**
+ * policy_mgr_is_6g_channel_allowed() - Check new 6Ghz connection
+ * allowed or not
+ * @psoc: Pointer to soc
+ * @mode: new connection mode
+ * @ch_freq: channel freq
+ *
+ * 1. Only STA/SAP are allowed on 6Ghz.
+ * 2. If there is DFS beacon entity existing on 5G band, 5G+6G MCC is not
+ * allowed.
+ *
+ *  Return: true if supports else false.
+ */
+static bool policy_mgr_is_6g_channel_allowed(
+	struct wlan_objmgr_psoc *psoc, enum policy_mgr_con_mode mode,
+	uint32_t ch_freq)
+{
+	uint32_t conn_index = 0;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	struct policy_mgr_conc_connection_info *conn;
+	bool is_dfs;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return false;
+	}
+	if (!WLAN_REG_IS_6GHZ_CHAN_FREQ(ch_freq))
+		return true;
+
+	/* Only STA/SAP is supported on 6Ghz currently */
+	if (!policy_mgr_is_6ghz_conc_mode_supported(psoc, mode))
+		return false;
+
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
+	for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS;
+				conn_index++) {
+		conn = &pm_conc_connection_list[conn_index];
+		if (!conn->in_use)
+			continue;
+		is_dfs = (conn->ch_flagext &
+			(IEEE80211_CHAN_DFS | IEEE80211_CHAN_DFS_CFREQ2)) &&
+			WLAN_REG_IS_5GHZ_CH_FREQ(conn->freq);
+		if ((conn->mode == PM_SAP_MODE ||
+		     conn->mode == PM_P2P_GO_MODE) &&
+		    is_dfs && ch_freq != conn->freq) {
+			policy_mgr_err("don't allow MCC if SAP/GO on DFS channel");
+			qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+			return false;
+		}
+	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+
+	return true;
+}
+
 bool policy_mgr_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc,
 				       enum policy_mgr_con_mode mode,
 				       uint32_t ch_freq,
@@ -2263,6 +2326,9 @@ bool policy_mgr_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc,
 		if (!policy_mgr_is_5g_channel_allowed(psoc,
 			ch_freq, list, PM_SAP_MODE))
 			goto done;
+		if (!policy_mgr_is_6g_channel_allowed(psoc, mode,
+						      ch_freq))
+			goto done;
 
 		sta_sap_scc_on_dfs_chan =
 			policy_mgr_is_sta_sap_scc_allowed_on_dfs_chan(psoc);
@@ -3811,7 +3877,7 @@ uint32_t policy_mgr_get_connection_info(struct wlan_objmgr_psoc *psoc,
 		policy_mgr_err("Invalid Context");
 		return count;
 	}
-
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
 	for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS;
 	     conn_index++) {
 		if (PM_CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) {
@@ -3822,9 +3888,12 @@ uint32_t policy_mgr_get_connection_info(struct wlan_objmgr_psoc *psoc,
 			info[count].channel = wlan_reg_freq_to_chan(
 				pm_ctx->pdev,
 				pm_conc_connection_list[conn_index].freq);
+			info[count].ch_freq =
+				pm_conc_connection_list[conn_index].freq;
 			count++;
 		}
 	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
 
 	return count;
 }
@@ -3931,6 +4000,125 @@ bool policy_mgr_sta_sap_scc_on_lte_coex_chan(
 	return scc_lte_coex;
 }
 
+#if defined(CONFIG_BAND_6GHZ) && defined(WLAN_FEATURE_11AX)
+void policy_mgr_init_ap_6ghz_capable(struct wlan_objmgr_psoc *psoc,
+				     uint8_t vdev_id,
+				     enum conn_6ghz_flag ap_6ghz_capable)
+{
+	struct policy_mgr_conc_connection_info *conn_info;
+	uint32_t conn_index;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	enum conn_6ghz_flag conn_6ghz_flag = 0;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return;
+	}
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
+	for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS;
+			conn_index++) {
+		conn_info = &pm_conc_connection_list[conn_index];
+		if (conn_info->in_use && PM_SAP_MODE == conn_info->mode &&
+		    vdev_id == conn_info->vdev_id) {
+			conn_info->conn_6ghz_flag = ap_6ghz_capable;
+			conn_info->conn_6ghz_flag |= CONN_6GHZ_FLAG_VALID;
+			conn_6ghz_flag = conn_info->conn_6ghz_flag;
+			break;
+		}
+	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+	policy_mgr_debug("vdev %d init conn_6ghz_flag %x new %x",
+			 vdev_id, ap_6ghz_capable, conn_6ghz_flag);
+}
+
+void policy_mgr_set_ap_6ghz_capable(struct wlan_objmgr_psoc *psoc,
+				    uint8_t vdev_id,
+				    bool set,
+				    enum conn_6ghz_flag ap_6ghz_capable)
+{
+	struct policy_mgr_conc_connection_info *conn_info;
+	uint32_t conn_index;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	enum conn_6ghz_flag conn_6ghz_flag = 0;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return;
+	}
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
+	for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS;
+			conn_index++) {
+		conn_info = &pm_conc_connection_list[conn_index];
+		if (conn_info->in_use && PM_SAP_MODE == conn_info->mode &&
+		    vdev_id == conn_info->vdev_id) {
+			if (set)
+				conn_info->conn_6ghz_flag |= ap_6ghz_capable;
+			else
+				conn_info->conn_6ghz_flag &= ~ap_6ghz_capable;
+			conn_info->conn_6ghz_flag |= CONN_6GHZ_FLAG_VALID;
+			conn_6ghz_flag = conn_info->conn_6ghz_flag;
+			break;
+		}
+	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+	policy_mgr_debug("vdev %d %s conn_6ghz_flag %x new %x",
+			 vdev_id, set ? "set" : "clr",
+			 ap_6ghz_capable, conn_6ghz_flag);
+}
+
+bool policy_mgr_get_ap_6ghz_capable(struct wlan_objmgr_psoc *psoc,
+				    uint8_t vdev_id,
+				    uint32_t *conn_flag)
+{
+	struct policy_mgr_conc_connection_info *conn_info;
+	uint32_t conn_index;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	enum conn_6ghz_flag conn_6ghz_flag = 0;
+	bool is_6g_allowed = false;
+
+	if (conn_flag)
+		*conn_flag = 0;
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return false;
+	}
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
+	for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS;
+			conn_index++) {
+		conn_info = &pm_conc_connection_list[conn_index];
+		if (conn_info->in_use && PM_SAP_MODE == conn_info->mode &&
+		    vdev_id == conn_info->vdev_id) {
+			conn_6ghz_flag = conn_info->conn_6ghz_flag;
+			break;
+		}
+	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+
+	/* If the vdev connection is not active, policy mgr will query legacy
+	 * hdd to get sap acs and security information.
+	 * The assumption is no legacy client connected for non active
+	 * connection.
+	 */
+	if (!(conn_6ghz_flag & CONN_6GHZ_FLAG_VALID) &&
+	    pm_ctx->hdd_cbacks.hdd_get_ap_6ghz_capable)
+		conn_6ghz_flag = pm_ctx->hdd_cbacks.hdd_get_ap_6ghz_capable(
+					psoc, vdev_id) |
+					CONN_6GHZ_FLAG_NO_LEGACY_CLIENT;
+
+	if ((conn_6ghz_flag & CONN_6GHZ_CAPABLIE) == CONN_6GHZ_CAPABLIE)
+		is_6g_allowed = true;
+	policy_mgr_debug("vdev %d conn_6ghz_flag %x 6ghz %s", vdev_id,
+			 conn_6ghz_flag, is_6g_allowed ? "allowed" : "deny");
+	if (conn_flag)
+		*conn_flag = conn_6ghz_flag;
+
+	return is_6g_allowed;
+}
+#endif
+
 bool policy_mgr_is_valid_for_channel_switch(struct wlan_objmgr_psoc *psoc,
 					    uint32_t ch_freq)
 {

+ 3 - 0
components/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c

@@ -635,6 +635,8 @@ QDF_STATUS policy_mgr_register_hdd_cb(struct wlan_objmgr_psoc *psoc,
 		hdd_cbacks->hdd_is_chan_switch_in_progress;
 	pm_ctx->hdd_cbacks.hdd_is_cac_in_progress =
 		hdd_cbacks->hdd_is_cac_in_progress;
+	pm_ctx->hdd_cbacks.hdd_get_ap_6ghz_capable =
+		hdd_cbacks->hdd_get_ap_6ghz_capable;
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -655,6 +657,7 @@ QDF_STATUS policy_mgr_deregister_hdd_cb(struct wlan_objmgr_psoc *psoc)
 	pm_ctx->hdd_cbacks.hdd_get_device_mode = NULL;
 	pm_ctx->hdd_cbacks.hdd_is_chan_switch_in_progress = NULL;
 	pm_ctx->hdd_cbacks.hdd_is_cac_in_progress = NULL;
+	pm_ctx->hdd_cbacks.hdd_get_ap_6ghz_capable = NULL;
 
 	return QDF_STATUS_SUCCESS;
 }

+ 84 - 0
core/hdd/src/wlan_hdd_hostapd.c

@@ -3198,6 +3198,90 @@ sap_restart:
 
 	return QDF_STATUS_SUCCESS;
 }
+
+#if defined(CONFIG_BAND_6GHZ) && defined(WLAN_FEATURE_11AX)
+uint32_t hdd_get_ap_6ghz_capable(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
+{
+	struct wlan_objmgr_vdev *vdev;
+	uint32_t keymgmt;
+	struct hdd_adapter *ap_adapter;
+	struct hdd_ap_ctx *ap_ctx;
+	struct sap_context *sap_context;
+	struct sap_config *sap_config;
+	uint32_t capable = 0;
+
+	if (!psoc) {
+		hdd_err("PSOC is NULL");
+		return 0;
+	}
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_HDD_ID_OBJ_MGR);
+	if (!vdev) {
+		hdd_err("vdev is NULL %d", vdev_id);
+		return 0;
+	}
+
+	ap_adapter = wlan_hdd_get_adapter_from_vdev(
+					psoc, vdev_id);
+	if (!ap_adapter) {
+		hdd_err("ap_adapter is NULL %d", vdev_id);
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_HDD_ID_OBJ_MGR);
+		return 0;
+	}
+	if (ap_adapter->device_mode != QDF_SAP_MODE) {
+		hdd_err("unexpected device mode %d", ap_adapter->device_mode);
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_HDD_ID_OBJ_MGR);
+		return 0;
+	}
+	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
+	sap_config = &ap_ctx->sap_config;
+	sap_context = ap_ctx->sap_context;
+	if (QDF_IS_STATUS_ERROR(wlansap_context_get(sap_context))) {
+		hdd_err("sap_context is get failed %d", vdev_id);
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_HDD_ID_OBJ_MGR);
+		return 0;
+	}
+	/* SAP is allowed on 6GHz with explicit indication from user space:
+	 * a. SAP is started on 6Ghz already.
+	 * b. SAP is configured on 6Ghz fixed channel from userspace.
+	 * c. SAP is configured by ACS range which includes any 6Ghz channel.
+	 */
+	if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
+		if (WLAN_REG_IS_6GHZ_CHAN_FREQ(
+				ap_ctx->operating_chan_freq))
+			capable |= CONN_6GHZ_FLAG_ACS_OR_USR_ALLOWED;
+	} else {
+		if (WLAN_REG_IS_6GHZ_CHAN_FREQ(sap_config->chan_freq))
+			capable |= CONN_6GHZ_FLAG_ACS_OR_USR_ALLOWED;
+		else if (sap_context && WLAN_REG_IS_6GHZ_CHAN_FREQ(
+				sap_context->chan_freq))
+			capable |= CONN_6GHZ_FLAG_ACS_OR_USR_ALLOWED;
+	}
+	if (wlansap_is_6ghz_included_in_acs_range(sap_context))
+		capable |= CONN_6GHZ_FLAG_ACS_OR_USR_ALLOWED;
+
+	keymgmt = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
+	if (!keymgmt || (keymgmt & (1 << WLAN_CRYPTO_KEY_MGMT_NONE |
+		       1 << WLAN_CRYPTO_KEY_MGMT_SAE |
+		       1 << WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B |
+		       1 << WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192 |
+		       1 << WLAN_CRYPTO_KEY_MGMT_OWE))) {
+		capable |= CONN_6GHZ_FLAG_SECURITY_ALLOWED;
+	}
+	capable |= CONN_6GHZ_FLAG_VALID;
+	hdd_debug("vdev_id %d keymgmt 0x%08x capable 0x%x",
+		  vdev_id, keymgmt, capable);
+	wlansap_context_put(sap_context);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_HDD_ID_OBJ_MGR);
+
+	return capable;
+}
+#else
+uint32_t hdd_get_ap_6ghz_capable(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
+{
+	return 0;
+}
+#endif
 #endif
 
 #ifdef WLAN_FEATURE_TSF_PTP

+ 13 - 0
core/hdd/src/wlan_hdd_hostapd.h

@@ -109,6 +109,19 @@ void hdd_sap_restart_chan_switch_cb(struct wlan_objmgr_psoc *psoc,
 QDF_STATUS wlan_hdd_get_channel_for_sap_restart(
 				struct wlan_objmgr_psoc *psoc,
 				uint8_t vdev_id, uint32_t *ch_freq);
+
+/**
+ * hdd_get_ap_6ghz_capable() - Get ap vdev 6ghz capable flags
+ * @psoc: PSOC object information
+ * @vdev_id: vdev id
+ *
+ * This function gets 6ghz capable information based on hdd ap adapter
+ * context.
+ *
+ * Return: uint32_t, vdev 6g capable flags from enum conn_6ghz_flag
+ */
+uint32_t hdd_get_ap_6ghz_capable(struct wlan_objmgr_psoc *psoc,
+				 uint8_t vdev_id);
 #endif
 
 /**

+ 1 - 0
core/hdd/src/wlan_hdd_main.c

@@ -2992,6 +2992,7 @@ static void hdd_register_policy_manager_callback(
 				hdd_is_cac_in_progress;
 	hdd_cbacks.wlan_hdd_set_sap_csa_reason =
 				wlan_hdd_set_sap_csa_reason;
+	hdd_cbacks.hdd_get_ap_6ghz_capable = hdd_get_ap_6ghz_capable;
 
 	if (QDF_STATUS_SUCCESS !=
 	    policy_mgr_register_hdd_cb(psoc, &hdd_cbacks)) {

+ 1 - 0
core/mac/src/pe/lim/lim_assoc_utils.c

@@ -3196,6 +3196,7 @@ lim_delete_dph_hash_entry(struct mac_context *mac_ctx, tSirMacAddr sta_addr,
 	if (dph_delete_hash_entry(mac_ctx, sta_addr, sta_id,
 		 &session_entry->dph.dphHashTable) != QDF_STATUS_SUCCESS)
 		pe_err("error deleting hash entry");
+	lim_ap_check_6g_compatible_peer(mac_ctx, session_entry);
 }
 
 /**

+ 1 - 0
core/mac/src/pe/lim/lim_process_assoc_req_frame.c

@@ -1807,6 +1807,7 @@ static bool lim_update_sta_ds(struct mac_context *mac_ctx, tpSirMacMgmtHdr hdr,
 		sta_ds->timingMeasCap = 0;
 		pe_debug("ExtCap not present");
 	}
+	lim_ap_check_6g_compatible_peer(mac_ctx, session);
 	return true;
 }
 

+ 58 - 0
core/mac/src/pe/lim/lim_utils.c

@@ -6585,6 +6585,64 @@ void lim_update_last_processed_frame(last_processed_msg *last_processed_frm,
 	last_processed_frm->seq_num = seq_num;
 }
 
+#if defined(CONFIG_BAND_6GHZ) && defined(WLAN_FEATURE_11AX)
+static bool lim_support_6ghz_band_op_class(struct mac_context *mac_ctx,
+					   tDot11fIESuppOperatingClasses *
+					   op_class_ie)
+{
+	uint16_t i;
+
+	if (!op_class_ie->present)
+		return false;
+	for (i = 0; i < op_class_ie->num_classes; i++) {
+		if (wlan_reg_is_6ghz_op_class(mac_ctx->pdev,
+					      op_class_ie->classes[i]))
+			break;
+	}
+	if (i < op_class_ie->num_classes)
+		return true;
+
+	return false;
+}
+
+void lim_ap_check_6g_compatible_peer(struct mac_context *mac_ctx,
+				     struct pe_session *session)
+{
+	uint16_t i;
+	tpDphHashNode sta_ds;
+	bool legacy_client_present = false;
+
+	if (!LIM_IS_AP_ROLE(session))
+		return;
+
+	for (i = 1; i < session->dph.dphHashTable.size; i++) {
+		sta_ds = dph_get_hash_entry(mac_ctx, i,
+					    &session->dph.dphHashTable);
+		if (!sta_ds)
+			continue;
+		if (sta_ds->staType != STA_ENTRY_PEER)
+			continue;
+		if (!lim_support_6ghz_band_op_class(
+			mac_ctx, &sta_ds->supp_operating_classes)) {
+			legacy_client_present = true;
+			pe_debug("peer %pM 6ghz not supported",
+				 sta_ds->staAddr);
+			break;
+		}
+		pe_debug("peer %pM 6ghz supported",
+			 sta_ds->staAddr);
+	}
+	if (legacy_client_present)
+		policy_mgr_set_ap_6ghz_capable(
+			mac_ctx->psoc, session->vdev_id, false,
+			CONN_6GHZ_FLAG_NO_LEGACY_CLIENT);
+	else
+		policy_mgr_set_ap_6ghz_capable(
+			mac_ctx->psoc, session->vdev_id, true,
+			CONN_6GHZ_FLAG_NO_LEGACY_CLIENT);
+}
+#endif
+
 #ifdef WLAN_FEATURE_11AX
 void lim_add_he_cap(tpAddStaParams add_sta_params, tpSirAssocReq assoc_req)
 {

+ 15 - 0
core/mac/src/pe/lim/lim_utils.h

@@ -1901,4 +1901,19 @@ QDF_STATUS lim_pre_vdev_start(struct mac_context *mac,
 QDF_STATUS
 lim_set_ch_phy_mode(struct wlan_objmgr_vdev *vdev, uint8_t dot11mode);
 
+#if defined(CONFIG_BAND_6GHZ) && defined(WLAN_FEATURE_11AX)
+/**
+ * lim_ap_check_6g_compatible_peer() - check all client support 6Ghz band
+ * @mac_ctx: mac context
+ * @session: pe session
+ *
+ * Return: void
+ */
+void lim_ap_check_6g_compatible_peer(struct mac_context *mac_ctx,
+				     struct pe_session *session);
+#else
+static inline void lim_ap_check_6g_compatible_peer(
+	struct mac_context *mac_ctx, struct pe_session *session)
+{}
+#endif
 #endif /* __LIM_UTILS_H */

+ 9 - 0
core/sap/inc/sap_api.h

@@ -1445,6 +1445,15 @@ QDF_STATUS wlansap_filter_ch_based_acs(struct sap_context *sap_ctx,
 				       uint32_t *ch_freq_list,
 				       uint32_t *ch_cnt);
 
+/**
+ * wlansap_is_6ghz_included_in_acs_range() - check 6ghz channel included in
+ * ACS range
+ * @sap_ctx: sap context
+ *
+ * Return: QDF_STATUS
+ */
+bool wlansap_is_6ghz_included_in_acs_range(struct sap_context *sap_ctx);
+
 /**
  * wlansap_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
  * restart

+ 19 - 0
core/sap/src/sap_module.c

@@ -2959,6 +2959,25 @@ QDF_STATUS wlansap_filter_ch_based_acs(struct sap_context *sap_ctx,
 	return QDF_STATUS_SUCCESS;
 }
 
+bool wlansap_is_6ghz_included_in_acs_range(struct sap_context *sap_ctx)
+{
+	uint32_t i;
+	uint32_t *ch_freq_list;
+
+	if (!sap_ctx || !sap_ctx->acs_cfg ||
+	    !sap_ctx->acs_cfg->master_freq_list ||
+	    !sap_ctx->acs_cfg->master_ch_list_count) {
+		sap_err("NULL parameters");
+		return false;
+	}
+	ch_freq_list = sap_ctx->acs_cfg->master_freq_list;
+	for (i = 0; i < sap_ctx->acs_cfg->master_ch_list_count; i++) {
+		if (WLAN_REG_IS_6GHZ_CHAN_FREQ(ch_freq_list[i]))
+			return true;
+	}
+	return false;
+}
+
 #if defined(FEATURE_WLAN_CH_AVOID)
 /**
  * wlansap_get_safe_channel() - Get safe channel from current regulatory