| From 387e8939307192d5a852a2afeeb83427fa477151 Mon Sep 17 00:00:00 2001 |
| From: Ricardo Ribalda <ribalda@chromium.org> |
| Date: Thu, 13 Mar 2025 12:20:39 +0000 |
| Subject: media: uvcvideo: Fix deferred probing error |
| |
| 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 |
| @@ -2232,13 +2232,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; |
| } |
| @@ -2264,24 +2267,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. */ |
| @@ -2315,7 +2326,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) |