diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2013-08-30 03:41:45 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-09-03 08:08:28 -0400 |
commit | be1a4b13089b1e18da83a549d49163ccad3c19ba (patch) | |
tree | 321f0e432ef3df8f7ea17a664087e58d3f24a7c6 /drivers/gpio | |
parent | 6c17aa0138a6c55364936bbaa35846e09a4db53b (diff) |
gpio: improve error path in gpiolib
At several places the gpiolib will proceed to handle a GPIO
descriptor even if it's ->chip member is NULL and no gpiochip
is associated.
Fix this by checking that both the descriptor cookie *and*
the chip pointer are valid.
Also bail out earlier with more specific diagnostic messages
on missing operations for setting as input/output or debounce.
ChangeLog v1->v2:
- Also return -EIO on gpiod_set_debounce() with missing
operations in the vtable
- Fix indentations.
Suggested-by: Alexandre Courbot <acourbot@nvidia.com>
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Reviewed-by: Frank Rowand <frank.rowand@sonymobile.com>
Cc: Tim Bird <tim.bird@sonymobile.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpiolib.c | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index d6413b2e0844..0cbdddab4ff2 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -1398,7 +1398,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) | |||
1398 | int status = -EPROBE_DEFER; | 1398 | int status = -EPROBE_DEFER; |
1399 | unsigned long flags; | 1399 | unsigned long flags; |
1400 | 1400 | ||
1401 | if (!desc) { | 1401 | if (!desc || !desc->chip) { |
1402 | pr_warn("%s: invalid GPIO\n", __func__); | 1402 | pr_warn("%s: invalid GPIO\n", __func__); |
1403 | return -EINVAL; | 1403 | return -EINVAL; |
1404 | } | 1404 | } |
@@ -1406,8 +1406,6 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) | |||
1406 | spin_lock_irqsave(&gpio_lock, flags); | 1406 | spin_lock_irqsave(&gpio_lock, flags); |
1407 | 1407 | ||
1408 | chip = desc->chip; | 1408 | chip = desc->chip; |
1409 | if (chip == NULL) | ||
1410 | goto done; | ||
1411 | 1409 | ||
1412 | if (!try_module_get(chip->owner)) | 1410 | if (!try_module_get(chip->owner)) |
1413 | goto done; | 1411 | goto done; |
@@ -1630,16 +1628,20 @@ static int gpiod_direction_input(struct gpio_desc *desc) | |||
1630 | int status = -EINVAL; | 1628 | int status = -EINVAL; |
1631 | int offset; | 1629 | int offset; |
1632 | 1630 | ||
1633 | if (!desc) { | 1631 | if (!desc || !desc->chip) { |
1634 | pr_warn("%s: invalid GPIO\n", __func__); | 1632 | pr_warn("%s: invalid GPIO\n", __func__); |
1635 | return -EINVAL; | 1633 | return -EINVAL; |
1636 | } | 1634 | } |
1637 | 1635 | ||
1636 | chip = desc->chip; | ||
1637 | if (!chip->get || !chip->direction_input) { | ||
1638 | pr_warn("%s: missing get() or direction_input() operations\n", | ||
1639 | __func__); | ||
1640 | return -EIO; | ||
1641 | } | ||
1642 | |||
1638 | spin_lock_irqsave(&gpio_lock, flags); | 1643 | spin_lock_irqsave(&gpio_lock, flags); |
1639 | 1644 | ||
1640 | chip = desc->chip; | ||
1641 | if (!chip || !chip->get || !chip->direction_input) | ||
1642 | goto fail; | ||
1643 | status = gpio_ensure_requested(desc); | 1645 | status = gpio_ensure_requested(desc); |
1644 | if (status < 0) | 1646 | if (status < 0) |
1645 | goto fail; | 1647 | goto fail; |
@@ -1691,7 +1693,7 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value) | |||
1691 | int status = -EINVAL; | 1693 | int status = -EINVAL; |
1692 | int offset; | 1694 | int offset; |
1693 | 1695 | ||
1694 | if (!desc) { | 1696 | if (!desc || !desc->chip) { |
1695 | pr_warn("%s: invalid GPIO\n", __func__); | 1697 | pr_warn("%s: invalid GPIO\n", __func__); |
1696 | return -EINVAL; | 1698 | return -EINVAL; |
1697 | } | 1699 | } |
@@ -1704,11 +1706,15 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value) | |||
1704 | if (!value && test_bit(FLAG_OPEN_SOURCE, &desc->flags)) | 1706 | if (!value && test_bit(FLAG_OPEN_SOURCE, &desc->flags)) |
1705 | return gpiod_direction_input(desc); | 1707 | return gpiod_direction_input(desc); |
1706 | 1708 | ||
1709 | chip = desc->chip; | ||
1710 | if (!chip->set || !chip->direction_output) { | ||
1711 | pr_warn("%s: missing set() or direction_output() operations\n", | ||
1712 | __func__); | ||
1713 | return -EIO; | ||
1714 | } | ||
1715 | |||
1707 | spin_lock_irqsave(&gpio_lock, flags); | 1716 | spin_lock_irqsave(&gpio_lock, flags); |
1708 | 1717 | ||
1709 | chip = desc->chip; | ||
1710 | if (!chip || !chip->set || !chip->direction_output) | ||
1711 | goto fail; | ||
1712 | status = gpio_ensure_requested(desc); | 1718 | status = gpio_ensure_requested(desc); |
1713 | if (status < 0) | 1719 | if (status < 0) |
1714 | goto fail; | 1720 | goto fail; |
@@ -1765,16 +1771,19 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) | |||
1765 | int status = -EINVAL; | 1771 | int status = -EINVAL; |
1766 | int offset; | 1772 | int offset; |
1767 | 1773 | ||
1768 | if (!desc) { | 1774 | if (!desc || !desc->chip) { |
1769 | pr_warn("%s: invalid GPIO\n", __func__); | 1775 | pr_warn("%s: invalid GPIO\n", __func__); |
1770 | return -EINVAL; | 1776 | return -EINVAL; |
1771 | } | 1777 | } |
1772 | 1778 | ||
1773 | spin_lock_irqsave(&gpio_lock, flags); | ||
1774 | |||
1775 | chip = desc->chip; | 1779 | chip = desc->chip; |
1776 | if (!chip || !chip->set || !chip->set_debounce) | 1780 | if (!chip->set || !chip->set_debounce) { |
1777 | goto fail; | 1781 | pr_warn("%s: missing set() or set_debounce() operations\n", |
1782 | __func__); | ||
1783 | return -EIO; | ||
1784 | } | ||
1785 | |||
1786 | spin_lock_irqsave(&gpio_lock, flags); | ||
1778 | 1787 | ||
1779 | status = gpio_ensure_requested(desc); | 1788 | status = gpio_ensure_requested(desc); |
1780 | if (status < 0) | 1789 | if (status < 0) |