diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
index c16606792539..bb02878fd8a4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
@@ -849,12 +849,14 @@ mt7996_rxfilter_show(struct seq_file *file, void *data)
 
 	mutex_lock(&phy->dev->mt76.mutex);
 
-	seq_printf(file, "CR: 0x%08x\n", phy->rxfilter);
+	seq_printf(file, "CR: 0x%08x\n", phy->rxfilter.cr);
 
-#define MT7996_RFCR_PRINT(flag) do {			\
-		if (phy->rxfilter & MT_WF_RFCR_##flag)	\
+#define __MT7996_RXFILTER_PRINT(reg, flag) do {		\
+		if (phy->rxfilter.reg & (flag))		\
 			seq_printf(file, #flag "\n");	\
 	} while (0)
+#define MT7996_RFCR_PRINT(flag) __MT7996_RXFILTER_PRINT(cr, MT_WF_RFCR_##flag)
+#define MT7996_RFCR1_PRINT(flag) __MT7996_RXFILTER_PRINT(cr1, MT_WF_RFCR1_##flag)
 
 	MT7996_RFCR_PRINT(DROP_STBC_MULTI);
 	MT7996_RFCR_PRINT(DROP_FCSFAIL);
@@ -877,6 +879,13 @@ mt7996_rxfilter_show(struct seq_file *file, void *data)
 	MT7996_RFCR_PRINT(DROP_NDPA);
 	MT7996_RFCR_PRINT(DROP_UNWANTED_CTL);
 
+	seq_printf(file, "\nCR1: 0x%08x\n", phy->rxfilter.cr1);
+	MT7996_RFCR1_PRINT(DROP_ACK);
+	MT7996_RFCR1_PRINT(DROP_BF_POLL);
+	MT7996_RFCR1_PRINT(DROP_BA);
+	MT7996_RFCR1_PRINT(DROP_CFEND);
+	MT7996_RFCR1_PRINT(DROP_CFACK);
+
 	mutex_unlock(&phy->dev->mt76.mutex);
 
 	return 0;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 91c64e3a0860..cbc9826320a7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -391,25 +391,60 @@ void mt7996_vif_link_remove(struct mt76_phy *mphy, struct ieee80211_vif *vif,
 static void mt7996_phy_set_rxfilter(struct mt7996_phy *phy)
 {
 	struct mt7996_dev *dev = phy->dev;
-	u32 ctl_flags = MT_WF_RFCR1_DROP_ACK |
-			MT_WF_RFCR1_DROP_BF_POLL |
-			MT_WF_RFCR1_DROP_BA |
-			MT_WF_RFCR1_DROP_CFEND |
-			MT_WF_RFCR1_DROP_CFACK;
-	u32 filter = phy->rxfilter;
-
-	if (filter & MT_WF_RFCR_DROP_OTHER_UC) {
-		filter |= MT_WF_RFCR_DROP_CTS |
-			  MT_WF_RFCR_DROP_RTS |
-			  MT_WF_RFCR_DROP_CTL_RSV |
-			  MT_WF_RFCR_DROP_FCSFAIL;
-	}
+	u32 supported_flags = 0;
+
+	/* Initially reset the filter */
+	phy->rxfilter.cr = 0;
+	phy->rxfilter.cr1 = 0;
+
+	/* The following HW flags should never be set here:
+	 * MT_WF_RFCR_DROP_OTHER_BSS
+	 * MT_WF_RFCR_DROP_OTHER_BEACON
+	 * MT_WF_RFCR_DROP_FRAME_REPORT
+	 * MT_WF_RFCR_DROP_PROBEREQ
+	 * MT_WF_RFCR_DROP_MCAST_FILTERED
+	 * MT_WF_RFCR_DROP_MCAST
+	 * MT_WF_RFCR_DROP_BCAST
+	 * MT_WF_RFCR_DROP_DUPLICATE
+	 * MT_WF_RFCR_DROP_A2_BSSID
+	 * MT_WF_RFCR_DROP_UNWANTED_CTL
+	 * MT_WF_RFCR_DROP_STBC_MULTI
+	 */
 
-	mt76_wr(dev, MT_WF_RFCR(phy->mt76->band_idx), filter);
-	if (filter & MT_WF_RFCR_DROP_CTL_RSV)
-		mt76_set(dev, MT_WF_RFCR1(phy->mt76->band_idx), ctl_flags);
-	else
-		mt76_clear(dev, MT_WF_RFCR1(phy->mt76->band_idx), ctl_flags);
+	supported_flags |= FIF_OTHER_BSS;
+	if (!(phy->mac80211_rxfilter_flags & FIF_OTHER_BSS))
+		phy->rxfilter.cr |= MT_WF_RFCR_DROP_OTHER_TIM |
+				    MT_WF_RFCR_DROP_A3_MAC |
+				    MT_WF_RFCR_DROP_A3_BSSID;
+
+	supported_flags |= FIF_FCSFAIL;
+	if (!(phy->mac80211_rxfilter_flags & FIF_FCSFAIL))
+		phy->rxfilter.cr |= MT_WF_RFCR_DROP_FCSFAIL;
+
+	supported_flags |= FIF_CONTROL;
+	if (!(phy->mac80211_rxfilter_flags & FIF_CONTROL))
+		phy->rxfilter.cr |= MT_WF_RFCR_DROP_CTS |
+				    MT_WF_RFCR_DROP_RTS |
+				    MT_WF_RFCR_DROP_CTL_RSV;
+
+	if (!phy->monitor_enabled)
+		phy->rxfilter.cr |= MT_WF_RFCR_DROP_CTS |
+				    MT_WF_RFCR_DROP_RTS |
+				    MT_WF_RFCR_DROP_CTL_RSV |
+				    MT_WF_RFCR_DROP_FCSFAIL |
+				    MT_WF_RFCR_DROP_OTHER_UC;
+
+	if (!((phy->mac80211_rxfilter_flags & FIF_CONTROL) || phy->monitor_enabled))
+		phy->rxfilter.cr1 |= MT_WF_RFCR1_DROP_ACK |
+				     MT_WF_RFCR1_DROP_BF_POLL |
+				     MT_WF_RFCR1_DROP_BA |
+				     MT_WF_RFCR1_DROP_CFEND |
+				     MT_WF_RFCR1_DROP_CFACK;
+
+	phy->mac80211_rxfilter_flags &= supported_flags;
+
+	mt76_wr(dev, MT_WF_RFCR(phy->mt76->band_idx), phy->rxfilter.cr);
+	mt76_wr(dev, MT_WF_RFCR1(phy->mt76->band_idx), phy->rxfilter.cr1);
 }
 
 static void mt7996_set_monitor(struct mt7996_phy *phy, bool enabled)
@@ -419,13 +454,10 @@ static void mt7996_set_monitor(struct mt7996_phy *phy, bool enabled)
 	if (!phy)
 		return;
 
-	if (enabled == !(phy->rxfilter & MT_WF_RFCR_DROP_OTHER_UC))
+	if (enabled == phy->monitor_enabled)
 		return;
 
-	if (!enabled)
-		phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
-	else
-		phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
+	phy->monitor_enabled = enabled;
 
 	mt76_rmw_field(dev, MT_DMA_DCR0(phy->mt76->band_idx),
 		       MT_DMA_DCR0_RXD_G5_EN, enabled);
@@ -620,46 +652,18 @@ static void mt7996_configure_filter(struct ieee80211_hw *hw,
 {
 	struct mt7996_dev *dev = mt7996_hw_dev(hw);
 	struct mt7996_phy *phy;
-	u32 filter_mask = 0, filter_set = 0;
 	u32 flags = 0;
 
-#define MT76_FILTER(_flag, _hw) do {				\
-		flags |= *total_flags & FIF_##_flag;		\
-		filter_mask |= (_hw);				\
-		filter_set |= !(flags & FIF_##_flag) * (_hw);	\
-	} while (0)
-
 	mutex_lock(&dev->mt76.mutex);
 
-	MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM |
-			       MT_WF_RFCR_DROP_A3_MAC |
-			       MT_WF_RFCR_DROP_A3_BSSID);
-
-	MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL);
-
-	MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS |
-			     MT_WF_RFCR_DROP_RTS |
-			     MT_WF_RFCR_DROP_CTL_RSV);
-
-	*total_flags = flags;
-
 	mt7996_for_each_phy(dev, phy) {
-		phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS |
-				   MT_WF_RFCR_DROP_OTHER_BEACON |
-				   MT_WF_RFCR_DROP_FRAME_REPORT |
-				   MT_WF_RFCR_DROP_PROBEREQ |
-				   MT_WF_RFCR_DROP_MCAST_FILTERED |
-				   MT_WF_RFCR_DROP_MCAST |
-				   MT_WF_RFCR_DROP_BCAST |
-				   MT_WF_RFCR_DROP_DUPLICATE |
-				   MT_WF_RFCR_DROP_A2_BSSID |
-				   MT_WF_RFCR_DROP_UNWANTED_CTL |
-				   MT_WF_RFCR_DROP_STBC_MULTI |
-				   filter_mask);
-		phy->rxfilter |= filter_set;
+		phy->mac80211_rxfilter_flags = *total_flags;
 		mt7996_phy_set_rxfilter(phy);
+		flags |= phy->mac80211_rxfilter_flags;
 	}
 
+	*total_flags = flags;
+
 	mutex_unlock(&dev->mt76.mutex);
 }
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 3300b7c8e4d2..2b2108f96255 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -273,7 +273,12 @@ struct mt7996_phy {
 	u8 throttle_state;
 	u32 throttle_temp[2]; /* 0: critical high, 1: maximum */
 
-	u32 rxfilter;
+	bool monitor_enabled;
+	u32 mac80211_rxfilter_flags;
+	struct {
+		u32 cr;
+		u32 cr1;
+	} rxfilter; /* Rx filter control registers */
 	u64 omac_mask;
 
 	u16 noise;
