mac80211: don't set set TDLS STA bandwidth wider than possible

When we set up a TDLS station, we set sta->sta.bandwidth solely based
on the capabilities, because the "what's the current bandwidth" check
is bypassed and only applied for other types of stations.

This leads to the unfortunate scenario that the sta->sta.bandwidth is
160 MHz if both stations support it, but we never actually configure
this bandwidth unless the AP is already using 160 MHz; even for wider
bandwidth support we only go up to 80 MHz (at least right now.)

For iwlwifi, this can also lead to firmware asserts, telling us that
we've configured the TX rates for a higher bandwidth than is actually
available due to the PHY configuration.

For non-TDLS, we check against the interface's requested bandwidth,
but we explicitly skip this check for TDLS to cope with the wider BW
case. Change this to
 (a) still limit to the TDLS peer's own chandef, which gets factored
     into the overall PHY configuration we request from the driver,
     and
 (b) limit it to when the TDLS peer is authorized, because it's only
     factored into the channel context in this case.

Fixes: 504871e602 ("mac80211: fix bandwidth computation for TDLS peers")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20201206145305.fcc7d29c4590.I11f77e9e25ddf871a3c8d5604650c763e2c5887a@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2020-12-06 14:54:44 +02:00
parent 3f8a39ff28
commit f65607cdbc
1 changed files with 10 additions and 4 deletions

View File

@ -465,12 +465,18 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta)
* IEEE80211-2016 specification makes higher bandwidth operation
* possible on the TDLS link if the peers have wider bandwidth
* capability.
*
* However, in this case, and only if the TDLS peer is authorized,
* limit to the tdls_chandef so that the configuration here isn't
* wider than what's actually requested on the channel context.
*/
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW))
return bw;
bw = min(bw, ieee80211_chan_width_to_rx_bw(bss_width));
test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW) &&
test_sta_flag(sta, WLAN_STA_AUTHORIZED) &&
sta->tdls_chandef.chan)
bw = min(bw, ieee80211_chan_width_to_rx_bw(sta->tdls_chandef.width));
else
bw = min(bw, ieee80211_chan_width_to_rx_bw(bss_width));
return bw;
}