mirror of
https://github.com/torvalds/linux.git
synced 2026-05-22 22:22:08 +02:00
wifi: mt76: mt7925: host-only unwind published links on add failure
Release host link resources when mt7925_mac_sta_add_links() fails after partial success. msta->link[] and dev->mt76.wcid[] may already be published, so unwind the host state to avoid leaving stale links behind. Signed-off-by: Sean Wang <sean.wang@mediatek.com> Link: https://patch.msgid.link/20260306232238.2039675-20-sean.wang@kernel.org Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
db13469192
commit
9fc83205a6
|
|
@ -989,11 +989,51 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Host-only unwind for sta_add_links() failures.
|
||||
*
|
||||
* If add_links fail due to MCU/firmware timeouts; calling the full remove
|
||||
* path would send more firmware commands and may hang again. So only rollback
|
||||
* host-published state here (msta->link/valid_links, dev->mt76.wcid[idx]) and
|
||||
* free mlink objects (RCU-safe). Firmware state is left for reset/recovery.
|
||||
*/
|
||||
static void
|
||||
mt7925_mac_sta_unwind_links_host(struct mt792x_dev *dev,
|
||||
struct ieee80211_sta *sta,
|
||||
unsigned long links)
|
||||
{
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
|
||||
unsigned int link_id;
|
||||
|
||||
for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct mt792x_link_sta *mlink;
|
||||
u16 idx;
|
||||
|
||||
mlink = rcu_replace_pointer(msta->link[link_id], NULL,
|
||||
lockdep_is_held(&dev->mt76.mutex));
|
||||
if (!mlink)
|
||||
continue;
|
||||
|
||||
msta->valid_links &= ~BIT(link_id);
|
||||
if (msta->deflink_id == link_id)
|
||||
msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
|
||||
|
||||
idx = mlink->wcid.idx;
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
|
||||
mt76_wcid_cleanup(&dev->mt76, &mlink->wcid);
|
||||
mt76_wcid_mask_clear(dev->mt76.wcid_mask, idx);
|
||||
|
||||
if (mlink != &msta->deflink)
|
||||
kfree_rcu(mlink, rcu_head);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mt7925_mac_sta_add_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, unsigned long new_links)
|
||||
{
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
|
||||
unsigned long added_links = 0;
|
||||
unsigned int link_id;
|
||||
int err = 0;
|
||||
|
||||
|
|
@ -1030,8 +1070,13 @@ mt7925_mac_sta_add_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
|||
|
||||
rcu_assign_pointer(msta->link[link_id], mlink);
|
||||
msta->valid_links |= BIT(link_id);
|
||||
|
||||
added_links |= BIT(link_id);
|
||||
}
|
||||
|
||||
if (err && added_links)
|
||||
mt7925_mac_sta_unwind_links_host(dev, sta, added_links);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user