|
| 1 | +From c24bf48d70b8c02f3c7b61e03ca3cbf43779b3d2 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Luo Jie <quic_luoj@quicinc.com> |
| 3 | +Date: Thu, 17 Apr 2025 18:47:08 +0800 |
| 4 | +Subject: [PATCH 502/512] bitfield: Add FIELD_MODIFY() helper |
| 5 | + |
| 6 | +Add a helper for replacing the contents of bitfield in memory |
| 7 | +with the specified value. |
| 8 | + |
| 9 | +Even though a helper xxx_replace_bits() is available, it is not |
| 10 | +well documented, and only reports errors at the run time, which |
| 11 | +will not be helpful to catch possible overflow errors due to |
| 12 | +incorrect parameter types used. |
| 13 | + |
| 14 | +FIELD_MODIFY(REG_FIELD_C, ®, c) is the wrapper to the code below. |
| 15 | + |
| 16 | + reg &= ~REG_FIELD_C; |
| 17 | + reg |= FIELD_PREP(REG_FIELD_C, c); |
| 18 | + |
| 19 | +Yury: trim commit message, align backslashes. |
| 20 | + |
| 21 | +Signed-off-by: Luo Jie <quic_luoj@quicinc.com> |
| 22 | +Signed-off-by: Yury Norov <yury.norov@gmail.com> |
| 23 | +--- |
| 24 | + include/linux/bitfield.h | 21 +++++++++++++++++++-- |
| 25 | + 1 file changed, 19 insertions(+), 2 deletions(-) |
| 26 | + |
| 27 | +diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h |
| 28 | +index 63928f173223..6d9a53db54b6 100644 |
| 29 | +--- a/include/linux/bitfield.h |
| 30 | ++++ b/include/linux/bitfield.h |
| 31 | +@@ -8,6 +8,7 @@ |
| 32 | + #define _LINUX_BITFIELD_H |
| 33 | + |
| 34 | + #include <linux/build_bug.h> |
| 35 | ++#include <linux/typecheck.h> |
| 36 | + #include <asm/byteorder.h> |
| 37 | + |
| 38 | + /* |
| 39 | +@@ -38,8 +39,7 @@ |
| 40 | + * FIELD_PREP(REG_FIELD_D, 0x40); |
| 41 | + * |
| 42 | + * Modify: |
| 43 | +- * reg &= ~REG_FIELD_C; |
| 44 | +- * reg |= FIELD_PREP(REG_FIELD_C, c); |
| 45 | ++ * FIELD_MODIFY(REG_FIELD_C, ®, c); |
| 46 | + */ |
| 47 | + |
| 48 | + #define __bf_shf(x) (__builtin_ffsll(x) - 1) |
| 49 | +@@ -156,6 +156,23 @@ |
| 50 | + (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \ |
| 51 | + }) |
| 52 | + |
| 53 | ++/** |
| 54 | ++ * FIELD_MODIFY() - modify a bitfield element |
| 55 | ++ * @_mask: shifted mask defining the field's length and position |
| 56 | ++ * @_reg_p: pointer to the memory that should be updated |
| 57 | ++ * @_val: value to store in the bitfield |
| 58 | ++ * |
| 59 | ++ * FIELD_MODIFY() modifies the set of bits in @_reg_p specified by @_mask, |
| 60 | ++ * by replacing them with the bitfield value passed in as @_val. |
| 61 | ++ */ |
| 62 | ++#define FIELD_MODIFY(_mask, _reg_p, _val) \ |
| 63 | ++ ({ \ |
| 64 | ++ typecheck_pointer(_reg_p); \ |
| 65 | ++ __BF_FIELD_CHECK(_mask, *(_reg_p), _val, "FIELD_MODIFY: "); \ |
| 66 | ++ *(_reg_p) &= ~(_mask); \ |
| 67 | ++ *(_reg_p) |= (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)); \ |
| 68 | ++ }) |
| 69 | ++ |
| 70 | + extern void __compiletime_error("value doesn't fit into mask") |
| 71 | + __field_overflow(void); |
| 72 | + extern void __compiletime_error("bad bitfield mask") |
| 73 | +-- |
| 74 | +2.34.1 |
| 75 | + |
0 commit comments