[PATCH v4 2/2] usb: misc: onboard_usb_dev: don't defer probing after the device is configured
From: James Clark
Date: Fri Nov 06 2026 - 01:18:37 EST
onboard_usb_dev breaks the rule that a driver must not return
-EPROBE_DEFER from its probe after it has registered child devices,
because that causes a probe loop (see commit fbc35b45f9f6 ("Add
documentation on meaning of -EPROBE_DEFER")). Its USB device driver
sets generic_subclass, so the generic probe runs first and registers
the device's interfaces. onboard_dev_usbdev_probe() then returns
-EPROBE_DEFER until the platform device for the onboard device has
probed. On a BeagleY-AI, the resulting loop has broken booting since
commit f918e3804498 ("arm64: enable HAVE_SHARED_GPIOS for all ARM64
platforms").
Call the generic driver's operations from the driver itself instead of
relying on generic_subclass.
When the device's node has neither a platform device nor a peer hub,
return -ENODEV instead of -EINVAL, so that the device is still
configured. The device now stays unconfigured while the probe is
deferred.
Fixes: 8bc063641ceb ("usb: misc: Add onboard_usb_hub driver")
Suggested-by: Johan Hovold <johan@xxxxxxxxxx>
Signed-off-by: James Clark <jjc@xxxxxxxxxx>
---
drivers/usb/misc/onboard_usb_dev.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/misc/onboard_usb_dev.c b/drivers/usb/misc/onboard_usb_dev.c
index c60406240416..51985e3473ad 100644
--- a/drivers/usb/misc/onboard_usb_dev.c
+++ b/drivers/usb/misc/onboard_usb_dev.c
@@ -591,7 +591,7 @@ static struct onboard_dev *_find_onboard_dev(struct device *dev)
np = of_parse_phandle(dev->of_node, "peer-hub", 0);
if (!np) {
dev_err(dev, "failed to find device node for peer hub\n");
- return ERR_PTR(-EINVAL);
+ return ERR_PTR(-ENODEV);
}
pdev = of_find_device_by_node(np);
@@ -639,7 +639,11 @@ static int onboard_dev_usbdev_probe(struct usb_device *udev)
if (err)
return err;
- return 0;
+ err = usb_generic_driver_probe(udev);
+ if (err)
+ onboard_dev_remove_usbdev(onboard_dev, udev);
+
+ return err;
}
static void onboard_dev_usbdev_disconnect(struct usb_device *udev)
@@ -647,6 +651,7 @@ static void onboard_dev_usbdev_disconnect(struct usb_device *udev)
struct onboard_dev *onboard_dev = dev_get_drvdata(&udev->dev);
onboard_dev_remove_usbdev(onboard_dev, udev);
+ usb_generic_driver_disconnect(udev);
}
static const struct usb_device_id onboard_dev_id_table[] = {
@@ -697,7 +702,10 @@ static struct usb_device_driver onboard_dev_usbdev_driver = {
.match = onboard_dev_usbdev_match,
.probe = onboard_dev_usbdev_probe,
.disconnect = onboard_dev_usbdev_disconnect,
- .generic_subclass = 1,
+#ifdef CONFIG_PM
+ .suspend = usb_generic_driver_suspend,
+ .resume = usb_generic_driver_resume,
+#endif
.supports_autosuspend = 1,
.id_table = onboard_dev_id_table,
};
--
2.56.0