diff -ruNp 550-timer-freezer-old/drivers/block/ll_rw_blk.c 550-timer-freezer-new/drivers/block/ll_rw_blk.c
--- 550-timer-freezer-old/drivers/block/ll_rw_blk.c	2004-12-10 21:51:49.073205008 +1100
+++ 550-timer-freezer-new/drivers/block/ll_rw_blk.c	2004-12-10 21:51:23.487094688 +1100
@@ -254,6 +254,7 @@ void blk_queue_make_request(request_queu
 
 	q->unplug_timer.function = blk_unplug_timeout;
 	q->unplug_timer.data = (unsigned long)q;
+	q->unplug_timer.no_freeze = 1;
 
 	/*
 	 * by default assume old behaviour and bounce for any highmem page
diff -ruNp 550-timer-freezer-old/drivers/input/serio/i8042.c 550-timer-freezer-new/drivers/input/serio/i8042.c
--- 550-timer-freezer-old/drivers/input/serio/i8042.c	2004-11-03 21:51:15.000000000 +1100
+++ 550-timer-freezer-new/drivers/input/serio/i8042.c	2004-12-10 21:51:23.499092864 +1100
@@ -1002,6 +1002,7 @@ int __init i8042_init(void)
 	dbg_init();
 
 	init_timer(&i8042_timer);
+	i8042_timer.no_freeze = 1;
 	i8042_timer.function = i8042_timer_func;
 
 	if (i8042_platform_init())
diff -ruNp 550-timer-freezer-old/include/linux/timer.h 550-timer-freezer-new/include/linux/timer.h
--- 550-timer-freezer-old/include/linux/timer.h	2004-11-03 21:54:17.000000000 +1100
+++ 550-timer-freezer-new/include/linux/timer.h	2004-12-10 21:51:23.507091648 +1100
@@ -19,6 +19,8 @@ struct timer_list {
 	unsigned long data;
 
 	struct tvec_t_base_s *base;
+
+	int no_freeze;
 };
 
 #define TIMER_MAGIC	0x4b87ad6e
diff -ruNp 550-timer-freezer-old/kernel/timer.c 550-timer-freezer-new/kernel/timer.c
--- 550-timer-freezer-old/kernel/timer.c	2004-12-10 21:51:49.129196496 +1100
+++ 550-timer-freezer-new/kernel/timer.c	2004-12-10 21:51:43.020125216 +1100
@@ -32,6 +32,7 @@
 #include <linux/jiffies.h>
 #include <linux/cpu.h>
 #include <linux/syscalls.h>
+#include <linux/suspend.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -430,6 +431,9 @@ static int cascade(tvec_base_t *base, tv
  */
 #define INDEX(N) (base->timer_jiffies >> (TVR_BITS + N * TVN_BITS)) & TVN_MASK
 
+#define FN_CACHE_SIZE 15
+static void * recent_fns[FN_CACHE_SIZE];
+
 static inline void __run_timers(tvec_base_t *base)
 {
 	struct timer_list *timer;
@@ -464,7 +468,23 @@ repeat:
 			smp_wmb();
 			timer->base = NULL;
 			spin_unlock_irq(&base->lock);
-			fn(data);
+			if (unlikely(test_suspend_state(SUSPEND_TIMER_FREEZER_ON) && (!timer->no_freeze))) {
+				int shown = 0, i, copy_start = 0;
+				for (i = 0; i < FN_CACHE_SIZE; i++)
+					if (fn == recent_fns[i]) {
+						shown = i + 1;
+						copy_start = i;
+						break;
+					}
+				for (i = copy_start; i < (FN_CACHE_SIZE - 1); i++)
+					recent_fns[i] = recent_fns[i+1];
+				recent_fns[FN_CACHE_SIZE - 1] = fn;
+				if (!shown) {
+					printk("Timed call of %p delayed while freezer on.\n", fn);
+				}
+				mod_timer(timer, jiffies + HZ);
+			} else
+				fn(data);
 			spin_lock_irq(&base->lock);
 			goto repeat;
 		}
diff -ruNp 550-timer-freezer-old/net/sched/sch_generic.c 550-timer-freezer-new/net/sched/sch_generic.c
--- 550-timer-freezer-old/net/sched/sch_generic.c	2004-12-10 21:29:45.359440088 +1100
+++ 550-timer-freezer-new/net/sched/sch_generic.c	2004-12-10 21:51:23.510091192 +1100
@@ -210,6 +210,7 @@ static void dev_watchdog_init(struct net
 	init_timer(&dev->watchdog_timer);
 	dev->watchdog_timer.data = (unsigned long)dev;
 	dev->watchdog_timer.function = dev_watchdog;
+	dev->watchdog_timer.no_freeze = 1;
 }
 
 void __netdev_watchdog_up(struct net_device *dev)
