2011-06-17 21:53:08

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 0/6] Merge Blackfin/SMP atomic.h support into asm-generic/atomic.h

I hate code in arch/blackfin/include/asm/. The more that exists in
include/asm-generic/, the happier I get.

This fixes up the atomic mask helpers, and then makes the asm-generic
version usable for SMP systems. Or at least Blackfin SMP; if other
peeps want in on the action, they can see what needs updating then.

The 2 Blackfin patches are just to show what's going on; I can merge
them through my tree like normal. But the asm-generic ones will have
to be picked up by Andrew.

These shouldn't specifically conflict with Arun's work, but it will
trigger a little fuzz hate. So I can wait for his stuff to get merged
before pushing mine through, and at this point treat the series as a
heads up.

Mike Frysinger (6):
asm-generic/atomic.h: simplify inc/dec test helpers
asm-generic/atomic.h: fix type used in atomic_clear_mask
asm-generic/atomic.h: add atomic_set_mask helper
asm-generic/atomic.h: allow SMP peeps to leverage this
Blackfin: SMP: punt unused atomic_test_mask helper
Blackfin: SMP: convert to common asm-generic/atomic.h

arch/blackfin/include/asm/atomic.h | 110 +++---------------------------------
include/asm-generic/atomic.h | 47 ++++++++++++++--
2 files changed, 51 insertions(+), 106 deletions(-)

--
1.7.5.3


2011-06-17 21:53:22

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 1/6] asm-generic/atomic.h: simplify inc/dec test helpers

We already declared inc/dec helpers, so we don't need to call the
atomic_{add,sub}_return funcs directly.

Signed-off-by: Mike Frysinger <[email protected]>
---
include/asm-generic/atomic.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
index e994197..5f62e28 100644
--- a/include/asm-generic/atomic.h
+++ b/include/asm-generic/atomic.h
@@ -117,8 +117,8 @@ static inline void atomic_dec(atomic_t *v)
#define atomic_inc_return(v) atomic_add_return(1, (v))

#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0)
-#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
-#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
+#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
+#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)

#define atomic_xchg(ptr, v) (xchg(&(ptr)->counter, (v)))
#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
--
1.7.5.3

2011-06-17 21:53:31

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 2/6] asm-generic/atomic.h: fix type used in atomic_clear_mask

The atomic helpers are supposed to take an atomic_t pointer, not a
random unsigned long pointer. So convert atomic_clear_mask over.

While we're here, also add some nice documentation to the func.

Signed-off-by: Mike Frysinger <[email protected]>
---
include/asm-generic/atomic.h | 11 +++++++++--
1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
index 5f62e28..28f5939 100644
--- a/include/asm-generic/atomic.h
+++ b/include/asm-generic/atomic.h
@@ -140,13 +140,20 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)

#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

-static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
+/**
+ * atomic_clear_mask - Atomically clear bits in atomic variable
+ * @mask: Mask of the bits to be cleared
+ * @v: pointer of type atomic_t
+ *
+ * Atomically clears the bits set in @mask from @v
+ */
+static inline void atomic_clear_mask(unsigned long mask, atomic_t *v)
{
unsigned long flags;

mask = ~mask;
raw_local_irq_save(flags); /* Don't trace it in a irqsoff handler */
- *addr &= mask;
+ v->counter &= mask;
raw_local_irq_restore(flags);
}

--
1.7.5.3

2011-06-17 21:53:24

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 3/6] asm-generic/atomic.h: add atomic_set_mask helper

Since arches are expected to implement this guy, add a common version
for people the same way as atomic_clear_mask is handled.

Signed-off-by: Mike Frysinger <[email protected]>
---
include/asm-generic/atomic.h | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
index 28f5939..8275ecd 100644
--- a/include/asm-generic/atomic.h
+++ b/include/asm-generic/atomic.h
@@ -157,6 +157,22 @@ static inline void atomic_clear_mask(unsigned long mask, atomic_t *v)
raw_local_irq_restore(flags);
}

+/**
+ * atomic_set_mask - Atomically set bits in atomic variable
+ * @mask: Mask of the bits to be set
+ * @v: pointer of type atomic_t
+ *
+ * Atomically sets the bits set in @mask in @v
+ */
+static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
+{
+ unsigned long flags;
+
+ raw_local_irq_save(flags); /* Don't trace it in a irqsoff handler */
+ v->counter |= mask;
+ raw_local_irq_restore(flags);
+}
+
/* Assume that atomic operations are already serializing */
#define smp_mb__before_atomic_dec() barrier()
#define smp_mb__after_atomic_dec() barrier()
--
1.7.5.3

2011-06-17 21:53:25

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 4/6] asm-generic/atomic.h: allow SMP peeps to leverage this

Only a few core funcs need to be implemented for SMP systems, so allow
the arches to override them while getting the rest for free.

At least, this is enough to allow the Blackfin SMP port use things.

Signed-off-by: Mike Frysinger <[email protected]>
---
include/asm-generic/atomic.h | 16 +++++++++++++++-
1 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
index 8275ecd..297f1a8 100644
--- a/include/asm-generic/atomic.h
+++ b/include/asm-generic/atomic.h
@@ -14,7 +14,11 @@
#define __ASM_GENERIC_ATOMIC_H

#ifdef CONFIG_SMP
-#error not SMP safe
+/* Force people to define core atomics */
+# if !defined(atomic_add_return) || !defined(atomic_sub_return) || \
+ !defined(atomic_clear_mask) || !defined(atomic_set_mask)
+# error "SMP requires a little arch-specific magic"
+# endif
#endif

/*
@@ -32,7 +36,9 @@
*
* Atomically reads the value of @v.
*/
+#ifndef atomic_read
#define atomic_read(v) (*(volatile int *)&(v)->counter)
+#endif

/**
* atomic_set - set atomic variable
@@ -53,6 +59,7 @@
*
* Atomically adds @i to @v and returns the result
*/
+#ifndef atomic_add_return
static inline int atomic_add_return(int i, atomic_t *v)
{
unsigned long flags;
@@ -66,6 +73,7 @@ static inline int atomic_add_return(int i, atomic_t *v)

return temp;
}
+#endif

/**
* atomic_sub_return - subtract integer from atomic variable
@@ -74,6 +82,7 @@ static inline int atomic_add_return(int i, atomic_t *v)
*
* Atomically subtracts @i from @v and returns the result
*/
+#ifndef atomic_sub_return
static inline int atomic_sub_return(int i, atomic_t *v)
{
unsigned long flags;
@@ -87,6 +96,7 @@ static inline int atomic_sub_return(int i, atomic_t *v)

return temp;
}
+#endif

static inline int atomic_add_negative(int i, atomic_t *v)
{
@@ -147,6 +157,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
*
* Atomically clears the bits set in @mask from @v
*/
+#ifndef atomic_clear_mask
static inline void atomic_clear_mask(unsigned long mask, atomic_t *v)
{
unsigned long flags;
@@ -156,6 +167,7 @@ static inline void atomic_clear_mask(unsigned long mask, atomic_t *v)
v->counter &= mask;
raw_local_irq_restore(flags);
}
+#endif

/**
* atomic_set_mask - Atomically set bits in atomic variable
@@ -164,6 +176,7 @@ static inline void atomic_clear_mask(unsigned long mask, atomic_t *v)
*
* Atomically sets the bits set in @mask in @v
*/
+#ifndef atomic_set_mask
static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
{
unsigned long flags;
@@ -172,6 +185,7 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
v->counter |= mask;
raw_local_irq_restore(flags);
}
+#endif

/* Assume that atomic operations are already serializing */
#define smp_mb__before_atomic_dec() barrier()
--
1.7.5.3

2011-06-17 21:53:28

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 5/6] Blackfin: SMP: punt unused atomic_test_mask helper

No one uses this func, so just punt it.

Signed-off-by: Mike Frysinger <[email protected]>
---
arch/blackfin/include/asm/atomic.h | 5 -----
1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/arch/blackfin/include/asm/atomic.h b/arch/blackfin/include/asm/atomic.h
index e485089..c857579 100644
--- a/arch/blackfin/include/asm/atomic.h
+++ b/arch/blackfin/include/asm/atomic.h
@@ -76,11 +76,6 @@ static inline void atomic_set_mask(int mask, atomic_t *v)
__raw_atomic_set_asm(&v->counter, mask);
}

-static inline int atomic_test_mask(int mask, atomic_t *v)
-{
- return __raw_atomic_test_asm(&v->counter, mask);
-}
-
/* Atomic operations are already serializing */
#define smp_mb__before_atomic_dec() barrier()
#define smp_mb__after_atomic_dec() barrier()
--
1.7.5.3

2011-06-17 21:53:30

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 6/6] Blackfin: SMP: convert to common asm-generic/atomic.h

Now that common code supports SMP systems, switch our SMP atomic logic
over to it to avoid code duplication.

Signed-off-by: Mike Frysinger <[email protected]>
---
arch/blackfin/include/asm/atomic.h | 105 +++--------------------------------
1 files changed, 9 insertions(+), 96 deletions(-)

diff --git a/arch/blackfin/include/asm/atomic.h b/arch/blackfin/include/asm/atomic.h
index c857579..4d611eb 100644
--- a/arch/blackfin/include/asm/atomic.h
+++ b/arch/blackfin/include/asm/atomic.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2009 Analog Devices Inc.
+ * Copyright 2004-2011 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
@@ -7,115 +7,28 @@
#ifndef __ARCH_BLACKFIN_ATOMIC__
#define __ARCH_BLACKFIN_ATOMIC__

-#ifndef CONFIG_SMP
-# include <asm-generic/atomic.h>
-#else
+#ifdef CONFIG_SMP

-#include <linux/types.h>
-#include <asm/system.h> /* local_irq_XXX() */
-
-/*
- * Atomic operations that C can't guarantee us. Useful for
- * resource counting etc..
- */
-
-#define ATOMIC_INIT(i) { (i) }
-#define atomic_set(v, i) (((v)->counter) = i)
-
-#define atomic_read(v) __raw_uncached_fetch_asm(&(v)->counter)
+#include <linux/linkage.h>

asmlinkage int __raw_uncached_fetch_asm(const volatile int *ptr);
-
asmlinkage int __raw_atomic_update_asm(volatile int *ptr, int value);
-
asmlinkage int __raw_atomic_clear_asm(volatile int *ptr, int value);
-
asmlinkage int __raw_atomic_set_asm(volatile int *ptr, int value);
-
asmlinkage int __raw_atomic_xor_asm(volatile int *ptr, int value);
-
asmlinkage int __raw_atomic_test_asm(const volatile int *ptr, int value);

-static inline void atomic_add(int i, atomic_t *v)
-{
- __raw_atomic_update_asm(&v->counter, i);
-}
-
-static inline void atomic_sub(int i, atomic_t *v)
-{
- __raw_atomic_update_asm(&v->counter, -i);
-}
-
-static inline int atomic_add_return(int i, atomic_t *v)
-{
- return __raw_atomic_update_asm(&v->counter, i);
-}
-
-static inline int atomic_sub_return(int i, atomic_t *v)
-{
- return __raw_atomic_update_asm(&v->counter, -i);
-}
-
-static inline void atomic_inc(volatile atomic_t *v)
-{
- __raw_atomic_update_asm(&v->counter, 1);
-}
-
-static inline void atomic_dec(volatile atomic_t *v)
-{
- __raw_atomic_update_asm(&v->counter, -1);
-}
-
-static inline void atomic_clear_mask(int mask, atomic_t *v)
-{
- __raw_atomic_clear_asm(&v->counter, mask);
-}
-
-static inline void atomic_set_mask(int mask, atomic_t *v)
-{
- __raw_atomic_set_asm(&v->counter, mask);
-}
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec() barrier()
-#define smp_mb__after_atomic_dec() barrier()
-#define smp_mb__before_atomic_inc() barrier()
-#define smp_mb__after_atomic_inc() barrier()
-
-#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
-#define atomic_dec_return(v) atomic_sub_return(1,(v))
-#define atomic_inc_return(v) atomic_add_return(1,(v))
-
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-#define atomic_add_unless(v, a, u) \
-({ \
- int c, old; \
- c = atomic_read(v); \
- while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
- c = old; \
- c != (u); \
-})
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-
-/*
- * atomic_inc_and_test - increment and test
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1
- * and returns true if the result is zero, or false for all
- * other cases.
- */
-#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
+#define atomic_read(v) __raw_uncached_fetch_asm(&(v)->counter)

-#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
-#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+#define atomic_add_return(i, v) __raw_atomic_update_asm(&(v)->counter, i)
+#define atomic_sub_return(i, v) __raw_atomic_update_asm(&(v)->counter, -(i))

-#include <asm-generic/atomic-long.h>
+#define atomic_clear_mask(m, v) __raw_atomic_clear_asm(&(v)->counter, m)
+#define atomic_set_mask(m, v) __raw_atomic_set_asm(&(v)->counter, m)

#endif

+#include <asm-generic/atomic.h>
#include <asm-generic/atomic64.h>

#endif
--
1.7.5.3

2011-06-21 23:05:52

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH 6/6] Blackfin: SMP: convert to common asm-generic/atomic.h

On Fri, 17 Jun 2011 17:53:34 -0400
Mike Frysinger <[email protected]> wrote:

> Now that common code supports SMP systems, switch our SMP atomic logic
> over to it to avoid code duplication.

There were some rejects on this one, I think because lines 2, 3 and 4
had non-ascii crap in them and because your patch was expecting
inclusions of asm-generic/atomic-long.h and asm-generic/atomic64.h,
which were removed.

I ended up with the below but I don't know if it works.

/*
* Copyright 2004-2011 Analog Devices Inc.
_*
_* Licensed under the GPL-2 or later.
_*/

#ifndef __ARCH_BLACKFIN_ATOMIC__
#define __ARCH_BLACKFIN_ATOMIC__

#ifdef CONFIG_SMP

#include <linux/linkage.h>

asmlinkage int __raw_uncached_fetch_asm(const volatile int *ptr);
asmlinkage int __raw_atomic_update_asm(volatile int *ptr, int value);
asmlinkage int __raw_atomic_clear_asm(volatile int *ptr, int value);
asmlinkage int __raw_atomic_set_asm(volatile int *ptr, int value);
asmlinkage int __raw_atomic_xor_asm(volatile int *ptr, int value);
asmlinkage int __raw_atomic_test_asm(const volatile int *ptr, int value);

#define atomic_read(v) __raw_uncached_fetch_asm(&(v)->counter)

#define atomic_add_return(i, v) __raw_atomic_update_asm(&(v)->counter, i)
#define atomic_sub_return(i, v) __raw_atomic_update_asm(&(v)->counter, -(i))
#define atomic_clear_mask(m, v) __raw_atomic_clear_asm(&(v)->counter, m)
#define atomic_set_mask(m, v) __raw_atomic_set_asm(&(v)->counter, m)

#endif

#include <asm-generic/atomic.h>

#endif

2011-06-21 23:35:58

by Mike Frysinger

[permalink] [raw]
Subject: Re: [uclinux-dist-devel] [PATCH 6/6] Blackfin: SMP: convert to common asm-generic/atomic.h

On Tue, Jun 21, 2011 at 19:05, Andrew Morton wrote:
> On Fri, 17 Jun 2011 17:53:34 -0400 Mike Frysinger wrote:
>> Now that common code supports SMP systems, switch our SMP atomic logic
>> over to it to avoid code duplication.
>
> There were some rejects on this one, I think because lines 2, 3 and 4
> had non-ascii crap in them and because your patch was expecting
> inclusions of asm-generic/atomic-long.h and asm-generic/atomic64.h,
> which were removed.

in the patch summary, i mentioned that the Blackfin ones are informational only:
> The 2 Blackfin patches are just to show what's going on; I can
> merge them through my tree like normal. But the asm-generic
> ones will have to be picked up by Andrew.

so dont pick the Blackfin ones up ;)
-mike