Переглянути джерело

qcacld-3.0: Update HE STBC cap and support to configure it

Update the HE STBC capabilty per latest spec and add support
to configure it using INI configuration and ioctl.

Change-Id: I4ecc7b600671c132c1f3968a10fb652a4311f484
CRs-Fixed: 2181114
Kiran Kumar Lokere 7 роки тому
батько
коміт
13dedacbdc

+ 19 - 4
core/hdd/src/wlan_hdd_he.c

@@ -56,6 +56,7 @@ void hdd_update_tgt_he_cap(struct hdd_context *hdd_ctx,
 	uint8_t chan_width;
 	QDF_STATUS status;
 	tDot11fIEhe_cap *he_cap = &cfg->he_cap;
+	struct hdd_config *config = hdd_ctx->config;
 
 	hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_CONTROL, he_cap->htc_he);
 	hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_TWT_REQUESTOR,
@@ -130,8 +131,24 @@ void hdd_update_tgt_he_cap(struct hdd_context *hdd_ctx,
 			   he_cap->midamble_rx_max_nsts);
 	hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_LTF_NDP,
 			   he_cap->he_4x_ltf_3200_gi_ndp);
-	hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_STBC_LT80,
-			   he_cap->stbc_lt_80mhz);
+	if (config->enableRxSTBC) {
+		hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_RX_STBC_LT80,
+				   he_cap->rx_stbc_lt_80mhz);
+		hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_RX_STBC_GT80,
+				   he_cap->rx_stbc_gt_80mhz);
+	} else {
+		hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_RX_STBC_LT80, 0);
+		hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_RX_STBC_GT80, 0);
+	}
+	if (config->enableTxSTBC) {
+		hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_TX_STBC_LT80,
+				   he_cap->tx_stbc_lt_80mhz);
+		hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_TX_STBC_GT80,
+				   he_cap->tx_stbc_gt_80mhz);
+	} else {
+		hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_TX_STBC_LT80, 0);
+		hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_TX_STBC_GT80, 0);
+	}
 	hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_DOPPLER, he_cap->doppler);
 	hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_UL_MUMIMO, he_cap->ul_mu);
 	hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_DCM_TX, he_cap->dcm_enc_tx);
@@ -173,8 +190,6 @@ void hdd_update_tgt_he_cap(struct hdd_context *hdd_ctx,
 	hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_4x_LTF_GI,
 			   he_cap->he_ltf_800_gi_4x);
 	hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_MAX_NC, he_cap->max_nc);
-	hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_STBC_GT80,
-			   he_cap->stbc_gt_80mhz);
 	hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_ER_4x_LTF_GI,
 			   he_cap->er_he_ltf_800_gi_4x);
 	hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_PPDU_20_IN_40MHZ_2G,

+ 7 - 0
core/hdd/src/wlan_hdd_wext.c

@@ -4322,6 +4322,9 @@ int hdd_set_tx_stbc(struct hdd_adapter *adapter, int value)
 				   value);
 	if (ret)
 		hdd_err("Failed to set TX STBC value");
+	ret = sme_update_he_tx_stbc_cap(hal, adapter->session_id, value);
+	if (ret)
+		hdd_err("Failed to set HE TX STBC value");
 
 	return ret;
 }
@@ -4390,6 +4393,10 @@ int hdd_set_rx_stbc(struct hdd_adapter *adapter, int value)
 	if (ret)
 		hdd_err("Failed to set RX STBC value");
 
+	ret = sme_update_he_rx_stbc_cap(hal, adapter->session_id, value);
+	if (ret)
+		hdd_err("Failed to set HE RX STBC value");
+
 	return ret;
 }
 

+ 13 - 7
core/mac/inc/sir_mac_prot_def.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -2155,7 +2155,8 @@ struct he_cap_network_endian {
 	uint32_t he_1x_ltf_800_gi_ppdu:1;
 	uint32_t midamble_rx_max_nsts:2;
 	uint32_t he_4x_ltf_3200_gi_ndp:1;
-	uint32_t stbc_lt_80mhz:2;
+	uint32_t tx_stbc_lt_80mhz:1;
+	uint32_t rx_stbc_lt_80mhz:1;
 	uint32_t doppler:2;
 	uint32_t ul_mu:2;
 	uint32_t dcm_enc_tx:3;
@@ -2181,7 +2182,8 @@ struct he_cap_network_endian {
 	uint32_t power_boost:1;
 	uint32_t he_ltf_800_gi_4x:1;
 	uint32_t max_nc:3;
-	uint32_t stbc_gt_80mhz:2;
+	uint32_t tx_stbc_gt_80mhz:1;
+	uint32_t rx_stbc_gt_80mhz:1;
 
 	uint8_t er_he_ltf_800_gi_4x:1;
 	uint8_t he_ppdu_20_in_40Mhz_2G:1;
@@ -2268,7 +2270,8 @@ struct he_capability_info {
 	uint32_t dcm_enc_tx:3;
 	uint32_t ul_mu:2;
 	uint32_t doppler:2;
-	uint32_t stbc_lt_80mhz:2;
+	uint32_t rx_stbc_lt_80mhz:1;
+	uint32_t tx_stbc_lt_80mhz:1;
 	uint32_t he_4x_ltf_3200_gi_ndp:1;
 	uint32_t midamble_rx_max_nsts:2;
 	uint32_t he_1x_ltf_800_gi_ppdu:1;
@@ -2278,7 +2281,8 @@ struct he_capability_info {
 	uint32_t chan_width:7;
 	uint32_t dual_band:1;
 
-	uint32_t stbc_gt_80mhz:2;
+	uint32_t rx_stbc_gt_80mhz:1;
+	uint32_t tx_stbc_gt_80mhz:1;
 	uint32_t max_nc:3;
 	uint32_t he_ltf_800_gi_4x:1;
 	uint32_t power_boost:1;
@@ -2354,7 +2358,8 @@ struct he_capability_info {
 	uint32_t he_1x_ltf_800_gi_ppdu:1;
 	uint32_t midamble_rx_max_nsts:2;
 	uint32_t he_4x_ltf_3200_gi_ndp:1;
-	uint32_t stbc_lt_80mhz:2;
+	uint32_t tx_stbc_lt_80mhz:1;
+	uint32_t rx_stbc_lt_80mhz:1;
 	uint32_t doppler:2;
 	uint32_t ul_mu:2;
 	uint32_t dcm_enc_tx:3;
@@ -2380,7 +2385,8 @@ struct he_capability_info {
 	uint32_t power_boost:1;
 	uint32_t he_ltf_800_gi_4x:1;
 	uint32_t max_nc:3;
-	uint32_t stbc_gt_80mhz:2;
+	uint32_t tx_stbc_gt_80mhz:1;
+	uint32_t rx_stbc_gt_80mhz:1;
 
 	uint8_t er_he_ltf_800_gi_4x:1;
 	uint8_t he_ppdu_20_in_40Mhz_2G:1;

+ 18 - 8
core/mac/inc/wni_cfg.h

@@ -290,7 +290,8 @@ enum {
 	WNI_CFG_HE_LTF_PPDU,
 	WNI_CFG_HE_MIDAMBLE_RX_MAX_NSTS,
 	WNI_CFG_HE_LTF_NDP,
-	WNI_CFG_HE_STBC_LT80,
+	WNI_CFG_HE_TX_STBC_LT80,
+	WNI_CFG_HE_RX_STBC_LT80,
 	WNI_CFG_HE_DOPPLER,
 	WNI_CFG_HE_UL_MUMIMO,
 	WNI_CFG_HE_DCM_TX,
@@ -315,7 +316,8 @@ enum {
 	WNI_CFG_HE_POWER_BOOST,
 	WNI_CFG_HE_4x_LTF_GI,
 	WNI_CFG_HE_MAX_NC,
-	WNI_CFG_HE_STBC_GT80,
+	WNI_CFG_HE_TX_STBC_GT80,
+	WNI_CFG_HE_RX_STBC_GT80,
 	WNI_CFG_HE_ER_4x_LTF_GI,
 	WNI_CFG_HE_PPDU_20_IN_40MHZ_2G,
 	WNI_CFG_HE_PPDU_20_IN_160_80P80MHZ,
@@ -1541,9 +1543,13 @@ enum {
 #define WNI_CFG_HE_LTF_NDP_STAMAX 0x3
 #define WNI_CFG_HE_LTF_NDP_STADEF 0
 
-#define WNI_CFG_HE_STBC_LT80_STAMIN 0
-#define WNI_CFG_HE_STBC_LT80_STAMAX 0x3
-#define WNI_CFG_HE_STBC_LT80_STADEF 0
+#define WNI_CFG_HE_TX_STBC_LT80_STAMIN 0
+#define WNI_CFG_HE_TX_STBC_LT80_STAMAX 1
+#define WNI_CFG_HE_TX_STBC_LT80_STADEF 0
+
+#define WNI_CFG_HE_RX_STBC_LT80_STAMIN 0
+#define WNI_CFG_HE_RX_STBC_LT80_STAMAX 1
+#define WNI_CFG_HE_RX_STBC_LT80_STADEF 0
 
 #define WNI_CFG_HE_DOPPLER_STAMIN 0
 #define WNI_CFG_HE_DOPPLER_STAMAX 0x3
@@ -1641,9 +1647,13 @@ enum {
 #define WNI_CFG_HE_MAX_NC_STAMAX 0x7
 #define WNI_CFG_HE_MAX_NC_STADEF 0
 
-#define WNI_CFG_HE_STBC_GT80_STAMIN 0
-#define WNI_CFG_HE_STBC_GT80_STAMAX 0x3
-#define WNI_CFG_HE_STBC_GT80_STADEF 0
+#define WNI_CFG_HE_TX_STBC_GT80_STAMIN 0
+#define WNI_CFG_HE_TX_STBC_GT80_STAMAX 1
+#define WNI_CFG_HE_TX_STBC_GT80_STADEF 0
+
+#define WNI_CFG_HE_RX_STBC_GT80_STAMIN 0
+#define WNI_CFG_HE_RX_STBC_GT80_STAMAX 1
+#define WNI_CFG_HE_RX_STBC_GT80_STADEF 0
 
 #define WNI_CFG_HE_ER_4x_LTF_GI_STAMIN 0
 #define WNI_CFG_HE_ER_4x_LTF_GI_STAMAX 1

+ 4 - 2
core/mac/src/cfg/cfgUtil/dot11f.frms

@@ -2870,7 +2870,8 @@ IE he_cap (EID_EXTN_ID_ELEMENT) OUI (0x23)
       he_1x_ltf_800_gi_ppdu:1;
       midamble_rx_max_nsts:2;
       he_4x_ltf_3200_gi_ndp:1;
-      stbc_lt_80mhz:2;
+      tx_stbc_lt_80mhz:1;
+      rx_stbc_lt_80mhz:1;
       doppler:2;
       ul_mu:2;
       dcm_enc_tx:3;
@@ -2897,7 +2898,8 @@ IE he_cap (EID_EXTN_ID_ELEMENT) OUI (0x23)
       power_boost:1;
       he_ltf_800_gi_4x:1;
       max_nc:3;
-      stbc_gt_80mhz:2;
+      tx_stbc_gt_80mhz:1;
+      rx_stbc_gt_80mhz:1;
     }
     {
       er_he_ltf_800_gi_4x:1;

+ 4 - 2
core/mac/src/cfg/cfg_param_name.c

@@ -297,7 +297,8 @@ const char *cfg_get_string(uint16_t cfg_id)
 	CASE_RETURN_STRING(WNI_CFG_HE_LDPC);
 	CASE_RETURN_STRING(WNI_CFG_HE_LTF_PPDU);
 	CASE_RETURN_STRING(WNI_CFG_HE_LTF_NDP);
-	CASE_RETURN_STRING(WNI_CFG_HE_STBC_LT80);
+	CASE_RETURN_STRING(WNI_CFG_HE_TX_STBC_LT80);
+	CASE_RETURN_STRING(WNI_CFG_HE_RX_STBC_LT80);
 	CASE_RETURN_STRING(WNI_CFG_HE_DOPPLER);
 	CASE_RETURN_STRING(WNI_CFG_HE_UL_MUMIMO);
 	CASE_RETURN_STRING(WNI_CFG_HE_DCM_TX);
@@ -322,7 +323,8 @@ const char *cfg_get_string(uint16_t cfg_id)
 	CASE_RETURN_STRING(WNI_CFG_HE_POWER_BOOST);
 	CASE_RETURN_STRING(WNI_CFG_HE_4x_LTF_GI);
 	CASE_RETURN_STRING(WNI_CFG_HE_MAX_NC);
-	CASE_RETURN_STRING(WNI_CFG_HE_STBC_GT80);
+	CASE_RETURN_STRING(WNI_CFG_HE_TX_STBC_GT80);
+	CASE_RETURN_STRING(WNI_CFG_HE_RX_STBC_GT80);
 	CASE_RETURN_STRING(WNI_CFG_HE_ER_4x_LTF_GI);
 	CASE_RETURN_STRING(WNI_CFG_HE_RX_MCS_MAP_LT_80);
 	CASE_RETURN_STRING(WNI_CFG_HE_TX_MCS_MAP_LT_80);

+ 14 - 6
core/mac/src/cfg/cfg_proc_msg.c

@@ -1310,10 +1310,14 @@ cgstatic cfg_static[CFG_PARAM_MAX_NUM] = {
 	CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT,
 	WNI_CFG_HE_LTF_NDP_STAMIN, WNI_CFG_HE_LTF_NDP_STAMAX,
 	WNI_CFG_HE_LTF_NDP_STADEF},
-	{WNI_CFG_HE_STBC_LT80,
+	{WNI_CFG_HE_TX_STBC_LT80,
 	CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT,
-	WNI_CFG_HE_STBC_LT80_STAMIN, WNI_CFG_HE_STBC_LT80_STAMAX,
-	WNI_CFG_HE_STBC_LT80_STADEF},
+	WNI_CFG_HE_TX_STBC_LT80_STAMIN, WNI_CFG_HE_TX_STBC_LT80_STAMAX,
+	WNI_CFG_HE_TX_STBC_LT80_STADEF},
+	{WNI_CFG_HE_RX_STBC_LT80,
+	CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT,
+	WNI_CFG_HE_RX_STBC_LT80_STAMIN, WNI_CFG_HE_RX_STBC_LT80_STAMAX,
+	WNI_CFG_HE_RX_STBC_LT80_STADEF},
 	{WNI_CFG_HE_DOPPLER,
 	CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT,
 	WNI_CFG_HE_DOPPLER_STAMIN, WNI_CFG_HE_DOPPLER_STAMAX,
@@ -1411,10 +1415,14 @@ cgstatic cfg_static[CFG_PARAM_MAX_NUM] = {
 	CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT,
 	WNI_CFG_HE_MAX_NC_STAMIN, WNI_CFG_HE_MAX_NC_STAMAX,
 	WNI_CFG_HE_MAX_NC_STADEF},
-	{WNI_CFG_HE_STBC_GT80,
+	{WNI_CFG_HE_TX_STBC_GT80,
+	CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT,
+	WNI_CFG_HE_TX_STBC_GT80_STAMIN, WNI_CFG_HE_TX_STBC_GT80_STAMAX,
+	WNI_CFG_HE_TX_STBC_GT80_STADEF},
+	{WNI_CFG_HE_RX_STBC_GT80,
 	CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT,
-	WNI_CFG_HE_STBC_GT80_STAMIN, WNI_CFG_HE_STBC_GT80_STAMAX,
-	WNI_CFG_HE_STBC_GT80_STADEF},
+	WNI_CFG_HE_RX_STBC_GT80_STAMIN, WNI_CFG_HE_RX_STBC_GT80_STAMAX,
+	WNI_CFG_HE_RX_STBC_GT80_STADEF},
 	{WNI_CFG_HE_ER_4x_LTF_GI,
 	CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT,
 	WNI_CFG_HE_ER_4x_LTF_GI_STAMIN, WNI_CFG_HE_ER_4x_LTF_GI_STAMAX,

+ 4 - 2
core/mac/src/include/dot11f.h

@@ -8760,7 +8760,8 @@ typedef struct sDot11fIEhe_cap {
 	uint32_t he_1x_ltf_800_gi_ppdu:1;
 	uint32_t midamble_rx_max_nsts:2;
 	uint32_t he_4x_ltf_3200_gi_ndp:1;
-	uint32_t        stbc_lt_80mhz:2;
+	uint32_t     tx_stbc_lt_80mhz:1;
+	uint32_t     rx_stbc_lt_80mhz:1;
 	uint32_t              doppler:2;
 	uint32_t                ul_mu:2;
 	uint32_t           dcm_enc_tx:3;
@@ -8785,7 +8786,8 @@ typedef struct sDot11fIEhe_cap {
 	uint32_t          power_boost:1;
 	uint32_t     he_ltf_800_gi_4x:1;
 	uint32_t               max_nc:3;
-	uint32_t        stbc_gt_80mhz:2;
+	uint32_t     tx_stbc_gt_80mhz:1;
+	uint32_t     rx_stbc_gt_80mhz:1;
 	uint8_t  er_he_ltf_800_gi_4x:1;
 	uint8_t he_ppdu_20_in_40Mhz_2G:1;
 	uint8_t he_ppdu_20_in_160_80p80Mhz:1;

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

@@ -7205,29 +7205,25 @@ static void lim_intersect_he_caps(tDot11fIEhe_cap *rcvd_he,
 
 	peer_he->fragmentation &= session_he->fragmentation;
 
-	/* Tx STBC is first bit and Rx STBC is second bit */
-	if (session_he->stbc_lt_80mhz) {
-		val = 0;
-		if ((session_he->stbc_lt_80mhz & 0x1) &&
-		    (peer_he->stbc_lt_80mhz & 0x10))
-			val |= (1 << 1);
-		if ((session_he->stbc_lt_80mhz & 0x10) &&
-		    (peer_he->stbc_lt_80mhz & 0x1))
-			val |= (1 << 0);
-		peer_he->stbc_lt_80mhz = val;
-	}
+	if (session_he->tx_stbc_lt_80mhz && peer_he->rx_stbc_lt_80mhz)
+		peer_he->rx_stbc_lt_80mhz = 1;
+	else
+		peer_he->rx_stbc_lt_80mhz = 0;
 
-	/* Tx STBC is first bit and Rx STBC is second bit */
-	if (session_he->stbc_gt_80mhz) {
-		val = 0;
-		if ((session_he->stbc_gt_80mhz & 0x1) &&
-		    (peer_he->stbc_gt_80mhz & 0x10))
-			val |= (1 << 1);
-		if ((session_he->stbc_gt_80mhz & 0x10) &&
-		    (peer_he->stbc_gt_80mhz & 0x1))
-			val |= (1 << 0);
-		peer_he->stbc_gt_80mhz = val;
-	}
+	if (session_he->rx_stbc_lt_80mhz && peer_he->tx_stbc_lt_80mhz)
+		peer_he->tx_stbc_lt_80mhz = 1;
+	else
+		peer_he->tx_stbc_lt_80mhz = 0;
+
+	if (session_he->tx_stbc_gt_80mhz && peer_he->rx_stbc_gt_80mhz)
+		peer_he->rx_stbc_gt_80mhz = 1;
+	else
+		peer_he->rx_stbc_gt_80mhz = 0;
+
+	if (session_he->rx_stbc_gt_80mhz && peer_he->tx_stbc_gt_80mhz)
+		peer_he->tx_stbc_gt_80mhz = 1;
+	else
+		peer_he->tx_stbc_gt_80mhz = 0;
 
 	/* Tx Doppler is first bit and Rx Doppler is second bit */
 	if (session_he->doppler) {
@@ -7505,8 +7501,10 @@ void lim_log_he_cap(tpAniSirGlobal mac, tDot11fIEhe_cap *he_cap)
 			he_cap->midamble_rx_max_nsts);
 	pe_debug("\tLTF and GI for NDP: 0x%02x",
 			he_cap->he_4x_ltf_3200_gi_ndp);
-	pe_debug("\tSTBC Tx & Rx support (<= 80MHz): 0x%02x",
-		 he_cap->stbc_lt_80mhz);
+	pe_debug("\tSTBC Tx support (<= 80MHz): 0x%01x",
+		 he_cap->tx_stbc_lt_80mhz);
+	pe_debug("\tSTBC Rx support (<= 80MHz): 0x%01x",
+		 he_cap->rx_stbc_lt_80mhz);
 	pe_debug("\tDoppler support: 0x%02x", he_cap->doppler);
 	pe_debug("\tUL MU: 0x%02x", he_cap->ul_mu);
 	pe_debug("\tDCM encoding Tx: 0x%03x", he_cap->dcm_enc_tx);
@@ -7542,8 +7540,10 @@ void lim_log_he_cap(tpAniSirGlobal mac, tDot11fIEhe_cap *he_cap)
 	pe_debug("\tSRP based SR-support: 0x%01x", he_cap->srp);
 	pe_debug("\tPower boost factor: 0x%01x", he_cap->power_boost);
 	pe_debug("\t4x HE LTF support: 0x%01x", he_cap->he_ltf_800_gi_4x);
-	pe_debug("\tSTBC Tx & Rx support (> 80MHz): 0x%02x",
-		 he_cap->stbc_gt_80mhz);
+	pe_debug("\tSTBC Tx support (> 80MHz): 0x%01x",
+		 he_cap->tx_stbc_gt_80mhz);
+	pe_debug("\tSTBC Rx support (> 80MHz): 0x%01x",
+		 he_cap->rx_stbc_gt_80mhz);
 	pe_debug("\tMax Nc: 0x%03x", he_cap->max_nc);
 	pe_debug("\tER 4x HE LTF support: 0x%01x", he_cap->er_he_ltf_800_gi_4x);
 	pe_debug("\tER 4x HE LTF support: 0x%01x",
@@ -7704,8 +7704,10 @@ void lim_set_he_caps(tpAniSirGlobal mac, tpPESession session, uint8_t *ie_start,
 		he_cap->he_1x_ltf_800_gi_ppdu = dot11_cap.he_1x_ltf_800_gi_ppdu;
 		he_cap->midamble_rx_max_nsts = dot11_cap.midamble_rx_max_nsts;
 		he_cap->he_4x_ltf_3200_gi_ndp = dot11_cap.he_4x_ltf_3200_gi_ndp;
-		he_cap->stbc_lt_80mhz = dot11_cap.stbc_lt_80mhz;
-		he_cap->stbc_gt_80mhz = dot11_cap.stbc_gt_80mhz;
+		he_cap->tx_stbc_lt_80mhz = dot11_cap.tx_stbc_lt_80mhz;
+		he_cap->rx_stbc_lt_80mhz = dot11_cap.rx_stbc_lt_80mhz;
+		he_cap->tx_stbc_gt_80mhz = dot11_cap.tx_stbc_gt_80mhz;
+		he_cap->rx_stbc_gt_80mhz = dot11_cap.rx_stbc_gt_80mhz;
 		he_cap->doppler = dot11_cap.doppler;
 		he_cap->ul_mu = dot11_cap.ul_mu;
 		he_cap->dcm_enc_tx = dot11_cap.dcm_enc_tx;

+ 8 - 4
core/mac/src/sys/legacy/src/utils/src/dot11f.c

@@ -6609,7 +6609,8 @@ uint32_t dot11f_unpack_ie_he_cap(tpAniSirGlobal pCtx,
 	pDst->he_1x_ltf_800_gi_ppdu = tmp78__ >> 14 & 0x1;
 	pDst->midamble_rx_max_nsts = tmp78__ >> 15 & 0x3;
 	pDst->he_4x_ltf_3200_gi_ndp = tmp78__ >> 17 & 0x1;
-	pDst->stbc_lt_80mhz = tmp78__ >> 18 & 0x3;
+	pDst->tx_stbc_lt_80mhz = tmp78__ >> 18 & 0x1;
+	pDst->rx_stbc_lt_80mhz = tmp78__ >> 19 & 0x1;
 	pDst->doppler = tmp78__ >> 20 & 0x3;
 	pDst->ul_mu = tmp78__ >> 22 & 0x3;
 	pDst->dcm_enc_tx = tmp78__ >> 24 & 0x7;
@@ -6637,7 +6638,8 @@ uint32_t dot11f_unpack_ie_he_cap(tpAniSirGlobal pCtx,
 	pDst->power_boost = tmp79__ >> 25 & 0x1;
 	pDst->he_ltf_800_gi_4x = tmp79__ >> 26 & 0x1;
 	pDst->max_nc = tmp79__ >> 27 & 0x7;
-	pDst->stbc_gt_80mhz = tmp79__ >> 30 & 0x3;
+	pDst->tx_stbc_gt_80mhz = tmp79__ >> 30 & 0x1;
+	pDst->rx_stbc_gt_80mhz = tmp79__ >> 31 & 0x1;
 	tmp80__ = *pBuf;
 	pBuf += 1;
 	ielen -= 1;
@@ -23456,7 +23458,8 @@ uint32_t dot11f_pack_ie_he_cap(tpAniSirGlobal pCtx,
 		tmp170__ |= (pSrc->he_1x_ltf_800_gi_ppdu << 14);
 		tmp170__ |= (pSrc->midamble_rx_max_nsts << 15);
 		tmp170__ |= (pSrc->he_4x_ltf_3200_gi_ndp << 17);
-		tmp170__ |= (pSrc->stbc_lt_80mhz << 18);
+		tmp170__ |= (pSrc->tx_stbc_lt_80mhz << 18);
+		tmp170__ |= (pSrc->rx_stbc_lt_80mhz << 19);
 		tmp170__ |= (pSrc->doppler << 20);
 		tmp170__ |= (pSrc->ul_mu << 22);
 		tmp170__ |= (pSrc->dcm_enc_tx << 24);
@@ -23486,7 +23489,8 @@ uint32_t dot11f_pack_ie_he_cap(tpAniSirGlobal pCtx,
 		tmp171__ |= (pSrc->power_boost << 25);
 		tmp171__ |= (pSrc->he_ltf_800_gi_4x << 26);
 		tmp171__ |= (pSrc->max_nc << 27);
-		tmp171__ |= (pSrc->stbc_gt_80mhz << 30);
+		tmp171__ |= (pSrc->tx_stbc_gt_80mhz << 30);
+		tmp171__ |= (pSrc->rx_stbc_gt_80mhz << 31);
 		frameshtonl(pCtx, pBuf, tmp171__, 0);
 		*pnConsumed += 4;
 		pBuf += 4;

+ 8 - 4
core/mac/src/sys/legacy/src/utils/src/parser_api.c

@@ -6208,8 +6208,10 @@ QDF_STATUS populate_dot11f_he_caps(tpAniSirGlobal mac_ctx, tpPESession session,
 		he_cap->midamble_rx_max_nsts = value;
 		CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_LTF_NDP, value);
 		he_cap->he_4x_ltf_3200_gi_ndp = value;
-		CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_STBC_LT80, value);
-		he_cap->stbc_lt_80mhz = value;
+		CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_TX_STBC_LT80, value);
+		he_cap->tx_stbc_lt_80mhz = value;
+		CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_RX_STBC_LT80, value);
+		he_cap->rx_stbc_lt_80mhz = value;
 		CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_DOPPLER, value);
 		he_cap->doppler = value;
 		CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_UL_MUMIMO, value);
@@ -6258,8 +6260,10 @@ QDF_STATUS populate_dot11f_he_caps(tpAniSirGlobal mac_ctx, tpPESession session,
 		he_cap->he_ltf_800_gi_4x = value;
 		CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_MAX_NC, value);
 		he_cap->max_nc = value;
-		CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_STBC_GT80, value);
-		he_cap->stbc_gt_80mhz = value;
+		CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_TX_STBC_GT80, value);
+		he_cap->tx_stbc_gt_80mhz = value;
+		CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_RX_STBC_GT80, value);
+		he_cap->rx_stbc_gt_80mhz = value;
 		CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_ER_4x_LTF_GI, value);
 		he_cap->er_he_ltf_800_gi_4x = value;
 		CFG_GET_INT(status, mac_ctx,

+ 30 - 0
core/sme/inc/sme_api.h

@@ -2128,6 +2128,25 @@ void sme_update_he_cap_nss(tHalHandle hal, uint8_t session_id,
  * Return: 0 on success else err code
  */
 int sme_update_he_mcs(tHalHandle hal, uint8_t session_id, uint16_t he_mcs);
+/**
+ * sme_update_he_tx_stbc_cap() - Sets the HE Tx STBC capability
+ * @hal: Pointer to HAL
+ * @session_id: SME session id
+ * @value: set value
+ *
+ * Return: 0 on success else err code
+ */
+int sme_update_he_tx_stbc_cap(tHalHandle hal, uint8_t session_id, int value);
+
+/**
+ * sme_update_he_rx_stbc_cap() - Sets the HE Rx STBC capability
+ * @hal: Pointer to HAL
+ * @session_id: SME session id
+ * @value: set value
+ *
+ * Return: 0 on success else err code
+ */
+int sme_update_he_rx_stbc_cap(tHalHandle hal, uint8_t session_id, int value);
 #else
 static inline void sme_update_he_cap_nss(tHalHandle hal, uint8_t session_id,
 		uint8_t nss)
@@ -2137,6 +2156,17 @@ static inline int sme_update_he_mcs(tHalHandle hal, uint8_t session_id,
 {
 	return 0;
 }
+static inline int sme_update_he_tx_stbc_cap(tHalHandle hal, uint8_t session_id,
+					    int value)
+{
+	return 0;
+}
+
+static inline int sme_update_he_rx_stbc_cap(tHalHandle hal, uint8_t session_id,
+					    int value)
+{
+	return 0;
+}
 #endif
 
 #endif /* #if !defined( __SME_API_H ) */

+ 45 - 0
core/sme/src/common/sme_api.c

@@ -13243,6 +13243,51 @@ int sme_update_he_mcs(tHalHandle hal, uint8_t session_id, uint16_t he_mcs)
 
 	return 0;
 }
+
+static int sme_update_he_cap(tHalHandle hal, uint8_t session_id,
+		uint16_t he_cap, int value)
+{
+	tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
+	struct csr_roam_session *session;
+	uint32_t he_cap_val = 0;
+
+	session = CSR_GET_SESSION(mac_ctx, session_id);
+	if (!session) {
+		sme_err("No session for id %d", session_id);
+		return -EINVAL;
+	}
+	he_cap_val = value ? 1 : 0;
+	sme_cfg_set_int(mac_ctx, he_cap, he_cap_val);
+	csr_update_session_he_cap(mac_ctx, session);
+
+	return 0;
+}
+
+int sme_update_he_tx_stbc_cap(tHalHandle hal, uint8_t session_id, int value)
+{
+	int ret;
+
+	ret = sme_update_he_cap(hal, session_id,
+			 WNI_CFG_HE_TX_STBC_LT80, value);
+	if (ret)
+		return ret;
+
+	return sme_update_he_cap(hal, session_id,
+			 WNI_CFG_HE_TX_STBC_GT80, value);
+}
+
+int sme_update_he_rx_stbc_cap(tHalHandle hal, uint8_t session_id, int value)
+{
+	int ret;
+
+	ret = sme_update_he_cap(hal, session_id,
+			 WNI_CFG_HE_RX_STBC_LT80, value);
+	if (ret)
+		return ret;
+
+	return sme_update_he_cap(hal, session_id,
+			 WNI_CFG_HE_RX_STBC_GT80, value);
+}
 #endif
 
 /**

+ 8 - 4
core/sme/src/csr/csr_api_roam.c

@@ -2422,8 +2422,10 @@ void csr_update_session_he_cap(tpAniSirGlobal mac_ctx,
 	he_cap->midamble_rx_max_nsts = value;
 	sme_cfg_get_int(mac_ctx, WNI_CFG_HE_LTF_NDP, &value);
 	he_cap->he_4x_ltf_3200_gi_ndp = value;
-	sme_cfg_get_int(mac_ctx, WNI_CFG_HE_STBC_LT80, &value);
-	he_cap->stbc_lt_80mhz = value;
+	sme_cfg_get_int(mac_ctx, WNI_CFG_HE_TX_STBC_LT80, &value);
+	he_cap->tx_stbc_lt_80mhz = value;
+	sme_cfg_get_int(mac_ctx, WNI_CFG_HE_RX_STBC_LT80, &value);
+	he_cap->rx_stbc_lt_80mhz = value;
 	sme_cfg_get_int(mac_ctx, WNI_CFG_HE_DOPPLER, &value);
 	he_cap->doppler = value;
 	sme_cfg_get_int(mac_ctx, WNI_CFG_HE_UL_MUMIMO, &value);
@@ -2472,8 +2474,10 @@ void csr_update_session_he_cap(tpAniSirGlobal mac_ctx,
 	he_cap->he_ltf_800_gi_4x = value;
 	sme_cfg_get_int(mac_ctx, WNI_CFG_HE_MAX_NC, &value);
 	he_cap->max_nc = value;
-	sme_cfg_get_int(mac_ctx, WNI_CFG_HE_STBC_GT80, &value);
-	he_cap->stbc_gt_80mhz = value;
+	sme_cfg_get_int(mac_ctx, WNI_CFG_HE_TX_STBC_GT80, &value);
+	he_cap->tx_stbc_gt_80mhz = value;
+	sme_cfg_get_int(mac_ctx, WNI_CFG_HE_RX_STBC_GT80, &value);
+	he_cap->rx_stbc_gt_80mhz = value;
 	sme_cfg_get_int(mac_ctx, WNI_CFG_HE_ER_4x_LTF_GI, &value);
 	he_cap->er_he_ltf_800_gi_4x = value;
 	sme_cfg_get_int(mac_ctx, WNI_CFG_HE_PPDU_20_IN_40MHZ_2G, &value);

+ 16 - 16
core/wma/src/wma_he.c

@@ -228,10 +228,10 @@ static void wma_convert_he_cap(tDot11fIEhe_cap *he_cap, uint32_t mac_cap,
 	he_cap->midamble_rx_max_nsts =
 		WMI_HECAP_PHY_MIDAMBLERXMAXNSTS_GET(phy_cap);
 	he_cap->he_4x_ltf_3200_gi_ndp = WMI_HECAP_PHY_LTFGIFORNDP_GET(phy_cap);
-	he_cap->stbc_lt_80mhz = (WMI_HECAP_PHY_RXSTBC_GET(phy_cap) << 1) |
-				 WMI_HECAP_PHY_TXSTBC_GET(phy_cap);
-	he_cap->stbc_gt_80mhz = (WMI_HECAP_PHY_STBCRXGT80_GET(phy_cap) << 1) |
-				 WMI_HECAP_PHY_STBCTXGT80_GET(phy_cap);
+	he_cap->rx_stbc_lt_80mhz = WMI_HECAP_PHY_RXSTBC_GET(phy_cap);
+	he_cap->tx_stbc_lt_80mhz = WMI_HECAP_PHY_TXSTBC_GET(phy_cap);
+	he_cap->rx_stbc_gt_80mhz = WMI_HECAP_PHY_STBCRXGT80_GET(phy_cap);
+	he_cap->tx_stbc_gt_80mhz = WMI_HECAP_PHY_STBCTXGT80_GET(phy_cap);
 
 	he_cap->doppler = (WMI_HECAP_PHY_RXDOPPLER_GET(phy_cap) << 1) |
 				WMI_HECAP_PHY_TXDOPPLER_GET(phy_cap);
@@ -412,8 +412,10 @@ static void wma_derive_ext_he_cap(tDot11fIEhe_cap *he_cap,
 	he_cap->he_4x_ltf_3200_gi_ndp =
 		QDF_MIN(he_cap->he_4x_ltf_3200_gi_ndp,
 				new_cap->he_4x_ltf_3200_gi_ndp);
-	he_cap->stbc_lt_80mhz = QDF_MIN(he_cap->stbc_lt_80mhz,
-			new_cap->stbc_lt_80mhz);
+	he_cap->tx_stbc_lt_80mhz = QDF_MIN(he_cap->tx_stbc_lt_80mhz,
+			new_cap->tx_stbc_lt_80mhz);
+	he_cap->rx_stbc_lt_80mhz = QDF_MIN(he_cap->rx_stbc_lt_80mhz,
+			new_cap->rx_stbc_lt_80mhz);
 	he_cap->doppler = QDF_MIN(he_cap->doppler,
 			new_cap->doppler);
 	he_cap->ul_mu = QDF_MIN(he_cap->ul_mu, new_cap->ul_mu);
@@ -566,7 +568,8 @@ void wma_print_he_cap(tDot11fIEhe_cap *he_cap)
 	WMA_LOGD("\tMidamble Rx MAX NSTS: 0x%02x",
 		 he_cap->midamble_rx_max_nsts);
 	WMA_LOGD("\tLTF and GI for NDP: 0x%02x", he_cap->he_4x_ltf_3200_gi_ndp);
-	WMA_LOGD("\tSTBC Tx & Rx support: 0x%02x", he_cap->stbc_lt_80mhz);
+	WMA_LOGD("\tSTBC Tx support <= 80M: 0x%01x", he_cap->tx_stbc_lt_80mhz);
+	WMA_LOGD("\tSTBC Rx support <= 80M: 0x%01x", he_cap->rx_stbc_lt_80mhz);
 	WMA_LOGD("\tDoppler support: 0x%02x", he_cap->doppler);
 	WMA_LOGD("\tUL MU: 0x%02x", he_cap->ul_mu);
 	WMA_LOGD("\tDCM encoding Tx: 0x%03x", he_cap->dcm_enc_tx);
@@ -600,7 +603,8 @@ void wma_print_he_cap(tDot11fIEhe_cap *he_cap)
 	WMA_LOGD("\t4x HE LTF support: 0x%01x", he_cap->he_ltf_800_gi_4x);
 
 	WMA_LOGD("\tMax NC: 0x%01x", he_cap->max_nc);
-	WMA_LOGD("\tstbc gt 80mhz: 0x%01x", he_cap->stbc_gt_80mhz);
+	WMA_LOGD("\tstbc Tx gt 80mhz: 0x%01x", he_cap->tx_stbc_gt_80mhz);
+	WMA_LOGD("\tstbc Rx gt 80mhz: 0x%01x", he_cap->rx_stbc_gt_80mhz);
 	WMA_LOGD("\ter_he_ltf_800_gi_4x: 0x%01x", he_cap->er_he_ltf_800_gi_4x);
 	WMA_LOGD("\the_ppdu_20_in_40Mhz_2G: 0x%01x",
 					he_cap->he_ppdu_20_in_40Mhz_2G);
@@ -1075,10 +1079,8 @@ void wma_populate_peer_he_cap(struct peer_assoc_params *peer,
 				he_cap->midamble_rx_max_nsts);
 	WMI_HECAP_PHY_LTFGIFORNDP_SET(phy_cap, he_cap->he_4x_ltf_3200_gi_ndp);
 
-	temp = he_cap->stbc_lt_80mhz & 0x1;
-	WMI_HECAP_PHY_RXSTBC_SET(phy_cap, temp);
-	temp = he_cap->stbc_lt_80mhz >> 0x1;
-	WMI_HECAP_PHY_TXSTBC_SET(phy_cap, temp);
+	WMI_HECAP_PHY_RXSTBC_SET(phy_cap, he_cap->rx_stbc_lt_80mhz);
+	WMI_HECAP_PHY_TXSTBC_SET(phy_cap, he_cap->tx_stbc_lt_80mhz);
 
 	temp = he_cap->doppler & 0x1;
 	WMI_HECAP_PHY_RXDOPPLER_SET(phy_cap, temp);
@@ -1117,10 +1119,8 @@ void wma_populate_peer_he_cap(struct peer_assoc_params *peer,
 
 	WMI_HECAP_PHY_MAXNC_SET(phy_cap, he_cap->max_nc);
 
-	temp = he_cap->stbc_gt_80mhz & 0x1;
-	WMI_HECAP_PHY_STBCRXGT80_SET(phy_cap, temp);
-	temp = he_cap->stbc_gt_80mhz >> 0x1;
-	WMI_HECAP_PHY_STBCTXGT80_SET(phy_cap, temp);
+	WMI_HECAP_PHY_STBCRXGT80_SET(phy_cap, he_cap->rx_stbc_gt_80mhz);
+	WMI_HECAP_PHY_STBCTXGT80_SET(phy_cap, he_cap->tx_stbc_gt_80mhz);
 
 	WMI_HECAP_PHY_ERSU4X800NSECGI_SET(phy_cap, he_cap->er_he_ltf_800_gi_4x);
 	WMI_HECAP_PHY_HEPPDU20IN40MHZ2G_SET(phy_cap,