| From a64b1a34d23f8e892b182cf9def35ae7b5a6832d Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 31 Jul 2020 14:38:36 +0200 |
| Subject: gpio: don't use same lockdep class for all devm_gpiochip_add_data |
| users |
| |
| From: Ahmad Fatoum <a.fatoum@pengutronix.de> |
| |
| [ Upstream commit 5f402bb17533113c21d61c2d4bc4ef4a6fa1c9a5 ] |
| |
| Commit 959bc7b22bd2 ("gpio: Automatically add lockdep keys") documents |
| in its commits message its intention to "create a unique class key for |
| each driver". |
| |
| It does so by having gpiochip_add_data add in-place the definition of |
| two static lockdep classes for LOCKDEP use. That way, every caller of |
| the macro adds their gpiochip with unique lockdep classes. |
| |
| There are many indirect callers of gpiochip_add_data, however, via |
| use of devm_gpiochip_add_data. devm_gpiochip_add_data has external |
| linkage and all its users will share the same lockdep classes, which |
| probably is not intended. |
| |
| Fix this by replicating the gpio_chip_add_data statics-in-macro for |
| the devm_ version as well. |
| |
| Fixes: 959bc7b22bd2 ("gpio: Automatically add lockdep keys") |
| Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> |
| Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> |
| Reviewed-by: Bartosz Golaszewski <bgolaszewski@baylibre.com> |
| Link: https://lore.kernel.org/r/20200731123835.8003-1-a.fatoum@pengutronix.de |
| Signed-off-by: Linus Walleij <linus.walleij@linaro.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/gpio/gpiolib-devres.c | 13 ++++++++----- |
| include/linux/gpio/driver.h | 13 +++++++++++-- |
| 2 files changed, 19 insertions(+), 7 deletions(-) |
| |
| diff --git a/drivers/gpio/gpiolib-devres.c b/drivers/gpio/gpiolib-devres.c |
| index 5c91c4365da1f..7dbce4c4ebdf4 100644 |
| --- a/drivers/gpio/gpiolib-devres.c |
| +++ b/drivers/gpio/gpiolib-devres.c |
| @@ -487,10 +487,12 @@ static void devm_gpio_chip_release(struct device *dev, void *res) |
| } |
| |
| /** |
| - * devm_gpiochip_add_data() - Resource managed gpiochip_add_data() |
| + * devm_gpiochip_add_data_with_key() - Resource managed gpiochip_add_data_with_key() |
| * @dev: pointer to the device that gpio_chip belongs to. |
| * @gc: the GPIO chip to register |
| * @data: driver-private data associated with this chip |
| + * @lock_key: lockdep class for IRQ lock |
| + * @request_key: lockdep class for IRQ request |
| * |
| * Context: potentially before irqs will work |
| * |
| @@ -501,8 +503,9 @@ static void devm_gpio_chip_release(struct device *dev, void *res) |
| * gc->base is invalid or already associated with a different chip. |
| * Otherwise it returns zero as a success code. |
| */ |
| -int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *gc, |
| - void *data) |
| +int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc, void *data, |
| + struct lock_class_key *lock_key, |
| + struct lock_class_key *request_key) |
| { |
| struct gpio_chip **ptr; |
| int ret; |
| @@ -512,7 +515,7 @@ int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *gc, |
| if (!ptr) |
| return -ENOMEM; |
| |
| - ret = gpiochip_add_data(gc, data); |
| + ret = gpiochip_add_data_with_key(gc, data, lock_key, request_key); |
| if (ret < 0) { |
| devres_free(ptr); |
| return ret; |
| @@ -523,4 +526,4 @@ int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *gc, |
| |
| return 0; |
| } |
| -EXPORT_SYMBOL_GPL(devm_gpiochip_add_data); |
| +EXPORT_SYMBOL_GPL(devm_gpiochip_add_data_with_key); |
| diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h |
| index b8fc92c177eba..e4a00bb42427c 100644 |
| --- a/include/linux/gpio/driver.h |
| +++ b/include/linux/gpio/driver.h |
| @@ -496,8 +496,16 @@ extern int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, |
| gpiochip_add_data_with_key(gc, data, &lock_key, \ |
| &request_key); \ |
| }) |
| +#define devm_gpiochip_add_data(dev, gc, data) ({ \ |
| + static struct lock_class_key lock_key; \ |
| + static struct lock_class_key request_key; \ |
| + devm_gpiochip_add_data_with_key(dev, gc, data, &lock_key, \ |
| + &request_key); \ |
| + }) |
| #else |
| #define gpiochip_add_data(gc, data) gpiochip_add_data_with_key(gc, data, NULL, NULL) |
| +#define devm_gpiochip_add_data(dev, gc, data) \ |
| + devm_gpiochip_add_data_with_key(dev, gc, data, NULL, NULL) |
| #endif /* CONFIG_LOCKDEP */ |
| |
| static inline int gpiochip_add(struct gpio_chip *gc) |
| @@ -505,8 +513,9 @@ static inline int gpiochip_add(struct gpio_chip *gc) |
| return gpiochip_add_data(gc, NULL); |
| } |
| extern void gpiochip_remove(struct gpio_chip *gc); |
| -extern int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *gc, |
| - void *data); |
| +extern int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc, void *data, |
| + struct lock_class_key *lock_key, |
| + struct lock_class_key *request_key); |
| |
| extern struct gpio_chip *gpiochip_find(void *data, |
| int (*match)(struct gpio_chip *gc, void *data)); |
| -- |
| 2.25.1 |
| |