Commit 06e79d3b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux

Pull second round of GPIO changes from Grant Likely:
 "This branch contains a few bug fixes that I missed the first time
  around and updates to the gpio_desc series included in the first pull
  request.  This tag has been retagged to drop the 2 head commits
  because the one of them caused a build failure."

* tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux:
  gpio/gpio-ich: fix ichx_gpio_check_available() return what callers expect
  gpiolib: move comment to right function
  gpiolib: use const parameters when possible
  gpiolib: check descriptors validity before use
parents a5e0d731 e97f9b52
...@@ -128,9 +128,9 @@ static int ichx_read_bit(int reg, unsigned nr) ...@@ -128,9 +128,9 @@ static int ichx_read_bit(int reg, unsigned nr)
return data & (1 << bit) ? 1 : 0; return data & (1 << bit) ? 1 : 0;
} }
static int ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)
{ {
return (ichx_priv.use_gpio & (1 << (nr / 32))) ? 0 : -ENXIO; return ichx_priv.use_gpio & (1 << (nr / 32));
} }
static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
......
...@@ -88,13 +88,14 @@ static int gpiod_request(struct gpio_desc *desc, const char *label); ...@@ -88,13 +88,14 @@ static int gpiod_request(struct gpio_desc *desc, const char *label);
static void gpiod_free(struct gpio_desc *desc); static void gpiod_free(struct gpio_desc *desc);
static int gpiod_direction_input(struct gpio_desc *desc); static int gpiod_direction_input(struct gpio_desc *desc);
static int gpiod_direction_output(struct gpio_desc *desc, int value); static int gpiod_direction_output(struct gpio_desc *desc, int value);
static int gpiod_get_direction(const struct gpio_desc *desc);
static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce); static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
static int gpiod_get_value_cansleep(struct gpio_desc *desc); static int gpiod_get_value_cansleep(const struct gpio_desc *desc);
static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value); static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value);
static int gpiod_get_value(struct gpio_desc *desc); static int gpiod_get_value(const struct gpio_desc *desc);
static void gpiod_set_value(struct gpio_desc *desc, int value); static void gpiod_set_value(struct gpio_desc *desc, int value);
static int gpiod_cansleep(struct gpio_desc *desc); static int gpiod_cansleep(const struct gpio_desc *desc);
static int gpiod_to_irq(struct gpio_desc *desc); static int gpiod_to_irq(const struct gpio_desc *desc);
static int gpiod_export(struct gpio_desc *desc, bool direction_may_change); static int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
static int gpiod_export_link(struct device *dev, const char *name, static int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc); struct gpio_desc *desc);
...@@ -171,12 +172,12 @@ static int gpio_ensure_requested(struct gpio_desc *desc) ...@@ -171,12 +172,12 @@ static int gpio_ensure_requested(struct gpio_desc *desc)
return 0; return 0;
} }
/* caller holds gpio_lock *OR* gpio is marked as requested */ static struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
static struct gpio_chip *gpiod_to_chip(struct gpio_desc *desc)
{ {
return desc->chip; return desc ? desc->chip : NULL;
} }
/* caller holds gpio_lock *OR* gpio is marked as requested */
struct gpio_chip *gpio_to_chip(unsigned gpio) struct gpio_chip *gpio_to_chip(unsigned gpio)
{ {
return gpiod_to_chip(gpio_to_desc(gpio)); return gpiod_to_chip(gpio_to_desc(gpio));
...@@ -207,7 +208,7 @@ static int gpiochip_find_base(int ngpio) ...@@ -207,7 +208,7 @@ static int gpiochip_find_base(int ngpio)
} }
/* caller ensures gpio is valid and requested, chip->get_direction may sleep */ /* caller ensures gpio is valid and requested, chip->get_direction may sleep */
static int gpiod_get_direction(struct gpio_desc *desc) static int gpiod_get_direction(const struct gpio_desc *desc)
{ {
struct gpio_chip *chip; struct gpio_chip *chip;
unsigned offset; unsigned offset;
...@@ -223,11 +224,13 @@ static int gpiod_get_direction(struct gpio_desc *desc) ...@@ -223,11 +224,13 @@ static int gpiod_get_direction(struct gpio_desc *desc)
if (status > 0) { if (status > 0) {
/* GPIOF_DIR_IN, or other positive */ /* GPIOF_DIR_IN, or other positive */
status = 1; status = 1;
clear_bit(FLAG_IS_OUT, &desc->flags); /* FLAG_IS_OUT is just a cache of the result of get_direction(),
* so it does not affect constness per se */
clear_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags);
} }
if (status == 0) { if (status == 0) {
/* GPIOF_DIR_OUT */ /* GPIOF_DIR_OUT */
set_bit(FLAG_IS_OUT, &desc->flags); set_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags);
} }
return status; return status;
} }
...@@ -263,7 +266,7 @@ static DEFINE_MUTEX(sysfs_lock); ...@@ -263,7 +266,7 @@ static DEFINE_MUTEX(sysfs_lock);
static ssize_t gpio_direction_show(struct device *dev, static ssize_t gpio_direction_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct gpio_desc *desc = dev_get_drvdata(dev); const struct gpio_desc *desc = dev_get_drvdata(dev);
ssize_t status; ssize_t status;
mutex_lock(&sysfs_lock); mutex_lock(&sysfs_lock);
...@@ -654,6 +657,11 @@ static ssize_t export_store(struct class *class, ...@@ -654,6 +657,11 @@ static ssize_t export_store(struct class *class,
goto done; goto done;
desc = gpio_to_desc(gpio); desc = gpio_to_desc(gpio);
/* reject invalid GPIOs */
if (!desc) {
pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
return -EINVAL;
}
/* No extra locking here; FLAG_SYSFS just signifies that the /* No extra locking here; FLAG_SYSFS just signifies that the
* request and export were done by on behalf of userspace, so * request and export were done by on behalf of userspace, so
...@@ -690,12 +698,14 @@ static ssize_t unexport_store(struct class *class, ...@@ -690,12 +698,14 @@ static ssize_t unexport_store(struct class *class,
if (status < 0) if (status < 0)
goto done; goto done;
status = -EINVAL;
desc = gpio_to_desc(gpio); desc = gpio_to_desc(gpio);
/* reject bogus commands (gpio_unexport ignores them) */ /* reject bogus commands (gpio_unexport ignores them) */
if (!desc) if (!desc) {
goto done; pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
return -EINVAL;
}
status = -EINVAL;
/* No extra locking here; FLAG_SYSFS just signifies that the /* No extra locking here; FLAG_SYSFS just signifies that the
* request and export were done by on behalf of userspace, so * request and export were done by on behalf of userspace, so
...@@ -846,8 +856,10 @@ static int gpiod_export_link(struct device *dev, const char *name, ...@@ -846,8 +856,10 @@ static int gpiod_export_link(struct device *dev, const char *name,
{ {
int status = -EINVAL; int status = -EINVAL;
if (!desc) if (!desc) {
goto done; pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
mutex_lock(&sysfs_lock); mutex_lock(&sysfs_lock);
...@@ -865,7 +877,6 @@ static int gpiod_export_link(struct device *dev, const char *name, ...@@ -865,7 +877,6 @@ static int gpiod_export_link(struct device *dev, const char *name,
mutex_unlock(&sysfs_lock); mutex_unlock(&sysfs_lock);
done:
if (status) if (status)
pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),
status); status);
...@@ -896,8 +907,10 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value) ...@@ -896,8 +907,10 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
struct device *dev = NULL; struct device *dev = NULL;
int status = -EINVAL; int status = -EINVAL;
if (!desc) if (!desc) {
goto done; pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
mutex_lock(&sysfs_lock); mutex_lock(&sysfs_lock);
...@@ -914,7 +927,6 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value) ...@@ -914,7 +927,6 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
unlock: unlock:
mutex_unlock(&sysfs_lock); mutex_unlock(&sysfs_lock);
done:
if (status) if (status)
pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),
status); status);
...@@ -940,8 +952,8 @@ static void gpiod_unexport(struct gpio_desc *desc) ...@@ -940,8 +952,8 @@ static void gpiod_unexport(struct gpio_desc *desc)
struct device *dev = NULL; struct device *dev = NULL;
if (!desc) { if (!desc) {
status = -EINVAL; pr_warn("%s: invalid GPIO\n", __func__);
goto done; return;
} }
mutex_lock(&sysfs_lock); mutex_lock(&sysfs_lock);
...@@ -962,7 +974,7 @@ static void gpiod_unexport(struct gpio_desc *desc) ...@@ -962,7 +974,7 @@ static void gpiod_unexport(struct gpio_desc *desc)
device_unregister(dev); device_unregister(dev);
put_device(dev); put_device(dev);
} }
done:
if (status) if (status)
pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),
status); status);
...@@ -1384,12 +1396,13 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) ...@@ -1384,12 +1396,13 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
int status = -EPROBE_DEFER; int status = -EPROBE_DEFER;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&gpio_lock, flags);
if (!desc) { if (!desc) {
status = -EINVAL; pr_warn("%s: invalid GPIO\n", __func__);
goto done; return -EINVAL;
} }
spin_lock_irqsave(&gpio_lock, flags);
chip = desc->chip; chip = desc->chip;
if (chip == NULL) if (chip == NULL)
goto done; goto done;
...@@ -1432,8 +1445,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) ...@@ -1432,8 +1445,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
done: done:
if (status) if (status)
pr_debug("_gpio_request: gpio-%d (%s) status %d\n", pr_debug("_gpio_request: gpio-%d (%s) status %d\n",
desc ? desc_to_gpio(desc) : -1, desc_to_gpio(desc), label ? : "?", status);
label ? : "?", status);
spin_unlock_irqrestore(&gpio_lock, flags); spin_unlock_irqrestore(&gpio_lock, flags);
return status; return status;
} }
...@@ -1616,10 +1628,13 @@ static int gpiod_direction_input(struct gpio_desc *desc) ...@@ -1616,10 +1628,13 @@ static int gpiod_direction_input(struct gpio_desc *desc)
int status = -EINVAL; int status = -EINVAL;
int offset; int offset;
if (!desc) {
pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
if (!desc)
goto fail;
chip = desc->chip; chip = desc->chip;
if (!chip || !chip->get || !chip->direction_input) if (!chip || !chip->get || !chip->direction_input)
goto fail; goto fail;
...@@ -1655,13 +1670,9 @@ static int gpiod_direction_input(struct gpio_desc *desc) ...@@ -1655,13 +1670,9 @@ static int gpiod_direction_input(struct gpio_desc *desc)
return status; return status;
fail: fail:
spin_unlock_irqrestore(&gpio_lock, flags); spin_unlock_irqrestore(&gpio_lock, flags);
if (status) { if (status)
int gpio = -1; pr_debug("%s: gpio-%d status %d\n", __func__,
if (desc) desc_to_gpio(desc), status);
gpio = desc_to_gpio(desc);
pr_debug("%s: gpio-%d status %d\n",
__func__, gpio, status);
}
return status; return status;
} }
...@@ -1678,6 +1689,11 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value) ...@@ -1678,6 +1689,11 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)
int status = -EINVAL; int status = -EINVAL;
int offset; int offset;
if (!desc) {
pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
/* Open drain pin should not be driven to 1 */ /* Open drain pin should not be driven to 1 */
if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags))
return gpiod_direction_input(desc); return gpiod_direction_input(desc);
...@@ -1688,8 +1704,6 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value) ...@@ -1688,8 +1704,6 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
if (!desc)
goto fail;
chip = desc->chip; chip = desc->chip;
if (!chip || !chip->set || !chip->direction_output) if (!chip || !chip->set || !chip->direction_output)
goto fail; goto fail;
...@@ -1725,13 +1739,9 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value) ...@@ -1725,13 +1739,9 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)
return status; return status;
fail: fail:
spin_unlock_irqrestore(&gpio_lock, flags); spin_unlock_irqrestore(&gpio_lock, flags);
if (status) { if (status)
int gpio = -1; pr_debug("%s: gpio-%d status %d\n", __func__,
if (desc) desc_to_gpio(desc), status);
gpio = desc_to_gpio(desc);
pr_debug("%s: gpio-%d status %d\n",
__func__, gpio, status);
}
return status; return status;
} }
...@@ -1753,10 +1763,13 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) ...@@ -1753,10 +1763,13 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
int status = -EINVAL; int status = -EINVAL;
int offset; int offset;
if (!desc) {
pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
if (!desc)
goto fail;
chip = desc->chip; chip = desc->chip;
if (!chip || !chip->set || !chip->set_debounce) if (!chip || !chip->set || !chip->set_debounce)
goto fail; goto fail;
...@@ -1776,13 +1789,9 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) ...@@ -1776,13 +1789,9 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
fail: fail:
spin_unlock_irqrestore(&gpio_lock, flags); spin_unlock_irqrestore(&gpio_lock, flags);
if (status) { if (status)
int gpio = -1; pr_debug("%s: gpio-%d status %d\n", __func__,
if (desc) desc_to_gpio(desc), status);
gpio = desc_to_gpio(desc);
pr_debug("%s: gpio-%d status %d\n",
__func__, gpio, status);
}
return status; return status;
} }
...@@ -1824,12 +1833,14 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce); ...@@ -1824,12 +1833,14 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce);
* It returns the zero or nonzero value provided by the associated * It returns the zero or nonzero value provided by the associated
* gpio_chip.get() method; or zero if no such method is provided. * gpio_chip.get() method; or zero if no such method is provided.
*/ */
static int gpiod_get_value(struct gpio_desc *desc) static int gpiod_get_value(const struct gpio_desc *desc)
{ {
struct gpio_chip *chip; struct gpio_chip *chip;
int value; int value;
int offset; int offset;
if (!desc)
return 0;
chip = desc->chip; chip = desc->chip;
offset = gpio_chip_hwgpio(desc); offset = gpio_chip_hwgpio(desc);
/* Should be using gpio_get_value_cansleep() */ /* Should be using gpio_get_value_cansleep() */
...@@ -1912,6 +1923,8 @@ static void gpiod_set_value(struct gpio_desc *desc, int value) ...@@ -1912,6 +1923,8 @@ static void gpiod_set_value(struct gpio_desc *desc, int value)
{ {
struct gpio_chip *chip; struct gpio_chip *chip;
if (!desc)
return;
chip = desc->chip; chip = desc->chip;
/* Should be using gpio_set_value_cansleep() */ /* Should be using gpio_set_value_cansleep() */
WARN_ON(chip->can_sleep); WARN_ON(chip->can_sleep);
...@@ -1938,8 +1951,10 @@ EXPORT_SYMBOL_GPL(__gpio_set_value); ...@@ -1938,8 +1951,10 @@ EXPORT_SYMBOL_GPL(__gpio_set_value);
* This is used directly or indirectly to implement gpio_cansleep(). It * This is used directly or indirectly to implement gpio_cansleep(). It
* returns nonzero if access reading or writing the GPIO value can sleep. * returns nonzero if access reading or writing the GPIO value can sleep.
*/ */
static int gpiod_cansleep(struct gpio_desc *desc) static int gpiod_cansleep(const struct gpio_desc *desc)
{ {
if (!desc)
return 0;
/* only call this on GPIOs that are valid! */ /* only call this on GPIOs that are valid! */
return desc->chip->can_sleep; return desc->chip->can_sleep;
} }
...@@ -1959,11 +1974,13 @@ EXPORT_SYMBOL_GPL(__gpio_cansleep); ...@@ -1959,11 +1974,13 @@ EXPORT_SYMBOL_GPL(__gpio_cansleep);
* It returns the number of the IRQ signaled by this (input) GPIO, * It returns the number of the IRQ signaled by this (input) GPIO,
* or a negative errno. * or a negative errno.
*/ */
static int gpiod_to_irq(struct gpio_desc *desc) static int gpiod_to_irq(const struct gpio_desc *desc)
{ {
struct gpio_chip *chip; struct gpio_chip *chip;
int offset; int offset;
if (!desc)
return -EINVAL;
chip = desc->chip; chip = desc->chip;
offset = gpio_chip_hwgpio(desc); offset = gpio_chip_hwgpio(desc);
return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO; return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO;
...@@ -1980,13 +1997,15 @@ EXPORT_SYMBOL_GPL(__gpio_to_irq); ...@@ -1980,13 +1997,15 @@ EXPORT_SYMBOL_GPL(__gpio_to_irq);
* Common examples include ones connected to I2C or SPI chips. * Common examples include ones connected to I2C or SPI chips.
*/ */
static int gpiod_get_value_cansleep(struct gpio_desc *desc) static int gpiod_get_value_cansleep(const struct gpio_desc *desc)
{ {
struct gpio_chip *chip; struct gpio_chip *chip;
int value; int value;
int offset; int offset;
might_sleep_if(extra_checks); might_sleep_if(extra_checks);
if (!desc)
return 0;
chip = desc->chip; chip = desc->chip;
offset = gpio_chip_hwgpio(desc); offset = gpio_chip_hwgpio(desc);
value = chip->get ? chip->get(chip, offset) : 0; value = chip->get ? chip->get(chip, offset) : 0;
...@@ -2005,6 +2024,8 @@ static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) ...@@ -2005,6 +2024,8 @@ static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
struct gpio_chip *chip; struct gpio_chip *chip;
might_sleep_if(extra_checks); might_sleep_if(extra_checks);
if (!desc)
return;
chip = desc->chip; chip = desc->chip;
trace_gpio_value(desc_to_gpio(desc), 0, value); trace_gpio_value(desc_to_gpio(desc), 0, value);
if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment