|
@@ -302,3 +302,77 @@ static inline int bfchg_mem_test_and_change_bit(int nr,
|
|
|
#define test_and_change_bit(nr, vaddr) bchg_mem_test_and_change_bit(nr, vaddr)
|
|
|
#else
|
|
|
#define test_and_change_bit(nr, vaddr) (__builtin_constant_p(nr) ? \
|
|
|
+ bchg_mem_test_and_change_bit(nr, vaddr) : \
|
|
|
+ bfchg_mem_test_and_change_bit(nr, vaddr))
|
|
|
+#endif
|
|
|
+
|
|
|
+#define __test_and_change_bit(nr, vaddr) test_and_change_bit(nr, vaddr)
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * The true 68020 and more advanced processors support the "bfffo"
|
|
|
+ * instruction for finding bits. ColdFire and simple 68000 parts
|
|
|
+ * (including CPU32) do not support this. They simply use the generic
|
|
|
+ * functions.
|
|
|
+ */
|
|
|
+#if defined(CONFIG_CPU_HAS_NO_BITFIELDS)
|
|
|
+#include <asm-generic/bitops/find.h>
|
|
|
+#include <asm-generic/bitops/ffz.h>
|
|
|
+#else
|
|
|
+
|
|
|
+static inline int find_first_zero_bit(const unsigned long *vaddr,
|
|
|
+ unsigned size)
|
|
|
+{
|
|
|
+ const unsigned long *p = vaddr;
|
|
|
+ int res = 32;
|
|
|
+ unsigned int words;
|
|
|
+ unsigned long num;
|
|
|
+
|
|
|
+ if (!size)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ words = (size + 31) >> 5;
|
|
|
+ while (!(num = ~*p++)) {
|
|
|
+ if (!--words)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
|
|
|
+ : "=d" (res) : "d" (num & -num));
|
|
|
+ res ^= 31;
|
|
|
+out:
|
|
|
+ res += ((long)p - (long)vaddr - 4) * 8;
|
|
|
+ return res < size ? res : size;
|
|
|
+}
|
|
|
+#define find_first_zero_bit find_first_zero_bit
|
|
|
+
|
|
|
+static inline int find_next_zero_bit(const unsigned long *vaddr, int size,
|
|
|
+ int offset)
|
|
|
+{
|
|
|
+ const unsigned long *p = vaddr + (offset >> 5);
|
|
|
+ int bit = offset & 31UL, res;
|
|
|
+
|
|
|
+ if (offset >= size)
|
|
|
+ return size;
|
|
|
+
|
|
|
+ if (bit) {
|
|
|
+ unsigned long num = ~*p++ & (~0UL << bit);
|
|
|
+ offset -= bit;
|
|
|
+
|
|
|
+ /* Look for zero in first longword */
|
|
|
+ __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
|
|
|
+ : "=d" (res) : "d" (num & -num));
|
|
|
+ if (res < 32) {
|
|
|
+ offset += res ^ 31;
|
|
|
+ return offset < size ? offset : size;
|
|
|
+ }
|
|
|
+ offset += 32;
|
|
|
+
|
|
|
+ if (offset >= size)
|
|
|
+ return size;
|
|
|
+ }
|
|
|
+ /* No zero yet, search remaining full bytes for a zero */
|
|
|
+ return offset + find_first_zero_bit(p, size - offset);
|
|
|
+}
|
|
|
+#define find_next_zero_bit find_next_zero_bit
|
|
|
+
|