Re: [PATCH v2] usb: core: clear both ep_in and ep_out for non-ep0 control endpoints

From: Alan Stern

Date: Sun Sep 20 2026 - 20:22:15 EST


On Sun, Sep 20, 2026 at 11:17:02PM +0000, Hui Peng wrote:
> In usb_enable_endpoint(), non-zero control endpoints (where
> usb_endpoint_xfer_control(&ep->desc) is true) populate both
> dev->ep_in[epnum] and dev->ep_out[epnum] with the same
> struct usb_host_endpoint pointer.
>
> However, usb_disable_endpoint() only clears either dev->ep_out[epnum]
> or dev->ep_in[epnum] depending on the direction bit of epaddr when
> reset_hardware is set, leaving the opposite direction's array slot
> pointing to the disabled/freed endpoint.
>
> Clear both dev->ep_out[epnum] and dev->ep_in[epnum] when disabling a
> non-ep0 control endpoint with reset_hardware set, and update the
> function kerneldoc accordingly.
>
> Tested in QEMU against Linux 7.3.0-rc3 using dummy_hcd and raw-gadget to
> enumerate a USB device with a non-zero control endpoint (bEndpointAddress
> 0x01, bmAttributes USB_ENDPOINT_XFER_CONTROL), verifying that both
> dev->ep_in[1] and dev->ep_out[1] are cleared when the interface is
> disabled.
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Cc: stable@xxxxxxxxxxxxxxx
> Assisted-by: LLM
> Signed-off-by: Hui Peng <benquike@xxxxxxxxx>
> ---
> Changes in v2:
> - Dropped all changes in the other files (config.c, hub.c, port.c,
> devio.c, sysfs.c, and ledtrig-usbport.c) per Alan Stern and Greg
> Kroah-Hartman, keeping only the usb_disable_endpoint() fix in
> drivers/usb/core/message.c.
> - Updated the usb_disable_endpoint() kerneldoc comment and commit
> description per Alan Stern.

Acked-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>

You might consider looking through other parts of the code to see if
they need similar attention. Historically we haven't been very good
about supporting control endpoints other than ep0.

Alan Stern

> drivers/usb/core/message.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
> index 75e2bfd744a9..0cd6dd2b6334 100644
> --- a/drivers/usb/core/message.c
> +++ b/drivers/usb/core/message.c
> @@ -1337,7 +1337,8 @@ static void remove_intf_ep_devs(struct usb_interface *intf)
> *
> * Disables the endpoint for URB submission and nukes all pending URBs.
> * If @reset_hardware is set then also deallocates hcd/hardware state
> - * for the endpoint.
> + * for the endpoint (clearing both ep_in and ep_out pointers for
> + * bidirectional non-ep0 control endpoints).
> */
> void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr,
> bool reset_hardware)
> @@ -1358,6 +1359,11 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr,
> dev->ep_in[epnum] = NULL;
> }
> if (ep) {
> + if (reset_hardware && epnum != 0 &&
> + usb_endpoint_xfer_control(&ep->desc)) {
> + dev->ep_out[epnum] = NULL;
> + dev->ep_in[epnum] = NULL;
> + }
> ep->enabled = 0;
> usb_hcd_flush_endpoint(dev, ep);
> if (reset_hardware)
> --
> 2.47.3