From aeca1b93d68ff6fe667ddf3e8b75f8f86765ad6c Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Mon, 16 Oct 2017 16:55:31 -0700 Subject: [PATCH] qcacld-3.0: Update 11AX - Draft 1.4 MCS support - 2/2 Update driver to conform with Draft 1.4 MCS frame parser changes made as part of Change-Id: I207db123d463f54ed6b148c9e957eb551d617ca2. Change-Id: I4007ce0303b87c281b6fb2a94df576ee0da3f3e8 CRs-Fixed: 2130185 --- core/hdd/src/wlan_hdd_he.c | 23 +- core/mac/inc/sir_api.h | 94 ++++++- core/mac/inc/sir_mac_prot_def.h | 25 +- core/mac/inc/wni_cfg.h | 36 ++- core/mac/src/cfg/cfg_param_name.c | 8 +- core/mac/src/cfg/cfg_proc_msg.c | 35 ++- core/mac/src/pe/lim/lim_assoc_utils.c | 2 +- .../src/pe/lim/lim_process_sme_req_messages.c | 11 +- core/mac/src/pe/lim/lim_utils.c | 229 ++++++++++++------ core/mac/src/pe/lim/lim_utils.h | 1 + .../src/sys/legacy/src/utils/src/parser_api.c | 30 ++- core/sme/src/csr/csr_api_roam.c | 26 +- core/wma/src/wma_he.c | 163 +++++++++---- 13 files changed, 507 insertions(+), 176 deletions(-) diff --git a/core/hdd/src/wlan_hdd_he.c b/core/hdd/src/wlan_hdd_he.c index 7aaa62728a09..9c255ed7b497 100644 --- a/core/hdd/src/wlan_hdd_he.c +++ b/core/hdd/src/wlan_hdd_he.c @@ -53,6 +53,7 @@ static int hdd_he_set_wni_cfg(struct hdd_context *hdd_ctx, void hdd_update_tgt_he_cap(struct hdd_context *hdd_ctx, struct wma_tgt_cfg *cfg) { + uint8_t chan_width; uint32_t ppet_size = sizeof(tDot11fIEppe_threshold); QDF_STATUS status; tDot11fIEhe_cap *he_cap = &cfg->he_cap; @@ -108,7 +109,12 @@ void hdd_update_tgt_he_cap(struct hdd_context *hdd_ctx, he_cap->ops_supp); hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_DUAL_BAND, he_cap->dual_band); - hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_CHAN_WIDTH, he_cap->chan_width); + chan_width = HE_CH_WIDTH_COMBINE(he_cap->chan_width_0, + he_cap->chan_width_1, he_cap->chan_width_2, + he_cap->chan_width_3, he_cap->chan_width_4, + he_cap->chan_width_5, he_cap->chan_width_6); + + hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_CHAN_WIDTH, chan_width); hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_RX_PREAM_PUNC, he_cap->rx_pream_puncturing); hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_CLASS_OF_DEVICE, @@ -165,8 +171,19 @@ void hdd_update_tgt_he_cap(struct hdd_context *hdd_ctx, 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_NSS, he_cap->nss_supported); - hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_MCS, he_cap->mcs_supported); + + hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_RX_MCS_MAP_LT_80, + he_cap->rx_he_mcs_map_lt_80); + hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_TX_MCS_MAP_LT_80, + he_cap->tx_he_mcs_map_lt_80); + hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_RX_MCS_MAP_160, + *((uint16_t *)he_cap->rx_he_mcs_map_160)); + hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_TX_MCS_MAP_160, + *((uint16_t *)he_cap->tx_he_mcs_map_160)); + hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_RX_MCS_MAP_80_80, + *((uint16_t *)he_cap->rx_he_mcs_map_80_80)); + hdd_he_set_wni_cfg(hdd_ctx, WNI_CFG_HE_TX_MCS_MAP_80_80, + *((uint16_t *)he_cap->tx_he_mcs_map_80_80)); /* PPET can not be configured by user - Set values from FW */ status = sme_cfg_set_str(hdd_ctx->hHal, WNI_CFG_HE_PPET, diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 2186befd9b07..79ccbe21cfe3 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -406,8 +406,12 @@ typedef struct sSirSupportedRates { uint16_t vhtTxMCSMap; uint16_t vhtTxHighestDataRate; #ifdef WLAN_FEATURE_11AX - uint32_t he_rx_mcs; - uint32_t he_tx_mcs; + uint16_t rx_he_mcs_map_lt_80; + uint16_t tx_he_mcs_map_lt_80; + uint16_t rx_he_mcs_map_160; + uint16_t tx_he_mcs_map_160; + uint16_t rx_he_mcs_map_80_80; + uint16_t tx_he_mcs_map_80_80; #endif } tSirSupportedRates, *tpSirSupportedRates; @@ -7574,16 +7578,77 @@ struct wow_enable_params { #define HE_MAX_PHY_CAP_SIZE 3 -/* - * Three bits are used for each MCS - * For SS - 1; bits 0-2 - * For SS - 2; bits 3-5 - * MCS values are interpreted as in IEEE 11ax-D1.0 spec - */ -#define HE_MCS_1x1 0xFFFFFFF8 -#define HE_MCS_2x2 0xFFFFFFC0 +#define HE_CH_WIDTH_GET_BIT(ch_wd, bit) (((ch_wd) >> (bit)) & 1) +#define HE_CH_WIDTH_COMBINE(b0, b1, b2, b3, b4, b5, b6) \ + ((uint8_t)(b0) | ((b1) << 1) | ((b2) << 2) | ((b3) << 3) | \ + ((b4) << 4) | ((b5) << 5) | ((b6) << 6)) -#define HEMCSSIZE 3 +/* + * MCS values are interpreted as in IEEE 11ax-D1.4 spec onwards + * +-----------------------------------------------------+ + * | SS8 | SS7 | SS6 | SS5 | SS4 | SS3 | SS2 | SS1 | + * +-----------------------------------------------------+ + * | 15-14 | 13-12 | 11-10 | 9-8 | 7-6 | 5-4 | 3-2 | 1-0 | + * +-----------------------------------------------------+ + */ +#define HE_MCS_NSS_SHIFT(nss) (((nss) - 1) << 1) +#define HE_MCS_MSK_4_NSS(nss) (3 << HE_MCS_NSS_SHIFT(nss)) +#define HE_MCS_INV_MSK_4_NSS(nss) (~HE_MCS_MSK_4_NSS(nss)) +#define HE_GET_MCS_4_NSS(mcs_set, nss) \ + (((mcs_set) >> HE_MCS_NSS_SHIFT(nss)) & 3) +#define HE_SET_MCS_4_NSS(mcs_set, mcs, nss) \ + (((mcs_set) & HE_MCS_INV_MSK_4_NSS(nss)) | \ + ((mcs) << HE_MCS_NSS_SHIFT(nss))) +#define HE_MCS_IS_NSS_ENABLED(mcs_set, nss) \ + ((HE_MCS_MSK_4_NSS(nss) & (mcs_set)) != HE_MCS_MSK_4_NSS(nss)) + +#define HE_MCS_ALL_DISABLED 0xFFFF +/* + * Following formuala has been arrived at using karnaugh map and unit tested + * with sample code. Take MCS for each NSS as 2 bit value first and solve for + * 2 bit intersection of NSS. Use following table/Matrix as guide for solving + * K-Maps + * MCS 1\MCS 2 00 01 10 11 + * 00 00 00 00 11 + * 01 00 01 01 11 + * 10 00 01 10 11 + * 11 11 11 11 11 + * if output MCS is o1o0, then as per K-map reduction: + * o0 = m1.m0 | n1.n0 | (~m1).m0.(n1^n0) | (~n1).n0.(m1^m0) + * o1 = m1.m0 | n1.n0 | m1.(~m0).n1.(~n0) + * + * Please note: Calculating MCS intersection is 80211 protocol specific and + * should be implemented in PE. WMA can use this macro rather than calling any + * lim API to do the intersection. + */ +#define HE_INTERSECT_MCS_BITS_PER_NSS(m1, m0, n1, n0) \ + (((m1 & m0) | (n1 & n0) | (((~m1) & m0) & (n1 ^ n0)) | \ + (((~n1) & n0) & (m1 ^ m0))) | (((m1 & m0) | (n1 & n0) | \ + (m1 & ~m0 & n1 & ~n0)) << 1)) + +/* following takes MCS as 2 bits */ +#define HE_INTERSECT_MCS_PER_NSS(mcs_1, mcs_2) \ + HE_INTERSECT_MCS_BITS_PER_NSS((mcs_1 >> 1), (mcs_1 & 1), \ + (mcs_2 >> 1), (mcs_2 & 1)) + +/* following takes MCS as 16 bits */ +#define HE_INTERSECT_MCS(mcs_1, mcs_2) ( \ + HE_INTERSECT_MCS_PER_NSS(HE_GET_MCS_4_NSS(mcs_1, 1), \ + HE_GET_MCS_4_NSS(mcs_2, 1)) << HE_MCS_NSS_SHIFT(1) | \ + HE_INTERSECT_MCS_PER_NSS(HE_GET_MCS_4_NSS(mcs_1, 2), \ + HE_GET_MCS_4_NSS(mcs_2, 2)) << HE_MCS_NSS_SHIFT(2) | \ + HE_INTERSECT_MCS_PER_NSS(HE_GET_MCS_4_NSS(mcs_1, 3), \ + HE_GET_MCS_4_NSS(mcs_2, 3)) << HE_MCS_NSS_SHIFT(3) | \ + HE_INTERSECT_MCS_PER_NSS(HE_GET_MCS_4_NSS(mcs_1, 4), \ + HE_GET_MCS_4_NSS(mcs_2, 4)) << HE_MCS_NSS_SHIFT(4) | \ + HE_INTERSECT_MCS_PER_NSS(HE_GET_MCS_4_NSS(mcs_1, 5), \ + HE_GET_MCS_4_NSS(mcs_2, 5)) << HE_MCS_NSS_SHIFT(5) | \ + HE_INTERSECT_MCS_PER_NSS(HE_GET_MCS_4_NSS(mcs_1, 6), \ + HE_GET_MCS_4_NSS(mcs_2, 6)) << HE_MCS_NSS_SHIFT(6) | \ + HE_INTERSECT_MCS_PER_NSS(HE_GET_MCS_4_NSS(mcs_1, 7), \ + HE_GET_MCS_4_NSS(mcs_2, 7)) << HE_MCS_NSS_SHIFT(7) | \ + HE_INTERSECT_MCS_PER_NSS(HE_GET_MCS_4_NSS(mcs_1, 8), \ + HE_GET_MCS_4_NSS(mcs_2, 8)) << HE_MCS_NSS_SHIFT(8)) /** * struct he_capability - to store 11ax HE capabilities @@ -7600,6 +7665,13 @@ struct he_capability { }; #endif +#define HE_GET_NSS(mcs, nss) \ + do { \ + (nss) = 0; \ + while ((((mcs) >> ((nss)*2)) & 3) != 3 && nss <= 8) \ + (nss)++; \ + } while (0) + /** * struct sir_del_all_tdls_peers - delete all tdls peers * @msg_type: type of message diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h index 99669914656b..281ae9780fc0 100644 --- a/core/mac/inc/sir_mac_prot_def.h +++ b/core/mac/inc/sir_mac_prot_def.h @@ -2175,10 +2175,12 @@ struct he_capability_info { uint8_t reserved2:3; uint8_t er_he_ltf_800_gi_4x:1; - uint16_t rx_bw_bitmap:5; - uint16_t tx_bw_bitmap:5; - uint16_t mcs_supported:3; - uint16_t nss_supported:3; + uint16_t tx_he_mcs_map_80_80; + uint16_t rx_he_mcs_map_80_80; + uint16_t tx_he_mcs_map_160; + uint16_t rx_he_mcs_map_160; + uint16_t tx_he_mcs_map_lt_80; + uint16_t rx_he_mcs_map_lt_80; #else uint32_t htc_he:1; uint32_t twt_request:1; @@ -2251,14 +2253,21 @@ struct he_capability_info { uint8_t er_he_ltf_800_gi_4x:1; uint8_t reserved3:7; - uint16_t nss_supported:3; - uint16_t mcs_supported:3; - uint16_t tx_bw_bitmap:5; - uint16_t rx_bw_bitmap:5; + uint16_t rx_he_mcs_map_lt_80; + uint16_t tx_he_mcs_map_lt_80; + uint16_t rx_he_mcs_map_160; + uint16_t tx_he_mcs_map_160; + uint16_t rx_he_mcs_map_80_80; + uint16_t tx_he_mcs_map_80_80; #endif } qdf_packed; #endif +/* + * frame parser does not include optional 160 and 80+80 mcs set for MIN IE len + */ +#define SIR_MAC_HE_CAP_MIN_LEN (DOT11F_IE_HE_CAP_MIN_LEN + 8) + /* QOS action frame definitions */ /* max number of possible tclas elements in any frame */ diff --git a/core/mac/inc/wni_cfg.h b/core/mac/inc/wni_cfg.h index 5ece58c37ae8..0ac55e981dc9 100644 --- a/core/mac/inc/wni_cfg.h +++ b/core/mac/inc/wni_cfg.h @@ -315,8 +315,12 @@ enum { WNI_CFG_HE_MAX_NC, WNI_CFG_HE_STBC_GT80, WNI_CFG_HE_ER_4x_LTF_GI, - WNI_CFG_HE_NSS, - WNI_CFG_HE_MCS, + WNI_CFG_HE_RX_MCS_MAP_LT_80, + WNI_CFG_HE_TX_MCS_MAP_LT_80, + WNI_CFG_HE_RX_MCS_MAP_160, + WNI_CFG_HE_TX_MCS_MAP_160, + WNI_CFG_HE_RX_MCS_MAP_80_80, + WNI_CFG_HE_TX_MCS_MAP_80_80, WNI_CFG_HE_PPET, WNI_CFG_PS_WOW_DATA_INACTIVITY_TIMEOUT, WNI_CFG_HE_STA_OBSSPD, @@ -1617,13 +1621,29 @@ enum { #define WNI_CFG_HE_ER_4x_LTF_GI_STAMAX 1 #define WNI_CFG_HE_ER_4x_LTF_GI_STADEF 0 -#define WNI_CFG_HE_NSS_STAMIN 0 -#define WNI_CFG_HE_NSS_STAMAX 0x7 -#define WNI_CFG_HE_NSS_STADEF 0 +#define WNI_CFG_HE_RX_MCS_MAP_LT_80_MIN 0x0000 +#define WNI_CFG_HE_RX_MCS_MAP_LT_80_MAX 0xFFFF +#define WNI_CFG_HE_RX_MCS_MAP_LT_80_DEF 0xFFF0 -#define WNI_CFG_HE_MCS_STAMIN 0 -#define WNI_CFG_HE_MCS_STAMAX 0x7 -#define WNI_CFG_HE_MCS_STADEF 0 +#define WNI_CFG_HE_TX_MCS_MAP_LT_80_MIN 0x0000 +#define WNI_CFG_HE_TX_MCS_MAP_LT_80_MAX 0xFFFF +#define WNI_CFG_HE_TX_MCS_MAP_LT_80_DEF 0xFFF0 + +#define WNI_CFG_HE_RX_MCS_MAP_160_MIN 0x0000 +#define WNI_CFG_HE_RX_MCS_MAP_160_MAX 0xFFFF +#define WNI_CFG_HE_RX_MCS_MAP_160_DEF 0xFFF0 + +#define WNI_CFG_HE_TX_MCS_MAP_160_MIN 0x0000 +#define WNI_CFG_HE_TX_MCS_MAP_160_MAX 0xFFFF +#define WNI_CFG_HE_TX_MCS_MAP_160_DEF 0xFFF0 + +#define WNI_CFG_HE_RX_MCS_MAP_80_80_MIN 0x0000 +#define WNI_CFG_HE_RX_MCS_MAP_80_80_MAX 0xFFFF +#define WNI_CFG_HE_RX_MCS_MAP_80_80_DEF 0xFFF0 + +#define WNI_CFG_HE_TX_MCS_MAP_80_80_MIN 0x0000 +#define WNI_CFG_HE_TX_MCS_MAP_80_80_MAX 0xFFFF +#define WNI_CFG_HE_TX_MCS_MAP_80_80_DEF 0xFFF0 #define WNI_CFG_HE_STA_OBSSPD_STAMIN 0 #define WNI_CFG_HE_STA_OBSSPD_STAMAX 0xffffffff diff --git a/core/mac/src/cfg/cfg_param_name.c b/core/mac/src/cfg/cfg_param_name.c index ab8d143723bc..0c574773a04f 100644 --- a/core/mac/src/cfg/cfg_param_name.c +++ b/core/mac/src/cfg/cfg_param_name.c @@ -324,8 +324,12 @@ const char *cfg_get_string(uint16_t cfg_id) CASE_RETURN_STRING(WNI_CFG_HE_MAX_NC); CASE_RETURN_STRING(WNI_CFG_HE_STBC_GT80); CASE_RETURN_STRING(WNI_CFG_HE_ER_4x_LTF_GI); - CASE_RETURN_STRING(WNI_CFG_HE_NSS); - CASE_RETURN_STRING(WNI_CFG_HE_MCS); + CASE_RETURN_STRING(WNI_CFG_HE_RX_MCS_MAP_LT_80); + CASE_RETURN_STRING(WNI_CFG_HE_TX_MCS_MAP_LT_80); + CASE_RETURN_STRING(WNI_CFG_HE_RX_MCS_MAP_160); + CASE_RETURN_STRING(WNI_CFG_HE_TX_MCS_MAP_160); + CASE_RETURN_STRING(WNI_CFG_HE_RX_MCS_MAP_80_80); + CASE_RETURN_STRING(WNI_CFG_HE_TX_MCS_MAP_80_80); CASE_RETURN_STRING(WNI_CFG_HE_PPET); CASE_RETURN_STRING(WNI_CFG_PS_WOW_DATA_INACTIVITY_TIMEOUT); CASE_RETURN_STRING(WNI_CFG_HE_STA_OBSSPD); diff --git a/core/mac/src/cfg/cfg_proc_msg.c b/core/mac/src/cfg/cfg_proc_msg.c index 23305c01cc94..ae63ffdc7ab5 100644 --- a/core/mac/src/cfg/cfg_proc_msg.c +++ b/core/mac/src/cfg/cfg_proc_msg.c @@ -1409,14 +1409,37 @@ cgstatic cfg_static[CFG_PARAM_MAX_NUM] = { 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, WNI_CFG_HE_ER_4x_LTF_GI_STADEF}, - {WNI_CFG_HE_NSS, + + {WNI_CFG_HE_RX_MCS_MAP_LT_80, CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, - WNI_CFG_HE_NSS_STAMIN, WNI_CFG_HE_NSS_STAMAX, - WNI_CFG_HE_NSS_STADEF}, - {WNI_CFG_HE_MCS, + WNI_CFG_HE_RX_MCS_MAP_LT_80_MIN, WNI_CFG_HE_RX_MCS_MAP_LT_80_MAX, + WNI_CFG_HE_RX_MCS_MAP_LT_80_DEF}, + + {WNI_CFG_HE_TX_MCS_MAP_LT_80, CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, - WNI_CFG_HE_MCS_STAMIN, WNI_CFG_HE_MCS_STAMAX, - WNI_CFG_HE_MCS_STADEF}, + WNI_CFG_HE_TX_MCS_MAP_LT_80_MIN, WNI_CFG_HE_TX_MCS_MAP_LT_80_MAX, + WNI_CFG_HE_TX_MCS_MAP_LT_80_DEF}, + + {WNI_CFG_HE_RX_MCS_MAP_160, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_HE_RX_MCS_MAP_160_MIN, WNI_CFG_HE_RX_MCS_MAP_160_MAX, + WNI_CFG_HE_RX_MCS_MAP_160_DEF}, + + {WNI_CFG_HE_TX_MCS_MAP_160, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_HE_TX_MCS_MAP_160_MIN, WNI_CFG_HE_TX_MCS_MAP_160_MAX, + WNI_CFG_HE_TX_MCS_MAP_160_DEF}, + + {WNI_CFG_HE_RX_MCS_MAP_80_80, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_HE_RX_MCS_MAP_80_80_MIN, WNI_CFG_HE_RX_MCS_MAP_80_80_MAX, + WNI_CFG_HE_RX_MCS_MAP_80_80_DEF}, + + {WNI_CFG_HE_TX_MCS_MAP_80_80, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_HE_TX_MCS_MAP_80_80_MIN, WNI_CFG_HE_TX_MCS_MAP_80_80_MAX, + WNI_CFG_HE_TX_MCS_MAP_80_80_DEF}, + {WNI_CFG_HE_PPET, CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE, 0, 0, 0}, diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index e895a8016571..39c0f6722fec 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -1778,7 +1778,7 @@ lim_populate_peer_rate_set(tpAniSirGlobal pMac, psessionEntry, psessionEntry->nss); if (IS_DOT11_MODE_HE(psessionEntry->dot11mode) && he_caps) { - psessionEntry->nss = he_caps->nss_supported; + HE_GET_NSS(he_caps->rx_he_mcs_map_lt_80, psessionEntry->nss); } else if (IS_DOT11_MODE_VHT(psessionEntry->dot11mode)) { if ((pRates->vhtRxMCSMap & MCSMAPMASK2x2) == MCSMAPMASK2x2) psessionEntry->nss = NSS_1x1_MODE; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 10bcdd0c553a..3614e37460b7 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1726,11 +1726,6 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) session->vht_config.su_beam_former); } - if (IS_DOT11_MODE_HE(session->dot11mode)) { - lim_update_session_he_capable(mac_ctx, session); - lim_copy_join_req_he_cap(session, sme_join_req); - } - pe_debug("vhtCapability: %d su_beam_formee: %d txbf_csn_value: %d su_tx_bformer %d", session->vhtCapability, session->vht_config.su_beam_formee, @@ -1763,6 +1758,12 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) session->ch_width = CH_WIDTH_20MHZ; } + if (IS_DOT11_MODE_HE(session->dot11mode)) { + lim_update_session_he_capable(mac_ctx, session); + lim_copy_join_req_he_cap(session, sme_join_req); + } + + /* Record if management frames need to be protected */ #ifdef WLAN_FEATURE_11W if (eSIR_ED_AES_128_CMAC == sme_join_req->MgmtEncryptionType) diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 3d78075d9ead..5466bff3618c 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -7388,10 +7388,23 @@ void lim_copy_join_req_he_cap(tpPESession session, { qdf_mem_copy(&(session->he_config), &(sme_join_req->he_config), sizeof(session->he_config)); + + if (session->ch_width <= CH_WIDTH_80MHZ) { + *(uint16_t *)session->he_config.rx_he_mcs_map_160 = + HE_MCS_ALL_DISABLED; + *(uint16_t *)session->he_config.tx_he_mcs_map_160 = + HE_MCS_ALL_DISABLED; + *(uint16_t *)session->he_config.rx_he_mcs_map_80_80 = + HE_MCS_ALL_DISABLED; + *(uint16_t *)session->he_config.tx_he_mcs_map_80_80 = + HE_MCS_ALL_DISABLED; + } } void lim_log_he_cap(tpAniSirGlobal mac, tDot11fIEhe_cap *he_cap) { + uint8_t chan_width; + if (!he_cap->present) return; @@ -7448,8 +7461,12 @@ void lim_log_he_cap(tpAniSirGlobal mac, tDot11fIEhe_cap *he_cap) /* HE PHY capabilities */ pe_debug("\tDual band support: 0x%01x", he_cap->dual_band); - pe_debug("\tChannel width support: 0x%07x", - he_cap->chan_width); + chan_width = HE_CH_WIDTH_COMBINE(he_cap->chan_width_0, + he_cap->chan_width_1, he_cap->chan_width_2, + he_cap->chan_width_3, he_cap->chan_width_4, + he_cap->chan_width_5, he_cap->chan_width_6); + + pe_debug("\tChannel width support: 0x%07x", chan_width); pe_debug("\tPreamble puncturing Rx: 0x%04x", he_cap->rx_pream_puncturing); pe_debug("\tClass of device: 0x%01x", he_cap->device_class); @@ -7501,12 +7518,18 @@ void lim_log_he_cap(tpAniSirGlobal mac, tDot11fIEhe_cap *he_cap) 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("\tHighest NSS supported: 0x%03x", - he_cap->nss_supported); - pe_debug("\tHighest MCS supported: 0x%03x", - he_cap->mcs_supported); - pe_debug("\tTX BW bitmap: 0x%05x", he_cap->tx_bw_bitmap); - pe_debug("\tRX BW bitmap: 0x%05x ", he_cap->rx_bw_bitmap); + pe_debug("\tRx MCS map for <= 80 Mhz: 0x%04x", + he_cap->rx_he_mcs_map_lt_80); + pe_debug("\tTx MCS map for <= 80 Mhz: 0x%04x", + he_cap->tx_he_mcs_map_lt_80); + pe_debug("\tRx MCS map for <= 160 Mhz: 0x%04x", + *((uint16_t *)he_cap->rx_he_mcs_map_160)); + pe_debug("\tTx MCS map for <= 160 Mhz: 0x%04x", + *((uint16_t *)he_cap->tx_he_mcs_map_160)); + pe_debug("\tRx MCS map for <= 80+80 Mhz: 0x%04x", + *((uint16_t *)he_cap->rx_he_mcs_map_80_80)); + pe_debug("\tTx MCS map for <= 80+80 Mhz: 0x%04x", + *((uint16_t *)he_cap->tx_he_mcs_map_80_80)); /* HE PPET */ if (!he_cap->ppet_present) @@ -7630,7 +7653,12 @@ void lim_set_he_caps(tpAniSirGlobal mac, tpPESession session, uint8_t *ie_start, he_cap->reserved1 = dot11_cap.reserved1; he_cap->dual_band = dot11_cap.dual_band; - he_cap->chan_width = dot11_cap.chan_width; + + he_cap->chan_width = HE_CH_WIDTH_COMBINE(dot11_cap.chan_width_0, + dot11_cap.chan_width_1, dot11_cap.chan_width_2, + dot11_cap.chan_width_3, dot11_cap.chan_width_4, + dot11_cap.chan_width_5, dot11_cap.chan_width_6); + he_cap->rx_pream_puncturing = dot11_cap.rx_pream_puncturing; he_cap->device_class = dot11_cap.device_class; he_cap->ldpc_coding = dot11_cap.ldpc_coding; @@ -7667,40 +7695,46 @@ void lim_set_he_caps(tpAniSirGlobal mac, tpPESession session, uint8_t *ie_start, he_cap->er_he_ltf_800_gi_4x = dot11_cap.er_he_ltf_800_gi_4x; he_cap->reserved2 = dot11_cap.reserved2; - he_cap->nss_supported = dot11_cap.nss_supported; - he_cap->mcs_supported = dot11_cap.mcs_supported; - he_cap->tx_bw_bitmap = dot11_cap.tx_bw_bitmap; - he_cap->rx_bw_bitmap = dot11_cap.rx_bw_bitmap; + he_cap->rx_he_mcs_map_lt_80 = dot11_cap.rx_he_mcs_map_lt_80; + he_cap->tx_he_mcs_map_lt_80 = dot11_cap.tx_he_mcs_map_lt_80; + he_cap->rx_he_mcs_map_160 = + *((uint16_t *)dot11_cap.rx_he_mcs_map_160); + he_cap->tx_he_mcs_map_160 = + *((uint16_t *)dot11_cap.tx_he_mcs_map_160); + he_cap->rx_he_mcs_map_80_80 = + *((uint16_t *)dot11_cap.rx_he_mcs_map_80_80); + he_cap->tx_he_mcs_map_80_80 = + *((uint16_t *)dot11_cap.tx_he_mcs_map_80_80); } } QDF_STATUS lim_send_he_caps_ie(tpAniSirGlobal mac_ctx, tpPESession session, uint8_t vdev_id) { - uint8_t he_caps[DOT11F_IE_HE_CAP_MIN_LEN + 3]; + uint8_t he_caps[SIR_MAC_HE_CAP_MIN_LEN + 3]; struct he_capability_info *he_cap; QDF_STATUS status_5g, status_2g; /* Sending only minimal info(no PPET) to FW now, update if required */ - qdf_mem_zero(he_caps, DOT11F_IE_HE_CAP_MIN_LEN + 3); + qdf_mem_zero(he_caps, SIR_MAC_HE_CAP_MIN_LEN + 3); he_caps[0] = DOT11F_EID_HE_CAP; - he_caps[1] = DOT11F_IE_HE_CAP_MIN_LEN; + he_caps[1] = SIR_MAC_HE_CAP_MIN_LEN; qdf_mem_copy(&he_caps[2], HE_CAP_OUI_TYPE, HE_CAP_OUI_SIZE); lim_set_he_caps(mac_ctx, session, he_caps, - DOT11F_IE_HE_CAP_MIN_LEN + 3); + SIR_MAC_HE_CAP_MIN_LEN + 3); he_cap = (struct he_capability_info *) (&he_caps[2 + HE_CAP_OUI_SIZE]); he_cap->ppet_present = 0; status_5g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_HE_CAP, CDS_BAND_5GHZ, &he_caps[2], - DOT11F_IE_HE_CAP_MIN_LEN + 1); + SIR_MAC_HE_CAP_MIN_LEN + 1); if (QDF_IS_STATUS_ERROR(status_5g)) pe_err("Unable send HE Cap IE for 5GHZ band, status: %d", status_5g); status_2g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_HE_CAP, CDS_BAND_2GHZ, &he_caps[2], - DOT11F_IE_HE_CAP_MIN_LEN + 1); + SIR_MAC_HE_CAP_MIN_LEN + 1); if (QDF_IS_STATUS_ERROR(status_2g)) pe_err("Unable send HE Cap IE for 2GHZ band, status: %d", status_2g); @@ -7713,64 +7747,88 @@ QDF_STATUS lim_send_he_caps_ie(tpAniSirGlobal mac_ctx, tpPESession session, } /** - * MCS-NSS Map will be as follows - Each MCS is 3 bits - * - 0 indicates support for HE-MCS 0-7 for n spatial streams - * - 1 indicates support for HE-MCS 0-8 for n spatial streams - * - 2 indicates support for HE-MCS 0-9 for n spatial streams - * - 3 indicates support for HE-MCS 0-10 for n spatial streams - * - 4 indicates support for HE-MCS 0-11 for n spatial streams - * - 5-6 reserved - * - 7 indicates that n spatial streams is not supported - * +-----+-----+-----+-----+-----+-----+-----+-----+-----+- - * | SS | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | - * +-----+-----+-----+-----+-----+-----+-----+-----+-----+ - * | MCS | 7 | 7 | 7 | 7 | 7 | 7 | 4 | 4 | - * +-----+-----+-----+-----+-----+-----+-----+-----+-----+ + * lim_populate_he_mcs_per_bw() - pouldate HE mcs set per BW (le 80, 160, 80+80) + * @mac_ctx: Global MAC context + * @self_rx: self rx mcs set + * @self_tx: self tx mcs set + * @peer_rx: peer rx mcs set + * @peer_tx: peer tx mcs set + * @nss: nss + * @cfg_rx_param: rx wni param to read + * @cfg_tx_param: tx wni param to read + * + * MCS values are interpreted as in IEEE 11ax-D1.4 spec onwards + * +-----------------------------------------------------+ + * | SS8 | SS7 | SS6 | SS5 | SS4 | SS3 | SS2 | SS1 | + * +-----------------------------------------------------+ + * | 15-14 | 13-12 | 11-10 | 9-8 | 7-6 | 5-4 | 3-2 | 1-0 | + * +-----------------------------------------------------+ + * + * Return: status of operation */ +static QDF_STATUS lim_populate_he_mcs_per_bw(tpAniSirGlobal mac_ctx, + uint16_t *self_rx, uint16_t *self_tx, + uint16_t peer_rx, uint16_t peer_tx, uint8_t nss, + uint32_t cfg_rx_param, uint32_t cfg_tx_param) +{ + uint32_t val; + + pe_debug("peer rates: rx_mcs - 0x%04x tx_mcs - 0x%04x", + peer_rx, peer_tx); + if (wlan_cfg_get_int(mac_ctx, cfg_rx_param, &val) != eSIR_SUCCESS) { + pe_err("could not retrieve HE_MCS"); + return QDF_STATUS_E_FAILURE; + } + *self_rx = (uint16_t) val; + if (wlan_cfg_get_int(mac_ctx, cfg_tx_param, &val) != eSIR_SUCCESS) { + pe_err("could not retrieve HE_MCS"); + return QDF_STATUS_E_FAILURE; + } + *self_tx = (uint16_t) val; + + *self_rx = HE_INTERSECT_MCS(*self_rx, peer_tx); + *self_tx = HE_INTERSECT_MCS(*self_tx, peer_rx); + + if (nss == NSS_1x1_MODE) { + *self_rx |= HE_MCS_INV_MSK_4_NSS(1); + *self_tx |= HE_MCS_INV_MSK_4_NSS(1); + } + /* if nss is 2, disable higher NSS */ + if (nss == NSS_2x2_MODE) { + *self_rx |= (HE_MCS_INV_MSK_4_NSS(1) & HE_MCS_INV_MSK_4_NSS(2)); + *self_tx |= (HE_MCS_INV_MSK_4_NSS(1) & HE_MCS_INV_MSK_4_NSS(2)); + } + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS lim_populate_he_mcs_set(tpAniSirGlobal mac_ctx, tpSirSupportedRates rates, tDot11fIEhe_cap *peer_he_caps, tpPESession session_entry, uint8_t nss) { - uint32_t val; - uint32_t self_sta_dot11mode = 0; - uint8_t self_mcs, peer_mcs, negotiated_mcs; - uint32_t mcsmap = 0xFFFFFFFF; bool support_2x2 = false; + uint32_t self_sta_dot11mode = 0; wlan_cfg_get_int(mac_ctx, WNI_CFG_DOT11_MODE, &self_sta_dot11mode); if (!IS_DOT11_MODE_HE(self_sta_dot11mode)) return QDF_STATUS_SUCCESS; - if (wlan_cfg_get_int(mac_ctx, WNI_CFG_HE_MCS, &val) != eSIR_SUCCESS) { - pe_err("could not retrieve HE_MCS"); - goto error; - } - - self_mcs = (uint16_t) val; - if (NSS_1x1_MODE == nss) { - /* Add MCS for SS-1 */ - mcsmap = self_mcs; - mcsmap |= HE_MCS_1x1; - } else if (NSS_2x2_MODE == nss) { - /* Add MCS for SS-1 */ - mcsmap = self_mcs; - /* Add MCS for SS-2 */ - mcsmap |= (self_mcs << HEMCSSIZE); - mcsmap |= HE_MCS_2x2; - - } - rates->he_rx_mcs = rates->he_tx_mcs = mcsmap; - if ((peer_he_caps == NULL) || (!peer_he_caps->present)) { - pe_debug("self rate: nss %d he_rx_mcs - %x he_tx_mcs - %x", - nss, rates->he_rx_mcs, rates->he_tx_mcs); + pe_debug("peer not he capable or he_caps NULL"); return QDF_STATUS_SUCCESS; } - pe_debug("peer rates: rx_mcs - %x tx_mcs - %x", - peer_he_caps->mcs_supported, peer_he_caps->mcs_supported); + pe_debug("peer rates lt 80: rx_mcs - 0x%04x tx_mcs - 0x%04x", + peer_he_caps->rx_he_mcs_map_lt_80, + peer_he_caps->tx_he_mcs_map_lt_80); + pe_debug("peer rates 160: rx_mcs - 0x%04x tx_mcs - 0x%04x", + (*(uint16_t *)peer_he_caps->rx_he_mcs_map_160), + (*(uint16_t *)peer_he_caps->tx_he_mcs_map_160)); + pe_debug("peer rates 80+80: rx_mcs - 0x%04x tx_mcs - 0x%04x", + (*(uint16_t *)peer_he_caps->rx_he_mcs_map_80_80), + (*(uint16_t *)peer_he_caps->tx_he_mcs_map_80_80)); if (session_entry && session_entry->nss == NSS_2x2_MODE) { if (mac_ctx->lteCoexAntShare && @@ -7785,29 +7843,40 @@ QDF_STATUS lim_populate_he_mcs_set(tpAniSirGlobal mac_ctx, } } - peer_mcs = peer_he_caps->mcs_supported; - negotiated_mcs = QDF_MIN(peer_mcs, self_mcs); - - if (support_2x2) { - /* Add MCS for SS-1 */ - mcsmap = negotiated_mcs; - /* Add MCS for SS-2 */ - mcsmap |= (negotiated_mcs << HEMCSSIZE); - mcsmap |= HE_MCS_2x2; - } else { - /* Add MCS for SS-1 */ - mcsmap = negotiated_mcs; - mcsmap |= HE_MCS_1x1; + lim_populate_he_mcs_per_bw(mac_ctx, + &rates->rx_he_mcs_map_lt_80, &rates->tx_he_mcs_map_lt_80, + peer_he_caps->rx_he_mcs_map_lt_80, + peer_he_caps->tx_he_mcs_map_lt_80, nss, + WNI_CFG_HE_RX_MCS_MAP_LT_80, WNI_CFG_HE_TX_MCS_MAP_LT_80); + lim_populate_he_mcs_per_bw(mac_ctx, + &rates->rx_he_mcs_map_160, &rates->tx_he_mcs_map_160, + *((uint16_t *)peer_he_caps->rx_he_mcs_map_160), + *((uint16_t *)peer_he_caps->tx_he_mcs_map_160), nss, + WNI_CFG_HE_RX_MCS_MAP_160, WNI_CFG_HE_TX_MCS_MAP_160); + lim_populate_he_mcs_per_bw(mac_ctx, + &rates->rx_he_mcs_map_80_80, &rates->tx_he_mcs_map_80_80, + *((uint16_t *)peer_he_caps->rx_he_mcs_map_80_80), + *((uint16_t *)peer_he_caps->tx_he_mcs_map_80_80), nss, + WNI_CFG_HE_RX_MCS_MAP_80_80, WNI_CFG_HE_TX_MCS_MAP_80_80); + if (!support_2x2) { + /* disable 2 and higher NSS MCS sets */ + rates->rx_he_mcs_map_lt_80 |= 0xFFFD; + rates->tx_he_mcs_map_lt_80 |= 0xFFFD; + rates->rx_he_mcs_map_160 |= 0xFFFD; + rates->tx_he_mcs_map_160 |= 0xFFFD; + rates->rx_he_mcs_map_80_80 |= 0xFFFD; + rates->tx_he_mcs_map_80_80 |= 0xFFFD; } - rates->he_rx_mcs = rates->he_tx_mcs = mcsmap; - - pe_debug("enable2x2 - %d nss %d he_rx_mcs - %x he_tx_mcs - %x", - mac_ctx->roam.configParam.enable2x2, nss, - rates->he_rx_mcs, rates->he_tx_mcs); + pe_debug("enable2x2 - %d nss %d", + mac_ctx->roam.configParam.enable2x2, nss); + pe_debug("he_rx_lt_80 - 0x%x he_tx_lt_80 0x%x", + rates->rx_he_mcs_map_lt_80, rates->tx_he_mcs_map_lt_80); + pe_debug("he_rx_160 - 0x%x he_tx_160 0x%x", + rates->rx_he_mcs_map_160, rates->tx_he_mcs_map_160); + pe_debug("he_rx_80_80 - 0x%x he_tx_80_80 0x%x", + rates->rx_he_mcs_map_80_80, rates->tx_he_mcs_map_80_80); return QDF_STATUS_SUCCESS; -error: - return QDF_STATUS_E_FAILURE; } #endif diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index 01441cd4fbe4..224de2df0df9 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -855,6 +855,7 @@ void lim_copy_bss_he_cap(tpPESession session, /** * lim_copy_join_req_he_cap() - Copy HE capability to PE session from Join req + * and update as per bandwidth supported * @session: pointer to PE session * @sme_join_req: pointer to SME join request * diff --git a/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/core/mac/src/sys/legacy/src/utils/src/parser_api.c index 9692d52c96b7..63578cef0160 100644 --- a/core/mac/src/sys/legacy/src/utils/src/parser_api.c +++ b/core/mac/src/sys/legacy/src/utils/src/parser_api.c @@ -6118,7 +6118,14 @@ QDF_STATUS populate_dot11f_he_caps(tpAniSirGlobal mac_ctx, tpPESession session, CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_DUAL_BAND, value); he_cap->dual_band = value; CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_CHAN_WIDTH, value); - he_cap->chan_width = value; + he_cap->chan_width_0 = HE_CH_WIDTH_GET_BIT(value, 0); + he_cap->chan_width_1 = HE_CH_WIDTH_GET_BIT(value, 1); + he_cap->chan_width_2 = HE_CH_WIDTH_GET_BIT(value, 2); + he_cap->chan_width_3 = HE_CH_WIDTH_GET_BIT(value, 3); + he_cap->chan_width_4 = HE_CH_WIDTH_GET_BIT(value, 4); + he_cap->chan_width_5 = HE_CH_WIDTH_GET_BIT(value, 5); + he_cap->chan_width_6 = HE_CH_WIDTH_GET_BIT(value, 6); + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_RX_PREAM_PUNC, value); he_cap->rx_pream_puncturing = value; CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_CLASS_OF_DEVICE, value); @@ -6183,10 +6190,23 @@ QDF_STATUS populate_dot11f_he_caps(tpAniSirGlobal mac_ctx, tpPESession session, he_cap->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, WNI_CFG_HE_NSS, value); - he_cap->nss_supported = value; - CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_MCS, value); - he_cap->mcs_supported = value; + + CFG_GET_INT(status, mac_ctx, + WNI_CFG_HE_RX_MCS_MAP_LT_80, value); + he_cap->rx_he_mcs_map_lt_80 = value; + CFG_GET_INT(status, mac_ctx, + WNI_CFG_HE_TX_MCS_MAP_LT_80, value); + he_cap->tx_he_mcs_map_lt_80 = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_RX_MCS_MAP_160, value); + *((uint16_t *)he_cap->rx_he_mcs_map_160) = value; + CFG_GET_INT(status, mac_ctx, WNI_CFG_HE_TX_MCS_MAP_160, value); + *((uint16_t *)he_cap->tx_he_mcs_map_160) = value; + CFG_GET_INT(status, mac_ctx, + WNI_CFG_HE_RX_MCS_MAP_80_80, value); + *((uint16_t *)he_cap->rx_he_mcs_map_80_80) = value; + CFG_GET_INT(status, mac_ctx, + WNI_CFG_HE_TX_MCS_MAP_80_80, value); + *((uint16_t *)he_cap->tx_he_mcs_map_80_80) = value; if (he_cap->ppet_present) { value = WNI_CFG_HE_PPET_LEN; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 6e8ebf2f026b..d7dd5598592b 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -2329,7 +2329,14 @@ static void csr_update_session_he_cap(tpAniSirGlobal mac_ctx, sme_cfg_get_int(mac_ctx, WNI_CFG_HE_DUAL_BAND, &value); he_cap->dual_band = value; sme_cfg_get_int(mac_ctx, WNI_CFG_HE_CHAN_WIDTH, &value); - he_cap->chan_width = value; + he_cap->chan_width_0 = HE_CH_WIDTH_GET_BIT(value, 0); + he_cap->chan_width_1 = HE_CH_WIDTH_GET_BIT(value, 1); + he_cap->chan_width_2 = HE_CH_WIDTH_GET_BIT(value, 2); + he_cap->chan_width_3 = HE_CH_WIDTH_GET_BIT(value, 3); + he_cap->chan_width_4 = HE_CH_WIDTH_GET_BIT(value, 4); + he_cap->chan_width_5 = HE_CH_WIDTH_GET_BIT(value, 5); + he_cap->chan_width_6 = HE_CH_WIDTH_GET_BIT(value, 6); + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_RX_PREAM_PUNC, &value); he_cap->rx_pream_puncturing = value; sme_cfg_get_int(mac_ctx, WNI_CFG_HE_CLASS_OF_DEVICE, &value); @@ -2394,10 +2401,19 @@ static void csr_update_session_he_cap(tpAniSirGlobal mac_ctx, he_cap->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_NSS, &value); - he_cap->nss_supported = value; - sme_cfg_get_int(mac_ctx, WNI_CFG_HE_MCS, &value); - he_cap->mcs_supported = value; + + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_RX_MCS_MAP_LT_80, &value); + he_cap->rx_he_mcs_map_lt_80 = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_TX_MCS_MAP_LT_80, &value); + he_cap->tx_he_mcs_map_lt_80 = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_RX_MCS_MAP_160, &value); + *((uint16_t *)he_cap->rx_he_mcs_map_160) = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_TX_MCS_MAP_160, &value); + *((uint16_t *)he_cap->tx_he_mcs_map_160) = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_RX_MCS_MAP_80_80, &value); + *((uint16_t *)he_cap->rx_he_mcs_map_80_80) = value; + sme_cfg_get_int(mac_ctx, WNI_CFG_HE_TX_MCS_MAP_80_80, &value); + *((uint16_t *)he_cap->tx_he_mcs_map_80_80) = value; if (he_cap->ppet_present) { value = WNI_CFG_HE_PPET_LEN; diff --git a/core/wma/src/wma_he.c b/core/wma/src/wma_he.c index c434a045bee5..da69cc8317e3 100644 --- a/core/wma/src/wma_he.c +++ b/core/wma/src/wma_he.c @@ -194,21 +194,14 @@ static void wma_convert_he_cap(tDot11fIEhe_cap *he_cap, uint32_t mac_cap, uint32_t supp_mcs, uint32_t tx_chain_mask, uint32_t rx_chain_mask) { + uint8_t nss, chan_width; + uint16_t rx_mcs_le_80, tx_mcs_le_80, rx_mcs_160, tx_mcs_160; struct wmi_host_ppe_threshold *ppet = he_ppet; - uint8_t mcs, nss, k, mcs_temp; nss = QDF_MAX(wma_get_num_of_setbits_from_bitmask(tx_chain_mask), - wma_get_num_of_setbits_from_bitmask(rx_chain_mask)); - - mcs = 0; - for (k = 1; k < nss; k++) { - mcs_temp = WMI_HE_MAX_MCS_4_SS_MASK(supp_mcs, k); - if (mcs_temp > mcs) - mcs = mcs_temp; - } + wma_get_num_of_setbits_from_bitmask(rx_chain_mask)); he_cap->present = true; - /* HE MAC capabilities */ he_cap->htc_he = WMI_HECAP_MAC_HECTRL_GET(mac_cap); he_cap->twt_request = WMI_HECAP_MAC_TWTREQ_GET(mac_cap); @@ -242,7 +235,14 @@ static void wma_convert_he_cap(tDot11fIEhe_cap *he_cap, uint32_t mac_cap, /* HE PHY capabilities */ he_cap->dual_band = WMI_HECAP_PHY_DB_GET(phy_cap); - he_cap->chan_width = WMI_HECAP_PHY_CBW_GET(phy_cap); + chan_width = WMI_HECAP_PHY_CBW_GET(phy_cap); + he_cap->chan_width_0 = HE_CH_WIDTH_GET_BIT(chan_width, 0); + he_cap->chan_width_1 = HE_CH_WIDTH_GET_BIT(chan_width, 1); + he_cap->chan_width_2 = HE_CH_WIDTH_GET_BIT(chan_width, 2); + he_cap->chan_width_3 = HE_CH_WIDTH_GET_BIT(chan_width, 3); + he_cap->chan_width_4 = HE_CH_WIDTH_GET_BIT(chan_width, 4); + he_cap->chan_width_5 = HE_CH_WIDTH_GET_BIT(chan_width, 5); + he_cap->chan_width_6 = HE_CH_WIDTH_GET_BIT(chan_width, 6); he_cap->rx_pream_puncturing = WMI_HECAP_PHY_PREAMBLEPUNCRX_GET(phy_cap); he_cap->device_class = WMI_HECAP_PHY_COD_GET(phy_cap); he_cap->ldpc_coding = WMI_HECAP_PHY_LDPC_GET(phy_cap); @@ -287,12 +287,28 @@ static void wma_convert_he_cap(tDot11fIEhe_cap *he_cap, uint32_t mac_cap, he_cap->er_he_ltf_800_gi_4x = WMI_HECAP_PHY_ERSU4X800NSECGI_GET(phy_cap); - he_cap->nss_supported = nss - 1; - he_cap->mcs_supported = mcs; - - /* For Draft 1.0, following fields will be zero */ - he_cap->tx_bw_bitmap = 0; - he_cap->rx_bw_bitmap = 0; + /* + * supp_mcs is split into 16 bits with lower indicating le_80 and + * upper indicating 160 and 80_80. + */ + WMA_LOGD(FL("supported_mcs: 0x%08x\n"), supp_mcs); + rx_mcs_le_80 = supp_mcs & 0xFFFF; + tx_mcs_le_80 = supp_mcs & 0xFFFF; + rx_mcs_160 = (supp_mcs & 0xFFFF0000) >> 16; + tx_mcs_160 = (supp_mcs & 0xFFFF0000) >> 16; + /* if FW indicated it is using 1x1 disable upper NSS-MCS sets */ + if (nss == NSS_1x1_MODE) { + rx_mcs_le_80 |= HE_MCS_INV_MSK_4_NSS(1); + tx_mcs_le_80 |= HE_MCS_INV_MSK_4_NSS(1); + rx_mcs_160 |= HE_MCS_INV_MSK_4_NSS(1); + tx_mcs_160 |= HE_MCS_INV_MSK_4_NSS(1); + } + he_cap->rx_he_mcs_map_lt_80 = rx_mcs_le_80; + he_cap->tx_he_mcs_map_lt_80 = tx_mcs_le_80; + *((uint16_t *)he_cap->tx_he_mcs_map_160) = rx_mcs_160; + *((uint16_t *)he_cap->rx_he_mcs_map_160) = tx_mcs_160; + *((uint16_t *)he_cap->rx_he_mcs_map_80_80) = rx_mcs_160; + *((uint16_t *)he_cap->tx_he_mcs_map_80_80) = tx_mcs_160; wma_convert_he_ppet(&he_cap->ppe_threshold, ppet); } @@ -313,6 +329,8 @@ static void wma_convert_he_cap(tDot11fIEhe_cap *he_cap, uint32_t mac_cap, static void wma_derive_ext_he_cap(t_wma_handle *wma_handle, tDot11fIEhe_cap *he_cap, tDot11fIEhe_cap *new_cap) { + uint16_t mcs_1, mcs_2; + if (!he_cap->present) { /* First time update, copy the capability as is */ qdf_mem_copy(he_cap, new_cap, sizeof(*he_cap)); @@ -375,8 +393,22 @@ static void wma_derive_ext_he_cap(t_wma_handle *wma_handle, he_cap->dual_band = QDF_MIN(he_cap->dual_band, new_cap->dual_band); - he_cap->chan_width = QDF_MIN(he_cap->chan_width, - new_cap->chan_width); + + he_cap->chan_width_0 = he_cap->chan_width_0 & + new_cap->chan_width_0; + he_cap->chan_width_1 = he_cap->chan_width_1 & + new_cap->chan_width_1; + he_cap->chan_width_2 = he_cap->chan_width_2 & + new_cap->chan_width_2; + he_cap->chan_width_3 = he_cap->chan_width_3 & + new_cap->chan_width_3; + he_cap->chan_width_4 = he_cap->chan_width_4 & + new_cap->chan_width_4; + he_cap->chan_width_5 = he_cap->chan_width_5 & + new_cap->chan_width_5; + he_cap->chan_width_6 = he_cap->chan_width_6 & + new_cap->chan_width_6; + he_cap->rx_pream_puncturing = QDF_MIN(he_cap->rx_pream_puncturing, new_cap->rx_pream_puncturing); @@ -438,20 +470,37 @@ static void wma_derive_ext_he_cap(t_wma_handle *wma_handle, new_cap->he_ltf_800_gi_4x); he_cap->reserved2 = QDF_MIN(he_cap->reserved2, new_cap->reserved2); - he_cap->nss_supported = QDF_MIN(he_cap->nss_supported, - new_cap->nss_supported); - he_cap->mcs_supported = QDF_MIN(he_cap->mcs_supported, - new_cap->mcs_supported); - he_cap->tx_bw_bitmap = QDF_MIN(he_cap->tx_bw_bitmap, - new_cap->tx_bw_bitmap); - he_cap->rx_bw_bitmap = QDF_MIN(he_cap->rx_bw_bitmap, - new_cap->rx_bw_bitmap); + /* take intersection for MCS map */ + mcs_1 = he_cap->rx_he_mcs_map_lt_80; + mcs_2 = new_cap->rx_he_mcs_map_lt_80; + he_cap->rx_he_mcs_map_lt_80 = HE_INTERSECT_MCS(mcs_1, mcs_2); + mcs_1 = he_cap->tx_he_mcs_map_lt_80; + mcs_2 = new_cap->tx_he_mcs_map_lt_80; + he_cap->tx_he_mcs_map_lt_80 = HE_INTERSECT_MCS(mcs_1, mcs_2); + mcs_1 = *((uint16_t *)he_cap->rx_he_mcs_map_160); + mcs_2 = *((uint16_t *)new_cap->rx_he_mcs_map_160); + *((uint16_t *)he_cap->rx_he_mcs_map_160) = + HE_INTERSECT_MCS(mcs_1, mcs_2); + mcs_1 = *((uint16_t *)he_cap->tx_he_mcs_map_160); + mcs_2 = *((uint16_t *)new_cap->tx_he_mcs_map_160); + *((uint16_t *)he_cap->tx_he_mcs_map_160) = + HE_INTERSECT_MCS(mcs_1, mcs_2); + mcs_1 = *((uint16_t *)he_cap->rx_he_mcs_map_80_80); + mcs_2 = *((uint16_t *)new_cap->rx_he_mcs_map_80_80); + *((uint16_t *)he_cap->rx_he_mcs_map_80_80) = + HE_INTERSECT_MCS(mcs_1, mcs_2); + mcs_1 = *((uint16_t *)he_cap->tx_he_mcs_map_80_80); + mcs_2 = *((uint16_t *)new_cap->tx_he_mcs_map_80_80); + *((uint16_t *)he_cap->tx_he_mcs_map_80_80) = + HE_INTERSECT_MCS(mcs_1, mcs_2); } } void wma_print_he_cap(tDot11fIEhe_cap *he_cap) { + uint8_t chan_width; + if (!he_cap->present) { WMA_LOGI(FL("HE Capabilities not present")); return; @@ -491,7 +540,12 @@ void wma_print_he_cap(tDot11fIEhe_cap *he_cap) /* HE PHY capabilities */ WMA_LOGD("\tDual band support: 0x%01x", he_cap->dual_band); - WMA_LOGD("\tChannel width support: 0x%07x", he_cap->chan_width); + chan_width = HE_CH_WIDTH_COMBINE(he_cap->chan_width_0, + he_cap->chan_width_1, he_cap->chan_width_2, + he_cap->chan_width_3, he_cap->chan_width_4, + he_cap->chan_width_5, he_cap->chan_width_6); + + WMA_LOGD("\tChannel width support: 0x%07x", chan_width); WMA_LOGD("\tPreamble puncturing Rx: 0x%04x", he_cap->rx_pream_puncturing); WMA_LOGD("\tClass of device: 0x%01x", he_cap->device_class); @@ -532,10 +586,18 @@ void wma_print_he_cap(tDot11fIEhe_cap *he_cap) WMA_LOGD("\tPower boost factor: 0x%01x", he_cap->power_boost); WMA_LOGD("\t4x HE LTF support: 0x%01x", he_cap->he_ltf_800_gi_4x); - WMA_LOGD("\tHighest NSS supported: 0x%03x", he_cap->nss_supported); - WMA_LOGD("\tHighest MCS supported: 0x%03x", he_cap->mcs_supported); - WMA_LOGD("\tTX BW bitmap: 0x%05x", he_cap->tx_bw_bitmap); - WMA_LOGD("\tRX BW bitmap: 0x%05x ", he_cap->rx_bw_bitmap); + WMA_LOGD("\tRx MCS MAP for BW <= 80 MHz: 0x%x", + he_cap->rx_he_mcs_map_lt_80); + WMA_LOGD("\tTx MCS MAP for BW <= 80 MHz: 0x%x", + he_cap->tx_he_mcs_map_lt_80); + WMA_LOGD("\tRx MCS MAP for BW = 160 MHz: 0x%x", + *((uint16_t *)he_cap->rx_he_mcs_map_160)); + WMA_LOGD("\tTx MCS MAP for BW = 160 MHz: 0x%x", + *((uint16_t *)he_cap->tx_he_mcs_map_160)); + WMA_LOGD("\tRx MCS MAP for BW = 80 + 80 MHz: 0x%x", + *((uint16_t *)he_cap->rx_he_mcs_map_80_80)); + WMA_LOGD("\tTx MCS MAP for BW = 80 + 80 MHz: 0x%x", + *((uint16_t *)he_cap->tx_he_mcs_map_80_80)); /* HE PPET */ WMA_LOGD("\tNSS: %d", he_cap->ppe_threshold.nss_count + 1); @@ -934,7 +996,7 @@ void wma_populate_peer_he_cap(struct peer_assoc_params *peer, tDot11fIEhe_op *he_op = ¶ms->he_op; uint32_t *phy_cap = peer->peer_he_cap_phyinfo; uint32_t mac_cap = 0, he_ops = 0; - uint8_t temp, i; + uint8_t temp, i, chan_width; if (params->he_capable) peer->peer_flags |= WMI_PEER_HE; @@ -975,7 +1037,11 @@ void wma_populate_peer_he_cap(struct peer_assoc_params *peer, /* HE PHY capabilities */ WMI_HECAP_PHY_DB_SET(phy_cap, he_cap->dual_band); - WMI_HECAP_PHY_CBW_SET(phy_cap, he_cap->chan_width); + chan_width = HE_CH_WIDTH_COMBINE(he_cap->chan_width_0, + he_cap->chan_width_1, he_cap->chan_width_2, + he_cap->chan_width_3, he_cap->chan_width_4, + he_cap->chan_width_5, he_cap->chan_width_6); + WMI_HECAP_PHY_CBW_SET(phy_cap, chan_width); WMI_HECAP_PHY_PREAMBLEPUNCRX_SET(phy_cap, he_cap->rx_pream_puncturing); WMI_HECAP_PHY_COD_SET(phy_cap, he_cap->device_class); WMI_HECAP_PHY_LDPC_SET(phy_cap, he_cap->ldpc_coding); @@ -1031,17 +1097,30 @@ void wma_populate_peer_he_cap(struct peer_assoc_params *peer, WMI_HECAP_PHY_ERSU4X800NSECGI_SET(phy_cap, he_cap->er_he_ltf_800_gi_4x); - /* until further update in standard */ - peer->peer_he_mcs_count = WMI_HOST_MAX_HE_RATE_SET; - for (i = 0; i < peer->peer_he_mcs_count; i++) { - peer->peer_he_rx_mcs_set[i] = params->supportedRates.he_rx_mcs; - peer->peer_he_tx_mcs_set[i] = params->supportedRates.he_tx_mcs; + /* as per 11ax draft 1.4 */ + peer->peer_he_mcs_count = 1; + peer->peer_he_rx_mcs_set[0] = + params->supportedRates.rx_he_mcs_map_lt_80; + peer->peer_he_tx_mcs_set[0] = + params->supportedRates.tx_he_mcs_map_lt_80; - WMA_LOGD(FL("[HE - MCS Map: %d] rx_mcs: %x, tx_mcs: %x"), i, - peer->peer_he_rx_mcs_set[i], - peer->peer_he_tx_mcs_set[i]); + if (params->ch_width > CH_WIDTH_80MHZ) { + peer->peer_he_mcs_count = WMI_HOST_MAX_HE_RATE_SET; + peer->peer_he_rx_mcs_set[1] = + params->supportedRates.rx_he_mcs_map_160; + peer->peer_he_tx_mcs_set[1] = + params->supportedRates.tx_he_mcs_map_160; + peer->peer_he_rx_mcs_set[2] = + params->supportedRates.rx_he_mcs_map_80_80; + peer->peer_he_tx_mcs_set[2] = + params->supportedRates.tx_he_mcs_map_80_80; } + for (i = 0; i < peer->peer_he_mcs_count; i++) + WMA_LOGD(FL("[HE - MCS Map: %d] rx_mcs: 0x%x, tx_mcs: 0x%x"), i, + peer->peer_he_rx_mcs_set[i], + peer->peer_he_tx_mcs_set[i]); + WMI_HEOPS_COLOR_SET(he_ops, he_op->bss_color); WMI_HEOPS_DEFPE_SET(he_ops, he_op->default_pe); WMI_HEOPS_TWT_SET(he_ops, he_op->twt_required);