Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
  IB/mad: RMPP support for additional classes
  IB/mad: include GID/class when matching receives
  IB/mthca: Fix section mismatch problems
  IPoIB: Fix oops with raw sockets
  IB/mthca: Fix check of size in SRQ creation
  IB/srp: Fix unmapping of fake scatterlist
diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl
index d260d92..5bcbb6e 100644
--- a/Documentation/DocBook/libata.tmpl
+++ b/Documentation/DocBook/libata.tmpl
@@ -120,14 +120,27 @@
 	<programlisting>
 void (*set_piomode) (struct ata_port *, struct ata_device *);
 void (*set_dmamode) (struct ata_port *, struct ata_device *);
-void (*post_set_mode) (struct ata_port *ap);
+void (*post_set_mode) (struct ata_port *);
+unsigned int (*mode_filter) (struct ata_port *, struct ata_device *, unsigned int);
 	</programlisting>
 
 	<para>
 	Hooks called prior to the issue of SET FEATURES - XFER MODE
-	command.  dev->pio_mode is guaranteed to be valid when
-	->set_piomode() is called, and dev->dma_mode is guaranteed to be
-	valid when ->set_dmamode() is called.  ->post_set_mode() is
+	command.  The optional ->mode_filter() hook is called when libata
+	has built a mask of the possible modes. This is passed to the 
+	->mode_filter() function which should return a mask of valid modes
+	after filtering those unsuitable due to hardware limits. It is not
+	valid to use this interface to add modes.
+	</para>
+	<para>
+	dev->pio_mode and dev->dma_mode are guaranteed to be valid when
+	->set_piomode() and when ->set_dmamode() is called. The timings for
+	any other drive sharing the cable will also be valid at this point.
+	That is the library records the decisions for the modes of each
+	drive on a channel before it attempts to set any of them.
+	</para>
+	<para>
+	->post_set_mode() is
 	called unconditionally, after the SET FEATURES - XFER MODE
 	command completes successfully.
 	</para>
@@ -230,6 +243,32 @@
 
 	</sect2>
 
+	<sect2><title>Private tuning method</title>
+	<programlisting>
+void (*set_mode) (struct ata_port *ap);
+	</programlisting>
+
+	<para>
+	By default libata performs drive and controller tuning in
+	accordance with the ATA timing rules and also applies blacklists
+	and cable limits. Some controllers need special handling and have
+	custom tuning rules, typically raid controllers that use ATA
+	commands but do not actually do drive timing.
+	</para>
+
+	<warning>
+	<para>
+	This hook should not be used to replace the standard controller
+	tuning logic when a controller has quirks. Replacing the default
+	tuning logic in that case would bypass handling for drive and
+	bridge quirks that may be important to data reliability. If a
+	controller needs to filter the mode selection it should use the
+	mode_filter hook instead.
+	</para>
+	</warning>
+
+	</sect2>
+
 	<sect2><title>Reset ATA bus</title>
 	<programlisting>
 void (*phy_reset) (struct ata_port *ap);
diff --git a/Documentation/networking/TODO b/Documentation/networking/TODO
deleted file mode 100644
index 66d36ff..0000000
--- a/Documentation/networking/TODO
+++ /dev/null
@@ -1,18 +0,0 @@
-To-do items for network drivers
--------------------------------
-
-* Move ethernet crc routine to generic code
-
-* (for 2.5) Integrate Jamal Hadi Salim's netdev Rx polling API change
-
-* Audit all net drivers to make sure magic packet / wake-on-lan /
-  similar features are disabled in the driver by default.
-
-* Audit all net drivers to make sure the module always prints out a
-  version string when loaded as a module, but only prints a version
-  string when built into the kernel if a device is detected.
-
-* Add ETHTOOL_GDRVINFO ioctl support to all ethernet drivers.
-
-* dmfe PCI DMA is totally wrong and only works on x86
-
diff --git a/Documentation/networking/bcm43xx.txt b/Documentation/networking/bcm43xx.txt
new file mode 100644
index 0000000..28541d2
--- /dev/null
+++ b/Documentation/networking/bcm43xx.txt
@@ -0,0 +1,36 @@
+
+			BCM43xx Linux Driver Project
+			============================
+
+About this software
+-------------------
+
+The goal of this project is to develop a linux driver for Broadcom
+BCM43xx chips, based on the specification at 
+http://bcm-specs.sipsolutions.net/
+
+The project page is http://bcm43xx.berlios.de/
+
+
+Requirements
+------------
+
+1)	Linux Kernel 2.6.16 or later
+	http://www.kernel.org/
+
+	You may want to configure your kernel with:
+
+	CONFIG_DEBUG_FS (optional):
+		-> Kernel hacking
+		  -> Debug Filesystem
+
+2)	SoftMAC IEEE 802.11 Networking Stack extension and patched ieee80211
+	modules:
+	http://softmac.sipsolutions.net/
+
+3)	Firmware Files
+
+	Please try fwcutter. Fwcutter can extract the firmware from various 
+	binary driver files. It supports driver files from Windows, MacOS and 
+	Linux. You can get fwcutter from http://bcm43xx.berlios.de/.
+	Also, fwcutter comes with a README file for further instructions.
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index ee551c6..217e517 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -719,6 +719,11 @@
     - model : this is your board name/model
     - #address-cells : address representation for "root" devices
     - #size-cells: the size representation for "root" devices
+    - device_type : This property shouldn't be necessary. However, if
+      you decide to create a device_type for your root node, make sure it
+      is _not_ "chrp" unless your platform is a pSeries or PAPR compliant
+      one for 64-bit, or a CHRP-type machine for 32-bit as this will
+      matched by the kernel this way.
 
   Additionally, some recommended properties are:
 
diff --git a/MAINTAINERS b/MAINTAINERS
index e5b051f..c946581 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1885,6 +1885,7 @@
 P:	Networking Team
 M:	netdev@vger.kernel.org
 L:	netdev@vger.kernel.org
+W:	http://linux-net.osdl.org/
 S:	Maintained
 
 NETWORKING [IPv4/IPv6]
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index 326595f..ce3ef4f 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -312,3 +312,4 @@
 	.long sys_unshare		/* 310 */
 	.long sys_set_robust_list
 	.long sys_get_robust_list
+	.long sys_splice
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 0e3eda9..750e8e7 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1605,5 +1605,6 @@
 	data8 sys_ni_syscall			// reserved for pselect
 	data8 sys_ni_syscall			// 1295 reserved for ppoll
 	data8 sys_unshare
+	data8 sys_splice
 
 	.org sys_call_table + 8*NR_syscalls	// guard against failures to increase NR_syscalls
diff --git a/arch/ia64/kernel/gate.lds.S b/arch/ia64/kernel/gate.lds.S
index e1e4aba..7c99e6e 100644
--- a/arch/ia64/kernel/gate.lds.S
+++ b/arch/ia64/kernel/gate.lds.S
@@ -59,6 +59,7 @@
 	*(.dynbss)
 	*(.bss .bss.* .gnu.linkonce.b.*)
 	*(__ex_table)
+	*(__mca_table)
   }
 }
 
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 8832c55..7956eb9 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -9,54 +9,65 @@
  * Copyright (C) 1999 VA Linux Systems
  * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
  *
- * 00/04/19	D. Mosberger	Rewritten to mirror more closely the x86 I/O APIC code.
- *				In particular, we now have separate handlers for edge
- *				and level triggered interrupts.
- * 00/10/27	Asit Mallick, Goutham Rao <goutham.rao@intel.com> IRQ vector allocation
- *				PCI to vector mapping, shared PCI interrupts.
- * 00/10/27	D. Mosberger	Document things a bit more to make them more understandable.
- *				Clean up much of the old IOSAPIC cruft.
- * 01/07/27	J.I. Lee	PCI irq routing, Platform/Legacy interrupts and fixes for
- *				ACPI S5(SoftOff) support.
+ * 00/04/19	D. Mosberger	Rewritten to mirror more closely the x86 I/O
+ *				APIC code.  In particular, we now have separate
+ *				handlers for edge and level triggered
+ *				interrupts.
+ * 00/10/27	Asit Mallick, Goutham Rao <goutham.rao@intel.com> IRQ vector
+ *				allocation PCI to vector mapping, shared PCI
+ *				interrupts.
+ * 00/10/27	D. Mosberger	Document things a bit more to make them more
+ *				understandable.  Clean up much of the old
+ *				IOSAPIC cruft.
+ * 01/07/27	J.I. Lee	PCI irq routing, Platform/Legacy interrupts
+ *				and fixes for ACPI S5(SoftOff) support.
  * 02/01/23	J.I. Lee	iosapic pgm fixes for PCI irq routing from _PRT
- * 02/01/07     E. Focht        <efocht@ess.nec.de> Redirectable interrupt vectors in
- *                              iosapic_set_affinity(), initializations for
- *                              /proc/irq/#/smp_affinity
+ * 02/01/07     E. Focht        <efocht@ess.nec.de> Redirectable interrupt
+ *				vectors in iosapic_set_affinity(),
+ *				initializations for /proc/irq/#/smp_affinity
  * 02/04/02	P. Diefenbaugh	Cleaned up ACPI PCI IRQ routing.
  * 02/04/18	J.I. Lee	bug fix in iosapic_init_pci_irq
- * 02/04/30	J.I. Lee	bug fix in find_iosapic to fix ACPI PCI IRQ to IOSAPIC mapping
- *				error
+ * 02/04/30	J.I. Lee	bug fix in find_iosapic to fix ACPI PCI IRQ to
+ *				IOSAPIC mapping error
  * 02/07/29	T. Kochi	Allocate interrupt vectors dynamically
- * 02/08/04	T. Kochi	Cleaned up terminology (irq, global system interrupt, vector, etc.)
- * 02/09/20	D. Mosberger	Simplified by taking advantage of ACPI's pci_irq code.
+ * 02/08/04	T. Kochi	Cleaned up terminology (irq, global system
+ *				interrupt, vector, etc.)
+ * 02/09/20	D. Mosberger	Simplified by taking advantage of ACPI's
+ *				pci_irq code.
  * 03/02/19	B. Helgaas	Make pcat_compat system-wide, not per-IOSAPIC.
- *				Remove iosapic_address & gsi_base from external interfaces.
- *				Rationalize __init/__devinit attributes.
+ *				Remove iosapic_address & gsi_base from
+ *				external interfaces.  Rationalize
+ *				__init/__devinit attributes.
  * 04/12/04 Ashok Raj	<ashok.raj@intel.com> Intel Corporation 2004
- *				Updated to work with irq migration necessary for CPU Hotplug
+ *				Updated to work with irq migration necessary
+ *				for CPU Hotplug
  */
 /*
- * Here is what the interrupt logic between a PCI device and the kernel looks like:
+ * Here is what the interrupt logic between a PCI device and the kernel looks
+ * like:
  *
- * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC, INTD).  The
- *     device is uniquely identified by its bus--, and slot-number (the function
- *     number does not matter here because all functions share the same interrupt
- *     lines).
+ * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC,
+ *     INTD).  The device is uniquely identified by its bus-, and slot-number
+ *     (the function number does not matter here because all functions share
+ *     the same interrupt lines).
  *
- * (2) The motherboard routes the interrupt line to a pin on a IOSAPIC controller.
- *     Multiple interrupt lines may have to share the same IOSAPIC pin (if they're level
- *     triggered and use the same polarity).  Each interrupt line has a unique Global
- *     System Interrupt (GSI) number which can be calculated as the sum of the controller's
- *     base GSI number and the IOSAPIC pin number to which the line connects.
+ * (2) The motherboard routes the interrupt line to a pin on a IOSAPIC
+ *     controller.  Multiple interrupt lines may have to share the same
+ *     IOSAPIC pin (if they're level triggered and use the same polarity).
+ *     Each interrupt line has a unique Global System Interrupt (GSI) number
+ *     which can be calculated as the sum of the controller's base GSI number
+ *     and the IOSAPIC pin number to which the line connects.
  *
- * (3) The IOSAPIC uses an internal routing table entries (RTEs) to map the IOSAPIC pin
- *     into the IA-64 interrupt vector.  This interrupt vector is then sent to the CPU.
+ * (3) The IOSAPIC uses an internal routing table entries (RTEs) to map the
+ * IOSAPIC pin into the IA-64 interrupt vector.  This interrupt vector is then
+ * sent to the CPU.
  *
- * (4) The kernel recognizes an interrupt as an IRQ.  The IRQ interface is used as
- *     architecture-independent interrupt handling mechanism in Linux.  As an
- *     IRQ is a number, we have to have IA-64 interrupt vector number <-> IRQ number
- *     mapping.  On smaller systems, we use one-to-one mapping between IA-64 vector and
- *     IRQ.  A platform can implement platform_irq_to_vector(irq) and
+ * (4) The kernel recognizes an interrupt as an IRQ.  The IRQ interface is
+ *     used as architecture-independent interrupt handling mechanism in Linux.
+ *     As an IRQ is a number, we have to have
+ *     IA-64 interrupt vector number <-> IRQ number mapping.  On smaller
+ *     systems, we use one-to-one mapping between IA-64 vector and IRQ.  A
+ *     platform can implement platform_irq_to_vector(irq) and
  *     platform_local_vector_to_irq(vector) APIs to differentiate the mapping.
  *     Please see also include/asm-ia64/hw_irq.h for those APIs.
  *
@@ -64,9 +75,9 @@
  *
  *	PCI pin -> global system interrupt (GSI) -> IA-64 vector <-> IRQ
  *
- * Note: The term "IRQ" is loosely used everywhere in Linux kernel to describe interrupts.
- * Now we use "IRQ" only for Linux IRQ's.  ISA IRQ (isa_irq) is the only exception in this
- * source code.
+ * Note: The term "IRQ" is loosely used everywhere in Linux kernel to
+ * describeinterrupts.  Now we use "IRQ" only for Linux IRQ's.  ISA IRQ
+ * (isa_irq) is the only exception in this source code.
  */
 #include <linux/config.h>
 
@@ -90,7 +101,6 @@
 #include <asm/ptrace.h>
 #include <asm/system.h>
 
-
 #undef DEBUG_INTERRUPT_ROUTING
 
 #ifdef DEBUG_INTERRUPT_ROUTING
@@ -99,36 +109,46 @@
 #define DBG(fmt...)
 #endif
 
-#define NR_PREALLOCATE_RTE_ENTRIES	(PAGE_SIZE / sizeof(struct iosapic_rte_info))
+#define NR_PREALLOCATE_RTE_ENTRIES \
+	(PAGE_SIZE / sizeof(struct iosapic_rte_info))
 #define RTE_PREALLOCATED	(1)
 
 static DEFINE_SPINLOCK(iosapic_lock);
 
-/* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */
+/*
+ * These tables map IA-64 vectors to the IOSAPIC pin that generates this
+ * vector.
+ */
 
 struct iosapic_rte_info {
-	struct list_head rte_list;	/* node in list of RTEs sharing the same vector */
+	struct list_head rte_list;	/* node in list of RTEs sharing the
+					 * same vector */
 	char __iomem	*addr;		/* base address of IOSAPIC */
-	unsigned int	gsi_base;	/* first GSI assigned to this IOSAPIC */
+	unsigned int	gsi_base;	/* first GSI assigned to this
+					 * IOSAPIC */
 	char		rte_index;	/* IOSAPIC RTE index */
 	int		refcnt;		/* reference counter */
 	unsigned int	flags;		/* flags */
 } ____cacheline_aligned;
 
 static struct iosapic_intr_info {
-	struct list_head rtes;		/* RTEs using this vector (empty => not an IOSAPIC interrupt) */
+	struct list_head rtes;		/* RTEs using this vector (empty =>
+					 * not an IOSAPIC interrupt) */
 	int		count;		/* # of RTEs that shares this vector */
-	u32		low32;		/* current value of low word of Redirection table entry */
+	u32		low32;		/* current value of low word of
+					 * Redirection table entry */
 	unsigned int	dest;		/* destination CPU physical ID */
 	unsigned char	dmode	: 3;	/* delivery mode (see iosapic.h) */
-	unsigned char 	polarity: 1;	/* interrupt polarity (see iosapic.h) */
+	unsigned char 	polarity: 1;	/* interrupt polarity
+					 * (see iosapic.h) */
 	unsigned char	trigger	: 1;	/* trigger mode (see iosapic.h) */
 } iosapic_intr_info[IA64_NUM_VECTORS];
 
 static struct iosapic {
 	char __iomem	*addr;		/* base address of IOSAPIC */
-	unsigned int 	gsi_base;	/* first GSI assigned to this IOSAPIC */
-	unsigned short 	num_rte;	/* number of RTE in this IOSAPIC */
+	unsigned int 	gsi_base;	/* first GSI assigned to this
+					 * IOSAPIC */
+	unsigned short 	num_rte;	/* # of RTEs on this IOSAPIC */
 	int		rtes_inuse;	/* # of RTEs in use on this IOSAPIC */
 #ifdef CONFIG_NUMA
 	unsigned short	node;		/* numa node association via pxm */
@@ -149,7 +169,8 @@
 	int i;
 
 	for (i = 0; i < NR_IOSAPICS; i++) {
-		if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < iosapic_lists[i].num_rte)
+		if ((unsigned) (gsi - iosapic_lists[i].gsi_base) <
+		    iosapic_lists[i].num_rte)
 			return i;
 	}
 
@@ -162,7 +183,8 @@
 	struct iosapic_intr_info *info;
 	struct iosapic_rte_info *rte;
 
-	for (info = iosapic_intr_info; info < iosapic_intr_info + IA64_NUM_VECTORS; ++info)
+	for (info = iosapic_intr_info; info <
+		     iosapic_intr_info + IA64_NUM_VECTORS; ++info)
 		list_for_each_entry(rte, &info->rtes, rte_list)
 			if (rte->gsi_base + rte->rte_index == gsi)
 				return info - iosapic_intr_info;
@@ -185,8 +207,8 @@
 	unsigned long flags;
 	int irq;
 	/*
-	 * XXX fix me: this assumes an identity mapping vetween IA-64 vector and Linux irq
-	 * numbers...
+	 * XXX fix me: this assumes an identity mapping between IA-64 vector
+	 * and Linux irq numbers...
 	 */
 	spin_lock_irqsave(&iosapic_lock, flags);
 	{
@@ -197,7 +219,8 @@
 	return irq;
 }
 
-static struct iosapic_rte_info *gsi_vector_to_rte(unsigned int gsi, unsigned int vec)
+static struct iosapic_rte_info *gsi_vector_to_rte(unsigned int gsi,
+						  unsigned int vec)
 {
 	struct iosapic_rte_info *rte;
 
@@ -237,7 +260,9 @@
 
 		for (irq = 0; irq < NR_IRQS; ++irq)
 			if (irq_to_vector(irq) == vector) {
-				set_irq_affinity_info(irq, (int)(dest & 0xffff), redir);
+				set_irq_affinity_info(irq,
+						      (int)(dest & 0xffff),
+						      redir);
 				break;
 			}
 	}
@@ -259,7 +284,7 @@
 }
 
 static void
-nop (unsigned int vector)
+nop (unsigned int irq)
 {
 	/* do nothing... */
 }
@@ -281,7 +306,8 @@
 	{
 		/* set only the mask bit */
 		low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK;
-		list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) {
+		list_for_each_entry(rte, &iosapic_intr_info[vec].rtes,
+				    rte_list) {
 			addr = rte->addr;
 			rte_index = rte->rte_index;
 			iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
@@ -306,7 +332,8 @@
 	spin_lock_irqsave(&iosapic_lock, flags);
 	{
 		low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK;
-		list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) {
+		list_for_each_entry(rte, &iosapic_intr_info[vec].rtes,
+				    rte_list) {
 			addr = rte->addr;
 			rte_index = rte->rte_index;
 			iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
@@ -346,21 +373,25 @@
 
 	spin_lock_irqsave(&iosapic_lock, flags);
 	{
-		low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT);
+		low32 = iosapic_intr_info[vec].low32 &
+			~(7 << IOSAPIC_DELIVERY_SHIFT);
 
 		if (redir)
 		        /* change delivery mode to lowest priority */
-			low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT);
+			low32 |= (IOSAPIC_LOWEST_PRIORITY <<
+				  IOSAPIC_DELIVERY_SHIFT);
 		else
 		        /* change delivery mode to fixed */
 			low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT);
 
 		iosapic_intr_info[vec].low32 = low32;
 		iosapic_intr_info[vec].dest = dest;
-		list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) {
+		list_for_each_entry(rte, &iosapic_intr_info[vec].rtes,
+				    rte_list) {
 			addr = rte->addr;
 			rte_index = rte->rte_index;
-			iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32);
+			iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index),
+				      high32);
 			iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
 		}
 	}
@@ -433,7 +464,8 @@
 	 * interrupt for real. This prevents IRQ storms from unhandled
 	 * devices.
 	 */
-	if ((idesc->status & (IRQ_PENDING|IRQ_DISABLED)) == (IRQ_PENDING|IRQ_DISABLED))
+	if ((idesc->status & (IRQ_PENDING|IRQ_DISABLED)) ==
+	    (IRQ_PENDING|IRQ_DISABLED))
 		mask_irq(irq);
 }
 
@@ -467,7 +499,8 @@
 	return iosapic_read(addr, IOSAPIC_VERSION);
 }
 
-static int iosapic_find_sharable_vector (unsigned long trigger, unsigned long pol)
+static int iosapic_find_sharable_vector (unsigned long trigger,
+					 unsigned long pol)
 {
 	int i, vector = -1, min_count = -1;
 	struct iosapic_intr_info *info;
@@ -482,7 +515,8 @@
 	for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) {
 		info = &iosapic_intr_info[i];
 		if (info->trigger == trigger && info->polarity == pol &&
-		    (info->dmode == IOSAPIC_FIXED || info->dmode == IOSAPIC_LOWEST_PRIORITY)) {
+		    (info->dmode == IOSAPIC_FIXED || info->dmode ==
+		     IOSAPIC_LOWEST_PRIORITY)) {
 			if (min_count == -1 || info->count < min_count) {
 				vector = i;
 				min_count = info->count;
@@ -506,12 +540,15 @@
 		new_vector = assign_irq_vector(AUTO_ASSIGN);
 		if (new_vector < 0)
 			panic("%s: out of interrupt vectors!\n", __FUNCTION__);
-		printk(KERN_INFO "Reassigning vector %d to %d\n", vector, new_vector);
+		printk(KERN_INFO "Reassigning vector %d to %d\n",
+		       vector, new_vector);
 		memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector],
 		       sizeof(struct iosapic_intr_info));
 		INIT_LIST_HEAD(&iosapic_intr_info[new_vector].rtes);
-		list_move(iosapic_intr_info[vector].rtes.next, &iosapic_intr_info[new_vector].rtes);
-		memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));
+		list_move(iosapic_intr_info[vector].rtes.next,
+			  &iosapic_intr_info[new_vector].rtes);
+		memset(&iosapic_intr_info[vector], 0,
+		       sizeof(struct iosapic_intr_info));
 		iosapic_intr_info[vector].low32 = IOSAPIC_MASK;
 		INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);
 	}
@@ -524,7 +561,8 @@
 	int preallocated = 0;
 
 	if (!iosapic_kmalloc_ok && list_empty(&free_rte_list)) {
-		rte = alloc_bootmem(sizeof(struct iosapic_rte_info) * NR_PREALLOCATE_RTE_ENTRIES);
+		rte = alloc_bootmem(sizeof(struct iosapic_rte_info) *
+				    NR_PREALLOCATE_RTE_ENTRIES);
 		if (!rte)
 			return NULL;
 		for (i = 0; i < NR_PREALLOCATE_RTE_ENTRIES; i++, rte++)
@@ -532,7 +570,8 @@
 	}
 
 	if (!list_empty(&free_rte_list)) {
-		rte = list_entry(free_rte_list.next, struct iosapic_rte_info, rte_list);
+		rte = list_entry(free_rte_list.next, struct iosapic_rte_info,
+				 rte_list);
 		list_del(&rte->rte_list);
 		preallocated++;
 	} else {
@@ -575,7 +614,8 @@
 
 	index = find_iosapic(gsi);
 	if (index < 0) {
-		printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n", __FUNCTION__, gsi);
+		printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n",
+		       __FUNCTION__, gsi);
 		return -ENODEV;
 	}
 
@@ -586,7 +626,8 @@
 	if (!rte) {
 		rte = iosapic_alloc_rte();
 		if (!rte) {
-			printk(KERN_WARNING "%s: cannot allocate memory\n", __FUNCTION__);
+			printk(KERN_WARNING "%s: cannot allocate memory\n",
+			       __FUNCTION__);
 			return -ENOMEM;
 		}
 
@@ -602,7 +643,9 @@
 	else if (vector_is_shared(vector)) {
 		struct iosapic_intr_info *info = &iosapic_intr_info[vector];
 		if (info->trigger != trigger || info->polarity != polarity) {
-			printk (KERN_WARNING "%s: cannot override the interrupt\n", __FUNCTION__);
+			printk (KERN_WARNING
+				"%s: cannot override the interrupt\n",
+				__FUNCTION__);
 			return -EINVAL;
 		}
 	}
@@ -619,8 +662,10 @@
 	idesc = irq_descp(vector);
 	if (idesc->handler != irq_type) {
 		if (idesc->handler != &no_irq_type)
-			printk(KERN_WARNING "%s: changing vector %d from %s to %s\n",
-			       __FUNCTION__, vector, idesc->handler->typename, irq_type->typename);
+			printk(KERN_WARNING
+			       "%s: changing vector %d from %s to %s\n",
+			       __FUNCTION__, vector,
+			       idesc->handler->typename, irq_type->typename);
 		idesc->handler = irq_type;
 	}
 	return 0;
@@ -681,7 +726,7 @@
 		if (!num_cpus)
 			goto skip_numa_setup;
 
-		/* Use vector assigment to distribute across cpus in node */
+		/* Use vector assignment to distribute across cpus in node */
 		cpu_index = vector % num_cpus;
 
 		for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++)
@@ -703,7 +748,7 @@
 	} while (!cpu_online(cpu));
 
 	return cpu_physical_id(cpu);
-#else
+#else  /* CONFIG_SMP */
 	return cpu_physical_id(smp_processor_id());
 #endif
 }
@@ -755,7 +800,8 @@
 			if (list_empty(&iosapic_intr_info[vector].rtes))
 				free_irq_vector(vector);
 			spin_unlock(&iosapic_lock);
-			spin_unlock_irqrestore(&irq_descp(vector)->lock, flags);
+			spin_unlock_irqrestore(&irq_descp(vector)->lock,
+					       flags);
 			goto again;
 		}
 
@@ -764,7 +810,8 @@
 			      polarity, trigger);
 		if (err < 0) {
 			spin_unlock(&iosapic_lock);
-			spin_unlock_irqrestore(&irq_descp(vector)->lock, flags);
+			spin_unlock_irqrestore(&irq_descp(vector)->lock,
+					       flags);
 			return err;
 		}
 
@@ -806,7 +853,8 @@
 	 */
 	irq = gsi_to_irq(gsi);
 	if (irq < 0) {
-		printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi);
+		printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n",
+		       gsi);
 		WARN_ON(1);
 		return;
 	}
@@ -817,7 +865,9 @@
 	spin_lock(&iosapic_lock);
 	{
 		if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) {
-			printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi);
+			printk(KERN_ERR
+			       "iosapic_unregister_intr(%u) unbalanced\n",
+			       gsi);
 			WARN_ON(1);
 			goto out;
 		}
@@ -827,7 +877,8 @@
 
 		/* Mask the interrupt */
 		low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK;
-		iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index), low32);
+		iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index),
+			      low32);
 
 		/* Remove the rte entry from the list */
 		list_del(&rte->rte_list);
@@ -840,7 +891,9 @@
 		trigger	 = iosapic_intr_info[vector].trigger;
 		polarity = iosapic_intr_info[vector].polarity;
 		dest     = iosapic_intr_info[vector].dest;
-		printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n",
+		printk(KERN_INFO
+		       "GSI %u (%s, %s) -> CPU %d (0x%04x)"
+		       " vector %d unregistered\n",
 		       gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
 		       (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
 		       cpu_logical_id(dest), dest, vector);
@@ -853,12 +906,15 @@
 			idesc->handler = &no_irq_type;
 
 			/* Clear the interrupt information */
-			memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));
+			memset(&iosapic_intr_info[vector], 0,
+			       sizeof(struct iosapic_intr_info));
 			iosapic_intr_info[vector].low32 |= IOSAPIC_MASK;
 			INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);
 
 			if (idesc->action) {
-				printk(KERN_ERR "interrupt handlers still exist on IRQ %u\n", irq);
+				printk(KERN_ERR
+				       "interrupt handlers still exist on"
+				       "IRQ %u\n", irq);
 				WARN_ON(1);
 			}
 
@@ -873,7 +929,6 @@
 
 /*
  * ACPI calls this when it finds an entry for a platform interrupt.
- * Note that the irq_base and IOSAPIC address must be set in iosapic_init().
  */
 int __init
 iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
@@ -907,13 +962,16 @@
 		mask = 1;
 		break;
 	      default:
-		printk(KERN_ERR "iosapic_register_platform_irq(): invalid int type 0x%x\n", int_type);
+		printk(KERN_ERR "%s: invalid int type 0x%x\n", __FUNCTION__,
+		       int_type);
 		return -1;
 	}
 
 	register_intr(gsi, vector, delivery, polarity, trigger);
 
-	printk(KERN_INFO "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",
+	printk(KERN_INFO
+	       "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x)"
+	       " vector %d\n",
 	       int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown",
 	       int_type, gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
 	       (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
@@ -923,10 +981,8 @@
 	return vector;
 }
 
-
 /*
  * ACPI calls this when it finds an entry for a legacy ISA IRQ override.
- * Note that the gsi_base and IOSAPIC address must be set in iosapic_init().
  */
 void __init
 iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
@@ -955,16 +1011,19 @@
 
 	for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) {
 		iosapic_intr_info[vector].low32 = IOSAPIC_MASK;
-		INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);	/* mark as unused */
+		/* mark as unused */
+		INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);
 	}
 
 	pcat_compat = system_pcat_compat;
 	if (pcat_compat) {
 		/*
-		 * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support
-		 * enabled.
+		 * Disable the compatibility mode interrupts (8259 style),
+		 * needs IN/OUT support enabled.
 		 */
-		printk(KERN_INFO "%s: Disabling PC-AT compatible 8259 interrupts\n", __FUNCTION__);
+		printk(KERN_INFO
+		       "%s: Disabling PC-AT compatible 8259 interrupts\n",
+		       __FUNCTION__);
 		outb(0xff, 0xA1);
 		outb(0xff, 0x21);
 	}
@@ -1004,10 +1063,7 @@
 		base = iosapic_lists[index].gsi_base;
 		end  = base + iosapic_lists[index].num_rte - 1;
 
-		if (gsi_base < base && gsi_end < base)
-			continue;/* OK */
-
-		if (gsi_base > end && gsi_end > end)
+		if (gsi_end < base || end < gsi_base)
 			continue; /* OK */
 
 		return -EBUSY;
@@ -1053,12 +1109,14 @@
 
 	if ((gsi_base == 0) && pcat_compat) {
 		/*
-		 * Map the legacy ISA devices into the IOSAPIC data.  Some of these may
-		 * get reprogrammed later on with data from the ACPI Interrupt Source
-		 * Override table.
+		 * Map the legacy ISA devices into the IOSAPIC data.  Some of
+		 * these may get reprogrammed later on with data from the ACPI
+		 * Interrupt Source Override table.
 		 */
 		for (isa_irq = 0; isa_irq < 16; ++isa_irq)
-			iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
+			iosapic_override_isa_irq(isa_irq, isa_irq,
+						 IOSAPIC_POL_HIGH,
+						 IOSAPIC_EDGE);
 	}
 	return 0;
 }
@@ -1081,7 +1139,8 @@
 
 		if (iosapic_lists[index].rtes_inuse) {
 			err = -EBUSY;
-			printk(KERN_WARNING "%s: IOSAPIC for GSI base %u is busy\n",
+			printk(KERN_WARNING
+			       "%s: IOSAPIC for GSI base %u is busy\n",
 			       __FUNCTION__, gsi_base);
 			goto out;
 		}
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 0b9e56d..783600f 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -70,6 +70,15 @@
 	  __stop___ex_table = .;
 	}
 
+  /* MCA table */
+  . = ALIGN(16);
+  __mca_table : AT(ADDR(__mca_table) - LOAD_OFFSET)
+	{
+	  __start___mca_table = .;
+	  *(__mca_table)
+	  __stop___mca_table = .;
+	}
+
   /* Global data */
   _data = .;
 
@@ -130,15 +139,6 @@
 	  __initcall_end = .;
 	}
 
-  /* MCA table */
-  . = ALIGN(16);
-  __mca_table : AT(ADDR(__mca_table) - LOAD_OFFSET)
-	{
-	  __start___mca_table = .;
-	  *(__mca_table)
-	  __stop___mca_table = .;
-	}
-
   .data.patch.vtop : AT(ADDR(.data.patch.vtop) - LOAD_OFFSET)
 	{
 	  __start___vtop_patchlist = .;
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 2ef1151..cafa877 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -109,6 +109,7 @@
 {
 	unsigned long addr;
 	struct page *page;
+	unsigned long order;
 
 	if (!pte_exec(pte))
 		return;				/* not an executable page... */
@@ -119,7 +120,12 @@
 	if (test_bit(PG_arch_1, &page->flags))
 		return;				/* i-cache is already coherent with d-cache */
 
-	flush_icache_range(addr, addr + PAGE_SIZE);
+	if (PageCompound(page)) {
+		order = (unsigned long) (page[1].lru.prev);
+		flush_icache_range(addr, addr + (1UL << order << PAGE_SHIFT));
+	}
+	else
+		flush_icache_range(addr, addr + PAGE_SIZE);
 	set_bit(PG_arch_1, &page->flags);	/* mark page as clean */
 }
 
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c
index 6232862..643ccc6 100644
--- a/arch/ia64/mm/ioremap.c
+++ b/arch/ia64/mm/ioremap.c
@@ -21,12 +21,12 @@
 void __iomem *
 ioremap (unsigned long offset, unsigned long size)
 {
-	if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC))
-		return __ioremap(offset, size);
-
 	if (efi_mem_attribute_range(offset, size, EFI_MEMORY_WB))
 		return phys_to_virt(offset);
 
+	if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC))
+		return __ioremap(offset, size);
+
 	/*
 	 * Someday this should check ACPI resources so we
 	 * can do the right thing for hot-plugged regions.
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index 6a4eec9..4dbbca0 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -156,17 +156,19 @@
 		nbits = purge.max_bits;
 	start &= ~((1UL << nbits) - 1);
 
-# ifdef CONFIG_SMP
-	platform_global_tlb_purge(mm, start, end, nbits);
-# else
 	preempt_disable();
+#ifdef CONFIG_SMP
+	if (mm != current->active_mm || cpus_weight(mm->cpu_vm_mask) != 1) {
+		platform_global_tlb_purge(mm, start, end, nbits);
+		preempt_enable();
+		return;
+	}
+#endif
 	do {
 		ia64_ptcl(start, (nbits<<2));
 		start += (1UL << nbits);
 	} while (start < end);
 	preempt_enable();
-# endif
-
 	ia64_srlz_i();			/* srlz.i implies srlz.d */
 }
 EXPORT_SYMBOL(flush_tlb_range);
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 70db21f..d917afa 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -110,7 +110,11 @@
 	if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab))
 		return -1;
 
-	for_each_node(cnode) {
+	/*
+	 * FIXME: replace with cleaner for_each_XXX macro which addresses
+	 * both compute and IO nodes once ACPI3.0 is available.
+	 */
+	for (cnode = 0; cnode < num_cnodes; cnode++) {
 		geoid = cnodeid_get_geoid(cnode);
 		module_id = geo_module(geoid);
 		this_rack = MODULE_GET_RACK(module_id);
@@ -605,7 +609,7 @@
 	op_info->a->arg &= SN_HWPERF_ARG_OBJID_MASK;
 
 	if (cpu != SN_HWPERF_ARG_ANY_CPU) {
-		if (cpu >= num_online_cpus() || !cpu_online(cpu)) {
+		if (cpu >= NR_CPUS || !cpu_online(cpu)) {
 			r = -EINVAL;
 			goto out;
 		}
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index a433b71..2cdc35c 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -491,7 +491,7 @@
 	  If in doubt, say Y here.
 
 config TAU
-	bool "Thermal Management Support"
+	bool "On-chip CPU temperature sensor support"
 	depends on 6xx
 	help
 	  G3 and G4 processors have an on-chip temperature sensor called the
@@ -500,7 +500,7 @@
 	  on-die temperature in /proc/cpuinfo if the cpu supports it.
 
 	  Unfortunately, on some chip revisions, this sensor is very inaccurate
-	  and in some cases, does not work at all, so don't assume the cpu
+	  and in many cases, does not work at all, so don't assume the cpu
 	  temp is actually what /proc/cpuinfo says it is.
 
 config TAU_INT
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 9254806..8d48e9e 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -110,11 +110,6 @@
 	depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \
 		PPC_GEN550 || PPC_MPC52xx
 
-config PPC_OCP
-	bool
-	depends on IBM_OCP || XILINX_OCP
-	default y
-
 choice
 	prompt "Early debugging (dangerous)"
 	bool
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 829e017..6ec84d3 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -129,13 +129,8 @@
 				   arch/powerpc/lib/ \
 				   arch/powerpc/sysdev/ \
 				   arch/powerpc/platforms/
-core-$(CONFIG_PPC32)		+= arch/ppc/kernel/
-core-$(CONFIG_MATH_EMULATION)	+= arch/ppc/math-emu/
+core-$(CONFIG_MATH_EMULATION)	+= arch/powerpc/math-emu/
 core-$(CONFIG_XMON)		+= arch/powerpc/xmon/
-core-$(CONFIG_APUS)		+= arch/ppc/amiga/
-drivers-$(CONFIG_8xx)		+= arch/ppc/8xx_io/
-drivers-$(CONFIG_4xx)		+= arch/ppc/4xx_io/
-drivers-$(CONFIG_CPM2)		+= arch/ppc/8260_io/
 
 drivers-$(CONFIG_OPROFILE)	+= arch/powerpc/oprofile/
 
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index 3c2acab..fe22e54 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc6
-# Wed Mar 15 16:19:48 2006
+# Linux kernel version: 2.6.16
+# Thu Mar 23 20:48:09 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -30,6 +30,7 @@
 CONFIG_PPC_FPU=y
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
 
@@ -51,7 +52,8 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -85,7 +87,7 @@
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_KMOD is not set
+CONFIG_KMOD=y
 CONFIG_STOP_MACHINE=y
 
 #
@@ -130,7 +132,8 @@
 #
 # Cell Broadband Engine options
 #
-CONFIG_SPU_FS=y
+CONFIG_SPU_FS=m
+CONFIG_SPUFS_MMAP=y
 
 #
 # Kernel options
@@ -144,7 +147,7 @@
 # CONFIG_PREEMPT is not set
 CONFIG_PREEMPT_BKL=y
 CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
+CONFIG_BINFMT_MISC=m
 CONFIG_FORCE_MAX_ZONEORDER=13
 # CONFIG_IOMMU_VMERGE is not set
 CONFIG_KEXEC=y
@@ -155,13 +158,16 @@
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
+# CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
 # CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_EXTREME=y
+# CONFIG_MEMORY_HOTPLUG is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
 # CONFIG_PPC_64K_PAGES is not set
 CONFIG_SCHED_SMT=y
 CONFIG_PROC_DEVICETREE=y
@@ -232,6 +238,7 @@
 # CONFIG_IP_VS is not set
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
@@ -244,25 +251,7 @@
 # Core Netfilter Configuration
 #
 # CONFIG_NETFILTER_NETLINK is not set
-CONFIG_NETFILTER_XTABLES=m
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+# CONFIG_NETFILTER_XTABLES is not set
 
 #
 # IP: Netfilter Configuration
@@ -278,51 +267,13 @@
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
 CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_TTL=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
 
 #
 # IPv6: Netfilter Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP6_NF_QUEUE is not set
-# CONFIG_IP6_NF_IPTABLES is not set
 
 #
 # DCCP Configuration (EXPERIMENTAL)
@@ -355,7 +306,6 @@
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
@@ -408,7 +358,7 @@
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
@@ -484,7 +434,23 @@
 #
 # Multi-device support (RAID and LVM)
 #
-# CONFIG_MD is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_MULTIPATH_EMC is not set
 
 #
 # Fusion MPT device support
@@ -548,7 +514,7 @@
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=m
-# CONFIG_E1000_NAPI is not set
+CONFIG_E1000_NAPI=y
 # CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
@@ -560,7 +526,7 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
-CONFIG_SPIDER_NET=y
+CONFIG_SPIDER_NET=m
 # CONFIG_MV643XX_ETH is not set
 
 #
@@ -678,6 +644,8 @@
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_RTAS=y
 
 #
 # IPMI
@@ -694,14 +662,13 @@
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_WATCHDOG_RTAS is not set
+CONFIG_WATCHDOG_RTAS=y
 
 #
 # PCI-based Watchdog Cards
 #
 # CONFIG_PCIPCWATCHDOG is not set
 # CONFIG_WDTPCI is not set
-# CONFIG_RTC is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
@@ -833,6 +800,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -852,7 +820,14 @@
 #
 # InfiniBand support
 #
-# CONFIG_INFINIBAND is not set
+CONFIG_INFINIBAND=y
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
 
 #
 # EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -1037,10 +1012,6 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
-CONFIG_TEXTSEARCH_BM=m
-CONFIG_TEXTSEARCH_FSM=m
 
 #
 # Instrumentation Support
@@ -1058,7 +1029,7 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_MUTEXES is not set
+CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_KOBJECT is not set
diff --git a/arch/powerpc/configs/mpc8540_ads_defconfig b/arch/powerpc/configs/mpc8540_ads_defconfig
index 2a8290e..7f0780f 100644
--- a/arch/powerpc/configs/mpc8540_ads_defconfig
+++ b/arch/powerpc/configs/mpc8540_ads_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 
-# Sat Jan 14 15:57:54 2006
+# Linux kernel version: 2.6.16
+# Mon Mar 27 23:37:36 2006
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -9,6 +9,7 @@
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
@@ -18,6 +19,7 @@
 CONFIG_PPC_OF=y
 CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
+CONFIG_DEFAULT_UIMAGE=y
 
 #
 # Processor support
@@ -42,7 +44,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -58,6 +59,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -72,10 +74,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -90,6 +88,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -183,6 +183,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -220,6 +221,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -229,11 +235,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -487,6 +488,12 @@
 # CONFIG_I2C is not set
 
 #
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
@@ -496,6 +503,7 @@
 #
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
@@ -503,10 +511,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -531,6 +535,7 @@
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -551,7 +556,7 @@
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
@@ -603,7 +608,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -658,6 +662,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 
 #
@@ -695,6 +700,8 @@
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUGGER is not set
 # CONFIG_BDI_SWITCH is not set
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 80e9fe2..0cc0995 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -12,12 +12,12 @@
 
 obj-y				:= semaphore.o cputable.o ptrace.o syscalls.o \
 				   irq.o align.o signal_32.o pmc.o vdso.o \
-				   init_task.o process.o systbl.o
+				   init_task.o process.o systbl.o idle.o
 obj-y				+= vdso32/
 obj-$(CONFIG_PPC64)		+= setup_64.o binfmt_elf32.o sys_ppc32.o \
 				   signal_64.o ptrace32.o \
 				   paca.o cpu_setup_power4.o \
-				   firmware.o sysfs.o idle_64.o
+				   firmware.o sysfs.o
 obj-$(CONFIG_PPC64)		+= vdso64/
 obj-$(CONFIG_ALTIVEC)		+= vecemu.o vector.o
 obj-$(CONFIG_POWER4)		+= idle_power4.o
@@ -34,6 +34,11 @@
 obj-$(CONFIG_GENERIC_TBSYNC)	+= smp-tbsync.o
 obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
+obj-$(CONFIG_6xx)		+= idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
+obj-$(CONFIG_TAU)		+= tau_6xx.o
+obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o
+obj32-$(CONFIG_MODULES)		+= module_32.o
+obj-$(CONFIG_E500)		+= perfmon_fsl_booke.o
 
 ifeq ($(CONFIG_PPC_MERGE),y)
 
@@ -51,7 +56,6 @@
 obj-$(CONFIG_PPC_MULTIPLATFORM)	+= prom_init.o
 obj-$(CONFIG_MODULES)		+= ppc_ksyms.o
 obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
-obj-$(CONFIG_6xx)		+= idle_6xx.o
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_PPC_UDBG_16550)	+= legacy_serial.o udbg_16550.o
@@ -77,6 +81,7 @@
 
 endif
 
+obj-$(CONFIG_PPC32)		+= $(obj32-y)
 obj-$(CONFIG_PPC64)		+= $(obj64-y)
 
 extra-$(CONFIG_PPC_FPU)		+= fpu.o
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 882889b..54b48f3 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -105,8 +105,6 @@
 	DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size));
 	DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size));
 	DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page));
-	DEFINE(PLATFORM_LPAR, PLATFORM_LPAR);
-
 	/* paca */
 	DEFINE(PACA_SIZE, sizeof(struct paca_struct));
 	DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index));
diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S
similarity index 100%
rename from arch/ppc/kernel/cpu_setup_6xx.S
rename to arch/powerpc/kernel/cpu_setup_6xx.S
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 4827ca1..b3a9794 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -135,10 +135,10 @@
 	mfspr	r11,SPRN_HID0
 	mtcr	r11
 BEGIN_FTR_SECTION
-	bt-	8,power_save_6xx_restore	/* Check DOZE */
+	bt-	8,4f			/* Check DOZE */
 END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
 BEGIN_FTR_SECTION
-	bt-	9,power_save_6xx_restore	/* Check NAP */
+	bt-	9,4f			/* Check NAP */
 END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
 #endif /* CONFIG_6xx */
 	.globl transfer_to_handler_cont
@@ -157,6 +157,10 @@
 	SYNC
 	RFI				/* jump to handler, enable MMU */
 
+#ifdef CONFIG_6xx	
+4:	b	power_save_6xx_restore
+#endif
+
 /*
  * On kernel stack overflow, load up an initial stack pointer
  * and call StackOverflow(regs), which should not return.
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 1060155..19ad5c6 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -617,6 +617,12 @@
 	mfsrr1	r10
 	std	r10,_SRR1(r1)
 
+	/* Temporary workaround to clear CR until RTAS can be modified to
+	 * ignore all bits.
+	 */
+	li	r0,0
+	mtcr	r0
+
 	/* There is no way it is acceptable to get here with interrupts enabled,
 	 * check it with the asm equivalent of WARN_ON
 	 */
diff --git a/arch/powerpc/kernel/firmware.c b/arch/powerpc/kernel/firmware.c
index 4d37a3c..0bfe906 100644
--- a/arch/powerpc/kernel/firmware.c
+++ b/arch/powerpc/kernel/firmware.c
@@ -14,7 +14,9 @@
  */
 
 #include <linux/config.h>
+#include <linux/module.h>
 
 #include <asm/firmware.h>
 
-unsigned long ppc64_firmware_features;
+unsigned long powerpc_firmware_features;
+EXPORT_SYMBOL_GPL(powerpc_firmware_features);
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 35084f3..a5ae04a 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -1544,7 +1544,11 @@
 	mr	r28,r6
 	mr	r27,r7
 
-	/* Align the stack to 16-byte boundary for broken yaboot */
+	/*
+	 * Align the stack to 16-byte boundary
+	 * Depending on the size and layout of the ELF sections in the initial
+	 * boot binary, the stack pointer will be unalignet on PowerMac
+	 */
 	rldicr	r1,r1,0,59
 
 	/* Make sure we are running in 64 bits mode */
@@ -1847,21 +1851,6 @@
 	bl	.__save_cpu_setup
 	sync
 
-	/* Setup a valid physical PACA pointer in SPRG3 for early_setup
-	 * note that boot_cpuid can always be 0 nowadays since there is
-	 * nowhere it can be initialized differently before we reach this
-	 * code
-	 */
-	LOAD_REG_IMMEDIATE(r27, boot_cpuid)
-	add	r27,r27,r26
-	lwz	r27,0(r27)
-
-	LOAD_REG_IMMEDIATE(r24, paca) 	/* Get base vaddr of paca array	 */
-	mulli	r13,r27,PACA_SIZE	/* Calculate vaddr of right paca */
-	add	r13,r13,r24		/* for this processor.		 */
-	add	r13,r13,r26		/* convert to physical addr	 */
-	mtspr	SPRN_SPRG3,r13
-	
 	/* Do very early kernel initializations, including initial hash table,
 	 * stab and slb setup before we turn on relocation.	*/
 
@@ -1930,6 +1919,17 @@
 	/* Not reached */
 	BUG_OPCODE
 
+/* Put the paca pointer into r13 and SPRG3 */
+_GLOBAL(setup_boot_paca)
+	LOAD_REG_IMMEDIATE(r3, boot_cpuid)
+	lwz	r3,0(r3)
+	LOAD_REG_IMMEDIATE(r4, paca) 	/* Get base vaddr of paca array	 */
+	mulli	r3,r3,PACA_SIZE		/* Calculate vaddr of right paca */
+	add	r13,r3,r4		/* for this processor.		 */
+	mtspr	SPRN_SPRG3,r13
+
+	blr
+
 /*
  * We put a few things here that have to be page-aligned.
  * This stuff goes at the beginning of the bss, which is page-aligned.
diff --git a/arch/powerpc/kernel/idle_64.c b/arch/powerpc/kernel/idle.c
similarity index 64%
rename from arch/powerpc/kernel/idle_64.c
rename to arch/powerpc/kernel/idle.c
index b879d30..e9f321d 100644
--- a/arch/powerpc/kernel/idle_64.c
+++ b/arch/powerpc/kernel/idle.c
@@ -2,13 +2,17 @@
  * Idle daemon for PowerPC.  Idle daemon will handle any action
  * that needs to be taken when the system becomes idle.
  *
- * Originally Written by Cort Dougan (cort@cs.nmt.edu)
+ * Originally written by Cort Dougan (cort@cs.nmt.edu).
+ * Subsequent 32-bit hacking by Tom Rini, Armin Kuster,
+ * Paul Mackerras and others.
  *
  * iSeries supported added by Mike Corrigan <mikejc@us.ibm.com>
  *
  * Additional shared processor, SMT, and firmware support
  *    Copyright (c) 2003 Dave Engebretsen <engebret@us.ibm.com>
  *
+ * 32-bit and 64-bit versions merged by Paul Mackerras <paulus@samba.org>
+ *
  * 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
@@ -29,18 +33,43 @@
 #include <asm/machdep.h>
 #include <asm/smp.h>
 
-extern void power4_idle(void);
+#ifdef CONFIG_HOTPLUG_CPU
+#define cpu_should_die()	(cpu_is_offline(smp_processor_id()) && \
+				 system_state == SYSTEM_RUNNING)
+#else
+#define cpu_should_die()	0
+#endif
 
-void default_idle(void)
+/*
+ * The body of the idle task.
+ */
+void cpu_idle(void)
 {
-	unsigned int cpu = smp_processor_id();
+	if (ppc_md.idle_loop)
+		ppc_md.idle_loop();	/* doesn't return */
+
 	set_thread_flag(TIF_POLLING_NRFLAG);
-
 	while (1) {
-		if (!need_resched()) {
-			while (!need_resched() && !cpu_is_offline(cpu)) {
-				ppc64_runlatch_off();
+		ppc64_runlatch_off();
 
+		while (!need_resched() && !cpu_should_die()) {
+			if (ppc_md.power_save) {
+				clear_thread_flag(TIF_POLLING_NRFLAG);
+				/*
+				 * smp_mb is so clearing of TIF_POLLING_NRFLAG
+				 * is ordered w.r.t. need_resched() test.
+				 */
+				smp_mb();
+				local_irq_disable();
+
+				/* check again after disabling irqs */
+				if (!need_resched() && !cpu_should_die())
+					ppc_md.power_save();
+
+				local_irq_enable();
+				set_thread_flag(TIF_POLLING_NRFLAG);
+
+			} else {
 				/*
 				 * Go into low thread priority and possibly
 				 * low power mode.
@@ -48,46 +77,18 @@
 				HMT_low();
 				HMT_very_low();
 			}
-
-			HMT_medium();
 		}
 
+		HMT_medium();
 		ppc64_runlatch_on();
+		if (cpu_should_die())
+			cpu_die();
 		preempt_enable_no_resched();
 		schedule();
 		preempt_disable();
-		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
-			cpu_die();
 	}
 }
 
-void native_idle(void)
-{
-	while (1) {
-		ppc64_runlatch_off();
-
-		if (!need_resched())
-			power4_idle();
-
-		if (need_resched()) {
-			ppc64_runlatch_on();
-			preempt_enable_no_resched();
-			schedule();
-			preempt_disable();
-		}
-
-		if (cpu_is_offline(smp_processor_id()) &&
-		    system_state == SYSTEM_RUNNING)
-			cpu_die();
-	}
-}
-
-void cpu_idle(void)
-{
-	BUG_ON(NULL == ppc_md.idle_loop);
-	ppc_md.idle_loop();
-}
-
 int powersave_nap;
 
 #ifdef CONFIG_SYSCTL
diff --git a/arch/powerpc/kernel/idle_6xx.S b/arch/powerpc/kernel/idle_6xx.S
index 444fdcc..12a4efb 100644
--- a/arch/powerpc/kernel/idle_6xx.S
+++ b/arch/powerpc/kernel/idle_6xx.S
@@ -87,19 +87,6 @@
 	cmpwi	0,r3,0
 	beqlr
 
-	/* Clear MSR:EE */
-	mfmsr	r7
-	rlwinm	r0,r7,0,17,15
-	mtmsr	r0
-
-	/* Check current_thread_info()->flags */
-	rlwinm	r4,r1,0,0,18
-	lwz	r4,TI_FLAGS(r4)
-	andi.	r0,r4,_TIF_NEED_RESCHED
-	beq	1f
-	mtmsr	r7	/* out of line this ? */
-	blr
-1:	
 	/* Some pre-nap cleanups needed on some CPUs */
 	andis.	r0,r3,HID0_NAP@h
 	beq	2f
@@ -157,7 +144,8 @@
 	DSSALL
 	sync
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
-	ori	r7,r7,MSR_EE /* Could be ommited (already set) */
+	mfmsr	r7
+	ori	r7,r7,MSR_EE
 	oris	r7,r7,MSR_POW@h
 	sync
 	isync
@@ -220,8 +208,6 @@
 _GLOBAL(nap_save_hid1)
 	.space	4*NR_CPUS
 
-_GLOBAL(powersave_nap)
-	.long	0
 _GLOBAL(powersave_lowspeed)
 	.long	0
 
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
index c16b4af..6dad1c0 100644
--- a/arch/powerpc/kernel/idle_power4.S
+++ b/arch/powerpc/kernel/idle_power4.S
@@ -1,11 +1,5 @@
 /*
- *  This file contains the power_save function for 6xx & 7xxx CPUs
- *  rewritten in assembler
- *
- *  Warning ! This code assumes that if your machine has a 750fx
- *  it will have PLL 1 set to low speed mode (used during NAP/DOZE).
- *  if this is not the case some additional changes will have to
- *  be done to check a runtime var (a bit like powersave-nap)
+ *  This file contains the power_save function for 970-family CPUs.
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
@@ -26,49 +20,23 @@
 
 	.text
 
-/*
- * Here is the power_save_6xx function. This could eventually be
- * split into several functions & changing the function pointer
- * depending on the various features.
- */
 _GLOBAL(power4_idle)
 BEGIN_FTR_SECTION
 	blr
 END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
-	/* We must dynamically check for the NAP feature as it
-	 * can be cleared by CPU init after the fixups are done
-	 */
-	LOAD_REG_ADDRBASE(r3,cur_cpu_spec)
-	ld	r4,ADDROFF(cur_cpu_spec)(r3)
-	ld	r4,CPU_SPEC_FEATURES(r4)
-	andi.	r0,r4,CPU_FTR_CAN_NAP
-	beqlr
 	/* Now check if user or arch enabled NAP mode */
 	LOAD_REG_ADDRBASE(r3,powersave_nap)
 	lwz	r4,ADDROFF(powersave_nap)(r3)
 	cmpwi	0,r4,0
 	beqlr
 
-	/* Clear MSR:EE */
-	mfmsr	r7
-	li	r4,0
-	ori	r4,r4,MSR_EE
-	andc	r0,r7,r4
-	mtmsrd	r0
-
-	/* Check current_thread_info()->flags */
-	clrrdi	r4,r1,THREAD_SHIFT
-	ld	r4,TI_FLAGS(r4)
-	andi.	r0,r4,_TIF_NEED_RESCHED
-	beq	1f
-	mtmsrd	r7	/* out of line this ? */
-	blr
-1:
 	/* Go to NAP now */
 BEGIN_FTR_SECTION
 	DSSALL
 	sync
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+	mfmsr	r7
+	ori	r7,r7,MSR_EE
 	oris	r7,r7,MSR_POW@h
 	sync
 	isync
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 771a59c..bb5c950 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -379,7 +379,7 @@
 	struct thread_info *tp;
 	int i;
 
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		memset((void *)softirq_ctx[i], 0, THREAD_SIZE);
 		tp = softirq_ctx[i];
 		tp->cpu = i;
diff --git a/arch/ppc/kernel/l2cr.S b/arch/powerpc/kernel/l2cr_6xx.S
similarity index 100%
rename from arch/ppc/kernel/l2cr.S
rename to arch/powerpc/kernel/l2cr_6xx.S
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index c7a799a..6e67b5b 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -37,7 +37,7 @@
 static int __init add_legacy_port(struct device_node *np, int want_index,
 				  int iotype, phys_addr_t base,
 				  phys_addr_t taddr, unsigned long irq,
-				  unsigned int flags)
+				  upf_t flags)
 {
 	u32 *clk, *spd, clock = BASE_BAUD * 16;
 	int index;
@@ -113,7 +113,7 @@
 {
 	phys_addr_t addr;
 	u32 *addrp;
-	unsigned int flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
+	upf_t flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
 
 	/* We only support ports that have a clock frequency properly
 	 * encoded in the device-tree.
@@ -236,6 +236,23 @@
 }
 #endif
 
+static void __init setup_legacy_serial_console(int console)
+{
+	struct legacy_serial_info *info =
+		&legacy_serial_infos[console];
+	void __iomem *addr;
+
+	if (info->taddr == 0)
+		return;
+	addr = ioremap(info->taddr, 0x1000);
+	if (addr == NULL)
+		return;
+	if (info->speed == 0)
+		info->speed = udbg_probe_uart_speed(addr, info->clock);
+	DBG("default console speed = %d\n", info->speed);
+	udbg_init_uart(addr, info->speed, info->clock);
+}
+
 /*
  * This is called very early, as part of setup_system() or eventually
  * setup_arch(), basically before anything else in this file. This function
@@ -318,25 +335,8 @@
 #endif
 
 	DBG("legacy_serial_console = %d\n", legacy_serial_console);
-
-	/* udbg is 64 bits only for now, that will change soon though ... */
-	while (legacy_serial_console >= 0) {
-		struct legacy_serial_info *info =
-			&legacy_serial_infos[legacy_serial_console];
-		void __iomem *addr;
-
-		if (info->taddr == 0)
-			break;
-		addr = ioremap(info->taddr, 0x1000);
-		if (addr == NULL)
-			break;
-		if (info->speed == 0)
-			info->speed = udbg_probe_uart_speed(addr, info->clock);
-		DBG("default console speed = %d\n", info->speed);
-		udbg_init_uart(addr, info->speed, info->clock);
-		break;
-	}
-
+	if (legacy_serial_console >= 0)
+		setup_legacy_serial_console(legacy_serial_console);
 	DBG(" <- find_legacy_serial_port()\n");
 }
 
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index e789fef..1b73508 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -56,7 +56,7 @@
 	unsigned long sum_purr = 0;
 	int cpu;
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		sum_purr += lppaca[cpu].emulated_time_base;
 
 #ifdef PURR_DEBUG
@@ -222,7 +222,7 @@
 	int cpu;
 	struct cpu_usage *cu;
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		cu = &per_cpu(cpu_usage_array, cpu);
 		sum_purr += cu->current_tb;
 	}
diff --git a/arch/ppc/kernel/module.c b/arch/powerpc/kernel/module_32.c
similarity index 100%
rename from arch/ppc/kernel/module.c
rename to arch/powerpc/kernel/module_32.c
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index fd7db8d..ada50aa 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -160,7 +160,7 @@
 	case IOC_NVRAM_GET_OFFSET: {
 		int part, offset;
 
-		if (_machine != PLATFORM_POWERMAC)
+		if (!machine_is(powermac))
 			return -EINVAL;
 		if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0)
 			return -EFAULT;
@@ -174,8 +174,9 @@
 		return 0;
 	}
 #endif /* CONFIG_PPC_PMAC */
+	default:
+		return -EINVAL;
 	}
-	return -EINVAL;
 }
 
 struct file_operations nvram_fops = {
@@ -443,7 +444,7 @@
 	 * in our nvram, as Apple defined partitions use pretty much
 	 * all of the space
 	 */
-	if (_machine == PLATFORM_POWERMAC)
+	if (machine_is(powermac))
 		return -ENOSPC;
 
 	/* see if we have an OS partition that meets our needs.
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 5d1b708..f505a88 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -56,14 +56,11 @@
  * processors.  The processor VPD array needs one entry per physical
  * processor (not thread).
  */
-#define PACA_INIT_COMMON(number, start, asrr, asrv)			    \
+#define PACA_INIT_COMMON(number)					    \
 	.lppaca_ptr = &lppaca[number],					    \
 	.lock_token = 0x8000,						    \
 	.paca_index = (number),		/* Paca Index */		    \
 	.kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL,		    \
-	.stab_real = (asrr), 		/* Real pointer to segment table */ \
-	.stab_addr = (asrv),		/* Virt pointer to segment table */ \
-	.cpu_start = (start),		/* Processor start */		    \
 	.hw_cpu_id = 0xffff,
 
 #ifdef CONFIG_PPC_ISERIES
@@ -72,30 +69,20 @@
 
 #define PACA_INIT(number)						    \
 {									    \
-	PACA_INIT_COMMON(number, 0, 0, 0)				    \
-	PACA_INIT_ISERIES(number)					    \
-}
-
-#define BOOTCPU_PACA_INIT(number)					    \
-{									    \
-	PACA_INIT_COMMON(number, 1, 0, (u64)&initial_stab)		    \
+	PACA_INIT_COMMON(number)					    \
 	PACA_INIT_ISERIES(number)					    \
 }
 
 #else
 #define PACA_INIT(number)						    \
 {									    \
-	PACA_INIT_COMMON(number, 0, 0, 0)				    \
+	PACA_INIT_COMMON(number)					    \
 }
 
-#define BOOTCPU_PACA_INIT(number)					    \
-{									    \
-	PACA_INIT_COMMON(number, 1, STAB0_PHYS_ADDR, (u64)&initial_stab)    \
-}
 #endif
 
 struct paca_struct paca[] = {
-	BOOTCPU_PACA_INIT(0),
+	PACA_INIT(0),
 #if NR_CPUS > 1
 	PACA_INIT(  1), PACA_INIT(  2), PACA_INIT(  3),
 #if NR_CPUS > 4
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 704c846..b129d2e 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -787,7 +787,7 @@
 	 * fix has to be done by making the remapping per-host and always
 	 * filling the pci_to_OF map. --BenH
 	 */
-	if (_machine == _MACH_Pmac && busnr >= 0xf0)
+	if (machine_is(powermac) && busnr >= 0xf0)
 		busnr -= 0xf0;
 	else
 #endif
@@ -1728,7 +1728,7 @@
 	 * (bus 0 is HT root), we return the AGP one instead.
 	 */
 #ifdef CONFIG_PPC_PMAC
-	if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4"))
+	if (machine_is(powermac) && machine_is_compatible("MacRISC4"))
 		if (bus == 0)
 			bus = 0xf0;
 #endif /* CONFIG_PPC_PMAC */
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index ba92bab7..4c4449b 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -78,6 +78,7 @@
 
 /* Cached ISA bridge dev. */
 struct pci_dev *ppc64_isabridge_dev = NULL;
+EXPORT_SYMBOL_GPL(ppc64_isabridge_dev);
 
 static void fixup_broken_pcnet32(struct pci_dev* dev)
 {
diff --git a/arch/ppc/kernel/perfmon_fsl_booke.c b/arch/powerpc/kernel/perfmon_fsl_booke.c
similarity index 100%
rename from arch/ppc/kernel/perfmon_fsl_booke.c
rename to arch/powerpc/kernel/perfmon_fsl_booke.c
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
index 7ba42a4..3c2cf66 100644
--- a/arch/powerpc/kernel/proc_ppc64.c
+++ b/arch/powerpc/kernel/proc_ppc64.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 
+#include <asm/machdep.h>
 #include <asm/vdso_datapage.h>
 #include <asm/rtas.h>
 #include <asm/uaccess.h>
@@ -51,7 +52,7 @@
 	if (!root)
 		return 1;
 
-	if (!(platform_is_pseries() || _machine == PLATFORM_CELL))
+	if (!machine_is(pseries) && !machine_is(cell))
 		return 0;
 
 	if (!proc_mkdir("rtas", root))
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index f698aa7..706090c 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -45,6 +45,7 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/time.h>
+#include <asm/syscalls.h>
 #ifdef CONFIG_PPC64
 #include <asm/firmware.h>
 #endif
@@ -362,7 +363,11 @@
 		if (!(i % 8))
 			printk("\n");
 
-		if (BAD_PC(pc) || __get_user(instr, (unsigned int *)pc)) {
+		/* We use __get_user here *only* to avoid an OOPS on a
+		 * bad address because the pc *should* only be a
+		 * kernel address.
+		 */
+		if (BAD_PC(pc) || __get_user(instr, (unsigned int __user *)pc)) {
 			printk("XXXXXXXX ");
 		} else {
 			if (regs->nip == pc)
@@ -765,7 +770,7 @@
 	return error;
 }
 
-static int validate_sp(unsigned long sp, struct task_struct *p,
+int validate_sp(unsigned long sp, struct task_struct *p,
 		       unsigned long nbytes)
 {
 	unsigned long stack_page = (unsigned long)task_stack_page(p);
@@ -803,6 +808,8 @@
 #define FRAME_MARKER	2
 #endif
 
+EXPORT_SYMBOL(validate_sp);
+
 unsigned long get_wchan(struct task_struct *p)
 {
 	unsigned long ip, sp;
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index d63cd56..4336390 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -383,14 +383,14 @@
 			/* Apple uses bits in there in a different way, let's
 			 * only keep the real sense bit on macs
 			 */
-			if (_machine == PLATFORM_POWERMAC)
+			if (machine_is(powermac))
 				sense &= 0x1;
 			np->intrs[intrcount].sense = map_mpic_senses[sense];
 		}
 
 #ifdef CONFIG_PPC64
 		/* We offset irq numbers for the u3 MPIC by 128 in PowerMac */
-		if (_machine == PLATFORM_POWERMAC && ic && ic->parent) {
+		if (machine_is(powermac) && ic && ic->parent) {
 			char *name = get_property(ic->parent, "name", NULL);
 			if (name && !strcmp(name, "u3"))
 				np->intrs[intrcount].line += 128;
@@ -570,6 +570,18 @@
 	return rc;
 }
 
+unsigned long __init of_get_flat_dt_root(void)
+{
+	unsigned long p = ((unsigned long)initial_boot_params) +
+		initial_boot_params->off_dt_struct;
+
+	while(*((u32 *)p) == OF_DT_NOP)
+		p += 4;
+	BUG_ON (*((u32 *)p) != OF_DT_BEGIN_NODE);
+	p += 4;
+	return _ALIGN(p + strlen((char *)p) + 1, 4);
+}
+
 /**
  * This  function can be used within scan_flattened_dt callback to get
  * access to properties
@@ -612,6 +624,25 @@
 	} while(1);
 }
 
+int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
+{
+	const char* cp;
+	unsigned long cplen, l;
+
+	cp = of_get_flat_dt_prop(node, "compatible", &cplen);
+	if (cp == NULL)
+		return 0;
+	while (cplen > 0) {
+		if (strncasecmp(cp, compat, strlen(compat)) == 0)
+			return 1;
+		l = strlen(cp) + 1;
+		cp += l;
+		cplen -= l;
+	}
+
+	return 0;
+}
+
 static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
 				       unsigned long align)
 {
@@ -686,7 +717,7 @@
 #ifdef DEBUG
 				if ((strlen(p) + l + 1) != allocl) {
 					DBG("%s: p: %d, l: %d, a: %d\n",
-					    pathp, strlen(p), l, allocl);
+					    pathp, (int)strlen(p), l, allocl);
 				}
 #endif
 				p += strlen(p);
@@ -854,35 +885,73 @@
 	DBG(" <- unflatten_device_tree()\n");
 }
 
-
 static int __init early_init_dt_scan_cpus(unsigned long node,
-					  const char *uname, int depth, void *data)
+					  const char *uname, int depth,
+					  void *data)
 {
+	static int logical_cpuid = 0;
+	char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+#ifdef CONFIG_ALTIVEC
 	u32 *prop;
-	unsigned long size;
-	char *type = of_get_flat_dt_prop(node, "device_type", &size);
+#endif
+	u32 *intserv;
+	int i, nthreads;
+	unsigned long len;
+	int found = 0;
 
 	/* We are scanning "cpu" nodes only */
 	if (type == NULL || strcmp(type, "cpu") != 0)
 		return 0;
 
-	boot_cpuid = 0;
-	boot_cpuid_phys = 0;
-	if (initial_boot_params && initial_boot_params->version >= 2) {
-		/* version 2 of the kexec param format adds the phys cpuid
-		 * of booted proc.
-		 */
-		boot_cpuid_phys = initial_boot_params->boot_cpuid_phys;
+	/* Get physical cpuid */
+	intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len);
+	if (intserv) {
+		nthreads = len / sizeof(int);
 	} else {
-		/* Check if it's the boot-cpu, set it's hw index now */
-		if (of_get_flat_dt_prop(node,
-					"linux,boot-cpu", NULL) != NULL) {
-			prop = of_get_flat_dt_prop(node, "reg", NULL);
-			if (prop != NULL)
-				boot_cpuid_phys = *prop;
-		}
+		intserv = of_get_flat_dt_prop(node, "reg", NULL);
+		nthreads = 1;
 	}
-	set_hard_smp_processor_id(0, boot_cpuid_phys);
+
+	/*
+	 * Now see if any of these threads match our boot cpu.
+	 * NOTE: This must match the parsing done in smp_setup_cpu_maps.
+	 */
+	for (i = 0; i < nthreads; i++) {
+		/*
+		 * version 2 of the kexec param format adds the phys cpuid of
+		 * booted proc.
+		 */
+		if (initial_boot_params && initial_boot_params->version >= 2) {
+			if (intserv[i] ==
+					initial_boot_params->boot_cpuid_phys) {
+				found = 1;
+				break;
+			}
+		} else {
+			/*
+			 * Check if it's the boot-cpu, set it's hw index now,
+			 * unfortunately this format did not support booting
+			 * off secondary threads.
+			 */
+			if (of_get_flat_dt_prop(node,
+					"linux,boot-cpu", NULL) != NULL) {
+				found = 1;
+				break;
+			}
+		}
+
+#ifdef CONFIG_SMP
+		/* logical cpu id is always 0 on UP kernels */
+		logical_cpuid++;
+#endif
+	}
+
+	if (found) {
+		DBG("boot cpu: logical %d physical %d\n", logical_cpuid,
+			intserv[i]);
+		boot_cpuid = logical_cpuid;
+		set_hard_smp_processor_id(boot_cpuid, intserv[i]);
+	}
 
 #ifdef CONFIG_ALTIVEC
 	/* Check if we have a VMX and eventually update CPU features */
@@ -901,16 +970,10 @@
 #endif /* CONFIG_ALTIVEC */
 
 #ifdef CONFIG_PPC_PSERIES
-	/*
-	 * Check for an SMT capable CPU and set the CPU feature. We do
-	 * this by looking at the size of the ibm,ppc-interrupt-server#s
-	 * property
-	 */
-	prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
-				       &size);
-	cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
-	if (prop && ((size / sizeof(u32)) > 1))
+	if (nthreads > 1)
 		cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
+	else
+		cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
 #endif
 
 	return 0;
@@ -919,7 +982,6 @@
 static int __init early_init_dt_scan_chosen(unsigned long node,
 					    const char *uname, int depth, void *data)
 {
-	u32 *prop;
 	unsigned long *lprop;
 	unsigned long l;
 	char *p;
@@ -930,14 +992,6 @@
 	    (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
 		return 0;
 
-	/* get platform type */
-	prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL);
-	if (prop == NULL)
-		return 0;
-#ifdef CONFIG_PPC_MULTIPLATFORM
-	_machine = *prop;
-#endif
-
 #ifdef CONFIG_PPC64
 	/* check if iommu is forced on or off */
 	if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
@@ -964,15 +1018,15 @@
 	 * set of RTAS infos now if available
 	 */
 	{
-		u64 *basep, *entryp;
+		u64 *basep, *entryp, *sizep;
 
 		basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL);
 		entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
-		prop = of_get_flat_dt_prop(node, "linux,rtas-size", NULL);
-		if (basep && entryp && prop) {
+		sizep = of_get_flat_dt_prop(node, "linux,rtas-size", NULL);
+		if (basep && entryp && sizep) {
 			rtas.base = *basep;
 			rtas.entry = *entryp;
-			rtas.size = *prop;
+			rtas.size = *sizep;
 		}
 	}
 #endif /* CONFIG_PPC_RTAS */
@@ -1001,25 +1055,13 @@
 
 	if (strstr(cmd_line, "mem=")) {
 		char *p, *q;
-		unsigned long maxmem = 0;
 
 		for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
 			q = p + 4;
 			if (p > cmd_line && p[-1] != ' ')
 				continue;
-			maxmem = simple_strtoul(q, &q, 0);
-			if (*q == 'k' || *q == 'K') {
-				maxmem <<= 10;
-				++q;
-			} else if (*q == 'm' || *q == 'M') {
-				maxmem <<= 20;
-				++q;
-			} else if (*q == 'g' || *q == 'G') {
-				maxmem <<= 30;
-				++q;
-			}
+			memory_limit = memparse(q, &q);
 		}
-		memory_limit = maxmem;
 	}
 
 	/* break now */
@@ -1755,7 +1797,7 @@
 	/* We don't support that function on PowerMac, at least
 	 * not yet
 	 */
-	if (_machine == PLATFORM_POWERMAC)
+	if (machine_is(powermac))
 		return -ENODEV;
 
 	/* fix up new node's linux_phandle field */
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 813c2cd..d66c5e7 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -180,6 +180,16 @@
 static unsigned long __initdata prom_tce_alloc_end;
 #endif
 
+/* Platforms codes are now obsolete in the kernel. Now only used within this
+ * file and ultimately gone too. Feel free to change them if you need, they
+ * are not shared with anything outside of this file anymore
+ */
+#define PLATFORM_PSERIES	0x0100
+#define PLATFORM_PSERIES_LPAR	0x0101
+#define PLATFORM_LPAR		0x0001
+#define PLATFORM_POWERMAC	0x0400
+#define PLATFORM_GENERIC	0x0500
+
 static int __initdata of_platform;
 
 static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
@@ -397,6 +407,11 @@
 	reason = PTRRELOC(reason);
 #endif
 	prom_print(reason);
+	/* Do not call exit because it clears the screen on pmac
+	 * it also causes some sort of double-fault on early pmacs */
+	if (RELOC(of_platform) == PLATFORM_POWERMAC)
+		asm("trap\n");
+
 	/* ToDo: should put up an SRC here on p/iSeries */
 	call_prom("exit", 0, 0);
 
@@ -1487,7 +1502,10 @@
 	int len, i = 0;
 #ifdef CONFIG_PPC64
 	phandle rtas;
+	int x;
 #endif
+
+	/* Look for a PowerMac */
 	len = prom_getprop(_prom->root, "compatible",
 			   compat, sizeof(compat)-1);
 	if (len > 0) {
@@ -1500,28 +1518,36 @@
 			if (strstr(p, RELOC("Power Macintosh")) ||
 			    strstr(p, RELOC("MacRISC")))
 				return PLATFORM_POWERMAC;
-#ifdef CONFIG_PPC64
-			if (strstr(p, RELOC("Momentum,Maple")))
-				return PLATFORM_MAPLE;
-			if (strstr(p, RELOC("IBM,CPB")))
-				return PLATFORM_CELL;
-#endif
 			i += sl + 1;
 		}
 	}
 #ifdef CONFIG_PPC64
+	/* If not a mac, try to figure out if it's an IBM pSeries or any other
+	 * PAPR compliant platform. We assume it is if :
+	 *  - /device_type is "chrp" (please, do NOT use that for future
+	 *    non-IBM designs !
+	 *  - it has /rtas
+	 */
+	len = prom_getprop(_prom->root, "model",
+			   compat, sizeof(compat)-1);
+	if (len <= 0)
+		return PLATFORM_GENERIC;
+	compat[len] = 0;
+	if (strcmp(compat, "chrp"))
+		return PLATFORM_GENERIC;
+
 	/* Default to pSeries. We need to know if we are running LPAR */
 	rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
-	if (PHANDLE_VALID(rtas)) {
-		int x = prom_getproplen(rtas, "ibm,hypertas-functions");
-		if (x != PROM_ERROR) {
-			prom_printf("Hypertas detected, assuming LPAR !\n");
-			return PLATFORM_PSERIES_LPAR;
-		}
+	if (!PHANDLE_VALID(rtas))
+		return PLATFORM_GENERIC;
+	x = prom_getproplen(rtas, "ibm,hypertas-functions");
+	if (x != PROM_ERROR) {
+		prom_printf("Hypertas detected, assuming LPAR !\n");
+		return PLATFORM_PSERIES_LPAR;
 	}
 	return PLATFORM_PSERIES;
 #else
-	return PLATFORM_CHRP;
+	return PLATFORM_GENERIC;
 #endif
 }
 
@@ -2029,7 +2055,6 @@
 {	
        	struct prom_t *_prom;
 	unsigned long hdr;
-	u32 getprop_rval;
 	unsigned long offset = reloc_offset();
 
 #ifdef CONFIG_PPC32
@@ -2060,6 +2085,12 @@
 	 */
 	prom_init_stdout();
 
+	/*
+	 * Get default machine type. At this point, we do not differentiate
+	 * between pSeries SMP and pSeries LPAR
+	 */
+	RELOC(of_platform) = prom_find_machine_type();
+
 	/* Bail if this is a kdump kernel. */
 	if (PHYSICAL_START > 0)
 		prom_panic("Error: You can't boot a kdump kernel from OF!\n");
@@ -2069,15 +2100,6 @@
 	 */
 	prom_check_initrd(r3, r4);
 
-	/*
-	 * Get default machine type. At this point, we do not differentiate
-	 * between pSeries SMP and pSeries LPAR
-	 */
-	RELOC(of_platform) = prom_find_machine_type();
-	getprop_rval = RELOC(of_platform);
-	prom_setprop(_prom->chosen, "/chosen", "linux,platform",
-		     &getprop_rval, sizeof(getprop_rval));
-
 #ifdef CONFIG_PPC_PSERIES
 	/*
 	 * On pSeries, inform the firmware about our capabilities
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c
index 1f03fb2..456286c 100644
--- a/arch/powerpc/kernel/rtas-proc.c
+++ b/arch/powerpc/kernel/rtas-proc.c
@@ -257,7 +257,7 @@
 {
 	struct proc_dir_entry *entry;
 
-	if (_machine != PLATFORM_PSERIES && _machine != PLATFORM_PSERIES_LPAR)
+	if (!machine_is(pseries))
 		return 1;
 
 	rtas_node = of_find_node_by_name(NULL, "rtas");
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index b5b2add..06636c9 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -25,6 +25,7 @@
 #include <asm/hvcall.h>
 #include <asm/semaphore.h>
 #include <asm/machdep.h>
+#include <asm/firmware.h>
 #include <asm/page.h>
 #include <asm/param.h>
 #include <asm/system.h>
@@ -32,6 +33,7 @@
 #include <asm/uaccess.h>
 #include <asm/lmb.h>
 #include <asm/udbg.h>
+#include <asm/syscalls.h>
 
 struct rtas_t rtas = {
 	.lock = SPIN_LOCK_UNLOCKED
@@ -591,7 +593,7 @@
 		data->waiting = 0;
 		data->args->args[data->args->nargs] =
 			rtas_call(ibm_suspend_me_token, 0, 1, NULL);
-		for_each_cpu(i)
+		for_each_possible_cpu(i)
 			plpar_hcall_norets(H_PROD,i);
 	} else {
 		data->waiting = -EBUSY;
@@ -624,7 +626,7 @@
 	/* Prod each CPU.  This won't hurt, and will wake
 	 * anyone we successfully put to sleep with H_Join
 	 */
-	for_each_cpu(i)
+	for_each_possible_cpu(i)
 		plpar_hcall_norets(H_PROD, i);
 
 	return data.waiting;
@@ -767,7 +769,7 @@
 	 * the stop-self token if any
 	 */
 #ifdef CONFIG_PPC64
-	if (_machine == PLATFORM_PSERIES_LPAR) {
+	if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR)) {
 		rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX);
 		ibm_suspend_me_token = rtas_token("ibm,suspend-me");
 	}
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index c1d62bf..c607f3b 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -9,6 +9,9 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  */
+
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/string.h>
@@ -41,6 +44,7 @@
 #include <asm/time.h>
 #include <asm/cputable.h>
 #include <asm/sections.h>
+#include <asm/firmware.h>
 #include <asm/btext.h>
 #include <asm/nvram.h>
 #include <asm/setup.h>
@@ -56,8 +60,6 @@
 
 #include "setup.h"
 
-#undef DEBUG
-
 #ifdef DEBUG
 #include <asm/udbg.h>
 #define DBG(fmt...) udbg_printf(fmt)
@@ -65,10 +67,12 @@
 #define DBG(fmt...)
 #endif
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
-int _machine = 0;
-EXPORT_SYMBOL(_machine);
-#endif
+/* The main machine-dep calls structure
+ */
+struct machdep_calls ppc_md;
+EXPORT_SYMBOL(ppc_md);
+struct machdep_calls *machine_id;
+EXPORT_SYMBOL(machine_id);
 
 unsigned long klimit = (unsigned long) _end;
 
@@ -168,7 +172,8 @@
 			   bogosum/(500000/HZ), bogosum/(5000/HZ) % 100);
 #endif /* CONFIG_SMP && CONFIG_PPC32 */
 		seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
-
+		if (ppc_md.name)
+			seq_printf(m, "platform\t: %s\n", ppc_md.name);
 		if (ppc_md.show_cpuinfo != NULL)
 			ppc_md.show_cpuinfo(m);
 
@@ -352,12 +357,13 @@
  * must be called before using this.
  *
  * While we're here, we may as well set the "physical" cpu ids in the paca.
+ *
+ * NOTE: This must match the parsing done in early_init_dt_scan_cpus.
  */
 void __init smp_setup_cpu_maps(void)
 {
 	struct device_node *dn = NULL;
 	int cpu = 0;
-	int swap_cpuid = 0;
 
 	while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
 		int *intserv;
@@ -376,30 +382,17 @@
 		for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
 			cpu_set(cpu, cpu_present_map);
 			set_hard_smp_processor_id(cpu, intserv[j]);
-
-			if (intserv[j] == boot_cpuid_phys)
-				swap_cpuid = cpu;
 			cpu_set(cpu, cpu_possible_map);
 			cpu++;
 		}
 	}
 
-	/* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that
-	 * boot cpu is logical 0.
-	 */
-	if (boot_cpuid_phys != get_hard_smp_processor_id(0)) {
-		u32 tmp;
-		tmp = get_hard_smp_processor_id(0);
-		set_hard_smp_processor_id(0, boot_cpuid_phys);
-		set_hard_smp_processor_id(swap_cpuid, tmp);
-	}
-
 #ifdef CONFIG_PPC64
 	/*
 	 * On pSeries LPAR, we need to know how many cpus
 	 * could possibly be added to this partition.
 	 */
-	if (_machine == PLATFORM_PSERIES_LPAR &&
+	if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR) &&
 	    (dn = of_find_node_by_path("/rtas"))) {
 		int num_addr_cell, num_size_cell, maxcpus;
 		unsigned int *ireg;
@@ -438,7 +431,7 @@
 	/*
 	 * Do the sibling map; assume only two threads per processor.
 	 */
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		cpu_set(cpu, cpu_sibling_map[cpu]);
 		if (cpu_has_feature(CPU_FTR_SMT))
 			cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
@@ -468,3 +461,34 @@
 }
 early_param("xmon", early_xmon);
 #endif
+
+void probe_machine(void)
+{
+	extern struct machdep_calls __machine_desc_start;
+	extern struct machdep_calls __machine_desc_end;
+
+	/*
+	 * Iterate all ppc_md structures until we find the proper
+	 * one for the current machine type
+	 */
+	DBG("Probing machine type ...\n");
+
+	for (machine_id = &__machine_desc_start;
+	     machine_id < &__machine_desc_end;
+	     machine_id++) {
+		DBG("  %s ...", machine_id->name);
+		memcpy(&ppc_md, machine_id, sizeof(struct machdep_calls));
+		if (ppc_md.probe()) {
+			DBG(" match !\n");
+			break;
+		}
+		DBG("\n");
+	}
+	/* What can we do if we didn't find ? */
+	if (machine_id >= &__machine_desc_end) {
+		DBG("No suitable machine found !\n");
+		for (;;);
+	}
+
+	printk(KERN_INFO "Using %s machine description\n", ppc_md.name);
+}
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index dc2770d..a72bf5d 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -53,9 +53,6 @@
 extern void platform_init(void);
 extern void bootx_init(unsigned long r4, unsigned long phys);
 
-extern void ppc6xx_idle(void);
-extern void power4_idle(void);
-
 boot_infos_t *boot_infos;
 struct ide_machdep_calls ppc_ide_md;
 
@@ -70,10 +67,6 @@
 int have_of = 1;
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
-extern void prep_init(void);
-extern void pmac_init(void);
-extern void chrp_init(void);
-
 dev_t boot_dev;
 #endif /* CONFIG_PPC_MULTIPLATFORM */
 
@@ -85,9 +78,6 @@
 unsigned long vgacon_remap_base;
 #endif
 
-struct machdep_calls ppc_md;
-EXPORT_SYMBOL(ppc_md);
-
 /*
  * These are used in binfmt_elf.c to put aux entries on the stack
  * for each elf executable being started.
@@ -111,7 +101,7 @@
 
 	/* First zero the BSS -- use memset_io, some platforms don't have
 	 * caches on yet */
-	memset_io(PTRRELOC(&__bss_start), 0, _end - __bss_start);
+	memset_io((void __iomem *)PTRRELOC(&__bss_start), 0, _end - __bss_start);
 
 	/*
 	 * Identify the CPU type and fix up code sections
@@ -123,48 +113,6 @@
 	return KERNELBASE + offset;
 }
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
-/*
- * The PPC_MULTIPLATFORM version of platform_init...
- */
-void __init platform_init(void)
-{
-	/* if we didn't get any bootinfo telling us what we are... */
-	if (_machine == 0) {
-		/* prep boot loader tells us if we're prep or not */
-		if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
-			_machine = _MACH_prep;
-	}
-
-#ifdef CONFIG_PPC_PREP
-	/* not much more to do here, if prep */
-	if (_machine == _MACH_prep) {
-		prep_init();
-		return;
-	}
-#endif
-
-#ifdef CONFIG_ADB
-	if (strstr(cmd_line, "adb_sync")) {
-		extern int __adb_probe_sync;
-		__adb_probe_sync = 1;
-	}
-#endif /* CONFIG_ADB */
-
-	switch (_machine) {
-#ifdef CONFIG_PPC_PMAC
-	case _MACH_Pmac:
-		pmac_init();
-		break;
-#endif
-#ifdef CONFIG_PPC_CHRP
-	case _MACH_chrp:
-		chrp_init();
-		break;
-#endif
-	}
-}
-#endif
 
 /*
  * Find out what kind of machine we're on and save any data we need
@@ -190,11 +138,17 @@
 		strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
 #endif /* CONFIG_CMDLINE */
 
-	/* Base init based on machine type */
+#ifdef CONFIG_PPC_MULTIPLATFORM
+	probe_machine();
+#else
+	/* Base init based on machine type. Obsoloete, please kill ! */
 	platform_init();
+#endif
 
 #ifdef CONFIG_6xx
-	ppc_md.power_save = ppc6xx_idle;
+	if (cpu_has_feature(CPU_FTR_CAN_DOZE) ||
+	    cpu_has_feature(CPU_FTR_CAN_NAP))
+		ppc_md.power_save = ppc6xx_idle;
 #endif
 
 	if (ppc_md.progress)
@@ -272,7 +226,7 @@
 	if ( ppc_md.progress ) ppc_md.progress("             ", 0xffff);
 
 	/* register CPU devices */
-	for_each_cpu(i)
+	for_each_possible_cpu(i)
 		register_cpu(&cpu_devices[i], i, NULL);
 
 	/* call platform init */
@@ -352,12 +306,6 @@
 	do_init_bootmem();
 	if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
 
-#ifdef CONFIG_PPC_OCP
-	/* Initialize OCP device list */
-	ocp_early_init();
-	if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab);
-#endif
-
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
 #endif
@@ -366,7 +314,4 @@
 	if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
 
 	paging_init();
-
-	/* this is for modules since _machine can be a define -- Cort */
-	ppc_md.ppc_machine = _machine;
 }
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index e20c1fa..59aa92c 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -73,7 +73,6 @@
 
 int have_of = 1;
 int boot_cpuid = 0;
-int boot_cpuid_phys = 0;
 dev_t boot_dev;
 u64 ppc64_pft_size;
 
@@ -96,11 +95,6 @@
 int icache_bsize;
 int ucache_bsize;
 
-/* The main machine-dep calls structure
- */
-struct machdep_calls ppc_md;
-EXPORT_SYMBOL(ppc_md);
-
 #ifdef CONFIG_MAGIC_SYSRQ
 unsigned long SYSRQ_KEY;
 #endif /* CONFIG_MAGIC_SYSRQ */
@@ -161,32 +155,6 @@
 #define check_smt_enabled()
 #endif /* CONFIG_SMP */
 
-extern struct machdep_calls pSeries_md;
-extern struct machdep_calls pmac_md;
-extern struct machdep_calls maple_md;
-extern struct machdep_calls cell_md;
-extern struct machdep_calls iseries_md;
-
-/* Ultimately, stuff them in an elf section like initcalls... */
-static struct machdep_calls __initdata *machines[] = {
-#ifdef CONFIG_PPC_PSERIES
-	&pSeries_md,
-#endif /* CONFIG_PPC_PSERIES */
-#ifdef CONFIG_PPC_PMAC
-	&pmac_md,
-#endif /* CONFIG_PPC_PMAC */
-#ifdef CONFIG_PPC_MAPLE
-	&maple_md,
-#endif /* CONFIG_PPC_MAPLE */
-#ifdef CONFIG_PPC_CELL
-	&cell_md,
-#endif
-#ifdef CONFIG_PPC_ISERIES
-	&iseries_md,
-#endif
-	NULL
-};
-
 /*
  * Early initialization entry point. This is called by head.S
  * with MMU translation disabled. We rely on the "feature" of
@@ -208,13 +176,10 @@
 
 void __init early_setup(unsigned long dt_ptr)
 {
-	struct paca_struct *lpaca = get_paca();
-	static struct machdep_calls **mach;
-
 	/* Enable early debugging if any specified (see udbg.h) */
 	udbg_early_init();
 
-	DBG(" -> early_setup()\n");
+ 	DBG(" -> early_setup(), dt_ptr: 0x%lx\n", dt_ptr);
 
 	/*
 	 * Do early initializations using the flattened device
@@ -223,22 +188,16 @@
 	 */
 	early_init_devtree(__va(dt_ptr));
 
-	/*
-	 * Iterate all ppc_md structures until we find the proper
-	 * one for the current machine type
-	 */
-	DBG("Probing machine type for platform %x...\n", _machine);
+	/* Now we know the logical id of our boot cpu, setup the paca. */
+	setup_boot_paca();
 
-	for (mach = machines; *mach; mach++) {
-		if ((*mach)->probe(_machine))
-			break;
-	}
-	/* What can we do if we didn't find ? */
-	if (*mach == NULL) {
-		DBG("No suitable machine found !\n");
-		for (;;);
-	}
-	ppc_md = **mach;
+	/* Fix up paca fields required for the boot cpu */
+	get_paca()->cpu_start = 1;
+	get_paca()->stab_real = __pa((u64)&initial_stab);
+	get_paca()->stab_addr = (u64)&initial_stab;
+
+	/* Probe the machine type */
+	probe_machine();
 
 #ifdef CONFIG_CRASH_DUMP
 	kdump_setup();
@@ -260,7 +219,7 @@
 		if (cpu_has_feature(CPU_FTR_SLB))
 			slb_initialize();
 		else
-			stab_initialize(lpaca->stab_real);
+			stab_initialize(get_paca()->stab_real);
 	}
 
 	DBG(" <- early_setup()\n");
@@ -340,7 +299,7 @@
 			const char *dc, *ic;
 
 			/* Then read cache informations */
-			if (_machine == PLATFORM_POWERMAC) {
+			if (machine_is(powermac)) {
 				dc = "d-cache-block-size";
 				ic = "i-cache-block-size";
 			} else {
@@ -484,7 +443,6 @@
 	printk("ppc64_pft_size                = 0x%lx\n", ppc64_pft_size);
 	printk("ppc64_interrupt_controller    = 0x%ld\n",
 	       ppc64_interrupt_controller);
-	printk("platform                      = 0x%x\n", _machine);
 	printk("physicalMemorySize            = 0x%lx\n", lmb_phys_mem_size());
 	printk("ppc64_caches.dcache_line_size = 0x%x\n",
 	       ppc64_caches.dline_size);
@@ -516,7 +474,7 @@
 	 * interrupt stacks must be under 256MB, we cannot afford to take
 	 * SLB misses on them.
 	 */
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		softirq_ctx[i] = (struct thread_info *)
 			__va(lmb_alloc_base(THREAD_SIZE,
 					    THREAD_SIZE, 0x10000000));
@@ -549,7 +507,7 @@
 	 */
 	limit = min(0x10000000UL, lmb.rmo_size);
 
-	for_each_cpu(i)
+	for_each_possible_cpu(i)
 		paca[i].emergency_sp =
 		__va(lmb_alloc_base(HW_PAGE_SIZE, 128, limit)) + HW_PAGE_SIZE;
 }
@@ -602,12 +560,6 @@
 
 	ppc_md.setup_arch();
 
-	/* Use the default idle loop if the platform hasn't provided one. */
-	if (NULL == ppc_md.idle_loop) {
-		ppc_md.idle_loop = default_idle;
-		printk(KERN_INFO "Using default idle loop\n");
-	}
-
 	paging_init();
 	ppc64_boot_msg(0x15, "Setup Done");
 }
@@ -672,7 +624,7 @@
 		size = PERCPU_ENOUGH_ROOM;
 #endif
 
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		ptr = alloc_bootmem_node(NODE_DATA(cpu_to_node(i)), size);
 		if (!ptr)
 			panic("Cannot allocate cpu data for CPU %d\n", i);
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index d7a4e81..01e3c08 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -42,6 +42,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
+#include <asm/syscalls.h>
 #include <asm/sigcontext.h>
 #include <asm/vdso.h>
 #ifdef CONFIG_PPC64
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 47f9103..27f65b9 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -33,6 +33,7 @@
 #include <asm/pgtable.h>
 #include <asm/unistd.h>
 #include <asm/cacheflush.h>
+#include <asm/syscalls.h>
 #include <asm/vdso.h>
 
 #define DEBUG_SIG 0
@@ -211,7 +212,7 @@
         /* Default to using normal stack */
         newsp = regs->gpr[1];
 
-	if (ka->sa.sa_flags & SA_ONSTACK) {
+	if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) {
 		if (! on_sig_stack(regs->gpr[1]))
 			newsp = (current->sas_ss_sp + current->sas_ss_size);
 	}
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 805eaed..530f7db 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -362,7 +362,7 @@
  
 	smp_space_timers(max_cpus);
 
-	for_each_cpu(cpu)
+	for_each_possible_cpu(cpu)
 		if (cpu != boot_cpuid)
 			smp_create_idle(cpu);
 }
diff --git a/arch/ppc/kernel/swsusp.S b/arch/powerpc/kernel/swsusp_32.S
similarity index 100%
rename from arch/ppc/kernel/swsusp.S
rename to arch/powerpc/kernel/swsusp_32.S
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c
index ad895c9..9b69d99 100644
--- a/arch/powerpc/kernel/syscalls.c
+++ b/arch/powerpc/kernel/syscalls.c
@@ -40,6 +40,7 @@
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
 #include <asm/semaphore.h>
+#include <asm/syscalls.h>
 #include <asm/time.h>
 #include <asm/unistd.h>
 
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 0f0c3a9..73560ef 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -65,20 +65,20 @@
 	unsigned int cpu;
 
 	if (!cpu_has_feature(CPU_FTR_SMT))
-		return 1;
+		return -ENODEV;
 
 	options = find_path_device("/options");
 	if (!options)
-		return 1;
+		return -ENODEV;
 
 	val = (unsigned int *)get_property(options, "ibm,smt-snooze-delay",
 					   NULL);
 	if (!smt_snooze_cmdline && val) {
-		for_each_cpu(cpu)
+		for_each_possible_cpu(cpu)
 			per_cpu(smt_snooze_delay, cpu) = *val;
 	}
 
-	return 1;
+	return 0;
 }
 __initcall(smt_setup);
 
@@ -93,7 +93,7 @@
 	smt_snooze_cmdline = 1;
 
 	if (get_option(&str, &snooze)) {
-		for_each_cpu(cpu)
+		for_each_possible_cpu(cpu)
 			per_cpu(smt_snooze_delay, cpu) = snooze;
 	}
 
@@ -347,7 +347,7 @@
 
 	register_cpu_notifier(&sysfs_cpu_nb);
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		struct cpu *c = &per_cpu(cpu_devices, cpu);
 
 #ifdef CONFIG_NUMA
diff --git a/arch/ppc/kernel/temp.c b/arch/powerpc/kernel/tau_6xx.c
similarity index 100%
rename from arch/ppc/kernel/temp.c
rename to arch/powerpc/kernel/tau_6xx.c
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 4a27218..24e3ad7 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -261,7 +261,7 @@
 
 	if (!cpu_has_feature(CPU_FTR_PURR))
 		return;
-	for_each_cpu(cpu)
+	for_each_possible_cpu(cpu)
 		spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock);
 	on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1);
 }
@@ -751,7 +751,7 @@
 	 * systems works better if the two threads' timebase interrupts
 	 * are staggered by half a jiffy with respect to each other.
 	 */
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		if (i == boot_cpuid)
 			continue;
 		if (i == (boot_cpuid ^ 1))
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 9763faa..4cbde21 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -97,7 +97,6 @@
 int die(const char *str, struct pt_regs *regs, long err)
 {
 	static int die_counter, crash_dump_start = 0;
-	int nl = 0;
 
 	if (debugger(regs))
 		return 1;
@@ -106,7 +105,7 @@
 	spin_lock_irq(&die_lock);
 	bust_spinlocks(1);
 #ifdef CONFIG_PMAC_BACKLIGHT
-	if (_machine == _MACH_Pmac) {
+	if (machine_is(powermac)) {
 		set_backlight_enable(1);
 		set_backlight_level(BACKLIGHT_MAX);
 	}
@@ -114,46 +113,18 @@
 	printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
 #ifdef CONFIG_PREEMPT
 	printk("PREEMPT ");
-	nl = 1;
 #endif
 #ifdef CONFIG_SMP
 	printk("SMP NR_CPUS=%d ", NR_CPUS);
-	nl = 1;
 #endif
 #ifdef CONFIG_DEBUG_PAGEALLOC
 	printk("DEBUG_PAGEALLOC ");
-	nl = 1;
 #endif
 #ifdef CONFIG_NUMA
 	printk("NUMA ");
-	nl = 1;
 #endif
-#ifdef CONFIG_PPC64
-	switch (_machine) {
-	case PLATFORM_PSERIES:
-		printk("PSERIES ");
-		nl = 1;
-		break;
-	case PLATFORM_PSERIES_LPAR:
-		printk("PSERIES LPAR ");
-		nl = 1;
-		break;
-	case PLATFORM_ISERIES_LPAR:
-		printk("ISERIES LPAR ");
-		nl = 1;
-		break;
-	case PLATFORM_POWERMAC:
-		printk("POWERMAC ");
-		nl = 1;
-		break;
-	case PLATFORM_CELL:
-		printk("CELL ");
-		nl = 1;
-		break;
-	}
-#endif
-	if (nl)
-		printk("\n");
+	printk("%s\n", ppc_md.name ? "" : ppc_md.name);
+
 	print_modules();
 	show_regs(regs);
 	bust_spinlocks(0);
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index ec83703..573afb6 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -33,6 +33,7 @@
 #include <asm/machdep.h>
 #include <asm/cputable.h>
 #include <asm/sections.h>
+#include <asm/firmware.h>
 #include <asm/vdso.h>
 #include <asm/vdso_datapage.h>
 
@@ -667,7 +668,13 @@
 	vdso_data->version.major = SYSTEMCFG_MAJOR;
 	vdso_data->version.minor = SYSTEMCFG_MINOR;
 	vdso_data->processor = mfspr(SPRN_PVR);
-	vdso_data->platform = _machine;
+	/*
+	 * Fake the old platform number for pSeries and iSeries and add
+	 * in LPAR bit if necessary
+	 */
+	vdso_data->platform = machine_is(iseries) ? 0x200 : 0x100;
+	if (firmware_has_feature(FW_FEATURE_LPAR))
+		vdso_data->platform |= 1;
 	vdso_data->physicalMemorySize = lmb_phys_mem_size();
 	vdso_data->dcache_size = ppc64_caches.dsize;
 	vdso_data->dcache_line_size = ppc64_caches.dline_size;
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 7fa7b15..fe79c258 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -1,9 +1,11 @@
 #include <linux/config.h>
 #ifdef CONFIG_PPC64
 #include <asm/page.h>
+#define PROVIDE32(x)	PROVIDE(__unused__##x)
 #else
 #define PAGE_SIZE	4096
 #define KERNELBASE	CONFIG_KERNEL_START
+#define PROVIDE32(x)	PROVIDE(x)
 #endif
 #include <asm-generic/vmlinux.lds.h>
 
@@ -18,43 +20,42 @@
 #endif
 SECTIONS
 {
-  /* Sections to be discarded. */
-  /DISCARD/ : {
-    *(.exitcall.exit)
-    *(.exit.data)
-  }
+	/* Sections to be discarded. */
+	/DISCARD/ : {
+	*(.exitcall.exit)
+	*(.exit.data)
+	}
 
-  . = KERNELBASE;
+	. = KERNELBASE;
 
-  /* Read-only sections, merged into text segment: */
-  .text : {
-    *(.text .text.*)
-    SCHED_TEXT
-    LOCK_TEXT
-    KPROBES_TEXT
-    *(.fixup)
+/*
+ * Text, read only data and other permanent read-only sections
+ */
+
+	/* Text and gots */
+	.text : {
+		*(.text .text.*)
+		SCHED_TEXT
+		LOCK_TEXT
+		KPROBES_TEXT
+		*(.fixup)
+
 #ifdef CONFIG_PPC32
-    *(.got1)
-    __got2_start = .;
-    *(.got2)
-    __got2_end = .;
-#else
-    . = ALIGN(PAGE_SIZE);
-    _etext = .;
-#endif
-  }
-#ifdef CONFIG_PPC32
-  _etext = .;
-  PROVIDE (etext = .);
+		*(.got1)
+		__got2_start = .;
+		*(.got2)
+		__got2_end = .;
+#endif /* CONFIG_PPC32 */
 
-  RODATA
-  .fini      : { *(.fini)    } =0
-  .ctors     : { *(.ctors)   }
-  .dtors     : { *(.dtors)   }
+		. = ALIGN(PAGE_SIZE);
+		_etext = .;
+		PROVIDE32 (etext = .);
+	}
 
-  .fixup   : { *(.fixup) }
-#endif
+	/* Read-only data */
+	RODATA
 
+	/* Exception & bug tables */
 	__ex_table : {
 		__start___ex_table = .;
 		*(__ex_table)
@@ -67,192 +68,172 @@
 		__stop___bug_table = .;
 	}
 
-#ifdef CONFIG_PPC64
+/*
+ * Init sections discarded at runtime
+ */
+	. = ALIGN(PAGE_SIZE);
+	__init_begin = .;
+
+	.init.text : {
+		_sinittext = .;
+		*(.init.text)
+		_einittext = .;
+	}
+
+	/* .exit.text is discarded at runtime, not link time,
+	 * to deal with references from __bug_table
+	 */
+	.exit.text : { *(.exit.text) }
+
+	.init.data : {
+		*(.init.data);
+		__vtop_table_begin = .;
+		*(.vtop_fixup);
+		__vtop_table_end = .;
+		__ptov_table_begin = .;
+		*(.ptov_fixup);
+		__ptov_table_end = .;
+	}
+
+	. = ALIGN(16);
+	.init.setup : {
+		__setup_start = .;
+		*(.init.setup)
+		__setup_end = .;
+	}
+
+	.initcall.init : {
+		__initcall_start = .;
+		*(.initcall1.init)
+		*(.initcall2.init)
+		*(.initcall3.init)
+		*(.initcall4.init)
+		*(.initcall5.init)
+		*(.initcall6.init)
+		*(.initcall7.init)
+		__initcall_end = .;
+		}
+
+	.con_initcall.init : {
+		__con_initcall_start = .;
+		*(.con_initcall.init)
+		__con_initcall_end = .;
+	}
+
+	SECURITY_INIT
+
+	. = ALIGN(8);
 	__ftr_fixup : {
 		__start___ftr_fixup = .;
 		*(__ftr_fixup)
 		__stop___ftr_fixup = .;
 	}
 
-  RODATA
-#endif
+	. = ALIGN(PAGE_SIZE);
+	.init.ramfs : {
+		__initramfs_start = .;
+		*(.init.ramfs)
+		__initramfs_end = .;
+	}
 
 #ifdef CONFIG_PPC32
-  /* Read-write section, merged into data segment: */
-  . = ALIGN(PAGE_SIZE);
-  _sdata = .;
-  .data    :
-  {
-    *(.data)
-    *(.data1)
-    *(.sdata)
-    *(.sdata2)
-    *(.got.plt) *(.got)
-    *(.dynamic)
-    CONSTRUCTORS
-  }
-
-  . = ALIGN(PAGE_SIZE);
-  __nosave_begin = .;
-  .data_nosave : { *(.data.nosave) }
-  . = ALIGN(PAGE_SIZE);
-  __nosave_end = .;
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  _edata  =  .;
-  PROVIDE (edata = .);
-
-  . = ALIGN(8192);
-  .data.init_task : { *(.data.init_task) }
-#endif
-
-  /* will be freed after init */
-  . = ALIGN(PAGE_SIZE);
-  __init_begin = .;
-  .init.text : {
-	_sinittext = .;
-	*(.init.text)
-	_einittext = .;
-  }
-#ifdef CONFIG_PPC32
-  /* .exit.text is discarded at runtime, not link time,
-     to deal with references from __bug_table */
-  .exit.text : { *(.exit.text) }
-#endif
-  .init.data : {
-    *(.init.data);
-    __vtop_table_begin = .;
-    *(.vtop_fixup);
-    __vtop_table_end = .;
-    __ptov_table_begin = .;
-    *(.ptov_fixup);
-    __ptov_table_end = .;
-  }
-
-  . = ALIGN(16);
-  .init.setup : {
-    __setup_start = .;
-    *(.init.setup)
-    __setup_end = .;
-  }
-
-  .initcall.init : {
-	__initcall_start = .;
-	*(.initcall1.init)
-	*(.initcall2.init)
-	*(.initcall3.init)
-	*(.initcall4.init)
-	*(.initcall5.init)
-	*(.initcall6.init)
-	*(.initcall7.init)
-	__initcall_end = .;
-  }
-
-  .con_initcall.init : {
-    __con_initcall_start = .;
-    *(.con_initcall.init)
-    __con_initcall_end = .;
-  }
-
-  SECURITY_INIT
-
-#ifdef CONFIG_PPC32
-  __start___ftr_fixup = .;
-  __ftr_fixup : { *(__ftr_fixup) }
-  __stop___ftr_fixup = .;
+	. = ALIGN(32);
 #else
-  . = ALIGN(PAGE_SIZE);
-  .init.ramfs : {
-    __initramfs_start = .;
-    *(.init.ramfs)
-    __initramfs_end = .;
-  }
+	. = ALIGN(128);
 #endif
+	.data.percpu : {
+		__per_cpu_start = .;
+		*(.data.percpu)
+		__per_cpu_end = .;
+	}
+
+	. = ALIGN(8);
+	.machine.desc : {
+		__machine_desc_start = . ;
+		*(.machine.desc)
+		__machine_desc_end = . ;
+	}
+
+	/* freed after init ends here */
+	. = ALIGN(PAGE_SIZE);
+	__init_end = .;
+
+/*
+ * And now the various read/write data
+ */
+
+	. = ALIGN(PAGE_SIZE);
+	_sdata = .;
 
 #ifdef CONFIG_PPC32
-  . = ALIGN(32);
-#endif
-  .data.percpu : {
-    __per_cpu_start = .;
-    *(.data.percpu)
-    __per_cpu_end = .;
-  }
-
- . = ALIGN(PAGE_SIZE);
-#ifdef CONFIG_PPC64
- . = ALIGN(16384);
- __init_end = .;
- /* freed after init ends here */
-
- /* Read/write sections */
- . = ALIGN(PAGE_SIZE);
- . = ALIGN(16384);
- _sdata = .;
- /* The initial task and kernel stack */
- .data.init_task : {
-      *(.data.init_task)
-      }
-
- . = ALIGN(PAGE_SIZE);
- .data.page_aligned : {
-      *(.data.page_aligned)
-      }
-
- .data.cacheline_aligned : {
-      *(.data.cacheline_aligned)
-      }
-
- .data : {
-      *(.data .data.rel* .toc1)
-      *(.branch_lt)
-      }
-
- .opd : {
-      *(.opd)
-      }
-
- .got : {
-      __toc_start = .;
-      *(.got)
-      *(.toc)
-      . = ALIGN(PAGE_SIZE);
-      _edata = .;
-      }
-
-  . = ALIGN(PAGE_SIZE);
+	.data    :
+	{
+		*(.data)
+		*(.sdata)
+		*(.got.plt) *(.got)
+	}
 #else
-  __initramfs_start = .;
-  .init.ramfs : {
-    *(.init.ramfs)
-  }
-  __initramfs_end = .;
+	.data : {
+		*(.data .data.rel* .toc1)
+		*(.branch_lt)
+	}
 
-  . = ALIGN(4096);
-  __init_end = .;
+	.opd : {
+		*(.opd)
+	}
 
-  . = ALIGN(4096);
-  _sextratext = .;
-  _eextratext = .;
-
-  __bss_start = .;
+	.got : {
+		__toc_start = .;
+		*(.got)
+		*(.toc)
+	}
 #endif
 
-  .bss : {
-    __bss_start = .;
-   *(.sbss) *(.scommon)
-   *(.dynbss)
-   *(.bss)
-   *(COMMON)
-  __bss_stop = .;
-  }
+	. = ALIGN(PAGE_SIZE);
+	_edata  =  .;
+	PROVIDE32 (edata = .);
 
-#ifdef CONFIG_PPC64
-  . = ALIGN(PAGE_SIZE);
-#endif
-  _end = . ;
+	/* The initial task and kernel stack */
 #ifdef CONFIG_PPC32
-  PROVIDE (end = .);
+	. = ALIGN(8192);
+#else
+	. = ALIGN(16384);
 #endif
+	.data.init_task : {
+		*(.data.init_task)
+	}
+
+	. = ALIGN(PAGE_SIZE);
+	.data.page_aligned : {
+		*(.data.page_aligned)
+	}
+
+	.data.cacheline_aligned : {
+		*(.data.cacheline_aligned)
+	}
+
+	. = ALIGN(PAGE_SIZE);
+	__data_nosave : {
+		__nosave_begin = .;
+		*(.data.nosave)
+		. = ALIGN(PAGE_SIZE);
+		__nosave_end = .;
+	}
+
+/*
+ * And finally the bss
+ */
+
+	.bss : {
+		__bss_start = .;
+		*(.sbss) *(.scommon)
+		*(.dynbss)
+		*(.bss)
+		*(COMMON)
+		__bss_stop = .;
+	}
+
+	. = ALIGN(PAGE_SIZE);
+	_end = . ;
+	PROVIDE32 (end = .);
 }
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 666c2aa..c251d99 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -18,7 +18,7 @@
 
 #ifdef CONFIG_PPC64
 /* Bits in SRR1 that are copied from MSR */
-#define MSR_MASK	0xffffffff87c0ffff
+#define MSR_MASK	0xffffffff87c0ffffUL
 #else
 #define MSR_MASK	0x87c0ffff
 #endif
diff --git a/arch/ppc/math-emu/Makefile b/arch/powerpc/math-emu/Makefile
similarity index 100%
rename from arch/ppc/math-emu/Makefile
rename to arch/powerpc/math-emu/Makefile
diff --git a/arch/ppc/math-emu/double.h b/arch/powerpc/math-emu/double.h
similarity index 100%
rename from arch/ppc/math-emu/double.h
rename to arch/powerpc/math-emu/double.h
diff --git a/arch/ppc/math-emu/fabs.c b/arch/powerpc/math-emu/fabs.c
similarity index 100%
rename from arch/ppc/math-emu/fabs.c
rename to arch/powerpc/math-emu/fabs.c
diff --git a/arch/ppc/math-emu/fadd.c b/arch/powerpc/math-emu/fadd.c
similarity index 100%
rename from arch/ppc/math-emu/fadd.c
rename to arch/powerpc/math-emu/fadd.c
diff --git a/arch/ppc/math-emu/fadds.c b/arch/powerpc/math-emu/fadds.c
similarity index 100%
rename from arch/ppc/math-emu/fadds.c
rename to arch/powerpc/math-emu/fadds.c
diff --git a/arch/ppc/math-emu/fcmpo.c b/arch/powerpc/math-emu/fcmpo.c
similarity index 100%
rename from arch/ppc/math-emu/fcmpo.c
rename to arch/powerpc/math-emu/fcmpo.c
diff --git a/arch/ppc/math-emu/fcmpu.c b/arch/powerpc/math-emu/fcmpu.c
similarity index 100%
rename from arch/ppc/math-emu/fcmpu.c
rename to arch/powerpc/math-emu/fcmpu.c
diff --git a/arch/ppc/math-emu/fctiw.c b/arch/powerpc/math-emu/fctiw.c
similarity index 100%
rename from arch/ppc/math-emu/fctiw.c
rename to arch/powerpc/math-emu/fctiw.c
diff --git a/arch/ppc/math-emu/fctiwz.c b/arch/powerpc/math-emu/fctiwz.c
similarity index 100%
rename from arch/ppc/math-emu/fctiwz.c
rename to arch/powerpc/math-emu/fctiwz.c
diff --git a/arch/ppc/math-emu/fdiv.c b/arch/powerpc/math-emu/fdiv.c
similarity index 100%
rename from arch/ppc/math-emu/fdiv.c
rename to arch/powerpc/math-emu/fdiv.c
diff --git a/arch/ppc/math-emu/fdivs.c b/arch/powerpc/math-emu/fdivs.c
similarity index 100%
rename from arch/ppc/math-emu/fdivs.c
rename to arch/powerpc/math-emu/fdivs.c
diff --git a/arch/ppc/math-emu/fmadd.c b/arch/powerpc/math-emu/fmadd.c
similarity index 100%
rename from arch/ppc/math-emu/fmadd.c
rename to arch/powerpc/math-emu/fmadd.c
diff --git a/arch/ppc/math-emu/fmadds.c b/arch/powerpc/math-emu/fmadds.c
similarity index 100%
rename from arch/ppc/math-emu/fmadds.c
rename to arch/powerpc/math-emu/fmadds.c
diff --git a/arch/ppc/math-emu/fmr.c b/arch/powerpc/math-emu/fmr.c
similarity index 100%
rename from arch/ppc/math-emu/fmr.c
rename to arch/powerpc/math-emu/fmr.c
diff --git a/arch/ppc/math-emu/fmsub.c b/arch/powerpc/math-emu/fmsub.c
similarity index 100%
rename from arch/ppc/math-emu/fmsub.c
rename to arch/powerpc/math-emu/fmsub.c
diff --git a/arch/ppc/math-emu/fmsubs.c b/arch/powerpc/math-emu/fmsubs.c
similarity index 100%
rename from arch/ppc/math-emu/fmsubs.c
rename to arch/powerpc/math-emu/fmsubs.c
diff --git a/arch/ppc/math-emu/fmul.c b/arch/powerpc/math-emu/fmul.c
similarity index 100%
rename from arch/ppc/math-emu/fmul.c
rename to arch/powerpc/math-emu/fmul.c
diff --git a/arch/ppc/math-emu/fmuls.c b/arch/powerpc/math-emu/fmuls.c
similarity index 100%
rename from arch/ppc/math-emu/fmuls.c
rename to arch/powerpc/math-emu/fmuls.c
diff --git a/arch/ppc/math-emu/fnabs.c b/arch/powerpc/math-emu/fnabs.c
similarity index 100%
rename from arch/ppc/math-emu/fnabs.c
rename to arch/powerpc/math-emu/fnabs.c
diff --git a/arch/ppc/math-emu/fneg.c b/arch/powerpc/math-emu/fneg.c
similarity index 100%
rename from arch/ppc/math-emu/fneg.c
rename to arch/powerpc/math-emu/fneg.c
diff --git a/arch/ppc/math-emu/fnmadd.c b/arch/powerpc/math-emu/fnmadd.c
similarity index 100%
rename from arch/ppc/math-emu/fnmadd.c
rename to arch/powerpc/math-emu/fnmadd.c
diff --git a/arch/ppc/math-emu/fnmadds.c b/arch/powerpc/math-emu/fnmadds.c
similarity index 100%
rename from arch/ppc/math-emu/fnmadds.c
rename to arch/powerpc/math-emu/fnmadds.c
diff --git a/arch/ppc/math-emu/fnmsub.c b/arch/powerpc/math-emu/fnmsub.c
similarity index 100%
rename from arch/ppc/math-emu/fnmsub.c
rename to arch/powerpc/math-emu/fnmsub.c
diff --git a/arch/ppc/math-emu/fnmsubs.c b/arch/powerpc/math-emu/fnmsubs.c
similarity index 100%
rename from arch/ppc/math-emu/fnmsubs.c
rename to arch/powerpc/math-emu/fnmsubs.c
diff --git a/arch/ppc/math-emu/fres.c b/arch/powerpc/math-emu/fres.c
similarity index 100%
rename from arch/ppc/math-emu/fres.c
rename to arch/powerpc/math-emu/fres.c
diff --git a/arch/ppc/math-emu/frsp.c b/arch/powerpc/math-emu/frsp.c
similarity index 100%
rename from arch/ppc/math-emu/frsp.c
rename to arch/powerpc/math-emu/frsp.c
diff --git a/arch/ppc/math-emu/frsqrte.c b/arch/powerpc/math-emu/frsqrte.c
similarity index 100%
rename from arch/ppc/math-emu/frsqrte.c
rename to arch/powerpc/math-emu/frsqrte.c
diff --git a/arch/ppc/math-emu/fsel.c b/arch/powerpc/math-emu/fsel.c
similarity index 100%
rename from arch/ppc/math-emu/fsel.c
rename to arch/powerpc/math-emu/fsel.c
diff --git a/arch/ppc/math-emu/fsqrt.c b/arch/powerpc/math-emu/fsqrt.c
similarity index 100%
rename from arch/ppc/math-emu/fsqrt.c
rename to arch/powerpc/math-emu/fsqrt.c
diff --git a/arch/ppc/math-emu/fsqrts.c b/arch/powerpc/math-emu/fsqrts.c
similarity index 100%
rename from arch/ppc/math-emu/fsqrts.c
rename to arch/powerpc/math-emu/fsqrts.c
diff --git a/arch/ppc/math-emu/fsub.c b/arch/powerpc/math-emu/fsub.c
similarity index 100%
rename from arch/ppc/math-emu/fsub.c
rename to arch/powerpc/math-emu/fsub.c
diff --git a/arch/ppc/math-emu/fsubs.c b/arch/powerpc/math-emu/fsubs.c
similarity index 100%
rename from arch/ppc/math-emu/fsubs.c
rename to arch/powerpc/math-emu/fsubs.c
diff --git a/arch/ppc/math-emu/lfd.c b/arch/powerpc/math-emu/lfd.c
similarity index 100%
rename from arch/ppc/math-emu/lfd.c
rename to arch/powerpc/math-emu/lfd.c
diff --git a/arch/ppc/math-emu/lfs.c b/arch/powerpc/math-emu/lfs.c
similarity index 100%
rename from arch/ppc/math-emu/lfs.c
rename to arch/powerpc/math-emu/lfs.c
diff --git a/arch/ppc/math-emu/math.c b/arch/powerpc/math-emu/math.c
similarity index 100%
rename from arch/ppc/math-emu/math.c
rename to arch/powerpc/math-emu/math.c
diff --git a/arch/ppc/math-emu/mcrfs.c b/arch/powerpc/math-emu/mcrfs.c
similarity index 100%
rename from arch/ppc/math-emu/mcrfs.c
rename to arch/powerpc/math-emu/mcrfs.c
diff --git a/arch/ppc/math-emu/mffs.c b/arch/powerpc/math-emu/mffs.c
similarity index 100%
rename from arch/ppc/math-emu/mffs.c
rename to arch/powerpc/math-emu/mffs.c
diff --git a/arch/ppc/math-emu/mtfsb0.c b/arch/powerpc/math-emu/mtfsb0.c
similarity index 100%
rename from arch/ppc/math-emu/mtfsb0.c
rename to arch/powerpc/math-emu/mtfsb0.c
diff --git a/arch/ppc/math-emu/mtfsb1.c b/arch/powerpc/math-emu/mtfsb1.c
similarity index 100%
rename from arch/ppc/math-emu/mtfsb1.c
rename to arch/powerpc/math-emu/mtfsb1.c
diff --git a/arch/ppc/math-emu/mtfsf.c b/arch/powerpc/math-emu/mtfsf.c
similarity index 100%
rename from arch/ppc/math-emu/mtfsf.c
rename to arch/powerpc/math-emu/mtfsf.c
diff --git a/arch/ppc/math-emu/mtfsfi.c b/arch/powerpc/math-emu/mtfsfi.c
similarity index 100%
rename from arch/ppc/math-emu/mtfsfi.c
rename to arch/powerpc/math-emu/mtfsfi.c
diff --git a/arch/ppc/math-emu/op-1.h b/arch/powerpc/math-emu/op-1.h
similarity index 100%
rename from arch/ppc/math-emu/op-1.h
rename to arch/powerpc/math-emu/op-1.h
diff --git a/arch/ppc/math-emu/op-2.h b/arch/powerpc/math-emu/op-2.h
similarity index 100%
rename from arch/ppc/math-emu/op-2.h
rename to arch/powerpc/math-emu/op-2.h
diff --git a/arch/ppc/math-emu/op-4.h b/arch/powerpc/math-emu/op-4.h
similarity index 100%
rename from arch/ppc/math-emu/op-4.h
rename to arch/powerpc/math-emu/op-4.h
diff --git a/arch/ppc/math-emu/op-common.h b/arch/powerpc/math-emu/op-common.h
similarity index 100%
rename from arch/ppc/math-emu/op-common.h
rename to arch/powerpc/math-emu/op-common.h
diff --git a/arch/ppc/math-emu/sfp-machine.h b/arch/powerpc/math-emu/sfp-machine.h
similarity index 100%
rename from arch/ppc/math-emu/sfp-machine.h
rename to arch/powerpc/math-emu/sfp-machine.h
diff --git a/arch/ppc/math-emu/single.h b/arch/powerpc/math-emu/single.h
similarity index 100%
rename from arch/ppc/math-emu/single.h
rename to arch/powerpc/math-emu/single.h
diff --git a/arch/ppc/math-emu/soft-fp.h b/arch/powerpc/math-emu/soft-fp.h
similarity index 100%
rename from arch/ppc/math-emu/soft-fp.h
rename to arch/powerpc/math-emu/soft-fp.h
diff --git a/arch/ppc/math-emu/stfd.c b/arch/powerpc/math-emu/stfd.c
similarity index 100%
rename from arch/ppc/math-emu/stfd.c
rename to arch/powerpc/math-emu/stfd.c
diff --git a/arch/ppc/math-emu/stfiwx.c b/arch/powerpc/math-emu/stfiwx.c
similarity index 100%
rename from arch/ppc/math-emu/stfiwx.c
rename to arch/powerpc/math-emu/stfiwx.c
diff --git a/arch/ppc/math-emu/stfs.c b/arch/powerpc/math-emu/stfs.c
similarity index 100%
rename from arch/ppc/math-emu/stfs.c
rename to arch/powerpc/math-emu/stfs.c
diff --git a/arch/ppc/math-emu/types.c b/arch/powerpc/math-emu/types.c
similarity index 100%
rename from arch/ppc/math-emu/types.c
rename to arch/powerpc/math-emu/types.c
diff --git a/arch/ppc/math-emu/udivmodti4.c b/arch/powerpc/math-emu/udivmodti4.c
similarity index 100%
rename from arch/ppc/math-emu/udivmodti4.c
rename to arch/powerpc/math-emu/udivmodti4.c
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index ec4adcb..5aea090 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -267,25 +267,29 @@
 #endif
 #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
 		pte_t *ptep;
+		pmd_t *pmdp;
 
 		/* Since 4xx/Book-E supports per-page execute permission,
 		 * we lazily flush dcache to icache. */
 		ptep = NULL;
-		if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) {
-			struct page *page = pte_page(*ptep);
+		if (get_pteptr(mm, address, &ptep, &pmdp)) {
+			spinlock_t *ptl = pte_lockptr(mm, pmdp);
+			spin_lock(ptl);
+			if (pte_present(*ptep)) {
+				struct page *page = pte_page(*ptep);
 
-			if (! test_bit(PG_arch_1, &page->flags)) {
-				flush_dcache_icache_page(page);
-				set_bit(PG_arch_1, &page->flags);
+				if (!test_bit(PG_arch_1, &page->flags)) {
+					flush_dcache_icache_page(page);
+					set_bit(PG_arch_1, &page->flags);
+				}
+				pte_update(ptep, 0, _PAGE_HWEXEC);
+				_tlbie(address);
+				pte_unmap_unlock(ptep, ptl);
+				up_read(&mm->mmap_sem);
+				return 0;
 			}
-			pte_update(ptep, 0, _PAGE_HWEXEC);
-			_tlbie(address);
-			pte_unmap(ptep);
-			up_read(&mm->mmap_sem);
-			return 0;
+			pte_unmap_unlock(ptep, ptl);
 		}
-		if (ptep != NULL)
-			pte_unmap(ptep);
 #endif
 	/* a write */
 	} else if (is_write) {
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 89b35c1..c006d90 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -167,7 +167,7 @@
 		 * normal insert callback here.
 		 */
 #ifdef CONFIG_PPC_ISERIES
-		if (_machine == PLATFORM_ISERIES_LPAR)
+		if (machine_is(iseries))
 			ret = iSeries_hpte_insert(hpteg, va,
 						  paddr,
 						  tmp_mode,
@@ -176,7 +176,7 @@
 		else
 #endif
 #ifdef CONFIG_PPC_PSERIES
-		if (_machine & PLATFORM_LPAR)
+		if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR))
 			ret = pSeries_lpar_hpte_insert(hpteg, va,
 						       paddr,
 						       tmp_mode,
@@ -295,8 +295,7 @@
 	 * Not in the device-tree, let's fallback on known size
 	 * list for 16M capable GP & GR
 	 */
-	if ((_machine != PLATFORM_ISERIES_LPAR) &&
-	    cpu_has_feature(CPU_FTR_16M_PAGE))
+	if (cpu_has_feature(CPU_FTR_16M_PAGE) && !machine_is(iseries))
 		memcpy(mmu_psize_defs, mmu_psize_defaults_gp,
 		       sizeof(mmu_psize_defaults_gp));
  found:
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 5e435a9..741dd88 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -342,7 +342,7 @@
 #ifdef CONFIG_NEED_MULTIPLE_NODES
         for_each_online_node(nid) {
 		if (NODE_DATA(nid)->node_spanned_pages != 0) {
-			printk("freeing bootmem node %x\n", nid);
+			printk("freeing bootmem node %d\n", nid);
 			totalram_pages +=
 				free_all_bootmem_node(NODE_DATA(nid));
 		}
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index e89b22a..0a335f3 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -756,6 +756,7 @@
 	struct device_node *memory = NULL;
 	nodemask_t nodes;
 	int default_nid = any_online_node(NODE_MASK_ALL);
+	int nid;
 
 	if (!numa_enabled || (min_common_depth < 0))
 		return default_nid;
@@ -790,6 +791,7 @@
 			goto ha_new_range;
 	}
 	BUG();	/* section address should be found above */
+	return 0;
 
 	/* Temporary code to ensure that returned node is not empty */
 got_nid:
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index d296eb6..9062860 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -372,7 +372,7 @@
  * the PTE pointer is unmodified if PTE is not found.
  */
 int
-get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
+get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp)
 {
         pgd_t	*pgd;
         pmd_t	*pmd;
@@ -387,6 +387,8 @@
                         if (pte) {
 				retval = 1;
 				*ptep = pte;
+				if (pmdp)
+					*pmdp = pmd;
 				/* XXX caller needs to do pte_unmap, yuck */
                         }
                 }
@@ -424,7 +426,7 @@
 		mm = &init_mm;
 
 	pa = 0;
-	if (get_pteptr(mm, addr, &pte)) {
+	if (get_pteptr(mm, addr, &pte, NULL)) {
 		pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
 		pte_unmap(pte);
 	}
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
index 91d25fb..4a9291d9 100644
--- a/arch/powerpc/mm/stab.c
+++ b/arch/powerpc/mm/stab.c
@@ -239,7 +239,7 @@
 	if (cpu_has_feature(CPU_FTR_SLB))
 		return;
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		unsigned long newstab;
 
 		if (cpu == 0)
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile
index 554cd7c..f5f9859 100644
--- a/arch/powerpc/oprofile/Makefile
+++ b/arch/powerpc/oprofile/Makefile
@@ -6,7 +6,7 @@
 		oprofilefs.o oprofile_stats.o \
 		timer_int.o )
 
-oprofile-y := $(DRIVER_OBJS) common.o
+oprofile-y := $(DRIVER_OBJS) common.o backtrace.o
 oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o
 oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o
 oprofile-$(CONFIG_PPC32) += op_model_7450.o
diff --git a/arch/powerpc/oprofile/backtrace.c b/arch/powerpc/oprofile/backtrace.c
new file mode 100644
index 0000000..75f57bc
--- /dev/null
+++ b/arch/powerpc/oprofile/backtrace.c
@@ -0,0 +1,126 @@
+/**
+ * Copyright (C) 2005 Brian Rogan <bcr6@cornell.edu>, IBM
+ *
+ * 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.
+**/
+
+#include <linux/oprofile.h>
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+#define STACK_SP(STACK)		*(STACK)
+
+#define STACK_LR64(STACK)	*((unsigned long *)(STACK) + 2)
+#define STACK_LR32(STACK)	*((unsigned int *)(STACK) + 1)
+
+#ifdef CONFIG_PPC64
+#define STACK_LR(STACK)		STACK_LR64(STACK)
+#else
+#define STACK_LR(STACK)		STACK_LR32(STACK)
+#endif
+
+static unsigned int user_getsp32(unsigned int sp, int is_first)
+{
+	unsigned int stack_frame[2];
+
+	if (!access_ok(VERIFY_READ, sp, sizeof(stack_frame)))
+		return 0;
+
+	/*
+	 * The most likely reason for this is that we returned -EFAULT,
+	 * which means that we've done all that we can do from
+	 * interrupt context.
+	 */
+	if (__copy_from_user_inatomic(stack_frame, (void *)(long)sp,
+					sizeof(stack_frame)))
+		return 0;
+
+	if (!is_first)
+		oprofile_add_trace(STACK_LR32(stack_frame));
+
+	/*
+	 * We do not enforce increasing stack addresses here because
+	 * we may transition to a different stack, eg a signal handler.
+	 */
+	return STACK_SP(stack_frame);
+}
+
+#ifdef CONFIG_PPC64
+static unsigned long user_getsp64(unsigned long sp, int is_first)
+{
+	unsigned long stack_frame[3];
+
+	if (!access_ok(VERIFY_READ, sp, sizeof(stack_frame)))
+		return 0;
+
+	if (__copy_from_user_inatomic(stack_frame, (void *)sp,
+					sizeof(stack_frame)))
+		return 0;
+
+	if (!is_first)
+		oprofile_add_trace(STACK_LR64(stack_frame));
+
+	return STACK_SP(stack_frame);
+}
+#endif
+
+static unsigned long kernel_getsp(unsigned long sp, int is_first)
+{
+	unsigned long *stack_frame = (unsigned long *)sp;
+
+	if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
+		return 0;
+
+	if (!is_first)
+		oprofile_add_trace(STACK_LR(stack_frame));
+
+	/*
+	 * We do not enforce increasing stack addresses here because
+	 * we might be transitioning from an interrupt stack to a kernel
+	 * stack. validate_sp() is designed to understand this, so just
+	 * use it.
+	 */
+	return STACK_SP(stack_frame);
+}
+
+void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth)
+{
+	unsigned long sp = regs->gpr[1];
+	int first_frame = 1;
+
+	/* We ditch the top stackframe so need to loop through an extra time */
+	depth += 1;
+
+	if (!user_mode(regs)) {
+		while (depth--) {
+			sp = kernel_getsp(sp, first_frame);
+			if (!sp)
+				break;
+			first_frame = 0;
+		}
+	} else {
+#ifdef CONFIG_PPC64
+		if (!test_thread_flag(TIF_32BIT)) {
+			while (depth--) {
+				sp = user_getsp64(sp, first_frame);
+				if (!sp)
+					break;
+				first_frame = 0;
+			}
+
+			return;
+		}
+#endif
+
+		while (depth--) {
+			sp = user_getsp32(sp, first_frame);
+			if (!sp)
+				break;
+			first_frame = 0;
+		}
+	}
+}
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c
index cc2535b..5b1de7e 100644
--- a/arch/powerpc/oprofile/common.c
+++ b/arch/powerpc/oprofile/common.c
@@ -117,18 +117,10 @@
 
 	oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
 	oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
-#ifdef CONFIG_PPC64
-	oprofilefs_create_ulong(sb, root, "backtrace_spinlocks",
-				&sys.backtrace_spinlocks);
-#endif
 
 	/* Default to tracing both kernel and user */
 	sys.enable_kernel = 1;
 	sys.enable_user = 1;
-#ifdef CONFIG_PPC64
-	/* Turn on backtracing through spinlocks by default */
-	sys.backtrace_spinlocks = 1;
-#endif
 
 	return 0;
 }
@@ -168,6 +160,7 @@
 	ops->shutdown = op_powerpc_shutdown;
 	ops->start = op_powerpc_start;
 	ops->stop = op_powerpc_stop;
+	ops->backtrace = op_powerpc_backtrace;
 
 	printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
 	       ops->cpu_type);
diff --git a/arch/powerpc/oprofile/op_model_7450.c b/arch/powerpc/oprofile/op_model_7450.c
index 32abfdb..e0491c3 100644
--- a/arch/powerpc/oprofile/op_model_7450.c
+++ b/arch/powerpc/oprofile/op_model_7450.c
@@ -176,13 +176,13 @@
 	mtmsr(mfmsr() | MSR_PMM);
 
 	pc = mfspr(SPRN_SIAR);
-	is_kernel = (pc >= KERNELBASE);
+	is_kernel = is_kernel_addr(pc);
 
 	for (i = 0; i < NUM_CTRS; ++i) {
 		val = ctr_read(i);
 		if (val < 0) {
 			if (oprofile_running && ctr[i].enabled) {
-				oprofile_add_pc(pc, is_kernel, i);
+				oprofile_add_ext_sample(pc, regs, i, is_kernel);
 				ctr_write(i, reset_value[i]);
 			} else {
 				ctr_write(i, 0);
diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_booke.c
index 26539cd..93d63e6 100644
--- a/arch/powerpc/oprofile/op_model_fsl_booke.c
+++ b/arch/powerpc/oprofile/op_model_fsl_booke.c
@@ -154,13 +154,13 @@
 	mtmsr(mfmsr() | MSR_PMM);
 
 	pc = regs->nip;
-	is_kernel = (pc >= KERNELBASE);
+	is_kernel = is_kernel_addr(pc);
 
 	for (i = 0; i < num_counters; ++i) {
 		val = ctr_read(i);
 		if (val < 0) {
 			if (oprofile_running && ctr[i].enabled) {
-				oprofile_add_pc(pc, is_kernel, i);
+				oprofile_add_ext_sample(pc, regs, i, is_kernel);
 				ctr_write(i, reset_value[i]);
 			} else {
 				ctr_write(i, 0);
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
index 4b06e53..4c2beab1 100644
--- a/arch/powerpc/oprofile/op_model_power4.c
+++ b/arch/powerpc/oprofile/op_model_power4.c
@@ -25,18 +25,14 @@
 
 static int oprofile_running;
 static int mmcra_has_sihv;
+/* Unfortunately these bits vary between CPUs */
+static unsigned long mmcra_sihv = MMCRA_SIHV;
+static unsigned long mmcra_sipr = MMCRA_SIPR;
 
 /* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */
 static u32 mmcr0_val;
 static u64 mmcr1_val;
-static u32 mmcra_val;
-
-/*
- * Since we do not have an NMI, backtracing through spinlocks is
- * only a best guess. In light of this, allow it to be disabled at
- * runtime.
- */
-static int backtrace_spinlocks;
+static u64 mmcra_val;
 
 static void power4_reg_setup(struct op_counter_config *ctr,
 			     struct op_system_config *sys,
@@ -63,8 +59,6 @@
 	mmcr1_val = sys->mmcr1;
 	mmcra_val = sys->mmcra;
 
-	backtrace_spinlocks = sys->backtrace_spinlocks;
-
 	for (i = 0; i < cur_cpu_spec->num_pmcs; ++i)
 		reset_value[i] = 0x80000000UL - ctr[i].count;
 
@@ -197,25 +191,6 @@
 {
 }
 
-static unsigned long check_spinlock_pc(struct pt_regs *regs,
-				       unsigned long profile_pc)
-{
-	unsigned long pc = instruction_pointer(regs);
-
-	/*
-	 * If both the SIAR (sampled instruction) and the perfmon exception
-	 * occurred in a spinlock region then we account the sample to the
-	 * calling function. This isnt 100% correct, we really need soft
-	 * IRQ disable so we always get the perfmon exception at the
-	 * point at which the SIAR is set.
-	 */
-	if (backtrace_spinlocks && in_lock_functions(pc) &&
-			in_lock_functions(profile_pc))
-		return regs->link;
-	else
-		return profile_pc;
-}
-
 /*
  * On GQ and newer the MMCRA stores the HV and PR bits at the time
  * the SIAR was sampled. We use that to work out if the SIAR was sampled in
@@ -228,17 +203,17 @@
 
 	/* Cant do much about it */
 	if (!mmcra_has_sihv)
-		return check_spinlock_pc(regs, pc);
+		return pc;
 
 	mmcra = mfspr(SPRN_MMCRA);
 
 	/* Were we in the hypervisor? */
-	if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & MMCRA_SIHV))
+	if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & mmcra_sihv))
 		/* function descriptor madness */
 		return *((unsigned long *)hypervisor_bucket);
 
 	/* We were in userspace, nothing to do */
-	if (mmcra & MMCRA_SIPR)
+	if (mmcra & mmcra_sipr)
 		return pc;
 
 #ifdef CONFIG_PPC_RTAS
@@ -257,7 +232,7 @@
 		/* function descriptor madness */
 		return *((unsigned long *)kernel_unknown_bucket);
 
-	return check_spinlock_pc(regs, pc);
+	return pc;
 }
 
 static int get_kernel(unsigned long pc)
@@ -268,7 +243,7 @@
 		is_kernel = is_kernel_addr(pc);
 	} else {
 		unsigned long mmcra = mfspr(SPRN_MMCRA);
-		is_kernel = ((mmcra & MMCRA_SIPR) == 0);
+		is_kernel = ((mmcra & mmcra_sipr) == 0);
 	}
 
 	return is_kernel;
@@ -293,7 +268,7 @@
 		val = ctr_read(i);
 		if (val < 0) {
 			if (oprofile_running && ctr[i].enabled) {
-				oprofile_add_pc(pc, is_kernel, i);
+				oprofile_add_ext_sample(pc, regs, i, is_kernel);
 				ctr_write(i, reset_value[i]);
 			} else {
 				ctr_write(i, 0);
diff --git a/arch/powerpc/oprofile/op_model_rs64.c b/arch/powerpc/oprofile/op_model_rs64.c
index 5c909ee..042f8f4 100644
--- a/arch/powerpc/oprofile/op_model_rs64.c
+++ b/arch/powerpc/oprofile/op_model_rs64.c
@@ -175,10 +175,13 @@
 				  struct op_counter_config *ctr)
 {
 	unsigned int mmcr0;
+	int is_kernel;
 	int val;
 	int i;
 	unsigned long pc = mfspr(SPRN_SIAR);
 
+	is_kernel = is_kernel_addr(pc);
+
 	/* set the PMM bit (see comment below) */
 	mtmsrd(mfmsr() | MSR_PMM);
 
@@ -186,7 +189,7 @@
 		val = ctr_read(i);
 		if (val < 0) {
 			if (ctr[i].enabled) {
-				oprofile_add_pc(pc, is_kernel_addr(pc), i);
+				oprofile_add_ext_sample(pc, regs, i, is_kernel);
 				ctr_write(i, reset_value[i]);
 			} else {
 				ctr_write(i, 0);
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index d3d0ff7..06e3712 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -7,6 +7,7 @@
 
 config MPC8540_ADS
 	bool "Freescale MPC8540 ADS"
+	select DEFAULT_UIMAGE
 	help
 	  This option enables support for the MPC 8540 ADS board
 
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 3157071..c2a3db8 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -10,4 +10,9 @@
 	  Units on machines implementing the Broadband Processor
 	  Architecture.
 
+config SPUFS_MMAP
+	bool
+	depends on SPU_FS && SPARSEMEM && !PPC_64K_PAGES
+	default y
+
 endmenu
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index 3b998a3..e570bad 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -6,5 +6,11 @@
 
 spu-base-y		+= spu_base.o spu_priv1.o
 
-builtin-spufs-$(CONFIG_SPU_FS)	+= spu_syscalls.o
-obj-y			+= $(builtin-spufs-m)
+# needed only when building loadable spufs.ko
+spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o
+obj-y			+= $(spufs-modular-m)
+
+# always needed in kernel
+spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o
+obj-y			+= $(spufs-builtin-y) $(spufs-builtin-m)
+
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 63aa52a..978be1c 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -63,7 +63,24 @@
 
 void iic_local_enable(void)
 {
-	out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
+	struct iic *iic = &__get_cpu_var(iic);
+	u64 tmp;
+
+	/*
+	 * There seems to be a bug that is present in DD2.x CPUs
+	 * and still only partially fixed in DD3.1.
+	 * This bug causes a value written to the priority register
+	 * not to make it there, resulting in a system hang unless we
+	 * write it again.
+	 * Masking with 0xf0 is done because the Cell BE does not
+	 * implement the lower four bits of the interrupt priority,
+	 * they always read back as zeroes, although future CPUs
+	 * might implement different bits.
+	 */
+	do {
+		out_be64(&iic->regs->prio, 0xff);
+		tmp = in_be64(&iic->regs->prio);
+	} while ((tmp & 0xf0) != 0xf0);
 }
 
 void iic_local_disable(void)
@@ -123,7 +140,7 @@
 		    pending.class != 2)
 			break;
 		irq = IIC_EXT_OFFSET
-			+ spider_get_irq(pending.prio + node * IIC_NODE_STRIDE)
+			+ spider_get_irq(node)
 			+ node * IIC_NODE_STRIDE;
 		break;
 	case 0x01 ... 0x04:
@@ -174,40 +191,100 @@
 	return irq;
 }
 
-static int setup_iic(int cpu, struct iic *iic)
+/* hardcoded part to be compatible with older firmware */
+
+static int setup_iic_hardcoded(void)
 {
 	struct device_node *np;
-	int nodeid = cpu / 2;
+	int nodeid, cpu;
 	unsigned long regs;
+	struct iic *iic;
 
-	for (np = of_find_node_by_type(NULL, "cpu");
-	     np;
-	     np = of_find_node_by_type(np, "cpu")) {
-		if (nodeid == *(int *)get_property(np, "node-id", NULL))
-			break;
+	for_each_cpu(cpu) {
+		iic = &per_cpu(iic, cpu);
+		nodeid = cpu/2;
+
+		for (np = of_find_node_by_type(NULL, "cpu");
+		     np;
+		     np = of_find_node_by_type(np, "cpu")) {
+			if (nodeid == *(int *)get_property(np, "node-id", NULL))
+				break;
+			}
+
+		if (!np) {
+			printk(KERN_WARNING "IIC: CPU %d not found\n", cpu);
+			iic->regs = NULL;
+			iic->target_id = 0xff;
+			return -ENODEV;
+			}
+
+		regs = *(long *)get_property(np, "iic", NULL);
+
+		/* hack until we have decided on the devtree info */
+		regs += 0x400;
+		if (cpu & 1)
+			regs += 0x20;
+
+		printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs);
+		iic->regs = ioremap(regs, sizeof(struct iic_regs));
+		iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe);
 	}
 
-	if (!np) {
-		printk(KERN_WARNING "IIC: CPU %d not found\n", cpu);
-		iic->regs = NULL;
-		iic->target_id = 0xff;
-		return -ENODEV;
-	}
-
-	regs = *(long *)get_property(np, "iic", NULL);
-
-	/* hack until we have decided on the devtree info */
-	regs += 0x400;
-	if (cpu & 1)
-		regs += 0x20;
-
-	printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs);
-	iic->regs = __ioremap(regs, sizeof(struct iic_regs),
-					 _PAGE_NO_CACHE);
-	iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe);
 	return 0;
 }
 
+static int setup_iic(void)
+{
+	struct device_node *dn;
+	unsigned long *regs;
+	char *compatible;
+ 	unsigned *np, found = 0;
+	struct iic *iic = NULL;
+
+	for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
+		compatible = (char *)get_property(dn, "compatible", NULL);
+
+		if (!compatible) {
+			printk(KERN_WARNING "no compatible property found !\n");
+			continue;
+		}
+
+ 		if (strstr(compatible, "IBM,CBEA-Internal-Interrupt-Controller"))
+ 			regs = (unsigned long *)get_property(dn,"reg", NULL);
+ 		else
+			continue;
+
+ 		if (!regs)
+ 			printk(KERN_WARNING "IIC: no reg property\n");
+
+ 		np = (unsigned int *)get_property(dn, "ibm,interrupt-server-ranges", NULL);
+
+ 		if (!np) {
+			printk(KERN_WARNING "IIC: CPU association not found\n");
+			iic->regs = NULL;
+			iic->target_id = 0xff;
+			return -ENODEV;
+		}
+
+ 		iic = &per_cpu(iic, np[0]);
+ 		iic->regs = ioremap(regs[0], sizeof(struct iic_regs));
+		iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe);
+ 		printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs);
+
+ 		iic = &per_cpu(iic, np[1]);
+ 		iic->regs = ioremap(regs[2], sizeof(struct iic_regs));
+		iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe);
+ 		printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs);
+
+		found++;
+  	}
+
+	if (found)
+		return 0;
+	else
+		return -ENODEV;
+}
+
 #ifdef CONFIG_SMP
 
 /* Use the highest interrupt priorities for IPI */
@@ -283,10 +360,12 @@
 	int cpu, irq_offset;
 	struct iic *iic;
 
+	if (setup_iic() < 0)
+		setup_iic_hardcoded();
+
 	irq_offset = 0;
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		iic = &per_cpu(iic, cpu);
-		setup_iic(cpu, iic);
 		if (iic->regs)
 			out_be64(&iic->regs->prio, 0xff);
 	}
diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h
index a14bd38..799f77d 100644
--- a/arch/powerpc/platforms/cell/interrupt.h
+++ b/arch/powerpc/platforms/cell/interrupt.h
@@ -57,7 +57,7 @@
 extern u8 iic_get_target_id(int cpu);
 
 extern void spider_init_IRQ(void);
-extern int spider_get_irq(unsigned long int_pending);
+extern int spider_get_irq(int node);
 
 #endif
 #endif /* ASM_CELL_PIC_H */
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 46e7cb9..a49ceb7 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -289,7 +289,7 @@
 	ioc_base = iommu->mapped_base;
 	ioc_mmio_base = iommu->mapped_mmio_base;
 
-	for (real_address = 0, io_address = 0;
+	for (real_address = 0, io_address = map_start;
 	     io_address <= map_start + map_size;
 	     real_address += io_page_size, io_address += io_page_size) {
 		ioste = get_iost_entry(fake_iopt, io_address, io_page_size);
@@ -302,7 +302,7 @@
 		set_iopt_cache(ioc_mmio_base,
 			get_ioc_hash_1way(ioste, io_address),
 			get_ioc_tag(ioste, io_address),
-			get_iopt_entry(real_address-map_start, ioid, IOPT_PROT_RW));
+			get_iopt_entry(real_address, ioid, IOPT_PROT_RW));
 	}
 }
 
@@ -344,8 +344,8 @@
 
 	/* node 0 */
 	iommu = &cell_iommus[0];
-	iommu->mapped_base = __ioremap(0x20000511000, 0x1000, _PAGE_NO_CACHE);
-	iommu->mapped_mmio_base = __ioremap(0x20000510000, 0x1000, _PAGE_NO_CACHE);
+	iommu->mapped_base = ioremap(0x20000511000, 0x1000);
+	iommu->mapped_mmio_base = ioremap(0x20000510000, 0x1000);
 
 	enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base);
 
@@ -357,8 +357,8 @@
 
 	/* node 1 */
 	iommu = &cell_iommus[1];
-	iommu->mapped_base = __ioremap(0x30000511000, 0x1000, _PAGE_NO_CACHE);
-	iommu->mapped_mmio_base = __ioremap(0x30000510000, 0x1000, _PAGE_NO_CACHE);
+	iommu->mapped_base = ioremap(0x30000511000, 0x1000);
+	iommu->mapped_mmio_base = ioremap(0x30000510000, 0x1000);
 
 	enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base);
 
@@ -407,8 +407,8 @@
 		iommu->base = *base;
 		iommu->mmio_base = *mmio_base;
 
-		iommu->mapped_base = __ioremap(*base, 0x1000, _PAGE_NO_CACHE);
-		iommu->mapped_mmio_base = __ioremap(*mmio_base, 0x1000, _PAGE_NO_CACHE);
+		iommu->mapped_base = ioremap(*base, 0x1000);
+		iommu->mapped_mmio_base = ioremap(*mmio_base, 0x1000);
 
 		enable_mapping(iommu->mapped_base,
 			       iommu->mapped_mmio_base);
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index e0e051c..7eed8c6 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -203,7 +203,7 @@
 
 	pr_debug("pervasive area for CPU %d at %lx, size %x\n",
 			cpu, real_address, size);
-	p->regs = __ioremap(real_address, size, _PAGE_NO_CACHE);
+	p->regs = ioremap(real_address, size);
 	p->thread = thread;
 	return 0;
 }
@@ -217,7 +217,7 @@
 	if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
 		return;
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		p = &cbe_pervasive[cpu];
 		ret = cbe_find_pmd_mmio(cpu, p);
 		if (ret)
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index fec8e65..dac5d03 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -195,9 +195,13 @@
 }
 
 
-static int __init cell_probe(int platform)
+static int __init cell_probe(void)
 {
-	if (platform != PLATFORM_CELL)
+	/* XXX This is temporary, the Cell maintainer will come up with
+	 * more appropriate detection logic
+	 */
+	unsigned long root = of_get_flat_dt_root();
+	if (!of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
 		return 0;
 
 	return 1;
@@ -212,7 +216,8 @@
 	return -ENODEV;
 }
 
-struct machdep_calls __initdata cell_md = {
+define_machine(cell) {
+	.name			= "Cell",
 	.probe			= cell_probe,
 	.setup_arch		= cell_setup_arch,
 	.init_early		= cell_init_early,
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index e741321..55cbdd7 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -84,10 +84,11 @@
 
 static void spider_enable_irq(unsigned int irq)
 {
+	int nodeid = (irq / IIC_NODE_STRIDE) * 0x10;
 	void __iomem *cfg = spider_get_irq_config(irq);
 	irq = spider_get_nr(irq);
 
-	out_be32(cfg, in_be32(cfg) | 0x3107000eu);
+	out_be32(cfg, (in_be32(cfg) & ~0xf0)| 0x3107000eu | nodeid);
 	out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq);
 }
 
@@ -131,61 +132,108 @@
 	.end = spider_end_irq,
 };
 
-
-int spider_get_irq(unsigned long int_pending)
+int spider_get_irq(int node)
 {
-	void __iomem *regs = spider_get_pic(int_pending);
 	unsigned long cs;
-	int irq;
+	void __iomem *regs = spider_pics[node];
 
-	cs = in_be32(regs + TIR_CS);
+	cs = in_be32(regs + TIR_CS) >> 24;
 
-	irq = cs >> 24;
-	if (irq != 63)
-		return irq;
-
-	return -1;
+	if (cs == 63)
+		return -1;
+	else
+		return cs;
 }
- 
-void spider_init_IRQ(void)
+
+/* hardcoded part to be compatible with older firmware */
+
+void spider_init_IRQ_hardcoded(void)
 {
 	int node;
-	struct device_node *dn;
-	unsigned int *property;
 	long spiderpic;
+	long pics[] = { 0x24000008000, 0x34000008000 };
 	int n;
 
-/* FIXME: detect multiple PICs as soon as the device tree has them */
-	for (node = 0; node < 1; node++) {
-		dn = of_find_node_by_path("/");
-		n = prom_n_addr_cells(dn);
-		property = (unsigned int *) get_property(dn,
-				"platform-spider-pic", NULL);
+	pr_debug("%s(%d): Using hardcoded defaults\n", __FUNCTION__, __LINE__);
 
-		if (!property)
-			continue;
-		for (spiderpic = 0; n > 0; --n)
-			spiderpic = (spiderpic << 32) + *property++;
+	for (node = 0; node < num_present_cpus()/2; node++) {
+		spiderpic = pics[node];
 		printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic);
-		spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE);
+		spider_pics[node] = ioremap(spiderpic, 0x800);
 		for (n = 0; n < IIC_NUM_EXT; n++) {
 			int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE;
 			get_irq_desc(irq)->handler = &spider_pic;
+		}
 
  		/* do not mask any interrupts because of level */
  		out_be32(spider_pics[node] + TIR_MSK, 0x0);
- 		
+
  		/* disable edge detection clear */
  		/* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
- 		
+
  		/* enable interrupt packets to be output */
  		out_be32(spider_pics[node] + TIR_PIEN,
 			in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
- 		
+
  		/* Enable the interrupt detection enable bit. Do this last! */
  		out_be32(spider_pics[node] + TIR_DEN,
-			in_be32(spider_pics[node] +TIR_DEN) | 0x1);
+			in_be32(spider_pics[node] + TIR_DEN) | 0x1);
+	}
+}
 
+void spider_init_IRQ(void)
+{
+	long spider_reg;
+	struct device_node *dn;
+	char *compatible;
+	int n, node = 0;
+
+	for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
+		compatible = (char *)get_property(dn, "compatible", NULL);
+
+		if (!compatible)
+			continue;
+
+		if (strstr(compatible, "CBEA,platform-spider-pic"))
+			spider_reg = *(long *)get_property(dn,"reg", NULL);
+		else if (strstr(compatible, "sti,platform-spider-pic")) {
+			spider_init_IRQ_hardcoded();
+			return;
+		} else
+			continue;
+
+		if (!spider_reg)
+			printk("interrupt controller does not have reg property !\n");
+
+		n = prom_n_addr_cells(dn);
+
+		if ( n != 2)
+			printk("reg property with invalid number of elements \n");
+
+		spider_pics[node] = ioremap(spider_reg, 0x800);
+
+		printk("SPIDER addr: %lx with %i addr_cells mapped to %p\n",
+		       spider_reg, n, spider_pics[node]);
+
+		for (n = 0; n < IIC_NUM_EXT; n++) {
+			int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE;
+			get_irq_desc(irq)->handler = &spider_pic;
 		}
+
+		/* do not mask any interrupts because of level */
+		out_be32(spider_pics[node] + TIR_MSK, 0x0);
+
+		/* disable edge detection clear */
+		/* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
+
+		/* enable interrupt packets to be output */
+		out_be32(spider_pics[node] + TIR_PIEN,
+			in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
+
+		/* Enable the interrupt detection enable bit. Do this last! */
+		out_be32(spider_pics[node] + TIR_DEN,
+			in_be32(spider_pics[node] + TIR_DEN) | 0x1);
+
+		node++;
 	}
 }
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index a8fa1ee..269dda4 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -111,7 +111,7 @@
 extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX
 static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
 {
-	pr_debug("%s\n", __FUNCTION__);
+	pr_debug("%s, %lx, %lx\n", __FUNCTION__, dsisr, ea);
 
 	/* Handle kernel space hash faults immediately.
 	   User hash faults need to be deferred to process context. */
@@ -168,7 +168,7 @@
 static int __spu_trap_tag_group(struct spu *spu)
 {
 	pr_debug("%s\n", __FUNCTION__);
-	/* wake_up(&spu->dma_wq); */
+	spu->mfc_callback(spu);
 	return 0;
 }
 
@@ -242,6 +242,8 @@
 		spu_mfc_dsisr_set(spu, 0ul);
 	spu_int_stat_clear(spu, 1, stat);
 	spin_unlock(&spu->register_lock);
+	pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat,
+			dar, dsisr);
 
 	if (stat & 1) /* segment fault */
 		__spu_trap_data_seg(spu, dar);
@@ -484,14 +486,13 @@
 
 	ea = spu->dar;
 	dsisr = spu->dsisr;
-	if (dsisr & MFC_DSISR_PTE_NOT_FOUND) {
+	if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) {
 		access = (_PAGE_PRESENT | _PAGE_USER);
 		access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL;
 		if (hash_page(ea, access, 0x300) != 0)
 			error |= CLASS1_ENABLE_STORAGE_FAULT_INTR;
 	}
-	if ((error & CLASS1_ENABLE_STORAGE_FAULT_INTR) ||
-	    (dsisr & MFC_DSISR_ACCESS_DENIED)) {
+	if (error & CLASS1_ENABLE_STORAGE_FAULT_INTR) {
 		if ((ret = spu_handle_mm_fault(spu)) != 0)
 			error |= CLASS1_ENABLE_STORAGE_FAULT_INTR;
 		else
@@ -568,6 +569,11 @@
 	if (!spu->local_store)
 		goto out;
 
+	prop = get_property(spe, "problem", NULL);
+	if (!prop)
+		goto out_unmap;
+	spu->problem_phys = *(unsigned long *)prop;
+
 	spu->problem= map_spe_prop(spe, "problem");
 	if (!spu->problem)
 		goto out_unmap;
@@ -632,6 +638,7 @@
 	spu->ibox_callback = NULL;
 	spu->wbox_callback = NULL;
 	spu->stop_callback = NULL;
+	spu->mfc_callback = NULL;
 
 	mutex_lock(&spu_mutex);
 	spu->number = number++;
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c
new file mode 100644
index 0000000..3a4245c
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spu_callbacks.c
@@ -0,0 +1,345 @@
+/*
+ * System call callback functions for SPUs
+ */
+
+#define DEBUG
+
+#include <linux/kallsyms.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+
+#include <asm/spu.h>
+#include <asm/syscalls.h>
+#include <asm/unistd.h>
+
+/*
+ * This table defines the system calls that an SPU can call.
+ * It is currently a subset of the 64 bit powerpc system calls,
+ * with the exact semantics.
+ *
+ * The reasons for disabling some of the system calls are:
+ * 1. They interact with the way SPU syscalls are handled
+ *    and we can't let them execute ever:
+ *	restart_syscall, exit, for, execve, ptrace, ...
+ * 2. They are deprecated and replaced by other means:
+ *	uselib, pciconfig_*, sysfs, ...
+ * 3. They are somewhat interacting with the system in a way
+ *    we don't want an SPU to:
+ *	reboot, init_module, mount, kexec_load
+ * 4. They are optional and we can't rely on them being
+ *    linked into the kernel. Unfortunately, the cond_syscall
+ *    helper does not work here as it does not add the necessary
+ *    opd symbols:
+ *	mbind, mq_open, ipc, ...
+ */
+
+void *spu_syscall_table[] = {
+	[__NR_restart_syscall]		sys_ni_syscall, /* sys_restart_syscall */
+	[__NR_exit]			sys_ni_syscall, /* sys_exit */
+	[__NR_fork]			sys_ni_syscall, /* ppc_fork */
+	[__NR_read]			sys_read,
+	[__NR_write]			sys_write,
+	[__NR_open]			sys_open,
+	[__NR_close]			sys_close,
+	[__NR_waitpid]			sys_waitpid,
+	[__NR_creat]			sys_creat,
+	[__NR_link]			sys_link,
+	[__NR_unlink]			sys_unlink,
+	[__NR_execve]			sys_ni_syscall, /* sys_execve */
+	[__NR_chdir]			sys_chdir,
+	[__NR_time]			sys_time,
+	[__NR_mknod]			sys_mknod,
+	[__NR_chmod]			sys_chmod,
+	[__NR_lchown]			sys_lchown,
+	[__NR_break]			sys_ni_syscall,
+	[__NR_oldstat]			sys_ni_syscall,
+	[__NR_lseek]			sys_lseek,
+	[__NR_getpid]			sys_getpid,
+	[__NR_mount]			sys_ni_syscall, /* sys_mount */
+	[__NR_umount]			sys_ni_syscall,
+	[__NR_setuid]			sys_setuid,
+	[__NR_getuid]			sys_getuid,
+	[__NR_stime]			sys_stime,
+	[__NR_ptrace]			sys_ni_syscall, /* sys_ptrace */
+	[__NR_alarm]			sys_alarm,
+	[__NR_oldfstat]			sys_ni_syscall,
+	[__NR_pause]			sys_ni_syscall, /* sys_pause */
+	[__NR_utime]			sys_ni_syscall, /* sys_utime */
+	[__NR_stty]			sys_ni_syscall,
+	[__NR_gtty]			sys_ni_syscall,
+	[__NR_access]			sys_access,
+	[__NR_nice]			sys_nice,
+	[__NR_ftime]			sys_ni_syscall,
+	[__NR_sync]			sys_sync,
+	[__NR_kill]			sys_kill,
+	[__NR_rename]			sys_rename,
+	[__NR_mkdir]			sys_mkdir,
+	[__NR_rmdir]			sys_rmdir,
+	[__NR_dup]			sys_dup,
+	[__NR_pipe]			sys_pipe,
+	[__NR_times]			sys_times,
+	[__NR_prof]			sys_ni_syscall,
+	[__NR_brk]			sys_brk,
+	[__NR_setgid]			sys_setgid,
+	[__NR_getgid]			sys_getgid,
+	[__NR_signal]			sys_ni_syscall, /* sys_signal */
+	[__NR_geteuid]			sys_geteuid,
+	[__NR_getegid]			sys_getegid,
+	[__NR_acct]			sys_ni_syscall, /* sys_acct */
+	[__NR_umount2]			sys_ni_syscall, /* sys_umount */
+	[__NR_lock]			sys_ni_syscall,
+	[__NR_ioctl]			sys_ioctl,
+	[__NR_fcntl]			sys_fcntl,
+	[__NR_mpx]			sys_ni_syscall,
+	[__NR_setpgid]			sys_setpgid,
+	[__NR_ulimit]			sys_ni_syscall,
+	[__NR_oldolduname]		sys_ni_syscall,
+	[__NR_umask]			sys_umask,
+	[__NR_chroot]			sys_chroot,
+	[__NR_ustat]			sys_ni_syscall, /* sys_ustat */
+	[__NR_dup2]			sys_dup2,
+	[__NR_getppid]			sys_getppid,
+	[__NR_getpgrp]			sys_getpgrp,
+	[__NR_setsid]			sys_setsid,
+	[__NR_sigaction]		sys_ni_syscall,
+	[__NR_sgetmask]			sys_sgetmask,
+	[__NR_ssetmask]			sys_ssetmask,
+	[__NR_setreuid]			sys_setreuid,
+	[__NR_setregid]			sys_setregid,
+	[__NR_sigsuspend]		sys_ni_syscall,
+	[__NR_sigpending]		sys_ni_syscall,
+	[__NR_sethostname]		sys_sethostname,
+	[__NR_setrlimit]		sys_setrlimit,
+	[__NR_getrlimit]		sys_ni_syscall,
+	[__NR_getrusage]		sys_getrusage,
+	[__NR_gettimeofday]		sys_gettimeofday,
+	[__NR_settimeofday]		sys_settimeofday,
+	[__NR_getgroups]		sys_getgroups,
+	[__NR_setgroups]		sys_setgroups,
+	[__NR_select]			sys_ni_syscall,
+	[__NR_symlink]			sys_symlink,
+	[__NR_oldlstat]			sys_ni_syscall,
+	[__NR_readlink]			sys_readlink,
+	[__NR_uselib]			sys_ni_syscall, /* sys_uselib */
+	[__NR_swapon]			sys_ni_syscall, /* sys_swapon */
+	[__NR_reboot]			sys_ni_syscall, /* sys_reboot */
+	[__NR_readdir]			sys_ni_syscall,
+	[__NR_mmap]			sys_mmap,
+	[__NR_munmap]			sys_munmap,
+	[__NR_truncate]			sys_truncate,
+	[__NR_ftruncate]		sys_ftruncate,
+	[__NR_fchmod]			sys_fchmod,
+	[__NR_fchown]			sys_fchown,
+	[__NR_getpriority]		sys_getpriority,
+	[__NR_setpriority]		sys_setpriority,
+	[__NR_profil]			sys_ni_syscall,
+	[__NR_statfs]			sys_ni_syscall, /* sys_statfs */
+	[__NR_fstatfs]			sys_ni_syscall, /* sys_fstatfs */
+	[__NR_ioperm]			sys_ni_syscall,
+	[__NR_socketcall]		sys_socketcall,
+	[__NR_syslog]			sys_syslog,
+	[__NR_setitimer]		sys_setitimer,
+	[__NR_getitimer]		sys_getitimer,
+	[__NR_stat]			sys_newstat,
+	[__NR_lstat]			sys_newlstat,
+	[__NR_fstat]			sys_newfstat,
+	[__NR_olduname]			sys_ni_syscall,
+	[__NR_iopl]			sys_ni_syscall,
+	[__NR_vhangup]			sys_vhangup,
+	[__NR_idle]			sys_ni_syscall,
+	[__NR_vm86]			sys_ni_syscall,
+	[__NR_wait4]			sys_wait4,
+	[__NR_swapoff]			sys_ni_syscall, /* sys_swapoff */
+	[__NR_sysinfo]			sys_sysinfo,
+	[__NR_ipc]			sys_ni_syscall, /* sys_ipc */
+	[__NR_fsync]			sys_fsync,
+	[__NR_sigreturn]		sys_ni_syscall,
+	[__NR_clone]			sys_ni_syscall, /* ppc_clone */
+	[__NR_setdomainname]		sys_setdomainname,
+	[__NR_uname]			ppc_newuname,
+	[__NR_modify_ldt]		sys_ni_syscall,
+	[__NR_adjtimex]			sys_adjtimex,
+	[__NR_mprotect]			sys_mprotect,
+	[__NR_sigprocmask]		sys_ni_syscall,
+	[__NR_create_module]		sys_ni_syscall,
+	[__NR_init_module]		sys_ni_syscall, /* sys_init_module */
+	[__NR_delete_module]		sys_ni_syscall, /* sys_delete_module */
+	[__NR_get_kernel_syms]		sys_ni_syscall,
+	[__NR_quotactl]			sys_ni_syscall, /* sys_quotactl */
+	[__NR_getpgid]			sys_getpgid,
+	[__NR_fchdir]			sys_fchdir,
+	[__NR_bdflush]			sys_bdflush,
+	[__NR_sysfs]			sys_ni_syscall, /* sys_sysfs */
+	[__NR_personality]		ppc64_personality,
+	[__NR_afs_syscall]		sys_ni_syscall,
+	[__NR_setfsuid]			sys_setfsuid,
+	[__NR_setfsgid]			sys_setfsgid,
+	[__NR__llseek]			sys_llseek,
+	[__NR_getdents]			sys_getdents,
+	[__NR__newselect]		sys_select,
+	[__NR_flock]			sys_flock,
+	[__NR_msync]			sys_msync,
+	[__NR_readv]			sys_readv,
+	[__NR_writev]			sys_writev,
+	[__NR_getsid]			sys_getsid,
+	[__NR_fdatasync]		sys_fdatasync,
+	[__NR__sysctl]			sys_ni_syscall, /* sys_sysctl */
+	[__NR_mlock]			sys_mlock,
+	[__NR_munlock]			sys_munlock,
+	[__NR_mlockall]			sys_mlockall,
+	[__NR_munlockall]		sys_munlockall,
+	[__NR_sched_setparam]		sys_sched_setparam,
+	[__NR_sched_getparam]		sys_sched_getparam,
+	[__NR_sched_setscheduler]	sys_sched_setscheduler,
+	[__NR_sched_getscheduler]	sys_sched_getscheduler,
+	[__NR_sched_yield]		sys_sched_yield,
+	[__NR_sched_get_priority_max]	sys_sched_get_priority_max,
+	[__NR_sched_get_priority_min]	sys_sched_get_priority_min,
+	[__NR_sched_rr_get_interval]	sys_sched_rr_get_interval,
+	[__NR_nanosleep]		sys_nanosleep,
+	[__NR_mremap]			sys_mremap,
+	[__NR_setresuid]		sys_setresuid,
+	[__NR_getresuid]		sys_getresuid,
+	[__NR_query_module]		sys_ni_syscall,
+	[__NR_poll]			sys_poll,
+	[__NR_nfsservctl]		sys_ni_syscall, /* sys_nfsservctl */
+	[__NR_setresgid]		sys_setresgid,
+	[__NR_getresgid]		sys_getresgid,
+	[__NR_prctl]			sys_prctl,
+	[__NR_rt_sigreturn]		sys_ni_syscall, /* ppc64_rt_sigreturn */
+	[__NR_rt_sigaction]		sys_ni_syscall, /* sys_rt_sigaction */
+	[__NR_rt_sigprocmask]		sys_ni_syscall, /* sys_rt_sigprocmask */
+	[__NR_rt_sigpending]		sys_ni_syscall, /* sys_rt_sigpending */
+	[__NR_rt_sigtimedwait]		sys_ni_syscall, /* sys_rt_sigtimedwait */
+	[__NR_rt_sigqueueinfo]		sys_ni_syscall, /* sys_rt_sigqueueinfo */
+	[__NR_rt_sigsuspend]		sys_ni_syscall, /* sys_rt_sigsuspend */
+	[__NR_pread64]			sys_pread64,
+	[__NR_pwrite64]			sys_pwrite64,
+	[__NR_chown]			sys_chown,
+	[__NR_getcwd]			sys_getcwd,
+	[__NR_capget]			sys_capget,
+	[__NR_capset]			sys_capset,
+	[__NR_sigaltstack]		sys_ni_syscall, /* sys_sigaltstack */
+	[__NR_sendfile]			sys_sendfile64,
+	[__NR_getpmsg]			sys_ni_syscall,
+	[__NR_putpmsg]			sys_ni_syscall,
+	[__NR_vfork]			sys_ni_syscall, /* ppc_vfork */
+	[__NR_ugetrlimit]		sys_getrlimit,
+	[__NR_readahead]		sys_readahead,
+	[192]				sys_ni_syscall,
+	[193]				sys_ni_syscall,
+	[194]				sys_ni_syscall,
+	[195]				sys_ni_syscall,
+	[196]				sys_ni_syscall,
+	[197]				sys_ni_syscall,
+	[__NR_pciconfig_read]		sys_ni_syscall, /* sys_pciconfig_read */
+	[__NR_pciconfig_write]		sys_ni_syscall, /* sys_pciconfig_write */
+	[__NR_pciconfig_iobase]		sys_ni_syscall, /* sys_pciconfig_iobase */
+	[__NR_multiplexer]		sys_ni_syscall,
+	[__NR_getdents64]		sys_getdents64,
+	[__NR_pivot_root]		sys_pivot_root,
+	[204]				sys_ni_syscall,
+	[__NR_madvise]			sys_madvise,
+	[__NR_mincore]			sys_mincore,
+	[__NR_gettid]			sys_gettid,
+	[__NR_tkill]			sys_tkill,
+	[__NR_setxattr]			sys_setxattr,
+	[__NR_lsetxattr]		sys_lsetxattr,
+	[__NR_fsetxattr]		sys_fsetxattr,
+	[__NR_getxattr]			sys_getxattr,
+	[__NR_lgetxattr]		sys_lgetxattr,
+	[__NR_fgetxattr]		sys_fgetxattr,
+	[__NR_listxattr]		sys_listxattr,
+	[__NR_llistxattr]		sys_llistxattr,
+	[__NR_flistxattr]		sys_flistxattr,
+	[__NR_removexattr]		sys_removexattr,
+	[__NR_lremovexattr]		sys_lremovexattr,
+	[__NR_fremovexattr]		sys_fremovexattr,
+	[__NR_futex]			sys_futex,
+	[__NR_sched_setaffinity]	sys_sched_setaffinity,
+	[__NR_sched_getaffinity]	sys_sched_getaffinity,
+	[__NR_tuxcall]			sys_ni_syscall,
+	[226]				sys_ni_syscall,
+	[__NR_io_setup]			sys_io_setup,
+	[__NR_io_destroy]		sys_io_destroy,
+	[__NR_io_getevents]		sys_io_getevents,
+	[__NR_io_submit]		sys_io_submit,
+	[__NR_io_cancel]		sys_io_cancel,
+	[__NR_set_tid_address]		sys_ni_syscall, /* sys_set_tid_address */
+	[__NR_fadvise64]		sys_fadvise64,
+	[__NR_exit_group]		sys_ni_syscall, /* sys_exit_group */
+	[__NR_lookup_dcookie]		sys_ni_syscall, /* sys_lookup_dcookie */
+	[__NR_epoll_create]		sys_epoll_create,
+	[__NR_epoll_ctl]		sys_epoll_ctl,
+	[__NR_epoll_wait]		sys_epoll_wait,
+	[__NR_remap_file_pages]		sys_remap_file_pages,
+	[__NR_timer_create]		sys_timer_create,
+	[__NR_timer_settime]		sys_timer_settime,
+	[__NR_timer_gettime]		sys_timer_gettime,
+	[__NR_timer_getoverrun]		sys_timer_getoverrun,
+	[__NR_timer_delete]		sys_timer_delete,
+	[__NR_clock_settime]		sys_clock_settime,
+	[__NR_clock_gettime]		sys_clock_gettime,
+	[__NR_clock_getres]		sys_clock_getres,
+	[__NR_clock_nanosleep]		sys_clock_nanosleep,
+	[__NR_swapcontext]		sys_ni_syscall, /* ppc64_swapcontext */
+	[__NR_tgkill]			sys_tgkill,
+	[__NR_utimes]			sys_utimes,
+	[__NR_statfs64]			sys_statfs64,
+	[__NR_fstatfs64]		sys_fstatfs64,
+	[254]				sys_ni_syscall,
+	[__NR_rtas]			ppc_rtas,
+	[256]				sys_ni_syscall,
+	[257]				sys_ni_syscall,
+	[258]				sys_ni_syscall,
+	[__NR_mbind]			sys_ni_syscall, /* sys_mbind */
+	[__NR_get_mempolicy]		sys_ni_syscall, /* sys_get_mempolicy */
+	[__NR_set_mempolicy]		sys_ni_syscall, /* sys_set_mempolicy */
+	[__NR_mq_open]			sys_ni_syscall, /* sys_mq_open */
+	[__NR_mq_unlink]		sys_ni_syscall, /* sys_mq_unlink */
+	[__NR_mq_timedsend]		sys_ni_syscall, /* sys_mq_timedsend */
+	[__NR_mq_timedreceive]		sys_ni_syscall, /* sys_mq_timedreceive */
+	[__NR_mq_notify]		sys_ni_syscall, /* sys_mq_notify */
+	[__NR_mq_getsetattr]		sys_ni_syscall, /* sys_mq_getsetattr */
+	[__NR_kexec_load]		sys_ni_syscall, /* sys_kexec_load */
+	[__NR_add_key]			sys_ni_syscall, /* sys_add_key */
+	[__NR_request_key]		sys_ni_syscall, /* sys_request_key */
+	[__NR_keyctl]			sys_ni_syscall, /* sys_keyctl */
+	[__NR_waitid]			sys_ni_syscall, /* sys_waitid */
+	[__NR_ioprio_set]		sys_ni_syscall, /* sys_ioprio_set */
+	[__NR_ioprio_get]		sys_ni_syscall, /* sys_ioprio_get */
+	[__NR_inotify_init]		sys_ni_syscall, /* sys_inotify_init */
+	[__NR_inotify_add_watch]	sys_ni_syscall, /* sys_inotify_add_watch */
+	[__NR_inotify_rm_watch]		sys_ni_syscall, /* sys_inotify_rm_watch */
+	[__NR_spu_run]			sys_ni_syscall, /* sys_spu_run */
+	[__NR_spu_create]		sys_ni_syscall, /* sys_spu_create */
+	[__NR_pselect6]			sys_ni_syscall, /* sys_pselect */
+	[__NR_ppoll]			sys_ni_syscall, /* sys_ppoll */
+	[__NR_unshare]			sys_unshare,
+};
+
+long spu_sys_callback(struct spu_syscall_block *s)
+{
+	long (*syscall)(u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6);
+
+	BUILD_BUG_ON(ARRAY_SIZE(spu_syscall_table) != __NR_syscalls);
+
+	syscall = spu_syscall_table[s->nr_ret];
+
+	if (s->nr_ret >= __NR_syscalls) {
+		pr_debug("%s: invalid syscall #%ld", __FUNCTION__, s->nr_ret);
+		return -ENOSYS;
+	}
+
+#ifdef DEBUG
+	print_symbol(KERN_DEBUG "SPU-syscall %s:", (unsigned long)syscall);
+	printk("syscall%ld(%lx, %lx, %lx, %lx, %lx, %lx)\n",
+			s->nr_ret,
+			s->parm[0], s->parm[1], s->parm[2],
+			s->parm[3], s->parm[4], s->parm[5]);
+#endif
+
+	return syscall(s->parm[0], s->parm[1], s->parm[2],
+		       s->parm[3], s->parm[4], s->parm[5]);
+}
+EXPORT_SYMBOL_GPL(spu_sys_callback);
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c
index a5c489a5..f1d35dd 100644
--- a/arch/powerpc/platforms/cell/spufs/backing_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c
@@ -285,6 +285,49 @@
 	spu_backing_runcntl_write(ctx, SPU_RUNCNTL_STOP);
 }
 
+static int spu_backing_set_mfc_query(struct spu_context * ctx, u32 mask,
+					u32 mode)
+{
+	struct spu_problem_collapsed *prob = &ctx->csa.prob;
+	int ret;
+
+	spin_lock(&ctx->csa.register_lock);
+	ret = -EAGAIN;
+	if (prob->dma_querytype_RW)
+		goto out;
+	ret = 0;
+	/* FIXME: what are the side-effects of this? */
+	prob->dma_querymask_RW = mask;
+	prob->dma_querytype_RW = mode;
+out:
+	spin_unlock(&ctx->csa.register_lock);
+
+	return ret;
+}
+
+static u32 spu_backing_read_mfc_tagstatus(struct spu_context * ctx)
+{
+	return ctx->csa.prob.dma_tagstatus_R;
+}
+
+static u32 spu_backing_get_mfc_free_elements(struct spu_context *ctx)
+{
+	return ctx->csa.prob.dma_qstatus_R;
+}
+
+static int spu_backing_send_mfc_command(struct spu_context *ctx,
+					struct mfc_dma_command *cmd)
+{
+	int ret;
+
+	spin_lock(&ctx->csa.register_lock);
+	ret = -EAGAIN;
+	/* FIXME: set up priv2->puq */
+	spin_unlock(&ctx->csa.register_lock);
+
+	return ret;
+}
+
 struct spu_context_ops spu_backing_ops = {
 	.mbox_read = spu_backing_mbox_read,
 	.mbox_stat_read = spu_backing_mbox_stat_read,
@@ -305,4 +348,8 @@
 	.get_ls = spu_backing_get_ls,
 	.runcntl_write = spu_backing_runcntl_write,
 	.runcntl_stop = spu_backing_runcntl_stop,
+	.set_mfc_query = spu_backing_set_mfc_query,
+	.read_mfc_tagstatus = spu_backing_read_mfc_tagstatus,
+	.get_mfc_free_elements = spu_backing_get_mfc_free_elements,
+	.send_mfc_command = spu_backing_send_mfc_command,
 };
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 336f238..8bb33ab 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -27,7 +27,7 @@
 #include <asm/spu_csa.h>
 #include "spufs.h"
 
-struct spu_context *alloc_spu_context(struct address_space *local_store)
+struct spu_context *alloc_spu_context(void)
 {
 	struct spu_context *ctx;
 	ctx = kmalloc(sizeof *ctx, GFP_KERNEL);
@@ -47,10 +47,17 @@
 	init_waitqueue_head(&ctx->ibox_wq);
 	init_waitqueue_head(&ctx->wbox_wq);
 	init_waitqueue_head(&ctx->stop_wq);
+	init_waitqueue_head(&ctx->mfc_wq);
 	ctx->ibox_fasync = NULL;
 	ctx->wbox_fasync = NULL;
+	ctx->mfc_fasync = NULL;
+	ctx->mfc = NULL;
+	ctx->tagwait = 0;
 	ctx->state = SPU_STATE_SAVED;
-	ctx->local_store = local_store;
+	ctx->local_store = NULL;
+	ctx->cntl = NULL;
+	ctx->signal1 = NULL;
+	ctx->signal2 = NULL;
 	ctx->spu = NULL;
 	ctx->ops = &spu_backing_ops;
 	ctx->owner = get_task_mm(current);
@@ -68,8 +75,6 @@
 	ctx = container_of(kref, struct spu_context, kref);
 	down_write(&ctx->state_sema);
 	spu_deactivate(ctx);
-	ctx->ibox_fasync = NULL;
-	ctx->wbox_fasync = NULL;
 	up_write(&ctx->state_sema);
 	spu_fini_csa(&ctx->csa);
 	kfree(ctx);
@@ -109,7 +114,16 @@
 
 void spu_unmap_mappings(struct spu_context *ctx)
 {
-	unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
+	if (ctx->local_store)
+		unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
+	if (ctx->mfc)
+		unmap_mapping_range(ctx->mfc, 0, 0x4000, 1);
+	if (ctx->cntl)
+		unmap_mapping_range(ctx->cntl, 0, 0x4000, 1);
+	if (ctx->signal1)
+		unmap_mapping_range(ctx->signal1, 0, 0x4000, 1);
+	if (ctx->signal2)
+		unmap_mapping_range(ctx->signal2, 0, 0x4000, 1);
 }
 
 int spu_acquire_runnable(struct spu_context *ctx)
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index dfa649c..366185e 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -20,6 +20,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#undef DEBUG
+
 #include <linux/fs.h>
 #include <linux/ioctl.h>
 #include <linux/module.h>
@@ -39,8 +41,10 @@
 spufs_mem_open(struct inode *inode, struct file *file)
 {
 	struct spufs_inode_info *i = SPUFS_I(inode);
-	file->private_data = i->i_ctx;
-	file->f_mapping = i->i_ctx->local_store;
+	struct spu_context *ctx = i->i_ctx;
+	file->private_data = ctx;
+	file->f_mapping = inode->i_mapping;
+	ctx->local_store = inode->i_mapping;
 	return 0;
 }
 
@@ -84,7 +88,7 @@
 	return ret;
 }
 
-#ifdef CONFIG_SPARSEMEM
+#ifdef CONFIG_SPUFS_MMAP
 static struct page *
 spufs_mem_mmap_nopage(struct vm_area_struct *vma,
 		      unsigned long address, int *type)
@@ -136,11 +140,113 @@
 	.read    = spufs_mem_read,
 	.write   = spufs_mem_write,
 	.llseek  = generic_file_llseek,
-#ifdef CONFIG_SPARSEMEM
+#ifdef CONFIG_SPUFS_MMAP
 	.mmap    = spufs_mem_mmap,
 #endif
 };
 
+#ifdef CONFIG_SPUFS_MMAP
+static struct page *spufs_ps_nopage(struct vm_area_struct *vma,
+				    unsigned long address,
+				    int *type, unsigned long ps_offs)
+{
+	struct page *page = NOPAGE_SIGBUS;
+	int fault_type = VM_FAULT_SIGBUS;
+	struct spu_context *ctx = vma->vm_file->private_data;
+	unsigned long offset = address - vma->vm_start;
+	unsigned long area;
+	int ret;
+
+	offset += vma->vm_pgoff << PAGE_SHIFT;
+	if (offset >= 0x4000)
+		goto out;
+
+	ret = spu_acquire_runnable(ctx);
+	if (ret)
+		goto out;
+
+	area = ctx->spu->problem_phys + ps_offs;
+	page = pfn_to_page((area + offset) >> PAGE_SHIFT);
+	fault_type = VM_FAULT_MINOR;
+	page_cache_get(page);
+
+	spu_release(ctx);
+
+      out:
+	if (type)
+		*type = fault_type;
+
+	return page;
+}
+
+static struct page *spufs_cntl_mmap_nopage(struct vm_area_struct *vma,
+					   unsigned long address, int *type)
+{
+	return spufs_ps_nopage(vma, address, type, 0x4000);
+}
+
+static struct vm_operations_struct spufs_cntl_mmap_vmops = {
+	.nopage = spufs_cntl_mmap_nopage,
+};
+
+/*
+ * mmap support for problem state control area [0x4000 - 0x4fff].
+ * Mapping this area requires that the application have CAP_SYS_RAWIO,
+ * as these registers require special care when read/writing.
+ */
+static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	if (!(vma->vm_flags & VM_SHARED))
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	vma->vm_flags |= VM_RESERVED;
+	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+				     | _PAGE_NO_CACHE);
+
+	vma->vm_ops = &spufs_cntl_mmap_vmops;
+	return 0;
+}
+#endif
+
+static int spufs_cntl_open(struct inode *inode, struct file *file)
+{
+	struct spufs_inode_info *i = SPUFS_I(inode);
+	struct spu_context *ctx = i->i_ctx;
+
+	file->private_data = ctx;
+	file->f_mapping = inode->i_mapping;
+	ctx->cntl = inode->i_mapping;
+	return 0;
+}
+
+static ssize_t
+spufs_cntl_read(struct file *file, char __user *buffer,
+		size_t size, loff_t *pos)
+{
+	/* FIXME: read from spu status */
+	return -EINVAL;
+}
+
+static ssize_t
+spufs_cntl_write(struct file *file, const char __user *buffer,
+		 size_t size, loff_t *pos)
+{
+	/* FIXME: write to runctl bit */
+	return -EINVAL;
+}
+
+static struct file_operations spufs_cntl_fops = {
+	.open = spufs_cntl_open,
+	.read = spufs_cntl_read,
+	.write = spufs_cntl_write,
+#ifdef CONFIG_SPUFS_MMAP
+	.mmap = spufs_cntl_mmap,
+#endif
+};
+
 static int
 spufs_regs_open(struct inode *inode, struct file *file)
 {
@@ -501,6 +607,16 @@
 	.read	= spufs_wbox_stat_read,
 };
 
+static int spufs_signal1_open(struct inode *inode, struct file *file)
+{
+	struct spufs_inode_info *i = SPUFS_I(inode);
+	struct spu_context *ctx = i->i_ctx;
+	file->private_data = ctx;
+	file->f_mapping = inode->i_mapping;
+	ctx->signal1 = inode->i_mapping;
+	return nonseekable_open(inode, file);
+}
+
 static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
 			size_t len, loff_t *pos)
 {
@@ -541,12 +657,50 @@
 	return 4;
 }
 
+#ifdef CONFIG_SPUFS_MMAP
+static struct page *spufs_signal1_mmap_nopage(struct vm_area_struct *vma,
+					      unsigned long address, int *type)
+{
+	return spufs_ps_nopage(vma, address, type, 0x14000);
+}
+
+static struct vm_operations_struct spufs_signal1_mmap_vmops = {
+	.nopage = spufs_signal1_mmap_nopage,
+};
+
+static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	if (!(vma->vm_flags & VM_SHARED))
+		return -EINVAL;
+
+	vma->vm_flags |= VM_RESERVED;
+	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+				     | _PAGE_NO_CACHE);
+
+	vma->vm_ops = &spufs_signal1_mmap_vmops;
+	return 0;
+}
+#endif
+
 static struct file_operations spufs_signal1_fops = {
-	.open = spufs_pipe_open,
+	.open = spufs_signal1_open,
 	.read = spufs_signal1_read,
 	.write = spufs_signal1_write,
+#ifdef CONFIG_SPUFS_MMAP
+	.mmap = spufs_signal1_mmap,
+#endif
 };
 
+static int spufs_signal2_open(struct inode *inode, struct file *file)
+{
+	struct spufs_inode_info *i = SPUFS_I(inode);
+	struct spu_context *ctx = i->i_ctx;
+	file->private_data = ctx;
+	file->f_mapping = inode->i_mapping;
+	ctx->signal2 = inode->i_mapping;
+	return nonseekable_open(inode, file);
+}
+
 static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
 			size_t len, loff_t *pos)
 {
@@ -589,10 +743,39 @@
 	return 4;
 }
 
+#ifdef CONFIG_SPUFS_MMAP
+static struct page *spufs_signal2_mmap_nopage(struct vm_area_struct *vma,
+					      unsigned long address, int *type)
+{
+	return spufs_ps_nopage(vma, address, type, 0x1c000);
+}
+
+static struct vm_operations_struct spufs_signal2_mmap_vmops = {
+	.nopage = spufs_signal2_mmap_nopage,
+};
+
+static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	if (!(vma->vm_flags & VM_SHARED))
+		return -EINVAL;
+
+	/* FIXME: */
+	vma->vm_flags |= VM_RESERVED;
+	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+				     | _PAGE_NO_CACHE);
+
+	vma->vm_ops = &spufs_signal2_mmap_vmops;
+	return 0;
+}
+#endif
+
 static struct file_operations spufs_signal2_fops = {
-	.open = spufs_pipe_open,
+	.open = spufs_signal2_open,
 	.read = spufs_signal2_read,
 	.write = spufs_signal2_write,
+#ifdef CONFIG_SPUFS_MMAP
+	.mmap = spufs_signal2_mmap,
+#endif
 };
 
 static void spufs_signal1_type_set(void *data, u64 val)
@@ -641,6 +824,332 @@
 DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
 					spufs_signal2_type_set, "%llu");
 
+#ifdef CONFIG_SPUFS_MMAP
+static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma,
+					   unsigned long address, int *type)
+{
+	return spufs_ps_nopage(vma, address, type, 0x3000);
+}
+
+static struct vm_operations_struct spufs_mfc_mmap_vmops = {
+	.nopage = spufs_mfc_mmap_nopage,
+};
+
+/*
+ * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
+ * Mapping this area requires that the application have CAP_SYS_RAWIO,
+ * as these registers require special care when read/writing.
+ */
+static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	if (!(vma->vm_flags & VM_SHARED))
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	vma->vm_flags |= VM_RESERVED;
+	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+				     | _PAGE_NO_CACHE);
+
+	vma->vm_ops = &spufs_mfc_mmap_vmops;
+	return 0;
+}
+#endif
+
+static int spufs_mfc_open(struct inode *inode, struct file *file)
+{
+	struct spufs_inode_info *i = SPUFS_I(inode);
+	struct spu_context *ctx = i->i_ctx;
+
+	/* we don't want to deal with DMA into other processes */
+	if (ctx->owner != current->mm)
+		return -EINVAL;
+
+	if (atomic_read(&inode->i_count) != 1)
+		return -EBUSY;
+
+	file->private_data = ctx;
+	return nonseekable_open(inode, file);
+}
+
+/* interrupt-level mfc callback function. */
+void spufs_mfc_callback(struct spu *spu)
+{
+	struct spu_context *ctx = spu->ctx;
+
+	wake_up_all(&ctx->mfc_wq);
+
+	pr_debug("%s %s\n", __FUNCTION__, spu->name);
+	if (ctx->mfc_fasync) {
+		u32 free_elements, tagstatus;
+		unsigned int mask;
+
+		/* no need for spu_acquire in interrupt context */
+		free_elements = ctx->ops->get_mfc_free_elements(ctx);
+		tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
+
+		mask = 0;
+		if (free_elements & 0xffff)
+			mask |= POLLOUT;
+		if (tagstatus & ctx->tagwait)
+			mask |= POLLIN;
+
+		kill_fasync(&ctx->mfc_fasync, SIGIO, mask);
+	}
+}
+
+static int spufs_read_mfc_tagstatus(struct spu_context *ctx, u32 *status)
+{
+	/* See if there is one tag group is complete */
+	/* FIXME we need locking around tagwait */
+	*status = ctx->ops->read_mfc_tagstatus(ctx) & ctx->tagwait;
+	ctx->tagwait &= ~*status;
+	if (*status)
+		return 1;
+
+	/* enable interrupt waiting for any tag group,
+	   may silently fail if interrupts are already enabled */
+	ctx->ops->set_mfc_query(ctx, ctx->tagwait, 1);
+	return 0;
+}
+
+static ssize_t spufs_mfc_read(struct file *file, char __user *buffer,
+			size_t size, loff_t *pos)
+{
+	struct spu_context *ctx = file->private_data;
+	int ret = -EINVAL;
+	u32 status;
+
+	if (size != 4)
+		goto out;
+
+	spu_acquire(ctx);
+	if (file->f_flags & O_NONBLOCK) {
+		status = ctx->ops->read_mfc_tagstatus(ctx);
+		if (!(status & ctx->tagwait))
+			ret = -EAGAIN;
+		else
+			ctx->tagwait &= ~status;
+	} else {
+		ret = spufs_wait(ctx->mfc_wq,
+			   spufs_read_mfc_tagstatus(ctx, &status));
+	}
+	spu_release(ctx);
+
+	if (ret)
+		goto out;
+
+	ret = 4;
+	if (copy_to_user(buffer, &status, 4))
+		ret = -EFAULT;
+
+out:
+	return ret;
+}
+
+static int spufs_check_valid_dma(struct mfc_dma_command *cmd)
+{
+	pr_debug("queueing DMA %x %lx %x %x %x\n", cmd->lsa,
+		 cmd->ea, cmd->size, cmd->tag, cmd->cmd);
+
+	switch (cmd->cmd) {
+	case MFC_PUT_CMD:
+	case MFC_PUTF_CMD:
+	case MFC_PUTB_CMD:
+	case MFC_GET_CMD:
+	case MFC_GETF_CMD:
+	case MFC_GETB_CMD:
+		break;
+	default:
+		pr_debug("invalid DMA opcode %x\n", cmd->cmd);
+		return -EIO;
+	}
+
+	if ((cmd->lsa & 0xf) != (cmd->ea &0xf)) {
+		pr_debug("invalid DMA alignment, ea %lx lsa %x\n",
+				cmd->ea, cmd->lsa);
+		return -EIO;
+	}
+
+	switch (cmd->size & 0xf) {
+	case 1:
+		break;
+	case 2:
+		if (cmd->lsa & 1)
+			goto error;
+		break;
+	case 4:
+		if (cmd->lsa & 3)
+			goto error;
+		break;
+	case 8:
+		if (cmd->lsa & 7)
+			goto error;
+		break;
+	case 0:
+		if (cmd->lsa & 15)
+			goto error;
+		break;
+	error:
+	default:
+		pr_debug("invalid DMA alignment %x for size %x\n",
+			cmd->lsa & 0xf, cmd->size);
+		return -EIO;
+	}
+
+	if (cmd->size > 16 * 1024) {
+		pr_debug("invalid DMA size %x\n", cmd->size);
+		return -EIO;
+	}
+
+	if (cmd->tag & 0xfff0) {
+		/* we reserve the higher tag numbers for kernel use */
+		pr_debug("invalid DMA tag\n");
+		return -EIO;
+	}
+
+	if (cmd->class) {
+		/* not supported in this version */
+		pr_debug("invalid DMA class\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int spu_send_mfc_command(struct spu_context *ctx,
+				struct mfc_dma_command cmd,
+				int *error)
+{
+	*error = ctx->ops->send_mfc_command(ctx, &cmd);
+	if (*error == -EAGAIN) {
+		/* wait for any tag group to complete
+		   so we have space for the new command */
+		ctx->ops->set_mfc_query(ctx, ctx->tagwait, 1);
+		/* try again, because the queue might be
+		   empty again */
+		*error = ctx->ops->send_mfc_command(ctx, &cmd);
+		if (*error == -EAGAIN)
+			return 0;
+	}
+	return 1;
+}
+
+static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer,
+			size_t size, loff_t *pos)
+{
+	struct spu_context *ctx = file->private_data;
+	struct mfc_dma_command cmd;
+	int ret = -EINVAL;
+
+	if (size != sizeof cmd)
+		goto out;
+
+	ret = -EFAULT;
+	if (copy_from_user(&cmd, buffer, sizeof cmd))
+		goto out;
+
+	ret = spufs_check_valid_dma(&cmd);
+	if (ret)
+		goto out;
+
+	spu_acquire_runnable(ctx);
+	if (file->f_flags & O_NONBLOCK) {
+		ret = ctx->ops->send_mfc_command(ctx, &cmd);
+	} else {
+		int status;
+		ret = spufs_wait(ctx->mfc_wq,
+				 spu_send_mfc_command(ctx, cmd, &status));
+		if (status)
+			ret = status;
+	}
+	spu_release(ctx);
+
+	if (ret)
+		goto out;
+
+	ctx->tagwait |= 1 << cmd.tag;
+
+out:
+	return ret;
+}
+
+static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait)
+{
+	struct spu_context *ctx = file->private_data;
+	u32 free_elements, tagstatus;
+	unsigned int mask;
+
+	spu_acquire(ctx);
+	ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2);
+	free_elements = ctx->ops->get_mfc_free_elements(ctx);
+	tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
+	spu_release(ctx);
+
+	poll_wait(file, &ctx->mfc_wq, wait);
+
+	mask = 0;
+	if (free_elements & 0xffff)
+		mask |= POLLOUT | POLLWRNORM;
+	if (tagstatus & ctx->tagwait)
+		mask |= POLLIN | POLLRDNORM;
+
+	pr_debug("%s: free %d tagstatus %d tagwait %d\n", __FUNCTION__,
+		free_elements, tagstatus, ctx->tagwait);
+
+	return mask;
+}
+
+static int spufs_mfc_flush(struct file *file)
+{
+	struct spu_context *ctx = file->private_data;
+	int ret;
+
+	spu_acquire(ctx);
+#if 0
+/* this currently hangs */
+	ret = spufs_wait(ctx->mfc_wq,
+			 ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2));
+	if (ret)
+		goto out;
+	ret = spufs_wait(ctx->mfc_wq,
+			 ctx->ops->read_mfc_tagstatus(ctx) == ctx->tagwait);
+out:
+#else
+	ret = 0;
+#endif
+	spu_release(ctx);
+
+	return ret;
+}
+
+static int spufs_mfc_fsync(struct file *file, struct dentry *dentry,
+			   int datasync)
+{
+	return spufs_mfc_flush(file);
+}
+
+static int spufs_mfc_fasync(int fd, struct file *file, int on)
+{
+	struct spu_context *ctx = file->private_data;
+
+	return fasync_helper(fd, file, on, &ctx->mfc_fasync);
+}
+
+static struct file_operations spufs_mfc_fops = {
+	.open	 = spufs_mfc_open,
+	.read	 = spufs_mfc_read,
+	.write	 = spufs_mfc_write,
+	.poll	 = spufs_mfc_poll,
+	.flush	 = spufs_mfc_flush,
+	.fsync	 = spufs_mfc_fsync,
+	.fasync	 = spufs_mfc_fasync,
+#ifdef CONFIG_SPUFS_MMAP
+	.mmap	 = spufs_mfc_mmap,
+#endif
+};
+
 static void spufs_npc_set(void *data, u64 val)
 {
 	struct spu_context *ctx = data;
@@ -783,6 +1292,8 @@
 	{ "signal2", &spufs_signal2_fops, 0666, },
 	{ "signal1_type", &spufs_signal1_type, 0666, },
 	{ "signal2_type", &spufs_signal2_type, 0666, },
+	{ "mfc", &spufs_mfc_fops, 0666, },
+	{ "cntl", &spufs_cntl_fops,  0666, },
 	{ "npc", &spufs_npc_ops, 0666, },
 	{ "fpcr", &spufs_fpcr_fops, 0666, },
 	{ "decr", &spufs_decr_ops, 0666, },
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c
index 5445719..a13a8b5 100644
--- a/arch/powerpc/platforms/cell/spufs/hw_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c
@@ -232,6 +232,59 @@
 	spin_unlock_irq(&ctx->spu->register_lock);
 }
 
+static int spu_hw_set_mfc_query(struct spu_context * ctx, u32 mask, u32 mode)
+{
+	struct spu_problem *prob = ctx->spu->problem;
+	int ret;
+
+	spin_lock_irq(&ctx->spu->register_lock);
+	ret = -EAGAIN;
+	if (in_be32(&prob->dma_querytype_RW))
+		goto out;
+	ret = 0;
+	out_be32(&prob->dma_querymask_RW, mask);
+	out_be32(&prob->dma_querytype_RW, mode);
+out:
+	spin_unlock_irq(&ctx->spu->register_lock);
+	return ret;
+}
+
+static u32 spu_hw_read_mfc_tagstatus(struct spu_context * ctx)
+{
+	return in_be32(&ctx->spu->problem->dma_tagstatus_R);
+}
+
+static u32 spu_hw_get_mfc_free_elements(struct spu_context *ctx)
+{
+	return in_be32(&ctx->spu->problem->dma_qstatus_R);
+}
+
+static int spu_hw_send_mfc_command(struct spu_context *ctx,
+					struct mfc_dma_command *cmd)
+{
+	u32 status;
+	struct spu_problem *prob = ctx->spu->problem;
+
+	spin_lock_irq(&ctx->spu->register_lock);
+	out_be32(&prob->mfc_lsa_W, cmd->lsa);
+	out_be64(&prob->mfc_ea_W, cmd->ea);
+	out_be32(&prob->mfc_union_W.by32.mfc_size_tag32,
+				cmd->size << 16 | cmd->tag);
+	out_be32(&prob->mfc_union_W.by32.mfc_class_cmd32,
+				cmd->class << 16 | cmd->cmd);
+	status = in_be32(&prob->mfc_union_W.by32.mfc_class_cmd32);
+	spin_unlock_irq(&ctx->spu->register_lock);
+
+	switch (status & 0xffff) {
+	case 0:
+		return 0;
+	case 2:
+		return -EAGAIN;
+	default:
+		return -EINVAL;
+	}
+}
+
 struct spu_context_ops spu_hw_ops = {
 	.mbox_read = spu_hw_mbox_read,
 	.mbox_stat_read = spu_hw_mbox_stat_read,
@@ -252,4 +305,8 @@
 	.get_ls = spu_hw_get_ls,
 	.runcntl_write = spu_hw_runcntl_write,
 	.runcntl_stop = spu_hw_runcntl_stop,
+	.set_mfc_query = spu_hw_set_mfc_query,
+	.read_mfc_tagstatus = spu_hw_read_mfc_tagstatus,
+	.get_mfc_free_elements = spu_hw_get_mfc_free_elements,
+	.send_mfc_command = spu_hw_send_mfc_command,
 };
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 5be40aa..d955419 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -241,7 +241,7 @@
 		inode->i_gid = dir->i_gid;
 		inode->i_mode &= S_ISGID;
 	}
-	ctx = alloc_spu_context(inode->i_mapping);
+	ctx = alloc_spu_context();
 	SPUFS_I(inode)->i_ctx = ctx;
 	if (!ctx)
 		goto out_iput;
@@ -442,7 +442,7 @@
 	.kill_sb = kill_litter_super,
 };
 
-static int spufs_init(void)
+static int __init spufs_init(void)
 {
 	int ret;
 	ret = -ENOMEM;
@@ -472,7 +472,7 @@
 }
 module_init(spufs_init);
 
-static void spufs_exit(void)
+static void __exit spufs_exit(void)
 {
 	spu_sched_exit();
 	unregister_spu_syscalls(&spufs_calls);
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 18ea886..c04e078 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -76,6 +76,90 @@
 	return 0;
 }
 
+/*
+ * SPU syscall restarting is tricky because we violate the basic
+ * assumption that the signal handler is running on the interrupted
+ * thread. Here instead, the handler runs on PowerPC user space code,
+ * while the syscall was called from the SPU.
+ * This means we can only do a very rough approximation of POSIX
+ * signal semantics.
+ */
+int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret,
+			  unsigned int *npc)
+{
+	int ret;
+
+	switch (*spu_ret) {
+	case -ERESTARTSYS:
+	case -ERESTARTNOINTR:
+		/*
+		 * Enter the regular syscall restarting for
+		 * sys_spu_run, then restart the SPU syscall
+		 * callback.
+		 */
+		*npc -= 8;
+		ret = -ERESTARTSYS;
+		break;
+	case -ERESTARTNOHAND:
+	case -ERESTART_RESTARTBLOCK:
+		/*
+		 * Restart block is too hard for now, just return -EINTR
+		 * to the SPU.
+		 * ERESTARTNOHAND comes from sys_pause, we also return
+		 * -EINTR from there.
+		 * Assume that we need to be restarted ourselves though.
+		 */
+		*spu_ret = -EINTR;
+		ret = -ERESTARTSYS;
+		break;
+	default:
+		printk(KERN_WARNING "%s: unexpected return code %ld\n",
+			__FUNCTION__, *spu_ret);
+		ret = 0;
+	}
+	return ret;
+}
+
+int spu_process_callback(struct spu_context *ctx)
+{
+	struct spu_syscall_block s;
+	u32 ls_pointer, npc;
+	char *ls;
+	long spu_ret;
+	int ret;
+
+	/* get syscall block from local store */
+	npc = ctx->ops->npc_read(ctx);
+	ls = ctx->ops->get_ls(ctx);
+	ls_pointer = *(u32*)(ls + npc);
+	if (ls_pointer > (LS_SIZE - sizeof(s)))
+		return -EFAULT;
+	memcpy(&s, ls + ls_pointer, sizeof (s));
+
+	/* do actual syscall without pinning the spu */
+	ret = 0;
+	spu_ret = -ENOSYS;
+	npc += 4;
+
+	if (s.nr_ret < __NR_syscalls) {
+		spu_release(ctx);
+		/* do actual system call from here */
+		spu_ret = spu_sys_callback(&s);
+		if (spu_ret <= -ERESTARTSYS) {
+			ret = spu_handle_restartsys(ctx, &spu_ret, &npc);
+		}
+		spu_acquire(ctx);
+		if (ret == -ERESTARTSYS)
+			return ret;
+	}
+
+	/* write result, jump over indirect pointer */
+	memcpy(ls + ls_pointer, &spu_ret, sizeof (spu_ret));
+	ctx->ops->npc_write(ctx, npc);
+	ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
+	return ret;
+}
+
 static inline int spu_process_events(struct spu_context *ctx)
 {
 	struct spu *spu = ctx->spu;
@@ -107,6 +191,13 @@
 		ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status));
 		if (unlikely(ret))
 			break;
+		if ((*status & SPU_STATUS_STOPPED_BY_STOP) &&
+		    (*status >> SPU_STOP_STATUS_SHIFT == 0x2104)) {
+			ret = spu_process_callback(ctx);
+			if (ret)
+				break;
+			*status &= ~SPU_STATUS_STOPPED_BY_STOP;
+		}
 		if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
 			ret = spu_reacquire_runnable(ctx, npc, status);
 			if (ret)
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 963182f..bf652cd 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -180,6 +180,7 @@
 	spu->ibox_callback = spufs_ibox_callback;
 	spu->wbox_callback = spufs_wbox_callback;
 	spu->stop_callback = spufs_stop_callback;
+	spu->mfc_callback = spufs_mfc_callback;
 	mb();
 	spu_unmap_mappings(ctx);
 	spu_restore(&ctx->csa, spu);
@@ -197,6 +198,7 @@
 	spu->ibox_callback = NULL;
 	spu->wbox_callback = NULL;
 	spu->stop_callback = NULL;
+	spu->mfc_callback = NULL;
 	spu->mm = NULL;
 	spu->pid = 0;
 	spu->prio = MAX_PRIO;
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index db2601f..4485738 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -43,7 +43,11 @@
 	struct spu *spu;		  /* pointer to a physical SPU */
 	struct spu_state csa;		  /* SPU context save area. */
 	spinlock_t mmio_lock;		  /* protects mmio access */
-	struct address_space *local_store;/* local store backing store */
+	struct address_space *local_store; /* local store mapping.  */
+	struct address_space *mfc;	   /* 'mfc' area mappings. */
+	struct address_space *cntl; 	   /* 'control' area mappings. */
+	struct address_space *signal1; 	   /* 'signal1' area mappings. */
+	struct address_space *signal2; 	   /* 'signal2' area mappings. */
 
 	enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
 	struct rw_semaphore state_sema;
@@ -55,13 +59,27 @@
 	wait_queue_head_t ibox_wq;
 	wait_queue_head_t wbox_wq;
 	wait_queue_head_t stop_wq;
+	wait_queue_head_t mfc_wq;
 	struct fasync_struct *ibox_fasync;
 	struct fasync_struct *wbox_fasync;
+	struct fasync_struct *mfc_fasync;
+	u32 tagwait;
 	struct spu_context_ops *ops;
 	struct work_struct reap_work;
 	u64 flags;
 };
 
+struct mfc_dma_command {
+	int32_t pad;	/* reserved */
+	uint32_t lsa;	/* local storage address */
+	uint64_t ea;	/* effective address */
+	uint16_t size;	/* transfer size */
+	uint16_t tag;	/* command tag */
+	uint16_t class;	/* class ID */
+	uint16_t cmd;	/* command opcode */
+};
+
+
 /* SPU context query/set operations. */
 struct spu_context_ops {
 	int (*mbox_read) (struct spu_context * ctx, u32 * data);
@@ -84,6 +102,11 @@
 	char*(*get_ls) (struct spu_context * ctx);
 	void (*runcntl_write) (struct spu_context * ctx, u32 data);
 	void (*runcntl_stop) (struct spu_context * ctx);
+	int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode);
+	u32 (*read_mfc_tagstatus)(struct spu_context * ctx);
+	u32 (*get_mfc_free_elements)(struct spu_context *ctx);
+	int (*send_mfc_command)(struct spu_context *ctx,
+					struct mfc_dma_command *cmd);
 };
 
 extern struct spu_context_ops spu_hw_ops;
@@ -106,7 +129,7 @@
 extern struct file_operations spufs_context_fops;
 
 /* context management */
-struct spu_context * alloc_spu_context(struct address_space *local_store);
+struct spu_context * alloc_spu_context(void);
 void destroy_spu_context(struct kref *kref);
 struct spu_context * get_spu_context(struct spu_context *ctx);
 int put_spu_context(struct spu_context *ctx);
@@ -159,5 +182,6 @@
 void spufs_ibox_callback(struct spu *spu);
 void spufs_wbox_callback(struct spu *spu);
 void spufs_stop_callback(struct spu *spu);
+void spufs_mfc_callback(struct spu *spu);
 
 #endif
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 212db28..97898d5 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -2145,7 +2145,8 @@
 	csa->priv1.int_mask_class1_RW = CLASS1_ENABLE_SEGMENT_FAULT_INTR |
 	    CLASS1_ENABLE_STORAGE_FAULT_INTR;
 	csa->priv1.int_mask_class2_RW = CLASS2_ENABLE_SPU_STOP_INTR |
-	    CLASS2_ENABLE_SPU_HALT_INTR;
+	    CLASS2_ENABLE_SPU_HALT_INTR |
+	    CLASS2_ENABLE_SPU_DMA_TAG_GROUP_COMPLETE_INTR;
 }
 
 static void init_priv2(struct spu_state *csa)
diff --git a/arch/powerpc/platforms/chrp/chrp.h b/arch/powerpc/platforms/chrp/chrp.h
index 814f547..63f0aee 100644
--- a/arch/powerpc/platforms/chrp/chrp.h
+++ b/arch/powerpc/platforms/chrp/chrp.h
@@ -8,4 +8,4 @@
 extern long chrp_time_init(void);
 
 extern void chrp_find_bridges(void);
-extern void chrp_event_scan(void);
+extern void chrp_event_scan(unsigned long);
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 8bf4307..23a2017 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -35,6 +35,7 @@
 #include <linux/root_dev.h>
 #include <linux/initrd.h>
 #include <linux/module.h>
+#include <linux/timer.h>
 
 #include <asm/io.h>
 #include <asm/pgtable.h>
@@ -61,6 +62,10 @@
 
 struct mpic *chrp_mpic;
 
+/* Used for doing CHRP event-scans */
+DEFINE_PER_CPU(struct timer_list, heartbeat_timer);
+unsigned long event_scan_interval;
+
 /*
  * XXX this should be in xmon.h, but putting it there means xmon.h
  * has to include <linux/interrupt.h> (to get irqreturn_t), which
@@ -229,8 +234,6 @@
 {
 	struct device_node *root = find_path_device ("/");
 	char *machine = NULL;
-	struct device_node *device;
-	unsigned int *p = NULL;
 
 	/* init to some ~sane value until calibrate_delay() runs */
 	loops_per_jiffy = 50000000/HZ;
@@ -287,23 +290,12 @@
 	 */
 	sio_init();
 
-	/* Get the event scan rate for the rtas so we know how
-	 * often it expects a heartbeat. -- Cort
-	 */
-	device = find_devices("rtas");
-	if (device)
-		p = (unsigned int *) get_property
-			(device, "rtas-event-scan-rate", NULL);
-	if (p && *p) {
-		ppc_md.heartbeat = chrp_event_scan;
-		ppc_md.heartbeat_reset = HZ / (*p * 30) - 1;
-		ppc_md.heartbeat_count = 1;
-		printk("RTAS Event Scan Rate: %u (%lu jiffies)\n",
-		       *p, ppc_md.heartbeat_reset);
-	}
-
 	pci_create_OF_bus_map();
 
+#ifdef CONFIG_SMP
+	smp_ops = &chrp_smp_ops;
+#endif /* CONFIG_SMP */
+
 	/*
 	 * Print the banner, then scroll down so boot progress
 	 * can be printed.  -- Cort
@@ -312,7 +304,7 @@
 }
 
 void
-chrp_event_scan(void)
+chrp_event_scan(unsigned long unused)
 {
 	unsigned char log[1024];
 	int ret = 0;
@@ -320,7 +312,8 @@
 	/* XXX: we should loop until the hardware says no more error logs -- Cort */
 	rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0,
 		  __pa(log), 1024);
-	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+	mod_timer(&__get_cpu_var(heartbeat_timer),
+		  jiffies + event_scan_interval);
 }
 
 /*
@@ -465,6 +458,9 @@
 void __init
 chrp_init2(void)
 {
+	struct device_node *device;
+	unsigned int *p = NULL;
+
 #ifdef CONFIG_NVRAM
 	chrp_nvram_init();
 #endif
@@ -476,12 +472,53 @@
 	request_region(0x80,0x10,"dma page reg");
 	request_region(0xc0,0x20,"dma2");
 
+	/* Get the event scan rate for the rtas so we know how
+	 * often it expects a heartbeat. -- Cort
+	 */
+	device = find_devices("rtas");
+	if (device)
+		p = (unsigned int *) get_property
+			(device, "rtas-event-scan-rate", NULL);
+	if (p && *p) {
+		/*
+		 * Arrange to call chrp_event_scan at least *p times
+		 * per minute.  We use 59 rather than 60 here so that
+		 * the rate will be slightly higher than the minimum.
+		 * This all assumes we don't do hotplug CPU on any
+		 * machine that needs the event scans done.
+		 */
+		unsigned long interval, offset;
+		int cpu, ncpus;
+		struct timer_list *timer;
+
+		interval = HZ * 59 / *p;
+		offset = HZ;
+		ncpus = num_online_cpus();
+		event_scan_interval = ncpus * interval;
+		for (cpu = 0; cpu < ncpus; ++cpu) {
+			timer = &per_cpu(heartbeat_timer, cpu);
+			setup_timer(timer, chrp_event_scan, 0);
+			timer->expires = jiffies + offset;
+			add_timer_on(timer, cpu);
+			offset += interval;
+		}
+		printk("RTAS Event Scan Rate: %u (%lu jiffies)\n",
+		       *p, interval);
+	}
+
 	if (ppc_md.progress)
 		ppc_md.progress("  Have fun!    ", 0x7777);
 }
 
-void __init chrp_init(void)
+static int __init chrp_probe(void)
 {
+ 	char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
+ 					  "device_type", NULL);
+ 	if (dtype == NULL)
+ 		return 0;
+ 	if (strcmp(dtype, "chrp"))
+		return 0;
+
 	ISA_DMA_THRESHOLD = ~0L;
 	DMA_MODE_READ = 0x44;
 	DMA_MODE_WRITE = 0x48;
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index fa45506..6ce8a40 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -675,18 +675,20 @@
 void __init iSeries_init_IRQ(void) { }
 #endif
 
-static int __init iseries_probe(int platform)
+static int __init iseries_probe(void)
 {
-	if (PLATFORM_ISERIES_LPAR != platform)
+	unsigned long root = of_get_flat_dt_root();
+	if (!of_flat_dt_is_compatible(root, "IBM,iSeries"))
 		return 0;
 
-	ppc64_firmware_features |= FW_FEATURE_ISERIES;
-	ppc64_firmware_features |= FW_FEATURE_LPAR;
+	powerpc_firmware_features |= FW_FEATURE_ISERIES;
+	powerpc_firmware_features |= FW_FEATURE_LPAR;
 
 	return 1;
 }
 
-struct machdep_calls __initdata iseries_md = {
+define_machine(iseries) {
+	.name		= "iSeries",
 	.setup_arch	= iSeries_setup_arch,
 	.show_cpuinfo	= iSeries_show_cpuinfo,
 	.init_IRQ	= iSeries_init_IRQ,
@@ -930,7 +932,6 @@
 
 	/* /chosen */
 	dt_start_node(dt, "chosen");
-	dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR);
 	dt_prop_str(dt, "bootargs", cmd_line);
 	if (cmd_mem_limit)
 		dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit);
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index ec5c1e1..24c0aef4 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -259,9 +259,10 @@
 /*
  * Called very early, MMU is off, device-tree isn't unflattened
  */
-static int __init maple_probe(int platform)
+static int __init maple_probe(void)
 {
-	if (platform != PLATFORM_MAPLE)
+	unsigned long root = of_get_flat_dt_root();
+	if (!of_flat_dt_is_compatible(root, "Momentum,Maple"))
 		return 0;
 	/*
 	 * On U3, the DART (iommu) must be allocated now since it
@@ -274,7 +275,8 @@
 	return 1;
 }
 
-struct machdep_calls __initdata maple_md = {
+define_machine(maple_md) {
+	.name			= "Maple",
 	.probe			= maple_probe,
 	.setup_arch		= maple_setup_arch,
 	.init_early		= maple_init_early,
@@ -290,7 +292,7 @@
        	.get_rtc_time		= maple_get_rtc_time,
       	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= maple_progress,
-	.idle_loop		= native_idle,
+	.power_save		= power4_idle,
 #ifdef CONFIG_KEXEC
 	.machine_kexec		= default_machine_kexec,
 	.machine_kexec_prepare	= default_machine_kexec_prepare,
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c
index fa8b4d7..eacbfd9 100644
--- a/arch/powerpc/platforms/powermac/bootx_init.c
+++ b/arch/powerpc/platforms/powermac/bootx_init.c
@@ -161,9 +161,7 @@
 static void __init bootx_add_chosen_props(unsigned long base,
 					  unsigned long *mem_end)
 {
-	u32 val = _MACH_Pmac;
-
-	bootx_dt_add_prop("linux,platform", &val, 4, mem_end);
+	u32 val;
 
 	if (bootx_info->kernelParamsOffset) {
 		char *args = (char *)((unsigned long)bootx_info) +
@@ -493,7 +491,7 @@
 		    && (strcmp(model, "iMac,1") == 0
 			|| strcmp(model, "PowerMac1,1") == 0)) {
 			bootx_printf("iMac,1 detected, shutting down USB \n");
-			out_le32((unsigned *)0x80880008, 1);	/* XXX */
+			out_le32((unsigned __iomem *)0x80880008, 1);	/* XXX */
 		}
 	}
 
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index e49eddd..a5063cd 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -2951,7 +2951,7 @@
 
 void pmac_set_early_video_resume(void (*proc)(void *data), void *data)
 {
-	if (_machine != _MACH_Pmac)
+	if (!machine_is(powermac))
 		return;
 	preempt_disable();
 	pmac_early_vresume_proc = proc;
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 87eb6bb..e14f9ac 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -1457,6 +1457,9 @@
 		return 0;
 	i2c_inited = 1;
 
+	if (!machine_is(powermac))
+		return 0;
+
 	/* Probe keywest-i2c busses */
 	kw_i2c_probe();
 
diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c
index 5fd2899..262f967 100644
--- a/arch/powerpc/platforms/powermac/nvram.c
+++ b/arch/powerpc/platforms/powermac/nvram.c
@@ -74,7 +74,7 @@
  * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
  */
 static int nvram_naddrs;
-static volatile unsigned char *nvram_data;
+static volatile unsigned char __iomem *nvram_data;
 static int is_core_99;
 static int core99_bank = 0;
 static int nvram_partitions[3];
@@ -148,7 +148,7 @@
 }
 
 #ifdef CONFIG_PPC32
-static volatile unsigned char *nvram_addr;
+static volatile unsigned char __iomem *nvram_addr;
 static int nvram_mult;
 
 static unsigned char direct_nvram_read_byte(int addr)
@@ -285,7 +285,7 @@
 	int stat, i;
 	unsigned long timeout;
 
-	u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+	u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
 
        	DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank);
 
@@ -317,7 +317,7 @@
 	int i, stat = 0;
 	unsigned long timeout;
 
-	u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+	u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
 
        	DBG("nvram: Sharp/Micron Writing bank %d...\n", bank);
 
@@ -352,7 +352,7 @@
 	int i, stat = 0;
 	unsigned long timeout;
 
-	u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+	u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
 
        	DBG("nvram: AMD Erasing bank %d...\n", bank);
 
@@ -399,7 +399,7 @@
 	int i, stat = 0;
 	unsigned long timeout;
 
-	u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+	u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
 
        	DBG("nvram: AMD Writing bank %d...\n", bank);
 
@@ -597,7 +597,7 @@
 	}
 
 #ifdef CONFIG_PPC32
-	if (_machine == _MACH_chrp && nvram_naddrs == 1) {
+	if (machine_is(chrp) && nvram_naddrs == 1) {
 		nvram_data = ioremap(r1.start, s1);
 		nvram_mult = 1;
 		ppc_md.nvram_read_val	= direct_nvram_read_byte;
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index de3f30e..f5d8d15 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -1201,7 +1201,7 @@
 #ifdef CONFIG_PPC32
 void pmac_pci_fixup_cardbus(struct pci_dev* dev)
 {
-	if (_machine != _MACH_Pmac)
+	if (!machine_is(powermac))
 		return;
 	/*
 	 * Fix the interrupt routing on the various cardbus bridges
@@ -1244,8 +1244,9 @@
         * On PowerMacs, we try to switch any PCI ATA controller to
 	* fully native mode
         */
-	if (_machine != _MACH_Pmac)
+	if (!machine_is(powermac))
 		return;
+
 	/* Some controllers don't have the class IDE */
 	if (dev->vendor == PCI_VENDOR_ID_PROMISE)
 		switch(dev->device) {
diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c
index 9b7150f..a3bd3e7 100644
--- a/arch/powerpc/platforms/powermac/pfunc_base.c
+++ b/arch/powerpc/platforms/powermac/pfunc_base.c
@@ -336,6 +336,8 @@
 		return 0;
 	pfbase_inited = 1;
 
+	if (!machine_is(powermac))
+		return 0;
 
 	DBG("Installing base platform functions...\n");
 
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 385aab9..4d15e39 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -350,6 +350,13 @@
 		smp_ops = &psurge_smp_ops;
 #endif
 #endif /* CONFIG_SMP */
+
+#ifdef CONFIG_ADB
+	if (strstr(cmd_line, "adb_sync")) {
+		extern int __adb_probe_sync;
+		__adb_probe_sync = 1;
+	}
+#endif /* CONFIG_ADB */
 }
 
 char *bootpath;
@@ -576,30 +583,6 @@
 	pmac_power_off();
 }
 
-#ifdef CONFIG_PPC32
-void __init pmac_init(void)
-{
-	/* isa_io_base gets set in pmac_pci_init */
-	isa_mem_base = PMAC_ISA_MEM_BASE;
-	pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
-	ISA_DMA_THRESHOLD = ~0L;
-	DMA_MODE_READ = 1;
-	DMA_MODE_WRITE = 2;
-
-	ppc_md = pmac_md;
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
-        ppc_ide_md.ide_init_hwif	= pmac_ide_init_hwif_ports;
-        ppc_ide_md.default_io_base	= pmac_ide_get_base;
-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
-#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
-
-	if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
-
-}
-#endif
-
 /* 
  * Early initialization.
  */
@@ -646,6 +629,12 @@
 {
 	struct device_node *np;
 
+	if (machine_is(chrp))
+		return -1;
+
+	if (!machine_is(powermac))
+		return 0;
+
 	np = of_find_node_by_name(NULL, "valkyrie");
 	if (np)
 		of_platform_device_create(np, "valkyrie", NULL);
@@ -666,12 +655,15 @@
 /*
  * Called very early, MMU is off, device-tree isn't unflattened
  */
-static int __init pmac_probe(int platform)
+static int __init pmac_probe(void)
 {
-#ifdef CONFIG_PPC64
-	if (platform != PLATFORM_POWERMAC)
+	unsigned long root = of_get_flat_dt_root();
+
+	if (!of_flat_dt_is_compatible(root, "Power Macintosh") &&
+	    !of_flat_dt_is_compatible(root, "MacRISC"))
 		return 0;
 
+#ifdef CONFIG_PPC64
 	/*
 	 * On U3, the DART (iommu) must be allocated now since it
 	 * has an impact on htab_initialize (due to the large page it
@@ -681,6 +673,23 @@
 	alloc_dart_table();
 #endif
 
+#ifdef CONFIG_PPC32
+	/* isa_io_base gets set in pmac_pci_init */
+	isa_mem_base = PMAC_ISA_MEM_BASE;
+	pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
+	ISA_DMA_THRESHOLD = ~0L;
+	DMA_MODE_READ = 1;
+	DMA_MODE_WRITE = 2;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+        ppc_ide_md.ide_init_hwif	= pmac_ide_init_hwif_ports;
+        ppc_ide_md.default_io_base	= pmac_ide_get_base;
+#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
+
+#endif /* CONFIG_PPC32 */
+
 #ifdef CONFIG_PMAC_SMU
 	/*
 	 * SMU based G5s need some memory below 2Gb, at least the current
@@ -709,10 +718,8 @@
 }
 #endif
 
-struct machdep_calls __initdata pmac_md = {
-#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
-	.cpu_die		= generic_mach_cpu_die,
-#endif
+define_machine(powermac) {
+	.name			= "PowerMac",
 	.probe			= pmac_probe,
 	.setup_arch		= pmac_setup_arch,
 	.init_early		= pmac_init_early,
@@ -733,7 +740,7 @@
 	.progress		= udbg_progress,
 #ifdef CONFIG_PPC64
 	.pci_probe_mode		= pmac_pci_probe_mode,
-	.idle_loop		= native_idle,
+	.power_save		= power4_idle,
 	.enable_pmcs		= power4_enable_pmcs,
 #ifdef CONFIG_KEXEC
 	.machine_kexec		= default_machine_kexec,
@@ -746,4 +753,7 @@
 	.pcibios_after_init	= pmac_pcibios_after_init,
 	.phys_mem_access_prot	= pci_phys_mem_access_prot,
 #endif
+#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
+	.cpu_die		= generic_mach_cpu_die,
+#endif
 };
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index 5d9afa1..890758a 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -336,10 +336,10 @@
  */
 void __init pmac_calibrate_decr(void)
 {
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) && defined(CONFIG_ADB_PMU)
 	/* XXX why here? */
 	pmu_register_sleep_notifier(&time_sleep_notifier);
-#endif /* CONFIG_PM */
+#endif
 
 	generic_calibrate_decr();
 
diff --git a/arch/powerpc/platforms/powermac/udbg_scc.c b/arch/powerpc/platforms/powermac/udbg_scc.c
index c4352a8..b4fa9f0 100644
--- a/arch/powerpc/platforms/powermac/udbg_scc.c
+++ b/arch/powerpc/platforms/powermac/udbg_scc.c
@@ -116,7 +116,7 @@
 	/* Setup for 57600 8N1 */
 	if (ch == ch_a)
 		addr += 0x20;
-	sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
+	sccc = ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
 	sccc += addr & ~PAGE_MASK;
 	sccd = sccc + 0x10;
 
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 2ab9dcd..9b2b1cb 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -1018,7 +1018,7 @@
 {
 	struct proc_dir_entry *e;
 
-	if (platform_is_pseries()) {
+	if (machine_is(pseries)) {
 		e = create_proc_entry("ppc64/eeh", 0, NULL);
 		if (e)
 			e->proc_fops = &proc_eeh_operations;
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index b811d5f..cc2495a 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -257,6 +257,7 @@
 	struct pci_bus *frozen_bus;
 	int rc = 0;
 	enum pci_ers_result result = PCI_ERS_RESULT_NONE;
+	const char *pci_str, *drv_str;
 
 	frozen_dn = find_device_pe(event->dn);
 	frozen_bus = pcibios_find_pci_bus(frozen_dn);
@@ -291,6 +292,13 @@
 
 	frozen_pdn = PCI_DN(frozen_dn);
 	frozen_pdn->eeh_freeze_count++;
+
+	pci_str = pci_name (frozen_pdn->pcidev);
+	drv_str = pcid_name (frozen_pdn->pcidev);
+	if (!pci_str) {
+		pci_str = pci_name (event->dev);
+		drv_str = pcid_name (event->dev);
+	}
 	
 	if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
 		goto hard_fail;
@@ -306,9 +314,7 @@
 	eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */);
 	printk(KERN_WARNING
 	   "EEH: This PCI device has failed %d times since last reboot: %s - %s\n",
-		frozen_pdn->eeh_freeze_count,
-		pci_name (frozen_pdn->pcidev), 
-		pcid_name(frozen_pdn->pcidev));
+		frozen_pdn->eeh_freeze_count, drv_str, pci_str);
 
 	/* Walk the various device drivers attached to this slot through
 	 * a reset sequence, giving each an opportunity to do what it needs
@@ -360,9 +366,7 @@
 	   "EEH: PCI device %s - %s has failed %d times \n"
 	   "and has been permanently disabled.  Please try reseating\n"
 	   "this device or replacing it.\n",
-		pci_name (frozen_pdn->pcidev), 
-		pcid_name(frozen_pdn->pcidev), 
-		frozen_pdn->eeh_freeze_count);
+		drv_str, pci_str, frozen_pdn->eeh_freeze_count);
 
 	eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */);
 
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c
index 989f4bc..c01d8f0 100644
--- a/arch/powerpc/platforms/pseries/firmware.c
+++ b/arch/powerpc/platforms/pseries/firmware.c
@@ -91,7 +91,7 @@
 				continue;
 
 			/* we have a match */
-			ppc64_firmware_features |=
+			powerpc_firmware_features |=
 				firmware_features_table[i].val;
 			break;
 		}
diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c
index 138e128..ba6befd 100644
--- a/arch/powerpc/platforms/pseries/hvconsole.c
+++ b/arch/powerpc/platforms/pseries/hvconsole.c
@@ -62,6 +62,11 @@
 	unsigned long *lbuf = (unsigned long *) buf;
 	long ret;
 
+
+	/* hcall will ret H_PARAMETER if 'count' exceeds firmware max.*/
+	if (count > MAX_VIO_PUT_CHARS)
+		count = MAX_VIO_PUT_CHARS;
+
 	ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count, lbuf[0],
 				 lbuf[1]);
 	if (ret == H_Success)
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
index 946ad59..e97e67f 100644
--- a/arch/powerpc/platforms/pseries/pci.c
+++ b/arch/powerpc/platforms/pseries/pci.c
@@ -120,7 +120,7 @@
 	int i;
 	unsigned int reg;
 
-	if (!platform_is_pseries())
+	if (!machine_is(pseries))
 		return;
 
 	printk("Using INTC for W82c105 IDE controller.\n");
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index 44abdeb..6bfacc2 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -28,6 +28,7 @@
 #include <linux/pci.h>
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
+#include <asm/firmware.h>
 
 static struct pci_bus *
 find_bus_among_children(struct pci_bus *bus,
@@ -152,20 +153,24 @@
 void
 pcibios_add_pci_devices(struct pci_bus * bus)
 {
-	int slotno, num;
+	int slotno, num, mode;
 	struct pci_dev *dev;
 	struct device_node *dn = pci_bus_to_OF_node(bus);
 
 	eeh_add_device_tree_early(dn);
 
-	if (_machine == PLATFORM_PSERIES_LPAR) {
+	mode = PCI_PROBE_NORMAL;
+	if (ppc_md.pci_probe_mode)
+		mode = ppc_md.pci_probe_mode(bus);
+
+	if (mode == PCI_PROBE_DEVTREE) {
 		/* use ofdt-based probe */
 		of_scan_bus(dn, bus);
 		if (!list_empty(&bus->devices)) {
 			pcibios_fixup_new_pci_devices(bus, 0);
 			pci_bus_add_devices(bus);
 		}
-	} else {
+	} else if (mode == PCI_PROBE_NORMAL) {
 		/* use legacy probe */
 		slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
 		num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index b046bcf..9639c66 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -132,7 +132,7 @@
 		of_node_put(np);
 	}
 
-	return 1;
+	return 0;
 }
 __initcall(init_ras_IRQ);
 
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 5ad9067..1773103 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -17,8 +17,9 @@
 #include <linux/proc_fs.h>
 
 #include <asm/prom.h>
-#include <asm/pSeries_reconfig.h>
+#include <asm/machdep.h>
 #include <asm/uaccess.h>
+#include <asm/pSeries_reconfig.h>
 
 
 
@@ -508,7 +509,7 @@
 {
 	struct proc_dir_entry *ent;
 
-	if (!platform_is_pseries())
+	if (!machine_is(pseries))
 		return 0;
 
 	ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL);
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
index a6f628d..fcc4d56 100644
--- a/arch/powerpc/platforms/pseries/rtasd.c
+++ b/arch/powerpc/platforms/pseries/rtasd.c
@@ -27,6 +27,7 @@
 #include <asm/prom.h>
 #include <asm/nvram.h>
 #include <asm/atomic.h>
+#include <asm/machdep.h>
 
 #if 0
 #define DEBUG(A...)	printk(KERN_ERR A)
@@ -481,7 +482,7 @@
 {
 	struct proc_dir_entry *entry;
 
-	if (!platform_is_pseries())
+	if (!machine_is(pseries))
 		return 0;
 
 	/* No RTAS */
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 44d5c7f..b2fbf8b 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -81,8 +81,8 @@
 
 int fwnmi_active;  /* TRUE if an FWNMI handler is present */
 
-static void pseries_shared_idle(void);
-static void pseries_dedicated_idle(void);
+static void pseries_shared_idle_sleep(void);
+static void pseries_dedicated_idle_sleep(void);
 
 struct mpic *pSeries_mpic;
 
@@ -236,14 +236,13 @@
 		vpa_init(boot_cpuid);
 		if (get_lppaca()->shared_proc) {
 			printk(KERN_INFO "Using shared processor idle loop\n");
-			ppc_md.idle_loop = pseries_shared_idle;
+			ppc_md.power_save = pseries_shared_idle_sleep;
 		} else {
 			printk(KERN_INFO "Using dedicated idle loop\n");
-			ppc_md.idle_loop = pseries_dedicated_idle;
+			ppc_md.power_save = pseries_dedicated_idle_sleep;
 		}
 	} else {
 		printk(KERN_INFO "Using default idle loop\n");
-		ppc_md.idle_loop = default_idle;
 	}
 
 	if (firmware_has_feature(FW_FEATURE_LPAR))
@@ -373,156 +372,123 @@
 /*
  * Called very early, MMU is off, device-tree isn't unflattened
  */
-extern struct machdep_calls pSeries_md;
 
-static int __init pSeries_probe(int platform)
+static int __init pSeries_probe_hypertas(unsigned long node,
+					 const char *uname, int depth,
+					 void *data)
 {
-	if (platform != PLATFORM_PSERIES &&
-	    platform != PLATFORM_PSERIES_LPAR)
+	if (depth != 1 ||
+	    (strcmp(uname, "rtas") != 0 && strcmp(uname, "rtas@0") != 0))
+ 		return 0;
+
+	if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL)
+ 		powerpc_firmware_features |= FW_FEATURE_LPAR;
+
+ 	return 1;
+}
+
+static int __init pSeries_probe(void)
+{
+ 	char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
+ 					  "device_type", NULL);
+ 	if (dtype == NULL)
+ 		return 0;
+ 	if (strcmp(dtype, "chrp"))
 		return 0;
 
-	/* if we have some ppc_md fixups for LPAR to do, do
-	 * it here ...
-	 */
+	DBG("pSeries detected, looking for LPAR capability...\n");
 
-	if (platform == PLATFORM_PSERIES_LPAR)
-		ppc64_firmware_features |= FW_FEATURE_LPAR;
+	/* Now try to figure out if we are running on LPAR */
+	of_scan_flat_dt(pSeries_probe_hypertas, NULL);
+
+	DBG("Machine is%s LPAR !\n",
+	    (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
 
 	return 1;
 }
 
+
 DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
 
-static inline void dedicated_idle_sleep(unsigned int cpu)
-{
-	struct lppaca *plppaca = &lppaca[cpu ^ 1];
-
-	/* Only sleep if the other thread is not idle */
-	if (!(plppaca->idle)) {
-		local_irq_disable();
-
-		/*
-		 * We are about to sleep the thread and so wont be polling any
-		 * more.
-		 */
-		clear_thread_flag(TIF_POLLING_NRFLAG);
-		smp_mb__after_clear_bit();
-
-		/*
-		 * SMT dynamic mode. Cede will result in this thread going
-		 * dormant, if the partner thread is still doing work.  Thread
-		 * wakes up if partner goes idle, an interrupt is presented, or
-		 * a prod occurs.  Returning from the cede enables external
-		 * interrupts.
-		 */
-		if (!need_resched())
-			cede_processor();
-		else
-			local_irq_enable();
-		set_thread_flag(TIF_POLLING_NRFLAG);
-	} else {
-		/*
-		 * Give the HV an opportunity at the processor, since we are
-		 * not doing any work.
-		 */
-		poll_pending();
-	}
-}
-
-static void pseries_dedicated_idle(void)
+static void pseries_dedicated_idle_sleep(void)
 { 
 	unsigned int cpu = smp_processor_id();
 	unsigned long start_snooze;
 	unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
-	set_thread_flag(TIF_POLLING_NRFLAG);
 
-	while (1) {
-		/*
-		 * Indicate to the HV that we are idle. Now would be
-		 * a good time to find other work to dispatch.
-		 */
-		get_lppaca()->idle = 1;
+	/*
+	 * Indicate to the HV that we are idle. Now would be
+	 * a good time to find other work to dispatch.
+	 */
+	get_lppaca()->idle = 1;
 
-		if (!need_resched()) {
-			start_snooze = get_tb() +
-				*smt_snooze_delay * tb_ticks_per_usec;
+	/*
+	 * We come in with interrupts disabled, and need_resched()
+	 * has been checked recently.  If we should poll for a little
+	 * while, do so.
+	 */
+	if (*smt_snooze_delay) {
+		start_snooze = get_tb() +
+			*smt_snooze_delay * tb_ticks_per_usec;
+		local_irq_enable();
+		set_thread_flag(TIF_POLLING_NRFLAG);
 
-			while (!need_resched() && !cpu_is_offline(cpu)) {
-				ppc64_runlatch_off();
-
-				/*
-				 * Go into low thread priority and possibly
-				 * low power mode.
-				 */
-				HMT_low();
-				HMT_very_low();
-
-				if (*smt_snooze_delay != 0 &&
-				    get_tb() > start_snooze) {
-					HMT_medium();
-					dedicated_idle_sleep(cpu);
-				}
-
-			}
-
-			HMT_medium();
+		while (get_tb() < start_snooze) {
+			if (need_resched() || cpu_is_offline(cpu))
+				goto out;
+			ppc64_runlatch_off();
+			HMT_low();
+			HMT_very_low();
 		}
 
-		get_lppaca()->idle = 0;
-		ppc64_runlatch_on();
-
-		preempt_enable_no_resched();
-		schedule();
-		preempt_disable();
-
-		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
-			cpu_die();
+		HMT_medium();
+		clear_thread_flag(TIF_POLLING_NRFLAG);
+		smp_mb();
+		local_irq_disable();
+		if (need_resched() || cpu_is_offline(cpu))
+			goto out;
 	}
+
+	/*
+	 * Cede if the other thread is not idle, so that it can
+	 * go single-threaded.  If the other thread is idle,
+	 * we ask the hypervisor if it has pending work it
+	 * wants to do and cede if it does.  Otherwise we keep
+	 * polling in order to reduce interrupt latency.
+	 *
+	 * Doing the cede when the other thread is active will
+	 * result in this thread going dormant, meaning the other
+	 * thread gets to run in single-threaded (ST) mode, which
+	 * is slightly faster than SMT mode with this thread at
+	 * very low priority.  The cede enables interrupts, which
+	 * doesn't matter here.
+	 */
+	if (!lppaca[cpu ^ 1].idle || poll_pending() == H_Pending)
+		cede_processor();
+
+out:
+	HMT_medium();
+	get_lppaca()->idle = 0;
 }
 
-static void pseries_shared_idle(void)
+static void pseries_shared_idle_sleep(void)
 {
-	unsigned int cpu = smp_processor_id();
+	/*
+	 * Indicate to the HV that we are idle. Now would be
+	 * a good time to find other work to dispatch.
+	 */
+	get_lppaca()->idle = 1;
 
-	while (1) {
-		/*
-		 * Indicate to the HV that we are idle. Now would be
-		 * a good time to find other work to dispatch.
-		 */
-		get_lppaca()->idle = 1;
+	/*
+	 * Yield the processor to the hypervisor.  We return if
+	 * an external interrupt occurs (which are driven prior
+	 * to returning here) or if a prod occurs from another
+	 * processor. When returning here, external interrupts
+	 * are enabled.
+	 */
+	cede_processor();
 
-		while (!need_resched() && !cpu_is_offline(cpu)) {
-			local_irq_disable();
-			ppc64_runlatch_off();
-
-			/*
-			 * Yield the processor to the hypervisor.  We return if
-			 * an external interrupt occurs (which are driven prior
-			 * to returning here) or if a prod occurs from another
-			 * processor. When returning here, external interrupts
-			 * are enabled.
-			 *
-			 * Check need_resched() again with interrupts disabled
-			 * to avoid a race.
-			 */
-			if (!need_resched())
-				cede_processor();
-			else
-				local_irq_enable();
-
-			HMT_medium();
-		}
-
-		get_lppaca()->idle = 0;
-		ppc64_runlatch_on();
-
-		preempt_enable_no_resched();
-		schedule();
-		preempt_disable();
-
-		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
-			cpu_die();
-	}
+	get_lppaca()->idle = 0;
 }
 
 static int pSeries_pci_probe_mode(struct pci_bus *bus)
@@ -553,7 +519,8 @@
 }
 #endif
 
-struct machdep_calls __initdata pSeries_md = {
+define_machine(pseries) {
+	.name			= "pSeries",
 	.probe			= pSeries_probe,
 	.setup_arch		= pSeries_setup_arch,
 	.init_early		= pSeries_init_early,
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index eb86cdb..4864cb3 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -500,7 +500,7 @@
 	     np;
 	     np = of_find_node_by_type(np, "cpu")) {
 		ireg = (uint *)get_property(np, "reg", &ilen);
-		if (ireg && ireg[0] == boot_cpuid_phys) {
+		if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) {
 			ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s",
 						    &ilen);
 			i = ilen / sizeof(int);
@@ -541,7 +541,7 @@
 		ops = &pSeriesLP_ops;
 	else {
 #ifdef CONFIG_SMP
-		for_each_cpu(i) {
+		for_each_possible_cpu(i) {
 			int hard_id;
 
 			/* FIXME: Do this dynamically! --RR */
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 3a3e302..e9a8f5d 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -61,15 +61,15 @@
 	select PPC_FPU
 	help
 	  There are four types of PowerPC chips supported.  The more common
-	  types (601, 603, 604, 740, 750, 7400), the Motorola embedded
-	  versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the IBM
-	  embedded versions (403 and 405) and the POWER3 processor.
-	  (For support for more recent 64-bit processors, set ARCH=powerpc.)
+	  types (601, 603, 604, 740, 750, 7400), the older Freescale
+	  (formerly Motorola) embedded versions (821, 823, 850, 855, 860,
+	  52xx, 82xx, 83xx), the IBM embedded versions (403 and 405) and
+	  the Book E embedded processors from IBM (44x) and Freescale (85xx).
+	  For support for 64-bit processors, set ARCH=powerpc.
 	  Unless you are building a kernel for one of the embedded processor
-	  systems or a POWER3-based IBM RS/6000, choose 6xx.
-	  Note that the kernel runs in 32-bit mode even on 64-bit chips.
-	  Also note that because the 52xx, 82xx, & 83xx family has a 603e core,
-	  specific support for that chipset is asked later on.
+	  systems, choose 6xx.
+	  Also note that because the 52xx, 82xx, & 83xx family have a 603e
+	  core, specific support for that chipset is asked later on.
 
 config 40x
 	bool "40x"
@@ -77,10 +77,6 @@
 config 44x
 	bool "44x"
 
-config POWER3
-	select PPC_FPU
-	bool "POWER3"
-
 config 8xx
 	bool "8xx"
 
@@ -252,14 +248,9 @@
 source arch/ppc/platforms/4xx/Kconfig
 source arch/ppc/platforms/85xx/Kconfig
 
-config PPC64BRIDGE
-	bool
-	depends on POWER3
-	default y
-
 config PPC_STD_MMU
 	bool
-	depends on 6xx || POWER3
+	depends on 6xx
 	default y
 
 config NOT_COHERENT_CACHE
@@ -534,8 +525,8 @@
 
 choice
 	prompt "Machine Type"
-	depends on 6xx || POWER3
-	default PPC_MULTIPLATFORM
+	depends on 6xx
+	default PPC_PREP
 	---help---
 	  Linux currently supports several different kinds of PowerPC-based
 	  machines: Apple Power Macintoshes and clones (such as the Motorola
@@ -545,15 +536,14 @@
 	  Platform) machines (including all of the recent IBM RS/6000 and
 	  pSeries machines), and several embedded PowerPC systems containing
 	  4xx, 6xx, 7xx, 8xx, 74xx, and 82xx processors.  Currently, the
-	  default option is to build a kernel which works on PReP and CHRP.
+	  default option is to build a kernel which works on PReP.
 
-	  Note that support for Apple machines is now only available with
-	  ARCH=powerpc, and has been removed from this menu.  If you wish
-	  to build a kernel for an Apple machine, exit this configuration
-	  process and re-run it with ARCH=powerpc.
+	  Note that support for Apple and CHRP machines is now only available
+	  with ARCH=powerpc, and has been removed from this menu.  If you
+	  wish to build a kernel for an Apple or CHRP machine, exit this
+	  configuration process and re-run it with ARCH=powerpc.
 
-	  Select CHRP/PReP if configuring for an IBM RS/6000 or
-	  pSeries machine, or a PReP machine.
+	  Select PReP if configuring for a PReP machine.
 
 	  Select Gemini if configuring for a Synergy Microsystems' Gemini
 	  series Single Board Computer.  More information is available at:
@@ -562,8 +552,8 @@
 	  Select APUS if configuring for a PowerUP Amiga.  More information is
 	  available at: <http://linux-apus.sourceforge.net/>.
 
-config PPC_MULTIPLATFORM
-	bool "CHRP/PReP"
+config PPC_PREP
+	bool "PReP"
 
 config APUS
 	bool "Amiga-APUS"
@@ -715,6 +705,13 @@
 	  much but it's only been tested on this board version. I think this
 	  board is also known as IceCube.
 
+config LITE5200B
+	bool "Freescale LITE5200B"
+	depends LITE5200
+	help
+	  Support for the LITE5200B dev board for the MPC5200 from Freescale.
+	  This is the new board with 2 PCI slots.
+
 config MPC834x_SYS
 	bool "Freescale MPC834x SYS"
 	help
@@ -800,25 +797,6 @@
 	  you wish to build a kernel for a machine with a CPM2 coprocessor
 	  on it (826x, 827x, 8560).
 
-config PPC_CHRP
-	bool "Support for CHRP (Common Hardware Reference Platform) machines"
-	depends on PPC_MULTIPLATFORM
-	select PPC_I8259
-	select PPC_INDIRECT_PCI
-	default y
-
-config PPC_PREP
-	bool "Support for PReP (PowerPC Reference Platform) machines"
-	depends on PPC_MULTIPLATFORM
-	select PPC_I8259
-	select PPC_INDIRECT_PCI
-	default y
-
-config PPC_OF
-	bool
-	depends on PPC_CHRP
-	default y
-
 config PPC_GEN550
 	bool
 	depends on SANDPOINT || SPRUCE || PPLUS || \
@@ -977,14 +955,6 @@
 
 source "fs/Kconfig.binfmt"
 
-config PROC_DEVICETREE
-	bool "Support for Open Firmware device tree in /proc"
-	depends on PPC_OF && PROC_FS
-	help
-	  This option adds a device-tree directory under /proc which contains
-	  an image of the device tree that the kernel copies from Open
-	  Firmware. If unsure, say Y here.
-
 config PREP_RESIDUAL
 	bool "Support for PReP Residual Data"
 	depends on PPC_PREP
@@ -1177,8 +1147,7 @@
 
 config ISA
 	bool "Support for ISA-bus hardware"
-	depends on PPC_PREP || PPC_CHRP
-	select PPC_I8259
+	depends on PPC_PREP
 	help
 	  Find out whether you have ISA slots on your motherboard.  ISA is the
 	  name of a bus system, i.e. the way the CPU talks to the other stuff
@@ -1188,18 +1157,18 @@
 
 config GENERIC_ISA_DMA
 	bool
-	depends on POWER3 || 6xx && !CPM2
+	depends on 6xx && !CPM2
 	default y
 
 config PPC_I8259
 	bool
-	default y if 85xx
+	default y if 85xx || PPC_PREP
 	default n
 
 config PPC_INDIRECT_PCI
 	bool
 	depends on PCI
-	default y if 40x || 44x || 85xx || 83xx
+	default y if 40x || 44x || 85xx || 83xx || PPC_PREP
 	default n
 
 config EISA
@@ -1390,7 +1359,7 @@
 
 config BOOT_LOAD_BOOL
 	bool "Set the boot link/load address"
-	depends on ADVANCED_OPTIONS && !PPC_MULTIPLATFORM
+	depends on ADVANCED_OPTIONS && !PPC_PREP
 	help
 	  This option allows you to set the initial load address of the zImage
 	  or zImage.initrd file.  This can be useful if you are on a board
diff --git a/arch/ppc/Kconfig.debug b/arch/ppc/Kconfig.debug
index 8cc75ab..f94b877 100644
--- a/arch/ppc/Kconfig.debug
+++ b/arch/ppc/Kconfig.debug
@@ -53,13 +53,6 @@
 	  Unless you are intending to debug the kernel with one of these
 	  machines, say N here.
 
-config BOOTX_TEXT
-	bool "Support for early boot text console (BootX or OpenFirmware only)"
-	depends PPC_OF
-	help
-	  Say Y here to see progress messages from the boot firmware in text
-	  mode. Requires either BootX or Open Firmware.
-
 config SERIAL_TEXT_DEBUG
 	bool "Support for early boot texts over serial port"
 	depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index 9fbdf54..0db66dc 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -40,10 +40,8 @@
 CFLAGS		+= -mstring
 endif
 
-cpu-as-$(CONFIG_PPC64BRIDGE)	+= -Wa,-mppc64bridge
 cpu-as-$(CONFIG_4xx)		+= -Wa,-m405
 cpu-as-$(CONFIG_6xx)		+= -Wa,-maltivec
-cpu-as-$(CONFIG_POWER4)		+= -Wa,-maltivec
 cpu-as-$(CONFIG_E500)		+= -Wa,-me500
 cpu-as-$(CONFIG_E200)		+= -Wa,-me200
 
@@ -59,8 +57,6 @@
 head-$(CONFIG_44x)		:= arch/ppc/kernel/head_44x.o
 head-$(CONFIG_FSL_BOOKE)	:= arch/ppc/kernel/head_fsl_booke.o
 
-head-$(CONFIG_6xx)		+= arch/ppc/kernel/idle_6xx.o
-head-$(CONFIG_POWER4)		+= arch/ppc/kernel/idle_power4.o
 head-$(CONFIG_PPC_FPU)		+= arch/powerpc/kernel/fpu.o
 
 core-y				+= arch/ppc/kernel/ arch/powerpc/kernel/ \
@@ -71,7 +67,7 @@
 core-$(CONFIG_4xx)		+= arch/ppc/platforms/4xx/
 core-$(CONFIG_83xx)		+= arch/ppc/platforms/83xx/
 core-$(CONFIG_85xx)		+= arch/ppc/platforms/85xx/
-core-$(CONFIG_MATH_EMULATION)	+= arch/ppc/math-emu/
+core-$(CONFIG_MATH_EMULATION)	+= arch/powerpc/math-emu/
 core-$(CONFIG_XMON)		+= arch/ppc/xmon/
 core-$(CONFIG_APUS)		+= arch/ppc/amiga/
 drivers-$(CONFIG_8xx)		+= arch/ppc/8xx_io/
diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile
index 84eec0b..b739e25 100644
--- a/arch/ppc/boot/Makefile
+++ b/arch/ppc/boot/Makefile
@@ -19,14 +19,13 @@
 BOOT_TARGETS	= zImage zImage.initrd znetboot znetboot.initrd
 
 bootdir-y			:= simple
-bootdir-$(CONFIG_PPC_OF)	+= openfirmware
 subdir-y			:= lib common images
-subdir-$(CONFIG_PPC_MULTIPLATFORM)	+= of1275
+subdir-$(CONFIG_PPC_PREP)	+= of1275
 
 # for cleaning
-subdir-				+= simple openfirmware
+subdir-				+= simple
 
-hostprogs-y := $(addprefix utils/, addnote mknote hack-coff mkprep mkbugboot mktree)
+hostprogs-y := $(addprefix utils/, mkprep mkbugboot mktree)
 
 PHONY += $(BOOT_TARGETS) $(bootdir-y)
 
diff --git a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile
deleted file mode 100644
index 66b7397..0000000
--- a/arch/ppc/boot/openfirmware/Makefile
+++ /dev/null
@@ -1,109 +0,0 @@
-# Makefile for making bootable images on various OpenFirmware machines.
-#
-# This file is included by the global makefile so that you can add your own
-# architecture-specific flags and dependencies.
-#
-# Paul Mackerras	January 1997
-#	XCOFF bootable images for PowerMacs
-# Geert Uytterhoeven	September 1997
-#	ELF bootable iamges for CHRP machines.
-# Tom Rini		January 2001
-# 	Cleaned up, moved into arch/ppc/boot/pmac
-# Tom Rini		July/August 2002
-#	Merged 'chrp' and 'pmac' into 'openfirmware', and cleaned up the
-#	rules.
-
-zImage.initrd znetboot.initrd: del-ramdisk-sec	:= -R .ramdisk
-zImage.initrd znetboot.initrd: initrd		:= .initrd
-
-
-boot	:= arch/ppc/boot
-common	:= $(boot)/common
-utils	:= $(boot)/utils
-bootlib	:= $(boot)/lib
-of1275	:= $(boot)/of1275
-images	:= $(boot)/images
-
-CHRP_LD_ARGS	:= -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00800000
-
-COMMONOBJS	:= start.o misc.o common.o
-CHRPOBJS	:= crt0.o     $(COMMONOBJS) chrpmain.o
-
-targets 	:= $(CHRPOBJS) dummy.o
-CHRPOBJS	:= $(addprefix $(obj)/, $(CHRPOBJS))
-
-LIBS		:= lib/lib.a $(bootlib)/lib.a $(of1275)/lib.a $(common)/lib.a
-
-ifdef CONFIG_SMP
-END := .smp
-endif
-ifdef CONFIG_PPC64BRIDGE
-END += .64
-endif
-
-
-$(images)/ramdisk.image.gz:
-	@echo '  MISSING $@'
-	@echo '          RAM disk image must be provided separately'
-	@/bin/false
-
-quiet_cmd_genimage = GEN     $@
-      cmd_genimage = $(OBJCOPY) -R .comment       \
-	--add-section=.image=$(images)/vmlinux.gz \
-	--set-section-flags=.image=contents,alloc,load,readonly,data $< $@
-
-targets += image.o
-$(obj)/image.o: $(obj)/dummy.o $(images)/vmlinux.gz FORCE
-	$(call if_changed,genimage)
-
-# Place the ramdisk in the initrd image.
-quiet_cmd_genimage-initrd = GEN     $@
-      cmd_genimage-initrd = $(OBJCOPY) $< $@ \
-	--add-section=.ramdisk=$(images)/ramdisk.image.gz \
-	--set-section-flags=.ramdisk=contents,alloc,load,readonly,data
-targets += image.initrd.o
-$(obj)/image.initrd.o: $(obj)/image.o $(images)/ramdisk.image.gz FORCE
-	$(call if_changed,genimage-initrd)
-
-
-targets += crt0.o
-$(obj)/crt0.o: $(common)/crt0.S FORCE
-	$(call if_changed_dep,as_o_S)
-
-quiet_cmd_gen-chrp = CHRP    $@
-      cmd_gen-chrp = $(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) $< $(LIBS) && \
-			$(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec)
-
-$(images)/zImage.chrp: $(obj)/image.o $(CHRPOBJS) $(LIBS) \
-				   $(srctree)/$(boot)/ld.script
-	$(call cmd,gen-chrp)
-$(images)/zImage.initrd.chrp: $(obj)/image.initrd.o $(CHRPOBJS) $(LIBS) \
-				   $(srctree)/$(boot)/ld.script
-	$(call cmd,gen-chrp)
-
-quiet_cmd_addnote = ADDNOTE $@
-      cmd_addnote = cat $< > $@ && $(utils)/addnote $@
-$(images)/zImage.chrp-rs6k $(images)/zImage.initrd.chrp-rs6k: \
-	%-rs6k: %
-	$(call cmd,addnote)
-
-# The targets used on the make command-line
-
-PHONY += zImage zImage.initrd
-zImage:		 $(images)/zImage.chrp		\
-		 $(images)/zImage.chrp-rs6k
-	@echo '  kernel: $@ is ready ($<)'
-zImage.initrd:	 $(images)/zImage.initrd.chrp		\
-		 $(images)/zImage.initrd.chrp-rs6k
-	@echo '  kernel: $@ is ready ($<)'
-
-TFTPIMAGE	:= /tftpboot/zImage
-
-PHONY += znetboot znetboot.initrd
-znetboot:	$(images)/zImage.chrp
-	cp $(images)/zImage.chrp      $(TFTPIMAGE).chrp$(END)
-	@echo '  kernel: $@ is ready ($<)'
-znetboot.initrd:$(images)/zImage.initrd.chrp
-	cp $(images)/zImage.initrd.chrp      $(TFTPIMAGE).chrp$(END)
-	@echo '  kernel: $@ is ready ($<)'
-
diff --git a/arch/ppc/boot/openfirmware/chrpmain.c b/arch/ppc/boot/openfirmware/chrpmain.c
deleted file mode 100644
index 245dbd9..0000000
--- a/arch/ppc/boot/openfirmware/chrpmain.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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.
- */
-#include <linux/string.h>
-#include "nonstdio.h"
-#include "of1275.h"
-#include <asm/processor.h>
-#include <asm/page.h>
-
-/* Passed from the linker */
-extern char __image_begin, __image_end;
-extern char __ramdisk_begin, __ramdisk_end;
-extern char _start, _end;
-
-extern unsigned int heap_max;
-extern void flush_cache(void *, unsigned long);
-extern void gunzip(void *, int, unsigned char *, int *);
-extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
-		unsigned int progend);
-
-char *avail_ram;
-char *begin_avail, *end_avail;
-char *avail_high;
-
-#define RAM_START	0x00000000
-#define RAM_END		(64<<20)
-
-#define BOOT_START	((unsigned long)_start)
-#define BOOT_END	((unsigned long)(_end + 0xFFF) & ~0xFFF)
-
-#define RAM_FREE	((unsigned long)(_end+0x1000)&~0xFFF)
-#define PROG_START	0x00010000
-#define PROG_SIZE	0x007f0000 /* 8MB */
-
-#define SCRATCH_SIZE	(128 << 10)
-
-static char scratch[SCRATCH_SIZE];	/* 128k of scratch space for gunzip */
-
-typedef void (*kernel_start_t)(int, int, void *, unsigned int, unsigned int);
-
-void
-boot(int a1, int a2, void *prom)
-{
-    unsigned sa, len;
-    void *dst;
-    unsigned char *im;
-    unsigned int initrd_size, initrd_start;
-
-    printf("chrpboot starting: loaded at 0x%p\n\r", &_start);
-
-    initrd_size = &__ramdisk_end - &__ramdisk_begin;
-    if (initrd_size) {
-	initrd_start = (RAM_END - initrd_size) & ~0xFFF;
-	a1 = initrd_start;
-	a2 = initrd_size;
-	claim(initrd_start, RAM_END - initrd_start, 0);
-	printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r",
-	       initrd_start, &__ramdisk_begin, initrd_size);
-	memcpy((char *)initrd_start, &__ramdisk_begin, initrd_size);
-    } else {
-	initrd_start = 0;
-	initrd_size = 0;
-	a2 = 0xdeadbeef;
-    }
-
-    im = &__image_begin;
-    len = &__image_end - &__image_begin;
-    /* claim 4MB starting at PROG_START */
-    claim(PROG_START, PROG_SIZE - PROG_START, 0);
-    dst = (void *) PROG_START;
-    if (im[0] == 0x1f && im[1] == 0x8b) {
-	avail_ram = scratch;
-	begin_avail = avail_high = avail_ram;
-	end_avail = scratch + sizeof(scratch);
-	printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len);
-	gunzip(dst, PROG_SIZE - PROG_START, im, &len);
-	printf("done %u bytes\n\r", len);
-	printf("%u bytes of heap consumed, max in use %u\n\r",
-	       avail_high - begin_avail, heap_max);
-    } else {
-	memmove(dst, im, len);
-    }
-
-    flush_cache(dst, len);
-    make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_chrp,
-		    (PROG_START + PROG_SIZE));
-
-    sa = PROG_START;
-    printf("start address = 0x%x\n\r", sa);
-
-    (*(kernel_start_t)sa)(a1, a2, prom, initrd_start, initrd_size);
-
-    printf("returned?\n\r");
-
-    pause();
-}
diff --git a/arch/ppc/boot/openfirmware/common.c b/arch/ppc/boot/openfirmware/common.c
deleted file mode 100644
index 0f46756..0000000
--- a/arch/ppc/boot/openfirmware/common.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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.
- */
-
-#include "nonstdio.h"
-#include "of1275.h"
-#include <linux/string.h>
-#include <linux/zlib.h>
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-
-/* Information from the linker */
-
-extern int strcmp(const char *s1, const char *s2);
-extern char *avail_ram, *avail_high;
-extern char *end_avail;
-
-unsigned int heap_use, heap_max;
-
-struct memchunk {
-    unsigned int size;
-    struct memchunk *next;
-};
-
-static struct memchunk *freechunks;
-
-static void *zalloc(unsigned size)
-{
-    void *p;
-    struct memchunk **mpp, *mp;
-
-    size = (size + 7) & -8;
-    heap_use += size;
-    if (heap_use > heap_max)
-	heap_max = heap_use;
-    for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) {
-	if (mp->size == size) {
-	    *mpp = mp->next;
-	    return mp;
-	}
-    }
-    p = avail_ram;
-    avail_ram += size;
-    if (avail_ram > avail_high)
-	avail_high = avail_ram;
-    if (avail_ram > end_avail) {
-	printf("oops... out of memory\n\r");
-	pause();
-    }
-    return p;
-}
-
-#define HEAD_CRC	2
-#define EXTRA_FIELD	4
-#define ORIG_NAME	8
-#define COMMENT		0x10
-#define RESERVED	0xe0
-
-void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
-{
-	z_stream s;
-	int r, i, flags;
-
-	/* skip header */
-	i = 10;
-	flags = src[3];
-	if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
-		printf("bad gzipped data\n\r");
-		exit();
-	}
-	if ((flags & EXTRA_FIELD) != 0)
-		i = 12 + src[10] + (src[11] << 8);
-	if ((flags & ORIG_NAME) != 0)
-		while (src[i++] != 0)
-			;
-	if ((flags & COMMENT) != 0)
-		while (src[i++] != 0)
-			;
-	if ((flags & HEAD_CRC) != 0)
-		i += 2;
-	if (i >= *lenp) {
-		printf("gunzip: ran out of data in header\n\r");
-		exit();
-	}
-
-	/* Initialize ourself. */
-	s.workspace = zalloc(zlib_inflate_workspacesize());
-	r = zlib_inflateInit2(&s, -MAX_WBITS);
-	if (r != Z_OK) {
-		printf("zlib_inflateInit2 returned %d\n\r", r);
-		exit();
-	}
-	s.next_in = src + i;
-	s.avail_in = *lenp - i;
-	s.next_out = dst;
-	s.avail_out = dstlen;
-	r = zlib_inflate(&s, Z_FINISH);
-	if (r != Z_OK && r != Z_STREAM_END) {
-		printf("inflate returned %d msg: %s\n\r", r, s.msg);
-		exit();
-	}
-	*lenp = s.next_out - (unsigned char *) dst;
-	zlib_inflateEnd(&s);
-}
-
-/* Make a bi_rec in OF.  We need to be passed a name for BI_BOOTLOADER_ID,
- * a machine type for BI_MACHTYPE, and the location where the end of the
- * bootloader is (PROG_START + PROG_SIZE)
- */
-void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
-		unsigned long progend)
-{
-	struct bi_record *rec;
-
-
-	/* leave a 1MB gap then align to the next 1MB boundary */
-	addr = _ALIGN(addr+ (1<<20) - 1, (1<<20));
-	/* oldworld machine seem very unhappy about this. -- Tom */
-	if (addr >= progend)
-		claim(addr, 0x1000, 0);
-
-	rec = (struct bi_record *)addr;
-	rec->tag = BI_FIRST;
-	rec->size = sizeof(struct bi_record);
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
-	rec->tag = BI_BOOTLOADER_ID;
-	sprintf( (char *)rec->data, name);
-	rec->size = sizeof(struct bi_record) + strlen(name) + 1;
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
-	rec->tag = BI_MACHTYPE;
-	rec->data[0] = mach;
-	rec->data[1] = 1;
-	rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
-	rec->tag = BI_LAST;
-	rec->size = sizeof(struct bi_record);
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-}
diff --git a/arch/ppc/boot/openfirmware/dummy.c b/arch/ppc/boot/openfirmware/dummy.c
deleted file mode 100644
index 31dbf45..0000000
--- a/arch/ppc/boot/openfirmware/dummy.c
+++ /dev/null
@@ -1,4 +0,0 @@
-int main(void)
-{
-	return 0;
-}
diff --git a/arch/ppc/boot/openfirmware/misc.S b/arch/ppc/boot/openfirmware/misc.S
deleted file mode 100644
index ab9e897..0000000
--- a/arch/ppc/boot/openfirmware/misc.S
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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.
- */
-	.text
-
-/*
- * Use the BAT2 & 3 registers to map the 1st 16MB of RAM to
- * the address given as the 1st argument.
- */
-	.globl	setup_bats
-setup_bats:
-	mfpvr	5
-	rlwinm	5,5,16,16,31		/* r3 = 1 for 601, 4 for 604 */
-	cmpwi	0,5,1
-	li	0,0
-	bne	4f
-	mtibatl	3,0			/* invalidate BAT first */
-	ori	3,3,4			/* set up BAT registers for 601 */
-	li	4,0x7f
-	mtibatu	2,3
-	mtibatl	2,4
-	oris	3,3,0x80
-	oris	4,4,0x80
-	mtibatu	3,3
-	mtibatl	3,4
-	b	5f
-4:	mtdbatu	3,0			/* invalidate BATs first */
-	mtibatu	3,0
-	ori	3,3,0xff		/* set up BAT registers for 604 */
-	li	4,2
-	mtdbatl	2,4
-	mtdbatu	2,3
-	mtibatl	2,4
-	mtibatu	2,3
-	oris	3,3,0x80
-	oris	4,4,0x80
-	mtdbatl	3,4
-	mtdbatu	3,3
-	mtibatl	3,4
-	mtibatu	3,3
-5:	sync
-	isync
-	blr
-
-/*
- * Flush the dcache and invalidate the icache for a range of addresses.
- *
- * flush_cache(addr, len)
- */
-	.global	flush_cache
-flush_cache:
-	addi	4,4,0x1f	/* len = (len + 0x1f) / 0x20 */
-	rlwinm.	4,4,27,5,31
-	mtctr	4
-	beqlr
-1:	dcbf	0,3
-	icbi	0,3
-	addi	3,3,0x20
-	bdnz	1b
-	sync
-	isync
-	blr
diff --git a/arch/ppc/boot/openfirmware/start.c b/arch/ppc/boot/openfirmware/start.c
deleted file mode 100644
index 1617a26..0000000
--- a/arch/ppc/boot/openfirmware/start.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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.
- */
-#include <stdarg.h>
-#include "of1275.h"
-
-extern int strlen(const char *s);
-extern void boot(int a1, int a2, void *prom);
-
-phandle stdin;
-phandle stdout;
-phandle stderr;
-
-void printk(char *fmt, ...);
-
-void
-start(int a1, int a2, void *promptr)
-{
-    ofinit(promptr);
-    if (ofstdio(&stdin, &stdout, &stderr))
-	exit();
-
-    boot(a1, a2, promptr);
-    for (;;)
-	exit();
-}
-
-int writestring(void *f, char *ptr, int nb)
-{
-	int w = 0, i;
-	char *ret = "\r";
-
-	for (i = 0; i < nb; ++i) {
-		if (ptr[i] == '\n') {
-			if (i > w) {
-				write(f, ptr + w, i - w);
-				w = i;
-			}
-			write(f, ret, 1);
-		}
-	}
-	if (w < nb)
-		write(f, ptr + w, nb - w);
-	return nb;
-}
-
-int
-putc(int c, void *f)
-{
-    char ch = c;
-
-    return writestring(f, &ch, 1) == 1? c: -1;
-}
-
-int
-putchar(int c)
-{
-    return putc(c, stdout);
-}
-
-int
-fputs(char *str, void *f)
-{
-    int n = strlen(str);
-
-    return writestring(f, str, n) == n? 0: -1;
-}
-
-int
-readchar(void)
-{
-    char ch;
-
-    for (;;) {
-	switch (read(stdin, &ch, 1)) {
-	case 1:
-	    return ch;
-	case -1:
-	    printk("read(stdin) returned -1\n");
-	    return -1;
-	}
-    }
-}
-
-static char line[256];
-static char *lineptr;
-static int lineleft;
-
-int
-getchar(void)
-{
-    int c;
-
-    if (lineleft == 0) {
-	lineptr = line;
-	for (;;) {
-	    c = readchar();
-	    if (c == -1 || c == 4)
-		break;
-	    if (c == '\r' || c == '\n') {
-		*lineptr++ = '\n';
-		putchar('\n');
-		break;
-	    }
-	    switch (c) {
-	    case 0177:
-	    case '\b':
-		if (lineptr > line) {
-		    putchar('\b');
-		    putchar(' ');
-		    putchar('\b');
-		    --lineptr;
-		}
-		break;
-	    case 'U' & 0x1F:
-		while (lineptr > line) {
-		    putchar('\b');
-		    putchar(' ');
-		    putchar('\b');
-		    --lineptr;
-		}
-		break;
-	    default:
-		if (lineptr >= &line[sizeof(line) - 1])
-		    putchar('\a');
-		else {
-		    putchar(c);
-		    *lineptr++ = c;
-		}
-	    }
-	}
-	lineleft = lineptr - line;
-	lineptr = line;
-    }
-    if (lineleft == 0)
-	return -1;
-    --lineleft;
-    return *lineptr++;
-}
-
-extern int vsprintf(char *buf, const char *fmt, va_list args);
-static char sprint_buf[1024];
-
-void
-printk(char *fmt, ...)
-{
-	va_list args;
-	int n;
-
-	va_start(args, fmt);
-	n = vsprintf(sprint_buf, fmt, args);
-	va_end(args);
-	writestring(stdout, sprint_buf, n);
-}
-
-int
-printf(char *fmt, ...)
-{
-	va_list args;
-	int n;
-
-	va_start(args, fmt);
-	n = vsprintf(sprint_buf, fmt, args);
-	va_end(args);
-	writestring(stdout, sprint_buf, n);
-	return n;
-}
diff --git a/arch/ppc/boot/simple/mpc10x_memory.c b/arch/ppc/boot/simple/mpc10x_memory.c
index c242908..8da8f57 100644
--- a/arch/ppc/boot/simple/mpc10x_memory.c
+++ b/arch/ppc/boot/simple/mpc10x_memory.c
@@ -50,10 +50,10 @@
  * the system.  This assumes that the firmware has correctly set up the memory
  * controller registers.  On CONFIG_PPC_PREP, we know we are being called
  * under a PReP memory map. On all other machines, we assume we are under
- * a CHRP memory map.  Further, on CONFIG_PPC_MULTIPLATFORM we must rename
+ * a CHRP memory map.  Further, on CONFIG_PPC_PREP we must rename
  * this function.
  */
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_PPC_PREP
 #define get_mem_size mpc10x_get_mem_size
 #endif
 unsigned long
diff --git a/arch/ppc/boot/simple/relocate.S b/arch/ppc/boot/simple/relocate.S
index 7efddc5..2533113 100644
--- a/arch/ppc/boot/simple/relocate.S
+++ b/arch/ppc/boot/simple/relocate.S
@@ -194,7 +194,7 @@
 	/*
 	 * Start at the begining.
 	 */
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_PPC_PREP
 	li	r9,0xc
 	mtlr	r9
 	/* tell kernel we're prep, by putting 0xdeadc0de at KERNELLOAD,
diff --git a/arch/ppc/boot/utils/addnote.c b/arch/ppc/boot/utils/addnote.c
deleted file mode 100644
index 6c52b18..0000000
--- a/arch/ppc/boot/utils/addnote.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Program to hack in a PT_NOTE program header entry in an ELF file.
- * This is needed for OF on RS/6000s to load an image correctly.
- * Note that OF needs a program header entry for the note, not an
- * ELF section.
- *
- * Copyright 2000 Paul Mackerras.
- *
- * 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.
- *
- * Usage: addnote zImage
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-
-char arch[] = "PowerPC";
-
-#define N_DESCR	6
-unsigned int descr[N_DESCR] = {
-#if 1
-	/* values for IBM RS/6000 machines */
-	0xffffffff,		/* real-mode = true */
-	0x00c00000,		/* real-base, i.e. where we expect OF to be */
-	0xffffffff,		/* real-size */
-	0xffffffff,		/* virt-base */
-	0xffffffff,		/* virt-size */
-	0x4000,			/* load-base */
-#else
-	/* values for longtrail CHRP */
-	0,			/* real-mode = false */
-	0xffffffff,		/* real-base */
-	0xffffffff,		/* real-size */
-	0xffffffff,		/* virt-base */
-	0xffffffff,		/* virt-size */
-	0x00600000,		/* load-base */
-#endif
-};
-
-unsigned char buf[512];
-
-#define GET_16BE(off)	((buf[off] << 8) + (buf[(off)+1]))
-#define GET_32BE(off)	((GET_16BE(off) << 16) + GET_16BE((off)+2))
-
-#define PUT_16BE(off, v)	(buf[off] = ((v) >> 8) & 0xff, \
-				 buf[(off) + 1] = (v) & 0xff)
-#define PUT_32BE(off, v)	(PUT_16BE((off), (v) >> 16), \
-				 PUT_16BE((off) + 2, (v)))
-
-/* Structure of an ELF file */
-#define E_IDENT		0	/* ELF header */
-#define	E_PHOFF		28
-#define E_PHENTSIZE	42
-#define E_PHNUM		44
-#define E_HSIZE		52	/* size of ELF header */
-
-#define EI_MAGIC	0	/* offsets in E_IDENT area */
-#define EI_CLASS	4
-#define EI_DATA		5
-
-#define PH_TYPE		0	/* ELF program header */
-#define PH_OFFSET	4
-#define PH_FILESZ	16
-#define PH_HSIZE	32	/* size of program header */
-
-#define PT_NOTE		4	/* Program header type = note */
-
-#define ELFCLASS32	1
-#define ELFDATA2MSB	2
-
-unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' };
-
-int main(int ac, char **av)
-{
-	int fd, n, i;
-	int ph, ps, np;
-	int nnote, ns;
-
-	if (ac != 2) {
-		fprintf(stderr, "Usage: %s elf-file\n", av[0]);
-		exit(1);
-	}
-	fd = open(av[1], O_RDWR);
-	if (fd < 0) {
-		perror(av[1]);
-		exit(1);
-	}
-
-	nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4;
-
-	n = read(fd, buf, sizeof(buf));
-	if (n < 0) {
-		perror("read");
-		exit(1);
-	}
-
-	if (n < E_HSIZE || memcmp(&buf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0)
-		goto notelf;
-
-	if (buf[E_IDENT+EI_CLASS] != ELFCLASS32
-	    || buf[E_IDENT+EI_DATA] != ELFDATA2MSB) {
-		fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n",
-			av[1]);
-		exit(1);
-	}
-
-	ph = GET_32BE(E_PHOFF);
-	ps = GET_16BE(E_PHENTSIZE);
-	np = GET_16BE(E_PHNUM);
-	if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
-		goto notelf;
-	if (ph + (np + 1) * ps + nnote > n)
-		goto nospace;
-
-	for (i = 0; i < np; ++i) {
-		if (GET_32BE(ph + PH_TYPE) == PT_NOTE) {
-			fprintf(stderr, "%s already has a note entry\n",
-				av[1]);
-			exit(0);
-		}
-		ph += ps;
-	}
-
-	/* XXX check that the area we want to use is all zeroes */
-	for (i = 0; i < ps + nnote; ++i)
-		if (buf[ph + i] != 0)
-			goto nospace;
-
-	/* fill in the program header entry */
-	ns = ph + ps;
-	PUT_32BE(ph + PH_TYPE, PT_NOTE);
-	PUT_32BE(ph + PH_OFFSET, ns);
-	PUT_32BE(ph + PH_FILESZ, nnote);
-
-	/* fill in the note area we point to */
-	/* XXX we should probably make this a proper section */
-	PUT_32BE(ns, strlen(arch) + 1);
-	PUT_32BE(ns + 4, N_DESCR * 4);
-	PUT_32BE(ns + 8, 0x1275);
-	strcpy(&buf[ns + 12], arch);
-	ns += 12 + strlen(arch) + 1;
-	for (i = 0; i < N_DESCR; ++i)
-		PUT_32BE(ns + i * 4, descr[i]);
-
-	/* Update the number of program headers */
-	PUT_16BE(E_PHNUM, np + 1);
-
-	/* write back */
-	lseek(fd, (long) 0, SEEK_SET);
-	i = write(fd, buf, n);
-	if (i < 0) {
-		perror("write");
-		exit(1);
-	}
-	if (i < n) {
-		fprintf(stderr, "%s: write truncated\n", av[1]);
-		exit(1);
-	}
-
-	exit(0);
-
- notelf:
-	fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]);
-	exit(1);
-
- nospace:
-	fprintf(stderr, "sorry, I can't find space in %s to put the note\n",
-		av[0]);
-	exit(1);
-}
diff --git a/arch/ppc/boot/utils/hack-coff.c b/arch/ppc/boot/utils/hack-coff.c
deleted file mode 100644
index 5e5a657..0000000
--- a/arch/ppc/boot/utils/hack-coff.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * hack-coff.c - hack the header of an xcoff file to fill in
- * a few fields needed by the Open Firmware xcoff loader on
- * Power Macs but not initialized by objcopy.
- *
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include "rs6000.h"
-
-#define AOUT_MAGIC	0x010b
-
-#define get_16be(x)	((((unsigned char *)(x))[0] << 8) \
-			 + ((unsigned char *)(x))[1])
-#define put_16be(x, v)	(((unsigned char *)(x))[0] = (v) >> 8, \
-			 ((unsigned char *)(x))[1] = (v) & 0xff)
-#define get_32be(x)	((((unsigned char *)(x))[0] << 24) \
-			 + (((unsigned char *)(x))[1] << 16) \
-			 + (((unsigned char *)(x))[2] << 8) \
-			 + ((unsigned char *)(x))[3])
-
-int
-main(int ac, char **av)
-{
-    int fd;
-    int i, nsect;
-    int aoutsz;
-    struct external_filehdr fhdr;
-    AOUTHDR aout;
-    struct external_scnhdr shdr;
-
-    if (ac != 2) {
-	fprintf(stderr, "Usage: hack-coff coff-file\n");
-	exit(1);
-    }
-    if ((fd = open(av[1], 2)) == -1) {
-	perror(av[2]);
-	exit(1);
-    }
-    if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr))
-	goto readerr;
-    i = get_16be(fhdr.f_magic);
-    if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) {
-	fprintf(stderr, "%s: not an xcoff file\n", av[1]);
-	exit(1);
-    }
-    aoutsz = get_16be(fhdr.f_opthdr);
-    if (read(fd, &aout, aoutsz) != aoutsz)
-	goto readerr;
-    nsect = get_16be(fhdr.f_nscns);
-    for (i = 0; i < nsect; ++i) {
-	if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr))
-	    goto readerr;
-	if (strcmp(shdr.s_name, ".text") == 0) {
-	    put_16be(aout.o_snentry, i+1);
-	    put_16be(aout.o_sntext, i+1);
-	} else if (strcmp(shdr.s_name, ".data") == 0) {
-	    put_16be(aout.o_sndata, i+1);
-	} else if (strcmp(shdr.s_name, ".bss") == 0) {
-	    put_16be(aout.o_snbss, i+1);
-	}
-    }
-    put_16be(aout.magic, AOUT_MAGIC);
-    if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1
-	|| write(fd, &aout, aoutsz) != aoutsz) {
-	fprintf(stderr, "%s: write error\n", av[1]);
-	exit(1);
-    }
-    close(fd);
-    exit(0);
-
-readerr:
-    fprintf(stderr, "%s: read error or file too short\n", av[1]);
-    exit(1);
-}
diff --git a/arch/ppc/boot/utils/mknote.c b/arch/ppc/boot/utils/mknote.c
deleted file mode 100644
index b9fbb2c..0000000
--- a/arch/ppc/boot/utils/mknote.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) Cort Dougan 1999.
- *
- * 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.
- *
- * Generate a note section as per the CHRP specification.
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#define PL(x) printf("%c%c%c%c", ((x)>>24)&0xff, ((x)>>16)&0xff, ((x)>>8)&0xff, (x)&0xff );
-
-int main(void)
-{
-/* header */
-	/* namesz */
-	PL(strlen("PowerPC")+1);
-	/* descrsz */
-	PL(6*4);
-	/* type */
-	PL(0x1275);
-	/* name */
-	printf("PowerPC"); printf("%c", 0);
-	
-/* descriptor */
-	/* real-mode */
-	PL(0xffffffff);
-	/* real-base */
-	PL(0x00c00000);
-	/* real-size */
-	PL(0xffffffff);
-	/* virt-base */
-	PL(0xffffffff);
-	/* virt-size */
-	PL(0xffffffff);
-	/* load-base */
-	PL(0x4000);
-	return 0;
-}
diff --git a/arch/ppc/configs/ibmchrp_defconfig b/arch/ppc/configs/ibmchrp_defconfig
deleted file mode 100644
index 27f3e69..0000000
--- a/arch/ppc/configs/ibmchrp_defconfig
+++ /dev/null
@@ -1,875 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MMU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_HAVE_DEC_LOCK=y
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_GENERIC_NVRAM=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-# CONFIG_STANDALONE is not set
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# Processor
-#
-CONFIG_6xx=y
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_POWER3 is not set
-# CONFIG_POWER4 is not set
-# CONFIG_8xx is not set
-# CONFIG_ALTIVEC is not set
-# CONFIG_TAU is not set
-# CONFIG_CPU_FREQ is not set
-# CONFIG_PPC601_SYNC_FIX is not set
-CONFIG_PPC_STD_MMU=y
-
-#
-# Platform options
-#
-CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_APUS is not set
-# CONFIG_WILLOW is not set
-# CONFIG_PCORE is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_EV64260 is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MCPN765 is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-# CONFIG_ADIR is not set
-# CONFIG_K2 is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
-# CONFIG_SBS8260 is not set
-# CONFIG_RPX6 is not set
-# CONFIG_TQM8260 is not set
-CONFIG_PPC_CHRP=y
-CONFIG_PPC_PMAC=y
-CONFIG_PPC_PREP=y
-CONFIG_PPC_OF=y
-CONFIG_PPCBUG_NVRAM=y
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-CONFIG_HIGHMEM=y
-CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
-CONFIG_PROC_DEVICETREE=y
-CONFIG_PPC_RTAS=y
-# CONFIG_PREP_RESIDUAL is not set
-# CONFIG_CMDLINE_BOOL is not set
-
-#
-# Bus options
-#
-CONFIG_ISA=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-
-#
-# Advanced setup
-#
-# CONFIG_ADVANCED_OPTIONS is not set
-
-#
-# Default settings for advanced configuration options are used
-#
-CONFIG_HIGHMEM_START=0xfe000000
-CONFIG_LOWMEM_SIZE=0x30000000
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE=0x80000000
-CONFIG_BOOT_LOAD=0x00800000
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_LBD=y
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-CONFIG_SCSI_SPI_ATTRS=y
-# CONFIG_SCSI_FC_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_NCR53C406A is not set
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
-# CONFIG_SCSI_MAC53C94 is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_ADB is not set
-# CONFIG_ADB_CUDA is not set
-# CONFIG_ADB_PMU is not set
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_MAC_SERIAL is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_QUEUE is not set
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-# CONFIG_IP_NF_MATCH_PKTTYPE is not set
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-# CONFIG_IP_NF_MANGLE is not set
-# CONFIG_IP_NF_TARGET_LOG is not set
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_RAW=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_OAKNET is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-CONFIG_PCNET32=y
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_CS89x0 is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_INPORT is not set
-# CONFIG_MOUSE_LOGIBM is not set
-# CONFIG_MOUSE_PC110PAD is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-# CONFIG_SERIAL_8250_CONSOLE is not set
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-# CONFIG_SERIAL_PMACZILOG is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-CONFIG_NVRAM=y
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_OF=y
-# CONFIG_FB_CONTROL is not set
-# CONFIG_FB_PLATINUM is not set
-# CONFIG_FB_VALKYRIE is not set
-# CONFIG_FB_CT65550 is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_RIVA is not set
-CONFIG_FB_MATROX=y
-CONFIG_FB_MATROX_MILLENIUM=y
-CONFIG_FB_MATROX_MYSTIQUE=y
-# CONFIG_FB_MATROX_G450 is not set
-CONFIG_FB_MATROX_G100A=y
-CONFIG_FB_MATROX_G100=y
-# CONFIG_FB_MATROX_MULTIHEAD is not set
-# CONFIG_FB_RADEON_OLD is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-CONFIG_FB_3DFX=y
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-# CONFIG_NFS_FS is not set
-# CONFIG_NFSD is not set
-# CONFIG_EXPORTFS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Library routines
-#
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_BOOTX_TEXT is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/configs/pmac_defconfig b/arch/ppc/configs/pmac_defconfig
deleted file mode 100644
index a2db8b5..0000000
--- a/arch/ppc/configs/pmac_defconfig
+++ /dev/null
@@ -1,1591 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc3
-# Wed Jul 13 14:13:13 2005
-#
-CONFIG_MMU=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_ALL is not set
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_KMOD=y
-
-#
-# Processor
-#
-CONFIG_6xx=y
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_POWER3 is not set
-# CONFIG_POWER4 is not set
-# CONFIG_8xx is not set
-# CONFIG_E200 is not set
-# CONFIG_E500 is not set
-CONFIG_PPC_FPU=y
-CONFIG_ALTIVEC=y
-CONFIG_TAU=y
-# CONFIG_TAU_INT is not set
-# CONFIG_TAU_AVERAGE is not set
-# CONFIG_KEXEC is not set
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_TABLE=y
-# CONFIG_CPU_FREQ_DEBUG is not set
-CONFIG_CPU_FREQ_STAT=m
-CONFIG_CPU_FREQ_STAT_DETAILS=y
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
-CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-CONFIG_CPU_FREQ_GOV_POWERSAVE=m
-CONFIG_CPU_FREQ_GOV_USERSPACE=m
-CONFIG_CPU_FREQ_GOV_ONDEMAND=m
-CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
-CONFIG_CPU_FREQ_PMAC=y
-CONFIG_PPC601_SYNC_FIX=y
-CONFIG_PM=y
-CONFIG_PPC_STD_MMU=y
-
-#
-# Platform options
-#
-CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_APUS is not set
-# CONFIG_KATANA is not set
-# CONFIG_WILLOW is not set
-# CONFIG_CPCI690 is not set
-# CONFIG_PCORE is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_CHESTNUT is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_HDPU is not set
-# CONFIG_EV64260 is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MCPN765 is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-# CONFIG_RADSTONE_PPC7D is not set
-# CONFIG_ADIR is not set
-# CONFIG_K2 is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
-# CONFIG_SBC82xx is not set
-# CONFIG_SBS8260 is not set
-# CONFIG_RPX8260 is not set
-# CONFIG_TQM8260 is not set
-# CONFIG_ADS8272 is not set
-# CONFIG_PQ2FADS is not set
-# CONFIG_LITE5200 is not set
-# CONFIG_MPC834x_SYS is not set
-CONFIG_PPC_CHRP=y
-CONFIG_PPC_PMAC=y
-CONFIG_PPC_PREP=y
-CONFIG_PPC_OF=y
-CONFIG_PPCBUG_NVRAM=y
-# CONFIG_SMP is not set
-# CONFIG_HIGHMEM is not set
-# CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PROC_DEVICETREE=y
-# CONFIG_PREP_RESIDUAL is not set
-# CONFIG_CMDLINE_BOOL is not set
-# CONFIG_PM_DEBUG is not set
-CONFIG_SOFTWARE_SUSPEND=y
-CONFIG_PM_STD_PARTITION=""
-# CONFIG_SECCOMP is not set
-CONFIG_ISA_DMA_API=y
-
-#
-# Bus options
-#
-# CONFIG_ISA is not set
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-# CONFIG_PCI_DEBUG is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-CONFIG_PCCARD=m
-# CONFIG_PCMCIA_DEBUG is not set
-CONFIG_PCMCIA=m
-# CONFIG_PCMCIA_LOAD_CIS is not set
-# CONFIG_PCMCIA_IOCTL is not set
-CONFIG_CARDBUS=y
-
-#
-# PC-card bridges
-#
-CONFIG_YENTA=m
-# CONFIG_PD6729 is not set
-# CONFIG_I82092 is not set
-# CONFIG_TCIC is not set
-CONFIG_PCCARD_NONSTATIC=m
-
-#
-# Advanced setup
-#
-CONFIG_ADVANCED_OPTIONS=y
-CONFIG_HIGHMEM_START=0xfe000000
-# CONFIG_LOWMEM_SIZE_BOOL is not set
-CONFIG_LOWMEM_SIZE=0x30000000
-# CONFIG_KERNEL_START_BOOL is not set
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE_BOOL=y
-CONFIG_TASK_SIZE=0xc0000000
-CONFIG_BOOT_LOAD=0x00800000
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_REALM=m
-CONFIG_IP_NF_MATCH_SCTP=m
-CONFIG_IP_NF_MATCH_COMMENT=m
-CONFIG_IP_NF_MATCH_CONNMARK=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_TARGET_CONNMARK=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETPOLL=y
-# CONFIG_NETPOLL_RX is not set
-# CONFIG_NETPOLL_TRAP is not set
-CONFIG_NET_POLL_CONTROLLER=y
-# CONFIG_HAMRADIO is not set
-CONFIG_IRDA=m
-
-#
-# IrDA protocols
-#
-CONFIG_IRLAN=m
-CONFIG_IRNET=m
-CONFIG_IRCOMM=m
-# CONFIG_IRDA_ULTRA is not set
-
-#
-# IrDA options
-#
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-
-#
-# SIR device drivers
-#
-CONFIG_IRTTY_SIR=m
-
-#
-# Dongle support
-#
-# CONFIG_DONGLE is not set
-
-#
-# Old SIR device drivers
-#
-# CONFIG_IRPORT_SIR is not set
-
-#
-# Old Serial dongle support
-#
-
-#
-# FIR device drivers
-#
-# CONFIG_USB_IRDA is not set
-# CONFIG_SIGMATEL_FIR is not set
-# CONFIG_NSC_FIR is not set
-# CONFIG_WINBOND_FIR is not set
-# CONFIG_TOSHIBA_FIR is not set
-# CONFIG_SMC_IRCC_FIR is not set
-# CONFIG_ALI_FIR is not set
-# CONFIG_VLSI_FIR is not set
-# CONFIG_VIA_FIR is not set
-# CONFIG_BT is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-# CONFIG_STANDALONE is not set
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-CONFIG_MAC_FLOPPY=m
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_UB is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-CONFIG_LBD=y
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDECS is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=y
-CONFIG_BLK_DEV_IDESCSI=y
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_IDE_GENERIC is not set
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-CONFIG_BLK_DEV_GENERIC=y
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-CONFIG_BLK_DEV_CMD64X=y
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-CONFIG_BLK_DEV_PDC202XX_NEW=y
-# CONFIG_PDC202XX_FORCE is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-CONFIG_BLK_DEV_IDE_PMAC=y
-CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
-CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_BLK_DEV_IDE_PMAC_BLINK=y
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
-# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-CONFIG_SCSI_SPI_ATTRS=y
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-CONFIG_SCSI_AIC7XXX=m
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-CONFIG_AIC7XXX_DEBUG_ENABLE=y
-CONFIG_AIC7XXX_DEBUG_MASK=0
-CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
-CONFIG_SCSI_AIC7XXX_OLD=m
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_LPFC is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-CONFIG_SCSI_MESH=y
-CONFIG_SCSI_MESH_SYNC_RATE=5
-CONFIG_SCSI_MESH_RESET_DELAY_MS=1000
-CONFIG_SCSI_MAC53C94=y
-
-#
-# PCMCIA SCSI adapter support
-#
-# CONFIG_PCMCIA_AHA152X is not set
-# CONFIG_PCMCIA_FDOMAIN is not set
-# CONFIG_PCMCIA_NINJA_SCSI is not set
-# CONFIG_PCMCIA_QLOGIC is not set
-# CONFIG_PCMCIA_SYM53C500 is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-CONFIG_IEEE1394=m
-
-#
-# Subsystem Options
-#
-# CONFIG_IEEE1394_VERBOSEDEBUG is not set
-# CONFIG_IEEE1394_OUI_DB is not set
-CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
-CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
-# CONFIG_IEEE1394_EXPORT_FULL_API is not set
-
-#
-# Device Drivers
-#
-# CONFIG_IEEE1394_PCILYNX is not set
-CONFIG_IEEE1394_OHCI1394=m
-
-#
-# Protocol Drivers
-#
-CONFIG_IEEE1394_VIDEO1394=m
-CONFIG_IEEE1394_SBP2=m
-# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
-CONFIG_IEEE1394_ETH1394=m
-CONFIG_IEEE1394_DV1394=m
-CONFIG_IEEE1394_RAWIO=m
-CONFIG_IEEE1394_CMP=m
-CONFIG_IEEE1394_AMDTP=m
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-CONFIG_ADB=y
-CONFIG_ADB_CUDA=y
-CONFIG_ADB_PMU=y
-CONFIG_PMAC_APM_EMU=y
-CONFIG_PMAC_MEDIABAY=y
-CONFIG_PMAC_BACKLIGHT=y
-CONFIG_ADB_MACIO=y
-CONFIG_INPUT_ADBHID=y
-CONFIG_MAC_EMUMOUSEBTN=y
-CONFIG_THERM_WINDTUNNEL=m
-CONFIG_THERM_ADT746X=m
-# CONFIG_ANSLCD is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACE=y
-# CONFIG_MACE_AAUI_PORT is not set
-CONFIG_BMAC=y
-# CONFIG_HAPPYMEAL is not set
-CONFIG_SUNGEM=y
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-CONFIG_PCNET32=y
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-# CONFIG_MV643XX_ETH is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-# CONFIG_PCMCIA_WAVELAN is not set
-# CONFIG_PCMCIA_NETWAVE is not set
-
-#
-# Wireless 802.11 Frequency Hopping cards support
-#
-# CONFIG_PCMCIA_RAYCS is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-CONFIG_HERMES=m
-CONFIG_APPLE_AIRPORT=m
-# CONFIG_PLX_HERMES is not set
-# CONFIG_TMD_HERMES is not set
-# CONFIG_PCI_HERMES is not set
-# CONFIG_ATMEL is not set
-
-#
-# Wireless 802.11b Pcmcia/Cardbus cards support
-#
-CONFIG_PCMCIA_HERMES=m
-# CONFIG_AIRO_CS is not set
-# CONFIG_PCMCIA_WL3501 is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-# CONFIG_PRISM54 is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# PCMCIA network device support
-#
-# CONFIG_NET_PCMCIA is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-CONFIG_NETCONSOLE=m
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-# CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_INPUT_MOUSE=y
-# CONFIG_MOUSE_PS2 is not set
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=m
-CONFIG_SERIAL_8250_CS=m
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_SERIAL_PMACZILOG=y
-CONFIG_SERIAL_PMACZILOG_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-CONFIG_NVRAM=y
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-CONFIG_AGP=m
-CONFIG_AGP_UNINORTH=m
-CONFIG_DRM=m
-# CONFIG_DRM_TDFX is not set
-CONFIG_DRM_R128=m
-CONFIG_DRM_RADEON=m
-# CONFIG_DRM_MGA is not set
-# CONFIG_DRM_SIS is not set
-# CONFIG_DRM_VIA is not set
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=m
-
-#
-# I2C Algorithms
-#
-CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_HYDRA is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_ISA is not set
-CONFIG_I2C_KEYWEST=m
-# CONFIG_I2C_MPC is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_SENSORS_M41T00 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
-CONFIG_FB_MACMODES=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_TILEBLITTING=y
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_OF=y
-CONFIG_FB_CONTROL=y
-CONFIG_FB_PLATINUM=y
-CONFIG_FB_VALKYRIE=y
-CONFIG_FB_CT65550=y
-# CONFIG_FB_ASILIANT is not set
-CONFIG_FB_IMSTT=y
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-CONFIG_FB_MATROX=y
-CONFIG_FB_MATROX_MILLENIUM=y
-CONFIG_FB_MATROX_MYSTIQUE=y
-CONFIG_FB_MATROX_G=y
-# CONFIG_FB_MATROX_I2C is not set
-# CONFIG_FB_MATROX_MULTIHEAD is not set
-# CONFIG_FB_RADEON_OLD is not set
-CONFIG_FB_RADEON=y
-CONFIG_FB_RADEON_I2C=y
-# CONFIG_FB_RADEON_DEBUG is not set
-CONFIG_FB_ATY128=y
-CONFIG_FB_ATY=y
-CONFIG_FB_ATY_CT=y
-CONFIG_FB_ATY_GENERIC_LCD=y
-# CONFIG_FB_ATY_XL_INIT is not set
-CONFIG_FB_ATY_GX=y
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-CONFIG_FB_3DFX=y
-CONFIG_FB_3DFX_ACCEL=y
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_LCD_DEVICE=y
-
-#
-# Sound
-#
-CONFIG_SOUND=m
-CONFIG_DMASOUND_PMAC=m
-CONFIG_DMASOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
-CONFIG_SND=m
-CONFIG_SND_TIMER=m
-CONFIG_SND_PCM=m
-CONFIG_SND_HWDEP=m
-CONFIG_SND_RAWMIDI=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-CONFIG_SND_DUMMY=m
-# CONFIG_SND_VIRMIDI is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# PCI devices
-#
-# CONFIG_SND_ALI5451 is not set
-# CONFIG_SND_ATIIXP is not set
-# CONFIG_SND_ATIIXP_MODEM is not set
-# CONFIG_SND_AU8810 is not set
-# CONFIG_SND_AU8820 is not set
-# CONFIG_SND_AU8830 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_EMU10K1X is not set
-# CONFIG_SND_CA0106 is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_ALS4000 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_ENS1370 is not set
-# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_MAESTRO3 is not set
-# CONFIG_SND_FM801 is not set
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-# CONFIG_SND_INTEL8X0 is not set
-# CONFIG_SND_INTEL8X0M is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_VIA82XX is not set
-# CONFIG_SND_VIA82XX_MODEM is not set
-# CONFIG_SND_VX222 is not set
-# CONFIG_SND_HDA_INTEL is not set
-
-#
-# ALSA PowerMac devices
-#
-CONFIG_SND_POWERMAC=m
-
-#
-# USB devices
-#
-CONFIG_SND_USB_AUDIO=m
-CONFIG_SND_USB_USX2Y=m
-
-#
-# PCMCIA devices
-#
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
-CONFIG_USB_DYNAMIC_MINORS=y
-CONFIG_USB_SUSPEND=y
-# CONFIG_USB_OTG is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_EHCI_HCD is not set
-# CONFIG_USB_ISP116X_HCD is not set
-CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-# CONFIG_USB_UHCI_HCD is not set
-# CONFIG_USB_SL811_HCD is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-# CONFIG_USB_STORAGE is not set
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-CONFIG_USB_PEGASUS=m
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET is not set
-# CONFIG_USB_ZD1201 is not set
-# CONFIG_USB_MON is not set
-
-#
-# USB port drivers
-#
-
-#
-# USB Serial Converter support
-#
-CONFIG_USB_SERIAL=m
-# CONFIG_USB_SERIAL_GENERIC is not set
-# CONFIG_USB_SERIAL_AIRPRIME is not set
-# CONFIG_USB_SERIAL_BELKIN is not set
-# CONFIG_USB_SERIAL_WHITEHEAT is not set
-# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-# CONFIG_USB_SERIAL_CP2101 is not set
-# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
-# CONFIG_USB_SERIAL_EMPEG is not set
-# CONFIG_USB_SERIAL_FTDI_SIO is not set
-CONFIG_USB_SERIAL_VISOR=m
-# CONFIG_USB_SERIAL_IPAQ is not set
-# CONFIG_USB_SERIAL_IR is not set
-# CONFIG_USB_SERIAL_EDGEPORT is not set
-# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
-# CONFIG_USB_SERIAL_GARMIN is not set
-# CONFIG_USB_SERIAL_IPW is not set
-# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-CONFIG_USB_SERIAL_KEYSPAN=m
-CONFIG_USB_SERIAL_KEYSPAN_MPR=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19=y
-CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
-# CONFIG_USB_SERIAL_KLSI is not set
-# CONFIG_USB_SERIAL_KOBIL_SCT is not set
-# CONFIG_USB_SERIAL_MCT_U232 is not set
-# CONFIG_USB_SERIAL_PL2303 is not set
-# CONFIG_USB_SERIAL_HP4X is not set
-# CONFIG_USB_SERIAL_SAFE is not set
-# CONFIG_USB_SERIAL_TI is not set
-# CONFIG_USB_SERIAL_CYBERJACK is not set
-# CONFIG_USB_SERIAL_XIRCOM is not set
-# CONFIG_USB_SERIAL_OPTION is not set
-# CONFIG_USB_SERIAL_OMNINET is not set
-CONFIG_USB_EZUSB=y
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_LD is not set
-# CONFIG_USB_TEST is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# SN Devices
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-# CONFIG_EXT2_FS_POSIX_ACL is not set
-# CONFIG_EXT2_FS_SECURITY is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-
-#
-# XFS support
-#
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-CONFIG_UDF_FS=m
-CONFIG_UDF_NLS=y
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-CONFIG_DEVPTS_FS_XATTR=y
-CONFIG_DEVPTS_FS_SECURITY=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_XATTR=y
-CONFIG_TMPFS_SECURITY=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=m
-CONFIG_HFSPLUS_FS=m
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-CONFIG_CRAMFS=m
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V2_ACL=y
-CONFIG_NFSD_V3=y
-CONFIG_NFSD_V3_ACL=y
-# CONFIG_NFSD_V4 is not set
-CONFIG_NFSD_TCP=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_ACL_SUPPORT=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-CONFIG_NLS_ISO8859_15=m
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-CONFIG_NLS_UTF8=m
-
-#
-# Library routines
-#
-CONFIG_CRC_CCITT=y
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOG_BUF_SHIFT=16
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_XMON is not set
-# CONFIG_BDI_SWITCH is not set
-CONFIG_BOOTX_TEXT=y
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
diff --git a/arch/ppc/configs/power3_defconfig b/arch/ppc/configs/power3_defconfig
deleted file mode 100644
index a1ef929..0000000
--- a/arch/ppc/configs/power3_defconfig
+++ /dev/null
@@ -1,1035 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MMU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_HAVE_DEC_LOCK=y
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_GENERIC_NVRAM=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-# CONFIG_STANDALONE is not set
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=15
-# CONFIG_HOTPLUG is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-CONFIG_STOP_MACHINE=y
-
-#
-# Processor
-#
-# CONFIG_6xx is not set
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-CONFIG_POWER3=y
-# CONFIG_POWER4 is not set
-# CONFIG_8xx is not set
-# CONFIG_CPU_FREQ is not set
-CONFIG_PPC64BRIDGE=y
-CONFIG_PPC_STD_MMU=y
-
-#
-# Platform options
-#
-CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_APUS is not set
-# CONFIG_WILLOW is not set
-# CONFIG_PCORE is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_EV64260 is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MCPN765 is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-# CONFIG_ADIR is not set
-# CONFIG_K2 is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
-# CONFIG_SBS8260 is not set
-# CONFIG_RPX6 is not set
-# CONFIG_TQM8260 is not set
-CONFIG_PPC_CHRP=y
-CONFIG_PPC_PMAC=y
-CONFIG_PPC_PREP=y
-CONFIG_PPC_OF=y
-CONFIG_PPCBUG_NVRAM=y
-CONFIG_SMP=y
-# CONFIG_IRQ_ALL_CPUS is not set
-CONFIG_NR_CPUS=32
-# CONFIG_PREEMPT is not set
-CONFIG_HIGHMEM=y
-CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
-CONFIG_PROC_DEVICETREE=y
-CONFIG_PPC_RTAS=y
-# CONFIG_PREP_RESIDUAL is not set
-# CONFIG_CMDLINE_BOOL is not set
-
-#
-# Bus options
-#
-CONFIG_ISA=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-
-#
-# Advanced setup
-#
-CONFIG_ADVANCED_OPTIONS=y
-# CONFIG_HIGHMEM_START_BOOL is not set
-CONFIG_HIGHMEM_START=0xfe000000
-# CONFIG_LOWMEM_SIZE_BOOL is not set
-CONFIG_LOWMEM_SIZE=0x30000000
-# CONFIG_KERNEL_START_BOOL is not set
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE_BOOL=y
-CONFIG_TASK_SIZE=0xc0000000
-CONFIG_BOOT_LOAD=0x00800000
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
-# CONFIG_PARPORT_SERIAL is not set
-CONFIG_PARPORT_PC_FIFO=y
-# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_OTHER is not set
-# CONFIG_PARPORT_1284 is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_LBD=y
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-
-#
-# SCSI Transport Attributes
-#
-CONFIG_SCSI_SPI_ATTRS=y
-# CONFIG_SCSI_FC_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
-# CONFIG_SCSI_NCR53C406A is not set
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
-# CONFIG_SCSI_MAC53C94 is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-CONFIG_MD_RAID5=y
-CONFIG_MD_RAID6=y
-# CONFIG_MD_MULTIPATH is not set
-CONFIG_BLK_DEV_DM=y
-CONFIG_DM_CRYPT=y
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_ADB is not set
-# CONFIG_ADB_CUDA is not set
-# CONFIG_ADB_PMU is not set
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_MAC_SERIAL is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_OAKNET is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-CONFIG_PCNET32=y
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_CS89x0 is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-CONFIG_E100=y
-# CONFIG_E100_NAPI is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-CONFIG_E1000=y
-# CONFIG_E1000_NAPI is not set
-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-CONFIG_GAMEPORT=m
-CONFIG_SOUND_GAMEPORT=m
-# CONFIG_GAMEPORT_NS558 is not set
-# CONFIG_GAMEPORT_L4 is not set
-# CONFIG_GAMEPORT_EMU10K1 is not set
-# CONFIG_GAMEPORT_VORTEX is not set
-# CONFIG_GAMEPORT_FM801 is not set
-# CONFIG_GAMEPORT_CS461x is not set
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_INPORT is not set
-# CONFIG_MOUSE_LOGIBM is not set
-# CONFIG_MOUSE_PC110PAD is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_PMACZILOG is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-CONFIG_PRINTER=m
-# CONFIG_LP_CONSOLE is not set
-# CONFIG_PPDEV is not set
-# CONFIG_TIPAR is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-CONFIG_NVRAM=y
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-CONFIG_I2C_ALGOBIT=y
-CONFIG_I2C_ALGOPCF=y
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_HYDRA is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
-# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_KEYWEST is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-
-#
-# Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_OF=y
-# CONFIG_FB_CONTROL is not set
-# CONFIG_FB_PLATINUM is not set
-# CONFIG_FB_VALKYRIE is not set
-# CONFIG_FB_CT65550 is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_RIVA is not set
-CONFIG_FB_MATROX=y
-CONFIG_FB_MATROX_MILLENIUM=y
-CONFIG_FB_MATROX_MYSTIQUE=y
-# CONFIG_FB_MATROX_G450 is not set
-CONFIG_FB_MATROX_G100A=y
-CONFIG_FB_MATROX_G100=y
-CONFIG_FB_MATROX_I2C=y
-# CONFIG_FB_MATROX_MAVEN is not set
-CONFIG_FB_MATROX_MULTIHEAD=y
-# CONFIG_FB_RADEON_OLD is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-# CONFIG_DMASOUND_PMAC is not set
-
-#
-# Advanced Linux Sound Architecture
-#
-CONFIG_SND=m
-CONFIG_SND_TIMER=m
-CONFIG_SND_PCM=m
-CONFIG_SND_HWDEP=m
-CONFIG_SND_RAWMIDI=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-CONFIG_SND_MPU401_UART=m
-CONFIG_SND_OPL3_LIB=m
-CONFIG_SND_DUMMY=m
-# CONFIG_SND_VIRMIDI is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# ISA devices
-#
-# CONFIG_SND_AD1848 is not set
-# CONFIG_SND_CS4231 is not set
-CONFIG_SND_CS4232=m
-# CONFIG_SND_CS4236 is not set
-# CONFIG_SND_ES1688 is not set
-# CONFIG_SND_ES18XX is not set
-# CONFIG_SND_GUSCLASSIC is not set
-# CONFIG_SND_GUSEXTREME is not set
-# CONFIG_SND_GUSMAX is not set
-# CONFIG_SND_INTERWAVE is not set
-# CONFIG_SND_INTERWAVE_STB is not set
-# CONFIG_SND_OPTI92X_AD1848 is not set
-# CONFIG_SND_OPTI92X_CS4231 is not set
-# CONFIG_SND_OPTI93X is not set
-# CONFIG_SND_SB8 is not set
-# CONFIG_SND_SB16 is not set
-# CONFIG_SND_SBAWE is not set
-# CONFIG_SND_WAVEFRONT is not set
-# CONFIG_SND_CMI8330 is not set
-# CONFIG_SND_OPL3SA2 is not set
-# CONFIG_SND_SGALAXY is not set
-# CONFIG_SND_SSCAPE is not set
-
-#
-# PCI devices
-#
-CONFIG_SND_AC97_CODEC=m
-# CONFIG_SND_ALI5451 is not set
-# CONFIG_SND_ATIIXP is not set
-# CONFIG_SND_AU8810 is not set
-# CONFIG_SND_AU8820 is not set
-# CONFIG_SND_AU8830 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-CONFIG_SND_CS46XX=m
-# CONFIG_SND_CS46XX_NEW_DSP is not set
-CONFIG_SND_CS4281=m
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_ALS4000 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_ENS1370 is not set
-# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_MAESTRO3 is not set
-# CONFIG_SND_FM801 is not set
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-# CONFIG_SND_INTEL8X0 is not set
-# CONFIG_SND_INTEL8X0M is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_VIA82XX is not set
-# CONFIG_SND_VX222 is not set
-
-#
-# ALSA PowerMac devices
-#
-# CONFIG_SND_POWERMAC is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-# CONFIG_ZISOFS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=y
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Library routines
-#
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_BOOTX_TEXT=y
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-# CONFIG_CRYPTO_SERPENT is not set
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_TEST is not set
diff --git a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/prep_defconfig
similarity index 100%
rename from arch/ppc/configs/common_defconfig
rename to arch/ppc/configs/prep_defconfig
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index e399bbb..466437f 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -1,48 +1,24 @@
 #
 # Makefile for the linux kernel.
 #
-ifneq ($(CONFIG_PPC_MERGE),y)
-
 extra-$(CONFIG_PPC_STD_MMU)	:= head.o
 extra-$(CONFIG_40x)		:= head_4xx.o
 extra-$(CONFIG_44x)		:= head_44x.o
 extra-$(CONFIG_FSL_BOOKE)	:= head_fsl_booke.o
 extra-$(CONFIG_8xx)		:= head_8xx.o
-extra-$(CONFIG_6xx)		+= idle_6xx.o
 extra-y				+= vmlinux.lds
 
-obj-y				:= entry.o traps.o idle.o time.o misc.o \
+obj-y				:= entry.o traps.o time.o misc.o \
 					setup.o \
 					ppc_htab.o
-obj-$(CONFIG_6xx)		+= l2cr.o cpu_setup_6xx.o
-obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o
-obj-$(CONFIG_MODULES)		+= module.o ppc_ksyms.o
+obj-$(CONFIG_MODULES)		+= ppc_ksyms.o
 obj-$(CONFIG_NOT_COHERENT_CACHE)	+= dma-mapping.o
 obj-$(CONFIG_PCI)		+= pci.o
 obj-$(CONFIG_RAPIDIO)		+= rio.o
 obj-$(CONFIG_KGDB)		+= ppc-stub.o
 obj-$(CONFIG_SMP)		+= smp.o smp-tbsync.o
-obj-$(CONFIG_TAU)		+= temp.o
-ifndef CONFIG_E200
-obj-$(CONFIG_FSL_BOOKE)		+= perfmon_fsl_booke.o
-endif
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 
 ifndef CONFIG_MATH_EMULATION
 obj-$(CONFIG_8xx)		+= softemu8xx.o
 endif
-
-# These are here while we do the architecture merge
-
-else
-obj-y				:= idle.o
-obj-$(CONFIG_6xx)		+= l2cr.o cpu_setup_6xx.o
-obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o
-obj-$(CONFIG_MODULES)		+= module.o
-obj-$(CONFIG_NOT_COHERENT_CACHE)	+= dma-mapping.o
-obj-$(CONFIG_KGDB)		+= ppc-stub.o
-obj-$(CONFIG_TAU)		+= temp.o
-ifndef CONFIG_E200
-obj-$(CONFIG_FSL_BOOKE)		+= perfmon_fsl_booke.o
-endif
-endif
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 3a28159..5891ecb 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -135,10 +135,10 @@
 	mfspr	r11,SPRN_HID0
 	mtcr	r11
 BEGIN_FTR_SECTION
-	bt-	8,power_save_6xx_restore	/* Check DOZE */
+	bt-	8,4f			/* Check DOZE */
 END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
 BEGIN_FTR_SECTION
-	bt-	9,power_save_6xx_restore	/* Check NAP */
+	bt-	9,4f			/* Check NAP */
 END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
 #endif /* CONFIG_6xx */
 	.globl transfer_to_handler_cont
@@ -157,6 +157,10 @@
 	SYNC
 	RFI				/* jump to handler, enable MMU */
 
+#ifdef CONFIG_6xx
+4:	b	power_save_6xx_restore
+#endif
+
 /*
  * On kernel stack overflow, load up an initial stack pointer
  * and call StackOverflow(regs), which should not return.
@@ -926,55 +930,3 @@
 	b	4b
 
 	.comm	ee_restarts,4
-
-/*
- * PROM code for specific machines follows.  Put it
- * here so it's easy to add arch-specific sections later.
- * -- Cort
- */
-#ifdef CONFIG_PPC_OF
-/*
- * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
- * called with the MMU off.
- */
-_GLOBAL(enter_rtas)
-	stwu	r1,-INT_FRAME_SIZE(r1)
-	mflr	r0
-	stw	r0,INT_FRAME_SIZE+4(r1)
-	lis	r4,rtas_data@ha
-	lwz	r4,rtas_data@l(r4)
-	lis	r6,1f@ha	/* physical return address for rtas */
-	addi	r6,r6,1f@l
-	tophys(r6,r6)
-	tophys(r7,r1)
-	lis	r8,rtas_entry@ha
-	lwz	r8,rtas_entry@l(r8)
-	mfmsr	r9
-	stw	r9,8(r1)
-	LOAD_MSR_KERNEL(r0,MSR_KERNEL)
-	SYNC			/* disable interrupts so SRR0/1 */
-	MTMSRD(r0)		/* don't get trashed */
-	li	r9,MSR_KERNEL & ~(MSR_IR|MSR_DR)
-	mtlr	r6
-	CLR_TOP32(r7)
-	mtspr	SPRN_SPRG2,r7
-	mtspr	SPRN_SRR0,r8
-	mtspr	SPRN_SRR1,r9
-	RFI
-1:	tophys(r9,r1)
-	lwz	r8,INT_FRAME_SIZE+4(r9)	/* get return address */
-	lwz	r9,8(r9)	/* original msr value */
-	FIX_SRR1(r9,r0)
-	addi	r1,r1,INT_FRAME_SIZE
-	li	r0,0
-	mtspr	SPRN_SPRG2,r0
-	mtspr	SPRN_SRR0,r8
-	mtspr	SPRN_SRR1,r9
-	RFI			/* return to caller */
-
-	.globl	machine_check_in_rtas
-machine_check_in_rtas:
-	twi	31,0,0
-	/* XXX load up BATs and panic */
-
-#endif /* CONFIG_PPC_OF */
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 53ea845..01303ef 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -37,19 +37,6 @@
 #include <asm/amigappc.h>
 #endif
 
-#ifdef CONFIG_PPC64BRIDGE
-#define LOAD_BAT(n, reg, RA, RB)	\
-	ld	RA,(n*32)+0(reg);	\
-	ld	RB,(n*32)+8(reg);	\
-	mtspr	SPRN_IBAT##n##U,RA;	\
-	mtspr	SPRN_IBAT##n##L,RB;	\
-	ld	RA,(n*32)+16(reg);	\
-	ld	RB,(n*32)+24(reg);	\
-	mtspr	SPRN_DBAT##n##U,RA;	\
-	mtspr	SPRN_DBAT##n##L,RB;	\
-
-#else /* CONFIG_PPC64BRIDGE */
-
 /* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
 #define LOAD_BAT(n, reg, RA, RB)	\
 	/* see the comment for clear_bats() -- Cort */ \
@@ -66,7 +53,6 @@
 	mtspr	SPRN_DBAT##n##U,RA;	\
 	mtspr	SPRN_DBAT##n##L,RB;	\
 1:
-#endif /* CONFIG_PPC64BRIDGE */
 
 	.text
 	.stabs	"arch/ppc/kernel/",N_SO,0,0,0f
@@ -129,11 +115,6 @@
 
 	.globl	__start
 __start:
-/*
- * We have to do any OF calls before we map ourselves to KERNELBASE,
- * because OF may have I/O devices mapped into that area
- * (particularly on CHRP).
- */
 	mr	r31,r3			/* save parameters */
 	mr	r30,r4
 	mr	r29,r5
@@ -148,14 +129,6 @@
  */
 	bl	early_init
 
-/*
- * On POWER4, we first need to tweak some CPU configuration registers
- * like real mode cache inhibit or exception base
- */
-#ifdef CONFIG_POWER4
-	bl	__970_cpu_preinit
-#endif /* CONFIG_POWER4 */
-
 #ifdef CONFIG_APUS
 /* On APUS the __va/__pa constants need to be set to the correct
  * values before continuing.
@@ -169,7 +142,6 @@
  */
  	bl	mmu_off
 __after_mmu_off:
-#ifndef CONFIG_POWER4
 	bl	clear_bats
 	bl	flush_tlbs
 
@@ -177,10 +149,6 @@
 #if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
 	bl	setup_disp_bat
 #endif
-#else /* CONFIG_POWER4 */
-	bl	reloc_offset
-	bl	initial_mm_power4
-#endif /* CONFIG_POWER4 */
 
 /*
  * Call setup_cpu for CPU 0 and initialize 6xx Idle
@@ -192,18 +160,11 @@
 	bl	reloc_offset
 	bl	init_idle_6xx
 #endif /* CONFIG_6xx */
-#ifdef CONFIG_POWER4
-	bl	reloc_offset
-	bl	init_idle_power4
-#endif /* CONFIG_POWER4 */
 
 
 #ifndef CONFIG_APUS
 /*
  * We need to run with _start at physical address 0.
- * On CHRP, we are loaded at 0x10000 since OF on CHRP uses
- * the exception vectors at 0 (and therefore this copy
- * overwrites OF's exception vectors with our own).
  * If the MMU is already turned on, we copy stuff to KERNELBASE,
  * otherwise we copy it to 0.
  */
@@ -358,51 +319,19 @@
 #endif
 
 /* Machine check */
-/*
- * On CHRP, this is complicated by the fact that we could get a
- * machine check inside RTAS, and we have no guarantee that certain
- * critical registers will have the values we expect.  The set of
- * registers that might have bad values includes all the GPRs
- * and all the BATs.  We indicate that we are in RTAS by putting
- * a non-zero value, the address of the exception frame to use,
- * in SPRG2.  The machine check handler checks SPRG2 and uses its
- * value if it is non-zero.  If we ever needed to free up SPRG2,
- * we could use a field in the thread_info or thread_struct instead.
- * (Other exception handlers assume that r1 is a valid kernel stack
- * pointer when we take an exception from supervisor mode.)
- *	-- paulus.
- */
 	. = 0x200
 	mtspr	SPRN_SPRG0,r10
 	mtspr	SPRN_SPRG1,r11
 	mfcr	r10
-#ifdef CONFIG_PPC_CHRP
-	mfspr	r11,SPRN_SPRG2
-	cmpwi	0,r11,0
-	bne	7f
-#endif /* CONFIG_PPC_CHRP */
 	EXCEPTION_PROLOG_1
 7:	EXCEPTION_PROLOG_2
 	addi	r3,r1,STACK_FRAME_OVERHEAD
-#ifdef CONFIG_PPC_CHRP
-	mfspr	r4,SPRN_SPRG2
-	cmpwi	cr1,r4,0
-	bne	cr1,1f
-#endif
 	EXC_XFER_STD(0x200, machine_check_exception)
-#ifdef CONFIG_PPC_CHRP
-1:	b	machine_check_in_rtas
-#endif
 
 /* Data access exception. */
 	. = 0x300
-#ifdef CONFIG_PPC64BRIDGE
-	b	DataAccess
-DataAccessCont:
-#else
 DataAccess:
 	EXCEPTION_PROLOG
-#endif /* CONFIG_PPC64BRIDGE */
 	mfspr	r10,SPRN_DSISR
 	andis.	r0,r10,0xa470		/* weird error? */
 	bne	1f			/* if not, try to put a PTE */
@@ -414,21 +343,10 @@
 	mfspr	r4,SPRN_DAR
 	EXC_XFER_EE_LITE(0x300, handle_page_fault)
 
-#ifdef CONFIG_PPC64BRIDGE
-/* SLB fault on data access. */
-	. = 0x380
-	b	DataSegment
-#endif /* CONFIG_PPC64BRIDGE */
-
 /* Instruction access exception. */
 	. = 0x400
-#ifdef CONFIG_PPC64BRIDGE
-	b	InstructionAccess
-InstructionAccessCont:
-#else
 InstructionAccess:
 	EXCEPTION_PROLOG
-#endif /* CONFIG_PPC64BRIDGE */
 	andis.	r0,r9,0x4000		/* no pte found? */
 	beq	1f			/* if so, try to put a PTE */
 	li	r3,0			/* into the hash table */
@@ -438,12 +356,6 @@
 	mr	r5,r9
 	EXC_XFER_EE_LITE(0x400, handle_page_fault)
 
-#ifdef CONFIG_PPC64BRIDGE
-/* SLB fault on instruction access. */
-	. = 0x480
-	b	InstructionSegment
-#endif /* CONFIG_PPC64BRIDGE */
-
 /* External interrupt */
 	EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
 
@@ -708,15 +620,9 @@
 	EXCEPTION(0x1300, Trap_13, instruction_breakpoint_exception, EXC_XFER_EE)
 	EXCEPTION(0x1400, SMI, SMIException, EXC_XFER_EE)
 	EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
-#ifdef CONFIG_POWER4
-	EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_EE)
-	EXCEPTION(0x1700, Trap_17, altivec_assist_exception, EXC_XFER_EE)
-	EXCEPTION(0x1800, Trap_18, TAUException, EXC_XFER_STD)
-#else /* !CONFIG_POWER4 */
 	EXCEPTION(0x1600, Trap_16, altivec_assist_exception, EXC_XFER_EE)
 	EXCEPTION(0x1700, Trap_17, TAUException, EXC_XFER_STD)
 	EXCEPTION(0x1800, Trap_18, unknown_exception, EXC_XFER_EE)
-#endif /* CONFIG_POWER4 */
 	EXCEPTION(0x1900, Trap_19, unknown_exception, EXC_XFER_EE)
 	EXCEPTION(0x1a00, Trap_1a, unknown_exception, EXC_XFER_EE)
 	EXCEPTION(0x1b00, Trap_1b, unknown_exception, EXC_XFER_EE)
@@ -754,28 +660,6 @@
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	EXC_XFER_EE_LITE(0xf20, altivec_unavailable_exception)
 
-#ifdef CONFIG_PPC64BRIDGE
-DataAccess:
-	EXCEPTION_PROLOG
-	b	DataAccessCont
-
-InstructionAccess:
-	EXCEPTION_PROLOG
-	b	InstructionAccessCont
-
-DataSegment:
-	EXCEPTION_PROLOG
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	mfspr	r4,SPRN_DAR
-	stw	r4,_DAR(r11)
-	EXC_XFER_STD(0x380, unknown_exception)
-
-InstructionSegment:
-	EXCEPTION_PROLOG
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	EXC_XFER_STD(0x480, unknown_exception)
-#endif /* CONFIG_PPC64BRIDGE */
-
 #ifdef CONFIG_ALTIVEC
 /* Note that the AltiVec support is closely modeled after the FP
  * support.  Changes to one are likely to be applicable to the
@@ -1048,13 +932,6 @@
 
 	.globl	__secondary_start
 __secondary_start:
-#ifdef CONFIG_PPC64BRIDGE
-	mfmsr	r0
-	clrldi	r0,r0,1			/* make sure it's in 32-bit mode */
-	SYNC
-	MTMSRD(r0)
-	isync
-#endif
 	/* Copy some CPU settings from CPU 0 */
 	bl	__restore_cpu_setup
 
@@ -1065,10 +942,6 @@
 	lis	r3,-KERNELBASE@h
 	bl	init_idle_6xx
 #endif /* CONFIG_6xx */
-#ifdef CONFIG_POWER4
-	lis	r3,-KERNELBASE@h
-	bl	init_idle_power4
-#endif /* CONFIG_POWER4 */
 
 	/* get current_thread_info and current */
 	lis	r1,secondary_ti@ha
@@ -1109,12 +982,12 @@
  * Those generic dummy functions are kept for CPUs not
  * included in CONFIG_6xx
  */
-#if !defined(CONFIG_6xx) && !defined(CONFIG_POWER4)
+#if !defined(CONFIG_6xx)
 _GLOBAL(__save_cpu_setup)
 	blr
 _GLOBAL(__restore_cpu_setup)
 	blr
-#endif /* !defined(CONFIG_6xx) && !defined(CONFIG_POWER4) */
+#endif /* !defined(CONFIG_6xx) */
 
 
 /*
@@ -1132,11 +1005,6 @@
 	tophys(r6,r6)
 	lwz	r6,_SDR1@l(r6)
 	mtspr	SPRN_SDR1,r6
-#ifdef CONFIG_PPC64BRIDGE
-	/* clear the ASR so we only use the pseudo-segment registers. */
-	li	r6,0
-	mtasr	r6
-#endif /* CONFIG_PPC64BRIDGE */
 	li	r0,16		/* load up segment register values */
 	mtctr	r0		/* for context 0 */
 	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
@@ -1145,7 +1013,7 @@
 	addi	r3,r3,0x111	/* increment VSID */
 	addis	r4,r4,0x1000	/* address of next segment */
 	bdnz	3b
-#ifndef CONFIG_POWER4
+
 /* Load the BAT registers with the values set up by MMU_init.
    MMU_init takes care of whether we're on a 601 or not. */
 	mfpvr	r3
@@ -1158,7 +1026,7 @@
 	LOAD_BAT(1,r3,r4,r5)
 	LOAD_BAT(2,r3,r4,r5)
 	LOAD_BAT(3,r3,r4,r5)
-#endif /* CONFIG_POWER4 */
+
 	blr
 
 /*
@@ -1269,9 +1137,6 @@
 	li	r4,0
 	isync
 3:
-#ifdef CONFIG_PPC64BRIDGE
-	slbie	r4
-#endif /* CONFIG_PPC64BRIDGE */
 	mtsrin	r3,r4
 	addi	r3,r3,0x111	/* next VSID */
 	rlwinm	r3,r3,0,8,3	/* clear out any overflow from VSID field */
@@ -1358,7 +1223,6 @@
 	sync
 	RFI
 
-#ifndef CONFIG_POWER4
 /*
  * Use the first pair of BAT registers to map the 1st 16MB
  * of RAM to KERNELBASE.  From this point on we can't safely
@@ -1366,7 +1230,6 @@
  */
 initial_bats:
 	lis	r11,KERNELBASE@h
-#ifndef CONFIG_PPC64BRIDGE
 	mfspr	r9,SPRN_PVR
 	rlwinm	r9,r9,16,16,31		/* r9 = 1 for 601, 4 for 604 */
 	cmpwi	0,r9,1
@@ -1381,7 +1244,6 @@
 	mtspr	SPRN_IBAT1L,r10
 	isync
 	blr
-#endif /* CONFIG_PPC64BRIDGE */
 
 4:	tophys(r8,r11)
 #ifdef CONFIG_SMP
@@ -1395,11 +1257,6 @@
 	ori	r11,r11,BL_256M<<2|0x2	/* set up BAT registers for 604 */
 #endif /* CONFIG_APUS */
 
-#ifdef CONFIG_PPC64BRIDGE
-	/* clear out the high 32 bits in the BAT */
-	clrldi	r11,r11,32
-	clrldi	r8,r8,32
-#endif /* CONFIG_PPC64BRIDGE */
 	mtspr	SPRN_DBAT0L,r8		/* N.B. 6xx (not 601) have valid */
 	mtspr	SPRN_DBAT0U,r11		/* bit in upper BAT register */
 	mtspr	SPRN_IBAT0L,r8
@@ -1432,38 +1289,6 @@
 
 #endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
 
-#else /* CONFIG_POWER4 */
-/*
- * Load up the SDR1 and segment register values now
- * since we don't have the BATs.
- * Also make sure we are running in 32-bit mode.
- */
-
-initial_mm_power4:
-	addis	r14,r3,_SDR1@ha		/* get the value from _SDR1 */
-	lwz	r14,_SDR1@l(r14)	/* assume hash table below 4GB */
-	mtspr	SPRN_SDR1,r14
-	slbia
-	lis	r4,0x2000		/* set pseudo-segment reg 12 */
-	ori	r5,r4,0x0ccc
-	mtsr	12,r5
-#if 0
-	ori	r5,r4,0x0888		/* set pseudo-segment reg 8 */
-	mtsr	8,r5			/* (for access to serial port) */
-#endif
-#ifdef CONFIG_BOOTX_TEXT
-	ori	r5,r4,0x0999		/* set pseudo-segment reg 9 */
-	mtsr	9,r5			/* (for access to screen) */
-#endif
-	mfmsr	r0
-	clrldi	r0,r0,1
-	sync
-	mtmsr	r0
-	isync
-	blr
-
-#endif /* CONFIG_POWER4 */
-
 #ifdef CONFIG_8260
 /* Jump into the system reset for the rom.
  * We first disable the MMU, and then jump to the ROM reset address.
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
deleted file mode 100644
index 1be3ca5..0000000
--- a/arch/ppc/kernel/idle.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Idle daemon for PowerPC.  Idle daemon will handle any action
- * that needs to be taken when the system becomes idle.
- *
- * Written by Cort Dougan (cort@cs.nmt.edu).  Subsequently hacked
- * on by Tom Rini, Armin Kuster, Paul Mackerras and others.
- *
- * 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.
- */
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/sysctl.h>
-#include <linux/cpu.h>
-
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/mmu.h>
-#include <asm/cache.h>
-#include <asm/cputable.h>
-#include <asm/machdep.h>
-#include <asm/smp.h>
-
-void default_idle(void)
-{
-	void (*powersave)(void);
-
-	powersave = ppc_md.power_save;
-
-	if (!need_resched()) {
-		if (powersave != NULL)
-			powersave();
-#ifdef CONFIG_SMP
-		else {
-			set_thread_flag(TIF_POLLING_NRFLAG);
-			while (!need_resched() &&
-					!cpu_is_offline(smp_processor_id()))
-				barrier();
-			clear_thread_flag(TIF_POLLING_NRFLAG);
-		}
-#endif
-	}
-}
-
-/*
- * The body of the idle task.
- */
-void cpu_idle(void)
-{
-	int cpu = smp_processor_id();
-
-	for (;;) {
-		while (!need_resched()) {
-			if (ppc_md.idle != NULL)
-				ppc_md.idle();
-			else
-				default_idle();
-		}
-
-		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
-			cpu_die();
-		preempt_enable_no_resched();
-		schedule();
-		preempt_disable();
-	}
-}
-
-#if defined(CONFIG_SYSCTL) && defined(CONFIG_6xx)
-/*
- * Register the sysctl to set/clear powersave_nap.
- */
-extern int powersave_nap;
-
-static ctl_table powersave_nap_ctl_table[]={
-	{
-		.ctl_name	= KERN_PPC_POWERSAVE_NAP,
-		.procname	= "powersave-nap",
-		.data		= &powersave_nap,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{ 0, },
-};
-static ctl_table powersave_nap_sysctl_root[] = {
-	{ 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, },
- 	{ 0,},
-};
-
-static int __init
-register_powersave_nap_sysctl(void)
-{
-	register_sysctl_table(powersave_nap_sysctl_root, 0);
-
-	return 0;
-}
-
-__initcall(register_powersave_nap_sysctl);
-#endif
diff --git a/arch/ppc/kernel/idle_6xx.S b/arch/ppc/kernel/idle_6xx.S
deleted file mode 100644
index 1a2194c..0000000
--- a/arch/ppc/kernel/idle_6xx.S
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- *  This file contains the power_save function for 6xx & 7xxx CPUs
- *  rewritten in assembler
- *
- *  Warning ! This code assumes that if your machine has a 750fx
- *  it will have PLL 1 set to low speed mode (used during NAP/DOZE).
- *  if this is not the case some additional changes will have to
- *  be done to check a runtime var (a bit like powersave-nap)
- *
- *  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.
- */
-
-#include <linux/config.h>
-#include <linux/threads.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/cputable.h>
-#include <asm/thread_info.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-
-#undef DEBUG
-
-	.text
-
-/*
- * Init idle, called at early CPU setup time from head.S for each CPU
- * Make sure no rest of NAP mode remains in HID0, save default
- * values for some CPU specific registers. Called with r24
- * containing CPU number and r3 reloc offset
- */
-_GLOBAL(init_idle_6xx)
-BEGIN_FTR_SECTION
-	mfspr	r4,SPRN_HID0
-	rlwinm	r4,r4,0,10,8	/* Clear NAP */
-	mtspr	SPRN_HID0, r4
-	b	1f
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
-	blr
-1:
-	slwi	r5,r24,2
-	add	r5,r5,r3
-BEGIN_FTR_SECTION
-	mfspr	r4,SPRN_MSSCR0
-	addis	r6,r5, nap_save_msscr0@ha
-	stw	r4,nap_save_msscr0@l(r6)
-END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
-BEGIN_FTR_SECTION
-	mfspr	r4,SPRN_HID1
-	addis	r6,r5,nap_save_hid1@ha
-	stw	r4,nap_save_hid1@l(r6)
-END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
-	blr
-
-/*
- * Here is the power_save_6xx function. This could eventually be
- * split into several functions & changing the function pointer
- * depending on the various features.
- */
-_GLOBAL(ppc6xx_idle)
-	/* Check if we can nap or doze, put HID0 mask in r3
-	 */
-	lis	r3, 0
-BEGIN_FTR_SECTION
-	lis	r3,HID0_DOZE@h
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
-BEGIN_FTR_SECTION
-	/* We must dynamically check for the NAP feature as it
-	 * can be cleared by CPU init after the fixups are done
-	 */
-	lis	r4,cur_cpu_spec@ha
-	lwz	r4,cur_cpu_spec@l(r4)
-	lwz	r4,CPU_SPEC_FEATURES(r4)
-	andi.	r0,r4,CPU_FTR_CAN_NAP
-	beq	1f
-	/* Now check if user or arch enabled NAP mode */
-	lis	r4,powersave_nap@ha
-	lwz	r4,powersave_nap@l(r4)
-	cmpwi	0,r4,0
-	beq	1f
-	lis	r3,HID0_NAP@h
-1:	
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
-	cmpwi	0,r3,0
-	beqlr
-
-	/* Clear MSR:EE */
-	mfmsr	r7
-	rlwinm	r0,r7,0,17,15
-	mtmsr	r0
-
-	/* Check current_thread_info()->flags */
-	rlwinm	r4,r1,0,0,18
-	lwz	r4,TI_FLAGS(r4)
-	andi.	r0,r4,_TIF_NEED_RESCHED
-	beq	1f
-	mtmsr	r7	/* out of line this ? */
-	blr
-1:	
-	/* Some pre-nap cleanups needed on some CPUs */
-	andis.	r0,r3,HID0_NAP@h
-	beq	2f
-BEGIN_FTR_SECTION
-	/* Disable L2 prefetch on some 745x and try to ensure
-	 * L2 prefetch engines are idle. As explained by errata
-	 * text, we can't be sure they are, we just hope very hard
-	 * that well be enough (sic !). At least I noticed Apple
-	 * doesn't even bother doing the dcbf's here...
-	 */
-	mfspr	r4,SPRN_MSSCR0
-	rlwinm	r4,r4,0,0,29
-	sync
-	mtspr	SPRN_MSSCR0,r4
-	sync
-	isync
-	lis	r4,KERNELBASE@h
-	dcbf	0,r4
-	dcbf	0,r4
-	dcbf	0,r4
-	dcbf	0,r4
-END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
-#ifdef DEBUG
-	lis	r6,nap_enter_count@ha
-	lwz	r4,nap_enter_count@l(r6)
-	addi	r4,r4,1
-	stw	r4,nap_enter_count@l(r6)
-#endif	
-2:
-BEGIN_FTR_SECTION
-	/* Go to low speed mode on some 750FX */
-	lis	r4,powersave_lowspeed@ha
-	lwz	r4,powersave_lowspeed@l(r4)
-	cmpwi	0,r4,0
-	beq	1f
-	mfspr	r4,SPRN_HID1
-	oris	r4,r4,0x0001
-	mtspr	SPRN_HID1,r4
-1:	
-END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
-
-	/* Go to NAP or DOZE now */	
-	mfspr	r4,SPRN_HID0
-	lis	r5,(HID0_NAP|HID0_SLEEP)@h
-BEGIN_FTR_SECTION
-	oris	r5,r5,HID0_DOZE@h
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
-	andc	r4,r4,r5
-	or	r4,r4,r3
-BEGIN_FTR_SECTION
-	oris	r4,r4,HID0_DPM@h	/* that should be done once for all  */
-END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
-	mtspr	SPRN_HID0,r4
-BEGIN_FTR_SECTION
-	DSSALL
-	sync
-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
-	ori	r7,r7,MSR_EE /* Could be ommited (already set) */
-	oris	r7,r7,MSR_POW@h
-	sync
-	isync
-	mtmsr	r7
-	isync
-	sync
-	blr
-	
-/*
- * Return from NAP/DOZE mode, restore some CPU specific registers,
- * we are called with DR/IR still off and r2 containing physical
- * address of current.
- */
-_GLOBAL(power_save_6xx_restore)
-	mfspr	r11,SPRN_HID0
-	rlwinm.	r11,r11,0,10,8	/* Clear NAP & copy NAP bit !state to cr1 EQ */
-	cror	4*cr1+eq,4*cr0+eq,4*cr0+eq
-BEGIN_FTR_SECTION
-	rlwinm	r11,r11,0,9,7	/* Clear DOZE */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
-	mtspr	SPRN_HID0, r11
-
-#ifdef DEBUG
-	beq	cr1,1f
-	lis	r11,(nap_return_count-KERNELBASE)@ha
-	lwz	r9,nap_return_count@l(r11)
-	addi	r9,r9,1
-	stw	r9,nap_return_count@l(r11)
-1:
-#endif
-	
-	rlwinm	r9,r1,0,0,18
-	tophys(r9,r9)
-	lwz	r11,TI_CPU(r9)
-	slwi	r11,r11,2
-	/* Todo make sure all these are in the same page
-	 * and load r22 (@ha part + CPU offset) only once
-	 */
-BEGIN_FTR_SECTION
-	beq	cr1,1f
-	addis	r9,r11,(nap_save_msscr0-KERNELBASE)@ha
-	lwz	r9,nap_save_msscr0@l(r9)
-	mtspr	SPRN_MSSCR0, r9
-	sync
-	isync
-1:
-END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
-BEGIN_FTR_SECTION
-	addis	r9,r11,(nap_save_hid1-KERNELBASE)@ha
-	lwz	r9,nap_save_hid1@l(r9)
-	mtspr	SPRN_HID1, r9
-END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
-	b	transfer_to_handler_cont
-
-	.data
-
-_GLOBAL(nap_save_msscr0)
-	.space	4*NR_CPUS
-
-_GLOBAL(nap_save_hid1)
-	.space	4*NR_CPUS
-
-_GLOBAL(powersave_nap)
-	.long	0
-_GLOBAL(powersave_lowspeed)
-	.long	0
-
-#ifdef DEBUG
-_GLOBAL(nap_enter_count)
-	.space	4
-_GLOBAL(nap_return_count)
-	.space	4
-#endif
diff --git a/arch/ppc/kernel/idle_power4.S b/arch/ppc/kernel/idle_power4.S
deleted file mode 100644
index cc0d535..0000000
--- a/arch/ppc/kernel/idle_power4.S
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *  This file contains the power_save function for 6xx & 7xxx CPUs
- *  rewritten in assembler
- *
- *  Warning ! This code assumes that if your machine has a 750fx
- *  it will have PLL 1 set to low speed mode (used during NAP/DOZE).
- *  if this is not the case some additional changes will have to
- *  be done to check a runtime var (a bit like powersave-nap)
- *
- *  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.
- */
-
-#include <linux/config.h>
-#include <linux/threads.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/cputable.h>
-#include <asm/thread_info.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-
-#undef DEBUG
-
-	.text
-
-/*
- * Init idle, called at early CPU setup time from head.S for each CPU
- * So nothing for now. Called with r24 containing CPU number and r3
- * reloc offset
- */
- 	.globl	init_idle_power4
-init_idle_power4:
-	blr
-
-/*
- * Here is the power_save_6xx function. This could eventually be
- * split into several functions & changing the function pointer
- * depending on the various features.
- */
-	.globl	power4_idle
-power4_idle:
-BEGIN_FTR_SECTION
-	blr
-END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
-	/* We must dynamically check for the NAP feature as it
-	 * can be cleared by CPU init after the fixups are done
-	 */
-	lis	r4,cur_cpu_spec@ha
-	lwz	r4,cur_cpu_spec@l(r4)
-	lwz	r4,CPU_SPEC_FEATURES(r4)
-	andi.	r0,r4,CPU_FTR_CAN_NAP
-	beqlr
-	/* Now check if user or arch enabled NAP mode */
-	lis	r4,powersave_nap@ha
-	lwz	r4,powersave_nap@l(r4)
-	cmpwi	0,r4,0
-	beqlr
-
-	/* Clear MSR:EE */
-	mfmsr	r7
-	rlwinm	r0,r7,0,17,15
-	mtmsr	r0
-
-	/* Check current_thread_info()->flags */
-	rlwinm	r4,r1,0,0,18
-	lwz	r4,TI_FLAGS(r4)
-	andi.	r0,r4,_TIF_NEED_RESCHED
-	beq	1f
-	mtmsr	r7	/* out of line this ? */
-	blr
-1:	
-	/* Go to NAP now */	
-BEGIN_FTR_SECTION
-	DSSALL
-	sync
-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
-	ori	r7,r7,MSR_EE /* Could be ommited (already set) */
-	oris	r7,r7,MSR_POW@h
-	sync
-	isync
-	mtmsr	r7
-	isync
-	sync
-	blr
-	
-	.globl powersave_nap
-powersave_nap:
-	.long	0
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 04d04c5..809673a 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -46,9 +46,6 @@
 static void fixup_broken_pcnet32(struct pci_dev* dev);
 static int reparent_resources(struct resource *parent, struct resource *res);
 static void fixup_cpc710_pci64(struct pci_dev* dev);
-#ifdef CONFIG_PPC_OF
-static u8* pci_to_OF_bus_map;
-#endif
 
 /* By default, we don't re-assign bus numbers.
  */
@@ -625,406 +622,13 @@
 	return hose;
 }
 
-#ifdef CONFIG_PPC_OF
-/*
- * Functions below are used on OpenFirmware machines.
- */
-static void
-make_one_node_map(struct device_node* node, u8 pci_bus)
-{
-	int *bus_range;
-	int len;
-
-	if (pci_bus >= pci_bus_count)
-		return;
-	bus_range = (int *) get_property(node, "bus-range", &len);
-	if (bus_range == NULL || len < 2 * sizeof(int)) {
-		printk(KERN_WARNING "Can't get bus-range for %s, "
-		       "assuming it starts at 0\n", node->full_name);
-		pci_to_OF_bus_map[pci_bus] = 0;
-	} else
-		pci_to_OF_bus_map[pci_bus] = bus_range[0];
-
-	for (node=node->child; node != 0;node = node->sibling) {
-		struct pci_dev* dev;
-		unsigned int *class_code, *reg;
-	
-		class_code = (unsigned int *) get_property(node, "class-code", NULL);
-		if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
-			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
-			continue;
-		reg = (unsigned int *)get_property(node, "reg", NULL);
-		if (!reg)
-			continue;
-		dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff));
-		if (!dev || !dev->subordinate)
-			continue;
-		make_one_node_map(node, dev->subordinate->number);
-	}
-}
-	
-void
-pcibios_make_OF_bus_map(void)
-{
-	int i;
-	struct pci_controller* hose;
-	u8* of_prop_map;
-
-	pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL);
-	if (!pci_to_OF_bus_map) {
-		printk(KERN_ERR "Can't allocate OF bus map !\n");
-		return;
-	}
-
-	/* We fill the bus map with invalid values, that helps
-	 * debugging.
-	 */
-	for (i=0; i<pci_bus_count; i++)
-		pci_to_OF_bus_map[i] = 0xff;
-
-	/* For each hose, we begin searching bridges */
-	for(hose=hose_head; hose; hose=hose->next) {
-		struct device_node* node;	
-		node = (struct device_node *)hose->arch_data;
-		if (!node)
-			continue;
-		make_one_node_map(node, hose->first_busno);
-	}
-	of_prop_map = get_property(find_path_device("/"), "pci-OF-bus-map", NULL);
-	if (of_prop_map)
-		memcpy(of_prop_map, pci_to_OF_bus_map, pci_bus_count);
-#ifdef DEBUG
-	printk("PCI->OF bus map:\n");
-	for (i=0; i<pci_bus_count; i++) {
-		if (pci_to_OF_bus_map[i] == 0xff)
-			continue;
-		printk("%d -> %d\n", i, pci_to_OF_bus_map[i]);
-	}
-#endif
-}
-
-typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data);
-
-static struct device_node*
-scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* data)
-{
-	struct device_node* sub_node;
-
-	for (; node != 0;node = node->sibling) {
-		unsigned int *class_code;
-	
-		if (filter(node, data))
-			return node;
-
-		/* For PCI<->PCI bridges or CardBus bridges, we go down
-		 * Note: some OFs create a parent node "multifunc-device" as
-		 * a fake root for all functions of a multi-function device,
-		 * we go down them as well.
-		 */
-		class_code = (unsigned int *) get_property(node, "class-code", NULL);
-		if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
-			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
-			strcmp(node->name, "multifunc-device"))
-			continue;
-		sub_node = scan_OF_pci_childs(node->child, filter, data);
-		if (sub_node)
-			return sub_node;
-	}
-	return NULL;
-}
-
-static int
-scan_OF_pci_childs_iterator(struct device_node* node, void* data)
-{
-	unsigned int *reg;
-	u8* fdata = (u8*)data;
-	
-	reg = (unsigned int *) get_property(node, "reg", NULL);
-	if (reg && ((reg[0] >> 8) & 0xff) == fdata[1]
-		&& ((reg[0] >> 16) & 0xff) == fdata[0])
-		return 1;
-	return 0;
-}
-
-static struct device_node*
-scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
-{
-	u8 filter_data[2] = {bus, dev_fn};
-
-	return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data);
-}
-
-/*
- * Scans the OF tree for a device node matching a PCI device
- */
-struct device_node *
-pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
-{
-	struct pci_controller *hose;
-	struct device_node *node;
-	int busnr;
-
-	if (!have_of)
-		return NULL;
-	
-	/* Lookup the hose */
-	busnr = bus->number;
-	hose = pci_bus_to_hose(busnr);
-	if (!hose)
-		return NULL;
-
-	/* Check it has an OF node associated */
-	node = (struct device_node *) hose->arch_data;
-	if (!node)
-		return NULL;
-
-	/* Fixup bus number according to what OF think it is. */
-	if (pci_to_OF_bus_map)
-		busnr = pci_to_OF_bus_map[busnr];
-	if (busnr == 0xff)
-		return NULL;
-	
-	/* Now, lookup childs of the hose */
-	return scan_OF_childs_for_device(node->child, busnr, devfn);
-}
-EXPORT_SYMBOL(pci_busdev_to_OF_node);
-
-struct device_node*
-pci_device_to_OF_node(struct pci_dev *dev)
-{
-	return pci_busdev_to_OF_node(dev->bus, dev->devfn);
-}
-EXPORT_SYMBOL(pci_device_to_OF_node);
-
-/* This routine is meant to be used early during boot, when the
- * PCI bus numbers have not yet been assigned, and you need to
- * issue PCI config cycles to an OF device.
- * It could also be used to "fix" RTAS config cycles if you want
- * to set pci_assign_all_buses to 1 and still use RTAS for PCI
- * config cycles.
- */
-struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
-{
-	if (!have_of)
-		return NULL;
-	while(node) {
-		struct pci_controller* hose;
-		for (hose=hose_head;hose;hose=hose->next)
-			if (hose->arch_data == node)
-				return hose;
-		node=node->parent;
-	}
-	return NULL;
-}
-
-static int
-find_OF_pci_device_filter(struct device_node* node, void* data)
-{
-	return ((void *)node == data);
-}
-
-/*
- * Returns the PCI device matching a given OF node
- */
-int
-pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
-{
-	unsigned int *reg;
-	struct pci_controller* hose;
-	struct pci_dev* dev = NULL;
-	
-	if (!have_of)
-		return -ENODEV;
-	/* Make sure it's really a PCI device */
-	hose = pci_find_hose_for_OF_device(node);
-	if (!hose || !hose->arch_data)
-		return -ENODEV;
-	if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child,
-			find_OF_pci_device_filter, (void *)node))
-		return -ENODEV;
-	reg = (unsigned int *) get_property(node, "reg", NULL);
-	if (!reg)
-		return -ENODEV;
-	*bus = (reg[0] >> 16) & 0xff;
-	*devfn = ((reg[0] >> 8) & 0xff);
-
-	/* Ok, here we need some tweak. If we have already renumbered
-	 * all busses, we can't rely on the OF bus number any more.
-	 * the pci_to_OF_bus_map is not enough as several PCI busses
-	 * may match the same OF bus number.
-	 */
-	if (!pci_to_OF_bus_map)
-		return 0;
-
-	for_each_pci_dev(dev)
-		if (pci_to_OF_bus_map[dev->bus->number] == *bus &&
-				dev->devfn == *devfn) {
-			*bus = dev->bus->number;
-			pci_dev_put(dev);
-			return 0;
-		}
-
-	return -ENODEV;
-}
-EXPORT_SYMBOL(pci_device_from_OF_node);
-
-void __init
-pci_process_bridge_OF_ranges(struct pci_controller *hose,
-			   struct device_node *dev, int primary)
-{
-	static unsigned int static_lc_ranges[256] __initdata;
-	unsigned int *dt_ranges, *lc_ranges, *ranges, *prev;
-	unsigned int size;
-	int rlen = 0, orig_rlen;
-	int memno = 0;
-	struct resource *res;
-	int np, na = prom_n_addr_cells(dev);
-	np = na + 5;
-
-	/* First we try to merge ranges to fix a problem with some pmacs
-	 * that can have more than 3 ranges, fortunately using contiguous
-	 * addresses -- BenH
-	 */
-	dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
-	if (!dt_ranges)
-		return;
-	/* Sanity check, though hopefully that never happens */
-	if (rlen > sizeof(static_lc_ranges)) {
-		printk(KERN_WARNING "OF ranges property too large !\n");
-		rlen = sizeof(static_lc_ranges);
-	}
-	lc_ranges = static_lc_ranges;
-	memcpy(lc_ranges, dt_ranges, rlen);
-	orig_rlen = rlen;
-
-	/* Let's work on a copy of the "ranges" property instead of damaging
-	 * the device-tree image in memory
-	 */
-	ranges = lc_ranges;
-	prev = NULL;
-	while ((rlen -= np * sizeof(unsigned int)) >= 0) {
-		if (prev) {
-			if (prev[0] == ranges[0] && prev[1] == ranges[1] &&
-				(prev[2] + prev[na+4]) == ranges[2] &&
-				(prev[na+2] + prev[na+4]) == ranges[na+2]) {
-				prev[na+4] += ranges[na+4];
-				ranges[0] = 0;
-				ranges += np;
-				continue;
-			}
-		}
-		prev = ranges;
-		ranges += np;
-	}
-
-	/*
-	 * The ranges property is laid out as an array of elements,
-	 * each of which comprises:
-	 *   cells 0 - 2:	a PCI address
-	 *   cells 3 or 3+4:	a CPU physical address
-	 *			(size depending on dev->n_addr_cells)
-	 *   cells 4+5 or 5+6:	the size of the range
-	 */
-	ranges = lc_ranges;
-	rlen = orig_rlen;
-	while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) {
-		res = NULL;
-		size = ranges[na+4];
-		switch ((ranges[0] >> 24) & 0x3) {
-		case 1:		/* I/O space */
-			if (ranges[2] != 0)
-				break;
-			hose->io_base_phys = ranges[na+2];
-			/* limit I/O space to 16MB */
-			if (size > 0x01000000)
-				size = 0x01000000;
-			hose->io_base_virt = ioremap(ranges[na+2], size);
-			if (primary)
-				isa_io_base = (unsigned long) hose->io_base_virt;
-			res = &hose->io_resource;
-			res->flags = IORESOURCE_IO;
-			res->start = ranges[2];
-			DBG("PCI: IO 0x%lx -> 0x%lx\n",
-				    res->start, res->start + size - 1);
-			break;
-		case 2:		/* memory space */
-			memno = 0;
-			if (ranges[1] == 0 && ranges[2] == 0
-			    && ranges[na+4] <= (16 << 20)) {
-				/* 1st 16MB, i.e. ISA memory area */
-				if (primary)
-					isa_mem_base = ranges[na+2];
-				memno = 1;
-			}
-			while (memno < 3 && hose->mem_resources[memno].flags)
-				++memno;
-			if (memno == 0)
-				hose->pci_mem_offset = ranges[na+2] - ranges[2];
-			if (memno < 3) {
-				res = &hose->mem_resources[memno];
-				res->flags = IORESOURCE_MEM;
-				if(ranges[0] & 0x40000000)
-					res->flags |= IORESOURCE_PREFETCH;
-				res->start = ranges[na+2];
-				DBG("PCI: MEM[%d] 0x%lx -> 0x%lx\n", memno,
-					    res->start, res->start + size - 1);
-			}
-			break;
-		}
-		if (res != NULL) {
-			res->name = dev->full_name;
-			res->end = res->start + size - 1;
-			res->parent = NULL;
-			res->sibling = NULL;
-			res->child = NULL;
-		}
-		ranges += np;
-	}
-}
-
-/* We create the "pci-OF-bus-map" property now so it appears in the
- * /proc device tree
- */
-void __init
-pci_create_OF_bus_map(void)
-{
-	struct property* of_prop;
-	
-	of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256);
-	if (of_prop && find_path_device("/")) {
-		memset(of_prop, -1, sizeof(struct property) + 256);
-		of_prop->name = "pci-OF-bus-map";
-		of_prop->length = 256;
-		of_prop->value = (unsigned char *)&of_prop[1];
-		prom_add_property(find_path_device("/"), of_prop);
-	}
-}
-
-static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct pci_dev *pdev;
-	struct device_node *np;
-
-	pdev = to_pci_dev (dev);
-	np = pci_device_to_OF_node(pdev);
-	if (np == NULL || np->full_name == NULL)
-		return 0;
-	return sprintf(buf, "%s", np->full_name);
-}
-static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-
-#else /* CONFIG_PPC_OF */
 void pcibios_make_OF_bus_map(void)
 {
 }
-#endif /* CONFIG_PPC_OF */
 
 /* Add sysfs properties */
 void pcibios_add_platform_entries(struct pci_dev *pdev)
 {
-#ifdef CONFIG_PPC_OF
-	device_create_file(&pdev->dev, &dev_attr_devspec);
-#endif /* CONFIG_PPC_OF */
 }
 
 
diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
index 9b84bff..75c6450 100644
--- a/arch/ppc/kernel/ppc_htab.c
+++ b/arch/ppc/kernel/ppc_htab.c
@@ -104,7 +104,7 @@
 static int ppc_htab_show(struct seq_file *m, void *v)
 {
 	unsigned long mmcr0 = 0, pmc1 = 0, pmc2 = 0;
-#if defined(CONFIG_PPC_STD_MMU) && !defined(CONFIG_PPC64BRIDGE)
+#if defined(CONFIG_PPC_STD_MMU)
 	unsigned int kptes = 0, uptes = 0;
 	PTE *ptr;
 #endif /* CONFIG_PPC_STD_MMU */
@@ -133,7 +133,6 @@
 		return 0;
 	}
 
-#ifndef CONFIG_PPC64BRIDGE
 	for (ptr = Hash; ptr < Hash_end; ptr++) {
 		unsigned int mctx, vsid;
 
@@ -147,7 +146,6 @@
 		else
 			uptes++;
 	}
-#endif
 
 	seq_printf(m,
 		      "PTE Hash Table Information\n"
@@ -155,20 +153,16 @@
 		      "Buckets\t\t: %lu\n"
  		      "Address\t\t: %08lx\n"
 		      "Entries\t\t: %lu\n"
-#ifndef CONFIG_PPC64BRIDGE
 		      "User ptes\t: %u\n"
 		      "Kernel ptes\t: %u\n"
 		      "Percent full\t: %lu%%\n"
-#endif
                       , (unsigned long)(Hash_size>>10),
 		      (Hash_size/(sizeof(PTE)*8)),
 		      (unsigned long)Hash,
 		      Hash_size/sizeof(PTE)
-#ifndef CONFIG_PPC64BRIDGE
                       , uptes,
 		      kptes,
 		      ((kptes+uptes)*100) / (Hash_size/sizeof(PTE))
-#endif
 		);
 
 	seq_printf(m,
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 82adb46..865ba74 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -18,7 +18,6 @@
 #include <linux/bitops.h>
 
 #include <asm/page.h>
-#include <asm/semaphore.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -30,7 +29,6 @@
 #include <linux/adb.h>
 #include <linux/cuda.h>
 #include <linux/pmu.h>
-#include <asm/prom.h>
 #include <asm/system.h>
 #include <asm/pci-bridge.h>
 #include <asm/irq.h>
@@ -208,27 +206,6 @@
 EXPORT_SYMBOL(cuda_request);
 EXPORT_SYMBOL(cuda_poll);
 #endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_PPC_OF
-EXPORT_SYMBOL(find_devices);
-EXPORT_SYMBOL(find_type_devices);
-EXPORT_SYMBOL(find_compatible_devices);
-EXPORT_SYMBOL(find_path_device);
-EXPORT_SYMBOL(device_is_compatible);
-EXPORT_SYMBOL(machine_is_compatible);
-EXPORT_SYMBOL(find_all_nodes);
-EXPORT_SYMBOL(get_property);
-EXPORT_SYMBOL(request_OF_resource);
-EXPORT_SYMBOL(release_OF_resource);
-EXPORT_SYMBOL(of_find_node_by_name);
-EXPORT_SYMBOL(of_find_node_by_type);
-EXPORT_SYMBOL(of_find_compatible_node);
-EXPORT_SYMBOL(of_find_node_by_path);
-EXPORT_SYMBOL(of_find_all_nodes);
-EXPORT_SYMBOL(of_get_parent);
-EXPORT_SYMBOL(of_get_next_child);
-EXPORT_SYMBOL(of_node_get);
-EXPORT_SYMBOL(of_node_put);
-#endif /* CONFIG_PPC_OF */
 #if defined(CONFIG_BOOTX_TEXT)
 EXPORT_SYMBOL(btext_update_display);
 #endif
@@ -262,9 +239,6 @@
 EXPORT_SYMBOL(xmon);
 EXPORT_SYMBOL(xmon_printf);
 #endif
-EXPORT_SYMBOL(__up);
-EXPORT_SYMBOL(__down);
-EXPORT_SYMBOL(__down_interruptible);
 
 #if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
 extern void (*debugger)(struct pt_regs *regs);
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 53e9dea..1f79e84 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -1,5 +1,5 @@
 /*
- * Common prep/chrp boot and setup code.
+ * Common prep boot and setup code.
  */
 
 #include <linux/config.h>
@@ -72,17 +72,12 @@
 unsigned int DMA_MODE_READ;
 unsigned int DMA_MODE_WRITE;
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
-int _machine = 0;
-EXPORT_SYMBOL(_machine);
-
+#ifdef CONFIG_PPC_PREP
 extern void prep_init(unsigned long r3, unsigned long r4,
 		unsigned long r5, unsigned long r6, unsigned long r7);
-extern void chrp_init(unsigned long r3, unsigned long r4,
-		unsigned long r5, unsigned long r6, unsigned long r7);
 
 dev_t boot_dev;
-#endif /* CONFIG_PPC_MULTIPLATFORM */
+#endif /* CONFIG_PPC_PREP */
 
 int have_of;
 EXPORT_SYMBOL(have_of);
@@ -319,72 +314,12 @@
 	identify_cpu(offset, 0);
 	do_cpu_ftr_fixups(offset);
 
-#if defined(CONFIG_PPC_OF)
-	reloc_got2(offset);
-
-	/*
-	 * don't do anything on prep
-	 * for now, don't use bootinfo because it breaks yaboot 0.5
-	 * and assume that if we didn't find a magic number, we have OF
-	 */
-	if (*(unsigned long *)(0) != 0xdeadc0de)
-		phys = prom_init(r3, r4, (prom_entry)r5);
-
-	reloc_got2(-offset);
-#endif
-
 	return phys;
 }
 
-#ifdef CONFIG_PPC_OF
+#ifdef CONFIG_PPC_PREP
 /*
- * Assume here that all clock rates are the same in a
- * smp system.  -- Cort
- */
-int
-of_show_percpuinfo(struct seq_file *m, int i)
-{
-	struct device_node *cpu_node;
-	u32 *fp;
-	int s;
-	
-	cpu_node = find_type_devices("cpu");
-	if (!cpu_node)
-		return 0;
-	for (s = 0; s < i && cpu_node->next; s++)
-		cpu_node = cpu_node->next;
-	fp = (u32 *)get_property(cpu_node, "clock-frequency", NULL);
-	if (fp)
-		seq_printf(m, "clock\t\t: %dMHz\n", *fp / 1000000);
-	return 0;
-}
-
-void __init
-intuit_machine_type(void)
-{
-	char *model;
-	struct device_node *root;
-	
-	/* ask the OF info if we're a chrp or pmac */
-	root = find_path_device("/");
-	if (root != 0) {
-		/* assume pmac unless proven to be chrp -- Cort */
-		_machine = _MACH_Pmac;
-		model = get_property(root, "device_type", NULL);
-		if (model && !strncmp("chrp", model, 4))
-			_machine = _MACH_chrp;
-		else {
-			model = get_property(root, "model", NULL);
-			if (model && !strncmp(model, "IBM", 3))
-				_machine = _MACH_chrp;
-		}
-	}
-}
-#endif
-
-#ifdef CONFIG_PPC_MULTIPLATFORM
-/*
- * The PPC_MULTIPLATFORM version of platform_init...
+ * The PPC_PREP version of platform_init...
  */
 void __init
 platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
@@ -399,161 +334,9 @@
 
 	parse_bootinfo(find_bootinfo());
 
-	/* if we didn't get any bootinfo telling us what we are... */
-	if (_machine == 0) {
-		/* prep boot loader tells us if we're prep or not */
-		if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
-			_machine = _MACH_prep;
-	}
-
-#ifdef CONFIG_PPC_PREP
-	/* not much more to do here, if prep */
-	if (_machine == _MACH_prep) {
-		prep_init(r3, r4, r5, r6, r7);
-		return;
-	}
-#endif
-
-#ifdef CONFIG_PPC_OF
-	have_of = 1;
-
-	/* prom_init has already been called from __start */
-	if (boot_infos)
-		relocate_nodes();
-
-	/* If we aren't PReP, we can find out if we're Pmac
-	 * or CHRP with this. */
-	if (_machine == 0)
-		intuit_machine_type();
-
-	/* finish_device_tree may need _machine defined. */
-	finish_device_tree();
-
-	/*
-	 * If we were booted via quik, r3 points to the physical
-	 * address of the command-line parameters.
-	 * If we were booted from an xcoff image (i.e. netbooted or
-	 * booted from floppy), we get the command line from the
-	 * bootargs property of the /chosen node.
-	 * If an initial ramdisk is present, r3 and r4
-	 * are used for initrd_start and initrd_size,
-	 * otherwise they contain 0xdeadbeef.
-	 */
-	if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) {
-		strlcpy(cmd_line, (char *)r3 + KERNELBASE,
-			sizeof(cmd_line));
-	} else if (boot_infos != 0) {
-		/* booted by BootX - check for ramdisk */
-		if (boot_infos->kernelParamsOffset != 0)
-			strlcpy(cmd_line, (char *) boot_infos
-				+ boot_infos->kernelParamsOffset,
-				sizeof(cmd_line));
-#ifdef CONFIG_BLK_DEV_INITRD
-		if (boot_infos->ramDisk) {
-			initrd_start = (unsigned long) boot_infos
-				+ boot_infos->ramDisk;
-			initrd_end = initrd_start + boot_infos->ramDiskSize;
-			initrd_below_start_ok = 1;
-		}
-#endif
-	} else {
-		struct device_node *chosen;
-		char *p;
-	
-#ifdef CONFIG_BLK_DEV_INITRD
-		if (r3 && r4 && r4 != 0xdeadbeef) {
-			if (r3 < KERNELBASE)
-				r3 += KERNELBASE;
-			initrd_start = r3;
-			initrd_end = r3 + r4;
-			ROOT_DEV = Root_RAM0;
-			initrd_below_start_ok = 1;
-		}
-#endif
-		chosen = find_devices("chosen");
-		if (chosen != NULL) {
-			p = get_property(chosen, "bootargs", NULL);
-			if (p && *p) {
-				strlcpy(cmd_line, p, sizeof(cmd_line));
-			}
-		}
-	}
-#ifdef CONFIG_ADB
-	if (strstr(cmd_line, "adb_sync")) {
-		extern int __adb_probe_sync;
-		__adb_probe_sync = 1;
-	}
-#endif /* CONFIG_ADB */
-
-	switch (_machine) {
-#ifdef CONFIG_PPC_CHRP
-	case _MACH_chrp:
-		chrp_init(r3, r4, r5, r6, r7);
-		break;
-#endif
-	}
-#endif /* CONFIG_PPC_OF */
+	prep_init(r3, r4, r5, r6, r7);
 }
-#endif /* CONFIG_PPC_MULTIPLATFORM */
-
-#ifdef CONFIG_PPC_OF
-#ifdef CONFIG_SERIAL_CORE_CONSOLE
-extern char *of_stdout_device;
-
-static int __init set_preferred_console(void)
-{
-	struct device_node *prom_stdout;
-	char *name;
-	int offset = 0;
-
-	if (of_stdout_device == NULL)
-		return -ENODEV;
-
-	/* The user has requested a console so this is already set up. */
-	if (strstr(saved_command_line, "console="))
-		return -EBUSY;
-
-	prom_stdout = find_path_device(of_stdout_device);
-	if (!prom_stdout)
-		return -ENODEV;
-
-	name = (char *)get_property(prom_stdout, "name", NULL);
-	if (!name)
-		return -ENODEV;
-
-	if (strcmp(name, "serial") == 0) {
-		int i;
-		u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
-		if (i > 8) {
-			switch (reg[1]) {
-				case 0x3f8:
-					offset = 0;
-					break;
-				case 0x2f8:
-					offset = 1;
-					break;
-				case 0x898:
-					offset = 2;
-					break;
-				case 0x890:
-					offset = 3;
-					break;
-				default:
-					/* We dont recognise the serial port */
-					return -ENODEV;
-			}
-		}
-	} else if (strcmp(name, "ch-a") == 0)
-		offset = 0;
-	else if (strcmp(name, "ch-b") == 0)
-		offset = 1;
-	else
-		return -ENODEV;
-	return add_preferred_console("ttyS", offset, NULL);
-}
-console_initcall(set_preferred_console);
-#endif /* CONFIG_SERIAL_CORE_CONSOLE */
-#endif /* CONFIG_PPC_OF */
+#endif /* CONFIG_PPC_PREP */
 
 struct bi_record *find_bootinfo(void)
 {
@@ -589,23 +372,6 @@
 			initrd_end = data[0] + data[1] + KERNELBASE;
 			break;
 #endif /* CONFIG_BLK_DEV_INITRD */
-#ifdef CONFIG_PPC_MULTIPLATFORM
-		case BI_MACHTYPE:
-			/* Machine types changed with the merge. Since the
-			 * bootinfo are now deprecated, we can just hard code
-			 * the appropriate conversion here for when we are
-			 * called with yaboot which passes us a machine type
-			 * this way.
-			 */
-			switch(data[0]) {
-			case 1: _machine = _MACH_prep; break;
-			case 2: _machine = _MACH_Pmac; break;
-			case 4: _machine = _MACH_chrp; break;
-			default:
-				_machine = data[0];
-			}
-			break;
-#endif
 		case BI_MEMSIZE:
 			boot_mem_size = data[0];
 			break;
@@ -631,9 +397,6 @@
 #ifdef CONFIG_6xx
 	ppc_md.power_save = ppc6xx_idle;
 #endif
-#ifdef CONFIG_POWER4
-	ppc_md.power_save = power4_idle;
-#endif
 
 	platform_init(r3, r4, r5, r6, r7);
 
@@ -711,7 +474,7 @@
 	if ( ppc_md.progress ) ppc_md.progress("             ", 0xffff);
 
 	/* register CPU devices */
-	for_each_cpu(i)
+	for_each_possible_cpu(i)
 		register_cpu(&cpu_devices[i], i, NULL);
 
 	/* call platform init */
@@ -799,7 +562,4 @@
 	if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
 
 	paging_init();
-
-	/* this is for modules since _machine can be a define -- Cort */
-	ppc_md.ppc_machine = _machine;
 }
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index e55cdda..f77795a 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -311,7 +311,7 @@
 	/* Backup CPU 0 state */
 	__save_cpu_setup();
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		if (cpu == smp_processor_id())
 			continue;
 		/* create a process for the processor */
diff --git a/arch/ppc/lib/strcase.c b/arch/ppc/lib/strcase.c
index 36b5210..3b0094c 100644
--- a/arch/ppc/lib/strcase.c
+++ b/arch/ppc/lib/strcase.c
@@ -1,4 +1,5 @@
 #include <linux/ctype.h>
+#include <linux/types.h>
 
 int strcasecmp(const char *s1, const char *s2)
 {
@@ -11,7 +12,7 @@
 	return c1 - c2;
 }
 
-int strncasecmp(const char *s1, const char *s2, int n)
+int strncasecmp(const char *s1, const char *s2, size_t n)
 {
 	int c1, c2;
 
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index 0217188..8e08ca3 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -202,6 +202,7 @@
 	/* an exec  - 4xx/Book-E allows for per-page execute permission */
 	} else if (TRAP(regs) == 0x400) {
 		pte_t *ptep;
+		pmd_t *pmdp;
 
 #if 0
 		/* It would be nice to actually enforce the VM execute
@@ -215,21 +216,24 @@
 		/* Since 4xx/Book-E supports per-page execute permission,
 		 * we lazily flush dcache to icache. */
 		ptep = NULL;
-		if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) {
-			struct page *page = pte_page(*ptep);
+		if (get_pteptr(mm, address, &ptep, &pmdp)) {
+			spinlock_t *ptl = pte_lockptr(mm, pmdp);
+			spin_lock(ptl);
+			if (pte_present(*ptep)) {
+				struct page *page = pte_page(*ptep);
 
-			if (! test_bit(PG_arch_1, &page->flags)) {
-				flush_dcache_icache_page(page);
-				set_bit(PG_arch_1, &page->flags);
+				if (!test_bit(PG_arch_1, &page->flags)) {
+					flush_dcache_icache_page(page);
+					set_bit(PG_arch_1, &page->flags);
+				}
+				pte_update(ptep, 0, _PAGE_HWEXEC);
+				_tlbie(address);
+				pte_unmap_unlock(ptep, ptl);
+				up_read(&mm->mmap_sem);
+				return 0;
 			}
-			pte_update(ptep, 0, _PAGE_HWEXEC);
-			_tlbie(address);
-			pte_unmap(ptep);
-			up_read(&mm->mmap_sem);
-			return 0;
+			pte_unmap_unlock(ptep, ptl);
 		}
-		if (ptep != NULL)
-			pte_unmap(ptep);
 #endif
 	/* a read */
 	} else {
diff --git a/arch/ppc/mm/hashtable.S b/arch/ppc/mm/hashtable.S
index f09fa88..31d0a92 100644
--- a/arch/ppc/mm/hashtable.S
+++ b/arch/ppc/mm/hashtable.S
@@ -74,12 +74,6 @@
  */
 	.text
 _GLOBAL(hash_page)
-#ifdef CONFIG_PPC64BRIDGE
-	mfmsr	r0
-	clrldi	r0,r0,1		/* make sure it's in 32-bit mode */
-	MTMSRD(r0)
-	isync
-#endif
 	tophys(r7,0)			/* gets -KERNELBASE into r7 */
 #ifdef CONFIG_SMP
 	addis	r8,r7,mmu_hash_lock@h
@@ -303,7 +297,6 @@
 Hash_bits = 12				/* e.g. 256kB hash table */
 Hash_msk = (((1 << Hash_bits) - 1) * 64)
 
-#ifndef CONFIG_PPC64BRIDGE
 /* defines for the PTE format for 32-bit PPCs */
 #define PTE_SIZE	8
 #define PTEG_SIZE	64
@@ -317,21 +310,6 @@
 #define SET_V(r)	oris r,r,PTE_V@h
 #define CLR_V(r,t)	rlwinm r,r,0,1,31
 
-#else
-/* defines for the PTE format for 64-bit PPCs */
-#define PTE_SIZE	16
-#define PTEG_SIZE	128
-#define LG_PTEG_SIZE	7
-#define LDPTEu		ldu
-#define STPTE		std
-#define CMPPTE		cmpd
-#define PTE_H		2
-#define PTE_V		1
-#define TST_V(r)	andi. r,r,PTE_V
-#define SET_V(r)	ori r,r,PTE_V
-#define CLR_V(r,t)	li t,PTE_V; andc r,r,t
-#endif /* CONFIG_PPC64BRIDGE */
-
 #define HASH_LEFT	31-(LG_PTEG_SIZE+Hash_bits-1)
 #define HASH_RIGHT	31-LG_PTEG_SIZE
 
@@ -349,14 +327,8 @@
 END_FTR_SECTION_IFSET(CPU_FTR_NEED_COHERENT)
 
 	/* Construct the high word of the PPC-style PTE (r5) */
-#ifndef CONFIG_PPC64BRIDGE
 	rlwinm	r5,r3,7,1,24		/* put VSID in 0x7fffff80 bits */
 	rlwimi	r5,r4,10,26,31		/* put in API (abbrev page index) */
-#else /* CONFIG_PPC64BRIDGE */
-	clrlwi	r3,r3,8			/* reduce vsid to 24 bits */
-	sldi	r5,r3,12		/* shift vsid into position */
-	rlwimi	r5,r4,16,20,24		/* put in API (abbrev page index) */
-#endif /* CONFIG_PPC64BRIDGE */
 	SET_V(r5)			/* set V (valid) bit */
 
 	/* Get the address of the primary PTE group in the hash table (r3) */
@@ -540,14 +512,8 @@
 	add	r3,r3,r0		/* note code below trims to 24 bits */
 
 	/* Construct the high word of the PPC-style PTE (r11) */
-#ifndef CONFIG_PPC64BRIDGE
 	rlwinm	r11,r3,7,1,24		/* put VSID in 0x7fffff80 bits */
 	rlwimi	r11,r4,10,26,31		/* put in API (abbrev page index) */
-#else /* CONFIG_PPC64BRIDGE */
-	clrlwi	r3,r3,8			/* reduce vsid to 24 bits */
-	sldi	r11,r3,12		/* shift vsid into position */
-	rlwimi	r11,r4,16,20,24		/* put in API (abbrev page index) */
-#endif /* CONFIG_PPC64BRIDGE */
 	SET_V(r11)			/* set V (valid) bit */
 
 #ifdef CONFIG_SMP
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index cb1c294..386e000 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -412,14 +412,6 @@
 	}
 #endif /* CONFIG_BLK_DEV_INITRD */
 
-#ifdef CONFIG_PPC_OF
-	/* mark the RTAS pages as reserved */
-	if ( rtas_data )
-		for (addr = (ulong)__va(rtas_data);
-		     addr < PAGE_ALIGN((ulong)__va(rtas_data)+rtas_size) ;
-		     addr += PAGE_SIZE)
-			SetPageReserved(virt_to_page(addr));
-#endif
 	for (addr = PAGE_OFFSET; addr < (unsigned long)high_memory;
 	     addr += PAGE_SIZE) {
 		if (!PageReserved(virt_to_page(addr)))
@@ -494,11 +486,6 @@
 				  initrd_end - initrd_start, 1);
 	}
 #endif /* CONFIG_BLK_DEV_INITRD */
-#ifdef CONFIG_PPC_OF
-	/* remove the RTAS pages from the available memory */
-	if (rtas_data)
-		mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1);
-#endif
 }
 
 /* Mark some memory as reserved by removing it from phys_avail. */
diff --git a/arch/ppc/mm/mmu_context.c b/arch/ppc/mm/mmu_context.c
index a8816e0..b4a4b3f 100644
--- a/arch/ppc/mm/mmu_context.c
+++ b/arch/ppc/mm/mmu_context.c
@@ -2,7 +2,7 @@
  * This file contains the routines for handling the MMU on those
  * PowerPC implementations where the MMU substantially follows the
  * architecture specification.  This includes the 6xx, 7xx, 7xxx,
- * 8260, and POWER3 implementations but excludes the 8xx and 4xx.
+ * 8260, and 83xx implementations but excludes the 8xx and 4xx.
  *  -- paulus
  *
  *  Derived from arch/ppc/mm/init.c:
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index 6ea9185..706bca8 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -39,7 +39,7 @@
 unsigned long ioremap_bot;
 int io_bat_index;
 
-#if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
+#if defined(CONFIG_6xx)
 #define HAVE_BATS	1
 #endif
 
@@ -368,7 +368,7 @@
  * the PTE pointer is unmodified if PTE is not found.
  */
 int
-get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep)
+get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp)
 {
         pgd_t	*pgd;
         pmd_t	*pmd;
@@ -383,6 +383,8 @@
                         if (pte) {
 				retval = 1;
 				*ptep = pte;
+				if (pmdp)
+					*pmdp = pmd;
 				/* XXX caller needs to do pte_unmap, yuck */
                         }
                 }
@@ -420,7 +422,7 @@
 		mm = &init_mm;
 
 	pa = 0;
-	if (get_pteptr(mm, addr, &pte)) {
+	if (get_pteptr(mm, addr, &pte, NULL)) {
 		pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
 		pte_unmap(pte);
 	}
diff --git a/arch/ppc/mm/ppc_mmu.c b/arch/ppc/mm/ppc_mmu.c
index 9a381ed5..25bb6f3 100644
--- a/arch/ppc/mm/ppc_mmu.c
+++ b/arch/ppc/mm/ppc_mmu.c
@@ -2,7 +2,7 @@
  * This file contains the routines for handling the MMU on those
  * PowerPC implementations where the MMU substantially follows the
  * architecture specification.  This includes the 6xx, 7xx, 7xxx,
- * 8260, and POWER3 implementations but excludes the 8xx and 4xx.
+ * 8260, and 83xx implementations but excludes the 8xx and 4xx.
  *  -- paulus
  *
  *  Derived from arch/ppc/mm/init.c:
@@ -42,11 +42,7 @@
 
 union ubat {			/* BAT register values to be loaded */
 	BAT	bat;
-#ifdef CONFIG_PPC64BRIDGE
-	u64	word[2];
-#else
 	u32	word[2];
-#endif
 } BATS[4][2];			/* 4 pairs of IBAT, DBAT */
 
 struct batrange {		/* stores address ranges mapped by BATs */
@@ -83,9 +79,6 @@
 
 unsigned long __init mmu_mapin_ram(void)
 {
-#ifdef CONFIG_POWER4
-	return 0;
-#else
 	unsigned long tot, bl, done;
 	unsigned long max_size = (256<<20);
 	unsigned long align;
@@ -122,7 +115,6 @@
 	}
 
 	return done;
-#endif
 }
 
 /*
@@ -205,27 +197,10 @@
 
 	if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105);
 
-#ifdef CONFIG_PPC64BRIDGE
-#define LG_HPTEG_SIZE	7		/* 128 bytes per HPTEG */
-#define SDR1_LOW_BITS	(lg_n_hpteg - 11)
-#define MIN_N_HPTEG	2048		/* min 256kB hash table */
-#else
 #define LG_HPTEG_SIZE	6		/* 64 bytes per HPTEG */
 #define SDR1_LOW_BITS	((n_hpteg - 1) >> 10)
 #define MIN_N_HPTEG	1024		/* min 64kB hash table */
-#endif
 
-#ifdef CONFIG_POWER4
-	/* The hash table has already been allocated and initialized
-	   in prom.c */
-	n_hpteg = Hash_size >> LG_HPTEG_SIZE;
-	lg_n_hpteg = __ilog2(n_hpteg);
-
-	/* Remove the hash table from the available memory */
-	if (Hash)
-		reserve_phys_mem(__pa(Hash), Hash_size);
-
-#else /* CONFIG_POWER4 */
 	/*
 	 * Allow 1 HPTE (1/8 HPTEG) for each page of memory.
 	 * This is less than the recommended amount, but then
@@ -248,7 +223,6 @@
 	Hash = mem_pieces_find(Hash_size, Hash_size);
 	cacheable_memzero(Hash, Hash_size);
 	_SDR1 = __pa(Hash) | SDR1_LOW_BITS;
-#endif /* CONFIG_POWER4 */
 
 	Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
 
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
index e8b91a3..90c6222 100644
--- a/arch/ppc/platforms/Makefile
+++ b/arch/ppc/platforms/Makefile
@@ -2,18 +2,10 @@
 # Makefile for the linux kernel.
 #
 
-# Extra CFLAGS so we don't have to do relative includes
-CFLAGS_chrp_setup.o	+= -Iarch/$(ARCH)/mm
-
 obj-$(CONFIG_APUS)		+= apus_setup.o
 ifeq ($(CONFIG_APUS),y)
 obj-$(CONFIG_PCI)		+= apus_pci.o
 endif
-obj-$(CONFIG_PPC_CHRP)		+= chrp_setup.o chrp_time.o chrp_pci.o \
-					chrp_pegasos_eth.o
-ifeq ($(CONFIG_PPC_CHRP),y)
-obj-$(CONFIG_NVRAM)		+= chrp_nvram.o
-endif
 obj-$(CONFIG_PPC_PREP)		+= prep_pci.o prep_setup.o
 obj-$(CONFIG_PREP_RESIDUAL)	+= residual.o
 obj-$(CONFIG_PQ2ADS)		+= pq2ads.o
@@ -40,7 +32,3 @@
 obj-$(CONFIG_MPC86XADS)		+= mpc866ads_setup.o
 obj-$(CONFIG_MPC885ADS)		+= mpc885ads_setup.o
 obj-$(CONFIG_ADS8272)		+= mpc8272ads_setup.o
-
-ifeq ($(CONFIG_SMP),y)
-obj-$(CONFIG_PPC_CHRP)		+= chrp_smp.o
-endif
diff --git a/arch/ppc/platforms/chrp_nvram.c b/arch/ppc/platforms/chrp_nvram.c
deleted file mode 100644
index 465ba9b..0000000
--- a/arch/ppc/platforms/chrp_nvram.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- *  c 2001 PPC 64 Team, IBM Corp
- *
- *      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.
- *
- * /dev/nvram driver for PPC
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <asm/uaccess.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-
-static unsigned int nvram_size;
-static unsigned char nvram_buf[4];
-static DEFINE_SPINLOCK(nvram_lock);
-
-static unsigned char chrp_nvram_read(int addr)
-{
-	unsigned long done, flags;
-	unsigned char ret;
-
-	if (addr >= nvram_size) {
-		printk(KERN_DEBUG "%s: read addr %d > nvram_size %u\n",
-		       current->comm, addr, nvram_size);
-		return 0xff;
-	}
-	spin_lock_irqsave(&nvram_lock, flags);
-	if ((call_rtas("nvram-fetch", 3, 2, &done, addr, __pa(nvram_buf), 1) != 0) || 1 != done)
-		ret = 0xff;
-	else
-		ret = nvram_buf[0];
-	spin_unlock_irqrestore(&nvram_lock, flags);
-
-	return ret;
-}
-
-static void chrp_nvram_write(int addr, unsigned char val)
-{
-	unsigned long done, flags;
-
-	if (addr >= nvram_size) {
-		printk(KERN_DEBUG "%s: write addr %d > nvram_size %u\n",
-		       current->comm, addr, nvram_size);
-		return;
-	}
-	spin_lock_irqsave(&nvram_lock, flags);
-	nvram_buf[0] = val;
-	if ((call_rtas("nvram-store", 3, 2, &done, addr, __pa(nvram_buf), 1) != 0) || 1 != done)
-		printk(KERN_DEBUG "rtas IO error storing 0x%02x at %d", val, addr);
-	spin_unlock_irqrestore(&nvram_lock, flags);
-}
-
-void __init chrp_nvram_init(void)
-{
-	struct device_node *nvram;
-	unsigned int *nbytes_p, proplen;
-
-	nvram = of_find_node_by_type(NULL, "nvram");
-	if (nvram == NULL)
-		return;
-
-	nbytes_p = (unsigned int *)get_property(nvram, "#bytes", &proplen);
-	if (nbytes_p == NULL || proplen != sizeof(unsigned int))
-		return;
-
-	nvram_size = *nbytes_p;
-
-	printk(KERN_INFO "CHRP nvram contains %u bytes\n", nvram_size);
-	of_node_put(nvram);
-
-	ppc_md.nvram_read_val = chrp_nvram_read;
-	ppc_md.nvram_write_val = chrp_nvram_write;
-
-	return;
-}
diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c
deleted file mode 100644
index c7fe618..0000000
--- a/arch/ppc/platforms/chrp_pci.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * CHRP pci routines.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/hydra.h>
-#include <asm/prom.h>
-#include <asm/gg2.h>
-#include <asm/machdep.h>
-#include <asm/sections.h>
-#include <asm/pci-bridge.h>
-#include <asm/open_pic.h>
-
-/* LongTrail */
-void __iomem *gg2_pci_config_base;
-
-/*
- * The VLSI Golden Gate II has only 512K of PCI configuration space, so we
- * limit the bus number to 3 bits
- */
-
-int gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off,
-			   int len, u32 *val)
-{
-	volatile void __iomem *cfg_data;
-	struct pci_controller *hose = bus->sysdata;
-
-	if (bus->number > 7)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	/*
-	 * Note: the caller has already checked that off is
-	 * suitably aligned and that len is 1, 2 or 4.
-	 */
-	cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
-	switch (len) {
-	case 1:
-		*val =  in_8(cfg_data);
-		break;
-	case 2:
-		*val = in_le16(cfg_data);
-		break;
-	default:
-		*val = in_le32(cfg_data);
-		break;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off,
-			    int len, u32 val)
-{
-	volatile void __iomem *cfg_data;
-	struct pci_controller *hose = bus->sysdata;
-
-	if (bus->number > 7)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	/*
-	 * Note: the caller has already checked that off is
-	 * suitably aligned and that len is 1, 2 or 4.
-	 */
-	cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
-	switch (len) {
-	case 1:
-		out_8(cfg_data, val);
-		break;
-	case 2:
-		out_le16(cfg_data, val);
-		break;
-	default:
-		out_le32(cfg_data, val);
-		break;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops gg2_pci_ops =
-{
-	gg2_read_config,
-	gg2_write_config
-};
-
-/*
- * Access functions for PCI config space using RTAS calls.
- */
-int
-rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
-		 int len, u32 *val)
-{
-	struct pci_controller *hose = bus->sysdata;
-	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
-		| (((bus->number - hose->first_busno) & 0xff) << 16)
-		| (hose->index << 24);
-        unsigned long ret = ~0UL;
-	int rval;
-
-	rval = call_rtas("read-pci-config", 2, 2, &ret, addr, len);
-	*val = ret;
-	return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
-}
-
-int
-rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
-		  int len, u32 val)
-{
-	struct pci_controller *hose = bus->sysdata;
-	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
-		| (((bus->number - hose->first_busno) & 0xff) << 16)
-		| (hose->index << 24);
-	int rval;
-
-	rval = call_rtas("write-pci-config", 3, 1, NULL, addr, len, val);
-	return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops rtas_pci_ops =
-{
-	rtas_read_config,
-	rtas_write_config
-};
-
-volatile struct Hydra __iomem *Hydra = NULL;
-
-int __init
-hydra_init(void)
-{
-	struct device_node *np;
-
-	np = find_devices("mac-io");
-	if (np == NULL || np->n_addrs == 0)
-		return 0;
-	Hydra = ioremap(np->addrs[0].address, np->addrs[0].size);
-	printk("Hydra Mac I/O at %x\n", np->addrs[0].address);
-	printk("Hydra Feature_Control was %x",
-	       in_le32(&Hydra->Feature_Control));
-	out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN |
-					   HYDRA_FC_SCSI_CELL_EN |
-					   HYDRA_FC_SCCA_ENABLE |
-					   HYDRA_FC_SCCB_ENABLE |
-					   HYDRA_FC_ARB_BYPASS |
-					   HYDRA_FC_MPIC_ENABLE |
-					   HYDRA_FC_SLOW_SCC_PCLK |
-					   HYDRA_FC_MPIC_IS_MASTER));
-	printk(", now %x\n", in_le32(&Hydra->Feature_Control));
-	return 1;
-}
-
-void __init
-chrp_pcibios_fixup(void)
-{
-	struct pci_dev *dev = NULL;
-	struct device_node *np;
-
-	/* PCI interrupts are controlled by the OpenPIC */
-	for_each_pci_dev(dev) {
-		np = pci_device_to_OF_node(dev);
-		if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
-			dev->irq = np->intrs[0].line;
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-	}
-}
-
-#define PRG_CL_RESET_VALID 0x00010000
-
-static void __init
-setup_python(struct pci_controller *hose, struct device_node *dev)
-{
-	u32 __iomem *reg;
-	u32 val;
-	unsigned long addr = dev->addrs[0].address;
-
-	setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010);
-
-	/* Clear the magic go-slow bit */
-	reg = ioremap(dev->addrs[0].address + 0xf6000, 0x40);
-	val = in_be32(&reg[12]);
-	if (val & PRG_CL_RESET_VALID) {
-		out_be32(&reg[12], val & ~PRG_CL_RESET_VALID);
-		in_be32(&reg[12]);
-	}
-	iounmap(reg);
-}
-
-/* Marvell Discovery II based Pegasos 2 */
-static void __init setup_peg2(struct pci_controller *hose, struct device_node *dev)
-{
-	struct device_node *root = find_path_device("/");
-	struct device_node *rtas;
-
-	rtas = of_find_node_by_name (root, "rtas");
-	if (rtas) {
-		hose->ops = &rtas_pci_ops;
-	} else {
-		printk ("RTAS supporting Pegasos OF not found, please upgrade"
-			" your firmware\n");
-	}
-	pci_assign_all_buses = 1;
-}
-
-void __init
-chrp_find_bridges(void)
-{
-	struct device_node *dev;
-	int *bus_range;
-	int len, index = -1;
-	struct pci_controller *hose;
-	unsigned int *dma;
-	char *model, *machine;
-	int is_longtrail = 0, is_mot = 0, is_pegasos = 0;
-	struct device_node *root = find_path_device("/");
-
-	/*
-	 * The PCI host bridge nodes on some machines don't have
-	 * properties to adequately identify them, so we have to
-	 * look at what sort of machine this is as well.
-	 */
-	machine = get_property(root, "model", NULL);
-	if (machine != NULL) {
-		is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0;
-		is_mot = strncmp(machine, "MOT", 3) == 0;
-		if (strncmp(machine, "Pegasos2", 8) == 0)
-			is_pegasos = 2;
-		else if (strncmp(machine, "Pegasos", 7) == 0)
-			is_pegasos = 1;
-	}
-	for (dev = root->child; dev != NULL; dev = dev->sibling) {
-		if (dev->type == NULL || strcmp(dev->type, "pci") != 0)
-			continue;
-		++index;
-		/* The GG2 bridge on the LongTrail doesn't have an address */
-		if (dev->n_addrs < 1 && !is_longtrail) {
-			printk(KERN_WARNING "Can't use %s: no address\n",
-			       dev->full_name);
-			continue;
-		}
-		bus_range = (int *) get_property(dev, "bus-range", &len);
-		if (bus_range == NULL || len < 2 * sizeof(int)) {
-			printk(KERN_WARNING "Can't get bus-range for %s\n",
-				dev->full_name);
-			continue;
-		}
-		if (bus_range[1] == bus_range[0])
-			printk(KERN_INFO "PCI bus %d", bus_range[0]);
-		else
-			printk(KERN_INFO "PCI buses %d..%d",
-			       bus_range[0], bus_range[1]);
-		printk(" controlled by %s", dev->type);
-		if (dev->n_addrs > 0)
-			printk(" at %x", dev->addrs[0].address);
-		printk("\n");
-
-		hose = pcibios_alloc_controller();
-		if (!hose) {
-			printk("Can't allocate PCI controller structure for %s\n",
-				dev->full_name);
-			continue;
-		}
-		hose->arch_data = dev;
-		hose->first_busno = bus_range[0];
-		hose->last_busno = bus_range[1];
-
-		model = get_property(dev, "model", NULL);
-		if (model == NULL)
-			model = "<none>";
-		if (device_is_compatible(dev, "IBM,python")) {
-			setup_python(hose, dev);
-		} else if (is_mot
-			   || strncmp(model, "Motorola, Grackle", 17) == 0) {
-			setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
-		} else if (is_longtrail) {
-			void __iomem *p = ioremap(GG2_PCI_CONFIG_BASE, 0x80000);
-			hose->ops = &gg2_pci_ops;
-			hose->cfg_data = p;
-			gg2_pci_config_base = p;
-		} else if (is_pegasos == 1) {
-			setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc);
-		} else if (is_pegasos == 2) {
-			setup_peg2(hose, dev);
-		} else {
-			printk("No methods for %s (model %s), using RTAS\n",
-			       dev->full_name, model);
-			hose->ops = &rtas_pci_ops;
-		}
-
-		pci_process_bridge_OF_ranges(hose, dev, index == 0);
-
-		/* check the first bridge for a property that we can
-		   use to set pci_dram_offset */
-		dma = (unsigned int *)
-			get_property(dev, "ibm,dma-ranges", &len);
-		if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) {
-			pci_dram_offset = dma[2] - dma[3];
-			printk("pci_dram_offset = %lx\n", pci_dram_offset);
-		}
-	}
-
-	/* Do not fixup interrupts from OF tree on pegasos */
-	if (is_pegasos == 0)
-		ppc_md.pcibios_fixup = chrp_pcibios_fixup;
-}
diff --git a/arch/ppc/platforms/chrp_pegasos_eth.c b/arch/ppc/platforms/chrp_pegasos_eth.c
deleted file mode 100644
index 9305c8a..0000000
--- a/arch/ppc/platforms/chrp_pegasos_eth.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- *  Copyright (C) 2005 Sven Luther <sl@bplan-gmbh.de>
- *  Thanks to :
- *	Dale Farnsworth <dale@farnsworth.org>
- *	Mark A. Greer <mgreer@mvista.com>
- *	Nicolas DET <nd@bplan-gmbh.de>
- *	Benjamin Herrenschmidt <benh@kernel.crashing.org>
- *  And anyone else who helped me on this.
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/mv643xx.h>
-#include <linux/pci.h>
-
-#define PEGASOS2_MARVELL_REGBASE 		(0xf1000000)
-#define PEGASOS2_MARVELL_REGSIZE 		(0x00004000)
-#define PEGASOS2_SRAM_BASE 			(0xf2000000)
-#define PEGASOS2_SRAM_SIZE			(256*1024)
-
-#define PEGASOS2_SRAM_BASE_ETH0			(PEGASOS2_SRAM_BASE)
-#define PEGASOS2_SRAM_BASE_ETH1			(PEGASOS2_SRAM_BASE_ETH0 + (PEGASOS2_SRAM_SIZE / 2) )
-
-
-#define PEGASOS2_SRAM_RXRING_SIZE		(PEGASOS2_SRAM_SIZE/4)
-#define PEGASOS2_SRAM_TXRING_SIZE		(PEGASOS2_SRAM_SIZE/4)
-
-#undef BE_VERBOSE
-
-static struct resource mv643xx_eth_shared_resources[] = {
-	[0] = {
-		.name	= "ethernet shared base",
-		.start	= 0xf1000000 + MV643XX_ETH_SHARED_REGS,
-		.end	= 0xf1000000 + MV643XX_ETH_SHARED_REGS +
-					MV643XX_ETH_SHARED_REGS_SIZE - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device mv643xx_eth_shared_device = {
-	.name		= MV643XX_ETH_SHARED_NAME,
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(mv643xx_eth_shared_resources),
-	.resource	= mv643xx_eth_shared_resources,
-};
-
-static struct resource mv643xx_eth0_resources[] = {
-	[0] = {
-		.name	= "eth0 irq",
-		.start	= 9,
-		.end	= 9,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-
-static struct mv643xx_eth_platform_data eth0_pd = {
-	.tx_sram_addr = PEGASOS2_SRAM_BASE_ETH0,
-	.tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
-	.tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
-
-	.rx_sram_addr = PEGASOS2_SRAM_BASE_ETH0 + PEGASOS2_SRAM_TXRING_SIZE,
-	.rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE,
-	.rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16,
-};
-
-static struct platform_device eth0_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(mv643xx_eth0_resources),
-	.resource	= mv643xx_eth0_resources,
-	.dev = {
-		.platform_data = &eth0_pd,
-	},
-};
-
-static struct resource mv643xx_eth1_resources[] = {
-	[0] = {
-		.name	= "eth1 irq",
-		.start	= 9,
-		.end	= 9,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mv643xx_eth_platform_data eth1_pd = {
-	.tx_sram_addr = PEGASOS2_SRAM_BASE_ETH1,
-	.tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
-	.tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
-
-	.rx_sram_addr = PEGASOS2_SRAM_BASE_ETH1 + PEGASOS2_SRAM_TXRING_SIZE,
-	.rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE,
-	.rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16,
-};
-
-static struct platform_device eth1_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(mv643xx_eth1_resources),
-	.resource	= mv643xx_eth1_resources,
-	.dev = {
-		.platform_data = &eth1_pd,
-	},
-};
-
-static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
-	&mv643xx_eth_shared_device,
-	&eth0_device,
-	&eth1_device,
-};
-
-/***********/
-/***********/
-#define MV_READ(offset,val) 	{ val = readl(mv643xx_reg_base + offset); }
-#define MV_WRITE(offset,data) writel(data, mv643xx_reg_base + offset)
-
-static void __iomem *mv643xx_reg_base;
-
-static int Enable_SRAM(void)
-{
-	u32 ALong;
-
-	if (mv643xx_reg_base == NULL)
-		mv643xx_reg_base = ioremap(PEGASOS2_MARVELL_REGBASE,
-					PEGASOS2_MARVELL_REGSIZE);
-
-	if (mv643xx_reg_base == NULL)
-		return -ENOMEM;
-
-#ifdef BE_VERBOSE
-	printk("Pegasos II/Marvell MV64361: register remapped from %p to %p\n",
-		(void *)PEGASOS2_MARVELL_REGBASE, (void *)mv643xx_reg_base);
-#endif
-
-	MV_WRITE(MV64340_SRAM_CONFIG, 0);
-
-	MV_WRITE(MV64340_INTEGRATED_SRAM_BASE_ADDR, PEGASOS2_SRAM_BASE >> 16);
-
-	MV_READ(MV64340_BASE_ADDR_ENABLE, ALong);
-	ALong &= ~(1 << 19);
-	MV_WRITE(MV64340_BASE_ADDR_ENABLE, ALong);
-
-	ALong = 0x02;
-	ALong |= PEGASOS2_SRAM_BASE & 0xffff0000;
-	MV_WRITE(MV643XX_ETH_BAR_4, ALong);
-
-	MV_WRITE(MV643XX_ETH_SIZE_REG_4, (PEGASOS2_SRAM_SIZE-1) & 0xffff0000);
-
-	MV_READ(MV643XX_ETH_BASE_ADDR_ENABLE_REG, ALong);
-	ALong &= ~(1 << 4);
-	MV_WRITE(MV643XX_ETH_BASE_ADDR_ENABLE_REG, ALong);
-
-#ifdef BE_VERBOSE
-	printk("Pegasos II/Marvell MV64361: register unmapped\n");
-	printk("Pegasos II/Marvell MV64361: SRAM at %p, size=%x\n", (void*) PEGASOS2_SRAM_BASE, PEGASOS2_SRAM_SIZE);
-#endif
-
-	iounmap(mv643xx_reg_base);
-	mv643xx_reg_base = NULL;
-
-	return 1;
-}
-
-
-/***********/
-/***********/
-int mv643xx_eth_add_pds(void)
-{
-	int ret = 0;
-	static struct pci_device_id pci_marvell_mv64360[] = {
-		{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64360) },
-		{ }
-	};
-
-#ifdef BE_VERBOSE
-	printk("Pegasos II/Marvell MV64361: init\n");
-#endif
-
-	if (pci_dev_present(pci_marvell_mv64360)) {
-		ret = platform_add_devices(mv643xx_eth_pd_devs,
-				ARRAY_SIZE(mv643xx_eth_pd_devs));
-
-		if ( Enable_SRAM() < 0)
-		{
-			eth0_pd.tx_sram_addr = 0;
-			eth0_pd.tx_sram_size = 0;
-			eth0_pd.rx_sram_addr = 0;
-			eth0_pd.rx_sram_size = 0;
-
-			eth1_pd.tx_sram_addr = 0;
-			eth1_pd.tx_sram_size = 0;
-			eth1_pd.rx_sram_addr = 0;
-			eth1_pd.rx_sram_size = 0;
-
-#ifdef BE_VERBOSE
-			printk("Pegasos II/Marvell MV64361: Can't enable the "
-				"SRAM\n");
-#endif
-		}
-	}
-
-#ifdef BE_VERBOSE
-	printk("Pegasos II/Marvell MV64361: init is over\n");
-#endif
-
-	return ret;
-}
-
-device_initcall(mv643xx_eth_add_pds);
diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c
deleted file mode 100644
index f9fd3f4..0000000
--- a/arch/ppc/platforms/chrp_setup.c
+++ /dev/null
@@ -1,669 +0,0 @@
-/*
- *  Copyright (C) 1995  Linus Torvalds
- *  Adapted from 'alpha' version by Gary Thomas
- *  Modified by Cort Dougan (cort@cs.nmt.edu)
- */
-
-/*
- * bootup setup stuff..
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/major.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/version.h>
-#include <linux/adb.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-#include <linux/console.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-#include <linux/initrd.h>
-#include <linux/module.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/prom.h>
-#include <asm/gg2.h>
-#include <asm/pci-bridge.h>
-#include <asm/dma.h>
-#include <asm/machdep.h>
-#include <asm/irq.h>
-#include <asm/hydra.h>
-#include <asm/sections.h>
-#include <asm/time.h>
-#include <asm/btext.h>
-#include <asm/i8259.h>
-#include <asm/open_pic.h>
-#include <asm/xmon.h>
-#include "mem_pieces.h"
-
-unsigned long chrp_get_rtc_time(void);
-int chrp_set_rtc_time(unsigned long nowtime);
-void chrp_calibrate_decr(void);
-long chrp_time_init(void);
-
-void chrp_find_bridges(void);
-void chrp_event_scan(void);
-void rtas_display_progress(char *, unsigned short);
-void rtas_indicator_progress(char *, unsigned short);
-void btext_progress(char *, unsigned short);
-
-extern int of_show_percpuinfo(struct seq_file *, int);
-
-int _chrp_type;
-EXPORT_SYMBOL(_chrp_type);
-
-/*
- * XXX this should be in xmon.h, but putting it there means xmon.h
- * has to include <linux/interrupt.h> (to get irqreturn_t), which
- * causes all sorts of problems.  -- paulus
- */
-extern irqreturn_t xmon_irq(int, void *, struct pt_regs *);
-
-extern dev_t boot_dev;
-
-extern PTE *Hash, *Hash_end;
-extern unsigned long Hash_size, Hash_mask;
-extern int probingmem;
-extern unsigned long loops_per_jiffy;
-static int max_width;
-
-#ifdef CONFIG_SMP
-extern struct smp_ops_t chrp_smp_ops;
-#endif
-
-static const char *gg2_memtypes[4] = {
-	"FPM", "SDRAM", "EDO", "BEDO"
-};
-static const char *gg2_cachesizes[4] = {
-	"256 KB", "512 KB", "1 MB", "Reserved"
-};
-static const char *gg2_cachetypes[4] = {
-	"Asynchronous", "Reserved", "Flow-Through Synchronous",
-	"Pipelined Synchronous"
-};
-static const char *gg2_cachemodes[4] = {
-	"Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
-};
-
-int
-chrp_show_cpuinfo(struct seq_file *m)
-{
-	int i, sdramen;
-	unsigned int t;
-	struct device_node *root;
-	const char *model = "";
-
-	root = find_path_device("/");
-	if (root)
-		model = get_property(root, "model", NULL);
-	seq_printf(m, "machine\t\t: CHRP %s\n", model);
-
-	/* longtrail (goldengate) stuff */
-	if (!strncmp(model, "IBM,LongTrail", 13)) {
-		/* VLSI VAS96011/12 `Golden Gate 2' */
-		/* Memory banks */
-		sdramen = (in_le32(gg2_pci_config_base + GG2_PCI_DRAM_CTRL)
-			   >>31) & 1;
-		for (i = 0; i < (sdramen ? 4 : 6); i++) {
-			t = in_le32(gg2_pci_config_base+
-						 GG2_PCI_DRAM_BANK0+
-						 i*4);
-			if (!(t & 1))
-				continue;
-			switch ((t>>8) & 0x1f) {
-			case 0x1f:
-				model = "4 MB";
-				break;
-			case 0x1e:
-				model = "8 MB";
-				break;
-			case 0x1c:
-				model = "16 MB";
-				break;
-			case 0x18:
-				model = "32 MB";
-				break;
-			case 0x10:
-				model = "64 MB";
-				break;
-			case 0x00:
-				model = "128 MB";
-				break;
-			default:
-				model = "Reserved";
-				break;
-			}
-			seq_printf(m, "memory bank %d\t: %s %s\n", i, model,
-				   gg2_memtypes[sdramen ? 1 : ((t>>1) & 3)]);
-		}
-		/* L2 cache */
-		t = in_le32(gg2_pci_config_base+GG2_PCI_CC_CTRL);
-		seq_printf(m, "board l2\t: %s %s (%s)\n",
-			   gg2_cachesizes[(t>>7) & 3],
-			   gg2_cachetypes[(t>>2) & 3],
-			   gg2_cachemodes[t & 3]);
-	}
-	return 0;
-}
-
-/*
- *  Fixes for the National Semiconductor PC78308VUL SuperI/O
- *
- *  Some versions of Open Firmware incorrectly initialize the IRQ settings
- *  for keyboard and mouse
- */
-static inline void __init sio_write(u8 val, u8 index)
-{
-	outb(index, 0x15c);
-	outb(val, 0x15d);
-}
-
-static inline u8 __init sio_read(u8 index)
-{
-	outb(index, 0x15c);
-	return inb(0x15d);
-}
-
-static void __init sio_fixup_irq(const char *name, u8 device, u8 level,
-				     u8 type)
-{
-	u8 level0, type0, active;
-
-	/* select logical device */
-	sio_write(device, 0x07);
-	active = sio_read(0x30);
-	level0 = sio_read(0x70);
-	type0 = sio_read(0x71);
-	if (level0 != level || type0 != type || !active) {
-		printk(KERN_WARNING "sio: %s irq level %d, type %d, %sactive: "
-		       "remapping to level %d, type %d, active\n",
-		       name, level0, type0, !active ? "in" : "", level, type);
-		sio_write(0x01, 0x30);
-		sio_write(level, 0x70);
-		sio_write(type, 0x71);
-	}
-}
-
-static void __init sio_init(void)
-{
-	struct device_node *root;
-
-	if ((root = find_path_device("/")) &&
-	    !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) {
-		/* logical device 0 (KBC/Keyboard) */
-		sio_fixup_irq("keyboard", 0, 1, 2);
-		/* select logical device 1 (KBC/Mouse) */
-		sio_fixup_irq("mouse", 1, 12, 2);
-	}
-}
-
-
-static void __init pegasos_set_l2cr(void)
-{
-	struct device_node *np;
-
-	/* On Pegasos, enable the l2 cache if needed, as the OF forgets it */
-	if (_chrp_type != _CHRP_Pegasos)
-		return;
-
-	/* Enable L2 cache if needed */
-	np = find_type_devices("cpu");
-	if (np != NULL) {
-		unsigned int *l2cr = (unsigned int *)
-			get_property (np, "l2cr", NULL);
-		if (l2cr == NULL) {
-			printk ("Pegasos l2cr : no cpu l2cr property found\n");
-			return;
-		}
-		if (!((*l2cr) & 0x80000000)) {
-			printk ("Pegasos l2cr : L2 cache was not active, "
-				"activating\n");
-			_set_L2CR(0);
-			_set_L2CR((*l2cr) | 0x80000000);
-		}
-	}
-}
-
-void __init chrp_setup_arch(void)
-{
-	struct device_node *device;
-
-	/* init to some ~sane value until calibrate_delay() runs */
-	loops_per_jiffy = 50000000/HZ;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	/* this is fine for chrp */
-	initrd_below_start_ok = 1;
-
-	if (initrd_start)
-		ROOT_DEV = Root_RAM0;
-	else
-#endif
-		ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
-
-	/* On pegasos, enable the L2 cache if not already done by OF */
-	pegasos_set_l2cr();
-
-	/* Lookup PCI host bridges */
-	chrp_find_bridges();
-
-#ifndef CONFIG_PPC64BRIDGE
-	/*
-	 *  Temporary fixes for PCI devices.
-	 *  -- Geert
-	 */
-	hydra_init();		/* Mac I/O */
-
-#endif /* CONFIG_PPC64BRIDGE */
-
-	/*
-	 *  Fix the Super I/O configuration
-	 */
-	sio_init();
-
-	/* Get the event scan rate for the rtas so we know how
-	 * often it expects a heartbeat. -- Cort
-	 */
-	if ( rtas_data ) {
-		struct property *p;
-		device = find_devices("rtas");
-		for ( p = device->properties;
-		      p && strncmp(p->name, "rtas-event-scan-rate", 20);
-		      p = p->next )
-			/* nothing */ ;
-		if ( p && *(unsigned long *)p->value ) {
-			ppc_md.heartbeat = chrp_event_scan;
-			ppc_md.heartbeat_reset = (HZ/(*(unsigned long *)p->value)*30)-1;
-			ppc_md.heartbeat_count = 1;
-			printk("RTAS Event Scan Rate: %lu (%lu jiffies)\n",
-			       *(unsigned long *)p->value, ppc_md.heartbeat_reset );
-		}
-	}
-
-	pci_create_OF_bus_map();
-}
-
-void
-chrp_event_scan(void)
-{
-	unsigned char log[1024];
-	unsigned long ret = 0;
-	/* XXX: we should loop until the hardware says no more error logs -- Cort */
-	call_rtas( "event-scan", 4, 1, &ret, 0xffffffff, 0,
-		   __pa(log), 1024 );
-	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
-}
-
-void
-chrp_restart(char *cmd)
-{
-	printk("RTAS system-reboot returned %d\n",
-	       call_rtas("system-reboot", 0, 1, NULL));
-	for (;;);
-}
-
-void
-chrp_power_off(void)
-{
-	/* allow power on only with power button press */
-	printk("RTAS power-off returned %d\n",
-	       call_rtas("power-off", 2, 1, NULL,0xffffffff,0xffffffff));
-	for (;;);
-}
-
-void
-chrp_halt(void)
-{
-	chrp_power_off();
-}
-
-/*
- * Finds the open-pic node and sets OpenPIC_Addr based on its reg property.
- * Then checks if it has an interrupt-ranges property.  If it does then
- * we have a distributed open-pic, so call openpic_set_sources to tell
- * the openpic code where to find the interrupt source registers.
- */
-static void __init chrp_find_openpic(void)
-{
-	struct device_node *np;
-	int len, i;
-	unsigned int *iranges;
-	void __iomem *isu;
-
-	np = find_type_devices("open-pic");
-	if (np == NULL || np->n_addrs == 0)
-		return;
-	printk(KERN_INFO "OpenPIC at %x (size %x)\n",
-	       np->addrs[0].address, np->addrs[0].size);
-	OpenPIC_Addr = ioremap(np->addrs[0].address, 0x40000);
-	if (OpenPIC_Addr == NULL) {
-		printk(KERN_ERR "Failed to map OpenPIC!\n");
-		return;
-	}
-
-	iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len);
-	if (iranges == NULL || len < 2 * sizeof(unsigned int))
-		return;		/* not distributed */
-
-	/*
-	 * The first pair of cells in interrupt-ranges refers to the
-	 * IDU; subsequent pairs refer to the ISUs.
-	 */
-	len /= 2 * sizeof(unsigned int);
-	if (np->n_addrs < len) {
-		printk(KERN_ERR "Insufficient addresses for distributed"
-		       " OpenPIC (%d < %d)\n", np->n_addrs, len);
-		return;
-	}
-	if (iranges[1] != 0) {
-		printk(KERN_INFO "OpenPIC irqs %d..%d in IDU\n",
-		       iranges[0], iranges[0] + iranges[1] - 1);
-		openpic_set_sources(iranges[0], iranges[1], NULL);
-	}
-	for (i = 1; i < len; ++i) {
-		iranges += 2;
-		printk(KERN_INFO "OpenPIC irqs %d..%d in ISU at %x (%x)\n",
-		       iranges[0], iranges[0] + iranges[1] - 1,
-		       np->addrs[i].address, np->addrs[i].size);
-		isu = ioremap(np->addrs[i].address, np->addrs[i].size);
-		if (isu != NULL)
-			openpic_set_sources(iranges[0], iranges[1], isu);
-		else
-			printk(KERN_ERR "Failed to map OpenPIC ISU at %x!\n",
-			       np->addrs[i].address);
-	}
-}
-
-#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
-static struct irqaction xmon_irqaction = {
-	.handler = xmon_irq,
-	.mask = CPU_MASK_NONE,
-	.name = "XMON break",
-};
-#endif
-
-void __init chrp_init_IRQ(void)
-{
-	struct device_node *np;
-	unsigned long chrp_int_ack = 0;
-	unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
-#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
-	struct device_node *kbd;
-#endif
-
-	for (np = find_devices("pci"); np != NULL; np = np->next) {
-		unsigned int *addrp = (unsigned int *)
-			get_property(np, "8259-interrupt-acknowledge", NULL);
-
-		if (addrp == NULL)
-			continue;
-		chrp_int_ack = addrp[prom_n_addr_cells(np)-1];
-		break;
-	}
-	if (np == NULL)
-		printk(KERN_ERR "Cannot find PCI interrupt acknowledge address\n");
-
-	chrp_find_openpic();
-
-	if (OpenPIC_Addr) {
-		prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS);
-		OpenPIC_InitSenses = init_senses;
-		OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS;
-
-		openpic_init(NUM_8259_INTERRUPTS);
-		/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
-		openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
-				       i8259_irq);
-
-	}
-	i8259_init(chrp_int_ack, 0);
-
-#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
-	/* see if there is a keyboard in the device tree
-	   with a parent of type "adb" */
-	for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next)
-		if (kbd->parent && kbd->parent->type
-		    && strcmp(kbd->parent->type, "adb") == 0)
-			break;
-	if (kbd)
-		setup_irq(HYDRA_INT_ADB_NMI, &xmon_irqaction);
-#endif
-}
-
-void __init
-chrp_init2(void)
-{
-#ifdef CONFIG_NVRAM
-	chrp_nvram_init();
-#endif
-
-	request_region(0x20,0x20,"pic1");
-	request_region(0xa0,0x20,"pic2");
-	request_region(0x00,0x20,"dma1");
-	request_region(0x40,0x20,"timer");
-	request_region(0x80,0x10,"dma page reg");
-	request_region(0xc0,0x20,"dma2");
-
-	if (ppc_md.progress)
-		ppc_md.progress("  Have fun!    ", 0x7777);
-}
-
-static struct device_node *memory_node;
-
-static int __init get_mem_prop(char *name, struct mem_pieces *mp)
-{
-	struct reg_property *rp;
-	int i, s;
-	unsigned int *ip;
-	int nac = prom_n_addr_cells(memory_node);
-	int nsc = prom_n_size_cells(memory_node);
-
-	ip = (unsigned int *) get_property(memory_node, name, &s);
-	if (ip == NULL) {
-		printk(KERN_ERR "error: couldn't get %s property on /memory\n",
-		       name);
-		return 0;
-	}
-	s /= (nsc + nac) * 4;
-	rp = mp->regions;
-	for (i = 0; i < s; ++i, ip += nac+nsc) {
-		if (nac >= 2 && ip[nac-2] != 0)
-			continue;
-		rp->address = ip[nac-1];
-		if (nsc >= 2 && ip[nac+nsc-2] != 0)
-			rp->size = ~0U;
-		else
-			rp->size = ip[nac+nsc-1];
-		++rp;
-	}
-	mp->n_regions = rp - mp->regions;
-
-	/* Make sure the pieces are sorted. */
-	mem_pieces_sort(mp);
-	mem_pieces_coalesce(mp);
-	return 1;
-}
-
-static unsigned long __init chrp_find_end_of_memory(void)
-{
-	unsigned long a, total;
-	struct mem_pieces phys_mem;
-
-	/*
-	 * Find out where physical memory is, and check that it
-	 * starts at 0 and is contiguous.  It seems that RAM is
-	 * always physically contiguous on Power Macintoshes.
-	 *
-	 * Supporting discontiguous physical memory isn't hard,
-	 * it just makes the virtual <-> physical mapping functions
-	 * more complicated (or else you end up wasting space
-	 * in mem_map).
-	 */
-	memory_node = find_devices("memory");
-	if (memory_node == NULL || !get_mem_prop("reg", &phys_mem)
-	    || phys_mem.n_regions == 0)
-		panic("No RAM??");
-	a = phys_mem.regions[0].address;
-	if (a != 0)
-		panic("RAM doesn't start at physical address 0");
-	total = phys_mem.regions[0].size;
-
-	if (phys_mem.n_regions > 1) {
-		printk("RAM starting at 0x%x is not contiguous\n",
-		       phys_mem.regions[1].address);
-		printk("Using RAM from 0 to 0x%lx\n", total-1);
-	}
-
-	return total;
-}
-
-void __init
-chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	  unsigned long r6, unsigned long r7)
-{
-	struct device_node *root = find_path_device ("/");
-	char *machine = NULL;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	/* take care of initrd if we have one */
-	if ( r6 )
-	{
-		initrd_start = r6 + KERNELBASE;
-		initrd_end = r6 + r7 + KERNELBASE;
-	}
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-	ISA_DMA_THRESHOLD = ~0L;
-	DMA_MODE_READ = 0x44;
-	DMA_MODE_WRITE = 0x48;
-	isa_io_base = CHRP_ISA_IO_BASE;		/* default value */
-	ppc_do_canonicalize_irqs = 1;
-
-	if (root)
-		machine = get_property(root, "model", NULL);
-	if (machine && strncmp(machine, "Pegasos", 7) == 0) {
-		_chrp_type = _CHRP_Pegasos;
-	} else if (machine && strncmp(machine, "IBM", 3) == 0) {
-		_chrp_type = _CHRP_IBM;
-	} else if (machine && strncmp(machine, "MOT", 3) == 0) {
-		_chrp_type = _CHRP_Motorola;
-	} else {
-		/* Let's assume it is an IBM chrp if all else fails */
-		_chrp_type = _CHRP_IBM;
-	}
-
-	ppc_md.setup_arch     = chrp_setup_arch;
-	ppc_md.show_percpuinfo = of_show_percpuinfo;
-	ppc_md.show_cpuinfo   = chrp_show_cpuinfo;
-
-	ppc_md.init_IRQ       = chrp_init_IRQ;
-	if (_chrp_type == _CHRP_Pegasos)
-		ppc_md.get_irq        = i8259_irq;
-	else
-		ppc_md.get_irq        = openpic_get_irq;
-
-	ppc_md.init           = chrp_init2;
-
-	ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
-
-	ppc_md.restart        = chrp_restart;
-	ppc_md.power_off      = chrp_power_off;
-	ppc_md.halt           = chrp_halt;
-
-	ppc_md.time_init      = chrp_time_init;
-	ppc_md.set_rtc_time   = chrp_set_rtc_time;
-	ppc_md.get_rtc_time   = chrp_get_rtc_time;
-	ppc_md.calibrate_decr = chrp_calibrate_decr;
-
-	ppc_md.find_end_of_memory = chrp_find_end_of_memory;
-
-	if (rtas_data) {
-		struct device_node *rtas;
-		unsigned int *p;
-
-		rtas = find_devices("rtas");
-		if (rtas != NULL) {
-			if (get_property(rtas, "display-character", NULL)) {
-				ppc_md.progress = rtas_display_progress;
-				p = (unsigned int *) get_property
-				       (rtas, "ibm,display-line-length", NULL);
-				if (p)
-					max_width = *p;
-			} else if (get_property(rtas, "set-indicator", NULL))
-				ppc_md.progress = rtas_indicator_progress;
-		}
-	}
-#ifdef CONFIG_BOOTX_TEXT
-	if (ppc_md.progress == NULL && boot_text_mapped)
-		ppc_md.progress = btext_progress;
-#endif
-
-#ifdef CONFIG_SMP
-	smp_ops = &chrp_smp_ops;
-#endif /* CONFIG_SMP */
-
-	/*
-	 * Print the banner, then scroll down so boot progress
-	 * can be printed.  -- Cort
-	 */
-	if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
-}
-
-void
-rtas_display_progress(char *s, unsigned short hex)
-{
-	int width;
-	char *os = s;
-
-	if ( call_rtas( "display-character", 1, 1, NULL, '\r' ) )
-		return;
-
-	width = max_width;
-	while ( *os )
-	{
-		if ( (*os == '\n') || (*os == '\r') )
-			width = max_width;
-		else
-			width--;
-		call_rtas( "display-character", 1, 1, NULL, *os++ );
-		/* if we overwrite the screen length */
-		if ( width == 0 )
-			while ( (*os != 0) && (*os != '\n') && (*os != '\r') )
-				os++;
-	}
-
-	/*while ( width-- > 0 )*/
-	call_rtas( "display-character", 1, 1, NULL, ' ' );
-}
-
-void
-rtas_indicator_progress(char *s, unsigned short hex)
-{
-	call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex);
-}
-
-#ifdef CONFIG_BOOTX_TEXT
-void
-btext_progress(char *s, unsigned short hex)
-{
-	prom_print(s);
-	prom_print("\n");
-}
-#endif /* CONFIG_BOOTX_TEXT */
diff --git a/arch/ppc/platforms/chrp_smp.c b/arch/ppc/platforms/chrp_smp.c
deleted file mode 100644
index 97e5395..0000000
--- a/arch/ppc/platforms/chrp_smp.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Smp support for CHRP machines.
- *
- * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
- * deal of code from the sparc and intel versions.
- *
- * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <asm/ptrace.h>
-#include <asm/atomic.h>
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/smp.h>
-#include <asm/residual.h>
-#include <asm/time.h>
-#include <asm/open_pic.h>
-#include <asm/machdep.h>
-
-extern unsigned long smp_chrp_cpu_nr;
-
-static int __init
-smp_chrp_probe(void)
-{
-	if (smp_chrp_cpu_nr > 1)
-		openpic_request_IPIs();
-
-	return smp_chrp_cpu_nr;
-}
-
-static void __devinit
-smp_chrp_kick_cpu(int nr)
-{
-	*(unsigned long *)KERNELBASE = nr;
-	asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
-}
-
-static void __devinit
-smp_chrp_setup_cpu(int cpu_nr)
-{
-	if (OpenPIC_Addr)
-		do_openpic_setup_cpu();
-}
-
-static DEFINE_SPINLOCK(timebase_lock);
-static unsigned int timebase_upper = 0, timebase_lower = 0;
-
-void __devinit
-smp_chrp_give_timebase(void)
-{
-	spin_lock(&timebase_lock);
-	call_rtas("freeze-time-base", 0, 1, NULL);
-	timebase_upper = get_tbu();
-	timebase_lower = get_tbl();
-	spin_unlock(&timebase_lock);
-
-	while (timebase_upper || timebase_lower)
-		barrier();
-	call_rtas("thaw-time-base", 0, 1, NULL);
-}
-
-void __devinit
-smp_chrp_take_timebase(void)
-{
-	while (!(timebase_upper || timebase_lower))
-		barrier();
-	spin_lock(&timebase_lock);
-	set_tb(timebase_upper, timebase_lower);
-	timebase_upper = 0;
-	timebase_lower = 0;
-	spin_unlock(&timebase_lock);
-	printk("CPU %i taken timebase\n", smp_processor_id());
-}
-
-/* CHRP with openpic */
-struct smp_ops_t chrp_smp_ops = {
-	.message_pass = smp_openpic_message_pass,
-	.probe = smp_chrp_probe,
-	.kick_cpu = smp_chrp_kick_cpu,
-	.setup_cpu = smp_chrp_setup_cpu,
-	.give_timebase = smp_chrp_give_timebase,
-	.take_timebase = smp_chrp_take_timebase,
-};
diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c
deleted file mode 100644
index 51e06ad..0000000
--- a/arch/ppc/platforms/chrp_time.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
- *
- * Adapted for PowerPC (PReP) by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu).
- * Copied and modified from arch/i386/kernel/time.c
- *
- */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/timex.h>
-#include <linux/kernel_stat.h>
-#include <linux/mc146818rtc.h>
-#include <linux/init.h>
-#include <linux/bcd.h>
-
-#include <asm/io.h>
-#include <asm/nvram.h>
-#include <asm/prom.h>
-#include <asm/sections.h>
-#include <asm/time.h>
-
-extern spinlock_t rtc_lock;
-
-static int nvram_as1 = NVRAM_AS1;
-static int nvram_as0 = NVRAM_AS0;
-static int nvram_data = NVRAM_DATA;
-
-long __init chrp_time_init(void)
-{
-	struct device_node *rtcs;
-	int base;
-
-	rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
-	if (rtcs == NULL)
-		rtcs = find_compatible_devices("rtc", "ds1385-rtc");
-	if (rtcs == NULL || rtcs->addrs == NULL)
-		return 0;
-	base = rtcs->addrs[0].address;
-	nvram_as1 = 0;
-	nvram_as0 = base;
-	nvram_data = base + 1;
-
-	return 0;
-}
-
-int chrp_cmos_clock_read(int addr)
-{
-	if (nvram_as1 != 0)
-		outb(addr>>8, nvram_as1);
-	outb(addr, nvram_as0);
-	return (inb(nvram_data));
-}
-
-void chrp_cmos_clock_write(unsigned long val, int addr)
-{
-	if (nvram_as1 != 0)
-		outb(addr>>8, nvram_as1);
-	outb(addr, nvram_as0);
-	outb(val, nvram_data);
-	return;
-}
-
-/*
- * Set the hardware clock. -- Cort
- */
-int chrp_set_rtc_time(unsigned long nowtime)
-{
-	unsigned char save_control, save_freq_select;
-	struct rtc_time tm;
-
-	spin_lock(&rtc_lock);
-	to_tm(nowtime, &tm);
-
-	save_control = chrp_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */
-
-	chrp_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL);
-
-	save_freq_select = chrp_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
-
-	chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-
-        tm.tm_year -= 1900;
-	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-		BIN_TO_BCD(tm.tm_sec);
-		BIN_TO_BCD(tm.tm_min);
-		BIN_TO_BCD(tm.tm_hour);
-		BIN_TO_BCD(tm.tm_mon);
-		BIN_TO_BCD(tm.tm_mday);
-		BIN_TO_BCD(tm.tm_year);
-	}
-	chrp_cmos_clock_write(tm.tm_sec,RTC_SECONDS);
-	chrp_cmos_clock_write(tm.tm_min,RTC_MINUTES);
-	chrp_cmos_clock_write(tm.tm_hour,RTC_HOURS);
-	chrp_cmos_clock_write(tm.tm_mon,RTC_MONTH);
-	chrp_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH);
-	chrp_cmos_clock_write(tm.tm_year,RTC_YEAR);
-
-	/* The following flags have to be released exactly in this order,
-	 * otherwise the DS12887 (popular MC146818A clone with integrated
-	 * battery and quartz) will not reset the oscillator and will not
-	 * update precisely 500 ms later. You won't find this mentioned in
-	 * the Dallas Semiconductor data sheets, but who believes data
-	 * sheets anyway ...                           -- Markus Kuhn
-	 */
-	chrp_cmos_clock_write(save_control, RTC_CONTROL);
-	chrp_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT);
-
-	spin_unlock(&rtc_lock);
-	return 0;
-}
-
-unsigned long chrp_get_rtc_time(void)
-{
-	unsigned int year, mon, day, hour, min, sec;
-
-	do {
-		sec = chrp_cmos_clock_read(RTC_SECONDS);
-		min = chrp_cmos_clock_read(RTC_MINUTES);
-		hour = chrp_cmos_clock_read(RTC_HOURS);
-		day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);
-		mon = chrp_cmos_clock_read(RTC_MONTH);
-		year = chrp_cmos_clock_read(RTC_YEAR);
-	} while (sec != chrp_cmos_clock_read(RTC_SECONDS));
-
-	if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY)
-	    || RTC_ALWAYS_BCD) {
-		BCD_TO_BIN(sec);
-		BCD_TO_BIN(min);
-		BCD_TO_BIN(hour);
-		BCD_TO_BIN(day);
-		BCD_TO_BIN(mon);
-		BCD_TO_BIN(year);
-	}
-
-	year += 1900;
-	if (year < 1970)
-		year += 100;
-	return mktime(year, mon, day, hour, min, sec);
-}
-
-/*
- * Calibrate the decrementer frequency with the VIA timer 1.
- */
-#define VIA_TIMER_FREQ_6	4700000	/* time 1 frequency * 6 */
-
-/* VIA registers */
-#define RS		0x200		/* skip between registers */
-#define T1CL		(4*RS)		/* Timer 1 ctr/latch (low 8 bits) */
-#define T1CH		(5*RS)		/* Timer 1 counter (high 8 bits) */
-#define T1LL		(6*RS)		/* Timer 1 latch (low 8 bits) */
-#define T1LH		(7*RS)		/* Timer 1 latch (high 8 bits) */
-#define ACR		(11*RS)		/* Auxiliary control register */
-#define IFR		(13*RS)		/* Interrupt flag register */
-
-/* Bits in ACR */
-#define T1MODE		0xc0		/* Timer 1 mode */
-#define T1MODE_CONT	0x40		/*  continuous interrupts */
-
-/* Bits in IFR and IER */
-#define T1_INT		0x40		/* Timer 1 interrupt */
-
-static int __init chrp_via_calibrate_decr(void)
-{
-	struct device_node *vias;
-	volatile unsigned char __iomem *via;
-	int count = VIA_TIMER_FREQ_6 / 100;
-	unsigned int dstart, dend;
-
-	vias = find_devices("via-cuda");
-	if (vias == 0)
-		vias = find_devices("via");
-	if (vias == 0 || vias->n_addrs == 0)
-		return 0;
-	via = ioremap(vias->addrs[0].address, vias->addrs[0].size);
-
-	/* set timer 1 for continuous interrupts */
-	out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
-	/* set the counter to a small value */
-	out_8(&via[T1CH], 2);
-	/* set the latch to `count' */
-	out_8(&via[T1LL], count);
-	out_8(&via[T1LH], count >> 8);
-	/* wait until it hits 0 */
-	while ((in_8(&via[IFR]) & T1_INT) == 0)
-		;
-	dstart = get_dec();
-	/* clear the interrupt & wait until it hits 0 again */
-	in_8(&via[T1CL]);
-	while ((in_8(&via[IFR]) & T1_INT) == 0)
-		;
-	dend = get_dec();
-
-	tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100);
-	tb_to_us = mulhwu_scale_factor(dstart - dend, 60000);
-
-	printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",
-	       tb_ticks_per_jiffy, dstart - dend);
-
-	iounmap(via);
-	
-	return 1;
-}
-
-void __init chrp_calibrate_decr(void)
-{
-	struct device_node *cpu;
-	unsigned int freq, *fp;
-
-	if (chrp_via_calibrate_decr())
-		return;
-
-	/*
-	 * The cpu node should have a timebase-frequency property
-	 * to tell us the rate at which the decrementer counts.
-	 */
-	freq = 16666000;		/* hardcoded default */
-	cpu = find_type_devices("cpu");
-	if (cpu != 0) {
-		fp = (unsigned int *)
-			get_property(cpu, "timebase-frequency", NULL);
-		if (fp != 0)
-			freq = *fp;
-	}
-	printk("time_init: decrementer frequency = %u.%.6u MHz\n",
- 	       freq/1000000, freq%1000000);
-	tb_ticks_per_jiffy = freq / HZ;
-	tb_to_us = mulhwu_scale_factor(freq, 1000000);
-}
diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c
index 5171b53..fecbe9a 100644
--- a/arch/ppc/platforms/lite5200.c
+++ b/arch/ppc/platforms/lite5200.c
@@ -34,8 +34,7 @@
 #include <asm/mpc52xx.h>
 #include <asm/ppc_sys.h>
 #include <asm/machdep.h>
-
-#include <syslib/mpc52xx_pci.h>
+#include <asm/pci-bridge.h>
 
 
 extern int powersave_nap;
@@ -68,44 +67,53 @@
 }
 
 #ifdef CONFIG_PCI
+#ifdef CONFIG_LITE5200B
+static int
+lite5200_map_irq(struct pci_dev *dev, unsigned char idsel,
+		    unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	/*
+	 *      PCI IDSEL/INTPIN->INTLINE
+	 *        A             B             C             D
+	 */
+	{
+		{MPC52xx_IRQ0, MPC52xx_IRQ1, MPC52xx_IRQ2, MPC52xx_IRQ3},
+		{MPC52xx_IRQ1, MPC52xx_IRQ2, MPC52xx_IRQ3, MPC52xx_IRQ0},
+	};
+
+	const long min_idsel = 24, max_idsel = 25, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+#else /* Original Lite */
 static int
 lite5200_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
 {
 	return (pin == 1) && (idsel==24) ? MPC52xx_IRQ0 : -1;
 }
 #endif
+#endif
 
 static void __init
 lite5200_setup_cpu(void)
 {
-	struct mpc52xx_cdm  __iomem *cdm;
 	struct mpc52xx_gpio __iomem *gpio;
 	struct mpc52xx_intr __iomem *intr;
-	struct mpc52xx_xlb  __iomem *xlb;
 
 	u32 port_config;
 	u32 intr_ctrl;
 
 	/* Map zones */
-	cdm  = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
 	gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
-	xlb  = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE);
 	intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
 
-	if (!cdm || !gpio || !xlb || !intr) {
-		printk("lite5200.c: Error while mapping CDM/GPIO/XLB/INTR during"
-				"lite5200_setup_cpu\n");
+	if (!gpio || !intr) {
+		printk(KERN_ERR __FILE__ ": "
+			"Error while mapping GPIO/INTR during "
+			"lite5200_setup_cpu\n");
 		goto unmap_regs;
 	}
 
-	/* Use internal 48 Mhz */
-	out_8(&cdm->ext_48mhz_en, 0x00);
-	out_8(&cdm->fd_enable, 0x01);
-	if (in_be32(&cdm->rstcfg) & 0x40)	/* Assumes 33Mhz clock */
-		out_be16(&cdm->fd_counters, 0x0001);
-	else
-		out_be16(&cdm->fd_counters, 0x5555);
-
 	/* Get port mux config */
 	port_config = in_be32(&gpio->port_config);
 
@@ -116,29 +124,29 @@
 	port_config &= ~0x00007000;	/* Differential mode - USB1 only */
 	port_config |=  0x00001000;
 
+	/* ATA CS is on csb_4/5 */
+	port_config &= ~0x03000000;
+	port_config |=  0x01000000;
+
 	/* Commit port config */
 	out_be32(&gpio->port_config, port_config);
 
-	/* Configure the XLB Arbiter */
-	out_be32(&xlb->master_pri_enable, 0xff);
-	out_be32(&xlb->master_priority, 0x11111111);
-
-	/* Enable ram snooping for 1GB window */
-	out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_SNOOP);
-	out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d);
-
-	/* IRQ[0-3] setup : IRQ0     - Level Active Low  */
-	/*                  IRQ[1-3] - Level Active High */
+	/* IRQ[0-3] setup */
 	intr_ctrl = in_be32(&intr->ctrl);
 	intr_ctrl &= ~0x00ff0000;
-	intr_ctrl |=  0x00c00000;
+#ifdef CONFIG_LITE5200B
+	/* IRQ[0-3] Level Active Low */
+	intr_ctrl |=  0x00ff0000;
+#else
+	/* IRQ0 Level Active Low
+	 * IRQ[1-3] Level Active High */
+ 	intr_ctrl |=  0x00c00000;
+#endif
 	out_be32(&intr->ctrl, intr_ctrl);
 
 	/* Unmap reg zone */
 unmap_regs:
-	if (cdm)  iounmap(cdm);
 	if (gpio) iounmap(gpio);
-	if (xlb)  iounmap(xlb);
 	if (intr) iounmap(intr);
 }
 
@@ -146,7 +154,8 @@
 lite5200_setup_arch(void)
 {
 	/* CPU & Port mux setup */
-	lite5200_setup_cpu();
+	mpc52xx_setup_cpu();	/* Generic */
+	lite5200_setup_cpu();	/* Platform specific */
 
 #ifdef CONFIG_PCI
 	/* PCI Bridge setup */
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
index d95c05d..e86f615 100644
--- a/arch/ppc/platforms/prep_setup.c
+++ b/arch/ppc/platforms/prep_setup.c
@@ -1067,15 +1067,13 @@
 static int __init
 prep_request_io(void)
 {
-	if (_machine == _MACH_prep) {
 #ifdef CONFIG_NVRAM
-		request_region(PREP_NVRAM_AS0, 0x8, "nvram");
+	request_region(PREP_NVRAM_AS0, 0x8, "nvram");
 #endif
-		request_region(0x00,0x20,"dma1");
-		request_region(0x40,0x20,"timer");
-		request_region(0x80,0x10,"dma page reg");
-		request_region(0xc0,0x20,"dma2");
-	}
+	request_region(0x00,0x20,"dma1");
+	request_region(0x40,0x20,"timer");
+	request_region(0x80,0x10,"dma page reg");
+	request_region(0xc0,0x20,"dma2");
 
 	return 0;
 }
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 5cb62c6..490749c 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -38,8 +38,6 @@
 obj-$(CONFIG_8xx)		+= m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \
 				   ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o
 obj-$(CONFIG_PCI_QSPAN)		+= qspan_pci.o
-obj-$(CONFIG_PPC_OF)		+= prom_init.o prom.o
-obj-$(CONFIG_PPC_CHRP)		+= open_pic.o
 obj-$(CONFIG_PPC_PREP)		+= open_pic.o todc_time.o
 obj-$(CONFIG_BAMBOO)		+= pci_auto.o todc_time.o
 obj-$(CONFIG_CPCI690)		+= todc_time.o pci_auto.o
diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c
index 9ec525f..5a5a7a9 100644
--- a/arch/ppc/syslib/mpc52xx_pci.c
+++ b/arch/ppc/syslib/mpc52xx_pci.c
@@ -225,7 +225,8 @@
 	/* The PCI Host bridge of MPC52xx has a prefetch memory resource
 	   fixed to 1Gb. Doesn't fit in the resource system so we remove it */
 	if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
-	     (dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200) ) {
+	     (   dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200
+	      || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
 		struct resource *res = &dev->resource[1];
 		res->start = res->end = res->flags = 0;
 	}
diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c
index 2ee48ce..ee6379b 100644
--- a/arch/ppc/syslib/mpc52xx_setup.c
+++ b/arch/ppc/syslib/mpc52xx_setup.c
@@ -24,6 +24,8 @@
 #include <asm/pgtable.h>
 #include <asm/ppcboot.h>
 
+#include <syslib/mpc52xx_pci.h>
+
 extern bd_t __res;
 
 static int core_mult[] = {		/* CPU Frequency multiplier, taken    */
@@ -216,6 +218,52 @@
 	tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000);
 }
 
+
+void __init
+mpc52xx_setup_cpu(void)
+{
+	struct mpc52xx_cdm  __iomem *cdm;
+	struct mpc52xx_xlb  __iomem *xlb;
+
+	/* Map zones */
+	cdm  = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
+	xlb  = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE);
+
+	if (!cdm || !xlb) {
+		printk(KERN_ERR __FILE__ ": "
+			"Error while mapping CDM/XLB during "
+			"mpc52xx_setup_cpu\n");
+		goto unmap_regs;
+	}
+
+	/* Use internal 48 Mhz */
+	out_8(&cdm->ext_48mhz_en, 0x00);
+	out_8(&cdm->fd_enable, 0x01);
+	if (in_be32(&cdm->rstcfg) & 0x40)	/* Assumes 33Mhz clock */
+		out_be16(&cdm->fd_counters, 0x0001);
+	else
+		out_be16(&cdm->fd_counters, 0x5555);
+
+	/* Configure the XLB Arbiter priorities */
+	out_be32(&xlb->master_pri_enable, 0xff);
+	out_be32(&xlb->master_priority, 0x11111111);
+
+	/* Enable ram snooping for 1GB window */
+	out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_SNOOP);
+	out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d);
+
+	/* Disable XLB pipelining */
+	/* (cfr errate 292. We could do this only just before ATA PIO
+	    transaction and re-enable it after ...) */
+	out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS);
+
+	/* Unmap reg zone */
+unmap_regs:
+	if (cdm)  iounmap(cdm);
+	if (xlb)  iounmap(xlb);
+}
+
+
 int mpc52xx_match_psc_function(int psc_idx, const char *func)
 {
 	struct mpc52xx_psc_func *cf = mpc52xx_psc_functions;
diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
index 38e5b93..70456c8 100644
--- a/arch/ppc/syslib/open_pic.c
+++ b/arch/ppc/syslib/open_pic.c
@@ -216,7 +216,7 @@
 u_int openpic_read_IPI(volatile u_int __iomem * addr)
 {
          u_int val = 0;
-#if defined(OPENPIC_BIG_ENDIAN) || defined(CONFIG_POWER3)
+#if defined(OPENPIC_BIG_ENDIAN)
         val = in_be32(addr);
 #else
         val = in_le32(addr);
diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c
deleted file mode 100644
index 482f837..0000000
--- a/arch/ppc/syslib/prom.c
+++ /dev/null
@@ -1,1429 +0,0 @@
-/*
- * Procedures for interfacing to the Open Firmware PROM on
- * Power Macintosh computers.
- *
- * In particular, we are interested in the device tree
- * and in using some of its services (exit, write to stdout).
- *
- * Paul Mackerras	August 1996.
- * Copyright (C) 1996 Paul Mackerras.
- */
-#include <stdarg.h>
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/threads.h>
-#include <linux/spinlock.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-
-#include <asm/sections.h>
-#include <asm/prom.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/bootx.h>
-#include <asm/system.h>
-#include <asm/mmu.h>
-#include <asm/pgtable.h>
-#include <asm/bootinfo.h>
-#include <asm/btext.h>
-#include <asm/pci-bridge.h>
-#include <asm/open_pic.h>
-
-
-struct pci_address {
-	unsigned a_hi;
-	unsigned a_mid;
-	unsigned a_lo;
-};
-
-struct pci_reg_property {
-	struct pci_address addr;
-	unsigned size_hi;
-	unsigned size_lo;
-};
-
-struct isa_reg_property {
-	unsigned space;
-	unsigned address;
-	unsigned size;
-};
-
-typedef unsigned long interpret_func(struct device_node *, unsigned long,
-				     int, int);
-static interpret_func interpret_pci_props;
-static interpret_func interpret_dbdma_props;
-static interpret_func interpret_isa_props;
-static interpret_func interpret_macio_props;
-static interpret_func interpret_root_props;
-
-extern char *klimit;
-
-/* Set for a newworld or CHRP machine */
-int use_of_interrupt_tree;
-struct device_node *dflt_interrupt_controller;
-int num_interrupt_controllers;
-
-extern unsigned int rtas_entry;  /* physical pointer */
-
-extern struct device_node *allnodes;
-
-static unsigned long finish_node(struct device_node *, unsigned long,
-				 interpret_func *, int, int);
-static unsigned long finish_node_interrupts(struct device_node *, unsigned long);
-static struct device_node *find_phandle(phandle);
-
-extern void enter_rtas(void *);
-void phys_call_rtas(int, int, int, ...);
-
-extern char cmd_line[512];	/* XXX */
-extern boot_infos_t *boot_infos;
-unsigned long dev_tree_size;
-
-void
-phys_call_rtas(int service, int nargs, int nret, ...)
-{
-	va_list list;
-	union {
-		unsigned long words[16];
-		double align;
-	} u;
-	void (*rtas)(void *, unsigned long);
-	int i;
-
-	u.words[0] = service;
-	u.words[1] = nargs;
-	u.words[2] = nret;
-	va_start(list, nret);
-	for (i = 0; i < nargs; ++i)
-		u.words[i+3] = va_arg(list, unsigned long);
-	va_end(list);
-
-	rtas = (void (*)(void *, unsigned long)) rtas_entry;
-	rtas(&u, rtas_data);
-}
-
-/*
- * finish_device_tree is called once things are running normally
- * (i.e. with text and data mapped to the address they were linked at).
- * It traverses the device tree and fills in the name, type,
- * {n_}addrs and {n_}intrs fields of each node.
- */
-void __init
-finish_device_tree(void)
-{
-	unsigned long mem = (unsigned long) klimit;
-	struct device_node *np;
-
-	/* All CHRPs now use the interrupt tree */
-	for (np = allnodes; np != NULL; np = np->allnext) {
-		if (get_property(np, "interrupt-parent", NULL)) {
-			use_of_interrupt_tree = 1;
-			break;
-		}
-	}
-
-	if (use_of_interrupt_tree) {
-		/*
-		 * We want to find out here how many interrupt-controller
-		 * nodes there are, and if we are booted from BootX,
-		 * we need a pointer to the first (and hopefully only)
-		 * such node.  But we can't use find_devices here since
-		 * np->name has not been set yet.  -- paulus
-		 */
-		int n = 0;
-		char *name, *ic;
-		int iclen;
-
-		for (np = allnodes; np != NULL; np = np->allnext) {
-			ic = get_property(np, "interrupt-controller", &iclen);
-			name = get_property(np, "name", NULL);
-			/* checking iclen makes sure we don't get a false
-			   match on /chosen.interrupt_controller */
-			if ((name != NULL
-			     && strcmp(name, "interrupt-controller") == 0)
-			    || (ic != NULL && iclen == 0 && strcmp(name, "AppleKiwi"))) {
-				if (n == 0)
-					dflt_interrupt_controller = np;
-				++n;
-			}
-		}
-		num_interrupt_controllers = n;
-	}
-
-	mem = finish_node(allnodes, mem, NULL, 1, 1);
-	dev_tree_size = mem - (unsigned long) allnodes;
-	klimit = (char *) mem;
-}
-
-static unsigned long __init
-finish_node(struct device_node *np, unsigned long mem_start,
-	    interpret_func *ifunc, int naddrc, int nsizec)
-{
-	struct device_node *child;
-	int *ip;
-
-	np->name = get_property(np, "name", NULL);
-	np->type = get_property(np, "device_type", NULL);
-
-	if (!np->name)
-		np->name = "<NULL>";
-	if (!np->type)
-		np->type = "<NULL>";
-
-	/* get the device addresses and interrupts */
-	if (ifunc != NULL)
-		mem_start = ifunc(np, mem_start, naddrc, nsizec);
-
-	if (use_of_interrupt_tree)
-		mem_start = finish_node_interrupts(np, mem_start);
-
-	/* Look for #address-cells and #size-cells properties. */
-	ip = (int *) get_property(np, "#address-cells", NULL);
-	if (ip != NULL)
-		naddrc = *ip;
-	ip = (int *) get_property(np, "#size-cells", NULL);
-	if (ip != NULL)
-		nsizec = *ip;
-
-	if (np->parent == NULL)
-		ifunc = interpret_root_props;
-	else if (np->type == 0)
-		ifunc = NULL;
-	else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))
-		ifunc = interpret_pci_props;
-	else if (!strcmp(np->type, "dbdma"))
-		ifunc = interpret_dbdma_props;
-	else if (!strcmp(np->type, "mac-io")
-		 || ifunc == interpret_macio_props)
-		ifunc = interpret_macio_props;
-	else if (!strcmp(np->type, "isa"))
-		ifunc = interpret_isa_props;
-	else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3"))
-		ifunc = interpret_root_props;
-	else if (!((ifunc == interpret_dbdma_props
-		    || ifunc == interpret_macio_props)
-		   && (!strcmp(np->type, "escc")
-		       || !strcmp(np->type, "media-bay"))))
-		ifunc = NULL;
-
-	/* if we were booted from BootX, convert the full name */
-	if (boot_infos
-	    && strncmp(np->full_name, "Devices:device-tree", 19) == 0) {
-		if (np->full_name[19] == 0) {
-			strcpy(np->full_name, "/");
-		} else if (np->full_name[19] == ':') {
-			char *p = np->full_name + 19;
-			np->full_name = p;
-			for (; *p; ++p)
-				if (*p == ':')
-					*p = '/';
-		}
-	}
-
-	for (child = np->child; child != NULL; child = child->sibling)
-		mem_start = finish_node(child, mem_start, ifunc,
-					naddrc, nsizec);
-
-	return mem_start;
-}
-
-/*
- * Find the interrupt parent of a node.
- */
-static struct device_node * __init
-intr_parent(struct device_node *p)
-{
-	phandle *parp;
-
-	parp = (phandle *) get_property(p, "interrupt-parent", NULL);
-	if (parp == NULL)
-		return p->parent;
-	p = find_phandle(*parp);
-	if (p != NULL)
-		return p;
-	/*
-	 * On a powermac booted with BootX, we don't get to know the
-	 * phandles for any nodes, so find_phandle will return NULL.
-	 * Fortunately these machines only have one interrupt controller
-	 * so there isn't in fact any ambiguity.  -- paulus
-	 */
-	if (num_interrupt_controllers == 1)
-		p = dflt_interrupt_controller;
-	return p;
-}
-
-/*
- * Find out the size of each entry of the interrupts property
- * for a node.
- */
-static int __init
-prom_n_intr_cells(struct device_node *np)
-{
-	struct device_node *p;
-	unsigned int *icp;
-
-	for (p = np; (p = intr_parent(p)) != NULL; ) {
-		icp = (unsigned int *)
-			get_property(p, "#interrupt-cells", NULL);
-		if (icp != NULL)
-			return *icp;
-		if (get_property(p, "interrupt-controller", NULL) != NULL
-		    || get_property(p, "interrupt-map", NULL) != NULL) {
-			printk("oops, node %s doesn't have #interrupt-cells\n",
-			       p->full_name);
-			return 1;
-		}
-	}
-	printk("prom_n_intr_cells failed for %s\n", np->full_name);
-	return 1;
-}
-
-/*
- * Map an interrupt from a device up to the platform interrupt
- * descriptor.
- */
-static int __init
-map_interrupt(unsigned int **irq, struct device_node **ictrler,
-	      struct device_node *np, unsigned int *ints, int nintrc)
-{
-	struct device_node *p, *ipar;
-	unsigned int *imap, *imask, *ip;
-	int i, imaplen, match;
-	int newintrc = 1, newaddrc = 1;
-	unsigned int *reg;
-	int naddrc;
-
-	reg = (unsigned int *) get_property(np, "reg", NULL);
-	naddrc = prom_n_addr_cells(np);
-	p = intr_parent(np);
-	while (p != NULL) {
-		if (get_property(p, "interrupt-controller", NULL) != NULL)
-			/* this node is an interrupt controller, stop here */
-			break;
-		imap = (unsigned int *)
-			get_property(p, "interrupt-map", &imaplen);
-		if (imap == NULL) {
-			p = intr_parent(p);
-			continue;
-		}
-		imask = (unsigned int *)
-			get_property(p, "interrupt-map-mask", NULL);
-		if (imask == NULL) {
-			printk("oops, %s has interrupt-map but no mask\n",
-			       p->full_name);
-			return 0;
-		}
-		imaplen /= sizeof(unsigned int);
-		match = 0;
-		ipar = NULL;
-		while (imaplen > 0 && !match) {
-			/* check the child-interrupt field */
-			match = 1;
-			for (i = 0; i < naddrc && match; ++i)
-				match = ((reg[i] ^ imap[i]) & imask[i]) == 0;
-			for (; i < naddrc + nintrc && match; ++i)
-				match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0;
-			imap += naddrc + nintrc;
-			imaplen -= naddrc + nintrc;
-			/* grab the interrupt parent */
-			ipar = find_phandle((phandle) *imap++);
-			--imaplen;
-			if (ipar == NULL && num_interrupt_controllers == 1)
-				/* cope with BootX not giving us phandles */
-				ipar = dflt_interrupt_controller;
-			if (ipar == NULL) {
-				printk("oops, no int parent %x in map of %s\n",
-				       imap[-1], p->full_name);
-				return 0;
-			}
-			/* find the parent's # addr and intr cells */
-			ip = (unsigned int *)
-				get_property(ipar, "#interrupt-cells", NULL);
-			if (ip == NULL) {
-				printk("oops, no #interrupt-cells on %s\n",
-				       ipar->full_name);
-				return 0;
-			}
-			newintrc = *ip;
-			ip = (unsigned int *)
-				get_property(ipar, "#address-cells", NULL);
-			newaddrc = (ip == NULL)? 0: *ip;
-			imap += newaddrc + newintrc;
-			imaplen -= newaddrc + newintrc;
-		}
-		if (imaplen < 0) {
-			printk("oops, error decoding int-map on %s, len=%d\n",
-			       p->full_name, imaplen);
-			return 0;
-		}
-		if (!match) {
-			printk("oops, no match in %s int-map for %s\n",
-			       p->full_name, np->full_name);
-			return 0;
-		}
-		p = ipar;
-		naddrc = newaddrc;
-		nintrc = newintrc;
-		ints = imap - nintrc;
-		reg = ints - naddrc;
-	}
-	if (p == NULL)
-		printk("hmmm, int tree for %s doesn't have ctrler\n",
-		       np->full_name);
-	*irq = ints;
-	*ictrler = p;
-	return nintrc;
-}
-
-/*
- * New version of finish_node_interrupts.
- */
-static unsigned long __init
-finish_node_interrupts(struct device_node *np, unsigned long mem_start)
-{
-	unsigned int *ints;
-	int intlen, intrcells;
-	int i, j, n, offset;
-	unsigned int *irq;
-	struct device_node *ic;
-
-	ints = (unsigned int *) get_property(np, "interrupts", &intlen);
-	if (ints == NULL)
-		return mem_start;
-	intrcells = prom_n_intr_cells(np);
-	intlen /= intrcells * sizeof(unsigned int);
-	np->n_intrs = intlen;
-	np->intrs = (struct interrupt_info *) mem_start;
-	mem_start += intlen * sizeof(struct interrupt_info);
-
-	for (i = 0; i < intlen; ++i) {
-		np->intrs[i].line = 0;
-		np->intrs[i].sense = 1;
-		n = map_interrupt(&irq, &ic, np, ints, intrcells);
-		if (n <= 0)
-			continue;
-		offset = 0;
-		/*
-		 * On a CHRP we have an 8259 which is subordinate to
-		 * the openpic in the interrupt tree, but we want the
-		 * openpic's interrupt numbers offsetted, not the 8259's.
-		 * So we apply the offset if the controller is at the
-		 * root of the interrupt tree, i.e. has no interrupt-parent.
-		 * This doesn't cope with the general case of multiple
-		 * cascaded interrupt controllers, but then neither will
-		 * irq.c at the moment either.  -- paulus
-		 * The G5 triggers that code, I add a machine test. On
-		 * those machines, we want to offset interrupts from the
-		 * second openpic by 128 -- BenH
-		 */
-		if (num_interrupt_controllers > 1
-		    && ic != NULL
-		    && get_property(ic, "interrupt-parent", NULL) == NULL)
-			offset = 16;
-
-		np->intrs[i].line = irq[0] + offset;
-		if (n > 1)
-			np->intrs[i].sense = irq[1];
-		if (n > 2) {
-			printk("hmmm, got %d intr cells for %s:", n,
-			       np->full_name);
-			for (j = 0; j < n; ++j)
-				printk(" %d", irq[j]);
-			printk("\n");
-		}
-		ints += intrcells;
-	}
-
-	return mem_start;
-}
-
-/*
- * When BootX makes a copy of the device tree from the MacOS
- * Name Registry, it is in the format we use but all of the pointers
- * are offsets from the start of the tree.
- * This procedure updates the pointers.
- */
-void __init
-relocate_nodes(void)
-{
-	unsigned long base;
-	struct device_node *np;
-	struct property *pp;
-
-#define ADDBASE(x)	(x = (typeof (x))((x)? ((unsigned long)(x) + base): 0))
-
-	base = (unsigned long) boot_infos + boot_infos->deviceTreeOffset;
-	allnodes = (struct device_node *)(base + 4);
-	for (np = allnodes; np != 0; np = np->allnext) {
-		ADDBASE(np->full_name);
-		ADDBASE(np->properties);
-		ADDBASE(np->parent);
-		ADDBASE(np->child);
-		ADDBASE(np->sibling);
-		ADDBASE(np->allnext);
-		for (pp = np->properties; pp != 0; pp = pp->next) {
-			ADDBASE(pp->name);
-			ADDBASE(pp->value);
-			ADDBASE(pp->next);
-		}
-	}
-}
-
-int
-prom_n_addr_cells(struct device_node* np)
-{
-	int* ip;
-	do {
-		if (np->parent)
-			np = np->parent;
-		ip = (int *) get_property(np, "#address-cells", NULL);
-		if (ip != NULL)
-			return *ip;
-	} while (np->parent);
-	/* No #address-cells property for the root node, default to 1 */
-	return 1;
-}
-
-int
-prom_n_size_cells(struct device_node* np)
-{
-	int* ip;
-	do {
-		if (np->parent)
-			np = np->parent;
-		ip = (int *) get_property(np, "#size-cells", NULL);
-		if (ip != NULL)
-			return *ip;
-	} while (np->parent);
-	/* No #size-cells property for the root node, default to 1 */
-	return 1;
-}
-
-static unsigned long __init
-map_addr(struct device_node *np, unsigned long space, unsigned long addr)
-{
-	int na;
-	unsigned int *ranges;
-	int rlen = 0;
-	unsigned int type;
-
-	type = (space >> 24) & 3;
-	if (type == 0)
-		return addr;
-
-	while ((np = np->parent) != NULL) {
-		if (strcmp(np->type, "pci") != 0)
-			continue;
-		/* PCI bridge: map the address through the ranges property */
-		na = prom_n_addr_cells(np);
-		ranges = (unsigned int *) get_property(np, "ranges", &rlen);
-		while ((rlen -= (na + 5) * sizeof(unsigned int)) >= 0) {
-			if (((ranges[0] >> 24) & 3) == type
-			    && ranges[2] <= addr
-			    && addr - ranges[2] < ranges[na+4]) {
-				/* ok, this matches, translate it */
-				addr += ranges[na+2] - ranges[2];
-				break;
-			}
-			ranges += na + 5;
-		}
-	}
-	return addr;
-}
-
-static unsigned long __init
-interpret_pci_props(struct device_node *np, unsigned long mem_start,
-		    int naddrc, int nsizec)
-{
-	struct address_range *adr;
-	struct pci_reg_property *pci_addrs;
-	int i, l, *ip;
-
-	pci_addrs = (struct pci_reg_property *)
-		get_property(np, "assigned-addresses", &l);
-	if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) {
-		i = 0;
-		adr = (struct address_range *) mem_start;
-		while ((l -= sizeof(struct pci_reg_property)) >= 0) {
-			adr[i].space = pci_addrs[i].addr.a_hi;
-			adr[i].address = map_addr(np, pci_addrs[i].addr.a_hi,
-						  pci_addrs[i].addr.a_lo);
-			adr[i].size = pci_addrs[i].size_lo;
-			++i;
-		}
-		np->addrs = adr;
-		np->n_addrs = i;
-		mem_start += i * sizeof(struct address_range);
-	}
-
-	if (use_of_interrupt_tree)
-		return mem_start;
-
-	ip = (int *) get_property(np, "AAPL,interrupts", &l);
-	if (ip == 0 && np->parent)
-		ip = (int *) get_property(np->parent, "AAPL,interrupts", &l);
-	if (ip == 0)
-		ip = (int *) get_property(np, "interrupts", &l);
-	if (ip != 0) {
-		np->intrs = (struct interrupt_info *) mem_start;
-		np->n_intrs = l / sizeof(int);
-		mem_start += np->n_intrs * sizeof(struct interrupt_info);
-		for (i = 0; i < np->n_intrs; ++i) {
-			np->intrs[i].line = *ip++;
-			np->intrs[i].sense = 1;
-		}
-	}
-
-	return mem_start;
-}
-
-static unsigned long __init
-interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
-		      int naddrc, int nsizec)
-{
-	struct reg_property *rp;
-	struct address_range *adr;
-	unsigned long base_address;
-	int i, l, *ip;
-	struct device_node *db;
-
-	base_address = 0;
-	for (db = np->parent; db != NULL; db = db->parent) {
-		if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) {
-			base_address = db->addrs[0].address;
-			break;
-		}
-	}
-
-	rp = (struct reg_property *) get_property(np, "reg", &l);
-	if (rp != 0 && l >= sizeof(struct reg_property)) {
-		i = 0;
-		adr = (struct address_range *) mem_start;
-		while ((l -= sizeof(struct reg_property)) >= 0) {
-			adr[i].space = 2;
-			adr[i].address = rp[i].address + base_address;
-			adr[i].size = rp[i].size;
-			++i;
-		}
-		np->addrs = adr;
-		np->n_addrs = i;
-		mem_start += i * sizeof(struct address_range);
-	}
-
-	if (use_of_interrupt_tree)
-		return mem_start;
-
-	ip = (int *) get_property(np, "AAPL,interrupts", &l);
-	if (ip == 0)
-		ip = (int *) get_property(np, "interrupts", &l);
-	if (ip != 0) {
-		np->intrs = (struct interrupt_info *) mem_start;
-		np->n_intrs = l / sizeof(int);
-		mem_start += np->n_intrs * sizeof(struct interrupt_info);
-		for (i = 0; i < np->n_intrs; ++i) {
-			np->intrs[i].line = *ip++;
-			np->intrs[i].sense = 1;
-		}
-	}
-
-	return mem_start;
-}
-
-static unsigned long __init
-interpret_macio_props(struct device_node *np, unsigned long mem_start,
-		      int naddrc, int nsizec)
-{
-	struct reg_property *rp;
-	struct address_range *adr;
-	unsigned long base_address;
-	int i, l, *ip;
-	struct device_node *db;
-
-	base_address = 0;
-	for (db = np->parent; db != NULL; db = db->parent) {
-		if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) {
-			base_address = db->addrs[0].address;
-			break;
-		}
-	}
-
-	rp = (struct reg_property *) get_property(np, "reg", &l);
-	if (rp != 0 && l >= sizeof(struct reg_property)) {
-		i = 0;
-		adr = (struct address_range *) mem_start;
-		while ((l -= sizeof(struct reg_property)) >= 0) {
-			adr[i].space = 2;
-			adr[i].address = rp[i].address + base_address;
-			adr[i].size = rp[i].size;
-			++i;
-		}
-		np->addrs = adr;
-		np->n_addrs = i;
-		mem_start += i * sizeof(struct address_range);
-	}
-
-	if (use_of_interrupt_tree)
-		return mem_start;
-
-	ip = (int *) get_property(np, "interrupts", &l);
-	if (ip == 0)
-		ip = (int *) get_property(np, "AAPL,interrupts", &l);
-	if (ip != 0) {
-		np->intrs = (struct interrupt_info *) mem_start;
-		np->n_intrs = l / sizeof(int);
-		for (i = 0; i < np->n_intrs; ++i) {
-			np->intrs[i].line = *ip++;
-			np->intrs[i].sense = 1;
-		}
-		mem_start += np->n_intrs * sizeof(struct interrupt_info);
-	}
-
-	return mem_start;
-}
-
-static unsigned long __init
-interpret_isa_props(struct device_node *np, unsigned long mem_start,
-		    int naddrc, int nsizec)
-{
-	struct isa_reg_property *rp;
-	struct address_range *adr;
-	int i, l, *ip;
-
-	rp = (struct isa_reg_property *) get_property(np, "reg", &l);
-	if (rp != 0 && l >= sizeof(struct isa_reg_property)) {
-		i = 0;
-		adr = (struct address_range *) mem_start;
-		while ((l -= sizeof(struct reg_property)) >= 0) {
-			adr[i].space = rp[i].space;
-			adr[i].address = rp[i].address
-				+ (adr[i].space? 0: _ISA_MEM_BASE);
-			adr[i].size = rp[i].size;
-			++i;
-		}
-		np->addrs = adr;
-		np->n_addrs = i;
-		mem_start += i * sizeof(struct address_range);
-	}
-
-	if (use_of_interrupt_tree)
-		return mem_start;
-
-	ip = (int *) get_property(np, "interrupts", &l);
-	if (ip != 0) {
-		np->intrs = (struct interrupt_info *) mem_start;
-		np->n_intrs = l / (2 * sizeof(int));
-		mem_start += np->n_intrs * sizeof(struct interrupt_info);
-		for (i = 0; i < np->n_intrs; ++i) {
-			np->intrs[i].line = *ip++;
-			np->intrs[i].sense = *ip++;
-		}
-	}
-
-	return mem_start;
-}
-
-static unsigned long __init
-interpret_root_props(struct device_node *np, unsigned long mem_start,
-		     int naddrc, int nsizec)
-{
-	struct address_range *adr;
-	int i, l, *ip;
-	unsigned int *rp;
-	int rpsize = (naddrc + nsizec) * sizeof(unsigned int);
-
-	rp = (unsigned int *) get_property(np, "reg", &l);
-	if (rp != 0 && l >= rpsize) {
-		i = 0;
-		adr = (struct address_range *) mem_start;
-		while ((l -= rpsize) >= 0) {
-			adr[i].space = (naddrc >= 2? rp[naddrc-2]: 2);
-			adr[i].address = rp[naddrc - 1];
-			adr[i].size = rp[naddrc + nsizec - 1];
-			++i;
-			rp += naddrc + nsizec;
-		}
-		np->addrs = adr;
-		np->n_addrs = i;
-		mem_start += i * sizeof(struct address_range);
-	}
-
-	if (use_of_interrupt_tree)
-		return mem_start;
-
-	ip = (int *) get_property(np, "AAPL,interrupts", &l);
-	if (ip == 0)
-		ip = (int *) get_property(np, "interrupts", &l);
-	if (ip != 0) {
-		np->intrs = (struct interrupt_info *) mem_start;
-		np->n_intrs = l / sizeof(int);
-		mem_start += np->n_intrs * sizeof(struct interrupt_info);
-		for (i = 0; i < np->n_intrs; ++i) {
-			np->intrs[i].line = *ip++;
-			np->intrs[i].sense = 1;
-		}
-	}
-
-	return mem_start;
-}
-
-/*
- * Work out the sense (active-low level / active-high edge)
- * of each interrupt from the device tree.
- */
-void __init
-prom_get_irq_senses(unsigned char *senses, int off, int max)
-{
-	struct device_node *np;
-	int i, j;
-
-	/* default to level-triggered */
-	memset(senses, 1, max - off);
-	if (!use_of_interrupt_tree)
-		return;
-
-	for (np = allnodes; np != 0; np = np->allnext) {
-		for (j = 0; j < np->n_intrs; j++) {
-			i = np->intrs[j].line;
-			if (i >= off && i < max) {
-				if (np->intrs[j].sense == 1)
-					senses[i-off] = (IRQ_SENSE_LEVEL
-						| IRQ_POLARITY_NEGATIVE);
-				else
-					senses[i-off] = (IRQ_SENSE_EDGE
-						| IRQ_POLARITY_POSITIVE);
-			}
-		}
-	}
-}
-
-/*
- * Construct and return a list of the device_nodes with a given name.
- */
-struct device_node *
-find_devices(const char *name)
-{
-	struct device_node *head, **prevp, *np;
-
-	prevp = &head;
-	for (np = allnodes; np != 0; np = np->allnext) {
-		if (np->name != 0 && strcasecmp(np->name, name) == 0) {
-			*prevp = np;
-			prevp = &np->next;
-		}
-	}
-	*prevp = NULL;
-	return head;
-}
-
-/*
- * Construct and return a list of the device_nodes with a given type.
- */
-struct device_node *
-find_type_devices(const char *type)
-{
-	struct device_node *head, **prevp, *np;
-
-	prevp = &head;
-	for (np = allnodes; np != 0; np = np->allnext) {
-		if (np->type != 0 && strcasecmp(np->type, type) == 0) {
-			*prevp = np;
-			prevp = &np->next;
-		}
-	}
-	*prevp = NULL;
-	return head;
-}
-
-/*
- * Returns all nodes linked together
- */
-struct device_node *
-find_all_nodes(void)
-{
-	struct device_node *head, **prevp, *np;
-
-	prevp = &head;
-	for (np = allnodes; np != 0; np = np->allnext) {
-		*prevp = np;
-		prevp = &np->next;
-	}
-	*prevp = NULL;
-	return head;
-}
-
-/* Checks if the given "compat" string matches one of the strings in
- * the device's "compatible" property
- */
-int
-device_is_compatible(struct device_node *device, const char *compat)
-{
-	const char* cp;
-	int cplen, l;
-
-	cp = (char *) get_property(device, "compatible", &cplen);
-	if (cp == NULL)
-		return 0;
-	while (cplen > 0) {
-		if (strncasecmp(cp, compat, strlen(compat)) == 0)
-			return 1;
-		l = strlen(cp) + 1;
-		cp += l;
-		cplen -= l;
-	}
-
-	return 0;
-}
-
-
-/*
- * Indicates whether the root node has a given value in its
- * compatible property.
- */
-int
-machine_is_compatible(const char *compat)
-{
-	struct device_node *root;
-
-	root = find_path_device("/");
-	if (root == 0)
-		return 0;
-	return device_is_compatible(root, compat);
-}
-
-/*
- * Construct and return a list of the device_nodes with a given type
- * and compatible property.
- */
-struct device_node *
-find_compatible_devices(const char *type, const char *compat)
-{
-	struct device_node *head, **prevp, *np;
-
-	prevp = &head;
-	for (np = allnodes; np != 0; np = np->allnext) {
-		if (type != NULL
-		    && !(np->type != 0 && strcasecmp(np->type, type) == 0))
-			continue;
-		if (device_is_compatible(np, compat)) {
-			*prevp = np;
-			prevp = &np->next;
-		}
-	}
-	*prevp = NULL;
-	return head;
-}
-
-/*
- * Find the device_node with a given full_name.
- */
-struct device_node *
-find_path_device(const char *path)
-{
-	struct device_node *np;
-
-	for (np = allnodes; np != 0; np = np->allnext)
-		if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
-			return np;
-	return NULL;
-}
-
-/*******
- *
- * New implementation of the OF "find" APIs, return a refcounted
- * object, call of_node_put() when done. Currently, still lacks
- * locking as old implementation, this is beeing done for ppc64.
- *
- * Note that property management will need some locking as well,
- * this isn't dealt with yet
- *
- *******/
-
-/**
- *	of_find_node_by_name - Find a node by it's "name" property
- *	@from:	The node to start searching from or NULL, the node
- *		you pass will not be searched, only the next one
- *		will; typically, you pass what the previous call
- *		returned. of_node_put() will be called on it
- *	@name:	The name string to match against
- *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.
- */
-struct device_node *of_find_node_by_name(struct device_node *from,
-	const char *name)
-{
-	struct device_node *np = from ? from->allnext : allnodes;
-
-	for (; np != 0; np = np->allnext)
-		if (np->name != 0 && strcasecmp(np->name, name) == 0)
-			break;
-	if (from)
-		of_node_put(from);
-	return of_node_get(np);
-}
-
-/**
- *	of_find_node_by_type - Find a node by it's "device_type" property
- *	@from:	The node to start searching from or NULL, the node
- *		you pass will not be searched, only the next one
- *		will; typically, you pass what the previous call
- *		returned. of_node_put() will be called on it
- *	@name:	The type string to match against
- *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.
- */
-struct device_node *of_find_node_by_type(struct device_node *from,
-	const char *type)
-{
-	struct device_node *np = from ? from->allnext : allnodes;
-
-	for (; np != 0; np = np->allnext)
-		if (np->type != 0 && strcasecmp(np->type, type) == 0)
-			break;
-	if (from)
-		of_node_put(from);
-	return of_node_get(np);
-}
-
-/**
- *	of_find_compatible_node - Find a node based on type and one of the
- *                                tokens in it's "compatible" property
- *	@from:		The node to start searching from or NULL, the node
- *			you pass will not be searched, only the next one
- *			will; typically, you pass what the previous call
- *			returned. of_node_put() will be called on it
- *	@type:		The type string to match "device_type" or NULL to ignore
- *	@compatible:	The string to match to one of the tokens in the device
- *			"compatible" list.
- *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.
- */
-struct device_node *of_find_compatible_node(struct device_node *from,
-	const char *type, const char *compatible)
-{
-	struct device_node *np = from ? from->allnext : allnodes;
-
-	for (; np != 0; np = np->allnext) {
-		if (type != NULL
-		    && !(np->type != 0 && strcasecmp(np->type, type) == 0))
-			continue;
-		if (device_is_compatible(np, compatible))
-			break;
-	}
-	if (from)
-		of_node_put(from);
-	return of_node_get(np);
-}
-
-/**
- *	of_find_node_by_path - Find a node matching a full OF path
- *	@path:	The full path to match
- *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.
- */
-struct device_node *of_find_node_by_path(const char *path)
-{
-	struct device_node *np = allnodes;
-
-	for (; np != 0; np = np->allnext)
-		if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
-			break;
-	return of_node_get(np);
-}
-
-/**
- *	of_find_all_nodes - Get next node in global list
- *	@prev:	Previous node or NULL to start iteration
- *		of_node_put() will be called on it
- *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.
- */
-struct device_node *of_find_all_nodes(struct device_node *prev)
-{
-	return of_node_get(prev ? prev->allnext : allnodes);
-}
-
-/**
- *	of_get_parent - Get a node's parent if any
- *	@node:	Node to get parent
- *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.
- */
-struct device_node *of_get_parent(const struct device_node *node)
-{
-	return node ? of_node_get(node->parent) : NULL;
-}
-
-/**
- *	of_get_next_child - Iterate a node childs
- *	@node:	parent node
- *	@prev:	previous child of the parent node, or NULL to get first
- *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.
- */
-struct device_node *of_get_next_child(const struct device_node *node,
-				      struct device_node *prev)
-{
-	struct device_node *next = prev ? prev->sibling : node->child;
-
-	for (; next != 0; next = next->sibling)
-		if (of_node_get(next))
-			break;
-	if (prev)
-		of_node_put(prev);
-	return next;
-}
-
-/**
- *	of_node_get - Increment refcount of a node
- *	@node:	Node to inc refcount, NULL is supported to
- *		simplify writing of callers
- *
- *	Returns the node itself or NULL if gone. Current implementation
- *	does nothing as we don't yet do dynamic node allocation on ppc32
- */
-struct device_node *of_node_get(struct device_node *node)
-{
-	return node;
-}
-
-/**
- *	of_node_put - Decrement refcount of a node
- *	@node:	Node to dec refcount, NULL is supported to
- *		simplify writing of callers
- *
- *	Current implementation does nothing as we don't yet do dynamic node
- *	allocation on ppc32
- */
-void  of_node_put(struct device_node *node)
-{
-}
-
-/*
- * Find the device_node with a given phandle.
- */
-static struct device_node * __init
-find_phandle(phandle ph)
-{
-	struct device_node *np;
-
-	for (np = allnodes; np != 0; np = np->allnext)
-		if (np->node == ph)
-			return np;
-	return NULL;
-}
-
-/*
- * Find a property with a given name for a given node
- * and return the value.
- */
-unsigned char *
-get_property(struct device_node *np, const char *name, int *lenp)
-{
-	struct property *pp;
-
-	for (pp = np->properties; pp != 0; pp = pp->next)
-		if (pp->name != NULL && strcmp(pp->name, name) == 0) {
-			if (lenp != 0)
-				*lenp = pp->length;
-			return pp->value;
-		}
-	return NULL;
-}
-
-/*
- * Add a property to a node
- */
-int
-prom_add_property(struct device_node* np, struct property* prop)
-{
-	struct property **next = &np->properties;
-
-	prop->next = NULL;
-	while (*next)
-		next = &(*next)->next;
-	*next = prop;
-
-	return 0;
-}
-
-/* I quickly hacked that one, check against spec ! */
-static inline unsigned long
-bus_space_to_resource_flags(unsigned int bus_space)
-{
-	u8 space = (bus_space >> 24) & 0xf;
-	if (space == 0)
-		space = 0x02;
-	if (space == 0x02)
-		return IORESOURCE_MEM;
-	else if (space == 0x01)
-		return IORESOURCE_IO;
-	else {
-		printk(KERN_WARNING "prom.c: bus_space_to_resource_flags(), space: %x\n",
-		    	bus_space);
-		return 0;
-	}
-}
-
-static struct resource*
-find_parent_pci_resource(struct pci_dev* pdev, struct address_range *range)
-{
-	unsigned long mask;
-	int i;
-
-	/* Check this one */
-	mask = bus_space_to_resource_flags(range->space);
-	for (i=0; i<DEVICE_COUNT_RESOURCE; i++) {
-		if ((pdev->resource[i].flags & mask) == mask &&
-			pdev->resource[i].start <= range->address &&
-			pdev->resource[i].end > range->address) {
-				if ((range->address + range->size - 1) > pdev->resource[i].end) {
-					/* Add better message */
-					printk(KERN_WARNING "PCI/OF resource overlap !\n");
-					return NULL;
-				}
-				break;
-			}
-	}
-	if (i == DEVICE_COUNT_RESOURCE)
-		return NULL;
-	return &pdev->resource[i];
-}
-
-/*
- * Request an OF device resource. Currently handles child of PCI devices,
- * or other nodes attached to the root node. Ultimately, put some
- * link to resources in the OF node.
- */
-struct resource*
-request_OF_resource(struct device_node* node, int index, const char* name_postfix)
-{
-	struct pci_dev* pcidev;
-	u8 pci_bus, pci_devfn;
-	unsigned long iomask;
-	struct device_node* nd;
-	struct resource* parent;
-	struct resource *res = NULL;
-	int nlen, plen;
-
-	if (index >= node->n_addrs)
-		goto fail;
-
-	/* Sanity check on bus space */
-	iomask = bus_space_to_resource_flags(node->addrs[index].space);
-	if (iomask & IORESOURCE_MEM)
-		parent = &iomem_resource;
-	else if (iomask & IORESOURCE_IO)
-		parent = &ioport_resource;
-	else
-		goto fail;
-
-	/* Find a PCI parent if any */
-	nd = node;
-	pcidev = NULL;
-	while(nd) {
-		if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
-			pcidev = pci_find_slot(pci_bus, pci_devfn);
-		if (pcidev) break;
-		nd = nd->parent;
-	}
-	if (pcidev)
-		parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
-	if (!parent) {
-		printk(KERN_WARNING "request_OF_resource(%s), parent not found\n",
-			node->name);
-		goto fail;
-	}
-
-	res = __request_region(parent, node->addrs[index].address, node->addrs[index].size, NULL);
-	if (!res)
-		goto fail;
-	nlen = strlen(node->name);
-	plen = name_postfix ? strlen(name_postfix) : 0;
-	res->name = (const char *)kmalloc(nlen+plen+1, GFP_KERNEL);
-	if (res->name) {
-		strcpy((char *)res->name, node->name);
-		if (plen)
-			strcpy((char *)res->name+nlen, name_postfix);
-	}
-	return res;
-fail:
-	return NULL;
-}
-
-int
-release_OF_resource(struct device_node* node, int index)
-{
-	struct pci_dev* pcidev;
-	u8 pci_bus, pci_devfn;
-	unsigned long iomask, start, end;
-	struct device_node* nd;
-	struct resource* parent;
-	struct resource *res = NULL;
-
-	if (index >= node->n_addrs)
-		return -EINVAL;
-
-	/* Sanity check on bus space */
-	iomask = bus_space_to_resource_flags(node->addrs[index].space);
-	if (iomask & IORESOURCE_MEM)
-		parent = &iomem_resource;
-	else if (iomask & IORESOURCE_IO)
-		parent = &ioport_resource;
-	else
-		return -EINVAL;
-
-	/* Find a PCI parent if any */
-	nd = node;
-	pcidev = NULL;
-	while(nd) {
-		if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
-			pcidev = pci_find_slot(pci_bus, pci_devfn);
-		if (pcidev) break;
-		nd = nd->parent;
-	}
-	if (pcidev)
-		parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
-	if (!parent) {
-		printk(KERN_WARNING "release_OF_resource(%s), parent not found\n",
-			node->name);
-		return -ENODEV;
-	}
-
-	/* Find us in the parent and its childs */
-	res = parent->child;
-	start = node->addrs[index].address;
-	end = start + node->addrs[index].size - 1;
-	while (res) {
-		if (res->start == start && res->end == end &&
-		    (res->flags & IORESOURCE_BUSY))
-		    	break;
-		if (res->start <= start && res->end >= end)
-			res = res->child;
-		else
-			res = res->sibling;
-	}
-	if (!res)
-		return -ENODEV;
-
-	kfree(res->name);
-	res->name = NULL;
-	release_resource(res);
-	kfree(res);
-
-	return 0;
-}
-
-#if 0
-void
-print_properties(struct device_node *np)
-{
-	struct property *pp;
-	char *cp;
-	int i, n;
-
-	for (pp = np->properties; pp != 0; pp = pp->next) {
-		printk(KERN_INFO "%s", pp->name);
-		for (i = strlen(pp->name); i < 16; ++i)
-			printk(" ");
-		cp = (char *) pp->value;
-		for (i = pp->length; i > 0; --i, ++cp)
-			if ((i > 1 && (*cp < 0x20 || *cp > 0x7e))
-			    || (i == 1 && *cp != 0))
-				break;
-		if (i == 0 && pp->length > 1) {
-			/* looks like a string */
-			printk(" %s\n", (char *) pp->value);
-		} else {
-			/* dump it in hex */
-			n = pp->length;
-			if (n > 64)
-				n = 64;
-			if (pp->length % 4 == 0) {
-				unsigned int *p = (unsigned int *) pp->value;
-
-				n /= 4;
-				for (i = 0; i < n; ++i) {
-					if (i != 0 && (i % 4) == 0)
-						printk("\n                ");
-					printk(" %08x", *p++);
-				}
-			} else {
-				unsigned char *bp = pp->value;
-
-				for (i = 0; i < n; ++i) {
-					if (i != 0 && (i % 16) == 0)
-						printk("\n                ");
-					printk(" %02x", *bp++);
-				}
-			}
-			printk("\n");
-			if (pp->length > 64)
-				printk("                 ... (length = %d)\n",
-				       pp->length);
-		}
-	}
-}
-#endif
-
-static DEFINE_SPINLOCK(rtas_lock);
-
-/* this can be called after setup -- Cort */
-int
-call_rtas(const char *service, int nargs, int nret,
-	  unsigned long *outputs, ...)
-{
-	va_list list;
-	int i;
-	unsigned long s;
-	struct device_node *rtas;
-	int *tokp;
-	union {
-		unsigned long words[16];
-		double align;
-	} u;
-
-	rtas = find_devices("rtas");
-	if (rtas == NULL)
-		return -1;
-	tokp = (int *) get_property(rtas, service, NULL);
-	if (tokp == NULL) {
-		printk(KERN_ERR "No RTAS service called %s\n", service);
-		return -1;
-	}
-	u.words[0] = *tokp;
-	u.words[1] = nargs;
-	u.words[2] = nret;
-	va_start(list, outputs);
-	for (i = 0; i < nargs; ++i)
-		u.words[i+3] = va_arg(list, unsigned long);
-	va_end(list);
-
-	/*
-	 * RTAS doesn't use floating point.
-	 * Or at least, according to the CHRP spec we enter RTAS
-	 * with FP disabled, and it doesn't change the FP registers.
-	 *  -- paulus.
-	 */
-	spin_lock_irqsave(&rtas_lock, s);
-	enter_rtas((void *)__pa(&u));
-	spin_unlock_irqrestore(&rtas_lock, s);
-
-	if (nret > 1 && outputs != NULL)
-		for (i = 0; i < nret-1; ++i)
-			outputs[i] = u.words[i+nargs+4];
-	return u.words[nargs+3];
-}
diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c
deleted file mode 100644
index df14422..0000000
--- a/arch/ppc/syslib/prom_init.c
+++ /dev/null
@@ -1,1011 +0,0 @@
-/*
- * Note that prom_init() and anything called from prom_init()
- * may be running at an address that is different from the address
- * that it was linked at.  References to static data items are
- * handled by compiling this file with -mrelocatable-lib.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/threads.h>
-#include <linux/spinlock.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-
-#include <asm/sections.h>
-#include <asm/prom.h>
-#include <asm/page.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/bootx.h>
-#include <asm/system.h>
-#include <asm/mmu.h>
-#include <asm/pgtable.h>
-#include <asm/bootinfo.h>
-#include <asm/btext.h>
-#include <asm/pci-bridge.h>
-#include <asm/open_pic.h>
-#include <asm/cacheflush.h>
-
-#ifdef CONFIG_LOGO_LINUX_CLUT224
-#include <linux/linux_logo.h>
-extern const struct linux_logo logo_linux_clut224;
-#endif
-
-/*
- * Properties whose value is longer than this get excluded from our
- * copy of the device tree.  This way we don't waste space storing
- * things like "driver,AAPL,MacOS,PowerPC" properties.  But this value
- * does need to be big enough to ensure that we don't lose things
- * like the interrupt-map property on a PCI-PCI bridge.
- */
-#define MAX_PROPERTY_LENGTH	4096
-
-#ifndef FB_MAX			/* avoid pulling in all of the fb stuff */
-#define FB_MAX	8
-#endif
-
-#define ALIGNUL(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
-
-typedef u32 prom_arg_t;
-
-struct prom_args {
-	const char *service;
-	int nargs;
-	int nret;
-	prom_arg_t args[10];
-};
-
-struct pci_address {
-	unsigned a_hi;
-	unsigned a_mid;
-	unsigned a_lo;
-};
-
-struct pci_reg_property {
-	struct pci_address addr;
-	unsigned size_hi;
-	unsigned size_lo;
-};
-
-struct pci_range {
-	struct pci_address addr;
-	unsigned phys;
-	unsigned size_hi;
-	unsigned size_lo;
-};
-
-struct isa_reg_property {
-	unsigned space;
-	unsigned address;
-	unsigned size;
-};
-
-struct pci_intr_map {
-	struct pci_address addr;
-	unsigned dunno;
-	phandle int_ctrler;
-	unsigned intr;
-};
-
-static void prom_exit(void);
-static int  call_prom(const char *service, int nargs, int nret, ...);
-static int  call_prom_ret(const char *service, int nargs, int nret,
-			  prom_arg_t *rets, ...);
-static void prom_print_hex(unsigned int v);
-static int  prom_set_color(ihandle ih, int i, int r, int g, int b);
-static int  prom_next_node(phandle *nodep);
-static unsigned long check_display(unsigned long mem);
-static void setup_disp_fake_bi(ihandle dp);
-static unsigned long copy_device_tree(unsigned long mem_start,
-				unsigned long mem_end);
-static unsigned long inspect_node(phandle node, struct device_node *dad,
-				unsigned long mem_start, unsigned long mem_end,
-				struct device_node ***allnextpp);
-static void prom_hold_cpus(unsigned long mem);
-static void prom_instantiate_rtas(void);
-static void * early_get_property(unsigned long base, unsigned long node,
-				char *prop);
-
-prom_entry prom __initdata;
-ihandle prom_chosen __initdata;
-ihandle prom_stdout __initdata;
-
-static char *prom_display_paths[FB_MAX] __initdata;
-static phandle prom_display_nodes[FB_MAX] __initdata;
-static unsigned int prom_num_displays __initdata;
-static ihandle prom_disp_node __initdata;
-char *of_stdout_device __initdata;
-
-unsigned int rtas_data;   /* physical pointer */
-unsigned int rtas_entry;  /* physical pointer */
-unsigned int rtas_size;
-unsigned int old_rtas;
-
-boot_infos_t *boot_infos;
-char *bootpath;
-char *bootdevice;
-struct device_node *allnodes;
-
-extern char *klimit;
-
-static void __init
-prom_exit(void)
-{
-	struct prom_args args;
-
-	args.service = "exit";
-	args.nargs = 0;
-	args.nret = 0;
-	prom(&args);
-	for (;;)			/* should never get here */
-		;
-}
-
-static int __init
-call_prom(const char *service, int nargs, int nret, ...)
-{
-	va_list list;
-	int i;
-	struct prom_args prom_args;
-
-	prom_args.service = service;
-	prom_args.nargs = nargs;
-	prom_args.nret = nret;
-	va_start(list, nret);
-	for (i = 0; i < nargs; ++i)
-		prom_args.args[i] = va_arg(list, prom_arg_t);
-	va_end(list);
-	for (i = 0; i < nret; ++i)
-		prom_args.args[i + nargs] = 0;
-	prom(&prom_args);
-	return prom_args.args[nargs];
-}
-
-static int __init
-call_prom_ret(const char *service, int nargs, int nret, prom_arg_t *rets, ...)
-{
-	va_list list;
-	int i;
-	struct prom_args prom_args;
-
-	prom_args.service = service;
-	prom_args.nargs = nargs;
-	prom_args.nret = nret;
-	va_start(list, rets);
-	for (i = 0; i < nargs; ++i)
-		prom_args.args[i] = va_arg(list, int);
-	va_end(list);
-	for (i = 0; i < nret; ++i)
-		prom_args.args[i + nargs] = 0;
-	prom(&prom_args);
-	for (i = 1; i < nret; ++i)
-		rets[i-1] = prom_args.args[nargs + i];
-	return prom_args.args[nargs];
-}
-
-void __init
-prom_print(const char *msg)
-{
-	const char *p, *q;
-
-	if (prom_stdout == 0)
-		return;
-
-	for (p = msg; *p != 0; p = q) {
-		for (q = p; *q != 0 && *q != '\n'; ++q)
-			;
-		if (q > p)
-			call_prom("write", 3, 1, prom_stdout, p, q - p);
-		if (*q != 0) {
-			++q;
-			call_prom("write", 3, 1, prom_stdout, "\r\n", 2);
-		}
-	}
-}
-
-static void __init
-prom_print_hex(unsigned int v)
-{
-	char buf[16];
-	int i, c;
-
-	for (i = 0; i < 8; ++i) {
-		c = (v >> ((7-i)*4)) & 0xf;
-		c += (c >= 10)? ('a' - 10): '0';
-		buf[i] = c;
-	}
-	buf[i] = ' ';
-	buf[i+1] = 0;
-	prom_print(buf);
-}
-
-static int __init
-prom_set_color(ihandle ih, int i, int r, int g, int b)
-{
-	return call_prom("call-method", 6, 1, "color!", ih, i, b, g, r);
-}
-
-static int __init
-prom_next_node(phandle *nodep)
-{
-	phandle node;
-
-	if ((node = *nodep) != 0
-	    && (*nodep = call_prom("child", 1, 1, node)) != 0)
-		return 1;
-	if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
-		return 1;
-	for (;;) {
-		if ((node = call_prom("parent", 1, 1, node)) == 0)
-			return 0;
-		if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
-			return 1;
-	}
-}
-
-#ifdef CONFIG_POWER4
-/*
- * Set up a hash table with a set of entries in it to map the
- * first 64MB of RAM.  This is used on 64-bit machines since
- * some of them don't have BATs.
- */
-
-static inline void make_pte(unsigned long htab, unsigned int hsize,
-			    unsigned int va, unsigned int pa, int mode)
-{
-	unsigned int *pteg;
-	unsigned int hash, i, vsid;
-
-	vsid = ((va >> 28) * 0x111) << 12;
-	hash = ((va ^ vsid) >> 5) & 0x7fff80;
-	pteg = (unsigned int *)(htab + (hash & (hsize - 1)));
-	for (i = 0; i < 8; ++i, pteg += 4) {
-		if ((pteg[1] & 1) == 0) {
-			pteg[1] = vsid | ((va >> 16) & 0xf80) | 1;
-			pteg[3] = pa | mode;
-			break;
-		}
-	}
-}
-
-extern unsigned long _SDR1;
-extern PTE *Hash;
-extern unsigned long Hash_size;
-
-static void __init
-prom_alloc_htab(void)
-{
-	unsigned int hsize;
-	unsigned long htab;
-	unsigned int addr;
-
-	/*
-	 * Because of OF bugs we can't use the "claim" client
-	 * interface to allocate memory for the hash table.
-	 * This code is only used on 64-bit PPCs, and the only
-	 * 64-bit PPCs at the moment are RS/6000s, and their
-	 * OF is based at 0xc00000 (the 12M point), so we just
-	 * arbitrarily use the 0x800000 - 0xc00000 region for the
-	 * hash table.
-	 *  -- paulus.
-	 */
-	hsize = 4 << 20;	/* POWER4 has no BATs */
-	htab = (8 << 20);
-	call_prom("claim", 3, 1, htab, hsize, 0);
-	Hash = (void *)(htab + KERNELBASE);
-	Hash_size = hsize;
-	_SDR1 = htab + __ilog2(hsize) - 18;
-
-	/*
-	 * Put in PTEs for the first 64MB of RAM
-	 */
-	memset((void *)htab, 0, hsize);
-	for (addr = 0; addr < 0x4000000; addr += 0x1000)
-		make_pte(htab, hsize, addr + KERNELBASE, addr,
-			 _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX);
-#if 0 /* DEBUG stuff mapping the SCC */
-	make_pte(htab, hsize, 0x80013000, 0x80013000,
-		 _PAGE_ACCESSED | _PAGE_NO_CACHE | _PAGE_GUARDED | PP_RWXX);
-#endif
-}
-#endif /* CONFIG_POWER4 */
-
-
-/*
- * If we have a display that we don't know how to drive,
- * we will want to try to execute OF's open method for it
- * later.  However, OF will probably fall over if we do that
- * we've taken over the MMU.
- * So we check whether we will need to open the display,
- * and if so, open it now.
- */
-static unsigned long __init
-check_display(unsigned long mem)
-{
-	phandle node;
-	ihandle ih;
-	int i, j;
-	char type[16], *path;
-	static unsigned char default_colors[] = {
-		0x00, 0x00, 0x00,
-		0x00, 0x00, 0xaa,
-		0x00, 0xaa, 0x00,
-		0x00, 0xaa, 0xaa,
-		0xaa, 0x00, 0x00,
-		0xaa, 0x00, 0xaa,
-		0xaa, 0xaa, 0x00,
-		0xaa, 0xaa, 0xaa,
-		0x55, 0x55, 0x55,
-		0x55, 0x55, 0xff,
-		0x55, 0xff, 0x55,
-		0x55, 0xff, 0xff,
-		0xff, 0x55, 0x55,
-		0xff, 0x55, 0xff,
-		0xff, 0xff, 0x55,
-		0xff, 0xff, 0xff
-	};
-	const unsigned char *clut;
-
-	prom_disp_node = 0;
-
-	for (node = 0; prom_next_node(&node); ) {
-		type[0] = 0;
-		call_prom("getprop", 4, 1, node, "device_type",
-			  type, sizeof(type));
-		if (strcmp(type, "display") != 0)
-			continue;
-		/* It seems OF doesn't null-terminate the path :-( */
-		path = (char *) mem;
-		memset(path, 0, 256);
-		if (call_prom("package-to-path", 3, 1, node, path, 255) < 0)
-			continue;
-
-		/*
-		 * If this display is the device that OF is using for stdout,
-		 * move it to the front of the list.
-		 */
-		mem += strlen(path) + 1;
-		i = prom_num_displays++;
-		if (of_stdout_device != 0 && i > 0
-		    && strcmp(of_stdout_device, path) == 0) {
-			for (; i > 0; --i) {
-				prom_display_paths[i]
-					= prom_display_paths[i-1];
-				prom_display_nodes[i]
-					= prom_display_nodes[i-1];
-			}
-		}
-		prom_display_paths[i] = path;
-		prom_display_nodes[i] = node;
-		if (i == 0)
-			prom_disp_node = node;
-		if (prom_num_displays >= FB_MAX)
-			break;
-	}
-
-	for (j=0; j<prom_num_displays; j++) {
-		path = prom_display_paths[j];
-		node = prom_display_nodes[j];
-		prom_print("opening display ");
-		prom_print(path);
-		ih = call_prom("open", 1, 1, path);
-		if (ih == 0 || ih == (ihandle) -1) {
-			prom_print("... failed\n");
-			for (i=j+1; i<prom_num_displays; i++) {
-				prom_display_paths[i-1] = prom_display_paths[i];
-				prom_display_nodes[i-1] = prom_display_nodes[i];
-			}
-			if (--prom_num_displays > 0) {
-				prom_disp_node = prom_display_nodes[j];
-				j--;
-			} else
-				prom_disp_node = 0;
-			continue;
-		} else {
-			prom_print("... ok\n");
-			call_prom("setprop", 4, 1, node, "linux,opened", 0, 0);
-
-			/*
-			 * Setup a usable color table when the appropriate
-			 * method is available.
-			 * Should update this to use set-colors.
-			 */
-			clut = default_colors;
-			for (i = 0; i < 32; i++, clut += 3)
-				if (prom_set_color(ih, i, clut[0], clut[1],
-						   clut[2]) != 0)
-					break;
-
-#ifdef CONFIG_LOGO_LINUX_CLUT224
-			clut = PTRRELOC(logo_linux_clut224.clut);
-			for (i = 0; i < logo_linux_clut224.clutsize;
-			     i++, clut += 3)
-				if (prom_set_color(ih, i + 32, clut[0],
-						   clut[1], clut[2]) != 0)
-					break;
-#endif /* CONFIG_LOGO_LINUX_CLUT224 */
-		}
-	}
-	
-	if (prom_stdout) {
-		phandle p;
-		p = call_prom("instance-to-package", 1, 1, prom_stdout);
-		if (p && p != -1) {
-			type[0] = 0;
-			call_prom("getprop", 4, 1, p, "device_type",
-				  type, sizeof(type));
-			if (strcmp(type, "display") == 0)
-				call_prom("setprop", 4, 1, p, "linux,boot-display",
-					  0, 0);
-		}
-	}
-
-	return ALIGNUL(mem);
-}
-
-/* This function will enable the early boot text when doing OF booting. This
- * way, xmon output should work too
- */
-static void __init
-setup_disp_fake_bi(ihandle dp)
-{
-#ifdef CONFIG_BOOTX_TEXT
-	int width = 640, height = 480, depth = 8, pitch;
-	unsigned address;
-	struct pci_reg_property addrs[8];
-	int i, naddrs;
-	char name[32];
-	char *getprop = "getprop";
-
-	prom_print("Initializing fake screen: ");
-
-	memset(name, 0, sizeof(name));
-	call_prom(getprop, 4, 1, dp, "name", name, sizeof(name));
-	name[sizeof(name)-1] = 0;
-	prom_print(name);
-	prom_print("\n");
-	call_prom(getprop, 4, 1, dp, "width", &width, sizeof(width));
-	call_prom(getprop, 4, 1, dp, "height", &height, sizeof(height));
-	call_prom(getprop, 4, 1, dp, "depth", &depth, sizeof(depth));
-	pitch = width * ((depth + 7) / 8);
-	call_prom(getprop, 4, 1, dp, "linebytes",
-		  &pitch, sizeof(pitch));
-	if (pitch == 1)
-		pitch = 0x1000;		/* for strange IBM display */
-	address = 0;
-	call_prom(getprop, 4, 1, dp, "address",
-		  &address, sizeof(address));
-	if (address == 0) {
-		/* look for an assigned address with a size of >= 1MB */
-		naddrs = call_prom(getprop, 4, 1, dp, "assigned-addresses",
-				   addrs, sizeof(addrs));
-		naddrs /= sizeof(struct pci_reg_property);
-		for (i = 0; i < naddrs; ++i) {
-			if (addrs[i].size_lo >= (1 << 20)) {
-				address = addrs[i].addr.a_lo;
-				/* use the BE aperture if possible */
-				if (addrs[i].size_lo >= (16 << 20))
-					address += (8 << 20);
-				break;
-			}
-		}
-		if (address == 0) {
-			prom_print("Failed to get address\n");
-			return;
-		}
-	}
-	/* kludge for valkyrie */
-	if (strcmp(name, "valkyrie") == 0)
-		address += 0x1000;
-
-#ifdef CONFIG_POWER4
-#if CONFIG_TASK_SIZE > 0x80000000
-#error CONFIG_TASK_SIZE cannot be above 0x80000000 with BOOTX_TEXT on G5
-#endif
-	{
-		extern boot_infos_t disp_bi;
-		unsigned long va, pa, i, offset;
-       		va = 0x90000000;
-		pa = address & 0xfffff000ul;
-		offset = address & 0x00000fff;
-
-		for (i=0; i<0x4000; i++) {  
-			make_pte((unsigned long)Hash - KERNELBASE, Hash_size, va, pa, 
-				 _PAGE_ACCESSED | _PAGE_NO_CACHE |
-				 _PAGE_GUARDED | PP_RWXX);
-			va += 0x1000;
-			pa += 0x1000;
-		}
-		btext_setup_display(width, height, depth, pitch, 0x90000000 | offset);
-		disp_bi.dispDeviceBase = (u8 *)address;
-	}
-#else /* CONFIG_POWER4 */
-	btext_setup_display(width, height, depth, pitch, address);
-	btext_prepare_BAT();
-#endif /* CONFIG_POWER4 */
-#endif /* CONFIG_BOOTX_TEXT */
-}
-
-/*
- * Make a copy of the device tree from the PROM.
- */
-static unsigned long __init
-copy_device_tree(unsigned long mem_start, unsigned long mem_end)
-{
-	phandle root;
-	unsigned long new_start;
-	struct device_node **allnextp;
-
-	root = call_prom("peer", 1, 1, (phandle)0);
-	if (root == (phandle)0) {
-		prom_print("couldn't get device tree root\n");
-		prom_exit();
-	}
-	allnextp = &allnodes;
-	mem_start = ALIGNUL(mem_start);
-	new_start = inspect_node(root, NULL, mem_start, mem_end, &allnextp);
-	*allnextp = NULL;
-	return new_start;
-}
-
-static unsigned long __init
-inspect_node(phandle node, struct device_node *dad,
-	     unsigned long mem_start, unsigned long mem_end,
-	     struct device_node ***allnextpp)
-{
-	int l;
-	phandle child;
-	struct device_node *np;
-	struct property *pp, **prev_propp;
-	char *prev_name, *namep;
-	unsigned char *valp;
-
-	np = (struct device_node *) mem_start;
-	mem_start += sizeof(struct device_node);
-	memset(np, 0, sizeof(*np));
-	np->node = node;
-	**allnextpp = PTRUNRELOC(np);
-	*allnextpp = &np->allnext;
-	if (dad != 0) {
-		np->parent = PTRUNRELOC(dad);
-		/* we temporarily use the `next' field as `last_child'. */
-		if (dad->next == 0)
-			dad->child = PTRUNRELOC(np);
-		else
-			dad->next->sibling = PTRUNRELOC(np);
-		dad->next = np;
-	}
-
-	/* get and store all properties */
-	prev_propp = &np->properties;
-	prev_name = "";
-	for (;;) {
-		pp = (struct property *) mem_start;
-		namep = (char *) (pp + 1);
-		pp->name = PTRUNRELOC(namep);
-		if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0)
-			break;
-		mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
-		prev_name = namep;
-		valp = (unsigned char *) mem_start;
-		pp->value = PTRUNRELOC(valp);
-		pp->length = call_prom("getprop", 4, 1, node, namep,
-				       valp, mem_end - mem_start);
-		if (pp->length < 0)
-			continue;
-#ifdef MAX_PROPERTY_LENGTH
-		if (pp->length > MAX_PROPERTY_LENGTH)
-			continue; /* ignore this property */
-#endif
-		mem_start = ALIGNUL(mem_start + pp->length);
-		*prev_propp = PTRUNRELOC(pp);
-		prev_propp = &pp->next;
-	}
-	if (np->node != 0) {
-		/* Add a "linux,phandle" property" */
-		pp = (struct property *) mem_start;
-		*prev_propp = PTRUNRELOC(pp);
-		prev_propp = &pp->next;
-		namep = (char *) (pp + 1);
-		pp->name = PTRUNRELOC(namep);
-		strcpy(namep, "linux,phandle");
-		mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
-		pp->value = (unsigned char *) PTRUNRELOC(&np->node);
-		pp->length = sizeof(np->node);
-	}
-	*prev_propp = NULL;
-
-	/* get the node's full name */
-	l = call_prom("package-to-path", 3, 1, node,
-		      mem_start, mem_end - mem_start);
-	if (l >= 0) {
-		char *p, *ep;
-
-		np->full_name = PTRUNRELOC((char *) mem_start);
-		*(char *)(mem_start + l) = 0;
-		/* Fixup an Apple bug where they have bogus \0 chars in the
-		 * middle of the path in some properties
-		 */
-		for (p = (char *)mem_start, ep = p + l; p < ep; p++)
-			if ((*p) == '\0') {
-				memmove(p, p+1, ep - p);
-				ep--;
-			}
-		mem_start = ALIGNUL(mem_start + l + 1);
-	}
-
-	/* do all our children */
-	child = call_prom("child", 1, 1, node);
-	while (child != 0) {
-		mem_start = inspect_node(child, np, mem_start, mem_end,
-					 allnextpp);
-		child = call_prom("peer", 1, 1, child);
-	}
-
-	return mem_start;
-}
-
-unsigned long smp_chrp_cpu_nr __initdata = 0;
-
-/*
- * With CHRP SMP we need to use the OF to start the other
- * processors so we can't wait until smp_boot_cpus (the OF is
- * trashed by then) so we have to put the processors into
- * a holding pattern controlled by the kernel (not OF) before
- * we destroy the OF.
- *
- * This uses a chunk of high memory, puts some holding pattern
- * code there and sends the other processors off to there until
- * smp_boot_cpus tells them to do something.  We do that by using
- * physical address 0x0.  The holding pattern checks that address
- * until its cpu # is there, when it is that cpu jumps to
- * __secondary_start().  smp_boot_cpus() takes care of setting those
- * values.
- *
- * We also use physical address 0x4 here to tell when a cpu
- * is in its holding pattern code.
- *
- * -- Cort
- *
- * Note that we have to do this if we have more than one CPU,
- * even if this is a UP kernel.  Otherwise when we trash OF
- * the other CPUs will start executing some random instructions
- * and crash the system.  -- paulus
- */
-static void __init
-prom_hold_cpus(unsigned long mem)
-{
-	extern void __secondary_hold(void);
-	unsigned long i;
-	int cpu;
-	phandle node;
-	char type[16], *path;
-	unsigned int reg;
-
-	/*
-	 * XXX: hack to make sure we're chrp, assume that if we're
-	 *      chrp we have a device_type property -- Cort
-	 */
-	node = call_prom("finddevice", 1, 1, "/");
-	if (call_prom("getprop", 4, 1, node,
-		      "device_type", type, sizeof(type)) <= 0)
-		return;
-
-	/* copy the holding pattern code to someplace safe (0) */
-	/* the holding pattern is now within the first 0x100
-	   bytes of the kernel image -- paulus */
-	memcpy((void *)0, _stext, 0x100);
-	flush_icache_range(0, 0x100);
-
-	/* look for cpus */
-	*(unsigned long *)(0x0) = 0;
-	asm volatile("dcbf 0,%0": : "r" (0) : "memory");
-	for (node = 0; prom_next_node(&node); ) {
-		type[0] = 0;
-		call_prom("getprop", 4, 1, node, "device_type",
-			  type, sizeof(type));
-		if (strcmp(type, "cpu") != 0)
-			continue;
-		path = (char *) mem;
-		memset(path, 0, 256);
-		if (call_prom("package-to-path", 3, 1, node, path, 255) < 0)
-			continue;
-		reg = -1;
-		call_prom("getprop", 4, 1, node, "reg", &reg, sizeof(reg));
-		cpu = smp_chrp_cpu_nr++;
-#ifdef CONFIG_SMP
-		smp_hw_index[cpu] = reg;
-#endif /* CONFIG_SMP */
-		/* XXX: hack - don't start cpu 0, this cpu -- Cort */
-		if (cpu == 0)
-			continue;
-		prom_print("starting cpu ");
-		prom_print(path);
-		*(ulong *)(0x4) = 0;
-		call_prom("start-cpu", 3, 0, node,
-			  (char *)__secondary_hold - _stext, cpu);
-		prom_print("...");
-		for ( i = 0 ; (i < 10000) && (*(ulong *)(0x4) == 0); i++ )
-			;
-		if (*(ulong *)(0x4) == cpu)
-			prom_print("ok\n");
-		else {
-			prom_print("failed: ");
-			prom_print_hex(*(ulong *)0x4);
-			prom_print("\n");
-		}
-	}
-}
-
-static void __init
-prom_instantiate_rtas(void)
-{
-	ihandle prom_rtas;
-	prom_arg_t result;
-
-	prom_rtas = call_prom("finddevice", 1, 1, "/rtas");
-	if (prom_rtas == -1)
-		return;
-
-	rtas_size = 0;
-	call_prom("getprop", 4, 1, prom_rtas,
-		  "rtas-size", &rtas_size, sizeof(rtas_size));
-	prom_print("instantiating rtas");
-	if (rtas_size == 0) {
-		rtas_data = 0;
-	} else {
-		/*
-		 * Ask OF for some space for RTAS.
-		 * Actually OF has bugs so we just arbitrarily
-		 * use memory at the 6MB point.
-		 */
-		rtas_data = 6 << 20;
-		prom_print(" at ");
-		prom_print_hex(rtas_data);
-	}
-
-	prom_rtas = call_prom("open", 1, 1, "/rtas");
-	prom_print("...");
-	rtas_entry = 0;
-	if (call_prom_ret("call-method", 3, 2, &result,
-			  "instantiate-rtas", prom_rtas, rtas_data) == 0)
-		rtas_entry = result;
-	if ((rtas_entry == -1) || (rtas_entry == 0))
-		prom_print(" failed\n");
-	else
-		prom_print(" done\n");
-}
-
-/*
- * We enter here early on, when the Open Firmware prom is still
- * handling exceptions and the MMU hash table for us.
- */
-unsigned long __init
-prom_init(int r3, int r4, prom_entry pp)
-{
-	unsigned long mem;
-	ihandle prom_mmu;
-	unsigned long offset = reloc_offset();
-	int i, l;
-	char *p, *d;
- 	unsigned long phys;
-	prom_arg_t result[3];
-	char model[32];
-	phandle node;
-	int rc;
-
- 	/* Default */
- 	phys = (unsigned long) &_stext;
-
-	/* First get a handle for the stdout device */
-	prom = pp;
-	prom_chosen = call_prom("finddevice", 1, 1, "/chosen");
-	if (prom_chosen == -1)
-		prom_exit();
-	if (call_prom("getprop", 4, 1, prom_chosen, "stdout",
-		      &prom_stdout, sizeof(prom_stdout)) <= 0)
-		prom_exit();
-
-	/* Get the full OF pathname of the stdout device */
-	mem = (unsigned long) klimit + offset;
-	p = (char *) mem;
-	memset(p, 0, 256);
-	call_prom("instance-to-path", 3, 1, prom_stdout, p, 255);
-	of_stdout_device = p;
-	mem += strlen(p) + 1;
-
-	/* Get the boot device and translate it to a full OF pathname. */
-	p = (char *) mem;
-	l = call_prom("getprop", 4, 1, prom_chosen, "bootpath", p, 1<<20);
-	if (l > 0) {
-		p[l] = 0;	/* should already be null-terminated */
-		bootpath = PTRUNRELOC(p);
-		mem += l + 1;
-		d = (char *) mem;
-		*d = 0;
-		call_prom("canon", 3, 1, p, d, 1<<20);
-		bootdevice = PTRUNRELOC(d);
-		mem = ALIGNUL(mem + strlen(d) + 1);
-	}
-
-	prom_instantiate_rtas();
-
-#ifdef CONFIG_POWER4
-	/*
-	 * Find out how much memory we have and allocate a
-	 * suitably-sized hash table.
-	 */
-	prom_alloc_htab();
-#endif
-	mem = check_display(mem);
-
-	prom_print("copying OF device tree...");
-	mem = copy_device_tree(mem, mem + (1<<20));
-	prom_print("done\n");
-
-	prom_hold_cpus(mem);
-
-	klimit = (char *) (mem - offset);
-
-	node = call_prom("finddevice", 1, 1, "/");
-	rc = call_prom("getprop", 4, 1, node, "model", model, sizeof(model));
-	if (rc > 0 && !strncmp (model, "Pegasos", 7)
-		&& strncmp (model, "Pegasos2", 8)) {
-		/* Pegasos 1 has a broken translate method in the OF,
-		 * and furthermore the BATs are mapped 1:1 so the phys
-		 * address calculated above is correct, so let's use
-		 * it directly.
-		 */
-	} else if (offset == 0) {
-		/* If we are already running at 0xc0000000, we assume we were
-	 	 * loaded by an OF bootloader which did set a BAT for us.
-	 	 * This breaks OF translate so we force phys to be 0.
-	 	 */
-		prom_print("(already at 0xc0000000) phys=0\n");
-		phys = 0;
-	} else if (call_prom("getprop", 4, 1, prom_chosen, "mmu",
-			     &prom_mmu, sizeof(prom_mmu)) <= 0) {
-		prom_print(" no MMU found\n");
-	} else if (call_prom_ret("call-method", 4, 4, result, "translate",
-				 prom_mmu, &_stext, 1) != 0) {
-		prom_print(" (translate failed)\n");
-	} else {
-		/* We assume the phys. address size is 3 cells */
-		phys = result[2];
-	}
-
-	if (prom_disp_node != 0)
-		setup_disp_fake_bi(prom_disp_node);
-
-	/* Use quiesce call to get OF to shut down any devices it's using */
-	prom_print("Calling quiesce ...\n");
-	call_prom("quiesce", 0, 0);
-
-	/* Relocate various pointers which will be used once the
-	   kernel is running at the address it was linked at. */
-	for (i = 0; i < prom_num_displays; ++i)
-		prom_display_paths[i] = PTRUNRELOC(prom_display_paths[i]);
-
-#ifdef CONFIG_SERIAL_CORE_CONSOLE
-	/* Relocate the of stdout for console autodetection */
-	of_stdout_device = PTRUNRELOC(of_stdout_device);
-#endif
-
-	prom_print("returning 0x");
-	prom_print_hex(phys);
-	prom_print("from prom_init\n");
-	prom_stdout = 0;
-
-	return phys;
-}
-
-/*
- * early_get_property is used to access the device tree image prepared
- * by BootX very early on, before the pointers in it have been relocated.
- */
-static void * __init
-early_get_property(unsigned long base, unsigned long node, char *prop)
-{
-	struct device_node *np = (struct device_node *)(base + node);
-	struct property *pp;
-
-	for (pp = np->properties; pp != 0; pp = pp->next) {
-		pp = (struct property *) (base + (unsigned long)pp);
-		if (strcmp((char *)((unsigned long)pp->name + base),
-			   prop) == 0) {
-			return (void *)((unsigned long)pp->value + base);
-		}
-	}
-	return NULL;
-}
-
-/* Is boot-info compatible ? */
-#define BOOT_INFO_IS_COMPATIBLE(bi)		((bi)->compatible_version <= BOOT_INFO_VERSION)
-#define BOOT_INFO_IS_V2_COMPATIBLE(bi)	((bi)->version >= 2)
-#define BOOT_INFO_IS_V4_COMPATIBLE(bi)	((bi)->version >= 4)
-
-void __init
-bootx_init(unsigned long r4, unsigned long phys)
-{
-	boot_infos_t *bi = (boot_infos_t *) r4;
-	unsigned long space;
-	unsigned long ptr, x;
-	char *model;
-
-	boot_infos = PTRUNRELOC(bi);
-	if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))
-		bi->logicalDisplayBase = NULL;
-
-#ifdef CONFIG_BOOTX_TEXT
-	btext_init(bi);
-
-	/*
-	 * Test if boot-info is compatible.  Done only in config
-	 * CONFIG_BOOTX_TEXT since there is nothing much we can do
-	 * with an incompatible version, except display a message
-	 * and eventually hang the processor...
-	 *
-	 * I'll try to keep enough of boot-info compatible in the
-	 * future to always allow display of this message;
-	 */
-	if (!BOOT_INFO_IS_COMPATIBLE(bi)) {
-		btext_drawstring(" !!! WARNING - Incompatible version of BootX !!!\n\n\n");
-		btext_flushscreen();
-	}
-#endif	/* CONFIG_BOOTX_TEXT */
-
-	/* New BootX enters kernel with MMU off, i/os are not allowed
-	   here. This hack will have been done by the boostrap anyway.
-	*/
-	if (bi->version < 4) {
-		/*
-		 * XXX If this is an iMac, turn off the USB controller.
-		 */
-		model = (char *) early_get_property
-			(r4 + bi->deviceTreeOffset, 4, "model");
-		if (model
-		    && (strcmp(model, "iMac,1") == 0
-			|| strcmp(model, "PowerMac1,1") == 0)) {
-			out_le32((unsigned *)0x80880008, 1);	/* XXX */
-		}
-	}
-
-	/* Move klimit to enclose device tree, args, ramdisk, etc... */
-	if (bi->version < 5) {
-		space = bi->deviceTreeOffset + bi->deviceTreeSize;
-		if (bi->ramDisk)
-			space = bi->ramDisk + bi->ramDiskSize;
-	} else
-		space = bi->totalParamsSize;
-	klimit = PTRUNRELOC((char *) bi + space);
-
-	/* New BootX will have flushed all TLBs and enters kernel with
-	   MMU switched OFF, so this should not be useful anymore.
-	*/
-	if (bi->version < 4) {
-		/*
-		 * Touch each page to make sure the PTEs for them
-		 * are in the hash table - the aim is to try to avoid
-		 * getting DSI exceptions while copying the kernel image.
-		 */
-		for (ptr = ((unsigned long) &_stext) & PAGE_MASK;
-		     ptr < (unsigned long)bi + space; ptr += PAGE_SIZE)
-			x = *(volatile unsigned long *)ptr;
-	}
-
-#ifdef CONFIG_BOOTX_TEXT
-	/*
-	 * Note that after we call btext_prepare_BAT, we can't do
-	 * prom_draw*, flushscreen or clearscreen until we turn the MMU
-	 * on, since btext_prepare_BAT sets disp_bi.logicalDisplayBase
-	 * to a virtual address.
-	 */
-	btext_prepare_BAT();
-#endif
-}
diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c
index ff86b2d..cfc2d6a 100644
--- a/arch/ppc/xmon/start.c
+++ b/arch/ppc/xmon/start.c
@@ -58,7 +58,7 @@
 void
 xmon_map_scc(void)
 {
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_PPC_PREP
 	volatile unsigned char *base;
 
 #elif defined(CONFIG_GEMINI)
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 73d30bf..889cad0 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -561,14 +561,31 @@
 
 	  If unsure, say N.
 
+config HVC_DRIVER
+	bool
+	help
+	  Users of pSeries machines that want to utilize the hvc console front-end
+	  module for their backend console driver should select this option.
+	  It will automatically be selected if one of the back-end console drivers
+	  is selected.
+
+
 config HVC_CONSOLE
 	bool "pSeries Hypervisor Virtual Console support"
 	depends on PPC_PSERIES
+	select HVC_DRIVER
 	help
 	  pSeries machines when partitioned support a hypervisor virtual
 	  console. This driver allows each pSeries partition to have a console
 	  which is accessed via the HMC.
 
+config HVC_RTAS
+	bool "IBM RTAS Console support"
+	depends on PPC_RTAS
+	select HVC_DRIVER
+	help
+	  IBM Console device driver which makes use of RTAS
+
 config HVCS
 	tristate "IBM Hypervisor Virtual Console Server support"
 	depends on PPC_PSERIES
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index b2a1124..a73cb49 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -41,7 +41,9 @@
 obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
 obj-$(CONFIG_SX)		+= sx.o generic_serial.o
 obj-$(CONFIG_RIO)		+= rio/ generic_serial.o
-obj-$(CONFIG_HVC_CONSOLE)	+= hvc_console.o hvc_vio.o hvsi.o
+obj-$(CONFIG_HVC_DRIVER)	+= hvc_console.o
+obj-$(CONFIG_HVC_CONSOLE)	+= hvc_vio.o hvsi.o
+obj-$(CONFIG_HVC_RTAS)		+= hvc_rtas.o
 obj-$(CONFIG_RAW_DRIVER)	+= raw.o
 obj-$(CONFIG_SGI_SNSC)		+= snsc.o snsc_event.o
 obj-$(CONFIG_MMTIMER)		+= mmtimer.o
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 107df9f..edc72a6 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -357,6 +357,12 @@
 	spinlock_t lock;
 } drm_freelist_t;
 
+typedef struct drm_dma_handle {
+	dma_addr_t busaddr;
+	void *vaddr;
+	size_t size;
+} drm_dma_handle_t;
+
 /**
  * Buffer entry.  There is one of this for each buffer size order.
  */
@@ -366,7 +372,7 @@
 	drm_buf_t *buflist;		/**< buffer list */
 	int seg_count;
 	int page_order;
-	unsigned long *seglist;
+	drm_dma_handle_t **seglist;
 
 	drm_freelist_t freelist;
 } drm_buf_entry_t;
@@ -483,12 +489,6 @@
 	drm_hw_lock_t *lock;
 } drm_sigdata_t;
 
-typedef struct drm_dma_handle {
-	dma_addr_t busaddr;
-	void *vaddr;
-	size_t size;
-} drm_dma_handle_t;
-
 /**
  * Mappings list
  */
@@ -813,8 +813,6 @@
 extern int drm_mem_info(char *buf, char **start, off_t offset,
 			int request, int *eof, void *data);
 extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area);
-extern unsigned long drm_alloc_pages(int order, int area);
-extern void drm_free_pages(unsigned long address, int order, int area);
 extern void *drm_ioremap(unsigned long offset, unsigned long size,
 			 drm_device_t * dev);
 extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index e2637b4..8a9cf12 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -474,8 +474,7 @@
 	if (entry->seg_count) {
 		for (i = 0; i < entry->seg_count; i++) {
 			if (entry->seglist[i]) {
-				drm_free_pages(entry->seglist[i],
-					       entry->page_order, DRM_MEM_DMA);
+				drm_pci_free(dev, entry->seglist[i]);
 			}
 		}
 		drm_free(entry->seglist,
@@ -678,7 +677,7 @@
 	int total;
 	int page_order;
 	drm_buf_entry_t *entry;
-	unsigned long page;
+	drm_dma_handle_t *dmah;
 	drm_buf_t *buf;
 	int alignment;
 	unsigned long offset;
@@ -781,8 +780,10 @@
 	page_count = 0;
 
 	while (entry->buf_count < count) {
-		page = drm_alloc_pages(page_order, DRM_MEM_DMA);
-		if (!page) {
+		
+		dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000, 0xfffffffful);
+		
+		if (!dmah) {
 			/* Set count correctly so we free the proper amount. */
 			entry->buf_count = count;
 			entry->seg_count = count;
@@ -794,13 +795,13 @@
 			atomic_dec(&dev->buf_alloc);
 			return -ENOMEM;
 		}
-		entry->seglist[entry->seg_count++] = page;
+		entry->seglist[entry->seg_count++] = dmah;
 		for (i = 0; i < (1 << page_order); i++) {
 			DRM_DEBUG("page %d @ 0x%08lx\n",
 				  dma->page_count + page_count,
-				  page + PAGE_SIZE * i);
+				  (unsigned long)dmah->vaddr + PAGE_SIZE * i);
 			temp_pagelist[dma->page_count + page_count++]
-			    = page + PAGE_SIZE * i;
+				= (unsigned long)dmah->vaddr + PAGE_SIZE * i;
 		}
 		for (offset = 0;
 		     offset + size <= total && entry->buf_count < count;
@@ -811,7 +812,8 @@
 			buf->order = order;
 			buf->used = 0;
 			buf->offset = (dma->byte_count + byte_count + offset);
-			buf->address = (void *)(page + offset);
+			buf->address = (void *)(dmah->vaddr + offset);
+			buf->bus_address = dmah->busaddr + offset;
 			buf->next = NULL;
 			buf->waiting = 0;
 			buf->pending = 0;
diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c
index 2afab95..892db70 100644
--- a/drivers/char/drm/drm_dma.c
+++ b/drivers/char/drm/drm_dma.c
@@ -85,9 +85,7 @@
 				  dma->bufs[i].seg_count);
 			for (j = 0; j < dma->bufs[i].seg_count; j++) {
 				if (dma->bufs[i].seglist[j]) {
-					drm_free_pages(dma->bufs[i].seglist[j],
-						       dma->bufs[i].page_order,
-						       DRM_MEM_DMA);
+					drm_pci_free(dev, dma->bufs[i].seglist[j]);
 				}
 			}
 			drm_free(dma->bufs[i].seglist,
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index 8074771..dddf8de 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -79,65 +79,6 @@
 	return pt;
 }
 
-/**
- * Allocate pages.
- *
- * \param order size order.
- * \param area memory area. (Not used.)
- * \return page address on success, or zero on failure.
- *
- * Allocate and reserve free pages.
- */
-unsigned long drm_alloc_pages(int order, int area)
-{
-	unsigned long address;
-	unsigned long bytes = PAGE_SIZE << order;
-	unsigned long addr;
-	unsigned int sz;
-
-	address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order);
-	if (!address)
-		return 0;
-
-	/* Zero */
-	memset((void *)address, 0, bytes);
-
-	/* Reserve */
-	for (addr = address, sz = bytes;
-	     sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
-		SetPageReserved(virt_to_page(addr));
-	}
-
-	return address;
-}
-
-/**
- * Free pages.
- *
- * \param address address of the pages to free.
- * \param order size order.
- * \param area memory area. (Not used.)
- *
- * Unreserve and free pages allocated by alloc_pages().
- */
-void drm_free_pages(unsigned long address, int order, int area)
-{
-	unsigned long bytes = PAGE_SIZE << order;
-	unsigned long addr;
-	unsigned int sz;
-
-	if (!address)
-		return;
-
-	/* Unreserve */
-	for (addr = address, sz = bytes;
-	     sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(addr));
-	}
-
-	free_pages(address, order);
-}
-
 #if __OS_HAS_AGP
 /** Wrapper around agp_allocate_memory() */
 DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type)
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
index e84605f..7868341 100644
--- a/drivers/char/drm/drm_memory_debug.h
+++ b/drivers/char/drm/drm_memory_debug.h
@@ -206,76 +206,6 @@
 	}
 }
 
-unsigned long drm_alloc_pages (int order, int area) {
-	unsigned long address;
-	unsigned long bytes = PAGE_SIZE << order;
-	unsigned long addr;
-	unsigned int sz;
-
-	spin_lock(&drm_mem_lock);
-	if ((drm_ram_used >> PAGE_SHIFT)
-	    > (DRM_RAM_PERCENT * drm_ram_available) / 100) {
-		spin_unlock(&drm_mem_lock);
-		return 0;
-	}
-	spin_unlock(&drm_mem_lock);
-
-	address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order);
-	if (!address) {
-		spin_lock(&drm_mem_lock);
-		++drm_mem_stats[area].fail_count;
-		spin_unlock(&drm_mem_lock);
-		return 0;
-	}
-	spin_lock(&drm_mem_lock);
-	++drm_mem_stats[area].succeed_count;
-	drm_mem_stats[area].bytes_allocated += bytes;
-	drm_ram_used += bytes;
-	spin_unlock(&drm_mem_lock);
-
-	/* Zero outside the lock */
-	memset((void *)address, 0, bytes);
-
-	/* Reserve */
-	for (addr = address, sz = bytes;
-	     sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
-		SetPageReserved(virt_to_page(addr));
-	}
-
-	return address;
-}
-
-void drm_free_pages (unsigned long address, int order, int area) {
-	unsigned long bytes = PAGE_SIZE << order;
-	int alloc_count;
-	int free_count;
-	unsigned long addr;
-	unsigned int sz;
-
-	if (!address) {
-		DRM_MEM_ERROR(area, "Attempt to free address 0\n");
-	} else {
-		/* Unreserve */
-		for (addr = address, sz = bytes;
-		     sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
-			ClearPageReserved(virt_to_page(addr));
-		}
-		free_pages(address, order);
-	}
-
-	spin_lock(&drm_mem_lock);
-	free_count = ++drm_mem_stats[area].free_count;
-	alloc_count = drm_mem_stats[area].succeed_count;
-	drm_mem_stats[area].bytes_freed += bytes;
-	drm_ram_used -= bytes;
-	spin_unlock(&drm_mem_lock);
-	if (free_count > alloc_count) {
-		DRM_MEM_ERROR(area,
-			      "Excess frees: %d frees, %d allocs\n",
-			      free_count, alloc_count);
-	}
-}
-
 void *drm_ioremap (unsigned long offset, unsigned long size,
 		    drm_device_t * dev) {
 	void *pt;
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c
index 1fd7ff16..b28ca9c 100644
--- a/drivers/char/drm/drm_pci.c
+++ b/drivers/char/drm/drm_pci.c
@@ -50,6 +50,10 @@
 				dma_addr_t maxaddr)
 {
 	drm_dma_handle_t *dmah;
+#if 1
+	unsigned long addr;
+	size_t sz;
+#endif
 #ifdef DRM_DEBUG_MEMORY
 	int area = DRM_MEM_DMA;
 
@@ -79,7 +83,7 @@
 		return NULL;
 
 	dmah->size = size;
-	dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr);
+	dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP);
 
 #ifdef DRM_DEBUG_MEMORY
 	if (dmah->vaddr == NULL) {
@@ -104,18 +108,29 @@
 
 	memset(dmah->vaddr, 0, size);
 
+	/* XXX - Is virt_to_page() legal for consistent mem? */
+	/* Reserve */
+	for (addr = (unsigned long)dmah->vaddr, sz = size;
+	     sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+		SetPageReserved(virt_to_page(addr));
+	}
+
 	return dmah;
 }
 
 EXPORT_SYMBOL(drm_pci_alloc);
 
 /**
- * \brief Free a PCI consistent memory block with freeing its descriptor.
+ * \brief Free a PCI consistent memory block without freeing its descriptor.
  *
  * This function is for internal use in the Linux-specific DRM core code.
  */
 void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah)
 {
+#if 1
+	unsigned long addr;
+	size_t sz;
+#endif
 #ifdef DRM_DEBUG_MEMORY
 	int area = DRM_MEM_DMA;
 	int alloc_count;
@@ -127,8 +142,14 @@
 		DRM_MEM_ERROR(area, "Attempt to free address 0\n");
 #endif
 	} else {
-		pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr,
-				    dmah->busaddr);
+		/* XXX - Is virt_to_page() legal for consistent mem? */
+		/* Unreserve */
+		for (addr = (unsigned long)dmah->vaddr, sz = dmah->size;
+		     sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+			ClearPageReserved(virt_to_page(addr));
+		}
+		dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr,
+				  dmah->busaddr);
 	}
 
 #ifdef DRM_DEBUG_MEMORY
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 2c17e88..b1bb3c7 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -3,49 +3,69 @@
    Please contact dri-devel@lists.sf.net to add new cards to this list
 */
 #define radeon_PCI_IDS \
-	{0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350},\
+	{0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \
+	{0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
 	{0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \
 	{0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \
 	{0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
 	{0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
 	{0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
 	{0x1002, 0x4147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+	{0x1002, 0x4148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+	{0x1002, 0x4149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+	{0x1002, 0x414A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+	{0x1002, 0x414B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
 	{0x1002, 0x4150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
 	{0x1002, 0x4151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
 	{0x1002, 0x4152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
 	{0x1002, 0x4153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
 	{0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+	{0x1002, 0x4155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
 	{0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-	{0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS250|CHIP_IS_IGP}, \
+	{0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \
 	{0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
 	{0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
 	{0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
 	{0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
-	{0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS250|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
-	{0x1002, 0x4964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
-	{0x1002, 0x4965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
-	{0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
-	{0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
-	{0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \
-	{0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \
+	{0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
+	{0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \
+	{0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \
+	{0x1002, 0x4A48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x4A4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x4A4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x4A4D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x4A4E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x4B4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
 	{0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \
 	{0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \
 	{0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \
 	{0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \
-	{0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
-	{0x1002, 0x4C65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
-	{0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
-	{0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
+	{0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \
+	{0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \
+	{0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \
 	{0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
 	{0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-	{0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+	{0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
 	{0x1002, 0x4E47, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
 	{0x1002, 0x4E48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
 	{0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-	{0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+	{0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
 	{0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
 	{0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
 	{0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
+	{0x1002, 0x4E52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
+	{0x1002, 0x4E53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
 	{0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
 	{0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
 	{0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
@@ -53,44 +73,66 @@
 	{0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
 	{0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
 	{0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-	{0x1002, 0x5149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-	{0x1002, 0x514A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-	{0x1002, 0x514B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
 	{0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
 	{0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-	{0x1002, 0x514E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-	{0x1002, 0x514F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
 	{0x1002, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \
 	{0x1002, 0x5158, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \
 	{0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
 	{0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
 	{0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
-	{0x1002, 0x5168, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-	{0x1002, 0x5169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-	{0x1002, 0x516A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-	{0x1002, 0x516B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-	{0x1002, 0x516C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-	{0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-	{0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+	{0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \
+	{0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \
+	{0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \
+	{0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
 	{0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \
 	{0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
-	{0x1002, 0x5836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \
-	{0x1002, 0x5837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \
 	{0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-	{0x1002, 0x5963, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-	{0x1002, 0x5968, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
+	{0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
-	{0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-	{0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
+	{0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5b64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \
 	{0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
-	{0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
-	{0x1002, 0x5c64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-	{0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-	{0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \
+	{0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_NEW_MEMMAP}, \
+	{0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \
 	{0, 0, 0}
 
 #define r128_PCI_IDS \
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index 1ff4c7c..9f4b8ce 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -495,8 +495,6 @@
 		}
 	}
 
-	dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
-
 	i915_emit_breadcrumb(dev);
 
 	return 0;
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index d3879ac..a752afd 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -53,6 +53,8 @@
 
 	I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
 
+	dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+
 	if (temp & USER_INT_FLAG)
 		DRM_WAKEUP(&dev_priv->irq_queue);
 
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
index c08fa50..b108c7f91 100644
--- a/drivers/char/drm/r300_cmdbuf.c
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -214,13 +214,13 @@
 	ADD_RANGE(0x4F54, 1);
 
 	ADD_RANGE(R300_TX_FILTER_0, 16);
-	ADD_RANGE(R300_TX_UNK1_0, 16);
+	ADD_RANGE(R300_TX_FILTER1_0, 16);
 	ADD_RANGE(R300_TX_SIZE_0, 16);
 	ADD_RANGE(R300_TX_FORMAT_0, 16);
 	ADD_RANGE(R300_TX_PITCH_0, 16);
 	/* Texture offset is dangerous and needs more checking */
 	ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);
-	ADD_RANGE(R300_TX_UNK4_0, 16);
+	ADD_RANGE(R300_TX_CHROMA_KEY_0, 16);
 	ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
 
 	/* Sporadic registers used as primitives are emitted */
@@ -242,8 +242,10 @@
 	return 0;
 }
 
-  /* we expect offsets passed to the framebuffer to be either within video memory or
-     within AGP space */
+/*
+ * we expect offsets passed to the framebuffer to be either within video 
+ * memory or within AGP space 
+ */
 static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,
 					u32 offset)
 {
@@ -251,11 +253,11 @@
 	   but this value is not being kept.
 	   This code is correct for now (does the same thing as the
 	   code that sets MC_FB_LOCATION) in radeon_cp.c */
-	if ((offset >= dev_priv->fb_location) &&
-	    (offset < dev_priv->gart_vm_start))
+	if (offset >= dev_priv->fb_location &&
+	    offset < (dev_priv->fb_location + dev_priv->fb_size))
 		return 0;
-	if ((offset >= dev_priv->gart_vm_start) &&
-	    (offset < dev_priv->gart_vm_start + dev_priv->gart_size))
+	if (offset >= dev_priv->gart_vm_start &&
+	    offset < (dev_priv->gart_vm_start + dev_priv->gart_size))
 		return 0;
 	return 1;
 }
@@ -490,6 +492,7 @@
 
 	return 0;
 }
+
 static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
 					     drm_radeon_kcmd_buffer_t *cmdbuf)
 {
@@ -701,6 +704,64 @@
 	buf->used = 0;
 }
 
+static int r300_scratch(drm_radeon_private_t *dev_priv,
+			drm_radeon_kcmd_buffer_t *cmdbuf,
+			drm_r300_cmd_header_t header)
+{
+	u32 *ref_age_base;
+	u32 i, buf_idx, h_pending;
+	RING_LOCALS;
+	
+	if (cmdbuf->bufsz < 
+	    (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) {
+		return DRM_ERR(EINVAL);
+	}
+	
+	if (header.scratch.reg >= 5) {
+		return DRM_ERR(EINVAL);
+	}
+	
+	dev_priv->scratch_ages[header.scratch.reg]++;
+	
+	ref_age_base = *(u32 **)cmdbuf->buf;
+	
+	cmdbuf->buf += sizeof(u64);
+	cmdbuf->bufsz -= sizeof(u64);
+	
+	for (i=0; i < header.scratch.n_bufs; i++) {
+		buf_idx = *(u32 *)cmdbuf->buf;
+		buf_idx *= 2; /* 8 bytes per buf */
+		
+		if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) {
+			return DRM_ERR(EINVAL);
+		}
+					
+		if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) {
+			return DRM_ERR(EINVAL);
+		}
+					
+		if (h_pending == 0) {
+			return DRM_ERR(EINVAL);
+		}
+					
+		h_pending--;
+						
+		if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) {
+			return DRM_ERR(EINVAL);
+		}
+					
+		cmdbuf->buf += sizeof(buf_idx);
+		cmdbuf->bufsz -= sizeof(buf_idx);
+	}
+	
+	BEGIN_RING(2);
+	OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0));
+	OUT_RING(dev_priv->scratch_ages[header.scratch.reg]);
+	ADVANCE_RING();
+	
+	return 0;
+}
+
 /**
  * Parses and validates a user-supplied command buffer and emits appropriate
  * commands on the DMA ring buffer.
@@ -838,6 +899,15 @@
 			}
 			break;
 
+		case R300_CMD_SCRATCH:
+			DRM_DEBUG("R300_CMD_SCRATCH\n");
+			ret = r300_scratch(dev_priv, cmdbuf, header);
+			if (ret) {
+				DRM_ERROR("r300_scratch failed\n");
+				goto cleanup;
+			}
+			break;
+			
 		default:
 			DRM_ERROR("bad cmd_type %i at %p\n",
 				  header.header.cmd_type,
diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h
index d1e1995..a881f96 100644
--- a/drivers/char/drm/r300_reg.h
+++ b/drivers/char/drm/r300_reg.h
@@ -711,8 +711,22 @@
 #	define R300_TX_MAX_ANISO_16_TO_1 (8 << 21)
 #	define R300_TX_MAX_ANISO_MASK    (14 << 21)
 
-#define R300_TX_UNK1_0                      0x4440
+#define R300_TX_FILTER1_0                      0x4440
+#	define R300_CHROMA_KEY_MODE_DISABLE    0
+#	define R300_CHROMA_KEY_FORCE	       1
+#	define R300_CHROMA_KEY_BLEND           2
+#	define R300_MC_ROUND_NORMAL            (0<<2)
+#	define R300_MC_ROUND_MPEG4             (1<<2)
 #	define R300_LOD_BIAS_MASK	    0x1fff
+#	define R300_EDGE_ANISO_EDGE_DIAG       (0<<13)
+#	define R300_EDGE_ANISO_EDGE_ONLY       (1<<13)
+#	define R300_MC_COORD_TRUNCATE_DISABLE  (0<<14)
+#	define R300_MC_COORD_TRUNCATE_MPEG     (1<<14)
+#	define R300_TX_TRI_PERF_0_8            (0<<15)
+#	define R300_TX_TRI_PERF_1_8            (1<<15)
+#	define R300_TX_TRI_PERF_1_4            (2<<15)
+#	define R300_TX_TRI_PERF_3_8            (3<<15)
+#	define R300_ANISO_THRESHOLD_MASK       (7<<17)
 
 #define R300_TX_SIZE_0                      0x4480
 #       define R300_TX_WIDTHMASK_SHIFT           0
@@ -722,6 +736,8 @@
 #       define R300_TX_UNK23                     (1 << 23)
 #       define R300_TX_SIZE_SHIFT                26	/* largest of width, height */
 #       define R300_TX_SIZE_MASK                 (15 << 26)
+#       define R300_TX_SIZE_PROJECTED                     (1<<30)
+#       define R300_TX_SIZE_TXPITCH_EN                     (1<<31)
 #define R300_TX_FORMAT_0                    0x44C0
 	/* The interpretation of the format word by Wladimir van der Laan */
 	/* The X, Y, Z and W refer to the layout of the components.
@@ -750,7 +766,8 @@
 #	define R300_TX_FORMAT_B8G8_B8G8	    	    0x14	/* no swizzle */
 #	define R300_TX_FORMAT_G8R8_G8B8	    	    0x15	/* no swizzle */
 						  /* 0x16 - some 16 bit green format.. ?? */
-#	define R300_TX_FORMAT_UNK25		   (1 << 25)	/* no swizzle */
+#	define R300_TX_FORMAT_UNK25		   (1 << 25) /* no swizzle */
+#	define R300_TX_FORMAT_CUBIC_MAP		   (1 << 26)
 
 	/* gap */
 	/* Floating point formats */
@@ -800,18 +817,20 @@
 
 #	define R300_TX_FORMAT_YUV_MODE		0x00800000
 
-#define R300_TX_PITCH_0			    0x4500
+#define R300_TX_PITCH_0			    0x4500 /* obvious missing in gap */
 #define R300_TX_OFFSET_0                    0x4540
 /* BEGIN: Guess from R200 */
 #       define R300_TXO_ENDIAN_NO_SWAP           (0 << 0)
 #       define R300_TXO_ENDIAN_BYTE_SWAP         (1 << 0)
 #       define R300_TXO_ENDIAN_WORD_SWAP         (2 << 0)
 #       define R300_TXO_ENDIAN_HALFDW_SWAP       (3 << 0)
+#       define R300_TXO_MACRO_TILE               (1 << 2)
+#       define R300_TXO_MICRO_TILE               (1 << 3)
 #       define R300_TXO_OFFSET_MASK              0xffffffe0
 #       define R300_TXO_OFFSET_SHIFT             5
 /* END */
-#define R300_TX_UNK4_0                      0x4580
-#define R300_TX_BORDER_COLOR_0              0x45C0	//ff00ff00 == { 0, 1.0, 0, 1.0 }
+#define R300_TX_CHROMA_KEY_0                      0x4580 /* 32 bit chroma key */
+#define R300_TX_BORDER_COLOR_0              0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 }
 
 /* END */
 
@@ -868,7 +887,9 @@
 #       define R300_PFS_NODE_TEX_OFFSET_MASK     (31 << 12)
 #       define R300_PFS_NODE_TEX_END_SHIFT       17
 #       define R300_PFS_NODE_TEX_END_MASK        (31 << 17)
-#       define R300_PFS_NODE_LAST_NODE           (1 << 22)
+/*#       define R300_PFS_NODE_LAST_NODE           (1 << 22) */
+#		define R300_PFS_NODE_OUTPUT_COLOR        (1 << 22)
+#		define R300_PFS_NODE_OUTPUT_DEPTH        (1 << 23)
 
 /* TEX
 // As far as I can tell, texture instructions cannot write into output
@@ -887,6 +908,7 @@
  */
 #		define R300_FPITX_OPCODE_SHIFT			15
 #			define R300_FPITX_OP_TEX			1
+#			define R300_FPITX_OP_KIL			2
 #			define R300_FPITX_OP_TXP			3
 #			define R300_FPITX_OP_TXB			4
 
@@ -962,9 +984,11 @@
 #       define R300_FPI1_SRC2C_CONST             (1 << 17)
 #       define R300_FPI1_DSTC_SHIFT              18
 #       define R300_FPI1_DSTC_MASK               (31 << 18)
+#		define R300_FPI1_DSTC_REG_MASK_SHIFT     23
 #       define R300_FPI1_DSTC_REG_X              (1 << 23)
 #       define R300_FPI1_DSTC_REG_Y              (1 << 24)
 #       define R300_FPI1_DSTC_REG_Z              (1 << 25)
+#		define R300_FPI1_DSTC_OUTPUT_MASK_SHIFT  26
 #       define R300_FPI1_DSTC_OUTPUT_X           (1 << 26)
 #       define R300_FPI1_DSTC_OUTPUT_Y           (1 << 27)
 #       define R300_FPI1_DSTC_OUTPUT_Z           (1 << 28)
@@ -983,6 +1007,7 @@
 #       define R300_FPI3_DSTA_MASK               (31 << 18)
 #       define R300_FPI3_DSTA_REG                (1 << 23)
 #       define R300_FPI3_DSTA_OUTPUT             (1 << 24)
+#		define R300_FPI3_DSTA_DEPTH              (1 << 27)
 
 #define R300_PFS_INSTR0_0                   0x48C0
 #       define R300_FPI0_ARGC_SRC0C_XYZ          0
@@ -1036,7 +1061,7 @@
 #       define R300_FPI0_OUTC_FRC                (9 << 23)
 #       define R300_FPI0_OUTC_REPL_ALPHA         (10 << 23)
 #       define R300_FPI0_OUTC_SAT                (1 << 30)
-#       define R300_FPI0_UNKNOWN_31              (1 << 31)
+#       define R300_FPI0_INSERT_NOP              (1 << 31)
 
 #define R300_PFS_INSTR2_0                   0x49C0
 #       define R300_FPI2_ARGA_SRC0C_X            0
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 9bb8ae0..7f949c9 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -1118,14 +1118,20 @@
 {
 	u32 ring_start, cur_read_ptr;
 	u32 tmp;
-
-	/* Initialize the memory controller */
-	RADEON_WRITE(RADEON_MC_FB_LOCATION,
-		     ((dev_priv->gart_vm_start - 1) & 0xffff0000)
-		     | (dev_priv->fb_location >> 16));
+	
+	/* Initialize the memory controller. With new memory map, the fb location
+	 * is not changed, it should have been properly initialized already. Part
+	 * of the problem is that the code below is bogus, assuming the GART is
+	 * always appended to the fb which is not necessarily the case
+	 */
+	if (!dev_priv->new_memmap)
+		RADEON_WRITE(RADEON_MC_FB_LOCATION,
+			     ((dev_priv->gart_vm_start - 1) & 0xffff0000)
+			     | (dev_priv->fb_location >> 16));
 
 #if __OS_HAS_AGP
 	if (dev_priv->flags & CHIP_IS_AGP) {
+		RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
 		RADEON_WRITE(RADEON_MC_AGP_LOCATION,
 			     (((dev_priv->gart_vm_start - 1 +
 				dev_priv->gart_size) & 0xffff0000) |
@@ -1153,8 +1159,6 @@
 
 #if __OS_HAS_AGP
 	if (dev_priv->flags & CHIP_IS_AGP) {
-		/* set RADEON_AGP_BASE here instead of relying on X from user space */
-		RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
 		RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
 			     dev_priv->ring_rptr->offset
 			     - dev->agp->base + dev_priv->gart_vm_start);
@@ -1174,6 +1178,17 @@
 			  entry->handle + tmp_ofs);
 	}
 
+	/* Set ring buffer size */
+#ifdef __BIG_ENDIAN
+	RADEON_WRITE(RADEON_CP_RB_CNTL,
+		     dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT);
+#else
+	RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw);
+#endif
+
+	/* Start with assuming that writeback doesn't work */
+	dev_priv->writeback_works = 0;
+
 	/* Initialize the scratch register pointer.  This will cause
 	 * the scratch register values to be written out to memory
 	 * whenever they are updated.
@@ -1190,7 +1205,38 @@
 
 	RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
 
-	/* Writeback doesn't seem to work everywhere, test it first */
+	/* Turn on bus mastering */
+	tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
+	RADEON_WRITE(RADEON_BUS_CNTL, tmp);
+
+	dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
+	RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
+
+	dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
+	RADEON_WRITE(RADEON_LAST_DISPATCH_REG,
+		     dev_priv->sarea_priv->last_dispatch);
+
+	dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
+	RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear);
+
+	radeon_do_wait_for_idle(dev_priv);
+
+	/* Sync everything up */
+	RADEON_WRITE(RADEON_ISYNC_CNTL,
+		     (RADEON_ISYNC_ANY2D_IDLE3D |
+		      RADEON_ISYNC_ANY3D_IDLE2D |
+		      RADEON_ISYNC_WAIT_IDLEGUI |
+		      RADEON_ISYNC_CPSCRATCH_IDLEGUI));
+
+}
+
+static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
+{
+	u32 tmp;
+
+	/* Writeback doesn't seem to work everywhere, test it here and possibly
+	 * enable it if it appears to work
+	 */
 	DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0);
 	RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef);
 
@@ -1203,46 +1249,15 @@
 
 	if (tmp < dev_priv->usec_timeout) {
 		dev_priv->writeback_works = 1;
-		DRM_DEBUG("writeback test succeeded, tmp=%d\n", tmp);
+		DRM_INFO("writeback test succeeded in %d usecs\n", tmp);
 	} else {
 		dev_priv->writeback_works = 0;
-		DRM_DEBUG("writeback test failed\n");
+		DRM_INFO("writeback test failed\n");
 	}
 	if (radeon_no_wb == 1) {
 		dev_priv->writeback_works = 0;
-		DRM_DEBUG("writeback forced off\n");
+		DRM_INFO("writeback forced off\n");
 	}
-
-	dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
-	RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
-
-	dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
-	RADEON_WRITE(RADEON_LAST_DISPATCH_REG,
-		     dev_priv->sarea_priv->last_dispatch);
-
-	dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
-	RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear);
-
-	/* Set ring buffer size */
-#ifdef __BIG_ENDIAN
-	RADEON_WRITE(RADEON_CP_RB_CNTL,
-		     dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT);
-#else
-	RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw);
-#endif
-
-	radeon_do_wait_for_idle(dev_priv);
-
-	/* Turn on bus mastering */
-	tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
-	RADEON_WRITE(RADEON_BUS_CNTL, tmp);
-
-	/* Sync everything up */
-	RADEON_WRITE(RADEON_ISYNC_CNTL,
-		     (RADEON_ISYNC_ANY2D_IDLE3D |
-		      RADEON_ISYNC_ANY3D_IDLE2D |
-		      RADEON_ISYNC_WAIT_IDLEGUI |
-		      RADEON_ISYNC_CPSCRATCH_IDLEGUI));
 }
 
 /* Enable or disable PCI-E GART on the chip */
@@ -1317,6 +1332,14 @@
 
 	DRM_DEBUG("\n");
 
+	/* if we require new memory map but we don't have it fail */
+	if ((dev_priv->flags & CHIP_NEW_MEMMAP) && !dev_priv->new_memmap)
+	{
+		DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX\n");
+		radeon_do_cleanup_cp(dev);
+		return DRM_ERR(EINVAL);
+	}
+
 	if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP))
 	{
 		DRM_DEBUG("Forcing AGP card to PCI mode\n");
@@ -1496,6 +1519,9 @@
 
 	dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION)
 				 & 0xffff) << 16;
+	dev_priv->fb_size = 
+		((RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff0000u) + 0x10000)
+		- dev_priv->fb_location;
 
 	dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
 					((dev_priv->front_offset
@@ -1510,8 +1536,46 @@
 					  + dev_priv->fb_location) >> 10));
 
 	dev_priv->gart_size = init->gart_size;
-	dev_priv->gart_vm_start = dev_priv->fb_location
-	    + RADEON_READ(RADEON_CONFIG_APER_SIZE);
+
+	/* New let's set the memory map ... */
+	if (dev_priv->new_memmap) {
+		u32 base = 0;
+
+		DRM_INFO("Setting GART location based on new memory map\n");
+
+		/* If using AGP, try to locate the AGP aperture at the same
+		 * location in the card and on the bus, though we have to
+		 * align it down.
+		 */
+#if __OS_HAS_AGP
+		if (dev_priv->flags & CHIP_IS_AGP) {
+			base = dev->agp->base;
+			/* Check if valid */
+			if ((base + dev_priv->gart_size) > dev_priv->fb_location &&
+			    base < (dev_priv->fb_location + dev_priv->fb_size)) {
+				DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n",
+					 dev->agp->base);
+				base = 0;
+			}
+		}
+#endif
+		/* If not or if AGP is at 0 (Macs), try to put it elsewhere */
+		if (base == 0) {
+			base = dev_priv->fb_location + dev_priv->fb_size;
+			if (((base + dev_priv->gart_size) & 0xfffffffful)
+			    < base)
+				base = dev_priv->fb_location
+					- dev_priv->gart_size;
+		}		
+		dev_priv->gart_vm_start = base & 0xffc00000u;
+		if (dev_priv->gart_vm_start != base)
+			DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n",
+				 base, dev_priv->gart_vm_start);
+	} else {
+		DRM_INFO("Setting GART location based on old memory map\n");
+		dev_priv->gart_vm_start = dev_priv->fb_location +
+			RADEON_READ(RADEON_CONFIG_APER_SIZE);
+	}
 
 #if __OS_HAS_AGP
 	if (dev_priv->flags & CHIP_IS_AGP)
@@ -1596,6 +1660,7 @@
 	dev_priv->last_buf = 0;
 
 	radeon_do_engine_reset(dev);
+	radeon_test_writeback(dev_priv);
 
 	return 0;
 }
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
index 9c177a6..c8e279e 100644
--- a/drivers/char/drm/radeon_drm.h
+++ b/drivers/char/drm/radeon_drm.h
@@ -222,6 +222,7 @@
 #	define R300_WAIT_3D  		0x2
 #	define R300_WAIT_2D_CLEAN  	0x3
 #	define R300_WAIT_3D_CLEAN  	0x4
+#define R300_CMD_SCRATCH		8
 
 typedef union {
 	unsigned int u;
@@ -247,6 +248,9 @@
 	struct {
 		unsigned char cmd_type, flags, pad0, pad1;
 	} wait;
+	struct {
+		unsigned char cmd_type, reg, n_bufs, flags;
+	} scratch;
 } drm_r300_cmd_header_t;
 
 #define RADEON_FRONT			0x1
@@ -697,6 +701,7 @@
 #define RADEON_SETPARAM_FB_LOCATION    1	/* determined framebuffer location */
 #define RADEON_SETPARAM_SWITCH_TILING  2	/* enable/disable color tiling */
 #define RADEON_SETPARAM_PCIGART_LOCATION 3	/* PCI Gart Location */
+#define RADEON_SETPARAM_NEW_MEMMAP 4		/* Use new memory map */
 
 /* 1.14: Clients can allocate/free a surface
  */
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 1f7d2ab..78345ce 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -38,7 +38,7 @@
 
 #define DRIVER_NAME		"radeon"
 #define DRIVER_DESC		"ATI Radeon"
-#define DRIVER_DATE		"20051229"
+#define DRIVER_DATE		"20060225"
 
 /* Interface history:
  *
@@ -91,9 +91,11 @@
  * 1.20- Add support for r300 texrect
  * 1.21- Add support for card type getparam
  * 1.22- Add support for texture cache flushes (R300_TX_CNTL)
+ * 1.23- Add new radeon memory map work from benh
+ * 1.24- Add general-purpose packet for manipulating scratch registers (r300)
  */
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		22
+#define DRIVER_MINOR		24
 #define DRIVER_PATCHLEVEL	0
 
 /*
@@ -101,20 +103,21 @@
  */
 enum radeon_family {
 	CHIP_R100,
-	CHIP_RS100,
 	CHIP_RV100,
+	CHIP_RS100,
 	CHIP_RV200,
-	CHIP_R200,
 	CHIP_RS200,
-	CHIP_R250,
-	CHIP_RS250,
+	CHIP_R200,
 	CHIP_RV250,
+	CHIP_RS300,
 	CHIP_RV280,
 	CHIP_R300,
-	CHIP_RS300,
 	CHIP_R350,
 	CHIP_RV350,
+	CHIP_RV380,
 	CHIP_R420,
+	CHIP_RV410,
+	CHIP_RS400,
 	CHIP_LAST,
 };
 
@@ -136,9 +139,11 @@
 	CHIP_IS_AGP = 0x00080000UL,
 	CHIP_HAS_HIERZ = 0x00100000UL,
 	CHIP_IS_PCIE = 0x00200000UL,
+	CHIP_NEW_MEMMAP = 0x00400000UL,
 };
 
-#define GET_RING_HEAD(dev_priv)		DRM_READ32(  (dev_priv)->ring_rptr, 0 )
+#define GET_RING_HEAD(dev_priv)	(dev_priv->writeback_works ? \
+        DRM_READ32(  (dev_priv)->ring_rptr, 0 ) : RADEON_READ(RADEON_CP_RB_RPTR))
 #define SET_RING_HEAD(dev_priv,val)	DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) )
 
 typedef struct drm_radeon_freelist {
@@ -199,6 +204,8 @@
 	drm_radeon_sarea_t *sarea_priv;
 
 	u32 fb_location;
+	u32 fb_size;
+	int new_memmap;
 
 	int gart_size;
 	u32 gart_vm_start;
@@ -272,6 +279,8 @@
 	unsigned long pcigart_offset;
 	drm_ati_pcigart_info gart_info;
 
+	u32 scratch_ages[5];
+
 	/* starting from here on, data is preserved accross an open */
 	uint32_t flags;		/* see radeon_chip_flags */
 } drm_radeon_private_t;
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 7bc2751..c5b8f77 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -45,22 +45,53 @@
 	u32 off = *offset;
 	struct drm_radeon_driver_file_fields *radeon_priv;
 
-	if (off >= dev_priv->fb_location &&
-	    off < (dev_priv->gart_vm_start + dev_priv->gart_size))
+	/* Hrm ... the story of the offset ... So this function converts
+	 * the various ideas of what userland clients might have for an
+	 * offset in the card address space into an offset into the card
+	 * address space :) So with a sane client, it should just keep
+	 * the value intact and just do some boundary checking. However,
+	 * not all clients are sane. Some older clients pass us 0 based
+	 * offsets relative to the start of the framebuffer and some may
+	 * assume the AGP aperture it appended to the framebuffer, so we
+	 * try to detect those cases and fix them up.
+	 *
+	 * Note: It might be a good idea here to make sure the offset lands
+	 * in some "allowed" area to protect things like the PCIE GART...
+	 */
+
+	/* First, the best case, the offset already lands in either the
+	 * framebuffer or the GART mapped space
+	 */
+	if ((off >= dev_priv->fb_location &&
+	     off < (dev_priv->fb_location + dev_priv->fb_size)) ||
+	    (off >= dev_priv->gart_vm_start &&
+	     off < (dev_priv->gart_vm_start + dev_priv->gart_size)))
 		return 0;
 
-	radeon_priv = filp_priv->driver_priv;
-	off += radeon_priv->radeon_fb_delta;
+	/* Ok, that didn't happen... now check if we have a zero based
+	 * offset that fits in the framebuffer + gart space, apply the
+	 * magic offset we get from SETPARAM or calculated from fb_location
+	 */
+	if (off < (dev_priv->fb_size + dev_priv->gart_size)) {
+		radeon_priv = filp_priv->driver_priv;
+		off += radeon_priv->radeon_fb_delta;
+	}
 
-	DRM_DEBUG("offset fixed up to 0x%x\n", off);
+	/* Finally, assume we aimed at a GART offset if beyond the fb */
+	if (off > (dev_priv->fb_location + dev_priv->fb_size))
+		off = off - (dev_priv->fb_location + dev_priv->fb_size) +
+			dev_priv->gart_vm_start;
 
-	if (off < dev_priv->fb_location ||
-	    off >= (dev_priv->gart_vm_start + dev_priv->gart_size))
-		return DRM_ERR(EINVAL);
-
-	*offset = off;
-
-	return 0;
+	/* Now recheck and fail if out of bounds */
+	if ((off >= dev_priv->fb_location &&
+	     off < (dev_priv->fb_location + dev_priv->fb_size)) ||
+	    (off >= dev_priv->gart_vm_start &&
+	     off < (dev_priv->gart_vm_start + dev_priv->gart_size))) {
+		DRM_DEBUG("offset fixed up to 0x%x\n", off);
+		*offset = off;
+		return 0;
+	}
+	return DRM_ERR(EINVAL);
 }
 
 static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
@@ -1939,11 +1970,6 @@
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_surface_alloc_t alloc;
 
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-		return DRM_ERR(EINVAL);
-	}
-
 	DRM_COPY_FROM_USER_IOCTL(alloc,
 				 (drm_radeon_surface_alloc_t __user *) data,
 				 sizeof(alloc));
@@ -1960,12 +1986,7 @@
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_surface_free_t memfree;
 
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-		return DRM_ERR(EINVAL);
-	}
-
-	DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data,
+	DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_surface_free_t __user *) data,
 				 sizeof(memfree));
 
 	if (free_surface(filp, dev_priv, memfree.address))
@@ -2100,11 +2121,6 @@
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-		return DRM_ERR(EINVAL);
-	}
-
 	DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
 
 	DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data,
@@ -2189,11 +2205,6 @@
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-		return DRM_ERR(EINVAL);
-	}
-
 	DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
 
 	DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data,
@@ -2340,11 +2351,6 @@
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-		return DRM_ERR(EINVAL);
-	}
-
 	DRM_COPY_FROM_USER_IOCTL(indirect,
 				 (drm_radeon_indirect_t __user *) data,
 				 sizeof(indirect));
@@ -2417,11 +2423,6 @@
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-		return DRM_ERR(EINVAL);
-	}
-
 	DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
 
 	DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data,
@@ -2738,11 +2739,6 @@
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-		return DRM_ERR(EINVAL);
-	}
-
 	DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
 
 	DRM_COPY_FROM_USER_IOCTL(cmdbuf,
@@ -2897,11 +2893,6 @@
 	drm_radeon_getparam_t param;
 	int value;
 
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-		return DRM_ERR(EINVAL);
-	}
-
 	DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data,
 				 sizeof(param));
 
@@ -2981,11 +2972,6 @@
 	drm_radeon_setparam_t sp;
 	struct drm_radeon_driver_file_fields *radeon_priv;
 
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-		return DRM_ERR(EINVAL);
-	}
-
 	DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
 
 	DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data,
@@ -3012,6 +2998,9 @@
 	case RADEON_SETPARAM_PCIGART_LOCATION:
 		dev_priv->pcigart_offset = sp.value;
 		break;
+	case RADEON_SETPARAM_NEW_MEMMAP:
+		dev_priv->new_memmap = sp.value;
+		break;
 	default:
 		DRM_DEBUG("Invalid parameter %d\n", sp.param);
 		return DRM_ERR(EINVAL);
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
index 6774d2f..5e9936b 100644
--- a/drivers/char/drm/sis_mm.c
+++ b/drivers/char/drm/sis_mm.c
@@ -110,7 +110,7 @@
 
 	DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
 
-	DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
+	DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset);
 
 	return retval;
 }
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c
index 1b5e01e..43ff598 100644
--- a/drivers/char/generic_nvram.c
+++ b/drivers/char/generic_nvram.c
@@ -22,6 +22,9 @@
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <asm/nvram.h>
+#ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
+#endif
 
 #define NVRAM_SIZE	8192
 
@@ -92,7 +95,7 @@
 	case IOC_NVRAM_GET_OFFSET: {
 		int part, offset;
 
-		if (_machine != _MACH_Pmac)
+		if (!machine_is(powermac))
 			return -EINVAL;
 		if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0)
 			return -EFAULT;
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index f65b2e1..2b6a56b 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -39,8 +39,10 @@
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/delay.h>
+
 #include <asm/uaccess.h>
-#include <asm/hvconsole.h>
+
+#include "hvc_console.h"
 
 #define HVC_MAJOR	229
 #define HVC_MINOR	0
@@ -54,17 +56,14 @@
 #define HVC_CLOSE_WAIT (HZ/100) /* 1/10 of a second */
 
 /*
- * The Linux TTY code does not support dynamic addition of tty derived devices
- * so we need to know how many tty devices we might need when space is allocated
- * for the tty device.  Since this driver supports hotplug of vty adapters we
- * need to make sure we have enough allocated.
+ * These sizes are most efficient for vio, because they are the
+ * native transfer size. We could make them selectable in the
+ * future to better deal with backends that want other buffer sizes.
  */
-#define HVC_ALLOC_TTY_ADAPTERS	8
-
 #define N_OUTBUF	16
 #define N_INBUF		16
 
-#define __ALIGNED__	__attribute__((__aligned__(8)))
+#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
 
 static struct tty_driver *hvc_driver;
 static struct task_struct *hvc_task;
@@ -154,7 +153,7 @@
 
 void hvc_console_print(struct console *co, const char *b, unsigned count)
 {
-	char c[16] __ALIGNED__;
+	char c[N_OUTBUF] __ALIGNED__;
 	unsigned i = 0, n = 0;
 	int r, donecr = 0, index = co->index;
 
@@ -473,8 +472,10 @@
 
 	n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
 	if (n <= 0) {
-		if (n == 0)
+		if (n == 0) {
+			hp->do_wakeup = 1;
 			return;
+		}
 		/* throw away output on error; this happens when
 		   there is no session connected to the vterm. */
 		hp->n_outbuf = 0;
@@ -486,12 +487,19 @@
 		hp->do_wakeup = 1;
 }
 
-static inline int __hvc_write_kernel(struct hvc_struct *hp,
-				   const unsigned char *buf, int count)
+static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count)
 {
+	struct hvc_struct *hp = tty->driver_data;
 	unsigned long flags;
 	int rsize, written = 0;
 
+	/* This write was probably executed during a tty close. */
+	if (!hp)
+		return -EPIPE;
+
+	if (hp->count <= 0)
+		return -EIO;
+
 	spin_lock_irqsave(&hp->lock, flags);
 
 	/* Push pending writes */
@@ -510,26 +518,8 @@
 	}
 	spin_unlock_irqrestore(&hp->lock, flags);
 
-	return written;
-}
-static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	struct hvc_struct *hp = tty->driver_data;
-	int written;
-
-	/* This write was probably executed during a tty close. */
-	if (!hp)
-		return -EPIPE;
-
-	if (hp->count <= 0)
-		return -EIO;
-
-	written = __hvc_write_kernel(hp, buf, count);
-
 	/*
 	 * Racy, but harmless, kick thread if there is still pending data.
-	 * There really is nothing wrong with kicking the thread, even if there
-	 * is no buffered data.
 	 */
 	if (hp->n_outbuf)
 		hvc_kick();
@@ -614,6 +604,13 @@
 				spin_unlock_irqrestore(&hp->lock, flags);
 				tty_hangup(tty);
 				spin_lock_irqsave(&hp->lock, flags);
+			} else if ( n == -EAGAIN ) {
+				/*
+				 * Some back-ends can only ensure a certain min
+				 * num of bytes read, which may be > 'count'.
+				 * Let the tty clear the flip buff to make room.
+				 */
+				poll_mask |= HVC_POLL_READ;
 			}
 			break;
 		}
@@ -635,16 +632,7 @@
 			tty_insert_flip_char(tty, buf[i], 0);
 		}
 
-		/*
-		 * Account for the total amount read in one loop, and if above
-		 * 64 bytes, we do a quick schedule loop to let the tty grok
-		 * the data and eventually throttle us.
-		 */
 		read_total += n;
-		if (read_total >= 64) {
-			poll_mask |= HVC_POLL_QUICK;
-			break;
-		}
 	}
  throttled:
 	/* Wakeup write queue if necessary */
@@ -767,7 +755,8 @@
 	 * see if this vterm id matches one registered for console.
 	 */
 	for (i=0; i < MAX_NR_HVC_CONSOLES; i++)
-		if (vtermnos[i] == hp->vtermno)
+		if (vtermnos[i] == hp->vtermno &&
+		    cons_ops[i] == hp->ops)
 			break;
 
 	/* no matching slot, just use a counter */
@@ -823,34 +812,38 @@
  * interfaces start to become available. */
 int __init hvc_init(void)
 {
+	struct tty_driver *drv;
+
 	/* We need more than hvc_count adapters due to hotplug additions. */
-	hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
-	if (!hvc_driver)
+	drv = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
+	if (!drv)
 		return -ENOMEM;
 
-	hvc_driver->owner = THIS_MODULE;
-	hvc_driver->devfs_name = "hvc/";
-	hvc_driver->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;
-	hvc_driver->init_termios = tty_std_termios;
-	hvc_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(hvc_driver, &hvc_ops);
+	drv->owner = THIS_MODULE;
+	drv->devfs_name = "hvc/";
+	drv->driver_name = "hvc";
+	drv->name = "hvc";
+	drv->major = HVC_MAJOR;
+	drv->minor_start = HVC_MINOR;
+	drv->type = TTY_DRIVER_TYPE_SYSTEM;
+	drv->init_termios = tty_std_termios;
+	drv->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(drv, &hvc_ops);
 
 	/* Always start the kthread because there can be hotplug vty adapters
 	 * added later. */
 	hvc_task = kthread_run(khvcd, NULL, "khvcd");
 	if (IS_ERR(hvc_task)) {
 		panic("Couldn't create kthread for console.\n");
-		put_tty_driver(hvc_driver);
+		put_tty_driver(drv);
 		return -EIO;
 	}
 
-	if (tty_register_driver(hvc_driver))
+	if (tty_register_driver(drv))
 		panic("Couldn't register hvc console driver\n");
 
+	mb();
+	hvc_driver = drv;
 	return 0;
 }
 module_init(hvc_init);
diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h
new file mode 100644
index 0000000..96b7401
--- /dev/null
+++ b/drivers/char/hvc_console.h
@@ -0,0 +1,63 @@
+/*
+ * hvc_console.h
+ * Copyright (C) 2005 IBM Corporation
+ *
+ * Author(s):
+ * 	Ryan S. Arnold <rsa@us.ibm.com>
+ *
+ * hvc_console header information:
+ *      moved here from include/asm-powerpc/hvconsole.h
+ *      and drivers/char/hvc_console.c
+ *
+ * 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 HVC_CONSOLE_H
+#define HVC_CONSOLE_H
+
+/*
+ * This is the max number of console adapters that can/will be found as
+ * console devices on first stage console init.  Any number beyond this range
+ * can't be used as a console device but is still a valid tty device.
+ */
+#define MAX_NR_HVC_CONSOLES	16
+
+/*
+ * The Linux TTY code does not support dynamic addition of tty derived devices
+ * so we need to know how many tty devices we might need when space is allocated
+ * for the tty device.  Since this driver supports hotplug of vty adapters we
+ * need to make sure we have enough allocated.
+ */
+#define HVC_ALLOC_TTY_ADAPTERS	8
+
+
+/* implemented by a low level driver */
+struct hv_ops {
+	int (*get_chars)(uint32_t vtermno, char *buf, int count);
+	int (*put_chars)(uint32_t vtermno, const char *buf, int count);
+};
+
+struct hvc_struct;
+
+/* Register a vterm and a slot index for use as a console (console_init) */
+extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops);
+
+/* register a vterm for hvc tty operation (module_init or hotplug add) */
+extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq,
+						 struct hv_ops *ops);
+/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */
+extern int __devexit hvc_remove(struct hvc_struct *hp);
+
+#endif // HVC_CONSOLE_H
diff --git a/drivers/char/hvc_rtas.c b/drivers/char/hvc_rtas.c
new file mode 100644
index 0000000..83364ea
--- /dev/null
+++ b/drivers/char/hvc_rtas.c
@@ -0,0 +1,138 @@
+/*
+ * IBM RTAS driver interface to hvc_console.c
+ *
+ * (C) Copyright IBM Corporation 2001-2005
+ * (C) Copyright Red Hat, Inc. 2005
+ *
+ * Author(s): Maximino Augilar <IBM STI Design Center>
+ *	    : Ryan S. Arnold <rsa@us.ibm.com>
+ *	    : Utz Bacher <utz.bacher@de.ibm.com>
+ *	    : David Woodhouse <dwmw2@infradead.org>
+ *
+ *    inspired by drivers/char/hvc_console.c
+ *    written by Anton Blanchard and Paul Mackerras
+ *
+ * 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/console.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+
+#include <asm/irq.h>
+#include <asm/rtas.h>
+#include "hvc_console.h"
+
+#define hvc_rtas_cookie 0x67781e15
+struct hvc_struct *hvc_rtas_dev;
+
+#define RTASCONS_PUT_ATTEMPTS  16
+
+static int rtascons_put_char_token = RTAS_UNKNOWN_SERVICE;
+static int rtascons_get_char_token = RTAS_UNKNOWN_SERVICE;
+static int rtascons_put_delay = 100;
+module_param_named(put_delay, rtascons_put_delay, int, 0644);
+
+static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf, int count)
+{
+	int done;
+
+	/* if there is more than one character to be displayed, wait a bit */
+	for (done = 0; done < count; done++) {
+		int result;
+		result = rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[done]);
+		if (result)
+			break;
+	}
+	/* the calling routine expects to receive the number of bytes sent */
+	return done;
+}
+
+static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count)
+{
+	int i;
+
+	for (i = 0; i < count; i++) {
+		int c, err;
+
+		err = rtas_call(rtascons_get_char_token, 0, 2, &c);
+		if (err)
+			break;
+
+		buf[i] = c;
+	}
+
+	return i;
+}
+
+static struct hv_ops hvc_rtas_get_put_ops = {
+	.get_chars = hvc_rtas_read_console,
+	.put_chars = hvc_rtas_write_console,
+};
+
+static int hvc_rtas_init(void)
+{
+	struct hvc_struct *hp;
+
+	if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
+		rtascons_put_char_token = rtas_token("put-term-char");
+	if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
+		return -EIO;
+
+	if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
+		rtascons_get_char_token = rtas_token("get-term-char");
+	if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
+		return -EIO;
+
+	BUG_ON(hvc_rtas_dev);
+
+	/* Allocate an hvc_struct for the console device we instantiated
+	 * earlier.  Save off hp so that we can return it on exit */
+	hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops);
+	if (IS_ERR(hp))
+		return PTR_ERR(hp);
+	hvc_rtas_dev = hp;
+	return 0;
+}
+module_init(hvc_rtas_init);
+
+/* This will tear down the tty portion of the driver */
+static void __exit hvc_rtas_exit(void)
+{
+	/* Really the fun isn't over until the worker thread breaks down and the
+	 * tty cleans up */
+	if (hvc_rtas_dev)
+		hvc_remove(hvc_rtas_dev);
+}
+module_exit(hvc_rtas_exit);
+
+/* This will happen prior to module init.  There is no tty at this time? */
+static int hvc_rtas_console_init(void)
+{
+	rtascons_put_char_token = rtas_token("put-term-char");
+	if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
+		return -EIO;
+	rtascons_get_char_token = rtas_token("get-term-char");
+	if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
+		return -EIO;
+
+	hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops );
+	add_preferred_console("hvc", 0, NULL);
+	return 0;
+}
+console_initcall(hvc_rtas_console_init);
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c
index f5212eb..9add81ce 100644
--- a/drivers/char/hvc_vio.c
+++ b/drivers/char/hvc_vio.c
@@ -31,10 +31,13 @@
 
 #include <linux/types.h>
 #include <linux/init.h>
+
 #include <asm/hvconsole.h>
 #include <asm/vio.h>
 #include <asm/prom.h>
 
+#include "hvc_console.h"
+
 char hvc_driver_name[] = "hvc_console";
 
 static struct vio_device_id hvc_driver_table[] __devinitdata = {
@@ -48,6 +51,14 @@
 	unsigned long got;
 	int i;
 
+	/*
+	 * Vio firmware will read up to SIZE_VIO_GET_CHARS at its own discretion
+	 * so we play safe and avoid the situation where got > count which could
+	 * overload the flip buffer.
+	 */
+	if (count < SIZE_VIO_GET_CHARS)
+		return -EAGAIN;
+
 	got = hvc_get_chars(vtermno, buf, count);
 
 	/*
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index f7ac318..327b00c 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -439,7 +439,6 @@
 	char buf[HVCS_BUFF_LEN] __ALIGNED__;
 	unsigned long flags;
 	int got = 0;
-	int i;
 
 	spin_lock_irqsave(&hvcsd->lock, flags);
 
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index c85b87c..3e677c4 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -440,7 +440,7 @@
 
 
 #if defined(CONFIG_PPC_CHRP) && defined(CONFIG_PPC32)
-	if(_machine == _MACH_chrp && _chrp_type == _CHRP_Pegasos) {
+	if(machine_is(chrp) && _chrp_type == _CHRP_Pegasos) {
 		hwif->irq = hwif->channel ? 15 : 14;
 	}
 #endif
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 5013b12..78e30f8 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -1677,7 +1677,7 @@
 void __init
 pmac_ide_probe(void)
 {
-	if (_machine != _MACH_Pmac)
+	if (!machine_is(powermac))
 		return;
 
 #ifdef CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index a86beeb..1922287 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -3529,7 +3529,7 @@
 static int ohci1394_pci_resume (struct pci_dev *pdev)
 {
 #ifdef CONFIG_PPC_PMAC
-	if (_machine == _MACH_Pmac) {
+	if (machine_is(powermac)) {
 		struct device_node *of_node;
 
 		/* Re-enable 1394 */
@@ -3548,7 +3548,7 @@
 static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
 {
 #ifdef CONFIG_PPC_PMAC
-	if (_machine == _MACH_Pmac) {
+	if (machine_is(powermac)) {
 		struct device_node *of_node;
 
 		/* Disable 1394 */
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 34fcaba..259fd89 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -42,6 +42,7 @@
 #include <asm/semaphore.h>
 #ifdef CONFIG_PPC
 #include <asm/prom.h>
+#include <asm/machdep.h>
 #endif
 
 
@@ -294,7 +295,7 @@
 	int i;
 
 #ifdef CONFIG_PPC32
-	if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
+	if (!machine_is(chrp) && !machine_is(powermac))
 		return 0;
 #endif
 #ifdef CONFIG_MAC
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index f5779a7..394334e 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -1206,8 +1206,8 @@
 static int __init adbhid_init(void)
 {
 #ifndef CONFIG_MAC
-	if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
-	    return 0;
+	if (!machine_is(chrp) && !machine_is(powermac))
+		return 0;
 #endif
 
 	led_request.complete = 1;
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 8dbf285..53c1c79 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -839,8 +839,8 @@
 		media_bays[i].cd_index		= -1;
 #endif
 	}
-	if (_machine != _MACH_Pmac)
-		return -ENODEV;
+	if (!machine_is(powermac))
+		return 0;
 
 	macio_register_driver(&media_bay_driver);	
 
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c
index 522e9dd..d9e3cad 100644
--- a/drivers/media/video/planb.c
+++ b/drivers/media/video/planb.c
@@ -2156,7 +2156,7 @@
 	struct pci_dev 		*pdev;
 	int rc;
 
-	if (_machine != _MACH_Pmac)
+	if (!machine_is(powermac))
 		return 0;
 
 	planb_devices = find_devices("planb");
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
index 599b68d..51e39dc 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/8390.h
@@ -134,7 +134,7 @@
 #define inb_p(_p)	inb(_p)
 #define outb_p(_v,_p)	outb(_v,_p)
 
-#elif defined(CONFIG_NET_CBUS) || defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE)
+#elif defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE)
 #define EI_SHIFT(x)	(ei_local->reg_offset[x])
 #else
 #define EI_SHIFT(x)	(x)
diff --git a/drivers/net/acenic_firmware.h b/drivers/net/acenic_firmware.h
index 6d625d5..d7882dd 100644
--- a/drivers/net/acenic_firmware.h
+++ b/drivers/net/acenic_firmware.h
@@ -4397,7 +4397,7 @@
 0x3c010001, 0x220821, 0xac317e30, 0x8fbf0024, 
 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 
 0x8fb00010, 0x3e00008, 0x27bd0028, 0x0 };
-static u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
+static u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __devinitdata = {
 0x24486561, 0x6465723a, 0x202f7072, 
 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
 0x2f2e2f6e, 0x69632f66, 0x772f636f, 0x6d6d6f6e, 
@@ -4571,7 +4571,7 @@
 0x0, 0x14c38, 0x14c38, 0x14b80, 
 0x14bc4, 0x14c38, 0x14c38, 0x0, 
 0x0, 0x0 };
-static u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __initdata = {
+static u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __devinitdata = {
 0x416c7465, 
 0x6f6e2041, 0x63654e49, 0x43205600, 0x416c7465, 
 0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242, 
@@ -4612,7 +4612,7 @@
 #define tigon2FwSbssLen 0xcc
 #define tigon2FwBssAddr 0x00016f50
 #define tigon2FwBssLen 0x20c0
-static u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
+static u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __devinitdata = {
 0x0, 
 0x10000003, 0x0, 0xd, 0xd, 
 0x3c1d0001, 0x8fbd6d20, 0x3a0f021, 0x3c100000, 
@@ -9154,7 +9154,7 @@
 0x24020001, 0x8f430328, 0x1021, 0x24630001, 
 0x3e00008, 0xaf430328, 0x3e00008, 0x0, 
 0x0, 0x0, 0x0, 0x0 };
-static u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
+static u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __devinitdata = {
 0x24486561, 0x6465723a, 0x202f7072, 
 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 
 0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 
@@ -9425,7 +9425,7 @@
 0x14ed8, 0x14b8c, 0x14bd8, 0x14c24, 
 0x14ed8, 0x7365746d, 0x61636163, 0x74000000, 
 0x0, 0x0 };
-static u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __initdata = {
+static u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __devinitdata = {
 0x1, 
 0x1, 0x1, 0xc001fc, 0x3ffc, 
 0xc00000, 0x416c7465, 0x6f6e2041, 0x63654e49, 
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index c3267e4..15032f2 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -1339,6 +1339,9 @@
 	if (netif_running(dev))
 		return -EBUSY;
 
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EINVAL;
+
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 
 	spin_lock_irq(&bp->lock);
@@ -1876,6 +1879,12 @@
 	bp->dev->dev_addr[3] = eeprom[80];
 	bp->dev->dev_addr[4] = eeprom[83];
 	bp->dev->dev_addr[5] = eeprom[82];
+
+	if (!is_valid_ether_addr(&bp->dev->dev_addr[0])){
+		printk(KERN_ERR PFX "Invalid MAC address found in EEPROM\n");
+		return -EINVAL;
+	}
+
 	memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len);
 
 	bp->phy_addr = eeprom[90] & 0x1f;
@@ -2033,6 +2042,11 @@
 
 	pci_save_state(bp->pdev);
 
+	/* Chip reset provides power to the b44 MAC & PCI cores, which 
+	 * is necessary for MAC register access.
+	 */ 
+	b44_chip_reset(bp);
+
 	printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name);
 	for (i = 0; i < 6; i++)
 		printk("%2.2x%c", dev->dev_addr[i],
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index f3f5825..6a40707 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2294,6 +2294,34 @@
 	port->sm_vars |= AD_PORT_BEGIN;
 }
 
+/*
+ * set link state for bonding master: if we have an active partnered
+ * aggregator, we're up, if not, we're down.  Presumes that we cannot
+ * have an active aggregator if there are no slaves with link up.
+ *
+ * Called by bond_set_carrier(). Return zero if carrier state does not
+ * change, nonzero if it does.
+ */
+int bond_3ad_set_carrier(struct bonding *bond)
+{
+	struct aggregator *agg;
+
+	agg = __get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator));
+	if (agg && MAC_ADDRESS_COMPARE(&agg->partner_system, &null_mac_addr)) {
+		if (!netif_carrier_ok(bond->dev)) {
+			netif_carrier_on(bond->dev);
+			return 1;
+		}
+		return 0;
+	}
+
+	if (netif_carrier_ok(bond->dev)) {
+		netif_carrier_off(bond->dev);
+		return 1;
+	}
+	return 0;
+}
+
 /**
  * bond_3ad_get_active_agg_info - get information of the active aggregator
  * @bond: bonding struct to work on
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index 5ee2cef..6ad5ad6 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -283,5 +283,6 @@
 int  bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info);
 int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev);
 int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev);
+int bond_3ad_set_carrier(struct bonding *bond);
 #endif //__BOND_3AD_H__
 
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index f13a539..55d2367 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -559,6 +559,42 @@
 /*------------------------------- Link status -------------------------------*/
 
 /*
+ * Set the carrier state for the master according to the state of its
+ * slaves.  If any slaves are up, the master is up.  In 802.3ad mode,
+ * do special 802.3ad magic.
+ *
+ * Returns zero if carrier state does not change, nonzero if it does.
+ */
+static int bond_set_carrier(struct bonding *bond)
+{
+	struct slave *slave;
+	int i;
+
+	if (bond->slave_cnt == 0)
+		goto down;
+
+	if (bond->params.mode == BOND_MODE_8023AD)
+		return bond_3ad_set_carrier(bond);
+
+	bond_for_each_slave(bond, slave, i) {
+		if (slave->link == BOND_LINK_UP) {
+			if (!netif_carrier_ok(bond->dev)) {
+				netif_carrier_on(bond->dev);
+				return 1;
+			}
+			return 0;
+		}
+	}
+
+down:
+	if (netif_carrier_ok(bond->dev)) {
+		netif_carrier_off(bond->dev);
+		return 1;
+	}
+	return 0;
+}
+
+/*
  * Get link speed and duplex from the slave's base driver
  * using ethtool. If for some reason the call fails or the
  * values are invalid, fake speed and duplex to 100/Full
@@ -1074,10 +1110,24 @@
 void bond_select_active_slave(struct bonding *bond)
 {
 	struct slave *best_slave;
+	int rv;
 
 	best_slave = bond_find_best_slave(bond);
 	if (best_slave != bond->curr_active_slave) {
 		bond_change_active_slave(bond, best_slave);
+		rv = bond_set_carrier(bond);
+		if (!rv)
+			return;
+
+		if (netif_carrier_ok(bond->dev)) {
+			printk(KERN_INFO DRV_NAME
+			       ": %s: first active interface up!\n",
+			       bond->dev->name);
+		} else {
+			printk(KERN_INFO DRV_NAME ": %s: "
+			       "now running without any active interface !\n",
+			       bond->dev->name);
+		}
 	}
 }
 
@@ -1458,10 +1508,14 @@
 		if (((!bond->curr_active_slave) ||
 		     (bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) &&
 		    (new_slave->link != BOND_LINK_DOWN)) {
-			dprintk("This is the first active slave\n");
 			/* first slave or no active slave yet, and this link
 			   is OK, so make this interface the active one */
 			bond_change_active_slave(bond, new_slave);
+			printk(KERN_INFO DRV_NAME
+			       ": %s: first active interface up!\n",
+			       bond->dev->name);
+			netif_carrier_on(bond->dev);
+
 		} else {
 			dprintk("This is just a backup slave\n");
 			bond_set_slave_inactive_flags(new_slave);
@@ -1517,6 +1571,8 @@
 		break;
 	} /* switch(bond_mode) */
 
+	bond_set_carrier(bond);
+
 	write_unlock_bh(&bond->lock);
 
 	res = bond_create_slave_symlinks(bond_dev, slave_dev);
@@ -1656,18 +1712,12 @@
 		bond_alb_deinit_slave(bond, slave);
 	}
 
-	if (oldcurrent == slave) {
+	if (oldcurrent == slave)
 		bond_select_active_slave(bond);
 
-		if (!bond->curr_active_slave) {
-			printk(KERN_INFO DRV_NAME
-			       ": %s: now running without any active "
-			       "interface !\n",
-			       bond_dev->name);
-		}
-	}
-
 	if (bond->slave_cnt == 0) {
+		bond_set_carrier(bond);
+
 		/* if the last slave was removed, zero the mac address
 		 * of the master so it will be set by the application
 		 * to the mac address of the first slave
@@ -1751,6 +1801,8 @@
 
 	write_lock_bh(&bond->lock);
 
+	netif_carrier_off(bond_dev);
+
 	if (bond->slave_cnt == 0) {
 		goto out;
 	}
@@ -2187,15 +2239,9 @@
 
 		bond_select_active_slave(bond);
 
-		if (oldcurrent && !bond->curr_active_slave) {
-			printk(KERN_INFO DRV_NAME
-			       ": %s: now running without any active "
-			       "interface !\n",
-			       bond_dev->name);
-		}
-
 		write_unlock(&bond->curr_slave_lock);
-	}
+	} else
+		bond_set_carrier(bond);
 
 re_arm:
 	if (bond->params.miimon) {
@@ -2499,13 +2545,6 @@
 
 		bond_select_active_slave(bond);
 
-		if (oldcurrent && !bond->curr_active_slave) {
-			printk(KERN_INFO DRV_NAME
-			       ": %s: now running without any active "
-			       "interface !\n",
-			       bond_dev->name);
-		}
-
 		write_unlock(&bond->curr_slave_lock);
 	}
 
@@ -2579,12 +2618,15 @@
 					bond->current_arp_slave = NULL;
 				}
 
+				bond_set_carrier(bond);
+
 				if (slave == bond->curr_active_slave) {
 					printk(KERN_INFO DRV_NAME
 					       ": %s: %s is up and now the "
 					       "active interface\n",
 					       bond_dev->name,
 					       slave->dev->name);
+					netif_carrier_on(bond->dev);
 				} else {
 					printk(KERN_INFO DRV_NAME
 					       ": %s: backup interface %s is "
@@ -2844,7 +2886,8 @@
 			   (curr) ? curr->dev->name : "None");
 	}
 
-	seq_printf(seq, "MII Status: %s\n", (curr) ? "up" : "down");
+	seq_printf(seq, "MII Status: %s\n", netif_carrier_ok(bond->dev) ?
+		   "up" : "down");
 	seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon);
 	seq_printf(seq, "Up Delay (ms): %d\n",
 		   bond->params.updelay * bond->params.miimon);
@@ -4531,6 +4574,8 @@
 	if (newbond)
 		*newbond = bond_dev->priv;
 
+	netif_carrier_off(bond_dev);
+
 	rtnl_unlock(); /* allows sysfs registration of net device */
 	res = bond_create_sysfs_entry(bond_dev->priv);
 	goto done;
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index ce9dc9b..0bdfe2c 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -22,8 +22,8 @@
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION	"3.0.2"
-#define DRV_RELDATE	"February 21, 2006"
+#define DRV_VERSION	"3.0.3"
+#define DRV_RELDATE	"March 23, 2006"
 #define DRV_NAME	"bonding"
 #define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
 
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
index 77f104a..fbc2d21 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -299,10 +299,7 @@
 	int i;
 	int err;
 
-	if (RX_BUF_COUNT > 192 || TX_BUF_COUNT > 192) {
-		static void __too_many_rx_or_tx_buffers(void);
-		__too_many_rx_or_tx_buffers();
-	}
+	BUILD_BUG_ON(RX_BUF_COUNT > 192 || TX_BUF_COUNT > 192);
 
 	printk(KERN_INFO "IXP2000 MSF ethernet driver %s\n", DRV_MODULE_VERSION);
 
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 8d49998..7826afb 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -226,7 +226,7 @@
 				 NATSEMI_PG1_NREGS)
 #define NATSEMI_REGS_VER	1 /* v1 added RFDR registers */
 #define NATSEMI_REGS_SIZE	(NATSEMI_NREGS * sizeof(u32))
-#define NATSEMI_EEPROM_SIZE	24 /* 12 16-bit values */
+#define NATSEMI_DEF_EEPROM_SIZE	24 /* 12 16-bit values */
 
 /* Buffer sizes:
  * The nic writes 32-bit values, even if the upper bytes of
@@ -714,6 +714,8 @@
 	unsigned int iosize;
 	spinlock_t lock;
 	u32 msg_enable;
+	/* EEPROM data */
+	int eeprom_size;
 };
 
 static void move_int_phy(struct net_device *dev, int addr);
@@ -890,6 +892,7 @@
 	np->msg_enable = (debug >= 0) ? (1<<debug)-1 : NATSEMI_DEF_MSG;
 	np->hands_off = 0;
 	np->intr_status = 0;
+	np->eeprom_size = NATSEMI_DEF_EEPROM_SIZE;
 
 	/* Initial port:
 	 * - If the nic was configured to use an external phy and if find_mii
@@ -2582,7 +2585,8 @@
 
 static int get_eeprom_len(struct net_device *dev)
 {
-	return NATSEMI_EEPROM_SIZE;
+	struct netdev_private *np = netdev_priv(dev);
+	return np->eeprom_size;
 }
 
 static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
@@ -2669,15 +2673,20 @@
 static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	u8 eebuf[NATSEMI_EEPROM_SIZE];
+	u8 *eebuf;
 	int res;
 
+	eebuf = kmalloc(np->eeprom_size, GFP_KERNEL);
+	if (!eebuf)
+		return -ENOMEM;
+
 	eeprom->magic = PCI_VENDOR_ID_NS | (PCI_DEVICE_ID_NS_83815<<16);
 	spin_lock_irq(&np->lock);
 	res = netdev_get_eeprom(dev, eebuf);
 	spin_unlock_irq(&np->lock);
 	if (!res)
 		memcpy(data, eebuf+eeprom->offset, eeprom->len);
+	kfree(eebuf);
 	return res;
 }
 
@@ -3033,9 +3042,10 @@
 	int i;
 	u16 *ebuf = (u16 *)buf;
 	void __iomem * ioaddr = ns_ioaddr(dev);
+	struct netdev_private *np = netdev_priv(dev);
 
 	/* eeprom_read reads 16 bits, and indexes by 16 bits */
-	for (i = 0; i < NATSEMI_EEPROM_SIZE/2; i++) {
+	for (i = 0; i < np->eeprom_size/2; i++) {
 		ebuf[i] = eeprom_read(ioaddr, i);
 		/* The EEPROM itself stores data bit-swapped, but eeprom_read
 		 * reads it back "sanely". So we swap it back here in order to
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index aa55813..1cc94b2 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -35,6 +35,7 @@
 #include <linux/spinlock.h>
 #include <linux/ethtool.h>
 #include <linux/netdevice.h>
+#include <linux/crc32.h>
 #include "../8390.h"
 
 #include <pcmcia/cs_types.h>
@@ -1682,17 +1683,67 @@
 	return &ei_local->stat;
 }
 
+/*
+ * Form the 64 bit 8390 multicast table from the linked list of addresses
+ * associated with this dev structure.
+ */
+ 
+static inline void make_mc_bits(u8 *bits, struct net_device *dev)
+{
+	struct dev_mc_list *dmi;
+	u32 crc;
+
+	for (dmi=dev->mc_list; dmi; dmi=dmi->next) {
+		
+		crc = ether_crc(ETH_ALEN, dmi->dmi_addr);
+		/* 
+		 * The 8390 uses the 6 most significant bits of the
+		 * CRC to index the multicast table.
+		 */
+		bits[crc>>29] |= (1<<((crc>>26)&7));
+	}
+}
+
 /**
  * do_set_multicast_list - set/clear multicast filter
  * @dev: net device for which multicast filter is adjusted
  *
- *	Set or clear the multicast filter for this adaptor. May be called
- *	from a BH in 2.1.x. Must be called with lock held. 
+ *	Set or clear the multicast filter for this adaptor.
+ *	Must be called with lock held. 
  */
  
 static void do_set_multicast_list(struct net_device *dev)
 {
 	long e8390_base = dev->base_addr;
+	int i;
+	struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev);
+
+	if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
+		memset(ei_local->mcfilter, 0, 8);
+		if (dev->mc_list)
+			make_mc_bits(ei_local->mcfilter, dev);
+	} else {
+		/* set to accept-all */
+		memset(ei_local->mcfilter, 0xFF, 8);
+	}
+
+	/* 
+	 * DP8390 manuals don't specify any magic sequence for altering
+	 * the multicast regs on an already running card. To be safe, we
+	 * ensure multicast mode is off prior to loading up the new hash
+	 * table. If this proves to be not enough, we can always resort
+	 * to stopping the NIC, loading the table and then restarting.
+	 */
+	 
+	if (netif_running(dev))
+		outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
+
+	outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
+	for(i = 0; i < 8; i++) 
+	{
+		outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
+	}
+	outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
 
   	if(dev->flags&IFF_PROMISC)
   		outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR);
@@ -1794,12 +1845,6 @@
 		if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
 			printk(KERN_ERR "Hw. address read/write mismap %d\n",i);
 	}
-	/*
-	 * Initialize the multicast list to accept-all.  If we enable multicast
-	 * the higher levels can do the filtering.
-	 */
-	for (i = 0; i < 8; i++)
-		outb_p(0xff, e8390_base + EN1_MULT + i);
 
 	outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
 	outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 9595f74..07c31f1 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -1167,8 +1167,8 @@
 	 * station address PROM at the base address and programmed into the
 	 * "Physical Address Registers" CSR12-14.
 	 * As a precautionary measure, we read the PROM values and complain if
-	 * they disagree with the CSRs.  Either way, we use the CSR values, and
-	 * double check that they are valid.
+	 * they disagree with the CSRs.  If they miscompare, and the PROM addr
+	 * is valid, then the PROM addr is used.
 	 */
 	for (i = 0; i < 3; i++) {
 		unsigned int val;
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 1f5975a..43f5e86 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -1442,7 +1442,7 @@
 	case SPIDER_NET_GRFAFLLINT: /* fallthrough */
 	case SPIDER_NET_GRMFLLINT:
 		if (netif_msg_intr(card) && net_ratelimit())
-			pr_err("Spider RX RAM full, incoming packets "
+			pr_debug("Spider RX RAM full, incoming packets "
 			       "might be discarded!\n");
 		spider_net_rx_irq_off(card);
 		tasklet_schedule(&card->rxram_full_tl);
@@ -2086,7 +2086,7 @@
 
 	spider_net_setup_netdev_ops(netdev);
 
-	netdev->features = 0;
+	netdev->features = NETIF_F_HW_CSUM;
 	/* some time: NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
 	 *		NETIF_F_HW_VLAN_FILTER */
 
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index b547332..964c096 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -69,8 +69,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.54"
-#define DRV_MODULE_RELDATE	"Mar 23, 2006"
+#define DRV_MODULE_VERSION	"3.55"
+#define DRV_MODULE_RELDATE	"Mar 27, 2006"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -497,33 +497,40 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&tp->indirect_lock, flags);
-	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
-	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+	if (tp->write32 != tg3_write_indirect_reg32) {
+		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
+		tw32_f(TG3PCI_MEM_WIN_DATA, val);
 
-	/* Always leave this as zero. */
-	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+		/* Always leave this as zero. */
+		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+	} else {
+		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+
+		/* Always leave this as zero. */
+		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+	}
 	spin_unlock_irqrestore(&tp->indirect_lock, flags);
 }
 
-static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val)
-{
-	/* If no workaround is needed, write to mem space directly */
-	if (tp->write32 != tg3_write_indirect_reg32)
-		tw32(NIC_SRAM_WIN_BASE + off, val);
-	else
-		tg3_write_mem(tp, off, val);
-}
-
 static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&tp->indirect_lock, flags);
-	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
-	pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+	if (tp->write32 != tg3_write_indirect_reg32) {
+		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
+		*val = tr32(TG3PCI_MEM_WIN_DATA);
 
-	/* Always leave this as zero. */
-	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+		/* Always leave this as zero. */
+		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
+	} else {
+		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
+		pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
+
+		/* Always leave this as zero. */
+		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+	}
 	spin_unlock_irqrestore(&tp->indirect_lock, flags);
 }
 
@@ -1367,12 +1374,12 @@
 		}
 	}
 
+	tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
+
 	/* Finally, set the new power state. */
 	pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
 	udelay(100);	/* Delay after power state change */
 
-	tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
-
 	return 0;
 }
 
@@ -3600,7 +3607,7 @@
 					  int len)
 {
 #if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64)
-	if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
+	if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG)
 		return (((u64) mapping + len) > DMA_40BIT_MASK);
 	return 0;
 #else
@@ -6461,6 +6468,9 @@
 {
 	struct tg3 *tp = (struct tg3 *) __opaque;
 
+	if (tp->irq_sync)
+		goto restart_timer;
+
 	spin_lock(&tp->lock);
 
 	if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
@@ -6537,11 +6547,11 @@
 		if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
 			u32 val;
 
-			tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX,
-					   FWCMD_NICDRV_ALIVE2);
-			tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
+			tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
+				      FWCMD_NICDRV_ALIVE2);
+			tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
 			/* 5 seconds timeout */
-			tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
+			tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
 			val = tr32(GRC_RX_CPU_EVENT);
 			val |= (1 << 14);
 			tw32(GRC_RX_CPU_EVENT, val);
@@ -6551,6 +6561,7 @@
 
 	spin_unlock(&tp->lock);
 
+restart_timer:
 	tp->timer.expires = jiffies + tp->timer_offset;
 	add_timer(&tp->timer);
 }
@@ -8399,8 +8410,11 @@
 		}
 		mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
 			   MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
-		if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
+		if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
 			mac_mode &= ~MAC_MODE_LINK_POLARITY;
+			tg3_writephy(tp, MII_TG3_EXT_CTRL,
+				     MII_TG3_EXT_CTRL_LNK3_LED_MODE);
+		}
 		tw32(MAC_MODE, mac_mode);
 	}
 	else
@@ -10531,6 +10545,7 @@
 {
 	struct net_device *dev = tp->dev;
 	u32 hi, lo, mac_offset;
+	int addr_ok = 0;
 
 #ifdef CONFIG_SPARC64
 	if (!tg3_get_macaddr_sparc(tp))
@@ -10560,29 +10575,34 @@
 		dev->dev_addr[3] = (lo >> 16) & 0xff;
 		dev->dev_addr[4] = (lo >>  8) & 0xff;
 		dev->dev_addr[5] = (lo >>  0) & 0xff;
-	}
-	/* Next, try NVRAM. */
-	else if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) &&
-		 !tg3_nvram_read(tp, mac_offset + 0, &hi) &&
-		 !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
-		dev->dev_addr[0] = ((hi >> 16) & 0xff);
-		dev->dev_addr[1] = ((hi >> 24) & 0xff);
-		dev->dev_addr[2] = ((lo >>  0) & 0xff);
-		dev->dev_addr[3] = ((lo >>  8) & 0xff);
-		dev->dev_addr[4] = ((lo >> 16) & 0xff);
-		dev->dev_addr[5] = ((lo >> 24) & 0xff);
-	}
-	/* Finally just fetch it out of the MAC control regs. */
-	else {
-		hi = tr32(MAC_ADDR_0_HIGH);
-		lo = tr32(MAC_ADDR_0_LOW);
 
-		dev->dev_addr[5] = lo & 0xff;
-		dev->dev_addr[4] = (lo >> 8) & 0xff;
-		dev->dev_addr[3] = (lo >> 16) & 0xff;
-		dev->dev_addr[2] = (lo >> 24) & 0xff;
-		dev->dev_addr[1] = hi & 0xff;
-		dev->dev_addr[0] = (hi >> 8) & 0xff;
+		/* Some old bootcode may report a 0 MAC address in SRAM */
+		addr_ok = is_valid_ether_addr(&dev->dev_addr[0]);
+	}
+	if (!addr_ok) {
+		/* Next, try NVRAM. */
+		if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) &&
+		    !tg3_nvram_read(tp, mac_offset + 0, &hi) &&
+		    !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
+			dev->dev_addr[0] = ((hi >> 16) & 0xff);
+			dev->dev_addr[1] = ((hi >> 24) & 0xff);
+			dev->dev_addr[2] = ((lo >>  0) & 0xff);
+			dev->dev_addr[3] = ((lo >>  8) & 0xff);
+			dev->dev_addr[4] = ((lo >> 16) & 0xff);
+			dev->dev_addr[5] = ((lo >> 24) & 0xff);
+		}
+		/* Finally just fetch it out of the MAC control regs. */
+		else {
+			hi = tr32(MAC_ADDR_0_HIGH);
+			lo = tr32(MAC_ADDR_0_LOW);
+
+			dev->dev_addr[5] = lo & 0xff;
+			dev->dev_addr[4] = (lo >> 8) & 0xff;
+			dev->dev_addr[3] = (lo >> 16) & 0xff;
+			dev->dev_addr[2] = (lo >> 24) & 0xff;
+			dev->dev_addr[1] = hi & 0xff;
+			dev->dev_addr[0] = (hi >> 8) & 0xff;
+		}
 	}
 
 	if (!is_valid_ether_addr(&dev->dev_addr[0])) {
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index d1a86a0..f560941 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -4160,7 +4160,7 @@
     ** If the address starts with 00 a0, we have to bit-reverse
     ** each byte of the address.
     */
-    if ( (_machine & _MACH_Pmac) &&
+    if ( machine_is(powermac) &&
 	 (dev->dev_addr[0] == 0) &&
 	 (dev->dev_addr[1] == 0xa0) )
     {
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 241871589..a9b2150 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -1085,6 +1085,25 @@
 	else
 	    iowrite8(ioread8(ioaddr + ChipCmd1) & ~Cmd1FDuplex,
 		   ioaddr + ChipCmd1);
+	if (debug > 1)
+		printk(KERN_INFO "%s: force_media %d, carrier %d\n", dev->name,
+			rp->mii_if.force_media, netif_carrier_ok(dev));
+}
+
+/* Called after status of force_media possibly changed */
+void rhine_set_carrier(struct mii_if_info *mii)
+{
+	if (mii->force_media) {
+		/* autoneg is off: Link is always assumed to be up */
+		if (!netif_carrier_ok(mii->dev))
+			netif_carrier_on(mii->dev);
+	}
+	else	/* Let MMI library update carrier status */
+		rhine_check_media(mii->dev, 0);
+	if (debug > 1)
+		printk(KERN_INFO "%s: force_media %d, carrier %d\n",
+		       mii->dev->name, mii->force_media,
+		       netif_carrier_ok(mii->dev));
 }
 
 static void rhine_check_media_task(struct net_device *dev)
@@ -1782,6 +1801,7 @@
 	spin_lock_irq(&rp->lock);
 	rc = mii_ethtool_sset(&rp->mii_if, cmd);
 	spin_unlock_irq(&rp->lock);
+	rhine_set_carrier(&rp->mii_if);
 
 	return rc;
 }
@@ -1869,6 +1889,7 @@
 	spin_lock_irq(&rp->lock);
 	rc = generic_mii_ioctl(&rp->mii_if, if_mii(rq), cmd, NULL);
 	spin_unlock_irq(&rp->lock);
+	rhine_set_carrier(&rp->mii_if);
 
 	return rc;
 }
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index fd17aa8..f85e301 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -309,7 +309,10 @@
 	  Say Y here to support the Airport 802.11b wireless Ethernet hardware
 	  built into the Macintosh iBook and other recent PowerPC-based
 	  Macintosh machines. This is essentially a Lucent Orinoco card with 
-	  a non-standard interface
+	  a non-standard interface.
+
+	  This driver does not support the Airport Extreme (802.11b/g). Use
+	  the BCM43xx driver for Airport Extreme cards.
 
 config PLX_HERMES
 	tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)"
@@ -401,6 +404,7 @@
 config PCMCIA_SPECTRUM
 	tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
 	depends on NET_RADIO && PCMCIA && HERMES
+	select FW_LOADER
 	---help---
 
 	  This is a driver for 802.11b cards using RAM-loadable Symbol
@@ -500,6 +504,7 @@
 	  will be called prism54.ko.
 
 source "drivers/net/wireless/hostap/Kconfig"
+source "drivers/net/wireless/bcm43xx/Kconfig"
 
 # yes, this works even when no drivers are selected
 config NET_WIRELESS
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 3a6f7ba..c867798 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -35,6 +35,7 @@
 obj-$(CONFIG_PRISM54)		+= prism54/
 
 obj-$(CONFIG_HOSTAP)		+= hostap/
+obj-$(CONFIG_BCM43XX)		+= bcm43xx/
 
 # 16-bit wireless PCMCIA client drivers
 obj-$(CONFIG_PCMCIA_RAYCS)	+= ray_cs.o
diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig
new file mode 100644
index 0000000..4184656
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/Kconfig
@@ -0,0 +1,62 @@
+config BCM43XX
+	tristate "Broadcom BCM43xx wireless support"
+	depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL
+	select FW_LOADER
+	---help---
+	  This is an experimental driver for the Broadcom 43xx wireless chip,
+	  found in the Apple Airport Extreme and various other devices.
+
+config BCM43XX_DEBUG
+	bool "Broadcom BCM43xx debugging (RECOMMENDED)"
+	depends on BCM43XX
+	default y
+	---help---
+	  Broadcom 43xx debugging messages.
+	  Say Y, because the driver is still very experimental and
+	  this will help you get it running.
+
+config BCM43XX_DMA
+	bool
+config BCM43XX_PIO
+	bool
+
+choice
+	prompt "BCM43xx data transfer mode"
+	depends on BCM43XX
+	default BCM43XX_DMA_AND_PIO_MODE
+
+config BCM43XX_DMA_AND_PIO_MODE
+	bool "DMA + PIO"
+	select BCM43XX_DMA
+	select BCM43XX_PIO
+	---help---
+	  Include both, Direct Memory Access (DMA) and Programmed I/O (PIO)
+	  data transfer modes.
+	  The actually used mode is selectable through the module
+	  parameter "pio". If the module parameter is pio=0, DMA is used.
+	  Otherwise PIO is used. DMA is default.
+
+	  If unsure, choose this option.
+
+config BCM43XX_DMA_MODE
+	bool "DMA (Direct Memory Access) only"
+	select BCM43XX_DMA
+	---help---
+	  Only include Direct Memory Access (DMA).
+	  This reduces the size of the driver module, by omitting the PIO code.
+
+config BCM43XX_PIO_MODE
+	bool "PIO (Programmed I/O) only"
+	select BCM43XX_PIO
+	---help---
+	  Only include Programmed I/O (PIO).
+	  This reduces the size of the driver module, by omitting the DMA code.
+	  Please note that PIO transfers are slow (compared to DMA).
+
+	  Also note that not all devices of the 43xx series support PIO.
+	  The 4306 (Apple Airport Extreme and others) supports PIO, while
+	  the 4318 is known to _not_ support PIO.
+
+	  Only use PIO, if DMA does not work for you.
+
+endchoice
diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile
new file mode 100644
index 0000000..bb5220c
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/Makefile
@@ -0,0 +1,12 @@
+obj-$(CONFIG_BCM43XX) += bcm43xx.o
+bcm43xx-obj-$(CONFIG_BCM43XX_DEBUG) += bcm43xx_debugfs.o
+
+bcm43xx-obj-$(CONFIG_BCM43XX_DMA) += bcm43xx_dma.o
+bcm43xx-obj-$(CONFIG_BCM43XX_PIO) += bcm43xx_pio.o
+
+bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \
+		bcm43xx_radio.o bcm43xx_phy.o \
+		bcm43xx_power.o bcm43xx_wx.o \
+		bcm43xx_leds.o bcm43xx_ethtool.o \
+		bcm43xx_xmit.o bcm43xx_sysfs.o \
+		$(bcm43xx-obj-y)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
new file mode 100644
index 0000000..dcadd29
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -0,0 +1,926 @@
+#ifndef BCM43xx_H_
+#define BCM43xx_H_
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/stringify.h>
+#include <linux/pci.h>
+#include <net/ieee80211.h>
+#include <net/ieee80211softmac.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+
+
+#include "bcm43xx_debugfs.h"
+#include "bcm43xx_leds.h"
+#include "bcm43xx_sysfs.h"
+
+
+#define PFX				KBUILD_MODNAME ": "
+
+#define BCM43xx_SWITCH_CORE_MAX_RETRIES	50
+#define BCM43xx_IRQWAIT_MAX_RETRIES	50
+
+#define BCM43xx_IO_SIZE			8192
+
+/* Active Core PCI Configuration Register. */
+#define BCM43xx_PCICFG_ACTIVE_CORE	0x80
+/* SPROM control register. */
+#define BCM43xx_PCICFG_SPROMCTL		0x88
+/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */
+#define BCM43xx_PCICFG_ICR		0x94
+
+/* MMIO offsets */
+#define BCM43xx_MMIO_DMA1_REASON	0x20
+#define BCM43xx_MMIO_DMA1_IRQ_MASK	0x24
+#define BCM43xx_MMIO_DMA2_REASON	0x28
+#define BCM43xx_MMIO_DMA2_IRQ_MASK	0x2C
+#define BCM43xx_MMIO_DMA3_REASON	0x30
+#define BCM43xx_MMIO_DMA3_IRQ_MASK	0x34
+#define BCM43xx_MMIO_DMA4_REASON	0x38
+#define BCM43xx_MMIO_DMA4_IRQ_MASK	0x3C
+#define BCM43xx_MMIO_STATUS_BITFIELD	0x120
+#define BCM43xx_MMIO_STATUS2_BITFIELD	0x124
+#define BCM43xx_MMIO_GEN_IRQ_REASON	0x128
+#define BCM43xx_MMIO_GEN_IRQ_MASK	0x12C
+#define BCM43xx_MMIO_RAM_CONTROL	0x130
+#define BCM43xx_MMIO_RAM_DATA		0x134
+#define BCM43xx_MMIO_PS_STATUS		0x140
+#define BCM43xx_MMIO_RADIO_HWENABLED_HI	0x158
+#define BCM43xx_MMIO_SHM_CONTROL	0x160
+#define BCM43xx_MMIO_SHM_DATA		0x164
+#define BCM43xx_MMIO_SHM_DATA_UNALIGNED	0x166
+#define BCM43xx_MMIO_XMITSTAT_0		0x170
+#define BCM43xx_MMIO_XMITSTAT_1		0x174
+#define BCM43xx_MMIO_REV3PLUS_TSF_LOW	0x180 /* core rev >= 3 only */
+#define BCM43xx_MMIO_REV3PLUS_TSF_HIGH	0x184 /* core rev >= 3 only */
+#define BCM43xx_MMIO_DMA1_BASE		0x200
+#define BCM43xx_MMIO_DMA2_BASE		0x220
+#define BCM43xx_MMIO_DMA3_BASE		0x240
+#define BCM43xx_MMIO_DMA4_BASE		0x260
+#define BCM43xx_MMIO_PIO1_BASE		0x300
+#define BCM43xx_MMIO_PIO2_BASE		0x310
+#define BCM43xx_MMIO_PIO3_BASE		0x320
+#define BCM43xx_MMIO_PIO4_BASE		0x330
+#define BCM43xx_MMIO_PHY_VER		0x3E0
+#define BCM43xx_MMIO_PHY_RADIO		0x3E2
+#define BCM43xx_MMIO_ANTENNA		0x3E8
+#define BCM43xx_MMIO_CHANNEL		0x3F0
+#define BCM43xx_MMIO_CHANNEL_EXT	0x3F4
+#define BCM43xx_MMIO_RADIO_CONTROL	0x3F6
+#define BCM43xx_MMIO_RADIO_DATA_HIGH	0x3F8
+#define BCM43xx_MMIO_RADIO_DATA_LOW	0x3FA
+#define BCM43xx_MMIO_PHY_CONTROL	0x3FC
+#define BCM43xx_MMIO_PHY_DATA		0x3FE
+#define BCM43xx_MMIO_MACFILTER_CONTROL	0x420
+#define BCM43xx_MMIO_MACFILTER_DATA	0x422
+#define BCM43xx_MMIO_RADIO_HWENABLED_LO	0x49A
+#define BCM43xx_MMIO_GPIO_CONTROL	0x49C
+#define BCM43xx_MMIO_GPIO_MASK		0x49E
+#define BCM43xx_MMIO_TSF_0		0x632 /* core rev < 3 only */
+#define BCM43xx_MMIO_TSF_1		0x634 /* core rev < 3 only */
+#define BCM43xx_MMIO_TSF_2		0x636 /* core rev < 3 only */
+#define BCM43xx_MMIO_TSF_3		0x638 /* core rev < 3 only */
+#define BCM43xx_MMIO_POWERUP_DELAY	0x6A8
+
+/* SPROM offsets. */
+#define BCM43xx_SPROM_BASE		0x1000
+#define BCM43xx_SPROM_BOARDFLAGS2	0x1c
+#define BCM43xx_SPROM_IL0MACADDR	0x24
+#define BCM43xx_SPROM_ET0MACADDR	0x27
+#define BCM43xx_SPROM_ET1MACADDR	0x2a
+#define BCM43xx_SPROM_ETHPHY		0x2d
+#define BCM43xx_SPROM_BOARDREV		0x2e
+#define BCM43xx_SPROM_PA0B0		0x2f
+#define BCM43xx_SPROM_PA0B1		0x30
+#define BCM43xx_SPROM_PA0B2		0x31
+#define BCM43xx_SPROM_WL0GPIO0		0x32
+#define BCM43xx_SPROM_WL0GPIO2		0x33
+#define BCM43xx_SPROM_MAXPWR		0x34
+#define BCM43xx_SPROM_PA1B0		0x35
+#define BCM43xx_SPROM_PA1B1		0x36
+#define BCM43xx_SPROM_PA1B2		0x37
+#define BCM43xx_SPROM_IDL_TSSI_TGT	0x38
+#define BCM43xx_SPROM_BOARDFLAGS	0x39
+#define BCM43xx_SPROM_ANTENNA_GAIN	0x3a
+#define BCM43xx_SPROM_VERSION		0x3f
+
+/* BCM43xx_SPROM_BOARDFLAGS values */
+#define BCM43xx_BFL_BTCOEXIST		0x0001 /* implements Bluetooth coexistance */
+#define BCM43xx_BFL_PACTRL		0x0002 /* GPIO 9 controlling the PA */
+#define BCM43xx_BFL_AIRLINEMODE		0x0004 /* implements GPIO 13 radio disable indication */
+#define BCM43xx_BFL_RSSI		0x0008 /* software calculates nrssi slope. */
+#define BCM43xx_BFL_ENETSPI		0x0010 /* has ephy roboswitch spi */
+#define BCM43xx_BFL_XTAL_NOSLOW		0x0020 /* no slow clock available */
+#define BCM43xx_BFL_CCKHIPWR		0x0040 /* can do high power CCK transmission */
+#define BCM43xx_BFL_ENETADM		0x0080 /* has ADMtek switch */
+#define BCM43xx_BFL_ENETVLAN		0x0100 /* can do vlan */
+#define BCM43xx_BFL_AFTERBURNER		0x0200 /* supports Afterburner mode */
+#define BCM43xx_BFL_NOPCI		0x0400 /* leaves PCI floating */
+#define BCM43xx_BFL_FEM			0x0800 /* supports the Front End Module */
+#define BCM43xx_BFL_EXTLNA		0x1000 /* has an external LNA */
+#define BCM43xx_BFL_HGPA		0x2000 /* had high gain PA */
+#define BCM43xx_BFL_BTCMOD		0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */
+#define BCM43xx_BFL_ALTIQ		0x8000 /* alternate I/Q settings */
+
+/* GPIO register offset, in both ChipCommon and PCI core. */
+#define BCM43xx_GPIO_CONTROL		0x6c
+
+/* SHM Routing */
+#define BCM43xx_SHM_SHARED		0x0001
+#define BCM43xx_SHM_WIRELESS		0x0002
+#define BCM43xx_SHM_PCM			0x0003
+#define BCM43xx_SHM_HWMAC		0x0004
+#define BCM43xx_SHM_UCODE		0x0300
+
+/* MacFilter offsets. */
+#define BCM43xx_MACFILTER_SELF		0x0000
+#define BCM43xx_MACFILTER_ASSOC		0x0003
+
+/* Chipcommon registers. */
+#define BCM43xx_CHIPCOMMON_CAPABILITIES 	0x04
+#define BCM43xx_CHIPCOMMON_PLLONDELAY		0xB0
+#define BCM43xx_CHIPCOMMON_FREFSELDELAY		0xB4
+#define BCM43xx_CHIPCOMMON_SLOWCLKCTL		0xB8
+#define BCM43xx_CHIPCOMMON_SYSCLKCTL		0xC0
+
+/* PCI core specific registers. */
+#define BCM43xx_PCICORE_BCAST_ADDR	0x50
+#define BCM43xx_PCICORE_BCAST_DATA	0x54
+#define BCM43xx_PCICORE_SBTOPCI2	0x108
+
+/* SBTOPCI2 values. */
+#define BCM43xx_SBTOPCI2_PREFETCH	0x4
+#define BCM43xx_SBTOPCI2_BURST		0x8
+
+/* Chipcommon capabilities. */
+#define BCM43xx_CAPABILITIES_PCTL		0x00040000
+#define BCM43xx_CAPABILITIES_PLLMASK		0x00030000
+#define BCM43xx_CAPABILITIES_PLLSHIFT		16
+#define BCM43xx_CAPABILITIES_FLASHMASK		0x00000700
+#define BCM43xx_CAPABILITIES_FLASHSHIFT		8
+#define BCM43xx_CAPABILITIES_EXTBUSPRESENT	0x00000040
+#define BCM43xx_CAPABILITIES_UARTGPIO		0x00000020
+#define BCM43xx_CAPABILITIES_UARTCLOCKMASK	0x00000018
+#define BCM43xx_CAPABILITIES_UARTCLOCKSHIFT	3
+#define BCM43xx_CAPABILITIES_MIPSBIGENDIAN	0x00000004
+#define BCM43xx_CAPABILITIES_NRUARTSMASK	0x00000003
+
+/* PowerControl */
+#define BCM43xx_PCTL_IN			0xB0
+#define BCM43xx_PCTL_OUT		0xB4
+#define BCM43xx_PCTL_OUTENABLE		0xB8
+#define BCM43xx_PCTL_XTAL_POWERUP	0x40
+#define BCM43xx_PCTL_PLL_POWERDOWN	0x80
+
+/* PowerControl Clock Modes */
+#define BCM43xx_PCTL_CLK_FAST		0x00
+#define BCM43xx_PCTL_CLK_SLOW		0x01
+#define BCM43xx_PCTL_CLK_DYNAMIC	0x02
+
+#define BCM43xx_PCTL_FORCE_SLOW		0x0800
+#define BCM43xx_PCTL_FORCE_PLL		0x1000
+#define BCM43xx_PCTL_DYN_XTAL		0x2000
+
+/* COREIDs */
+#define BCM43xx_COREID_CHIPCOMMON	0x800
+#define BCM43xx_COREID_ILINE20          0x801
+#define BCM43xx_COREID_SDRAM            0x803
+#define BCM43xx_COREID_PCI		0x804
+#define BCM43xx_COREID_MIPS             0x805
+#define BCM43xx_COREID_ETHERNET         0x806
+#define BCM43xx_COREID_V90		0x807
+#define BCM43xx_COREID_USB11_HOSTDEV    0x80a
+#define BCM43xx_COREID_IPSEC            0x80b
+#define BCM43xx_COREID_PCMCIA		0x80d
+#define BCM43xx_COREID_EXT_IF           0x80f
+#define BCM43xx_COREID_80211		0x812
+#define BCM43xx_COREID_MIPS_3302        0x816
+#define BCM43xx_COREID_USB11_HOST       0x817
+#define BCM43xx_COREID_USB11_DEV        0x818
+#define BCM43xx_COREID_USB20_HOST       0x819
+#define BCM43xx_COREID_USB20_DEV        0x81a
+#define BCM43xx_COREID_SDIO_HOST        0x81b
+
+/* Core Information Registers */
+#define BCM43xx_CIR_BASE		0xf00
+#define BCM43xx_CIR_SBTPSFLAG		(BCM43xx_CIR_BASE + 0x18)
+#define BCM43xx_CIR_SBIMSTATE		(BCM43xx_CIR_BASE + 0x90)
+#define BCM43xx_CIR_SBINTVEC		(BCM43xx_CIR_BASE + 0x94)
+#define BCM43xx_CIR_SBTMSTATELOW	(BCM43xx_CIR_BASE + 0x98)
+#define BCM43xx_CIR_SBTMSTATEHIGH	(BCM43xx_CIR_BASE + 0x9c)
+#define BCM43xx_CIR_SBIMCONFIGLOW	(BCM43xx_CIR_BASE + 0xa8)
+#define BCM43xx_CIR_SB_ID_HI		(BCM43xx_CIR_BASE + 0xfc)
+
+/* Mask to get the Backplane Flag Number from SBTPSFLAG. */
+#define BCM43xx_BACKPLANE_FLAG_NR_MASK	0x3f
+
+/* SBIMCONFIGLOW values/masks. */
+#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK		0x00000007
+#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT	0
+#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK		0x00000070
+#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT	4
+#define BCM43xx_SBIMCONFIGLOW_CONNID_MASK		0x00ff0000
+#define BCM43xx_SBIMCONFIGLOW_CONNID_SHIFT		16
+
+/* sbtmstatelow state flags */
+#define BCM43xx_SBTMSTATELOW_RESET		0x01
+#define BCM43xx_SBTMSTATELOW_REJECT		0x02
+#define BCM43xx_SBTMSTATELOW_CLOCK		0x10000
+#define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK	0x20000
+
+/* sbtmstatehigh state flags */
+#define BCM43xx_SBTMSTATEHIGH_SERROR		0x1
+#define BCM43xx_SBTMSTATEHIGH_BUSY		0x4
+
+/* sbimstate flags */
+#define BCM43xx_SBIMSTATE_IB_ERROR		0x20000
+#define BCM43xx_SBIMSTATE_TIMEOUT		0x40000
+
+/* PHYVersioning */
+#define BCM43xx_PHYTYPE_A		0x00
+#define BCM43xx_PHYTYPE_B		0x01
+#define BCM43xx_PHYTYPE_G		0x02
+
+/* PHYRegisters */
+#define BCM43xx_PHY_ILT_A_CTRL		0x0072
+#define BCM43xx_PHY_ILT_A_DATA1		0x0073
+#define BCM43xx_PHY_ILT_A_DATA2		0x0074
+#define BCM43xx_PHY_G_LO_CONTROL	0x0810
+#define BCM43xx_PHY_ILT_G_CTRL		0x0472
+#define BCM43xx_PHY_ILT_G_DATA1		0x0473
+#define BCM43xx_PHY_ILT_G_DATA2		0x0474
+#define BCM43xx_PHY_A_PCTL		0x007B
+#define BCM43xx_PHY_G_PCTL		0x0029
+#define BCM43xx_PHY_A_CRS		0x0029
+#define BCM43xx_PHY_RADIO_BITFIELD	0x0401
+#define BCM43xx_PHY_G_CRS		0x0429
+#define BCM43xx_PHY_NRSSILT_CTRL	0x0803
+#define BCM43xx_PHY_NRSSILT_DATA	0x0804
+
+/* RadioRegisters */
+#define BCM43xx_RADIOCTL_ID		0x01
+
+/* StatusBitField */
+#define BCM43xx_SBF_MAC_ENABLED		0x00000001
+#define BCM43xx_SBF_2			0x00000002 /*FIXME: fix name*/
+#define BCM43xx_SBF_CORE_READY		0x00000004
+#define BCM43xx_SBF_400			0x00000400 /*FIXME: fix name*/
+#define BCM43xx_SBF_4000		0x00004000 /*FIXME: fix name*/
+#define BCM43xx_SBF_8000		0x00008000 /*FIXME: fix name*/
+#define BCM43xx_SBF_XFER_REG_BYTESWAP	0x00010000
+#define BCM43xx_SBF_MODE_NOTADHOC	0x00020000
+#define BCM43xx_SBF_MODE_AP		0x00040000
+#define BCM43xx_SBF_RADIOREG_LOCK	0x00080000
+#define BCM43xx_SBF_MODE_MONITOR	0x00400000
+#define BCM43xx_SBF_MODE_PROMISC	0x01000000
+#define BCM43xx_SBF_PS1			0x02000000
+#define BCM43xx_SBF_PS2			0x04000000
+#define BCM43xx_SBF_NO_SSID_BCAST	0x08000000
+#define BCM43xx_SBF_TIME_UPDATE		0x10000000
+#define BCM43xx_SBF_80000000		0x80000000 /*FIXME: fix name*/
+
+/* MicrocodeFlagsBitfield (addr + lo-word values?)*/
+#define BCM43xx_UCODEFLAGS_OFFSET	0x005E
+
+#define BCM43xx_UCODEFLAG_AUTODIV	0x0001
+#define BCM43xx_UCODEFLAG_UNKBGPHY	0x0002
+#define BCM43xx_UCODEFLAG_UNKBPHY	0x0004
+#define BCM43xx_UCODEFLAG_UNKGPHY	0x0020
+#define BCM43xx_UCODEFLAG_UNKPACTRL	0x0040
+#define BCM43xx_UCODEFLAG_JAPAN		0x0080
+
+/* Generic-Interrupt reasons. */
+#define BCM43xx_IRQ_READY		(1 << 0)
+#define BCM43xx_IRQ_BEACON		(1 << 1)
+#define BCM43xx_IRQ_PS			(1 << 2)
+#define BCM43xx_IRQ_REG124		(1 << 5)
+#define BCM43xx_IRQ_PMQ			(1 << 6)
+#define BCM43xx_IRQ_PIO_WORKAROUND	(1 << 8)
+#define BCM43xx_IRQ_XMIT_ERROR		(1 << 11)
+#define BCM43xx_IRQ_RX			(1 << 15)
+#define BCM43xx_IRQ_SCAN		(1 << 16)
+#define BCM43xx_IRQ_NOISE		(1 << 18)
+#define BCM43xx_IRQ_XMIT_STATUS		(1 << 29)
+
+#define BCM43xx_IRQ_ALL			0xffffffff
+#define BCM43xx_IRQ_INITIAL		(BCM43xx_IRQ_PS |		\
+					 BCM43xx_IRQ_REG124 |		\
+					 BCM43xx_IRQ_PMQ |		\
+					 BCM43xx_IRQ_XMIT_ERROR |	\
+					 BCM43xx_IRQ_RX |		\
+					 BCM43xx_IRQ_SCAN |		\
+					 BCM43xx_IRQ_NOISE |		\
+					 BCM43xx_IRQ_XMIT_STATUS)
+					 
+
+/* Initial default iw_mode */
+#define BCM43xx_INITIAL_IWMODE			IW_MODE_INFRA
+
+/* Bus type PCI. */
+#define BCM43xx_BUSTYPE_PCI	0
+/* Bus type Silicone Backplane Bus. */
+#define BCM43xx_BUSTYPE_SB	1
+/* Bus type PCMCIA. */
+#define BCM43xx_BUSTYPE_PCMCIA	2
+
+/* Threshold values. */
+#define BCM43xx_MIN_RTS_THRESHOLD		1U
+#define BCM43xx_MAX_RTS_THRESHOLD		2304U
+#define BCM43xx_DEFAULT_RTS_THRESHOLD		BCM43xx_MAX_RTS_THRESHOLD
+
+#define BCM43xx_DEFAULT_SHORT_RETRY_LIMIT	7
+#define BCM43xx_DEFAULT_LONG_RETRY_LIMIT	4
+
+/* Max size of a security key */
+#define BCM43xx_SEC_KEYSIZE			16
+/* Security algorithms. */
+enum {
+	BCM43xx_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */
+	BCM43xx_SEC_ALGO_WEP,
+	BCM43xx_SEC_ALGO_UNKNOWN,
+	BCM43xx_SEC_ALGO_AES,
+	BCM43xx_SEC_ALGO_WEP104,
+	BCM43xx_SEC_ALGO_TKIP,
+};
+
+#ifdef assert
+# undef assert
+#endif
+#ifdef CONFIG_BCM43XX_DEBUG
+#define assert(expr) \
+	do {									\
+		if (unlikely(!(expr))) {					\
+		printk(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n",	\
+			#expr, __FILE__, __LINE__, __FUNCTION__);		\
+		}								\
+	} while (0)
+#else
+#define assert(expr)	do { /* nothing */ } while (0)
+#endif
+
+/* rate limited printk(). */
+#ifdef printkl
+# undef printkl
+#endif
+#define printkl(f, x...)  do { if (printk_ratelimit()) printk(f ,##x); } while (0)
+/* rate limited printk() for debugging */
+#ifdef dprintkl
+# undef dprintkl
+#endif
+#ifdef CONFIG_BCM43XX_DEBUG
+# define dprintkl		printkl
+#else
+# define dprintkl(f, x...)	do { /* nothing */ } while (0)
+#endif
+
+/* Helper macro for if branches.
+ * An if branch marked with this macro is only taken in DEBUG mode.
+ * Example:
+ *	if (DEBUG_ONLY(foo == bar)) {
+ *		do something
+ *	}
+ *	In DEBUG mode, the branch will be taken if (foo == bar).
+ *	In non-DEBUG mode, the branch will never be taken.
+ */
+#ifdef DEBUG_ONLY
+# undef DEBUG_ONLY
+#endif
+#ifdef CONFIG_BCM43XX_DEBUG
+# define DEBUG_ONLY(x)	(x)
+#else
+# define DEBUG_ONLY(x)	0
+#endif
+
+/* debugging printk() */
+#ifdef dprintk
+# undef dprintk
+#endif
+#ifdef CONFIG_BCM43XX_DEBUG
+# define dprintk(f, x...)  do { printk(f ,##x); } while (0)
+#else
+# define dprintk(f, x...)  do { /* nothing */ } while (0)
+#endif
+
+
+struct net_device;
+struct pci_dev;
+struct bcm43xx_dmaring;
+struct bcm43xx_pioqueue;
+
+struct bcm43xx_initval {
+	u16 offset;
+	u16 size;
+	u32 value;
+} __attribute__((__packed__));
+
+/* Values for bcm430x_sprominfo.locale */
+enum {
+	BCM43xx_LOCALE_WORLD = 0,
+	BCM43xx_LOCALE_THAILAND,
+	BCM43xx_LOCALE_ISRAEL,
+	BCM43xx_LOCALE_JORDAN,
+	BCM43xx_LOCALE_CHINA,
+	BCM43xx_LOCALE_JAPAN,
+	BCM43xx_LOCALE_USA_CANADA_ANZ,
+	BCM43xx_LOCALE_EUROPE,
+	BCM43xx_LOCALE_USA_LOW,
+	BCM43xx_LOCALE_JAPAN_HIGH,
+	BCM43xx_LOCALE_ALL,
+	BCM43xx_LOCALE_NONE,
+};
+
+#define BCM43xx_SPROM_SIZE	64 /* in 16-bit words. */
+struct bcm43xx_sprominfo {
+	u16 boardflags2;
+	u8 il0macaddr[6];
+	u8 et0macaddr[6];
+	u8 et1macaddr[6];
+	u8 et0phyaddr:5;
+	u8 et1phyaddr:5;
+	u8 et0mdcport:1;
+	u8 et1mdcport:1;
+	u8 boardrev;
+	u8 locale:4;
+	u8 antennas_aphy:2;
+	u8 antennas_bgphy:2;
+	u16 pa0b0;
+	u16 pa0b1;
+	u16 pa0b2;
+	u8 wl0gpio0;
+	u8 wl0gpio1;
+	u8 wl0gpio2;
+	u8 wl0gpio3;
+	u8 maxpower_aphy;
+	u8 maxpower_bgphy;
+	u16 pa1b0;
+	u16 pa1b1;
+	u16 pa1b2;
+	u8 idle_tssi_tgt_aphy;
+	u8 idle_tssi_tgt_bgphy;
+	u16 boardflags;
+	u16 antennagain_aphy;
+	u16 antennagain_bgphy;
+};
+
+/* Value pair to measure the LocalOscillator. */
+struct bcm43xx_lopair {
+	s8 low;
+	s8 high;
+	u8 used:1;
+};
+#define BCM43xx_LO_COUNT	(14*4)
+
+struct bcm43xx_phyinfo {
+	/* Hardware Data */
+	u8 version;
+	u8 type;
+	u8 rev;
+	u16 antenna_diversity;
+	u16 savedpctlreg;
+	u16 minlowsig[2];
+	u16 minlowsigpos[2];
+	u8 connected:1,
+	   calibrated:1,
+	   is_locked:1, /* used in bcm43xx_phy_{un}lock() */
+	   dyn_tssi_tbl:1; /* used in bcm43xx_phy_init_tssi2dbm_table() */
+	/* LO Measurement Data.
+	 * Use bcm43xx_get_lopair() to get a value.
+	 */
+	struct bcm43xx_lopair *_lo_pairs;
+
+	/* TSSI to dBm table in use */
+	const s8 *tssi2dbm;
+	/* idle TSSI value */
+	s8 idle_tssi;
+
+	/* Values from bcm43xx_calc_loopback_gain() */
+	u16 loopback_gain[2];
+
+	/* PHY lock for core.rev < 3
+	 * This lock is only used by bcm43xx_phy_{un}lock()
+	 */
+	spinlock_t lock;
+};
+
+
+struct bcm43xx_radioinfo {
+	u16 manufact;
+	u16 version;
+	u8 revision;
+
+	/* Desired TX power in dBm Q5.2 */
+	u16 txpower_desired;
+	/* TX Power control values. */
+	union {
+		/* B/G PHY */
+		struct {
+			u16 baseband_atten;
+			u16 radio_atten;
+			u16 txctl1;
+			u16 txctl2;
+		};
+		/* A PHY */
+		struct {
+			u16 txpwr_offset;
+		};
+	};
+
+	/* Current Interference Mitigation mode */
+	int interfmode;
+	/* Stack of saved values from the Interference Mitigation code.
+	 * Each value in the stack is layed out as follows:
+	 * bit 0-11:  offset
+	 * bit 12-15: register ID
+	 * bit 16-32: value
+	 * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
+	 */
+#define BCM43xx_INTERFSTACK_SIZE	26
+	u32 interfstack[BCM43xx_INTERFSTACK_SIZE];
+
+	/* Saved values from the NRSSI Slope calculation */
+	s16 nrssi[2];
+	s32 nrssislope;
+	/* In memory nrssi lookup table. */
+	s8 nrssi_lt[64];
+
+	/* current channel */
+	u8 channel;
+	u8 initial_channel;
+
+	u16 lofcal;
+
+	u16 initval;
+
+	u8 enabled:1;
+	/* ACI (adjacent channel interference) flags. */
+	u8 aci_enable:1,
+	   aci_wlan_automatic:1,
+	   aci_hw_rssi:1;
+};
+
+/* Data structures for DMA transmission, per 80211 core. */
+struct bcm43xx_dma {
+	struct bcm43xx_dmaring *tx_ring0;
+	struct bcm43xx_dmaring *tx_ring1;
+	struct bcm43xx_dmaring *tx_ring2;
+	struct bcm43xx_dmaring *tx_ring3;
+	struct bcm43xx_dmaring *rx_ring0;
+	struct bcm43xx_dmaring *rx_ring1; /* only available on core.rev < 5 */
+};
+
+/* Data structures for PIO transmission, per 80211 core. */
+struct bcm43xx_pio {
+	struct bcm43xx_pioqueue *queue0;
+	struct bcm43xx_pioqueue *queue1;
+	struct bcm43xx_pioqueue *queue2;
+	struct bcm43xx_pioqueue *queue3;
+};
+
+#define BCM43xx_MAX_80211_CORES		2
+
+#ifdef CONFIG_BCM947XX
+#define core_offset(bcm) (bcm)->current_core_offset
+#else
+#define core_offset(bcm) 0
+#endif
+
+/* Generic information about a core. */
+struct bcm43xx_coreinfo {
+	u8 available:1,
+	   enabled:1,
+	   initialized:1;
+	/** core_id ID number */
+	u16 id;
+	/** core_rev revision number */
+	u8 rev;
+	/** Index number for _switch_core() */
+	u8 index;
+};
+
+/* Additional information for each 80211 core. */
+struct bcm43xx_coreinfo_80211 {
+	/* PHY device. */
+	struct bcm43xx_phyinfo phy;
+	/* Radio device. */
+	struct bcm43xx_radioinfo radio;
+	union {
+		/* DMA context. */
+		struct bcm43xx_dma dma;
+		/* PIO context. */
+		struct bcm43xx_pio pio;
+	};
+};
+
+/* Context information for a noise calculation (Link Quality). */
+struct bcm43xx_noise_calculation {
+	struct bcm43xx_coreinfo *core_at_start;
+	u8 channel_at_start;
+	u8 calculation_running:1;
+	u8 nr_samples;
+	s8 samples[8][4];
+};
+
+struct bcm43xx_stats {
+	u8 link_quality;
+	u8 noise;
+	struct iw_statistics wstats;
+	/* Store the last TX/RX times here for updating the leds. */
+	unsigned long last_tx;
+	unsigned long last_rx;
+};
+
+struct bcm43xx_key {
+	u8 enabled:1;
+	u8 algorithm;
+};
+
+struct bcm43xx_private {
+	struct bcm43xx_sysfs sysfs;
+
+	struct ieee80211_device *ieee;
+	struct ieee80211softmac_device *softmac;
+
+	struct net_device *net_dev;
+	struct pci_dev *pci_dev;
+	unsigned int irq;
+
+	void __iomem *mmio_addr;
+	unsigned int mmio_len;
+
+	/* Do not use the lock directly. Use the bcm43xx_lock* helper
+	 * functions, to be MMIO-safe. */
+	spinlock_t _lock;
+
+	/* Driver status flags. */
+	u32 initialized:1,		/* init_board() succeed */
+	    was_initialized:1,		/* for PCI suspend/resume. */
+	    shutting_down:1,		/* free_board() in progress */
+	    __using_pio:1,		/* Internal, use bcm43xx_using_pio(). */
+	    bad_frames_preempt:1,	/* Use "Bad Frames Preemption" (default off) */
+	    reg124_set_0x4:1,		/* Some variable to keep track of IRQ stuff. */
+	    powersaving:1,		/* TRUE if we are in PowerSaving mode. FALSE otherwise. */
+	    short_preamble:1,		/* TRUE, if short preamble is enabled. */
+	    firmware_norelease:1;	/* Do not release the firmware. Used on suspend. */
+
+	struct bcm43xx_stats stats;
+
+	/* Bus type we are connected to.
+	 * This is currently always BCM43xx_BUSTYPE_PCI
+	 */
+	u8 bustype;
+
+	u16 board_vendor;
+	u16 board_type;
+	u16 board_revision;
+
+	u16 chip_id;
+	u8 chip_rev;
+	u8 chip_package;
+
+	struct bcm43xx_sprominfo sprom;
+#define BCM43xx_NR_LEDS		4
+	struct bcm43xx_led leds[BCM43xx_NR_LEDS];
+
+	/* The currently active core. */
+	struct bcm43xx_coreinfo *current_core;
+#ifdef CONFIG_BCM947XX
+	/** current core memory offset */
+	u32 current_core_offset;
+#endif
+	struct bcm43xx_coreinfo *active_80211_core;
+	/* coreinfo structs for all possible cores follow.
+	 * Note that a core might not exist.
+	 * So check the coreinfo flags before using it.
+	 */
+	struct bcm43xx_coreinfo core_chipcommon;
+	struct bcm43xx_coreinfo core_pci;
+	struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ];
+	/* Additional information, specific to the 80211 cores. */
+	struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ];
+	/* Index of the current 80211 core. If current_core is not
+	 * an 80211 core, this is -1.
+	 */
+	int current_80211_core_idx;
+	/* Number of available 80211 cores. */
+	int nr_80211_available;
+
+	u32 chipcommon_capabilities;
+
+	/* Reason code of the last interrupt. */
+	u32 irq_reason;
+	u32 dma_reason[4];
+	/* saved irq enable/disable state bitfield. */
+	u32 irq_savedstate;
+	/* Link Quality calculation context. */
+	struct bcm43xx_noise_calculation noisecalc;
+
+	/* Threshold values. */
+	//TODO: The RTS thr has to be _used_. Currently, it is only set via WX.
+	u32 rts_threshold;
+
+	/* Interrupt Service Routine tasklet (bottom-half) */
+	struct tasklet_struct isr_tasklet;
+
+	/* Periodic tasks */
+	struct timer_list periodic_tasks;
+	unsigned int periodic_state;
+
+	struct work_struct restart_work;
+
+	/* Informational stuff. */
+	char nick[IW_ESSID_MAX_SIZE + 1];
+
+	/* encryption/decryption */
+	u16 security_offset;
+	struct bcm43xx_key key[54];
+	u8 default_key_idx;
+
+	/* Firmware. */
+	const struct firmware *ucode;
+	const struct firmware *pcm;
+	const struct firmware *initvals0;
+	const struct firmware *initvals1;
+
+	/* Debugging stuff follows. */
+#ifdef CONFIG_BCM43XX_DEBUG
+	struct bcm43xx_dfsentry *dfsentry;
+#endif
+};
+
+/* bcm43xx_(un)lock() protect struct bcm43xx_private.
+ * Note that _NO_ MMIO writes are allowed. If you want to
+ * write to the device through MMIO in the critical section, use
+ * the *_mmio lock functions.
+ * MMIO read-access is allowed, though.
+ */
+#define bcm43xx_lock(bcm, flags)	spin_lock_irqsave(&(bcm)->_lock, flags)
+#define bcm43xx_unlock(bcm, flags)	spin_unlock_irqrestore(&(bcm)->_lock, flags)
+/* bcm43xx_(un)lock_mmio() protect struct bcm43xx_private and MMIO.
+ * MMIO write-access to the device is allowed.
+ * All MMIO writes are flushed on unlock, so it is guaranteed to not
+ * interfere with other threads writing MMIO registers.
+ */
+#define bcm43xx_lock_mmio(bcm, flags)	bcm43xx_lock(bcm, flags)
+#define bcm43xx_unlock_mmio(bcm, flags)	do { mmiowb(); bcm43xx_unlock(bcm, flags); } while (0)
+
+static inline
+struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
+{
+	return ieee80211softmac_priv(dev);
+}
+
+
+/* Helper function, which returns a boolean.
+ * TRUE, if PIO is used; FALSE, if DMA is used.
+ */
+#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
+static inline
+int bcm43xx_using_pio(struct bcm43xx_private *bcm)
+{
+	return bcm->__using_pio;
+}
+#elif defined(CONFIG_BCM43XX_DMA)
+static inline
+int bcm43xx_using_pio(struct bcm43xx_private *bcm)
+{
+	return 0;
+}
+#elif defined(CONFIG_BCM43XX_PIO)
+static inline
+int bcm43xx_using_pio(struct bcm43xx_private *bcm)
+{
+	return 1;
+}
+#else
+# error "Using neither DMA nor PIO? Confused..."
+#endif
+
+/* Helper functions to access data structures private to the 80211 cores.
+ * Note that we _must_ have an 80211 core mapped when calling
+ * any of these functions.
+ */
+static inline
+struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm)
+{
+	assert(bcm43xx_using_pio(bcm));
+	assert(bcm->current_80211_core_idx >= 0);
+	assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
+	return &(bcm->core_80211_ext[bcm->current_80211_core_idx].pio);
+}
+static inline
+struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm)
+{
+	assert(!bcm43xx_using_pio(bcm));
+	assert(bcm->current_80211_core_idx >= 0);
+	assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
+	return &(bcm->core_80211_ext[bcm->current_80211_core_idx].dma);
+}
+static inline
+struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm)
+{
+	assert(bcm->current_80211_core_idx >= 0);
+	assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
+	return &(bcm->core_80211_ext[bcm->current_80211_core_idx].phy);
+}
+static inline
+struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm)
+{
+	assert(bcm->current_80211_core_idx >= 0);
+	assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
+	return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio);
+}
+
+/* Are we running in init_board() context? */
+static inline
+int bcm43xx_is_initializing(struct bcm43xx_private *bcm)
+{
+	if (bcm->initialized)
+		return 0;
+	if (bcm->shutting_down)
+		return 0;
+	return 1;
+}
+
+static inline
+struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy,
+					   u16 radio_attenuation,
+					   u16 baseband_attenuation)
+{
+	return phy->_lo_pairs + (radio_attenuation + 14 * (baseband_attenuation / 2));
+}
+
+
+static inline
+u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset)
+{
+	return ioread16(bcm->mmio_addr + core_offset(bcm) + offset);
+}
+
+static inline
+void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value)
+{
+	iowrite16(value, bcm->mmio_addr + core_offset(bcm) + offset);
+}
+
+static inline
+u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset)
+{
+	return ioread32(bcm->mmio_addr + core_offset(bcm) + offset);
+}
+
+static inline
+void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value)
+{
+	iowrite32(value, bcm->mmio_addr + core_offset(bcm) + offset);
+}
+
+static inline
+int bcm43xx_pci_read_config16(struct bcm43xx_private *bcm, int offset, u16 *value)
+{
+	return pci_read_config_word(bcm->pci_dev, offset, value);
+}
+
+static inline
+int bcm43xx_pci_read_config32(struct bcm43xx_private *bcm, int offset, u32 *value)
+{
+	return pci_read_config_dword(bcm->pci_dev, offset, value);
+}
+
+static inline
+int bcm43xx_pci_write_config16(struct bcm43xx_private *bcm, int offset, u16 value)
+{
+	return pci_write_config_word(bcm->pci_dev, offset, value);
+}
+
+static inline
+int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 value)
+{
+	return pci_write_config_dword(bcm->pci_dev, offset, value);
+}
+
+/** Limit a value between two limits */
+#ifdef limit_value
+# undef limit_value
+#endif
+#define limit_value(value, min, max)  \
+	({						\
+		typeof(value) __value = (value);	\
+	 	typeof(value) __min = (min);		\
+	 	typeof(value) __max = (max);		\
+	 	if (__value < __min)			\
+	 		__value = __min;		\
+	 	else if (__value > __max)		\
+	 		__value = __max;		\
+	 	__value;				\
+	})
+
+/** Helpers to print MAC addresses. */
+#define BCM43xx_MACFMT		"%02x:%02x:%02x:%02x:%02x:%02x"
+#define BCM43xx_MACARG(x)	((u8*)(x))[0], ((u8*)(x))[1], \
+				((u8*)(x))[2], ((u8*)(x))[3], \
+				((u8*)(x))[4], ((u8*)(x))[5]
+
+#endif /* BCM43xx_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
new file mode 100644
index 0000000..d2c3401
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
@@ -0,0 +1,499 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  debugfs driver debugging code
+
+  Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de>
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+
+
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include "bcm43xx.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_debugfs.h"
+#include "bcm43xx_dma.h"
+#include "bcm43xx_pio.h"
+#include "bcm43xx_xmit.h"
+
+#define REALLY_BIG_BUFFER_SIZE	(1024*256)
+
+static struct bcm43xx_debugfs fs;
+static char really_big_buffer[REALLY_BIG_BUFFER_SIZE];
+static DECLARE_MUTEX(big_buffer_sem);
+
+
+static ssize_t write_file_dummy(struct file *file, const char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	return count;
+}
+
+static int open_file_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->u.generic_ip;
+	return 0;
+}
+
+#define fappend(fmt, x...)	pos += snprintf(buf + pos, len - pos, fmt , ##x)
+
+static ssize_t devinfo_read_file(struct file *file, char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	const size_t len = REALLY_BIG_BUFFER_SIZE;
+
+	struct bcm43xx_private *bcm = file->private_data;
+	char *buf = really_big_buffer;
+	size_t pos = 0;
+	ssize_t res;
+	struct net_device *net_dev;
+	struct pci_dev *pci_dev;
+	unsigned long flags;
+	u16 tmp16;
+	int i;
+
+	down(&big_buffer_sem);
+
+	bcm43xx_lock_mmio(bcm, flags);
+	if (!bcm->initialized) {
+		fappend("Board not initialized.\n");
+		goto out;
+	}
+	net_dev = bcm->net_dev;
+	pci_dev = bcm->pci_dev;
+
+	/* This is where the information is written to the "devinfo" file */
+	fappend("*** %s devinfo ***\n", net_dev->name);
+	fappend("vendor:           0x%04x   device:           0x%04x\n",
+		pci_dev->vendor, pci_dev->device);
+	fappend("subsystem_vendor: 0x%04x   subsystem_device: 0x%04x\n",
+		pci_dev->subsystem_vendor, pci_dev->subsystem_device);
+	fappend("IRQ: %d\n", bcm->irq);
+	fappend("mmio_addr: 0x%p   mmio_len: %u\n", bcm->mmio_addr, bcm->mmio_len);
+	fappend("chip_id: 0x%04x   chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev);
+	if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16)))
+		fappend("Radio disabled by hardware!\n");
+	if ((bcm->core_80211[0].rev < 3) && !(bcm43xx_read16(bcm, 0x049A) & (1 << 4)))
+		fappend("Radio disabled by hardware!\n");
+	fappend("board_vendor: 0x%04x   board_type: 0x%04x\n", bcm->board_vendor,
+	        bcm->board_type);
+
+	fappend("\nCores:\n");
+#define fappend_core(name, info) fappend("core \"" name "\" %s, %s, id: 0x%04x, "	\
+					 "rev: 0x%02x, index: 0x%02x\n",		\
+					 (info).available				\
+						? "available" : "nonavailable",		\
+					 (info).enabled					\
+						? "enabled" : "disabled",		\
+					 (info).id, (info).rev, (info).index)
+	fappend_core("CHIPCOMMON", bcm->core_chipcommon);
+	fappend_core("PCI", bcm->core_pci);
+	fappend_core("first 80211", bcm->core_80211[0]);
+	fappend_core("second 80211", bcm->core_80211[1]);
+#undef fappend_core
+	tmp16 = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+	fappend("LEDs: ");
+	for (i = 0; i < BCM43xx_NR_LEDS; i++)
+		fappend("%d ", !!(tmp16 & (1 << i)));
+	fappend("\n");
+
+out:
+	bcm43xx_unlock_mmio(bcm, flags);
+	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+	up(&big_buffer_sem);
+	return res;
+}
+
+static ssize_t drvinfo_read_file(struct file *file, char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	const size_t len = REALLY_BIG_BUFFER_SIZE;
+
+	char *buf = really_big_buffer;
+	size_t pos = 0;
+	ssize_t res;
+
+	down(&big_buffer_sem);
+
+	/* This is where the information is written to the "driver" file */
+	fappend(KBUILD_MODNAME " driver\n");
+	fappend("Compiled at: %s %s\n", __DATE__, __TIME__);
+
+	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+	up(&big_buffer_sem);
+	return res;
+}
+
+static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	const size_t len = REALLY_BIG_BUFFER_SIZE;
+
+	struct bcm43xx_private *bcm = file->private_data;
+	char *buf = really_big_buffer;
+	size_t pos = 0;
+	ssize_t res;
+	unsigned long flags;
+
+	down(&big_buffer_sem);
+	bcm43xx_lock_mmio(bcm, flags);
+	if (!bcm->initialized) {
+		fappend("Board not initialized.\n");
+		goto out;
+	}
+
+	/* This is where the information is written to the "sprom_dump" file */
+	fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
+
+out:
+	bcm43xx_unlock_mmio(bcm, flags);
+	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+	up(&big_buffer_sem);
+	return res;
+}
+
+static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
+			     size_t count, loff_t *ppos)
+{
+	const size_t len = REALLY_BIG_BUFFER_SIZE;
+
+	struct bcm43xx_private *bcm = file->private_data;
+	char *buf = really_big_buffer;
+	size_t pos = 0;
+	ssize_t res;
+	unsigned long flags;
+	u64 tsf;
+
+	down(&big_buffer_sem);
+	bcm43xx_lock_mmio(bcm, flags);
+	if (!bcm->initialized) {
+		fappend("Board not initialized.\n");
+		goto out;
+	}
+	bcm43xx_tsf_read(bcm, &tsf);
+	fappend("0x%08x%08x\n",
+		(unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32),
+		(unsigned int)(tsf & 0xFFFFFFFFULL));
+
+out:
+	bcm43xx_unlock_mmio(bcm, flags);
+	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+	up(&big_buffer_sem);
+	return res;
+}
+
+static ssize_t tsf_write_file(struct file *file, const char __user *user_buf,
+			      size_t count, loff_t *ppos)
+{
+	struct bcm43xx_private *bcm = file->private_data;
+	char *buf = really_big_buffer;
+	ssize_t buf_size;
+	ssize_t res;
+	unsigned long flags;
+	u64 tsf;
+
+	buf_size = min(count, sizeof (really_big_buffer) - 1);
+	down(&big_buffer_sem);
+	if (copy_from_user(buf, user_buf, buf_size)) {
+	        res = -EFAULT;
+		goto out_up;
+	}
+	bcm43xx_lock_mmio(bcm, flags);
+	if (!bcm->initialized) {
+		printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
+		res = -EFAULT;
+		goto out_unlock;
+	}
+	if (sscanf(buf, "%lli", &tsf) != 1) {
+		printk(KERN_INFO PFX "debugfs: invalid values for \"tsf\"\n");
+		res = -EINVAL;
+		goto out_unlock;
+	}
+	bcm43xx_tsf_write(bcm, tsf);
+	res = buf_size;
+	
+out_unlock:
+	bcm43xx_unlock_mmio(bcm, flags);
+out_up:
+	up(&big_buffer_sem);
+	return res;
+}
+
+static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
+				size_t count, loff_t *ppos)
+{
+	const size_t len = REALLY_BIG_BUFFER_SIZE;
+
+	struct bcm43xx_private *bcm = file->private_data;
+	char *buf = really_big_buffer;
+	size_t pos = 0;
+	ssize_t res;
+	unsigned long flags;
+	struct bcm43xx_dfsentry *e;
+	struct bcm43xx_xmitstatus *status;
+	int i, cnt, j = 0;
+
+	down(&big_buffer_sem);
+	bcm43xx_lock(bcm, flags);
+
+	fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
+		BCM43xx_NR_LOGGED_XMITSTATUS);
+	e = bcm->dfsentry;
+	if (e->xmitstatus_printing == 0) {
+		/* At the beginning, make a copy of all data to avoid
+		 * concurrency, as this function is called multiple
+		 * times for big logs. Without copying, the data might
+		 * change between reads. This would result in total trash.
+		 */
+		e->xmitstatus_printing = 1;
+		e->saved_xmitstatus_ptr = e->xmitstatus_ptr;
+		e->saved_xmitstatus_cnt = e->xmitstatus_cnt;
+		memcpy(e->xmitstatus_print_buffer, e->xmitstatus_buffer,
+		       BCM43xx_NR_LOGGED_XMITSTATUS * sizeof(*(e->xmitstatus_buffer)));
+	}
+	i = e->saved_xmitstatus_ptr - 1;
+	if (i < 0)
+		i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
+	cnt = e->saved_xmitstatus_cnt;
+	while (cnt) {
+		status = e->xmitstatus_print_buffer + i;
+		fappend("0x%02x:   cookie: 0x%04x,  flags: 0x%02x,  "
+			"cnt1: 0x%02x,  cnt2: 0x%02x,  seq: 0x%04x,  "
+			"unk: 0x%04x\n", j,
+			status->cookie, status->flags,
+			status->cnt1, status->cnt2, status->seq,
+			status->unknown);
+		j++;
+		cnt--;
+		i--;
+		if (i < 0)
+			i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
+	}
+
+	bcm43xx_unlock(bcm, flags);
+	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+	bcm43xx_lock(bcm, flags);
+	if (*ppos == pos) {
+		/* Done. Drop the copied data. */
+		e->xmitstatus_printing = 0;
+	}
+	bcm43xx_unlock(bcm, flags);
+	up(&big_buffer_sem);
+	return res;
+}
+
+#undef fappend
+
+
+static struct file_operations devinfo_fops = {
+	.read = devinfo_read_file,
+	.write = write_file_dummy,
+	.open = open_file_generic,
+};
+
+static struct file_operations spromdump_fops = {
+	.read = spromdump_read_file,
+	.write = write_file_dummy,
+	.open = open_file_generic,
+};
+
+static struct file_operations drvinfo_fops = {
+	.read = drvinfo_read_file,
+	.write = write_file_dummy,
+	.open = open_file_generic,
+};
+
+static struct file_operations tsf_fops = {
+	.read = tsf_read_file,
+	.write = tsf_write_file,
+	.open = open_file_generic,
+};
+
+static struct file_operations txstat_fops = {
+	.read = txstat_read_file,
+	.write = write_file_dummy,
+	.open = open_file_generic,
+};
+
+
+void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_dfsentry *e;
+	char devdir[IFNAMSIZ];
+
+	assert(bcm);
+	e = kzalloc(sizeof(*e), GFP_KERNEL);
+	if (!e) {
+		printk(KERN_ERR PFX "out of memory\n");
+		return;
+	}
+	e->bcm = bcm;
+	e->xmitstatus_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS
+				       * sizeof(*(e->xmitstatus_buffer)),
+				       GFP_KERNEL);
+	if (!e->xmitstatus_buffer) {
+		printk(KERN_ERR PFX "out of memory\n");
+		kfree(e);
+		return;
+	}
+	e->xmitstatus_print_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS
+					     * sizeof(*(e->xmitstatus_buffer)),
+					     GFP_KERNEL);
+	if (!e->xmitstatus_print_buffer) {
+		printk(KERN_ERR PFX "out of memory\n");
+		kfree(e);
+		return;
+	}
+
+
+	bcm->dfsentry = e;
+
+	strncpy(devdir, bcm->net_dev->name, ARRAY_SIZE(devdir));
+	e->subdir = debugfs_create_dir(devdir, fs.root);
+	e->dentry_devinfo = debugfs_create_file("devinfo", 0444, e->subdir,
+						bcm, &devinfo_fops);
+	if (!e->dentry_devinfo)
+		printk(KERN_ERR PFX "debugfs: creating \"devinfo\" for \"%s\" failed!\n", devdir);
+	e->dentry_spromdump = debugfs_create_file("sprom_dump", 0444, e->subdir,
+						  bcm, &spromdump_fops);
+	if (!e->dentry_spromdump)
+		printk(KERN_ERR PFX "debugfs: creating \"sprom_dump\" for \"%s\" failed!\n", devdir);
+	e->dentry_tsf = debugfs_create_file("tsf", 0666, e->subdir,
+	                                    bcm, &tsf_fops);
+	if (!e->dentry_tsf)
+		printk(KERN_ERR PFX "debugfs: creating \"tsf\" for \"%s\" failed!\n", devdir);
+	e->dentry_txstat = debugfs_create_file("tx_status", 0444, e->subdir,
+						bcm, &txstat_fops);
+	if (!e->dentry_txstat)
+		printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir);
+}
+
+void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_dfsentry *e;
+
+	if (!bcm)
+		return;
+
+	e = bcm->dfsentry;
+	assert(e);
+	debugfs_remove(e->dentry_spromdump);
+	debugfs_remove(e->dentry_devinfo);
+	debugfs_remove(e->dentry_tsf);
+	debugfs_remove(e->dentry_txstat);
+	debugfs_remove(e->subdir);
+	kfree(e->xmitstatus_buffer);
+	kfree(e->xmitstatus_print_buffer);
+	kfree(e);
+}
+
+void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
+				struct bcm43xx_xmitstatus *status)
+{
+	struct bcm43xx_dfsentry *e;
+	struct bcm43xx_xmitstatus *savedstatus;
+
+	/* This is protected by bcm->_lock */
+	e = bcm->dfsentry;
+	assert(e);
+	savedstatus = e->xmitstatus_buffer + e->xmitstatus_ptr;
+	memcpy(savedstatus, status, sizeof(*status));
+	e->xmitstatus_ptr++;
+	if (e->xmitstatus_ptr >= BCM43xx_NR_LOGGED_XMITSTATUS)
+		e->xmitstatus_ptr = 0;
+	if (e->xmitstatus_cnt < BCM43xx_NR_LOGGED_XMITSTATUS)
+		e->xmitstatus_cnt++;
+}
+
+void bcm43xx_debugfs_init(void)
+{
+	memset(&fs, 0, sizeof(fs));
+	fs.root = debugfs_create_dir(KBUILD_MODNAME, NULL);
+	if (!fs.root)
+		printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "\" subdir failed!\n");
+	fs.dentry_driverinfo = debugfs_create_file("driver", 0444, fs.root, NULL, &drvinfo_fops);
+	if (!fs.dentry_driverinfo)
+		printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "/driver\" failed!\n");
+}
+
+void bcm43xx_debugfs_exit(void)
+{
+	debugfs_remove(fs.dentry_driverinfo);
+	debugfs_remove(fs.root);
+}
+
+void bcm43xx_printk_dump(const char *data,
+			 size_t size,
+			 const char *description)
+{
+	size_t i;
+	char c;
+
+	printk(KERN_INFO PFX "Data dump (%s, %u bytes):",
+	       description, size);
+	for (i = 0; i < size; i++) {
+		c = data[i];
+		if (i % 8 == 0)
+			printk("\n" KERN_INFO PFX "0x%08x:  0x%02x, ", i, c & 0xff);
+		else
+			printk("0x%02x, ", c & 0xff);
+	}
+	printk("\n");
+}
+
+void bcm43xx_printk_bitdump(const unsigned char *data,
+			    size_t bytes, int msb_to_lsb,
+			    const char *description)
+{
+	size_t i;
+	int j;
+	const unsigned char *d;
+
+	printk(KERN_INFO PFX "*** Bitdump (%s, %u bytes, %s) ***",
+	       description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB");
+	for (i = 0; i < bytes; i++) {
+		d = data + i;
+		if (i % 8 == 0)
+			printk("\n" KERN_INFO PFX "0x%08x:  ", i);
+		if (msb_to_lsb) {
+			for (j = 7; j >= 0; j--) {
+				if (*d & (1 << j))
+					printk("1");
+				else
+					printk("0");
+			}
+		} else {
+			for (j = 0; j < 8; j++) {
+				if (*d & (1 << j))
+					printk("1");
+				else
+					printk("0");
+			}
+		}
+		printk(" ");
+	}
+	printk("\n");
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
new file mode 100644
index 0000000..50ce267
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
@@ -0,0 +1,117 @@
+#ifndef BCM43xx_DEBUGFS_H_
+#define BCM43xx_DEBUGFS_H_
+
+struct bcm43xx_private;
+struct bcm43xx_xmitstatus;
+
+#ifdef CONFIG_BCM43XX_DEBUG
+
+#include <linux/list.h>
+#include <asm/semaphore.h>
+
+struct dentry;
+
+/* limited by the size of the "really_big_buffer" */
+#define BCM43xx_NR_LOGGED_XMITSTATUS	100
+
+struct bcm43xx_dfsentry {
+	struct dentry *subdir;
+	struct dentry *dentry_devinfo;
+	struct dentry *dentry_spromdump;
+	struct dentry *dentry_tsf;
+	struct dentry *dentry_txstat;
+
+	struct bcm43xx_private *bcm;
+
+	/* saved xmitstatus. */
+	struct bcm43xx_xmitstatus *xmitstatus_buffer;
+	int xmitstatus_ptr;
+	int xmitstatus_cnt;
+	/* We need a seperate buffer while printing to avoid
+	 * concurrency issues. (New xmitstatus can arrive
+	 * while we are printing).
+	 */
+	struct bcm43xx_xmitstatus *xmitstatus_print_buffer;
+	int saved_xmitstatus_ptr;
+	int saved_xmitstatus_cnt;
+	int xmitstatus_printing;
+};
+
+struct bcm43xx_debugfs {
+	struct dentry *root;
+	struct dentry *dentry_driverinfo;
+};
+
+void bcm43xx_debugfs_init(void);
+void bcm43xx_debugfs_exit(void);
+void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm);
+void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm);
+void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
+				struct bcm43xx_xmitstatus *status);
+
+/* Debug helper: Dump binary data through printk. */
+void bcm43xx_printk_dump(const char *data,
+			 size_t size,
+			 const char *description);
+/* Debug helper: Dump bitwise binary data through printk. */
+void bcm43xx_printk_bitdump(const unsigned char *data,
+			    size_t bytes, int msb_to_lsb,
+			    const char *description);
+#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) \
+	do {									\
+		bcm43xx_printk_bitdump((const unsigned char *)(pointer),	\
+				       sizeof(*(pointer)),			\
+				       (msb_to_lsb),				\
+				       (description));				\
+	} while (0)
+
+#else /* CONFIG_BCM43XX_DEBUG*/
+
+static inline
+void bcm43xx_debugfs_init(void) { }
+static inline
+void bcm43xx_debugfs_exit(void) { }
+static inline
+void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) { }
+static inline
+void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) { }
+static inline
+void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
+				struct bcm43xx_xmitstatus *status) { }
+
+static inline
+void bcm43xx_printk_dump(const char *data,
+			 size_t size,
+			 const char *description)
+{
+}
+static inline
+void bcm43xx_printk_bitdump(const unsigned char *data,
+			    size_t bytes, int msb_to_lsb,
+			    const char *description)
+{
+}
+#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description)  do { /* nothing */ } while (0)
+
+#endif /* CONFIG_BCM43XX_DEBUG*/
+
+/* Ugly helper macros to make incomplete code more verbose on runtime */
+#ifdef TODO
+# undef TODO
+#endif
+#define TODO()  \
+	do {										\
+		printk(KERN_INFO PFX "TODO: Incomplete code in %s() at %s:%d\n",	\
+		       __FUNCTION__, __FILE__, __LINE__);				\
+	} while (0)
+
+#ifdef FIXME
+# undef FIXME
+#endif
+#define FIXME()  \
+	do {										\
+		printk(KERN_INFO PFX "FIXME: Possibly broken code in %s() at %s:%d\n",	\
+		       __FUNCTION__, __FILE__, __LINE__);				\
+	} while (0)
+
+#endif /* BCM43xx_DEBUGFS_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
new file mode 100644
index 0000000..c3681b8
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -0,0 +1,968 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  DMA ringbuffer and descriptor allocation/management
+
+  Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de>
+
+  Some code in this file is derived from the b44.c driver
+  Copyright (C) 2002 David S. Miller
+  Copyright (C) Pekka Pietikainen
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "bcm43xx.h"
+#include "bcm43xx_dma.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_debugfs.h"
+#include "bcm43xx_power.h"
+#include "bcm43xx_xmit.h"
+
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+
+
+static inline int free_slots(struct bcm43xx_dmaring *ring)
+{
+	return (ring->nr_slots - ring->used_slots);
+}
+
+static inline int next_slot(struct bcm43xx_dmaring *ring, int slot)
+{
+	assert(slot >= -1 && slot <= ring->nr_slots - 1);
+	if (slot == ring->nr_slots - 1)
+		return 0;
+	return slot + 1;
+}
+
+static inline int prev_slot(struct bcm43xx_dmaring *ring, int slot)
+{
+	assert(slot >= 0 && slot <= ring->nr_slots - 1);
+	if (slot == 0)
+		return ring->nr_slots - 1;
+	return slot - 1;
+}
+
+/* Request a slot for usage. */
+static inline
+int request_slot(struct bcm43xx_dmaring *ring)
+{
+	int slot;
+
+	assert(ring->tx);
+	assert(!ring->suspended);
+	assert(free_slots(ring) != 0);
+
+	slot = next_slot(ring, ring->current_slot);
+	ring->current_slot = slot;
+	ring->used_slots++;
+
+	/* Check the number of available slots and suspend TX,
+	 * if we are running low on free slots.
+	 */
+	if (unlikely(free_slots(ring) < ring->suspend_mark)) {
+		netif_stop_queue(ring->bcm->net_dev);
+		ring->suspended = 1;
+	}
+#ifdef CONFIG_BCM43XX_DEBUG
+	if (ring->used_slots > ring->max_used_slots)
+		ring->max_used_slots = ring->used_slots;
+#endif /* CONFIG_BCM43XX_DEBUG*/
+
+	return slot;
+}
+
+/* Return a slot to the free slots. */
+static inline
+void return_slot(struct bcm43xx_dmaring *ring, int slot)
+{
+	assert(ring->tx);
+
+	ring->used_slots--;
+
+	/* Check if TX is suspended and check if we have
+	 * enough free slots to resume it again.
+	 */
+	if (unlikely(ring->suspended)) {
+		if (free_slots(ring) >= ring->resume_mark) {
+			ring->suspended = 0;
+			netif_wake_queue(ring->bcm->net_dev);
+		}
+	}
+}
+
+static inline
+dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring,
+			  unsigned char *buf,
+			  size_t len,
+			  int tx)
+{
+	dma_addr_t dmaaddr;
+
+	if (tx) {
+		dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
+					 buf, len,
+					 DMA_TO_DEVICE);
+	} else {
+		dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
+					 buf, len,
+					 DMA_FROM_DEVICE);
+	}
+
+	return dmaaddr;
+}
+
+static inline
+void unmap_descbuffer(struct bcm43xx_dmaring *ring,
+		      dma_addr_t addr,
+		      size_t len,
+		      int tx)
+{
+	if (tx) {
+		dma_unmap_single(&ring->bcm->pci_dev->dev,
+				 addr, len,
+				 DMA_TO_DEVICE);
+	} else {
+		dma_unmap_single(&ring->bcm->pci_dev->dev,
+				 addr, len,
+				 DMA_FROM_DEVICE);
+	}
+}
+
+static inline
+void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring,
+			     dma_addr_t addr,
+			     size_t len)
+{
+	assert(!ring->tx);
+
+	dma_sync_single_for_cpu(&ring->bcm->pci_dev->dev,
+				addr, len, DMA_FROM_DEVICE);
+}
+
+static inline
+void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring,
+				dma_addr_t addr,
+				size_t len)
+{
+	assert(!ring->tx);
+
+	dma_sync_single_for_device(&ring->bcm->pci_dev->dev,
+				   addr, len, DMA_FROM_DEVICE);
+}
+
+/* Unmap and free a descriptor buffer. */
+static inline
+void free_descriptor_buffer(struct bcm43xx_dmaring *ring,
+			    struct bcm43xx_dmadesc *desc,
+			    struct bcm43xx_dmadesc_meta *meta,
+			    int irq_context)
+{
+	assert(meta->skb);
+	if (irq_context)
+		dev_kfree_skb_irq(meta->skb);
+	else
+		dev_kfree_skb(meta->skb);
+	meta->skb = NULL;
+}
+
+static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
+{
+	struct device *dev = &(ring->bcm->pci_dev->dev);
+
+	ring->vbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
+					 &(ring->dmabase), GFP_KERNEL);
+	if (!ring->vbase) {
+		printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
+		return -ENOMEM;
+	}
+	if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) {
+		printk(KERN_ERR PFX ">>>FATAL ERROR<<<  DMA RINGMEMORY >1G "
+				    "(0x%08x, len: %lu)\n",
+		       ring->dmabase, BCM43xx_DMA_RINGMEMSIZE);
+		dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
+				  ring->vbase, ring->dmabase);
+		return -ENOMEM;
+	}
+	assert(!(ring->dmabase & 0x000003FF));
+	memset(ring->vbase, 0, BCM43xx_DMA_RINGMEMSIZE);
+
+	return 0;
+}
+
+static void free_ringmemory(struct bcm43xx_dmaring *ring)
+{
+	struct device *dev = &(ring->bcm->pci_dev->dev);
+
+	dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
+			  ring->vbase, ring->dmabase);
+}
+
+/* Reset the RX DMA channel */
+int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
+				   u16 mmio_base)
+{
+	int i;
+	u32 value;
+
+	bcm43xx_write32(bcm,
+			mmio_base + BCM43xx_DMA_RX_CONTROL,
+			0x00000000);
+	for (i = 0; i < 1000; i++) {
+		value = bcm43xx_read32(bcm,
+				       mmio_base + BCM43xx_DMA_RX_STATUS);
+		value &= BCM43xx_DMA_RXSTAT_STAT_MASK;
+		if (value == BCM43xx_DMA_RXSTAT_STAT_DISABLED) {
+			i = -1;
+			break;
+		}
+		udelay(10);
+	}
+	if (i != -1) {
+		printk(KERN_ERR PFX "Error: Wait on DMA RX status timed out.\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/* Reset the RX DMA channel */
+int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
+				   u16 mmio_base)
+{
+	int i;
+	u32 value;
+
+	for (i = 0; i < 1000; i++) {
+		value = bcm43xx_read32(bcm,
+				       mmio_base + BCM43xx_DMA_TX_STATUS);
+		value &= BCM43xx_DMA_TXSTAT_STAT_MASK;
+		if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED ||
+		    value == BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT ||
+		    value == BCM43xx_DMA_TXSTAT_STAT_STOPPED)
+			break;
+		udelay(10);
+	}
+	bcm43xx_write32(bcm,
+			mmio_base + BCM43xx_DMA_TX_CONTROL,
+			0x00000000);
+	for (i = 0; i < 1000; i++) {
+		value = bcm43xx_read32(bcm,
+				       mmio_base + BCM43xx_DMA_TX_STATUS);
+		value &= BCM43xx_DMA_TXSTAT_STAT_MASK;
+		if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED) {
+			i = -1;
+			break;
+		}
+		udelay(10);
+	}
+	if (i != -1) {
+		printk(KERN_ERR PFX "Error: Wait on DMA TX status timed out.\n");
+		return -ENODEV;
+	}
+	/* ensure the reset is completed. */
+	udelay(300);
+
+	return 0;
+}
+
+static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring,
+			       struct bcm43xx_dmadesc *desc,
+			       struct bcm43xx_dmadesc_meta *meta,
+			       gfp_t gfp_flags)
+{
+	struct bcm43xx_rxhdr *rxhdr;
+	dma_addr_t dmaaddr;
+	u32 desc_addr;
+	u32 desc_ctl;
+	const int slot = (int)(desc - ring->vbase);
+	struct sk_buff *skb;
+
+	assert(slot >= 0 && slot < ring->nr_slots);
+	assert(!ring->tx);
+
+	skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
+	if (unlikely(!skb))
+		return -ENOMEM;
+	dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
+	if (unlikely(dmaaddr + ring->rx_buffersize > BCM43xx_DMA_BUSADDRMAX)) {
+		unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
+		dev_kfree_skb_any(skb);
+		printk(KERN_ERR PFX ">>>FATAL ERROR<<<  DMA RX SKB >1G "
+				    "(0x%08x, len: %u)\n",
+		       dmaaddr, ring->rx_buffersize);
+		return -ENOMEM;
+	}
+	meta->skb = skb;
+	meta->dmaaddr = dmaaddr;
+	skb->dev = ring->bcm->net_dev;
+	desc_addr = (u32)(dmaaddr + ring->memoffset);
+	desc_ctl = (BCM43xx_DMADTOR_BYTECNT_MASK &
+		    (u32)(ring->rx_buffersize - ring->frameoffset));
+	if (slot == ring->nr_slots - 1)
+		desc_ctl |= BCM43xx_DMADTOR_DTABLEEND;
+	set_desc_addr(desc, desc_addr);
+	set_desc_ctl(desc, desc_ctl);
+
+	rxhdr = (struct bcm43xx_rxhdr *)(skb->data);
+	rxhdr->frame_length = 0;
+	rxhdr->flags1 = 0;
+
+	return 0;
+}
+
+/* Allocate the initial descbuffers.
+ * This is used for an RX ring only.
+ */
+static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring)
+{
+	int i, err = -ENOMEM;
+	struct bcm43xx_dmadesc *desc;
+	struct bcm43xx_dmadesc_meta *meta;
+
+	for (i = 0; i < ring->nr_slots; i++) {
+		desc = ring->vbase + i;
+		meta = ring->meta + i;
+
+		err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
+		if (err)
+			goto err_unwind;
+	}
+	ring->used_slots = ring->nr_slots;
+	err = 0;
+out:
+	return err;
+
+err_unwind:
+	for (i--; i >= 0; i--) {
+		desc = ring->vbase + i;
+		meta = ring->meta + i;
+
+		unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
+		dev_kfree_skb(meta->skb);
+	}
+	goto out;
+}
+
+/* Do initial setup of the DMA controller.
+ * Reset the controller, write the ring busaddress
+ * and switch the "enable" bit on.
+ */
+static int dmacontroller_setup(struct bcm43xx_dmaring *ring)
+{
+	int err = 0;
+	u32 value;
+
+	if (ring->tx) {
+		/* Set Transmit Control register to "transmit enable" */
+		bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL,
+				  BCM43xx_DMA_TXCTRL_ENABLE);
+		/* Set Transmit Descriptor ring address. */
+		bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING,
+				  ring->dmabase + ring->memoffset);
+	} else {
+		err = alloc_initial_descbuffers(ring);
+		if (err)
+			goto out;
+		/* Set Receive Control "receive enable" and frame offset */
+		value = (ring->frameoffset << BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT);
+		value |= BCM43xx_DMA_RXCTRL_ENABLE;
+		bcm43xx_dma_write(ring, BCM43xx_DMA_RX_CONTROL, value);
+		/* Set Receive Descriptor ring address. */
+		bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING,
+				  ring->dmabase + ring->memoffset);
+		/* Init the descriptor pointer. */
+		bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX, 200);
+	}
+
+out:
+	return err;
+}
+
+/* Shutdown the DMA controller. */
+static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring)
+{
+	if (ring->tx) {
+		bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base);
+		/* Zero out Transmit Descriptor ring address. */
+		bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING, 0);
+	} else {
+		bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base);
+		/* Zero out Receive Descriptor ring address. */
+		bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING, 0);
+	}
+}
+
+static void free_all_descbuffers(struct bcm43xx_dmaring *ring)
+{
+	struct bcm43xx_dmadesc *desc;
+	struct bcm43xx_dmadesc_meta *meta;
+	int i;
+
+	if (!ring->used_slots)
+		return;
+	for (i = 0; i < ring->nr_slots; i++) {
+		desc = ring->vbase + i;
+		meta = ring->meta + i;
+
+		if (!meta->skb) {
+			assert(ring->tx);
+			continue;
+		}
+		if (ring->tx) {
+			unmap_descbuffer(ring, meta->dmaaddr,
+					 meta->skb->len, 1);
+		} else {
+			unmap_descbuffer(ring, meta->dmaaddr,
+					 ring->rx_buffersize, 0);
+		}
+		free_descriptor_buffer(ring, desc, meta, 0);
+	}
+}
+
+/* Main initialization function. */
+static
+struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
+					       u16 dma_controller_base,
+					       int nr_descriptor_slots,
+					       int tx)
+{
+	struct bcm43xx_dmaring *ring;
+	int err;
+
+	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
+	if (!ring)
+		goto out;
+
+	ring->meta = kzalloc(sizeof(*ring->meta) * nr_descriptor_slots,
+			     GFP_KERNEL);
+	if (!ring->meta)
+		goto err_kfree_ring;
+
+	ring->memoffset = BCM43xx_DMA_DMABUSADDROFFSET;
+#ifdef CONFIG_BCM947XX
+	if (bcm->pci_dev->bus->number == 0)
+		ring->memoffset = 0;
+#endif
+
+	ring->bcm = bcm;
+	ring->nr_slots = nr_descriptor_slots;
+	ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100;
+	ring->resume_mark = ring->nr_slots * BCM43xx_TXRESUME_PERCENT / 100;
+	assert(ring->suspend_mark < ring->resume_mark);
+	ring->mmio_base = dma_controller_base;
+	if (tx) {
+		ring->tx = 1;
+		ring->current_slot = -1;
+	} else {
+		switch (dma_controller_base) {
+		case BCM43xx_MMIO_DMA1_BASE:
+			ring->rx_buffersize = BCM43xx_DMA1_RXBUFFERSIZE;
+			ring->frameoffset = BCM43xx_DMA1_RX_FRAMEOFFSET;
+			break;
+		case BCM43xx_MMIO_DMA4_BASE:
+			ring->rx_buffersize = BCM43xx_DMA4_RXBUFFERSIZE;
+			ring->frameoffset = BCM43xx_DMA4_RX_FRAMEOFFSET;
+			break;
+		default:
+			assert(0);
+		}
+	}
+
+	err = alloc_ringmemory(ring);
+	if (err)
+		goto err_kfree_meta;
+	err = dmacontroller_setup(ring);
+	if (err)
+		goto err_free_ringmemory;
+
+out:
+	return ring;
+
+err_free_ringmemory:
+	free_ringmemory(ring);
+err_kfree_meta:
+	kfree(ring->meta);
+err_kfree_ring:
+	kfree(ring);
+	ring = NULL;
+	goto out;
+}
+
+/* Main cleanup function. */
+static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring)
+{
+	if (!ring)
+		return;
+
+	dprintk(KERN_INFO PFX "DMA 0x%04x (%s) max used slots: %d/%d\n",
+		ring->mmio_base,
+		(ring->tx) ? "TX" : "RX",
+		ring->max_used_slots, ring->nr_slots);
+	/* Device IRQs are disabled prior entering this function,
+	 * so no need to take care of concurrency with rx handler stuff.
+	 */
+	dmacontroller_cleanup(ring);
+	free_all_descbuffers(ring);
+	free_ringmemory(ring);
+
+	kfree(ring->meta);
+	kfree(ring);
+}
+
+void bcm43xx_dma_free(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_dma *dma;
+
+	if (bcm43xx_using_pio(bcm))
+		return;
+	dma = bcm43xx_current_dma(bcm);
+
+	bcm43xx_destroy_dmaring(dma->rx_ring1);
+	dma->rx_ring1 = NULL;
+	bcm43xx_destroy_dmaring(dma->rx_ring0);
+	dma->rx_ring0 = NULL;
+	bcm43xx_destroy_dmaring(dma->tx_ring3);
+	dma->tx_ring3 = NULL;
+	bcm43xx_destroy_dmaring(dma->tx_ring2);
+	dma->tx_ring2 = NULL;
+	bcm43xx_destroy_dmaring(dma->tx_ring1);
+	dma->tx_ring1 = NULL;
+	bcm43xx_destroy_dmaring(dma->tx_ring0);
+	dma->tx_ring0 = NULL;
+}
+
+int bcm43xx_dma_init(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm);
+	struct bcm43xx_dmaring *ring;
+	int err = -ENOMEM;
+
+	/* setup TX DMA channels. */
+	ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE,
+				     BCM43xx_TXRING_SLOTS, 1);
+	if (!ring)
+		goto out;
+	dma->tx_ring0 = ring;
+
+	ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA2_BASE,
+				     BCM43xx_TXRING_SLOTS, 1);
+	if (!ring)
+		goto err_destroy_tx0;
+	dma->tx_ring1 = ring;
+
+	ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA3_BASE,
+				     BCM43xx_TXRING_SLOTS, 1);
+	if (!ring)
+		goto err_destroy_tx1;
+	dma->tx_ring2 = ring;
+
+	ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE,
+				     BCM43xx_TXRING_SLOTS, 1);
+	if (!ring)
+		goto err_destroy_tx2;
+	dma->tx_ring3 = ring;
+
+	/* setup RX DMA channels. */
+	ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE,
+				     BCM43xx_RXRING_SLOTS, 0);
+	if (!ring)
+		goto err_destroy_tx3;
+	dma->rx_ring0 = ring;
+
+	if (bcm->current_core->rev < 5) {
+		ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE,
+					     BCM43xx_RXRING_SLOTS, 0);
+		if (!ring)
+			goto err_destroy_rx0;
+		dma->rx_ring1 = ring;
+	}
+
+	dprintk(KERN_INFO PFX "DMA initialized\n");
+	err = 0;
+out:
+	return err;
+
+err_destroy_rx0:
+	bcm43xx_destroy_dmaring(dma->rx_ring0);
+	dma->rx_ring0 = NULL;
+err_destroy_tx3:
+	bcm43xx_destroy_dmaring(dma->tx_ring3);
+	dma->tx_ring3 = NULL;
+err_destroy_tx2:
+	bcm43xx_destroy_dmaring(dma->tx_ring2);
+	dma->tx_ring2 = NULL;
+err_destroy_tx1:
+	bcm43xx_destroy_dmaring(dma->tx_ring1);
+	dma->tx_ring1 = NULL;
+err_destroy_tx0:
+	bcm43xx_destroy_dmaring(dma->tx_ring0);
+	dma->tx_ring0 = NULL;
+	goto out;
+}
+
+/* Generate a cookie for the TX header. */
+static u16 generate_cookie(struct bcm43xx_dmaring *ring,
+			   int slot)
+{
+	u16 cookie = 0x0000;
+
+	/* Use the upper 4 bits of the cookie as
+	 * DMA controller ID and store the slot number
+	 * in the lower 12 bits
+	 */
+	switch (ring->mmio_base) {
+	default:
+		assert(0);
+	case BCM43xx_MMIO_DMA1_BASE:
+		break;
+	case BCM43xx_MMIO_DMA2_BASE:
+		cookie = 0x1000;
+		break;
+	case BCM43xx_MMIO_DMA3_BASE:
+		cookie = 0x2000;
+		break;
+	case BCM43xx_MMIO_DMA4_BASE:
+		cookie = 0x3000;
+		break;
+	}
+	assert(((u16)slot & 0xF000) == 0x0000);
+	cookie |= (u16)slot;
+
+	return cookie;
+}
+
+/* Inspect a cookie and find out to which controller/slot it belongs. */
+static
+struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm,
+				      u16 cookie, int *slot)
+{
+	struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm);
+	struct bcm43xx_dmaring *ring = NULL;
+
+	switch (cookie & 0xF000) {
+	case 0x0000:
+		ring = dma->tx_ring0;
+		break;
+	case 0x1000:
+		ring = dma->tx_ring1;
+		break;
+	case 0x2000:
+		ring = dma->tx_ring2;
+		break;
+	case 0x3000:
+		ring = dma->tx_ring3;
+		break;
+	default:
+		assert(0);
+	}
+	*slot = (cookie & 0x0FFF);
+	assert(*slot >= 0 && *slot < ring->nr_slots);
+
+	return ring;
+}
+
+static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring,
+				  int slot)
+{
+	/* Everything is ready to start. Buffers are DMA mapped and
+	 * associated with slots.
+	 * "slot" is the last slot of the new frame we want to transmit.
+	 * Close your seat belts now, please.
+	 */
+	wmb();
+	slot = next_slot(ring, slot);
+	bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_INDEX,
+			  (u32)(slot * sizeof(struct bcm43xx_dmadesc)));
+}
+
+static int dma_tx_fragment(struct bcm43xx_dmaring *ring,
+			   struct sk_buff *skb,
+			   u8 cur_frag)
+{
+	int slot;
+	struct bcm43xx_dmadesc *desc;
+	struct bcm43xx_dmadesc_meta *meta;
+	u32 desc_ctl;
+	u32 desc_addr;
+
+	assert(skb_shinfo(skb)->nr_frags == 0);
+
+	slot = request_slot(ring);
+	desc = ring->vbase + slot;
+	meta = ring->meta + slot;
+
+	/* Add a device specific TX header. */
+	assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr));
+	/* Reserve enough headroom for the device tx header. */
+	__skb_push(skb, sizeof(struct bcm43xx_txhdr));
+	/* Now calculate and add the tx header.
+	 * The tx header includes the PLCP header.
+	 */
+	bcm43xx_generate_txhdr(ring->bcm,
+			       (struct bcm43xx_txhdr *)skb->data,
+			       skb->data + sizeof(struct bcm43xx_txhdr),
+			       skb->len - sizeof(struct bcm43xx_txhdr),
+			       (cur_frag == 0),
+			       generate_cookie(ring, slot));
+
+	meta->skb = skb;
+	meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+	if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) {
+		return_slot(ring, slot);
+		printk(KERN_ERR PFX ">>>FATAL ERROR<<<  DMA TX SKB >1G "
+				    "(0x%08x, len: %u)\n",
+		       meta->dmaaddr, skb->len);
+		return -ENOMEM;
+	}
+
+	desc_addr = (u32)(meta->dmaaddr + ring->memoffset);
+	desc_ctl = BCM43xx_DMADTOR_FRAMESTART | BCM43xx_DMADTOR_FRAMEEND;
+	desc_ctl |= BCM43xx_DMADTOR_COMPIRQ;
+	desc_ctl |= (BCM43xx_DMADTOR_BYTECNT_MASK &
+		     (u32)(meta->skb->len - ring->frameoffset));
+	if (slot == ring->nr_slots - 1)
+		desc_ctl |= BCM43xx_DMADTOR_DTABLEEND;
+
+	set_desc_ctl(desc, desc_ctl);
+	set_desc_addr(desc, desc_addr);
+	/* Now transfer the whole frame. */
+	dmacontroller_poke_tx(ring, slot);
+
+	return 0;
+}
+
+int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
+		   struct ieee80211_txb *txb)
+{
+	/* We just received a packet from the kernel network subsystem.
+	 * Add headers and DMA map the memory. Poke
+	 * the device to send the stuff.
+	 * Note that this is called from atomic context.
+	 */
+	struct bcm43xx_dmaring *ring = bcm43xx_current_dma(bcm)->tx_ring1;
+	u8 i;
+	struct sk_buff *skb;
+
+	assert(ring->tx);
+	if (unlikely(free_slots(ring) < txb->nr_frags)) {
+		/* The queue should be stopped,
+		 * if we are low on free slots.
+		 * If this ever triggers, we have to lower the suspend_mark.
+		 */
+		dprintkl(KERN_ERR PFX "Out of DMA descriptor slots!\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < txb->nr_frags; i++) {
+		skb = txb->fragments[i];
+		/* Take skb from ieee80211_txb_free */
+		txb->fragments[i] = NULL;
+		dma_tx_fragment(ring, skb, i);
+		//TODO: handle failure of dma_tx_fragment
+	}
+	ieee80211_txb_free(txb);
+
+	return 0;
+}
+
+void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
+				   struct bcm43xx_xmitstatus *status)
+{
+	struct bcm43xx_dmaring *ring;
+	struct bcm43xx_dmadesc *desc;
+	struct bcm43xx_dmadesc_meta *meta;
+	int is_last_fragment;
+	int slot;
+
+	ring = parse_cookie(bcm, status->cookie, &slot);
+	assert(ring);
+	assert(ring->tx);
+	assert(get_desc_ctl(ring->vbase + slot) & BCM43xx_DMADTOR_FRAMESTART);
+	while (1) {
+		assert(slot >= 0 && slot < ring->nr_slots);
+		desc = ring->vbase + slot;
+		meta = ring->meta + slot;
+
+		is_last_fragment = !!(get_desc_ctl(desc) & BCM43xx_DMADTOR_FRAMEEND);
+		unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
+		free_descriptor_buffer(ring, desc, meta, 1);
+		/* Everything belonging to the slot is unmapped
+		 * and freed, so we can return it.
+		 */
+		return_slot(ring, slot);
+
+		if (is_last_fragment)
+			break;
+		slot = next_slot(ring, slot);
+	}
+	bcm->stats.last_tx = jiffies;
+}
+
+static void dma_rx(struct bcm43xx_dmaring *ring,
+		   int *slot)
+{
+	struct bcm43xx_dmadesc *desc;
+	struct bcm43xx_dmadesc_meta *meta;
+	struct bcm43xx_rxhdr *rxhdr;
+	struct sk_buff *skb;
+	u16 len;
+	int err;
+	dma_addr_t dmaaddr;
+
+	desc = ring->vbase + *slot;
+	meta = ring->meta + *slot;
+
+	sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
+	skb = meta->skb;
+
+	if (ring->mmio_base == BCM43xx_MMIO_DMA4_BASE) {
+		/* We received an xmit status. */
+		struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data;
+		struct bcm43xx_xmitstatus stat;
+
+		stat.cookie = le16_to_cpu(hw->cookie);
+		stat.flags = hw->flags;
+		stat.cnt1 = hw->cnt1;
+		stat.cnt2 = hw->cnt2;
+		stat.seq = le16_to_cpu(hw->seq);
+		stat.unknown = le16_to_cpu(hw->unknown);
+
+		bcm43xx_debugfs_log_txstat(ring->bcm, &stat);
+		bcm43xx_dma_handle_xmitstatus(ring->bcm, &stat);
+		/* recycle the descriptor buffer. */
+		sync_descbuffer_for_device(ring, meta->dmaaddr, ring->rx_buffersize);
+
+		return;
+	}
+	rxhdr = (struct bcm43xx_rxhdr *)skb->data;
+	len = le16_to_cpu(rxhdr->frame_length);
+	if (len == 0) {
+		int i = 0;
+
+		do {
+			udelay(2);
+			barrier();
+			len = le16_to_cpu(rxhdr->frame_length);
+		} while (len == 0 && i++ < 5);
+		if (unlikely(len == 0)) {
+			/* recycle the descriptor buffer. */
+			sync_descbuffer_for_device(ring, meta->dmaaddr,
+						   ring->rx_buffersize);
+			goto drop;
+		}
+	}
+	if (unlikely(len > ring->rx_buffersize)) {
+		/* The data did not fit into one descriptor buffer
+		 * and is split over multiple buffers.
+		 * This should never happen, as we try to allocate buffers
+		 * big enough. So simply ignore this packet.
+		 */
+		int cnt = 0;
+		s32 tmp = len;
+
+		while (1) {
+			desc = ring->vbase + *slot;
+			meta = ring->meta + *slot;
+			/* recycle the descriptor buffer. */
+			sync_descbuffer_for_device(ring, meta->dmaaddr,
+						   ring->rx_buffersize);
+			*slot = next_slot(ring, *slot);
+			cnt++;
+			tmp -= ring->rx_buffersize;
+			if (tmp <= 0)
+				break;
+		}
+		printkl(KERN_ERR PFX "DMA RX buffer too small "
+				     "(len: %u, buffer: %u, nr-dropped: %d)\n",
+		        len, ring->rx_buffersize, cnt);
+		goto drop;
+	}
+	len -= IEEE80211_FCS_LEN;
+
+	dmaaddr = meta->dmaaddr;
+	err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC);
+	if (unlikely(err)) {
+		dprintkl(KERN_ERR PFX "DMA RX: setup_rx_descbuffer() failed\n");
+		sync_descbuffer_for_device(ring, dmaaddr,
+					   ring->rx_buffersize);
+		goto drop;
+	}
+
+	unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
+	skb_put(skb, len + ring->frameoffset);
+	skb_pull(skb, ring->frameoffset);
+
+	err = bcm43xx_rx(ring->bcm, skb, rxhdr);
+	if (err) {
+		dev_kfree_skb_irq(skb);
+		goto drop;
+	}
+
+drop:
+	return;
+}
+
+void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
+{
+	u32 status;
+	u16 descptr;
+	int slot, current_slot;
+#ifdef CONFIG_BCM43XX_DEBUG
+	int used_slots = 0;
+#endif
+
+	assert(!ring->tx);
+	status = bcm43xx_dma_read(ring, BCM43xx_DMA_RX_STATUS);
+	descptr = (status & BCM43xx_DMA_RXSTAT_DPTR_MASK);
+	current_slot = descptr / sizeof(struct bcm43xx_dmadesc);
+	assert(current_slot >= 0 && current_slot < ring->nr_slots);
+
+	slot = ring->current_slot;
+	for ( ; slot != current_slot; slot = next_slot(ring, slot)) {
+		dma_rx(ring, &slot);
+#ifdef CONFIG_BCM43XX_DEBUG
+		if (++used_slots > ring->max_used_slots)
+			ring->max_used_slots = used_slots;
+#endif
+	}
+	bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX,
+			  (u32)(slot * sizeof(struct bcm43xx_dmadesc)));
+	ring->current_slot = slot;
+}
+
+void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
+{
+	assert(ring->tx);
+	bcm43xx_power_saving_ctl_bits(ring->bcm, -1, 1);
+	bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL,
+			  bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL)
+			  | BCM43xx_DMA_TXCTRL_SUSPEND);
+}
+
+void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
+{
+	assert(ring->tx);
+	bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL,
+			  bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL)
+			  & ~BCM43xx_DMA_TXCTRL_SUSPEND);
+	bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1);
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
new file mode 100644
index 0000000..2d520e4
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
@@ -0,0 +1,218 @@
+#ifndef BCM43xx_DMA_H_
+#define BCM43xx_DMA_H_
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/linkage.h>
+#include <asm/atomic.h>
+
+
+/* DMA-Interrupt reasons. */
+#define BCM43xx_DMAIRQ_FATALMASK	((1 << 10) | (1 << 11) | (1 << 12) \
+					 | (1 << 14) | (1 << 15))
+#define BCM43xx_DMAIRQ_NONFATALMASK	(1 << 13)
+#define BCM43xx_DMAIRQ_RX_DONE		(1 << 16)
+
+/* DMA controller register offsets. (relative to BCM43xx_DMA#_BASE) */
+#define BCM43xx_DMA_TX_CONTROL		0x00
+#define BCM43xx_DMA_TX_DESC_RING	0x04
+#define BCM43xx_DMA_TX_DESC_INDEX	0x08
+#define BCM43xx_DMA_TX_STATUS		0x0c
+#define BCM43xx_DMA_RX_CONTROL		0x10
+#define BCM43xx_DMA_RX_DESC_RING	0x14
+#define BCM43xx_DMA_RX_DESC_INDEX	0x18
+#define BCM43xx_DMA_RX_STATUS		0x1c
+
+/* DMA controller channel control word values. */
+#define BCM43xx_DMA_TXCTRL_ENABLE		(1 << 0)
+#define BCM43xx_DMA_TXCTRL_SUSPEND		(1 << 1)
+#define BCM43xx_DMA_TXCTRL_LOOPBACK		(1 << 2)
+#define BCM43xx_DMA_TXCTRL_FLUSH		(1 << 4)
+#define BCM43xx_DMA_RXCTRL_ENABLE		(1 << 0)
+#define BCM43xx_DMA_RXCTRL_FRAMEOFF_MASK	0x000000fe
+#define BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT	1
+#define BCM43xx_DMA_RXCTRL_PIO			(1 << 8)
+/* DMA controller channel status word values. */
+#define BCM43xx_DMA_TXSTAT_DPTR_MASK		0x00000fff
+#define BCM43xx_DMA_TXSTAT_STAT_MASK		0x0000f000
+#define BCM43xx_DMA_TXSTAT_STAT_DISABLED	0x00000000
+#define BCM43xx_DMA_TXSTAT_STAT_ACTIVE		0x00001000
+#define BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT	0x00002000
+#define BCM43xx_DMA_TXSTAT_STAT_STOPPED		0x00003000
+#define BCM43xx_DMA_TXSTAT_STAT_SUSP		0x00004000
+#define BCM43xx_DMA_TXSTAT_ERROR_MASK		0x000f0000
+#define BCM43xx_DMA_TXSTAT_FLUSHED		(1 << 20)
+#define BCM43xx_DMA_RXSTAT_DPTR_MASK		0x00000fff
+#define BCM43xx_DMA_RXSTAT_STAT_MASK		0x0000f000
+#define BCM43xx_DMA_RXSTAT_STAT_DISABLED	0x00000000
+#define BCM43xx_DMA_RXSTAT_STAT_ACTIVE		0x00001000
+#define BCM43xx_DMA_RXSTAT_STAT_IDLEWAIT	0x00002000
+#define BCM43xx_DMA_RXSTAT_STAT_RESERVED	0x00003000
+#define BCM43xx_DMA_RXSTAT_STAT_ERRORS		0x00004000
+#define BCM43xx_DMA_RXSTAT_ERROR_MASK		0x000f0000
+
+/* DMA descriptor control field values. */
+#define BCM43xx_DMADTOR_BYTECNT_MASK		0x00001fff
+#define BCM43xx_DMADTOR_DTABLEEND		(1 << 28) /* End of descriptor table */
+#define BCM43xx_DMADTOR_COMPIRQ			(1 << 29) /* IRQ on completion request */
+#define BCM43xx_DMADTOR_FRAMEEND		(1 << 30)
+#define BCM43xx_DMADTOR_FRAMESTART		(1 << 31)
+
+/* Misc DMA constants */
+#define BCM43xx_DMA_RINGMEMSIZE		PAGE_SIZE
+#define BCM43xx_DMA_BUSADDRMAX		0x3FFFFFFF
+#define BCM43xx_DMA_DMABUSADDROFFSET	(1 << 30)
+#define BCM43xx_DMA1_RX_FRAMEOFFSET	30
+#define BCM43xx_DMA4_RX_FRAMEOFFSET	0
+
+/* DMA engine tuning knobs */
+#define BCM43xx_TXRING_SLOTS		512
+#define BCM43xx_RXRING_SLOTS		64
+#define BCM43xx_DMA1_RXBUFFERSIZE	(2304 + 100)
+#define BCM43xx_DMA4_RXBUFFERSIZE	16
+/* Suspend the tx queue, if less than this percent slots are free. */
+#define BCM43xx_TXSUSPEND_PERCENT	20
+/* Resume the tx queue, if more than this percent slots are free. */
+#define BCM43xx_TXRESUME_PERCENT	50
+
+
+
+#ifdef CONFIG_BCM43XX_DMA
+
+
+struct sk_buff;
+struct bcm43xx_private;
+struct bcm43xx_xmitstatus;
+
+
+struct bcm43xx_dmadesc {
+	__le32 _control;
+	__le32 _address;
+} __attribute__((__packed__));
+
+/* Macros to access the bcm43xx_dmadesc struct */
+#define get_desc_ctl(desc)		le32_to_cpu((desc)->_control)
+#define set_desc_ctl(desc, ctl)		do { (desc)->_control = cpu_to_le32(ctl); } while (0)
+#define get_desc_addr(desc)		le32_to_cpu((desc)->_address)
+#define set_desc_addr(desc, addr)	do { (desc)->_address = cpu_to_le32(addr); } while (0)
+
+struct bcm43xx_dmadesc_meta {
+	/* The kernel DMA-able buffer. */
+	struct sk_buff *skb;
+	/* DMA base bus-address of the descriptor buffer. */
+	dma_addr_t dmaaddr;
+};
+
+struct bcm43xx_dmaring {
+	struct bcm43xx_private *bcm;
+	/* Kernel virtual base address of the ring memory. */
+	struct bcm43xx_dmadesc *vbase;
+	/* DMA memory offset */
+	dma_addr_t memoffset;
+	/* (Unadjusted) DMA base bus-address of the ring memory. */
+	dma_addr_t dmabase;
+	/* Meta data about all descriptors. */
+	struct bcm43xx_dmadesc_meta *meta;
+	/* Number of descriptor slots in the ring. */
+	int nr_slots;
+	/* Number of used descriptor slots. */
+	int used_slots;
+	/* Currently used slot in the ring. */
+	int current_slot;
+	/* Marks to suspend/resume the queue. */
+	int suspend_mark;
+	int resume_mark;
+	/* Frameoffset in octets. */
+	u32 frameoffset;
+	/* Descriptor buffer size. */
+	u16 rx_buffersize;
+	/* The MMIO base register of the DMA controller, this
+	 * ring is posted to.
+	 */
+	u16 mmio_base;
+	u8 tx:1,	/* TRUE, if this is a TX ring. */
+	   suspended:1;	/* TRUE, if transfers are suspended on this ring. */
+#ifdef CONFIG_BCM43XX_DEBUG
+	/* Maximum number of used slots. */
+	int max_used_slots;
+#endif /* CONFIG_BCM43XX_DEBUG*/
+};
+
+
+static inline
+u32 bcm43xx_dma_read(struct bcm43xx_dmaring *ring,
+		     u16 offset)
+{
+	return bcm43xx_read32(ring->bcm, ring->mmio_base + offset);
+}
+
+static inline
+void bcm43xx_dma_write(struct bcm43xx_dmaring *ring,
+		       u16 offset, u32 value)
+{
+	bcm43xx_write32(ring->bcm, ring->mmio_base + offset, value);
+}
+
+
+int bcm43xx_dma_init(struct bcm43xx_private *bcm);
+void bcm43xx_dma_free(struct bcm43xx_private *bcm);
+
+int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
+				   u16 dmacontroller_mmio_base);
+int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
+				   u16 dmacontroller_mmio_base);
+
+void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring);
+void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring);
+
+void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
+				   struct bcm43xx_xmitstatus *status);
+
+int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
+		   struct ieee80211_txb *txb);
+void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring);
+
+
+#else /* CONFIG_BCM43XX_DMA */
+
+
+static inline
+int bcm43xx_dma_init(struct bcm43xx_private *bcm)
+{
+	return 0;
+}
+static inline
+void bcm43xx_dma_free(struct bcm43xx_private *bcm)
+{
+}
+static inline
+int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
+				   u16 dmacontroller_mmio_base)
+{
+	return 0;
+}
+static inline
+int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
+				   u16 dmacontroller_mmio_base)
+{
+	return 0;
+}
+static inline
+int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
+		   struct ieee80211_txb *txb)
+{
+	return 0;
+}
+static inline
+void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
+				   struct bcm43xx_xmitstatus *status)
+{
+}
+static inline
+void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
+{
+}
+
+#endif /* CONFIG_BCM43XX_DMA */
+#endif /* BCM43xx_DMA_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
new file mode 100644
index 0000000..b3ffcf5
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
@@ -0,0 +1,50 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  ethtool support
+
+  Copyright (c) 2006 Jason Lunz <lunz@falooley.org>
+
+  Some code in this file is derived from the 8139too.c driver
+  Copyright (C) 2002 Jeff Garzik
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "bcm43xx.h"
+#include "bcm43xx_ethtool.h"
+
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/version.h>
+
+
+static void bcm43xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(dev);
+
+	strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+	strncpy(info->version, UTS_RELEASE, sizeof(info->version));
+	strncpy(info->bus_info, pci_name(bcm->pci_dev), ETHTOOL_BUSINFO_LEN);
+}
+
+struct ethtool_ops bcm43xx_ethtool_ops = {
+	.get_drvinfo = bcm43xx_get_drvinfo,
+	.get_link = ethtool_op_get_link,
+};
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h
new file mode 100644
index 0000000..8137049
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h
@@ -0,0 +1,8 @@
+#ifndef BCM43xx_ETHTOOL_H_
+#define BCM43xx_ETHTOOL_H_
+
+#include <linux/ethtool.h>
+
+extern struct ethtool_ops bcm43xx_ethtool_ops;
+
+#endif /* BCM43xx_ETHTOOL_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
new file mode 100644
index 0000000..ad8e569
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
@@ -0,0 +1,337 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+                     Stefano Brivio <st3@riseup.net>
+                     Michael Buesch <mbuesch@freenet.de>
+                     Danny van Dyk <kugelfang@gentoo.org>
+                     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "bcm43xx.h"
+#include "bcm43xx_ilt.h"
+#include "bcm43xx_phy.h"
+
+
+/**** Initial Internal Lookup Tables ****/
+
+const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE] = {
+	0xFEB93FFD, 0xFEC63FFD, /* 0 */
+	0xFED23FFD, 0xFEDF3FFD,
+	0xFEEC3FFE, 0xFEF83FFE,
+	0xFF053FFE, 0xFF113FFE,
+	0xFF1E3FFE, 0xFF2A3FFF, /* 8 */
+	0xFF373FFF, 0xFF443FFF,
+	0xFF503FFF, 0xFF5D3FFF,
+	0xFF693FFF, 0xFF763FFF,
+	0xFF824000, 0xFF8F4000, /* 16 */
+	0xFF9B4000, 0xFFA84000,
+	0xFFB54000, 0xFFC14000,
+	0xFFCE4000, 0xFFDA4000,
+	0xFFE74000, 0xFFF34000, /* 24 */
+	0x00004000, 0x000D4000,
+	0x00194000, 0x00264000,
+	0x00324000, 0x003F4000,
+	0x004B4000, 0x00584000, /* 32 */
+	0x00654000, 0x00714000,
+	0x007E4000, 0x008A3FFF,
+	0x00973FFF, 0x00A33FFF,
+	0x00B03FFF, 0x00BC3FFF, /* 40 */
+	0x00C93FFF, 0x00D63FFF,
+	0x00E23FFE, 0x00EF3FFE,
+	0x00FB3FFE, 0x01083FFE,
+	0x01143FFE, 0x01213FFD, /* 48 */
+	0x012E3FFD, 0x013A3FFD,
+	0x01473FFD,
+};
+
+const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE] = {
+	0xDB93CB87, 0xD666CF64, /* 0 */
+	0xD1FDD358, 0xCDA6D826,
+	0xCA38DD9F, 0xC729E2B4,
+	0xC469E88E, 0xC26AEE2B,
+	0xC0DEF46C, 0xC073FA62, /* 8 */
+	0xC01D00D5, 0xC0760743,
+	0xC1560D1E, 0xC2E51369,
+	0xC4ED18FF, 0xC7AC1ED7,
+	0xCB2823B2, 0xCEFA28D9, /* 16 */
+	0xD2F62D3F, 0xD7BB3197,
+	0xDCE53568, 0xE1FE3875,
+	0xE7D13B35, 0xED663D35,
+	0xF39B3EC4, 0xF98E3FA7, /* 24 */
+	0x00004000, 0x06723FA7,
+	0x0C653EC4, 0x129A3D35,
+	0x182F3B35, 0x1E023875,
+	0x231B3568, 0x28453197, /* 32 */
+	0x2D0A2D3F, 0x310628D9,
+	0x34D823B2, 0x38541ED7,
+	0x3B1318FF, 0x3D1B1369,
+	0x3EAA0D1E, 0x3F8A0743, /* 40 */
+	0x3FE300D5, 0x3F8DFA62,
+	0x3F22F46C, 0x3D96EE2B,
+	0x3B97E88E, 0x38D7E2B4,
+	0x35C8DD9F, 0x325AD826, /* 48 */
+	0x2E03D358, 0x299ACF64,
+	0x246DCB87,
+};
+
+const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE] = {
+	0x0082, 0x0082, 0x0102, 0x0182, /* 0 */
+ 	0x0202, 0x0282, 0x0302, 0x0382,
+ 	0x0402, 0x0482, 0x0502, 0x0582,
+ 	0x05E2, 0x0662, 0x06E2, 0x0762,
+ 	0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */
+ 	0x09C2, 0x0A22, 0x0AA2, 0x0B02,
+ 	0x0B82, 0x0BE2, 0x0C62, 0x0CC2,
+ 	0x0D42, 0x0DA2, 0x0E02, 0x0E62,
+ 	0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */
+ 	0x1062, 0x10C2, 0x1122, 0x1182,
+ 	0x11E2, 0x1242, 0x12A2, 0x12E2,
+ 	0x1342, 0x13A2, 0x1402, 0x1442,
+ 	0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */
+ 	0x15E2, 0x1622, 0x1662, 0x16C1,
+ 	0x1701, 0x1741, 0x1781, 0x17E1,
+ 	0x1821, 0x1861, 0x18A1, 0x18E1,
+ 	0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */
+ 	0x1A21, 0x1A61, 0x1AA1, 0x1AC1,
+ 	0x1B01, 0x1B41, 0x1B81, 0x1BA1,
+ 	0x1BE1, 0x1C21, 0x1C41, 0x1C81,
+ 	0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */
+ 	0x1D61, 0x1DA1, 0x1DC1, 0x1E01,
+ 	0x1E21, 0x1E61, 0x1E81, 0x1EA1,
+ 	0x1EE1, 0x1F01, 0x1F21, 0x1F41,
+ 	0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */
+ 	0x2001, 0x2041, 0x2061, 0x2081,
+ 	0x20A1, 0x20C1, 0x20E1, 0x2101,
+ 	0x2121, 0x2141, 0x2161, 0x2181,
+ 	0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */
+ 	0x2221, 0x2241, 0x2261, 0x2281,
+ 	0x22A1, 0x22C1, 0x22C1, 0x22E1,
+ 	0x2301, 0x2321, 0x2341, 0x2361,
+ 	0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */
+ 	0x23E1, 0x23E1, 0x2401, 0x2421,
+ 	0x2441, 0x2441, 0x2461, 0x2481,
+ 	0x2481, 0x24A1, 0x24C1, 0x24C1,
+ 	0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */
+ 	0x2541, 0x2541, 0x2561, 0x2561,
+ 	0x2581, 0x25A1, 0x25A1, 0x25C1,
+ 	0x25C1, 0x25E1, 0x2601, 0x2601,
+ 	0x2621, 0x2621, 0x2641, 0x2641, /* 160 */
+ 	0x2661, 0x2661, 0x2681, 0x2681,
+ 	0x26A1, 0x26A1, 0x26C1, 0x26C1,
+ 	0x26E1, 0x26E1, 0x2701, 0x2701,
+ 	0x2721, 0x2721, 0x2740, 0x2740, /* 176 */
+ 	0x2760, 0x2760, 0x2780, 0x2780,
+ 	0x2780, 0x27A0, 0x27A0, 0x27C0,
+ 	0x27C0, 0x27E0, 0x27E0, 0x27E0,
+ 	0x2800, 0x2800, 0x2820, 0x2820, /* 192 */
+ 	0x2820, 0x2840, 0x2840, 0x2840,
+ 	0x2860, 0x2860, 0x2880, 0x2880,
+ 	0x2880, 0x28A0, 0x28A0, 0x28A0,
+ 	0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */
+ 	0x28E0, 0x28E0, 0x2900, 0x2900,
+ 	0x2900, 0x2920, 0x2920, 0x2920,
+ 	0x2940, 0x2940, 0x2940, 0x2960,
+ 	0x2960, 0x2960, 0x2960, 0x2980, /* 224 */
+ 	0x2980, 0x2980, 0x29A0, 0x29A0,
+ 	0x29A0, 0x29A0, 0x29C0, 0x29C0,
+ 	0x29C0, 0x29E0, 0x29E0, 0x29E0,
+ 	0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */
+ 	0x2A00, 0x2A20, 0x2A20, 0x2A20,
+ 	0x2A20, 0x2A40, 0x2A40, 0x2A40,
+ 	0x2A40, 0x2A60, 0x2A60, 0x2A60,
+};
+
+const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE] = {
+	0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */
+	0x05A9, 0x0669, 0x0709, 0x0789,
+	0x0829, 0x08A9, 0x0929, 0x0989,
+	0x0A09, 0x0A69, 0x0AC9, 0x0B29,
+	0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */
+	0x0D09, 0x0D69, 0x0DA9, 0x0E09,
+	0x0E69, 0x0EA9, 0x0F09, 0x0F49,
+	0x0FA9, 0x0FE9, 0x1029, 0x1089,
+	0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */
+	0x11E9, 0x1229, 0x1289, 0x12C9,
+	0x1309, 0x1349, 0x1389, 0x13C9,
+	0x1409, 0x1449, 0x14A9, 0x14E9,
+	0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */
+	0x1629, 0x1669, 0x16A9, 0x16E8,
+	0x1728, 0x1768, 0x17A8, 0x17E8,
+	0x1828, 0x1868, 0x18A8, 0x18E8,
+	0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */
+	0x1A28, 0x1A68, 0x1AA8, 0x1AE8,
+	0x1B28, 0x1B68, 0x1BA8, 0x1BE8,
+	0x1C28, 0x1C68, 0x1CA8, 0x1CE8,
+	0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */
+	0x1E48, 0x1E88, 0x1EC8, 0x1F08,
+	0x1F48, 0x1F88, 0x1FE8, 0x2028,
+	0x2068, 0x20A8, 0x2108, 0x2148,
+	0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */
+	0x22C8, 0x2308, 0x2348, 0x23A8,
+	0x23E8, 0x2448, 0x24A8, 0x24E8,
+	0x2548, 0x25A8, 0x2608, 0x2668,
+	0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */
+	0x2847, 0x28C7, 0x2947, 0x29A7,
+	0x2A27, 0x2AC7, 0x2B47, 0x2BE7,
+	0x2CA7, 0x2D67, 0x2E47, 0x2F67,
+	0x3247, 0x3526, 0x3646, 0x3726, /* 128 */
+	0x3806, 0x38A6, 0x3946, 0x39E6,
+	0x3A66, 0x3AE6, 0x3B66, 0x3BC6,
+	0x3C45, 0x3CA5, 0x3D05, 0x3D85,
+	0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */
+	0x3F45, 0x3FA5, 0x4005, 0x4045,
+	0x40A5, 0x40E5, 0x4145, 0x4185,
+	0x41E5, 0x4225, 0x4265, 0x42C5,
+	0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */
+	0x4424, 0x4464, 0x44C4, 0x4504,
+	0x4544, 0x4584, 0x45C4, 0x4604,
+	0x4644, 0x46A4, 0x46E4, 0x4724,
+	0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */
+	0x4864, 0x48A4, 0x48E4, 0x4924,
+	0x4964, 0x49A4, 0x49E4, 0x4A24,
+	0x4A64, 0x4AA4, 0x4AE4, 0x4B23,
+	0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */
+	0x4C63, 0x4CA3, 0x4CE3, 0x4D23,
+	0x4D63, 0x4DA3, 0x4DE3, 0x4E23,
+	0x4E63, 0x4EA3, 0x4EE3, 0x4F23,
+	0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */
+	0x5083, 0x50C3, 0x5103, 0x5143,
+	0x5183, 0x51E2, 0x5222, 0x5262,
+	0x52A2, 0x52E2, 0x5342, 0x5382,
+	0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */
+	0x5502, 0x5542, 0x55A2, 0x55E2,
+	0x5642, 0x5682, 0x56E2, 0x5722,
+	0x5782, 0x57E1, 0x5841, 0x58A1,
+	0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */
+	0x5AA1, 0x5B01, 0x5B81, 0x5BE1,
+	0x5C61, 0x5D01, 0x5D80, 0x5E20,
+	0x5EE0, 0x5FA0, 0x6080, 0x61C0,
+};
+
+const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE] = {
+	0x0001, 0x0001, 0x0001, 0xFFFE,
+	0xFFFE, 0x3FFF, 0x1000, 0x0393,
+};
+
+const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE] = {
+	0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
+	0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
+};
+
+const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE] = {
+	0x013C, 0x01F5, 0x031A, 0x0631,
+	0x0001, 0x0001, 0x0001, 0x0001,
+};
+
+const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE] = {
+	0x5484, 0x3C40, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE] = {
+	0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */
+	0x2F2D, 0x2A2A, 0x2527, 0x1F21,
+	0x1A1D, 0x1719, 0x1616, 0x1414,
+	0x1414, 0x1400, 0x1414, 0x1614,
+	0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */
+	0x2A27, 0x2F2A, 0x332D, 0x3B35,
+	0x5140, 0x6C62, 0x0077,
+};
+
+const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE] = {
+	0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */
+	0xB2B0, 0xADAD, 0xA7A9, 0x9FA1,
+	0x969B, 0x9195, 0x8F8F, 0x8A8A,
+	0x8A8A, 0x8A00, 0x8A8A, 0x8F8A,
+	0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */
+	0xADA9, 0xB2AD, 0xB6B0, 0xBCB7,
+	0xCBC0, 0xD8D4, 0x00DD,
+};
+
+const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE] = {
+	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */
+	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+	0xA4A4, 0xA400, 0xA4A4, 0xA4A4,
+	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */
+	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+	0xA4A4, 0xA4A4, 0x00A4,
+};
+
+const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE] = {
+	0x007A, 0x0075, 0x0071, 0x006C, /* 0 */
+	0x0067, 0x0063, 0x005E, 0x0059,
+	0x0054, 0x0050, 0x004B, 0x0046,
+	0x0042, 0x003D, 0x003D, 0x003D,
+	0x003D, 0x003D, 0x003D, 0x003D, /* 16 */
+	0x003D, 0x003D, 0x003D, 0x003D,
+	0x003D, 0x003D, 0x0000, 0x003D,
+	0x003D, 0x003D, 0x003D, 0x003D,
+	0x003D, 0x003D, 0x003D, 0x003D, /* 32 */
+	0x003D, 0x003D, 0x003D, 0x003D,
+	0x0042, 0x0046, 0x004B, 0x0050,
+	0x0054, 0x0059, 0x005E, 0x0063,
+	0x0067, 0x006C, 0x0071, 0x0075, /* 48 */
+	0x007A,
+};
+
+const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE] = {
+	0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */
+	0x00D6, 0x00D4, 0x00D2, 0x00CF,
+	0x00CD, 0x00CA, 0x00C7, 0x00C4,
+	0x00C1, 0x00BE, 0x00BE, 0x00BE,
+	0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */
+	0x00BE, 0x00BE, 0x00BE, 0x00BE,
+	0x00BE, 0x00BE, 0x0000, 0x00BE,
+	0x00BE, 0x00BE, 0x00BE, 0x00BE,
+	0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */
+	0x00BE, 0x00BE, 0x00BE, 0x00BE,
+	0x00C1, 0x00C4, 0x00C7, 0x00CA,
+	0x00CD, 0x00CF, 0x00D2, 0x00D4,
+	0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */
+	0x00DE,
+};
+
+/**** Helper functions to access the device Internal Lookup Tables ****/
+
+void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
+{
+	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
+		mmiowb();
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val);
+	} else {
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
+		mmiowb();
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val);
+	}
+}
+
+u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset)
+{
+	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
+		return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1);
+	} else {
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
+		return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1);
+	}
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
new file mode 100644
index 0000000..464521a
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
@@ -0,0 +1,32 @@
+#ifndef BCM43xx_ILT_H_
+#define BCM43xx_ILT_H_
+
+#define BCM43xx_ILT_ROTOR_SIZE		53
+extern const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE];
+#define BCM43xx_ILT_RETARD_SIZE		53
+extern const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE];
+#define BCM43xx_ILT_FINEFREQA_SIZE	256
+extern const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE];
+#define BCM43xx_ILT_FINEFREQG_SIZE	256
+extern const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE];
+#define BCM43xx_ILT_NOISEA2_SIZE	8
+extern const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE];
+#define BCM43xx_ILT_NOISEA3_SIZE	8
+extern const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE];
+#define BCM43xx_ILT_NOISEG1_SIZE	8
+extern const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE];
+#define BCM43xx_ILT_NOISEG2_SIZE	8
+extern const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE];
+#define BCM43xx_ILT_NOISESCALEG_SIZE	27
+extern const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE];
+extern const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE];
+extern const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE];
+#define BCM43xx_ILT_SIGMASQR_SIZE	53
+extern const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE];
+extern const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE];
+
+
+void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
+u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset);
+
+#endif /* BCM43xx_ILT_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
new file mode 100644
index 0000000..4b2c02c0
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
@@ -0,0 +1,293 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+                     Stefano Brivio <st3@riseup.net>
+                     Michael Buesch <mbuesch@freenet.de>
+                     Danny van Dyk <kugelfang@gentoo.org>
+                     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "bcm43xx_leds.h"
+#include "bcm43xx.h"
+
+#include <asm/bitops.h>
+
+
+static void bcm43xx_led_changestate(struct bcm43xx_led *led)
+{
+	struct bcm43xx_private *bcm = led->bcm;
+	const int index = bcm43xx_led_index(led);
+	const u16 mask = (1 << index);
+	u16 ledctl;
+
+	assert(index >= 0 && index < BCM43xx_NR_LEDS);
+	assert(led->blink_interval);
+	ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+	ledctl = (ledctl & mask) ? (ledctl & ~mask) : (ledctl | mask);
+	bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+}
+
+static void bcm43xx_led_blink(unsigned long d)
+{
+	struct bcm43xx_led *led = (struct bcm43xx_led *)d;
+	struct bcm43xx_private *bcm = led->bcm;
+	unsigned long flags;
+
+	bcm43xx_lock_mmio(bcm, flags);
+	if (led->blink_interval) {
+		bcm43xx_led_changestate(led);
+		mod_timer(&led->blink_timer, jiffies + led->blink_interval);
+	}
+	bcm43xx_unlock_mmio(bcm, flags);
+}
+
+static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
+				    unsigned long interval)
+{
+	if (led->blink_interval)
+		return;
+	led->blink_interval = interval;
+	bcm43xx_led_changestate(led);
+	led->blink_timer.expires = jiffies + interval;
+	add_timer(&led->blink_timer);
+}
+
+static void bcm43xx_led_blink_stop(struct bcm43xx_led *led, int sync)
+{
+	struct bcm43xx_private *bcm = led->bcm;
+	const int index = bcm43xx_led_index(led);
+	u16 ledctl;
+
+	if (!led->blink_interval)
+		return;
+	if (unlikely(sync))
+		del_timer_sync(&led->blink_timer);
+	else
+		del_timer(&led->blink_timer);
+	led->blink_interval = 0;
+
+	/* Make sure the LED is turned off. */
+	assert(index >= 0 && index < BCM43xx_NR_LEDS);
+	ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+	if (led->activelow)
+		ledctl |= (1 << index);
+	else
+		ledctl &= ~(1 << index);
+	bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+}
+
+static void bcm43xx_led_init_hardcoded(struct bcm43xx_private *bcm,
+				       struct bcm43xx_led *led,
+				       int led_index)
+{
+	/* This function is called, if the behaviour (and activelow)
+	 * information for a LED is missing in the SPROM.
+	 * We hardcode the behaviour values for various devices here.
+	 * Note that the BCM43xx_LED_TEST_XXX behaviour values can
+	 * be used to figure out which led is mapped to which index.
+	 */
+
+	switch (led_index) {
+	case 0:
+		led->behaviour = BCM43xx_LED_ACTIVITY;
+		if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ)
+			led->behaviour = BCM43xx_LED_RADIO_ALL;
+		break;
+	case 1:
+		led->behaviour = BCM43xx_LED_RADIO_B;
+		if (bcm->board_vendor == PCI_VENDOR_ID_ASUSTEK)
+			led->behaviour = BCM43xx_LED_ASSOC;
+		break;
+	case 2:
+		led->behaviour = BCM43xx_LED_RADIO_A;
+		break;
+	case 3:
+		led->behaviour = BCM43xx_LED_OFF;
+		break;
+	default:
+		assert(0);
+	}
+}
+
+int bcm43xx_leds_init(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_led *led;
+	u8 sprom[4];
+	int i;
+
+	sprom[0] = bcm->sprom.wl0gpio0;
+	sprom[1] = bcm->sprom.wl0gpio1;
+	sprom[2] = bcm->sprom.wl0gpio2;
+	sprom[3] = bcm->sprom.wl0gpio3;
+
+	for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+		led = &(bcm->leds[i]);
+		led->bcm = bcm;
+		setup_timer(&led->blink_timer,
+			    bcm43xx_led_blink,
+			    (unsigned long)led);
+
+		if (sprom[i] == 0xFF) {
+			bcm43xx_led_init_hardcoded(bcm, led, i);
+		} else {
+			led->behaviour = sprom[i] & BCM43xx_LED_BEHAVIOUR;
+			led->activelow = !!(sprom[i] & BCM43xx_LED_ACTIVELOW);
+		}
+	}
+
+	return 0;
+}
+
+void bcm43xx_leds_exit(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_led *led;
+	int i;
+
+	for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+		led = &(bcm->leds[i]);
+		bcm43xx_led_blink_stop(led, 1);
+	}
+	bcm43xx_leds_switch_all(bcm, 0);
+}
+
+void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
+{
+	struct bcm43xx_led *led;
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	const int transferring = (jiffies - bcm->stats.last_tx) < BCM43xx_LED_XFER_THRES;
+	int i, turn_on;
+	unsigned long interval = 0;
+	u16 ledctl;
+
+	ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+	for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+		led = &(bcm->leds[i]);
+
+		turn_on = 0;
+		switch (led->behaviour) {
+		case BCM43xx_LED_INACTIVE:
+			continue;
+		case BCM43xx_LED_OFF:
+			break;
+		case BCM43xx_LED_ON:
+			turn_on = 1;
+			break;
+		case BCM43xx_LED_ACTIVITY:
+			turn_on = activity;
+			break;
+		case BCM43xx_LED_RADIO_ALL:
+			turn_on = radio->enabled;
+			break;
+		case BCM43xx_LED_RADIO_A:
+			turn_on = (radio->enabled && phy->type == BCM43xx_PHYTYPE_A);
+			break;
+		case BCM43xx_LED_RADIO_B:
+			turn_on = (radio->enabled &&
+				   (phy->type == BCM43xx_PHYTYPE_B ||
+				    phy->type == BCM43xx_PHYTYPE_G));
+			break;
+		case BCM43xx_LED_MODE_BG:
+			if (phy->type == BCM43xx_PHYTYPE_G &&
+			    1/*FIXME: using G rates.*/)
+				turn_on = 1;
+			break;
+		case BCM43xx_LED_TRANSFER:
+			if (transferring)
+				bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM);
+			else
+				bcm43xx_led_blink_stop(led, 0);
+			continue;
+		case BCM43xx_LED_APTRANSFER:
+			if (bcm->ieee->iw_mode == IW_MODE_MASTER) {
+				if (transferring) {
+					interval = BCM43xx_LEDBLINK_FAST;
+					turn_on = 1;
+				}
+			} else {
+				turn_on = 1;
+				if (0/*TODO: not assoc*/)
+					interval = BCM43xx_LEDBLINK_SLOW;
+				else if (transferring)
+					interval = BCM43xx_LEDBLINK_FAST;
+				else
+					turn_on = 0;
+			}
+			if (turn_on)
+				bcm43xx_led_blink_start(led, interval);
+			else
+				bcm43xx_led_blink_stop(led, 0);
+			continue;
+		case BCM43xx_LED_WEIRD:
+			//TODO
+			break;
+		case BCM43xx_LED_ASSOC:
+			if (bcm->softmac->associated)
+				turn_on = 1;
+			break;
+#ifdef CONFIG_BCM43XX_DEBUG
+		case BCM43xx_LED_TEST_BLINKSLOW:
+			bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_SLOW);
+			continue;
+		case BCM43xx_LED_TEST_BLINKMEDIUM:
+			bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM);
+			continue;
+		case BCM43xx_LED_TEST_BLINKFAST:
+			bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_FAST);
+			continue;
+#endif /* CONFIG_BCM43XX_DEBUG */
+		default:
+			assert(0);
+		};
+
+		if (led->activelow)
+			turn_on = !turn_on;
+		if (turn_on)
+			ledctl |= (1 << i);
+		else
+			ledctl &= ~(1 << i);
+	}
+	bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+}
+
+void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
+{
+	struct bcm43xx_led *led;
+	u16 ledctl;
+	int i;
+	int bit_on;
+
+	ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+	for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+		led = &(bcm->leds[i]);
+		if (led->behaviour == BCM43xx_LED_INACTIVE)
+			continue;
+		if (on)
+			bit_on = led->activelow ? 0 : 1;
+		else
+			bit_on = led->activelow ? 1 : 0;
+		if (bit_on)
+			ledctl |= (1 << i);
+		else
+			ledctl &= ~(1 << i);
+	}
+	bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
new file mode 100644
index 0000000..d3716cf
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
@@ -0,0 +1,56 @@
+#ifndef BCM43xx_LEDS_H_
+#define BCM43xx_LEDS_H_
+
+#include <linux/types.h>
+#include <linux/timer.h>
+
+
+struct bcm43xx_led {
+	u8 behaviour:7;
+	u8 activelow:1;
+
+	struct bcm43xx_private *bcm;
+	struct timer_list blink_timer;
+	unsigned long blink_interval;
+};
+#define bcm43xx_led_index(led)	((int)((led) - (led)->bcm->leds))
+
+/* Delay between state changes when blinking in jiffies */
+#define BCM43xx_LEDBLINK_SLOW		(HZ / 1)
+#define BCM43xx_LEDBLINK_MEDIUM		(HZ / 4)
+#define BCM43xx_LEDBLINK_FAST		(HZ / 8)
+
+#define BCM43xx_LED_XFER_THRES		(HZ / 100)
+
+#define BCM43xx_LED_BEHAVIOUR		0x7F
+#define BCM43xx_LED_ACTIVELOW		0x80
+enum { /* LED behaviour values */
+	BCM43xx_LED_OFF,
+	BCM43xx_LED_ON,
+	BCM43xx_LED_ACTIVITY,
+	BCM43xx_LED_RADIO_ALL,
+	BCM43xx_LED_RADIO_A,
+	BCM43xx_LED_RADIO_B,
+	BCM43xx_LED_MODE_BG,
+	BCM43xx_LED_TRANSFER,
+	BCM43xx_LED_APTRANSFER,
+	BCM43xx_LED_WEIRD,//FIXME
+	BCM43xx_LED_ASSOC,
+	BCM43xx_LED_INACTIVE,
+
+	/* Behaviour values for testing.
+	 * With these values it is easier to figure out
+	 * the real behaviour of leds, in case the SPROM
+	 * is missing information.
+	 */
+	BCM43xx_LED_TEST_BLINKSLOW,
+	BCM43xx_LED_TEST_BLINKMEDIUM,
+	BCM43xx_LED_TEST_BLINKFAST,
+};
+
+int bcm43xx_leds_init(struct bcm43xx_private *bcm);
+void bcm43xx_leds_exit(struct bcm43xx_private *bcm);
+void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity);
+void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on);
+
+#endif /* BCM43xx_LEDS_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
new file mode 100644
index 0000000..c37371f
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -0,0 +1,3973 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+                     Stefano Brivio <st3@riseup.net>
+                     Michael Buesch <mbuesch@freenet.de>
+                     Danny van Dyk <kugelfang@gentoo.org>
+                     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/version.h>
+#include <linux/firmware.h>
+#include <linux/wireless.h>
+#include <linux/workqueue.h>
+#include <linux/skbuff.h>
+#include <linux/dma-mapping.h>
+#include <net/iw_handler.h>
+
+#include "bcm43xx.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_debugfs.h"
+#include "bcm43xx_radio.h"
+#include "bcm43xx_phy.h"
+#include "bcm43xx_dma.h"
+#include "bcm43xx_pio.h"
+#include "bcm43xx_power.h"
+#include "bcm43xx_wx.h"
+#include "bcm43xx_ethtool.h"
+#include "bcm43xx_xmit.h"
+
+
+MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
+MODULE_AUTHOR("Martin Langer");
+MODULE_AUTHOR("Stefano Brivio");
+MODULE_AUTHOR("Michael Buesch");
+MODULE_LICENSE("GPL");
+
+#ifdef CONFIG_BCM947XX
+extern char *nvram_get(char *name);
+#endif
+
+#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
+static int modparam_pio;
+module_param_named(pio, modparam_pio, int, 0444);
+MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode");
+#elif defined(CONFIG_BCM43XX_DMA)
+# define modparam_pio	0
+#elif defined(CONFIG_BCM43XX_PIO)
+# define modparam_pio	1
+#endif
+
+static int modparam_bad_frames_preempt;
+module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
+MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames Preemption");
+
+static int modparam_short_retry = BCM43xx_DEFAULT_SHORT_RETRY_LIMIT;
+module_param_named(short_retry, modparam_short_retry, int, 0444);
+MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)");
+
+static int modparam_long_retry = BCM43xx_DEFAULT_LONG_RETRY_LIMIT;
+module_param_named(long_retry, modparam_long_retry, int, 0444);
+MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");
+
+static int modparam_locale = -1;
+module_param_named(locale, modparam_locale, int, 0444);
+MODULE_PARM_DESC(country, "Select LocaleCode 0-11 (For travelers)");
+
+static int modparam_noleds;
+module_param_named(noleds, modparam_noleds, int, 0444);
+MODULE_PARM_DESC(noleds, "Turn off all LED activity");
+
+#ifdef CONFIG_BCM43XX_DEBUG
+static char modparam_fwpostfix[64];
+module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444);
+MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging.");
+#else
+# define modparam_fwpostfix  ""
+#endif /* CONFIG_BCM43XX_DEBUG*/
+
+
+/* If you want to debug with just a single device, enable this,
+ * where the string is the pci device ID (as given by the kernel's
+ * pci_name function) of the device to be used.
+ */
+//#define DEBUG_SINGLE_DEVICE_ONLY	"0001:11:00.0"
+
+/* If you want to enable printing of each MMIO access, enable this. */
+//#define DEBUG_ENABLE_MMIO_PRINT
+
+/* If you want to enable printing of MMIO access within
+ * ucode/pcm upload, initvals write, enable this.
+ */
+//#define DEBUG_ENABLE_UCODE_MMIO_PRINT
+
+/* If you want to enable printing of PCI Config Space access, enable this */
+//#define DEBUG_ENABLE_PCILOG
+
+
+/* Detailed list maintained at:
+ * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices
+ */
+	static struct pci_device_id bcm43xx_pci_tbl[] = {
+	/* Broadcom 4303 802.11b */
+	{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+		/* Broadcom 4307 802.11b */
+	{ PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+		/* Broadcom 4318 802.11b/g */
+	{ PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	/* Broadcom 4306 802.11b/g */
+	{ PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+		/* Broadcom 4306 802.11a */
+//	{ PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	/* Broadcom 4309 802.11a/b/g */
+	{ PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	/* Broadcom 43XG 802.11b/g */
+	{ PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+#ifdef CONFIG_BCM947XX
+	/* SB bus on BCM947xx */
+	{ PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+#endif
+	{ 0 },
+};
+MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl);
+
+static void bcm43xx_ram_write(struct bcm43xx_private *bcm, u16 offset, u32 val)
+{
+	u32 status;
+
+	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+	if (!(status & BCM43xx_SBF_XFER_REG_BYTESWAP))
+		val = swab32(val);
+
+	bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset);
+	mmiowb();
+	bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_DATA, val);
+}
+
+static inline
+void bcm43xx_shm_control_word(struct bcm43xx_private *bcm,
+			      u16 routing, u16 offset)
+{
+	u32 control;
+
+	/* "offset" is the WORD offset. */
+
+	control = routing;
+	control <<= 16;
+	control |= offset;
+	bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_CONTROL, control);
+}
+
+u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm,
+		       u16 routing, u16 offset)
+{
+	u32 ret;
+
+	if (routing == BCM43xx_SHM_SHARED) {
+		if (offset & 0x0003) {
+			/* Unaligned access */
+			bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+			ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
+			ret <<= 16;
+			bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
+			ret |= bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
+
+			return ret;
+		}
+		offset >>= 2;
+	}
+	bcm43xx_shm_control_word(bcm, routing, offset);
+	ret = bcm43xx_read32(bcm, BCM43xx_MMIO_SHM_DATA);
+
+	return ret;
+}
+
+u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm,
+		       u16 routing, u16 offset)
+{
+	u16 ret;
+
+	if (routing == BCM43xx_SHM_SHARED) {
+		if (offset & 0x0003) {
+			/* Unaligned access */
+			bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+			ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
+
+			return ret;
+		}
+		offset >>= 2;
+	}
+	bcm43xx_shm_control_word(bcm, routing, offset);
+	ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
+
+	return ret;
+}
+
+void bcm43xx_shm_write32(struct bcm43xx_private *bcm,
+			 u16 routing, u16 offset,
+			 u32 value)
+{
+	if (routing == BCM43xx_SHM_SHARED) {
+		if (offset & 0x0003) {
+			/* Unaligned access */
+			bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+			mmiowb();
+			bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
+					(value >> 16) & 0xffff);
+			mmiowb();
+			bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
+			mmiowb();
+			bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA,
+					value & 0xffff);
+			return;
+		}
+		offset >>= 2;
+	}
+	bcm43xx_shm_control_word(bcm, routing, offset);
+	mmiowb();
+	bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, value);
+}
+
+void bcm43xx_shm_write16(struct bcm43xx_private *bcm,
+			 u16 routing, u16 offset,
+			 u16 value)
+{
+	if (routing == BCM43xx_SHM_SHARED) {
+		if (offset & 0x0003) {
+			/* Unaligned access */
+			bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+			mmiowb();
+			bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
+					value);
+			return;
+		}
+		offset >>= 2;
+	}
+	bcm43xx_shm_control_word(bcm, routing, offset);
+	mmiowb();
+	bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value);
+}
+
+void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf)
+{
+	/* We need to be careful. As we read the TSF from multiple
+	 * registers, we should take care of register overflows.
+	 * In theory, the whole tsf read process should be atomic.
+	 * We try to be atomic here, by restaring the read process,
+	 * if any of the high registers changed (overflew).
+	 */
+	if (bcm->current_core->rev >= 3) {
+		u32 low, high, high2;
+
+		do {
+			high = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
+			low = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW);
+			high2 = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
+		} while (unlikely(high != high2));
+
+		*tsf = high;
+		*tsf <<= 32;
+		*tsf |= low;
+	} else {
+		u64 tmp;
+		u16 v0, v1, v2, v3;
+		u16 test1, test2, test3;
+
+		do {
+			v3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
+			v2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
+			v1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
+			v0 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_0);
+
+			test3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
+			test2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
+			test1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
+		} while (v3 != test3 || v2 != test2 || v1 != test1);
+
+		*tsf = v3;
+		*tsf <<= 48;
+		tmp = v2;
+		tmp <<= 32;
+		*tsf |= tmp;
+		tmp = v1;
+		tmp <<= 16;
+		*tsf |= tmp;
+		*tsf |= v0;
+	}
+}
+
+void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf)
+{
+	u32 status;
+
+	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+	status |= BCM43xx_SBF_TIME_UPDATE;
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+	mmiowb();
+
+	/* Be careful with the in-progress timer.
+	 * First zero out the low register, so we have a full
+	 * register-overflow duration to complete the operation.
+	 */
+	if (bcm->current_core->rev >= 3) {
+		u32 lo = (tsf & 0x00000000FFFFFFFFULL);
+		u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32;
+
+		bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, 0);
+		mmiowb();
+		bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH, hi);
+		mmiowb();
+		bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, lo);
+	} else {
+		u16 v0 = (tsf & 0x000000000000FFFFULL);
+		u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16;
+		u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32;
+		u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48;
+
+		bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, 0);
+		mmiowb();
+		bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_3, v3);
+		mmiowb();
+		bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_2, v2);
+		mmiowb();
+		bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_1, v1);
+		mmiowb();
+		bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0);
+	}
+
+	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+	status &= ~BCM43xx_SBF_TIME_UPDATE;
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+}
+
+static
+void bcm43xx_macfilter_set(struct bcm43xx_private *bcm,
+			   u16 offset,
+			   const u8 *mac)
+{
+	u16 data;
+
+	offset |= 0x0020;
+	bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_CONTROL, offset);
+
+	data = mac[0];
+	data |= mac[1] << 8;
+	bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
+	data = mac[2];
+	data |= mac[3] << 8;
+	bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
+	data = mac[4];
+	data |= mac[5] << 8;
+	bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
+}
+
+static void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm,
+				    u16 offset)
+{
+	const u8 zero_addr[ETH_ALEN] = { 0 };
+
+	bcm43xx_macfilter_set(bcm, offset, zero_addr);
+}
+
+static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm)
+{
+	const u8 *mac = (const u8 *)(bcm->net_dev->dev_addr);
+	const u8 *bssid = (const u8 *)(bcm->ieee->bssid);
+	u8 mac_bssid[ETH_ALEN * 2];
+	int i;
+
+	memcpy(mac_bssid, mac, ETH_ALEN);
+	memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN);
+
+	/* Write our MAC address and BSSID to template ram */
+	for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
+		bcm43xx_ram_write(bcm, 0x20 + i, *((u32 *)(mac_bssid + i)));
+	for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
+		bcm43xx_ram_write(bcm, 0x78 + i, *((u32 *)(mac_bssid + i)));
+	for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
+		bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i)));
+}
+
+//FIXME: Well, we should probably call them from somewhere.
+#if 0
+static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time)
+{
+	/* slot_time is in usec. */
+	if (bcm43xx_current_phy(bcm)->type != BCM43xx_PHYTYPE_G)
+		return;
+	bcm43xx_write16(bcm, 0x684, 510 + slot_time);
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time);
+}
+
+static void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm)
+{
+	bcm43xx_set_slot_time(bcm, 9);
+}
+
+static void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm)
+{
+	bcm43xx_set_slot_time(bcm, 20);
+}
+#endif
+
+/* FIXME: To get the MAC-filter working, we need to implement the
+ *        following functions (and rename them :)
+ */
+#if 0
+static void bcm43xx_disassociate(struct bcm43xx_private *bcm)
+{
+	bcm43xx_mac_suspend(bcm);
+	bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
+
+	bcm43xx_ram_write(bcm, 0x0026, 0x0000);
+	bcm43xx_ram_write(bcm, 0x0028, 0x0000);
+	bcm43xx_ram_write(bcm, 0x007E, 0x0000);
+	bcm43xx_ram_write(bcm, 0x0080, 0x0000);
+	bcm43xx_ram_write(bcm, 0x047E, 0x0000);
+	bcm43xx_ram_write(bcm, 0x0480, 0x0000);
+
+	if (bcm->current_core->rev < 3) {
+		bcm43xx_write16(bcm, 0x0610, 0x8000);
+		bcm43xx_write16(bcm, 0x060E, 0x0000);
+	} else
+		bcm43xx_write32(bcm, 0x0188, 0x80000000);
+
+	bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
+
+	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G &&
+	    ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate))
+		bcm43xx_short_slot_timing_enable(bcm);
+
+	bcm43xx_mac_enable(bcm);
+}
+
+static void bcm43xx_associate(struct bcm43xx_private *bcm,
+			      const u8 *mac)
+{
+	memcpy(bcm->ieee->bssid, mac, ETH_ALEN);
+
+	bcm43xx_mac_suspend(bcm);
+	bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_ASSOC, mac);
+	bcm43xx_write_mac_bssid_templates(bcm);
+	bcm43xx_mac_enable(bcm);
+}
+#endif
+
+/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
+ * Returns the _previously_ enabled IRQ mask.
+ */
+static inline u32 bcm43xx_interrupt_enable(struct bcm43xx_private *bcm, u32 mask)
+{
+	u32 old_mask;
+
+	old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask | mask);
+
+	return old_mask;
+}
+
+/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
+ * Returns the _previously_ enabled IRQ mask.
+ */
+static inline u32 bcm43xx_interrupt_disable(struct bcm43xx_private *bcm, u32 mask)
+{
+	u32 old_mask;
+
+	old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
+
+	return old_mask;
+}
+
+/* Make sure we don't receive more data from the device. */
+static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate)
+{
+	u32 old;
+	unsigned long flags;
+
+	bcm43xx_lock_mmio(bcm, flags);
+	if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) {
+		bcm43xx_unlock_mmio(bcm, flags);
+		return -EBUSY;
+	}
+	old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+	tasklet_disable(&bcm->isr_tasklet);
+	bcm43xx_unlock_mmio(bcm, flags);
+	if (oldstate)
+		*oldstate = old;
+
+	return 0;
+}
+
+static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	u32 radio_id;
+	u16 manufact;
+	u16 version;
+	u8 revision;
+	s8 i;
+
+	if (bcm->chip_id == 0x4317) {
+		if (bcm->chip_rev == 0x00)
+			radio_id = 0x3205017F;
+		else if (bcm->chip_rev == 0x01)
+			radio_id = 0x4205017F;
+		else
+			radio_id = 0x5205017F;
+	} else {
+		bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
+		radio_id = bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_HIGH);
+		radio_id <<= 16;
+		bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
+		radio_id |= bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW);
+	}
+
+	manufact = (radio_id & 0x00000FFF);
+	version = (radio_id & 0x0FFFF000) >> 12;
+	revision = (radio_id & 0xF0000000) >> 28;
+
+	dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n",
+		radio_id, manufact, version, revision);
+
+	switch (phy->type) {
+	case BCM43xx_PHYTYPE_A:
+		if ((version != 0x2060) || (revision != 1) || (manufact != 0x17f))
+			goto err_unsupported_radio;
+		break;
+	case BCM43xx_PHYTYPE_B:
+		if ((version & 0xFFF0) != 0x2050)
+			goto err_unsupported_radio;
+		break;
+	case BCM43xx_PHYTYPE_G:
+		if (version != 0x2050)
+			goto err_unsupported_radio;
+		break;
+	}
+
+	radio->manufact = manufact;
+	radio->version = version;
+	radio->revision = revision;
+
+	/* Set default attenuation values. */
+	radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
+	radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
+	radio->txctl1 = bcm43xx_default_txctl1(bcm);
+	radio->txctl2 = 0xFFFF;
+	if (phy->type == BCM43xx_PHYTYPE_A)
+		radio->txpower_desired = bcm->sprom.maxpower_aphy;
+	else
+		radio->txpower_desired = bcm->sprom.maxpower_bgphy;
+
+	/* Initialize the in-memory nrssi Lookup Table. */
+	for (i = 0; i < 64; i++)
+		radio->nrssi_lt[i] = i;
+
+	return 0;
+
+err_unsupported_radio:
+	printk(KERN_ERR PFX "Unsupported Radio connected to the PHY!\n");
+	return -ENODEV;
+}
+
+static const char * bcm43xx_locale_iso(u8 locale)
+{
+	/* ISO 3166-1 country codes.
+	 * Note that there aren't ISO 3166-1 codes for
+	 * all or locales. (Not all locales are countries)
+	 */
+	switch (locale) {
+	case BCM43xx_LOCALE_WORLD:
+	case BCM43xx_LOCALE_ALL:
+		return "XX";
+	case BCM43xx_LOCALE_THAILAND:
+		return "TH";
+	case BCM43xx_LOCALE_ISRAEL:
+		return "IL";
+	case BCM43xx_LOCALE_JORDAN:
+		return "JO";
+	case BCM43xx_LOCALE_CHINA:
+		return "CN";
+	case BCM43xx_LOCALE_JAPAN:
+	case BCM43xx_LOCALE_JAPAN_HIGH:
+		return "JP";
+	case BCM43xx_LOCALE_USA_CANADA_ANZ:
+	case BCM43xx_LOCALE_USA_LOW:
+		return "US";
+	case BCM43xx_LOCALE_EUROPE:
+		return "EU";
+	case BCM43xx_LOCALE_NONE:
+		return "  ";
+	}
+	assert(0);
+	return "  ";
+}
+
+static const char * bcm43xx_locale_string(u8 locale)
+{
+	switch (locale) {
+	case BCM43xx_LOCALE_WORLD:
+		return "World";
+	case BCM43xx_LOCALE_THAILAND:
+		return "Thailand";
+	case BCM43xx_LOCALE_ISRAEL:
+		return "Israel";
+	case BCM43xx_LOCALE_JORDAN:
+		return "Jordan";
+	case BCM43xx_LOCALE_CHINA:
+		return "China";
+	case BCM43xx_LOCALE_JAPAN:
+		return "Japan";
+	case BCM43xx_LOCALE_USA_CANADA_ANZ:
+		return "USA/Canada/ANZ";
+	case BCM43xx_LOCALE_EUROPE:
+		return "Europe";
+	case BCM43xx_LOCALE_USA_LOW:
+		return "USAlow";
+	case BCM43xx_LOCALE_JAPAN_HIGH:
+		return "JapanHigh";
+	case BCM43xx_LOCALE_ALL:
+		return "All";
+	case BCM43xx_LOCALE_NONE:
+		return "None";
+	}
+	assert(0);
+	return "";
+}
+
+static inline u8 bcm43xx_crc8(u8 crc, u8 data)
+{
+	static const u8 t[] = {
+		0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
+		0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
+		0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
+		0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
+		0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
+		0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
+		0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
+		0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
+		0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
+		0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
+		0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
+		0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
+		0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
+		0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
+		0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
+		0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
+		0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
+		0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
+		0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
+		0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
+		0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
+		0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
+		0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
+		0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
+		0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
+		0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
+		0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
+		0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
+		0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
+		0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
+		0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
+		0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
+	};
+	return t[crc ^ data];
+}
+
+static u8 bcm43xx_sprom_crc(const u16 *sprom)
+{
+	int word;
+	u8 crc = 0xFF;
+
+	for (word = 0; word < BCM43xx_SPROM_SIZE - 1; word++) {
+		crc = bcm43xx_crc8(crc, sprom[word] & 0x00FF);
+		crc = bcm43xx_crc8(crc, (sprom[word] & 0xFF00) >> 8);
+	}
+	crc = bcm43xx_crc8(crc, sprom[BCM43xx_SPROM_VERSION] & 0x00FF);
+	crc ^= 0xFF;
+
+	return crc;
+}
+
+int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom)
+{
+	int i;
+	u8 crc, expected_crc;
+
+	for (i = 0; i < BCM43xx_SPROM_SIZE; i++)
+		sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2));
+	/* CRC-8 check. */
+	crc = bcm43xx_sprom_crc(sprom);
+	expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
+	if (crc != expected_crc) {
+		printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum "
+					"(0x%02X, expected: 0x%02X)\n",
+		       crc, expected_crc);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom)
+{
+	int i, err;
+	u8 crc, expected_crc;
+	u32 spromctl;
+
+	/* CRC-8 validation of the input data. */
+	crc = bcm43xx_sprom_crc(sprom);
+	expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
+	if (crc != expected_crc) {
+		printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n");
+		return -EINVAL;
+	}
+
+	printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
+	err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl);
+	if (err)
+		goto err_ctlreg;
+	spromctl |= 0x10; /* SPROM WRITE enable. */
+	bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
+	if (err)
+		goto err_ctlreg;
+	/* We must burn lots of CPU cycles here, but that does not
+	 * really matter as one does not write the SPROM every other minute...
+	 */
+	printk(KERN_INFO PFX "[ 0%%");
+	mdelay(500);
+	for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+		if (i == 16)
+			printk("25%%");
+		else if (i == 32)
+			printk("50%%");
+		else if (i == 48)
+			printk("75%%");
+		else if (i % 2)
+			printk(".");
+		bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]);
+		mmiowb();
+		mdelay(20);
+	}
+	spromctl &= ~0x10; /* SPROM WRITE enable. */
+	bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
+	if (err)
+		goto err_ctlreg;
+	mdelay(500);
+	printk("100%% ]\n");
+	printk(KERN_INFO PFX "SPROM written.\n");
+	bcm43xx_controller_restart(bcm, "SPROM update");
+
+	return 0;
+err_ctlreg:
+	printk(KERN_ERR PFX "Could not access SPROM control register.\n");
+	return -ENODEV;
+}
+
+static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
+{
+	u16 value;
+	u16 *sprom;
+#ifdef CONFIG_BCM947XX
+	char *c;
+#endif
+
+	sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16),
+			GFP_KERNEL);
+	if (!sprom) {
+		printk(KERN_ERR PFX "sprom_extract OOM\n");
+		return -ENOMEM;
+	}
+#ifdef CONFIG_BCM947XX
+	sprom[BCM43xx_SPROM_BOARDFLAGS2] = atoi(nvram_get("boardflags2"));
+	sprom[BCM43xx_SPROM_BOARDFLAGS] = atoi(nvram_get("boardflags"));
+
+	if ((c = nvram_get("il0macaddr")) != NULL)
+		e_aton(c, (char *) &(sprom[BCM43xx_SPROM_IL0MACADDR]));
+
+	if ((c = nvram_get("et1macaddr")) != NULL)
+		e_aton(c, (char *) &(sprom[BCM43xx_SPROM_ET1MACADDR]));
+
+	sprom[BCM43xx_SPROM_PA0B0] = atoi(nvram_get("pa0b0"));
+	sprom[BCM43xx_SPROM_PA0B1] = atoi(nvram_get("pa0b1"));
+	sprom[BCM43xx_SPROM_PA0B2] = atoi(nvram_get("pa0b2"));
+
+	sprom[BCM43xx_SPROM_PA1B0] = atoi(nvram_get("pa1b0"));
+	sprom[BCM43xx_SPROM_PA1B1] = atoi(nvram_get("pa1b1"));
+	sprom[BCM43xx_SPROM_PA1B2] = atoi(nvram_get("pa1b2"));
+
+	sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev"));
+#else
+	bcm43xx_sprom_read(bcm, sprom);
+#endif
+
+	/* boardflags2 */
+	value = sprom[BCM43xx_SPROM_BOARDFLAGS2];
+	bcm->sprom.boardflags2 = value;
+
+	/* il0macaddr */
+	value = sprom[BCM43xx_SPROM_IL0MACADDR + 0];
+	*(((u16 *)bcm->sprom.il0macaddr) + 0) = cpu_to_be16(value);
+	value = sprom[BCM43xx_SPROM_IL0MACADDR + 1];
+	*(((u16 *)bcm->sprom.il0macaddr) + 1) = cpu_to_be16(value);
+	value = sprom[BCM43xx_SPROM_IL0MACADDR + 2];
+	*(((u16 *)bcm->sprom.il0macaddr) + 2) = cpu_to_be16(value);
+
+	/* et0macaddr */
+	value = sprom[BCM43xx_SPROM_ET0MACADDR + 0];
+	*(((u16 *)bcm->sprom.et0macaddr) + 0) = cpu_to_be16(value);
+	value = sprom[BCM43xx_SPROM_ET0MACADDR + 1];
+	*(((u16 *)bcm->sprom.et0macaddr) + 1) = cpu_to_be16(value);
+	value = sprom[BCM43xx_SPROM_ET0MACADDR + 2];
+	*(((u16 *)bcm->sprom.et0macaddr) + 2) = cpu_to_be16(value);
+
+	/* et1macaddr */
+	value = sprom[BCM43xx_SPROM_ET1MACADDR + 0];
+	*(((u16 *)bcm->sprom.et1macaddr) + 0) = cpu_to_be16(value);
+	value = sprom[BCM43xx_SPROM_ET1MACADDR + 1];
+	*(((u16 *)bcm->sprom.et1macaddr) + 1) = cpu_to_be16(value);
+	value = sprom[BCM43xx_SPROM_ET1MACADDR + 2];
+	*(((u16 *)bcm->sprom.et1macaddr) + 2) = cpu_to_be16(value);
+
+	/* ethernet phy settings */
+	value = sprom[BCM43xx_SPROM_ETHPHY];
+	bcm->sprom.et0phyaddr = (value & 0x001F);
+	bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5;
+	bcm->sprom.et0mdcport = (value & (1 << 14)) >> 14;
+	bcm->sprom.et1mdcport = (value & (1 << 15)) >> 15;
+
+	/* boardrev, antennas, locale */
+	value = sprom[BCM43xx_SPROM_BOARDREV];
+	bcm->sprom.boardrev = (value & 0x00FF);
+	bcm->sprom.locale = (value & 0x0F00) >> 8;
+	bcm->sprom.antennas_aphy = (value & 0x3000) >> 12;
+	bcm->sprom.antennas_bgphy = (value & 0xC000) >> 14;
+	if (modparam_locale != -1) {
+		if (modparam_locale >= 0 && modparam_locale <= 11) {
+			bcm->sprom.locale = modparam_locale;
+			printk(KERN_WARNING PFX "Operating with modified "
+						"LocaleCode %u (%s)\n",
+			       bcm->sprom.locale,
+			       bcm43xx_locale_string(bcm->sprom.locale));
+		} else {
+			printk(KERN_WARNING PFX "Module parameter \"locale\" "
+						"invalid value. (0 - 11)\n");
+		}
+	}
+
+	/* pa0b* */
+	value = sprom[BCM43xx_SPROM_PA0B0];
+	bcm->sprom.pa0b0 = value;
+	value = sprom[BCM43xx_SPROM_PA0B1];
+	bcm->sprom.pa0b1 = value;
+	value = sprom[BCM43xx_SPROM_PA0B2];
+	bcm->sprom.pa0b2 = value;
+
+	/* wl0gpio* */
+	value = sprom[BCM43xx_SPROM_WL0GPIO0];
+	if (value == 0x0000)
+		value = 0xFFFF;
+	bcm->sprom.wl0gpio0 = value & 0x00FF;
+	bcm->sprom.wl0gpio1 = (value & 0xFF00) >> 8;
+	value = sprom[BCM43xx_SPROM_WL0GPIO2];
+	if (value == 0x0000)
+		value = 0xFFFF;
+	bcm->sprom.wl0gpio2 = value & 0x00FF;
+	bcm->sprom.wl0gpio3 = (value & 0xFF00) >> 8;
+
+	/* maxpower */
+	value = sprom[BCM43xx_SPROM_MAXPWR];
+	bcm->sprom.maxpower_aphy = (value & 0xFF00) >> 8;
+	bcm->sprom.maxpower_bgphy = value & 0x00FF;
+
+	/* pa1b* */
+	value = sprom[BCM43xx_SPROM_PA1B0];
+	bcm->sprom.pa1b0 = value;
+	value = sprom[BCM43xx_SPROM_PA1B1];
+	bcm->sprom.pa1b1 = value;
+	value = sprom[BCM43xx_SPROM_PA1B2];
+	bcm->sprom.pa1b2 = value;
+
+	/* idle tssi target */
+	value = sprom[BCM43xx_SPROM_IDL_TSSI_TGT];
+	bcm->sprom.idle_tssi_tgt_aphy = value & 0x00FF;
+	bcm->sprom.idle_tssi_tgt_bgphy = (value & 0xFF00) >> 8;
+
+	/* boardflags */
+	value = sprom[BCM43xx_SPROM_BOARDFLAGS];
+	if (value == 0xFFFF)
+		value = 0x0000;
+	bcm->sprom.boardflags = value;
+	/* boardflags workarounds */
+	if (bcm->board_vendor == PCI_VENDOR_ID_DELL &&
+	    bcm->chip_id == 0x4301 &&
+	    bcm->board_revision == 0x74)
+		bcm->sprom.boardflags |= BCM43xx_BFL_BTCOEXIST;
+	if (bcm->board_vendor == PCI_VENDOR_ID_APPLE &&
+	    bcm->board_type == 0x4E &&
+	    bcm->board_revision > 0x40)
+		bcm->sprom.boardflags |= BCM43xx_BFL_PACTRL;
+
+	/* antenna gain */
+	value = sprom[BCM43xx_SPROM_ANTENNA_GAIN];
+	if (value == 0x0000 || value == 0xFFFF)
+		value = 0x0202;
+	/* convert values to Q5.2 */
+	bcm->sprom.antennagain_aphy = ((value & 0xFF00) >> 8) * 4;
+	bcm->sprom.antennagain_bgphy = (value & 0x00FF) * 4;
+
+	kfree(sprom);
+
+	return 0;
+}
+
+static void bcm43xx_geo_init(struct bcm43xx_private *bcm)
+{
+	struct ieee80211_geo geo;
+	struct ieee80211_channel *chan;
+	int have_a = 0, have_bg = 0;
+	int i;
+	u8 channel;
+	struct bcm43xx_phyinfo *phy;
+	const char *iso_country;
+
+	memset(&geo, 0, sizeof(geo));
+	for (i = 0; i < bcm->nr_80211_available; i++) {
+		phy = &(bcm->core_80211_ext[i].phy);
+		switch (phy->type) {
+		case BCM43xx_PHYTYPE_B:
+		case BCM43xx_PHYTYPE_G:
+			have_bg = 1;
+			break;
+		case BCM43xx_PHYTYPE_A:
+			have_a = 1;
+			break;
+		default:
+			assert(0);
+		}
+	}
+	iso_country = bcm43xx_locale_iso(bcm->sprom.locale);
+
+ 	if (have_a) {
+		for (i = 0, channel = 0; channel < 201; channel++) {
+			chan = &geo.a[i++];
+			chan->freq = bcm43xx_channel_to_freq_a(channel);
+			chan->channel = channel;
+		}
+		geo.a_channels = i;
+	}
+	if (have_bg) {
+		for (i = 0, channel = 1; channel < 15; channel++) {
+			chan = &geo.bg[i++];
+			chan->freq = bcm43xx_channel_to_freq_bg(channel);
+			chan->channel = channel;
+		}
+		geo.bg_channels = i;
+	}
+	memcpy(geo.name, iso_country, 2);
+	if (0 /*TODO: Outdoor use only */)
+		geo.name[2] = 'O';
+	else if (0 /*TODO: Indoor use only */)
+		geo.name[2] = 'I';
+	else
+		geo.name[2] = ' ';
+	geo.name[3] = '\0';
+
+	ieee80211_set_geo(bcm->ieee, &geo);
+}
+
+/* DummyTransmission function, as documented on 
+ * http://bcm-specs.sipsolutions.net/DummyTransmission
+ */
+void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	unsigned int i, max_loop;
+	u16 value = 0;
+	u32 buffer[5] = {
+		0x00000000,
+		0x0000D400,
+		0x00000000,
+		0x00000001,
+		0x00000000,
+	};
+
+	switch (phy->type) {
+	case BCM43xx_PHYTYPE_A:
+		max_loop = 0x1E;
+		buffer[0] = 0xCC010200;
+		break;
+	case BCM43xx_PHYTYPE_B:
+	case BCM43xx_PHYTYPE_G:
+		max_loop = 0xFA;
+		buffer[0] = 0x6E840B00; 
+		break;
+	default:
+		assert(0);
+		return;
+	}
+
+	for (i = 0; i < 5; i++)
+		bcm43xx_ram_write(bcm, i * 4, buffer[i]);
+
+	bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
+
+	bcm43xx_write16(bcm, 0x0568, 0x0000);
+	bcm43xx_write16(bcm, 0x07C0, 0x0000);
+	bcm43xx_write16(bcm, 0x050C, ((phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0));
+	bcm43xx_write16(bcm, 0x0508, 0x0000);
+	bcm43xx_write16(bcm, 0x050A, 0x0000);
+	bcm43xx_write16(bcm, 0x054C, 0x0000);
+	bcm43xx_write16(bcm, 0x056A, 0x0014);
+	bcm43xx_write16(bcm, 0x0568, 0x0826);
+	bcm43xx_write16(bcm, 0x0500, 0x0000);
+	bcm43xx_write16(bcm, 0x0502, 0x0030);
+
+	if (radio->version == 0x2050 && radio->revision <= 0x5)
+		bcm43xx_radio_write16(bcm, 0x0051, 0x0017);
+	for (i = 0x00; i < max_loop; i++) {
+		value = bcm43xx_read16(bcm, 0x050E);
+		if (value & 0x0080)
+			break;
+		udelay(10);
+	}
+	for (i = 0x00; i < 0x0A; i++) {
+		value = bcm43xx_read16(bcm, 0x050E);
+		if (value & 0x0400)
+			break;
+		udelay(10);
+	}
+	for (i = 0x00; i < 0x0A; i++) {
+		value = bcm43xx_read16(bcm, 0x0690);
+		if (!(value & 0x0100))
+			break;
+		udelay(10);
+	}
+	if (radio->version == 0x2050 && radio->revision <= 0x5)
+		bcm43xx_radio_write16(bcm, 0x0051, 0x0037);
+}
+
+static void key_write(struct bcm43xx_private *bcm,
+		      u8 index, u8 algorithm, const u16 *key)
+{
+	unsigned int i, basic_wep = 0;
+	u32 offset;
+	u16 value;
+ 
+	/* Write associated key information */
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x100 + (index * 2),
+			    ((index << 4) | (algorithm & 0x0F)));
+ 
+	/* The first 4 WEP keys need extra love */
+	if (((algorithm == BCM43xx_SEC_ALGO_WEP) ||
+	    (algorithm == BCM43xx_SEC_ALGO_WEP104)) && (index < 4))
+		basic_wep = 1;
+ 
+	/* Write key payload, 8 little endian words */
+	offset = bcm->security_offset + (index * BCM43xx_SEC_KEYSIZE);
+	for (i = 0; i < (BCM43xx_SEC_KEYSIZE / sizeof(u16)); i++) {
+		value = cpu_to_le16(key[i]);
+		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+				    offset + (i * 2), value);
+ 
+		if (!basic_wep)
+			continue;
+ 
+		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+				    offset + (i * 2) + 4 * BCM43xx_SEC_KEYSIZE,
+				    value);
+	}
+}
+
+static void keymac_write(struct bcm43xx_private *bcm,
+			 u8 index, const u32 *addr)
+{
+	/* for keys 0-3 there is no associated mac address */
+	if (index < 4)
+		return;
+
+	index -= 4;
+	if (bcm->current_core->rev >= 5) {
+		bcm43xx_shm_write32(bcm,
+				    BCM43xx_SHM_HWMAC,
+				    index * 2,
+				    cpu_to_be32(*addr));
+		bcm43xx_shm_write16(bcm,
+				    BCM43xx_SHM_HWMAC,
+				    (index * 2) + 1,
+				    cpu_to_be16(*((u16 *)(addr + 1))));
+	} else {
+		if (index < 8) {
+			TODO(); /* Put them in the macaddress filter */
+		} else {
+			TODO();
+			/* Put them BCM43xx_SHM_SHARED, stating index 0x0120.
+			   Keep in mind to update the count of keymacs in 0x003E as well! */
+		}
+	}
+}
+
+static int bcm43xx_key_write(struct bcm43xx_private *bcm,
+			     u8 index, u8 algorithm,
+			     const u8 *_key, int key_len,
+			     const u8 *mac_addr)
+{
+	u8 key[BCM43xx_SEC_KEYSIZE] = { 0 };
+
+	if (index >= ARRAY_SIZE(bcm->key))
+		return -EINVAL;
+	if (key_len > ARRAY_SIZE(key))
+		return -EINVAL;
+	if (algorithm < 1 || algorithm > 5)
+		return -EINVAL;
+
+	memcpy(key, _key, key_len);
+	key_write(bcm, index, algorithm, (const u16 *)key);
+	keymac_write(bcm, index, (const u32 *)mac_addr);
+
+	bcm->key[index].algorithm = algorithm;
+
+	return 0;
+}
+
+static void bcm43xx_clear_keys(struct bcm43xx_private *bcm)
+{
+	static const u32 zero_mac[2] = { 0 };
+	unsigned int i,j, nr_keys = 54;
+	u16 offset;
+
+	if (bcm->current_core->rev < 5)
+		nr_keys = 16;
+	assert(nr_keys <= ARRAY_SIZE(bcm->key));
+
+	for (i = 0; i < nr_keys; i++) {
+		bcm->key[i].enabled = 0;
+		/* returns for i < 4 immediately */
+		keymac_write(bcm, i, zero_mac);
+		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+				    0x100 + (i * 2), 0x0000);
+		for (j = 0; j < 8; j++) {
+			offset = bcm->security_offset + (j * 4) + (i * BCM43xx_SEC_KEYSIZE);
+			bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+					    offset, 0x0000);
+		}
+	}
+	dprintk(KERN_INFO PFX "Keys cleared\n");
+}
+
+/* Lowlevel core-switch function. This is only to be used in
+ * bcm43xx_switch_core() and bcm43xx_probe_cores()
+ */
+static int _switch_core(struct bcm43xx_private *bcm, int core)
+{
+	int err;
+	int attempts = 0;
+	u32 current_core;
+
+	assert(core >= 0);
+	while (1) {
+		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
+						 (core * 0x1000) + 0x18000000);
+		if (unlikely(err))
+			goto error;
+		err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
+						&current_core);
+		if (unlikely(err))
+			goto error;
+		current_core = (current_core - 0x18000000) / 0x1000;
+		if (current_core == core)
+			break;
+
+		if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES))
+			goto error;
+		udelay(10);
+	}
+#ifdef CONFIG_BCM947XX
+	if (bcm->pci_dev->bus->number == 0)
+		bcm->current_core_offset = 0x1000 * core;
+	else
+		bcm->current_core_offset = 0;
+#endif
+
+	return 0;
+error:
+	printk(KERN_ERR PFX "Failed to switch to core %d\n", core);
+	return -ENODEV;
+}
+
+int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core)
+{
+	int err;
+
+	if (unlikely(!new_core))
+		return 0;
+	if (!new_core->available)
+		return -ENODEV;
+	if (bcm->current_core == new_core)
+		return 0;
+	err = _switch_core(bcm, new_core->index);
+	if (unlikely(err))
+		goto out;
+
+	bcm->current_core = new_core;
+	bcm->current_80211_core_idx = -1;
+	if (new_core->id == BCM43xx_COREID_80211)
+		bcm->current_80211_core_idx = (int)(new_core - &(bcm->core_80211[0]));
+
+out:
+	return err;
+}
+
+static int bcm43xx_core_enabled(struct bcm43xx_private *bcm)
+{
+	u32 value;
+
+	value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+	value &= BCM43xx_SBTMSTATELOW_CLOCK | BCM43xx_SBTMSTATELOW_RESET
+		 | BCM43xx_SBTMSTATELOW_REJECT;
+
+	return (value == BCM43xx_SBTMSTATELOW_CLOCK);
+}
+
+/* disable current core */
+static int bcm43xx_core_disable(struct bcm43xx_private *bcm, u32 core_flags)
+{
+	u32 sbtmstatelow;
+	u32 sbtmstatehigh;
+	int i;
+
+	/* fetch sbtmstatelow from core information registers */
+	sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+
+	/* core is already in reset */
+	if (sbtmstatelow & BCM43xx_SBTMSTATELOW_RESET)
+		goto out;
+
+	if (sbtmstatelow & BCM43xx_SBTMSTATELOW_CLOCK) {
+		sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
+			       BCM43xx_SBTMSTATELOW_REJECT;
+		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+
+		for (i = 0; i < 1000; i++) {
+			sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+			if (sbtmstatelow & BCM43xx_SBTMSTATELOW_REJECT) {
+				i = -1;
+				break;
+			}
+			udelay(10);
+		}
+		if (i != -1) {
+			printk(KERN_ERR PFX "Error: core_disable() REJECT timeout!\n");
+			return -EBUSY;
+		}
+
+		for (i = 0; i < 1000; i++) {
+			sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+			if (!(sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_BUSY)) {
+				i = -1;
+				break;
+			}
+			udelay(10);
+		}
+		if (i != -1) {
+			printk(KERN_ERR PFX "Error: core_disable() BUSY timeout!\n");
+			return -EBUSY;
+		}
+
+		sbtmstatelow = BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
+			       BCM43xx_SBTMSTATELOW_REJECT |
+			       BCM43xx_SBTMSTATELOW_RESET |
+			       BCM43xx_SBTMSTATELOW_CLOCK |
+			       core_flags;
+		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+		udelay(10);
+	}
+
+	sbtmstatelow = BCM43xx_SBTMSTATELOW_RESET |
+		       BCM43xx_SBTMSTATELOW_REJECT |
+		       core_flags;
+	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+
+out:
+	bcm->current_core->enabled = 0;
+
+	return 0;
+}
+
+/* enable (reset) current core */
+static int bcm43xx_core_enable(struct bcm43xx_private *bcm, u32 core_flags)
+{
+	u32 sbtmstatelow;
+	u32 sbtmstatehigh;
+	u32 sbimstate;
+	int err;
+
+	err = bcm43xx_core_disable(bcm, core_flags);
+	if (err)
+		goto out;
+
+	sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
+		       BCM43xx_SBTMSTATELOW_RESET |
+		       BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
+		       core_flags;
+	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+	udelay(1);
+
+	sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+	if (sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_SERROR) {
+		sbtmstatehigh = 0x00000000;
+		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATEHIGH, sbtmstatehigh);
+	}
+
+	sbimstate = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMSTATE);
+	if (sbimstate & (BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT)) {
+		sbimstate &= ~(BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT);
+		bcm43xx_write32(bcm, BCM43xx_CIR_SBIMSTATE, sbimstate);
+	}
+
+	sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
+		       BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
+		       core_flags;
+	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+	udelay(1);
+
+	sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | core_flags;
+	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+	udelay(1);
+
+	bcm->current_core->enabled = 1;
+	assert(err == 0);
+out:
+	return err;
+}
+
+/* http://bcm-specs.sipsolutions.net/80211CoreReset */
+void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
+{
+	u32 flags = 0x00040000;
+
+	if ((bcm43xx_core_enabled(bcm)) &&
+	    !bcm43xx_using_pio(bcm)) {
+//FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here?
+#ifndef CONFIG_BCM947XX
+		/* reset all used DMA controllers. */
+		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
+		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA2_BASE);
+		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA3_BASE);
+		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
+		bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
+		if (bcm->current_core->rev < 5)
+			bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
+#endif
+	}
+	if (bcm->shutting_down) {
+		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+		                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+				& ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002));
+	} else {
+		if (connect_phy)
+			flags |= 0x20000000;
+		bcm43xx_phy_connect(bcm, connect_phy);
+		bcm43xx_core_enable(bcm, flags);
+		bcm43xx_write16(bcm, 0x03E6, 0x0000);
+		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+				bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+				| BCM43xx_SBF_400);
+	}
+}
+
+static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm)
+{
+	bcm43xx_radio_turn_off(bcm);
+	bcm43xx_write16(bcm, 0x03E6, 0x00F4);
+	bcm43xx_core_disable(bcm, 0);
+}
+
+/* Mark the current 80211 core inactive.
+ * "active_80211_core" is the other 80211 core, which is used.
+ */
+static int bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm,
+					       struct bcm43xx_coreinfo *active_80211_core)
+{
+	u32 sbtmstatelow;
+	struct bcm43xx_coreinfo *old_core;
+	int err = 0;
+
+	bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+	bcm43xx_radio_turn_off(bcm);
+	sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+	sbtmstatelow &= ~0x200a0000;
+	sbtmstatelow |= 0xa0000;
+	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+	udelay(1);
+	sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+	sbtmstatelow &= ~0xa0000;
+	sbtmstatelow |= 0x80000;
+	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+	udelay(1);
+
+	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G) {
+		old_core = bcm->current_core;
+		err = bcm43xx_switch_core(bcm, active_80211_core);
+		if (err)
+			goto out;
+		sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+		sbtmstatelow &= ~0x20000000;
+		sbtmstatelow |= 0x20000000;
+		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+		err = bcm43xx_switch_core(bcm, old_core);
+	}
+
+out:
+	return err;
+}
+
+static void handle_irq_transmit_status(struct bcm43xx_private *bcm)
+{
+	u32 v0, v1;
+	u16 tmp;
+	struct bcm43xx_xmitstatus stat;
+
+	while (1) {
+		v0 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0);
+		if (!v0)
+			break;
+		v1 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1);
+
+		stat.cookie = (v0 >> 16) & 0x0000FFFF;
+		tmp = (u16)((v0 & 0xFFF0) | ((v0 & 0xF) >> 1));
+		stat.flags = tmp & 0xFF;
+		stat.cnt1 = (tmp & 0x0F00) >> 8;
+		stat.cnt2 = (tmp & 0xF000) >> 12;
+		stat.seq = (u16)(v1 & 0xFFFF);
+		stat.unknown = (u16)((v1 >> 16) & 0xFF);
+
+		bcm43xx_debugfs_log_txstat(bcm, &stat);
+
+		if (stat.flags & BCM43xx_TXSTAT_FLAG_IGNORE)
+			continue;
+		if (!(stat.flags & BCM43xx_TXSTAT_FLAG_ACK)) {
+			//TODO: packet was not acked (was lost)
+		}
+		//TODO: There are more (unknown) flags to test. see bcm43xx_main.h
+
+		if (bcm43xx_using_pio(bcm))
+			bcm43xx_pio_handle_xmitstatus(bcm, &stat);
+		else
+			bcm43xx_dma_handle_xmitstatus(bcm, &stat);
+	}
+}
+
+static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm)
+{
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F);
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x40A, 0x7F7F);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
+			bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) | (1 << 4));
+	assert(bcm->noisecalc.core_at_start == bcm->current_core);
+	assert(bcm->noisecalc.channel_at_start == bcm43xx_current_radio(bcm)->channel);
+}
+
+static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm)
+{
+	/* Top half of Link Quality calculation. */
+
+	if (bcm->noisecalc.calculation_running)
+		return;
+	bcm->noisecalc.core_at_start = bcm->current_core;
+	bcm->noisecalc.channel_at_start = bcm43xx_current_radio(bcm)->channel;
+	bcm->noisecalc.calculation_running = 1;
+	bcm->noisecalc.nr_samples = 0;
+
+	bcm43xx_generate_noise_sample(bcm);
+}
+
+static void handle_irq_noise(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 tmp;
+	u8 noise[4];
+	u8 i, j;
+	s32 average;
+
+	/* Bottom half of Link Quality calculation. */
+
+	assert(bcm->noisecalc.calculation_running);
+	if (bcm->noisecalc.core_at_start != bcm->current_core ||
+	    bcm->noisecalc.channel_at_start != radio->channel)
+		goto drop_calculation;
+	tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x408);
+	noise[0] = (tmp & 0x00FF);
+	noise[1] = (tmp & 0xFF00) >> 8;
+	tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40A);
+	noise[2] = (tmp & 0x00FF);
+	noise[3] = (tmp & 0xFF00) >> 8;
+	if (noise[0] == 0x7F || noise[1] == 0x7F ||
+	    noise[2] == 0x7F || noise[3] == 0x7F)
+		goto generate_new;
+
+	/* Get the noise samples. */
+	assert(bcm->noisecalc.nr_samples <= 8);
+	i = bcm->noisecalc.nr_samples;
+	noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+	noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+	noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+	noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+	bcm->noisecalc.samples[i][0] = radio->nrssi_lt[noise[0]];
+	bcm->noisecalc.samples[i][1] = radio->nrssi_lt[noise[1]];
+	bcm->noisecalc.samples[i][2] = radio->nrssi_lt[noise[2]];
+	bcm->noisecalc.samples[i][3] = radio->nrssi_lt[noise[3]];
+	bcm->noisecalc.nr_samples++;
+	if (bcm->noisecalc.nr_samples == 8) {
+		/* Calculate the Link Quality by the noise samples. */
+		average = 0;
+		for (i = 0; i < 8; i++) {
+			for (j = 0; j < 4; j++)
+				average += bcm->noisecalc.samples[i][j];
+		}
+		average /= (8 * 4);
+		average *= 125;
+		average += 64;
+		average /= 128;
+
+		tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40C);
+		tmp = (tmp / 128) & 0x1F;
+		if (tmp >= 8)
+			average += 2;
+		else
+			average -= 25;
+		if (tmp == 8)
+			average -= 72;
+		else
+			average -= 48;
+
+/* FIXME: This is wrong, but people want fancy stats. well... */
+bcm->stats.noise = average;
+		if (average > -65)
+			bcm->stats.link_quality = 0;
+		else if (average > -75)
+			bcm->stats.link_quality = 1;
+		else if (average > -85)
+			bcm->stats.link_quality = 2;
+		else
+			bcm->stats.link_quality = 3;
+//		dprintk(KERN_INFO PFX "Link Quality: %u (avg was %d)\n", bcm->stats.link_quality, average);
+drop_calculation:
+		bcm->noisecalc.calculation_running = 0;
+		return;
+	}
+generate_new:
+	bcm43xx_generate_noise_sample(bcm);
+}
+
+static void handle_irq_ps(struct bcm43xx_private *bcm)
+{
+	if (bcm->ieee->iw_mode == IW_MODE_MASTER) {
+		///TODO: PS TBTT
+	} else {
+		if (1/*FIXME: the last PSpoll frame was sent successfully */)
+			bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+	}
+	if (bcm->ieee->iw_mode == IW_MODE_ADHOC)
+		bcm->reg124_set_0x4 = 1;
+	//FIXME else set to false?
+}
+
+static void handle_irq_reg124(struct bcm43xx_private *bcm)
+{
+	if (!bcm->reg124_set_0x4)
+		return;
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
+			bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD)
+			| 0x4);
+	//FIXME: reset reg124_set_0x4 to false?
+}
+
+static void handle_irq_pmq(struct bcm43xx_private *bcm)
+{
+	u32 tmp;
+
+	//TODO: AP mode.
+
+	while (1) {
+		tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_PS_STATUS);
+		if (!(tmp & 0x00000008))
+			break;
+	}
+	/* 16bit write is odd, but correct. */
+	bcm43xx_write16(bcm, BCM43xx_MMIO_PS_STATUS, 0x0002);
+}
+
+static void bcm43xx_generate_beacon_template(struct bcm43xx_private *bcm,
+					     u16 ram_offset, u16 shm_size_offset)
+{
+	u32 value;
+	u16 size = 0;
+
+	/* Timestamp. */
+	//FIXME: assumption: The chip sets the timestamp
+	value = 0;
+	bcm43xx_ram_write(bcm, ram_offset++, value);
+	bcm43xx_ram_write(bcm, ram_offset++, value);
+	size += 8;
+
+	/* Beacon Interval / Capability Information */
+	value = 0x0000;//FIXME: Which interval?
+	value |= (1 << 0) << 16; /* ESS */
+	value |= (1 << 2) << 16; /* CF Pollable */	//FIXME?
+	value |= (1 << 3) << 16; /* CF Poll Request */	//FIXME?
+	if (!bcm->ieee->open_wep)
+		value |= (1 << 4) << 16; /* Privacy */
+	bcm43xx_ram_write(bcm, ram_offset++, value);
+	size += 4;
+
+	/* SSID */
+	//TODO
+
+	/* FH Parameter Set */
+	//TODO
+
+	/* DS Parameter Set */
+	//TODO
+
+	/* CF Parameter Set */
+	//TODO
+
+	/* TIM */
+	//TODO
+
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size);
+}
+
+static void handle_irq_beacon(struct bcm43xx_private *bcm)
+{
+	u32 status;
+
+	bcm->irq_savedstate &= ~BCM43xx_IRQ_BEACON;
+	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD);
+
+	if ((status & 0x1) && (status & 0x2)) {
+		/* ACK beacon IRQ. */
+		bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON,
+				BCM43xx_IRQ_BEACON);
+		bcm->irq_savedstate |= BCM43xx_IRQ_BEACON;
+		return;
+	}
+	if (!(status & 0x1)) {
+		bcm43xx_generate_beacon_template(bcm, 0x68, 0x18);
+		status |= 0x1;
+		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
+	}
+	if (!(status & 0x2)) {
+		bcm43xx_generate_beacon_template(bcm, 0x468, 0x1A);
+		status |= 0x2;
+		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
+	}
+}
+
+/* Interrupt handler bottom-half */
+static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
+{
+	u32 reason;
+	u32 dma_reason[4];
+	int activity = 0;
+	unsigned long flags;
+
+#ifdef CONFIG_BCM43XX_DEBUG
+	u32 _handled = 0x00000000;
+# define bcmirq_handled(irq)	do { _handled |= (irq); } while (0)
+#else
+# define bcmirq_handled(irq)	do { /* nothing */ } while (0)
+#endif /* CONFIG_BCM43XX_DEBUG*/
+
+	bcm43xx_lock_mmio(bcm, flags);
+	reason = bcm->irq_reason;
+	dma_reason[0] = bcm->dma_reason[0];
+	dma_reason[1] = bcm->dma_reason[1];
+	dma_reason[2] = bcm->dma_reason[2];
+	dma_reason[3] = bcm->dma_reason[3];
+
+	if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) {
+		/* TX error. We get this when Template Ram is written in wrong endianess
+		 * in dummy_tx(). We also get this if something is wrong with the TX header
+		 * on DMA or PIO queues.
+		 * Maybe we get this in other error conditions, too.
+		 */
+		printkl(KERN_ERR PFX "FATAL ERROR: BCM43xx_IRQ_XMIT_ERROR\n");
+		bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR);
+	}
+	if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_FATALMASK) |
+		     (dma_reason[1] & BCM43xx_DMAIRQ_FATALMASK) |
+		     (dma_reason[2] & BCM43xx_DMAIRQ_FATALMASK) |
+		     (dma_reason[3] & BCM43xx_DMAIRQ_FATALMASK))) {
+		printkl(KERN_ERR PFX "FATAL ERROR: Fatal DMA error: "
+				     "0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
+		        dma_reason[0], dma_reason[1],
+			dma_reason[2], dma_reason[3]);
+		bcm43xx_controller_restart(bcm, "DMA error");
+		bcm43xx_unlock_mmio(bcm, flags);
+		return;
+	}
+	if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) |
+		     (dma_reason[1] & BCM43xx_DMAIRQ_NONFATALMASK) |
+		     (dma_reason[2] & BCM43xx_DMAIRQ_NONFATALMASK) |
+		     (dma_reason[3] & BCM43xx_DMAIRQ_NONFATALMASK))) {
+		printkl(KERN_ERR PFX "DMA error: "
+				     "0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
+		        dma_reason[0], dma_reason[1],
+			dma_reason[2], dma_reason[3]);
+	}
+
+	if (reason & BCM43xx_IRQ_PS) {
+		handle_irq_ps(bcm);
+		bcmirq_handled(BCM43xx_IRQ_PS);
+	}
+
+	if (reason & BCM43xx_IRQ_REG124) {
+		handle_irq_reg124(bcm);
+		bcmirq_handled(BCM43xx_IRQ_REG124);
+	}
+
+	if (reason & BCM43xx_IRQ_BEACON) {
+		if (bcm->ieee->iw_mode == IW_MODE_MASTER)
+			handle_irq_beacon(bcm);
+		bcmirq_handled(BCM43xx_IRQ_BEACON);
+	}
+
+	if (reason & BCM43xx_IRQ_PMQ) {
+		handle_irq_pmq(bcm);
+		bcmirq_handled(BCM43xx_IRQ_PMQ);
+	}
+
+	if (reason & BCM43xx_IRQ_SCAN) {
+		/*TODO*/
+		//bcmirq_handled(BCM43xx_IRQ_SCAN);
+	}
+
+	if (reason & BCM43xx_IRQ_NOISE) {
+		handle_irq_noise(bcm);
+		bcmirq_handled(BCM43xx_IRQ_NOISE);
+	}
+
+	/* Check the DMA reason registers for received data. */
+	assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE));
+	assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE));
+	if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) {
+		if (bcm43xx_using_pio(bcm))
+			bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue0);
+		else
+			bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring0);
+		/* We intentionally don't set "activity" to 1, here. */
+	}
+	if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) {
+		if (bcm43xx_using_pio(bcm))
+			bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue3);
+		else
+			bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring1);
+		activity = 1;
+	}
+	bcmirq_handled(BCM43xx_IRQ_RX);
+
+	if (reason & BCM43xx_IRQ_XMIT_STATUS) {
+		handle_irq_transmit_status(bcm);
+		activity = 1;
+		//TODO: In AP mode, this also causes sending of powersave responses.
+		bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS);
+	}
+
+	/* IRQ_PIO_WORKAROUND is handled in the top-half. */
+	bcmirq_handled(BCM43xx_IRQ_PIO_WORKAROUND);
+#ifdef CONFIG_BCM43XX_DEBUG
+	if (unlikely(reason & ~_handled)) {
+		printkl(KERN_WARNING PFX
+			"Unhandled IRQ! Reason: 0x%08x,  Unhandled: 0x%08x,  "
+			"DMA: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+			reason, (reason & ~_handled),
+			dma_reason[0], dma_reason[1],
+			dma_reason[2], dma_reason[3]);
+	}
+#endif
+#undef bcmirq_handled
+
+	if (!modparam_noleds)
+		bcm43xx_leds_update(bcm, activity);
+	bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
+	bcm43xx_unlock_mmio(bcm, flags);
+}
+
+static void pio_irq_workaround(struct bcm43xx_private *bcm,
+			       u16 base, int queueidx)
+{
+	u16 rxctl;
+
+	rxctl = bcm43xx_read16(bcm, base + BCM43xx_PIO_RXCTL);
+	if (rxctl & BCM43xx_PIO_RXCTL_DATAAVAILABLE)
+		bcm->dma_reason[queueidx] |= BCM43xx_DMAIRQ_RX_DONE;
+	else
+		bcm->dma_reason[queueidx] &= ~BCM43xx_DMAIRQ_RX_DONE;
+}
+
+static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason)
+{
+	if (bcm43xx_using_pio(bcm) &&
+	    (bcm->current_core->rev < 3) &&
+	    (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) {
+		/* Apply a PIO specific workaround to the dma_reasons */
+		pio_irq_workaround(bcm, BCM43xx_MMIO_PIO1_BASE, 0);
+		pio_irq_workaround(bcm, BCM43xx_MMIO_PIO2_BASE, 1);
+		pio_irq_workaround(bcm, BCM43xx_MMIO_PIO3_BASE, 2);
+		pio_irq_workaround(bcm, BCM43xx_MMIO_PIO4_BASE, 3);
+	}
+
+	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason);
+
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON,
+			bcm->dma_reason[0]);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON,
+			bcm->dma_reason[1]);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON,
+			bcm->dma_reason[2]);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON,
+			bcm->dma_reason[3]);
+}
+
+/* Interrupt handler top-half */
+static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	irqreturn_t ret = IRQ_HANDLED;
+	struct bcm43xx_private *bcm = dev_id;
+	u32 reason;
+
+	if (!bcm)
+		return IRQ_NONE;
+
+	spin_lock(&bcm->_lock);
+
+	reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+	if (reason == 0xffffffff) {
+		/* irq not for us (shared irq) */
+		ret = IRQ_NONE;
+		goto out;
+	}
+	reason &= bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
+	if (!reason)
+		goto out;
+
+	bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON)
+			     & 0x0001dc00;
+	bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON)
+			     & 0x0000dc00;
+	bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON)
+			     & 0x0000dc00;
+	bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON)
+			     & 0x0001dc00;
+
+	bcm43xx_interrupt_ack(bcm, reason);
+
+	/* Only accept IRQs, if we are initialized properly.
+	 * This avoids an RX race while initializing.
+	 * We should probably not enable IRQs before we are initialized
+	 * completely, but some careful work is needed to fix this. I think it
+	 * is best to stay with this cheap workaround for now... .
+	 */
+	if (likely(bcm->initialized)) {
+		/* disable all IRQs. They are enabled again in the bottom half. */
+		bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+		/* save the reason code and call our bottom half. */
+		bcm->irq_reason = reason;
+		tasklet_schedule(&bcm->isr_tasklet);
+	}
+
+out:
+	mmiowb();
+	spin_unlock(&bcm->_lock);
+
+	return ret;
+}
+
+static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force)
+{
+	if (bcm->firmware_norelease && !force)
+		return; /* Suspending or controller reset. */
+	release_firmware(bcm->ucode);
+	bcm->ucode = NULL;
+	release_firmware(bcm->pcm);
+	bcm->pcm = NULL;
+	release_firmware(bcm->initvals0);
+	bcm->initvals0 = NULL;
+	release_firmware(bcm->initvals1);
+	bcm->initvals1 = NULL;
+}
+
+static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	u8 rev = bcm->current_core->rev;
+	int err = 0;
+	int nr;
+	char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 };
+
+	if (!bcm->ucode) {
+		snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw",
+			 (rev >= 5 ? 5 : rev),
+			 modparam_fwpostfix);
+		err = request_firmware(&bcm->ucode, buf, &bcm->pci_dev->dev);
+		if (err) {
+			printk(KERN_ERR PFX 
+			       "Error: Microcode \"%s\" not available or load failed.\n",
+			        buf);
+			goto error;
+		}
+	}
+
+	if (!bcm->pcm) {
+		snprintf(buf, ARRAY_SIZE(buf),
+			 "bcm43xx_pcm%d%s.fw",
+			 (rev < 5 ? 4 : 5),
+			 modparam_fwpostfix);
+		err = request_firmware(&bcm->pcm, buf, &bcm->pci_dev->dev);
+		if (err) {
+			printk(KERN_ERR PFX
+			       "Error: PCM \"%s\" not available or load failed.\n",
+			       buf);
+			goto error;
+		}
+	}
+
+	if (!bcm->initvals0) {
+		if (rev == 2 || rev == 4) {
+			switch (phy->type) {
+			case BCM43xx_PHYTYPE_A:
+				nr = 3;
+				break;
+			case BCM43xx_PHYTYPE_B:
+			case BCM43xx_PHYTYPE_G:
+				nr = 1;
+				break;
+			default:
+				goto err_noinitval;
+			}
+		
+		} else if (rev >= 5) {
+			switch (phy->type) {
+			case BCM43xx_PHYTYPE_A:
+				nr = 7;
+				break;
+			case BCM43xx_PHYTYPE_B:
+			case BCM43xx_PHYTYPE_G:
+				nr = 5;
+				break;
+			default:
+				goto err_noinitval;
+			}
+		} else
+			goto err_noinitval;
+		snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
+			 nr, modparam_fwpostfix);
+
+		err = request_firmware(&bcm->initvals0, buf, &bcm->pci_dev->dev);
+		if (err) {
+			printk(KERN_ERR PFX 
+			       "Error: InitVals \"%s\" not available or load failed.\n",
+			        buf);
+			goto error;
+		}
+		if (bcm->initvals0->size % sizeof(struct bcm43xx_initval)) {
+			printk(KERN_ERR PFX "InitVals fileformat error.\n");
+			goto error;
+		}
+	}
+
+	if (!bcm->initvals1) {
+		if (rev >= 5) {
+			u32 sbtmstatehigh;
+
+			switch (phy->type) {
+			case BCM43xx_PHYTYPE_A:
+				sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+				if (sbtmstatehigh & 0x00010000)
+					nr = 9;
+				else
+					nr = 10;
+				break;
+			case BCM43xx_PHYTYPE_B:
+			case BCM43xx_PHYTYPE_G:
+					nr = 6;
+				break;
+			default:
+				goto err_noinitval;
+			}
+			snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
+				 nr, modparam_fwpostfix);
+
+			err = request_firmware(&bcm->initvals1, buf, &bcm->pci_dev->dev);
+			if (err) {
+				printk(KERN_ERR PFX 
+				       "Error: InitVals \"%s\" not available or load failed.\n",
+			        	buf);
+				goto error;
+			}
+			if (bcm->initvals1->size % sizeof(struct bcm43xx_initval)) {
+				printk(KERN_ERR PFX "InitVals fileformat error.\n");
+				goto error;
+			}
+		}
+	}
+
+out:
+	return err;
+error:
+	bcm43xx_release_firmware(bcm, 1);
+	goto out;
+err_noinitval:
+	printk(KERN_ERR PFX "Error: No InitVals available!\n");
+	err = -ENOENT;
+	goto error;
+}
+
+static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
+{
+	const u32 *data;
+	unsigned int i, len;
+
+	/* Upload Microcode. */
+	data = (u32 *)(bcm->ucode->data);
+	len = bcm->ucode->size / sizeof(u32);
+	bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000);
+	for (i = 0; i < len; i++) {
+		bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
+				be32_to_cpu(data[i]));
+		udelay(10);
+	}
+
+	/* Upload PCM data. */
+	data = (u32 *)(bcm->pcm->data);
+	len = bcm->pcm->size / sizeof(u32);
+	bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000);
+	bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb);
+	for (i = 0; i < len; i++) {
+		bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
+				be32_to_cpu(data[i]));
+		udelay(10);
+	}
+}
+
+static int bcm43xx_write_initvals(struct bcm43xx_private *bcm,
+				  const struct bcm43xx_initval *data,
+				  const unsigned int len)
+{
+	u16 offset, size;
+	u32 value;
+	unsigned int i;
+
+	for (i = 0; i < len; i++) {
+		offset = be16_to_cpu(data[i].offset);
+		size = be16_to_cpu(data[i].size);
+		value = be32_to_cpu(data[i].value);
+
+		if (unlikely(offset >= 0x1000))
+			goto err_format;
+		if (size == 2) {
+			if (unlikely(value & 0xFFFF0000))
+				goto err_format;
+			bcm43xx_write16(bcm, offset, (u16)value);
+		} else if (size == 4) {
+			bcm43xx_write32(bcm, offset, value);
+		} else
+			goto err_format;
+	}
+
+	return 0;
+
+err_format:
+	printk(KERN_ERR PFX "InitVals (bcm43xx_initvalXX.fw) file-format error. "
+			    "Please fix your bcm43xx firmware files.\n");
+	return -EPROTO;
+}
+
+static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm)
+{
+	int err;
+
+	err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data,
+				     bcm->initvals0->size / sizeof(struct bcm43xx_initval));
+	if (err)
+		goto out;
+	if (bcm->initvals1) {
+		err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data,
+					     bcm->initvals1->size / sizeof(struct bcm43xx_initval));
+		if (err)
+			goto out;
+	}
+out:
+	return err;
+}
+
+static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
+{
+	int res;
+	unsigned int i;
+	u32 data;
+
+	bcm->irq = bcm->pci_dev->irq;
+#ifdef CONFIG_BCM947XX
+	if (bcm->pci_dev->bus->number == 0) {
+		struct pci_dev *d = NULL;
+		/* FIXME: we will probably need more device IDs here... */
+		d = pci_find_device(PCI_VENDOR_ID_BROADCOM, 0x4324, NULL);
+		if (d != NULL) {
+			bcm->irq = d->irq;
+		}
+	}
+#endif
+	res = request_irq(bcm->irq, bcm43xx_interrupt_handler,
+			  SA_SHIRQ, KBUILD_MODNAME, bcm);
+	if (res) {
+		printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq);
+		return -ENODEV;
+	}
+	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xffffffff);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
+	i = 0;
+	while (1) {
+		data = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+		if (data == BCM43xx_IRQ_READY)
+			break;
+		i++;
+		if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
+			printk(KERN_ERR PFX "Card IRQ register not responding. "
+					    "Giving up.\n");
+			free_irq(bcm->irq, bcm);
+			return -ENODEV;
+		}
+		udelay(10);
+	}
+	// dummy read
+	bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+
+	return 0;
+}
+
+/* Switch to the core used to write the GPIO register.
+ * This is either the ChipCommon, or the PCI core.
+ */
+static int switch_to_gpio_core(struct bcm43xx_private *bcm)
+{
+	int err;
+
+	/* Where to find the GPIO register depends on the chipset.
+	 * If it has a ChipCommon, its register at offset 0x6c is the GPIO
+	 * control register. Otherwise the register at offset 0x6c in the
+	 * PCI core is the GPIO control register.
+	 */
+	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+	if (err == -ENODEV) {
+		err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+		if (unlikely(err == -ENODEV)) {
+			printk(KERN_ERR PFX "gpio error: "
+			       "Neither ChipCommon nor PCI core available!\n");
+		}
+	}
+
+	return err;
+}
+
+/* Initialize the GPIOs
+ * http://bcm-specs.sipsolutions.net/GPIO
+ */
+static int bcm43xx_gpio_init(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_coreinfo *old_core;
+	int err;
+	u32 mask, set;
+
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+			bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+			& 0xFFFF3FFF);
+
+	bcm43xx_leds_switch_all(bcm, 0);
+	bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
+			bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) | 0x000F);
+
+	mask = 0x0000001F;
+	set = 0x0000000F;
+	if (bcm->chip_id == 0x4301) {
+		mask |= 0x0060;
+		set |= 0x0060;
+	}
+	if (0 /* FIXME: conditional unknown */) {
+		bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
+				bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK)
+				| 0x0100);
+		mask |= 0x0180;
+		set |= 0x0180;
+	}
+	if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
+		bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
+				bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK)
+				| 0x0200);
+		mask |= 0x0200;
+		set |= 0x0200;
+	}
+	if (bcm->current_core->rev >= 2)
+		mask  |= 0x0010; /* FIXME: This is redundant. */
+
+	old_core = bcm->current_core;
+	err = switch_to_gpio_core(bcm);
+	if (err)
+		goto out;
+	bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL,
+	                (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | set);
+	err = bcm43xx_switch_core(bcm, old_core);
+out:
+	return err;
+}
+
+/* Turn off all GPIO stuff. Call this on module unload, for example. */
+static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_coreinfo *old_core;
+	int err;
+
+	old_core = bcm->current_core;
+	err = switch_to_gpio_core(bcm);
+	if (err)
+		return err;
+	bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, 0x00000000);
+	err = bcm43xx_switch_core(bcm, old_core);
+	assert(err == 0);
+
+	return 0;
+}
+
+/* http://bcm-specs.sipsolutions.net/EnableMac */
+void bcm43xx_mac_enable(struct bcm43xx_private *bcm)
+{
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+	                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+			| BCM43xx_SBF_MAC_ENABLED);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
+	bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
+	bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+	bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+}
+
+/* http://bcm-specs.sipsolutions.net/SuspendMAC */
+void bcm43xx_mac_suspend(struct bcm43xx_private *bcm)
+{
+	int i;
+	u32 tmp;
+
+	bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+	                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+			& ~BCM43xx_SBF_MAC_ENABLED);
+	bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+	for (i = 100000; i; i--) {
+		tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+		if (tmp & BCM43xx_IRQ_READY)
+			return;
+		udelay(10);
+	}
+	printkl(KERN_ERR PFX "MAC suspend failed\n");
+}
+
+void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
+			int iw_mode)
+{
+	unsigned long flags;
+	struct net_device *net_dev = bcm->net_dev;
+	u32 status;
+	u16 value;
+
+	spin_lock_irqsave(&bcm->ieee->lock, flags);
+	bcm->ieee->iw_mode = iw_mode;
+	spin_unlock_irqrestore(&bcm->ieee->lock, flags);
+	if (iw_mode == IW_MODE_MONITOR)
+		net_dev->type = ARPHRD_IEEE80211;
+	else
+		net_dev->type = ARPHRD_ETHER;
+
+	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+	/* Reset status to infrastructured mode */
+	status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR);
+	status &= ~BCM43xx_SBF_MODE_PROMISC;
+	status |= BCM43xx_SBF_MODE_NOTADHOC;
+
+/* FIXME: Always enable promisc mode, until we get the MAC filters working correctly. */
+status |= BCM43xx_SBF_MODE_PROMISC;
+
+	switch (iw_mode) {
+	case IW_MODE_MONITOR:
+		status |= BCM43xx_SBF_MODE_MONITOR;
+		status |= BCM43xx_SBF_MODE_PROMISC;
+		break;
+	case IW_MODE_ADHOC:
+		status &= ~BCM43xx_SBF_MODE_NOTADHOC;
+		break;
+	case IW_MODE_MASTER:
+		status |= BCM43xx_SBF_MODE_AP;
+		break;
+	case IW_MODE_SECOND:
+	case IW_MODE_REPEAT:
+		TODO(); /* TODO */
+		break;
+	case IW_MODE_INFRA:
+		/* nothing to be done here... */
+		break;
+	default:
+		dprintk(KERN_ERR PFX "Unknown mode in set_iwmode: %d\n", iw_mode);
+	}
+	if (net_dev->flags & IFF_PROMISC)
+		status |= BCM43xx_SBF_MODE_PROMISC;
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+
+	value = 0x0002;
+	if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) {
+		if (bcm->chip_id == 0x4306 && bcm->chip_rev == 3)
+			value = 0x0064;
+		else
+			value = 0x0032;
+	}
+	bcm43xx_write16(bcm, 0x0612, value);
+}
+
+/* This is the opposite of bcm43xx_chip_init() */
+static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm)
+{
+	bcm43xx_radio_turn_off(bcm);
+	if (!modparam_noleds)
+		bcm43xx_leds_exit(bcm);
+	bcm43xx_gpio_cleanup(bcm);
+	free_irq(bcm->irq, bcm);
+	bcm43xx_release_firmware(bcm, 0);
+}
+
+/* Initialize the chip
+ * http://bcm-specs.sipsolutions.net/ChipInit
+ */
+static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	int err;
+	int tmp;
+	u32 value32;
+	u16 value16;
+
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+			BCM43xx_SBF_CORE_READY
+			| BCM43xx_SBF_400);
+
+	err = bcm43xx_request_firmware(bcm);
+	if (err)
+		goto out;
+	bcm43xx_upload_microcode(bcm);
+
+	err = bcm43xx_initialize_irq(bcm);
+	if (err)
+		goto err_release_fw;
+
+	err = bcm43xx_gpio_init(bcm);
+	if (err)
+		goto err_free_irq;
+
+	err = bcm43xx_upload_initvals(bcm);
+	if (err)
+		goto err_gpio_cleanup;
+	bcm43xx_radio_turn_on(bcm);
+
+	bcm43xx_write16(bcm, 0x03E6, 0x0000);
+	err = bcm43xx_phy_init(bcm);
+	if (err)
+		goto err_radio_off;
+
+	/* Select initial Interference Mitigation. */
+	tmp = radio->interfmode;
+	radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
+	bcm43xx_radio_set_interference_mitigation(bcm, tmp);
+
+	bcm43xx_phy_set_antenna_diversity(bcm);
+	bcm43xx_radio_set_txantenna(bcm, BCM43xx_RADIO_TXANTENNA_DEFAULT);
+	if (phy->type == BCM43xx_PHYTYPE_B) {
+		value16 = bcm43xx_read16(bcm, 0x005E);
+		value16 |= 0x0004;
+		bcm43xx_write16(bcm, 0x005E, value16);
+	}
+	bcm43xx_write32(bcm, 0x0100, 0x01000000);
+	if (bcm->current_core->rev < 5)
+		bcm43xx_write32(bcm, 0x010C, 0x01000000);
+
+	value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+	value32 &= ~ BCM43xx_SBF_MODE_NOTADHOC;
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
+	value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+	value32 |= BCM43xx_SBF_MODE_NOTADHOC;
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
+
+	value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+	value32 |= 0x100000;
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
+
+	if (bcm43xx_using_pio(bcm)) {
+		bcm43xx_write32(bcm, 0x0210, 0x00000100);
+		bcm43xx_write32(bcm, 0x0230, 0x00000100);
+		bcm43xx_write32(bcm, 0x0250, 0x00000100);
+		bcm43xx_write32(bcm, 0x0270, 0x00000100);
+		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0034, 0x0000);
+	}
+
+	/* Probe Response Timeout value */
+	/* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000);
+
+	/* Initially set the wireless operation mode. */
+	bcm43xx_set_iwmode(bcm, bcm->ieee->iw_mode);
+
+	if (bcm->current_core->rev < 3) {
+		bcm43xx_write16(bcm, 0x060E, 0x0000);
+		bcm43xx_write16(bcm, 0x0610, 0x8000);
+		bcm43xx_write16(bcm, 0x0604, 0x0000);
+		bcm43xx_write16(bcm, 0x0606, 0x0200);
+	} else {
+		bcm43xx_write32(bcm, 0x0188, 0x80000000);
+		bcm43xx_write32(bcm, 0x018C, 0x02000000);
+	}
+	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0001DC00);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0000DC00);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0001DC00);
+
+	value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+	value32 |= 0x00100000;
+	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, value32);
+
+	bcm43xx_write16(bcm, BCM43xx_MMIO_POWERUP_DELAY, bcm43xx_pctl_powerup_delay(bcm));
+
+	assert(err == 0);
+	dprintk(KERN_INFO PFX "Chip initialized\n");
+out:
+	return err;
+
+err_radio_off:
+	bcm43xx_radio_turn_off(bcm);
+err_gpio_cleanup:
+	bcm43xx_gpio_cleanup(bcm);
+err_free_irq:
+	free_irq(bcm->irq, bcm);
+err_release_fw:
+	bcm43xx_release_firmware(bcm, 1);
+	goto out;
+}
+	
+/* Validate chip access
+ * http://bcm-specs.sipsolutions.net/ValidateChipAccess */
+static int bcm43xx_validate_chip(struct bcm43xx_private *bcm)
+{
+	u32 value;
+	u32 shm_backup;
+
+	shm_backup = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000);
+	bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0xAA5555AA);
+	if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA)
+		goto error;
+	bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0x55AAAA55);
+	if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55)
+		goto error;
+	bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, shm_backup);
+
+	value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+	if ((value | 0x80000000) != 0x80000400)
+		goto error;
+
+	value = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+	if (value != 0x00000000)
+		goto error;
+
+	return 0;
+error:
+	printk(KERN_ERR PFX "Failed to validate the chipaccess\n");
+	return -ENODEV;
+}
+
+static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy)
+{
+	/* Initialize a "phyinfo" structure. The structure is already
+	 * zeroed out.
+	 */
+	phy->antenna_diversity = 0xFFFF;
+	phy->savedpctlreg = 0xFFFF;
+	phy->minlowsig[0] = 0xFFFF;
+	phy->minlowsig[1] = 0xFFFF;
+	spin_lock_init(&phy->lock);
+}
+
+static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio)
+{
+	/* Initialize a "radioinfo" structure. The structure is already
+	 * zeroed out.
+	 */
+	radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
+	radio->channel = 0xFF;
+	radio->initial_channel = 0xFF;
+	radio->lofcal = 0xFFFF;
+	radio->initval = 0xFFFF;
+	radio->nrssi[0] = -1000;
+	radio->nrssi[1] = -1000;
+}
+
+static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
+{
+	int err, i;
+	int current_core;
+	u32 core_vendor, core_id, core_rev;
+	u32 sb_id_hi, chip_id_32 = 0;
+	u16 pci_device, chip_id_16;
+	u8 core_count;
+
+	memset(&bcm->core_chipcommon, 0, sizeof(struct bcm43xx_coreinfo));
+	memset(&bcm->core_pci, 0, sizeof(struct bcm43xx_coreinfo));
+	memset(&bcm->core_80211, 0, sizeof(struct bcm43xx_coreinfo)
+				    * BCM43xx_MAX_80211_CORES);
+	memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211)
+					* BCM43xx_MAX_80211_CORES);
+	bcm->current_80211_core_idx = -1;
+	bcm->nr_80211_available = 0;
+	bcm->current_core = NULL;
+	bcm->active_80211_core = NULL;
+
+	/* map core 0 */
+	err = _switch_core(bcm, 0);
+	if (err)
+		goto out;
+
+	/* fetch sb_id_hi from core information registers */
+	sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
+
+	core_id = (sb_id_hi & 0xFFF0) >> 4;
+	core_rev = (sb_id_hi & 0xF);
+	core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
+
+	/* if present, chipcommon is always core 0; read the chipid from it */
+	if (core_id == BCM43xx_COREID_CHIPCOMMON) {
+		chip_id_32 = bcm43xx_read32(bcm, 0);
+		chip_id_16 = chip_id_32 & 0xFFFF;
+		bcm->core_chipcommon.available = 1;
+		bcm->core_chipcommon.id = core_id;
+		bcm->core_chipcommon.rev = core_rev;
+		bcm->core_chipcommon.index = 0;
+		/* While we are at it, also read the capabilities. */
+		bcm->chipcommon_capabilities = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_CAPABILITIES);
+	} else {
+		/* without a chipCommon, use a hard coded table. */
+		pci_device = bcm->pci_dev->device;
+		if (pci_device == 0x4301)
+			chip_id_16 = 0x4301;
+		else if ((pci_device >= 0x4305) && (pci_device <= 0x4307))
+			chip_id_16 = 0x4307;
+		else if ((pci_device >= 0x4402) && (pci_device <= 0x4403))
+			chip_id_16 = 0x4402;
+		else if ((pci_device >= 0x4610) && (pci_device <= 0x4615))
+			chip_id_16 = 0x4610;
+		else if ((pci_device >= 0x4710) && (pci_device <= 0x4715))
+			chip_id_16 = 0x4710;
+#ifdef CONFIG_BCM947XX
+		else if ((pci_device >= 0x4320) && (pci_device <= 0x4325))
+			chip_id_16 = 0x4309;
+#endif
+		else {
+			printk(KERN_ERR PFX "Could not determine Chip ID\n");
+			return -ENODEV;
+		}
+	}
+
+	/* ChipCommon with Core Rev >=4 encodes number of cores,
+	 * otherwise consult hardcoded table */
+	if ((core_id == BCM43xx_COREID_CHIPCOMMON) && (core_rev >= 4)) {
+		core_count = (chip_id_32 & 0x0F000000) >> 24;
+	} else {
+		switch (chip_id_16) {
+			case 0x4610:
+			case 0x4704:
+			case 0x4710:
+				core_count = 9;
+				break;
+			case 0x4310:
+				core_count = 8;
+				break;
+			case 0x5365:
+				core_count = 7;
+				break;
+			case 0x4306:
+				core_count = 6;
+				break;
+			case 0x4301:
+			case 0x4307:
+				core_count = 5;
+				break;
+			case 0x4402:
+				core_count = 3;
+				break;
+			default:
+				/* SOL if we get here */
+				assert(0);
+				core_count = 1;
+		}
+	}
+
+	bcm->chip_id = chip_id_16;
+	bcm->chip_rev = (chip_id_32 & 0x000F0000) >> 16;
+	bcm->chip_package = (chip_id_32 & 0x00F00000) >> 20;
+
+	dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n",
+		bcm->chip_id, bcm->chip_rev);
+	dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count);
+	if (bcm->core_chipcommon.available) {
+		dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n",
+			core_id, core_rev, core_vendor,
+			bcm43xx_core_enabled(bcm) ? "enabled" : "disabled");
+	}
+
+	if (bcm->core_chipcommon.available)
+		current_core = 1;
+	else
+		current_core = 0;
+	for ( ; current_core < core_count; current_core++) {
+		struct bcm43xx_coreinfo *core;
+		struct bcm43xx_coreinfo_80211 *ext_80211;
+
+		err = _switch_core(bcm, current_core);
+		if (err)
+			goto out;
+		/* Gather information */
+		/* fetch sb_id_hi from core information registers */
+		sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
+
+		/* extract core_id, core_rev, core_vendor */
+		core_id = (sb_id_hi & 0xFFF0) >> 4;
+		core_rev = (sb_id_hi & 0xF);
+		core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
+
+		dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n",
+			current_core, core_id, core_rev, core_vendor,
+			bcm43xx_core_enabled(bcm) ? "enabled" : "disabled" );
+
+		core = NULL;
+		switch (core_id) {
+		case BCM43xx_COREID_PCI:
+			core = &bcm->core_pci;
+			if (core->available) {
+				printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
+				continue;
+			}
+			break;
+		case BCM43xx_COREID_80211:
+			for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+				core = &(bcm->core_80211[i]);
+				ext_80211 = &(bcm->core_80211_ext[i]);
+				if (!core->available)
+					break;
+				core = NULL;
+			}
+			if (!core) {
+				printk(KERN_WARNING PFX "More than %d cores of type 802.11 found.\n",
+				       BCM43xx_MAX_80211_CORES);
+				continue;
+			}
+			if (i != 0) {
+				/* More than one 80211 core is only supported
+				 * by special chips.
+				 * There are chips with two 80211 cores, but with
+				 * dangling pins on the second core. Be careful
+				 * and ignore these cores here.
+				 */
+				if (bcm->pci_dev->device != 0x4324) {
+					dprintk(KERN_INFO PFX "Ignoring additional 802.11 core.\n");
+					continue;
+				}
+			}
+			switch (core_rev) {
+			case 2:
+			case 4:
+			case 5:
+			case 6:
+			case 7:
+			case 9:
+				break;
+			default:
+				printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
+				       core_rev);
+				err = -ENODEV;
+				goto out;
+			}
+			bcm->nr_80211_available++;
+			bcm43xx_init_struct_phyinfo(&ext_80211->phy);
+			bcm43xx_init_struct_radioinfo(&ext_80211->radio);
+			break;
+		case BCM43xx_COREID_CHIPCOMMON:
+			printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n");
+			break;
+		}
+		if (core) {
+			core->available = 1;
+			core->id = core_id;
+			core->rev = core_rev;
+			core->index = current_core;
+		}
+	}
+
+	if (!bcm->core_80211[0].available) {
+		printk(KERN_ERR PFX "Error: No 80211 core found!\n");
+		err = -ENODEV;
+		goto out;
+	}
+
+	err = bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
+
+	assert(err == 0);
+out:
+	return err;
+}
+
+static void bcm43xx_gen_bssid(struct bcm43xx_private *bcm)
+{
+	const u8 *mac = (const u8*)(bcm->net_dev->dev_addr);
+	u8 *bssid = bcm->ieee->bssid;
+
+	switch (bcm->ieee->iw_mode) {
+	case IW_MODE_ADHOC:
+		random_ether_addr(bssid);
+		break;
+	case IW_MODE_MASTER:
+	case IW_MODE_INFRA:
+	case IW_MODE_REPEAT:
+	case IW_MODE_SECOND:
+	case IW_MODE_MONITOR:
+		memcpy(bssid, mac, ETH_ALEN);
+		break;
+	default:
+		assert(0);
+	}
+}
+
+static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm,
+				      u16 rate,
+				      int is_ofdm)
+{
+	u16 offset;
+
+	if (is_ofdm) {
+		offset = 0x480;
+		offset += (bcm43xx_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2;
+	}
+	else {
+		offset = 0x4C0;
+		offset += (bcm43xx_plcp_get_ratecode_cck(rate) & 0x000F) * 2;
+	}
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, offset + 0x20,
+			    bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, offset));
+}
+
+static void bcm43xx_rate_memory_init(struct bcm43xx_private *bcm)
+{
+	switch (bcm43xx_current_phy(bcm)->type) {
+	case BCM43xx_PHYTYPE_A:
+	case BCM43xx_PHYTYPE_G:
+		bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_6MB, 1);
+		bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_12MB, 1);
+		bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_18MB, 1);
+		bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_24MB, 1);
+		bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_36MB, 1);
+		bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_48MB, 1);
+		bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_54MB, 1);
+	case BCM43xx_PHYTYPE_B:
+		bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_1MB, 0);
+		bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_2MB, 0);
+		bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_5MB, 0);
+		bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_11MB, 0);
+		break;
+	default:
+		assert(0);
+	}
+}
+
+static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm)
+{
+	bcm43xx_chip_cleanup(bcm);
+	bcm43xx_pio_free(bcm);
+	bcm43xx_dma_free(bcm);
+
+	bcm->current_core->initialized = 0;
+}
+
+/* http://bcm-specs.sipsolutions.net/80211Init */
+static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u32 ucodeflags;
+	int err;
+	u32 sbimconfiglow;
+	u8 limit;
+
+	if (bcm->chip_rev < 5) {
+		sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
+		sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
+		sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
+		if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
+			sbimconfiglow |= 0x32;
+		else if (bcm->bustype == BCM43xx_BUSTYPE_SB)
+			sbimconfiglow |= 0x53;
+		else
+			assert(0);
+		bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
+	}
+
+	bcm43xx_phy_calibrate(bcm);
+	err = bcm43xx_chip_init(bcm);
+	if (err)
+		goto out;
+
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0016, bcm->current_core->rev);
+	ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, BCM43xx_UCODEFLAGS_OFFSET);
+
+	if (0 /*FIXME: which condition has to be used here? */)
+		ucodeflags |= 0x00000010;
+
+	/* HW decryption needs to be set now */
+	ucodeflags |= 0x40000000;
+	
+	if (phy->type == BCM43xx_PHYTYPE_G) {
+		ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
+		if (phy->rev == 1)
+			ucodeflags |= BCM43xx_UCODEFLAG_UNKGPHY;
+		if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
+			ucodeflags |= BCM43xx_UCODEFLAG_UNKPACTRL;
+	} else if (phy->type == BCM43xx_PHYTYPE_B) {
+		ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
+		if (phy->rev >= 2 && radio->version == 0x2050)
+			ucodeflags &= ~BCM43xx_UCODEFLAG_UNKGPHY;
+	}
+
+	if (ucodeflags != bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+					     BCM43xx_UCODEFLAGS_OFFSET)) {
+		bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+				    BCM43xx_UCODEFLAGS_OFFSET, ucodeflags);
+	}
+
+	/* Short/Long Retry Limit.
+	 * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing
+	 * the chip-internal counter.
+	 */
+	limit = limit_value(modparam_short_retry, 0, 0xF);
+	bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0006, limit);
+	limit = limit_value(modparam_long_retry, 0, 0xF);
+	bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0007, limit);
+
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0044, 3);
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0046, 2);
+
+	bcm43xx_rate_memory_init(bcm);
+
+	/* Minimum Contention Window */
+	if (phy->type == BCM43xx_PHYTYPE_B)
+		bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000001f);
+	else
+		bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000000f);
+	/* Maximum Contention Window */
+	bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
+
+	bcm43xx_gen_bssid(bcm);
+	bcm43xx_write_mac_bssid_templates(bcm);
+
+	if (bcm->current_core->rev >= 5)
+		bcm43xx_write16(bcm, 0x043C, 0x000C);
+
+	if (bcm43xx_using_pio(bcm))
+		err = bcm43xx_pio_init(bcm);
+	else
+		err = bcm43xx_dma_init(bcm);
+	if (err)
+		goto err_chip_cleanup;
+	bcm43xx_write16(bcm, 0x0612, 0x0050);
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050);
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4);
+
+	bcm43xx_mac_enable(bcm);
+	bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
+
+	bcm->current_core->initialized = 1;
+out:
+	return err;
+
+err_chip_cleanup:
+	bcm43xx_chip_cleanup(bcm);
+	goto out;
+}
+
+static int bcm43xx_chipset_attach(struct bcm43xx_private *bcm)
+{
+	int err;
+	u16 pci_status;
+
+	err = bcm43xx_pctl_set_crystal(bcm, 1);
+	if (err)
+		goto out;
+	bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
+	bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
+
+out:
+	return err;
+}
+
+static void bcm43xx_chipset_detach(struct bcm43xx_private *bcm)
+{
+	bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
+	bcm43xx_pctl_set_crystal(bcm, 0);
+}
+
+static void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm,
+					    u32 address,
+					    u32 data)
+{
+	bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_ADDR, address);
+	bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_DATA, data);
+}
+
+static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm)
+{
+	int err;
+	struct bcm43xx_coreinfo *old_core;
+
+	old_core = bcm->current_core;
+	err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+	if (err)
+		goto out;
+
+	bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
+
+	bcm43xx_switch_core(bcm, old_core);
+	assert(err == 0);
+out:
+	return err;
+}
+
+/* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable.
+ * To enable core 0, pass a core_mask of 1<<0
+ */
+static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm,
+						  u32 core_mask)
+{
+	u32 backplane_flag_nr;
+	u32 value;
+	struct bcm43xx_coreinfo *old_core;
+	int err = 0;
+
+	value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTPSFLAG);
+	backplane_flag_nr = value & BCM43xx_BACKPLANE_FLAG_NR_MASK;
+
+	old_core = bcm->current_core;
+	err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+	if (err)
+		goto out;
+
+	if (bcm->core_pci.rev < 6) {
+		value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
+		value |= (1 << backplane_flag_nr);
+		bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value);
+	} else {
+		err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ICR, &value);
+		if (err) {
+			printk(KERN_ERR PFX "Error: ICR setup failure!\n");
+			goto out_switch_back;
+		}
+		value |= core_mask << 8;
+		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ICR, value);
+		if (err) {
+			printk(KERN_ERR PFX "Error: ICR setup failure!\n");
+			goto out_switch_back;
+		}
+	}
+
+	value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
+	value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
+	bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
+
+	if (bcm->core_pci.rev < 5) {
+		value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
+		value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
+			 & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
+		value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
+			 & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
+		bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
+		err = bcm43xx_pcicore_commit_settings(bcm);
+		assert(err == 0);
+	}
+
+out_switch_back:
+	err = bcm43xx_switch_core(bcm, old_core);
+out:
+	return err;
+}
+
+static void bcm43xx_softmac_init(struct bcm43xx_private *bcm)
+{
+	ieee80211softmac_start(bcm->net_dev);
+}
+
+static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
+	if (phy->type != BCM43xx_PHYTYPE_G || phy->rev < 2)
+		return;
+
+	bcm43xx_mac_suspend(bcm);
+	bcm43xx_phy_lo_g_measure(bcm);
+	bcm43xx_mac_enable(bcm);
+}
+
+static void bcm43xx_periodic_every60sec(struct bcm43xx_private *bcm)
+{
+	bcm43xx_phy_lo_mark_all_unused(bcm);
+	if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+		bcm43xx_mac_suspend(bcm);
+		bcm43xx_calc_nrssi_slope(bcm);
+		bcm43xx_mac_enable(bcm);
+	}
+}
+
+static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm)
+{
+	/* Update device statistics. */
+	bcm43xx_calculate_link_quality(bcm);
+}
+
+static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+
+	if (phy->type == BCM43xx_PHYTYPE_G) {
+		//TODO: update_aci_moving_average
+		if (radio->aci_enable && radio->aci_wlan_automatic) {
+			bcm43xx_mac_suspend(bcm);
+			if (!radio->aci_enable && 1 /*TODO: not scanning? */) {
+				if (0 /*TODO: bunch of conditions*/) {
+					bcm43xx_radio_set_interference_mitigation(bcm,
+										  BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
+				}
+			} else if (1/*TODO*/) {
+				/*
+				if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) {
+					bcm43xx_radio_set_interference_mitigation(bcm,
+										  BCM43xx_RADIO_INTERFMODE_NONE);
+				}
+				*/
+			}
+			bcm43xx_mac_enable(bcm);
+		} else if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN &&
+			   phy->rev == 1) {
+			//TODO: implement rev1 workaround
+		}
+	}
+	bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning?
+	//TODO for APHY (temperature?)
+}
+
+static void bcm43xx_periodic_task_handler(unsigned long d)
+{
+	struct bcm43xx_private *bcm = (struct bcm43xx_private *)d;
+	unsigned long flags;
+	unsigned int state;
+
+	bcm43xx_lock_mmio(bcm, flags);
+
+	assert(bcm->initialized);
+	state = bcm->periodic_state;
+	if (state % 8 == 0)
+		bcm43xx_periodic_every120sec(bcm);
+	if (state % 4 == 0)
+		bcm43xx_periodic_every60sec(bcm);
+	if (state % 2 == 0)
+		bcm43xx_periodic_every30sec(bcm);
+	bcm43xx_periodic_every15sec(bcm);
+	bcm->periodic_state = state + 1;
+
+	mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15));
+
+	bcm43xx_unlock_mmio(bcm, flags);
+}
+
+static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
+{
+	del_timer_sync(&bcm->periodic_tasks);
+}
+
+static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
+{
+	struct timer_list *timer = &(bcm->periodic_tasks);
+
+	assert(bcm->initialized);
+	setup_timer(timer,
+		    bcm43xx_periodic_task_handler,
+		    (unsigned long)bcm);
+	timer->expires = jiffies;
+	add_timer(timer);
+}
+
+static void bcm43xx_security_init(struct bcm43xx_private *bcm)
+{
+	bcm->security_offset = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+						  0x0056) * 2;
+	bcm43xx_clear_keys(bcm);
+}
+
+/* This is the opposite of bcm43xx_init_board() */
+static void bcm43xx_free_board(struct bcm43xx_private *bcm)
+{
+	int i, err;
+	unsigned long flags;
+
+	bcm43xx_sysfs_unregister(bcm);
+
+	bcm43xx_periodic_tasks_delete(bcm);
+
+	bcm43xx_lock(bcm, flags);
+	bcm->initialized = 0;
+	bcm->shutting_down = 1;
+	bcm43xx_unlock(bcm, flags);
+
+	for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+		if (!bcm->core_80211[i].available)
+			continue;
+		if (!bcm->core_80211[i].initialized)
+			continue;
+
+		err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
+		assert(err == 0);
+		bcm43xx_wireless_core_cleanup(bcm);
+	}
+
+	bcm43xx_pctl_set_crystal(bcm, 0);
+
+	bcm43xx_lock(bcm, flags);
+	bcm->shutting_down = 0;
+	bcm43xx_unlock(bcm, flags);
+}
+
+static int bcm43xx_init_board(struct bcm43xx_private *bcm)
+{
+	int i, err;
+	int connect_phy;
+	unsigned long flags;
+
+	might_sleep();
+
+	bcm43xx_lock(bcm, flags);
+	bcm->initialized = 0;
+	bcm->shutting_down = 0;
+	bcm43xx_unlock(bcm, flags);
+
+	err = bcm43xx_pctl_set_crystal(bcm, 1);
+	if (err)
+		goto out;
+	err = bcm43xx_pctl_init(bcm);
+	if (err)
+		goto err_crystal_off;
+	err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST);
+	if (err)
+		goto err_crystal_off;
+
+	tasklet_enable(&bcm->isr_tasklet);
+	for (i = 0; i < bcm->nr_80211_available; i++) {
+		err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
+		assert(err != -ENODEV);
+		if (err)
+			goto err_80211_unwind;
+
+		/* Enable the selected wireless core.
+		 * Connect PHY only on the first core.
+		 */
+		if (!bcm43xx_core_enabled(bcm)) {
+			if (bcm->nr_80211_available == 1) {
+				connect_phy = bcm43xx_current_phy(bcm)->connected;
+			} else {
+				if (i == 0)
+					connect_phy = 1;
+				else
+					connect_phy = 0;
+			}
+			bcm43xx_wireless_core_reset(bcm, connect_phy);
+		}
+
+		if (i != 0)
+			bcm43xx_wireless_core_mark_inactive(bcm, &bcm->core_80211[0]);
+
+		err = bcm43xx_wireless_core_init(bcm);
+		if (err)
+			goto err_80211_unwind;
+
+		if (i != 0) {
+			bcm43xx_mac_suspend(bcm);
+			bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+			bcm43xx_radio_turn_off(bcm);
+		}
+	}
+	bcm->active_80211_core = &bcm->core_80211[0];
+	if (bcm->nr_80211_available >= 2) {
+		bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
+		bcm43xx_mac_enable(bcm);
+	}
+	bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
+	bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
+	dprintk(KERN_INFO PFX "80211 cores initialized\n");
+	bcm43xx_security_init(bcm);
+	bcm43xx_softmac_init(bcm);
+
+	bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC);
+
+	if (bcm43xx_current_radio(bcm)->initial_channel != 0xFF) {
+		bcm43xx_mac_suspend(bcm);
+		bcm43xx_radio_selectchannel(bcm, bcm43xx_current_radio(bcm)->initial_channel, 0);
+		bcm43xx_mac_enable(bcm);
+	}
+
+	/* Initialization of the board is done. Flag it as such. */
+	bcm43xx_lock(bcm, flags);
+	bcm->initialized = 1;
+	bcm43xx_unlock(bcm, flags);
+
+	bcm43xx_periodic_tasks_setup(bcm);
+	bcm43xx_sysfs_register(bcm);
+	//FIXME: check for bcm43xx_sysfs_register failure. This function is a bit messy regarding unwinding, though...
+
+	assert(err == 0);
+out:
+	return err;
+
+err_80211_unwind:
+	tasklet_disable(&bcm->isr_tasklet);
+	/* unwind all 80211 initialization */
+	for (i = 0; i < bcm->nr_80211_available; i++) {
+		if (!bcm->core_80211[i].initialized)
+			continue;
+		bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+		bcm43xx_wireless_core_cleanup(bcm);
+	}
+err_crystal_off:
+	bcm43xx_pctl_set_crystal(bcm, 0);
+	goto out;
+}
+
+static void bcm43xx_detach_board(struct bcm43xx_private *bcm)
+{
+	struct pci_dev *pci_dev = bcm->pci_dev;
+	int i;
+
+	bcm43xx_chipset_detach(bcm);
+	/* Do _not_ access the chip, after it is detached. */
+	iounmap(bcm->mmio_addr);
+	
+	pci_release_regions(pci_dev);
+	pci_disable_device(pci_dev);
+
+	/* Free allocated structures/fields */
+	for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+		kfree(bcm->core_80211_ext[i].phy._lo_pairs);
+		if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
+			kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
+	}
+}	
+
+static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	u16 value;
+	u8 phy_version;
+	u8 phy_type;
+	u8 phy_rev;
+	int phy_rev_ok = 1;
+	void *p;
+
+	value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER);
+
+	phy_version = (value & 0xF000) >> 12;
+	phy_type = (value & 0x0F00) >> 8;
+	phy_rev = (value & 0x000F);
+
+	dprintk(KERN_INFO PFX "Detected PHY: Version: %x, Type %x, Revision %x\n",
+		phy_version, phy_type, phy_rev);
+
+	switch (phy_type) {
+	case BCM43xx_PHYTYPE_A:
+		if (phy_rev >= 4)
+			phy_rev_ok = 0;
+		/*FIXME: We need to switch the ieee->modulation, etc.. flags,
+		 *       if we switch 80211 cores after init is done.
+		 *       As we do not implement on the fly switching between
+		 *       wireless cores, I will leave this as a future task.
+		 */
+		bcm->ieee->modulation = IEEE80211_OFDM_MODULATION;
+		bcm->ieee->mode = IEEE_A;
+		bcm->ieee->freq_band = IEEE80211_52GHZ_BAND |
+				       IEEE80211_24GHZ_BAND;
+		break;
+	case BCM43xx_PHYTYPE_B:
+		if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6 && phy_rev != 7)
+			phy_rev_ok = 0;
+		bcm->ieee->modulation = IEEE80211_CCK_MODULATION;
+		bcm->ieee->mode = IEEE_B;
+		bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
+		break;
+	case BCM43xx_PHYTYPE_G:
+		if (phy_rev > 7)
+			phy_rev_ok = 0;
+		bcm->ieee->modulation = IEEE80211_OFDM_MODULATION |
+					IEEE80211_CCK_MODULATION;
+		bcm->ieee->mode = IEEE_G;
+		bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
+		break;
+	default:
+		printk(KERN_ERR PFX "Error: Unknown PHY Type %x\n",
+		       phy_type);
+		return -ENODEV;
+	};
+	if (!phy_rev_ok) {
+		printk(KERN_WARNING PFX "Invalid PHY Revision %x\n",
+		       phy_rev);
+	}
+
+	phy->version = phy_version;
+	phy->type = phy_type;
+	phy->rev = phy_rev;
+	if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) {
+		p = kzalloc(sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT,
+			    GFP_KERNEL);
+		if (!p)
+			return -ENOMEM;
+		phy->_lo_pairs = p;
+	}
+
+	return 0;
+}
+
+static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
+{
+	struct pci_dev *pci_dev = bcm->pci_dev;
+	struct net_device *net_dev = bcm->net_dev;
+	int err;
+	int i;
+	unsigned long mmio_start, mmio_flags, mmio_len;
+	u32 coremask;
+
+	err = pci_enable_device(pci_dev);
+	if (err) {
+		printk(KERN_ERR PFX "unable to wake up pci device (%i)\n", err);
+		goto out;
+	}
+	mmio_start = pci_resource_start(pci_dev, 0);
+	mmio_flags = pci_resource_flags(pci_dev, 0);
+	mmio_len = pci_resource_len(pci_dev, 0);
+	if (!(mmio_flags & IORESOURCE_MEM)) {
+		printk(KERN_ERR PFX
+		       "%s, region #0 not an MMIO resource, aborting\n",
+		       pci_name(pci_dev));
+		err = -ENODEV;
+		goto err_pci_disable;
+	}
+	err = pci_request_regions(pci_dev, KBUILD_MODNAME);
+	if (err) {
+		printk(KERN_ERR PFX
+		       "could not access PCI resources (%i)\n", err);
+		goto err_pci_disable;
+	}
+	/* enable PCI bus-mastering */
+	pci_set_master(pci_dev);
+	bcm->mmio_addr = ioremap(mmio_start, mmio_len);
+	if (!bcm->mmio_addr) {
+		printk(KERN_ERR PFX "%s: cannot remap MMIO, aborting\n",
+		       pci_name(pci_dev));
+		err = -EIO;
+		goto err_pci_release;
+	}
+	bcm->mmio_len = mmio_len;
+	net_dev->base_addr = (unsigned long)bcm->mmio_addr;
+
+	bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
+	                          &bcm->board_vendor);
+	bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
+	                          &bcm->board_type);
+	bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
+	                          &bcm->board_revision);
+
+	err = bcm43xx_chipset_attach(bcm);
+	if (err)
+		goto err_iounmap;
+	err = bcm43xx_pctl_init(bcm);
+	if (err)
+		goto err_chipset_detach;
+	err = bcm43xx_probe_cores(bcm);
+	if (err)
+		goto err_chipset_detach;
+	
+	/* Attach all IO cores to the backplane. */
+	coremask = 0;
+	for (i = 0; i < bcm->nr_80211_available; i++)
+		coremask |= (1 << bcm->core_80211[i].index);
+	//FIXME: Also attach some non80211 cores?
+	err = bcm43xx_setup_backplane_pci_connection(bcm, coremask);
+	if (err) {
+		printk(KERN_ERR PFX "Backplane->PCI connection failed!\n");
+		goto err_chipset_detach;
+	}
+
+	err = bcm43xx_sprom_extract(bcm);
+	if (err)
+		goto err_chipset_detach;
+	err = bcm43xx_leds_init(bcm);
+	if (err)
+		goto err_chipset_detach;
+
+	for (i = 0; i < bcm->nr_80211_available; i++) {
+		err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
+		assert(err != -ENODEV);
+		if (err)
+			goto err_80211_unwind;
+
+		/* Enable the selected wireless core.
+		 * Connect PHY only on the first core.
+		 */
+		bcm43xx_wireless_core_reset(bcm, (i == 0));
+
+		err = bcm43xx_read_phyinfo(bcm);
+		if (err && (i == 0))
+			goto err_80211_unwind;
+
+		err = bcm43xx_read_radioinfo(bcm);
+		if (err && (i == 0))
+			goto err_80211_unwind;
+
+		err = bcm43xx_validate_chip(bcm);
+		if (err && (i == 0))
+			goto err_80211_unwind;
+
+		bcm43xx_radio_turn_off(bcm);
+		err = bcm43xx_phy_init_tssi2dbm_table(bcm);
+		if (err)
+			goto err_80211_unwind;
+		bcm43xx_wireless_core_disable(bcm);
+	}
+	bcm43xx_pctl_set_crystal(bcm, 0);
+
+	/* Set the MAC address in the networking subsystem */
+	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
+		memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6);
+	else
+		memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6);
+
+	bcm43xx_geo_init(bcm);
+
+	snprintf(bcm->nick, IW_ESSID_MAX_SIZE,
+		 "Broadcom %04X", bcm->chip_id);
+
+	assert(err == 0);
+out:
+	return err;
+
+err_80211_unwind:
+	for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+		kfree(bcm->core_80211_ext[i].phy._lo_pairs);
+		if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
+			kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
+	}
+err_chipset_detach:
+	bcm43xx_chipset_detach(bcm);
+err_iounmap:
+	iounmap(bcm->mmio_addr);
+err_pci_release:
+	pci_release_regions(pci_dev);
+err_pci_disable:
+	pci_disable_device(pci_dev);
+	goto out;
+}
+
+/* Do the Hardware IO operations to send the txb */
+static inline int bcm43xx_tx(struct bcm43xx_private *bcm,
+			     struct ieee80211_txb *txb)
+{
+	int err = -ENODEV;
+
+	if (bcm43xx_using_pio(bcm))
+		err = bcm43xx_pio_tx(bcm, txb);
+	else
+		err = bcm43xx_dma_tx(bcm, txb);
+
+	return err;
+}
+
+static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
+				       u8 channel)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	struct bcm43xx_radioinfo *radio;
+	unsigned long flags;
+
+	bcm43xx_lock_mmio(bcm, flags);
+	if (bcm->initialized) {
+		bcm43xx_mac_suspend(bcm);
+		bcm43xx_radio_selectchannel(bcm, channel, 0);
+		bcm43xx_mac_enable(bcm);
+	} else {
+		radio = bcm43xx_current_radio(bcm);
+		radio->initial_channel = channel;
+	}
+	bcm43xx_unlock_mmio(bcm, flags);
+}
+
+/* set_security() callback in struct ieee80211_device */
+static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
+					   struct ieee80211_security *sec)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	struct ieee80211_security *secinfo = &bcm->ieee->sec;
+	unsigned long flags;
+	int keyidx;
+	
+	dprintk(KERN_INFO PFX "set security called\n");
+
+	bcm43xx_lock_mmio(bcm, flags);
+
+	for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
+		if (sec->flags & (1<<keyidx)) {
+			secinfo->encode_alg[keyidx] = sec->encode_alg[keyidx];
+			secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx];
+			memcpy(secinfo->keys[keyidx], sec->keys[keyidx], SCM_KEY_LEN);
+		}
+	
+	if (sec->flags & SEC_ACTIVE_KEY) {
+		secinfo->active_key = sec->active_key;
+		dprintk(KERN_INFO PFX "   .active_key = %d\n", sec->active_key);
+	}
+	if (sec->flags & SEC_UNICAST_GROUP) {
+		secinfo->unicast_uses_group = sec->unicast_uses_group;
+		dprintk(KERN_INFO PFX "   .unicast_uses_group = %d\n", sec->unicast_uses_group);
+	}
+	if (sec->flags & SEC_LEVEL) {
+		secinfo->level = sec->level;
+		dprintk(KERN_INFO PFX "   .level = %d\n", sec->level);
+	}
+	if (sec->flags & SEC_ENABLED) {
+		secinfo->enabled = sec->enabled;
+		dprintk(KERN_INFO PFX "   .enabled = %d\n", sec->enabled);
+	}
+	if (sec->flags & SEC_ENCRYPT) {
+		secinfo->encrypt = sec->encrypt;
+		dprintk(KERN_INFO PFX "   .encrypt = %d\n", sec->encrypt);
+	}
+	if (bcm->initialized && !bcm->ieee->host_encrypt) {
+		if (secinfo->enabled) {
+			/* upload WEP keys to hardware */
+			char null_address[6] = { 0 };
+			u8 algorithm = 0;
+			for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) {
+				if (!(sec->flags & (1<<keyidx)))
+					continue;
+				switch (sec->encode_alg[keyidx]) {
+					case SEC_ALG_NONE: algorithm = BCM43xx_SEC_ALGO_NONE; break;
+					case SEC_ALG_WEP:
+						algorithm = BCM43xx_SEC_ALGO_WEP;
+						if (secinfo->key_sizes[keyidx] == 13)
+							algorithm = BCM43xx_SEC_ALGO_WEP104;
+						break;
+					case SEC_ALG_TKIP:
+						FIXME();
+						algorithm = BCM43xx_SEC_ALGO_TKIP;
+						break;
+					case SEC_ALG_CCMP:
+						FIXME();
+						algorithm = BCM43xx_SEC_ALGO_AES;
+						break;
+					default:
+						assert(0);
+						break;
+				}
+				bcm43xx_key_write(bcm, keyidx, algorithm, sec->keys[keyidx], secinfo->key_sizes[keyidx], &null_address[0]);
+				bcm->key[keyidx].enabled = 1;
+				bcm->key[keyidx].algorithm = algorithm;
+			}
+		} else
+				bcm43xx_clear_keys(bcm);
+	}
+	bcm43xx_unlock_mmio(bcm, flags);
+}
+
+/* hard_start_xmit() callback in struct ieee80211_device */
+static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb,
+					     struct net_device *net_dev,
+					     int pri)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	int err = -ENODEV;
+	unsigned long flags;
+
+	bcm43xx_lock_mmio(bcm, flags);
+	if (likely(bcm->initialized))
+		err = bcm43xx_tx(bcm, txb);
+	bcm43xx_unlock_mmio(bcm, flags);
+
+	return err;
+}
+
+static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_dev)
+{
+	return &(bcm43xx_priv(net_dev)->ieee->stats);
+}
+
+static void bcm43xx_net_tx_timeout(struct net_device *net_dev)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+
+	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_controller_restart(bcm, "TX timeout");
+	bcm43xx_unlock_mmio(bcm, flags);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void bcm43xx_net_poll_controller(struct net_device *net_dev)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+
+	local_irq_save(flags);
+	bcm43xx_interrupt_handler(bcm->irq, bcm, NULL);
+	local_irq_restore(flags);
+}
+#endif /* CONFIG_NET_POLL_CONTROLLER */
+
+static int bcm43xx_net_open(struct net_device *net_dev)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+
+	return bcm43xx_init_board(bcm);
+}
+
+static int bcm43xx_net_stop(struct net_device *net_dev)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+
+	ieee80211softmac_stop(net_dev);
+	bcm43xx_disable_interrupts_sync(bcm, NULL);
+	bcm43xx_free_board(bcm);
+
+	return 0;
+}
+
+static int bcm43xx_init_private(struct bcm43xx_private *bcm,
+				struct net_device *net_dev,
+				struct pci_dev *pci_dev)
+{
+	int err;
+
+	bcm->ieee = netdev_priv(net_dev);
+	bcm->softmac = ieee80211_priv(net_dev);
+	bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
+
+	bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
+	bcm->pci_dev = pci_dev;
+	bcm->net_dev = net_dev;
+	bcm->bad_frames_preempt = modparam_bad_frames_preempt;
+	spin_lock_init(&bcm->_lock);
+	tasklet_init(&bcm->isr_tasklet,
+		     (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
+		     (unsigned long)bcm);
+	tasklet_disable_nosync(&bcm->isr_tasklet);
+	if (modparam_pio) {
+		bcm->__using_pio = 1;
+	} else {
+		err = pci_set_dma_mask(pci_dev, DMA_30BIT_MASK);
+		err |= pci_set_consistent_dma_mask(pci_dev, DMA_30BIT_MASK);
+		if (err) {
+#ifdef CONFIG_BCM43XX_PIO
+			printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n");
+			bcm->__using_pio = 1;
+#else
+			printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
+					    "Recompile the driver with PIO support, please.\n");
+			return -ENODEV;
+#endif /* CONFIG_BCM43XX_PIO */
+		}
+	}
+	bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD;
+
+	/* default to sw encryption for now */
+	bcm->ieee->host_build_iv = 0;
+	bcm->ieee->host_encrypt = 1;
+	bcm->ieee->host_decrypt = 1;
+	
+	bcm->ieee->iw_mode = BCM43xx_INITIAL_IWMODE;
+	bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr);
+	bcm->ieee->set_security = bcm43xx_ieee80211_set_security;
+	bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit;
+
+	return 0;
+}
+
+static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
+				      const struct pci_device_id *ent)
+{
+	struct net_device *net_dev;
+	struct bcm43xx_private *bcm;
+	int err;
+
+#ifdef CONFIG_BCM947XX
+	if ((pdev->bus->number == 0) && (pdev->device != 0x0800))
+		return -ENODEV;
+#endif
+
+#ifdef DEBUG_SINGLE_DEVICE_ONLY
+	if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY))
+		return -ENODEV;
+#endif
+
+	net_dev = alloc_ieee80211softmac(sizeof(*bcm));
+	if (!net_dev) {
+		printk(KERN_ERR PFX
+		       "could not allocate ieee80211 device %s\n",
+		       pci_name(pdev));
+		err = -ENOMEM;
+		goto out;
+	}
+	/* initialize the net_device struct */
+	SET_MODULE_OWNER(net_dev);
+	SET_NETDEV_DEV(net_dev, &pdev->dev);
+
+	net_dev->open = bcm43xx_net_open;
+	net_dev->stop = bcm43xx_net_stop;
+	net_dev->get_stats = bcm43xx_net_get_stats;
+	net_dev->tx_timeout = bcm43xx_net_tx_timeout;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	net_dev->poll_controller = bcm43xx_net_poll_controller;
+#endif
+	net_dev->wireless_handlers = &bcm43xx_wx_handlers_def;
+	net_dev->irq = pdev->irq;
+	SET_ETHTOOL_OPS(net_dev, &bcm43xx_ethtool_ops);
+
+	/* initialize the bcm43xx_private struct */
+	bcm = bcm43xx_priv(net_dev);
+	memset(bcm, 0, sizeof(*bcm));
+	err = bcm43xx_init_private(bcm, net_dev, pdev);
+	if (err)
+		goto err_free_netdev;
+
+	pci_set_drvdata(pdev, net_dev);
+
+	err = bcm43xx_attach_board(bcm);
+	if (err)
+		goto err_free_netdev;
+
+	err = register_netdev(net_dev);
+	if (err) {
+		printk(KERN_ERR PFX "Cannot register net device, "
+		       "aborting.\n");
+		err = -ENOMEM;
+		goto err_detach_board;
+	}
+
+	bcm43xx_debugfs_add_device(bcm);
+
+	assert(err == 0);
+out:
+	return err;
+
+err_detach_board:
+	bcm43xx_detach_board(bcm);
+err_free_netdev:
+	free_ieee80211softmac(net_dev);
+	goto out;
+}
+
+static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
+{
+	struct net_device *net_dev = pci_get_drvdata(pdev);
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+
+	bcm43xx_debugfs_remove_device(bcm);
+	unregister_netdev(net_dev);
+	bcm43xx_detach_board(bcm);
+	assert(bcm->ucode == NULL);
+	free_ieee80211softmac(net_dev);
+}
+
+/* Hard-reset the chip. Do not call this directly.
+ * Use bcm43xx_controller_restart()
+ */
+static void bcm43xx_chip_reset(void *_bcm)
+{
+	struct bcm43xx_private *bcm = _bcm;
+	struct net_device *net_dev = bcm->net_dev;
+	struct pci_dev *pci_dev = bcm->pci_dev;
+	int err;
+	int was_initialized = bcm->initialized;
+
+	netif_stop_queue(bcm->net_dev);
+	tasklet_disable(&bcm->isr_tasklet);
+
+	bcm->firmware_norelease = 1;
+	if (was_initialized)
+		bcm43xx_free_board(bcm);
+	bcm->firmware_norelease = 0;
+	bcm43xx_detach_board(bcm);
+	err = bcm43xx_init_private(bcm, net_dev, pci_dev);
+	if (err)
+		goto failure;
+	err = bcm43xx_attach_board(bcm);
+	if (err)
+		goto failure;
+	if (was_initialized) {
+		err = bcm43xx_init_board(bcm);
+		if (err)
+			goto failure;
+	}
+	netif_wake_queue(bcm->net_dev);
+	printk(KERN_INFO PFX "Controller restarted\n");
+
+	return;
+failure:
+	printk(KERN_ERR PFX "Controller restart failed\n");
+}
+
+/* Hard-reset the chip.
+ * This can be called from interrupt or process context.
+ * Make sure to _not_ re-enable device interrupts after this has been called.
+*/
+void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
+{
+	bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+	bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
+	printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
+	INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm);
+	schedule_work(&bcm->restart_work);
+}
+
+#ifdef CONFIG_PM
+
+static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *net_dev = pci_get_drvdata(pdev);
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	int try_to_shutdown = 0, err;
+
+	dprintk(KERN_INFO PFX "Suspending...\n");
+
+	bcm43xx_lock(bcm, flags);
+	bcm->was_initialized = bcm->initialized;
+	if (bcm->initialized)
+		try_to_shutdown = 1;
+	bcm43xx_unlock(bcm, flags);
+
+	netif_device_detach(net_dev);
+	if (try_to_shutdown) {
+		ieee80211softmac_stop(net_dev);
+		err = bcm43xx_disable_interrupts_sync(bcm, &bcm->irq_savedstate);
+		if (unlikely(err)) {
+			dprintk(KERN_ERR PFX "Suspend failed.\n");
+			return -EAGAIN;
+		}
+		bcm->firmware_norelease = 1;
+		bcm43xx_free_board(bcm);
+		bcm->firmware_norelease = 0;
+	}
+	bcm43xx_chipset_detach(bcm);
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	dprintk(KERN_INFO PFX "Device suspended.\n");
+
+	return 0;
+}
+
+static int bcm43xx_resume(struct pci_dev *pdev)
+{
+	struct net_device *net_dev = pci_get_drvdata(pdev);
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	int err = 0;
+
+	dprintk(KERN_INFO PFX "Resuming...\n");
+
+	pci_set_power_state(pdev, 0);
+	pci_enable_device(pdev);
+	pci_restore_state(pdev);
+
+	bcm43xx_chipset_attach(bcm);
+	if (bcm->was_initialized) {
+		bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
+		err = bcm43xx_init_board(bcm);
+	}
+	if (err) {
+		printk(KERN_ERR PFX "Resume failed!\n");
+		return err;
+	}
+
+	netif_device_attach(net_dev);
+	
+	/*FIXME: This should be handled by softmac instead. */
+	schedule_work(&bcm->softmac->associnfo.work);
+
+	dprintk(KERN_INFO PFX "Device resumed.\n");
+
+	return 0;
+}
+
+#endif				/* CONFIG_PM */
+
+static struct pci_driver bcm43xx_pci_driver = {
+	.name = KBUILD_MODNAME,
+	.id_table = bcm43xx_pci_tbl,
+	.probe = bcm43xx_init_one,
+	.remove = __devexit_p(bcm43xx_remove_one),
+#ifdef CONFIG_PM
+	.suspend = bcm43xx_suspend,
+	.resume = bcm43xx_resume,
+#endif				/* CONFIG_PM */
+};
+
+static int __init bcm43xx_init(void)
+{
+	printk(KERN_INFO KBUILD_MODNAME " driver\n");
+	bcm43xx_debugfs_init();
+	return pci_register_driver(&bcm43xx_pci_driver);
+}
+
+static void __exit bcm43xx_exit(void)
+{
+	pci_unregister_driver(&bcm43xx_pci_driver);
+	bcm43xx_debugfs_exit();
+}
+
+module_init(bcm43xx_init)
+module_exit(bcm43xx_exit)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
new file mode 100644
index 0000000..eca79a3
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
@@ -0,0 +1,168 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+                     Stefano Brivio <st3@riseup.net>
+                     Michael Buesch <mbuesch@freenet.de>
+                     Danny van Dyk <kugelfang@gentoo.org>
+                     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef BCM43xx_MAIN_H_
+#define BCM43xx_MAIN_H_
+
+#include "bcm43xx.h"
+
+#ifdef CONFIG_BCM947XX
+#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
+
+static inline void e_aton(char *str, char *dest)
+{
+	int i = 0;
+	u16 *d = (u16 *) dest;
+
+	for (;;) {
+		dest[i++] = (char) simple_strtoul(str, NULL, 16);
+		str += 2;
+		if (!*str++ || i == 6)
+			break;
+	}
+	for (i = 0; i < 3; i++)
+		d[i] = cpu_to_be16(d[i]);
+}
+#endif
+
+#define P4D_BYT3S(magic, nr_bytes)	u8 __p4dding##magic[nr_bytes]
+#define P4D_BYTES(line, nr_bytes)	P4D_BYT3S(line, nr_bytes)
+/* Magic helper macro to pad structures. Ignore those above. It's magic. */
+#define PAD_BYTES(nr_bytes)		P4D_BYTES( __LINE__ , (nr_bytes))
+
+
+/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
+static inline
+u8 bcm43xx_freq_to_channel_a(int freq)
+{
+	return ((freq - 5000) / 5);
+}
+static inline
+u8 bcm43xx_freq_to_channel_bg(int freq)
+{
+	u8 channel;
+
+	if (freq == 2484)
+		channel = 14;
+	else
+		channel = (freq - 2407) / 5;
+
+	return channel;
+}
+static inline
+u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm,
+			   int freq)
+{
+	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
+		return bcm43xx_freq_to_channel_a(freq);
+	return bcm43xx_freq_to_channel_bg(freq);
+}
+
+/* Lightweight function to convert a channel number to a frequency (in Mhz). */
+static inline
+int bcm43xx_channel_to_freq_a(u8 channel)
+{
+	return (5000 + (5 * channel));
+}
+static inline
+int bcm43xx_channel_to_freq_bg(u8 channel)
+{
+	int freq;
+
+	if (channel == 14)
+		freq = 2484;
+	else
+		freq = 2407 + (5 * channel);
+
+	return freq;
+}
+static inline
+int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm,
+			    u8 channel)
+{
+	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
+		return bcm43xx_channel_to_freq_a(channel);
+	return bcm43xx_channel_to_freq_bg(channel);
+}
+
+/* Lightweight function to check if a channel number is valid.
+ * Note that this does _NOT_ check for geographical restrictions!
+ */
+static inline
+int bcm43xx_is_valid_channel_a(u8 channel)
+{
+	return (channel <= 200);
+}
+static inline
+int bcm43xx_is_valid_channel_bg(u8 channel)
+{
+	return (channel >= 1 && channel <= 14);
+}
+static inline
+int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm,
+			     u8 channel)
+{
+	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
+		return bcm43xx_is_valid_channel_a(channel);
+	return bcm43xx_is_valid_channel_bg(channel);
+}
+
+void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf);
+void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf);
+
+void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
+			int iw_mode);
+
+u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm,
+		       u16 routing, u16 offset);
+u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm,
+		       u16 routing, u16 offset);
+void bcm43xx_shm_write32(struct bcm43xx_private *bcm,
+			 u16 routing, u16 offset,
+			 u32 value);
+void bcm43xx_shm_write16(struct bcm43xx_private *bcm,
+			 u16 routing, u16 offset,
+			 u16 value);
+
+void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm);
+
+int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core);
+
+void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
+
+void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
+void bcm43xx_mac_enable(struct bcm43xx_private *bcm);
+
+void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason);
+
+int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom);
+int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom);
+
+#endif /* BCM43xx_MAIN_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
new file mode 100644
index 0000000..0a66f43
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -0,0 +1,2345 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+                     Stefano Brivio <st3@riseup.net>
+                     Michael Buesch <mbuesch@freenet.de>
+                     Danny van Dyk <kugelfang@gentoo.org>
+                     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+
+#include "bcm43xx.h"
+#include "bcm43xx_phy.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_radio.h"
+#include "bcm43xx_ilt.h"
+#include "bcm43xx_power.h"
+
+
+static const s8 bcm43xx_tssi2dbm_b_table[] = {
+	0x4D, 0x4C, 0x4B, 0x4A,
+	0x4A, 0x49, 0x48, 0x47,
+	0x47, 0x46, 0x45, 0x45,
+	0x44, 0x43, 0x42, 0x42,
+	0x41, 0x40, 0x3F, 0x3E,
+	0x3D, 0x3C, 0x3B, 0x3A,
+	0x39, 0x38, 0x37, 0x36,
+	0x35, 0x34, 0x32, 0x31,
+	0x30, 0x2F, 0x2D, 0x2C,
+	0x2B, 0x29, 0x28, 0x26,
+	0x25, 0x23, 0x21, 0x1F,
+	0x1D, 0x1A, 0x17, 0x14,
+	0x10, 0x0C, 0x06, 0x00,
+	  -7,   -7,   -7,   -7,
+	  -7,   -7,   -7,   -7,
+	  -7,   -7,   -7,   -7,
+};
+
+static const s8 bcm43xx_tssi2dbm_g_table[] = {
+	 77,  77,  77,  76,
+	 76,  76,  75,  75,
+	 74,  74,  73,  73,
+	 73,  72,  72,  71,
+	 71,  70,  70,  69,
+	 68,  68,  67,  67,
+	 66,  65,  65,  64,
+	 63,  63,  62,  61,
+	 60,  59,  58,  57,
+	 56,  55,  54,  53,
+	 52,  50,  49,  47,
+	 45,  43,  40,  37,
+	 33,  28,  22,  14,
+	  5,  -7, -20, -20,
+	-20, -20, -20, -20,
+	-20, -20, -20, -20,
+};
+
+static void bcm43xx_phy_initg(struct bcm43xx_private *bcm);
+
+
+void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
+	assert(irqs_disabled());
+	if (bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) == 0x00000000) {
+		phy->is_locked = 0;
+		return;
+	}
+	if (bcm->current_core->rev < 3) {
+		bcm43xx_mac_suspend(bcm);
+		spin_lock(&phy->lock);
+	} else {
+		if (bcm->ieee->iw_mode != IW_MODE_MASTER)
+			bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
+	}
+	phy->is_locked = 1;
+}
+
+void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
+	assert(irqs_disabled());
+	if (bcm->current_core->rev < 3) {
+		if (phy->is_locked) {
+			spin_unlock(&phy->lock);
+			bcm43xx_mac_enable(bcm);
+		}
+	} else {
+		if (bcm->ieee->iw_mode != IW_MODE_MASTER)
+			bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+	}
+	phy->is_locked = 0;
+}
+
+u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset)
+{
+	bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset);
+	return bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_DATA);
+}
+
+void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
+{
+	bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset);
+	mmiowb();
+	bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_DATA, val);
+}
+
+void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	unsigned long flags;
+
+	bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */
+	if (phy->calibrated)
+		return;
+	if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) {
+		/* We do not want to be preempted while calibrating
+		 * the hardware.
+		 */
+		local_irq_save(flags);
+
+		bcm43xx_wireless_core_reset(bcm, 0);
+		bcm43xx_phy_initg(bcm);
+		bcm43xx_wireless_core_reset(bcm, 1);
+
+		local_irq_restore(flags);
+	}
+	phy->calibrated = 1;
+}
+
+/* Connect the PHY 
+ * http://bcm-specs.sipsolutions.net/SetPHY
+ */
+int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	u32 flags;
+
+	if (bcm->current_core->rev < 5)
+		goto out;
+
+	flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+	if (connect) {
+		if (!(flags & 0x00010000))
+			return -ENODEV;
+		flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+		flags |= (0x800 << 18);
+		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
+	} else {
+		if (!(flags & 0x00020000))
+			return -ENODEV;
+		flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+		flags &= ~(0x800 << 18);
+		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
+	}
+out:
+	phy->connected = connect;
+	if (connect)
+		dprintk(KERN_INFO PFX "PHY connected\n");
+	else
+		dprintk(KERN_INFO PFX "PHY disconnected\n");
+
+	return 0;
+}
+
+/* intialize B PHY power control
+ * as described in http://bcm-specs.sipsolutions.net/InitPowerControl
+ */
+static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 saved_batt = 0, saved_ratt = 0, saved_txctl1 = 0;
+	int must_reset_txpower = 0;
+
+	assert(phy->type != BCM43xx_PHYTYPE_A);
+	if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
+	    (bcm->board_type == 0x0416))
+		return;
+
+	bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF);
+	bcm43xx_phy_write(bcm, 0x0028, 0x8018);
+
+	if (phy->type == BCM43xx_PHYTYPE_G) {
+		if (!phy->connected)
+			return;
+		bcm43xx_phy_write(bcm, 0x047A, 0xC111);
+	}
+	if (phy->savedpctlreg != 0xFFFF)
+		return;
+
+	if (phy->type == BCM43xx_PHYTYPE_B &&
+	    phy->rev >= 2 &&
+	    radio->version == 0x2050) {
+		bcm43xx_radio_write16(bcm, 0x0076,
+				      bcm43xx_radio_read16(bcm, 0x0076) | 0x0084);
+	} else {
+		saved_batt = radio->baseband_atten;
+		saved_ratt = radio->radio_atten;
+		saved_txctl1 = radio->txctl1;
+		if ((radio->revision >= 6) && (radio->revision <= 8)
+		    && /*FIXME: incomplete specs for 5 < revision < 9 */ 0)
+			bcm43xx_radio_set_txpower_bg(bcm, 0xB, 0x1F, 0);
+		else
+			bcm43xx_radio_set_txpower_bg(bcm, 0xB, 9, 0);
+		must_reset_txpower = 1;
+	}
+	bcm43xx_dummy_transmission(bcm);
+
+	phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_PCTL);
+
+	if (must_reset_txpower)
+		bcm43xx_radio_set_txpower_bg(bcm, saved_batt, saved_ratt, saved_txctl1);
+	else
+		bcm43xx_radio_write16(bcm, 0x0076, bcm43xx_radio_read16(bcm, 0x0076) & 0xFF7B);
+	bcm43xx_radio_clear_tssi(bcm);
+}
+
+static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	u16 offset = 0x0000;
+
+	if (phy->rev == 1)
+		offset = 0x4C00;
+
+	bcm43xx_ilt_write(bcm, offset, 0x00FE);
+	bcm43xx_ilt_write(bcm, offset + 1, 0x000D);
+	bcm43xx_ilt_write(bcm, offset + 2, 0x0013);
+	bcm43xx_ilt_write(bcm, offset + 3, 0x0019);
+
+	if (phy->rev == 1) {
+		bcm43xx_ilt_write(bcm, 0x1800, 0x2710);
+		bcm43xx_ilt_write(bcm, 0x1801, 0x9B83);
+		bcm43xx_ilt_write(bcm, 0x1802, 0x9B83);
+		bcm43xx_ilt_write(bcm, 0x1803, 0x0F8D);
+		bcm43xx_phy_write(bcm, 0x0455, 0x0004);
+	}
+
+	bcm43xx_phy_write(bcm, 0x04A5, (bcm43xx_phy_read(bcm, 0x04A5) & 0x00FF) | 0x5700);
+	bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xFF80) | 0x000F);
+	bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xC07F) | 0x2B80);
+	bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xF0FF) | 0x0300);
+
+	bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0008);
+
+	bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFF0) | 0x0008);
+	bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xF0FF) | 0x0600);
+	bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0700);
+	bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0100);
+
+	if (phy->rev == 1)
+		bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x0007);
+
+	bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xFF00) | 0x001C);
+	bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xC0FF) | 0x0200);
+	bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0xFF00) | 0x001C);
+	bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xFF00) | 0x0020);
+	bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xC0FF) | 0x0200);
+	bcm43xx_phy_write(bcm, 0x0482, (bcm43xx_phy_read(bcm, 0x0482) & 0xFF00) | 0x002E);
+	bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0x00FF) | 0x1A00);
+	bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0xFF00) | 0x0028);
+	bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0x00FF) | 0x2C00);
+
+	if (phy->rev == 1) {
+		bcm43xx_phy_write(bcm, 0x0430, 0x092B);
+		bcm43xx_phy_write(bcm, 0x041B, (bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1) | 0x0002);
+	} else {
+		bcm43xx_phy_write(bcm, 0x041B, bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1);
+		bcm43xx_phy_write(bcm, 0x041F, 0x287A);
+		bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0xFFF0) | 0x0004);
+	}
+
+	if (phy->rev > 2) {
+		bcm43xx_phy_write(bcm, 0x0422, 0x287A);
+		bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0x0FFF) | 0x3000); 
+	}
+		
+	bcm43xx_phy_write(bcm, 0x04A8, (bcm43xx_phy_read(bcm, 0x04A8) & 0x8080) | 0x7874);
+	bcm43xx_phy_write(bcm, 0x048E, 0x1C00);
+
+	if (phy->rev == 1) {
+		bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB) & 0xF0FF) | 0x0600);
+		bcm43xx_phy_write(bcm, 0x048B, 0x005E);
+		bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xFF00) | 0x001E);
+		bcm43xx_phy_write(bcm, 0x048D, 0x0002);
+	}
+
+	bcm43xx_ilt_write(bcm, offset + 0x0800, 0);
+	bcm43xx_ilt_write(bcm, offset + 0x0801, 7);
+	bcm43xx_ilt_write(bcm, offset + 0x0802, 16);
+	bcm43xx_ilt_write(bcm, offset + 0x0803, 28);
+}
+
+static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	u16 i;
+
+	assert(phy->type == BCM43xx_PHYTYPE_G);
+	if (phy->rev == 1) {
+		bcm43xx_phy_write(bcm, 0x0406, 0x4F19);
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+				  (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0xFC3F) | 0x0340);
+		bcm43xx_phy_write(bcm, 0x042C, 0x005A);
+		bcm43xx_phy_write(bcm, 0x0427, 0x001A);
+
+		for (i = 0; i < BCM43xx_ILT_FINEFREQG_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqg[i]);
+		for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]);
+		for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
+	} else {
+		/* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */
+		bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654);
+
+		if (phy->rev == 2) {
+			bcm43xx_phy_write(bcm, 0x04C0, 0x1861);
+			bcm43xx_phy_write(bcm, 0x04C1, 0x0271);
+		} else if (phy->rev > 2) {
+			bcm43xx_phy_write(bcm, 0x04C0, 0x0098);
+			bcm43xx_phy_write(bcm, 0x04C1, 0x0070);
+			bcm43xx_phy_write(bcm, 0x04C9, 0x0080);
+		}
+		bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x800);
+
+		for (i = 0; i < 64; i++)
+			bcm43xx_ilt_write(bcm, 0x4000 + i, i);
+		for (i = 0; i < BCM43xx_ILT_NOISEG2_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg2[i]);
+	}
+	
+	if (phy->rev <= 2)
+		for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]);
+	else if ((phy->rev == 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200))
+		for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]);
+	else
+		for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg2[i]);
+	
+	if (phy->rev == 2)
+		for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
+	else if ((phy->rev > 2) && (phy->rev <= 7))
+		for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]);
+	
+	if (phy->rev == 1) {
+		for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
+		for (i = 0; i < 4; i++) {
+			bcm43xx_ilt_write(bcm, 0x5404 + i, 0x0020);
+			bcm43xx_ilt_write(bcm, 0x5408 + i, 0x0020);
+			bcm43xx_ilt_write(bcm, 0x540C + i, 0x0020);
+			bcm43xx_ilt_write(bcm, 0x5410 + i, 0x0020);
+		}
+		bcm43xx_phy_agcsetup(bcm);
+
+		if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
+		    (bcm->board_type == 0x0416) &&
+		    (bcm->board_revision == 0x0017))
+			return;
+
+		bcm43xx_ilt_write(bcm, 0x5001, 0x0002);
+		bcm43xx_ilt_write(bcm, 0x5002, 0x0001);
+	} else {
+		for (i = 0; i <= 0x2F; i++)
+			bcm43xx_ilt_write(bcm, 0x1000 + i, 0x0820);
+		bcm43xx_phy_agcsetup(bcm);
+		bcm43xx_phy_read(bcm, 0x0400); /* dummy read */
+		bcm43xx_phy_write(bcm, 0x0403, 0x1000);
+		bcm43xx_ilt_write(bcm, 0x3C02, 0x000F);
+		bcm43xx_ilt_write(bcm, 0x3C03, 0x0014);
+
+		if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
+		    (bcm->board_type == 0x0416) &&
+		    (bcm->board_revision == 0x0017))
+			return;
+
+		bcm43xx_ilt_write(bcm, 0x0401, 0x0002);
+		bcm43xx_ilt_write(bcm, 0x0402, 0x0001);
+	}
+}
+
+/* Initialize the noisescaletable for APHY */
+static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	int i;
+
+	bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, 0x1400);
+	for (i = 0; i < 12; i++) {
+		if (phy->rev == 2)
+			bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767);
+		else
+			bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323);
+	}
+	if (phy->rev == 2)
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6700);
+	else
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2300);
+	for (i = 0; i < 11; i++) {
+		if (phy->rev == 2)
+			bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767);
+		else
+			bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323);
+	}
+	if (phy->rev == 2)
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0067);
+	else
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0023);
+}
+
+static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	u16 i;
+
+	assert(phy->type == BCM43xx_PHYTYPE_A);
+	switch (phy->rev) {
+	case 2:
+		bcm43xx_phy_write(bcm, 0x008E, 0x3800);
+		bcm43xx_phy_write(bcm, 0x0035, 0x03FF);
+		bcm43xx_phy_write(bcm, 0x0036, 0x0400);
+
+		bcm43xx_ilt_write(bcm, 0x3807, 0x0051);
+
+		bcm43xx_phy_write(bcm, 0x001C, 0x0FF9);
+		bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F);
+		bcm43xx_ilt_write(bcm, 0x3C0C, 0x07BF);
+		bcm43xx_radio_write16(bcm, 0x0002, 0x07BF);
+
+		bcm43xx_phy_write(bcm, 0x0024, 0x4680);
+		bcm43xx_phy_write(bcm, 0x0020, 0x0003);
+		bcm43xx_phy_write(bcm, 0x001D, 0x0F40);
+		bcm43xx_phy_write(bcm, 0x001F, 0x1C00);
+
+		bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400);
+		bcm43xx_phy_write(bcm, 0x002B, bcm43xx_phy_read(bcm, 0x002B) & 0xFBFF);
+		bcm43xx_phy_write(bcm, 0x008E, 0x58C1);
+
+		bcm43xx_ilt_write(bcm, 0x0803, 0x000F);
+		bcm43xx_ilt_write(bcm, 0x0804, 0x001F);
+		bcm43xx_ilt_write(bcm, 0x0805, 0x002A);
+		bcm43xx_ilt_write(bcm, 0x0805, 0x0030);
+		bcm43xx_ilt_write(bcm, 0x0807, 0x003A);
+
+		bcm43xx_ilt_write(bcm, 0x0000, 0x0013);
+		bcm43xx_ilt_write(bcm, 0x0001, 0x0013);
+		bcm43xx_ilt_write(bcm, 0x0002, 0x0013);
+		bcm43xx_ilt_write(bcm, 0x0003, 0x0013);
+		bcm43xx_ilt_write(bcm, 0x0004, 0x0015);
+		bcm43xx_ilt_write(bcm, 0x0005, 0x0015);
+		bcm43xx_ilt_write(bcm, 0x0006, 0x0019);
+
+		bcm43xx_ilt_write(bcm, 0x0404, 0x0003);
+		bcm43xx_ilt_write(bcm, 0x0405, 0x0003);
+		bcm43xx_ilt_write(bcm, 0x0406, 0x0007);
+
+		for (i = 0; i < 16; i++)
+			bcm43xx_ilt_write(bcm, 0x4000 + i, (0x8 + i) & 0x000F);
+
+		bcm43xx_ilt_write(bcm, 0x3003, 0x1044);
+		bcm43xx_ilt_write(bcm, 0x3004, 0x7201);
+		bcm43xx_ilt_write(bcm, 0x3006, 0x0040);
+		bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008);
+
+		for (i = 0; i < BCM43xx_ILT_FINEFREQA_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqa[i]);
+		for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]);
+		for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
+		bcm43xx_phy_init_noisescaletbl(bcm);
+		for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
+		break;
+	case 3:
+		for (i = 0; i < 64; i++)
+			bcm43xx_ilt_write(bcm, 0x4000 + i, i);
+
+		bcm43xx_ilt_write(bcm, 0x3807, 0x0051);
+
+		bcm43xx_phy_write(bcm, 0x001C, 0x0FF9);
+		bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F);
+		bcm43xx_radio_write16(bcm, 0x0002, 0x07BF);
+
+		bcm43xx_phy_write(bcm, 0x0024, 0x4680);
+		bcm43xx_phy_write(bcm, 0x0020, 0x0003);
+		bcm43xx_phy_write(bcm, 0x001D, 0x0F40);
+		bcm43xx_phy_write(bcm, 0x001F, 0x1C00);
+		bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400);
+
+		bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008);
+		for (i = 0; i < BCM43xx_ILT_NOISEA3_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea3[i]);
+		bcm43xx_phy_init_noisescaletbl(bcm);
+		for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
+			bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
+
+		bcm43xx_phy_write(bcm, 0x0003, 0x1808);
+
+		bcm43xx_ilt_write(bcm, 0x0803, 0x000F);
+		bcm43xx_ilt_write(bcm, 0x0804, 0x001F);
+		bcm43xx_ilt_write(bcm, 0x0805, 0x002A);
+		bcm43xx_ilt_write(bcm, 0x0805, 0x0030);
+		bcm43xx_ilt_write(bcm, 0x0807, 0x003A);
+
+		bcm43xx_ilt_write(bcm, 0x0000, 0x0013);
+		bcm43xx_ilt_write(bcm, 0x0001, 0x0013);
+		bcm43xx_ilt_write(bcm, 0x0002, 0x0013);
+		bcm43xx_ilt_write(bcm, 0x0003, 0x0013);
+		bcm43xx_ilt_write(bcm, 0x0004, 0x0015);
+		bcm43xx_ilt_write(bcm, 0x0005, 0x0015);
+		bcm43xx_ilt_write(bcm, 0x0006, 0x0019);
+
+		bcm43xx_ilt_write(bcm, 0x0404, 0x0003);
+		bcm43xx_ilt_write(bcm, 0x0405, 0x0003);
+		bcm43xx_ilt_write(bcm, 0x0406, 0x0007);
+
+		bcm43xx_ilt_write(bcm, 0x3C02, 0x000F);
+		bcm43xx_ilt_write(bcm, 0x3C03, 0x0014);
+		break;
+	default:
+		assert(0);
+	}
+}
+
+/* Initialize APHY. This is also called for the GPHY in some cases. */
+static void bcm43xx_phy_inita(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 tval;
+
+	if (phy->type == BCM43xx_PHYTYPE_A) {
+		bcm43xx_phy_setupa(bcm);
+	} else {
+		bcm43xx_phy_setupg(bcm);
+		if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
+			bcm43xx_phy_write(bcm, 0x046E, 0x03CF);
+		return;
+	}
+
+	bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS,
+	                  (bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) & 0xF83C) | 0x0340);
+	bcm43xx_phy_write(bcm, 0x0034, 0x0001);
+
+	TODO();//TODO: RSSI AGC
+	bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS,
+	                  bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) | (1 << 14));
+	bcm43xx_radio_init2060(bcm);
+
+	if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM)
+	    && ((bcm->board_type == 0x0416) || (bcm->board_type == 0x040A))) {
+		if (radio->lofcal == 0xFFFF) {
+			TODO();//TODO: LOF Cal
+			bcm43xx_radio_set_tx_iq(bcm);
+		} else
+			bcm43xx_radio_write16(bcm, 0x001E, radio->lofcal);
+	}
+
+	bcm43xx_phy_write(bcm, 0x007A, 0xF111);
+
+	if (phy->savedpctlreg == 0xFFFF) {
+		bcm43xx_radio_write16(bcm, 0x0019, 0x0000);
+		bcm43xx_radio_write16(bcm, 0x0017, 0x0020);
+
+		tval = bcm43xx_ilt_read(bcm, 0x3001);
+		if (phy->rev == 1) {
+			bcm43xx_ilt_write(bcm, 0x3001,
+					  (bcm43xx_ilt_read(bcm, 0x3001) & 0xFF87)
+					  | 0x0058);
+		} else {
+			bcm43xx_ilt_write(bcm, 0x3001,
+					  (bcm43xx_ilt_read(bcm, 0x3001) & 0xFFC3)
+					  | 0x002C);
+		}
+		bcm43xx_dummy_transmission(bcm);
+		phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_A_PCTL);
+		bcm43xx_ilt_write(bcm, 0x3001, tval);
+
+		bcm43xx_radio_set_txpower_a(bcm, 0x0018);
+	}
+	bcm43xx_radio_clear_tssi(bcm);
+}
+
+static void bcm43xx_phy_initb2(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 offset, val;
+
+	bcm43xx_write16(bcm, 0x03EC, 0x3F22);
+	bcm43xx_phy_write(bcm, 0x0020, 0x301C);
+	bcm43xx_phy_write(bcm, 0x0026, 0x0000);
+	bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
+	bcm43xx_phy_write(bcm, 0x0088, 0x3E00);
+	val = 0x3C3D;
+	for (offset = 0x0089; offset < 0x00A7; offset++) {
+		bcm43xx_phy_write(bcm, offset, val);
+		val -= 0x0202;
+	}
+	bcm43xx_phy_write(bcm, 0x03E4, 0x3000);
+	if (radio->channel == 0xFF)
+		bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+	else
+		bcm43xx_radio_selectchannel(bcm, radio->channel, 0);
+	if (radio->version != 0x2050) {
+		bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
+		bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
+	}
+	bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+	bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+	if (radio->version == 0x2050) {
+		bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+		bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+		bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+		bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+		bcm43xx_radio_write16(bcm, 0x007A, 0x000F);
+		bcm43xx_phy_write(bcm, 0x0038, 0x0677);
+		bcm43xx_radio_init2050(bcm);
+	}
+	bcm43xx_phy_write(bcm, 0x0014, 0x0080);
+	bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
+	bcm43xx_phy_write(bcm, 0x0032, 0x00CC);
+	bcm43xx_phy_write(bcm, 0x0035, 0x07C2);
+	bcm43xx_phy_lo_b_measure(bcm);
+	bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
+	if (radio->version != 0x2050)
+		bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
+	bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1000);
+	bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
+	if (radio->version != 0x2050)
+		bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
+	bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+	bcm43xx_phy_init_pctl(bcm);
+}
+
+static void bcm43xx_phy_initb4(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 offset, val;
+
+	bcm43xx_write16(bcm, 0x03EC, 0x3F22);
+	bcm43xx_phy_write(bcm, 0x0020, 0x301C);
+	bcm43xx_phy_write(bcm, 0x0026, 0x0000);
+	bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
+	bcm43xx_phy_write(bcm, 0x0088, 0x3E00);
+	val = 0x3C3D;
+	for (offset = 0x0089; offset < 0x00A7; offset++) {
+		bcm43xx_phy_write(bcm, offset, val);
+		val -= 0x0202;
+	}
+	bcm43xx_phy_write(bcm, 0x03E4, 0x3000);
+	if (radio->channel == 0xFF)
+		bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+	else
+		bcm43xx_radio_selectchannel(bcm, radio->channel, 0);
+	if (radio->version != 0x2050) {
+		bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
+		bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
+	}
+	bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+	bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+	if (radio->version == 0x2050) {
+		bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+		bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+		bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+		bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+		bcm43xx_radio_write16(bcm, 0x007A, 0x000F);
+		bcm43xx_phy_write(bcm, 0x0038, 0x0677);
+		bcm43xx_radio_init2050(bcm);
+	}
+	bcm43xx_phy_write(bcm, 0x0014, 0x0080);
+	bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
+	if (radio->version == 0x2050)
+		bcm43xx_phy_write(bcm, 0x0032, 0x00E0);
+	bcm43xx_phy_write(bcm, 0x0035, 0x07C2);
+
+	bcm43xx_phy_lo_b_measure(bcm);
+
+	bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
+	if (radio->version == 0x2050)
+		bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
+	bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1100);
+	bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
+	if (radio->version == 0x2050)
+		bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
+	bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+	if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+		bcm43xx_calc_nrssi_slope(bcm);
+		bcm43xx_calc_nrssi_threshold(bcm);
+	}
+	bcm43xx_phy_init_pctl(bcm);
+}
+
+static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 offset;
+
+	if (phy->version == 1 &&
+	    radio->version == 0x2050) {
+		bcm43xx_radio_write16(bcm, 0x007A,
+				      bcm43xx_radio_read16(bcm, 0x007A)
+				      | 0x0050);
+	}
+	if ((bcm->board_vendor != PCI_VENDOR_ID_BROADCOM) &&
+	    (bcm->board_type != 0x0416)) {
+		for (offset = 0x00A8 ; offset < 0x00C7; offset++) {
+			bcm43xx_phy_write(bcm, offset,
+					  (bcm43xx_phy_read(bcm, offset) + 0x2020)
+					  & 0x3F3F);
+		}
+	}
+	bcm43xx_phy_write(bcm, 0x0035,
+			  (bcm43xx_phy_read(bcm, 0x0035) & 0xF0FF)
+			  | 0x0700);
+	if (radio->version == 0x2050)
+		bcm43xx_phy_write(bcm, 0x0038, 0x0667);
+
+	if (phy->connected) {
+		if (radio->version == 0x2050) {
+			bcm43xx_radio_write16(bcm, 0x007A,
+					      bcm43xx_radio_read16(bcm, 0x007A)
+					      | 0x0020);
+			bcm43xx_radio_write16(bcm, 0x0051,
+					      bcm43xx_radio_read16(bcm, 0x0051)
+					      | 0x0004);
+		}
+		bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, 0x0000);
+
+		bcm43xx_phy_write(bcm, 0x0802, bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
+		bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
+
+		bcm43xx_phy_write(bcm, 0x001C, 0x186A);
+
+		bcm43xx_phy_write(bcm, 0x0013, (bcm43xx_phy_read(bcm, 0x0013) & 0x00FF) | 0x1900);
+		bcm43xx_phy_write(bcm, 0x0035, (bcm43xx_phy_read(bcm, 0x0035) & 0xFFC0) | 0x0064);
+		bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D) & 0xFF80) | 0x000A);
+	}
+
+	if (bcm->bad_frames_preempt) {
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+				  bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11));
+	}
+
+	if (phy->version == 1 && radio->version == 0x2050) {
+		bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
+		bcm43xx_phy_write(bcm, 0x0021, 0x3763);
+		bcm43xx_phy_write(bcm, 0x0022, 0x1BC3);
+		bcm43xx_phy_write(bcm, 0x0023, 0x06F9);
+		bcm43xx_phy_write(bcm, 0x0024, 0x037E);
+	} else
+		bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
+	bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
+	bcm43xx_write16(bcm, 0x03EC, 0x3F22);
+
+	if (phy->version == 1 && radio->version == 0x2050)
+		bcm43xx_phy_write(bcm, 0x0020, 0x3E1C);
+	else
+		bcm43xx_phy_write(bcm, 0x0020, 0x301C);
+
+	if (phy->version == 0)
+		bcm43xx_write16(bcm, 0x03E4, 0x3000);
+
+	/* Force to channel 7, even if not supported. */
+	bcm43xx_radio_selectchannel(bcm, 7, 0);
+
+	if (radio->version != 0x2050) {
+		bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
+		bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
+	}
+
+	bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+	bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+
+	if (radio->version == 0x2050) {
+		bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+		bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+	}
+
+	bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+	bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+
+	bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0007);
+
+	bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+
+	bcm43xx_phy_write(bcm, 0x0014, 0x0080);
+	bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
+	bcm43xx_phy_write(bcm, 0x88A3, 0x002A);
+
+	bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+
+	if (radio->version == 0x2050)
+		bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
+
+	bcm43xx_write16(bcm, 0x03E4, (bcm43xx_read16(bcm, 0x03E4) & 0xFFC0) | 0x0004);
+}
+
+static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 offset, val;
+
+	bcm43xx_phy_write(bcm, 0x003E, 0x817A);
+	bcm43xx_radio_write16(bcm, 0x007A,
+	                      (bcm43xx_radio_read16(bcm, 0x007A) | 0x0058));
+	if ((radio->manufact == 0x17F) &&
+	    (radio->version == 0x2050) &&
+	    (radio->revision == 3 ||
+	     radio->revision == 4 ||
+	     radio->revision == 5)) {
+		bcm43xx_radio_write16(bcm, 0x0051, 0x001F);
+		bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
+		bcm43xx_radio_write16(bcm, 0x0053, 0x005B);
+		bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
+		bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
+		bcm43xx_radio_write16(bcm, 0x005B, 0x0088);
+		bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
+		bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
+		bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
+	}
+	if ((radio->manufact == 0x17F) &&
+	    (radio->version == 0x2050) &&
+	    (radio->revision == 6)) {
+		bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
+		bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
+		bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
+		bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
+		bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
+		bcm43xx_radio_write16(bcm, 0x005B, 0x008B);
+		bcm43xx_radio_write16(bcm, 0x005C, 0x00B5);
+		bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
+		bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
+		bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
+		bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
+		bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
+	}
+	if ((radio->manufact == 0x17F) &&
+	    (radio->version == 0x2050) &&
+	    (radio->revision == 7)) {
+		bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
+		bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
+		bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
+		bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
+		bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
+		bcm43xx_radio_write16(bcm, 0x005B, 0x00A8);
+		bcm43xx_radio_write16(bcm, 0x005C, 0x0075);
+		bcm43xx_radio_write16(bcm, 0x005D, 0x00F5);
+		bcm43xx_radio_write16(bcm, 0x005E, 0x00B8);
+		bcm43xx_radio_write16(bcm, 0x007D, 0x00E8);
+		bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
+		bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
+		bcm43xx_radio_write16(bcm, 0x007B, 0x0000);
+	}
+	if ((radio->manufact == 0x17F) &&
+	    (radio->version == 0x2050) &&
+	    (radio->revision == 8)) {
+		bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
+		bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
+		bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
+		bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
+		bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
+		bcm43xx_radio_write16(bcm, 0x005B, 0x006B);
+		bcm43xx_radio_write16(bcm, 0x005C, 0x000F);
+		if (bcm->sprom.boardflags & 0x8000) {
+			bcm43xx_radio_write16(bcm, 0x005D, 0x00FA);
+			bcm43xx_radio_write16(bcm, 0x005E, 0x00D8);
+		} else {
+			bcm43xx_radio_write16(bcm, 0x005D, 0x00F5);
+			bcm43xx_radio_write16(bcm, 0x005E, 0x00B8);
+		}
+		bcm43xx_radio_write16(bcm, 0x0073, 0x0003);
+		bcm43xx_radio_write16(bcm, 0x007D, 0x00A8);
+		bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
+		bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
+	}
+	val = 0x1E1F;
+	for (offset = 0x0088; offset < 0x0098; offset++) {
+		bcm43xx_phy_write(bcm, offset, val);
+		val -= 0x0202;
+	}
+	val = 0x3E3F;
+	for (offset = 0x0098; offset < 0x00A8; offset++) {
+		bcm43xx_phy_write(bcm, offset, val);
+		val -= 0x0202;
+	}
+	val = 0x2120;
+	for (offset = 0x00A8; offset < 0x00C8; offset++) {
+		bcm43xx_phy_write(bcm, offset, (val & 0x3F3F));
+		val += 0x0202;
+	}
+	if (phy->type == BCM43xx_PHYTYPE_G) {
+		bcm43xx_radio_write16(bcm, 0x007A,
+		                      bcm43xx_radio_read16(bcm, 0x007A) | 0x0020);
+		bcm43xx_radio_write16(bcm, 0x0051,
+		                      bcm43xx_radio_read16(bcm, 0x0051) | 0x0004);
+		bcm43xx_phy_write(bcm, 0x0802,
+		                  bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
+		bcm43xx_phy_write(bcm, 0x042B,
+		                  bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
+	}
+
+	/* Force to channel 7, even if not supported. */
+	bcm43xx_radio_selectchannel(bcm, 7, 0);
+
+	bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+	bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+	udelay(40);
+	bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C) | 0x0002));
+	bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+	if (radio->manufact == 0x17F &&
+	    radio->version == 0x2050 &&
+	    radio->revision <= 2) {
+		bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+		bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+		bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+		bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+	}
+	bcm43xx_radio_write16(bcm, 0x007A,
+	                      (bcm43xx_radio_read16(bcm, 0x007A) & 0x00F8) | 0x0007);
+
+	bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+
+	bcm43xx_phy_write(bcm, 0x0014, 0x0200);
+	if (radio->version == 0x2050){
+		if (radio->revision == 3 ||
+		    radio->revision == 4 ||
+		    radio->revision == 5)
+			bcm43xx_phy_write(bcm, 0x002A, 0x8AC0);
+		else
+			bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
+	}
+	bcm43xx_phy_write(bcm, 0x0038, 0x0668);
+	bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+	if (radio->version == 0x2050) {
+		if (radio->revision == 3 ||
+		    radio->revision == 4 ||
+		    radio->revision == 5)
+			bcm43xx_phy_write(bcm, 0x005D, bcm43xx_phy_read(bcm, 0x005D) | 0x0003);
+		else if (radio->revision <= 2)
+			bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
+	}
+	
+	if (phy->rev == 4)
+		bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004);
+	else
+		bcm43xx_write16(bcm, 0x03E4, 0x0009);
+	if (phy->type == BCM43xx_PHYTYPE_B) {
+		bcm43xx_write16(bcm, 0x03E6, 0x8140);
+		bcm43xx_phy_write(bcm, 0x0016, 0x0410);
+		bcm43xx_phy_write(bcm, 0x0017, 0x0820);
+		bcm43xx_phy_write(bcm, 0x0062, 0x0007);
+		(void) bcm43xx_radio_calibrationvalue(bcm);
+		bcm43xx_phy_lo_b_measure(bcm);
+		if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+			bcm43xx_calc_nrssi_slope(bcm);
+			bcm43xx_calc_nrssi_threshold(bcm);
+		}
+		bcm43xx_phy_init_pctl(bcm);
+	} else
+		bcm43xx_write16(bcm, 0x03E6, 0x0);
+}
+
+static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 backup_phy[15];
+	u16 backup_radio[3];
+	u16 backup_bband;
+	u16 i;
+	u16 loop1_cnt, loop1_done, loop1_omitted;
+	u16 loop2_done;
+
+	backup_phy[0] = bcm43xx_phy_read(bcm, 0x0429);
+	backup_phy[1] = bcm43xx_phy_read(bcm, 0x0001);
+	backup_phy[2] = bcm43xx_phy_read(bcm, 0x0811);
+	backup_phy[3] = bcm43xx_phy_read(bcm, 0x0812);
+	backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814);
+	backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815);
+	backup_phy[6] = bcm43xx_phy_read(bcm, 0x005A);
+	backup_phy[7] = bcm43xx_phy_read(bcm, 0x0059);
+	backup_phy[8] = bcm43xx_phy_read(bcm, 0x0058);
+	backup_phy[9] = bcm43xx_phy_read(bcm, 0x000A);
+	backup_phy[10] = bcm43xx_phy_read(bcm, 0x0003);
+	backup_phy[11] = bcm43xx_phy_read(bcm, 0x080F);
+	backup_phy[12] = bcm43xx_phy_read(bcm, 0x0810);
+	backup_phy[13] = bcm43xx_phy_read(bcm, 0x002B);
+	backup_phy[14] = bcm43xx_phy_read(bcm, 0x0015);
+	bcm43xx_phy_read(bcm, 0x002D); /* dummy read */
+	backup_bband = radio->baseband_atten;
+	backup_radio[0] = bcm43xx_radio_read16(bcm, 0x0052);
+	backup_radio[1] = bcm43xx_radio_read16(bcm, 0x0043);
+	backup_radio[2] = bcm43xx_radio_read16(bcm, 0x007A);
+
+	bcm43xx_phy_write(bcm, 0x0429,
+			  bcm43xx_phy_read(bcm, 0x0429) & 0x3FFF);
+	bcm43xx_phy_write(bcm, 0x0001,
+			  bcm43xx_phy_read(bcm, 0x0001) & 0x8000);
+	bcm43xx_phy_write(bcm, 0x0811,
+			  bcm43xx_phy_read(bcm, 0x0811) | 0x0002);
+	bcm43xx_phy_write(bcm, 0x0812,
+			  bcm43xx_phy_read(bcm, 0x0812) & 0xFFFD);
+	bcm43xx_phy_write(bcm, 0x0811,
+			  bcm43xx_phy_read(bcm, 0x0811) | 0x0001);
+	bcm43xx_phy_write(bcm, 0x0812,
+			  bcm43xx_phy_read(bcm, 0x0812) & 0xFFFE);
+	bcm43xx_phy_write(bcm, 0x0814,
+			  bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
+	bcm43xx_phy_write(bcm, 0x0815,
+			  bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
+	bcm43xx_phy_write(bcm, 0x0814,
+			  bcm43xx_phy_read(bcm, 0x0814) | 0x0002);
+	bcm43xx_phy_write(bcm, 0x0815,
+			  bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD);
+	bcm43xx_phy_write(bcm, 0x0811,
+			  bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
+	bcm43xx_phy_write(bcm, 0x0812,
+			  bcm43xx_phy_read(bcm, 0x0812) | 0x000C);
+
+	bcm43xx_phy_write(bcm, 0x0811,
+			  (bcm43xx_phy_read(bcm, 0x0811)
+			   & 0xFFCF) | 0x0030);
+	bcm43xx_phy_write(bcm, 0x0812,
+			  (bcm43xx_phy_read(bcm, 0x0812)
+			   & 0xFFCF) | 0x0010);
+
+	bcm43xx_phy_write(bcm, 0x005A, 0x0780);
+	bcm43xx_phy_write(bcm, 0x0059, 0xC810);
+	bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+	if (phy->version == 0) {
+		bcm43xx_phy_write(bcm, 0x0003, 0x0122);
+	} else {
+		bcm43xx_phy_write(bcm, 0x000A,
+				  bcm43xx_phy_read(bcm, 0x000A)
+				  | 0x2000);
+	}
+	bcm43xx_phy_write(bcm, 0x0814,
+			  bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
+	bcm43xx_phy_write(bcm, 0x0815,
+			  bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
+	bcm43xx_phy_write(bcm, 0x0003,
+			  (bcm43xx_phy_read(bcm, 0x0003)
+			   & 0xFF9F) | 0x0040);
+	if (radio->version == 0x2050 && radio->revision == 2) {
+		bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
+		bcm43xx_radio_write16(bcm, 0x0043,
+				      (bcm43xx_radio_read16(bcm, 0x0043)
+				       & 0xFFF0) | 0x0009);
+		loop1_cnt = 9;
+	} else if (radio->revision == 8) {
+		bcm43xx_radio_write16(bcm, 0x0043, 0x000F);
+		loop1_cnt = 15;
+	} else
+		loop1_cnt = 0;
+
+	bcm43xx_phy_set_baseband_attenuation(bcm, 11);
+
+	if (phy->rev >= 3)
+		bcm43xx_phy_write(bcm, 0x080F, 0xC020);
+	else
+		bcm43xx_phy_write(bcm, 0x080F, 0x8020);
+	bcm43xx_phy_write(bcm, 0x0810, 0x0000);
+
+	bcm43xx_phy_write(bcm, 0x002B,
+			  (bcm43xx_phy_read(bcm, 0x002B)
+			   & 0xFFC0) | 0x0001);
+	bcm43xx_phy_write(bcm, 0x002B,
+			  (bcm43xx_phy_read(bcm, 0x002B)
+			   & 0xC0FF) | 0x0800);
+	bcm43xx_phy_write(bcm, 0x0811,
+			  bcm43xx_phy_read(bcm, 0x0811) | 0x0100);
+	bcm43xx_phy_write(bcm, 0x0812,
+			  bcm43xx_phy_read(bcm, 0x0812) & 0xCFFF);
+	if (bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA) {
+		if (phy->rev >= 7) {
+			bcm43xx_phy_write(bcm, 0x0811,
+					  bcm43xx_phy_read(bcm, 0x0811)
+					  | 0x0800);
+			bcm43xx_phy_write(bcm, 0x0812,
+					  bcm43xx_phy_read(bcm, 0x0812)
+					  | 0x8000);
+		}
+	}
+	bcm43xx_radio_write16(bcm, 0x007A,
+			      bcm43xx_radio_read16(bcm, 0x007A)
+			      & 0x00F7);
+
+	for (i = 0; i < loop1_cnt; i++) {
+		bcm43xx_radio_write16(bcm, 0x0043, loop1_cnt);
+		bcm43xx_phy_write(bcm, 0x0812,
+				  (bcm43xx_phy_read(bcm, 0x0812)
+				   & 0xF0FF) | (i << 8));
+		bcm43xx_phy_write(bcm, 0x0015,
+				  (bcm43xx_phy_read(bcm, 0x0015)
+				   & 0x0FFF) | 0xA000);
+		bcm43xx_phy_write(bcm, 0x0015,
+				  (bcm43xx_phy_read(bcm, 0x0015)
+				   & 0x0FFF) | 0xF000);
+		udelay(20);
+		if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC)
+			break;
+	}
+	loop1_done = i;
+	loop1_omitted = loop1_cnt - loop1_done;
+
+	loop2_done = 0;
+	if (loop1_done >= 8) {
+		bcm43xx_phy_write(bcm, 0x0812,
+				  bcm43xx_phy_read(bcm, 0x0812)
+				  | 0x0030);
+		for (i = loop1_done - 8; i < 16; i++) {
+			bcm43xx_phy_write(bcm, 0x0812,
+					  (bcm43xx_phy_read(bcm, 0x0812)
+					   & 0xF0FF) | (i << 8));
+			bcm43xx_phy_write(bcm, 0x0015,
+					  (bcm43xx_phy_read(bcm, 0x0015)
+					   & 0x0FFF) | 0xA000);
+			bcm43xx_phy_write(bcm, 0x0015,
+					  (bcm43xx_phy_read(bcm, 0x0015)
+					   & 0x0FFF) | 0xF000);
+			udelay(20);
+			if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC)
+				break;
+		}
+	}
+
+	bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]);
+	bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]);
+	bcm43xx_phy_write(bcm, 0x005A, backup_phy[6]);
+	bcm43xx_phy_write(bcm, 0x0059, backup_phy[7]);
+	bcm43xx_phy_write(bcm, 0x0058, backup_phy[8]);
+	bcm43xx_phy_write(bcm, 0x000A, backup_phy[9]);
+	bcm43xx_phy_write(bcm, 0x0003, backup_phy[10]);
+	bcm43xx_phy_write(bcm, 0x080F, backup_phy[11]);
+	bcm43xx_phy_write(bcm, 0x0810, backup_phy[12]);
+	bcm43xx_phy_write(bcm, 0x002B, backup_phy[13]);
+	bcm43xx_phy_write(bcm, 0x0015, backup_phy[14]);
+
+	bcm43xx_phy_set_baseband_attenuation(bcm, backup_bband);
+
+	bcm43xx_radio_write16(bcm, 0x0052, backup_radio[0]);
+	bcm43xx_radio_write16(bcm, 0x0043, backup_radio[1]);
+	bcm43xx_radio_write16(bcm, 0x007A, backup_radio[2]);
+
+	bcm43xx_phy_write(bcm, 0x0811, backup_phy[2] | 0x0003);
+	udelay(10);
+	bcm43xx_phy_write(bcm, 0x0811, backup_phy[2]);
+	bcm43xx_phy_write(bcm, 0x0812, backup_phy[3]);
+	bcm43xx_phy_write(bcm, 0x0429, backup_phy[0]);
+	bcm43xx_phy_write(bcm, 0x0001, backup_phy[1]);
+
+	phy->loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - 11;
+	phy->loopback_gain[1] = (24 - (3 * loop2_done)) * 2;
+}
+
+static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 tmp;
+
+	if (phy->rev == 1)
+		bcm43xx_phy_initb5(bcm);
+	else if (phy->rev >= 2 && phy->rev <= 7)
+		bcm43xx_phy_initb6(bcm);
+	if (phy->rev >= 2 || phy->connected)
+		bcm43xx_phy_inita(bcm);
+
+	if (phy->rev >= 2) {
+		bcm43xx_phy_write(bcm, 0x0814, 0x0000);
+		bcm43xx_phy_write(bcm, 0x0815, 0x0000);
+		if (phy->rev == 2)
+			bcm43xx_phy_write(bcm, 0x0811, 0x0000);
+		else if (phy->rev >= 3)
+			bcm43xx_phy_write(bcm, 0x0811, 0x0400);
+		bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
+		if (phy->connected) {
+			tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF;
+			if (tmp < 6) {
+				bcm43xx_phy_write(bcm, 0x04C2, 0x1816);
+				bcm43xx_phy_write(bcm, 0x04C3, 0x8006);
+				if (tmp != 3) {
+					bcm43xx_phy_write(bcm, 0x04CC,
+							  (bcm43xx_phy_read(bcm, 0x04CC)
+							   & 0x00FF) | 0x1F00);
+				}
+			}
+		}
+	}
+	if (phy->rev < 3 && phy->connected)
+		bcm43xx_phy_write(bcm, 0x047E, 0x0078);
+	if (phy->rev >= 6 && phy->rev <= 8) {
+		bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080);
+		bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004);
+	}
+	if (phy->rev >= 2 && phy->connected)
+		bcm43xx_calc_loopback_gain(bcm);
+	if (radio->revision != 8) {
+		if (radio->initval == 0xFFFF)
+			radio->initval = bcm43xx_radio_init2050(bcm);
+		else
+			bcm43xx_radio_write16(bcm, 0x0078, radio->initval);
+	}
+	if (radio->txctl2 == 0xFFFF) {
+		bcm43xx_phy_lo_g_measure(bcm);
+	} else {
+		if (radio->version == 0x2050 && radio->revision == 8) {
+			//FIXME
+		} else {
+			bcm43xx_radio_write16(bcm, 0x0052,
+					      (bcm43xx_radio_read16(bcm, 0x0052)
+					       & 0xFFF0) | radio->txctl1);
+		}
+		if (phy->rev >= 6) {
+			/*
+			bcm43xx_phy_write(bcm, 0x0036,
+					  (bcm43xx_phy_read(bcm, 0x0036)
+					   & 0xF000) | (FIXME << 12));
+			*/
+		}
+		if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
+			bcm43xx_phy_write(bcm, 0x002E, 0x8075);
+		else
+			bcm43xx_phy_write(bcm, 0x003E, 0x807F);
+		if (phy->rev < 2)
+			bcm43xx_phy_write(bcm, 0x002F, 0x0101);
+		else
+			bcm43xx_phy_write(bcm, 0x002F, 0x0202);
+	}
+	if (phy->connected) {
+		bcm43xx_phy_lo_adjust(bcm, 0);
+		bcm43xx_phy_write(bcm, 0x080F, 0x8078);
+	}
+
+	if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {
+		/* The specs state to update the NRSSI LT with
+		 * the value 0x7FFFFFFF here. I think that is some weird
+		 * compiler optimization in the original driver.
+		 * Essentially, what we do here is resetting all NRSSI LT
+		 * entries to -32 (see the limit_value() in nrssi_hw_update())
+		 */
+		bcm43xx_nrssi_hw_update(bcm, 0xFFFF);
+		bcm43xx_calc_nrssi_threshold(bcm);
+	} else if (phy->connected) {
+		if (radio->nrssi[0] == -1000) {
+			assert(radio->nrssi[1] == -1000);
+			bcm43xx_calc_nrssi_slope(bcm);
+		} else {
+			assert(radio->nrssi[1] != -1000);
+			bcm43xx_calc_nrssi_threshold(bcm);
+		}
+	}
+	if (radio->revision == 8)
+		bcm43xx_phy_write(bcm, 0x0805, 0x3230);
+	bcm43xx_phy_init_pctl(bcm);
+	if (bcm->chip_id == 0x4306 && bcm->chip_package != 2) {
+		bcm43xx_phy_write(bcm, 0x0429,
+				  bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF);
+		bcm43xx_phy_write(bcm, 0x04C3,
+				  bcm43xx_phy_read(bcm, 0x04C3) & 0x7FFF);
+	}
+}
+
+static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm)
+{
+	int i;
+	u16 ret = 0;
+
+	for (i = 0; i < 10; i++){
+		bcm43xx_phy_write(bcm, 0x0015, 0xAFA0);
+		udelay(1);
+		bcm43xx_phy_write(bcm, 0x0015, 0xEFA0);
+		udelay(10);
+		bcm43xx_phy_write(bcm, 0x0015, 0xFFA0);
+		udelay(40);
+		ret += bcm43xx_phy_read(bcm, 0x002C);
+	}
+
+	return ret;
+}
+
+void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	u16 regstack[12] = { 0 };
+	u16 mls;
+	u16 fval;
+	int i, j;
+
+	regstack[0] = bcm43xx_phy_read(bcm, 0x0015);
+	regstack[1] = bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0;
+
+	if (radio->version == 0x2053) {
+		regstack[2] = bcm43xx_phy_read(bcm, 0x000A);
+		regstack[3] = bcm43xx_phy_read(bcm, 0x002A);
+		regstack[4] = bcm43xx_phy_read(bcm, 0x0035);
+		regstack[5] = bcm43xx_phy_read(bcm, 0x0003);
+		regstack[6] = bcm43xx_phy_read(bcm, 0x0001);
+		regstack[7] = bcm43xx_phy_read(bcm, 0x0030);
+
+		regstack[8] = bcm43xx_radio_read16(bcm, 0x0043);
+		regstack[9] = bcm43xx_radio_read16(bcm, 0x007A);
+		regstack[10] = bcm43xx_read16(bcm, 0x03EC);
+		regstack[11] = bcm43xx_radio_read16(bcm, 0x0052) & 0x00F0;
+
+		bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
+		bcm43xx_write16(bcm, 0x03EC, 0x3F3F);
+		bcm43xx_phy_write(bcm, 0x0035, regstack[4] & 0xFF7F);
+		bcm43xx_radio_write16(bcm, 0x007A, regstack[9] & 0xFFF0);
+	}
+	bcm43xx_phy_write(bcm, 0x0015, 0xB000);
+	bcm43xx_phy_write(bcm, 0x002B, 0x0004);
+
+	if (radio->version == 0x2053) {
+		bcm43xx_phy_write(bcm, 0x002B, 0x0203);
+		bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
+	}
+
+	phy->minlowsig[0] = 0xFFFF;
+
+	for (i = 0; i < 4; i++) {
+		bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i);
+		bcm43xx_phy_lo_b_r15_loop(bcm);
+	}
+	for (i = 0; i < 10; i++) {
+		bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i);
+		mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10;
+		if (mls < phy->minlowsig[0]) {
+			phy->minlowsig[0] = mls;
+			phy->minlowsigpos[0] = i;
+		}
+	}
+	bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | phy->minlowsigpos[0]);
+
+	phy->minlowsig[1] = 0xFFFF;
+
+	for (i = -4; i < 5; i += 2) {
+		for (j = -4; j < 5; j += 2) {
+			if (j < 0)
+				fval = (0x0100 * i) + j + 0x0100;
+			else
+				fval = (0x0100 * i) + j;
+			bcm43xx_phy_write(bcm, 0x002F, fval);
+			mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10;
+			if (mls < phy->minlowsig[1]) {
+				phy->minlowsig[1] = mls;
+				phy->minlowsigpos[1] = fval;
+			}
+		}
+	}
+	phy->minlowsigpos[1] += 0x0101;
+
+	bcm43xx_phy_write(bcm, 0x002F, phy->minlowsigpos[1]);
+	if (radio->version == 0x2053) {
+		bcm43xx_phy_write(bcm, 0x000A, regstack[2]);
+		bcm43xx_phy_write(bcm, 0x002A, regstack[3]);
+		bcm43xx_phy_write(bcm, 0x0035, regstack[4]);
+		bcm43xx_phy_write(bcm, 0x0003, regstack[5]);
+		bcm43xx_phy_write(bcm, 0x0001, regstack[6]);
+		bcm43xx_phy_write(bcm, 0x0030, regstack[7]);
+
+		bcm43xx_radio_write16(bcm, 0x0043, regstack[8]);
+		bcm43xx_radio_write16(bcm, 0x007A, regstack[9]);
+
+		bcm43xx_radio_write16(bcm, 0x0052,
+		                      (bcm43xx_radio_read16(bcm, 0x0052) & 0x000F)
+				      | regstack[11]);
+
+		bcm43xx_write16(bcm, 0x03EC, regstack[10]);
+	}
+	bcm43xx_phy_write(bcm, 0x0015, regstack[0]);
+}
+
+static inline
+u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
+	if (phy->connected) {
+		bcm43xx_phy_write(bcm, 0x15, 0xE300);
+		control <<= 8;
+		bcm43xx_phy_write(bcm, 0x0812, control | 0x00B0);
+		udelay(5);
+		bcm43xx_phy_write(bcm, 0x0812, control | 0x00B2);
+		udelay(2);
+		bcm43xx_phy_write(bcm, 0x0812, control | 0x00B3);
+		udelay(4);
+		bcm43xx_phy_write(bcm, 0x0015, 0xF300);
+		udelay(8);
+	} else {
+		bcm43xx_phy_write(bcm, 0x0015, control | 0xEFA0);
+		udelay(2);
+		bcm43xx_phy_write(bcm, 0x0015, control | 0xEFE0);
+		udelay(4);
+		bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0);
+		udelay(8);
+	}
+
+	return bcm43xx_phy_read(bcm, 0x002D);
+}
+
+static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control)
+{
+	int i;
+	u32 ret = 0;
+
+	for (i = 0; i < 8; i++)
+		ret += bcm43xx_phy_lo_g_deviation_subval(bcm, control);
+
+	return ret;
+}
+
+/* Write the LocalOscillator CONTROL */
+static inline
+void bcm43xx_lo_write(struct bcm43xx_private *bcm,
+		      struct bcm43xx_lopair *pair)
+{
+	u16 value;
+
+	value = (u8)(pair->low);
+	value |= ((u8)(pair->high)) << 8;
+
+#ifdef CONFIG_BCM43XX_DEBUG
+	/* Sanity check. */
+	if (pair->low < -8 || pair->low > 8 ||
+	    pair->high < -8 || pair->high > 8) {
+		printk(KERN_WARNING PFX
+		       "WARNING: Writing invalid LOpair "
+		       "(low: %d, high: %d, index: %lu)\n",
+		       pair->low, pair->high,
+		       (unsigned long)(pair - bcm43xx_current_phy(bcm)->_lo_pairs));
+		dump_stack();
+	}
+#endif
+
+	bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, value);
+}
+
+static inline
+struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm,
+					    u16 baseband_attenuation,
+					    u16 radio_attenuation,
+					    u16 tx)
+{
+	static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 };
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
+	if (baseband_attenuation > 6)
+		baseband_attenuation = 6;
+	assert(radio_attenuation < 10);
+
+	if (tx == 3) {
+		return bcm43xx_get_lopair(phy,
+					  radio_attenuation,
+					  baseband_attenuation);
+	}
+	return bcm43xx_get_lopair(phy, dict[radio_attenuation], baseband_attenuation);
+}
+
+static inline
+struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+
+	return bcm43xx_find_lopair(bcm,
+				   radio->baseband_atten,
+				   radio->radio_atten,
+				   radio->txctl1);
+}
+
+/* Adjust B/G LO */
+void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed)
+{
+	struct bcm43xx_lopair *pair;
+
+	if (fixed) {
+		/* Use fixed values. Only for initialization. */
+		pair = bcm43xx_find_lopair(bcm, 2, 3, 0);
+	} else
+		pair = bcm43xx_current_lopair(bcm);
+	bcm43xx_lo_write(bcm, pair);
+}
+
+static void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 txctl2 = 0, i;
+	u32 smallest, tmp;
+
+	bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
+	udelay(10);
+	smallest = bcm43xx_phy_lo_g_singledeviation(bcm, 0);
+	for (i = 0; i < 16; i++) {
+		bcm43xx_radio_write16(bcm, 0x0052, i);
+		udelay(10);
+		tmp = bcm43xx_phy_lo_g_singledeviation(bcm, 0);
+		if (tmp < smallest) {
+			smallest = tmp;
+			txctl2 = i;
+		}
+	}
+	radio->txctl2 = txctl2;
+}
+
+static
+void bcm43xx_phy_lo_g_state(struct bcm43xx_private *bcm,
+			    const struct bcm43xx_lopair *in_pair,
+			    struct bcm43xx_lopair *out_pair,
+			    u16 r27)
+{
+	static const struct bcm43xx_lopair transitions[8] = {
+		{ .high =  1,  .low =  1, },
+		{ .high =  1,  .low =  0, },
+		{ .high =  1,  .low = -1, },
+		{ .high =  0,  .low = -1, },
+		{ .high = -1,  .low = -1, },
+		{ .high = -1,  .low =  0, },
+		{ .high = -1,  .low =  1, },
+		{ .high =  0,  .low =  1, },
+	};
+	struct bcm43xx_lopair lowest_transition = {
+		.high = in_pair->high,
+		.low = in_pair->low,
+	};
+	struct bcm43xx_lopair tmp_pair;
+	struct bcm43xx_lopair transition;
+	int i = 12;
+	int state = 0;
+	int found_lower;
+	int j, begin, end;
+	u32 lowest_deviation;
+	u32 tmp;
+
+	/* Note that in_pair and out_pair can point to the same pair. Be careful. */
+
+	bcm43xx_lo_write(bcm, &lowest_transition);
+	lowest_deviation = bcm43xx_phy_lo_g_singledeviation(bcm, r27);
+	do {
+		found_lower = 0;
+		assert(state >= 0 && state <= 8);
+		if (state == 0) {
+			begin = 1;
+			end = 8;
+		} else if (state % 2 == 0) {
+			begin = state - 1;
+			end = state + 1;
+		} else {
+			begin = state - 2;
+			end = state + 2;
+		}
+		if (begin < 1)
+			begin += 8;
+		if (end > 8)
+			end -= 8;
+
+		j = begin;
+		tmp_pair.high = lowest_transition.high;
+		tmp_pair.low = lowest_transition.low;
+		while (1) {
+			assert(j >= 1 && j <= 8);
+			transition.high = tmp_pair.high + transitions[j - 1].high;
+			transition.low = tmp_pair.low + transitions[j - 1].low;
+			if ((abs(transition.low) < 9) && (abs(transition.high) < 9)) {
+				bcm43xx_lo_write(bcm, &transition);
+				tmp = bcm43xx_phy_lo_g_singledeviation(bcm, r27);
+				if (tmp < lowest_deviation) {
+					lowest_deviation = tmp;
+					state = j;
+					found_lower = 1;
+
+					lowest_transition.high = transition.high;
+					lowest_transition.low = transition.low;
+				}
+			}
+			if (j == end)
+				break;
+			if (j == 8)
+				j = 1;
+			else
+				j++;
+		}
+	} while (i-- && found_lower);
+
+	out_pair->high = lowest_transition.high;
+	out_pair->low = lowest_transition.low;
+}
+
+/* Set the baseband attenuation value on chip. */
+void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
+					  u16 baseband_attenuation)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	u16 value;
+
+	if (phy->version == 0) {
+		value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0);
+		value |= (baseband_attenuation & 0x000F);
+		bcm43xx_write16(bcm, 0x03E6, value);
+		return;
+	}
+
+	if (phy->version > 1) {
+		value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
+		value |= (baseband_attenuation << 2) & 0x003C;
+	} else {
+		value = bcm43xx_phy_read(bcm, 0x0060) & ~0x0078;
+		value |= (baseband_attenuation << 3) & 0x0078;
+	}
+	bcm43xx_phy_write(bcm, 0x0060, value);
+}
+
+/* http://bcm-specs.sipsolutions.net/LocalOscillator/Measure */
+void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
+{
+	static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 };
+	const int is_initializing = bcm43xx_is_initializing(bcm);
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 h, i, oldi = 0, j;
+	struct bcm43xx_lopair control;
+	struct bcm43xx_lopair *tmp_control;
+	u16 tmp;
+	u16 regstack[16] = { 0 };
+	u8 oldchannel;
+
+	//XXX: What are these?
+	u8 r27 = 0, r31;
+
+	oldchannel = radio->channel;
+	/* Setup */
+	if (phy->connected) {
+		regstack[0] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);
+		regstack[1] = bcm43xx_phy_read(bcm, 0x0802);
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF);
+		bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC);
+	}
+	regstack[3] = bcm43xx_read16(bcm, 0x03E2);
+	bcm43xx_write16(bcm, 0x03E2, regstack[3] | 0x8000);
+	regstack[4] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+	regstack[5] = bcm43xx_phy_read(bcm, 0x15);
+	regstack[6] = bcm43xx_phy_read(bcm, 0x2A);
+	regstack[7] = bcm43xx_phy_read(bcm, 0x35);
+	regstack[8] = bcm43xx_phy_read(bcm, 0x60);
+	regstack[9] = bcm43xx_radio_read16(bcm, 0x43);
+	regstack[10] = bcm43xx_radio_read16(bcm, 0x7A);
+	regstack[11] = bcm43xx_radio_read16(bcm, 0x52);
+	if (phy->connected) {
+		regstack[12] = bcm43xx_phy_read(bcm, 0x0811);
+		regstack[13] = bcm43xx_phy_read(bcm, 0x0812);
+		regstack[14] = bcm43xx_phy_read(bcm, 0x0814);
+		regstack[15] = bcm43xx_phy_read(bcm, 0x0815);
+	}
+	bcm43xx_radio_selectchannel(bcm, 6, 0);
+	if (phy->connected) {
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF);
+		bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC);
+		bcm43xx_dummy_transmission(bcm);
+	}
+	bcm43xx_radio_write16(bcm, 0x0043, 0x0006);
+
+	bcm43xx_phy_set_baseband_attenuation(bcm, 2);
+
+	bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x0000);
+	bcm43xx_phy_write(bcm, 0x002E, 0x007F);
+	bcm43xx_phy_write(bcm, 0x080F, 0x0078);
+	bcm43xx_phy_write(bcm, 0x0035, regstack[7] & ~(1 << 7));
+	bcm43xx_radio_write16(bcm, 0x007A, regstack[10] & 0xFFF0);
+	bcm43xx_phy_write(bcm, 0x002B, 0x0203);
+	bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
+	if (phy->connected) {
+		bcm43xx_phy_write(bcm, 0x0814, regstack[14] | 0x0003);
+		bcm43xx_phy_write(bcm, 0x0815, regstack[15] & 0xFFFC);
+		bcm43xx_phy_write(bcm, 0x0811, 0x01B3);
+		bcm43xx_phy_write(bcm, 0x0812, 0x00B2);
+	}
+	if (is_initializing)
+		bcm43xx_phy_lo_g_measure_txctl2(bcm);
+	bcm43xx_phy_write(bcm, 0x080F, 0x8078);
+
+	/* Measure */
+	control.low = 0;
+	control.high = 0;
+	for (h = 0; h < 10; h++) {
+		/* Loop over each possible RadioAttenuation (0-9) */
+		i = pairorder[h];
+		if (is_initializing) {
+			if (i == 3) {
+				control.low = 0;
+				control.high = 0;
+			} else if (((i % 2 == 1) && (oldi % 2 == 1)) ||
+				  ((i % 2 == 0) && (oldi % 2 == 0))) {
+				tmp_control = bcm43xx_get_lopair(phy, oldi, 0);
+				memcpy(&control, tmp_control, sizeof(control));
+			} else {
+				tmp_control = bcm43xx_get_lopair(phy, 3, 0);
+				memcpy(&control, tmp_control, sizeof(control));
+			}
+		}
+		/* Loop over each possible BasebandAttenuation/2 */
+		for (j = 0; j < 4; j++) {
+			if (is_initializing) {
+				tmp = i * 2 + j;
+				r27 = 0;
+				r31 = 0;
+				if (tmp > 14) {
+					r31 = 1;
+					if (tmp > 17)
+						r27 = 1;
+					if (tmp > 19)
+						r27 = 2;
+				}
+			} else {
+				tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
+				if (!tmp_control->used)
+					continue;
+				memcpy(&control, tmp_control, sizeof(control));
+				r27 = 3;
+				r31 = 0;
+			}
+			bcm43xx_radio_write16(bcm, 0x43, i);
+			bcm43xx_radio_write16(bcm, 0x52, radio->txctl2);
+			udelay(10);
+
+			bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
+
+			tmp = (regstack[10] & 0xFFF0);
+			if (r31)
+				tmp |= 0x0008;
+			bcm43xx_radio_write16(bcm, 0x007A, tmp);
+
+			tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
+			bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27);
+		}
+		oldi = i;
+	}
+	/* Loop over each possible RadioAttenuation (10-13) */
+	for (i = 10; i < 14; i++) {
+		/* Loop over each possible BasebandAttenuation/2 */
+		for (j = 0; j < 4; j++) {
+			if (is_initializing) {
+				tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2);
+				memcpy(&control, tmp_control, sizeof(control));
+				tmp = (i - 9) * 2 + j - 5;//FIXME: This is wrong, as the following if statement can never trigger.
+				r27 = 0;
+				r31 = 0;
+				if (tmp > 14) {
+					r31 = 1;
+					if (tmp > 17)
+						r27 = 1;
+					if (tmp > 19)
+						r27 = 2;
+				}
+			} else {
+				tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2);
+				if (!tmp_control->used)
+					continue;
+				memcpy(&control, tmp_control, sizeof(control));
+				r27 = 3;
+				r31 = 0;
+			}
+			bcm43xx_radio_write16(bcm, 0x43, i - 9);
+			bcm43xx_radio_write16(bcm, 0x52,
+					      radio->txctl2
+					      | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above?
+			udelay(10);
+
+			bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
+
+			tmp = (regstack[10] & 0xFFF0);
+			if (r31)
+				tmp |= 0x0008;
+			bcm43xx_radio_write16(bcm, 0x7A, tmp);
+
+			tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
+			bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27);
+		}
+	}
+
+	/* Restoration */
+	if (phy->connected) {
+		bcm43xx_phy_write(bcm, 0x0015, 0xE300);
+		bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA0);
+		udelay(5);
+		bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2);
+		udelay(2);
+		bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3);
+	} else
+		bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0);
+	bcm43xx_phy_lo_adjust(bcm, is_initializing);
+	bcm43xx_phy_write(bcm, 0x002E, 0x807F);
+	if (phy->connected)
+		bcm43xx_phy_write(bcm, 0x002F, 0x0202);
+	else
+		bcm43xx_phy_write(bcm, 0x002F, 0x0101);
+	bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, regstack[4]);
+	bcm43xx_phy_write(bcm, 0x0015, regstack[5]);
+	bcm43xx_phy_write(bcm, 0x002A, regstack[6]);
+	bcm43xx_phy_write(bcm, 0x0035, regstack[7]);
+	bcm43xx_phy_write(bcm, 0x0060, regstack[8]);
+	bcm43xx_radio_write16(bcm, 0x0043, regstack[9]);
+	bcm43xx_radio_write16(bcm, 0x007A, regstack[10]);
+	regstack[11] &= 0x00F0;
+	regstack[11] |= (bcm43xx_radio_read16(bcm, 0x52) & 0x000F);
+	bcm43xx_radio_write16(bcm, 0x52, regstack[11]);
+	bcm43xx_write16(bcm, 0x03E2, regstack[3]);
+	if (phy->connected) {
+		bcm43xx_phy_write(bcm, 0x0811, regstack[12]);
+		bcm43xx_phy_write(bcm, 0x0812, regstack[13]);
+		bcm43xx_phy_write(bcm, 0x0814, regstack[14]);
+		bcm43xx_phy_write(bcm, 0x0815, regstack[15]);
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0]);
+		bcm43xx_phy_write(bcm, 0x0802, regstack[1]);
+	}
+	bcm43xx_radio_selectchannel(bcm, oldchannel, 1);
+
+#ifdef CONFIG_BCM43XX_DEBUG
+	{
+		/* Sanity check for all lopairs. */
+		for (i = 0; i < BCM43xx_LO_COUNT; i++) {
+			tmp_control = phy->_lo_pairs + i;
+			if (tmp_control->low < -8 || tmp_control->low > 8 ||
+			    tmp_control->high < -8 || tmp_control->high > 8) {
+				printk(KERN_WARNING PFX
+				       "WARNING: Invalid LOpair (low: %d, high: %d, index: %d)\n",
+				       tmp_control->low, tmp_control->high, i);
+			}
+		}
+	}
+#endif /* CONFIG_BCM43XX_DEBUG */
+}
+
+static
+void bcm43xx_phy_lo_mark_current_used(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_lopair *pair;
+
+	pair = bcm43xx_current_lopair(bcm);
+	pair->used = 1;
+}
+
+void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_lopair *pair;
+	int i;
+
+	for (i = 0; i < BCM43xx_LO_COUNT; i++) {
+		pair = phy->_lo_pairs + i;
+		pair->used = 0;
+	}
+}
+
+/* http://bcm-specs.sipsolutions.net/EstimatePowerOut
+ * This function converts a TSSI value to dBm in Q5.2
+ */
+static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_private *bcm, s8 tssi)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	s8 dbm = 0;
+	s32 tmp;
+
+	tmp = phy->idle_tssi;
+	tmp += tssi;
+	tmp -= phy->savedpctlreg;
+
+	switch (phy->type) {
+		case BCM43xx_PHYTYPE_A:
+			tmp += 0x80;
+			tmp = limit_value(tmp, 0x00, 0xFF);
+			dbm = phy->tssi2dbm[tmp];
+			TODO(); //TODO: There's a FIXME on the specs
+			break;
+		case BCM43xx_PHYTYPE_B:
+		case BCM43xx_PHYTYPE_G:
+			tmp = limit_value(tmp, 0x00, 0x3F);
+			dbm = phy->tssi2dbm[tmp];
+			break;
+		default:
+			assert(0);
+	}
+
+	return dbm;
+}
+
+/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */
+void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	
+	if (phy->savedpctlreg == 0xFFFF)
+		return;
+	if ((bcm->board_type == 0x0416) &&
+	    (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM))
+		return;
+	
+	switch (phy->type) {
+	case BCM43xx_PHYTYPE_A: {
+
+		TODO(); //TODO: Nothing for A PHYs yet :-/
+
+		break;
+	}
+	case BCM43xx_PHYTYPE_B:
+	case BCM43xx_PHYTYPE_G: {
+		u16 tmp;
+		u16 txpower;
+		s8 v0, v1, v2, v3;
+		s8 average;
+		u8 max_pwr;
+		s16 desired_pwr, estimated_pwr, pwr_adjust;
+		s16 radio_att_delta, baseband_att_delta;
+		s16 radio_attenuation, baseband_attenuation;
+		unsigned long phylock_flags;
+
+		tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0058);
+		v0 = (s8)(tmp & 0x00FF);
+		v1 = (s8)((tmp & 0xFF00) >> 8);
+		tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005A);
+		v2 = (s8)(tmp & 0x00FF);
+		v3 = (s8)((tmp & 0xFF00) >> 8);
+		tmp = 0;
+
+		if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) {
+			tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0070);
+			v0 = (s8)(tmp & 0x00FF);
+			v1 = (s8)((tmp & 0xFF00) >> 8);
+			tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0072);
+			v2 = (s8)(tmp & 0x00FF);
+			v3 = (s8)((tmp & 0xFF00) >> 8);
+			if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F)
+				return;
+			v0 = (v0 + 0x20) & 0x3F;
+			v1 = (v1 + 0x20) & 0x3F;
+			v2 = (v2 + 0x20) & 0x3F;
+			v3 = (v3 + 0x20) & 0x3F;
+			tmp = 1;
+		}
+		bcm43xx_radio_clear_tssi(bcm);
+
+		average = (v0 + v1 + v2 + v3 + 2) / 4;
+
+		if (tmp && (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005E) & 0x8))
+			average -= 13;
+
+		estimated_pwr = bcm43xx_phy_estimate_power_out(bcm, average);
+
+		max_pwr = bcm->sprom.maxpower_bgphy;
+
+		if ((bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) &&
+		    (phy->type == BCM43xx_PHYTYPE_G))
+			max_pwr -= 0x3;
+
+		/*TODO:
+		max_pwr = min(REG - bcm->sprom.antennagain_bgphy - 0x6, max_pwr)
+			where REG is the max power as per the regulatory domain
+		*/
+
+		desired_pwr = limit_value(radio->txpower_desired, 0, max_pwr);
+		/* Check if we need to adjust the current power. */
+		pwr_adjust = desired_pwr - estimated_pwr;
+		radio_att_delta = -(pwr_adjust + 7) >> 3;
+		baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta);
+		if ((radio_att_delta == 0) && (baseband_att_delta == 0)) {
+			bcm43xx_phy_lo_mark_current_used(bcm);
+			return;
+		}
+
+		/* Calculate the new attenuation values. */
+		baseband_attenuation = radio->baseband_atten;
+		baseband_attenuation += baseband_att_delta;
+		radio_attenuation = radio->radio_atten;
+		radio_attenuation += radio_att_delta;
+
+		/* Get baseband and radio attenuation values into their permitted ranges.
+		 * baseband 0-11, radio 0-9.
+		 * Radio attenuation affects power level 4 times as much as baseband.
+		 */
+		if (radio_attenuation < 0) {
+			baseband_attenuation -= (4 * -radio_attenuation);
+			radio_attenuation = 0;
+		} else if (radio_attenuation > 9) {
+			baseband_attenuation += (4 * (radio_attenuation - 9));
+			radio_attenuation = 9;
+		} else {
+			while (baseband_attenuation < 0 && radio_attenuation > 0) {
+				baseband_attenuation += 4;
+				radio_attenuation--;
+			}
+			while (baseband_attenuation > 11 && radio_attenuation < 9) {
+				baseband_attenuation -= 4;
+				radio_attenuation++;
+			}
+		}
+		baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
+
+		txpower = radio->txctl1;
+		if ((radio->version == 0x2050) && (radio->revision == 2)) {
+			if (radio_attenuation <= 1) {
+				if (txpower == 0) {
+					txpower = 3;
+					radio_attenuation += 2;
+					baseband_attenuation += 2;
+				} else if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
+					baseband_attenuation += 4 * (radio_attenuation - 2);
+					radio_attenuation = 2;
+				}
+			} else if (radio_attenuation > 4 && txpower != 0) {
+				txpower = 0;
+				if (baseband_attenuation < 3) {
+					radio_attenuation -= 3;
+					baseband_attenuation += 2;
+				} else {
+					radio_attenuation -= 2;
+					baseband_attenuation -= 2;
+				}
+			}
+		}
+		radio->txctl1 = txpower;
+		baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
+		radio_attenuation = limit_value(radio_attenuation, 0, 9);
+
+		bcm43xx_phy_lock(bcm, phylock_flags);
+		bcm43xx_radio_lock(bcm);
+		bcm43xx_radio_set_txpower_bg(bcm, baseband_attenuation,
+					     radio_attenuation, txpower);
+		bcm43xx_phy_lo_mark_current_used(bcm);
+		bcm43xx_radio_unlock(bcm);
+		bcm43xx_phy_unlock(bcm, phylock_flags);
+		break;
+	}
+	default:
+		assert(0);
+	}
+}
+
+static inline
+s32 bcm43xx_tssi2dbm_ad(s32 num, s32 den)
+{
+	if (num < 0)
+		return num/den;
+	else
+		return (num+den/2)/den;
+}
+
+static inline
+s8 bcm43xx_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2)
+{
+	s32 m1, m2, f = 256, q, delta;
+	s8 i = 0;
+	
+	m1 = bcm43xx_tssi2dbm_ad(16 * pab0 + index * pab1, 32);
+	m2 = max(bcm43xx_tssi2dbm_ad(32768 + index * pab2, 256), 1);
+	do {
+		if (i > 15)
+			return -EINVAL;
+		q = bcm43xx_tssi2dbm_ad(f * 4096 -
+					bcm43xx_tssi2dbm_ad(m2 * f, 16) * f, 2048);
+		delta = abs(q - f);
+		f = q;
+		i++;
+	} while (delta >= 2);
+	entry[index] = limit_value(bcm43xx_tssi2dbm_ad(m1 * f, 8192), -127, 128);
+	return 0;
+}
+
+/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */
+int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	s16 pab0, pab1, pab2;
+	u8 idx;
+	s8 *dyn_tssi2dbm;
+	
+	if (phy->type == BCM43xx_PHYTYPE_A) {
+		pab0 = (s16)(bcm->sprom.pa1b0);
+		pab1 = (s16)(bcm->sprom.pa1b1);
+		pab2 = (s16)(bcm->sprom.pa1b2);
+	} else {
+		pab0 = (s16)(bcm->sprom.pa0b0);
+		pab1 = (s16)(bcm->sprom.pa0b1);
+		pab2 = (s16)(bcm->sprom.pa0b2);
+	}
+
+	if ((bcm->chip_id == 0x4301) && (radio->version != 0x2050)) {
+		phy->idle_tssi = 0x34;
+		phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
+		return 0;
+	}
+
+	if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
+	    pab0 != -1 && pab1 != -1 && pab2 != -1) {
+		/* The pabX values are set in SPROM. Use them. */
+		if (phy->type == BCM43xx_PHYTYPE_A) {
+			if ((s8)bcm->sprom.idle_tssi_tgt_aphy != 0 &&
+			    (s8)bcm->sprom.idle_tssi_tgt_aphy != -1)
+				phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_aphy);
+			else
+				phy->idle_tssi = 62;
+		} else {
+			if ((s8)bcm->sprom.idle_tssi_tgt_bgphy != 0 &&
+			    (s8)bcm->sprom.idle_tssi_tgt_bgphy != -1)
+				phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_bgphy);
+			else
+				phy->idle_tssi = 62;
+		}
+		dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
+		if (dyn_tssi2dbm == NULL) {
+			printk(KERN_ERR PFX "Could not allocate memory"
+					    "for tssi2dbm table\n");
+			return -ENOMEM;
+		}
+		for (idx = 0; idx < 64; idx++)
+			if (bcm43xx_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0, pab1, pab2)) {
+				phy->tssi2dbm = NULL;
+				printk(KERN_ERR PFX "Could not generate "
+						    "tssi2dBm table\n");
+				return -ENODEV;
+			}
+		phy->tssi2dbm = dyn_tssi2dbm;
+		phy->dyn_tssi_tbl = 1;
+	} else {
+		/* pabX values not set in SPROM. */
+		switch (phy->type) {
+		case BCM43xx_PHYTYPE_A:
+			/* APHY needs a generated table. */
+			phy->tssi2dbm = NULL;
+			printk(KERN_ERR PFX "Could not generate tssi2dBm "
+					    "table (wrong SPROM info)!\n");
+			return -ENODEV;
+		case BCM43xx_PHYTYPE_B:
+			phy->idle_tssi = 0x34;
+			phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
+			break;
+		case BCM43xx_PHYTYPE_G:
+			phy->idle_tssi = 0x34;
+			phy->tssi2dbm = bcm43xx_tssi2dbm_g_table;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+int bcm43xx_phy_init(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	int err = -ENODEV;
+	unsigned long flags;
+
+	/* We do not want to be preempted while calibrating
+	 * the hardware.
+	 */
+	local_irq_save(flags);
+
+	switch (phy->type) {
+	case BCM43xx_PHYTYPE_A:
+		if (phy->rev == 2 || phy->rev == 3) {
+			bcm43xx_phy_inita(bcm);
+			err = 0;
+		}
+		break;
+	case BCM43xx_PHYTYPE_B:
+		switch (phy->rev) {
+		case 2:
+			bcm43xx_phy_initb2(bcm);
+			err = 0;
+			break;
+		case 4:
+			bcm43xx_phy_initb4(bcm);
+			err = 0;
+			break;
+		case 5:
+			bcm43xx_phy_initb5(bcm);
+			err = 0;
+			break;
+		case 6:
+			bcm43xx_phy_initb6(bcm);
+			err = 0;
+			break;
+		}
+		break;
+	case BCM43xx_PHYTYPE_G:
+		bcm43xx_phy_initg(bcm);
+		err = 0;
+		break;
+	}
+	local_irq_restore(flags);
+	if (err)
+		printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n");
+
+	return err;
+}
+
+void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	u16 antennadiv;
+	u16 offset;
+	u16 value;
+	u32 ucodeflags;
+
+	antennadiv = phy->antenna_diversity;
+
+	if (antennadiv == 0xFFFF)
+		antennadiv = 3;
+	assert(antennadiv <= 3);
+
+	ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+					BCM43xx_UCODEFLAGS_OFFSET);
+	bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+			    BCM43xx_UCODEFLAGS_OFFSET,
+			    ucodeflags & ~BCM43xx_UCODEFLAG_AUTODIV);
+
+	switch (phy->type) {
+	case BCM43xx_PHYTYPE_A:
+	case BCM43xx_PHYTYPE_G:
+		if (phy->type == BCM43xx_PHYTYPE_A)
+			offset = 0x0000;
+		else
+			offset = 0x0400;
+
+		if (antennadiv == 2)
+			value = (3/*automatic*/ << 7);
+		else
+			value = (antennadiv << 7);
+		bcm43xx_phy_write(bcm, offset + 1,
+				  (bcm43xx_phy_read(bcm, offset + 1)
+				   & 0x7E7F) | value);
+
+		if (antennadiv >= 2) {
+			if (antennadiv == 2)
+				value = (antennadiv << 7);
+			else
+				value = (0/*force0*/ << 7);
+			bcm43xx_phy_write(bcm, offset + 0x2B,
+					  (bcm43xx_phy_read(bcm, offset + 0x2B)
+					   & 0xFEFF) | value);
+		}
+
+		if (phy->type == BCM43xx_PHYTYPE_G) {
+			if (antennadiv >= 2)
+				bcm43xx_phy_write(bcm, 0x048C,
+						  bcm43xx_phy_read(bcm, 0x048C)
+						   | 0x2000);
+			else
+				bcm43xx_phy_write(bcm, 0x048C,
+						  bcm43xx_phy_read(bcm, 0x048C)
+						   & ~0x2000);
+			if (phy->rev >= 2) {
+				bcm43xx_phy_write(bcm, 0x0461,
+						  bcm43xx_phy_read(bcm, 0x0461)
+						   | 0x0010);
+				bcm43xx_phy_write(bcm, 0x04AD,
+						  (bcm43xx_phy_read(bcm, 0x04AD)
+						   & 0x00FF) | 0x0015);
+				if (phy->rev == 2)
+					bcm43xx_phy_write(bcm, 0x0427, 0x0008);
+				else
+					bcm43xx_phy_write(bcm, 0x0427,
+						(bcm43xx_phy_read(bcm, 0x0427)
+						 & 0x00FF) | 0x0008);
+			}
+			else if (phy->rev >= 6)
+				bcm43xx_phy_write(bcm, 0x049B, 0x00DC);
+		} else {
+			if (phy->rev < 3)
+				bcm43xx_phy_write(bcm, 0x002B,
+						  (bcm43xx_phy_read(bcm, 0x002B)
+						   & 0x00FF) | 0x0024);
+			else {
+				bcm43xx_phy_write(bcm, 0x0061,
+						  bcm43xx_phy_read(bcm, 0x0061)
+						   | 0x0010);
+				if (phy->rev == 3) {
+					bcm43xx_phy_write(bcm, 0x0093, 0x001D);
+					bcm43xx_phy_write(bcm, 0x0027, 0x0008);
+				} else {
+					bcm43xx_phy_write(bcm, 0x0093, 0x003A);
+					bcm43xx_phy_write(bcm, 0x0027,
+						(bcm43xx_phy_read(bcm, 0x0027)
+						 & 0x00FF) | 0x0008);
+				}
+			}
+		}
+		break;
+	case BCM43xx_PHYTYPE_B:
+		if (bcm->current_core->rev == 2)
+			value = (3/*automatic*/ << 7);
+		else
+			value = (antennadiv << 7);
+		bcm43xx_phy_write(bcm, 0x03E2,
+				  (bcm43xx_phy_read(bcm, 0x03E2)
+				   & 0xFE7F) | value);
+		break;
+	default:
+		assert(0);
+	}
+
+	if (antennadiv >= 2) {
+		ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+						BCM43xx_UCODEFLAGS_OFFSET);
+		bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+				    BCM43xx_UCODEFLAGS_OFFSET,
+				    ucodeflags | BCM43xx_UCODEFLAG_AUTODIV);
+	}
+
+	phy->antenna_diversity = antennadiv;
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.h b/drivers/net/wireless/bcm43xx/bcm43xx_phy.h
new file mode 100644
index 0000000..1f321ef
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.h
@@ -0,0 +1,74 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+                     Stefano Brivio <st3@riseup.net>
+                     Michael Buesch <mbuesch@freenet.de>
+                     Danny van Dyk <kugelfang@gentoo.org>
+                     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef BCM43xx_PHY_H_
+#define BCM43xx_PHY_H_
+
+#include <linux/types.h>
+
+struct bcm43xx_private;
+
+void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm);
+#define bcm43xx_phy_lock(bcm, flags) \
+	do {					\
+		local_irq_save(flags);		\
+		bcm43xx_raw_phy_lock(bcm);	\
+	} while (0)
+void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm);
+#define bcm43xx_phy_unlock(bcm, flags) \
+	do {					\
+		bcm43xx_raw_phy_unlock(bcm);	\
+		local_irq_restore(flags);	\
+	} while (0)
+
+u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset);
+void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
+
+int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm);
+int bcm43xx_phy_init(struct bcm43xx_private *bcm);
+
+void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm);
+void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm);
+int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect);
+
+void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm);
+void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm);
+void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm);
+
+/* Adjust the LocalOscillator to the saved values.
+ * "fixed" is only set to 1 once in initialization. Set to 0 otherwise.
+ */
+void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed);
+void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm);
+
+void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
+					  u16 baseband_attenuation);
+
+#endif /* BCM43xx_PHY_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
new file mode 100644
index 0000000..c59ddd4
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
@@ -0,0 +1,606 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  PIO Transmission
+
+  Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de>
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "bcm43xx.h"
+#include "bcm43xx_pio.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_xmit.h"
+
+#include <linux/delay.h>
+
+
+static void tx_start(struct bcm43xx_pioqueue *queue)
+{
+	bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+			  BCM43xx_PIO_TXCTL_INIT);
+}
+
+static void tx_octet(struct bcm43xx_pioqueue *queue,
+		     u8 octet)
+{
+	if (queue->need_workarounds) {
+		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
+				  octet);
+		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+				  BCM43xx_PIO_TXCTL_WRITEHI);
+	} else {
+		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+				  BCM43xx_PIO_TXCTL_WRITEHI);
+		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
+				  octet);
+	}
+}
+
+static u16 tx_get_next_word(struct bcm43xx_txhdr *txhdr,
+			    const u8 *packet,
+			    unsigned int *pos)
+{
+	const u8 *source;
+	unsigned int i = *pos;
+	u16 ret;
+
+	if (i < sizeof(*txhdr)) {
+		source = (const u8 *)txhdr;
+	} else {
+		source = packet;
+		i -= sizeof(*txhdr);
+	}
+	ret = le16_to_cpu( *((u16 *)(source + i)) );
+	*pos += 2;
+
+	return ret;
+}
+
+static void tx_data(struct bcm43xx_pioqueue *queue,
+		    struct bcm43xx_txhdr *txhdr,
+		    const u8 *packet,
+		    unsigned int octets)
+{
+	u16 data;
+	unsigned int i = 0;
+
+	if (queue->need_workarounds) {
+		data = tx_get_next_word(txhdr, packet, &i);
+		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
+	}
+	bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+			  BCM43xx_PIO_TXCTL_WRITELO |
+			  BCM43xx_PIO_TXCTL_WRITEHI);
+	while (i < octets - 1) {
+		data = tx_get_next_word(txhdr, packet, &i);
+		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
+	}
+	if (octets % 2)
+		tx_octet(queue, packet[octets - sizeof(*txhdr) - 1]);
+}
+
+static void tx_complete(struct bcm43xx_pioqueue *queue,
+			struct sk_buff *skb)
+{
+	if (queue->need_workarounds) {
+		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
+				  skb->data[skb->len - 1]);
+		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+				  BCM43xx_PIO_TXCTL_WRITEHI |
+				  BCM43xx_PIO_TXCTL_COMPLETE);
+	} else {
+		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+				  BCM43xx_PIO_TXCTL_COMPLETE);
+	}
+}
+
+static u16 generate_cookie(struct bcm43xx_pioqueue *queue,
+			   int packetindex)
+{
+	u16 cookie = 0x0000;
+
+	/* We use the upper 4 bits for the PIO
+	 * controller ID and the lower 12 bits
+	 * for the packet index (in the cache).
+	 */
+	switch (queue->mmio_base) {
+	case BCM43xx_MMIO_PIO1_BASE:
+		break;
+	case BCM43xx_MMIO_PIO2_BASE:
+		cookie = 0x1000;
+		break;
+	case BCM43xx_MMIO_PIO3_BASE:
+		cookie = 0x2000;
+		break;
+	case BCM43xx_MMIO_PIO4_BASE:
+		cookie = 0x3000;
+		break;
+	default:
+		assert(0);
+	}
+	assert(((u16)packetindex & 0xF000) == 0x0000);
+	cookie |= (u16)packetindex;
+
+	return cookie;
+}
+
+static
+struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm,
+				       u16 cookie,
+				       struct bcm43xx_pio_txpacket **packet)
+{
+	struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm);
+	struct bcm43xx_pioqueue *queue = NULL;
+	int packetindex;
+
+	switch (cookie & 0xF000) {
+	case 0x0000:
+		queue = pio->queue0;
+		break;
+	case 0x1000:
+		queue = pio->queue1;
+		break;
+	case 0x2000:
+		queue = pio->queue2;
+		break;
+	case 0x3000:
+		queue = pio->queue3;
+		break;
+	default:
+		assert(0);
+	}
+	packetindex = (cookie & 0x0FFF);
+	assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS);
+	*packet = &(queue->tx_packets_cache[packetindex]);
+
+	return queue;
+}
+
+static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue,
+				  struct sk_buff *skb,
+				  struct bcm43xx_pio_txpacket *packet)
+{
+	struct bcm43xx_txhdr txhdr;
+	unsigned int octets;
+
+	assert(skb_shinfo(skb)->nr_frags == 0);
+	bcm43xx_generate_txhdr(queue->bcm,
+			       &txhdr, skb->data, skb->len,
+			       (packet->xmitted_frags == 0),
+			       generate_cookie(queue, pio_txpacket_getindex(packet)));
+
+	tx_start(queue);
+	octets = skb->len + sizeof(txhdr);
+	if (queue->need_workarounds)
+		octets--;
+	tx_data(queue, &txhdr, (u8 *)skb->data, octets);
+	tx_complete(queue, skb);
+}
+
+static void free_txpacket(struct bcm43xx_pio_txpacket *packet,
+			  int irq_context)
+{
+	struct bcm43xx_pioqueue *queue = packet->queue;
+
+	ieee80211_txb_free(packet->txb);
+	list_move(&packet->list, &queue->txfree);
+	queue->nr_txfree++;
+
+	assert(queue->tx_devq_used >= packet->xmitted_octets);
+	assert(queue->tx_devq_packets >= packet->xmitted_frags);
+	queue->tx_devq_used -= packet->xmitted_octets;
+	queue->tx_devq_packets -= packet->xmitted_frags;
+}
+
+static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet)
+{
+	struct bcm43xx_pioqueue *queue = packet->queue;
+	struct ieee80211_txb *txb = packet->txb;
+	struct sk_buff *skb;
+	u16 octets;
+	int i;
+
+	for (i = packet->xmitted_frags; i < txb->nr_frags; i++) {
+		skb = txb->fragments[i];
+
+		octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr);
+		assert(queue->tx_devq_size >= octets);
+		assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS);
+		assert(queue->tx_devq_used <= queue->tx_devq_size);
+		/* Check if there is sufficient free space on the device
+		 * TX queue. If not, return and let the TX tasklet
+		 * retry later.
+		 */
+		if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS)
+			return -EBUSY;
+		if (queue->tx_devq_used + octets > queue->tx_devq_size)
+			return -EBUSY;
+		/* Now poke the device. */
+		pio_tx_write_fragment(queue, skb, packet);
+
+		/* Account for the packet size.
+		 * (We must not overflow the device TX queue)
+		 */
+		queue->tx_devq_packets++;
+		queue->tx_devq_used += octets;
+
+		assert(packet->xmitted_frags <= packet->txb->nr_frags);
+		packet->xmitted_frags++;
+		packet->xmitted_octets += octets;
+	}
+	list_move_tail(&packet->list, &queue->txrunning);
+
+	return 0;
+}
+
+static void tx_tasklet(unsigned long d)
+{
+	struct bcm43xx_pioqueue *queue = (struct bcm43xx_pioqueue *)d;
+	struct bcm43xx_private *bcm = queue->bcm;
+	unsigned long flags;
+	struct bcm43xx_pio_txpacket *packet, *tmp_packet;
+	int err;
+
+	bcm43xx_lock_mmio(bcm, flags);
+	list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
+		assert(packet->xmitted_frags < packet->txb->nr_frags);
+		if (packet->xmitted_frags == 0) {
+			int i;
+			struct sk_buff *skb;
+
+			/* Check if the device queue is big
+			 * enough for every fragment. If not, drop the
+			 * whole packet.
+			 */
+			for (i = 0; i < packet->txb->nr_frags; i++) {
+				skb = packet->txb->fragments[i];
+				if (unlikely(skb->len > queue->tx_devq_size)) {
+					dprintkl(KERN_ERR PFX "PIO TX device queue too small. "
+							      "Dropping packet.\n");
+					free_txpacket(packet, 1);
+					goto next_packet;
+				}
+			}
+		}
+		/* Try to transmit the packet.
+		 * This may not completely succeed.
+		 */
+		err = pio_tx_packet(packet);
+		if (err)
+			break;
+	next_packet:
+		continue;
+	}
+	bcm43xx_unlock_mmio(bcm, flags);
+}
+
+static void setup_txqueues(struct bcm43xx_pioqueue *queue)
+{
+	struct bcm43xx_pio_txpacket *packet;
+	int i;
+
+	queue->nr_txfree = BCM43xx_PIO_MAXTXPACKETS;
+	for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) {
+		packet = &(queue->tx_packets_cache[i]);
+
+		packet->queue = queue;
+		INIT_LIST_HEAD(&packet->list);
+
+		list_add(&packet->list, &queue->txfree);
+	}
+}
+
+static
+struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm,
+						 u16 pio_mmio_base)
+{
+	struct bcm43xx_pioqueue *queue;
+	u32 value;
+	u16 qsize;
+
+	queue = kzalloc(sizeof(*queue), GFP_KERNEL);
+	if (!queue)
+		goto out;
+
+	queue->bcm = bcm;
+	queue->mmio_base = pio_mmio_base;
+	queue->need_workarounds = (bcm->current_core->rev < 3);
+
+	INIT_LIST_HEAD(&queue->txfree);
+	INIT_LIST_HEAD(&queue->txqueue);
+	INIT_LIST_HEAD(&queue->txrunning);
+	tasklet_init(&queue->txtask, tx_tasklet,
+		     (unsigned long)queue);
+
+	value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+	value |= BCM43xx_SBF_XFER_REG_BYTESWAP;
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value);
+
+	qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE);
+	if (qsize <= BCM43xx_PIO_TXQADJUST) {
+		printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", qsize);
+		goto err_freequeue;
+	}
+	qsize -= BCM43xx_PIO_TXQADJUST;
+	queue->tx_devq_size = qsize;
+
+	setup_txqueues(queue);
+
+out:
+	return queue;
+
+err_freequeue:
+	kfree(queue);
+	queue = NULL;
+	goto out;
+}
+
+static void cancel_transfers(struct bcm43xx_pioqueue *queue)
+{
+	struct bcm43xx_pio_txpacket *packet, *tmp_packet;
+
+	netif_tx_disable(queue->bcm->net_dev);
+	assert(queue->bcm->shutting_down);
+	tasklet_disable(&queue->txtask);
+
+	list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
+		free_txpacket(packet, 0);
+	list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list)
+		free_txpacket(packet, 0);
+}
+
+static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue)
+{
+	if (!queue)
+		return;
+
+	cancel_transfers(queue);
+	kfree(queue);
+}
+
+void bcm43xx_pio_free(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_pio *pio;
+
+	if (!bcm43xx_using_pio(bcm))
+		return;
+	pio = bcm43xx_current_pio(bcm);
+
+	bcm43xx_destroy_pioqueue(pio->queue3);
+	pio->queue3 = NULL;
+	bcm43xx_destroy_pioqueue(pio->queue2);
+	pio->queue2 = NULL;
+	bcm43xx_destroy_pioqueue(pio->queue1);
+	pio->queue1 = NULL;
+	bcm43xx_destroy_pioqueue(pio->queue0);
+	pio->queue0 = NULL;
+}
+
+int bcm43xx_pio_init(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm);
+	struct bcm43xx_pioqueue *queue;
+	int err = -ENOMEM;
+
+	queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE);
+	if (!queue)
+		goto out;
+	pio->queue0 = queue;
+
+	queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE);
+	if (!queue)
+		goto err_destroy0;
+	pio->queue1 = queue;
+
+	queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE);
+	if (!queue)
+		goto err_destroy1;
+	pio->queue2 = queue;
+
+	queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE);
+	if (!queue)
+		goto err_destroy2;
+	pio->queue3 = queue;
+
+	if (bcm->current_core->rev < 3)
+		bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND;
+
+	dprintk(KERN_INFO PFX "PIO initialized\n");
+	err = 0;
+out:
+	return err;
+
+err_destroy2:
+	bcm43xx_destroy_pioqueue(pio->queue2);
+	pio->queue2 = NULL;
+err_destroy1:
+	bcm43xx_destroy_pioqueue(pio->queue1);
+	pio->queue1 = NULL;
+err_destroy0:
+	bcm43xx_destroy_pioqueue(pio->queue0);
+	pio->queue0 = NULL;
+	goto out;
+}
+
+int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
+		   struct ieee80211_txb *txb)
+{
+	struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1;
+	struct bcm43xx_pio_txpacket *packet;
+	u16 tmp;
+
+	assert(!queue->tx_suspended);
+	assert(!list_empty(&queue->txfree));
+
+	tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
+	if (tmp & BCM43xx_PIO_TXCTL_SUSPEND)
+		return -EBUSY;
+
+	packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list);
+	packet->txb = txb;
+	packet->xmitted_frags = 0;
+	packet->xmitted_octets = 0;
+	list_move_tail(&packet->list, &queue->txqueue);
+	queue->nr_txfree--;
+	assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS);
+
+	/* Suspend TX, if we are out of packets in the "free" queue. */
+	if (unlikely(list_empty(&queue->txfree))) {
+		netif_stop_queue(queue->bcm->net_dev);
+		queue->tx_suspended = 1;
+	}
+
+	tasklet_schedule(&queue->txtask);
+
+	return 0;
+}
+
+void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
+				   struct bcm43xx_xmitstatus *status)
+{
+	struct bcm43xx_pioqueue *queue;
+	struct bcm43xx_pio_txpacket *packet;
+
+	queue = parse_cookie(bcm, status->cookie, &packet);
+	assert(queue);
+//TODO
+if (!queue)
+return;
+	free_txpacket(packet, 1);
+	if (unlikely(queue->tx_suspended)) {
+		queue->tx_suspended = 0;
+		netif_wake_queue(queue->bcm->net_dev);
+	}
+	/* If there are packets on the txqueue, poke the tasklet. */
+	if (!list_empty(&queue->txqueue))
+		tasklet_schedule(&queue->txtask);
+}
+
+static void pio_rx_error(struct bcm43xx_pioqueue *queue,
+			 int clear_buffers,
+			 const char *error)
+{
+	int i;
+
+	printkl("PIO RX error: %s\n", error);
+	bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
+			  BCM43xx_PIO_RXCTL_READY);
+	if (clear_buffers) {
+		assert(queue->mmio_base == BCM43xx_MMIO_PIO1_BASE);
+		for (i = 0; i < 15; i++) {
+			/* Dummy read. */
+			bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+		}
+	}
+}
+
+void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
+{
+	u16 preamble[21] = { 0 };
+	struct bcm43xx_rxhdr *rxhdr;
+	u16 tmp, len, rxflags2;
+	int i, preamble_readwords;
+	struct sk_buff *skb;
+
+return;
+	tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
+	if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) {
+		dprintkl(KERN_ERR PFX "PIO RX: No data available\n");//TODO: remove this printk.
+		return;
+	}
+	bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
+			  BCM43xx_PIO_RXCTL_DATAAVAILABLE);
+
+	for (i = 0; i < 10; i++) {
+		tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
+		if (tmp & BCM43xx_PIO_RXCTL_READY)
+			goto data_ready;
+		udelay(10);
+	}
+	dprintkl(KERN_ERR PFX "PIO RX timed out\n");
+	return;
+data_ready:
+
+//FIXME: endianess in this function.
+	len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA));
+	if (unlikely(len > 0x700)) {
+		pio_rx_error(queue, 0, "len > 0x700");
+		return;
+	}
+	if (unlikely(len == 0 && queue->mmio_base != BCM43xx_MMIO_PIO4_BASE)) {
+		pio_rx_error(queue, 0, "len == 0");
+		return;
+	}
+	preamble[0] = cpu_to_le16(len);
+	if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE)
+		preamble_readwords = 14 / sizeof(u16);
+	else
+		preamble_readwords = 18 / sizeof(u16);
+	for (i = 0; i < preamble_readwords; i++) {
+		tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+		preamble[i + 1] = cpu_to_be16(tmp);//FIXME?
+	}
+	rxhdr = (struct bcm43xx_rxhdr *)preamble;
+	rxflags2 = le16_to_cpu(rxhdr->flags2);
+	if (unlikely(rxflags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) {
+		pio_rx_error(queue,
+			     (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE),
+			     "invalid frame");
+		return;
+	}
+	if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) {
+		/* We received an xmit status. */
+		struct bcm43xx_hwxmitstatus *hw;
+		struct bcm43xx_xmitstatus stat;
+
+		hw = (struct bcm43xx_hwxmitstatus *)(preamble + 1);
+		stat.cookie = le16_to_cpu(hw->cookie);
+		stat.flags = hw->flags;
+		stat.cnt1 = hw->cnt1;
+		stat.cnt2 = hw->cnt2;
+		stat.seq = le16_to_cpu(hw->seq);
+		stat.unknown = le16_to_cpu(hw->unknown);
+
+		bcm43xx_debugfs_log_txstat(queue->bcm, &stat);
+		bcm43xx_pio_handle_xmitstatus(queue->bcm, &stat);
+
+		return;
+	}
+
+	skb = dev_alloc_skb(len);
+	if (unlikely(!skb)) {
+		pio_rx_error(queue, 1, "OOM");
+		return;
+	}
+	skb_put(skb, len);
+	for (i = 0; i < len - 1; i += 2) {
+		tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA));
+		*((u16 *)(skb->data + i)) = tmp;
+	}
+	if (len % 2) {
+		tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+		skb->data[len - 1] = (tmp & 0x00FF);
+		if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME)
+			skb->data[0x20] = (tmp & 0xFF00) >> 8;
+		else
+			skb->data[0x1E] = (tmp & 0xFF00) >> 8;
+	}
+	bcm43xx_rx(queue->bcm, skb, rxhdr);
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
new file mode 100644
index 0000000..970627b
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
@@ -0,0 +1,138 @@
+#ifndef BCM43xx_PIO_H_
+#define BCM43xx_PIO_H_
+
+#include "bcm43xx.h"
+
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+
+
+#define BCM43xx_PIO_TXCTL		0x00
+#define BCM43xx_PIO_TXDATA		0x02
+#define BCM43xx_PIO_TXQBUFSIZE		0x04
+#define BCM43xx_PIO_RXCTL		0x08
+#define BCM43xx_PIO_RXDATA		0x0A
+
+#define BCM43xx_PIO_TXCTL_WRITEHI	(1 << 0)
+#define BCM43xx_PIO_TXCTL_WRITELO	(1 << 1)
+#define BCM43xx_PIO_TXCTL_COMPLETE	(1 << 2)
+#define BCM43xx_PIO_TXCTL_INIT		(1 << 3)
+#define BCM43xx_PIO_TXCTL_SUSPEND	(1 << 7)
+
+#define BCM43xx_PIO_RXCTL_DATAAVAILABLE	(1 << 0)
+#define BCM43xx_PIO_RXCTL_READY		(1 << 1)
+
+/* PIO constants */
+#define BCM43xx_PIO_MAXTXDEVQPACKETS	31
+#define BCM43xx_PIO_TXQADJUST		80
+
+/* PIO tuning knobs */
+#define BCM43xx_PIO_MAXTXPACKETS	256
+
+
+
+#ifdef CONFIG_BCM43XX_PIO
+
+
+struct bcm43xx_pioqueue;
+struct bcm43xx_xmitstatus;
+
+struct bcm43xx_pio_txpacket {
+	struct bcm43xx_pioqueue *queue;
+	struct ieee80211_txb *txb;
+	struct list_head list;
+
+	u8 xmitted_frags;
+	u16 xmitted_octets;
+};
+
+#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->tx_packets_cache)) 
+
+struct bcm43xx_pioqueue {
+	struct bcm43xx_private *bcm;
+	u16 mmio_base;
+
+	u8 tx_suspended:1,
+	   need_workarounds:1; /* Workarounds needed for core.rev < 3 */
+
+	/* Adjusted size of the device internal TX buffer. */
+	u16 tx_devq_size;
+	/* Used octets of the device internal TX buffer. */
+	u16 tx_devq_used;
+	/* Used packet slots in the device internal TX buffer. */
+	u8 tx_devq_packets;
+	/* Packets from the txfree list can
+	 * be taken on incoming TX requests.
+	 */
+	struct list_head txfree;
+	unsigned int nr_txfree;
+	/* Packets on the txqueue are queued,
+	 * but not completely written to the chip, yet.
+	 */
+	struct list_head txqueue;
+	/* Packets on the txrunning queue are completely
+	 * posted to the device. We are waiting for the txstatus.
+	 */
+	struct list_head txrunning;
+	/* Total number or packets sent.
+	 * (This counter can obviously wrap).
+	 */
+	unsigned int nr_tx_packets;
+	struct tasklet_struct txtask;
+	struct bcm43xx_pio_txpacket tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS];
+};
+
+static inline
+u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue,
+		     u16 offset)
+{
+	return bcm43xx_read16(queue->bcm, queue->mmio_base + offset);
+}
+
+static inline
+void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue,
+		       u16 offset, u16 value)
+{
+	bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value);
+}
+
+
+int bcm43xx_pio_init(struct bcm43xx_private *bcm);
+void bcm43xx_pio_free(struct bcm43xx_private *bcm);
+
+int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
+		   struct ieee80211_txb *txb);
+void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
+				   struct bcm43xx_xmitstatus *status);
+void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
+
+#else /* CONFIG_BCM43XX_PIO */
+
+static inline
+int bcm43xx_pio_init(struct bcm43xx_private *bcm)
+{
+	return 0;
+}
+static inline
+void bcm43xx_pio_free(struct bcm43xx_private *bcm)
+{
+}
+static inline
+int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
+		   struct ieee80211_txb *txb)
+{
+	return 0;
+}
+static inline
+void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
+				   struct bcm43xx_xmitstatus *status)
+{
+}
+static inline
+void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
+{
+}
+
+#endif /* CONFIG_BCM43XX_PIO */
+#endif /* BCM43xx_PIO_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
new file mode 100644
index 0000000..3c92b62
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
@@ -0,0 +1,358 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+                     Stefano Brivio <st3@riseup.net>
+                     Michael Buesch <mbuesch@freenet.de>
+                     Danny van Dyk <kugelfang@gentoo.org>
+                     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/delay.h>
+
+#include "bcm43xx.h"
+#include "bcm43xx_power.h"
+#include "bcm43xx_main.h"
+
+
+/* Get max/min slowclock frequency
+ * as described in http://bcm-specs.sipsolutions.net/PowerControl
+ */
+static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm,
+				       int get_max)
+{
+	int limit = 0;
+	int divisor;
+	int selection;
+	int err;
+	u32 tmp;
+	struct bcm43xx_coreinfo *old_core;
+
+	if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
+		goto out;
+	old_core = bcm->current_core;
+	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+	if (err)
+		goto out;
+
+	if (bcm->current_core->rev < 6) {
+		if ((bcm->bustype == BCM43xx_BUSTYPE_PCMCIA) ||
+			(bcm->bustype == BCM43xx_BUSTYPE_SB)) {
+			selection = 1;
+			divisor = 32;
+		} else {
+			err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
+			if (err) {
+				printk(KERN_ERR PFX "clockfreqlimit pcicfg read failure\n");
+				goto out_switchback;
+			}
+			if (tmp & 0x10) {
+				/* PCI */
+				selection = 2;
+				divisor = 64;
+			} else {
+				/* XTAL */
+				selection = 1;
+				divisor = 32;
+			}
+		}
+	} else if (bcm->current_core->rev < 10) {
+		selection = (tmp & 0x07);
+		if (selection) {
+			tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+			divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16));
+		} else
+			divisor = 1;
+	} else {
+		tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL);
+		divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16));
+		selection = 1;
+	}
+	
+	switch (selection) {
+	case 0:
+		/* LPO */
+		if (get_max)
+			limit = 43000;
+		else
+			limit = 25000;
+		break;
+	case 1:
+		/* XTAL */
+		if (get_max)
+			limit = 20200000;
+		else
+			limit = 19800000;
+		break;
+	case 2:
+		/* PCI */
+		if (get_max)
+			limit = 34000000;
+		else
+			limit = 25000000;
+		break;
+	default:
+		assert(0);
+	}
+	limit /= divisor;
+
+out_switchback:
+	err = bcm43xx_switch_core(bcm, old_core);
+	assert(err == 0);
+
+out:
+	return limit;
+}
+
+/* init power control
+ * as described in http://bcm-specs.sipsolutions.net/PowerControl
+ */
+int bcm43xx_pctl_init(struct bcm43xx_private *bcm)
+{
+	int err, maxfreq;
+	struct bcm43xx_coreinfo *old_core;
+
+	if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
+		return 0;
+	old_core = bcm->current_core;
+	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+	if (err == -ENODEV)
+		return 0;
+	if (err)
+		goto out;
+
+	maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
+	bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
+			(maxfreq * 150 + 999999) / 1000000);
+	bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
+			(maxfreq * 15 + 999999) / 1000000);
+
+	err = bcm43xx_switch_core(bcm, old_core);
+	assert(err == 0);
+
+out:
+	return err;
+}
+
+u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm)
+{
+	u16 delay = 0;
+	int err;
+	u32 pll_on_delay;
+	struct bcm43xx_coreinfo *old_core;
+	int minfreq;
+
+	if (bcm->bustype != BCM43xx_BUSTYPE_PCI)
+		goto out;
+	if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
+		goto out;
+	old_core = bcm->current_core;
+	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+	if (err == -ENODEV)
+		goto out;
+
+	minfreq = bcm43xx_pctl_clockfreqlimit(bcm, 0);
+	pll_on_delay = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY);
+	delay = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq;
+
+	err = bcm43xx_switch_core(bcm, old_core);
+	assert(err == 0);
+
+out:
+	return delay;
+}
+
+/* set the powercontrol clock
+ * as described in http://bcm-specs.sipsolutions.net/PowerControl
+ */
+int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode)
+{
+	int err;
+	struct bcm43xx_coreinfo *old_core;
+	u32 tmp;
+
+	old_core = bcm->current_core;
+	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+	if (err == -ENODEV)
+		return 0;
+	if (err)
+		goto out;
+	
+	if (bcm->core_chipcommon.rev < 6) {
+		if (mode == BCM43xx_PCTL_CLK_FAST) {
+			err = bcm43xx_pctl_set_crystal(bcm, 1);
+			if (err)
+				goto out;
+		}
+	} else {
+		if ((bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) &&
+			(bcm->core_chipcommon.rev < 10)) {
+			switch (mode) {
+			case BCM43xx_PCTL_CLK_FAST:
+				tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+				tmp = (tmp & ~BCM43xx_PCTL_FORCE_SLOW) | BCM43xx_PCTL_FORCE_PLL;
+				bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
+				break;
+			case BCM43xx_PCTL_CLK_SLOW:
+				tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+				tmp |= BCM43xx_PCTL_FORCE_SLOW;
+				bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
+				break;
+			case BCM43xx_PCTL_CLK_DYNAMIC:
+				tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+				tmp &= ~BCM43xx_PCTL_FORCE_SLOW;
+				tmp |= BCM43xx_PCTL_FORCE_PLL;
+				tmp &= ~BCM43xx_PCTL_DYN_XTAL;
+				bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
+			}
+		}
+	}
+	
+	err = bcm43xx_switch_core(bcm, old_core);
+	assert(err == 0);
+
+out:
+	return err;
+}
+
+int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on)
+{
+	int err;
+	u32 in, out, outenable;
+
+	err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_IN, &in);
+	if (err)
+		goto err_pci;
+	err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &out);
+	if (err)
+		goto err_pci;
+	err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUTENABLE, &outenable);
+	if (err)
+		goto err_pci;
+
+	outenable |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN);
+
+	if (on) {
+		if (in & 0x40)
+			return 0;
+
+		out |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN);
+
+		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
+		if (err)
+			goto err_pci;
+		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable);
+		if (err)
+			goto err_pci;
+		udelay(1000);
+
+		out &= ~BCM43xx_PCTL_PLL_POWERDOWN;
+		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
+		if (err)
+			goto err_pci;
+		udelay(5000);
+	} else {
+		if (bcm->current_core->rev < 5)
+			return 0;
+		if (bcm->sprom.boardflags & BCM43xx_BFL_XTAL_NOSLOW)
+			return 0;
+
+/*		XXX: Why BCM43xx_MMIO_RADIO_HWENABLED_xx can't be read at this time?
+ *		err = bcm43xx_switch_core(bcm, bcm->active_80211_core);
+ *		if (err)
+ *			return err;
+ *		if (((bcm->current_core->rev >= 3) &&
+ *			(bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI) & (1 << 16))) ||
+ *		      ((bcm->current_core->rev < 3) &&
+ *			!(bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO) & (1 << 4))))
+ *			return 0;
+ *		err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+ *		if (err)
+ *			return err;
+ */
+		
+		err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
+		if (err)
+			goto out;
+		out &= ~BCM43xx_PCTL_XTAL_POWERUP;
+		out |= BCM43xx_PCTL_PLL_POWERDOWN;
+		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
+		if (err)
+			goto err_pci;
+		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable);
+		if (err)
+			goto err_pci;
+	}
+
+out:
+	return err;
+
+err_pci:
+	printk(KERN_ERR PFX "Error: pctl_set_clock() could not access PCI config space!\n");
+	err = -EBUSY;
+	goto out;
+}
+
+/* Set the PowerSavingControlBits.
+ * Bitvalues:
+ *   0  => unset the bit
+ *   1  => set the bit
+ *   -1 => calculate the bit
+ */
+void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm,
+				   int bit25, int bit26)
+{
+	int i;
+	u32 status;
+
+//FIXME: Force 25 to off and 26 to on for now:
+bit25 = 0;
+bit26 = 1;
+
+	if (bit25 == -1) {
+		//TODO: If powersave is not off and FIXME is not set and we are not in adhoc
+		//	and thus is not an AP and we are associated, set bit 25
+	}
+	if (bit26 == -1) {
+		//TODO: If the device is awake or this is an AP, or we are scanning, or FIXME,
+		//	or we are associated, or FIXME, or the latest PS-Poll packet sent was
+		//	successful, set bit26
+	}
+	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+	if (bit25)
+		status |= BCM43xx_SBF_PS1;
+	else
+		status &= ~BCM43xx_SBF_PS1;
+	if (bit26)
+		status |= BCM43xx_SBF_PS2;
+	else
+		status &= ~BCM43xx_SBF_PS2;
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+	if (bit26 && bcm->current_core->rev >= 5) {
+		for (i = 0; i < 100; i++) {
+			if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0040) != 4)
+				break;
+			udelay(10);
+		}
+	}
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.h b/drivers/net/wireless/bcm43xx/bcm43xx_power.h
new file mode 100644
index 0000000..5f63640
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.h
@@ -0,0 +1,47 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+                     Stefano Brivio <st3@riseup.net>
+                     Michael Buesch <mbuesch@freenet.de>
+                     Danny van Dyk <kugelfang@gentoo.org>
+                     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef BCM43xx_POWER_H_
+#define BCM43xx_POWER_H_
+
+#include <linux/types.h>
+
+
+struct bcm43xx_private;
+
+int bcm43xx_pctl_init(struct bcm43xx_private *bcm);
+int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode);
+int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on);
+u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm);
+
+void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm,
+				   int bit25, int bit26);
+
+#endif /* BCM43xx_POWER_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
new file mode 100644
index 0000000..af5c0bf
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
@@ -0,0 +1,2026 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+                     Stefano Brivio <st3@riseup.net>
+                     Michael Buesch <mbuesch@freenet.de>
+                     Danny van Dyk <kugelfang@gentoo.org>
+                     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/delay.h>
+
+#include "bcm43xx.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_phy.h"
+#include "bcm43xx_radio.h"
+#include "bcm43xx_ilt.h"
+
+
+/* Table for bcm43xx_radio_calibrationvalue() */
+static const u16 rcc_table[16] = {
+	0x0002, 0x0003, 0x0001, 0x000F,
+	0x0006, 0x0007, 0x0005, 0x000F,
+	0x000A, 0x000B, 0x0009, 0x000F,
+	0x000E, 0x000F, 0x000D, 0x000F,
+};
+
+/* Reverse the bits of a 4bit value.
+ * Example:  1101 is flipped 1011
+ */
+static u16 flip_4bit(u16 value)
+{
+	u16 flipped = 0x0000;
+
+	assert((value & ~0x000F) == 0x0000);
+
+	flipped |= (value & 0x0001) << 3;
+	flipped |= (value & 0x0002) << 1;
+	flipped |= (value & 0x0004) >> 1;
+	flipped |= (value & 0x0008) >> 3;
+
+	return flipped;
+}
+
+/* Get the freq, as it has to be written to the device. */
+static inline
+u16 channel2freq_bg(u8 channel)
+{
+	/* Frequencies are given as frequencies_bg[index] + 2.4GHz
+	 * Starting with channel 1
+	 */
+	static const u16 frequencies_bg[14] = {
+		12, 17, 22, 27,
+		32, 37, 42, 47,
+		52, 57, 62, 67,
+		72, 84,
+	};
+
+	assert(channel >= 1 && channel <= 14);
+
+	return frequencies_bg[channel - 1];
+}
+
+/* Get the freq, as it has to be written to the device. */
+static inline
+u16 channel2freq_a(u8 channel)
+{
+	assert(channel <= 200);
+
+	return (5000 + 5 * channel);
+}
+
+void bcm43xx_radio_lock(struct bcm43xx_private *bcm)
+{
+	u32 status;
+
+	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+	status |= BCM43xx_SBF_RADIOREG_LOCK;
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+	mmiowb();
+	udelay(10);
+}
+
+void bcm43xx_radio_unlock(struct bcm43xx_private *bcm)
+{
+	u32 status;
+
+	bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); /* dummy read */
+	status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+	status &= ~BCM43xx_SBF_RADIOREG_LOCK;
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+	mmiowb();
+}
+
+u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+
+	switch (phy->type) {
+	case BCM43xx_PHYTYPE_A:
+		offset |= 0x0040;
+		break;
+	case BCM43xx_PHYTYPE_B:
+		if (radio->version == 0x2053) {
+			if (offset < 0x70)
+				offset += 0x80;
+			else if (offset < 0x80)
+				offset += 0x70;
+		} else if (radio->version == 0x2050) {
+			offset |= 0x80;
+		} else
+			assert(0);
+		break;
+	case BCM43xx_PHYTYPE_G:
+		offset |= 0x80;
+		break;
+	}
+
+	bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset);
+	return bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW);
+}
+
+void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val)
+{
+	bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset);
+	mmiowb();
+	bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW, val);
+}
+
+static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm,
+				  s16 first, s16 second, s16 third)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	u16 i;
+	u16 start = 0x08, end = 0x18;
+	u16 offset = 0x0400;
+	u16 tmp;
+
+	if (phy->rev <= 1) {
+		offset = 0x5000;
+		start = 0x10;
+		end = 0x20;
+	}
+
+	for (i = 0; i < 4; i++)
+		bcm43xx_ilt_write(bcm, offset + i, first);
+
+	for (i = start; i < end; i++)
+		bcm43xx_ilt_write(bcm, offset + i, second);
+
+	if (third != -1) {
+		tmp = ((u16)third << 14) | ((u16)third << 6);
+		bcm43xx_phy_write(bcm, 0x04A0,
+		                  (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | tmp);
+		bcm43xx_phy_write(bcm, 0x04A1,
+		                  (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | tmp);
+		bcm43xx_phy_write(bcm, 0x04A2,
+		                  (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | tmp);
+	}
+	bcm43xx_dummy_transmission(bcm);
+}
+
+static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	u16 i, tmp;
+	u16 offset = 0x0400;
+	u16 start = 0x0008, end = 0x0018;
+
+	if (phy->rev <= 1) {
+		offset = 0x5000;
+		start = 0x0010;
+		end = 0x0020;
+	}
+
+	for (i = 0; i < 4; i++) {
+		tmp = (i & 0xFFFC);
+		tmp |= (i & 0x0001) << 1;
+		tmp |= (i & 0x0002) >> 1;
+
+		bcm43xx_ilt_write(bcm, offset + i, tmp);
+	}
+
+	for (i = start; i < end; i++)
+		bcm43xx_ilt_write(bcm, offset + i, i - start);
+
+	bcm43xx_phy_write(bcm, 0x04A0,
+	                  (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | 0x4040);
+	bcm43xx_phy_write(bcm, 0x04A1,
+	                  (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | 0x4040);
+	bcm43xx_phy_write(bcm, 0x04A2,
+	                  (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | 0x4000);
+	bcm43xx_dummy_transmission(bcm);
+}
+
+/* Synthetic PU workaround */
+static void bcm43xx_synth_pu_workaround(struct bcm43xx_private *bcm, u8 channel)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	
+	if (radio->version != 0x2050 || radio->revision >= 6) {
+		/* We do not need the workaround. */
+		return;
+	}
+
+	if (channel <= 10) {
+		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+				channel2freq_bg(channel + 4));
+	} else {
+		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+				channel2freq_bg(1));
+	}
+	udelay(100);
+	bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+			channel2freq_bg(channel));
+}
+
+u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u8 ret = 0;
+	u16 saved, rssi, temp;
+	int i, j = 0;
+
+	saved = bcm43xx_phy_read(bcm, 0x0403);
+	bcm43xx_radio_selectchannel(bcm, channel, 0);
+	bcm43xx_phy_write(bcm, 0x0403, (saved & 0xFFF8) | 5);
+	if (radio->aci_hw_rssi)
+		rssi = bcm43xx_phy_read(bcm, 0x048A) & 0x3F;
+	else
+		rssi = saved & 0x3F;
+	/* clamp temp to signed 5bit */
+	if (rssi > 32)
+		rssi -= 64;
+	for (i = 0;i < 100; i++) {
+		temp = (bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x3F;
+		if (temp > 32)
+			temp -= 64;
+		if (temp < rssi)
+			j++;
+		if (j >= 20)
+			ret = 1;
+	}
+	bcm43xx_phy_write(bcm, 0x0403, saved);
+
+	return ret;
+}
+
+u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u8 ret[13];
+	unsigned int channel = radio->channel;
+	unsigned int i, j, start, end;
+	unsigned long phylock_flags;
+
+	if (!((phy->type == BCM43xx_PHYTYPE_G) && (phy->rev > 0)))
+		return 0;
+
+	bcm43xx_phy_lock(bcm, phylock_flags);
+	bcm43xx_radio_lock(bcm);
+	bcm43xx_phy_write(bcm, 0x0802,
+	                  bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC);
+	bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+	                  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF);
+	bcm43xx_set_all_gains(bcm, 3, 8, 1);
+
+	start = (channel - 5 > 0) ? channel - 5 : 1;
+	end = (channel + 5 < 14) ? channel + 5 : 13;
+
+	for (i = start; i <= end; i++) {
+		if (abs(channel - i) > 2)
+			ret[i-1] = bcm43xx_radio_aci_detect(bcm, i);
+	}
+	bcm43xx_radio_selectchannel(bcm, channel, 0);
+	bcm43xx_phy_write(bcm, 0x0802,
+	                  (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC) | 0x0003);
+	bcm43xx_phy_write(bcm, 0x0403,
+	                  bcm43xx_phy_read(bcm, 0x0403) & 0xFFF8);
+	bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+	                  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000);
+	bcm43xx_set_original_gains(bcm);
+	for (i = 0; i < 13; i++) {
+		if (!ret[i])
+			continue;
+		end = (i + 5 < 13) ? i + 5 : 13;
+		for (j = i; j < end; j++)
+			ret[j] = 1;
+	}
+	bcm43xx_radio_unlock(bcm);
+	bcm43xx_phy_unlock(bcm, phylock_flags);
+
+	return ret[channel - 1];
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val)
+{
+	bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset);
+	mmiowb();
+	bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_DATA, (u16)val);
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset)
+{
+	u16 val;
+
+	bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset);
+	val = bcm43xx_phy_read(bcm, BCM43xx_PHY_NRSSILT_DATA);
+
+	return (s16)val;
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val)
+{
+	u16 i;
+	s16 tmp;
+
+	for (i = 0; i < 64; i++) {
+		tmp = bcm43xx_nrssi_hw_read(bcm, i);
+		tmp -= val;
+		tmp = limit_value(tmp, -32, 31);
+		bcm43xx_nrssi_hw_write(bcm, i, tmp);
+	}
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	s16 i, delta;
+	s32 tmp;
+
+	delta = 0x1F - radio->nrssi[0];
+	for (i = 0; i < 64; i++) {
+		tmp = (i - delta) * radio->nrssislope;
+		tmp /= 0x10000;
+		tmp += 0x3A;
+		tmp = limit_value(tmp, 0, 0x3F);
+		radio->nrssi_lt[i] = tmp;
+	}
+}
+
+static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	u16 backup[20] = { 0 };
+	s16 v47F;
+	u16 i;
+	u16 saved = 0xFFFF;
+
+	backup[0] = bcm43xx_phy_read(bcm, 0x0001);
+	backup[1] = bcm43xx_phy_read(bcm, 0x0811);
+	backup[2] = bcm43xx_phy_read(bcm, 0x0812);
+	backup[3] = bcm43xx_phy_read(bcm, 0x0814);
+	backup[4] = bcm43xx_phy_read(bcm, 0x0815);
+	backup[5] = bcm43xx_phy_read(bcm, 0x005A);
+	backup[6] = bcm43xx_phy_read(bcm, 0x0059);
+	backup[7] = bcm43xx_phy_read(bcm, 0x0058);
+	backup[8] = bcm43xx_phy_read(bcm, 0x000A);
+	backup[9] = bcm43xx_phy_read(bcm, 0x0003);
+	backup[10] = bcm43xx_radio_read16(bcm, 0x007A);
+	backup[11] = bcm43xx_radio_read16(bcm, 0x0043);
+
+	bcm43xx_phy_write(bcm, 0x0429,
+			  bcm43xx_phy_read(bcm, 0x0429) & 0x7FFF);
+	bcm43xx_phy_write(bcm, 0x0001,
+			  (bcm43xx_phy_read(bcm, 0x0001) & 0x3FFF) | 0x4000);
+	bcm43xx_phy_write(bcm, 0x0811,
+			  bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
+	bcm43xx_phy_write(bcm, 0x0812,
+			  (bcm43xx_phy_read(bcm, 0x0812) & 0xFFF3) | 0x0004);
+	bcm43xx_phy_write(bcm, 0x0802,
+			  bcm43xx_phy_read(bcm, 0x0802) & ~(0x1 | 0x2));
+	if (phy->rev >= 6) {
+		backup[12] = bcm43xx_phy_read(bcm, 0x002E);
+		backup[13] = bcm43xx_phy_read(bcm, 0x002F);
+		backup[14] = bcm43xx_phy_read(bcm, 0x080F);
+		backup[15] = bcm43xx_phy_read(bcm, 0x0810);
+		backup[16] = bcm43xx_phy_read(bcm, 0x0801);
+		backup[17] = bcm43xx_phy_read(bcm, 0x0060);
+		backup[18] = bcm43xx_phy_read(bcm, 0x0014);
+		backup[19] = bcm43xx_phy_read(bcm, 0x0478);
+
+		bcm43xx_phy_write(bcm, 0x002E, 0);
+		bcm43xx_phy_write(bcm, 0x002F, 0);
+		bcm43xx_phy_write(bcm, 0x080F, 0);
+		bcm43xx_phy_write(bcm, 0x0810, 0);
+		bcm43xx_phy_write(bcm, 0x0478,
+				  bcm43xx_phy_read(bcm, 0x0478) | 0x0100);
+		bcm43xx_phy_write(bcm, 0x0801,
+				  bcm43xx_phy_read(bcm, 0x0801) | 0x0040);
+		bcm43xx_phy_write(bcm, 0x0060,
+				  bcm43xx_phy_read(bcm, 0x0060) | 0x0040);
+		bcm43xx_phy_write(bcm, 0x0014,
+				  bcm43xx_phy_read(bcm, 0x0014) | 0x0200);
+	}
+	bcm43xx_radio_write16(bcm, 0x007A,
+			      bcm43xx_radio_read16(bcm, 0x007A) | 0x0070);
+	bcm43xx_radio_write16(bcm, 0x007A,
+			      bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
+	udelay(30);
+
+	v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+	if (v47F >= 0x20)
+		v47F -= 0x40;
+	if (v47F == 31) {
+		for (i = 7; i >= 4; i--) {
+			bcm43xx_radio_write16(bcm, 0x007B, i);
+			udelay(20);
+			v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+			if (v47F >= 0x20)
+				v47F -= 0x40;
+			if (v47F < 31 && saved == 0xFFFF)
+				saved = i;
+		}
+		if (saved == 0xFFFF)
+			saved = 4;
+	} else {
+		bcm43xx_radio_write16(bcm, 0x007A,
+				      bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
+		bcm43xx_phy_write(bcm, 0x0814,
+				  bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
+		bcm43xx_phy_write(bcm, 0x0815,
+				  bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
+		bcm43xx_phy_write(bcm, 0x0811,
+				  bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
+		bcm43xx_phy_write(bcm, 0x0812,
+				  bcm43xx_phy_read(bcm, 0x0812) | 0x000C);
+		bcm43xx_phy_write(bcm, 0x0811,
+				  bcm43xx_phy_read(bcm, 0x0811) | 0x0030);
+		bcm43xx_phy_write(bcm, 0x0812,
+				  bcm43xx_phy_read(bcm, 0x0812) | 0x0030);
+		bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+		bcm43xx_phy_write(bcm, 0x0059, 0x0810);
+		bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+		if (phy->rev == 0) {
+			bcm43xx_phy_write(bcm, 0x0003, 0x0122);
+		} else {
+			bcm43xx_phy_write(bcm, 0x000A,
+					  bcm43xx_phy_read(bcm, 0x000A)
+					  | 0x2000);
+		}
+		bcm43xx_phy_write(bcm, 0x0814,
+				  bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
+		bcm43xx_phy_write(bcm, 0x0815,
+				  bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
+		bcm43xx_phy_write(bcm, 0x0003,
+				  (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F)
+				  | 0x0040);
+		bcm43xx_radio_write16(bcm, 0x007A,
+				      bcm43xx_radio_read16(bcm, 0x007A) | 0x000F);
+		bcm43xx_set_all_gains(bcm, 3, 0, 1);
+		bcm43xx_radio_write16(bcm, 0x0043,
+				      (bcm43xx_radio_read16(bcm, 0x0043)
+				       & 0x00F0) | 0x000F);
+		udelay(30);
+		v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+		if (v47F >= 0x20)
+			v47F -= 0x40;
+		if (v47F == -32) {
+			for (i = 0; i < 4; i++) {
+				bcm43xx_radio_write16(bcm, 0x007B, i);
+				udelay(20);
+				v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+				if (v47F >= 0x20)
+					v47F -= 0x40;
+				if (v47F > -31 && saved == 0xFFFF)
+					saved = i;
+			}
+			if (saved == 0xFFFF)
+				saved = 3;
+		} else
+			saved = 0;
+	}
+	bcm43xx_radio_write16(bcm, 0x007B, saved);
+
+	if (phy->rev >= 6) {
+		bcm43xx_phy_write(bcm, 0x002E, backup[12]);
+		bcm43xx_phy_write(bcm, 0x002F, backup[13]);
+		bcm43xx_phy_write(bcm, 0x080F, backup[14]);
+		bcm43xx_phy_write(bcm, 0x0810, backup[15]);
+	}
+	bcm43xx_phy_write(bcm, 0x0814, backup[3]);
+	bcm43xx_phy_write(bcm, 0x0815, backup[4]);
+	bcm43xx_phy_write(bcm, 0x005A, backup[5]);
+	bcm43xx_phy_write(bcm, 0x0059, backup[6]);
+	bcm43xx_phy_write(bcm, 0x0058, backup[7]);
+	bcm43xx_phy_write(bcm, 0x000A, backup[8]);
+	bcm43xx_phy_write(bcm, 0x0003, backup[9]);
+	bcm43xx_radio_write16(bcm, 0x0043, backup[11]);
+	bcm43xx_radio_write16(bcm, 0x007A, backup[10]);
+	bcm43xx_phy_write(bcm, 0x0802,
+			  bcm43xx_phy_read(bcm, 0x0802) | 0x1 | 0x2);
+	bcm43xx_phy_write(bcm, 0x0429,
+			  bcm43xx_phy_read(bcm, 0x0429) | 0x8000);
+	bcm43xx_set_original_gains(bcm);
+	if (phy->rev >= 6) {
+		bcm43xx_phy_write(bcm, 0x0801, backup[16]);
+		bcm43xx_phy_write(bcm, 0x0060, backup[17]);
+		bcm43xx_phy_write(bcm, 0x0014, backup[18]);
+		bcm43xx_phy_write(bcm, 0x0478, backup[19]);
+	}
+	bcm43xx_phy_write(bcm, 0x0001, backup[0]);
+	bcm43xx_phy_write(bcm, 0x0812, backup[2]);
+	bcm43xx_phy_write(bcm, 0x0811, backup[1]);
+}
+
+void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 backup[18] = { 0 };
+	u16 tmp;
+	s16 nrssi0, nrssi1;
+
+	switch (phy->type) {
+	case BCM43xx_PHYTYPE_B:
+		backup[0] = bcm43xx_radio_read16(bcm, 0x007A);
+		backup[1] = bcm43xx_radio_read16(bcm, 0x0052);
+		backup[2] = bcm43xx_radio_read16(bcm, 0x0043);
+		backup[3] = bcm43xx_phy_read(bcm, 0x0030);
+		backup[4] = bcm43xx_phy_read(bcm, 0x0026);
+		backup[5] = bcm43xx_phy_read(bcm, 0x0015);
+		backup[6] = bcm43xx_phy_read(bcm, 0x002A);
+		backup[7] = bcm43xx_phy_read(bcm, 0x0020);
+		backup[8] = bcm43xx_phy_read(bcm, 0x005A);
+		backup[9] = bcm43xx_phy_read(bcm, 0x0059);
+		backup[10] = bcm43xx_phy_read(bcm, 0x0058);
+		backup[11] = bcm43xx_read16(bcm, 0x03E2);
+		backup[12] = bcm43xx_read16(bcm, 0x03E6);
+		backup[13] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+
+		tmp  = bcm43xx_radio_read16(bcm, 0x007A);
+		tmp &= (phy->rev >= 5) ? 0x007F : 0x000F;
+		bcm43xx_radio_write16(bcm, 0x007A, tmp);
+		bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
+		bcm43xx_write16(bcm, 0x03EC, 0x7F7F);
+		bcm43xx_phy_write(bcm, 0x0026, 0x0000);
+		bcm43xx_phy_write(bcm, 0x0015,
+				  bcm43xx_phy_read(bcm, 0x0015) | 0x0020);
+		bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
+		bcm43xx_radio_write16(bcm, 0x007A,
+				      bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
+
+		nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027);
+		bcm43xx_radio_write16(bcm, 0x007A,
+				      bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
+		if (phy->rev >= 2) {
+			bcm43xx_write16(bcm, 0x03E6, 0x0040);
+		} else if (phy->rev == 0) {
+			bcm43xx_write16(bcm, 0x03E6, 0x0122);
+		} else {
+			bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+					bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) & 0x2000);
+		}
+		bcm43xx_phy_write(bcm, 0x0020, 0x3F3F);
+		bcm43xx_phy_write(bcm, 0x0015, 0xF330);
+		bcm43xx_radio_write16(bcm, 0x005A, 0x0060);
+		bcm43xx_radio_write16(bcm, 0x0043,
+				      bcm43xx_radio_read16(bcm, 0x0043) & 0x00F0);
+		bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+		bcm43xx_phy_write(bcm, 0x0059, 0x0810);
+		bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+		udelay(20);
+
+		nrssi1 = (s16)bcm43xx_phy_read(bcm, 0x0027);
+		bcm43xx_phy_write(bcm, 0x0030, backup[3]);
+		bcm43xx_radio_write16(bcm, 0x007A, backup[0]);
+		bcm43xx_write16(bcm, 0x03E2, backup[11]);
+		bcm43xx_phy_write(bcm, 0x0026, backup[4]);
+		bcm43xx_phy_write(bcm, 0x0015, backup[5]);
+		bcm43xx_phy_write(bcm, 0x002A, backup[6]);
+		bcm43xx_synth_pu_workaround(bcm, radio->channel);
+		if (phy->rev != 0)
+			bcm43xx_write16(bcm, 0x03F4, backup[13]);
+
+		bcm43xx_phy_write(bcm, 0x0020, backup[7]);
+		bcm43xx_phy_write(bcm, 0x005A, backup[8]);
+		bcm43xx_phy_write(bcm, 0x0059, backup[9]);
+		bcm43xx_phy_write(bcm, 0x0058, backup[10]);
+		bcm43xx_radio_write16(bcm, 0x0052, backup[1]);
+		bcm43xx_radio_write16(bcm, 0x0043, backup[2]);
+
+		if (nrssi0 == nrssi1)
+			radio->nrssislope = 0x00010000;
+		else 
+			radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
+
+		if (nrssi0 <= -4) {
+			radio->nrssi[0] = nrssi0;
+			radio->nrssi[1] = nrssi1;
+		}
+		break;
+	case BCM43xx_PHYTYPE_G:
+		if (radio->revision >= 9)
+			return;
+		if (radio->revision == 8)
+			bcm43xx_calc_nrssi_offset(bcm);
+
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+				  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF);
+		bcm43xx_phy_write(bcm, 0x0802,
+				  bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC);
+		backup[7] = bcm43xx_read16(bcm, 0x03E2);
+		bcm43xx_write16(bcm, 0x03E2,
+				bcm43xx_read16(bcm, 0x03E2) | 0x8000);
+		backup[0] = bcm43xx_radio_read16(bcm, 0x007A);
+		backup[1] = bcm43xx_radio_read16(bcm, 0x0052);
+		backup[2] = bcm43xx_radio_read16(bcm, 0x0043);
+		backup[3] = bcm43xx_phy_read(bcm, 0x0015);
+		backup[4] = bcm43xx_phy_read(bcm, 0x005A);
+		backup[5] = bcm43xx_phy_read(bcm, 0x0059);
+		backup[6] = bcm43xx_phy_read(bcm, 0x0058);
+		backup[8] = bcm43xx_read16(bcm, 0x03E6);
+		backup[9] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+		if (phy->rev >= 3) {
+			backup[10] = bcm43xx_phy_read(bcm, 0x002E);
+			backup[11] = bcm43xx_phy_read(bcm, 0x002F);
+			backup[12] = bcm43xx_phy_read(bcm, 0x080F);
+			backup[13] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_LO_CONTROL);
+			backup[14] = bcm43xx_phy_read(bcm, 0x0801);
+			backup[15] = bcm43xx_phy_read(bcm, 0x0060);
+			backup[16] = bcm43xx_phy_read(bcm, 0x0014);
+			backup[17] = bcm43xx_phy_read(bcm, 0x0478);
+			bcm43xx_phy_write(bcm, 0x002E, 0);
+			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, 0);
+			switch (phy->rev) {
+			case 4: case 6: case 7:
+				bcm43xx_phy_write(bcm, 0x0478,
+						  bcm43xx_phy_read(bcm, 0x0478)
+						  | 0x0100);
+				bcm43xx_phy_write(bcm, 0x0801,
+						  bcm43xx_phy_read(bcm, 0x0801)
+						  | 0x0040);
+				break;
+			case 3: case 5:
+				bcm43xx_phy_write(bcm, 0x0801,
+						  bcm43xx_phy_read(bcm, 0x0801)
+						  & 0xFFBF);
+				break;
+			}
+			bcm43xx_phy_write(bcm, 0x0060,
+					  bcm43xx_phy_read(bcm, 0x0060)
+					  | 0x0040);
+			bcm43xx_phy_write(bcm, 0x0014,
+					  bcm43xx_phy_read(bcm, 0x0014)
+					  | 0x0200);
+		}
+		bcm43xx_radio_write16(bcm, 0x007A,
+				      bcm43xx_radio_read16(bcm, 0x007A) | 0x0070);
+		bcm43xx_set_all_gains(bcm, 0, 8, 0);
+		bcm43xx_radio_write16(bcm, 0x007A,
+				      bcm43xx_radio_read16(bcm, 0x007A) & 0x00F7);
+		if (phy->rev >= 2) {
+			bcm43xx_phy_write(bcm, 0x0811,
+					  (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0030);
+			bcm43xx_phy_write(bcm, 0x0812,
+					  (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0010);
+		}
+		bcm43xx_radio_write16(bcm, 0x007A,
+				      bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
+		udelay(20);
+
+		nrssi0 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+		if (nrssi0 >= 0x0020)
+			nrssi0 -= 0x0040;
+
+		bcm43xx_radio_write16(bcm, 0x007A,
+				      bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
+		if (phy->rev >= 2) {
+			bcm43xx_phy_write(bcm, 0x0003,
+					  (bcm43xx_phy_read(bcm, 0x0003)
+					   & 0xFF9F) | 0x0040);
+		}
+
+		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+				bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
+				| 0x2000);
+		bcm43xx_radio_write16(bcm, 0x007A,
+				      bcm43xx_radio_read16(bcm, 0x007A) | 0x000F);
+		bcm43xx_phy_write(bcm, 0x0015, 0xF330);
+		if (phy->rev >= 2) {
+			bcm43xx_phy_write(bcm, 0x0812,
+					  (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0020);
+			bcm43xx_phy_write(bcm, 0x0811,
+					  (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0020);
+		}
+
+		bcm43xx_set_all_gains(bcm, 3, 0, 1);
+		if (radio->revision == 8) {
+			bcm43xx_radio_write16(bcm, 0x0043, 0x001F);
+		} else {
+			tmp = bcm43xx_radio_read16(bcm, 0x0052) & 0xFF0F;
+			bcm43xx_radio_write16(bcm, 0x0052, tmp | 0x0060);
+			tmp = bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0;
+			bcm43xx_radio_write16(bcm, 0x0043, tmp | 0x0009);
+		}
+		bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+		bcm43xx_phy_write(bcm, 0x0059, 0x0810);
+		bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+		udelay(20);
+		nrssi1 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+		if (nrssi1 >= 0x0020)
+			nrssi1 -= 0x0040;
+		if (nrssi0 == nrssi1)
+			radio->nrssislope = 0x00010000;
+		else
+			radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
+		if (nrssi0 >= -4) {
+			radio->nrssi[0] = nrssi1;
+			radio->nrssi[1] = nrssi0;
+		}
+		if (phy->rev >= 3) {
+			bcm43xx_phy_write(bcm, 0x002E, backup[10]);
+			bcm43xx_phy_write(bcm, 0x002F, backup[11]);
+			bcm43xx_phy_write(bcm, 0x080F, backup[12]);
+			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, backup[13]);
+		}
+		if (phy->rev >= 2) {
+			bcm43xx_phy_write(bcm, 0x0812,
+					  bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF);
+			bcm43xx_phy_write(bcm, 0x0811,
+					  bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF);
+		}
+
+		bcm43xx_radio_write16(bcm, 0x007A, backup[0]);
+		bcm43xx_radio_write16(bcm, 0x0052, backup[1]);
+		bcm43xx_radio_write16(bcm, 0x0043, backup[2]);
+		bcm43xx_write16(bcm, 0x03E2, backup[7]);
+		bcm43xx_write16(bcm, 0x03E6, backup[8]);
+		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[9]);
+		bcm43xx_phy_write(bcm, 0x0015, backup[3]);
+		bcm43xx_phy_write(bcm, 0x005A, backup[4]);
+		bcm43xx_phy_write(bcm, 0x0059, backup[5]);
+		bcm43xx_phy_write(bcm, 0x0058, backup[6]);
+		bcm43xx_synth_pu_workaround(bcm, radio->channel);
+		bcm43xx_phy_write(bcm, 0x0802,
+				  bcm43xx_phy_read(bcm, 0x0802) | (0x0001 | 0x0002));
+		bcm43xx_set_original_gains(bcm);
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+				  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000);
+		if (phy->rev >= 3) {
+			bcm43xx_phy_write(bcm, 0x0801, backup[14]);
+			bcm43xx_phy_write(bcm, 0x0060, backup[15]);
+			bcm43xx_phy_write(bcm, 0x0014, backup[16]);
+			bcm43xx_phy_write(bcm, 0x0478, backup[17]);
+		}
+		bcm43xx_nrssi_mem_update(bcm);
+		bcm43xx_calc_nrssi_threshold(bcm);
+		break;
+	default:
+		assert(0);
+	}
+}
+
+void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	s32 threshold;
+	s32 a, b;
+	s16 tmp16;
+	u16 tmp_u16;
+
+	switch (phy->type) {
+	case BCM43xx_PHYTYPE_B: {
+		if (radio->version != 0x2050)
+			return;
+		if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI))
+			return;
+
+		if (radio->revision >= 6) {
+			threshold = (radio->nrssi[1] - radio->nrssi[0]) * 32;
+			threshold += 20 * (radio->nrssi[0] + 1);
+			threshold /= 40;
+		} else
+			threshold = radio->nrssi[1] - 5;
+
+		threshold = limit_value(threshold, 0, 0x3E);
+		bcm43xx_phy_read(bcm, 0x0020); /* dummy read */
+		bcm43xx_phy_write(bcm, 0x0020, (((u16)threshold) << 8) | 0x001C);
+
+		if (radio->revision >= 6) {
+			bcm43xx_phy_write(bcm, 0x0087, 0x0E0D);
+			bcm43xx_phy_write(bcm, 0x0086, 0x0C0B);
+			bcm43xx_phy_write(bcm, 0x0085, 0x0A09);
+			bcm43xx_phy_write(bcm, 0x0084, 0x0808);
+			bcm43xx_phy_write(bcm, 0x0083, 0x0808);
+			bcm43xx_phy_write(bcm, 0x0082, 0x0604);
+			bcm43xx_phy_write(bcm, 0x0081, 0x0302);
+			bcm43xx_phy_write(bcm, 0x0080, 0x0100);
+		}
+		break;
+	}
+	case BCM43xx_PHYTYPE_G:
+		if (!phy->connected ||
+		    !(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {
+			tmp16 = bcm43xx_nrssi_hw_read(bcm, 0x20);
+			if (tmp16 >= 0x20)
+				tmp16 -= 0x40;
+			if (tmp16 < 3) {
+				bcm43xx_phy_write(bcm, 0x048A,
+						  (bcm43xx_phy_read(bcm, 0x048A)
+						   & 0xF000) | 0x09EB);
+			} else {
+				bcm43xx_phy_write(bcm, 0x048A,
+						  (bcm43xx_phy_read(bcm, 0x048A)
+						   & 0xF000) | 0x0AED);
+			}
+		} else {
+			if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) {
+				a = 0xE;
+				b = 0xA;
+			} else if (!radio->aci_wlan_automatic && radio->aci_enable) {
+				a = 0x13;
+				b = 0x12;
+			} else {
+				a = 0xE;
+				b = 0x11;
+			}
+
+			a = a * (radio->nrssi[1] - radio->nrssi[0]);
+			a += (radio->nrssi[0] << 6);
+			if (a < 32)
+				a += 31;
+			else
+				a += 32;
+			a = a >> 6;
+			a = limit_value(a, -31, 31);
+
+			b = b * (radio->nrssi[1] - radio->nrssi[0]);
+			b += (radio->nrssi[0] << 6);
+			if (b < 32)
+				b += 31;
+			else
+				b += 32;
+			b = b >> 6;
+			b = limit_value(b, -31, 31);
+
+			tmp_u16 = bcm43xx_phy_read(bcm, 0x048A) & 0xF000;
+			tmp_u16 |= ((u32)b & 0x0000003F);
+			tmp_u16 |= (((u32)a & 0x0000003F) << 6);
+			bcm43xx_phy_write(bcm, 0x048A, tmp_u16);
+		}
+		break;
+	default:
+		assert(0);
+	}
+}
+
+/* Stack implementation to save/restore values from the
+ * interference mitigation code.
+ * It is save to restore values in random order.
+ */
+static void _stack_save(u32 *_stackptr, size_t *stackidx,
+			u8 id, u16 offset, u16 value)
+{
+	u32 *stackptr = &(_stackptr[*stackidx]);
+
+	assert((offset & 0xF000) == 0x0000);
+	assert((id & 0xF0) == 0x00);
+	*stackptr = offset;
+	*stackptr |= ((u32)id) << 12;
+	*stackptr |= ((u32)value) << 16;
+	(*stackidx)++;
+	assert(*stackidx < BCM43xx_INTERFSTACK_SIZE);
+}
+
+static u16 _stack_restore(u32 *stackptr,
+			  u8 id, u16 offset)
+{
+	size_t i;
+
+	assert((offset & 0xF000) == 0x0000);
+	assert((id & 0xF0) == 0x00);
+	for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) {
+		if ((*stackptr & 0x00000FFF) != offset)
+			continue;
+		if (((*stackptr & 0x0000F000) >> 12) != id)
+			continue;
+		return ((*stackptr & 0xFFFF0000) >> 16);
+	}
+	assert(0);
+
+	return 0;
+}
+
+#define phy_stacksave(offset)					\
+	do {							\
+		_stack_save(stack, &stackidx, 0x1, (offset),	\
+			    bcm43xx_phy_read(bcm, (offset)));	\
+	} while (0)
+#define phy_stackrestore(offset)				\
+	do {							\
+		bcm43xx_phy_write(bcm, (offset),		\
+				  _stack_restore(stack, 0x1,	\
+					  	 (offset)));	\
+	} while (0)
+#define radio_stacksave(offset)						\
+	do {								\
+		_stack_save(stack, &stackidx, 0x2, (offset),		\
+			    bcm43xx_radio_read16(bcm, (offset)));	\
+	} while (0)
+#define radio_stackrestore(offset)					\
+	do {								\
+		bcm43xx_radio_write16(bcm, (offset),			\
+				      _stack_restore(stack, 0x2,	\
+						     (offset)));	\
+	} while (0)
+#define ilt_stacksave(offset)					\
+	do {							\
+		_stack_save(stack, &stackidx, 0x3, (offset),	\
+			    bcm43xx_ilt_read(bcm, (offset)));	\
+	} while (0)
+#define ilt_stackrestore(offset)				\
+	do {							\
+		bcm43xx_ilt_write(bcm, (offset),		\
+				  _stack_restore(stack, 0x3,	\
+						 (offset)));	\
+	} while (0)
+
+static void
+bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm,
+					     int mode)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 tmp, flipped;
+	u32 tmp32;
+	size_t stackidx = 0;
+	u32 *stack = radio->interfstack;
+
+	switch (mode) {
+	case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+		if (phy->rev != 1) {
+			bcm43xx_phy_write(bcm, 0x042B,
+			                  bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
+			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+			                  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000);
+			break;
+		}
+		radio_stacksave(0x0078);
+		tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E);
+		flipped = flip_4bit(tmp);
+		if (flipped < 10 && flipped >= 8)
+			flipped = 7;
+		else if (flipped >= 10)
+			flipped -= 3;
+		flipped = flip_4bit(flipped);
+		flipped = (flipped << 1) | 0x0020;
+		bcm43xx_radio_write16(bcm, 0x0078, flipped);
+
+		bcm43xx_calc_nrssi_threshold(bcm);
+
+		phy_stacksave(0x0406);
+		bcm43xx_phy_write(bcm, 0x0406, 0x7E28);
+
+		bcm43xx_phy_write(bcm, 0x042B,
+		                  bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+		                  bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000);
+
+		phy_stacksave(0x04A0);
+		bcm43xx_phy_write(bcm, 0x04A0,
+		                  (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008);
+		phy_stacksave(0x04A1);
+		bcm43xx_phy_write(bcm, 0x04A1,
+				  (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605);
+		phy_stacksave(0x04A2);
+		bcm43xx_phy_write(bcm, 0x04A2,
+				  (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204);
+		phy_stacksave(0x04A8);
+		bcm43xx_phy_write(bcm, 0x04A8,
+				  (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0803);
+		phy_stacksave(0x04AB);
+		bcm43xx_phy_write(bcm, 0x04AB,
+				  (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0605);
+
+		phy_stacksave(0x04A7);
+		bcm43xx_phy_write(bcm, 0x04A7, 0x0002);
+		phy_stacksave(0x04A3);
+		bcm43xx_phy_write(bcm, 0x04A3, 0x287A);
+		phy_stacksave(0x04A9);
+		bcm43xx_phy_write(bcm, 0x04A9, 0x2027);
+		phy_stacksave(0x0493);
+		bcm43xx_phy_write(bcm, 0x0493, 0x32F5);
+		phy_stacksave(0x04AA);
+		bcm43xx_phy_write(bcm, 0x04AA, 0x2027);
+		phy_stacksave(0x04AC);
+		bcm43xx_phy_write(bcm, 0x04AC, 0x32F5);
+		break;
+	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+		if (bcm43xx_phy_read(bcm, 0x0033) & 0x0800)
+			break;
+
+		radio->aci_enable = 1;
+
+		phy_stacksave(BCM43xx_PHY_RADIO_BITFIELD);
+		phy_stacksave(BCM43xx_PHY_G_CRS);
+		if (phy->rev < 2) {
+			phy_stacksave(0x0406);
+		} else {
+			phy_stacksave(0x04C0);
+			phy_stacksave(0x04C1);
+		}
+		phy_stacksave(0x0033);
+		phy_stacksave(0x04A7);
+		phy_stacksave(0x04A3);
+		phy_stacksave(0x04A9);
+		phy_stacksave(0x04AA);
+		phy_stacksave(0x04AC);
+		phy_stacksave(0x0493);
+		phy_stacksave(0x04A1);
+		phy_stacksave(0x04A0);
+		phy_stacksave(0x04A2);
+		phy_stacksave(0x048A);
+		phy_stacksave(0x04A8);
+		phy_stacksave(0x04AB);
+		if (phy->rev == 2) {
+			phy_stacksave(0x04AD);
+			phy_stacksave(0x04AE);
+		} else if (phy->rev >= 3) {
+			phy_stacksave(0x04AD);
+			phy_stacksave(0x0415);
+			phy_stacksave(0x0416);
+			phy_stacksave(0x0417);
+			ilt_stacksave(0x1A00 + 0x2);
+			ilt_stacksave(0x1A00 + 0x3);
+		}
+		phy_stacksave(0x042B);
+		phy_stacksave(0x048C);
+
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+				  bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
+				  & ~0x1000);
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+				  (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
+				   & 0xFFFC) | 0x0002);
+
+		bcm43xx_phy_write(bcm, 0x0033, 0x0800);
+		bcm43xx_phy_write(bcm, 0x04A3, 0x2027);
+		bcm43xx_phy_write(bcm, 0x04A9, 0x1CA8);
+		bcm43xx_phy_write(bcm, 0x0493, 0x287A);
+		bcm43xx_phy_write(bcm, 0x04AA, 0x1CA8);
+		bcm43xx_phy_write(bcm, 0x04AC, 0x287A);
+
+		bcm43xx_phy_write(bcm, 0x04A0,
+				  (bcm43xx_phy_read(bcm, 0x04A0)
+				   & 0xFFC0) | 0x001A);
+		bcm43xx_phy_write(bcm, 0x04A7, 0x000D);
+
+		if (phy->rev < 2) {
+			bcm43xx_phy_write(bcm, 0x0406, 0xFF0D);
+		} else if (phy->rev == 2) {
+			bcm43xx_phy_write(bcm, 0x04C0, 0xFFFF);
+			bcm43xx_phy_write(bcm, 0x04C1, 0x00A9);
+		} else {
+			bcm43xx_phy_write(bcm, 0x04C0, 0x00C1);
+			bcm43xx_phy_write(bcm, 0x04C1, 0x0059);
+		}
+
+		bcm43xx_phy_write(bcm, 0x04A1,
+		                  (bcm43xx_phy_read(bcm, 0x04A1)
+				   & 0xC0FF) | 0x1800);
+		bcm43xx_phy_write(bcm, 0x04A1,
+		                  (bcm43xx_phy_read(bcm, 0x04A1)
+				   & 0xFFC0) | 0x0015);
+		bcm43xx_phy_write(bcm, 0x04A8,
+		                  (bcm43xx_phy_read(bcm, 0x04A8)
+				   & 0xCFFF) | 0x1000);
+		bcm43xx_phy_write(bcm, 0x04A8,
+		                  (bcm43xx_phy_read(bcm, 0x04A8)
+				   & 0xF0FF) | 0x0A00);
+		bcm43xx_phy_write(bcm, 0x04AB,
+		                  (bcm43xx_phy_read(bcm, 0x04AB)
+				   & 0xCFFF) | 0x1000);
+		bcm43xx_phy_write(bcm, 0x04AB,
+		                  (bcm43xx_phy_read(bcm, 0x04AB)
+				   & 0xF0FF) | 0x0800);
+		bcm43xx_phy_write(bcm, 0x04AB,
+		                  (bcm43xx_phy_read(bcm, 0x04AB)
+				   & 0xFFCF) | 0x0010);
+		bcm43xx_phy_write(bcm, 0x04AB,
+		                  (bcm43xx_phy_read(bcm, 0x04AB)
+				   & 0xFFF0) | 0x0005);
+		bcm43xx_phy_write(bcm, 0x04A8,
+		                  (bcm43xx_phy_read(bcm, 0x04A8)
+				   & 0xFFCF) | 0x0010);
+		bcm43xx_phy_write(bcm, 0x04A8,
+		                  (bcm43xx_phy_read(bcm, 0x04A8)
+				   & 0xFFF0) | 0x0006);
+		bcm43xx_phy_write(bcm, 0x04A2,
+		                  (bcm43xx_phy_read(bcm, 0x04A2)
+				   & 0xF0FF) | 0x0800);
+		bcm43xx_phy_write(bcm, 0x04A0,
+				  (bcm43xx_phy_read(bcm, 0x04A0)
+				   & 0xF0FF) | 0x0500);
+		bcm43xx_phy_write(bcm, 0x04A2,
+				  (bcm43xx_phy_read(bcm, 0x04A2)
+				   & 0xFFF0) | 0x000B);
+
+		if (phy->rev >= 3) {
+			bcm43xx_phy_write(bcm, 0x048A,
+					  bcm43xx_phy_read(bcm, 0x048A)
+					  & ~0x8000);
+			bcm43xx_phy_write(bcm, 0x0415,
+					  (bcm43xx_phy_read(bcm, 0x0415)
+					   & 0x8000) | 0x36D8);
+			bcm43xx_phy_write(bcm, 0x0416,
+					  (bcm43xx_phy_read(bcm, 0x0416)
+					   & 0x8000) | 0x36D8);
+			bcm43xx_phy_write(bcm, 0x0417,
+					  (bcm43xx_phy_read(bcm, 0x0417)
+					   & 0xFE00) | 0x016D);
+		} else {
+			bcm43xx_phy_write(bcm, 0x048A,
+					  bcm43xx_phy_read(bcm, 0x048A)
+					  | 0x1000);
+			bcm43xx_phy_write(bcm, 0x048A,
+					  (bcm43xx_phy_read(bcm, 0x048A)
+					   & 0x9FFF) | 0x2000);
+			tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+						   BCM43xx_UCODEFLAGS_OFFSET);
+			if (!(tmp32 & 0x800)) {
+				tmp32 |= 0x800;
+				bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+						    BCM43xx_UCODEFLAGS_OFFSET,
+						    tmp32);
+			}
+		}
+		if (phy->rev >= 2) {
+			bcm43xx_phy_write(bcm, 0x042B,
+					  bcm43xx_phy_read(bcm, 0x042B)
+					  | 0x0800);
+		}
+		bcm43xx_phy_write(bcm, 0x048C,
+				  (bcm43xx_phy_read(bcm, 0x048C)
+				   & 0xF0FF) | 0x0200);
+		if (phy->rev == 2) {
+			bcm43xx_phy_write(bcm, 0x04AE,
+					  (bcm43xx_phy_read(bcm, 0x04AE)
+					   & 0xFF00) | 0x007F);
+			bcm43xx_phy_write(bcm, 0x04AD,
+					  (bcm43xx_phy_read(bcm, 0x04AD)
+					   & 0x00FF) | 0x1300);
+		} else if (phy->rev >= 6) {
+			bcm43xx_ilt_write(bcm, 0x1A00 + 0x3, 0x007F);
+			bcm43xx_ilt_write(bcm, 0x1A00 + 0x2, 0x007F);
+			bcm43xx_phy_write(bcm, 0x04AD,
+					  bcm43xx_phy_read(bcm, 0x04AD)
+					  & 0x00FF);
+		}
+		bcm43xx_calc_nrssi_slope(bcm);
+		break;
+	default:
+		assert(0);
+	}
+}
+
+static void
+bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm,
+					      int mode)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u32 tmp32;
+	u32 *stack = radio->interfstack;
+
+	switch (mode) {
+	case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+		if (phy->rev != 1) {
+			bcm43xx_phy_write(bcm, 0x042B,
+			                  bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
+			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+			                  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
+			break;
+		}
+		phy_stackrestore(0x0078);
+		bcm43xx_calc_nrssi_threshold(bcm);
+		phy_stackrestore(0x0406);
+		bcm43xx_phy_write(bcm, 0x042B,
+				  bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
+		if (!bcm->bad_frames_preempt) {
+			bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+					  bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
+					  & ~(1 << 11));
+		}
+		bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+				  bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
+		phy_stackrestore(0x04A0);
+		phy_stackrestore(0x04A1);
+		phy_stackrestore(0x04A2);
+		phy_stackrestore(0x04A8);
+		phy_stackrestore(0x04AB);
+		phy_stackrestore(0x04A7);
+		phy_stackrestore(0x04A3);
+		phy_stackrestore(0x04A9);
+		phy_stackrestore(0x0493);
+		phy_stackrestore(0x04AA);
+		phy_stackrestore(0x04AC);
+		break;
+	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+		if (!(bcm43xx_phy_read(bcm, 0x0033) & 0x0800))
+			break;
+
+		radio->aci_enable = 0;
+
+		phy_stackrestore(BCM43xx_PHY_RADIO_BITFIELD);
+		phy_stackrestore(BCM43xx_PHY_G_CRS);
+		phy_stackrestore(0x0033);
+		phy_stackrestore(0x04A3);
+		phy_stackrestore(0x04A9);
+		phy_stackrestore(0x0493);
+		phy_stackrestore(0x04AA);
+		phy_stackrestore(0x04AC);
+		phy_stackrestore(0x04A0);
+		phy_stackrestore(0x04A7);
+		if (phy->rev >= 2) {
+			phy_stackrestore(0x04C0);
+			phy_stackrestore(0x04C1);
+		} else
+			phy_stackrestore(0x0406);
+		phy_stackrestore(0x04A1);
+		phy_stackrestore(0x04AB);
+		phy_stackrestore(0x04A8);
+		if (phy->rev == 2) {
+			phy_stackrestore(0x04AD);
+			phy_stackrestore(0x04AE);
+		} else if (phy->rev >= 3) {
+			phy_stackrestore(0x04AD);
+			phy_stackrestore(0x0415);
+			phy_stackrestore(0x0416);
+			phy_stackrestore(0x0417);
+			ilt_stackrestore(0x1A00 + 0x2);
+			ilt_stackrestore(0x1A00 + 0x3);
+		}
+		phy_stackrestore(0x04A2);
+		phy_stackrestore(0x04A8);
+		phy_stackrestore(0x042B);
+		phy_stackrestore(0x048C);
+		tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+					   BCM43xx_UCODEFLAGS_OFFSET);
+		if (tmp32 & 0x800) {
+			tmp32 &= ~0x800;
+			bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+					    BCM43xx_UCODEFLAGS_OFFSET,
+					    tmp32);
+		}
+		bcm43xx_calc_nrssi_slope(bcm);
+		break;
+	default:
+		assert(0);
+	}
+}
+
+#undef phy_stacksave
+#undef phy_stackrestore
+#undef radio_stacksave
+#undef radio_stackrestore
+#undef ilt_stacksave
+#undef ilt_stackrestore
+
+int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm,
+					      int mode)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	int currentmode;
+
+	if ((phy->type != BCM43xx_PHYTYPE_G) ||
+	    (phy->rev == 0) ||
+	    (!phy->connected))
+		return -ENODEV;
+
+	radio->aci_wlan_automatic = 0;
+	switch (mode) {
+	case BCM43xx_RADIO_INTERFMODE_AUTOWLAN:
+		radio->aci_wlan_automatic = 1;
+		if (radio->aci_enable)
+			mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
+		else
+			mode = BCM43xx_RADIO_INTERFMODE_NONE;
+		break;
+	case BCM43xx_RADIO_INTERFMODE_NONE:
+	case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	currentmode = radio->interfmode;
+	if (currentmode == mode)
+		return 0;
+	if (currentmode != BCM43xx_RADIO_INTERFMODE_NONE)
+		bcm43xx_radio_interference_mitigation_disable(bcm, currentmode);
+
+	if (mode == BCM43xx_RADIO_INTERFMODE_NONE) {
+		radio->aci_enable = 0;
+		radio->aci_hw_rssi = 0;
+	} else
+		bcm43xx_radio_interference_mitigation_enable(bcm, mode);
+	radio->interfmode = mode;
+
+	return 0;
+}
+
+u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm)
+{
+	u16 reg, index, ret;
+
+	reg = bcm43xx_radio_read16(bcm, 0x0060);
+	index = (reg & 0x001E) >> 1;
+	ret = rcc_table[index] << 1;
+	ret |= (reg & 0x0001);
+	ret |= 0x0020;
+
+	return ret;
+}
+
+u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 backup[19] = { 0 };
+	u16 ret;
+	u16 i, j;
+	u32 tmp1 = 0, tmp2 = 0;
+
+	backup[0] = bcm43xx_radio_read16(bcm, 0x0043);
+	backup[14] = bcm43xx_radio_read16(bcm, 0x0051);
+	backup[15] = bcm43xx_radio_read16(bcm, 0x0052);
+	backup[1] = bcm43xx_phy_read(bcm, 0x0015);
+	backup[16] = bcm43xx_phy_read(bcm, 0x005A);
+	backup[17] = bcm43xx_phy_read(bcm, 0x0059);
+	backup[18] = bcm43xx_phy_read(bcm, 0x0058);
+	if (phy->type == BCM43xx_PHYTYPE_B) {
+		backup[2] = bcm43xx_phy_read(bcm, 0x0030);
+		backup[3] = bcm43xx_read16(bcm, 0x03EC);
+		bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
+		bcm43xx_write16(bcm, 0x03EC, 0x3F3F);
+	} else {
+		if (phy->connected) {
+			backup[4] = bcm43xx_phy_read(bcm, 0x0811);
+			backup[5] = bcm43xx_phy_read(bcm, 0x0812);
+			backup[6] = bcm43xx_phy_read(bcm, 0x0814);
+			backup[7] = bcm43xx_phy_read(bcm, 0x0815);
+			backup[8] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);
+			backup[9] = bcm43xx_phy_read(bcm, 0x0802);
+			bcm43xx_phy_write(bcm, 0x0814,
+			                  (bcm43xx_phy_read(bcm, 0x0814) | 0x0003));
+			bcm43xx_phy_write(bcm, 0x0815,
+			                  (bcm43xx_phy_read(bcm, 0x0815) & 0xFFFC));	
+			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+			                  (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF));
+			bcm43xx_phy_write(bcm, 0x0802,
+			                  (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC));
+			bcm43xx_phy_write(bcm, 0x0811, 0x01B3);
+			bcm43xx_phy_write(bcm, 0x0812, 0x0FB2);
+		}
+		bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,
+		                (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000));
+	}
+	backup[10] = bcm43xx_phy_read(bcm, 0x0035);
+	bcm43xx_phy_write(bcm, 0x0035,
+	                  (bcm43xx_phy_read(bcm, 0x0035) & 0xFF7F));
+	backup[11] = bcm43xx_read16(bcm, 0x03E6);
+	backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+
+	// Initialization
+	if (phy->version == 0) {
+		bcm43xx_write16(bcm, 0x03E6, 0x0122);
+	} else {
+		if (phy->version >= 2)
+			bcm43xx_write16(bcm, 0x03E6, 0x0040);
+		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+		                (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) | 0x2000));
+	}
+
+	ret = bcm43xx_radio_calibrationvalue(bcm);
+
+	if (phy->type == BCM43xx_PHYTYPE_B)
+		bcm43xx_radio_write16(bcm, 0x0078, 0x0003);
+
+	bcm43xx_phy_write(bcm, 0x0015, 0xBFAF);
+	bcm43xx_phy_write(bcm, 0x002B, 0x1403);
+	if (phy->connected)
+		bcm43xx_phy_write(bcm, 0x0812, 0x00B2);
+	bcm43xx_phy_write(bcm, 0x0015, 0xBFA0);
+	bcm43xx_radio_write16(bcm, 0x0051,
+	                      (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004));
+	bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
+	bcm43xx_radio_write16(bcm, 0x0043,
+			      bcm43xx_radio_read16(bcm, 0x0043) | 0x0009);
+	bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+
+	for (i = 0; i < 16; i++) {
+		bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+		bcm43xx_phy_write(bcm, 0x0059, 0xC810);
+		bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+		if (phy->connected)
+			bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
+		bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+		udelay(10);
+		if (phy->connected)
+			bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
+		bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);
+		udelay(10);
+		if (phy->connected)
+			bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
+		bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);
+		udelay(10);
+		tmp1 += bcm43xx_phy_read(bcm, 0x002D);
+		bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+		if (phy->connected)
+			bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
+		bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+	}
+
+	tmp1++;
+	tmp1 >>= 9;
+	udelay(10);
+	bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+
+	for (i = 0; i < 16; i++) {
+		bcm43xx_radio_write16(bcm, 0x0078, (flip_4bit(i) << 1) | 0x0020);
+		backup[13] = bcm43xx_radio_read16(bcm, 0x0078);
+		udelay(10);
+		for (j = 0; j < 16; j++) {
+			bcm43xx_phy_write(bcm, 0x005A, 0x0D80);
+			bcm43xx_phy_write(bcm, 0x0059, 0xC810);
+			bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+			if (phy->connected)
+				bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
+			bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+			udelay(10);
+			if (phy->connected)
+				bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
+			bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);
+			udelay(10);
+			if (phy->connected)
+				bcm43xx_phy_write(bcm, 0x0812, 0x30B3); /* 0x30B3 is not a typo */
+			bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);
+			udelay(10);
+			tmp2 += bcm43xx_phy_read(bcm, 0x002D);
+			bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+			if (phy->connected)
+				bcm43xx_phy_write(bcm, 0x0812, 0x30B2);
+			bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+		}
+		tmp2++;
+		tmp2 >>= 8;
+		if (tmp1 < tmp2)
+			break;
+	}
+
+	/* Restore the registers */
+	bcm43xx_phy_write(bcm, 0x0015, backup[1]);
+	bcm43xx_radio_write16(bcm, 0x0051, backup[14]);
+	bcm43xx_radio_write16(bcm, 0x0052, backup[15]);
+	bcm43xx_radio_write16(bcm, 0x0043, backup[0]);
+	bcm43xx_phy_write(bcm, 0x005A, backup[16]);
+	bcm43xx_phy_write(bcm, 0x0059, backup[17]);
+	bcm43xx_phy_write(bcm, 0x0058, backup[18]);
+	bcm43xx_write16(bcm, 0x03E6, backup[11]);
+	if (phy->version != 0)
+		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]);
+	bcm43xx_phy_write(bcm, 0x0035, backup[10]);
+	bcm43xx_radio_selectchannel(bcm, radio->channel, 1);
+	if (phy->type == BCM43xx_PHYTYPE_B) {
+		bcm43xx_phy_write(bcm, 0x0030, backup[2]);
+		bcm43xx_write16(bcm, 0x03EC, backup[3]);
+	} else {
+		bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,
+				(bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) & 0x7FFF));
+		if (phy->connected) {
+			bcm43xx_phy_write(bcm, 0x0811, backup[4]);
+			bcm43xx_phy_write(bcm, 0x0812, backup[5]);
+			bcm43xx_phy_write(bcm, 0x0814, backup[6]);
+			bcm43xx_phy_write(bcm, 0x0815, backup[7]);
+			bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, backup[8]);
+			bcm43xx_phy_write(bcm, 0x0802, backup[9]);
+		}
+	}
+	if (i >= 15)
+		ret = backup[13];
+
+	return ret;
+}
+
+void bcm43xx_radio_init2060(struct bcm43xx_private *bcm)
+{
+	int err;
+
+	bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);
+	bcm43xx_radio_write16(bcm, 0x0005, 0x0008);
+	bcm43xx_radio_write16(bcm, 0x0009, 0x0040);
+	bcm43xx_radio_write16(bcm, 0x0005, 0x00AA);
+	bcm43xx_radio_write16(bcm, 0x0032, 0x008F);
+	bcm43xx_radio_write16(bcm, 0x0006, 0x008F);
+	bcm43xx_radio_write16(bcm, 0x0034, 0x008F);
+	bcm43xx_radio_write16(bcm, 0x002C, 0x0007);
+	bcm43xx_radio_write16(bcm, 0x0082, 0x0080);
+	bcm43xx_radio_write16(bcm, 0x0080, 0x0000);
+	bcm43xx_radio_write16(bcm, 0x003F, 0x00DA);
+	bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);
+	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0010);
+	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);
+	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);
+	udelay(400);
+
+	bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020) | 0x0010);
+	udelay(400);
+
+	bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008) | 0x0008);
+	bcm43xx_radio_write16(bcm, 0x0085, bcm43xx_radio_read16(bcm, 0x0085) & ~0x0010);
+	bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);
+	bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040);
+	bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040) | 0x0040);
+	bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0008) | 0x0008);
+	bcm43xx_phy_write(bcm, 0x0063, 0xDDC6);
+	bcm43xx_phy_write(bcm, 0x0069, 0x07BE);
+	bcm43xx_phy_write(bcm, 0x006A, 0x0000);
+
+	err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_A, 0);
+	assert(err == 0);
+	udelay(1000);
+}
+
+static inline
+u16 freq_r3A_value(u16 frequency)
+{
+	u16 value;
+
+	if (frequency < 5091)
+		value = 0x0040;
+	else if (frequency < 5321)
+		value = 0x0000;
+	else if (frequency < 5806)
+		value = 0x0080;
+	else
+		value = 0x0040;
+
+	return value;
+}
+
+void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm)
+{
+	static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
+	static const u8 data_low[5]  = { 0x00, 0x01, 0x05, 0x06, 0x0A };
+	u16 tmp = bcm43xx_radio_read16(bcm, 0x001E);
+	int i, j;
+	
+	for (i = 0; i < 5; i++) {
+		for (j = 0; j < 5; j++) {
+			if (tmp == (data_high[i] << 4 | data_low[j])) {
+				bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0);
+				return;
+			}
+		}
+	}
+}
+
+int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm,
+				u8 channel,
+				int synthetic_pu_workaround)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 r8, tmp;
+	u16 freq;
+
+	if ((radio->manufact == 0x17F) &&
+	    (radio->version == 0x2060) &&
+	    (radio->revision == 1)) {
+		if (channel > 200)
+			return -EINVAL;
+		freq = channel2freq_a(channel);
+
+		r8 = bcm43xx_radio_read16(bcm, 0x0008);
+		bcm43xx_write16(bcm, 0x03F0, freq);
+		bcm43xx_radio_write16(bcm, 0x0008, r8);
+
+		TODO();//TODO: write max channel TX power? to Radio 0x2D
+		tmp = bcm43xx_radio_read16(bcm, 0x002E);
+		tmp &= 0x0080;
+		TODO();//TODO: OR tmp with the Power out estimation for this channel?
+		bcm43xx_radio_write16(bcm, 0x002E, tmp);
+
+		if (freq >= 4920 && freq <= 5500) {
+			/* 
+			 * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F;
+			 *    = (freq * 0.025862069
+			 */
+			r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */
+		}
+		bcm43xx_radio_write16(bcm, 0x0007, (r8 << 4) | r8);
+		bcm43xx_radio_write16(bcm, 0x0020, (r8 << 4) | r8);
+		bcm43xx_radio_write16(bcm, 0x0021, (r8 << 4) | r8);
+		bcm43xx_radio_write16(bcm, 0x0022,
+				      (bcm43xx_radio_read16(bcm, 0x0022)
+				       & 0x000F) | (r8 << 4));
+		bcm43xx_radio_write16(bcm, 0x002A, (r8 << 4));
+		bcm43xx_radio_write16(bcm, 0x002B, (r8 << 4));
+		bcm43xx_radio_write16(bcm, 0x0008,
+				      (bcm43xx_radio_read16(bcm, 0x0008)
+				       & 0x00F0) | (r8 << 4));
+		bcm43xx_radio_write16(bcm, 0x0029,
+				      (bcm43xx_radio_read16(bcm, 0x0029)
+				       & 0xFF0F) | 0x00B0);
+		bcm43xx_radio_write16(bcm, 0x0035, 0x00AA);
+		bcm43xx_radio_write16(bcm, 0x0036, 0x0085);
+		bcm43xx_radio_write16(bcm, 0x003A,
+				      (bcm43xx_radio_read16(bcm, 0x003A)
+				       & 0xFF20) | freq_r3A_value(freq));
+		bcm43xx_radio_write16(bcm, 0x003D,
+				      bcm43xx_radio_read16(bcm, 0x003D) & 0x00FF);
+		bcm43xx_radio_write16(bcm, 0x0081,
+				      (bcm43xx_radio_read16(bcm, 0x0081)
+				       & 0xFF7F) | 0x0080);
+		bcm43xx_radio_write16(bcm, 0x0035,
+				      bcm43xx_radio_read16(bcm, 0x0035) & 0xFFEF);
+		bcm43xx_radio_write16(bcm, 0x0035,
+				      (bcm43xx_radio_read16(bcm, 0x0035)
+				       & 0xFFEF) | 0x0010);
+		bcm43xx_radio_set_tx_iq(bcm);
+		TODO();	//TODO:	TSSI2dbm workaround
+		bcm43xx_phy_xmitpower(bcm);//FIXME correct?
+	} else {
+		if ((channel < 1) || (channel > 14))
+			return -EINVAL;
+
+		if (synthetic_pu_workaround)
+			bcm43xx_synth_pu_workaround(bcm, channel);
+
+		bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+				channel2freq_bg(channel));
+
+		if (channel == 14) {
+			if (bcm->sprom.locale == BCM43xx_LOCALE_JAPAN) {
+				bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+						    BCM43xx_UCODEFLAGS_OFFSET,
+						    bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+								       BCM43xx_UCODEFLAGS_OFFSET)
+						    & ~(1 << 7));
+			} else {
+				bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+						    BCM43xx_UCODEFLAGS_OFFSET,
+						    bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+								       BCM43xx_UCODEFLAGS_OFFSET)
+						    | (1 << 7));
+			}
+			bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+					bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
+					| (1 << 11));
+		} else {
+			bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+					bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
+					& 0xF7BF);
+		}
+	}
+
+	radio->channel = channel;
+	//XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states
+	//     that 2000 usecs might suffice.
+	udelay(8000);
+
+	return 0;
+}
+
+void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val)
+{
+	u16 tmp;
+
+	val <<= 8;
+	tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0022) & 0xFCFF;
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0022, tmp | val);
+	tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x03A8) & 0xFCFF;
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x03A8, tmp | val);
+	tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0054) & 0xFCFF;
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0054, tmp | val);
+}
+
+/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */
+static u16 bcm43xx_get_txgain_base_band(u16 txpower)
+{
+	u16 ret;
+
+	assert(txpower <= 63);
+
+	if (txpower >= 54)
+		ret = 2;
+	else if (txpower >= 49)
+		ret = 4;
+	else if (txpower >= 44)
+		ret = 5;
+	else
+		ret = 6;
+
+	return ret;
+}
+
+/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */
+static u16 bcm43xx_get_txgain_freq_power_amp(u16 txpower)
+{
+	u16 ret;
+
+	assert(txpower <= 63);
+
+	if (txpower >= 32)
+		ret = 0;
+	else if (txpower >= 25)
+		ret = 1;
+	else if (txpower >= 20)
+		ret = 2;
+	else if (txpower >= 12)
+		ret = 3;
+	else
+		ret = 4;
+
+	return ret;
+}
+
+/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */
+static u16 bcm43xx_get_txgain_dac(u16 txpower)
+{
+	u16 ret;
+
+	assert(txpower <= 63);
+
+	if (txpower >= 54)
+		ret = txpower - 53;
+	else if (txpower >= 49)
+		ret = txpower - 42;
+	else if (txpower >= 44)
+		ret = txpower - 37;
+	else if (txpower >= 32)
+		ret = txpower - 32;
+	else if (txpower >= 25)
+		ret = txpower - 20;
+	else if (txpower >= 20)
+		ret = txpower - 13;
+	else if (txpower >= 12)
+		ret = txpower - 8;
+	else
+		ret = txpower;
+
+	return ret;
+}
+
+void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 pamp, base, dac, ilt;
+
+	txpower = limit_value(txpower, 0, 63);
+
+	pamp = bcm43xx_get_txgain_freq_power_amp(txpower);
+	pamp <<= 5;
+	pamp &= 0x00E0;
+	bcm43xx_phy_write(bcm, 0x0019, pamp);
+
+	base = bcm43xx_get_txgain_base_band(txpower);
+	base &= 0x000F;
+	bcm43xx_phy_write(bcm, 0x0017, base | 0x0020);
+
+	ilt = bcm43xx_ilt_read(bcm, 0x3001);
+	ilt &= 0x0007;
+
+	dac = bcm43xx_get_txgain_dac(txpower);
+	dac <<= 3;
+	dac |= ilt;
+
+	bcm43xx_ilt_write(bcm, 0x3001, dac);
+
+	radio->txpwr_offset = txpower;
+
+	TODO();
+	//TODO: FuncPlaceholder (Adjust BB loft cancel)
+}
+
+void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
+                                 u16 baseband_attenuation, u16 radio_attenuation,
+                                 u16 txpower)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
+	if (baseband_attenuation == 0xFFFF)
+		baseband_attenuation = radio->baseband_atten;
+	if (radio_attenuation == 0xFFFF)
+		radio_attenuation = radio->radio_atten;
+	if (txpower == 0xFFFF)
+		txpower = radio->txctl1;
+	radio->baseband_atten = baseband_attenuation;
+	radio->radio_atten = radio_attenuation;
+	radio->txctl1 = txpower;
+
+	assert(/*baseband_attenuation >= 0 &&*/ baseband_attenuation <= 11);
+	if (radio->revision < 6)
+		assert(/*radio_attenuation >= 0 &&*/ radio_attenuation <= 9);
+	else
+		assert(/* radio_attenuation >= 0 &&*/ radio_attenuation <= 31);
+	assert(/*txpower >= 0 &&*/ txpower <= 7);
+
+	bcm43xx_phy_set_baseband_attenuation(bcm, baseband_attenuation);
+	bcm43xx_radio_write16(bcm, 0x0043, radio_attenuation);
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0064, radio_attenuation);
+	if (radio->version == 0x2050) {
+		bcm43xx_radio_write16(bcm, 0x0052,
+		                      (bcm43xx_radio_read16(bcm, 0x0052) & ~0x0070)
+				       | ((txpower << 4) & 0x0070));
+	}
+	//FIXME: The spec is very weird and unclear here.
+	if (phy->type == BCM43xx_PHYTYPE_G)
+		bcm43xx_phy_lo_adjust(bcm, 0);
+}
+
+u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+
+	if (radio->version == 0x2050 && radio->revision < 6)
+		return 0;
+	return 2;
+}
+
+u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	u16 att = 0xFFFF;
+
+	if (phy->type == BCM43xx_PHYTYPE_A)
+		return 0x60;
+
+	switch (radio->version) {
+	case 0x2053:
+		switch (radio->revision) {
+		case 1:
+			att = 6;
+			break;
+		}
+		break;
+	case 0x2050:
+		switch (radio->revision) {
+		case 0:
+			att = 5;
+			break;
+		case 1:
+			if (phy->type == BCM43xx_PHYTYPE_G) {
+				if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+				    bcm->board_type == 0x421 &&
+				    bcm->board_revision >= 30)
+					att = 3;
+				else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+					 bcm->board_type == 0x416)
+					att = 3;
+				else
+					att = 1;
+			} else {
+				if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+				    bcm->board_type == 0x421 &&
+				    bcm->board_revision >= 30)
+					att = 7;
+				else
+					att = 6;
+			}
+			break;
+		case 2:
+			if (phy->type == BCM43xx_PHYTYPE_G) {
+				if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+				    bcm->board_type == 0x421 &&
+				    bcm->board_revision >= 30)
+					att = 3;
+				else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+					 bcm->board_type == 0x416)
+					att = 5;
+				else if (bcm->chip_id == 0x4320)
+					att = 4;
+				else
+					att = 3;
+			} else
+				att = 6;
+			break;
+		case 3:
+			att = 5;
+			break;
+		case 4:
+		case 5:
+			att = 1;
+			break;
+		case 6:
+		case 7:
+			att = 5;
+			break;
+		case 8:
+			att = 0x1A;
+			break;
+		case 9:
+		default:
+			att = 5;
+		}
+	}
+	if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+	    bcm->board_type == 0x421) {
+		if (bcm->board_revision < 0x43)
+			att = 2;
+		else if (bcm->board_revision < 0x51)
+			att = 3;
+	}
+	if (att == 0xFFFF)
+		att = 5;
+
+	return att;
+}
+
+u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+
+	if (radio->version != 0x2050)
+		return 0;
+	if (radio->revision == 1)
+		return 3;
+	if (radio->revision < 6)
+		return 2;
+	if (radio->revision == 8)
+		return 1;
+	return 0;
+}
+
+void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	int err;
+
+	if (radio->enabled)
+		return;
+
+	switch (phy->type) {
+	case BCM43xx_PHYTYPE_A:
+		bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);
+		bcm43xx_radio_write16(bcm, 0x0005, 0x0008);
+		bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) & 0xFFF7);
+		bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) & 0xFFF7);
+		bcm43xx_radio_init2060(bcm);	
+		break;
+	case BCM43xx_PHYTYPE_B:
+	case BCM43xx_PHYTYPE_G:
+		bcm43xx_phy_write(bcm, 0x0015, 0x8000);
+		bcm43xx_phy_write(bcm, 0x0015, 0xCC00);
+		bcm43xx_phy_write(bcm, 0x0015, (phy->connected ? 0x00C0 : 0x0000));
+		err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 1);
+		assert(err == 0);
+		break;
+	default:
+		assert(0);
+	}
+	radio->enabled = 1;
+	dprintk(KERN_INFO PFX "Radio turned on\n");
+}
+	
+void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+
+	if (phy->type == BCM43xx_PHYTYPE_A) {
+		bcm43xx_radio_write16(bcm, 0x0004, 0x00FF);
+		bcm43xx_radio_write16(bcm, 0x0005, 0x00FB);
+		bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) | 0x0008);
+		bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) | 0x0008);
+	}
+	if (phy->type == BCM43xx_PHYTYPE_G && bcm->current_core->rev >= 5) {
+		bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) | 0x008C);
+		bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFF73);
+	} else
+		bcm43xx_phy_write(bcm, 0x0015, 0xAA00);
+	radio->enabled = 0;
+	dprintk(KERN_INFO PFX "Radio turned off\n");
+}
+
+void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
+	switch (phy->type) {
+	case BCM43xx_PHYTYPE_A:
+		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0068, 0x7F7F);
+		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x006a, 0x7F7F);
+		break;
+	case BCM43xx_PHYTYPE_B:
+	case BCM43xx_PHYTYPE_G:
+		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0058, 0x7F7F);
+		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x005a, 0x7F7F);
+		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0070, 0x7F7F);
+		bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0072, 0x7F7F);
+		break;
+	}
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
new file mode 100644
index 0000000..9ed1803
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
@@ -0,0 +1,99 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+                     Stefano Brivio <st3@riseup.net>
+                     Michael Buesch <mbuesch@freenet.de>
+                     Danny van Dyk <kugelfang@gentoo.org>
+                     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef BCM43xx_RADIO_H_
+#define BCM43xx_RADIO_H_
+
+#include "bcm43xx.h"
+
+
+#define BCM43xx_RADIO_DEFAULT_CHANNEL_A		36
+#define BCM43xx_RADIO_DEFAULT_CHANNEL_BG	6
+
+/* Force antenna 0. */
+#define BCM43xx_RADIO_TXANTENNA_0		0
+/* Force antenna 1. */
+#define BCM43xx_RADIO_TXANTENNA_1		1
+/* Use the RX antenna, that was selected for the most recently
+ * received good PLCP header.
+ */
+#define BCM43xx_RADIO_TXANTENNA_LASTPLCP	3
+#define BCM43xx_RADIO_TXANTENNA_DEFAULT		BCM43xx_RADIO_TXANTENNA_LASTPLCP
+
+#define BCM43xx_RADIO_INTERFMODE_NONE		0
+#define BCM43xx_RADIO_INTERFMODE_NONWLAN	1
+#define BCM43xx_RADIO_INTERFMODE_MANUALWLAN	2
+#define BCM43xx_RADIO_INTERFMODE_AUTOWLAN	3
+
+
+void bcm43xx_radio_lock(struct bcm43xx_private *bcm);
+void bcm43xx_radio_unlock(struct bcm43xx_private *bcm);
+
+u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset);
+void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val);
+
+u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm);
+void bcm43xx_radio_init2060(struct bcm43xx_private *bcm);
+
+void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm);
+void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm);
+
+int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, u8 channel,
+				int synthetic_pu_workaround);
+
+void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower);
+void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
+                               u16 baseband_attenuation, u16 attenuation,
+			       u16 txpower);
+
+u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm);
+u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm);
+u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm);
+
+void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val);
+
+void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm);
+
+u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel);
+u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm);
+
+int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode);
+
+void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm);
+void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm);
+s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset);
+void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val);
+void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val);
+void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm);
+
+void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm);
+u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm);
+
+#endif /* BCM43xx_RADIO_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
new file mode 100644
index 0000000..c44d890
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
@@ -0,0 +1,322 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  SYSFS support routines
+
+  Copyright (c) 2006 Michael Buesch <mbuesch@freenet.de>
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "bcm43xx_sysfs.h"
+#include "bcm43xx.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_radio.h"
+
+#include <linux/capability.h>
+
+
+#define GENERIC_FILESIZE	64
+
+
+static int get_integer(const char *buf, size_t count)
+{
+	char tmp[10 + 1] = { 0 };
+	int ret = -EINVAL;
+
+	if (count == 0)
+		goto out;
+	count = min(count, (size_t)10);
+	memcpy(tmp, buf, count);
+	ret = simple_strtol(tmp, NULL, 10);
+out:
+	return ret;
+}
+
+static int get_boolean(const char *buf, size_t count)
+{
+	if (count != 0) {
+		if (buf[0] == '1')
+			return 1;
+		if (buf[0] == '0')
+			return 0;
+		if (count >= 4 && memcmp(buf, "true", 4) == 0)
+			return 1;
+		if (count >= 5 && memcmp(buf, "false", 5) == 0)
+			return 0;
+		if (count >= 3 && memcmp(buf, "yes", 3) == 0)
+			return 1;
+		if (count >= 2 && memcmp(buf, "no", 2) == 0)
+			return 0;
+		if (count >= 2 && memcmp(buf, "on", 2) == 0)
+			return 1;
+		if (count >= 3 && memcmp(buf, "off", 3) == 0)
+			return 0;
+	}
+	return -EINVAL;
+}
+
+static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom);
+	u16 *sprom;
+	unsigned long flags;
+	int i, err;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	assert(BCM43xx_SPROM_SIZE * sizeof(u16) <= PAGE_SIZE);
+	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+			GFP_KERNEL);
+	if (!sprom)
+		return -ENOMEM;
+	bcm43xx_lock_mmio(bcm, flags);
+	assert(bcm->initialized);
+	err = bcm43xx_sprom_read(bcm, sprom);
+	if (!err) {
+		for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+			buf[i * 2] = sprom[i] & 0x00FF;
+			buf[i * 2 + 1] = (sprom[i] & 0xFF00) >> 8;
+		}
+	}
+	bcm43xx_unlock_mmio(bcm, flags);
+	kfree(sprom);
+
+	return err ? err : BCM43xx_SPROM_SIZE * sizeof(u16);
+}
+
+static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom);
+	u16 *sprom;
+	unsigned long flags;
+	int i, err;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (count != BCM43xx_SPROM_SIZE * sizeof(u16))
+		return -EINVAL;
+	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+			GFP_KERNEL);
+	if (!sprom)
+		return -ENOMEM;
+	for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+		sprom[i] = buf[i * 2] & 0xFF;
+		sprom[i] |= ((u16)(buf[i * 2 + 1] & 0xFF)) << 8;
+	}
+	bcm43xx_lock_mmio(bcm, flags);
+	assert(bcm->initialized);
+	err = bcm43xx_sprom_write(bcm, sprom);
+	bcm43xx_unlock_mmio(bcm, flags);
+	kfree(sprom);
+
+	return err ? err : count;
+
+}
+
+static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
+					    struct device_attribute *attr,
+					    char *buf)
+{
+	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode);
+	unsigned long flags;
+	int err;
+	ssize_t count = 0;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	bcm43xx_lock(bcm, flags);
+	assert(bcm->initialized);
+
+	switch (bcm43xx_current_radio(bcm)->interfmode) {
+	case BCM43xx_RADIO_INTERFMODE_NONE:
+		count = snprintf(buf, PAGE_SIZE, "0 (No Interference Mitigation)\n");
+		break;
+	case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+		count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference Mitigation)\n");
+		break;
+	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+		count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference Mitigation)\n");
+		break;
+	default:
+		assert(0);
+	}
+	err = 0;
+
+	bcm43xx_unlock(bcm, flags);
+
+	return err ? err : count;
+
+}
+
+static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
+					     struct device_attribute *attr,
+					     const char *buf, size_t count)
+{
+	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode);
+	unsigned long flags;
+	int err;
+	int mode;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	mode = get_integer(buf, count);
+	switch (mode) {
+	case 0:
+		mode = BCM43xx_RADIO_INTERFMODE_NONE;
+		break;
+	case 1:
+		mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
+		break;
+	case 2:
+		mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
+		break;
+	case 3:
+		mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	bcm43xx_lock_mmio(bcm, flags);
+	assert(bcm->initialized);
+
+	err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
+	if (err) {
+		printk(KERN_ERR PFX "Interference Mitigation not "
+				    "supported by device\n");
+	}
+
+	bcm43xx_unlock_mmio(bcm, flags);
+
+	return err ? err : count;
+}
+
+static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
+{
+	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble);
+	unsigned long flags;
+	int err;
+	ssize_t count;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	bcm43xx_lock(bcm, flags);
+	assert(bcm->initialized);
+
+	if (bcm->short_preamble)
+		count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
+	else
+		count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
+
+	err = 0;
+	bcm43xx_unlock(bcm, flags);
+
+	return err ? err : count;
+}
+
+static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
+					   struct device_attribute *attr,
+					   const char *buf, size_t count)
+{
+	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble);
+	unsigned long flags;
+	int err;
+	int value;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	value = get_boolean(buf, count);
+	if (value < 0)
+		return value;
+	bcm43xx_lock(bcm, flags);
+	assert(bcm->initialized);
+
+	bcm->short_preamble = !!value;
+
+	err = 0;
+	bcm43xx_unlock(bcm, flags);
+
+	return err ? err : count;
+}
+
+int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
+{
+	struct device *dev = &bcm->pci_dev->dev;
+	struct bcm43xx_sysfs *sysfs = &bcm->sysfs;
+	int err;
+
+	assert(bcm->initialized);
+
+	sysfs->attr_sprom.attr.name = "sprom";
+	sysfs->attr_sprom.attr.owner = THIS_MODULE;
+	sysfs->attr_sprom.attr.mode = 0600;
+	sysfs->attr_sprom.show = bcm43xx_attr_sprom_show;
+	sysfs->attr_sprom.store = bcm43xx_attr_sprom_store;
+	err = device_create_file(dev, &sysfs->attr_sprom);
+	if (err)
+		goto out;
+
+	sysfs->attr_interfmode.attr.name = "interference";
+	sysfs->attr_interfmode.attr.owner = THIS_MODULE;
+	sysfs->attr_interfmode.attr.mode = 0600;
+	sysfs->attr_interfmode.show = bcm43xx_attr_interfmode_show;
+	sysfs->attr_interfmode.store = bcm43xx_attr_interfmode_store;
+	err = device_create_file(dev, &sysfs->attr_interfmode);
+	if (err)
+		goto err_remove_sprom;
+
+	sysfs->attr_preamble.attr.name = "shortpreamble";
+	sysfs->attr_preamble.attr.owner = THIS_MODULE;
+	sysfs->attr_preamble.attr.mode = 0600;
+	sysfs->attr_preamble.show = bcm43xx_attr_preamble_show;
+	sysfs->attr_preamble.store = bcm43xx_attr_preamble_store;
+	err = device_create_file(dev, &sysfs->attr_preamble);
+	if (err)
+		goto err_remove_interfmode;
+
+out:
+	return err;
+err_remove_interfmode:
+	device_remove_file(dev, &sysfs->attr_interfmode);
+err_remove_sprom:
+	device_remove_file(dev, &sysfs->attr_sprom);
+	goto out;
+}
+
+void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
+{
+	struct device *dev = &bcm->pci_dev->dev;
+	struct bcm43xx_sysfs *sysfs = &bcm->sysfs;
+
+	device_remove_file(dev, &sysfs->attr_preamble);
+	device_remove_file(dev, &sysfs->attr_interfmode);
+	device_remove_file(dev, &sysfs->attr_sprom);
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
new file mode 100644
index 0000000..57f1451
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
@@ -0,0 +1,25 @@
+#ifndef BCM43xx_SYSFS_H_
+#define BCM43xx_SYSFS_H_
+
+#include <linux/device.h>
+
+
+struct bcm43xx_sysfs {
+	struct device_attribute attr_sprom;
+	struct device_attribute attr_interfmode;
+	struct device_attribute attr_preamble;
+};
+
+#define devattr_to_bcm(attr, attr_name)	({				\
+	struct bcm43xx_sysfs *__s; struct bcm43xx_private *__p;		\
+	__s = container_of((attr), struct bcm43xx_sysfs, attr_name);	\
+	__p = container_of(__s, struct bcm43xx_private, sysfs);		\
+	__p;								\
+					})
+
+struct bcm43xx_private;
+
+int bcm43xx_sysfs_register(struct bcm43xx_private *bcm);
+void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm);
+
+#endif /* BCM43xx_SYSFS_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
new file mode 100644
index 0000000..3daee82
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -0,0 +1,1002 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+                     Stefano Brivio <st3@riseup.net>
+                     Michael Buesch <mbuesch@freenet.de>
+                     Danny van Dyk <kugelfang@gentoo.org>
+                     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <net/ieee80211softmac.h>
+#include <net/ieee80211softmac_wx.h>
+#include <linux/capability.h>
+#include <linux/sched.h> /* for capable() */
+#include <linux/delay.h>
+
+#include "bcm43xx.h"
+#include "bcm43xx_wx.h"
+#include "bcm43xx_main.h"
+#include "bcm43xx_radio.h"
+#include "bcm43xx_phy.h"
+
+
+/* The WIRELESS_EXT version, which is implemented by this driver. */
+#define BCM43xx_WX_VERSION	18
+
+#define MAX_WX_STRING		80
+
+
+static int bcm43xx_wx_get_name(struct net_device *net_dev,
+                               struct iw_request_info *info,
+			       union iwreq_data *data,
+			       char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	int i;
+	struct bcm43xx_phyinfo *phy;
+	char suffix[7] = { 0 };
+	int have_a = 0, have_b = 0, have_g = 0;
+
+	bcm43xx_lock(bcm, flags);
+	for (i = 0; i < bcm->nr_80211_available; i++) {
+		phy = &(bcm->core_80211_ext[i].phy);
+		switch (phy->type) {
+		case BCM43xx_PHYTYPE_A:
+			have_a = 1;
+			break;
+		case BCM43xx_PHYTYPE_G:
+			have_g = 1;
+		case BCM43xx_PHYTYPE_B:
+			have_b = 1;
+			break;
+		default:
+			assert(0);
+		}
+	}
+	bcm43xx_unlock(bcm, flags);
+
+	i = 0;
+	if (have_a) {
+		suffix[i++] = 'a';
+		suffix[i++] = '/';
+	}
+	if (have_b) {
+		suffix[i++] = 'b';
+		suffix[i++] = '/';
+	}
+	if (have_g) {
+		suffix[i++] = 'g';
+		suffix[i++] = '/';
+	}
+	if (i != 0) 
+		suffix[i - 1] = '\0';
+
+	snprintf(data->name, IFNAMSIZ, "IEEE 802.11%s", suffix);
+
+	return 0;
+}
+
+static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
+				      struct iw_request_info *info,
+				      union iwreq_data *data,
+				      char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	u8 channel;
+	int freq;
+	int err = -EINVAL;
+
+	bcm43xx_lock_mmio(bcm, flags);
+	if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
+		channel = data->freq.m;
+		freq = bcm43xx_channel_to_freq(bcm, channel);
+	} else {
+		channel = bcm43xx_freq_to_channel(bcm, data->freq.m);
+		freq = data->freq.m;
+	}
+	if (!bcm43xx_is_valid_channel(bcm, channel))
+		goto out_unlock;
+	if (bcm->initialized) {
+		//ieee80211softmac_disassoc(softmac, $REASON);
+		bcm43xx_mac_suspend(bcm);
+		err = bcm43xx_radio_selectchannel(bcm, channel, 0);
+		bcm43xx_mac_enable(bcm);
+	} else {
+		bcm43xx_current_radio(bcm)->initial_channel = channel;
+		err = 0;
+	}
+out_unlock:
+	bcm43xx_unlock_mmio(bcm, flags);
+
+	return err;
+}
+
+static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
+				      struct iw_request_info *info,
+				      union iwreq_data *data,
+				      char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	struct bcm43xx_radioinfo *radio;
+	unsigned long flags;
+	int err = -ENODEV;
+	u16 channel;
+
+	bcm43xx_lock(bcm, flags);
+	radio = bcm43xx_current_radio(bcm);
+	channel = radio->channel;
+	if (channel == 0xFF) {
+		assert(!bcm->initialized);
+		channel = radio->initial_channel;
+		if (channel == 0xFF)
+			goto out_unlock;
+	}
+	assert(channel > 0 && channel <= 1000);
+	data->freq.e = 1;
+	data->freq.m = bcm43xx_channel_to_freq(bcm, channel) * 100000;
+	data->freq.flags = 1;
+
+	err = 0;
+out_unlock:
+	bcm43xx_unlock(bcm, flags);
+
+	return err;
+}
+
+static int bcm43xx_wx_set_mode(struct net_device *net_dev,
+			       struct iw_request_info *info,
+			       union iwreq_data *data,
+			       char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	int mode;
+
+	mode = data->mode;
+	if (mode == IW_MODE_AUTO)
+		mode = BCM43xx_INITIAL_IWMODE;
+
+	bcm43xx_lock_mmio(bcm, flags);
+	if (bcm->ieee->iw_mode != mode)
+		bcm43xx_set_iwmode(bcm, mode);
+	bcm43xx_unlock_mmio(bcm, flags);
+
+	return 0;
+}
+
+static int bcm43xx_wx_get_mode(struct net_device *net_dev,
+			       struct iw_request_info *info,
+			       union iwreq_data *data,
+			       char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+
+	bcm43xx_lock(bcm, flags);
+	data->mode = bcm->ieee->iw_mode;
+	bcm43xx_unlock(bcm, flags);
+
+	return 0;
+}
+
+static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
+				      struct iw_request_info *info,
+				      union iwreq_data *data,
+				      char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	struct iw_range *range = (struct iw_range *)extra;
+	const struct ieee80211_geo *geo;
+	unsigned long flags;
+	int i, j;
+	struct bcm43xx_phyinfo *phy;
+
+	data->data.length = sizeof(*range);
+	memset(range, 0, sizeof(*range));
+
+	//TODO: What about 802.11b?
+	/* 54Mb/s == ~27Mb/s payload throughput (802.11g) */
+	range->throughput = 27 * 1000 * 1000;
+
+	range->max_qual.qual = 100;
+	/* TODO: Real max RSSI */
+	range->max_qual.level = 3;
+	range->max_qual.noise = 100;
+	range->max_qual.updated = 7;
+
+	range->avg_qual.qual = 70;
+	range->avg_qual.level = 2;
+	range->avg_qual.noise = 40;
+	range->avg_qual.updated = 7;
+
+	range->min_rts = BCM43xx_MIN_RTS_THRESHOLD;
+	range->max_rts = BCM43xx_MAX_RTS_THRESHOLD;
+	range->min_frag = MIN_FRAG_THRESHOLD;
+	range->max_frag = MAX_FRAG_THRESHOLD;
+
+	range->encoding_size[0] = 5;
+	range->encoding_size[1] = 13;
+	range->num_encoding_sizes = 2;
+	range->max_encoding_tokens = WEP_KEYS;
+
+	range->we_version_compiled = WIRELESS_EXT;
+	range->we_version_source = BCM43xx_WX_VERSION;
+
+	range->enc_capa = IW_ENC_CAPA_WPA |
+			  IW_ENC_CAPA_WPA2 |
+			  IW_ENC_CAPA_CIPHER_TKIP |
+			  IW_ENC_CAPA_CIPHER_CCMP;
+
+	bcm43xx_lock(bcm, flags);
+	phy = bcm43xx_current_phy(bcm);
+
+	range->num_bitrates = 0;
+	i = 0;
+	if (phy->type == BCM43xx_PHYTYPE_A ||
+	    phy->type == BCM43xx_PHYTYPE_G) {
+		range->num_bitrates = 8;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB;
+		range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB;
+	}
+	if (phy->type == BCM43xx_PHYTYPE_B ||
+	    phy->type == BCM43xx_PHYTYPE_G) {
+		range->num_bitrates += 4;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_1MB;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_2MB;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_5MB;
+		range->bitrate[i++] = IEEE80211_CCK_RATE_11MB;
+	}
+
+	geo = ieee80211_get_geo(bcm->ieee);
+	range->num_channels = geo->a_channels + geo->bg_channels;
+	j = 0;
+	for (i = 0; i < geo->a_channels; i++) {
+		if (j == IW_MAX_FREQUENCIES)
+			break;
+		range->freq[j].i = j + 1;
+		range->freq[j].m = geo->a[i].freq;//FIXME?
+		range->freq[j].e = 1;
+		j++;
+	}
+	for (i = 0; i < geo->bg_channels; i++) {
+		if (j == IW_MAX_FREQUENCIES)
+			break;
+		range->freq[j].i = j + 1;
+		range->freq[j].m = geo->bg[i].freq;//FIXME?
+		range->freq[j].e = 1;
+		j++;
+	}
+	range->num_frequency = j;
+
+	bcm43xx_unlock(bcm, flags);
+
+	return 0;
+}
+
+static int bcm43xx_wx_set_nick(struct net_device *net_dev,
+			       struct iw_request_info *info,
+			       union iwreq_data *data,
+			       char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	size_t len;
+
+	bcm43xx_lock(bcm, flags);
+	len =  min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
+	memcpy(bcm->nick, extra, len);
+	bcm->nick[len] = '\0';
+	bcm43xx_unlock(bcm, flags);
+
+	return 0;
+}
+
+static int bcm43xx_wx_get_nick(struct net_device *net_dev,
+			       struct iw_request_info *info,
+			       union iwreq_data *data,
+			       char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	size_t len;
+
+	bcm43xx_lock(bcm, flags);
+	len = strlen(bcm->nick) + 1;
+	memcpy(extra, bcm->nick, len);
+	data->data.length = (__u16)len;
+	data->data.flags = 1;
+	bcm43xx_unlock(bcm, flags);
+
+	return 0;
+}
+
+static int bcm43xx_wx_set_rts(struct net_device *net_dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *data,
+			      char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	int err = -EINVAL;
+
+	bcm43xx_lock(bcm, flags);
+	if (data->rts.disabled) {
+		bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
+		err = 0;
+	} else {
+		if (data->rts.value >= BCM43xx_MIN_RTS_THRESHOLD &&
+		    data->rts.value <= BCM43xx_MAX_RTS_THRESHOLD) {
+			bcm->rts_threshold = data->rts.value;
+			err = 0;
+		}
+	}
+	bcm43xx_unlock(bcm, flags);
+
+	return err;
+}
+
+static int bcm43xx_wx_get_rts(struct net_device *net_dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *data,
+			      char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+
+	bcm43xx_lock(bcm, flags);
+	data->rts.value = bcm->rts_threshold;
+	data->rts.fixed = 0;
+	data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
+	bcm43xx_unlock(bcm, flags);
+
+	return 0;
+}
+
+static int bcm43xx_wx_set_frag(struct net_device *net_dev,
+			       struct iw_request_info *info,
+			       union iwreq_data *data,
+			       char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	int err = -EINVAL;
+
+	bcm43xx_lock(bcm, flags);
+	if (data->frag.disabled) {
+		bcm->ieee->fts = MAX_FRAG_THRESHOLD;
+		err = 0;
+	} else {
+		if (data->frag.value >= MIN_FRAG_THRESHOLD &&
+		    data->frag.value <= MAX_FRAG_THRESHOLD) {
+			bcm->ieee->fts = data->frag.value & ~0x1;
+			err = 0;
+		}
+	}
+	bcm43xx_unlock(bcm, flags);
+
+	return err;
+}
+
+static int bcm43xx_wx_get_frag(struct net_device *net_dev,
+			       struct iw_request_info *info,
+			       union iwreq_data *data,
+			       char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+
+	bcm43xx_lock(bcm, flags);
+	data->frag.value = bcm->ieee->fts;
+	data->frag.fixed = 0;
+	data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
+	bcm43xx_unlock(bcm, flags);
+
+	return 0;
+}
+
+static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
+				    struct iw_request_info *info,
+				    union iwreq_data *data,
+				    char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	struct bcm43xx_radioinfo *radio;
+	struct bcm43xx_phyinfo *phy;
+	unsigned long flags;
+	int err = -ENODEV;
+	u16 maxpower;
+
+	if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
+		printk(PFX KERN_ERR "TX power not in dBm.\n");
+		return -EOPNOTSUPP;
+	}
+
+	bcm43xx_lock_mmio(bcm, flags);
+	if (!bcm->initialized)
+		goto out_unlock;
+	radio = bcm43xx_current_radio(bcm);
+	phy = bcm43xx_current_phy(bcm);
+	if (data->txpower.disabled != (!(radio->enabled))) {
+		if (data->txpower.disabled)
+			bcm43xx_radio_turn_off(bcm);
+		else
+			bcm43xx_radio_turn_on(bcm);
+	}
+	if (data->txpower.value > 0) {
+		/* desired and maxpower dBm values are in Q5.2 */
+		if (phy->type == BCM43xx_PHYTYPE_A)
+			maxpower = bcm->sprom.maxpower_aphy;
+		else
+			maxpower = bcm->sprom.maxpower_bgphy;
+		radio->txpower_desired = limit_value(data->txpower.value << 2,
+						     0, maxpower);
+		bcm43xx_phy_xmitpower(bcm);
+	}
+	err = 0;
+
+out_unlock:
+	bcm43xx_unlock_mmio(bcm, flags);
+
+	return err;
+}
+
+static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
+				    struct iw_request_info *info,
+				    union iwreq_data *data,
+				    char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	struct bcm43xx_radioinfo *radio;
+	unsigned long flags;
+	int err = -ENODEV;
+
+	bcm43xx_lock(bcm, flags);
+	if (!bcm->initialized)
+		goto out_unlock;
+	radio = bcm43xx_current_radio(bcm);
+	/* desired dBm value is in Q5.2 */
+	data->txpower.value = radio->txpower_desired >> 2;
+	data->txpower.fixed = 1;
+	data->txpower.flags = IW_TXPOW_DBM;
+	data->txpower.disabled = !(radio->enabled);
+
+	err = 0;
+out_unlock:
+	bcm43xx_unlock(bcm, flags);
+
+	return err;
+}
+
+static int bcm43xx_wx_set_encoding(struct net_device *net_dev,
+				   struct iw_request_info *info,
+				   union iwreq_data *data,
+				   char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	int err;
+
+	err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra);
+
+	return err;
+}
+
+static int bcm43xx_wx_set_encodingext(struct net_device *net_dev,
+                                   struct iw_request_info *info,
+                                   union iwreq_data *data,
+                                   char *extra)
+{
+        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+        int err;
+
+        err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra);
+
+        return err;
+}
+
+static int bcm43xx_wx_get_encoding(struct net_device *net_dev,
+				   struct iw_request_info *info,
+				   union iwreq_data *data,
+				   char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	int err;
+
+	err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra);
+
+	return err;
+}
+
+static int bcm43xx_wx_get_encodingext(struct net_device *net_dev,
+                                   struct iw_request_info *info,
+                                   union iwreq_data *data,
+                                   char *extra)
+{
+        struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+        int err;
+
+        err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra);
+
+        return err;
+}
+
+static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
+				     struct iw_request_info *info,
+				     union iwreq_data *data,
+				     char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	int mode, err = 0;
+
+	mode = *((int *)extra);
+	switch (mode) {
+	case 0:
+		mode = BCM43xx_RADIO_INTERFMODE_NONE;
+		break;
+	case 1:
+		mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
+		break;
+	case 2:
+		mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
+		break;
+	case 3:
+		mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
+		break;
+	default:
+		printk(KERN_ERR PFX "set_interfmode allowed parameters are: "
+				    "0 => None,  1 => Non-WLAN,  2 => WLAN,  "
+				    "3 => Auto-WLAN\n");
+		return -EINVAL;
+	}
+
+	bcm43xx_lock_mmio(bcm, flags);
+	if (bcm->initialized) {
+		err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
+		if (err) {
+			printk(KERN_ERR PFX "Interference Mitigation not "
+					    "supported by device\n");
+		}
+	} else {
+		if (mode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN) {
+			printk(KERN_ERR PFX "Interference Mitigation mode Auto-WLAN "
+					    "not supported while the interface is down.\n");
+			err = -ENODEV;
+		} else
+			bcm43xx_current_radio(bcm)->interfmode = mode;
+	}
+	bcm43xx_unlock_mmio(bcm, flags);
+
+	return err;
+}
+
+static int bcm43xx_wx_get_interfmode(struct net_device *net_dev,
+				     struct iw_request_info *info,
+				     union iwreq_data *data,
+				     char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	int mode;
+
+	bcm43xx_lock(bcm, flags);
+	mode = bcm43xx_current_radio(bcm)->interfmode;
+	bcm43xx_unlock(bcm, flags);
+
+	switch (mode) {
+	case BCM43xx_RADIO_INTERFMODE_NONE:
+		strncpy(extra, "0 (No Interference Mitigation)", MAX_WX_STRING);
+		break;
+	case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+		strncpy(extra, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING);
+		break;
+	case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+		strncpy(extra, "2 (WLAN Interference Mitigation)", MAX_WX_STRING);
+		break;
+	default:
+		assert(0);
+	}
+	data->data.length = strlen(extra) + 1;
+
+	return 0;
+}
+
+static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev,
+					struct iw_request_info *info,
+					union iwreq_data *data,
+					char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	int on;
+
+	on = *((int *)extra);
+	bcm43xx_lock(bcm, flags);
+	bcm->short_preamble = !!on;
+	bcm43xx_unlock(bcm, flags);
+
+	return 0;
+}
+
+static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev,
+					struct iw_request_info *info,
+					union iwreq_data *data,
+					char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	int on;
+
+	bcm43xx_lock(bcm, flags);
+	on = bcm->short_preamble;
+	bcm43xx_unlock(bcm, flags);
+
+	if (on)
+		strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
+	else
+		strncpy(extra, "0 (Short Preamble disabled)", MAX_WX_STRING);
+	data->data.length = strlen(extra) + 1;
+
+	return 0;
+}
+
+static int bcm43xx_wx_set_swencryption(struct net_device *net_dev,
+				       struct iw_request_info *info,
+				       union iwreq_data *data,
+				       char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	int on;
+	
+	on = *((int *)extra);
+
+	bcm43xx_lock(bcm, flags);
+	bcm->ieee->host_encrypt = !!on;
+	bcm->ieee->host_decrypt = !!on;
+	bcm->ieee->host_build_iv = !on;
+	bcm43xx_unlock(bcm, flags);
+
+	return 0;
+}
+
+static int bcm43xx_wx_get_swencryption(struct net_device *net_dev,
+				       struct iw_request_info *info,
+				       union iwreq_data *data,
+				       char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	unsigned long flags;
+	int on;
+
+	bcm43xx_lock(bcm, flags);
+	on = bcm->ieee->host_encrypt;
+	bcm43xx_unlock(bcm, flags);
+
+	if (on)
+		strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
+	else
+		strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING);
+	data->data.length = strlen(extra + 1);
+
+	return 0;
+}
+
+/* Enough buffer to hold a hexdump of the sprom data. */
+#define SPROM_BUFFERSIZE	512
+
+static int sprom2hex(const u16 *sprom, char *dump)
+{
+	int i, pos = 0;
+
+	for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+		pos += snprintf(dump + pos, SPROM_BUFFERSIZE - pos - 1,
+				"%04X", swab16(sprom[i]) & 0xFFFF);
+	}
+
+	return pos + 1;
+}
+
+static int hex2sprom(u16 *sprom, const char *dump, unsigned int len)
+{
+	char tmp[5] = { 0 };
+	int cnt = 0;
+	unsigned long parsed;
+
+	if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
+		return -EINVAL;
+	while (cnt < BCM43xx_SPROM_SIZE) {
+		memcpy(tmp, dump, 4);
+		dump += 4;
+		parsed = simple_strtoul(tmp, NULL, 16);
+		sprom[cnt++] = swab16((u16)parsed);
+	}
+
+	return 0;
+}
+
+static int bcm43xx_wx_sprom_read(struct net_device *net_dev,
+				 struct iw_request_info *info,
+				 union iwreq_data *data,
+				 char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	int err = -EPERM;
+	u16 *sprom;
+	unsigned long flags;
+
+	if (!capable(CAP_SYS_RAWIO))
+		goto out;
+
+	err = -ENOMEM;
+	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+			GFP_KERNEL);
+	if (!sprom)
+		goto out;
+
+	bcm43xx_lock_mmio(bcm, flags);
+	err = -ENODEV;
+	if (bcm->initialized)
+		err = bcm43xx_sprom_read(bcm, sprom);
+	bcm43xx_unlock_mmio(bcm, flags);
+	if (!err)
+		data->data.length = sprom2hex(sprom, extra);
+	kfree(sprom);
+out:
+	return err;
+}
+
+static int bcm43xx_wx_sprom_write(struct net_device *net_dev,
+				  struct iw_request_info *info,
+				  union iwreq_data *data,
+				  char *extra)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	int err = -EPERM;
+	u16 *sprom;
+	unsigned long flags;
+	char *input;
+	unsigned int len;
+
+	if (!capable(CAP_SYS_RAWIO))
+		goto out;
+
+	err = -ENOMEM;
+	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+			GFP_KERNEL);
+	if (!sprom)
+		goto out;
+
+	len = data->data.length;
+	extra[len - 1] = '\0';
+	input = strchr(extra, ':');
+	if (input) {
+		input++;
+		len -= input - extra;
+	} else
+		input = extra;
+	err = hex2sprom(sprom, input, len);
+	if (err)
+		goto out_kfree;
+
+	bcm43xx_lock_mmio(bcm, flags);
+	err = -ENODEV;
+	if (bcm->initialized)
+		err = bcm43xx_sprom_write(bcm, sprom);
+	bcm43xx_unlock_mmio(bcm, flags);
+out_kfree:
+	kfree(sprom);
+out:
+	return err;
+}
+
+/* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
+
+static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_dev)
+{
+	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
+	struct iw_statistics *wstats;
+
+	wstats = &bcm->stats.wstats;
+	if (!mac->associated) {
+		wstats->miss.beacon = 0;
+//		bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here?
+		wstats->discard.retries = 0;
+//		bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question
+		wstats->discard.nwid = 0;
+//		bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto
+		wstats->discard.code = 0;
+//		bcm->ieee->ieee_stats.rx_fragments = 0;  // FIXME: same here
+		wstats->discard.fragment = 0;
+		wstats->discard.misc = 0;
+		wstats->qual.qual = 0;
+		wstats->qual.level = 0;
+		wstats->qual.noise = 0;
+		wstats->qual.updated = 7;
+		wstats->qual.updated |= IW_QUAL_NOISE_INVALID |
+			IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
+		return wstats;
+	}
+	/* fill in the real statistics when iface associated */
+	wstats->qual.qual = 100;     // TODO: get the real signal quality
+	wstats->qual.level = 3 - bcm->stats.link_quality;
+	wstats->qual.noise = bcm->stats.noise;
+	wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
+			IW_QUAL_NOISE_UPDATED;
+	wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable;
+	wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded;
+	wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa;
+	wstats->discard.fragment = bcm->ieee->ieee_stats.rx_fragments;
+	wstats->discard.misc = 0;	// FIXME
+	wstats->miss.beacon = 0;	// FIXME
+	return wstats;
+}
+
+
+#ifdef WX
+# undef WX
+#endif
+#define WX(ioctl)  [(ioctl) - SIOCSIWCOMMIT]
+static const iw_handler bcm43xx_wx_handlers[] = {
+	/* Wireless Identification */
+	WX(SIOCGIWNAME)		= bcm43xx_wx_get_name,
+	/* Basic operations */
+	WX(SIOCSIWFREQ)		= bcm43xx_wx_set_channelfreq,
+	WX(SIOCGIWFREQ)		= bcm43xx_wx_get_channelfreq,
+	WX(SIOCSIWMODE)		= bcm43xx_wx_set_mode,
+	WX(SIOCGIWMODE)		= bcm43xx_wx_get_mode,
+	/* Informative stuff */
+	WX(SIOCGIWRANGE)	= bcm43xx_wx_get_rangeparams,
+	/* Access Point manipulation */
+	WX(SIOCSIWAP)           = ieee80211softmac_wx_set_wap,
+	WX(SIOCGIWAP)           = ieee80211softmac_wx_get_wap,
+	WX(SIOCSIWSCAN)		= ieee80211softmac_wx_trigger_scan,
+	WX(SIOCGIWSCAN)		= ieee80211softmac_wx_get_scan_results,
+	/* 802.11 specific support */
+	WX(SIOCSIWESSID)	= ieee80211softmac_wx_set_essid,
+	WX(SIOCGIWESSID)	= ieee80211softmac_wx_get_essid,
+	WX(SIOCSIWNICKN)	= bcm43xx_wx_set_nick,
+	WX(SIOCGIWNICKN)	= bcm43xx_wx_get_nick,
+	/* Other parameters */
+	WX(SIOCSIWRATE)		= ieee80211softmac_wx_set_rate,
+	WX(SIOCGIWRATE)		= ieee80211softmac_wx_get_rate,
+	WX(SIOCSIWRTS)		= bcm43xx_wx_set_rts,
+	WX(SIOCGIWRTS)		= bcm43xx_wx_get_rts,
+	WX(SIOCSIWFRAG)		= bcm43xx_wx_set_frag,
+	WX(SIOCGIWFRAG)		= bcm43xx_wx_get_frag,
+	WX(SIOCSIWTXPOW)	= bcm43xx_wx_set_xmitpower,
+	WX(SIOCGIWTXPOW)	= bcm43xx_wx_get_xmitpower,
+//TODO	WX(SIOCSIWRETRY)	= bcm43xx_wx_set_retry,
+//TODO	WX(SIOCGIWRETRY)	= bcm43xx_wx_get_retry,
+	/* Encoding */
+	WX(SIOCSIWENCODE)	= bcm43xx_wx_set_encoding,
+	WX(SIOCGIWENCODE)	= bcm43xx_wx_get_encoding,
+	WX(SIOCSIWENCODEEXT)	= bcm43xx_wx_set_encodingext,
+	WX(SIOCGIWENCODEEXT)	= bcm43xx_wx_get_encodingext,
+	/* Power saving */
+//TODO	WX(SIOCSIWPOWER)	= bcm43xx_wx_set_power,
+//TODO	WX(SIOCGIWPOWER)	= bcm43xx_wx_get_power,
+	WX(SIOCSIWGENIE)	= ieee80211softmac_wx_set_genie,
+	WX(SIOCGIWGENIE)	= ieee80211softmac_wx_get_genie,
+	WX(SIOCSIWAUTH)		= ieee80211_wx_set_auth,
+	WX(SIOCGIWAUTH)		= ieee80211_wx_get_auth,
+};
+#undef WX
+
+static const iw_handler bcm43xx_priv_wx_handlers[] = {
+	/* Set Interference Mitigation Mode. */
+	bcm43xx_wx_set_interfmode,
+	/* Get Interference Mitigation Mode. */
+	bcm43xx_wx_get_interfmode,
+	/* Enable/Disable Short Preamble mode. */
+	bcm43xx_wx_set_shortpreamble,
+	/* Get Short Preamble mode. */
+	bcm43xx_wx_get_shortpreamble,
+	/* Enable/Disable Software Encryption mode */
+	bcm43xx_wx_set_swencryption,
+	/* Get Software Encryption mode */
+	bcm43xx_wx_get_swencryption,
+	/* Write SRPROM data. */
+	bcm43xx_wx_sprom_write,
+	/* Read SPROM data. */
+	bcm43xx_wx_sprom_read,
+};
+
+#define PRIV_WX_SET_INTERFMODE		(SIOCIWFIRSTPRIV + 0)
+#define PRIV_WX_GET_INTERFMODE		(SIOCIWFIRSTPRIV + 1)
+#define PRIV_WX_SET_SHORTPREAMBLE	(SIOCIWFIRSTPRIV + 2)
+#define PRIV_WX_GET_SHORTPREAMBLE	(SIOCIWFIRSTPRIV + 3)
+#define PRIV_WX_SET_SWENCRYPTION	(SIOCIWFIRSTPRIV + 4)
+#define PRIV_WX_GET_SWENCRYPTION	(SIOCIWFIRSTPRIV + 5)
+#define PRIV_WX_SPROM_WRITE		(SIOCIWFIRSTPRIV + 6)
+#define PRIV_WX_SPROM_READ		(SIOCIWFIRSTPRIV + 7)
+
+#define PRIV_WX_DUMMY(ioctl)	\
+	{					\
+		.cmd		= (ioctl),	\
+		.name		= "__unused"	\
+	}
+
+static const struct iw_priv_args bcm43xx_priv_wx_args[] = {
+	{
+		.cmd		= PRIV_WX_SET_INTERFMODE,
+		.set_args	= IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+		.name		= "set_interfmode",
+	},
+	{
+		.cmd		= PRIV_WX_GET_INTERFMODE,
+		.get_args	= IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+		.name		= "get_interfmode",
+	},
+	{
+		.cmd		= PRIV_WX_SET_SHORTPREAMBLE,
+		.set_args	= IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+		.name		= "set_shortpreambl",
+	},
+	{
+		.cmd		= PRIV_WX_GET_SHORTPREAMBLE,
+		.get_args	= IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+		.name		= "get_shortpreambl",
+	},
+	{
+		.cmd		= PRIV_WX_SET_SWENCRYPTION,
+		.set_args	= IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+		.name		= "set_swencryption",
+	},
+	{
+		.cmd		= PRIV_WX_GET_SWENCRYPTION,
+		.get_args	= IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+		.name		= "get_swencryption",
+	},
+	{
+		.cmd		= PRIV_WX_SPROM_WRITE,
+		.set_args	= IW_PRIV_TYPE_CHAR | SPROM_BUFFERSIZE,
+		.name		= "write_sprom",
+	},
+	{
+		.cmd		= PRIV_WX_SPROM_READ,
+		.get_args	= IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | SPROM_BUFFERSIZE,
+		.name		= "read_sprom",
+	},
+};
+
+const struct iw_handler_def bcm43xx_wx_handlers_def = {
+	.standard		= bcm43xx_wx_handlers,
+	.num_standard		= ARRAY_SIZE(bcm43xx_wx_handlers),
+	.num_private		= ARRAY_SIZE(bcm43xx_priv_wx_handlers),
+	.num_private_args	= ARRAY_SIZE(bcm43xx_priv_wx_args),
+	.private		= bcm43xx_priv_wx_handlers,
+	.private_args		= bcm43xx_priv_wx_args,
+	.get_wireless_stats	= bcm43xx_get_wireless_stats,
+};
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.h b/drivers/net/wireless/bcm43xx/bcm43xx_wx.h
new file mode 100644
index 0000000..1f29ff3
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.h
@@ -0,0 +1,36 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+                     Stefano Brivio <st3@riseup.net>
+                     Michael Buesch <mbuesch@freenet.de>
+                     Danny van Dyk <kugelfang@gentoo.org>
+                     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef BCM43xx_WX_H_
+#define BCM43xx_WX_H_
+
+extern const struct iw_handler_def bcm43xx_wx_handlers_def;
+
+#endif /* BCM43xx_WX_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
new file mode 100644
index 0000000..d8ece28
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
@@ -0,0 +1,582 @@
+/*
+
+  Broadcom BCM43xx wireless driver
+
+  Transmission (TX/RX) related functions.
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+                     Stefano Brivio <st3@riseup.net>
+                     Michael Buesch <mbuesch@freenet.de>
+                     Danny van Dyk <kugelfang@gentoo.org>
+                     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  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; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "bcm43xx_xmit.h"
+
+#include <linux/etherdevice.h>
+
+
+/* Extract the bitrate out of a CCK PLCP header. */
+static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp)
+{
+	switch (plcp->raw[0]) {
+	case 0x0A:
+		return IEEE80211_CCK_RATE_1MB;
+	case 0x14:
+		return IEEE80211_CCK_RATE_2MB;
+	case 0x37:
+		return IEEE80211_CCK_RATE_5MB;
+	case 0x6E:
+		return IEEE80211_CCK_RATE_11MB;
+	}
+	assert(0);
+	return 0;
+}
+
+/* Extract the bitrate out of an OFDM PLCP header. */
+static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr4 *plcp)
+{
+	switch (plcp->raw[0] & 0xF) {
+	case 0xB:
+		return IEEE80211_OFDM_RATE_6MB;
+	case 0xF:
+		return IEEE80211_OFDM_RATE_9MB;
+	case 0xA:
+		return IEEE80211_OFDM_RATE_12MB;
+	case 0xE:
+		return IEEE80211_OFDM_RATE_18MB;
+	case 0x9:
+		return IEEE80211_OFDM_RATE_24MB;
+	case 0xD:
+		return IEEE80211_OFDM_RATE_36MB;
+	case 0x8:
+		return IEEE80211_OFDM_RATE_48MB;
+	case 0xC:
+		return IEEE80211_OFDM_RATE_54MB;
+	}
+	assert(0);
+	return 0;
+}
+
+u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate)
+{
+	switch (bitrate) {
+	case IEEE80211_CCK_RATE_1MB:
+		return 0x0A;
+	case IEEE80211_CCK_RATE_2MB:
+		return 0x14;
+	case IEEE80211_CCK_RATE_5MB:
+		return 0x37;
+	case IEEE80211_CCK_RATE_11MB:
+		return 0x6E;
+	}
+	assert(0);
+	return 0;
+}
+
+u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate)
+{
+	switch (bitrate) {
+	case IEEE80211_OFDM_RATE_6MB:
+		return 0xB;
+	case IEEE80211_OFDM_RATE_9MB:
+		return 0xF;
+	case IEEE80211_OFDM_RATE_12MB:
+		return 0xA;
+	case IEEE80211_OFDM_RATE_18MB:
+		return 0xE;
+	case IEEE80211_OFDM_RATE_24MB:
+		return 0x9;
+	case IEEE80211_OFDM_RATE_36MB:
+		return 0xD;
+	case IEEE80211_OFDM_RATE_48MB:
+		return 0x8;
+	case IEEE80211_OFDM_RATE_54MB:
+		return 0xC;
+	}
+	assert(0);
+	return 0;
+}
+
+static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
+				      const u16 octets, const u8 bitrate,
+				      const int ofdm_modulation)
+{
+	__le32 *data = &(plcp->data);
+	__u8 *raw = plcp->raw;
+
+	if (ofdm_modulation) {
+		*data = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
+		assert(!(octets & 0xF000));
+		*data |= (octets << 5);
+		*data = cpu_to_le32(*data);
+	} else {
+		u32 plen;
+
+		plen = octets * 16 / bitrate;
+		if ((octets * 16 % bitrate) > 0) {
+			plen++;
+			if ((bitrate == IEEE80211_CCK_RATE_11MB)
+			    && ((octets * 8 % 11) < 4)) {
+				raw[1] = 0x84;
+			} else
+				raw[1] = 0x04;
+		} else
+			raw[1] = 0x04;
+		*data |= cpu_to_le32(plen << 16);
+		raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate);
+	}
+}
+
+static u8 bcm43xx_calc_fallback_rate(u8 bitrate)
+{
+	switch (bitrate) {
+	case IEEE80211_CCK_RATE_1MB:
+		return IEEE80211_CCK_RATE_1MB;
+	case IEEE80211_CCK_RATE_2MB:
+		return IEEE80211_CCK_RATE_1MB;
+	case IEEE80211_CCK_RATE_5MB:
+		return IEEE80211_CCK_RATE_2MB;
+	case IEEE80211_CCK_RATE_11MB:
+		return IEEE80211_CCK_RATE_5MB;
+	case IEEE80211_OFDM_RATE_6MB:
+		return IEEE80211_CCK_RATE_5MB;
+	case IEEE80211_OFDM_RATE_9MB:
+		return IEEE80211_OFDM_RATE_6MB;
+	case IEEE80211_OFDM_RATE_12MB:
+		return IEEE80211_OFDM_RATE_9MB;
+	case IEEE80211_OFDM_RATE_18MB:
+		return IEEE80211_OFDM_RATE_12MB;
+	case IEEE80211_OFDM_RATE_24MB:
+		return IEEE80211_OFDM_RATE_18MB;
+	case IEEE80211_OFDM_RATE_36MB:
+		return IEEE80211_OFDM_RATE_24MB;
+	case IEEE80211_OFDM_RATE_48MB:
+		return IEEE80211_OFDM_RATE_36MB;
+	case IEEE80211_OFDM_RATE_54MB:
+		return IEEE80211_OFDM_RATE_48MB;
+	}
+	assert(0);
+	return 0;
+}
+
+static
+__le16 bcm43xx_calc_duration_id(const struct ieee80211_hdr *wireless_header,
+				u8 bitrate)
+{
+	const u16 frame_ctl = le16_to_cpu(wireless_header->frame_ctl);
+	__le16 duration_id = wireless_header->duration_id;
+
+	switch (WLAN_FC_GET_TYPE(frame_ctl)) {
+	case IEEE80211_FTYPE_DATA:
+	case IEEE80211_FTYPE_MGMT:
+		//TODO: Steal the code from ieee80211, once it is completed there.
+		break;
+	case IEEE80211_FTYPE_CTL:
+		/* Use the original duration/id. */
+		break;
+	default:
+		assert(0);
+	}
+
+	return duration_id;
+}
+
+static inline
+u16 ceiling_div(u16 dividend, u16 divisor)
+{
+	return ((dividend + divisor - 1) / divisor);
+}
+
+static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy,
+				 struct bcm43xx_txhdr *txhdr,
+				 u16 *flags,
+				 u8 bitrate,
+				 const struct ieee80211_hdr_4addr *wlhdr)
+{
+	u16 fctl;
+	u16 dur;
+	u8 fallback_bitrate;
+	int ofdm_modulation;
+	int fallback_ofdm_modulation;
+//	u8 *sa, *da;
+	u16 flen;
+
+//FIXME	sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr);
+//FIXME	da = ieee80211_get_DA((struct ieee80211_hdr *)wlhdr);
+	fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
+	ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
+	fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
+
+	flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + IEEE80211_FCS_LEN,
+	bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_plcp),
+				  flen, bitrate,
+				  !ieee80211_is_cck_rate(bitrate));
+	bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_fallback_plcp),
+				  flen, fallback_bitrate,
+				  !ieee80211_is_cck_rate(fallback_bitrate));
+	fctl = IEEE80211_FTYPE_CTL;
+	fctl |= IEEE80211_STYPE_RTS;
+	dur = le16_to_cpu(wlhdr->duration_id);
+/*FIXME: should we test for dur==0 here and let it unmodified in this case?
+ *       The following assert checks for this case...
+ */
+assert(dur);
+/*FIXME: The duration calculation is not really correct.
+ *       I am not 100% sure which bitrate to use. We use the RTS rate here,
+ *       but this is likely to be wrong.
+ */
+	if (phy->type == BCM43xx_PHYTYPE_A) {
+		/* Three times SIFS */
+		dur += 16 * 3;
+		/* Add ACK duration. */
+		dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
+				   bitrate * 4);
+		/* Add CTS duration. */
+		dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
+				   bitrate * 4);
+	} else {
+		/* Three times SIFS */
+		dur += 10 * 3;
+		/* Add ACK duration. */
+		dur += ceiling_div(8 * (14 /*bytes*/) * 10,
+				   bitrate);
+		/* Add CTS duration. */
+		dur += ceiling_div(8 * (14 /*bytes*/) * 10,
+				   bitrate);
+	}
+
+	txhdr->rts_cts_frame_control = cpu_to_le16(fctl);
+	txhdr->rts_cts_dur = cpu_to_le16(dur);
+//printk(BCM43xx_MACFMT "  " BCM43xx_MACFMT "  " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3));
+//printk(BCM43xx_MACFMT "  " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da));
+	memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME!
+//	memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN);
+
+	*flags |= BCM43xx_TXHDRFLAG_RTSCTS;
+	*flags |= BCM43xx_TXHDRFLAG_RTS;
+	if (ofdm_modulation)
+		*flags |= BCM43xx_TXHDRFLAG_RTSCTS_OFDM;
+	if (fallback_ofdm_modulation)
+		*flags |= BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM;
+}
+				 
+void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
+			    struct bcm43xx_txhdr *txhdr,
+			    const unsigned char *fragment_data,
+			    const unsigned int fragment_len,
+			    const int is_first_fragment,
+			    const u16 cookie)
+{
+	const struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data;
+	const struct ieee80211_security *secinfo = &bcm->ieee->sec;
+	u8 bitrate;
+	u8 fallback_bitrate;
+	int ofdm_modulation;
+	int fallback_ofdm_modulation;
+	u16 plcp_fragment_len = fragment_len;
+	u16 flags = 0;
+	u16 control = 0;
+	u16 wsec_rate = 0;
+	u16 encrypt_frame;
+
+	/* Now construct the TX header. */
+	memset(txhdr, 0, sizeof(*txhdr));
+
+	bitrate = bcm->softmac->txrates.default_rate;
+	ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
+	fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
+	fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
+
+	/* Set Frame Control from 80211 header. */
+	txhdr->frame_control = wireless_header->frame_ctl;
+	/* Copy address1 from 80211 header. */
+	memcpy(txhdr->mac1, wireless_header->addr1, 6);
+	/* Set the fallback duration ID. */
+	txhdr->fallback_dur_id = bcm43xx_calc_duration_id((const struct ieee80211_hdr *)wireless_header,
+							  fallback_bitrate);
+	/* Set the cookie (used as driver internal ID for the frame) */
+	txhdr->cookie = cpu_to_le16(cookie);
+
+	/* Hardware appends FCS. */
+	plcp_fragment_len += IEEE80211_FCS_LEN;
+
+	/* Hardware encryption. */
+	encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED;
+	if (encrypt_frame && !bcm->ieee->host_encrypt) {
+		const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header;
+		memcpy(txhdr->wep_iv, hdr->payload, 4);
+		/* Hardware appends ICV. */
+		plcp_fragment_len += 4;
+
+		wsec_rate |= (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT)
+			     & BCM43xx_TXHDR_WSEC_ALGO_MASK;
+		wsec_rate |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT)
+			     & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK;
+	}
+
+	/* Generate the PLCP header and the fallback PLCP header. */
+	bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
+				  plcp_fragment_len,
+				  bitrate, ofdm_modulation);
+	bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len,
+				  fallback_bitrate, fallback_ofdm_modulation);
+
+	/* Set the CONTROL field */
+	if (ofdm_modulation)
+		control |= BCM43xx_TXHDRCTL_OFDM;
+	if (bcm->short_preamble) //FIXME: could be the other way around, please test
+		control |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE;
+	control |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT)
+		   & BCM43xx_TXHDRCTL_ANTENNADIV_MASK;
+
+	/* Set the FLAGS field */
+	if (!is_multicast_ether_addr(wireless_header->addr1) &&
+	    !is_broadcast_ether_addr(wireless_header->addr1))
+		flags |= BCM43xx_TXHDRFLAG_EXPECTACK;
+	if (1 /* FIXME: PS poll?? */)
+		flags |= 0x10; // FIXME: unknown meaning.
+	if (fallback_ofdm_modulation)
+		flags |= BCM43xx_TXHDRFLAG_FALLBACKOFDM;
+	if (is_first_fragment)
+		flags |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT;
+
+	/* Set WSEC/RATE field */
+	wsec_rate |= (txhdr->plcp.raw[0] << BCM43xx_TXHDR_RATE_SHIFT)
+		     & BCM43xx_TXHDR_RATE_MASK;
+
+	/* Generate the RTS/CTS packet, if required. */
+	/* FIXME: We should first try with CTS-to-self,
+	 *        if we are on 80211g. If we get too many
+	 *        failures (hidden nodes), we should switch back to RTS/CTS.
+	 */
+	if (0/*FIXME txctl->use_rts_cts*/) {
+		bcm43xx_generate_rts(phy, txhdr, &flags,
+				     0/*FIXME txctl->rts_cts_rate*/,
+				     wireless_header);
+	}
+
+	txhdr->flags = cpu_to_le16(flags);
+	txhdr->control = cpu_to_le16(control);
+	txhdr->wsec_rate = cpu_to_le16(wsec_rate);
+}
+
+static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm,
+				   u8 in_rssi, int ofdm,
+				   int adjust_2053, int adjust_2050)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	s32 tmp;
+
+	switch (radio->version) {
+	case 0x2050:
+		if (ofdm) {
+			tmp = in_rssi;
+			if (tmp > 127)
+				tmp -= 256;
+			tmp *= 73;
+			tmp /= 64;
+			if (adjust_2050)
+				tmp += 25;
+			else
+				tmp -= 3;
+		} else {
+			if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+				if (in_rssi > 63)
+					in_rssi = 63;
+				tmp = radio->nrssi_lt[in_rssi];
+				tmp = 31 - tmp;
+				tmp *= -131;
+				tmp /= 128;
+				tmp -= 57;
+			} else {
+				tmp = in_rssi;
+				tmp = 31 - tmp;
+				tmp *= -149;
+				tmp /= 128;
+				tmp -= 68;
+			}
+			if (phy->type == BCM43xx_PHYTYPE_G &&
+			    adjust_2050)
+				tmp += 25;
+		}
+		break;
+	case 0x2060:
+		if (in_rssi > 127)
+			tmp = in_rssi - 256;
+		else
+			tmp = in_rssi;
+		break;
+	default:
+		tmp = in_rssi;
+		tmp -= 11;
+		tmp *= 103;
+		tmp /= 64;
+		if (adjust_2053)
+			tmp -= 109;
+		else
+			tmp -= 83;
+	}
+
+	return (s8)tmp;
+}
+
+//TODO
+#if 0
+static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm,
+					u8 in_rssi)
+{
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	s8 ret;
+
+	if (phy->type == BCM43xx_PHYTYPE_A) {
+		//TODO: Incomplete specs.
+		ret = 0;
+	} else
+		ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1);
+
+	return ret;
+}
+#endif
+
+int bcm43xx_rx(struct bcm43xx_private *bcm,
+	       struct sk_buff *skb,
+	       struct bcm43xx_rxhdr *rxhdr)
+{
+	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	struct bcm43xx_plcp_hdr4 *plcp;
+	struct ieee80211_rx_stats stats;
+	struct ieee80211_hdr_4addr *wlhdr;
+	u16 frame_ctl;
+	int is_packet_for_us = 0;
+	int err = -EINVAL;
+	const u16 rxflags1 = le16_to_cpu(rxhdr->flags1);
+	const u16 rxflags2 = le16_to_cpu(rxhdr->flags2);
+	const u16 rxflags3 = le16_to_cpu(rxhdr->flags3);
+	const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM);
+
+	if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) {
+		plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2);
+		/* Skip two unknown bytes and the PLCP header. */
+		skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6));
+	} else {
+		plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data);
+		/* Skip the PLCP header. */
+		skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6));
+	}
+	/* The SKB contains the PAYLOAD (wireless header + data)
+	 * at this point. The FCS at the end is stripped.
+	 */
+
+	memset(&stats, 0, sizeof(stats));
+	stats.mac_time = le16_to_cpu(rxhdr->mactime);
+	stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
+					      !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
+					      !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
+	stats.signal = rxhdr->signal_quality;	//FIXME
+//TODO	stats.noise = 
+	if (is_ofdm)
+		stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
+	else
+		stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
+//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate);
+	stats.received_channel = radio->channel;
+//TODO	stats.control = 
+	stats.mask = IEEE80211_STATMASK_SIGNAL |
+//TODO		     IEEE80211_STATMASK_NOISE |
+		     IEEE80211_STATMASK_RATE |
+		     IEEE80211_STATMASK_RSSI;
+	if (phy->type == BCM43xx_PHYTYPE_A)
+		stats.freq = IEEE80211_52GHZ_BAND;
+	else
+		stats.freq = IEEE80211_24GHZ_BAND;
+	stats.len = skb->len;
+
+	bcm->stats.last_rx = jiffies;
+	if (bcm->ieee->iw_mode == IW_MODE_MONITOR) {
+		err = ieee80211_rx(bcm->ieee, skb, &stats);
+		return (err == 0) ? -EINVAL : 0;
+	}
+
+	wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
+
+	switch (bcm->ieee->iw_mode) {
+	case IW_MODE_ADHOC:
+		if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
+		    memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
+		    is_broadcast_ether_addr(wlhdr->addr1) ||
+		    is_multicast_ether_addr(wlhdr->addr1) ||
+		    bcm->net_dev->flags & IFF_PROMISC)
+			is_packet_for_us = 1;
+		break;
+	case IW_MODE_INFRA:
+	default:
+		/* When receiving multicast or broadcast packets, filter out
+		   the packets we send ourself; we shouldn't see those */
+		if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
+		    memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
+		    (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) &&
+		     (is_broadcast_ether_addr(wlhdr->addr1) ||
+		      is_multicast_ether_addr(wlhdr->addr1) ||
+		      bcm->net_dev->flags & IFF_PROMISC)))
+			is_packet_for_us = 1;
+		break;
+	}
+
+	frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
+	if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) {
+		frame_ctl &= ~IEEE80211_FCTL_PROTECTED;
+		wlhdr->frame_ctl = cpu_to_le16(frame_ctl);		
+		/* trim IV and ICV */
+		/* FIXME: this must be done only for WEP encrypted packets */
+		if (skb->len < 32) {
+			dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag "
+					      "set and length < 32)\n");
+			return -EINVAL;
+		} else {		
+			memmove(skb->data + 4, skb->data, 24);
+			skb_pull(skb, 4);
+			skb_trim(skb, skb->len - 4);
+			stats.len -= 8;
+		}
+		wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
+	}
+	
+	switch (WLAN_FC_GET_TYPE(frame_ctl)) {
+	case IEEE80211_FTYPE_MGMT:
+		ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);
+		break;
+	case IEEE80211_FTYPE_DATA:
+		if (is_packet_for_us) {
+			err = ieee80211_rx(bcm->ieee, skb, &stats);
+			err = (err == 0) ? -EINVAL : 0;
+		}
+		break;
+	case IEEE80211_FTYPE_CTL:
+		break;
+	default:
+		assert(0);
+		return -EINVAL;
+	}
+
+	return err;
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
new file mode 100644
index 0000000..2aed19e
--- /dev/null
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
@@ -0,0 +1,156 @@
+#ifndef BCM43xx_XMIT_H_
+#define BCM43xx_XMIT_H_
+
+#include "bcm43xx_main.h"
+
+
+#define _bcm43xx_declare_plcp_hdr(size) \
+	struct bcm43xx_plcp_hdr##size {		\
+		union {				\
+			__le32 data;		\
+			__u8 raw[size];		\
+		} __attribute__((__packed__));	\
+	} __attribute__((__packed__))
+
+/* struct bcm43xx_plcp_hdr4 */
+_bcm43xx_declare_plcp_hdr(4);
+/* struct bcm43xx_plcp_hdr6 */
+_bcm43xx_declare_plcp_hdr(6);
+
+#undef _bcm43xx_declare_plcp_hdr
+
+/* Device specific TX header. To be prepended to TX frames. */
+struct bcm43xx_txhdr {
+	union {
+		struct {
+			__le16 flags;
+			__le16 wsec_rate;
+			__le16 frame_control;
+			u16 unknown_zeroed_0;
+			__le16 control;
+			u8 wep_iv[10];
+			u8 unknown_wsec_tkip_data[3]; //FIXME
+			PAD_BYTES(3);
+			u8 mac1[6];
+			u16 unknown_zeroed_1;
+			struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp;
+			__le16 rts_cts_dur_fallback;
+			struct bcm43xx_plcp_hdr4 fallback_plcp;
+			__le16 fallback_dur_id;
+			PAD_BYTES(2);
+			__le16 cookie;
+			__le16 unknown_scb_stuff; //FIXME
+			struct bcm43xx_plcp_hdr6 rts_cts_plcp;
+			__le16 rts_cts_frame_control;
+			__le16 rts_cts_dur;
+			u8 rts_cts_mac1[6];
+			u8 rts_cts_mac2[6];
+			PAD_BYTES(2);
+			struct bcm43xx_plcp_hdr6 plcp;
+		} __attribute__((__packed__));
+		u8 raw[82];
+	} __attribute__((__packed__));
+} __attribute__((__packed__));
+
+/* Values/Masks for the device TX header */
+#define BCM43xx_TXHDRFLAG_EXPECTACK		0x0001
+#define BCM43xx_TXHDRFLAG_RTSCTS		0x0002
+#define BCM43xx_TXHDRFLAG_RTS			0x0004
+#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT		0x0008
+#define BCM43xx_TXHDRFLAG_DESTPSMODE		0x0020
+#define BCM43xx_TXHDRFLAG_RTSCTS_OFDM		0x0080
+#define BCM43xx_TXHDRFLAG_FALLBACKOFDM		0x0100
+#define BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM	0x0200
+#define BCM43xx_TXHDRFLAG_CTS			0x0400
+#define BCM43xx_TXHDRFLAG_FRAMEBURST		0x0800
+
+#define BCM43xx_TXHDRCTL_OFDM			0x0001
+#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE		0x0010
+#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK	0x0030
+#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT	8
+
+#define BCM43xx_TXHDR_RATE_MASK			0x0F00
+#define BCM43xx_TXHDR_RATE_SHIFT		8
+#define BCM43xx_TXHDR_RTSRATE_MASK		0xF000
+#define BCM43xx_TXHDR_RTSRATE_SHIFT		12
+#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK	0x00F0
+#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT	4
+#define BCM43xx_TXHDR_WSEC_ALGO_MASK		0x0003
+#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT		0
+
+void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
+			    struct bcm43xx_txhdr *txhdr,
+			    const unsigned char *fragment_data,
+			    const unsigned int fragment_len,
+			    const int is_first_fragment,
+			    const u16 cookie);
+
+/* RX header as received from the hardware. */
+struct bcm43xx_rxhdr {
+	/* Frame Length. Must be generated explicitely in PIO mode. */
+	__le16 frame_length;
+	PAD_BYTES(2);
+	/* Flags field 1 */
+	__le16 flags1;
+	u8 rssi;
+	u8 signal_quality;
+	PAD_BYTES(2);
+	/* Flags field 3 */
+	__le16 flags3;
+	/* Flags field 2 */
+	__le16 flags2;
+	/* Lower 16bits of the TSF at the time the frame started. */
+	__le16 mactime;
+	PAD_BYTES(14);
+} __attribute__((__packed__));
+
+#define BCM43xx_RXHDR_FLAGS1_OFDM		(1 << 0)
+/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL???	(1 << 3) FIXME */
+#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE	(1 << 7)
+#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ	(1 << 14)
+
+#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME	(1 << 0)
+#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME		(1 << 2)
+/*FIXME: WEP related flags */
+
+#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ	(1 << 10)
+
+/* Transmit Status as received from the hardware. */
+struct bcm43xx_hwxmitstatus {
+	PAD_BYTES(4);
+	__le16 cookie;
+	u8 flags;
+	u8 cnt1:4,
+	   cnt2:4;
+	PAD_BYTES(2);
+	__le16 seq;
+	__le16 unknown; //FIXME
+} __attribute__((__packed__));
+
+/* Transmit Status in CPU byteorder. */
+struct bcm43xx_xmitstatus {
+	u16 cookie;
+	u8 flags;
+	u8 cnt1:4,
+	   cnt2:4;
+	u16 seq;
+	u16 unknown; //FIXME
+};
+
+#define BCM43xx_TXSTAT_FLAG_ACK		0x01
+//TODO #define BCM43xx_TXSTAT_FLAG_???	0x02
+//TODO #define BCM43xx_TXSTAT_FLAG_???	0x04
+//TODO #define BCM43xx_TXSTAT_FLAG_???	0x08
+//TODO #define BCM43xx_TXSTAT_FLAG_???	0x10
+#define BCM43xx_TXSTAT_FLAG_IGNORE	0x20
+//TODO #define BCM43xx_TXSTAT_FLAG_???	0x40
+//TODO #define BCM43xx_TXSTAT_FLAG_???	0x80
+
+u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate);
+u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate);
+
+int bcm43xx_rx(struct bcm43xx_private *bcm,
+	       struct sk_buff *skb,
+	       struct bcm43xx_rxhdr *rxhdr);
+
+#endif /* BCM43xx_XMIT_H_ */
diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h
index 1fc72fe..cc1ee7f 100644
--- a/drivers/net/wireless/hostap/hostap_80211.h
+++ b/drivers/net/wireless/hostap/hostap_80211.h
@@ -92,8 +92,6 @@
 void hostap_dump_tx_80211(const char *name, struct sk_buff *skb);
 int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev);
 int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev);
-struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
-				   struct ieee80211_crypt_data *crypt);
 int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev);
 
 #endif /* HOSTAP_80211_H */
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 4a85e63..06a5214 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -299,8 +299,8 @@
 
 
 /* Called only from software IRQ */
-struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
-				   struct ieee80211_crypt_data *crypt)
+static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
+					  struct ieee80211_crypt_data *crypt)
 {
 	struct hostap_interface *iface;
 	local_info_t *local;
@@ -317,7 +317,7 @@
 	}
 
 	if (local->tkip_countermeasures &&
-	    crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
+	    strcmp(crypt->ops->name, "TKIP") == 0) {
 		hdr = (struct ieee80211_hdr_4addr *) skb->data;
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
@@ -469,7 +469,7 @@
 	}
 
 	if (local->ieee_802_1x && meta->ethertype == ETH_P_PAE && tx.crypt &&
-	    !(fc & IEEE80211_FCTL_VERS)) {
+	    !(fc & IEEE80211_FCTL_PROTECTED)) {
 		no_encrypt = 1;
 		PDEBUG(DEBUG_EXTRA2, "%s: TX: IEEE 802.1X - passing "
 		       "unencrypted EAPOL frame\n", dev->name);
@@ -535,5 +535,4 @@
 
 
 EXPORT_SYMBOL(hostap_dump_tx_80211);
-EXPORT_SYMBOL(hostap_tx_encrypt);
 EXPORT_SYMBOL(hostap_master_start_xmit);
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c
index 95d81d8..835dff0 100644
--- a/drivers/scsi/libata-bmdma.c
+++ b/drivers/scsi/libata-bmdma.c
@@ -703,6 +703,7 @@
 	struct ata_probe_ent *probe_ent =
 		ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
 	int p = 0;
+	unsigned long bmdma;
 
 	if (!probe_ent)
 		return NULL;
@@ -716,7 +717,12 @@
 		probe_ent->port[p].altstatus_addr =
 		probe_ent->port[p].ctl_addr =
 			pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-		probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4);
+		bmdma = pci_resource_start(pdev, 4);
+		if (bmdma) {
+			if (inb(bmdma + 2) & 0x80)
+				probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+			probe_ent->port[p].bmdma_addr = bmdma;
+		}
 		ata_std_ports(&probe_ent->port[p]);
 		p++;
 	}
@@ -726,7 +732,13 @@
 		probe_ent->port[p].altstatus_addr =
 		probe_ent->port[p].ctl_addr =
 			pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-		probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+		bmdma = pci_resource_start(pdev, 4);
+		if (bmdma) {
+			bmdma += 8;
+			if(inb(bmdma + 2) & 0x80)
+			probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+			probe_ent->port[p].bmdma_addr = bmdma;
+		}
 		ata_std_ports(&probe_ent->port[p]);
 		p++;
 	}
@@ -740,6 +752,7 @@
 				struct ata_port_info *port, int port_num)
 {
 	struct ata_probe_ent *probe_ent;
+	unsigned long bmdma;
 
 	probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port);
 	if (!probe_ent)
@@ -766,8 +779,13 @@
 			break;
 	}
 
-	probe_ent->port[0].bmdma_addr =
-		pci_resource_start(pdev, 4) + 8 * port_num;
+	bmdma = pci_resource_start(pdev, 4);
+	if (bmdma != 0) {
+		bmdma += 8 * port_num;
+		probe_ent->port[0].bmdma_addr = bmdma;
+		if (inb(bmdma + 2) & 0x80)
+			probe_ent->host_set_flags |= ATA_HOST_SIMPLEX;
+	}
 	ata_std_ports(&probe_ent->port[0]);
 
 	return probe_ent;
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index d279666..21b0ed5 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -62,7 +62,9 @@
 #include "libata.h"
 
 static unsigned int ata_dev_init_params(struct ata_port *ap,
-					struct ata_device *dev);
+					struct ata_device *dev,
+					u16 heads,
+					u16 sectors);
 static void ata_set_mode(struct ata_port *ap);
 static unsigned int ata_dev_set_xfermode(struct ata_port *ap,
 					 struct ata_device *dev);
@@ -1081,9 +1083,8 @@
  *
  *	Read ID data from the specified device.  ATA_CMD_ID_ATA is
  *	performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI
- *	devices.  This function also takes care of EDD signature
- *	misreporting (to be removed once EDD support is gone) and
- *	issues ATA_CMD_INIT_DEV_PARAMS for pre-ATA4 drives.
+ *	devices.  This function also issues ATA_CMD_INIT_DEV_PARAMS
+ *	for pre-ATA4 drives.
  *
  *	LOCKING:
  *	Kernel thread context (may sleep)
@@ -1095,7 +1096,6 @@
 			   unsigned int *p_class, int post_reset, u16 **p_id)
 {
 	unsigned int class = *p_class;
-	unsigned int using_edd;
 	struct ata_taskfile tf;
 	unsigned int err_mask = 0;
 	u16 *id;
@@ -1104,12 +1104,6 @@
 
 	DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno);
 
-	if (ap->ops->probe_reset ||
-	    ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET))
-		using_edd = 0;
-	else
-		using_edd = 1;
-
 	ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
 
 	id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL);
@@ -1139,39 +1133,16 @@
 
 	err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
 				     id, sizeof(id[0]) * ATA_ID_WORDS);
-
 	if (err_mask) {
 		rc = -EIO;
 		reason = "I/O error";
-
-		if (err_mask & ~AC_ERR_DEV)
-			goto err_out;
-
-		/*
-		 * arg!  EDD works for all test cases, but seems to return
-		 * the ATA signature for some ATAPI devices.  Until the
-		 * reason for this is found and fixed, we fix up the mess
-		 * here.  If IDENTIFY DEVICE returns command aborted
-		 * (as ATAPI devices do), then we issue an
-		 * IDENTIFY PACKET DEVICE.
-		 *
-		 * ATA software reset (SRST, the default) does not appear
-		 * to have this problem.
-		 */
-		if ((using_edd) && (class == ATA_DEV_ATA)) {
-			u8 err = tf.feature;
-			if (err & ATA_ABORTED) {
-				class = ATA_DEV_ATAPI;
-				goto retry;
-			}
-		}
 		goto err_out;
 	}
 
 	swap_buf_le16(id, ATA_ID_WORDS);
 
 	/* sanity check */
-	if ((class == ATA_DEV_ATA) != ata_id_is_ata(id)) {
+	if ((class == ATA_DEV_ATA) != (ata_id_is_ata(id) | ata_id_is_cfa(id))) {
 		rc = -EINVAL;
 		reason = "device reports illegal type";
 		goto err_out;
@@ -1187,7 +1158,7 @@
 		 * Some drives were very specific about that exact sequence.
 		 */
 		if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
-			err_mask = ata_dev_init_params(ap, dev);
+			err_mask = ata_dev_init_params(ap, dev, id[3], id[6]);
 			if (err_mask) {
 				rc = -EIO;
 				reason = "INIT_DEV_PARAMS failed";
@@ -1440,7 +1411,11 @@
 	if (!found)
 		goto err_out_disable;
 
-	ata_set_mode(ap);
+	if (ap->ops->set_mode)
+		ap->ops->set_mode(ap);
+	else
+		ata_set_mode(ap);
+
 	if (ap->flags & ATA_FLAG_PORT_DISABLED)
 		goto err_out_disable;
 
@@ -1845,7 +1820,7 @@
  */
 static void ata_set_mode(struct ata_port *ap)
 {
-	int i, rc;
+	int i, rc, used_dma = 0;
 
 	/* step 1: calculate xfer_mask */
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
@@ -1863,6 +1838,9 @@
 		dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask);
 		dev->pio_mode = ata_xfer_mask2mode(pio_mask);
 		dev->dma_mode = ata_xfer_mask2mode(dma_mask);
+
+		if (dev->dma_mode)
+			used_dma = 1;
 	}
 
 	/* step 2: always set host PIO timings */
@@ -1884,6 +1862,17 @@
 			goto err_out;
 	}
 
+	/*
+	 *	Record simplex status. If we selected DMA then the other
+	 *	host channels are not permitted to do so.
+	 */
+
+	if (used_dma && (ap->host_set->flags & ATA_HOST_SIMPLEX))
+		ap->host_set->simplex_claimed = 1;
+
+	/*
+	 *	Chip specific finalisation
+	 */
 	if (ap->ops->post_set_mode)
 		ap->ops->post_set_mode(ap);
 
@@ -2005,45 +1994,6 @@
 		ap->ops->dev_select(ap, 0);
 }
 
-/**
- *	ata_bus_edd - Issue EXECUTE DEVICE DIAGNOSTIC command.
- *	@ap: Port to reset and probe
- *
- *	Use the EXECUTE DEVICE DIAGNOSTIC command to reset and
- *	probe the bus.  Not often used these days.
- *
- *	LOCKING:
- *	PCI/etc. bus probe sem.
- *	Obtains host_set lock.
- *
- */
-
-static unsigned int ata_bus_edd(struct ata_port *ap)
-{
-	struct ata_taskfile tf;
-	unsigned long flags;
-
-	/* set up execute-device-diag (bus reset) taskfile */
-	/* also, take interrupts to a known state (disabled) */
-	DPRINTK("execute-device-diag\n");
-	ata_tf_init(ap, &tf, 0);
-	tf.ctl |= ATA_NIEN;
-	tf.command = ATA_CMD_EDD;
-	tf.protocol = ATA_PROT_NODATA;
-
-	/* do bus reset */
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	ata_tf_to_host(ap, &tf);
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
-	/* spec says at least 2ms.  but who knows with those
-	 * crazy ATAPI devices...
-	 */
-	msleep(150);
-
-	return ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
-}
-
 static unsigned int ata_bus_softreset(struct ata_port *ap,
 				      unsigned int devmask)
 {
@@ -2078,13 +2028,12 @@
 	 */
 	msleep(150);
 
-
 	/* Before we perform post reset processing we want to see if
-	   the bus shows 0xFF because the odd clown forgets the D7 pulldown
-	   resistor */
-
+	 * the bus shows 0xFF because the odd clown forgets the D7
+	 * pulldown resistor.
+	 */
 	if (ata_check_status(ap) == 0xFF)
-		return 1;	/* Positive is failure for some reason */
+		return AC_ERR_OTHER;
 
 	ata_bus_post_reset(ap, devmask);
 
@@ -2116,7 +2065,7 @@
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
 	u8 err;
-	unsigned int dev0, dev1 = 0, rc = 0, devmask = 0;
+	unsigned int dev0, dev1 = 0, devmask = 0;
 
 	DPRINTK("ENTER, host %u, port %u\n", ap->id, ap->port_no);
 
@@ -2139,18 +2088,8 @@
 
 	/* issue bus reset */
 	if (ap->flags & ATA_FLAG_SRST)
-		rc = ata_bus_softreset(ap, devmask);
-	else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) {
-		/* set up device control */
-		if (ap->flags & ATA_FLAG_MMIO)
-			writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
-		else
-			outb(ap->ctl, ioaddr->ctl_addr);
-		rc = ata_bus_edd(ap);
-	}
-
-	if (rc)
-		goto err_out;
+		if (ata_bus_softreset(ap, devmask))
+			goto err_out;
 
 	/*
 	 * determine by signature whether we have ATA or ATAPI devices
@@ -2223,9 +2162,9 @@
  *	so makes reset sequence different from the original
  *	->phy_reset implementation and Jeff nervous.  :-P
  */
-extern void ata_std_probeinit(struct ata_port *ap)
+void ata_std_probeinit(struct ata_port *ap)
 {
-	if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) {
+	if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) {
 		sata_phy_resume(ap);
 		if (sata_dev_present(ap))
 			ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
@@ -2714,18 +2653,23 @@
  *	known limits including host controller limits, device
  *	blacklist, etc...
  *
+ *	FIXME: The current implementation limits all transfer modes to
+ *	the fastest of the lowested device on the port.  This is not
+ *	required on most controllers.
+ *
  *	LOCKING:
  *	None.
  */
 static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev)
 {
+	struct ata_host_set *hs = ap->host_set;
 	unsigned long xfer_mask;
 	int i;
 
 	xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask,
 				      ap->udma_mask);
 
-	/* use port-wide xfermask for now */
+	/* FIXME: Use port-wide xfermask for now */
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
 		struct ata_device *d = &ap->device[i];
 		if (!ata_dev_present(d))
@@ -2735,12 +2679,23 @@
 		xfer_mask &= ata_id_xfermask(d->id);
 		if (ata_dma_blacklisted(d))
 			xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+		/* Apply cable rule here. Don't apply it early because when
+		   we handle hot plug the cable type can itself change */
+		if (ap->cbl == ATA_CBL_PATA40)
+			xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
 	}
 
 	if (ata_dma_blacklisted(dev))
 		printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, "
 		       "disabling DMA\n", ap->id, dev->devno);
 
+	if (hs->flags & ATA_HOST_SIMPLEX) {
+		if (hs->simplex_claimed)
+			xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+	}
+	if (ap->ops->mode_filter)
+		xfer_mask = ap->ops->mode_filter(ap, dev, xfer_mask);
+
 	ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask,
 			    &dev->udma_mask);
 }
@@ -2795,16 +2750,16 @@
  */
 
 static unsigned int ata_dev_init_params(struct ata_port *ap,
-					struct ata_device *dev)
+					struct ata_device *dev,
+					u16 heads,
+					u16 sectors)
 {
 	struct ata_taskfile tf;
 	unsigned int err_mask;
-	u16 sectors = dev->id[6];
-	u16 heads   = dev->id[3];
 
 	/* Number of sectors per track 1-255. Number of heads 1-16 */
 	if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
-		return 0;
+		return AC_ERR_INVALID;
 
 	/* set up init dev params taskfile */
 	DPRINTK("init dev params \n");
@@ -4536,6 +4491,14 @@
 	int rc;
 
 	DPRINTK("ENTER\n");
+
+	if (!ent->port_ops->probe_reset &&
+	    !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) {
+		printk(KERN_ERR "ata%u: no reset mechanism available\n",
+		       port_no);
+		return NULL;
+	}
+
 	host = scsi_host_alloc(ent->sht, sizeof(struct ata_port));
 	if (!host)
 		return NULL;
@@ -4596,6 +4559,7 @@
 	host_set->mmio_base = ent->mmio_base;
 	host_set->private_data = ent->private_data;
 	host_set->ops = ent->port_ops;
+	host_set->flags = ent->host_set_flags;
 
 	/* register each port bound to this device */
 	for (i = 0; i < ent->n_ports; i++) {
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index d6d2125..f852421 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1748,7 +1748,7 @@
 
 static void set_mesh_power(struct mesh_state *ms, int state)
 {
-	if (_machine != _MACH_Pmac)
+	if (!machine_is(powermac))
 		return;
 	if (state) {
 		pmac_call_feature(PMAC_FTR_MESH_ENABLE, macio_get_of_node(ms->mdev), 0, 1);
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index 275ed9b..fa901fd 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -1010,7 +1010,7 @@
 
 			pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff);
 			pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16);
-			pp->sg_tbl[i].flags_size = cpu_to_le32(len);
+			pp->sg_tbl[i].flags_size = cpu_to_le32(len & 0xffff);
 
 			sg_len -= len;
 			addr += len;
@@ -1350,7 +1350,6 @@
 {
 	void __iomem *mmio = host_set->mmio_base;
 	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
-	struct ata_port *ap;
 	struct ata_queued_cmd *qc;
 	u32 hc_irq_cause;
 	int shift, port, port0, hard_port, handled;
@@ -1373,25 +1372,32 @@
 
 	for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
 		u8 ata_status = 0;
-		ap = host_set->ports[port];
+		struct ata_port *ap = host_set->ports[port];
+		struct mv_port_priv *pp = ap->private_data;
+
 		hard_port = port & MV_PORT_MASK;	/* range 0-3 */
 		handled = 0;	/* ensure ata_status is set if handled++ */
 
-		if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
-			/* new CRPB on the queue; just one at a time until NCQ
-			 */
-			ata_status = mv_get_crpb_status(ap);
-			handled++;
-		} else if ((DEV_IRQ << hard_port) & hc_irq_cause) {
-			/* received ATA IRQ; read the status reg to clear INTRQ
-			 */
-			ata_status = readb((void __iomem *)
+		/* Note that DEV_IRQ might happen spuriously during EDMA,
+		 * and should be ignored in such cases.  We could mask it,
+		 * but it's pretty rare and may not be worth the overhead.
+		 */ 
+		if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
+			/* EDMA: check for response queue interrupt */
+			if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
+				ata_status = mv_get_crpb_status(ap);
+				handled = 1;
+			}
+		} else {
+			/* PIO: check for device (drive) interrupt */
+			if ((DEV_IRQ << hard_port) & hc_irq_cause) {
+				ata_status = readb((void __iomem *)
 					   ap->ioaddr.status_addr);
-			handled++;
+				handled = 1;
+			}
 		}
 
-		if (ap &&
-		    (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))
+		if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))
 			continue;
 
 		err_mask = ac_err_mask(ata_status);
@@ -1403,12 +1409,12 @@
 		if ((PORT0_ERR << shift) & relevant) {
 			mv_err_intr(ap);
 			err_mask |= AC_ERR_OTHER;
-			handled++;
+			handled = 1;
 		}
 
-		if (handled && ap) {
+		if (handled) {
 			qc = ata_qc_from_tag(ap, ap->active_tag);
-			if (NULL != qc) {
+			if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) {
 				VPRINTK("port %u IRQ found for qc, "
 					"ata_status 0x%x\n", port,ata_status);
 				/* mark qc status appropriately */
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index e0afb5a..0d2193b 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -296,7 +296,7 @@
 
 #ifdef CONFIG_PPC_PMAC
 		/* Disable ASIC clocks for USB */
-		if (_machine == _MACH_Pmac) {
+		if (machine_is(powermac)) {
 			struct device_node	*of_node;
 
 			of_node = pci_device_to_OF_node (dev);
@@ -331,7 +331,7 @@
 
 #ifdef CONFIG_PPC_PMAC
 	/* Reenable ASIC clocks for USB */
-	if (_machine == _MACH_Pmac) {
+	if (machine_is(powermac)) {
 		struct device_node *of_node;
 
 		of_node = pci_device_to_OF_node (dev);
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
index fe9b60c..9b1e4ed 100644
--- a/drivers/usb/net/zd1201.c
+++ b/drivers/usb/net/zd1201.c
@@ -1736,6 +1736,7 @@
 	.standard 		= (iw_handler *)zd1201_iw_handler,
 	.private 		= (iw_handler *)zd1201_private_handler,
 	.private_args 		= (struct iw_priv_args *) zd1201_private_args,
+	.get_wireless_stats	= zd1201_get_wireless_stats,
 };
 
 static int zd1201_probe(struct usb_interface *interface,
@@ -1796,7 +1797,6 @@
 	zd->dev->open = zd1201_net_open;
 	zd->dev->stop = zd1201_net_stop;
 	zd->dev->get_stats = zd1201_get_stats;
-	zd->dev->get_wireless_stats = zd1201_get_wireless_stats;
 	zd->dev->wireless_handlers =
 	    (struct iw_handler_def *)&zd1201_iw_handlers;
 	zd->dev->hard_start_xmit = zd1201_hard_start_xmit;
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 821c6da..f7bbff4 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -67,6 +67,7 @@
 #include <asm/io.h>
 
 #ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
@@ -1748,7 +1749,7 @@
 
 	var = default_var;
 #ifdef CONFIG_PPC_PMAC
-	if (_machine == _MACH_Pmac) {
+	if (machine_is(powermac)) {
 		/* Indicate sleep capability */
 		if (par->chip_gen == rage_M3) {
 			pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1);
@@ -2011,7 +2012,7 @@
 		return 0;
 
 #ifdef CONFIG_PMAC_BACKLIGHT
-	if ((_machine == _MACH_Pmac) && blank)
+	if (machine_is(powermac) && blank)
 		set_backlight_enable(0);
 #endif /* CONFIG_PMAC_BACKLIGHT */
 
@@ -2029,7 +2030,7 @@
 		aty128_set_lcd_enable(par, par->lcd_on && !blank);
 	}
 #ifdef CONFIG_PMAC_BACKLIGHT
-	if ((_machine == _MACH_Pmac) && !blank)
+	if (machine_is(powermac) && !blank)
 		set_backlight_enable(1);
 #endif /* CONFIG_PMAC_BACKLIGHT */
 	return 0;
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index e799fcc..b39e72d 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -75,6 +75,7 @@
 #include "ati_ids.h"
 
 #ifdef __powerpc__
+#include <asm/machdep.h>
 #include <asm/prom.h>
 #include "../macmodes.h"
 #endif
@@ -2518,7 +2519,7 @@
 
 	memset(&var, 0, sizeof(var));
 #ifdef CONFIG_PPC
-	if (_machine == _MACH_Pmac) {
+	if (machine_is(powermac)) {
 		/*
 		 *  FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
 		 *         applies to all Mac video cards
@@ -2673,7 +2674,7 @@
 		return 0;
 
 #ifdef CONFIG_PMAC_BACKLIGHT
-	if ((_machine == _MACH_Pmac) && blank > FB_BLANK_NORMAL)
+	if (machine_is(powermac) && blank > FB_BLANK_NORMAL)
 		set_backlight_enable(0);
 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
 	if (par->lcd_table && blank > FB_BLANK_NORMAL &&
@@ -2705,7 +2706,7 @@
 	aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
 
 #ifdef CONFIG_PMAC_BACKLIGHT
-	if ((_machine == _MACH_Pmac) && blank <= FB_BLANK_NORMAL)
+	if (machine_is(powermac) && blank <= FB_BLANK_NORMAL)
 		set_backlight_enable(1);
 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
 	if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 5886a2f..c709176 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -20,7 +20,7 @@
 #include <linux/agp_backend.h>
 
 #ifdef CONFIG_PPC_PMAC
-#include <asm/processor.h>
+#include <asm/machdep.h>
 #include <asm/prom.h>
 #include <asm/pmac_feature.h>
 #endif
@@ -2745,7 +2745,7 @@
 		rinfo->pm_mode |= radeon_pm_off;
 	}
 #if defined(CONFIG_PPC_PMAC)
-	if (_machine == _MACH_Pmac && rinfo->of_node) {
+	if (machine_is(powermac) && rinfo->of_node) {
 		if (rinfo->is_mobility && rinfo->pm_reg &&
 		    rinfo->family <= CHIP_FAMILY_RV250)
 			rinfo->pm_mode |= radeon_pm_d2;
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 66d6f2f..1103010 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -60,8 +60,8 @@
 #include <asm/amigahw.h>
 #endif
 #ifdef CONFIG_PPC_PREP
-#include <asm/processor.h>
-#define isPReP (_machine == _MACH_prep)
+#include <asm/machdep.h>
+#define isPReP (machine_is(prep))
 #else
 #define isPReP 0
 #endif
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 951c997..23c1827 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -115,6 +115,7 @@
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
 unsigned char nvram_read_byte(int);
 static int default_vmode = VMODE_NVRAM;
 static int default_cmode = CMODE_NVRAM;
@@ -1833,7 +1834,7 @@
 	/* FIXME: Where to move this?! */
 #if defined(CONFIG_PPC_PMAC)
 #ifndef MODULE
-	if (_machine == _MACH_Pmac) {
+	if (machine_is(powermac)) {
 		struct fb_var_screeninfo var;
 		if (default_vmode <= 0 || default_vmode > VMODE_MAX)
 			default_vmode = VMODE_640_480_60;
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 6d3e489..093ab99 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -30,6 +30,7 @@
 #include <asm/pci-bridge.h>
 #endif
 #ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/machdep.h>
 #include <asm/backlight.h>
 #endif
 
@@ -1355,7 +1356,7 @@
 	NVWriteCrtc(par, 0x1a, vesa);
 
 #ifdef CONFIG_PMAC_BACKLIGHT
-	if (par->FlatPanel && _machine == _MACH_Pmac) {
+	if (par->FlatPanel && machine_is(powermac)) {
 		set_backlight_enable(!blank);
 	}
 #endif
@@ -1741,7 +1742,7 @@
 	       info->fix.id,
 	       par->FbMapSize / (1024 * 1024), info->fix.smem_start);
 #ifdef CONFIG_PMAC_BACKLIGHT
-	if (par->FlatPanel && _machine == _MACH_Pmac)
+	if (par->FlatPanel && machine_is(powermac))
 		register_backlight_controller(&nvidia_backlight_controller,
 					      par, "mnca");
 #endif
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index 24982ad..afb6c2e 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -1596,7 +1596,7 @@
 		return 0;
 		
 #ifdef CONFIG_PMAC_BACKLIGHT
-	if (rinfo->dviDisp_type == MT_LCD && _machine == _MACH_Pmac) {
+	if (rinfo->dviDisp_type == MT_LCD && machine_is(powermac)) {
 		set_backlight_enable(!blank);
 		return 0;
 	}
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index f841f01..3e9308f 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -49,6 +49,7 @@
 #include <asm/pci-bridge.h>
 #endif
 #ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/machdep.h>
 #include <asm/backlight.h>
 #endif
 
@@ -1247,7 +1248,7 @@
 	CRTCout(par, 0x1a, vesa);
 
 #ifdef CONFIG_PMAC_BACKLIGHT
-	if ( par->FlatPanel && _machine == _MACH_Pmac) {
+	if ( par->FlatPanel && machine_is(powermac)) {
 		set_backlight_enable(!blank);
 	}
 #endif
@@ -2037,9 +2038,9 @@
 		info->fix.smem_len / (1024 * 1024),
 		info->fix.smem_start);
 #ifdef CONFIG_PMAC_BACKLIGHT
-	if (default_par->FlatPanel && _machine == _MACH_Pmac)
-	register_backlight_controller(&riva_backlight_controller,
-						default_par, "mnca");
+	if (default_par->FlatPanel && machine_is(powermac))
+		register_backlight_controller(&riva_backlight_controller,
+					      default_par, "mnca");
 #endif
 	NVTRACE_LEAVE();
 	return 0;
diff --git a/fs/Makefile b/fs/Makefile
index 080b386..f3a4f70 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -10,7 +10,7 @@
 		ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \
 		attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
 		seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \
-		ioprio.o pnode.o drop_caches.o
+		ioprio.o pnode.o drop_caches.o splice.o
 
 obj-$(CONFIG_INOTIFY)		+= inotify.o
 obj-$(CONFIG_EPOLL)		+= eventpoll.o
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 509ccec..23e2c7c 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -53,6 +53,8 @@
 	.readv		= generic_file_readv,
 	.writev		= generic_file_writev,
 	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
+	.splice_write	= generic_file_splice_write,
 };
 
 #ifdef CONFIG_EXT2_FS_XIP
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 783a796..1efefb6 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -119,6 +119,8 @@
 	.release	= ext3_release_file,
 	.fsync		= ext3_sync_file,
 	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
+	.splice_write	= generic_file_splice_write,
 };
 
 struct inode_operations ext3_file_inode_operations = {
diff --git a/fs/partitions/mac.c b/fs/partitions/mac.c
index bb22cdd..813292f 100644
--- a/fs/partitions/mac.c
+++ b/fs/partitions/mac.c
@@ -12,6 +12,7 @@
 #include "mac.h"
 
 #ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
 extern void note_bootable_part(dev_t dev, int part, int goodness);
 #endif
 
@@ -79,7 +80,7 @@
 		 * If this is the first bootable partition, tell the
 		 * setup code, in case it wants to make this the root.
 		 */
-		if (_machine == _MACH_Pmac) {
+		if (machine_is(powermac)) {
 			int goodness = 0;
 
 			mac_fix_string(part->processor, 16);
diff --git a/fs/pipe.c b/fs/pipe.c
index e2f4f1d..109a102 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -15,6 +15,7 @@
 #include <linux/pipe_fs_i.h>
 #include <linux/uio.h>
 #include <linux/highmem.h>
+#include <linux/pagemap.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
@@ -94,11 +95,20 @@
 {
 	struct page *page = buf->page;
 
-	if (info->tmp_page) {
-		__free_page(page);
+	/*
+	 * If nobody else uses this page, and we don't already have a
+	 * temporary page, let's keep track of it as a one-deep
+	 * allocation cache
+	 */
+	if (page_count(page) == 1 && !info->tmp_page) {
+		info->tmp_page = page;
 		return;
 	}
-	info->tmp_page = page;
+
+	/*
+	 * Otherwise just release our reference to it
+	 */
+	page_cache_release(page);
 }
 
 static void *anon_pipe_buf_map(struct file *file, struct pipe_inode_info *info, struct pipe_buffer *buf)
@@ -111,11 +121,19 @@
 	kunmap(buf->page);
 }
 
+static int anon_pipe_buf_steal(struct pipe_inode_info *info,
+			       struct pipe_buffer *buf)
+{
+	buf->stolen = 1;
+	return 0;
+}
+
 static struct pipe_buf_operations anon_pipe_buf_ops = {
 	.can_merge = 1,
 	.map = anon_pipe_buf_map,
 	.unmap = anon_pipe_buf_unmap,
 	.release = anon_pipe_buf_release,
+	.steal = anon_pipe_buf_steal,
 };
 
 static ssize_t
@@ -152,6 +170,11 @@
 				chars = total_len;
 
 			addr = ops->map(filp, info, buf);
+			if (IS_ERR(addr)) {
+				if (!ret)
+					ret = PTR_ERR(addr);
+				break;
+			}
 			error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars);
 			ops->unmap(info, buf);
 			if (unlikely(error)) {
@@ -254,8 +277,16 @@
 		struct pipe_buf_operations *ops = buf->ops;
 		int offset = buf->offset + buf->len;
 		if (ops->can_merge && offset + chars <= PAGE_SIZE) {
-			void *addr = ops->map(filp, info, buf);
-			int error = pipe_iov_copy_from_user(offset + addr, iov, chars);
+			void *addr;
+			int error;
+
+			addr = ops->map(filp, info, buf);
+			if (IS_ERR(addr)) {
+				error = PTR_ERR(addr);
+				goto out;
+			}
+			error = pipe_iov_copy_from_user(offset + addr, iov,
+							chars);
 			ops->unmap(info, buf);
 			ret = error;
 			do_wakeup = 1;
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index 596b4b4..abdf068 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -52,7 +52,8 @@
  * Add a property to a node
  */
 static struct proc_dir_entry *
-__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp)
+__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp,
+		const char *name)
 {
 	struct proc_dir_entry *ent;
 
@@ -60,14 +61,14 @@
 	 * Unfortunately proc_register puts each new entry
 	 * at the beginning of the list.  So we rearrange them.
 	 */
-	ent = create_proc_read_entry(pp->name,
-				     strncmp(pp->name, "security-", 9)
+	ent = create_proc_read_entry(name,
+				     strncmp(name, "security-", 9)
 				     ? S_IRUGO : S_IRUSR, de,
 				     property_read_proc, pp);
 	if (ent == NULL)
 		return NULL;
 
-	if (!strncmp(pp->name, "security-", 9))
+	if (!strncmp(name, "security-", 9))
 		ent->size = 0; /* don't leak number of password chars */
 	else
 		ent->size = pp->length;
@@ -78,7 +79,7 @@
 
 void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop)
 {
-	__proc_device_tree_add_prop(pde, prop);
+	__proc_device_tree_add_prop(pde, prop, prop->name);
 }
 
 void proc_device_tree_remove_prop(struct proc_dir_entry *pde,
@@ -106,6 +107,69 @@
 }
 
 /*
+ * Various dodgy firmware might give us nodes and/or properties with
+ * conflicting names. That's generally ok, except for exporting via /proc,
+ * so munge names here to ensure they're unique.
+ */
+
+static int duplicate_name(struct proc_dir_entry *de, const char *name)
+{
+	struct proc_dir_entry *ent;
+	int found = 0;
+
+	spin_lock(&proc_subdir_lock);
+
+	for (ent = de->subdir; ent != NULL; ent = ent->next) {
+		if (strcmp(ent->name, name) == 0) {
+			found = 1;
+			break;
+		}
+	}
+
+	spin_unlock(&proc_subdir_lock);
+
+	return found;
+}
+
+static const char *fixup_name(struct device_node *np, struct proc_dir_entry *de,
+		const char *name)
+{
+	char *fixed_name;
+	int fixup_len = strlen(name) + 2 + 1; /* name + #x + \0 */
+	int i = 1, size;
+
+realloc:
+	fixed_name = kmalloc(fixup_len, GFP_KERNEL);
+	if (fixed_name == NULL) {
+		printk(KERN_ERR "device-tree: Out of memory trying to fixup "
+				"name \"%s\"\n", name);
+		return name;
+	}
+
+retry:
+	size = snprintf(fixed_name, fixup_len, "%s#%d", name, i);
+	size++; /* account for NULL */
+
+	if (size > fixup_len) {
+		/* We ran out of space, free and reallocate. */
+		kfree(fixed_name);
+		fixup_len = size;
+		goto realloc;
+	}
+
+	if (duplicate_name(de, fixed_name)) {
+		/* Multiple duplicates. Retry with a different offset. */
+		i++;
+		goto retry;
+	}
+
+	printk(KERN_WARNING "device-tree: Duplicate name in %s, "
+			"renamed to \"%s\"\n", np->full_name, fixed_name);
+
+	return fixed_name;
+}
+
+/*
  * Process a node, adding entries for its children and its properties.
  */
 void proc_device_tree_add_node(struct device_node *np,
@@ -118,37 +182,30 @@
 
 	set_node_proc_entry(np, de);
 	for (child = NULL; (child = of_get_next_child(np, child));) {
+		/* Use everything after the last slash, or the full name */
 		p = strrchr(child->full_name, '/');
 		if (!p)
 			p = child->full_name;
 		else
 			++p;
+
+		if (duplicate_name(de, p))
+			p = fixup_name(np, de, p);
+
 		ent = proc_mkdir(p, de);
 		if (ent == 0)
 			break;
 		proc_device_tree_add_node(child, ent);
 	}
 	of_node_put(child);
-	for (pp = np->properties; pp != 0; pp = pp->next) {
-		/*
-		 * Yet another Apple device-tree bogosity: on some machines,
-		 * they have properties & nodes with the same name. Those
-		 * properties are quite unimportant for us though, thus we
-		 * simply "skip" them here, but we do have to check.
-		 */
-		spin_lock(&proc_subdir_lock);
-		for (ent = de->subdir; ent != NULL; ent = ent->next)
-			if (!strcmp(ent->name, pp->name))
-				break;
-		spin_unlock(&proc_subdir_lock);
-		if (ent != NULL) {
-			printk(KERN_WARNING "device-tree: property \"%s\" name"
-			       " conflicts with node in %s\n", pp->name,
-			       np->full_name);
-			continue;
-		}
 
-		ent = __proc_device_tree_add_prop(de, pp);
+	for (pp = np->properties; pp != 0; pp = pp->next) {
+		p = pp->name;
+
+		if (duplicate_name(de, p))
+			p = fixup_name(np, de, p);
+
+		ent = __proc_device_tree_add_prop(de, pp, p);
 		if (ent == 0)
 			break;
 	}
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 010094d1..cf6e1cf 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1576,6 +1576,8 @@
 	.sendfile = generic_file_sendfile,
 	.aio_read = generic_file_aio_read,
 	.aio_write = reiserfs_aio_write,
+	.splice_read = generic_file_splice_read,
+	.splice_write = generic_file_splice_write,
 };
 
 struct inode_operations reiserfs_file_inode_operations = {
diff --git a/fs/splice.c b/fs/splice.c
new file mode 100644
index 0000000..4a026f9
--- /dev/null
+++ b/fs/splice.c
@@ -0,0 +1,659 @@
+/*
+ * "splice": joining two ropes together by interweaving their strands.
+ *
+ * This is the "extended pipe" functionality, where a pipe is used as
+ * an arbitrary in-memory buffer. Think of a pipe as a small kernel
+ * buffer that you can use to transfer data from one end to the other.
+ *
+ * The traditional unix read/write is extended with a "splice()" operation
+ * that transfers data buffers to or from a pipe buffer.
+ *
+ * Named by Larry McVoy, original implementation from Linus, extended by
+ * Jens to support splicing to files and fixing the initial implementation
+ * bugs.
+ *
+ * Copyright (C) 2005 Jens Axboe <axboe@suse.de>
+ * Copyright (C) 2005 Linus Torvalds <torvalds@osdl.org>
+ *
+ */
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/pagemap.h>
+#include <linux/pipe_fs_i.h>
+#include <linux/mm_inline.h>
+#include <linux/swap.h>
+
+/*
+ * Passed to the actors
+ */
+struct splice_desc {
+	unsigned int len, total_len;	/* current and remaining length */
+	unsigned int flags;		/* splice flags */
+	struct file *file;		/* file to read/write */
+	loff_t pos;			/* file position */
+};
+
+static int page_cache_pipe_buf_steal(struct pipe_inode_info *info,
+				     struct pipe_buffer *buf)
+{
+	struct page *page = buf->page;
+
+	WARN_ON(!PageLocked(page));
+	WARN_ON(!PageUptodate(page));
+
+	if (!remove_mapping(page_mapping(page), page))
+		return 1;
+
+	if (PageLRU(page)) {
+		struct zone *zone = page_zone(page);
+
+		spin_lock_irq(&zone->lru_lock);
+		BUG_ON(!PageLRU(page));
+		__ClearPageLRU(page);
+		del_page_from_lru(zone, page);
+		spin_unlock_irq(&zone->lru_lock);
+	}
+
+	buf->stolen = 1;
+	return 0;
+}
+
+static void page_cache_pipe_buf_release(struct pipe_inode_info *info,
+					struct pipe_buffer *buf)
+{
+	page_cache_release(buf->page);
+	buf->page = NULL;
+	buf->stolen = 0;
+}
+
+static void *page_cache_pipe_buf_map(struct file *file,
+				     struct pipe_inode_info *info,
+				     struct pipe_buffer *buf)
+{
+	struct page *page = buf->page;
+
+	lock_page(page);
+
+	if (!PageUptodate(page)) {
+		unlock_page(page);
+		return ERR_PTR(-EIO);
+	}
+
+	if (!page->mapping) {
+		unlock_page(page);
+		return ERR_PTR(-ENODATA);
+	}
+
+	return kmap(buf->page);
+}
+
+static void page_cache_pipe_buf_unmap(struct pipe_inode_info *info,
+				      struct pipe_buffer *buf)
+{
+	if (!buf->stolen)
+		unlock_page(buf->page);
+	kunmap(buf->page);
+}
+
+static struct pipe_buf_operations page_cache_pipe_buf_ops = {
+	.can_merge = 0,
+	.map = page_cache_pipe_buf_map,
+	.unmap = page_cache_pipe_buf_unmap,
+	.release = page_cache_pipe_buf_release,
+	.steal = page_cache_pipe_buf_steal,
+};
+
+static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
+			    int nr_pages, unsigned long offset,
+			    unsigned long len)
+{
+	struct pipe_inode_info *info;
+	int ret, do_wakeup, i;
+
+	ret = 0;
+	do_wakeup = 0;
+	i = 0;
+
+	mutex_lock(PIPE_MUTEX(*inode));
+
+	info = inode->i_pipe;
+	for (;;) {
+		int bufs;
+
+		if (!PIPE_READERS(*inode)) {
+			send_sig(SIGPIPE, current, 0);
+			if (!ret)
+				ret = -EPIPE;
+			break;
+		}
+
+		bufs = info->nrbufs;
+		if (bufs < PIPE_BUFFERS) {
+			int newbuf = (info->curbuf + bufs) & (PIPE_BUFFERS - 1);
+			struct pipe_buffer *buf = info->bufs + newbuf;
+			struct page *page = pages[i++];
+			unsigned long this_len;
+
+			this_len = PAGE_CACHE_SIZE - offset;
+			if (this_len > len)
+				this_len = len;
+
+			buf->page = page;
+			buf->offset = offset;
+			buf->len = this_len;
+			buf->ops = &page_cache_pipe_buf_ops;
+			info->nrbufs = ++bufs;
+			do_wakeup = 1;
+
+			ret += this_len;
+			len -= this_len;
+			offset = 0;
+			if (!--nr_pages)
+				break;
+			if (!len)
+				break;
+			if (bufs < PIPE_BUFFERS)
+				continue;
+
+			break;
+		}
+
+		if (signal_pending(current)) {
+			if (!ret)
+				ret = -ERESTARTSYS;
+			break;
+		}
+
+		if (do_wakeup) {
+			wake_up_interruptible_sync(PIPE_WAIT(*inode));
+			kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO,
+				    POLL_IN);
+			do_wakeup = 0;
+		}
+
+		PIPE_WAITING_WRITERS(*inode)++;
+		pipe_wait(inode);
+		PIPE_WAITING_WRITERS(*inode)--;
+	}
+
+	mutex_unlock(PIPE_MUTEX(*inode));
+
+	if (do_wakeup) {
+		wake_up_interruptible(PIPE_WAIT(*inode));
+		kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
+	}
+
+	while (i < nr_pages)
+		page_cache_release(pages[i++]);
+
+	return ret;
+}
+
+static int __generic_file_splice_read(struct file *in, struct inode *pipe,
+				      size_t len)
+{
+	struct address_space *mapping = in->f_mapping;
+	unsigned int offset, nr_pages;
+	struct page *pages[PIPE_BUFFERS], *shadow[PIPE_BUFFERS];
+	struct page *page;
+	pgoff_t index, pidx;
+	int i, j;
+
+	index = in->f_pos >> PAGE_CACHE_SHIFT;
+	offset = in->f_pos & ~PAGE_CACHE_MASK;
+	nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+
+	if (nr_pages > PIPE_BUFFERS)
+		nr_pages = PIPE_BUFFERS;
+
+	/*
+	 * initiate read-ahead on this page range
+	 */
+	do_page_cache_readahead(mapping, in, index, nr_pages);
+
+	/*
+	 * Get as many pages from the page cache as possible..
+	 * Start IO on the page cache entries we create (we
+	 * can assume that any pre-existing ones we find have
+	 * already had IO started on them).
+	 */
+	i = find_get_pages(mapping, index, nr_pages, pages);
+
+	/*
+	 * common case - we found all pages and they are contiguous,
+	 * kick them off
+	 */
+	if (i && (pages[i - 1]->index == index + i - 1))
+		goto splice_them;
+
+	/*
+	 * fill shadow[] with pages at the right locations, so we only
+	 * have to fill holes
+	 */
+	memset(shadow, 0, i * sizeof(struct page *));
+	for (j = 0, pidx = index; j < i; pidx++, j++)
+		shadow[pages[j]->index - pidx] = pages[j];
+
+	/*
+	 * now fill in the holes
+	 */
+	for (i = 0, pidx = index; i < nr_pages; pidx++, i++) {
+		int error;
+
+		if (shadow[i])
+			continue;
+
+		/*
+		 * no page there, look one up / create it
+		 */
+		page = find_or_create_page(mapping, pidx,
+						   mapping_gfp_mask(mapping));
+		if (!page)
+			break;
+
+		if (PageUptodate(page))
+			unlock_page(page);
+		else {
+			error = mapping->a_ops->readpage(in, page);
+
+			if (unlikely(error)) {
+				page_cache_release(page);
+				break;
+			}
+		}
+		shadow[i] = page;
+	}
+
+	if (!i) {
+		for (i = 0; i < nr_pages; i++) {
+			 if (shadow[i])
+				page_cache_release(shadow[i]);
+		}
+		return 0;
+	}
+
+	memcpy(pages, shadow, i * sizeof(struct page *));
+
+	/*
+	 * Now we splice them into the pipe..
+	 */
+splice_them:
+	return move_to_pipe(pipe, pages, i, offset, len);
+}
+
+ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
+				 size_t len, unsigned int flags)
+{
+	ssize_t spliced;
+	int ret;
+
+	ret = 0;
+	spliced = 0;
+	while (len) {
+		ret = __generic_file_splice_read(in, pipe, len);
+
+		if (ret <= 0)
+			break;
+
+		in->f_pos += ret;
+		len -= ret;
+		spliced += ret;
+	}
+
+	if (spliced)
+		return spliced;
+
+	return ret;
+}
+
+/*
+ * Send 'len' bytes to socket from 'file' at position 'pos' using sendpage().
+ */
+static int pipe_to_sendpage(struct pipe_inode_info *info,
+			    struct pipe_buffer *buf, struct splice_desc *sd)
+{
+	struct file *file = sd->file;
+	loff_t pos = sd->pos;
+	unsigned int offset;
+	ssize_t ret;
+	void *ptr;
+
+	/*
+	 * sub-optimal, but we are limited by the pipe ->map. we don't
+	 * need a kmap'ed buffer here, we just want to make sure we
+	 * have the page pinned if the pipe page originates from the
+	 * page cache
+	 */
+	ptr = buf->ops->map(file, info, buf);
+	if (IS_ERR(ptr))
+		return PTR_ERR(ptr);
+
+	offset = pos & ~PAGE_CACHE_MASK;
+
+	ret = file->f_op->sendpage(file, buf->page, offset, sd->len, &pos,
+					sd->len < sd->total_len);
+
+	buf->ops->unmap(info, buf);
+	if (ret == sd->len)
+		return 0;
+
+	return -EIO;
+}
+
+/*
+ * This is a little more tricky than the file -> pipe splicing. There are
+ * basically three cases:
+ *
+ *	- Destination page already exists in the address space and there
+ *	  are users of it. For that case we have no other option that
+ *	  copying the data. Tough luck.
+ *	- Destination page already exists in the address space, but there
+ *	  are no users of it. Make sure it's uptodate, then drop it. Fall
+ *	  through to last case.
+ *	- Destination page does not exist, we can add the pipe page to
+ *	  the page cache and avoid the copy.
+ *
+ * For now we just do the slower thing and always copy pages over, it's
+ * easier than migrating pages from the pipe to the target file. For the
+ * case of doing file | file splicing, the migrate approach had some LRU
+ * nastiness...
+ */
+static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
+			struct splice_desc *sd)
+{
+	struct file *file = sd->file;
+	struct address_space *mapping = file->f_mapping;
+	unsigned int offset;
+	struct page *page;
+	pgoff_t index;
+	char *src;
+	int ret;
+
+	/*
+	 * after this, page will be locked and unmapped
+	 */
+	src = buf->ops->map(file, info, buf);
+	if (IS_ERR(src))
+		return PTR_ERR(src);
+
+	index = sd->pos >> PAGE_CACHE_SHIFT;
+	offset = sd->pos & ~PAGE_CACHE_MASK;
+
+	/*
+	 * reuse buf page, if SPLICE_F_MOVE is set
+	 */
+	if (sd->flags & SPLICE_F_MOVE) {
+		if (buf->ops->steal(info, buf))
+			goto find_page;
+
+		page = buf->page;
+		if (add_to_page_cache_lru(page, mapping, index,
+						mapping_gfp_mask(mapping)))
+			goto find_page;
+	} else {
+find_page:
+		ret = -ENOMEM;
+		page = find_or_create_page(mapping, index,
+						mapping_gfp_mask(mapping));
+		if (!page)
+			goto out;
+
+		/*
+		 * If the page is uptodate, it is also locked. If it isn't
+		 * uptodate, we can mark it uptodate if we are filling the
+		 * full page. Otherwise we need to read it in first...
+		 */
+		if (!PageUptodate(page)) {
+			if (sd->len < PAGE_CACHE_SIZE) {
+				ret = mapping->a_ops->readpage(file, page);
+				if (unlikely(ret))
+					goto out;
+
+				lock_page(page);
+
+				if (!PageUptodate(page)) {
+					/*
+					 * page got invalidated, repeat
+					 */
+					if (!page->mapping) {
+						unlock_page(page);
+						page_cache_release(page);
+						goto find_page;
+					}
+					ret = -EIO;
+					goto out;
+				}
+			} else {
+				WARN_ON(!PageLocked(page));
+				SetPageUptodate(page);
+			}
+		}
+	}
+
+	ret = mapping->a_ops->prepare_write(file, page, 0, sd->len);
+	if (ret)
+		goto out;
+
+	if (!buf->stolen) {
+		char *dst = kmap_atomic(page, KM_USER0);
+
+		memcpy(dst + offset, src + buf->offset, sd->len);
+		flush_dcache_page(page);
+		kunmap_atomic(dst, KM_USER0);
+	}
+
+	ret = mapping->a_ops->commit_write(file, page, 0, sd->len);
+	if (ret < 0)
+		goto out;
+
+	set_page_dirty(page);
+	ret = write_one_page(page, 0);
+out:
+	if (ret < 0)
+		unlock_page(page);
+	if (!buf->stolen)
+		page_cache_release(page);
+	buf->ops->unmap(info, buf);
+	return ret;
+}
+
+typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
+			   struct splice_desc *);
+
+static ssize_t move_from_pipe(struct inode *inode, struct file *out,
+			      size_t len, unsigned int flags,
+			      splice_actor *actor)
+{
+	struct pipe_inode_info *info;
+	int ret, do_wakeup, err;
+	struct splice_desc sd;
+
+	ret = 0;
+	do_wakeup = 0;
+
+	sd.total_len = len;
+	sd.flags = flags;
+	sd.file = out;
+	sd.pos = out->f_pos;
+
+	mutex_lock(PIPE_MUTEX(*inode));
+
+	info = inode->i_pipe;
+	for (;;) {
+		int bufs = info->nrbufs;
+
+		if (bufs) {
+			int curbuf = info->curbuf;
+			struct pipe_buffer *buf = info->bufs + curbuf;
+			struct pipe_buf_operations *ops = buf->ops;
+
+			sd.len = buf->len;
+			if (sd.len > sd.total_len)
+				sd.len = sd.total_len;
+
+			err = actor(info, buf, &sd);
+			if (err) {
+				if (!ret && err != -ENODATA)
+					ret = err;
+
+				break;
+			}
+
+			ret += sd.len;
+			buf->offset += sd.len;
+			buf->len -= sd.len;
+			if (!buf->len) {
+				buf->ops = NULL;
+				ops->release(info, buf);
+				curbuf = (curbuf + 1) & (PIPE_BUFFERS - 1);
+				info->curbuf = curbuf;
+				info->nrbufs = --bufs;
+				do_wakeup = 1;
+			}
+
+			sd.pos += sd.len;
+			sd.total_len -= sd.len;
+			if (!sd.total_len)
+				break;
+		}
+
+		if (bufs)
+			continue;
+		if (!PIPE_WRITERS(*inode))
+			break;
+		if (!PIPE_WAITING_WRITERS(*inode)) {
+			if (ret)
+				break;
+		}
+
+		if (signal_pending(current)) {
+			if (!ret)
+				ret = -ERESTARTSYS;
+			break;
+		}
+
+		if (do_wakeup) {
+			wake_up_interruptible_sync(PIPE_WAIT(*inode));
+			kill_fasync(PIPE_FASYNC_WRITERS(*inode),SIGIO,POLL_OUT);
+			do_wakeup = 0;
+		}
+
+		pipe_wait(inode);
+	}
+
+	mutex_unlock(PIPE_MUTEX(*inode));
+
+	if (do_wakeup) {
+		wake_up_interruptible(PIPE_WAIT(*inode));
+		kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
+	}
+
+	mutex_lock(&out->f_mapping->host->i_mutex);
+	out->f_pos = sd.pos;
+	mutex_unlock(&out->f_mapping->host->i_mutex);
+	return ret;
+
+}
+
+ssize_t generic_file_splice_write(struct inode *inode, struct file *out,
+				  size_t len, unsigned int flags)
+{
+	return move_from_pipe(inode, out, len, flags, pipe_to_file);
+}
+
+ssize_t generic_splice_sendpage(struct inode *inode, struct file *out,
+				size_t len, unsigned int flags)
+{
+	return move_from_pipe(inode, out, len, flags, pipe_to_sendpage);
+}
+
+static long do_splice_from(struct inode *pipe, struct file *out, size_t len,
+			   unsigned int flags)
+{
+	loff_t pos;
+	int ret;
+
+	if (!out->f_op || !out->f_op->splice_write)
+		return -EINVAL;
+
+	if (!(out->f_mode & FMODE_WRITE))
+		return -EBADF;
+
+	pos = out->f_pos;
+	ret = rw_verify_area(WRITE, out, &pos, len);
+	if (unlikely(ret < 0))
+		return ret;
+
+	return out->f_op->splice_write(pipe, out, len, flags);
+}
+
+static long do_splice_to(struct file *in, struct inode *pipe, size_t len,
+			 unsigned int flags)
+{
+	loff_t pos, isize, left;
+	int ret;
+
+	if (!in->f_op || !in->f_op->splice_read)
+		return -EINVAL;
+
+	if (!(in->f_mode & FMODE_READ))
+		return -EBADF;
+
+	pos = in->f_pos;
+	ret = rw_verify_area(READ, in, &pos, len);
+	if (unlikely(ret < 0))
+		return ret;
+
+	isize = i_size_read(in->f_mapping->host);
+	if (unlikely(in->f_pos >= isize))
+		return 0;
+	
+	left = isize - in->f_pos;
+	if (left < len)
+		len = left;
+
+	return in->f_op->splice_read(in, pipe, len, flags);
+}
+
+static long do_splice(struct file *in, struct file *out, size_t len,
+		      unsigned int flags)
+{
+	struct inode *pipe;
+
+	pipe = in->f_dentry->d_inode;
+	if (pipe->i_pipe)
+		return do_splice_from(pipe, out, len, flags);
+
+	pipe = out->f_dentry->d_inode;
+	if (pipe->i_pipe)
+		return do_splice_to(in, pipe, len, flags);
+
+	return -EINVAL;
+}
+
+asmlinkage long sys_splice(int fdin, int fdout, size_t len, unsigned int flags)
+{
+	long error;
+	struct file *in, *out;
+	int fput_in, fput_out;
+
+	if (unlikely(!len))
+		return 0;
+
+	error = -EBADF;
+	in = fget_light(fdin, &fput_in);
+	if (in) {
+		if (in->f_mode & FMODE_READ) {
+			out = fget_light(fdout, &fput_out);
+			if (out) {
+				if (out->f_mode & FMODE_WRITE)
+					error = do_splice(in, out, len, flags);
+				fput_light(out, fput_out);
+			}
+		}
+
+		fput_light(in, fput_in);
+	}
+
+	return error;
+}
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index 014e356..789e9bd 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -318,8 +318,9 @@
 #define __NR_unshare		310
 #define __NR_set_robust_list	311
 #define __NR_get_robust_list	312
+#define __NR_sys_splice		313
 
-#define NR_syscalls 313
+#define NR_syscalls 314
 
 /*
  * user-visible error numbers are in the range -1 - -128: see
diff --git a/include/asm-ia64/asmmacro.h b/include/asm-ia64/asmmacro.h
index d4cec32..edf2cebb 100644
--- a/include/asm-ia64/asmmacro.h
+++ b/include/asm-ia64/asmmacro.h
@@ -38,6 +38,10 @@
 
 /*
  * Helper macros for accessing user memory.
+ *
+ * When adding any new .section/.previous entries here, make sure to
+ * also add it to the DISCARD section in arch/ia64/kernel/gate.lds.S or
+ * unpleasant things will happen.
  */
 
 	.section "__ex_table", "a"		// declare section & section attributes
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index 019956c..36070c1 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -285,12 +285,13 @@
 #define __NR_faccessat			1293
 /* 1294, 1295 reserved for pselect/ppoll */
 #define __NR_unshare			1296
+#define __NR_splice			1297
 
 #ifdef __KERNEL__
 
 #include <linux/config.h>
 
-#define NR_syscalls			273 /* length of syscall table */
+#define NR_syscalls			274 /* length of syscall table */
 
 #define __ARCH_WANT_SYS_RT_SIGACTION
 
diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h
index 99817a8..f44b529 100644
--- a/include/asm-powerpc/bug.h
+++ b/include/asm-powerpc/bug.h
@@ -30,34 +30,60 @@
 
 #ifdef CONFIG_BUG
 
+/*
+ * BUG_ON() and WARN_ON() do their best to cooperate with compile-time
+ * optimisations. However depending on the complexity of the condition
+ * some compiler versions may not produce optimal results.
+ */
+
 #define BUG() do {							 \
 	__asm__ __volatile__(						 \
 		"1:	twi 31,0,0\n"					 \
 		".section __bug_table,\"a\"\n"				 \
-		"\t"PPC_LONG"	1b,%0,%1,%2\n"			 \
+		"\t"PPC_LONG"	1b,%0,%1,%2\n"				 \
 		".previous"						 \
 		: : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \
 } while (0)
 
 #define BUG_ON(x) do {						\
-	__asm__ __volatile__(					\
+	if (__builtin_constant_p(x)) {				\
+		if (x)						\
+			BUG();					\
+	} else {						\
+		__asm__ __volatile__(				\
 		"1:	"PPC_TLNEI"	%0,0\n"			\
 		".section __bug_table,\"a\"\n"			\
-		"\t"PPC_LONG"	1b,%1,%2,%3\n"		\
+		"\t"PPC_LONG"	1b,%1,%2,%3\n"			\
 		".previous"					\
 		: : "r" ((long)(x)), "i" (__LINE__),		\
 		    "i" (__FILE__), "i" (__FUNCTION__));	\
+	}							\
+} while (0)
+
+#define __WARN() do {						\
+	__asm__ __volatile__(					\
+		"1:	twi 31,0,0\n"				\
+		".section __bug_table,\"a\"\n"			\
+		"\t"PPC_LONG"	1b,%0,%1,%2\n"			\
+		".previous"					\
+		: : "i" (__LINE__ + BUG_WARNING_TRAP),		\
+		    "i" (__FILE__), "i" (__FUNCTION__));	\
 } while (0)
 
 #define WARN_ON(x) do {						\
-	__asm__ __volatile__(					\
+	if (__builtin_constant_p(x)) {				\
+		if (x)						\
+			__WARN();				\
+	} else {						\
+		__asm__ __volatile__(				\
 		"1:	"PPC_TLNEI"	%0,0\n"			\
 		".section __bug_table,\"a\"\n"			\
-		"\t"PPC_LONG"	1b,%1,%2,%3\n"		\
+		"\t"PPC_LONG"	1b,%1,%2,%3\n"			\
 		".previous"					\
 		: : "r" ((long)(x)),				\
 		    "i" (__LINE__ + BUG_WARNING_TRAP),		\
 		    "i" (__FILE__), "i" (__FUNCTION__));	\
+	}							\
 } while (0)
 
 #define HAVE_ARCH_BUG
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index fe45f6f..4321483 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -188,153 +188,154 @@
 		     !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \
 		     !defined(CONFIG_BOOKE))
 
-enum {
-	CPU_FTRS_PPC601 = CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE,
-	CPU_FTRS_603 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
-	    CPU_FTR_MAYBE_CAN_NAP,
-	CPU_FTRS_604 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE,
-	CPU_FTRS_740_NOTAU = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
-	    CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
-	CPU_FTRS_740 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
-	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
-	CPU_FTRS_750 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
-	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
-	CPU_FTRS_750FX1 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
-	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
-	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM,
-	CPU_FTRS_750FX2 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
-	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
-	    CPU_FTR_NO_DPM,
-	CPU_FTRS_750FX = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
-	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
-	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS,
-	CPU_FTRS_750GX = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
-	    CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU |
-	    CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
-	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS,
-	CPU_FTRS_7400_NOTAU = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
-	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
-	    CPU_FTR_MAYBE_CAN_NAP,
-	CPU_FTRS_7400 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR |
-	    CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
-	    CPU_FTR_MAYBE_CAN_NAP,
-	CPU_FTRS_7450_20 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
-	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
-	    CPU_FTR_NEED_COHERENT,
-	CPU_FTRS_7450_21 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_USE_TB |
-	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
-	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
-	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP |
-	    CPU_FTR_NEED_COHERENT,
-	CPU_FTRS_7450_23 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_USE_TB |
-	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
-	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
-	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT,
-	CPU_FTRS_7455_1 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_USE_TB |
-	    CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
-	    CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS |
-	    CPU_FTR_NEED_COHERENT,
-	CPU_FTRS_7455_20 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_USE_TB |
-	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
-	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
-	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP |
-	    CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS,
-	CPU_FTRS_7455 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_USE_TB |
-	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
-	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
-	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
-	    CPU_FTR_NEED_COHERENT,
-	CPU_FTRS_7447_10 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_USE_TB |
-	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
-	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
-	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
-	    CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC,
-	CPU_FTRS_7447 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_USE_TB |
-	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
-	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
-	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
-	    CPU_FTR_NEED_COHERENT,
-	CPU_FTRS_7447A = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_USE_TB |
-	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
-	    CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 |
-	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS |
-	    CPU_FTR_NEED_COHERENT,
-	CPU_FTRS_82XX = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB,
-	CPU_FTRS_G2_LE = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
-	    CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
-	CPU_FTRS_E300 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE |
-	    CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS |
-	    CPU_FTR_COMMON,
-	CPU_FTRS_CLASSIC32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
-	CPU_FTRS_POWER3_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
-	CPU_FTRS_POWER4_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_NODSISRALIGN,
-	CPU_FTRS_970_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_ALTIVEC_COMP |
-	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN,
-	CPU_FTRS_8XX = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
-	CPU_FTRS_40X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
-	    CPU_FTR_NODSISRALIGN,
-	CPU_FTRS_44X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
-	    CPU_FTR_NODSISRALIGN,
-	CPU_FTRS_E200 = CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN,
-	CPU_FTRS_E500 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
-	    CPU_FTR_NODSISRALIGN,
-	CPU_FTRS_E500_2 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
-	    CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN,
-	CPU_FTRS_GENERIC_32 = CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN,
+#define CPU_FTRS_PPC601	(CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE)
+#define CPU_FTRS_603	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
+	    CPU_FTR_MAYBE_CAN_NAP)
+#define CPU_FTRS_604	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE)
+#define CPU_FTRS_740_NOTAU	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+	    CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+#define CPU_FTRS_740	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+#define CPU_FTRS_750	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+#define CPU_FTRS_750FX1	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM)
+#define CPU_FTRS_750FX2	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+	    CPU_FTR_NO_DPM)
+#define CPU_FTRS_750FX	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_750GX	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+	    CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | \
+	    CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_7400_NOTAU	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
+	    CPU_FTR_MAYBE_CAN_NAP)
+#define CPU_FTRS_7400	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
+	    CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
+	    CPU_FTR_MAYBE_CAN_NAP)
+#define CPU_FTRS_7450_20	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+	    CPU_FTR_NEED_COHERENT)
+#define CPU_FTRS_7450_21	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_USE_TB | \
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
+	    CPU_FTR_NEED_COHERENT)
+#define CPU_FTRS_7450_23	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_USE_TB | \
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT)
+#define CPU_FTRS_7455_1	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_USE_TB | \
+	    CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \
+	    CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \
+	    CPU_FTR_NEED_COHERENT)
+#define CPU_FTRS_7455_20	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_USE_TB | \
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_7455	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_USE_TB | \
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
+	    CPU_FTR_NEED_COHERENT)
+#define CPU_FTRS_7447_10	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_USE_TB | \
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC)
+#define CPU_FTRS_7447	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_USE_TB | \
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
+	    CPU_FTR_NEED_COHERENT)
+#define CPU_FTRS_7447A	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_USE_TB | \
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
+	    CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
+	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
+	    CPU_FTR_NEED_COHERENT)
+#define CPU_FTRS_82XX	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB)
+#define CPU_FTRS_G2_LE	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+	    CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS)
+#define CPU_FTRS_E300	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+	    CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
+	    CPU_FTR_COMMON)
+#define CPU_FTRS_CLASSIC32	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
+#define CPU_FTRS_POWER3_32	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
+#define CPU_FTRS_POWER4_32	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_970_32	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
+	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_ALTIVEC_COMP | \
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_8XX	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB)
+#define CPU_FTRS_40X	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+	    CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_44X	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+	    CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_E200	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_E500	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+	    CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_E500_2	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+	    CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 #ifdef __powerpc64__
-	CPU_FTRS_POWER3 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
-	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR,
-	CPU_FTRS_RS64 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
-	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
-	    CPU_FTR_MMCRA | CPU_FTR_CTRL,
-	CPU_FTRS_POWER4 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
-	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA,
-	CPU_FTRS_PPC970 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
-	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 |
-	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA,
-	CPU_FTRS_POWER5 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
-	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 |
-	    CPU_FTR_MMCRA | CPU_FTR_SMT |
-	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
-	    CPU_FTR_MMCRA_SIHV | CPU_FTR_PURR,
-	CPU_FTRS_CELL = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
-	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 |
-	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT |
-	    CPU_FTR_CTRL | CPU_FTR_PAUSE_ZERO,
-	CPU_FTRS_COMPATIBLE = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
-	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2,
+#define CPU_FTRS_POWER3	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR)
+#define CPU_FTRS_RS64	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \
+	    CPU_FTR_MMCRA | CPU_FTR_CTRL)
+#define CPU_FTRS_POWER4	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA)
+#define CPU_FTRS_PPC970	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA)
+#define CPU_FTRS_POWER5	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
+	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
+	    CPU_FTR_MMCRA_SIHV | CPU_FTR_PURR)
+#define CPU_FTRS_CELL	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
+	    CPU_FTR_CTRL | CPU_FTR_PAUSE_ZERO)
+#define CPU_FTRS_COMPATIBLE	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2)
 #endif
 
-	CPU_FTRS_POSSIBLE =
 #ifdef __powerpc64__
-	    CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 |
-	    CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_CELL |
-            CPU_FTR_CI_LARGE_PAGE |
+#define CPU_FTRS_POSSIBLE	\
+	    (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 |	\
+	    CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_CELL |	\
+            CPU_FTR_CI_LARGE_PAGE)
 #else
+enum {
+	CPU_FTRS_POSSIBLE =
 #if CLASSIC_PPC
 	    CPU_FTRS_PPC601 | CPU_FTRS_603 | CPU_FTRS_604 | CPU_FTRS_740_NOTAU |
 	    CPU_FTRS_740 | CPU_FTRS_750 | CPU_FTRS_750FX1 |
@@ -368,14 +369,18 @@
 #ifdef CONFIG_E500
 	    CPU_FTRS_E500 | CPU_FTRS_E500_2 |
 #endif
-#endif /* __powerpc64__ */
 	    0,
+};
+#endif /* __powerpc64__ */
 
-	CPU_FTRS_ALWAYS =
 #ifdef __powerpc64__
-	    CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 &
-	    CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_CELL &
+#define CPU_FTRS_ALWAYS		\
+	    (CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 &	\
+	    CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_CELL &	\
+	    CPU_FTRS_POSSIBLE)
 #else
+enum {
+	CPU_FTRS_ALWAYS =
 #if CLASSIC_PPC
 	    CPU_FTRS_PPC601 & CPU_FTRS_603 & CPU_FTRS_604 & CPU_FTRS_740_NOTAU &
 	    CPU_FTRS_740 & CPU_FTRS_750 & CPU_FTRS_750FX1 &
@@ -409,9 +414,9 @@
 #ifdef CONFIG_E500
 	    CPU_FTRS_E500 & CPU_FTRS_E500_2 &
 #endif
-#endif /* __powerpc64__ */
 	    CPU_FTRS_POSSIBLE,
 };
+#endif /* __powerpc64__ */
 
 static inline int cpu_has_feature(unsigned long feature)
 {
diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h
index ce37882..77069df 100644
--- a/include/asm-powerpc/firmware.h
+++ b/include/asm-powerpc/firmware.h
@@ -82,13 +82,11 @@
 /* This is used to identify firmware features which are available
  * to the kernel.
  */
-extern unsigned long	ppc64_firmware_features;
+extern unsigned long	powerpc_firmware_features;
 
-static inline unsigned long firmware_has_feature(unsigned long feature)
-{
-	return (FW_FEATURE_ALWAYS & feature) ||
-		(FW_FEATURE_POSSIBLE & ppc64_firmware_features & feature);
-}
+#define firmware_has_feature(feature)					\
+	((FW_FEATURE_ALWAYS & (feature)) ||				\
+		(FW_FEATURE_POSSIBLE & powerpc_firmware_features & (feature)))
 
 extern void system_reset_fwnmi(void);
 extern void machine_check_fwnmi(void);
diff --git a/include/asm-powerpc/floppy.h b/include/asm-powerpc/floppy.h
index e258778..608164c 100644
--- a/include/asm-powerpc/floppy.h
+++ b/include/asm-powerpc/floppy.h
@@ -35,6 +35,7 @@
 #ifdef CONFIG_PCI
 
 #include <linux/pci.h>
+#include <asm/ppc-pci.h>	/* for ppc64_isabridge_dev */
 
 #define fd_dma_setup(addr,size,mode,io) powerpc_fd_dma_setup(addr,size,mode,io)
 
@@ -52,12 +53,12 @@
 	if (bus_addr 
 	    && (addr != prev_addr || size != prev_size || dir != prev_dir)) {
 		/* different from last time -- unmap prev */
-		pci_unmap_single(NULL, bus_addr, prev_size, prev_dir);
+		pci_unmap_single(ppc64_isabridge_dev, bus_addr, prev_size, prev_dir);
 		bus_addr = 0;
 	}
 
 	if (!bus_addr)	/* need to map it */
-		bus_addr = pci_map_single(NULL, addr, size, dir);
+		bus_addr = pci_map_single(ppc64_isabridge_dev, addr, size, dir);
 
 	/* remember this one as prev */
 	prev_addr = addr;
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
index 38ca9ad..b72c04f 100644
--- a/include/asm-powerpc/hvcall.h
+++ b/include/asm-powerpc/hvcall.h
@@ -9,6 +9,7 @@
 #define H_Closed	2	/* Resource closed */
 #define H_Constrained	4	/* Resource request constrained to max allowed */
 #define H_InProgress   14	/* Kind of like busy */
+#define H_Pending      17	/* returned from H_POLL_PENDING */
 #define H_Continue     18	/* Returned from H_Join on success */
 #define H_LongBusyStartRange   9900  /* Start of long busy range */
 #define H_LongBusyOrder1msec   9900  /* Long busy, hint that 1msec is a good time to retry */
diff --git a/include/asm-powerpc/hvconsole.h b/include/asm-powerpc/hvconsole.h
index 34daf7b..35ea69e 100644
--- a/include/asm-powerpc/hvconsole.h
+++ b/include/asm-powerpc/hvconsole.h
@@ -24,28 +24,18 @@
 #ifdef __KERNEL__
 
 /*
- * This is the max number of console adapters that can/will be found as
- * console devices on first stage console init.  Any number beyond this range
- * can't be used as a console device but is still a valid tty device.
+ * PSeries firmware will only send/recv up to 16 bytes of character data per
+ * hcall.
  */
-#define MAX_NR_HVC_CONSOLES	16
+#define MAX_VIO_PUT_CHARS	16
+#define SIZE_VIO_GET_CHARS	16
 
-/* implemented by a low level driver */
-struct hv_ops {
-	int (*get_chars)(uint32_t vtermno, char *buf, int count);
-	int (*put_chars)(uint32_t vtermno, const char *buf, int count);
-};
+/*
+ * Vio firmware always attempts to fetch MAX_VIO_GET_CHARS chars.  The 'count'
+ * parm is included to conform to put_chars() function pointer template
+ */
 extern int hvc_get_chars(uint32_t vtermno, char *buf, int count);
 extern int hvc_put_chars(uint32_t vtermno, const char *buf, int count);
 
-struct hvc_struct;
-
-/* Register a vterm and a slot index for use as a console (console_init) */
-extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops);
-/* register a vterm for hvc tty operation (module_init or hotplug add) */
-extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq,
-						 struct hv_ops *ops);
-/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */
-extern int __devexit hvc_remove(struct hvc_struct *hp);
 #endif /* __KERNEL__ */
 #endif /* _PPC64_HVCONSOLE_H */
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 5348b82..5ed8476 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -47,6 +47,7 @@
 #endif
 
 struct machdep_calls {
+	char		*name;
 #ifdef CONFIG_PPC64
 	void            (*hpte_invalidate)(unsigned long slot,
 					   unsigned long va,
@@ -85,9 +86,9 @@
 	void		(*iommu_dev_setup)(struct pci_dev *dev);
 	void		(*iommu_bus_setup)(struct pci_bus *bus);
 	void		(*irq_bus_setup)(struct pci_bus *bus);
-#endif
+#endif /* CONFIG_PPC64 */
 
-	int		(*probe)(int platform);
+	int		(*probe)(void);
 	void		(*setup_arch)(void);
 	void		(*init_early)(void);
 	/* Optional, may be NULL. */
@@ -158,6 +159,12 @@
 	/* Idle loop for this platform, leave empty for default idle loop */
 	void		(*idle_loop)(void);
 
+	/*
+	 * Function for waiting for work with reduced power in idle loop;
+	 * called with interrupts disabled.
+	 */
+	void		(*power_save)(void);
+
 	/* Function to enable performance monitor counters for this
 	   platform, called once per cpu. */
 	void		(*enable_pmcs)(void);
@@ -170,13 +177,6 @@
 	   May be NULL. */
 	void		(*init)(void);
 
-	void		(*idle)(void);
-	void		(*power_save)(void);
-
-	void		(*heartbeat)(void);
-	unsigned long	heartbeat_reset;
-	unsigned long	heartbeat_count;
-
 	void		(*setup_io_mappings)(void);
 
 	void		(*early_serial_map)(void);
@@ -208,8 +208,6 @@
 	/* Called at then very end of pcibios_init() */
 	void (*pcibios_after_init)(void);
 
-	/* this is for modules, since _machine can be a define -- Cort */
-	int ppc_machine;
 #endif /* CONFIG_PPC32 */
 
 	/* Called to shutdown machine specific hardware not already controlled
@@ -242,10 +240,29 @@
 #endif /* CONFIG_KEXEC */
 };
 
-extern void default_idle(void);
-extern void native_idle(void);
+extern void power4_idle(void);
+extern void ppc6xx_idle(void);
 
+/*
+ * ppc_md contains a copy of the machine description structure for the
+ * current platform. machine_id contains the initial address where the
+ * description was found during boot.
+ */
 extern struct machdep_calls ppc_md;
+extern struct machdep_calls *machine_id;
+
+#define __machine_desc __attribute__ ((__section__ (".machine.desc")))
+
+#define define_machine(name) struct machdep_calls mach_##name __machine_desc =
+#define machine_is(name) \
+	({ \
+		extern struct machdep_calls mach_##name \
+			__attribute__((weak));		 \
+		machine_id == &mach_##name; \
+	})
+
+extern void probe_machine(void);
+
 extern char cmd_line[COMMAND_LINE_SIZE];
 
 #ifdef CONFIG_PPC_PMAC
diff --git a/include/asm-powerpc/oprofile_impl.h b/include/asm-powerpc/oprofile_impl.h
index 338e6a7..5b33994 100644
--- a/include/asm-powerpc/oprofile_impl.h
+++ b/include/asm-powerpc/oprofile_impl.h
@@ -17,9 +17,6 @@
 
 /* Per-counter configuration as set via oprofilefs.  */
 struct op_counter_config {
-#ifdef __powerpc64__
-	unsigned long valid;
-#endif
 	unsigned long enabled;
 	unsigned long event;
 	unsigned long count;
@@ -38,9 +35,6 @@
 #endif
 	unsigned long enable_kernel;
 	unsigned long enable_user;
-#ifdef CONFIG_PPC64
-	unsigned long backtrace_spinlocks;
-#endif
 };
 
 /* Per-arch configuration */
@@ -56,17 +50,12 @@
 	int num_counters;
 };
 
-#ifdef CONFIG_FSL_BOOKE
 extern struct op_powerpc_model op_model_fsl_booke;
-#else /* Otherwise, it's classic */
-
-#ifdef CONFIG_PPC64
 extern struct op_powerpc_model op_model_rs64;
 extern struct op_powerpc_model op_model_power4;
-
-#else /* Otherwise, CONFIG_PPC32 */
 extern struct op_powerpc_model op_model_7450;
-#endif
+
+#ifndef CONFIG_FSL_BOOKE
 
 /* All the classic PPC parts use these */
 static inline unsigned int ctr_read(unsigned int i)
@@ -134,5 +123,7 @@
 }
 #endif /* !CONFIG_FSL_BOOKE */
 
+extern void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth);
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_OPROFILE_IMPL_H */
diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h
index 4465b95..706325f 100644
--- a/include/asm-powerpc/paca.h
+++ b/include/asm-powerpc/paca.h
@@ -105,5 +105,7 @@
 
 extern struct paca_struct paca[];
 
+void setup_boot_paca(void);
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_PACA_H */
diff --git a/include/asm-powerpc/percpu.h b/include/asm-powerpc/percpu.h
index 464301c..184a7a4 100644
--- a/include/asm-powerpc/percpu.h
+++ b/include/asm-powerpc/percpu.h
@@ -27,7 +27,7 @@
 #define percpu_modcopy(pcpudst, src, size)			\
 do {								\
 	unsigned int __i;					\
-	for_each_cpu(__i)					\
+	for_each_possible_cpu(__i)				\
 		memcpy((pcpudst)+__per_cpu_offset(__i),		\
 		       (src), (size));				\
 } while (0)
diff --git a/include/asm-powerpc/pmac_feature.h b/include/asm-powerpc/pmac_feature.h
index 3221628..d3599cc 100644
--- a/include/asm-powerpc/pmac_feature.h
+++ b/include/asm-powerpc/pmac_feature.h
@@ -305,7 +305,7 @@
 extern void pmac_set_early_video_resume(void (*proc)(void *data), void *data);
 extern void pmac_call_early_video_resume(void);
 
-#define PMAC_FTR_DEF(x) ((_MACH_Pmac << 16) | (x))
+#define PMAC_FTR_DEF(x) ((0x6660000) | (x))
 
 /* The AGP driver registers itself here */
 extern void pmac_register_agp_pm(struct pci_dev *bridge,
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
index 1c64a21..93f83ef 100644
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -22,22 +22,6 @@
  * -- BenH.
  */
 
-/* Platforms codes (to be obsoleted) */
-#define PLATFORM_PSERIES	0x0100
-#define PLATFORM_PSERIES_LPAR	0x0101
-#define PLATFORM_ISERIES_LPAR	0x0201
-#define PLATFORM_LPAR		0x0001
-#define PLATFORM_POWERMAC	0x0400
-#define PLATFORM_MAPLE		0x0500
-#define PLATFORM_PREP		0x0600
-#define PLATFORM_CHRP		0x0700
-#define PLATFORM_CELL		0x1000
-
-/* Compat platform codes for 32 bits */
-#define _MACH_prep	PLATFORM_PREP
-#define _MACH_Pmac	PLATFORM_POWERMAC
-#define _MACH_chrp	PLATFORM_CHRP
-
 /* PREP sub-platform types see residual.h for these */
 #define _PREP_Motorola	0x01	/* motorola prep */
 #define _PREP_Firm	0x02	/* firmworks prep */
@@ -49,18 +33,14 @@
 #define _CHRP_IBM	0x05	/* IBM chrp, the longtrail and longtrail 2 */
 #define _CHRP_Pegasos	0x06	/* Genesi/bplan's Pegasos and Pegasos2 */
 
-#ifdef __KERNEL__
-#define platform_is_pseries()	(_machine == PLATFORM_PSERIES || \
-				 _machine == PLATFORM_PSERIES_LPAR)
+#if defined(__KERNEL__) && defined(CONFIG_PPC32)
 
-#if defined(CONFIG_PPC_MULTIPLATFORM)
-extern int _machine;
+extern int _chrp_type;
 
-#ifdef CONFIG_PPC32
+#ifdef CONFIG_PPC_PREP
 
 /* what kind of prep workstation we are */
 extern int _prep_type;
-extern int _chrp_type;
 
 /*
  * This is used to identify the board type from a given PReP board
@@ -70,17 +50,14 @@
 extern unsigned char ucBoardRev;
 extern unsigned char ucBoardRevMaj, ucBoardRevMin;
 
-#endif /* CONFIG_PPC32 */
+#endif /* CONFIG_PPC_PREP */
 
-#elif defined(CONFIG_PPC_ISERIES)
-/*
- * iSeries is soon to become MULTIPLATFORM hopefully ...
- */
-#define _machine PLATFORM_ISERIES_LPAR
-#else
+#ifndef CONFIG_PPC_MULTIPLATFORM
 #define _machine 0
 #endif /* CONFIG_PPC_MULTIPLATFORM */
-#endif /* __KERNEL__ */
+
+#endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */
+
 /*
  * Default implementation of macro that returns current
  * instruction pointer ("program counter").
@@ -251,6 +228,10 @@
 #define cpu_relax()	barrier()
 #endif
 
+/* Check that a certain kernel stack pointer is valid in task_struct p */
+int validate_sp(unsigned long sp, struct task_struct *p,
+                       unsigned long nbytes);
+
 /*
  * Prefetch macros.
  */
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 782e13a..97ef1cd 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -149,12 +149,14 @@
 extern void of_node_put(struct device_node *node);
 
 /* For scanning the flat device-tree at boot time */
-int __init of_scan_flat_dt(int (*it)(unsigned long node,
-				     const char *uname, int depth,
-				     void *data),
-			   void *data);
-void* __init of_get_flat_dt_prop(unsigned long node, const char *name,
-				 unsigned long *size);
+extern int __init of_scan_flat_dt(int (*it)(unsigned long node,
+					    const char *uname, int depth,
+					    void *data),
+				  void *data);
+extern void* __init of_get_flat_dt_prop(unsigned long node, const char *name,
+					unsigned long *size);
+extern int __init of_flat_dt_is_compatible(unsigned long node, const char *name);
+extern unsigned long __init of_get_flat_dt_root(void);
 
 /* For updating the device tree at runtime */
 extern void of_attach_node(struct device_node *);
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index 72bfe3a..bd467bf 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -622,6 +622,10 @@
 extern unsigned long scom970_read(unsigned int address);
 extern void scom970_write(unsigned int address, unsigned long value);
 
+#else
+#define ppc64_runlatch_on()
+#define ppc64_runlatch_off()
+
 #endif /* CONFIG_PPC64 */
 
 #define __get_SP()	({unsigned long sp; \
diff --git a/include/asm-powerpc/smp.h b/include/asm-powerpc/smp.h
index 98581e5..4a716f7 100644
--- a/include/asm-powerpc/smp.h
+++ b/include/asm-powerpc/smp.h
@@ -29,7 +29,6 @@
 #endif
 
 extern int boot_cpuid;
-extern int boot_cpuid_phys;
 
 extern void cpu_die(void);
 
@@ -99,6 +98,7 @@
 #else
 /* 32-bit */
 #ifndef CONFIG_SMP
+extern int boot_cpuid_phys;
 #define get_hard_smp_processor_id(cpu) 	boot_cpuid_phys
 #define set_hard_smp_processor_id(cpu, phys)
 #endif
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index 38bacf2..f431d8b0 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -110,6 +110,7 @@
 	char *name;
 	unsigned long local_store_phys;
 	u8 *local_store;
+	unsigned long problem_phys;
 	struct spu_problem __iomem *problem;
 	struct spu_priv1 __iomem *priv1;
 	struct spu_priv2 __iomem *priv2;
@@ -137,6 +138,7 @@
 	void (* wbox_callback)(struct spu *spu);
 	void (* ibox_callback)(struct spu *spu);
 	void (* stop_callback)(struct spu *spu);
+	void (* mfc_callback)(struct spu *spu);
 
 	char irq_c0[8];
 	char irq_c1[8];
@@ -149,6 +151,14 @@
 int spu_irq_class_1_bottom(struct spu *spu);
 void spu_irq_setaffinity(struct spu *spu, int cpu);
 
+/* system callbacks from the SPU */
+struct spu_syscall_block {
+	u64 nr_ret;
+	u64 parm[6];
+};
+extern long spu_sys_callback(struct spu_syscall_block *s);
+
+/* syscalls implemented in spufs */
 extern struct spufs_calls {
 	asmlinkage long (*create_thread)(const char __user *name,
 					unsigned int flags, mode_t mode);
@@ -399,7 +409,6 @@
 #define SPU_GET_REVISION_BITS(vr)	(vr & SPU_REVISION_BITS)
 	u8  pad_0x28_0x100[0x100 - 0x28];			/* 0x28 */
 
-
 	/* Interrupt Area */
 	u64 int_mask_RW[3];					/* 0x100 */
 #define CLASS0_ENABLE_DMA_ALIGNMENT_INTR		0x1L
diff --git a/include/asm-powerpc/syscalls.h b/include/asm-powerpc/syscalls.h
new file mode 100644
index 0000000..c2fe79d
--- /dev/null
+++ b/include/asm-powerpc/syscalls.h
@@ -0,0 +1,58 @@
+#ifndef __ASM_POWERPC_SYSCALLS_H
+#define __ASM_POWERPC_SYSCALLS_H
+#ifdef __KERNEL__
+
+#include <linux/compiler.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <asm/signal.h>
+
+struct new_utsname;
+struct pt_regs;
+struct rtas_args;
+struct sigaction;
+
+asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
+		unsigned long prot, unsigned long flags,
+		unsigned long fd, off_t offset);
+asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len,
+		unsigned long prot, unsigned long flags,
+		unsigned long fd, unsigned long pgoff);
+asmlinkage int sys_execve(unsigned long a0, unsigned long a1,
+		unsigned long a2, unsigned long a3, unsigned long a4,
+		unsigned long a5, struct pt_regs *regs);
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long usp,
+		int __user *parent_tidp, void __user *child_threadptr,
+		int __user *child_tidp, int p6, struct pt_regs *regs);
+asmlinkage int sys_fork(unsigned long p1, unsigned long p2,
+		unsigned long p3, unsigned long p4, unsigned long p5,
+		unsigned long p6, struct pt_regs *regs);
+asmlinkage int sys_vfork(unsigned long p1, unsigned long p2,
+		unsigned long p3, unsigned long p4, unsigned long p5,
+		unsigned long p6, struct pt_regs *regs);
+asmlinkage int sys_pipe(int __user *fildes);
+asmlinkage long sys_rt_sigaction(int sig,
+		const struct sigaction __user *act,
+		struct sigaction __user *oact, size_t sigsetsize);
+asmlinkage int sys_ipc(uint call, int first, unsigned long second,
+		long third, void __user *ptr, long fifth);
+asmlinkage long ppc64_personality(unsigned long personality);
+asmlinkage int ppc_rtas(struct rtas_args __user *uargs);
+asmlinkage time_t sys64_time(time_t __user * tloc);
+asmlinkage long ppc_newuname(struct new_utsname __user * name);
+
+asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset,
+		size_t sigsetsize);
+
+#ifndef __powerpc64__
+asmlinkage long sys_sigaltstack(const stack_t __user *uss,
+		stack_t __user *uoss, int r5, int r6, int r7, int r8,
+		struct pt_regs *regs);
+#else /* __powerpc64__ */
+asmlinkage long sys_sigaltstack(const stack_t __user *uss,
+		stack_t __user *uoss, unsigned long r5, unsigned long r6,
+		unsigned long r7, unsigned long r8, struct pt_regs *regs);
+#endif /* __powerpc64__ */
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_POWERPC_SYSCALLS_H */
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index 3555699..536ba08 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -301,8 +301,9 @@
 #define __NR_pselect6		280
 #define __NR_ppoll		281
 #define __NR_unshare		282
+#define __NR_splice		283
 
-#define __NR_syscalls		283
+#define __NR_syscalls		284
 
 #ifdef __KERNEL__
 #define __NR__exit __NR_exit
@@ -425,6 +426,7 @@
 #include <linux/types.h>
 #include <linux/compiler.h>
 #include <linux/linkage.h>
+#include <asm/syscalls.h>
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
@@ -460,44 +462,10 @@
  * System call prototypes.
  */
 #ifdef __KERNEL_SYSCALLS__
-extern pid_t setsid(void);
-extern int write(int fd, const char *buf, off_t count);
-extern int read(int fd, char *buf, off_t count);
-extern off_t lseek(int fd, off_t offset, int count);
-extern int dup(int fd);
 extern int execve(const char *file, char **argv, char **envp);
-extern int open(const char *file, int flag, int mode);
-extern int close(int fd);
-extern pid_t waitpid(pid_t pid, int *wait_stat, int options);
 #endif /* __KERNEL_SYSCALLS__ */
 
 /*
- * Functions that implement syscalls.
- */
-unsigned long sys_mmap(unsigned long addr, size_t len, unsigned long prot,
-		       unsigned long flags, unsigned long fd, off_t offset);
-unsigned long sys_mmap2(unsigned long addr, size_t len,
-			unsigned long prot, unsigned long flags,
-			unsigned long fd, unsigned long pgoff);
-struct pt_regs;
-int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
-		unsigned long a3, unsigned long a4, unsigned long a5,
-		struct pt_regs *regs);
-int sys_clone(unsigned long clone_flags, unsigned long usp,
-		int __user *parent_tidp, void __user *child_threadptr,
-		int __user *child_tidp, int p6, struct pt_regs *regs);
-int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3,
-		unsigned long p4, unsigned long p5, unsigned long p6,
-		struct pt_regs *regs);
-int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
-		unsigned long p4, unsigned long p5, unsigned long p6,
-		struct pt_regs *regs);
-int sys_pipe(int __user *fildes);
-struct sigaction;
-long sys_rt_sigaction(int sig, const struct sigaction __user *act,
-		      struct sigaction __user *oact, size_t sigsetsize);
-
-/*
  * "Conditional" syscalls
  *
  * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
diff --git a/include/asm-powerpc/vdso_datapage.h b/include/asm-powerpc/vdso_datapage.h
index 7aa9208..8a94f0e 100644
--- a/include/asm-powerpc/vdso_datapage.h
+++ b/include/asm-powerpc/vdso_datapage.h
@@ -55,6 +55,9 @@
 		__u32 minor;		/* Minor number			0x14 */
 	} version;
 
+	/* Note about the platform flags: it now only contains the lpar
+	 * bit. The actual platform number is dead and burried
+	 */
 	__u32 platform;			/* Platform flags		0x18 */
 	__u32 processor;		/* Processor type		0x1C */
 	__u64 processorCount;		/* # of physical processors	0x20 */
diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h
index a3e8a45..e1a0a7b 100644
--- a/include/asm-ppc/machdep.h
+++ b/include/asm-ppc/machdep.h
@@ -19,6 +19,18 @@
 struct seq_file;
 struct file;
 
+/*
+ * This is for compatibility with ARCH=powerpc.
+ */
+#define machine_is(x)	__MACHINE_IS_##x
+#define __MACHINE_IS_powermac	0
+#define __MACHINE_IS_chrp	0
+#ifdef CONFIG_PPC_PREP
+#define __MACHINE_IS_prep	1
+#else
+#define __MACHINE_IS_prep	0
+#endif
+
 /* We export this macro for external modules like Alsa to know if
  * ppc_md.feature_call is implemented or not
  */
@@ -44,7 +56,7 @@
 	void		(*power_off)(void);
 	void		(*halt)(void);
 
-	void		(*idle)(void);
+	void		(*idle_loop)(void);
 	void		(*power_save)(void);
 
 	long		(*time_init)(void); /* Optional, may be NULL */
@@ -104,9 +116,6 @@
 						unsigned long size,
 						pgprot_t vma_prot);
 
-	/* this is for modules, since _machine can be a define -- Cort */
-	int ppc_machine;
-
 	/* Motherboard/chipset features. This is a kind of general purpose
 	 * hook used to control some machine specific features (like reset
 	 * lines, chip power control, etc...).
diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
index 6167f74..7e98428 100644
--- a/include/asm-ppc/mpc52xx.h
+++ b/include/asm-ppc/mpc52xx.h
@@ -355,6 +355,7 @@
 	u32	snoop_window;		/* XLB + 0x70 */
 };
 
+#define MPC52xx_XLB_CFG_PLDIS		(1 << 31)
 #define MPC52xx_XLB_CFG_SNOOP		(1 << 15)
 
 /* Clock Distribution control */
@@ -427,6 +428,9 @@
 
 extern void mpc52xx_find_bridges(void);
 
+extern void mpc52xx_setup_cpu(void);
+
+
 
 	/* Matching of PSC function */
 struct mpc52xx_psc_func {
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index e1c62da..570b355 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -837,7 +837,8 @@
  */
 #define pgtable_cache_init()	do { } while (0)
 
-extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep);
+extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep,
+		      pmd_t **pmdp);
 
 #include <asm-generic/pgtable.h>
 
diff --git a/include/asm-ppc/prom.h b/include/asm-ppc/prom.h
index 6d431d6..adc5ae7 100644
--- a/include/asm-ppc/prom.h
+++ b/include/asm-ppc/prom.h
@@ -8,126 +8,19 @@
 #ifndef _PPC_PROM_H
 #define _PPC_PROM_H
 
-#include <linux/config.h>
-#include <linux/types.h>
-
-typedef u32 phandle;
-typedef u32 ihandle;
-
-struct address_range {
-	unsigned int space;
-	unsigned int address;
-	unsigned int size;
-};
-
-struct interrupt_info {
-	int	line;
-	int	sense;		/* +ve/-ve logic, edge or level, etc. */
-};
-
+/* This is used in arch/ppc/mm/mem_pieces.h */
 struct reg_property {
 	unsigned int address;
 	unsigned int size;
 };
 
-struct property {
-	char	*name;
-	int	length;
-	unsigned char *value;
-	struct property *next;
-};
-
 /*
- * Note: don't change this structure for now or you'll break BootX !
- */
-struct device_node {
-	char	*name;
-	char	*type;
-	phandle	node;
-	int	n_addrs;
-	struct	address_range *addrs;
-	int	n_intrs;
-	struct	interrupt_info *intrs;
-	char	*full_name;
-	struct	property *properties;
-	struct	device_node *parent;
-	struct	device_node *child;
-	struct	device_node *sibling;
-	struct	device_node *next;	/* next device of same type */
-	struct	device_node *allnext;	/* next in list of all nodes */
-};
-
-struct prom_args;
-typedef void (*prom_entry)(struct prom_args *);
-
-/* OBSOLETE: Old style node lookup */
-extern struct device_node *find_devices(const char *name);
-extern struct device_node *find_type_devices(const char *type);
-extern struct device_node *find_path_device(const char *path);
-extern struct device_node *find_compatible_devices(const char *type,
-						   const char *compat);
-extern struct device_node *find_all_nodes(void);
-
-/* New style node lookup */
-extern struct device_node *of_find_node_by_name(struct device_node *from,
-	const char *name);
-extern struct device_node *of_find_node_by_type(struct device_node *from,
-	const char *type);
-extern struct device_node *of_find_compatible_node(struct device_node *from,
-	const char *type, const char *compat);
-extern struct device_node *of_find_node_by_path(const char *path);
-extern struct device_node *of_find_all_nodes(struct device_node *prev);
-extern struct device_node *of_get_parent(const struct device_node *node);
-extern struct device_node *of_get_next_child(const struct device_node *node,
-					     struct device_node *prev);
-extern struct device_node *of_node_get(struct device_node *node);
-extern void of_node_put(struct device_node *node);
-
-/* Other Prototypes */
-extern void abort(void);
-extern unsigned long prom_init(int, int, prom_entry);
-extern void prom_print(const char *msg);
-extern void relocate_nodes(void);
-extern void finish_device_tree(void);
-extern int device_is_compatible(struct device_node *device, const char *);
-extern int machine_is_compatible(const char *compat);
-extern unsigned char *get_property(struct device_node *node, const char *name,
-				   int *lenp);
-extern int prom_add_property(struct device_node* np, struct property* prop);
-extern void prom_get_irq_senses(unsigned char *, int, int);
-extern int prom_n_addr_cells(struct device_node* np);
-extern int prom_n_size_cells(struct device_node* np);
-
-extern struct resource*
-request_OF_resource(struct device_node* node, int index, const char* name_postfix);
-extern int release_OF_resource(struct device_node* node, int index);
-
-extern void print_properties(struct device_node *node);
-extern int call_rtas(const char *service, int nargs, int nret,
-		     unsigned long *outputs, ...);
-
-/*
- * PCI <-> OF matching functions
- */
-struct pci_bus;
-struct pci_dev;
-extern int pci_device_from_OF_node(struct device_node *node,
-				   u8* bus, u8* devfn);
-extern struct device_node* pci_busdev_to_OF_node(struct pci_bus *, int);
-extern struct device_node* pci_device_to_OF_node(struct pci_dev *);
-extern void pci_create_OF_bus_map(void);
-
-/*
- * When we call back to the Open Firmware client interface, we usually
- * have to do that before the kernel is relocated to its final location
- * (this is because we can't use OF after we have overwritten the
- * exception vectors with our exception handlers).  These macros assist
- * in performing the address calculations that we need to do to access
- * data when the kernel is running at an address that is different from
- * the address that the kernel is linked at.  The reloc_offset() function
- * returns the difference between these two addresses and the macros
- * simplify the process of adding or subtracting this offset to/from
- * pointer values.  See arch/ppc/kernel/prom.c for how these are used.
+ * These macros assist in performing the address calculations that we
+ * need to do to access data when the kernel is running at an address
+ * that is different from the address that the kernel is linked at.
+ * The reloc_offset() function returns the difference between these
+ * two addresses and the macros simplify the process of adding or
+ * subtracting this offset to/from pointer values.
  */
 extern unsigned long reloc_offset(void);
 extern unsigned long add_reloc_offset(unsigned long);
@@ -136,45 +29,12 @@
 #define PTRRELOC(x)	((typeof(x))add_reloc_offset((unsigned long)(x)))
 #define PTRUNRELOC(x)	((typeof(x))sub_reloc_offset((unsigned long)(x)))
 
-
 /*
- * OF address retreival & translation
- */
-
-
-/* Translate an OF address block into a CPU physical address
- */
-#define OF_BAD_ADDR	((u64)-1)
-extern u64 of_translate_address(struct device_node *np, u32 *addr);
-
-/* Extract an address from a device, returns the region size and
- * the address space flags too. The PCI version uses a BAR number
- * instead of an absolute index
- */
-extern u32 *of_get_address(struct device_node *dev, int index,
-			   u64 *size, unsigned int *flags);
-extern u32 *of_get_pci_address(struct device_node *dev, int bar_no,
-			       u64 *size, unsigned int *flags);
-
-/* Get an address as a resource. Note that if your address is
- * a PIO address, the conversion will fail if the physical address
- * can't be internally converted to an IO token with
- * pci_address_to_pio(), that is because it's either called to early
- * or it can't be matched to any host bridge IO space
- */
-extern int of_address_to_resource(struct device_node *dev, int index,
-				  struct resource *r);
-extern int of_pci_address_to_resource(struct device_node *dev, int bar,
-				      struct resource *r);
-
-#ifndef CONFIG_PPC_OF
-/*
- * Fallback definitions for builds where we don't have prom.c included.
+ * Fallback definitions since we don't support OF in arch/ppc any more.
  */
 #define machine_is_compatible(x)		0
 #define of_find_compatible_node(f, t, c)	NULL
 #define get_property(p, n, l)			NULL
-#endif
 
 #endif /* _PPC_PROM_H */
 #endif /* __KERNEL__ */
diff --git a/include/asm-ppc/serial.h b/include/asm-ppc/serial.h
index 485a924..b74af54 100644
--- a/include/asm-ppc/serial.h
+++ b/include/asm-ppc/serial.h
@@ -41,15 +41,10 @@
 #else
 
 /*
- * XXX Assume for now it has PC-style ISA serial ports.
- * This is true for PReP and CHRP at least.
+ * XXX Assume it has PC-style ISA serial ports - true for PReP at least.
  */
 #include <asm/pc_serial.h>
 
-#if defined(CONFIG_MAC_SERIAL)
-#define SERIAL_DEV_OFFSET	((_machine == _MACH_prep || _machine == _MACH_chrp) ? 0 : 2)
-#endif
-
 #endif /* !CONFIG_GEMINI and others */
 #endif /* __ASM_SERIAL_H__ */
 #endif /* __KERNEL__ */
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index fcc5163..f21ff2c 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -609,8 +609,10 @@
 __SYSCALL(__NR_set_robust_list, sys_set_robust_list)
 #define __NR_get_robust_list	274
 __SYSCALL(__NR_get_robust_list, sys_get_robust_list)
+#define __NR_splice		275
+__SYSCALL(__NR_splice, sys_splice)
 
-#define __NR_syscall_max __NR_get_robust_list
+#define __NR_syscall_max __NR_splice
 
 #ifndef __NO_STUBS
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 408fe89..20fa5f6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1032,6 +1032,8 @@
 	int (*check_flags)(int);
 	int (*dir_notify)(struct file *filp, unsigned long arg);
 	int (*flock) (struct file *, int, struct file_lock *);
+	ssize_t (*splice_write)(struct inode *, struct file *, size_t, unsigned int);
+	ssize_t (*splice_read)(struct file *, struct inode *, size_t, unsigned int);
 };
 
 struct inode_operations {
@@ -1609,6 +1611,8 @@
 extern void do_generic_mapping_read(struct address_space *mapping,
 				    struct file_ra_state *, struct file *,
 				    loff_t *, read_descriptor_t *, read_actor_t);
+extern ssize_t generic_file_splice_read(struct file *, struct inode *, size_t, unsigned int);
+extern ssize_t generic_file_splice_write(struct inode *, struct file *, size_t, unsigned int);
 extern void
 file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
 extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov, 
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 0471922..0d61357 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -160,8 +160,10 @@
 	ATA_QCFLAG_DMAMAP	= ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
 	ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */
 
+	/* host set flags */
+	ATA_HOST_SIMPLEX	= (1 << 0),	/* Host is simplex, one DMA channel per host_set only */
+	
 	/* various lengths of time */
-	ATA_TMOUT_EDD		= 5 * HZ,	/* heuristic */
 	ATA_TMOUT_PIO		= 30 * HZ,
 	ATA_TMOUT_BOOT		= 30 * HZ,	/* heuristic */
 	ATA_TMOUT_BOOT_QUICK	= 7 * HZ,	/* heuristic */
@@ -279,6 +281,7 @@
 	unsigned long		irq;
 	unsigned int		irq_flags;
 	unsigned long		host_flags;
+	unsigned long		host_set_flags;
 	void __iomem		*mmio_base;
 	void			*private_data;
 };
@@ -291,6 +294,9 @@
 	unsigned int		n_ports;
 	void			*private_data;
 	const struct ata_port_operations *ops;
+	unsigned long		flags;
+	int			simplex_claimed;	/* Keep seperate in case we
+							   ever need to do this locked */
 	struct ata_port *	ports[0];
 };
 
@@ -420,6 +426,7 @@
 
 	void (*set_piomode) (struct ata_port *, struct ata_device *);
 	void (*set_dmamode) (struct ata_port *, struct ata_device *);
+	unsigned long (*mode_filter) (const struct ata_port *, struct ata_device *, unsigned long);
 
 	void (*tf_load) (struct ata_port *ap, const struct ata_taskfile *tf);
 	void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
@@ -430,6 +437,7 @@
 	void (*dev_select)(struct ata_port *ap, unsigned int device);
 
 	void (*phy_reset) (struct ata_port *ap); /* obsolete */
+	void (*set_mode) (struct ata_port *ap);
 	int (*probe_reset) (struct ata_port *ap, unsigned int *classes);
 
 	void (*post_set_mode) (struct ata_port *ap);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index e2ab2ac..870fe38 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -773,6 +773,7 @@
 #define PCI_DEVICE_ID_MOTOROLA_HAWK	0x4803
 #define PCI_DEVICE_ID_MOTOROLA_HARRIER	0x480b
 #define PCI_DEVICE_ID_MOTOROLA_MPC5200	0x5803
+#define PCI_DEVICE_ID_MOTOROLA_MPC5200B	0x5809
 
 #define PCI_VENDOR_ID_PROMISE		0x105a
 #define PCI_DEVICE_ID_PROMISE_20265	0x0d30
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index b12e59c..75c7f55 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -9,6 +9,7 @@
 	struct page *page;
 	unsigned int offset, len;
 	struct pipe_buf_operations *ops;
+	unsigned int stolen;
 };
 
 struct pipe_buf_operations {
@@ -16,6 +17,7 @@
 	void * (*map)(struct file *, struct pipe_inode_info *, struct pipe_buffer *);
 	void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *);
 	void (*release)(struct pipe_inode_info *, struct pipe_buffer *);
+	int (*steal)(struct pipe_inode_info *, struct pipe_buffer *);
 };
 
 struct pipe_inode_info {
@@ -53,4 +55,10 @@
 struct inode* pipe_new(struct inode* inode);
 void free_pipe_info(struct inode* inode);
 
+/*
+ * splice is tied to pipes as a transport (at least for now), so we'll just
+ * add the splice flags here.
+ */
+#define SPLICE_F_MOVE	(0x01)	/* move pages instead of copying */
+
 #endif
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index e487e3b..e78ffc7 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -569,5 +569,7 @@
 asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
 				   int flags, int mode);
 asmlinkage long sys_unshare(unsigned long unshare_flags);
+asmlinkage long sys_splice(int fdin, int fdout, size_t len,
+				unsigned int flags);
 
 #endif
diff --git a/include/net/sock.h b/include/net/sock.h
index 2aa73c0..af2b054 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -938,28 +938,7 @@
 		sk_free(sk);
 }
 
-static inline int sk_receive_skb(struct sock *sk, struct sk_buff *skb)
-{
-	int rc = NET_RX_SUCCESS;
-
-	if (sk_filter(sk, skb, 0))
-		goto discard_and_relse;
-
-	skb->dev = NULL;
-
-	bh_lock_sock(sk);
-	if (!sock_owned_by_user(sk))
-		rc = sk->sk_backlog_rcv(sk, skb);
-	else
-		sk_add_backlog(sk, skb);
-	bh_unlock_sock(sk);
-out:
-	sock_put(sk);
-	return rc;
-discard_and_relse:
-	kfree_skb(skb);
-	goto out;
-}
+extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb);
 
 /* Detach socket from process context.
  * Announce socket dead, detach it from wait queue and inode.
@@ -1044,33 +1023,9 @@
 	write_unlock(&sk->sk_dst_lock);
 }
 
-static inline struct dst_entry *
-__sk_dst_check(struct sock *sk, u32 cookie)
-{
-	struct dst_entry *dst = sk->sk_dst_cache;
+extern struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie);
 
-	if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
-		sk->sk_dst_cache = NULL;
-		dst_release(dst);
-		return NULL;
-	}
-
-	return dst;
-}
-
-static inline struct dst_entry *
-sk_dst_check(struct sock *sk, u32 cookie)
-{
-	struct dst_entry *dst = sk_dst_get(sk);
-
-	if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
-		sk_dst_reset(sk);
-		dst_release(dst);
-		return NULL;
-	}
-
-	return dst;
-}
+extern struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie);
 
 static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
 {
@@ -1140,45 +1095,7 @@
 
 extern void sk_stop_timer(struct sock *sk, struct timer_list* timer);
 
-static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
-{
-	int err = 0;
-	int skb_len;
-
-	/* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
-	   number of warnings when compiling with -W --ANK
-	 */
-	if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
-	    (unsigned)sk->sk_rcvbuf) {
-		err = -ENOMEM;
-		goto out;
-	}
-
-	/* It would be deadlock, if sock_queue_rcv_skb is used
-	   with socket lock! We assume that users of this
-	   function are lock free.
-	*/
-	err = sk_filter(sk, skb, 1);
-	if (err)
-		goto out;
-
-	skb->dev = NULL;
-	skb_set_owner_r(skb, sk);
-
-	/* Cache the SKB length before we tack it onto the receive
-	 * queue.  Once it is added it no longer belongs to us and
-	 * may be freed by other threads of control pulling packets
-	 * from the queue.
-	 */
-	skb_len = skb->len;
-
-	skb_queue_tail(&sk->sk_receive_queue, skb);
-
-	if (!sock_flag(sk, SOCK_DEAD))
-		sk->sk_data_ready(sk, skb_len);
-out:
-	return err;
-}
+extern int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 
 static inline int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
 {
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 61b7504..e100291 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -864,13 +864,19 @@
 /* XFRM tunnel handlers.  */
 struct xfrm_tunnel {
 	int (*handler)(struct sk_buff *skb);
-	void (*err_handler)(struct sk_buff *skb, __u32 info);
+	int (*err_handler)(struct sk_buff *skb, __u32 info);
+
+	struct xfrm_tunnel *next;
+	int priority;
 };
 
 struct xfrm6_tunnel {
-	int (*handler)(struct sk_buff **pskb);
-	void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
-			    int type, int code, int offset, __u32 info);
+	int (*handler)(struct sk_buff *skb);
+	int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
+			   int type, int code, int offset, __u32 info);
+
+	struct xfrm6_tunnel *next;
+	int priority;
 };
 
 extern void xfrm_init(void);
@@ -906,7 +912,7 @@
 extern int xfrm4_output(struct sk_buff *skb);
 extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
 extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
-extern int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi);
+extern int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi);
 extern int xfrm6_rcv(struct sk_buff **pskb);
 extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
 extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 697ac55e..7b1eb9a 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1819,6 +1819,22 @@
 	return rc;
 }
 
+
+#ifdef CONFIG_COMPAT
+static int atalk_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+	/*
+	 * All Appletalk ioctls except SIOCATALKDIFADDR are standard.  And
+	 * SIOCATALKDIFADDR is handled by upper layer as well, so there is
+	 * nothing to do.  Eventually SIOCATALKDIFADDR should be moved
+	 * here so there is no generic SIOCPROTOPRIVATE translation in the
+	 * system.
+	 */
+	return -ENOIOCTLCMD;
+}
+#endif
+
+
 static struct net_proto_family atalk_family_ops = {
 	.family		= PF_APPLETALK,
 	.create		= atalk_create,
@@ -1836,6 +1852,9 @@
 	.getname	= atalk_getname,
 	.poll		= datagram_poll,
 	.ioctl		= atalk_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= atalk_compat_ioctl,
+#endif
 	.listen		= sock_no_listen,
 	.shutdown	= sock_no_shutdown,
 	.setsockopt	= sock_no_setsockopt,
diff --git a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c
index 468ebdf..d42f63f 100644
--- a/net/bridge/netfilter/ebt_802_3.c
+++ b/net/bridge/netfilter/ebt_802_3.c
@@ -58,16 +58,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_802_3_init(void)
 {
 	return ebt_register_match(&filter_802_3);
 }
 
-static void __exit fini(void)
+static void __exit ebt_802_3_fini(void)
 {
 	ebt_unregister_match(&filter_802_3);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_802_3_init);
+module_exit(ebt_802_3_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c
index 5a1f5e3..a614485 100644
--- a/net/bridge/netfilter/ebt_among.c
+++ b/net/bridge/netfilter/ebt_among.c
@@ -213,16 +213,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_among_init(void)
 {
 	return ebt_register_match(&filter_among);
 }
 
-static void __exit fini(void)
+static void __exit ebt_among_fini(void)
 {
 	ebt_unregister_match(&filter_among);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_among_init);
+module_exit(ebt_among_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c
index b94c48c..a6c81d9 100644
--- a/net/bridge/netfilter/ebt_arp.c
+++ b/net/bridge/netfilter/ebt_arp.c
@@ -125,16 +125,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_arp_init(void)
 {
 	return ebt_register_match(&filter_arp);
 }
 
-static void __exit fini(void)
+static void __exit ebt_arp_fini(void)
 {
 	ebt_unregister_match(&filter_arp);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_arp_init);
+module_exit(ebt_arp_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c
index b934de9..d19fc4b 100644
--- a/net/bridge/netfilter/ebt_arpreply.c
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -82,16 +82,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_arpreply_init(void)
 {
 	return ebt_register_target(&reply_target);
 }
 
-static void __exit fini(void)
+static void __exit ebt_arpreply_fini(void)
 {
 	ebt_unregister_target(&reply_target);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_arpreply_init);
+module_exit(ebt_arpreply_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c
index f546308..4582659 100644
--- a/net/bridge/netfilter/ebt_dnat.c
+++ b/net/bridge/netfilter/ebt_dnat.c
@@ -61,16 +61,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_dnat_init(void)
 {
 	return ebt_register_target(&dnat);
 }
 
-static void __exit fini(void)
+static void __exit ebt_dnat_fini(void)
 {
 	ebt_unregister_target(&dnat);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_dnat_init);
+module_exit(ebt_dnat_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
index dc5d0b2..65b665c 100644
--- a/net/bridge/netfilter/ebt_ip.c
+++ b/net/bridge/netfilter/ebt_ip.c
@@ -112,16 +112,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_ip_init(void)
 {
 	return ebt_register_match(&filter_ip);
 }
 
-static void __exit fini(void)
+static void __exit ebt_ip_fini(void)
 {
 	ebt_unregister_match(&filter_ip);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_ip_init);
+module_exit(ebt_ip_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_limit.c b/net/bridge/netfilter/ebt_limit.c
index 637c884..d48fa5c 100644
--- a/net/bridge/netfilter/ebt_limit.c
+++ b/net/bridge/netfilter/ebt_limit.c
@@ -98,16 +98,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_limit_init(void)
 {
 	return ebt_register_match(&ebt_limit_reg);
 }
 
-static void __exit fini(void)
+static void __exit ebt_limit_fini(void)
 {
 	ebt_unregister_match(&ebt_limit_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_limit_init);
+module_exit(ebt_limit_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 288ff1d..d159c92 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -188,7 +188,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_log_init(void)
 {
 	int ret;
 
@@ -205,12 +205,12 @@
 	return 0;
 }
 
-static void __exit fini(void)
+static void __exit ebt_log_fini(void)
 {
 	nf_log_unregister_logger(&ebt_log_logger);
 	ebt_unregister_watcher(&log);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_log_init);
+module_exit(ebt_log_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
index c93d35a..770c0df 100644
--- a/net/bridge/netfilter/ebt_mark.c
+++ b/net/bridge/netfilter/ebt_mark.c
@@ -52,16 +52,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_mark_init(void)
 {
 	return ebt_register_target(&mark_target);
 }
 
-static void __exit fini(void)
+static void __exit ebt_mark_fini(void)
 {
 	ebt_unregister_target(&mark_target);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_mark_init);
+module_exit(ebt_mark_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c
index 625102d..a6413e4 100644
--- a/net/bridge/netfilter/ebt_mark_m.c
+++ b/net/bridge/netfilter/ebt_mark_m.c
@@ -47,16 +47,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_mark_m_init(void)
 {
 	return ebt_register_match(&filter_mark);
 }
 
-static void __exit fini(void)
+static void __exit ebt_mark_m_fini(void)
 {
 	ebt_unregister_match(&filter_mark);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_mark_m_init);
+module_exit(ebt_mark_m_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_pkttype.c b/net/bridge/netfilter/ebt_pkttype.c
index ecd3b42..4fffd70 100644
--- a/net/bridge/netfilter/ebt_pkttype.c
+++ b/net/bridge/netfilter/ebt_pkttype.c
@@ -44,16 +44,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_pkttype_init(void)
 {
 	return ebt_register_match(&filter_pkttype);
 }
 
-static void __exit fini(void)
+static void __exit ebt_pkttype_fini(void)
 {
 	ebt_unregister_match(&filter_pkttype);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_pkttype_init);
+module_exit(ebt_pkttype_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
index 1538b43..9f378ea 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -66,16 +66,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_redirect_init(void)
 {
 	return ebt_register_target(&redirect_target);
 }
 
-static void __exit fini(void)
+static void __exit ebt_redirect_fini(void)
 {
 	ebt_unregister_target(&redirect_target);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_redirect_init);
+module_exit(ebt_redirect_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
index 1529bdc..cbb33e2 100644
--- a/net/bridge/netfilter/ebt_snat.c
+++ b/net/bridge/netfilter/ebt_snat.c
@@ -61,16 +61,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_snat_init(void)
 {
 	return ebt_register_target(&snat);
 }
 
-static void __exit fini(void)
+static void __exit ebt_snat_fini(void)
 {
 	ebt_unregister_target(&snat);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_snat_init);
+module_exit(ebt_snat_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c
index 0248c67..a0bed82 100644
--- a/net/bridge/netfilter/ebt_stp.c
+++ b/net/bridge/netfilter/ebt_stp.c
@@ -180,16 +180,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_stp_init(void)
 {
 	return ebt_register_match(&filter_stp);
 }
 
-static void __exit fini(void)
+static void __exit ebt_stp_fini(void)
 {
 	ebt_unregister_match(&filter_stp);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_stp_init);
+module_exit(ebt_stp_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 802baf7..ee5a517 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -281,7 +281,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_ulog_init(void)
 {
 	int i, ret = 0;
 
@@ -316,7 +316,7 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit ebt_ulog_fini(void)
 {
 	ebt_ulog_buff_t *ub;
 	int i;
@@ -337,8 +337,8 @@
 	sock_release(ebtulognl->sk_socket);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_ulog_init);
+module_exit(ebt_ulog_fini);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
 MODULE_DESCRIPTION("ebtables userspace logging module for bridged Ethernet"
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
index db60d73..a2b4528 100644
--- a/net/bridge/netfilter/ebt_vlan.c
+++ b/net/bridge/netfilter/ebt_vlan.c
@@ -178,7 +178,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ebt_vlan_init(void)
 {
 	DEBUG_MSG("ebtables 802.1Q extension module v"
 		  MODULE_VERS "\n");
@@ -186,10 +186,10 @@
 	return ebt_register_match(&filter_vlan);
 }
 
-static void __exit fini(void)
+static void __exit ebt_vlan_fini(void)
 {
 	ebt_unregister_match(&filter_vlan);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebt_vlan_init);
+module_exit(ebt_vlan_fini);
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
index 1767c94..9a6e548 100644
--- a/net/bridge/netfilter/ebtable_broute.c
+++ b/net/bridge/netfilter/ebtable_broute.c
@@ -62,7 +62,7 @@
 	return 0; /* bridge it */
 }
 
-static int __init init(void)
+static int __init ebtable_broute_init(void)
 {
 	int ret;
 
@@ -74,13 +74,13 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit ebtable_broute_fini(void)
 {
 	br_should_route_hook = NULL;
 	synchronize_net();
 	ebt_unregister_table(&broute_table);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebtable_broute_init);
+module_exit(ebtable_broute_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index c18666e..3d5bd44 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -91,7 +91,7 @@
 	},
 };
 
-static int __init init(void)
+static int __init ebtable_filter_init(void)
 {
 	int i, j, ret;
 
@@ -109,7 +109,7 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit ebtable_filter_fini(void)
 {
 	int i;
 
@@ -118,6 +118,6 @@
 	ebt_unregister_table(&frame_filter);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebtable_filter_init);
+module_exit(ebtable_filter_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index 828cac2..04dd42e 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -98,7 +98,7 @@
 	},
 };
 
-static int __init init(void)
+static int __init ebtable_nat_init(void)
 {
 	int i, ret, j;
 
@@ -116,7 +116,7 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit ebtable_nat_fini(void)
 {
 	int i;
 
@@ -125,6 +125,6 @@
 	ebt_unregister_table(&frame_nat);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ebtable_nat_init);
+module_exit(ebtable_nat_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 9979533..01eae97 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1487,7 +1487,7 @@
 	.get		= do_ebt_get_ctl,
 };
 
-static int __init init(void)
+static int __init ebtables_init(void)
 {
 	int ret;
 
@@ -1501,7 +1501,7 @@
 	return 0;
 }
 
-static void __exit fini(void)
+static void __exit ebtables_fini(void)
 {
 	nf_unregister_sockopt(&ebt_sockopts);
 	printk(KERN_NOTICE "Ebtables v2.0 unregistered\n");
@@ -1516,6 +1516,6 @@
 EXPORT_SYMBOL(ebt_register_target);
 EXPORT_SYMBOL(ebt_unregister_target);
 EXPORT_SYMBOL(ebt_do_table);
-module_init(init);
-module_exit(fini);
+module_init(ebtables_init);
+module_exit(ebtables_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/core/sock.c b/net/core/sock.c
index e110b90..a96ea7d 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -187,6 +187,99 @@
 }
 
 
+int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+{
+	int err = 0;
+	int skb_len;
+
+	/* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
+	   number of warnings when compiling with -W --ANK
+	 */
+	if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
+	    (unsigned)sk->sk_rcvbuf) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	/* It would be deadlock, if sock_queue_rcv_skb is used
+	   with socket lock! We assume that users of this
+	   function are lock free.
+	*/
+	err = sk_filter(sk, skb, 1);
+	if (err)
+		goto out;
+
+	skb->dev = NULL;
+	skb_set_owner_r(skb, sk);
+
+	/* Cache the SKB length before we tack it onto the receive
+	 * queue.  Once it is added it no longer belongs to us and
+	 * may be freed by other threads of control pulling packets
+	 * from the queue.
+	 */
+	skb_len = skb->len;
+
+	skb_queue_tail(&sk->sk_receive_queue, skb);
+
+	if (!sock_flag(sk, SOCK_DEAD))
+		sk->sk_data_ready(sk, skb_len);
+out:
+	return err;
+}
+EXPORT_SYMBOL(sock_queue_rcv_skb);
+
+int sk_receive_skb(struct sock *sk, struct sk_buff *skb)
+{
+	int rc = NET_RX_SUCCESS;
+
+	if (sk_filter(sk, skb, 0))
+		goto discard_and_relse;
+
+	skb->dev = NULL;
+
+	bh_lock_sock(sk);
+	if (!sock_owned_by_user(sk))
+		rc = sk->sk_backlog_rcv(sk, skb);
+	else
+		sk_add_backlog(sk, skb);
+	bh_unlock_sock(sk);
+out:
+	sock_put(sk);
+	return rc;
+discard_and_relse:
+	kfree_skb(skb);
+	goto out;
+}
+EXPORT_SYMBOL(sk_receive_skb);
+
+struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie)
+{
+	struct dst_entry *dst = sk->sk_dst_cache;
+
+	if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
+		sk->sk_dst_cache = NULL;
+		dst_release(dst);
+		return NULL;
+	}
+
+	return dst;
+}
+EXPORT_SYMBOL(__sk_dst_check);
+
+struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie)
+{
+	struct dst_entry *dst = sk_dst_get(sk);
+
+	if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
+		sk_dst_reset(sk);
+		dst_release(dst);
+		return NULL;
+	}
+
+	return dst;
+}
+EXPORT_SYMBOL(sk_dst_check);
+
 /*
  *	This is meant for all protocols to use and covers goings on
  *	at the socket level. Everything here is generic.
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index 16a5a31..74133ec 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -133,7 +133,7 @@
 	.priority	= NF_DN_PRI_DNRTMSG,
 };
 
-static int __init init(void)
+static int __init dn_rtmsg_init(void)
 {
 	int rv = 0;
 
@@ -152,7 +152,7 @@
 	return rv;
 }
 
-static void __exit fini(void)
+static void __exit dn_rtmsg_fini(void)
 {
 	nf_unregister_hook(&dnrmg_ops);
 	sock_release(dnrmg->sk_socket);
@@ -164,6 +164,6 @@
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_DNRTMSG);
 
-module_init(init);
-module_exit(fini);
+module_init(dn_rtmsg_init);
+module_exit(dn_rtmsg_fini);
 
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index c792994..8682656 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -42,6 +42,7 @@
 #include <linux/spinlock.h>
 #include <linux/rcupdate.h>
 #include <linux/bitops.h>
+#include <linux/mutex.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -49,6 +50,7 @@
 static const struct proto_ops econet_ops;
 static struct hlist_head econet_sklist;
 static DEFINE_RWLOCK(econet_lock);
+static DEFINE_MUTEX(econet_mutex);
 
 /* Since there are only 256 possible network numbers (or fewer, depends
    how you count) it makes sense to use a simple lookup table. */
@@ -124,6 +126,8 @@
 
 	msg->msg_namelen = sizeof(struct sockaddr_ec);
 
+	mutex_lock(&econet_mutex);
+
 	/*
 	 *	Call the generic datagram receiver. This handles all sorts
 	 *	of horrible races and re-entrancy so we can forget about it
@@ -174,6 +178,7 @@
 out_free:
 	skb_free_datagram(sk, skb);
 out:
+	mutex_unlock(&econet_mutex);
 	return err;
 }
 
@@ -184,8 +189,8 @@
 static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
 	struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
-	struct sock *sk=sock->sk;
-	struct econet_sock *eo = ec_sk(sk);
+	struct sock *sk;
+	struct econet_sock *eo;
 	
 	/*
 	 *	Check legality
@@ -195,11 +200,18 @@
 	    sec->sec_family != AF_ECONET)
 		return -EINVAL;
 	
+	mutex_lock(&econet_mutex);
+
+	sk = sock->sk;
+	eo = ec_sk(sk);
+
 	eo->cb	    = sec->cb;
 	eo->port    = sec->port;
 	eo->station = sec->addr.station;
 	eo->net	    = sec->addr.net;
 
+	mutex_unlock(&econet_mutex);
+
 	return 0;
 }
 
@@ -284,6 +296,8 @@
 	 *	Get and verify the address. 
 	 */
 	 
+	mutex_lock(&econet_mutex);
+
 	if (saddr == NULL) {
 		struct econet_sock *eo = ec_sk(sk);
 
@@ -292,8 +306,10 @@
 		port	     = eo->port;
 		cb	     = eo->cb;
 	} else {
-		if (msg->msg_namelen < sizeof(struct sockaddr_ec)) 
+		if (msg->msg_namelen < sizeof(struct sockaddr_ec)) {
+			mutex_unlock(&econet_mutex);
 			return -EINVAL;
+		}
 		addr.station = saddr->addr.station;
 		addr.net = saddr->addr.net;
 		port = saddr->port;
@@ -304,19 +320,21 @@
 	dev = net2dev_map[addr.net];
 
 	/* If not directly reachable, use some default */
-	if (dev == NULL)
-	{
+	if (dev == NULL) {
 		dev = net2dev_map[0];
 		/* No interfaces at all? */
-		if (dev == NULL)
+		if (dev == NULL) {
+			mutex_unlock(&econet_mutex);
 			return -ENETDOWN;
+		}
 	}
 
-	if (len + 15 > dev->mtu)
+	if (len + 15 > dev->mtu) {
+		mutex_unlock(&econet_mutex);
 		return -EMSGSIZE;
+	}
 
-	if (dev->type == ARPHRD_ECONET)
-	{
+	if (dev->type == ARPHRD_ECONET) {
 		/* Real hardware Econet.  We're not worthy etc. */
 #ifdef CONFIG_ECONET_NATIVE
 		unsigned short proto = 0;
@@ -374,6 +392,7 @@
 		
 		dev_queue_xmit(skb);
 		dev_put(dev);
+		mutex_unlock(&econet_mutex);
 		return(len);
 
 	out_free:
@@ -384,14 +403,18 @@
 #else
 		err = -EPROTOTYPE;
 #endif
+		mutex_unlock(&econet_mutex);
+
 		return err;
 	}
 
 #ifdef CONFIG_ECONET_AUNUDP
 	/* AUN virtual Econet. */
 
-	if (udpsock == NULL)
+	if (udpsock == NULL) {
+		mutex_unlock(&econet_mutex);
 		return -ENETDOWN;		/* No socket - can't send */
+	}
 	
 	/* Make up a UDP datagram and hand it off to some higher intellect. */
 
@@ -438,8 +461,10 @@
 		void __user *base = msg->msg_iov[i].iov_base;
 		size_t len = msg->msg_iov[i].iov_len;
 		/* Check it now since we switch to KERNEL_DS later. */
-		if (!access_ok(VERIFY_READ, base, len))
+		if (!access_ok(VERIFY_READ, base, len)) {
+			mutex_unlock(&econet_mutex);
 			return -EFAULT;
+		}
 		iov[i+1].iov_base = base;
 		iov[i+1].iov_len = len;
 		size += len;
@@ -447,8 +472,11 @@
 
 	/* Get a skbuff (no data, just holds our cb information) */
 	if ((skb = sock_alloc_send_skb(sk, 0, 
-			     msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)
+				       msg->msg_flags & MSG_DONTWAIT,
+				       &err)) == NULL) {
+		mutex_unlock(&econet_mutex);
 		return err;
+	}
 
 	eb = (struct ec_cb *)&skb->cb;
 
@@ -475,6 +503,8 @@
 #else
 	err = -EPROTOTYPE;
 #endif
+	mutex_unlock(&econet_mutex);
+
 	return err;
 }
 
@@ -485,18 +515,25 @@
 static int econet_getname(struct socket *sock, struct sockaddr *uaddr,
 			  int *uaddr_len, int peer)
 {
-	struct sock *sk = sock->sk;
-	struct econet_sock *eo = ec_sk(sk);
+	struct sock *sk;
+	struct econet_sock *eo;
 	struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
 
 	if (peer)
 		return -EOPNOTSUPP;
 
+	mutex_lock(&econet_mutex);
+
+	sk = sock->sk;
+	eo = ec_sk(sk);
+
 	sec->sec_family	  = AF_ECONET;
 	sec->port	  = eo->port;
 	sec->addr.station = eo->station;
 	sec->addr.net	  = eo->net;
 
+	mutex_unlock(&econet_mutex);
+
 	*uaddr_len = sizeof(*sec);
 	return 0;
 }
@@ -522,10 +559,13 @@
 
 static int econet_release(struct socket *sock)
 {
-	struct sock *sk = sock->sk;
+	struct sock *sk;
 
+	mutex_lock(&econet_mutex);
+
+	sk = sock->sk;
 	if (!sk)
-		return 0;
+		goto out_unlock;
 
 	econet_remove_socket(&econet_sklist, sk);
 
@@ -549,10 +589,14 @@
 		sk->sk_timer.expires  = jiffies + HZ;
 		sk->sk_timer.function = econet_destroy_timer;
 		add_timer(&sk->sk_timer);
-		return 0;
+
+		goto out_unlock;
 	}
 
 	sk_free(sk);
+
+out_unlock:
+	mutex_unlock(&econet_mutex);
 	return 0;
 }
 
@@ -608,6 +652,7 @@
 	struct ec_device *edev;
 	struct net_device *dev;
 	struct sockaddr_ec *sec;
+	int err;
 
 	/*
 	 *	Fetch the caller's info block into kernel space
@@ -621,38 +666,35 @@
 
 	sec = (struct sockaddr_ec *)&ifr.ifr_addr;
 
-	switch (cmd)
-	{
+	mutex_lock(&econet_mutex);
+
+	err = 0;
+	switch (cmd) {
 	case SIOCSIFADDR:
 		edev = dev->ec_ptr;
-		if (edev == NULL)
-		{
+		if (edev == NULL) {
 			/* Magic up a new one. */
 			edev = kmalloc(sizeof(struct ec_device), GFP_KERNEL);
 			if (edev == NULL) {
-				printk("af_ec: memory squeeze.\n");
-				dev_put(dev);
-				return -ENOMEM;
+				err = -ENOMEM;
+				break;
 			}
 			memset(edev, 0, sizeof(struct ec_device));
 			dev->ec_ptr = edev;
-		}
-		else
+		} else
 			net2dev_map[edev->net] = NULL;
 		edev->station = sec->addr.station;
 		edev->net = sec->addr.net;
 		net2dev_map[sec->addr.net] = dev;
 		if (!net2dev_map[0])
 			net2dev_map[0] = dev;
-		dev_put(dev);
-		return 0;
+		break;
 
 	case SIOCGIFADDR:
 		edev = dev->ec_ptr;
-		if (edev == NULL)
-		{
-			dev_put(dev);
-			return -ENODEV;
+		if (edev == NULL) {
+			err = -ENODEV;
+			break;
 		}
 		memset(sec, 0, sizeof(struct sockaddr_ec));
 		sec->addr.station = edev->station;
@@ -660,12 +702,19 @@
 		sec->sec_family = AF_ECONET;
 		dev_put(dev);
 		if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
-			return -EFAULT;
-		return 0;
+			err = -EFAULT;
+		break;
+
+	default:
+		err = -EINVAL;
+		break;
 	}
 
+	mutex_unlock(&econet_mutex);
+
 	dev_put(dev);
-	return -EINVAL;
+
+	return err;
 }
 
 /*
@@ -699,7 +748,7 @@
 	.owner	=	THIS_MODULE,
 };
 
-static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
+static const struct proto_ops econet_ops = {
 	.family =	PF_ECONET,
 	.owner =	THIS_MODULE,
 	.release =	econet_release,
@@ -720,9 +769,6 @@
 	.sendpage =	sock_no_sendpage,
 };
 
-#include <linux/smp_lock.h>
-SOCKOPS_WRAP(econet, PF_ECONET);
-
 #if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE)
 /*
  *	Find the listening socket, if any, for the given data.
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index af7f9bb..b885fd1 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -42,7 +42,7 @@
 };
 
 #define MAX_CUSTOM_LEN 64
-static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
+static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
 					   char *start, char *stop,
 					   struct ieee80211_network *network)
 {
@@ -274,7 +274,7 @@
 
 		if (ieee->scan_age == 0 ||
 		    time_after(network->last_scanned + ieee->scan_age, jiffies))
-			ev = ipw2100_translate_scan(ieee, ev, stop, network);
+			ev = ieee80211_translate_scan(ieee, ev, stop, network);
 		else
 			IEEE80211_DEBUG_SCAN("Not showing network '%s ("
 					     MAC_FMT ")' due to age (%dms).\n",
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index 6f99f78..60f06a31 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -183,16 +183,21 @@
 	 */
 	if (mac->txrates_change)
 		oldrates = mac->txrates;
-	if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
-		mac->txrates.default_rate = IEEE80211_OFDM_RATE_54MB;
-		change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
-		mac->txrates.default_fallback = IEEE80211_OFDM_RATE_24MB;
-		change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
-	} else if (ieee->modulation & IEEE80211_CCK_MODULATION) {
+	/* FIXME: We don't correctly handle backing down to lower
+	   rates, so 801.11g devices start off at 11M for now. People
+	   can manually change it if they really need to, but 11M is
+	   more reliable. Note similar logic in
+	   ieee80211softmac_wx_set_rate() */	 
+	if (ieee->modulation & IEEE80211_CCK_MODULATION) {
 		mac->txrates.default_rate = IEEE80211_CCK_RATE_11MB;
 		change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
 		mac->txrates.default_fallback = IEEE80211_CCK_RATE_5MB;
 		change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+	} else if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
+		mac->txrates.default_rate = IEEE80211_OFDM_RATE_54MB;
+		change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+		mac->txrates.default_fallback = IEEE80211_OFDM_RATE_24MB;
+		change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
 	} else
 		assert(0);
 	if (mac->txrates_change)
diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h
index 9ba7dbd..65d9816 100644
--- a/net/ieee80211/softmac/ieee80211softmac_priv.h
+++ b/net/ieee80211/softmac/ieee80211softmac_priv.h
@@ -167,7 +167,7 @@
 		) || ieee80211softmac_scan_handlers_check_self(sm);
 }
 
-#define IEEE80211SOFTMAC_PROBE_DELAY		HZ/2
+#define IEEE80211SOFTMAC_PROBE_DELAY		HZ/50
 #define IEEE80211SOFTMAC_WORKQUEUE_NAME_LEN	(17 + IFNAMSIZ)
 
 struct ieee80211softmac_network {
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index e1a9bc6..b559aa9 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -135,11 +135,15 @@
 	int err = -EINVAL;
 
 	if (in_rate == -1) {
-		/* automatic detect */
-		if (ieee->modulation & IEEE80211_OFDM_MODULATION)
-			in_rate = 54000000;
-		else
+		/* FIXME: We don't correctly handle backing down to lower
+		   rates, so 801.11g devices start off at 11M for now. People
+		   can manually change it if they really need to, but 11M is
+		   more reliable. Note similar logic in
+		   ieee80211softmac_wx_set_rate() */	 
+		if (ieee->modulation & IEEE80211_CCK_MODULATION)
 			in_rate = 11000000;
+		else
+			in_rate = 54000000;
 	}
 
 	switch (in_rate) {
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 011cca7..e40f753 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -235,6 +235,7 @@
 #   bool '    IP: ARP support' CONFIG_IP_PNP_ARP		
 config NET_IPIP
 	tristate "IP: tunneling"
+	select INET_TUNNEL
 	---help---
 	  Tunneling means encapsulating data of one protocol type within
 	  another protocol and sending it over a channel that understands the
@@ -395,7 +396,7 @@
 config INET_IPCOMP
 	tristate "IP: IPComp transformation"
 	select XFRM
-	select INET_TUNNEL
+	select INET_XFRM_TUNNEL
 	select CRYPTO
 	select CRYPTO_DEFLATE
 	---help---
@@ -404,14 +405,14 @@
 	  
 	  If unsure, say Y.
 
+config INET_XFRM_TUNNEL
+	tristate
+	select INET_TUNNEL
+	default n
+
 config INET_TUNNEL
-	tristate "IP: tunnel transformation"
-	select XFRM
-	---help---
-	  Support for generic IP tunnel transformation, which is required by
-	  the IP tunneling module as well as tunnel mode IPComp.
-	  
-	  If unsure, say Y.
+	tristate
+	default n
 
 config INET_DIAG
 	tristate "INET: socket monitoring interface"
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 35e5f59..9ef50a0 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -22,7 +22,8 @@
 obj-$(CONFIG_INET_AH) += ah4.o
 obj-$(CONFIG_INET_ESP) += esp4.o
 obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
-obj-$(CONFIG_INET_TUNNEL) += xfrm4_tunnel.o 
+obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o
+obj-$(CONFIG_INET_TUNNEL) += tunnel4.o
 obj-$(CONFIG_IP_PNP) += ipconfig.o
 obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
 obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 03d1374..eef07b0 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -114,7 +114,6 @@
 #include <net/sock.h>
 #include <net/ip.h>
 #include <net/icmp.h>
-#include <net/protocol.h>
 #include <net/ipip.h>
 #include <net/inet_ecn.h>
 #include <net/xfrm.h>
@@ -274,7 +273,7 @@
 	dev_put(dev);
 }
 
-static void ipip_err(struct sk_buff *skb, u32 info)
+static int ipip_err(struct sk_buff *skb, u32 info)
 {
 #ifndef I_WISH_WORLD_WERE_PERFECT
 
@@ -286,21 +285,22 @@
 	int type = skb->h.icmph->type;
 	int code = skb->h.icmph->code;
 	struct ip_tunnel *t;
+	int err;
 
 	switch (type) {
 	default:
 	case ICMP_PARAMETERPROB:
-		return;
+		return 0;
 
 	case ICMP_DEST_UNREACH:
 		switch (code) {
 		case ICMP_SR_FAILED:
 		case ICMP_PORT_UNREACH:
 			/* Impossible event. */
-			return;
+			return 0;
 		case ICMP_FRAG_NEEDED:
 			/* Soft state for pmtu is maintained by IP core. */
-			return;
+			return 0;
 		default:
 			/* All others are translated to HOST_UNREACH.
 			   rfc2003 contains "deep thoughts" about NET_UNREACH,
@@ -311,14 +311,18 @@
 		break;
 	case ICMP_TIME_EXCEEDED:
 		if (code != ICMP_EXC_TTL)
-			return;
+			return 0;
 		break;
 	}
 
+	err = -ENOENT;
+
 	read_lock(&ipip_lock);
 	t = ipip_tunnel_lookup(iph->daddr, iph->saddr);
 	if (t == NULL || t->parms.iph.daddr == 0)
 		goto out;
+
+	err = 0;
 	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
 		goto out;
 
@@ -329,7 +333,7 @@
 	t->err_time = jiffies;
 out:
 	read_unlock(&ipip_lock);
-	return;
+	return err;
 #else
 	struct iphdr *iph = (struct iphdr*)dp;
 	int hlen = iph->ihl<<2;
@@ -344,15 +348,15 @@
 	struct rtable *rt;
 
 	if (len < hlen + sizeof(struct iphdr))
-		return;
+		return 0;
 	eiph = (struct iphdr*)(dp + hlen);
 
 	switch (type) {
 	default:
-		return;
+		return 0;
 	case ICMP_PARAMETERPROB:
 		if (skb->h.icmph->un.gateway < hlen)
-			return;
+			return 0;
 
 		/* So... This guy found something strange INSIDE encapsulated
 		   packet. Well, he is fool, but what can we do ?
@@ -366,16 +370,16 @@
 		case ICMP_SR_FAILED:
 		case ICMP_PORT_UNREACH:
 			/* Impossible event. */
-			return;
+			return 0;
 		case ICMP_FRAG_NEEDED:
 			/* And it is the only really necessary thing :-) */
 			rel_info = ntohs(skb->h.icmph->un.frag.mtu);
 			if (rel_info < hlen+68)
-				return;
+				return 0;
 			rel_info -= hlen;
 			/* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */
 			if (rel_info > ntohs(eiph->tot_len))
-				return;
+				return 0;
 			break;
 		default:
 			/* All others are translated to HOST_UNREACH.
@@ -389,14 +393,14 @@
 		break;
 	case ICMP_TIME_EXCEEDED:
 		if (code != ICMP_EXC_TTL)
-			return;
+			return 0;
 		break;
 	}
 
 	/* Prepare fake skb to feed it to icmp_send */
 	skb2 = skb_clone(skb, GFP_ATOMIC);
 	if (skb2 == NULL)
-		return;
+		return 0;
 	dst_release(skb2->dst);
 	skb2->dst = NULL;
 	skb_pull(skb2, skb->data - (u8*)eiph);
@@ -409,7 +413,7 @@
 	fl.proto = IPPROTO_IPIP;
 	if (ip_route_output_key(&rt, &key)) {
 		kfree_skb(skb2);
-		return;
+		return 0;
 	}
 	skb2->dev = rt->u.dst.dev;
 
@@ -424,14 +428,14 @@
 		    rt->u.dst.dev->type != ARPHRD_TUNNEL) {
 			ip_rt_put(rt);
 			kfree_skb(skb2);
-			return;
+			return 0;
 		}
 	} else {
 		ip_rt_put(rt);
 		if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) ||
 		    skb2->dst->dev->type != ARPHRD_TUNNEL) {
 			kfree_skb(skb2);
-			return;
+			return 0;
 		}
 	}
 
@@ -439,7 +443,7 @@
 	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
 		if (rel_info > dst_mtu(skb2->dst)) {
 			kfree_skb(skb2);
-			return;
+			return 0;
 		}
 		skb2->dst->ops->update_pmtu(skb2->dst, rel_info);
 		rel_info = htonl(rel_info);
@@ -453,7 +457,7 @@
 
 	icmp_send(skb2, rel_type, rel_code, rel_info);
 	kfree_skb(skb2);
-	return;
+	return 0;
 #endif
 }
 
@@ -855,39 +859,12 @@
 	return 0;
 }
 
-#ifdef CONFIG_INET_TUNNEL
 static struct xfrm_tunnel ipip_handler = {
 	.handler	=	ipip_rcv,
 	.err_handler	=	ipip_err,
+	.priority	=	1,
 };
 
-static inline int ipip_register(void)
-{
-	return xfrm4_tunnel_register(&ipip_handler);
-}
-
-static inline int ipip_unregister(void)
-{
-	return xfrm4_tunnel_deregister(&ipip_handler);
-}
-#else
-static struct net_protocol ipip_protocol = {
-	.handler	=	ipip_rcv,
-	.err_handler	=	ipip_err,
-	.no_policy	=	1,
-};
-
-static inline int ipip_register(void)
-{
-	return inet_add_protocol(&ipip_protocol, IPPROTO_IPIP);
-}
-
-static inline int ipip_unregister(void)
-{
-	return inet_del_protocol(&ipip_protocol, IPPROTO_IPIP);
-}
-#endif
-
 static char banner[] __initdata =
 	KERN_INFO "IPv4 over IPv4 tunneling driver\n";
 
@@ -897,7 +874,7 @@
 
 	printk(banner);
 
-	if (ipip_register() < 0) {
+	if (xfrm4_tunnel_register(&ipip_handler)) {
 		printk(KERN_INFO "ipip init: can't register tunnel\n");
 		return -EAGAIN;
 	}
@@ -919,7 +896,7 @@
  err2:
 	free_netdev(ipip_fb_tunnel_dev);
  err1:
-	ipip_unregister();
+	xfrm4_tunnel_deregister(&ipip_handler);
 	goto out;
 }
 
@@ -939,7 +916,7 @@
 
 static void __exit ipip_fini(void)
 {
-	if (ipip_unregister() < 0)
+	if (xfrm4_tunnel_deregister(&ipip_handler))
 		printk(KERN_INFO "ipip close: can't deregister tunnel\n");
 
 	rtnl_lock();
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index ed42cdc..b5ad9ac 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -167,15 +167,15 @@
 	.reroute	= queue_reroute,
 };
 
-static int init(void)
+static int ipv4_netfilter_init(void)
 {
 	return nf_register_queue_rerouter(PF_INET, &ip_reroute);
 }
 
-static void fini(void)
+static void ipv4_netfilter_fini(void)
 {
 	nf_unregister_queue_rerouter(PF_INET);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipv4_netfilter_init);
+module_exit(ipv4_netfilter_fini);
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index ff0c594..a44a5d7 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1166,7 +1166,7 @@
 	.get		= do_arpt_get_ctl,
 };
 
-static int __init init(void)
+static int __init arp_tables_init(void)
 {
 	int ret;
 
@@ -1187,7 +1187,7 @@
 	return 0;
 }
 
-static void __exit fini(void)
+static void __exit arp_tables_fini(void)
 {
 	nf_unregister_sockopt(&arpt_sockopts);
 	xt_proto_fini(NF_ARP);
@@ -1197,5 +1197,5 @@
 EXPORT_SYMBOL(arpt_unregister_table);
 EXPORT_SYMBOL(arpt_do_table);
 
-module_init(init);
-module_exit(fini);
+module_init(arp_tables_init);
+module_exit(arp_tables_fini);
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index 0f2a953..a58325c 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -89,7 +89,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init arpt_mangle_init(void)
 {
 	if (arpt_register_target(&arpt_mangle_reg))
 		return -EINVAL;
@@ -97,10 +97,10 @@
 	return 0;
 }
 
-static void __exit fini(void)
+static void __exit arpt_mangle_fini(void)
 {
 	arpt_unregister_target(&arpt_mangle_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(arpt_mangle_init);
+module_exit(arpt_mangle_fini);
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index f6ab45f..d0d379c 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -179,7 +179,7 @@
 	},
 };
 
-static int __init init(void)
+static int __init arptable_filter_init(void)
 {
 	int ret, i;
 
@@ -201,7 +201,7 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit arptable_filter_fini(void)
 {
 	unsigned int i;
 
@@ -211,5 +211,5 @@
 	arpt_unregister_table(&packet_filter);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(arptable_filter_init);
+module_exit(arptable_filter_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index 84e4f79..a604b1c 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -153,13 +153,13 @@
 	},
 };
 
-static void __exit fini(void)
+static void __exit ip_conntrack_amanda_fini(void)
 {
 	ip_conntrack_helper_unregister(&amanda_helper);
 	kfree(amanda_buffer);
 }
 
-static int __init init(void)
+static int __init ip_conntrack_amanda_init(void)
 {
 	int ret;
 
@@ -177,5 +177,5 @@
 
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_amanda_init);
+module_exit(ip_conntrack_amanda_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index e627e58..3e542bf 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -453,7 +453,7 @@
 static char ftp_names[MAX_PORTS][sizeof("ftp-65535")];
 
 /* Not __exit: called from init() */
-static void fini(void)
+static void ip_conntrack_ftp_fini(void)
 {
 	int i;
 	for (i = 0; i < ports_c; i++) {
@@ -465,7 +465,7 @@
 	kfree(ftp_buffer);
 }
 
-static int __init init(void)
+static int __init ip_conntrack_ftp_init(void)
 {
 	int i, ret;
 	char *tmpname;
@@ -499,12 +499,12 @@
 		ret = ip_conntrack_helper_register(&ftp[i]);
 
 		if (ret) {
-			fini();
+			ip_conntrack_ftp_fini();
 			return ret;
 		}
 	}
 	return 0;
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_ftp_init);
+module_exit(ip_conntrack_ftp_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
index d716bba..7d3ba43 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
@@ -766,7 +766,7 @@
 extern int __init ip_ct_proto_gre_init(void);
 
 /* ip_conntrack_pptp initialization */
-static int __init init(void)
+static int __init ip_conntrack_helper_pptp_init(void)
 {
 	int retcode;
  
@@ -786,15 +786,15 @@
 	return 0;
 }
 
-static void __exit fini(void)
+static void __exit ip_conntrack_helper_pptp_fini(void)
 {
 	ip_conntrack_helper_unregister(&pptp);
 	ip_ct_proto_gre_fini();
 	printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_helper_pptp_init);
+module_exit(ip_conntrack_helper_pptp_fini);
 
 EXPORT_SYMBOL(ip_nat_pptp_hook_outbound);
 EXPORT_SYMBOL(ip_nat_pptp_hook_inbound);
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index c51a2cf..a2ac5ce 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -242,9 +242,9 @@
 static struct ip_conntrack_helper irc_helpers[MAX_PORTS];
 static char irc_names[MAX_PORTS][sizeof("irc-65535")];
 
-static void fini(void);
+static void ip_conntrack_irc_fini(void);
 
-static int __init init(void)
+static int __init ip_conntrack_irc_init(void)
 {
 	int i, ret;
 	struct ip_conntrack_helper *hlpr;
@@ -288,7 +288,7 @@
 		if (ret) {
 			printk("ip_conntrack_irc: ERROR registering port %d\n",
 				ports[i]);
-			fini();
+			ip_conntrack_irc_fini();
 			return -EBUSY;
 		}
 	}
@@ -297,7 +297,7 @@
 
 /* This function is intentionally _NOT_ defined as __exit, because 
  * it is needed by the init function */
-static void fini(void)
+static void ip_conntrack_irc_fini(void)
 {
 	int i;
 	for (i = 0; i < ports_c; i++) {
@@ -308,5 +308,5 @@
 	kfree(irc_buffer);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_irc_init);
+module_exit(ip_conntrack_irc_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
index 4e68e16..a566a81 100644
--- a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
+++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
@@ -127,16 +127,16 @@
 	.help			= help,
 };
 
-static int __init init(void)
+static int __init ip_conntrack_netbios_ns_init(void)
 {
 	helper.timeout = timeout;
 	return ip_conntrack_helper_register(&helper);
 }
 
-static void __exit fini(void)
+static void __exit ip_conntrack_netbios_ns_fini(void)
 {
 	ip_conntrack_helper_unregister(&helper);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_netbios_ns_init);
+module_exit(ip_conntrack_netbios_ns_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
index be602e8..5259abd 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
@@ -609,7 +609,7 @@
 static struct ctl_table_header *ip_ct_sysctl_header;
 #endif
 
-static int __init init(void)
+static int __init ip_conntrack_proto_sctp_init(void)
 {
 	int ret;
 
@@ -640,7 +640,7 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit ip_conntrack_proto_sctp_fini(void)
 {
 	ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
 #ifdef CONFIG_SYSCTL
@@ -649,8 +649,8 @@
 	DEBUGP("SCTP conntrack module unloaded\n");
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_proto_sctp_init);
+module_exit(ip_conntrack_proto_sctp_fini);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Kiran Kumar Immidi");
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 833fcb4..5207602 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -929,18 +929,18 @@
 	ip_ct_iterate_cleanup(kill_proto, &proto->proto);
 }
 
-static int __init init(void)
+static int __init ip_conntrack_standalone_init(void)
 {
 	return init_or_cleanup(1);
 }
 
-static void __exit fini(void)
+static void __exit ip_conntrack_standalone_fini(void)
 {
 	init_or_cleanup(0);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_standalone_init);
+module_exit(ip_conntrack_standalone_fini);
 
 /* Some modules need us, but don't depend directly on any symbol.
    They should call this. */
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
index 4ba4463..7e33d3b 100644
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_tftp.c
@@ -103,7 +103,7 @@
 static struct ip_conntrack_helper tftp[MAX_PORTS];
 static char tftp_names[MAX_PORTS][sizeof("tftp-65535")];
 
-static void fini(void)
+static void ip_conntrack_tftp_fini(void)
 {
 	int i;
 
@@ -114,7 +114,7 @@
 	} 
 }
 
-static int __init init(void)
+static int __init ip_conntrack_tftp_init(void)
 {
 	int i, ret;
 	char *tmpname;
@@ -148,12 +148,12 @@
 		if (ret) {
 			printk("ERROR registering helper for port %d\n",
 				ports[i]);
-			fini();
+			ip_conntrack_tftp_fini();
 			return(ret);
 		}
 	}
 	return(0);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_tftp_init);
+module_exit(ip_conntrack_tftp_fini);
diff --git a/net/ipv4/netfilter/ip_nat_amanda.c b/net/ipv4/netfilter/ip_nat_amanda.c
index 706c807..3a88871 100644
--- a/net/ipv4/netfilter/ip_nat_amanda.c
+++ b/net/ipv4/netfilter/ip_nat_amanda.c
@@ -68,19 +68,19 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit ip_nat_amanda_fini(void)
 {
 	ip_nat_amanda_hook = NULL;
 	/* Make sure noone calls it, meanwhile. */
 	synchronize_net();
 }
 
-static int __init init(void)
+static int __init ip_nat_amanda_init(void)
 {
 	BUG_ON(ip_nat_amanda_hook);
 	ip_nat_amanda_hook = help;
 	return 0;
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_amanda_init);
+module_exit(ip_nat_amanda_fini);
diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c
index b8daab3..3328fc5 100644
--- a/net/ipv4/netfilter/ip_nat_ftp.c
+++ b/net/ipv4/netfilter/ip_nat_ftp.c
@@ -154,14 +154,14 @@
 	return NF_ACCEPT;
 }
 
-static void __exit fini(void)
+static void __exit ip_nat_ftp_fini(void)
 {
 	ip_nat_ftp_hook = NULL;
 	/* Make sure noone calls it, meanwhile. */
 	synchronize_net();
 }
 
-static int __init init(void)
+static int __init ip_nat_ftp_init(void)
 {
 	BUG_ON(ip_nat_ftp_hook);
 	ip_nat_ftp_hook = ip_nat_ftp;
@@ -177,5 +177,5 @@
 }
 module_param_call(ports, warn_set, NULL, NULL, 0);
 
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_ftp_init);
+module_exit(ip_nat_ftp_fini);
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
index b9c016c..f397772 100644
--- a/net/ipv4/netfilter/ip_nat_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c
@@ -370,7 +370,7 @@
 extern int __init ip_nat_proto_gre_init(void);
 extern void __exit ip_nat_proto_gre_fini(void);
 
-static int __init init(void)
+static int __init ip_nat_helper_pptp_init(void)
 {
 	int ret;
 
@@ -396,7 +396,7 @@
 	return 0;
 }
 
-static void __exit fini(void)
+static void __exit ip_nat_helper_pptp_fini(void)
 {
 	DEBUGP("cleanup_module\n" );
 
@@ -412,5 +412,5 @@
 	printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_helper_pptp_init);
+module_exit(ip_nat_helper_pptp_fini);
diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c
index 461c833..a767123 100644
--- a/net/ipv4/netfilter/ip_nat_irc.c
+++ b/net/ipv4/netfilter/ip_nat_irc.c
@@ -96,14 +96,14 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit ip_nat_irc_fini(void)
 {
 	ip_nat_irc_hook = NULL;
 	/* Make sure noone calls it, meanwhile. */
 	synchronize_net();
 }
 
-static int __init init(void)
+static int __init ip_nat_irc_init(void)
 {
 	BUG_ON(ip_nat_irc_hook);
 	ip_nat_irc_hook = help;
@@ -119,5 +119,5 @@
 }
 module_param_call(ports, warn_set, NULL, NULL, 0);
 
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_irc_init);
+module_exit(ip_nat_irc_fini);
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index f029da2..c622538 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c
@@ -1324,7 +1324,7 @@
  *
  *****************************************************************************/
  
-static int __init init(void)
+static int __init ip_nat_snmp_basic_init(void)
 {
 	int ret = 0;
 
@@ -1339,13 +1339,13 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit ip_nat_snmp_basic_fini(void)
 {
 	ip_conntrack_helper_unregister(&snmp_helper);
 	ip_conntrack_helper_unregister(&snmp_trap_helper);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_snmp_basic_init);
+module_exit(ip_nat_snmp_basic_fini);
 
 module_param(debug, bool, 0600);
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 380aef3..3505b0d 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -425,17 +425,17 @@
 	return ret;
 }
 
-static int __init init(void)
+static int __init ip_nat_standalone_init(void)
 {
 	return init_or_cleanup(1);
 }
 
-static void __exit fini(void)
+static void __exit ip_nat_standalone_fini(void)
 {
 	init_or_cleanup(0);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_standalone_init);
+module_exit(ip_nat_standalone_fini);
 
 MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ip_nat_tftp.c b/net/ipv4/netfilter/ip_nat_tftp.c
index 43c3bd7..94a7801 100644
--- a/net/ipv4/netfilter/ip_nat_tftp.c
+++ b/net/ipv4/netfilter/ip_nat_tftp.c
@@ -53,19 +53,19 @@
 	return NF_ACCEPT;
 }
 
-static void __exit fini(void)
+static void __exit ip_nat_tftp_fini(void)
 {
 	ip_nat_tftp_hook = NULL;
 	/* Make sure noone calls it, meanwhile. */
 	synchronize_net();
 }
 
-static int __init init(void)
+static int __init ip_nat_tftp_init(void)
 {
 	BUG_ON(ip_nat_tftp_hook);
 	ip_nat_tftp_hook = help;
 	return 0;
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip_nat_tftp_init);
+module_exit(ip_nat_tftp_fini);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 1655866..896a244 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -717,13 +717,13 @@
 	return status;
 }
 
-static int __init init(void)
+static int __init ip_queue_init(void)
 {
 	
 	return init_or_cleanup(1);
 }
 
-static void __exit fini(void)
+static void __exit ip_queue_fini(void)
 {
 	init_or_cleanup(0);
 }
@@ -732,5 +732,5 @@
 MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
 MODULE_LICENSE("GPL");
 
-module_init(init);
-module_exit(fini);
+module_init(ip_queue_init);
+module_exit(ip_queue_fini);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index a7b194c..460fd90 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1364,7 +1364,7 @@
 	.checkentry	= icmp_checkentry,
 };
 
-static int __init init(void)
+static int __init ip_tables_init(void)
 {
 	int ret;
 
@@ -1386,7 +1386,7 @@
 	return 0;
 }
 
-static void __exit fini(void)
+static void __exit ip_tables_fini(void)
 {
 	nf_unregister_sockopt(&ipt_sockopts);
 
@@ -1400,5 +1400,5 @@
 EXPORT_SYMBOL(ipt_register_table);
 EXPORT_SYMBOL(ipt_unregister_table);
 EXPORT_SYMBOL(ipt_do_table);
-module_init(init);
-module_exit(fini);
+module_init(ip_tables_init);
+module_exit(ip_tables_fini);
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 61e11ed..e4768a3 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -770,15 +770,15 @@
 	return -EINVAL;
 }
 
-static int __init init(void)
+static int __init ipt_clusterip_init(void)
 {
 	return init_or_cleanup(0);
 }
 
-static void __exit fini(void)
+static void __exit ipt_clusterip_fini(void)
 {
 	init_or_cleanup(1);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_clusterip_init);
+module_exit(ipt_clusterip_fini);
diff --git a/net/ipv4/netfilter/ipt_DSCP.c b/net/ipv4/netfilter/ipt_DSCP.c
index cfb0b90..c8e9712 100644
--- a/net/ipv4/netfilter/ipt_DSCP.c
+++ b/net/ipv4/netfilter/ipt_DSCP.c
@@ -82,15 +82,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_dscp_init(void)
 {
 	return ipt_register_target(&ipt_dscp_reg);
 }
 
-static void __exit fini(void)
+static void __exit ipt_dscp_fini(void)
 {
 	ipt_unregister_target(&ipt_dscp_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_dscp_init);
+module_exit(ipt_dscp_fini);
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index b9b80f9..4adf5c9 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -151,15 +151,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_ecn_init(void)
 {
 	return ipt_register_target(&ipt_ecn_reg);
 }
 
-static void __exit fini(void)
+static void __exit ipt_ecn_fini(void)
 {
 	ipt_unregister_target(&ipt_ecn_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_ecn_init);
+module_exit(ipt_ecn_fini);
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 750d322..39fd4c2 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -471,7 +471,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_log_init(void)
 {
 	if (ipt_register_target(&ipt_log_reg))
 		return -EINVAL;
@@ -485,11 +485,11 @@
 	return 0;
 }
 
-static void __exit fini(void)
+static void __exit ipt_log_fini(void)
 {
 	nf_log_unregister_logger(&ipt_log_logger);
 	ipt_unregister_target(&ipt_log_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_log_init);
+module_exit(ipt_log_fini);
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index e0c321c..8b3e7f9 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -175,7 +175,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_masquerade_init(void)
 {
 	int ret;
 
@@ -191,12 +191,12 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit ipt_masquerade_fini(void)
 {
 	ipt_unregister_target(&masquerade);
 	unregister_netdevice_notifier(&masq_dev_notifier);
 	unregister_inetaddr_notifier(&masq_inet_notifier);	
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_masquerade_init);
+module_exit(ipt_masquerade_fini);
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index fba181c..2fcf107 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -98,15 +98,15 @@
     	.me 		= THIS_MODULE 
 };
 
-static int __init init(void)
+static int __init ipt_netmap_init(void)
 {
 	return ipt_register_target(&target_module);
 }
 
-static void __exit fini(void)
+static void __exit ipt_netmap_fini(void)
 {
 	ipt_unregister_target(&target_module);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_netmap_init);
+module_exit(ipt_netmap_fini);
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index be3da7c..f290463 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -112,15 +112,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_redirect_init(void)
 {
 	return ipt_register_target(&redirect_reg);
 }
 
-static void __exit fini(void)
+static void __exit ipt_redirect_fini(void)
 {
 	ipt_unregister_target(&redirect_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_redirect_init);
+module_exit(ipt_redirect_fini);
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 9d3b357..4269a54 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -313,15 +313,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_reject_init(void)
 {
 	return ipt_register_target(&ipt_reject_reg);
 }
 
-static void __exit fini(void)
+static void __exit ipt_reject_fini(void)
 {
 	ipt_unregister_target(&ipt_reject_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_reject_init);
+module_exit(ipt_reject_fini);
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index 7e2ebc9..7169b09 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -189,16 +189,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_same_init(void)
 {
 	return ipt_register_target(&same_reg);
 }
 
-static void __exit fini(void)
+static void __exit ipt_same_fini(void)
 {
 	ipt_unregister_target(&same_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_same_init);
+module_exit(ipt_same_fini);
 
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
index c4fc50e..ef2fe5b 100644
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -243,15 +243,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_tcpmss_init(void)
 {
 	return ipt_register_target(&ipt_tcpmss_reg);
 }
 
-static void __exit fini(void)
+static void __exit ipt_tcpmss_fini(void)
 {
 	ipt_unregister_target(&ipt_tcpmss_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_tcpmss_init);
+module_exit(ipt_tcpmss_fini);
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 9aa7817..1c7a5ca 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -81,15 +81,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_tos_init(void)
 {
 	return ipt_register_target(&ipt_tos_reg);
 }
 
-static void __exit fini(void)
+static void __exit ipt_tos_fini(void)
 {
 	ipt_unregister_target(&ipt_tos_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_tos_init);
+module_exit(ipt_tos_fini);
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index 5009a00..f48892a 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -94,15 +94,15 @@
 	.me 		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_ttl_init(void)
 {
 	return ipt_register_target(&ipt_TTL);
 }
 
-static void __exit fini(void)
+static void __exit ipt_ttl_fini(void)
 {
 	ipt_unregister_target(&ipt_TTL);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_ttl_init);
+module_exit(ipt_ttl_fini);
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index a82a32e..c84cc03 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -374,7 +374,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_ulog_init(void)
 {
 	int i;
 
@@ -407,7 +407,7 @@
 	return 0;
 }
 
-static void __exit fini(void)
+static void __exit ipt_ulog_fini(void)
 {
 	ulog_buff_t *ub;
 	int i;
@@ -435,5 +435,5 @@
 
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_ulog_init);
+module_exit(ipt_ulog_fini);
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index 5fdf85d..893dae2 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -51,15 +51,15 @@
 	.me		= THIS_MODULE
 };
 
-static int __init init(void)
+static int __init ipt_addrtype_init(void)
 {
 	return ipt_register_match(&addrtype_match);
 }
 
-static void __exit fini(void)
+static void __exit ipt_addrtype_fini(void)
 {
 	ipt_unregister_match(&addrtype_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_addrtype_init);
+module_exit(ipt_addrtype_fini);
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
index 35a21fb..2927135 100644
--- a/net/ipv4/netfilter/ipt_ah.c
+++ b/net/ipv4/netfilter/ipt_ah.c
@@ -96,15 +96,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_ah_init(void)
 {
 	return ipt_register_match(&ah_match);
 }
 
-static void __exit cleanup(void)
+static void __exit ipt_ah_fini(void)
 {
 	ipt_unregister_match(&ah_match);
 }
 
-module_init(init);
-module_exit(cleanup);
+module_init(ipt_ah_init);
+module_exit(ipt_ah_fini);
diff --git a/net/ipv4/netfilter/ipt_dscp.c b/net/ipv4/netfilter/ipt_dscp.c
index 11963c3..4717759 100644
--- a/net/ipv4/netfilter/ipt_dscp.c
+++ b/net/ipv4/netfilter/ipt_dscp.c
@@ -39,16 +39,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_dscp_init(void)
 {
 	return ipt_register_match(&dscp_match);
 }
 
-static void __exit fini(void)
+static void __exit ipt_dscp_fini(void)
 {
 	ipt_unregister_match(&dscp_match);
 
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_dscp_init);
+module_exit(ipt_dscp_fini);
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
index d7e29f6..b282504 100644
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -118,15 +118,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_ecn_init(void)
 {
 	return ipt_register_match(&ecn_match);
 }
 
-static void __exit fini(void)
+static void __exit ipt_ecn_fini(void)
 {
 	ipt_unregister_match(&ecn_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_ecn_init);
+module_exit(ipt_ecn_fini);
diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/ipv4/netfilter/ipt_esp.c
index af0d5ec..3840b41 100644
--- a/net/ipv4/netfilter/ipt_esp.c
+++ b/net/ipv4/netfilter/ipt_esp.c
@@ -97,15 +97,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_esp_init(void)
 {
 	return ipt_register_match(&esp_match);
 }
 
-static void __exit cleanup(void)
+static void __exit ipt_esp_fini(void)
 {
 	ipt_unregister_match(&esp_match);
 }
 
-module_init(init);
-module_exit(cleanup);
+module_init(ipt_esp_init);
+module_exit(ipt_esp_fini);
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index ba5e235..7c6836c 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -719,15 +719,15 @@
 	
 }
 
-static int __init init(void)
+static int __init ipt_hashlimit_init(void)
 {
 	return init_or_fini(0);
 }
 
-static void __exit fini(void)
+static void __exit ipt_hashlimit_fini(void)
 {
 	init_or_fini(1);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_hashlimit_init);
+module_exit(ipt_hashlimit_fini);
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c
index ae70112..5202edd 100644
--- a/net/ipv4/netfilter/ipt_iprange.c
+++ b/net/ipv4/netfilter/ipt_iprange.c
@@ -71,15 +71,15 @@
 	.me		= THIS_MODULE
 };
 
-static int __init init(void)
+static int __init ipt_iprange_init(void)
 {
 	return ipt_register_match(&iprange_match);
 }
 
-static void __exit fini(void)
+static void __exit ipt_iprange_fini(void)
 {
 	ipt_unregister_match(&iprange_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_iprange_init);
+module_exit(ipt_iprange_fini);
diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c
index bd07f7c..ac95d83 100644
--- a/net/ipv4/netfilter/ipt_multiport.c
+++ b/net/ipv4/netfilter/ipt_multiport.c
@@ -171,7 +171,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_multiport_init(void)
 {
 	int err;
 
@@ -185,11 +185,11 @@
 	return err;
 }
 
-static void __exit fini(void)
+static void __exit ipt_multiport_fini(void)
 {
 	ipt_unregister_match(&multiport_match);
 	ipt_unregister_match(&multiport_match_v1);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_multiport_init);
+module_exit(ipt_multiport_fini);
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
index 3900428..5ac6ac0 100644
--- a/net/ipv4/netfilter/ipt_owner.c
+++ b/net/ipv4/netfilter/ipt_owner.c
@@ -78,15 +78,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_owner_init(void)
 {
 	return ipt_register_match(&owner_match);
 }
 
-static void __exit fini(void)
+static void __exit ipt_owner_fini(void)
 {
 	ipt_unregister_match(&owner_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_owner_init);
+module_exit(ipt_owner_fini);
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 06792ea..1438432 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -962,7 +962,7 @@
 };
 
 /* Kernel module initialization. */
-static int __init init(void)
+static int __init ipt_recent_init(void)
 {
 	int err, count;
 
@@ -995,7 +995,7 @@
 }
 
 /* Kernel module destruction. */
-static void __exit fini(void)
+static void __exit ipt_recent_fini(void)
 {
 	ipt_unregister_match(&recent_match);
 
@@ -1003,5 +1003,5 @@
 }
 
 /* Register our module with the kernel. */
-module_init(init);
-module_exit(fini);
+module_init(ipt_recent_init);
+module_exit(ipt_recent_fini);
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c
index e404e92d..5549c39 100644
--- a/net/ipv4/netfilter/ipt_tos.c
+++ b/net/ipv4/netfilter/ipt_tos.c
@@ -39,15 +39,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_multiport_init(void)
 {
 	return ipt_register_match(&tos_match);
 }
 
-static void __exit fini(void)
+static void __exit ipt_multiport_fini(void)
 {
 	ipt_unregister_match(&tos_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_multiport_init);
+module_exit(ipt_multiport_fini);
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c
index ae7ce4d..a5243bd 100644
--- a/net/ipv4/netfilter/ipt_ttl.c
+++ b/net/ipv4/netfilter/ipt_ttl.c
@@ -55,16 +55,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ipt_ttl_init(void)
 {
 	return ipt_register_match(&ttl_match);
 }
 
-static void __exit fini(void)
+static void __exit ipt_ttl_fini(void)
 {
 	ipt_unregister_match(&ttl_match);
 
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ipt_ttl_init);
+module_exit(ipt_ttl_fini);
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 212a307..3d80aef 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -139,7 +139,7 @@
 static int forward = NF_ACCEPT;
 module_param(forward, bool, 0000);
 
-static int __init init(void)
+static int __init iptable_filter_init(void)
 {
 	int ret;
 
@@ -181,7 +181,7 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit iptable_filter_fini(void)
 {
 	unsigned int i;
 
@@ -191,5 +191,5 @@
 	ipt_unregister_table(&packet_filter);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(iptable_filter_init);
+module_exit(iptable_filter_fini);
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 3212a5c..412fc96 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -201,7 +201,7 @@
 	},
 };
 
-static int __init init(void)
+static int __init iptable_mangle_init(void)
 {
 	int ret;
 
@@ -247,7 +247,7 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit iptable_mangle_fini(void)
 {
 	unsigned int i;
 
@@ -257,5 +257,5 @@
 	ipt_unregister_table(&packet_mangler);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(iptable_mangle_init);
+module_exit(iptable_mangle_fini);
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index fdb9e9c..03cc79a 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -116,7 +116,7 @@
 	},
 };
 
-static int __init init(void)
+static int __init iptable_raw_init(void)
 {
 	int ret;
 
@@ -144,7 +144,7 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit iptable_raw_fini(void)
 {
 	unsigned int i;
 
@@ -154,6 +154,6 @@
 	ipt_unregister_table(&packet_raw);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(iptable_raw_init);
+module_exit(iptable_raw_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index c8abc9d..4afbc69 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -571,18 +571,18 @@
 MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
 MODULE_LICENSE("GPL");
 
-static int __init init(void)
+static int __init nf_conntrack_l3proto_ipv4_init(void)
 {
 	need_conntrack();
 	return init_or_cleanup(1);
 }
 
-static void __exit fini(void)
+static void __exit nf_conntrack_l3proto_ipv4_fini(void)
 {
 	init_or_cleanup(0);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(nf_conntrack_l3proto_ipv4_init);
+module_exit(nf_conntrack_l3proto_ipv4_fini);
 
 EXPORT_SYMBOL(nf_ct_ipv4_gather_frags);
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index e688c68..91c2f41 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -223,7 +223,7 @@
 
  	/* In dangerous area, increase slowly. */
 	else if (sysctl_tcp_abc) {
- 		/* RFC3465: Apppriate Byte Count
+ 		/* RFC3465: Appropriate Byte Count
  		 * increase once for each full cwnd acked
  		 */
  		if (tp->bytes_acked >= tp->snd_cwnd*tp->mss_cache) {
diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
new file mode 100644
index 0000000..0d7d386
--- /dev/null
+++ b/net/ipv4/tunnel4.c
@@ -0,0 +1,113 @@
+/* tunnel4.c: Generic IP tunnel transformer.
+ *
+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <net/protocol.h>
+#include <net/xfrm.h>
+
+static struct xfrm_tunnel *tunnel4_handlers;
+static DEFINE_MUTEX(tunnel4_mutex);
+
+int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
+{
+	struct xfrm_tunnel **pprev;
+	int ret = -EEXIST;
+	int priority = handler->priority;
+
+	mutex_lock(&tunnel4_mutex);
+
+	for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
+		if ((*pprev)->priority > priority)
+			break;
+		if ((*pprev)->priority == priority)
+			goto err;
+	}
+
+	handler->next = *pprev;
+	*pprev = handler;
+
+	ret = 0;
+
+err:
+	mutex_unlock(&tunnel4_mutex);
+
+	return ret;
+}
+
+EXPORT_SYMBOL(xfrm4_tunnel_register);
+
+int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
+{
+	struct xfrm_tunnel **pprev;
+	int ret = -ENOENT;
+
+	mutex_lock(&tunnel4_mutex);
+
+	for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
+		if (*pprev == handler) {
+			*pprev = handler->next;
+			ret = 0;
+			break;
+		}
+	}
+
+	mutex_unlock(&tunnel4_mutex);
+
+	synchronize_net();
+
+	return ret;
+}
+
+EXPORT_SYMBOL(xfrm4_tunnel_deregister);
+
+static int tunnel4_rcv(struct sk_buff *skb)
+{
+	struct xfrm_tunnel *handler;
+
+	for (handler = tunnel4_handlers; handler; handler = handler->next)
+		if (!handler->handler(skb))
+			return 0;
+
+	kfree_skb(skb);
+	return 0;
+}
+
+static void tunnel4_err(struct sk_buff *skb, u32 info)
+{
+	struct xfrm_tunnel *handler;
+
+	for (handler = tunnel4_handlers; handler; handler = handler->next)
+		if (!handler->err_handler(skb, info))
+			break;
+}
+
+static struct net_protocol tunnel4_protocol = {
+	.handler	=	tunnel4_rcv,
+	.err_handler	=	tunnel4_err,
+	.no_policy	=	1,
+};
+
+static int __init tunnel4_init(void)
+{
+	if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) {
+		printk(KERN_ERR "tunnel4 init: can't add protocol\n");
+		return -EAGAIN;
+	}
+	return 0;
+}
+
+static void __exit tunnel4_fini(void)
+{
+	if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP))
+		printk(KERN_ERR "tunnel4 close: can't remove protocol\n");
+}
+
+module_init(tunnel4_init);
+module_exit(tunnel4_fini);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index b08d56b..2d67093 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -26,64 +26,6 @@
 	return 0;
 }
 
-static struct xfrm_tunnel *ipip_handler;
-static DEFINE_MUTEX(xfrm4_tunnel_mutex);
-
-int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
-{
-	int ret;
-
-	mutex_lock(&xfrm4_tunnel_mutex);
-	ret = 0;
-	if (ipip_handler != NULL)
-		ret = -EINVAL;
-	if (!ret)
-		ipip_handler = handler;
-	mutex_unlock(&xfrm4_tunnel_mutex);
-
-	return ret;
-}
-
-EXPORT_SYMBOL(xfrm4_tunnel_register);
-
-int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
-{
-	int ret;
-
-	mutex_lock(&xfrm4_tunnel_mutex);
-	ret = 0;
-	if (ipip_handler != handler)
-		ret = -EINVAL;
-	if (!ret)
-		ipip_handler = NULL;
-	mutex_unlock(&xfrm4_tunnel_mutex);
-
-	synchronize_net();
-
-	return ret;
-}
-
-EXPORT_SYMBOL(xfrm4_tunnel_deregister);
-
-static int ipip_rcv(struct sk_buff *skb)
-{
-	struct xfrm_tunnel *handler = ipip_handler;
-
-	/* Tunnel devices take precedence.  */
-	if (handler && handler->handler(skb) == 0)
-		return 0;
-
-	return xfrm4_rcv(skb);
-}
-
-static void ipip_err(struct sk_buff *skb, u32 info)
-{
-	struct xfrm_tunnel *handler = ipip_handler;
-
-	if (handler)
-		handler->err_handler(skb, info);
-}
-
 static int ipip_init_state(struct xfrm_state *x)
 {
 	if (!x->props.mode)
@@ -111,10 +53,15 @@
 	.output		= ipip_output
 };
 
-static struct net_protocol ipip_protocol = {
-	.handler	=	ipip_rcv,
-	.err_handler	=	ipip_err,
-	.no_policy	=	1,
+static int xfrm_tunnel_err(struct sk_buff *skb, u32 info)
+{
+	return -ENOENT;
+}
+
+static struct xfrm_tunnel xfrm_tunnel_handler = {
+	.handler	=	xfrm4_rcv,
+	.err_handler	=	xfrm_tunnel_err,
+	.priority	=	2,
 };
 
 static int __init ipip_init(void)
@@ -123,8 +70,8 @@
 		printk(KERN_INFO "ipip init: can't add xfrm type\n");
 		return -EAGAIN;
 	}
-	if (inet_add_protocol(&ipip_protocol, IPPROTO_IPIP) < 0) {
-		printk(KERN_INFO "ipip init: can't add protocol\n");
+	if (xfrm4_tunnel_register(&xfrm_tunnel_handler)) {
+		printk(KERN_INFO "ipip init: can't add xfrm handler\n");
 		xfrm_unregister_type(&ipip_type, AF_INET);
 		return -EAGAIN;
 	}
@@ -133,8 +80,8 @@
 
 static void __exit ipip_fini(void)
 {
-	if (inet_del_protocol(&ipip_protocol, IPPROTO_IPIP) < 0)
-		printk(KERN_INFO "ipip close: can't remove protocol\n");
+	if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler))
+		printk(KERN_INFO "ipip close: can't remove xfrm handler\n");
 	if (xfrm_unregister_type(&ipip_type, AF_INET) < 0)
 		printk(KERN_INFO "ipip close: can't remove xfrm type\n");
 }
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index e6f83b6..f8a107a 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -88,7 +88,7 @@
 	tristate "IPv6: IPComp transformation"
 	depends on IPV6
 	select XFRM
-	select INET6_TUNNEL
+	select INET6_XFRM_TUNNEL
 	select CRYPTO
 	select CRYPTO_DEFLATE
 	---help---
@@ -97,19 +97,18 @@
 
 	  If unsure, say Y.
 
+config INET6_XFRM_TUNNEL
+	tristate
+	select INET6_TUNNEL
+	default n
+
 config INET6_TUNNEL
-	tristate "IPv6: tunnel transformation"
-	depends on IPV6
-	select XFRM
-	---help---
-	  Support for generic IPv6-in-IPv6 tunnel transformation, which is
-	  required by the IPv6-in-IPv6 tunneling module as well as tunnel mode
-	  IPComp.
-	  
-	  If unsure, say Y.
+	tristate
+	default n
 
 config IPV6_TUNNEL
 	tristate "IPv6: IPv6-in-IPv6 tunnel"
+	select INET6_TUNNEL
 	depends on IPV6
 	---help---
 	  Support for IPv6-in-IPv6 tunnels described in RFC 2473.
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 41877ab..a760b09 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -18,7 +18,8 @@
 obj-$(CONFIG_INET6_AH) += ah6.o
 obj-$(CONFIG_INET6_ESP) += esp6.o
 obj-$(CONFIG_INET6_IPCOMP) += ipcomp6.o
-obj-$(CONFIG_INET6_TUNNEL) += xfrm6_tunnel.o 
+obj-$(CONFIG_INET6_XFRM_TUNNEL) += xfrm6_tunnel.o
+obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o
 obj-$(CONFIG_NETFILTER)	+= netfilter/
 
 obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 4859753..ff9040c 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -44,7 +44,6 @@
 
 #include <net/ip.h>
 #include <net/ipv6.h>
-#include <net/protocol.h>
 #include <net/ip6_route.h>
 #include <net/addrconf.h>
 #include <net/ip6_tunnel.h>
@@ -391,7 +390,7 @@
  *   to the specifications in RFC 2473.
  **/
 
-static void 
+static int
 ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	   int type, int code, int offset, __u32 info)
 {
@@ -402,6 +401,7 @@
 	int rel_code = ICMPV6_ADDR_UNREACH;
 	__u32 rel_info = 0;
 	__u16 len;
+	int err = -ENOENT;
 
 	/* If the packet doesn't contain the original IPv6 header we are 
 	   in trouble since we might need the source address for further 
@@ -411,6 +411,8 @@
 	if ((t = ip6ip6_tnl_lookup(&ipv6h->daddr, &ipv6h->saddr)) == NULL)
 		goto out;
 
+	err = 0;
+
 	switch (type) {
 		__u32 teli;
 		struct ipv6_tlv_tnl_enc_lim *tel;
@@ -492,6 +494,7 @@
 	}
 out:
 	read_unlock(&ip6ip6_lock);
+	return err;
 }
 
 static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,
@@ -511,9 +514,8 @@
  **/
 
 static int 
-ip6ip6_rcv(struct sk_buff **pskb)
+ip6ip6_rcv(struct sk_buff *skb)
 {
-	struct sk_buff *skb = *pskb;
 	struct ipv6hdr *ipv6h;
 	struct ip6_tnl *t;
 
@@ -1112,39 +1114,12 @@
 	return 0;
 }
 
-#ifdef CONFIG_INET6_TUNNEL
 static struct xfrm6_tunnel ip6ip6_handler = {
 	.handler	= ip6ip6_rcv,
 	.err_handler	= ip6ip6_err,
+	.priority	=	1,
 };
 
-static inline int ip6ip6_register(void)
-{
-	return xfrm6_tunnel_register(&ip6ip6_handler);
-}
-
-static inline int ip6ip6_unregister(void)
-{
-	return xfrm6_tunnel_deregister(&ip6ip6_handler);
-}
-#else
-static struct inet6_protocol xfrm6_tunnel_protocol = {
-	.handler	= ip6ip6_rcv,
-	.err_handler	= ip6ip6_err,
-	.flags		= INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
-};
-
-static inline int ip6ip6_register(void)
-{
-	return inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6);
-}
-
-static inline int ip6ip6_unregister(void)
-{
-	return inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6);
-}
-#endif
-
 /**
  * ip6_tunnel_init - register protocol and reserve needed resources
  *
@@ -1155,7 +1130,7 @@
 {
 	int  err;
 
-	if (ip6ip6_register() < 0) {
+	if (xfrm6_tunnel_register(&ip6ip6_handler)) {
 		printk(KERN_ERR "ip6ip6 init: can't register tunnel\n");
 		return -EAGAIN;
 	}
@@ -1174,7 +1149,7 @@
 	}
 	return 0;
 fail:
-	ip6ip6_unregister();
+	xfrm6_tunnel_deregister(&ip6ip6_handler);
 	return err;
 }
 
@@ -1184,7 +1159,7 @@
 
 static void __exit ip6_tunnel_cleanup(void)
 {
-	if (ip6ip6_unregister() < 0)
+	if (xfrm6_tunnel_deregister(&ip6ip6_handler))
 		printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n");
 
 	unregister_netdev(ip6ip6_fb_tnl_dev);
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 344eab3..e81c6a9 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -713,13 +713,13 @@
 	return status;
 }
 
-static int __init init(void)
+static int __init ip6_queue_init(void)
 {
 	
 	return init_or_cleanup(1);
 }
 
-static void __exit fini(void)
+static void __exit ip6_queue_fini(void)
 {
 	init_or_cleanup(0);
 }
@@ -727,5 +727,5 @@
 MODULE_DESCRIPTION("IPv6 packet queue handler");
 MODULE_LICENSE("GPL");
 
-module_init(init);
-module_exit(fini);
+module_init(ip6_queue_init);
+module_exit(ip6_queue_fini);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index db3c9ae..3ecf2db 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1406,7 +1406,7 @@
 	.family		= AF_INET6,
 };
 
-static int __init init(void)
+static int __init ip6_tables_init(void)
 {
 	int ret;
 
@@ -1429,7 +1429,7 @@
 	return 0;
 }
 
-static void __exit fini(void)
+static void __exit ip6_tables_fini(void)
 {
 	nf_unregister_sockopt(&ip6t_sockopts);
 	xt_unregister_match(&icmp6_matchstruct);
@@ -1517,5 +1517,5 @@
 EXPORT_SYMBOL(ip6t_ext_hdr);
 EXPORT_SYMBOL(ipv6_find_hdr);
 
-module_init(init);
-module_exit(fini);
+module_init(ip6_tables_init);
+module_exit(ip6_tables_fini);
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index da14c6d..b8eff8e 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -93,15 +93,15 @@
 	.me		= THIS_MODULE
 };
 
-static int __init init(void)
+static int __init ip6t_hl_init(void)
 {
 	return ip6t_register_target(&ip6t_HL);
 }
 
-static void __exit fini(void)
+static void __exit ip6t_hl_fini(void)
 {
 	ip6t_unregister_target(&ip6t_HL);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip6t_hl_init);
+module_exit(ip6t_hl_fini);
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 07c6bcb..a96c0de 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -483,7 +483,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ip6t_log_init(void)
 {
 	if (ip6t_register_target(&ip6t_log_reg))
 		return -EINVAL;
@@ -497,11 +497,11 @@
 	return 0;
 }
 
-static void __exit fini(void)
+static void __exit ip6t_log_fini(void)
 {
 	nf_log_unregister_logger(&ip6t_logger);
 	ip6t_unregister_target(&ip6t_log_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip6t_log_init);
+module_exit(ip6t_log_fini);
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index ddfa385..de1175c 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -255,17 +255,17 @@
 	.me		= THIS_MODULE
 };
 
-static int __init init(void)
+static int __init ip6t_reject_init(void)
 {
 	if (ip6t_register_target(&ip6t_reject_reg))
 		return -EINVAL;
 	return 0;
 }
 
-static void __exit fini(void)
+static void __exit ip6t_reject_fini(void)
 {
 	ip6t_unregister_target(&ip6t_reject_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip6t_reject_init);
+module_exit(ip6t_reject_fini);
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index 178f6fb..2f7bb20 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -122,15 +122,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ip6t_ah_init(void)
 {
 	return ip6t_register_match(&ah_match);
 }
 
-static void __exit cleanup(void)
+static void __exit ip6t_ah_fini(void)
 {
 	ip6t_unregister_match(&ah_match);
 }
 
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_ah_init);
+module_exit(ip6t_ah_fini);
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
index e97a702..9422413 100644
--- a/net/ipv6/netfilter/ip6t_dst.c
+++ b/net/ipv6/netfilter/ip6t_dst.c
@@ -206,15 +206,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ip6t_dst_init(void)
 {
 	return ip6t_register_match(&opts_match);
 }
 
-static void __exit cleanup(void)
+static void __exit ip6t_dst_fini(void)
 {
 	ip6t_unregister_match(&opts_match);
 }
 
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_dst_init);
+module_exit(ip6t_dst_fini);
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
index 540b8bf..36bedad 100644
--- a/net/ipv6/netfilter/ip6t_esp.c
+++ b/net/ipv6/netfilter/ip6t_esp.c
@@ -101,15 +101,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ip6t_esp_init(void)
 {
 	return ip6t_register_match(&esp_match);
 }
 
-static void __exit cleanup(void)
+static void __exit ip6t_esp_fini(void)
 {
 	ip6t_unregister_match(&esp_match);
 }
 
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_esp_init);
+module_exit(ip6t_esp_fini);
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index d4b0bad..94dbdb8 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -70,15 +70,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ip6t_eui64_init(void)
 {
 	return ip6t_register_match(&eui64_match);
 }
 
-static void __exit fini(void)
+static void __exit ip6t_eui64_fini(void)
 {
 	ip6t_unregister_match(&eui64_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip6t_eui64_init);
+module_exit(ip6t_eui64_fini);
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 4c41e14..06768c8 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -139,15 +139,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ip6t_frag_init(void)
 {
 	return ip6t_register_match(&frag_match);
 }
 
-static void __exit cleanup(void)
+static void __exit ip6t_frag_fini(void)
 {
 	ip6t_unregister_match(&frag_match);
 }
 
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_frag_init);
+module_exit(ip6t_frag_fini);
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index b4a1fdf..374f1be 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -206,15 +206,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ip6t_hbh_init(void)
 {
 	return ip6t_register_match(&opts_match);
 }
 
-static void __exit cleanup(void)
+static void __exit ip6t_hbh_fini(void)
 {
 	ip6t_unregister_match(&opts_match);
 }
 
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_hbh_init);
+module_exit(ip6t_hbh_fini);
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c
index 3740557..44a729e 100644
--- a/net/ipv6/netfilter/ip6t_hl.c
+++ b/net/ipv6/netfilter/ip6t_hl.c
@@ -55,16 +55,16 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ip6t_hl_init(void)
 {
 	return ip6t_register_match(&hl_match);
 }
 
-static void __exit fini(void)
+static void __exit ip6t_hl_fini(void)
 {
 	ip6t_unregister_match(&hl_match);
 
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip6t_hl_init);
+module_exit(ip6t_hl_fini);
diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c
index 752b65d..10c48ba 100644
--- a/net/ipv6/netfilter/ip6t_multiport.c
+++ b/net/ipv6/netfilter/ip6t_multiport.c
@@ -111,15 +111,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ip6t_multiport_init(void)
 {
 	return ip6t_register_match(&multiport_match);
 }
 
-static void __exit fini(void)
+static void __exit ip6t_multiport_fini(void)
 {
 	ip6t_unregister_match(&multiport_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip6t_multiport_init);
+module_exit(ip6t_multiport_fini);
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index e2cee3b..5d04799 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -79,15 +79,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ip6t_owner_init(void)
 {
 	return ip6t_register_match(&owner_match);
 }
 
-static void __exit fini(void)
+static void __exit ip6t_owner_fini(void)
 {
 	ip6t_unregister_match(&owner_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip6t_owner_init);
+module_exit(ip6t_owner_fini);
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index 4c6b55b..fbb0184 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -225,15 +225,15 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init ip6t_rt_init(void)
 {
 	return ip6t_register_match(&rt_match);
 }
 
-static void __exit cleanup(void)
+static void __exit ip6t_rt_fini(void)
 {
 	ip6t_unregister_match(&rt_match);
 }
 
-module_init(init);
-module_exit(cleanup);
+module_init(ip6t_rt_init);
+module_exit(ip6t_rt_fini);
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index ce4a968..e5e724d 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -159,7 +159,7 @@
 static int forward = NF_ACCEPT;
 module_param(forward, bool, 0000);
 
-static int __init init(void)
+static int __init ip6table_filter_init(void)
 {
 	int ret;
 
@@ -201,7 +201,7 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit ip6table_filter_fini(void)
 {
 	unsigned int i;
 
@@ -211,5 +211,5 @@
 	ip6t_unregister_table(&packet_filter);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip6table_filter_init);
+module_exit(ip6table_filter_fini);
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 30a4627..e1f0f6a 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -228,7 +228,7 @@
 	},
 };
 
-static int __init init(void)
+static int __init ip6table_mangle_init(void)
 {
 	int ret;
 
@@ -274,7 +274,7 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit ip6table_mangle_fini(void)
 {
 	unsigned int i;
 
@@ -284,5 +284,5 @@
 	ip6t_unregister_table(&packet_mangler);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip6table_mangle_init);
+module_exit(ip6table_mangle_fini);
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index db28ba3..54d1fff 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -142,7 +142,7 @@
 	},
 };
 
-static int __init init(void)
+static int __init ip6table_raw_init(void)
 {
 	int ret;
 
@@ -170,7 +170,7 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit ip6table_raw_fini(void)
 {
 	unsigned int i;
 
@@ -180,6 +180,6 @@
 	ip6t_unregister_table(&packet_raw);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip6table_raw_init);
+module_exit(ip6table_raw_fini);
 MODULE_LICENSE("GPL");
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index c16f629..c8b5a96 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -588,16 +588,16 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
 
-static int __init init(void)
+static int __init nf_conntrack_l3proto_ipv6_init(void)
 {
 	need_conntrack();
 	return init_or_cleanup(1);
 }
 
-static void __exit fini(void)
+static void __exit nf_conntrack_l3proto_ipv6_fini(void)
 {
 	init_or_cleanup(0);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(nf_conntrack_l3proto_ipv6_init);
+module_exit(nf_conntrack_l3proto_ipv6_fini);
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c
new file mode 100644
index 0000000..5659b522
--- /dev/null
+++ b/net/ipv6/tunnel6.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C)2003,2004 USAGI/WIDE Project
+ *
+ * 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
+ *
+ * Authors	Mitsuru KANDA  <mk@linux-ipv6.org>
+ * 		YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <net/protocol.h>
+#include <net/xfrm.h>
+
+static struct xfrm6_tunnel *tunnel6_handlers;
+static DEFINE_MUTEX(tunnel6_mutex);
+
+int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
+{
+	struct xfrm6_tunnel **pprev;
+	int ret = -EEXIST;
+	int priority = handler->priority;
+
+	mutex_lock(&tunnel6_mutex);
+
+	for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
+		if ((*pprev)->priority > priority)
+			break;
+		if ((*pprev)->priority == priority)
+			goto err;
+	}
+
+	handler->next = *pprev;
+	*pprev = handler;
+
+	ret = 0;
+
+err:
+	mutex_unlock(&tunnel6_mutex);
+
+	return ret;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_register);
+
+int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
+{
+	struct xfrm6_tunnel **pprev;
+	int ret = -ENOENT;
+
+	mutex_lock(&tunnel6_mutex);
+
+	for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
+		if (*pprev == handler) {
+			*pprev = handler->next;
+			ret = 0;
+			break;
+		}
+	}
+
+	mutex_unlock(&tunnel6_mutex);
+
+	synchronize_net();
+
+	return ret;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_deregister);
+
+static int tunnel6_rcv(struct sk_buff **pskb)
+{
+	struct sk_buff *skb = *pskb;
+	struct xfrm6_tunnel *handler;
+
+	for (handler = tunnel6_handlers; handler; handler = handler->next)
+		if (!handler->handler(skb))
+			return 0;
+
+	kfree_skb(skb);
+	return 0;
+}
+
+static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+			int type, int code, int offset, __u32 info)
+{
+	struct xfrm6_tunnel *handler;
+
+	for (handler = tunnel6_handlers; handler; handler = handler->next)
+		if (!handler->err_handler(skb, opt, type, code, offset, info))
+			break;
+}
+
+static struct inet6_protocol tunnel6_protocol = {
+	.handler	= tunnel6_rcv,
+	.err_handler	= tunnel6_err,
+	.flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+};
+
+static int __init tunnel6_init(void)
+{
+	if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) {
+		printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
+		return -EAGAIN;
+	}
+	return 0;
+}
+
+static void __exit tunnel6_fini(void)
+{
+	if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6))
+		printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
+}
+
+module_init(tunnel6_init);
+module_exit(tunnel6_fini);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 1ca2da6..cccf8b7 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -28,9 +28,8 @@
 		IP6_ECN_set_ce(inner_iph);
 }
 
-int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi)
+int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
 {
-	struct sk_buff *skb = *pskb;
 	int err;
 	u32 seq;
 	struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH];
@@ -159,5 +158,5 @@
 
 int xfrm6_rcv(struct sk_buff **pskb)
 {
-	return xfrm6_rcv_spi(pskb, 0);
+	return xfrm6_rcv_spi(*pskb, 0);
 }
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 08f9abb..a8f6776 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -28,7 +28,6 @@
 #include <net/ip.h>
 #include <net/xfrm.h>
 #include <net/ipv6.h>
-#include <net/protocol.h>
 #include <linux/ipv6.h>
 #include <linux/icmpv6.h>
 #include <linux/mutex.h>
@@ -357,71 +356,18 @@
 	return 0;
 }
 
-static struct xfrm6_tunnel *xfrm6_tunnel_handler;
-static DEFINE_MUTEX(xfrm6_tunnel_mutex);
-
-int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
+static int xfrm6_tunnel_rcv(struct sk_buff *skb)
 {
-	int ret;
-
-	mutex_lock(&xfrm6_tunnel_mutex);
-	ret = 0;
-	if (xfrm6_tunnel_handler != NULL)
-		ret = -EINVAL;
-	if (!ret)
-		xfrm6_tunnel_handler = handler;
-	mutex_unlock(&xfrm6_tunnel_mutex);
-
-	return ret;
-}
-
-EXPORT_SYMBOL(xfrm6_tunnel_register);
-
-int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
-{
-	int ret;
-
-	mutex_lock(&xfrm6_tunnel_mutex);
-	ret = 0;
-	if (xfrm6_tunnel_handler != handler)
-		ret = -EINVAL;
-	if (!ret)
-		xfrm6_tunnel_handler = NULL;
-	mutex_unlock(&xfrm6_tunnel_mutex);
-
-	synchronize_net();
-
-	return ret;
-}
-
-EXPORT_SYMBOL(xfrm6_tunnel_deregister);
-
-static int xfrm6_tunnel_rcv(struct sk_buff **pskb)
-{
-	struct sk_buff *skb = *pskb;
-	struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
 	struct ipv6hdr *iph = skb->nh.ipv6h;
 	u32 spi;
 
-	/* device-like_ip6ip6_handler() */
-	if (handler && handler->handler(pskb) == 0)
-		return 0;
-
 	spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
-	return xfrm6_rcv_spi(pskb, spi);
+	return xfrm6_rcv_spi(skb, spi);
 }
 
-static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
-			     int type, int code, int offset, __u32 info)
+static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+			    int type, int code, int offset, __u32 info)
 {
-	struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
-
-	/* call here first for device-like ip6ip6 err handling */
-	if (handler) {
-		handler->err_handler(skb, opt, type, code, offset, info);
-		return;
-	}
-
 	/* xfrm6_tunnel native err handling */
 	switch (type) {
 	case ICMPV6_DEST_UNREACH: 
@@ -462,7 +408,8 @@
 	default:
 		break;
 	}
-	return;
+
+	return 0;
 }
 
 static int xfrm6_tunnel_init_state(struct xfrm_state *x)
@@ -493,10 +440,10 @@
 	.output		= xfrm6_tunnel_output,
 };
 
-static struct inet6_protocol xfrm6_tunnel_protocol = {
+static struct xfrm6_tunnel xfrm6_tunnel_handler = {
 	.handler	= xfrm6_tunnel_rcv,
-	.err_handler	= xfrm6_tunnel_err, 
-	.flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+	.err_handler	= xfrm6_tunnel_err,
+	.priority	= 2,
 };
 
 static int __init xfrm6_tunnel_init(void)
@@ -508,16 +455,16 @@
 			   "xfrm6_tunnel init: can't add xfrm type\n");
 		return -EAGAIN;
 	}
-	if (inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) {
+	if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) {
 		X6TPRINTK1(KERN_ERR
-			   "xfrm6_tunnel init(): can't add protocol\n");
+			   "xfrm6_tunnel init(): can't add handler\n");
 		xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
 		return -EAGAIN;
 	}
 	if (xfrm6_tunnel_spi_init() < 0) {
 		X6TPRINTK1(KERN_ERR
 			   "xfrm6_tunnel init: failed to initialize spi\n");
-		inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6);
+		xfrm6_tunnel_deregister(&xfrm6_tunnel_handler);
 		xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
 		return -EAGAIN;
 	}
@@ -529,9 +476,9 @@
 	X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
 
 	xfrm6_tunnel_spi_fini();
-	if (inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0)
+	if (xfrm6_tunnel_deregister(&xfrm6_tunnel_handler))
 		X6TPRINTK1(KERN_ERR 
-			   "xfrm6_tunnel close: can't remove protocol\n");
+			   "xfrm6_tunnel close: can't remove handler\n");
 	if (xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6) < 0)
 		X6TPRINTK1(KERN_ERR
 			   "xfrm6_tunnel close: can't remove xfrm type\n");
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 0fb513a..2dbf134 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -1892,6 +1892,29 @@
 	return rc;
 }
 
+
+#ifdef CONFIG_COMPAT
+static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+	/*
+	 * These 4 commands use same structure on 32bit and 64bit.  Rest of IPX
+	 * commands is handled by generic ioctl code.  As these commands are
+	 * SIOCPROTOPRIVATE..SIOCPROTOPRIVATE+3, they cannot be handled by generic
+	 * code.
+	 */
+	switch (cmd) {
+	case SIOCAIPXITFCRT:
+	case SIOCAIPXPRISLT:
+	case SIOCIPXCFGDATA:
+	case SIOCIPXNCPCONN:
+		return ipx_ioctl(sock, cmd, arg);
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+#endif
+
+
 /*
  * Socket family declarations
  */
@@ -1913,6 +1936,9 @@
 	.getname	= ipx_getname,
 	.poll		= datagram_poll,
 	.ioctl		= ipx_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= ipx_compat_ioctl,
+#endif
 	.listen		= sock_no_listen,
 	.shutdown	= sock_no_shutdown, /* FIXME: support shutdown */
 	.setsockopt	= ipx_setsockopt,
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 627b113..2f37c9f 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -1830,6 +1830,19 @@
 	return 0;
 }
 
+#ifdef CONFIG_COMPAT
+/*
+ * Function irda_ioctl (sock, cmd, arg)
+ */
+static int irda_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+	/*
+	 * All IRDA's ioctl are standard ones.
+	 */
+	return -ENOIOCTLCMD;
+}
+#endif
+
 /*
  * Function irda_setsockopt (sock, level, optname, optval, optlen)
  *
@@ -2476,6 +2489,9 @@
 	.getname =	irda_getname,
 	.poll =		irda_poll,
 	.ioctl =	irda_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl =	irda_compat_ioctl,
+#endif
 	.listen =	irda_listen,
 	.shutdown =	irda_shutdown,
 	.setsockopt =	irda_setsockopt,
@@ -2497,6 +2513,9 @@
 	.getname =	irda_getname,
 	.poll =		datagram_poll,
 	.ioctl =	irda_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl =	irda_compat_ioctl,
+#endif
 	.listen =	irda_listen,
 	.shutdown =	irda_shutdown,
 	.setsockopt =	irda_setsockopt,
@@ -2518,6 +2537,9 @@
 	.getname =	irda_getname,
 	.poll =		datagram_poll,
 	.ioctl =	irda_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl =	irda_compat_ioctl,
+#endif
 	.listen =	irda_listen,
 	.shutdown =	irda_shutdown,
 	.setsockopt =	irda_setsockopt,
@@ -2540,6 +2562,9 @@
 	.getname =	irda_getname,
 	.poll =		datagram_poll,
 	.ioctl =	irda_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl =	irda_compat_ioctl,
+#endif
 	.listen =	sock_no_listen,
 	.shutdown =	irda_shutdown,
 	.setsockopt =	irda_setsockopt,
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index cd191b0..e38a4b5 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -624,7 +624,7 @@
 static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")];
 
 /* don't make this __exit, since it's called from __init ! */
-static void fini(void)
+static void nf_conntrack_ftp_fini(void)
 {
 	int i, j;
 	for (i = 0; i < ports_c; i++) {
@@ -642,7 +642,7 @@
 	kfree(ftp_buffer);
 }
 
-static int __init init(void)
+static int __init nf_conntrack_ftp_init(void)
 {
 	int i, j = -1, ret = 0;
 	char *tmpname;
@@ -683,7 +683,7 @@
 				printk("nf_ct_ftp: failed to register helper "
 				       " for pf: %d port: %d\n",
 					ftp[i][j].tuple.src.l3num, ports[i]);
-				fini();
+				nf_conntrack_ftp_fini();
 				return ret;
 			}
 		}
@@ -692,5 +692,5 @@
 	return 0;
 }
 
-module_init(init);
-module_exit(fini);
+module_init(nf_conntrack_ftp_init);
+module_exit(nf_conntrack_ftp_fini);
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index cf798e6..9cccc32 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -615,7 +615,7 @@
 static struct ctl_table_header *nf_ct_sysctl_header;
 #endif
 
-int __init init(void)
+int __init nf_conntrack_proto_sctp_init(void)
 {
 	int ret;
 
@@ -652,7 +652,7 @@
 	return ret;
 }
 
-void __exit fini(void)
+void __exit nf_conntrack_proto_sctp_fini(void)
 {
 	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp6);
 	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_sctp4);
@@ -662,8 +662,8 @@
 	DEBUGP("SCTP conntrack module unloaded\n");
 }
 
-module_init(init);
-module_exit(fini);
+module_init(nf_conntrack_proto_sctp_init);
+module_exit(nf_conntrack_proto_sctp_fini);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Kiran Kumar Immidi");
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 75577e1..c72aa3c 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -806,18 +806,18 @@
 	nf_ct_iterate_cleanup(kill_proto, proto);
 }
 
-static int __init init(void)
+static int __init nf_conntrack_standalone_init(void)
 {
 	return init_or_cleanup(1);
 }
 
-static void __exit fini(void)
+static void __exit nf_conntrack_standalone_fini(void)
 {
 	init_or_cleanup(0);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(nf_conntrack_standalone_init);
+module_exit(nf_conntrack_standalone_fini);
 
 /* Some modules need us, but don't depend directly on any symbol.
    They should call this. */
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 54cbbaa..3e3f544 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -1081,13 +1081,13 @@
 	return status;
 }
 
-static int __init init(void)
+static int __init nfnetlink_log_init(void)
 {
 	
 	return init_or_cleanup(1);
 }
 
-static void __exit fini(void)
+static void __exit nfnetlink_log_fini(void)
 {
 	init_or_cleanup(0);
 }
@@ -1097,5 +1097,5 @@
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ULOG);
 
-module_init(init);
-module_exit(fini);
+module_init(nfnetlink_log_init);
+module_exit(nfnetlink_log_fini);
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index b570166..d0e62f6 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -1117,13 +1117,13 @@
 	return status;
 }
 
-static int __init init(void)
+static int __init nfnetlink_queue_init(void)
 {
 	
 	return init_or_cleanup(1);
 }
 
-static void __exit fini(void)
+static void __exit nfnetlink_queue_fini(void)
 {
 	init_or_cleanup(0);
 }
@@ -1133,5 +1133,5 @@
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_QUEUE);
 
-module_init(init);
-module_exit(fini);
+module_init(nfnetlink_queue_init);
+module_exit(nfnetlink_queue_fini);
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index 3cd2ac9..e54e577 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -62,7 +62,7 @@
 };
 
 
-static int __init init(void)
+static int __init xt_classify_init(void)
 {
 	int ret;
 
@@ -77,11 +77,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_classify_fini(void)
 {
 	xt_unregister_target(&classify_reg);
 	xt_unregister_target(&classify6_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_classify_init);
+module_exit(xt_classify_fini);
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 35448b8..60c375d 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -115,7 +115,7 @@
 	.me		= THIS_MODULE
 };
 
-static int __init init(void)
+static int __init xt_connmark_init(void)
 {
 	int ret;
 
@@ -132,11 +132,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_connmark_fini(void)
 {
 	xt_unregister_target(&connmark_reg);
 	xt_unregister_target(&connmark6_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_connmark_init);
+module_exit(xt_connmark_fini);
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index 73bdd5c..ee9c34e 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -145,7 +145,7 @@
 	.revision	= 0,
 };
 
-static int __init init(void)
+static int __init xt_mark_init(void)
 {
 	int err;
 
@@ -166,12 +166,12 @@
 	return err;
 }
 
-static void __exit fini(void)
+static void __exit xt_mark_fini(void)
 {
 	xt_unregister_target(&ipt_mark_reg_v0);
 	xt_unregister_target(&ipt_mark_reg_v1);
 	xt_unregister_target(&ip6t_mark_reg_v0);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_mark_init);
+module_exit(xt_mark_fini);
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 2873e1c..86ccceb 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -61,7 +61,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init xt_nfqueue_init(void)
 {
 	int ret;
 	ret = xt_register_target(&ipt_NFQ_reg);
@@ -83,12 +83,12 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_nfqueue_fini(void)
 {
 	xt_unregister_target(&arpt_NFQ_reg);
 	xt_unregister_target(&ip6t_NFQ_reg);
 	xt_unregister_target(&ipt_NFQ_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_nfqueue_init);
+module_exit(xt_nfqueue_fini);
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index cf2ebd7..98f4b53 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -52,7 +52,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init xt_notrack_init(void)
 {
 	int ret;
 
@@ -67,11 +67,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_notrack_fini(void)
 {
 	xt_unregister_target(&notrack6_reg);
 	xt_unregister_target(&notrack_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_notrack_init);
+module_exit(xt_notrack_fini);
diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c
index 2637724..197609c 100644
--- a/net/netfilter/xt_comment.c
+++ b/net/netfilter/xt_comment.c
@@ -45,7 +45,7 @@
 	.me		= THIS_MODULE
 };
 
-static int __init init(void)
+static int __init xt_comment_init(void)
 {
 	int ret;
 
@@ -60,11 +60,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_comment_fini(void)
 {
 	xt_unregister_match(&comment_match);
 	xt_unregister_match(&comment6_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_comment_init);
+module_exit(xt_comment_fini);
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 4985f5e..1396fe2 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -160,7 +160,7 @@
 	.me		= THIS_MODULE
 };
 
-static int __init init(void)
+static int __init xt_connbytes_init(void)
 {
 	int ret;
 	ret = xt_register_match(&connbytes_match);
@@ -173,11 +173,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_connbytes_fini(void)
 {
 	xt_unregister_match(&connbytes_match);
 	xt_unregister_match(&connbytes6_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_connbytes_init);
+module_exit(xt_connbytes_fini);
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index 7b16f1e..dc26a27 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -102,7 +102,7 @@
 	.me		= THIS_MODULE
 };
 
-static int __init init(void)
+static int __init xt_connmark_init(void)
 {
 	int ret;
 
@@ -118,11 +118,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_connmark_fini(void)
 {
 	xt_unregister_match(&connmark6_match);
 	xt_unregister_match(&connmark_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_connmark_init);
+module_exit(xt_connmark_fini);
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 65a8480..145489a 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -239,7 +239,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init xt_conntrack_init(void)
 {
 	int ret;
 	need_conntrack();
@@ -248,10 +248,10 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_conntrack_fini(void)
 {
 	xt_unregister_match(&conntrack_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_conntrack_init);
+module_exit(xt_conntrack_fini);
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index 2f331de..dfb10b6 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -164,7 +164,7 @@
 };
 
 
-static int __init init(void)
+static int __init xt_dccp_init(void)
 {
 	int ret;
 
@@ -191,12 +191,12 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_dccp_fini(void)
 {
 	xt_unregister_match(&dccp6_match);
 	xt_unregister_match(&dccp_match);
 	kfree(dccp_optbuf);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_dccp_init);
+module_exit(xt_dccp_fini);
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index 101f000..799c2a4 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -182,7 +182,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init xt_helper_init(void)
 {
 	int ret;
 	need_conntrack();
@@ -198,12 +198,12 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_helper_fini(void)
 {
 	xt_unregister_match(&helper_match);
 	xt_unregister_match(&helper6_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_helper_init);
+module_exit(xt_helper_fini);
 
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
index 38560ca..109132c 100644
--- a/net/netfilter/xt_length.c
+++ b/net/netfilter/xt_length.c
@@ -68,7 +68,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init xt_length_init(void)
 {
 	int ret;
 	ret = xt_register_match(&length_match);
@@ -81,11 +81,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_length_fini(void)
 {
 	xt_unregister_match(&length_match);
 	xt_unregister_match(&length6_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_length_init);
+module_exit(xt_length_fini);
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index e91c1a4..ce7fdb7 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -153,7 +153,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init xt_limit_init(void)
 {
 	int ret;
 	
@@ -168,11 +168,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_limit_fini(void)
 {
 	xt_unregister_match(&ipt_limit_reg);
 	xt_unregister_match(&limit6_reg);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_limit_init);
+module_exit(xt_limit_fini);
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
index f4defa2..356290f 100644
--- a/net/netfilter/xt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -62,7 +62,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init xt_mac_init(void)
 {
 	int ret;
 	ret = xt_register_match(&mac_match);
@@ -76,11 +76,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_mac_fini(void)
 {
 	xt_unregister_match(&mac_match);
 	xt_unregister_match(&mac6_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_mac_init);
+module_exit(xt_mac_fini);
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index ce0badf..8b385a3 100644
--- a/net/netfilter/xt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -69,7 +69,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init xt_mark_init(void)
 {
 	int ret;
 	ret = xt_register_match(&mark_match);
@@ -83,11 +83,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_mark_fini(void)
 {
 	xt_unregister_match(&mark_match);
 	xt_unregister_match(&mark6_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_mark_init);
+module_exit(xt_mark_fini);
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index 089f4f7..5fe4c9d 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -134,7 +134,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init xt_physdev_init(void)
 {
 	int ret;
 
@@ -149,11 +149,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_physdev_fini(void)
 {
 	xt_unregister_match(&physdev_match);
 	xt_unregister_match(&physdev6_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_physdev_init);
+module_exit(xt_physdev_fini);
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
index 8b8bca9..3ac703b 100644
--- a/net/netfilter/xt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -49,7 +49,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init xt_pkttype_init(void)
 {
 	int ret;
 	ret = xt_register_match(&pkttype_match);
@@ -63,11 +63,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_pkttype_fini(void)
 {
 	xt_unregister_match(&pkttype_match);
 	xt_unregister_match(&pkttype6_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_pkttype_init);
+module_exit(xt_pkttype_fini);
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c
index 5e31a4a..a80b7d13 100644
--- a/net/netfilter/xt_realm.c
+++ b/net/netfilter/xt_realm.c
@@ -49,15 +49,15 @@
 	.me		= THIS_MODULE
 };
 
-static int __init init(void)
+static int __init xt_realm_init(void)
 {
 	return xt_register_match(&realm_match);
 }
 
-static void __exit fini(void)
+static void __exit xt_realm_fini(void)
 {
 	xt_unregister_match(&realm_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_realm_init);
+module_exit(xt_realm_fini);
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index c6eb24a..34bd872 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -200,7 +200,7 @@
 	.me		= THIS_MODULE
 };
 
-static int __init init(void)
+static int __init xt_sctp_init(void)
 {
 	int ret;
 	ret = xt_register_match(&sctp_match);
@@ -214,11 +214,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_sctp_fini(void)
 {
 	xt_unregister_match(&sctp6_match);
 	xt_unregister_match(&sctp_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_sctp_init);
+module_exit(xt_sctp_fini);
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index e6c0be9..f9e304d 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -89,7 +89,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init xt_state_init(void)
 {
 	int ret;
 
@@ -106,11 +106,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_state_fini(void)
 {
 	xt_unregister_match(&state_match);
 	xt_unregister_match(&state6_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_state_init);
+module_exit(xt_state_fini);
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index 703d80f..79d9ea6 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -91,7 +91,7 @@
 	.me 		= THIS_MODULE
 };
 
-static int __init init(void)
+static int __init xt_string_init(void)
 {
 	int ret;
 
@@ -105,11 +105,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_string_fini(void)
 {
 	xt_unregister_match(&string_match);
 	xt_unregister_match(&string6_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_string_init);
+module_exit(xt_string_fini);
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index 70a8858..cf7d335c 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -112,7 +112,7 @@
 };
 
 
-static int __init init(void)
+static int __init xt_tcpmss_init(void)
 {
 	int ret;
 	ret = xt_register_match(&tcpmss_match);
@@ -126,11 +126,11 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_tcpmss_fini(void)
 {
 	xt_unregister_match(&tcpmss6_match);
 	xt_unregister_match(&tcpmss_match);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_tcpmss_init);
+module_exit(xt_tcpmss_fini);
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index 14a990e..1b61dac 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -238,7 +238,7 @@
 	.me		= THIS_MODULE,
 };
 
-static int __init init(void)
+static int __init xt_tcpudp_init(void)
 {
 	int ret;
 	ret = xt_register_match(&tcp_matchstruct);
@@ -268,7 +268,7 @@
 	return ret;
 }
 
-static void __exit fini(void)
+static void __exit xt_tcpudp_fini(void)
 {
 	xt_unregister_match(&udp6_matchstruct);
 	xt_unregister_match(&udp_matchstruct);
@@ -276,5 +276,5 @@
 	xt_unregister_match(&tcp_matchstruct);
 }
 
-module_init(init);
-module_exit(fini);
+module_init(xt_tcpudp_init);
+module_exit(xt_tcpudp_fini);
diff --git a/net/socket.c b/net/socket.c
index fcd77ea..b13042f 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -119,6 +119,9 @@
 static ssize_t sock_sendpage(struct file *file, struct page *page,
 			     int offset, size_t size, loff_t *ppos, int more);
 
+extern ssize_t generic_splice_sendpage(struct inode *inode, struct file *out,
+				size_t len, unsigned int flags);
+
 
 /*
  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
@@ -141,7 +144,8 @@
 	.fasync =	sock_fasync,
 	.readv =	sock_readv,
 	.writev =	sock_writev,
-	.sendpage =	sock_sendpage
+	.sendpage =	sock_sendpage,
+	.splice_write = generic_splice_sendpage,
 };
 
 /*
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c
index 3bbc810..c8e2103 100644
--- a/sound/oss/dmasound/dmasound_awacs.c
+++ b/sound/oss/dmasound/dmasound_awacs.c
@@ -2814,7 +2814,7 @@
 	struct device_node *io = NULL, *info = NULL;
 	int vol, res;
 
-	if (_machine != _MACH_Pmac)
+	if (!machine_is(powermac))
 		return -ENODEV;
 
 	awacs_subframe = 0;
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index aa57170..f0794ef 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -869,7 +869,7 @@
 
 	u32 layout_id = 0;
 
-	if (_machine != _MACH_Pmac)
+	if (!machine_is(powermac))
 		return -ENODEV;
 
 	chip->subframe = 0;