[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <62a5058e460129155e4e7539e37140bd0f0d4abc.1762435376.git.geert+renesas@glider.be>
Date: Thu, 6 Nov 2025 14:34:01 +0100
From: Geert Uytterhoeven <geert+renesas@...der.be>
To: Yury Norov <yury.norov@...il.com>,
Michael Turquette <mturquette@...libre.com>,
Stephen Boyd <sboyd@...nel.org>,
Nicolas Ferre <nicolas.ferre@...rochip.com>,
Alexandre Belloni <alexandre.belloni@...tlin.com>,
Claudiu Beznea <claudiu.beznea@...on.dev>,
Giovanni Cabiddu <giovanni.cabiddu@...el.com>,
Herbert Xu <herbert@...dor.apana.org.au>,
David Miller <davem@...emloft.net>,
Linus Walleij <linus.walleij@...aro.org>,
Bartosz Golaszewski <brgl@...ev.pl>,
Joel Stanley <joel@....id.au>,
Andrew Jeffery <andrew@...econstruct.com.au>,
Crt Mori <cmo@...exis.com>,
Jonathan Cameron <jic23@...nel.org>,
Lars-Peter Clausen <lars@...afoo.de>,
Jacky Huang <ychuang3@...oton.com>,
Shan-Chun Hung <schung@...oton.com>,
Rasmus Villemoes <linux@...musvillemoes.dk>,
Jaroslav Kysela <perex@...ex.cz>,
Takashi Iwai <tiwai@...e.com>,
Johannes Berg <johannes@...solutions.net>,
Jakub Kicinski <kuba@...nel.org>,
Alex Elder <elder@...e.org>,
David Laight <david.laight.linux@...il.com>,
Vincent Mailhol <mailhol.vincent@...adoo.fr>,
Jason Baron <jbaron@...mai.com>,
Borislav Petkov <bp@...en8.de>,
Tony Luck <tony.luck@...el.com>,
Michael Hennerich <Michael.Hennerich@...log.com>,
Kim Seer Paller <kimseer.paller@...log.com>,
David Lechner <dlechner@...libre.com>,
Nuno Sá <nuno.sa@...log.com>,
Andy Shevchenko <andy@...nel.org>,
Richard Genoud <richard.genoud@...tlin.com>,
Cosmin Tanislav <demonsingur@...il.com>,
Biju Das <biju.das.jz@...renesas.com>,
Jianping Shen <Jianping.Shen@...bosch.com>,
Nathan Chancellor <nathan@...nel.org>,
Nick Desaulniers <nick.desaulniers+lkml@...il.com>,
Miquel Raynal <miquel.raynal@...tlin.com>,
Richard Weinberger <richard@....at>,
Vignesh Raghavendra <vigneshr@...com>
Cc: linux-clk@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org,
linux-renesas-soc@...r.kernel.org,
linux-crypto@...r.kernel.org,
linux-edac@...r.kernel.org,
qat-linux@...el.com,
linux-gpio@...r.kernel.org,
linux-aspeed@...ts.ozlabs.org,
linux-iio@...r.kernel.org,
linux-sound@...r.kernel.org,
linux-mtd@...ts.infradead.org,
linux-kernel@...r.kernel.org,
Geert Uytterhoeven <geert+renesas@...der.be>,
Jonathan Cameron <Jonathan.Cameron@...wei.com>,
Andy Shevchenko <andriy.shevchenko@...el.com>
Subject: [PATCH v6 13/26] 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.
Signed-off-by: Geert Uytterhoeven <geert+renesas@...der.be>
Acked-by: Alexandre Belloni <alexandre.belloni@...tlin.com>
Acked-by: Jonathan Cameron <Jonathan.Cameron@...wei.com>
Acked-by: Crt Mori <cmo@...exis.com>
Acked-by: Nuno Sá <nuno.sa@...log.com>
Acked-by: Richard Genoud <richard.genoud@...tlin.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@...el.com>
---
v6:
- Align \,
- Add Return sections to kerneldoc,
- Add Reviewed-by,
- Document field_{get,prep} in top comment block,
- Use less-checking __FIELD_{GET,PREP}() to avoid build issues with
clang and W=1:
https://lore.kernel.org/all/202510281335.UpSLYJG9-lkp@intel.com
https://lore.kernel.org/all/202510281414.DnejZh4n-lkp@intel.com
https://lore.kernel.org/all/202510281304.RK3J3c3t-lkp@intel.com
v5:
- Add Acked-by,
- Split off changes outside <linux/bitfield.h>,
- Document that mask must be non-zero,
- Document typical usage pattern,
- Recommend using FIELD_{PREP,GET}() directly to ensure compile-time
constant masks,
- Check BITS_PER_TYPE(mask) instead of sizeof(mask),
- Wire field_{get,prep}() to FIELD_{GET,PREP}() when mask is
constant, to improve type checking.
v4:
- Add Acked-by,
- Rebase on top of commit 7c68005a46108ffa ("crypto: qat - relocate
power management debugfs helper APIs") in v6.17-rc1,
- Convert more recently introduced upstream copies:
- drivers/edac/ie31200_edac.c
- drivers/iio/dac/ad3530r.c
v3:
- Add Acked-by,
- Drop underscores from macro parameters,
- Use __auto_type where possible,
- Correctly cast reg to the mask type,
- Introduces __val and __reg intermediates to simplify the actual
operation,
- Drop unneeded parentheses,
- Clarify having both FIELD_{GET,PREP}() and field_{get,prep}(),
v2:
- Cast val resp. reg to the mask type,
- Fix 64-bit use on 32-bit architectures,
- Convert new upstream users:
- drivers/crypto/intel/qat/qat_common/adf_gen4_pm_debugfs.c
- drivers/gpio/gpio-aspeed.c
- drivers/iio/temperature/mlx90614.c
- drivers/pinctrl/nuvoton/pinctrl-ma35.c
- sound/usb/mixer_quirks.c
- Convert new user queued in renesas-devel for v6.15:
- drivers/soc/renesas/rz-sysc.c
---
include/linux/bitfield.h | 59 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h
index bf8e0ae4b5b41038..f92e18c9629a59c6 100644
--- a/include/linux/bitfield.h
+++ b/include/linux/bitfield.h
@@ -17,6 +17,7 @@
* FIELD_{GET,PREP} macros take as first parameter shifted mask
* from which they extract the base mask and shift amount.
* Mask must be a compilation time constant.
+ * field_{get,prep} are variants that take a non-const mask.
*
* Example:
*
@@ -240,4 +241,62 @@ __MAKE_OP(64)
#undef __MAKE_OP
#undef ____MAKE_OP
+#define __field_prep(mask, val) \
+ ({ \
+ __auto_type __mask = (mask); \
+ typeof(mask) __val = (val); \
+ unsigned int __shift = BITS_PER_TYPE(mask) <= 32 ? \
+ __ffs(__mask) : __ffs64(__mask); \
+ (__val << __shift) & __mask; \
+ })
+
+#define __field_get(mask, reg) \
+ ({ \
+ __auto_type __mask = (mask); \
+ typeof(mask) __reg = (reg); \
+ unsigned int __shift = BITS_PER_TYPE(mask) <= 32 ? \
+ __ffs(__mask) : __ffs64(__mask); \
+ (__reg & __mask) >> __shift; \
+ })
+
+/**
+ * field_prep() - prepare a bitfield element
+ * @mask: shifted mask defining the field's length and position, must be
+ * non-zero
+ * @val: value to put in the field
+ *
+ * Return: field value masked and shifted to its final destination
+ *
+ * field_prep() masks and shifts up the value. The result should be
+ * combined with other fields of the bitfield using logical OR.
+ * Unlike FIELD_PREP(), @mask is not limited to a compile-time constant.
+ * Typical usage patterns are a value stored in a table, or calculated by
+ * shifting a constant by a variable number of bits.
+ * If you want to ensure that @mask is a compile-time constant, please use
+ * FIELD_PREP() directly instead.
+ */
+#define field_prep(mask, val) \
+ (__builtin_constant_p(mask) ? __FIELD_PREP(mask, val, "field_prep: ") \
+ : __field_prep(mask, val))
+
+/**
+ * field_get() - extract a bitfield element
+ * @mask: shifted mask defining the field's length and position, must be
+ * non-zero
+ * @reg: value of entire bitfield
+ *
+ * Return: extracted field value
+ *
+ * field_get() extracts the field specified by @mask from the
+ * bitfield passed in as @reg by masking and shifting it down.
+ * Unlike FIELD_GET(), @mask is not limited to a compile-time constant.
+ * Typical usage patterns are a value stored in a table, or calculated by
+ * shifting a constant by a variable number of bits.
+ * If you want to ensure that @mask is a compile-time constant, please use
+ * FIELD_GET() directly instead.
+ */
+#define field_get(mask, reg) \
+ (__builtin_constant_p(mask) ? __FIELD_GET(mask, reg, "field_get: ") \
+ : __field_get(mask, reg))
+
#endif
--
2.43.0
Powered by blists - more mailing lists