diff options
Diffstat (limited to 'drivers/net/usb/asix.c')
-rw-r--r-- | drivers/net/usb/asix.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 8e7d2374558b..66c5e89326c1 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c | |||
@@ -322,8 +322,29 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
322 | /* get the packet length */ | 322 | /* get the packet length */ |
323 | size = (u16) (header & 0x0000ffff); | 323 | size = (u16) (header & 0x0000ffff); |
324 | 324 | ||
325 | if ((skb->len) - ((size + 1) & 0xfffe) == 0) | 325 | if ((skb->len) - ((size + 1) & 0xfffe) == 0) { |
326 | u8 alignment = (u32)skb->data & 0x3; | ||
327 | if (alignment != 0x2) { | ||
328 | /* | ||
329 | * not 16bit aligned so use the room provided by | ||
330 | * the 32 bit header to align the data | ||
331 | * | ||
332 | * note we want 16bit alignment as MAC header is | ||
333 | * 14bytes thus ip header will be aligned on | ||
334 | * 32bit boundary so accessing ipheader elements | ||
335 | * using a cast to struct ip header wont cause | ||
336 | * an unaligned accesses. | ||
337 | */ | ||
338 | u8 realignment = (alignment + 2) & 0x3; | ||
339 | memmove(skb->data - realignment, | ||
340 | skb->data, | ||
341 | size); | ||
342 | skb->data -= realignment; | ||
343 | skb_set_tail_pointer(skb, size); | ||
344 | } | ||
326 | return 2; | 345 | return 2; |
346 | } | ||
347 | |||
327 | if (size > ETH_FRAME_LEN) { | 348 | if (size > ETH_FRAME_LEN) { |
328 | netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", | 349 | netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", |
329 | size); | 350 | size); |
@@ -331,7 +352,18 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
331 | } | 352 | } |
332 | ax_skb = skb_clone(skb, GFP_ATOMIC); | 353 | ax_skb = skb_clone(skb, GFP_ATOMIC); |
333 | if (ax_skb) { | 354 | if (ax_skb) { |
355 | u8 alignment = (u32)packet & 0x3; | ||
334 | ax_skb->len = size; | 356 | ax_skb->len = size; |
357 | |||
358 | if (alignment != 0x2) { | ||
359 | /* | ||
360 | * not 16bit aligned use the room provided by | ||
361 | * the 32 bit header to align the data | ||
362 | */ | ||
363 | u8 realignment = (alignment + 2) & 0x3; | ||
364 | memmove(packet - realignment, packet, size); | ||
365 | packet -= realignment; | ||
366 | } | ||
335 | ax_skb->data = packet; | 367 | ax_skb->data = packet; |
336 | skb_set_tail_pointer(ax_skb, size); | 368 | skb_set_tail_pointer(ax_skb, size); |
337 | usbnet_skb_return(dev, ax_skb); | 369 | usbnet_skb_return(dev, ax_skb); |