• Hans de Goede's avatar
    i2c-cht-wc: Fix lockdep warning · 232219b9
    Hans de Goede authored
    When the kernel is build with lockdep support and the i2c-cht-wc driver is
    used, the following warning is shown:
    
    [   66.674334] ======================================================
    [   66.674337] WARNING: possible circular locking dependency detected
    [   66.674340] 5.3.0-rc4+ #83 Not tainted
    [   66.674342] ------------------------------------------------------
    [   66.674345] systemd-udevd/1232 is trying to acquire lock:
    [   66.674349] 00000000a74dab07 (intel_soc_pmic_chtwc:167:(&cht_wc_regmap_cfg)->lock){+.+.}, at: regmap_write+0x31/0x70
    [   66.674360]
                   but task is already holding lock:
    [   66.674362] 00000000d44a85b7 (i2c_register_adapter){+.+.}, at: i2c_smbus_xfer+0x49/0xf0
    [   66.674370]
                   which lock already depends on the new lock.
    
    [   66.674371]
                   the existing dependency chain (in reverse order) is:
    [   66.674374]
                   -> #1 (i2c_register_adapter){+.+.}:
    [   66.674381]        rt_mutex_lock_nested+0x46/0x60
    [   66.674384]        i2c_smbus_xfer+0x49/0xf0
    [   66.674387]        i2c_smbus_read_byte_data+0x45/0x70
    [   66.674391]        cht_wc_byte_reg_read+0x35/0x50
    [   66.674394]        _regmap_read+0x63/0x1a0
    [   66.674396]        _regmap_update_bits+0xa8/0xe0
    [   66.674399]        regmap_update_bits_base+0x63/0xa0
    [   66.674403]        regmap_irq_update_bits.isra.0+0x3b/0x50
    [   66.674406]        regmap_add_irq_chip+0x592/0x7a0
    [   66.674409]        devm_regmap_add_irq_chip+0x89/0xed
    [   66.674412]        cht_wc_probe+0x102/0x158
    [   66.674415]        i2c_device_probe+0x95/0x250
    [   66.674419]        really_probe+0xf3/0x380
    [   66.674422]        driver_probe_device+0x59/0xd0
    [   66.674425]        device_driver_attach+0x53/0x60
    [   66.674428]        __driver_attach+0x92/0x150
    [   66.674431]        bus_for_each_dev+0x7d/0xc0
    [   66.674434]        bus_add_driver+0x14d/0x1f0
    [   66.674437]        driver_register+0x6d/0xb0
    [   66.674440]        i2c_register_driver+0x45/0x80
    [   66.674445]        do_one_initcall+0x60/0x2f4
    [   66.674450]        kernel_init_freeable+0x20d/0x2b4
    [   66.674453]        kernel_init+0xa/0x10c
    [   66.674457]        ret_from_fork+0x3a/0x50
    [   66.674459]
                   -> #0 (intel_soc_pmic_chtwc:167:(&cht_wc_regmap_cfg)->lock){+.+.}:
    [   66.674465]        __lock_acquire+0xe07/0x1930
    [   66.674468]        lock_acquire+0x9d/0x1a0
    [   66.674472]        __mutex_lock+0xa8/0x9a0
    [   66.674474]        regmap_write+0x31/0x70
    [   66.674480]        cht_wc_i2c_adap_smbus_xfer+0x72/0x240 [i2c_cht_wc]
    [   66.674483]        __i2c_smbus_xfer+0x1a3/0x640
    [   66.674486]        i2c_smbus_xfer+0x67/0xf0
    [   66.674489]        i2c_smbus_read_byte_data+0x45/0x70
    [   66.674494]        bq24190_probe+0x26b/0x410 [bq24190_charger]
    [   66.674497]        i2c_device_probe+0x189/0x250
    [   66.674500]        really_probe+0xf3/0x380
    [   66.674503]        driver_probe_device+0x59/0xd0
    [   66.674506]        device_driver_attach+0x53/0x60
    [   66.674509]        __driver_attach+0x92/0x150
    [   66.674512]        bus_for_each_dev+0x7d/0xc0
    [   66.674515]        bus_add_driver+0x14d/0x1f0
    [   66.674518]        driver_register+0x6d/0xb0
    [   66.674521]        i2c_register_driver+0x45/0x80
    [   66.674524]        do_one_initcall+0x60/0x2f4
    [   66.674528]        do_init_module+0x5c/0x230
    [   66.674531]        load_module+0x2707/0x2a20
    [   66.674534]        __do_sys_init_module+0x188/0x1b0
    [   66.674537]        do_syscall_64+0x5c/0xb0
    [   66.674541]        entry_SYSCALL_64_after_hwframe+0x49/0xbe
    [   66.674543]
                   other info that might help us debug this:
    
    [   66.674545]  Possible unsafe locking scenario:
    
    [   66.674547]        CPU0                    CPU1
    [   66.674548]        ----                    ----
    [   66.674550]   lock(i2c_register_adapter);
    [   66.674553]                                lock(intel_soc_pmic_chtwc:167:(&cht_wc_regmap_cfg)->lock);
    [   66.674556]                                lock(i2c_register_adapter);
    [   66.674559]   lock(intel_soc_pmic_chtwc:167:(&cht_wc_regmap_cfg)->lock);
    [   66.674561]
                    *** DEADLOCK ***
    
    The problem is that the CHT Whiskey Cove PMIC's builtin i2c-adapter is
    itself a part of an i2c-client (the PMIC). This means that transfers done
    through it take adapter->bus_lock twice, once for the parent i2c-adapter
    and once for its own bus_lock. Lockdep does not like this nested locking.
    
    To make lockdep happy in the case of busses with muxes, the i2c-core's
    i2c_adapter_lock_bus function calls:
    
     rt_mutex_lock_nested(&adapter->bus_lock, i2c_adapter_depth(adapter));
    
    But i2c_adapter_depth only works when the direct parent of the adapter is
    another adapter, as it is only meant for muxes. In this case there is an
    i2c-client and MFD instantiated platform_device in the parent->child chain
    between the 2 devices.
    
    This commit overrides the default i2c_lock_operations, passing a hardcoded
    depth of 1 to rt_mutex_lock_nested, making lockdep happy.
    
    Note that if there were to be a mux attached to the i2c-wc-cht adapter,
    this would break things again since the i2c-mux code expects the
    root-adapter to have a locking depth of 0. But the i2c-wc-cht adapter
    always has only 1 client directly attached in the form of the charger IC
    paired with the CHT Whiskey Cove PMIC.
    Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
    Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
    232219b9
i2c-cht-wc.c 12.3 KB