gpiolib: rework the wrapper around gpio_chip::set_multiple()

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.

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Link: https://lore.kernel.org/r/20250220-gpio-set-retval-v2-4-bc4cfd38dae3@linaro.org
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
This commit is contained in:
Bartosz Golaszewski 2025-02-20 10:57:01 +01:00
parent d36058b89a
commit 9b40731275

View File

@ -3582,21 +3582,33 @@ static int gpiod_set_raw_value_commit(struct gpio_desc *desc, bool value)
* defines which outputs are to be changed * defines which outputs are to be changed
* @bits: bit value array; one bit per output; BITS_PER_LONG bits per word * @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 * 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, static int gpiochip_set_multiple(struct gpio_chip *gc,
unsigned long *mask, unsigned long *bits) unsigned long *mask, unsigned long *bits)
{ {
unsigned int i;
int ret;
lockdep_assert_held(&gc->gpiodev->srcu); lockdep_assert_held(&gc->gpiodev->srcu);
if (WARN_ON(unlikely(!gc->set_multiple && !gc->set)))
return -EOPNOTSUPP;
if (gc->set_multiple) { if (gc->set_multiple) {
gc->set_multiple(gc, mask, bits); gc->set_multiple(gc, mask, bits);
} else { return 0;
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));
} }
/* 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, int gpiod_set_array_value_complex(bool raw, bool can_sleep,
@ -3606,7 +3618,7 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
unsigned long *value_bitmap) unsigned long *value_bitmap)
{ {
struct gpio_chip *gc; struct gpio_chip *gc;
int i = 0; int i = 0, ret;
/* /*
* Validate array_info against desc_array and its size. * Validate array_info against desc_array and its size.
@ -3629,7 +3641,10 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
bitmap_xor(value_bitmap, value_bitmap, bitmap_xor(value_bitmap, value_bitmap,
array_info->invert_mask, array_size); array_info->invert_mask, array_size);
gpio_chip_set_multiple(gc, array_info->set_mask, value_bitmap); ret = gpiochip_set_multiple(gc, array_info->set_mask,
value_bitmap);
if (ret)
return ret;
i = find_first_zero_bit(array_info->set_mask, array_size); i = find_first_zero_bit(array_info->set_mask, array_size);
if (i == array_size) if (i == array_size)
@ -3706,8 +3721,11 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
} while ((i < array_size) && } while ((i < array_size) &&
gpio_device_chip_cmp(desc_array[i]->gdev, guard.gc)); gpio_device_chip_cmp(desc_array[i]->gdev, guard.gc));
/* push collected bits to outputs */ /* push collected bits to outputs */
if (count != 0) if (count != 0) {
gpio_chip_set_multiple(guard.gc, mask, bits); ret = gpiochip_set_multiple(guard.gc, mask, bits);
if (ret)
return ret;
}
if (mask != fastpath_mask) if (mask != fastpath_mask)
bitmap_free(mask); bitmap_free(mask);