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: 85cd5534a3f2e ("wifi: mt76: mt7996: use correct link_id when filling TXD and TXP") Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 12 +++--- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 52 ++++++++++++++++-------- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 2560e2f46e89a4bc46e21d796fca80b7decefa5c..4d33265971e2e00c788541a5c780dc20619e7396 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -2403,14 +2403,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 diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 8bf85a9beee7dc8c6741568af5b36cf89f0c1a88..1baace971ec3511dba3e8a64c236a2b55f9dbd36 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -945,6 +945,22 @@ mt7996_channel_switch_beacon(struct ieee80211_hw *hw, mutex_unlock(&dev->mt76.mutex); } +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, @@ -962,21 +978,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(sizeof(*msta_link), GFP_KERNEL); if (!msta_link) @@ -1058,13 +1063,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 == msta->deflink_id) { + /* no secondary link available */ + msta->deflink_id = IEEE80211_LINK_UNSPECIFIED; + msta->seclink_id = msta->deflink_id; + } else { + struct mt7996_sta_link *msta_seclink; + + /* switch to the secondary link */ + msta->deflink_id = msta->seclink_id; + msta_seclink = mt76_dereference( + msta->link[msta->seclink_id], + mdev); + if (msta_seclink) + 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); } } -- 2.52.0