diff -ruNp 420-refrigerator.patch-old/include/linux/sched.h 420-refrigerator.patch-new/include/linux/sched.h
--- 420-refrigerator.patch-old/include/linux/sched.h	2005-07-30 20:33:26.000000000 +1000
+++ 420-refrigerator.patch-new/include/linux/sched.h	2005-07-30 20:27:58.000000000 +1000
@@ -1331,8 +1331,8 @@ static inline void frozen_process(struct
 }
 
 extern void refrigerator(void);
-extern int freeze_processes(void);
-extern void thaw_processes(void);
+extern int freeze_processes(int no_progress);
+extern void thaw_processes(int which_threads);
 
 static inline int try_to_freeze(void)
 {
diff -ruNp 420-refrigerator.patch-old/kernel/power/disk.c 420-refrigerator.patch-new/kernel/power/disk.c
--- 420-refrigerator.patch-old/kernel/power/disk.c	2005-07-30 15:42:48.000000000 +1000
+++ 420-refrigerator.patch-new/kernel/power/disk.c	2005-07-30 20:27:58.000000000 +1000
@@ -116,7 +116,7 @@ static void finish(void)
 {
 	device_resume();
 	platform_finish();
-	thaw_processes();
+	thaw_processes(FREEZER_ALL_THREADS);
 	enable_nonboot_cpus();
 	pm_restore_console();
 }
@@ -132,7 +132,11 @@ static int prepare_processes(void)
 
 	disable_nonboot_cpus();
 
-	if (freeze_processes()) {
+	
+	/* Reset Suspend2's result variable, used in the refrigerator for aborting suspending */
+	suspend_result = 0;
+
+	if (freeze_processes(1)) {
 		error = -EBUSY;
 		goto thaw;
 	}
@@ -148,7 +152,7 @@ static int prepare_processes(void)
 	free_some_memory();
 	return 0;
 thaw:
-	thaw_processes();
+	thaw_processes(FREEZER_ALL_THREADS);
 	enable_nonboot_cpus();
 	pm_restore_console();
 	return error;
@@ -157,7 +161,7 @@ thaw:
 static void unprepare_processes(void)
 {
 	platform_finish();
-	thaw_processes();
+	thaw_processes(FREEZER_ALL_THREADS);
 	enable_nonboot_cpus();
 	pm_restore_console();
 }
diff -ruNp 420-refrigerator.patch-old/kernel/power/main.c 420-refrigerator.patch-new/kernel/power/main.c
--- 420-refrigerator.patch-old/kernel/power/main.c	2005-07-30 15:42:48.000000000 +1000
+++ 420-refrigerator.patch-new/kernel/power/main.c	2005-07-30 20:27:58.000000000 +1000
@@ -66,7 +66,10 @@ static int suspend_prepare(suspend_state
 		goto Enable_cpu;
 	}
 
-	if (freeze_processes()) {
+	/* Reset Suspend2's result variable, used in the refrigerator for aborting suspending */
+	suspend_result = 0;
+	
+	if (freeze_processes(1)) {
 		error = -EAGAIN;
 		goto Thaw;
 	}
@@ -95,7 +98,7 @@ static int suspend_prepare(suspend_state
 	if (pm_ops->finish)
 		pm_ops->finish(state);
  Thaw:
-	thaw_processes();
+	thaw_processes(FREEZER_ALL_THREADS);
  Enable_cpu:
 	enable_nonboot_cpus();
 	pm_restore_console();
@@ -135,7 +138,7 @@ static void suspend_finish(suspend_state
 	device_resume();
 	if (pm_ops && pm_ops->finish)
 		pm_ops->finish(state);
-	thaw_processes();
+	thaw_processes(FREEZER_ALL_THREADS);
 	enable_nonboot_cpus();
 	pm_restore_console();
 }
diff -ruNp 420-refrigerator.patch-old/kernel/power/power.h 420-refrigerator.patch-new/kernel/power/power.h
--- 420-refrigerator.patch-old/kernel/power/power.h	2004-11-03 21:55:05.000000000 +1100
+++ 420-refrigerator.patch-new/kernel/power/power.h	2005-07-30 20:33:32.000000000 +1000
@@ -45,8 +45,8 @@ static struct subsys_attribute _name##_a
 
 extern struct subsystem power_subsys;
 
-extern int freeze_processes(void);
-extern void thaw_processes(void);
+extern int freeze_processes(int no_progress);
+extern void thaw_processes(int which_threads);
 
 extern int pm_prepare_console(void);
 extern void pm_restore_console(void);
diff -ruNp 420-refrigerator.patch-old/kernel/power/process.c 420-refrigerator.patch-new/kernel/power/process.c
--- 420-refrigerator.patch-old/kernel/power/process.c	2005-07-30 15:42:48.000000000 +1000
+++ 420-refrigerator.patch-new/kernel/power/process.c	2005-07-30 20:33:32.000000000 +1000
@@ -1,113 +1,476 @@
 /*
- * drivers/power/process.c - Functions for starting/stopping processes on 
- *                           suspend transitions.
+ * kernel/power/process.c
  *
- * Originally from swsusp.
+ * Copyright (C) 1998-2001 Gabor Kuti <seasons@fornax.hu>
+ * Copyright (C) 1998,2001,2002 Pavel Machek <pavel@suse.cz>
+ * Copyright (C) 2002-2003 Florent Chabaud <fchabaud@free.fr>
+ * Copyright (C) 2002-2004 Nigel Cunningham <ncunningham@linuxmail.org>
+ *
+ * This file is released under the GPLv2.
+ *
+ * Freeze_and_free contains the routines software suspend uses to freeze other
+ * processes during the suspend cycle and to (if necessary) free up memory in
+ * accordance with limitations on the image size.
+ *
+ * Ideally, the image saved to disk would be an atomic copy of the entire 
+ * contents of all RAM and related hardware state. One of the first 
+ * prerequisites for getting our approximation of this is stopping the activity
+ * of other processes. We can't stop all other processes, however, since some 
+ * are needed in doing the I/O to save the image. Freeze_and_free.c contains 
+ * the routines that control suspension and resuming of these processes.
+ * 
+ * Under high I/O load, we need to be careful about the order in which we
+ * freeze processes. If we freeze processes in the wrong order, we could
+ * deadlock others. The freeze_order array this specifies the order in which
+ * critical processes are frozen. All others are suspended after these have
+ * entered the refrigerator.
+ *
+ * Another complicating factor is that freeing memory requires the processes
+ * to not be frozen, but at the end of freeing memory, they need to be frozen
+ * so that we can be sure we actually have eaten enough memory. This is why
+ * freezing and freeing are in the one file. The freezer is not called from
+ * the main logic, but indirectly, via the code for eating memory. The eat
+ * memory logic is iterative, first freezing processes and checking the stats,
+ * then (if necessary) unfreezing them and eating more memory until it looks 
+ * like the criteria are met (at which point processes are frozen & stats
+ * checked again).
  */
 
+#define SUSPEND_FREEZER_C
 
-#undef DEBUG
-
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
 #include <linux/suspend.h>
 #include <linux/module.h>
+#include <asm/tlbflush.h>
+#include "suspend.h"
+#include "ui.h"
+
+unsigned long suspend_action = 0;
+unsigned long suspend_result = 0;
+unsigned long suspend_debug_state = 0;
+unsigned int suspend_task = 0;
+
+atomic_t __nosavedata suspend_cpu_counter = { 0 }; 
+
+/* Timeouts when freezing */
+#define FREEZER_TOTAL_TIMEOUT (5 * HZ)
+#define FREEZER_CHECK_TIMEOUT (HZ / 10)
+
+extern void suspend_relinquish_console(void);
+extern void freeze_lru(void);
+extern void thaw_lru(void);
 
-/* 
- * Timeout for stopping processes
+/*
+ * to_be_frozen
+ *
+ * Description:	Determine whether a process should be frozen yet.
+ * Parameters:	struct task_struct *	The process to consider.
+ * 		int			Which group of processes to consider.
+ * Returns:	int			0 if don't freeze yet, otherwise do.
  */
-#define TIMEOUT	(6 * HZ)
-
+static int to_be_frozen(struct task_struct * p, int type_being_frozen) {
 
-static inline int freezeable(struct task_struct * p)
-{
-	if ((p == current) || 
+	if ((p == current) ||
+	    (frozen(p)) ||
 	    (p->flags & PF_NOFREEZE) ||
 	    (p->exit_state == EXIT_ZOMBIE) ||
 	    (p->exit_state == EXIT_DEAD) ||
 	    (p->state == TASK_STOPPED) ||
 	    (p->state == TASK_TRACED))
 		return 0;
+	if ((!(p->mm)) && (type_being_frozen < 3))
+		return 0;
+	if ((p->flags & PF_SYNCTHREAD) && (type_being_frozen == 1))
+		return 0;
+	if ((p->state == TASK_UNINTERRUPTIBLE) && (type_being_frozen == 3))
+		return 0;
 	return 1;
 }
 
-/* Refrigerator is place where frozen processes are stored :-). */
+/**
+ * refrigerator - idle routine for frozen processes
+ * @flag: unsigned long, non zero if signals to be flushed.
+ *
+ * A routine for kernel threads which should not do work during suspend
+ * to enter and spin in until the process is finished.
+ */
+
 void refrigerator(void)
 {
-	/* Hmm, should we be allowed to suspend when there are realtime
-	   processes around? */
+	unsigned long flags;
 	long save;
+	
+	spin_lock_irqsave(&current->sighand->siglock, flags);
+	recalc_sigpending();
+	spin_unlock_irqrestore(&current->sighand->siglock, flags);
+
+	if (unlikely(current->flags & PF_NOFREEZE)) {
+		thaw_process(current);
+		return;
+	}
+
 	save = current->state;
 	current->state = TASK_UNINTERRUPTIBLE;
-	pr_debug("%s entered refrigerator\n", current->comm);
-	printk("=");
+	suspend_message(SUSPEND_FREEZER, SUSPEND_VERBOSE, 0,
+		"\n%s (%d) refrigerated and sigpending recalculated.",
+		current->comm, current->pid);
 
 	frozen_process(current);
-	spin_lock_irq(&current->sighand->siglock);
-	recalc_sigpending(); /* We sent fake signal, clean it up */
-	spin_unlock_irq(&current->sighand->siglock);
 
-	while (frozen(current))
+	while (test_suspend_state(SUSPEND_FREEZER_ON) && frozen(current)) {
 		schedule();
-	pr_debug("%s left refrigerator\n", current->comm);
+		spin_lock_irqsave(&current->sighand->siglock, flags);
+		recalc_sigpending();
+		spin_unlock_irqrestore(&current->sighand->siglock, flags);
+	}
+	
 	current->state = save;
 }
 
-/* 0 = success, else # of processes that we failed to stop */
-int freeze_processes(void)
+
+#ifdef CONFIG_SMP
+static void __smp_pause(void * data)
 {
-	int todo;
-	unsigned long start_time;
-	struct task_struct *g, *p;
-	unsigned long flags;
+	atomic_inc(&suspend_cpu_counter);
+	while(test_suspend_state(SUSPEND_FREEZE_SMP)) {
+		cpu_relax();
+		barrier();
+	}
+	local_flush_tlb();
+	atomic_dec(&suspend_cpu_counter);
+}
+
+void smp_pause(void)
+{
+	set_suspend_state(SUSPEND_FREEZE_SMP);
+	smp_call_function(__smp_pause, NULL, 0, 0);
+
+	while (atomic_read(&suspend_cpu_counter) < (num_online_cpus() - 1)) {
+		cpu_relax();
+		barrier();
+	}
+}
+
+void smp_continue(void)
+{
+	clear_suspend_state(SUSPEND_FREEZE_SMP);
+		
+	while (atomic_read(&suspend_cpu_counter)) {
+		cpu_relax();
+		barrier();
+	}
+}
+
+extern void __smp_suspend_lowlevel(void * info);
+
+void smp_suspend(void)
+{
+	set_suspend_state(SUSPEND_FREEZE_SMP);
+	smp_call_function(__smp_suspend_lowlevel, NULL, 0, 0);
+
+	while (atomic_read(&suspend_cpu_counter) < (num_online_cpus() - 1)) {
+		cpu_relax();
+		barrier();
+	}
+}
+#else
+#define smp_pause() do { } while(0)
+#define smp_continue() do { } while(0)
+#define smp_suspend() do { } while(0)
+#endif
+
+/*
+ * num_to_be_frozen
+ *
+ * Description:	Determine how many processes of our type are still to be
+ * 		frozen. As a side effect, update the progress bar too.
+ * Parameters:	int	Which type we are trying to freeze.
+ * 		int	Whether we are displaying our progress.
+ */
+static int num_to_be_frozen(int type_being_frozen, int no_progress) {
+	
+	struct task_struct *p, *g;
+	int todo_this_type = 0, total_todo = 0;
+	int total_threads = 0;
+
+	read_lock(&tasklist_lock);
+	do_each_thread(g, p) {
+		if (to_be_frozen(p, type_being_frozen)) {
+			todo_this_type++;
+			total_todo++;
+		} else if (to_be_frozen(p, 3))
+			total_todo++;
+		total_threads++;
+	} while_each_thread(g, p);
+	read_unlock(&tasklist_lock);
+
+	if (!no_progress) {
+		suspend2_update_status(
+				total_threads - total_todo,
+				total_threads,
+				"%d/%d", 
+				total_threads - total_todo,
+				total_threads);
+	}
+	return todo_this_type;
+}
+
+/*
+ * freeze_threads
+ *
+ * Freeze a set of threads having particular attributes.
+ *
+ * Types:
+ * 1: User threads not syncing.
+ * 2: Remaining user threads.
+ * 3: Kernel threads.
+ */
+extern void show_task(struct task_struct * p);
+
+static int freeze_threads(int type, int no_progress)
+{
+	struct task_struct *p, *g;
+	unsigned long start_time = jiffies;
+	int result = 0, still_to_do;
+
+	suspend_message(SUSPEND_FREEZER, SUSPEND_VERBOSE, 1,
+		"\n STARTING TO FREEZE TYPE %d THREADS.\n",
+		type);
 
-	printk( "Stopping tasks: " );
-	start_time = jiffies;
 	do {
-		todo = 0;
+		int numsignalled = 0;
+
+		/* 
+		 * Pause the other processors so we can safely
+		 * change threads' flags
+		 */
+		smp_pause();
+
+		if (test_result_state(SUSPEND_ABORTED)) {
+			smp_continue();
+			return 1;
+		}
+
+		preempt_disable();
+
+		local_irq_disable();
+
 		read_lock(&tasklist_lock);
+
+		/*
+		 * Signal the processes.
+		 *
+		 * We signal them every time through. Otherwise pdflush -
+		 * and maybe other processes - might never enter the
+		 * fridge.
+		 *
+		 * NB: We're inside an SMP pause. Our printks are unsafe.
+		 * They're only here for debugging.
+		 *
+		 */
+		
 		do_each_thread(g, p) {
-			if (!freezeable(p))
-				continue;
-			if (frozen(p))
+			unsigned long flags;
+			if (!to_be_frozen(p, type))
 				continue;
-
+			
+			numsignalled++;
+			suspend_message(SUSPEND_FREEZER, SUSPEND_VERBOSE, 0, 
+				"\n   %s: pid %d",
+				p->comm, p->pid);
 			freeze(p);
 			spin_lock_irqsave(&p->sighand->siglock, flags);
 			signal_wake_up(p, 0);
 			spin_unlock_irqrestore(&p->sighand->siglock, flags);
-			todo++;
+		} while_each_thread(g, p);
+
+		if (numsignalled)
+			suspend_message(SUSPEND_FREEZER, SUSPEND_VERBOSE, 0,
+				"\n Number of threads signalled this iteration is %d.\n",
+				numsignalled);
+
+		read_unlock(&tasklist_lock);
+
+		/* 
+		 * Let the processes run.
+		 */		
+		smp_continue();
+
+		preempt_enable();
+
+		local_irq_enable();
+		
+		/*
+		 * Sleep.
+		 */
+		set_task_state(current, TASK_INTERRUPTIBLE);
+		schedule_timeout(FREEZER_CHECK_TIMEOUT);
+
+		still_to_do = num_to_be_frozen(type, no_progress);
+	} while(still_to_do && (!test_result_state(SUSPEND_ABORTED)) &&
+		!time_after(jiffies, start_time + FREEZER_TOTAL_TIMEOUT));
+
+	/*
+	 * Did we time out? See if we failed to freeze processes as well.
+	 *
+	 */
+	if ((time_after(jiffies, start_time + FREEZER_TOTAL_TIMEOUT)) && (still_to_do)) {
+		read_lock(&tasklist_lock);
+		do_each_thread(g, p) {
+			if (!to_be_frozen(p, type)) 
+				continue;
+			
+			if (!result) {
+				printk(KERN_ERR	"Stopping tasks failed.\n");
+				printk(KERN_ERR "Tasks that refused to be "
+				 "refrigerated and haven't since exited:\n");
+				result = 1;
+			}
+			
+			if ((freezing(p))) {
+				printk(" - %s (#%d) signalled but "
+					"didn't enter refrigerator.\n",
+					p->comm, p->pid);
+				show_task(p);
+			} else
+				printk(" - %s (#%d) wasn't "
+					"signalled.\n",
+					p->comm, p->pid);
 		} while_each_thread(g, p);
 		read_unlock(&tasklist_lock);
-		yield();			/* Yield is okay here */
-		if (time_after(jiffies, start_time + TIMEOUT)) {
-			printk( "\n" );
-			printk(KERN_ERR " stopping tasks failed (%d tasks remaining)\n", todo );
-			return todo;
+	} else
+		suspend_message(SUSPEND_FREEZER, SUSPEND_VERBOSE, 1,
+			"\n\nSuccessfully froze processes of type %d.\n",
+			type);
+	return result;
+}
+
+/*
+ * freeze_processes - Freeze processes prior to saving an image of memory.
+ * 
+ * Return value: 0 = success, else # of processes that we failed to stop.
+ */
+extern asmlinkage long sys_sync(void);
+
+/* Freeze_processes.
+ * If the flag no_progress is non-zero, progress bars not be updated.
+ * Debugging output is still printed.
+ */
+int freeze_processes(int no_progress)
+{
+	int showidlelist, result = 0, num_type[3];
+	struct task_struct *p, *g;
+
+	showidlelist = 1;
+
+	num_type[0] = num_type[1] = num_type[2] = 0;
+
+	set_suspend_state(SUSPEND_FREEZER_ON);
+
+	read_lock(&tasklist_lock);
+	do_each_thread(g, p) {
+		if (p->mm) {
+			if (p->flags & PF_SYNCTHREAD) {
+				suspend_message(SUSPEND_FREEZER, SUSPEND_MEDIUM, 0,
+					"%s (%d) is a syncthread at entrance to "
+					"fridge\n", p->comm, p->pid);
+				num_type[1]++;
+			} else
+				num_type[2]++;
+		} else {
+			if (p->flags & PF_NOFREEZE)
+				suspend_message(SUSPEND_FREEZER, SUSPEND_MEDIUM, 0,
+					"%s (%d) is NO_FREEZE.\n",
+					p->comm, p->pid);
+			else
+				num_type[2]++;
 		}
-	} while(todo);
+	} while_each_thread(g, p);
+	read_unlock(&tasklist_lock);
+	suspend_message(SUSPEND_FREEZER, SUSPEND_MEDIUM, 0, "\n");
 
-	printk( "|\n" );
-	BUG_ON(in_atomic());
-	return 0;
+	/* First, freeze all userspace,	non syncing threads. */
+	if (freeze_threads(1, no_progress) || (test_result_state(SUSPEND_ABORTED)))
+		goto aborting;
+	
+	/* Now freeze processes that were syncing and are still running */
+	if (freeze_threads(2, no_progress) || (test_result_state(SUSPEND_ABORTED)))
+		goto aborting;
+
+	/* Now do our own sync, just in case one wasn't running already */
+	if (!no_progress)
+		suspend2_prepare_status(CLEAR_BAR, "Freezing processes: Syncing remaining I/O.");
+
+	sys_sync();
+
+	set_suspend_state(SUSPEND_DISABLE_SYNCING);
+
+	/* Freeze kernel threads */
+	if (freeze_threads(3, no_progress) || (test_result_state(SUSPEND_ABORTED)))
+		goto aborting;
+
+	suspend_task = current->pid;
+
+	freeze_lru();
+out:
+	suspend_message(SUSPEND_FREEZER, SUSPEND_VERBOSE, 1,
+				"Left freezer loop.\n");
+
+	clear_suspend_state(SUSPEND_FREEZE_SMP);
+
+	while (atomic_read(&suspend_cpu_counter)) {
+		cpu_relax();
+		barrier();
+	}
+
+	return result;
+aborting:
+	result = -1;
+	goto out;
 }
 
-void thaw_processes(void)
+void thaw_processes(int which_threads)
 {
-	struct task_struct *g, *p;
+	struct task_struct *p, *g;
+	suspend_message(SUSPEND_FREEZER, SUSPEND_LOW, 1, "Thawing tasks\n");
+	
+	suspend_task = 0;
+	if (which_threads != FREEZER_KERNEL_THREADS)
+		clear_suspend_state(SUSPEND_FREEZER_ON);
+
+	clear_suspend_state(SUSPEND_DISABLE_SYNCING);
+	
+	/* 
+	 * Pause the other processors so we can safely
+	 * change threads' flags
+	 */
+
+	smp_pause();
+
+	preempt_disable();
+	
+	local_irq_disable();
 
-	printk( "Restarting tasks..." );
 	read_lock(&tasklist_lock);
+
 	do_each_thread(g, p) {
-		if (!freezeable(p))
-			continue;
-		if (!thaw_process(p))
-			printk(KERN_INFO " Strange, %s not stopped\n", p->comm );
+		if (frozen(p)) {
+			if ((which_threads == FREEZER_KERNEL_THREADS) && p->mm)
+				continue;
+			suspend_message(SUSPEND_FREEZER, SUSPEND_VERBOSE, 0,
+					"Waking %5d: %s.\n", p->pid, p->comm);
+			thaw_process(p);
+		}
 	} while_each_thread(g, p);
 
 	read_unlock(&tasklist_lock);
+
+	smp_continue();
+	
+	preempt_enable();
+
+	local_irq_enable();
+
 	schedule();
-	printk( " done\n" );
 }
 
-EXPORT_SYMBOL(refrigerator);
+EXPORT_SYMBOL_GPL(refrigerator);
diff -ruNp 420-refrigerator.patch-old/kernel/sched.c 420-refrigerator.patch-new/kernel/sched.c
--- 420-refrigerator.patch-old/kernel/sched.c	2005-07-30 20:33:26.000000000 +1000
+++ 420-refrigerator.patch-new/kernel/sched.c	2005-07-30 20:27:58.000000000 +1000
@@ -32,7 +32,6 @@
 #include <linux/security.h>
 #include <linux/notifier.h>
 #include <linux/profile.h>
-#include <linux/suspend.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/smp.h>
@@ -4121,7 +4120,7 @@ static inline struct task_struct *younge
 	return list_entry(p->sibling.next,struct task_struct,sibling);
 }
 
-static void show_task(task_t * p)
+void show_task(task_t * p)
 {
 	task_t *relative;
 	unsigned state;

