mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-03 22:44:27 -05:00 
			
		
		
		
	Backport Russell King's series [1] net: mvneta: reduce size of TSO header allocation to pending-5.15 to fix random crashes on Turris Omnia. This also backports two patches that are dependencies to this series: net: mvneta: Delete unused variable net: mvneta: fix potential double-frees in mvneta_txq_sw_deinit() [1] https://lore.kernel.org/netdev/ZCsbJ4nG+So%2Fn9qY@shell.armlinux.org.uk/ Signed-off-by: Marek Behún <kabel@kernel.org> Signed-off-by: Christian Lamparter <chunkeey@gmail.com> (squashed)
		
			
				
	
	
		
			112 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From d6d80269cf5c79f9dfe7d69f8b41a72015c89748 Mon Sep 17 00:00:00 2001
 | 
						|
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
						|
Date: Mon, 3 Apr 2023 19:30:20 +0100
 | 
						|
Subject: [PATCH 1/5] net: mvneta: fix transmit path dma-unmapping on error
 | 
						|
 | 
						|
The transmit code assumes that the transmit descriptors that are used
 | 
						|
begin with the first descriptor in the ring, but this may not be the
 | 
						|
case. Fix this by providing a new function that dma-unmaps a range of
 | 
						|
numbered descriptor entries, and use that to do the unmapping.
 | 
						|
 | 
						|
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
						|
---
 | 
						|
 drivers/net/ethernet/marvell/mvneta.c | 53 +++++++++++++++++----------
 | 
						|
 1 file changed, 33 insertions(+), 20 deletions(-)
 | 
						|
 | 
						|
--- a/drivers/net/ethernet/marvell/mvneta.c
 | 
						|
+++ b/drivers/net/ethernet/marvell/mvneta.c
 | 
						|
@@ -2647,14 +2647,40 @@ mvneta_tso_put_data(struct net_device *d
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
+static void mvneta_release_descs(struct mvneta_port *pp,
 | 
						|
+				 struct mvneta_tx_queue *txq,
 | 
						|
+				 int first, int num)
 | 
						|
+{
 | 
						|
+	int desc_idx, i;
 | 
						|
+
 | 
						|
+	desc_idx = first + num;
 | 
						|
+	if (desc_idx >= txq->size)
 | 
						|
+		desc_idx -= txq->size;
 | 
						|
+
 | 
						|
+	for (i = num; i >= 0; i--) {
 | 
						|
+		struct mvneta_tx_desc *tx_desc = txq->descs + desc_idx;
 | 
						|
+
 | 
						|
+		if (!IS_TSO_HEADER(txq, tx_desc->buf_phys_addr))
 | 
						|
+			dma_unmap_single(pp->dev->dev.parent,
 | 
						|
+					 tx_desc->buf_phys_addr,
 | 
						|
+					 tx_desc->data_size,
 | 
						|
+					 DMA_TO_DEVICE);
 | 
						|
+
 | 
						|
+		mvneta_txq_desc_put(txq);
 | 
						|
+
 | 
						|
+		if (desc_idx == 0)
 | 
						|
+			desc_idx = txq->size;
 | 
						|
+		desc_idx -= 1;
 | 
						|
+	}
 | 
						|
+}
 | 
						|
+
 | 
						|
 static int mvneta_tx_tso(struct sk_buff *skb, struct net_device *dev,
 | 
						|
 			 struct mvneta_tx_queue *txq)
 | 
						|
 {
 | 
						|
 	int hdr_len, total_len, data_left;
 | 
						|
-	int desc_count = 0;
 | 
						|
+	int first_desc, desc_count = 0;
 | 
						|
 	struct mvneta_port *pp = netdev_priv(dev);
 | 
						|
 	struct tso_t tso;
 | 
						|
-	int i;
 | 
						|
 
 | 
						|
 	/* Count needed descriptors */
 | 
						|
 	if ((txq->count + tso_count_descs(skb)) >= txq->size)
 | 
						|
@@ -2665,6 +2691,8 @@ static int mvneta_tx_tso(struct sk_buff
 | 
						|
 		return 0;
 | 
						|
 	}
 | 
						|
 
 | 
						|
+	first_desc = txq->txq_put_index;
 | 
						|
+
 | 
						|
 	/* Initialize the TSO handler, and prepare the first payload */
 | 
						|
 	hdr_len = tso_start(skb, &tso);
 | 
						|
 
 | 
						|
@@ -2705,15 +2733,7 @@ err_release:
 | 
						|
 	/* Release all used data descriptors; header descriptors must not
 | 
						|
 	 * be DMA-unmapped.
 | 
						|
 	 */
 | 
						|
-	for (i = desc_count - 1; i >= 0; i--) {
 | 
						|
-		struct mvneta_tx_desc *tx_desc = txq->descs + i;
 | 
						|
-		if (!IS_TSO_HEADER(txq, tx_desc->buf_phys_addr))
 | 
						|
-			dma_unmap_single(pp->dev->dev.parent,
 | 
						|
-					 tx_desc->buf_phys_addr,
 | 
						|
-					 tx_desc->data_size,
 | 
						|
-					 DMA_TO_DEVICE);
 | 
						|
-		mvneta_txq_desc_put(txq);
 | 
						|
-	}
 | 
						|
+	mvneta_release_descs(pp, txq, first_desc, desc_count - 1);
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
@@ -2723,6 +2743,7 @@ static int mvneta_tx_frag_process(struct
 | 
						|
 {
 | 
						|
 	struct mvneta_tx_desc *tx_desc;
 | 
						|
 	int i, nr_frags = skb_shinfo(skb)->nr_frags;
 | 
						|
+	int first_desc = txq->txq_put_index;
 | 
						|
 
 | 
						|
 	for (i = 0; i < nr_frags; i++) {
 | 
						|
 		struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index];
 | 
						|
@@ -2761,15 +2782,7 @@ error:
 | 
						|
 	/* Release all descriptors that were used to map fragments of
 | 
						|
 	 * this packet, as well as the corresponding DMA mappings
 | 
						|
 	 */
 | 
						|
-	for (i = i - 1; i >= 0; i--) {
 | 
						|
-		tx_desc = txq->descs + i;
 | 
						|
-		dma_unmap_single(pp->dev->dev.parent,
 | 
						|
-				 tx_desc->buf_phys_addr,
 | 
						|
-				 tx_desc->data_size,
 | 
						|
-				 DMA_TO_DEVICE);
 | 
						|
-		mvneta_txq_desc_put(txq);
 | 
						|
-	}
 | 
						|
-
 | 
						|
+	mvneta_release_descs(pp, txq, first_desc, i - 1);
 | 
						|
 	return -ENOMEM;
 | 
						|
 }
 | 
						|
 
 |