]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
wifi: mt76: move wed common utilities in wed.c
authorLorenzo Bianconi <lorenzo@kernel.org>
Mon, 11 Dec 2023 12:07:29 +0000 (13:07 +0100)
committerFelix Fietkau <nbd@nbd.name>
Thu, 22 Feb 2024 08:55:18 +0000 (09:55 +0100)
Introduce wed.c in order to collect mt76 wed common codebase used by
mt7915 and mt7996 drivers.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
13 files changed:
drivers/net/wireless/mediatek/mt76/Makefile
drivers/net/wireless/mediatek/mt76/dma.c
drivers/net/wireless/mediatek/mt76/dma.h
drivers/net/wireless/mediatek/mt76/mac80211.c
drivers/net/wireless/mediatek/mt76/mmio.c
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt7915/dma.c
drivers/net/wireless/mediatek/mt76/mt7915/main.c
drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
drivers/net/wireless/mediatek/mt76/mt7996/dma.c
drivers/net/wireless/mediatek/mt76/mt7996/main.c
drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
drivers/net/wireless/mediatek/mt76/wed.c [new file with mode: 0644]

index d6575fe18c6b0274712c4c4d88a81d6f6661b4cd..f7f2d9a8ab0f967af92503d7bc555b13af1671f6 100644 (file)
@@ -10,7 +10,7 @@ obj-$(CONFIG_MT792x_USB) += mt792x-usb.o
 
 mt76-y := \
        mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \
-       tx.o agg-rx.o mcu.o
+       tx.o agg-rx.o mcu.o wed.o
 
 mt76-$(CONFIG_PCI) += pci.o
 mt76-$(CONFIG_NL80211_TESTMODE) += testmode.o
index 00230f106294bef5ef9869b88548762e1941fd95..72a7bd5a85769572be15c113786990095c5de28b 100644 (file)
@@ -197,9 +197,8 @@ mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
        q->tail = q->head;
 }
 
-static void
-__mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q,
-                      bool reset_idx)
+void __mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q,
+                           bool reset_idx)
 {
        if (!q || !q->ndesc)
                return;
@@ -219,8 +218,7 @@ __mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q,
        mt76_dma_sync_idx(dev, q);
 }
 
-static void
-mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
+void mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
 {
        __mt76_dma_queue_reset(dev, q, true);
 }
@@ -632,9 +630,8 @@ free_skb:
        return ret;
 }
 
-static int
-mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
-                bool allow_direct)
+int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
+                    bool allow_direct)
 {
        int len = SKB_WITH_OVERHEAD(q->buf_size);
        int frames = 0;
@@ -681,81 +678,6 @@ done:
        return frames;
 }
 
-int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
-{
-#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-       int ret = 0, type, ring;
-       u16 flags;
-
-       if (!q || !q->ndesc)
-               return -EINVAL;
-
-       flags = q->flags;
-       if (!q->wed || !mtk_wed_device_active(q->wed))
-               q->flags &= ~MT_QFLAG_WED;
-
-       if (!(q->flags & MT_QFLAG_WED))
-               return 0;
-
-       type = FIELD_GET(MT_QFLAG_WED_TYPE, q->flags);
-       ring = FIELD_GET(MT_QFLAG_WED_RING, q->flags);
-
-       switch (type) {
-       case MT76_WED_Q_TX:
-               ret = mtk_wed_device_tx_ring_setup(q->wed, ring, q->regs,
-                                                  reset);
-               if (!ret)
-                       q->wed_regs = q->wed->tx_ring[ring].reg_base;
-               break;
-       case MT76_WED_Q_TXFREE:
-               /* WED txfree queue needs ring to be initialized before setup */
-               q->flags = 0;
-               mt76_dma_queue_reset(dev, q);
-               mt76_dma_rx_fill(dev, q, false);
-
-               ret = mtk_wed_device_txfree_ring_setup(q->wed, q->regs);
-               if (!ret)
-                       q->wed_regs = q->wed->txfree_ring.reg_base;
-               break;
-       case MT76_WED_Q_RX:
-               ret = mtk_wed_device_rx_ring_setup(q->wed, ring, q->regs,
-                                                  reset);
-               if (!ret)
-                       q->wed_regs = q->wed->rx_ring[ring].reg_base;
-               break;
-       case MT76_WED_RRO_Q_DATA:
-               q->flags &= ~MT_QFLAG_WED;
-               __mt76_dma_queue_reset(dev, q, false);
-               mtk_wed_device_rro_rx_ring_setup(q->wed, ring, q->regs);
-               q->head = q->ndesc - 1;
-               q->queued = q->head;
-               break;
-       case MT76_WED_RRO_Q_MSDU_PG:
-               q->flags &= ~MT_QFLAG_WED;
-               __mt76_dma_queue_reset(dev, q, false);
-               mtk_wed_device_msdu_pg_rx_ring_setup(q->wed, ring, q->regs);
-               q->head = q->ndesc - 1;
-               q->queued = q->head;
-               break;
-       case MT76_WED_RRO_Q_IND:
-               q->flags &= ~MT_QFLAG_WED;
-               mt76_dma_queue_reset(dev, q);
-               mt76_dma_rx_fill(dev, q, false);
-               mtk_wed_device_ind_rx_ring_setup(q->wed, q->regs);
-               break;
-       default:
-               ret = -EINVAL;
-               break;
-       }
-       q->flags = flags;
-
-       return ret;
-#else
-       return 0;
-#endif
-}
-EXPORT_SYMBOL_GPL(mt76_dma_wed_setup);
-
 static int
 mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
                     int idx, int n_desc, int bufsize,
@@ -800,7 +722,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
        if (ret)
                return ret;
 
-       ret = mt76_dma_wed_setup(dev, q, false);
+       ret = mt76_wed_dma_setup(dev, q, false);
        if (ret)
                return ret;
 
@@ -863,7 +785,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
        mt76_dma_rx_cleanup(dev, q);
 
        /* reset WED rx queues */
-       mt76_dma_wed_setup(dev, q, true);
+       mt76_wed_dma_setup(dev, q, true);
 
        if (mt76_queue_is_wed_tx_free(q))
                return;
@@ -1054,20 +976,6 @@ void mt76_dma_attach(struct mt76_dev *dev)
 }
 EXPORT_SYMBOL_GPL(mt76_dma_attach);
 
-void mt76_dma_wed_reset(struct mt76_dev *dev)
-{
-       struct mt76_mmio *mmio = &dev->mmio;
-
-       if (!test_bit(MT76_STATE_WED_RESET, &dev->phy.state))
-               return;
-
-       complete(&mmio->wed_reset);
-
-       if (!wait_for_completion_timeout(&mmio->wed_reset_complete, 3 * HZ))
-               dev_err(dev->dev, "wed reset complete timeout\n");
-}
-EXPORT_SYMBOL_GPL(mt76_dma_wed_reset);
-
 void mt76_dma_cleanup(struct mt76_dev *dev)
 {
        int i;
index c479cc6388eff4f260cb3e39898ed3e3b0a5c499..1de5a2b20f747838884f61a454f25bdecb1c1d41 100644 (file)
@@ -79,15 +79,18 @@ enum mt76_dma_wed_ind_reason {
 int mt76_dma_rx_poll(struct napi_struct *napi, int budget);
 void mt76_dma_attach(struct mt76_dev *dev);
 void mt76_dma_cleanup(struct mt76_dev *dev);
-int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset);
-void mt76_dma_wed_reset(struct mt76_dev *dev);
+int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
+                    bool allow_direct);
+void __mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q,
+                           bool reset_idx);
+void mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q);
 
 static inline void
 mt76_dma_reset_tx_queue(struct mt76_dev *dev, struct mt76_queue *q)
 {
        dev->queue_ops->reset_q(dev, q);
        if (mtk_wed_device_active(&dev->mmio.wed))
-               mt76_dma_wed_setup(dev, q, true);
+               mt76_wed_dma_setup(dev, q, true);
 }
 
 static inline void
index 758e380fdf1dd4991b9c4029499538835ebfcf9a..e3ebadcd149946d874cc680f8b03b15277cdf97b 100644 (file)
@@ -1854,19 +1854,3 @@ enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy)
        return MT_DFS_STATE_ACTIVE;
 }
 EXPORT_SYMBOL_GPL(mt76_phy_dfs_state);
-
-#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-int mt76_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                     struct net_device *netdev, enum tc_setup_type type,
-                     void *type_data)
-{
-       struct mt76_phy *phy = hw->priv;
-       struct mtk_wed_device *wed = &phy->dev->mmio.wed;
-
-       if (!mtk_wed_device_active(wed))
-               return -EOPNOTSUPP;
-
-       return mtk_wed_device_setup_tc(wed, netdev, type, type_data);
-}
-EXPORT_SYMBOL_GPL(mt76_net_setup_tc);
-#endif /* CONFIG_NET_MEDIATEK_SOC_WED */
index c3e0e23e0161ac7daac34190c3b363b99fc94399..cd2e9737c3bf9275699046c03749aa13b9bf1d77 100644 (file)
@@ -85,113 +85,6 @@ void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr,
 }
 EXPORT_SYMBOL_GPL(mt76_set_irq_mask);
 
-#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
-{
-       struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
-       int i;
-
-       for (i = 0; i < dev->rx_token_size; i++) {
-               struct mt76_txwi_cache *t;
-
-               t = mt76_rx_token_release(dev, i);
-               if (!t || !t->ptr)
-                       continue;
-
-               mt76_put_page_pool_buf(t->ptr, false);
-               t->ptr = NULL;
-
-               mt76_put_rxwi(dev, t);
-       }
-
-       mt76_free_pending_rxwi(dev);
-}
-EXPORT_SYMBOL_GPL(mt76_mmio_wed_release_rx_buf);
-
-u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
-{
-       struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
-       struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc;
-       struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
-       int i, len = SKB_WITH_OVERHEAD(q->buf_size);
-       struct mt76_txwi_cache *t = NULL;
-
-       for (i = 0; i < size; i++) {
-               enum dma_data_direction dir;
-               dma_addr_t addr;
-               u32 offset;
-               int token;
-               void *buf;
-
-               t = mt76_get_rxwi(dev);
-               if (!t)
-                       goto unmap;
-
-               buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
-               if (!buf)
-                       goto unmap;
-
-               addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset;
-               dir = page_pool_get_dma_dir(q->page_pool);
-               dma_sync_single_for_device(dev->dma_dev, addr, len, dir);
-
-               desc->buf0 = cpu_to_le32(addr);
-               token = mt76_rx_token_consume(dev, buf, t, addr);
-               if (token < 0) {
-                       mt76_put_page_pool_buf(buf, false);
-                       goto unmap;
-               }
-
-               token = FIELD_PREP(MT_DMA_CTL_TOKEN, token);
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-               token |= FIELD_PREP(MT_DMA_CTL_SDP0_H, addr >> 32);
-#endif
-               desc->token |= cpu_to_le32(token);
-               desc++;
-       }
-
-       return 0;
-
-unmap:
-       if (t)
-               mt76_put_rxwi(dev, t);
-       mt76_mmio_wed_release_rx_buf(wed);
-
-       return -ENOMEM;
-}
-EXPORT_SYMBOL_GPL(mt76_mmio_wed_init_rx_buf);
-
-int mt76_mmio_wed_offload_enable(struct mtk_wed_device *wed)
-{
-       struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
-
-       spin_lock_bh(&dev->token_lock);
-       dev->token_size = wed->wlan.token_start;
-       spin_unlock_bh(&dev->token_lock);
-
-       return !wait_event_timeout(dev->tx_wait, !dev->wed_token_count, HZ);
-}
-EXPORT_SYMBOL_GPL(mt76_mmio_wed_offload_enable);
-
-void mt76_mmio_wed_offload_disable(struct mtk_wed_device *wed)
-{
-       struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
-
-       spin_lock_bh(&dev->token_lock);
-       dev->token_size = dev->drv->token_size;
-       spin_unlock_bh(&dev->token_lock);
-}
-EXPORT_SYMBOL_GPL(mt76_mmio_wed_offload_disable);
-
-void mt76_mmio_wed_reset_complete(struct mtk_wed_device *wed)
-{
-       struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
-
-       complete(&dev->mmio.wed_reset_complete);
-}
-EXPORT_SYMBOL_GPL(mt76_mmio_wed_reset_complete);
-#endif /*CONFIG_NET_MEDIATEK_SOC_WED */
-
 void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
 {
        static const struct mt76_bus_ops mt76_mmio_ops = {
index 98fe533af20fdd7aa23fdfdd28739974cff5b571..ac969a88438b927b5d6b89c8a31f249d554cf50a 100644 (file)
@@ -1082,12 +1082,6 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
 void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs);
 void mt76_pci_disable_aspm(struct pci_dev *pdev);
 
-#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-int mt76_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                     struct net_device *netdev, enum tc_setup_type type,
-                     void *type_data);
-#endif /*CONFIG_NET_MEDIATEK_SOC_WED */
-
 static inline u16 mt76_chip(struct mt76_dev *dev)
 {
        return dev->rev >> 16;
@@ -1098,13 +1092,34 @@ static inline u16 mt76_rev(struct mt76_dev *dev)
        return dev->rev & 0xffff;
 }
 
+void mt76_wed_release_rx_buf(struct mtk_wed_device *wed);
+void mt76_wed_offload_disable(struct mtk_wed_device *wed);
+void mt76_wed_reset_complete(struct mtk_wed_device *wed);
+void mt76_wed_dma_reset(struct mt76_dev *dev);
+int mt76_wed_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                         struct net_device *netdev, enum tc_setup_type type,
+                         void *type_data);
 #ifdef CONFIG_NET_MEDIATEK_SOC_WED
-u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size);
-void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed);
-int mt76_mmio_wed_offload_enable(struct mtk_wed_device *wed);
-void mt76_mmio_wed_offload_disable(struct mtk_wed_device *wed);
-void mt76_mmio_wed_reset_complete(struct mtk_wed_device *wed);
-#endif /*CONFIG_NET_MEDIATEK_SOC_WED */
+u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size);
+int mt76_wed_offload_enable(struct mtk_wed_device *wed);
+int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset);
+#else
+static inline u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
+{
+       return 0;
+}
+
+static inline int mt76_wed_offload_enable(struct mtk_wed_device *wed)
+{
+       return 0;
+}
+
+static inline int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q,
+                                    bool reset)
+{
+       return 0;
+}
+#endif /* CONFIG_NET_MEDIATEK_SOC_WED */
 
 #define mt76xx_chip(dev) mt76_chip(&((dev)->mt76))
 #define mt76xx_rev(dev) mt76_rev(&((dev)->mt76))
index c91a1c54027fa3503e83a5b84f6ec68fe0910fce..0baa82c8df5ac0576b9378f5be544e50ebc7db7b 100644 (file)
@@ -614,7 +614,7 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force)
                mtk_wed_device_dma_reset(wed);
 
        mt7915_dma_disable(dev, force);
-       mt76_dma_wed_reset(&dev->mt76);
+       mt76_wed_dma_reset(&dev->mt76);
 
        /* reset hw queues */
        for (i = 0; i < __MT_TXQ_MAX; i++) {
index df2d4279790d9df2fc27d401324464b647cb0d91..3709d18da0e6baafee9d171bffb4a166a2c00b33 100644 (file)
@@ -1708,6 +1708,6 @@ const struct ieee80211_ops mt7915_ops = {
        .set_radar_background = mt7915_set_radar_background,
 #ifdef CONFIG_NET_MEDIATEK_SOC_WED
        .net_fill_forward_path = mt7915_net_fill_forward_path,
-       .net_setup_tc = mt76_net_setup_tc,
+       .net_setup_tc = mt76_wed_net_setup_tc,
 #endif
 };
index dceb505987b19841874d35a8814c5f81216a1bf0..d6ecd698cdcd08de199f3a180e48e6dd99504706 100644 (file)
@@ -706,13 +706,13 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
        }
 
        wed->wlan.init_buf = mt7915_wed_init_buf;
-       wed->wlan.offload_enable = mt76_mmio_wed_offload_enable;
-       wed->wlan.offload_disable = mt76_mmio_wed_offload_disable;
-       wed->wlan.init_rx_buf = mt76_mmio_wed_init_rx_buf;
-       wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf;
+       wed->wlan.offload_enable = mt76_wed_offload_enable;
+       wed->wlan.offload_disable = mt76_wed_offload_disable;
+       wed->wlan.init_rx_buf = mt76_wed_init_rx_buf;
+       wed->wlan.release_rx_buf = mt76_wed_release_rx_buf;
        wed->wlan.update_wo_rx_stats = mt7915_mmio_wed_update_rx_stats;
        wed->wlan.reset = mt7915_mmio_wed_reset;
-       wed->wlan.reset_complete = mt76_mmio_wed_reset_complete;
+       wed->wlan.reset_complete = mt76_wed_reset_complete;
 
        dev->mt76.rx_token_size = wed->wlan.rx_npkt;
 
index fe37110e66875c469a6355cb1c90b295d8e95a3e..73e633d0d7004c2217c7ebcab9eaa62b48b383a6 100644 (file)
@@ -695,7 +695,7 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
                mtk_wed_device_dma_reset(&dev->mt76.mmio.wed);
 
        mt7996_dma_disable(dev, force);
-       mt76_dma_wed_reset(&dev->mt76);
+       mt76_wed_dma_reset(&dev->mt76);
 
        /* reset hw queues */
        for (i = 0; i < __MT_TXQ_MAX; i++) {
index 0889a699d603c2f004826ccbe8f77eb9118962aa..f7da8d6dd9030a114c8bd166d44e8054ad10973b 100644 (file)
@@ -1502,6 +1502,6 @@ const struct ieee80211_ops mt7996_ops = {
        .set_radar_background = mt7996_set_radar_background,
 #ifdef CONFIG_NET_MEDIATEK_SOC_WED
        .net_fill_forward_path = mt7996_net_fill_forward_path,
-       .net_setup_tc = mt76_net_setup_tc,
+       .net_setup_tc = mt76_wed_net_setup_tc,
 #endif
 };
index efd4a767eb37dbecf93e39d1986b9fefb7dc751e..304e5fd1480340db0c147e8f4bf65f8861665a89 100644 (file)
@@ -410,13 +410,13 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
        wed->wlan.amsdu_max_len = 1536;
 
        wed->wlan.init_buf = mt7996_wed_init_buf;
-       wed->wlan.init_rx_buf = mt76_mmio_wed_init_rx_buf;
-       wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf;
-       wed->wlan.offload_enable = mt76_mmio_wed_offload_enable;
-       wed->wlan.offload_disable = mt76_mmio_wed_offload_disable;
+       wed->wlan.init_rx_buf = mt76_wed_init_rx_buf;
+       wed->wlan.release_rx_buf = mt76_wed_release_rx_buf;
+       wed->wlan.offload_enable = mt76_wed_offload_enable;
+       wed->wlan.offload_disable = mt76_wed_offload_disable;
        if (!hif2) {
                wed->wlan.reset = mt7996_mmio_wed_reset;
-               wed->wlan.reset_complete = mt76_mmio_wed_reset_complete;
+               wed->wlan.reset_complete = mt76_wed_reset_complete;
        }
 
        if (mtk_wed_device_attach(wed))
diff --git a/drivers/net/wireless/mediatek/mt76/wed.c b/drivers/net/wireless/mediatek/mt76/wed.c
new file mode 100644 (file)
index 0000000..f89e453
--- /dev/null
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (C) 2023 Lorenzo Bianconi <lorenzo@kernel.org>
+ */
+
+#include "mt76.h"
+#include "dma.h"
+
+void mt76_wed_release_rx_buf(struct mtk_wed_device *wed)
+{
+       struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
+       int i;
+
+       for (i = 0; i < dev->rx_token_size; i++) {
+               struct mt76_txwi_cache *t;
+
+               t = mt76_rx_token_release(dev, i);
+               if (!t || !t->ptr)
+                       continue;
+
+               mt76_put_page_pool_buf(t->ptr, false);
+               t->ptr = NULL;
+
+               mt76_put_rxwi(dev, t);
+       }
+
+       mt76_free_pending_rxwi(dev);
+}
+EXPORT_SYMBOL_GPL(mt76_wed_release_rx_buf);
+
+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
+{
+       struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
+       struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc;
+       struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
+       int i, len = SKB_WITH_OVERHEAD(q->buf_size);
+       struct mt76_txwi_cache *t = NULL;
+
+       for (i = 0; i < size; i++) {
+               enum dma_data_direction dir;
+               dma_addr_t addr;
+               u32 offset;
+               int token;
+               void *buf;
+
+               t = mt76_get_rxwi(dev);
+               if (!t)
+                       goto unmap;
+
+               buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
+               if (!buf)
+                       goto unmap;
+
+               addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset;
+               dir = page_pool_get_dma_dir(q->page_pool);
+               dma_sync_single_for_device(dev->dma_dev, addr, len, dir);
+
+               desc->buf0 = cpu_to_le32(addr);
+               token = mt76_rx_token_consume(dev, buf, t, addr);
+               if (token < 0) {
+                       mt76_put_page_pool_buf(buf, false);
+                       goto unmap;
+               }
+
+               token = FIELD_PREP(MT_DMA_CTL_TOKEN, token);
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+               token |= FIELD_PREP(MT_DMA_CTL_SDP0_H, addr >> 32);
+#endif
+               desc->token |= cpu_to_le32(token);
+               desc++;
+       }
+
+       return 0;
+
+unmap:
+       if (t)
+               mt76_put_rxwi(dev, t);
+       mt76_wed_release_rx_buf(wed);
+
+       return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(mt76_wed_init_rx_buf);
+
+int mt76_wed_offload_enable(struct mtk_wed_device *wed)
+{
+       struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
+
+       spin_lock_bh(&dev->token_lock);
+       dev->token_size = wed->wlan.token_start;
+       spin_unlock_bh(&dev->token_lock);
+
+       return !wait_event_timeout(dev->tx_wait, !dev->wed_token_count, HZ);
+}
+EXPORT_SYMBOL_GPL(mt76_wed_offload_enable);
+
+int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+{
+       int ret = 0, type, ring;
+       u16 flags;
+
+       if (!q || !q->ndesc)
+               return -EINVAL;
+
+       flags = q->flags;
+       if (!q->wed || !mtk_wed_device_active(q->wed))
+               q->flags &= ~MT_QFLAG_WED;
+
+       if (!(q->flags & MT_QFLAG_WED))
+               return 0;
+
+       type = FIELD_GET(MT_QFLAG_WED_TYPE, q->flags);
+       ring = FIELD_GET(MT_QFLAG_WED_RING, q->flags);
+
+       switch (type) {
+       case MT76_WED_Q_TX:
+               ret = mtk_wed_device_tx_ring_setup(q->wed, ring, q->regs,
+                                                  reset);
+               if (!ret)
+                       q->wed_regs = q->wed->tx_ring[ring].reg_base;
+               break;
+       case MT76_WED_Q_TXFREE:
+               /* WED txfree queue needs ring to be initialized before setup */
+               q->flags = 0;
+               mt76_dma_queue_reset(dev, q);
+               mt76_dma_rx_fill(dev, q, false);
+
+               ret = mtk_wed_device_txfree_ring_setup(q->wed, q->regs);
+               if (!ret)
+                       q->wed_regs = q->wed->txfree_ring.reg_base;
+               break;
+       case MT76_WED_Q_RX:
+               ret = mtk_wed_device_rx_ring_setup(q->wed, ring, q->regs,
+                                                  reset);
+               if (!ret)
+                       q->wed_regs = q->wed->rx_ring[ring].reg_base;
+               break;
+       case MT76_WED_RRO_Q_DATA:
+               q->flags &= ~MT_QFLAG_WED;
+               __mt76_dma_queue_reset(dev, q, false);
+               mtk_wed_device_rro_rx_ring_setup(q->wed, ring, q->regs);
+               q->head = q->ndesc - 1;
+               q->queued = q->head;
+               break;
+       case MT76_WED_RRO_Q_MSDU_PG:
+               q->flags &= ~MT_QFLAG_WED;
+               __mt76_dma_queue_reset(dev, q, false);
+               mtk_wed_device_msdu_pg_rx_ring_setup(q->wed, ring, q->regs);
+               q->head = q->ndesc - 1;
+               q->queued = q->head;
+               break;
+       case MT76_WED_RRO_Q_IND:
+               q->flags &= ~MT_QFLAG_WED;
+               mt76_dma_queue_reset(dev, q);
+               mt76_dma_rx_fill(dev, q, false);
+               mtk_wed_device_ind_rx_ring_setup(q->wed, q->regs);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       q->flags = flags;
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(mt76_wed_dma_setup);
+#endif /*CONFIG_NET_MEDIATEK_SOC_WED */
+
+void mt76_wed_offload_disable(struct mtk_wed_device *wed)
+{
+       struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
+
+       spin_lock_bh(&dev->token_lock);
+       dev->token_size = dev->drv->token_size;
+       spin_unlock_bh(&dev->token_lock);
+}
+EXPORT_SYMBOL_GPL(mt76_wed_offload_disable);
+
+void mt76_wed_reset_complete(struct mtk_wed_device *wed)
+{
+       struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
+
+       complete(&dev->mmio.wed_reset_complete);
+}
+EXPORT_SYMBOL_GPL(mt76_wed_reset_complete);
+
+int mt76_wed_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                         struct net_device *netdev, enum tc_setup_type type,
+                         void *type_data)
+{
+       struct mt76_phy *phy = hw->priv;
+       struct mtk_wed_device *wed = &phy->dev->mmio.wed;
+
+       if (!mtk_wed_device_active(wed))
+               return -EOPNOTSUPP;
+
+       return mtk_wed_device_setup_tc(wed, netdev, type, type_data);
+}
+EXPORT_SYMBOL_GPL(mt76_wed_net_setup_tc);
+
+void mt76_wed_dma_reset(struct mt76_dev *dev)
+{
+       struct mt76_mmio *mmio = &dev->mmio;
+
+       if (!test_bit(MT76_STATE_WED_RESET, &dev->phy.state))
+               return;
+
+       complete(&mmio->wed_reset);
+
+       if (!wait_for_completion_timeout(&mmio->wed_reset_complete, 3 * HZ))
+               dev_err(dev->dev, "wed reset complete timeout\n");
+}
+EXPORT_SYMBOL_GPL(mt76_wed_dma_reset);