mirror of
https://github.com/torvalds/linux.git
synced 2026-10-23 07:11:03 +02:00
bitfield: get rid of __MAKE_OP machinery
The __MAKE_OP machinery hides the fixed-width bitfield helper definitions from source searches and makes the end result highly obscured and largely uncontrolled. This follows earlier discussions about making these helpers easier to find: [1], [2]. Move the explicit helpers and their shared checks into linux/bitfield-fix-width.h in both the kernel and tools headers, and include it from bitfield.h to preserve existing users. The repeated overflow check is factored into __assert_field(), preserving the original condition and compile-time diagnostics. With GCC 15.2.0 and x86-64 defconfig plus the bitfield KUnit tests, the before/after kernel builds are binary identical. The __MAKE_OP generates the following 40 functions (including the direct ____MAKE_OP(u8,u8,,) invocation): u8_encode_bits() u8_replace_bits() u8p_replace_bits() u8_get_bits() le16_encode_bits() le16_replace_bits() [dead code] le16p_replace_bits() le16_get_bits() be16_encode_bits() be16_replace_bits() [dead code] be16p_replace_bits() [dead code] be16_get_bits() u16_encode_bits() u16_replace_bits() u16p_replace_bits() u16_get_bits() le32_encode_bits() le32_replace_bits() [dead code] le32p_replace_bits() le32_get_bits() be32_encode_bits() be32_replace_bits() [dead code] be32p_replace_bits() be32_get_bits() u32_encode_bits() u32_replace_bits() u32p_replace_bits() u32_get_bits() le64_encode_bits() le64_replace_bits() [dead code] le64p_replace_bits() [dead code] le64_get_bits() be64_encode_bits() be64_replace_bits() [dead code] be64p_replace_bits() [dead code] be64_get_bits() u64_encode_bits() u64_replace_bits() u64p_replace_bits() u64_get_bits() Functions marked with [dead code] have no in-tree callers and are removed by this change. Link: https://lore.kernel.org/all/20250214073402.0129e259@kernel.org/ [1] Link: https://lore.kernel.org/all/aeub59FBHbCy-KKP@yury/ [2] Assisted-by: OpenAI Codex Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> Acked-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Yury Norov <ynorov@nvidia.com>
This commit is contained in:
parent
93f51579e7
commit
1c88ceb09d
|
|
@ -4638,6 +4638,7 @@ BITMAP API
|
|||
M: Yury Norov <yury.norov@gmail.com>
|
||||
R: Rasmus Villemoes <linux@rasmusvillemoes.dk>
|
||||
S: Maintained
|
||||
F: include/linux/bitfield-fix-width.h
|
||||
F: include/linux/bitfield.h
|
||||
F: include/linux/bitmap-str.h
|
||||
F: include/linux/bitmap.h
|
||||
|
|
@ -4658,6 +4659,7 @@ F: lib/find_bit_benchmark.c
|
|||
F: lib/region_alloc_benchmark.c
|
||||
F: lib/test_bitmap.c
|
||||
F: lib/tests/cpumask_kunit.c
|
||||
F: tools/include/linux/bitfield-fix-width.h
|
||||
F: tools/include/linux/bitfield.h
|
||||
F: tools/include/linux/bitmap.h
|
||||
F: tools/include/linux/bits.h
|
||||
|
|
|
|||
235
include/linux/bitfield-fix-width.h
Normal file
235
include/linux/bitfield-fix-width.h
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _LINUX_BITFIELD_FIX_WIDTH_H
|
||||
#define _LINUX_BITFIELD_FIX_WIDTH_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
extern void __compiletime_error("value doesn't fit into mask")
|
||||
__field_overflow(void);
|
||||
|
||||
extern void __compiletime_error("bad bitfield mask")
|
||||
__bad_mask(void);
|
||||
|
||||
static __always_inline
|
||||
u64 field_multiplier(u64 field)
|
||||
{
|
||||
if ((field | (field - 1)) & ((field | (field - 1)) + 1))
|
||||
__bad_mask();
|
||||
return field & -field;
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u64 field_mask(u64 field)
|
||||
{
|
||||
return field / field_multiplier(field);
|
||||
}
|
||||
|
||||
#define field_max(field) ((typeof(field))field_mask(field))
|
||||
|
||||
#define __assert_field(v, field) \
|
||||
do { \
|
||||
if (__builtin_constant_p(v) && \
|
||||
((v) & ~field_mask(field))) \
|
||||
__field_overflow(); \
|
||||
} while (0)
|
||||
|
||||
static __always_inline __must_check
|
||||
__u8 u8_encode_bits(u8 v, u8 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__u8 u8_replace_bits(__u8 old, u8 val, u8 field)
|
||||
{
|
||||
return (old & ~field) | u8_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u8p_replace_bits(__u8 *p, u8 val, u8 field)
|
||||
{
|
||||
*p = (*p & ~field) | u8_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u8 u8_get_bits(__u8 v, u8 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__le16 le16_encode_bits(u16 v, u16 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_le16((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void le16p_replace_bits(__le16 *p, u16 val, u16 field)
|
||||
{
|
||||
*p = (*p & ~cpu_to_le16(field)) | le16_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u16 le16_get_bits(__le16 v, u16 field)
|
||||
{
|
||||
return (le16_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__be16 be16_encode_bits(u16 v, u16 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_be16((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u16 be16_get_bits(__be16 v, u16 field)
|
||||
{
|
||||
return (be16_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__u16 u16_encode_bits(u16 v, u16 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__u16 u16_replace_bits(__u16 old, u16 val, u16 field)
|
||||
{
|
||||
return (old & ~field) | u16_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u16p_replace_bits(__u16 *p, u16 val, u16 field)
|
||||
{
|
||||
*p = (*p & ~field) | u16_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u16 u16_get_bits(__u16 v, u16 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__le32 le32_encode_bits(u32 v, u32 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_le32((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void le32p_replace_bits(__le32 *p, u32 val, u32 field)
|
||||
{
|
||||
*p = (*p & ~cpu_to_le32(field)) | le32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u32 le32_get_bits(__le32 v, u32 field)
|
||||
{
|
||||
return (le32_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__be32 be32_encode_bits(u32 v, u32 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_be32((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void be32p_replace_bits(__be32 *p, u32 val, u32 field)
|
||||
{
|
||||
*p = (*p & ~cpu_to_be32(field)) | be32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u32 be32_get_bits(__be32 v, u32 field)
|
||||
{
|
||||
return (be32_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__u32 u32_encode_bits(u32 v, u32 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__u32 u32_replace_bits(__u32 old, u32 val, u32 field)
|
||||
{
|
||||
return (old & ~field) | u32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u32p_replace_bits(__u32 *p, u32 val, u32 field)
|
||||
{
|
||||
*p = (*p & ~field) | u32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u32 u32_get_bits(__u32 v, u32 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__le64 le64_encode_bits(u64 v, u64 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_le64((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u64 le64_get_bits(__le64 v, u64 field)
|
||||
{
|
||||
return (le64_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__be64 be64_encode_bits(u64 v, u64 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_be64((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u64 be64_get_bits(__be64 v, u64 field)
|
||||
{
|
||||
return (be64_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__u64 u64_encode_bits(u64 v, u64 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
__u64 u64_replace_bits(__u64 old, u64 val, u64 field)
|
||||
{
|
||||
return (old & ~field) | u64_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u64p_replace_bits(__u64 *p, u64 val, u64 field)
|
||||
{
|
||||
*p = (*p & ~field) | u64_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
u64 u64_get_bits(__u64 v, u64 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_BITFIELD_FIX_WIDTH_H */
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
#include <linux/build_bug.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/typecheck.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/bitfield-fix-width.h>
|
||||
|
||||
/*
|
||||
* Bitfield access macros
|
||||
|
|
@ -211,53 +211,6 @@
|
|||
*(_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")
|
||||
__bad_mask(void);
|
||||
static __always_inline u64 field_multiplier(u64 field)
|
||||
{
|
||||
if ((field | (field - 1)) & ((field | (field - 1)) + 1))
|
||||
__bad_mask();
|
||||
return field & -field;
|
||||
}
|
||||
static __always_inline u64 field_mask(u64 field)
|
||||
{
|
||||
return field / field_multiplier(field);
|
||||
}
|
||||
#define field_max(field) ((typeof(field))field_mask(field))
|
||||
#define ____MAKE_OP(type,base,to,from) \
|
||||
static __always_inline __##type __must_check type##_encode_bits(base v, base field) \
|
||||
{ \
|
||||
if (__builtin_constant_p(v) && (v & ~field_mask(field))) \
|
||||
__field_overflow(); \
|
||||
return to((v & field_mask(field)) * field_multiplier(field)); \
|
||||
} \
|
||||
static __always_inline __##type __must_check type##_replace_bits(__##type old, \
|
||||
base val, base field) \
|
||||
{ \
|
||||
return (old & ~to(field)) | type##_encode_bits(val, field); \
|
||||
} \
|
||||
static __always_inline void type##p_replace_bits(__##type *p, \
|
||||
base val, base field) \
|
||||
{ \
|
||||
*p = (*p & ~to(field)) | type##_encode_bits(val, field); \
|
||||
} \
|
||||
static __always_inline base __must_check type##_get_bits(__##type v, base field) \
|
||||
{ \
|
||||
return (from(v) & field)/field_multiplier(field); \
|
||||
}
|
||||
#define __MAKE_OP(size) \
|
||||
____MAKE_OP(le##size,u##size,cpu_to_le##size,le##size##_to_cpu) \
|
||||
____MAKE_OP(be##size,u##size,cpu_to_be##size,be##size##_to_cpu) \
|
||||
____MAKE_OP(u##size,u##size,,)
|
||||
____MAKE_OP(u8,u8,,)
|
||||
__MAKE_OP(16)
|
||||
__MAKE_OP(32)
|
||||
__MAKE_OP(64)
|
||||
#undef __MAKE_OP
|
||||
#undef ____MAKE_OP
|
||||
|
||||
#define __field_prep(mask, val) \
|
||||
({ \
|
||||
auto __mask = (mask); \
|
||||
|
|
|
|||
236
tools/include/linux/bitfield-fix-width.h
Normal file
236
tools/include/linux/bitfield-fix-width.h
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _LINUX_BITFIELD_FIX_WIDTH_H
|
||||
#define _LINUX_BITFIELD_FIX_WIDTH_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
extern void __compiletime_error("value doesn't fit into mask")
|
||||
__field_overflow(void);
|
||||
|
||||
extern void __compiletime_error("bad bitfield mask")
|
||||
__bad_mask(void);
|
||||
|
||||
static __always_inline
|
||||
u64 field_multiplier(u64 field)
|
||||
{
|
||||
if ((field | (field - 1)) & ((field | (field - 1)) + 1))
|
||||
__bad_mask();
|
||||
return field & -field;
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u64 field_mask(u64 field)
|
||||
{
|
||||
return field / field_multiplier(field);
|
||||
}
|
||||
|
||||
#define field_max(field) ((typeof(field))field_mask(field))
|
||||
|
||||
#define __assert_field(v, field) \
|
||||
do { \
|
||||
if (__builtin_constant_p(v) && \
|
||||
((v) & ~field_mask(field))) \
|
||||
__field_overflow(); \
|
||||
} while (0)
|
||||
|
||||
static __always_inline
|
||||
__u8 u8_encode_bits(u8 v, u8 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__u8 u8_replace_bits(__u8 old, u8 val, u8 field)
|
||||
{
|
||||
return (old & ~field) | u8_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u8p_replace_bits(__u8 *p, u8 val, u8 field)
|
||||
{
|
||||
*p = (*p & ~field) | u8_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u8 u8_get_bits(__u8 v, u8 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__le16 le16_encode_bits(u16 v, u16 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_le16((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void le16p_replace_bits(__le16 *p, u16 val, u16 field)
|
||||
{
|
||||
*p = (*p & ~cpu_to_le16(field)) | le16_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u16 le16_get_bits(__le16 v, u16 field)
|
||||
{
|
||||
return (le16_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__be16 be16_encode_bits(u16 v, u16 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_be16((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u16 be16_get_bits(__be16 v, u16 field)
|
||||
{
|
||||
return (be16_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__u16 u16_encode_bits(u16 v, u16 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__u16 u16_replace_bits(__u16 old, u16 val, u16 field)
|
||||
{
|
||||
return (old & ~field) | u16_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u16p_replace_bits(__u16 *p, u16 val, u16 field)
|
||||
{
|
||||
*p = (*p & ~field) | u16_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u16 u16_get_bits(__u16 v, u16 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__le32 le32_encode_bits(u32 v, u32 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_le32((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void le32p_replace_bits(__le32 *p, u32 val, u32 field)
|
||||
{
|
||||
*p = (*p & ~cpu_to_le32(field)) | le32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u32 le32_get_bits(__le32 v, u32 field)
|
||||
{
|
||||
return (le32_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__be32 be32_encode_bits(u32 v, u32 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_be32((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void be32p_replace_bits(__be32 *p, u32 val, u32 field)
|
||||
{
|
||||
*p = (*p & ~cpu_to_be32(field)) | be32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u32 be32_get_bits(__be32 v, u32 field)
|
||||
{
|
||||
return (be32_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__u32 u32_encode_bits(u32 v, u32 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__u32 u32_replace_bits(__u32 old, u32 val, u32 field)
|
||||
{
|
||||
return (old & ~field) | u32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u32p_replace_bits(__u32 *p, u32 val, u32 field)
|
||||
{
|
||||
*p = (*p & ~field) | u32_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u32 u32_get_bits(__u32 v, u32 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__le64 le64_encode_bits(u64 v, u64 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_le64((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u64 le64_get_bits(__le64 v, u64 field)
|
||||
{
|
||||
return (le64_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__be64 be64_encode_bits(u64 v, u64 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return cpu_to_be64((v & field_mask(field)) * field_multiplier(field));
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u64 be64_get_bits(__be64 v, u64 field)
|
||||
{
|
||||
return (be64_to_cpu(v) & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__u64 u64_encode_bits(u64 v, u64 field)
|
||||
{
|
||||
__assert_field(v, field);
|
||||
return (v & field_mask(field)) * field_multiplier(field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
__u64 u64_replace_bits(__u64 old, u64 val, u64 field)
|
||||
{
|
||||
return (old & ~field) | u64_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void u64p_replace_bits(__u64 *p, u64 val, u64 field)
|
||||
{
|
||||
*p = (*p & ~field) | u64_encode_bits(val, field);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
u64 u64_get_bits(__u64 v, u64 field)
|
||||
{
|
||||
return (v & field) / field_multiplier(field);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_BITFIELD_FIX_WIDTH_H */
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include <linux/build_bug.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/bitfield-fix-width.h>
|
||||
|
||||
/*
|
||||
* Bitfield access macros
|
||||
|
|
@ -127,51 +127,4 @@
|
|||
(typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
|
||||
})
|
||||
|
||||
extern void __compiletime_error("value doesn't fit into mask")
|
||||
__field_overflow(void);
|
||||
extern void __compiletime_error("bad bitfield mask")
|
||||
__bad_mask(void);
|
||||
static __always_inline u64 field_multiplier(u64 field)
|
||||
{
|
||||
if ((field | (field - 1)) & ((field | (field - 1)) + 1))
|
||||
__bad_mask();
|
||||
return field & -field;
|
||||
}
|
||||
static __always_inline u64 field_mask(u64 field)
|
||||
{
|
||||
return field / field_multiplier(field);
|
||||
}
|
||||
#define field_max(field) ((typeof(field))field_mask(field))
|
||||
#define ____MAKE_OP(type,base,to,from) \
|
||||
static __always_inline __##type type##_encode_bits(base v, base field) \
|
||||
{ \
|
||||
if (__builtin_constant_p(v) && (v & ~field_mask(field))) \
|
||||
__field_overflow(); \
|
||||
return to((v & field_mask(field)) * field_multiplier(field)); \
|
||||
} \
|
||||
static __always_inline __##type type##_replace_bits(__##type old, \
|
||||
base val, base field) \
|
||||
{ \
|
||||
return (old & ~to(field)) | type##_encode_bits(val, field); \
|
||||
} \
|
||||
static __always_inline void type##p_replace_bits(__##type *p, \
|
||||
base val, base field) \
|
||||
{ \
|
||||
*p = (*p & ~to(field)) | type##_encode_bits(val, field); \
|
||||
} \
|
||||
static __always_inline base type##_get_bits(__##type v, base field) \
|
||||
{ \
|
||||
return (from(v) & field)/field_multiplier(field); \
|
||||
}
|
||||
#define __MAKE_OP(size) \
|
||||
____MAKE_OP(le##size,u##size,cpu_to_le##size,le##size##_to_cpu) \
|
||||
____MAKE_OP(be##size,u##size,cpu_to_be##size,be##size##_to_cpu) \
|
||||
____MAKE_OP(u##size,u##size,,)
|
||||
____MAKE_OP(u8,u8,,)
|
||||
__MAKE_OP(16)
|
||||
__MAKE_OP(32)
|
||||
__MAKE_OP(64)
|
||||
#undef __MAKE_OP
|
||||
#undef ____MAKE_OP
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user