162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * MSB0 numbered special bitops handling.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * The bits are numbered:
662306a36Sopenharmony_ci *   |0..............63|64............127|128...........191|192...........255|
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * The reason for this bit numbering is the fact that the hardware sets bits
962306a36Sopenharmony_ci * in a bitmap starting at bit 0 (MSB) and we don't want to scan the bitmap
1062306a36Sopenharmony_ci * from the 'wrong end'.
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/compiler.h>
1462306a36Sopenharmony_ci#include <linux/bitops.h>
1562306a36Sopenharmony_ci#include <linux/export.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ciunsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	const unsigned long *p = addr;
2062306a36Sopenharmony_ci	unsigned long result = 0;
2162306a36Sopenharmony_ci	unsigned long tmp;
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	while (size & ~(BITS_PER_LONG - 1)) {
2462306a36Sopenharmony_ci		if ((tmp = *(p++)))
2562306a36Sopenharmony_ci			goto found;
2662306a36Sopenharmony_ci		result += BITS_PER_LONG;
2762306a36Sopenharmony_ci		size -= BITS_PER_LONG;
2862306a36Sopenharmony_ci	}
2962306a36Sopenharmony_ci	if (!size)
3062306a36Sopenharmony_ci		return result;
3162306a36Sopenharmony_ci	tmp = (*p) & (~0UL << (BITS_PER_LONG - size));
3262306a36Sopenharmony_ci	if (!tmp)		/* Are any bits set? */
3362306a36Sopenharmony_ci		return result + size;	/* Nope. */
3462306a36Sopenharmony_cifound:
3562306a36Sopenharmony_ci	return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ciEXPORT_SYMBOL(find_first_bit_inv);
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ciunsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size,
4062306a36Sopenharmony_ci				unsigned long offset)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	const unsigned long *p = addr + (offset / BITS_PER_LONG);
4362306a36Sopenharmony_ci	unsigned long result = offset & ~(BITS_PER_LONG - 1);
4462306a36Sopenharmony_ci	unsigned long tmp;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	if (offset >= size)
4762306a36Sopenharmony_ci		return size;
4862306a36Sopenharmony_ci	size -= result;
4962306a36Sopenharmony_ci	offset %= BITS_PER_LONG;
5062306a36Sopenharmony_ci	if (offset) {
5162306a36Sopenharmony_ci		tmp = *(p++);
5262306a36Sopenharmony_ci		tmp &= (~0UL >> offset);
5362306a36Sopenharmony_ci		if (size < BITS_PER_LONG)
5462306a36Sopenharmony_ci			goto found_first;
5562306a36Sopenharmony_ci		if (tmp)
5662306a36Sopenharmony_ci			goto found_middle;
5762306a36Sopenharmony_ci		size -= BITS_PER_LONG;
5862306a36Sopenharmony_ci		result += BITS_PER_LONG;
5962306a36Sopenharmony_ci	}
6062306a36Sopenharmony_ci	while (size & ~(BITS_PER_LONG-1)) {
6162306a36Sopenharmony_ci		if ((tmp = *(p++)))
6262306a36Sopenharmony_ci			goto found_middle;
6362306a36Sopenharmony_ci		result += BITS_PER_LONG;
6462306a36Sopenharmony_ci		size -= BITS_PER_LONG;
6562306a36Sopenharmony_ci	}
6662306a36Sopenharmony_ci	if (!size)
6762306a36Sopenharmony_ci		return result;
6862306a36Sopenharmony_ci	tmp = *p;
6962306a36Sopenharmony_cifound_first:
7062306a36Sopenharmony_ci	tmp &= (~0UL << (BITS_PER_LONG - size));
7162306a36Sopenharmony_ci	if (!tmp)		/* Are any bits set? */
7262306a36Sopenharmony_ci		return result + size;	/* Nope. */
7362306a36Sopenharmony_cifound_middle:
7462306a36Sopenharmony_ci	return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ciEXPORT_SYMBOL(find_next_bit_inv);
77