From 8e43062ef964e9d0bdafddff69f04620e65beca8 Mon Sep 17 00:00:00 2001 From: Neil Jones Date: Mon, 17 May 2010 17:18:28 -0700 Subject: [PATCH] --- yaml --- r: 195143 b: refs/heads/master c: 3f78d1f210ff89af77f042ab7f4a8fee39feb1c9 h: refs/heads/master i: 195141: b2305e9fd7d9e5bb7e54c079b629605b0fabfcbf 195139: dd112f0a6ec4310f39d57c5f8d79e68d93b5671c 195135: 2a1d4c3a66fcff28557323e19c30ec1ab86f9dd6 v: v3 --- [refs] | 2 +- trunk/drivers/net/usb/asix.c | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index de59ab582bc1..9f6bae87817f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: e7a3af5d8cd782b84e6ca4e4dcc8613be1a809f0 +refs/heads/master: 3f78d1f210ff89af77f042ab7f4a8fee39feb1c9 diff --git a/trunk/drivers/net/usb/asix.c b/trunk/drivers/net/usb/asix.c index 8e7d2374558b..66c5e89326c1 100644 --- a/trunk/drivers/net/usb/asix.c +++ b/trunk/drivers/net/usb/asix.c @@ -322,8 +322,29 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) /* get the packet length */ size = (u16) (header & 0x0000ffff); - if ((skb->len) - ((size + 1) & 0xfffe) == 0) + if ((skb->len) - ((size + 1) & 0xfffe) == 0) { + u8 alignment = (u32)skb->data & 0x3; + if (alignment != 0x2) { + /* + * not 16bit aligned so use the room provided by + * the 32 bit header to align the data + * + * note we want 16bit alignment as MAC header is + * 14bytes thus ip header will be aligned on + * 32bit boundary so accessing ipheader elements + * using a cast to struct ip header wont cause + * an unaligned accesses. + */ + u8 realignment = (alignment + 2) & 0x3; + memmove(skb->data - realignment, + skb->data, + size); + skb->data -= realignment; + skb_set_tail_pointer(skb, size); + } return 2; + } + if (size > ETH_FRAME_LEN) { netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", size); @@ -331,7 +352,18 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) } ax_skb = skb_clone(skb, GFP_ATOMIC); if (ax_skb) { + u8 alignment = (u32)packet & 0x3; ax_skb->len = size; + + if (alignment != 0x2) { + /* + * not 16bit aligned use the room provided by + * the 32 bit header to align the data + */ + u8 realignment = (alignment + 2) & 0x3; + memmove(packet - realignment, packet, size); + packet -= realignment; + } ax_skb->data = packet; skb_set_tail_pointer(ax_skb, size); usbnet_skb_return(dev, ax_skb);