aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2017-12-06 14:21:24 -0500
committerDavid S. Miller <davem@davemloft.net>2017-12-07 14:32:30 -0500
commita4abd7a80addb4a9547f7dfc7812566b60ec505c (patch)
tree2e12cda983f7c8c7c0ffe64e5ed65759b7263a54
parent8632385022f2b05a6ca0b9e0f95575865de0e2ce (diff)
usbnet: fix alignment for frames with no ethernet header
The qmi_wwan minidriver support a 'raw-ip' mode where frames are received without any ethernet header. This causes alignment issues because the skbs allocated by usbnet are "IP aligned". Fix by allowing minidrivers to disable the additional alignment offset. This is implemented using a per-device flag, since the same minidriver also supports 'ethernet' mode. Fixes: 32f7adf633b9 ("net: qmi_wwan: support "raw IP" mode") Reported-and-tested-by: Jay Foster <jay@systech.com> Signed-off-by: Bjørn Mork <bjorn@mork.no> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/usb/qmi_wwan.c2
-rw-r--r--drivers/net/usb/usbnet.c5
-rw-r--r--include/linux/usb/usbnet.h1
3 files changed, 7 insertions, 1 deletions
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index c750cf7c042b..304ec6555cd8 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -261,9 +261,11 @@ static void qmi_wwan_netdev_setup(struct net_device *net)
261 net->hard_header_len = 0; 261 net->hard_header_len = 0;
262 net->addr_len = 0; 262 net->addr_len = 0;
263 net->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; 263 net->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
264 set_bit(EVENT_NO_IP_ALIGN, &dev->flags);
264 netdev_dbg(net, "mode: raw IP\n"); 265 netdev_dbg(net, "mode: raw IP\n");
265 } else if (!net->header_ops) { /* don't bother if already set */ 266 } else if (!net->header_ops) { /* don't bother if already set */
266 ether_setup(net); 267 ether_setup(net);
268 clear_bit(EVENT_NO_IP_ALIGN, &dev->flags);
267 netdev_dbg(net, "mode: Ethernet\n"); 269 netdev_dbg(net, "mode: Ethernet\n");
268 } 270 }
269 271
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 80348b6a8646..d56fe32bf48d 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -484,7 +484,10 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
484 return -ENOLINK; 484 return -ENOLINK;
485 } 485 }
486 486
487 skb = __netdev_alloc_skb_ip_align(dev->net, size, flags); 487 if (test_bit(EVENT_NO_IP_ALIGN, &dev->flags))
488 skb = __netdev_alloc_skb(dev->net, size, flags);
489 else
490 skb = __netdev_alloc_skb_ip_align(dev->net, size, flags);
488 if (!skb) { 491 if (!skb) {
489 netif_dbg(dev, rx_err, dev->net, "no rx skb\n"); 492 netif_dbg(dev, rx_err, dev->net, "no rx skb\n");
490 usbnet_defer_kevent (dev, EVENT_RX_MEMORY); 493 usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index a69877734c4e..e2ec3582e549 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -82,6 +82,7 @@ struct usbnet {
82# define EVENT_RX_KILL 10 82# define EVENT_RX_KILL 10
83# define EVENT_LINK_CHANGE 11 83# define EVENT_LINK_CHANGE 11
84# define EVENT_SET_RX_MODE 12 84# define EVENT_SET_RX_MODE 12
85# define EVENT_NO_IP_ALIGN 13
85}; 86};
86 87
87static inline struct usb_driver *driver_of(struct usb_interface *intf) 88static inline struct usb_driver *driver_of(struct usb_interface *intf)