public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
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


  reply	other threads:[~2012-10-15 22:05 UTC|newest]

Thread overview: 22+ 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 ` [PATCH RFC 1/6 v3] gpio: Add a block GPIO API to gpiolib Roland Stigge
2012-10-15  5:20   ` Ryan Mallon
2012-10-15 17:20     ` Roland Stigge
2012-10-15 22:05       ` Ryan Mallon [this message]
2012-10-15 22:55         ` Roland Stigge
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-15  5:35   ` Ryan Mallon
2012-10-15 18:01     ` Roland Stigge
2012-10-15 18:07   ` Jean-Christophe PLAGNIOL-VILLARD
2012-10-15 18:15     ` Roland Stigge
2012-10-15 18:19     ` Greg Kroah-Hartman
2012-10-15 20:30       ` Linus Walleij
2012-10-15 21:38         ` Roland Stigge
2012-10-16  8:43         ` Jean-Christophe PLAGNIOL-VILLARD
2012-10-18  4:38         ` Daniel Glöckner
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 ` [PATCH RFC 4/6 v3] gpio-max730x: Add " Roland Stigge
2012-10-12 19:11 ` [PATCH RFC 5/6 v3] gpio-lpc32xx: " Roland Stigge
2012-10-12 19:11 ` [PATCH RFC 6/6 v3] gpio-generic: " 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=broonie@opensource.wolfsonmicro.com \
    --cc=grant.likely@secretlab.ca \
    --cc=highguy@gmail.com \
    --cc=jbe@pengutronix.de \
    --cc=linus.walleij@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=plagnioj@jcrosoft.com \
    --cc=stigge@antcom.de \
    --cc=w.sang@pengutronix.de \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox