* [PATCHv5] atomic: add *_dec_not_zero
From: Sven Eckelmann @ 2011-12-04 15:42 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-m32r-ja, linux-mips, linux-ia64, linux-doc, H. Peter Anvin,
Heiko Carstens, Randy Dunlap, Paul Mackerras, Helge Deller,
sparclinux, linux-hexagon, Sven Eckelmann, linux-arch, linux-s390,
Russell King, user-mode-linux-devel, Richard Weinberger,
Hirokazu Takata, x86, James E.J. Bottomley, Ingo Molnar,
Matt Turner, Fenghua Yu, Arnd Bergmann, Jeff Dike, Chris Metcalf,
linux-m32r, Ivan Kokshaysky, Thomas Gleixner, linux-arm-kernel,
Richard Henderson, Tony Luck, linux-parisc, b.a.t.m.a.n,
linux-kernel, Ralf Baechle, Kyle McMartin, linux-alpha,
Martin Schwidefsky, linux390, linuxppc-dev, David S. Miller
Introduce an *_dec_not_zero operation. Make this a special case of
*_add_unless because batman-adv uses atomic_dec_not_zero in different
places like re-broadcast queue or aggregation queue management. There
are other non-final patches which may also want to use this macro.
Suggested-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Cc: Randy Dunlap <rdunlap@xenotime.net>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Hirokazu Takata <takata@linux-m32r.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Kyle McMartin <kyle@mcmartin.ca>
Cc: Helge Deller <deller@gmx.de>
Cc: "James E.J. Bottomley" <jejb@parisc-linux.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: linux390@de.ibm.com
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Chris Metcalf <cmetcalf@tilera.com>
Cc: Jeff Dike <jdike@addtoit.com>
Cc: Richard Weinberger <richard@nod.at>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linux-doc@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-alpha@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-ia64@vger.kernel.org
Cc: linux-m32r@ml.linux-m32r.org
Cc: linux-m32r-ja@ml.linux-m32r.org
Cc: linux-mips@linux-mips.org
Cc: linux-parisc@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-s390@vger.kernel.org
Cc: sparclinux@vger.kernel.org
Cc: user-mode-linux-devel@lists.sourceforge.net
Cc: linux-hexagon@vger.kernel.org
---
David S. Miller recommended this change in
https://lists.open-mesh.org/pipermail/b.a.t.m.a.n/2011-May/004560.html
Arnd Bergmann wanted to apply it in 201106172320.26476.arnd@arndb.de
... and then Arun Sharma created a big merge conflict with
https://lkml.org/lkml/2011/6/6/430
I don't think that it is a a good idea to assume that everyone still
agrees with the patch after I've rewritten it. I try Andrew Morton this
time because he applied the last changes to include/linux/atomic.h.
There are already two projects (batman-adv/fault_inject) which include
their private definition (not conflicting) and I have patches for 9
other modules that could use it.
Documentation/atomic_ops.txt | 1 +
arch/alpha/include/asm/atomic.h | 1 +
arch/alpha/include/asm/local.h | 1 +
arch/arm/include/asm/atomic.h | 1 +
arch/hexagon/include/asm/atomic.h | 1 +
arch/ia64/include/asm/atomic.h | 1 +
arch/m32r/include/asm/local.h | 1 +
arch/mips/include/asm/atomic.h | 1 +
arch/mips/include/asm/local.h | 1 +
arch/parisc/include/asm/atomic.h | 1 +
arch/powerpc/include/asm/atomic.h | 1 +
arch/powerpc/include/asm/local.h | 1 +
arch/s390/include/asm/atomic.h | 1 +
arch/sparc/include/asm/atomic_64.h | 1 +
arch/tile/include/asm/atomic_32.h | 1 +
arch/tile/include/asm/atomic_64.h | 1 +
arch/x86/include/asm/atomic64_32.h | 12 ++++++++++++
arch/x86/include/asm/atomic64_64.h | 1 +
arch/x86/include/asm/local.h | 1 +
arch/x86/lib/atomic64_32.c | 4 ++++
arch/x86/lib/atomic64_386_32.S | 21 +++++++++++++++++++++
arch/x86/lib/atomic64_cx8_32.S | 28 ++++++++++++++++++++++++++++
include/asm-generic/atomic-long.h | 2 ++
include/asm-generic/atomic64.h | 1 +
include/asm-generic/local.h | 1 +
include/asm-generic/local64.h | 2 ++
include/linux/atomic.h | 9 +++++++++
lib/atomic64_test.c | 19 +++++++++++++++++++
28 files changed, 117 insertions(+), 0 deletions(-)
diff --git a/Documentation/atomic_ops.txt b/Documentation/atomic_ops.txt
index 3bd585b..1eec221 100644
--- a/Documentation/atomic_ops.txt
+++ b/Documentation/atomic_ops.txt
@@ -190,6 +190,7 @@ atomic_add_unless requires explicit memory barriers around the operation
unless it fails (returns 0).
atomic_inc_not_zero, equivalent to atomic_add_unless(v, 1, 0)
+atomic_dec_not_zero, equivalent to atomic_add_unless(v, -1, 0)
If a caller requires memory barrier semantics around an atomic_t
diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h
index 640f909..09d1571 100644
--- a/arch/alpha/include/asm/atomic.h
+++ b/arch/alpha/include/asm/atomic.h
@@ -225,6 +225,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
}
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
#define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0)
diff --git a/arch/alpha/include/asm/local.h b/arch/alpha/include/asm/local.h
index 9c94b84..51eb678 100644
--- a/arch/alpha/include/asm/local.h
+++ b/arch/alpha/include/asm/local.h
@@ -79,6 +79,7 @@ static __inline__ long local_sub_return(long i, local_t * l)
c != (u); \
})
#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
+#define local_dec_not_zero(l) local_add_unless((l), -1, 0)
#define local_add_negative(a, l) (local_add_return((a), (l)) < 0)
diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h
index 86976d0..80ed975 100644
--- a/arch/arm/include/asm/atomic.h
+++ b/arch/arm/include/asm/atomic.h
@@ -458,6 +458,7 @@ static inline int atomic64_add_unless(atomic64_t *v, u64 a, u64 u)
#define atomic64_dec_return(v) atomic64_sub_return(1LL, (v))
#define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0)
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL)
+#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1LL, 0LL)
#endif /* !CONFIG_GENERIC_ATOMIC64 */
#endif
diff --git a/arch/hexagon/include/asm/atomic.h b/arch/hexagon/include/asm/atomic.h
index e220f90..3a1a33a 100644
--- a/arch/hexagon/include/asm/atomic.h
+++ b/arch/hexagon/include/asm/atomic.h
@@ -148,6 +148,7 @@ 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)
+#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
#define atomic_inc(v) atomic_add(1, (v))
#define atomic_dec(v) atomic_sub(1, (v))
diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h
index 3fad89e..af6e9b2 100644
--- a/arch/ia64/include/asm/atomic.h
+++ b/arch/ia64/include/asm/atomic.h
@@ -122,6 +122,7 @@ static __inline__ long atomic64_add_unless(atomic64_t *v, long a, long u)
}
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
#define atomic_add_return(i,v) \
({ \
diff --git a/arch/m32r/include/asm/local.h b/arch/m32r/include/asm/local.h
index 734bca8..d536082 100644
--- a/arch/m32r/include/asm/local.h
+++ b/arch/m32r/include/asm/local.h
@@ -272,6 +272,7 @@ static inline int local_add_unless(local_t *l, long a, long u)
}
#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
+#define local_dec_not_zero(l) local_add_unless((l), -1, 0)
static inline void local_clear_mask(unsigned long mask, local_t *addr)
{
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 1d93f81..babb043 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -697,6 +697,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
}
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
#define atomic64_dec_return(v) atomic64_sub_return(1, (v))
#define atomic64_inc_return(v) atomic64_add_return(1, (v))
diff --git a/arch/mips/include/asm/local.h b/arch/mips/include/asm/local.h
index 94fde8d..0242256 100644
--- a/arch/mips/include/asm/local.h
+++ b/arch/mips/include/asm/local.h
@@ -137,6 +137,7 @@ static __inline__ long local_sub_return(long i, local_t * l)
c != (u); \
})
#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
+#define local_dec_not_zero(l) local_add_unless((l), -1, 0)
#define local_dec_return(l) local_sub_return(1, (l))
#define local_inc_return(l) local_add_return(1, (l))
diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h
index 4054b31..57b7069 100644
--- a/arch/parisc/include/asm/atomic.h
+++ b/arch/parisc/include/asm/atomic.h
@@ -334,6 +334,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
}
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
#endif /* !CONFIG_64BIT */
diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
index 02e41b5..0798420 100644
--- a/arch/powerpc/include/asm/atomic.h
+++ b/arch/powerpc/include/asm/atomic.h
@@ -468,6 +468,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
}
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
#endif /* __powerpc64__ */
diff --git a/arch/powerpc/include/asm/local.h b/arch/powerpc/include/asm/local.h
index b8da913..d182e34 100644
--- a/arch/powerpc/include/asm/local.h
+++ b/arch/powerpc/include/asm/local.h
@@ -134,6 +134,7 @@ static __inline__ int local_add_unless(local_t *l, long a, long u)
}
#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
+#define local_dec_not_zero(l) local_add_unless((l), -1, 0)
#define local_sub_and_test(a, l) (local_sub_return((a), (l)) == 0)
#define local_dec_and_test(l) (local_dec_return((l)) == 0)
diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h
index 8517d2a..92e7d5d 100644
--- a/arch/s390/include/asm/atomic.h
+++ b/arch/s390/include/asm/atomic.h
@@ -325,6 +325,7 @@ static inline long long atomic64_dec_if_positive(atomic64_t *v)
#define atomic64_dec_return(_v) atomic64_sub_return(1, _v)
#define atomic64_dec_and_test(_v) (atomic64_sub_return(1, _v) == 0)
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
#define smp_mb__before_atomic_dec() smp_mb()
#define smp_mb__after_atomic_dec() smp_mb()
diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h
index 9f421df..94cf160 100644
--- a/arch/sparc/include/asm/atomic_64.h
+++ b/arch/sparc/include/asm/atomic_64.h
@@ -106,6 +106,7 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u)
}
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
/* Atomic operations are already serializing */
#define smp_mb__before_atomic_dec() barrier()
diff --git a/arch/tile/include/asm/atomic_32.h b/arch/tile/include/asm/atomic_32.h
index c03349e..9cfafb3 100644
--- a/arch/tile/include/asm/atomic_32.h
+++ b/arch/tile/include/asm/atomic_32.h
@@ -233,6 +233,7 @@ static inline void atomic64_set(atomic64_t *v, u64 n)
#define atomic64_dec_return(v) atomic64_sub_return(1LL, (v))
#define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0)
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL)
+#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1LL, 0LL)
/*
* We need to barrier before modifying the word, since the _atomic_xxx()
diff --git a/arch/tile/include/asm/atomic_64.h b/arch/tile/include/asm/atomic_64.h
index 27fe667..9c22f50 100644
--- a/arch/tile/include/asm/atomic_64.h
+++ b/arch/tile/include/asm/atomic_64.h
@@ -141,6 +141,7 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u)
#define atomic64_add_negative(i, v) (atomic64_add_return((i), (v)) < 0)
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
/* Atomic dec and inc don't implement barrier, so provide them if needed. */
#define smp_mb__before_atomic_dec() smp_mb()
diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h
index 24098aa..3cd4431 100644
--- a/arch/x86/include/asm/atomic64_32.h
+++ b/arch/x86/include/asm/atomic64_32.h
@@ -287,6 +287,18 @@ static inline int atomic64_inc_not_zero(atomic64_t *v)
return r;
}
+
+static inline int atomic64_dec_not_zero(atomic64_t *v)
+{
+ int r;
+ asm volatile(ATOMIC64_ALTERNATIVE(dec_not_zero)
+ : "=a" (r)
+ : "S" (v)
+ : "ecx", "edx", "memory"
+ );
+ return r;
+}
+
static inline long long atomic64_dec_if_positive(atomic64_t *v)
{
long long r;
diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h
index 0e1cbfc..539e41b 100644
--- a/arch/x86/include/asm/atomic64_64.h
+++ b/arch/x86/include/asm/atomic64_64.h
@@ -216,6 +216,7 @@ static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
}
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
/*
* atomic64_dec_if_positive - decrement by 1 if old value positive
diff --git a/arch/x86/include/asm/local.h b/arch/x86/include/asm/local.h
index 9cdae5d..2c8c92d 100644
--- a/arch/x86/include/asm/local.h
+++ b/arch/x86/include/asm/local.h
@@ -185,6 +185,7 @@ static inline long local_sub_return(long i, local_t *l)
c != (u); \
})
#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
+#define local_dec_not_zero(l) local_add_unless((l), -1, 0)
/* On x86_32, these are no better than the atomic variants.
* On x86-64 these are better than the atomic variants on SMP kernels
diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c
index 042f682..7da05c3 100644
--- a/arch/x86/lib/atomic64_32.c
+++ b/arch/x86/lib/atomic64_32.c
@@ -24,6 +24,8 @@ long long atomic64_dec_if_positive_cx8(atomic64_t *v);
EXPORT_SYMBOL(atomic64_dec_if_positive_cx8);
int atomic64_inc_not_zero_cx8(atomic64_t *v);
EXPORT_SYMBOL(atomic64_inc_not_zero_cx8);
+int atomic64_dec_not_zero_cx8(atomic64_t *v);
+EXPORT_SYMBOL(atomic64_dec_not_zero_cx8);
int atomic64_add_unless_cx8(atomic64_t *v, long long a, long long u);
EXPORT_SYMBOL(atomic64_add_unless_cx8);
@@ -54,6 +56,8 @@ long long atomic64_dec_if_positive_386(atomic64_t *v);
EXPORT_SYMBOL(atomic64_dec_if_positive_386);
int atomic64_inc_not_zero_386(atomic64_t *v);
EXPORT_SYMBOL(atomic64_inc_not_zero_386);
+int atomic64_dec_not_zero_386(atomic64_t *v);
+EXPORT_SYMBOL(atomic64_dec_not_zero_386);
int atomic64_add_unless_386(atomic64_t *v, long long a, long long u);
EXPORT_SYMBOL(atomic64_add_unless_386);
#endif
diff --git a/arch/x86/lib/atomic64_386_32.S b/arch/x86/lib/atomic64_386_32.S
index e8e7e0d..c78337b 100644
--- a/arch/x86/lib/atomic64_386_32.S
+++ b/arch/x86/lib/atomic64_386_32.S
@@ -181,6 +181,27 @@ ENDP
#undef v
#define v %esi
+BEGIN(dec_not_zero)
+ movl (v), %eax
+ movl 4(v), %edx
+ testl %eax, %eax
+ je 3f
+1:
+ subl $1, %eax
+ sbbl $0, %edx
+ movl %eax, (v)
+ movl %edx, 4(v)
+ movl $1, %eax
+2:
+ RET
+3:
+ testl %edx, %edx
+ jne 1b
+ jmp 2b
+ENDP
+#undef v
+
+#define v %esi
BEGIN(dec_if_positive)
movl (v), %eax
movl 4(v), %edx
diff --git a/arch/x86/lib/atomic64_cx8_32.S b/arch/x86/lib/atomic64_cx8_32.S
index 391a083..989638c 100644
--- a/arch/x86/lib/atomic64_cx8_32.S
+++ b/arch/x86/lib/atomic64_cx8_32.S
@@ -220,3 +220,31 @@ ENTRY(atomic64_inc_not_zero_cx8)
jmp 3b
CFI_ENDPROC
ENDPROC(atomic64_inc_not_zero_cx8)
+
+ENTRY(atomic64_dec_not_zero_cx8)
+ CFI_STARTPROC
+ SAVE ebx
+
+ read64 %esi
+1:
+ testl %eax, %eax
+ je 4f
+2:
+ movl %eax, %ebx
+ movl %edx, %ecx
+ subl $1, %ebx
+ sbbl $0, %ecx
+ LOCK_PREFIX
+ cmpxchg8b (%esi)
+ jne 1b
+
+ movl $1, %eax
+3:
+ RESTORE ebx
+ ret
+4:
+ testl %edx, %edx
+ jne 2b
+ jmp 3b
+ CFI_ENDPROC
+ENDPROC(atomic64_dec_not_zero_cx8)
diff --git a/include/asm-generic/atomic-long.h b/include/asm-generic/atomic-long.h
index b7babf0..0fe75ab 100644
--- a/include/asm-generic/atomic-long.h
+++ b/include/asm-generic/atomic-long.h
@@ -130,6 +130,7 @@ static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
}
#define atomic_long_inc_not_zero(l) atomic64_inc_not_zero((atomic64_t *)(l))
+#define atomic_long_dec_not_zero(l) atomic64_dec_not_zero((atomic64_t *)(l))
#define atomic_long_cmpxchg(l, old, new) \
(atomic64_cmpxchg((atomic64_t *)(l), (old), (new)))
@@ -247,6 +248,7 @@ static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
}
#define atomic_long_inc_not_zero(l) atomic_inc_not_zero((atomic_t *)(l))
+#define atomic_long_dec_not_zero(l) atomic_dec_not_zero((atomic_t *)(l))
#define atomic_long_cmpxchg(l, old, new) \
(atomic_cmpxchg((atomic_t *)(l), (old), (new)))
diff --git a/include/asm-generic/atomic64.h b/include/asm-generic/atomic64.h
index b18ce4f..90ff9b1 100644
--- a/include/asm-generic/atomic64.h
+++ b/include/asm-generic/atomic64.h
@@ -38,5 +38,6 @@ extern int atomic64_add_unless(atomic64_t *v, long long a, long long u);
#define atomic64_dec_return(v) atomic64_sub_return(1LL, (v))
#define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0)
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL)
+#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1LL, 0LL)
#endif /* _ASM_GENERIC_ATOMIC64_H */
diff --git a/include/asm-generic/local.h b/include/asm-generic/local.h
index 9ceb03b..fabf4f3 100644
--- a/include/asm-generic/local.h
+++ b/include/asm-generic/local.h
@@ -44,6 +44,7 @@ typedef struct
#define local_xchg(l, n) atomic_long_xchg((&(l)->a), (n))
#define local_add_unless(l, _a, u) atomic_long_add_unless((&(l)->a), (_a), (u))
#define local_inc_not_zero(l) atomic_long_inc_not_zero(&(l)->a)
+#define local_dec_not_zero(l) atomic_long_dec_not_zero(&(l)->a)
/* Non-atomic variants, ie. preemption disabled and won't be touched
* in interrupt, etc. Some archs can optimize this case well. */
diff --git a/include/asm-generic/local64.h b/include/asm-generic/local64.h
index 5980002..76acbe2 100644
--- a/include/asm-generic/local64.h
+++ b/include/asm-generic/local64.h
@@ -45,6 +45,7 @@ typedef struct {
#define local64_xchg(l, n) local_xchg((&(l)->a), (n))
#define local64_add_unless(l, _a, u) local_add_unless((&(l)->a), (_a), (u))
#define local64_inc_not_zero(l) local_inc_not_zero(&(l)->a)
+#define local64_dec_not_zero(l) local_dec_not_zero(&(l)->a)
/* Non-atomic variants, ie. preemption disabled and won't be touched
* in interrupt, etc. Some archs can optimize this case well. */
@@ -83,6 +84,7 @@ typedef struct {
#define local64_xchg(l, n) atomic64_xchg((&(l)->a), (n))
#define local64_add_unless(l, _a, u) atomic64_add_unless((&(l)->a), (_a), (u))
#define local64_inc_not_zero(l) atomic64_inc_not_zero(&(l)->a)
+#define local64_dec_not_zero(l) atomic64_dec_not_zero(&(l)->a)
/* Non-atomic variants, ie. preemption disabled and won't be touched
* in interrupt, etc. Some archs can optimize this case well. */
diff --git a/include/linux/atomic.h b/include/linux/atomic.h
index 42b77b5..ad2b750 100644
--- a/include/linux/atomic.h
+++ b/include/linux/atomic.h
@@ -27,6 +27,15 @@ 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)
/**
+ * atomic_dec_not_zero - decrement unless the number is zero
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1, so long as @v is non-zero.
+ * Returns non-zero if @v was non-zero, and zero otherwise.
+ */
+#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
+
+/**
* atomic_inc_not_zero_hint - increment if not null
* @v: pointer of type atomic_t
* @hint: probable value of the atomic before the increment
diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c
index 0c33cde..b7468b7 100644
--- a/lib/atomic64_test.c
+++ b/lib/atomic64_test.c
@@ -145,6 +145,25 @@ static __init int test_atomic64(void)
r += one;
BUG_ON(v.counter != r);
+ INIT(onestwos);
+ BUG_ON(!atomic64_dec_not_zero(&v));
+ r -= one;
+ BUG_ON(v.counter != r);
+
+ INIT(0);
+ BUG_ON(atomic64_dec_not_zero(&v));
+ BUG_ON(v.counter != r);
+
+ INIT(one);
+ BUG_ON(!atomic64_dec_not_zero(&v));
+ r -= one;
+ BUG_ON(v.counter != r);
+
+ INIT(-one);
+ BUG_ON(!atomic64_dec_not_zero(&v));
+ r -= one;
+ BUG_ON(v.counter != r);
+
#ifdef CONFIG_X86
printk(KERN_INFO "atomic64 test passed for %s platform %s CX8 and %s SSE\n",
#ifdef CONFIG_X86_64
--
1.7.7.3
^ permalink raw reply related
* Re: [PATCH-RFC 08/10] powerpc: switch to GENERIC_PCI_IOMAP
From: Benjamin Herrenschmidt @ 2011-12-04 20:52 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20111204104835.GJ15464@redhat.com>
On Sun, 2011-12-04 at 12:48 +0200, Michael S. Tsirkin wrote:
> On Thu, Nov 24, 2011 at 10:19:54PM +0200, Michael S. Tsirkin wrote:
> > powerpc copied pci_iomap from generic code, probably to avoid
> > pulling the rest of iomap.c in. Since that's in
> > a separate file now, we can reuse the common implementation.
> >
> > The only difference is handling of nocache flag,
> > that turns out to be done correctly by the
> > generic code since arch/powerpc/include/asm/io.h
> > defines ioremap_nocache same as ioremap.
> >
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
>
>
> Sorry to nag, any ACKs/NACKs on the powerpc changes?
> I intend to send this to Linus if there are no
> objections. Thanks!
Ah sorry, forgot about that. Do you have a git tree I can pull to do
quick test ?
No objection in principle.
Cheers,
Ben.
> > ---
> > arch/powerpc/Kconfig | 1 +
> > arch/powerpc/kernel/iomap.c | 19 -------------------
> > 2 files changed, 1 insertions(+), 19 deletions(-)
> >
> > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> > index 951e18f..6ffe3df 100644
> > --- a/arch/powerpc/Kconfig
> > +++ b/arch/powerpc/Kconfig
> > @@ -710,6 +710,7 @@ config PCI
> > default PCI_PERMEDIA if !4xx && !CPM2 && !8xx
> > default PCI_QSPAN if !4xx && !CPM2 && 8xx
> > select ARCH_SUPPORTS_MSI
> > + select GENERIC_PCI_IOMAP
> > help
> > Find out whether your system includes a PCI bus. PCI is the name of
> > a bus system, i.e. the way the CPU talks to the other stuff inside
> > diff --git a/arch/powerpc/kernel/iomap.c b/arch/powerpc/kernel/iomap.c
> > index 2627918..97a3715 100644
> > --- a/arch/powerpc/kernel/iomap.c
> > +++ b/arch/powerpc/kernel/iomap.c
> > @@ -119,24 +119,6 @@ EXPORT_SYMBOL(ioport_map);
> > EXPORT_SYMBOL(ioport_unmap);
> >
> > #ifdef CONFIG_PCI
> > -void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
> > -{
> > - resource_size_t start = pci_resource_start(dev, bar);
> > - resource_size_t len = pci_resource_len(dev, bar);
> > - unsigned long flags = pci_resource_flags(dev, bar);
> > -
> > - if (!len)
> > - return NULL;
> > - if (max && len > max)
> > - len = max;
> > - if (flags & IORESOURCE_IO)
> > - return ioport_map(start, len);
> > - if (flags & IORESOURCE_MEM)
> > - return ioremap(start, len);
> > - /* What? */
> > - return NULL;
> > -}
> > -
> > void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
> > {
> > if (isa_vaddr_is_ioport(addr))
> > @@ -146,6 +128,5 @@ void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
> > iounmap(addr);
> > }
> >
> > -EXPORT_SYMBOL(pci_iomap);
> > EXPORT_SYMBOL(pci_iounmap);
> > #endif /* CONFIG_PCI */
> > --
> > 1.7.5.53.gc233e
^ permalink raw reply
* Re: Re: [PATCHv5] atomic: add *_dec_not_zero
From: Sven Eckelmann @ 2011-12-04 21:49 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: linux-m32r-ja, linux-mips, linux-ia64, linux-doc, H. Peter Anvin,
Heiko Carstens, Randy Dunlap, Paul Mackerras, Helge Deller,
sparclinux, linux-hexagon, linux-arch, linux-s390,
user-mode-linux-devel, Richard Weinberger, Hirokazu Takata, x86,
James E.J. Bottomley, Ingo Molnar, Matt Turner, Fenghua Yu,
Arnd Bergma nn, Jeff Dike, Chris Metcalf, linux-m32r,
Ivan Kokshaysky, Thomas Gleixner, linux-arm-kernel,
Richard Henderson, Tony Luck, linux-parisc, b.a.t.m.a.n,
linux-kernel, Ralf Baechle, Kyle McMartin, linux-alpha,
Martin Schwidefsky, linux390, Andrew Morton, linuxppc-dev,
David S. Miller
In-Reply-To: <20111204213316.GB14542@n2100.arm.linux.org.uk>
[-- Attachment #1: Type: text/plain, Size: 843 bytes --]
On Sunday 04 December 2011 21:33:16 Russell King - ARM Linux wrote:
[...]
> > +#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1LL, 0LL)
>
> I think this is rather silly - all these definitions are very similar to
> each other. Is there really no way to put this into include/linux/atomic.h,
> maybe as something like:
>
> #ifndef atomic64_dec_not_zero
> #define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
> #endif
>
> and avoid having to add essentially the same definition to 12 individual
> files?
>
> Architectures which want to override it can do by the following:
>
> #define atomic64_dec_not_zero atomic64_dec_not_zero
>
> which won't have any effect on C nor asm code.
* https://lkml.org/lkml/2011/5/8/15
* https://lkml.org/lkml/2011/5/8/16
* https://lkml.org/lkml/2011/5/8/321
Kind regards,
Sven
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCHv5] atomic: add *_dec_not_zero
From: Russell King - ARM Linux @ 2011-12-04 21:33 UTC (permalink / raw)
To: Sven Eckelmann
Cc: linux-m32r-ja, linux-mips, linux-ia64, linux-doc, H. Peter Anvin,
Heiko Carstens, Randy Dunlap, Paul Mackerras, Helge Deller,
sparclinux, linux-hexagon, linux-arch, linux-s390,
user-mode-linux-devel, Richard Weinberger, Hirokazu Takata, x86,
James E.J. Bottomley, Ingo Molnar, Matt Turner, Fenghua Yu,
Arnd Bergmann, Jeff Dike, Chris Metcalf, linux-m32r,
Ivan Kokshaysky, Thomas Gleixner, linux-arm-kernel,
Richard Henderson, Tony Luck, linux-parisc, b.a.t.m.a.n,
linux-kernel, Ralf Baechle, Kyle McMartin, linux-alpha,
Martin Schwidefsky, linux390, Andrew Morton, linuxppc-dev,
David S. Miller
In-Reply-To: <1323013369-29691-1-git-send-email-sven@narfation.org>
On Sun, Dec 04, 2011 at 04:42:49PM +0100, Sven Eckelmann wrote:
> diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h
> +#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
> diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h
> +#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1LL, 0LL)
> diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h
> +#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
> diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
> +#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
> diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h
> +#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
> diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
> +#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
> diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h
> +#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
> diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h
> +#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
> diff --git a/arch/tile/include/asm/atomic_32.h b/arch/tile/include/asm/atomic_32.h
> +#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1LL, 0LL)
> diff --git a/arch/tile/include/asm/atomic_64.h b/arch/tile/include/asm/atomic_64.h
> +#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
> diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h
> +#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
> diff --git a/include/asm-generic/atomic64.h b/include/asm-generic/atomic64.h
> +#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1LL, 0LL)
I think this is rather silly - all these definitions are very similar to
each other. Is there really no way to put this into include/linux/atomic.h,
maybe as something like:
#ifndef atomic64_dec_not_zero
#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
#endif
and avoid having to add essentially the same definition to 12 individual
files?
Architectures which want to override it can do by the following:
#define atomic64_dec_not_zero atomic64_dec_not_zero
which won't have any effect on C nor asm code.
^ permalink raw reply
* Re: Re: [PATCHv5] atomic: add *_dec_not_zero
From: Russell King - ARM Linux @ 2011-12-04 22:18 UTC (permalink / raw)
To: Sven Eckelmann
Cc: linux-m32r-ja, linux-mips, linux-ia64, linux-doc, H. Peter Anvin,
Heiko Carstens, Randy Dunlap, Paul Mackerras, Helge Deller,
sparclinux, linux-hexagon, linux-arch, linux-s390,
user-mode-linux-devel, Richard Weinberger, Hirokazu Takata, x86,
James E.J. Bottomley, Ingo Molnar, Matt Turner, Fenghua Yu,
Arnd Bergma nn, Jeff Dike, Chris Metcalf, linux-m32r,
Ivan Kokshaysky, Thomas Gleixner, linux-arm-kernel,
Richard Henderson, Tony Luck, linux-parisc, b.a.t.m.a.n,
linux-kernel, Ralf Baechle, Kyle McMartin, linux-alpha,
Martin Schwidefsky, linux390, Andrew Morton, linuxppc-dev,
David S. Miller
In-Reply-To: <1699880.NTdz2k3W9O@sven-laptop.home.narfation.org>
On Sun, Dec 04, 2011 at 10:49:10PM +0100, Sven Eckelmann wrote:
> On Sunday 04 December 2011 21:33:16 Russell King - ARM Linux wrote:
> [...]
> > > +#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1LL, 0LL)
> >
> > I think this is rather silly - all these definitions are very similar to
> > each other. Is there really no way to put this into include/linux/atomic.h,
> > maybe as something like:
> >
> > #ifndef atomic64_dec_not_zero
> > #define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
> > #endif
> >
> > and avoid having to add essentially the same definition to 12 individual
> > files?
> >
> > Architectures which want to override it can do by the following:
> >
> > #define atomic64_dec_not_zero atomic64_dec_not_zero
> >
> > which won't have any effect on C nor asm code.
>
> * https://lkml.org/lkml/2011/5/8/15
> * https://lkml.org/lkml/2011/5/8/16
> * https://lkml.org/lkml/2011/5/8/321
I don't see any reason in that set of messages _not_ to do what I suggest.
Even on SMP architectures, your:
#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
makes total sense - and with the adjustments I've suggested it means
that architectures (like x86) can still override it if have a more
optimal way to perform this operation.
Not only that, but we already do this kind of thing in
include/linux/atomic.h for the non-64 bit ops, for example:
#ifndef atomic_inc_unless_negative
static inline int atomic_inc_unless_negative(atomic_t *p)
{
int v, v1;
for (v = 0; v >= 0; v = v1) {
v1 = atomic_cmpxchg(p, v, v + 1);
if (likely(v1 == v))
return 1;
}
return 0;
}
#endif
And really, I believe it would be a good cleanup if all the standard
definitions for atomic64 ops (like atomic64_add_negative) were also
defined in include/linux/atomic.h rather than individually in every
atomic*.h header throughout the kernel source, except where an arch
wants to explicitly override it. Yet again, virtually all architectures
define these in exactly the same way.
We have more than enough code in arch/ for any architecture to worry
about, we don't need schemes to add more when there's simple and
practical solutions to avoiding doing so if the right design were
chosen (preferably from the outset.)
So, I'm not going to offer my ack for a change which I don't believe
is the correct approach.
^ permalink raw reply
* Re: Re: Re: [PATCHv5] atomic: add *_dec_not_zero
From: Sven Eckelmann @ 2011-12-04 22:42 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: linux-m32r-ja, linux-mips, linux-ia64, linux-doc, H. Peter Anvin,
Heiko Carstens, Randy Dunlap, Paul Mackerras, Helge Deller,
sparclinux, linux-hexagon, linux-arch, linux-s390,
user-mode-linux-devel, Richard Weinberger, Hirokazu Takata, x86,
James E.J. Bottomley, Ingo Molnar, Matt Turner, Fenghua Yu,
Arnd Bergma nn, Jeff Dike, Chris Metcalf, linux-m32r,
Ivan Kokshaysky, Thomas Gleixner, linux-arm-kernel,
Richard Henderson, Tony Luck, linux-parisc, b.a.t.m.a.n,
linux-kernel, Ralf Baechle, Kyle McMartin, linux-alpha,
Martin Schwidefsky, linux390, Andrew Morton, linuxppc-dev,
David S. Miller
In-Reply-To: <20111204221850.GC14542@n2100.arm.linux.org.uk>
[-- Attachment #1: Type: text/plain, Size: 2941 bytes --]
On Sunday 04 December 2011 22:18:50 Russell King - ARM Linux wrote:
> On Sun, Dec 04, 2011 at 10:49:10PM +0100, Sven Eckelmann wrote:
> > On Sunday 04 December 2011 21:33:16 Russell King - ARM Linux wrote:
> > [...]
> >
> > > > +#define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1LL,
> > > > 0LL)
> > >
> > > I think this is rather silly - all these definitions are very
> > > similar to each other. Is there really no way to put this into
> > > include/linux/atomic.h, maybe as something like:
> > >
> > > #ifndef atomic64_dec_not_zero
> > > #define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
> > > #endif
> > >
> > > and avoid having to add essentially the same definition to 12
> > > individual files?
> > >
> > > Architectures which want to override it can do by the following:
> > >
> > > #define atomic64_dec_not_zero atomic64_dec_not_zero
> > >
> > > which won't have any effect on C nor asm code.
> >
> > * https://lkml.org/lkml/2011/5/8/15
> > * https://lkml.org/lkml/2011/5/8/16
> > * https://lkml.org/lkml/2011/5/8/321
>
> I don't see any reason in that set of messages _not_ to do what I suggest.
> Even on SMP architectures, your:
>
> #define atomic64_dec_not_zero(v) atomic64_add_unless((v), -1, 0)
>
> makes total sense - and with the adjustments I've suggested it means
> that architectures (like x86) can still override it if have a more
> optimal way to perform this operation.
>
> Not only that, but we already do this kind of thing in
> include/linux/atomic.h for the non-64 bit ops, for example:
>
> #ifndef atomic_inc_unless_negative
> static inline int atomic_inc_unless_negative(atomic_t *p)
> {
> int v, v1;
> for (v = 0; v >= 0; v = v1) {
> v1 = atomic_cmpxchg(p, v, v + 1);
> if (likely(v1 == v))
> return 1;
> }
> return 0;
> }
> #endif
>
> And really, I believe it would be a good cleanup if all the standard
> definitions for atomic64 ops (like atomic64_add_negative) were also
> defined in include/linux/atomic.h rather than individually in every
> atomic*.h header throughout the kernel source, except where an arch
> wants to explicitly override it. Yet again, virtually all architectures
> define these in exactly the same way.
>
> We have more than enough code in arch/ for any architecture to worry
> about, we don't need schemes to add more when there's simple and
> practical solutions to avoiding doing so if the right design were
> chosen (preferably from the outset.)
>
> So, I'm not going to offer my ack for a change which I don't believe
> is the correct approach.
Ok, I wanted to say that I just did what is currently done and did not offer a
redesign. There is just a difference between adding something and replacing
everything with something else. But I am fine with not getting the ack because
now somebody at least made a statement.
Kind regards,
Sven
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: Re: [PATCHv5] atomic: add *_dec_not_zero
From: Benjamin Herrenschmidt @ 2011-12-04 22:41 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: linux-m32r-ja, linux-mips, linux-ia64, linux-doc, Heiko Carstens,
Randy Dunlap, Paul Mackerras, H. Peter Anvin, sparclinux,
Sven Eckelmann, linux-arch, linux-s390, Arnd Bergma nn,
linux-hexagon, Helge Deller, x86, James E.J. Bottomley,
Ingo Molnar, Matt Turner, Fenghua Yu, user-mode-linux-devel,
Jeff Dike, linux-alpha, Chris Metcalf, Tony Luck, Ivan Kokshaysky,
Thomas Gleixner, linux-arm-kernel, Richard Henderson, linux-m32r,
linux-parisc, b.a.t.m.a.n, linux-kernel, Ralf Baechle,
David S. Miller, Kyle McMartin, Richard Weinberger,
Martin Schwidefsky, linux390, Andrew Morton, linuxppc-dev,
Hirokazu Takata
In-Reply-To: <20111204221850.GC14542@n2100.arm.linux.org.uk>
On Sun, 2011-12-04 at 22:18 +0000, Russell King - ARM Linux wrote:
.../...
> And really, I believe it would be a good cleanup if all the standard
> definitions for atomic64 ops (like atomic64_add_negative) were also
> defined in include/linux/atomic.h rather than individually in every
> atomic*.h header throughout the kernel source, except where an arch
> wants to explicitly override it. Yet again, virtually all architectures
> define these in exactly the same way.
>
> We have more than enough code in arch/ for any architecture to worry
> about, we don't need schemes to add more when there's simple and
> practical solutions to avoiding doing so if the right design were
> chosen (preferably from the outset.)
>
> So, I'm not going to offer my ack for a change which I don't believe
> is the correct approach.
I agree with Russell, his approach is a lot easier to maintain long run,
we should even consider converting existing definitions.
Cheers,
Ben.
^ permalink raw reply
* [PATCH] powerpc: Increase minimum RMO size from 64MB to 256MB
From: Anton Blanchard @ 2011-12-04 23:13 UTC (permalink / raw)
To: benh, paulus, tony; +Cc: linuxppc-dev
The minimum RMO size field in ibm,client-architecture is currently
ignored, but a future firmware version will rectify that. Since we
always get at least 128MB of RMO right now, asking for 64MB is
likely to result in boot failures.
We should bump it to at least 128MB, but considering all the boot
issues we have on 128MB RMO boxes and all new machines have virtual
RMO, we may as well set our minimum to 256MB.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-powerpc/arch/powerpc/kernel/prom_init.c
===================================================================
--- linux-powerpc.orig/arch/powerpc/kernel/prom_init.c 2011-12-05 10:11:45.666351716 +1100
+++ linux-powerpc/arch/powerpc/kernel/prom_init.c 2011-12-05 10:11:52.798475491 +1100
@@ -742,7 +742,7 @@ static unsigned char ibm_architecture_ve
W(0xffffffff), /* virt_base */
W(0xffffffff), /* virt_size */
W(0xffffffff), /* load_base */
- W(64), /* 64MB min RMA */
+ W(256), /* 256MB min RMA */
W(0xffffffff), /* full client load */
0, /* min RMA percentage of total RAM */
48, /* max log_2(hash table size) */
^ permalink raw reply
* Re: [PATCH 1/1] Punch a hole in /dev/mem for librtas
From: Benjamin Herrenschmidt @ 2011-12-04 23:18 UTC (permalink / raw)
To: Segher Boessenkool
Cc: linuxppc-dev, sbest, Sukadev Bhattiprolu, paulus, anton
In-Reply-To: <144CAEA6-C129-4935-B6D1-A7D6F24530A5@kernel.crashing.org>
On Sat, 2011-12-03 at 04:22 +0100, Segher Boessenkool wrote:
> > +static inline int page_is_rtas_user_buf(unsigned long pfn)
> > +{
> > + unsigned long paddr = (pfn << PAGE_SHIFT);
> > + if (paddr >= rtas_rmo_buf && paddr < (rtas_rmo_buf +
> > RTAS_RMOBUF_MAX))
>
> It probably cannot overflow with actual values of rtas_rmo_buf
> and RTAS_RMOBUF_MAX, but otherwise it is an incorrect test;
> please write
>
> if (paddr >= rtas_rmo_buf && paddr - rtas_rmo_buf < RTAS_RMOBUF_MAX)
>
> (and, _MAX? Shouldn't it be the actual size here? Or is _MAX
> just a confusing name :-) )
The original code is a lot more readable and perfectly correct for all
possible values of rtas_rmo_buf :-)
Cheers,
Ben.
^ permalink raw reply
* [PATCH 0/6] RFCv2 Fix Fsl 8250 BRK bug
From: Paul Gortmaker @ 2011-12-04 23:42 UTC (permalink / raw)
To: alan, gregkh, scottwood, galak; +Cc: linuxppc-dev, linux-kernel, linux-serial
In-Reply-To: <1322783258-20443-1-git-send-email-paul.gortmaker@windriver.com>
Alan wrote:
> Things like 8250_dw.c is perhaps more the style we want to be looking at
> for other devices and adjusting 8250.c as needed to export or split
> methods up so they can be used as helpers.
[...]
> Sorting out a ->handle_port override is probably ultimately the right
> thing to do and then we can push some of the other funnies out further.
I never figured spending this much time on this, but I think this is
a lot better, and 8250.c comes out slightly smaller and cleaner too,
hopefully satisfying Alan's other request "...we want less not more".
The errata is firewalled off in 8250_fsl.c (as per Alan's 1st comment),
and 8250.c now exports a couple more things to be used as helpers.
When I started looking at a handle_port override, I realized that it
really didn't need to exist at all, and the existing handle_irq
override we already have does the job nicely. In the process, I found
an interesting quirk while cleaning up duplicated code in the timeout
handler, where we don't use the custom IRQ handler if there is one.
So, the errata is dealt with by installing a custom IRQ handler, and
it doesn't have the "eew ick" factor that Scott mentioned, in regards
to trying to learn state from watching serial_in() traffic.
The timeout cleanup seemed so obvious, that I was convinced I must
be missing some subtle thing. So I confirmed it by stripping my IRQ
properties from my dts file and running the serial console IRQ-less.
I also re-tested the sysRq feature on sbc8349, to ensure the WAR was
actually doing its job, and I also tested with serial console on
an old SocketA board to make sure non-ppc didn't get hosed somehow.
Anyway, have a look and see if this version of things is acceptable
to all. (Again, the dts update from Kumar isn't shown here).
Thanks to all who provided the feedback on v1.
Paul.
------
Paul Gortmaker (6):
serial: move struct uart_8250_port from 8250.c to 8250.h
serial: clean up parameter passing for 8250 Rx IRQ handling
serial: export the key functions for an 8250 IRQ handler
serial: make 8250 timeout use the specified IRQ handler
serial: manually inline serial8250_handle_port
serial: add irq handler for Freescale 16550 errata.
arch/powerpc/kernel/legacy_serial.c | 3 +
drivers/tty/serial/8250.c | 92 ++++++++++++-----------------------
drivers/tty/serial/8250.h | 26 ++++++++++
drivers/tty/serial/8250_fsl.c | 63 ++++++++++++++++++++++++
drivers/tty/serial/Kconfig | 5 ++
drivers/tty/serial/Makefile | 1 +
include/linux/serial_8250.h | 5 ++
7 files changed, 134 insertions(+), 61 deletions(-)
create mode 100644 drivers/tty/serial/8250_fsl.c
--
1.7.7
^ permalink raw reply
* [PATCH 3/6] serial: export the key functions for an 8250 IRQ handler
From: Paul Gortmaker @ 2011-12-04 23:42 UTC (permalink / raw)
To: alan, gregkh, scottwood, galak; +Cc: linuxppc-dev, linux-kernel, linux-serial
In-Reply-To: <1323042143-25330-1-git-send-email-paul.gortmaker@windriver.com>
For drivers that need to construct their own IRQ handler, the
three components are seen in the current handle_port -- i.e.
Rx, Tx and modem_status.
Make these exported symbols so that "almost" 8250 UARTs can
construct their own IRQ handler with these shared components,
while working around their own unique errata issues.
The function names are given a serial8250 prefix, since they
are now entering the global namespace.
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
drivers/tty/serial/8250.c | 29 +++++++++++++++--------------
include/linux/serial_8250.h | 4 ++++
2 files changed, 19 insertions(+), 14 deletions(-)
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index a20d7eb..91afe7a 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -1300,8 +1300,6 @@ static void serial8250_stop_tx(struct uart_port *port)
}
}
-static void transmit_chars(struct uart_8250_port *up);
-
static void serial8250_start_tx(struct uart_port *port)
{
struct uart_8250_port *up =
@@ -1318,7 +1316,7 @@ static void serial8250_start_tx(struct uart_port *port)
if ((up->port.type == PORT_RM9000) ?
(lsr & UART_LSR_THRE) :
(lsr & UART_LSR_TEMT))
- transmit_chars(up);
+ serial8250_tx_chars(up);
}
}
@@ -1376,12 +1374,12 @@ static void clear_rx_fifo(struct uart_8250_port *up)
}
/*
- * receive_chars: processes according to the passed in LSR
+ * serial8250_rx_chars: processes according to the passed in LSR
* value, and returns the remaining LSR bits not handled
* by this Rx routine.
*/
-static unsigned char
-receive_chars(struct uart_8250_port *up, unsigned char lsr)
+unsigned char
+serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
{
struct tty_struct *tty = up->port.state->port.tty;
unsigned char ch;
@@ -1462,8 +1460,9 @@ ignore_char:
spin_lock(&up->port.lock);
return lsr;
}
+EXPORT_SYMBOL_GPL(serial8250_rx_chars);
-static void transmit_chars(struct uart_8250_port *up)
+void serial8250_tx_chars(struct uart_8250_port *up)
{
struct circ_buf *xmit = &up->port.state->xmit;
int count;
@@ -1500,8 +1499,9 @@ static void transmit_chars(struct uart_8250_port *up)
if (uart_circ_empty(xmit))
__stop_tx(up);
}
+EXPORT_SYMBOL_GPL(serial8250_tx_chars);
-static unsigned int check_modem_status(struct uart_8250_port *up)
+unsigned int serial8250_modem_status(struct uart_8250_port *up)
{
unsigned int status = serial_in(up, UART_MSR);
@@ -1523,6 +1523,7 @@ static unsigned int check_modem_status(struct uart_8250_port *up)
return status;
}
+EXPORT_SYMBOL_GPL(serial8250_modem_status);
/*
* This handles the interrupt from one port.
@@ -1539,10 +1540,10 @@ static void serial8250_handle_port(struct uart_8250_port *up)
DEBUG_INTR("status = %x...", status);
if (status & (UART_LSR_DR | UART_LSR_BI))
- status = receive_chars(up, status);
- check_modem_status(up);
+ status = serial8250_rx_chars(up, status);
+ serial8250_modem_status(up);
if (status & UART_LSR_THRE)
- transmit_chars(up);
+ serial8250_tx_chars(up);
spin_unlock_irqrestore(&up->port.lock, flags);
}
@@ -1780,7 +1781,7 @@ static void serial8250_backup_timeout(unsigned long data)
}
if (!(iir & UART_IIR_NO_INT))
- transmit_chars(up);
+ serial8250_tx_chars(up);
if (is_real_interrupt(up->port.irq))
serial_out(up, UART_IER, ier);
@@ -1814,7 +1815,7 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port)
unsigned int status;
unsigned int ret;
- status = check_modem_status(up);
+ status = serial8250_modem_status(up);
ret = 0;
if (status & UART_MSR_DCD)
@@ -2861,7 +2862,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
* while processing with interrupts off.
*/
if (up->msr_saved_flags)
- check_modem_status(up);
+ serial8250_modem_status(up);
if (locked)
spin_unlock(&up->port.lock);
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 1f05bbe..b44034e 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -66,6 +66,7 @@ enum {
* dependent on the 8250 driver.
*/
struct uart_port;
+struct uart_8250_port;
int serial8250_register_port(struct uart_port *);
void serial8250_unregister_port(int line);
@@ -82,6 +83,9 @@ extern void serial8250_do_set_termios(struct uart_port *port,
extern void serial8250_do_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate);
int serial8250_handle_irq(struct uart_port *port, unsigned int iir);
+unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr);
+void serial8250_tx_chars(struct uart_8250_port *up);
+unsigned int serial8250_modem_status(struct uart_8250_port *up);
extern void serial8250_set_isa_configurator(void (*v)
(int port, struct uart_port *up,
--
1.7.7
^ permalink raw reply related
* [PATCH 1/6] serial: move struct uart_8250_port from 8250.c to 8250.h
From: Paul Gortmaker @ 2011-12-04 23:42 UTC (permalink / raw)
To: alan, gregkh, scottwood, galak; +Cc: linuxppc-dev, linux-kernel, linux-serial
In-Reply-To: <1323042143-25330-1-git-send-email-paul.gortmaker@windriver.com>
Since we want to promote sharing and move away from one single
uart driver with a bunch of platform specific bugfixes all
munged into one, relocate some header like material from
the C file to the header.
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
drivers/tty/serial/8250.c | 26 --------------------------
drivers/tty/serial/8250.h | 26 ++++++++++++++++++++++++++
2 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index eeadf1b..d97628e 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -129,32 +129,6 @@ static unsigned long probe_rsa[PORT_RSA_MAX];
static unsigned int probe_rsa_count;
#endif /* CONFIG_SERIAL_8250_RSA */
-struct uart_8250_port {
- struct uart_port port;
- struct timer_list timer; /* "no irq" timer */
- struct list_head list; /* ports on this IRQ */
- unsigned short capabilities; /* port capabilities */
- unsigned short bugs; /* port bugs */
- unsigned int tx_loadsz; /* transmit fifo load size */
- unsigned char acr;
- unsigned char ier;
- unsigned char lcr;
- unsigned char mcr;
- unsigned char mcr_mask; /* mask of user bits */
- unsigned char mcr_force; /* mask of forced bits */
- unsigned char cur_iotype; /* Running I/O type */
-
- /*
- * Some bits in registers are cleared on a read, so they must
- * be saved whenever the register is read but the bits will not
- * be immediately processed.
- */
-#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
- unsigned char lsr_saved_flags;
-#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
- unsigned char msr_saved_flags;
-};
-
struct irq_info {
struct hlist_node node;
int irq;
diff --git a/drivers/tty/serial/8250.h b/drivers/tty/serial/8250.h
index 6edf4a6..ae027be 100644
--- a/drivers/tty/serial/8250.h
+++ b/drivers/tty/serial/8250.h
@@ -13,6 +13,32 @@
#include <linux/serial_8250.h>
+struct uart_8250_port {
+ struct uart_port port;
+ struct timer_list timer; /* "no irq" timer */
+ struct list_head list; /* ports on this IRQ */
+ unsigned short capabilities; /* port capabilities */
+ unsigned short bugs; /* port bugs */
+ unsigned int tx_loadsz; /* transmit fifo load size */
+ unsigned char acr;
+ unsigned char ier;
+ unsigned char lcr;
+ unsigned char mcr;
+ unsigned char mcr_mask; /* mask of user bits */
+ unsigned char mcr_force; /* mask of forced bits */
+ unsigned char cur_iotype; /* Running I/O type */
+
+ /*
+ * Some bits in registers are cleared on a read, so they must
+ * be saved whenever the register is read but the bits will not
+ * be immediately processed.
+ */
+#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
+ unsigned char lsr_saved_flags;
+#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+ unsigned char msr_saved_flags;
+};
+
struct old_serial_port {
unsigned int uart;
unsigned int baud_base;
--
1.7.7
^ permalink raw reply related
* [PATCH 2/6] serial: clean up parameter passing for 8250 Rx IRQ handling
From: Paul Gortmaker @ 2011-12-04 23:42 UTC (permalink / raw)
To: alan, gregkh, scottwood, galak; +Cc: linuxppc-dev, linux-kernel, linux-serial
In-Reply-To: <1323042143-25330-1-git-send-email-paul.gortmaker@windriver.com>
The receive_chars() was taking a pointer to a passed in LSR value
in status and knocking off bits as it processed them. But since
receive_chars isn't returning a value, we can instead pass in
a normal non-pointer value for LSR, and simply return the
residual (unprocessed) LSR once it is done.
The value in this cleanup, is that it clarifies the API of the
receive_chars prior to exporting it to other 8250-like drivers
for shared usage.
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
drivers/tty/serial/8250.c | 17 +++++++++++------
1 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index d97628e..a20d7eb 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -1375,11 +1375,16 @@ static void clear_rx_fifo(struct uart_8250_port *up)
} while (1);
}
-static void
-receive_chars(struct uart_8250_port *up, unsigned int *status)
+/*
+ * receive_chars: processes according to the passed in LSR
+ * value, and returns the remaining LSR bits not handled
+ * by this Rx routine.
+ */
+static unsigned char
+receive_chars(struct uart_8250_port *up, unsigned char lsr)
{
struct tty_struct *tty = up->port.state->port.tty;
- unsigned char ch, lsr = *status;
+ unsigned char ch;
int max_count = 256;
char flag;
@@ -1455,7 +1460,7 @@ ignore_char:
spin_unlock(&up->port.lock);
tty_flip_buffer_push(tty);
spin_lock(&up->port.lock);
- *status = lsr;
+ return lsr;
}
static void transmit_chars(struct uart_8250_port *up)
@@ -1524,7 +1529,7 @@ static unsigned int check_modem_status(struct uart_8250_port *up)
*/
static void serial8250_handle_port(struct uart_8250_port *up)
{
- unsigned int status;
+ unsigned char status;
unsigned long flags;
spin_lock_irqsave(&up->port.lock, flags);
@@ -1534,7 +1539,7 @@ static void serial8250_handle_port(struct uart_8250_port *up)
DEBUG_INTR("status = %x...", status);
if (status & (UART_LSR_DR | UART_LSR_BI))
- receive_chars(up, &status);
+ status = receive_chars(up, status);
check_modem_status(up);
if (status & UART_LSR_THRE)
transmit_chars(up);
--
1.7.7
^ permalink raw reply related
* [PATCH 5/6] serial: manually inline serial8250_handle_port
From: Paul Gortmaker @ 2011-12-04 23:42 UTC (permalink / raw)
To: alan, gregkh, scottwood, galak; +Cc: linuxppc-dev, linux-kernel, linux-serial
In-Reply-To: <1323042143-25330-1-git-send-email-paul.gortmaker@windriver.com>
Currently serial8250_handle_irq is a trivial wrapper around
serial8250_handle_port, which actually does all the work.
Since there are no other callers of serial8250_handle_port, we
can just move it inline into serial8250_handle_irq. This also
makes it more clear what functionality any custom IRQ handlers
need to provide if not using serial8250_default_handle_irq.
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
drivers/tty/serial/8250.c | 23 ++++++++---------------
1 files changed, 8 insertions(+), 15 deletions(-)
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index 9e7780d..23332cb 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -1528,10 +1528,15 @@ EXPORT_SYMBOL_GPL(serial8250_modem_status);
/*
* This handles the interrupt from one port.
*/
-static void serial8250_handle_port(struct uart_8250_port *up)
+int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
{
unsigned char status;
unsigned long flags;
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+
+ if (iir & UART_IIR_NO_INT)
+ return 0;
spin_lock_irqsave(&up->port.lock, flags);
@@ -1546,19 +1551,7 @@ static void serial8250_handle_port(struct uart_8250_port *up)
serial8250_tx_chars(up);
spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- if (!(iir & UART_IIR_NO_INT)) {
- serial8250_handle_port(up);
- return 1;
- }
-
- return 0;
+ return 1;
}
EXPORT_SYMBOL_GPL(serial8250_handle_irq);
@@ -2825,7 +2818,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
local_irq_save(flags);
if (up->port.sysrq) {
- /* serial8250_handle_port() already took the lock */
+ /* serial8250_handle_irq() already took the lock */
locked = 0;
} else if (oops_in_progress) {
locked = spin_trylock(&up->port.lock);
--
1.7.7
^ permalink raw reply related
* [PATCH 4/6] serial: make 8250 timeout use the specified IRQ handler
From: Paul Gortmaker @ 2011-12-04 23:42 UTC (permalink / raw)
To: alan, gregkh, scottwood, galak; +Cc: linuxppc-dev, linux-kernel, linux-serial
In-Reply-To: <1323042143-25330-1-git-send-email-paul.gortmaker@windriver.com>
The current 8250 timeout code duplicates the code path in
serial8250_default_handle_irq and then serial8250_handle_irq
i.e. reading iir, check for IIR_NO_INT, and then calling
serial8250_handle_port.
So the immediate thought is to replace the duplicated code
with a call to serial8250_default_handle_irq.
But this highlights a problem. We let 8250 driver variants
use their own IRQ handler via specifying their own custom
->handle_irq, but in the event of a timeout, we ignore their
handler and implicitly run serial8250_default_handle_irq instead.
So, go through the struct to get ->handle_irq and call that,
which for most will still be serial8250_default_handle_irq.
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
drivers/tty/serial/8250.c | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index 91afe7a..9e7780d 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -1738,11 +1738,8 @@ static void serial_unlink_irq_chain(struct uart_8250_port *up)
static void serial8250_timeout(unsigned long data)
{
struct uart_8250_port *up = (struct uart_8250_port *)data;
- unsigned int iir;
- iir = serial_in(up, UART_IIR);
- if (!(iir & UART_IIR_NO_INT))
- serial8250_handle_port(up);
+ up->port.handle_irq(&up->port);
mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
}
--
1.7.7
^ permalink raw reply related
* [PATCH 6/6] serial: add irq handler for Freescale 16550 errata.
From: Paul Gortmaker @ 2011-12-04 23:42 UTC (permalink / raw)
To: alan, gregkh, scottwood, galak; +Cc: linuxppc-dev, linux-kernel, linux-serial
In-Reply-To: <1323042143-25330-1-git-send-email-paul.gortmaker@windriver.com>
Sending a break on the SOC UARTs found in some MPC83xx/85xx/86xx
chips seems to cause a short lived IRQ storm (/proc/interrupts
typically shows somewhere between 300 and 1500 events). Unfortunately
this renders SysRQ over the serial console completely inoperable.
The suggested workaround in the errata is to read the Rx register,
wait one character period, and then read the Rx register again.
We achieve this by tracking the old LSR value, and on the subsequent
interrupt event after a break, we don't read LSR, instead we just
read the RBR again and return immediately.
The "fsl,ns16550" is used in the compatible field of the serial
device to mark UARTs known to have this issue.
Thanks to Scott Wood for providing the errata data which led to
a much cleaner fix.
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
arch/powerpc/kernel/legacy_serial.c | 3 ++
drivers/tty/serial/8250_fsl.c | 63 +++++++++++++++++++++++++++++++++++
drivers/tty/serial/Kconfig | 5 +++
drivers/tty/serial/Makefile | 1 +
include/linux/serial_8250.h | 1 +
5 files changed, 73 insertions(+), 0 deletions(-)
create mode 100644 drivers/tty/serial/8250_fsl.c
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index c7b5afe..3fea368 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -441,6 +441,9 @@ static void __init fixup_port_irq(int index,
return;
port->irq = virq;
+
+ if (of_device_is_compatible(np, "fsl,ns16550"))
+ port->handle_irq = fsl8250_handle_irq;
}
static void __init fixup_port_pio(int index,
diff --git a/drivers/tty/serial/8250_fsl.c b/drivers/tty/serial/8250_fsl.c
new file mode 100644
index 0000000..f4d3c47
--- /dev/null
+++ b/drivers/tty/serial/8250_fsl.c
@@ -0,0 +1,63 @@
+#include <linux/serial_reg.h>
+#include <linux/serial_8250.h>
+
+#include "8250.h"
+
+/*
+ * Freescale 16550 UART "driver", Copyright (C) 2011 Paul Gortmaker.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This isn't a full driver; it just provides an alternate IRQ
+ * handler to deal with an errata. Everything else is just
+ * using the bog standard 8250 support.
+ *
+ * We follow code flow of serial8250_default_handle_irq() but add
+ * a check for a break and insert a dummy read on the Rx for the
+ * immediately following IRQ event.
+ *
+ * We re-use the already existing "bug handling" lsr_saved_flags
+ * field to carry the "what we just did" information from the one
+ * IRQ event to the next one.
+ */
+
+int fsl8250_handle_irq(struct uart_port *port)
+{
+ unsigned char lsr, orig_lsr;
+ unsigned long flags;
+ unsigned int iir;
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ iir = port->serial_in(port, UART_IIR);
+ if (iir & UART_IIR_NO_INT) {
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ return 0;
+ }
+
+ /* This is the WAR; if last event was BRK, then read and return */
+ if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) {
+ up->lsr_saved_flags &= ~UART_LSR_BI;
+ port->serial_in(port, UART_RX);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ return 1;
+ }
+
+ lsr = orig_lsr = up->port.serial_in(&up->port, UART_LSR);
+
+ if (lsr & (UART_LSR_DR | UART_LSR_BI))
+ lsr = serial8250_rx_chars(up, lsr);
+
+ serial8250_modem_status(up);
+
+ if (lsr & UART_LSR_THRE)
+ serial8250_tx_chars(up);
+
+ up->lsr_saved_flags = orig_lsr;
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ return 1;
+}
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 925a1e5..aa46993 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -97,6 +97,11 @@ config SERIAL_8250_PNP
This builds standard PNP serial support. You may be able to
disable this feature if you only need legacy serial support.
+config SERIAL_8250_FSL
+ bool
+ depends on SERIAL_8250 && PPC
+ default PPC
+
config SERIAL_8250_HP300
tristate
depends on SERIAL_8250 && HP300
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index e10cf5b..fb187a3 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
+obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o
obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o
obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index b44034e..8f012f8 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -82,6 +82,7 @@ extern void serial8250_do_set_termios(struct uart_port *port,
struct ktermios *termios, struct ktermios *old);
extern void serial8250_do_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate);
+extern int fsl8250_handle_irq(struct uart_port *port);
int serial8250_handle_irq(struct uart_port *port, unsigned int iir);
unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr);
void serial8250_tx_chars(struct uart_8250_port *up);
--
1.7.7
^ permalink raw reply related
* Re: [PATCHv5] atomic: add *_dec_not_zero
From: H. Peter Anvin @ 2011-12-05 0:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linux-m32r-ja, linux-mips, linux-ia64, linux-doc, Heiko Carstens,
Randy Dunlap, Paul Mackerras, sparclinux, Sven Eckelmann,
linux-arch, linux-s390, Russell King - ARM Linux, Arnd Bergma nn,
linux-hexagon, Helge Deller, x86, James E.J. Bottomley,
Ingo Molnar, Matt Turner, Fenghua Yu, user-mode-linux-devel,
Jeff Dike, linux-alpha, Chris Metcalf, Tony Luck, Ivan Kokshaysky,
Thomas Gleixner, linux-arm-kernel, Richard Henderson, linux-m32r,
linux-parisc, b.a.t.m.a.n, linux-kernel, Ralf Baechle,
David S. Miller, Kyle McMartin, Richard Weinberger,
Martin Schwidefsky, linux390, Andrew Morton, linuxppc-dev,
Hirokazu Takata
In-Reply-To: <1323038515.11728.26.camel@pasglop>
On 12/04/2011 02:41 PM, Benjamin Herrenschmidt wrote:
>
> I agree with Russell, his approach is a lot easier to maintain long run,
> we should even consider converting existing definitions.
>
Thirded.
-hpa
--
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel. I don't speak on their behalf.
^ permalink raw reply
* Re: [PATCH-RFC 08/10] powerpc: switch to GENERIC_PCI_IOMAP
From: Michael S. Tsirkin @ 2011-12-05 6:03 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <1323031921.11728.25.camel@pasglop>
On Mon, Dec 05, 2011 at 07:52:01AM +1100, Benjamin Herrenschmidt wrote:
> On Sun, 2011-12-04 at 12:48 +0200, Michael S. Tsirkin wrote:
> > On Thu, Nov 24, 2011 at 10:19:54PM +0200, Michael S. Tsirkin wrote:
> > > powerpc copied pci_iomap from generic code, probably to avoid
> > > pulling the rest of iomap.c in. Since that's in
> > > a separate file now, we can reuse the common implementation.
> > >
> > > The only difference is handling of nocache flag,
> > > that turns out to be done correctly by the
> > > generic code since arch/powerpc/include/asm/io.h
> > > defines ioremap_nocache same as ioremap.
> > >
> > > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> >
> >
> > Sorry to nag, any ACKs/NACKs on the powerpc changes?
> > I intend to send this to Linus if there are no
> > objections. Thanks!
>
> Ah sorry, forgot about that. Do you have a git tree I can pull to do
> quick test ?
Yes.
git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git linux-next
Thanks!
> No objection in principle.
>
> Cheers,
> Ben.
^ permalink raw reply
* RE: [PATCH][RFC] fsldma: fix performance degradation by optimizing spinlock use.
From: Shi Xuelin-B29237 @ 2011-12-05 6:11 UTC (permalink / raw)
To: Ira W. Snyder
Cc: vinod.koul@intel.com, dan.j.williams@intel.com,
linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org,
Li Yang-R58472
In-Reply-To: <20111202171334.GA19677@ovro.caltech.edu>
Hi Iris,
>Remember, without barriers, CPU-B can observe CPU-A's memory accesses in *=
any possible order*. Memory accesses are not guaranteed to be *complete* by=
=20
>the time fsl_dma_tx_submit() returns!
fsl_dma_tx_submit is enclosed by spin_lock_irqsave/spin_unlock_irqrestore, =
when this function returns, I believe the memory access are completed. spin=
_unlock_irqsave is an implicit memory barrier and guaranteed this.
Thanks,
Forrest
-----Original Message-----
From: Ira W. Snyder [mailto:iws@ovro.caltech.edu]=20
Sent: 2011=1B$BG/=1B(B12=1B$B7n=1B(B3=1B$BF|=1B(B 1:14
To: Shi Xuelin-B29237
Cc: vinod.koul@intel.com; dan.j.williams@intel.com; linuxppc-dev@lists.ozla=
bs.org; linux-kernel@vger.kernel.org; Li Yang-R58472
Subject: Re: [PATCH][RFC] fsldma: fix performance degradation by optimizing=
spinlock use.
On Fri, Dec 02, 2011 at 03:47:27AM +0000, Shi Xuelin-B29237 wrote:
> Hi Iris,
>=20
> >I'm convinced that "smp_rmb()" is needed when removing the spinlock.=20
> >As noted, Documentation/memory-barriers.txt says that stores on one CPU =
can be observed by another CPU in a different order.
> >Previously, there was an UNLOCK (in fsl_dma_tx_submit) followed by a=20
> >LOCK (in fsl_tx_status). This provided a "full barrier", forcing the ope=
rations to complete correctly when viewed by the second CPU.
>=20
> I do not agree this smp_rmb() works here. Because when this smp_rmb() exe=
cuted and begin to read chan->common.cookie, you still cannot avoid the ord=
er issue. Something like one is reading old value, but another CPU is updat=
ing the new value.=20
>=20
> My point is here the order is not important for the DMA decision.
> Completed DMA tx is decided as not complete is not a big deal, because ne=
xt time it will be OK.
>=20
> I believe there is no case that could cause uncompleted DMA tx is decided=
as completed, because the fsl_tx_status is called after fsl_dma_tx_submit =
for a specific cookie. If you can give me an example here, I will agree wit=
h you.
>=20
According to memory-barriers.txt, writes to main memory may be observed in =
any order if memory barriers are not used. This means that writes can appea=
r to happen in a different order than they were issued by the CPU.
Citing from the text:
> There are certain things that the Linux kernel memory barriers do not gua=
rantee:
>
> (*) There is no guarantee that any of the memory accesses specified befo=
re a
> memory barrier will be _complete_ by the completion of a memory barr=
ier
> instruction; the barrier can be considered to draw a line in that CP=
U's
> access queue that accesses of the appropriate type may not cross.
Also:
> Without intervention, CPU 2 may perceive the events on CPU 1 in some=20
> effectively random order, despite the write barrier issued by CPU 1:
Also:
> When dealing with CPU-CPU interactions, certain types of memory=20
> barrier should always be paired. A lack of appropriate pairing is almost=
certainly an error.
>
> A write barrier should always be paired with a data dependency barrier=20
> or read barrier, though a general barrier would also be viable.
Therefore, in an SMP system, the following situation can happen.
descriptor->cookie =3D 2
chan->common.cookie =3D 1
chan->completed_cookie =3D 1
This occurs when CPU-A calls fsl_dma_tx_submit() and then CPU-B calls
dma_async_is_complete() ***after*** CPU-B has observed the write to
descriptor->cookie, and ***before*** before CPU-B has observed the write=20
descriptor->to
chan->common.cookie.
Remember, without barriers, CPU-B can observe CPU-A's memory accesses in *a=
ny possible order*. Memory accesses are not guaranteed to be *complete* by =
the time fsl_dma_tx_submit() returns!
With the above values, dma_async_is_complete() returns DMA_COMPLETE. This i=
s incorrect: the DMA is still in progress. The required invariant
chan->common.cookie >=3D descriptor->cookie has not been met.
By adding an smp_rmb(), I force CPU-B to stall until *both* stores in
fsl_dma_tx_submit() (descriptor->cookie and chan->common.cookie) actually h=
it main memory. This avoids the above situation: all CPU's observe
descriptor->cookie and chan->common.cookie to update in sync with each
other.
Is this unclear in any way?
Please run your test with the smp_rmb() and measure the performance impact.
Ira
^ permalink raw reply
* Re: [PATCH 3/3] mtd/nand : workaround for Freescale FCM to support large-page Nand chip
From: Artem Bityutskiy @ 2011-12-05 6:47 UTC (permalink / raw)
To: shuo.liu
Cc: Artem.Bityutskiy, linuxppc-dev, linux-kernel, linux-mtd,
scottwood, akpm, dwmw2
In-Reply-To: <1322973098-2528-3-git-send-email-shuo.liu@freescale.com>
On Sun, 2011-12-04 at 12:31 +0800, shuo.liu@freescale.com wrote:
> + /*
> + * Freescale FCM controller has a 2K size limitation of buffer
> + * RAM, so elbc_fcm_ctrl->buffer have to be used if writesize
> + * of chip is greater than 2048.
> + * We malloc a large enough buffer (maximum page size is 16K).
> + */
> + elbc_fcm_ctrl->buffer = kmalloc(1024 * 16 + 1024, GFP_KERNEL);
> + if (!elbc_fcm_ctrl->buffer) {
> + dev_err(dev, "failed to allocate memory\n");
> + mutex_unlock(&fsl_elbc_nand_mutex);
> + ret = -ENOMEM;
> + goto err;
> + }
Sorry for returning to this again and agian - I do not have time to dig
suggest you the right solutions on the one hand, you do not provide me a
good answer on the other hand (or I forgot?).
16KiB pages do not even exist I believe. And you kmalloc 33KiB or RAM
although in most cases you need only 5KiB. I think this is wrong - what
is the very strong reason of wasting RAM you have?
Why you cannot allocate exactly the required amount of RAM after
'nand_scan_ident()' finishes and you know the page size?
Artem.
^ permalink raw reply
* Re: [PATCH 1/3] mtd/nand : use elbc_fcm_ctrl->oob to set FPAR_MS bit of FPAR
From: Artem Bityutskiy @ 2011-12-05 6:50 UTC (permalink / raw)
To: shuo.liu
Cc: Artem.Bityutskiy, linuxppc-dev, linux-kernel, linux-mtd,
scottwood, akpm, dwmw2
In-Reply-To: <1322973098-2528-1-git-send-email-shuo.liu@freescale.com>
On Sun, 2011-12-04 at 12:31 +0800, shuo.liu@freescale.com wrote:
> From: Liu Shuo <b35362@freescale.com>
>
> On both of large-page chip and small-page chip, we always should use
> 'elbc_fcm_ctrl->oob' to set the FPAR_LP_MS/FPAR_SP_MS bit of FPAR, don't
> use a overflowed 'column' to set it.
>
> Signed-off-by: Liu Shuo <b35362@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
Pushed patches 1 and 2 to l2-mtd-2.6.git, thanks!
Artem.
^ permalink raw reply
* Re: [PATCH 1/1] Punch a hole in /dev/mem for librtas
From: Segher Boessenkool @ 2011-12-05 7:58 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linuxppc-dev, sbest, Sukadev Bhattiprolu, paulus, anton
In-Reply-To: <1323040701.11728.27.camel@pasglop>
>>> +static inline int page_is_rtas_user_buf(unsigned long pfn)
>>> +{
>>> + unsigned long paddr = (pfn << PAGE_SHIFT);
>>> + if (paddr >= rtas_rmo_buf && paddr < (rtas_rmo_buf +
>>> RTAS_RMOBUF_MAX))
>>
>> It probably cannot overflow with actual values of rtas_rmo_buf
>> and RTAS_RMOBUF_MAX, but otherwise it is an incorrect test;
>> please write
>>
>> if (paddr >= rtas_rmo_buf && paddr - rtas_rmo_buf < RTAS_RMOBUF_MAX)
>>
>> (and, _MAX? Shouldn't it be the actual size here? Or is _MAX
>> just a confusing name :-) )
>
> The original code is a lot more readable and perfectly correct for all
> possible values of rtas_rmo_buf :-)
You have to consider those possible values before you see it cannot
overflow. So no, it's a lot _less_ readable IMHO.
It's also a dangerous habit to get into. Just say no :-)
Segher
^ permalink raw reply
* Re: Re: Re: [PATCHv5] atomic: add *_dec_not_zero
From: Sven Eckelmann @ 2011-12-05 7:57 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linux-m32r-ja, linux-mips, linux-ia64, linux-doc, Heiko Carstens,
Randy Dunlap, Paul Mackerras, H. Peter Anvin, sparclinux,
linux-arch, linux-s390, Russell King - ARM Linux, Arnd Bergma nn,
linux-hexagon, Helge Deller, x86, James E.J. Bottomley,
linux-arm-kernel, Ingo Molnar, Matt Turner, Fenghua Yu,
user-mode-linux-devel, Jeff Dike, linux-alpha, Chris Metcalf,
Tony Luck, Ivan Kokshaysky, fradead.org, Thomas Gleixner,
Richard Henderson, linux-m32r, linux-parisc, b.a.t.m.a.n,
linux-kernel, Ralf Baechle, David S. Miller, Kyle McMartin,
Richard Weinberger, Martin Schwidefsky, linux390, Andrew Morton,
linuxppc-dev, Hirokazu Takata
In-Reply-To: <1323038515.11728.26.camel@pasglop>
[-- Attachment #1: Type: text/plain, Size: 1486 bytes --]
On Monday 05 December 2011 09:41:55 Benjamin Herrenschmidt wrote:
> On Sun, 2011-12-04 at 22:18 +0000, Russell King - ARM Linux wrote:
>
> .../...
>
> > And really, I believe it would be a good cleanup if all the standard
> > definitions for atomic64 ops (like atomic64_add_negative) were also
> > defined in include/linux/atomic.h rather than individually in every
> > atomic*.h header throughout the kernel source, except where an arch
> > wants to explicitly override it. Yet again, virtually all architectures
> > define these in exactly the same way.
> >
> > We have more than enough code in arch/ for any architecture to worry
> > about, we don't need schemes to add more when there's simple and
> > practical solutions to avoiding doing so if the right design were
> > chosen (preferably from the outset.)
> >
> > So, I'm not going to offer my ack for a change which I don't believe
> > is the correct approach.
>
> I agree with Russell, his approach is a lot easier to maintain long run,
> we should even consider converting existing definitions.
I would rather go with "the existing definitions have to converted" and this
means "not by this patch". At the moment, the atomic64 stuff exist only as
separate generic or arch specific implementation. It is fine that Russell King
noticed that people like Arun Sharma did a lot of work to made it true for
atomic_t, but atomic64_t is a little bit different right now (at least as I
understand it).
Kind regards,
Sven
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: Re: Re: [PATCHv5] atomic: add *_dec_not_zero
From: Benjamin Herrenschmidt @ 2011-12-05 8:26 UTC (permalink / raw)
To: Sven Eckelmann
Cc: linux-m32r-ja, linux-mips, linux-ia64, linux-doc, Heiko Carstens,
Randy Dunlap, Paul Mackerras, H. Peter Anvin, sparclinux,
linux-arch, linux-s390, Russell King - ARM Linux, Arnd Bergma nn,
linux-hexagon, Helge Deller, x86, James E.J. Bottomley,
Ingo Molnar, Matt Turner, Fenghua Yu, user-mode-linux-devel,
Jeff Dike, linux-alpha, Chris Metcalf, Tony Luck, Ivan Kokshaysky,
Thomas Gleixner, linux-arm-kernel, Richard Henderson, linux-m32r,
linux-parisc, b.a.t.m.a.n, linux-kernel, Ralf Baechle,
David S. Miller, Kyle McMartin, Richard Weinberger,
Martin Schwidefsky, linux390, Andrew Morton, linuxppc-dev,
Hirokazu Takata
In-Reply-To: <3836467.I5Tqg6MFf9@sven-laptop.home.narfation.org>
On Mon, 2011-12-05 at 08:57 +0100, Sven Eckelmann wrote:
> On Monday 05 December 2011 09:41:55 Benjamin Herrenschmidt wrote:
> > On Sun, 2011-12-04 at 22:18 +0000, Russell King - ARM Linux wrote:
> >
> > .../...
> >
> > > And really, I believe it would be a good cleanup if all the standard
> > > definitions for atomic64 ops (like atomic64_add_negative) were also
> > > defined in include/linux/atomic.h rather than individually in every
> > > atomic*.h header throughout the kernel source, except where an arch
> > > wants to explicitly override it. Yet again, virtually all architectures
> > > define these in exactly the same way.
> > >
> > > We have more than enough code in arch/ for any architecture to worry
> > > about, we don't need schemes to add more when there's simple and
> > > practical solutions to avoiding doing so if the right design were
> > > chosen (preferably from the outset.)
> > >
> > > So, I'm not going to offer my ack for a change which I don't believe
> > > is the correct approach.
> >
> > I agree with Russell, his approach is a lot easier to maintain long run,
> > we should even consider converting existing definitions.
>
> I would rather go with "the existing definitions have to converted" and this
> means "not by this patch".
Right. I didn't suggest -you- had to do it as a pre-req to your patch.
> At the moment, the atomic64 stuff exist only as
> separate generic or arch specific implementation. It is fine that Russell King
> noticed that people like Arun Sharma did a lot of work to made it true for
> atomic_t, but atomic64_t is a little bit different right now (at least as I
> understand it).
Cheers,
Ben.
^ permalink raw reply
* Re: oprofile callgraph support missing for common cpus
From: Joakim Tjernlund @ 2011-12-05 8:50 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Robert Richter, linuxppc-dev, Andy Fleming, oprofile-list
In-Reply-To: <1322198672.32635.24.camel@pasglop>
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote on 2011/11/25 06:24:32:
>
> On Fri, 2011-11-18 at 09:22 +0100, Joakim Tjernlund wrote:
>
> > I forgot to ask, oprofile mentions setting -no-omit-framepointer to get
> > correct backtrace but I cannot turn on frame pointers for the ppc kernel.
> > Isn't frame pointers needed for pcc? what about user space?
>
> PowerPC always has frame pointers, ignore that :-)
A bit late but consider this:
int leaf(int x)
{
return x+3;
}
which yields(with gcc -O2 -S):
.file "leaf.c"
.section ".text"
.align 2
.globl leaf
.type leaf, @function
leaf:
addi 3,3,3
blr
.size leaf, .-leaf
.section .note.GNU-stack,"",@progbits
.ident "GCC: (GNU) 3.4.6 (Gentoo 3.4.6-r2, ssp-3.4.6-1.0, pie-8.7.9)"
Here there is with frame pointer(I guess that the messing around with r11 and r31 is a defect?):
(With gcc -O2 -S -fno-omit-frame-pointer)
.file "leaf.c"
.section ".text"
.align 2
.globl leaf
.type leaf, @function
leaf:
stwu 1,-16(1)
addi 3,3,3
lwz 11,0(1)
stw 31,12(1)
mr 31,1
lwz 31,-4(11)
mr 1,11
blr
.size leaf, .-leaf
.section .note.GNU-stack,"",@progbits
.ident "GCC: (GNU) 3.4.6 (Gentoo 3.4.6-r2, ssp-3.4.6-1.0, pie-8.7.9)"
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox