
From: Sau Dan Lee <danlee@informatik.uni-freiburg.de>

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

_
