[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20141119205150.954960197@linuxfoundation.org>
Date: Wed, 19 Nov 2014 12:50:31 -0800
From: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
To: linux-kernel@...r.kernel.org
Cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
stable@...r.kernel.org,
Slawomir Gajzner <slawomir.gajzner@...il.com>,
Julien DAscenzio <jdascenzio@...oo.fr>,
Karl Beldan <karl.beldan@...ierawaves.com>,
Ian Campbell <ijc@...lion.org.uk>,
Eric Dumazet <eric.dumazet@...il.com>,
Ezequiel Garcia <ezequiel.garcia@...e-electrons.com>,
Sebastian Hesselbarth <sebastian.hesselbarth@...il.com>,
"David S. Miller" <davem@...emloft.net>
Subject: [PATCH 3.17 008/141] net: mv643xx_eth: reclaim TX skbs only when released by the HW
3.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karl Beldan <karl.beldan@...ierawaves.com>
[ Upstream commit 2c2a9cbd64387d6b70ac5db013e9bfe9412c7354 ]
ATM, txq_reclaim will dequeue and free an skb for each tx desc released
by the hw that has TX_LAST_DESC set. However, in case of TSO, each
hw desc embedding the last part of a segment has TX_LAST_DESC set,
losing the one-to-one 'last skb frag'/'TX_LAST_DESC set' correspondance,
which causes data corruption.
Fix this by checking TX_ENABLE_INTERRUPT instead of TX_LAST_DESC, and
warn when trying to dequeue from an empty txq (which can be symptomatic
of releasing skbs prematurely).
Fixes: 3ae8f4e0b98 ('net: mv643xx_eth: Implement software TSO')
Reported-by: Slawomir Gajzner <slawomir.gajzner@...il.com>
Reported-by: Julien D'Ascenzio <jdascenzio@...oo.fr>
Signed-off-by: Karl Beldan <karl.beldan@...ierawaves.com>
Cc: Ian Campbell <ijc@...lion.org.uk>
Cc: Eric Dumazet <eric.dumazet@...il.com>
Cc: Ezequiel Garcia <ezequiel.garcia@...e-electrons.com>
Cc: Sebastian Hesselbarth <sebastian.hesselbarth@...il.com>
Signed-off-by: David S. Miller <davem@...emloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
---
drivers/net/ethernet/marvell/mv643xx_eth.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -1047,7 +1047,6 @@ static int txq_reclaim(struct tx_queue *
int tx_index;
struct tx_desc *desc;
u32 cmd_sts;
- struct sk_buff *skb;
tx_index = txq->tx_used_desc;
desc = &txq->tx_desc_area[tx_index];
@@ -1066,19 +1065,22 @@ static int txq_reclaim(struct tx_queue *
reclaimed++;
txq->tx_desc_count--;
- skb = NULL;
- if (cmd_sts & TX_LAST_DESC)
- skb = __skb_dequeue(&txq->tx_skb);
+ if (!IS_TSO_HEADER(txq, desc->buf_ptr))
+ dma_unmap_single(mp->dev->dev.parent, desc->buf_ptr,
+ desc->byte_cnt, DMA_TO_DEVICE);
+
+ if (cmd_sts & TX_ENABLE_INTERRUPT) {
+ struct sk_buff *skb = __skb_dequeue(&txq->tx_skb);
+
+ if (!WARN_ON(!skb))
+ dev_kfree_skb(skb);
+ }
if (cmd_sts & ERROR_SUMMARY) {
netdev_info(mp->dev, "tx error\n");
mp->dev->stats.tx_errors++;
}
- if (!IS_TSO_HEADER(txq, desc->buf_ptr))
- dma_unmap_single(mp->dev->dev.parent, desc->buf_ptr,
- desc->byte_cnt, DMA_TO_DEVICE);
- dev_kfree_skb(skb);
}
__netif_tx_unlock_bh(nq);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists