Skip to content

Commit

Permalink
net: calxedaxgmac: fix rx DMA mapping API size mismatches
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Rob Herring authored and David S. Miller committed Sep 4, 2013
1 parent d2a5128 commit 531cda2
Showing 1 changed file with 12 additions and 6 deletions.
18 changes: 12 additions & 6 deletions drivers/net/ethernet/calxeda/xgmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -695,9 +695,14 @@ static void xgmac_rx_refill(struct xgmac_priv *priv)
if (unlikely(skb == NULL))
break;

priv->rx_skbuff[entry] = skb;
paddr = dma_map_single(priv->device, skb->data,
bufsz, DMA_FROM_DEVICE);
priv->dma_buf_sz - NET_IP_ALIGN,
DMA_FROM_DEVICE);
if (dma_mapping_error(priv->device, paddr)) {
dev_kfree_skb_any(skb);
break;
}
priv->rx_skbuff[entry] = skb;
desc_set_buf_addr(p, paddr, priv->dma_buf_sz);
}

Expand Down Expand Up @@ -794,13 +799,14 @@ static void xgmac_free_rx_skbufs(struct xgmac_priv *priv)
return;

for (i = 0; i < DMA_RX_RING_SZ; i++) {
if (priv->rx_skbuff[i] == NULL)
struct sk_buff *skb = priv->rx_skbuff[i];
if (skb == NULL)
continue;

p = priv->dma_rx + i;
dma_unmap_single(priv->device, desc_get_buf_addr(p),
priv->dma_buf_sz, DMA_FROM_DEVICE);
dev_kfree_skb_any(priv->rx_skbuff[i]);
priv->dma_buf_sz - NET_IP_ALIGN, DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
priv->rx_skbuff[i] = NULL;
}
}
Expand Down Expand Up @@ -1187,7 +1193,7 @@ static int xgmac_rx(struct xgmac_priv *priv, int limit)

skb_put(skb, frame_len);
dma_unmap_single(priv->device, desc_get_buf_addr(p),
frame_len, DMA_FROM_DEVICE);
priv->dma_buf_sz - NET_IP_ALIGN, DMA_FROM_DEVICE);

skb->protocol = eth_type_trans(skb, priv->dev);
skb->ip_summed = ip_checksum;
Expand Down

0 comments on commit 531cda2

Please sign in to comment.