vt: Fix deadlock on scroll-lock
PATCH v2 1/1 vt: Fix deadlock on scroll-lock
From: Alan Cox <[email protected]>
Fixing the locking accidentally replaced a race in the scroll lock handling with a deadlock. Turn it back into a race for now.
The basic problem is that there are two paths into the tty stop/start helpers. One via the tty layer ^S/^Q handling where we need to take the kbd_event_lock and one via the special keyboard handler for fn_hold where we already hold it. Probably we need to split out into a separate LED lock but for now just go back to the race as it's a bit close to release.
Signed-off-by Alan Cox <[email protected]>
---
drivers/tty/vt/keyboard.c | 26 +++++++++++++++++++------- 1 files changed, 19 insertions(+), 7 deletions(-)
drivers/tty/vt/keyboard.c +19 -7
@@ -1085,15 +1085,21 @@ void vt_set_led_state(int console, int leds)* * Handle console start. This is a wrapper for the VT layer * so that we can keep kbd knowledge internal +* +* FIXME: We eventually need to hold the kbd lock here to protect +* the LED updating. We can't do it yet because fn_hold calls stop_tty +* and start_tty under the kbd_event_lock, while normal tty paths +* don't hold the lock. We probably need to split out an LED lock +* but not during an -rc release! */ void vt_kbd_con_start (int console) {struct kbd_struct * kbd = kbd_table + console; -unsigned long flags; -spin_lock_irqsave (&kbd_event_lock, flags); +/* unsigned long flags; */ +/* spin_lock_irqsave(&kbd_event_lock, flags); */ clr_vc_kbd_led (kbd,VC_SCROLLOCK );set_leds (); -spin_unlock_irqrestore (&kbd_event_lock, flags); +/* spin_unlock_irqrestore(&kbd_event_lock, flags); */ }/**
@@ -1102,22 +1108,28 @@ void vt_kbd_con_start(int console)* * Handle console stop. This is a wrapper for the VT layer * so that we can keep kbd knowledge internal +* +* FIXME: We eventually need to hold the kbd lock here to protect +* the LED updating. We can't do it yet because fn_hold calls stop_tty +* and start_tty under the kbd_event_lock, while normal tty paths +* don't hold the lock. We probably need to split out an LED lock +* but not during an -rc release! */ void vt_kbd_con_stop (int console) {struct kbd_struct * kbd = kbd_table + console; -unsigned long flags; -spin_lock_irqsave (&kbd_event_lock, flags); +/* unsigned long flags; */ +/* spin_lock_irqsave(&kbd_event_lock, flags); */ set_vc_kbd_led (kbd,VC_SCROLLOCK );set_leds (); -spin_unlock_irqrestore (&kbd_event_lock, flags); +/* spin_unlock_irqrestore(&kbd_event_lock, flags); */ }/* * This is the tasklet that updates LED state on all keyboards * attached to the box. The reason we use tasklet is that we * need to handle the scenario when keyboard handler is not -* registered yet but we already getting updates form VT to +* registered yet but we already getting updates from the VT to * update led state. */ static void kbd_bh (unsigned long dummy)