From 559b46990e7635758d7350a4385d63682b181ed1 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 16 Sep 2016 18:02:45 +0200 Subject: 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 Acked-by: Peter Rosin Acked-by: Peter Zijlstra (Intel) Acked-by: Linus Walleij Signed-off-by: Wolfram Sang --- drivers/gpio/gpio-pca953x.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpio') 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. -- cgit v1.2.3-59-g8ed1b From 6212e1d6ed4018ae3d3e6079ea0c45df346c97a6 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 24 Sep 2016 11:06:29 +0200 Subject: gpio: pca953x: variable 'id' was used twice sparse rightfully said: drivers/gpio/gpio-pca953x.c:771:45: warning: symbol 'id' shadows an earlier one drivers/gpio/gpio-pca953x.c:742:36: originally declared here So, name them explicitly 'i2c_id' and 'acpi_id' to avoid any confusion. Signed-off-by: Wolfram Sang --- drivers/gpio/gpio-pca953x.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 892dc043f40b..018f39cc19c8 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -739,7 +739,7 @@ out: static const struct of_device_id pca953x_dt_ids[]; static int pca953x_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *i2c_id) { struct pca953x_platform_data *pdata; struct pca953x_chip *chip; @@ -765,21 +765,21 @@ static int pca953x_probe(struct i2c_client *client, chip->client = client; - if (id) { - chip->driver_data = id->driver_data; + if (i2c_id) { + chip->driver_data = i2c_id->driver_data; } else { - const struct acpi_device_id *id; + const struct acpi_device_id *acpi_id; const struct of_device_id *match; match = of_match_device(pca953x_dt_ids, &client->dev); if (match) { chip->driver_data = (int)(uintptr_t)match->data; } else { - id = acpi_match_device(pca953x_acpi_ids, &client->dev); - if (!id) + acpi_id = acpi_match_device(pca953x_acpi_ids, &client->dev); + if (!acpi_id) return -ENODEV; - chip->driver_data = id->driver_data; + chip->driver_data = acpi_id->driver_data; } } -- cgit v1.2.3-59-g8ed1b