diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 3b001c1f6962..a5fc4529ad11 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -4439,4 +4439,21 @@ static inline void hdd_sta_destroy_ctx_all(struct hdd_context *hdd_ctx) */ void hdd_init_start_completion(void); +/** + * hdd_update_phymode() - update the PHY mode of the adapter + * @adapter: adapter being modified + * @phymode: new PHY mode for the adapter + * @band: new band for the adapter + * @chwidth: new channel width for the adapter + * + * This function is called when the adapter is set to a new PHY mode. + * It takes a holistic look at the desired PHY mode along with the + * configured capabilities of the driver and the reported capabilities + * of the hardware in order to correctly configure all PHY-related + * parameters. + * + * Return: 0 on success, negative errno value on error + */ +int hdd_update_phymode(struct hdd_adapter *adapter, eCsrPhyMode phymode, + enum band_info band, uint32_t chwidth); #endif /* end #if !defined(WLAN_HDD_MAIN_H) */ diff --git a/core/hdd/inc/wlan_hdd_wext.h b/core/hdd/inc/wlan_hdd_wext.h index 05dca93d177a..37dfe0c1f033 100644 --- a/core/hdd/inc/wlan_hdd_wext.h +++ b/core/hdd/inc/wlan_hdd_wext.h @@ -258,7 +258,7 @@ int hdd_set_11ax_rate(struct hdd_adapter *adapter, int value, struct sap_config *sap_config); /** - * wlan_hdd_update_phymode() - handle change in PHY mode + * hdd_we_update_phymode() - handle change in PHY mode * @adapter: adapter being modified * @new_phymode: new PHY mode for the device * @@ -270,7 +270,8 @@ int hdd_set_11ax_rate(struct hdd_adapter *adapter, int value, * * Return: 0 on success, negative errno value on error */ -int wlan_hdd_update_phymode(struct hdd_adapter *adapter, int new_phymode); +int hdd_we_update_phymode(struct hdd_adapter *adapter, int new_phymode); + /** * wlan_hdd_update_btcoex_mode() - set BTCoex Mode * @adapter: adapter being modified diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 273365b34fac..12bc88843862 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -6713,6 +6713,7 @@ const struct nla_policy wlan_hdd_wifi_config_policy[ [QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC] = {.type = NLA_U8 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC] = {.type = NLA_U8 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE] = {.type = NLA_U32 }, }; @@ -7045,6 +7046,191 @@ static int wlan_hdd_cfg80211_wifi_set_rx_blocksize(struct hdd_adapter *adapter, return ret_val; } +static eCsrPhyMode +hdd_vendor_mode_to_phymode(enum qca_wlan_vendor_phy_mode vendor_phy_mode) +{ + eCsrPhyMode phymode; + + switch (vendor_phy_mode) { + case QCA_WLAN_VENDOR_PHY_MODE_AUTO: + case QCA_WLAN_VENDOR_PHY_MODE_2G_AUTO: + case QCA_WLAN_VENDOR_PHY_MODE_5G_AUTO: + phymode = eCSR_DOT11_MODE_AUTO; + break; + case QCA_WLAN_VENDOR_PHY_MODE_11A: + phymode = eCSR_DOT11_MODE_11a; + break; + case QCA_WLAN_VENDOR_PHY_MODE_11B: + phymode = eCSR_DOT11_MODE_11b; + break; + case QCA_WLAN_VENDOR_PHY_MODE_11G: + phymode = eCSR_DOT11_MODE_11g; + break; + case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT20: + case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40: + case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40PLUS: + case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40MINUS: + case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT20: + case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40: + case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40PLUS: + case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40MINUS: + case QCA_WLAN_VENDOR_PHY_MODE_11AGN: + phymode = eCSR_DOT11_MODE_11n; + break; + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT20: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40PLUS: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40MINUS: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80P80: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160: + phymode = eCSR_DOT11_MODE_11ac; + break; + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE20: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40PLUS: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40MINUS: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80P80: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160: + phymode = eCSR_DOT11_MODE_11ax; + break; + default: + hdd_err("Not supported mode %d", vendor_phy_mode); + phymode = -EINVAL; + } + + return phymode; +} + +static enum band_info +hdd_vendor_mode_to_band(enum qca_wlan_vendor_phy_mode vendor_phy_mode) +{ + enum band_info band; + + switch (vendor_phy_mode) { + case QCA_WLAN_VENDOR_PHY_MODE_AUTO: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT20: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40PLUS: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40MINUS: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80P80: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE20: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40PLUS: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40MINUS: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80P80: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160: + case QCA_WLAN_VENDOR_PHY_MODE_11AGN: + band = BAND_ALL; + break; + case QCA_WLAN_VENDOR_PHY_MODE_11A: + case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT20: + case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40: + case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40PLUS: + case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40MINUS: + case QCA_WLAN_VENDOR_PHY_MODE_5G_AUTO: + band = BAND_5G; + break; + case QCA_WLAN_VENDOR_PHY_MODE_11B: + case QCA_WLAN_VENDOR_PHY_MODE_11G: + case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT20: + case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40: + case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40PLUS: + case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40MINUS: + case QCA_WLAN_VENDOR_PHY_MODE_2G_AUTO: + band = BAND_2G; + break; + default: + hdd_err("Not supported mode %d", vendor_phy_mode); + band = -EINVAL; + } + + return band; +} + +static uint32_t +hdd_vendor_mode_to_chwidth(enum qca_wlan_vendor_phy_mode vendor_phy_mode) +{ + uint32_t chwidth; + + switch (vendor_phy_mode) { + case QCA_WLAN_VENDOR_PHY_MODE_AUTO: + case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40: + case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40PLUS: + case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40MINUS: + case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40: + case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40PLUS: + case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40MINUS: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40PLUS: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40MINUS: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80P80: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40PLUS: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40MINUS: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80P80: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160: + case QCA_WLAN_VENDOR_PHY_MODE_2G_AUTO: + case QCA_WLAN_VENDOR_PHY_MODE_5G_AUTO: + case QCA_WLAN_VENDOR_PHY_MODE_11AGN: + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; + break; + case QCA_WLAN_VENDOR_PHY_MODE_11A: + case QCA_WLAN_VENDOR_PHY_MODE_11B: + case QCA_WLAN_VENDOR_PHY_MODE_11G: + case QCA_WLAN_VENDOR_PHY_MODE_11NA_HT20: + case QCA_WLAN_VENDOR_PHY_MODE_11NG_HT20: + case QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT20: + case QCA_WLAN_VENDOR_PHY_MODE_11AX_HE20: + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + break; + default: + hdd_err("Not supported mode %d", vendor_phy_mode); + chwidth = -EINVAL; + } + + return chwidth; +} + +/** + * hdd_config_phy_mode() - set PHY mode + * @adapter: hdd adapter + * @attr: nla attr sent by supplicant + * + * Return: 0 on success; error number otherwise + */ +static int hdd_config_phy_mode(struct hdd_adapter *adapter, + const struct nlattr *attr) +{ + enum qca_wlan_vendor_phy_mode vendor_phy_mode; + eCsrPhyMode phymode; + enum band_info band; + uint32_t chwidth; + + vendor_phy_mode = nla_get_u8(attr); + + phymode = hdd_vendor_mode_to_phymode(vendor_phy_mode); + if (phymode < 0) + return -EINVAL; + + band = hdd_vendor_mode_to_band(vendor_phy_mode); + if (band < 0) + return -EINVAL; + + chwidth = hdd_vendor_mode_to_chwidth(vendor_phy_mode); + if (chwidth < 0) + return -EINVAL; + + return hdd_update_phymode(adapter, phymode, band, chwidth); +} + /** * hdd_set_roam_reason_vsie_status() - enable/disable inclusion of * roam reason vsie in Reassoc @@ -8145,6 +8331,8 @@ static const struct independent_setters independent_setters[] = { hdd_config_tx_stbc}, {QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC, hdd_config_rx_stbc}, + {QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE, + hdd_config_phy_mode}, }; #ifdef WLAN_FEATURE_ELNA diff --git a/core/hdd/src/wlan_hdd_hostapd_wext.c b/core/hdd/src/wlan_hdd_hostapd_wext.c index 45b507f32fd8..400fbb2d2252 100644 --- a/core/hdd/src/wlan_hdd_hostapd_wext.c +++ b/core/hdd/src/wlan_hdd_hostapd_wext.c @@ -926,7 +926,7 @@ static __iw_softap_setparam(struct net_device *dev, } case QCASAP_SET_PHYMODE: - ret = wlan_hdd_update_phymode(adapter, set_value); + ret = hdd_we_update_phymode(adapter, set_value); break; case QCASAP_DUMP_STATS: diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index dd4d1c2ada5f..bef6d949fd1f 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -17405,6 +17405,177 @@ QDF_STATUS hdd_monitor_mode_vdev_status(struct hdd_adapter *adapter) } #endif +static enum hdd_dot11_mode hdd_phymode_to_dot11_mode(eCsrPhyMode phymode) +{ + enum hdd_dot11_mode dot11_mode; + + switch (phymode) { + case eCSR_DOT11_MODE_AUTO: + dot11_mode = eHDD_DOT11_MODE_AUTO; + break; + case eCSR_DOT11_MODE_11a: + dot11_mode = eHDD_DOT11_MODE_11a; + break; + case eCSR_DOT11_MODE_11b: + dot11_mode = eHDD_DOT11_MODE_11b; + break; + case eCSR_DOT11_MODE_11g: + dot11_mode = eHDD_DOT11_MODE_11g; + break; + case eCSR_DOT11_MODE_11n: + dot11_mode = eHDD_DOT11_MODE_11n; + break; + case eCSR_DOT11_MODE_11ac: + dot11_mode = eHDD_DOT11_MODE_11ac; + break; + case eCSR_DOT11_MODE_11ax: + dot11_mode = eHDD_DOT11_MODE_11ax; + break; + default: + hdd_err("Not supported mode %d", phymode); + dot11_mode = -EINVAL; + } + + return dot11_mode; +} + +int hdd_update_phymode(struct hdd_adapter *adapter, eCsrPhyMode phymode, + enum band_info band, uint32_t chwidth) +{ + struct net_device *net = adapter->dev; + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + struct sme_config_params *sme_config = NULL; + struct csr_config_params *csr_config; + eCsrPhyMode old_phymode; + enum hdd_dot11_mode hdd_dot11mode; + uint32_t channel_bonding_mode; + uint8_t ui_band; + int ret = 0; + QDF_STATUS status; + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret < 0) + return ret; + + hdd_dot11mode = hdd_phymode_to_dot11_mode(phymode); + if (hdd_dot11mode < 0) + return -EINVAL; + + hdd_debug("phymode=%d chwidth=%d band=%d", phymode, chwidth, band); + + old_phymode = sme_get_phy_mode(hdd_ctx->mac_handle); + + sme_set_phy_mode(hdd_ctx->mac_handle, phymode); + + switch (band) { + case BAND_ALL: + ui_band = WLAN_HDD_UI_BAND_AUTO; + break; + case BAND_5G: + ui_band = WLAN_HDD_UI_BAND_5_GHZ; + break; + case BAND_2G: + ui_band = WLAN_HDD_UI_BAND_2_4_GHZ; + break; + default: + hdd_err("Invalid band %d", band); + return -EINVAL; + } + + if (hdd_reg_set_band(net, ui_band)) { + sme_set_phy_mode(hdd_ctx->mac_handle, old_phymode); + return -EIO; + } + + sme_config = qdf_mem_malloc(sizeof(*sme_config)); + if (!sme_config) { + hdd_err("Failed to allocate memory for sme_config"); + return -ENOMEM; + } + sme_get_config_param(hdd_ctx->mac_handle, sme_config); + csr_config = &sme_config->csr_config; + csr_config->phyMode = phymode; +#ifdef QCA_HT_2040_COEX + if (phymode == eCSR_DOT11_MODE_11n && + chwidth == WNI_CFG_CHANNEL_BONDING_MODE_DISABLE) { + csr_config->obssEnabled = false; + status = sme_set_ht2040_mode(hdd_ctx->mac_handle, + adapter->vdev_id, + eHT_CHAN_HT20, false); + if (status == QDF_STATUS_E_FAILURE) { + hdd_err("Failed to disable OBSS"); + ret = -EIO; + goto free; + } + } else if (phymode == eCSR_DOT11_MODE_11n && + chwidth == WNI_CFG_CHANNEL_BONDING_MODE_ENABLE) { + csr_config->obssEnabled = true; + status = sme_set_ht2040_mode(hdd_ctx->mac_handle, + adapter->vdev_id, + eHT_CHAN_HT20, true); + if (status == QDF_STATUS_E_FAILURE) { + hdd_err("Failed to enable OBSS"); + ret = -EIO; + goto free; + } + } +#endif + status = ucfg_mlme_set_band_capability(hdd_ctx->psoc, band); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("failed to set MLME band capability"); + ret = -EIO; + goto free; + } + + if (band == BAND_2G) { + status = ucfg_mlme_set_11h_enabled(hdd_ctx->psoc, 0); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_err("Failed to set 11h_enable flag"); + ret = -EIO; + goto free; + } + } + if (band == BAND_2G) { + csr_config->channelBondingMode24GHz = chwidth; + } else if (band == BAND_5G) { + csr_config->channelBondingMode5GHz = chwidth; + } else { + csr_config->channelBondingMode24GHz = chwidth; + csr_config->channelBondingMode5GHz = chwidth; + } + sme_update_config(hdd_ctx->mac_handle, sme_config); + + hdd_ctx->config->dot11Mode = hdd_dot11mode; + ucfg_mlme_set_channel_bonding_24ghz(hdd_ctx->psoc, + csr_config->channelBondingMode24GHz); + ucfg_mlme_set_channel_bonding_5ghz(hdd_ctx->psoc, + csr_config->channelBondingMode5GHz); + if (hdd_update_config_cfg(hdd_ctx) == false) { + hdd_err("could not update config_dat"); + ret = -EIO; + goto free; + } + + if (band == BAND_ALL || band == BAND_5G) { + struct ieee80211_supported_band *ieee_band; + + ucfg_mlme_get_channel_bonding_5ghz(hdd_ctx->psoc, + &channel_bonding_mode); + ieee_band = hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ]; + if (channel_bonding_mode) + ieee_band->ht_cap.cap |= + IEEE80211_HT_CAP_SUP_WIDTH_20_40; + else + ieee_band->ht_cap.cap &= + ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + } + +free: + if (sme_config) + qdf_mem_free(sme_config); + return ret; +} + #ifdef CONFIG_WLAN_DEBUG_CRASH_INJECT int hdd_crash_inject(struct hdd_adapter *adapter, uint32_t v1, uint32_t v2) { diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 93a26b33554d..9d371601a481 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -3415,342 +3415,128 @@ static int iw_get_wlm_stats(struct net_device *net_dev, } #endif /* FEATURE_WLM_STATS */ -int wlan_hdd_update_phymode(struct hdd_adapter *adapter, int new_phymode) +static eCsrPhyMode hdd_we_ieee_to_phymode(int ieee_mode) { - struct net_device *net = adapter->dev; - struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); - mac_handle_t mac_handle = hdd_ctx->mac_handle; - bool band_24 = false, band_5g = false; - bool ch_bond24 = false, ch_bond5g = false; - struct sme_config_params *sme_config = NULL; - struct csr_config_params *csr_config; - uint32_t chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; - uint8_t vhtchanwidth; - eCsrPhyMode phymode = -EIO, old_phymode; - enum hdd_dot11_mode hdd_dot11mode = hdd_ctx->config->dot11Mode; - enum band_info curr_band = BAND_ALL; - int retval = 0; - uint8_t band_capability; - QDF_STATUS status; - uint32_t channel_bonding_mode; + eCsrPhyMode phymode; - if (!mac_handle) - return -EINVAL; - - old_phymode = sme_get_phy_mode(mac_handle); - - ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc, - &channel_bonding_mode); - if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != - sme_get_cb_phy_state_from_cb_ini_value(channel_bonding_mode)) - ch_bond24 = true; - - ucfg_mlme_get_channel_bonding_5ghz(hdd_ctx->psoc, - &channel_bonding_mode); - if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != - sme_get_cb_phy_state_from_cb_ini_value(channel_bonding_mode)) - ch_bond5g = true; - - status = wlan_mlme_get_band_capability(hdd_ctx->psoc, &band_capability); - if (QDF_IS_STATUS_ERROR(status)) { - hdd_err("Failed to get MLME Band capability"); - return -EIO; - } - - if (band_capability == BAND_ALL) - band_24 = band_5g = true; - else if (band_capability == BAND_2G) - band_24 = true; - else if (band_capability == BAND_5G) - band_5g = true; - - status = ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc, &vhtchanwidth); - if (!QDF_IS_STATUS_SUCCESS(status)) - hdd_err("Failed to get channel_width"); - - hdd_debug("ch_bond24=%d ch_bond5g=%d band_24=%d band_5g=%d VHT_ch_width=%u", - ch_bond24, ch_bond5g, band_24, band_5g, vhtchanwidth); - - switch (new_phymode) { + switch (ieee_mode) { case IEEE80211_MODE_AUTO: - sme_set_phy_mode(mac_handle, eCSR_DOT11_MODE_AUTO); - if (hdd_reg_set_band(net, WLAN_HDD_UI_BAND_AUTO) == 0) { - phymode = eCSR_DOT11_MODE_AUTO; - hdd_dot11mode = eHDD_DOT11_MODE_AUTO; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; - curr_band = BAND_ALL; - vhtchanwidth = eHT_CHANNEL_WIDTH_80MHZ; - } else { - sme_set_phy_mode(mac_handle, old_phymode); - return -EIO; - } + case IEEE80211_MODE_2G_AUTO: + case IEEE80211_MODE_5G_AUTO: + phymode = eCSR_DOT11_MODE_AUTO; break; case IEEE80211_MODE_11A: - sme_set_phy_mode(mac_handle, eCSR_DOT11_MODE_11a); - if (hdd_reg_set_band(net, WLAN_HDD_UI_BAND_5_GHZ) == 0) { - phymode = eCSR_DOT11_MODE_11a; - hdd_dot11mode = eHDD_DOT11_MODE_11a; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; - curr_band = BAND_5G; - } else { - sme_set_phy_mode(mac_handle, old_phymode); - return -EIO; - } + phymode = eCSR_DOT11_MODE_11a; break; case IEEE80211_MODE_11B: - sme_set_phy_mode(mac_handle, eCSR_DOT11_MODE_11b); - if (hdd_reg_set_band(net, WLAN_HDD_UI_BAND_2_4_GHZ) == 0) { - phymode = eCSR_DOT11_MODE_11b; - hdd_dot11mode = eHDD_DOT11_MODE_11b; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; - curr_band = BAND_2G; - } else { - sme_set_phy_mode(mac_handle, old_phymode); - return -EIO; - } + phymode = eCSR_DOT11_MODE_11b; break; case IEEE80211_MODE_11G: - sme_set_phy_mode(mac_handle, eCSR_DOT11_MODE_11g); - if (hdd_reg_set_band(net, WLAN_HDD_UI_BAND_2_4_GHZ) == 0) { - phymode = eCSR_DOT11_MODE_11g; - hdd_dot11mode = eHDD_DOT11_MODE_11g; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; - curr_band = BAND_2G; - } else { - sme_set_phy_mode(mac_handle, old_phymode); - return -EIO; - } + phymode = eCSR_DOT11_MODE_11g; break; - /* UMAC doesn't have option to set MODE_11NA/MODE_11NG as phymode - * so setting phymode as eCSR_DOT11_MODE_11n and updating the band - * and channel bonding in configuration to reflect MODE_11NA/MODE_11NG - */ case IEEE80211_MODE_11NA_HT20: - sme_set_phy_mode(mac_handle, eCSR_DOT11_MODE_11n); - if (hdd_reg_set_band(net, WLAN_HDD_UI_BAND_5_GHZ) == 0) { - phymode = eCSR_DOT11_MODE_11n; - hdd_dot11mode = eHDD_DOT11_MODE_11n; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; - curr_band = BAND_5G; - } else { - sme_set_phy_mode(mac_handle, old_phymode); - return -EIO; - } - break; case IEEE80211_MODE_11NA_HT40: - sme_set_phy_mode(mac_handle, eCSR_DOT11_MODE_11n); - if (hdd_reg_set_band(net, WLAN_HDD_UI_BAND_5_GHZ) == 0) { - phymode = eCSR_DOT11_MODE_11n; - hdd_dot11mode = eHDD_DOT11_MODE_11n; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; - curr_band = BAND_5G; - } else { - sme_set_phy_mode(mac_handle, old_phymode); - return -EIO; - } - break; case IEEE80211_MODE_11NG_HT20: - sme_set_phy_mode(mac_handle, eCSR_DOT11_MODE_11n); - if (hdd_reg_set_band(net, WLAN_HDD_UI_BAND_2_4_GHZ) == 0) { - phymode = eCSR_DOT11_MODE_11n; - hdd_dot11mode = eHDD_DOT11_MODE_11n; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; - curr_band = BAND_2G; - } else { - sme_set_phy_mode(mac_handle, old_phymode); - return -EIO; - } - break; case IEEE80211_MODE_11NG_HT40: - sme_set_phy_mode(mac_handle, eCSR_DOT11_MODE_11n); - if (hdd_reg_set_band(net, WLAN_HDD_UI_BAND_2_4_GHZ) == 0) { - phymode = eCSR_DOT11_MODE_11n; - hdd_dot11mode = eHDD_DOT11_MODE_11n; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; - curr_band = BAND_2G; - } else { - sme_set_phy_mode(mac_handle, old_phymode); - return -EIO; - } + case IEEE80211_MODE_11AGN: + phymode = eCSR_DOT11_MODE_11n; break; case IEEE80211_MODE_11AC_VHT20: case IEEE80211_MODE_11AC_VHT40: case IEEE80211_MODE_11AC_VHT80: - sme_set_phy_mode(mac_handle, eCSR_DOT11_MODE_11ac); phymode = eCSR_DOT11_MODE_11ac; - hdd_dot11mode = eHDD_DOT11_MODE_11ac; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; - if (band_5g && band_24) { - curr_band = BAND_ALL; - break; - } else if (band_5g) { - curr_band = BAND_5G; - break; - } else if (new_phymode != IEEE80211_MODE_11AC_VHT80) { - curr_band = BAND_2G; - break; - } - if (hdd_reg_set_band(net, WLAN_HDD_UI_BAND_AUTO) == 0) { - curr_band = BAND_ALL; - } else { - sme_set_phy_mode(mac_handle, old_phymode); - return -EIO; - } - break; - case IEEE80211_MODE_2G_AUTO: - sme_set_phy_mode(mac_handle, eCSR_DOT11_MODE_AUTO); - if (hdd_reg_set_band(net, WLAN_HDD_UI_BAND_2_4_GHZ) == 0) { - phymode = eCSR_DOT11_MODE_AUTO; - hdd_dot11mode = eHDD_DOT11_MODE_AUTO; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; - curr_band = BAND_2G; - } else { - sme_set_phy_mode(mac_handle, old_phymode); - return -EIO; - } - break; - case IEEE80211_MODE_5G_AUTO: - sme_set_phy_mode(mac_handle, eCSR_DOT11_MODE_AUTO); - if (hdd_reg_set_band(net, WLAN_HDD_UI_BAND_5_GHZ) == 0) { - phymode = eCSR_DOT11_MODE_AUTO; - hdd_dot11mode = eHDD_DOT11_MODE_AUTO; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; - vhtchanwidth = eHT_CHANNEL_WIDTH_80MHZ; - curr_band = BAND_5G; - } else { - sme_set_phy_mode(mac_handle, old_phymode); - return -EIO; - } - break; - case IEEE80211_MODE_11AGN: - sme_set_phy_mode(mac_handle, eCSR_DOT11_MODE_11n); - if (hdd_reg_set_band(net, WLAN_HDD_UI_BAND_AUTO) == 0) { - phymode = eCSR_DOT11_MODE_11n; - hdd_dot11mode = eHDD_DOT11_MODE_11n; - chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; - curr_band = BAND_ALL; - } else { - sme_set_phy_mode(mac_handle, old_phymode); - return -EIO; - } break; default: - return -EIO; + hdd_err("Not supported mode %d", ieee_mode); + phymode = -EINVAL; } - switch (new_phymode) { + return phymode; +} + +static enum band_info hdd_we_ieee_to_band(int ieee_mode) +{ + enum band_info band; + + switch (ieee_mode) { + case IEEE80211_MODE_AUTO: + case IEEE80211_MODE_11AC_VHT20: + case IEEE80211_MODE_11AC_VHT40: + case IEEE80211_MODE_11AC_VHT80: + case IEEE80211_MODE_11AGN: + band = BAND_ALL; + break; + case IEEE80211_MODE_11A: + case IEEE80211_MODE_11NA_HT20: + case IEEE80211_MODE_11NA_HT40: + case IEEE80211_MODE_5G_AUTO: + band = BAND_5G; + break; + case IEEE80211_MODE_11B: + case IEEE80211_MODE_11G: + case IEEE80211_MODE_11NG_HT20: + case IEEE80211_MODE_11NG_HT40: + case IEEE80211_MODE_2G_AUTO: + band = BAND_2G; + break; + default: + hdd_err("Not supported mode %d", ieee_mode); + band = -EINVAL; + } + + return band; +} + +static uint32_t hdd_we_ieee_to_chwidth(int ieee_mode) +{ + uint32_t chwidth; + + switch (ieee_mode) { + case IEEE80211_MODE_AUTO: + case IEEE80211_MODE_11NA_HT40: + case IEEE80211_MODE_11NG_HT40: + case IEEE80211_MODE_11AC_VHT40: + case IEEE80211_MODE_11AC_VHT80: + case IEEE80211_MODE_2G_AUTO: + case IEEE80211_MODE_5G_AUTO: + case IEEE80211_MODE_11AGN: + chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; + break; + case IEEE80211_MODE_11A: + case IEEE80211_MODE_11B: + case IEEE80211_MODE_11G: + case IEEE80211_MODE_11NA_HT20: + case IEEE80211_MODE_11NG_HT20: case IEEE80211_MODE_11AC_VHT20: chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; - vhtchanwidth = eHT_CHANNEL_WIDTH_20MHZ; - break; - case IEEE80211_MODE_11AC_VHT40: - vhtchanwidth = eHT_CHANNEL_WIDTH_40MHZ; - break; - case IEEE80211_MODE_11AC_VHT80: - vhtchanwidth = eHT_CHANNEL_WIDTH_80MHZ; break; default: - status = ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc, - &vhtchanwidth); - if (!QDF_IS_STATUS_SUCCESS(status)) - hdd_err("Failed to get channel_width"); - break; + hdd_err("Not supported mode %d", ieee_mode); + chwidth = -EINVAL; } - if (phymode != -EIO) { - sme_config = qdf_mem_malloc(sizeof(*sme_config)); - if (!sme_config) { - hdd_err("Failed to allocate memory for sme_config"); - return -ENOMEM; - } - qdf_mem_zero(sme_config, sizeof(*sme_config)); - sme_get_config_param(mac_handle, sme_config); - csr_config = &sme_config->csr_config; - csr_config->phyMode = phymode; -#ifdef QCA_HT_2040_COEX - if (phymode == eCSR_DOT11_MODE_11n && - chwidth == WNI_CFG_CHANNEL_BONDING_MODE_DISABLE) { - csr_config->obssEnabled = false; - status = sme_set_ht2040_mode(mac_handle, - adapter->vdev_id, - eHT_CHAN_HT20, false); - if (status == QDF_STATUS_E_FAILURE) { - hdd_err("Failed to disable OBSS"); - retval = -EIO; - goto free; - } - } else if (phymode == eCSR_DOT11_MODE_11n && - chwidth == WNI_CFG_CHANNEL_BONDING_MODE_ENABLE) { - csr_config->obssEnabled = true; - status = sme_set_ht2040_mode(mac_handle, - adapter->vdev_id, - eHT_CHAN_HT20, true); - if (status == QDF_STATUS_E_FAILURE) { - hdd_err("Failed to enable OBSS"); - retval = -EIO; - goto free; - } - } -#endif - status = ucfg_mlme_set_band_capability(hdd_ctx->psoc, - curr_band); - if (QDF_IS_STATUS_ERROR(status)) { - hdd_err("failed to set MLME band capability"); - goto free; - } + return chwidth; +} - if (curr_band == BAND_2G) { - status = ucfg_mlme_set_11h_enabled(hdd_ctx->psoc, 0); - if (!QDF_IS_STATUS_SUCCESS(status)) { - hdd_err("Failed to set 11h_enable flag"); - goto free; - } - } - if (curr_band == BAND_2G) - csr_config->channelBondingMode24GHz = chwidth; - else if (curr_band == BAND_5G) - csr_config->channelBondingMode5GHz = chwidth; - else { - csr_config->channelBondingMode24GHz = chwidth; - csr_config->channelBondingMode5GHz = chwidth; - } - sme_update_config(mac_handle, sme_config); +int hdd_we_update_phymode(struct hdd_adapter *adapter, int new_phymode) +{ + eCsrPhyMode phymode; + enum band_info band; + uint32_t chwidth; - hdd_ctx->config->dot11Mode = hdd_dot11mode; - ucfg_mlme_set_channel_bonding_24ghz( - hdd_ctx->psoc, - csr_config->channelBondingMode24GHz); - ucfg_mlme_set_channel_bonding_5ghz( - hdd_ctx->psoc, - csr_config->channelBondingMode5GHz); - if (hdd_update_config_cfg(hdd_ctx) == false) { - hdd_err("could not update config_dat"); - retval = -EIO; - goto free; - } + phymode = hdd_we_ieee_to_phymode(new_phymode); + if (phymode < 0) + return -EINVAL; - if (band_5g) { - struct ieee80211_supported_band *band; + band = hdd_we_ieee_to_band(new_phymode); + if (band < 0) + return -EINVAL; - ucfg_mlme_get_channel_bonding_5ghz( - hdd_ctx->psoc, &channel_bonding_mode); - band = hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ]; - if (channel_bonding_mode) - band->ht_cap.cap |= - IEEE80211_HT_CAP_SUP_WIDTH_20_40; - else - band->ht_cap.cap &= - ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - } + chwidth = hdd_we_ieee_to_chwidth(new_phymode); + if (chwidth < 0) + return -EINVAL; - hdd_debug("New_Phymode= %d ch_bonding=%d band=%d VHT_ch_width=%u", - phymode, chwidth, curr_band, vhtchanwidth); - } - -free: - if (sme_config) - qdf_mem_free(sme_config); - return retval; + return hdd_update_phymode(adapter, phymode, band, chwidth); } static int hdd_validate_pdev_reset(int value) @@ -5155,7 +4941,7 @@ static const setint_getnone_fn setint_getnone_cb[] = { [WE_SET_HASTINGS_BT_WAR] = hdd_we_set_hastings_bt_war, #endif [WE_SET_TM_LEVEL] = hdd_we_set_tm_level, - [WE_SET_PHYMODE] = wlan_hdd_update_phymode, + [WE_SET_PHYMODE] = hdd_we_update_phymode, [WE_SET_NSS] = hdd_we_set_nss, [WE_SET_GTX_HT_MCS] = hdd_we_set_gtx_ht_mcs, [WE_SET_GTX_VHT_MCS] = hdd_we_set_gtx_vht_mcs,