From: David Gow <david@davidgow.net>
To: Jim Cromie <jim.cromie@gmail.com>,
"Maciej W . Rozycki" <macro@orcam.me.uk>,
Andrew Morton <akpm@linux-foundation.org>,
Matthew Auld <matthew.auld@intel.com>,
Arun Pravin <arunpravin.paneerselvam@amd.com>,
Joel Fernandes <joelagnelf@nvidia.com>,
David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
Chris Mason <mason@kernel.org>, David Sterba <dsterba@suse.com>
Cc: David Gow <david@davidgow.net>,
dri-devel@lists.freedesktop.org, linux-btrfs@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH v2 1/3] linux/log2.h: Add 64-bit safe variants of power-of-two functions
Date: Sun, 30 Aug 2026 18:33:15 +0800 [thread overview]
Message-ID: <20260830103321.2042968-1-david@davidgow.net> (raw)
The existing roundup_pow_of_two() and rounddown_pow_of_two() functions work
on values of type unsigned long, which is 32-bit on 32-bit systems.
Equally, is_power_of_2() operates on an unsigned long.
There are several instances where 64-bit safe versions of these (which
operate on a 64-bit value regardless of sizeof(long)) are required. Most
particularly, some hardware (especially GPUs) have 64-bit address spaces,
and some formats (such as filesystems) use 64-bit offsets. Some of these
(such as i915 and btrfs) have already implemented their own 64-bit
is_power_of_2() helpers.
Add a version of these which always operate on a 64-bit value. These have
the (unimaginative) names:
- is_power_of_2_u64()
- roundup_pow_of_two_u64(), and
- rounddown_pow_of_two_u64()
and otherwise work identically to their unsigned long counterparts.
To avoid conflicts, the i915 implementation is also removed here. The btrfs
one (which has a different name) is replaced in a separate patch.
Signed-off-by: David Gow <david@davidgow.net>
---
This patch adds u64 helpers, and the following two use them. And v2 also
has the i915 change to remove the conflicting implementation.
So I'm not sure who best wants to take these. Ultimately it's an include/linux
change, but it touches i915, patch 2 touches GPU/DRM, and patch 3 btrfs.
Personally, I'm keen to get patch 2 in, as it fixes a real issue, so if taking
1 and 2 via DRM makes more sense, that's fine by me.
Changes since v1:
https://lore.kernel.org/all/20260821091918.1902032-1-david@ingeniumdigital.com/
- Include is_power_of_2_u64() as well, and remove the i915 version
(Thanks, Matthew)
- Use _u64 as a suffix for the 64-bit versions, not just 64
(This is a much nicer name, and matches what everone else was doing)
- Fix some comment typos.
- Add a third patch which removes a similar is_power_of_two_u64() helper
from btrfs.
---
drivers/gpu/drm/i915/i915_utils.h | 5 ---
include/linux/log2.h | 73 +++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
index ecc20e0528f4..1cec51984d8c 100644
--- a/drivers/gpu/drm/i915/i915_utils.h
+++ b/drivers/gpu/drm/i915/i915_utils.h
@@ -75,11 +75,6 @@ struct drm_i915_private;
__idx; \
})
-static inline bool is_power_of_2_u64(u64 n)
-{
- return (n != 0 && ((n & (n - 1)) == 0));
-}
-
void add_taint_for_CI(struct drm_i915_private *i915, unsigned int taint);
static inline void __add_taint_for_CI(unsigned int taint)
{
diff --git a/include/linux/log2.h b/include/linux/log2.h
index e17ceb32e0c9..fc44e59f5732 100644
--- a/include/linux/log2.h
+++ b/include/linux/log2.h
@@ -47,6 +47,22 @@ bool is_power_of_2(unsigned long n)
return n - 1 < (n ^ (n - 1));
}
+/**
+ * is_power_of_2_u64() - check if a 64-bit value is a power of two
+ * @n: the value to check
+ *
+ * Determine whether some value is a power of two, where zero is
+ * *not* considered a power of two. Unlike is_power_of_2, this version
+ * always operates on 64-bit values, even on 32-bit architectures where
+ * long is 32-bit.
+ * Return: true if @n is a power of 2, otherwise false.
+ */
+static __always_inline __attribute_const__
+bool is_power_of_2_u64(u64 n)
+{
+ return n - 1 < (n ^ (n - 1));
+}
+
/**
* __roundup_pow_of_two() - round up to nearest power of two
* @n: value to round up
@@ -195,6 +211,63 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
__rounddown_pow_of_two(n) \
)
+/**
+ * __rounddown_pow_of_two_64() - round a 64-bit value down to nearest power of two
+ * @n: value to round down
+ */
+static inline __attribute_const__
+u64 __rounddown_pow_of_two_u64(u64 n)
+{
+ return 1ULL << ilog2(n);
+}
+
+/**
+ * rounddown_pow_of_two_u64 - round a 64-bit value down to nearest power of two
+ * @n: parameter
+ *
+ * round the given value down to the nearest power of two
+ * - this always operates on 64-bit values, even on 32-bit systems
+ * - the result is undefined when n == 0
+ * - this can be used to initialise global variables from constant data
+ */
+#define rounddown_pow_of_two_u64(n) \
+( \
+ __builtin_constant_p(n) ? ( \
+ ((n) == 1) ? 1ULL : \
+ (1ULL << ilog2((n))) \
+ ) : \
+ __rounddown_pow_of_two_u64(n) \
+)
+
+
+/**
+ * __roundup_pow_of_two_u64() - round a 64-bit value up to nearest power of two
+ * @n: value to round up
+ */
+static inline __attribute_const__
+u64 __roundup_pow_of_two_u64(u64 n)
+{
+ return 1ULL << (ilog2(n - 1) + 1);
+}
+
+/**
+ * roundup_pow_of_two_u64 - round a 64-bit value up to nearest power of two
+ * @n: parameter
+ *
+ * round the given value up to the nearest power of two
+ * - this always operates on 64-bit values, even on 32-bit systems
+ * - the result is undefined when n == 0
+ * - this can be used to initialise global variables from constant data
+ */
+#define roundup_pow_of_two_u64(n) \
+( \
+ __builtin_constant_p(n) ? ( \
+ ((n) == 1) ? 1ULL : \
+ (1ULL << (ilog2((n) - 1) + 1)) \
+ ) : \
+ __roundup_pow_of_two_u64(n) \
+)
+
static inline __attribute_const__
int __order_base_2(unsigned long n)
{
--
2.55.0
next reply other threads:[~2026-08-30 10:38 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-30 10:33 David Gow [this message]
2026-08-30 10:33 ` [PATCH v2 2/3] drm_buddy: fix power-of-2 rounding errs David Gow
2026-08-30 10:33 ` [PATCH v2 3/3] fs:btrfs: Use the new global is_power_of_2_u64() helper David Gow
2026-08-30 11:43 ` [PATCH v2 1/3] linux/log2.h: Add 64-bit safe variants of power-of-two functions David Laight
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=20260830103321.2042968-1-david@davidgow.net \
--to=david@davidgow.net \
--cc=airlied@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=arunpravin.paneerselvam@amd.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=dsterba@suse.com \
--cc=jim.cromie@gmail.com \
--cc=joelagnelf@nvidia.com \
--cc=linux-btrfs@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=macro@orcam.me.uk \
--cc=mason@kernel.org \
--cc=matthew.auld@intel.com \
--cc=simona@ffwll.ch \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®