From 6745cece7a0717d5f70946c07889bc86b02d5791 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 11 Sep 2025 15:02:05 +0200 Subject: [PATCH] wifi: mt76: mt7996: reset station links on hardware restart Ensure that all allocated memory is freed properly Signed-off-by: Felix Fietkau --- mt7996/mac.c | 27 +++++++++++++++++++++++++++ mt7996/main.c | 11 +++++------ mt7996/mt7996.h | 2 ++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/mt7996/mac.c b/mt7996/mac.c index f2f1a905..d519e081 100644 --- a/mt7996/mac.c +++ b/mt7996/mac.c @@ -2356,6 +2356,32 @@ out: return ret; } +static void +mt7996_mac_reset_sta_iter(void *data, struct ieee80211_sta *sta) +{ + struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; + struct mt7996_dev *dev = data; + int i; + + for (i = 0; i < ARRAY_SIZE(msta->link); i++) { + struct mt7996_sta_link *msta_link = NULL; + + msta_link = rcu_replace_pointer(msta->link[i], msta_link, + lockdep_is_held(&dev->mt76.mutex)); + if (!msta_link) + continue; + + mt7996_mac_sta_deinit_link(dev, msta_link); + + if (msta->deflink_id == i) { + msta->deflink_id = IEEE80211_LINK_UNSPECIFIED; + continue; + } + + kfree_rcu(msta_link, rcu_head); + } +} + static void mt7996_mac_full_reset(struct mt7996_dev *dev) { @@ -2385,6 +2411,7 @@ mt7996_mac_full_reset(struct mt7996_dev *dev) mt7996_for_each_phy(dev, phy) phy->omac_mask = 0; + ieee80211_iterate_stations_atomic(hw, mt7996_mac_reset_sta_iter, dev); mt76_reset_device(&dev->mt76); INIT_LIST_HEAD(&dev->sta_rc_list); diff --git a/mt7996/main.c b/mt7996/main.c index 32f88048..aa759605 100644 --- a/mt7996/main.c +++ b/mt7996/main.c @@ -1000,13 +1000,9 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev, return 0; } -static void -mt7996_mac_sta_deinit_link(struct mt7996_dev *dev, - struct mt7996_sta_link *msta_link) +void mt7996_mac_sta_deinit_link(struct mt7996_dev *dev, + struct mt7996_sta_link *msta_link) { - mt7996_mac_wtbl_update(dev, msta_link->wcid.idx, - MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - spin_lock_bh(&dev->mt76.sta_poll_lock); if (!list_empty(&msta_link->wcid.poll_list)) list_del_init(&msta_link->wcid.poll_list); @@ -1036,6 +1032,9 @@ mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_vif *vif, if (!msta_link) continue; + mt7996_mac_wtbl_update(dev, msta_link->wcid.idx, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); + mt7996_mac_sta_deinit_link(dev, msta_link); link = mt7996_vif_link(dev, vif, link_id); if (!link) diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h index 98116254..8ec2acdb 100644 --- a/mt7996/mt7996.h +++ b/mt7996/mt7996.h @@ -817,6 +817,8 @@ void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev, struct mt7996_vif_link *link, struct mt7996_sta_link *msta_link, u8 flowid); +void mt7996_mac_sta_deinit_link(struct mt7996_dev *dev, + struct mt7996_sta_link *msta_link); void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct ieee80211_twt_setup *twt);