]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
media: uvcvideo: Turn on the camera if V4L2_EVENT_SUB_FL_SEND_INITIAL
authorRicardo Ribalda <ribalda@chromium.org>
Tue, 1 Jul 2025 06:45:17 +0000 (06:45 +0000)
committerHans Verkuil <hverkuil@xs4all.nl>
Fri, 11 Jul 2025 17:27:28 +0000 (19:27 +0200)
If we subscribe to an event with V4L2_EVENT_SUB_FL_SEND_INITIAL, the
driver needs to report back some values that require the camera to be
powered on. But VIDIOC_SUBSCRIBE_EVENT is not part of the ioctls that
turn on the camera.

We could unconditionally turn on the camera during
VIDIOC_SUBSCRIBE_EVENT, but it is more efficient to turn it on only
during V4L2_EVENT_SUB_FL_SEND_INITIAL, which we believe is not a common
usecase.

To avoid a list_del if uvc_pm_get() fails, we move list_add_tail to the
end of the function.

Reviewed-by: Hans de Goede <hansg@kernel.org>
Fixes: d1b618e79548 ("media: uvcvideo: Do not turn on the camera for some ioctls")
Cc: stable@vger.kernel.org
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Link: https://lore.kernel.org/r/20250701-uvc-grannular-invert-v4-5-8003b9b89f68@chromium.org
Signed-off-by: Hans de Goede <hansg@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
drivers/media/usb/uvc/uvc_ctrl.c

index 303b7509ec47964dc1bf0e28127075b4a3867511..efe609d7087752cb2ef516eef0fce12acd13e747 100644 (file)
@@ -2072,18 +2072,24 @@ static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
                goto done;
        }
 
-       list_add_tail(&sev->node, &mapping->ev_subs);
        if (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL) {
                struct v4l2_event ev;
                u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
                s32 val = 0;
 
+               ret = uvc_pm_get(handle->chain->dev);
+               if (ret)
+                       goto done;
+
                if (uvc_ctrl_mapping_is_compound(mapping) ||
                    __uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0)
                        changes |= V4L2_EVENT_CTRL_CH_VALUE;
 
                uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, val,
                                    changes);
+
+               uvc_pm_put(handle->chain->dev);
+
                /*
                 * Mark the queue as active, allowing this initial event to be
                 * accepted.
@@ -2092,6 +2098,8 @@ static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
                v4l2_event_queue_fh(sev->fh, &ev);
        }
 
+       list_add_tail(&sev->node, &mapping->ev_subs);
+
 done:
        mutex_unlock(&handle->chain->ctrl_mutex);
        return ret;