diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/Kconfig 110-ppc64_update/arch/ppc64/Kconfig
--- 107-kgdb_gdb6_patches/arch/ppc64/Kconfig	Wed Feb  4 23:03:17 2004
+++ 110-ppc64_update/arch/ppc64/Kconfig	Mon Feb  9 10:06:05 2004
@@ -251,54 +251,10 @@ config CMDLINE
 
 endmenu
 
-source "drivers/base/Kconfig"
-
-source "drivers/mtd/Kconfig"
-
-source "drivers/parport/Kconfig"
-
-source "drivers/pnp/Kconfig"
-
-source "drivers/block/Kconfig"
-
-source "drivers/ide/Kconfig"
-
-source "drivers/scsi/Kconfig"
-
-source "drivers/md/Kconfig"
-
-source "drivers/message/fusion/Kconfig"
-
-source "drivers/ieee1394/Kconfig"
-
-source "drivers/message/i2o/Kconfig"
-
-source "net/Kconfig"
-
-source "drivers/isdn/Kconfig"
-
-source "drivers/telephony/Kconfig"
-
-#
-# input before char - char/joystick depends on it. As does USB.
-#
-source "drivers/input/Kconfig"
-
-source "drivers/char/Kconfig"
-
-source "drivers/i2c/Kconfig"
-
-source "drivers/media/Kconfig"
+source "drivers/Kconfig"
 
 source "fs/Kconfig"
 
-source "drivers/video/Kconfig"
-
-source "sound/Kconfig"
-
-source "drivers/usb/Kconfig"
-
-
 menu "iSeries device drivers"
 	depends on PPC_ISERIES
 
@@ -401,6 +357,13 @@ config DEBUG_INFO
 	  debugging info resulting in a larger kernel image.
 	  Say Y here only if you plan to use gdb to debug the kernel.
 	  If you don't debug the kernel, you can say N.
+
+config DEBUG_SPINLOCK_SLEEP
+	bool "Sleep-inside-spinlock checking"
+	depends on DEBUG_KERNEL
+	help
+	  If you say Y here, various routines which may sleep will become very
+	  noisy if they are called with a spinlock held.
 	  
 endmenu
 
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/kernel/Makefile 110-ppc64_update/arch/ppc64/kernel/Makefile
--- 107-kgdb_gdb6_patches/arch/ppc64/kernel/Makefile	Wed Feb  4 23:03:17 2004
+++ 110-ppc64_update/arch/ppc64/kernel/Makefile	Mon Feb  9 10:06:05 2004
@@ -39,6 +39,6 @@ obj-$(CONFIG_PPC_RTAS)		+= rtas-proc.o
 obj-$(CONFIG_SCANLOG)		+= scanlog.o
 obj-$(CONFIG_VIOPATH)		+= viopath.o
 obj-$(CONFIG_LPARCFG)		+= lparcfg.o
-
+obj-$(CONFIG_HVC_CONSOLE)   += hvconsole.o
 
 CFLAGS_ioctl32.o += -Ifs/
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/kernel/head.S 110-ppc64_update/arch/ppc64/kernel/head.S
--- 107-kgdb_gdb6_patches/arch/ppc64/kernel/head.S	Wed Feb  4 23:03:17 2004
+++ 110-ppc64_update/arch/ppc64/kernel/head.S	Mon Feb  9 10:06:05 2004
@@ -52,7 +52,7 @@
 /*
  * hcall interface to pSeries LPAR
  */
-#define HSC .long 0x44000022
+#define HVSC .long 0x44000022
 #define H_SET_ASR		0x30
 
 /*
@@ -1743,7 +1743,7 @@ _GLOBAL(__secondary_start)
 	cmpwi	r3,0x34         /* Pulsar */
 	bne	98f
 97:	li	r3,H_SET_ASR    /* hcall = H_SET_ASR */
-	HSC     		/* Invoking hcall */
+	HVSC     		/* Invoking hcall */
 	b	99f
 98:                             /* !(rpa hypervisor) || !(star)  */
 	mtasr	r4	        /* set the stab location         */
@@ -1912,7 +1912,7 @@ _STATIC(start_here_pSeries)
 	cmpwi	r3,0x34         /* Pulsar */
 	bne	98f
 97:	li	r3,H_SET_ASR    /* hcall = H_SET_ASR */
-	HSC     	        /* Invoking hcall */
+	HVSC     	        /* Invoking hcall */
 	b     	99f
 98:                             /* !(rpa hypervisor) || !(star) */
 	mtasr	r4	        /* set the stab location         */
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/kernel/hvconsole.c 110-ppc64_update/arch/ppc64/kernel/hvconsole.c
--- 107-kgdb_gdb6_patches/arch/ppc64/kernel/hvconsole.c	Wed Dec 31 16:00:00 1969
+++ 110-ppc64_update/arch/ppc64/kernel/hvconsole.c	Mon Feb  9 10:06:05 2004
@@ -0,0 +1,88 @@
+/*
+ * hvconsole.c
+ * Copyright (C) 2004 Hollis Blanchard, IBM Corporation
+ *
+ * LPAR console support.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <asm/hvcall.h>
+#include <asm/prom.h>
+#include <asm/hvconsole.h>
+
+int hvc_get_chars(int index, char *buf, int count)
+{
+	unsigned long got;
+
+	if (plpar_hcall(H_GET_TERM_CHAR, index, 0, 0, 0, &got,
+		(unsigned long *)buf, (unsigned long *)buf+1) == H_Success) {
+		/*
+		 * Work around a HV bug where it gives us a null
+		 * after every \r.  -- paulus
+		 */
+		if (got > 0) {
+			int i;
+			for (i = 1; i < got; ++i) {
+				if (buf[i] == 0 && buf[i-1] == '\r') {
+					--got;
+					if (i < got)
+						memmove(&buf[i], &buf[i+1],
+							got - i);
+				}
+			}
+		}
+		return got;
+	}
+	return 0;
+}
+
+int hvc_put_chars(int index, const char *buf, int count)
+{
+	unsigned long *lbuf = (unsigned long *) buf;
+	long ret;
+
+	ret = plpar_hcall_norets(H_PUT_TERM_CHAR, index, count, lbuf[0],
+				 lbuf[1]);
+	if (ret == H_Success)
+		return count;
+	if (ret == H_Busy)
+		return 0;
+	return -1;
+}
+
+/* return the number of client vterms present */
+/* XXX this requires an interface change to handle multiple discontiguous
+ * vterms */
+int hvc_count(int *start_termno)
+{
+	struct device_node *vty;
+	int num_found = 0;
+
+	/* consider only the first vty node.
+	 * we should _always_ be able to find one. */
+	vty = of_find_node_by_name(NULL, "vty");
+	if (vty && device_is_compatible(vty, "hvterm1")) {
+		u32 *termno = (u32 *)get_property(vty, "reg", 0);
+
+		if (termno && start_termno)
+			*start_termno = *termno;
+		num_found = 1;
+		of_node_put(vty);
+	}
+
+	return num_found;
+}
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/kernel/iSeries_htab.c 110-ppc64_update/arch/ppc64/kernel/iSeries_htab.c
--- 107-kgdb_gdb6_patches/arch/ppc64/kernel/iSeries_htab.c	Wed Feb  4 23:03:17 2004
+++ 110-ppc64_update/arch/ppc64/kernel/iSeries_htab.c	Mon Feb  9 10:06:05 2004
@@ -109,6 +109,12 @@ static long iSeries_hpte_remove(unsigned
 	return -1;
 }
 
+/*
+ * The HyperVisor expects the "flags" argument in this form:
+ * 	bits  0..59 : reserved
+ * 	bit      60 : N
+ * 	bits 61..63 : PP2,PP1,PP0
+ */
 static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
 				  unsigned long va, int large, int local)
 {
@@ -117,7 +123,7 @@ static long iSeries_hpte_updatepp(unsign
 
 	HvCallHpt_get(&hpte, slot);
 	if ((hpte.dw0.dw0.avpn == avpn) && (hpte.dw0.dw0.v)) {
-		HvCallHpt_setPp(slot, newpp);
+		HvCallHpt_setPp(slot, (newpp & 0x3) | ((newpp & 0x4) << 1));
 		return 0;
 	}
 	return -1;
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/kernel/idle.c 110-ppc64_update/arch/ppc64/kernel/idle.c
--- 107-kgdb_gdb6_patches/arch/ppc64/kernel/idle.c	Wed Feb  4 23:03:17 2004
+++ 110-ppc64_update/arch/ppc64/kernel/idle.c	Mon Feb  9 10:06:05 2004
@@ -161,7 +161,7 @@ int dedicated_idle(void)
 	struct paca_struct *lpaca = get_paca(), *ppaca;
 	unsigned long start_snooze;
 
-	ppaca = &paca[(lpaca->xPacaIndex) ^ 1];
+	ppaca = &paca[smp_processor_id() ^ 1];
 
 	while (1) {
 		/* Indicate to the HV that we are idle.  Now would be
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/kernel/lparcfg.c 110-ppc64_update/arch/ppc64/kernel/lparcfg.c
--- 107-kgdb_gdb6_patches/arch/ppc64/kernel/lparcfg.c	Wed Feb  4 23:03:17 2004
+++ 110-ppc64_update/arch/ppc64/kernel/lparcfg.c	Mon Feb  9 10:06:05 2004
@@ -331,7 +331,7 @@ static int lparcfg_data(unsigned char *b
 	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
 		system_potential_processors =  get_splpar_potential_characteristics();
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
-			      "system_active_processors=%d\n", 
+			      "system_active_processors=%ld\n", 
 			      (h_resource >> 2*8) & 0xffff);
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
 			      "system_potential_processors=%d\n", 
@@ -373,16 +373,16 @@ static int lparcfg_data(unsigned char *b
 
 	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
-			      "pool=%d\n", (h_aggregation >> 0*8)&0xffff);
+			      "pool=%ld\n", (h_aggregation >> 0*8)&0xffff);
 
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
-			      "pool_capacity=%d\n", (h_resource >> 3*8) &0xffff);
+			      "pool_capacity=%ld\n", (h_resource >> 3*8) &0xffff);
 
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
-			      "group=%d\n", (h_aggregation >> 2*8)&0xffff);
+			      "group=%ld\n", (h_aggregation >> 2*8)&0xffff);
 
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
-			      "capped=%d\n", (h_resource >> 6*8)&0x40);
+			      "capped=%ld\n", (h_resource >> 6*8)&0x40);
 
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, 
 			      "capacity_weight=%d\n", (int)(h_resource>>5*8)&0xFF);
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/kernel/pSeries_hvCall.S 110-ppc64_update/arch/ppc64/kernel/pSeries_hvCall.S
--- 107-kgdb_gdb6_patches/arch/ppc64/kernel/pSeries_hvCall.S	Wed Feb  4 23:03:17 2004
+++ 110-ppc64_update/arch/ppc64/kernel/pSeries_hvCall.S	Mon Feb  9 10:06:05 2004
@@ -22,7 +22,7 @@
 /*
  * hcall interface to pSeries LPAR
  */
-#define HSC .long 0x44000022
+#define HVSC .long 0x44000022
 
 /* long plpar_hcall(unsigned long opcode,	 R3 
 		 unsigned long arg1,		 R4 
@@ -44,7 +44,7 @@ _GLOBAL(plpar_hcall)
         std     r9,-16(r1)
         std     r10,-24(r1)
 	
-	HSC                     /* invoke the hypervisor */
+	HVSC                    /* invoke the hypervisor */
 
         ld      r10,-8(r1)      /* Fetch r4-r7 ret args. */
         std     r4,0(r10)
@@ -63,7 +63,7 @@ _GLOBAL(plpar_hcall)
 _GLOBAL(plpar_hcall_norets)
 	mfcr	r0
 	std	r0,-8(r1)
-	HSC                     /* invoke the hypervisor */
+	HVSC                    /* invoke the hypervisor */
 	ld	r0,-8(r1)
 	mtcrf	0xff,r0
 	blr                     /* return r3 = status */
@@ -94,7 +94,7 @@ _GLOBAL(plpar_hcall_8arg_2ret)
 
         std     r12,-8(r1)      /* Save out ptr */
 	
-	HSC                    /* invoke the hypervisor */
+	HVSC                    /* invoke the hypervisor */
 
         ld      r10,-8(r1)      /* Fetch r4 ret arg */
         std     r4,0(r10)
@@ -126,7 +126,7 @@ _GLOBAL(plpar_hcall_4out)
 	std     r10,16(r1)
 	std     r14,8(r1)
 	
-	HSC                    /* invoke the hypervisor */
+	HVSC                    /* invoke the hypervisor */
 
 	ld      r14,32(r1)      /* Fetch r4-r7 ret args. */
 	std     r4,0(r14)
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/kernel/pSeries_lpar.c 110-ppc64_update/arch/ppc64/kernel/pSeries_lpar.c
--- 107-kgdb_gdb6_patches/arch/ppc64/kernel/pSeries_lpar.c	Wed Feb  4 23:03:17 2004
+++ 110-ppc64_update/arch/ppc64/kernel/pSeries_lpar.c	Mon Feb  9 10:06:05 2004
@@ -313,69 +313,6 @@ void pSeriesLP_init_early(void)
 	}
 }
 
-int hvc_get_chars(int index, char *buf, int count)
-{
-	unsigned long got;
-
-	if (plpar_hcall(H_GET_TERM_CHAR, index, 0, 0, 0, &got,
-		(unsigned long *)buf, (unsigned long *)buf+1) == H_Success) {
-		/*
-		 * Work around a HV bug where it gives us a null
-		 * after every \r.  -- paulus
-		 */
-		if (got > 0) {
-			int i;
-			for (i = 1; i < got; ++i) {
-				if (buf[i] == 0 && buf[i-1] == '\r') {
-					--got;
-					if (i < got)
-						memmove(&buf[i], &buf[i+1],
-							got - i);
-				}
-			}
-		}
-		return got;
-	}
-	return 0;
-}
-
-int hvc_put_chars(int index, const char *buf, int count)
-{
-	unsigned long *lbuf = (unsigned long *) buf;
-	long ret;
-
-	ret = plpar_hcall_norets(H_PUT_TERM_CHAR, index, count, lbuf[0],
-				 lbuf[1]);
-	if (ret == H_Success)
-		return count;
-	if (ret == H_Busy)
-		return 0;
-	return -1;
-}
-
-/* return the number of client vterms present */
-/* XXX this requires an interface change to handle multiple discontiguous
- * vterms */
-int hvc_count(int *start_termno)
-{
-	struct device_node *vty;
-	int num_found = 0;
-
-	/* consider only the first vty node.
-	 * we should _always_ be able to find one. */
-	vty = of_find_node_by_name(NULL, "vty");
-	if (vty && device_is_compatible(vty, "hvterm1")) {
-		u32 *termno = (u32 *)get_property(vty, "reg", 0);
-
-		if (termno && start_termno)
-			*start_termno = *termno;
-		num_found = 1;
-		of_node_put(vty);
-	}
-
-	return num_found;
-}
-
 long pSeries_lpar_hpte_insert(unsigned long hpte_group,
 			      unsigned long va, unsigned long prpn,
 			      int secondary, unsigned long hpteflags,
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/kernel/proc_ppc64.c 110-ppc64_update/arch/ppc64/kernel/proc_ppc64.c
--- 107-kgdb_gdb6_patches/arch/ppc64/kernel/proc_ppc64.c	Wed Feb  4 23:03:17 2004
+++ 110-ppc64_update/arch/ppc64/kernel/proc_ppc64.c	Mon Feb  9 10:06:05 2004
@@ -268,12 +268,10 @@ out:
 static int do_remove_node(char *buf)
 {
 	struct device_node *node;
-	int rv = 0;
+	int rv = -ENODEV;
 
 	if ((node = of_find_node_by_path(buf)))
-		of_remove_node(node);
-	else
-		rv = -ENODEV;
+		rv = of_remove_node(node);
 
 	of_node_put(node);
 	return rv;
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/kernel/prom.c 110-ppc64_update/arch/ppc64/kernel/prom.c
--- 107-kgdb_gdb6_patches/arch/ppc64/kernel/prom.c	Wed Feb  4 23:03:17 2004
+++ 110-ppc64_update/arch/ppc64/kernel/prom.c	Mon Feb  9 10:06:05 2004
@@ -2507,29 +2507,48 @@ int of_add_node(const char *path, struct
 
 /*
  * Remove an OF device node from the system.
+ * Caller should have already "gotten" np.
  */
 int of_remove_node(struct device_node *np)
 {
 	struct device_node *parent, *child;
 
 	parent = of_get_parent(np);
-	child = of_get_next_child(np, NULL);
-	if (child && !child->child && !child->sibling) {
-		/* For now, we will allow removal of a
-		 * node with one and only one child, so
-		 * that we can support removing a slot with
-		 * an IOA in it.  More general support for
-		 * subtree removal to be implemented later, if
-		 * necessary.
-		 */
-		of_remove_node(child);
-	}
-	else if (child) {
-		of_node_put(child);
-		of_node_put(parent);
+
+	if (!parent)
 		return -EINVAL;
+
+	/* Make sure we are not recursively removing
+	 * more than one level of nodes.  We need to
+	 * allow this so we can remove a slot containing
+	 * an IOA.
+	 */
+	for (child = of_get_next_child(np, NULL);
+	     child != NULL;
+	     child = of_get_next_child(np, child)) {
+		struct device_node *grandchild;
+
+		if ((grandchild = of_get_next_child(child, NULL))) {
+			/* Too deep */
+			of_node_put(grandchild);
+			of_node_put(child);
+			return -EBUSY;
+		}
+	}
+
+	/* Now that we're reasonably sure that we won't
+	 * overflow our stack, remove any children of np.
+	 */
+	for (child = of_get_next_child(np, NULL);
+	     child != NULL;
+	     child = of_get_next_child(np, child)) {
+		int rc;
+
+		if ((rc = of_remove_node(child))) {
+			of_node_put(child);
+			return rc;
+		}
 	}
-	of_node_put(child);
 
 	write_lock(&devtree_lock);
 	OF_MARK_STALE(np);
@@ -2545,8 +2564,8 @@ int of_remove_node(struct device_node *n
 		prev->allnext = np->allnext;
 	}
 
-	if (np->parent->child == np)
-		np->parent->child = np->sibling;
+	if (parent->child == np)
+		parent->child = np->sibling;
 	else {
 		struct device_node *prevsib;
 		for (prevsib = np->parent->child;
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/kernel/rtas-proc.c 110-ppc64_update/arch/ppc64/kernel/rtas-proc.c
--- 107-kgdb_gdb6_patches/arch/ppc64/kernel/rtas-proc.c	Wed Feb  4 23:03:17 2004
+++ 110-ppc64_update/arch/ppc64/kernel/rtas-proc.c	Mon Feb  9 10:06:05 2004
@@ -285,13 +285,13 @@ static ssize_t ppc_rtas_poweron_read(str
 		size_t count, loff_t *ppos)
 {
 	char stkbuf[40];  /* its small, its on stack */
-	int n;
+	int n, sn;
 	if (power_on_time == 0)
 		n = snprintf(stkbuf, 40, "Power on time not set\n");
 	else
 		n = snprintf(stkbuf, 40, "%lu\n", power_on_time);
 
-	int sn = strlen (stkbuf) +1;
+	sn = strlen (stkbuf) +1;
 	if (*ppos >= sn)
 		return 0;
 	if (n > sn - *ppos)
@@ -331,18 +331,19 @@ static ssize_t ppc_rtas_progress_write(s
 static ssize_t ppc_rtas_progress_read(struct file * file, char * buf,
 		size_t count, loff_t *ppos)
 {
-	int n = 0;
+	int sn, n = 0;
+	char *tmpbuf;
 
 	if (progress_led == NULL) return 0;
 
-	char * tmpbuf = kmalloc (MAX_LINELENGTH, GFP_KERNEL);
+	tmpbuf = kmalloc (MAX_LINELENGTH, GFP_KERNEL);
 	if (!tmpbuf) {
 		printk(KERN_ERR "error: kmalloc failed\n");
 		return -ENOMEM;
 	}
 	n = sprintf (tmpbuf, "%s\n", progress_led);
 
-	int sn = strlen (tmpbuf) +1;
+	sn = strlen (tmpbuf) +1;
 	if (*ppos >= sn) {
 		kfree (tmpbuf);
 		return 0;
@@ -398,15 +399,14 @@ static ssize_t ppc_rtas_clock_read(struc
 {
 	unsigned int year, mon, day, hour, min, sec;
 	unsigned long *ret = kmalloc(4*8, GFP_KERNEL);
-	int n, error;
+	int n, sn, error;
+	char stkbuf[40];  /* its small, its on stack */
 
 	error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
 	
 	year = ret[0]; mon  = ret[1]; day  = ret[2];
 	hour = ret[3]; min  = ret[4]; sec  = ret[5];
 
-	char stkbuf[40];  /* its small, its on stack */
-
 	if (error != 0){
 		printk(KERN_WARNING "error: reading the clock returned: %s\n", 
 				ppc_rtas_process_error(error));
@@ -416,7 +416,7 @@ static ssize_t ppc_rtas_clock_read(struc
 	}
 	kfree(ret);
 
-	int sn = strlen (stkbuf) +1;
+	sn = strlen (stkbuf) +1;
 	if (*ppos >= sn)
 		return 0;
 	if (n > sn - *ppos)
@@ -860,11 +860,12 @@ static ssize_t ppc_rtas_tone_freq_write(
 static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf,
 		size_t count, loff_t *ppos)
 {
-	int n;
+	int n, sn;
 	char stkbuf[40];  /* its small, its on stack */
+
 	n = snprintf(stkbuf, 40, "%lu\n", rtas_tone_frequency);
 
-	int sn = strlen (stkbuf) +1;
+	sn = strlen (stkbuf) +1;
 	if (*ppos >= sn)
 		return 0;
 	if (n > sn - *ppos)
@@ -913,11 +914,12 @@ static ssize_t ppc_rtas_tone_volume_writ
 static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf,
 		size_t count, loff_t *ppos)
 {
-	int n;
+	int n, sn;
 	char stkbuf[40];  /* its small, its on stack */
+
 	n = snprintf(stkbuf, 40, "%lu\n", rtas_tone_volume);
 
-	int sn = strlen (stkbuf) +1;
+	sn = strlen (stkbuf) +1;
 	if (*ppos >= sn)
 		return 0;
 	if (n > sn - *ppos)
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/kernel/setup.c 110-ppc64_update/arch/ppc64/kernel/setup.c
--- 107-kgdb_gdb6_patches/arch/ppc64/kernel/setup.c	Wed Feb  4 23:03:18 2004
+++ 110-ppc64_update/arch/ppc64/kernel/setup.c	Mon Feb  9 10:06:05 2004
@@ -283,6 +283,10 @@ EXPORT_SYMBOL(machine_halt);
 unsigned long ppc_proc_freq;
 unsigned long ppc_tb_freq;
 
+#ifdef CONFIG_SMP
+DEFINE_PER_CPU(unsigned int, pvr);
+#endif
+
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
 	unsigned long cpu_id = (unsigned long)v - 1;
@@ -302,7 +306,7 @@ static int show_cpuinfo(struct seq_file 
 		return 0;
 
 #ifdef CONFIG_SMP
-	pvr = paca[cpu_id].pvr;
+	pvr = per_cpu(pvr, cpu_id);
 #else
 	pvr = _get_PVR();
 #endif
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/kernel/smp.c 110-ppc64_update/arch/ppc64/kernel/smp.c
--- 107-kgdb_gdb6_patches/arch/ppc64/kernel/smp.c	Wed Feb  4 23:03:18 2004
+++ 110-ppc64_update/arch/ppc64/kernel/smp.c	Mon Feb  9 10:06:05 2004
@@ -575,9 +575,11 @@ extern struct gettimeofday_struct do_gto
 
 struct thread_info *current_set[NR_CPUS];
 
+DECLARE_PER_CPU(unsigned int, pvr);
+
 static void __devinit smp_store_cpu_info(int id)
 {
-	paca[id].pvr = _get_PVR();
+	per_cpu(pvr, id) = _get_PVR();
 }
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/kernel/time.c 110-ppc64_update/arch/ppc64/kernel/time.c
--- 107-kgdb_gdb6_patches/arch/ppc64/kernel/time.c	Wed Feb  4 23:03:18 2004
+++ 110-ppc64_update/arch/ppc64/kernel/time.c	Mon Feb  9 10:06:05 2004
@@ -267,7 +267,7 @@ int timer_interrupt(struct pt_regs * reg
 	int next_dec;
 	unsigned long cur_tb;
 	struct paca_struct *lpaca = get_paca();
-	unsigned long cpu = lpaca->xPacaIndex;
+	unsigned long cpu = smp_processor_id();
 
 	irq_enter();
 
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/kernel/vio.c 110-ppc64_update/arch/ppc64/kernel/vio.c
--- 107-kgdb_gdb6_patches/arch/ppc64/kernel/vio.c	Wed Feb  4 23:03:18 2004
+++ 110-ppc64_update/arch/ppc64/kernel/vio.c	Mon Feb  9 10:06:05 2004
@@ -4,6 +4,7 @@
  *    Copyright (c) 2003 IBM Corp.
  *     Dave Engebretsen engebret@us.ibm.com
  *     Santiago Leon santil@us.ibm.com
+ *     Hollis Blanchard <hollisb@us.ibm.com>
  *
  *      This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -16,14 +17,16 @@
 #include <linux/pci.h>
 #include <linux/version.h>
 #include <linux/module.h>
+#include <linux/kobject.h>
+#include <linux/mm.h>
 #include <asm/rtas.h>
 #include <asm/pci_dma.h>
 #include <asm/dma.h>
 #include <asm/ppcdebug.h>
 #include <asm/vio.h>
 #include <asm/hvcall.h>
-#include <linux/mm.h>
-#include "open_pic.h" 	/* temporary, until we merge large irq support */
+
+#define DBGENTER() pr_debug("%s entered\n", __FUNCTION__)
 
 extern struct TceTable *build_tce_table(struct TceTable *tbl);
 
@@ -32,83 +35,74 @@ extern dma_addr_t get_tces(struct TceTab
 extern void tce_free(struct TceTable *tbl, dma_addr_t dma_addr,
 		     unsigned order, unsigned num_pages);
 
+static int vio_num_address_cells;
+static struct vio_dev *vio_bus_device; /* fake "parent" device */
 
-static struct vio_bus vio_bus;
-static LIST_HEAD(registered_vio_drivers);
-int vio_num_address_cells;
-EXPORT_SYMBOL(vio_num_address_cells);
-
-/* TODO:
- *   really fit into driver model (see include/linux/device.h)
- *   locking around list accesses
- */
+/* convert from struct device to struct vio_dev and pass to driver.
+ * dev->driver has already been set by generic code because vio_bus_match
+ * succeeded. */
+static int vio_bus_probe(struct device *dev)
+{
+	struct vio_dev *viodev = to_vio_dev(dev);
+	struct vio_driver *viodrv = to_vio_driver(dev->driver);
+	const struct vio_device_id *id;
+	int error = -ENODEV;
+
+	DBGENTER();
+
+	if (!viodrv->probe)
+		return error;
+
+	id = vio_match_device(viodrv->id_table, viodev);
+	if (id) {
+		error = viodrv->probe(viodev, id);
+	}
+
+	return error;
+}
+
+/* convert from struct device to struct vio_dev and pass to driver. */
+static int vio_bus_remove(struct device *dev)
+{
+	struct vio_dev *viodev = to_vio_dev(dev);
+	struct vio_driver *viodrv = to_vio_driver(dev->driver);
+
+	DBGENTER();
+
+	if (viodrv->remove) {
+		return viodrv->remove(viodev);
+	}
+
+	/* driver can't remove */
+	return 1;
+}
 
 /**
  * vio_register_driver: - Register a new vio driver
  * @drv:	The vio_driver structure to be registered.
- *
- * Adds the driver structure to the list of registered drivers
- * Returns the number of vio devices which were claimed by the driver
- * during registration.  The driver remains registered even if the
- * return value is zero.
  */
-int vio_register_driver(struct vio_driver *drv)
+int vio_register_driver(struct vio_driver *viodrv)
 {
-	int count = 0;
-	struct vio_dev *dev;
-
-	printk(KERN_DEBUG "%s: driver %s/%s registering\n", __FUNCTION__,
-		drv->id_table[0].type, drv->id_table[0].type);
-
-	/* find matching devices not already claimed by other drivers and pass
-	 * them to probe() */
-	list_for_each_entry(dev, &vio_bus.devices, devices_list) {
-		const struct vio_device_id* id;
-
-		if (dev->driver)
-			continue; /* this device is already owned */
-
-		id = vio_match_device(drv->id_table, dev);
-		if (drv && id) {
-			if (0 == drv->probe(dev, id)) {
-				printk(KERN_DEBUG "  took device %p\n", dev);
-				dev->driver = drv;
-				count++;
-			}
-		}
-	}
+	printk(KERN_DEBUG "%s: driver %s registering\n", __FUNCTION__,
+		viodrv->name);
 
-	list_add_tail(&drv->node, &registered_vio_drivers);
+	/* fill in 'struct driver' fields */
+	viodrv->driver.name = viodrv->name;
+	viodrv->driver.bus = &vio_bus_type;
+	viodrv->driver.probe = vio_bus_probe;
+	viodrv->driver.remove = vio_bus_remove;
 
-	return count;
+	return driver_register(&viodrv->driver);
 }
 EXPORT_SYMBOL(vio_register_driver);
 
 /**
  * vio_unregister_driver - Remove registration of vio driver.
  * @driver:	The vio_driver struct to be removed form registration
- *
- * Searches for devices that are assigned to the driver and calls
- * driver->remove() for each one.  Removes the driver from the list
- * of registered drivers.  Returns the number of devices that were
- * assigned to that driver.
  */
-int vio_unregister_driver(struct vio_driver *driver)
+void vio_unregister_driver(struct vio_driver *viodrv)
 {
-	struct vio_dev *dev;
-	int devices_found = 0;
-
-	list_for_each_entry(dev, &vio_bus.devices, devices_list) {
-		if (dev->driver == driver) {
-			driver->remove(dev);
-			dev->driver = NULL;
-			devices_found++;
-		}
-	}
-
-	list_del(&driver->node);
-
-	return devices_found;
+	driver_unregister(&viodrv->driver);
 }
 EXPORT_SYMBOL(vio_unregister_driver);
 
@@ -121,9 +115,11 @@ EXPORT_SYMBOL(vio_unregister_driver);
  * system is in its list of supported devices. Returns the matching
  * vio_device_id structure or NULL if there is no match.
  */
-const struct vio_device_id *
-vio_match_device(const struct vio_device_id *ids, const struct vio_dev *dev)
+const struct vio_device_id * vio_match_device(const struct vio_device_id *ids,
+	const struct vio_dev *dev)
 {
+	DBGENTER();
+
 	while (ids->type) {
 		if ((strncmp(dev->archdata->type, ids->type, strlen(ids->type)) == 0) &&
 			device_is_compatible((struct device_node*)dev->archdata, ids->compat))
@@ -136,18 +132,33 @@ vio_match_device(const struct vio_device
 /**
  * vio_bus_init: - Initialize the virtual IO bus
  */
-int __init
-vio_bus_init(void)
+static int __init vio_bus_init(void)
 {
-	struct device_node *node_vroot, *node_vdev;
+	struct device_node *node_vroot, *of_node;
+	int err;
 
-	INIT_LIST_HEAD(&vio_bus.devices);
+	err = bus_register(&vio_bus_type);
+	if (err) {
+		printk(KERN_ERR "failed to register VIO bus\n");
+		return err;
+	}
+
+	/* the fake parent of all vio devices, just to give us a nice directory */
+	vio_bus_device = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
+	if (!vio_bus_device) {
+		return 1;
+	}
+	memset(vio_bus_device, 0, sizeof(struct vio_dev));
+	strcpy(vio_bus_device->dev.bus_id, "vdevice");
+
+	err = device_register(&vio_bus_device->dev);
+	if (err) {
+		printk(KERN_WARNING "%s: device_register returned %i\n", __FUNCTION__,
+			err);
+		kfree(vio_bus_device);
+		return err;
+	}
 
-	/*
-	 * Create device node entries for each virtual device
-	 * identified in the device tree.
-	 * Functionally takes the place of pci_scan_bus
-	 */
 	node_vroot = find_devices("vdevice");
 	if ((node_vroot == NULL) || (node_vroot->child == NULL)) {
 		printk(KERN_INFO "VIO: missing or empty /vdevice node; no virtual IO"
@@ -157,12 +168,16 @@ vio_bus_init(void)
 
 	vio_num_address_cells = prom_n_addr_cells(node_vroot->child);
 
-	for (node_vdev = node_vroot->child;
-			node_vdev != NULL;
-			node_vdev = node_vdev->sibling) {
-		printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, node_vdev);
+	/*
+	 * Create struct vio_devices for each virtual device in the device tree.
+	 * Drivers will associate with them later.
+	 */
+	for (of_node = node_vroot->child;
+			of_node != NULL;
+			of_node = of_node->sibling) {
+		printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node);
 
-		vio_register_device(node_vdev);
+		vio_register_device(of_node);
 	}
 
 	return 0;
@@ -171,98 +186,91 @@ vio_bus_init(void)
 __initcall(vio_bus_init);
 
 
-/**
- * vio_probe_device - attach dev to appropriate driver
- * @dev:	device to find a driver for
- *
- * Walks the list of registered VIO drivers looking for one to take this
- * device.
- *
- * Returns a pointer to the matched driver or NULL if driver is not
- * found.
- */
-struct vio_driver * __devinit vio_probe_device(struct vio_dev* dev)
+/* vio_dev refcount hit 0 */
+static void __devinit vio_dev_release(struct device *dev)
 {
-	struct vio_driver *driver;
-
-	list_for_each_entry(driver, &registered_vio_drivers, node) {
-		const struct vio_device_id* id;
+	struct vio_dev *viodev = to_vio_dev(dev);
 
-		id = vio_match_device(driver->id_table, dev);
-		if (id && (0 < driver->probe(dev, id))) {
-			printk(KERN_DEBUG "%s: driver %s/%s took device %p\n",
-				__FUNCTION__, id->type, id->compat, dev);
-			dev->driver = driver;
-			return driver;
-		}
-	}
+	DBGENTER();
 
-	printk(KERN_DEBUG "%s: device %p found no driver\n", __FUNCTION__, dev);
-	return NULL;
+	/* XXX free TCE table */
+	of_node_put(viodev->archdata);
+	kfree(viodev);
 }
 
 /**
  * vio_register_device: - Register a new vio device.
- * @archdata:	The OF node for this device.
+ * @of_node:	The OF node for this device.
  *
  * Creates and initializes a vio_dev structure from the data in
- * node_vdev (archdata) and adds it to the list of virtual devices.
+ * of_node (archdata) and adds it to the list of virtual devices.
  * Returns a pointer to the created vio_dev or NULL if node has
  * NULL device_type or compatible fields.
  */
-struct vio_dev * __devinit vio_register_device(struct device_node *node_vdev)
+struct vio_dev * __devinit vio_register_device(struct device_node *of_node)
 {
-	struct vio_dev *dev;
+	struct vio_dev *viodev;
 	unsigned int *unit_address;
 	unsigned int *irq_p;
 
-	/* guarantee all vio_devs have 'device_type' field*/
-	if ((NULL == node_vdev->type)) {
+	DBGENTER();
+
+	/* we need the 'device_type' property, in order to match with drivers */
+	if ((NULL == of_node->type)) {
 		printk(KERN_WARNING
 			"%s: node %s missing 'device_type'\n", __FUNCTION__,
-			node_vdev->name ? node_vdev->name : "<unknown>");
+			of_node->name ? of_node->name : "<unknown>");
 		return NULL;
 	}
 
-	unit_address = (unsigned int *)get_property(node_vdev, "reg", NULL);
+	unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
 	if (!unit_address) {
 		printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__,
-			node_vdev->name ? node_vdev->name : "<unknown>");
+			of_node->name ? of_node->name : "<unknown>");
 		return NULL;
 	}
 
 	/* allocate a vio_dev for this node */
-	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev)
+	viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
+	if (!viodev) {
 		return NULL;
-	memset(dev, 0, sizeof(*dev));
-
-	dev->archdata = (void*)of_node_get(node_vdev);
-	dev->bus = &vio_bus;
-	dev->unit_address = *unit_address;
-	dev->tce_table = vio_build_tce_table(dev);
-
-	irq_p = (unsigned int *) get_property(node_vdev, "interrupts", 0);
-	if(irq_p) {
-		dev->irq = openpic_to_irq(virt_irq_create_mapping(*irq_p));
-	} else {
-		dev->irq = (unsigned int) -1;
 	}
+	memset(viodev, 0, sizeof(struct vio_dev));
 
-	list_add_tail(&dev->devices_list, &vio_bus.devices);
-
-	vio_probe_device(dev); /* finally, assign it to a driver */
+	viodev->archdata = (void *)of_node_get(of_node);
+	viodev->unit_address = *unit_address;
+	viodev->tce_table = vio_build_tce_table(viodev);
+
+	viodev->irq = (unsigned int) -1;
+	irq_p = (unsigned int *)get_property(of_node, "interrupts", 0);
+	if (irq_p) {
+		viodev->irq = irq_offset_up(*irq_p);
+	}
+
+	/* init generic 'struct device' fields: */
+	viodev->dev.parent = &vio_bus_device->dev;
+	viodev->dev.bus = &vio_bus_type;
+	snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s@%lx",
+		of_node->name, viodev->unit_address);
+	viodev->dev.release = vio_dev_release;
+
+	/* register with generic device framework */
+	if (device_register(&viodev->dev)) {
+		printk(KERN_ERR "%s: failed to register device %s\n", __FUNCTION__,
+			viodev->dev.bus_id);
+		/* XXX free TCE table */
+		kfree(viodev);
+		return NULL;
+	}
 
-	return dev;
+	return viodev;
 }
 EXPORT_SYMBOL(vio_register_device);
 
-int __devinit vio_unregister_device(struct vio_dev *dev)
+void __devinit vio_unregister_device(struct vio_dev *viodev)
 {
-	list_del(&dev->devices_list);
-	of_node_put(dev->archdata);
-
-	return 0;
+	DBGENTER();
+	device_unregister(&viodev->dev);
 }
 EXPORT_SYMBOL(vio_unregister_device);
 
@@ -531,6 +539,30 @@ void vio_free_consistent(struct vio_dev 
 	}
 }
 EXPORT_SYMBOL(vio_free_consistent);
+
+static int vio_bus_match(struct device *dev, struct device_driver *drv)
+{
+	const struct vio_dev *vio_dev = to_vio_dev(dev);
+	struct vio_driver *vio_drv = to_vio_driver(drv);
+	const struct vio_device_id *ids = vio_drv->id_table;
+	const struct vio_device_id *found_id;
+
+	DBGENTER();
+
+	if (!ids)
+		return 0;
+
+	found_id = vio_match_device(ids, vio_dev);
+	if (found_id)
+		return 1;
+
+	return 0;
+}
+
+struct bus_type vio_bus_type = {
+	.name = "vio",
+	.match = vio_bus_match,
+};
 
 EXPORT_SYMBOL(plpar_hcall_norets);
 EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/mm/numa.c 110-ppc64_update/arch/ppc64/mm/numa.c
--- 107-kgdb_gdb6_patches/arch/ppc64/mm/numa.c	Wed Feb  4 23:03:18 2004
+++ 110-ppc64_update/arch/ppc64/mm/numa.c	Mon Feb  9 10:06:05 2004
@@ -273,8 +273,8 @@ void __init do_init_bootmem(void)
 					physbase = start_paddr;
 				}
 
-				if (size > end_paddr - start_paddr)
-					size = end_paddr - start_paddr;
+				if (size > end_paddr - physbase)
+					size = end_paddr - physbase;
 
 				dbg("free_bootmem %lx %lx\n", physbase, size);
 				free_bootmem_node(NODE_DATA(nid), physbase,
@@ -294,8 +294,8 @@ void __init do_init_bootmem(void)
 					physbase = start_paddr;
 				}
 
-				if (size > end_paddr - start_paddr)
-					size = end_paddr - start_paddr;
+				if (size > end_paddr - physbase)
+					size = end_paddr - physbase;
 
 				dbg("reserve_bootmem %lx %lx\n", physbase,
 				    size);
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/xmon/start.c 110-ppc64_update/arch/ppc64/xmon/start.c
--- 107-kgdb_gdb6_patches/arch/ppc64/xmon/start.c	Wed Feb  4 23:03:18 2004
+++ 110-ppc64_update/arch/ppc64/xmon/start.c	Mon Feb  9 10:06:05 2004
@@ -41,7 +41,7 @@ static void sysrq_handle_xmon(int key, s
 static struct sysrq_key_op sysrq_xmon_op = 
 {
 	.handler =	sysrq_handle_xmon,
-	.help_msg =	"xmon",
+	.help_msg =	"Xmon",
 	.action_msg =	"Entering xmon\n",
 };
 
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/arch/ppc64/xmon/xmon.c 110-ppc64_update/arch/ppc64/xmon/xmon.c
--- 107-kgdb_gdb6_patches/arch/ppc64/xmon/xmon.c	Wed Feb  4 23:03:18 2004
+++ 110-ppc64_update/arch/ppc64/xmon/xmon.c	Mon Feb  9 10:06:05 2004
@@ -16,6 +16,7 @@
 #include <linux/reboot.h>
 #include <linux/delay.h>
 #include <linux/kallsyms.h>
+#include <linux/cpumask.h>
 
 #include <asm/ptrace.h>
 #include <asm/string.h>
@@ -37,7 +38,7 @@
 #define skipbl	xmon_skipbl
 
 #ifdef CONFIG_SMP
-volatile unsigned long cpus_in_xmon = 0;
+volatile cpumask_t cpus_in_xmon = CPU_MASK_NONE;
 static unsigned long got_xmon = 0;
 static volatile int take_xmon = -1;
 static volatile int leaving_xmon = 0;
@@ -288,17 +289,18 @@ xmon(struct pt_regs *excp)
 	leaving_xmon = 0;
 	/* possible race condition here if a CPU is held up and gets
 	 * here while we are exiting */
-	if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon)) {
+	if (cpu_test_and_set(smp_processor_id(), cpus_in_xmon)) {
 		/* xmon probably caused an exception itself */
 		printf("We are already in xmon\n");
 		for (;;)
-			;
+			cpu_relax();
 	}
 	while (test_and_set_bit(0, &got_xmon)) {
 		if (take_xmon == smp_processor_id()) {
 			take_xmon = -1;
 			break;
 		}
+		cpu_relax();
 	}
 	/*
 	 * XXX: breakpoints are removed while any cpu is in xmon
@@ -325,7 +327,7 @@ xmon(struct pt_regs *excp)
 	leaving_xmon = 1;
 	if (cmd != 's')
 		clear_bit(0, &got_xmon);
-	clear_bit(smp_processor_id(), &cpus_in_xmon);
+	cpu_clear(smp_processor_id(), cpus_in_xmon);
 #endif /* CONFIG_SMP */
 	set_msrd(msr);		/* restore interrupt enable */
 }
@@ -602,6 +604,7 @@ cmds(struct pt_regs *excp)
 			printf(" (type ? for help)\n");
 			break;
 		}
+		cpu_relax();
 	}
 }
 
@@ -638,7 +641,7 @@ static void cpu_cmd(void)
 		/* print cpus waiting or in xmon */
 		printf("cpus stopped:");
 		for (cpu = 0; cpu < NR_CPUS; ++cpu) {
-			if (test_bit(cpu, &cpus_in_xmon)) {
+			if (cpu_isset(cpu, cpus_in_xmon)) {
 				printf(" %x", cpu);
 				if (cpu == smp_processor_id())
 					printf("*", cpu);
@@ -664,6 +667,7 @@ static void cpu_cmd(void)
 			take_xmon = -1;
 			break;
 		}
+		cpu_relax();
 	}
 }
 #endif /* CONFIG_SMP */
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/drivers/char/hvc_console.c 110-ppc64_update/drivers/char/hvc_console.c
--- 107-kgdb_gdb6_patches/drivers/char/hvc_console.c	Mon Nov 17 18:28:44 2003
+++ 110-ppc64_update/drivers/char/hvc_console.c	Mon Feb  9 10:06:06 2004
@@ -29,6 +29,7 @@
 #include <linux/kbd_kern.h>
 #include <asm/uaccess.h>
 #include <linux/spinlock.h>
+#include <linux/cpumask.h>
 
 extern int hvc_count(int *);
 extern int hvc_get_chars(int index, char *buf, int count);
@@ -223,10 +224,10 @@ static void hvc_poll(int index)
 	spin_unlock_irqrestore(&hp->lock, flags);
 }
 
-#if defined (CONFIG_XMON)
-extern unsigned long cpus_in_xmon;
+#if defined(CONFIG_XMON) && defined(CONFIG_SMP)
+extern cpumask_t cpus_in_xmon;
 #else
-unsigned long cpus_in_xmon=0;
+static const cpumask_t cpus_in_xmon = CPU_MASK_NONE;
 #endif
 
 
@@ -237,7 +238,7 @@ int khvcd(void *unused)
 	daemonize("khvcd");
 
 	for (;;) {
-		if (!cpus_in_xmon) {
+		if (cpus_empty(cpus_in_xmon)) {
 			for (i = 0; i < MAX_NR_HVC_CONSOLES; ++i)
 				hvc_poll(i);
 		}
@@ -268,8 +269,9 @@ int __init hvc_init(void)
 		return -ENOMEM;
 
 	hvc_driver->owner = THIS_MODULE;
+	hvc_driver->devfs_name = "hvc/";
 	hvc_driver->driver_name = "hvc";
-	hvc_driver->name = "hvc/";
+	hvc_driver->name = "hvc";
 	hvc_driver->major = HVC_MAJOR;
 	hvc_driver->minor_start = HVC_MINOR;
 	hvc_driver->type = TTY_DRIVER_TYPE_SYSTEM;
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/include/asm-ppc64/hardirq.h 110-ppc64_update/include/asm-ppc64/hardirq.h
--- 107-kgdb_gdb6_patches/include/asm-ppc64/hardirq.h	Mon Nov 17 18:29:43 2003
+++ 110-ppc64_update/include/asm-ppc64/hardirq.h	Mon Feb  9 10:06:06 2004
@@ -80,7 +80,7 @@ typedef struct {
 
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 
-#ifdef CONFIG_PREEMPT
+#if defined(CONFIG_PREEMPT) || defined(CONFIG_DEBUG_SPINLOCK_SLEEP)
 # define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
 # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
 #else
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/include/asm-ppc64/hvcall.h 110-ppc64_update/include/asm-ppc64/hvcall.h
--- 107-kgdb_gdb6_patches/include/asm-ppc64/hvcall.h	Wed Feb  4 23:03:35 2004
+++ 110-ppc64_update/include/asm-ppc64/hvcall.h	Mon Feb  9 10:06:06 2004
@@ -102,6 +102,8 @@ long plpar_hcall(unsigned long opcode,
 		 unsigned long *out2,
 		 unsigned long *out3);
 
+#define HVSC			".long 0x44000022\n"
+
 /* Same as plpar_hcall but for those opcodes that return no values
  * other than status.  Slightly more efficient.
  */
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/include/asm-ppc64/hvconsole.h 110-ppc64_update/include/asm-ppc64/hvconsole.h
--- 107-kgdb_gdb6_patches/include/asm-ppc64/hvconsole.h	Wed Dec 31 16:00:00 1969
+++ 110-ppc64_update/include/asm-ppc64/hvconsole.h	Mon Feb  9 10:06:06 2004
@@ -0,0 +1,30 @@
+/*
+ * hvconsole.h
+ * Copyright (C) 2004 Ryan S Arnold, IBM Corporation
+ *
+ * LPAR console support.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef _PPC64_HVCONSOLE_H
+#define _PPC64_HVCONSOLE_H
+
+extern int hvc_get_chars(int index, char *buf, int count);
+extern int hvc_put_chars(int index, const char *buf, int count);
+extern int hvc_count(int *start_termno);
+
+#endif /* _PPC64_HVCONSOLE_H */
+
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/include/asm-ppc64/iSeries/vio.h 110-ppc64_update/include/asm-ppc64/iSeries/vio.h
--- 107-kgdb_gdb6_patches/include/asm-ppc64/iSeries/vio.h	Wed Feb  4 23:03:35 2004
+++ 110-ppc64_update/include/asm-ppc64/iSeries/vio.h	Mon Feb  9 10:06:06 2004
@@ -49,7 +49,7 @@
  * in.  We use a table to route these, and this defines
  * the maximum number of distinct subtypes
  */
-#define VIO_MAX_SUBTYPES 7
+#define VIO_MAX_SUBTYPES 8
 
 /* Each subtype can register a handler to process their events.
  * The handler must have this interface.
@@ -103,7 +103,8 @@ enum viosubtypes {
 	viomajorsubtype_chario = 0x0300,
 	viomajorsubtype_config = 0x0400,
 	viomajorsubtype_cdio = 0x0500,
-	viomajorsubtype_tape = 0x0600
+	viomajorsubtype_tape = 0x0600,
+	viomajorsubtype_scsi = 0x0700
 };
 
 
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/include/asm-ppc64/paca.h 110-ppc64_update/include/asm-ppc64/paca.h
--- 107-kgdb_gdb6_patches/include/asm-ppc64/paca.h	Wed Feb  4 23:03:35 2004
+++ 110-ppc64_update/include/asm-ppc64/paca.h	Mon Feb  9 10:06:06 2004
@@ -64,14 +64,13 @@ struct paca_struct {
         u16 xHwProcNum;                 /* Physical processor number            0x1A */
 	u32 default_decr;		/* Default decrementer value		0x1c */	
 	u64 xKsave;			/* Saved Kernel stack addr or zero	0x20 */
-	u64 pvr;			/* Processor version register		0x28 */
 	struct ItLpQueue *lpQueuePtr;	/* LpQueue handled by this processor    0x30 */
 	u64  xTOC;			/* Kernel TOC address			0x38 */
 	STAB xStab_data;		/* Segment table information		0x40,0x48,0x50 */
 	u8 *exception_sp;		/*                                      0x58 */
 	u8 xProcEnabled;		/*                                      0x59 */
 	u8 prof_enabled;		/* 1=iSeries profiling enabled          0x60 */
-	u8 resv1[30];			/*					0x61-0x7F */
+	u8 resv1[38];			/*					0x61-0x7F */
 
 /*=====================================================================================
  * CACHE_LINE_2 0x0080 - 0x00FF
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/include/asm-ppc64/pci.h 110-ppc64_update/include/asm-ppc64/pci.h
--- 107-kgdb_gdb6_patches/include/asm-ppc64/pci.h	Wed Feb  4 23:03:35 2004
+++ 110-ppc64_update/include/asm-ppc64/pci.h	Mon Feb  9 10:06:06 2004
@@ -19,6 +19,12 @@
 #define PCIBIOS_MIN_IO		0x1000
 #define PCIBIOS_MIN_MEM		0x10000000
 
+#ifdef CONFIG_PPC_ISERIES
+#define pcibios_scan_all_fns(a, b)	0
+#else
+extern int pcibios_scan_all_fns(struct pci_bus *bus, int devfn);
+#endif
+
 static inline void pcibios_set_master(struct pci_dev *dev)
 {
 	/* No special bus mastering setup handling */
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/include/asm-ppc64/vio.h 110-ppc64_update/include/asm-ppc64/vio.h
--- 107-kgdb_gdb6_patches/include/asm-ppc64/vio.h	Wed Feb  4 23:03:35 2004
+++ 110-ppc64_update/include/asm-ppc64/vio.h	Mon Feb  9 10:06:06 2004
@@ -16,6 +16,7 @@
 
 #include <linux/init.h>
 #include <linux/errno.h>
+#include <linux/device.h>
 #include <asm/hvcall.h>
 #include <asm/prom.h>
 #include <asm/scatterlist.h>
@@ -40,11 +41,11 @@ struct vio_device_id;
 struct TceTable;
 
 int vio_register_driver(struct vio_driver *drv);
-int vio_unregister_driver(struct vio_driver *drv);
+void vio_unregister_driver(struct vio_driver *drv);
 const struct vio_device_id * vio_match_device(const struct vio_device_id *ids, 
 						const struct vio_dev *dev);
 struct vio_dev * __devinit vio_register_device(struct device_node *node_vdev);
-int __devinit vio_unregister_device(struct vio_dev *dev);
+void __devinit vio_unregister_device(struct vio_dev *dev);
 const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length);
 int vio_get_irq(struct vio_dev *dev);
 struct TceTable * vio_build_tce_table(struct vio_dev *dev);
@@ -64,11 +65,11 @@ void *vio_alloc_consistent(struct vio_de
 void vio_free_consistent(struct vio_dev *dev, size_t size, void *vaddr, 
 			 dma_addr_t dma_handle);
 
+extern struct bus_type vio_bus_type;
+
 struct vio_device_id {
 	char *type;
 	char *compat;
-/* I don't think we need this
-	unsigned long driver_data;	*/ /* Data private to the driver */
 };
 
 struct vio_driver {
@@ -76,55 +77,33 @@ struct vio_driver {
 	char *name;
 	const struct vio_device_id *id_table;	/* NULL if wants all devices */
 	int  (*probe)  (struct vio_dev *dev, const struct vio_device_id *id);	/* New device inserted */
-	void (*remove) (struct vio_dev *dev);	/* Device removed (NULL if not a hot-plug capable driver) */
+	int (*remove) (struct vio_dev *dev);	/* Device removed (NULL if not a hot-plug capable driver) */
 	unsigned long driver_data;
+
+	struct device_driver driver;
 };
 
-struct vio_bus;
+static inline struct vio_driver *to_vio_driver(struct device_driver *drv)
+{
+	return container_of(drv, struct vio_driver, driver);
+}
+
 /*
  * The vio_dev structure is used to describe virtual I/O devices.
  */
 struct vio_dev {
-	struct list_head devices_list;   /* node in list of all vio devices */
-	struct device_node *archdata;    /* Open Firmware node */
-	struct vio_bus *bus;            /* bus this device is on */
-	struct vio_driver *driver;      /* owning driver */
+	struct device_node *archdata;   /* Open Firmware node */
 	void *driver_data;              /* data private to the driver */
 	unsigned long unit_address;	
-
-	struct TceTable *tce_table; /* vio_map_* uses this */
+	struct TceTable *tce_table;     /* vio_map_* uses this */
 	unsigned int irq;
-	struct proc_dir_entry *procent; /* device entry in /proc/bus/vio */
-};
 
-struct vio_bus {
-	struct list_head devices;       /* list of virtual devices */
+	struct device dev;
 };
 
-
-static inline int vio_module_init(struct vio_driver *drv)
+static inline struct vio_dev *to_vio_dev(struct device *dev)
 {
-        int rc = vio_register_driver (drv);
-
-        if (rc > 0)
-                return 0;
-
-        /* iff CONFIG_HOTPLUG and built into kernel, we should
-         * leave the driver around for future hotplug events.
-         * For the module case, a hotplug daemon of some sort
-         * should load a module in response to an insert event. */
-#if defined(CONFIG_HOTPLUG) && !defined(MODULE)
-        if (rc == 0)
-                return 0;
-#else
-        if (rc == 0)
-                rc = -ENODEV;
-#endif
-
-        /* if we get here, we need to clean up vio driver instance
-         * and return some sort of error */
-
-        return rc;
+	return container_of(dev, struct vio_dev, dev);
 }
 
 #endif /* _PHYP_H */
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/include/linux/preempt.h 110-ppc64_update/include/linux/preempt.h
--- 107-kgdb_gdb6_patches/include/linux/preempt.h	Mon Dec  8 09:55:53 2003
+++ 110-ppc64_update/include/linux/preempt.h	Mon Feb  9 10:06:06 2004
@@ -24,6 +24,17 @@ do { \
 
 extern void preempt_schedule(void);
 
+#define preempt_check_resched() \
+do { \
+	if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
+		preempt_schedule(); \
+} while (0)
+#else
+#define preempt_check_resched()		do { } while (0)
+#endif
+
+#if defined(CONFIG_PREEMPT) || defined(CONFIG_DEBUG_SPINLOCK_SLEEP)
+
 #define preempt_disable() \
 do { \
 	inc_preempt_count(); \
@@ -34,12 +45,6 @@ do { \
 do { \
 	barrier(); \
 	dec_preempt_count(); \
-} while (0)
-
-#define preempt_check_resched() \
-do { \
-	if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
-		preempt_schedule(); \
 } while (0)
 
 #define preempt_enable() \
diff -aurpN -X /home/fletch/.diff.exclude 107-kgdb_gdb6_patches/kernel/sched.c 110-ppc64_update/kernel/sched.c
--- 107-kgdb_gdb6_patches/kernel/sched.c	Mon Feb  9 09:04:07 2004
+++ 110-ppc64_update/kernel/sched.c	Mon Feb  9 10:06:06 2004
@@ -728,7 +728,7 @@ void sched_fork(task_t *p)
 	INIT_LIST_HEAD(&p->run_list);
 	p->array = NULL;
 	spin_lock_init(&p->switch_lock);
-#ifdef CONFIG_PREEMPT
+#if defined(CONFIG_PREEMPT) || defined(CONFIG_DEBUG_SPINLOCK_SLEEP)
 	/*
 	 * During context-switch we hold precisely one spinlock, which
 	 * schedule_tail drops. (in the common case it's this_rq()->lock,
@@ -2666,7 +2666,7 @@ void __init init_idle(task_t *idle, int 
 	local_irq_restore(flags);
 
 	/* Set the preempt count _outside_ the spinlocks! */
-#ifdef CONFIG_PREEMPT
+#if defined(CONFIG_PREEMPT) || defined(CONFIG_DEBUG_SPINLOCK_SLEEP)
 	idle->thread_info->preempt_count = (idle->lock_depth >= 0);
 #else
 	idle->thread_info->preempt_count = 0;