Commit 9b407312 authored by Bartosz Golaszewski's avatar Bartosz Golaszewski
Browse files

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: default avatarLinus Walleij <linus.walleij@linaro.org>
Acked-by: default avatarUwe 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: default avatarBartosz Golaszewski <bartosz.golaszewski@linaro.org>
parent d36058b8
Loading
Loading
Loading
Loading
+29 −11
Original line number Diff line number Diff line
@@ -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,
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));
	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);