This patch add a hook to check the port init status. Currently, only usbcore knows port init status even if the result is bad. It will cause a USB host keep doing USB enumeration for a long time when the USB host connects to a broken USB accessory. The hc_driver could use the hook to know port init status and do possible error handling according to platform requirements or limitations. Signed-off-by: Ray Chi <raychi@xxxxxxxxxx> --- drivers/usb/core/hub.c | 14 ++++++++++++++ include/linux/usb/hcd.h | 8 ++++++++ 2 files changed, 22 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 2633acde7ac1..6ce6092816cb 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4659,6 +4659,16 @@ static int hub_enable_device(struct usb_device *udev) return hcd->driver->enable_device(hcd, udev); } +static int hub_port_check_init_status(struct usb_device *udev, int r) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (!hcd->driver->check_init_status) + return 0; + + return hcd->driver->check_init_status(hcd, udev, r); +} + /* Reset device, (re)assign address, get device descriptor. * Device connection must be stable, no more debouncing needed. * Returns device in USB_STATE_ADDRESS, except on error. @@ -4855,6 +4865,10 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, buf->bMaxPacketSize0; kfree(buf); + retval = hub_port_check_init_status(udev, r); + if (retval < 0) + goto fail; + retval = hub_port_reset(hub, port1, udev, delay, false); if (retval < 0) /* error or disconnect */ goto fail; diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 67f8713d3fa3..8fa30b4a6b7d 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -297,6 +297,14 @@ struct hc_driver { gfp_t mem_flags); void (*unmap_urb_for_dma)(struct usb_hcd *hcd, struct urb *urb); + /* + * (optional) HCD could get the information of GET_DESCRIPTOR by this hook. + * In general, it is not necessary unless the enumeration takes long + * time to do. The host controller could know the enumeration status by + * this hook and do some error handlings. + */ + int (*check_init_status)(struct usb_hcd *hcd, struct usb_device *udev, int r); + /* hw synch, freeing endpoint resources that urb_dequeue can't */ void (*endpoint_disable)(struct usb_hcd *hcd, struct usb_host_endpoint *ep); -- 2.37.1.595.g718a3a8f04-goog