in gpiolib.c [2568:2679]
int gpiod_get_array_value_complex(bool raw, bool can_sleep,
unsigned int array_size,
struct gpio_desc **desc_array,
struct gpio_array *array_info,
unsigned long *value_bitmap)
{
int ret, i = 0;
/*
* Validate array_info against desc_array and its size.
* It should immediately follow desc_array if both
* have been obtained from the same gpiod_get_array() call.
*/
if (array_info && array_info->desc == desc_array &&
array_size <= array_info->size &&
(void *)array_info == desc_array + array_info->size) {
if (!can_sleep)
WARN_ON(array_info->chip->can_sleep);
ret = gpio_chip_get_multiple(array_info->chip,
array_info->get_mask,
value_bitmap);
if (ret)
return ret;
if (!raw && !bitmap_empty(array_info->invert_mask, array_size))
bitmap_xor(value_bitmap, value_bitmap,
array_info->invert_mask, array_size);
i = find_first_zero_bit(array_info->get_mask, array_size);
if (i == array_size)
return 0;
} else {
array_info = NULL;
}
while (i < array_size) {
struct gpio_chip *gc = desc_array[i]->gdev->chip;
DECLARE_BITMAP(fastpath_mask, FASTPATH_NGPIO);
DECLARE_BITMAP(fastpath_bits, FASTPATH_NGPIO);
unsigned long *mask, *bits;
int first, j;
if (likely(gc->ngpio <= FASTPATH_NGPIO)) {
mask = fastpath_mask;
bits = fastpath_bits;
} else {
gfp_t flags = can_sleep ? GFP_KERNEL : GFP_ATOMIC;
mask = bitmap_alloc(gc->ngpio, flags);
if (!mask)
return -ENOMEM;
bits = bitmap_alloc(gc->ngpio, flags);
if (!bits) {
bitmap_free(mask);
return -ENOMEM;
}
}
bitmap_zero(mask, gc->ngpio);
if (!can_sleep)
WARN_ON(gc->can_sleep);
/* collect all inputs belonging to the same chip */
first = i;
do {
const struct gpio_desc *desc = desc_array[i];
int hwgpio = gpio_chip_hwgpio(desc);
__set_bit(hwgpio, mask);
i++;
if (array_info)
i = find_next_zero_bit(array_info->get_mask,
array_size, i);
} while ((i < array_size) &&
(desc_array[i]->gdev->chip == gc));
ret = gpio_chip_get_multiple(gc, mask, bits);
if (ret) {
if (mask != fastpath_mask)
bitmap_free(mask);
if (bits != fastpath_bits)
bitmap_free(bits);
return ret;
}
for (j = first; j < i; ) {
const struct gpio_desc *desc = desc_array[j];
int hwgpio = gpio_chip_hwgpio(desc);
int value = test_bit(hwgpio, bits);
if (!raw && test_bit(FLAG_ACTIVE_LOW, &desc->flags))
value = !value;
__assign_bit(j, value_bitmap, value);
trace_gpio_value(desc_to_gpio(desc), 1, value);
j++;
if (array_info)
j = find_next_zero_bit(array_info->get_mask, i,
j);
}
if (mask != fastpath_mask)
bitmap_free(mask);
if (bits != fastpath_bits)
bitmap_free(bits);
}
return 0;
}