Skip to contentSkip to conversation

Patch "asix: Fix offset calculation in asix_rx_fixup() causing slow transmissions" has been added to the 4.4-stable tree

PATCH [email protected] 1 participant 1 message May 29, 2016

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

asix: Fix offset calculation in asix_rx_fixup() causing slow transmissions

to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
asix-fix-offset-calculation-in-asix_rx_fixup-causing-slow-transmissions.patch
and it can be found in the queue-4.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From cd9e2e5d3ff148be9ea210f622ce3e8e8292fcd6 Mon Sep 17 00:00:00 2001

From: John Stultz <[email protected]>
Date: Mon, 16 May 2016 20:36:15 -0700
Subject: asix: Fix offset calculation in asix_rx_fixup() causing slow transmissions

From: John Stultz <[email protected]>

commit cd9e2e5d3ff148be9ea210f622ce3e8e8292fcd6 upstream.

In testing with HiKey, we found that since
commit 3f30b158eba5 ("asix: On RX avoid creating bad Ethernet frames"),
we're seeing lots of noise during network transfers:

[  239.027993] asix 1-1.1:1.0 eth0: asix_rx_fixup() Data Header synchronisation was lost, remaining 988
[  239.037310] asix 1-1.1:1.0 eth0: asix_rx_fixup() Bad Header Length 0x54ebb5ec, offset 4
[  239.045519] asix 1-1.1:1.0 eth0: asix_rx_fixup() Bad Header Length 0xcdffe7a2, offset 4
[  239.275044] asix 1-1.1:1.0 eth0: asix_rx_fixup() Data Header synchronisation was lost, remaining 988
[  239.284355] asix 1-1.1:1.0 eth0: asix_rx_fixup() Bad Header Length 0x1d36f59d, offset 4
[  239.292541] asix 1-1.1:1.0 eth0: asix_rx_fixup() Bad Header Length 0xaef3c1e9, offset 4
[  239.518996] asix 1-1.1:1.0 eth0: asix_rx_fixup() Data Header synchronisation was lost, remaining 988
[  239.528300] asix 1-1.1:1.0 eth0: asix_rx_fixup() Bad Header Length 0x2881912, offset 4
[  239.536413] asix 1-1.1:1.0 eth0: asix_rx_fixup() Bad Header Length 0x5638f7e2, offset 4

And network throughput ends up being pretty bursty and slow with a overall throughput of at best ~30kB/s (where as previously we got 1.1MB/s with the slower USB1.1 "full speed" host).

We found the issue also was reproducible on a x86_64 system, using a "high-speed" USB2.0 port but the throughput did not measurably drop (possibly due to the scp transfer being cpu bound on my slow test hardware).

After lots of debugging, I found the check added in the problematic commit seems to be calculating the offset incorrectly.

In the normal case, in the main loop of the function, we do:
(where offset is zero, or set to "offset += (copy_length + 1) & 0xfffe" in the previous loop)

    rx->header = get_unaligned_le32(skb->data +
                                    offset);
    offset += sizeof(u32);

But the problematic patch calculates:

    offset = ((rx->remaining + 1) & 0xfffe) + sizeof(u32);
    rx->header = get_unaligned_le32(skb->data + offset);

Adding some debug logic to check those offset calculation used to find rx->header, the one in problematic code is always too large by sizeof(u32).

Thus, this patch removes the incorrect " + sizeof(u32)" addition in the problematic calculation, and resolves the issue.

---
 drivers/net/usb/asix_common.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/usb/asix_common.c +1 -1
@@ -66,7 +66,7 @@ int asix_rx_fixup_internal(struct usbnet
 	 * buffer.
 	 */
 	if (rx->remaining && (rx->remaining + sizeof(u32) <= skb->len)) {
-		offset = ((rx->remaining + 1) & 0xfffe) + sizeof(u32);
+		offset = ((rx->remaining + 1) & 0xfffe);
 		rx->header = get_unaligned_le32(skb->data + offset);
 		offset = 0;
 

Patches currently in stable-queue which might be from [email protected] are

queue-4.4/asix-fix-offset-calculation-in-asix_rx_fixup-causing-slow-transmissions.patch