mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
media: intel/ipu6: do not handle interrupts when device is disabled
Some IPU6 devices have shared interrupts. We need to handle properly
case when interrupt is triggered from other device on shared irq line
and IPU6 itself disabled. In such case we get 0xffffffff from
ISR_STATUS register and handle all irq's cases, for what we are not
not prepared and usually hang the whole system.
To avoid the issue use pm_runtime_get_if_active() to check if
the device is enabled and prevent suspending it when we handle irq
until the end of irq. Additionally use synchronize_irq() in suspend
Fixes: ab29a2478e
("media: intel/ipu6: add IPU6 buttress interface driver")
Cc: stable@vger.kernel.org
Signed-off-by: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Tested-by: Hans de Goede <hdegoede@redhat.com> # ThinkPad X1 Yoga Gen 8, ov2740
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
This commit is contained in:
parent
0a33a4e050
commit
1429826883
2 changed files with 12 additions and 4 deletions
|
@ -346,12 +346,16 @@ irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr)
|
|||
u32 disable_irqs = 0;
|
||||
u32 irq_status;
|
||||
u32 i, count = 0;
|
||||
int active;
|
||||
|
||||
pm_runtime_get_noresume(&isp->pdev->dev);
|
||||
active = pm_runtime_get_if_active(&isp->pdev->dev);
|
||||
if (!active)
|
||||
return IRQ_NONE;
|
||||
|
||||
irq_status = readl(isp->base + reg_irq_sts);
|
||||
if (!irq_status) {
|
||||
pm_runtime_put_noidle(&isp->pdev->dev);
|
||||
if (irq_status == 0 || WARN_ON_ONCE(irq_status == 0xffffffffu)) {
|
||||
if (active > 0)
|
||||
pm_runtime_put_noidle(&isp->pdev->dev);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
|
@ -427,7 +431,8 @@ irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr)
|
|||
writel(BUTTRESS_IRQS & ~disable_irqs,
|
||||
isp->base + BUTTRESS_REG_ISR_ENABLE);
|
||||
|
||||
pm_runtime_put(&isp->pdev->dev);
|
||||
if (active > 0)
|
||||
pm_runtime_put(&isp->pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -753,6 +753,9 @@ static void ipu6_pci_reset_done(struct pci_dev *pdev)
|
|||
*/
|
||||
static int ipu6_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
||||
synchronize_irq(pdev->irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue