diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 03d6499a6366..1559e6c35452 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -6579,19 +6579,80 @@ void lim_add_self_he_cap(tpAddStaParams add_sta_params, struct pe_session *sessi sizeof(add_sta_params->he_op)); } +static bool lim_check_is_bss_greater_than_4_nss_supp(struct pe_session *session, + tDot11fIEhe_cap *he_cap) +{ + uint8_t i; + uint16_t mcs_map; +#define NSS_4 4 +#define NSS_8 8 + + if (!session->he_capable || !he_cap->present) + return false; + mcs_map = he_cap->rx_he_mcs_map_lt_80; + for (i = NSS_4; i < NSS_8; i++) { + if (((mcs_map >> (i * 2)) & 0x3) != 0x3) + return true; + } + + return false; +} + +bool lim_check_he_80_mcs11_supp(struct pe_session *session, + tDot11fIEhe_cap *he_cap) +{ + uint16_t rx_mcs_map; + uint16_t tx_mcs_map; + + rx_mcs_map = he_cap->rx_he_mcs_map_lt_80; + tx_mcs_map = he_cap->tx_he_mcs_map_lt_80; + if ((session->nss == NSS_1x1_MODE) && + ((HE_GET_MCS_4_NSS(rx_mcs_map, 1) == HE_MCS_0_11) || + (HE_GET_MCS_4_NSS(tx_mcs_map, 1) == HE_MCS_0_11))) + return true; + + if ((session->nss == NSS_2x2_MODE) && + ((HE_GET_MCS_4_NSS(rx_mcs_map, 2) == HE_MCS_0_11) || + (HE_GET_MCS_4_NSS(tx_mcs_map, 2) == HE_MCS_0_11))) + return true; + + return false; +} + +/** + * lim_check_he_ldpc_cap() - set he ldpc coding to one if + * channel width is > 20 or mcs 10/11 bit are supported or + * nss is greater than 4. + * @beacon_struct: beacon structure + * @session: A pointer to session entry. + * + * Return: None + */ + +static void lim_check_and_force_he_ldpc_cap(struct pe_session *session, + tDot11fIEhe_cap *he_cap) +{ + if (!he_cap->ldpc_coding && + (session->ch_width > CH_WIDTH_20MHZ || + lim_check_he_80_mcs11_supp(session, he_cap) || + lim_check_is_bss_greater_than_4_nss_supp(session, he_cap))) + he_cap->ldpc_coding = 1; +} + /** * lim_intersect_he_caps() - Intersect peer capability and self capability * @rcvd_he: pointer to received peer capability - * @session_he: pointer to self capability * @peer_he: pointer to Intersected capability + * @session: A pointer to session entry. * * Return: None */ static void lim_intersect_he_caps(tDot11fIEhe_cap *rcvd_he, - tDot11fIEhe_cap *session_he, - tDot11fIEhe_cap *peer_he) + tDot11fIEhe_cap *peer_he, + struct pe_session *session) { uint8_t val; + tDot11fIEhe_cap *session_he = &session->he_config; qdf_mem_copy(peer_he, rcvd_he, sizeof(*peer_he)); @@ -6599,6 +6660,7 @@ static void lim_intersect_he_caps(tDot11fIEhe_cap *rcvd_he, peer_he->fragmentation); peer_he->ldpc_coding &= session_he->ldpc_coding; + lim_check_and_force_he_ldpc_cap(session, peer_he); if (session_he->tb_ppdu_tx_stbc_lt_80mhz && peer_he->rx_stbc_lt_80mhz) peer_he->rx_stbc_lt_80mhz = 1; @@ -6650,7 +6712,6 @@ void lim_intersect_sta_he_caps(struct mac_context *mac_ctx, tpDphHashNode sta_ds) { tDot11fIEhe_cap *rcvd_he = &assoc_req->he_cap; - tDot11fIEhe_cap *session_he = &session->he_config; tDot11fIEhe_cap *peer_he = &sta_ds->he_config; if (!sta_ds->mlmStaContext.he_capable) @@ -6660,7 +6721,7 @@ void lim_intersect_sta_he_caps(struct mac_context *mac_ctx, if (!IS_DOT11_MODE_HE(session->dot11mode)) return; - lim_intersect_he_caps(rcvd_he, session_he, peer_he); + lim_intersect_he_caps(rcvd_he, peer_he, session); /* If MCS 12/13 is supported from assoc QCN IE */ if (assoc_req->qcn_ie.present && @@ -6685,7 +6746,6 @@ void lim_intersect_ap_he_caps(struct pe_session *session, struct bss_params *add tSchBeaconStruct *beacon, tpSirAssocRsp assoc_rsp) { tDot11fIEhe_cap *rcvd_he; - tDot11fIEhe_cap *session_he = &session->he_config; tDot11fIEhe_cap *peer_he = &add_bss->staContext.he_config; if (assoc_rsp && assoc_rsp->he_cap.present) @@ -6693,7 +6753,7 @@ void lim_intersect_ap_he_caps(struct pe_session *session, struct bss_params *add else rcvd_he = &beacon->he_cap; - lim_intersect_he_caps(rcvd_he, session_he, peer_he); + lim_intersect_he_caps(rcvd_he, peer_he, session); add_bss->staContext.he_capable = true; } @@ -6740,98 +6800,35 @@ void lim_update_he_6gop_assoc_resp(struct bss_params *pAddBssParams, pAddBssParams->staContext.ch_width = pAddBssParams->ch_width; } -static bool lim_check_is_bss_greater_than_4_nss_supp(struct pe_session *session, - tDot11fIEhe_cap *he_cap) -{ - uint8_t i; - uint16_t mcs_map; -#define NSS_4 4 -#define NSS_8 8 - - if (!session->he_capable || !he_cap->present) - return false; - mcs_map = he_cap->rx_he_mcs_map_lt_80; - for (i = NSS_4; i < NSS_8; i++) { - if (((mcs_map >> (i * 2)) & 0x3) != 0x3) - return true; - } - - return false; -} - -bool lim_check_he_80_mcs11_supp(struct pe_session *session, - tDot11fIEhe_cap *he_cap) -{ - uint16_t rx_mcs_map; - uint16_t tx_mcs_map; - - rx_mcs_map = he_cap->rx_he_mcs_map_lt_80; - tx_mcs_map = he_cap->tx_he_mcs_map_lt_80; - if ((session->nss == NSS_1x1_MODE) && - ((HE_GET_MCS_4_NSS(rx_mcs_map, 1) == HE_MCS_0_11) || - (HE_GET_MCS_4_NSS(tx_mcs_map, 1) == HE_MCS_0_11))) - return true; - - if ((session->nss == NSS_2x2_MODE) && - ((HE_GET_MCS_4_NSS(rx_mcs_map, 2) == HE_MCS_0_11) || - (HE_GET_MCS_4_NSS(tx_mcs_map, 2) == HE_MCS_0_11))) - return true; - - return false; -} - -/** - * lim_check_he_ldpc_cap() - set he ladpc coding to one if - * channel width is > 20 or mcs 10/11 bit are supported or - * nss is greater than 4. - * @beacon_struct: beacon structure - * @session: A pointer to session entry. - * - * Return: None - */ - -static void lim_check_and_force_he_ldpc_cap(struct pe_session *session, - tDot11fIEhe_cap *he_cap) -{ - if (!he_cap->ldpc_coding && - !WLAN_REG_IS_24GHZ_CH_FREQ(session->curr_op_freq) && - (session->ch_width > CH_WIDTH_20MHZ || - lim_check_he_80_mcs11_supp(session, he_cap) || - lim_check_is_bss_greater_than_4_nss_supp(session, he_cap))) - he_cap->ldpc_coding = 1; -} - void lim_update_stads_he_caps(struct mac_context *mac_ctx, tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp, struct pe_session *session_entry, tSchBeaconStruct *beacon) { - tDot11fIEhe_cap *he_cap; - - he_cap = &assoc_rsp->he_cap; - - if (assoc_rsp->he_cap.present) { - he_cap = &assoc_rsp->he_cap; - } else if (beacon && beacon->he_cap.present) { + if (!assoc_rsp->he_cap.present && beacon && beacon->he_cap.present) { /* Use beacon HE caps if assoc resp doesn't have he caps */ pe_debug("he_caps missing in assoc rsp"); - he_cap = &beacon->he_cap; qdf_mem_copy(&assoc_rsp->he_cap, &beacon->he_cap, - sizeof(*he_cap)); - } else { - return; + sizeof(tDot11fIEhe_cap)); } - sta_ds->mlmStaContext.he_capable = he_cap->present; + /* assoc resp and beacon doesn't have he caps */ + if (!assoc_rsp->he_cap.present) + return; - /* setting lpdc_coding if any of assoc_rsp or beacon has ladpc_coding + sta_ds->mlmStaContext.he_capable = assoc_rsp->he_cap.present; + + /* setting ldpc_coding if any of assoc_rsp or beacon has ldpc_coding * enabled */ if (beacon) - he_cap->ldpc_coding |= beacon->he_cap.ldpc_coding; - lim_check_and_force_he_ldpc_cap(session_entry, he_cap); + assoc_rsp->he_cap.ldpc_coding |= beacon->he_cap.ldpc_coding; + lim_check_and_force_he_ldpc_cap(session_entry, &assoc_rsp->he_cap); + if (beacon) + beacon->he_cap.ldpc_coding = assoc_rsp->he_cap.ldpc_coding; - qdf_mem_copy(&sta_ds->he_config, he_cap, sizeof(*he_cap)); + qdf_mem_copy(&sta_ds->he_config, &assoc_rsp->he_cap, + sizeof(tDot11fIEhe_cap)); /* If HE is not supported, do not fill sta_ds and return */ if (!IS_DOT11_MODE_HE(session_entry->dot11mode))