diff options
Diffstat (limited to 'include/linux/bitfield.h')
-rw-r--r-- | include/linux/bitfield.h | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h index 1030651f8309..cf2588d81148 100644 --- a/include/linux/bitfield.h +++ b/include/linux/bitfield.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #define _LINUX_BITFIELD_H | 16 | #define _LINUX_BITFIELD_H |
17 | 17 | ||
18 | #include <linux/build_bug.h> | 18 | #include <linux/build_bug.h> |
19 | #include <asm/byteorder.h> | ||
19 | 20 | ||
20 | /* | 21 | /* |
21 | * Bitfield access macros | 22 | * Bitfield access macros |
@@ -103,4 +104,49 @@ | |||
103 | (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \ | 104 | (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \ |
104 | }) | 105 | }) |
105 | 106 | ||
107 | extern void __compiletime_warning("value doesn't fit into mask") | ||
108 | __field_overflow(void); | ||
109 | extern void __compiletime_error("bad bitfield mask") | ||
110 | __bad_mask(void); | ||
111 | static __always_inline u64 field_multiplier(u64 field) | ||
112 | { | ||
113 | if ((field | (field - 1)) & ((field | (field - 1)) + 1)) | ||
114 | __bad_mask(); | ||
115 | return field & -field; | ||
116 | } | ||
117 | static __always_inline u64 field_mask(u64 field) | ||
118 | { | ||
119 | return field / field_multiplier(field); | ||
120 | } | ||
121 | #define ____MAKE_OP(type,base,to,from) \ | ||
122 | static __always_inline __##type type##_encode_bits(base v, base field) \ | ||
123 | { \ | ||
124 | if (__builtin_constant_p(v) && (v & ~field_multiplier(field))) \ | ||
125 | __field_overflow(); \ | ||
126 | return to((v & field_mask(field)) * field_multiplier(field)); \ | ||
127 | } \ | ||
128 | static __always_inline __##type type##_replace_bits(__##type old, \ | ||
129 | base val, base field) \ | ||
130 | { \ | ||
131 | return (old & ~to(field)) | type##_encode_bits(val, field); \ | ||
132 | } \ | ||
133 | static __always_inline void type##p_replace_bits(__##type *p, \ | ||
134 | base val, base field) \ | ||
135 | { \ | ||
136 | *p = (*p & ~to(field)) | type##_encode_bits(val, field); \ | ||
137 | } \ | ||
138 | static __always_inline base type##_get_bits(__##type v, base field) \ | ||
139 | { \ | ||
140 | return (from(v) & field)/field_multiplier(field); \ | ||
141 | } | ||
142 | #define __MAKE_OP(size) \ | ||
143 | ____MAKE_OP(le##size,u##size,cpu_to_le##size,le##size##_to_cpu) \ | ||
144 | ____MAKE_OP(be##size,u##size,cpu_to_be##size,be##size##_to_cpu) \ | ||
145 | ____MAKE_OP(u##size,u##size,,) | ||
146 | __MAKE_OP(16) | ||
147 | __MAKE_OP(32) | ||
148 | __MAKE_OP(64) | ||
149 | #undef __MAKE_OP | ||
150 | #undef ____MAKE_OP | ||
151 | |||
106 | #endif | 152 | #endif |