[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