From: sashiko-bot@kernel.org
To: "James Clark" <jjc@jclark.com>
Cc: linux-usb@vger.kernel.org, linux-gpio@vger.kernel.org
Subject: Re: [PATCH v2] usb: core: add a pre_probe callback for device drivers that may defer
Date: Fri, 30 Oct 2026 15:41:34 +0000 [thread overview]
Message-ID: <sashiko-outbox-191184@kernel.org> (raw)
In-Reply-To: <20261030151919.3511106-1-jjc@jclark.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] usb: core: missing generic and runtime PM cleanup in usb_probe_device()
--
commit c4ba8a98e9f819e5526aef5f1c45cb74910c09c6
Author: James Clark <jjc@jclark.com>
usb: core: add a pre_probe callback for device drivers that may defer
This commit adds a pre_probe callback to struct usb_device_driver so that
device drivers with generic_subclass set can defer probing before
usb_generic_driver_probe() configures the device and binds its interfaces.
It also converts onboard_usb_dev to use pre_probe to avoid a re-probe loop
when the companion platform device has not finished probing.
> diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
> index d3a61ebc6afb0..724cfa9da4e01 100644
> --- a/drivers/usb/core/driver.c
> +++ b/drivers/usb/core/driver.c
> @@ -249,24 +249,41 @@ static int usb_probe_device(struct device *dev)
> {
> struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
> struct usb_device *udev = to_usb_device(dev);
> - int error = 0;
> + int error = 0, pre_error = 0;
>
> dev_dbg(dev, "%s\n", __func__);
>
> /* TODO: Add real matching code */
>
> + /*
> + * Give the driver a chance to defer before anything is done to the
> + * device. The generic probe below binds the interface drivers, and
> + * each binding triggers deferred probing, so a probe that deferred
> + * after it would be retried straight away and the device re-probed
> + * in a loop.
> + *
> + * Any other error from pre_probe() is not acted on until the generic
> + * probe has run, so that the -ENODEV fallback below works as it does
> + * for probe().
> + */
> + if (udriver->pre_probe) {
> + pre_error = udriver->pre_probe(udev);
> + if (pre_error == -EPROBE_DEFER)
> + return pre_error;
> + }
> +
> /* The device should always appear to be in use
> * unless the driver supports autosuspend.
> */
> if (!udriver->supports_autosuspend)
> error = usb_autoresume_device(udev);
> if (error)
> - return error;
> + goto err_pre_probe;
>
> if (udriver->generic_subclass)
> error = usb_generic_driver_probe(udev);
> if (error)
> - return error;
> + goto err_pre_probe;
>
> /* Probe the USB device with the driver in hand, but only
> * defer to a generic driver in case the current USB
> @@ -289,15 +306,26 @@ static int usb_probe_device(struct device *dev)
> * specialised device drivers prior to setting the
> * use_generic_driver bit.
> */
> - if (udriver->probe)
> + if (pre_error)
> + error = pre_error;
> + else if (udriver->probe)
> error = udriver->probe(udev);
> else if (!udriver->generic_subclass)
> error = -EINVAL;
> if (error == -ENODEV && udriver != &usb_generic_driver &&
> (udriver->id_table || udriver->match)) {
> udev->use_generic_driver = 1;
> - return -EPROBE_DEFER;
> + error = -EPROBE_DEFER;
> }
> + if (error)
> + goto err_pre_probe;
> +
> + return 0;
> +
> +err_pre_probe:
> + /* The driver core doesn't call disconnect() for a failed probe. */
> + if (udriver->pre_probe && !pre_error && udriver->disconnect)
> + udriver->disconnect(udev);
> return error;
> }
[Severity: Medium]
When udriver->pre_probe(udev) returns a non-deferral error (for example,
-EINVAL or -ENOMEM from onboard_dev_usbdev_pre_probe() when
_find_onboard_dev() or onboard_dev_add_usbdev() fails), or when pre_probe()
succeeds and udriver->probe(udev) fails, usb_probe_device() runs
usb_autoresume_device(udev) and usb_generic_driver_probe(udev) before jumping
to err_pre_probe.
However, err_pre_probe only invokes udriver->disconnect(udev) and does not
undo usb_generic_driver_probe(udev) or usb_autoresume_device(udev) the way
usb_unbind_device() does:
drivers/usb/core/driver.c:usb_unbind_device() {
if (udriver->disconnect)
udriver->disconnect(udev);
if (udriver->generic_subclass)
usb_generic_driver_disconnect(udev);
if (!udriver->supports_autosuspend)
usb_autosuspend_device(udev);
}
Because the driver core does not call usb_unbind_device() when
usb_probe_device() fails, doesn't a non-deferral failure leave udev unbound
(udev->dev.driver == NULL) while still configured with bound child
interfaces, an unbalanced runtime PM usage count when !supports_autosuspend,
and a sent USB_DEVICE_ADD notification that will never be paired with
USB_DEVICE_REMOVE on unplug (leaking struct usbport_trig_port and sysfs
attributes in usbport_trig_notify())?
Similarly, on the -ENODEV fallback path where udev->use_generic_driver is set
to 1 and usb_probe_device() returns -EPROBE_DEFER, won't leaving
usb_generic_driver_probe(udev) and usb_autoresume_device(udev) in place cause
the subsequent usb_generic_driver probe to call usb_generic_driver_probe() a
second time and emit a duplicate USB_DEVICE_ADD notification without an
intervening USB_DEVICE_REMOVE?
Should pre_probe() handle the -ENODEV fallback and return immediately on any
error before touching the device, and should the error path after
usb_generic_driver_probe() and usb_autoresume_device() also unwind them via
usb_generic_driver_disconnect() and usb_autosuspend_device()?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261030151919.3511106-1-jjc@jclark.com?part=1
next prev parent reply other threads:[~2026-10-30 15:41 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-30 15:19 [PATCH v2] usb: core: add a pre_probe callback for device drivers that may defer James Clark
2026-10-30 15:41 ` sashiko-bot [this message]
2026-10-31 3:24 ` James Clark
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-191184@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=jjc@jclark.com \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.