Skip to content

Commit 8fa8eb5

Browse files
nbd168gregkh
authored andcommitted
wifi: mt76: mt7915: fix list corruption after hardware restart
[ Upstream commit 065c79d ] Since stations are recreated from scratch, all lists that wcids are added to must be cleared before calling ieee80211_restart_hw. Set wcid->sta = 0 for each wcid entry in order to ensure that they are not added again before they are ready. Fixes: 8a55712 ("wifi: mt76: mt7915: enable full system reset support") Link: https://patch.msgid.link/20250827085352.51636-4-nbd@nbd.name Signed-off-by: Felix Fietkau <nbd@nbd.name> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 69dcc19 commit 8fa8eb5

File tree

3 files changed

+43
-7
lines changed

3 files changed

+43
-7
lines changed

drivers/net/wireless/mediatek/mt76/mac80211.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,43 @@ void mt76_free_device(struct mt76_dev *dev)
818818
}
819819
EXPORT_SYMBOL_GPL(mt76_free_device);
820820

821+
static void mt76_reset_phy(struct mt76_phy *phy)
822+
{
823+
if (!phy)
824+
return;
825+
826+
INIT_LIST_HEAD(&phy->tx_list);
827+
}
828+
829+
void mt76_reset_device(struct mt76_dev *dev)
830+
{
831+
int i;
832+
833+
rcu_read_lock();
834+
for (i = 0; i < ARRAY_SIZE(dev->wcid); i++) {
835+
struct mt76_wcid *wcid;
836+
837+
wcid = rcu_dereference(dev->wcid[i]);
838+
if (!wcid)
839+
continue;
840+
841+
wcid->sta = 0;
842+
mt76_wcid_cleanup(dev, wcid);
843+
rcu_assign_pointer(dev->wcid[i], NULL);
844+
}
845+
rcu_read_unlock();
846+
847+
INIT_LIST_HEAD(&dev->wcid_list);
848+
INIT_LIST_HEAD(&dev->sta_poll_list);
849+
dev->vif_mask = 0;
850+
memset(dev->wcid_mask, 0, sizeof(dev->wcid_mask));
851+
852+
mt76_reset_phy(&dev->phy);
853+
for (i = 0; i < ARRAY_SIZE(dev->phys); i++)
854+
mt76_reset_phy(dev->phys[i]);
855+
}
856+
EXPORT_SYMBOL_GPL(mt76_reset_device);
857+
821858
struct mt76_phy *mt76_vif_phy(struct ieee80211_hw *hw,
822859
struct ieee80211_vif *vif)
823860
{

drivers/net/wireless/mediatek/mt76/mt76.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
12411241
struct ieee80211_rate *rates, int n_rates);
12421242
void mt76_unregister_device(struct mt76_dev *dev);
12431243
void mt76_free_device(struct mt76_dev *dev);
1244+
void mt76_reset_device(struct mt76_dev *dev);
12441245
void mt76_unregister_phy(struct mt76_phy *phy);
12451246

12461247
struct mt76_phy *mt76_alloc_radio_phy(struct mt76_dev *dev, unsigned int size,

drivers/net/wireless/mediatek/mt76/mt7915/mac.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,17 +1460,15 @@ mt7915_mac_full_reset(struct mt7915_dev *dev)
14601460
if (i == 10)
14611461
dev_err(dev->mt76.dev, "chip full reset failed\n");
14621462

1463-
spin_lock_bh(&dev->mt76.sta_poll_lock);
1464-
while (!list_empty(&dev->mt76.sta_poll_list))
1465-
list_del_init(dev->mt76.sta_poll_list.next);
1466-
spin_unlock_bh(&dev->mt76.sta_poll_lock);
1467-
1468-
memset(dev->mt76.wcid_mask, 0, sizeof(dev->mt76.wcid_mask));
1469-
dev->mt76.vif_mask = 0;
14701463
dev->phy.omac_mask = 0;
14711464
if (phy2)
14721465
phy2->omac_mask = 0;
14731466

1467+
mt76_reset_device(&dev->mt76);
1468+
1469+
INIT_LIST_HEAD(&dev->sta_rc_list);
1470+
INIT_LIST_HEAD(&dev->twt_list);
1471+
14741472
i = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
14751473
dev->mt76.global_wcid.idx = i;
14761474
dev->recovery.hw_full_reset = false;

0 commit comments

Comments
 (0)