mirror of
https://github.com/torvalds/linux.git
synced 2024-12-25 12:21:37 +00:00
wifi: mac80211: work around Cisco AP 9115 VHT MPDU length
Cisco AP module 9115 with FW 17.3 has a bug and sends a too large maximum MPDU length in the association response (indicating 12k) that it cannot actually process. Work around that by taking the minimum between what's in the association response and the BSS elements (from beacon or probe response). Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Link: https://lore.kernel.org/r/20230918140607.d1966a9a532e.I090225babb7cd4d1081ee9acd40e7de7e41c15ae@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
0914468adf
commit
084cf2aeca
@ -1860,7 +1860,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
|
||||
/* VHT can override some HT caps such as the A-MSDU max length */
|
||||
if (params->vht_capa)
|
||||
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
|
||||
params->vht_capa, link_sta);
|
||||
params->vht_capa, NULL,
|
||||
link_sta);
|
||||
|
||||
if (params->he_capa)
|
||||
ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
|
||||
|
@ -1072,7 +1072,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
|
||||
&chandef);
|
||||
memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie));
|
||||
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
|
||||
&cap_ie,
|
||||
&cap_ie, NULL,
|
||||
&sta->deflink);
|
||||
if (memcmp(&cap, &sta->sta.deflink.vht_cap, sizeof(cap)))
|
||||
rates_updated |= true;
|
||||
|
@ -2141,6 +2141,7 @@ void
|
||||
ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_supported_band *sband,
|
||||
const struct ieee80211_vht_cap *vht_cap_ie,
|
||||
const struct ieee80211_vht_cap *vht_cap_ie2,
|
||||
struct link_sta_info *link_sta);
|
||||
enum ieee80211_sta_rx_bandwidth
|
||||
ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta);
|
||||
|
@ -451,7 +451,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
|
||||
changed |= IEEE80211_RC_BW_CHANGED;
|
||||
|
||||
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
|
||||
elems->vht_cap_elem,
|
||||
elems->vht_cap_elem, NULL,
|
||||
&sta->deflink);
|
||||
|
||||
ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap,
|
||||
|
@ -4202,10 +4202,33 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
|
||||
elems->ht_cap_elem,
|
||||
link_sta);
|
||||
|
||||
if (elems->vht_cap_elem && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
|
||||
if (elems->vht_cap_elem &&
|
||||
!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) {
|
||||
const struct ieee80211_vht_cap *bss_vht_cap = NULL;
|
||||
const struct cfg80211_bss_ies *ies;
|
||||
|
||||
/*
|
||||
* Cisco AP module 9115 with FW 17.3 has a bug and sends a
|
||||
* too large maximum MPDU length in the association response
|
||||
* (indicating 12k) that it cannot actually process ...
|
||||
* Work around that.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
ies = rcu_dereference(cbss->ies);
|
||||
if (ies) {
|
||||
const struct element *elem;
|
||||
|
||||
elem = cfg80211_find_elem(WLAN_EID_VHT_CAPABILITY,
|
||||
ies->data, ies->len);
|
||||
if (elem && elem->datalen >= sizeof(*bss_vht_cap))
|
||||
bss_vht_cap = (const void *)elem->data;
|
||||
}
|
||||
|
||||
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
|
||||
elems->vht_cap_elem,
|
||||
link_sta);
|
||||
bss_vht_cap, link_sta);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
if (elems->he_operation && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) &&
|
||||
elems->he_cap) {
|
||||
|
@ -4,7 +4,7 @@
|
||||
*
|
||||
* Portions of this file
|
||||
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 - 2022 Intel Corporation
|
||||
* Copyright (C) 2018 - 2023 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
@ -116,12 +116,14 @@ void
|
||||
ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_supported_band *sband,
|
||||
const struct ieee80211_vht_cap *vht_cap_ie,
|
||||
const struct ieee80211_vht_cap *vht_cap_ie2,
|
||||
struct link_sta_info *link_sta)
|
||||
{
|
||||
struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap;
|
||||
struct ieee80211_sta_vht_cap own_cap;
|
||||
u32 cap_info, i;
|
||||
bool have_80mhz;
|
||||
u32 mpdu_len;
|
||||
|
||||
memset(vht_cap, 0, sizeof(*vht_cap));
|
||||
|
||||
@ -317,11 +319,21 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta);
|
||||
|
||||
/*
|
||||
* Work around the Cisco 9115 FW 17.3 bug by taking the min of
|
||||
* both reported MPDU lengths.
|
||||
*/
|
||||
mpdu_len = vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK;
|
||||
if (vht_cap_ie2)
|
||||
mpdu_len = min_t(u32, mpdu_len,
|
||||
le32_get_bits(vht_cap_ie2->vht_cap_info,
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_MASK));
|
||||
|
||||
/*
|
||||
* FIXME - should the amsdu len be per link? store per link
|
||||
* and maintain a minimum?
|
||||
*/
|
||||
switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
|
||||
switch (mpdu_len) {
|
||||
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
|
||||
link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user