Skip to content

Commit c1c6ab8

Browse files
geertuYuryNorov
authored andcommitted
bitfield: Add non-constant field_{prep,get}() helpers
The existing FIELD_{GET,PREP}() macros are limited to compile-time constants. However, it is very common to prepare or extract bitfield elements where the bitfield mask is not a compile-time constant. To avoid this limitation, the AT91 clock driver and several other drivers already have their own non-const field_{prep,get}() macros. Make them available for general use by adding them to <linux/bitfield.h>, and improve them slightly: 1. Avoid evaluating macro parameters more than once, 2. Replace "ffs() - 1" by "__ffs()", 3. Support 64-bit use on 32-bit architectures, 4. Wire field_{get,prep}() to FIELD_{GET,PREP}() when mask is actually constant. This is deliberately not merged into the existing FIELD_{GET,PREP}() macros, as people expressed the desire to keep stricter variants for increased safety, or for performance critical paths. Yury: use __mask withing new macros. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Acked-by: Crt Mori <cmo@melexis.com> Acked-by: Nuno Sá <nuno.sa@analog.com> Acked-by: Richard Genoud <richard.genoud@bootlin.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com> Reviewed-by: Yury Norov (NVIDIA) <yury.norov@gmail.com> Signed-off-by: Yury Norov (NVIDIA) <yury.norov@gmail.com>
1 parent 2a6c045 commit c1c6ab8

1 file changed

Lines changed: 59 additions & 0 deletions

File tree

include/linux/bitfield.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
* FIELD_{GET,PREP} macros take as first parameter shifted mask
1818
* from which they extract the base mask and shift amount.
1919
* Mask must be a compilation time constant.
20+
* field_{get,prep} are variants that take a non-const mask.
2021
*
2122
* Example:
2223
*
@@ -240,4 +241,62 @@ __MAKE_OP(64)
240241
#undef __MAKE_OP
241242
#undef ____MAKE_OP
242243

244+
#define __field_prep(mask, val) \
245+
({ \
246+
__auto_type __mask = (mask); \
247+
typeof(__mask) __val = (val); \
248+
unsigned int __shift = BITS_PER_TYPE(__mask) <= 32 ? \
249+
__ffs(__mask) : __ffs64(__mask); \
250+
(__val << __shift) & __mask; \
251+
})
252+
253+
#define __field_get(mask, reg) \
254+
({ \
255+
__auto_type __mask = (mask); \
256+
typeof(__mask) __reg = (reg); \
257+
unsigned int __shift = BITS_PER_TYPE(__mask) <= 32 ? \
258+
__ffs(__mask) : __ffs64(__mask); \
259+
(__reg & __mask) >> __shift; \
260+
})
261+
262+
/**
263+
* field_prep() - prepare a bitfield element
264+
* @mask: shifted mask defining the field's length and position, must be
265+
* non-zero
266+
* @val: value to put in the field
267+
*
268+
* Return: field value masked and shifted to its final destination
269+
*
270+
* field_prep() masks and shifts up the value. The result should be
271+
* combined with other fields of the bitfield using logical OR.
272+
* Unlike FIELD_PREP(), @mask is not limited to a compile-time constant.
273+
* Typical usage patterns are a value stored in a table, or calculated by
274+
* shifting a constant by a variable number of bits.
275+
* If you want to ensure that @mask is a compile-time constant, please use
276+
* FIELD_PREP() directly instead.
277+
*/
278+
#define field_prep(mask, val) \
279+
(__builtin_constant_p(mask) ? __FIELD_PREP(mask, val, "field_prep: ") \
280+
: __field_prep(mask, val))
281+
282+
/**
283+
* field_get() - extract a bitfield element
284+
* @mask: shifted mask defining the field's length and position, must be
285+
* non-zero
286+
* @reg: value of entire bitfield
287+
*
288+
* Return: extracted field value
289+
*
290+
* field_get() extracts the field specified by @mask from the
291+
* bitfield passed in as @reg by masking and shifting it down.
292+
* Unlike FIELD_GET(), @mask is not limited to a compile-time constant.
293+
* Typical usage patterns are a value stored in a table, or calculated by
294+
* shifting a constant by a variable number of bits.
295+
* If you want to ensure that @mask is a compile-time constant, please use
296+
* FIELD_GET() directly instead.
297+
*/
298+
#define field_get(mask, reg) \
299+
(__builtin_constant_p(mask) ? __FIELD_GET(mask, reg, "field_get: ") \
300+
: __field_get(mask, reg))
301+
243302
#endif

0 commit comments

Comments
 (0)