diff options
author | Bartosz Golaszewski <bgolaszewski@baylibre.com> | 2016-09-16 18:02:45 +0200 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2016-09-24 10:53:14 +0200 |
commit | 559b46990e7635758d7350a4385d63682b181ed1 (patch) | |
tree | b09df43deaffb3ebe44921b588b2574d6e074c9c /drivers/gpio/gpio-pca953x.c | |
parent | i2c: add a warning to i2c_adapter_depth() (diff) | |
download | linux-559b46990e7635758d7350a4385d63682b181ed1.tar.xz linux-559b46990e7635758d7350a4385d63682b181ed1.zip |
gpio: pca953x: fix an incorrect lockdep warning
If an I2C GPIO multiplexer is driven by a GPIO provided by an expander
when there's a second expander using the same device driver on one of
the I2C bus segments, lockdep prints a deadlock warning when trying to
set the direction or the value of the GPIOs provided by the second
expander.
The below diagram presents the setup:
- - - - -
------- --------- Bus segment 1 | |
| | | |--------------- Devices
| | SCL/SDA | | | |
| Linux |-----------| I2C MUX | - - - - -
| | | | | Bus segment 2
| | | | |-------------------
------- | --------- |
| | - - - - -
------------ | MUX GPIO | |
| | | Devices
| GPIO | | | |
| Expander 1 |---- - - - - -
| | |
------------ | SCL/SDA
|
------------
| |
| GPIO |
| Expander 2 |
| |
------------
The reason for lockdep warning is that we take the chip->i2c_lock in
pca953x_gpio_set_value() or pca953x_gpio_direction_output() and then
come right back to pca953x_gpio_set_value() when the GPIO mux kicks
in. The locks actually protect different expanders, but for lockdep
both are of the same class, so it says:
Possible unsafe locking scenario:
CPU0
----
lock(&chip->i2c_lock);
lock(&chip->i2c_lock);
*** DEADLOCK ***
May be due to missing lock nesting notation
In order to get rid of the warning, retrieve the adapter nesting depth
and use it as lockdep subclass for chip->i2c_lock.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Acked-by: Peter Rosin <peda@axentia.se>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/gpio/gpio-pca953x.c')
-rw-r--r-- | drivers/gpio/gpio-pca953x.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 02f2a5621bb0..892dc043f40b 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -786,6 +786,8 @@ static int pca953x_probe(struct i2c_client *client, chip->chip_type = PCA_CHIP_TYPE(chip->driver_data); mutex_init(&chip->i2c_lock); + lockdep_set_subclass(&chip->i2c_lock, + i2c_adapter_depth(client->adapter)); /* initialize cached registers from their original values. * we can't share this chip with another i2c master. |