pinctrl: core: create nolock version of pinctrl_find_gpio_range_from_pin
authorJoachim Eastwood <manabian@gmail.com>
Thu, 25 Feb 2016 21:44:37 +0000 (22:44 +0100)
committerLinus Walleij <linus.walleij@linaro.org>
Mon, 7 Mar 2016 03:41:20 +0000 (10:41 +0700)
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 <manabian@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/pinctrl/core.c
drivers/pinctrl/core.h

index 2686a4450dfc3261029d560d2ce9838191fbf39c..f67a8b7a4e18252338c54c282152b78971d34225 100644 (file)
@@ -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);
index b24ea846c8677ebea49ffd435c04c3de40f226b9..ca08723b9ee1e90fdfc792666cc7491ad5fc492e 100644 (file)
@@ -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);