is_power_of_2() does not work properly for e.g. u64 in 32-bit builds. Choose an unsigned long long version if the argument is bigger than unsigned long. Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> Cc: Christian König <christian.koenig@xxxxxxx> Cc: David Gow <davidgow@xxxxxxxxxx> Link: https://lore.kernel.org/r/20230329065532.2122295-2-davidgow@xxxxxxxxxx Signed-off-by: Jani Nikula <jani.nikula@xxxxxxxxx> --- include/linux/log2.h | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/include/linux/log2.h b/include/linux/log2.h index 19e773116ae3..4027d1eecd7f 100644 --- a/include/linux/log2.h +++ b/include/linux/log2.h @@ -35,6 +35,18 @@ int __ilog2_u64(u64 n) #define __IS_POWER_OF_2(n) ((n) != 0 && (((n) & ((n) - 1)) == 0)) +static inline __attribute__((const)) +bool __is_power_of_2_ull(unsigned long long n) +{ + return __IS_POWER_OF_2(n); +} + +static inline __attribute__((const)) +bool __is_power_of_2(unsigned long n) +{ + return __IS_POWER_OF_2(n); +} + /** * is_power_of_2() - check if a value is a power of two * @n: the value to check @@ -43,11 +55,10 @@ int __ilog2_u64(u64 n) * *not* considered a power of two. * Return: true if @n is a power of 2, otherwise false. */ -static inline __attribute__((const)) -bool is_power_of_2(unsigned long n) -{ - return __IS_POWER_OF_2(n); -} +#define is_power_of_2(n) \ + __builtin_choose_expr(sizeof(n) > sizeof(unsigned long), \ + __is_power_of_2_ull(n), \ + __is_power_of_2(n)) /** * __roundup_pow_of_two() - round up to nearest power of two -- 2.39.2