mirror of
				https://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 17:35:49 +00:00 
			
		
		
		
	This is an automatically generated commit. When doing `git bisect`, consider `git bisect --skip`. Signed-off-by: Kenneth Kasilag <kenneth@kasilag.me> Link: https://github.com/openwrt/openwrt/pull/19038 Signed-off-by: Robert Marko <robimarko@gmail.com>
		
			
				
	
	
		
			73 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			73 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From d6d2b0e1538d5c381ec0ca95afaf772c096ea5dc Mon Sep 17 00:00:00 2001
 | |
| From: Lorenzo Bianconi <lorenzo@kernel.org>
 | |
| Date: Thu, 15 May 2025 08:33:06 +0200
 | |
| Subject: [PATCH] net: airoha: Fix page recycling in airoha_qdma_rx_process()
 | |
| 
 | |
| Do not recycle the page twice in airoha_qdma_rx_process routine in case
 | |
| of error. Just run dev_kfree_skb() if the skb has been allocated and marked
 | |
| for recycling. Run page_pool_put_full_page() directly if the skb has not
 | |
| been allocated yet.
 | |
| Moreover, rely on DMA address from queue entry element instead of reading
 | |
| it from the DMA descriptor for DMA syncing in airoha_qdma_rx_process().
 | |
| 
 | |
| Fixes: e12182ddb6e71 ("net: airoha: Enable Rx Scatter-Gather")
 | |
| Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
 | |
| Link: https://patch.msgid.link/20250515-airoha-fix-rx-process-error-condition-v2-1-657e92c894b9@kernel.org
 | |
| Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | |
| ---
 | |
|  drivers/net/ethernet/airoha/airoha_eth.c | 22 +++++++++-------------
 | |
|  1 file changed, 9 insertions(+), 13 deletions(-)
 | |
| 
 | |
| --- a/drivers/net/ethernet/airoha/airoha_eth.c
 | |
| +++ b/drivers/net/ethernet/airoha/airoha_eth.c
 | |
| @@ -636,7 +636,6 @@ static int airoha_qdma_rx_process(struct
 | |
|  		struct airoha_queue_entry *e = &q->entry[q->tail];
 | |
|  		struct airoha_qdma_desc *desc = &q->desc[q->tail];
 | |
|  		u32 hash, reason, msg1 = le32_to_cpu(desc->msg1);
 | |
| -		dma_addr_t dma_addr = le32_to_cpu(desc->addr);
 | |
|  		struct page *page = virt_to_head_page(e->buf);
 | |
|  		u32 desc_ctrl = le32_to_cpu(desc->ctrl);
 | |
|  		struct airoha_gdm_port *port;
 | |
| @@ -645,22 +644,16 @@ static int airoha_qdma_rx_process(struct
 | |
|  		if (!(desc_ctrl & QDMA_DESC_DONE_MASK))
 | |
|  			break;
 | |
|  
 | |
| -		if (!dma_addr)
 | |
| -			break;
 | |
| -
 | |
| -		len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl);
 | |
| -		if (!len)
 | |
| -			break;
 | |
| -
 | |
|  		q->tail = (q->tail + 1) % q->ndesc;
 | |
|  		q->queued--;
 | |
|  
 | |
| -		dma_sync_single_for_cpu(eth->dev, dma_addr,
 | |
| +		dma_sync_single_for_cpu(eth->dev, e->dma_addr,
 | |
|  					SKB_WITH_OVERHEAD(q->buf_size), dir);
 | |
|  
 | |
| +		len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl);
 | |
|  		data_len = q->skb ? q->buf_size
 | |
|  				  : SKB_WITH_OVERHEAD(q->buf_size);
 | |
| -		if (data_len < len)
 | |
| +		if (!len || data_len < len)
 | |
|  			goto free_frag;
 | |
|  
 | |
|  		p = airoha_qdma_get_gdm_port(eth, desc);
 | |
| @@ -723,9 +716,12 @@ static int airoha_qdma_rx_process(struct
 | |
|  		q->skb = NULL;
 | |
|  		continue;
 | |
|  free_frag:
 | |
| -		page_pool_put_full_page(q->page_pool, page, true);
 | |
| -		dev_kfree_skb(q->skb);
 | |
| -		q->skb = NULL;
 | |
| +		if (q->skb) {
 | |
| +			dev_kfree_skb(q->skb);
 | |
| +			q->skb = NULL;
 | |
| +		} else {
 | |
| +			page_pool_put_full_page(q->page_pool, page, true);
 | |
| +		}
 | |
|  	}
 | |
|  	airoha_qdma_fill_rx_queue(q);
 | |
|  
 |