diff options
author | Thierry Reding <thierry.reding@avionic-design.de> | 2012-04-12 13:26:01 +0200 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-08-17 07:35:41 +0200 |
commit | f9c4a31f61501d25f0a45faae6a5cd701ad5694a (patch) | |
tree | fc98b2e1357f7374a5384615f12fb2e9e7d25d37 /drivers/gpio/gpiolib.c | |
parent | d9875690d9b89a866022ff49e3fcea892345ad92 (diff) | |
download | linux-f9c4a31f61501d25f0a45faae6a5cd701ad5694a.tar.bz2 |
gpiolib: Use seq_file's iterator interface
When dumping a collection of items via seq_file, it is recommended to
use the iterator interface. For the gpiolib debugfs interface this can
be done to dump each GPIO chip in turn.
Note that for gpiolib this is a little cumbersome because it does not
provide a list of registered GPIO chips and the only way to iterate is
over each GPIO individually. Once a chip is found, the number of GPIOs
it provides can be skipped as a small optimization.
This patch was requested by Arnd Bergmann here:
http://article.gmane.org/gmane.linux.ports.tegra/3535
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: linux-kernel@vger.kernel.org
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r-- | drivers/gpio/gpiolib.c | 102 |
1 files changed, 74 insertions, 28 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index de0213c9d11c..5d6c71edc739 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1773,56 +1773,102 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) } } -static int gpiolib_show(struct seq_file *s, void *unused) +static void *gpiolib_seq_start(struct seq_file *s, loff_t *pos) { - struct gpio_chip *chip = NULL; - unsigned gpio; - int started = 0; + struct gpio_chip *chip = NULL; + unsigned int gpio; + void *ret = NULL; + loff_t index = 0; /* REVISIT this isn't locked against gpio_chip removal ... */ for (gpio = 0; gpio_is_valid(gpio); gpio++) { - struct device *dev; - - if (chip == gpio_desc[gpio].chip) + if (gpio_desc[gpio].chip == chip) continue; + chip = gpio_desc[gpio].chip; if (!chip) continue; - seq_printf(s, "%sGPIOs %d-%d", - started ? "\n" : "", - chip->base, chip->base + chip->ngpio - 1); - dev = chip->dev; - if (dev) - seq_printf(s, ", %s/%s", - dev->bus ? dev->bus->name : "no-bus", - dev_name(dev)); - if (chip->label) - seq_printf(s, ", %s", chip->label); - if (chip->can_sleep) - seq_printf(s, ", can sleep"); - seq_printf(s, ":\n"); - - started = 1; - if (chip->dbg_show) - chip->dbg_show(s, chip); - else - gpiolib_dbg_show(s, chip); + if (index++ >= *pos) { + ret = chip; + break; + } } + + s->private = ""; + + return ret; +} + +static void *gpiolib_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + struct gpio_chip *chip = v; + unsigned int gpio; + void *ret = NULL; + + /* skip GPIOs provided by the current chip */ + for (gpio = chip->base + chip->ngpio; gpio_is_valid(gpio); gpio++) { + chip = gpio_desc[gpio].chip; + if (chip) { + ret = chip; + break; + } + } + + s->private = "\n"; + ++*pos; + + return ret; +} + +static void gpiolib_seq_stop(struct seq_file *s, void *v) +{ +} + +static int gpiolib_seq_show(struct seq_file *s, void *v) +{ + struct gpio_chip *chip = v; + struct device *dev; + + seq_printf(s, "%sGPIOs %d-%d", (char *)s->private, + chip->base, chip->base + chip->ngpio - 1); + dev = chip->dev; + if (dev) + seq_printf(s, ", %s/%s", dev->bus ? dev->bus->name : "no-bus", + dev_name(dev)); + if (chip->label) + seq_printf(s, ", %s", chip->label); + if (chip->can_sleep) + seq_printf(s, ", can sleep"); + seq_printf(s, ":\n"); + + if (chip->dbg_show) + chip->dbg_show(s, chip); + else + gpiolib_dbg_show(s, chip); + return 0; } +static const struct seq_operations gpiolib_seq_ops = { + .start = gpiolib_seq_start, + .next = gpiolib_seq_next, + .stop = gpiolib_seq_stop, + .show = gpiolib_seq_show, +}; + static int gpiolib_open(struct inode *inode, struct file *file) { - return single_open(file, gpiolib_show, NULL); + return seq_open(file, &gpiolib_seq_ops); } static const struct file_operations gpiolib_operations = { + .owner = THIS_MODULE, .open = gpiolib_open, .read = seq_read, .llseek = seq_lseek, - .release = single_release, + .release = seq_release, }; static int __init gpiolib_debugfs_init(void) |