* [PATCH v2] qmi_wwan: allow max_mtu above hard_mtu to control rx_urb_size
@ 2026-03-04 13:43 Laurent Vivier
2026-03-07 0:50 ` patchwork-bot+netdevbpf
0 siblings, 1 reply; 2+ messages in thread
From: Laurent Vivier @ 2026-03-04 13:43 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Koen Vandeputte, Daniele Palmas, linux-kernel, Stefano Brivio,
linux-usb, netdev, Laurent Vivier, stable
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>
---
Notes:
v2: Add cc: to stable and Link:
drivers/net/usb/qmi_wwan.c | 4 ++--
drivers/net/usb/usbnet.c | 7 ++++---
include/linux/usb/usbnet.h | 1 +
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 3a4985b582cb..05acac10cd2b 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -928,7 +928,7 @@ static int qmi_wwan_resume(struct usb_interface *intf)
static const struct driver_info qmi_wwan_info = {
.description = "WWAN/QMI device",
- .flags = FLAG_WWAN | FLAG_SEND_ZLP,
+ .flags = FLAG_WWAN | FLAG_NOMAXMTU | FLAG_SEND_ZLP,
.bind = qmi_wwan_bind,
.unbind = qmi_wwan_unbind,
.manage_power = qmi_wwan_manage_power,
@@ -937,7 +937,7 @@ static const struct driver_info qmi_wwan_info = {
static const struct driver_info qmi_wwan_info_quirk_dtr = {
.description = "WWAN/QMI device",
- .flags = FLAG_WWAN | FLAG_SEND_ZLP,
+ .flags = FLAG_WWAN | FLAG_NOMAXMTU | FLAG_SEND_ZLP,
.bind = qmi_wwan_bind,
.unbind = qmi_wwan_unbind,
.manage_power = qmi_wwan_manage_power,
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index ed86ba87ca4e..b72ba0803392 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1829,11 +1829,12 @@ usbnet_probe(struct usb_interface *udev, const struct usb_device_id *prod)
if ((dev->driver_info->flags & FLAG_NOARP) != 0)
net->flags |= IFF_NOARP;
- if (net->max_mtu > (dev->hard_mtu - net->hard_header_len))
+ if ((dev->driver_info->flags & FLAG_NOMAXMTU) == 0 &&
+ net->max_mtu > (dev->hard_mtu - net->hard_header_len))
net->max_mtu = dev->hard_mtu - net->hard_header_len;
- if (net->mtu > net->max_mtu)
- net->mtu = net->max_mtu;
+ if (net->mtu > (dev->hard_mtu - net->hard_header_len))
+ net->mtu = dev->hard_mtu - net->hard_header_len;
} else if (!info->in || !info->out)
status = usbnet_get_endpoints(dev, udev);
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index b0e84896e6ac..bbf799ccf3b3 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -132,6 +132,7 @@ struct driver_info {
#define FLAG_MULTI_PACKET 0x2000
#define FLAG_RX_ASSEMBLE 0x4000 /* rx packets may span >1 frames */
#define FLAG_NOARP 0x8000 /* device can't do ARP */
+#define FLAG_NOMAXMTU 0x10000 /* allow max_mtu above hard_mtu */
/* init device ... can sleep, or cause probe() failure */
int (*bind)(struct usbnet *, struct usb_interface *);
--
2.53.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v2] qmi_wwan: allow max_mtu above hard_mtu to control rx_urb_size
2026-03-04 13:43 [PATCH v2] qmi_wwan: allow max_mtu above hard_mtu to control rx_urb_size Laurent Vivier
@ 2026-03-07 0:50 ` patchwork-bot+netdevbpf
0 siblings, 0 replies; 2+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-03-07 0:50 UTC (permalink / raw)
To: Laurent Vivier
Cc: kuba, koen.vandeputte, dnlplm, linux-kernel, sbrivio, linux-usb,
netdev, stable
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 4 Mar 2026 14:43:38 +0100 you wrote:
> 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.
>
> [...]
Here is the summary with links:
- [v2] qmi_wwan: allow max_mtu above hard_mtu to control rx_urb_size
https://git.kernel.org/netdev/net/c/55f854dd5bdd
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-03-07 0:50 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-04 13:43 [PATCH v2] qmi_wwan: allow max_mtu above hard_mtu to control rx_urb_size Laurent Vivier
2026-03-07 0:50 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox