150825Smdodd/* SPDX-License-Identifier: GPL-2.0 */
250825Smdodd#ifndef __ASM_GENERIC_GETORDER_H
350825Smdodd#define __ASM_GENERIC_GETORDER_H
450825Smdodd
550825Smdodd#ifndef __ASSEMBLY__
650825Smdodd
750825Smdodd#include <linux/compiler.h>
850825Smdodd#include <linux/log2.h>
950825Smdodd
1050825Smdodd/**
1150825Smdodd * get_order - Determine the allocation order of a memory size
1250825Smdodd * @size: The size for which to get the order
1350825Smdodd *
1450825Smdodd * Determine the allocation order of a particular sized block of memory.  This
1550825Smdodd * is on a logarithmic scale, where:
1650825Smdodd *
1750825Smdodd *	0 -> 2^0 * PAGE_SIZE and below
1850825Smdodd *	1 -> 2^1 * PAGE_SIZE to 2^0 * PAGE_SIZE + 1
1950825Smdodd *	2 -> 2^2 * PAGE_SIZE to 2^1 * PAGE_SIZE + 1
2050825Smdodd *	3 -> 2^3 * PAGE_SIZE to 2^2 * PAGE_SIZE + 1
2150825Smdodd *	4 -> 2^4 * PAGE_SIZE to 2^3 * PAGE_SIZE + 1
2250825Smdodd *	...
2350825Smdodd *
2450825Smdodd * The order returned is used to find the smallest allocation granule required
2550825Smdodd * to hold an object of the specified size.
2650825Smdodd *
2750825Smdodd * The result is undefined if the size is 0.
28119418Sobrien */
29119418Sobrienstatic __always_inline __attribute_const__ int get_order(unsigned long size)
30119418Sobrien{
3150825Smdodd	if (__builtin_constant_p(size)) {
3250825Smdodd		if (!size)
3350825Smdodd			return BITS_PER_LONG - PAGE_SHIFT;
3450825Smdodd
3550825Smdodd		if (size < (1UL << PAGE_SHIFT))
3650825Smdodd			return 0;
3750825Smdodd
3850825Smdodd		return ilog2((size) - 1) - PAGE_SHIFT + 1;
3950825Smdodd	}
4050825Smdodd
4150825Smdodd	size--;
4250825Smdodd	size >>= PAGE_SHIFT;
43114216Skan#if BITS_PER_LONG == 32
4450825Smdodd	return fls(size);
4550825Smdodd#else
4650825Smdodd	return fls64(size);
4750825Smdodd#endif
4850825Smdodd}
4950825Smdodd
5050825Smdodd#endif	/* __ASSEMBLY__ */
5150825Smdodd
5250825Smdodd#endif	/* __ASM_GENERIC_GETORDER_H */
5350825Smdodd