net: mvneta: Avoid unmapping the TSO header buffers
authorEzequiel Garcia <ezequiel.garcia@free-electrons.com>
Fri, 30 May 2014 16:40:07 +0000 (13:40 -0300)
committerDavid S. Miller <davem@davemloft.net>
Mon, 2 Jun 2014 23:16:05 +0000 (16:16 -0700)
The buffers for the TSO headers belong to a DMA coherent region which is
allocated at ndo_open() time, and released at ndo_stop() time.

Therefore, and contrary to the TSO payload descriptor buffers, the TSO header
buffers don't need to be unmapped. This commit adds a check to detect a
TSO header buffer and explicitly prevent the unmap.

Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/mvneta.c

index f95e7ca..45beca1 100644 (file)
              ETH_HLEN + ETH_FCS_LEN,                        \
              MVNETA_CPU_D_CACHE_LINE_SIZE)
 
+#define IS_TSO_HEADER(txq, addr) \
+       ((addr >= txq->tso_hdrs_phys) && \
+        (addr < txq->tso_hdrs_phys + txq->size * TSO_HEADER_SIZE))
+
 #define MVNETA_RX_BUF_SIZE(pkt_size)   ((pkt_size) + NET_SKB_PAD)
 
 struct mvneta_pcpu_stats {
@@ -1291,8 +1295,10 @@ static void mvneta_txq_bufs_free(struct mvneta_port *pp,
 
                mvneta_txq_inc_get(txq);
 
-               dma_unmap_single(pp->dev->dev.parent, tx_desc->buf_phys_addr,
-                                tx_desc->data_size, DMA_TO_DEVICE);
+               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);
                if (!skb)
                        continue;
                dev_kfree_skb_any(skb);
@@ -1642,7 +1648,7 @@ err_release:
         */
        for (i = desc_count - 1; i >= 0; i--) {
                struct mvneta_tx_desc *tx_desc = txq->descs + i;
-               if (!(tx_desc->command & MVNETA_TXD_F_DESC))
+               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,