5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ricardo Ribalda ribalda@chromium.org
commit 387e8939307192d5a852a2afeeb83427fa477151 upstream.
uvc_gpio_parse() can return -EPROBE_DEFER when the GPIOs it depends on have not yet been probed. This return code should be propagated to the caller of uvc_probe() to ensure that probing is retried when the required GPIOs become available.
Currently, this error code is incorrectly converted to -ENODEV, causing some internal cameras to be ignored.
This commit fixes this issue by propagating the -EPROBE_DEFER error.
Cc: stable@vger.kernel.org Fixes: 2886477ff987 ("media: uvcvideo: Implement UVC_EXT_GPIO_UNIT") Reviewed-by: Douglas Anderson dianders@chromium.org Signed-off-by: Ricardo Ribalda ribalda@chromium.org Message-ID: 20250313-uvc-eprobedefer-v3-1-a1d312708eef@chromium.org Reviewed-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/media/usb/uvc/uvc_driver.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-)
--- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -2447,13 +2447,16 @@ static int uvc_probe(struct usb_interfac #endif
/* Parse the Video Class control descriptor. */ - if (uvc_parse_control(dev) < 0) { + ret = uvc_parse_control(dev); + if (ret < 0) { + ret = -ENODEV; uvc_dbg(dev, PROBE, "Unable to parse UVC descriptors\n"); goto error; }
/* Parse the associated GPIOs. */ - if (uvc_gpio_parse(dev) < 0) { + ret = uvc_gpio_parse(dev); + if (ret < 0) { uvc_dbg(dev, PROBE, "Unable to parse UVC GPIOs\n"); goto error; } @@ -2479,24 +2482,32 @@ static int uvc_probe(struct usb_interfac }
/* Register the V4L2 device. */ - if (v4l2_device_register(&intf->dev, &dev->vdev) < 0) + ret = v4l2_device_register(&intf->dev, &dev->vdev); + if (ret < 0) goto error;
/* Scan the device for video chains. */ - if (uvc_scan_device(dev) < 0) + if (uvc_scan_device(dev) < 0) { + ret = -ENODEV; goto error; + }
/* Initialize controls. */ - if (uvc_ctrl_init_device(dev) < 0) + if (uvc_ctrl_init_device(dev) < 0) { + ret = -ENODEV; goto error; + }
/* Register video device nodes. */ - if (uvc_register_chains(dev) < 0) + if (uvc_register_chains(dev) < 0) { + ret = -ENODEV; goto error; + }
#ifdef CONFIG_MEDIA_CONTROLLER /* Register the media device node */ - if (media_device_register(&dev->mdev) < 0) + ret = media_device_register(&dev->mdev); + if (ret < 0) goto error; #endif /* Save our data pointer in the interface data. */ @@ -2523,7 +2534,7 @@ static int uvc_probe(struct usb_interfac error: uvc_unregister_video(dev); kref_put(&dev->ref, uvc_delete); - return -ENODEV; + return ret; }
static void uvc_disconnect(struct usb_interface *intf)