[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[microblaze-uclinux] [patch] microblaze ethernet driver



Hi,

A fix on the microblaze ethernet driver 
(drivers/net/xilinx_enet/adapter.c) to get the packet socket interface 
working.  David or Greg, would you please apply?

CVS note:

A fix to get the packet socket interface working.  The driver performs 
an alignment move to get the IP header to a word boundary.  Previously, 
we were only moving the IP header and above, thus obliterating the 
ethernet header.  This broke the packet socket interface.

The alignment move now includes the ethernet header as well.  DHCP and 
tcpdump (which use packet socket interface) work well now.

Regards,

John
--- /opt/src/uClinux-2.4.x/drivers/net/xilinx_enet/adapter.c	2003-11-12 13:36:37.000000000 +1000
+++ adapter.c	2004-03-31 11:14:56.000000000 +1000
@@ -711,20 +711,27 @@
 
 	skb_put(skb, len);	/* Tell the skb how much data we got. */
 	skb->dev = dev;		/* Fill out required meta-data. */
-	skb->protocol = eth_type_trans(skb, dev);
 
-	/* FIXME FIXME!! */
-	/* Microblaze can't do unaligned struct accesses, so after stripping
-	   ethernet header (22 octets), ip packet is unaligned.  We do a copy
-	   now to put it back on wrd alignment.  This violates every principle
-	   of linux networking efficiency, but until either mb-gcc or 
-	   microblaze itself is fixed, we're stuck with it */
+	/* Microblaze can't do unaligned struct accesses, meaning that the
+	   IP headers must reside on a word-boundary.  However, we must also
+	   keep the ethernet header intact, for the packet_socket interface to
+	   work.  The ethernet header is 22 bytes long...
+
+	   The solution?  Move the packet contents so that the ethernet 
+	   header is halfword aligned, thus the IP header is word aligned.
+	   It's not pretty, but it works.  JW
+	/*
 
-	memcpy(skb->head, skb->data, skb->len);
+	/* Move the packet data.  Earlier code ensured that skb->head 
+	   is word aligned, so skb->head+2 will always be halfword aligned */
+	memcpy(skb->head+2, skb->data, skb->len);
 
 	/* And fix up skbuff ptrs */
-	skb->tail -= (skb->data-skb->head);
-	skb->data=skb->head;
+	skb->tail -= (skb->data-(skb->head+2));
+	skb->data=skb->head+2;
+
+	/* Finally strip the ethernet header (really just shuffle pointers) */
+	skb->protocol = eth_type_trans(skb, dev);
 
 	lp->stats.rx_packets++;
 	lp->stats.rx_bytes += len;