162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
362306a36Sopenharmony_ci#define _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/bits.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci/**
862306a36Sopenharmony_ci * ___set_bit - Set a bit in memory
962306a36Sopenharmony_ci * @nr: the bit to set
1062306a36Sopenharmony_ci * @addr: the address to start counting from
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * Unlike set_bit(), this function is non-atomic and may be reordered.
1362306a36Sopenharmony_ci * If it's called on the same region of memory simultaneously, the effect
1462306a36Sopenharmony_ci * may be that only one operation succeeds.
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_cistatic __always_inline void
1762306a36Sopenharmony_ci___set_bit(unsigned long nr, volatile unsigned long *addr)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	unsigned long mask = BIT_MASK(nr);
2062306a36Sopenharmony_ci	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	*p  |= mask;
2362306a36Sopenharmony_ci}
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic __always_inline void
2662306a36Sopenharmony_ci___clear_bit(unsigned long nr, volatile unsigned long *addr)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	unsigned long mask = BIT_MASK(nr);
2962306a36Sopenharmony_ci	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	*p &= ~mask;
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/**
3562306a36Sopenharmony_ci * ___change_bit - Toggle a bit in memory
3662306a36Sopenharmony_ci * @nr: the bit to change
3762306a36Sopenharmony_ci * @addr: the address to start counting from
3862306a36Sopenharmony_ci *
3962306a36Sopenharmony_ci * Unlike change_bit(), this function is non-atomic and may be reordered.
4062306a36Sopenharmony_ci * If it's called on the same region of memory simultaneously, the effect
4162306a36Sopenharmony_ci * may be that only one operation succeeds.
4262306a36Sopenharmony_ci */
4362306a36Sopenharmony_cistatic __always_inline void
4462306a36Sopenharmony_ci___change_bit(unsigned long nr, volatile unsigned long *addr)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	unsigned long mask = BIT_MASK(nr);
4762306a36Sopenharmony_ci	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	*p ^= mask;
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/**
5362306a36Sopenharmony_ci * ___test_and_set_bit - Set a bit and return its old value
5462306a36Sopenharmony_ci * @nr: Bit to set
5562306a36Sopenharmony_ci * @addr: Address to count from
5662306a36Sopenharmony_ci *
5762306a36Sopenharmony_ci * This operation is non-atomic and can be reordered.
5862306a36Sopenharmony_ci * If two examples of this operation race, one can appear to succeed
5962306a36Sopenharmony_ci * but actually fail.  You must protect multiple accesses with a lock.
6062306a36Sopenharmony_ci */
6162306a36Sopenharmony_cistatic __always_inline bool
6262306a36Sopenharmony_ci___test_and_set_bit(unsigned long nr, volatile unsigned long *addr)
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	unsigned long mask = BIT_MASK(nr);
6562306a36Sopenharmony_ci	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
6662306a36Sopenharmony_ci	unsigned long old = *p;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	*p = old | mask;
6962306a36Sopenharmony_ci	return (old & mask) != 0;
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/**
7362306a36Sopenharmony_ci * ___test_and_clear_bit - Clear a bit and return its old value
7462306a36Sopenharmony_ci * @nr: Bit to clear
7562306a36Sopenharmony_ci * @addr: Address to count from
7662306a36Sopenharmony_ci *
7762306a36Sopenharmony_ci * This operation is non-atomic and can be reordered.
7862306a36Sopenharmony_ci * If two examples of this operation race, one can appear to succeed
7962306a36Sopenharmony_ci * but actually fail.  You must protect multiple accesses with a lock.
8062306a36Sopenharmony_ci */
8162306a36Sopenharmony_cistatic __always_inline bool
8262306a36Sopenharmony_ci___test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	unsigned long mask = BIT_MASK(nr);
8562306a36Sopenharmony_ci	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
8662306a36Sopenharmony_ci	unsigned long old = *p;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	*p = old & ~mask;
8962306a36Sopenharmony_ci	return (old & mask) != 0;
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci/* WARNING: non atomic and it can be reordered! */
9362306a36Sopenharmony_cistatic __always_inline bool
9462306a36Sopenharmony_ci___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	unsigned long mask = BIT_MASK(nr);
9762306a36Sopenharmony_ci	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
9862306a36Sopenharmony_ci	unsigned long old = *p;
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	*p = old ^ mask;
10162306a36Sopenharmony_ci	return (old & mask) != 0;
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci/**
10562306a36Sopenharmony_ci * _test_bit - Determine whether a bit is set
10662306a36Sopenharmony_ci * @nr: bit number to test
10762306a36Sopenharmony_ci * @addr: Address to start counting from
10862306a36Sopenharmony_ci */
10962306a36Sopenharmony_cistatic __always_inline bool
11062306a36Sopenharmony_ci_test_bit(unsigned long nr, const volatile unsigned long *addr)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci#endif /* _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ */
116