From: rmallon@gmail.com (Ryan Mallon)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH RFC 1/6 v3] gpio: Add a block GPIO API to gpiolib
Date: Tue, 16 Oct 2012 09:05:00 +1100 [thread overview]
Message-ID: <507C888C.7040903@gmail.com> (raw)
In-Reply-To: <507C45EF.7080203@antcom.de>
On 16/10/12 04:20, Roland Stigge wrote:
> Hi Ryan,
>
> thank you for your feedback, I will include it, except for some points
> noted below:
>>> + gbc->mask |= BIT(bit);
>>> +
>>> + /* collect gpios that are specified together, represented by
>>> + * neighboring bits
>>> + */
>>> + remap = &gbc->remap[gbc->nremap - 1];
>>
>> This looks broken. If gbc was re-alloced above (index < 0) then
>> gbc->remap == NULL and this will oops?
>
> No, because I took care that even though index can be < 0, the resulting
> pointer is never dereferenced for -1.
Ah, I see. I think its a bit non-obvious and flaky though, since it
looks like you are both dereferencing a potentially NULL pointer, and
indexing an array with -1.
Even changing it to this I think makes it a bit more clear:
if (gbc->remap == 0 ||
bit - i != gbc->remap[gbc->nremap - 1].offset)
gbc->nremap++;
gbc->remap = krealloc(...);
...
If you want to keep your way, at the very least I think it deserves a
comment, since it is easy to misread.
>> The remap functionality isn't very well explained
>
> Documenting now in gpio.h like this:
>
> /*
> * struct gpio_remap - a structure for describing a bit mapping
> * @mask: a bit mask
> * @offset: how many bits to shift to the left (negative: to the
> * right)
> *
> * When we are mapping bit values from one word to another (here: from
> * GPIO block domain to GPIO driver domain), we first mask them out
> * with mask and shift them as specified with offset. More complicated
> * mappings are done by grouping several of those structs and adding
> * the results together.
> */
> struct gpio_remap {
> int mask;
> int offset;
> };
Looks good. Thanks.
> If you find an issue, please let me know. Works fine for me. Have you
> tried? :-)
No, I was just looking at the code, and misread it.
>>> +unsigned gpio_block_get(const struct gpio_block *block)
>>> +{
>>> + struct gpio_block_chip *gbc;
>>> + int i, j;
>>> + unsigned values = 0;
>>> +
>>> + for (i = 0; i < block->nchip; i++) {
>>> + unsigned remapped = 0;
>>> +
>>> + gbc = &block->gbc[i];
>>> +
>>> + if (gbc->gc->get_block) {
>>> + remapped = gbc->gc->get_block(gbc->gc, gbc->mask);
>>> + } else { /* emulate */
>>> + unsigned bit = 1;
>>> +
>>> + for (j = 0; j < sizeof(unsigned) * 8; j++, bit <<= 1) {
>>> + if (gbc->mask & bit)
>>
>> A proper bitmask might be more ideal for this. It would remove the
>> sizeof(unsigned) restriction and allow you to use for_each_set_bit for
>> these loops.
>
> In a previous version of these patches, I actually had a generic bit
> mask which was in turn awkward to handle, especially for the bit
> remapping. Stijn brought me to the idea that for pragmatic reasons, 32
> bit access is fully sufficient in most cases.
>
> I also needed userland access (via sysfs), so there was no way of
> accessing a block except via an int.
>
> When there are GPIO drivers where we seriously need (and can handle
> simultaneously) more than 32 bits, we can still extend the API. For now,
> the cases where it is used is typically creating 8/16/32 bit busses with
> GPIO lines, and on 64bit architectures even 64bit busses.
>
> For this, the current API is working fine, even enabling userland access
> via sysfs.
Fair enough. I didn't see the first round of patches. You probably can
still use for_each_set_bit though (maybe convert the mask to unsigned
long first to match the bitops API):
for_each_set_bit(j, &gbc->mask, BITS_PER_LONG)
...
>>> + unsigned bit = 1;
>>> +
>>> + for (j = 0; j < sizeof(unsigned) * 8; j++, bit <<= 1) {
>>> + if (gbc->mask & bit)
>>> + gbc->gc->set(gbc->gc, gbc->gc->base + j,
>>> + (remapped >> j) & 1);
>>> + }
>>
>> This doesn't clear pins which are set to zero?
>
> It does. gbc->mask only masks which bits to set and clear. remapped
> contains the actual bit values to set. 0 or 1.
Ugh, for some reason I was thinking that the gpio set function only
drove bits that were set in the mask (and had an analogous clear
function). Ignore me :-).
~Ryan
WARNING: multiple messages have this Message-ID (diff)
From: Ryan Mallon <rmallon@gmail.com>
To: Roland Stigge <stigge@antcom.de>
Cc: grant.likely@secretlab.ca, linus.walleij@linaro.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, w.sang@pengutronix.de,
jbe@pengutronix.de, plagnioj@jcrosoft.com, highguy@gmail.com,
broonie@opensource.wolfsonmicro.com
Subject: Re: [PATCH RFC 1/6 v3] gpio: Add a block GPIO API to gpiolib
Date: Tue, 16 Oct 2012 09:05:00 +1100 [thread overview]
Message-ID: <507C888C.7040903@gmail.com> (raw)
In-Reply-To: <507C45EF.7080203@antcom.de>
On 16/10/12 04:20, Roland Stigge wrote:
> Hi Ryan,
>
> thank you for your feedback, I will include it, except for some points
> noted below:
>>> + gbc->mask |= BIT(bit);
>>> +
>>> + /* collect gpios that are specified together, represented by
>>> + * neighboring bits
>>> + */
>>> + remap = &gbc->remap[gbc->nremap - 1];
>>
>> This looks broken. If gbc was re-alloced above (index < 0) then
>> gbc->remap == NULL and this will oops?
>
> No, because I took care that even though index can be < 0, the resulting
> pointer is never dereferenced for -1.
Ah, I see. I think its a bit non-obvious and flaky though, since it
looks like you are both dereferencing a potentially NULL pointer, and
indexing an array with -1.
Even changing it to this I think makes it a bit more clear:
if (gbc->remap == 0 ||
bit - i != gbc->remap[gbc->nremap - 1].offset)
gbc->nremap++;
gbc->remap = krealloc(...);
...
If you want to keep your way, at the very least I think it deserves a
comment, since it is easy to misread.
>> The remap functionality isn't very well explained
>
> Documenting now in gpio.h like this:
>
> /*
> * struct gpio_remap - a structure for describing a bit mapping
> * @mask: a bit mask
> * @offset: how many bits to shift to the left (negative: to the
> * right)
> *
> * When we are mapping bit values from one word to another (here: from
> * GPIO block domain to GPIO driver domain), we first mask them out
> * with mask and shift them as specified with offset. More complicated
> * mappings are done by grouping several of those structs and adding
> * the results together.
> */
> struct gpio_remap {
> int mask;
> int offset;
> };
Looks good. Thanks.
> If you find an issue, please let me know. Works fine for me. Have you
> tried? :-)
No, I was just looking at the code, and misread it.
>>> +unsigned gpio_block_get(const struct gpio_block *block)
>>> +{
>>> + struct gpio_block_chip *gbc;
>>> + int i, j;
>>> + unsigned values = 0;
>>> +
>>> + for (i = 0; i < block->nchip; i++) {
>>> + unsigned remapped = 0;
>>> +
>>> + gbc = &block->gbc[i];
>>> +
>>> + if (gbc->gc->get_block) {
>>> + remapped = gbc->gc->get_block(gbc->gc, gbc->mask);
>>> + } else { /* emulate */
>>> + unsigned bit = 1;
>>> +
>>> + for (j = 0; j < sizeof(unsigned) * 8; j++, bit <<= 1) {
>>> + if (gbc->mask & bit)
>>
>> A proper bitmask might be more ideal for this. It would remove the
>> sizeof(unsigned) restriction and allow you to use for_each_set_bit for
>> these loops.
>
> In a previous version of these patches, I actually had a generic bit
> mask which was in turn awkward to handle, especially for the bit
> remapping. Stijn brought me to the idea that for pragmatic reasons, 32
> bit access is fully sufficient in most cases.
>
> I also needed userland access (via sysfs), so there was no way of
> accessing a block except via an int.
>
> When there are GPIO drivers where we seriously need (and can handle
> simultaneously) more than 32 bits, we can still extend the API. For now,
> the cases where it is used is typically creating 8/16/32 bit busses with
> GPIO lines, and on 64bit architectures even 64bit busses.
>
> For this, the current API is working fine, even enabling userland access
> via sysfs.
Fair enough. I didn't see the first round of patches. You probably can
still use for_each_set_bit though (maybe convert the mask to unsigned
long first to match the bitops API):
for_each_set_bit(j, &gbc->mask, BITS_PER_LONG)
...
>>> + unsigned bit = 1;
>>> +
>>> + for (j = 0; j < sizeof(unsigned) * 8; j++, bit <<= 1) {
>>> + if (gbc->mask & bit)
>>> + gbc->gc->set(gbc->gc, gbc->gc->base + j,
>>> + (remapped >> j) & 1);
>>> + }
>>
>> This doesn't clear pins which are set to zero?
>
> It does. gbc->mask only masks which bits to set and clear. remapped
> contains the actual bit values to set. 0 or 1.
Ugh, for some reason I was thinking that the gpio set function only
drove bits that were set in the mask (and had an analogous clear
function). Ignore me :-).
~Ryan
next prev parent reply other threads:[~2012-10-15 22:05 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-12 19:11 [PATCH RFC 0/6 v3] gpio: Add block GPIO Roland Stigge
2012-10-12 19:11 ` Roland Stigge
2012-10-12 19:11 ` [PATCH RFC 1/6 v3] gpio: Add a block GPIO API to gpiolib Roland Stigge
2012-10-12 19:11 ` Roland Stigge
2012-10-15 5:20 ` Ryan Mallon
2012-10-15 5:20 ` Ryan Mallon
2012-10-15 17:20 ` Roland Stigge
2012-10-15 17:20 ` Roland Stigge
2012-10-15 22:05 ` Ryan Mallon [this message]
2012-10-15 22:05 ` Ryan Mallon
2012-10-15 22:55 ` Roland Stigge
2012-10-15 22:55 ` Roland Stigge
2012-10-15 19:56 ` Linus Walleij
2012-10-15 19:56 ` Linus Walleij
2012-10-12 19:11 ` [PATCH RFC 2/6 v3] gpio: Add sysfs support to block GPIO API Roland Stigge
2012-10-12 19:11 ` Roland Stigge
2012-10-15 5:35 ` Ryan Mallon
2012-10-15 5:35 ` Ryan Mallon
2012-10-15 18:01 ` Roland Stigge
2012-10-15 18:01 ` Roland Stigge
2012-10-15 18:07 ` Jean-Christophe PLAGNIOL-VILLARD
2012-10-15 18:07 ` Jean-Christophe PLAGNIOL-VILLARD
2012-10-15 18:15 ` Roland Stigge
2012-10-15 18:15 ` Roland Stigge
2012-10-15 18:19 ` Greg Kroah-Hartman
2012-10-15 18:19 ` Greg Kroah-Hartman
2012-10-15 20:30 ` Linus Walleij
2012-10-15 20:30 ` Linus Walleij
2012-10-15 21:38 ` Roland Stigge
2012-10-15 21:38 ` Roland Stigge
2012-10-16 8:43 ` Jean-Christophe PLAGNIOL-VILLARD
2012-10-16 8:43 ` Jean-Christophe PLAGNIOL-VILLARD
2012-10-18 4:38 ` Daniel Glöckner
2012-10-18 4:38 ` Daniel Glöckner
2012-10-19 10:29 ` Linus Walleij
2012-10-19 10:29 ` Linus Walleij
2012-10-12 19:11 ` [PATCH RFC 3/6 v3] gpio: Add device tree " Roland Stigge
2012-10-12 19:11 ` Roland Stigge
2012-10-12 19:11 ` [PATCH RFC 4/6 v3] gpio-max730x: Add " Roland Stigge
2012-10-12 19:11 ` Roland Stigge
2012-10-12 19:11 ` [PATCH RFC 5/6 v3] gpio-lpc32xx: " Roland Stigge
2012-10-12 19:11 ` Roland Stigge
2012-10-12 19:11 ` [PATCH RFC 6/6 v3] gpio-generic: " Roland Stigge
2012-10-12 19:11 ` Roland Stigge
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=507C888C.7040903@gmail.com \
--to=rmallon@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.