mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 07:59:42 -04:00
wifi: mt76: mt7915: fix list corruption after hardware restart
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: 8a55712d12 ("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>
This commit is contained in:
@@ -818,6 +818,43 @@ void mt76_free_device(struct mt76_dev *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_free_device);
|
||||
|
||||
static void mt76_reset_phy(struct mt76_phy *phy)
|
||||
{
|
||||
if (!phy)
|
||||
return;
|
||||
|
||||
INIT_LIST_HEAD(&phy->tx_list);
|
||||
}
|
||||
|
||||
void mt76_reset_device(struct mt76_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
rcu_read_lock();
|
||||
for (i = 0; i < ARRAY_SIZE(dev->wcid); i++) {
|
||||
struct mt76_wcid *wcid;
|
||||
|
||||
wcid = rcu_dereference(dev->wcid[i]);
|
||||
if (!wcid)
|
||||
continue;
|
||||
|
||||
wcid->sta = 0;
|
||||
mt76_wcid_cleanup(dev, wcid);
|
||||
rcu_assign_pointer(dev->wcid[i], NULL);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
INIT_LIST_HEAD(&dev->wcid_list);
|
||||
INIT_LIST_HEAD(&dev->sta_poll_list);
|
||||
dev->vif_mask = 0;
|
||||
memset(dev->wcid_mask, 0, sizeof(dev->wcid_mask));
|
||||
|
||||
mt76_reset_phy(&dev->phy);
|
||||
for (i = 0; i < ARRAY_SIZE(dev->phys); i++)
|
||||
mt76_reset_phy(dev->phys[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_reset_device);
|
||||
|
||||
struct mt76_phy *mt76_vif_phy(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
|
||||
@@ -1243,6 +1243,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
|
||||
struct ieee80211_rate *rates, int n_rates);
|
||||
void mt76_unregister_device(struct mt76_dev *dev);
|
||||
void mt76_free_device(struct mt76_dev *dev);
|
||||
void mt76_reset_device(struct mt76_dev *dev);
|
||||
void mt76_unregister_phy(struct mt76_phy *phy);
|
||||
|
||||
struct mt76_phy *mt76_alloc_radio_phy(struct mt76_dev *dev, unsigned int size,
|
||||
|
||||
@@ -1460,17 +1460,15 @@ mt7915_mac_full_reset(struct mt7915_dev *dev)
|
||||
if (i == 10)
|
||||
dev_err(dev->mt76.dev, "chip full reset failed\n");
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
while (!list_empty(&dev->mt76.sta_poll_list))
|
||||
list_del_init(dev->mt76.sta_poll_list.next);
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
memset(dev->mt76.wcid_mask, 0, sizeof(dev->mt76.wcid_mask));
|
||||
dev->mt76.vif_mask = 0;
|
||||
dev->phy.omac_mask = 0;
|
||||
if (phy2)
|
||||
phy2->omac_mask = 0;
|
||||
|
||||
mt76_reset_device(&dev->mt76);
|
||||
|
||||
INIT_LIST_HEAD(&dev->sta_rc_list);
|
||||
INIT_LIST_HEAD(&dev->twt_list);
|
||||
|
||||
i = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
|
||||
dev->mt76.global_wcid.idx = i;
|
||||
dev->recovery.hw_full_reset = false;
|
||||
|
||||
Reference in New Issue
Block a user