From b44cd572623cb6a931a947d9108595517fd945f8 Mon Sep 17 00:00:00 2001
From: Dale Farnsworth <dale@farnsworth.org>
Date: Mon, 16 Jan 2006 16:51:22 -0700
Subject: [PATCH] [PATCH] mv643xx_eth: Receive buffers require 8 byte alignment

The Marvell mv643xx ethernet hardware requires that DMA buffers be
aligned to 8-byte boundaries.  This patch satisfies this requirement.
Buffers allocated by dev_alloc_skb() only have 4-byte alignment when
slab debugging is enabled.

Also, document that the 2-byte offset to align the IP packets on
receive is a hardware feature and is not tied to NET_IP_ALIGN.

Signed-off-by: Dale Farnsworth <dale@farnsworth.org>

 mv643xx_eth.c |   12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
---
 drivers/net/mv643xx_eth.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index f100ca7d3ee2..4afb954092a6 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -57,7 +57,9 @@
 /* Constants */
 #define VLAN_HLEN		4
 #define FCS_LEN			4
-#define WRAP			NET_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN
+#define DMA_ALIGN		8	/* hw requires 8-byte alignment */
+#define HW_IP_ALIGN		2	/* hw aligns IP header */
+#define WRAP			HW_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN
 #define RX_SKB_SIZE		((dev->mtu + WRAP + 7) & ~0x7)
 
 #define INT_CAUSE_UNMASK_ALL		0x0007ffff
@@ -173,15 +175,19 @@ static void mv643xx_eth_rx_task(void *data)
 	struct mv643xx_private *mp = netdev_priv(dev);
 	struct pkt_info pkt_info;
 	struct sk_buff *skb;
+	int unaligned;
 
 	if (test_and_set_bit(0, &mp->rx_task_busy))
 		panic("%s: Error in test_set_bit / clear_bit", dev->name);
 
 	while (mp->rx_ring_skbs < (mp->rx_ring_size - 5)) {
-		skb = dev_alloc_skb(RX_SKB_SIZE);
+		skb = dev_alloc_skb(RX_SKB_SIZE + DMA_ALIGN);
 		if (!skb)
 			break;
 		mp->rx_ring_skbs++;
+		unaligned = (u32)skb->data & (DMA_ALIGN - 1);
+		if (unaligned)
+			skb_reserve(skb, DMA_ALIGN - unaligned);
 		pkt_info.cmd_sts = ETH_RX_ENABLE_INTERRUPT;
 		pkt_info.byte_cnt = RX_SKB_SIZE;
 		pkt_info.buf_ptr = dma_map_single(NULL, skb->data, RX_SKB_SIZE,
@@ -192,7 +198,7 @@ static void mv643xx_eth_rx_task(void *data)
 				"%s: Error allocating RX Ring\n", dev->name);
 			break;
 		}
-		skb_reserve(skb, 2);
+		skb_reserve(skb, HW_IP_ALIGN);
 	}
 	clear_bit(0, &mp->rx_task_busy);
 	/*
-- 
GitLab