From: Christian Marangi <ansuelsmth@gmail.com>
To: Mark Kettenis <kettenis@openbsd.org>,
Tom Rini <trini@konsulko.com>, Lukasz Majewski <lukma@denx.de>,
Sean Anderson <seanga2@gmail.com>,
Casey Connolly <casey.connolly@linaro.org>,
Neil Armstrong <neil.armstrong@linaro.org>,
Sumit Garg <sumit.garg@kernel.org>,
Dario Binacchi <dario.binacchi@amarulasolutions.com>,
Michael Trimarchi <michael@amarulasolutions.com>,
Frieder Schrempf <frieder.schrempf@kontron.de>,
Simon Glass <sjg@chromium.org>,
Christian Marangi <ansuelsmth@gmail.com>,
u-boot@lists.denx.de, u-boot-qcom@groups.io
Subject: [PATCH v4 4/5] linux/bitfield.h: sync <linux/bitfield.h> from Linux 6.15
Date: Sat, 7 Jun 2025 23:11:20 +0200 [thread overview]
Message-ID: <20250607211133.2005-5-ansuelsmth@gmail.com> (raw)
In-Reply-To: <20250607211133.2005-1-ansuelsmth@gmail.com>
Sync bitfield.h header with Linux 6.15 version. Mainly is to permit the
introduction of FIELD_PREP_CONST. The bug.h header changed to
build_bug.h doesn't cause any regression as we also ship split header
similar to how it's done with in Linux.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
include/linux/bitfield.h | 103 ++++++++++++++++++++++++++++-----------
1 file changed, 75 insertions(+), 28 deletions(-)
diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h
index 7ad02f8cbb9..63928f17322 100644
--- a/include/linux/bitfield.h
+++ b/include/linux/bitfield.h
@@ -1,21 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2014 Felix Fietkau <nbd@nbd.name>
* Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#ifndef _LINUX_BITFIELD_H
#define _LINUX_BITFIELD_H
-#include <linux/bug.h>
+#include <linux/build_bug.h>
#include <asm/byteorder.h>
/*
@@ -27,6 +19,9 @@
*
* Example:
*
+ * #include <linux/bitfield.h>
+ * #include <linux/bits.h>
+ *
* #define REG_FIELD_A GENMASK(6, 0)
* #define REG_FIELD_B BIT(7)
* #define REG_FIELD_C GENMASK(15, 8)
@@ -49,20 +44,51 @@
#define __bf_shf(x) (__builtin_ffsll(x) - 1)
+#define __scalar_type_to_unsigned_cases(type) \
+ unsigned type: (unsigned type)0, \
+ signed type: (unsigned type)0
+
+#define __unsigned_scalar_typeof(x) typeof( \
+ _Generic((x), \
+ char: (unsigned char)0, \
+ __scalar_type_to_unsigned_cases(char), \
+ __scalar_type_to_unsigned_cases(short), \
+ __scalar_type_to_unsigned_cases(int), \
+ __scalar_type_to_unsigned_cases(long), \
+ __scalar_type_to_unsigned_cases(long long), \
+ default: (x)))
+
+#define __bf_cast_unsigned(type, x) ((__unsigned_scalar_typeof(type))(x))
+
#define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx) \
({ \
BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask), \
_pfx "mask is not constant"); \
- BUILD_BUG_ON_MSG(!(_mask), _pfx "mask is zero"); \
+ BUILD_BUG_ON_MSG((_mask) == 0, _pfx "mask is zero"); \
BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \
- ~((_mask) >> __bf_shf(_mask)) & (_val) : 0, \
+ ~((_mask) >> __bf_shf(_mask)) & \
+ (0 + (_val)) : 0, \
_pfx "value too large for the field"); \
- BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull, \
+ BUILD_BUG_ON_MSG(__bf_cast_unsigned(_mask, _mask) > \
+ __bf_cast_unsigned(_reg, ~0ull), \
_pfx "type of reg too small for mask"); \
__BUILD_BUG_ON_NOT_POWER_OF_2((_mask) + \
(1ULL << __bf_shf(_mask))); \
})
+/**
+ * FIELD_MAX() - produce the maximum value representable by a field
+ * @_mask: shifted mask defining the field's length and position
+ *
+ * FIELD_MAX() returns the maximum value that can be held in the field
+ * specified by @_mask.
+ */
+#define FIELD_MAX(_mask) \
+ ({ \
+ __BF_FIELD_CHECK(_mask, 0ULL, 0ULL, "FIELD_MAX: "); \
+ (typeof(_mask))((_mask) >> __bf_shf(_mask)); \
+ })
+
/**
* FIELD_FIT() - check if value fits in the field
* @_mask: shifted mask defining the field's length and position
@@ -72,7 +98,7 @@
*/
#define FIELD_FIT(_mask, _val) \
({ \
- __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_FIT: "); \
+ __BF_FIELD_CHECK(_mask, 0ULL, 0ULL, "FIELD_FIT: "); \
!((((typeof(_mask))_val) << __bf_shf(_mask)) & ~(_mask)); \
})
@@ -90,10 +116,36 @@
((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \
})
+#define __BF_CHECK_POW2(n) BUILD_BUG_ON_ZERO(((n) & ((n) - 1)) != 0)
+
+/**
+ * FIELD_PREP_CONST() - prepare a constant bitfield element
+ * @_mask: shifted mask defining the field's length and position
+ * @_val: value to put in the field
+ *
+ * FIELD_PREP_CONST() masks and shifts up the value. The result should
+ * be combined with other fields of the bitfield using logical OR.
+ *
+ * Unlike FIELD_PREP() this is a constant expression and can therefore
+ * be used in initializers. Error checking is less comfortable for this
+ * version, and non-constant masks cannot be used.
+ */
+#define FIELD_PREP_CONST(_mask, _val) \
+ ( \
+ /* mask must be non-zero */ \
+ BUILD_BUG_ON_ZERO((_mask) == 0) + \
+ /* check if value fits */ \
+ BUILD_BUG_ON_ZERO(~((_mask) >> __bf_shf(_mask)) & (_val)) + \
+ /* check if mask is contiguous */ \
+ __BF_CHECK_POW2((_mask) + (1ULL << __bf_shf(_mask))) + \
+ /* and create the value */ \
+ (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)) \
+ )
+
/**
* FIELD_GET() - extract a bitfield element
* @_mask: shifted mask defining the field's length and position
- * @_reg: 32bit value of entire bitfield
+ * @_reg: value of entire bitfield
*
* FIELD_GET() extracts the field specified by @_mask from the
* bitfield passed in as @_reg by masking and shifting it down.
@@ -108,20 +160,18 @@ 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 ____MAKE_OP(type, base, to, from) \
+#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))) \
@@ -133,26 +183,23 @@ static __always_inline __##type type##_replace_bits(__##type old, \
{ \
return (old & ~to(field)) | type##_encode_bits(val, field); \
} \
-static __always_inline void type##p_replace_bits(__##type * p, \
+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); \
+ 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(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
--
2.48.1
next prev parent reply other threads:[~2025-06-07 21:12 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-07 21:11 [PATCH v4 0/5] linux/bitfield.h: sync <linux/bitfield.h> from Linux 6.15 + winbond Christian Marangi
2025-06-07 21:11 ` [PATCH v4 1/5] clk: imx: add missing linux/bug.h header for WARN Christian Marangi
2025-06-07 21:11 ` [PATCH v4 2/5] iommu: qcom-smmu: add missing linux/bug.h header for WARN_ON Christian Marangi
2025-06-07 21:11 ` [PATCH v4 3/5] arm: apple: rtkit: add missing header linux/bug.h and linux/bitops.h Christian Marangi
2025-06-07 21:11 ` Christian Marangi [this message]
2025-06-07 21:11 ` [PATCH v4 5/5] mtd: spinand: winbond: add Winbond W25N04KV flash support Christian Marangi
2025-06-14 17:44 ` [PATCH v4 0/5] linux/bitfield.h: sync <linux/bitfield.h> from Linux 6.15 + winbond Tom Rini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250607211133.2005-5-ansuelsmth@gmail.com \
--to=ansuelsmth@gmail.com \
--cc=casey.connolly@linaro.org \
--cc=dario.binacchi@amarulasolutions.com \
--cc=frieder.schrempf@kontron.de \
--cc=kettenis@openbsd.org \
--cc=lukma@denx.de \
--cc=michael@amarulasolutions.com \
--cc=neil.armstrong@linaro.org \
--cc=seanga2@gmail.com \
--cc=sjg@chromium.org \
--cc=sumit.garg@kernel.org \
--cc=trini@konsulko.com \
--cc=u-boot-qcom@groups.io \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.