• T
    genirq: Prevent oneshot irq thread race · 0b1adaa0
    Thomas Gleixner 提交于
    Lars-Peter pointed out that the oneshot threaded interrupt handler
    code has the following race:
    
     CPU0                            CPU1
     hande_level_irq(irq X)
       mask_ack_irq(irq X)
       handle_IRQ_event(irq X)
         wake_up(thread_handler)
                                     thread handler(irq X) runs
                                     finalize_oneshot(irq X)
    				  does not unmask due to 
    				  !(desc->status & IRQ_MASKED)
    
     return from irq
     does not unmask due to
     (desc->status & IRQ_ONESHOT)
      				  
    This leaves the interrupt line masked forever. 
    
    The reason for this is the inconsistent handling of the IRQ_MASKED
    flag. Instead of setting it in the mask function the oneshot support
    sets the flag after waking up the irq thread.
    
    The solution for this is to set/clear the IRQ_MASKED status whenever
    we mask/unmask an interrupt line. That's the easy part, but that
    cleanup opens another race:
    
     CPU0                            CPU1
     hande_level_irq(irq)
       mask_ack_irq(irq)
       handle_IRQ_event(irq)
         wake_up(thread_handler)
                                     thread handler(irq) runs
                                     finalize_oneshot_irq(irq)
    				  unmask(irq)
         irq triggers again
         handle_level_irq(irq)
           mask_ack_irq(irq)
         return from irq due to IRQ_INPROGRESS				  
    
     return from irq
     does not unmask due to
     (desc->status & IRQ_ONESHOT)
    
    This requires that we synchronize finalize_oneshot_irq() with the
    primary handler. If IRQ_INPROGESS is set we wait until the primary
    handler on the other CPU has returned before unmasking the interrupt
    line again.
    
    We probably have never seen that problem because it does not happen on
    UP and on SMP the irqbalancer protects us by pinning the primary
    handler and the thread to the same CPU.
    Reported-by: NLars-Peter Clausen <lars@metafoo.de>
    Signed-off-by: NThomas Gleixner <tglx@linutronix.de>
    Cc: stable@kernel.org
    0b1adaa0
manage.c 27.5 KB