> However, I've located one more problem which I don't know yet how to fix
> correctly.
> AFAIR, device may pass several incoming frames in one urb, and second
> and later frames are 2-byte-aligned.
> This may cause situations when IP layer gets IP packet not aligned at
> 32-bit word boundary and occasionally crash because of unligned access
> (hardware and/or codebase I'm working with really dislikes unaligned
> accesses from kernel).
>
> Looks the only way to fix that is to detect such cases, and copy data?
> But this will hurt performance on systems that can handle unaligned
> accesses ...

Attached is a patch that handles this, based on additional Kconfig key.
I've tested this on hardware and kernel I'm working with, and then 
forward-ported to 2.6.19-pre6

Signed-off-by: Nikita Youshchenko <[EMAIL PROTECTED]>

Nikita
diff -ur net.orig/asix.c net/asix.c
--- net.orig/asix.c	2006-10-15 16:20:26.000000000 +0400
+++ net/asix.c	2006-11-24 07:53:03.277679810 +0300
@@ -697,6 +697,7 @@
 	char *packet;
 	struct sk_buff *ax_skb;
 	u16 size;
+	int offset;
 
 	head = (u8 *) skb->data;
 	memcpy(&header, head, sizeof(header));
@@ -713,8 +714,20 @@
 		/* get the packet length */
 		size = (u16) (header & 0x0000ffff);
 
-		if ((skb->len) - ((size + 1) & 0xfffe) == 0)
+		if ((skb->len) - ((size + 1) & 0xfffe) == 0) {
+#ifdef CONFIG_USB_NET_AX8817X_ALIGN
+			offset = ((unsigned long)packet + 2) & 3;
+#else
+			offset = 0;
+#endif
+			if (offset) {
+				skb->data -= offset;
+				skb->tail -= offset;
+				memmove(packet - offset, packet, size);
+			}
+
 			return 2;
+		}
 		if (size > ETH_FRAME_LEN) {
 			devdbg(dev,"invalid rx length %d", size);
 			return 0;
@@ -722,8 +735,17 @@
 		ax_skb = skb_clone(skb, GFP_ATOMIC);
 		if (ax_skb) {
 			ax_skb->len = size;
-			ax_skb->data = packet;
-			ax_skb->tail = packet + size;
+
+#ifdef CONFIG_USB_NET_AX8817X_ALIGN
+			offset = ((unsigned long)packet + 2) & 3;
+#else
+			offset = 0;
+#endif
+			ax_skb->data = packet - offset;
+			ax_skb->tail = packet - offset + size;
+			if (offset)
+				memmove(packet - offset, packet, size);
+
 			usbnet_skb_return(dev, ax_skb);
 		} else {
 			return 0;
diff -ur net.orig/Kconfig net/Kconfig
--- net.orig/Kconfig	2006-10-15 16:20:26.000000000 +0400
+++ net/Kconfig	2006-11-24 07:49:16.155519445 +0300
@@ -153,6 +153,27 @@
 	  This driver creates an interface named "ethX", where X depends on
 	  what other networking devices you have in use.
 
+config USB_AX8817X_ALIGN
+	boolean "ASIX AX88xxx: align incoming frames"
+	depends on USB_NET_AX8817X
+	default y if MIPS || ARM
+	default n if X86 || X86_64
+	help
+	  AX88xxx chips sometimes packs several network frames into same USB
+	  data block. This may cause payload of second and subsequent frames
+	  not to be aligned at 32bit boundary, which in turn may cause large
+	  performance penalties or even kernel crashes on some RISC processors.
+
+	  Answering Y here will add to driver code that detects incorrectly
+	  aligned frames, and manually moves those to fix alignment. This
+	  fixes the issue for processors that have it, but only causes
+	  unneeded performance penalty on processors that have no problems
+	  with unaligned data access (such as x86 PC processors).
+
+	  If unsure, say N.
+	  
+	  If you are experiencing kernel crashes when using AX88xxx-based
+	  hardware, answer Y.
 
 config USB_NET_CDCETHER
 	tristate "CDC Ethernet support (smart devices such as cable modems)"

Attachment: pgpE31SZVOAKW.pgp
Description: PGP signature

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to