From: Sau Dan Lee Fix a bug with improper shutdown of a timer. Cause: When the i8042 module is unloaded, the i8042_exit() shuts down it timer by calling del_timer_sync(). However, after that call, there can still be interrupts from the i8042 chip (due to keyboard or mouse activities). Such interrupts invoke the interrupt handler i8042_interrupt(), which would call mod_timer() to reschedule a new timer event. But i8042_exit() won't want for this new timer event. It may exit before the event arrives. The module is unloaded as i8042_exit() exits, but this can happen before the new timer event comes. As a result, when the timer expires, the kernel tries to call i8042_timer_func(), which has been unloaded! This results in a complete freeze. The Fix: is to make sure interrupts from the i8042 chip are disabled before calling del_timer_sync() to clean up the timer. In i8042_exit(), this is as easy as swapping the order of the calls to del_timer_sync() and i8042_controller_cleanup(). --- 25-akpm/drivers/input/serio/i8042.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff -puN drivers/input/serio/i8042.c~i8042-shutdown-fix drivers/input/serio/i8042.c --- 25/drivers/input/serio/i8042.c~i8042-shutdown-fix 2004-05-08 13:15:18.727572312 -0700 +++ 25-akpm/drivers/input/serio/i8042.c 2004-05-08 13:15:18.731571704 -0700 @@ -997,10 +997,14 @@ void __exit i8042_exit(void) sysdev_class_unregister(&kbc_sysclass); } - del_timer_sync(&i8042_timer); - i8042_controller_cleanup(); + /* we must delete the timer AFTER the i8042 chip is cleaned up, + so as to prevent any more interrupts to invoke i8042_interrupt() + which then schedules newer timer events. + */ + del_timer_sync(&i8042_timer); + if (i8042_kbd_values.exists) serio_unregister_port(&i8042_kbd_port); _