Browse Source

qcacld-3.0: STA SAP concurrency changes for DFS channel

Previously, if STA is connected to DFS channel and SAP starts on
Non-DBS HW, then it is forced to start on DFS channel with BW 160 Mhz
irrespective of BW on which STA is connected without CAC.
Even after STA disconnects, SAP remains on DFS channel with BW 160Mhz.
So, scan will be disabled and STA cannot be connected on any channel
other than DFS channel.
If STA is connected on non-DFS channel on 5 GHz and SAP starts, it
will start on non-DFS channel as primary channel with BW 160 Mhz
without CAC. Also, scanning was also allowed when SAP is started with
BW 160 Mhz. This might violate regulatory in case radar comes up while
scanning.
Standalone SAP on DFS channel was not allowed.

To fix this, Force set SCC for non-dbs HW, this way standalone SAP
can come on DFS channel but scan will be disabled in such case and
STA cannot be connected other than DFS channel.
In case STA gets connected to dfs channel in non-dbs HW, then sap
starts only on STA channel with force SCC with BW
MIN(sta_chan_width, CH_WIDTH_80MHZ).
Afterwards, if STA disconnects, restart the AP with BW CH_WIDTH_80MHZ
on safe channel. Scan will be allowed as the DFS master capability is
offloaded to AP with which STA is connected on DFS channel.
Also, if standalone sap starts, then STA connects to DFS channel then
SAP will restart with STA channel frequency and Channel width
MIN(sta_chan_width, 80MHZ).
If standalone SAP starts and then STA connects to non-dfs AP or SAP
starts when STA is already connected to non-DFS AP, then ch_width is
MAX(sta_chan_width, 80MHZ) (5 Ghz) or 20 Mhz (2.4 Ghz).
If STA disconnects during SAP+STA on non-DFS, SAP won't restart unless
the STA was connected on BW 160 Mhz.

Change-Id: I1cebfc79f170c1e4e2710ed747ec804df3d8b441
CRs-Fixed: 2809255
Utkarsh Bhatnagar 4 years ago
parent
commit
ff006ecb1f

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

@@ -179,6 +179,20 @@ QDF_STATUS policy_mgr_set_dual_mac_feature(struct wlan_objmgr_psoc *psoc,
  */
 QDF_STATUS policy_mgr_get_force_1x1(struct wlan_objmgr_psoc *psoc,
 				    uint8_t *force_1x1);
+
+/**
+ * policy_mgr_set_sta_sap_scc_on_dfs_chnl() - to set sta_sap_scc_on_dfs_chnl
+ * @psoc: pointer to psoc
+ * @sta_sap_scc_on_dfs_chnl: value to be set
+ *
+ * This API is used to set sta_sap_scc_on_dfs_chnl
+ *
+ * Return: QDF_STATUS_SUCCESS up on success and any other status for failure.
+ */
+QDF_STATUS
+policy_mgr_set_sta_sap_scc_on_dfs_chnl(struct wlan_objmgr_psoc *psoc,
+				       uint8_t sta_sap_scc_on_dfs_chnl);
+
 /**
  * policy_mgr_get_sta_sap_scc_on_dfs_chnl() - to find out if STA and SAP
  *						   SCC is allowed on DFS channel
@@ -818,6 +832,7 @@ uint32_t policy_mgr_get_dfs_beaconing_session_id(
  * if any DFS session
  * @psoc: PSOC object information
  * @ch_freq: pointer to channel frequency that needs to filled
+ * @ch_width: pointer to channel width for the beaconing session
  *
  * If any beaconing session such as SAP or GO present and it is on DFS channel
  * then this function will return true
@@ -825,7 +840,9 @@ uint32_t policy_mgr_get_dfs_beaconing_session_id(
  * Return: true if session is on DFS or false if session is on non-dfs channel
  */
 bool policy_mgr_is_any_dfs_beaconing_session_present(
-		struct wlan_objmgr_psoc *psoc, uint32_t *ch_freq);
+		struct wlan_objmgr_psoc *psoc, qdf_freq_t *ch_freq,
+		enum hw_mode_bandwidth *ch_width);
+
 /**
  * policy_mgr_allow_concurrency() - Check for allowed concurrency
  * combination consulting the PCL
@@ -2065,6 +2082,36 @@ QDF_STATUS policy_mgr_get_chan_by_session_id(struct wlan_objmgr_psoc *psoc,
 uint32_t policy_mgr_get_sap_go_count_on_mac(struct wlan_objmgr_psoc *psoc,
 					    uint32_t *list, uint8_t mac_id);
 
+/**
+ * policy_mgr_is_sta_present_on_dfs_channel() - to find whether any DFS STA is
+ *                                              present
+ * @psoc: PSOC object information
+ * @vdev_id: pointer to vdev_id. It will be filled with the vdev_id of DFS STA
+ * @ch_freq: pointer to channel frequency on which DFS STA is present
+ * @ch_width: pointer channel width on which DFS STA is connected
+ * If any STA is connected on DFS channel then this function will return true
+ *
+ * Return: true if session is on DFS or false if session is on non-dfs channel
+ */
+bool policy_mgr_is_sta_present_on_dfs_channel(struct wlan_objmgr_psoc *psoc,
+					      uint8_t *vdev_id,
+					      qdf_freq_t *ch_freq,
+					      enum hw_mode_bandwidth *ch_width);
+
+/**
+ * policy_mgr_is_sta_present_on_freq() - Checks whether sta is present on the
+ *                                       given frequency
+ * @psoc: PSOC object information
+ * @vdev_id: pointer to vdev_id. It will be filled with the vdev_id of DFS STA
+ * @ch_freq: channel for which this checks is needed
+ * @ch_width: pointer channel width on which DFS STA is connected
+ *
+ * Return: true if STA is found in ch_freq
+ */
+bool policy_mgr_is_sta_present_on_freq(struct wlan_objmgr_psoc *psoc,
+				       uint8_t *vdev_id, qdf_freq_t ch_freq,
+				       enum hw_mode_bandwidth *ch_width);
+
 /**
  * policy_mgr_is_sta_gc_active_on_mac() - Is there active sta/gc for a
  * given mac id
@@ -2966,6 +3013,14 @@ QDF_STATUS policy_mgr_get_updated_scan_and_fw_mode_config(
 bool policy_mgr_is_safe_channel(struct wlan_objmgr_psoc *psoc,
 				uint32_t ch_freq);
 
+/**
+ * policy_mgr_get_ch_width() - Convert hw_mode_bandwidth to phy_ch_width
+ * @bw: Hardware mode band width used by WMI
+ *
+ * Return: phy_ch_width
+ */
+enum phy_ch_width policy_mgr_get_ch_width(enum hw_mode_bandwidth bw);
+
 /**
  * policy_mgr_is_force_scc() - checks if SCC needs to be
  * mandated

+ 111 - 9
components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -120,6 +120,22 @@ QDF_STATUS policy_mgr_get_force_1x1(struct wlan_objmgr_psoc *psoc,
 	return QDF_STATUS_SUCCESS;
 }
 
+QDF_STATUS
+policy_mgr_set_sta_sap_scc_on_dfs_chnl(struct wlan_objmgr_psoc *psoc,
+				       uint8_t sta_sap_scc_on_dfs_chnl)
+{
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("pm_ctx is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+	pm_ctx->cfg.sta_sap_scc_on_dfs_chnl = sta_sap_scc_on_dfs_chnl;
+
+	return QDF_STATUS_SUCCESS;
+}
+
 QDF_STATUS
 policy_mgr_get_sta_sap_scc_on_dfs_chnl(struct wlan_objmgr_psoc *psoc,
 				       uint8_t *sta_sap_scc_on_dfs_chnl)
@@ -3103,6 +3119,77 @@ bool policy_mgr_is_multiple_active_sta_sessions(struct wlan_objmgr_psoc *psoc)
 		psoc, PM_STA_MODE, NULL) > 1;
 }
 
+bool policy_mgr_is_sta_present_on_dfs_channel(struct wlan_objmgr_psoc *psoc,
+					      uint8_t *vdev_id,
+					      qdf_freq_t *ch_freq,
+					      enum hw_mode_bandwidth *ch_width)
+{
+	struct policy_mgr_conc_connection_info *conn_info;
+	bool status = false;
+	uint32_t conn_index = 0;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+
+	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 &&
+		    (conn_info->mode == PM_STA_MODE ||
+		     conn_info->mode == PM_P2P_CLIENT_MODE) &&
+		    (wlan_reg_is_dfs_for_freq(pm_ctx->pdev, conn_info->freq) ||
+		     (wlan_reg_is_5ghz_ch_freq(conn_info->freq) &&
+		      conn_info->bw == HW_MODE_160_MHZ))) {
+			*vdev_id = conn_info->vdev_id;
+			*ch_freq = pm_conc_connection_list[conn_index].freq;
+			*ch_width = conn_info->bw;
+			status = true;
+			break;
+		}
+	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+
+	return status;
+}
+
+bool policy_mgr_is_sta_present_on_freq(struct wlan_objmgr_psoc *psoc,
+				       uint8_t *vdev_id,
+				       qdf_freq_t ch_freq,
+				       enum hw_mode_bandwidth *ch_width)
+{
+	struct policy_mgr_conc_connection_info *conn_info;
+	bool status = false;
+	uint32_t conn_index = 0;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+
+	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 &&
+		    (conn_info->mode == PM_STA_MODE ||
+		     conn_info->mode == PM_P2P_CLIENT_MODE) &&
+		    ch_freq == conn_info->freq) {
+			*vdev_id = conn_info->vdev_id;
+			*ch_width = conn_info->bw;
+			status = true;
+			break;
+		}
+	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+
+	return status;
+}
+
 bool policy_mgr_is_sta_gc_active_on_mac(struct wlan_objmgr_psoc *psoc,
 					uint8_t mac_id)
 {
@@ -3217,7 +3304,8 @@ uint32_t policy_mgr_get_dfs_beaconing_session_id(
 }
 
 bool policy_mgr_is_any_dfs_beaconing_session_present(
-		struct wlan_objmgr_psoc *psoc, uint32_t *ch_freq)
+		struct wlan_objmgr_psoc *psoc, qdf_freq_t *ch_freq,
+		enum hw_mode_bandwidth *ch_width)
 {
 	struct policy_mgr_conc_connection_info *conn_info;
 	bool status = false;
@@ -3234,10 +3322,13 @@ bool policy_mgr_is_any_dfs_beaconing_session_present(
 			conn_index++) {
 		conn_info = &pm_conc_connection_list[conn_index];
 		if (conn_info->in_use &&
-		    wlan_reg_is_dfs_for_freq(pm_ctx->pdev, conn_info->freq) &&
-		    (PM_SAP_MODE == conn_info->mode ||
-		     PM_P2P_GO_MODE == conn_info->mode)) {
+		    (conn_info->mode == PM_SAP_MODE ||
+		     conn_info->mode == PM_P2P_GO_MODE) &&
+		     (wlan_reg_is_dfs_for_freq(pm_ctx->pdev, conn_info->freq) ||
+		      (wlan_reg_is_5ghz_ch_freq(conn_info->freq) &&
+		      conn_info->bw == HW_MODE_160_MHZ))) {
 			*ch_freq = pm_conc_connection_list[conn_index].freq;
+			*ch_width = conn_info->bw;
 			status = true;
 		}
 	}
@@ -3249,7 +3340,9 @@ bool policy_mgr_is_any_dfs_beaconing_session_present(
 bool policy_mgr_scan_trim_5g_chnls_for_dfs_ap(struct wlan_objmgr_psoc *psoc)
 {
 	struct policy_mgr_psoc_priv_obj *pm_ctx;
-	uint32_t ap_dfs_ch_freq = 0;
+	qdf_freq_t dfs_ch_frq = 0;
+	uint8_t vdev_id;
+	enum hw_mode_bandwidth ch_width;
 
 	pm_ctx = policy_mgr_get_context(psoc);
 	if (!pm_ctx) {
@@ -3257,8 +3350,17 @@ bool policy_mgr_scan_trim_5g_chnls_for_dfs_ap(struct wlan_objmgr_psoc *psoc)
 		return false;
 	}
 
-	policy_mgr_is_any_dfs_beaconing_session_present(psoc, &ap_dfs_ch_freq);
-	if (!ap_dfs_ch_freq)
+	if (policy_mgr_is_sta_present_on_dfs_channel(psoc, &vdev_id,
+						     &dfs_ch_frq,
+						     &ch_width)) {
+		policymgr_nofl_err("DFS STA present vdev_id %d ch_feq %d ch_width %d",
+				   vdev_id, dfs_ch_frq, ch_width);
+		return false;
+	}
+
+	policy_mgr_is_any_dfs_beaconing_session_present(psoc, &dfs_ch_frq,
+							&ch_width);
+	if (!dfs_ch_frq)
 		return false;
 	/*
 	 * 1) if agile & DFS scans are supportet
@@ -3273,8 +3375,8 @@ bool policy_mgr_scan_trim_5g_chnls_for_dfs_ap(struct wlan_objmgr_psoc *psoc)
 	    policy_mgr_get_single_mac_scan_with_dfs_config(psoc))
 		return false;
 
-	policy_mgr_debug("scan skip 5g chan due to dfs ap(ch %d) present",
-			 ap_dfs_ch_freq);
+	policy_mgr_debug("scan skip 5g chan due to dfs ap(ch %d / ch_width %d) present",
+			 dfs_ch_frq, ch_width);
 
 	return true;
 }

+ 4 - 5
components/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h

@@ -570,15 +570,14 @@ QDF_STATUS policy_mgr_pdev_get_pcl(struct wlan_objmgr_psoc *psoc,
 void pm_dbs_opportunistic_timer_handler(void *data);
 enum policy_mgr_con_mode policy_mgr_get_mode(uint8_t type,
 		uint8_t subtype);
-enum hw_mode_bandwidth policy_mgr_get_bw(enum phy_ch_width chan_width);
 
 /**
- * policy_mgr_get_bw() - Convert hw_mode_bandwidth to phy_ch_width
- * @bw: Hardware mode band width used by WMI
+ * policy_mgr_get_bw() - Convert phy_ch_width to hw_mode_bandwidth.
+ * @chan_width: phy_ch_width
  *
- * Return: phy_ch_width
+ * Return: hw_mode_bandwidth
  */
-enum phy_ch_width policy_mgr_get_ch_width(enum hw_mode_bandwidth bw);
+enum hw_mode_bandwidth policy_mgr_get_bw(enum phy_ch_width chan_width);
 
 QDF_STATUS policy_mgr_get_channel_list(struct wlan_objmgr_psoc *psoc,
 			enum policy_mgr_pcl_type pcl,

+ 7 - 1
components/cmn_services/policy_mgr/src/wlan_policy_mgr_ucfg.c

@@ -55,9 +55,15 @@ static QDF_STATUS policy_mgr_init_cfg(struct wlan_objmgr_psoc *psoc)
 		cfg_get(psoc, CFG_FORCE_1X1_FEATURE);
 	cfg->sta_sap_scc_on_dfs_chnl =
 		cfg_get(psoc, CFG_STA_SAP_SCC_ON_DFS_CHAN);
+
+	/*
+	 * Force set sta_sap_scc_on_dfs_chnl on Non-DBS HW so that standalone
+	 * SAP is not allowed on DFS channel on non-DBS HW, Also, force SCC in
+	 * case of STA+SAP
+	 */
 	if (cfg->sta_sap_scc_on_dfs_chnl == 2 &&
 	    !cfg_get(psoc, CFG_ENABLE_DFS_MASTER_CAPABILITY))
-		cfg->sta_sap_scc_on_dfs_chnl = 0;
+		cfg->sta_sap_scc_on_dfs_chnl = 1;
 	cfg->nan_sap_scc_on_lte_coex_chnl =
 		cfg_get(psoc, CFG_NAN_SAP_SCC_ON_LTE_COEX_CHAN);
 	cfg->sta_sap_scc_on_lte_coex_chnl =

+ 6 - 1
core/hdd/src/wlan_hdd_hostapd.c

@@ -3243,6 +3243,8 @@ QDF_STATUS wlan_hdd_get_channel_for_sap_restart(
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	/* Initialized ch_width to CH_WIDTH_MAX */
+	ch_params.ch_width = CH_WIDTH_MAX;
 	intf_ch_freq = wlansap_get_chan_band_restrict(sap_context, &csa_reason);
 	if (intf_ch_freq)
 		goto sap_restart;
@@ -3315,7 +3317,10 @@ sap_restart:
 	}
 	hdd_debug("SAP restart orig chan freq: %d, new freq: %d",
 		  hdd_ap_ctx->sap_config.chan_freq, intf_ch_freq);
-	ch_params.ch_width = CH_WIDTH_MAX;
+	ch_params.ch_width = wlan_sap_get_concurrent_bw(hdd_ctx->pdev,
+							hdd_ctx->psoc,
+							intf_ch_freq,
+							ch_params.ch_width);
 	hdd_ap_ctx->bss_stop_reason = BSS_STOP_DUE_TO_MCC_SCC_SWITCH;
 
 	wlan_reg_set_channel_params_for_freq(hdd_ctx->pdev,

+ 9 - 3
core/hdd/src/wlan_hdd_scan.c

@@ -459,7 +459,7 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy,
 	int status;
 	struct hdd_scan_info *scan_info = NULL;
 	struct hdd_adapter *con_sap_adapter;
-	uint32_t con_dfs_ch_freq;
+	qdf_freq_t con_dfs_ch_freq;
 	uint8_t curr_vdev_id;
 	enum scan_reject_states curr_reason;
 	static uint32_t scan_ebusy_cnt;
@@ -468,6 +468,7 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy,
 	struct wlan_objmgr_vdev *vdev;
 	QDF_STATUS qdf_status;
 	bool enable_connected_scan;
+	enum phy_ch_width con_dfs_ch_width;
 
 	if (cds_is_fw_down()) {
 		hdd_err("firmware is down, scan cmd cannot be processed");
@@ -525,18 +526,23 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy,
 	scan_info = &adapter->scan_info;
 
 	/* Block All Scan during DFS operation and send null scan result */
+
 	con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
 	if (con_sap_adapter) {
 		con_dfs_ch_freq =
 			con_sap_adapter->session.ap.sap_config.chan_freq;
+		con_dfs_ch_width =
+		      con_sap_adapter->session.ap.sap_config.ch_params.ch_width;
 		if (con_dfs_ch_freq == AUTO_CHANNEL_SELECT)
 			con_dfs_ch_freq =
 				con_sap_adapter->session.ap.operating_chan_freq;
 
 		if (!policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) &&
-		    wlan_reg_is_dfs_for_freq(hdd_ctx->pdev, con_dfs_ch_freq) &&
 		    !policy_mgr_is_sta_sap_scc_allowed_on_dfs_chan(
-			hdd_ctx->psoc)) {
+		    hdd_ctx->psoc) &&
+		    (wlan_reg_is_dfs_for_freq(hdd_ctx->pdev, con_dfs_ch_freq) ||
+		    (wlan_reg_is_5ghz_ch_freq(con_dfs_ch_freq) &&
+		     con_dfs_ch_width == CH_WIDTH_160MHZ))) {
 			/* Provide empty scan result during DFS operation since
 			 * scanning not supported during DFS. Reason is
 			 * following case:

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

@@ -1230,6 +1230,25 @@ struct csr_roam_profile *wlan_sap_get_roam_profile(struct sap_context *sap_ctx);
  */
 eCsrPhyMode wlan_sap_get_phymode(struct sap_context *sap_ctx);
 
+/**
+ * wlan_sap_get_concurrent_bw() - Returns SAP BW based on concurrent channel &
+ *                                STA DFS channel
+ * @pdev: Pointer to Pdev
+ * @psoc: Pointer to Psoc
+ * @con_ch_freq: interfering concurrent channel
+ * @channel_width: Channel width
+ *
+ * Return: Channel width. If STA is not present on con_ch_freq, it returns
+ *        max of STA BW and 80 Mhz. If STA is not connected in dfs chan or STA
+ *........BW is not 160 Mhz (which includes DFS channel), then it will return
+ *        BW maximum of STA BW and 80 Mhz. If DFS STA is present, then return
+ *        BW as min of 80 and STA BW.
+ */
+enum phy_ch_width wlan_sap_get_concurrent_bw(struct wlan_objmgr_pdev *pdev,
+					     struct wlan_objmgr_psoc *psoc,
+					     qdf_freq_t con_ch_freq,
+					     enum phy_ch_width channel_width);
+
 /**
  * wlan_sap_get_vht_ch_width() - Returns SAP VHT channel width.
  * @sap_ctx:	Pointer to Sap Context

+ 5 - 4
core/sap/src/sap_fsm.c

@@ -806,10 +806,11 @@ sap_validate_chan(struct sap_context *sap_context,
 					  sap_context->chan_freq,
 					con_ch_freq);
 				sap_context->chan_freq = con_ch_freq;
-				if (WLAN_REG_IS_24GHZ_CH_FREQ(
-				    sap_context->chan_freq))
-					sap_context->ch_params.ch_width =
-							CH_WIDTH_20MHZ;
+				sap_context->ch_params.ch_width =
+				    wlan_sap_get_concurrent_bw(mac_ctx->pdev,
+							       mac_ctx->psoc,
+							       con_ch_freq,
+					       sap_context->ch_params.ch_width);
 				wlan_reg_set_channel_params_for_freq(
 					mac_ctx->pdev,
 					sap_context->chan_freq,

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

@@ -576,6 +576,44 @@ eCsrPhyMode wlan_sap_get_phymode(struct sap_context *sap_ctx)
 	return sap_ctx->csr_roamProfile.phyMode;
 }
 
+enum phy_ch_width wlan_sap_get_concurrent_bw(struct wlan_objmgr_pdev *pdev,
+					     struct wlan_objmgr_psoc *psoc,
+					     qdf_freq_t con_ch_freq,
+					     enum phy_ch_width channel_width)
+{
+	enum hw_mode_bandwidth sta_ch_width;
+	enum phy_ch_width sta_chan_width;
+	bool sta_present, is_con_chan_dfs = false;
+	uint8_t sta_vdev_id;
+
+	if (WLAN_REG_IS_24GHZ_CH_FREQ(con_ch_freq))
+		return CH_WIDTH_20MHZ;
+
+	if (wlan_reg_is_6ghz_chan_freq(con_ch_freq))
+		return channel_width;
+
+	sta_present = policy_mgr_is_sta_present_on_freq(psoc,
+							&sta_vdev_id,
+							con_ch_freq,
+							&sta_ch_width);
+
+	/* if no STA present return max of BW and 80MHZ */
+	if (!sta_present)
+		return CH_WIDTH_80MHZ;
+
+	sta_chan_width = policy_mgr_get_ch_width(sta_ch_width);
+	if (wlan_reg_is_dfs_for_freq(pdev, con_ch_freq) ||
+	    sta_chan_width == CH_WIDTH_160MHZ)
+		is_con_chan_dfs = true;
+
+	/* if STA not on DFS return max of BW and 80MHZ */
+	if (!is_con_chan_dfs)
+		return  QDF_MAX(sta_chan_width, CH_WIDTH_80MHZ);
+
+	/* If sta channel is DFS return min of 80 and STA BW */
+	return QDF_MIN(sta_chan_width, CH_WIDTH_80MHZ);
+}
+
 uint32_t wlan_sap_get_vht_ch_width(struct sap_context *sap_ctx)
 {
 	if (!sap_ctx) {

+ 13 - 0
core/wma/src/wma_main.c

@@ -6698,6 +6698,7 @@ int wma_rx_service_ready_ext_event(void *handle, uint8_t *event,
 	struct wmi_unified *wmi_handle;
 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
 	target_resource_config *wlan_res_cfg;
+	uint8_t sta_sap_scc_on_dfs_chnl;
 
 	wma_debug("Enter");
 
@@ -6761,6 +6762,18 @@ int wma_rx_service_ready_ext_event(void *handle, uint8_t *event,
 	wma_init_scan_fw_mode_config(wma_handle->psoc, conc_scan_config_bits,
 				     fw_config_bits);
 
+	policy_mgr_get_sta_sap_scc_on_dfs_chnl(wma_handle->psoc,
+					       &sta_sap_scc_on_dfs_chnl);
+
+	/*
+	 * For non-dbs HW, disallow sta+sap on DFS channel as if SAP comes
+	 * on DFS master mode enable (sta_sap_scc_on_dfs_chnl = 2), scan will
+	 * be disabled and STA cannot connect to any other channel
+	 */
+	if (!policy_mgr_is_hw_dbs_capable(wma_handle->psoc) &&
+	    sta_sap_scc_on_dfs_chnl == 2)
+		policy_mgr_set_sta_sap_scc_on_dfs_chnl(wma_handle->psoc, 1);
+
 	target_psoc_set_num_radios(tgt_hdl, 1);
 
 	if (wmi_service_enabled(wmi_handle,