mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 18:43:33 +02:00
media: staging/ipu7: Ignore interrupts when device is suspended
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: b7fe4c0019 ("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>
This commit is contained in:
parent
6099f78e4c
commit
9ad65684b9
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user