diff options
-rw-r--r-- | drivers/gpio/gpiolib-legacy.c | 10 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-sysfs.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 19 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.h | 2 | ||||
-rw-r--r-- | include/linux/gpio.h | 6 |
5 files changed, 22 insertions, 17 deletions
diff --git a/drivers/gpio/gpiolib-legacy.c b/drivers/gpio/gpiolib-legacy.c index 616d60187f85..5a9911ae9125 100644 --- a/drivers/gpio/gpiolib-legacy.c +++ b/drivers/gpio/gpiolib-legacy.c @@ -28,10 +28,9 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) struct gpio_desc *desc; int err; - desc = gpio_to_desc(gpio); - /* Compatibility: assume unavailable "valid" GPIOs will appear later */ - if (!desc && gpio_is_valid(gpio)) + desc = gpio_to_desc(gpio); + if (!desc) return -EPROBE_DEFER; err = gpiod_request(desc, label); @@ -63,10 +62,11 @@ EXPORT_SYMBOL_GPL(gpio_request_one); */ int gpio_request(unsigned gpio, const char *label) { - struct gpio_desc *desc = gpio_to_desc(gpio); + struct gpio_desc *desc; /* Compatibility: assume unavailable "valid" GPIOs will appear later */ - if (!desc && gpio_is_valid(gpio)) + desc = gpio_to_desc(gpio); + if (!desc) return -EPROBE_DEFER; return gpiod_request(desc, label); diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 6853ecd98bcb..26202586fd39 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -412,7 +412,7 @@ static ssize_t base_show(struct device *dev, { const struct gpio_device *gdev = dev_get_drvdata(dev); - return sysfs_emit(buf, "%d\n", gdev->base); + return sysfs_emit(buf, "%u\n", gdev->base); } static DEVICE_ATTR_RO(base); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f20367b1ea8e..f749ece2d3cd 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -150,9 +150,6 @@ struct gpio_desc *gpio_to_desc(unsigned gpio) } } - if (!gpio_is_valid(gpio)) - pr_warn("invalid GPIO %d\n", gpio); - return NULL; } EXPORT_SYMBOL_GPL(gpio_to_desc); @@ -297,10 +294,10 @@ struct gpio_chip *gpio_device_get_chip(struct gpio_device *gdev) EXPORT_SYMBOL_GPL(gpio_device_get_chip); /* dynamic allocation of GPIOs, e.g. on a hotplugged device */ -static int gpiochip_find_base_unlocked(int ngpio) +static int gpiochip_find_base_unlocked(u16 ngpio) { + unsigned int base = GPIO_DYNAMIC_BASE; struct gpio_device *gdev; - int base = GPIO_DYNAMIC_BASE; list_for_each_entry_srcu(gdev, &gpio_devices, list, lockdep_is_held(&gpio_devices_lock)) { @@ -311,9 +308,11 @@ static int gpiochip_find_base_unlocked(int ngpio) base = gdev->base + gdev->ngpio; if (base < GPIO_DYNAMIC_BASE) base = GPIO_DYNAMIC_BASE; + if (base > GPIO_DYNAMIC_MAX - ngpio) + break; } - if (gpio_is_valid(base)) { + if (base <= GPIO_DYNAMIC_MAX - ngpio) { pr_debug("%s: found new base at %d\n", __func__, base); return base; } else { @@ -749,7 +748,7 @@ static int gpiochip_setup_dev(struct gpio_device *gdev) if (ret) goto err_remove_device; - dev_dbg(&gdev->dev, "registered GPIOs %d to %d on %s\n", gdev->base, + dev_dbg(&gdev->dev, "registered GPIOs %u to %u on %s\n", gdev->base, gdev->base + gdev->ngpio - 1, gdev->label); return 0; @@ -4788,14 +4787,14 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev) value = gpio_chip_get_value(gc, desc); is_irq = test_bit(FLAG_USED_AS_IRQ, &desc->flags); active_low = test_bit(FLAG_ACTIVE_LOW, &desc->flags); - seq_printf(s, " gpio-%-3d (%-20.20s|%-20.20s) %s %s %s%s\n", + seq_printf(s, " gpio-%-3u (%-20.20s|%-20.20s) %s %s %s%s\n", gpio, desc->name ?: "", gpiod_get_label(desc), is_out ? "out" : "in ", value >= 0 ? (value ? "hi" : "lo") : "? ", is_irq ? "IRQ " : "", active_low ? "ACTIVE LOW" : ""); } else if (desc->name) { - seq_printf(s, " gpio-%-3d (%-20.20s)\n", gpio, desc->name); + seq_printf(s, " gpio-%-3u (%-20.20s)\n", gpio, desc->name); } gpio++; @@ -4867,7 +4866,7 @@ static int gpiolib_seq_show(struct seq_file *s, void *v) return 0; } - seq_printf(s, "%s%s: GPIOs %d-%d", priv->newline ? "\n" : "", + seq_printf(s, "%s%s: GPIOs %u-%u", priv->newline ? "\n" : "", dev_name(&gdev->dev), gdev->base, gdev->base + gdev->ngpio - 1); parent = gc->parent; diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index f67d5991ab1c..7f94580efdbc 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -61,7 +61,7 @@ struct gpio_device { struct module *owner; struct gpio_chip __rcu *chip; struct gpio_desc *descs; - int base; + unsigned int base; u16 ngpio; bool can_sleep; const char *label; diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 4aaedcf424ce..56ac7e7a2889 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -74,6 +74,12 @@ static inline bool gpio_is_valid(int number) * Until they are all fixed, leave 0-512 space for them. */ #define GPIO_DYNAMIC_BASE 512 +/* + * Define the maximum of the possible GPIO in the global numberspace. + * While the GPIO base and numbers are positive, we limit it with signed + * maximum as a lot of code is using negative values for special cases. + */ +#define GPIO_DYNAMIC_MAX INT_MAX /* Always use the library code for GPIO management calls, * or when sleeping may be involved. |