summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBingbu Cao <bingbu.cao@intel.com>2025-12-23 10:23:00 +0300
committerSasha Levin <sashal@kernel.org>2026-03-04 15:21:12 +0300
commitc2e0b70acc68d5fa39043cfd79bf63d142242a3f (patch)
treeba868b2a2d9949f56f36ca2d93829c032de211e8
parent3cd9e7539a3010a83391fecade1186cf30e616c9 (diff)
downloadlinux-c2e0b70acc68d5fa39043cfd79bf63d142242a3f.tar.xz
media: staging/ipu7: Ignore interrupts when device is suspended
[ Upstream commit 9ad65684b9285c5d66fb417d50e91a25ef8c994d ] IPU7 devices have shared interrupts with others. In some case when IPU7 device is suspended, driver get unexpected interrupt and invalid irq status 0xffffffff from ISR_STATUS and PB LOCAL_STATUS registers as interrupt is triggered from other device on shared irq line. In order to avoid this issue use pm_runtime_get_if_active() to check if IPU7 device is resumed, ignore the invalid irq status and use synchronize_irq() in suspend. Cc: Stable@vger.kernel.org Fixes: b7fe4c0019b1 ("media: staging/ipu7: add Intel IPU7 PCI device driver") Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/staging/media/ipu7/ipu7-buttress.c17
-rw-r--r--drivers/staging/media/ipu7/ipu7.c4
2 files changed, 20 insertions, 1 deletions
diff --git a/drivers/staging/media/ipu7/ipu7-buttress.c b/drivers/staging/media/ipu7/ipu7-buttress.c
index e5707f5e300b..40c6c8473357 100644
--- a/drivers/staging/media/ipu7/ipu7-buttress.c
+++ b/drivers/staging/media/ipu7/ipu7-buttress.c
@@ -342,14 +342,23 @@ irqreturn_t ipu_buttress_isr(int irq, void *isp_ptr)
u32 disable_irqs = 0;
u32 irq_status;
unsigned int i;
+ int active;
- pm_runtime_get_noresume(dev);
+ active = pm_runtime_get_if_active(dev);
+ if (active <= 0)
+ return IRQ_NONE;
pb_irq = readl(isp->pb_base + INTERRUPT_STATUS);
writel(pb_irq, isp->pb_base + INTERRUPT_STATUS);
/* check btrs ATS, CFI and IMR errors, BIT(0) is unused for IPU */
pb_local_irq = readl(isp->pb_base + BTRS_LOCAL_INTERRUPT_MASK);
+ if (pb_local_irq == 0xffffffff) {
+ dev_warn_once(dev, "invalid PB irq status\n");
+ pm_runtime_put_noidle(dev);
+ return IRQ_NONE;
+ }
+
if (pb_local_irq & ~BIT(0)) {
dev_warn(dev, "PB interrupt status 0x%x local 0x%x\n", pb_irq,
pb_local_irq);
@@ -370,6 +379,12 @@ irqreturn_t ipu_buttress_isr(int irq, void *isp_ptr)
return IRQ_NONE;
}
+ if (irq_status == 0xffffffff) {
+ dev_warn_once(dev, "invalid irq status 0x%08x\n", irq_status);
+ pm_runtime_put_noidle(dev);
+ return IRQ_NONE;
+ }
+
do {
writel(irq_status, isp->base + BUTTRESS_REG_IRQ_CLEAR);
diff --git a/drivers/staging/media/ipu7/ipu7.c b/drivers/staging/media/ipu7/ipu7.c
index 5cddc09c72bf..6c8c3eea44ac 100644
--- a/drivers/staging/media/ipu7/ipu7.c
+++ b/drivers/staging/media/ipu7/ipu7.c
@@ -2684,6 +2684,10 @@ static void ipu7_pci_reset_done(struct pci_dev *pdev)
*/
static int ipu7_suspend(struct device *dev)
{
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ synchronize_irq(pdev->irq);
+
return 0;
}