Thread (17 messages) 17 messages, 5 authors, 2012-11-02

[PATCH RESEND 1/5 v6] gpio: Add a block GPIO API to gpiolib

From: Roland Stigge <hidden>
Date: 2012-10-31 17:47:21
Also in: lkml

Hi Linus,

thanks for your notes, comments below:

On 10/31/2012 03:06 PM, Linus Walleij wrote:
quoted
+struct gpio_block *gpio_block_create(unsigned *gpios, size_t size,
+                                    const char *name)
+{
+       struct gpio_block *block;
+       struct gpio_block_chip *gbc;
+       struct gpio_remap *remap;
+       void *tmp;
+       int i;
+
+       if (size < 1 || size > sizeof(unsigned long) * 8)
+               return ERR_PTR(-EINVAL);
If the most GPIOs in a block is BITS_PER_LONG, why is the
latter clause not size > BITS_PER_LONG?
Good catch, thanks! :-)
quoted
+       for (i = 0; i < size; i++)
+               if (!gpio_is_valid(gpios[i]))
+                       return ERR_PTR(-EINVAL);
+
+       block = kzalloc(sizeof(struct gpio_block), GFP_KERNEL);
+       if (!block)
+               return ERR_PTR(-ENOMEM);
If these were instead glued to a struct device you could do
devm_kzalloc() here and have it garbage collected.
Good, will do.
This is why
https://blueprints.launchpad.net/linux-linaro/+spec/gpiochip-to-dev
needs to happen. (Sorry for hyperlinking.)
quoted
+       block->name = name;
+       block->ngpio = size;
+       block->gpio = kzalloc(sizeof(*block->gpio) * size, GFP_KERNEL);
+       if (!block->gpio)
+               goto err1;
+
+       memcpy(block->gpio, gpios, sizeof(*block->gpio) * size);
+
+       for (i = 0; i < size; i++) {
+               struct gpio_chip *gc = gpio_to_chip(gpios[i]);
+               int bit = gpios[i] - gc->base;
+               int index = gpio_block_chip_index(block, gc);
+
+               if (index < 0) {
+                       block->nchip++;
+                       tmp = krealloc(block->gbc,
+                                      sizeof(struct gpio_block_chip) *
+                                      block->nchip, GFP_KERNEL);
Don't do this dynamic array business. Use a linked list instead.
OK, I checked the important spots where access to the two lists (gbc and
remap) happen (set and get functions), and the access is always
sequential, monotonic. So will use lists. Thanks.
[...]
/*
 * Maybe I'm a bit picky on comment style but I prefer
 * that the first line of a multi-line comment is blank.
 * Applies everywhere.
 */
As noted earlier in the discussion, current gpiolib.c's convention is
done first-line-not-blank. So I sticked to this (un)convention. But can
change this - you are not the first one pointing this out. :-)
quoted
+                       if (!tmp) {
+                               kfree(gbc->remap);
+                               goto err3;
+                       }
+                       gbc->remap = tmp;
+                       remap = &gbc->remap[gbc->nremap - 1];
+                       remap->offset = bit - i;
+                       remap->mask = 0;
+               }
+
+               /* represents the mask necessary for bit reordering between
+                * gpio_block (i.e. as specified on gpio_block_get() and
+                * gpio_block_set()) and gpio_chip domain (i.e. as specified on
+                * the driver's .set_block() and .get_block())
+                */
+               remap->mask |= BIT(i);
+       }
+
+       return block;
+err3:
+       for (i = 0; i < block->nchip - 1; i++)
+               kfree(block->gbc[i].remap);
+       kfree(block->gbc);
+err2:
+       kfree(block->gpio);
+err1:
+       kfree(block);
+       return ERR_PTR(-ENOMEM);
+}
+EXPORT_SYMBOL_GPL(gpio_block_create);
+
+void gpio_block_free(struct gpio_block *block)
+{
+       int i;
+
+       for (i = 0; i < block->nchip; i++)
+               kfree(block->gbc[i].remap);
+       kfree(block->gpio);
+       kfree(block->gbc);
+       kfree(block);
+}
+EXPORT_SYMBOL_GPL(gpio_block_free);
So if we only had a real struct device  inside the gpiochip all
this boilerplate would go away, as devm_* take care of releasing
the resources.
Right. I guess you mean struct gpio_block here which should have a dev?
(Having gpiochip as a dev also would be best, though.) :-)

We need a separate dev for struct gpio_block, since those can be defined
dynamically (i.e. often) during the lifespan of gpio and gpiochip, so
garbage collection would be deferred for too long.

Thanks,

Roland
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help