Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: uvcvideo: Fix deferred probing error

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>

authored by

Ricardo Ribalda and committed by
Hans Verkuil
387e8939 a70705d3

+19 -8
+19 -8
drivers/media/usb/uvc/uvc_driver.c
··· 2232 2232 #endif 2233 2233 2234 2234 /* Parse the Video Class control descriptor. */ 2235 - if (uvc_parse_control(dev) < 0) { 2235 + ret = uvc_parse_control(dev); 2236 + if (ret < 0) { 2237 + ret = -ENODEV; 2236 2238 uvc_dbg(dev, PROBE, "Unable to parse UVC descriptors\n"); 2237 2239 goto error; 2238 2240 } 2239 2241 2240 2242 /* Parse the associated GPIOs. */ 2241 - if (uvc_gpio_parse(dev) < 0) { 2243 + ret = uvc_gpio_parse(dev); 2244 + if (ret < 0) { 2242 2245 uvc_dbg(dev, PROBE, "Unable to parse UVC GPIOs\n"); 2243 2246 goto error; 2244 2247 } ··· 2267 2264 } 2268 2265 2269 2266 /* Register the V4L2 device. */ 2270 - if (v4l2_device_register(&intf->dev, &dev->vdev) < 0) 2267 + ret = v4l2_device_register(&intf->dev, &dev->vdev); 2268 + if (ret < 0) 2271 2269 goto error; 2272 2270 2273 2271 /* Scan the device for video chains. */ 2274 - if (uvc_scan_device(dev) < 0) 2272 + if (uvc_scan_device(dev) < 0) { 2273 + ret = -ENODEV; 2275 2274 goto error; 2275 + } 2276 2276 2277 2277 /* Initialize controls. */ 2278 - if (uvc_ctrl_init_device(dev) < 0) 2278 + if (uvc_ctrl_init_device(dev) < 0) { 2279 + ret = -ENODEV; 2279 2280 goto error; 2281 + } 2280 2282 2281 2283 /* Register video device nodes. */ 2282 - if (uvc_register_chains(dev) < 0) 2284 + if (uvc_register_chains(dev) < 0) { 2285 + ret = -ENODEV; 2283 2286 goto error; 2287 + } 2284 2288 2285 2289 #ifdef CONFIG_MEDIA_CONTROLLER 2286 2290 /* Register the media device node */ 2287 - if (media_device_register(&dev->mdev) < 0) 2291 + ret = media_device_register(&dev->mdev); 2292 + if (ret < 0) 2288 2293 goto error; 2289 2294 #endif 2290 2295 /* Save our data pointer in the interface data. */ ··· 2326 2315 error: 2327 2316 uvc_unregister_video(dev); 2328 2317 kref_put(&dev->ref, uvc_delete); 2329 - return -ENODEV; 2318 + return ret; 2330 2319 } 2331 2320 2332 2321 static void uvc_disconnect(struct usb_interface *intf)