[PATCH v7 05/19] media: meson: vdec: Fix race condition and synchronize esparser IRQ
Anand Moon
linux.amoon at gmail.com
Mon Jul 13 05:07:00 PDT 2026
During session teardown sequences in vdec_stop_streaming() and
vdec_close(), the 'esparser' hardware interrupt handler can still be
actively triggered or executing on another CPU core. This creates a
transient race condition where the ISR attempts to handle stream data and
allocate internal tracking state structures after session contexts have
been modified or freed.
Update esparser_isr() to read the current session context utilizing an
smp_load_acquire() barrier snapshot. If the pointer resolves to NULL,
terminate processing early with IRQ_HANDLED to protect against
concurrent dismantling.
Suggested-by: Doruk Tan Ozturk <doruk at 0sec.ai>
Reported-by: Sashiko <sashiko-bot at kernel.org>
Closes: https://lore.kernel.org/all/20260521090944.F35401F00A3D@smtp.kernel.org/
Signed-off-by: Anand Moon <linux.amoon at gmail.com>
---
drivers/staging/media/meson/vdec/esparser.c | 8 ++++++++
drivers/staging/media/meson/vdec/vdec.c | 4 ++++
drivers/staging/media/meson/vdec/vdec.h | 2 ++
3 files changed, 14 insertions(+)
diff --git a/drivers/staging/media/meson/vdec/esparser.c b/drivers/staging/media/meson/vdec/esparser.c
index 4632346f04a9e..37749ede308c6 100644
--- a/drivers/staging/media/meson/vdec/esparser.c
+++ b/drivers/staging/media/meson/vdec/esparser.c
@@ -60,6 +60,12 @@ static irqreturn_t esparser_isr(int irq, void *dev)
{
int int_status;
struct amvdec_core *core = dev;
+ struct amvdec_session *sess;
+
+ /* Secure an atomic snapshot to protect against concurrent teardown */
+ sess = smp_load_acquire(&core->cur_sess);
+ if (!sess)
+ return IRQ_HANDLED;
int_status = amvdec_read_parser(core, PARSER_INT_STATUS);
amvdec_write_parser(core, PARSER_INT_STATUS, int_status);
@@ -439,6 +445,8 @@ int esparser_init(struct platform_device *pdev, struct amvdec_core *core)
if (irq < 0)
return irq;
+ core->esparser_irq = irq;
+
ret = devm_request_irq(dev, irq, esparser_isr, IRQF_SHARED,
"esparserirq", core);
if (ret) {
diff --git a/drivers/staging/media/meson/vdec/vdec.c b/drivers/staging/media/meson/vdec/vdec.c
index 7ae3d5a9dd6ab..7689ffdb2e500 100644
--- a/drivers/staging/media/meson/vdec/vdec.c
+++ b/drivers/staging/media/meson/vdec/vdec.c
@@ -486,6 +486,8 @@ static void vdec_stop_streaming(struct vb2_queue *q)
/* Synchronize and flush pending hardware interrupt service routines */
synchronize_irq(core->vdec_irq);
+ /* Ensure esparser ISR finishes executing */
+ synchronize_irq(core->esparser_irq);
vdec_poweroff(sess);
vdec_free_canvas(sess);
@@ -994,6 +996,8 @@ static int vdec_close(struct file *file)
/* Synchronize and flush pending hardware interrupt service routines */
synchronize_irq(core->vdec_irq);
+ /* Ensure esparser ISR finishes executing */
+ synchronize_irq(core->esparser_irq);
if (!IS_ERR_OR_NULL(sess->recycle_thread)) {
kthread_stop(sess->recycle_thread);
diff --git a/drivers/staging/media/meson/vdec/vdec.h b/drivers/staging/media/meson/vdec/vdec.h
index d165c343fd022..c4639cf33e73e 100644
--- a/drivers/staging/media/meson/vdec/vdec.h
+++ b/drivers/staging/media/meson/vdec/vdec.h
@@ -68,6 +68,7 @@ struct amvdec_session;
* @cur_sess: current decoding session
* @lock: video device lock
* @vdec_irq: irq for video decoding
+ * @esparser_irq: irq for elementary stream parsing
*/
struct amvdec_core {
void __iomem *dos_base;
@@ -95,6 +96,7 @@ struct amvdec_core {
struct amvdec_session *cur_sess;
struct mutex lock;
int vdec_irq;
+ int esparser_irq;
};
/**
--
2.50.1
More information about the linux-amlogic
mailing list