• Thomas Petazzoni's avatar
    irqchip/armada-370-xp: Re-enable per-CPU interrupts at resume time · 0fa4ce74
    Thomas Petazzoni authored
    Commit d17cab44 ("irqchip: Kill off set_irq_flags usage") changed
    the code of armada_370_xp_mpic_irq_map() from using set_irq_flags() to
    irq_set_probe().
    
    While the commit log seems to imply that there are no functional
    changes, there are indeed functional changes introduced by this commit:
    the IRQ_NOAUTOEN flag is no longer cleared. This functional change
    caused a regression on Armada XP, which no longer works properly after
    suspend/resume because per-CPU interrupts remain disabled. This
    regression was temporarly worked around in commit
    353d6d6c ("irqchip/armada-370-xp: Fix regression by clearing
    IRQ_NOAUTOEN"), but it is not the most satisfying solution. This commit
    implements the solution that was initially discussed with Thomas
    Gleixner.
    
    Due to how the hardware registers work, the irq-armada-370-xp cannot
    simply save/restore a bunch of registers at suspend/resume to make sure
    that the interrupts remain in the same state after resuming. Therefore,
    it relies on the kernel to say whether the interrupt is disabled or not,
    using the irqd_irq_disabled() function. This was all working fine while
    the IRQ_NOAUTOEN flag was cleared.
    
    With the change introduced by Rob Herring in d17cab44, the
    IRQ_NOAUTOEN flag is now set for all interrupts. irqd_irq_disabled()
    returns false for per-CPU interrupts, and therefore our per-CPU
    interrupts are no longer re-enabled after resume.
    
    This commit fixes that by using irqd_irq_disabled() only for global
    interrupts, and using the newly introduced irq_percpu_is_enabled() for
    per-CPU interrupts.
    
    Also, it fixes a related problems that per-CPU interrupts were only
    re-enabled on the boot CPU and not other CPUs. Until now this wasn't a
    problem since on this platform, only the local timers are using per-CPU
    interrupts and the local timers of secondary CPUs are turned off/on
    during CPU hotplug before suspend, after after resume. However, since
    Linux 4.4, we are also be using per-CPU interrupts for the network
    controller, so we need to properly restore the per-CPU interrupts on
    secondary CPUs as well.
    Signed-off-by: default avatarThomas Petazzoni <thomas.petazzoni@free-electrons.com>
    Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
    0fa4ce74
irq-armada-370-xp.c 19.6 KB