1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _ASM_GENERIC_BITOPS_LE_H_ 3 #define _ASM_GENERIC_BITOPS_LE_H_ 4 5 #include <asm-generic/bitops/find.h> 6 #include <asm/types.h> 7 #include <asm/byteorder.h> 8 #include <linux/swab.h> 9 10 #if defined(__LITTLE_ENDIAN) 11 12 #define BITOP_LE_SWIZZLE 0 13 14 static inline unsigned long find_next_zero_bit_le(const void *addr, 15 unsigned long size, unsigned long offset) 16 { 17 return find_next_zero_bit(addr, size, offset); 18 } 19 20 static inline unsigned long find_next_bit_le(const void *addr, 21 unsigned long size, unsigned long offset) 22 { 23 return find_next_bit(addr, size, offset); 24 } 25 26 static inline unsigned long find_first_zero_bit_le(const void *addr, 27 unsigned long size) 28 { 29 return find_first_zero_bit(addr, size); 30 } 31 32 #elif defined(__BIG_ENDIAN) 33 34 #define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7) 35 36 #ifndef find_next_zero_bit_le 37 static inline 38 unsigned long find_next_zero_bit_le(const void *addr, unsigned 39 long size, unsigned long offset) 40 { 41 if (small_const_nbits(size)) { 42 unsigned long val = *(const unsigned long *)addr; 43 44 if (unlikely(offset >= size)) 45 return size; 46 47 val = swab(val) | ~GENMASK(size - 1, offset); 48 return val == ~0UL ? size : ffz(val); 49 } 50 51 return _find_next_bit(addr, NULL, size, offset, ~0UL, 1); 52 } 53 #endif 54 55 #ifndef find_next_bit_le 56 static inline 57 unsigned long find_next_bit_le(const void *addr, unsigned 58 long size, unsigned long offset) 59 { 60 if (small_const_nbits(size)) { 61 unsigned long val = *(const unsigned long *)addr; 62 63 if (unlikely(offset >= size)) 64 return size; 65 66 val = swab(val) & GENMASK(size - 1, offset); 67 return val ? __ffs(val) : size; 68 } 69 70 return _find_next_bit(addr, NULL, size, offset, 0UL, 1); 71 } 72 #endif 73 74 #ifndef find_first_zero_bit_le 75 #define find_first_zero_bit_le(addr, size) \ 76 find_next_zero_bit_le((addr), (size), 0) 77 #endif 78 79 #else 80 #error "Please fix <asm/byteorder.h>" 81 #endif 82 83 static inline int test_bit_le(int nr, const void *addr) 84 { 85 return test_bit(nr ^ BITOP_LE_SWIZZLE, addr); 86 } 87 88 static inline void set_bit_le(int nr, void *addr) 89 { 90 set_bit(nr ^ BITOP_LE_SWIZZLE, addr); 91 } 92 93 static inline void clear_bit_le(int nr, void *addr) 94 { 95 clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); 96 } 97 98 static inline void __set_bit_le(int nr, void *addr) 99 { 100 __set_bit(nr ^ BITOP_LE_SWIZZLE, addr); 101 } 102 103 static inline void __clear_bit_le(int nr, void *addr) 104 { 105 __clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); 106 } 107 108 static inline int test_and_set_bit_le(int nr, void *addr) 109 { 110 return test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr); 111 } 112 113 static inline int test_and_clear_bit_le(int nr, void *addr) 114 { 115 return test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); 116 } 117 118 static inline int __test_and_set_bit_le(int nr, void *addr) 119 { 120 return __test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr); 121 } 122 123 static inline int __test_and_clear_bit_le(int nr, void *addr) 124 { 125 return __test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); 126 } 127 128 #endif /* _ASM_GENERIC_BITOPS_LE_H_ */ 129