diff options
author | 2025-02-20 10:57:01 +0100 | |
---|---|---|
committer | 2025-02-26 11:17:39 +0100 | |
commit | 9b407312755fd5db012413ca005f0f3a661db8dd (patch) | |
tree | 20a68dc19556ab93299286cbf877f2eb569f5617 | |
parent | gpiolib: wrap gpio_chip::set() (diff) | |
download | wireguard-linux-9b407312755fd5db012413ca005f0f3a661db8dd.tar.xz wireguard-linux-9b407312755fd5db012413ca005f0f3a661db8dd.zip |
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>
-rw-r--r-- | drivers/gpio/gpiolib.c | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index a83494dd3e12..d26cad6442bf 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3582,21 +3582,33 @@ 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; + int ret; + 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; + return 0; + } - /* 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, @@ -3606,7 +3618,7 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, unsigned long *value_bitmap) { struct gpio_chip *gc; - int i = 0; + int i = 0, ret; /* * 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, 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); if (i == array_size) @@ -3706,8 +3721,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); |