History

bitops: introduce the for_each_set_clump8 macro

Pach series "Introduce the for_each_set_clump8 macro", v18. While adding GPIO get_multiple/set_multiple callback support for various drivers, I noticed a pattern of looping manifesting that would be useful standardized as a macro. This patchset introduces the for_each_set_clump8 macro and utilizes it in several GPIO drivers. The for_each_set_clump macro8 facilitates a for-loop syntax that iterates over a memory region entire groups of set bits at a time. For example, suppose you would like to iterate over a 32-bit integer 8 bits at a time, skipping over 8-bit groups with no set bit, where XXXXXXXX represents the current 8-bit group: Example: 10111110 00000000 11111111 00110011 First loop: 10111110 00000000 11111111 XXXXXXXX Second loop: 10111110 00000000 XXXXXXXX 00110011 Third loop: XXXXXXXX 00000000 11111111 00110011 Each iteration of the loop returns the next 8-bit group that has at least one set bit. The for_each_set_clump8 macro has four parameters: * start: set to the bit offset of the current clump * clump: set to the current clump value * bits: bitmap to search within * size: bitmap size in number of bits In this version of the patchset, the for_each_set_clump macro has been reimplemented and simplified based on the suggestions provided by Rasmus Villemoes and Andy Shevchenko in the version 4 submission. In particular, the function of the for_each_set_clump macro has been restricted to handle only 8-bit clumps; the drivers that use the for_each_set_clump macro only handle 8-bit ports so a generic for_each_set_clump implementation is not necessary. Thus, a solution for large clumps (i.e. those larger than the width of a bitmap word) can be postponed until a driver appears that actually requires such a generic for_each_set_clump implementation. For what it's worth, a semi-generic for_each_set_clump (i.e. for clumps smaller than the width of a bitmap word) can be implemented by simply replacing the hardcoded '8' and '0xFF' instances with respective variables. I have not yet had a need for such an implementation, and since it falls short of a true generic for_each_set_clump function, I have decided to forgo such an implementation for now. In addition, the bitmap_get_value8 and bitmap_set_value8 functions are introduced to get and set 8-bit values respectively. Their use is based on the behavior suggested in the patchset version 4 review. This patch (of 14): This macro iterates for each 8-bit group of bits (clump) with set bits, within a bitmap memory region. For each iteration, "start" is set to the bit offset of the found clump, while the respective clump value is stored to the location pointed by "clump". Additionally, the bitmap_get_value8 and bitmap_set_value8 functions are introduced to respectively get and set an 8-bit value in a bitmap memory region. [gustavo@embeddedor.com: fix potential sign-extension overflow] Link: http://lkml.kernel.org/r/20191015184657.GA26541@embeddedor [akpm@linux-foundation.org: s/ULL/UL/, per Joe] [vilhelm.gray@gmail.com: add for_each_set_clump8 documentation] Link: http://lkml.kernel.org/r/20191016161825.301082-1-vilhelm.gray@gmail.com Link: http://lkml.kernel.org/r/893c3b4f03266c9496137cc98ac2b1bd27f92c73.1570641097.git.vilhelm.gray@gmail.com Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com> Suggested-by: Andy Shevchenko <andy.shevchenko@gmail.com> Suggested-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Suggested-by: Lukas Wunner <lukas@wunner.de> Tested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com> Cc: Masahiro Yamada <yamada.masahiro@socionext.com> Cc: Geert Uytterhoeven <geert@linux-m68k.org> Cc: Phil Reid <preid@electromag.com.au> Cc: Geert Uytterhoeven <geert+renesas@glider.be> Cc: Mathias Duckeck <m.duckeck@kunbus.de> Cc: Morten Hein Tiljeset <morten.tiljeset@prevas.dk> Cc: Sean Nyekjaer <sean.nyekjaer@prevas.dk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

William Breathitt Gray committed 6 years ago

Commit 169c4741 parent 5e1aada4 files · +78 −0Browse files

Showing the changes to include/linux (2 of 4 files). Show all

Unified · Split

2 files
  1. include/linux/bitmap.h +35 −0
  2. include/linux/bitops.h +12 −0
include/linux/bitmap.h+35−0
@@ -66,6 +66,8 @@ · 65 unmodified lines
66 * bitmap_allocate_region(bitmap, pos, order) Allocate specified bit region66 * bitmap_allocate_region(bitmap, pos, order) Allocate specified bit region
67 * bitmap_from_arr32(dst, buf, nbits) Copy nbits from u32[] buf to dst67 * bitmap_from_arr32(dst, buf, nbits) Copy nbits from u32[] buf to dst
68 * bitmap_to_arr32(buf, src, nbits) Copy nbits from buf to u32[] dst68 * bitmap_to_arr32(buf, src, nbits) Copy nbits from buf to u32[] dst
69 * bitmap_get_value8(map, start) Get 8bit value from map at start
70 * bitmap_set_value8(map, value, start) Set 8bit value to map at start
69 *71 *
70 * Note, bitmap_zero() and bitmap_fill() operate over the region of72 * Note, bitmap_zero() and bitmap_fill() operate over the region of
71 * unsigned longs, that is, bits behind bitmap till the unsigned long73 * unsigned longs, that is, bits behind bitmap till the unsigned long
@@ -489,6 +491,39 @@ static inline void bitmap_from_u64(unsigned long *dst, u64 mask) · 417 unmodified lines
489 dst[1] = mask >> 32;491 dst[1] = mask >> 32;
490}492}
491 493
494/**
495 * bitmap_get_value8 - get an 8-bit value within a memory region
496 * @map: address to the bitmap memory region
497 * @start: bit offset of the 8-bit value; must be a multiple of 8
498 *
499 * Returns the 8-bit value located at the @start bit offset within the @src
500 * memory region.
501 */
502static inline unsigned long bitmap_get_value8(const unsigned long *map,
503 unsigned long start)
504{
505 const size_t index = BIT_WORD(start);
506 const unsigned long offset = start % BITS_PER_LONG;
507
508 return (map[index] >> offset) & 0xFF;
509}
510
511/**
512 * bitmap_set_value8 - set an 8-bit value within a memory region
513 * @map: address to the bitmap memory region
514 * @value: the 8-bit value; values wider than 8 bits may clobber bitmap
515 * @start: bit offset of the 8-bit value; must be a multiple of 8
516 */
517static inline void bitmap_set_value8(unsigned long *map, unsigned long value,
518 unsigned long start)
519{
520 const size_t index = BIT_WORD(start);
521 const unsigned long offset = start % BITS_PER_LONG;
522
523 map[index] &= ~(0xFFUL << offset);
524 map[index] |= value << offset;
525}
526
492#endif /* __ASSEMBLY__ */527#endif /* __ASSEMBLY__ */
493 528
494#endif /* __LINUX_BITMAP_H */529#endif /* __LINUX_BITMAP_H */
include/linux/bitops.h+12−0
@@ -47,6 +47,18 @@ extern unsigned long __sw_hweight64(__u64 w); · 46 unmodified lines
47 (bit) < (size); \47 (bit) < (size); \
48 (bit) = find_next_zero_bit((addr), (size), (bit) + 1))48 (bit) = find_next_zero_bit((addr), (size), (bit) + 1))
49 49
50/**
51 * for_each_set_clump8 - iterate over bitmap for each 8-bit clump with set bits
52 * @start: bit offset to start search and to store the current iteration offset
53 * @clump: location to store copy of current 8-bit clump
54 * @bits: bitmap address to base the search on
55 * @size: bitmap size in number of bits
56 */
57#define for_each_set_clump8(start, clump, bits, size) \
58 for ((start) = find_first_clump8(&(clump), (bits), (size)); \
59 (start) < (size); \
60 (start) = find_next_clump8(&(clump), (bits), (size), (start) + 8))
61
50static inline int get_bitmask_order(unsigned int count)62static inline int get_bitmask_order(unsigned int count)
51{63{
52 int order;64 int order;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t