Skip to content

Commit 084cf2a

Browse files
committed
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 <[email protected]> Signed-off-by: Gregory Greenman <[email protected]> Link: https://lore.kernel.org/r/20230918140607.d1966a9a532e.I090225babb7cd4d1081ee9acd40e7de7e41c15ae@changeid Signed-off-by: Johannes Berg <[email protected]>
1 parent 0914468 commit 084cf2a

File tree

6 files changed

+44
-7
lines changed

6 files changed

+44
-7
lines changed

net/mac80211/cfg.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1860,7 +1860,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
18601860
/* VHT can override some HT caps such as the A-MSDU max length */
18611861
if (params->vht_capa)
18621862
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
1863-
params->vht_capa, link_sta);
1863+
params->vht_capa, NULL,
1864+
link_sta);
18641865

18651866
if (params->he_capa)
18661867
ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,

net/mac80211/ibss.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1072,7 +1072,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
10721072
&chandef);
10731073
memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie));
10741074
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
1075-
&cap_ie,
1075+
&cap_ie, NULL,
10761076
&sta->deflink);
10771077
if (memcmp(&cap, &sta->sta.deflink.vht_cap, sizeof(cap)))
10781078
rates_updated |= true;

net/mac80211/ieee80211_i.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2141,6 +2141,7 @@ void
21412141
ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
21422142
struct ieee80211_supported_band *sband,
21432143
const struct ieee80211_vht_cap *vht_cap_ie,
2144+
const struct ieee80211_vht_cap *vht_cap_ie2,
21442145
struct link_sta_info *link_sta);
21452146
enum ieee80211_sta_rx_bandwidth
21462147
ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta);

net/mac80211/mesh_plink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
451451
changed |= IEEE80211_RC_BW_CHANGED;
452452

453453
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
454-
elems->vht_cap_elem,
454+
elems->vht_cap_elem, NULL,
455455
&sta->deflink);
456456

457457
ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap,

net/mac80211/mlme.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4202,10 +4202,33 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
42024202
elems->ht_cap_elem,
42034203
link_sta);
42044204

4205-
if (elems->vht_cap_elem && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
4205+
if (elems->vht_cap_elem &&
4206+
!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) {
4207+
const struct ieee80211_vht_cap *bss_vht_cap = NULL;
4208+
const struct cfg80211_bss_ies *ies;
4209+
4210+
/*
4211+
* Cisco AP module 9115 with FW 17.3 has a bug and sends a
4212+
* too large maximum MPDU length in the association response
4213+
* (indicating 12k) that it cannot actually process ...
4214+
* Work around that.
4215+
*/
4216+
rcu_read_lock();
4217+
ies = rcu_dereference(cbss->ies);
4218+
if (ies) {
4219+
const struct element *elem;
4220+
4221+
elem = cfg80211_find_elem(WLAN_EID_VHT_CAPABILITY,
4222+
ies->data, ies->len);
4223+
if (elem && elem->datalen >= sizeof(*bss_vht_cap))
4224+
bss_vht_cap = (const void *)elem->data;
4225+
}
4226+
42064227
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
42074228
elems->vht_cap_elem,
4208-
link_sta);
4229+
bss_vht_cap, link_sta);
4230+
rcu_read_unlock();
4231+
}
42094232

42104233
if (elems->he_operation && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) &&
42114234
elems->he_cap) {

net/mac80211/vht.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*
55
* Portions of this file
66
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
7-
* Copyright (C) 2018 - 2022 Intel Corporation
7+
* Copyright (C) 2018 - 2023 Intel Corporation
88
*/
99

1010
#include <linux/ieee80211.h>
@@ -116,12 +116,14 @@ void
116116
ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
117117
struct ieee80211_supported_band *sband,
118118
const struct ieee80211_vht_cap *vht_cap_ie,
119+
const struct ieee80211_vht_cap *vht_cap_ie2,
119120
struct link_sta_info *link_sta)
120121
{
121122
struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap;
122123
struct ieee80211_sta_vht_cap own_cap;
123124
u32 cap_info, i;
124125
bool have_80mhz;
126+
u32 mpdu_len;
125127

126128
memset(vht_cap, 0, sizeof(*vht_cap));
127129

@@ -317,11 +319,21 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
317319

318320
link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta);
319321

322+
/*
323+
* Work around the Cisco 9115 FW 17.3 bug by taking the min of
324+
* both reported MPDU lengths.
325+
*/
326+
mpdu_len = vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK;
327+
if (vht_cap_ie2)
328+
mpdu_len = min_t(u32, mpdu_len,
329+
le32_get_bits(vht_cap_ie2->vht_cap_info,
330+
IEEE80211_VHT_CAP_MAX_MPDU_MASK));
331+
320332
/*
321333
* FIXME - should the amsdu len be per link? store per link
322334
* and maintain a minimum?
323335
*/
324-
switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
336+
switch (mpdu_len) {
325337
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
326338
link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454;
327339
break;

0 commit comments

Comments
 (0)