diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h
index 5d0159c37da9..982dfc096633 100644
--- a/core/hdd/inc/wlan_hdd_cfg.h
+++ b/core/hdd/inc/wlan_hdd_cfg.h
@@ -300,6 +300,30 @@ enum hdd_dot11_mode {
#define CFG_CHANNEL_BONDING_MODE_MAX WNI_CFG_CHANNEL_BONDING_MODE_STAMAX
#define CFG_CHANNEL_BONDING_MODE_DEFAULT WNI_CFG_CHANNEL_BONDING_MODE_STADEF
+/*
+ *
+ * override_ht20_40_24g - use channel Bonding in 24 GHz from supplicant
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * This ini is used to use channel Bonding in 24 GHz from supplicant if
+ * gChannelBondingMode24GHz is set
+ *
+ * Related: gChannelBondingMode24GHz
+ *
+ * Supported Feature: STA
+ *
+ * Usage: Internal/External
+ *
+ *
+ */
+
+#define CFG_OVERRIDE_HT40_20_24GHZ_NAME "override_ht20_40_24g"
+#define CFG_OVERRIDE_HT40_20_24GHZ_MIN 0
+#define CFG_OVERRIDE_HT40_20_24GHZ_MAX 1
+#define CFG_OVERRIDE_HT40_20_24GHZ_DEFAULT 0
+
/*
*
* gChannelBondingMode5GHz - Configures Channel Bonding in 5 GHz
@@ -11568,6 +11592,7 @@ struct hdd_config {
uint32_t nBmpsMinListenInterval;
enum hdd_dot11_mode dot11Mode;
uint32_t nChannelBondingMode24GHz;
+ bool override_ht20_40_24g;
uint32_t nChannelBondingMode5GHz;
uint32_t MaxRxAmpduFactor;
uint16_t TxRate;
diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c
index b9ff033f3e21..f898db0cba3a 100644
--- a/core/hdd/src/wlan_hdd_cfg.c
+++ b/core/hdd/src/wlan_hdd_cfg.c
@@ -481,6 +481,13 @@ struct reg_table_entry g_registry_table[] = {
CFG_CHANNEL_BONDING_MODE_MIN,
CFG_CHANNEL_BONDING_MODE_MAX),
+ REG_VARIABLE(CFG_OVERRIDE_HT40_20_24GHZ_NAME, WLAN_PARAM_Integer,
+ struct hdd_config, override_ht20_40_24g,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_OVERRIDE_HT40_20_24GHZ_DEFAULT,
+ CFG_OVERRIDE_HT40_20_24GHZ_MIN,
+ CFG_OVERRIDE_HT40_20_24GHZ_MAX),
+
REG_VARIABLE(CFG_CHANNEL_BONDING_MODE_5GHZ_NAME, WLAN_PARAM_Integer,
struct hdd_config, nChannelBondingMode5GHz,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
@@ -5646,6 +5653,9 @@ void hdd_cfg_print(hdd_context_t *pHddCtx)
pHddCtx->config->sap_p2p_11ac_override);
hdd_debug("Name = [ChannelBondingMode] Value = [%u]",
pHddCtx->config->nChannelBondingMode24GHz);
+ hdd_debug("Name = [%s] Value = [%u] ",
+ CFG_OVERRIDE_HT40_20_24GHZ_NAME,
+ pHddCtx->config->override_ht20_40_24g);
hdd_debug("Name = [ChannelBondingMode] Value = [%u]",
pHddCtx->config->nChannelBondingMode5GHz);
hdd_debug("Name = [dot11Mode] Value = [%u]",
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 7af07645542e..9d9b26b7203d 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -16002,6 +16002,55 @@ static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
}
#endif
+
+/**
+ * wlan_hdd_check_ht20_ht40_ind() - check if Supplicant has indicated to
+ * connect in HT20 mode
+ * @hdd_ctx: hdd context
+ * @adapter: Pointer to the HDD adapter
+ * @req: Pointer to the structure cfg_connect_params receieved from user space
+ *
+ * This function will check if supplicant has indicated to to connect in HT20
+ * mode. this is currently applicable only for 2.4Ghz mode only.
+ * if feature is enabled and supplicant indicate HT20 set
+ * force_24ghz_in_ht20 to true to force 2.4Ghz in HT20 else set it to false.
+ *
+ * Return: void
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
+static void wlan_hdd_check_ht20_ht40_ind(hdd_context_t *hdd_ctx,
+ hdd_adapter_t *adapter,
+ struct cfg80211_connect_params *req)
+{
+ hdd_wext_state_t *wext_state = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
+ tCsrRoamProfile *roam_profile;
+
+ roam_profile = &wext_state->roamProfile;
+ roam_profile->force_24ghz_in_ht20 = false;
+
+ if (hdd_ctx->config->override_ht20_40_24g &&
+ !(req->ht_capa.cap_info &
+ IEEE80211_HT_CAP_SUP_WIDTH_20_40))
+ roam_profile->force_24ghz_in_ht20 = true;
+
+ hdd_debug("req->ht_capa.cap_info %x override_ht20_40_24g %d",
+ req->ht_capa.cap_info,
+ hdd_ctx->config->override_ht20_40_24g);
+}
+#else
+static inline void wlan_hdd_check_ht20_ht40_ind(hdd_context_t *hdd_ctx,
+ hdd_adapter_t *adapter,
+ struct cfg80211_connect_params *req)
+{
+ hdd_wext_state_t *wext_state = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
+ tCsrRoamProfile *roam_profile;
+
+ roam_profile = &wext_state->roamProfile;
+
+ roam_profile->force_24ghz_in_ht20 = false;
+}
+#endif
+
/**
* __wlan_hdd_cfg80211_connect() - cfg80211 connect api
* @wiphy: Pointer to wiphy
@@ -16150,6 +16199,9 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
channel = req->channel->hw_value;
else
channel = 0;
+
+ wlan_hdd_check_ht20_ht40_ind(pHddCtx, pAdapter, req);
+
status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
req->ssid_len, req->bssid,
bssid_hint, channel, 0);
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index 840cec0cc75b..75e2c302953a 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -1246,6 +1246,7 @@ typedef struct sSirSmeJoinReq {
struct cds_fils_connection_info fils_con_info;
#endif
/* Pls make this as last variable in struct */
+ bool force_24ghz_in_ht20;
tSirBssDescription bssDescription;
/*
* WARNING: Pls make bssDescription as last variable in struct
diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h
index 54cbe04b9422..5d0d244249cd 100644
--- a/core/mac/src/pe/include/lim_session.h
+++ b/core/mac/src/pe/include/lim_session.h
@@ -518,6 +518,7 @@ typedef struct sPESession /* Added to Support BT-AMP */
#endif
bool enable_bcast_probe_rsp;
uint8_t ht_client_cnt;
+ bool force_24ghz_in_ht20;
bool ch_switch_in_progress;
#ifdef WLAN_FEATURE_FILS_SK
struct pe_fils_session *fils_info;
diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c
index ac831c229ac0..f8b3128f3b26 100644
--- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c
+++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c
@@ -1686,9 +1686,10 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
/*Store Persona */
session->pePersona = sme_join_req->staPersona;
QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_INFO,
- FL("PE PERSONA=%d cbMode %u nwType: %d dot11mode: %d"),
+ FL("PE PERSONA=%d cbMode %u nwType: %d dot11mode: %d force_24ghz_in_ht20 %d"),
session->pePersona, sme_join_req->cbMode,
- session->nwType, session->dot11mode);
+ session->nwType, session->dot11mode,
+ sme_join_req->force_24ghz_in_ht20);
/* Copy The channel Id to the session Table */
session->currentOperChannel = bss_desc->channelId;
@@ -1731,6 +1732,8 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
/*Phy mode */
session->gLimPhyMode = bss_desc->nwType;
handle_ht_capabilityand_ht_info(mac_ctx, session);
+ session->force_24ghz_in_ht20 =
+ sme_join_req->force_24ghz_in_ht20;
/* cbMode is already merged value of peer and self -
* done by csr in csr_get_cb_mode_from_ies */
session->htSupportedChannelWidthSet =
diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c
index a3363eda6178..e4b13012a541 100644
--- a/core/mac/src/pe/lim/lim_utils.c
+++ b/core/mac/src/pe/lim/lim_utils.c
@@ -4371,6 +4371,12 @@ void lim_update_sta_run_time_ht_switch_chnl_params(tpAniSirGlobal pMac,
(pMac, eHT_SUPPORTED_CHANNEL_WIDTH_SET, psessionEntry))
return;
+ if (WLAN_REG_IS_24GHZ_CH(psessionEntry->currentOperChannel) &&
+ psessionEntry->force_24ghz_in_ht20) {
+ pe_debug("force_24ghz_in_ht20 is set and channel is 2.4 Ghz");
+ return;
+ }
+
if (psessionEntry->ftPEContext.ftPreAuthSession) {
pe_err("FT PREAUTH channel change is in progress");
return;
diff --git a/core/mac/src/pe/sch/sch_beacon_process.c b/core/mac/src/pe/sch/sch_beacon_process.c
index c9f88b6a717a..7bcbe9f127c2 100644
--- a/core/mac/src/pe/sch/sch_beacon_process.c
+++ b/core/mac/src/pe/sch/sch_beacon_process.c
@@ -684,9 +684,13 @@ sch_bcn_process_sta_ibss(tpAniSirGlobal mac_ctx,
uint16_t aid;
uint8_t cb_mode;
- if (CHAN_ENUM_14 >= session->currentOperChannel)
- cb_mode = mac_ctx->roam.configParam.channelBondingMode24GHz;
- else
+ if (CHAN_ENUM_14 >= session->currentOperChannel) {
+ if (session->force_24ghz_in_ht20)
+ cb_mode = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
+ else
+ cb_mode =
+ mac_ctx->roam.configParam.channelBondingMode24GHz;
+ } else
cb_mode = mac_ctx->roam.configParam.channelBondingMode5GHz;
/* check for VHT capability */
pStaDs = dph_lookup_hash_entry(mac_ctx, pMh->sa, &aid,
diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h
index 630db794ad4f..f843636e7771 100644
--- a/core/sme/inc/csr_api.h
+++ b/core/sme/inc/csr_api.h
@@ -1000,6 +1000,7 @@ typedef struct tagCsrRoamProfile {
tSirMacRateSet supported_rates;
tSirMacRateSet extended_rates;
struct qdf_mac_addr bssid_hint;
+ bool force_24ghz_in_ht20;
bool do_not_roam;
uint32_t cac_duration_ms;
uint32_t dfs_regdomain;
diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c
index 112fb0099c47..69de06ccadd0 100644
--- a/core/sme/src/csr/csr_api_roam.c
+++ b/core/sme/src/csr/csr_api_roam.c
@@ -4328,6 +4328,12 @@ QDF_STATUS csr_roam_prepare_bss_config(tpAniSirGlobal pMac,
else
pBssConfig->cbMode = PHY_SINGLE_CHANNEL_CENTERED;
+ if (WLAN_REG_IS_24GHZ_CH(pBssDesc->channelId) &&
+ pProfile->force_24ghz_in_ht20) {
+ pBssConfig->cbMode = PHY_SINGLE_CHANNEL_CENTERED;
+ sme_debug("force_24ghz_in_ht20 is set so set cbmode to 0");
+ }
+
return QDF_STATUS_SUCCESS;
}
@@ -7848,6 +7854,7 @@ QDF_STATUS csr_roam_copy_profile(tpAniSirGlobal pMac,
/*Save the WPS info */
pDstProfile->bWPSAssociation = pSrcProfile->bWPSAssociation;
pDstProfile->bOSENAssociation = pSrcProfile->bOSENAssociation;
+ pDstProfile->force_24ghz_in_ht20 = pSrcProfile->force_24ghz_in_ht20;
pDstProfile->uapsd_mask = pSrcProfile->uapsd_mask;
pDstProfile->beaconInterval = pSrcProfile->beaconInterval;
pDstProfile->privacy = pSrcProfile->privacy;
@@ -14715,8 +14722,11 @@ QDF_STATUS csr_send_join_req_msg(tpAniSirGlobal pMac, uint32_t sessionId,
csr_join_req->staPersona = (uint8_t) pProfile->csrPersona;
csr_join_req->wps_registration = pProfile->bWPSAssociation;
csr_join_req->cbMode = (uint8_t) pSession->bssParams.cbMode;
- sme_debug("CSR PERSONA: %d CSR CbMode: %d",
- pProfile->csrPersona, pSession->bssParams.cbMode);
+ csr_join_req->force_24ghz_in_ht20 =
+ pProfile->force_24ghz_in_ht20;
+ sme_debug("CSR PERSONA: %d CSR CbMode: %d force 24gh ht20 %d",
+ pProfile->csrPersona, pSession->bssParams.cbMode,
+ csr_join_req->force_24ghz_in_ht20);
csr_join_req->uapsdPerAcBitmask = pProfile->uapsd_mask;
pSession->uapsd_mask = pProfile->uapsd_mask;
status =