From: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxx> Make the existing wrapper around gpio_chip::set_multiple() consistent with the one for gpio_chip::set(): make it return int, add a lockdep assertion, warn on missing set callback and move the code a bit for better readability. Add return value checks in all call places. Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxx> --- drivers/gpio/gpiolib.c | 45 ++++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 7826bfb72104..1f078a20ce3d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3468,19 +3468,32 @@ static int gpiod_set_raw_value_commit(struct gpio_desc *desc, bool value) * defines which outputs are to be changed * @bits: bit value array; one bit per output; BITS_PER_LONG bits per word * defines the values the outputs specified by mask are to be set to + * + * Returns: 0 on success, negative error number on failure. */ -static void gpio_chip_set_multiple(struct gpio_chip *gc, - unsigned long *mask, unsigned long *bits) +static int gpiochip_set_multiple(struct gpio_chip *gc, + unsigned long *mask, unsigned long *bits) { + unsigned int i; + + lockdep_assert_held(&gc->gpiodev->srcu); + + if (WARN_ON(unlikely(!gc->set_multiple && !gc->set))) + return -EOPNOTSUPP; + if (gc->set_multiple) { gc->set_multiple(gc, mask, bits); - } else { - unsigned int i; - - /* set outputs if the corresponding mask bit is set */ - for_each_set_bit(i, mask, gc->ngpio) - gpiochip_set(gc, i, test_bit(i, bits)); + return 0; } + + /* set outputs if the corresponding mask bit is set */ + for_each_set_bit(i, mask, gc->ngpio) { + ret = gpiochip_set(gc, i, test_bit(i, bits)); + if (ret) + break; + } + + return ret; } int gpiod_set_array_value_complex(bool raw, bool can_sleep, @@ -3489,7 +3502,7 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, struct gpio_array *array_info, unsigned long *value_bitmap) { - int i = 0; + int i = 0, ret; /* * Validate array_info against desc_array and its size. @@ -3506,8 +3519,11 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, bitmap_xor(value_bitmap, value_bitmap, array_info->invert_mask, array_size); - gpio_chip_set_multiple(array_info->chip, array_info->set_mask, - value_bitmap); + ret = gpiochip_set_multiple(array_info->chip, + array_info->set_mask, + value_bitmap); + if (ret) + return ret; i = find_first_zero_bit(array_info->set_mask, array_size); if (i == array_size) @@ -3584,8 +3600,11 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, } while ((i < array_size) && gpio_device_chip_cmp(desc_array[i]->gdev, guard.gc)); /* push collected bits to outputs */ - if (count != 0) - gpio_chip_set_multiple(guard.gc, mask, bits); + if (count != 0) { + ret = gpiochip_set_multiple(guard.gc, mask, bits); + if (ret) + return ret; + } if (mask != fastpath_mask) bitmap_free(mask); -- 2.45.2