diff options
author | Alan Cox <alan@linux.intel.com> | 2012-05-01 11:12:19 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-01 14:01:28 -0400 |
commit | 84f904ecd3aa2ccb5779b815b69c1cb592f07bb5 (patch) | |
tree | eeaf995be900b9a1beb2be751224a97cfadf422d /drivers/tty/vt | |
parent | 69964ea4c7b68c9399f7977aa5b9aa6539a6a98a (diff) |
vt: Fix deadlock on scroll-lock
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.
Reported-by: Clemens Ladisch <clemens@ladisch.de>
Cc: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/vt')
-rw-r--r-- | drivers/tty/vt/keyboard.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 86dd1e302bb3..29ca20dbd335 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c | |||
@@ -1085,15 +1085,21 @@ void vt_set_led_state(int console, int leds) | |||
1085 | * | 1085 | * |
1086 | * Handle console start. This is a wrapper for the VT layer | 1086 | * Handle console start. This is a wrapper for the VT layer |
1087 | * so that we can keep kbd knowledge internal | 1087 | * so that we can keep kbd knowledge internal |
1088 | * | ||
1089 | * FIXME: We eventually need to hold the kbd lock here to protect | ||
1090 | * the LED updating. We can't do it yet because fn_hold calls stop_tty | ||
1091 | * and start_tty under the kbd_event_lock, while normal tty paths | ||
1092 | * don't hold the lock. We probably need to split out an LED lock | ||
1093 | * but not during an -rc release! | ||
1088 | */ | 1094 | */ |
1089 | void vt_kbd_con_start(int console) | 1095 | void vt_kbd_con_start(int console) |
1090 | { | 1096 | { |
1091 | struct kbd_struct * kbd = kbd_table + console; | 1097 | struct kbd_struct * kbd = kbd_table + console; |
1092 | unsigned long flags; | 1098 | /* unsigned long flags; */ |
1093 | spin_lock_irqsave(&kbd_event_lock, flags); | 1099 | /* spin_lock_irqsave(&kbd_event_lock, flags); */ |
1094 | clr_vc_kbd_led(kbd, VC_SCROLLOCK); | 1100 | clr_vc_kbd_led(kbd, VC_SCROLLOCK); |
1095 | set_leds(); | 1101 | set_leds(); |
1096 | spin_unlock_irqrestore(&kbd_event_lock, flags); | 1102 | /* spin_unlock_irqrestore(&kbd_event_lock, flags); */ |
1097 | } | 1103 | } |
1098 | 1104 | ||
1099 | /** | 1105 | /** |
@@ -1102,22 +1108,28 @@ void vt_kbd_con_start(int console) | |||
1102 | * | 1108 | * |
1103 | * Handle console stop. This is a wrapper for the VT layer | 1109 | * Handle console stop. This is a wrapper for the VT layer |
1104 | * so that we can keep kbd knowledge internal | 1110 | * so that we can keep kbd knowledge internal |
1111 | * | ||
1112 | * FIXME: We eventually need to hold the kbd lock here to protect | ||
1113 | * the LED updating. We can't do it yet because fn_hold calls stop_tty | ||
1114 | * and start_tty under the kbd_event_lock, while normal tty paths | ||
1115 | * don't hold the lock. We probably need to split out an LED lock | ||
1116 | * but not during an -rc release! | ||
1105 | */ | 1117 | */ |
1106 | void vt_kbd_con_stop(int console) | 1118 | void vt_kbd_con_stop(int console) |
1107 | { | 1119 | { |
1108 | struct kbd_struct * kbd = kbd_table + console; | 1120 | struct kbd_struct * kbd = kbd_table + console; |
1109 | unsigned long flags; | 1121 | /* unsigned long flags; */ |
1110 | spin_lock_irqsave(&kbd_event_lock, flags); | 1122 | /* spin_lock_irqsave(&kbd_event_lock, flags); */ |
1111 | set_vc_kbd_led(kbd, VC_SCROLLOCK); | 1123 | set_vc_kbd_led(kbd, VC_SCROLLOCK); |
1112 | set_leds(); | 1124 | set_leds(); |
1113 | spin_unlock_irqrestore(&kbd_event_lock, flags); | 1125 | /* spin_unlock_irqrestore(&kbd_event_lock, flags); */ |
1114 | } | 1126 | } |
1115 | 1127 | ||
1116 | /* | 1128 | /* |
1117 | * This is the tasklet that updates LED state on all keyboards | 1129 | * This is the tasklet that updates LED state on all keyboards |
1118 | * attached to the box. The reason we use tasklet is that we | 1130 | * attached to the box. The reason we use tasklet is that we |
1119 | * need to handle the scenario when keyboard handler is not | 1131 | * need to handle the scenario when keyboard handler is not |
1120 | * registered yet but we already getting updates form VT to | 1132 | * registered yet but we already getting updates from the VT to |
1121 | * update led state. | 1133 | * update led state. |
1122 | */ | 1134 | */ |
1123 | static void kbd_bh(unsigned long dummy) | 1135 | static void kbd_bh(unsigned long dummy) |