• Paul Burton's avatar
    irqchip/mips-gic: Fix local interrupts · e875bd66
    Paul Burton authored
    Since the device hierarchy domain was added by commit c98c1822
    ("irqchip/mips-gic: Add device hierarchy domain"), GIC local interrupts
    have been broken.
    
    Users attempting to setup a per-cpu local IRQ, for example the GIC timer
    clock events code in drivers/clocksource/mips-gic-timer.c, the
    setup_percpu_irq function would refuse with -EINVAL because the GIC
    irqchip driver never called irq_set_percpu_devid so the
    IRQ_PER_CPU_DEVID flag was never set for the IRQ. This happens because
    irq_set_percpu_devid was being called from the gic_irq_domain_map
    function which is no longer called.
    
    Doing only that runs into further problems because gic_dev_domain_alloc
    set the struct irq_chip for all interrupts, local or shared, to
    gic_level_irq_controller despite that only being suitable for shared
    interrupts. The typical outcome of this is that gic_level_irq_controller
    callback functions are called for local interrupts, and then hwirq
    number calculations overflow & the driver ends up attempting to access
    some invalid register with an address calculated from an invalid hwirq
    number. Best case scenario is that this then leads to a bus error. This
    is fixed by abstracting the setup of the hwirq & chip to a new function
    gic_setup_dev_chip which is used by both the root GIC IRQ domain & the
    device domain.
    
    Finally, decoding local interrupts failed because gic_dev_domain_alloc
    only called irq_domain_alloc_irqs_parent for shared interrupts. Local
    ones were therefore never associated with hwirqs in the root GIC IRQ
    domain and the virq in gic_handle_local_int would always be 0. This is
    fixed by calling irq_domain_alloc_irqs_parent unconditionally & having
    gic_irq_domain_alloc handle both local & shared interrupts, which is
    easy due to the aforementioned abstraction of chip setup into
    gic_setup_dev_chip.
    
    This fixes use of the MIPS GIC timer for clock events, which has been
    broken since c98c1822 ("irqchip/mips-gic: Add device hierarchy
    domain") but hadn't been noticed due to a silent fallback to the MIPS
    coprocessor 0 count/compare clock events device.
    
    Fixes: c98c1822 ("irqchip/mips-gic: Add device hierarchy domain")
    Signed-off-by: default avatarPaul Burton <paul.burton@imgtec.com>
    Cc: linux-mips@linux-mips.org
    Cc: Jason Cooper <jason@lakedaemon.net>
    Cc: Qais Yousef <qsyousef@gmail.com>
    Cc: stable@vger.kernel.org
    Cc: Marc Zyngier <marc.zyngier@arm.com>
    Link: http://lkml.kernel.org/r/20160913165335.31389-1-paul.burton@imgtec.comSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    e875bd66
irq-mips-gic.c 28 KB