* [PATCH v4 0/4] Non-const bitfield helpers
@ 2025-10-17 10:54 Geert Uytterhoeven
2025-10-17 10:54 ` [PATCH v4 1/4] bitfield: Drop underscores from macro parameters Geert Uytterhoeven
` (3 more replies)
0 siblings, 4 replies; 16+ messages in thread
From: Geert Uytterhoeven @ 2025-10-17 10:54 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea, Giovanni Cabiddu, Herbert Xu, David Miller,
Linus Walleij, Bartosz Golaszewski, Joel Stanley, Andrew Jeffery,
Crt Mori, Jonathan Cameron, Lars-Peter Clausen, Jacky Huang,
Shan-Chun Hung, Yury Norov, Rasmus Villemoes, Jaroslav Kysela,
Takashi Iwai, Johannes Berg, Jakub Kicinski, Alex Elder,
David Laight, Vincent Mailhol, Jason Baron, Borislav Petkov,
Tony Luck, Michael Hennerich, Kim Seer Paller, David Lechner,
Nuno Sá, Andy Shevchenko, Richard Genoud, Cosmin Tanislav,
Biju Das, Jianping Shen
Cc: linux-clk, linux-arm-kernel, linux-renesas-soc, linux-crypto,
linux-edac, qat-linux, linux-gpio, linux-aspeed, linux-iio,
linux-sound, linux-kernel, Geert Uytterhoeven
Hi all,
<linux/bitfield.h> contains various helpers for accessing bitfields, as
typically used in hardware registers for memory-mapped I/O blocks.
These helpers ensure type safety, and deduce automatically shift values
from mask values, avoiding mistakes due to inconsistent shifts and
masks, and leading to a reduction in source code size.
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 (e.g. it
comes from a table, or is created by shifting a compile-time constant).
To avoid this limitation, the AT91 clock driver introduced its own
field_{prep,get}() macros. During the past four years, these have been
copied to multiple drivers, and more copies are on their way[1], leading
to the obvious review comment "please move this to <linux/bitfield.h>".
Hence this series makes field_{prep,get}() available for general use
(first two patches), and converts a few Renesas drivers to the existing
FIELD_{GET,PREP}() and the new field_{get,prep}() helpers (last two
patches).
Alternatives would be to use the typed {u*,be*,le*,...}_{get,encode}_bits()
macros instead (which currently do not work with non-constant masks
either, and the first attempt to change that generates much worse code),
or to store the low bit and width of the mask instead (which would
require changing all code that passes masks directly, and also generates
worse code).
Changes compared to v3[2]:
- Update recently introduced FIELD_MODIFY() macro,
- 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
Changes compared to v2[3]:
- New patch "[PATCH v3 1/4] bitfield: Drop underscores from macro
parameters",
- 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}(),
Changes compared to v1[4]:
- 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
- Drop the last 14 RFC patches.
They can be updated/resubmitted/applied later.
I plan to take all four patches through the Renesas tree, and provide an
immutable branch + tag with the first two patches, so subsystem
maintainers that want to queue patches that depend on this can easily do
so. Once that tag has been merged in subsystem trees or upstream, I
plan to update and resend actual conversions (see patches 4-17 in
v1[4]).
Thanks for your comments!
[1] Work-in-progress new copies posted during the last few months (there
may be more):
- "[PATCH 10/24] mtd: rawnand: sunxi: cosmetic: move ECC_PAT_FOUND register in SoC caps"
https://lore.kernel.org/20251016142752.2627710-11-richard.genoud@bootlin.com
- "[PATCH 12/24] mtd: rawnand: sunxi: cosmetic: move NFC_ECC_MODE offset in SoC caps"
https://lore.kernel.org/20251016142752.2627710-13-richard.genoud@bootlin.com
- "[PATCH v2 05/15] mtd: rawnand: sunxi: rework pattern found registers"
https://lore.kernel.org/20251013152645.1119308-6-richard.genoud@bootlin.com
- "[PATCH v2 07/15] mtd: rawnand: sunxi: introduce ecc_mode_mask in sunxi_nfc_caps"
https://lore.kernel.org/20251013152645.1119308-8-richard.genoud@bootlin.com
- "[PATCH v5 2/2] iio: imu: smi330: Add driver"
https://lore.kernel.org/20251009153149.5162-3-Jianping.Shen@de.bosch.com
- "[PATCH v3 2/8] pwm: rzg2l-gpt: Add info variable to struct rzg2l_gpt_chip"
https://lore.kernel.org/20250923144524.191892-3-biju.das.jz@bp.renesas.com
- "[PATCH v2 3/3] gpio: gpio-ltc4283: Add support for the LTC4283 Swap Controller"
https://lore.kernel.org/20250903-ltc4283-support-v2-3-6bce091510bf@analog.com
- "[PATCH v7 15/24] media: i2c: add Maxim GMSL2/3 serializer and deserializer framework"
https://lore.kernel.org/20250718152500.2656391-16-demonsingur@gmail.com
[2] "[PATCH v3 0/4] Non-const bitfield helpers"
https://lore.kernel.org/all/cover.1739540679.git.geert+renesas@glider.be/
[3] "[PATCH v2 0/3] Non-const bitfield helpers"
https://lore.kernel.org/all/cover.1738329458.git.geert+renesas@glider.be
[4] "[PATCH 00/17] Non-const bitfield helper conversions"
https://lore.kernel.org/all/cover.1637592133.git.geert+renesas@glider.be
Geert Uytterhoeven (4):
bitfield: Drop underscores from macro parameters
bitfield: Add non-constant field_{prep,get}() helpers
clk: renesas: Use bitfield helpers
soc: renesas: Use bitfield helpers
drivers/clk/at91/clk-peripheral.c | 1 +
drivers/clk/at91/pmc.h | 3 -
drivers/clk/renesas/clk-div6.c | 6 +-
drivers/clk/renesas/rcar-gen3-cpg.c | 15 +-
drivers/clk/renesas/rcar-gen4-cpg.c | 9 +-
.../intel/qat/qat_common/adf_pm_dbgfs_utils.c | 8 +-
drivers/edac/ie31200_edac.c | 4 +-
drivers/gpio/gpio-aspeed.c | 5 +-
drivers/iio/dac/ad3530r.c | 3 -
drivers/iio/temperature/mlx90614.c | 5 +-
drivers/pinctrl/nuvoton/pinctrl-ma35.c | 4 -
drivers/soc/renesas/renesas-soc.c | 4 +-
drivers/soc/renesas/rz-sysc.c | 3 +-
include/linux/bitfield.h | 142 +++++++++++-------
sound/usb/mixer_quirks.c | 4 -
15 files changed, 108 insertions(+), 108 deletions(-)
--
2.43.0
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v4 1/4] bitfield: Drop underscores from macro parameters
2025-10-17 10:54 [PATCH v4 0/4] Non-const bitfield helpers Geert Uytterhoeven
@ 2025-10-17 10:54 ` Geert Uytterhoeven
2025-10-17 16:37 ` Yury Norov
2025-10-17 10:54 ` [PATCH v4 2/4] bitfield: Add non-constant field_{prep,get}() helpers Geert Uytterhoeven
` (2 subsequent siblings)
3 siblings, 1 reply; 16+ messages in thread
From: Geert Uytterhoeven @ 2025-10-17 10:54 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea, Giovanni Cabiddu, Herbert Xu, David Miller,
Linus Walleij, Bartosz Golaszewski, Joel Stanley, Andrew Jeffery,
Crt Mori, Jonathan Cameron, Lars-Peter Clausen, Jacky Huang,
Shan-Chun Hung, Yury Norov, Rasmus Villemoes, Jaroslav Kysela,
Takashi Iwai, Johannes Berg, Jakub Kicinski, Alex Elder,
David Laight, Vincent Mailhol, Jason Baron, Borislav Petkov,
Tony Luck, Michael Hennerich, Kim Seer Paller, David Lechner,
Nuno Sá, Andy Shevchenko, Richard Genoud, Cosmin Tanislav,
Biju Das, Jianping Shen
Cc: linux-clk, linux-arm-kernel, linux-renesas-soc, linux-crypto,
linux-edac, qat-linux, linux-gpio, linux-aspeed, linux-iio,
linux-sound, linux-kernel, Geert Uytterhoeven
There is no need to prefix macro parameters with underscores.
Remove the underscores.
Suggested-by: David Laight <david.laight.linux@gmail.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
v4:
- Update recently introduced FIELD_MODIFY() macro,
v3:
- New.
---
include/linux/bitfield.h | 106 +++++++++++++++++++--------------------
1 file changed, 53 insertions(+), 53 deletions(-)
diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h
index 5355f8f806a97974..7ff817bdae19b468 100644
--- a/include/linux/bitfield.h
+++ b/include/linux/bitfield.h
@@ -60,68 +60,68 @@
#define __bf_cast_unsigned(type, x) ((__unsigned_scalar_typeof(type))(x))
-#define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx) \
+#define __BF_FIELD_CHECK(mask, reg, val, pfx) \
({ \
- BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask), \
- _pfx "mask is not constant"); \
- BUILD_BUG_ON_MSG((_mask) == 0, _pfx "mask is zero"); \
- BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \
- ~((_mask) >> __bf_shf(_mask)) & \
- (0 + (_val)) : 0, \
- _pfx "value too large for the field"); \
- BUILD_BUG_ON_MSG(__bf_cast_unsigned(_mask, _mask) > \
- __bf_cast_unsigned(_reg, ~0ull), \
- _pfx "type of reg too small for mask"); \
- __BUILD_BUG_ON_NOT_POWER_OF_2((_mask) + \
- (1ULL << __bf_shf(_mask))); \
+ BUILD_BUG_ON_MSG(!__builtin_constant_p(mask), \
+ pfx "mask is not constant"); \
+ BUILD_BUG_ON_MSG((mask) == 0, pfx "mask is zero"); \
+ BUILD_BUG_ON_MSG(__builtin_constant_p(val) ? \
+ ~((mask) >> __bf_shf(mask)) & \
+ (0 + (val)) : 0, \
+ pfx "value too large for the field"); \
+ BUILD_BUG_ON_MSG(__bf_cast_unsigned(mask, mask) > \
+ __bf_cast_unsigned(reg, ~0ull), \
+ pfx "type of reg too small for mask"); \
+ __BUILD_BUG_ON_NOT_POWER_OF_2((mask) + \
+ (1ULL << __bf_shf(mask))); \
})
/**
* FIELD_MAX() - produce the maximum value representable by a field
- * @_mask: shifted mask defining the field's length and position
+ * @mask: shifted mask defining the field's length and position
*
* FIELD_MAX() returns the maximum value that can be held in the field
- * specified by @_mask.
+ * specified by @mask.
*/
-#define FIELD_MAX(_mask) \
+#define FIELD_MAX(mask) \
({ \
- __BF_FIELD_CHECK(_mask, 0ULL, 0ULL, "FIELD_MAX: "); \
- (typeof(_mask))((_mask) >> __bf_shf(_mask)); \
+ __BF_FIELD_CHECK(mask, 0ULL, 0ULL, "FIELD_MAX: "); \
+ (typeof(mask))((mask) >> __bf_shf(mask)); \
})
/**
* FIELD_FIT() - check if value fits in the field
- * @_mask: shifted mask defining the field's length and position
- * @_val: value to test against the field
+ * @mask: shifted mask defining the field's length and position
+ * @val: value to test against the field
*
- * Return: true if @_val can fit inside @_mask, false if @_val is too big.
+ * Return: true if @val can fit inside @mask, false if @val is too big.
*/
-#define FIELD_FIT(_mask, _val) \
+#define FIELD_FIT(mask, val) \
({ \
- __BF_FIELD_CHECK(_mask, 0ULL, 0ULL, "FIELD_FIT: "); \
- !((((typeof(_mask))_val) << __bf_shf(_mask)) & ~(_mask)); \
+ __BF_FIELD_CHECK(mask, 0ULL, 0ULL, "FIELD_FIT: "); \
+ !((((typeof(mask))val) << __bf_shf(mask)) & ~(mask)); \
})
/**
* FIELD_PREP() - prepare a bitfield element
- * @_mask: shifted mask defining the field's length and position
- * @_val: value to put in the field
+ * @mask: shifted mask defining the field's length and position
+ * @val: value to put in the field
*
* FIELD_PREP() masks and shifts up the value. The result should
* be combined with other fields of the bitfield using logical OR.
*/
-#define FIELD_PREP(_mask, _val) \
+#define FIELD_PREP(mask, val) \
({ \
- __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: "); \
- ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \
+ __BF_FIELD_CHECK(mask, 0ULL, val, "FIELD_PREP: "); \
+ ((typeof(mask))(val) << __bf_shf(mask)) & (mask); \
})
#define __BF_CHECK_POW2(n) BUILD_BUG_ON_ZERO(((n) & ((n) - 1)) != 0)
/**
* FIELD_PREP_CONST() - prepare a constant bitfield element
- * @_mask: shifted mask defining the field's length and position
- * @_val: value to put in the field
+ * @mask: shifted mask defining the field's length and position
+ * @val: value to put in the field
*
* FIELD_PREP_CONST() masks and shifts up the value. The result should
* be combined with other fields of the bitfield using logical OR.
@@ -130,47 +130,47 @@
* be used in initializers. Error checking is less comfortable for this
* version, and non-constant masks cannot be used.
*/
-#define FIELD_PREP_CONST(_mask, _val) \
+#define FIELD_PREP_CONST(mask, val) \
( \
/* mask must be non-zero */ \
- BUILD_BUG_ON_ZERO((_mask) == 0) + \
+ BUILD_BUG_ON_ZERO((mask) == 0) + \
/* check if value fits */ \
- BUILD_BUG_ON_ZERO(~((_mask) >> __bf_shf(_mask)) & (_val)) + \
+ BUILD_BUG_ON_ZERO(~((mask) >> __bf_shf(mask)) & (val)) + \
/* check if mask is contiguous */ \
- __BF_CHECK_POW2((_mask) + (1ULL << __bf_shf(_mask))) + \
+ __BF_CHECK_POW2((mask) + (1ULL << __bf_shf(mask))) + \
/* and create the value */ \
- (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)) \
+ (((typeof(mask))(val) << __bf_shf(mask)) & (mask)) \
)
/**
* FIELD_GET() - extract a bitfield element
- * @_mask: shifted mask defining the field's length and position
- * @_reg: value of entire bitfield
+ * @mask: shifted mask defining the field's length and position
+ * @reg: value of entire bitfield
*
- * FIELD_GET() extracts the field specified by @_mask from the
- * bitfield passed in as @_reg by masking and shifting it down.
+ * FIELD_GET() extracts the field specified by @mask from the
+ * bitfield passed in as @reg by masking and shifting it down.
*/
-#define FIELD_GET(_mask, _reg) \
+#define FIELD_GET(mask, reg) \
({ \
- __BF_FIELD_CHECK(_mask, _reg, 0U, "FIELD_GET: "); \
- (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
+ __BF_FIELD_CHECK(mask, reg, 0U, "FIELD_GET: "); \
+ (typeof(mask))(((reg) & (mask)) >> __bf_shf(mask)); \
})
/**
* FIELD_MODIFY() - modify a bitfield element
- * @_mask: shifted mask defining the field's length and position
- * @_reg_p: pointer to the memory that should be updated
- * @_val: value to store in the bitfield
+ * @mask: shifted mask defining the field's length and position
+ * @reg_p: pointer to the memory that should be updated
+ * @val: value to store in the bitfield
*
- * FIELD_MODIFY() modifies the set of bits in @_reg_p specified by @_mask,
- * by replacing them with the bitfield value passed in as @_val.
+ * FIELD_MODIFY() modifies the set of bits in @reg_p specified by @mask,
+ * by replacing them with the bitfield value passed in as @val.
*/
-#define FIELD_MODIFY(_mask, _reg_p, _val) \
+#define FIELD_MODIFY(mask, reg_p, val) \
({ \
- typecheck_pointer(_reg_p); \
- __BF_FIELD_CHECK(_mask, *(_reg_p), _val, "FIELD_MODIFY: "); \
- *(_reg_p) &= ~(_mask); \
- *(_reg_p) |= (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)); \
+ typecheck_pointer(reg_p); \
+ __BF_FIELD_CHECK(mask, *(reg_p), val, "FIELD_MODIFY: "); \
+ *(reg_p) &= ~(mask); \
+ *(reg_p) |= (((typeof(mask))(val) << __bf_shf(mask)) & (mask)); \
})
extern void __compiletime_error("value doesn't fit into mask")
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 2/4] bitfield: Add non-constant field_{prep,get}() helpers
2025-10-17 10:54 [PATCH v4 0/4] Non-const bitfield helpers Geert Uytterhoeven
2025-10-17 10:54 ` [PATCH v4 1/4] bitfield: Drop underscores from macro parameters Geert Uytterhoeven
@ 2025-10-17 10:54 ` Geert Uytterhoeven
2025-10-17 12:33 ` Nuno Sá
2025-10-17 18:51 ` Yury Norov
2025-10-17 10:54 ` [PATCH v4 3/4] clk: renesas: Use bitfield helpers Geert Uytterhoeven
2025-10-17 10:54 ` [PATCH v4 4/4] soc: " Geert Uytterhoeven
3 siblings, 2 replies; 16+ messages in thread
From: Geert Uytterhoeven @ 2025-10-17 10:54 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea, Giovanni Cabiddu, Herbert Xu, David Miller,
Linus Walleij, Bartosz Golaszewski, Joel Stanley, Andrew Jeffery,
Crt Mori, Jonathan Cameron, Lars-Peter Clausen, Jacky Huang,
Shan-Chun Hung, Yury Norov, Rasmus Villemoes, Jaroslav Kysela,
Takashi Iwai, Johannes Berg, Jakub Kicinski, Alex Elder,
David Laight, Vincent Mailhol, Jason Baron, Borislav Petkov,
Tony Luck, Michael Hennerich, Kim Seer Paller, David Lechner,
Nuno Sá, Andy Shevchenko, Richard Genoud, Cosmin Tanislav,
Biju Das, Jianping Shen
Cc: linux-clk, linux-arm-kernel, linux-renesas-soc, linux-crypto,
linux-edac, qat-linux, linux-gpio, linux-aspeed, linux-iio,
linux-sound, linux-kernel, Geert Uytterhoeven, Jonathan Cameron
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 consolidating them in
<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.
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@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>
---
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
---
drivers/clk/at91/clk-peripheral.c | 1 +
drivers/clk/at91/pmc.h | 3 --
.../intel/qat/qat_common/adf_pm_dbgfs_utils.c | 8 +----
drivers/edac/ie31200_edac.c | 4 +--
drivers/gpio/gpio-aspeed.c | 5 +--
drivers/iio/dac/ad3530r.c | 3 --
drivers/iio/temperature/mlx90614.c | 5 +--
drivers/pinctrl/nuvoton/pinctrl-ma35.c | 4 ---
drivers/soc/renesas/rz-sysc.c | 3 +-
include/linux/bitfield.h | 36 +++++++++++++++++++
sound/usb/mixer_quirks.c | 4 ---
11 files changed, 42 insertions(+), 34 deletions(-)
diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c
index e700f40fd87f9327..e7208c47268b6397 100644
--- a/drivers/clk/at91/clk-peripheral.c
+++ b/drivers/clk/at91/clk-peripheral.c
@@ -3,6 +3,7 @@
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
*/
+#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
index 5daa32c4cf2540d7..543d7aee8d248cdb 100644
--- a/drivers/clk/at91/pmc.h
+++ b/drivers/clk/at91/pmc.h
@@ -117,9 +117,6 @@ struct at91_clk_pms {
unsigned int parent;
};
-#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
-#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
-
#define ndck(a, s) (a[s - 1].id + 1)
#define nck(a) (a[ARRAY_SIZE(a) - 1].id + 1)
diff --git a/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs_utils.c b/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs_utils.c
index 69295a9ddf0ac92f..4ccc94ed9493a64c 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs_utils.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs_utils.c
@@ -1,18 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2025 Intel Corporation */
+#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/sprintf.h>
#include <linux/string_helpers.h>
#include "adf_pm_dbgfs_utils.h"
-/*
- * This is needed because a variable is used to index the mask at
- * pm_scnprint_table(), making it not compile time constant, so the compile
- * asserts from FIELD_GET() or u32_get_bits() won't be fulfilled.
- */
-#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
-
#define PM_INFO_MAX_KEY_LEN 21
static int pm_scnprint_table(char *buff, const struct pm_status_row *table,
diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c
index 5a080ab65476dacf..dfc9a9cecd74207d 100644
--- a/drivers/edac/ie31200_edac.c
+++ b/drivers/edac/ie31200_edac.c
@@ -44,6 +44,7 @@
* but lo_hi_readq() ensures that we are safe across all e3-1200 processors.
*/
+#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
@@ -139,9 +140,6 @@
#define IE31200_CAPID0_DDPCD BIT(6)
#define IE31200_CAPID0_ECC BIT(1)
-/* Non-constant mask variant of FIELD_GET() */
-#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
-
static int nr_channels;
static struct pci_dev *mci_pdev;
static int ie31200_registered = 1;
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index 7953a9c4e36d7550..3da999334971d501 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -5,6 +5,7 @@
* Joel Stanley <joel@jms.id.au>
*/
+#include <linux/bitfield.h>
#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/gpio/aspeed.h>
@@ -31,10 +32,6 @@
#include <linux/gpio/consumer.h>
#include "gpiolib.h"
-/* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */
-#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
-#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
-
#define GPIO_G7_IRQ_STS_BASE 0x100
#define GPIO_G7_IRQ_STS_OFFSET(x) (GPIO_G7_IRQ_STS_BASE + (x) * 0x4)
#define GPIO_G7_CTRL_REG_BASE 0x180
diff --git a/drivers/iio/dac/ad3530r.c b/drivers/iio/dac/ad3530r.c
index 6134613777b8e1d4..b97b46090d808ee7 100644
--- a/drivers/iio/dac/ad3530r.c
+++ b/drivers/iio/dac/ad3530r.c
@@ -53,9 +53,6 @@
#define AD3530R_MAX_CHANNELS 8
#define AD3531R_MAX_CHANNELS 4
-/* Non-constant mask variant of FIELD_PREP() */
-#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
-
enum ad3530r_mode {
AD3530R_NORMAL_OP,
AD3530R_POWERDOWN_1K,
diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c
index 8a44a00bfd5ece38..1ad21b73e1b44cb0 100644
--- a/drivers/iio/temperature/mlx90614.c
+++ b/drivers/iio/temperature/mlx90614.c
@@ -22,6 +22,7 @@
* the "wakeup" GPIO is not given, power management will be disabled.
*/
+#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
@@ -68,10 +69,6 @@
#define MLX90614_CONST_SCALE 20 /* Scale in milliKelvin (0.02 * 1000) */
#define MLX90614_CONST_FIR 0x7 /* Fixed value for FIR part of low pass filter */
-/* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */
-#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
-#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
-
struct mlx_chip_info {
/* EEPROM offsets with 16-bit data, MSB first */
/* emissivity correction coefficient */
diff --git a/drivers/pinctrl/nuvoton/pinctrl-ma35.c b/drivers/pinctrl/nuvoton/pinctrl-ma35.c
index cdad01d68a37e365..8d71dc53cc1de1f8 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-ma35.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-ma35.c
@@ -81,10 +81,6 @@
#define MVOLT_1800 0
#define MVOLT_3300 1
-/* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */
-#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
-#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
-
static const char * const gpio_group_name[] = {
"gpioa", "gpiob", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog",
"gpioh", "gpioi", "gpioj", "gpiok", "gpiol", "gpiom", "gpion",
diff --git a/drivers/soc/renesas/rz-sysc.c b/drivers/soc/renesas/rz-sysc.c
index 9f79e299e6f41641..73eaf8b9d69f7208 100644
--- a/drivers/soc/renesas/rz-sysc.c
+++ b/drivers/soc/renesas/rz-sysc.c
@@ -5,6 +5,7 @@
* Copyright (C) 2024 Renesas Electronics Corp.
*/
+#include <linux/bitfield.h>
#include <linux/cleanup.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
@@ -16,8 +17,6 @@
#include "rz-sysc.h"
-#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
-
/**
* struct rz_sysc - RZ SYSC private data structure
* @base: SYSC base address
diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h
index 7ff817bdae19b468..c999fe70076f6684 100644
--- a/include/linux/bitfield.h
+++ b/include/linux/bitfield.h
@@ -220,4 +220,40 @@ __MAKE_OP(64)
#undef __MAKE_OP
#undef ____MAKE_OP
+/**
+ * field_prep() - prepare a bitfield element
+ * @mask: shifted mask defining the field's length and position
+ * @val: value to put in the field
+ *
+ * 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.
+ */
+#define field_prep(mask, val) \
+ ({ \
+ __auto_type __mask = (mask); \
+ typeof(mask) __val = (val); \
+ unsigned int __shift = sizeof(mask) <= 4 ? \
+ __ffs(__mask) : __ffs64(__mask); \
+ (__val << __shift) & __mask; \
+ })
+
+/**
+ * field_get() - extract a bitfield element
+ * @mask: shifted mask defining the field's length and position
+ * @reg: value of entire bitfield
+ *
+ * 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.
+ */
+#define field_get(mask, reg) \
+ ({ \
+ __auto_type __mask = (mask); \
+ typeof(mask) __reg = (reg); \
+ unsigned int __shift = sizeof(mask) <= 4 ? \
+ __ffs(__mask) : __ffs64(__mask); \
+ (__reg & __mask) >> __shift; \
+ })
+
#endif
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 828af3095b86ee0a..6eee89cbc0867f2b 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -3311,10 +3311,6 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer)
#define RME_DIGIFACE_REGISTER(reg, mask) (((reg) << 16) | (mask))
#define RME_DIGIFACE_INVERT BIT(31)
-/* Nonconst helpers */
-#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
-#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
-
static int snd_rme_digiface_write_reg(struct snd_kcontrol *kcontrol, int item, u16 mask, u16 val)
{
struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 3/4] clk: renesas: Use bitfield helpers
2025-10-17 10:54 [PATCH v4 0/4] Non-const bitfield helpers Geert Uytterhoeven
2025-10-17 10:54 ` [PATCH v4 1/4] bitfield: Drop underscores from macro parameters Geert Uytterhoeven
2025-10-17 10:54 ` [PATCH v4 2/4] bitfield: Add non-constant field_{prep,get}() helpers Geert Uytterhoeven
@ 2025-10-17 10:54 ` Geert Uytterhoeven
2025-10-17 10:54 ` [PATCH v4 4/4] soc: " Geert Uytterhoeven
3 siblings, 0 replies; 16+ messages in thread
From: Geert Uytterhoeven @ 2025-10-17 10:54 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea, Giovanni Cabiddu, Herbert Xu, David Miller,
Linus Walleij, Bartosz Golaszewski, Joel Stanley, Andrew Jeffery,
Crt Mori, Jonathan Cameron, Lars-Peter Clausen, Jacky Huang,
Shan-Chun Hung, Yury Norov, Rasmus Villemoes, Jaroslav Kysela,
Takashi Iwai, Johannes Berg, Jakub Kicinski, Alex Elder,
David Laight, Vincent Mailhol, Jason Baron, Borislav Petkov,
Tony Luck, Michael Hennerich, Kim Seer Paller, David Lechner,
Nuno Sá, Andy Shevchenko, Richard Genoud, Cosmin Tanislav,
Biju Das, Jianping Shen
Cc: linux-clk, linux-arm-kernel, linux-renesas-soc, linux-crypto,
linux-edac, qat-linux, linux-gpio, linux-aspeed, linux-iio,
linux-sound, linux-kernel, Geert Uytterhoeven
Use the FIELD_{GET,PREP}() and field_{get,prep}() helpers for const
respective non-const bitfields, instead of open-coding the same
operations.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
v4:
- No changes,
v3:
- No changes,
v2:
- Rebase on top of commit 470e3f0d0b1529ab ("clk: renesas: rcar-gen4:
Introduce R-Car Gen4 CPG driver").
---
drivers/clk/renesas/clk-div6.c | 6 +++---
drivers/clk/renesas/rcar-gen3-cpg.c | 15 +++++----------
drivers/clk/renesas/rcar-gen4-cpg.c | 9 +++------
3 files changed, 11 insertions(+), 19 deletions(-)
diff --git a/drivers/clk/renesas/clk-div6.c b/drivers/clk/renesas/clk-div6.c
index 3abd6e5400aded6a..f7b827b5e9b2dd32 100644
--- a/drivers/clk/renesas/clk-div6.c
+++ b/drivers/clk/renesas/clk-div6.c
@@ -7,6 +7,7 @@
* Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
*/
+#include <linux/bitfield.h>
#include <linux/clk-provider.h>
#include <linux/init.h>
#include <linux/io.h>
@@ -171,8 +172,7 @@ static u8 cpg_div6_clock_get_parent(struct clk_hw *hw)
if (clock->src_mask == 0)
return 0;
- hw_index = (readl(clock->reg) & clock->src_mask) >>
- __ffs(clock->src_mask);
+ hw_index = field_get(clock->src_mask, readl(clock->reg));
for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
if (clock->parents[i] == hw_index)
return i;
@@ -191,7 +191,7 @@ static int cpg_div6_clock_set_parent(struct clk_hw *hw, u8 index)
if (index >= clk_hw_get_num_parents(hw))
return -EINVAL;
- src = clock->parents[index] << __ffs(clock->src_mask);
+ src = field_prep(clock->src_mask, clock->parents[index]);
writel((readl(clock->reg) & ~clock->src_mask) | src, clock->reg);
return 0;
}
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c
index 10ae20489df9abd8..b954278ddd9d8aa8 100644
--- a/drivers/clk/renesas/rcar-gen3-cpg.c
+++ b/drivers/clk/renesas/rcar-gen3-cpg.c
@@ -54,10 +54,8 @@ static unsigned long cpg_pll_clk_recalc_rate(struct clk_hw *hw,
{
struct cpg_pll_clk *pll_clk = to_pll_clk(hw);
unsigned int mult;
- u32 val;
- val = readl(pll_clk->pllcr_reg) & CPG_PLLnCR_STC_MASK;
- mult = (val >> __ffs(CPG_PLLnCR_STC_MASK)) + 1;
+ mult = FIELD_GET(CPG_PLLnCR_STC_MASK, readl(pll_clk->pllcr_reg)) + 1;
return parent_rate * mult * pll_clk->fixed_mult;
}
@@ -94,7 +92,7 @@ static int cpg_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
val = readl(pll_clk->pllcr_reg);
val &= ~CPG_PLLnCR_STC_MASK;
- val |= (mult - 1) << __ffs(CPG_PLLnCR_STC_MASK);
+ val |= FIELD_PREP(CPG_PLLnCR_STC_MASK, mult - 1);
writel(val, pll_clk->pllcr_reg);
for (i = 1000; i; i--) {
@@ -176,11 +174,7 @@ static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct cpg_z_clk *zclk = to_z_clk(hw);
- unsigned int mult;
- u32 val;
-
- val = readl(zclk->reg) & zclk->mask;
- mult = 32 - (val >> __ffs(zclk->mask));
+ unsigned int mult = 32 - field_get(zclk->mask, readl(zclk->reg));
return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult,
32 * zclk->fixed_div);
@@ -231,7 +225,8 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
return -EBUSY;
- cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask));
+ cpg_reg_modify(zclk->reg, zclk->mask,
+ field_prep(zclk->mask, 32 - mult));
/*
* Set KICK bit in FRQCRB to update hardware setting and wait for
diff --git a/drivers/clk/renesas/rcar-gen4-cpg.c b/drivers/clk/renesas/rcar-gen4-cpg.c
index fb9a876aaba5cbcd..db3a0b8ef2b936bb 100644
--- a/drivers/clk/renesas/rcar-gen4-cpg.c
+++ b/drivers/clk/renesas/rcar-gen4-cpg.c
@@ -279,11 +279,7 @@ static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct cpg_z_clk *zclk = to_z_clk(hw);
- unsigned int mult;
- u32 val;
-
- val = readl(zclk->reg) & zclk->mask;
- mult = 32 - (val >> __ffs(zclk->mask));
+ unsigned int mult = 32 - field_get(zclk->mask, readl(zclk->reg));
return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult,
32 * zclk->fixed_div);
@@ -334,7 +330,8 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
return -EBUSY;
- cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask));
+ cpg_reg_modify(zclk->reg, zclk->mask,
+ field_prep(zclk->mask, 32 - mult));
/*
* Set KICK bit in FRQCRB to update hardware setting and wait for
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 4/4] soc: renesas: Use bitfield helpers
2025-10-17 10:54 [PATCH v4 0/4] Non-const bitfield helpers Geert Uytterhoeven
` (2 preceding siblings ...)
2025-10-17 10:54 ` [PATCH v4 3/4] clk: renesas: Use bitfield helpers Geert Uytterhoeven
@ 2025-10-17 10:54 ` Geert Uytterhoeven
3 siblings, 0 replies; 16+ messages in thread
From: Geert Uytterhoeven @ 2025-10-17 10:54 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea, Giovanni Cabiddu, Herbert Xu, David Miller,
Linus Walleij, Bartosz Golaszewski, Joel Stanley, Andrew Jeffery,
Crt Mori, Jonathan Cameron, Lars-Peter Clausen, Jacky Huang,
Shan-Chun Hung, Yury Norov, Rasmus Villemoes, Jaroslav Kysela,
Takashi Iwai, Johannes Berg, Jakub Kicinski, Alex Elder,
David Laight, Vincent Mailhol, Jason Baron, Borislav Petkov,
Tony Luck, Michael Hennerich, Kim Seer Paller, David Lechner,
Nuno Sá, Andy Shevchenko, Richard Genoud, Cosmin Tanislav,
Biju Das, Jianping Shen
Cc: linux-clk, linux-arm-kernel, linux-renesas-soc, linux-crypto,
linux-edac, qat-linux, linux-gpio, linux-aspeed, linux-iio,
linux-sound, linux-kernel, Geert Uytterhoeven
Use the field_get() helper, instead of open-coding the same operation.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
v4:
- No changes,
v3:
- No changes,
v2:
- Drop RFC, as a dependency was applied.
---
drivers/soc/renesas/renesas-soc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c
index 1eb52356b996bdd7..ee4f17bb4db45db7 100644
--- a/drivers/soc/renesas/renesas-soc.c
+++ b/drivers/soc/renesas/renesas-soc.c
@@ -5,6 +5,7 @@
* Copyright (C) 2014-2016 Glider bvba
*/
+#include <linux/bitfield.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -524,8 +525,7 @@ static int __init renesas_soc_init(void)
eshi, eslo);
}
- if (soc->id &&
- ((product & id->mask) >> __ffs(id->mask)) != soc->id) {
+ if (soc->id && field_get(id->mask, product) != soc->id) {
pr_warn("SoC mismatch (product = 0x%x)\n", product);
ret = -ENODEV;
goto free_soc_dev_attr;
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v4 2/4] bitfield: Add non-constant field_{prep,get}() helpers
2025-10-17 10:54 ` [PATCH v4 2/4] bitfield: Add non-constant field_{prep,get}() helpers Geert Uytterhoeven
@ 2025-10-17 12:33 ` Nuno Sá
2025-10-17 12:43 ` Richard GENOUD
2025-10-17 18:51 ` Yury Norov
1 sibling, 1 reply; 16+ messages in thread
From: Nuno Sá @ 2025-10-17 12:33 UTC (permalink / raw)
To: Geert Uytterhoeven, Michael Turquette, Stephen Boyd,
Nicolas Ferre, Alexandre Belloni, Claudiu Beznea,
Giovanni Cabiddu, Herbert Xu, David Miller, Linus Walleij,
Bartosz Golaszewski, Joel Stanley, Andrew Jeffery, Crt Mori,
Jonathan Cameron, Lars-Peter Clausen, Jacky Huang, Shan-Chun Hung,
Yury Norov, Rasmus Villemoes, Jaroslav Kysela, Takashi Iwai,
Johannes Berg, Jakub Kicinski, Alex Elder, David Laight,
Vincent Mailhol, Jason Baron, Borislav Petkov, Tony Luck,
Michael Hennerich, Kim Seer Paller, David Lechner, Nuno Sá,
Andy Shevchenko, Richard Genoud, Cosmin Tanislav, Biju Das,
Jianping Shen
Cc: linux-clk, linux-arm-kernel, linux-renesas-soc, linux-crypto,
linux-edac, qat-linux, linux-gpio, linux-aspeed, linux-iio,
linux-sound, linux-kernel, Jonathan Cameron
On Fri, 2025-10-17 at 12:54 +0200, Geert Uytterhoeven wrote:
> 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 consolidating them in
> <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.
>
> 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@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>
> ---
Hopefully this gets merged soon. About time to have these variants (I do have a
driver submitted - in review - which is adding yet another variant of this)
Acked-by: Nuno Sá <nuno.sa@analog.com>
> 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
> ---
> drivers/clk/at91/clk-peripheral.c | 1 +
> drivers/clk/at91/pmc.h | 3 --
> .../intel/qat/qat_common/adf_pm_dbgfs_utils.c | 8 +----
> drivers/edac/ie31200_edac.c | 4 +--
> drivers/gpio/gpio-aspeed.c | 5 +--
> drivers/iio/dac/ad3530r.c | 3 --
> drivers/iio/temperature/mlx90614.c | 5 +--
> drivers/pinctrl/nuvoton/pinctrl-ma35.c | 4 ---
> drivers/soc/renesas/rz-sysc.c | 3 +-
> include/linux/bitfield.h | 36 +++++++++++++++++++
> sound/usb/mixer_quirks.c | 4 ---
> 11 files changed, 42 insertions(+), 34 deletions(-)
>
> diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-
> peripheral.c
> index e700f40fd87f9327..e7208c47268b6397 100644
> --- a/drivers/clk/at91/clk-peripheral.c
> +++ b/drivers/clk/at91/clk-peripheral.c
> @@ -3,6 +3,7 @@
> * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
> */
>
> +#include <linux/bitfield.h>
> #include <linux/bitops.h>
> #include <linux/clk-provider.h>
> #include <linux/clkdev.h>
> diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
> index 5daa32c4cf2540d7..543d7aee8d248cdb 100644
> --- a/drivers/clk/at91/pmc.h
> +++ b/drivers/clk/at91/pmc.h
> @@ -117,9 +117,6 @@ struct at91_clk_pms {
> unsigned int parent;
> };
>
> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
> -#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
> -
> #define ndck(a, s) (a[s - 1].id + 1)
> #define nck(a) (a[ARRAY_SIZE(a) - 1].id + 1)
>
> diff --git a/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs_utils.c
> b/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs_utils.c
> index 69295a9ddf0ac92f..4ccc94ed9493a64c 100644
> --- a/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs_utils.c
> +++ b/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs_utils.c
> @@ -1,18 +1,12 @@
> // SPDX-License-Identifier: GPL-2.0-only
> /* Copyright(c) 2025 Intel Corporation */
> +#include <linux/bitfield.h>
> #include <linux/bitops.h>
> #include <linux/sprintf.h>
> #include <linux/string_helpers.h>
>
> #include "adf_pm_dbgfs_utils.h"
>
> -/*
> - * This is needed because a variable is used to index the mask at
> - * pm_scnprint_table(), making it not compile time constant, so the compile
> - * asserts from FIELD_GET() or u32_get_bits() won't be fulfilled.
> - */
> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
> -
> #define PM_INFO_MAX_KEY_LEN 21
>
> static int pm_scnprint_table(char *buff, const struct pm_status_row *table,
> diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c
> index 5a080ab65476dacf..dfc9a9cecd74207d 100644
> --- a/drivers/edac/ie31200_edac.c
> +++ b/drivers/edac/ie31200_edac.c
> @@ -44,6 +44,7 @@
> * but lo_hi_readq() ensures that we are safe across all e3-1200 processors.
> */
>
> +#include <linux/bitfield.h>
> #include <linux/module.h>
> #include <linux/init.h>
> #include <linux/pci.h>
> @@ -139,9 +140,6 @@
> #define IE31200_CAPID0_DDPCD BIT(6)
> #define IE31200_CAPID0_ECC BIT(1)
>
> -/* Non-constant mask variant of FIELD_GET() */
> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
> -
> static int nr_channels;
> static struct pci_dev *mci_pdev;
> static int ie31200_registered = 1;
> diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
> index 7953a9c4e36d7550..3da999334971d501 100644
> --- a/drivers/gpio/gpio-aspeed.c
> +++ b/drivers/gpio/gpio-aspeed.c
> @@ -5,6 +5,7 @@
> * Joel Stanley <joel@jms.id.au>
> */
>
> +#include <linux/bitfield.h>
> #include <linux/cleanup.h>
> #include <linux/clk.h>
> #include <linux/gpio/aspeed.h>
> @@ -31,10 +32,6 @@
> #include <linux/gpio/consumer.h>
> #include "gpiolib.h"
>
> -/* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */
> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
> -#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) &
> (_mask))
> -
> #define GPIO_G7_IRQ_STS_BASE 0x100
> #define GPIO_G7_IRQ_STS_OFFSET(x) (GPIO_G7_IRQ_STS_BASE + (x) * 0x4)
> #define GPIO_G7_CTRL_REG_BASE 0x180
> diff --git a/drivers/iio/dac/ad3530r.c b/drivers/iio/dac/ad3530r.c
> index 6134613777b8e1d4..b97b46090d808ee7 100644
> --- a/drivers/iio/dac/ad3530r.c
> +++ b/drivers/iio/dac/ad3530r.c
> @@ -53,9 +53,6 @@
> #define AD3530R_MAX_CHANNELS 8
> #define AD3531R_MAX_CHANNELS 4
>
> -/* Non-constant mask variant of FIELD_PREP() */
> -#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) &
> (_mask))
> -
> enum ad3530r_mode {
> AD3530R_NORMAL_OP,
> AD3530R_POWERDOWN_1K,
> diff --git a/drivers/iio/temperature/mlx90614.c
> b/drivers/iio/temperature/mlx90614.c
> index 8a44a00bfd5ece38..1ad21b73e1b44cb0 100644
> --- a/drivers/iio/temperature/mlx90614.c
> +++ b/drivers/iio/temperature/mlx90614.c
> @@ -22,6 +22,7 @@
> * the "wakeup" GPIO is not given, power management will be disabled.
> */
>
> +#include <linux/bitfield.h>
> #include <linux/delay.h>
> #include <linux/err.h>
> #include <linux/gpio/consumer.h>
> @@ -68,10 +69,6 @@
> #define MLX90614_CONST_SCALE 20 /* Scale in milliKelvin (0.02 * 1000) */
> #define MLX90614_CONST_FIR 0x7 /* Fixed value for FIR part of low pass filter
> */
>
> -/* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */
> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
> -#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) &
> (_mask))
> -
> struct mlx_chip_info {
> /* EEPROM offsets with 16-bit data, MSB first */
> /* emissivity correction coefficient */
> diff --git a/drivers/pinctrl/nuvoton/pinctrl-ma35.c
> b/drivers/pinctrl/nuvoton/pinctrl-ma35.c
> index cdad01d68a37e365..8d71dc53cc1de1f8 100644
> --- a/drivers/pinctrl/nuvoton/pinctrl-ma35.c
> +++ b/drivers/pinctrl/nuvoton/pinctrl-ma35.c
> @@ -81,10 +81,6 @@
> #define MVOLT_1800 0
> #define MVOLT_3300 1
>
> -/* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */
> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
> -#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) &
> (_mask))
> -
> static const char * const gpio_group_name[] = {
> "gpioa", "gpiob", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog",
> "gpioh", "gpioi", "gpioj", "gpiok", "gpiol", "gpiom", "gpion",
> diff --git a/drivers/soc/renesas/rz-sysc.c b/drivers/soc/renesas/rz-sysc.c
> index 9f79e299e6f41641..73eaf8b9d69f7208 100644
> --- a/drivers/soc/renesas/rz-sysc.c
> +++ b/drivers/soc/renesas/rz-sysc.c
> @@ -5,6 +5,7 @@
> * Copyright (C) 2024 Renesas Electronics Corp.
> */
>
> +#include <linux/bitfield.h>
> #include <linux/cleanup.h>
> #include <linux/io.h>
> #include <linux/mfd/syscon.h>
> @@ -16,8 +17,6 @@
>
> #include "rz-sysc.h"
>
> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
> -
> /**
> * struct rz_sysc - RZ SYSC private data structure
> * @base: SYSC base address
> diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h
> index 7ff817bdae19b468..c999fe70076f6684 100644
> --- a/include/linux/bitfield.h
> +++ b/include/linux/bitfield.h
> @@ -220,4 +220,40 @@ __MAKE_OP(64)
> #undef __MAKE_OP
> #undef ____MAKE_OP
>
> +/**
> + * field_prep() - prepare a bitfield element
> + * @mask: shifted mask defining the field's length and position
> + * @val: value to put in the field
> + *
> + * 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.
> + */
> +#define field_prep(mask, val) \
> + ({ \
> + __auto_type __mask = (mask); \
> + typeof(mask) __val = (val); \
> + unsigned int __shift = sizeof(mask) <= 4 ? \
> + __ffs(__mask) :
> __ffs64(__mask); \
> + (__val << __shift) & __mask; \
> + })
> +
> +/**
> + * field_get() - extract a bitfield element
> + * @mask: shifted mask defining the field's length and position
> + * @reg: value of entire bitfield
> + *
> + * 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.
> + */
> +#define field_get(mask, reg) \
> + ({ \
> + __auto_type __mask = (mask); \
> + typeof(mask) __reg = (reg); \
> + unsigned int __shift = sizeof(mask) <= 4 ? \
> + __ffs(__mask) :
> __ffs64(__mask); \
> + (__reg & __mask) >> __shift; \
> + })
> +
> #endif
> diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
> index 828af3095b86ee0a..6eee89cbc0867f2b 100644
> --- a/sound/usb/mixer_quirks.c
> +++ b/sound/usb/mixer_quirks.c
> @@ -3311,10 +3311,6 @@ static int snd_bbfpro_controls_create(struct
> usb_mixer_interface *mixer)
> #define RME_DIGIFACE_REGISTER(reg, mask) (((reg) << 16) | (mask))
> #define RME_DIGIFACE_INVERT BIT(31)
>
> -/* Nonconst helpers */
> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
> -#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
> -
> static int snd_rme_digiface_write_reg(struct snd_kcontrol *kcontrol, int
> item, u16 mask, u16 val)
> {
> struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 2/4] bitfield: Add non-constant field_{prep,get}() helpers
2025-10-17 12:33 ` Nuno Sá
@ 2025-10-17 12:43 ` Richard GENOUD
0 siblings, 0 replies; 16+ messages in thread
From: Richard GENOUD @ 2025-10-17 12:43 UTC (permalink / raw)
To: Nuno Sá, Geert Uytterhoeven, Michael Turquette, Stephen Boyd,
Nicolas Ferre, Alexandre Belloni, Claudiu Beznea,
Giovanni Cabiddu, Herbert Xu, David Miller, Linus Walleij,
Bartosz Golaszewski, Joel Stanley, Andrew Jeffery, Crt Mori,
Jonathan Cameron, Lars-Peter Clausen, Jacky Huang, Shan-Chun Hung,
Yury Norov, Rasmus Villemoes, Jaroslav Kysela, Takashi Iwai,
Johannes Berg, Jakub Kicinski, Alex Elder, David Laight,
Vincent Mailhol, Jason Baron, Borislav Petkov, Tony Luck,
Michael Hennerich, Kim Seer Paller, David Lechner, Nuno Sá,
Andy Shevchenko, Cosmin Tanislav, Biju Das, Jianping Shen
Cc: linux-clk, linux-arm-kernel, linux-renesas-soc, linux-crypto,
linux-edac, qat-linux, linux-gpio, linux-aspeed, linux-iio,
linux-sound, linux-kernel, Jonathan Cameron
Le 17/10/2025 à 14:33, Nuno Sá a écrit :
> On Fri, 2025-10-17 at 12:54 +0200, Geert Uytterhoeven wrote:
>> 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 consolidating them in
>> <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.
>>
>> 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@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>
>> ---
>
> Hopefully this gets merged soon. About time to have these variants (I do have a
> driver submitted - in review - which is adding yet another variant of this)
>
> Acked-by: Nuno Sá <nuno.sa@analog.com>
Same here, I would happily drop field_{get,set} from my series under
review to include bitfield.h
Thanks Geert!
Acked-by: Richard Genoud <richard.genoud@bootlin.com>
>
>> 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
>> ---
>> drivers/clk/at91/clk-peripheral.c | 1 +
>> drivers/clk/at91/pmc.h | 3 --
>> .../intel/qat/qat_common/adf_pm_dbgfs_utils.c | 8 +----
>> drivers/edac/ie31200_edac.c | 4 +--
>> drivers/gpio/gpio-aspeed.c | 5 +--
>> drivers/iio/dac/ad3530r.c | 3 --
>> drivers/iio/temperature/mlx90614.c | 5 +--
>> drivers/pinctrl/nuvoton/pinctrl-ma35.c | 4 ---
>> drivers/soc/renesas/rz-sysc.c | 3 +-
>> include/linux/bitfield.h | 36 +++++++++++++++++++
>> sound/usb/mixer_quirks.c | 4 ---
>> 11 files changed, 42 insertions(+), 34 deletions(-)
>>
>> diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-
>> peripheral.c
>> index e700f40fd87f9327..e7208c47268b6397 100644
>> --- a/drivers/clk/at91/clk-peripheral.c
>> +++ b/drivers/clk/at91/clk-peripheral.c
>> @@ -3,6 +3,7 @@
>> * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
>> */
>>
>> +#include <linux/bitfield.h>
>> #include <linux/bitops.h>
>> #include <linux/clk-provider.h>
>> #include <linux/clkdev.h>
>> diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
>> index 5daa32c4cf2540d7..543d7aee8d248cdb 100644
>> --- a/drivers/clk/at91/pmc.h
>> +++ b/drivers/clk/at91/pmc.h
>> @@ -117,9 +117,6 @@ struct at91_clk_pms {
>> unsigned int parent;
>> };
>>
>> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
>> -#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
>> -
>> #define ndck(a, s) (a[s - 1].id + 1)
>> #define nck(a) (a[ARRAY_SIZE(a) - 1].id + 1)
>>
>> diff --git a/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs_utils.c
>> b/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs_utils.c
>> index 69295a9ddf0ac92f..4ccc94ed9493a64c 100644
>> --- a/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs_utils.c
>> +++ b/drivers/crypto/intel/qat/qat_common/adf_pm_dbgfs_utils.c
>> @@ -1,18 +1,12 @@
>> // SPDX-License-Identifier: GPL-2.0-only
>> /* Copyright(c) 2025 Intel Corporation */
>> +#include <linux/bitfield.h>
>> #include <linux/bitops.h>
>> #include <linux/sprintf.h>
>> #include <linux/string_helpers.h>
>>
>> #include "adf_pm_dbgfs_utils.h"
>>
>> -/*
>> - * This is needed because a variable is used to index the mask at
>> - * pm_scnprint_table(), making it not compile time constant, so the compile
>> - * asserts from FIELD_GET() or u32_get_bits() won't be fulfilled.
>> - */
>> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
>> -
>> #define PM_INFO_MAX_KEY_LEN 21
>>
>> static int pm_scnprint_table(char *buff, const struct pm_status_row *table,
>> diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c
>> index 5a080ab65476dacf..dfc9a9cecd74207d 100644
>> --- a/drivers/edac/ie31200_edac.c
>> +++ b/drivers/edac/ie31200_edac.c
>> @@ -44,6 +44,7 @@
>> * but lo_hi_readq() ensures that we are safe across all e3-1200 processors.
>> */
>>
>> +#include <linux/bitfield.h>
>> #include <linux/module.h>
>> #include <linux/init.h>
>> #include <linux/pci.h>
>> @@ -139,9 +140,6 @@
>> #define IE31200_CAPID0_DDPCD BIT(6)
>> #define IE31200_CAPID0_ECC BIT(1)
>>
>> -/* Non-constant mask variant of FIELD_GET() */
>> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
>> -
>> static int nr_channels;
>> static struct pci_dev *mci_pdev;
>> static int ie31200_registered = 1;
>> diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
>> index 7953a9c4e36d7550..3da999334971d501 100644
>> --- a/drivers/gpio/gpio-aspeed.c
>> +++ b/drivers/gpio/gpio-aspeed.c
>> @@ -5,6 +5,7 @@
>> * Joel Stanley <joel@jms.id.au>
>> */
>>
>> +#include <linux/bitfield.h>
>> #include <linux/cleanup.h>
>> #include <linux/clk.h>
>> #include <linux/gpio/aspeed.h>
>> @@ -31,10 +32,6 @@
>> #include <linux/gpio/consumer.h>
>> #include "gpiolib.h"
>>
>> -/* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */
>> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
>> -#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) &
>> (_mask))
>> -
>> #define GPIO_G7_IRQ_STS_BASE 0x100
>> #define GPIO_G7_IRQ_STS_OFFSET(x) (GPIO_G7_IRQ_STS_BASE + (x) * 0x4)
>> #define GPIO_G7_CTRL_REG_BASE 0x180
>> diff --git a/drivers/iio/dac/ad3530r.c b/drivers/iio/dac/ad3530r.c
>> index 6134613777b8e1d4..b97b46090d808ee7 100644
>> --- a/drivers/iio/dac/ad3530r.c
>> +++ b/drivers/iio/dac/ad3530r.c
>> @@ -53,9 +53,6 @@
>> #define AD3530R_MAX_CHANNELS 8
>> #define AD3531R_MAX_CHANNELS 4
>>
>> -/* Non-constant mask variant of FIELD_PREP() */
>> -#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) &
>> (_mask))
>> -
>> enum ad3530r_mode {
>> AD3530R_NORMAL_OP,
>> AD3530R_POWERDOWN_1K,
>> diff --git a/drivers/iio/temperature/mlx90614.c
>> b/drivers/iio/temperature/mlx90614.c
>> index 8a44a00bfd5ece38..1ad21b73e1b44cb0 100644
>> --- a/drivers/iio/temperature/mlx90614.c
>> +++ b/drivers/iio/temperature/mlx90614.c
>> @@ -22,6 +22,7 @@
>> * the "wakeup" GPIO is not given, power management will be disabled.
>> */
>>
>> +#include <linux/bitfield.h>
>> #include <linux/delay.h>
>> #include <linux/err.h>
>> #include <linux/gpio/consumer.h>
>> @@ -68,10 +69,6 @@
>> #define MLX90614_CONST_SCALE 20 /* Scale in milliKelvin (0.02 * 1000) */
>> #define MLX90614_CONST_FIR 0x7 /* Fixed value for FIR part of low pass filter
>> */
>>
>> -/* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */
>> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
>> -#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) &
>> (_mask))
>> -
>> struct mlx_chip_info {
>> /* EEPROM offsets with 16-bit data, MSB first */
>> /* emissivity correction coefficient */
>> diff --git a/drivers/pinctrl/nuvoton/pinctrl-ma35.c
>> b/drivers/pinctrl/nuvoton/pinctrl-ma35.c
>> index cdad01d68a37e365..8d71dc53cc1de1f8 100644
>> --- a/drivers/pinctrl/nuvoton/pinctrl-ma35.c
>> +++ b/drivers/pinctrl/nuvoton/pinctrl-ma35.c
>> @@ -81,10 +81,6 @@
>> #define MVOLT_1800 0
>> #define MVOLT_3300 1
>>
>> -/* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */
>> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
>> -#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) &
>> (_mask))
>> -
>> static const char * const gpio_group_name[] = {
>> "gpioa", "gpiob", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog",
>> "gpioh", "gpioi", "gpioj", "gpiok", "gpiol", "gpiom", "gpion",
>> diff --git a/drivers/soc/renesas/rz-sysc.c b/drivers/soc/renesas/rz-sysc.c
>> index 9f79e299e6f41641..73eaf8b9d69f7208 100644
>> --- a/drivers/soc/renesas/rz-sysc.c
>> +++ b/drivers/soc/renesas/rz-sysc.c
>> @@ -5,6 +5,7 @@
>> * Copyright (C) 2024 Renesas Electronics Corp.
>> */
>>
>> +#include <linux/bitfield.h>
>> #include <linux/cleanup.h>
>> #include <linux/io.h>
>> #include <linux/mfd/syscon.h>
>> @@ -16,8 +17,6 @@
>>
>> #include "rz-sysc.h"
>>
>> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
>> -
>> /**
>> * struct rz_sysc - RZ SYSC private data structure
>> * @base: SYSC base address
>> diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h
>> index 7ff817bdae19b468..c999fe70076f6684 100644
>> --- a/include/linux/bitfield.h
>> +++ b/include/linux/bitfield.h
>> @@ -220,4 +220,40 @@ __MAKE_OP(64)
>> #undef __MAKE_OP
>> #undef ____MAKE_OP
>>
>> +/**
>> + * field_prep() - prepare a bitfield element
>> + * @mask: shifted mask defining the field's length and position
>> + * @val: value to put in the field
>> + *
>> + * 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.
>> + */
>> +#define field_prep(mask, val) \
>> + ({ \
>> + __auto_type __mask = (mask); \
>> + typeof(mask) __val = (val); \
>> + unsigned int __shift = sizeof(mask) <= 4 ? \
>> + __ffs(__mask) :
>> __ffs64(__mask); \
>> + (__val << __shift) & __mask; \
>> + })
>> +
>> +/**
>> + * field_get() - extract a bitfield element
>> + * @mask: shifted mask defining the field's length and position
>> + * @reg: value of entire bitfield
>> + *
>> + * 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.
>> + */
>> +#define field_get(mask, reg) \
>> + ({ \
>> + __auto_type __mask = (mask); \
>> + typeof(mask) __reg = (reg); \
>> + unsigned int __shift = sizeof(mask) <= 4 ? \
>> + __ffs(__mask) :
>> __ffs64(__mask); \
>> + (__reg & __mask) >> __shift; \
>> + })
>> +
>> #endif
>> diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
>> index 828af3095b86ee0a..6eee89cbc0867f2b 100644
>> --- a/sound/usb/mixer_quirks.c
>> +++ b/sound/usb/mixer_quirks.c
>> @@ -3311,10 +3311,6 @@ static int snd_bbfpro_controls_create(struct
>> usb_mixer_interface *mixer)
>> #define RME_DIGIFACE_REGISTER(reg, mask) (((reg) << 16) | (mask))
>> #define RME_DIGIFACE_INVERT BIT(31)
>>
>> -/* Nonconst helpers */
>> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
>> -#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
>> -
>> static int snd_rme_digiface_write_reg(struct snd_kcontrol *kcontrol, int
>> item, u16 mask, u16 val)
>> {
>> struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
--
Richard Genoud, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 1/4] bitfield: Drop underscores from macro parameters
2025-10-17 10:54 ` [PATCH v4 1/4] bitfield: Drop underscores from macro parameters Geert Uytterhoeven
@ 2025-10-17 16:37 ` Yury Norov
2025-10-20 12:13 ` Geert Uytterhoeven
0 siblings, 1 reply; 16+ messages in thread
From: Yury Norov @ 2025-10-17 16:37 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Michael Turquette, Stephen Boyd, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea, Giovanni Cabiddu, Herbert Xu, David Miller,
Linus Walleij, Bartosz Golaszewski, Joel Stanley, Andrew Jeffery,
Crt Mori, Jonathan Cameron, Lars-Peter Clausen, Jacky Huang,
Shan-Chun Hung, Rasmus Villemoes, Jaroslav Kysela, Takashi Iwai,
Johannes Berg, Jakub Kicinski, Alex Elder, David Laight,
Vincent Mailhol, Jason Baron, Borislav Petkov, Tony Luck,
Michael Hennerich, Kim Seer Paller, David Lechner, Nuno Sá,
Andy Shevchenko, Richard Genoud, Cosmin Tanislav, Biju Das,
Jianping Shen, linux-clk, linux-arm-kernel, linux-renesas-soc,
linux-crypto, linux-edac, qat-linux, linux-gpio, linux-aspeed,
linux-iio, linux-sound, linux-kernel
On Fri, Oct 17, 2025 at 12:54:09PM +0200, Geert Uytterhoeven wrote:
> There is no need to prefix macro parameters with underscores.
> Remove the underscores.
>
> Suggested-by: David Laight <david.laight.linux@gmail.com>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> v4:
> - Update recently introduced FIELD_MODIFY() macro,
>
> v3:
> - New.
> ---
> include/linux/bitfield.h | 106 +++++++++++++++++++--------------------
> 1 file changed, 53 insertions(+), 53 deletions(-)
>
> diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h
> index 5355f8f806a97974..7ff817bdae19b468 100644
> --- a/include/linux/bitfield.h
> +++ b/include/linux/bitfield.h
> @@ -60,68 +60,68 @@
>
> #define __bf_cast_unsigned(type, x) ((__unsigned_scalar_typeof(type))(x))
>
> -#define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx) \
> +#define __BF_FIELD_CHECK(mask, reg, val, pfx) \
> ({ \
> - BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask), \
> - _pfx "mask is not constant"); \
> - BUILD_BUG_ON_MSG((_mask) == 0, _pfx "mask is zero"); \
> - BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \
> - ~((_mask) >> __bf_shf(_mask)) & \
> - (0 + (_val)) : 0, \
> - _pfx "value too large for the field"); \
> - BUILD_BUG_ON_MSG(__bf_cast_unsigned(_mask, _mask) > \
> - __bf_cast_unsigned(_reg, ~0ull), \
> - _pfx "type of reg too small for mask"); \
> - __BUILD_BUG_ON_NOT_POWER_OF_2((_mask) + \
> - (1ULL << __bf_shf(_mask))); \
> + BUILD_BUG_ON_MSG(!__builtin_constant_p(mask), \
> + pfx "mask is not constant"); \
> + BUILD_BUG_ON_MSG((mask) == 0, pfx "mask is zero"); \
> + BUILD_BUG_ON_MSG(__builtin_constant_p(val) ? \
> + ~((mask) >> __bf_shf(mask)) & \
> + (0 + (val)) : 0, \
> + pfx "value too large for the field"); \
> + BUILD_BUG_ON_MSG(__bf_cast_unsigned(mask, mask) > \
> + __bf_cast_unsigned(reg, ~0ull), \
> + pfx "type of reg too small for mask"); \
> + __BUILD_BUG_ON_NOT_POWER_OF_2((mask) + \
> + (1ULL << __bf_shf(mask))); \
> })
Hi Geert,
Thanks for the series!
I agree that underscored parameters are excessive. But fixing them has
a side effect of wiping the history, which is a bad thing.
I would prefer to save a history over following a rule that seemingly
is not written down. Let's keep this untouched for now, and if there
will be a need to move the code, we can drop underscores as well.
Meanwhile you (and David) can propose a corresponding rule in
coding-style.rst and a checkpatch warning. That way we at least will
stop merging a new code of that style.
Thanks,
Yury
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 2/4] bitfield: Add non-constant field_{prep,get}() helpers
2025-10-17 10:54 ` [PATCH v4 2/4] bitfield: Add non-constant field_{prep,get}() helpers Geert Uytterhoeven
2025-10-17 12:33 ` Nuno Sá
@ 2025-10-17 18:51 ` Yury Norov
2025-10-20 13:00 ` Geert Uytterhoeven
1 sibling, 1 reply; 16+ messages in thread
From: Yury Norov @ 2025-10-17 18:51 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Michael Turquette, Stephen Boyd, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea, Giovanni Cabiddu, Herbert Xu, David Miller,
Linus Walleij, Bartosz Golaszewski, Joel Stanley, Andrew Jeffery,
Crt Mori, Jonathan Cameron, Lars-Peter Clausen, Jacky Huang,
Shan-Chun Hung, Rasmus Villemoes, Jaroslav Kysela, Takashi Iwai,
Johannes Berg, Jakub Kicinski, Alex Elder, David Laight,
Vincent Mailhol, Jason Baron, Borislav Petkov, Tony Luck,
Michael Hennerich, Kim Seer Paller, David Lechner, Nuno Sá,
Andy Shevchenko, Richard Genoud, Cosmin Tanislav, Biju Das,
Jianping Shen, linux-clk, linux-arm-kernel, linux-renesas-soc,
linux-crypto, linux-edac, qat-linux, linux-gpio, linux-aspeed,
linux-iio, linux-sound, linux-kernel, Jonathan Cameron
On Fri, Oct 17, 2025 at 12:54:10PM +0200, Geert Uytterhoeven wrote:
> 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 consolidating them in
> <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.
>
> 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@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>
> ---
> 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
Can you split out the part that actually introduces the new API?
...
> diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h
> index 7ff817bdae19b468..c999fe70076f6684 100644
> --- a/include/linux/bitfield.h
> +++ b/include/linux/bitfield.h
> @@ -220,4 +220,40 @@ __MAKE_OP(64)
> #undef __MAKE_OP
> #undef ____MAKE_OP
>
> +/**
> + * field_prep() - prepare a bitfield element
> + * @mask: shifted mask defining the field's length and position
> + * @val: value to put in the field
> + *
> + * 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.
> + */
> +#define field_prep(mask, val) \
> + ({ \
> + __auto_type __mask = (mask); \
> + typeof(mask) __val = (val); \
> + unsigned int __shift = sizeof(mask) <= 4 ? \
> + __ffs(__mask) : __ffs64(__mask); \
> + (__val << __shift) & __mask; \
__ffs(0) is undef. The corresponding comment in
include/asm-generic/bitops/__ffs.h explicitly says: "code should check
against 0 first".
I think mask = 0 is a sign of error here. Can you add a code catching
it at compile time, and maybe at runtime too? Something like:
#define __field_prep(mask, val)
({
unsigned __shift = sizeof(mask) <= 4 ? __ffs(mask) : __ffs64(mask);
(val << __shift) & mask;
})
#define field_prep(mask, val)
({
unsigned int __shift;
__auto_type __mask = (mask), __ret = 0;
typeof(mask) __val = (val);
BUILD_BUG_ON_ZERO(const_true(mask == 0));
if (WARN_ON_ONCE(mask == 0))
goto out;
__ret = __field_prep(__mask, __val);
out:
ret;
})
> +
> +/**
> + * field_get() - extract a bitfield element
> + * @mask: shifted mask defining the field's length and position
> + * @reg: value of entire bitfield
> + *
> + * 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.
> + */
> +#define field_get(mask, reg) \
> + ({ \
> + __auto_type __mask = (mask); \
> + typeof(mask) __reg = (reg); \
This would trigger Wconversion warning. Consider
unsigned reg = 0xfff;
field_get(0xf, reg);
<source>:6:26: warning: conversion to 'int' from 'unsigned int' may change the sign of the result [-Wsign-conversion]
6 | typeof(mask) __reg = reg;
| ^~~
Notice, the __auto_type makes the __mask to be int, while the reg is
unsigned int. You need to do:
typeof(mask) __reg = (typeof(mask))(reg);
Please enable higher warning levels for the next round.
Also, because for numerals __auto_type is int, when char is enough - are
you sure that the macro generates the optimal code? User can workaround it
with:
field_get((u8)0xf, reg)
but it may not be trivial. Can you add an example and explanation please?
> + unsigned int __shift = sizeof(mask) <= 4 ? \
> + __ffs(__mask) : __ffs64(__mask); \
Can you use BITS_PER_TYPE() here?
> + (__reg & __mask) >> __shift; \
> + })
> +
When mask == 0, we shouldn't touch 'val' at all. Consider
field_get(0, get_user(ptr))
In this case, evaluating 'reg' is an error, similarly to memcpy().
Thanks,
Yury
> #endif
> diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
> index 828af3095b86ee0a..6eee89cbc0867f2b 100644
> --- a/sound/usb/mixer_quirks.c
> +++ b/sound/usb/mixer_quirks.c
> @@ -3311,10 +3311,6 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer)
> #define RME_DIGIFACE_REGISTER(reg, mask) (((reg) << 16) | (mask))
> #define RME_DIGIFACE_INVERT BIT(31)
>
> -/* Nonconst helpers */
> -#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
> -#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
> -
> static int snd_rme_digiface_write_reg(struct snd_kcontrol *kcontrol, int item, u16 mask, u16 val)
> {
> struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
> --
> 2.43.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 1/4] bitfield: Drop underscores from macro parameters
2025-10-17 16:37 ` Yury Norov
@ 2025-10-20 12:13 ` Geert Uytterhoeven
2025-10-20 14:56 ` Yury Norov
0 siblings, 1 reply; 16+ messages in thread
From: Geert Uytterhoeven @ 2025-10-20 12:13 UTC (permalink / raw)
To: Yury Norov
Cc: Michael Turquette, Stephen Boyd, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea, Giovanni Cabiddu, Herbert Xu, David Miller,
Linus Walleij, Bartosz Golaszewski, Joel Stanley, Andrew Jeffery,
Crt Mori, Jonathan Cameron, Lars-Peter Clausen, Jacky Huang,
Shan-Chun Hung, Rasmus Villemoes, Jaroslav Kysela, Takashi Iwai,
Johannes Berg, Jakub Kicinski, Alex Elder, David Laight,
Vincent Mailhol, Jason Baron, Borislav Petkov, Tony Luck,
Michael Hennerich, Kim Seer Paller, David Lechner, Nuno Sá,
Andy Shevchenko, Richard Genoud, Cosmin Tanislav, Biju Das,
Jianping Shen, linux-clk, linux-arm-kernel, linux-renesas-soc,
linux-crypto, linux-edac, qat-linux, linux-gpio, linux-aspeed,
linux-iio, linux-sound, linux-kernel
Hi Yury,
On Fri, 17 Oct 2025 at 18:37, Yury Norov <yury.norov@gmail.com> wrote:
> On Fri, Oct 17, 2025 at 12:54:09PM +0200, Geert Uytterhoeven wrote:
> > There is no need to prefix macro parameters with underscores.
> > Remove the underscores.
> >
> > Suggested-by: David Laight <david.laight.linux@gmail.com>
> > Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> > ---
> > v4:
> > - Update recently introduced FIELD_MODIFY() macro,
> > --- a/include/linux/bitfield.h
> > +++ b/include/linux/bitfield.h
> > @@ -60,68 +60,68 @@
> >
> > #define __bf_cast_unsigned(type, x) ((__unsigned_scalar_typeof(type))(x))
> >
> > -#define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx) \
> > +#define __BF_FIELD_CHECK(mask, reg, val, pfx) \
> > ({ \
> > - BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask), \
> > - _pfx "mask is not constant"); \
> > - BUILD_BUG_ON_MSG((_mask) == 0, _pfx "mask is zero"); \
> > - BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \
> > - ~((_mask) >> __bf_shf(_mask)) & \
> > - (0 + (_val)) : 0, \
> > - _pfx "value too large for the field"); \
> > - BUILD_BUG_ON_MSG(__bf_cast_unsigned(_mask, _mask) > \
> > - __bf_cast_unsigned(_reg, ~0ull), \
> > - _pfx "type of reg too small for mask"); \
> > - __BUILD_BUG_ON_NOT_POWER_OF_2((_mask) + \
> > - (1ULL << __bf_shf(_mask))); \
> > + BUILD_BUG_ON_MSG(!__builtin_constant_p(mask), \
> > + pfx "mask is not constant"); \
> > + BUILD_BUG_ON_MSG((mask) == 0, pfx "mask is zero"); \
> > + BUILD_BUG_ON_MSG(__builtin_constant_p(val) ? \
> > + ~((mask) >> __bf_shf(mask)) & \
> > + (0 + (val)) : 0, \
> > + pfx "value too large for the field"); \
> > + BUILD_BUG_ON_MSG(__bf_cast_unsigned(mask, mask) > \
> > + __bf_cast_unsigned(reg, ~0ull), \
> > + pfx "type of reg too small for mask"); \
> > + __BUILD_BUG_ON_NOT_POWER_OF_2((mask) + \
> > + (1ULL << __bf_shf(mask))); \
> > })
>
> I agree that underscored parameters are excessive. But fixing them has
> a side effect of wiping the history, which is a bad thing.
>
> I would prefer to save a history over following a rule that seemingly
> is not written down. Let's keep this untouched for now, and if there
> will be a need to move the code, we can drop underscores as well.
Fair enough.
So I assume you are fine with not having underscored parameters in
new code, like in [PATCH v4 2/4]?
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 2/4] bitfield: Add non-constant field_{prep,get}() helpers
2025-10-17 18:51 ` Yury Norov
@ 2025-10-20 13:00 ` Geert Uytterhoeven
2025-10-22 4:20 ` Yury Norov
0 siblings, 1 reply; 16+ messages in thread
From: Geert Uytterhoeven @ 2025-10-20 13:00 UTC (permalink / raw)
To: Yury Norov
Cc: Michael Turquette, Stephen Boyd, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea, Giovanni Cabiddu, Herbert Xu, David Miller,
Linus Walleij, Bartosz Golaszewski, Joel Stanley, Andrew Jeffery,
Crt Mori, Jonathan Cameron, Lars-Peter Clausen, Jacky Huang,
Shan-Chun Hung, Rasmus Villemoes, Jaroslav Kysela, Takashi Iwai,
Johannes Berg, Jakub Kicinski, Alex Elder, David Laight,
Vincent Mailhol, Jason Baron, Borislav Petkov, Tony Luck,
Michael Hennerich, Kim Seer Paller, David Lechner, Nuno Sá,
Andy Shevchenko, Richard Genoud, Cosmin Tanislav, Biju Das,
Jianping Shen, linux-clk, linux-arm-kernel, linux-renesas-soc,
linux-crypto, linux-edac, qat-linux, linux-gpio, linux-aspeed,
linux-iio, linux-sound, linux-kernel, Jonathan Cameron
Hi Yury,
On Fri, 17 Oct 2025 at 20:51, Yury Norov <yury.norov@gmail.com> wrote:
> On Fri, Oct 17, 2025 at 12:54:10PM +0200, Geert Uytterhoeven wrote:
> > 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 consolidating them in
> > <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.
> >
> > 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@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>
> > ---
> > 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
>
> Can you split out the part that actually introduces the new API?
Unfortunately not, as that would cause build warnings/failures due
to conflicting redefinitions.
That is a reason why I want to apply this patch ASAP: new copies show
up all the time.
> > --- a/include/linux/bitfield.h
> > +++ b/include/linux/bitfield.h
> > @@ -220,4 +220,40 @@ __MAKE_OP(64)
> > #undef __MAKE_OP
> > #undef ____MAKE_OP
> >
> > +/**
> > + * field_prep() - prepare a bitfield element
> > + * @mask: shifted mask defining the field's length and position
> > + * @val: value to put in the field
> > + *
> > + * 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.
> > + */
> > +#define field_prep(mask, val) \
> > + ({ \
> > + __auto_type __mask = (mask); \
> > + typeof(mask) __val = (val); \
> > + unsigned int __shift = sizeof(mask) <= 4 ? \
> > + __ffs(__mask) : __ffs64(__mask); \
> > + (__val << __shift) & __mask; \
>
> __ffs(0) is undef. The corresponding comment in
> include/asm-generic/bitops/__ffs.h explicitly says: "code should check
> against 0 first".
An all zeroes mask is a bug in the code that calls field_{get,prep}().
> I think mask = 0 is a sign of error here. Can you add a code catching
> it at compile time, and maybe at runtime too? Something like:
>
> #define __field_prep(mask, val)
> ({
> unsigned __shift = sizeof(mask) <= 4 ? __ffs(mask) : __ffs64(mask);
> (val << __shift) & mask;
> })
>
> #define field_prep(mask, val)
> ({
> unsigned int __shift;
> __auto_type __mask = (mask), __ret = 0;
> typeof(mask) __val = (val);
>
> BUILD_BUG_ON_ZERO(const_true(mask == 0));
Futile, as code with a constant mask should use FIELD_PREP() instead.
>
> if (WARN_ON_ONCE(mask == 0))
> goto out;
>
> __ret = __field_prep(__mask, __val);
> out:
> ret;
> })
Should we penalize all users (this is a macro, thus inlined everywhere)
to protect against something that is clearly a bug in the caller?
E.g. do_div() does not check for a zero divisor either.
> > +
> > +/**
> > + * field_get() - extract a bitfield element
> > + * @mask: shifted mask defining the field's length and position
> > + * @reg: value of entire bitfield
> > + *
> > + * 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.
> > + */
> > +#define field_get(mask, reg) \
> > + ({ \
> > + __auto_type __mask = (mask); \
> > + typeof(mask) __reg = (reg); \
>
> This would trigger Wconversion warning. Consider
> unsigned reg = 0xfff;
> field_get(0xf, reg);
>
> <source>:6:26: warning: conversion to 'int' from 'unsigned int' may change the sign of the result [-Wsign-conversion]
> 6 | typeof(mask) __reg = reg;
> | ^~~
>
> Notice, the __auto_type makes the __mask to be int, while the reg is
Apparently using typeof(mask) has the same "issue"...
> unsigned int. You need to do:
>
> typeof(mask) __reg = (typeof(mask))(reg);
... so the cast is just hiding the issue? Worse, the cast may prevent the
compiler from flagging other issues, e.g. when accidentally passing
a pointer for reg.
>
> Please enable higher warning levels for the next round.
Enabling -Wsign-conversion gives lots of other (false positive?)
warnings.
> Also, because for numerals __auto_type is int, when char is enough - are
> you sure that the macro generates the optimal code? User can workaround it
> with:
>
> field_get((u8)0xf, reg)
>
> but it may not be trivial. Can you add an example and explanation please?
These new macros are intended for the case where mask is not a constant.
So typically it is a variable of type u32 or u64.
> > + unsigned int __shift = sizeof(mask) <= 4 ? \
> > + __ffs(__mask) : __ffs64(__mask); \
>
> Can you use BITS_PER_TYPE() here?
Yes, I could use BITS_PER_TYPE(unsigned long) here, to match the
parameter type of __ffs() (on 64-bit platforms, __ffs() can be used
unconditionally anyway), at the expense of making the line much longer
so it has to be split. Is that worthwhile?
>
> > + (__reg & __mask) >> __shift; \
> > + })
> > +
>
> When mask == 0, we shouldn't touch 'val' at all. Consider
>
> field_get(0, get_user(ptr))
>
> In this case, evaluating 'reg' is an error, similarly to memcpy().
Again, a zero mask is a bug.
Thanks!
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 1/4] bitfield: Drop underscores from macro parameters
2025-10-20 12:13 ` Geert Uytterhoeven
@ 2025-10-20 14:56 ` Yury Norov
0 siblings, 0 replies; 16+ messages in thread
From: Yury Norov @ 2025-10-20 14:56 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Michael Turquette, Stephen Boyd, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea, Giovanni Cabiddu, Herbert Xu, David Miller,
Linus Walleij, Bartosz Golaszewski, Joel Stanley, Andrew Jeffery,
Crt Mori, Jonathan Cameron, Lars-Peter Clausen, Jacky Huang,
Shan-Chun Hung, Rasmus Villemoes, Jaroslav Kysela, Takashi Iwai,
Johannes Berg, Jakub Kicinski, Alex Elder, David Laight,
Vincent Mailhol, Jason Baron, Borislav Petkov, Tony Luck,
Michael Hennerich, Kim Seer Paller, David Lechner, Nuno Sá,
Andy Shevchenko, Richard Genoud, Cosmin Tanislav, Biju Das,
Jianping Shen, linux-clk, linux-arm-kernel, linux-renesas-soc,
linux-crypto, linux-edac, qat-linux, linux-gpio, linux-aspeed,
linux-iio, linux-sound, linux-kernel
> > I agree that underscored parameters are excessive. But fixing them has
> > a side effect of wiping the history, which is a bad thing.
> >
> > I would prefer to save a history over following a rule that seemingly
> > is not written down. Let's keep this untouched for now, and if there
> > will be a need to move the code, we can drop underscores as well.
>
> Fair enough.
> So I assume you are fine with not having underscored parameters in
> new code, like in [PATCH v4 2/4]?
Yes, sure.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 2/4] bitfield: Add non-constant field_{prep,get}() helpers
2025-10-20 13:00 ` Geert Uytterhoeven
@ 2025-10-22 4:20 ` Yury Norov
2025-10-22 10:01 ` Geert Uytterhoeven
0 siblings, 1 reply; 16+ messages in thread
From: Yury Norov @ 2025-10-22 4:20 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Michael Turquette, Stephen Boyd, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea, Giovanni Cabiddu, Herbert Xu, David Miller,
Linus Walleij, Bartosz Golaszewski, Joel Stanley, Andrew Jeffery,
Crt Mori, Jonathan Cameron, Lars-Peter Clausen, Jacky Huang,
Shan-Chun Hung, Rasmus Villemoes, Jaroslav Kysela, Takashi Iwai,
Johannes Berg, Jakub Kicinski, Alex Elder, David Laight,
Vincent Mailhol, Jason Baron, Borislav Petkov, Tony Luck,
Michael Hennerich, Kim Seer Paller, David Lechner, Nuno Sá,
Andy Shevchenko, Richard Genoud, Cosmin Tanislav, Biju Das,
Jianping Shen, linux-clk, linux-arm-kernel, linux-renesas-soc,
linux-crypto, linux-edac, qat-linux, linux-gpio, linux-aspeed,
linux-iio, linux-sound, linux-kernel, Jonathan Cameron
On Mon, Oct 20, 2025 at 03:00:24PM +0200, Geert Uytterhoeven wrote:
> Hi Yury,
>
> On Fri, 17 Oct 2025 at 20:51, Yury Norov <yury.norov@gmail.com> wrote:
> > On Fri, Oct 17, 2025 at 12:54:10PM +0200, Geert Uytterhoeven wrote:
> > > 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 consolidating them in
> > > <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.
> > >
> > > 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@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>
> > > ---
> > > 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
> >
> > Can you split out the part that actually introduces the new API?
>
> Unfortunately not, as that would cause build warnings/failures due
> to conflicting redefinitions.
> That is a reason why I want to apply this patch ASAP: new copies show
> up all the time.
In a preparation patch, for each driver:
+#ifndef field_prep
#define field_prep() ...
+#endif
Or simply
+#undef field_prep
#define field_prep() ...
Then add the generic field_prep() in a separate patch. Then you can drop
ifdefery in the drivers.
Yeah, more patches, but the result is cleaner.
> > > --- a/include/linux/bitfield.h
> > > +++ b/include/linux/bitfield.h
> > > @@ -220,4 +220,40 @@ __MAKE_OP(64)
> > > #undef __MAKE_OP
> > > #undef ____MAKE_OP
> > >
> > > +/**
> > > + * field_prep() - prepare a bitfield element
> > > + * @mask: shifted mask defining the field's length and position
> > > + * @val: value to put in the field
> > > + *
> > > + * 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.
> > > + */
> > > +#define field_prep(mask, val) \
> > > + ({ \
> > > + __auto_type __mask = (mask); \
> > > + typeof(mask) __val = (val); \
> > > + unsigned int __shift = sizeof(mask) <= 4 ? \
> > > + __ffs(__mask) : __ffs64(__mask); \
> > > + (__val << __shift) & __mask; \
> >
> > __ffs(0) is undef. The corresponding comment in
> > include/asm-generic/bitops/__ffs.h explicitly says: "code should check
> > against 0 first".
>
> An all zeroes mask is a bug in the code that calls field_{get,prep}().
It's a bug in FIELD_GET() - for sure. Because it's enforced in
__BF_FIELD_CHECK(). field_get() doesn't enforce it, doesn't even
mention that in the comment.
I'm not fully convinced that empty runtime mask should be a bug.
Consider memcpy(dst, src, 0). This is a no-op, but not a bug as
soon as the pointers are valid. If you _think_ it's a bug - please
enforce it.
> > I think mask = 0 is a sign of error here. Can you add a code catching
> > it at compile time, and maybe at runtime too? Something like:
> >
> > #define __field_prep(mask, val)
> > ({
> > unsigned __shift = sizeof(mask) <= 4 ? __ffs(mask) : __ffs64(mask);
> > (val << __shift) & mask;
> > })
> >
> > #define field_prep(mask, val)
> > ({
> > unsigned int __shift;
> > __auto_type __mask = (mask), __ret = 0;
> > typeof(mask) __val = (val);
> >
> > BUILD_BUG_ON_ZERO(const_true(mask == 0));
>
> Futile, as code with a constant mask should use FIELD_PREP() instead.
It's a weak argument. Sometimes compiler is smart enough to realize
that something is a constant, while people won't. Sometimes code gets
refactored. Sometimes people build complex expressions that should
work both in run-time and compile time cases. Sometimes variables are
compile- or run-time depending on config (nr_cpu_ids is an example).
The field_prep() must handle const case just as good as capitalized
version does.
> > if (WARN_ON_ONCE(mask == 0))
> > goto out;
> >
> > __ret = __field_prep(__mask, __val);
> > out:
> > ret;
> > })
>
> Should we penalize all users (this is a macro, thus inlined everywhere)
> to protect against something that is clearly a bug in the caller?
No. But we can wrap it with a config:
#ifdef CONFIG_BITFIELD_HARDENING
if (WARN_ON_ONCE(mask == 0))
goto out;
#endif
The real question here: do you want to help people to catch their bugs,
or you want them to fight it alone?
The _BF_FIELD_CHECK() authors are nice people and provide helpful guides.
(I don't insist, it's up to you.)
> E.g. do_div() does not check for a zero divisor either.
>
> > > +/**
> > > + * field_get() - extract a bitfield element
> > > + * @mask: shifted mask defining the field's length and position
> > > + * @reg: value of entire bitfield
> > > + *
> > > + * 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.
> > > + */
> > > +#define field_get(mask, reg) \
> > > + ({ \
> > > + __auto_type __mask = (mask); \
> > > + typeof(mask) __reg = (reg); \
> >
> > This would trigger Wconversion warning. Consider
> > unsigned reg = 0xfff;
> > field_get(0xf, reg);
> >
> > <source>:6:26: warning: conversion to 'int' from 'unsigned int' may change the sign of the result [-Wsign-conversion]
> > 6 | typeof(mask) __reg = reg;
> > | ^~~
> >
> > Notice, the __auto_type makes the __mask to be int, while the reg is
>
> Apparently using typeof(mask) has the same "issue"...
>
> > unsigned int. You need to do:
> >
> > typeof(mask) __reg = (typeof(mask))(reg);
>
> ... so the cast is just hiding the issue? Worse, the cast may prevent the
> compiler from flagging other issues, e.g. when accidentally passing
> a pointer for reg.
Ok, makes sense.
> > Please enable higher warning levels for the next round.
>
> Enabling -Wsign-conversion gives lots of other (false positive?)
> warnings.
>
> > Also, because for numerals __auto_type is int, when char is enough - are
> > you sure that the macro generates the optimal code? User can workaround it
> > with:
> >
> > field_get((u8)0xf, reg)
> >
> > but it may not be trivial. Can you add an example and explanation please?
>
> These new macros are intended for the case where mask is not a constant.
> So typically it is a variable of type u32 or u64.
You never mentioned that. Anyways, it's again a weak argument.
> > > + unsigned int __shift = sizeof(mask) <= 4 ? \
> > > + __ffs(__mask) : __ffs64(__mask); \
> >
> > Can you use BITS_PER_TYPE() here?
>
> Yes, I could use BITS_PER_TYPE(unsigned long) here, to match the
> parameter type of __ffs() (on 64-bit platforms, __ffs() can be used
> unconditionally anyway), at the expense of making the line much longer
> so it has to be split. Is that worthwhile?
Not sure I understand... The
"unsigned int __shift = BITS_PER_TYPE(mask) < 64 ?"
is 49 chars long vs 42 in your version. Even if you add two tabs, it's
still way below limits. And yes,
unsigned int __shift = sizeof(mask) <= 4 ? \
__ffs(__mask) : __ffs64(__mask); \
is worse than
unsigned int __shift = BITS_PER_TYPE(mask) < 64 ? \
__ffs(__mask) : __ffs64(__mask); \
> > > + (__reg & __mask) >> __shift; \
> > > + })
> > > +
> >
> > When mask == 0, we shouldn't touch 'val' at all. Consider
> >
> > field_get(0, get_user(ptr))
> >
> > In this case, evaluating 'reg' is an error, similarly to memcpy().
>
> Again, a zero mask is a bug.
>
> Thanks!
>
> Gr{oetje,eeting}s,
>
> Geert
>
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
>
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
> -- Linus Torvalds
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 2/4] bitfield: Add non-constant field_{prep,get}() helpers
2025-10-22 4:20 ` Yury Norov
@ 2025-10-22 10:01 ` Geert Uytterhoeven
2025-10-22 15:50 ` Yury Norov
0 siblings, 1 reply; 16+ messages in thread
From: Geert Uytterhoeven @ 2025-10-22 10:01 UTC (permalink / raw)
To: Yury Norov
Cc: Michael Turquette, Stephen Boyd, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea, Giovanni Cabiddu, Herbert Xu, David Miller,
Linus Walleij, Bartosz Golaszewski, Joel Stanley, Andrew Jeffery,
Crt Mori, Jonathan Cameron, Lars-Peter Clausen, Jacky Huang,
Shan-Chun Hung, Rasmus Villemoes, Jaroslav Kysela, Takashi Iwai,
Johannes Berg, Jakub Kicinski, Alex Elder, David Laight,
Vincent Mailhol, Jason Baron, Borislav Petkov, Tony Luck,
Michael Hennerich, Kim Seer Paller, David Lechner, Nuno Sá,
Andy Shevchenko, Richard Genoud, Cosmin Tanislav, Biju Das,
Jianping Shen, linux-clk, linux-arm-kernel, linux-renesas-soc,
linux-crypto, linux-edac, qat-linux, linux-gpio, linux-aspeed,
linux-iio, linux-sound, linux-kernel, Jonathan Cameron
Hi Yury,
On Wed, 22 Oct 2025 at 06:20, Yury Norov <yury.norov@gmail.com> wrote:
> On Mon, Oct 20, 2025 at 03:00:24PM +0200, Geert Uytterhoeven wrote:
> > On Fri, 17 Oct 2025 at 20:51, Yury Norov <yury.norov@gmail.com> wrote:
> > > On Fri, Oct 17, 2025 at 12:54:10PM +0200, Geert Uytterhoeven wrote:
> > > > 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 consolidating them in
> > > > <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.
> > > >
> > > > 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@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>
> > > > ---
> > > > 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
> > >
> > > Can you split out the part that actually introduces the new API?
> >
> > Unfortunately not, as that would cause build warnings/failures due
> > to conflicting redefinitions.
> > That is a reason why I want to apply this patch ASAP: new copies show
> > up all the time.
>
> In a preparation patch, for each driver:
>
> +#ifndef field_prep
> #define field_prep() ...
> +#endif
>
> Or simply
>
> +#undef field_prep
> #define field_prep() ...
>
> Then add the generic field_prep() in a separate patch. Then you can drop
> ifdefery in the drivers.
>
> Yeah, more patches, but the result is cleaner.
And we need 3 kernel releases, as the addition of the macros to
the header file now has a hard dependency on adding the #undefs?
Unless I still apply all of them to an immutable branch, but then what
is the point?
> > > > --- a/include/linux/bitfield.h
> > > > +++ b/include/linux/bitfield.h
> > > > @@ -220,4 +220,40 @@ __MAKE_OP(64)
> > > > #undef __MAKE_OP
> > > > #undef ____MAKE_OP
> > > >
> > > > +/**
> > > > + * field_prep() - prepare a bitfield element
> > > > + * @mask: shifted mask defining the field's length and position
> > > > + * @val: value to put in the field
> > > > + *
> > > > + * 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.
> > > > + */
> > > > +#define field_prep(mask, val) \
> > > > + ({ \
> > > > + __auto_type __mask = (mask); \
> > > > + typeof(mask) __val = (val); \
> > > > + unsigned int __shift = sizeof(mask) <= 4 ? \
> > > > + __ffs(__mask) : __ffs64(__mask); \
> > > > + (__val << __shift) & __mask; \
> > >
> > > __ffs(0) is undef. The corresponding comment in
> > > include/asm-generic/bitops/__ffs.h explicitly says: "code should check
> > > against 0 first".
> >
> > An all zeroes mask is a bug in the code that calls field_{get,prep}().
>
> It's a bug in FIELD_GET() - for sure. Because it's enforced in
> __BF_FIELD_CHECK(). field_get() doesn't enforce it, doesn't even
> mention that in the comment.
>
> I'm not fully convinced that empty runtime mask should be a bug.
Getting (and using) data from nowhere is a bug.
Storing data where there is no space to store is also a bug.
I will add a comment.
> Consider memcpy(dst, src, 0). This is a no-op, but not a bug as
> soon as the pointers are valid. If you _think_ it's a bug - please
> enforce it.
memcpy() with a fixed size of zero is probably a bug.
memcpy() with a variable size is usually used to copy "as much as is
needed", so zero is usually not a bug.
> > > I think mask = 0 is a sign of error here. Can you add a code catching
> > > it at compile time, and maybe at runtime too? Something like:
> > >
> > > #define __field_prep(mask, val)
> > > ({
> > > unsigned __shift = sizeof(mask) <= 4 ? __ffs(mask) : __ffs64(mask);
> > > (val << __shift) & mask;
> > > })
> > >
> > > #define field_prep(mask, val)
> > > ({
> > > unsigned int __shift;
> > > __auto_type __mask = (mask), __ret = 0;
> > > typeof(mask) __val = (val);
> > >
> > > BUILD_BUG_ON_ZERO(const_true(mask == 0));
> >
> > Futile, as code with a constant mask should use FIELD_PREP() instead.
>
> It's a weak argument. Sometimes compiler is smart enough to realize
> that something is a constant, while people won't. Sometimes code gets
> refactored. Sometimes people build complex expressions that should
> work both in run-time and compile time cases. Sometimes variables are
> compile- or run-time depending on config (nr_cpu_ids is an example).
>
> The field_prep() must handle const case just as good as capitalized
> version does.
OK, I will add the (build-time) check.
> > > if (WARN_ON_ONCE(mask == 0))
> > > goto out;
> > >
> > > __ret = __field_prep(__mask, __val);
> > > out:
> > > ret;
> > > })
> >
> > Should we penalize all users (this is a macro, thus inlined everywhere)
> > to protect against something that is clearly a bug in the caller?
>
> No. But we can wrap it with a config:
>
> #ifdef CONFIG_BITFIELD_HARDENING
> if (WARN_ON_ONCE(mask == 0))
> goto out;
> #endif
That can be done later, when hardening other bitfield functions
and macros.
> > These new macros are intended for the case where mask is not a constant.
> > So typically it is a variable of type u32 or u64.
>
> You never mentioned that. Anyways, it's again a weak argument.
I'll add more comments ;-)
> > > > + unsigned int __shift = sizeof(mask) <= 4 ? \
> > > > + __ffs(__mask) : __ffs64(__mask); \
> > >
> > > Can you use BITS_PER_TYPE() here?
> >
> > Yes, I could use BITS_PER_TYPE(unsigned long) here, to match the
> > parameter type of __ffs() (on 64-bit platforms, __ffs() can be used
> > unconditionally anyway), at the expense of making the line much longer
> > so it has to be split. Is that worthwhile?
>
> Not sure I understand... The
>
> "unsigned int __shift = BITS_PER_TYPE(mask) < 64 ?"
>
> is 49 chars long vs 42 in your version. Even if you add two tabs, it's
> still way below limits. And yes,
Oh, you meant instead of the size check.
I thought you objected to the hardcoded number 4.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 2/4] bitfield: Add non-constant field_{prep,get}() helpers
2025-10-22 10:01 ` Geert Uytterhoeven
@ 2025-10-22 15:50 ` Yury Norov
2025-10-23 11:38 ` Geert Uytterhoeven
0 siblings, 1 reply; 16+ messages in thread
From: Yury Norov @ 2025-10-22 15:50 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Michael Turquette, Stephen Boyd, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea, Giovanni Cabiddu, Herbert Xu, David Miller,
Linus Walleij, Bartosz Golaszewski, Joel Stanley, Andrew Jeffery,
Crt Mori, Jonathan Cameron, Lars-Peter Clausen, Jacky Huang,
Shan-Chun Hung, Rasmus Villemoes, Jaroslav Kysela, Takashi Iwai,
Johannes Berg, Jakub Kicinski, Alex Elder, David Laight,
Vincent Mailhol, Jason Baron, Borislav Petkov, Tony Luck,
Michael Hennerich, Kim Seer Paller, David Lechner, Nuno Sá,
Andy Shevchenko, Richard Genoud, Cosmin Tanislav, Biju Das,
Jianping Shen, linux-clk, linux-arm-kernel, linux-renesas-soc,
linux-crypto, linux-edac, qat-linux, linux-gpio, linux-aspeed,
linux-iio, linux-sound, linux-kernel, Jonathan Cameron
On Wed, Oct 22, 2025 at 12:01:37PM +0200, Geert Uytterhoeven wrote:
> Hi Yury,
>
> On Wed, 22 Oct 2025 at 06:20, Yury Norov <yury.norov@gmail.com> wrote:
> > On Mon, Oct 20, 2025 at 03:00:24PM +0200, Geert Uytterhoeven wrote:
> > > On Fri, 17 Oct 2025 at 20:51, Yury Norov <yury.norov@gmail.com> wrote:
> > > > On Fri, Oct 17, 2025 at 12:54:10PM +0200, Geert Uytterhoeven wrote:
> > > > > 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 consolidating them in
> > > > > <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.
> > > > >
> > > > > 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@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>
> > > > > ---
> > > > > 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
> > > >
> > > > Can you split out the part that actually introduces the new API?
> > >
> > > Unfortunately not, as that would cause build warnings/failures due
> > > to conflicting redefinitions.
> > > That is a reason why I want to apply this patch ASAP: new copies show
> > > up all the time.
> >
> > In a preparation patch, for each driver:
> >
> > +#ifndef field_prep
> > #define field_prep() ...
> > +#endif
> >
> > Or simply
> >
> > +#undef field_prep
> > #define field_prep() ...
> >
> > Then add the generic field_prep() in a separate patch. Then you can drop
> > ifdefery in the drivers.
> >
> > Yeah, more patches, but the result is cleaner.
>
> And we need 3 kernel releases, as the addition of the macros to
> the header file now has a hard dependency on adding the #undefs?
> Unless I still apply all of them to an immutable branch, but then what
> is the point?
Not sure what do you mean. You can do it in a single series, and you
don't need and should not split the series across releases. Consider
my recent cpumask_next_wrap() rework as an example:
https://lore.kernel.org/all/20250128164646.4009-1-yury.norov@gmail.com/
1. #1-4 switch kernel users to alternative functions;
2. #5 deprecates cpumask_next_wrap(), making sure it's a pure renaming,
i.e. no-op.
3. #6 introduces the new nice implementation. It's the core-only patch,
no drivers are touched.
4. #7-12 switch the rest of codebase from old version to new.
5. #13 drops deprecated old function.
This is the most common scheme. In you case you can cut the corners.
The goals here are:
- keep core patches free of non-core code;
- switch drivers to the new functionality one-by-one in sake of
bisectability.
> > > > > --- a/include/linux/bitfield.h
> > > > > +++ b/include/linux/bitfield.h
> > > > > @@ -220,4 +220,40 @@ __MAKE_OP(64)
> > > > > #undef __MAKE_OP
> > > > > #undef ____MAKE_OP
> > > > >
> > > > > +/**
> > > > > + * field_prep() - prepare a bitfield element
> > > > > + * @mask: shifted mask defining the field's length and position
> > > > > + * @val: value to put in the field
> > > > > + *
> > > > > + * 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.
> > > > > + */
> > > > > +#define field_prep(mask, val) \
> > > > > + ({ \
> > > > > + __auto_type __mask = (mask); \
> > > > > + typeof(mask) __val = (val); \
> > > > > + unsigned int __shift = sizeof(mask) <= 4 ? \
> > > > > + __ffs(__mask) : __ffs64(__mask); \
> > > > > + (__val << __shift) & __mask; \
> > > >
> > > > __ffs(0) is undef. The corresponding comment in
> > > > include/asm-generic/bitops/__ffs.h explicitly says: "code should check
> > > > against 0 first".
> > >
> > > An all zeroes mask is a bug in the code that calls field_{get,prep}().
> >
> > It's a bug in FIELD_GET() - for sure. Because it's enforced in
> > __BF_FIELD_CHECK(). field_get() doesn't enforce it, doesn't even
> > mention that in the comment.
> >
> > I'm not fully convinced that empty runtime mask should be a bug.
>
> Getting (and using) data from nowhere is a bug.
> Storing data where there is no space to store is also a bug.
>
> I will add a comment.
>
> > Consider memcpy(dst, src, 0). This is a no-op, but not a bug as
> > soon as the pointers are valid. If you _think_ it's a bug - please
> > enforce it.
>
> memcpy() with a fixed size of zero is probably a bug.
> memcpy() with a variable size is usually used to copy "as much as is
> needed", so zero is usually not a bug.
5 lines above you say: "Getting (and using) data from nowhere is a bug".
Now you're saying: "so zero is usually not a bug". So, is it a bug or
not?
Consider this example:
unsigned a = field_get(mask, get_user(ptr));
Conceptually it's the same as per-bit copy_from_user().
The copy_from_user
1. allows size == 0;
2. does not dereference pointers in that case, i.e. doesn't call
get_user().
Can we make sure that field_get() provides the same guarantees?
> > > > I think mask = 0 is a sign of error here. Can you add a code catching
> > > > it at compile time, and maybe at runtime too? Something like:
> > > >
> > > > #define __field_prep(mask, val)
> > > > ({
> > > > unsigned __shift = sizeof(mask) <= 4 ? __ffs(mask) : __ffs64(mask);
> > > > (val << __shift) & mask;
> > > > })
> > > >
> > > > #define field_prep(mask, val)
> > > > ({
> > > > unsigned int __shift;
> > > > __auto_type __mask = (mask), __ret = 0;
> > > > typeof(mask) __val = (val);
> > > >
> > > > BUILD_BUG_ON_ZERO(const_true(mask == 0));
> > >
> > > Futile, as code with a constant mask should use FIELD_PREP() instead.
> >
> > It's a weak argument. Sometimes compiler is smart enough to realize
> > that something is a constant, while people won't. Sometimes code gets
> > refactored. Sometimes people build complex expressions that should
> > work both in run-time and compile time cases. Sometimes variables are
> > compile- or run-time depending on config (nr_cpu_ids is an example).
> >
> > The field_prep() must handle const case just as good as capitalized
> > version does.
>
> OK, I will add the (build-time) check.
If mask is compile-time, you can wire field_prep() to FIELD_PREP(), so
it will do the work for you.
Thanks,
Yury
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 2/4] bitfield: Add non-constant field_{prep,get}() helpers
2025-10-22 15:50 ` Yury Norov
@ 2025-10-23 11:38 ` Geert Uytterhoeven
0 siblings, 0 replies; 16+ messages in thread
From: Geert Uytterhoeven @ 2025-10-23 11:38 UTC (permalink / raw)
To: Yury Norov
Cc: Michael Turquette, Stephen Boyd, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea, Giovanni Cabiddu, Herbert Xu, David Miller,
Linus Walleij, Bartosz Golaszewski, Joel Stanley, Andrew Jeffery,
Crt Mori, Jonathan Cameron, Lars-Peter Clausen, Jacky Huang,
Shan-Chun Hung, Rasmus Villemoes, Jaroslav Kysela, Takashi Iwai,
Johannes Berg, Jakub Kicinski, Alex Elder, David Laight,
Vincent Mailhol, Jason Baron, Borislav Petkov, Tony Luck,
Michael Hennerich, Kim Seer Paller, David Lechner, Nuno Sá,
Andy Shevchenko, Richard Genoud, Cosmin Tanislav, Biju Das,
Jianping Shen, linux-clk, linux-arm-kernel, linux-renesas-soc,
linux-crypto, linux-edac, qat-linux, linux-gpio, linux-aspeed,
linux-iio, linux-sound, linux-kernel, Jonathan Cameron
Hi Yury,
On Wed, 22 Oct 2025 at 17:50, Yury Norov <yury.norov@gmail.com> wrote:
> On Wed, Oct 22, 2025 at 12:01:37PM +0200, Geert Uytterhoeven wrote:
> > On Wed, 22 Oct 2025 at 06:20, Yury Norov <yury.norov@gmail.com> wrote:
> > > On Mon, Oct 20, 2025 at 03:00:24PM +0200, Geert Uytterhoeven wrote:
> > > > On Fri, 17 Oct 2025 at 20:51, Yury Norov <yury.norov@gmail.com> wrote:
> > > > > On Fri, Oct 17, 2025 at 12:54:10PM +0200, Geert Uytterhoeven wrote:
> > > > > > 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 consolidating them in
> > > > > > <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.
> > > > > >
> > > > > > 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@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>
> > > > > > ---
> > > > > > 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
> > > > >
> > > > > Can you split out the part that actually introduces the new API?
> > > >
> > > > Unfortunately not, as that would cause build warnings/failures due
> > > > to conflicting redefinitions.
> > > > That is a reason why I want to apply this patch ASAP: new copies show
> > > > up all the time.
> > >
> > > In a preparation patch, for each driver:
> > >
> > > +#ifndef field_prep
> > > #define field_prep() ...
> > > +#endif
> > >
> > > Or simply
> > >
> > > +#undef field_prep
> > > #define field_prep() ...
> > >
> > > Then add the generic field_prep() in a separate patch. Then you can drop
> > > ifdefery in the drivers.
> > >
> > > Yeah, more patches, but the result is cleaner.
> >
> > And we need 3 kernel releases, as the addition of the macros to
> > the header file now has a hard dependency on adding the #undefs?
> > Unless I still apply all of them to an immutable branch, but then what
> > is the point?
>
> Not sure what do you mean. You can do it in a single series, and you
> don't need and should not split the series across releases. Consider
> my recent cpumask_next_wrap() rework as an example:
>
> https://lore.kernel.org/all/20250128164646.4009-1-yury.norov@gmail.com/
>
> 1. #1-4 switch kernel users to alternative functions;
> 2. #5 deprecates cpumask_next_wrap(), making sure it's a pure renaming,
> i.e. no-op.
> 3. #6 introduces the new nice implementation. It's the core-only patch,
> no drivers are touched.
> 4. #7-12 switch the rest of codebase from old version to new.
> 5. #13 drops deprecated old function.
>
> This is the most common scheme. In you case you can cut the corners.
>
> The goals here are:
>
> - keep core patches free of non-core code;
> - switch drivers to the new functionality one-by-one in sake of
> bisectability.
OK, I'll make it so...
> > > > > > --- a/include/linux/bitfield.h
> > > > > > +++ b/include/linux/bitfield.h
> > > > > > @@ -220,4 +220,40 @@ __MAKE_OP(64)
> > > > > > #undef __MAKE_OP
> > > > > > #undef ____MAKE_OP
> > > > > >
> > > > > > +/**
> > > > > > + * field_prep() - prepare a bitfield element
> > > > > > + * @mask: shifted mask defining the field's length and position
> > > > > > + * @val: value to put in the field
> > > > > > + *
> > > > > > + * 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.
> > > > > > + */
> > > > > > +#define field_prep(mask, val) \
> > > > > > + ({ \
> > > > > > + __auto_type __mask = (mask); \
> > > > > > + typeof(mask) __val = (val); \
> > > > > > + unsigned int __shift = sizeof(mask) <= 4 ? \
> > > > > > + __ffs(__mask) : __ffs64(__mask); \
> > > > > > + (__val << __shift) & __mask; \
> > > > >
> > > > > __ffs(0) is undef. The corresponding comment in
> > > > > include/asm-generic/bitops/__ffs.h explicitly says: "code should check
> > > > > against 0 first".
> > > >
> > > > An all zeroes mask is a bug in the code that calls field_{get,prep}().
> > >
> > > It's a bug in FIELD_GET() - for sure. Because it's enforced in
> > > __BF_FIELD_CHECK(). field_get() doesn't enforce it, doesn't even
> > > mention that in the comment.
> > >
> > > I'm not fully convinced that empty runtime mask should be a bug.
> >
> > Getting (and using) data from nowhere is a bug.
^^^ This is about field_get().
> > Storing data where there is no space to store is also a bug.
^^^ This is about field_prep().
> > I will add a comment.
> >
> > > Consider memcpy(dst, src, 0). This is a no-op, but not a bug as
> > > soon as the pointers are valid. If you _think_ it's a bug - please
> > > enforce it.
> >
> > memcpy() with a fixed size of zero is probably a bug.
> > memcpy() with a variable size is usually used to copy "as much as is
> > needed", so zero is usually not a bug.
^^^ These 3 lines are about memcpy().
> 5 lines above you say: "Getting (and using) data from nowhere is a bug".
> Now you're saying: "so zero is usually not a bug". So, is it a bug or
> not?
> > > > > I think mask = 0 is a sign of error here. Can you add a code catching
> > > > > it at compile time, and maybe at runtime too? Something like:
> > > > >
> > > > > #define __field_prep(mask, val)
> > > > > ({
> > > > > unsigned __shift = sizeof(mask) <= 4 ? __ffs(mask) : __ffs64(mask);
> > > > > (val << __shift) & mask;
> > > > > })
> > > > >
> > > > > #define field_prep(mask, val)
> > > > > ({
> > > > > unsigned int __shift;
> > > > > __auto_type __mask = (mask), __ret = 0;
> > > > > typeof(mask) __val = (val);
> > > > >
> > > > > BUILD_BUG_ON_ZERO(const_true(mask == 0));
> > > >
> > > > Futile, as code with a constant mask should use FIELD_PREP() instead.
> > >
> > > It's a weak argument. Sometimes compiler is smart enough to realize
> > > that something is a constant, while people won't. Sometimes code gets
> > > refactored. Sometimes people build complex expressions that should
> > > work both in run-time and compile time cases. Sometimes variables are
> > > compile- or run-time depending on config (nr_cpu_ids is an example).
> > >
> > > The field_prep() must handle const case just as good as capitalized
> > > version does.
> >
> > OK, I will add the (build-time) check.
>
> If mask is compile-time, you can wire field_prep() to FIELD_PREP(), so
> it will do the work for you.
OK, I will look into it.
Thanks!
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2025-10-23 11:46 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-17 10:54 [PATCH v4 0/4] Non-const bitfield helpers Geert Uytterhoeven
2025-10-17 10:54 ` [PATCH v4 1/4] bitfield: Drop underscores from macro parameters Geert Uytterhoeven
2025-10-17 16:37 ` Yury Norov
2025-10-20 12:13 ` Geert Uytterhoeven
2025-10-20 14:56 ` Yury Norov
2025-10-17 10:54 ` [PATCH v4 2/4] bitfield: Add non-constant field_{prep,get}() helpers Geert Uytterhoeven
2025-10-17 12:33 ` Nuno Sá
2025-10-17 12:43 ` Richard GENOUD
2025-10-17 18:51 ` Yury Norov
2025-10-20 13:00 ` Geert Uytterhoeven
2025-10-22 4:20 ` Yury Norov
2025-10-22 10:01 ` Geert Uytterhoeven
2025-10-22 15:50 ` Yury Norov
2025-10-23 11:38 ` Geert Uytterhoeven
2025-10-17 10:54 ` [PATCH v4 3/4] clk: renesas: Use bitfield helpers Geert Uytterhoeven
2025-10-17 10:54 ` [PATCH v4 4/4] soc: " Geert Uytterhoeven
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).