Messages in this thread Patch in this message | | | Date | Wed, 14 Nov 2007 09:03:29 +0800 | From | "eric miao" <> | Subject | Re: [patch/rfc 1/4] GPIO implementation framework |
| |
Here comes the point of "struct gpio_desc"
Subject: [PATCH 3/5] use a per GPIO "struct gpio_desc" and chain "gpio_chip" to a list
--- include/asm-generic/gpio.h | 7 +++++ lib/gpiolib.c | 64 ++++++++++++++++++++++---------------------- 2 files changed, 39 insertions(+), 32 deletions(-)
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index ba3e336..783adcf 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -23,6 +23,12 @@
struct seq_file;
+struct gpio_chip; + +struct gpio_desc { + struct gpio_chip *chip; +}; + /** * struct gpio_chip - abstract a GPIO controller * @label: for diagnostics @@ -76,6 +82,7 @@ struct gpio_chip { DECLARE_BITMAP(requested, ARCH_GPIOS_PER_CHIP);
#ifdef CONFIG_DEBUG_FS + struct list_head node; const char *requested_str[ARCH_GPIOS_PER_CHIP]; #endif }; diff --git a/lib/gpiolib.c b/lib/gpiolib.c index d52c7f1..57e0d10 100644 --- a/lib/gpiolib.c +++ b/lib/gpiolib.c @@ -25,13 +25,12 @@ #define extra_checks 0 #endif
-/* gpio_lock protects modification to the table of chips and to - * gpio_chip->requested. If a gpio is requested, its gpio_chip - * is not removable. - */ static DEFINE_SPINLOCK(gpio_lock); -static struct gpio_chip *chips[DIV_ROUND_UP(ARCH_NR_GPIOS, - ARCH_GPIOS_PER_CHIP)]; +struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; + +#ifdef CONFIG_DEBUG_FS +static LIST_HEAD(gpio_chip_list); +#endif
static inline int gpio_is_onchip(unsigned gpio, struct gpio_chip *chip) { @@ -63,7 +62,7 @@ static void gpio_ensure_requested(struct gpio_chip *chip, unsigned offset) /* caller holds gpio_lock */ static inline struct gpio_chip *gpio_to_chip(unsigned gpio) { - return chips[gpio / ARCH_GPIOS_PER_CHIP]; + return gpio_desc[gpio].chip; }
/** @@ -78,7 +77,6 @@ static inline struct gpio_chip *gpio_to_chip(unsigned gpio) int gpiochip_add(struct gpio_chip *chip) { unsigned long flags; - int status = 0; unsigned id;
if (chip->base < 0 || (chip->base % ARCH_GPIOS_PER_CHIP) != 0) @@ -89,13 +87,21 @@ int gpiochip_add(struct gpio_chip *chip) return -EINVAL;
spin_lock_irqsave(&gpio_lock, flags); - id = chip->base / ARCH_GPIOS_PER_CHIP; - if (chips[id] == NULL) - chips[id] = chip; - else - status = -EBUSY; + + for (id = chip->base; id < chip->base + chip->ngpio; id++) + if (gpio_desc[id].chip) { + spin_unlock_irqrestore(&gpio_lock, flags); + return -EBUSY; + } + + for (id = chip->base; id < chip->base + chip->ngpio; id++) + gpio_desc[id].chip = chip; + +#ifdef CONFIG_DEBUG_FS + list_add(&chip->node, &gpio_chip_list); +#endif spin_unlock_irqrestore(&gpio_lock, flags); - return status; + return 0; } EXPORT_SYMBOL_GPL(gpiochip_add);
@@ -108,28 +114,26 @@ EXPORT_SYMBOL_GPL(gpiochip_add); int gpiochip_remove(struct gpio_chip *chip) { unsigned long flags; - int status = 0; int offset; - unsigned id = chip->base / ARCH_GPIOS_PER_CHIP; + unsigned id;
spin_lock_irqsave(&gpio_lock, flags);
- for (offset = 0; offset < chip->ngpio; offset++) { + for (offset = 0; offset < chip->ngpio; offset++) if (gpiochip_is_requested(chip, offset)) { - status = -EBUSY; - break; + spin_unlock_irqrestore(&gpio_lock, flags); + return -EBUSY; } - }
- if (status == 0) { - if (chips[id] == chip) - chips[id] = NULL; - else - status = -EINVAL; - } + for (id = chip->base; id < chip->base + chip->ngpio; id++) + gpio_desc[id].chip = NULL; + +#ifdef CONFIG_DEBUG_FS + list_del(&chip->node); +#endif
spin_unlock_irqrestore(&gpio_lock, flags); - return status; + return 0; } EXPORT_SYMBOL_GPL(gpiochip_remove);
@@ -463,11 +467,7 @@ static int gpiolib_show(struct seq_file *s, void *unused)
/* REVISIT this isn't locked against gpio_chip removal ... */
- for (id = 0; id < ARRAY_SIZE(chips); id++) { - chip = chips[id]; - if (!chip) - continue; - + list_for_each_entry(chip, &gpio_chip_list, node) { seq_printf(s, "%sGPIOs %d-%d, %s%s:\n", started ? "\n" : "", chip->base, chip->base + chip->ngpio - 1, -- 1.5.2.5.GIT - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |