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);