diff options
Diffstat (limited to 'drivers/gpio')
| -rw-r--r-- | drivers/gpio/gpio-ich.c | 4 | ||||
| -rw-r--r-- | drivers/gpio/gpio-mvebu.c | 7 | ||||
| -rw-r--r-- | drivers/gpio/gpiolib-of.c | 5 | ||||
| -rw-r--r-- | drivers/gpio/gpiolib.c | 143 | 
4 files changed, 93 insertions, 66 deletions
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c index 6f2306db859..f9dbd503fc4 100644 --- a/drivers/gpio/gpio-ich.c +++ b/drivers/gpio/gpio-ich.c @@ -128,9 +128,9 @@ static int ichx_read_bit(int reg, unsigned nr)  	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) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 7472182967c..61a6fde6c08 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -42,6 +42,7 @@  #include <linux/io.h>  #include <linux/of_irq.h>  #include <linux/of_device.h> +#include <linux/clk.h>  #include <linux/pinctrl/consumer.h>  /* @@ -496,6 +497,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)  	struct resource *res;  	struct irq_chip_generic *gc;  	struct irq_chip_type *ct; +	struct clk *clk;  	unsigned int ngpios;  	int soc_variant;  	int i, cpu, id; @@ -529,6 +531,11 @@ static int mvebu_gpio_probe(struct platform_device *pdev)  		return id;  	} +	clk = devm_clk_get(&pdev->dev, NULL); +	/* Not all SoCs require a clock.*/ +	if (!IS_ERR(clk)) +		clk_prepare_enable(clk); +  	mvchip->soc_variant = soc_variant;  	mvchip->chip.label = dev_name(&pdev->dev);  	mvchip->chip.dev = &pdev->dev; diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index a71a54a3e3f..5150df6cba0 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -193,7 +193,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)  	if (!np)  		return; -	do { +	for (;; index++) {  		ret = of_parse_phandle_with_args(np, "gpio-ranges",  				"#gpio-range-cells", index, &pinspec);  		if (ret) @@ -222,8 +222,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)  		if (ret)  			break; - -	} while (index++); +	}  }  #else diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index fff9786cdc6..c2534d62911 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -88,13 +88,14 @@ static int gpiod_request(struct gpio_desc *desc, const char *label);  static void gpiod_free(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_get_direction(const struct gpio_desc *desc);  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 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 int gpiod_cansleep(struct gpio_desc *desc); -static int gpiod_to_irq(struct gpio_desc *desc); +static int gpiod_cansleep(const 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_link(struct device *dev, const char *name,  			     struct gpio_desc *desc); @@ -171,12 +172,12 @@ static int gpio_ensure_requested(struct gpio_desc *desc)  	return 0;  } -/* caller holds gpio_lock *OR* gpio is marked as requested */ -static struct gpio_chip *gpiod_to_chip(struct gpio_desc *desc) +static struct gpio_chip *gpiod_to_chip(const 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)  {  	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  */ -static int gpiod_get_direction(struct gpio_desc *desc) +static int gpiod_get_direction(const struct gpio_desc *desc)  {  	struct gpio_chip	*chip;  	unsigned		offset; @@ -223,11 +224,13 @@ static int gpiod_get_direction(struct gpio_desc *desc)  	if (status > 0) {  		/* GPIOF_DIR_IN, or other positive */  		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) {  		/* GPIOF_DIR_OUT */ -		set_bit(FLAG_IS_OUT, &desc->flags); +		set_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags);  	}  	return status;  } @@ -263,7 +266,7 @@ static DEFINE_MUTEX(sysfs_lock);  static ssize_t gpio_direction_show(struct device *dev,  		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;  	mutex_lock(&sysfs_lock); @@ -654,6 +657,11 @@ static ssize_t export_store(struct class *class,  		goto done;  	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  	 * 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)  		goto done; -	status = -EINVAL; -  	desc = gpio_to_desc(gpio);  	/* reject bogus commands (gpio_unexport ignores them) */ -	if (!desc) -		goto done; +	if (!desc) { +		pr_warn("%s: invalid GPIO %ld\n", __func__, gpio); +		return -EINVAL; +	} + +	status = -EINVAL;  	/* No extra locking here; FLAG_SYSFS just signifies that the  	 * 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; -	if (!desc) -		goto done; +	if (!desc) { +		pr_warn("%s: invalid GPIO\n", __func__); +		return -EINVAL; +	}  	mutex_lock(&sysfs_lock); @@ -865,7 +877,6 @@ static int gpiod_export_link(struct device *dev, const char *name,  	mutex_unlock(&sysfs_lock); -done:  	if (status)  		pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),  			 status); @@ -896,8 +907,10 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)  	struct device		*dev = NULL;  	int			status = -EINVAL; -	if (!desc) -		goto done; +	if (!desc) { +		pr_warn("%s: invalid GPIO\n", __func__); +		return -EINVAL; +	}  	mutex_lock(&sysfs_lock); @@ -914,7 +927,6 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)  unlock:  	mutex_unlock(&sysfs_lock); -done:  	if (status)  		pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),  			 status); @@ -940,8 +952,8 @@ static void gpiod_unexport(struct gpio_desc *desc)  	struct device		*dev = NULL;  	if (!desc) { -		status = -EINVAL; -		goto done; +		pr_warn("%s: invalid GPIO\n", __func__); +		return;  	}  	mutex_lock(&sysfs_lock); @@ -962,7 +974,7 @@ static void gpiod_unexport(struct gpio_desc *desc)  		device_unregister(dev);  		put_device(dev);  	} -done: +  	if (status)  		pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),  			 status); @@ -1384,12 +1396,13 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)  	int			status = -EPROBE_DEFER;  	unsigned long		flags; -	spin_lock_irqsave(&gpio_lock, flags); -  	if (!desc) { -		status = -EINVAL; -		goto done; +		pr_warn("%s: invalid GPIO\n", __func__); +		return -EINVAL;  	} + +	spin_lock_irqsave(&gpio_lock, flags); +  	chip = desc->chip;  	if (chip == NULL)  		goto done; @@ -1432,8 +1445,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)  done:  	if (status)  		pr_debug("_gpio_request: gpio-%d (%s) status %d\n", -			 desc ? desc_to_gpio(desc) : -1, -			 label ? : "?", status); +			 desc_to_gpio(desc), label ? : "?", status);  	spin_unlock_irqrestore(&gpio_lock, flags);  	return status;  } @@ -1616,10 +1628,13 @@ static int gpiod_direction_input(struct gpio_desc *desc)  	int			status = -EINVAL;  	int			offset; +	if (!desc) { +		pr_warn("%s: invalid GPIO\n", __func__); +		return -EINVAL; +	} +  	spin_lock_irqsave(&gpio_lock, flags); -	if (!desc) -		goto fail;  	chip = desc->chip;  	if (!chip || !chip->get || !chip->direction_input)  		goto fail; @@ -1655,13 +1670,9 @@ lose:  	return status;  fail:  	spin_unlock_irqrestore(&gpio_lock, flags); -	if (status) { -		int gpio = -1; -		if (desc) -			gpio = desc_to_gpio(desc); -		pr_debug("%s: gpio-%d status %d\n", -			__func__, gpio, status); -	} +	if (status) +		pr_debug("%s: gpio-%d status %d\n", __func__, +			 desc_to_gpio(desc), status);  	return status;  } @@ -1678,6 +1689,11 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)  	int			status = -EINVAL;  	int offset; +	if (!desc) { +		pr_warn("%s: invalid GPIO\n", __func__); +		return -EINVAL; +	} +  	/* Open drain pin should not be driven to 1 */  	if (value && test_bit(FLAG_OPEN_DRAIN,  &desc->flags))  		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); -	if (!desc) -		goto fail;  	chip = desc->chip;  	if (!chip || !chip->set || !chip->direction_output)  		goto fail; @@ -1725,13 +1739,9 @@ lose:  	return status;  fail:  	spin_unlock_irqrestore(&gpio_lock, flags); -	if (status) { -		int gpio = -1; -		if (desc) -			gpio = desc_to_gpio(desc); -		pr_debug("%s: gpio-%d status %d\n", -			__func__, gpio, status); -	} +	if (status) +		pr_debug("%s: gpio-%d status %d\n", __func__, +			 desc_to_gpio(desc), status);  	return status;  } @@ -1753,10 +1763,13 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)  	int			status = -EINVAL;  	int			offset; +	if (!desc) { +		pr_warn("%s: invalid GPIO\n", __func__); +		return -EINVAL; +	} +  	spin_lock_irqsave(&gpio_lock, flags); -	if (!desc) -		goto fail;  	chip = desc->chip;  	if (!chip || !chip->set || !chip->set_debounce)  		goto fail; @@ -1776,13 +1789,9 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)  fail:  	spin_unlock_irqrestore(&gpio_lock, flags); -	if (status) { -		int gpio = -1; -		if (desc) -			gpio = desc_to_gpio(desc); -		pr_debug("%s: gpio-%d status %d\n", -			__func__, gpio, status); -	} +	if (status) +		pr_debug("%s: gpio-%d status %d\n", __func__, +			 desc_to_gpio(desc), status);  	return status;  } @@ -1824,12 +1833,14 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce);   * It returns the zero or nonzero value provided by the associated   * 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;  	int value;  	int offset; +	if (!desc) +		return 0;  	chip = desc->chip;  	offset = gpio_chip_hwgpio(desc);  	/* 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; +	if (!desc) +		return;  	chip = desc->chip;  	/* Should be using gpio_set_value_cansleep() */  	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   * 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! */  	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,   * 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;  	int			offset; +	if (!desc) +		return -EINVAL;  	chip = desc->chip;  	offset = gpio_chip_hwgpio(desc);  	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.   */ -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;  	int value;  	int offset;  	might_sleep_if(extra_checks); +	if (!desc) +		return 0;  	chip = desc->chip;  	offset = gpio_chip_hwgpio(desc);  	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;  	might_sleep_if(extra_checks); +	if (!desc) +		return;  	chip = desc->chip;  	trace_gpio_value(desc_to_gpio(desc), 0, value);  	if (test_bit(FLAG_OPEN_DRAIN,  &desc->flags))  |