summaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@nvidia.com>2013-02-02 17:29:28 +0100
committerGrant Likely <grant.likely@secretlab.ca>2013-02-09 11:07:10 +0100
commit83cabe33eb05b51a6239a3df344d89cafac2306c (patch)
treef18d922e7558e73c2aab5e825800ad136ed2fd57 /drivers/gpio
parentgpiolib: use gpio_chips list in sysfs ops (diff)
downloadlinux-83cabe33eb05b51a6239a3df344d89cafac2306c.tar.xz
linux-83cabe33eb05b51a6239a3df344d89cafac2306c.zip
gpiolib: use gpio_chips list in gpiochip_find_base
Re-implement gpiochip_find_base using the list of chips instead of the global gpio_desc[] array. This makes it both simpler and more efficient, and is needed to remove the global descriptors array. The new code should preserve the exact same GPIO number assignment policy as the code it is replacing. There shouldn't be any visible change to the assigned GPIO numbers. Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> [grant.likely: Added comment about assignment policy] Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpiolib.c37
1 files changed, 16 insertions, 21 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 585d7c3ce12e..8ccf68bb8a40 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -126,30 +126,25 @@ struct gpio_chip *gpio_to_chip(unsigned gpio)
/* dynamic allocation of GPIOs, e.g. on a hotplugged device */
static int gpiochip_find_base(int ngpio)
{
- int i;
- int spare = 0;
- int base = -ENOSPC;
-
- for (i = ARCH_NR_GPIOS - 1; i >= 0 ; i--) {
- struct gpio_desc *desc = &gpio_desc[i];
- struct gpio_chip *chip = desc->chip;
-
- if (!chip) {
- spare++;
- if (spare == ngpio) {
- base = i;
- break;
- }
- } else {
- spare = 0;
- if (chip)
- i -= chip->ngpio - 1;
- }
+ struct gpio_chip *chip;
+ int base = ARCH_NR_GPIOS - ngpio;
+
+ list_for_each_entry_reverse(chip, &gpio_chips, list) {
+ /* found a free space? */
+ if (chip->base + chip->ngpio <= base)
+ break;
+ else
+ /* nope, check the space right before the chip */
+ base = chip->base - ngpio;
}
- if (gpio_is_valid(base))
+ if (gpio_is_valid(base)) {
pr_debug("%s: found new base at %d\n", __func__, base);
- return base;
+ return base;
+ } else {
+ pr_err("%s: cannot find free range\n", __func__);
+ return -ENOSPC;
+ }
}
/* caller ensures gpio is valid and requested, chip->get_direction may sleep */