[PATCH] media: qcom: camss: stop started subdevices when stream-on fails
From: Jizhou Tong
Date: Wed Sep 30 2026 - 03:05:24 EST
CAMSS starts subdevices from the video node towards the sensor. If a
later subdevice fails to start, video_start_streaming() stops only the
media pipeline and returns the queued buffers. Earlier subdevices remain
streaming, leaving their resources and V4L2 stream state active.
Successful stream-on sequences do not enter this error path.
On a Surface Laptop 7, an OV02C10 register-write timeout was followed by
call_s_stream() warnings when the next capture retried the already
started subdevices.
Walk the pipeline again on failure and stop each subdevice before the
failing entity. Keep the original start error and continue cleanup even
if a stop operation fails, then release the media pipeline and buffers.
Fixes: 0ac2586c410f ("media: camss: Add files which handle the video device nodes")
Signed-off-by: Jizhou Tong <fqwqf@xxxxxxxxx>
---
Based on Linux 7.3-rc5.
This touches the legacy pipeline walk also refactored by Gjorgji's
streams API series [1]. The start-failure cleanup is still needed in
its video_start_streaming_legacy() path.
Validation: ARM64 W=1 object build and ASan/UBSan tests of the actual
start function, covering 320 failure/retry combinations plus pipeline
allocation and format-check failures. The baseline leaves subdevices
enabled; the patched function cleans them up before a successful retry.
The fix has build and software-test coverage; the hardware observations
in the commit message are from the original kernel.
Test harness:
https://gist.github.com/fQwQf/60bd12627e06b10a2fc159e545f85dae/7b21a7d3a1b676a0e4cdaba06168ede09a2949e3
[1] https://lore.kernel.org/all/20260911062213.195007-8-gjorgji.rosikopulos@xxxxxxxxxxxxxxxx/
.../media/platform/qcom/camss/camss-video.c | 23 +++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c
index 0852eb6f13..44fb5d8cc3 100644
--- a/drivers/media/platform/qcom/camss/camss-video.c
+++ b/drivers/media/platform/qcom/camss/camss-video.c
@@ -253,7 +253,7 @@ static int video_start_streaming(struct vb2_queue *q, unsigned int count)
{
struct camss_video *video = vb2_get_drv_priv(q);
struct video_device *vdev = &video->vdev;
- struct media_entity *entity;
+ struct media_entity *entity, *started_entity;
struct media_pad *pad;
struct v4l2_subdev *subdev;
int ret;
@@ -283,11 +283,30 @@ static int video_start_streaming(struct vb2_queue *q, unsigned int count)
ret = v4l2_subdev_call(subdev, video, s_stream, 1);
if (ret < 0 && ret != -ENOIOCTLCMD)
- goto error;
+ goto stop_subdevs;
}
return 0;
+stop_subdevs:
+ /* Stop the subdevices started before the failing entity. */
+ started_entity = &vdev->entity;
+ while (1) {
+ pad = &started_entity->pads[0];
+ if (!(pad->flags & MEDIA_PAD_FL_SINK))
+ break;
+
+ pad = media_pad_remote_pad_first(pad);
+ if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
+ break;
+
+ started_entity = pad->entity;
+ if (started_entity == entity)
+ break;
+
+ subdev = media_entity_to_v4l2_subdev(started_entity);
+ v4l2_subdev_call(subdev, video, s_stream, 0);
+ }
error:
video_device_pipeline_stop(vdev);
base-commit: 72d3fcf802c45d00b300f25b848a93c3a2bd7c7e
--
2.53.0