mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-22 15:02:32 +00:00
76cabb95da
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)
(cherry picked from commit 7b31c2e9ed
)
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;
|
|
}
|
|
|