.set_rts_threshold = mt7915_set_rts_threshold,
--- a/mt7996/main.c
+++ b/mt7996/main.c
-@@ -715,8 +715,7 @@ static void mt7996_configure_filter(stru
+@@ -717,8 +717,7 @@ static void mt7996_configure_filter(stru
}
static int
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt7996_phy *phy = mt7996_vif_link_phy(&mvif->deflink);
-@@ -1687,13 +1686,12 @@ out:
- rcu_read_unlock();
+@@ -1702,26 +1701,31 @@ static void mt7996_link_rate_ctrl_update
+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
}
-static void mt7996_link_sta_rc_update(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta,
+ u32 changed)
{
- struct mt7996_dev *dev = mt7996_hw_dev(hw);
- struct ieee80211_sta *sta = link_sta->sta;
+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
+- struct mt7996_sta_link *msta_link;
++ struct mt7996_dev *dev = mt7996_hw_dev(hw);
++ struct ieee80211_link_sta *link_sta;
++ unsigned int link_id;
+
+ rcu_read_lock();
+
+- msta_link = rcu_dereference(msta->link[link_sta->link_id]);
+- if (msta_link) {
+- struct mt7996_dev *dev = mt7996_hw_dev(hw);
++ for_each_sta_active_link(vif, sta, link_sta, link_id) {
++ struct mt7996_sta_link *msta_link;
++
++ msta_link = rcu_dereference(msta->link[link_sta->link_id]);
++ if (!msta_link)
++ continue;
+
+ mt7996_link_rate_ctrl_update(&changed, msta_link);
+- ieee80211_queue_work(hw, &dev->rc_work);
+ }
+
+ rcu_read_unlock();
++
++ ieee80211_queue_work(hw, &dev->rc_work);
+ }
- mt7996_link_rate_ctrl_update(&changed, sta);
- ieee80211_queue_work(hw, &dev->rc_work);
-@@ -2186,7 +2184,7 @@ const struct ieee80211_ops mt7996_ops =
+ static void mt7996_sta_rate_ctrl_update(void *data, struct ieee80211_sta *sta)
+@@ -2234,7 +2238,7 @@ const struct ieee80211_ops mt7996_ops =
.link_info_changed = mt7996_link_info_changed,
.sta_state = mt7996_sta_state,
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
int n_chains, delta;
--- a/mt76.h
+++ b/mt76.h
-@@ -1521,7 +1521,7 @@ int mt76_get_min_avg_rssi(struct mt76_de
+@@ -1547,7 +1547,7 @@ int mt76_get_min_avg_rssi(struct mt76_de
s8 mt76_get_power_bound(struct mt76_phy *phy, s8 txpower);
int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
--- /dev/null
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Tue, 12 Aug 2025 06:57:23 +0200
+Subject: [PATCH] net: mediatek: wed: Introduce MT7992 WED support to MT7988
+ SoC
+
+Introduce the second WDMA RX ring in WED driver for MT7988 SoC since the
+Mediatek MT7992 WiFi chipset supports two separated WDMA rings.
+Add missing MT7988 configurations to properly support WED for MT7992 in
+MT76 driver.
+
+Co-developed-by: Rex Lu <rex.lu@mediatek.com>
+Signed-off-by: Rex Lu <rex.lu@mediatek.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20250812-mt7992-wed-support-v3-1-9ada78a819a4@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+
+--- a/drivers/net/ethernet/mediatek/mtk_wed.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed.c
+@@ -59,7 +59,9 @@ struct mtk_wed_flow_block_priv {
+ static const struct mtk_wed_soc_data mt7622_data = {
+ .regmap = {
+ .tx_bm_tkid = 0x088,
+- .wpdma_rx_ring0 = 0x770,
++ .wpdma_rx_ring = {
++ 0x770,
++ },
+ .reset_idx_tx_mask = GENMASK(3, 0),
+ .reset_idx_rx_mask = GENMASK(17, 16),
+ },
+@@ -70,7 +72,9 @@ static const struct mtk_wed_soc_data mt7
+ static const struct mtk_wed_soc_data mt7986_data = {
+ .regmap = {
+ .tx_bm_tkid = 0x0c8,
+- .wpdma_rx_ring0 = 0x770,
++ .wpdma_rx_ring = {
++ 0x770,
++ },
+ .reset_idx_tx_mask = GENMASK(1, 0),
+ .reset_idx_rx_mask = GENMASK(7, 6),
+ },
+@@ -81,7 +85,10 @@ static const struct mtk_wed_soc_data mt7
+ static const struct mtk_wed_soc_data mt7988_data = {
+ .regmap = {
+ .tx_bm_tkid = 0x0c8,
+- .wpdma_rx_ring0 = 0x7d0,
++ .wpdma_rx_ring = {
++ 0x7d0,
++ 0x7d8,
++ },
+ .reset_idx_tx_mask = GENMASK(1, 0),
+ .reset_idx_rx_mask = GENMASK(7, 6),
+ },
+@@ -621,8 +628,8 @@ mtk_wed_amsdu_init(struct mtk_wed_device
+ return ret;
+ }
+
+- /* eagle E1 PCIE1 tx ring 22 flow control issue */
+- if (dev->wlan.id == 0x7991)
++ /* Kite and Eagle E1 PCIE1 tx ring 22 flow control issue */
++ if (dev->wlan.id == 0x7991 || dev->wlan.id == 0x7992)
+ wed_clr(dev, MTK_WED_AMSDU_FIFO, MTK_WED_AMSDU_IS_PRIOR0_RING);
+
+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN);
+@@ -1239,7 +1246,11 @@ mtk_wed_set_wpdma(struct mtk_wed_device
+ return;
+
+ wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo);
+- wed_w32(dev, dev->hw->soc->regmap.wpdma_rx_ring0, dev->wlan.wpdma_rx);
++ wed_w32(dev, dev->hw->soc->regmap.wpdma_rx_ring[0],
++ dev->wlan.wpdma_rx[0]);
++ if (mtk_wed_is_v3_or_greater(dev->hw))
++ wed_w32(dev, dev->hw->soc->regmap.wpdma_rx_ring[1],
++ dev->wlan.wpdma_rx[1]);
+
+ if (!dev->wlan.hw_rro)
+ return;
+@@ -2335,6 +2346,16 @@ mtk_wed_start(struct mtk_wed_device *dev
+ if (!dev->rx_wdma[i].desc)
+ mtk_wed_wdma_rx_ring_setup(dev, i, 16, false);
+
++ if (dev->wlan.hw_rro) {
++ for (i = 0; i < MTK_WED_RX_PAGE_QUEUES; i++) {
++ u32 addr = MTK_WED_RRO_MSDU_PG_CTRL0(i) +
++ MTK_WED_RING_OFS_COUNT;
++
++ if (!wed_r32(dev, addr))
++ wed_w32(dev, addr, 1);
++ }
++ }
++
+ mtk_wed_hw_init(dev);
+ mtk_wed_configure_irq(dev, irq_mask);
+
+--- a/drivers/net/ethernet/mediatek/mtk_wed.h
++++ b/drivers/net/ethernet/mediatek/mtk_wed.h
+@@ -17,7 +17,7 @@ struct mtk_wed_wo;
+ struct mtk_wed_soc_data {
+ struct {
+ u32 tx_bm_tkid;
+- u32 wpdma_rx_ring0;
++ u32 wpdma_rx_ring[MTK_WED_RX_QUEUES];
+ u32 reset_idx_tx_mask;
+ u32 reset_idx_rx_mask;
+ } regmap;
+--- a/include/linux/soc/mediatek/mtk_wed.h
++++ b/include/linux/soc/mediatek/mtk_wed.h
+@@ -147,7 +147,7 @@ struct mtk_wed_device {
+ u32 wpdma_tx;
+ u32 wpdma_txfree;
+ u32 wpdma_rx_glo;
+- u32 wpdma_rx;
++ u32 wpdma_rx[MTK_WED_RX_QUEUES];
+ u32 wpdma_rx_rro[MTK_WED_RX_QUEUES];
+ u32 wpdma_rx_pg;
+