> > > Don't introduce a config option. If you do this by ifdef, use ifdef
> > > on the arches that you used as default. On those arches the memmove
> > > is definitely a win.
> > > You could even test it unconditionally on i386 or x86_64. A copy may
> > > be faster than keeping it in place, as you touch the data many
> > > times, but copy it only once.
> >
> > Do you thing that copy of whole frames (up to 1.5 kilobytes!) is
> > faster than unaligned accesses to header on x86/x86_64 (which is
> > definitly used by vast majority of this driver users)?
>
> You will in most cases touch more than just the header processing
> that frame. Eventually you will copy the frame anyway. It needs to
> be tested. The bottleneck is probably reading the buffer from a cold
> cache. The assumption cannot be made without testing, but is worth
> testing.

I can't do such a test myself - I'm doing my job remotely so I don't have 
physical access to hardware, and people for whom I work are definitly not 
interested in such things so they won't set up needed environment.

But, maybe it is not important?
Multiple-frames-per-urb happens only when network load is high (and who 
uses USB network in high-load cases?), and even then - not too often.
So maybe performance impact is of minor interest?

Attached is a patch without Kconfig option.

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 11:45:00.133930152 +0300
@@ -690,6 +690,21 @@
 	return ret;
 }
 
+
+/* AX88xxx hardware sometimes packs several frames into single urb,
+ * and second and subsequent frames are 2-byte-aligned.
+ * 
+ * On RISC processors, frames must be aligned at (4n+2) adresses, to avoid
+ * unaligned accesses to IP header fields, so data move may be required.
+ *
+ * On PC processors, data move looks like unnecessary overhead.
+ */
+#if defined(CONFIG_X86_32) || defined(CONFIG_X86_64)
+#undef FIX_FRAME_ALIGNMENT
+#else
+#define FIX_FRAME_ALIGNMENT
+#endif
+
 static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
 	u8  *head;
@@ -697,6 +712,7 @@
 	char *packet;
 	struct sk_buff *ax_skb;
 	u16 size;
+	int offset;
 
 	head = (u8 *) skb->data;
 	memcpy(&header, head, sizeof(header));
@@ -713,8 +729,20 @@
 		/* get the packet length */
 		size = (u16) (header & 0x0000ffff);
 
-		if ((skb->len) - ((size + 1) & 0xfffe) == 0)
+		if ((skb->len) - ((size + 1) & 0xfffe) == 0) {
+#ifdef FIX_FRAME_ALIGNMENT
+			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 +750,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 FIX_FRAME_ALIGNMENT
+			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;
-------------------------------------------------------------------------
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