• Thomas Gleixner's avatar
    genirq: Prevent chip buslock deadlock · abc7e40c
    Thomas Gleixner authored
    If a interrupt chip utilizes chip->buslock then free_irq() can
    deadlock in the following way:
    
    CPU0				CPU1
    				interrupt(X) (Shared or spurious)
    free_irq(X)			interrupt_thread(X)
    chip_bus_lock(X)
    				   irq_finalize_oneshot(X)
    				     chip_bus_lock(X)
    synchronize_irq(X)
    	
    synchronize_irq() waits for the interrupt thread to complete,
    i.e. forever.
    
    Solution is simple: Drop chip_bus_lock() before calling
    synchronize_irq() as we do with the irq_desc lock. There is nothing to
    be protected after the point where irq_desc lock has been released.
    
    This adds chip_bus_lock/unlock() to the remove_irq() code path, but
    that's actually correct in the case where remove_irq() is called on
    such an interrupt. The current users of remove_irq() are not affected
    as none of those interrupts is on a chip which requires buslock.
    Reported-by: default avatarFredrik Markström <fredrik.markstrom@gmail.com>
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Cc: stable@vger.kernel.org
    abc7e40c
manage.c 51.9 KB