Re: commit 662dc80a5e86 breaks rmnet over usb

From: Daniele Palmas

Date: Wed Feb 25 2026 - 09:37:04 EST


Hello Laurent,

Il giorno mer 25 feb 2026 alle ore 12:04 Laurent Vivier
<lvivier@xxxxxxxxxx> ha scritto:
>
> On 2/25/26 08:48, Laurent Vivier wrote:
> > On 2/25/26 08:19, Daniele Palmas wrote:
> >> Hello,
> >
> > Hello Daniele,
> >
> >>
> >> Il giorno lun 23 feb 2026 alle ore 15:08 Laurent Vivier
> >> <lvivier@xxxxxxxxxx> ha scritto:
> >>>
> >>> On 2/23/26 13:04, Koen Vandeputte wrote:
> >>>> Hi Laurent,
> >>>
> >>> Hi Koen,
> >>>
> >>>> I'm testing the latest openwrt state and found an issue probably
> >>>> caused by your usb mtu limit patch :-)
> >>>>
> >>>> I'm talking about this one:
> >>>> 662dc80a5e86 ("usbnet: limit max_mtu based on device's hard_mtu")
> >>>>
> >>>> https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?
> >>>> h=v6.12.74&id=662dc80a5e86b35bbf339e0b87b7cc3f07c09de1
> >>>>
> >>>>
> >>>> When using wwan0 iface normally, this makes sense, but the problem is
> >>>> when using QMI modems combined with the rmnet driver and aggregated
> >>>> frames.
> >>>>
> >>>> - The modem is configured to frame sizes of 16383 or 32767 using QMI
> >>>> - wwan0 (using qmi_wwan) is configured to match this frame size by
> >>>> setting it's MTU to the same value
> >>>> - Frames of this size are sent over to qmi_wwan driver (containing
> >>>> multiple data packets)
> >>>> - Frames are then forwarded to the rmnet driver
> >>>> - Frames get de-aggregated here and sent to the network stack for processing.
> >>>>
> >>>> The reason here is to reduce USB transfers heavily.
> >>>>
> >>>>
> >>>> As you see, it's perfectly possible here to use very large MTU sizes
> >>>> as the aggregation feature by rmnet relies on this.
> >>>> Also the modem can be perfectly configured to send very large aggregated frames.
> >>>>
> >>>> After your patch, wwan0 is limited to 1500 bytes it seems, effectively
> >>>> breaking aggregation.
> >>>>
> >>>> On my tests, download speeds are reduced from >300Mbps to ~.8Mbps
> >>>>
> >>>> I also made a build reverting this patch and all works well again.
> >>>>
> >>>>
> >>>> Is there any other solution to fix this?
> >>>> I guess it should be reverted otherwise :-)
> >>>
> >>> It's weird to be able to set an MTU that is not supported by the hardware.
> >>>
> >>> To restore performance I think the rx_usb_size should be decoupled from MTU max in
> >>> qmi_wwan.
> >>>
> >>> Could you try something like:
> >>>
> >>> diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
> >>> index 3a4985b582cb..6b4796fac692 100644
> >>> --- a/drivers/net/usb/qmi_wwan.c
> >>> +++ b/drivers/net/usb/qmi_wwan.c
> >>> @@ -788,6 +788,8 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface
> >>> *intf)
> >>> usbnet_get_ethernet_addr(dev, cdc_ether->iMACAddress);
> >>> }
> >>>
> >>> + dev->rx_urb_size = 32768;
> >>> +
> >>
> >> So far userspace tools (e.g. also the most important one which is
> >> ModemManager) rely on changing the rx_urb_size by changing the MTU: I
> >> know this is ugly, but it is a behavior that has been there since a
> >> lot of time, not sure how many tools based on this assumption could
> >> break.
> >>
> >> There's also the chance that there are modems which require a higher
> >> rx_urb_size, so having this fixed could not work well.
> >>
> >> Unfortunately usbnet serves many drivers, I agree with Koen that a
> >> revert is the safest option.
> >
> > And there is no intermediate driver (qmi_wwan or rmnet) that can define a max_mtu higher
> > than that defined by usbnet?
>
> Perhaps we can remove the change from usbnet and move it to the device bind function?
>
> diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
> index a032c1ded406..836915e4abad 100644
> --- a/drivers/net/usb/cdc_ether.c
> +++ b/drivers/net/usb/cdc_ether.c
> @@ -235,6 +235,8 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface
> *intf)
>
> if (header.usb_cdc_ether_desc && info->ether->wMaxSegmentSize) {
> dev->hard_mtu = le16_to_cpu(info->ether->wMaxSegmentSize);
> + if (dev->net->max_mtu > (dev->hard_mtu - dev->net->hard_header_len))
> + dev->net->max_mtu = dev->hard_mtu - dev->net->hard_header_len;
> /* because of Zaurus, we may be ignoring the host
> * side link address we were given.
> */
> diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
> index ed86ba87ca4e..295c3614878b 100644
> --- a/drivers/net/usb/usbnet.c
> +++ b/drivers/net/usb/usbnet.c
> @@ -1829,11 +1829,9 @@ 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))
> - net->max_mtu = dev->hard_mtu - net->hard_header_len;
> -
> - if (net->mtu > net->max_mtu)
> - net->mtu = net->max_mtu;
> + /* maybe the remote can't receive an Ethernet 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);
>
> An other solution would be to add a FLAG_NOMAXMTU in qmi_wwan driver_info->flags to
> disable the setting of max_mtu in usbnet_probe() to keep the change generic and qmi_wwan
> the exception.
>

Both solutions look good to me.

If you think that your change provides benefit to other usbnet users,
then keeping qmi_wwan the exception is probably better.

Thanks,
Daniele

> Thanks,
> Laurent
>