PATCH: psaux lockups on SMP 2.4.0-test*

From: Kevin Buhr (
Date: Sat Aug 26 2000 - 11:17:48 EST

Chaskiel M Grundman <> 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?


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

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 <>

--- 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);
 static void aux_write_ack(int val);
+static void __aux_write_ack(int val);
 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 :) */
@@ -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);
@@ -834,6 +832,14 @@
         /* we expect an ACK in response. */
+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
Please read the FAQ at

This archive was generated by hypermail 2b29 : Thu Aug 31 2000 - 21:00:17 EST