Skip to content

Commit 55f854d

Browse files
vivierkuba-moo
authored andcommitted
qmi_wwan: allow max_mtu above hard_mtu to control rx_urb_size
Commit c7159e9 ("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: c7159e9 ("usbnet: limit max_mtu based on device's hard_mtu") Cc: [email protected] Link: https://lore.kernel.org/lkml/CAPh3n803k8JcBPV5qEzUB-oKzWkAs-D5CU7z=Vd_nLRCr5ZqQg@mail.gmail.com/ Reported-by: Koen Vandeputte <[email protected]> Tested-by: Daniele Palmas <[email protected]> Signed-off-by: Laurent Vivier <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 03910cd commit 55f854d

3 files changed

Lines changed: 7 additions & 5 deletions

File tree

drivers/net/usb/qmi_wwan.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -928,7 +928,7 @@ static int qmi_wwan_resume(struct usb_interface *intf)
928928

929929
static const struct driver_info qmi_wwan_info = {
930930
.description = "WWAN/QMI device",
931-
.flags = FLAG_WWAN | FLAG_SEND_ZLP,
931+
.flags = FLAG_WWAN | FLAG_NOMAXMTU | FLAG_SEND_ZLP,
932932
.bind = qmi_wwan_bind,
933933
.unbind = qmi_wwan_unbind,
934934
.manage_power = qmi_wwan_manage_power,
@@ -937,7 +937,7 @@ static const struct driver_info qmi_wwan_info = {
937937

938938
static const struct driver_info qmi_wwan_info_quirk_dtr = {
939939
.description = "WWAN/QMI device",
940-
.flags = FLAG_WWAN | FLAG_SEND_ZLP,
940+
.flags = FLAG_WWAN | FLAG_NOMAXMTU | FLAG_SEND_ZLP,
941941
.bind = qmi_wwan_bind,
942942
.unbind = qmi_wwan_unbind,
943943
.manage_power = qmi_wwan_manage_power,

drivers/net/usb/usbnet.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,11 +1829,12 @@ usbnet_probe(struct usb_interface *udev, const struct usb_device_id *prod)
18291829
if ((dev->driver_info->flags & FLAG_NOARP) != 0)
18301830
net->flags |= IFF_NOARP;
18311831

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))
18331834
net->max_mtu = dev->hard_mtu - net->hard_header_len;
18341835

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;
18371838

18381839
} else if (!info->in || !info->out)
18391840
status = usbnet_get_endpoints(dev, udev);

include/linux/usb/usbnet.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ struct driver_info {
132132
#define FLAG_MULTI_PACKET 0x2000
133133
#define FLAG_RX_ASSEMBLE 0x4000 /* rx packets may span >1 frames */
134134
#define FLAG_NOARP 0x8000 /* device can't do ARP */
135+
#define FLAG_NOMAXMTU 0x10000 /* allow max_mtu above hard_mtu */
135136

136137
/* init device ... can sleep, or cause probe() failure */
137138
int (*bind)(struct usbnet *, struct usb_interface *);

0 commit comments

Comments
 (0)