> 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 ...
One more attempt, with typo fixed ... 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:58:31.655621451 +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_NET_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)"
pgpoxI2QdwMRu.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
_______________________________________________ [email protected] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
