diff options
-rw-r--r-- | Documentation/gpio.txt | 10 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 14 | ||||
-rw-r--r-- | include/asm-generic/gpio.h | 12 |
3 files changed, 29 insertions, 7 deletions
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt index 54630095aa3c..c35ca9e40d4c 100644 --- a/Documentation/gpio.txt +++ b/Documentation/gpio.txt | |||
@@ -107,6 +107,16 @@ type of GPIO controller, and on one particular board 80-95 with an FPGA. | |||
107 | The numbers need not be contiguous; either of those platforms could also | 107 | The numbers need not be contiguous; either of those platforms could also |
108 | use numbers 2000-2063 to identify GPIOs in a bank of I2C GPIO expanders. | 108 | use numbers 2000-2063 to identify GPIOs in a bank of I2C GPIO expanders. |
109 | 109 | ||
110 | If you want to initialize a structure with an invalid GPIO number, use | ||
111 | some negative number (perhaps "-EINVAL"); that will never be valid. To | ||
112 | test if a number could reference a GPIO, you may use this predicate: | ||
113 | |||
114 | int gpio_is_valid(int number); | ||
115 | |||
116 | A number that's not valid will be rejected by calls which may request | ||
117 | or free GPIOs (see below). Other numbers may also be rejected; for | ||
118 | example, a number might be valid but unused on a given board. | ||
119 | |||
110 | Whether a platform supports multiple GPIO controllers is currently a | 120 | Whether a platform supports multiple GPIO controllers is currently a |
111 | platform-specific implementation issue. | 121 | platform-specific implementation issue. |
112 | 122 | ||
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index eb75d12e83b7..623fcd9b547a 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -99,7 +99,7 @@ int gpiochip_add(struct gpio_chip *chip) | |||
99 | * dynamic allocation. We don't currently support that. | 99 | * dynamic allocation. We don't currently support that. |
100 | */ | 100 | */ |
101 | 101 | ||
102 | if (chip->base < 0 || (chip->base + chip->ngpio) >= ARCH_NR_GPIOS) { | 102 | if (chip->base < 0 || !gpio_is_valid(chip->base + chip->ngpio)) { |
103 | status = -EINVAL; | 103 | status = -EINVAL; |
104 | goto fail; | 104 | goto fail; |
105 | } | 105 | } |
@@ -174,7 +174,7 @@ int gpio_request(unsigned gpio, const char *label) | |||
174 | 174 | ||
175 | spin_lock_irqsave(&gpio_lock, flags); | 175 | spin_lock_irqsave(&gpio_lock, flags); |
176 | 176 | ||
177 | if (gpio >= ARCH_NR_GPIOS) | 177 | if (!gpio_is_valid(gpio)) |
178 | goto done; | 178 | goto done; |
179 | desc = &gpio_desc[gpio]; | 179 | desc = &gpio_desc[gpio]; |
180 | if (desc->chip == NULL) | 180 | if (desc->chip == NULL) |
@@ -209,7 +209,7 @@ void gpio_free(unsigned gpio) | |||
209 | unsigned long flags; | 209 | unsigned long flags; |
210 | struct gpio_desc *desc; | 210 | struct gpio_desc *desc; |
211 | 211 | ||
212 | if (gpio >= ARCH_NR_GPIOS) { | 212 | if (!gpio_is_valid(gpio)) { |
213 | WARN_ON(extra_checks); | 213 | WARN_ON(extra_checks); |
214 | return; | 214 | return; |
215 | } | 215 | } |
@@ -245,7 +245,7 @@ const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset) | |||
245 | { | 245 | { |
246 | unsigned gpio = chip->base + offset; | 246 | unsigned gpio = chip->base + offset; |
247 | 247 | ||
248 | if (gpio >= ARCH_NR_GPIOS || gpio_desc[gpio].chip != chip) | 248 | if (!gpio_is_valid(gpio) || gpio_desc[gpio].chip != chip) |
249 | return NULL; | 249 | return NULL; |
250 | if (test_bit(FLAG_REQUESTED, &gpio_desc[gpio].flags) == 0) | 250 | if (test_bit(FLAG_REQUESTED, &gpio_desc[gpio].flags) == 0) |
251 | return NULL; | 251 | return NULL; |
@@ -276,7 +276,7 @@ int gpio_direction_input(unsigned gpio) | |||
276 | 276 | ||
277 | spin_lock_irqsave(&gpio_lock, flags); | 277 | spin_lock_irqsave(&gpio_lock, flags); |
278 | 278 | ||
279 | if (gpio >= ARCH_NR_GPIOS) | 279 | if (!gpio_is_valid(gpio)) |
280 | goto fail; | 280 | goto fail; |
281 | chip = desc->chip; | 281 | chip = desc->chip; |
282 | if (!chip || !chip->get || !chip->direction_input) | 282 | if (!chip || !chip->get || !chip->direction_input) |
@@ -314,7 +314,7 @@ int gpio_direction_output(unsigned gpio, int value) | |||
314 | 314 | ||
315 | spin_lock_irqsave(&gpio_lock, flags); | 315 | spin_lock_irqsave(&gpio_lock, flags); |
316 | 316 | ||
317 | if (gpio >= ARCH_NR_GPIOS) | 317 | if (!gpio_is_valid(gpio)) |
318 | goto fail; | 318 | goto fail; |
319 | chip = desc->chip; | 319 | chip = desc->chip; |
320 | if (!chip || !chip->set || !chip->direction_output) | 320 | if (!chip || !chip->set || !chip->direction_output) |
@@ -531,7 +531,7 @@ static int gpiolib_show(struct seq_file *s, void *unused) | |||
531 | 531 | ||
532 | /* REVISIT this isn't locked against gpio_chip removal ... */ | 532 | /* REVISIT this isn't locked against gpio_chip removal ... */ |
533 | 533 | ||
534 | for (gpio = 0; gpio < ARCH_NR_GPIOS; gpio++) { | 534 | for (gpio = 0; gpio_is_valid(gpio); gpio++) { |
535 | if (chip == gpio_desc[gpio].chip) | 535 | if (chip == gpio_desc[gpio].chip) |
536 | continue; | 536 | continue; |
537 | chip = gpio_desc[gpio].chip; | 537 | chip = gpio_desc[gpio].chip; |
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 7e77b6ff45bb..464c5b334dc2 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h | |||
@@ -16,6 +16,12 @@ | |||
16 | #define ARCH_NR_GPIOS 256 | 16 | #define ARCH_NR_GPIOS 256 |
17 | #endif | 17 | #endif |
18 | 18 | ||
19 | static inline int gpio_is_valid(int number) | ||
20 | { | ||
21 | /* only some non-negative numbers are valid */ | ||
22 | return ((unsigned)number) < ARCH_NR_GPIOS; | ||
23 | } | ||
24 | |||
19 | struct seq_file; | 25 | struct seq_file; |
20 | struct module; | 26 | struct module; |
21 | 27 | ||
@@ -99,6 +105,12 @@ extern int __gpio_cansleep(unsigned gpio); | |||
99 | 105 | ||
100 | #else | 106 | #else |
101 | 107 | ||
108 | static inline int gpio_is_valid(int number) | ||
109 | { | ||
110 | /* only non-negative numbers are valid */ | ||
111 | return number >= 0; | ||
112 | } | ||
113 | |||
102 | /* platforms that don't directly support access to GPIOs through I2C, SPI, | 114 | /* platforms that don't directly support access to GPIOs through I2C, SPI, |
103 | * or other blocking infrastructure can use these wrappers. | 115 | * or other blocking infrastructure can use these wrappers. |
104 | */ | 116 | */ |