[PATCH] mv643xx: add workaround for HW checksum generation bug

[PATCH] [NET] mv643xx: add workaround for HW checksum generation bug

The hardware checksum generator on the mv64xxx occasionally generates
an incorrect checksum.  This patch works around the issue and enables
hardware checksum generation.

Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 0405e1f..fb6b232 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -1157,16 +1157,20 @@
 	if (!skb_shinfo(skb)->nr_frags) {
 linear:
 		if (skb->ip_summed != CHECKSUM_HW) {
+			/* Errata BTS #50, IHL must be 5 if no HW checksum */
 			pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
-					ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;
+					   ETH_TX_FIRST_DESC |
+					   ETH_TX_LAST_DESC |
+					   5 << ETH_TX_IHL_SHIFT;
 			pkt_info.l4i_chk = 0;
 		} else {
-			u32 ipheader = skb->nh.iph->ihl << 11;
 
 			pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
-					ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC |
-					ETH_GEN_TCP_UDP_CHECKSUM |
-					ETH_GEN_IP_V_4_CHECKSUM | ipheader;
+					   ETH_TX_FIRST_DESC |
+					   ETH_TX_LAST_DESC |
+					   ETH_GEN_TCP_UDP_CHECKSUM |
+					   ETH_GEN_IP_V_4_CHECKSUM |
+					   skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
 			/* CPU already calculated pseudo header checksum. */
 			if (skb->nh.iph->protocol == IPPROTO_UDP) {
 				pkt_info.cmd_sts |= ETH_UDP_FRAME;
@@ -1193,7 +1197,6 @@
 		stats->tx_bytes += pkt_info.byte_cnt;
 	} else {
 		unsigned int frag;
-		u32 ipheader;
 
 		/* Since hardware can't handle unaligned fragments smaller
 		 * than 9 bytes, if we find any, we linearize the skb
@@ -1222,12 +1225,16 @@
 							DMA_TO_DEVICE);
 		pkt_info.l4i_chk = 0;
 		pkt_info.return_info = 0;
-		pkt_info.cmd_sts = ETH_TX_FIRST_DESC;
 
-		if (skb->ip_summed == CHECKSUM_HW) {
-			ipheader = skb->nh.iph->ihl << 11;
-			pkt_info.cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM |
-					ETH_GEN_IP_V_4_CHECKSUM | ipheader;
+		if (skb->ip_summed != CHECKSUM_HW)
+			/* Errata BTS #50, IHL must be 5 if no HW checksum */
+			pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
+					   5 << ETH_TX_IHL_SHIFT;
+		else {
+			pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
+					   ETH_GEN_TCP_UDP_CHECKSUM |
+					   ETH_GEN_IP_V_4_CHECKSUM |
+					   skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
 			/* CPU already calculated pseudo header checksum. */
 			if (skb->nh.iph->protocol == IPPROTO_UDP) {
 				pkt_info.cmd_sts |= ETH_UDP_FRAME;