qcacld-3.0: Fix LDPC setting for HE connection

Fix the issue with LDPC setting in HE caps sent to FW.

Change-Id: Idc7965d81f32cac5f848b9ade8fc367d27a70e83
CRs-Fixed: 2818299
This commit is contained in:
Kiran Kumar Lokere 2020-11-12 10:52:37 -08:00 • committed by snandini
commit 7e4220459b

View file

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