OSDN Git Service

mt76: mt7915: fix rxrate reporting
authorRyder Lee <ryder.lee@mediatek.com>
Wed, 3 Mar 2021 10:37:59 +0000 (18:37 +0800)
committerFelix Fietkau <nbd@nbd.name>
Sun, 11 Apr 2021 22:01:24 +0000 (00:01 +0200)
Avoid directly updating sinfo->rxrate from firmware since rate_info might
be overwritten by wrong results even mt7915_mcu_get_rx_rate() fails check.

Add more error handlings accordingly.

Fixes: 11553d88d0b9 ("mt76: mt7915: query station rx rate from firmware")
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7915/main.c
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c

index cacc9b6..bb49ea9 100644 (file)
@@ -839,9 +839,12 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw,
        struct mt7915_phy *phy = mt7915_hw_phy(hw);
        struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
        struct mt7915_sta_stats *stats = &msta->stats;
+       struct rate_info rxrate = {};
 
-       if (mt7915_mcu_get_rx_rate(phy, vif, sta, &sinfo->rxrate) == 0)
+       if (!mt7915_mcu_get_rx_rate(phy, vif, sta, &rxrate)) {
+               sinfo->rxrate = rxrate;
                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
+       }
 
        if (!stats->tx_rate.legacy && !stats->tx_rate.flags)
                return;
index e0c03b7..b204c5d 100644 (file)
@@ -3552,9 +3552,8 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
        struct ieee80211_supported_band *sband;
        struct mt7915_mcu_phy_rx_info *res;
        struct sk_buff *skb;
-       u16 flags = 0;
        int ret;
-       int i;
+       bool cck = false;
 
        ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(PHY_STAT_INFO),
                                        &req, sizeof(req), true, &skb);
@@ -3568,48 +3567,53 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
 
        switch (res->mode) {
        case MT_PHY_TYPE_CCK:
+               cck = true;
+               fallthrough;
        case MT_PHY_TYPE_OFDM:
                if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
                        sband = &mphy->sband_5g.sband;
                else
                        sband = &mphy->sband_2g.sband;
 
-               for (i = 0; i < sband->n_bitrates; i++) {
-                       if (rate->mcs != (sband->bitrates[i].hw_value & 0xf))
-                               continue;
-
-                       rate->legacy = sband->bitrates[i].bitrate;
-                       break;
-               }
+               rate->mcs = mt76_get_rate(&dev->mt76, sband, rate->mcs, cck);
+               rate->legacy = sband->bitrates[rate->mcs].bitrate;
                break;
        case MT_PHY_TYPE_HT:
        case MT_PHY_TYPE_HT_GF:
-               if (rate->mcs > 31)
-                       return -EINVAL;
-
-               flags |= RATE_INFO_FLAGS_MCS;
+               if (rate->mcs > 31) {
+                       ret = -EINVAL;
+                       goto out;
+               }
 
+               rate->flags = RATE_INFO_FLAGS_MCS;
                if (res->gi)
-                       flags |= RATE_INFO_FLAGS_SHORT_GI;
+                       rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
                break;
        case MT_PHY_TYPE_VHT:
-               flags |= RATE_INFO_FLAGS_VHT_MCS;
+               if (rate->mcs > 9) {
+                       ret = -EINVAL;
+                       goto out;
+               }
 
+               rate->flags = RATE_INFO_FLAGS_VHT_MCS;
                if (res->gi)
-                       flags |= RATE_INFO_FLAGS_SHORT_GI;
+                       rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
                break;
        case MT_PHY_TYPE_HE_SU:
        case MT_PHY_TYPE_HE_EXT_SU:
        case MT_PHY_TYPE_HE_TB:
        case MT_PHY_TYPE_HE_MU:
+               if (res->gi > NL80211_RATE_INFO_HE_GI_3_2 || rate->mcs > 11) {
+                       ret = -EINVAL;
+                       goto out;
+               }
                rate->he_gi = res->gi;
-
-               flags |= RATE_INFO_FLAGS_HE_MCS;
+               rate->flags = RATE_INFO_FLAGS_HE_MCS;
                break;
        default:
-               break;
+               ret = -EINVAL;
+               goto out;
        }
-       rate->flags = flags;
 
        switch (res->bw) {
        case IEEE80211_STA_RX_BW_160:
@@ -3626,7 +3630,8 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
                break;
        }
 
+out:
        dev_kfree_skb(skb);
 
-       return 0;
+       return ret;
 }