[PATCH 1/2] usb: core: add a hook to check port init status

From: Ray Chi
Date: Tue Aug 16 2022 - 05:55:47 EST


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