Chaskiel M Grundman <cg2v+@andrew.cmu.edu> writes:
>
> I have encountered a problem on several machines that causes the machine
> to lock up when gpm retakes control of the ps2 mouse device after X is
> shut down, but only when the system is running an SMP kernel. I could
> not find any reports of similar problems, which makes me wonder if I
> might be doing something wrong.... Any ideas? Any other info I should
> provide?
Linus:
What a coincidence! I just got bitten by this last night while
chasing down a problem with a wheel mouse. For some reason,
Chaskiel's call trace seems to be missing the additional
"aux_write_ack" call made by "handle_kbd_event"---maybe his compiler
automagically optimized it away or something---but it looks like
exactly the same problem, except I saw "keyboard_interrupt (grabs
spinlock) -> handle_kbd_event -> handle_mouse_event -> aux_write_ack
(grabs spinlock)".
Anyway, here's the message I composed before reading Chaskiel's
report:
There's an insidious spinlock hang hidden in "drivers/char/pc_keyb.c".
"handle_mouse_event" is called with the "kbd_controller_lock" held. If it
sees an "AUX_RECONNECT" scancode on the wire, it tries to---according
to the comments---"ping the mouse". Unfortunately, it does this using
"aux_write_ack" which tries to grab the lock again.
I triggered this while playing protocol games with a new wheel mouse.
Presumably, anyone who plugs a PS/2 mouse into a running SMP machine
will hang their machine; and a flakey mouse that generates spurious
AUX_RECONNECT messages (or even a working mouse that happens to generate
that scancode validly) would lead to mysterious lockups, I think.
Anyway, here's a patch. I've tested this on 2.4.0-test5, but it should
work fine on test7, too.
Kevin <buhr@stat.wisc.edu>
--- linux-2.4.0-test7/drivers/char/pc_keyb.c Fri Jul 21 00:26:15 2000
+++ linux-2.4.0-test7-local/drivers/char/pc_keyb.c Sat Aug 26 00:25:25 2000
@@ -62,6 +62,7 @@
static void kbd_write_output_w(int data);
#ifdef CONFIG_PSMOUSE
static void aux_write_ack(int val);
+static void __aux_write_ack(int val);
#endif
spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
@@ -404,7 +405,7 @@
}
else if(scancode == AUX_RECONNECT){
queue->head = queue->tail = 0; /* Flush input queue */
- aux_write_ack(AUX_ENABLE_DEV); /* ping the mouse :) */
+ __aux_write_ack(AUX_ENABLE_DEV); /* ping the mouse :) */
return;
}
@@ -822,11 +823,8 @@
/*
* Send a byte to the mouse & handle returned ack
*/
-static void aux_write_ack(int val)
+static void __aux_write_ack(int val)
{
- unsigned long flags;
-
- spin_lock_irqsave(&kbd_controller_lock, flags);
kb_wait();
kbd_write_command(KBD_CCMD_WRITE_MOUSE);
kb_wait();
@@ -834,6 +832,14 @@
/* we expect an ACK in response. */
mouse_reply_expected++;
kb_wait();
+}
+
+static void aux_write_ack(int val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&kbd_controller_lock, flags);
+ __aux_write_ack(val);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Thu Aug 31 2000 - 21:00:17 EST