mac80211 does not call remove_interface() after add_interface() fails, so the driver must undo any state it published before returning an error. mt7615_add_interface() records a monitor vif before resource allocation, and later reserves vif and OMAC bits and publishes the station WCID. An allocation or firmware failure leaves some or all of that state behind. The stale monitor_vif can then be used by the testmode transmit path after mac80211 frees the vif, while the leaked mask bits permanently consume interface resources. Unpublish the WCID and release its resources when adding device information fails, clear the reserved mask bits after failures that occur after their allocation, and clear monitor_vif on every failed add. Commit 2fb6480c52f6 ("wifi: mt76: mt7915: unwind state on add_interface failure") fixed the same failure-unwind issue in mt7915. Fixes: 4f0bce1c8888 ("mt76: mt7615: implement testmode support") Cc: stable@vger.kernel.org Signed-off-by: Jiale Yao --- .../net/wireless/mediatek/mt76/mt7615/main.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 67f56e428d9a..d20b109666dc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -219,7 +219,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, ret = mt7615_mcu_set_dbdc(dev); if (ret) - goto out; + goto err_mask; idx = MT7615_WTBL_RESERVED - mvif->mt76.idx; @@ -237,7 +237,24 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, } ret = mt7615_mcu_add_dev_info(phy, vif, true); + if (ret) + goto err_wcid; + + mt7615_mutex_release(dev); + + return 0; + +err_wcid: + rcu_assign_pointer(dev->mt76.wcid[idx], NULL); + mt76_wcid_cleanup(&dev->mt76, &mvif->sta.wcid); +err_mask: + dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); + dev->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); + phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); out: + if (phy->monitor_vif == vif) + phy->monitor_vif = NULL; + mt7615_mutex_release(dev); return ret; -- 2.34.1