aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorRob Herring <rob.herring@calxeda.com>2013-08-30 17:49:28 -0400
committerDavid S. Miller <davem@davemloft.net>2013-09-03 22:21:16 -0400
commit531cda20cd44d5a7a77debaaeaa407d4802d7e05 (patch)
treed7b0756ac82ccc95de95ecb8e037a2fe9795f355 /drivers/net
parentd2a5128fbc30480763bbb8a43ec7c8161c1bf055 (diff)
net: calxedaxgmac: fix rx DMA mapping API size mismatches
Fix the mismatch in the DMA mapping and unmapping sizes for receive. The unmap size must be equal to the map size and should not be the actual received frame length. The map size should also be adjusted by the NET_IP_ALIGN size since the h/w buffer size (dma_buf_sz) includes this offset. Also, add a missing dma_mapping_error check in xgmac_rx_refill. Reported-by: Lennert Buytenhek <buytenh@wantstofly.org> Signed-off-by: Rob Herring <rob.herring@calxeda.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/calxeda/xgmac.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 04c585ce9bfb..cd5010b4a89c 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -695,9 +695,14 @@ static void xgmac_rx_refill(struct xgmac_priv *priv)
695 if (unlikely(skb == NULL)) 695 if (unlikely(skb == NULL))
696 break; 696 break;
697 697
698 priv->rx_skbuff[entry] = skb;
699 paddr = dma_map_single(priv->device, skb->data, 698 paddr = dma_map_single(priv->device, skb->data,
700 bufsz, DMA_FROM_DEVICE); 699 priv->dma_buf_sz - NET_IP_ALIGN,
700 DMA_FROM_DEVICE);
701 if (dma_mapping_error(priv->device, paddr)) {
702 dev_kfree_skb_any(skb);
703 break;
704 }
705 priv->rx_skbuff[entry] = skb;
701 desc_set_buf_addr(p, paddr, priv->dma_buf_sz); 706 desc_set_buf_addr(p, paddr, priv->dma_buf_sz);
702 } 707 }
703 708
@@ -794,13 +799,14 @@ static void xgmac_free_rx_skbufs(struct xgmac_priv *priv)
794 return; 799 return;
795 800
796 for (i = 0; i < DMA_RX_RING_SZ; i++) { 801 for (i = 0; i < DMA_RX_RING_SZ; i++) {
797 if (priv->rx_skbuff[i] == NULL) 802 struct sk_buff *skb = priv->rx_skbuff[i];
803 if (skb == NULL)
798 continue; 804 continue;
799 805
800 p = priv->dma_rx + i; 806 p = priv->dma_rx + i;
801 dma_unmap_single(priv->device, desc_get_buf_addr(p), 807 dma_unmap_single(priv->device, desc_get_buf_addr(p),
802 priv->dma_buf_sz, DMA_FROM_DEVICE); 808 priv->dma_buf_sz - NET_IP_ALIGN, DMA_FROM_DEVICE);
803 dev_kfree_skb_any(priv->rx_skbuff[i]); 809 dev_kfree_skb_any(skb);
804 priv->rx_skbuff[i] = NULL; 810 priv->rx_skbuff[i] = NULL;
805 } 811 }
806} 812}
@@ -1187,7 +1193,7 @@ static int xgmac_rx(struct xgmac_priv *priv, int limit)
1187 1193
1188 skb_put(skb, frame_len); 1194 skb_put(skb, frame_len);
1189 dma_unmap_single(priv->device, desc_get_buf_addr(p), 1195 dma_unmap_single(priv->device, desc_get_buf_addr(p),
1190 frame_len, DMA_FROM_DEVICE); 1196 priv->dma_buf_sz - NET_IP_ALIGN, DMA_FROM_DEVICE);
1191 1197
1192 skb->protocol = eth_type_trans(skb, priv->dev); 1198 skb->protocol = eth_type_trans(skb, priv->dev);
1193 skb->ip_summed = ip_checksum; 1199 skb->ip_summed = ip_checksum;