diff options
| author | Patrice Chotard <patrice.chotard@st.com> | 2013-04-11 05:01:27 -0400 |
|---|---|---|
| committer | Linus Walleij <linus.walleij@linaro.org> | 2013-04-26 11:01:35 -0400 |
| commit | 42fed7ba44e4e8c1fb27b28ad14490cb1daff3c7 (patch) | |
| tree | 3caafd69ed9807e9a15f14d6c482fa1f1a697a8b | |
| parent | cb6d315dc36ce56bc017051befa9ac9391300eb9 (diff) | |
pinctrl: move subsystem mutex to pinctrl_dev struct
This mutex avoids deadlock in case of use of multiple pin
controllers. Before this modification, by using a global
mutex, deadlock appeared when, for example, a call to
pinctrl_pins_show() locked the pinctrl_mutex, called the
ops->pin_dbg_show of a particular pin controller. If this
pin controller needs I2C access to retrieve configuration
information and I2C driver is using pinctrl to drive its
pins, a call to pinctrl_select_state() try to lock again
pinctrl_mutex which leads to a deadlock.
Notice that the mutex grab from the two direction functions
was moved into pinctrl_gpio_direction().
For several cases, we can't replace pinctrl_mutex by
pctldev->mutex, because at this stage, pctldev is
not accessible :
- pinctrl_get()/pinctrl_put()
- pinctrl_register_maps()
So add respectively pinctrl_list_mutex and
pinctrl_maps_mutex in order to protect
pinctrl_list and pinctrl_maps list instead.
Reintroduce pinctrldev_list_mutex in
find_pinctrl_by_of_node(),
pinctrl_find_and_add_gpio_range()
pinctrl_request_gpio(), pinctrl_free_gpio(),
pinctrl_gpio_direction(), pinctrl_devices_show(),
pinctrl_register() and pinctrl_unregister() to
protect pinctrldev_list.
Changes v2->v3:
- Fix a missing EXPORT_SYMBOL_GPL() for pinctrl_select_state().
Changes v1->v2:
- pinctrl_select_state_locked() is removed, all lock mechanism
is located inside pinctrl_select_state(). When parsing
the state->setting list, take the per-pin-controller driver
lock. (Patrice).
- Introduce pinctrldev_list_mutex to protect pinctrldev_list
in all functions which parse or modify pictrldev_list.
(Patrice).
- move find_pinctrl_by_of_node() from pinctrl/devicetree.c to
pinctrl/core.c in order to protect pinctrldev_list.
(Patrice).
- Sink mutex:es into some functions and remove some _locked
variants down to where the lists are actually accessed to
make things simpler. (Linus)
- Drop *all* mutexes completely from pinctrl_lookup_state()
and pinctrl_select_state() - no relevant mutex was taken
and it was unclear what this was protecting against. (Linus)
Reported by : Seraphin Bonnaffe <seraphin.bonnaffe@stericsson.com>
Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
| -rw-r--r-- | drivers/pinctrl/core.c | 265 | ||||
| -rw-r--r-- | drivers/pinctrl/core.h | 6 | ||||
| -rw-r--r-- | drivers/pinctrl/devicetree.c | 15 | ||||
| -rw-r--r-- | drivers/pinctrl/pinconf.c | 46 | ||||
| -rw-r--r-- | drivers/pinctrl/pinmux.c | 8 |
5 files changed, 176 insertions, 164 deletions
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 8b832ce6a8e3..c3d222ed39a2 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c | |||
| @@ -40,11 +40,17 @@ | |||
| 40 | 40 | ||
| 41 | static bool pinctrl_dummy_state; | 41 | static bool pinctrl_dummy_state; |
| 42 | 42 | ||
| 43 | /* Mutex taken by all entry points */ | 43 | /* Mutex taken to protect pinctrl_list */ |
| 44 | DEFINE_MUTEX(pinctrl_mutex); | 44 | DEFINE_MUTEX(pinctrl_list_mutex); |
| 45 | |||
| 46 | /* Mutex taken to protect pinctrl_maps */ | ||
| 47 | DEFINE_MUTEX(pinctrl_maps_mutex); | ||
| 48 | |||
| 49 | /* Mutex taken to protect pinctrldev_list */ | ||
| 50 | DEFINE_MUTEX(pinctrldev_list_mutex); | ||
| 45 | 51 | ||
| 46 | /* Global list of pin control devices (struct pinctrl_dev) */ | 52 | /* Global list of pin control devices (struct pinctrl_dev) */ |
| 47 | LIST_HEAD(pinctrldev_list); | 53 | static LIST_HEAD(pinctrldev_list); |
| 48 | 54 | ||
| 49 | /* List of pin controller handles (struct pinctrl) */ | 55 | /* List of pin controller handles (struct pinctrl) */ |
| 50 | static LIST_HEAD(pinctrl_list); | 56 | static LIST_HEAD(pinctrl_list); |
| @@ -111,6 +117,23 @@ struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *devname) | |||
| 111 | return found ? pctldev : NULL; | 117 | return found ? pctldev : NULL; |
| 112 | } | 118 | } |
| 113 | 119 | ||
| 120 | struct pinctrl_dev *get_pinctrl_dev_from_of_node(struct device_node *np) | ||
| 121 | { | ||
| 122 | struct pinctrl_dev *pctldev; | ||
| 123 | |||
| 124 | mutex_lock(&pinctrldev_list_mutex); | ||
| 125 | |||
| 126 | list_for_each_entry(pctldev, &pinctrldev_list, node) | ||
| 127 | if (pctldev->dev->of_node == np) { | ||
| 128 | mutex_unlock(&pinctrldev_list_mutex); | ||
| 129 | return pctldev; | ||
| 130 | } | ||
| 131 | |||
| 132 | mutex_lock(&pinctrldev_list_mutex); | ||
| 133 | |||
| 134 | return NULL; | ||
| 135 | } | ||
| 136 | |||
| 114 | /** | 137 | /** |
| 115 | * pin_get_from_name() - look up a pin number from a name | 138 | * pin_get_from_name() - look up a pin number from a name |
| 116 | * @pctldev: the pin control device to lookup the pin on | 139 | * @pctldev: the pin control device to lookup the pin on |
| @@ -170,9 +193,9 @@ bool pin_is_valid(struct pinctrl_dev *pctldev, int pin) | |||
| 170 | if (pin < 0) | 193 | if (pin < 0) |
| 171 | return false; | 194 | return false; |
| 172 | 195 | ||
| 173 | mutex_lock(&pinctrl_mutex); | 196 | mutex_lock(&pctldev->mutex); |
| 174 | pindesc = pin_desc_get(pctldev, pin); | 197 | pindesc = pin_desc_get(pctldev, pin); |
| 175 | mutex_unlock(&pinctrl_mutex); | 198 | mutex_unlock(&pctldev->mutex); |
| 176 | 199 | ||
| 177 | return pindesc != NULL; | 200 | return pindesc != NULL; |
| 178 | } | 201 | } |
| @@ -269,15 +292,17 @@ pinctrl_match_gpio_range(struct pinctrl_dev *pctldev, unsigned gpio) | |||
| 269 | { | 292 | { |
| 270 | struct pinctrl_gpio_range *range = NULL; | 293 | struct pinctrl_gpio_range *range = NULL; |
| 271 | 294 | ||
| 295 | mutex_lock(&pctldev->mutex); | ||
| 272 | /* Loop over the ranges */ | 296 | /* Loop over the ranges */ |
| 273 | list_for_each_entry(range, &pctldev->gpio_ranges, node) { | 297 | list_for_each_entry(range, &pctldev->gpio_ranges, node) { |
| 274 | /* Check if we're in the valid range */ | 298 | /* Check if we're in the valid range */ |
| 275 | if (gpio >= range->base && | 299 | if (gpio >= range->base && |
| 276 | gpio < range->base + range->npins) { | 300 | gpio < range->base + range->npins) { |
| 301 | mutex_unlock(&pctldev->mutex); | ||
| 277 | return range; | 302 | return range; |
| 278 | } | 303 | } |
| 279 | } | 304 | } |
| 280 | 305 | mutex_unlock(&pctldev->mutex); | |
| 281 | return NULL; | 306 | return NULL; |
| 282 | } | 307 | } |
| 283 | 308 | ||
| @@ -361,9 +386,9 @@ static int pinctrl_get_device_gpio_range(unsigned gpio, | |||
| 361 | void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev, | 386 | void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev, |
| 362 | struct pinctrl_gpio_range *range) | 387 | struct pinctrl_gpio_range *range) |
| 363 | { | 388 | { |
| 364 | mutex_lock(&pinctrl_mutex); | 389 | mutex_lock(&pctldev->mutex); |
| 365 | list_add_tail(&range->node, &pctldev->gpio_ranges); | 390 | list_add_tail(&range->node, &pctldev->gpio_ranges); |
| 366 | mutex_unlock(&pinctrl_mutex); | 391 | mutex_unlock(&pctldev->mutex); |
| 367 | } | 392 | } |
| 368 | EXPORT_SYMBOL_GPL(pinctrl_add_gpio_range); | 393 | EXPORT_SYMBOL_GPL(pinctrl_add_gpio_range); |
| 369 | 394 | ||
| @@ -381,17 +406,25 @@ EXPORT_SYMBOL_GPL(pinctrl_add_gpio_ranges); | |||
| 381 | struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname, | 406 | struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname, |
| 382 | struct pinctrl_gpio_range *range) | 407 | struct pinctrl_gpio_range *range) |
| 383 | { | 408 | { |
| 384 | struct pinctrl_dev *pctldev = get_pinctrl_dev_from_devname(devname); | 409 | struct pinctrl_dev *pctldev; |
| 410 | |||
| 411 | mutex_lock(&pinctrldev_list_mutex); | ||
| 412 | |||
| 413 | pctldev = get_pinctrl_dev_from_devname(devname); | ||
| 385 | 414 | ||
| 386 | /* | 415 | /* |
| 387 | * If we can't find this device, let's assume that is because | 416 | * If we can't find this device, let's assume that is because |
| 388 | * it has not probed yet, so the driver trying to register this | 417 | * it has not probed yet, so the driver trying to register this |
| 389 | * range need to defer probing. | 418 | * range need to defer probing. |
| 390 | */ | 419 | */ |
| 391 | if (!pctldev) | 420 | if (!pctldev) { |
| 421 | mutex_unlock(&pinctrldev_list_mutex); | ||
| 392 | return ERR_PTR(-EPROBE_DEFER); | 422 | return ERR_PTR(-EPROBE_DEFER); |
| 393 | 423 | } | |
| 394 | pinctrl_add_gpio_range(pctldev, range); | 424 | pinctrl_add_gpio_range(pctldev, range); |
| 425 | |||
| 426 | mutex_unlock(&pinctrldev_list_mutex); | ||
| 427 | |||
| 395 | return pctldev; | 428 | return pctldev; |
| 396 | } | 429 | } |
| 397 | EXPORT_SYMBOL_GPL(pinctrl_find_and_add_gpio_range); | 430 | EXPORT_SYMBOL_GPL(pinctrl_find_and_add_gpio_range); |
| @@ -407,14 +440,17 @@ pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev, | |||
| 407 | { | 440 | { |
| 408 | struct pinctrl_gpio_range *range = NULL; | 441 | struct pinctrl_gpio_range *range = NULL; |
| 409 | 442 | ||
| 443 | mutex_lock(&pctldev->mutex); | ||
| 410 | /* Loop over the ranges */ | 444 | /* Loop over the ranges */ |
| 411 | list_for_each_entry(range, &pctldev->gpio_ranges, node) { | 445 | list_for_each_entry(range, &pctldev->gpio_ranges, node) { |
| 412 | /* Check if we're in the valid range */ | 446 | /* Check if we're in the valid range */ |
| 413 | if (pin >= range->pin_base && | 447 | if (pin >= range->pin_base && |
| 414 | pin < range->pin_base + range->npins) { | 448 | pin < range->pin_base + range->npins) { |
| 449 | mutex_unlock(&pctldev->mutex); | ||
| 415 | return range; | 450 | return range; |
| 416 | } | 451 | } |
| 417 | } | 452 | } |
| 453 | mutex_unlock(&pctldev->mutex); | ||
| 418 | 454 | ||
| 419 | return NULL; | 455 | return NULL; |
| 420 | } | 456 | } |
| @@ -428,9 +464,9 @@ EXPORT_SYMBOL_GPL(pinctrl_find_gpio_range_from_pin); | |||
| 428 | void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev, | 464 | void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev, |
| 429 | struct pinctrl_gpio_range *range) | 465 | struct pinctrl_gpio_range *range) |
| 430 | { | 466 | { |
| 431 | mutex_lock(&pinctrl_mutex); | 467 | mutex_lock(&pctldev->mutex); |
| 432 | list_del(&range->node); | 468 | list_del(&range->node); |
| 433 | mutex_unlock(&pinctrl_mutex); | 469 | mutex_unlock(&pctldev->mutex); |
| 434 | } | 470 | } |
| 435 | EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range); | 471 | EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range); |
| 436 | 472 | ||
| @@ -481,13 +517,13 @@ int pinctrl_request_gpio(unsigned gpio) | |||
| 481 | int ret; | 517 | int ret; |
| 482 | int pin; | 518 | int pin; |
| 483 | 519 | ||
