diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index ad4ee4145db49d..05dae086c4d025 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -151,16 +151,16 @@ static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, spin_lock_irqsave(&chip->gpio_lock[0], flags); spin_lock(&chip->gpio_lock[1]); - bitmap_set_value(old, state[0], 0, width[0]); - bitmap_set_value(old, state[1], width[0], width[1]); + bitmap_set_value(old, 64, state[0], width[0], 0); + bitmap_set_value(old, 64, state[1], width[1], width[0]); bitmap_replace(new, old, bits, mask, gc->ngpio); - bitmap_set_value(old, state[0], 0, 32); - bitmap_set_value(old, state[1], 32, 32); + bitmap_set_value(old, 64, state[0], 32, 0); + bitmap_set_value(old, 64, state[1], 32, 32); state[0] = bitmap_get_value(new, 0, width[0]); state[1] = bitmap_get_value(new, width[0], width[1]); - bitmap_set_value(new, state[0], 0, 32); - bitmap_set_value(new, state[1], 32, 32); + bitmap_set_value(new, 64, state[0], 32, 0); + bitmap_set_value(new, 64, state[1], 32, 32); bitmap_xor(changed, old, new, 64); if (((u32 *)changed)[0]) diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index 386d0877734225..efb6199ea1e7e9 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -78,8 +78,9 @@ * bitmap_get_value(map, start, nbits) Get bit value of size * 'nbits' from map at start * bitmap_set_value8(map, value, start) Set 8bit value to map at start - * bitmap_set_value(map, value, start, nbits) Set bit value of size 'nbits' - * of map at start + * bitmap_set_value(map, nbits, value, value_width, start) + * Set bit value of size value_width + * to map at start * * Note, bitmap_zero() and bitmap_fill() operate over the region of * unsigned longs, that is, bits behind bitmap till the unsigned long @@ -610,30 +611,36 @@ static inline void bitmap_set_value8(unsigned long *map, unsigned long value, } /** - * bitmap_set_value - set n-bit value within a memory region + * bitmap_set_value - set value within a memory region * @map: address to the bitmap memory region - * @value: value of nbits - * @start: bit offset of the n-bit value - * @nbits: size of value in bits (must be between 1 and BITS_PER_LONG inclusive). + * @nbits: size of map in bits + * @value: value of clump + * @value_width: size of value in bits (must be between 1 and BITS_PER_LONG inclusive) + * @start: bit offset of the value */ -static inline void bitmap_set_value(unsigned long *map, - unsigned long value, - unsigned long start, unsigned long nbits) +static inline void bitmap_set_value(unsigned long *map, unsigned long nbits, + unsigned long value, unsigned long value_width, + unsigned long start) { - const size_t index = BIT_WORD(start); + const unsigned long index = BIT_WORD(start); + const unsigned long length = BIT_WORD(nbits); const unsigned long offset = start % BITS_PER_LONG; const unsigned long ceiling = round_up(start + 1, BITS_PER_LONG); const unsigned long space = ceiling - start; - value &= GENMASK(nbits - 1, 0); + value &= GENMASK(value_width - 1, 0); - if (space >= nbits) { - map[index] &= ~(GENMASK(nbits - 1, 0) << offset); + if (space >= value_width) { + map[index] &= ~(GENMASK(value_width - 1, 0) << offset); map[index] |= value << offset; } else { map[index + 0] &= ~BITMAP_FIRST_WORD_MASK(start); map[index + 0] |= value << offset; - map[index + 1] &= ~BITMAP_LAST_WORD_MASK(start + nbits); + + if (index + 1 >= length) + __builtin_unreachable(); + + map[index + 1] &= ~BITMAP_LAST_WORD_MASK(start + value_width); map[index + 1] |= value >> space; } } diff --git a/lib/test_bitmap.c b/lib/test_bitmap.c index 1c5791ff02cb07..7fafe6a0bc08c1 100644 --- a/lib/test_bitmap.c +++ b/lib/test_bitmap.c @@ -656,8 +656,8 @@ static void __init prepare_test_data(unsigned int index) unsigned long width = 0; for (i = 0; i < clump_test_data[index].count; i++) { - bitmap_set_value(clump_test_data[index].data, - clump_bitmap_data[(clump_test_data[index].offset)++], width, 32); + bitmap_set_value(clump_test_data[index].data, 256, + clump_bitmap_data[(clump_test_data[index].offset)++], 32, width); width += 32; } }