summaryrefslogtreecommitdiff
path: root/arch/powerpc
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2007-12-12 14:58:12 +1100
committerPaul Mackerras <paulus@samba.org>2007-12-14 15:50:46 +1100
commit88f0178e6ec2c73167de973e4af86905b4dbfd45 (patch)
treefa55f0649178d9c87e0608f9ee3560938f931e7a /arch/powerpc
parentda8cadb31b82c9d41fc593c8deab6aa20b162d6b (diff)
downloadlinux-3.10-88f0178e6ec2c73167de973e4af86905b4dbfd45.tar.gz
linux-3.10-88f0178e6ec2c73167de973e4af86905b4dbfd45.tar.bz2
linux-3.10-88f0178e6ec2c73167de973e4af86905b4dbfd45.zip
[POWERPC] iSeries: don't printk with HV spinlock held
Printk was observed to hang during module unload due to a limited window of characters that may be sent to the hypervisor. The window only reexpands when we receive an ack from the HV and the spinlock here prevents us from ever processing that ack. This fixes it by dropping the lock before doing the printk, then looping back to the top to reacquire the lock. Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/iseries/lpevents.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
index 34bdbbe3ce5..275f4944983 100644
--- a/arch/powerpc/platforms/iseries/lpevents.c
+++ b/arch/powerpc/platforms/iseries/lpevents.c
@@ -121,6 +121,7 @@ void process_hvlpevents(void)
{
struct HvLpEvent * event;
+ restart:
/* If we have recursed, just return */
if (!spin_trylock(&hvlpevent_queue.hq_lock))
return;
@@ -146,8 +147,20 @@ void process_hvlpevents(void)
if (event->xType < HvLpEvent_Type_NumTypes &&
lpEventHandler[event->xType])
lpEventHandler[event->xType](event);
- else
- printk(KERN_INFO "Unexpected Lp Event type=%d\n", event->xType );
+ else {
+ u8 type = event->xType;
+
+ /*
+ * Don't printk in the spinlock as printk
+ * may require ack events form the HV to send
+ * any characters there.
+ */
+ hvlpevent_clear_valid(event);
+ spin_unlock(&hvlpevent_queue.hq_lock);
+ printk(KERN_INFO
+ "Unexpected Lp Event type=%d\n", type);
+ goto restart;
+ }
hvlpevent_clear_valid(event);
} else if (hvlpevent_queue.hq_overflow_pending)