diff options
author | David S. Miller <davem@davemloft.net> | 2010-03-03 12:06:03 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-03-03 12:06:03 -0500 |
commit | 8a4fd1e4922413cfdfa6c51a59efb720d904a5eb (patch) | |
tree | 3e46821fac9d3de604466b55345c2b267d157355 /arch/sparc | |
parent | c7d5a0050773e98d1094eaa9f2a1a793fafac300 (diff) |
sparc64: Make prom entry spinlock NMI safe.
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>
Diffstat (limited to 'arch/sparc')
-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 | } |