From b18537cd8ec2e5280ba19d24ea8812b80e5b3208 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Thu, 25 Feb 2016 22:44:37 +0100 Subject: [PATCH] pinctrl: core: create nolock version of pinctrl_find_gpio_range_from_pin pinctrl_find_gpio_range_from_pin takes the pctldev->mutex but so does pinconf_pins_show and this will cause a deadlock if pinctrl_find_gpio_range_from_pin is used in .pin_config_get callback. Create a nolock version of pinctrl_find_gpio_range_from_pin to allow pin to gpio lookup to be used from pinconf_pins_show. Signed-off-by: Joachim Eastwood Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 35 +++++++++++++++++++++++------------ drivers/pinctrl/core.h | 4 ++++ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 2686a4450dfc..f67a8b7a4e18 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -481,18 +481,12 @@ int pinctrl_get_group_pins(struct pinctrl_dev *pctldev, const char *pin_group, } EXPORT_SYMBOL_GPL(pinctrl_get_group_pins); -/** - * pinctrl_find_gpio_range_from_pin() - locate the GPIO range for a pin - * @pctldev: the pin controller device to look in - * @pin: a controller-local number to find the range for - */ struct pinctrl_gpio_range * -pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev, - unsigned int pin) +pinctrl_find_gpio_range_from_pin_nolock(struct pinctrl_dev *pctldev, + unsigned int pin) { struct pinctrl_gpio_range *range; - mutex_lock(&pctldev->mutex); /* Loop over the ranges */ list_for_each_entry(range, &pctldev->gpio_ranges, node) { /* Check if we're in the valid range */ @@ -500,15 +494,32 @@ pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev, int a; for (a = 0; a < range->npins; a++) { if (range->pins[a] == pin) - goto out; + return range; } } else if (pin >= range->pin_base && pin < range->pin_base + range->npins) - goto out; + return range; } - range = NULL; -out: + + return NULL; +} +EXPORT_SYMBOL_GPL(pinctrl_find_gpio_range_from_pin_nolock); + +/** + * pinctrl_find_gpio_range_from_pin() - locate the GPIO range for a pin + * @pctldev: the pin controller device to look in + * @pin: a controller-local number to find the range for + */ +struct pinctrl_gpio_range * +pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev, + unsigned int pin) +{ + struct pinctrl_gpio_range *range; + + mutex_lock(&pctldev->mutex); + range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin); mutex_unlock(&pctldev->mutex); + return range; } EXPORT_SYMBOL_GPL(pinctrl_find_gpio_range_from_pin); diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index b24ea846c867..ca08723b9ee1 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h @@ -182,6 +182,10 @@ static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, return radix_tree_lookup(&pctldev->pin_desc_tree, pin); } +extern struct pinctrl_gpio_range * +pinctrl_find_gpio_range_from_pin_nolock(struct pinctrl_dev *pctldev, + unsigned int pin); + int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps, bool dup); void pinctrl_unregister_map(struct pinctrl_map const *map); -- 2.20.1