From 2f8a36092fe958eb5f9fd9bb5bc5450943e076ff Mon Sep 17 00:00:00 2001 From: Kiran Kumar Lokere Date: Thu, 21 Nov 2019 17:40:06 -0800 Subject: [PATCH] qcacld-3.0: Validate peer HE mcs map before configuring to FW Validate the HE mcs map in assoc response frame while sending it in peer assoc command to FW. If the valid MCS is not found in assoc response frame then populate HE mcs map from beacon HE caps as the session Nss is derived from beacon capabilities. Change-Id: Icea452bc23b86f8a45f6096ffcacbc6f8545aab5 CRs-Fixed: 2566959 --- core/mac/src/pe/lim/lim_assoc_utils.c | 52 ++++++++++++++++++++- core/mac/src/pe/lim/lim_utils.c | 65 ++++++++++++++++----------- 2 files changed, 91 insertions(+), 26 deletions(-) diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index bb94dedaad88..f035dfcc138e 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -1741,11 +1741,42 @@ static void lim_calculate_he_nss(struct supported_rates *rates, { HE_GET_NSS(rates->rx_he_mcs_map_lt_80, session->nss); } + +static bool lim_check_valid_mcs_for_nss(struct pe_session *session, + tDot11fIEhe_cap *he_caps) +{ + uint16_t mcs_map; + uint8_t mcs_count = 2, i; + + if (!session->he_capable || !he_caps) + return true; + + mcs_map = he_caps->rx_he_mcs_map_lt_80; + + do { + for (i = 0; i < session->nss; i++) { + if (((mcs_map >> (i * 2)) & 0x3) == 0x3) + return false; + } + + mcs_map = he_caps->tx_he_mcs_map_lt_80; + mcs_count--; + } while (mcs_count); + + return true; + +} #else static void lim_calculate_he_nss(struct supported_rates *rates, struct pe_session *session) { } + +static bool lim_check_valid_mcs_for_nss(struct pe_session *session, + tDot11fIEhe_cap *he_caps) +{ + return true; +} #endif QDF_STATUS lim_populate_peer_rate_set(struct mac_context *mac, @@ -1763,6 +1794,10 @@ QDF_STATUS lim_populate_peer_rate_set(struct mac_context *mac, qdf_size_t val_len; uint8_t aRateIndex = 0; uint8_t bRateIndex = 0; + tDot11fIEhe_cap *peer_he_caps; + struct bss_description *bssDescription = + &pe_session->lim_join_req->bssDescription; + tSchBeaconStruct *pBeaconStruct; /* copy operational rate set from pe_session */ if (pe_session->rateSet.numRates <= WLAN_SUPPORTED_RATES_IE_MAX_LEN) { @@ -1889,7 +1924,22 @@ QDF_STATUS lim_populate_peer_rate_set(struct mac_context *mac, lim_populate_vht_mcs_set(mac, pRates, pVHTCaps, pe_session, pe_session->nss, sta_ds); - lim_populate_he_mcs_set(mac, pRates, he_caps, + if (lim_check_valid_mcs_for_nss(pe_session, he_caps)) { + peer_he_caps = he_caps; + } else { + bssDescription = &pe_session->lim_join_req->bssDescription; + pBeaconStruct = qdf_mem_malloc(sizeof(tSchBeaconStruct)); + if (!pBeaconStruct) + return QDF_STATUS_E_NOMEM; + lim_extract_ap_capabilities(mac, + (uint8_t *)bssDescription->ieFields, + lim_get_ielen_from_bss_description( + bssDescription), + pBeaconStruct); + peer_he_caps = &pBeaconStruct->he_cap; + } + + lim_populate_he_mcs_set(mac, pRates, peer_he_caps, pe_session, pe_session->nss); if (IS_DOT11_MODE_HE(pe_session->dot11mode) && he_caps) { diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 9c528cdb368d..917278916340 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -7336,7 +7336,7 @@ QDF_STATUS lim_send_he_caps_ie(struct mac_context *mac_ctx, struct pe_session *s * Return: status of operation */ static QDF_STATUS lim_populate_he_mcs_per_bw(struct mac_context *mac_ctx, - uint16_t *self_rx, uint16_t *self_tx, + uint16_t *supp_rx_mcs, uint16_t *supp_tx_mcs, uint16_t peer_rx, uint16_t peer_tx, uint8_t nss, uint16_t rx_mcs, uint16_t tx_mcs) { @@ -7344,20 +7344,22 @@ static QDF_STATUS lim_populate_he_mcs_per_bw(struct mac_context *mac_ctx, pe_debug("peer rates: rx_mcs - 0x%04x tx_mcs - 0x%04x", peer_rx, peer_tx); - *self_rx = rx_mcs; - *self_tx = tx_mcs; + *supp_rx_mcs = rx_mcs; + *supp_tx_mcs = tx_mcs; - *self_rx = HE_INTERSECT_MCS(*self_rx, peer_tx); - *self_tx = HE_INTERSECT_MCS(*self_tx, peer_rx); + *supp_tx_mcs = HE_INTERSECT_MCS(*supp_rx_mcs, peer_tx); + *supp_rx_mcs = HE_INTERSECT_MCS(*supp_tx_mcs, 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); + *supp_rx_mcs |= HE_MCS_INV_MSK_4_NSS(1); + *supp_tx_mcs |= 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)); + *supp_rx_mcs |= (HE_MCS_INV_MSK_4_NSS(1) & + HE_MCS_INV_MSK_4_NSS(2)); + *supp_tx_mcs |= (HE_MCS_INV_MSK_4_NSS(1) & + HE_MCS_INV_MSK_4_NSS(2)); } return QDF_STATUS_SUCCESS; @@ -7408,22 +7410,35 @@ QDF_STATUS lim_populate_he_mcs_set(struct mac_context *mac_ctx, peer_he_caps->tx_he_mcs_map_lt_80, nss, mac_ctx->mlme_cfg->he_caps.dot11_he_cap.rx_he_mcs_map_lt_80, mac_ctx->mlme_cfg->he_caps.dot11_he_cap.tx_he_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, - *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap. - rx_he_mcs_map_160), - *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap. - tx_he_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, - *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap. - rx_he_mcs_map_80_80), - *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap. - tx_he_mcs_map_80_80)); + if (session_entry->ch_width == CH_WIDTH_160MHZ) { + 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, + *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap. + rx_he_mcs_map_160), + *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap. + tx_he_mcs_map_160)); + } else { + rates->tx_he_mcs_map_160 = HE_MCS_ALL_DISABLED; + rates->rx_he_mcs_map_160 = HE_MCS_ALL_DISABLED; + } + if (session_entry->ch_width == CH_WIDTH_80P80MHZ) { + 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, + *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap. + rx_he_mcs_map_80_80), + *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap. + tx_he_mcs_map_80_80)); + } else { + rates->tx_he_mcs_map_80_80 = HE_MCS_ALL_DISABLED; + rates->rx_he_mcs_map_80_80 = HE_MCS_ALL_DISABLED; + } if (!support_2x2) { /* disable 2 and higher NSS MCS sets */ rates->rx_he_mcs_map_lt_80 |= HE_MCS_INV_MSK_4_NSS(1);