Browse Source

qcacld-3.0: Fix UL TPUT issue when connected to 160MHz AP

This is qcacld-2.0 to qcacld-3.0 propagation

When STA is connected to 160MHz AP, channel width is updated to
20MHz since the 160MHz channel width is not handled.
Add support to handle the 160MHz BW in beacon IEs.

Change-Id: Id13164762d6da142093f049121440ce976cecfc1
CRs-Fixed: 924219
Naveen Rawat 9 years ago
parent
commit
c0c91cd58c

+ 16 - 7
core/mac/src/pe/lim/lim_assoc_utils.c

@@ -4033,11 +4033,14 @@ tSirRetStatus lim_sta_send_add_bss(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp,
 				lim_log(pMac, LOG1, FL(
 					"VHT Op IE is in vendor Specfic IE"));
 			}
-			if ((vht_oper != NULL) &&
-					pAddBssParams->staContext.vhtCapable &&
-					vht_oper->chanWidth)
-				pAddBssParams->staContext.ch_width =
-					vht_oper->chanWidth + 1;
+			/*
+			 * in limExtractApCapability function intersection of FW
+			 * advertised channel width and AP advertised channel
+			 * width has been taken into account for calculating
+			 * psessionEntry->ch_width
+			 */
+			pAddBssParams->staContext.ch_width =
+					psessionEntry->ch_width;
 
 			lim_log(pMac, LOGE, FL(
 					"StaCtx: vhtCap %d ChBW %d TxBF %d"),
@@ -4480,13 +4483,19 @@ tSirRetStatus lim_sta_send_add_bss_pre_assoc(tpAniSirGlobal pMac, uint8_t update
 		if ((vht_oper != NULL) &&
 			vht_oper->chanWidth &&
 			chanWidthSupp) {
-			pAddBssParams->ch_width =
-				vht_oper->chanWidth + 1;
 			pAddBssParams->ch_center_freq_seg0 =
 				vht_oper->chanCenterFreqSeg1;
 			pAddBssParams->ch_center_freq_seg1 =
 				vht_oper->chanCenterFreqSeg2;
 		}
+		/*
+		 * in limExtractApCapability function intersection of FW
+		 * advertised channel width and AP advertised channel width has
+		 * been taken into account for calculating
+		 * psessionEntry->ch_width
+		 */
+		pAddBssParams->ch_width =
+			psessionEntry->ch_width;
 		pAddBssParams->staContext.maxAmpduSize =
 			SIR_MAC_GET_VHT_MAX_AMPDU_EXPO(
 					pAddBssParams->staContext.vht_caps);

+ 23 - 8
core/mac/src/pe/lim/lim_process_action_frame.c

@@ -58,7 +58,7 @@
 #include "lim_session_utils.h"
 #include "cds_concurrency.h"
 #include "wma_types.h"
-
+#include "wma.h"
 
 #define BA_DEFAULT_TX_BUFFER_SIZE 64
 
@@ -466,6 +466,8 @@ static void __lim_process_operating_mode_action_frame(tpAniSirGlobal mac_ctx,
 	uint16_t aid;
 	uint8_t oper_mode;
 	uint8_t cb_mode;
+	uint8_t ch_bw = 0;
+	uint8_t skip_opmode_update = false;
 
 	mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
 	body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
@@ -514,7 +516,16 @@ static void __lim_process_operating_mode_action_frame(tpAniSirGlobal mac_ctx,
 	} else {
 		oper_mode = eHT_CHANNEL_WIDTH_20MHZ;
 	}
-	if (oper_mode != operating_mode_frm->OperatingMode.chanWidth) {
+
+	if ((oper_mode == eHT_CHANNEL_WIDTH_80MHZ) &&
+			(operating_mode_frm->OperatingMode.chanWidth >
+				eHT_CHANNEL_WIDTH_80MHZ))
+		skip_opmode_update = true;
+
+	if (!skip_opmode_update && (oper_mode !=
+		operating_mode_frm->OperatingMode.chanWidth)) {
+		uint32_t fw_vht_ch_wd = wma_get_vht_ch_width();
+
 		lim_log(mac_ctx, LOGE,
 			FL(" received Chanwidth %d, staIdx = %d"),
 			(operating_mode_frm->OperatingMode.chanWidth),
@@ -525,34 +536,38 @@ static void __lim_process_operating_mode_action_frame(tpAniSirGlobal mac_ctx,
 			mac_hdr->sa[0], mac_hdr->sa[1], mac_hdr->sa[2],
 			mac_hdr->sa[3], mac_hdr->sa[4], mac_hdr->sa[5]);
 
-		if (operating_mode_frm->OperatingMode.chanWidth ==
-				eHT_CHANNEL_WIDTH_160MHZ) {
+		if (operating_mode_frm->OperatingMode.chanWidth >=
+				eHT_CHANNEL_WIDTH_160MHZ
+				&& (fw_vht_ch_wd >= eHT_CHANNEL_WIDTH_160MHZ)) {
 			sta_ptr->vhtSupportedChannelWidthSet =
 				WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
 			sta_ptr->htSupportedChannelWidthSet =
 				eHT_CHANNEL_WIDTH_40MHZ;
-		} else if (operating_mode_frm->OperatingMode.chanWidth ==
+			ch_bw = eHT_CHANNEL_WIDTH_160MHZ;
+		} else if (operating_mode_frm->OperatingMode.chanWidth >=
 				eHT_CHANNEL_WIDTH_80MHZ) {
 			sta_ptr->vhtSupportedChannelWidthSet =
 				WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
 			sta_ptr->htSupportedChannelWidthSet =
 				eHT_CHANNEL_WIDTH_40MHZ;
+			ch_bw = eHT_CHANNEL_WIDTH_80MHZ;
 		} else if (operating_mode_frm->OperatingMode.chanWidth ==
 				eHT_CHANNEL_WIDTH_40MHZ) {
 			sta_ptr->vhtSupportedChannelWidthSet =
 				WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
 			sta_ptr->htSupportedChannelWidthSet =
 				eHT_CHANNEL_WIDTH_40MHZ;
+			ch_bw = eHT_CHANNEL_WIDTH_40MHZ;
 		} else if (operating_mode_frm->OperatingMode.chanWidth ==
 				eHT_CHANNEL_WIDTH_20MHZ) {
 			sta_ptr->vhtSupportedChannelWidthSet =
 				WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
 			sta_ptr->htSupportedChannelWidthSet =
 				eHT_CHANNEL_WIDTH_20MHZ;
+			ch_bw = eHT_CHANNEL_WIDTH_20MHZ;
 		}
-		lim_check_vht_op_mode_change(mac_ctx, session,
-			operating_mode_frm->OperatingMode.chanWidth,
-			sta_ptr->staIndex, mac_hdr->sa);
+		lim_check_vht_op_mode_change(mac_ctx, session, ch_bw,
+					     sta_ptr->staIndex, mac_hdr->sa);
 	}
 
 	if (sta_ptr->vhtSupportedRxNss !=

+ 25 - 6
core/mac/src/pe/lim/lim_prop_exts_utils.c

@@ -55,6 +55,8 @@
 #include "lim_ft_defs.h"
 #endif
 #include "lim_session.h"
+#include "wma.h"
+
 #define LIM_GET_NOISE_MAX_TRY 5
 /**
  * lim_extract_ap_capability() - extract AP's HCF/WME/WSM capability
@@ -140,6 +142,7 @@ lim_extract_ap_capability(tpAniSirGlobal mac_ctx, uint8_t *p_ie,
 		} else {
 			session->vhtCapabilityPresentInBeacon = 0;
 		}
+
 		if (session->vhtCapabilityPresentInBeacon == 1 &&
 		    session->txBFIniFeatureEnabled == 0) {
 			cfg_set_status = cfg_set_int(mac_ctx,
@@ -159,12 +162,28 @@ lim_extract_ap_capability(tpAniSirGlobal mac_ctx, uint8_t *p_ie,
 				session->txBFIniFeatureEnabled = 0;
 		} else if (session->vhtCapabilityPresentInBeacon == 1 &&
 			   beacon_struct->VHTOperation.chanWidth) {
-			session->ch_center_freq_seg0 =
-				beacon_struct->VHTOperation.chanCenterFreqSeg1;
-			session->ch_center_freq_seg1 =
-				beacon_struct->VHTOperation.chanCenterFreqSeg2;
-			session->ch_width =
-				beacon_struct->VHTOperation.chanWidth + 1;
+			/* If VHT is supported min 80 MHz support is must */
+			uint32_t fw_vht_ch_wd = wma_get_vht_ch_width();
+			uint32_t vht_ch_wd = CDF_MIN(fw_vht_ch_wd,
+					beacon_struct->VHTOperation.chanWidth);
+			if (vht_ch_wd == beacon_struct->VHTOperation.chanWidth
+			    || vht_ch_wd >= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) {
+				/*
+				 * This block covers 2 cases:
+				 * 1) AP and STA both have same vht capab
+				 * 2) AP is 160 (80+80), we are 160 only
+				 */
+				session->ch_center_freq_seg0 =
+				 beacon_struct->VHTOperation.chanCenterFreqSeg1;
+				session->ch_center_freq_seg1 =
+				 beacon_struct->VHTOperation.chanCenterFreqSeg2;
+			} else {
+				/* when AP was 160 but we were 80 only */
+				session->ch_center_freq_seg0 =
+					lim_get_80Mhz_center_channel(
+						beacon_struct->channelNumber);
+			}
+			session->ch_width = vht_ch_wd + 1;
 			if (CH_WIDTH_80MHZ < session->ch_width) {
 				session->enable_su_tx_bformer = 0;
 				session->nss = 1;

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

@@ -7143,3 +7143,33 @@ void lim_merge_extcap_struct(tDot11fIEExtCap *dst,
 	}
 }
 
+/**
+ * lim_get_80Mhz_center_channel - finds 80 Mhz center channel
+ *
+ * @primary_channel:   Primary channel for given 80 MHz band
+ *
+ * There are fixed 80MHz band and for each fixed band there is only one center
+ * valid channel. Also location of primary channel decides what 80 MHz band will
+ * it use, hence it decides what center channel will be used. This function
+ * does thus calculation and returns the center channel.
+ *
+ * Return: center channel
+ */
+uint8_t
+lim_get_80Mhz_center_channel(uint8_t primary_channel)
+{
+	if (primary_channel >= 36 && primary_channel <= 48)
+		return (36+48)/2;
+	if (primary_channel >= 52 && primary_channel <= 64)
+		return (52+64)/2;
+	if (primary_channel >= 100 && primary_channel <= 112)
+		return (100+112)/2;
+	if (primary_channel >= 116 && primary_channel <= 128)
+		return (116+128)/2;
+	if (primary_channel >= 132 && primary_channel <= 144)
+		return (132+144)/2;
+	if (primary_channel >= 149 && primary_channel <= 161)
+		return (149+161)/2;
+
+	return INVALID_CHANNEL_ID;
+}

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

@@ -588,4 +588,5 @@ tSirRetStatus lim_strip_extcap_update_struct(tpAniSirGlobal mac_ctx,
 		uint8_t *addn_ie, uint16_t *addn_ielen, tDot11fIEExtCap *dst);
 void lim_merge_extcap_struct(tDot11fIEExtCap *dst, tDot11fIEExtCap *src);
 
+uint8_t lim_get_80Mhz_center_channel(uint8_t primary_channel);
 #endif /* __LIM_UTILS_H */

+ 101 - 92
core/mac/src/pe/sch/sch_beacon_process.c

@@ -58,6 +58,7 @@
 #include "host_diag_core_log.h"
 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
 
+#include "wma.h"
 /**
  * Number of bytes of variation in beacon length from the last beacon
  * to trigger reprogramming of rx delay register
@@ -529,6 +530,8 @@ sch_bcn_process_sta_bt_amp_sta_ibss(tpAniSirGlobal mac_ctx,
 	uint8_t operMode;
 	uint8_t chWidth = 0;
 	uint8_t cb_mode;
+	uint32_t fw_vht_ch_wd = wma_get_vht_ch_width();
+	bool skip_opmode_update = false;
 
 	if (RF_CHAN_14 >= session->currentOperChannel)
 		cb_mode = mac_ctx->roam.configParam.channelBondingMode24GHz;
@@ -545,55 +548,63 @@ sch_bcn_process_sta_bt_amp_sta_ibss(tpAniSirGlobal mac_ctx,
 
 	if (session->vhtCapability && bcn->OperatingMode.present) {
 		operMode = get_operating_channel_width(pStaDs);
-		if (operMode == bcn->OperatingMode.chanWidth)
-			return;
-
-		PELOGE(sch_log(mac_ctx, LOGE,
-		       FL("received OpMode Chanwidth %d, staIdx = %d"),
-		       bcn->OperatingMode.chanWidth, pStaDs->staIndex);)
-		PELOGE(sch_log(mac_ctx, LOGE,
-		       FL("MAC - %0x:%0x:%0x:%0x:%0x:%0x"),
-		       pMh->sa[0], pMh->sa[1],
-		       pMh->sa[2], pMh->sa[3],
-		       pMh->sa[4], pMh->sa[5]);)
+		if ((operMode == eHT_CHANNEL_WIDTH_80MHZ) &&
+		    (bcn->OperatingMode.chanWidth > eHT_CHANNEL_WIDTH_80MHZ))
+			skip_opmode_update = true;
 
-		if (bcn->OperatingMode.chanWidth ==
-			eHT_CHANNEL_WIDTH_160MHZ) {
+		if (!skip_opmode_update &&
+		    (operMode != bcn->OperatingMode.chanWidth)) {
 			PELOGE(sch_log(mac_ctx, LOGE,
-			       FL("Updating the CH Width to 160MHz"));)
-			pStaDs->vhtSupportedChannelWidthSet =
-				WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
-			pStaDs->htSupportedChannelWidthSet =
-				eHT_CHANNEL_WIDTH_40MHZ;
-		} else if (bcn->OperatingMode.chanWidth ==
-			eHT_CHANNEL_WIDTH_80MHZ) {
+			       FL("received OpMode Chanwidth %d, staIdx = %d"),
+			       bcn->OperatingMode.chanWidth, pStaDs->staIndex);)
 			PELOGE(sch_log(mac_ctx, LOGE,
-			       FL("Updating the CH Width to 80MHz"));)
-			pStaDs->vhtSupportedChannelWidthSet =
-				WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
-			pStaDs->htSupportedChannelWidthSet =
-				eHT_CHANNEL_WIDTH_40MHZ;
-		} else if (bcn->OperatingMode.chanWidth ==
-			eHT_CHANNEL_WIDTH_40MHZ) {
-			PELOGE(sch_log(mac_ctx, LOGE,
-			       FL("Updating the CH Width to 40MHz"));)
-			pStaDs->vhtSupportedChannelWidthSet =
-				WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
-			pStaDs->htSupportedChannelWidthSet =
-				eHT_CHANNEL_WIDTH_40MHZ;
-		} else if (bcn->OperatingMode.chanWidth ==
-			eHT_CHANNEL_WIDTH_20MHZ) {
-			PELOGE(sch_log(mac_ctx, LOGE,
-			       FL("Updating the CH Width to 20MHz"));)
-			pStaDs->vhtSupportedChannelWidthSet =
-				WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
-			pStaDs->htSupportedChannelWidthSet =
-				eHT_CHANNEL_WIDTH_20MHZ;
+			       FL("MAC - %0x:%0x:%0x:%0x:%0x:%0x"),
+			       pMh->sa[0], pMh->sa[1],
+			       pMh->sa[2], pMh->sa[3],
+			       pMh->sa[4], pMh->sa[5]);)
+
+			if ((bcn->OperatingMode.chanWidth >=
+				eHT_CHANNEL_WIDTH_160MHZ) &&
+				(fw_vht_ch_wd > eHT_CHANNEL_WIDTH_80MHZ)) {
+				PELOGE(sch_log(mac_ctx, LOGE,
+				       FL("Updating the CH Width to 160MHz"));)
+				pStaDs->vhtSupportedChannelWidthSet =
+					WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
+				pStaDs->htSupportedChannelWidthSet =
+					eHT_CHANNEL_WIDTH_40MHZ;
+				chWidth = eHT_CHANNEL_WIDTH_160MHZ;
+			} else if (bcn->OperatingMode.chanWidth >=
+				eHT_CHANNEL_WIDTH_80MHZ) {
+				PELOGE(sch_log(mac_ctx, LOGE,
+				       FL("Updating the CH Width to 80MHz"));)
+				pStaDs->vhtSupportedChannelWidthSet =
+					WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
+				pStaDs->htSupportedChannelWidthSet =
+					eHT_CHANNEL_WIDTH_40MHZ;
+				chWidth = eHT_CHANNEL_WIDTH_80MHZ;
+			} else if (bcn->OperatingMode.chanWidth ==
+				eHT_CHANNEL_WIDTH_40MHZ) {
+				PELOGE(sch_log(mac_ctx, LOGE,
+				       FL("Updating the CH Width to 40MHz"));)
+				pStaDs->vhtSupportedChannelWidthSet =
+					WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
+				pStaDs->htSupportedChannelWidthSet =
+					eHT_CHANNEL_WIDTH_40MHZ;
+				chWidth = eHT_CHANNEL_WIDTH_40MHZ;
+			} else if (bcn->OperatingMode.chanWidth ==
+				eHT_CHANNEL_WIDTH_20MHZ) {
+				PELOGE(sch_log(mac_ctx, LOGE,
+				       FL("Updating the CH Width to 20MHz"));)
+				pStaDs->vhtSupportedChannelWidthSet =
+					WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
+				pStaDs->htSupportedChannelWidthSet =
+					eHT_CHANNEL_WIDTH_20MHZ;
+				chWidth = eHT_CHANNEL_WIDTH_20MHZ;
+			}
+			lim_check_vht_op_mode_change(mac_ctx, session,
+					chWidth, pStaDs->staIndex, pMh->sa);
+			update_nss(mac_ctx, pStaDs, bcn, session, pMh);
 		}
-		lim_check_vht_op_mode_change(mac_ctx, session,
-				bcn->OperatingMode.chanWidth,
-				pStaDs->staIndex, pMh->sa);
-		update_nss(mac_ctx, pStaDs, bcn, session, pMh);
 		return;
 	}
 
@@ -601,63 +612,61 @@ sch_bcn_process_sta_bt_amp_sta_ibss(tpAniSirGlobal mac_ctx,
 		return;
 
 	operMode = pStaDs->vhtSupportedChannelWidthSet;
-	if (operMode == bcn->VHTOperation.chanWidth)
-		return;
+	if ((operMode == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) &&
+	    (operMode < bcn->VHTOperation.chanWidth))
+		skip_opmode_update = true;
 
-	PELOGE(sch_log(mac_ctx, LOGE,
-	       FL("received VHTOP CHWidth %d staIdx = %d"),
-	       bcn->VHTOperation.chanWidth, pStaDs->staIndex);)
-	PELOGE(sch_log(mac_ctx, LOGE,
-	       FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"),
-	       pMh->sa[0], pMh->sa[1],
-	       pMh->sa[2], pMh->sa[3],
-	       pMh->sa[4], pMh->sa[5]);)
-
-	if (bcn->VHTOperation.chanWidth ==
-		WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) {
-		PELOGE(sch_log(mac_ctx, LOGE,
-			FL("Updating the CH Width to 160MHz"));)
-		pStaDs->vhtSupportedChannelWidthSet =
-			WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
-		pStaDs->htSupportedChannelWidthSet =
-			eHT_CHANNEL_WIDTH_40MHZ;
-		chWidth = eHT_CHANNEL_WIDTH_160MHZ;
-	} else if (bcn->VHTOperation.chanWidth ==
-		WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ) {
+	if (!skip_opmode_update &&
+	    (operMode != bcn->VHTOperation.chanWidth)) {
 		PELOGE(sch_log(mac_ctx, LOGE,
-		       FL("Updating the CH Width to 160MHz"));)
-		pStaDs->vhtSupportedChannelWidthSet =
-			WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
-		pStaDs->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ;
-		chWidth = eHT_CHANNEL_WIDTH_160MHZ;
-	} else if (bcn->VHTOperation.chanWidth ==
-		WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) {
+		       FL("received VHTOP CHWidth %d staIdx = %d"),
+		       bcn->VHTOperation.chanWidth, pStaDs->staIndex);)
 		PELOGE(sch_log(mac_ctx, LOGE,
-		       FL("Updating the CH Width to 80MHz"));)
-		pStaDs->vhtSupportedChannelWidthSet =
-			WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
-		pStaDs->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ;
-		chWidth = eHT_CHANNEL_WIDTH_80MHZ;
-	} else if (bcn->VHTOperation.chanWidth ==
-		WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) {
-		pStaDs->vhtSupportedChannelWidthSet =
-			WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
-		if (bcn->HTCaps.supportedChannelWidthSet) {
+		       FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"),
+		       pMh->sa[0], pMh->sa[1],
+		       pMh->sa[2], pMh->sa[3],
+		       pMh->sa[4], pMh->sa[5]);)
+
+		if ((bcn->VHTOperation.chanWidth >=
+			WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) &&
+			(fw_vht_ch_wd > eHT_CHANNEL_WIDTH_80MHZ)) {
 			PELOGE(sch_log(mac_ctx, LOGE,
-			       FL("Updating the CH Width to 40MHz"));)
+				FL("Updating the CH Width to 160MHz"));)
+			pStaDs->vhtSupportedChannelWidthSet =
+				bcn->VHTOperation.chanWidth;
 			pStaDs->htSupportedChannelWidthSet =
 				eHT_CHANNEL_WIDTH_40MHZ;
-			chWidth = eHT_CHANNEL_WIDTH_40MHZ;
-		} else {
+			chWidth = eHT_CHANNEL_WIDTH_160MHZ;
+		} else if (bcn->VHTOperation.chanWidth >=
+			WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) {
 			PELOGE(sch_log(mac_ctx, LOGE,
-			       FL("Updating the CH Width to 20MHz"));)
+			       FL("Updating the CH Width to 80MHz"));)
+			pStaDs->vhtSupportedChannelWidthSet =
+				WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
 			pStaDs->htSupportedChannelWidthSet =
-				eHT_CHANNEL_WIDTH_20MHZ;
-			chWidth = eHT_CHANNEL_WIDTH_20MHZ;
+				eHT_CHANNEL_WIDTH_40MHZ;
+			chWidth = eHT_CHANNEL_WIDTH_80MHZ;
+		} else if (bcn->VHTOperation.chanWidth ==
+			WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) {
+			pStaDs->vhtSupportedChannelWidthSet =
+				WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
+			if (bcn->HTCaps.supportedChannelWidthSet) {
+				PELOGE(sch_log(mac_ctx, LOGE,
+				       FL("Updating the CH Width to 40MHz"));)
+				pStaDs->htSupportedChannelWidthSet =
+					eHT_CHANNEL_WIDTH_40MHZ;
+				chWidth = eHT_CHANNEL_WIDTH_40MHZ;
+			} else {
+				PELOGE(sch_log(mac_ctx, LOGE,
+				       FL("Updating the CH Width to 20MHz"));)
+				pStaDs->htSupportedChannelWidthSet =
+					eHT_CHANNEL_WIDTH_20MHZ;
+				chWidth = eHT_CHANNEL_WIDTH_20MHZ;
+			}
 		}
+		lim_check_vht_op_mode_change(mac_ctx, session, chWidth,
+						pStaDs->staIndex, pMh->sa);
 	}
-	lim_check_vht_op_mode_change(mac_ctx, session, chWidth,
-					pStaDs->staIndex, pMh->sa);
 	return;
 }
 

+ 1 - 0
core/wma/inc/wma.h

@@ -2000,6 +2000,7 @@ void wmi_desc_put(tp_wma_handle wma_handle, struct wmi_desc_t *wmi_desc);
 int wma_mgmt_tx_completion_handler(void *handle, uint8_t *cmpl_event_params,
 				   uint32_t len);
 void wma_set_dfs_region(tp_wma_handle wma, uint8_t dfs_region);
+uint32_t wma_get_vht_ch_width(void);
 
 #if defined(FEATURE_LRO)
 CDF_STATUS wma_lro_config_cmd(tp_wma_handle wma_handle,

+ 25 - 0
core/wma/src/wma_utils.c

@@ -70,6 +70,8 @@
 #include "wma_internal.h"
 #include "cds_concurrency.h"
 
+#include "linux/ieee80211.h"
+
 /* MCS Based rate table */
 /* HT MCS parameters with Nss = 1 */
 static struct index_data_rate_type supported_mcs_rate_nss1[] = {
@@ -3604,3 +3606,26 @@ bool wma_is_scan_simultaneous_capable(void)
 
 	return false;
 }
+
+/**
+ * wma_get_vht_ch_width - return vht channel width
+ *
+ * Return: return vht channel width
+ */
+uint32_t wma_get_vht_ch_width(void)
+{
+	uint32_t fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
+	tp_wma_handle wm_hdl = cds_get_context(CDF_MODULE_ID_WMA);
+
+	if (NULL == wm_hdl)
+		return fw_ch_wd;
+
+	if (wm_hdl->vht_cap_info &
+	    IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)
+		fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
+	else if (wm_hdl->vht_cap_info &
+		 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
+		fw_ch_wd = WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
+
+	return fw_ch_wd;
+}