[PATCH 1/2] linux/log2.h: Add round{up,down}_pow_of_two64()

David Gow <[email protected]>
Newsgroups org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
From: David Gow <[email protected]>

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. There
are cases (most notably in the GPU buddy allocator) which always operate on
64-bit values (as a 32-bit host can still use a GPU which internally has
64-bit addresses).

Add a version of these which always operate on a 64-bit value. These have
the (unimaginative) names roundup_pow_of_two64() and
rounddown_pow_of_two64(), and otherwise work identically to their unsigned
long counterparts. They are a bit ugly, but better than everyone hardcoding
calls to ilog2() -- which does handle 64-bit values -- directly.

Signed-off-by: David Gow <[email protected]>
---

Hi all,

This series is basically a reworked and rebased version of
https://lore.kernel.org/all/[email protected]/

Most importantly, the drm_test_buddy_alloc_exceeds_max_order KUnit test
was failing in linux-next on 32-bit systems, which this series fixes.

In rebasing it, I decided to add these helper functions, rather than
having an open-coded round{up,down} implementation in the buddy allocator,
but if no-one thinks it's worth having these for (at the moment) just one
user, I'm not too worried either way.

Cheers,
-- David

---
 include/linux/log2.h | 57 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/include/linux/log2.h b/include/linux/log2.h
index e17ceb32e0c9..67446d5ce9a3 100644
--- a/include/linux/log2.h
+++ b/include/linux/log2.h
@@ -195,6 +195,63 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
 	__rounddown_pow_of_two(n)		\
  )
 
+/**
+ * __rounddown_pow_of_two64() - round a 64-bit value down to nearest power of two
+ * @n: value to round up
+ */
+static inline __attribute_const__
+u64 __rounddown_pow_of_two64(u64 n)
+{
+	return 1ULL << ilog2(n);
+}
+
+/**
+ * rounddown_pow_of_two64 - 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_two64(n)		\
+(						\
+	__builtin_constant_p(n) ? (		\
+		((n) == 1) ? 1ULL :		\
+		(1ULL << ilog2((n)))		\
+				   ) :		\
+	__rounddown_pow_of_two64(n)		\
+)
+
+
+/**
+ * __roundup_pow_of_two64() - round a 64-bit value up to nearest power of two
+ * @n: value to round up
+ */
+static inline __attribute_const__
+u64 __roundup_pow_of_two64(u64 n)
+{
+	return 1ULL << (ilog2(n - 1) + 1);
+}
+
+/**
+ * roundup_pow_of_two64 - 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_two64(n)			\
+(						\
+	__builtin_constant_p(n) ? (		\
+		((n) == 1) ? 1ULL :		\
+		(1ULL << (ilog2((n) - 1) + 1))	\
+				   ) :		\
+	__roundup_pow_of_two64(n)		\
+)
+
 static inline __attribute_const__
 int __order_base_2(unsigned long n)
 {
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.