diff mbox series

[net-next] octeontx2-pf: Add support for page pool

Message ID 20230515055607.651799-1-rkannoth@marvell.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [net-next] octeontx2-pf: Add support for page pool | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 8 this patch: 8
netdev/cc_maintainers warning 3 maintainers not CCed: sbhatta@marvell.com gakula@marvell.com hkelam@marvell.com
netdev/build_clang success Errors and warnings before: 8 this patch: 8
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 22 this patch: 22
netdev/checkpatch warning WARNING: line length of 84 exceeds 80 columns WARNING: line length of 85 exceeds 80 columns WARNING: line length of 86 exceeds 80 columns WARNING: line length of 87 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Ratheesh Kannoth May 15, 2023, 5:56 a.m. UTC
Page pool for each rx queue enhance rx side performance
by reclaiming buffers back to each queue specific pool. DMA
mapping is done only for first allocation of buffers.
As subsequent buffers allocation avoid DMA mapping,
it results in performance improvement.

Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
---
 .../marvell/octeontx2/nic/otx2_common.c       | 72 +++++++++++++++++--
 .../marvell/octeontx2/nic/otx2_common.h       |  2 +-
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  | 11 ++-
 .../marvell/octeontx2/nic/otx2_txrx.c         | 23 ++++--
 .../marvell/octeontx2/nic/otx2_txrx.h         |  1 +
 5 files changed, 96 insertions(+), 13 deletions(-)

Comments

Yunsheng Lin May 16, 2023, 1:14 a.m. UTC | #1
On 2023/5/15 13:56, Ratheesh Kannoth wrote:
> Page pool for each rx queue enhance rx side performance
> by reclaiming buffers back to each queue specific pool. DMA
> mapping is done only for first allocation of buffers.
> As subsequent buffers allocation avoid DMA mapping,
> it results in performance improvement.

Any performance data to share here?

....
> @@ -1170,15 +1199,24 @@ void otx2_free_aura_ptr(struct otx2_nic *pfvf, int type)
>  	/* Free SQB and RQB pointers from the aura pool */
>  	for (pool_id = pool_start; pool_id < pool_end; pool_id++) {
>  		iova = otx2_aura_allocptr(pfvf, pool_id);
> +		pool = &pfvf->qset.pool[pool_id];
>  		while (iova) {
>  			if (type == AURA_NIX_RQ)
>  				iova -= OTX2_HEAD_ROOM;
>  
>  			pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
> -			dma_unmap_page_attrs(pfvf->dev, iova, size,
> -					     DMA_FROM_DEVICE,
> -					     DMA_ATTR_SKIP_CPU_SYNC);
> -			put_page(virt_to_page(phys_to_virt(pa)));
> +			page = virt_to_page(phys_to_virt(pa));

virt_to_page() seems ok for order-0 page allocated from page
pool as it does now, but it may break for order-1+ page as
page_pool_put_page() expects head page of compound page or base
page. Maybe add a comment for that or use virt_to_head_page()
explicitly.

> +
> +			if (pool->page_pool) {
> +				page_pool_put_page(pool->page_pool, page, size, true);

page_pool_put_full_page() seems more appropriate here, as the
PP_FLAG_DMA_SYNC_DEV flag is not set, even if it is set, it seems
the whole page need to be synced instead of a frag.


> +			} else {
> +				dma_unmap_page_attrs(pfvf->dev, iova, size,
> +						     DMA_FROM_DEVICE,
> +						     DMA_ATTR_SKIP_CPU_SYNC);
> +
> +				put_page(page);
> +			}
> +
>  			iova = otx2_aura_allocptr(pfvf, pool_id);
>  		}
>  	}
> @@ -1196,6 +1234,8 @@ void otx2_aura_pool_free(struct otx2_nic *pfvf)
>  		pool = &pfvf->qset.pool[pool_id];
>  		qmem_free(pfvf->dev, pool->stack);
>  		qmem_free(pfvf->dev, pool->fc_addr);
> +		page_pool_destroy(pool->page_pool);
> +		pool->page_pool = NULL;
>  	}
>  	devm_kfree(pfvf->dev, pfvf->qset.pool);
>  	pfvf->qset.pool = NULL;
> @@ -1279,8 +1319,10 @@ static int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
>  }
>  
>  static int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
> -			  int stack_pages, int numptrs, int buf_size)
> +			  int stack_pages, int numptrs, int buf_size,
> +			  int type)
>  {
> +	struct page_pool_params pp_params = { 0 };
>  	struct npa_aq_enq_req *aq;
>  	struct otx2_pool *pool;
>  	int err;
> @@ -1324,6 +1366,22 @@ static int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
>  	aq->ctype = NPA_AQ_CTYPE_POOL;
>  	aq->op = NPA_AQ_INSTOP_INIT;
>  
> +	if (type != AURA_NIX_RQ) {
> +		pool->page_pool = NULL;
> +		return 0;
> +	}
> +
> +	pp_params.flags = PP_FLAG_PAGE_FRAG | PP_FLAG_DMA_MAP;
> +	pp_params.pool_size = numptrs;
> +	pp_params.nid = NUMA_NO_NODE;
> +	pp_params.dev = pfvf->dev;
> +	pp_params.dma_dir = DMA_FROM_DEVICE;
> +	pool->page_pool = page_pool_create(&pp_params);
> +	if (!pool->page_pool) {
> +		netdev_err(pfvf->netdev, "Creation of page pool failed\n");
> +		return -EFAULT;
> +	}
> +
>  	return 0;
>  }
>  
> @@ -1358,7 +1416,7 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf)
>  
>  		/* Initialize pool context */
>  		err = otx2_pool_init(pfvf, pool_id, stack_pages,
> -				     num_sqbs, hw->sqb_size);
> +				     num_sqbs, hw->sqb_size, AURA_NIX_SQ);
>  		if (err)
>  			goto fail;
>  	}
> @@ -1421,7 +1479,7 @@ int otx2_rq_aura_pool_init(struct otx2_nic *pfvf)
>  	}
>  	for (pool_id = 0; pool_id < hw->rqpool_cnt; pool_id++) {
>  		err = otx2_pool_init(pfvf, pool_id, stack_pages,
> -				     num_ptrs, pfvf->rbsize);
> +				     num_ptrs, pfvf->rbsize, AURA_NIX_RQ);
>  		if (err)
>  			goto fail;
>  	}

...

> diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> index 7045fedfd73a..df5f45aa6980 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> @@ -217,9 +217,10 @@ static bool otx2_skb_add_frag(struct otx2_nic *pfvf, struct sk_buff *skb,
>  		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
>  				va - page_address(page) + off,
>  				len - off, pfvf->rbsize);
> -
> +#ifndef CONFIG_PAGE_POOL

Most driver does 'select PAGE_POOL' in config when adding page
pool support, is there any reason it does not do it here?

>  		otx2_dma_unmap_page(pfvf, iova - OTX2_HEAD_ROOM,
>  				    pfvf->rbsize, DMA_FROM_DEVICE);
> +#endif
>  		return true;
>  	}
>  
> @@ -382,6 +383,8 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
>  	if (pfvf->netdev->features & NETIF_F_RXCSUM)
>  		skb->ip_summed = CHECKSUM_UNNECESSARY;
>  
> +	skb_mark_for_recycle(skb);
> +
>  	napi_gro_frags(napi);
>  }
>  
> @@ -1180,11 +1183,14 @@ bool otx2_sq_append_skb(struct net_device *netdev, struct otx2_snd_queue *sq,
>  }
>  EXPORT_SYMBOL(otx2_sq_append_skb);
>  
> -void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
> +void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, int qidx)
>  {
>  	struct nix_cqe_rx_s *cqe;
>  	int processed_cqe = 0;
> +	struct otx2_pool *pool;
> +	struct page *page;
>  	u64 iova, pa;
> +	u16 pool_id;
>  
>  	if (pfvf->xdp_prog)
>  		xdp_rxq_info_unreg(&cq->xdp_rxq);
> @@ -1192,6 +1198,9 @@ void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
>  	if (otx2_nix_cq_op_status(pfvf, cq) || !cq->pend_cqe)
>  		return;
>  
> +	pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_RQ, qidx);
> +	pool = &pfvf->qset.pool[pool_id];
> +
>  	while (cq->pend_cqe) {
>  		cqe = (struct nix_cqe_rx_s *)otx2_get_next_cqe(cq);
>  		processed_cqe++;
> @@ -1205,8 +1214,14 @@ void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
>  		}
>  		iova = cqe->sg.seg_addr - OTX2_HEAD_ROOM;
>  		pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
> -		otx2_dma_unmap_page(pfvf, iova, pfvf->rbsize, DMA_FROM_DEVICE);
> -		put_page(virt_to_page(phys_to_virt(pa)));
> +		page = virt_to_page(phys_to_virt(pa));
> +
> +		if (pool->page_pool) {
> +			page_pool_put_page(pool->page_pool, page, pfvf->rbsize, true);
> +		} else {
> +			otx2_dma_unmap_page(pfvf, iova, pfvf->rbsize, DMA_FROM_DEVICE);
> +			put_page(page);
> +		}

Maybe add a helper for the above as there is a similiar code block
in the otx2_free_aura_ptr()


>
Ratheesh Kannoth May 16, 2023, 3:36 a.m. UTC | #2
> -----Original Message-----
> From: Yunsheng Lin <linyunsheng@huawei.com>
> Sent: Tuesday, May 16, 2023 6:44 AM
> To: Ratheesh Kannoth <rkannoth@marvell.com>; netdev@vger.kernel.org;
> linux-kernel@vger.kernel.org
> Cc: Sunil Kovvuri Goutham <sgoutham@marvell.com>;
> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com
> Subject: [EXT] Re: [PATCH net-next] octeontx2-pf: Add support for page pool
> 

> ----------------------------------------------------------------------
> On 2023/5/15 13:56, Ratheesh Kannoth wrote:
> > Page pool for each rx queue enhance rx side performance by reclaiming
> > buffers back to each queue specific pool. DMA mapping is done only for
> > first allocation of buffers.
> > As subsequent buffers allocation avoid DMA mapping, it results in
> > performance improvement.
> 
> Any performance data to share here?
Performance improvement of 39Mpps when measured with Linux packet generator. 
Will update the same in commit message.  

> ....
> > @@ -1170,15 +1199,24 @@ void otx2_free_aura_ptr(struct otx2_nic *pfvf,
> int type)
> >  	/* Free SQB and RQB pointers from the aura pool */
> >  	for (pool_id = pool_start; pool_id < pool_end; pool_id++) {
> >  		iova = otx2_aura_allocptr(pfvf, pool_id);
> > +		pool = &pfvf->qset.pool[pool_id];
> >  		while (iova) {
> >  			if (type == AURA_NIX_RQ)
> >  				iova -= OTX2_HEAD_ROOM;
> >
> >  			pa = otx2_iova_to_phys(pfvf->iommu_domain,
> iova);
> > -			dma_unmap_page_attrs(pfvf->dev, iova, size,
> > -					     DMA_FROM_DEVICE,
> > -					     DMA_ATTR_SKIP_CPU_SYNC);
> > -			put_page(virt_to_page(phys_to_virt(pa)));
> > +			page = virt_to_page(phys_to_virt(pa));
> 
> virt_to_page() seems ok for order-0 page allocated from page pool as it does
> now, but it may break for order-1+ page as
> page_pool_put_page() expects head page of compound page or base page.
> Maybe add a comment for that or use virt_to_head_page() explicitly.
Thanks !!. 
> 
> > +
> > +			if (pool->page_pool) {
> > +				page_pool_put_page(pool->page_pool,
> page, size, true);
> 
> page_pool_put_full_page() seems more appropriate here, as the
> PP_FLAG_DMA_SYNC_DEV flag is not set, even if it is set, it seems the whole
> page need to be synced instead of a frag.
Agree. 
> 
> 
> > +			} else {
> > +				dma_unmap_page_attrs(pfvf->dev, iova,
> size,
> > +						     DMA_FROM_DEVICE,
> > +
> DMA_ATTR_SKIP_CPU_SYNC);
> > +
> > +				put_page(page);
> > +			}
> > +
> >  			iova = otx2_aura_allocptr(pfvf, pool_id);
> >  		}
> >  	}
> > @@ -1196,6 +1234,8 @@ void otx2_aura_pool_free(struct otx2_nic *pfvf)
> >  		pool = &pfvf->qset.pool[pool_id];
> >  		qmem_free(pfvf->dev, pool->stack);
> >  		qmem_free(pfvf->dev, pool->fc_addr);
> > +		page_pool_destroy(pool->page_pool);
> > +		pool->page_pool = NULL;
> >  	}
> >  	devm_kfree(pfvf->dev, pfvf->qset.pool);
> >  	pfvf->qset.pool = NULL;
> > @@ -1279,8 +1319,10 @@ static int otx2_aura_init(struct otx2_nic
> > *pfvf, int aura_id,  }
> >
> >  static int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
> > -			  int stack_pages, int numptrs, int buf_size)
> > +			  int stack_pages, int numptrs, int buf_size,
> > +			  int type)
> >  {
> > +	struct page_pool_params pp_params = { 0 };
> >  	struct npa_aq_enq_req *aq;
> >  	struct otx2_pool *pool;
> >  	int err;
> > @@ -1324,6 +1366,22 @@ static int otx2_pool_init(struct otx2_nic *pfvf,
> u16 pool_id,
> >  	aq->ctype = NPA_AQ_CTYPE_POOL;
> >  	aq->op = NPA_AQ_INSTOP_INIT;
> >
> > +	if (type != AURA_NIX_RQ) {
> > +		pool->page_pool = NULL;
> > +		return 0;
> > +	}
> > +
> > +	pp_params.flags = PP_FLAG_PAGE_FRAG | PP_FLAG_DMA_MAP;
> > +	pp_params.pool_size = numptrs;
> > +	pp_params.nid = NUMA_NO_NODE;
> > +	pp_params.dev = pfvf->dev;
> > +	pp_params.dma_dir = DMA_FROM_DEVICE;
> > +	pool->page_pool = page_pool_create(&pp_params);
> > +	if (!pool->page_pool) {
> > +		netdev_err(pfvf->netdev, "Creation of page pool failed\n");
> > +		return -EFAULT;
> > +	}
> > +
> >  	return 0;
> >  }
> >
> > @@ -1358,7 +1416,7 @@ int otx2_sq_aura_pool_init(struct otx2_nic
> > *pfvf)
> >
> >  		/* Initialize pool context */
> >  		err = otx2_pool_init(pfvf, pool_id, stack_pages,
> > -				     num_sqbs, hw->sqb_size);
> > +				     num_sqbs, hw->sqb_size, AURA_NIX_SQ);
> >  		if (err)
> >  			goto fail;
> >  	}
> > @@ -1421,7 +1479,7 @@ int otx2_rq_aura_pool_init(struct otx2_nic *pfvf)
> >  	}
> >  	for (pool_id = 0; pool_id < hw->rqpool_cnt; pool_id++) {
> >  		err = otx2_pool_init(pfvf, pool_id, stack_pages,
> > -				     num_ptrs, pfvf->rbsize);
> > +				     num_ptrs, pfvf->rbsize, AURA_NIX_RQ);
> >  		if (err)
> >  			goto fail;
> >  	}
> 
> ...
> 
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > index 7045fedfd73a..df5f45aa6980 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > @@ -217,9 +217,10 @@ static bool otx2_skb_add_frag(struct otx2_nic
> *pfvf, struct sk_buff *skb,
> >  		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
> >  				va - page_address(page) + off,
> >  				len - off, pfvf->rbsize);
> > -
> > +#ifndef CONFIG_PAGE_POOL
> 
> Most driver does 'select PAGE_POOL' in config when adding page pool
> support, is there any reason it does not do it here?
We thought about it. User should be able to use the driver without PAGE_POOL support. 
> 
> >  		otx2_dma_unmap_page(pfvf, iova - OTX2_HEAD_ROOM,
> >  				    pfvf->rbsize, DMA_FROM_DEVICE);
> > +#endif
> >  		return true;
> >  	}
> >
> > @@ -382,6 +383,8 @@ static void otx2_rcv_pkt_handler(struct otx2_nic
> *pfvf,
> >  	if (pfvf->netdev->features & NETIF_F_RXCSUM)
> >  		skb->ip_summed = CHECKSUM_UNNECESSARY;
> >
> > +	skb_mark_for_recycle(skb);
> > +
> >  	napi_gro_frags(napi);
> >  }
> >
> > @@ -1180,11 +1183,14 @@ bool otx2_sq_append_skb(struct net_device
> > *netdev, struct otx2_snd_queue *sq,  }
> > EXPORT_SYMBOL(otx2_sq_append_skb);
> >
> > -void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue
> > *cq)
> > +void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue
> > +*cq, int qidx)
> >  {
> >  	struct nix_cqe_rx_s *cqe;
> >  	int processed_cqe = 0;
> > +	struct otx2_pool *pool;
> > +	struct page *page;
> >  	u64 iova, pa;
> > +	u16 pool_id;
> >
> >  	if (pfvf->xdp_prog)
> >  		xdp_rxq_info_unreg(&cq->xdp_rxq);
> > @@ -1192,6 +1198,9 @@ void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf,
> struct otx2_cq_queue *cq)
> >  	if (otx2_nix_cq_op_status(pfvf, cq) || !cq->pend_cqe)
> >  		return;
> >
> > +	pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_RQ, qidx);
> > +	pool = &pfvf->qset.pool[pool_id];
> > +
> >  	while (cq->pend_cqe) {
> >  		cqe = (struct nix_cqe_rx_s *)otx2_get_next_cqe(cq);
> >  		processed_cqe++;
> > @@ -1205,8 +1214,14 @@ void otx2_cleanup_rx_cqes(struct otx2_nic
> *pfvf, struct otx2_cq_queue *cq)
> >  		}
> >  		iova = cqe->sg.seg_addr - OTX2_HEAD_ROOM;
> >  		pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
> > -		otx2_dma_unmap_page(pfvf, iova, pfvf->rbsize,
> DMA_FROM_DEVICE);
> > -		put_page(virt_to_page(phys_to_virt(pa)));
> > +		page = virt_to_page(phys_to_virt(pa));
> > +
> > +		if (pool->page_pool) {
> > +			page_pool_put_page(pool->page_pool, page, pfvf-
> >rbsize, true);
> > +		} else {
> > +			otx2_dma_unmap_page(pfvf, iova, pfvf->rbsize,
> DMA_FROM_DEVICE);
> > +			put_page(page);
> > +		}
> 
> Maybe add a helper for the above as there is a similiar code block in the
> otx2_free_aura_ptr()
Ok.
> 
> 
> >
Paolo Abeni May 16, 2023, 8:51 a.m. UTC | #3
On Tue, 2023-05-16 at 03:36 +0000, Ratheesh Kannoth wrote:
> 
> > ....
> > > @@ -1170,15 +1199,24 @@ void otx2_free_aura_ptr(struct otx2_nic
> > > *pfvf,
> > int type)
> > >  	/* Free SQB and RQB pointers from the aura pool */
> > >  	for (pool_id = pool_start; pool_id < pool_end;
> > > pool_id++) {
> > >  		iova = otx2_aura_allocptr(pfvf, pool_id);
> > > +		pool = &pfvf->qset.pool[pool_id];
> > >  		while (iova) {
> > >  			if (type == AURA_NIX_RQ)
> > >  				iova -= OTX2_HEAD_ROOM;
> > > 
> > >  			pa = otx2_iova_to_phys(pfvf-
> > > >iommu_domain,
> > iova);
> > > -			dma_unmap_page_attrs(pfvf->dev, iova,
> > > size,
> > > -					     DMA_FROM_DEVICE,
> > > -					    
> > > DMA_ATTR_SKIP_CPU_SYNC);
> > > -
> > > 			put_page(virt_to_page(phys_to_virt(pa)));
> > > +			page = virt_to_page(phys_to_virt(pa));
> > 
> > virt_to_page() seems ok for order-0 page allocated from page pool
> > as it does
> > now, but it may break for order-1+ page as
> > page_pool_put_page() expects head page of compound page or base
> > page.
> > Maybe add a comment for that or use virt_to_head_page() explicitly.
> Thanks !!. 
> > 
> > > +
> > > +			if (pool->page_pool) {
> > > +				page_pool_put_page(pool-
> > > >page_pool,
> > page, size, true);
> > 
> > page_pool_put_full_page() seems more appropriate here, as the
> > PP_FLAG_DMA_SYNC_DEV flag is not set, even if it is set, it seems
> > the whole
> > page need to be synced instead of a frag.
> Agree. 
> > 
> > 
> > > +			} else {
> > > +				dma_unmap_page_attrs(pfvf->dev,
> > > iova,
> > size,
> > > +						    
> > > DMA_FROM_DEVICE,
> > > +
> > DMA_ATTR_SKIP_CPU_SYNC);
> > > +
> > > +				put_page(page);
> > > +			}
> > > +
> > >  			iova = otx2_aura_allocptr(pfvf,
> > > pool_id);
> > >  		}
> > >  	}
> > > @@ -1196,6 +1234,8 @@ void otx2_aura_pool_free(struct otx2_nic
> > > *pfvf)
> > >  		pool = &pfvf->qset.pool[pool_id];
> > >  		qmem_free(pfvf->dev, pool->stack);
> > >  		qmem_free(pfvf->dev, pool->fc_addr);
> > > +		page_pool_destroy(pool->page_pool);
> > > +		pool->page_pool = NULL;
> > >  	}
> > >  	devm_kfree(pfvf->dev, pfvf->qset.pool);
> > >  	pfvf->qset.pool = NULL;
> > > @@ -1279,8 +1319,10 @@ static int otx2_aura_init(struct otx2_nic
> > > *pfvf, int aura_id,  }
> > > 
> > >  static int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
> > > -			  int stack_pages, int numptrs, int
> > > buf_size)
> > > +			  int stack_pages, int numptrs, int
> > > buf_size,
> > > +			  int type)
> > >  {
> > > +	struct page_pool_params pp_params = { 0 };
> > >  	struct npa_aq_enq_req *aq;
> > >  	struct otx2_pool *pool;
> > >  	int err;
> > > @@ -1324,6 +1366,22 @@ static int otx2_pool_init(struct otx2_nic
> > > *pfvf,
> > u16 pool_id,
> > >  	aq->ctype = NPA_AQ_CTYPE_POOL;
> > >  	aq->op = NPA_AQ_INSTOP_INIT;
> > > 
> > > +	if (type != AURA_NIX_RQ) {
> > > +		pool->page_pool = NULL;
> > > +		return 0;
> > > +	}
> > > +
> > > +	pp_params.flags = PP_FLAG_PAGE_FRAG | PP_FLAG_DMA_MAP;
> > > +	pp_params.pool_size = numptrs;
> > > +	pp_params.nid = NUMA_NO_NODE;
> > > +	pp_params.dev = pfvf->dev;
> > > +	pp_params.dma_dir = DMA_FROM_DEVICE;
> > > +	pool->page_pool = page_pool_create(&pp_params);
> > > +	if (!pool->page_pool) {
> > > +		netdev_err(pfvf->netdev, "Creation of page pool
> > > failed\n");
> > > +		return -EFAULT;
> > > +	}
> > > +
> > >  	return 0;
> > >  }
> > > 
> > > @@ -1358,7 +1416,7 @@ int otx2_sq_aura_pool_init(struct otx2_nic
> > > *pfvf)
> > > 
> > >  		/* Initialize pool context */
> > >  		err = otx2_pool_init(pfvf, pool_id, stack_pages,
> > > -				     num_sqbs, hw->sqb_size);
> > > +				     num_sqbs, hw->sqb_size,
> > > AURA_NIX_SQ);
> > >  		if (err)
> > >  			goto fail;
> > >  	}
> > > @@ -1421,7 +1479,7 @@ int otx2_rq_aura_pool_init(struct otx2_nic
> > > *pfvf)
> > >  	}
> > >  	for (pool_id = 0; pool_id < hw->rqpool_cnt; pool_id++) {
> > >  		err = otx2_pool_init(pfvf, pool_id, stack_pages,
> > > -				     num_ptrs, pfvf->rbsize);
> > > +				     num_ptrs, pfvf->rbsize,
> > > AURA_NIX_RQ);
> > >  		if (err)
> > >  			goto fail;
> > >  	}
> > 
> > ...
> > 
> > > diff --git
> > > a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > > b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > > index 7045fedfd73a..df5f45aa6980 100644
> > > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > > @@ -217,9 +217,10 @@ static bool otx2_skb_add_frag(struct
> > > otx2_nic
> > *pfvf, struct sk_buff *skb,
> > >  		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
> > > page,
> > >  				va - page_address(page) + off,
> > >  				len - off, pfvf->rbsize);
> > > -
> > > +#ifndef CONFIG_PAGE_POOL
> > 
> > Most driver does 'select PAGE_POOL' in config when adding page pool
> > support, is there any reason it does not do it here?
> We thought about it. User should be able to use the driver without
> PAGE_POOL support. 

Uhm... the above looks like a questionable choice, as page pull is a
small infra, and the performance delta should be relevant.

Anyway if you really want to use such strategy, please be consistent
and guard any relevant chunck of code with compiler guards. Likely it
would be better providing dummy helpers for the few page_pool functions
still missing them when !CONFIG_PAGE_POOL

> 
Cheers,

Paolo
Paolo Abeni May 16, 2023, 9:01 a.m. UTC | #4
On Mon, 2023-05-15 at 11:26 +0530, Ratheesh Kannoth wrote:
> diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> index 7045fedfd73a..df5f45aa6980 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> @@ -217,9 +217,10 @@ static bool otx2_skb_add_frag(struct otx2_nic *pfvf, struct sk_buff *skb,
>  		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
>  				va - page_address(page) + off,
>  				len - off, pfvf->rbsize);
> -
> +#ifndef CONFIG_PAGE_POOL
>  		otx2_dma_unmap_page(pfvf, iova - OTX2_HEAD_ROOM,
>  				    pfvf->rbsize, DMA_FROM_DEVICE);
> +#endif

Don't you need to do the same even when CONFIG_PAGE_POOL and !pool-
>page_pool ?

>  		return true;
>  	}
>  
> @@ -382,6 +383,8 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
>  	if (pfvf->netdev->features & NETIF_F_RXCSUM)
>  		skb->ip_summed = CHECKSUM_UNNECESSARY;
>  
> +	skb_mark_for_recycle(skb);

Don't you need to set the recycle only when pool->page_pool?

Overall it looks like that having both the pool->page_pool and
CONFIG_PAGE_POOL checks in place add a few possible sources of bugs.

Cheers,

Paolo
Ratheesh Kannoth May 16, 2023, 9:21 a.m. UTC | #5
> -----Original Message-----
> From: Paolo Abeni <pabeni@redhat.com>
> Sent: Tuesday, May 16, 2023 2:21 PM
> To: Ratheesh Kannoth <rkannoth@marvell.com>; Yunsheng Lin
> <linyunsheng@huawei.com>; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org
> Cc: Sunil Kovvuri Goutham <sgoutham@marvell.com>;
> davem@davemloft.net; edumazet@google.com; kuba@kernel.org
> Subject: Re: Re: [PATCH net-next] octeontx2-pf: Add support for page
> pool
> >
> > > ....
> > > > @@ -1170,15 +1199,24 @@ void otx2_free_aura_ptr(struct otx2_nic
> > > > *pfvf,
> > > int type)
> > > >  	/* Free SQB and RQB pointers from the aura pool */
> > > >  	for (pool_id = pool_start; pool_id < pool_end;
> > > > pool_id++) {
> > > >  		iova = otx2_aura_allocptr(pfvf, pool_id);
> > > > +		pool = &pfvf->qset.pool[pool_id];
> > > >  		while (iova) {
> > > >  			if (type == AURA_NIX_RQ)
> > > >  				iova -= OTX2_HEAD_ROOM;
> > > >
> > > >  			pa = otx2_iova_to_phys(pfvf-
> > > > >iommu_domain,
> > > iova);
> > > > -			dma_unmap_page_attrs(pfvf->dev, iova,
> > > > size,
> > > > -					     DMA_FROM_DEVICE,
> > > > -
> > > > DMA_ATTR_SKIP_CPU_SYNC);
> > > > -
> > > > 			put_page(virt_to_page(phys_to_virt(pa)));
> > > > +			page = virt_to_page(phys_to_virt(pa));
> > >
> > > virt_to_page() seems ok for order-0 page allocated from page pool as
> > > it does now, but it may break for order-1+ page as
> > > page_pool_put_page() expects head page of compound page or base
> > > page.
> > > Maybe add a comment for that or use virt_to_head_page() explicitly.
> > Thanks !!.
> > >
> > > > +
> > > > +			if (pool->page_pool) {
> > > > +				page_pool_put_page(pool-
> > > > >page_pool,
> > > page, size, true);
> > >
> > > page_pool_put_full_page() seems more appropriate here, as the
> > > PP_FLAG_DMA_SYNC_DEV flag is not set, even if it is set, it seems
> > > the whole page need to be synced instead of a frag.
> > Agree.
> > >
> > >
> > > > +			} else {
> > > > +				dma_unmap_page_attrs(pfvf->dev,
> > > > iova,
> > > size,
> > > > +
> > > > DMA_FROM_DEVICE,
> > > > +
> > > DMA_ATTR_SKIP_CPU_SYNC);
> > > > +
> > > > +				put_page(page);
> > > > +			}
> > > > +
> > > >  			iova = otx2_aura_allocptr(pfvf, pool_id);
> > > >  		}
> > > >  	}
> > > > @@ -1196,6 +1234,8 @@ void otx2_aura_pool_free(struct otx2_nic
> > > > *pfvf)
> > > >  		pool = &pfvf->qset.pool[pool_id];
> > > >  		qmem_free(pfvf->dev, pool->stack);
> > > >  		qmem_free(pfvf->dev, pool->fc_addr);
> > > > +		page_pool_destroy(pool->page_pool);
> > > > +		pool->page_pool = NULL;
> > > >  	}
> > > >  	devm_kfree(pfvf->dev, pfvf->qset.pool);
> > > >  	pfvf->qset.pool = NULL;
> > > > @@ -1279,8 +1319,10 @@ static int otx2_aura_init(struct otx2_nic
> > > > *pfvf, int aura_id,  }
> > > >
> > > >  static int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
> > > > -			  int stack_pages, int numptrs, int
> > > > buf_size)
> > > > +			  int stack_pages, int numptrs, int
> > > > buf_size,
> > > > +			  int type)
> > > >  {
> > > > +	struct page_pool_params pp_params = { 0 };
> > > >  	struct npa_aq_enq_req *aq;
> > > >  	struct otx2_pool *pool;
> > > >  	int err;
> > > > @@ -1324,6 +1366,22 @@ static int otx2_pool_init(struct otx2_nic
> > > > *pfvf,
> > > u16 pool_id,
> > > >  	aq->ctype = NPA_AQ_CTYPE_POOL;
> > > >  	aq->op = NPA_AQ_INSTOP_INIT;
> > > >
> > > > +	if (type != AURA_NIX_RQ) {
> > > > +		pool->page_pool = NULL;
> > > > +		return 0;
> > > > +	}
> > > > +
> > > > +	pp_params.flags = PP_FLAG_PAGE_FRAG | PP_FLAG_DMA_MAP;
> > > > +	pp_params.pool_size = numptrs;
> > > > +	pp_params.nid = NUMA_NO_NODE;
> > > > +	pp_params.dev = pfvf->dev;
> > > > +	pp_params.dma_dir = DMA_FROM_DEVICE;
> > > > +	pool->page_pool = page_pool_create(&pp_params);
> > > > +	if (!pool->page_pool) {
> > > > +		netdev_err(pfvf->netdev, "Creation of page pool
> > > > failed\n");
> > > > +		return -EFAULT;
> > > > +	}
> > > > +
> > > >  	return 0;
> > > >  }
> > > >
> > > > @@ -1358,7 +1416,7 @@ int otx2_sq_aura_pool_init(struct otx2_nic
> > > > *pfvf)
> > > >
> > > >  		/* Initialize pool context */
> > > >  		err = otx2_pool_init(pfvf, pool_id, stack_pages,
> > > > -				     num_sqbs, hw->sqb_size);
> > > > +				     num_sqbs, hw->sqb_size,
> > > > AURA_NIX_SQ);
> > > >  		if (err)
> > > >  			goto fail;
> > > >  	}
> > > > @@ -1421,7 +1479,7 @@ int otx2_rq_aura_pool_init(struct otx2_nic
> > > > *pfvf)
> > > >  	}
> > > >  	for (pool_id = 0; pool_id < hw->rqpool_cnt; pool_id++) {
> > > >  		err = otx2_pool_init(pfvf, pool_id, stack_pages,
> > > > -				     num_ptrs, pfvf->rbsize);
> > > > +				     num_ptrs, pfvf->rbsize,
> > > > AURA_NIX_RQ);
> > > >  		if (err)
> > > >  			goto fail;
> > > >  	}
> > >
> > > ...
> > >
> > > > diff --git
> > > > a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > > > b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > > > index 7045fedfd73a..df5f45aa6980 100644
> > > > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > > > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > > > @@ -217,9 +217,10 @@ static bool otx2_skb_add_frag(struct otx2_nic
> > > *pfvf, struct sk_buff *skb,
> > > >  		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
> > > >  				va - page_address(page) + off,
> > > >  				len - off, pfvf->rbsize);
> > > > -
> > > > +#ifndef CONFIG_PAGE_POOL
> > >
> > > Most driver does 'select PAGE_POOL' in config when adding page pool
> > > support, is there any reason it does not do it here?
> > We thought about it. User should be able to use the driver without
> > PAGE_POOL support.
> 
> Uhm... the above looks like a questionable choice, as page pull is a small infra,
> and the performance delta should be relevant.
> 
Okay. Will select PAGE_POOL in config.  

> Anyway if you really want to use such strategy, please be consistent and
> guard any relevant chunck of code with compiler guards. Likely it would be
> better providing dummy helpers for the few page_pool functions still missing
> them when !CONFIG_PAGE_POOL

As page pool brings in performance improvement and is selected by default. I am thinking, not to implement dummy functions.

> 
> >
> Cheers,
> 
> Paolo
Ratheesh Kannoth May 16, 2023, 9:35 a.m. UTC | #6
> -----Original Message-----
> From: Paolo Abeni <pabeni@redhat.com>
> Sent: Tuesday, May 16, 2023 2:31 PM
> To: Ratheesh Kannoth <rkannoth@marvell.com>; netdev@vger.kernel.org;
> linux-kernel@vger.kernel.org
> Cc: Sunil Kovvuri Goutham <sgoutham@marvell.com>;
> davem@davemloft.net; edumazet@google.com; kuba@kernel.org
> Subject: [EXT] Re: [PATCH net-next] octeontx2-pf: Add support for page pool

> ----------------------------------------------------------------------
> On Mon, 2023-05-15 at 11:26 +0530, Ratheesh Kannoth wrote:
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > index 7045fedfd73a..df5f45aa6980 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
> > @@ -217,9 +217,10 @@ static bool otx2_skb_add_frag(struct otx2_nic
> *pfvf, struct sk_buff *skb,
> >  		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
> >  				va - page_address(page) + off,
> >  				len - off, pfvf->rbsize);
> > -
> > +#ifndef CONFIG_PAGE_POOL
> >  		otx2_dma_unmap_page(pfvf, iova - OTX2_HEAD_ROOM,
> >  				    pfvf->rbsize, DMA_FROM_DEVICE);
> > +#endif
> 
> Don't you need to do the same even when CONFIG_PAGE_POOL and !pool-
> >page_pool ?
No,   if CONFIG_PAGE_POOL is enabled,  pool->page_pool  would be != NULL.   As you suggested earlier,  we will select CONFIG_PAGE_POOL on enabling 
the driver.   This means, all these ifdef checks will go away. 
> 
> >  		return true;
> >  	}
> >
> > @@ -382,6 +383,8 @@ static void otx2_rcv_pkt_handler(struct otx2_nic
> *pfvf,
> >  	if (pfvf->netdev->features & NETIF_F_RXCSUM)
> >  		skb->ip_summed = CHECKSUM_UNNECESSARY;
> >
> > +	skb_mark_for_recycle(skb);
> 
> Don't you need to set the recycle only when pool->page_pool?
No.  Page pool is enabled only for RX side.  Pool->page_pool will be != NULL if  CONFIG_PAGE_POOL is enabled.   
skb_mark_for_recycle() function is dummy if CONFIG_PAGE_POOL is not selected. 

static inline void skb_mark_for_recycle(struct sk_buff *skb)
{
#ifdef CONFIG_PAGE_POOL
        skb->pp_recycle = 1;
#endif
}
> 
> Overall it looks like that having both the pool->page_pool and
> CONFIG_PAGE_POOL checks in place add a few possible sources of bugs.

We added #ifdef checks to improve performance incase CONFIG_PAGE_POOL is disabled.  As we decided (As per your review comments) to select CONFIG_PAGE_POOL
For the driver, all these #ifdefs will be removed.  


Thanks,
Ratheesh Kannoth
diff mbox series

Patch

diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
index 8a41ad8ca04f..561b00ed8846 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
@@ -513,11 +513,38 @@  void otx2_config_irq_coalescing(struct otx2_nic *pfvf, int qidx)
 		     (pfvf->hw.cq_ecount_wait - 1));
 }
 
+static int otx2_alloc_pool_buf(struct otx2_nic *pfvf, struct otx2_pool *pool,
+			       dma_addr_t *dma)
+{
+	unsigned int offset = 0;
+	struct page *page;
+	size_t sz;
+
+	sz = SKB_DATA_ALIGN(pool->rbsize);
+	sz = ALIGN(sz, OTX2_ALIGN);
+
+	page = page_pool_alloc_frag(pool->page_pool, &offset, sz,
+				    (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL) |
+				    GFP_DMA);
+	if (unlikely(!page)) {
+		netdev_err(pfvf->netdev, "Allocation of page pool failed\n");
+		return -ENOMEM;
+	}
+
+	*dma = page_pool_get_dma_addr(page) + offset;
+	return 0;
+}
+
 int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
 		      dma_addr_t *dma)
 {
 	u8 *buf;
 
+#ifdef CONFIG_PAGE_POOL
+	if (pool->page_pool)
+		return otx2_alloc_pool_buf(pfvf, pool, dma);
+#endif
+
 	buf = napi_alloc_frag_align(pool->rbsize, OTX2_ALIGN);
 	if (unlikely(!buf))
 		return -ENOMEM;
@@ -1154,6 +1181,8 @@  void otx2_sq_free_sqbs(struct otx2_nic *pfvf)
 void otx2_free_aura_ptr(struct otx2_nic *pfvf, int type)
 {
 	int pool_id, pool_start = 0, pool_end = 0, size = 0;
+	struct otx2_pool *pool;
+	struct page *page;
 	u64 iova, pa;
 
 	if (type == AURA_NIX_SQ) {
@@ -1170,15 +1199,24 @@  void otx2_free_aura_ptr(struct otx2_nic *pfvf, int type)
 	/* Free SQB and RQB pointers from the aura pool */
 	for (pool_id = pool_start; pool_id < pool_end; pool_id++) {
 		iova = otx2_aura_allocptr(pfvf, pool_id);
+		pool = &pfvf->qset.pool[pool_id];
 		while (iova) {
 			if (type == AURA_NIX_RQ)
 				iova -= OTX2_HEAD_ROOM;
 
 			pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
-			dma_unmap_page_attrs(pfvf->dev, iova, size,
-					     DMA_FROM_DEVICE,
-					     DMA_ATTR_SKIP_CPU_SYNC);
-			put_page(virt_to_page(phys_to_virt(pa)));
+			page = virt_to_page(phys_to_virt(pa));
+
+			if (pool->page_pool) {
+				page_pool_put_page(pool->page_pool, page, size, true);
+			} else {
+				dma_unmap_page_attrs(pfvf->dev, iova, size,
+						     DMA_FROM_DEVICE,
+						     DMA_ATTR_SKIP_CPU_SYNC);
+
+				put_page(page);
+			}
+
 			iova = otx2_aura_allocptr(pfvf, pool_id);
 		}
 	}
@@ -1196,6 +1234,8 @@  void otx2_aura_pool_free(struct otx2_nic *pfvf)
 		pool = &pfvf->qset.pool[pool_id];
 		qmem_free(pfvf->dev, pool->stack);
 		qmem_free(pfvf->dev, pool->fc_addr);
+		page_pool_destroy(pool->page_pool);
+		pool->page_pool = NULL;
 	}
 	devm_kfree(pfvf->dev, pfvf->qset.pool);
 	pfvf->qset.pool = NULL;
@@ -1279,8 +1319,10 @@  static int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
 }
 
 static int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
-			  int stack_pages, int numptrs, int buf_size)
+			  int stack_pages, int numptrs, int buf_size,
+			  int type)
 {
+	struct page_pool_params pp_params = { 0 };
 	struct npa_aq_enq_req *aq;
 	struct otx2_pool *pool;
 	int err;
@@ -1324,6 +1366,22 @@  static int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
 	aq->ctype = NPA_AQ_CTYPE_POOL;
 	aq->op = NPA_AQ_INSTOP_INIT;
 
+	if (type != AURA_NIX_RQ) {
+		pool->page_pool = NULL;
+		return 0;
+	}
+
+	pp_params.flags = PP_FLAG_PAGE_FRAG | PP_FLAG_DMA_MAP;
+	pp_params.pool_size = numptrs;
+	pp_params.nid = NUMA_NO_NODE;
+	pp_params.dev = pfvf->dev;
+	pp_params.dma_dir = DMA_FROM_DEVICE;
+	pool->page_pool = page_pool_create(&pp_params);
+	if (!pool->page_pool) {
+		netdev_err(pfvf->netdev, "Creation of page pool failed\n");
+		return -EFAULT;
+	}
+
 	return 0;
 }
 
@@ -1358,7 +1416,7 @@  int otx2_sq_aura_pool_init(struct otx2_nic *pfvf)
 
 		/* Initialize pool context */
 		err = otx2_pool_init(pfvf, pool_id, stack_pages,
-				     num_sqbs, hw->sqb_size);
+				     num_sqbs, hw->sqb_size, AURA_NIX_SQ);
 		if (err)
 			goto fail;
 	}
@@ -1421,7 +1479,7 @@  int otx2_rq_aura_pool_init(struct otx2_nic *pfvf)
 	}
 	for (pool_id = 0; pool_id < hw->rqpool_cnt; pool_id++) {
 		err = otx2_pool_init(pfvf, pool_id, stack_pages,
-				     num_ptrs, pfvf->rbsize);
+				     num_ptrs, pfvf->rbsize, AURA_NIX_RQ);
 		if (err)
 			goto fail;
 	}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
index 3d22cc6a2804..7ed7c9426dc3 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
@@ -927,7 +927,7 @@  int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
 int otx2_rxtx_enable(struct otx2_nic *pfvf, bool enable);
 void otx2_ctx_disable(struct mbox *mbox, int type, bool npa);
 int otx2_nix_config_bp(struct otx2_nic *pfvf, bool enable);
-void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);
+void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, int qidx);
 void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);
 int otx2_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura);
 int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 179433d0a54a..3071928ff6bf 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1551,8 +1551,10 @@  static void otx2_free_hw_resources(struct otx2_nic *pf)
 	struct nix_lf_free_req *free_req;
 	struct mbox *mbox = &pf->mbox;
 	struct otx2_cq_queue *cq;
+	struct otx2_pool *pool;
 	struct msg_req *req;
 	int qidx, err;
+	int pool_id;
 
 	/* Ensure all SQE are processed */
 	otx2_sqb_flush(pf);
@@ -1580,7 +1582,7 @@  static void otx2_free_hw_resources(struct otx2_nic *pf)
 	for (qidx = 0; qidx < qset->cq_cnt; qidx++) {
 		cq = &qset->cq[qidx];
 		if (cq->cq_type == CQ_RX)
-			otx2_cleanup_rx_cqes(pf, cq);
+			otx2_cleanup_rx_cqes(pf, cq, qidx);
 		else
 			otx2_cleanup_tx_cqes(pf, cq);
 	}
@@ -1590,6 +1592,13 @@  static void otx2_free_hw_resources(struct otx2_nic *pf)
 	/* Free RQ buffer pointers*/
 	otx2_free_aura_ptr(pf, AURA_NIX_RQ);
 
+	for (qidx = 0; qidx < pf->hw.rx_queues; qidx++) {
+		pool_id = otx2_get_pool_idx(pf, AURA_NIX_RQ, qidx);
+		pool = &pf->qset.pool[pool_id];
+		page_pool_destroy(pool->page_pool);
+		pool->page_pool = NULL;
+	}
+
 	otx2_free_cq_res(pf);
 
 	/* Free all ingress bandwidth profiles allocated */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
index 7045fedfd73a..df5f45aa6980 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
@@ -217,9 +217,10 @@  static bool otx2_skb_add_frag(struct otx2_nic *pfvf, struct sk_buff *skb,
 		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
 				va - page_address(page) + off,
 				len - off, pfvf->rbsize);
-
+#ifndef CONFIG_PAGE_POOL
 		otx2_dma_unmap_page(pfvf, iova - OTX2_HEAD_ROOM,
 				    pfvf->rbsize, DMA_FROM_DEVICE);
+#endif
 		return true;
 	}
 
@@ -382,6 +383,8 @@  static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
 	if (pfvf->netdev->features & NETIF_F_RXCSUM)
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
+	skb_mark_for_recycle(skb);
+
 	napi_gro_frags(napi);
 }
 
@@ -1180,11 +1183,14 @@  bool otx2_sq_append_skb(struct net_device *netdev, struct otx2_snd_queue *sq,
 }
 EXPORT_SYMBOL(otx2_sq_append_skb);
 
-void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
+void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, int qidx)
 {
 	struct nix_cqe_rx_s *cqe;
 	int processed_cqe = 0;
+	struct otx2_pool *pool;
+	struct page *page;
 	u64 iova, pa;
+	u16 pool_id;
 
 	if (pfvf->xdp_prog)
 		xdp_rxq_info_unreg(&cq->xdp_rxq);
@@ -1192,6 +1198,9 @@  void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
 	if (otx2_nix_cq_op_status(pfvf, cq) || !cq->pend_cqe)
 		return;
 
+	pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_RQ, qidx);
+	pool = &pfvf->qset.pool[pool_id];
+
 	while (cq->pend_cqe) {
 		cqe = (struct nix_cqe_rx_s *)otx2_get_next_cqe(cq);
 		processed_cqe++;
@@ -1205,8 +1214,14 @@  void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
 		}
 		iova = cqe->sg.seg_addr - OTX2_HEAD_ROOM;
 		pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
-		otx2_dma_unmap_page(pfvf, iova, pfvf->rbsize, DMA_FROM_DEVICE);
-		put_page(virt_to_page(phys_to_virt(pa)));
+		page = virt_to_page(phys_to_virt(pa));
+
+		if (pool->page_pool) {
+			page_pool_put_page(pool->page_pool, page, pfvf->rbsize, true);
+		} else {
+			otx2_dma_unmap_page(pfvf, iova, pfvf->rbsize, DMA_FROM_DEVICE);
+			put_page(page);
+		}
 	}
 
 	/* Free CQEs to HW */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
index 93cac2c2664c..176472ece656 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
@@ -117,6 +117,7 @@  struct otx2_cq_poll {
 struct otx2_pool {
 	struct qmem		*stack;
 	struct qmem		*fc_addr;
+	struct page_pool	*page_pool;
 	u16			rbsize;
 };