wifi: mt76: mt7996: Switch to the secondary link if the default one is removed

Switch to the secondary link if available in mt7996_mac_sta_remove_links
routine if the primary one is removed.
Moreover reset secondary link index for single link scenario.

Fixes: 85cd5534a3 ("wifi: mt76: mt7996: use correct link_id when filling TXD and TXP")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20251205-mt76-txq-wicd-fix-v2-3-f19ba48af7c1@kernel.org
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Lorenzo Bianconi 2025-12-05 11:24:38 +01:00 committed by Felix Fietkau
parent 751a2679b1
commit 5ef44c2006
2 changed files with 41 additions and 22 deletions

View File

@ -2365,14 +2365,12 @@ mt7996_mac_reset_sta_iter(void *data, struct ieee80211_sta *sta)
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);
if (msta_link != &msta->deflink)
kfree_rcu(msta_link, rcu_head);
}
msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
msta->seclink_id = msta->deflink_id;
}
static void

View File

@ -994,6 +994,22 @@ mt7996_post_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
return ret;
}
static void
mt7996_sta_init_txq_wcid(struct ieee80211_sta *sta, int idx)
{
int i;
for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
struct mt76_txq *mtxq;
if (!sta->txq[i])
continue;
mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
mtxq->wcid = idx;
}
}
static int
mt7996_mac_sta_init_link(struct mt7996_dev *dev,
struct ieee80211_bss_conf *link_conf,
@ -1011,21 +1027,10 @@ mt7996_mac_sta_init_link(struct mt7996_dev *dev,
return -ENOSPC;
if (msta->deflink_id == IEEE80211_LINK_UNSPECIFIED) {
int i;
msta_link = &msta->deflink;
msta->deflink_id = link_id;
msta->seclink_id = msta->deflink_id;
for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
struct mt76_txq *mtxq;
if (!sta->txq[i])
continue;
mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
mtxq->wcid = idx;
}
mt7996_sta_init_txq_wcid(sta, idx);
} else {
msta_link = kzalloc_obj(*msta_link);
if (!msta_link)
@ -1108,12 +1113,28 @@ mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
mphy->num_sta--;
if (msta->deflink_id == link_id) {
msta->deflink_id = IEEE80211_LINK_UNSPECIFIED;
continue;
if (msta->seclink_id == link_id) {
/* no secondary link available */
msta->seclink_id = msta->deflink_id;
} else {
struct mt7996_sta_link *msta_seclink;
/* switch to the secondary link */
msta_seclink = mt76_dereference(
msta->link[msta->seclink_id],
mdev);
if (msta_seclink) {
msta->deflink_id = msta->seclink_id;
mt7996_sta_init_txq_wcid(sta,
msta_seclink->wcid.idx);
}
}
} else if (msta->seclink_id == link_id) {
msta->seclink_id = IEEE80211_LINK_UNSPECIFIED;
msta->seclink_id = msta->deflink_id;
}
kfree_rcu(msta_link, rcu_head);
if (msta_link != &msta->deflink)
kfree_rcu(msta_link, rcu_head);
}
}