summaryrefslogtreecommitdiffstats
path: root/drivers/net/mv643xx_eth.c
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2008-08-24 03:00:20 +0200
committerLennert Buytenhek <buytenh@marvell.com>2008-08-24 03:33:44 +0200
commitabe787170bb3888c5e587e8e986711fe32ddf2f9 (patch)
treea1e1854fe95054adf2c3336bb5713936f2ab4efe /drivers/net/mv643xx_eth.c
parent9e1f37724265725ad4c14fc2ef60a162dc13ac64 (diff)
mv643xx_eth: enforce multiple-of-8-bytes receive buffer size restriction
The mv643xx_eth hardware ignores the lower three bits of the buffer size field in receive descriptors, causing the reception of full-sized packets to fail at some MTUs. Fix this by rounding the size of allocated receive buffers up to a multiple of eight bytes. While we are at it, add a bit of extra space to each receive buffer so that we can handle multiple vlan tags on ingress. Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Diffstat (limited to 'drivers/net/mv643xx_eth.c')
-rw-r--r--drivers/net/mv643xx_eth.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index e33dfc0165f..a02a5f4a029 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -474,11 +474,19 @@ static void rxq_refill(struct rx_queue *rxq)
/*
* Reserve 2+14 bytes for an ethernet header (the
* hardware automatically prepends 2 bytes of dummy
- * data to each received packet), 4 bytes for a VLAN
- * header, and 4 bytes for the trailing FCS -- 24
- * bytes total.
+ * data to each received packet), 16 bytes for up to
+ * four VLAN tags, and 4 bytes for the trailing FCS
+ * -- 36 bytes total.
*/
- skb_size = mp->dev->mtu + 24;
+ skb_size = mp->dev->mtu + 36;
+
+ /*
+ * Make sure that the skb size is a multiple of 8
+ * bytes, as the lower three bits of the receive
+ * descriptor's buffer size field are ignored by
+ * the hardware.
+ */
+ skb_size = (skb_size + 7) & ~7;
skb = dev_alloc_skb(skb_size + dma_get_cache_alignment() - 1);
if (skb == NULL)
@@ -552,7 +560,7 @@ static int rxq_process(struct rx_queue *rxq, int budget)
spin_unlock_irqrestore(&mp->lock, flags);
dma_unmap_single(NULL, rx_desc->buf_ptr + 2,
- mp->dev->mtu + 24, DMA_FROM_DEVICE);
+ rx_desc->buf_size, DMA_FROM_DEVICE);
rxq->rx_desc_count--;
rx++;