From a09e72360063f492cb676864d217551bd55f2a76 Mon Sep 17 00:00:00 2001 From: AxxzyWasTaken Date: Fri, 30 Oct 2026 14:59:10 +0000 Subject: [PATCH] media: apple: avd: Do not pop an empty mailbox The interrupt handler reads MBOX1_RETRIEVE without checking that the mailbox holds a message. An interrupt that finds it empty pops the previous message again. When that is a post-processing "done", the frame is finished early, the next frame starts while the PP is still busy, its PP never completes, and the watchdog resets the decoder; the frames that follow then fail with a VP error. Seen on a J616C (T6041) with VP9 in Chromium while the system is under load: a PP "done" 8 us after its kick instead of 400-1000 us, then a timeout on the next frame. Check the mailbox's empty flag first, give a late message up to 10 us, and ignore the interrupt if the mailbox stays empty. Signed-off-by: AxxzyWasTaken --- drivers/media/platform/apple/avd/avd-drv.c | 20 ++++++++++++++++++++ drivers/media/platform/apple/avd/avd-regs.h | 2 ++ 2 files changed, 22 insertions(+) diff --git a/drivers/media/platform/apple/avd/avd-drv.c b/drivers/media/platform/apple/avd/avd-drv.c index bf5bf96f4c62a..acbab4a2eb2be 100644 --- a/drivers/media/platform/apple/avd/avd-drv.c +++ b/drivers/media/platform/apple/avd/avd-drv.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -300,6 +301,25 @@ static irqreturn_t avd_irq_handler(int irq, void *data) if (!ctx) return IRQ_HANDLED; + /* + * Only pop a message the mailbox holds: popping an empty mailbox returns + * the previous message again. A stale post-processing "done" read that + * way finishes the frame early, the next frame starts while the PP is + * still busy, and its PP never completes, so the watchdog resets the + * decoder and the stream fails. The interrupt can also arrive just before + * its message is readable, so give the message a moment first. + */ + if (readl(avd->mbox + AVD_REG_MBOX1_STATUS) & AVD_MBOX1_STATUS_EMPTY) { + u32 mb; + + if (readl_poll_timeout_atomic(avd->mbox + AVD_REG_MBOX1_STATUS, mb, + !(mb & AVD_MBOX1_STATUS_EMPTY), 1, 10)) { + dev_dbg(avd->dev, "spurious interrupt, mailbox empty\n"); + writel(AVD_MBOX1_NOT_EMPTY, avd->mbox + AVD_REG_MBOX_IRQ_CLR); + return IRQ_HANDLED; + } + } + status = readl(avd->mbox + AVD_REG_MBOX1_RETRIEVE); writel(AVD_MBOX1_NOT_EMPTY, avd->mbox + AVD_REG_MBOX_IRQ_CLR); diff --git a/drivers/media/platform/apple/avd/avd-regs.h b/drivers/media/platform/apple/avd/avd-regs.h index 388f3e64895f5..ace0e4c48f40a 100644 --- a/drivers/media/platform/apple/avd/avd-regs.h +++ b/drivers/media/platform/apple/avd/avd-regs.h @@ -13,6 +13,8 @@ #define AVD_MBOX1_NOT_EMPTY BIT(3) #define AVD_REG_MBOX1_STATUS 0x5c +/* Read side: bits 8-11 write pointer, bits 12-15 read pointer, bit 17 empty. */ +#define AVD_MBOX1_STATUS_EMPTY BIT(17) #define AVD_REG_MBOX1_RETRIEVE 0x64 #define AVD_MBOX_ENABLE BIT(0)