aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/asix_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/usb/asix_common.c')
-rw-r--r--drivers/net/usb/asix_common.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index 6a8eddfea229..1e4768debcc9 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -56,6 +56,34 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb,
56 int offset = 0; 56 int offset = 0;
57 u16 size; 57 u16 size;
58 58
59 /* When an Ethernet frame spans multiple URB socket buffers,
60 * do a sanity test for the Data header synchronisation.
61 * Attempt to detect the situation of the previous socket buffer having
62 * been truncated or a socket buffer was missing. These situations
63 * cause a discontinuity in the data stream and therefore need to avoid
64 * appending bad data to the end of the current netdev socket buffer.
65 * Also avoid unnecessarily discarding a good current netdev socket
66 * buffer.
67 */
68 if (rx->remaining && (rx->remaining + sizeof(u32) <= skb->len)) {
69 offset = ((rx->remaining + 1) & 0xfffe) + sizeof(u32);
70 rx->header = get_unaligned_le32(skb->data + offset);
71 offset = 0;
72
73 size = (u16)(rx->header & 0x7ff);
74 if (size != ((~rx->header >> 16) & 0x7ff)) {
75 netdev_err(dev->net, "asix_rx_fixup() Data Header synchronisation was lost, remaining %d\n",
76 rx->remaining);
77 kfree_skb(rx->ax_skb);
78 rx->ax_skb = NULL;
79 /* Discard the incomplete netdev Ethernet frame and
80 * assume the Data header is at the start of the current
81 * URB socket buffer.
82 */
83 rx->remaining = 0;
84 }
85 }
86
59 while (offset + sizeof(u16) <= skb->len) { 87 while (offset + sizeof(u16) <= skb->len) {
60 u16 copy_length; 88 u16 copy_length;
61 unsigned char *data; 89 unsigned char *data;