lkml.org 
[lkml]   [2014]   [Nov]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.17 008/141] net: mv643xx_eth: reclaim TX skbs only when released by the HW
    Date
    3.17-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Karl Beldan <karl.beldan@rivierawaves.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@gmail.com>
    Reported-by: Julien D'Ascenzio <jdascenzio@yahoo.fr>
    Signed-off-by: Karl Beldan <karl.beldan@rivierawaves.com>
    Cc: Ian Campbell <ijc@hellion.org.uk>
    Cc: Eric Dumazet <eric.dumazet@gmail.com>
    Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
    Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.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);



    \
     
     \ /
      Last update: 2014-11-20 00:01    [W:4.215 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site