On 09/03/2012 02:52 PM, Jim Quinlan wrote:
The "else clause" of most functions in bitops.h invoked
raw_local_irq_{save,restore}() and so had a dependency on irqflags.h. This
fix moves said code to bitops.c, removing the dependency.
Signed-off-by: Jim Quinlan <jim2101024@xxxxxxxxx>
This is much better I think.
Now only a few very minor things I would change...
---
arch/mips/include/asm/bitops.h | 114 +++++++------------------
arch/mips/include/asm/io.h | 1 +
arch/mips/lib/Makefile | 2 +-
arch/mips/lib/bitops.c | 180 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 214 insertions(+), 83 deletions(-)
create mode 100644 arch/mips/lib/bitops.c
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index 82ad35c..9fd0b1d 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -14,7 +14,6 @@
#endif
#include <linux/compiler.h>
-#include <linux/irqflags.h>
#include <linux/types.h>
#include <asm/barrier.h>
#include <asm/byteorder.h> /* sigh ... */
@@ -44,6 +43,24 @@
#define smp_mb__before_clear_bit() smp_mb__before_llsc()
#define smp_mb__after_clear_bit() smp_llsc_mb()
+
+/*
+ * These are the "slower" versions of the functions and are in bitops.c.
+ * These functions call raw_local_irq_{save,restore}().
+ */
+extern void atomic_set_bit(unsigned long nr, volatile unsigned long *addr);
+extern void atomic_clear_bit(unsigned long nr, volatile unsigned long *addr);
+extern void atomic_change_bit(unsigned long nr, volatile unsigned long *addr);
+extern int atomic_test_and_set_bit(unsigned long nr,
+ volatile unsigned long *addr);
+extern int atomic_test_and_set_bit_lock(unsigned long nr,
+ volatile unsigned long *addr);
+extern int atomic_test_and_clear_bit(unsigned long nr,
+ volatile unsigned long *addr);
+extern int atomic_test_and_change_bit(unsigned long nr,
+ volatile unsigned long *addr);
+
No 'extern' needed.
These shouldn't be directly called from user code. I would suggest
renaming the functions to something like:
__mips_set_bit();
[...]
diff --git a/arch/mips/lib/bitops.c b/arch/mips/lib/bitops.c
new file mode 100644
index 0000000..6562ab2
--- /dev/null
+++ b/arch/mips/lib/bitops.c
@@ -0,0 +1,180 @@
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1994-1997, 99, 2000, 06, 07 Ralf Baechle (ralf@xxxxxxxxxxxxxx)
+ * Copyright (c) 1999, 2000 Silicon Graphics, Inc.
+ */
+
+#include <linux/irqflags.h>
+
+#if _MIPS_SZLONG == 32
+#define SZLONG_LOG 5
+#define SZLONG_MASK 31UL
+#elif _MIPS_SZLONG == 64
+#define SZLONG_MASK 63UL
+#define SZLONG_LOG 6
+#endif
+
There has to be a cleaner way to do this... Perhaps:
#define SZLONG_LOG (ilog2(sizeof(unsigned long)) + 3)
#define SZLONG_MASK ((1 << SZLONG_LOG) - 1)
+
+/*
+ * atomic_set_bit - Atomically set a bit in memory. This is called by
+ * if set_bit() if it cannot find a faster solution.
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ */
+void atomic_set_bit(unsigned long nr, volatile unsigned long *addr)
+{
+ volatile unsigned long *a = addr;
+ unsigned short bit = nr & SZLONG_MASK;
just make bit type 'int'. In some cases forcing a narrower type than
necessary requires the compiler to emit extra code. I am not sure if it
would here, but why use a type other than int unless absolutely necessary?
+ unsigned long mask;
+ unsigned long flags;
+
+ a += nr >> SZLONG_LOG;
+ mask = 1UL << bit;
+ raw_local_irq_save(flags);
+ *a |= mask;
+ raw_local_irq_restore(flags);
+}
All these must be EXPORT_SYMBOL(), so the bitop intrinsics can be used
from modules.