diff options
| author | Luo Jie <quic_luoj@quicinc.com> | 2025-04-17 18:47:08 +0800 |
|---|---|---|
| committer | Yury Norov <yury.norov@gmail.com> | 2025-04-29 15:58:38 -0400 |
| commit | a256ae22570ee4c3427fdc703a58a89afee6a332 (patch) | |
| tree | 8168df33dba0f19402ca698901f73cb6196e38e2 | |
| parent | 89a44a808814d4717a8bf945ddebd5c39bfffcf4 (diff) | |
bitfield: Add FIELD_MODIFY() helper
Add a helper for replacing the contents of bitfield in memory
with the specified value.
Even though a helper xxx_replace_bits() is available, it is not
well documented, and only reports errors at the run time, which
will not be helpful to catch possible overflow errors due to
incorrect parameter types used.
FIELD_MODIFY(REG_FIELD_C, ®, c) is the wrapper to the code below.
reg &= ~REG_FIELD_C;
reg |= FIELD_PREP(REG_FIELD_C, c);
Yury: trim commit message, align backslashes.
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
Signed-off-by: Yury Norov <yury.norov@gmail.com>
| -rw-r--r-- | include/linux/bitfield.h | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h index 63928f173223..6d9a53db54b6 100644 --- a/include/linux/bitfield.h +++ b/include/linux/bitfield.h @@ -8,6 +8,7 @@ #define _LINUX_BITFIELD_H #include <linux/build_bug.h> +#include <linux/typecheck.h> #include <asm/byteorder.h> /* @@ -38,8 +39,7 @@ * FIELD_PREP(REG_FIELD_D, 0x40); * * Modify: - * reg &= ~REG_FIELD_C; - * reg |= FIELD_PREP(REG_FIELD_C, c); + * FIELD_MODIFY(REG_FIELD_C, ®, c); */ #define __bf_shf(x) (__builtin_ffsll(x) - 1) @@ -156,6 +156,23 @@ (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 + * + * 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) \ + ({ \ + 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") __field_overflow(void); extern void __compiletime_error("bad bitfield mask") |
