Skip to content
  • Grygorii Strashko's avatar
    gpiolib: irqchip: use different lockdep class for each gpio irqchip · a0a8bcf4
    Grygorii Strashko authored and Linus Walleij's avatar Linus Walleij committed
    Since IRQ chip helpers were introduced drivers lose ability to
    register separate lockdep classes for each registered GPIO IRQ
    chip and the gpiolib now is using shared lockdep class for
    all GPIO IRQ chips (gpiochip_irq_lock_class).
    As result, lockdep will produce warning when there are min two
    stacked GPIO chips and all of them are interrupt controllers.
    
    HW configuration which generates lockdep warning (TI dra7-evm):
    
    [SOC GPIO bankA.gpioX]
      <- irq - [pcf875x.gpioY]
                <- irq - DevZ.enable_irq_wake(pcf_gpioY_irq);
    The issue was reported in [1] and discussed [2].
    
    =============================================
    [ INFO: possible recursive locking detected ]
    4.2.0-rc6-00013-g5d050ed-dirty #55 Not tainted
    ---------------------------------------------
    sh/63 is trying to acquire lock:
     (class){......}, at: [<c009b91c>] __irq_get_desc_lock+0x50/0x94
    
    but task is already holding lock:
     (class){......}, at: [<c009b91c>] __irq_get_desc_lock+0x50/0x94
    
    other info that might help us debug this:
     Possible unsafe locking scenario:
    
           CPU0
           ----
      lock(class);
      lock(class);
    
     *** DEADLOCK ***
    
     May be due to missing lock nesting notation
    
    7 locks held by sh/63:
     #0:  (sb_writers#4){.+.+.+}, at: [<c016bbb8>] vfs_write+0x13c/0x164
     #1:  (&of->mutex){+.+.+.}, at: [<c01debf4>] kernfs_fop_write+0x4c/0x1a0
     #2:  (s_active#36){.+.+.+}, at: [<c01debfc>] kernfs_fop_write+0x54/0x1a0
     #3:  (pm_mutex){+.+.+.}, at: [<c009758c>] pm_suspend+0xec/0x4c4
     #4:  (&dev->mutex){......}, at: [<c03f77f8>] __device_suspend+0xd4/0x398
     #5:  (&gpio->lock){+.+.+.}, at: [<c009b940>] __irq_get_desc_lock+0x74/0x94
     #6:  (class){......}, at: [<c009b91c>] __irq_get_desc_lock+0x50/0x94
    
    stack backtrace:
    CPU: 0 PID: 63 Comm: sh Not tainted 4.2.0-rc6-00013-g5d050ed-dirty #55
    Hardware name: Generic DRA74X (Flattened Device Tree)
    [<c0016e24>] (unwind_backtrace) from [<c0013338>] (show_stack+0x10/0x14)
    [<c0013338>] (show_stack) from [<c05f6b24>] (dump_stack+0x84/0x9c)
    [<c05f6b24>] (dump_stack) from [<c00903f4>] (__lock_acquire+0x19c0/0x1e20)
    [<c00903f4>] (__lock_acquire) from [<c0091098>] (lock_acquire+0xa8/0x128)
    [<c0091098>] (lock_acquire) from [<c05fd61c>] (_raw_spin_lock_irqsave+0x38/0x4c)
    [<c05fd61c>] (_raw_spin_lock_irqsave) from [<c009b91c>] (__irq_get_desc_lock+0x50/0x94)
    [<c009b91c>] (__irq_get_desc_lock) from [<c009c4f4>] (irq_set_irq_wake+0x20/0xfc)
    [<c009c4f4>] (irq_set_irq_wake) from [<c0393ac4>] (pcf857x_irq_set_wake+0x24/0x54)
    [<c0393ac4>] (pcf857x_irq_set_wake) from [<c009c560>] (irq_set_irq_wake+0x8c/0xfc)
    [<c009c560>] (irq_set_irq_wake) from [<c04a02ac>] (gpio_keys_suspend+0x70/0xd4)
    [<c04a02ac>] (gpio_keys_suspend) from [<c03f6a00>] (dpm_run_callback+0x50/0x124)
    [<c03f6a00>] (dpm_run_callback) from [<c03f7830>] (__device_suspend+0x10c/0x398)
    [<c03f7830>] (__device_suspend) from [<c03f90f0>] (dpm_suspend+0x134/0x2f4)
    [<c03f90f0>] (dpm_suspend) from [<c0096e20>] (suspend_devices_and_enter+0xa8/0x728)
    [<c0096e20>] (suspend_devices_and_enter) from [<c00977cc>] (pm_suspend+0x32c/0x4c4)
    [<c00977cc>] (pm_suspend) from [<c0096060>] (state_store+0x64/0xb8)
    [<c0096060>] (state_store) from [<c01dec64>] (kernfs_fop_write+0xbc/0x1a0)
    [<c01dec64>] (kernfs_fop_write) from [<c016b280>] (__vfs_write+0x20/0xd8)
    [<c016b280>] (__vfs_write) from [<c016bb0c>] (vfs_write+0x90/0x164)
    [<c016bb0c>] (vfs_write) from [<c016c330>] (SyS_write+0x44/0x9c)
    [<c016c330>] (SyS_write) from [<c000f500>] (ret_fast_syscall+0x0/0x54)
    
    Lets fix it by using separate lockdep class for each registered GPIO
    IRQ Chip. This is done by wrapping gpiochip_irqchip_add call into macros.
    
    The implementation of this patch inspired by solution done by Nicolas
    Boichat for regmap [3]
    
    [1] http://www.spinics.net/lists/linux-gpio/msg05844.html
    [2] http://www.spinics.net/lists/linux-gpio/msg06021.html
    [3] http://www.spinics.net/lists/arm-kernel/msg429834.html
    
    
    
    Cc: Geert Uytterhoeven <geert@linux-m68k.org>
    Cc: Roger Quadros <rogerq@ti.com>
    Reported-by: default avatarRoger Quadros <rogerq@ti.com>
    Tested-by: default avatarRoger Quadros <rogerq@ti.com>
    Signed-off-by: default avatarGrygorii Strashko <grygorii.strashko@ti.com>
    Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
    a0a8bcf4