Skip to content

Commit a256ae2

Browse files
Luo JieYuryNorov
authored andcommitted
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, &reg, 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>
1 parent 89a44a8 commit a256ae2

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

include/linux/bitfield.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define _LINUX_BITFIELD_H
99

1010
#include <linux/build_bug.h>
11+
#include <linux/typecheck.h>
1112
#include <asm/byteorder.h>
1213

1314
/*
@@ -38,8 +39,7 @@
3839
* FIELD_PREP(REG_FIELD_D, 0x40);
3940
*
4041
* Modify:
41-
* reg &= ~REG_FIELD_C;
42-
* reg |= FIELD_PREP(REG_FIELD_C, c);
42+
* FIELD_MODIFY(REG_FIELD_C, &reg, c);
4343
*/
4444

4545
#define __bf_shf(x) (__builtin_ffsll(x) - 1)
@@ -156,6 +156,23 @@
156156
(typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
157157
})
158158

159+
/**
160+
* FIELD_MODIFY() - modify a bitfield element
161+
* @_mask: shifted mask defining the field's length and position
162+
* @_reg_p: pointer to the memory that should be updated
163+
* @_val: value to store in the bitfield
164+
*
165+
* FIELD_MODIFY() modifies the set of bits in @_reg_p specified by @_mask,
166+
* by replacing them with the bitfield value passed in as @_val.
167+
*/
168+
#define FIELD_MODIFY(_mask, _reg_p, _val) \
169+
({ \
170+
typecheck_pointer(_reg_p); \
171+
__BF_FIELD_CHECK(_mask, *(_reg_p), _val, "FIELD_MODIFY: "); \
172+
*(_reg_p) &= ~(_mask); \
173+
*(_reg_p) |= (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)); \
174+
})
175+
159176
extern void __compiletime_error("value doesn't fit into mask")
160177
__field_overflow(void);
161178
extern void __compiletime_error("bad bitfield mask")

0 commit comments

Comments
 (0)