Explorar o código

qcacld-3.0: Set Wi-Fi configurations - PHY_MODE

Add attributes in SET_WIFI_CONFIGURATION to dynamically
configure capabilities - PHY_MODE.

Change-Id: I3085cfed5b188d2ccba87a4b47ac597ebbbec76e
CRs-Fixed: 2694250
Min Liu %!s(int64=4) %!d(string=hai) anos
pai
achega
22bc5b94d3

+ 17 - 0
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) */

+ 3 - 2
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

+ 188 - 0
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

+ 1 - 1
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:

+ 171 - 0
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)
 {

+ 85 - 299
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;
-
-	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;
+	eCsrPhyMode phymode;
 
-	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;
-		}
+	default:
+		hdd_err("Not supported mode %d", ieee_mode);
+		phymode = -EINVAL;
+	}
+
+	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:
-		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;
-		}
+		band = BAND_5G;
 		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;
-		}
+	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:
-		return -EIO;
+		hdd_err("Not supported mode %d", ieee_mode);
+		band = -EINVAL;
 	}
 
-	switch (new_phymode) {
-	case IEEE80211_MODE_11AC_VHT20:
-		chwidth = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
-		vhtchanwidth = eHT_CHANNEL_WIDTH_20MHZ;
-		break;
+	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:
-		vhtchanwidth = eHT_CHANNEL_WIDTH_40MHZ;
-		break;
 	case IEEE80211_MODE_11AC_VHT80:
-		vhtchanwidth = eHT_CHANNEL_WIDTH_80MHZ;
+	case IEEE80211_MODE_2G_AUTO:
+	case IEEE80211_MODE_5G_AUTO:
+	case IEEE80211_MODE_11AGN:
+		chwidth = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE;
 		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");
+	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;
 		break;
+	default:
+		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;
-
-			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;
-		}
+	band = hdd_we_ieee_to_band(new_phymode);
+	if (band < 0)
+		return -EINVAL;
 
-		hdd_debug("New_Phymode= %d ch_bonding=%d band=%d VHT_ch_width=%u",
-			phymode, chwidth, curr_band, vhtchanwidth);
-	}
+	chwidth = hdd_we_ieee_to_chwidth(new_phymode);
+	if (chwidth < 0)
+		return -EINVAL;
 
-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,