MT_MDP_DCR0_RX_HDR_TRANS_EN is one bit for the whole chip, but mt7996_set_monitor() writes it from the state of one radio. When a monitor interface goes away that covers a radio no other monitor covers, mt7996_remove_interface() turns sniffer mode off on that radio, and header translation comes back on while a monitor of another radio still runs. Frames translated to 802.3 do not reach monitor interfaces, so that monitor stops receiving the data frames addressed to the device. Turn header translation off while any radio of the device is in monitor mode, like mt7915_config() does with dev->monitor_mask. Fixes: 947d63d8cd3b ("wifi: mt76: mt7996: Disable Rx hdr_trans in monitor mode") Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 6815f5192116..ec7c5e8f3fda 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -612,6 +612,17 @@ static void mt7996_phy_set_rxfilter(struct mt7996_phy *phy) mt76_clear(dev, MT_WF_RFCR1(phy->mt76->band_idx), ctl_flags); } +static bool mt7996_monitor_active(struct mt7996_dev *dev) +{ + struct mt7996_phy *phy; + + mt7996_for_each_phy(dev, phy) + if (!(phy->rxfilter & MT_WF_RFCR_DROP_OTHER_UC)) + return true; + + return false; +} + static void mt7996_set_monitor(struct mt7996_phy *phy, bool enabled) { struct mt7996_dev *dev; @@ -632,7 +643,7 @@ static void mt7996_set_monitor(struct mt7996_phy *phy, bool enabled) mt76_rmw_field(dev, MT_DMA_DCR0(phy->mt76->band_idx), MT_DMA_DCR0_RXD_G5_EN, enabled); mt76_rmw_field(dev, MT_MDP_DCR0, - MT_MDP_DCR0_RX_HDR_TRANS_EN, !enabled); + MT_MDP_DCR0_RX_HDR_TRANS_EN, !mt7996_monitor_active(dev)); mt7996_phy_set_rxfilter(phy); mt7996_mcu_set_sniffer_mode(phy, enabled); } -- 2.47.3