aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/stmicro
diff options
context:
space:
mode:
authorRayagond Kokatanur <rayagond@vayavyalabs.com>2013-03-26 00:43:09 -0400
committerDavid S. Miller <davem@davemloft.net>2013-03-26 12:53:37 -0400
commitcf32deec16e4e8d47305bdc638fd108c88e06081 (patch)
tree1ea6ae2de2f92f18fff9332410f403f923e6cb99 /drivers/net/ethernet/stmicro
parente58bb43f5e438c9e003100a13a168aa90a651faa (diff)
stmmac: add tx_skbuff_dma to save descriptors used by PTP
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>
Diffstat (limited to 'drivers/net/ethernet/stmicro')
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/chain_mode.c3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/ring_mode.c3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c19
4 files changed, 22 insertions, 4 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
index 688c3f4f1781..63b6031e304a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
@@ -47,6 +47,7 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
47 47
48 desc->des2 = dma_map_single(priv->device, skb->data, 48 desc->des2 = dma_map_single(priv->device, skb->data,
49 bmax, DMA_TO_DEVICE); 49 bmax, DMA_TO_DEVICE);
50 priv->tx_skbuff_dma[entry] = desc->des2;
50 priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE); 51 priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE);
51 52
52 while (len != 0) { 53 while (len != 0) {
@@ -57,6 +58,7 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
57 desc->des2 = dma_map_single(priv->device, 58 desc->des2 = dma_map_single(priv->device,
58 (skb->data + bmax * i), 59 (skb->data + bmax * i),
59 bmax, DMA_TO_DEVICE); 60 bmax, DMA_TO_DEVICE);
61 priv->tx_skbuff_dma[entry] = desc->des2;
60 priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum, 62 priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum,
61 STMMAC_CHAIN_MODE); 63 STMMAC_CHAIN_MODE);
62 priv->hw->desc->set_tx_owner(desc); 64 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)
67 desc->des2 = dma_map_single(priv->device, 69 desc->des2 = dma_map_single(priv->device,
68 (skb->data + bmax * i), len, 70 (skb->data + bmax * i), len,
69 DMA_TO_DEVICE); 71 DMA_TO_DEVICE);
72 priv->tx_skbuff_dma[entry] = desc->des2;
70 priv->hw->desc->prepare_tx_desc(desc, 0, len, csum, 73 priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
71 STMMAC_CHAIN_MODE); 74 STMMAC_CHAIN_MODE);
72 priv->hw->desc->set_tx_owner(desc); 75 priv->hw->desc->set_tx_owner(desc);
diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
index 8a5e661f4fda..43fc699b21cc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
@@ -48,6 +48,7 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
48 48
49 desc->des2 = dma_map_single(priv->device, skb->data, 49 desc->des2 = dma_map_single(priv->device, skb->data,
50 bmax, DMA_TO_DEVICE); 50 bmax, DMA_TO_DEVICE);
51 priv->tx_skbuff_dma[entry] = desc->des2;
51 desc->des3 = desc->des2 + BUF_SIZE_4KiB; 52 desc->des3 = desc->des2 + BUF_SIZE_4KiB;
52 priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, 53 priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum,
53 STMMAC_RING_MODE); 54 STMMAC_RING_MODE);
@@ -57,6 +58,7 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
57 58
58 desc->des2 = dma_map_single(priv->device, skb->data + bmax, 59 desc->des2 = dma_map_single(priv->device, skb->data + bmax,
59 len, DMA_TO_DEVICE); 60 len, DMA_TO_DEVICE);
61 priv->tx_skbuff_dma[entry] = desc->des2;
60 desc->des3 = desc->des2 + BUF_SIZE_4KiB; 62 desc->des3 = desc->des2 + BUF_SIZE_4KiB;
61 priv->hw->desc->prepare_tx_desc(desc, 0, len, csum, 63 priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
62 STMMAC_RING_MODE); 64 STMMAC_RING_MODE);
@@ -66,6 +68,7 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
66 } else { 68 } else {
67 desc->des2 = dma_map_single(priv->device, skb->data, 69 desc->des2 = dma_map_single(priv->device, skb->data,
68 nopaged_len, DMA_TO_DEVICE); 70 nopaged_len, DMA_TO_DEVICE);
71 priv->tx_skbuff_dma[entry] = desc->des2;
69 desc->des3 = desc->des2 + BUF_SIZE_4KiB; 72 desc->des3 = desc->des2 + BUF_SIZE_4KiB;
70 priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum, 73 priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum,
71 STMMAC_RING_MODE); 74 STMMAC_RING_MODE);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 182a83802aa2..5176cae44b03 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -38,6 +38,7 @@ struct stmmac_priv {
38 struct dma_extended_desc *dma_etx; /* Extended TX descriptor */ 38 struct dma_extended_desc *dma_etx; /* Extended TX descriptor */
39 dma_addr_t dma_tx_phy; 39 dma_addr_t dma_tx_phy;
40 struct sk_buff **tx_skbuff; 40 struct sk_buff **tx_skbuff;
41 dma_addr_t *tx_skbuff_dma;
41 unsigned int cur_tx; 42 unsigned int cur_tx;
42 unsigned int dirty_tx; 43 unsigned int dirty_tx;
43 unsigned int dma_tx_size; 44 unsigned int dma_tx_size;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index ac166be325ed..180eed7168c1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -661,6 +661,8 @@ static void init_dma_desc_rings(struct net_device *dev)
661 GFP_KERNEL); 661 GFP_KERNEL);
662 priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *), 662 priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *),
663 GFP_KERNEL); 663 GFP_KERNEL);
664 priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t),
665 GFP_KERNEL);
664 priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *), 666 priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *),
665 GFP_KERNEL); 667 GFP_KERNEL);
666 if (netif_msg_drv(priv)) 668 if (netif_msg_drv(priv))
@@ -710,6 +712,7 @@ static void init_dma_desc_rings(struct net_device *dev)
710 else 712 else
711 p = priv->dma_tx + i; 713 p = priv->dma_tx + i;
712 p->des2 = 0; 714 p->des2 = 0;
715 priv->tx_skbuff_dma[i] = 0;
713 priv->tx_skbuff[i] = NULL; 716 priv->tx_skbuff[i] = NULL;
714 } 717 }
715 718
@@ -748,12 +751,14 @@ static void dma_free_tx_skbufs(struct stmmac_priv *priv)
748 else 751 else
749 p = priv->dma_tx + i; 752 p = priv->dma_tx + i;
750 753
751 if (p->des2) 754 if (priv->tx_skbuff_dma[i])
752 dma_unmap_single(priv->device, p->des2, 755 dma_unmap_single(priv->device,
756 priv->tx_skbuff_dma[i],
753 priv->hw->desc->get_tx_len(p), 757 priv->hw->desc->get_tx_len(p),
754 DMA_TO_DEVICE); 758 DMA_TO_DEVICE);
755 dev_kfree_skb_any(priv->tx_skbuff[i]); 759 dev_kfree_skb_any(priv->tx_skbuff[i]);
756 priv->tx_skbuff[i] = NULL; 760 priv->tx_skbuff[i] = NULL;
761 priv->tx_skbuff_dma[i] = 0;
757 } 762 }
758 } 763 }
759} 764}
@@ -783,6 +788,7 @@ static void free_dma_desc_resources(struct stmmac_priv *priv)
783 } 788 }
784 kfree(priv->rx_skbuff_dma); 789 kfree(priv->rx_skbuff_dma);
785 kfree(priv->rx_skbuff); 790 kfree(priv->rx_skbuff);
791 kfree(priv->tx_skbuff_dma);
786 kfree(priv->tx_skbuff); 792 kfree(priv->tx_skbuff);
787} 793}
788 794
@@ -854,10 +860,13 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
854 TX_DBG("%s: curr %d, dirty %d\n", __func__, 860 TX_DBG("%s: curr %d, dirty %d\n", __func__,
855 priv->cur_tx, priv->dirty_tx); 861 priv->cur_tx, priv->dirty_tx);
856 862
857 if (likely(p->des2)) 863 if (likely(priv->tx_skbuff_dma[entry])) {
858 dma_unmap_single(priv->device, p->des2, 864 dma_unmap_single(priv->device,
865 priv->tx_skbuff_dma[entry],
859 priv->hw->desc->get_tx_len(p), 866 priv->hw->desc->get_tx_len(p),
860 DMA_TO_DEVICE); 867 DMA_TO_DEVICE);
868 priv->tx_skbuff_dma[entry] = 0;
869 }
861 if (priv->mode == STMMAC_RING_MODE) 870 if (priv->mode == STMMAC_RING_MODE)
862 priv->hw->ring->clean_desc3(p); 871 priv->hw->ring->clean_desc3(p);
863 872
@@ -1423,6 +1432,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
1423 if (likely(!is_jumbo)) { 1432 if (likely(!is_jumbo)) {
1424 desc->des2 = dma_map_single(priv->device, skb->data, 1433 desc->des2 = dma_map_single(priv->device, skb->data,
1425 nopaged_len, DMA_TO_DEVICE); 1434 nopaged_len, DMA_TO_DEVICE);
1435 priv->tx_skbuff_dma[entry] = desc->des2;
1426 priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, 1436 priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
1427 csum_insertion, priv->mode); 1437 csum_insertion, priv->mode);
1428 } else 1438 } else
@@ -1441,6 +1451,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
1441 TX_DBG("\t[entry %d] segment len: %d\n", entry, len); 1451 TX_DBG("\t[entry %d] segment len: %d\n", entry, len);
1442 desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len, 1452 desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len,
1443 DMA_TO_DEVICE); 1453 DMA_TO_DEVICE);
1454 priv->tx_skbuff_dma[entry] = desc->des2;
1444 priv->tx_skbuff[entry] = NULL; 1455 priv->tx_skbuff[entry] = NULL;
1445 priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion, 1456 priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,
1446 priv->mode); 1457 priv->mode);