099-0004-usbnet-fix-alignment-for-frames-with-no-ethernet-hea.patch 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. From a4abd7a80addb4a9547f7dfc7812566b60ec505c Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
  3. Date: Wed, 6 Dec 2017 20:21:24 +0100
  4. Subject: [PATCH] usbnet: fix alignment for frames with no ethernet header
  5. MIME-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. The qmi_wwan minidriver support a 'raw-ip' mode where frames are
  9. received without any ethernet header. This causes alignment issues
  10. because the skbs allocated by usbnet are "IP aligned".
  11. Fix by allowing minidrivers to disable the additional alignment
  12. offset. This is implemented using a per-device flag, since the same
  13. minidriver also supports 'ethernet' mode.
  14. Fixes: 32f7adf633b9 ("net: qmi_wwan: support "raw IP" mode")
  15. Reported-and-tested-by: Jay Foster <jay@systech.com>
  16. Signed-off-by: Bjørn Mork <bjorn@mork.no>
  17. Signed-off-by: David S. Miller <davem@davemloft.net>
  18. ---
  19. drivers/net/usb/qmi_wwan.c | 2 ++
  20. drivers/net/usb/usbnet.c | 5 ++++-
  21. include/linux/usb/usbnet.h | 1 +
  22. 3 files changed, 7 insertions(+), 1 deletion(-)
  23. --- a/drivers/net/usb/qmi_wwan.c
  24. +++ b/drivers/net/usb/qmi_wwan.c
  25. @@ -70,9 +70,11 @@ static void qmi_wwan_netdev_setup(struct
  26. net->hard_header_len = 0;
  27. net->addr_len = 0;
  28. net->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
  29. + set_bit(EVENT_NO_IP_ALIGN, &dev->flags);
  30. netdev_dbg(net, "mode: raw IP\n");
  31. } else if (!net->header_ops) { /* don't bother if already set */
  32. ether_setup(net);
  33. + clear_bit(EVENT_NO_IP_ALIGN, &dev->flags);
  34. netdev_dbg(net, "mode: Ethernet\n");
  35. }
  36. --- a/drivers/net/usb/usbnet.c
  37. +++ b/drivers/net/usb/usbnet.c
  38. @@ -482,7 +482,10 @@ static int rx_submit (struct usbnet *dev
  39. return -ENOLINK;
  40. }
  41. - skb = __netdev_alloc_skb_ip_align(dev->net, size, flags);
  42. + if (test_bit(EVENT_NO_IP_ALIGN, &dev->flags))
  43. + skb = __netdev_alloc_skb(dev->net, size, flags);
  44. + else
  45. + skb = __netdev_alloc_skb_ip_align(dev->net, size, flags);
  46. if (!skb) {
  47. netif_dbg(dev, rx_err, dev->net, "no rx skb\n");
  48. usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
  49. --- a/include/linux/usb/usbnet.h
  50. +++ b/include/linux/usb/usbnet.h
  51. @@ -79,6 +79,7 @@ struct usbnet {
  52. # define EVENT_RX_KILL 10
  53. # define EVENT_LINK_CHANGE 11
  54. # define EVENT_SET_RX_MODE 12
  55. +# define EVENT_NO_IP_ALIGN 13
  56. };
  57. static inline struct usb_driver *driver_of(struct usb_interface *intf)