1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
24117b021SAkinobu Mita #ifndef _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
34117b021SAkinobu Mita #define _ASM_GENERIC_BITOPS_NON_ATOMIC_H_
44117b021SAkinobu Mita 
54117b021SAkinobu Mita #include <asm/types.h>
64117b021SAkinobu Mita 
74117b021SAkinobu Mita /**
84117b021SAkinobu Mita  * __set_bit - Set a bit in memory
94117b021SAkinobu Mita  * @nr: the bit to set
104117b021SAkinobu Mita  * @addr: the address to start counting from
114117b021SAkinobu Mita  *
124117b021SAkinobu Mita  * Unlike set_bit(), this function is non-atomic and may be reordered.
134117b021SAkinobu Mita  * If it's called on the same region of memory simultaneously, the effect
144117b021SAkinobu Mita  * may be that only one operation succeeds.
154117b021SAkinobu Mita  */
164117b021SAkinobu Mita static inline void __set_bit(int nr, volatile unsigned long *addr)
174117b021SAkinobu Mita {
18d05be13bSJiri Slaby 	unsigned long mask = BIT_MASK(nr);
19d05be13bSJiri Slaby 	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
204117b021SAkinobu Mita 
214117b021SAkinobu Mita 	*p  |= mask;
224117b021SAkinobu Mita }
234117b021SAkinobu Mita 
244117b021SAkinobu Mita static inline void __clear_bit(int nr, volatile unsigned long *addr)
254117b021SAkinobu Mita {
26d05be13bSJiri Slaby 	unsigned long mask = BIT_MASK(nr);
27d05be13bSJiri Slaby 	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
284117b021SAkinobu Mita 
294117b021SAkinobu Mita 	*p &= ~mask;
304117b021SAkinobu Mita }
314117b021SAkinobu Mita 
324117b021SAkinobu Mita /**
334117b021SAkinobu Mita  * __change_bit - Toggle a bit in memory
344117b021SAkinobu Mita  * @nr: the bit to change
354117b021SAkinobu Mita  * @addr: the address to start counting from
364117b021SAkinobu Mita  *
374117b021SAkinobu Mita  * Unlike change_bit(), this function is non-atomic and may be reordered.
384117b021SAkinobu Mita  * If it's called on the same region of memory simultaneously, the effect
394117b021SAkinobu Mita  * may be that only one operation succeeds.
404117b021SAkinobu Mita  */
414117b021SAkinobu Mita static inline void __change_bit(int nr, volatile unsigned long *addr)
424117b021SAkinobu Mita {
43d05be13bSJiri Slaby 	unsigned long mask = BIT_MASK(nr);
44d05be13bSJiri Slaby 	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
454117b021SAkinobu Mita 
464117b021SAkinobu Mita 	*p ^= mask;
474117b021SAkinobu Mita }
484117b021SAkinobu Mita 
494117b021SAkinobu Mita /**
504117b021SAkinobu Mita  * __test_and_set_bit - Set a bit and return its old value
514117b021SAkinobu Mita  * @nr: Bit to set
524117b021SAkinobu Mita  * @addr: Address to count from
534117b021SAkinobu Mita  *
544117b021SAkinobu Mita  * This operation is non-atomic and can be reordered.
554117b021SAkinobu Mita  * If two examples of this operation race, one can appear to succeed
564117b021SAkinobu Mita  * but actually fail.  You must protect multiple accesses with a lock.
574117b021SAkinobu Mita  */
584117b021SAkinobu Mita static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
594117b021SAkinobu Mita {
60d05be13bSJiri Slaby 	unsigned long mask = BIT_MASK(nr);
61d05be13bSJiri Slaby 	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
624117b021SAkinobu Mita 	unsigned long old = *p;
634117b021SAkinobu Mita 
644117b021SAkinobu Mita 	*p = old | mask;
654117b021SAkinobu Mita 	return (old & mask) != 0;
664117b021SAkinobu Mita }
674117b021SAkinobu Mita 
684117b021SAkinobu Mita /**
694117b021SAkinobu Mita  * __test_and_clear_bit - Clear a bit and return its old value
704117b021SAkinobu Mita  * @nr: Bit to clear
714117b021SAkinobu Mita  * @addr: Address to count from
724117b021SAkinobu Mita  *
734117b021SAkinobu Mita  * This operation is non-atomic and can be reordered.
744117b021SAkinobu Mita  * If two examples of this operation race, one can appear to succeed
754117b021SAkinobu Mita  * but actually fail.  You must protect multiple accesses with a lock.
764117b021SAkinobu Mita  */
774117b021SAkinobu Mita static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
784117b021SAkinobu Mita {
79d05be13bSJiri Slaby 	unsigned long mask = BIT_MASK(nr);
80d05be13bSJiri Slaby 	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
814117b021SAkinobu Mita 	unsigned long old = *p;
824117b021SAkinobu Mita 
834117b021SAkinobu Mita 	*p = old & ~mask;
844117b021SAkinobu Mita 	return (old & mask) != 0;
854117b021SAkinobu Mita }
864117b021SAkinobu Mita 
874117b021SAkinobu Mita /* WARNING: non atomic and it can be reordered! */
884117b021SAkinobu Mita static inline int __test_and_change_bit(int nr,
894117b021SAkinobu Mita 					    volatile unsigned long *addr)
904117b021SAkinobu Mita {
91d05be13bSJiri Slaby 	unsigned long mask = BIT_MASK(nr);
92d05be13bSJiri Slaby 	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
934117b021SAkinobu Mita 	unsigned long old = *p;
944117b021SAkinobu Mita 
954117b021SAkinobu Mita 	*p = old ^ mask;
964117b021SAkinobu Mita 	return (old & mask) != 0;
974117b021SAkinobu Mita }
984117b021SAkinobu Mita 
994117b021SAkinobu Mita /**
1004117b021SAkinobu Mita  * test_bit - Determine whether a bit is set
1014117b021SAkinobu Mita  * @nr: bit number to test
1024117b021SAkinobu Mita  * @addr: Address to start counting from
1034117b021SAkinobu Mita  */
1044117b021SAkinobu Mita static inline int test_bit(int nr, const volatile unsigned long *addr)
1054117b021SAkinobu Mita {
106d05be13bSJiri Slaby 	return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
1074117b021SAkinobu Mita }
1084117b021SAkinobu Mita 
1094117b021SAkinobu Mita #endif /* _ASM_GENERIC_BITOPS_NON_ATOMIC_H_ */
110