Skip to content

Commit

Permalink
gpio: aggregator: Refactor ->{get, set}_multiple() to make Sparse happy
Browse files Browse the repository at this point in the history
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.

Code size impact is +52 bytes with arm-linux-gnueabihf-gcc 7.5.0.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
  • Loading branch information
Andy Shevchenko authored and Bartosz Golaszewski committed Aug 18, 2020
1 parent 329afb9 commit 01e8d85
Showing 1 changed file with 43 additions and 27 deletions.
70 changes: 43 additions & 27 deletions drivers/gpio/gpio-aggregator.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)];
Expand All @@ -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;
}
Expand All @@ -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)];
Expand All @@ -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,
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 01e8d85

Please sign in to comment.