Linux wireless drivers development
 help / color / mirror / Atom feed
From: "Eason Lai (賴易聖)" <Eason.Lai@mediatek.com>
To: "lorenzo@kernel.org" <lorenzo@kernel.org>
Cc: "Yf Luo (羅元富)" <Yf.Luo@mediatek.com>,
	"nbd@nbd.name" <nbd@nbd.name>,
	"Kun Wu (吳謹至)" <kun.wu@mediatek.com>,
	"Quan Zhou (周全)" <Quan.Zhou@mediatek.com>,
	"Deren Wu (武德仁)" <Deren.Wu@mediatek.com>,
	"Ryder Lee" <Ryder.Lee@mediatek.com>,
	"linux-wireless@vger.kernel.org" <linux-wireless@vger.kernel.org>,
	"Sean Wang" <Sean.Wang@mediatek.com>,
	"Leon Yen (顏良儒)" <Leon.Yen@mediatek.com>,
	"linux-mediatek@lists.infradead.org"
	<linux-mediatek@lists.infradead.org>,
	"Litien Chang (張立典)" <Litien.Chang@mediatek.com>,
	"JB Tsai (蔡志彬)" <Jb.Tsai@mediatek.com>
Subject: Re: [PATCH 2/3] wifi: mt76: mt792x: Add TX page pool support for IOMMU-enabled systems
Date: Mon, 13 Jul 2026 03:13:05 +0000	[thread overview]
Message-ID: <b3239d674f05e87d8602d533a374806bf5e0a4ba.camel@mediatek.com> (raw)
In-Reply-To: <ak9bWO47T3fo2NkI@lore-desk>

On Thu, 2026-07-09 at 10:27 +0200, Lorenzo Bianconi wrote:
> On Jul 09, Eason Lai wrote:
> > From: Eason Lai <Eason.Lai@mediatek.com>
> > 
> > Add support for TX page pool allocation in mt792x devices when
> > IOMMU is
> > enabled. This optimization reduces DMA mapping overhead by
> > pre-allocating and reusing page pool buffers for TX operations.
> 
> Can you please provide some test results here? In particular
> regarding the
> resulting throughput.
> 

On MT8196, the HE160 TCP UL peak throuhgput could drop below 1.4Gbps
when IOMMU is enabled. With this series, the throughput reaches the
expected performance (>1.8G bps).

> > 
> > Key changes:
> > - Export DMA helper functions and ops for mt792x usage
> >   - Add tx_prealloc_enabled flag to track page pool state
> >     - Implement mt792x-specific DMA queue operations with TX page
> > pool
> >       - Create page pools per TX queue when IOMMU is detected
> >         - Handle page pool buffer cleanup in both success and error
> >           paths
> > - Add proper skip_unmap flag handling for page pool buffers
> > 
> > The page pool path is used for linear skbs without fragments,
> > falling
> > back to standard DMA mapping for complex skb structures.
> > 
> > Signed-off-by: Eason Lai <Eason.Lai@mediatek.com>
> > ---
> 
> [...]
> 
> >  
> > -static void
> > +void
> >  mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q)
> >  {
> >  	wmb();
> > @@ -409,6 +417,7 @@ mt76_dma_kick_queue(struct mt76_dev *dev,
> > struct mt76_queue *q)
> >  	else
> >  		Q_WRITE(q, cpu_idx, q->head);
> >  }
> > +EXPORT_SYMBOL_GPL(mt76_dma_kick_queue);
> 
> this is already available in mt76_queue_ops struct.
> 

Thanks. I'll use mt76_queue_kick() in v2.

> >  
> >  static void
> >  mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q,
> > bool flush)
> > @@ -1152,7 +1161,7 @@ mt76_dma_init(struct mt76_dev *dev,
> >  	return 0;
> >  }
> >  
> > -static const struct mt76_queue_ops mt76_dma_ops = {
> > +const struct mt76_queue_ops mt76_dma_ops = {
> >  	.init = mt76_dma_init,
> >  	.alloc = mt76_dma_alloc_queue,
> >  	.reset_q = mt76_dma_queue_reset,
> > @@ -1164,6 +1173,7 @@ static const struct mt76_queue_ops
> > mt76_dma_ops = {
> >  	.rx_reset = mt76_dma_rx_reset,
> >  	.kick = mt76_dma_kick_queue,
> >  };
> > +EXPORT_SYMBOL_GPL(mt76_dma_ops);
> >  
> >  void mt76_dma_attach(struct mt76_dev *dev)
> >  {
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h
> > b/drivers/net/wireless/mediatek/mt76/mt76.h
> > index 927c21536f4e..25e24fa36eca 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> > +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> > @@ -957,6 +957,8 @@ struct mt76_dev {
> >  	int tx_dma_idx[4];
> >  	enum mt76_hwrro_mode hwrro_mode;
> >  
> > +	bool tx_prealloc_enabled;
> > +
> >  	struct mt76_worker tx_worker;
> >  	struct napi_struct tx_napi;
> >  
> > @@ -1785,7 +1787,16 @@ mt76_tx_status_get_hw(struct mt76_dev *dev,
> > struct sk_buff *skb)
> >  
> >  void mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache
> > *t);
> >  void mt76_put_rxwi(struct mt76_dev *dev, struct mt76_txwi_cache
> > *t);
> > +struct mt76_txwi_cache *mt76_get_txwi(struct mt76_dev *dev);
> >  struct mt76_txwi_cache *mt76_get_rxwi(struct mt76_dev *dev);
> > +int mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
> > +		     struct mt76_queue_buf *buf, int nbufs, u32
> > info,
> > +		     struct sk_buff *skb, void *txwi);
> > +void mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct
> > mt76_queue *q, int idx,
> > +			     struct mt76_queue_entry *prev_e);
> > +void mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue
> > *q);
> > +void mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue
> > *q);
> > +extern const struct mt76_queue_ops mt76_dma_ops;
> >  void mt76_free_pending_rxwi(struct mt76_dev *dev);
> >  void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head
> > *frames,
> >  		      struct napi_struct *napi);
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
> > b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
> > index 0339e2e7ab60..d4b36b0832b8 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
> > @@ -250,6 +250,12 @@ void mt76_connac_txp_skb_unmap(struct mt76_dev
> > *dev,
> >  {
> >  	struct mt76_connac_txp_common *txp;
> >  
> > +	if (t->page_pool_buf) {
> > +		mt76_put_page_pool_buf(t->page_pool_buf, false);
> > +		t->page_pool_buf = NULL;
> > +		return;
> > +	}
> > +
> >  	txp = mt76_connac_txwi_to_txp(dev, t);
> >  	if (is_mt76_fw_txp(dev))
> >  		mt76_connac_txp_skb_unmap_fw(dev, &txp->fw);
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
> > b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
> > index c4161754c01d..3d69d8c67dea 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
> > @@ -214,7 +214,7 @@ static int mt7925_dma_init(struct mt792x_dev
> > *dev)
> >  {
> >  	int ret;
> >  
> > -	mt76_dma_attach(&dev->mt76);
> > +	mt792x_dma_attach(&dev->mt76);
> >  
> >  	ret = mt792x_dma_disable(dev, true);
> >  	if (ret)
> > @@ -263,6 +263,8 @@ static int mt7925_dma_init(struct mt792x_dev
> > *dev)
> >  			  mt792x_poll_tx);
> >  	napi_enable(&dev->mt76.tx_napi);
> >  
> > +	mt792x_dma_tx_page_pool_init(dev);
> > +
> >  	return mt792x_dma_enable(dev);
> >  }
> >  
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h
> > b/drivers/net/wireless/mediatek/mt76/mt792x.h
> > index 4ff93f2cd624..7ac0318dc249 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt792x.h
> > +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
> > @@ -418,8 +418,10 @@ void mt792x_sta_statistics(struct ieee80211_hw
> > *hw,
> >  			   struct station_info *sinfo);
> >  void mt792x_set_coverage_class(struct ieee80211_hw *hw, int
> > radio_idx,
> >  			       s16 coverage_class);
> > +void mt792x_dma_attach(struct mt76_dev *dev);
> >  void mt792x_dma_cleanup(struct mt792x_dev *dev);
> >  int mt792x_dma_enable(struct mt792x_dev *dev);
> > +int mt792x_dma_tx_page_pool_init(struct mt792x_dev *dev);
> >  int mt792x_wpdma_reset(struct mt792x_dev *dev, bool force);
> >  int mt792x_wpdma_reinit_cond(struct mt792x_dev *dev);
> >  int mt792x_dma_disable(struct mt792x_dev *dev, bool force);
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
> > b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
> > index 002aece857b2..b341f1cb3ce0 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
> > @@ -3,6 +3,9 @@
> >  
> >  #include <linux/module.h>
> >  #include <linux/firmware.h>
> > +#include <linux/iommu.h>
> > +#include <net/page_pool/helpers.h>
> > +#include <linux/of.h>
> >  
> >  #include "mt792x.h"
> >  #include "dma.h"
> > @@ -266,6 +269,323 @@ int mt792x_wpdma_reinit_cond(struct
> > mt792x_dev *dev)
> >  }
> >  EXPORT_SYMBOL_GPL(mt792x_wpdma_reinit_cond);
> >  
> > +static int mt792x_create_tx_page_pool(struct mt76_dev *dev, struct
> > mt76_queue *q)
> > +{
> > +	struct page_pool_params pp_params = {
> > +		.order = 0,
> > +		.flags = 0,
> > +		.nid = NUMA_NO_NODE,
> > +		.dev = dev->dma_dev,
> > +	};
> > +
> > +	if (!q || !dev->tx_prealloc_enabled)
> > +		return 0;
> > +
> > +	if (!mt76_is_mmio(dev))
> > +		return 0;
> 
> do you really need this check? you already check it in
> mt792x_dma_tx_page_pool_init().
> 

OK, I will remove it in v2.

> > +
> > +	pp_params.pool_size = 256;
> > +	pp_params.flags |= PP_FLAG_DMA_MAP;
> > +	pp_params.dma_dir = DMA_BIDIRECTIONAL;
> > +	pp_params.max_len = PAGE_SIZE;
> > +	pp_params.offset = 0;
> > +
> > +	q->page_pool = page_pool_create(&pp_params);
> > +	if (IS_ERR(q->page_pool)) {
> > +		int err = PTR_ERR(q->page_pool);
> > +
> > +		q->page_pool = NULL;
> > +		dev_warn(dev->dev, "Failed to create TX page pool
> > for queue %d (err=%d)\n",
> > +			 q->hw_idx, err);
> > +		return 0;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +int mt792x_dma_tx_page_pool_init(struct mt792x_dev *dev)
> > +{
> > +	struct mt76_dev *mdev = &dev->mt76;
> > +	int i, ret, pool_count = 0;
> > +
> > +	if (!iommu_get_domain_for_dev(mdev->dma_dev))
> > +		return 0;
> > +
> > +	if (!mt76_is_mmio(mdev))
> > +		return 0;
> > +
> > +	mdev->tx_prealloc_enabled = true;
> > +
> > +	for (i = 0; i < ARRAY_SIZE(mdev->phy.q_tx); i++) {
> > +		struct mt76_queue *q = mdev->phy.q_tx[i];
> > +
> > +		if (!q)
> > +			continue;
> > +
> > +		ret = mt792x_create_tx_page_pool(mdev, q);
> > +		if (ret)
> > +			return ret;
> > +
> > +		if (q->page_pool)
> > +			pool_count++;
> > +	}
> > +
> > +	if (pool_count > 0)
> > +		dev_info(mdev->dev,
> > +			 "IOMMU enabled, created %d TX page
> > pools\n", pool_count);
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(mt792x_dma_tx_page_pool_init);
> > +
> > +static void mt792x_dma_tx_page_pool_cleanup(struct mt792x_dev
> > *dev)
> > +{
> > +	struct mt76_dev *mdev = &dev->mt76;
> > +	int i;
> > +
> > +	for (i = 0; i < ARRAY_SIZE(mdev->phy.q_tx); i++) {
> > +		struct mt76_queue *q = mdev->phy.q_tx[i];
> > +
> > +		if (!q || !q->page_pool)
> > +			continue;
> > +
> > +		page_pool_destroy(q->page_pool);
> > +		q->page_pool = NULL;
> > +	}
> > +
> > +	mdev->tx_prealloc_enabled = false;
> > +}
> > +
> > +static void *
> > +mt792x_dma_tx_alloc_page_pool_buf(struct mt76_dev *dev, struct
> > mt76_queue *q,
> > +				  struct sk_buff *skb, dma_addr_t
> > *dma_addr,
> > +				  int *buf_len)
> > +{
> > +	struct page *page;
> > +	void *buf;
> > +	int len;
> > +	u32 offset;
> > +
> > +	if (!q->page_pool || !dev->tx_prealloc_enabled)
> > +		return NULL;
> > +
> > +	len = skb_headlen(skb);
> > +	if (len > PAGE_SIZE)
> > +		return NULL;
> > +
> > +	buf = mt76_get_page_pool_buf(q, &offset, len);
> > +	if (!buf)
> > +		return NULL;
> > +
> > +	page = virt_to_head_page(buf);
> > +	*dma_addr = page_pool_get_dma_addr(page) + offset;
> > +	if (unlikely(!*dma_addr)) {
> > +		dev_warn_ratelimited(dev->dev, "Page pool returned
> > NULL DMA address\n");
> > +		mt76_put_page_pool_buf(buf, false);
> > +		return NULL;
> > +	}
> > +
> > +	*buf_len = len;
> > +
> > +	dma_sync_single_for_cpu(dev->dma_dev, *dma_addr, len,
> > DMA_TO_DEVICE);
> > +	skb_copy_from_linear_data(skb, buf, len);
> 
> I would like to see some results here since usually it is not a good
> idea to
> copy all the packets (even if it is just the linear part).
> 

The results are shown above.

> > +	dma_sync_single_for_device(dev->dma_dev, *dma_addr, len,
> > DMA_TO_DEVICE);
> > +
> > +	return buf;
> > +}
> > +
> > +static int
> > +mt792x_dma_tx_queue_skb(struct mt76_phy *phy, struct mt76_queue
> > *q,
> > +			enum mt76_txq_id qid, struct sk_buff *skb,
> > +			struct mt76_wcid *wcid, struct
> > ieee80211_sta *sta)
> > +{
> > +	struct ieee80211_tx_status status = {
> > +		.sta = sta,
> > +	};
> > +	struct mt76_tx_info tx_info = {
> > +		.skb = skb,
> > +	};
> > +	struct mt76_dev *dev = phy->dev;
> > +	struct ieee80211_hw *hw;
> > +	int len, n = 0, ret = -ENOMEM;
> > +	struct mt76_txwi_cache *t;
> > +	struct sk_buff *iter;
> > +	dma_addr_t addr;
> > +	u8 *txwi;
> > +
> > +	if (test_bit(MT76_RESET, &phy->state))
> > +		goto free_skb;
> > +
> > +	t = mt76_get_txwi(dev);
> > +	if (!t)
> > +		goto free_skb;
> > +
> > +	txwi = mt76_get_txwi_ptr(dev, t);
> > +
> > +	skb->prev = NULL;
> > +	skb->next = NULL;
> > +	if (dev->drv->drv_flags & MT_DRV_TX_ALIGNED4_SKBS)
> > +		mt76_insert_hdr_pad(skb);
> > +
> > +	len = skb_headlen(skb);
> > +
> > +	if (dev->tx_prealloc_enabled && q->page_pool &&
> > +	    !skb_has_frag_list(skb) && !skb_shinfo(skb)->nr_frags)
> > {
> > +		void *buf;
> > +		int pp_len;
> > +
> > +		buf = mt792x_dma_tx_alloc_page_pool_buf(dev, q,
> > skb, &addr, &pp_len);
> > +		if (buf) {
> > +			t->page_pool_buf = buf;
> > +			len = pp_len;
> > +
> > +			tx_info.buf[n].addr = t->dma_addr;
> > +			tx_info.buf[n++].len = dev->drv-
> > >txwi_size;
> > +			tx_info.buf[n].addr = addr;
> > +			tx_info.buf[n].len = len;
> > +			tx_info.buf[n].skip_unmap = true;
> > +			n++;
> > +
> > +			goto skip_dma_map;
> > +		}
> > +	}
> > +
> > +	addr = dma_map_single(dev->dma_dev, skb->data, len,
> > DMA_TO_DEVICE);
> > +	if (unlikely(dma_mapping_error(dev->dma_dev, addr)))
> > +		goto free;
> > +
> > +	t->page_pool_buf = NULL;
> > +
> > +	tx_info.buf[n].addr = t->dma_addr;
> > +	tx_info.buf[n++].len = dev->drv->txwi_size;
> > +	tx_info.buf[n].addr = addr;
> > +	tx_info.buf[n++].len = len;
> > +
> > +skip_dma_map:
> > +	skb_walk_frags(skb, iter) {
> > +		if (n == ARRAY_SIZE(tx_info.buf))
> > +			goto unmap;
> > +
> > +		addr = dma_map_single(dev->dma_dev, iter->data,
> > iter->len,
> > +				      DMA_TO_DEVICE);
> > +		if (unlikely(dma_mapping_error(dev->dma_dev,
> > addr)))
> > +			goto unmap;
> > +
> > +		tx_info.buf[n].addr = addr;
> > +		tx_info.buf[n].skip_unmap = false;
> > +		tx_info.buf[n++].len = iter->len;
> > +	}
> > +	tx_info.nbuf = n;
> > +
> > +	if (q->queued + (tx_info.nbuf + 1) / 2 >= q->ndesc - 1) {
> > +		ret = -ENOMEM;
> > +		goto unmap;
> > +	}
> > +
> > +	dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr, dev-
> > >drv->txwi_size,
> > +				DMA_TO_DEVICE);
> > +	ret = dev->drv->tx_prepare_skb(dev, txwi, qid, wcid, sta,
> > &tx_info);
> > +	dma_sync_single_for_device(dev->dma_dev, t->dma_addr, dev-
> > >drv->txwi_size,
> > +				   DMA_TO_DEVICE);
> > +	if (ret < 0)
> > +		goto unmap;
> > +
> > +	return mt76_dma_add_buf(dev, q, tx_info.buf, tx_info.nbuf,
> > +				tx_info.info, tx_info.skb, t);
> > +
> > +unmap:
> > +	for (n--; n > 0; n--) {
> > +		if (!tx_info.buf[n].skip_unmap)
> > +			dma_unmap_single(dev->dma_dev,
> > tx_info.buf[n].addr,
> > +					 tx_info.buf[n].len,
> > DMA_TO_DEVICE);
> > +	}
> > +
> > +	if (t->page_pool_buf) {
> > +		mt76_put_page_pool_buf(t->page_pool_buf, false);
> > +		t->page_pool_buf = NULL;
> > +	}
> > +
> > +free:
> > +#ifdef CONFIG_NL80211_TESTMODE
> > +	if (mt76_is_testmode_skb(dev, skb, &hw)) {
> > +		struct mt76_phy *phy = hw->priv;
> > +
> > +		if (tx_info.skb == phy->test.tx_skb)
> > +			phy->test.tx_done--;
> > +	}
> > +#endif
> > +
> > +	mt76_put_txwi(dev, t);
> > +
> > +free_skb:
> > +	status.skb = tx_info.skb;
> > +	hw = mt76_tx_status_get_hw(dev, tx_info.skb);
> > +	spin_lock_bh(&dev->rx_lock);
> > +	ieee80211_tx_status_ext(hw, &status);
> > +	spin_unlock_bh(&dev->rx_lock);
> > +
> > +	return ret;
> > +}
> > +
> > +static void
> > +mt792x_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q,
> > bool flush)
> 
> this is almost a copy of mt76_dma_tx_cleanup(). Can we do something
> better
> here?
> 

Yes, it's minor enough that there's no need to split the logic into a
separate mt792x_dma_tx_cleanup() function. I will make the change in
mt76_dma_tx_cleanup() in v2. 
 
> > +{
> > +	struct mt76_queue_entry entry;
> > +	int last;
> > +
> > +	if (!q || !q->ndesc)
> > +		return;
> > +
> > +	spin_lock_bh(&q->cleanup_lock);
> > +	if (flush)
> > +		last = -1;
> > +	else
> > +		last = Q_READ(q, dma_idx);
> > +
> > +	while (q->queued > 0 && q->tail != last) {
> > +		mt76_dma_tx_cleanup_idx(dev, q, q->tail, &entry);
> > +		mt76_npu_txdesc_cleanup(q, q->tail);
> > +		mt76_queue_tx_complete(dev, q, &entry);
> > +
> > +		if (entry.txwi) {
> > +			if (entry.skb && entry.txwi-
> > >page_pool_buf) {
> > +				mt76_put_page_pool_buf(entry.txwi-
> > >page_pool_buf, false);
> > +				entry.txwi->page_pool_buf = NULL;
> > +			}
> > +
> > +			if (!(dev->drv->drv_flags &
> > MT_DRV_TXWI_NO_FREE))
> > +				mt76_put_txwi(dev, entry.txwi);
> > +		}
> > +
> > +		if (!flush && q->tail == last)
> > +			last = Q_READ(q, dma_idx);
> > +	}
> > +	spin_unlock_bh(&q->cleanup_lock);
> > +
> > +	if (flush) {
> > +		spin_lock_bh(&q->lock);
> > +		mt76_dma_sync_idx(dev, q);
> > +		mt76_dma_kick_queue(dev, q);
> > +		spin_unlock_bh(&q->lock);
> > +	}
> > +
> > +	if (!q->queued)
> > +		wake_up(&dev->tx_wait);
> > +}
> > +
> > +static struct mt76_queue_ops mt792x_queue_ops;
> > +
> > +void mt792x_dma_attach(struct mt76_dev *dev)
> > +{
> > +	mt792x_queue_ops = mt76_dma_ops;
> 
> can you please take a look to mt7615_mmio_probe()?
> 
> Regards,
> Lorenzo
> 

Yes, I've referenced it and will make this change in v2 if you're OK
with it.

    void mt792x_dma_attach(struct mt76_dev *dev)
    {
    -    mt702x_queue_ops = mt76_dma_ops;
    +    mt76_dma_attach(dev);
    +    mt792x_queue_ops = *dev->queue_ops;
    +    mt792x_queue_ops.tx_queue_skb = mt792x_dma_tx_queue_skb;
    -    mt792x_queue_ops.tx_cleanup = mt792x_dma_tx_cleanup;
         dev->queue_ops = &mt792x_queue_ops;
    }

Thanks,
Eason

> > +
> > +	mt792x_queue_ops.tx_queue_skb = mt792x_dma_tx_queue_skb;
> > +	mt792x_queue_ops.tx_cleanup = mt792x_dma_tx_cleanup;
> > +
> > +	dev->queue_ops = &mt792x_queue_ops;
> > +}
> > +EXPORT_SYMBOL_GPL(mt792x_dma_attach);
> > +
> >  int mt792x_dma_disable(struct mt792x_dev *dev, bool force)
> >  {
> >  	/* disable WFDMA0 */
> > @@ -326,6 +646,8 @@ void mt792x_dma_cleanup(struct mt792x_dev *dev)
> >  		 MT_WFDMA0_RST_LOGIC_RST);
> >  
> >  	mt76_dma_cleanup(&dev->mt76);
> > +
> > +	mt792x_dma_tx_page_pool_cleanup(dev);
> >  }
> >  EXPORT_SYMBOL_GPL(mt792x_dma_cleanup);
> >  
> > -- 
> > 2.45.2
> > 


  reply	other threads:[~2026-07-13  3:13 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-09  7:55 [PATCH 0/3] Fix TX performance degradation when IOMMU is enabled Eason Lai
2026-07-09  7:55 ` [PATCH 1/3] wifi: mt76: Separate skb and page_pool_buf pointers in mt76_txwi_cache Eason Lai
2026-07-09  8:19   ` Lorenzo Bianconi
2026-07-13  1:57     ` Eason Lai (賴易聖)
2026-07-09  7:55 ` [PATCH 2/3] wifi: mt76: mt792x: Add TX page pool support for IOMMU-enabled systems Eason Lai
2026-07-09  8:27   ` Lorenzo Bianconi
2026-07-13  3:13     ` Eason Lai (賴易聖) [this message]
2026-07-09  7:55 ` [PATCH 3/3] wifi: mt76: mt792x: Restrict TX page pool to MT8196 platform Eason Lai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b3239d674f05e87d8602d533a374806bf5e0a4ba.camel@mediatek.com \
    --to=eason.lai@mediatek.com \
    --cc=Deren.Wu@mediatek.com \
    --cc=Jb.Tsai@mediatek.com \
    --cc=Leon.Yen@mediatek.com \
    --cc=Litien.Chang@mediatek.com \
    --cc=Quan.Zhou@mediatek.com \
    --cc=Ryder.Lee@mediatek.com \
    --cc=Sean.Wang@mediatek.com \
    --cc=Yf.Luo@mediatek.com \
    --cc=kun.wu@mediatek.com \
    --cc=linux-mediatek@lists.infradead.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=lorenzo@kernel.org \
    --cc=nbd@nbd.name \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox