* [PATCH v1 0/3] gpio: aggregator: Further improvements @ 2020-07-18 21:26 Andy Shevchenko 2020-07-18 21:26 ` [PATCH v1 1/3] gpio: aggregator: Refactor ->{get,set}_multiple() to make Sparse happy Andy Shevchenko ` (3 more replies) 0 siblings, 4 replies; 9+ messages in thread From: Andy Shevchenko @ 2020-07-18 21:26 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski, linux-gpio, Geert Uytterhoeven Cc: Andy Shevchenko Patch 1 makes sparse happy about locking and, in my opinion, improves readability, though increases LOC count. Patch 2 simplifies parser by using existing helpers. Patch 3 refactors loop in parser for better readability in my opinion. It might be you have different opinions about patches 1 and 3, we may discuss. Compile tested only. Andy Shevchenko (3): gpio: aggregator: Refactor ->{get,set}_multiple() to make Sparse happy gpio: aggregator: Simplify isrange() by using get_option() gpio: aggregator: Assign name and offsets only once in a loop drivers/gpio/gpio-aggregator.c | 110 +++++++++++++++++---------------- 1 file changed, 57 insertions(+), 53 deletions(-) -- 2.27.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v1 1/3] gpio: aggregator: Refactor ->{get,set}_multiple() to make Sparse happy 2020-07-18 21:26 [PATCH v1 0/3] gpio: aggregator: Further improvements Andy Shevchenko @ 2020-07-18 21:26 ` Andy Shevchenko 2020-08-05 14:56 ` Geert Uytterhoeven 2020-07-18 21:26 ` [PATCH v1 2/3] gpio: aggregator: Simplify isrange() by using get_option() Andy Shevchenko ` (2 subsequent siblings) 3 siblings, 1 reply; 9+ messages in thread From: Andy Shevchenko @ 2020-07-18 21:26 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski, linux-gpio, Geert Uytterhoeven Cc: Andy Shevchenko Sparse can't see locking scheme used in ->get_multiple() and ->set_multiple() callbacks. CHECK .../drivers/gpio/gpio-aggregator.c .../spinlock.h:409:9: warning: context imbalance in 'gpio_fwd_get_multiple' - unexpected unlock .../spinlock.h:409:9: warning: context imbalance in 'gpio_fwd_set_multiple' - unexpected unlock Refactor them to have better readability and make Sparse happy. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> --- drivers/gpio/gpio-aggregator.c | 70 +++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 424a3d25350b..5be166e73381 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -333,20 +333,14 @@ static int gpio_fwd_get(struct gpio_chip *chip, unsigned int offset) return gpiod_get_value(fwd->descs[offset]); } -static int gpio_fwd_get_multiple(struct gpio_chip *chip, unsigned long *mask, +static int gpio_fwd_get_multiple(struct gpiochip_fwd *fwd, unsigned long *mask, unsigned long *bits) { - struct gpiochip_fwd *fwd = gpiochip_get_data(chip); - unsigned long *values, flags = 0; struct gpio_desc **descs; + unsigned long *values; unsigned int i, j = 0; int error; - if (chip->can_sleep) - mutex_lock(&fwd->mlock); - else - spin_lock_irqsave(&fwd->slock, flags); - /* Both values bitmap and desc pointers are stored in tmp[] */ values = &fwd->tmp[0]; descs = (void *)&fwd->tmp[BITS_TO_LONGS(fwd->chip.ngpio)]; @@ -356,16 +350,32 @@ static int gpio_fwd_get_multiple(struct gpio_chip *chip, unsigned long *mask, descs[j++] = fwd->descs[i]; error = gpiod_get_array_value(j, descs, NULL, values); - if (!error) { - j = 0; - for_each_set_bit(i, mask, fwd->chip.ngpio) - __assign_bit(i, bits, test_bit(j++, values)); - } + if (error) + return error; - if (chip->can_sleep) + j = 0; + for_each_set_bit(i, mask, fwd->chip.ngpio) + __assign_bit(i, bits, test_bit(j++, values)); + + return 0; +} + +static int gpio_fwd_get_multiple_locked(struct gpio_chip *chip, + unsigned long *mask, unsigned long *bits) +{ + struct gpiochip_fwd *fwd = gpiochip_get_data(chip); + unsigned long flags; + int error; + + if (chip->can_sleep) { + mutex_lock(&fwd->mlock); + error = gpio_fwd_get_multiple(fwd, mask, bits); mutex_unlock(&fwd->mlock); - else + } else { + spin_lock_irqsave(&fwd->slock, flags); + error = gpio_fwd_get_multiple(fwd, mask, bits); spin_unlock_irqrestore(&fwd->slock, flags); + } return error; } @@ -377,19 +387,13 @@ static void gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value) gpiod_set_value(fwd->descs[offset], value); } -static void gpio_fwd_set_multiple(struct gpio_chip *chip, unsigned long *mask, +static void gpio_fwd_set_multiple(struct gpiochip_fwd *fwd, unsigned long *mask, unsigned long *bits) { - struct gpiochip_fwd *fwd = gpiochip_get_data(chip); - unsigned long *values, flags = 0; struct gpio_desc **descs; + unsigned long *values; unsigned int i, j = 0; - if (chip->can_sleep) - mutex_lock(&fwd->mlock); - else - spin_lock_irqsave(&fwd->slock, flags); - /* Both values bitmap and desc pointers are stored in tmp[] */ values = &fwd->tmp[0]; descs = (void *)&fwd->tmp[BITS_TO_LONGS(fwd->chip.ngpio)]; @@ -400,11 +404,23 @@ static void gpio_fwd_set_multiple(struct gpio_chip *chip, unsigned long *mask, } gpiod_set_array_value(j, descs, NULL, values); +} - if (chip->can_sleep) +static void gpio_fwd_set_multiple_locked(struct gpio_chip *chip, + unsigned long *mask, unsigned long *bits) +{ + struct gpiochip_fwd *fwd = gpiochip_get_data(chip); + unsigned long flags; + + if (chip->can_sleep) { + mutex_lock(&fwd->mlock); + gpio_fwd_set_multiple(fwd, mask, bits); mutex_unlock(&fwd->mlock); - else + } else { + spin_lock_irqsave(&fwd->slock, flags); + gpio_fwd_set_multiple(fwd, mask, bits); spin_unlock_irqrestore(&fwd->slock, flags); + } } static int gpio_fwd_set_config(struct gpio_chip *chip, unsigned int offset, @@ -470,9 +486,9 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev, chip->direction_input = gpio_fwd_direction_input; chip->direction_output = gpio_fwd_direction_output; chip->get = gpio_fwd_get; - chip->get_multiple = gpio_fwd_get_multiple; + chip->get_multiple = gpio_fwd_get_multiple_locked; chip->set = gpio_fwd_set; - chip->set_multiple = gpio_fwd_set_multiple; + chip->set_multiple = gpio_fwd_set_multiple_locked; chip->base = -1; chip->ngpio = ngpios; fwd->descs = descs; -- 2.27.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v1 1/3] gpio: aggregator: Refactor ->{get,set}_multiple() to make Sparse happy 2020-07-18 21:26 ` [PATCH v1 1/3] gpio: aggregator: Refactor ->{get,set}_multiple() to make Sparse happy Andy Shevchenko @ 2020-08-05 14:56 ` Geert Uytterhoeven 2020-08-10 11:09 ` Andy Shevchenko 0 siblings, 1 reply; 9+ messages in thread From: Geert Uytterhoeven @ 2020-08-05 14:56 UTC (permalink / raw) To: Andy Shevchenko Cc: Linus Walleij, Bartosz Golaszewski, open list:GPIO SUBSYSTEM Hi Andy, On Sat, Jul 18, 2020 at 11:26 PM Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote: > Sparse can't see locking scheme used in ->get_multiple() and > ->set_multiple() callbacks. > CHECK .../drivers/gpio/gpio-aggregator.c > .../spinlock.h:409:9: warning: context imbalance in 'gpio_fwd_get_multiple' - unexpected unlock > .../spinlock.h:409:9: warning: context imbalance in 'gpio_fwd_set_multiple' - unexpected unlock > > Refactor them to have better readability and make Sparse happy. > > Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Thanks for your patch! > --- a/drivers/gpio/gpio-aggregator.c > +++ b/drivers/gpio/gpio-aggregator.c > +static int gpio_fwd_get_multiple_locked(struct gpio_chip *chip, > + unsigned long *mask, unsigned long *bits) Trading one static analysis tool error for a different one? ;-) ERROR: code indent should use tabs where possible > @@ -400,11 +404,23 @@ static void gpio_fwd_set_multiple(struct gpio_chip *chip, unsigned long *mask, > } > > gpiod_set_array_value(j, descs, NULL, values); > +} > > - if (chip->can_sleep) > +static void gpio_fwd_set_multiple_locked(struct gpio_chip *chip, > + unsigned long *mask, unsigned long *bits) ERROR: code indent should use tabs where possible With the above checkpatch errors fixed: Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Code size impact is +52 bytes with arm-linux-gnueabihf-gcc 7.5.0. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 1/3] gpio: aggregator: Refactor ->{get,set}_multiple() to make Sparse happy 2020-08-05 14:56 ` Geert Uytterhoeven @ 2020-08-10 11:09 ` Andy Shevchenko 0 siblings, 0 replies; 9+ messages in thread From: Andy Shevchenko @ 2020-08-10 11:09 UTC (permalink / raw) To: Geert Uytterhoeven Cc: Linus Walleij, Bartosz Golaszewski, open list:GPIO SUBSYSTEM On Wed, Aug 05, 2020 at 04:56:06PM +0200, Geert Uytterhoeven wrote: > On Sat, Jul 18, 2020 at 11:26 PM Andy Shevchenko > <andriy.shevchenko@linux.intel.com> wrote: ... > ERROR: code indent should use tabs where possible ... > ERROR: code indent should use tabs where possible > With the above checkpatch errors fixed: > Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Thanks, I'll send it separately, patch 2 needs to be thought thru a bit more. -- With Best Regards, Andy Shevchenko ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v1 2/3] gpio: aggregator: Simplify isrange() by using get_option() 2020-07-18 21:26 [PATCH v1 0/3] gpio: aggregator: Further improvements Andy Shevchenko 2020-07-18 21:26 ` [PATCH v1 1/3] gpio: aggregator: Refactor ->{get,set}_multiple() to make Sparse happy Andy Shevchenko @ 2020-07-18 21:26 ` Andy Shevchenko 2020-08-05 14:37 ` Geert Uytterhoeven 2020-07-18 21:26 ` [PATCH v1 3/3] gpio: aggregator: Assign name and offsets only once in a loop Andy Shevchenko 2020-07-21 9:46 ` [PATCH v1 0/3] gpio: aggregator: Further improvements Linus Walleij 3 siblings, 1 reply; 9+ messages in thread From: Andy Shevchenko @ 2020-07-18 21:26 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski, linux-gpio, Geert Uytterhoeven Cc: Andy Shevchenko We already have a nice helper called get_option() which can be used to validate the input format. Simplify isrange() by using it. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> --- drivers/gpio/gpio-aggregator.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 5be166e73381..de9ae622ca23 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -64,30 +64,17 @@ static char *get_arg(char **args) static bool isrange(const char *s) { - size_t n; + char **args = (char **)&s; + int dummy; + int res; - if (IS_ERR_OR_NULL(s)) + if (IS_ERR_OR_NULL(s) || *s == '\0') return false; - while (1) { - n = strspn(s, "0123456789"); - if (!n) - return false; - - s += n; - - switch (*s++) { - case '\0': - return true; - - case '-': - case ',': - break; - - default: - return false; - } - } + do { + res = get_option(args, &dummy); + } while (res); + return **args == '\0'; } static int aggr_add_gpio(struct gpio_aggregator *aggr, const char *key, -- 2.27.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v1 2/3] gpio: aggregator: Simplify isrange() by using get_option() 2020-07-18 21:26 ` [PATCH v1 2/3] gpio: aggregator: Simplify isrange() by using get_option() Andy Shevchenko @ 2020-08-05 14:37 ` Geert Uytterhoeven 0 siblings, 0 replies; 9+ messages in thread From: Geert Uytterhoeven @ 2020-08-05 14:37 UTC (permalink / raw) To: Andy Shevchenko Cc: Linus Walleij, Bartosz Golaszewski, open list:GPIO SUBSYSTEM Hi Andy, On Sat, Jul 18, 2020 at 11:26 PM Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote: > We already have a nice helper called get_option() which can be used > to validate the input format. Simplify isrange() by using it. > > Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Thanks for your patch! > --- a/drivers/gpio/gpio-aggregator.c > +++ b/drivers/gpio/gpio-aggregator.c > @@ -64,30 +64,17 @@ static char *get_arg(char **args) > > static bool isrange(const char *s) > { > - size_t n; > + char **args = (char **)&s; > + int dummy; > + int res; > > - if (IS_ERR_OR_NULL(s)) > + if (IS_ERR_OR_NULL(s) || *s == '\0') > return false; > > - while (1) { > - n = strspn(s, "0123456789"); > - if (!n) > - return false; > - > - s += n; > - > - switch (*s++) { > - case '\0': > - return true; > - > - case '-': > - case ',': > - break; > - > - default: > - return false; > - } > - } > + do { > + res = get_option(args, &dummy); > + } while (res); > + return **args == '\0'; > } This change makes isrange() return true for all of the following, although they are not valid ranges: -7 --7 7- 7--9 Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v1 3/3] gpio: aggregator: Assign name and offsets only once in a loop 2020-07-18 21:26 [PATCH v1 0/3] gpio: aggregator: Further improvements Andy Shevchenko 2020-07-18 21:26 ` [PATCH v1 1/3] gpio: aggregator: Refactor ->{get,set}_multiple() to make Sparse happy Andy Shevchenko 2020-07-18 21:26 ` [PATCH v1 2/3] gpio: aggregator: Simplify isrange() by using get_option() Andy Shevchenko @ 2020-07-18 21:26 ` Andy Shevchenko 2020-07-19 10:12 ` Andy Shevchenko 2020-07-21 9:46 ` [PATCH v1 0/3] gpio: aggregator: Further improvements Linus Walleij 3 siblings, 1 reply; 9+ messages in thread From: Andy Shevchenko @ 2020-07-18 21:26 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski, linux-gpio, Geert Uytterhoeven Cc: Andy Shevchenko The for-loop looks a bit hard to read when we extract two arguments per iteration. The 'do {} while (true)' makes it easier to read despite being infinite loop. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> --- drivers/gpio/gpio-aggregator.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index de9ae622ca23..962ec9373d6f 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -109,14 +109,17 @@ static int aggr_parse(struct gpio_aggregator *aggr) if (!bitmap) return -ENOMEM; - for (name = get_arg(&args), offsets = get_arg(&args); name; - offsets = get_arg(&args)) { + do { + name = get_arg(&args); + if (!name) + break; if (IS_ERR(name)) { pr_err("Cannot get GPIO specifier: %pe\n", name); error = PTR_ERR(name); goto free_bitmap; } + offsets = get_arg(&args); if (!isrange(offsets)) { /* Named GPIO line */ error = aggr_add_gpio(aggr, name, U16_MAX, &n); @@ -139,9 +142,7 @@ static int aggr_parse(struct gpio_aggregator *aggr) if (error) goto free_bitmap; } - - name = get_arg(&args); - } + } while (true); if (!n) { pr_err("No GPIOs specified\n"); -- 2.27.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v1 3/3] gpio: aggregator: Assign name and offsets only once in a loop 2020-07-18 21:26 ` [PATCH v1 3/3] gpio: aggregator: Assign name and offsets only once in a loop Andy Shevchenko @ 2020-07-19 10:12 ` Andy Shevchenko 0 siblings, 0 replies; 9+ messages in thread From: Andy Shevchenko @ 2020-07-19 10:12 UTC (permalink / raw) To: Andy Shevchenko Cc: Linus Walleij, Bartosz Golaszewski, open list:GPIO SUBSYSTEM, Geert Uytterhoeven On Sun, Jul 19, 2020 at 12:26 AM Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote: > > The for-loop looks a bit hard to read when we extract two arguments > per iteration. The 'do {} while (true)' makes it easier to read > despite being infinite loop. This is not gonna work. Please, discard this patch from the series. -- With Best Regards, Andy Shevchenko ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 0/3] gpio: aggregator: Further improvements 2020-07-18 21:26 [PATCH v1 0/3] gpio: aggregator: Further improvements Andy Shevchenko ` (2 preceding siblings ...) 2020-07-18 21:26 ` [PATCH v1 3/3] gpio: aggregator: Assign name and offsets only once in a loop Andy Shevchenko @ 2020-07-21 9:46 ` Linus Walleij 3 siblings, 0 replies; 9+ messages in thread From: Linus Walleij @ 2020-07-21 9:46 UTC (permalink / raw) To: Andy Shevchenko, Geert Uytterhoeven Cc: Bartosz Golaszewski, open list:GPIO SUBSYSTEM On Sat, Jul 18, 2020 at 11:26 PM Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote: > Patch 1 makes sparse happy about locking and, in my opinion, improves > readability, though increases LOC count. > Patch 2 simplifies parser by using existing helpers. > Patch 3 refactors loop in parser for better readability in my opinion. I see you retracted patch 3, but patch 1 & 2 looks good to me, I just would like Geert to have a look at them first, Geert? Yours, Linus Walleij ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2020-08-10 11:33 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-07-18 21:26 [PATCH v1 0/3] gpio: aggregator: Further improvements Andy Shevchenko 2020-07-18 21:26 ` [PATCH v1 1/3] gpio: aggregator: Refactor ->{get,set}_multiple() to make Sparse happy Andy Shevchenko 2020-08-05 14:56 ` Geert Uytterhoeven 2020-08-10 11:09 ` Andy Shevchenko 2020-07-18 21:26 ` [PATCH v1 2/3] gpio: aggregator: Simplify isrange() by using get_option() Andy Shevchenko 2020-08-05 14:37 ` Geert Uytterhoeven 2020-07-18 21:26 ` [PATCH v1 3/3] gpio: aggregator: Assign name and offsets only once in a loop Andy Shevchenko 2020-07-19 10:12 ` Andy Shevchenko 2020-07-21 9:46 ` [PATCH v1 0/3] gpio: aggregator: Further improvements Linus Walleij
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).