EHT: Use HE operating channel width in MCS length calculation
Channel width in HE Capabilities element added to management frames is calculated in hostapd_eid_he_capab() by intersecting the driver capabilities and the operating channel width. Kernel uses this value from the Beacon frames to verify EHT capabilities length. However, EHT MCS length calculation uses only the driver capabilities which results in EHT AP bring up failure in some cases dues to different lengths. Modify the EHT code to use the HE operating channel width as well to determine matching length for the information. Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
This commit is contained in:
parent
23e31eb68e
commit
3df42cf3c7
1 changed files with 29 additions and 8 deletions
|
@ -42,11 +42,29 @@ static u16 ieee80211_eht_ppet_size(u16 ppe_thres_hdr, const u8 *phy_cap_info)
|
|||
|
||||
|
||||
static u8 ieee80211_eht_mcs_set_size(enum hostapd_hw_mode mode, u8 opclass,
|
||||
const u8 *he_phy_cap,
|
||||
u8 he_oper_chwidth, const u8 *he_phy_cap,
|
||||
const u8 *eht_phy_cap)
|
||||
{
|
||||
u8 sz = EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS;
|
||||
bool band24, band5, band6;
|
||||
u8 he_phy_cap_chwidth = ~HE_PHYCAP_CHANNEL_WIDTH_MASK;
|
||||
|
||||
switch (he_oper_chwidth) {
|
||||
case CONF_OPER_CHWIDTH_80P80MHZ:
|
||||
he_phy_cap_chwidth |=
|
||||
HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G;
|
||||
/* fall through */
|
||||
case CONF_OPER_CHWIDTH_160MHZ:
|
||||
he_phy_cap_chwidth |= HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
|
||||
/* fall through */
|
||||
case CONF_OPER_CHWIDTH_80MHZ:
|
||||
case CONF_OPER_CHWIDTH_USE_HT:
|
||||
he_phy_cap_chwidth |= HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
|
||||
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
|
||||
break;
|
||||
}
|
||||
|
||||
he_phy_cap_chwidth &= he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX];
|
||||
|
||||
band24 = mode == HOSTAPD_MODE_IEEE80211B ||
|
||||
mode == HOSTAPD_MODE_IEEE80211G ||
|
||||
|
@ -56,19 +74,18 @@ static u8 ieee80211_eht_mcs_set_size(enum hostapd_hw_mode mode, u8 opclass,
|
|||
band6 = is_6ghz_op_class(opclass);
|
||||
|
||||
if (band24 &&
|
||||
(he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
|
||||
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G) == 0)
|
||||
(he_phy_cap_chwidth & HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G) == 0)
|
||||
return EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY;
|
||||
|
||||
if (band5 &&
|
||||
(he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
|
||||
(he_phy_cap_chwidth &
|
||||
(HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
|
||||
HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
|
||||
HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)) == 0)
|
||||
return EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY;
|
||||
|
||||
if (band5 &&
|
||||
(he_phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
|
||||
(he_phy_cap_chwidth &
|
||||
(HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
|
||||
HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)))
|
||||
sz += EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS;
|
||||
|
@ -98,6 +115,7 @@ size_t hostapd_eid_eht_capab_len(struct hostapd_data *hapd,
|
|||
return 0;
|
||||
|
||||
len += ieee80211_eht_mcs_set_size(mode->mode, hapd->iconf->op_class,
|
||||
hapd->iconf->he_oper_chwidth,
|
||||
mode->he_capab[opmode].phy_cap,
|
||||
eht_cap->phy_cap);
|
||||
len += ieee80211_eht_ppet_size(WPA_GET_LE16(&eht_cap->ppet[0]),
|
||||
|
@ -152,6 +170,7 @@ u8 * hostapd_eid_eht_capab(struct hostapd_data *hapd, u8 *eid,
|
|||
|
||||
mcs_nss_len = ieee80211_eht_mcs_set_size(mode->mode,
|
||||
hapd->iconf->op_class,
|
||||
hapd->iconf->he_oper_chwidth,
|
||||
mode->he_capab[opmode].phy_cap,
|
||||
eht_cap->phy_cap);
|
||||
if (mcs_nss_len) {
|
||||
|
@ -275,6 +294,7 @@ static bool check_valid_eht_mcs(struct hostapd_data *hapd,
|
|||
sta_mcs = capab->optional;
|
||||
|
||||
if (ieee80211_eht_mcs_set_size(mode->mode, hapd->iconf->op_class,
|
||||
hapd->iconf->he_oper_chwidth,
|
||||
mode->he_capab[opmode].phy_cap,
|
||||
mode->eht_capab[opmode].phy_cap) ==
|
||||
EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY)
|
||||
|
@ -300,7 +320,7 @@ static bool check_valid_eht_mcs(struct hostapd_data *hapd,
|
|||
|
||||
|
||||
static bool ieee80211_invalid_eht_cap_size(enum hostapd_hw_mode mode,
|
||||
u8 opclass,
|
||||
u8 opclass, u8 he_oper_chwidth,
|
||||
const u8 *he_cap, const u8 *eht_cap,
|
||||
size_t len)
|
||||
{
|
||||
|
@ -317,8 +337,8 @@ static bool ieee80211_invalid_eht_cap_size(enum hostapd_hw_mode mode,
|
|||
if (len < cap_len)
|
||||
return true;
|
||||
|
||||
cap_len += ieee80211_eht_mcs_set_size(mode, opclass, he_phy_cap,
|
||||
cap->phy_cap);
|
||||
cap_len += ieee80211_eht_mcs_set_size(mode, opclass, he_oper_chwidth,
|
||||
he_phy_cap, cap->phy_cap);
|
||||
if (len < cap_len)
|
||||
return true;
|
||||
|
||||
|
@ -342,6 +362,7 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
!he_capab || he_capab_len < IEEE80211_HE_CAPAB_MIN_LEN ||
|
||||
!eht_capab ||
|
||||
ieee80211_invalid_eht_cap_size(mode, hapd->iconf->op_class,
|
||||
hapd->iconf->he_oper_chwidth,
|
||||
he_capab, eht_capab,
|
||||
eht_capab_len) ||
|
||||
!check_valid_eht_mcs(hapd, eht_capab, opmode)) {
|
||||
|
|
Loading…
Reference in a new issue