stmmac: add tx_skbuff_dma to save descriptors used by PTP
authorRayagond Kokatanur <rayagond@vayavyalabs.com>
Tue, 26 Mar 2013 04:43:09 +0000 (04:43 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 26 Mar 2013 16:53:37 +0000 (12:53 -0400)
This patch adds a new pointer variable called "tx_skbuff_dma" to private
data structure. This variable will holds the physical address of packet
to be transmitted & same will be used to free/unmap the memory once the
corresponding packet is transmitted by device.

Prior to this patch the descriptor buffer pointer(ie des2) itself was
being used for freeing/unmapping the buffer memory. But in case PTP v1
with normal descriptor the field(des2) will be overwritten by device
with timestamp value, hence driver will loose the buffer pointer to be
freed/unmapped.

Signed-off-by: Rayagond Kokatanur <rayagond@vayavyalabs.com>
Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/stmicro/stmmac/chain_mode.c
drivers/net/ethernet/stmicro/stmmac/ring_mode.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

index 688c3f4f1781c2e6a764c5985694d05630ca3f29..63b6031e304a54af305621017d560858d2db67a9 100644 (file)
@@ -47,6 +47,7 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 
        desc->des2 = dma_map_single(priv->device, skb->data,
                                    bmax, DMA_TO_DEVICE);
+       priv->tx_skbuff_dma[entry] = desc->des2;
        priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE);
 
        while (len != 0) {
@@ -57,6 +58,7 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
                        desc->des2 = dma_map_single(priv->device,
                                                    (skb->data + bmax * i),
                                                    bmax, DMA_TO_DEVICE);
+                       priv->tx_skbuff_dma[entry] = desc->des2;
                        priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum,
                                                        STMMAC_CHAIN_MODE);
                        priv->hw->desc->set_tx_owner(desc);
@@ -67,6 +69,7 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
                        desc->des2 = dma_map_single(priv->device,
                                                    (skb->data + bmax * i), len,
                                                    DMA_TO_DEVICE);
+                       priv->tx_skbuff_dma[entry] = desc->des2;
                        priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
                                                        STMMAC_CHAIN_MODE);
                        priv->hw->desc->set_tx_owner(desc);
index 8a5e661f4fda5a2d6bad252f97d614ff202c48b0..43fc699b21cc6bd09ad02e2a4308e6a2c1b1940e 100644 (file)
@@ -48,6 +48,7 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 
                desc->des2 = dma_map_single(priv->device, skb->data,
                                            bmax, DMA_TO_DEVICE);
+               priv->tx_skbuff_dma[entry] = desc->des2;
                desc->des3 = desc->des2 + BUF_SIZE_4KiB;
                priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum,
                                                STMMAC_RING_MODE);
@@ -57,6 +58,7 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 
                desc->des2 = dma_map_single(priv->device, skb->data + bmax,
                                            len, DMA_TO_DEVICE);
+               priv->tx_skbuff_dma[entry] = desc->des2;
                desc->des3 = desc->des2 + BUF_SIZE_4KiB;
                priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
                                                STMMAC_RING_MODE);
@@ -66,6 +68,7 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
        } else {
                desc->des2 = dma_map_single(priv->device, skb->data,
                                            nopaged_len, DMA_TO_DEVICE);
+               priv->tx_skbuff_dma[entry] = desc->des2;
                desc->des3 = desc->des2 + BUF_SIZE_4KiB;
                priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum,
                                                STMMAC_RING_MODE);
index 182a83802aa2b68d2b48ef978cab1281c1a1b8a1..5176cae44b038dfbb7b3c314f283ff0471c823a7 100644 (file)
@@ -38,6 +38,7 @@ struct stmmac_priv {
        struct dma_extended_desc *dma_etx;      /* Extended TX descriptor */
        dma_addr_t dma_tx_phy;
        struct sk_buff **tx_skbuff;
+       dma_addr_t *tx_skbuff_dma;
        unsigned int cur_tx;
        unsigned int dirty_tx;
        unsigned int dma_tx_size;
index ac166be325ede6e1f3946aeebe19d4d8d5b7dcc8..180eed7168c14b3c0641a5b8e91b5601c535a173 100644 (file)
@@ -661,6 +661,8 @@ static void init_dma_desc_rings(struct net_device *dev)
                                            GFP_KERNEL);
        priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *),
                                        GFP_KERNEL);
+       priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t),
+                                       GFP_KERNEL);
        priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *),
                                        GFP_KERNEL);
        if (netif_msg_drv(priv))
@@ -710,6 +712,7 @@ static void init_dma_desc_rings(struct net_device *dev)
                else
                        p = priv->dma_tx + i;
                p->des2 = 0;
+               priv->tx_skbuff_dma[i] = 0;
                priv->tx_skbuff[i] = NULL;
        }
 
@@ -748,12 +751,14 @@ static void dma_free_tx_skbufs(struct stmmac_priv *priv)
                        else
                                p = priv->dma_tx + i;
 
-                       if (p->des2)
-                               dma_unmap_single(priv->device, p->des2,
+                       if (priv->tx_skbuff_dma[i])
+                               dma_unmap_single(priv->device,
+                                                priv->tx_skbuff_dma[i],
                                                 priv->hw->desc->get_tx_len(p),
                                                 DMA_TO_DEVICE);
                        dev_kfree_skb_any(priv->tx_skbuff[i]);
                        priv->tx_skbuff[i] = NULL;
+                       priv->tx_skbuff_dma[i] = 0;
                }
        }
 }
@@ -783,6 +788,7 @@ static void free_dma_desc_resources(struct stmmac_priv *priv)
        }
        kfree(priv->rx_skbuff_dma);
        kfree(priv->rx_skbuff);
+       kfree(priv->tx_skbuff_dma);
        kfree(priv->tx_skbuff);
 }
 
@@ -854,10 +860,13 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
                TX_DBG("%s: curr %d, dirty %d\n", __func__,
                        priv->cur_tx, priv->dirty_tx);
 
-               if (likely(p->des2))
-                       dma_unmap_single(priv->device, p->des2,
+               if (likely(priv->tx_skbuff_dma[entry])) {
+                       dma_unmap_single(priv->device,
+                                        priv->tx_skbuff_dma[entry],
                                         priv->hw->desc->get_tx_len(p),
                                         DMA_TO_DEVICE);
+                       priv->tx_skbuff_dma[entry] = 0;
+               }
                if (priv->mode == STMMAC_RING_MODE)
                        priv->hw->ring->clean_desc3(p);
 
@@ -1423,6 +1432,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
        if (likely(!is_jumbo)) {
                desc->des2 = dma_map_single(priv->device, skb->data,
                                        nopaged_len, DMA_TO_DEVICE);
+               priv->tx_skbuff_dma[entry] = desc->des2;
                priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
                                                csum_insertion, priv->mode);
        } else
@@ -1441,6 +1451,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
                TX_DBG("\t[entry %d] segment len: %d\n", entry, len);
                desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len,
                                              DMA_TO_DEVICE);
+               priv->tx_skbuff_dma[entry] = desc->des2;
                priv->tx_skbuff[entry] = NULL;
                priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,
                                                priv->mode);