Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

qmi_wwan: allow max_mtu above hard_mtu to control rx_urb_size

Commit c7159e960f14 ("usbnet: limit max_mtu based on device's hard_mtu")
capped net->max_mtu to the device's hard_mtu in usbnet_probe(). While
this correctly prevents oversized packets on standard USB network
devices, it breaks the qmi_wwan driver.

qmi_wwan relies on userspace (e.g. ModemManager) setting a large MTU on
the wwan0 interface to configure rx_urb_size via usbnet_change_mtu().
QMI modems negotiate USB transfer sizes of 16,383 or 32,767 bytes, and
the USB receive buffers must be sized accordingly. With max_mtu capped
to hard_mtu (~1500 bytes), userspace can no longer raise the MTU, the
receive buffers remain small, and download speeds drop from >300 Mbps
to ~0.8 Mbps.

Introduce a FLAG_NOMAXMTU driver flag that allows individual usbnet
drivers to opt out of the max_mtu cap. Set this flag in qmi_wwan's
driver_info structures to restore the previous behavior for QMI devices,
while keeping the safety fix in place for all other usbnet drivers.

Fixes: c7159e960f14 ("usbnet: limit max_mtu based on device's hard_mtu")
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/lkml/CAPh3n803k8JcBPV5qEzUB-oKzWkAs-D5CU7z=Vd_nLRCr5ZqQg@mail.gmail.com/
Reported-by: Koen Vandeputte <koen.vandeputte@citymesh.com>
Tested-by: Daniele Palmas <dnlplm@gmail.com>
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Link: https://patch.msgid.link/20260304134338.1785002-1-lvivier@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Laurent Vivier and committed by
Jakub Kicinski
55f854dd 03910cdc

+7 -5
+2 -2
drivers/net/usb/qmi_wwan.c
··· 928 928 929 929 static const struct driver_info qmi_wwan_info = { 930 930 .description = "WWAN/QMI device", 931 - .flags = FLAG_WWAN | FLAG_SEND_ZLP, 931 + .flags = FLAG_WWAN | FLAG_NOMAXMTU | FLAG_SEND_ZLP, 932 932 .bind = qmi_wwan_bind, 933 933 .unbind = qmi_wwan_unbind, 934 934 .manage_power = qmi_wwan_manage_power, ··· 937 937 938 938 static const struct driver_info qmi_wwan_info_quirk_dtr = { 939 939 .description = "WWAN/QMI device", 940 - .flags = FLAG_WWAN | FLAG_SEND_ZLP, 940 + .flags = FLAG_WWAN | FLAG_NOMAXMTU | FLAG_SEND_ZLP, 941 941 .bind = qmi_wwan_bind, 942 942 .unbind = qmi_wwan_unbind, 943 943 .manage_power = qmi_wwan_manage_power,
+4 -3
drivers/net/usb/usbnet.c
··· 1829 1829 if ((dev->driver_info->flags & FLAG_NOARP) != 0) 1830 1830 net->flags |= IFF_NOARP; 1831 1831 1832 - if (net->max_mtu > (dev->hard_mtu - net->hard_header_len)) 1832 + if ((dev->driver_info->flags & FLAG_NOMAXMTU) == 0 && 1833 + net->max_mtu > (dev->hard_mtu - net->hard_header_len)) 1833 1834 net->max_mtu = dev->hard_mtu - net->hard_header_len; 1834 1835 1835 - if (net->mtu > net->max_mtu) 1836 - net->mtu = net->max_mtu; 1836 + if (net->mtu > (dev->hard_mtu - net->hard_header_len)) 1837 + net->mtu = dev->hard_mtu - net->hard_header_len; 1837 1838 1838 1839 } else if (!info->in || !info->out) 1839 1840 status = usbnet_get_endpoints(dev, udev);
+1
include/linux/usb/usbnet.h
··· 132 132 #define FLAG_MULTI_PACKET 0x2000 133 133 #define FLAG_RX_ASSEMBLE 0x4000 /* rx packets may span >1 frames */ 134 134 #define FLAG_NOARP 0x8000 /* device can't do ARP */ 135 + #define FLAG_NOMAXMTU 0x10000 /* allow max_mtu above hard_mtu */ 135 136 136 137 /* init device ... can sleep, or cause probe() failure */ 137 138 int (*bind)(struct usbnet *, struct usb_interface *);