Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+30 -12
+30 -12
drivers/gpio/gpiolib.c
··· 3582 3582 * defines which outputs are to be changed 3583 3583 * @bits: bit value array; one bit per output; BITS_PER_LONG bits per word 3584 3584 * defines the values the outputs specified by mask are to be set to 3585 + * 3586 + * Returns: 0 on success, negative error number on failure. 3585 3587 */ 3586 - static void gpio_chip_set_multiple(struct gpio_chip *gc, 3587 - unsigned long *mask, unsigned long *bits) 3588 + static int gpiochip_set_multiple(struct gpio_chip *gc, 3589 + unsigned long *mask, unsigned long *bits) 3588 3590 { 3591 + unsigned int i; 3592 + int ret; 3593 + 3589 3594 lockdep_assert_held(&gc->gpiodev->srcu); 3595 + 3596 + if (WARN_ON(unlikely(!gc->set_multiple && !gc->set))) 3597 + return -EOPNOTSUPP; 3590 3598 3591 3599 if (gc->set_multiple) { 3592 3600 gc->set_multiple(gc, mask, bits); 3593 - } else { 3594 - unsigned int i; 3595 - 3596 - /* set outputs if the corresponding mask bit is set */ 3597 - for_each_set_bit(i, mask, gc->ngpio) 3598 - gpiochip_set(gc, i, test_bit(i, bits)); 3601 + return 0; 3599 3602 } 3603 + 3604 + /* set outputs if the corresponding mask bit is set */ 3605 + for_each_set_bit(i, mask, gc->ngpio) { 3606 + ret = gpiochip_set(gc, i, test_bit(i, bits)); 3607 + if (ret) 3608 + break; 3609 + } 3610 + 3611 + return ret; 3600 3612 } 3601 3613 3602 3614 int gpiod_set_array_value_complex(bool raw, bool can_sleep, ··· 3618 3606 unsigned long *value_bitmap) 3619 3607 { 3620 3608 struct gpio_chip *gc; 3621 - int i = 0; 3609 + int i = 0, ret; 3622 3610 3623 3611 /* 3624 3612 * Validate array_info against desc_array and its size. ··· 3641 3629 bitmap_xor(value_bitmap, value_bitmap, 3642 3630 array_info->invert_mask, array_size); 3643 3631 3644 - gpio_chip_set_multiple(gc, array_info->set_mask, value_bitmap); 3632 + ret = gpiochip_set_multiple(gc, array_info->set_mask, 3633 + value_bitmap); 3634 + if (ret) 3635 + return ret; 3645 3636 3646 3637 i = find_first_zero_bit(array_info->set_mask, array_size); 3647 3638 if (i == array_size) ··· 3721 3706 } while ((i < array_size) && 3722 3707 gpio_device_chip_cmp(desc_array[i]->gdev, guard.gc)); 3723 3708 /* push collected bits to outputs */ 3724 - if (count != 0) 3725 - gpio_chip_set_multiple(guard.gc, mask, bits); 3709 + if (count != 0) { 3710 + ret = gpiochip_set_multiple(guard.gc, mask, bits); 3711 + if (ret) 3712 + return ret; 3713 + } 3726 3714 3727 3715 if (mask != fastpath_mask) 3728 3716 bitmap_free(mask);