Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (21 commits)
  [TIPC]: Removing useless casts
  [IPV4]: Fix nexthop realm dumping for multipath routes
  [DUMMY]: Avoid an oops when dummy_init_one() failed
  [IFB] After ifb_init_one() failed, i is increased. Decrease
  [NET]: Fix reversed error test in netif_tx_trylock
  [MAINTAINERS]: Mark LAPB as Oprhan.
  [NET]: Conversions from kmalloc+memset to k(z|c)alloc.
  [NET]: sun happymeal, little pci cleanup
  [IrDA]: Use alloc_skb() in IrDA TX path
  [I/OAT]: Remove pci_module_init() from Intel I/OAT DMA engine
  [I/OAT]: net/core/user_dma.c should #include <net/netdma.h>
  [SCTP]: ADDIP: Don't use an address as source until it is ASCONF-ACKed
  [SCTP]: Set chunk->data_accepted only if we are going to accept it.
  [SCTP]: Verify all the paths to a peer via heartbeat before using them.
  [SCTP]: Unhash the endpoint in sctp_endpoint_free().
  [SCTP]: Check for NULL arg to sctp_bucket_destroy().
  [PKT_SCHED] netem: Fix slab corruption with netem (2nd try)
  [WAN]: Converted synclink drivers to use netif_carrier_*()
  [WAN]: Cosmetic changes to N2 and C101 drivers
  [WAN]: Added missing netif_dormant_off() to generic HDLC
  ...
diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c
index adba9df..af90a5f 100644
--- a/arch/sparc/kernel/devices.c
+++ b/arch/sparc/kernel/devices.c
@@ -15,6 +15,7 @@
 
 #include <asm/page.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 #include <asm/smp.h>
 #include <asm/system.h>
 #include <asm/cpudata.h>
@@ -34,12 +35,6 @@
 			  int (*compare)(int, int, void *), void *compare_arg,
 			  int *prom_node, int *mid)
 {
-	char node_str[128];
-
-	prom_getstring(nd, "device_type", node_str, sizeof(node_str));
-	if (strcmp(node_str, "cpu"))
-		return -ENODEV;
-	
 	if (!compare(nd, *cur_inst, compare_arg)) {
 		if (prom_node)
 			*prom_node = nd;
@@ -59,20 +54,14 @@
 static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
 			 int *prom_node, int *mid)
 {
-	int nd, cur_inst, err;
+	struct device_node *dp;
+	int cur_inst;
 
-	nd = prom_root_node;
 	cur_inst = 0;
-
-	err = check_cpu_node(nd, &cur_inst, compare, compare_arg,
-			     prom_node, mid);
-	if (!err)
-		return 0;
-
-	nd = prom_getchild(nd);
-	while ((nd = prom_getsibling(nd)) != 0) {
-		err = check_cpu_node(nd, &cur_inst, compare, compare_arg,
-				     prom_node, mid);
+	for_each_node_by_type(dp, "cpu") {
+		int err = check_cpu_node(dp->node, &cur_inst,
+					 compare, compare_arg,
+					 prom_node, mid);
 		if (!err)
 			return 0;
 	}
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index cde7332..72f0201 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -329,7 +329,7 @@
 	disable_pil_irq(irq);
 #ifdef CONFIG_SMP
 	/* Only rotate on lower priority IRQ's (scsi, ethernet, etc.). */
-	if(irq < 10)
+	if((sparc_cpu_model==sun4m) && (irq < 10))
 		smp4m_irq_rotate(cpu);
 #endif
 	action = sparc_irq[irq].action;
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c
index 5a2faad..97bf87e8 100644
--- a/arch/sparc/kernel/of_device.c
+++ b/arch/sparc/kernel/of_device.c
@@ -596,14 +596,41 @@
 		static int pil_to_sbus[] = {
 			0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0,
 		};
-		struct device_node *busp = dp->parent;
+		struct device_node *io_unit, *sbi = dp->parent;
 		struct linux_prom_registers *regs;
-		int board = of_getintprop_default(busp, "board#", 0);
-		int slot;
+		int board, slot;
+
+		while (sbi) {
+			if (!strcmp(sbi->name, "sbi"))
+				break;
+
+			sbi = sbi->parent;
+		}
+		if (!sbi)
+			goto build_resources;
 
 		regs = of_get_property(dp, "reg", NULL);
+		if (!regs)
+			goto build_resources;
+
 		slot = regs->which_io;
 
+		/* If SBI's parent is not io-unit or the io-unit lacks
+		 * a "board#" property, something is very wrong.
+		 */
+		if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) {
+			printk("%s: Error, parent is not io-unit.\n",
+			       sbi->full_name);
+			goto build_resources;
+		}
+		io_unit = sbi->parent;
+		board = of_getintprop_default(io_unit, "board#", -1);
+		if (board == -1) {
+			printk("%s: Error, lacks board# property.\n",
+			       io_unit->full_name);
+			goto build_resources;
+		}
+
 		for (i = 0; i < op->num_irqs; i++) {
 			int this_irq = op->irqs[i];
 			int sbusl = pil_to_sbus[this_irq];
@@ -617,6 +644,7 @@
 		}
 	}
 
+build_resources:
 	build_device_resources(op, parent);
 
 	op->dev.parent = parent;
diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c
index 4b06dcb..4ca9e5f 100644
--- a/arch/sparc/kernel/prom.c
+++ b/arch/sparc/kernel/prom.c
@@ -444,6 +444,7 @@
 	static struct property *tmp = NULL;
 	struct property *p;
 	int len;
+	const char *name;
 
 	if (tmp) {
 		p = tmp;
@@ -456,19 +457,21 @@
 
 	p->name = (char *) (p + 1);
 	if (special_name) {
+		strcpy(p->name, special_name);
 		p->length = special_len;
 		p->value = prom_early_alloc(special_len);
 		memcpy(p->value, special_val, special_len);
 	} else {
 		if (prev == NULL) {
-			prom_firstprop(node, p->name);
+			name = prom_firstprop(node, NULL);
 		} else {
-			prom_nextprop(node, prev, p->name);
+			name = prom_nextprop(node, prev, NULL);
 		}
-		if (strlen(p->name) == 0) {
+		if (strlen(name) == 0) {
 			tmp = p;
 			return NULL;
 		}
+		strcpy(p->name, name);
 		p->length = prom_getproplen(node, p->name);
 		if (p->length <= 0) {
 			p->length = 0;
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 6135d4f..e311ade 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -87,6 +87,7 @@
 void __init smp_cpus_done(unsigned int max_cpus)
 {
 	extern void smp4m_smp_done(void);
+	extern void smp4d_smp_done(void);
 	unsigned long bogosum = 0;
 	int cpu, num;
 
@@ -100,8 +101,34 @@
 		num, bogosum/(500000/HZ),
 		(bogosum/(5000/HZ))%100);
 
-	BUG_ON(sparc_cpu_model != sun4m);
-	smp4m_smp_done();
+	switch(sparc_cpu_model) {
+	case sun4:
+		printk("SUN4\n");
+		BUG();
+		break;
+	case sun4c:
+		printk("SUN4C\n");
+		BUG();
+		break;
+	case sun4m:
+		smp4m_smp_done();
+		break;
+	case sun4d:
+		smp4d_smp_done();
+		break;
+	case sun4e:
+		printk("SUN4E\n");
+		BUG();
+		break;
+	case sun4u:
+		printk("SUN4U\n");
+		BUG();
+		break;
+	default:
+		printk("UNKNOWN!\n");
+		BUG();
+		break;
+	};
 }
 
 void cpu_panic(void)
@@ -267,9 +294,9 @@
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
 	extern void smp4m_boot_cpus(void);
+	extern void smp4d_boot_cpus(void);
 	int i, cpuid, extra;
 
-	BUG_ON(sparc_cpu_model != sun4m);
 	printk("Entering SMP Mode...\n");
 
 	extra = 0;
@@ -283,7 +310,34 @@
 
 	smp_store_cpu_info(boot_cpu_id);
 
-	smp4m_boot_cpus();
+	switch(sparc_cpu_model) {
+	case sun4:
+		printk("SUN4\n");
+		BUG();
+		break;
+	case sun4c:
+		printk("SUN4C\n");
+		BUG();
+		break;
+	case sun4m:
+		smp4m_boot_cpus();
+		break;
+	case sun4d:
+		smp4d_boot_cpus();
+		break;
+	case sun4e:
+		printk("SUN4E\n");
+		BUG();
+		break;
+	case sun4u:
+		printk("SUN4U\n");
+		BUG();
+		break;
+	default:
+		printk("UNKNOWN!\n");
+		BUG();
+		break;
+	};
 }
 
 /* Set this up early so that things like the scheduler can init
@@ -323,9 +377,37 @@
 int __cpuinit __cpu_up(unsigned int cpu)
 {
 	extern int smp4m_boot_one_cpu(int);
-	int ret;
+	extern int smp4d_boot_one_cpu(int);
+	int ret=0;
 
-	ret = smp4m_boot_one_cpu(cpu);
+	switch(sparc_cpu_model) {
+	case sun4:
+		printk("SUN4\n");
+		BUG();
+		break;
+	case sun4c:
+		printk("SUN4C\n");
+		BUG();
+		break;
+	case sun4m:
+		ret = smp4m_boot_one_cpu(cpu);
+		break;
+	case sun4d:
+		ret = smp4d_boot_one_cpu(cpu);
+		break;
+	case sun4e:
+		printk("SUN4E\n");
+		BUG();
+		break;
+	case sun4u:
+		printk("SUN4U\n");
+		BUG();
+		break;
+	default:
+		printk("UNKNOWN!\n");
+		BUG();
+		break;
+	};
 
 	if (!ret) {
 		cpu_set(cpu, smp_commenced_mask);
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 5fb987f..4d441a5 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -237,7 +237,6 @@
 EXPORT_SYMBOL(prom_setprop);
 EXPORT_SYMBOL(saved_command_line);
 EXPORT_SYMBOL(prom_apply_obio_ranges);
-EXPORT_SYMBOL(prom_getname);
 EXPORT_SYMBOL(prom_feval);
 EXPORT_SYMBOL(prom_getbool);
 EXPORT_SYMBOL(prom_getstring);
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index b141b7e..ba843f6 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -43,15 +43,10 @@
 extern void calibrate_delay(void);
 
 extern volatile int smp_processors_ready;
-extern int smp_num_cpus;
 static int smp_highest_cpu;
 extern volatile unsigned long cpu_callin_map[NR_CPUS];
 extern cpuinfo_sparc cpu_data[NR_CPUS];
 extern unsigned char boot_cpu_id;
-extern int smp_activated;
-extern volatile int __cpu_number_map[NR_CPUS];
-extern volatile int __cpu_logical_map[NR_CPUS];
-extern volatile unsigned long ipi_count;
 extern volatile int smp_process_available;
 
 extern cpumask_t smp_commenced_mask;
@@ -144,6 +139,8 @@
 	spin_lock_irqsave(&sun4d_imsk_lock, flags);
 	cc_set_imsk(cc_get_imsk() & ~0x4000); /* Allow PIL 14 as well */
 	spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
+	cpu_set(cpuid, cpu_online_map);
+
 }
 
 extern void init_IRQ(void);
@@ -160,51 +157,24 @@
 
 void __init smp4d_boot_cpus(void)
 {
-	int cpucount = 0;
-	int i, mid;
-
-	printk("Entering SMP Mode...\n");
-	
 	if (boot_cpu_id)
 		current_set[0] = NULL;
-
-	local_irq_enable();
-	cpus_clear(cpu_present_map);
-
-	/* XXX This whole thing has to go.  See sparc64. */
-	for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++)
-		cpu_set(mid, cpu_present_map);
-	SMP_PRINTK(("cpu_present_map %08lx\n", cpus_addr(cpu_present_map)[0]));
-	for(i=0; i < NR_CPUS; i++)
-		__cpu_number_map[i] = -1;
-	for(i=0; i < NR_CPUS; i++)
-		__cpu_logical_map[i] = -1;
-	__cpu_number_map[boot_cpu_id] = 0;
-	__cpu_logical_map[0] = boot_cpu_id;
-	current_thread_info()->cpu = boot_cpu_id;
-	smp_store_cpu_info(boot_cpu_id);
 	smp_setup_percpu_timer();
 	local_flush_cache_all();
-	if (cpu_find_by_instance(1, NULL, NULL))
-		return;  /* Not an MP box. */
-	SMP_PRINTK(("Iterating over CPUs\n"));
-	for(i = 0; i < NR_CPUS; i++) {
-		if(i == boot_cpu_id)
-			continue;
+}
 
-		if (cpu_isset(i, cpu_present_map)) {
+int smp4d_boot_one_cpu(int i)
+{
 			extern unsigned long sun4d_cpu_startup;
 			unsigned long *entry = &sun4d_cpu_startup;
 			struct task_struct *p;
 			int timeout;
-			int no;
+			int cpu_node;
 
+			cpu_find_by_instance(i, &cpu_node,NULL);
 			/* Cook up an idler for this guy. */
 			p = fork_idle(i);
-			cpucount++;
 			current_set[i] = task_thread_info(p);
-			for (no = 0; !cpu_find_by_instance(no, NULL, &mid)
-				     && mid != i; no++) ;
 
 			/*
 			 * Initialize the contexts table
@@ -216,9 +186,9 @@
 			smp_penguin_ctable.reg_size = 0;
 
 			/* whirrr, whirrr, whirrrrrrrrr... */
-			SMP_PRINTK(("Starting CPU %d at %p task %d node %08x\n", i, entry, cpucount, cpu_data(no).prom_node));
+			SMP_PRINTK(("Starting CPU %d at %p \n", i, entry));
 			local_flush_cache_all();
-			prom_startcpu(cpu_data(no).prom_node,
+			prom_startcpu(cpu_node,
 				      &smp_penguin_ctable, 0, (char *)entry);
 				      
 			SMP_PRINTK(("prom_startcpu returned :)\n"));
@@ -230,39 +200,30 @@
 				udelay(200);
 			}
 			
-			if(cpu_callin_map[i]) {
-				/* Another "Red Snapper". */
-				__cpu_number_map[i] = cpucount;
-				__cpu_logical_map[cpucount] = i;
-			} else {
-				cpucount--;
-				printk("Processor %d is stuck.\n", i);
-			}
-		}
-		if(!(cpu_callin_map[i])) {
-			cpu_clear(i, cpu_present_map);
-			__cpu_number_map[i] = -1;
-		}
+	if (!(cpu_callin_map[i])) {
+		printk("Processor %d is stuck.\n", i);
+		return -ENODEV;
+
 	}
 	local_flush_cache_all();
-	if(cpucount == 0) {
-		printk("Error: only one Processor found.\n");
-		cpu_present_map = cpumask_of_cpu(hard_smp4d_processor_id());
-	} else {
-		unsigned long bogosum = 0;
-		
-		for_each_present_cpu(i) {
-			bogosum += cpu_data(i).udelay_val;
-			smp_highest_cpu = i;
+	return 0;
+}
+
+void __init smp4d_smp_done(void)
+{
+	int i, first;
+	int *prev;
+
+	/* setup cpu list for irq rotation */
+	first = 0;
+	prev = &first;
+	for (i = 0; i < NR_CPUS; i++)
+		if (cpu_online(i)) {
+			*prev = i;
+			prev = &cpu_data(i).next;
 		}
-		SMP_PRINTK(("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, bogosum/(500000/HZ), (bogosum/(5000/HZ))%100));
-		printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n",
-		       cpucount + 1,
-		       bogosum/(500000/HZ),
-		       (bogosum/(5000/HZ))%100);
-		smp_activated = 1;
-		smp_num_cpus = cpucount + 1;
-	}
+	*prev = first;
+	local_flush_cache_all();
 
 	/* Free unneeded trap tables */
 	ClearPageReserved(virt_to_page(trapbase_cpu1));
@@ -334,7 +295,7 @@
 			register int i;
 
 			mask = cpumask_of_cpu(hard_smp4d_processor_id());
-			cpus_andnot(mask, cpu_present_map, mask);
+			cpus_andnot(mask, cpu_online_map, mask);
 			for(i = 0; i <= high; i++) {
 				if (cpu_isset(i, mask)) {
 					ccall_info.processors_in[i] = 0;
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index 0cdfc9d..a41c8a5 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -465,21 +465,21 @@
 
 asmlinkage int sys_getdomainname(char __user *name, int len)
 {
- 	int nlen;
- 	int err = -EFAULT;
+ 	int nlen, err;
  	
+	if (len < 0 || len > __NEW_UTS_LEN)
+		return -EINVAL;
+
  	down_read(&uts_sem);
  	
 	nlen = strlen(system_utsname.domainname) + 1;
-
 	if (nlen < len)
 		len = nlen;
-	if (len > __NEW_UTS_LEN)
-		goto done;
-	if (copy_to_user(name, system_utsname.domainname, len))
-		goto done;
-	err = 0;
-done:
+
+	err = -EFAULT;
+	if (!copy_to_user(name, system_utsname.domainname, len))
+		err = 0;
+
 	up_read(&uts_sem);
 	return err;
 }
diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c
index 42c1c70..2bb1309 100644
--- a/arch/sparc/mm/io-unit.c
+++ b/arch/sparc/mm/io-unit.c
@@ -64,6 +64,7 @@
 	
 	sbus->iommu = (struct iommu_struct *)iounit;
 	iounit->page_table = xpt;
+	spin_lock_init(&iounit->lock);
 	
 	for (xptend = iounit->page_table + (16 * PAGE_SIZE) / sizeof(iopte_t);
 	     xpt < xptend;)
diff --git a/arch/sparc/prom/tree.c b/arch/sparc/prom/tree.c
index 2bf03ee..5ec2465 100644
--- a/arch/sparc/prom/tree.c
+++ b/arch/sparc/prom/tree.c
@@ -205,24 +205,6 @@
 	return 0;
 }
 
-/* Gets name in the form prom v2+ uses it (name@x,yyyyy or name (if no reg)) */
-int prom_getname (int node, char *buffer, int len)
-{
-	int i;
-	struct linux_prom_registers reg[PROMREG_MAX];
-	
-	i = prom_getproperty (node, "name", buffer, len);
-	if (i <= 0) return -1;
-	buffer [i] = 0;
-	len -= i;
-	i = prom_getproperty (node, "reg", (char *)reg, sizeof (reg));
-	if (i <= 0) return 0;
-	if (len < 11) return -1;
-	buffer = strchr (buffer, 0);
-	sprintf (buffer, "@%x,%x", reg[0].which_io, (uint)reg[0].phys_addr);
-	return 0;
-}
-
 /* Interal version of nextprop that does not alter return values. */
 char * __prom_nextprop(int node, char * oprop)
 {
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 3835362..43d9229 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Wed Jul 12 14:00:58 2006
+# Linux kernel version: 2.6.18-rc2
+# Fri Jul 21 14:19:24 2006
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -36,6 +36,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
@@ -1120,7 +1121,7 @@
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
@@ -1279,7 +1280,6 @@
 # CONFIG_NFSD is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c
index f8ef2f2..ec10f7e 100644
--- a/arch/sparc64/kernel/devices.c
+++ b/arch/sparc64/kernel/devices.c
@@ -66,9 +66,6 @@
 			  void *compare_arg,
 			  struct device_node **dev_node, int *mid)
 {
-	if (strcmp(dp->type, "cpu"))
-		return -ENODEV;
-
 	if (!compare(dp, *cur_inst, compare_arg)) {
 		if (dev_node)
 			*dev_node = dp;
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index 7064cee..238bbf6 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -542,9 +542,17 @@
 	/* Convert to num-cells.  */
 	num_reg /= 4;
 
-	/* Conver to num-entries.  */
+	/* Convert to num-entries.  */
 	num_reg /= na + ns;
 
+	/* Prevent overruning the op->resources[] array.  */
+	if (num_reg > PROMREG_MAX) {
+		printk(KERN_WARNING "%s: Too many regs (%d), "
+		       "limiting to %d.\n",
+		       op->node->full_name, num_reg, PROMREG_MAX);
+		num_reg = PROMREG_MAX;
+	}
+
 	for (index = 0; index < num_reg; index++) {
 		struct resource *r = &op->resource[index];
 		u32 addr[OF_MAX_ADDR_CELLS];
@@ -650,8 +658,22 @@
 	next:
 		imap += (na + 3);
 	}
-	if (i == imlen)
+	if (i == imlen) {
+		/* Psycho and Sabre PCI controllers can have 'interrupt-map'
+		 * properties that do not include the on-board device
+		 * interrupts.  Instead, the device's 'interrupts' property
+		 * is already a fully specified INO value.
+		 *
+		 * Handle this by deciding that, if we didn't get a
+		 * match in the parent's 'interrupt-map', and the
+		 * parent is an IRQ translater, then use the parent as
+		 * our IRQ controller.
+		 */
+		if (pp->irq_trans)
+			return pp;
+
 		return NULL;
+	}
 
 	*irq_p = irq;
 	cp = of_find_node_by_phandle(handle);
@@ -803,6 +825,14 @@
 		op->num_irqs = 0;
 	}
 
+	/* Prevent overruning the op->irqs[] array.  */
+	if (op->num_irqs > PROMINTR_MAX) {
+		printk(KERN_WARNING "%s: Too many irqs (%d), "
+		       "limiting to %d.\n",
+		       dp->full_name, op->num_irqs, PROMINTR_MAX);
+		op->num_irqs = PROMINTR_MAX;
+	}
+
 	build_device_resources(op, parent);
 	for (i = 0; i < op->num_irqs; i++)
 		op->irqs[i] = build_one_device_irq(op, parent, op->irqs[i]);
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index c86007a..5cc5ab6 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -344,10 +344,12 @@
 /*0x2f*/	PSYCHO_IMAP_CE,
 /*0x30*/	PSYCHO_IMAP_A_ERR,
 /*0x31*/	PSYCHO_IMAP_B_ERR,
-/*0x32*/	PSYCHO_IMAP_PMGMT
+/*0x32*/	PSYCHO_IMAP_PMGMT,
+/*0x33*/	PSYCHO_IMAP_GFX,
+/*0x34*/	PSYCHO_IMAP_EUPA,
 };
 #define PSYCHO_ONBOARD_IRQ_BASE		0x20
-#define PSYCHO_ONBOARD_IRQ_LAST		0x32
+#define PSYCHO_ONBOARD_IRQ_LAST		0x34
 #define psycho_onboard_imap_offset(__ino) \
 	__psycho_onboard_imap_off[(__ino) - PSYCHO_ONBOARD_IRQ_BASE]
 
@@ -529,6 +531,10 @@
 /*0x2e*/	SABRE_IMAP_UE,
 /*0x2f*/	SABRE_IMAP_CE,
 /*0x30*/	SABRE_IMAP_PCIERR,
+/*0x31*/	0 /* reserved */,
+/*0x32*/	0 /* reserved */,
+/*0x33*/	SABRE_IMAP_GFX,
+/*0x34*/	SABRE_IMAP_EUPA,
 };
 #define SABRE_ONBOARD_IRQ_BASE		0x20
 #define SABRE_ONBOARD_IRQ_LAST		0x30
@@ -895,6 +901,8 @@
 	SYSIO_IMAP_CE,
 	SYSIO_IMAP_SBERR,
 	SYSIO_IMAP_PMGMT,
+	SYSIO_IMAP_GFX,
+	SYSIO_IMAP_EUPA,
 };
 
 #undef bogon
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 237524d..beffc82 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -254,7 +254,6 @@
 EXPORT_SYMBOL(prom_node_has_property);
 EXPORT_SYMBOL(prom_setprop);
 EXPORT_SYMBOL(saved_command_line);
-EXPORT_SYMBOL(prom_getname);
 EXPORT_SYMBOL(prom_finddevice);
 EXPORT_SYMBOL(prom_feval);
 EXPORT_SYMBOL(prom_getbool);
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index 51c056d..054d0ab 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -701,21 +701,21 @@
 
 asmlinkage long sys_getdomainname(char __user *name, int len)
 {
-        int nlen;
-	int err = -EFAULT;
+        int nlen, err;
+
+	if (len < 0 || len > __NEW_UTS_LEN)
+		return -EINVAL;
 
  	down_read(&uts_sem);
  	
 	nlen = strlen(system_utsname.domainname) + 1;
-
         if (nlen < len)
                 len = nlen;
-	if (len > __NEW_UTS_LEN)
-		goto done;
-	if (copy_to_user(name, system_utsname.domainname, len))
-		goto done;
-	err = 0;
-done:
+
+	err = -EFAULT;
+	if (!copy_to_user(name, system_utsname.domainname, len))
+		err = 0;
+
 	up_read(&uts_sem);
 	return err;
 }
diff --git a/arch/sparc64/prom/tree.c b/arch/sparc64/prom/tree.c
index 49075ab..500f05e 100644
--- a/arch/sparc64/prom/tree.c
+++ b/arch/sparc64/prom/tree.c
@@ -193,91 +193,6 @@
 	return 0;
 }
 
-/* Gets name in the {name@x,yyyyy|name (if no reg)} form */
-int 
-prom_getname (int node, char *buffer, int len)
-{
-	int i, sbus = 0;
-	int pci = 0, ebus = 0, ide = 0;
-	struct linux_prom_registers *reg;
-	struct linux_prom64_registers reg64[PROMREG_MAX];
-	
-	for (sbus = prom_getparent (node); sbus; sbus = prom_getparent (sbus)) {
-		i = prom_getproperty (sbus, "name", buffer, len);
-		if (i > 0) {
-			buffer [i] = 0;
-			if (!strcmp (buffer, "sbus"))
-				goto getit;
-		}
-	}
-	if ((pci = prom_getparent (node))) {
-		i = prom_getproperty (pci, "name", buffer, len);
-		if (i > 0) {
-			buffer [i] = 0;
-			if (!strcmp (buffer, "pci"))
-				goto getit;
-		}
-		pci = 0;
-	}
-	if ((ebus = prom_getparent (node))) {
-		i = prom_getproperty (ebus, "name", buffer, len);
-		if (i > 0) {
-			buffer[i] = 0;
-			if (!strcmp (buffer, "ebus"))
-				goto getit;
-		}
-		ebus = 0;
-	}
-	if ((ide = prom_getparent (node))) {
-		i = prom_getproperty (ide, "name", buffer, len);
-		if (i > 0) {
-			buffer [i] = 0;
-			if (!strcmp (buffer, "ide"))
-				goto getit;
-		}
-		ide = 0;
-	}
-getit:
-	i = prom_getproperty (node, "name", buffer, len);
-	if (i <= 0) {
-		buffer [0] = 0;
-		return -1;
-	}
-	buffer [i] = 0;
-	len -= i;
-	i = prom_getproperty (node, "reg", (char *)reg64, sizeof (reg64));
-	if (i <= 0) return 0;
-	if (len < 16) return -1;
-	buffer = strchr (buffer, 0);
-	if (sbus) {
-		reg = (struct linux_prom_registers *)reg64;
-		sprintf (buffer, "@%x,%x", reg[0].which_io, (uint)reg[0].phys_addr);
-	} else if (pci) {
-		int dev, fn;
-		reg = (struct linux_prom_registers *)reg64;
-		fn = (reg[0].which_io >> 8) & 0x07;
-		dev = (reg[0].which_io >> 11) & 0x1f;
-		if (fn)
-			sprintf (buffer, "@%x,%x", dev, fn);
-		else
-			sprintf (buffer, "@%x", dev);
-	} else if (ebus) {
-		reg = (struct linux_prom_registers *)reg64;
-		sprintf (buffer, "@%x,%x", reg[0].which_io, reg[0].phys_addr);
-	} else if (ide) {
-		reg = (struct linux_prom_registers *)reg64;
-		sprintf (buffer, "@%x,%x", reg[0].which_io, reg[0].phys_addr);
-	} else if (i == 4) {	/* Happens on 8042's children on Ultra/PCI. */
-		reg = (struct linux_prom_registers *)reg64;
-		sprintf (buffer, "@%x", reg[0].which_io);
-	} else {
-		sprintf (buffer, "@%x,%x",
-			 (unsigned int)(reg64[0].phys_addr >> 36),
-			 (unsigned int)(reg64[0].phys_addr));
-	}
-	return 0;
-}
-
 /* Return the first property type for node 'node'.
  * buffer should be at least 32B in length
  */
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
index 16b5977..935952e 100644
--- a/drivers/sbus/sbus.c
+++ b/drivers/sbus/sbus.c
@@ -233,7 +233,7 @@
 	sbus->ofdev.node = dp;
 	sbus->ofdev.dev.parent = NULL;
 	sbus->ofdev.dev.bus = &sbus_bus_type;
-	strcpy(sbus->ofdev.dev.bus_id, dp->path_component_name);
+	sprintf(sbus->ofdev.dev.bus_id, "sbus%d", num_sbus);
 
 	if (of_device_register(&sbus->ofdev) != 0)
 		printk(KERN_DEBUG "sbus: device registration error for %s!\n",
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 979497f..dc673e1 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -1047,12 +1047,13 @@
 	up = &sunsab_ports[inst * 2];
 
 	err = sunsab_init_one(&up[0], op,
-			      sizeof(union sab82532_async_regs),
+			      0,
 			      (inst * 2) + 0);
 	if (err)
 		return err;
 
-	err = sunsab_init_one(&up[1], op, 0,
+	err = sunsab_init_one(&up[1], op,
+			      sizeof(union sab82532_async_regs),
 			      (inst * 2) + 1);
 	if (err) {
 		of_iounmap(up[0].port.membase,
@@ -1117,7 +1118,7 @@
 	int err;
 
 	num_channels = 0;
-	for_each_node_by_name(dp, "su")
+	for_each_node_by_name(dp, "se")
 		num_channels += 2;
 	for_each_node_by_name(dp, "serial") {
 		if (of_device_is_compatible(dp, "sab82532"))
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index a1456d9..47bc3d5 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -68,9 +68,6 @@
 #define NUM_SUNZILOG	num_sunzilog
 #define NUM_CHANNELS	(NUM_SUNZILOG * 2)
 
-#define KEYBOARD_LINE 0x2
-#define MOUSE_LINE    0x3
-
 #define ZS_CLOCK		4915200 /* Zilog input clock rate. */
 #define ZS_CLOCK_DIVISOR	16      /* Divisor this driver uses. */
 
@@ -1225,12 +1222,10 @@
 {
 	int baud, brg;
 
-	if (channel == KEYBOARD_LINE) {
-		up->flags |= SUNZILOG_FLAG_CONS_KEYB;
+	if (up->flags & SUNZILOG_FLAG_CONS_KEYB) {
 		up->cflag = B1200 | CS8 | CLOCAL | CREAD;
 		baud = 1200;
 	} else {
-		up->flags |= SUNZILOG_FLAG_CONS_MOUSE;
 		up->cflag = B4800 | CS8 | CLOCAL | CREAD;
 		baud = 4800;
 	}
@@ -1243,14 +1238,14 @@
 }
 
 #ifdef CONFIG_SERIO
-static void __init sunzilog_register_serio(struct uart_sunzilog_port *up, int channel)
+static void __init sunzilog_register_serio(struct uart_sunzilog_port *up)
 {
 	struct serio *serio = &up->serio;
 
 	serio->port_data = up;
 
 	serio->id.type = SERIO_RS232;
-	if (channel == KEYBOARD_LINE) {
+	if (up->flags & SUNZILOG_FLAG_CONS_KEYB) {
 		serio->id.proto = SERIO_SUNKBD;
 		strlcpy(serio->name, "zskbd", sizeof(serio->name));
 	} else {
@@ -1259,7 +1254,8 @@
 		strlcpy(serio->name, "zsms", sizeof(serio->name));
 	}
 	strlcpy(serio->phys,
-		(channel == KEYBOARD_LINE ? "zs/serio0" : "zs/serio1"),
+		((up->flags & SUNZILOG_FLAG_CONS_KEYB) ?
+		 "zs/serio0" : "zs/serio1"),
 		sizeof(serio->phys));
 
 	serio->write = sunzilog_serio_write;
@@ -1286,8 +1282,8 @@
 		(void) read_zsreg(channel, R0);
 	}
 
-	if (up->port.line == KEYBOARD_LINE ||
-	    up->port.line == MOUSE_LINE) {
+	if (up->flags & (SUNZILOG_FLAG_CONS_KEYB |
+			 SUNZILOG_FLAG_CONS_MOUSE)) {
 		sunzilog_init_kbdms(up, up->port.line);
 		up->curregs[R9] |= (NV | MIE);
 		write_zsreg(channel, R9, up->curregs[R9]);
@@ -1313,37 +1309,26 @@
 	spin_unlock_irqrestore(&up->port.lock, flags);
 
 #ifdef CONFIG_SERIO
-	if (up->port.line == KEYBOARD_LINE || up->port.line == MOUSE_LINE)
-		sunzilog_register_serio(up, up->port.line);
+	if (up->flags & (SUNZILOG_FLAG_CONS_KEYB |
+			 SUNZILOG_FLAG_CONS_MOUSE))
+		sunzilog_register_serio(up);
 #endif
 }
 
-static int __devinit zs_get_instance(struct device_node *dp)
-{
-	int ret;
-
-	ret = of_getintprop_default(dp, "slave", -1);
-	if (ret != -1)
-		return ret;
-
-	if (of_find_property(dp, "keyboard", NULL))
-		ret = 1;
-	else
-		ret = 0;
-
-	return ret;
-}
-
 static int zilog_irq = -1;
 
-static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *match)
+static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match)
 {
-	struct of_device *op = to_of_device(&dev->dev);
+	static int inst;
 	struct uart_sunzilog_port *up;
 	struct zilog_layout __iomem *rp;
-	int inst = zs_get_instance(dev->node);
+	int keyboard_mouse;
 	int err;
 
+	keyboard_mouse = 0;
+	if (of_find_property(op->node, "keyboard", NULL))
+		keyboard_mouse = 1;
+
 	sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0,
 					      sizeof(struct zilog_layout),
 					      "zs");
@@ -1352,16 +1337,8 @@
 
 	rp = sunzilog_chip_regs[inst];
 
-	if (zilog_irq == -1) {
+	if (zilog_irq == -1)
 		zilog_irq = op->irqs[0];
-		err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
-				  "zs", sunzilog_irq_chain);
-		if (err) {
-			of_iounmap(rp, sizeof(struct zilog_layout));
-
-			return err;
-		}
-	}
 
 	up = &sunzilog_port_table[inst * 2];
 
@@ -1378,7 +1355,7 @@
 	up[0].port.line = (inst * 2) + 0;
 	up[0].port.dev = &op->dev;
 	up[0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A;
-	if (inst == 1)
+	if (keyboard_mouse)
 		up[0].flags |= SUNZILOG_FLAG_CONS_KEYB;
 	sunzilog_init_hw(&up[0]);
 
@@ -1395,11 +1372,11 @@
 	up[1].port.line = (inst * 2) + 1;
 	up[1].port.dev = &op->dev;
 	up[1].flags |= 0;
-	if (inst == 1)
+	if (keyboard_mouse)
 		up[1].flags |= SUNZILOG_FLAG_CONS_MOUSE;
 	sunzilog_init_hw(&up[1]);
 
-	if (inst != 1) {
+	if (!keyboard_mouse) {
 		err = uart_add_one_port(&sunzilog_reg, &up[0].port);
 		if (err) {
 			of_iounmap(rp, sizeof(struct zilog_layout));
@@ -1411,9 +1388,18 @@
 			of_iounmap(rp, sizeof(struct zilog_layout));
 			return err;
 		}
+	} else {
+		printk(KERN_INFO "%s: Keyboard at MMIO %lx (irq = %d) "
+		       "is a zs\n",
+		       op->dev.bus_id, up[0].port.mapbase, op->irqs[0]);
+		printk(KERN_INFO "%s: Mouse at MMIO %lx (irq = %d) "
+		       "is a zs\n",
+		       op->dev.bus_id, up[1].port.mapbase, op->irqs[0]);
 	}
 
-	dev_set_drvdata(&dev->dev, &up[0]);
+	dev_set_drvdata(&op->dev, &up[0]);
+
+	inst++;
 
 	return 0;
 }
@@ -1462,36 +1448,65 @@
 static int __init sunzilog_init(void)
 {
 	struct device_node *dp;
-	int err;
+	int err, uart_count;
+	int num_keybms;
 
 	NUM_SUNZILOG = 0;
-	for_each_node_by_name(dp, "zs")
+	num_keybms = 0;
+	for_each_node_by_name(dp, "zs") {
 		NUM_SUNZILOG++;
+		if (of_find_property(dp, "keyboard", NULL))
+			num_keybms++;
+	}
 
+	uart_count = 0;
 	if (NUM_SUNZILOG) {
 		int uart_count;
 
 		err = sunzilog_alloc_tables();
 		if (err)
-			return err;
+			goto out;
 
-		/* Subtract 1 for keyboard, 1 for mouse.  */
-		uart_count = (NUM_SUNZILOG * 2) - 2;
+		uart_count = (NUM_SUNZILOG * 2) - (2 * num_keybms);
 
 		sunzilog_reg.nr = uart_count;
 		sunzilog_reg.minor = sunserial_current_minor;
 		err = uart_register_driver(&sunzilog_reg);
-		if (err) {
-			sunzilog_free_tables();
-			return err;
-		}
+		if (err)
+			goto out_free_tables;
+
 		sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64;
 		sunzilog_reg.cons = SUNZILOG_CONSOLE();
 
 		sunserial_current_minor += uart_count;
 	}
 
-	return of_register_driver(&zs_driver, &of_bus_type);
+	err = of_register_driver(&zs_driver, &of_bus_type);
+	if (err)
+		goto out_unregister_uart;
+
+	if (zilog_irq != -1) {
+		err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
+				  "zs", sunzilog_irq_chain);
+		if (err)
+			goto out_unregister_driver;
+	}
+
+out:
+	return err;
+
+out_unregister_driver:
+	of_unregister_driver(&zs_driver);
+
+out_unregister_uart:
+	if (NUM_SUNZILOG) {
+		uart_unregister_driver(&sunzilog_reg);
+		sunzilog_reg.cons = NULL;
+	}
+
+out_free_tables:
+	sunzilog_free_tables();
+	goto out;
 }
 
 static void __exit sunzilog_exit(void)
diff --git a/include/asm-m68k/oplib.h b/include/asm-m68k/oplib.h
index c3594f4..06caa2d 100644
--- a/include/asm-m68k/oplib.h
+++ b/include/asm-m68k/oplib.h
@@ -244,11 +244,6 @@
 /* Does the passed node have the given "name"? YES=1 NO=0 */
 extern int prom_nodematch(int thisnode, char *name);
 
-/* Puts in buffer a prom name in the form name@x,y or name (x for which_io
- * and y for first regs phys address
- */
-extern int prom_getname(int node, char *buf, int buflen);
-
 /* Search all siblings starting at the passed node for "name" matching
  * the given string.  Returns the node on success, zero on failure.
  */
diff --git a/include/asm-sparc/oplib.h b/include/asm-sparc/oplib.h
index f283f8a..91691e5 100644
--- a/include/asm-sparc/oplib.h
+++ b/include/asm-sparc/oplib.h
@@ -267,11 +267,6 @@
 /* Does the passed node have the given "name"? YES=1 NO=0 */
 extern int prom_nodematch(int thisnode, char *name);
 
-/* Puts in buffer a prom name in the form name@x,y or name (x for which_io 
- * and y for first regs phys address
- */
-extern int prom_getname(int node, char *buf, int buflen);
-
 /* Search all siblings starting at the passed node for "name" matching
  * the given string.  Returns the node on success, zero on failure.
  */
diff --git a/include/asm-sparc64/openprom.h b/include/asm-sparc64/openprom.h
index b4959d2..e01b805 100644
--- a/include/asm-sparc64/openprom.h
+++ b/include/asm-sparc64/openprom.h
@@ -175,7 +175,7 @@
 };
 
 /* More fun PROM structures for device probing. */
-#define PROMREG_MAX     16
+#define PROMREG_MAX     24
 #define PROMVADDR_MAX   16
 #define PROMINTR_MAX    15
 
diff --git a/include/asm-sparc64/oplib.h b/include/asm-sparc64/oplib.h
index a68b0bb..6a0da3b 100644
--- a/include/asm-sparc64/oplib.h
+++ b/include/asm-sparc64/oplib.h
@@ -287,11 +287,6 @@
 /* Does the passed node have the given "name"? YES=1 NO=0 */
 extern int prom_nodematch(int thisnode, const char *name);
 
-/* Puts in buffer a prom name in the form name@x,y or name (x for which_io 
- * and y for first regs phys address
- */
-extern int prom_getname(int node, char *buf, int buflen);
-
 /* Search all siblings starting at the passed node for "name" matching
  * the given string.  Returns the node on success, zero on failure.
  */