From b17d1bf16cc72a374a48d748940f700009d40ff4 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 11 Feb 2015 11:52:37 +0100 Subject: gpio: make flags mandatory for gpiod_get functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that all[1] users of the gpiod_get functions are converted to make use of the up to now optional flags parameter, make it mandatory which allows to remove some cpp magic. [1] all but etraxfs-uart which is broken anyhow and I'm allowed to ignore it by Jesper Nilsson :-) Acked-by: Alexandre Courbot Signed-off-by: Uwe Kleine-König --- include/linux/gpio/consumer.h | 82 ++++++++++++------------------------------- 1 file changed, 23 insertions(+), 59 deletions(-) (limited to 'include/linux/gpio') diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index adac255aee86..14cac67c2012 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -47,17 +47,17 @@ enum gpiod_flags { int gpiod_count(struct device *dev, const char *con_id); /* Acquire and dispose GPIOs */ -struct gpio_desc *__must_check __gpiod_get(struct device *dev, +struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id, enum gpiod_flags flags); -struct gpio_desc *__must_check __gpiod_get_index(struct device *dev, +struct gpio_desc *__must_check gpiod_get_index(struct device *dev, const char *con_id, unsigned int idx, enum gpiod_flags flags); -struct gpio_desc *__must_check __gpiod_get_optional(struct device *dev, +struct gpio_desc *__must_check gpiod_get_optional(struct device *dev, const char *con_id, enum gpiod_flags flags); -struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev, +struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev, const char *con_id, unsigned int index, enum gpiod_flags flags); @@ -70,18 +70,18 @@ struct gpio_descs *__must_check gpiod_get_array_optional(struct device *dev, void gpiod_put(struct gpio_desc *desc); void gpiod_put_array(struct gpio_descs *descs); -struct gpio_desc *__must_check __devm_gpiod_get(struct device *dev, +struct gpio_desc *__must_check devm_gpiod_get(struct device *dev, const char *con_id, enum gpiod_flags flags); -struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev, +struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, const char *con_id, unsigned int idx, enum gpiod_flags flags); -struct gpio_desc *__must_check __devm_gpiod_get_optional(struct device *dev, +struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev, const char *con_id, enum gpiod_flags flags); struct gpio_desc *__must_check -__devm_gpiod_get_index_optional(struct device *dev, const char *con_id, +devm_gpiod_get_index_optional(struct device *dev, const char *con_id, unsigned int index, enum gpiod_flags flags); struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev, const char *con_id, @@ -146,31 +146,31 @@ static inline int gpiod_count(struct device *dev, const char *con_id) return 0; } -static inline struct gpio_desc *__must_check __gpiod_get(struct device *dev, - const char *con_id, - enum gpiod_flags flags) +static inline struct gpio_desc *__must_check gpiod_get(struct device *dev, + const char *con_id, + enum gpiod_flags flags) { return ERR_PTR(-ENOSYS); } static inline struct gpio_desc *__must_check -__gpiod_get_index(struct device *dev, - const char *con_id, - unsigned int idx, - enum gpiod_flags flags) +gpiod_get_index(struct device *dev, + const char *con_id, + unsigned int idx, + enum gpiod_flags flags) { return ERR_PTR(-ENOSYS); } static inline struct gpio_desc *__must_check -__gpiod_get_optional(struct device *dev, const char *con_id, - enum gpiod_flags flags) +gpiod_get_optional(struct device *dev, const char *con_id, + enum gpiod_flags flags) { return ERR_PTR(-ENOSYS); } static inline struct gpio_desc *__must_check -__gpiod_get_index_optional(struct device *dev, const char *con_id, - unsigned int index, enum gpiod_flags flags) +gpiod_get_index_optional(struct device *dev, const char *con_id, + unsigned int index, enum gpiod_flags flags) { return ERR_PTR(-ENOSYS); } @@ -206,7 +206,7 @@ static inline void gpiod_put_array(struct gpio_descs *descs) } static inline struct gpio_desc *__must_check -__devm_gpiod_get(struct device *dev, +devm_gpiod_get(struct device *dev, const char *con_id, enum gpiod_flags flags) { @@ -214,7 +214,7 @@ __devm_gpiod_get(struct device *dev, } static inline struct gpio_desc *__must_check -__devm_gpiod_get_index(struct device *dev, +devm_gpiod_get_index(struct device *dev, const char *con_id, unsigned int idx, enum gpiod_flags flags) @@ -223,14 +223,14 @@ __devm_gpiod_get_index(struct device *dev, } static inline struct gpio_desc *__must_check -__devm_gpiod_get_optional(struct device *dev, const char *con_id, +devm_gpiod_get_optional(struct device *dev, const char *con_id, enum gpiod_flags flags) { return ERR_PTR(-ENOSYS); } static inline struct gpio_desc *__must_check -__devm_gpiod_get_index_optional(struct device *dev, const char *con_id, +devm_gpiod_get_index_optional(struct device *dev, const char *con_id, unsigned int index, enum gpiod_flags flags) { return ERR_PTR(-ENOSYS); @@ -424,42 +424,6 @@ static inline struct gpio_desc *devm_get_gpiod_from_child( #endif /* CONFIG_GPIOLIB */ -/* - * Vararg-hacks! This is done to transition the kernel to always pass - * the options flags argument to the below functions. During a transition - * phase these vararg macros make both old-and-newstyle code compile, - * but when all calls to the elder API are removed, these should go away - * and the __gpiod_get() etc functions above be renamed just gpiod_get() - * etc. - */ -#define __gpiod_get(dev, con_id, flags, ...) __gpiod_get(dev, con_id, flags) -#define gpiod_get(varargs...) __gpiod_get(varargs, GPIOD_ASIS) -#define __gpiod_get_index(dev, con_id, index, flags, ...) \ - __gpiod_get_index(dev, con_id, index, flags) -#define gpiod_get_index(varargs...) __gpiod_get_index(varargs, GPIOD_ASIS) -#define __gpiod_get_optional(dev, con_id, flags, ...) \ - __gpiod_get_optional(dev, con_id, flags) -#define gpiod_get_optional(varargs...) __gpiod_get_optional(varargs, GPIOD_ASIS) -#define __gpiod_get_index_optional(dev, con_id, index, flags, ...) \ - __gpiod_get_index_optional(dev, con_id, index, flags) -#define gpiod_get_index_optional(varargs...) \ - __gpiod_get_index_optional(varargs, GPIOD_ASIS) -#define __devm_gpiod_get(dev, con_id, flags, ...) \ - __devm_gpiod_get(dev, con_id, flags) -#define devm_gpiod_get(varargs...) __devm_gpiod_get(varargs, GPIOD_ASIS) -#define __devm_gpiod_get_index(dev, con_id, index, flags, ...) \ - __devm_gpiod_get_index(dev, con_id, index, flags) -#define devm_gpiod_get_index(varargs...) \ - __devm_gpiod_get_index(varargs, GPIOD_ASIS) -#define __devm_gpiod_get_optional(dev, con_id, flags, ...) \ - __devm_gpiod_get_optional(dev, con_id, flags) -#define devm_gpiod_get_optional(varargs...) \ - __devm_gpiod_get_optional(varargs, GPIOD_ASIS) -#define __devm_gpiod_get_index_optional(dev, con_id, index, flags, ...) \ - __devm_gpiod_get_index_optional(dev, con_id, index, flags) -#define devm_gpiod_get_index_optional(varargs...) \ - __devm_gpiod_get_index_optional(varargs, GPIOD_ASIS) - #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) int gpiod_export(struct gpio_desc *desc, bool direction_may_change); -- cgit v1.2.3-71-gd317 From be9015abb8296d8dc72cef4da75fa30e88ab7c81 Mon Sep 17 00:00:00 2001 From: Shobhit Kumar Date: Fri, 26 Jun 2015 14:32:04 +0530 Subject: gpiolib: Add support for removing registered consumer lookup table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case we unload and load a driver module again that is registering a lookup table, without this it will result in multiple entries. Provide an option to remove the lookup table on driver unload Cc: Samuel Ortiz Cc: Linus Walleij Cc: Alexandre Courbot Cc: Thierry Reding Reviewed-by: Alexandre Courbot Reviewed-by: Linus Walleij Tested-by: Ville Syrjälä Signed-off-by: Shobhit Kumar Acked-by: Lee Jones Signed-off-by: Daniel Vetter --- drivers/gpio/gpiolib.c | 13 +++++++++++++ include/linux/gpio/machine.h | 1 + 2 files changed, 14 insertions(+) (limited to 'include/linux/gpio') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index bf4bd1d120c3..f25dc880b007 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1672,6 +1672,19 @@ void gpiod_add_lookup_table(struct gpiod_lookup_table *table) mutex_unlock(&gpio_lookup_lock); } +/** + * gpiod_remove_lookup_table() - unregister GPIO device consumers + * @table: table of consumers to unregister + */ +void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) +{ + mutex_lock(&gpio_lookup_lock); + + list_del(&table->list); + + mutex_unlock(&gpio_lookup_lock); +} + static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, unsigned int idx, enum gpio_lookup_flags *flags) diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index e2706140eaff..c0d712d22b07 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h @@ -57,5 +57,6 @@ struct gpiod_lookup_table { } void gpiod_add_lookup_table(struct gpiod_lookup_table *table); +void gpiod_remove_lookup_table(struct gpiod_lookup_table *table); #endif /* __LINUX_GPIO_MACHINE_H */ -- cgit v1.2.3-71-gd317 From a0a8bcf4670c2c696e6e83742539a5e0dd7a62d6 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Mon, 17 Aug 2015 15:35:23 +0300 Subject: gpiolib: irqchip: use different lockdep class for each gpio irqchip 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: [] __irq_get_desc_lock+0x50/0x94 but task is already holding lock: (class){......}, at: [] __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: [] vfs_write+0x13c/0x164 #1: (&of->mutex){+.+.+.}, at: [] kernfs_fop_write+0x4c/0x1a0 #2: (s_active#36){.+.+.+}, at: [] kernfs_fop_write+0x54/0x1a0 #3: (pm_mutex){+.+.+.}, at: [] pm_suspend+0xec/0x4c4 #4: (&dev->mutex){......}, at: [] __device_suspend+0xd4/0x398 #5: (&gpio->lock){+.+.+.}, at: [] __irq_get_desc_lock+0x74/0x94 #6: (class){......}, at: [] __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) [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0x84/0x9c) [] (dump_stack) from [] (__lock_acquire+0x19c0/0x1e20) [] (__lock_acquire) from [] (lock_acquire+0xa8/0x128) [] (lock_acquire) from [] (_raw_spin_lock_irqsave+0x38/0x4c) [] (_raw_spin_lock_irqsave) from [] (__irq_get_desc_lock+0x50/0x94) [] (__irq_get_desc_lock) from [] (irq_set_irq_wake+0x20/0xfc) [] (irq_set_irq_wake) from [] (pcf857x_irq_set_wake+0x24/0x54) [] (pcf857x_irq_set_wake) from [] (irq_set_irq_wake+0x8c/0xfc) [] (irq_set_irq_wake) from [] (gpio_keys_suspend+0x70/0xd4) [] (gpio_keys_suspend) from [] (dpm_run_callback+0x50/0x124) [] (dpm_run_callback) from [] (__device_suspend+0x10c/0x398) [] (__device_suspend) from [] (dpm_suspend+0x134/0x2f4) [] (dpm_suspend) from [] (suspend_devices_and_enter+0xa8/0x728) [] (suspend_devices_and_enter) from [] (pm_suspend+0x32c/0x4c4) [] (pm_suspend) from [] (state_store+0x64/0xb8) [] (state_store) from [] (kernfs_fop_write+0xbc/0x1a0) [] (kernfs_fop_write) from [] (__vfs_write+0x20/0xd8) [] (__vfs_write) from [] (vfs_write+0x90/0x164) [] (vfs_write) from [] (SyS_write+0x44/0x9c) [] (SyS_write) from [] (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 Cc: Roger Quadros Reported-by: Roger Quadros Tested-by: Roger Quadros Signed-off-by: Grygorii Strashko Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 27 ++++++++++++++------------- include/linux/gpio/driver.h | 26 +++++++++++++++++++++----- 2 files changed, 35 insertions(+), 18 deletions(-) (limited to 'include/linux/gpio') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 34f95fbc884a..b562dd36c4af 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -462,12 +462,6 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, } EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip); -/* - * This lock class tells lockdep that GPIO irqs are in a different - * category than their parents, so it won't report false recursion. - */ -static struct lock_class_key gpiochip_irq_lock_class; - /** * gpiochip_irq_map() - maps an IRQ into a GPIO irqchip * @d: the irqdomain used by this irqchip @@ -484,7 +478,11 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, struct gpio_chip *chip = d->host_data; irq_set_chip_data(irq, chip); - irq_set_lockdep_class(irq, &gpiochip_irq_lock_class); + /* + * This lock class tells lockdep that GPIO irqs are in a different + * category than their parents, so it won't report false recursion. + */ + irq_set_lockdep_class(irq, chip->lock_key); irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler); /* Chips that can sleep need nested thread handlers */ if (chip->can_sleep && !chip->irq_not_threaded) @@ -589,6 +587,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) * @handler: the irq handler to use (often a predefined irq core function) * @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE * to have the core avoid setting up any default type in the hardware. + * @lock_key: lockdep class * * This function closely associates a certain irqchip with a certain * gpiochip, providing an irq domain to translate the local IRQs to @@ -604,11 +603,12 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) * the pins on the gpiochip can generate a unique IRQ. Everything else * need to be open coded. */ -int gpiochip_irqchip_add(struct gpio_chip *gpiochip, - struct irq_chip *irqchip, - unsigned int first_irq, - irq_flow_handler_t handler, - unsigned int type) +int _gpiochip_irqchip_add(struct gpio_chip *gpiochip, + struct irq_chip *irqchip, + unsigned int first_irq, + irq_flow_handler_t handler, + unsigned int type, + struct lock_class_key *lock_key) { struct device_node *of_node; unsigned int offset; @@ -634,6 +634,7 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip, gpiochip->irq_handler = handler; gpiochip->irq_default_type = type; gpiochip->to_irq = gpiochip_to_irq; + gpiochip->lock_key = lock_key; gpiochip->irqdomain = irq_domain_add_simple(of_node, gpiochip->ngpio, first_irq, &gpiochip_domain_ops, gpiochip); @@ -671,7 +672,7 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip, return 0; } -EXPORT_SYMBOL_GPL(gpiochip_irqchip_add); +EXPORT_SYMBOL_GPL(_gpiochip_irqchip_add); #else /* CONFIG_GPIOLIB_IRQCHIP */ diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index c8393cd4d44f..0c7004dab437 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -6,6 +6,7 @@ #include #include #include +#include #include struct device; @@ -126,6 +127,7 @@ struct gpio_chip { irq_flow_handler_t irq_handler; unsigned int irq_default_type; int irq_parent; + struct lock_class_key *lock_key; #endif #if defined(CONFIG_OF_GPIO) @@ -171,11 +173,25 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, int parent_irq, irq_flow_handler_t parent_handler); -int gpiochip_irqchip_add(struct gpio_chip *gpiochip, - struct irq_chip *irqchip, - unsigned int first_irq, - irq_flow_handler_t handler, - unsigned int type); +int _gpiochip_irqchip_add(struct gpio_chip *gpiochip, + struct irq_chip *irqchip, + unsigned int first_irq, + irq_flow_handler_t handler, + unsigned int type, + struct lock_class_key *lock_key); + +#ifdef CONFIG_LOCKDEP +#define gpiochip_irqchip_add(...) \ +( \ + ({ \ + static struct lock_class_key _key; \ + _gpiochip_irqchip_add(__VA_ARGS__, &_key); \ + }) \ +) +#else +#define gpiochip_irqchip_add(...) \ + _gpiochip_irqchip_add(__VA_ARGS__, NULL) +#endif #endif /* CONFIG_GPIOLIB_IRQCHIP */ -- cgit v1.2.3-71-gd317 From 41d6bb4c890c8db01248b1bdd512a18e7bd29ca3 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Mon, 17 Aug 2015 15:35:24 +0300 Subject: gpiolib: add description for gpio irqchip fields in struct gpio_chip Add missed description for GPIO irqchip fields in struct gpio_chip. Signed-off-by: Grygorii Strashko Signed-off-by: Linus Walleij --- include/linux/gpio/driver.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'include/linux/gpio') diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 0c7004dab437..1aed31c5ffba 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -65,6 +65,17 @@ struct seq_file; * registers. * @irq_not_threaded: flag must be set if @can_sleep is set but the * IRQs don't need to be threaded + * @irqchip: GPIO IRQ chip impl, provided by GPIO driver + * @irqdomain: Interrupt translation domain; responsible for mapping + * between GPIO hwirq number and linux irq number + * @irq_base: first linux IRQ number assigned to GPIO IRQ chip (deprecated) + * @irq_handler: the irq handler to use (often a predefined irq core function) + * for GPIO IRQs, provided by GPIO driver + * @irq_default_type: default IRQ triggering type applied during GPIO driver + * initialization, provided by GPIO driver + * @irq_parent: GPIO IRQ chip parent/bank linux irq number, + * provided by GPIO driver + * @lock_key: per GPIO IRQ chip lockdep class * * A gpio_chip can help platforms abstract various sources of GPIOs so * they can all be accessed through a common programing interface. -- cgit v1.2.3-71-gd317