aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/v4l2-core
diff options
context:
space:
mode:
authorGravatar Laurent Pinchart <laurent.pinchart@ideasonboard.com> 2023-09-18 15:48:38 +0300
committerGravatar Hans Verkuil <hverkuil-cisco@xs4all.nl> 2023-09-27 09:39:57 +0200
commit009905ec50433259c05f474251000b040098564e (patch)
tree8ed63e6498fda63971982fd024c24ed84264ba85 /drivers/media/v4l2-core
parentmedia: ov13b10: Add 1364x768 register settings (diff)
downloadlinux-009905ec50433259c05f474251000b040098564e.tar.gz
linux-009905ec50433259c05f474251000b040098564e.tar.bz2
linux-009905ec50433259c05f474251000b040098564e.zip
media: v4l2-subdev: Document and enforce .s_stream() requirements
The subdev .s_stream() operation must not be called to start an already started subdev, or stop an already stopped one. This requirement has never been formally documented. Fix it, and catch possible offenders with a WARN_ON() in the call_s_stream() wrapper. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Diffstat (limited to 'drivers/media/v4l2-core')
-rw-r--r--drivers/media/v4l2-core/v4l2-subdev.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index b92348ad61f6..32b7d9cd43e6 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -359,6 +359,18 @@ static int call_s_stream(struct v4l2_subdev *sd, int enable)
{
int ret;
+ /*
+ * The .s_stream() operation must never be called to start or stop an
+ * already started or stopped subdev. Catch offenders but don't return
+ * an error yet to avoid regressions.
+ *
+ * As .s_stream() is mutually exclusive with the .enable_streams() and
+ * .disable_streams() operation, we can use the enabled_streams field
+ * to store the subdev streaming state.
+ */
+ if (WARN_ON(!!sd->enabled_streams == !!enable))
+ return 0;
+
#if IS_REACHABLE(CONFIG_LEDS_CLASS)
if (!IS_ERR_OR_NULL(sd->privacy_led)) {
if (enable)
@@ -372,9 +384,12 @@ static int call_s_stream(struct v4l2_subdev *sd, int enable)
if (!enable && ret < 0) {
dev_warn(sd->dev, "disabling streaming failed (%d)\n", ret);
- return 0;
+ ret = 0;
}
+ if (!ret)
+ sd->enabled_streams = enable ? BIT(0) : 0;
+
return ret;
}