diff options
author | David S. Miller <davem@davemloft.net> | 2010-03-03 12:06:03 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-04-01 19:01:19 -0400 |
commit | 6b485cd307ba56876d20b6d443a02f3cc5bbb7a2 (patch) | |
tree | 2b158efc315b22ea2212fb71ce8c0405d72a8ab9 | |
parent | 38b5c1269e7c1582d25a2ffd71d9289d8520d9b8 (diff) |
sparc64: Make prom entry spinlock NMI safe.
[ Upstream commit 8a4fd1e4922413cfdfa6c51a59efb720d904a5eb ]
If we do something like try to print to the OF console from an NMI
while we're already in OpenFirmware, we'll deadlock on the spinlock.
Use a raw spinlock and disable NMIs when we take it.
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | arch/sparc/prom/p1275.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/arch/sparc/prom/p1275.c b/arch/sparc/prom/p1275.c index 4b7c937bba61..2d8b70d397f1 100644 --- a/arch/sparc/prom/p1275.c +++ b/arch/sparc/prom/p1275.c | |||
@@ -32,10 +32,9 @@ extern void prom_cif_interface(void); | |||
32 | extern void prom_cif_callback(void); | 32 | extern void prom_cif_callback(void); |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * This provides SMP safety on the p1275buf. prom_callback() drops this lock | 35 | * This provides SMP safety on the p1275buf. |
36 | * to allow recursuve acquisition. | ||
37 | */ | 36 | */ |
38 | DEFINE_SPINLOCK(prom_entry_lock); | 37 | DEFINE_RAW_SPINLOCK(prom_entry_lock); |
39 | 38 | ||
40 | long p1275_cmd(const char *service, long fmt, ...) | 39 | long p1275_cmd(const char *service, long fmt, ...) |
41 | { | 40 | { |
@@ -47,7 +46,9 @@ long p1275_cmd(const char *service, long fmt, ...) | |||
47 | 46 | ||
48 | p = p1275buf.prom_buffer; | 47 | p = p1275buf.prom_buffer; |
49 | 48 | ||
50 | spin_lock_irqsave(&prom_entry_lock, flags); | 49 | raw_local_save_flags(flags); |
50 | raw_local_irq_restore(PIL_NMI); | ||
51 | raw_spin_lock(&prom_entry_lock); | ||
51 | 52 | ||
52 | p1275buf.prom_args[0] = (unsigned long)p; /* service */ | 53 | p1275buf.prom_args[0] = (unsigned long)p; /* service */ |
53 | strcpy (p, service); | 54 | strcpy (p, service); |
@@ -139,7 +140,8 @@ long p1275_cmd(const char *service, long fmt, ...) | |||
139 | va_end(list); | 140 | va_end(list); |
140 | x = p1275buf.prom_args [nargs + 3]; | 141 | x = p1275buf.prom_args [nargs + 3]; |
141 | 142 | ||
142 | spin_unlock_irqrestore(&prom_entry_lock, flags); | 143 | raw_spin_unlock(&prom_entry_lock); |
144 | raw_local_irq_restore(flags); | ||
143 | 145 | ||
144 | return x; | 146 | return x; |
145 | } | 147 | } |