From: Christian Cortner <ccortner@gmail.com>
To: Bryan O'Donoghue <bod@kernel.org>,
Vikash Garodia <vikash.garodia@oss.qualcomm.com>,
Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Cc: Abhinav Kumar <abhinav.kumar@linux.dev>,
Birk Skyum <birk.skyum@pm.me>,
linux-media@vger.kernel.org, linux-arm-msm@vger.kernel.org
Subject: [RFC PATCH v2 4/4] media: iris: Let a resolution change drain before stopping CAPTURE
Date: Tue, 27 Oct 2026 22:43:35 -0500 [thread overview]
Message-ID: <20261028034335.26075-5-ccortner@gmail.com> (raw)
In-Reply-To: <20261028034335.26075-1-ccortner@gmail.com>
ffmpeg's h264_v4l2m2m stops CAPTURE about 10 us after it dequeues a
source change event. If the stop reaches the firmware before the
PSC_LAST buffer, that buffer still arrives (1.3 ms later in a trace),
iris_inst_sub_state_change_drc_last() rejects it, and the instance
goes to IRIS_INST_ERROR: no more buffers come back.
Wait up to 500 ms in iris_vb2_stop_streaming() for a pending source
change to drain, and warn when it does not.
Fixes: 84e17adae3e3 ("media: iris: add support for dynamic resolution change")
Assisted-by: LLM sparse smatch
---
.../media/platform/qcom/iris/iris_instance.h | 3 +++
drivers/media/platform/qcom/iris/iris_state.c | 8 +++++++-
drivers/media/platform/qcom/iris/iris_vb2.c | 20 +++++++++++++++++++
drivers/media/platform/qcom/iris/iris_vidc.c | 1 +
4 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h
index 771269e705d9..1013ed2911a1 100644
--- a/drivers/media/platform/qcom/iris/iris_instance.h
+++ b/drivers/media/platform/qcom/iris/iris_instance.h
@@ -7,6 +7,7 @@
#define __IRIS_INSTANCE_H__
#include <linux/kref.h>
+#include <linux/wait.h>
#include <media/v4l2-ctrls.h>
@@ -56,6 +57,7 @@ struct iris_hfi_session_ops;
* @metadata_idx: index for metadata buffer
* @codec: codec type
* @last_buffer_dequeued: a flag to indicate that last buffer is sent by driver
+ * @drc_wq: woken when IRIS_INST_SUB_DRC_LAST is set
* @last_buf_ns: start time of received input buffer for current one second FPS window
* @frame_counter: input buffer counter for current one second FPS window
* @frame_rate: frame rate of current instance
@@ -104,6 +106,7 @@ struct iris_inst {
u32 metadata_idx;
u32 codec;
bool last_buffer_dequeued;
+ wait_queue_head_t drc_wq;
u64 last_buf_ns;
u32 frame_counter;
u32 frame_rate;
diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c
index 5552725c614e..dd8e0093b972 100644
--- a/drivers/media/platform/qcom/iris/iris_state.c
+++ b/drivers/media/platform/qcom/iris/iris_state.c
@@ -209,6 +209,7 @@ int iris_inst_sub_state_change_drain_last(struct iris_inst *inst)
int iris_inst_sub_state_change_drc_last(struct iris_inst *inst)
{
enum iris_inst_sub_state set_sub_state;
+ int ret;
if (inst->sub_state & IRIS_INST_SUB_DRC_LAST)
return -EINVAL;
@@ -222,7 +223,12 @@ int iris_inst_sub_state_change_drc_last(struct iris_inst *inst)
set_sub_state = IRIS_INST_SUB_DRC_LAST | IRIS_INST_SUB_OUTPUT_PAUSE;
- return iris_inst_change_sub_state(inst, 0, set_sub_state);
+ ret = iris_inst_change_sub_state(inst, 0, set_sub_state);
+ /* a CAPTURE STREAMOFF may be waiting, see iris_vb2_stop_streaming() */
+ if (!ret)
+ wake_up_all(&inst->drc_wq);
+
+ return ret;
}
int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane)
diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c
index bb713da20605..2460778c408d 100644
--- a/drivers/media/platform/qcom/iris/iris_vb2.c
+++ b/drivers/media/platform/qcom/iris/iris_vb2.c
@@ -228,6 +228,15 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
return ret;
}
+/* a source change whose drain the firmware has not completed yet */
+static bool iris_drc_draining(struct iris_inst *inst)
+{
+ enum iris_inst_sub_state sub_state = READ_ONCE(inst->sub_state);
+
+ return sub_state & IRIS_INST_SUB_DRC &&
+ !(sub_state & IRIS_INST_SUB_DRC_LAST);
+}
+
void iris_vb2_stop_streaming(struct vb2_queue *q)
{
struct iris_inst *inst;
@@ -238,6 +247,17 @@ void iris_vb2_stop_streaming(struct vb2_queue *q)
if (V4L2_TYPE_IS_CAPTURE(q->type) && inst->state == IRIS_INST_INIT)
return;
+ /*
+ * Stopping CAPTURE before the firmware has drained a pending
+ * resolution change leaves the change incomplete, and decoding stalls
+ * after the next STREAMON. Wait up to 500 ms for the drain.
+ */
+ if (V4L2_TYPE_IS_CAPTURE(q->type) &&
+ !wait_event_timeout(inst->drc_wq, !iris_drc_draining(inst),
+ msecs_to_jiffies(500)))
+ dev_warn(inst->core->dev,
+ "resolution change drain timed out, stopping CAPTURE\n");
+
mutex_lock(&inst->lock);
if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index 05aab6e3005d..0df0a5915e16 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -201,6 +201,7 @@ int iris_open(struct file *filp)
INIT_LIST_HEAD(&inst->buffers[BUF_PARTIAL].list);
init_completion(&inst->completion);
init_completion(&inst->flush_completion);
+ init_waitqueue_head(&inst->drc_wq);
iris_v4l2_fh_init(inst, filp);
--
2.56.0
next prev parent reply other threads:[~2026-10-28 3:43 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <-D3aZIsoO4_H5CdnB-7Co7GWmm5F9FuU6aFuhXWogBXhfqNOaqC2Y8tkBxT9ljDcy84UAX1jmUWGl7NtGUG6Mg==@protonmail.internalid>
2026-10-28 3:43 ` [RFC PATCH v2 0/4] media: iris: decoder fixes for resolution changes Christian Cortner
2026-10-28 3:43 ` [RFC PATCH v2 1/4] media: iris: Don't flag an empty source change LAST buffer as an error Christian Cortner
2026-10-28 3:43 ` [RFC PATCH v2 2/4] media: iris: Update the CAPTURE stride and size on S_FMT(OUTPUT) Christian Cortner
2026-10-28 3:43 ` [RFC PATCH v2 3/4] media: iris: Signal V4L2_EVENT_EOS only at the end of a drain Christian Cortner
2026-10-28 3:43 ` Christian Cortner [this message]
2026-10-28 10:00 ` [RFC PATCH v2 0/4] media: iris: decoder fixes for resolution changes Bryan O'Donoghue
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261028034335.26075-5-ccortner@gmail.com \
--to=ccortner@gmail.com \
--cc=abhinav.kumar@linux.dev \
--cc=birk.skyum@pm.me \
--cc=bod@kernel.org \
--cc=dikshita.agarwal@oss.qualcomm.com \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=vikash.garodia@oss.qualcomm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.