Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -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)
+82 −61
Original line number Original line Diff line number Diff line
@@ -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)
	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)
}
}


/* 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)
	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);
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,
		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,
	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,
{
{
	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,


	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)
	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)
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)
	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)
		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)
	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)
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)
	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 @@ lose:
	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)
	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)


	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 @@ lose:
	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)
	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)


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);
 * 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)
{
{
	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);
 * 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);
 * 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);
 * 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)
	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))