]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: mt76: do not add wcid entries to sta poll list during MCU reset
authorFelix Fietkau <nbd@nbd.name>
Mon, 30 Dec 2024 19:42:02 +0000 (20:42 +0100)
committerFelix Fietkau <nbd@nbd.name>
Tue, 14 Jan 2025 12:34:37 +0000 (13:34 +0100)
Fixes linked list management issues during restart, where sta entries
can be recreated and reinitialized while still in the poll list, triggering
kernel warnings.

Link: https://patch.msgid.link/20241230194202.95065-14-nbd@nbd.name
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mac80211.c
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt7603/mac.c
drivers/net/wireless/mediatek/mt76/mt7615/mac.c
drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
drivers/net/wireless/mediatek/mt76/mt7915/mac.c
drivers/net/wireless/mediatek/mt76/mt7921/mac.c
drivers/net/wireless/mediatek/mt76/mt7925/mac.c
drivers/net/wireless/mediatek/mt76/mt7996/mac.c

index 3642c490fa6db81bec14e8eb9a7b243a110be0a3..6db59652be6e9329a78c3a0af1811224f46ec860 100644 (file)
@@ -1595,6 +1595,18 @@ void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid)
 }
 EXPORT_SYMBOL_GPL(mt76_wcid_cleanup);
 
+void mt76_wcid_add_poll(struct mt76_dev *dev, struct mt76_wcid *wcid)
+{
+       if (test_bit(MT76_MCU_RESET, &dev->phy.state))
+               return;
+
+       spin_lock_bh(&dev->sta_poll_lock);
+       if (list_empty(&wcid->poll_list))
+               list_add_tail(&wcid->poll_list, &dev->sta_poll_list);
+       spin_unlock_bh(&dev->sta_poll_lock);
+}
+EXPORT_SYMBOL_GPL(mt76_wcid_add_poll);
+
 int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                     unsigned int link_id, int *dbm)
 {
index 3bc591c14b65d262e4791ca0d5d877b218367cb8..34b6b094b8eb4169b49be5625c0d0649b607d54e 100644 (file)
@@ -1735,5 +1735,6 @@ mt76_token_put(struct mt76_dev *dev, int token)
 
 void mt76_wcid_init(struct mt76_wcid *wcid);
 void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid);
+void mt76_wcid_add_poll(struct mt76_dev *dev, struct mt76_wcid *wcid);
 
 #endif
index dc8a77f0a1cc4685ffc70fb2db1691c76b3fd480..dafa4b05f623fa66ddd5c2c2aa5423708605843e 100644 (file)
@@ -1277,12 +1277,7 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data)
 
        msta = container_of(wcid, struct mt7603_sta, wcid);
        sta = wcid_to_sta(wcid);
-
-       if (list_empty(&msta->wcid.poll_list)) {
-               spin_lock_bh(&dev->mt76.sta_poll_lock);
-               list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list);
-               spin_unlock_bh(&dev->mt76.sta_poll_lock);
-       }
+       mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
 
        if (mt7603_mac_add_txs_skb(dev, msta, pid, txs_data))
                goto out;
index 7ba789834e8df387ee3f7233b210a8587d279a9c..27c3857bcd7b862615eab6c004310e3fb10696ff 100644 (file)
@@ -387,11 +387,7 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
                struct mt7615_sta *msta;
 
                msta = container_of(status->wcid, struct mt7615_sta, wcid);
-               spin_lock_bh(&dev->mt76.sta_poll_lock);
-               if (list_empty(&msta->wcid.poll_list))
-                       list_add_tail(&msta->wcid.poll_list,
-                                     &dev->mt76.sta_poll_list);
-               spin_unlock_bh(&dev->mt76.sta_poll_lock);
+               mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
        }
 
        if (mt76_is_mmio(&dev->mt76) && (rxd0 & csum_mask) == csum_mask &&
@@ -1514,11 +1510,7 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
 
        msta = container_of(wcid, struct mt7615_sta, wcid);
        sta = wcid_to_sta(wcid);
-
-       spin_lock_bh(&dev->mt76.sta_poll_lock);
-       if (list_empty(&msta->wcid.poll_list))
-               list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list);
-       spin_unlock_bh(&dev->mt76.sta_poll_lock);
+       mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
 
        if (mt7615_mac_add_txs_skb(dev, msta, pid, txs_data))
                goto out;
index a72551ba27e46fec1034da9b468b2ac929857bd6..f719457e39b2f924f701c5073fa4756759f42c48 100644 (file)
@@ -1174,11 +1174,7 @@ void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t,
                if (wcid && wcid->sta) {
                        sta = container_of((void *)wcid, struct ieee80211_sta,
                                           drv_priv);
-                       spin_lock_bh(&dev->sta_poll_lock);
-                       if (list_empty(&wcid->poll_list))
-                               list_add_tail(&wcid->poll_list,
-                                             &dev->sta_poll_list);
-                       spin_unlock_bh(&dev->sta_poll_lock);
+                       mt76_wcid_add_poll(dev, wcid);
                }
        }
 
index e2693aea2e8e8ba3f873b0ae5bc07086fc99d139..13bdc0a7174c909c074c1647d27aec0e3f2f1d0f 100644 (file)
@@ -333,11 +333,7 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb,
 
        if (status->wcid) {
                msta = container_of(status->wcid, struct mt7915_sta, wcid);
-               spin_lock_bh(&dev->mt76.sta_poll_lock);
-               if (list_empty(&msta->wcid.poll_list))
-                       list_add_tail(&msta->wcid.poll_list,
-                                     &dev->mt76.sta_poll_list);
-               spin_unlock_bh(&dev->mt76.sta_poll_lock);
+               mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
        }
 
        status->freq = mphy->chandef.chan->center_freq;
@@ -927,11 +923,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
                                continue;
 
                        msta = container_of(wcid, struct mt7915_sta, wcid);
-                       spin_lock_bh(&mdev->sta_poll_lock);
-                       if (list_empty(&msta->wcid.poll_list))
-                               list_add_tail(&msta->wcid.poll_list,
-                                             &mdev->sta_poll_list);
-                       spin_unlock_bh(&mdev->sta_poll_lock);
+                       mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
                        continue;
                }
 
@@ -1040,10 +1032,7 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
        if (!wcid->sta)
                goto out;
 
-       spin_lock_bh(&dev->mt76.sta_poll_lock);
-       if (list_empty(&msta->wcid.poll_list))
-               list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list);
-       spin_unlock_bh(&dev->mt76.sta_poll_lock);
+       mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
 
 out:
        rcu_read_unlock();
index bd1455698ebe5f6d4d359e76894435ae85df0164..5dd57de59f275a7296af3d228542cd79272bf7ba 100644 (file)
@@ -216,11 +216,7 @@ mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb)
        if (status->wcid) {
                mlink = container_of(status->wcid, struct mt792x_link_sta, wcid);
                msta = container_of(mlink, struct mt792x_sta, deflink);
-               spin_lock_bh(&dev->mt76.sta_poll_lock);
-               if (list_empty(&mlink->wcid.poll_list))
-                       list_add_tail(&mlink->wcid.poll_list,
-                                     &dev->mt76.sta_poll_list);
-               spin_unlock_bh(&dev->mt76.sta_poll_lock);
+               mt76_wcid_add_poll(&dev->mt76, &mlink->wcid);
        }
 
        mt792x_get_status_freq_info(status, chfreq);
@@ -479,10 +475,7 @@ void mt7921_mac_add_txs(struct mt792x_dev *dev, void *data)
        if (!wcid->sta)
                goto out;
 
-       spin_lock_bh(&dev->mt76.sta_poll_lock);
-       if (list_empty(&mlink->wcid.poll_list))
-               list_add_tail(&mlink->wcid.poll_list, &dev->mt76.sta_poll_list);
-       spin_unlock_bh(&dev->mt76.sta_poll_lock);
+       mt76_wcid_add_poll(&dev->mt76, &mlink->wcid);
 
 out:
        rcu_read_unlock();
@@ -529,11 +522,7 @@ static void mt7921_mac_tx_free(struct mt792x_dev *dev, void *data, int len)
                                continue;
 
                        mlink = container_of(wcid, struct mt792x_link_sta, wcid);
-                       spin_lock_bh(&mdev->sta_poll_lock);
-                       if (list_empty(&mlink->wcid.poll_list))
-                               list_add_tail(&mlink->wcid.poll_list,
-                                             &mdev->sta_poll_list);
-                       spin_unlock_bh(&mdev->sta_poll_lock);
+                       mt76_wcid_add_poll(&dev->mt76, &mlink->wcid);
                        continue;
                }
 
index a095fb31e391a12264dd7d8e408a9e69f60999e8..187770537a1af776a5e0140829d81cb1c47c6b65 100644 (file)
@@ -395,11 +395,7 @@ mt7925_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb)
 
        if (status->wcid) {
                mlink = container_of(status->wcid, struct mt792x_link_sta, wcid);
-               spin_lock_bh(&dev->mt76.sta_poll_lock);
-               if (list_empty(&mlink->wcid.poll_list))
-                       list_add_tail(&mlink->wcid.poll_list,
-                                     &dev->mt76.sta_poll_list);
-               spin_unlock_bh(&dev->mt76.sta_poll_lock);
+               mt76_wcid_add_poll(&dev->mt76, &mlink->wcid);
        }
 
        mt792x_get_status_freq_info(status, chfreq);
@@ -1054,10 +1050,7 @@ void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data)
        if (!wcid->sta)
                goto out;
 
-       spin_lock_bh(&dev->mt76.sta_poll_lock);
-       if (list_empty(&mlink->wcid.poll_list))
-               list_add_tail(&mlink->wcid.poll_list, &dev->mt76.sta_poll_list);
-       spin_unlock_bh(&dev->mt76.sta_poll_lock);
+       mt76_wcid_add_poll(&dev->mt76, &mlink->wcid);
 
 out:
        rcu_read_unlock();
@@ -1135,11 +1128,7 @@ mt7925_mac_tx_free(struct mt792x_dev *dev, void *data, int len)
                                continue;
 
                        mlink = container_of(wcid, struct mt792x_link_sta, wcid);
-                       spin_lock_bh(&mdev->sta_poll_lock);
-                       if (list_empty(&mlink->wcid.poll_list))
-                               list_add_tail(&mlink->wcid.poll_list,
-                                             &mdev->sta_poll_list);
-                       spin_unlock_bh(&mdev->sta_poll_lock);
+                       mt76_wcid_add_poll(&dev->mt76, &mlink->wcid);
                        continue;
                }
 
index 4706ddefea9e11fdb341557aa13689d88baae7e3..8e3620d8a7c896624e198a306420347494424017 100644 (file)
@@ -478,11 +478,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
 
        if (status->wcid) {
                msta = container_of(status->wcid, struct mt7996_sta, wcid);
-               spin_lock_bh(&dev->mt76.sta_poll_lock);
-               if (list_empty(&msta->wcid.poll_list))
-                       list_add_tail(&msta->wcid.poll_list,
-                                     &dev->mt76.sta_poll_list);
-               spin_unlock_bh(&dev->mt76.sta_poll_lock);
+               mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
        }
 
        status->freq = mphy->chandef.chan->center_freq;
@@ -1149,11 +1145,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
                                continue;
 
                        msta = container_of(wcid, struct mt7996_sta, wcid);
-                       spin_lock_bh(&mdev->sta_poll_lock);
-                       if (list_empty(&msta->wcid.poll_list))
-                               list_add_tail(&msta->wcid.poll_list,
-                                             &mdev->sta_poll_list);
-                       spin_unlock_bh(&mdev->sta_poll_lock);
+                       mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
                        continue;
                } else if (info & MT_TXFREE_INFO_HEADER) {
                        u32 tx_retries = 0, tx_failed = 0;
@@ -1379,10 +1371,7 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
        if (!wcid->sta)
                goto out;
 
-       spin_lock_bh(&dev->mt76.sta_poll_lock);
-       if (list_empty(&msta->wcid.poll_list))
-               list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list);
-       spin_unlock_bh(&dev->mt76.sta_poll_lock);
+       mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
 
 out:
        rcu_read_unlock();