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
This commit is contained in:
Kiran Kumar Lokere 2019-11-08 17:10:08 -08:00 • committed by nshrivas
commit 5abc59e4bf
8 changed files with 209 additions and 60 deletions

View file

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

View file

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

View file

@ -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",

View file

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

View file

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

View file

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

View file

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

View file

@ -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],