If the driver doesn't fill NL80211_STA_INFO_TX_BITRATE in sta_set_sinfo() then as a fallback sta->deflink.tx_stats.last_rate is used. Unfortunately there's no guarantee that this has actually been set before it's used. Originally found when 'iw <dev> link' would always return a tx rate of 6Mbps regardless of actual link speed for the QCA9337 running firmware WLAN.TF.2.1-00021-QCARMSWP-1 in my netbook. Use the sanity check logic from ieee80211_fill_rx_status() and refactor that to use the new inline function. Signed-off-by: Stephen Douthit <stephen.douthit@xxxxxxxxx> --- include/net/mac80211.h | 7 +++++++ net/mac80211/airtime.c | 2 +- net/mac80211/sta_info.c | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 2635e6de8101..f6d4fd4d7ce9 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1058,6 +1058,13 @@ struct ieee80211_tx_rate { #define IEEE80211_MAX_TX_RETRY 31 +static inline int ieee80211_rate_invalid(struct ieee80211_tx_rate *rate) +{ + if (rate->idx < 0 || !rate->count) + return -EINVAL; + return 0; +} + static inline void ieee80211_rate_set_vht(struct ieee80211_tx_rate *rate, u8 mcs, u8 nss) { diff --git a/net/mac80211/airtime.c b/net/mac80211/airtime.c index e8ebd343e2bf..35ca46a9d709 100644 --- a/net/mac80211/airtime.c +++ b/net/mac80211/airtime.c @@ -557,7 +557,7 @@ static int ieee80211_fill_rx_status(struct ieee80211_rx_status *stat, if (ieee80211_fill_rate_info(hw, stat, band, ri)) return 0; - if (rate->idx < 0 || !rate->count) + if (ieee80211_rate_invalid(rate)) return -1; if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 27c737fe7fb8..f1c39de65f67 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -2675,7 +2675,8 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, } if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) && - !sta->sta.valid_links) { + !sta->sta.valid_links && + !ieee80211_rate_invalid(&sta->deflink.tx_stats.last_rate)) { sta_set_rate_info_tx(sta, &sta->deflink.tx_stats.last_rate, &sinfo->txrate); sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); -- 2.39.1