From 5abc59e4bffc8e0f0a69d416a7f8a398610dec7e Mon Sep 17 00:00:00 2001 From: Kiran Kumar Lokere Date: Fri, 8 Nov 2019 17:10:08 -0800 Subject: [PATCH] qcacld-3.0: Fix incorrect phymode in 6GHz connection Add support to parse 6GHz operation information from AP beacon for connection. Change-Id: I67d167cd982163e28b3bbe7dc81747d8289a1513 CRs-Fixed: 2567849 --- core/mac/src/pe/lim/lim_assoc_utils.c | 83 +++++++++++-------- .../src/pe/lim/lim_process_assoc_rsp_frame.c | 18 +++- .../src/pe/lim/lim_process_sme_req_messages.c | 1 + core/mac/src/pe/lim/lim_prop_exts_utils.c | 65 +++++++++++++-- core/mac/src/pe/lim/lim_utils.c | 21 +++++ core/mac/src/pe/lim/lim_utils.h | 40 +++++++++ core/sme/src/csr/csr_api_roam.c | 35 +++++--- core/wma/src/wma_he.c | 4 + 8 files changed, 208 insertions(+), 59 deletions(-) diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c index 502a6bfe3f41..46df2c47eee5 100644 --- a/core/mac/src/pe/lim/lim_assoc_utils.c +++ b/core/mac/src/pe/lim/lim_assoc_utils.c @@ -1761,6 +1761,8 @@ QDF_STATUS lim_populate_peer_rate_set(struct mac_context *mac, tSirMacRateSet tempRateSet2; uint32_t i, j, val, min, isArate = 0; qdf_size_t val_len; + uint8_t aRateIndex = 0; + uint8_t bRateIndex = 0; /* copy operational rate set from pe_session */ if (pe_session->rateSet.numRates <= WLAN_SUPPORTED_RATES_IE_MAX_LEN) { @@ -1806,42 +1808,31 @@ QDF_STATUS lim_populate_peer_rate_set(struct mac_context *mac, * Sort rates in tempRateSet (they are likely to be already sorted) * put the result in pSupportedRates */ - { - uint8_t aRateIndex = 0; - uint8_t bRateIndex = 0; - qdf_mem_zero(pRates, sizeof(*pRates)); - for (i = 0; i < tempRateSet.numRates; i++) { - min = 0; - val = 0xff; - isArate = 0; - for (j = 0; - (j < tempRateSet.numRates) - && (j < WLAN_SUPPORTED_RATES_IE_MAX_LEN); j++) { - if ((uint32_t) (tempRateSet.rate[j] & 0x7f) < - val) { - val = tempRateSet.rate[j] & 0x7f; - min = j; - } + qdf_mem_zero(pRates, sizeof(*pRates)); + for (i = 0; i < tempRateSet.numRates; i++) { + min = 0; + val = 0xff; + isArate = 0; + for (j = 0; (j < tempRateSet.numRates) && + (j < WLAN_SUPPORTED_RATES_IE_MAX_LEN); j++) { + if ((uint32_t)(tempRateSet.rate[j] & 0x7f) < + val) { + val = tempRateSet.rate[j] & 0x7f; + min = j; } - if (sirIsArate(tempRateSet.rate[min] & 0x7f)) - isArate = 1; - /* - * HAL needs to know whether the rate is basic rate or not, as it needs to - * update the response rate table accordingly. e.g. if one of the 11a rates is - * basic rate, then that rate can be used for sending control frames. - * HAL updates the response rate table whenever basic rate set is changed. - */ - if (basicOnly) { - if (tempRateSet.rate[min] & 0x80) { - if (isArate) - pRates->llaRates[aRateIndex++] = - tempRateSet.rate[min]; - else - pRates->llbRates[bRateIndex++] = - tempRateSet.rate[min]; - } - } else { + } + if (sirIsArate(tempRateSet.rate[min] & 0x7f)) + isArate = 1; + /* + * HAL needs to know whether the rate is basic rate or not, + * as it needs to update the response rate table accordingly. + * e.g. if one of the 11a rates is basic rate, then that rate + * can be used for sending control frames. HAL updates the + * response rate table whenever basic rate set is changed. + */ + if (basicOnly) { + if (tempRateSet.rate[min] & 0x80) { if (isArate) pRates->llaRates[aRateIndex++] = tempRateSet.rate[min]; @@ -1849,11 +1840,19 @@ QDF_STATUS lim_populate_peer_rate_set(struct mac_context *mac, pRates->llbRates[bRateIndex++] = tempRateSet.rate[min]; } - tempRateSet.rate[min] = 0xff; + } else { + if (isArate) + pRates->llaRates[aRateIndex++] = + tempRateSet.rate[min]; + else + pRates->llbRates[bRateIndex++] = + tempRateSet.rate[min]; } + tempRateSet.rate[min] = 0xff; } - if (IS_DOT11_MODE_HT(pe_session->dot11mode)) { + if (IS_DOT11_MODE_HT(pe_session->dot11mode) && + !lim_is_he_6ghz_band(pe_session)) { val_len = SIZE_OF_SUPPORTED_MCS_SET; if (wlan_mlme_get_cfg_str( pRates->supportedMCSSet, @@ -3667,6 +3666,8 @@ QDF_STATUS lim_sta_send_add_bss(struct mac_context *mac, tpSirAssocRsp pAssocRsp (pAssocRsp->he_cap.present)) { lim_add_bss_he_cap(pAddBssParams, pAssocRsp); lim_add_bss_he_cfg(pAddBssParams, pe_session); + lim_update_he_6gop_assoc_resp(pAddBssParams, &pAssocRsp->he_op, + pe_session); } /* * Populate the STA-related parameters here @@ -3876,6 +3877,16 @@ QDF_STATUS lim_sta_send_add_bss(struct mac_context *mac, tpSirAssocRsp pAssocRsp pAddBssParams->staContext.htLdpcCapable, pAddBssParams->staContext.vhtLdpcCapable); } + if (lim_is_he_6ghz_band(pe_session)) { + if (lim_is_session_he_capable(pe_session) && + pAssocRsp->he_cap.present) { + lim_intersect_ap_he_caps(pe_session, + pAddBssParams, + NULL, + pAssocRsp); + lim_update_he_stbc_capable(&pAddBssParams->staContext); + } + } pAddBssParams->staContext.smesessionId = pe_session->smeSessionId; pAddBssParams->staContext.wpa_rsn = pBeaconStruct->rsnPresent; diff --git a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c index 3f48fecf4357..e48df79cd73b 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c @@ -519,9 +519,20 @@ lim_handle_assoc_reject_status(struct mac_context *mac_ctx, * Return: nss advertised by AP in beacon */ static uint8_t lim_get_nss_supported_by_ap(tDot11fIEVHTCaps *vht_caps, - tDot11fIEHTCaps *ht_caps) + tDot11fIEHTCaps *ht_caps, + tDot11fIEhe_cap *he_caps) { - if (vht_caps->present) { + + if (he_caps->present) { + if ((he_caps->rx_he_mcs_map_lt_80 & 0xC0) != 0xC0) + return NSS_4x4_MODE; + + if ((he_caps->rx_he_mcs_map_lt_80 & 0x30) != 0x30) + return NSS_3x3_MODE; + + if ((he_caps->rx_he_mcs_map_lt_80 & 0x0C) != 0x0C) + return NSS_2x2_MODE; + } else if (vht_caps->present) { if ((vht_caps->rxMCSMap & 0xC0) != 0xC0) return NSS_4x4_MODE; @@ -859,7 +870,8 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, QDF_STATUS_SUCCESS), assoc_rsp->status_code); ap_nss = lim_get_nss_supported_by_ap(&assoc_rsp->VHTCaps, - &assoc_rsp->HTCaps); + &assoc_rsp->HTCaps, + &assoc_rsp->he_cap); if (subtype == LIM_REASSOC) { pe_debug("Successfully Reassociated with BSS"); 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 374ed4c6c54f..3b8caf8aaf62 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 @@ -772,6 +772,7 @@ __lim_handle_sme_start_bss_request(struct mac_context *mac_ctx, uint32_t *msg_bu sme_start_bss_req->center_freq_seg0; session->ch_center_freq_seg1 = sme_start_bss_req->center_freq_seg1; + lim_update_he_bw_cap_mcs(session); } pe_debug("vht su tx bformer %d", diff --git a/core/mac/src/pe/lim/lim_prop_exts_utils.c b/core/mac/src/pe/lim/lim_prop_exts_utils.c index 41ce364b219d..2b4b55f2c5bc 100644 --- a/core/mac/src/pe/lim/lim_prop_exts_utils.c +++ b/core/mac/src/pe/lim/lim_prop_exts_utils.c @@ -102,11 +102,61 @@ static inline void get_ese_version_ie_probe_response(struct mac_context *mac_ctx static void lim_extract_he_op(struct pe_session *session, tSirProbeRespBeacon *beacon_struct) { - if (session->he_capable && beacon_struct->he_op.present) { - qdf_mem_copy(&session->he_op, &beacon_struct->he_op, - sizeof(session->he_op)); - pe_debug("he_op.bss_color %d", session->he_op.bss_color); - pe_debug("he_op.default_pe %d", session->he_op.default_pe); + uint8_t fw_vht_ch_wd; + uint8_t ap_bcon_ch_width; + uint8_t center_freq_diff; + + if (!session->he_capable) + return; + if (!beacon_struct->he_op.present) { + pe_debug("HE op not present in beacon"); + return; + } + qdf_mem_copy(&session->he_op, &beacon_struct->he_op, + sizeof(session->he_op)); + pe_debug("he_op.bss_color %d", session->he_op.bss_color); + pe_debug("he_op.default_pe %d", session->he_op.default_pe); + if (!session->he_6ghz_band) + return; + if (!session->he_op.oper_info_6g_present) { + pe_debug("6GHz op not present in 6G beacon"); + return; + } + session->ch_width = session->he_op.oper_info_6g.info.ch_width; + session->ch_center_freq_seg0 = + session->he_op.oper_info_6g.info.center_freq_seg0; + session->ch_center_freq_seg1 = + session->he_op.oper_info_6g.info.center_freq_seg1; + + pe_debug("6G op info: ch_wd %d cntr_freq_seg0 %d cntr_freq_seg1 %d", + session->ch_width, session->ch_center_freq_seg0, + session->ch_center_freq_seg1); + + if (!session->ch_center_freq_seg1) + return; + + fw_vht_ch_wd = wma_get_vht_ch_width(); + if (fw_vht_ch_wd <= WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) { + session->ch_width = CH_WIDTH_80MHZ; + session->ch_center_freq_seg1 = 0; + return; + } + center_freq_diff = abs(session->ch_center_freq_seg1 - + session->ch_center_freq_seg0); + if (center_freq_diff == 8) { + ap_bcon_ch_width = CH_WIDTH_160MHZ; + } else if (center_freq_diff > 16) { + ap_bcon_ch_width = CH_WIDTH_80P80MHZ; + } else { + session->ch_width = CH_WIDTH_80MHZ; + session->ch_center_freq_seg1 = 0; + return; + } + + if ((ap_bcon_ch_width == CH_WIDTH_80P80MHZ) && + (fw_vht_ch_wd != WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ)) { + session->ch_width = CH_WIDTH_80MHZ; + session->ch_center_freq_seg1 = 0; } } @@ -151,7 +201,7 @@ static void lim_check_he_ldpc_cap(struct pe_session *session, } } -static void lim_update_he_bw_cap_mcs(struct pe_session *session) +void lim_update_he_bw_cap_mcs(struct pe_session *session) { if (!session->he_capable) return; @@ -192,9 +242,6 @@ static inline void lim_extract_he_op(struct pe_session *session, static void lim_check_he_ldpc_cap(struct pe_session *session, tSirProbeRespBeacon *beacon_struct) {} - -static void lim_update_he_bw_cap_mcs(struct pe_session *session) -{} #endif void lim_objmgr_update_vdev_nss(struct wlan_objmgr_psoc *psoc, diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index ee4751e665a5..3eddda122aea 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -6718,6 +6718,27 @@ void lim_add_bss_he_cfg(struct bss_params *add_bss, struct pe_session *session) add_bss->he_sta_obsspd = session->he_sta_obsspd; } +void lim_update_he_6gop_assoc_resp(struct bss_params *pAddBssParams, + tDot11fIEhe_op *he_op, + struct pe_session *pe_session) +{ + if (!pe_session->he_6ghz_band) + return; + + if (!he_op->oper_info_6g_present) { + pe_debug("6G operation info not present in beacon"); + return; + } + if (!pe_session->ch_width) + return; + + pAddBssParams->ch_width = QDF_MIN(he_op->oper_info_6g.info.ch_width, + pe_session->ch_width); + + if (pAddBssParams->ch_width == CH_WIDTH_160MHZ) + pAddBssParams->ch_width = pe_session->ch_width; +} + void lim_update_stads_he_caps(tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp, struct pe_session *session_entry) { diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index ff3bd0490a7c..4e35d67c0b12 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -1029,6 +1029,17 @@ void lim_add_bss_he_cfg(struct bss_params *add_bss, struct pe_session *session); void lim_copy_bss_he_cap(struct pe_session *session, struct start_bss_req *sme_start_bss_req); +/** + * lim_update_he_6gop_assoc_resp() - Update HE 6GHz op info to BSS params + * @add_bss: pointer to add bss params + * @he_op: Pointer to HE operation info IE + * @session: Pointer to Session entry struct + * + * Return: None + */ +void lim_update_he_6gop_assoc_resp(struct bss_params *pAddBssParams, + tDot11fIEhe_op *he_op, + struct pe_session *pe_session); /** * lim_copy_join_req_he_cap() - Copy HE capability to PE session from Join req * and update as per bandwidth supported @@ -1143,6 +1154,19 @@ static inline bool lim_is_session_he_capable(struct pe_session *session) return session->he_capable; } +/** + * lim_update_he_bw_cap_mcs(): Update he mcs map per bandwidth + * @session_entry: pointer to PE session + * + * Return: None + */ +void lim_update_he_bw_cap_mcs(struct pe_session *session); + +static inline bool lim_is_he_6ghz_band(struct pe_session *session) +{ + return session->he_6ghz_band; +} + /** * lim_get_session_he_frag_cap(): Get session HE fragmentation cap * @session: pointer to session @@ -1252,6 +1276,13 @@ static inline void lim_add_bss_he_cfg(struct bss_params *add_bss, { } +static inline void lim_update_he_6gop_assoc_resp( + struct bss_params *pAddBssParams, + tDot11fIEhe_op *he_op, + struct pe_session *pe_session) +{ +} + static inline void lim_intersect_ap_he_caps(struct pe_session *session, struct bss_params *add_bss, tSchBeaconStruct *pBeaconStruct, tpSirAssocRsp assoc_rsp) @@ -1313,6 +1344,15 @@ static inline bool lim_is_session_he_capable(struct pe_session *session) return false; } +static inline void lim_update_he_bw_cap_mcs(struct pe_session *session) +{ +} + +static inline bool lim_is_he_6ghz_band(struct pe_session *session) +{ + return false; +} + static inline uint8_t lim_get_session_he_frag_cap(struct pe_session *session) { return 0; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index e2f619f3c6d3..5133b270eb70 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -15423,34 +15423,45 @@ static inline void csr_update_sae_config(struct join_req *csr_join_req, */ static uint8_t csr_get_nss_supported_by_sta_and_ap(tDot11fIEVHTCaps *vht_caps, tDot11fIEHTCaps *ht_caps, + tDot11fIEhe_cap *he_cap, uint32_t dot11_mode) { - bool vht_capability, ht_capability; + bool vht_capability, ht_capability, he_capability; vht_capability = IS_DOT11_MODE_VHT(dot11_mode); ht_capability = IS_DOT11_MODE_HT(dot11_mode); + he_capability = IS_DOT11_MODE_HE(dot11_mode); - if (vht_capability && vht_caps->present) { + if (he_capability && he_cap->present) { + if ((he_cap->rx_he_mcs_map_lt_80 & 0xC0) != 0xC0) + return NSS_4x4_MODE; + + if ((he_cap->rx_he_mcs_map_lt_80 & 0x30) != 0x30) + return NSS_3x3_MODE; + + if ((he_cap->rx_he_mcs_map_lt_80 & 0x0C) != 0x0C) + return NSS_2x2_MODE; + } else if (vht_capability && vht_caps->present) { if ((vht_caps->rxMCSMap & 0xC0) != 0xC0) - return 4; + return NSS_4x4_MODE; if ((vht_caps->rxMCSMap & 0x30) != 0x30) - return 3; + return NSS_3x3_MODE; if ((vht_caps->rxMCSMap & 0x0C) != 0x0C) - return 2; + return NSS_2x2_MODE; } else if (ht_capability && ht_caps->present) { if (ht_caps->supportedMCSSet[3]) - return 4; + return NSS_4x4_MODE; if (ht_caps->supportedMCSSet[2]) - return 3; + return NSS_3x3_MODE; if (ht_caps->supportedMCSSet[1]) - return 2; + return NSS_2x2_MODE; } - return 1; + return NSS_1x1_MODE; } /** @@ -15785,7 +15796,7 @@ QDF_STATUS csr_send_join_req_msg(struct mac_context *mac, uint32_t sessionId, vendor_ap_search_attr.mac_addr = &pBssDescription->bssId[0]; vendor_ap_search_attr.nss = csr_get_nss_supported_by_sta_and_ap( &pIes->VHTCaps, &pIes->HTCaps, - dot11mode); + &pIes->he_cap, dot11mode); vendor_ap_search_attr.ht_cap = pIes->HTCaps.present; vendor_ap_search_attr.vht_cap = pIes->VHTCaps.present; vendor_ap_search_attr.enable_2g = @@ -15816,7 +15827,9 @@ QDF_STATUS csr_send_join_req_msg(struct mac_context *mac, uint32_t sessionId, if (!force_max_nss) ap_nss = csr_get_nss_supported_by_sta_and_ap( &pIes->VHTCaps, - &pIes->HTCaps, dot11mode); + &pIes->HTCaps, + &pIes->he_cap, + dot11mode); if (!force_max_nss && pSession->nss > ap_nss) { pSession->nss = ap_nss; pSession->vdev_nss = pSession->nss; diff --git a/core/wma/src/wma_he.c b/core/wma/src/wma_he.c index 42db2f3a0032..d42ee779f623 100644 --- a/core/wma/src/wma_he.c +++ b/core/wma/src/wma_he.c @@ -1264,6 +1264,10 @@ void wma_populate_peer_he_cap(struct peer_assoc_params *peer, params->supportedRates.tx_he_mcs_map_80_80; } +#define HE2x2MCSMASK 0xc + + peer->peer_nss = ((params->supportedRates.rx_he_mcs_map_lt_80 & + HE2x2MCSMASK) == HE2x2MCSMASK) ? 1 : 2; 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],