Skip to content
  • Paul Walmsley's avatar
    i2c-omap: Close suspected race between omap_i2c_idle() and omap_i2c_isr() · 0cbbcffd
    Paul Walmsley authored
    
    
    omap_i2c_idle() sets an internal flag, "dev->idle", instructing its
    ISR to decline interrupts.  It sets this flag before it actually masks
    the interrupts on the I2C controller.  This is problematic, since an
    I2C interrupt could arrive after dev->idle is set, but before the
    interrupt source is masked.  When this happens, Linux disables the I2C
    controller's IRQ, causing all future transactions on the bus to fail.
    
    Symptoms, happening on about 7% of boots:
    
       irq 56: nobody cared (try booting with the "irqpoll" option)
       <warning traceback here>
       Disabling IRQ #56
       i2c_omap i2c_omap.1: controller timed out
    
    In omap_i2c_idle(), this patch sets dev->idle only after the interrupt
    mask write to the I2C controller has left the ARM write buffer.
    That's probably the major offender.  For additional prophylaxis, in
    omap_i2c_unidle(), the patch clears the dev->idle flag before
    interrupts are enabled, rather than afterwards.
    
    The patch has survived twenty-two reboots on the 3430SDP here without
    wedging I2C1.  Not absolutely dispositive, but promising!
    
    Signed-off-by: default avatarPaul Walmsley <paul@pwsan.com>
    Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
    
    0cbbcffd