]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
mt76: mt7915: fix txrate reporting
authorRyder Lee <ryder.lee@mediatek.com>
Wed, 3 Mar 2021 10:38:00 +0000 (18:38 +0800)
committerKelsey Skunberg <kelsey.skunberg@canonical.com>
Mon, 24 May 2021 23:46:37 +0000 (17:46 -0600)
BugLink: https://bugs.launchpad.net/bugs/1929455
[ Upstream commit f43b941fd61003659a3f0e039595e5e525917aa8 ]

Properly check rate_info to fix unexpected reporting.

[ 1215.161863] Call trace:
[ 1215.164307]  cfg80211_calculate_bitrate+0x124/0x200 [cfg80211]
[ 1215.170139]  ieee80211s_update_metric+0x80/0xc0 [mac80211]
[ 1215.175624]  ieee80211_tx_status_ext+0x508/0x838 [mac80211]
[ 1215.181190]  mt7915_mcu_get_rx_rate+0x28c/0x8d0 [mt7915e]
[ 1215.186580]  mt7915_mac_tx_free+0x324/0x7c0 [mt7915e]
[ 1215.191623]  mt7915_queue_rx_skb+0xa8/0xd0 [mt7915e]
[ 1215.196582]  mt76_dma_cleanup+0x7b0/0x11d0 [mt76]
[ 1215.201276]  __napi_poll+0x38/0xf8
[ 1215.204668]  napi_workfn+0x40/0x80
[ 1215.208062]  process_one_work+0x1fc/0x390
[ 1215.212062]  worker_thread+0x48/0x4d0
[ 1215.215715]  kthread+0x120/0x128
[ 1215.218935]  ret_from_fork+0x10/0x1c

Fixes: e57b7901469f ("mt76: add mac80211 driver for MT7915 PCIe-based chipsets")
Fixes: e4c5ead632ff ("mt76: mt7915: rename mt7915_mcu_get_rate_info to mt7915_mcu_get_tx_rate")
Reported-by: Evelyn Tsai <evelyn.tsai@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Kelsey Skunberg <kelsey.skunberg@canonical.com>
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c

index ad71b8767c58c65a1c4cd7b22d4626abfb42b9f7..35bfa197dff6d13f777074c0aae2e65b796a6fca 100644 (file)
@@ -351,54 +351,62 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
        dev->hw_pattern++;
 }
 
-static void
+static int
 mt7915_mcu_tx_rate_parse(struct mt76_phy *mphy, struct mt7915_mcu_ra_info *ra,
                         struct rate_info *rate, u16 r)
 {
        struct ieee80211_supported_band *sband;
        u16 ru_idx = le16_to_cpu(ra->ru_idx);
-       u16 flags = 0;
+       bool cck = false;
 
        rate->mcs = FIELD_GET(MT_RA_RATE_MCS, r);
        rate->nss = FIELD_GET(MT_RA_RATE_NSS, r) + 1;
 
        switch (FIELD_GET(MT_RA_RATE_TX_MODE, r)) {
        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;
 
+               rate->mcs = mt76_get_rate(mphy->dev, sband, rate->mcs, cck);
                rate->legacy = sband->bitrates[rate->mcs].bitrate;
                break;
        case MT_PHY_TYPE_HT:
        case MT_PHY_TYPE_HT_GF:
                rate->mcs += (rate->nss - 1) * 8;
-               flags |= RATE_INFO_FLAGS_MCS;
+               if (rate->mcs > 31)
+                       return -EINVAL;
 
+               rate->flags = RATE_INFO_FLAGS_MCS;
                if (ra->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)
+                       return -EINVAL;
 
+               rate->flags = RATE_INFO_FLAGS_VHT_MCS;
                if (ra->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 (ra->gi > NL80211_RATE_INFO_HE_GI_3_2 || rate->mcs > 11)
+                       return -EINVAL;
+
                rate->he_gi = ra->gi;
                rate->he_dcm = FIELD_GET(MT_RA_RATE_DCM_EN, r);
-
-               flags |= RATE_INFO_FLAGS_HE_MCS;
+               rate->flags = RATE_INFO_FLAGS_HE_MCS;
                break;
        default:
-               break;
+               return -EINVAL;
        }
-       rate->flags = flags;
 
        if (ru_idx) {
                switch (ru_idx) {
@@ -435,6 +443,8 @@ mt7915_mcu_tx_rate_parse(struct mt76_phy *mphy, struct mt7915_mcu_ra_info *ra,
                        break;
                }
        }
+
+       return 0;
 }
 
 static void
@@ -465,12 +475,12 @@ mt7915_mcu_tx_rate_report(struct mt7915_dev *dev, struct sk_buff *skb)
                mphy = dev->mt76.phy2;
 
        /* current rate */
-       mt7915_mcu_tx_rate_parse(mphy, ra, &rate, curr);
-       stats->tx_rate = rate;
+       if (!mt7915_mcu_tx_rate_parse(mphy, ra, &rate, curr))
+               stats->tx_rate = rate;
 
        /* probing rate */
-       mt7915_mcu_tx_rate_parse(mphy, ra, &prob_rate, probe);
-       stats->prob_rate = prob_rate;
+       if (!mt7915_mcu_tx_rate_parse(mphy, ra, &prob_rate, probe))
+               stats->prob_rate = prob_rate;
 
        if (attempts) {
                u16 success = le16_to_cpu(ra->success);