diff mbox series

[U-Boot,RFC,v1] mips: add atomic operations

Message ID 20180907082404.31983-1-judge.packham@gmail.com
State Superseded
Delegated to: Daniel Schwierzeck
Headers show
Series [U-Boot,RFC,v1] mips: add atomic operations | expand

Commit Message

Chris Packham Sept. 7, 2018, 8:24 a.m. UTC
Add mips version of atomic.h and basic atomic operations. These aren't
the optimised versions from the Linux kernel, just basic stubs that
satisfy users that need something to define atomic_inc() etc.

Signed-off-by: Chris Packham <judge.packham@gmail.com>

---
At $dayjob we have a mips target that we want to run UBIFS on. UBIFS
requires atomic.h. This is my naive attempt to supply enough of atomic.h
to satisfy UBIFS.

It's no coincidence that this looks like the arm version. I am
wondering if it's worth a asm-generic version leaving architectures that
actually need true atomic operations able to define them.

 arch/mips/include/asm/atomic.h | 151 +++++++++++++++++++++++++++++++++
 1 file changed, 151 insertions(+)
 create mode 100644 arch/mips/include/asm/atomic.h

Comments

Stefan Roese Sept. 7, 2018, 10:24 a.m. UTC | #1
Hi Chris,

(added Daniel)

On 07.09.2018 10:24, Chris Packham wrote:
> Add mips version of atomic.h and basic atomic operations. These aren't
> the optimised versions from the Linux kernel, just basic stubs that
> satisfy users that need something to define atomic_inc() etc.
> 
> Signed-off-by: Chris Packham <judge.packham@gmail.com>
> 
> ---
> At $dayjob we have a mips target that we want to run UBIFS on. UBIFS
> requires atomic.h. This is my naive attempt to supply enough of atomic.h
> to satisfy UBIFS.
> 
> It's no coincidence that this looks like the arm version. I am
> wondering if it's worth a asm-generic version leaving architectures that
> actually need true atomic operations able to define them.

I did a pretty similar job and copied the files from xtensa a few
weeks ago:

https://patchwork.ozlabs.org/patch/958286/

It would be better of course, to have some generic version of this
file. But frankly, I don't have the time right now for this.

Thanks,
Stefan
  
>   arch/mips/include/asm/atomic.h | 151 +++++++++++++++++++++++++++++++++
>   1 file changed, 151 insertions(+)
>   create mode 100644 arch/mips/include/asm/atomic.h
> 
> diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
> new file mode 100644
> index 000000000000..3ab5684fdef4
> --- /dev/null
> +++ b/arch/mips/include/asm/atomic.h
> @@ -0,0 +1,151 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +#ifndef _ASM_ATOMIC_H
> +#define _ASM_ATOMIC_H
> +
> +#include <asm/system.h>
> +
> +typedef struct { volatile int counter; } atomic_t;
> +#if BITS_PER_LONG == 32
> +typedef struct { volatile long long counter; } atomic64_t;
> +#else /* BIT_PER_LONG == 32 */
> +typedef struct { volatile long counter; } atomic64_t;
> +#endif
> +
> +#define ATOMIC_INIT(i)	  { (i) }
> +
> +#define atomic_read(v)	((v)->counter)
> +#define atomic_set(v, i)	(((v)->counter) = (i))
> +#define atomic64_read(v)	atomic_read(v)
> +#define atomic64_set(v, i)	atomic_set(v, i)
> +
> +static inline void atomic_add(int i, volatile atomic_t *v)
> +{
> +	unsigned long flags = 0;
> +
> +	local_irq_save(flags);
> +	v->counter += i;
> +	local_irq_restore(flags);
> +}
> +
> +static inline void atomic_sub(int i, volatile atomic_t *v)
> +{
> +	unsigned long flags = 0;
> +
> +	local_irq_save(flags);
> +	v->counter -= i;
> +	local_irq_restore(flags);
> +}
> +
> +static inline void atomic_inc(volatile atomic_t *v)
> +{
> +	unsigned long flags = 0;
> +
> +	local_irq_save(flags);
> +	v->counter += 1;
> +	local_irq_restore(flags);
> +}
> +
> +static inline void atomic_dec(volatile atomic_t *v)
> +{
> +	unsigned long flags = 0;
> +
> +	local_irq_save(flags);
> +	v->counter -= 1;
> +	local_irq_restore(flags);
> +}
> +
> +static inline int atomic_dec_and_test(volatile atomic_t *v)
> +{
> +	unsigned long flags = 0;
> +	int val;
> +
> +	local_irq_save(flags);
> +	val = v->counter;
> +	v->counter = val -= 1;
> +	local_irq_restore(flags);
> +
> +	return val == 0;
> +}
> +
> +static inline int atomic_add_negative(int i, volatile atomic_t *v)
> +{
> +	unsigned long flags = 0;
> +	int val;
> +
> +	local_irq_save(flags);
> +	val = v->counter;
> +	v->counter = val += i;
> +	local_irq_restore(flags);
> +
> +	return val < 0;
> +}
> +
> +static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
> +{
> +	unsigned long flags = 0;
> +
> +	local_irq_save(flags);
> +	*addr &= ~mask;
> +	local_irq_restore(flags);
> +}
> +
> +#if BITS_PER_LONG == 32
> +
> +static inline void atomic64_add(long long i, volatile atomic64_t *v)
> +{
> +	unsigned long flags = 0;
> +
> +	local_irq_save(flags);
> +	v->counter += i;
> +	local_irq_restore(flags);
> +}
> +
> +static inline void atomic64_sub(long long i, volatile atomic64_t *v)
> +{
> +	unsigned long flags = 0;
> +
> +	local_irq_save(flags);
> +	v->counter -= i;
> +	local_irq_restore(flags);
> +}
> +
> +#else /* BIT_PER_LONG == 32 */
> +
> +static inline void atomic64_add(long i, volatile atomic64_t *v)
> +{
> +	unsigned long flags = 0;
> +
> +	local_irq_save(flags);
> +	v->counter += i;
> +	local_irq_restore(flags);
> +}
> +
> +static inline void atomic64_sub(long i, volatile atomic64_t *v)
> +{
> +	unsigned long flags = 0;
> +
> +	local_irq_save(flags);
> +	v->counter -= i;
> +	local_irq_restore(flags);
> +}
> +#endif /* BIT_PER_LONG == 32 */
> +
> +static inline void atomic64_inc(volatile atomic64_t *v)
> +{
> +	unsigned long flags = 0;
> +
> +	local_irq_save(flags);
> +	v->counter += 1;
> +	local_irq_restore(flags);
> +}
> +
> +static inline void atomic64_dec(volatile atomic64_t *v)
> +{
> +	unsigned long flags = 0;
> +
> +	local_irq_save(flags);
> +	v->counter -= 1;
> +	local_irq_restore(flags);
> +}
> +
> +#endif
>
Chris Packham Sept. 7, 2018, 12:08 p.m. UTC | #2
On Fri, 7 Sep 2018, 10:24 PM Stefan, <sr@denx.de> wrote:

> Hi Chris,
>
> (added Daniel)
>
> On 07.09.2018 10:24, Chris Packham wrote:
> > Add mips version of atomic.h and basic atomic operations. These aren't
> > the optimised versions from the Linux kernel, just basic stubs that
> > satisfy users that need something to define atomic_inc() etc.
> >
> > Signed-off-by: Chris Packham <judge.packham@gmail.com>
> >
> > ---
> > At $dayjob we have a mips target that we want to run UBIFS on. UBIFS
> > requires atomic.h. This is my naive attempt to supply enough of atomic.h
> > to satisfy UBIFS.
> >
> > It's no coincidence that this looks like the arm version. I am
> > wondering if it's worth a asm-generic version leaving architectures that
> > actually need true atomic operations able to define them.
>
> I did a pretty similar job and copied the files from xtensa a few
> weeks ago:
>
> https://patchwork.ozlabs.org/patch/958286/


Weird coincidence. I figured noone had needed ubifs on mips since the need
for atomic.h has been there for a while.

I'm more than happy for your version to go in since it's part of a bigger
series. The only thing missing is 64 bit support (our platform happens to
be mips64) but i don't think ubifs cares.


> It would be better of course, to have some generic version of this
> file. But frankly, I don't have the time right now for this.
>

Given that the arm, xtensa and now mips are so similar it's probably worth
it. I'll see if i can find some cycles to spend on it.
diff mbox series

Patch

diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
new file mode 100644
index 000000000000..3ab5684fdef4
--- /dev/null
+++ b/arch/mips/include/asm/atomic.h
@@ -0,0 +1,151 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+#ifndef _ASM_ATOMIC_H
+#define _ASM_ATOMIC_H
+
+#include <asm/system.h>
+
+typedef struct { volatile int counter; } atomic_t;
+#if BITS_PER_LONG == 32
+typedef struct { volatile long long counter; } atomic64_t;
+#else /* BIT_PER_LONG == 32 */
+typedef struct { volatile long counter; } atomic64_t;
+#endif
+
+#define ATOMIC_INIT(i)	  { (i) }
+
+#define atomic_read(v)	((v)->counter)
+#define atomic_set(v, i)	(((v)->counter) = (i))
+#define atomic64_read(v)	atomic_read(v)
+#define atomic64_set(v, i)	atomic_set(v, i)
+
+static inline void atomic_add(int i, volatile atomic_t *v)
+{
+	unsigned long flags = 0;
+
+	local_irq_save(flags);
+	v->counter += i;
+	local_irq_restore(flags);
+}
+
+static inline void atomic_sub(int i, volatile atomic_t *v)
+{
+	unsigned long flags = 0;
+
+	local_irq_save(flags);
+	v->counter -= i;
+	local_irq_restore(flags);
+}
+
+static inline void atomic_inc(volatile atomic_t *v)
+{
+	unsigned long flags = 0;
+
+	local_irq_save(flags);
+	v->counter += 1;
+	local_irq_restore(flags);
+}
+
+static inline void atomic_dec(volatile atomic_t *v)
+{
+	unsigned long flags = 0;
+
+	local_irq_save(flags);
+	v->counter -= 1;
+	local_irq_restore(flags);
+}
+
+static inline int atomic_dec_and_test(volatile atomic_t *v)
+{
+	unsigned long flags = 0;
+	int val;
+
+	local_irq_save(flags);
+	val = v->counter;
+	v->counter = val -= 1;
+	local_irq_restore(flags);
+
+	return val == 0;
+}
+
+static inline int atomic_add_negative(int i, volatile atomic_t *v)
+{
+	unsigned long flags = 0;
+	int val;
+
+	local_irq_save(flags);
+	val = v->counter;
+	v->counter = val += i;
+	local_irq_restore(flags);
+
+	return val < 0;
+}
+
+static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
+{
+	unsigned long flags = 0;
+
+	local_irq_save(flags);
+	*addr &= ~mask;
+	local_irq_restore(flags);
+}
+
+#if BITS_PER_LONG == 32
+
+static inline void atomic64_add(long long i, volatile atomic64_t *v)
+{
+	unsigned long flags = 0;
+
+	local_irq_save(flags);
+	v->counter += i;
+	local_irq_restore(flags);
+}
+
+static inline void atomic64_sub(long long i, volatile atomic64_t *v)
+{
+	unsigned long flags = 0;
+
+	local_irq_save(flags);
+	v->counter -= i;
+	local_irq_restore(flags);
+}
+
+#else /* BIT_PER_LONG == 32 */
+
+static inline void atomic64_add(long i, volatile atomic64_t *v)
+{
+	unsigned long flags = 0;
+
+	local_irq_save(flags);
+	v->counter += i;
+	local_irq_restore(flags);
+}
+
+static inline void atomic64_sub(long i, volatile atomic64_t *v)
+{
+	unsigned long flags = 0;
+
+	local_irq_save(flags);
+	v->counter -= i;
+	local_irq_restore(flags);
+}
+#endif /* BIT_PER_LONG == 32 */
+
+static inline void atomic64_inc(volatile atomic64_t *v)
+{
+	unsigned long flags = 0;
+
+	local_irq_save(flags);
+	v->counter += 1;
+	local_irq_restore(flags);
+}
+
+static inline void atomic64_dec(volatile atomic64_t *v)
+{
+	unsigned long flags = 0;
+
+	local_irq_save(flags);
+	v->counter -= 1;
+	local_irq_restore(flags);
+}
+
+#endif