• Pavel Emelianov's avatar
    [PATCH] Fix misrouted interrupts deadlocks · f72fa707
    Pavel Emelianov authored
    While testing kernel on machine with "irqpoll" option I've caught such a
    lockup:
    
    	__do_IRQ()
    	   spin_lock(&desc->lock);
               desc->chip->ack(); /* IRQ is ACKed */
    	note_interrupt()
    	misrouted_irq()
    	handle_IRQ_event()
               if (...)
    	      local_irq_enable_in_hardirq();
    	/* interrupts are enabled from now */
    	...
    	__do_IRQ() /* same IRQ we've started from */
    	   spin_lock(&desc->lock); /* LOCKUP */
    
    Looking at misrouted_irq() code I've found that a potential deadlock like
    this can also take place:
    
    1CPU:
    __do_IRQ()
       spin_lock(&desc->lock); /* irq = A */
    misrouted_irq()
       for (i = 1; i < NR_IRQS; i++) {
          spin_lock(&desc->lock); /* irq = B */
          if (desc->status & IRQ_INPROGRESS) {
    
    2CPU:
    __do_IRQ()
       spin_lock(&desc->lock); /* irq = B */
    misrouted_irq()
       for (i = 1; i < NR_IRQS; i++) {
          spin_lock(&desc->lock); /* irq = A */
          if (desc->status & IRQ_INPROGRESS) {
    
    As the second lock on both CPUs is taken before checking that this irq is
    being handled in another processor this may cause a deadlock.  This issue
    is only theoretical.
    
    I propose the attached patch to fix booth problems: when trying to handle
    misrouted IRQ active desc->lock may be unlocked.
    Acked-by: default avatarIngo Molnar <mingo@redhat.com>
    Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
    f72fa707
spurious.c 4.83 KB