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 | 41 ++++++++++++++++++++++++++--------------- drivers/pinctrl/core.h | 4 ++++ 2 files changed, 30 insertions(+), 15 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,6 +481,30 @@ int pinctrl_get_group_pins(struct pinctrl_dev *pctldev, const char *pin_group, } EXPORT_SYMBOL_GPL(pinctrl_get_group_pins); +struct pinctrl_gpio_range * +pinctrl_find_gpio_range_from_pin_nolock(struct pinctrl_dev *pctldev, + unsigned int pin) +{ + struct pinctrl_gpio_range *range; + + /* Loop over the ranges */ + list_for_each_entry(range, &pctldev->gpio_ranges, node) { + /* Check if we're in the valid range */ + if (range->pins) { + int a; + for (a = 0; a < range->npins; a++) { + if (range->pins[a] == pin) + return range; + } + } else if (pin >= range->pin_base && + pin < range->pin_base + range->npins) + return range; + } + + 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 @@ -493,22 +517,9 @@ pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev, 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 */ - if (range->pins) { - int a; - for (a = 0; a < range->npins; a++) { - if (range->pins[a] == pin) - goto out; - } - } else if (pin >= range->pin_base && - pin < range->pin_base + range->npins) - goto out; - } - range = NULL; -out: + 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);