diff -Nru a/Documentation/basic_profiling.txt b/Documentation/basic_profiling.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/basic_profiling.txt	Tue Mar  4 23:48:44 2003
@@ -0,0 +1,48 @@
+These instructions are deliberately very basic. If you want something clever,
+go read the real docs ;-) Please don't add more stuff, but feel free to 
+correct my mistakes ;-)    (mbligh@aracnet.com)
+Thanks to John Levon, Dave Hansen, et al. for help writing this.
+
+<test> is the thing you're trying to measure.
+Make sure you have the correct System.map / vmlinux referenced!
+IMHO it's easier to use "make install" for linux and hack /sbin/installkernel
+to copy config files, system.map, vmlinux to /boot.
+
+Readprofile
+-----------
+You need a fixed readprofile command for 2.5 ... either get hold of
+a current version from:
+http://www.kernel.org/pub/linux/utils/util-linux/
+or get readprofile binary fixed for 2.5 / akpm's 2.5 patch from 
+ftp://ftp.kernel.org/pub/linux/kernel/people/mbligh/tools/readprofile/
+
+Add "profile=2" to the kernel command line.
+
+clear		readprofile -r
+		<test>
+dump output	readprofile -m /boot/System.map > captured_profile
+
+Oprofile
+--------
+get source (I use 0.5) from http://oprofile.sourceforge.net/
+add "idle=poll" to the kernel command line 
+Configure with CONFIG_PROFILING=y and CONFIG_OPROFILE=y & reboot on new kernel
+./configure --with-kernel-support
+make install
+
+One time setup (pick appropriate one for your CPU):
+P3		opcontrol --setup --vmlinux=/boot/vmlinux \
+		--ctr0-event=CPU_CLK_UNHALTED --ctr0-count=100000
+Athlon/x86-64	opcontrol --setup --vmlinux=/boot/vmlinux \
+		--ctr0-event=RETIRED_INSNS --ctr0-count=100000
+P4		opcontrol --setup --vmlinux=/boot/vmlinux \
+		--ctr0-event=GLOBAL_POWER_EVENTS \
+		--ctr0-unit-mask=1 --ctr0-count=100000
+
+start daemon	opcontrol --start-daemon
+clear		opcontrol --reset
+start		opcontrol --start
+		<test>
+stop		opcontrol --stop
+dump output	oprofpp -dl -i /boot/vmlinux  >  output_file
+
diff -Nru a/Documentation/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex
--- a/Documentation/cdrom/cdrom-standard.tex	Tue Feb  5 09:40:36 2002
+++ b/Documentation/cdrom/cdrom-standard.tex	Sat Mar  8 14:50:21 2003
@@ -758,11 +758,8 @@
 \subsection{$Struct\ file_operations\ cdrom_fops$}
 
 The contents of this structure were described in section~\ref{cdrom.c}.
-As already stated, this structure should be used to register block
-devices with the kernel:
-$$
-register_blkdev(major, <name>, \&cdrom_fops);
-$$
+A pointer to this structure is assigned to the $fops$ field
+of the $struct gendisk$.
 
 \subsection{$Int\ register_cdrom( struct\ cdrom_device_info\ * cdi)$}
 
diff -Nru a/Documentation/cpu-freq/core.txt b/Documentation/cpu-freq/core.txt
--- a/Documentation/cpu-freq/core.txt	Tue Feb  4 11:04:44 2003
+++ b/Documentation/cpu-freq/core.txt	Sat Mar  8 01:39:53 2003
@@ -35,6 +35,10 @@
 kernel "constant" loops_per_jiffy is updated on frequency changes
 here.
 
+Reference counting is done by cpufreq_get_cpu and cpufreq_put_cpu,
+which make sure that the cpufreq processor driver is correctly
+registered with the core, and will not be unloaded until
+cpufreq_put_cpu is called.
 
 2. CPUFreq notifiers
 ====================
diff -Nru a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt
--- a/Documentation/cpu-freq/cpu-drivers.txt	Sat Mar  1 08:56:11 2003
+++ b/Documentation/cpu-freq/cpu-drivers.txt	Sat Mar  8 01:39:53 2003
@@ -63,6 +63,9 @@
 
 cpufreq_driver.exit -		A pointer to a per-CPU cleanup function.
 
+cpufreq_driver.attr -		A pointer to a NULL-terminated list of
+				"struct freq_attr" which allow to
+				export values to sysfs.
 
 
 1.2 Per-CPU Initialization
diff -Nru a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt
--- a/Documentation/cpu-freq/user-guide.txt	Sat Mar  1 08:56:11 2003
+++ b/Documentation/cpu-freq/user-guide.txt	Sat Mar  8 01:39:53 2003
@@ -114,9 +114,9 @@
 ------------------------------
 
 The preferred interface is located in the sysfs filesystem. If you
-mounted it at /sys, the cpufreq interface is located in the 
-cpu-device directory (e.g. /sys/devices/sys/cpu0/ for the first
-CPU).
+mounted it at /sys, the cpufreq interface is located in a subdirectory
+"cpufreq" within the cpu-device directory
+(e.g. /sys/devices/sys/cpu0/cpufreq/ for the first CPU).
 
 cpuinfo_min_freq :		this file shows the minimum operating
 				frequency the processor can run at(in kHz) 
@@ -125,7 +125,7 @@
 scaling_driver :		this file shows what cpufreq driver is
 				used to set the frequency on this CPU
 
-available_scaling_governors :	this file shows the CPUfreq governors
+scaling_available_governors :	this file shows the CPUfreq governors
 				available in this kernel. You can see the
 				currently activated governor in
 
diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt
--- a/Documentation/crypto/api-intro.txt	Tue Jan 14 03:45:05 2003
+++ b/Documentation/crypto/api-intro.txt	Sat Mar  8 15:26:02 2003
@@ -38,9 +38,8 @@
 Compressors.  The compression algorithms especially seem to be performing
 very well so far.
 
-An asynchronous scheduling interface is in planning but not yet
-implemented, as we need to further analyze the requirements of all of
-the possible hardware scenarios (e.g. IPsec NIC offload).
+Support for hardware crypto devices via an asynchronous interface is
+under development.
 
 Here's an example of how to use the API:
 
@@ -87,8 +86,8 @@
 
 DEVELOPER NOTES
 
-None of this code should be called from hardirq context, only softirq and
-user contexts.
+Transforms may only be allocated in user context, and cryptographic
+methods may only be called from softirq and user contexts.
 
 When using the API for ciphers, performance will be optimal if each
 scatterlist contains data which is a multiple of the cipher's block
@@ -137,16 +136,11 @@
 list, see:
 http://samba.org/~jamesm/crypto/
 
-Ongoing development discussion may also be found on
-kerneli cryptoapi-devel, 
-see http://www.kerneli.org/mailman/listinfo/cryptoapi-devel
-
 
 AUTHORS
 
 James Morris
 David S. Miller
-Jean-Francois Dive (SHA1 algorithm module)
 
 
 CREDITS
@@ -191,6 +185,10 @@
   Matthew Skala (Twofish)
   Dag Arne Osvik (Serpent)
   Brian Gladman (AES)
+
+
+SHA1 algorithm contributors:
+  Jean-Francois Dive
   
 DES algorithm contributors:
   Raimar Falke
@@ -215,6 +213,8 @@
   Herbert Valerio Riedel
   Kyle McMartin
   Adam J. Richter
+
+Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
 
 Please send any credits updates or corrections to:
 James Morris <jmorris@intercode.com.au>
diff -Nru a/Documentation/ia64/fsys.txt b/Documentation/ia64/fsys.txt
--- a/Documentation/ia64/fsys.txt	Mon Jan 27 10:57:50 2003
+++ b/Documentation/ia64/fsys.txt	Wed Feb 12 00:11:32 2003
@@ -4,7 +4,7 @@
 		-----------------------------------
 
 		        Started: 13-Jan-2003
-		    Last update: 24-Jan-2003
+		    Last update: 11-Feb-2003
 
 	              David Mosberger-Tang
 		      <davidm@hpl.hp.com>
@@ -42,9 +42,9 @@
     can disable interrupts and avoid all other interruption-sources
     to avoid preemption)
 
-  - neither the memory nor the register stack can be trusted while
+  - neither the memory-stack nor the register-stack can be trusted while
     in fsys-mode (they point to the user-level stacks, which may
-    be invalid)
+    be invalid, or completely bogus addresses)
 
 In summary, fsys-mode is much more similar to running in user-mode
 than it is to running in kernel-mode.  Of course, given that the
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Tue Feb 18 10:57:56 2003
+++ b/MAINTAINERS	Thu Mar  6 09:07:03 2003
@@ -641,7 +641,7 @@
 P:	Rui Sousa	
 M:	rui.p.m.sousa@clix.pt	
 L:	emu10k1-devel@lists.sourceforge.net
-W:	http://opensource.creative.com/
+W:	http://sourceforge.net/projects/emu10k1/
 S:	Maintained
 
 ETHEREXPRESS-16 NETWORK DRIVER
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Tue Mar  4 19:11:15 2003
+++ b/Makefile	Tue Mar 11 04:26:10 2003
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 64
-EXTRAVERSION =
+EXTRAVERSION = bk6
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -107,6 +107,11 @@
 
 #	For now, leave verbose as default
 
+ifdef V
+  ifeq ("$(origin V)", "command line")
+    KBUILD_VERBOSE = $(V)
+  endif
+endif
 ifndef KBUILD_VERBOSE
   KBUILD_VERBOSE = 1
 endif
@@ -322,13 +327,14 @@
 #	set -e makes the rule exit immediately on error
 
 define rule_vmlinux__
-	set -e;								\
+	set -e								\
 	$(if $(filter .tmp_kallsyms%,$^),,				\
 	  echo '  GEN     .version';					\
 	  . $(srctree)/scripts/mkversion > .tmp_version;		\
 	  mv -f .tmp_version .version;					\
 	  $(MAKE) $(build)=init;					\
 	)
+	set -e								\
 	$(call cmd,vmlinux__);						\
 	echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
 endef
diff -Nru a/arch/alpha/Kconfig b/arch/alpha/Kconfig
--- a/arch/alpha/Kconfig	Tue Feb 18 15:57:50 2003
+++ b/arch/alpha/Kconfig	Sat Mar  8 14:50:37 2003
@@ -15,10 +15,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 
diff -Nru a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
--- a/arch/alpha/kernel/core_marvel.c	Fri Feb 14 05:51:04 2003
+++ b/arch/alpha/kernel/core_marvel.c	Sat Feb 15 04:55:38 2003
@@ -1076,7 +1076,7 @@
 	/*
 	 * Fill it in.
 	 */
-	agp->type = 0 /* FIXME: ALPHA_CORE_AGP */;
+	agp->type = ALPHA_CORE_AGP;
 	agp->hose = hose;
 	agp->private = NULL;
 	agp->ops = &marvel_agp_ops;
diff -Nru a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c
--- a/arch/alpha/kernel/core_titan.c	Fri Jan 17 11:59:36 2003
+++ b/arch/alpha/kernel/core_titan.c	Sat Feb 15 04:55:54 2003
@@ -764,7 +764,7 @@
 	/*
 	 * Fill it in.
 	 */
-	agp->type = 0 /* FIXME: ALPHA_CORE_AGP */;
+	agp->type = ALPHA_CORE_AGP;
 	agp->hose = hose;
 	agp->private = port;
 	agp->ops = &titan_agp_ops;
diff -Nru a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
--- a/arch/alpha/kernel/irq.c	Tue Jan 21 05:42:33 2003
+++ b/arch/alpha/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -515,6 +515,7 @@
 #endif
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 #ifdef CONFIG_SMP
 	seq_puts(p, "           ");
@@ -525,9 +526,10 @@
 #endif
 
 	for (i = 0; i < ACTUAL_NR_IRQS; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto unlock;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -538,15 +540,18 @@
 #endif
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
 		seq_printf(p, "  %c%s",
-			     (action->flags & SA_INTERRUPT)?'+':' ',
-			     action->name);
+			(action->flags & SA_INTERRUPT)?'+':' ',
+			action->name);
 
 		for (action=action->next; action; action = action->next) {
 			seq_printf(p, ", %c%s",
-				     (action->flags & SA_INTERRUPT)?'+':' ',
-				     action->name);
+				  (action->flags & SA_INTERRUPT)?'+':' ',
+				   action->name);
 		}
+
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 #if CONFIG_SMP
 	seq_puts(p, "IPI: ");
diff -Nru a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
--- a/arch/alpha/kernel/pci.c	Wed Feb 26 17:20:09 2003
+++ b/arch/alpha/kernel/pci.c	Thu Mar  6 11:08:47 2003
@@ -393,26 +393,36 @@
 }
 
 static void __init
+pcibios_claim_one_bus(struct pci_bus *b)
+{
+	struct list_head *ld;
+	struct pci_bus *child_bus;
+
+	for (ld = b->devices.next; ld != &b->devices; ld = ld->next) {
+		struct pci_dev *dev = pci_dev_b(ld);
+		int i;
+
+		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+			struct resource *r = &dev->resource[i];
+
+			if (r->parent || !r->start || !r->flags)
+				continue;
+			pci_claim_resource(dev, i);
+		}
+	}
+
+	list_for_each_entry(child_bus, &b->children, node)
+		pcibios_claim_one_bus(child_bus);
+}
+
+static void __init
 pcibios_claim_console_setup(void)
 {
 	struct list_head *lb;
 
 	for(lb = pci_root_buses.next; lb != &pci_root_buses; lb = lb->next) {
 		struct pci_bus *b = pci_bus_b(lb);
-		struct list_head *ld;
-
-		for (ld = b->devices.next; ld != &b->devices; ld = ld->next) {
-			struct pci_dev *dev = pci_dev_b(ld);
-			int i;
-
-			for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-				struct resource *r = &dev->resource[i];
-
-				if (r->parent || !r->start || !r->flags)
-					continue;
-				pci_claim_resource(dev, i);
-			}
-		}
+		pcibios_claim_one_bus(b);
 	}
 }
 
diff -Nru a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
--- a/arch/alpha/kernel/sys_nautilus.c	Thu Jan 23 10:59:07 2003
+++ b/arch/alpha/kernel/sys_nautilus.c	Sun Mar  2 17:34:25 2003
@@ -78,6 +78,8 @@
 nautilus_kill_arch(int mode)
 {
 	struct pci_bus *bus = pci_isa_hose->bus;
+	u32 pmuport;
+	int off;
 
 	switch (mode) {
 	case LINUX_REBOOT_CMD_RESTART:
@@ -92,14 +94,18 @@
 		break;
 
 	case LINUX_REBOOT_CMD_POWER_OFF:
-		{
-			u32 pmuport;
-			pci_bus_read_config_dword(bus, 0x88, 0x10, &pmuport);
-			pmuport &= 0xfffe;
-			outl(0xffff, pmuport); /* clear pending events */
-			outw(0x2000, pmuport+4); /* power off */
-			/* NOTREACHED */
+		/* Assume M1543C */
+		off = 0x2000;		/* SLP_TYPE = 0, SLP_EN = 1 */
+		pci_bus_read_config_dword(bus, 0x88, 0x10, &pmuport);
+		if (!pmuport) {
+			/* M1535D/D+ */
+			off = 0x3400;	/* SLP_TYPE = 5, SLP_EN = 1 */
+			pci_bus_read_config_dword(bus, 0x88, 0xe0, &pmuport);
 		}
+		pmuport &= 0xfffe;
+		outw(0xffff, pmuport);	/* Clear pending events. */
+		outw(off, pmuport + 4);
+		/* NOTREACHED */
 		break;
 	}
 }
diff -Nru a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
--- a/arch/alpha/mm/fault.c	Mon Jan  6 10:11:27 2003
+++ b/arch/alpha/mm/fault.c	Thu Mar  6 08:19:03 2003
@@ -232,11 +232,11 @@
 	else {
 		/* Synchronize this task's top level page-table
 		   with the "reference" page table from init.  */
-		long offset = __pgd_offset(address);
+		long index = pgd_index(address);
 		pgd_t *pgd, *pgd_k;
 
-		pgd = current->active_mm->pgd + offset;
-		pgd_k = swapper_pg_dir + offset;
+		pgd = current->active_mm->pgd + index;
+		pgd_k = swapper_pg_dir + index;
 		if (!pgd_present(*pgd) && pgd_present(*pgd_k)) {
 			pgd_val(*pgd) = pgd_val(*pgd_k);
 			return;
diff -Nru a/arch/alpha/oprofile/op_model_ev4.c b/arch/alpha/oprofile/op_model_ev4.c
--- a/arch/alpha/oprofile/op_model_ev4.c	Tue Feb 18 19:05:36 2003
+++ b/arch/alpha/oprofile/op_model_ev4.c	Fri Mar  7 20:31:28 2003
@@ -34,7 +34,7 @@
 	   for these "disabled" counter overflows are ignored by the
 	   interrupt handler.
 
-	   This is most irritating, becuase the hardware *can* enable and
+	   This is most irritating, because the hardware *can* enable and
 	   disable the interrupts for these counters independently, but the
 	   wrperfmon interface doesn't allow it.  */
 
diff -Nru a/arch/alpha/vmlinux.lds.S b/arch/alpha/vmlinux.lds.S
--- a/arch/alpha/vmlinux.lds.S	Wed Jan 15 19:04:27 2003
+++ b/arch/alpha/vmlinux.lds.S	Fri Mar  7 00:58:06 2003
@@ -63,6 +63,13 @@
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
 
+  . = ALIGN(8);
+  .con_initcall.init : {
+	__con_initcall_start = .;
+	*(.con_initcall.init)
+	__con_initcall_end = .;
+  }
+
   . = ALIGN(64);
   __per_cpu_start = .;
   .data.percpu : { *(.data.percpu) }
diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig
--- a/arch/arm/Kconfig	Sat Feb 15 01:34:08 2003
+++ b/arch/arm/Kconfig	Sat Mar  8 14:50:37 2003
@@ -20,10 +20,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config EISA
 	bool
 	---help---
@@ -534,15 +530,63 @@
 	  written) to implement the policy. If you don't understand what this
 	  is all about, it's safe to say 'N'.
 
+
+# CPUfreq on SA11x0 is special -- it _needs_ the userspace governor
+
+config CPU_FREQ_SA1100
+	bool
+	depends on CPU_FREQ && SA1100_LART
+	default y
+
+config CPU_FREQ_SA1110
+	bool
+	depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3)
+	default y
+
+if (CPU_FREQ_SA1100 || CPU_FREQ_SA1110)
+
+config CPU_FREQ_GOV_USERSPACE
+ 	bool
+ 	depends on CPU_FREQ
+ 	default y
+
 config CPU_FREQ_24_API
 	bool
-	depends on CPU_FREQ
+	depends on CPU_FREQ_GOV_USERSPACE && SYSCTL
 	default y
 
 config CPU_FREQ_PROC_INTF
-	tristate
-	depends on CPU_FREQ
+	tristate "/proc/cpufreq interface (deprecated)"
+	depends on CPU_FREQ && PROC_FS
+	help
+	  This enables the /proc/cpufreq interface for controlling
+	  CPUFreq. Please note that it is recommended to use the sysfs
+	  interface instead (which is built automatically).
+
+	  For details, take a look at linux/Documentation/cpufreq.
+
+	  If in doubt, say N.
+
+endif
+
+# CPUfreq on Integrator can use the generic cpufreq core
+
+config CPU_FREQ_INTEGRATOR
+	tristate "CPUfreq driver for ARM Integrator CPUs"
+	depends on ARCH_INTEGRATOR && CPU_FREQ
 	default y
+	help
+	  This enables the CPUfreq driver for ARM Integrator CPUs.
+
+	  For details, take a look at linux/Documentation/cpufreq.
+
+	  If in doubt, say Y.
+
+if (CPU_FREQ_INTEGRATOR)
+
+source "drivers/cpufreq/Kconfig"
+
+endif
 
 source "drivers/pci/Kconfig"
 
diff -Nru a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
--- a/arch/arm/common/sa1111.c	Mon Feb 17 12:43:37 2003
+++ b/arch/arm/common/sa1111.c	Thu Mar  6 08:08:19 2003
@@ -743,25 +743,23 @@
 static int sa1111_suspend(struct device *dev, u32 state, u32 level)
 {
 	struct sa1111 *sachip = dev_get_drvdata(dev);
+	struct sa1111_save_data *save;
 	unsigned long flags;
 	char *base;
 
+	if (!dev->saved_state && level == SUSPEND_NOTIFY)
+		dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
+	if (!dev->saved_state)
+		return -ENOMEM;
+
+	save = (struct sa1111_save_data *)dev->saved_state;
+
+	spin_lock_irqsave(&sachip->lock, flags);
+
 	/*
 	 * Save state.
 	 */
-	if (level == SUSPEND_SAVE_STATE ||
-	    level == SUSPEND_DISABLE ||
-	    level == SUSPEND_POWER_DOWN) {
-		struct sa1111_save_data *save;
-
-		if (!dev->saved_state)
-			dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
-		if (!dev->saved_state)
-			return -ENOMEM;
-
-		save = (struct sa1111_save_data *)dev->saved_state;
-
-		spin_lock_irqsave(&sachip->lock, flags);
+	if (level == SUSPEND_SAVE_STATE) {
 		base = sachip->base;
 		save->skcr     = sa1111_readl(base + SA1111_SKCR);
 		save->skpcr    = sa1111_readl(base + SA1111_SKPCR);
@@ -779,26 +777,21 @@
 		save->wakepol1 = sa1111_readl(base + SA1111_WAKEPOL1);
 		save->wakeen0  = sa1111_readl(base + SA1111_WAKEEN0);
 		save->wakeen1  = sa1111_readl(base + SA1111_WAKEEN1);
-		spin_unlock_irqrestore(&sachip->lock, flags);
 	}
 
 	/*
 	 * Disable.
 	 */
-	if (level == SUSPEND_DISABLE && state == 4) {
-		unsigned int val;
-
-		spin_lock_irqsave(&sachip->lock, flags);
-		base = sachip->base;
-
-		sa1111_writel(0, base + SA1111_SKPWM0);
-		sa1111_writel(0, base + SA1111_SKPWM1);
-		val = sa1111_readl(base + SA1111_SKCR);
-		sa1111_writel(val | SKCR_SLEEP, base + SA1111_SKCR);
+	if (level == SUSPEND_POWER_DOWN && state == 4) {
+		unsigned int val = sa1111_readl(sachip->base + SA1111_SKCR);
 
-		spin_unlock_irqrestore(&sachip->lock, flags);
+		sa1111_writel(val | SKCR_SLEEP, sachip->base + SA1111_SKCR);
+		sa1111_writel(0, sachip->base + SA1111_SKPWM0);
+		sa1111_writel(0, sachip->base + SA1111_SKPWM1);
 	}
 
+	spin_unlock_irqrestore(&sachip->lock, flags);
+
 	return 0;
 }
 
@@ -819,17 +812,15 @@
 	unsigned long flags, id;
 	char *base;
 
-	if (level != RESUME_RESTORE_STATE && level != RESUME_ENABLE)
-		return 0;
-
 	save = (struct sa1111_save_data *)dev->saved_state;
 	if (!save)
 		return 0;
 
-	dev->saved_state = NULL;
+	spin_lock_irqsave(&sachip->lock, flags);
 
 	/*
 	 * Ensure that the SA1111 is still here.
+	 * FIXME: shouldn't do this here.
 	 */
 	id = sa1111_readl(sachip->base + SA1111_SKID);
 	if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
@@ -839,29 +830,42 @@
 		return 0;
 	}
 
-	spin_lock_irqsave(&sachip->lock, flags);
-	sa1111_wake(sachip);
+	/*
+	 * First of all, wake up the chip.
+	 */
+	if (level == RESUME_POWER_ON) {
+		sa1111_wake(sachip);
+
+		sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0);
+		sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1);
+	}
+
+	if (level == RESUME_RESTORE_STATE) {
+		base = sachip->base;
+		sa1111_writel(save->skcr,     base + SA1111_SKCR);
+		sa1111_writel(save->skpcr,    base + SA1111_SKPCR);
+		sa1111_writel(save->skcdr,    base + SA1111_SKCDR);
+		sa1111_writel(save->skaud,    base + SA1111_SKAUD);
+		sa1111_writel(save->skpwm0,   base + SA1111_SKPWM0);
+		sa1111_writel(save->skpwm1,   base + SA1111_SKPWM1);
+
+		base = sachip->base + SA1111_INTC;
+		sa1111_writel(save->intpol0,  base + SA1111_INTPOL0);
+		sa1111_writel(save->intpol1,  base + SA1111_INTPOL1);
+		sa1111_writel(save->inten0,   base + SA1111_INTEN0);
+		sa1111_writel(save->inten1,   base + SA1111_INTEN1);
+		sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0);
+		sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1);
+		sa1111_writel(save->wakeen0,  base + SA1111_WAKEEN0);
+		sa1111_writel(save->wakeen1,  base + SA1111_WAKEEN1);
+	}
 
-	base = sachip->base;
-	sa1111_writel(save->skcr,     base + SA1111_SKCR);
-	sa1111_writel(save->skpcr,    base + SA1111_SKPCR);
-	sa1111_writel(save->skcdr,    base + SA1111_SKCDR);
-	sa1111_writel(save->skaud,    base + SA1111_SKAUD);
-	sa1111_writel(save->skpwm0,   base + SA1111_SKPWM0);
-	sa1111_writel(save->skpwm1,   base + SA1111_SKPWM1);
-
-	base = sachip->base + SA1111_INTC;
-	sa1111_writel(save->intpol0,  base + SA1111_INTPOL0);
-	sa1111_writel(save->intpol1,  base + SA1111_INTPOL1);
-	sa1111_writel(save->inten0,   base + SA1111_INTEN0);
-	sa1111_writel(save->inten1,   base + SA1111_INTEN1);
-	sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0);
-	sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1);
-	sa1111_writel(save->wakeen0,  base + SA1111_WAKEEN0);
-	sa1111_writel(save->wakeen1,  base + SA1111_WAKEEN1);
 	spin_unlock_irqrestore(&sachip->lock, flags);
 
-	kfree(save);
+	if (level == RESUME_ENABLE) {
+		dev->saved_state = NULL;
+		kfree(save);
+	}
 
 	return 0;
 }
diff -Nru a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
--- a/arch/arm/kernel/Makefile	Mon Feb  3 14:19:35 2003
+++ b/arch/arm/kernel/Makefile	Thu Mar  6 07:59:42 2003
@@ -16,6 +16,7 @@
 obj-		:=
 
 obj-$(CONFIG_APM)		+= apm.o
+obj-$(CONFIG_PM)		+= pm.o
 obj-$(CONFIG_ARCH_ACORN)	+= ecard.o time-acorn.o
 obj-$(CONFIG_ARCH_CLPS7500)	+= time-acorn.o
 obj-$(CONFIG_FOOTBRIDGE)	+= isa.o
diff -Nru a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/kernel/apm.c	Thu Mar  6 07:59:42 2003
@@ -0,0 +1,573 @@
+/*
+ * bios-less APM driver for ARM Linux 
+ *  Jamey Hicks <jamey@crl.dec.com>
+ *  adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com)
+ *
+ * APM 1.2 Reference:
+ *   Intel Corporation, Microsoft Corporation. Advanced Power Management
+ *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
+ *
+ * [This document is available from Microsoft at:
+ *    http://www.microsoft.com/hwdev/busbios/amp_12.htm]
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/apm_bios.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+
+#include <asm/system.h>
+
+/*
+ * The apm_bios device is one of the misc char devices.
+ * This is its minor number.
+ */
+#define APM_MINOR_DEV	134
+
+/*
+ * See Documentation/Config.help for the configuration options.
+ *
+ * Various options can be changed at boot time as follows:
+ * (We allow underscores for compatibility with the modules code)
+ *	apm=on/off			enable/disable APM
+ */
+
+/*
+ * Maximum number of events stored
+ */
+#define APM_MAX_EVENTS		20
+
+/*
+ * The per-file APM data
+ */
+struct apm_user {
+	struct list_head	list;
+
+	int			suser: 1;
+	int			writer: 1;
+	int			reader: 1;
+	int			suspend_wait: 1;
+	int			suspend_result;
+
+	int			suspends_pending;
+	int			standbys_pending;
+	unsigned int		suspends_read;
+	unsigned int		standbys_read;
+
+	int			event_head;
+	int			event_tail;
+	apm_event_t		events[APM_MAX_EVENTS];
+};
+
+/*
+ * Local variables
+ */
+static int suspends_pending;
+static int standbys_pending;
+static int apm_disabled;
+
+static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
+
+/*
+ * This is a list of everyone who has opened /dev/apm_bios
+ */
+static spinlock_t user_list_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(apm_user_list);
+
+/*
+ * The kapmd info.
+ */
+static struct task_struct *kapmd;
+static DECLARE_COMPLETION(kapmd_exit);
+
+static const char driver_version[] = "1.13";	/* no spaces */
+
+/*
+ * This structure gets filled in by the machine specific 'get_power_status'
+ * implementation.  Any fields which are not set default to a safe value.
+ */
+struct apm_power_info {
+	unsigned char	ac_line_status;
+	unsigned char	battery_status;
+	unsigned char	battery_flag;
+	unsigned char	battery_life;
+	int		time;
+	int		units;
+};
+
+/*
+ * Compatibility cruft until the IPAQ people move over to the new
+ * interface.
+ */
+static void __apm_get_power_status(struct apm_power_info *info)
+{
+#if 0 && defined(CONFIG_SA1100_H3600) && defined(CONFIG_TOUCHSCREEN_H3600)
+	extern int h3600_apm_get_power_status(u_char *, u_char *, u_char *,
+					      u_char *, u_short *);
+
+	if (machine_is_h3600()) {
+		int dx;
+		h3600_apm_get_power_status(&info->ac_line_status,
+				&info->battery_status, &info->battery_flag,
+				&info->battery_life, &dx);
+		info->time = dx & 0x7fff;
+		info->units = dx & 0x8000 ? 0 : 1;
+	}
+#endif
+}
+
+/*
+ * This allows machines to provide their own "apm get power status" function.
+ */
+void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
+EXPORT_SYMBOL(apm_get_power_status);
+
+static int queue_empty(struct apm_user *as)
+{
+	return as->event_head == as->event_tail;
+}
+
+static apm_event_t get_queued_event(struct apm_user *as)
+{
+	as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+	return as->events[as->event_tail];
+}
+
+static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+{
+	as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
+	if (as->event_head == as->event_tail) {
+		static int notified;
+
+		if (notified++ == 0)
+		    printk(KERN_ERR "apm: an event queue overflowed\n");
+		as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+	}
+	as->events[as->event_head] = event;
+
+	if (!as->suser || !as->writer)
+		return;
+
+	switch (event) {
+	case APM_SYS_SUSPEND:
+	case APM_USER_SUSPEND:
+		as->suspends_pending++;
+		suspends_pending++;
+		break;
+
+	case APM_SYS_STANDBY:
+	case APM_USER_STANDBY:
+		as->standbys_pending++;
+		standbys_pending++;
+		break;
+	}
+}
+
+static void queue_event(apm_event_t event, struct apm_user *sender)
+{
+	struct list_head *l;
+
+	spin_lock(&user_list_lock);
+	list_for_each(l, &apm_user_list) {
+		struct apm_user *as = list_entry(l, struct apm_user, list);
+
+		if (as != sender && as->reader)
+			queue_event_one_user(as, event);
+	}
+	spin_unlock(&user_list_lock);
+	wake_up_interruptible(&apm_waitqueue);
+}
+
+/* defined in pm.c */
+extern int suspend(void);
+
+static int apm_suspend(void)
+{
+	struct list_head *l;
+	int err = suspend();
+
+	/*
+	 * Anyone on the APM queues will think we're still suspended.
+	 * Send a message so everyone knows we're now awake again.
+	 */
+	queue_event(APM_NORMAL_RESUME, NULL);
+
+	/*
+	 * Finally, wake up anyone who is sleeping on the suspend.
+	 */
+	spin_lock(&user_list_lock);
+	list_for_each(l, &apm_user_list) {
+		struct apm_user *as = list_entry(l, struct apm_user, list);
+
+		as->suspend_result = err;
+		as->suspend_wait = 0;
+	}
+	spin_unlock(&user_list_lock);
+
+	wake_up_interruptible(&apm_suspend_waitqueue);
+	return err;
+}
+
+static ssize_t apm_read(struct file *fp, char *buf, size_t count, loff_t *ppos)
+{
+	struct apm_user *as = fp->private_data;
+	apm_event_t event;
+	int i = count, ret = 0, nonblock = fp->f_flags & O_NONBLOCK;
+
+	if (count < sizeof(apm_event_t))
+		return -EINVAL;
+
+	if (queue_empty(as) && nonblock)
+		return -EAGAIN;
+
+	wait_event_interruptible(apm_waitqueue, !queue_empty(as));
+
+	while ((i >= sizeof(event)) && !queue_empty(as)) {
+		event = get_queued_event(as);
+		printk("  apm_read: event=%d\n", event);
+
+		ret = -EFAULT;
+		if (copy_to_user(buf, &event, sizeof(event)))
+			break;
+
+		switch (event) {
+		case APM_SYS_SUSPEND:
+		case APM_USER_SUSPEND:
+			as->suspends_read++;
+			break;
+
+		case APM_SYS_STANDBY:
+		case APM_USER_STANDBY:
+			as->standbys_read++;
+			break;
+		}
+
+		buf += sizeof(event);
+		i -= sizeof(event);
+	}
+
+	if (i < count)
+		ret = count - i;
+
+	return ret;
+}
+
+static unsigned int apm_poll(struct file *fp, poll_table * wait)
+{
+	struct apm_user * as = fp->private_data;
+
+	poll_wait(fp, &apm_waitqueue, wait);
+	return queue_empty(as) ? 0 : POLLIN | POLLRDNORM;
+}
+
+/*
+ * apm_ioctl - handle APM ioctl
+ *
+ * APM_IOC_SUSPEND
+ *   This IOCTL is overloaded, and performs two functions.  It is used to:
+ *     - initiate a suspend
+ *     - acknowledge a suspend read from /dev/apm_bios.
+ *   Only when everyone who has opened /dev/apm_bios with write permission
+ *   has acknowledge does the actual suspend happen.
+ */
+static int
+apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
+{
+	struct apm_user *as = filp->private_data;
+	int err = -EINVAL;
+
+	if (!as->suser || !as->writer)
+		return -EPERM;
+
+	switch (cmd) {
+	case APM_IOC_STANDBY:
+		break;
+
+	case APM_IOC_SUSPEND:
+		/*
+		 * If we read a suspend command from /dev/apm_bios,
+		 * then the corresponding APM_IOC_SUSPEND ioctl is
+		 * interpreted as an acknowledge.
+		 */
+		if (as->suspends_read > 0) {
+			as->suspends_read--;
+			as->suspends_pending--;
+			suspends_pending--;
+		} else {
+			queue_event(APM_USER_SUSPEND, as);
+		}
+
+		/*
+		 * If there are outstanding suspend requests for other
+		 * people on /dev/apm_bios, we must sleep for them.
+		 * Last one to bed turns the lights out.
+		 */
+		if (suspends_pending > 0) {
+			as->suspend_wait = 1;
+			err = wait_event_interruptible(apm_suspend_waitqueue,
+						 as->suspend_wait == 0);
+			if (err == 0)
+				err = as->suspend_result;
+		} else {			
+			err = apm_suspend();
+		}
+		break;
+	}
+
+	return err;
+}
+
+static int apm_release(struct inode * inode, struct file * filp)
+{
+	struct apm_user *as = filp->private_data;
+	filp->private_data = NULL;
+
+	spin_lock(&user_list_lock);
+	list_del(&as->list);
+	spin_unlock(&user_list_lock);
+
+	/*
+	 * We are now unhooked from the chain.  As far as new
+	 * events are concerned, we no longer exist.  However, we
+	 * need to balance standbys_pending and suspends_pending,
+	 * which means the possibility of sleeping.
+	 */
+	if (as->standbys_pending > 0) {
+		standbys_pending -= as->standbys_pending;
+//		if (standbys_pending <= 0)
+//			standby();
+	}
+	if (as->suspends_pending > 0) {
+		suspends_pending -= as->suspends_pending;
+		if (suspends_pending <= 0)
+			apm_suspend();
+	}
+
+	kfree(as);
+	return 0;
+}
+
+static int apm_open(struct inode * inode, struct file * filp)
+{
+	struct apm_user *as;
+
+	as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
+	if (as) {
+		memset(as, 0, sizeof(*as));
+
+		/*
+		 * XXX - this is a tiny bit broken, when we consider BSD
+		 * process accounting. If the device is opened by root, we
+		 * instantly flag that we used superuser privs. Who knows,
+		 * we might close the device immediately without doing a
+		 * privileged operation -- cevans
+		 */
+		as->suser = capable(CAP_SYS_ADMIN);
+		as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
+		as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
+
+		spin_lock(&user_list_lock);
+		list_add(&as->list, &apm_user_list);
+		spin_unlock(&user_list_lock);
+
+		filp->private_data = as;
+	}
+
+	return as ? 0 : -ENOMEM;
+}
+
+static struct file_operations apm_bios_fops = {
+	owner:		THIS_MODULE,
+	read:		apm_read,
+	poll:		apm_poll,
+	ioctl:		apm_ioctl,
+	open:		apm_open,
+	release:	apm_release,
+};
+
+static struct miscdevice apm_device = {
+	minor:		APM_MINOR_DEV,
+	name:		"apm_bios",
+	fops:		&apm_bios_fops
+};
+
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Arguments, with symbols from linux/apm_bios.h.
+ *
+ *   0) Linux driver version (this will change if format changes)
+ *   1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
+ *   2) APM flags from APM Installation Check (0x00):
+ *	bit 0: APM_16_BIT_SUPPORT
+ *	bit 1: APM_32_BIT_SUPPORT
+ *	bit 2: APM_IDLE_SLOWS_CLOCK
+ *	bit 3: APM_BIOS_DISABLED
+ *	bit 4: APM_BIOS_DISENGAGED
+ *   3) AC line status
+ *	0x00: Off-line
+ *	0x01: On-line
+ *	0x02: On backup power (BIOS >= 1.1 only)
+ *	0xff: Unknown
+ *   4) Battery status
+ *	0x00: High
+ *	0x01: Low
+ *	0x02: Critical
+ *	0x03: Charging
+ *	0x04: Selected battery not present (BIOS >= 1.2 only)
+ *	0xff: Unknown
+ *   5) Battery flag
+ *	bit 0: High
+ *	bit 1: Low
+ *	bit 2: Critical
+ *	bit 3: Charging
+ *	bit 7: No system battery
+ *	0xff: Unknown
+ *   6) Remaining battery life (percentage of charge):
+ *	0-100: valid
+ *	-1: Unknown
+ *   7) Remaining battery life (time units):
+ *	Number of remaining minutes or seconds
+ *	-1: Unknown
+ *   8) min = minutes; sec = seconds
+ */
+static int apm_get_info(char *buf, char **start, off_t fpos, int length)
+{
+	struct apm_power_info info;
+	char *units;
+	int ret;
+
+	info.ac_line_status = 0xff;
+	info.battery_status = 0xff;
+	info.battery_flag   = 0xff;
+	info.battery_life   = 255;
+	info.time	    = -1;
+	info.units	    = -1;
+
+	if (apm_get_power_status)
+		apm_get_power_status(&info);
+
+	switch (info.units) {
+	default:	units = "?";	break;
+	case 0: 	units = "min";	break;
+	case 1: 	units = "sec";	break;
+	}
+
+	ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+		     driver_version, APM_32_BIT_SUPPORT,
+		     info.ac_line_status, info.battery_status,
+		     info.battery_flag, info.battery_life,
+		     info.time, units);
+
+ 	return ret;
+}
+#endif
+
+#if 0
+static int kapmd(void *startup)
+{
+	struct task_struct *tsk = current;
+
+	daemonize();
+	strcpy(tsk->comm, "kapmd");
+	kapmd = tsk;
+
+	spin_lock_irq(&tsk->sigmask_lock);
+	siginitsetinv(&tsk->blocked, sigmask(SIGQUIT));
+	recalc_sigpending(tsk);
+	spin_unlock_irq(&tsk->sigmask_lock);
+
+	complete((struct completion *)startup);
+
+	do {
+		set_task_state(tsk, TASK_INTERRUPTIBLE);
+		schedule();
+	} while (!signal_pending(tsk));
+
+	complete_and_exit(&kapmd_exit, 0);
+}
+#endif
+
+static int __init apm_init(void)
+{
+//	struct completion startup = COMPLETION_INITIALIZER(startup);
+	int ret;
+
+	if (apm_disabled) {
+		printk(KERN_NOTICE "apm: disabled on user request.\n");
+		return -ENODEV;
+	}
+
+	if (PM_IS_ACTIVE()) {
+		printk(KERN_NOTICE "apm: overridden by ACPI.\n");
+		return -EINVAL;
+	}
+
+//	ret = kernel_thread(kapmd, &startup, CLONE_FS | CLONE_FILES);
+//	if (ret)
+//		return ret;
+//	wait_for_completion(&startup);
+
+	pm_active = 1;
+
+#ifdef CONFIG_PROC_FS
+	create_proc_info_entry("apm", 0, NULL, apm_get_info);
+#endif
+
+	ret = misc_register(&apm_device);
+	if (ret != 0) {
+		pm_active = 0;
+		remove_proc_entry("apm", NULL);
+		send_sig(SIGQUIT, kapmd, 1);
+		wait_for_completion(&kapmd_exit);
+	}
+
+	return ret;
+}
+
+static void __exit apm_exit(void)
+{
+	misc_deregister(&apm_device);
+	remove_proc_entry("apm", NULL);
+	pm_active = 0;
+//	send_sig(SIGQUIT, kapmd, 1);
+//	wait_for_completion(&kapmd_exit);
+}
+
+module_init(apm_init);
+module_exit(apm_exit);
+
+MODULE_AUTHOR("Stephen Rothwell");
+MODULE_DESCRIPTION("Advanced Power Management");
+MODULE_LICENSE("GPL");
+
+EXPORT_NO_SYMBOLS;
+
+#ifndef MODULE
+static int __init apm_setup(char *str)
+{
+	while ((str != NULL) && (*str != '\0')) {
+		if (strncmp(str, "off", 3) == 0)
+			apm_disabled = 1;
+		if (strncmp(str, "on", 2) == 0)
+			apm_disabled = 0;
+		str = strchr(str, ',');
+		if (str != NULL)
+			str += strspn(str, ", \t");
+	}
+	return 1;
+}
+
+__setup("apm=", apm_setup);
+#endif
diff -Nru a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
--- a/arch/arm/kernel/bios32.c	Thu Jan 16 06:42:22 2003
+++ b/arch/arm/kernel/bios32.c	Thu Mar  6 08:26:25 2003
@@ -18,7 +18,6 @@
 #include <asm/mach/pci.h>
 
 static int debug_pci;
-int have_isa_bridge;
 
 void pcibios_report_status(u_int status_mask, int warn)
 {
@@ -363,9 +362,8 @@
 void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 {
 	struct pci_sys_data *root = bus->sysdata;
-	struct list_head *walk;
-	u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
-	u16 all_status = -1;
+	struct pci_dev *dev;
+	u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_FAST_BACK;
 
 	pbus_assign_bus_resources(bus, root);
 
@@ -373,42 +371,43 @@
 	 * Walk the devices on this bus, working out what we can
 	 * and can't support.
 	 */
-	for (walk = bus->devices.next; walk != &bus->devices; walk = walk->next) {
-		struct pci_dev *dev = pci_dev_b(walk);
+	list_for_each_entry(dev, &bus->devices, bus_list) {
 		u16 status;
 
 		pdev_fixup_device_resources(root, dev);
 
 		pci_read_config_word(dev, PCI_STATUS, &status);
-		all_status &= status;
+
+		/*
+		 * If any device on this bus does not support fast back
+		 * to back transfers, then the bus as a whole is not able
+		 * to support them.  Having fast back to back transfers
+		 * on saves us one PCI cycle per transaction.
+		 */
+		if (!(status & PCI_STATUS_FAST_BACK))
+			features &= ~PCI_COMMAND_FAST_BACK;
 
 		if (pdev_bad_for_parity(dev))
 			features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
 
-		/*
-		 * If this device is an ISA bridge, set the have_isa_bridge
-		 * flag.  We will then go looking for things like keyboard,
-		 * etc
-		 */
-		if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA ||
-		    dev->class >> 8 == PCI_CLASS_BRIDGE_EISA)
-			have_isa_bridge = !0;
+		switch (dev->class >> 8) {
+#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
+		case PCI_CLASS_BRIDGE_ISA:
+		case PCI_CLASS_BRIDGE_EISA:
+			/*
+			 * If this device is an ISA bridge, set isa_bridge
+			 * to point at this device.  We will then go looking
+			 * for things like keyboard, etc.
+			 */
+			isa_bridge = dev;
+			break;
+#endif
 	}
 
 	/*
-	 * If any device on this bus does not support fast back to back
-	 * transfers, then the bus as a whole is not able to support them.
-	 * Having fast back to back transfers on saves us one PCI cycle
-	 * per transaction.
-	 */
-	if (all_status & PCI_STATUS_FAST_BACK)
-		features |= PCI_COMMAND_FAST_BACK;
-
-	/*
 	 * Now walk the devices again, this time setting them up.
 	 */
-	for (walk = bus->devices.next; walk != &bus->devices; walk = walk->next) {
-		struct pci_dev *dev = pci_dev_b(walk);
+	list_for_each_entry(dev, &bus->devices, bus_list) {
 		u16 cmd;
 
 		pci_read_config_word(dev, PCI_COMMAND, &cmd);
@@ -416,7 +415,17 @@
 		pci_write_config_word(dev, PCI_COMMAND, cmd);
 
 		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
-				      SMP_CACHE_BYTES >> 2);
+				      L1_CACHE_BYTES >> 2);
+	}
+
+	/*
+	 * Propagate the flags to the PCI bridge.
+	 */
+	if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+		if (features & PCI_COMMAND_FAST_BACK)
+			bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
+		if (features & PCI_COMMAND_PARITY)
+			bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
 	}
 
 	/*
@@ -454,20 +463,17 @@
  */
 u8 __devinit pci_std_swizzle(struct pci_dev *dev, u8 *pinp)
 {
-	int pin = *pinp;
+	int pin = *pinp - 1;
 
-	if (pin != 0) {
-		pin -= 1;
-		while (dev->bus->self) {
-			pin = (pin + PCI_SLOT(dev->devfn)) & 3;
-			/*
-			 * move up the chain of bridges,
-			 * swizzling as we go.
-			 */
-			dev = dev->bus->self;
-		}
-		*pinp = pin + 1;
+	while (dev->bus->self) {
+		pin = (pin + PCI_SLOT(dev->devfn)) & 3;
+		/*
+		 * move up the chain of bridges,
+		 * swizzling as we go.
+		 */
+		dev = dev->bus->self;
 	}
+	*pinp = pin + 1;
 
 	return PCI_SLOT(dev->devfn);
 }
diff -Nru a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
--- a/arch/arm/kernel/ecard.c	Tue Feb 11 14:57:50 2003
+++ b/arch/arm/kernel/ecard.c	Thu Mar  6 05:14:05 2003
@@ -37,7 +37,6 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
-#include <linux/notifier.h>
 #include <linux/device.h>
 #include <linux/init.h>
 
@@ -57,7 +56,7 @@
 
 enum req {
 	req_readbytes,
-	req_reset_all
+	req_reset
 };
 
 struct ecard_request {
@@ -131,14 +130,11 @@
 #define POD_INT_ADDR(x)	((volatile unsigned char *)\
 			 ((BUS_ADDR((x)) - IO_BASE) + IO_START))
 
-static inline void ecard_task_reset(void)
+static inline void ecard_task_reset(struct ecard_request *req)
 {
-	ecard_t *ec;
-
-	for (ec = cards; ec; ec = ec->next)
-		if (ec->loader)
-			ecard_loader_reset(POD_INT_ADDR(ec->podaddr),
-					   ec->loader);
+	struct expansion_card *ec = req->ec;
+	if (ec->loader)
+		ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader);
 }
 
 static void
@@ -218,8 +214,8 @@
 		ecard_task_readbytes(req);
 		break;
 
-	case req_reset_all:
-		ecard_task_reset();
+	case req_reset:
+		ecard_task_reset(req);
 		break;
 	}
 }
@@ -355,60 +351,6 @@
 
 /* ======================= Mid-level card control ===================== */
 
-/*
- * This function is responsible for resetting the expansion cards to a
- * sensible state immediately prior to rebooting the system.  This function
- * has process state (keventd), so we can sleep.
- *
- * Possible "val" values here:
- *  SYS_RESTART   -  restarting system
- *  SYS_HALT      - halting system
- *  SYS_POWER_OFF - powering down system
- *
- * We ignore all calls, unless it is a SYS_RESTART call - power down/halts
- * will be followed by a SYS_RESTART if ctrl-alt-del is pressed again.
- */
-static int ecard_reboot(struct notifier_block *me, unsigned long val, void *v)
-{
-	struct ecard_request req;
-
-	if (val != SYS_RESTART)
-		return 0;
-
-	/*
-	 * Disable the expansion card interrupt
-	 */
-	disable_irq(IRQ_EXPANSIONCARD);
-
-	/*
-	 * If we have any expansion card loader code which will handle
-	 * the reset for us, call it now.
-	 */
-	req.req = req_reset_all;
-	ecard_call(&req);
-
-	/*
-	 * Disable the expansion card interrupt again, just to be sure.
-	 */
-	disable_irq(IRQ_EXPANSIONCARD);
-
-	/*
-	 * Finally, reset the expansion card interrupt mask to
-	 * all enable (RISC OS doesn't set this)
-	 */
-#ifdef HAS_EXPMASK
-	have_expmask = ~0;
-	__raw_writeb(have_expmask, EXPMASK_ENABLE);
-#endif
-	return 0;
-}
-
-static struct notifier_block ecard_reboot_notifier = {
-	.notifier_call	= ecard_reboot,
-};
-
-
-
 static void
 ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld)
 {
@@ -1083,11 +1025,6 @@
 {
 	int slot, irqhw;
 
-	/*
-	 * Register our reboot notifier
-	 */
-	register_reboot_notifier(&ecard_reboot_notifier);
-
 #ifdef CONFIG_CPU_32
 	init_waitqueue_head(&ecard_wait);
 #endif
@@ -1158,11 +1095,32 @@
 	return 0;
 }
 
+/*
+ * Before rebooting, we must make sure that the expansion card is in a
+ * sensible state, so it can be re-detected.  This means that the first
+ * page of the ROM must be visible.  We call the expansion cards reset
+ * handler, if any.
+ */
+static void ecard_drv_shutdown(struct device *dev)
+{
+	struct expansion_card *ec = ECARD_DEV(dev);
+	struct ecard_driver *drv = ECARD_DRV(dev->driver);
+	struct ecard_request req;
+
+	if (drv->shutdown)
+		drv->shutdown(ec);
+	ecard_release(ec);
+	req.req = req_reset;
+	req.ec = ec;
+	ecard_call(&req);
+}
+
 int ecard_register_driver(struct ecard_driver *drv)
 {
 	drv->drv.bus = &ecard_bus_type;
 	drv->drv.probe = ecard_drv_probe;
 	drv->drv.remove = ecard_drv_remove;
+	drv->drv.shutdown = ecard_drv_shutdown;
 
 	return driver_register(&drv->drv);
 }
diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
--- a/arch/arm/kernel/entry-armv.S	Mon Feb 24 12:42:23 2003
+++ b/arch/arm/kernel/entry-armv.S	Thu Mar  6 07:52:20 2003
@@ -1028,8 +1028,10 @@
 		@
 		@ now branch to the relevant MODE handling routine
 		@
-		mov	r13, #PSR_I_BIT | MODE_SVC
-		msr	spsr_c, r13			@ switch to SVC_32 mode
+		mrs	r13, cpsr
+		bic	r13, r13, #MODE_MASK
+		orr	r13, r13, #MODE_SVC
+		msr	spsr, r13			@ switch to SVC_32 mode
 
 		and	lr, lr, #15
 		ldr	lr, [pc, lr, lsl #2]
diff -Nru a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
--- a/arch/arm/kernel/entry-common.S	Sat Jul 27 12:49:37 2002
+++ b/arch/arm/kernel/entry-common.S	Thu Mar  6 05:18:11 2003
@@ -75,9 +75,8 @@
  * This is how we return from a fork.
  */
 ENTRY(ret_from_fork)
-#ifdef CONFIG_PREEMPT
+	ldr	r0, [r0, #TI_TASK]
 	bl	schedule_tail
-#endif
 	get_thread_info tsk
 	ldr	r1, [tsk, #TI_FLAGS]		@ check for syscall tracing
 	mov	why, #1
diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
--- a/arch/arm/kernel/irq.c	Tue Feb 11 15:05:29 2003
+++ b/arch/arm/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -165,17 +165,22 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_controller_lock, flags);
 	    	action = irq_desc[i].action;
 		if (!action)
-			continue;
+			goto unlock;
+
 		seq_printf(p, "%3d: %10u ", i, kstat_irqs(i));
 		seq_printf(p, "  %s", action->name);
-		for (action = action->next; action; action = action->next) {
+		for (action = action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
-		}
+
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_controller_lock, flags);
 	}
 
 #ifdef CONFIG_ARCH_ACORN
diff -Nru a/arch/arm/kernel/pm.c b/arch/arm/kernel/pm.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/kernel/pm.c	Thu Mar  6 07:59:45 2003
@@ -0,0 +1,126 @@
+/*
+ *  linux/arch/arm/kernel/suspend.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ *
+ *  This is the common support code for suspending an ARM machine.
+ *  pm_do_suspend() is responsible for actually putting the CPU to
+ *  sleep.
+ */
+#include <linux/config.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/cpufreq.h>
+
+#include <asm/leds.h>
+#include <asm/system.h>
+
+int suspend(void)
+{
+	int ret;
+
+	/*
+	 * Suspend "legacy" devices.
+	 */
+	ret = pm_send_all(PM_SUSPEND, (void *)3);
+	if (ret != 0)
+		goto out;
+
+	/*
+	 * Tell LDM devices we're going to suspend.
+	 */
+	ret = device_suspend(4, SUSPEND_NOTIFY);
+	if (ret != 0)
+		goto resume_legacy;
+
+	/*
+	 * Disable, devices, and save state.
+	 */
+	device_suspend(4, SUSPEND_DISABLE);
+	device_suspend(4, SUSPEND_SAVE_STATE);
+
+	/*
+	 * Tell devices that they're going to be powered off.
+	 */
+	device_suspend(4, SUSPEND_POWER_DOWN);
+
+	local_irq_disable();
+	leds_event(led_stop);
+
+	ret = pm_do_suspend();
+
+	leds_event(led_start);
+	local_irq_enable();
+
+	/*
+	 * Tell devices that they now have power.
+	 */
+	device_resume(RESUME_POWER_ON);
+
+	/*
+	 * Restore the CPU frequency settings.
+	 */
+#ifdef CONFIG_CPU_FREQ
+	cpufreq_restore();
+#endif
+
+	/*
+	 * Resume LDM devices.
+	 */
+	device_resume(RESUME_RESTORE_STATE);
+	device_resume(RESUME_ENABLE);
+
+ resume_legacy:
+	/*
+	 * Resume "legacy" devices.
+	 */
+	pm_send_all(PM_RESUME, (void *)0);
+
+ out:
+	return ret;
+}
+
+#ifdef CONFIG_SYSCTL
+#include <linux/init.h>
+#include <linux/sysctl.h>
+
+/*
+ * This came from arch/arm/mach-sa1100/pm.c:
+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
+ *  with modifications by Nicolas Pitre and Russell King.
+ *
+ * ARGH!  ACPI people defined CTL_ACPI in linux/acpi.h rather than
+ * linux/sysctl.h.
+ *
+ * This means our interface here won't survive long - it needs a new
+ * interface.  Quick hack to get this working - use sysctl id 9999.
+ */
+#warning ACPI broke the kernel, this interface needs to be fixed up.
+#define CTL_ACPI 9999
+#define ACPI_S1_SLP_TYP 19
+
+static struct ctl_table pm_table[] =
+{
+	{ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&suspend},
+	{0}
+};
+
+static struct ctl_table pm_dir_table[] =
+{
+	{CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
+	{0}
+};
+
+/*
+ * Initialize power interface
+ */
+static int __init pm_init(void)
+{
+	register_sysctl_table(pm_dir_table, 1);
+	return 0;
+}
+
+fs_initcall(pm_init);
+
+#endif
diff -Nru a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
--- a/arch/arm/kernel/time.c	Mon Feb 24 23:13:09 2003
+++ b/arch/arm/kernel/time.c	Thu Mar  6 05:40:54 2003
@@ -200,6 +200,7 @@
 
 static struct irqaction timer_irq = {
 	.name	= "timer",
+	.flags	= SA_INTERRUPT,
 };
 
 /*
diff -Nru a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile
--- a/arch/arm/mach-integrator/Makefile	Sat Dec 14 04:38:56 2002
+++ b/arch/arm/mach-integrator/Makefile	Thu Mar  6 08:48:28 2003
@@ -4,10 +4,11 @@
 
 # Object file lists.
 
-obj-y			:= arch.o cpu.o irq.o mm.o time.o
+obj-y			:= arch.o irq.o mm.o time.o
 obj-m			:=
 obj-n			:=
 obj-			:=
 
 obj-$(CONFIG_LEDS)	+= leds.o
 obj-$(CONFIG_PCI)	+= pci_v3.o pci.o
+obj-$(CONFIG_CPU_FREQ_INTEGRATOR)	+= cpu.o
diff -Nru a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c
--- a/arch/arm/mach-integrator/cpu.c	Tue Jan 14 16:01:39 2003
+++ b/arch/arm/mach-integrator/cpu.c	Thu Mar  6 11:27:03 2003
@@ -23,6 +23,8 @@
 #include <asm/hardware.h>
 #include <asm/io.h>
 
+static struct cpufreq_driver integrator_driver;
+
 #define CM_ID  	(IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_ID_OFFSET)
 #define CM_OSC	(IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_OSC_OFFSET)
 #define CM_STAT (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_STAT_OFFSET)
@@ -43,7 +45,6 @@
 	return 2000 * (vco.vdw + 8) / cc_divisor[vco.od] / factor;
 }
 
-#ifdef CONFIG_CPU_FREQ
 /*
  * Divisor indexes in ascending divisor order
  */
@@ -69,21 +70,17 @@
 	return vco;
 }
 
+
 /*
- * Validate the speed in khz.  If it is outside our
- * range, then return the lowest.
+ * Validate the speed policy.
  */
-static int integrator_verify_speed(struct cpufreq_policy *policy)
+static int integrator_verify_policy(struct cpufreq_policy *policy)
 {
 	struct vco vco;
 
-	if (policy->max > policy->cpuinfo.max_freq)
-		policy->max = policy->cpuinfo.max_freq;
-
-	if (policy->max < 12000)
-		policy->max = 12000;
-	if (policy->max > 160000)
-		policy->max = 160000;
+	cpufreq_verify_within_limits(policy, 
+				     policy->cpuinfo.min_freq, 
+				     policy->cpuinfo.max_freq);
 
 	vco = freq_to_vco(policy->max, 1);
 
@@ -92,12 +89,28 @@
 	if (vco.vdw > 152)
 		vco.vdw = 152;
 
-	policy->min = policy->max = vco_to_freq(vco, 1);
+	policy->max = vco_to_freq(vco, 1);
+
+	vco = freq_to_vco(policy->min, 1);
+
+	if (vco.vdw < 4)
+		vco.vdw = 4;
+	if (vco.vdw > 152)
+		vco.vdw = 152;
+
+	policy->min = vco_to_freq(vco, 1);
+
+	cpufreq_verify_within_limits(policy, 
+				     policy->cpuinfo.min_freq, 
+				     policy->cpuinfo.max_freq);
 
 	return 0;
 }
 
-static int integrator_set_policy(struct cpufreq_policy *policy)
+
+static int integrator_set_target(struct cpufreq_policy *policy,
+				 unsigned int target_freq,
+				 unsigned int relation)
 {
 	unsigned long cpus_allowed;
 	int cpu = policy->cpu;
@@ -121,9 +134,18 @@
 	cm_osc = __raw_readl(CM_OSC);
 	vco.od = (cm_osc >> 8) & 7;
 	vco.vdw = cm_osc & 255;
-
 	freqs.old = vco_to_freq(vco, 1);
-	freqs.new = target_freq;
+
+	/* freq_to_vco rounds down -- so we need the next larger freq in
+	 * case of CPUFREQ_RELATION_L.
+	 */
+	if (relation == CPUFREQ_RELATION_L)
+		target_freq += 1999;
+	if (target_freq > policy->max)
+		target_freq = policy->max;
+	vco = freq_to_vco(target_freq, 1);
+	freqs.new = vco_to_freq(vco, 1);
+
 	freqs.cpu = policy->cpu;
 
 	if (freqs.old == freqs.new) {
@@ -132,7 +154,6 @@
 	}
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-	vco = freq_to_vco(policy->max, 1);
 
 	cm_osc = __raw_readl(CM_OSC);
 	cm_osc &= 0xfffff800;
@@ -152,80 +173,64 @@
 	return 0;
 }
 
-static struct cpufreq_policy integrator_policy = {
-	.cpu		= 0,
-	.policy		= CPUFREQ_POLICY_POWERSAVE,
-	.cpuinfo	= {
-		.max_freq		= 160000,
-		.min_freq		= 12000,
-		.transition_latency	= CPUFREQ_ETERNAL,
-	},
-};
+static int integrator_cpufreq_init(struct cpufreq *policy)
+{
+	unsigned long cus_allowed;
+	unsigned int cpu = policy->cpu;
+	u_int cm_osc, cm_stat, mem_freq_khz;
+	struct vco vco;
 
-static struct cpufreq_driver integrator_driver = {
-	.verify		= integrator_verify_speed,
-	.setpolicy	= integrator_set_policy,
-	.policy		= &integrator_policy,
-	.name		= "integrator",
-};
-#endif
+	cpus_allowed = current->cpus_allowed;
 
-static int __init integrator_cpu_init(void)
-{
-	struct cpufreq_policy *policies;
-	unsigned long cpus_allowed;
-	int cpu;
+	set_cpus_allowed(current, 1 << cpu);
+	BUG_ON(cpu != smp_processor_id());
 
-	policies = kmalloc(sizeof(struct cpufreq_policy) * NR_CPUS,
-			   GFP_KERNEL);
-	if (!policies) {
-		printk(KERN_ERR "CPU: unable to allocate policies structure\n");
-		return -ENOMEM;
-	}
+	/* detect memory etc. */
+	cm_stat = __raw_readl(CM_STAT);
+	cm_osc = __raw_readl(CM_OSC);
+	vco.od  = (cm_osc >> 20) & 7;
+	vco.vdw = (cm_osc >> 12) & 255;
+	mem_freq_khz = vco_to_freq(vco, 2);
+
+	printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255);
+	printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n",
+	       cpu, mem_freq_khz / 1000, mem_freq_khz % 1000);
 
-	cpus_allowed = current->cpus_allowed;
-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
-		u_int cm_osc, cm_stat, mem_freq_khz;
-		struct vco vco;
-
-		if (!cpu_online(cpu))
-			continue;
-
-		set_cpus_allowed(current, 1 << cpu);
-		BUG_ON(cpu != smp_processor_id());
-
-		cm_stat = __raw_readl(CM_STAT);
-		cm_osc = __raw_readl(CM_OSC);
-		vco.od  = (cm_osc >> 20) & 7;
-		vco.vdw = (cm_osc >> 12) & 255;
-		mem_freq_khz = vco_to_freq(vco, 2);
-
-		printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255);
-		printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n",
-			cpu, mem_freq_khz / 1000, mem_freq_khz % 1000);
-
-		vco.od = (cm_osc >> 8) & 7;
-		vco.vdw = cm_osc & 255;
-
-		policies[cpu].cpu = cpu;
-		policies[cpu].policy = CPUFREQ_POLICY_POWERSAVE,
-		policies[cpu].cpuinfo.max_freq = 160000;
-		policies[cpu].cpuinfo.min_freq = 12000;
-		policies[cpu].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-		policies[cpu].min =
-		policies[cpu].max = vco_to_freq(vco, 1);
-	}
+	vco.od = (cm_osc >> 8) & 7;
+	vco.vdw = cm_osc & 255;
 
-	set_cpus_allowed(current, cpus_allowed);
+	/* set default policy and cpuinfo */
+	policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+	policy->cpuinfo.max_freq = 160000;
+	policy->cpuinfo.min_freq = 12000;
+	policy->cpuinfo.transition_latency = 1000; /* 1 ms, assumed */
+	policy->cur = policy->min = policy->max = vco_to_freq(vco, 1); /* current freq */
 
-#ifdef CONFIG_CPU_FREQ
-	integrator_driver.policy = policies;
-	cpufreq_register(&integrator_driver);
-#else
-	kfree(policies);
-#endif
+	set_cpus_allowed(current, cpus_allowed);
 
 	return 0;
 }
 
-arch_initcall(integrator_cpu_init);
+static struct cpufreq_driver integrator_driver = {
+	.verify		= integrator_verify_policy,
+	.target		= integrator_set_target,
+	.init		= integrator_cpufreq_init,
+	.name		= "integrator",
+};
+
+static int __init integrator_cpu_init(void)
+{
+	return cpufreq_register_driver(&integrator_driver);
+}
+
+static void __exit integrator_cpu_exit(void)
+{
+	cpufreq_unregister_driver(&integrator_driver);
+}
+
+MODULE_AUTHOR ("Russell M. King");
+MODULE_DESCRIPTION ("cpufreq driver for ARM Integrator CPUs");
+MODULE_LICENSE ("GPL");
+
+module_init(integrator_cpu_init);
+module_exit(integrator_cpu_exit);
diff -Nru a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
--- a/arch/arm/mach-sa1100/Kconfig	Wed Nov 13 08:41:25 2002
+++ b/arch/arm/mach-sa1100/Kconfig	Thu Mar  6 16:15:28 2003
@@ -326,6 +326,15 @@
 #	help
 #	  :: write me ::
 
+config SA1100_SSP
+	tristate "Generic PIO SSP"
+	depends on ARCH_SA1100
+	help
+	  Say Y here to enable support for the generic PIO SSP driver.
+	  This isn't for audio support, but for attached sensors and
+	  other devices, eg for BadgePAD 4 sensor support, or Jornada
+	  720 touchscreen support.
+
 config SA1100_USB
 	tristate "SA1100 USB function support"
 	depends on ARCH_SA1100
diff -Nru a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
--- a/arch/arm/mach-sa1100/Makefile	Mon Feb  3 14:19:35 2003
+++ b/arch/arm/mach-sa1100/Makefile	Thu Mar  6 16:15:28 2003
@@ -9,15 +9,8 @@
 obj-  :=
 led-y := leds.o
 
-# This needs to be cleaned up.  We probably need to have SA1100
-# and SA1110 config symbols.
-ifeq ($(CONFIG_CPU_FREQ),y)
-obj-$(CONFIG_SA1100_ASSABET)		+= cpu-sa1110.o
-obj-$(CONFIG_SA1100_CERF)		+= cpu-sa1110.o
-obj-$(CONFIG_SA1100_HACKKIT)		+= cpu-sa1110.o
-obj-$(CONFIG_SA1100_LART)		+= cpu-sa1100.o
-obj-$(CONFIG_SA1100_PT_SYSTEM3)		+= cpu-sa1110.o
-endif
+obj-$(CONFIG_CPU_FREQ_SA1100)		+= cpu-sa1100.o
+obj-$(CONFIG_CPU_FREQ_SA1110)		+= cpu-sa1110.o
 
 # Specific board support
 obj-$(CONFIG_SA1100_ADSBITSY)		+= adsbitsy.o
@@ -99,3 +92,4 @@
 
 # Miscelaneous functions
 obj-$(CONFIG_PM)			+= pm.o sleep.o
+obj-$(CONFIG_SA1100_SSP)		+= ssp.o
diff -Nru a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
--- a/arch/arm/mach-sa1100/cpu-sa1100.c	Tue Jan 14 16:01:40 2003
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c	Thu Mar  6 11:27:04 2003
@@ -101,7 +101,7 @@
 } sa1100_dram_regs_t;
 
 
-
+static struct cpufreq_driver sa1100_driver;
 
 static sa1100_dram_regs_t sa1100_dram_settings[] =
 {
@@ -176,60 +176,73 @@
 	}
 }
 
-static int sa1100_setspeed(struct cpufreq_policy *policy)
+static int sa1100_target(struct cpufreq_policy *policy,
+			 unsigned int target_freq,
+			 unsigned int relation)
 {
 	unsigned int cur = sa11x0_getspeed();
+	unsigned int new_ppcr;
+
 	struct cpufreq_freqs freqs;
+	switch(relation){
+	case CPUFREQ_RELATION_L:
+		new_ppcr = sa11x0_freq_to_ppcr(target_freq);
+		if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
+			new_ppcr--;
+		break;
+	case CPUFREQ_RELATION_H:
+		new_ppcr = sa11x0_freq_to_ppcr(target_freq);
+		if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) &&
+		    (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min))
+			mew_ppcr--;
+		break;
+	}
 
 	freqs.old = cur;
-	freqs.new = policy->max;
+	freqs.new = sa11x0_ppcr_to_freq(new_ppcr);
 	freqs.cpu = 0;
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
-	if (policy->max > cur)
-		sa1100_update_dram_timings(cur, policy->max);
+	if (freqs.new > cur)
+		sa1100_update_dram_timings(cur, freqs.new);
 
-	PPCR = sa11x0_freq_to_ppcr(policy->max);
+	PPCR = new_ppcr;
 
-	if (policy->max < cur)
-		sa1100_update_dram_timings(cur, policy->max);
+	if (freqs.new < cur)
+		sa1100_update_dram_timings(cur, freqs.new);
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
 
-static struct cpufreq_policy sa1100_policy = {
-	.cpu		= 0,
-	.policy		= CPUFREQ_POLICY_POWERSAVE,
-	.cpuinfo	= {
-		.max_freq		= 287000,
-		.min_freq		= 59000,
-		.transition_latency	= CPUFREQ_ETERNAL,
-	},
-};
+static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
+{
+	if (policy->cpu != 0)
+		return -EINVAL;
+	policy->cur = policy->min = policy->max = sa11x0_getspeed();
+	policy->policy = CPUFREQ_POLICY_POWERSAVE;
+	policy->cpuinfo.min_freq = 59000;
+	policy->cpuinfo.max_freq = 287000;
+	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+	return 0;
+}
 
 static struct cpufreq_driver sa1100_driver = {
 	.verify		= sa11x0_verify_speed,
-	.setpolicy	= sa1100_setspeed,
-	.policy		= &sa1100_policy,
+	.target		= sa1100_target,
+	.init		= sa1100_cpu_init,
 	.name		= "sa1100",
 };
 
 static int __init sa1100_dram_init(void)
 {
-	int ret = -ENODEV;
-
-	if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) {
-		sa1100_driver.cpu_cur_freq[0] =
-		sa1100_policy.min =
-		sa1100_policy.max = sa11x0_getspeed();
-
-		ret = cpufreq_register(&sa1100_driver);
-	}
-
-	return ret;
+	cpufreq_gov_userspace_init();
+ 	if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID)
+		return cpufreq_register_driver(&sa1100_driver);
+	else
+		return -ENODEV;
 }
 
 arch_initcall(sa1100_dram_init);
diff -Nru a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
--- a/arch/arm/mach-sa1100/cpu-sa1110.c	Tue Jan 14 16:01:40 2003
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c	Thu Mar  6 11:27:04 2003
@@ -32,6 +32,8 @@
 
 #undef DEBUG
 
+static struct cpufreq_driver sa1110_driver;
+
 struct sdram_params {
 	u_char  rows;		/* bits				 */
 	u_char  cas_latency;	/* cycles			 */
@@ -208,11 +210,11 @@
 }
 
 /*
- * Ok, set the CPU frequency.  Since we've done the validation
- * above, we can match for an exact frequency.  If we don't find
- * an exact match, we will to set the lowest frequency to be safe.
+ * Ok, set the CPU frequency.  
  */
-static int sa1110_setspeed(struct cpufreq_policy *policy)
+static int sa1110_target(struct cpufreq_policy *policy,
+			 unsigned int target_freq,
+			 unsigned int relation)
 {
 	struct sdram_params *sdram = &sdram_params;
 	struct cpufreq_freqs freqs;
@@ -220,8 +222,25 @@
 	unsigned long flags;
 	unsigned int ppcr, unused;
 
-	ppcr = sa11x0_freq_to_ppcr(policy->max);
-	sdram_calculate_timing(&sd, policy->max, sdram);
+	switch(relation){
+	case CPUFREQ_RELATION_L:
+		ppcr = sa11x0_freq_to_ppcr(target_freq);
+		if (sa11x0_ppcr_to_freq(ppcr) > policy->max)
+			ppcr--;
+		break;
+	case CPUFREQ_RELATION_H:
+		ppcr = sa11x0_freq_to_ppcr(target_freq);
+		if (ppcr && (sa11x0_ppcr_to_freq(ppcr) > target_freq) &&
+		    (sa11x0_ppcr_to_freq(ppcr-1) >= policy->min))
+			ppcr--;
+		break;
+	}
+
+	freqs.old = sa11x0_getspeed();
+	freqs.new = sa11x0_ppcr_to_freq(ppcr);
+	freqs.cpu = 0;
+
+	sdram_calculate_timing(&sd, freqs.new, sdram);
 
 #if 0
 	/*
@@ -240,10 +259,6 @@
 	sd.mdcas[2] = 0xaaaaaaaa;
 #endif
 
-	freqs.old = sa11x0_getspeed();
-	freqs.new = policy->max;
-	freqs.cpu = 0;
-
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
 	/*
@@ -288,27 +303,29 @@
 	/*
 	 * Now, return the SDRAM refresh back to normal.
 	 */
-	sdram_update_refresh(policy->max, sdram);
+	sdram_update_refresh(freqs.new, sdram);
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
 
-static struct cpufreq_policy sa1110_policy = {
-	.cpu		= 0,
-	.policy		= CPUFREQ_POLICY_POWERSAVE,
-	.cpuinfo	= {
-		.max_freq		= 287000,
-		.min_freq		= 59000,
-		.transition_latency	= CPUFREQ_ETERNAL,
-	},
-};
+static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
+{
+	if (policy->cpu != 0)
+		return -EINVAL;
+	policy->cur = policy->min = policy->max = sa11x0_getspeed();
+	policy->policy = CPUFREQ_POLICY_POWERSAVE;
+	policy->cpuinfo.min_freq = 59000;
+	policy->cpuinfo.max_freq = 287000;
+	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+	return 0;
+}
 
 static struct cpufreq_driver sa1110_driver = {
-	.verify		 = sa11x0_verify_speed,
-	.setpolicy	 = sa1110_setspeed,
-	.policy		 = &sa1110_policy,
+	.verify		= sa11x0_verify_speed,
+	.target		= sa1110_target,
+	.init		= sa1110_cpu_init,
 	.name		= "sa1110",
 };
 
@@ -331,15 +348,11 @@
 			sdram->tck, sdram->trcd, sdram->trp,
 			sdram->twr, sdram->refresh, sdram->cas_latency);
 
+		cpufreq_gov_userspace_init();
+ 
 		memcpy(&sdram_params, sdram, sizeof(sdram_params));
 
-		sa1110_driver.cpu_cur_freq[0] =
-		sa1110_policy.min =
-		sa1110_policy.max = sa11x0_getspeed();
-
-		sa1110_setspeed(&sa1110_policy);
-
-		return cpufreq_register(&sa1110_driver);
+		return cpufreq_register_driver(&sa1110_driver);
 	}
 
 	return 0;
diff -Nru a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
--- a/arch/arm/mach-sa1100/generic.c	Fri Dec 13 06:22:36 2002
+++ b/arch/arm/mach-sa1100/generic.c	Thu Mar  6 12:25:44 2003
@@ -48,33 +48,48 @@
 	2802    /* 280.2 MHz */
 };
 
-#ifdef CONFIG_CPU_FREQ
+#if defined(CONFIG_CPU_FREQ_SA1100) || defined(CONFIG_CPU_FREQ_SA1110)
+/* rounds up(!)  */
 unsigned int sa11x0_freq_to_ppcr(unsigned int khz)
 {
 	int i;
 
 	khz /= 100;
 
-	for (i = NR_FREQS - 1; i > 0; i--)
-		if (cclk_frequency_100khz[i] <= khz)
+	for (i = 0; i < NR_FREQS; i++)
+		if (cclk_frequency_100khz[i] >= khz)
 			break;
 
 	return i;
 }
 
-/*
- * Validate the policy.  We aren't able to do any fancy in-kernel
- * scaling, so we force min=max, and set the policy to "performance".
- * If we can't generate the precise frequency requested, round it up.
+unsigned int sa11x0_ppcr_to_freq(unsigned int idx)
+{
+	unsigned int freq = 0;
+	if (idx < NR_FREQS)
+		freq = cclk_frequency_100khz[idx] * 100;
+	return freq;
+}
+
+
+/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+ * this platform, anyway.
  */
 int sa11x0_verify_speed(struct cpufreq_policy *policy)
 {
-	if (policy->max > policy->cpuinfo.max_freq)
-		policy->max = policy->cpuinfo.max_freq;
+	unsigned int tmp;
+	if (policy->cpu)
+		return -EINVAL;
+
+	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
+
+	/* make sure that at least one frequency is within the policy */
+	tmp = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->min)] * 100;
+	if (tmp > policy->max)
+		policy->max = tmp;
+
+	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
 
-	policy->max = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->max)] * 100;
-	policy->min = policy->max;
-	policy->policy = CPUFREQ_POLICY_POWERSAVE;
 	return 0;
 }
 
diff -Nru a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
--- a/arch/arm/mach-sa1100/generic.h	Sun Nov 24 15:14:21 2002
+++ b/arch/arm/mach-sa1100/generic.h	Thu Mar  6 08:48:29 2003
@@ -23,3 +23,4 @@
 extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
 extern int sa11x0_verify_speed(struct cpufreq_policy *policy);
 extern unsigned int sa11x0_getspeed(void);
+extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx);
diff -Nru a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
--- a/arch/arm/mach-sa1100/irq.c	Sun Mar  2 23:32:23 2003
+++ b/arch/arm/mach-sa1100/irq.c	Thu Mar  6 12:33:33 2003
@@ -211,6 +211,99 @@
 	.end	= 0x9005ffff,
 };
 
+struct sa1100irq_state {
+	unsigned int	saved;
+	unsigned int	icmr;
+	unsigned int	iclr;
+	unsigned int	iccr;
+};
+
+static int sa1100irq_suspend(struct device *dev, u32 state, u32 level)
+{
+	struct sa1100irq_state *st;
+
+	if (!dev->saved_state && level == SUSPEND_NOTIFY)
+		dev->saved_state = kmalloc(sizeof(struct sa1100irq_state),
+					   GFP_KERNEL);
+	if (!dev->saved_state)
+		return -ENOMEM;
+
+	if (level == SUSPEND_POWER_DOWN) {
+		st = (struct sa1100irq_state *)dev->saved_state;
+
+		st->saved = 1;
+		st->icmr = ICMR;
+		st->iclr = ICLR;
+		st->iccr = ICCR;
+
+		/*
+		 * Disable all GPIO-based interrupts.
+		 */
+		ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7|
+			  IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2|
+			  IC_GPIO1|IC_GPIO0);
+
+		/*
+		 * Set the appropriate edges for wakeup.
+		 */
+		GRER = PWER & GPIO_IRQ_rising_edge;
+		GFER = PWER & GPIO_IRQ_falling_edge;
+
+		/*
+		 * Clear any pending GPIO interrupts.
+		 */
+		GEDR = GEDR;
+	}
+	return 0;
+}
+
+static int sa1100irq_resume(struct device *dev, u32 level)
+{
+	struct sa1100irq_state *st;
+
+	if (level == RESUME_POWER_ON) {
+		st = (struct sa1100irq_state *)dev->saved_state;
+		dev->saved_state = NULL;
+
+		if (st->saved) {
+			ICCR = st->iccr;
+			ICLR = st->iclr;
+
+			GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
+			GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+
+			ICMR = st->icmr;
+		}
+
+		kfree(st);
+	}
+	return 0;
+}
+
+static struct device_driver sa1100irq_driver = {
+	.name		= "sa11x0-irq",
+	.bus		= &system_bus_type,
+	.suspend	= sa1100irq_suspend,
+	.resume		= sa1100irq_resume,
+};
+
+static struct sys_device sa1100irq_device = {
+	.name		= "irq",
+	.id		= 0,
+	.dev = {
+		.name	= "Intel SA11x0 [Interrupt Controller]",
+		.driver	= &sa1100irq_driver,
+	},
+};
+
+static int __init sa1100irq_init_devicefs(void)
+{
+	driver_register(&sa1100irq_driver);
+	return sys_device_register(&sa1100irq_device);
+}
+
+device_initcall(sa1100irq_init_devicefs);
+
 void __init sa1100_init_irq(void)
 {
 	unsigned int irq;
diff -Nru a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
--- a/arch/arm/mach-sa1100/pm.c	Sun Nov 17 07:31:13 2002
+++ b/arch/arm/mach-sa1100/pm.c	Thu Mar  6 08:08:20 2003
@@ -22,25 +22,12 @@
  * 2002-05-27:	Nicolas Pitre	Killed sleep.h and the kmalloced save array.
  * 				Storage is local on the stack now.
  */
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pm.h>
-#include <linux/sysctl.h>
 #include <linux/errno.h>
-#include <linux/device.h>
-#include <linux/cpufreq.h>
+#include <linux/time.h>
 
 #include <asm/hardware.h>
 #include <asm/memory.h>
 #include <asm/system.h>
-#include <asm/leds.h>
-
-
-/*
- * Debug macros
- */
-#undef DEBUG
 
 extern void sa1100_cpu_suspend(void);
 extern void sa1100_cpu_resume(void);
@@ -58,10 +45,9 @@
 	SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
 	SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
 
-	SLEEP_SAVE_GPDR, SLEEP_SAVE_GRER, SLEEP_SAVE_GFER, SLEEP_SAVE_GAFR,
+	SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR,
 	SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
 
-	SLEEP_SAVE_ICMR,
 	SLEEP_SAVE_Ser1SDCR0,
 
 	SLEEP_SAVE_SIZE
@@ -72,10 +58,6 @@
 {
 	unsigned long sleep_save[SLEEP_SAVE_SIZE];
 
-	local_irq_disable();
-
-	leds_event(led_stop);
-
 	/* preserve current time */
 	RCNR = xtime.tv_sec;
 
@@ -88,8 +70,6 @@
 	SAVE(OIER);
 
 	SAVE(GPDR);
-	SAVE(GRER);
-	SAVE(GFER);
 	SAVE(GAFR);
 
 	SAVE(PPDR);
@@ -99,13 +79,6 @@
 
 	SAVE(Ser1SDCR0);
 
-	SAVE(ICMR);
-
-	/* ... maybe a global variable initialized by arch code to set this? */
-	GRER = PWER;
-	GFER = 0;
-	GEDR = GEDR;
-
 	/* Clear previous reset status */
 	RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
 
@@ -115,22 +88,23 @@
 	/* go zzz */
 	sa1100_cpu_suspend();
 
-	/* ensure not to come back here if it wasn't intended */
+	/*
+	 * Ensure not to come back here if it wasn't intended
+	 */
 	PSPR = 0;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "*** made it back from resume\n");
-#endif
+	/*
+	 * Ensure interrupt sources are disabled; we will re-init
+	 * the interrupt subsystem via the device manager.
+	 */
+	ICLR = 0;
+	ICCR = 1;
+	ICMR = 0;
 
 	/* restore registers */
 	RESTORE(GPDR);
-	RESTORE(GRER);
-	RESTORE(GFER);
 	RESTORE(GAFR);
 
-	/* clear any edge detect bit */
-	GEDR = GEDR;
-
 	RESTORE(PPDR);
 	RESTORE(PPSR);
 	RESTORE(PPAR);
@@ -138,6 +112,9 @@
 
 	RESTORE(Ser1SDCR0);
 
+	/*
+	 * Clear the peripheral sleep-hold bit.
+	 */
 	PSSR = PSSR_PH;
 
 	RESTORE(OSMR0);
@@ -147,24 +124,9 @@
 	RESTORE(OSCR);
 	RESTORE(OIER);
 
-	ICLR = 0;
-	ICCR = 1;
-	RESTORE(ICMR);
-
 	/* restore current time */
 	xtime.tv_sec = RCNR;
 
-	leds_event(led_start);
-
-	local_irq_enable();
-
-	/*
-	 * Restore the CPU frequency settings.
-	 */
-#ifdef CONFIG_CPU_FREQ
-	cpufreq_restore();
-#endif
-
 	return 0;
 }
 
@@ -172,78 +134,3 @@
 {
 	return virt_to_phys(sp);
 }
-
-#ifdef CONFIG_SYSCTL
-/*
- * ARGH!  ACPI people defined CTL_ACPI in linux/acpi.h rather than
- * linux/sysctl.h.
- *
- * This means our interface here won't survive long - it needs a new
- * interface.  Quick hack to get this working - use sysctl id 9999.
- */
-#warning ACPI broke the kernel, this interface needs to be fixed up.
-#define CTL_ACPI 9999
-#define ACPI_S1_SLP_TYP 19
-
-/*
- * Send us to sleep.
- */
-static int sysctl_pm_do_suspend(void)
-{
-	int retval;
-
-	/*
-	 * Suspend "legacy" devices.
-	 */
-	retval = pm_send_all(PM_SUSPEND, (void *)3);
-	if (retval == 0) {
-		/*
-		 * Suspend LDM devices.
-		 */
-		device_suspend(4, SUSPEND_NOTIFY);
-		device_suspend(4, SUSPEND_SAVE_STATE);
-		device_suspend(4, SUSPEND_DISABLE);
-
-		retval = pm_do_suspend();
-
-		/*
-		 * Resume LDM devices.
-		 */
-		device_resume(RESUME_RESTORE_STATE);
-		device_resume(RESUME_ENABLE);
-
-		/*
-		 * Resume "legacy" devices.
-		 */
-		pm_send_all(PM_RESUME, (void *)0);
-	}
-
-	return retval;
-}
-
-static struct ctl_table pm_table[] =
-{
-	{ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend},
-	{0}
-};
-
-static struct ctl_table pm_dir_table[] =
-{
-	{CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
-	{0}
-};
-
-/*
- * Initialize power interface
- */
-static int __init pm_init(void)
-{
-	register_sysctl_table(pm_dir_table, 1);
-	return 0;
-}
-
-fs_initcall(pm_init);
-
-#endif
-
-EXPORT_SYMBOL(pm_do_suspend);
diff -Nru a/arch/arm/mach-sa1100/ssp.c b/arch/arm/mach-sa1100/ssp.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/mach-sa1100/ssp.c	Thu Mar  6 16:15:28 2003
@@ -0,0 +1,208 @@
+/*
+ *  linux/arch/arm/mach-sa1100/ssp.c
+ *
+ *  Copyright (C) 2003 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Generic SSP driver.  This provides the generic core for simple
+ *  IO-based SSP applications.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/hardware/ssp.h>
+
+static void ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned int status = Ser4SSSR;
+
+	if (status & SSSR_ROR) {
+		printk(KERN_WARNING "SSP: receiver overrun\n");
+	}
+
+	Ser4SSSR = SSSR_ROR;
+}
+
+/**
+ * ssp_write_word - write a word to the SSP port
+ * @data: 16-bit, MSB justified data to write.
+ *
+ * Wait for a free entry in the SSP transmit FIFO, and write a data
+ * word to the SSP port.
+ *
+ * The caller is expected to perform the necessary locking.
+ *
+ * Returns:
+ *   %-ETIMEDOUT	timeout occurred (for future)
+ *   0			success
+ */
+int ssp_write_word(u16 data)
+{
+	while (!(Ser4SSSR & SSSR_TNF))
+		cpu_relax();
+
+	Ser4SSDR = data;
+
+	return 0;
+}
+
+/**
+ * ssp_read_word - read a word from the SSP port
+ *
+ * Wait for a data word in the SSP receive FIFO, and return the
+ * received data.  Data is LSB justified.
+ *
+ * Note: Currently, if data is not expected to be received, this
+ * function will wait for ever.
+ *
+ * The caller is expected to perform the necessary locking.
+ *
+ * Returns:
+ *   %-ETIMEDOUT	timeout occurred (for future)
+ *   16-bit data	success
+ */
+int ssp_read_word(void)
+{
+	while (!(Ser4SSSR & SSSR_RNE))
+		cpu_relax();
+
+	return Ser4SSDR;
+}
+
+/**
+ * ssp_flush - flush the transmit and receive FIFOs
+ *
+ * Wait for the SSP to idle, and ensure that the receive FIFO
+ * is empty.
+ *
+ * The caller is expected to perform the necessary locking.
+ */
+void ssp_flush(void)
+{
+	do {
+		while (Ser4SSSR & SSSR_RNE) {
+			(void) Ser4SSDR;
+		}
+	} while (Ser4SSSR & SSSR_BSY);
+}
+
+/**
+ * ssp_enable - enable the SSP port
+ *
+ * Turn on the SSP port.
+ */
+void ssp_enable(void)
+{
+	Ser4SSCR0 |= SSCR0_SSE;
+}
+
+/**
+ * ssp_disable - shut down the SSP port
+ *
+ * Turn off the SSP port, optionally powering it down.
+ */
+void ssp_disable(void)
+{
+	Ser4SSCR0 &= ~SSCR0_SSE;
+}
+
+/**
+ * ssp_save_state - save the SSP configuration
+ * @ssp: pointer to structure to save SSP configuration
+ *
+ * Save the configured SSP state for suspend.
+ */
+void ssp_save_state(struct ssp_state *ssp)
+{
+	ssp->cr0 = Ser4SSCR0;
+	ssp->cr1 = Ser4SSCR1;
+
+	Ser4SSCR0 &= ~SSCR0_SSE;
+}
+
+/**
+ * ssp_restore_state - restore a previously saved SSP configuration
+ * @ssp: pointer to configuration saved by ssp_save_state
+ *
+ * Restore the SSP configuration saved previously by ssp_save_state.
+ */
+void ssp_restore_state(struct ssp_state *ssp)
+{
+	Ser4SSSR = SSSR_ROR;
+
+	Ser4SSCR0 = ssp->cr0 & ~SSCR0_SSE;
+	Ser4SSCR1 = ssp->cr1;
+	Ser4SSCR0 = ssp->cr0;
+}
+
+/**
+ * ssp_init - setup the SSP port
+ *
+ * initialise and claim resources for the SSP port.
+ *
+ * Returns:
+ *   %-ENODEV	if the SSP port is unavailable
+ *   %-EBUSY	if the resources are already in use
+ *   %0		on success
+ */
+int ssp_init(void)
+{
+	int ret;
+
+	if (!(PPAR & PPAR_SPR) && (Ser4MCCR0 & MCCR0_MCE))
+		return -ENODEV;
+
+	if (!request_mem_region(__PREG(Ser4SSCR0), 0x18, "SSP")) {
+		return -EBUSY;
+	}
+
+	Ser4SSSR = SSSR_ROR;
+
+	ret = request_irq(IRQ_Ser4SSP, ssp_interrupt, 0, "SSP", NULL);
+	if (ret)
+		goto out_region;
+
+	return 0;
+
+ out_region:
+	release_mem_region(__PREG(Ser4SSCR0), 0x18);
+	return ret;
+}
+
+/**
+ * ssp_exit - undo the effects of ssp_init
+ *
+ * release and free resources for the SSP port.
+ */
+void ssp_exit(void)
+{
+	Ser4SSCR0 &= ~SSCR0_SSE;
+
+	free_irq(IRQ_Ser4SSP, NULL);
+	release_mem_region(__PREG(Ser4SSCR0), 0x18);
+}
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("SA11x0 SSP PIO driver");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(ssp_write_word);
+EXPORT_SYMBOL(ssp_read_word);
+EXPORT_SYMBOL(ssp_flush);
+EXPORT_SYMBOL(ssp_enable);
+EXPORT_SYMBOL(ssp_disable);
+EXPORT_SYMBOL(ssp_save_state);
+EXPORT_SYMBOL(ssp_restore_state);
+EXPORT_SYMBOL(ssp_init);
+EXPORT_SYMBOL(ssp_exit);
diff -Nru a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c
--- a/arch/arm/mach-sa1100/system3.c	Sun Nov 17 07:31:13 2002
+++ b/arch/arm/mach-sa1100/system3.c	Thu Mar  6 08:48:29 2003
@@ -213,11 +213,17 @@
 static int sdram_notifier(struct notifier_block *nb, unsigned long event,
 		void *data)
 {
+	struct cpufreq_policy *policy = data;
 	switch (event) {
-		case CPUFREQ_MINMAX:
-			cpufreq_updateminmax(data, 147500, 206000);
+		case CPUFREQ_ADJUST:
+		case CPUFREQ_INCOMPATIBLE:
+			cpufreq_verify_within_limits(policy, 147500, 206000);
+			break;
+		case CPUFREQ_NOTIFY:
+			if ((policy->min < 147500) || 
+			    (policy->max > 206000))
+				panic("cpufreq failed to limit the speed\n");
 			break;
-
 	}
 	return 0;
 }
@@ -405,7 +411,7 @@
 		goto DONE;
 	}
 
-#if defined( CONFIG_CPU_FREQ )
+#ifdef CONFIG_CPU_FREQ
 	ret = cpufreq_register_notifier(&system3_clkchg_block);
 	if ( ret != 0 ) {
 		printk( KERN_WARNING"PT Digital Board: could not register clock scale callback\n" );
diff -Nru a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c
--- a/arch/arm/mm/fault-common.c	Sun Jan 12 09:11:08 2003
+++ b/arch/arm/mm/fault-common.c	Thu Mar  6 08:19:03 2003
@@ -342,20 +342,20 @@
 			 struct pt_regs *regs)
 {
 	struct task_struct *tsk;
-	unsigned int offset;
+	unsigned int index;
 	pgd_t *pgd, *pgd_k;
 	pmd_t *pmd, *pmd_k;
 
 	if (addr < TASK_SIZE)
 		return do_page_fault(addr, fsr, regs);
 
-	offset = __pgd_offset(addr);
+	index = pgd_index(addr);
 
 	/*
 	 * FIXME: CP15 C1 is write only on ARMv3 architectures.
 	 */
-	pgd = cpu_get_pgd() + offset;
-	pgd_k = init_mm.pgd + offset;
+	pgd = cpu_get_pgd() + index;
+	pgd_k = init_mm.pgd + index;
 
 	if (pgd_none(*pgd_k))
 		goto bad_area;
diff -Nru a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
--- a/arch/arm/tools/mach-types	Thu Jan 16 06:52:35 2003
+++ b/arch/arm/tools/mach-types	Thu Mar  6 06:57:42 2003
@@ -6,7 +6,7 @@
 # To add an entry into this database, please see Documentation/arm/README,
 # or contact rmk@arm.linux.org.uk
 #
-# Last update: Mon Jan 13 22:55:16 2003
+# Last update: Wed Mar 5 22:11:59 2003
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -228,7 +228,7 @@
 arnold			SA1100_ARNOLD		ARNOLD			217
 psiboard		SA1100_PSIBOARD		PSIBOARD		218
 jz8028			ARCH_JZ8028		JZ8028			219
-ipaq3			ARCH_IPAQ3		IPAQ3			220
+h5400			ARCH_IPAQ3		IPAQ3			220
 forte			SA1100_FORTE		FORTE			221
 acam			SA1100_ACAM		ACAM			222
 abox			SA1100_ABOX		ABOX			223
@@ -259,7 +259,7 @@
 stork_egg		ARCH_STORK_EGG		STORK_EGG		248
 wismo			SA1100_WISMO		WISMO			249
 ezlinx			ARCH_EZLINX		EZLINX			250
-at91rm9200		ARCH_AT91		AT91			251
+at91			ARCH_AT91		AT91			251
 orion			ARCH_ORION		ORION			252
 neptune			ARCH_NEPTUNE		NEPTUNE			253
 hackkit			SA1100_HACKKIT		HACKKIT			254
@@ -281,3 +281,27 @@
 siren			ARCH_SIREN		SIREN			270
 greenlake		ARCH_GREENLAKE		GREENLAKE		271
 argus			ARCH_ARGUS		ARGUS			272
+combadge		SA1100_COMBADGE		COMBADGE		273
+rokepxa			ARCH_ROKEPXA		ROKEPXA			274
+cintegrator		ARCH_CINTEGRATOR	CINTEGRATOR		275
+guidea07		ARCH_GUIDEA07		GUIDEA07		276
+tat257			ARCH_TAT257		TAT257			277
+igp2425			ARCH_IGP2425		IGP2425			278
+bluegrama		ARCH_BLUEGRAMMA		BLUEGRAMMA		279
+ipod			ARCH_IPOD		IPOD			280
+adsbitsyx		ARCH_ADSBITSYX		ADSBITSYX		281
+trizeps2		ARCH_TRIZEPS2		TRIZEPS2		282
+viper			ARCH_VIPER		VIPER			283
+adsbitsyplus		SA1100_ADSBITSYPLUS	ADSBITSYPLUS		284
+adsagc			SA1100_ADSAGC		ADSAGC			285
+stp7312			ARCH_STP7312		STP7312			286
+nx_phnx			ARCH_PXA255		PXA255			287
+wep_ep250		ARCH_WEP_EP250		WEP_EP250		288
+inhandelf3		ARCH_INHANDELF3		INHANDELF3		289
+adi_coyote		ARCH_ADI_COYOTE		ADI_COYOTE		290
+iyonix			ARCH_IYONIX		IYONIX			291
+damicam_sa1110		ARCH_DAMICAM_SA1110	DAMICAM_SA1110		292
+meg03			ARCH_MEG03		MEG03			293
+pxa_whitechapel		ARCH_PXA_WHITECHAPEL	PXA_WHITECHAPEL		294
+nwsc			ARCH_NWSC		NWSC			295
+nwlarm			ARCH_NWLARM		NWLARM			296
diff -Nru a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in
--- a/arch/arm/vmlinux-armo.lds.in	Wed Jan 15 09:48:42 2003
+++ b/arch/arm/vmlinux-armo.lds.in	Fri Feb 14 14:36:57 2003
@@ -38,6 +38,9 @@
 			*(.initcall6.init)
 			*(.initcall7.init)
 		__initcall_end = .;
+		__con_initcall_start = .;
+			*(.con_initcall.init)
+		__con_initcall_end = .;
 		. = ALIGN(32768);
 		__init_end = .;
 	}
diff -Nru a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in
--- a/arch/arm/vmlinux-armv.lds.in	Tue Feb 11 08:24:17 2003
+++ b/arch/arm/vmlinux-armv.lds.in	Wed Feb 19 07:21:37 2003
@@ -45,6 +45,9 @@
 			*(.initcall6.init)
 			*(.initcall7.init)
 		__initcall_end = .;
+		__con_initcall_start = .;
+			*(.con_initcall.init)
+		__con_initcall_end = .;
 		. = ALIGN(32);
 		__initramfs_start = .;
 			usr/built-in.o(.init.ramfs)
diff -Nru a/arch/cris/Kconfig b/arch/cris/Kconfig
--- a/arch/cris/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/cris/Kconfig	Sat Mar  8 14:50:37 2003
@@ -9,10 +9,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 	default y
diff -Nru a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c
--- a/arch/cris/kernel/irq.c	Thu Oct 31 07:28:36 2002
+++ b/arch/cris/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -228,11 +228,13 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0; i < NR_IRQS; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %10u %c %s",
 			i, kstat_cpu(0).irqs[i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -243,6 +245,8 @@
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/cris/vmlinux.lds.S b/arch/cris/vmlinux.lds.S
--- a/arch/cris/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/cris/vmlinux.lds.S	Fri Feb 14 14:37:05 2003
@@ -69,7 +69,12 @@
 		*(.initcall6.init);
 		*(.initcall7.init);
 		__initcall_end = .;
-
+	}
+	.con_initcall.init : {
+		__con_initcall_start = .;
+		*(.con_initcall.init)
+		__con_initcall_end = .;
+	
 		/* We fill to the next page, so we can discard all init
 		   pages without needing to consider what payload might be
 		   appended to the kernel image.  */
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig	Sun Mar  2 18:14:31 2003
+++ b/arch/i386/Kconfig	Sat Mar  8 14:50:37 2003
@@ -18,15 +18,6 @@
 	bool
 	default y
 
-config SWAP
-	bool "Support for paging of anonymous memory"
-	default y
-	help
-	  This option allows you to choose whether you want to have support
-	  for socalled swap devices or swap files in your kernel that are
-	  used to provide more virtual memory than the actual RAM present
-	  in your computer.  If unusre say Y.
-
 config SBUS
 	bool
 
@@ -488,7 +479,7 @@
 # Common NUMA Features
 config NUMA
 	bool "Numa Memory Allocation Support"
-	depends on (HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY)))
+	depends on (HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY))) || X86_PC
 
 config DISCONTIGMEM
 	bool
diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile
--- a/arch/i386/Makefile	Fri Feb 21 19:34:09 2003
+++ b/arch/i386/Makefile	Tue Mar  4 15:09:44 2003
@@ -92,7 +92,8 @@
 
 boot := arch/i386/boot
 
-.PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install
+.PHONY: zImage bzImage compressed zlilo bzlilo \
+	zdisk bzdisk fdimage fdimage144 fdimage288 install
 
 all: bzImage
 
@@ -110,8 +111,8 @@
 zdisk bzdisk: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk
 
-install: vmlinux
-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) install
+install fdimage fdimage144 fdimage288: vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
 
 archclean:
 	$(Q)$(MAKE) $(clean)=arch/i386/boot
@@ -122,5 +123,8 @@
   echo  '		   (your) ~/bin/installkernel or'
   echo  '		   (distribution) /sbin/installkernel or'
   echo  '		   install to $$(INSTALL_PATH) and run lilo'
+  echo  '  bzdisk       - Create a boot floppy in /dev/fd0'
+  echo  '  fdimage      - Create a boot floppy image'
 endef
 
+CLEAN_FILES += arch/$(ARCH)/boot/fdimage arch/$(ARCH)/boot/mtools.conf
diff -Nru a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
--- a/arch/i386/boot/Makefile	Mon Dec 30 23:11:35 2002
+++ b/arch/i386/boot/Makefile	Fri Mar  7 14:10:59 2003
@@ -62,8 +62,36 @@
 	$(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed \
 					IMAGE_OFFSET=$(IMAGE_OFFSET) $@
 
-zdisk: $(BOOTIMAGE)
-	dd bs=8192 if=$(BOOTIMAGE) of=/dev/fd0
+# Set this if you want to pass append arguments to the zdisk/fdimage kernel
+FDARGS = 
+
+$(obj)/mtools.conf: $(src)/mtools.conf.in
+	sed -e 's|@OBJ@|$(obj)|g' < $< > $@
+
+# This requires write access to /dev/fd0
+zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
+	MTOOLSRC=$(obj)/mtools.conf mformat a:			; sync
+	syslinux /dev/fd0					; sync
+	echo 'default linux $(FDARGS)' | \
+		MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux	; sync
+
+# These require being root or having syslinux 2.02 or higher installed
+fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf
+	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
+	MTOOLSRC=$(obj)/mtools.conf mformat v:			; sync
+	syslinux $(obj)/fdimage					; sync
+	echo 'default linux $(FDARGS)' | \
+		MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux	; sync
+
+fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
+	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880
+	MTOOLSRC=$(obj)/mtools.conf mformat w:			; sync
+	syslinux $(obj)/fdimage					; sync
+	echo 'default linux $(FDARGS)' | \
+		MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux	; sync
 
 zlilo: $(BOOTIMAGE)
 	if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
diff -Nru a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S
--- a/arch/i386/boot/bootsect.S	Fri Feb 21 06:03:16 2003
+++ b/arch/i386/boot/bootsect.S	Tue Mar  4 15:10:25 2003
@@ -4,29 +4,13 @@
  *	modified by Drew Eckhardt
  *	modified by Bruce Evans (bde)
  *	modified by Chris Noe (May 1999) (as86 -> gas)
- *
- * 360k/720k disk support: Andrzej Krzysztofowicz <ankry@green.mif.pg.gda.pl>
+ *	gutted by H. Peter Anvin (Jan 2003)
  *
  * BIG FAT NOTE: We're in real mode using 64k segments.  Therefore segment
  * addresses must be multiplied by 16 to obtain their respective linear
  * addresses. To avoid confusion, linear addresses are written using leading
  * hex while segment addresses are written as segment:offset.
  *
- * bde - should not jump blindly, there may be systems with only 512K low
- * memory.  Use int 0x12 to get the top of memory, etc.
- *
- * It then loads 'setup' directly after itself (0x90200), and the system
- * at 0x10000, using BIOS interrupts. 
- *
- * NOTE! currently system is at most (8*65536-4096) bytes long. This should 
- * be no problem, even in the future. I want to keep it simple. This 508 kB
- * kernel size should be enough, especially as this doesn't contain the
- * buffer cache as in minix (and especially now that the kernel is 
- * compressed :-)
- *
- * The loader has been made as simple as possible, and continuous
- * read errors will result in a unbreakable loop. Reboot by hand. It
- * loads pretty fast by getting whole tracks at a time whenever possible.
  */
 
 #include <asm/boot.h>
@@ -59,359 +43,51 @@
 .global _start
 _start:
 
-# First things first. Move ourself from 0x7C00 -> 0x90000 and jump there.
+	# Normalize the start address
+	jmpl	$BOOTSEG, $start2
 
-	movw	$BOOTSEG, %ax
-	movw	%ax, %ds		# %ds = BOOTSEG
-	movw	$INITSEG, %ax
-	movw	%ax, %es		# %ax = %es = INITSEG
-	movw	$256, %cx
-	subw	%si, %si
-	subw	%di, %di
-	cld
-	rep
-	movsw
-	ljmp	$INITSEG, $go
-
-# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde).  We
-# wouldn't have to worry about this if we checked the top of memory.  Also
-# my BIOS can be configured to put the wini drive tables in high memory
-# instead of in the vector table.  The old stack might have clobbered the
-# drive table.
-
-go:	movw	$0x4000-12, %di		# 0x4000 is an arbitrary value >=
-					# length of bootsect + length of
-					# setup + room for stack;
-					# 12 is disk parm size.
-	movw	%ax, %ds		# %ax and %es already contain INITSEG
+start2:
+	movw	%cs, %ax
+	movw	%ax, %ds
+	movw	%ax, %es
 	movw	%ax, %ss
-	movw	%di, %sp		# put stack at INITSEG:0x4000-12.
+	movw	$0x7c00, %sp
+	sti
+	cld
 
-# Many BIOS's default disk parameter tables will not recognize
-# multi-sector reads beyond the maximum sector number specified
-# in the default diskette parameter tables - this may mean 7
-# sectors in some cases.
-#
-# Since single sector reads are slow and out of the question,
-# we must take care of this by creating new parameter tables
-# (for the first disk) in RAM.  We will set the maximum sector
-# count to 36 - the most we will encounter on an ED 2.88.  
-#
-# High doesn't hurt.  Low does.
-#
-# Segments are as follows: %cs = %ds = %es = %ss = INITSEG, %fs = 0,
-# and %gs is unused.
-
-	movw	%cx, %fs		# %fs = 0
-	movw	$0x78, %bx		# %fs:%bx is parameter table address
-	pushw	%ds
-	ldsw	%fs:(%bx), %si		# %ds:%si is source
-	movb	$6, %cl			# copy 12 bytes
-	pushw	%di			# %di = 0x4000-12.
-	rep				# don't worry about cld
-	movsw				# already done above
-	popw	%di
-	popw	%ds
-	movb	$36, 0x4(%di)		# patch sector count
-	movw	%di, %fs:(%bx)
-	movw	%es, %fs:2(%bx)
-
-# Get disk drive parameters, specifically number of sectors/track.
-
-# It seems that there is no BIOS call to get the number of sectors.
-# Guess 36 sectors if sector 36 can be read, 18 sectors if sector 18
-# can be read, 15 if sector 15 can be read.  Otherwise guess 9.
-# Note that %cx = 0 from rep movsw above.
+	movw	$bugger_off_msg, %si
 
-	movw	$disksizes, %si		# table of sizes to try
-probe_loop:
+msg_loop:
 	lodsb
-	cbtw				# extend to word
-	movw	%ax, sectors
-	cmpw	$disksizes+4, %si
-	jae	got_sectors		# If all else fails, try 9
-
-	xchgw	%cx, %ax		# %cx = track and sector
-	xorw	%dx, %dx		# drive 0, head 0
-	movw	$0x0200, %bx		# address = 512, in INITSEG (%es = %cs)
-	movw	$0x0201, %ax		# service 2, 1 sector
-	int	$0x13
-	jc	probe_loop		# try next value
-
-got_sectors:
-	movb	$0x03, %ah		# read cursor pos
-	xorb	%bh, %bh
-	int	$0x10
-	movw	$9, %cx
-	movb	$0x07, %bl		# page 0, attribute 7 (normal)
-					# %bh is set above; int10 doesn't
-					# modify it
-	movw	$msg1, %bp
-	movw	$0x1301, %ax		# write string, move cursor
-	int	$0x10			# tell the user we're loading..
-
-# Load the setup-sectors directly after the moved bootblock (at 0x90200).
-# We should know the drive geometry to do it, as setup may exceed first
-# cylinder (for 9-sector 360K and 720K floppies).
-
-	movw	$0x0001, %ax		# set sread (sector-to-read) to 1 as
-	movw	$sread, %si		# the boot sector has already been read
-	movw	%ax, (%si)
-
-	call	kill_motor		# reset FDC
-	movw	$0x0200, %bx		# address = 512, in INITSEG
-next_step:
-	movb	setup_sects, %al
-	movw	sectors, %cx
-	subw	(%si), %cx		# (%si) = sread
-	cmpb	%cl, %al
-	jbe	no_cyl_crossing
-	movw	sectors, %ax
-	subw	(%si), %ax		# (%si) = sread
-no_cyl_crossing:
-	call	read_track
-	pushw	%ax			# save it
-	call	set_next		# set %bx properly; it uses %ax,%cx,%dx
-	popw	%ax			# restore
-	subb	%al, setup_sects	# rest - for next step
-	jnz	next_step
-
-	pushw	$SYSSEG
-	popw	%es			# %es = SYSSEG
-	call	read_it
-	call	kill_motor
-	call	print_nl
-
-# After that we check which root-device to use. If the device is
-# defined (!= 0), nothing is done and the given device is used.
-# Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8)
-# depending on the number of sectors we pretend to know we have.
-
-# Segments are as follows: %cs = %ds = %ss = INITSEG,
-#	%es = SYSSEG, %fs = 0, %gs is unused.
-
-	movw	root_dev, %ax
-	orw	%ax, %ax
-	jne	root_defined
-
-	movw	sectors, %bx
-	movw	$0x0208, %ax		# /dev/ps0 - 1.2Mb
-	cmpw	$15, %bx
-	je	root_defined
-
-	movb	$0x1c, %al		# /dev/PS0 - 1.44Mb
-	cmpw	$18, %bx
-	je	root_defined
-
-	movb	$0x20, %al		# /dev/fd0H2880 - 2.88Mb
-	cmpw	$36, %bx
-	je	root_defined
-
-	movb	$0, %al			# /dev/fd0 - autodetect
-root_defined:
-	movw	%ax, root_dev
-
-# After that (everything loaded), we jump to the setup-routine
-# loaded directly after the bootblock:
-
-	ljmp	$SETUPSEG, $0
-
-# These variables are addressed via %si register as it gives shorter code.
-
-sread:	.word 0				# sectors read of current track
-head:	.word 0				# current head
-track:	.word 0				# current track
-
-# This routine loads the system at address SYSSEG, making sure
-# no 64kB boundaries are crossed. We try to load it as fast as
-# possible, loading whole tracks whenever we can.
-
-read_it:
-	movw	%es, %ax		# %es = SYSSEG when called
-	testw	$0x0fff, %ax
-die:	jne	die			# %es must be at 64kB boundary
-	xorw	%bx, %bx		# %bx is starting address within segment
-rp_read:
-#ifdef __BIG_KERNEL__			# look in setup.S for bootsect_kludge
-	bootsect_kludge = 0x220		# 0x200 + 0x20 which is the size of the
-	lcall	*bootsect_kludge	# bootsector + bootsect_kludge offset
-#else
-	movw	%es, %ax
-	subw	$SYSSEG, %ax
-	movw	%bx, %cx
-	shr	$4, %cx
-	add	%cx, %ax		# check offset
-#endif
-	cmpw	syssize, %ax		# have we loaded everything yet?
-	jbe	ok1_read
-
-	ret
-
-ok1_read:
-	movw	sectors, %ax
-	subw	(%si), %ax		# (%si) = sread
-	movw	%ax, %cx
-	shlw	$9, %cx
-	addw	%bx, %cx
-	jnc	ok2_read
-
-	je	ok2_read
-
-	xorw	%ax, %ax
-	subw	%bx, %ax
-	shrw	$9, %ax
-ok2_read:
-	call	read_track
-	call	set_next
-	jmp	rp_read
-
-read_track:
-	pusha
-	pusha	
-	movw	$0xe2e, %ax 		# loading... message 2e = .
+	andb	%al, %al
+	jz	die
+	movb	$0xe, %ah
 	movw	$7, %bx
- 	int	$0x10
-	popa		
-
-# Accessing head, track, sread via %si gives shorter code.
+	int	$0x10
+	jmp	msg_loop
 
-	movw	4(%si), %dx		# 4(%si) = track
-	movw	(%si), %cx		# (%si)  = sread
-	incw	%cx
-	movb	%dl, %ch
-	movw	2(%si), %dx		# 2(%si) = head
-	movb	%dl, %dh
-	andw	$0x0100, %dx
-	movb	$2, %ah
-	pushw	%dx			# save for error dump
-	pushw	%cx
-	pushw	%bx
-	pushw	%ax
-	int	$0x13
-	jc	bad_rt
-
-	addw	$8, %sp
-	popa
-	ret
-
-set_next:
-	movw	%ax, %cx
-	addw	(%si), %ax		# (%si) = sread
-	cmp	sectors, %ax
-	jne	ok3_set
-	movw	$0x0001, %ax
-	xorw	%ax, 2(%si)		# change head
-	jne	ok4_set
-	incw	4(%si)			# next track
-ok4_set:
+die:
+	# Allow the user to press a key, then reboot
 	xorw	%ax, %ax
-ok3_set:
-	movw	%ax, (%si)		# set sread
-	shlw	$9, %cx
-	addw	%cx, %bx
-	jnc	set_next_fin
-	movw	%es, %ax
-	addb	$0x10, %ah
-	movw	%ax, %es
-	xorw	%bx, %bx
-set_next_fin:
-	ret
-
-bad_rt:
-	pushw	%ax			# save error code
-	call	print_all		# %ah = error, %al = read
-	xorb	%ah, %ah
-	xorb	%dl, %dl
-	int	$0x13
-	addw	$10, %sp
-	popa
-	jmp read_track
-
-# print_all is for debugging purposes.  
-#
-# it will print out all of the registers.  The assumption is that this is
-# called from a routine, with a stack frame like
-#
-#	%dx 
-#	%cx
-#	%bx
-#	%ax
-#	(error)
-#	ret <- %sp
- 
-print_all:
-	movw	$5, %cx			# error code + 4 registers
-	movw	%sp, %bp
-print_loop:
-	pushw	%cx			# save count remaining
-	call	print_nl		# <-- for readability
-	cmpb	$5, %cl
-	jae	no_reg			# see if register name is needed
-	
-	movw	$0xe05 + 'A' - 1, %ax
-	subb	%cl, %al
-	int	$0x10
-	movb	$'X', %al
-	int	$0x10
-	movb	$':', %al
-	int	$0x10
-no_reg:
-	addw	$2, %bp			# next register
-	call	print_hex		# print it
-	popw	%cx
-	loop	print_loop
-	ret
+	int	$0x16
+	int	$0x19
 
-print_nl:
-	movw	$0xe0d, %ax		# CR
-	int	$0x10
-	movb	$0xa, %al		# LF
-	int 	$0x10
-	ret
-
-# print_hex is for debugging purposes, and prints the word
-# pointed to by %ss:%bp in hexadecimal.
-
-print_hex:
-	movw	$4, %cx			# 4 hex digits
-	movw	(%bp), %dx		# load word into %dx
-print_digit:
-	rolw	$4, %dx			# rotate to use low 4 bits
-	movw	$0xe0f, %ax		# %ah = request
-	andb	%dl, %al		# %al = mask for nybble
-	addb	$0x90, %al		# convert %al to ascii hex
-	daa				# in only four instructions!
-	adc	$0x40, %al
-	daa
-	int	$0x10
-	loop	print_digit
-	ret
+	# int 0x19 should never return.  In case it does anyway,
+	# invoke the BIOS reset code...
+	ljmp	$0xf000,$0xfff0
 
-# This procedure turns off the floppy drive motor, so
-# that we enter the kernel in a known state, and
-# don't have to worry about it later.
-# NOTE: Doesn't save %ax or %dx; do it yourself if you need to.
-
-kill_motor:
-#if 1
-	xorw	%ax, %ax		# reset FDC
-	xorb	%dl, %dl
-	int	$0x13
-#else
-	movw	$0x3f2, %dx
-	xorb	%al, %al
-	outb	%al, %dx
-#endif
-	ret
 
-sectors:	.word 0
-disksizes:	.byte 36, 21, 18, 15, 9
-msg1:		.byte 13, 10
-		.ascii "Loading"
+bugger_off_msg:
+	.ascii	"Direct booting from floppy is no longer supported.\r\n"
+	.ascii	"Please use a boot loader program instead.\r\n"
+	.ascii	"\n"
+	.ascii	"Remove disk and press any key to reboot . . .\r\n"
+	.byte	0
+	
 
-# XXX: This is a fairly snug fit.
+	# Kernel attributes; used by setup
 
-.org 497
+	.org 497
 setup_sects:	.byte SETUPSECTS
 root_flags:	.word ROOT_RDONLY
 syssize:	.word SYSSIZE
diff -Nru a/arch/i386/boot/mtools.conf.in b/arch/i386/boot/mtools.conf.in
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/i386/boot/mtools.conf.in	Tue Mar  4 15:09:44 2003
@@ -0,0 +1,17 @@
+#
+# mtools configuration file for "make (b)zdisk"
+#
+
+# Actual floppy drive
+drive a:
+  file="/dev/fd0"
+
+# 1.44 MB floppy disk image
+drive v:
+  file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter
+
+# 2.88 MB floppy disk image (mostly for virtual uses)
+drive w:
+  file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter
+
+
diff -Nru a/arch/i386/boot/tools/build.c b/arch/i386/boot/tools/build.c
--- a/arch/i386/boot/tools/build.c	Mon Feb  4 23:41:17 2002
+++ b/arch/i386/boot/tools/build.c	Tue Mar  4 15:09:44 2003
@@ -150,13 +150,10 @@
 	sz = sb.st_size;
 	fprintf (stderr, "System is %d kB\n", sz/1024);
 	sys_size = (sz + 15) / 16;
-	/* 0x28000*16 = 2.5 MB, conservative estimate for the current maximum */
-	if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE))
+	/* 0x40000*16 = 4.0 MB, reasonable estimate for the current maximum */
+	if (sys_size > (is_big_kernel ? 0x40000 : DEF_SYSSIZE))
 		die("System is too big. Try using %smodules.",
 			is_big_kernel ? "" : "bzImage or ");
-	if (sys_size > 0xefff)
-		fprintf(stderr,"warning: kernel is too big for standalone boot "
-		    "from floppy\n");
 	while (sz > 0) {
 		int l, n;
 
diff -Nru a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
--- a/arch/i386/kernel/cpu/common.c	Wed Feb 19 17:48:55 2003
+++ b/arch/i386/kernel/cpu/common.c	Mon Mar 10 10:20:30 2003
@@ -480,7 +480,7 @@
 	 */
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
-	if(current->mm)
+	if (current->mm)
 		BUG();
 	enter_lazy_tlb(&init_mm, current, cpu);
 
@@ -508,7 +508,7 @@
 	/*
 	 * Force FPU initialization:
 	 */
-	clear_thread_flag(TIF_USEDFPU);
+	current_thread_info()->status = 0;
 	current->used_math = 0;
 	stts();
 }
diff -Nru a/arch/i386/kernel/cpu/cpufreq/acpi.c b/arch/i386/kernel/cpu/cpufreq/acpi.c
--- a/arch/i386/kernel/cpu/cpufreq/acpi.c	Fri Feb 28 07:59:47 2003
+++ b/arch/i386/kernel/cpu/cpufreq/acpi.c	Sat Mar  8 01:37:35 2003
@@ -619,6 +619,7 @@
 	.init		= acpi_cpufreq_cpu_init,
 	.exit		= acpi_cpufreq_cpu_exit,
 	.name		= "acpi-cpufreq",
+	.owner		= THIS_MODULE,
 };
 
 
diff -Nru a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c
--- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c	Fri Feb 28 07:52:11 2003
+++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c	Sat Mar  8 01:37:35 2003
@@ -250,6 +250,7 @@
 	.target 	= elanfreq_target,
 	.init		= elanfreq_cpu_init,
 	.name		= "elanfreq",
+	.owner		= THIS_MODULE,
 };
 
 
diff -Nru a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
--- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c	Fri Feb 28 07:52:11 2003
+++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c	Sat Mar  8 01:37:35 2003
@@ -451,6 +451,7 @@
 	.target		= cpufreq_gx_target,
 	.init		= cpufreq_gx_cpu_init,
 	.name		= "gx-suspmod",
+	.owner		= THIS_MODULE,
 };
 
 static int __init cpufreq_gx_init(void)
diff -Nru a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c	Fri Feb 28 08:02:11 2003
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c	Sat Mar  8 01:37:35 2003
@@ -649,6 +649,7 @@
 	.target 	= longhaul_target,
 	.init		= longhaul_cpu_init,
 	.name		= "longhaul",
+	.owner		= THIS_MODULE,
 };
 
 static int __init longhaul_init (void)
diff -Nru a/arch/i386/kernel/cpu/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c
--- a/arch/i386/kernel/cpu/cpufreq/longrun.c	Fri Feb 28 08:08:36 2003
+++ b/arch/i386/kernel/cpu/cpufreq/longrun.c	Sat Mar  8 01:37:35 2003
@@ -253,6 +253,7 @@
 	.setpolicy 	= longrun_set_policy,
 	.init		= longrun_cpu_init,
 	.name		= "longrun",
+	.owner		= THIS_MODULE,
 };
 
 
diff -Nru a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
--- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	Fri Feb 28 07:52:11 2003
+++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	Sat Mar  8 01:39:17 2003
@@ -214,6 +214,7 @@
 		else
 			p4clockmod_table[i].frequency = (stock_freq * i)/8;
 	}
+	cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu);
 	
 	/* cpuinfo and default policy values */
 	policy->policy = CPUFREQ_POLICY_PERFORMANCE;
@@ -226,9 +227,14 @@
 
 static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy)
 {
+	cpufreq_frequency_table_put_attr(policy->cpu);    
 	return cpufreq_p4_setdc(policy->cpu, DC_DISABLE);
 }
 
+static struct freq_attr* p4clockmod_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
 
 static struct cpufreq_driver p4clockmod_driver = {
 	.verify 	= cpufreq_p4_verify,
@@ -236,6 +242,8 @@
 	.init		= cpufreq_p4_cpu_init,
 	.exit		= cpufreq_p4_cpu_exit,
 	.name		= "p4-clockmod",
+	.owner		= THIS_MODULE,
+	.attr		= p4clockmod_attr,
 };
 
 
diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c	Fri Feb 28 08:03:44 2003
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c	Sat Mar  8 01:37:35 2003
@@ -190,6 +190,7 @@
 	.init		= powernow_k6_cpu_init,
 	.exit		= powernow_k6_cpu_exit,
 	.name		= "powernow-k6",
+	.owner		= THIS_MODULE,
 };
 
 
diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	Fri Feb 28 08:03:52 2003
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	Sat Mar  8 01:37:35 2003
@@ -377,6 +377,7 @@
 	.target 	= powernow_target,
 	.init		= powernow_cpu_init,
 	.name		= "powernow-k7",
+	.owner		= THIS_MODULE,
 };
 
 static int __init powernow_init (void)
diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep.c b/arch/i386/kernel/cpu/cpufreq/speedstep.c
--- a/arch/i386/kernel/cpu/cpufreq/speedstep.c	Fri Feb 28 08:04:04 2003
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep.c	Sat Mar  8 01:46:02 2003
@@ -29,7 +29,6 @@
 
 #include <asm/msr.h>
 
-
 /* speedstep_chipset:
  *   It is necessary to know which chipset is used. As accesses to 
  * this device occur at various places in this module, we need a 
@@ -40,7 +39,7 @@
 
 #define SPEEDSTEP_CHIPSET_ICH2M         0x00000002
 #define SPEEDSTEP_CHIPSET_ICH3M         0x00000003
-
+#define SPEEDSTEP_CHIPSET_ICH4M         0x00000004
 
 /* speedstep_processor
  */
@@ -106,6 +105,7 @@
 	switch (speedstep_chipset) {
 	case SPEEDSTEP_CHIPSET_ICH2M:
 	case SPEEDSTEP_CHIPSET_ICH3M:
+	case SPEEDSTEP_CHIPSET_ICH4M:
 		/* get PMBASE */
 		pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
 		if (!(pmbase & 0x01))
@@ -166,6 +166,7 @@
 	switch (speedstep_chipset) {
 	case SPEEDSTEP_CHIPSET_ICH2M:
 	case SPEEDSTEP_CHIPSET_ICH3M:
+	case SPEEDSTEP_CHIPSET_ICH4M:
 		/* get PMBASE */
 		pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
 		if (!(pmbase & 0x01))
@@ -245,6 +246,7 @@
 	switch (speedstep_chipset) {
 	case SPEEDSTEP_CHIPSET_ICH2M:
 	case SPEEDSTEP_CHIPSET_ICH3M:
+	case SPEEDSTEP_CHIPSET_ICH4M:
 	{
 		u16             value = 0;
 
@@ -277,6 +279,14 @@
 static unsigned int speedstep_detect_chipset (void)
 {
 	speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
+			      PCI_DEVICE_ID_INTEL_82801DB_12, 
+			      PCI_ANY_ID,
+			      PCI_ANY_ID,
+			      NULL);
+	if (speedstep_chipset_dev)
+		return SPEEDSTEP_CHIPSET_ICH4M;
+
+	speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
 			      PCI_DEVICE_ID_INTEL_82801CA_12, 
 			      PCI_ANY_ID,
 			      PCI_ANY_ID,
@@ -658,6 +668,7 @@
 	.verify 	= speedstep_verify,
 	.target 	= speedstep_target,
 	.init		= speedstep_cpu_init,
+	.owner		= THIS_MODULE,
 };
 
 
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	Tue Feb 25 11:06:46 2003
+++ b/arch/i386/kernel/entry.S	Mon Mar 10 14:41:23 2003
@@ -72,6 +72,12 @@
 NT_MASK		= 0x00004000
 VM_MASK		= 0x00020000
 
+/*
+ * ESP0 is at offset 4. 0x100 is the size of the TSS, and
+ * also thus the top-of-stack pointer offset of SYSENTER_ESP
+ */
+TSS_ESP0_OFFSET = (4 - 0x100)
+
 #ifdef CONFIG_PREEMPT
 #define preempt_stop		cli
 #else
@@ -229,6 +235,8 @@
 
 	# sysenter call handler stub
 ENTRY(sysenter_entry)
+	movl TSS_ESP0_OFFSET(%esp),%esp
+sysenter_past_esp:
 	sti
 	pushl $(__USER_DS)
 	pushl %ebp
@@ -458,12 +466,36 @@
 	addl $4, %esp
 	jmp ret_from_exception
 
+/*
+ * Debug traps and NMI can happen at the one SYSENTER instruction
+ * that sets up the real kernel stack. Check here, since we can't
+ * allow the wrong stack to be used.
+ *
+ * "TSS_ESP0_OFFSET+12" is because the NMI/debug handler will have
+ * already pushed 3 words if it hits on the sysenter instruction:
+ * eflags, cs and eip.
+ *
+ * We just load the right stack, and push the three (known) values
+ * by hand onto the new stack - while updating the return eip past
+ * the instruction that would have done it for sysenter.
+ */
+#define CHECK_SYSENTER_EIP			\
+	cmpl $sysenter_entry,(%esp);		\
+	jne 1f;					\
+	movl TSS_ESP0_OFFSET+12(%esp),%esp;	\
+	pushfl;					\
+	pushl $__KERNEL_CS;			\
+	pushl $sysenter_past_esp;		\
+1:
+
 ENTRY(debug)
+	CHECK_SYSENTER_EIP
 	pushl $0
 	pushl $do_debug
 	jmp error_code
 
 ENTRY(nmi)
+	CHECK_SYSENTER_EIP
 	pushl %eax
 	SAVE_ALL
 	movl %esp, %edx
diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
--- a/arch/i386/kernel/i386_ksyms.c	Fri Feb 28 00:05:34 2003
+++ b/arch/i386/kernel/i386_ksyms.c	Wed Mar  5 00:44:17 2003
@@ -68,6 +68,7 @@
 EXPORT_SYMBOL(MCA_bus);
 #ifdef CONFIG_DISCONTIGMEM
 EXPORT_SYMBOL(node_data);
+EXPORT_SYMBOL(physnode_map);
 #endif
 #ifdef CONFIG_X86_NUMAQ
 EXPORT_SYMBOL(xquad_portio);
diff -Nru a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c
--- a/arch/i386/kernel/i387.c	Mon Dec  2 12:31:00 2002
+++ b/arch/i386/kernel/i387.c	Mon Mar 10 10:20:30 2003
@@ -52,29 +52,13 @@
  * FPU lazy state save handling.
  */
 
-static inline void __save_init_fpu( struct task_struct *tsk )
-{
-	if ( cpu_has_fxsr ) {
-		asm volatile( "fxsave %0 ; fnclex"
-			      : "=m" (tsk->thread.i387.fxsave) );
-	} else {
-		asm volatile( "fnsave %0 ; fwait"
-			      : "=m" (tsk->thread.i387.fsave) );
-	}
-	clear_tsk_thread_flag(tsk, TIF_USEDFPU);
-}
-
-void save_init_fpu( struct task_struct *tsk )
-{
-	__save_init_fpu(tsk);
-	stts();
-}
-
 void kernel_fpu_begin(void)
 {
+	struct thread_info *thread = current_thread_info();
+
 	preempt_disable();
-	if (test_thread_flag(TIF_USEDFPU)) {
-		__save_init_fpu(current);
+	if (thread->status & TS_USEDFPU) {
+		__save_init_fpu(thread->task);
 		return;
 	}
 	clts();
diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
--- a/arch/i386/kernel/io_apic.c	Sun Mar  2 18:13:32 2003
+++ b/arch/i386/kernel/io_apic.c	Sat Mar  8 14:50:47 2003
@@ -221,8 +221,9 @@
 #  define Dprintk(x...) 
 # endif
 
-extern unsigned long irq_affinity [NR_IRQS];
-int __cacheline_aligned pending_irq_balance_apicid [NR_IRQS];
+extern unsigned long irq_affinity[NR_IRQS];
+
+static int __cacheline_aligned pending_irq_balance_apicid[NR_IRQS];
 static int irqbalance_disabled = NO_BALANCE_IRQ;
 static int physical_balance = 0;
 
@@ -251,8 +252,54 @@
 #define BALANCED_IRQ_LESS_DELTA		(HZ)
 
 long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL;
-					 
-static inline void balance_irq(int cpu, int irq);
+
+static unsigned long move(int curr_cpu, unsigned long allowed_mask,
+			unsigned long now, int direction)
+{
+	int search_idle = 1;
+	int cpu = curr_cpu;
+
+	goto inside;
+
+	do {
+		if (unlikely(cpu == curr_cpu))
+			search_idle = 0;
+inside:
+		if (direction == 1) {
+			cpu++;
+			if (cpu >= NR_CPUS)
+				cpu = 0;
+		} else {
+			cpu--;
+			if (cpu == -1)
+				cpu = NR_CPUS-1;
+		}
+	} while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) ||
+			(search_idle && !IDLE_ENOUGH(cpu,now)));
+
+	return cpu;
+}
+
+static inline void balance_irq(int cpu, int irq)
+{
+	unsigned long now = jiffies;
+	unsigned long allowed_mask;
+	unsigned int new_cpu;
+		
+	if (irqbalance_disabled)
+		return;
+
+	allowed_mask = cpu_online_map & irq_affinity[irq];
+	new_cpu = move(cpu, allowed_mask, now, 1);
+	if (cpu != new_cpu) {
+		irq_desc_t *desc = irq_desc + irq;
+		unsigned long flags;
+
+		spin_lock_irqsave(&desc->lock, flags);
+		pending_irq_balance_apicid[irq]=cpu_to_logical_apicid(new_cpu);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
+}
 
 static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold)
 {
@@ -263,7 +310,8 @@
 			if (!irq_desc[j].action)
 				continue;
 			/* Is it a significant load ?  */
-			if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) < useful_load_threshold)
+			if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) <
+						useful_load_threshold)
 				continue;
 			balance_irq(i, j);
 		}
@@ -430,7 +478,8 @@
 	 * We seek the least loaded sibling by making the comparison
 	 * (A+B)/2 vs B
 	 */
-	if (physical_balance && (CPU_IRQ(min_loaded) >> 1) > CPU_IRQ(cpu_sibling_map[min_loaded]))
+	if (physical_balance && (CPU_IRQ(min_loaded) >> 1) >
+					CPU_IRQ(cpu_sibling_map[min_loaded]))
 		min_loaded = cpu_sibling_map[min_loaded];
 
 	allowed_mask = cpu_online_map & irq_affinity[selected_irq];
@@ -438,11 +487,15 @@
 
 	if (target_cpu_mask & allowed_mask) {
 		irq_desc_t *desc = irq_desc + selected_irq;
-		Dprintk("irq = %d moved to cpu = %d\n", selected_irq, min_loaded);
+		unsigned long flags;
+
+		Dprintk("irq = %d moved to cpu = %d\n",
+				selected_irq, min_loaded);
 		/* mark for change destination */
-		spin_lock(&desc->lock);
-		pending_irq_balance_apicid[selected_irq] = cpu_to_logical_apicid(min_loaded);
-		spin_unlock(&desc->lock);
+		spin_lock_irqsave(&desc->lock, flags);
+		pending_irq_balance_apicid[selected_irq] =
+				cpu_to_logical_apicid(min_loaded);
+		spin_unlock_irqrestore(&desc->lock, flags);
 		/* Since we made a change, come back sooner to 
 		 * check for more variation.
 		 */
@@ -453,58 +506,16 @@
 	goto tryanotherirq;
 
 not_worth_the_effort:
-	/* if we did not find an IRQ to move, then adjust the time interval upward */
+	/*
+	 * if we did not find an IRQ to move, then adjust the time interval
+	 * upward
+	 */
 	balanced_irq_interval = min((long)MAX_BALANCED_IRQ_INTERVAL,
 		balanced_irq_interval + BALANCED_IRQ_MORE_DELTA);	
 	Dprintk("IRQ worth rotating not found\n");
 	return;
 }
 
-static unsigned long move(int curr_cpu, unsigned long allowed_mask, unsigned long now, int direction)
-{
-	int search_idle = 1;
-	int cpu = curr_cpu;
-
-	goto inside;
-
-	do {
-		if (unlikely(cpu == curr_cpu))
-			search_idle = 0;
-inside:
-		if (direction == 1) {
-			cpu++;
-			if (cpu >= NR_CPUS)
-				cpu = 0;
-		} else {
-			cpu--;
-			if (cpu == -1)
-				cpu = NR_CPUS-1;
-		}
-	} while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) ||
-			(search_idle && !IDLE_ENOUGH(cpu,now)));
-
-	return cpu;
-}
-
-static inline void balance_irq (int cpu, int irq)
-{
-	unsigned long now = jiffies;
-	unsigned long allowed_mask;
-	unsigned int new_cpu;
-		
-	if (irqbalance_disabled)
-		return;
-
-	allowed_mask = cpu_online_map & irq_affinity[irq];
-	new_cpu = move(cpu, allowed_mask, now, 1);
-	if (cpu != new_cpu) {
-		irq_desc_t *desc = irq_desc + irq;
-		spin_lock(&desc->lock);
-		pending_irq_balance_apicid[irq] = cpu_to_logical_apicid(new_cpu);
-		spin_unlock(&desc->lock);
-	}
-}
-
 int balanced_irq(void *unused)
 {
 	int i;
@@ -516,26 +527,32 @@
 	/* push everything to CPU 0 to give us a starting point.  */
 	for (i = 0 ; i < NR_IRQS ; i++)
 		pending_irq_balance_apicid[i] = cpu_to_logical_apicid(0);
-	for (;;) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		time_remaining = schedule_timeout(time_remaining);
-		if (time_after(jiffies, prev_balance_time+balanced_irq_interval)) {
-			Dprintk("balanced_irq: calling do_irq_balance() %lu\n", jiffies);
-			do_irq_balance();
-			prev_balance_time = jiffies;
-			time_remaining = balanced_irq_interval;
-		}
-        }
+
+repeat:
+	set_current_state(TASK_INTERRUPTIBLE);
+	time_remaining = schedule_timeout(time_remaining);
+	if (time_after(jiffies, prev_balance_time+balanced_irq_interval)) {
+		Dprintk("balanced_irq: calling do_irq_balance() %lu\n",
+					jiffies);
+		do_irq_balance();
+		prev_balance_time = jiffies;
+		time_remaining = balanced_irq_interval;
+	}
+	goto repeat;
 }
 
 static int __init balanced_irq_init(void)
 {
 	int i;
 	struct cpuinfo_x86 *c;
+
         c = &boot_cpu_data;
 	if (irqbalance_disabled)
 		return 0;
-	/* Enable physical balance only if more than 1 physical processor is present */
+	/*
+	 * Enable physical balance only if more than 1 physical processor
+	 * is present
+	 */
 	if (smp_num_siblings > 1 && cpu_online_map >> 2)
 		physical_balance = 1;
 
@@ -1150,11 +1167,8 @@
 	enable_8259A_irq(0);
 }
 
-void __init UNEXPECTED_IO_APIC(void)
+static inline void UNEXPECTED_IO_APIC(void)
 {
-	printk(KERN_WARNING "INFO: unexpected IO-APIC, please file a report at\n");
-	printk(KERN_WARNING "      http://bugzilla.kernel.org\n");
-	printk(KERN_WARNING "      if your kernel is less than 3 months old.\n");
 }
 
 void __init print_IO_APIC(void)
@@ -1566,7 +1580,7 @@
  */
 static int __init timer_irq_works(void)
 {
-	unsigned int t1 = jiffies;
+	unsigned long t1 = jiffies;
 
 	local_irq_enable();
 	/* Let ten ticks pass... */
diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
--- a/arch/i386/kernel/irq.c	Tue Feb 25 01:38:22 2003
+++ b/arch/i386/kernel/irq.c	Sat Mar  8 14:50:44 2003
@@ -135,43 +135,47 @@
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_printf(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
 		if (cpu_online(j))
-			p += seq_printf(p, "CPU%d       ",j);
+			seq_printf(p, "CPU%d       ",j);
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for (j = 0; j < NR_CPUS; j++)
 			if (cpu_online(j))
-				p += seq_printf(p, "%10u ",
-					     kstat_cpu(j).irqs[i]);
+				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
+
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "NMI: ");
 	for (j = 0; j < NR_CPUS; j++)
 		if (cpu_online(j))
-			p += seq_printf(p, "%10u ", nmi_count(j));
+			seq_printf(p, "%10u ", nmi_count(j));
 	seq_putc(p, '\n');
 #if CONFIG_X86_LOCAL_APIC
 	seq_printf(p, "LOC: ");
 	for (j = 0; j < NR_CPUS; j++)
 		if (cpu_online(j))
-			p += seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs);
+			seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs);
 	seq_putc(p, '\n');
 #endif
 	seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
diff -Nru a/arch/i386/kernel/numaq.c b/arch/i386/kernel/numaq.c
--- a/arch/i386/kernel/numaq.c	Fri Feb 28 00:05:34 2003
+++ b/arch/i386/kernel/numaq.c	Tue Mar  4 23:41:55 2003
@@ -31,8 +31,7 @@
 #include <asm/numaq.h>
 
 /* These are needed before the pgdat's are created */
-unsigned long node_start_pfn[MAX_NUMNODES];
-unsigned long node_end_pfn[MAX_NUMNODES];
+extern long node_start_pfn[], node_end_pfn[];
 
 #define	MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT))
 
@@ -64,26 +63,6 @@
 		}
 	}
 }
-
-/*
- * -----------------------------------------
- *
- * functions related to physnode_map
- *
- * -----------------------------------------
- */
-/*
- * physnode_map keeps track of the physical memory layout of the
- * numaq nodes on a 256Mb break (each element of the array will
- * represent 256Mb of memory and will be marked by the node id.  so,
- * if the first gig is on node 0, and the second gig is on node 1
- * physnode_map will contain:
- * physnode_map[0-3] = 0;
- * physnode_map[4-7] = 1;
- * physnode_map[8- ] = -1;
- */
-int physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
-EXPORT_SYMBOL(physnode_map);
 
 /*
  * for each node mark the regions
diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
--- a/arch/i386/kernel/process.c	Thu Feb 20 20:33:52 2003
+++ b/arch/i386/kernel/process.c	Mon Mar 10 10:20:30 2003
@@ -275,6 +275,15 @@
 	release_x86_irqs(dead_task);
 }
 
+/*
+ * This gets called before we allocate a new thread and copy
+ * the current task into it.
+ */
+void prepare_to_copy(struct task_struct *tsk)
+{
+	unlazy_fpu(tsk);
+}
+
 int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
 	unsigned long unused,
 	struct task_struct * p, struct pt_regs * regs)
@@ -297,9 +306,6 @@
 	savesegment(gs,p->thread.gs);
 
 	tsk = current;
-	unlazy_fpu(tsk);
-	struct_cpy(&p->thread.i387, &tsk->thread.i387);
-
 	if (unlikely(NULL != tsk->thread.ts_io_bitmap)) {
 		p->thread.ts_io_bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
 		if (!p->thread.ts_io_bitmap)
diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
--- a/arch/i386/kernel/smpboot.c	Tue Feb 25 10:47:22 2003
+++ b/arch/i386/kernel/smpboot.c	Tue Mar  4 23:41:54 2003
@@ -966,6 +966,7 @@
 		if (APIC_init_uniprocessor())
 			printk(KERN_NOTICE "Local APIC not detected."
 					   " Using dummy APIC emulation.\n");
+		map_cpu_to_logical_apicid();
 		return;
 	}
 
diff -Nru a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c
--- a/arch/i386/kernel/srat.c	Mon Feb 24 23:13:14 2003
+++ b/arch/i386/kernel/srat.c	Wed Mar  5 00:44:17 2003
@@ -57,8 +57,7 @@
 static int zholes_size_init;
 static unsigned long zholes_size[MAX_NUMNODES * MAX_NR_ZONES];
 
-unsigned long node_start_pfn[MAX_NUMNODES];
-unsigned long node_end_pfn[MAX_NUMNODES];
+extern unsigned long node_start_pfn[], node_end_pfn[];
 
 extern void * boot_ioremap(unsigned long, unsigned long);
 
@@ -182,30 +181,19 @@
 	}
 }
 
-/*
- * physnode_map keeps track of the physical memory layout of the
- * numaq nodes on a 256Mb break (each element of the array will
- * represent 256Mb of memory and will be marked by the node id.  so,
- * if the first gig is on node 0, and the second gig is on node 1
- * physnode_map will contain:
- * physnode_map[0-3] = 0;
- * physnode_map[4-7] = 1;
- * physnode_map[8- ] = -1;
- */
-int pfnnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
-EXPORT_SYMBOL(pfnnode_map);
-
-static void __init initialize_pfnnode_map(void)
+static void __init initialize_physnode_map(void)
 {
-	unsigned long topofchunk, cur = 0;
 	int i;
-	
-	for (i = 0; i < num_memory_chunks; i++) {
-		cur = node_memory_chunk[i].start_pfn;
-		topofchunk = node_memory_chunk[i].end_pfn;
-		while (cur < topofchunk) {
-			pfnnode_map[PFN_TO_ELEMENT(cur)] = node_memory_chunk[i].nid;
-			cur ++;
+	unsigned long pfn;
+	struct node_memory_chunk_s *nmcp;
+
+	/* Run the list of memory chunks and fill in the phymap. */
+	nmcp = node_memory_chunk;
+	for (i = num_memory_chunks; --i >= 0; nmcp++) {
+		for (pfn = nmcp->start_pfn; pfn <= nmcp->end_pfn;
+						pfn += PAGES_PER_ELEMENT)
+		{
+			physnode_map[pfn / PAGES_PER_ELEMENT] = (int)nmcp->nid;
 		}
 	}
 }
@@ -272,7 +260,7 @@
 	for (i = 0; i < num_memory_chunks; i++)
 		node_memory_chunk[i].nid = pxm_to_nid_map[node_memory_chunk[i].pxm];
 
-	initialize_pfnnode_map();
+	initialize_physnode_map();
 	
 	printk("pxm bitmap: ");
 	for (i = 0; i < sizeof(pxm_bitmap); i++) {
diff -Nru a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c
--- a/arch/i386/kernel/sysenter.c	Sun Mar  2 18:13:32 2003
+++ b/arch/i386/kernel/sysenter.c	Mon Mar 10 14:41:23 2003
@@ -40,8 +40,10 @@
 	int cpu = get_cpu();
 	struct tss_struct *tss = init_tss + cpu;
 
+	tss->ss1 = __KERNEL_CS;
+	tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss;
 	wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
-	wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp0, 0);
+	wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp1, 0);
 	wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0);
 
 	printk("Enabling SEP on CPU %d\n", cpu);
diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
--- a/arch/i386/kernel/traps.c	Fri Feb 21 17:44:10 2003
+++ b/arch/i386/kernel/traps.c	Mon Mar 10 10:20:30 2003
@@ -737,13 +737,14 @@
  */
 asmlinkage void math_state_restore(struct pt_regs regs)
 {
-	struct task_struct *tsk = current;
-	clts();		/* Allow maths ops (or we recurse) */
+	struct thread_info *thread = current_thread_info();
+	struct task_struct *tsk = thread->task;
 
+	clts();		/* Allow maths ops (or we recurse) */
 	if (!tsk->used_math)
 		init_fpu(tsk);
 	restore_fpu(tsk);
-	set_thread_flag(TIF_USEDFPU);	/* So we fnsave on switch_to() */
+	thread->status |= TS_USEDFPU;	/* So we fnsave on switch_to() */
 }
 
 #ifndef CONFIG_MATH_EMULATION
diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
--- a/arch/i386/kernel/vm86.c	Sat Feb 15 19:30:17 2003
+++ b/arch/i386/kernel/vm86.c	Sun Mar  9 18:49:37 2003
@@ -291,7 +291,7 @@
 
 	tss = init_tss + smp_processor_id();
 	tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
-	disable_sysenter();
+	disable_sysenter(tss);
 
 	tsk->thread.screen_bitmap = info->screen_bitmap;
 	if (info->flags & VM86_SCREEN_BITMAP)
diff -Nru a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
--- a/arch/i386/mm/discontig.c	Fri Feb 28 15:08:58 2003
+++ b/arch/i386/mm/discontig.c	Tue Mar  4 23:41:55 2003
@@ -36,11 +36,36 @@
 struct pglist_data *node_data[MAX_NUMNODES];
 bootmem_data_t node0_bdata;
 
+/*
+ * numa interface - we expect the numa architecture specfic code to have
+ *                  populated the following initialisation.
+ *
+ * 1) numnodes         - the total number of nodes configured in the system
+ * 2) physnode_map     - the mapping between a pfn and owning node
+ * 3) node_start_pfn   - the starting page frame number for a node
+ * 3) node_end_pfn     - the ending page fram number for a node
+ */
+
+/*
+ * physnode_map keeps track of the physical memory layout of a generic
+ * numa node on a 256Mb break (each element of the array will
+ * represent 256Mb of memory and will be marked by the node id.  so,
+ * if the first gig is on node 0, and the second gig is on node 1
+ * physnode_map will contain:
+ *
+ *     physnode_map[0-3] = 0;
+ *     physnode_map[4-7] = 1;
+ *     physnode_map[8- ] = -1;
+ */
+u8 physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
+
+unsigned long node_start_pfn[MAX_NUMNODES];
+unsigned long node_end_pfn[MAX_NUMNODES];
+
 extern unsigned long find_max_low_pfn(void);
 extern void find_max_pfn(void);
 extern void one_highpage_init(struct page *, int, int);
 
-extern unsigned long node_start_pfn[], node_end_pfn[];
 extern struct e820map e820;
 extern char _end;
 extern unsigned long highend_pfn, highstart_pfn;
@@ -55,6 +80,36 @@
 unsigned long node_remap_offset[MAX_NUMNODES];
 void *node_remap_start_vaddr[MAX_NUMNODES];
 void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
+
+/*
+ * FLAT - support for basic PC memory model with discontig enabled, essentially
+ *        a single node with all available processors in it with a flat
+ *        memory map.
+ */
+void __init get_memcfg_numa_flat(void)
+{
+	int pfn;
+
+	printk("NUMA - single node, flat memory mode\n");
+
+	/* Run the memory configuration and find the top of memory. */
+	find_max_pfn();
+	node_start_pfn[0]  = 0;
+	node_end_pfn[0]	  = max_pfn;
+
+	/* Fill in the physnode_map with our simplistic memory model,
+	* all memory is in node 0.
+	*/
+	for (pfn = node_start_pfn[0]; pfn <= node_end_pfn[0];
+	       pfn += PAGES_PER_ELEMENT)
+	{
+		physnode_map[pfn / PAGES_PER_ELEMENT] = 0;
+	}
+
+         /* Indicate there is one node available. */
+	node_set_online(0);
+	numnodes = 1;
+}
 
 /*
  * Find the highest page frame number we have available for the node
diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
--- a/arch/i386/mm/fault.c	Fri Jan 10 19:29:47 2003
+++ b/arch/i386/mm/fault.c	Thu Mar  6 08:19:03 2003
@@ -394,14 +394,14 @@
 		 * Do _not_ use "tsk" here. We might be inside
 		 * an interrupt in the middle of a task switch..
 		 */
-		int offset = __pgd_offset(address);
+		int index = pgd_index(address);
 		pgd_t *pgd, *pgd_k;
 		pmd_t *pmd, *pmd_k;
 		pte_t *pte_k;
 
 		asm("movl %%cr3,%0":"=r" (pgd));
-		pgd = offset + (pgd_t *)__va(pgd);
-		pgd_k = init_mm.pgd + offset;
+		pgd = index + (pgd_t *)__va(pgd);
+		pgd_k = init_mm.pgd + index;
 
 		if (!pgd_present(*pgd_k))
 			goto no_context;
diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c
--- a/arch/i386/mm/init.c	Mon Feb  3 23:46:49 2003
+++ b/arch/i386/mm/init.c	Thu Mar  6 08:19:07 2003
@@ -98,26 +98,26 @@
 {
 	pgd_t *pgd;
 	pmd_t *pmd;
-	int pgd_ofs, pmd_ofs;
+	int pgd_idx, pmd_idx;
 	unsigned long vaddr;
 
 	vaddr = start;
-	pgd_ofs = __pgd_offset(vaddr);
-	pmd_ofs = __pmd_offset(vaddr);
-	pgd = pgd_base + pgd_ofs;
+	pgd_idx = pgd_index(vaddr);
+	pmd_idx = pmd_index(vaddr);
+	pgd = pgd_base + pgd_idx;
 
-	for ( ; (pgd_ofs < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_ofs++) {
+	for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
 		if (pgd_none(*pgd)) 
 			one_md_table_init(pgd);
 
 		pmd = pmd_offset(pgd, vaddr);
-		for (; (pmd_ofs < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_ofs++) {
+		for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
 			if (pmd_none(*pmd)) 
 				one_page_table_init(pmd);
 
 			vaddr += PMD_SIZE;
 		}
-		pmd_ofs = 0;
+		pmd_idx = 0;
 	}
 }
 
@@ -132,17 +132,17 @@
 	pgd_t *pgd;
 	pmd_t *pmd;
 	pte_t *pte;
-	int pgd_ofs, pmd_ofs, pte_ofs;
+	int pgd_idx, pmd_idx, pte_ofs;
 
-	pgd_ofs = __pgd_offset(PAGE_OFFSET);
-	pgd = pgd_base + pgd_ofs;
+	pgd_idx = pgd_index(PAGE_OFFSET);
+	pgd = pgd_base + pgd_idx;
 	pfn = 0;
 
-	for (; pgd_ofs < PTRS_PER_PGD; pgd++, pgd_ofs++) {
+	for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
 		pmd = one_md_table_init(pgd);
 		if (pfn >= max_low_pfn)
 			continue;
-		for (pmd_ofs = 0; pmd_ofs < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_ofs++) {
+		for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
 			/* Map with big pages if possible, otherwise create normal page tables. */
 			if (cpu_has_pse) {
 				set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
@@ -214,7 +214,7 @@
 	vaddr = PKMAP_BASE;
 	page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
 
-	pgd = swapper_pg_dir + __pgd_offset(vaddr);
+	pgd = swapper_pg_dir + pgd_index(vaddr);
 	pmd = pmd_offset(pgd, vaddr);
 	pte = pte_offset_kernel(pmd, vaddr);
 	pkmap_page_table = pte;	
diff -Nru a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
--- a/arch/i386/mm/ioremap.c	Mon Feb 24 23:13:24 2003
+++ b/arch/i386/mm/ioremap.c	Thu Mar  6 06:34:47 2003
@@ -148,7 +148,7 @@
 	 */
 	offset = phys_addr & ~PAGE_MASK;
 	phys_addr &= PAGE_MASK;
-	size = PAGE_ALIGN(last_addr) - phys_addr;
+	size = PAGE_ALIGN(last_addr+1) - phys_addr;
 
 	/*
 	 * Ok, go for it..
diff -Nru a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
--- a/arch/i386/mm/pgtable.c	Sun Mar  2 18:14:31 2003
+++ b/arch/i386/mm/pgtable.c	Thu Mar  6 08:19:03 2003
@@ -64,7 +64,7 @@
 	pmd_t *pmd;
 	pte_t *pte;
 
-	pgd = swapper_pg_dir + __pgd_offset(vaddr);
+	pgd = swapper_pg_dir + pgd_index(vaddr);
 	if (pgd_none(*pgd)) {
 		BUG();
 		return;
@@ -104,7 +104,7 @@
 		printk ("set_pmd_pfn: pfn misaligned\n");
 		return; /* BUG(); */
 	}
-	pgd = swapper_pg_dir + __pgd_offset(vaddr);
+	pgd = swapper_pg_dir + pgd_index(vaddr);
 	if (pgd_none(*pgd)) {
 		printk ("set_pmd_pfn: pgd_none\n");
 		return; /* BUG(); */
diff -Nru a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c
--- a/arch/i386/oprofile/nmi_int.c	Sun Mar  2 18:13:32 2003
+++ b/arch/i386/oprofile/nmi_int.c	Wed Mar  5 11:46:56 2003
@@ -58,7 +58,7 @@
 	unsigned int const nr_ctrls = model->num_controls; 
 	struct op_msr_group * counters = &msrs->counters;
 	struct op_msr_group * controls = &msrs->controls;
-	int i;
+	unsigned int i;
 
 	for (i = 0; i < nr_ctrs; ++i) {
 		rdmsr(counters->addrs[i],
@@ -108,7 +108,7 @@
 	unsigned int const nr_ctrls = model->num_controls; 
 	struct op_msr_group * counters = &msrs->counters;
 	struct op_msr_group * controls = &msrs->controls;
-	int i;
+	unsigned int i;
 
 	for (i = 0; i < nr_ctrls; ++i) {
 		wrmsr(controls->addrs[i],
@@ -182,7 +182,7 @@
 
 static int nmi_create_files(struct super_block * sb, struct dentry * root)
 {
-	int i;
+	unsigned int i;
 
 	for (i = 0; i < model->num_counters; ++i) {
 		struct dentry * dir;
diff -Nru a/arch/i386/oprofile/op_model_athlon.c b/arch/i386/oprofile/op_model_athlon.c
--- a/arch/i386/oprofile/op_model_athlon.c	Thu Jan 23 12:24:53 2003
+++ b/arch/i386/oprofile/op_model_athlon.c	Sun Mar  9 05:09:00 2003
@@ -104,10 +104,11 @@
 		if (CTR_OVERFLOWED(low)) {
 			oprofile_add_sample(eip, is_kernel, i, cpu);
 			CTR_WRITE(reset_value[i], msrs, i);
-			return 1;
 		}
 	}
-	return 0;
+
+	/* See op_model_ppro.c */
+	return 1;
 }
 
  
diff -Nru a/arch/i386/oprofile/op_model_p4.c b/arch/i386/oprofile/op_model_p4.c
--- a/arch/i386/oprofile/op_model_p4.c	Thu Jan 30 19:57:28 2003
+++ b/arch/i386/oprofile/op_model_p4.c	Sun Mar  9 05:08:41 2003
@@ -389,7 +389,7 @@
 
 static void p4_fill_in_addresses(struct op_msrs * const msrs)
 {
-	int i; 
+	unsigned int i; 
 	unsigned int addr, stag;
 
 	setup_num_counters();
@@ -608,13 +608,14 @@
  			CTR_WRITE(reset_value[i], real);
 			/* P4 quirk: you have to re-unmask the apic vector */
 			apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
-			return 1;
 		}
 	}
 
 	/* P4 quirk: you have to re-unmask the apic vector */
 	apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
-	return 0;
+
+	/* See op_model_ppro.c */
+	return 1;
 }
 
 
diff -Nru a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c
--- a/arch/i386/oprofile/op_model_ppro.c	Thu Jan 23 12:24:53 2003
+++ b/arch/i386/oprofile/op_model_ppro.c	Sun Mar  9 06:15:07 2003
@@ -98,10 +98,17 @@
 		if (CTR_OVERFLOWED(low)) {
 			oprofile_add_sample(eip, is_kernel, i, cpu);
 			CTR_WRITE(reset_value[i], msrs, i);
-			return 1;
 		}
 	}
-	return 0;
+
+	/* We can't work out if we really handled an interrupt. We
+	 * might have caught a *second* counter just after overflowing
+	 * the interrupt for this counter then arrives
+	 * and we don't find a counter that's overflowed, so we
+	 * would return 0 and get dazed + confused. Instead we always
+	 * assume we found an overflow. This sucks.
+	 */
+	return 1;
 }
 
  
diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
--- a/arch/i386/pci/irq.c	Mon Oct  7 07:36:47 2002
+++ b/arch/i386/pci/irq.c	Fri Mar  7 19:36:28 2003
@@ -804,6 +804,7 @@
 int pirq_enable_irq(struct pci_dev *dev)
 {
 	u8 pin;
+	extern int interrupt_line_quirk;
 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 	if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
 		char *msg;
@@ -813,9 +814,17 @@
 			msg = "";
 		else
 			msg = " Please try using pci=biosirq.";
+			
+		/* With IDE legacy devices the IRQ lookup failure is not a problem.. */
+		if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5))
+			return 0;
+			
 		printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
 		       'A' + pin - 1, dev->slot_name, msg);
 	}
-
+	/* VIA bridges use interrupt line for apic/pci steering across
+	   the V-Link */
+	else if (interrupt_line_quirk)
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
 	return 0;
 }
diff -Nru a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S
--- a/arch/i386/vmlinux.lds.S	Tue Feb 18 18:58:52 2003
+++ b/arch/i386/vmlinux.lds.S	Sun Feb 16 15:55:23 2003
@@ -74,6 +74,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/ia64/Kconfig	Sat Mar  8 14:50:37 2003
@@ -22,11 +22,7 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
-config RWSEM_GENERIC_SPINLOCK
+config RWSEM_XCHGADD_ALGORITHM
 	bool
 	default y
 
@@ -424,6 +420,18 @@
 
 	  If you don't know what to do here, say N.
 
+config PREEMPT
+	bool "Preemptible Kernel"
+        help
+          This option reduces the latency of the kernel when reacting to
+          real-time or interactive events by allowing a low priority process to
+          be preempted even if it is in kernel mode executing a system call.
+          This allows applications to run more reliably even when the system is
+          under load.
+
+          Say Y here if you are building a kernel for a desktop, embedded
+          or real-time system.  Say N if you are unsure.
+
 config IA32_SUPPORT
 	bool "Support running of Linux/x86 binaries"
 	help
@@ -874,6 +882,12 @@
 	  and certain other kinds of spinlock errors commonly made.  This is
 	  best used in conjunction with the NMI watchdog so that spinlock
 	  deadlocks are also debuggable.
+
+config DEBUG_SPINLOCK_SLEEP
+	  bool "Sleep-inside-spinlock checking"
+	  help
+	    If you say Y here, various routines which may sleep will become very
+	    noisy if they are called with a spinlock held.
 
 config IA64_DEBUG_CMPXCHG
 	bool "Turn on compare-and-exchange bug checking (slow!)"
diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile
--- a/arch/ia64/Makefile	Thu Feb  6 22:47:17 2003
+++ b/arch/ia64/Makefile	Mon Feb 24 05:40:16 2003
@@ -52,18 +52,19 @@
 core-$(CONFIG_IA64_HP_ZX1)	+= arch/ia64/dig/
 core-$(CONFIG_IA64_SGI_SN)	+= arch/ia64/sn/kernel/ \
 				   arch/ia64/sn/io/ \
+				   arch/ia64/sn/io/sn2/ \
+				   arch/ia64/sn/io/sn2/pcibr/ \
 				   arch/ia64/sn/kernel/sn2/
 drivers-$(CONFIG_PCI)		+= arch/ia64/pci/
 drivers-$(CONFIG_IA64_HP_SIM)	+= arch/ia64/hp/sim/
 drivers-$(CONFIG_IA64_HP_ZX1)	+= arch/ia64/hp/common/ arch/ia64/hp/zx1/
-drivers-$(CONFIG_IA64_SGI_SN)	+= arch/ia64/sn/fakeprom/
 
 boot := arch/ia64/boot
 tools := arch/ia64/tools
 
 .PHONY: boot compressed include/asm-ia64/offsets.h
 
-all: vmlinux
+all: prepare vmlinux
 
 compressed: vmlinux.gz
 
diff -Nru a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
--- a/arch/ia64/hp/sim/simscsi.c	Tue Feb  4 17:06:04 2003
+++ b/arch/ia64/hp/sim/simscsi.c	Wed Feb 12 00:11:32 2003
@@ -156,7 +156,7 @@
 	if (sc->request_bufflen < req.len)
 		return;
 
-	stat.fd = desc[sc->target];
+	stat.fd = desc[sc->device->id];
 	if (DBG)
 		printk("simscsi_%s @ %lx (off %lx)\n",
 		       mode == SSC_READ ? "read":"write", req.addr, offset);
@@ -178,7 +178,7 @@
 	struct disk_stat stat;
 	struct disk_req req;
 
-	stat.fd = desc[sc->target];
+	stat.fd = desc[sc->device->id];
 
 	while (list_len) {
 		req.addr = __pa(page_address(sl->page) + sl->offset);
@@ -259,6 +259,7 @@
 int
 simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *))
 {
+	unsigned int target_id = sc->device->id;
 	char fname[MAX_ROOT_LEN+16];
 	size_t disk_size;
 	char *buf;
@@ -267,21 +268,21 @@
 
 	if (DBG)
 		printk("simscsi_queuecommand: target=%d,cmnd=%u,sc=%lu,sp=%lx,done=%p\n",
-		       sc->target, sc->cmnd[0], sc->serial_number, sp, done);
+		       target_id, sc->cmnd[0], sc->serial_number, sp, done);
 #endif
 
 	sc->result = DID_BAD_TARGET << 16;
 	sc->scsi_done = done;
-	if (sc->target <= 15 && sc->lun == 0) {
+	if (target_id <= 15 && sc->device->lun == 0) {
 		switch (sc->cmnd[0]) {
 		      case INQUIRY:
 			if (sc->request_bufflen < 35) {
 				break;
 			}
-			sprintf (fname, "%s%c", simscsi_root, 'a' + sc->target);
-			desc[sc->target] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS,
-						    0, 0, SSC_OPEN);
-			if (desc[sc->target] < 0) {
+			sprintf (fname, "%s%c", simscsi_root, 'a' + target_id);
+			desc[target_id] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS,
+						   0, 0, SSC_OPEN);
+			if (desc[target_id] < 0) {
 				/* disk doesn't exist... */
 				break;
 			}
@@ -303,37 +304,37 @@
 			break;
 
 		      case READ_6:
-			if (desc[sc->target] < 0 )
+			if (desc[target_id] < 0 )
 				break;
 			simscsi_readwrite6(sc, SSC_READ);
 			break;
 
 		      case READ_10:
-			if (desc[sc->target] < 0 )
+			if (desc[target_id] < 0 )
 				break;
 			simscsi_readwrite10(sc, SSC_READ);
 			break;
 
 		      case WRITE_6:
-			if (desc[sc->target] < 0)
+			if (desc[target_id] < 0)
 				break;
 			simscsi_readwrite6(sc, SSC_WRITE);
 			break;
 
 		      case WRITE_10:
-			if (desc[sc->target] < 0)
+			if (desc[target_id] < 0)
 				break;
 			simscsi_readwrite10(sc, SSC_WRITE);
 			break;
 
 
 		      case READ_CAPACITY:
-			if (desc[sc->target] < 0 || sc->request_bufflen < 8) {
+			if (desc[target_id] < 0 || sc->request_bufflen < 8) {
 				break;
 			}
 			buf = sc->request_buffer;
 
-			disk_size = simscsi_get_disk_size(desc[sc->target]);
+			disk_size = simscsi_get_disk_size(desc[target_id]);
 
 			/* pretend to be a 1GB disk (partition table contains real stuff): */
 			buf[0] = (disk_size >> 24) & 0xff;
diff -Nru a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
--- a/arch/ia64/hp/sim/simserial.c	Tue Feb  4 17:06:04 2003
+++ b/arch/ia64/hp/sim/simserial.c	Thu Feb 13 05:43:47 2003
@@ -63,7 +63,6 @@
 
 static char *serial_name = "SimSerial driver";
 static char *serial_version = "0.6";
-static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  * This has been extracted from asm/serial.h. We need one eventually but
@@ -235,14 +234,14 @@
 
 	if (!tty || !info->xmit.buf) return;
 
-	spin_lock_irqsave(&serial_lock, flags);
+	local_irq_save(flags);
 	if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) {
-		spin_unlock_irqrestore(&serial_lock, flags);
+		local_irq_restore(flags);
 		return;
 	}
 	info->xmit.buf[info->xmit.head] = ch;
 	info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
-	spin_unlock_irqrestore(&serial_lock, flags);
+	local_irq_restore(flags);
 }
 
 static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
@@ -250,7 +249,8 @@
 	int count;
 	unsigned long flags;
 
-	spin_lock_irqsave(&serial_lock, flags);
+
+	local_irq_save(flags);
 
 	if (info->x_char) {
 		char c = info->x_char;
@@ -293,7 +293,7 @@
 		info->xmit.tail += count;
 	}
 out:
-	spin_unlock_irqrestore(&serial_lock, flags);
+	local_irq_restore(flags);
 }
 
 static void rs_flush_chars(struct tty_struct *tty)
@@ -334,7 +334,7 @@
 				break;
 			}
 
-			spin_lock_irqsave(&serial_lock, flags);
+			local_irq_save(flags);
 			{
 				c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail,
 						       SERIAL_XMIT_SIZE);
@@ -344,7 +344,7 @@
 				info->xmit.head = ((info->xmit.head + c) &
 						   (SERIAL_XMIT_SIZE-1));
 			}
-			spin_unlock_irqrestore(&serial_lock, flags);
+			local_irq_restore(flags);
 
 			buf += c;
 			count -= c;
@@ -352,7 +352,7 @@
 		}
 		up(&tmp_buf_sem);
 	} else {
-		spin_lock_irqsave(&serial_lock, flags);
+		local_irq_save(flags);
 		while (1) {
 			c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
 			if (count < c)
@@ -367,7 +367,7 @@
 			count -= c;
 			ret += c;
 		}
-		spin_unlock_irqrestore(&serial_lock, flags);
+		local_irq_restore(flags);
 	}
 	/*
 	 * Hey, we transmit directly from here in our case
@@ -398,9 +398,9 @@
 	struct async_struct *info = (struct async_struct *)tty->driver_data;
 	unsigned long flags;
 
-	spin_lock_irqsave(&serial_lock, flags);
+	local_irq_save(flags);
 	info->xmit.head = info->xmit.tail = 0;
-	spin_unlock_irqrestore(&serial_lock, flags);
+	local_irq_restore(flags);
 
 	wake_up_interruptible(&tty->write_wait);
 
@@ -573,7 +573,7 @@
 	       state->irq);
 #endif
 
-	spin_lock_irqsave(&serial_lock, flags);
+	local_irq_save(flags);
 	{
 		/*
 		 * First unlink the serial port from the IRQ chain...
@@ -611,7 +611,7 @@
 
 		info->flags &= ~ASYNC_INITIALIZED;
 	}
-	spin_unlock_irqrestore(&serial_lock, flags);
+	local_irq_restore(flags);
 }
 
 /*
@@ -634,13 +634,13 @@
 
 	state = info->state;
 
-	spin_lock_irqsave(&serial_lock, flags);
+	local_irq_save(flags);
 	if (tty_hung_up_p(filp)) {
 #ifdef SIMSERIAL_DEBUG
 		printk("rs_close: hung_up\n");
 #endif
 		MOD_DEC_USE_COUNT;
-		spin_unlock_irqrestore(&serial_lock, flags);
+		local_irq_restore(flags);
 		return;
 	}
 #ifdef SIMSERIAL_DEBUG
@@ -665,11 +665,11 @@
 	}
 	if (state->count) {
 		MOD_DEC_USE_COUNT;
-		spin_unlock_irqrestore(&serial_lock, flags);
+		local_irq_restore(flags);
 		return;
 	}
 	info->flags |= ASYNC_CLOSING;
-	spin_unlock_irqrestore(&serial_lock, flags);
+	local_irq_restore(flags);
 
 	/*
 	 * Now we wait for the transmit buffer to clear; and we notify
@@ -776,7 +776,7 @@
 	if (!page)
 		return -ENOMEM;
 
-	spin_lock_irqsave(&serial_lock, flags);
+	local_irq_save(flags);
 
 	if (info->flags & ASYNC_INITIALIZED) {
 		free_page(page);
@@ -857,11 +857,11 @@
 	}
 
 	info->flags |= ASYNC_INITIALIZED;
-	spin_unlock_irqrestore(&serial_lock, flags);
+	local_irq_restore(flags);
 	return 0;
 
 errout:
-	spin_unlock_irqrestore(&serial_lock, flags);
+	local_irq_restore(flags);
 	return retval;
 }
 
diff -Nru a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
--- a/arch/ia64/ia32/ia32_entry.S	Sun Jan 12 16:07:06 2003
+++ b/arch/ia64/ia32/ia32_entry.S	Sat Mar  8 11:30:11 2003
@@ -300,7 +300,7 @@
 	data8 compat_sys_statfs
 	data8 compat_sys_fstatfs	  /* 100 */
 	data8 sys32_ioperm
-	data8 sys32_socketcall
+	data8 compat_sys_socketcall
 	data8 sys_syslog
 	data8 compat_sys_setitimer
 	data8 compat_sys_getitimer	  /* 105 */
@@ -424,6 +424,26 @@
 	data8 sys_ni_syscall		/* reserved for Security */
 	data8 sys_gettid
 	data8 sys_readahead	  /* 225 */
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall	/* 230 */
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall	/* 235 */
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 compat_sys_futex	/* 240 */
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall	/* 245 */
 	data8 sys_ni_syscall
 	data8 sys_ni_syscall
 	data8 sys_ni_syscall
diff -Nru a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c
--- a/arch/ia64/ia32/ia32_ioctl.c	Tue Feb  4 17:06:05 2003
+++ b/arch/ia64/ia32/ia32_ioctl.c	Thu Mar  6 11:06:44 2003
@@ -97,11 +97,9 @@
 	int info;		/* [o] auxiliary information */
 } sg_io_hdr32_t;  /* 64 bytes long (on IA32) */
 
-struct iovec32 { unsigned int iov_base; int iov_len; };
-
 static int alloc_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
 {
-	struct iovec32 *uiov = (struct iovec32 *) P(uptr32);
+	struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32);
 	sg_iovec_t *kiov;
 	int i;
 
@@ -136,7 +134,7 @@
 
 static int copy_back_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
 {
-	struct iovec32 *uiov = (struct iovec32 *) P(uptr32);
+	struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32);
 	sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
 	int i;
 
diff -Nru a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c
--- a/arch/ia64/ia32/ia32_support.c	Fri Jan 17 14:56:29 2003
+++ b/arch/ia64/ia32/ia32_support.c	Thu Jan 30 06:14:13 2003
@@ -93,7 +93,7 @@
 {
 	unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd, tssd;
 	struct pt_regs *regs = ia64_task_regs(t);
-	int nr = smp_processor_id();	/* LDT and TSS depend on CPU number: */
+	int nr = get_cpu();	/* LDT and TSS depend on CPU number: */
 
 	eflag = t->thread.eflag;
 	fsr = t->thread.fsr;
@@ -119,6 +119,7 @@
 
 	regs->r17 = (_TSS(nr) << 48) | (_LDT(nr) << 32) | (__u32) regs->r17;
 	regs->r30 = load_desc(_LDT(nr));				/* LDTD */
+	put_cpu();
 }
 
 /*
diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
--- a/arch/ia64/ia32/sys_ia32.c	Tue Feb 18 10:25:13 2003
+++ b/arch/ia64/ia32/sys_ia32.c	Sat Mar  8 11:30:11 2003
@@ -924,12 +924,11 @@
 			    (struct compat_timeval *) A(a.tvp));
 }
 
-struct iovec32 { unsigned int iov_base; int iov_len; };
 asmlinkage ssize_t sys_readv (unsigned long,const struct iovec *,unsigned long);
 asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long);
 
 static struct iovec *
-get_iovec32 (struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type)
+get_compat_iovec (struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type)
 {
 	int i;
 	u32 buf, len;
@@ -939,7 +938,7 @@
 
 	if (!count)
 		return 0;
-	if (verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count))
+	if (verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*count))
 		return NULL;
 	if (count > UIO_MAXIOV)
 		return NULL;
@@ -971,14 +970,14 @@
 }
 
 asmlinkage long
-sys32_readv (int fd, struct iovec32 *vector, u32 count)
+sys32_readv (int fd, struct compat_iovec *vector, u32 count)
 {
 	struct iovec iovstack[UIO_FASTIOV];
 	struct iovec *iov;
 	long ret;
 	mm_segment_t old_fs = get_fs();
 
-	iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE);
+	iov = get_compat_iovec(vector, iovstack, count, VERIFY_WRITE);
 	if (!iov)
 		return -EFAULT;
 	set_fs(KERNEL_DS);
@@ -990,14 +989,14 @@
 }
 
 asmlinkage long
-sys32_writev (int fd, struct iovec32 *vector, u32 count)
+sys32_writev (int fd, struct compat_iovec *vector, u32 count)
 {
 	struct iovec iovstack[UIO_FASTIOV];
 	struct iovec *iov;
 	long ret;
 	mm_segment_t old_fs = get_fs();
 
-	iov = get_iovec32(vector, iovstack, count, VERIFY_READ);
+	iov = get_compat_iovec(vector, iovstack, count, VERIFY_READ);
 	if (!iov)
 		return -EFAULT;
 	set_fs(KERNEL_DS);
@@ -1080,701 +1079,6 @@
 }
 
 /*
- *  Declare the IA32 version of the msghdr
- */
-
-struct msghdr32 {
-	unsigned int    msg_name;	/* Socket name			*/
-	int		msg_namelen;	/* Length of name		*/
-	unsigned int    msg_iov;	/* Data blocks			*/
-	unsigned int	msg_iovlen;	/* Number of blocks		*/
-	unsigned int    msg_control;	/* Per protocol magic (eg BSD file descriptor passing) */
-	unsigned int	msg_controllen;	/* Length of cmsg list */
-	unsigned	msg_flags;
-};
-
-struct cmsghdr32 {
-	compat_size_t cmsg_len;
-	int               cmsg_level;
-	int               cmsg_type;
-};
-
-/* Bleech... */
-#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
-#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen)	cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
-#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
-#define CMSG32_DATA(cmsg) \
-	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
-#define CMSG32_SPACE(len) \
-	(CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
-#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
-#define __CMSG32_FIRSTHDR(ctl,len) \
-	((len) >= sizeof(struct cmsghdr32) ? (struct cmsghdr32 *)(ctl) : (struct cmsghdr32 *)NULL)
-#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-
-static inline struct cmsghdr32 *
-__cmsg32_nxthdr (void *ctl, __kernel_size_t size, struct cmsghdr32 *cmsg, int cmsg_len)
-{
-	struct cmsghdr32 * ptr;
-
-	ptr = (struct cmsghdr32 *)(((unsigned char *) cmsg) + CMSG32_ALIGN(cmsg_len));
-	if ((unsigned long)((char*)(ptr+1) - (char *) ctl) > size)
-		return NULL;
-	return ptr;
-}
-
-static inline struct cmsghdr32 *
-cmsg32_nxthdr (struct msghdr *msg, struct cmsghdr32 *cmsg, int cmsg_len)
-{
-	return __cmsg32_nxthdr(msg->msg_control, msg->msg_controllen, cmsg, cmsg_len);
-}
-
-static inline int
-get_msghdr32 (struct msghdr *mp, struct msghdr32 *mp32)
-{
-	int ret;
-	unsigned int i;
-
-	if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32)))
-		return -EFAULT;
-	ret = __get_user(i, &mp32->msg_name);
-	mp->msg_name = (void *)A(i);
-	ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen);
-	ret |= __get_user(i, &mp32->msg_iov);
-	mp->msg_iov = (struct iovec *)A(i);
-	ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen);
-	ret |= __get_user(i, &mp32->msg_control);
-	mp->msg_control = (void *)A(i);
-	ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen);
-	ret |= __get_user(mp->msg_flags, &mp32->msg_flags);
-	return ret ? -EFAULT : 0;
-}
-
-/*
- * There is a lot of hair here because the alignment rules (and thus placement) of cmsg
- * headers and length are different for 32-bit apps.  -DaveM
- */
-static int
-get_cmsghdr32 (struct msghdr *kmsg, unsigned char *stackbuf, struct sock *sk, size_t *bufsize)
-{
-	struct cmsghdr *kcmsg, *kcmsg_base;
-	__kernel_size_t kcmlen, tmp;
-	compat_size_t ucmlen;
-	struct cmsghdr32 *ucmsg;
-	long err;
-
-	kcmlen = 0;
-	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while (ucmsg != NULL) {
-		if (get_user(ucmlen, &ucmsg->cmsg_len))
-			return -EFAULT;
-
-		/* Catch bogons. */
-		if (CMSG32_ALIGN(ucmlen) < CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if ((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) + ucmlen)
-		    > kmsg->msg_controllen)
-			return -EINVAL;
-
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmlen += tmp;
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-	if (kcmlen == 0)
-		return -EINVAL;
-
-	/*
-	 * The kcmlen holds the 64-bit version of the control length.  It may not be
-	 * modified as we do not stick it into the kmsg until we have successfully copied
-	 * over all of the data from the user.
-	 */
-	if (kcmlen > *bufsize) {
-		*bufsize = kcmlen;
-		kcmsg_base = kcmsg = sock_kmalloc(sk, kcmlen, GFP_KERNEL);
-	}
-	if (kcmsg == NULL)
-		return -ENOBUFS;
-
-	/* Now copy them over neatly. */
-	memset(kcmsg, 0, kcmlen);
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while (ucmsg != NULL) {
-		err = get_user(ucmlen, &ucmsg->cmsg_len);
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmsg->cmsg_len = tmp;
-		err |= get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
-		err |= get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
-		/* Copy over the data. */
-		err |= copy_from_user(CMSG_DATA(kcmsg), CMSG32_DATA(ucmsg),
-				      (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))));
-		if (err)
-			goto out_free_efault;
-
-		/* Advance. */
-		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-
-	/* Ok, looks like we made it.  Hook it up and return success. */
-	kmsg->msg_control = kcmsg_base;
-	kmsg->msg_controllen = kcmlen;
-	return 0;
-
-out_free_efault:
-	if (kcmsg_base != (struct cmsghdr *)stackbuf)
-		sock_kfree_s(sk, kcmsg_base, kcmlen);
-	return -EFAULT;
-}
-
-/*
- *	Verify & re-shape IA32 iovec. The caller must ensure that the
- *      iovec is big enough to hold the re-shaped message iovec.
- *
- *	Save time not doing verify_area. copy_*_user will make this work
- *	in any case.
- *
- *	Don't need to check the total size for overflow (cf net/core/iovec.c),
- *	32-bit sizes can't overflow a 64-bit count.
- */
-
-static inline int
-verify_iovec32 (struct msghdr *m, struct iovec *iov, char *address, int mode)
-{
-	int size, err, ct;
-	struct iovec32 *iov32;
-
-	if (m->msg_namelen) {
-		if (mode == VERIFY_READ) {
-			err = move_addr_to_kernel(m->msg_name, m->msg_namelen, address);
-			if (err < 0)
-				goto out;
-		}
-		m->msg_name = address;
-	} else
-		m->msg_name = NULL;
-
-	err = -EFAULT;
-	size = m->msg_iovlen * sizeof(struct iovec32);
-	if (copy_from_user(iov, m->msg_iov, size))
-		goto out;
-	m->msg_iov = iov;
-
-	err = 0;
-	iov32 = (struct iovec32 *)iov;
-	for (ct = m->msg_iovlen; ct-- > 0; ) {
-		iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len;
-		iov[ct].iov_base = (void *) A(iov32[ct].iov_base);
-		err += iov[ct].iov_len;
-	}
-out:
-	return err;
-}
-
-static void
-put_cmsg32(struct msghdr *kmsg, int level, int type, int len, void *data)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	struct cmsghdr32 cmhdr;
-	int cmlen = CMSG32_LEN(len);
-
-	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		return;
-	}
-
-	if(kmsg->msg_controllen < cmlen) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		cmlen = kmsg->msg_controllen;
-	}
-	cmhdr.cmsg_level = level;
-	cmhdr.cmsg_type = type;
-	cmhdr.cmsg_len = cmlen;
-
-	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
-		return;
-	if(copy_to_user(CMSG32_DATA(cm), data,
-			cmlen - sizeof(struct cmsghdr32)))
-		return;
-	cmlen = CMSG32_SPACE(len);
-	kmsg->msg_control += cmlen;
-	kmsg->msg_controllen -= cmlen;
-}
-
-static void
-scm_detach_fds32 (struct msghdr *kmsg, struct scm_cookie *scm)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32))
-		/ sizeof(int);
-	int fdnum = scm->fp->count;
-	struct file **fp = scm->fp->fp;
-	int *cmfptr;
-	int err = 0, i;
-
-	if (fdnum < fdmax)
-		fdmax = fdnum;
-
-	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm);
-	     i < fdmax;
-	     i++, cmfptr++) {
-		int new_fd;
-		err = get_unused_fd();
-		if (err < 0)
-			break;
-		new_fd = err;
-		err = put_user(new_fd, cmfptr);
-		if (err) {
-			put_unused_fd(new_fd);
-			break;
-		}
-		/* Bump the usage count and install the file. */
-		get_file(fp[i]);
-		current->files->fd[new_fd] = fp[i];
-	}
-
-	if (i > 0) {
-		int cmlen = CMSG32_LEN(i * sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
-		if (!err)
-			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
-		if (!err)
-			err = put_user(cmlen, &cm->cmsg_len);
-		if (!err) {
-			cmlen = CMSG32_SPACE(i * sizeof(int));
-			kmsg->msg_control += cmlen;
-			kmsg->msg_controllen -= cmlen;
-		}
-	}
-	if (i < fdnum)
-		kmsg->msg_flags |= MSG_CTRUNC;
-
-	/*
-	 * All of the files that fit in the message have had their
-	 * usage counts incremented, so we just free the list.
-	 */
-	__scm_destroy(scm);
-}
-
-/*
- * In these cases we (currently) can just copy to data over verbatim because all CMSGs
- * created by the kernel have well defined types which have the same layout in both the
- * 32-bit and 64-bit API.  One must add some special cased conversions here if we start
- * sending control messages with incompatible types.
- *
- * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
- * we do our work.  The remaining cases are:
- *
- * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
- *		IP_TTL		int			32-bit clean
- *		IP_TOS		__u8			32-bit clean
- *		IP_RECVOPTS	variable length		32-bit clean
- *		IP_RETOPTS	variable length		32-bit clean
- *		(these last two are clean because the types are defined
- *		 by the IPv4 protocol)
- *		IP_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in	32-bit clean
- * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in6	32-bit clean
- *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
- *		IPV6_HOPLIMIT	int			32-bit clean
- *		IPV6_FLOWINFO	u32			32-bit clean
- *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
- *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
- *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
- *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
- */
-static void
-cmsg32_recvmsg_fixup (struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
-{
-	unsigned char *workbuf, *wp;
-	unsigned long bufsz, space_avail;
-	struct cmsghdr *ucmsg;
-	long err;
-
-	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
-	space_avail = kmsg->msg_controllen + bufsz;
-	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
-	if (workbuf == NULL)
-		goto fail;
-
-	/* To make this more sane we assume the kernel sends back properly
-	 * formatted control messages.  Because of how the kernel will truncate
-	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
-	 */
-	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
-	while (((unsigned long)ucmsg) < ((unsigned long)kmsg->msg_control)) {
-		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
-		int clen64, clen32;
-
-		/*
-		 * UCMSG is the 64-bit format CMSG entry in user-space.  KCMSG32 is within
-		 * the kernel space temporary buffer we use to convert into a 32-bit style
-		 * CMSG.
-		 */
-		err = get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
-		err |= get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
-		err |= get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
-		if (err)
-			goto fail2;
-
-		clen64 = kcmsg32->cmsg_len;
-		copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
-			       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
-		clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
-			  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
-		kcmsg32->cmsg_len = clen32;
-
-		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
-		wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
-	}
-
-	/* Copy back fixed up data, and adjust pointers. */
-	bufsz = (wp - workbuf);
-	if (copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz))
-		goto fail2;
-
-	kmsg->msg_control = (struct cmsghdr *) (((char *)orig_cmsg_uptr) + bufsz);
-	kmsg->msg_controllen = space_avail - bufsz;
-	kfree(workbuf);
-	return;
-
-  fail2:
-	kfree(workbuf);
-  fail:
-	/*
-	 * If we leave the 64-bit format CMSG chunks in there, the application could get
-	 * confused and crash.  So to ensure greater recovery, we report no CMSGs.
-	 */
-	kmsg->msg_controllen += bufsz;
-	kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-/* XXX This really belongs in some header file... -DaveM */
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain -
-					   16 for IP, 16 for IPX,
-					   24 for IPv6,
-					   about 80 for AX.25 */
-/*
- *	BSD sendmsg interface
- */
-
-int
-sys32_sendmsg (int fd, struct msghdr32 *msg, unsigned flags)
-{
-	struct socket *sock;
-	char address[MAX_SOCK_ADDR];
-	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
-	unsigned char ctl[sizeof(struct cmsghdr) + 20];	/* 20 is size of ipv6_pktinfo */
-	unsigned char *ctl_buf = ctl;
-	struct msghdr msg_sys;
-	int err, iov_size, total_len;
-	size_t ctl_len;
-
-	err = -EFAULT;
-	if (get_msghdr32(&msg_sys, msg))
-		goto out;
-
-	sock = sockfd_lookup(fd, &err);
-	if (!sock)
-		goto out;
-
-	/* do not move before msg_sys is valid */
-	err = -EINVAL;
-	if (msg_sys.msg_iovlen > UIO_MAXIOV)
-		goto out_put;
-
-	/* Check whether to allocate the iovec area*/
-	err = -ENOMEM;
-	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32);
-	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
-		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
-		if (!iov)
-			goto out_put;
-	}
-
-	/* This will also move the address data into kernel space */
-	err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ);
-	if (err < 0)
-		goto out_freeiov;
-	total_len = err;
-
-	err = -ENOBUFS;
-
-	if (msg_sys.msg_controllen > INT_MAX)
-		goto out_freeiov;
-	if (msg_sys.msg_controllen) {
-		ctl_len = sizeof(ctl);
-		err = get_cmsghdr32(&msg_sys, ctl_buf, sock->sk, &ctl_len);
-		if (err)
-			goto out_freeiov;
-		ctl_buf = msg_sys.msg_control;
-	}
-	msg_sys.msg_flags = flags;
-
-	if (sock->file->f_flags & O_NONBLOCK)
-		msg_sys.msg_flags |= MSG_DONTWAIT;
-	err = sock_sendmsg(sock, &msg_sys, total_len);
-
-	if (ctl_buf != ctl)
-		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
-out_freeiov:
-	if (iov != iovstack)
-		sock_kfree_s(sock->sk, iov, iov_size);
-out_put:
-	sockfd_put(sock);
-out:
-	return err;
-}
-
-/*
- *	BSD recvmsg interface
- */
-
-int
-sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags)
-{
-	struct socket *sock;
-	struct iovec iovstack[UIO_FASTIOV];
-	struct iovec *iov=iovstack;
-	struct msghdr msg_sys;
-	unsigned long cmsg_ptr;
-	int err, iov_size, total_len, len;
-
-	/* kernel mode address */
-	char addr[MAX_SOCK_ADDR];
-
-	/* user mode address pointers */
-	struct sockaddr *uaddr;
-	int *uaddr_len;
-
-	err = -EFAULT;
-	if (get_msghdr32(&msg_sys, msg))
-		goto out;
-
-	sock = sockfd_lookup(fd, &err);
-	if (!sock)
-		goto out;
-
-	err = -EINVAL;
-	if (msg_sys.msg_iovlen > UIO_MAXIOV)
-		goto out_put;
-
-	/* Check whether to allocate the iovec area*/
-	err = -ENOMEM;
-	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
-	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
-		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
-		if (!iov)
-			goto out_put;
-	}
-
-	/*
-	 *	Save the user-mode address (verify_iovec will change the
-	 *	kernel msghdr to use the kernel address space)
-	 */
-
-	uaddr = msg_sys.msg_name;
-	uaddr_len = &msg->msg_namelen;
-	err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE);
-	if (err < 0)
-		goto out_freeiov;
-	total_len=err;
-
-	cmsg_ptr = (unsigned long)msg_sys.msg_control;
-	msg_sys.msg_flags = 0;
-
-	if (sock->file->f_flags & O_NONBLOCK)
-		flags |= MSG_DONTWAIT;
-
-	/* XXX This code needs massive updating... -DaveM */
-	lock_kernel();
-	{
-		struct sock_iocb *si;
-		struct kiocb iocb;
-
-		init_sync_kiocb(&iocb, NULL);
-		si = kiocb_to_siocb(&iocb);
-		si->sock = sock;
-		si->scm = &si->async_scm;
-		si->msg = &msg_sys;
-		si->size = total_len;
-		si->flags = flags;
-		memset(si->scm, 0, sizeof(*si->scm));
-
-		err = sock->ops->recvmsg(&iocb, sock, &msg_sys, total_len,
-					 flags, si->scm);
-		if (-EIOCBQUEUED == err)
-			err = wait_on_sync_kiocb(&iocb);
-
-		if (err < 0)
-			goto out_unlock_freeiov;
-
-		len = err;
-		if (!msg_sys.msg_control) {
-			if (sock->passcred || si->scm->fp)
-				msg_sys.msg_flags |= MSG_CTRUNC;
-			if (si->scm->fp)
-				__scm_destroy(si->scm);
-		} else {
-			/*
-			 * If recvmsg processing itself placed some control messages into
-			 * user space, it's is using 64-bit CMSG processing, so we need to
-			 * fix it up before we tack on more stuff.
-			 */
-			if ((unsigned long) msg_sys.msg_control != cmsg_ptr)
-				cmsg32_recvmsg_fixup(&msg_sys, cmsg_ptr);
-
-			/* Wheee... */
-			if (sock->passcred)
-				put_cmsg32(&msg_sys, SOL_SOCKET, SCM_CREDENTIALS,
-					   sizeof(si->scm->creds),
-					   &si->scm->creds);
-			if (si->scm->fp != NULL)
-				scm_detach_fds32(&msg_sys, si->scm);
-		}
-	}
-	unlock_kernel();
-
-	if (uaddr != NULL) {
-		err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
-		if (err < 0)
-			goto out_freeiov;
-	}
-	err = __put_user(msg_sys.msg_flags, &msg->msg_flags);
-	if (err)
-		goto out_freeiov;
-	err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr,
-							 &msg->msg_controllen);
-	if (err)
-		goto out_freeiov;
-	err = len;
-
-  out_freeiov:
-	if (iov != iovstack)
-		sock_kfree_s(sock->sk, iov, iov_size);
-  out_put:
-	sockfd_put(sock);
-  out:
-	return err;
-
-  out_unlock_freeiov:
-	goto out_freeiov;
-}
-
-/* Argument list sizes for sys_socketcall */
-#define AL(x) ((x) * sizeof(u32))
-static const unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
-				    AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
-				    AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
-#undef AL
-
-extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
-extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr,
-				  int addrlen);
-extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr,
-				 int *upeer_addrlen);
-extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr,
-				      int *usockaddr_len);
-extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr,
-				      int *usockaddr_len);
-extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags);
-extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len,
-				   unsigned flags, u32 addr, int addr_len);
-extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
-extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size,
-				     unsigned flags, u32 addr, u32 addr_len);
-extern asmlinkage long sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
-				       u32 optval, u32 optlen);
-
-extern asmlinkage long sys_socket(int family, int type, int protocol);
-extern asmlinkage long sys_socketpair(int family, int type, int protocol,
-				     int usockvec[2]);
-extern asmlinkage long sys_shutdown(int fd, int how);
-extern asmlinkage long sys_listen(int fd, int backlog);
-
-asmlinkage long
-sys32_socketcall (int call, u32 *args)
-{
-	int ret;
-	u32 a[6];
-	u32 a0,a1;
-
-	if (call<SYS_SOCKET||call>SYS_RECVMSG)
-		return -EINVAL;
-	if (copy_from_user(a, args, nas[call]))
-		return -EFAULT;
-	a0=a[0];
-	a1=a[1];
-
-	switch(call)
-	{
-		case SYS_SOCKET:
-			ret = sys_socket(a0, a1, a[2]);
-			break;
-		case SYS_BIND:
-			ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]);
-			break;
-		case SYS_CONNECT:
-			ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]);
-			break;
-		case SYS_LISTEN:
-			ret = sys_listen(a0, a1);
-			break;
-		case SYS_ACCEPT:
-			ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
-			break;
-		case SYS_GETSOCKNAME:
-			ret = sys_getsockname(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
-			break;
-		case SYS_GETPEERNAME:
-			ret = sys_getpeername(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
-			break;
-		case SYS_SOCKETPAIR:
-			ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
-			break;
-		case SYS_SEND:
-			ret = sys_send(a0, (void *)A(a1), a[2], a[3]);
-			break;
-		case SYS_SENDTO:
-			ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]);
-			break;
-		case SYS_RECV:
-			ret = sys_recv(a0, (void *)A(a1), a[2], a[3]);
-			break;
-		case SYS_RECVFROM:
-			ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
-			break;
-		case SYS_SHUTDOWN:
-			ret = sys_shutdown(a0,a1);
-			break;
-		case SYS_SETSOCKOPT:
-			ret = sys_setsockopt(a0, a1, a[2], (char *)A(a[3]),
-					      a[4]);
-			break;
-		case SYS_GETSOCKOPT:
-			ret = sys_getsockopt(a0, a1, a[2], a[3], a[4]);
-			break;
-		case SYS_SENDMSG:
-			ret = sys32_sendmsg(a0, (struct msghdr32 *) A(a1), a[2]);
-			break;
-		case SYS_RECVMSG:
-			ret = sys32_recvmsg(a0, (struct msghdr32 *) A(a1), a[2]);
-			break;
-		default:
-			ret = EINVAL;
-			break;
-	}
-	return ret;
-}
-
-/*
  * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
  *
  * This is really horribly ugly.
@@ -3151,6 +2455,7 @@
 asmlinkage long
 sys32_sysctl (struct sysctl32 *args)
 {
+#ifdef CONFIG_SYSCTL
 	struct sysctl32 a32;
 	mm_segment_t old_fs = get_fs ();
 	void *oldvalp, *newvalp;
@@ -3188,6 +2493,9 @@
 		return -EFAULT;
 
 	return ret;
+#else
+	return -ENOSYS;
+#endif
 }
 
 asmlinkage long
@@ -3433,8 +2741,12 @@
 	u32 bufferram;
 	u32 totalswap;
 	u32 freeswap;
-	unsigned short procs;
-	char _f[22];
+	u16 procs;
+	u16 pad;
+	u32 totalhigh;
+	u32 freehigh;
+	u32 mem_unit;
+	char _f[8];
 };
 
 asmlinkage long
@@ -3463,6 +2775,9 @@
 	err |= __put_user(s.totalswap, &info->totalswap);
 	err |= __put_user(s.freeswap, &info->freeswap);
 	err |= __put_user(s.procs, &info->procs);
+	err |= __put_user (s.totalhigh, &info->totalhigh);
+	err |= __put_user (s.freehigh, &info->freehigh);
+	err |= __put_user (s.mem_unit, &info->mem_unit);
 	if (err)
 		return -EFAULT;
 	return ret;
diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
--- a/arch/ia64/kernel/acpi.c	Tue Feb  4 17:06:06 2003
+++ b/arch/ia64/kernel/acpi.c	Thu Mar  6 22:21:39 2003
@@ -55,6 +55,7 @@
 asm (".weak iosapic_override_isa_irq");
 asm (".weak iosapic_register_platform_intr");
 asm (".weak iosapic_init");
+asm (".weak iosapic_system_init");
 asm (".weak iosapic_version");
 
 void (*pm_idle) (void);
@@ -182,7 +183,9 @@
 #define ACPI_MAX_PLATFORM_INTERRUPTS	256
 
 /* Array to record platform interrupt vectors for generic interrupt routing. */
-int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = { [0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1 };
+int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = {
+	[0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1
+};
 
 enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC;
 
@@ -291,40 +294,6 @@
 
 
 static int __init
-acpi_find_iosapic (unsigned int gsi, u32 *gsi_base, char **iosapic_address)
-{
-	struct acpi_table_iosapic *iosapic;
-	int ver;
-	int max_pin;
-	char *p;
-	char *end;
-
-	if (!gsi_base || !iosapic_address)
-		return -ENODEV;
-
-	p = (char *) (acpi_madt + 1);
-	end = p + (acpi_madt->header.length - sizeof(struct acpi_table_madt));
-
-	while (p < end) {
-		if (*p == ACPI_MADT_IOSAPIC) {
-			iosapic = (struct acpi_table_iosapic *) p;
-
-			*gsi_base = iosapic->global_irq_base;
-			*iosapic_address = ioremap(iosapic->address, 0);
-
-			ver = iosapic_version(*iosapic_address);
-			max_pin = (ver >> 16) & 0xff;
-
-			if ((gsi - *gsi_base) <= max_pin)
-				return 0;	/* Found it! */
-		}
-		p += p[1];
-	}
-	return -ENODEV;
-}
-
-
-static int __init
 acpi_parse_iosapic (acpi_table_entry_header *header)
 {
 	struct acpi_table_iosapic *iosapic;
@@ -335,16 +304,9 @@
 
 	acpi_table_print_madt_entry(header);
 
-	if (iosapic_init) {
-#ifndef CONFIG_ITANIUM
-		/* PCAT_COMPAT flag indicates dual-8259 setup */
-		iosapic_init(iosapic->address, iosapic->global_irq_base,
-			     acpi_madt->flags.pcat_compat);
-#else
-		/* Firmware on old Itanium systems is broken */
-		iosapic_init(iosapic->address, iosapic->global_irq_base, 1);
-#endif
-	}
+	if (iosapic_init)
+		iosapic_init(iosapic->address, iosapic->global_irq_base);
+
 	return 0;
 }
 
@@ -354,8 +316,6 @@
 {
 	struct acpi_table_plat_int_src *plintsrc;
 	int vector;
-	u32 gsi_base;
-	char *iosapic_address;
 
 	plintsrc = (struct acpi_table_plat_int_src *) header;
 	if (!plintsrc)
@@ -368,11 +328,6 @@
 		return -ENODEV;
 	}
 
-	if (acpi_find_iosapic(plintsrc->global_irq, &gsi_base, &iosapic_address)) {
-		printk(KERN_WARNING PREFIX "IOSAPIC not found\n");
-		return -ENODEV;
-	}
-
 	/*
 	 * Get vector assignment for this interrupt, set attributes,
 	 * and program the IOSAPIC routing table.
@@ -382,10 +337,8 @@
 						plintsrc->iosapic_vector,
 						plintsrc->eid,
 						plintsrc->id,
-						(plintsrc->flags.polarity == 1) ? 1 : 0,
-						(plintsrc->flags.trigger == 1) ? 1 : 0,
-						gsi_base,
-						iosapic_address);
+						(plintsrc->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
+						(plintsrc->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
 
 	platform_intr_list[plintsrc->type] = vector;
 	return 0;
@@ -408,8 +361,8 @@
 		return 0;
 
 	iosapic_override_isa_irq(p->bus_irq, p->global_irq,
-				 (p->flags.polarity == 1) ? 1 : 0,
-				 (p->flags.trigger == 1) ? 1 : 0);
+				 (p->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
+				 (p->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
 	return 0;
 }
 
@@ -439,7 +392,13 @@
 	acpi_madt = (struct acpi_table_madt *) __va(phys_addr);
 
 	/* remember the value for reference after free_initmem() */
+#ifdef CONFIG_ITANIUM
+	has_8259 = 1; /* Firmware on old Itanium systems is broken */
+#else
 	has_8259 = acpi_madt->flags.pcat_compat;
+#endif
+	if (iosapic_system_init)
+		iosapic_system_init(has_8259);
 
 	/* Get base address of IPI Message Block */
 
@@ -571,7 +530,7 @@
 }
 
 void __init
-acpi_numa_arch_fixup(void)
+acpi_numa_arch_fixup (void)
 {
 	int i, j, node_from, node_to;
 
@@ -618,7 +577,7 @@
 			if (!pxm_bit_test(j))
 				continue;
 			node_to = pxm_to_nid_map[j];
-			node_distance(node_from, node_to) = 
+			node_distance(node_from, node_to) =
 				slit_table->entry[i*slit_table->localities + j];
 		}
 	}
@@ -639,8 +598,7 @@
 {
 	struct acpi_table_header *fadt_header;
 	struct fadt_descriptor_rev2 *fadt;
-	u32 sci_irq, gsi_base;
-	char *iosapic_address;
+	u32 sci_irq;
 
 	if (!phys_addr || !size)
 		return -EINVAL;
@@ -662,8 +620,7 @@
 	if (has_8259 && sci_irq < 16)
 		return 0;	/* legacy, no setup required */
 
-	if (!acpi_find_iosapic(sci_irq, &gsi_base, &iosapic_address))
-		iosapic_register_intr(sci_irq, 0, 0, gsi_base, iosapic_address);
+	iosapic_register_intr(sci_irq, IOSAPIC_POL_LOW, IOSAPIC_LEVEL);
 	return 0;
 }
 
@@ -717,8 +674,6 @@
 	if ((spcr->base_addr.space_id != ACPI_SERIAL_PCICONF_SPACE) &&
 	    (spcr->int_type == ACPI_SERIAL_INT_SAPIC))
 	{
-		u32 gsi_base;
-		char *iosapic_address;
 		int vector;
 
 		/* We have a UART in memory space with an SAPIC interrupt */
@@ -728,11 +683,7 @@
 			 (spcr->global_int[1] << 8)  |
 			 (spcr->global_int[0])  );
 
-		/* Which iosapic does this interrupt belong to? */
-
-		if (!acpi_find_iosapic(gsi, &gsi_base, &iosapic_address))
-			vector = iosapic_register_intr(gsi, 1, 1,
-						       gsi_base, iosapic_address);
+		vector = iosapic_register_intr(gsi, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
 	}
 	return 0;
 }
@@ -741,7 +692,7 @@
 
 
 int __init
-acpi_boot_init (char *cmdline)
+acpi_boot_init (void)
 {
 
 	/*
@@ -812,20 +763,20 @@
 	smp_boot_data.cpu_count = total_cpus;
 
 	smp_build_cpu_map();
-#ifdef CONFIG_NUMA
+# ifdef CONFIG_NUMA
 	build_cpu_to_node_map();
-#endif
+# endif
 #endif
 	/* Make boot-up look pretty */
 	printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, total_cpus);
 	return 0;
 }
 
+/*
+ * PCI Interrupt Routing
+ */
 
-/* --------------------------------------------------------------------------
-                             PCI Interrupt Routing
-   -------------------------------------------------------------------------- */
-
+#ifdef CONFIG_PCI
 int __init
 acpi_get_prt (struct pci_vector_struct **vectors, int *count)
 {
@@ -866,6 +817,7 @@
 	*count = acpi_prt.count;
 	return 0;
 }
+#endif /* CONFIG_PCI */
 
 /* Assume IA64 always use I/O SAPIC */
 
@@ -888,12 +840,10 @@
 	return gsi_to_vector(irq);
 }
 
-int __init
+int
 acpi_register_irq (u32 gsi, u32 polarity, u32 trigger)
 {
 	int vector = 0;
-	u32 irq_base;
-	char *iosapic_address;
 
 	if (acpi_madt->flags.pcat_compat && (gsi < 16))
 		return isa_irq_to_vector(gsi);
@@ -901,12 +851,9 @@
 	if (!iosapic_register_intr)
 		return 0;
 
-	/* Find the IOSAPIC */
-	if (!acpi_find_iosapic(gsi, &irq_base, &iosapic_address)) {
-		/* Turn it on */
-		vector = iosapic_register_intr (gsi, polarity, trigger,
-						irq_base, iosapic_address);
-	}
+	/* Turn it on */
+	vector = iosapic_register_intr (gsi, polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
+			trigger ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
 	return vector;
 }
 
diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
--- a/arch/ia64/kernel/entry.S	Tue Jan 21 18:31:31 2003
+++ b/arch/ia64/kernel/entry.S	Thu Mar  6 14:56:33 2003
@@ -586,10 +586,21 @@
 	// work.need_resched etc. mustn't get changed by this CPU before it returns to
 	// user- or fsys-mode:
 (pUStk)	cmp.eq.unc p6,p0=r0,r0			// p6 <- pUStk
+#ifdef CONFIG_PREEMPT
+	rsm psr.i				// disable interrupts
+	adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
+(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+	;;
+(pKStk) ld4  r21=[r20]			// preempt_count ->r21
+	;;
+(pKStk)	cmp4.eq	p6,p0=r21,r0		// p6 <- preempt_count == 0
+	;;
+#else /* CONFIG_PREEMPT */
 (pUStk)	rsm psr.i
 	;;
 (pUStk)	adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
 	;;
+#endif /* CONFIG_PREEMPT */
 .work_processed:
 (p6)	ld4 r18=[r17]				// load current_thread_info()->flags
 	adds r2=PT(R8)+16,r12
@@ -701,7 +712,7 @@
 	 * NOTE: alloc, loadrs, and cover can't be predicated.
 	 */
 (pNonSys) br.cond.dpnt dont_preserve_current_frame
-	cover				// add current frame into dirty partition
+	cover				// add current frame into dirty partition and set cr.ifs
 	;;
 	mov r19=ar.bsp			// get new backing store pointer
 	sub r16=r16,r18			// krbs = old bsp - size of dirty partition
@@ -727,7 +738,7 @@
 #	define Nregs	14
 #endif
 	alloc loc0=ar.pfs,2,Nregs-2,2,0
-	shr.u loc1=r18,9		// RNaTslots <= dirtySize / (64*8) + 1
+	shr.u loc1=r18,9		// RNaTslots <= floor(dirtySize / (64*8))
 	sub r17=r17,r18			// r17 = (physStackedSize + 8) - dirtySize
 	;;
 	mov ar.rsc=r19			// load ar.rsc to be used for "loadrs"
@@ -774,13 +785,13 @@
 	;;
 	mov loc3=0
 	mov loc4=0
-	mov loc9=0
 	mov loc5=0
 	mov loc6=0
+	mov loc7=0
 (pRecurse) br.call.sptk.many b6=rse_clear_invalid
 	;;
-	mov loc7=0
 	mov loc8=0
+	mov loc9=0
 	cmp.ne pReturn,p0=r0,in1	// if recursion count != 0, we need to do a br.ret
 	mov loc10=0
 	mov loc11=0
@@ -810,15 +821,27 @@
 .work_pending:
 	tbit.z p6,p0=r18,TIF_NEED_RESCHED		// current_thread_info()->need_resched==0?
 (p6)	br.cond.sptk.few .notify
+#ifdef CONFIG_PREEMPT
+(pKStk)	dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1
+	;;
+(pKStk) st4 [r20]=r21
+	ssm  psr.i		// enable interrupts
+#endif
+
 #if __GNUC__ < 3
 	br.call.spnt.many rp=invoke_schedule
 #else
 	br.call.spnt.many rp=schedule
 #endif
 .ret9:	cmp.eq p6,p0=r0,r0				// p6 <- 1
-	rsm psr.i
+	rsm psr.i		// disable interrupts
 	;;
 	adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
+#if CONFIG_PREEMPT
+(pKStk)	adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+	;;
+(pKStk)	st4 [r20]=r0		// preempt_count() <- 0
+#endif
 	br.cond.sptk.many .work_processed		// re-check
 
 .notify:
@@ -904,13 +927,14 @@
 	mov r9=ar.unat
 	mov loc0=rp				// save return address
 	mov out0=0				// there is no "oldset"
-	adds out1=0,sp				// out1=&sigscratch
+	adds out1=8,sp				// out1=&sigscratch->ar_pfs
 (pSys)	mov out2=1				// out2==1 => we're in a syscall
 	;;
 (pNonSys) mov out2=0				// out2==0 => not a syscall
 	.fframe 16
 	.spillpsp ar.unat, 16			// (note that offset is relative to psp+0x10!)
 	st8 [sp]=r9,-16				// allocate space for ar.unat and save it
+	st8 [out1]=loc1,-8			// save ar.pfs, out1=&sigscratch
 	.body
 	br.call.sptk.many rp=do_notify_resume_user
 .ret15:	.restore sp
@@ -931,11 +955,12 @@
 	mov loc0=rp				// save return address
 	mov out0=in0				// mask
 	mov out1=in1				// sigsetsize
-	adds out2=0,sp				// out2=&sigscratch
+	adds out2=8,sp				// out2=&sigscratch->ar_pfs
 	;;
 	.fframe 16
 	.spillpsp ar.unat, 16			// (note that offset is relative to psp+0x10!)
 	st8 [sp]=r9,-16				// allocate space for ar.unat and save it
+	st8 [out2]=loc1,-8			// save ar.pfs, out2=&sigscratch
 	.body
 	br.call.sptk.many rp=ia64_rt_sigsuspend
 .ret17:	.restore sp
@@ -1242,7 +1267,7 @@
 	data8 sys_sched_setaffinity
 	data8 sys_sched_getaffinity
 	data8 sys_set_tid_address
-	data8 ia64_ni_syscall
+	data8 sys_fadvise64
 	data8 ia64_ni_syscall 			// 1235
 	data8 sys_exit_group
 	data8 sys_lookup_dcookie
@@ -1256,15 +1281,15 @@
 	data8 sys_epoll_wait			// 1245
 	data8 sys_restart_syscall
 	data8 sys_semtimedop
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall			// 1250
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall			// 1255
-	data8 ia64_ni_syscall
+	data8 sys_timer_create
+	data8 sys_timer_settime
+	data8 sys_timer_gettime			// 1250
+	data8 sys_timer_getoverrun
+	data8 sys_timer_delete
+	data8 sys_clock_settime
+	data8 sys_clock_gettime
+	data8 sys_clock_getres			// 1255
+	data8 sys_clock_nanosleep
 	data8 ia64_ni_syscall
 	data8 ia64_ni_syscall
 	data8 ia64_ni_syscall
diff -Nru a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
--- a/arch/ia64/kernel/fsys.S	Wed Jan 29 22:16:51 2003
+++ b/arch/ia64/kernel/fsys.S	Fri Feb 28 16:51:10 2003
@@ -3,11 +3,16 @@
  *
  * Copyright (C) 2003 Hewlett-Packard Co
  * 	David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * 18-Feb-03 louisk	Implement fsys_gettimeofday().
+ * 28-Feb-03 davidm	Fixed several bugs in fsys_gettimeofday().  Tuned it some more,
+ *			probably broke it along the way... ;-)
  */
 
 #include <asm/asmmacro.h>
 #include <asm/errno.h>
 #include <asm/offsets.h>
+#include <asm/percpu.h>
 #include <asm/thread_info.h>
 
 /*
@@ -123,6 +128,183 @@
 	br.ret.sptk.many b6
 END(fsys_set_tid_address)
 
+/*
+ * Note 1: This routine uses floating-point registers, but only with registers that
+ *	   operate on integers.  Because of that, we don't need to set ar.fpsr to the
+ *	   kernel default value.
+ *
+ * Note 2: For now, we will assume that all CPUs run at the same clock-frequency.
+ *	   If that wasn't the case, we would have to disable preemption (e.g.,
+ *	   by disabling interrupts) between reading the ITC and reading
+ *	   local_cpu_data->nsec_per_cyc.
+ *
+ * Note 3: On platforms where the ITC-drift bit is set in the SAL feature vector,
+ *	   we ought to either skip the ITC-based interpolation or run an ntp-like
+ *	   daemon to keep the ITCs from drifting too far apart.
+ */
+ENTRY(fsys_gettimeofday)
+	add r9=TI_FLAGS+IA64_TASK_SIZE,r16
+	movl r3=THIS_CPU(cpu_info)
+
+	mov.m r31=ar.itc		// put time stamp into r31 (ITC) == now		(35 cyc)
+	movl r19=xtime			// xtime is a timespec struct
+	;;
+
+#ifdef CONFIG_SMP
+	movl r10=__per_cpu_offset
+	;;
+	ld8 r10=[r10]			// r10 <- __per_cpu_offset[0]
+	movl r21=cpu_info__per_cpu
+	;;
+	add r10=r21, r10		// r10 <- &cpu_data(time_keeper_id)
+#else
+	mov r10=r3
+#endif
+	ld4 r9=[r9]
+	movl r17=xtime_lock
+	;;
+
+	// r32, r33 should contain the 2 args of gettimeofday
+	adds r21=IA64_CPUINFO_ITM_NEXT_OFFSET, r10
+	mov r2=-1
+	tnat.nz p6,p7=r32		// guard against NaT args
+	;;
+
+	adds r10=IA64_CPUINFO_ITM_DELTA_OFFSET, r10
+(p7)	tnat.nz p6,p0=r33
+(p6)	br.cond.spnt.few .fail
+
+	adds r8=IA64_CPUINFO_NSEC_PER_CYC_OFFSET, r3
+	movl r24=2361183241434822607	// for division hack (only for / 1000)
+	;;
+
+	ldf8 f7=[r10]			// f7 now contains itm_delta
+	setf.sig f11=r2
+	adds r10=8, r32
+
+	adds r20=IA64_TIMESPEC_TV_NSEC_OFFSET, r19	// r20 = &xtime->tv_nsec
+	movl r26=jiffies
+
+	setf.sig f9=r24			// f9 is used for division hack
+	movl r27=wall_jiffies
+
+	and r9=TIF_ALLWORK_MASK,r9
+	movl r25=last_nsec_offset
+	;;
+
+	/*
+	 * Verify that we have permission to write to struct timeval.  Note:
+	 * Another thread might unmap the mapping before we actually get
+	 * to store the result.  That's OK as long as the stores are also
+	 * protect by EX().
+	 */
+EX(.fail, probe.w.fault r32, 3)		// this must come _after_ NaT-check
+EX(.fail, probe.w.fault r10, 3)		// this must come _after_ NaT-check
+	nop 0
+
+	ldf8 f10=[r8]			// f10 <- local_cpu_data->nsec_per_cyc value
+	cmp.ne p8, p0=0, r9
+(p8)	br.spnt.many fsys_fallback_syscall
+	;;
+.retry:	// *** seq = read_seqbegin(&xtime_lock); ***
+	ld4.acq r23=[r17]		// since &xtime_lock == &xtime_lock->sequence
+	ld8 r14=[r25]			// r14 (old) = last_nsec_offset
+
+	ld8 r28=[r26]			// r28 = jiffies
+	ld8 r29=[r27]			// r29 = wall_jiffies
+	;;
+
+	ldf8 f8=[r21]			// f8 now contains itm_next
+	sub r28=r29, r28, 1		// r28 now contains "-(lost + 1)"
+	tbit.nz p9, p10=r23, 0		// p9 <- is_odd(r23), p10 <- is_even(r23)
+	;;
+
+	ld8 r2=[r19]			// r2 = sec = xtime.tv_sec
+	ld8 r29=[r20]			// r29 = nsec = xtime.tv_nsec
+
+	setf.sig f6=r28			// f6 <- -(lost + 1)				(6 cyc)
+	;;
+
+	mf
+	xma.l f8=f6, f7, f8	// f8 (last_tick) <- -(lost + 1)*itm_delta + itm_next	(5 cyc)
+	nop 0
+
+	setf.sig f12=r31		// f12 <- ITC					(6 cyc)
+	// *** if (unlikely(read_seqretry(&xtime_lock, seq))) continue; ***
+	ld4 r24=[r17]			// r24 = xtime_lock->sequence (re-read)
+	nop 0
+	;;
+
+	mov r31=ar.itc			// re-read ITC in case we .retry		(35 cyc)
+	xma.l f8=f11, f8, f12	// f8 (elapsed_cycles) <- (-1*last_tick + now) = (now - last_tick)
+	nop 0
+	;;
+
+	getf.sig r18=f8			// r18 <- (now - last_tick)
+	xmpy.l f8=f8, f10		// f8 <- elapsed_cycles*nsec_per_cyc (5 cyc)
+	add r3=r29, r14			// r3 = (nsec + old)
+	;;
+
+	cmp.lt p7, p8=r18, r0		// if now < last_tick, set p7 = 1, p8 = 0
+	getf.sig r18=f8			// r18 = elapsed_cycles*nsec_per_cyc		(6 cyc)
+	nop 0
+	;;
+
+(p10)	cmp.ne p9, p0=r23, r24		// if xtime_lock->sequence != seq, set p9
+	shr.u r18=r18, IA64_NSEC_PER_CYC_SHIFT	// r18 <- offset
+(p9)	br.spnt.many .retry
+	;;
+
+	mov ar.ccv=r14			// ar.ccv = old					(1 cyc)
+	cmp.leu p7, p8=r18, r14		// if (offset <= old), set p7 = 1, p8 = 0
+	;;
+
+(p8)	cmpxchg8.rel r24=[r25], r18, ar.ccv	// compare-and-exchange (atomic!)
+(p8)	add r3=r29, r18			// r3 = (nsec + offset)
+	;;
+	shr.u r3=r3, 3			// initiate dividing r3 by 1000
+	;;
+	setf.sig f8=r3			//						(6 cyc)
+	mov r10=1000000			// r10 = 1000000
+	;;
+(p8)	cmp.ne.unc p9, p0=r24, r14
+	xmpy.hu f6=f8, f9		//						(5 cyc)
+(p9)	br.spnt.many .retry
+	;;
+
+	getf.sig r3=f6			//						(6 cyc)
+	;;
+	shr.u r3=r3, 4			// end of division, r3 is divided by 1000 (=usec)
+	;;
+
+1:	cmp.geu p7, p0=r3, r10		// while (usec >= 1000000)
+	;;
+(p7)	sub r3=r3, r10			// usec -= 1000000
+(p7)	adds r2=1, r2			// ++sec
+(p7)	br.spnt.many 1b
+
+	// finally: r2 = sec, r3 = usec
+EX(.fail, st8 [r32]=r2)
+	adds r9=8, r32
+	mov r8=r0			// success
+	;;
+EX(.fail, st8 [r9]=r3)			// store them in the timeval struct
+	mov r10=0
+	MCKINLEY_E9_WORKAROUND
+	br.ret.sptk.many b6		// return to caller
+	/*
+	 * Note: We are NOT clearing the scratch registers here.  Since the only things
+	 *	 in those registers are time-related variables and some addresses (which
+	 *	 can be obtained from System.map), none of this should be security-sensitive
+	 *	 and we should be fine.
+	 */
+
+.fail:	adds r8=EINVAL, r0		// r8 = EINVAL
+	adds r10=-1, r0			// r10 = -1
+	MCKINLEY_E9_WORKAROUND
+	br.ret.spnt.many b6		// return with r8 set to EINVAL
+END(fsys_gettimeofday)
+
 	.rodata
 	.align 8
 	.globl fsyscall_table
@@ -190,7 +372,7 @@
 	data8 fsys_fallback_syscall	// setrlimit
 	data8 fsys_fallback_syscall	// getrlimit		// 1085
 	data8 fsys_fallback_syscall	// getrusage
-	data8 fsys_fallback_syscall	// gettimeofday
+	data8 fsys_gettimeofday		// gettimeofday
 	data8 fsys_fallback_syscall	// settimeofday
 	data8 fsys_fallback_syscall	// select
 	data8 fsys_fallback_syscall	// poll			// 1090
diff -Nru a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S
--- a/arch/ia64/kernel/gate.S	Fri Jan 17 19:18:54 2003
+++ b/arch/ia64/kernel/gate.S	Mon Feb 10 18:28:00 2003
@@ -145,11 +145,12 @@
 	 */
 
 #define SIGTRAMP_SAVES										\
-	.unwabi @svr4, 's'		// mark this as a sigtramp handler (saves scratch regs)	\
-	.savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF						\
-	.savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF						\
-	.savesp pr, PR_OFF+SIGCONTEXT_OFF							\
-	.savesp rp, RP_OFF+SIGCONTEXT_OFF							\
+	.unwabi @svr4, 's';	/* mark this as a sigtramp handler (saves scratch regs) */	\
+	.savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF;						\
+	.savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF;						\
+	.savesp pr, PR_OFF+SIGCONTEXT_OFF;     							\
+	.savesp rp, RP_OFF+SIGCONTEXT_OFF;							\
+	.savesp ar.pfs, CFM_OFF+SIGCONTEXT_OFF;							\
 	.vframesp SP_OFF+SIGCONTEXT_OFF
 
 GLOBAL_ENTRY(ia64_sigtramp)
@@ -173,9 +174,7 @@
 	.spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
 (p8)	br.cond.spnt setup_rbs		// yup -> (clobbers r14, r15, and r16)
 back_from_setup_rbs:
-
-	.spillreg ar.pfs, r8
-	alloc r8=ar.pfs,0,0,3,0		// get CFM0, EC0, and CPL0 into r8
+	alloc r8=ar.pfs,0,0,3,0
 	ld8 out0=[base0],16		// load arg0 (signum)
 	adds base1=(ARG1_OFF-(RBS_BASE_OFF+SIGCONTEXT_OFF)),base1
 	;;
@@ -184,17 +183,12 @@
 	;;
 	ld8 out2=[base0]		// load arg2 (sigcontextp)
 	ld8 gp=[r17]			// get signal handler's global pointer
-
 	adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
 	;;
 	.spillsp ar.bsp, BSP_OFF+SIGCONTEXT_OFF
-	st8 [base0]=r9,(CFM_OFF-BSP_OFF)	// save sc_ar_bsp
-	dep r8=0,r8,38,26			// clear EC0, CPL0 and reserved bits
-	adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
-	;;
-	.spillsp ar.pfs, CFM_OFF+SIGCONTEXT_OFF
-	st8 [base0]=r8				// save CFM0
+	st8 [base0]=r9			// save sc_ar_bsp
 	adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
+	adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
 	;;
 	stf.spill [base0]=f6,32
 	stf.spill [base1]=f7,32
@@ -217,7 +211,6 @@
 	ld8 r15=[base0],(CFM_OFF-BSP_OFF)	// fetch sc_ar_bsp and advance to CFM_OFF
 	mov r14=ar.bsp
 	;;
-	ld8 r8=[base0]				// restore (perhaps modified) CFM0, EC0, and CPL0
 	cmp.ne p8,p0=r14,r15			// do we need to restore the rbs?
 (p8)	br.cond.spnt restore_rbs		// yup -> (clobbers r14-r18, f6 & f7)
 	;;
diff -Nru a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c
--- a/arch/ia64/kernel/init_task.c	Tue Sep 17 23:22:09 2002
+++ b/arch/ia64/kernel/init_task.c	Wed Feb 12 00:11:32 2003
@@ -17,6 +17,7 @@
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
 struct mm_struct init_mm = INIT_MM(init_mm);
 
 /*
diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
--- a/arch/ia64/kernel/iosapic.c	Tue Feb  4 17:06:08 2003
+++ b/arch/ia64/kernel/iosapic.c	Wed Feb 19 14:07:24 2003
@@ -29,6 +29,9 @@
  * 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.
+ * 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.
  */
 /*
  * Here is what the interrupt logic between a PCI device and the kernel looks like:
@@ -111,16 +114,17 @@
 	char		*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 char	pcat_compat;	/* 8259 compatibility flag */
-} iosapic_lists[256] __devinitdata;
+} iosapic_lists[256];
 
-static int num_iosapic = 0;
+static int num_iosapic;
+
+static unsigned char pcat_compat __initdata;	/* 8259 compatibility flag */
 
 
 /*
  * Find an IOSAPIC associated with a GSI
  */
-static inline int __devinit
+static inline int
 find_iosapic (unsigned int gsi)
 {
 	int i;
@@ -423,7 +427,7 @@
  * if the given vector is already owned by other,
  *  assign a new vector for the other and make the vector available
  */
-static void
+static void __init
 iosapic_reassign_vector (int vector)
 {
 	int new_vector;
@@ -443,50 +447,36 @@
 
 static void
 register_intr (unsigned int gsi, int vector, unsigned char delivery,
-	       unsigned long polarity, unsigned long edge_triggered,
-	       unsigned int gsi_base, char *iosapic_address)
+	       unsigned long polarity, unsigned long trigger)
 {
 	irq_desc_t *idesc;
 	struct hw_interrupt_type *irq_type;
 	int rte_index;
+	int index;
+	unsigned long gsi_base;
+	char *iosapic_address;
+
+	index = find_iosapic(gsi);
+	if (index < 0) {
+		printk(KERN_WARNING "%s: No IOSAPIC for GSI 0x%x\n", __FUNCTION__, gsi);
+		return;
+	}
+
+	iosapic_address = iosapic_lists[index].addr;
+	gsi_base = iosapic_lists[index].gsi_base;
 
 	rte_index = gsi - gsi_base;
 	iosapic_intr_info[vector].rte_index = rte_index;
-	iosapic_intr_info[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW;
+	iosapic_intr_info[vector].polarity = polarity;
 	iosapic_intr_info[vector].dmode    = delivery;
+	iosapic_intr_info[vector].addr     = iosapic_address;
+	iosapic_intr_info[vector].gsi_base = gsi_base;
+	iosapic_intr_info[vector].trigger  = trigger;
 
-	/*
-	 * In override, it may not provide addr/gsi_base.  GSI is enough to
-	 * locate iosapic addr, gsi_base and rte_index by examining
-	 * gsi_base and num_rte of registered iosapics (tbd)
-	 */
-#ifndef	OVERRIDE_DEBUG
-	if (iosapic_address) {
-		iosapic_intr_info[vector].addr = iosapic_address;
-		iosapic_intr_info[vector].gsi_base = gsi_base;
-	}
-#else
-	if (iosapic_address) {
-		if (iosapic_intr_info[vector].addr && (iosapic_intr_info[vector].addr != iosapic_address))
-			printk(KERN_WARNING "warning: register_intr: diff IOSAPIC ADDRESS for "
-			       "GSI 0x%x, vector %d\n", gsi, vector);
-		iosapic_intr_info[vector].addr = iosapic_address;
-		if (iosapic_intr_info[vector].gsi_base && (iosapic_intr_info[vector].gsi_base != gsi_base)) {
-			printk(KERN_WARNING "warning: register_intr: diff GSI base 0x%x for "
-			       "GSI 0x%x, vector %d\n", gsi_base, gsi, vector);
-		}
-		iosapic_intr_info[vector].gsi_base = gsi_base;
-	} else if (!iosapic_intr_info[vector].addr)
-		printk(KERN_WARNING "warning: register_intr: invalid override for GSI 0x%x, "
-		       "vector %d\n", gsi, vector);
-#endif
-	if (edge_triggered) {
-		iosapic_intr_info[vector].trigger = IOSAPIC_EDGE;
+	if (trigger == IOSAPIC_EDGE)
 		irq_type = &irq_type_iosapic_edge;
-	} else {
-		iosapic_intr_info[vector].trigger = IOSAPIC_LEVEL;
+	else
 		irq_type = &irq_type_iosapic_level;
-	}
 
 	idesc = irq_desc(vector);
 	if (idesc->handler != irq_type) {
@@ -504,8 +494,7 @@
  */
 int
 iosapic_register_intr (unsigned int gsi,
-		       unsigned long polarity, unsigned long edge_triggered,
-		       unsigned int gsi_base, char *iosapic_address)
+		       unsigned long polarity, unsigned long trigger)
 {
 	int vector;
 	unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;
@@ -515,11 +504,11 @@
 		vector = ia64_alloc_vector();
 
 	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
-		      polarity, edge_triggered, gsi_base, iosapic_address);
+		      polarity, trigger);
 
 	printk(KERN_INFO "GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
-	       gsi, (polarity ? "high" : "low"),
-	       (edge_triggered ? "edge" : "level"), dest, vector);
+	       gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
+	       (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector);
 
 	/* program the IOSAPIC routing table */
 	set_rte(vector, dest);
@@ -530,11 +519,10 @@
  * 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
+int __init
 iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
 				int iosapic_vector, u16 eid, u16 id,
-				unsigned long polarity, unsigned long edge_triggered,
-				unsigned int gsi_base, char *iosapic_address)
+				unsigned long polarity, unsigned long trigger)
 {
 	unsigned char delivery;
 	int vector;
@@ -564,11 +552,11 @@
 	}
 
 	register_intr(gsi, vector, delivery, polarity,
-		      edge_triggered, gsi_base, iosapic_address);
+		      trigger);
 
 	printk(KERN_INFO "PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
-	       int_type, gsi, (polarity ? "high" : "low"),
-	       (edge_triggered ? "edge" : "level"), dest, vector);
+	       int_type, gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
+	       (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector);
 
 	/* program the IOSAPIC routing table */
 	set_rte(vector, dest);
@@ -580,54 +568,36 @@
  * 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
+void __init
 iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
 			  unsigned long polarity,
-			  unsigned long edge_triggered)
+			  unsigned long trigger)
 {
-	int index, vector;
-	unsigned int gsi_base;
-	char *addr;
+	int vector;
 	unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;
 
-	index = find_iosapic(gsi);
-
-	if (index < 0) {
-		printk(KERN_ERR "ISA: No corresponding IOSAPIC found : ISA IRQ %u -> GSI 0x%x\n",
-		       isa_irq, gsi);
-		return;
-	}
-
 	vector = isa_irq_to_vector(isa_irq);
-	addr = iosapic_lists[index].addr;
-	gsi_base = iosapic_lists[index].gsi_base;
 
-	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, edge_triggered,
-		      gsi_base, addr);
+	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger);
 
 	DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n",
 	    isa_irq, gsi,
-	    polarity ? "high" : "low", edge_triggered ? "edge" : "level",
+	    polarity == IOSAPIC_POL_HIGH ? "high" : "low", trigger == IOSAPIC_EDGE ? "edge" : "level",
 	    dest, vector);
 
 	/* program the IOSAPIC routing table */
 	set_rte(vector, dest);
 }
 
-void __devinit
-iosapic_init (unsigned long phys_addr, unsigned int gsi_base, int pcat_compat)
+void __init
+iosapic_system_init (int system_pcat_compat)
 {
-	int num_rte, vector;
-	unsigned int isa_irq, ver;
-	char *addr;
-	static int first_time = 1;
+	int vector;
 
-	if (first_time) {
-		first_time = 0;
-		for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
-			iosapic_intr_info[vector].rte_index = -1;	/* mark as unused */
-	}
+	for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
+		iosapic_intr_info[vector].rte_index = -1;	/* mark as unused */
 
+	pcat_compat = system_pcat_compat;
 	if (pcat_compat) {
 		/*
 		 * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support
@@ -637,6 +607,14 @@
 		outb(0xff, 0xA1);
 		outb(0xff, 0x21);
 	}
+}
+
+void __init
+iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
+{
+	int num_rte;
+	unsigned int isa_irq, ver;
+	char *addr;
 
 	addr = ioremap(phys_addr, 0);
 	ver = iosapic_version(addr);
@@ -649,7 +627,6 @@
 	num_rte = ((ver >> 16) & 0xff) + 1;
 
 	iosapic_lists[num_iosapic].addr = addr;
-	iosapic_lists[num_iosapic].pcat_compat = pcat_compat;
 	iosapic_lists[num_iosapic].gsi_base = gsi_base;
 	iosapic_lists[num_iosapic].num_rte = num_rte;
 	num_iosapic++;
@@ -658,30 +635,18 @@
 	       (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1);
 
 	if ((gsi_base == 0) && pcat_compat) {
-		unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;
 
 		/*
 		 * 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) {
-			vector = isa_irq_to_vector(isa_irq);
-
-			register_intr(isa_irq, vector, IOSAPIC_LOWEST_PRIORITY,
-				     /* IOSAPIC_POL_HIGH, IOSAPIC_EDGE */
-				     1, 1, gsi_base, addr);
-
-			DBG("ISA: IRQ %u -> GSI 0x%x (high,edge) -> CPU 0x%04x vector %d\n",
-			    isa_irq, isa_irq, dest, vector);
-
-			/* program the IOSAPIC routing table: */
-			set_rte(vector, dest);
-		}
+		for (isa_irq = 0; isa_irq < 16; ++isa_irq)
+			iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
 	}
 }
 
-static void
+static void __init
 fixup_vector (int vector, unsigned int gsi, const char *pci_id)
 {
 	struct hw_interrupt_type *irq_type = &irq_type_iosapic_level;
@@ -731,10 +696,9 @@
 {
 	struct acpi_prt_entry *entry;
 	struct list_head *node;
-	unsigned int gsi, gsi_base;
-	int index, vector, pcat_compat;
+	unsigned int gsi;
+	int vector;
 	char pci_id[16];
-	char *addr;
 
 	list_for_each(node, &acpi_prt.entries) {
 		entry = list_entry(node, struct acpi_prt_entry, node);
@@ -748,23 +712,13 @@
 		vector = gsi_to_vector(gsi);
 		if (vector < 0) {
 			/* allocate a vector for this interrupt line */
-			index = find_iosapic(gsi);
-
-			if (index < 0) {
-				printk(KERN_WARNING "IOSAPIC: GSI 0x%x has no IOSAPIC!\n", gsi);
-				continue;
-			}
-			addr = iosapic_lists[index].addr;
-			gsi_base = iosapic_lists[index].gsi_base;
-			pcat_compat = iosapic_lists[index].pcat_compat;
-
 			if (pcat_compat && (gsi < 16))
 				vector = isa_irq_to_vector(gsi);
 			else
 				/* new GSI; allocate a vector for it */
 				vector = ia64_alloc_vector();
 
-			register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, 0, 0, gsi_base, addr);
+			register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, IOSAPIC_LEVEL);
 		}
 		snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]",
 			 entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin);
diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
--- a/arch/ia64/kernel/irq.c	Tue Feb 25 01:38:25 2003
+++ b/arch/ia64/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -154,6 +154,7 @@
 	int i, j;
 	struct irqaction * action;
 	irq_desc_t *idesc;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
@@ -163,9 +164,10 @@
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
 		idesc = irq_desc(i);
+		spin_lock_irqsave(&idesc->lock, flags);
 		action = idesc->action;
 		if (!action)
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -176,10 +178,12 @@
 #endif
 		seq_printf(p, " %14s", idesc->handler->typename);
 		seq_printf(p, "  %s", action->name);
-
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
+		
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&idesc->lock, flags);
 	}
 	seq_puts(p, "NMI: ");
 	for (j = 0; j < NR_CPUS; j++)
@@ -340,12 +344,14 @@
 	 * 0 return value means that this irq is already being
 	 * handled by some other CPU. (or is disabled)
 	 */
-	int cpu = smp_processor_id();
+	int cpu;
 	irq_desc_t *desc = irq_desc(irq);
 	struct irqaction * action;
 	unsigned int status;
 
 	irq_enter();
+	cpu = smp_processor_id();
+
 	kstat_cpu(cpu).irqs[irq]++;
 
 	if (desc->status & IRQ_PER_CPU) {
diff -Nru a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
--- a/arch/ia64/kernel/ivt.S	Wed Jan 15 16:26:26 2003
+++ b/arch/ia64/kernel/ivt.S	Sat Feb 15 04:39:48 2003
@@ -848,7 +848,7 @@
 	alloc r15=ar.pfs,0,0,6,0	// must first in an insn group
 	;;
 	ld4 r8=[r14],8		// r8 == eax (syscall number)
-	mov r15=230		// number of entries in ia32 system call table
+	mov r15=250		// number of entries in ia32 system call table
 	;;
 	cmp.ltu.unc p6,p7=r8,r15
 	ld4 out1=[r14],8	// r9 == ecx
diff -Nru a/arch/ia64/kernel/machvec.c b/arch/ia64/kernel/machvec.c
--- a/arch/ia64/kernel/machvec.c	Tue Feb  4 17:06:10 2003
+++ b/arch/ia64/kernel/machvec.c	Thu Feb 20 02:35:33 2003
@@ -10,19 +10,6 @@
 
 struct ia64_machine_vector ia64_mv;
 
-/*
- * Most platforms use this routine for mapping page frame addresses into a memory map
- * index.
- *
- * Note: we can't use __pa() because map_nr_dense(X) MUST map to something >= max_mapnr if
- * X is outside the identity mapped kernel space.
- */
-unsigned long
-map_nr_dense (unsigned long addr)
-{
-	return (addr - PAGE_OFFSET) >> PAGE_SHIFT;
-}
-
 static struct ia64_machine_vector *
 lookup_machvec (const char *name)
 {
diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
--- a/arch/ia64/kernel/mca.c	Tue Feb  4 17:06:10 2003
+++ b/arch/ia64/kernel/mca.c	Tue Mar  4 18:33:56 2003
@@ -825,7 +825,7 @@
 	plog_ptr=(ia64_err_rec_t *)IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_INIT);
 	proc_ptr = &plog_ptr->proc_err;
 
-	ia64_process_min_state_save(&proc_ptr->processor_static_info.min_state_area);
+	ia64_process_min_state_save(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area);
 
 	/* Clear the INIT SAL logs now that they have been saved in the OS buffer */
 	ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT);
@@ -1620,7 +1620,7 @@
 	 *  absent. Also, current implementations only allocate space for number of
 	 *  elements used.  So we walk the data pointer from here on.
 	 */
-	p_data = &slpi->cache_check_info[0];
+	p_data = &slpi->info[0];
 
 	/* Print the cache check information if any*/
 	for (i = 0 ; i < slpi->valid.num_cache_check; i++, p_data++)
diff -Nru a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
--- a/arch/ia64/kernel/palinfo.c	Tue Feb  4 17:06:11 2003
+++ b/arch/ia64/kernel/palinfo.c	Thu Feb 13 05:43:47 2003
@@ -341,11 +341,11 @@
 		return 0;
 	}
 
-	p += sprintf(p, "\nTLB walker                     : %s implemented\n" \
+	p += sprintf(p, "\nTLB walker                     : %simplemented\n" \
 			"Number of DTR                  : %d\n" \
 			"Number of ITR                  : %d\n" \
 			"TLB insertable page sizes      : ",
-			vm_info_1.pal_vm_info_1_s.vw ? "\b":"not",
+			vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
 			vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
 			vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
 
@@ -894,10 +894,12 @@
 	 * in SMP mode, we may need to call another CPU to get correct
 	 * information. PAL, by definition, is processor specific
 	 */
-	if (f->req_cpu == smp_processor_id())
+	if (f->req_cpu == get_cpu())
 		len = (*palinfo_entries[f->func_id].proc_read)(page);
 	else
 		len = palinfo_handle_smp(f, page);
+
+	put_cpu();
 
 	if (len <= off+count) *eof = 1;
 
diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
--- a/arch/ia64/kernel/perfmon.c	Tue Feb 25 09:44:04 2003
+++ b/arch/ia64/kernel/perfmon.c	Thu Mar  6 11:40:52 2003
@@ -8,7 +8,7 @@
  * Modifications by Stephane Eranian, Hewlett-Packard Co.
  * Modifications by David Mosberger-Tang, Hewlett-Packard Co.
  *
- * Copyright (C) 1999-2002  Hewlett Packard Co
+ * Copyright (C) 1999-2003  Hewlett Packard Co
  *               Stephane Eranian <eranian@hpl.hp.com>
  *               David Mosberger-Tang <davidm@hpl.hp.com>
  */
@@ -230,9 +230,15 @@
 	unsigned int protected:1;	/* allow access to creator of context only */
 	unsigned int using_dbreg:1;	/* using range restrictions (debug registers) */
 	unsigned int excl_idle:1;	/* exclude idle task in system wide session */
-	unsigned int reserved:23;
+	unsigned int trap_reason:2;	/* reason for going into pfm_block_ovfl_reset() */
+	unsigned int reserved:21;
 } pfm_context_flags_t;
 
+#define PFM_TRAP_REASON_NONE		0x0	/* default value */
+#define PFM_TRAP_REASON_BLOCKSIG	0x1	/* we need to block on overflow and signal user */
+#define PFM_TRAP_REASON_SIG		0x2	/* we simply need to signal user */
+#define PFM_TRAP_REASON_RESET		0x3	/* we need to reset PMDs */
+
 /*
  * perfmon context: encapsulates all the state of a monitoring session
  * XXX: probably need to change layout
@@ -277,6 +283,7 @@
 #define ctx_fl_protected	ctx_flags.protected
 #define ctx_fl_using_dbreg	ctx_flags.using_dbreg
 #define ctx_fl_excl_idle	ctx_flags.excl_idle
+#define ctx_fl_trap_reason	ctx_flags.trap_reason
 
 /*
  * global information about all sessions
@@ -1225,6 +1232,8 @@
 	ctx->ctx_fl_system    = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0;
 	ctx->ctx_fl_excl_idle = (ctx_flags & PFM_FL_EXCL_IDLE) ? 1: 0;
 	ctx->ctx_fl_frozen    = 0;
+	ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE;
+
 	/*
 	 * setting this flag to 0 here means, that the creator or the task that the
 	 * context is being attached are granted access. Given that a context can only
@@ -1505,7 +1514,7 @@
 	unsigned long value, hw_value;
 	unsigned int cnum;
 	int i;
-	int ret = 0;
+	int ret = -EINVAL;
 
 	/* we don't quite support this right now */
 	if (task != current) return -EINVAL;
@@ -1514,10 +1523,10 @@
 	 * Cannot do anything before PMU is enabled 
 	 */
 	if (!CTX_IS_ENABLED(ctx)) return -EINVAL;
+	preempt_disable();
 
 	/* XXX: ctx locking may be required here */
 
-	ret = -EINVAL;
 
 	for (i = 0; i < count; i++, req++) {
 
@@ -1591,10 +1600,12 @@
 				ctx->ctx_used_pmds[0],
 				ctx->ctx_soft_pmds[cnum].reset_pmds[0]));
 	}
-
+	preempt_enable();
 	return 0;
 
 abort_mission:
+	preempt_enable();
+
 	/*
 	 * for now, we have only one possibility for error
 	 */
@@ -1639,6 +1650,7 @@
 	DBprintk(("ctx_last_cpu=%d for [%d]\n", atomic_read(&ctx->ctx_last_cpu), task->pid));
 
 	for (i = 0; i < count; i++, req++) {
+		int me;
 #if __GNUC__ < 3
 		foo = __get_user(cnum, &req->reg_num);
 		if (foo) return -EFAULT;
@@ -1666,13 +1678,16 @@
 		 * PMU state is still in the local live register due to lazy ctxsw.
 		 * If true, then we read directly from the registers.
 		 */
-		if (atomic_read(&ctx->ctx_last_cpu) == smp_processor_id()){
+		me = get_cpu();
+		if (atomic_read(&ctx->ctx_last_cpu) == me){
 			ia64_srlz_d();
 			val = ia64_get_pmd(cnum);
 			DBprintk(("reading pmd[%u]=0x%lx from hw\n", cnum, val));
 		} else {
 			val = th->pmd[cnum];
 		}
+
+
 		if (PMD_IS_COUNTING(cnum)) {
 			/*
 			 * XXX: need to check for overflow
@@ -1694,6 +1709,8 @@
 
 		PFM_REG_RETFLAG_SET(reg_flags, ret);
 
+		put_cpu();
+
 		DBprintk(("read pmd[%u] ret=%d value=0x%lx pmc=0x%lx\n", 
 					cnum, ret, val, ia64_get_pmc(cnum)));
 
@@ -1831,6 +1848,7 @@
 			ctx->ctx_fl_frozen,
 			ctx->ctx_ovfl_regs[0]));
 
+		preempt_disable();
 		pfm_reset_regs(ctx, ctx->ctx_ovfl_regs, PFM_PMD_LONG_RESET);
 
 		ctx->ctx_ovfl_regs[0] = 0UL;
@@ -1849,6 +1867,8 @@
 		/* simply unfreeze */
 		pfm_unfreeze_pmu();
 
+		preempt_enable();
+
 		return 0;
 	} 
 	/* restart on another task */
@@ -1906,6 +1926,7 @@
 				ctx->ctx_fl_system, PMU_OWNER(),
 				current));
 
+	preempt_disable();
 	/* simply stop monitoring but not the PMU */
 	if (ctx->ctx_fl_system) {
 
@@ -1933,6 +1954,7 @@
 		 */
 		ia64_psr(regs)->up = 0;
 	}
+	preempt_enable();
 	return 0;
 }
 
@@ -1945,6 +1967,7 @@
 
 	if (!CTX_IS_ENABLED(ctx)) return -EINVAL;
 
+	preempt_disable();
 	/*
 	 * stop monitoring, freeze PMU, and save state in context
 	 * this call will clear IA64_THREAD_PM_VALID for per-task sessions.
@@ -1965,6 +1988,7 @@
 	DBprintk(("enabling psr.sp for [%d]\n", current->pid));
 
 	ctx->ctx_flags.state = PFM_CTX_DISABLED;
+	preempt_enable();
 
 	return 0;
 }
@@ -2314,6 +2338,7 @@
 		return -EINVAL;
 	}
 
+	preempt_disable();
 	if (ctx->ctx_fl_system) {
 		
 		PFM_CPUINFO_SET(PFM_CPUINFO_DCR_PP);
@@ -2331,6 +2356,7 @@
 
 	} else {
 		if ((task->thread.flags & IA64_THREAD_PM_VALID) == 0) {
+			preempt_enable();
 			printk(KERN_DEBUG "perfmon: pfm_start task flag not set for [%d]\n",
 			       task->pid);
 			return -EINVAL;
@@ -2344,6 +2370,7 @@
 		ia64_srlz_i();
 	}
 
+	preempt_enable();
 	return 0;
 }
 
@@ -2351,9 +2378,13 @@
 pfm_enable(struct task_struct *task, pfm_context_t *ctx, void *arg, int count, 
 	   struct pt_regs *regs)
 {
+	int me;
+
 	/* we don't quite support this right now */
 	if (task != current) return -EINVAL;
 
+	me = get_cpu();  /* make sure we're not migrated or preempted */
+
 	if (ctx->ctx_fl_system == 0 && PMU_OWNER()  && PMU_OWNER() != current) 
 		pfm_lazy_save_regs(PMU_OWNER());
 
@@ -2397,11 +2428,13 @@
 	SET_PMU_OWNER(task);
 
 	ctx->ctx_flags.state = PFM_CTX_ENABLED;
-	atomic_set(&ctx->ctx_last_cpu, smp_processor_id());
+	atomic_set(&ctx->ctx_last_cpu, me);
 
 	/* simply unfreeze */
 	pfm_unfreeze_pmu();
 
+	put_cpu();
+
 	return 0;
 }
 
@@ -2547,6 +2580,10 @@
 
 			task = find_task_by_pid(pid);
 
+			if (task) get_task_struct(task);
+
+			read_unlock(&tasklist_lock);
+
 			if (!task) goto abort_call;
 
 			ret = -EPERM;
@@ -2584,16 +2621,116 @@
 	ret = (*pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func)(task, ctx, arg, count, regs);
 
 abort_call:
-	if (task != current) read_unlock(&tasklist_lock);
+	if (task && task != current) put_task_struct(task);
 
 	return ret;
 }
 
+/*
+ * send SIGPROF to register task, must be invoked when it
+ * is safe to send a signal, e.g., not holding any runqueue
+ * related locks.
+ */
+static int
+pfm_notify_user(pfm_context_t *ctx)
+{
+	struct siginfo si;
+	int ret;
+
+	if (ctx->ctx_notify_task == NULL) {
+		DBprintk(("[%d] no notifier\n", current->pid));
+		return -EINVAL;
+	}
+
+	si.si_errno    = 0;
+	si.si_addr     = NULL;
+	si.si_pid      = current->pid; /* who is sending */
+	si.si_signo    = SIGPROF;
+	si.si_code     = PROF_OVFL;
+
+	si.si_pfm_ovfl[0] = ctx->ctx_ovfl_regs[0];
+
+	/*
+	 * when the target of the signal is not ourself, we have to be more
+	 * careful. The notify_task may being cleared by the target task itself
+	 * in release_thread(). We must ensure mutual exclusion here such that
+	 * the signal is delivered (even to a dying task) safely.
+	 */
+
+	if (ctx->ctx_notify_task != current) {
+		/*
+		 * grab the notification lock for this task
+		 * This guarantees that the sequence: test + send_signal
+		 * is atomic with regards to the ctx_notify_task field.
+		 *
+		 * We need a spinlock and not just an atomic variable for this.
+		 *
+		 */
+		spin_lock(&ctx->ctx_lock);
+
+		/*
+		 * now notify_task cannot be modified until we're done
+		 * if NULL, they it got modified while we were in the handler
+		 */
+		if (ctx->ctx_notify_task == NULL) {
+
+			spin_unlock(&ctx->ctx_lock);
+
+			/*
+			 * If we've lost the notified task, then we will run
+			 * to completion wbut keep the PMU frozen. Results
+			 * will be incorrect anyway. We do not kill task
+			 * to leave it possible to attach perfmon context
+			 * to already running task.
+			 */
+			printk("perfmon: pfm_notify_user() lost notify_task\n");
+			DBprintk_ovfl(("notification task has disappeared !\n"));
+
+			/* we cannot afford to block now */
+			ctx->ctx_fl_block = 0;
+
+			return  -EINVAL;
+		}
+
+		/*
+		 * required by send_sig_info() to make sure the target
+		 * task does not disappear on us.
+		 */
+		read_lock(&tasklist_lock);
+	}
+	/*
+ 	 * in this case, we don't stop the task, we let it go on. It will
+ 	 * necessarily go to the signal handler (if any) when it goes back to
+ 	 * user mode.
+ 	 */
+	DBprintk_ovfl(("[%d] sending notification to [%d]\n", 
+			current->pid, ctx->ctx_notify_task->pid));
+
+	/* 
+	 * this call is safe in an interrupt handler, so does read_lock() on tasklist_lock
+	 */
+	ret = send_sig_info(SIGPROF, &si, ctx->ctx_notify_task);
+	if (ret) {
+		printk("perfmon: send_sig_info(process %d, SIGPROF)=%d\n", 
+				ctx->ctx_notify_task->pid, ret);
+	}
+
+	/*
+	 * now undo the protections in order
+	 */
+	if (ctx->ctx_notify_task != current) {
+		read_unlock(&tasklist_lock);
+		spin_unlock(&ctx->ctx_lock);
+	}
+	return ret;
+}
+
 void
 pfm_ovfl_block_reset(void)
 {
 	struct thread_struct *th = &current->thread;
 	pfm_context_t *ctx = current->thread.pfm_context;
+	unsigned int reason;
 	int ret;
 
 	/*
@@ -2609,8 +2746,31 @@
 		printk(KERN_DEBUG "perfmon: [%d] has no PFM context\n", current->pid);
 		return;
 	}
+	/*
+	 * extract reason for being here and clear
+	 */
+	reason = ctx->ctx_fl_trap_reason;
+	ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE;
 
-	if (CTX_OVFL_NOBLOCK(ctx)) goto non_blocking;
+	DBprintk(("[%d] reason=%d\n", current->pid, reason));
+
+	/*
+	 * just here for a reset (non-blocking context only)
+	 */
+	if (reason == PFM_TRAP_REASON_RESET) goto non_blocking;
+
+	/*
+	 * first notify user. This can fail if notify_task has disappeared.
+	 */
+	if (reason == PFM_TRAP_REASON_SIG || reason == PFM_TRAP_REASON_BLOCKSIG) {
+		ret = pfm_notify_user(ctx);
+		if (ret) return;
+	}
+
+	/*
+	 * came here just to signal (non-blocking)
+	 */
+	if (reason == PFM_TRAP_REASON_SIG) return;
 
 	DBprintk(("[%d] before sleeping\n", current->pid));
 
@@ -2691,7 +2851,7 @@
 	 * initialize entry header
 	 */
 	h->pid  = current->pid;
-	h->cpu  = smp_processor_id();
+	h->cpu  = get_cpu();
 	h->last_reset_value = ovfl_mask ? ctx->ctx_soft_pmds[ffz(~ovfl_mask)].lval : 0UL;
 	h->ip   = regs ? regs->cr_iip | ((regs->cr_ipsr >> 41) & 0x3): 0x0UL;
 	h->regs = ovfl_mask; 			/* which registers overflowed */
@@ -2718,7 +2878,7 @@
 		DBprintk_ovfl(("e=%p pmd%d =0x%lx\n", (void *)e, j, *e));
 		e++;
 	}
-	pfm_stats[smp_processor_id()].pfm_recorded_samples_count++;
+	pfm_stats[h->cpu].pfm_recorded_samples_count++;
 
 	/*
 	 * make the new entry visible to user, needs to be atomic
@@ -2735,9 +2895,11 @@
 		/*
 		 * XXX: must reset buffer in blocking mode and lost notified
 		 */
-		pfm_stats[smp_processor_id()].pfm_full_smpl_buffer_count++;
+		pfm_stats[h->cpu].pfm_full_smpl_buffer_count++;
+		put_cpu();
 		return 1;
 	}
+	put_cpu();
 	return 0;
 }
 
@@ -2756,7 +2918,6 @@
 	unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL;
 	int i;
 	int ret = 1;
-	struct siginfo si;
 	/*
 	 * It is never safe to access the task for which the overflow interrupt is destinated
 	 * using the current variable as the interrupt may occur in the middle of a context switch
@@ -2770,6 +2931,8 @@
 	 * valid one, i.e. the one that caused the interrupt.
 	 */
 
+	preempt_disable();
+
 	t   = &task->thread;
 
 	/*
@@ -2779,6 +2942,7 @@
 	if ((t->flags & IA64_THREAD_PM_VALID) == 0 && ctx->ctx_fl_system == 0) {
 		printk(KERN_DEBUG "perfmon: Spurious overflow interrupt: process %d not "
 		       "using perfmon\n", task->pid);
+		preempt_enable_no_resched();
 		return 0x1;
 	}
 	/*
@@ -2787,6 +2951,7 @@
 	if ((pmc0 & 0x1) == 0) {
 		printk(KERN_DEBUG "perfmon: pid %d pmc0=0x%lx assumption error for freeze bit\n",
 		       task->pid, pmc0);
+		preempt_enable_no_resched();
 		return 0x0;
 	}
 
@@ -2869,7 +3034,8 @@
 	if (ovfl_notify == 0UL) {
 		if (ovfl_pmds) 
 			pfm_reset_regs(ctx, &ovfl_pmds, PFM_PMD_SHORT_RESET);
-		return 0x0;
+		preempt_enable_no_resched();
+		return 0x0UL;
 	}
 
 	/* 
@@ -2877,142 +3043,35 @@
 	 */
 	ctx->ctx_ovfl_regs[0]  = ovfl_pmds; 
 
-	/*
-	 * we have come to this point because there was an overflow and that notification
-	 * was requested. The notify_task may have disappeared, in which case notify_task
-	 * is NULL.
-	 */
-	if (ctx->ctx_notify_task) {
-
-		si.si_errno    = 0;
-		si.si_addr     = NULL;
-		si.si_pid      = task->pid; /* who is sending */
-
-		si.si_signo    = SIGPROF;
-		si.si_code     = PROF_OVFL; /* indicates a perfmon SIGPROF signal */
-		/*
-		 * Shift the bitvector such that the user sees bit 4 for PMD4 and so on.
-		 * We only use smpl_ovfl[0] for now. It should be fine for quite a while
-		 * until we have more than 61 PMD available.
-		 */
-		si.si_pfm_ovfl[0] = ovfl_notify;
-	
-		/*
-		 * when the target of the signal is not ourself, we have to be more
-		 * careful. The notify_task may being cleared by the target task itself
-		 * in release_thread(). We must ensure mutual exclusion here such that
-		 * the signal is delivered (even to a dying task) safely.
-		 */
-
-		if (ctx->ctx_notify_task != current) {
-			/*
-			 * grab the notification lock for this task
-			 * This guarantees that the sequence: test + send_signal
-			 * is atomic with regards to the ctx_notify_task field.
-			 *
-			 * We need a spinlock and not just an atomic variable for this.
-			 *
-			 */
-			spin_lock(&ctx->ctx_lock);
-
-			/*
-			 * now notify_task cannot be modified until we're done
-			 * if NULL, they it got modified while we were in the handler
-			 */
-			if (ctx->ctx_notify_task == NULL) {
-
-				spin_unlock(&ctx->ctx_lock);
+	DBprintk_ovfl(("block=%d notify [%d] current [%d]\n", 
+		ctx->ctx_fl_block,
+		ctx->ctx_notify_task ? ctx->ctx_notify_task->pid: -1, 
+		current->pid ));
 
-				/*
-				 * If we've lost the notified task, then we will run
-				 * to completion wbut keep the PMU frozen. Results
-				 * will be incorrect anyway. We do not kill task
-				 * to leave it possible to attach perfmon context
-				 * to already running task.
-				 */
-				goto lost_notify;
-			}
-			/*
-			 * required by send_sig_info() to make sure the target
-			 * task does not disappear on us.
-			 */
-			read_lock(&tasklist_lock);
-		}
-		/*
-	 	 * in this case, we don't stop the task, we let it go on. It will
-	 	 * necessarily go to the signal handler (if any) when it goes back to
-	 	 * user mode.
-	 	 */
-		DBprintk_ovfl(("[%d] sending notification to [%d]\n", 
-			  task->pid, ctx->ctx_notify_task->pid));
-
-
-		/* 
-		 * this call is safe in an interrupt handler, so does read_lock() on tasklist_lock
-		 */
-		ret = send_sig_info(SIGPROF, &si, ctx->ctx_notify_task);
-		if (ret != 0)
-			printk(KERN_DEBUG "send_sig_info(process %d, SIGPROF)=%d\n",
-			       ctx->ctx_notify_task->pid, ret);
-		/*
-		 * now undo the protections in order
-		 */
-		if (ctx->ctx_notify_task != current) {
-			read_unlock(&tasklist_lock);
-			spin_unlock(&ctx->ctx_lock);
-		}
-
-		/*
-		 * if we block set the pfm_must_block bit
-		 * when in block mode, we can effectively block only when the notified
-		 * task is not self, otherwise we would deadlock. 
-		 * in this configuration, the notification is sent, the task will not 
-		 * block on the way back to user mode, but the PMU will be kept frozen
-		 * until PFM_RESTART.
-		 * Note that here there is still a race condition with notify_task
-		 * possibly being nullified behind our back, but this is fine because
-		 * it can only be changed to NULL which by construction, can only be
-		 * done when notify_task != current. So if it was already different
-		 * before, changing it to NULL will still maintain this invariant.
-		 * Of course, when it is equal to current it cannot change at this point.
-		 */
-		DBprintk_ovfl(("block=%d notify [%d] current [%d]\n", 
-			ctx->ctx_fl_block,
-			ctx->ctx_notify_task ? ctx->ctx_notify_task->pid: -1, 
-			current->pid ));
-
-		if (!CTX_OVFL_NOBLOCK(ctx) && ctx->ctx_notify_task != task) {
-			t->pfm_ovfl_block_reset = 1; /* will cause blocking */
-		}
+	/* 
+	 * ctx_notify_task could already be NULL, checked in pfm_notify_user() 
+	 */
+	if (CTX_OVFL_NOBLOCK(ctx) == 0 && ctx->ctx_notify_task != task) {
+		t->pfm_ovfl_block_reset = 1; /* will cause blocking */
+		ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_BLOCKSIG;
 	} else {
-lost_notify: /* XXX: more to do here, to convert to non-blocking (reset values) */
-
-		DBprintk_ovfl(("notification task has disappeared !\n"));
-		/*
-		 * for a non-blocking context, we make sure we do not fall into the 
-		 * pfm_overflow_notify() trap. Also in the case of a blocking context with lost 
-		 * notify process, then we do not want to block either (even though it is 
-		 * interruptible). In this case, the PMU will be kept frozen and the process will 
-		 * run to completion without monitoring enabled.
-		 *
-		 * Of course, we cannot loose notify process when self-monitoring.
-		 */
-		t->pfm_ovfl_block_reset = 0; 
-
+		t->pfm_ovfl_block_reset = 1; /* will cause blocking */
+		ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_SIG;
 	}
+
 	/*
-	 * If notification was successful, then we rely on the pfm_restart()
-	 * call to unfreeze and reset (in both blocking or non-blocking mode).
-	 *
-	 * If notification failed, then we will keep the PMU frozen and run
-	 * the task to completion
+	 * keep the PMU frozen until either pfm_restart() or 
+	 * task completes (non-blocking or notify_task gone).
 	 */
 	ctx->ctx_fl_frozen = 1;
 
-	DBprintk_ovfl(("return pmc0=0x%x must_block=%ld\n",
-				ctx->ctx_fl_frozen ? 0x1 : 0x0, t->pfm_ovfl_block_reset));
+	DBprintk_ovfl(("return pmc0=0x%x must_block=%ld reason=%d\n",
+		ctx->ctx_fl_frozen ? 0x1 : 0x0, 
+		t->pfm_ovfl_block_reset,
+		ctx->ctx_fl_trap_reason));
 
-	return ctx->ctx_fl_frozen ? 0x1 : 0x0;
+	preempt_enable_no_resched();
+	return 0x1UL;
 }
 
 static void
@@ -3022,13 +3081,14 @@
 	struct task_struct *task;
 	pfm_context_t *ctx;
 
-	pfm_stats[smp_processor_id()].pfm_ovfl_intr_count++;
+	pfm_stats[get_cpu()].pfm_ovfl_intr_count++;
 
 	/*
 	 * if an alternate handler is registered, just bypass the default one
 	 */
 	if (pfm_alternate_intr_handler) {
 		(*pfm_alternate_intr_handler->handler)(irq, arg, regs);
+		put_cpu();
 		return;
 	}
 
@@ -3053,6 +3113,7 @@
 		if (!ctx) {
 			printk(KERN_DEBUG "perfmon: Spurious overflow interrupt: process %d has "
 			       "no PFM context\n", task->pid);
+			put_cpu();
 			return;
 		}
 
@@ -3060,17 +3121,25 @@
 		 * assume PMC[0].fr = 1 at this point 
 		 */
 		pmc0 = pfm_overflow_handler(task, ctx, pmc0, regs);
-
 		/*
-		 * We always clear the overflow status bits and either unfreeze
-		 * or keep the PMU frozen.
+		 * we can only update pmc0 when the overflow
+		 * is for the current context. In UP the current
+		 * task may not be the one owning the PMU
 		 */
-		ia64_set_pmc(0, pmc0);
-		ia64_srlz_d();
-
+		if (task == current) {
+			/*
+		 	 * We always clear the overflow status bits and either unfreeze
+		 	 * or keep the PMU frozen.
+		 	 */
+			ia64_set_pmc(0, pmc0);
+			ia64_srlz_d();
+		} else {
+			task->thread.pmc[0] = pmc0;
+		}
 	} else {
 		pfm_stats[smp_processor_id()].pfm_spurious_ovfl_intr_count++;
 	}
+	put_cpu_no_resched();
 }
 
 /* for debug only */
@@ -3141,6 +3210,7 @@
 	unsigned long dcr;
 	unsigned long dcr_pp;
 
+	preempt_disable();
 	dcr_pp = info & PFM_CPUINFO_DCR_PP ? 1 : 0;
 
 	/*
@@ -3151,6 +3221,7 @@
 		regs = (struct pt_regs *)((unsigned long) task + IA64_STK_OFFSET);
 		regs--;
 		ia64_psr(regs)->pp = is_ctxswin ? dcr_pp : 0;
+		preempt_enable();
 		return;
 	}
 	/*
@@ -3166,6 +3237,7 @@
 			ia64_set_dcr(dcr & ~IA64_DCR_PP);
 			pfm_clear_psr_pp();
 			ia64_srlz_i();
+			preempt_enable();
 			return;
 		}
 		/* 
@@ -3179,6 +3251,7 @@
 		pfm_set_psr_pp();
 		ia64_srlz_i();
 	}
+	preempt_enable();
 }
 
 void
@@ -3189,6 +3262,8 @@
 	u64 psr;
 	int i;
 
+	preempt_disable();
+
 	ctx = task->thread.pfm_context;
 
 
@@ -3242,6 +3317,7 @@
 	 */
 	atomic_set(&ctx->ctx_last_cpu, -1);
 #endif
+	preempt_enable();
 }
 
 static void
@@ -3252,6 +3328,7 @@
 	unsigned long mask;
 	int i;
 
+	preempt_disable();
 	DBprintk(("on [%d] by [%d]\n", task->pid, current->pid));
 
 	t   = &task->thread;
@@ -3278,6 +3355,7 @@
 
 	/* not owned by this CPU */
 	atomic_set(&ctx->ctx_last_cpu, -1);
+	preempt_enable();
 }
 
 void
@@ -3290,11 +3368,14 @@
 	u64 psr;
 	int i;
 
+	preempt_disable();
+
 	owner = PMU_OWNER();
 	ctx   = task->thread.pfm_context;
 	t     = &task->thread;
 
 	if (ctx == NULL) {
+		preempt_enable();
 		printk("perfmon: pfm_load_regs: null ctx for [%d]\n", task->pid);
 		return;
 	}
@@ -3333,7 +3414,7 @@
 
 		psr = ctx->ctx_saved_psr;
 		pfm_set_psr_l(psr);
-
+		preempt_enable();
 		return;
 	}
 
@@ -3373,16 +3454,20 @@
 		if (mask & 0x1) ia64_set_pmc(i, t->pmc[i]);
 	}
 
+	/*
+	 * manually invoke core interrupt handler
+	 * if the task had a pending overflow when it was ctxsw out.
+	 * Side effect on ctx_fl_frozen is possible.
+	 */
 	if (t->pmc[0] & ~0x1) {
-		pfm_overflow_handler(task, ctx, t->pmc[0], NULL);
+		t->pmc[0] = pfm_overflow_handler(task, ctx, t->pmc[0], NULL);
 	}
 
 	/*
-	 * fl_frozen==1 when we are in blocking mode waiting for restart
+	 * unfreeze PMU if possible
 	 */
-	if (ctx->ctx_fl_frozen == 0) {
-		pfm_unfreeze_pmu();
-	}
+	if (ctx->ctx_fl_frozen == 0) pfm_unfreeze_pmu();
+
 	atomic_set(&ctx->ctx_last_cpu, smp_processor_id());
 
 	SET_PMU_OWNER(task);
@@ -3391,6 +3476,7 @@
 	 * restore the psr we changed in pfm_save_regs()
 	 */
 	psr = ctx->ctx_saved_psr;
+	preempt_enable();
 	pfm_set_psr_l(psr);
 }
 
@@ -3408,6 +3494,7 @@
 		printk("perfmon: invalid task in pfm_reset_pmu()\n");
 		return;
 	}
+	preempt_disable();
 
 	/* Let's make sure the PMU is frozen */
 	pfm_freeze_pmu();
@@ -3490,6 +3577,7 @@
 	ctx->ctx_used_dbrs[0] = 0UL;
 
 	ia64_srlz_d();
+	preempt_enable();
 }
 
 /*
@@ -3519,6 +3607,7 @@
 	 */
 	if (ctx->ctx_flags.state == PFM_CTX_DISABLED) return;
 
+	preempt_disable();
 	/*
 	 * stop monitoring:
 	 * This is the only way to stop monitoring without destroying overflow
@@ -3646,7 +3735,7 @@
 	 * indicates that context has been saved
 	 */
 	atomic_set(&ctx->ctx_last_cpu, -1);
-
+	preempt_enable();
 }
 
 
@@ -3669,6 +3758,7 @@
 	ctx    = task->thread.pfm_context;
 	thread = &task->thread;
 
+	preempt_disable();
 	/*
 	 * make sure child cannot mess up the monitoring session
 	 */
@@ -3723,6 +3813,8 @@
 		 */
 	 	ia64_psr(regs)->up = 0;
 
+		preempt_enable();
+
 		/* copy_thread() clears IA64_THREAD_PM_VALID */
 		return 0;
 	}
@@ -3770,8 +3862,9 @@
 		}
 	}
 
-	nctx->ctx_fl_frozen    = 0;
-	nctx->ctx_ovfl_regs[0] = 0UL;
+	nctx->ctx_fl_frozen      = 0;
+	nctx->ctx_ovfl_regs[0]   = 0UL;
+	nctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE;
 	atomic_set(&nctx->ctx_last_cpu, -1);
 
 	/*
@@ -3827,6 +3920,8 @@
 		thread->flags |= IA64_THREAD_PM_VALID;
 	}
 
+	preempt_enable();
+
 	return 0;
 }
 
@@ -3848,6 +3943,7 @@
 	/*
 	 * check sampling buffer
 	 */
+	preempt_disable();
 	if (ctx->ctx_psb) {
 		pfm_smpl_buffer_desc_t *psb = ctx->ctx_psb;
 
@@ -3940,6 +4036,7 @@
 	}
 
 	UNLOCK_CTX(ctx);
+	preempt_enable();
 
 	pfm_unreserve_session(task, ctx->ctx_fl_system, 1UL << ctx->ctx_cpu);
 
@@ -4118,17 +4215,27 @@
 {
 	int ret;
 
+
 	/* some sanity checks */
-	if (hdl == NULL || hdl->handler == NULL) return -EINVAL;
+	if (hdl == NULL || hdl->handler == NULL) {
+		return -EINVAL;
+	}
 
 	/* do the easy test first */
-	if (pfm_alternate_intr_handler) return -EBUSY;
+	if (pfm_alternate_intr_handler) {
+		return -EBUSY;
+	}
 
+	preempt_disable();
 	/* reserve our session */
 	ret = pfm_reserve_session(NULL, 1, cpu_online_map);
-	if (ret) return ret;
+	if (ret) {
+		preempt_enable();
+		return ret;
+	}
 
 	if (pfm_alternate_intr_handler) {
+		preempt_enable();
 		printk(KERN_DEBUG "perfmon: install_alternate, intr_handler not NULL "
 		       "after reserve\n");
 		return -EINVAL;
@@ -4136,17 +4243,21 @@
 
 	pfm_alternate_intr_handler = hdl;
 
+	preempt_enable();
 	return 0;
 }
 
 int
 pfm_remove_alternate_syswide_subsystem(pfm_intr_handler_desc_t *hdl)
 {
-	if (hdl == NULL) return -EINVAL;
+	if (hdl == NULL)
+		return -EINVAL;
 
 	/* cannot remove someone else's handler! */
-	if (pfm_alternate_intr_handler != hdl) return -EINVAL;
+	if (pfm_alternate_intr_handler != hdl) 
+		return -EINVAL;
 
+	preempt_disable();
 	pfm_alternate_intr_handler = NULL;
 
 	/* 
@@ -4154,6 +4265,8 @@
 	 */
 	pfm_unreserve_session(NULL, 1, cpu_online_map);
 
+	preempt_enable();
+
 	return 0;
 }
 
@@ -4234,8 +4347,9 @@
 pfm_init_percpu(void)
 {
 	int i;
+	int me = get_cpu();
 
-	if (smp_processor_id() == 0)
+	if (me == 0)
 		register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction);
 
 	ia64_set_pmv(IA64_PERFMON_VECTOR);
@@ -4259,6 +4373,7 @@
 		if (PMD_IS_IMPL(i) == 0) continue;
 		ia64_set_pmd(i, 0UL);
 	}
+	put_cpu();
 	pfm_freeze_pmu();
 }
 
diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
--- a/arch/ia64/kernel/process.c	Fri Jan 24 11:56:49 2003
+++ b/arch/ia64/kernel/process.c	Thu Mar  6 21:11:46 2003
@@ -746,7 +746,7 @@
 
 	memcpy(tsk, orig, sizeof(struct task_struct) + sizeof(struct thread_info));
 	tsk->thread_info = (struct thread_info *) ((char *) tsk + IA64_TASK_SIZE);
-	atomic_set(&tsk->usage, 1);
+	atomic_set(&tsk->usage, 2);
 	return tsk;
 }
 
diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
--- a/arch/ia64/kernel/ptrace.c	Tue Jan 14 21:57:29 2003
+++ b/arch/ia64/kernel/ptrace.c	Thu Mar  6 14:56:33 2003
@@ -1,7 +1,7 @@
 /*
  * Kernel support for the ptrace() and syscall tracing interfaces.
  *
- * Copyright (C) 1999-2002 Hewlett-Packard Co
+ * Copyright (C) 1999-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * Derived from the x86 and Alpha versions.  Most of the code in here
@@ -1235,19 +1235,12 @@
 		ret = 0;
 		goto out_tsk;
 
-	      case PTRACE_GETSIGINFO:
-		ret = -EIO;
-		if (!access_ok(VERIFY_WRITE, data, sizeof (siginfo_t)) || !child->thread.siginfo)
-			goto out_tsk;
-		ret = copy_siginfo_to_user((siginfo_t *) data, child->thread.siginfo);
+	      case PTRACE_OLD_GETSIGINFO:		/* for backwards-compatibility */
+		ret = ptrace_request(child, PTRACE_GETSIGINFO, addr, data);
 		goto out_tsk;
 
-	      case PTRACE_SETSIGINFO:
-		ret = -EIO;
-		if (!access_ok(VERIFY_READ, data, sizeof (siginfo_t))
-		    || child->thread.siginfo == 0)
-			goto out_tsk;
-		ret = copy_siginfo_from_user(child->thread.siginfo, (siginfo_t *) data);
+	      case PTRACE_OLD_SETSIGINFO:		/* for backwards-compatibility */
+		ret = ptrace_request(child, PTRACE_SETSIGINFO, addr, data);
 		goto out_tsk;
 
 	      case PTRACE_SYSCALL:	/* continue and stop at next (return from) syscall */
@@ -1349,15 +1342,12 @@
 	 * The 0x80 provides a way for the tracing parent to distinguish between a syscall
 	 * stop and SIGTRAP delivery.
 	 */
-	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-					? 0x80 : 0);
-	set_current_state(TASK_STOPPED);
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
+
 	/*
-	 * This isn't the same as continuing with a signal, but it
-	 * will do for normal use.  strace only continues with a
-	 * signal if the stopping signal is not SIGTRAP.  -brl
+	 * This isn't the same as continuing with a signal, but it will do for normal use.
+	 * strace only continues with a signal if the stopping signal is not SIGTRAP.
+	 * -brl
 	 */
 	if (current->exit_code) {
 		send_sig(current->exit_code, current, 1);
diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
--- a/arch/ia64/kernel/setup.c	Tue Feb  4 17:06:14 2003
+++ b/arch/ia64/kernel/setup.c	Wed Feb 12 00:11:32 2003
@@ -363,7 +363,7 @@
 
 #ifdef CONFIG_ACPI_BOOT
 	/* Initialize the ACPI boot-time table parser */
-	acpi_table_init(*cmdline_p);
+	acpi_table_init();
 # ifdef CONFIG_ACPI_NUMA
 	acpi_numa_init();
 # endif
@@ -422,7 +422,7 @@
 	cpu_init();	/* initialize the bootstrap CPU */
 
 #ifdef CONFIG_ACPI_BOOT
-	acpi_boot_init(*cmdline_p);
+	acpi_boot_init();
 #endif
 #ifdef CONFIG_SERIAL_HCDP
 	if (efi.hcdp) {
diff -Nru a/arch/ia64/kernel/sigframe.h b/arch/ia64/kernel/sigframe.h
--- a/arch/ia64/kernel/sigframe.h	Fri Mar  8 18:11:39 2002
+++ b/arch/ia64/kernel/sigframe.h	Mon Feb 10 18:28:00 2003
@@ -1,6 +1,6 @@
 struct sigscratch {
 	unsigned long scratch_unat;	/* ar.unat for the general registers saved in pt */
-	unsigned long pad;
+	unsigned long ar_pfs;		/* for syscalls, the user-level function-state  */
 	struct pt_regs pt;
 };
 
diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
--- a/arch/ia64/kernel/signal.c	Tue Feb 11 04:25:29 2003
+++ b/arch/ia64/kernel/signal.c	Thu Mar  6 11:40:52 2003
@@ -315,7 +315,7 @@
 static long
 setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr)
 {
-	unsigned long flags = 0, ifs, nat;
+	unsigned long flags = 0, ifs, cfm, nat;
 	long err;
 
 	ifs = scr->pt.cr_ifs;
@@ -325,7 +325,9 @@
 	if ((ifs & (1UL << 63)) == 0) {
 		/* if cr_ifs isn't valid, we got here through a syscall */
 		flags |= IA64_SC_FLAG_IN_SYSCALL;
-	}
+		cfm = scr->ar_pfs & ((1UL << 38) - 1);
+	} else
+		cfm = ifs & ((1UL << 38) - 1);
 	ia64_flush_fph(current);
 	if ((current->thread.flags & IA64_THREAD_FPH_VALID)) {
 		flags |= IA64_SC_FLAG_FPH_VALID;
@@ -344,6 +346,7 @@
 
 	err |= __put_user(nat, &sc->sc_nat);
 	err |= PUT_SIGSET(mask, &sc->sc_mask);
+	err |= __put_user(cfm, &sc->sc_cfm);
 	err |= __put_user(scr->pt.cr_ipsr & IA64_PSR_UM, &sc->sc_um);
 	err |= __put_user(scr->pt.ar_rsc, &sc->sc_ar_rsc);
 	err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv);
@@ -422,6 +425,15 @@
 	scr->pt.ar_fpsr = FPSR_DEFAULT;			/* reset fpsr for signal handler */
 	scr->pt.cr_iip = tramp_addr;
 	ia64_psr(&scr->pt)->ri = 0;			/* start executing in first slot */
+	/*
+	 * Force the interruption function mask to zero.  This has no effect when a
+	 * system-call got interrupted by a signal (since, in that case, scr->pt_cr_ifs is
+	 * ignored), but it has the desirable effect of making it possible to deliver a
+	 * signal with an incomplete register frame (which happens when a mandatory RSE
+	 * load faults).  Furthermore, it has no negative effect on the getting the user's
+	 * dirty partition preserved, because that's governed by scr->pt.loadrs.
+	 */
+	scr->pt.cr_ifs = (1UL << 63);
 
 	/*
 	 * Note: this affects only the NaT bits of the scratch regs (the ones saved in
@@ -522,7 +534,7 @@
 		if (signr <= 0)
 			break;
 
-		ka = &current->sig->action[signr - 1];
+		ka = &current->sighand->action[signr - 1];
 
 		if (restart) {
 			switch (errno) {
diff -Nru a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
--- a/arch/ia64/kernel/smp.c	Sun Mar  2 18:13:32 2003
+++ b/arch/ia64/kernel/smp.c	Thu Mar  6 11:40:52 2003
@@ -90,7 +90,7 @@
 void
 handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
 {
-	int this_cpu = smp_processor_id();
+	int this_cpu = get_cpu();
 	unsigned long *pending_ipis = &__get_cpu_var(ipi_operation);
 	unsigned long ops;
 
@@ -146,8 +146,12 @@
 		} while (ops);
 		mb();	/* Order data access and bit testing. */
 	}
+	put_cpu();
 }
 
+/*
+ * Called with preeemption disabled 
+ */
 static inline void
 send_IPI_single (int dest_cpu, int op)
 {
@@ -155,6 +159,9 @@
 	platform_send_ipi(dest_cpu, IA64_IPI_VECTOR, IA64_IPI_DM_INT, 0);
 }
 
+/*
+ * Called with preeemption disabled 
+ */
 static inline void
 send_IPI_allbutself (int op)
 {
@@ -166,6 +173,9 @@
 	}
 }
 
+/*
+ * Called with preeemption disabled 
+ */
 static inline void
 send_IPI_all (int op)
 {
@@ -176,12 +186,18 @@
 			send_IPI_single(i, op);
 }
 
+/*
+ * Called with preeemption disabled 
+ */
 static inline void
 send_IPI_self (int op)
 {
 	send_IPI_single(smp_processor_id(), op);
 }
 
+/*
+ * Called with preeemption disabled 
+ */
 void
 smp_send_reschedule (int cpu)
 {
@@ -197,12 +213,15 @@
 smp_send_reschedule_all (void)
 {
 	int i;
+	int cpu = get_cpu(); /* disable preemption */
 
 	for (i = 0; i < NR_CPUS; i++)
-		if (cpu_online(i) && i != smp_processor_id())
+		if (cpu_online(i) && i != cpu)
 			smp_send_reschedule(i);
+	put_cpu();
 }
 
+
 void
 smp_flush_tlb_all (void)
 {
@@ -247,9 +266,11 @@
 {
 	struct call_data_struct data;
 	int cpus = 1;
+	int me = get_cpu(); /* prevent preemption and reschedule on another processor */
 
-	if (cpuid == smp_processor_id()) {
+	if (cpuid == me) {
 		printk("%s: trying to call self\n", __FUNCTION__);
+		put_cpu();
 		return -EBUSY;
 	}
 
@@ -276,6 +297,7 @@
 	call_data = NULL;
 
 	spin_unlock_bh(&call_lock);
+	put_cpu();
 	return 0;
 }
 
diff -Nru a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
--- a/arch/ia64/kernel/sys_ia64.c	Mon Jan 27 11:04:16 2003
+++ b/arch/ia64/kernel/sys_ia64.c	Wed Feb 26 06:03:08 2003
@@ -33,17 +33,8 @@
 		return -ENOMEM;
 
 #ifdef CONFIG_HUGETLB_PAGE
-#define COLOR_HALIGN(addr) ((addr + HPAGE_SIZE - 1) & ~(HPAGE_SIZE - 1))
-#define TASK_HPAGE_BASE ((REGION_HPAGE << REGION_SHIFT) | HPAGE_SIZE)
-	if (filp && is_file_hugepages(filp)) {
-		if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE -1)))
-			addr = TASK_HPAGE_BASE;
-		addr = COLOR_HALIGN(addr);
-	}
-	else {
-		if (REGION_NUMBER(addr) == REGION_HPAGE)
-			addr = 0;
-	}
+	if (REGION_NUMBER(addr) == REGION_HPAGE)
+		addr = 0;
 #endif
 	if (!addr)
 		addr = TASK_UNMAPPED_BASE;
diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
--- a/arch/ia64/kernel/time.c	Mon Feb 24 23:13:09 2003
+++ b/arch/ia64/kernel/time.c	Thu Mar  6 11:40:52 2003
@@ -25,7 +25,7 @@
 #include <asm/system.h>
 
 extern unsigned long wall_jiffies;
-extern unsigned long last_time_offset;
+extern unsigned long last_nsec_offset;
 
 u64 jiffies_64 = INITIAL_JIFFIES;
 
@@ -74,13 +74,13 @@
 		     - (lost + 1)*cpu_data(time_keeper_id)->itm_delta);
 
 	now = ia64_get_itc();
-	if ((long) (now - last_tick) < 0) {
+	if (unlikely((long) (now - last_tick) < 0)) {
 		printk(KERN_ERR "CPU %d: now < last_tick (now=0x%lx,last_tick=0x%lx)!\n",
 		       smp_processor_id(), now, last_tick);
-		return last_time_offset;
+		return last_nsec_offset;
 	}
 	elapsed_cycles = now - last_tick;
-	return (elapsed_cycles*local_cpu_data->usec_per_cyc) >> IA64_USEC_PER_CYC_SHIFT;
+	return (elapsed_cycles*local_cpu_data->nsec_per_cyc) >> IA64_NSEC_PER_CYC_SHIFT;
 }
 
 void
@@ -115,30 +115,55 @@
 void
 do_gettimeofday (struct timeval *tv)
 {
-	unsigned long seq, usec, sec, old;
+	unsigned long seq, nsec, usec, sec, old, offset;
 
-	do {
+	while (1) {
 		seq = read_seqbegin(&xtime_lock);
-		usec = gettimeoffset();
-
+		{
+			old = last_nsec_offset;
+			offset = gettimeoffset();
+			sec = xtime.tv_sec;
+			nsec = xtime.tv_nsec;
+		}
+		if (unlikely(read_seqretry(&xtime_lock, seq)))
+			continue;
 		/*
-		 * Ensure time never goes backwards, even when ITC on 
-		 * different CPUs are not perfectly synchronized.
+		 * Ensure that for any pair of causally ordered gettimeofday() calls, time
+		 * never goes backwards (even when ITC on different CPUs are not perfectly
+		 * synchronized).  (A pair of concurrent calls to gettimeofday() is by
+		 * definition non-causal and hence it makes no sense to talk about
+		 * time-continuity for such calls.)
+		 *
+		 * Doing this in a lock-free and race-free manner is tricky.  Here is why
+		 * it works (most of the time): read_seqretry() just succeeded, which
+		 * implies we calculated a consistent (valid) value for "offset".  If the
+		 * cmpxchg() below succeeds, we further know that last_nsec_offset still
+		 * has the same value as at the beginning of the loop, so there was
+		 * presumably no timer-tick or other updates to last_nsec_offset in the
+		 * meantime.  This isn't 100% true though: there _is_ a possibility of a
+		 * timer-tick occurring right right after read_seqretry() and then getting
+		 * zero or more other readers which will set last_nsec_offset to the same
+		 * value as the one we read at the beginning of the loop.  If this
+		 * happens, we'll end up returning a slightly newer time than we ought to
+		 * (the jump forward is at most "offset" nano-seconds).  There is no
+		 * danger of causing time to go backwards, though, so we are safe in that
+		 * sense.  We could make the probability of this unlucky case occurring
+		 * arbitrarily small by encoding a version number in last_nsec_offset, but
+		 * even without versioning, the probability of this unlucky case should be
+		 * so small that we won't worry about it.
 		 */
-		do {
-			old = last_time_offset;
-			if (usec <= old) {
-				usec = old;
-				break;
-			}
-		} while (cmpxchg(&last_time_offset, old, usec) != old);
-
-		sec = xtime.tv_sec;
-		usec += xtime.tv_nsec / 1000;
-	} while (read_seqend(&xtime_lock, seq));
+		if (offset <= old) {
+			offset = old;
+			break;
+		} else if (likely(cmpxchg(&last_nsec_offset, old, offset) == old))
+			break;
+
+		/* someone else beat us to updating last_nsec_offset; try again */
+	}
 
+	usec = (nsec + offset) / 1000;
 
-	while (usec >= 1000000) {
+	while (unlikely(usec >= 1000000)) {
 		usec -= 1000000;
 		++sec;
 	}
@@ -278,7 +303,7 @@
 	local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den;
 	local_cpu_data->itc_freq = itc_freq;
 	local_cpu_data->cyc_per_usec = (itc_freq + 500000) / 1000000;
-	local_cpu_data->usec_per_cyc = ((1000000UL<<IA64_USEC_PER_CYC_SHIFT)
+	local_cpu_data->nsec_per_cyc = ((1000000000UL<<IA64_NSEC_PER_CYC_SHIFT)
 					+ itc_freq/2)/itc_freq;
 
 	/* Setup the CPU local timer tick */
diff -Nru a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
--- a/arch/ia64/kernel/traps.c	Tue Feb  4 17:06:16 2003
+++ b/arch/ia64/kernel/traps.c	Thu Mar  6 13:42:08 2003
@@ -486,19 +486,23 @@
 
 	      case 26: /* NaT Consumption */
 		if (user_mode(regs)) {
+			void *addr;
+
 			if (((isr >> 4) & 0xf) == 2) {
 				/* NaT page consumption */
 				sig = SIGSEGV;
 				code = SEGV_ACCERR;
+				addr = (void *) ifa;
 			} else {
 				/* register NaT consumption */
 				sig = SIGILL;
 				code = ILL_ILLOPN;
+				addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
 			}
 			siginfo.si_signo = sig;
 			siginfo.si_code = code;
 			siginfo.si_errno = 0;
-			siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+			siginfo.si_addr = addr;
 			siginfo.si_imm = vector;
 			siginfo.si_flags = __ISR_VALID;
 			siginfo.si_isr = isr;
diff -Nru a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
--- a/arch/ia64/kernel/unwind.c	Tue Feb  4 17:06:17 2003
+++ b/arch/ia64/kernel/unwind.c	Thu Mar  6 21:11:46 2003
@@ -51,18 +51,24 @@
 #define UNW_LOG_HASH_SIZE	(UNW_LOG_CACHE_SIZE + 1)
 #define UNW_HASH_SIZE		(1 << UNW_LOG_HASH_SIZE)
 
-#define UNW_DEBUG	0
 #define UNW_STATS	0	/* WARNING: this disabled interrupts for long time-spans!! */
 
-#if UNW_DEBUG
-  static long unw_debug_level = 255;
-# define debug(level,format...)	if (unw_debug_level > level) printk(format)
-# define dprintk(format...)	printk(format)
-# define inline
-#else
-# define debug(level,format...)
-# define dprintk(format...)
-#endif
+#ifdef UNW_DEBUG
+  static unsigned int unw_debug_level = UNW_DEBUG;
+#  ifdef CONFIG_KDB
+#    include <linux/kdb.h>
+#    define UNW_DEBUG_ON(n)	(unw_debug_level >= n && !KDB_IS_RUNNING())
+#    define UNW_DPRINT(n, ...)	if (UNW_DEBUG_ON(n)) kdb_printf(__VA_ARGS__)
+#  else	/* !CONFIG_KDB */
+#    define UNW_DEBUG_ON(n)	unw_debug_level >= n
+     /* Do not code a printk level, not all debug lines end in newline */
+#    define UNW_DPRINT(n, ...)  if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
+#  endif /* CONFIG_KDB */
+#  define inline
+#else /* !UNW_DEBUG */
+#  define UNW_DEBUG_ON(n)  0
+#  define UNW_DPRINT(n, ...)
+#endif /* UNW_DEBUG */
 
 #if UNW_STATS
 # define STAT(x...)	x
@@ -111,7 +117,7 @@
 	/* script cache: */
 	struct unw_script cache[UNW_CACHE_SIZE];
 
-# if UNW_DEBUG
+# ifdef UNW_DEBUG
 	const char *preg_name[UNW_NUM_REGS];
 # endif
 # if UNW_STATS
@@ -190,7 +196,7 @@
 		struct_offset(struct unw_frame_info, fr_loc[31 - 16])/8,
 	},
 	.hash = { [0 ... UNW_HASH_SIZE - 1] = -1 },
-#if UNW_DEBUG
+#ifdef UNW_DEBUG
 	.preg_name = {
 		"pri_unat_gr", "pri_unat_mem", "bsp", "bspstore", "ar.pfs", "ar.rnat", "psp", "rp",
 		"r4", "r5", "r6", "r7",
@@ -223,10 +229,22 @@
 	else if (reg <= 31)
 		off = struct_offset(struct pt_regs, r16) + 8*(reg - 16);
 	else
-		dprintk("unwind: bad scratch reg r%lu\n", reg);
+		UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __FUNCTION__, reg);
 	return off;
 }
 
+static inline struct pt_regs *
+get_scratch_regs (struct unw_frame_info *info)
+{
+	if (!info->pt) {
+		/* This should not happen with valid unwind info.  */
+		UNW_DPRINT(0, "unwind.%s: bad unwind info: resetting info->pt\n", __FUNCTION__);
+		info->pt = info->sp - 16;
+	}
+	UNW_DPRINT(3, "unwind.%s: sp 0x%lx pt 0x%lx\n", __FUNCTION__, info->sp, info->pt);
+	return (struct pt_regs *) info->pt;
+}
+
 int
 unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char *nat, int write)
 {
@@ -235,7 +253,8 @@
 	struct pt_regs *pt;
 
 	if ((unsigned) regnum - 1 >= 127) {
-		dprintk("unwind: trying to access non-existent r%u\n", regnum);
+		UNW_DPRINT(0, "unwind.%s: trying to access non-existent r%u\n",
+			   __FUNCTION__, regnum);
 		return -1;
 	}
 
@@ -280,8 +299,9 @@
 					if ((unsigned long) addr < info->regstk.limit
 					    || (unsigned long) addr >= info->regstk.top)
 					{
-						dprintk("unwind: %p outside of regstk "
-							"[0x%lx-0x%lx)\n", (void *) addr,
+						UNW_DPRINT(0, "unwind.%s: %p outside of regstk "
+							"[0x%lx-0x%lx)\n",
+							__FUNCTION__, (void *) addr,
 							info->regstk.limit,
 							info->regstk.top);
 						return -1;
@@ -298,11 +318,13 @@
 			}
 		} else {
 			/* access a scratch register */
-			if (info->flags & UNW_FLAG_INTERRUPT_FRAME)
-				pt = (struct pt_regs *) info->psp - 1;
-			else
-				pt = (struct pt_regs *) info->sp - 1;
-			addr = (unsigned long *) ((long) pt + pt_regs_off(regnum));
+			if (!info->pt) {
+				UNW_DPRINT(0, "unwind.%s: no pt-regs; cannot access r%d\n",
+					   __FUNCTION__, regnum);
+				return -1;
+			}
+			pt = get_scratch_regs(info);
+			addr = (unsigned long *) (pt + pt_regs_off(regnum));
 			if (info->pri_unat_loc)
 				nat_addr = info->pri_unat_loc;
 			else
@@ -316,7 +338,8 @@
 		if ((unsigned long) addr < info->regstk.limit
 		    || (unsigned long) addr >= info->regstk.top)
 		{
-			dprintk("unwind: ignoring attempt to access register outside of rbs\n");
+			UNW_DPRINT(0, "unwind.%s: ignoring attempt to access register outside "
+				   "of rbs\n",  __FUNCTION__);
 			return -1;
 		}
 		if ((unsigned long) nat_addr >= info->regstk.top)
@@ -348,10 +371,7 @@
 	unsigned long *addr;
 	struct pt_regs *pt;
 
-	if (info->flags & UNW_FLAG_INTERRUPT_FRAME)
-		pt = (struct pt_regs *) info->psp - 1;
-	else
-		pt = (struct pt_regs *) info->sp - 1;
+	pt = get_scratch_regs(info);
 	switch (regnum) {
 		/* scratch: */
 	      case 0: addr = &pt->b0; break;
@@ -366,7 +386,8 @@
 		break;
 
 	      default:
-		dprintk("unwind: trying to access non-existent b%u\n", regnum);
+		UNW_DPRINT(0, "unwind.%s: trying to access non-existent b%u\n",
+			   __FUNCTION__, regnum);
 		return -1;
 	}
 	if (write)
@@ -383,14 +404,12 @@
 	struct pt_regs *pt;
 
 	if ((unsigned) (regnum - 2) >= 126) {
-		dprintk("unwind: trying to access non-existent f%u\n", regnum);
+		UNW_DPRINT(0, "unwind.%s: trying to access non-existent f%u\n",
+			   __FUNCTION__, regnum);
 		return -1;
 	}
 
-	if (info->flags & UNW_FLAG_INTERRUPT_FRAME)
-		pt = (struct pt_regs *) info->psp - 1;
-	else
-		pt = (struct pt_regs *) info->sp - 1;
+	pt = get_scratch_regs(info);
 
 	if (regnum <= 5) {
 		addr = *(&info->f2_loc + (regnum - 2));
@@ -428,11 +447,7 @@
 	unsigned long *addr;
 	struct pt_regs *pt;
 
-	if (info->flags & UNW_FLAG_INTERRUPT_FRAME)
-		pt = (struct pt_regs *) info->psp - 1;
-	else
-		pt = (struct pt_regs *) info->sp - 1;
-
+	pt = get_scratch_regs(info);
 	switch (regnum) {
 	      case UNW_AR_BSP:
 		addr = info->bsp_loc;
@@ -495,7 +510,8 @@
 		break;
 
 	      default:
-		dprintk("unwind: trying to access non-existent ar%u\n", regnum);
+		UNW_DPRINT(0, "unwind.%s: trying to access non-existent ar%u\n",
+			   __FUNCTION__, regnum);
 		return -1;
 	}
 
@@ -612,7 +628,7 @@
 	      default:
 		break;
 	}
-	dprintk("unwind: bad abreg=0x%x\n", abreg);
+	UNW_DPRINT(0, "unwind.%s: bad abreg=0x%x\n", __FUNCTION__, abreg);
 	return UNW_REG_LC;
 }
 
@@ -652,7 +668,7 @@
 			return;
 		}
 	}
-	dprintk("unwind: excess spill!\n");
+	UNW_DPRINT(0, "unwind.%s: excess spill!\n",  __FUNCTION__);
 }
 
 static inline void
@@ -720,7 +736,7 @@
 desc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave,
 	       struct unw_state_record *sr)
 {
-	int i;
+	int i, region_start;
 
 	if (!(sr->in_body || sr->first_region))
 		finish_prologue(sr);
@@ -732,19 +748,20 @@
 		return;
 	}
 
+	region_start = sr->region_start + sr->region_len;
+
 	for (i = 0; i < sr->epilogue_count; ++i)
 		pop(sr);
 	sr->epilogue_count = 0;
 	sr->epilogue_start = UNW_WHEN_NEVER;
 
-	if (!body)
-		push(sr);
-
-	sr->region_start += sr->region_len;
+	sr->region_start = region_start;
 	sr->region_len = rlen;
 	sr->in_body = body;
 
 	if (!body) {
+		push(sr);
+
 		for (i = 0; i < 4; ++i) {
 			if (mask & 0x8)
 				set_reg(sr->curr.reg + unw.save_order[i], UNW_WHERE_GR,
@@ -765,10 +782,13 @@
 static inline void
 desc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr)
 {
-	if (abi == 0 && context == 'i')
+	if (abi == 0 && context == 'i') {
 		sr->flags |= UNW_FLAG_INTERRUPT_FRAME;
+		UNW_DPRINT(3, "unwind.%s: interrupt frame\n",  __FUNCTION__);
+	}
 	else
-		dprintk("unwind: ignoring unwabi(abi=0x%x,context=0x%x)\n", abi, context);
+		UNW_DPRINT(0, "unwind%s: ignoring unwabi(abi=0x%x,context=0x%x)\n",
+				__FUNCTION__, abi, context);
 }
 
 static inline void
@@ -1136,6 +1156,9 @@
 	unsigned short index;
 	unsigned long ip, pr;
 
+	if (UNW_DEBUG_ON(0))
+		return 0;	/* Always regenerate scripts in debug mode */
+
 	STAT(++unw.stat.cache.lookups);
 
 	ip = info->ip;
@@ -1260,8 +1283,8 @@
 script_emit (struct unw_script *script, struct unw_insn insn)
 {
 	if (script->count >= UNW_MAX_SCRIPT_LEN) {
-		dprintk("unwind: script exceeds maximum size of %u instructions!\n",
-			UNW_MAX_SCRIPT_LEN);
+		UNW_DPRINT(0, "unwind.%s: script exceeds maximum size of %u instructions!\n",
+			__FUNCTION__, UNW_MAX_SCRIPT_LEN);
 		return;
 	}
 	script->insn[script->count++] = insn;
@@ -1302,7 +1325,8 @@
 		break;
 
 	      default:
-		dprintk("unwind: don't know how to emit nat info for where = %u\n", r->where);
+		UNW_DPRINT(0, "unwind.%s: don't know how to emit nat info for where = %u\n",
+			   __FUNCTION__, r->where);
 		return;
 	}
 	insn.opc = opc;
@@ -1339,8 +1363,9 @@
 			}
 			val = unw.preg_index[UNW_REG_R4 + (rval - 4)];
 		} else {
-			opc = UNW_INSN_ADD_SP;
-			val = -sizeof(struct pt_regs) + pt_regs_off(rval);
+			/* register got spilled to a scratch register */
+			opc = UNW_INSN_MOVE_SCRATCH;
+			val = pt_regs_off(rval);
 		}
 		break;
 
@@ -1350,12 +1375,12 @@
 		else if (rval >= 16 && rval <= 31)
 			val = unw.preg_index[UNW_REG_F16 + (rval - 16)];
 		else {
-			opc = UNW_INSN_ADD_SP;
-			val = -sizeof(struct pt_regs);
+			opc = UNW_INSN_MOVE_SCRATCH;
 			if (rval <= 9)
-				val += struct_offset(struct pt_regs, f6) + 16*(rval - 6);
+				val = struct_offset(struct pt_regs, f6) + 16*(rval - 6);
 			else
-				dprintk("unwind: kernel may not touch f%lu\n", rval);
+				UNW_DPRINT(0, "unwind.%s: kernel may not touch f%lu\n",
+					   __FUNCTION__, rval);
 		}
 		break;
 
@@ -1363,14 +1388,13 @@
 		if (rval >= 1 && rval <= 5)
 			val = unw.preg_index[UNW_REG_B1 + (rval - 1)];
 		else {
-			opc = UNW_INSN_ADD_SP;
-			val = -sizeof(struct pt_regs);
+			opc = UNW_INSN_MOVE_SCRATCH;
 			if (rval == 0)
-				val += struct_offset(struct pt_regs, b0);
+				val = struct_offset(struct pt_regs, b0);
 			else if (rval == 6)
-				val += struct_offset(struct pt_regs, b6);
+				val = struct_offset(struct pt_regs, b6);
 			else
-				val += struct_offset(struct pt_regs, b7);
+				val = struct_offset(struct pt_regs, b7);
 		}
 		break;
 
@@ -1383,7 +1407,8 @@
 		break;
 
 	      default:
-		dprintk("unwind: register %u has unexpected `where' value of %u\n", i, r->where);
+		UNW_DPRINT(0, "unwind%s: register %u has unexpected `where' value of %u\n",
+			   __FUNCTION__, i, r->where);
 		break;
 	}
 	insn.opc = opc;
@@ -1456,9 +1481,10 @@
 		r->when = UNW_WHEN_NEVER;
 	sr.pr_val = info->pr;
 
+	UNW_DPRINT(3, "unwind.%s: ip 0x%lx\n", __FUNCTION__, ip);
 	script = script_new(ip);
 	if (!script) {
-		dprintk("unwind: failed to create unwind script\n");
+		UNW_DPRINT(0, "unwind.%s: failed to create unwind script\n",  __FUNCTION__);
 		STAT(unw.stat.script.build_time += ia64_get_itc() - start);
 		return 0;
 	}
@@ -1476,8 +1502,8 @@
 	}
 	if (!e) {
 		/* no info, return default unwinder (leaf proc, no mem stack, no saved regs)  */
-		dprintk("unwind: no unwind info for ip=0x%lx (prev ip=0x%lx)\n", ip,
-			unw.cache[info->prev_script].ip);
+		UNW_DPRINT(1, "unwind.%s: no unwind info for ip=0x%lx (prev ip=0x%lx)\n",
+			__FUNCTION__, ip, unw.cache[info->prev_script].ip);
 		sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
 		sr.curr.reg[UNW_REG_RP].when = -1;
 		sr.curr.reg[UNW_REG_RP].val = 0;
@@ -1525,26 +1551,32 @@
 		sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
 		sr.curr.reg[UNW_REG_RP].when = -1;
 		sr.curr.reg[UNW_REG_RP].val = sr.return_link_reg;
+		UNW_DPRINT(1, "unwind.%s: using default for rp at ip=0x%lx where=%d val=0x%lx\n",
+			   __FUNCTION__, ip, sr.curr.reg[UNW_REG_RP].where,
+			   sr.curr.reg[UNW_REG_RP].val);
 	}
 
-#if UNW_DEBUG
-	printk("unwind: state record for func 0x%lx, t=%u:\n",
-	       table->segment_base + e->start_offset, sr.when_target);
+#ifdef UNW_DEBUG
+	UNW_DPRINT(1, "unwind.%s: state record for func 0x%lx, t=%u:\n",
+		__FUNCTION__, table->segment_base + e->start_offset, sr.when_target);
 	for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r) {
 		if (r->where != UNW_WHERE_NONE || r->when != UNW_WHEN_NEVER) {
-			printk("  %s <- ", unw.preg_name[r - sr.curr.reg]);
+			UNW_DPRINT(1, "  %s <- ", unw.preg_name[r - sr.curr.reg]);
 			switch (r->where) {
-			      case UNW_WHERE_GR:     printk("r%lu", r->val); break;
-			      case UNW_WHERE_FR:     printk("f%lu", r->val); break;
-			      case UNW_WHERE_BR:     printk("b%lu", r->val); break;
-			      case UNW_WHERE_SPREL:  printk("[sp+0x%lx]", r->val); break;
-			      case UNW_WHERE_PSPREL: printk("[psp+0x%lx]", r->val); break;
+			      case UNW_WHERE_GR:     UNW_DPRINT(1, "r%lu", r->val); break;
+			      case UNW_WHERE_FR:     UNW_DPRINT(1, "f%lu", r->val); break;
+			      case UNW_WHERE_BR:     UNW_DPRINT(1, "b%lu", r->val); break;
+			      case UNW_WHERE_SPREL:  UNW_DPRINT(1, "[sp+0x%lx]", r->val); break;
+			      case UNW_WHERE_PSPREL: UNW_DPRINT(1, "[psp+0x%lx]", r->val); break;
 			      case UNW_WHERE_NONE:
-				printk("%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val);
+				UNW_DPRINT(1, "%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val);
+				break;
+
+			      default:
+				UNW_DPRINT(1, "BADWHERE(%d)", r->where);
 				break;
-			      default:		     printk("BADWHERE(%d)", r->where); break;
 			}
-			printk("\t\t%d\n", r->when);
+			UNW_DPRINT(1, "\t\t%d\n", r->when);
 		}
 	}
 #endif
@@ -1642,6 +1674,16 @@
 			s[dst] = s[val];
 			break;
 
+		      case UNW_INSN_MOVE_SCRATCH:
+			if (state->pt) {
+				s[dst] = (unsigned long) get_scratch_regs(state) + val;
+			} else {
+				s[dst] = 0;
+				UNW_DPRINT(0, "unwind.%s: no state->pt, dst=%ld, val=%ld\n",
+					   __FUNCTION__, dst, val);
+			}
+			break;
+
 		      case UNW_INSN_MOVE_STACKED:
 			s[dst] = (unsigned long) ia64_rse_skip_regs((unsigned long *)state->bsp,
 								    val);
@@ -1667,11 +1709,12 @@
 			break;
 
 		      case UNW_INSN_LOAD:
-#if UNW_DEBUG
+#ifdef UNW_DEBUG
 			if ((s[val] & (local_cpu_data->unimpl_va_mask | 0x7)) != 0
 			    || s[val] < TASK_SIZE)
 			{
-				debug(1, "unwind: rejecting bad psp=0x%lx\n", s[val]);
+				UNW_DPRINT(0, "unwind.%s: rejecting bad psp=0x%lx\n",
+					   __FUNCTION__, s[val]);
 				break;
 			}
 #endif
@@ -1704,7 +1747,8 @@
 
 	if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) {
 		/* don't let obviously bad addresses pollute the cache */
-		debug(1, "unwind: rejecting bad ip=0x%lx\n", info->ip);
+		/* FIXME: should really be level 0 but it occurs too often. KAO */
+		UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", __FUNCTION__, info->ip);
 		info->rp_loc = 0;
 		return -1;
 	}
@@ -1713,8 +1757,9 @@
 	if (!scr) {
 		scr = build_script(info);
 		if (!scr) {
-			dprintk("unwind: failed to locate/build unwind script for ip %lx\n",
-				info->ip);
+			UNW_DPRINT(0,
+				   "unwind.%s: failed to locate/build unwind script for ip %lx\n",
+				   __FUNCTION__, info->ip);
 			return -1;
 		}
 		have_write_lock = 1;
@@ -1747,7 +1792,9 @@
 
 	/* restore the ip */
 	if (!info->rp_loc) {
-		debug(1, "unwind: failed to locate return link (ip=0x%lx)!\n", info->ip);
+		/* FIXME: should really be level 0 but it occurs too often. KAO */
+		UNW_DPRINT(1, "unwind.%s: failed to locate return link (ip=0x%lx)!\n",
+			   __FUNCTION__, info->ip);
 		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 		return -1;
 	}
@@ -1757,14 +1804,14 @@
 		 * We don't have unwind info for the gate page, so we consider that part
 		 * of user-space for the purpose of unwinding.
 		 */
-		debug(1, "unwind: reached user-space (ip=0x%lx)\n", ip);
+		UNW_DPRINT(2, "unwind.%s: reached user-space (ip=0x%lx)\n", __FUNCTION__, ip);
 		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 		return -1;
 	}
 
 	/* restore the cfm: */
 	if (!info->pfs_loc) {
-		dprintk("unwind: failed to locate ar.pfs!\n");
+		UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", __FUNCTION__);
 		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 		return -1;
 	}
@@ -1774,16 +1821,18 @@
 	pr = info->pr;
 	num_regs = 0;
 	if ((info->flags & UNW_FLAG_INTERRUPT_FRAME)) {
+		info->pt = info->sp + 16;
 		if ((pr & (1UL << pNonSys)) != 0)
 			num_regs = *info->cfm_loc & 0x7f;		/* size of frame */
 		info->pfs_loc =
-			(unsigned long *) (info->sp + 16 + struct_offset(struct pt_regs, ar_pfs));
+			(unsigned long *) (info->pt + struct_offset(struct pt_regs, ar_pfs));
+		UNW_DPRINT(3, "unwind.%s: interrupt_frame pt 0x%lx\n", __FUNCTION__, info->pt);
 	} else
 		num_regs = (*info->cfm_loc >> 7) & 0x7f;	/* size of locals */
 	info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->bsp, -num_regs);
 	if (info->bsp < info->regstk.limit || info->bsp > info->regstk.top) {
-		dprintk("unwind: bsp (0x%lx) out of range [0x%lx-0x%lx]\n",
-			info->bsp, info->regstk.limit, info->regstk.top);
+		UNW_DPRINT(0, "unwind.%s: bsp (0x%lx) out of range [0x%lx-0x%lx]\n",
+			__FUNCTION__, info->bsp, info->regstk.limit, info->regstk.top);
 		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 		return -1;
 	}
@@ -1791,14 +1840,15 @@
 	/* restore the sp: */
 	info->sp = info->psp;
 	if (info->sp < info->memstk.top || info->sp > info->memstk.limit) {
-		dprintk("unwind: sp (0x%lx) out of range [0x%lx-0x%lx]\n",
-			info->sp, info->memstk.top, info->memstk.limit);
+		UNW_DPRINT(0, "unwind.%s: sp (0x%lx) out of range [0x%lx-0x%lx]\n",
+			__FUNCTION__, info->sp, info->memstk.top, info->memstk.limit);
 		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 		return -1;
 	}
 
 	if (info->ip == prev_ip && info->sp == prev_sp && info->bsp == prev_bsp) {
-		dprintk("unwind: ip, sp, bsp remain unchanged; stopping here (ip=0x%lx)\n", ip);
+		UNW_DPRINT(0, "unwind.%s: ip, sp, bsp unchanged; stopping here (ip=0x%lx)\n",
+			   __FUNCTION__, ip);
 		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 		return -1;
 	}
@@ -1822,7 +1872,8 @@
 	while (unw_unwind(info) >= 0) {
 		if (unw_get_rp(info, &ip) < 0) {
 			unw_get_ip(info, &ip);
-			dprintk("unwind: failed to read return pointer (ip=0x%lx)\n", ip);
+			UNW_DPRINT(0, "unwind.%s: failed to read return pointer (ip=0x%lx)\n",
+				   __FUNCTION__, ip);
 			return -1;
 		}
 		/*
@@ -1833,7 +1884,7 @@
 			return 0;
 	}
 	unw_get_ip(info, &ip);
-	dprintk("unwind: failed to unwind to user-level (ip=0x%lx)\n", ip);
+	UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip);
 	return -1;
 }
 
@@ -1874,11 +1925,30 @@
 	info->task = t;
 	info->sw  = sw;
 	info->sp = info->psp = (unsigned long) (sw + 1) - 16;
+	info->pt = 0;
 	info->cfm_loc = &sw->ar_pfs;
 	sol = (*info->cfm_loc >> 7) & 0x7f;
 	info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol);
 	info->ip = sw->b0;
 	info->pr = sw->pr;
+	UNW_DPRINT(3,
+			"unwind.%s\n"
+			"  rbslimit 0x%lx\n"
+			"  rbstop   0x%lx\n"
+			"  stklimit 0x%lx\n"
+			"  stktop   0x%lx\n"
+			"  task     0x%lx\n"
+			"  sw       0x%lx\n",
+			__FUNCTION__, rbslimit, rbstop, stklimit, stktop,
+			(unsigned long)(info->task),
+			(unsigned long)(info->sw));
+	UNW_DPRINT(3,
+			"  sp/psp   0x%lx\n"
+			"  sol      0x%lx\n"
+			"  bsp      0x%lx\n"
+			"  ip       0x%lx\n"
+			"  pr       0x%lx\n",
+			info->sp, sol, info->bsp, info->ip, info->pr);
 
 	find_save_locs(info);
 	STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags));
@@ -1889,6 +1959,7 @@
 {
 	struct switch_stack *sw = (struct switch_stack *) (t->thread.ksp + 16);
 
+	UNW_DPRINT(1, "unwind.%s\n", __FUNCTION__);
 	unw_init_frame_info(info, t, sw);
 }
 
@@ -1916,7 +1987,8 @@
 	unsigned long flags;
 
 	if (end - start <= 0) {
-		dprintk("unwind: ignoring attempt to insert empty unwind table\n");
+		UNW_DPRINT(0, "unwind.%s: ignoring attempt to insert empty unwind table\n",
+			   __FUNCTION__);
 		return 0;
 	}
 
@@ -1946,13 +2018,15 @@
 	long index;
 
 	if (!handle) {
-		dprintk("unwind: ignoring attempt to remove non-existent unwind table\n");
+		UNW_DPRINT(0, "unwind.%s: ignoring attempt to remove non-existent unwind table\n",
+			   __FUNCTION__);
 		return;
 	}
 
 	table = handle;
 	if (table == &unw.kernel_table) {
-		dprintk("unwind: sorry, freeing the kernel's unwind table is a no-can-do!\n");
+		UNW_DPRINT(0, "unwind.%s: sorry, freeing the kernel's unwind table is a "
+			   "no-can-do!\n", __FUNCTION__);
 		return;
 	}
 
@@ -1964,7 +2038,8 @@
 			if (prev->next == table)
 				break;
 		if (!prev) {
-			dprintk("unwind: failed to find unwind table %p\n", (void *) table);
+			UNW_DPRINT(0, "unwind.%s: failed to find unwind table %p\n",
+				   __FUNCTION__, (void *) table);
 			spin_unlock_irqrestore(&unw.lock, flags);
 			return;
 		}
diff -Nru a/arch/ia64/kernel/unwind_i.h b/arch/ia64/kernel/unwind_i.h
--- a/arch/ia64/kernel/unwind_i.h	Tue Apr  2 10:57:30 2002
+++ b/arch/ia64/kernel/unwind_i.h	Mon Mar  3 16:00:00 2003
@@ -137,7 +137,8 @@
 	UNW_INSN_SETNAT_MEMSTK,		/* s[dst+1].nat.type = MEMSTK;
 					   s[dst+1].nat.off = *s.pri_unat - s[dst] */
 	UNW_INSN_SETNAT_TYPE,		/* s[dst+1].nat.type = val */
-	UNW_INSN_LOAD			/* s[dst] = *s[val] */
+	UNW_INSN_LOAD,			/* s[dst] = *s[val] */
+	UNW_INSN_MOVE_SCRATCH,		/* s[dst] = scratch reg "val" */
 };
 
 struct unw_insn {
diff -Nru a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
--- a/arch/ia64/mm/fault.c	Tue Feb  4 17:06:20 2003
+++ b/arch/ia64/mm/fault.c	Thu Feb 13 05:43:47 2003
@@ -55,7 +55,7 @@
 	/*
 	 * If we're in an interrupt or have no user context, we must not take the fault..
 	 */
-	if (in_interrupt() || !mm)
+	if (in_atomic() || !mm)
 		goto no_context;
 
 	down_read(&mm->mmap_sem);
@@ -79,7 +79,7 @@
 
 #	if (((1 << VM_READ_BIT) != VM_READ || (1 << VM_WRITE_BIT) != VM_WRITE) \
 	    || (1 << VM_EXEC_BIT) != VM_EXEC)
-#		error File is out of sync with <linux/mm.h>.  Pleaes update.
+#		error File is out of sync with <linux/mm.h>.  Please update.
 #	endif
 
 	mask = (  (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
diff -Nru a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
--- a/arch/ia64/mm/hugetlbpage.c	Mon Feb 24 23:13:11 2003
+++ b/arch/ia64/mm/hugetlbpage.c	Thu Mar  6 13:34:27 2003
@@ -19,6 +19,8 @@
 
 #include <linux/sysctl.h>
 
+#define TASK_HPAGE_BASE (REGION_HPAGE << REGION_SHIFT)
+
 static long    htlbpagemem;
 int     htlbpage_max;
 static long    htlbzone_pages;
@@ -98,7 +100,6 @@
 	set_pte(page_table, entry);
 	return;
 }
-
 /*
  * This function checks for proper alignment of input addr and len parameters.
  */
@@ -108,6 +109,20 @@
 		return -EINVAL;
 	if (addr & ~HPAGE_MASK)
 		return -EINVAL;
+	if (REGION_NUMBER(addr) != REGION_HPAGE)
+		return -EINVAL;
+
+	return 0;
+}
+/* This function checks if the address and address+len falls out of HugeTLB region.  It
+ * return -EINVAL if any part of address range falls in HugeTLB region.
+ */
+int  is_invalid_hugepage_range(unsigned long addr, unsigned long len)
+{
+	if (REGION_NUMBER(addr) == REGION_HPAGE)
+		return -EINVAL;
+	if (REGION_NUMBER(addr+len) == REGION_HPAGE)
+		return -EINVAL;
 	return 0;
 }
 
@@ -173,6 +188,39 @@
 	return i;
 }
 
+struct vm_area_struct *hugepage_vma(struct mm_struct *mm, unsigned long addr)
+{
+	if (mm->used_hugetlb) {
+		if (REGION_NUMBER(addr) == REGION_HPAGE) {
+			struct vm_area_struct *vma = find_vma(mm, addr);
+			if (vma && is_vm_hugetlb_page(vma))
+				return vma;
+		}
+	}
+	return NULL;
+}
+
+struct page *follow_huge_addr(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, int write)
+{
+	struct page *page;
+	pte_t *ptep;
+
+	ptep = huge_pte_offset(mm, addr);
+	page = pte_page(*ptep);
+	page += ((addr & ~HPAGE_MASK) >> PAGE_SHIFT);
+	get_page(page);
+	return page;
+}
+int pmd_huge(pmd_t pmd)
+{
+	return 0;
+}
+struct page *
+follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write)
+{
+	return NULL;
+}
+
 void free_huge_page(struct page *page)
 {
 	BUG_ON(page_count(page));
@@ -204,8 +252,6 @@
 	BUG_ON(start & (HPAGE_SIZE - 1));
 	BUG_ON(end & (HPAGE_SIZE - 1));
 
-	spin_lock(&htlbpage_lock);
-	spin_unlock(&htlbpage_lock);
 	for (address = start; address < end; address += HPAGE_SIZE) {
 		pte = huge_pte_offset(mm, address);
 		if (pte_none(*pte))
@@ -257,8 +303,12 @@
 				ret = -ENOMEM;
 				goto out;
 			}
-			add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
+			ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
 			unlock_page(page);
+			if (ret) {
+				free_huge_page(page);
+				goto out;
+			}
 		}
 		set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
 	}
@@ -267,6 +317,29 @@
 	return ret;
 }
 
+unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
+		unsigned long pgoff, unsigned long flags)
+{
+	struct vm_area_struct *vmm;
+
+	if (len > RGN_MAP_LIMIT)
+		return -ENOMEM;
+	if (len & ~HPAGE_MASK)
+		return -EINVAL;
+	/* This code assumes that REGION_HPAGE != 0. */
+	if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1)))
+		addr = TASK_HPAGE_BASE;
+	else
+		addr = ALIGN(addr, HPAGE_SIZE);
+	for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
+		/* At this point:  (!vmm || addr < vmm->vm_end). */
+		if (REGION_OFFSET(addr) + len > RGN_MAP_LIMIT)
+			return -ENOMEM;
+		if (!vmm || (addr + len) <= vmm->vm_start)
+			return addr;
+		addr = ALIGN(vmm->vm_end, HPAGE_SIZE);
+	}
+}
 void update_and_free_page(struct page *page)
 {
 	int j;
@@ -302,8 +375,8 @@
 				break;
 		}
 		page = list_entry(p, struct page, list);
-		if ((page_zone(page))->name[0] != 'H') // Look for non-Highmem
-				map = page;
+		if (!PageHighMem(page))
+			map = page;
 	}
 	if (map) {
 		list_del(&map->list);
@@ -317,8 +390,8 @@
 
 int set_hugetlb_mem_size(int count)
 {
-	int j, lcount;
-	struct page *page, *map;
+	int  lcount;
+	struct page *page ;
 	extern long htlbzone_pages;
 	extern struct list_head htlbpage_freelist;
 
@@ -417,5 +490,4 @@
 
 struct vm_operations_struct hugetlb_vm_ops = {
 	.nopage =	hugetlb_nopage,
-	.close =	zap_hugetlb_resources,
 };
diff -Nru a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
--- a/arch/ia64/mm/tlb.c	Wed Nov 13 17:57:34 2002
+++ b/arch/ia64/mm/tlb.c	Thu Jan 30 06:14:13 2003
@@ -81,9 +81,13 @@
 	}
 	read_unlock(&tasklist_lock);
 	/* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */
-	for (i = 0; i < NR_CPUS; ++i)
-		if (i != smp_processor_id())
-			per_cpu(ia64_need_tlb_flush, i) = 1;
+	{
+		int cpu = get_cpu(); /* prevent preemption/migration */
+		for (i = 0; i < NR_CPUS; ++i)
+			if (i != cpu)
+				per_cpu(ia64_need_tlb_flush, i) = 1;
+		put_cpu();
+	}
 	local_flush_tlb_all();
 }
 
diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
--- a/arch/ia64/pci/pci.c	Tue Nov  5 07:08:17 2002
+++ b/arch/ia64/pci/pci.c	Tue Mar  4 18:40:15 2003
@@ -272,3 +272,76 @@
 
 	return 0;
 }
+
+/**
+ * pci_cacheline_size - determine cacheline size for PCI devices
+ * @dev: void
+ *
+ * We want to use the line-size of the outer-most cache.  We assume
+ * that this line-size is the same for all CPUs.
+ *
+ * Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info().
+ *
+ * RETURNS: An appropriate -ERRNO error value on eror, or zero for success.
+ */
+static unsigned long
+pci_cacheline_size (void)
+{
+	u64 levels, unique_caches;
+	s64 status;
+	pal_cache_config_info_t cci;
+	static u8 cacheline_size;
+
+	if (cacheline_size)
+		return cacheline_size;
+
+	status = ia64_pal_cache_summary(&levels, &unique_caches);
+	if (status != 0) {
+		printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n",
+		       __FUNCTION__, status);
+		return SMP_CACHE_BYTES;
+	}
+
+	status = ia64_pal_cache_config_info(levels - 1, /* cache_type (data_or_unified)= */ 2,
+					    &cci);
+	if (status != 0) {
+		printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed (status=%ld)\n",
+		       __FUNCTION__, status);
+		return SMP_CACHE_BYTES;
+	}
+	cacheline_size = 1 << cci.pcci_line_size;
+	return cacheline_size;
+}
+
+/**
+ * pcibios_prep_mwi - helper function for drivers/pci/pci.c:pci_set_mwi()
+ * @dev: the PCI device for which MWI is enabled
+ *
+ * For ia64, we can get the cacheline sizes from PAL.
+ *
+ * RETURNS: An appropriate -ERRNO error value on eror, or zero for success.
+ */
+int
+pcibios_prep_mwi (struct pci_dev *dev)
+{
+	unsigned long desired_linesize, current_linesize;
+	int rc = 0;
+	u8 pci_linesize;
+
+	desired_linesize = pci_cacheline_size();
+
+	pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &pci_linesize);
+	current_linesize = 4 * pci_linesize;
+	if (desired_linesize != current_linesize) {
+		printk(KERN_WARNING "PCI: slot %s has incorrect PCI cache line size of %lu bytes,",
+		       dev->slot_name, current_linesize);
+		if (current_linesize > desired_linesize) {
+			printk(" expected %lu bytes instead\n", desired_linesize);
+			rc = -EINVAL;
+		} else {
+			printk(" correcting to %lu\n", desired_linesize);
+			pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, desired_linesize / 4);
+		}
+	}
+	return rc;
+}
diff -Nru a/arch/ia64/sn/io/Makefile b/arch/ia64/sn/io/Makefile
--- a/arch/ia64/sn/io/Makefile	Mon Feb  3 14:19:35 2003
+++ b/arch/ia64/sn/io/Makefile	Mon Feb 24 04:55:04 2003
@@ -17,6 +17,6 @@
 		hcl.o labelcl.o invent.o sgi_io_sim.o \
 		klgraph_hack.o hcl_util.o cdl.o hubdev.o hubspc.o \
 		alenlist.o pci.o pci_dma.o ate_utils.o \
-		ifconfig_net.o io.o ifconfig_bus.o
+		ifconfig_net.o io.o ioconfig_bus.o
 
 obj-$(CONFIG_PCIBA)		+= pciba.o
diff -Nru a/arch/ia64/sn/io/ioconfig_bus.c b/arch/ia64/sn/io/ioconfig_bus.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/ioconfig_bus.c	Mon Feb 24 04:55:13 2003
@@ -0,0 +1,402 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ *  ioconfig_bus - SGI's Persistent PCI Bus Numbering.
+ *
+ * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc.  All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+
+#include <asm/sn/sgi.h>
+#include <linux/devfs_fs.h>
+#include <linux/devfs_fs_kernel.h>
+#include <asm/io.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm//sn/sn_sal.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/ioconfig_bus.h>
+
+#define SGI_IOCONFIG_BUS "SGI-PERSISTENT PCI BUS NUMBERING"
+#define SGI_IOCONFIG_BUS_VERSION "1.0"
+
+/*
+ * Some Global definitions.
+ */
+devfs_handle_t ioconfig_bus_handle = NULL;
+unsigned long ioconfig_bus_debug = 0;
+
+#ifdef IOCONFIG_BUS_DEBUG
+#define DBG(x...)	printk(x)
+#else
+#define DBG(x...)
+#endif
+
+u64 ioconfig_file = 0;
+u64 ioconfig_file_size = 0;
+u64 ioconfig_activated = 0;
+char ioconfig_kernopts[128];
+
+/*
+ * For debugging purpose .. hardcode a table ..
+ */
+struct  ascii_moduleid *ioconfig_bus_table;
+u64 ioconfig_bus_table_size = 0;
+
+
+int free_entry = 0;
+int new_entry = 0;
+
+int next_basebus_number = 0;
+
+void
+ioconfig_get_busnum(char *io_moduleid, int *bus_num)
+{
+	struct	ascii_moduleid  *temp;
+	int index;
+
+	DBG("ioconfig_get_busnum io_moduleid %s\n", io_moduleid);
+
+	*bus_num = -1;
+	temp = ioconfig_bus_table;
+	for (index = 0; index < free_entry; temp++, index++) {
+		if ( (io_moduleid[0] == temp->io_moduleid[0]) &&
+		     (io_moduleid[1] == temp->io_moduleid[1]) &&
+		     (io_moduleid[2] == temp->io_moduleid[2]) &&
+		     (io_moduleid[4] == temp->io_moduleid[4]) &&
+		     (io_moduleid[5] == temp->io_moduleid[5]) ) {
+			*bus_num = index * 0x10;
+			return;
+		}
+	}
+
+	/*
+	 * New IO Brick encountered.
+	 */
+	if (((int)io_moduleid[0]) == 0) {
+		DBG("ioconfig_get_busnum: Invalid Module Id given %s\n", io_moduleid);
+		return;
+	}
+
+	io_moduleid[3] = '#';
+	strcpy((char *)&(ioconfig_bus_table[free_entry].io_moduleid), io_moduleid);
+	*bus_num = free_entry * 0x10;
+	free_entry++;
+}
+
+void
+dump_ioconfig_table()
+{
+
+	int index = 0;
+	struct ascii_moduleid *temp;
+
+	temp = ioconfig_bus_table;
+	while (index < free_entry) {
+		DBG("ASSCI Module ID %s\n", temp->io_moduleid);
+		temp++;
+		index++;
+	}
+}
+
+/*
+ * nextline
+ *	This routine returns the nextline in the buffer.
+ */
+int nextline(char *buffer, char **next, char *line)
+{
+
+	char *temp;
+
+	if (buffer[0] == 0x0) {
+		return(0);
+	}
+
+	temp = buffer;
+	while (*temp != 0) {
+		*line = *temp;
+		if (*temp != '\n'){
+			*line = *temp;
+			temp++; line++;
+		} else
+			break;
+	}
+
+	if (*temp == 0)
+		*next = temp;
+	else
+		*next = ++temp;
+
+	return(1);
+}
+
+/*
+ * build_pcibus_name
+ *	This routine parses the ioconfig contents read into
+ *	memory by ioconfig command in EFI and builds the
+ *	persistent pci bus naming table.
+ */
+void
+build_moduleid_table(char *file_contents, struct ascii_moduleid *table)
+{
+	/*
+	 * Read the whole file into memory.
+	 */
+	int rc;
+	char *name;
+	char *temp;
+	char *next;
+	char *current;
+	char *line;
+	struct ascii_moduleid *moduleid;
+
+	line = kmalloc(256, GFP_KERNEL);
+	memset(line, 0,256);
+	name = kmalloc(125, GFP_KERNEL);
+	memset(name, 0, 125);
+	moduleid = table;
+	current = file_contents;
+	while (nextline(current, &next, line)){
+
+		DBG("current 0x%lx next 0x%lx\n", current, next);
+
+		temp = line;
+		/*
+		 * Skip all leading Blank lines ..
+		 */
+		while (isspace(*temp))
+			if (*temp != '\n')
+				temp++;
+			else
+				break;
+
+		if (*temp == '\n') {
+			current = next;
+			memset(line, 0, 256);
+			continue;
+		}
+ 
+		/*
+		 * Skip comment lines
+		 */
+		if (*temp == '#') {
+			current = next;
+			memset(line, 0, 256);
+			continue;
+		}
+
+		/*
+		 * Get the next free entry in the table.
+		 */
+		rc = sscanf(temp, "%s", name);
+		strcpy(&moduleid->io_moduleid[0], name);
+		DBG("Found %s\n", name);
+		moduleid++;
+		free_entry++;
+		current = next;
+		memset(line, 0, 256);
+	}
+
+	new_entry = free_entry;
+	kfree(line);
+	kfree(name);
+
+	return;
+}
+
+void
+ioconfig_bus_init(void)
+{
+
+	struct ia64_sal_retval ret_stuff;
+	u64	*temp;
+	int	cnode;
+
+	DBG("ioconfig_bus_init called.\n");
+
+        for (cnode = 0; cnode < numnodes; cnode++) {
+		nasid_t nasid;
+		/*
+	 	 * Make SAL call to get the address of the bus configuration table.
+	 	 */
+		ret_stuff.status = (uint64_t)0;
+		ret_stuff.v0 = (uint64_t)0;
+		ret_stuff.v1 = (uint64_t)0;
+		ret_stuff.v2 = (uint64_t)0;
+		nasid = COMPACT_TO_NASID_NODEID(cnode);
+		SAL_CALL(ret_stuff, SN_SAL_BUS_CONFIG, 0, nasid, 0, 0, 0, 0, 0);
+		temp = (u64 *)TO_NODE_CAC(nasid, ret_stuff.v0);
+		ioconfig_file = *temp;
+		DBG("ioconfig_bus_init: Nasid %d ret_stuff.v0 0x%lx\n", nasid,
+			ret_stuff.v0);
+		if (ioconfig_file) {
+			ioconfig_file_size = ret_stuff.v1;
+			ioconfig_file = (ioconfig_file | CACHEABLE_MEM_SPACE);
+			ioconfig_activated = 1;
+			break;
+		}
+	}
+
+	DBG("ioconfig_bus_init: ret_stuff.v0 %p ioconfig_file %p %d\n",
+		ret_stuff.v0, (void *)ioconfig_file, (int)ioconfig_file_size);
+
+	ioconfig_bus_table = kmalloc( 512, GFP_KERNEL );
+	memset(ioconfig_bus_table, 0, 512);
+
+	/*
+	 * If ioconfig options are given on the bootline .. take it.
+	 */
+	if (*ioconfig_kernopts != '\0') {
+		/*
+		 * ioconfig="..." kernel options given.
+		 */
+		DBG("ioconfig_bus_init: Kernel Options given.\n");
+		(void) build_moduleid_table((char *)ioconfig_kernopts, ioconfig_bus_table);
+		(void) dump_ioconfig_table(ioconfig_bus_table);
+		return;
+	}
+
+	if (ioconfig_activated) {
+		DBG("ioconfig_bus_init: ioconfig file given.\n");
+		(void) build_moduleid_table((char *)ioconfig_file, ioconfig_bus_table);
+		(void) dump_ioconfig_table(ioconfig_bus_table);
+	} else {
+		DBG("ioconfig_bus_init: ioconfig command not executed in prom\n");
+	}
+
+}
+
+void
+ioconfig_bus_new_entries(void)
+{
+
+	
+	int index = 0;
+	struct ascii_moduleid *temp;
+
+	if ((ioconfig_activated) && (free_entry > new_entry)) {
+		printk("### Please add the following new IO Bricks Module ID \n");
+		printk("### to your Persistent Bus Numbering Config File\n");
+	} else
+		return;
+
+	index = new_entry;
+	temp = &ioconfig_bus_table[index];
+        while (index < free_entry) {
+                printk("%s\n", temp);
+		temp++;
+                index++;
+        }
+	printk("### End\n");
+
+}
+static int ioconfig_bus_ioctl(struct inode * inode, struct file * file,
+        unsigned int cmd, unsigned long arg)
+{
+
+	struct ioconfig_parm parm;
+
+	/*
+	 * Copy in the parameters.
+	 */
+	copy_from_user(&parm, (char *)arg, sizeof(struct ioconfig_parm));
+	parm.number = free_entry - new_entry;
+	parm.ioconfig_activated = ioconfig_activated;
+	copy_to_user((char *)arg, &parm, sizeof(struct ioconfig_parm));
+	copy_to_user((char *)parm.buffer, &ioconfig_bus_table[new_entry], sizeof(struct  ascii_moduleid) * (free_entry - new_entry));
+
+	return 0;
+}
+
+/*
+ * ioconfig_bus_open - Opens the special device node "/dev/hw/.ioconfig_bus".
+ */
+static int ioconfig_bus_open(struct inode * inode, struct file * filp)
+{
+	if (ioconfig_bus_debug) {
+        	DBG("ioconfig_bus_open called.\n");
+	}
+
+        return(0);
+
+}
+
+/*
+ * ioconfig_bus_close - Closes the special device node "/dev/hw/.ioconfig_bus".
+ */
+static int ioconfig_bus_close(struct inode * inode, struct file * filp)
+{
+
+	if (ioconfig_bus_debug) {
+        	DBG("ioconfig_bus_close called.\n");
+	}
+
+        return(0);
+}
+
+struct file_operations ioconfig_bus_fops = {
+	ioctl:ioconfig_bus_ioctl,
+	open:ioconfig_bus_open,		/* open */
+	release:ioconfig_bus_close	/* release */
+};
+
+
+/*
+ * init_ifconfig_bus() - Boot time initialization.  Ensure that it is called 
+ *	after devfs has been initialized.
+ *
+ */
+int init_ioconfig_bus(void)
+{
+	ioconfig_bus_handle = NULL;
+	ioconfig_bus_handle = hwgraph_register(hwgraph_root, ".ioconfig_bus",
+			0, DEVFS_FL_AUTO_DEVNUM,
+			0, 0,
+			S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
+			&ioconfig_bus_fops, NULL);
+
+	if (ioconfig_bus_handle == NULL) {
+		panic("Unable to create SGI PERSISTENT BUS NUMBERING Driver.\n");
+	}
+
+	return(0);
+
+}
+
+static int __init ioconfig_bus_setup (char *str)
+{
+
+	char *temp;
+
+	DBG("ioconfig_bus_setup: Kernel Options %s\n", str);
+
+	temp = (char *)ioconfig_kernopts;
+	memset(temp, 0, 128);
+	while ( (*str != '\0') && !isspace (*str) ) {
+		if (*str == ',') {
+			*temp = '\n';
+			temp++;
+			str++;
+			continue;
+		}
+		*temp = *str;
+		temp++;
+		str++;
+	}
+
+	return(0);
+		
+}
+__setup("ioconfig=", ioconfig_bus_setup);
diff -Nru a/arch/ia64/sn/io/sn2/Makefile b/arch/ia64/sn/io/sn2/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/Makefile	Mon Feb 24 05:40:29 2003
@@ -0,0 +1,19 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2002-2003 Silicon Graphics, Inc.  All Rights Reserved.
+#
+# Makefile for the sn2 specific io routines.
+
+EXTRA_CFLAGS    := -DLITTLE_ENDIAN
+
+obj-y += bte_error.o geo_op.o klconflib.o klgraph.o l1.o \
+	 l1_command.o ml_iograph.o ml_SN_init.o ml_SN_intr.o module.o \
+	 pci_bus_cvlink.o pciio.o pic.o sgi_io_init.o shub.o shuberror.o \
+	 shub_intr.o shubio.o xbow.o xtalk.o
+
+obj-$(CONFIG_KDB) += kdba_io.o 
+
+obj-$(CONFIG_SHUB_1_0_SPECIFIC) += efi-rtc.o
diff -Nru a/arch/ia64/sn/io/sn2/geo_op.c b/arch/ia64/sn/io/sn2/geo_op.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/geo_op.c	Mon Feb 24 05:23:08 2003
@@ -0,0 +1,314 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+/*
+ * @doc file m:hwcfg
+ * DESCRIPTION:
+ * 
+ * This file contains routines for manipulating and generating 
+ * Geographic IDs.  They are in a file by themself since they have
+ * no dependencies on other modules.
+ *  
+ * ORIGIN:
+ * 
+ * New for SN2
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <asm/smp.h>
+#include <asm/irq.h>
+#include <asm/hw_irq.h>
+#include <asm/sn/types.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/io.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/xtalk/xtalk.h>
+#include <asm/sn/pci/pcibr_private.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn2/shub_mmr_t.h>
+#include <asm/sn/sn2/shubio.h>
+#include <asm/sal.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/module.h>
+#include <asm/sn/geo.h>
+
+/********** Global functions and data (visible outside the module) ***********/
+
+/*
+ * @doc gf:geo_module
+ * 
+ * moduleid_t geo_module(geoid_t g)
+ * 
+ * DESCRIPTION:
+ * 
+ * Return the moduleid component of a geoid.
+ *  
+ * INTERNALS:
+ * 
+ * Return INVALID_MODULE for an invalid geoid.  Otherwise extract the
+ * moduleid from the structure, and return it.
+ *   
+ * ORIGIN:
+ * 
+ * New for SN2
+ */
+
+moduleid_t
+geo_module(geoid_t g)
+{
+    if (g.any.type == GEO_TYPE_INVALID)
+	return INVALID_MODULE;
+    else
+	return g.any.module;
+}
+
+
+/*
+ * @doc gf:geo_slab
+ * 
+ * slabid_t geo_slab(geoid_t g)
+ * 
+ * DESCRIPTION:
+ * 
+ * Return the slabid component of a geoid.
+ *  
+ * INTERNALS:
+ * 
+ * Return INVALID_SLAB for an invalid geoid.  Otherwise extract the
+ * slabid from the structure, and return it.
+ *   
+ * ORIGIN:
+ * 
+ * New for SN2
+ */
+
+slabid_t
+geo_slab(geoid_t g)
+{
+    if (g.any.type == GEO_TYPE_INVALID)
+	return INVALID_SLAB;
+    else
+	return g.any.slab;
+}
+
+
+/*
+ * @doc gf:geo_type
+ * 
+ * geo_type_t geo_type(geoid_t g)
+ * 
+ * DESCRIPTION:
+ * 
+ * Return the type component of a geoid.
+ *  
+ * INTERNALS:
+ * 
+ * Extract the type from the structure, and return it.
+ *   
+ * ORIGIN:
+ * 
+ * New for SN2
+ */
+
+geo_type_t
+geo_type(geoid_t g)
+{
+    return g.any.type;
+}
+
+
+/*
+ * @doc gf:geo_valid
+ * 
+ * int geo_valid(geoid_t g)
+ * 
+ * DESCRIPTION:
+ * 
+ * Return nonzero if g has a valid geoid type.
+ *  
+ * INTERNALS:
+ * 
+ * Test the type against GEO_TYPE_INVALID, and return the result.
+ *   
+ * ORIGIN:
+ * 
+ * New for SN2
+ */
+
+int
+geo_valid(geoid_t g)
+{
+    return g.any.type != GEO_TYPE_INVALID;
+}
+
+
+/*
+ * @doc gf:geo_cmp
+ * 
+ * int geo_cmp(geoid_t g0, geoid_t g1)
+ * 
+ * DESCRIPTION:
+ * 
+ * Compare two geoid_t values, from the coarsest field to the finest.
+ * The comparison should be consistent with the physical locations of
+ * of the hardware named by the geoids.
+ *  
+ * INTERNALS:
+ * 
+ * First compare the module, then the slab, type, and type-specific fields.
+ *   
+ * ORIGIN:
+ * 
+ * New for SN2
+ */
+
+int
+geo_cmp(geoid_t g0, geoid_t g1)
+{
+    int rv;
+
+    /* Compare the common fields */
+    rv = MODULE_CMP(geo_module(g0), geo_module(g1));
+    if (rv != 0)
+	return rv;
+
+    rv = geo_slab(g0) - geo_slab(g1);
+    if (rv != 0)
+	return rv;
+
+    /* Within a slab, sort by type */
+    rv = geo_type(g0) - geo_type(g1);
+    if (rv != 0)
+	return rv;
+
+    switch(geo_type(g0)) {
+    case GEO_TYPE_CPU:
+	rv = g0.cpu.slice - g1.cpu.slice;
+	break;
+
+    case GEO_TYPE_IOCARD:
+	rv = g0.pcicard.bus - g1.pcicard.bus;
+	if (rv) break;
+	rv = SLOTNUM_GETSLOT(g0.pcicard.slot) -
+	    SLOTNUM_GETSLOT(g1.pcicard.slot);
+	break;
+
+    case GEO_TYPE_MEM:
+	rv = g0.mem.membus - g1.mem.membus;
+	if (rv) break;
+	rv = g0.mem.memslot - g1.mem.memslot;
+	break;
+
+    default:
+	rv = 0;
+    }
+
+    return rv;
+}
+
+
+/*
+ * @doc gf:geo_new
+ * 
+ * geoid_t geo_new(geo_type_t type, ...)
+ * 
+ * DESCRIPTION:
+ * 
+ * Generate a new geoid_t value of the given type from its components.
+ * Expected calling sequences:
+ * \@itemize \@bullet
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_INVALID)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_MODULE, moduleid_t m)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_NODE, moduleid_t m, slabid_t s)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_RTR, moduleid_t m, slabid_t s)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_IOCNTL, moduleid_t m, slabid_t s)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_IOCARD, moduleid_t m, slabid_t s, char bus, slotid_t slot)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_CPU, moduleid_t m, slabid_t s, char slice)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_MEM, moduleid_t m, slabid_t s, char membus, char slot)\}
+ * \@end itemize
+ *
+ * Invalid types return a GEO_TYPE_INVALID geoid_t.
+ *  
+ * INTERNALS:
+ * 
+ * Use the type to determine which fields to expect.  Write the fields into
+ * a new geoid_t and return it.  Note:  scalars smaller than an "int" are
+ * promoted to "int" by the "..." operator, so we need extra casts on "char",
+ * "slotid_t", and "slabid_t".
+ *   
+ * ORIGIN:
+ * 
+ * New for SN2
+ */
+
+geoid_t
+geo_new(geo_type_t type, ...)
+{
+    va_list al;
+    geoid_t g;
+    memset(&g, 0, sizeof(g));
+
+    va_start(al, type);
+
+    /* Make sure the type is sane */
+    if (type >= GEO_TYPE_MAX)
+	type = GEO_TYPE_INVALID;
+
+    g.any.type = type;
+    if (type == GEO_TYPE_INVALID)
+	goto done;		/* invalid geoids have no components at all */
+
+    g.any.module = va_arg(al, moduleid_t);
+    if (type == GEO_TYPE_MODULE)
+	goto done;
+
+    g.any.slab = (slabid_t)va_arg(al, int);
+
+    /* Some types have additional components */
+    switch(type) {
+    case GEO_TYPE_CPU:
+	g.cpu.slice = (char)va_arg(al, int);
+	break;
+
+    case GEO_TYPE_IOCARD:
+	g.pcicard.bus = (char)va_arg(al, int);
+	g.pcicard.slot = (slotid_t)va_arg(al, int);
+	break;
+
+    case GEO_TYPE_MEM:
+	g.mem.membus = (char)va_arg(al, int);
+	g.mem.memslot = (char)va_arg(al, int);
+	break;
+
+    default:
+	break;
+    }
+
+ done:
+    va_end(al);
+    return g;
+}
diff -Nru a/arch/ia64/sn/io/sn2/klconflib.c b/arch/ia64/sn/io/sn2/klconflib.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/klconflib.c	Mon Feb 24 05:23:53 2003
@@ -0,0 +1,933 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/io.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/nodepda.h>
+#include <asm/sn/module.h>
+#include <asm/sn/router.h>
+#include <asm/sn/xtalk/xbow.h>
+
+#define printf printk
+int hasmetarouter;
+
+#define LDEBUG 0
+#define NIC_UNKNOWN ((nic_t) -1)
+
+#undef DEBUG_KLGRAPH
+#ifdef DEBUG_KLGRAPH
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* DEBUG_KLGRAPH */
+
+static void sort_nic_names(lboard_t *) ;
+
+u64 klgraph_addr[MAX_COMPACT_NODES];
+int module_number = 0;
+
+lboard_t *
+find_lboard(lboard_t *start, unsigned char brd_type)
+{
+	/* Search all boards stored on this node. */
+	while (start) {
+		if (start->brd_type == brd_type)
+			return start;
+		start = KLCF_NEXT(start);
+	}
+
+	/* Didn't find it. */
+	return (lboard_t *)NULL;
+}
+
+lboard_t *
+find_lboard_class(lboard_t *start, unsigned char brd_type)
+{
+	/* Search all boards stored on this node. */
+	while (start) {
+		if (KLCLASS(start->brd_type) == KLCLASS(brd_type))
+			return start;
+		start = KLCF_NEXT(start);
+	}
+
+	/* Didn't find it. */
+	return (lboard_t *)NULL;
+}
+
+klinfo_t *
+find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type)
+{
+	int index, j;
+
+	if (kli == (klinfo_t *)NULL) {
+		index = 0;
+	} else {
+		for (j = 0; j < KLCF_NUM_COMPS(brd); j++) {
+			if (kli == KLCF_COMP(brd, j))
+				break;
+		}
+		index = j;
+		if (index == KLCF_NUM_COMPS(brd)) {
+			DBG("find_component: Bad pointer: 0x%p\n", kli);
+			return (klinfo_t *)NULL;
+		}
+		index++;	/* next component */
+	}
+	
+	for (; index < KLCF_NUM_COMPS(brd); index++) {		
+		kli = KLCF_COMP(brd, index);
+		DBG("find_component: brd %p kli %p  request type = 0x%x kli type 0x%x\n", brd, kli, kli->struct_type, KLCF_COMP_TYPE(kli));
+		if (KLCF_COMP_TYPE(kli) == struct_type)
+			return kli;
+	}
+
+	/* Didn't find it. */
+	return (klinfo_t *)NULL;
+}
+
+klinfo_t *
+find_first_component(lboard_t *brd, unsigned char struct_type)
+{
+	return find_component(brd, (klinfo_t *)NULL, struct_type);
+}
+
+lboard_t *
+find_lboard_modslot(lboard_t *start, geoid_t geoid)
+{
+	/* Search all boards stored on this node. */
+	while (start) {
+		if (geo_cmp(start->brd_geoid, geoid))
+			return start;
+		start = KLCF_NEXT(start);
+	}
+
+	/* Didn't find it. */
+	return (lboard_t *)NULL;
+}
+
+lboard_t *
+find_lboard_module(lboard_t *start, geoid_t geoid)
+{
+        /* Search all boards stored on this node. */
+        while (start) {
+                if (geo_cmp(start->brd_geoid, geoid))
+                        return start;
+                start = KLCF_NEXT(start);
+        }
+
+        /* Didn't find it. */
+        return (lboard_t *)NULL;
+}
+
+lboard_t *
+find_lboard_module_class(lboard_t *start, geoid_t geoid,
+                                                unsigned char brd_type)
+{
+	while (start) {
+		DBG("find_lboard_module_class: lboard 0x%p, start->brd_geoid 0x%x, mod 0x%x, start->brd_type 0x%x, brd_type 0x%x\n", start, start->brd_geoid, geoid, start->brd_type, brd_type);
+
+		if (geo_cmp(start->brd_geoid, geoid) &&
+			(KLCLASS(start->brd_type) == KLCLASS(brd_type)))
+			return start;
+		start = KLCF_NEXT(start);
+	}
+
+	/* Didn't find it. */
+	return (lboard_t *)NULL;
+}
+
+/*
+ * Convert a NIC name to a name for use in the hardware graph.
+ */
+void
+nic_name_convert(char *old_name, char *new_name)
+{
+        int i;
+        char c;
+        char *compare_ptr;
+
+	if ((old_name[0] == '\0') || (old_name[1] == '\0')) {
+                strcpy(new_name, EDGE_LBL_XWIDGET);
+        } else {
+                for (i = 0; i < strlen(old_name); i++) {
+                        c = old_name[i];
+
+                        if (isalpha(c))
+                                new_name[i] = tolower(c);
+                        else if (isdigit(c))
+                                new_name[i] = c;
+                        else
+                                new_name[i] = '_';
+                }
+                new_name[i] = '\0';
+        }
+
+        /* XXX -
+         * Since a bunch of boards made it out with weird names like
+         * IO6-fibbbed and IO6P2, we need to look for IO6 in a name and
+         * replace it with "baseio" to avoid confusion in the field.
+	 * We also have to make sure we don't report media_io instead of
+	 * baseio.
+         */
+
+        /* Skip underscores at the beginning of the name */
+        for (compare_ptr = new_name; (*compare_ptr) == '_'; compare_ptr++)
+                ;
+
+	/*
+	 * Check for some names we need to replace.  Early boards
+	 * had junk following the name so check only the first
+	 * characters.
+	 */
+        if (!strncmp(new_name, "io6", 3) || 
+            !strncmp(new_name, "mio", 3) || 
+	    !strncmp(new_name, "media_io", 8))
+		strcpy(new_name, "baseio");
+	else if (!strncmp(new_name, "divo", 4))
+		strcpy(new_name, "divo") ;
+
+}
+
+/*
+ * Find the lboard structure and get the board name.
+ * If we can't find the structure or it's too low a revision,
+ * use default name.
+ */
+lboard_t *
+get_board_name(nasid_t nasid, geoid_t geoid, slotid_t slot, char *name)
+{
+	lboard_t *brd;
+
+	brd = find_lboard_modslot((lboard_t *)KL_CONFIG_INFO(nasid),
+				  geoid);
+
+#ifndef _STANDALONE
+	{
+		cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid);
+
+		if (!brd && (NODEPDA(cnode)->xbow_peer != INVALID_NASID))
+			brd = find_lboard_modslot((lboard_t *)
+				KL_CONFIG_INFO(NODEPDA(cnode)->xbow_peer),
+				geoid);
+	}
+#endif
+
+	if (!brd || (brd->brd_sversion < 2)) {
+		strcpy(name, EDGE_LBL_XWIDGET);
+	} else {
+		nic_name_convert(brd->brd_name, name);
+	}
+
+	/*
+	 * PV # 540860
+	 * If the name is not 'baseio'
+	 * get the lowest of all the names in the nic string.
+	 * This is needed for boards like divo, which can have
+	 * a bunch of daughter cards, but would like to be called
+	 * divo. We could do this for baseio
+	 * but it has some special case names that we would not
+	 * like to disturb at this point.
+	 */
+
+	/* gfx boards don't need any of this name scrambling */
+	if (brd && (KLCLASS(brd->brd_type) == KLCLASS_GFX)) {
+		return(brd);
+	}
+
+	if (!(!strcmp(name, "baseio") )) {
+		if (brd) {
+			sort_nic_names(brd) ;
+			/* Convert to small case, '-' to '_' etc */
+			nic_name_convert(brd->brd_name, name) ;
+		}
+	}
+
+	return(brd);
+}
+
+/*
+ * get_actual_nasid
+ *
+ *	Completely disabled brds have their klconfig on 
+ *	some other nasid as they have no memory. But their
+ *	actual nasid is hidden in the klconfig. Use this
+ *	routine to get it. Works for normal boards too.
+ */
+nasid_t
+get_actual_nasid(lboard_t *brd)
+{
+	klhub_t	*hub ;
+
+	if (!brd)
+		return INVALID_NASID ;
+
+	/* find out if we are a completely disabled brd. */
+
+        hub  = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
+	if (!hub)
+                return INVALID_NASID ;
+	if (!(hub->hub_info.flags & KLINFO_ENABLE))	/* disabled node brd */
+		return hub->hub_info.physid ;
+	else
+		return brd->brd_nasid ;
+}
+
+int
+xbow_port_io_enabled(nasid_t nasid, int link)
+{
+	lboard_t *brd;
+	klxbow_t *xbow_p;
+
+	/*
+	 * look for boards that might contain an xbow or xbridge
+	 */
+	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW);
+	if (brd == NULL) return 0;
+		
+	if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW))
+	    == NULL)
+	    return 0;
+
+	if (!XBOW_PORT_TYPE_IO(xbow_p, link) || !XBOW_PORT_IS_ENABLED(xbow_p, link))
+	    return 0;
+
+	return 1;
+}
+
+void
+board_to_path(lboard_t *brd, char *path)
+{
+	moduleid_t modnum;
+	char *board_name;
+	char buffer[16];
+
+	ASSERT(brd);
+
+	switch (KLCLASS(brd->brd_type)) {
+
+		case KLCLASS_NODE:
+			board_name = EDGE_LBL_NODE;
+			break;
+		case KLCLASS_ROUTER:
+			if (brd->brd_type == KLTYPE_META_ROUTER) {
+				board_name = EDGE_LBL_META_ROUTER;
+				hasmetarouter++;
+			} else if (brd->brd_type == KLTYPE_REPEATER_ROUTER) {
+				board_name = EDGE_LBL_REPEATER_ROUTER;
+				hasmetarouter++;
+			} else
+				board_name = EDGE_LBL_ROUTER;
+			break;
+		case KLCLASS_MIDPLANE:
+			board_name = EDGE_LBL_MIDPLANE;
+			break;
+		case KLCLASS_IO:
+			board_name = EDGE_LBL_IO;
+			break;
+		case KLCLASS_IOBRICK:
+			if (brd->brd_type == KLTYPE_PBRICK)
+				board_name = EDGE_LBL_PBRICK;
+			else if (brd->brd_type == KLTYPE_IBRICK)
+				board_name = EDGE_LBL_IBRICK;
+			else if (brd->brd_type == KLTYPE_XBRICK)
+				board_name = EDGE_LBL_XBRICK;
+			else
+				board_name = EDGE_LBL_IOBRICK;
+			break;
+		default:
+			board_name = EDGE_LBL_UNKNOWN;
+	}
+			
+	modnum = geo_module(brd->brd_geoid);
+	memset(buffer, 0, 16);
+	format_module_id(buffer, modnum, MODULE_FORMAT_BRIEF);
+	sprintf(path, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d/%s", buffer, geo_slab(brd->brd_geoid), board_name);
+}
+
+/*
+ * Get the module number for a NASID.
+ */
+moduleid_t
+get_module_id(nasid_t nasid)
+{
+	lboard_t *brd;
+
+	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+
+	if (!brd)
+		return INVALID_MODULE;
+	else
+		return geo_module(brd->brd_geoid);
+}
+
+
+#define MHZ	1000000
+
+
+/* Get the canonical hardware graph name for the given pci component
+ * on the given io board.
+ */
+void
+device_component_canonical_name_get(lboard_t 	*brd,
+				    klinfo_t 	*component,
+				    char 	*name)
+{
+	slotid_t 	slot;
+	char 		board_name[20];
+
+	ASSERT(brd);
+
+	/* Convert the [ CLASS | TYPE ] kind of slotid
+	 * into a string
+	 */
+	slot = brd->brd_slot;
+
+	/* Get the io board name  */
+	if (!brd || (brd->brd_sversion < 2)) {
+		strcpy(name, EDGE_LBL_XWIDGET);
+	} else {
+		nic_name_convert(brd->brd_name, board_name);
+	}
+
+	/* Give out the canonical  name of the pci device*/
+	sprintf(name,
+		"/dev/hw/"EDGE_LBL_MODULE "/%x/"EDGE_LBL_SLAB"/%d/"
+		EDGE_LBL_SLOT"/%s/"EDGE_LBL_PCI"/%d",
+		geo_module(brd->brd_geoid), geo_slab(brd->brd_geoid), 
+		board_name, KLCF_BRIDGE_W_ID(component));
+}
+
+/*
+ * Get the serial number of the main  component of a board
+ * Returns 0 if a valid serial number is found
+ * 1 otherwise.
+ * Assumptions: Nic manufacturing string  has the following format
+ *			*Serial:<serial_number>;*
+ */
+static int
+component_serial_number_get(lboard_t 		*board,
+			    klconf_off_t 	mfg_nic_offset,
+			    char		*serial_number,
+			    char		*key_pattern)
+{
+
+	char	*mfg_nic_string;
+	char	*serial_string,*str;
+	int	i;
+	char	*serial_pattern = "Serial:";
+
+	/* We have an error on a null mfg nic offset */
+	if (!mfg_nic_offset)
+		return(1);
+	/* Get the hub's manufacturing nic information
+	 * which is in the form of a pre-formatted string
+	 */
+	mfg_nic_string = 
+		(char *)NODE_OFFSET_TO_K0(NASID_GET(board),
+					  mfg_nic_offset);
+	/* There is no manufacturing nic info */
+	if (!mfg_nic_string)
+		return(1);
+
+	str = mfg_nic_string;
+	/* Look for the key pattern first (if it is  specified)
+	 * and then print the serial number corresponding to that.
+	 */
+	if (strcmp(key_pattern,"") && 
+	    !(str = strstr(mfg_nic_string,key_pattern)))
+		return(1);
+
+	/* There is no serial number info in the manufacturing
+	 * nic info
+	 */
+	if (!(serial_string = strstr(str,serial_pattern)))
+		return(1);
+
+	serial_string = serial_string + strlen(serial_pattern);
+	/*  Copy the serial number information from the klconfig */
+	i = 0;
+	while (serial_string[i] != ';') {
+		serial_number[i] = serial_string[i];
+		i++;
+	}
+	serial_number[i] = 0;
+	
+	return(0);
+}
+/*
+ * Get the serial number of a board
+ * Returns 0 if a valid serial number is found
+ * 1 otherwise.
+ */
+
+int
+board_serial_number_get(lboard_t *board,char *serial_number)
+{
+	ASSERT(board && serial_number);
+	if (!board || !serial_number)
+		return(1);
+
+	strcpy(serial_number,"");
+	switch(KLCLASS(board->brd_type)) {
+	case KLCLASS_CPU: {	/* Node board */
+		klhub_t	*hub;
+		
+		/* Get the hub component information */
+		hub = (klhub_t *)find_first_component(board,
+						      KLSTRUCT_HUB);
+		/* If we don't have a hub component on an IP27
+		 * then we have a weird klconfig.
+		 */
+		if (!hub)
+			return(1);
+		/* Get the serial number information from
+		 * the hub's manufacturing nic info
+		 */
+		if (component_serial_number_get(board,
+						hub->hub_mfg_nic,
+						serial_number,
+						"IP37"))
+				return(1);
+		break;
+	}
+	case KLCLASS_IO: {	/* IO board */
+		if (KLTYPE(board->brd_type) == KLTYPE_TPU) {
+		/* Special case for TPU boards */
+			kltpu_t *tpu;	
+		
+			/* Get the tpu component information */
+			tpu = (kltpu_t *)find_first_component(board,
+						      KLSTRUCT_TPU);
+			/* If we don't have a tpu component on a tpu board
+			 * then we have a weird klconfig.
+			 */
+			if (!tpu)
+				return(1);
+			/* Get the serial number information from
+			 * the tpu's manufacturing nic info
+			 */
+			if (component_serial_number_get(board,
+						tpu->tpu_mfg_nic,
+						serial_number,
+						""))
+				return(1);
+			break;
+		} else  if ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ||
+		            (KLTYPE(board->brd_type) == KLTYPE_GSN_B)) {
+		/* Special case for GSN boards */
+			klgsn_t *gsn;	
+		
+			/* Get the gsn component information */
+			gsn = (klgsn_t *)find_first_component(board,
+			      ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ?
+					KLSTRUCT_GSN_A : KLSTRUCT_GSN_B));
+			/* If we don't have a gsn component on a gsn board
+			 * then we have a weird klconfig.
+			 */
+			if (!gsn)
+				return(1);
+			/* Get the serial number information from
+			 * the gsn's manufacturing nic info
+			 */
+			if (component_serial_number_get(board,
+						gsn->gsn_mfg_nic,
+						serial_number,
+						""))
+				return(1);
+			break;
+		} else {
+		     	klbri_t	*bridge;
+		
+			/* Get the bridge component information */
+			bridge = (klbri_t *)find_first_component(board,
+							 KLSTRUCT_BRI);
+			/* If we don't have a bridge component on an IO board
+			 * then we have a weird klconfig.
+			 */
+			if (!bridge)
+				return(1);
+			/* Get the serial number information from
+		 	 * the bridge's manufacturing nic info
+			 */
+			if (component_serial_number_get(board,
+						bridge->bri_mfg_nic,
+						serial_number,
+						""))
+				return(1);
+			break;
+		}
+	}
+	case KLCLASS_ROUTER: {	/* Router board */
+		klrou_t *router;	
+		
+		/* Get the router component information */
+		router = (klrou_t *)find_first_component(board,
+							 KLSTRUCT_ROU);
+		/* If we don't have a router component on a router board
+		 * then we have a weird klconfig.
+		 */
+		if (!router)
+			return(1);
+		/* Get the serial number information from
+		 * the router's manufacturing nic info
+		 */
+		if (component_serial_number_get(board,
+						router->rou_mfg_nic,
+						serial_number,
+						""))
+			return(1);
+		break;
+	}
+	case KLCLASS_GFX: {	/* Gfx board */
+		klgfx_t *graphics;
+		
+		/* Get the graphics component information */
+		graphics = (klgfx_t *)find_first_component(board, KLSTRUCT_GFX);
+		/* If we don't have a gfx component on a gfx board
+		 * then we have a weird klconfig.
+		 */
+		if (!graphics)
+			return(1);
+		/* Get the serial number information from
+		 * the graphics's manufacturing nic info
+		 */
+		if (component_serial_number_get(board,
+						graphics->gfx_mfg_nic,
+						serial_number,
+						""))
+			return(1);
+		break;
+	}
+	default:
+		strcpy(serial_number,"");
+		break;
+	}
+	return(0);
+}
+
+#include "asm/sn/sn_private.h"
+
+xwidgetnum_t
+nodevertex_widgetnum_get(devfs_handle_t node_vtx)
+{
+	hubinfo_t hubinfo_p;
+
+	hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO, 
+			     (arbitrary_info_t *) &hubinfo_p);
+	return(hubinfo_p->h_widgetid);
+}
+
+devfs_handle_t
+nodevertex_xbow_peer_get(devfs_handle_t node_vtx)
+{
+	hubinfo_t hubinfo_p;
+	nasid_t xbow_peer_nasid;
+	cnodeid_t xbow_peer;
+
+	hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO,
+				     (arbitrary_info_t *) &hubinfo_p);
+	xbow_peer_nasid = hubinfo_p->h_nodepda->xbow_peer;
+	if(xbow_peer_nasid == INVALID_NASID) 
+			return ( (devfs_handle_t)-1);
+	xbow_peer = NASID_TO_COMPACT_NODEID(xbow_peer_nasid);
+	return(NODEPDA(xbow_peer)->node_vertex);
+}
+
+/* NIC Sorting Support */
+
+#define MAX_NICS_PER_STRING 	32
+#define MAX_NIC_NAME_LEN	32
+
+static char *
+get_nic_string(lboard_t *lb)
+{
+        int         	i;
+        klinfo_t    	*k = NULL ;
+    	klconf_off_t    mfg_off = 0 ;
+    	char            *mfg_nic = NULL ;
+
+        for (i = 0; i < KLCF_NUM_COMPS(lb); i++) {
+                k = KLCF_COMP(lb, i) ;
+                switch(k->struct_type) {
+                        case KLSTRUCT_BRI:
+            			mfg_off = ((klbri_t *)k)->bri_mfg_nic ;
+				break ;
+
+                        case KLSTRUCT_HUB:
+            			mfg_off = ((klhub_t *)k)->hub_mfg_nic ;
+				break ;
+
+                        case KLSTRUCT_ROU:
+            			mfg_off = ((klrou_t *)k)->rou_mfg_nic ;
+				break ;
+
+                        case KLSTRUCT_GFX:
+            			mfg_off = ((klgfx_t *)k)->gfx_mfg_nic ;
+				break ;
+
+                        case KLSTRUCT_TPU:
+            			mfg_off = ((kltpu_t *)k)->tpu_mfg_nic ;
+				break ;
+
+                        case KLSTRUCT_GSN_A:
+                        case KLSTRUCT_GSN_B:
+            			mfg_off = ((klgsn_t *)k)->gsn_mfg_nic ;
+				break ;
+
+                        case KLSTRUCT_XTHD:
+                                mfg_off = ((klxthd_t *)k)->xthd_mfg_nic ;
+                                break;
+
+			default:
+				mfg_off = 0 ;
+                                break ;
+                }
+		if (mfg_off)
+			break ;
+        }
+
+	if ((mfg_off) && (k))
+		mfg_nic = (char *)NODE_OFFSET_TO_K0(k->nasid, mfg_off) ;
+
+        return mfg_nic ;
+}
+
+char *
+get_first_string(char **ptrs, int n)
+{
+        int     i ;
+        char    *tmpptr ;
+
+        if ((ptrs == NULL) || (n == 0))
+                return NULL ;
+
+        tmpptr = ptrs[0] ;
+
+        if (n == 1)
+                return tmpptr ;
+
+        for (i = 0 ; i < n ; i++) {
+                if (strcmp(tmpptr, ptrs[i]) > 0)
+                        tmpptr = ptrs[i] ;
+        }
+
+        return tmpptr ;
+}
+
+int
+get_ptrs(char *idata, char **ptrs, int n, char *label)
+{
+        int     i = 0 ;
+        char    *tmp = idata ;
+
+        if ((ptrs == NULL) || (idata == NULL) || (label == NULL) || (n == 0))
+                return 0 ;
+
+        while  ( (tmp = strstr(tmp, label)) ){
+                tmp += strlen(label) ;
+                /* check for empty name field, and last NULL ptr */
+                if ((i < (n-1)) && (*tmp != ';')) {
+                        ptrs[i++] = tmp ;
+                }
+        }
+
+        ptrs[i] = NULL ;
+
+        return i ;
+}
+
+/*
+ * sort_nic_names
+ *
+ * 	Does not really do sorting. Find the alphabetically lowest
+ *	name among all the nic names found in a nic string.
+ *
+ * Return:
+ *	Nothing
+ *
+ * Side Effects:
+ *
+ *	lb->brd_name gets the new name found
+ */
+
+static void
+sort_nic_names(lboard_t *lb)
+{
+	char 	*nic_str ;
+        char    *ptrs[MAX_NICS_PER_STRING] ;
+        char    name[MAX_NIC_NAME_LEN] ;
+        char    *tmp, *tmp1 ;
+
+	*name = 0 ;
+
+	/* Get the nic pointer from the lb */
+
+	if ((nic_str = get_nic_string(lb)) == NULL)
+		return ;
+
+        tmp = get_first_string(ptrs,
+                        get_ptrs(nic_str, ptrs, MAX_NICS_PER_STRING, "Name:")) ;
+
+        if (tmp == NULL)
+		return ;
+
+        if  ( (tmp1 = strchr(tmp, ';')) ){
+                strncpy(name, tmp, tmp1-tmp) ;
+                name[tmp1-tmp] = 0 ;
+        } else {
+                strncpy(name, tmp, (sizeof(name) -1)) ;
+                name[sizeof(name)-1] = 0 ;
+        }
+
+	strcpy(lb->brd_name, name) ;
+}
+
+
+
+char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#012345";
+
+/*
+ * Format a module id for printing.
+ */
+void
+format_module_id(char *buffer, moduleid_t m, int fmt)
+{
+	int rack, position;
+	char brickchar;
+
+	rack = MODULE_GET_RACK(m);
+	ASSERT(MODULE_GET_BTYPE(m) < MAX_BRICK_TYPES);
+	brickchar = MODULE_GET_BTCHAR(m);
+	position = MODULE_GET_BPOS(m);
+
+	if (fmt == MODULE_FORMAT_BRIEF) {
+	    /* Brief module number format, eg. 002c15 */
+
+	    /* Decompress the rack number */
+	    *buffer++ = '0' + RACK_GET_CLASS(rack);
+	    *buffer++ = '0' + RACK_GET_GROUP(rack);
+	    *buffer++ = '0' + RACK_GET_NUM(rack);
+
+	    /* Add the brick type */
+	    *buffer++ = brickchar;
+	}
+	else if (fmt == MODULE_FORMAT_LONG) {
+	    /* Fuller hwgraph format, eg. rack/002/bay/15 */
+
+	    strcpy(buffer, EDGE_LBL_RACK "/");  buffer += strlen(buffer);
+
+	    *buffer++ = '0' + RACK_GET_CLASS(rack);
+	    *buffer++ = '0' + RACK_GET_GROUP(rack);
+	    *buffer++ = '0' + RACK_GET_NUM(rack);
+
+	    strcpy(buffer, "/" EDGE_LBL_RPOS "/");  buffer += strlen(buffer);
+	}
+
+	/* Add the bay position, using at least two digits */
+	if (position < 10)
+	    *buffer++ = '0';
+	sprintf(buffer, "%d", position);
+
+}
+
+/*
+ * Parse a module id, in either brief or long form.
+ * Returns < 0 on error.
+ * The long form does not include a brick type, so it defaults to 0 (CBrick)
+ */
+int
+parse_module_id(char *buffer)
+{
+	unsigned int	v, rack, bay, type, form;
+	moduleid_t	m;
+	char 		c;
+
+	if (strstr(buffer, EDGE_LBL_RACK "/") == buffer) {
+		form = MODULE_FORMAT_LONG;
+		buffer += strlen(EDGE_LBL_RACK "/");
+
+		/* A long module ID must be exactly 5 non-template chars. */
+		if (strlen(buffer) != strlen("/" EDGE_LBL_RPOS "/") + 5)
+			return -1;
+	}
+	else {
+		form = MODULE_FORMAT_BRIEF;
+
+		/* A brief module id must be exactly 6 characters */
+		if (strlen(buffer) != 6)
+			return -2;
+	}
+
+	/* The rack number must be exactly 3 digits */
+	if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && isdigit(buffer[2])))
+		return -3;
+
+	rack = 0;
+	v = *buffer++ - '0';
+	if (v > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack))
+		return -4;
+	RACK_ADD_CLASS(rack, v);
+
+	v = *buffer++ - '0';
+	if (v > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack))
+		return -5;
+	RACK_ADD_GROUP(rack, v);
+
+	v = *buffer++ - '0';
+	/* rack numbers are 1-based */
+	if (v-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack))
+		return -6;
+	RACK_ADD_NUM(rack, v);
+
+	if (form == MODULE_FORMAT_BRIEF) {
+		/* Next should be a module type character.  Accept ucase or lcase. */
+		c = *buffer++;
+		if (!isalpha(c))
+			return -7;
+
+		/* strchr() returns a pointer into brick_types[], or NULL */
+		type = (unsigned int)(strchr(brick_types, tolower(c)) - brick_types);
+		if (type > MODULE_BTYPE_MASK >> MODULE_BTYPE_SHFT)
+			return -8;
+	}
+	else {
+		/* Hardcode the module type, and skip over the boilerplate */
+		type = MODULE_CBRICK;
+
+		if (strstr(buffer, "/" EDGE_LBL_RPOS "/") != buffer)
+			return -9;
+
+		buffer += strlen("/" EDGE_LBL_RPOS "/");
+	}
+		
+	/* The bay number is last.  Make sure it's exactly two digits */
+
+	if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && !buffer[2]))
+		return -10;
+
+	bay = 10 * (buffer[0] - '0') + (buffer[1] - '0');
+
+	if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT)
+		return -11;
+
+	m = RBT_TO_MODULE(rack, bay, type);
+
+	/* avoid sign extending the moduleid_t */
+	return (int)(unsigned short)m;
+}
diff -Nru a/arch/ia64/sn/io/sn2/klgraph.c b/arch/ia64/sn/io/sn2/klgraph.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/klgraph.c	Mon Feb 24 05:24:10 2003
@@ -0,0 +1,866 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+/*
+ * klgraph.c-
+ *      This file specifies the interface between the kernel and the PROM's
+ *      configuration data structures.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/io.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/kldir.h>
+#include <asm/sn/gda.h> 
+#include <asm/sn/klconfig.h>
+#include <asm/sn/router.h>
+#include <asm/sn/xtalk/xbow.h>
+#include <asm/sn/hcl_util.h>
+
+// #define KLGRAPH_DEBUG 1
+#ifdef KLGRAPH_DEBUG
+#define GRPRINTF(x)	printk x
+#define CE_GRPANIC	CE_PANIC
+#else
+#define GRPRINTF(x)
+#define CE_GRPANIC	CE_PANIC
+#endif
+
+#include <asm/sn/sn_private.h>
+
+extern char arg_maxnodes[];
+extern u64 klgraph_addr[];
+void mark_cpuvertex_as_cpu(devfs_handle_t vhdl, cpuid_t cpuid);
+
+
+/*
+ * Support for verbose inventory via hardware graph. 
+ * klhwg_invent_alloc allocates the necessary size of inventory information
+ * and fills in the generic information.
+ */
+invent_generic_t *
+klhwg_invent_alloc(cnodeid_t cnode, int class, int size)
+{
+	invent_generic_t *invent;
+
+	invent = kern_malloc(size);
+	if (!invent) return NULL;
+	
+	invent->ig_module = NODE_MODULEID(cnode);
+	invent->ig_slot = SLOTNUM_GETSLOT(NODE_SLOTID(cnode));
+	invent->ig_invclass = class;
+
+	return invent;
+}
+
+/*
+ * Add detailed disabled cpu inventory info to the hardware graph.
+ */
+void
+klhwg_disabled_cpu_invent_info(devfs_handle_t cpuv,
+                               cnodeid_t cnode,
+                               klcpu_t *cpu, slotid_t slot)
+{
+	invent_cpuinfo_t *cpu_invent;
+	diag_inv_t       *diag_invent;
+
+	cpu_invent = (invent_cpuinfo_t *)
+	klhwg_invent_alloc(cnode, INV_PROCESSOR, sizeof(invent_cpuinfo_t));
+	if (!cpu_invent)
+		return;
+
+	/* Diag information on this processor */
+	diag_invent = (diag_inv_t *)
+	klhwg_invent_alloc(cnode, INV_CPUDIAGVAL, sizeof(diag_inv_t));
+
+	if (!diag_invent)
+		return;
+
+
+	/* Disabled CPU */
+	cpu_invent->ic_gen.ig_flag = 0x0;
+	cpu_invent->ic_gen.ig_slot = slot;
+	cpu_invent->ic_cpu_info.cpuflavor = cpu->cpu_prid;
+	cpu_invent->ic_cpu_info.cpufq = cpu->cpu_speed;
+	cpu_invent->ic_cpu_info.sdfreq = cpu->cpu_scachespeed;
+
+	cpu_invent->ic_cpu_info.sdsize = cpu->cpu_scachesz;
+	cpu_invent->ic_cpuid = cpu->cpu_info.virtid;
+	cpu_invent->ic_slice = cpu->cpu_info.physid;
+
+	/* Disabled CPU label */
+	hwgraph_info_add_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
+			(arbitrary_info_t) cpu_invent);
+	hwgraph_info_export_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
+			sizeof(invent_cpuinfo_t));
+
+	/* Diagval label - stores reason for disable +{virt,phys}id +diagval*/
+	hwgraph_info_add_LBL(cpuv, INFO_LBL_DIAGVAL,
+			(arbitrary_info_t) diag_invent);
+
+	hwgraph_info_export_LBL(cpuv, INFO_LBL_DIAGVAL,
+			sizeof(diag_inv_t));
+}
+
+/*
+ * Add detailed cpu inventory info to the hardware graph.
+ */
+void
+klhwg_cpu_invent_info(devfs_handle_t cpuv,
+			cnodeid_t cnode,
+			klcpu_t *cpu)
+{
+	invent_cpuinfo_t *cpu_invent;
+
+	cpu_invent = (invent_cpuinfo_t *)
+		klhwg_invent_alloc(cnode, INV_PROCESSOR, sizeof(invent_cpuinfo_t));
+	if (!cpu_invent)
+		return;
+
+	if (KLCONFIG_INFO_ENABLED((klinfo_t *)cpu))
+		cpu_invent->ic_gen.ig_flag = INVENT_ENABLED;
+	else
+		cpu_invent->ic_gen.ig_flag = 0x0;
+
+	cpu_invent->ic_cpu_info.cpuflavor = cpu->cpu_prid;
+	cpu_invent->ic_cpu_info.cpufq = cpu->cpu_speed;
+	cpu_invent->ic_cpu_info.sdfreq = cpu->cpu_scachespeed;
+
+	cpu_invent->ic_cpu_info.sdsize = cpu->cpu_scachesz;
+	cpu_invent->ic_cpuid = cpu->cpu_info.virtid;
+	cpu_invent->ic_slice = cpu_physical_id_to_slice(cpu->cpu_info.virtid);
+
+	hwgraph_info_add_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
+			(arbitrary_info_t) cpu_invent);
+	hwgraph_info_export_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
+			sizeof(invent_cpuinfo_t));
+}
+
+/* 
+ * Add information about the baseio prom version number
+ * as a part of detailed inventory info in the hwgraph.
+ */
+void
+klhwg_baseio_inventory_add(devfs_handle_t baseio_vhdl,cnodeid_t cnode)
+{
+	invent_miscinfo_t	*baseio_inventory;
+	unsigned char		version = 0,revision = 0;
+
+	/* Allocate memory for the "detailed inventory" info
+	 * for the baseio
+	 */
+	baseio_inventory = (invent_miscinfo_t *) 
+		klhwg_invent_alloc(cnode, INV_PROM, sizeof(invent_miscinfo_t));
+	baseio_inventory->im_type = INV_IO6PROM;
+	/* Store the revision info  in the inventory */
+	baseio_inventory->im_version = version;
+	baseio_inventory->im_rev = revision;
+	/* Put the inventory info in the hardware graph */
+	hwgraph_info_add_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT, 
+			     (arbitrary_info_t) baseio_inventory);
+	/* Make the information available to the user programs
+	 * thru hwgfs.
+	 */
+        hwgraph_info_export_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT,
+				sizeof(invent_miscinfo_t));
+}
+
+char	*hub_rev[] = {
+	"0.0",
+	"1.0",
+	"2.0",
+	"2.1",
+	"2.2",
+	"2.3"
+};
+
+/*
+ * Add detailed cpu inventory info to the hardware graph.
+ */
+void
+klhwg_hub_invent_info(devfs_handle_t hubv,
+		      cnodeid_t cnode, 
+		      klhub_t *hub)
+{
+	invent_miscinfo_t *hub_invent;
+
+	hub_invent = (invent_miscinfo_t *) 
+	    klhwg_invent_alloc(cnode, INV_MISC, sizeof(invent_miscinfo_t));
+	if (!hub_invent)
+	    return;
+
+	if (KLCONFIG_INFO_ENABLED((klinfo_t *)hub))
+	    hub_invent->im_gen.ig_flag = INVENT_ENABLED;
+
+	hub_invent->im_type = INV_HUB;
+	hub_invent->im_rev = hub->hub_info.revision;
+	hub_invent->im_speed = hub->hub_speed;
+	hwgraph_info_add_LBL(hubv, INFO_LBL_DETAIL_INVENT, 
+			     (arbitrary_info_t) hub_invent);
+        hwgraph_info_export_LBL(hubv, INFO_LBL_DETAIL_INVENT,
+				sizeof(invent_miscinfo_t));
+}
+
+/* ARGSUSED */
+void
+klhwg_add_hub(devfs_handle_t node_vertex, klhub_t *hub, cnodeid_t cnode)
+{
+	devfs_handle_t myhubv;
+	devfs_handle_t hub_mon;
+	int rc;
+	extern struct file_operations shub_mon_fops;
+
+	GRPRINTF(("klhwg_add_hub: adding %s\n", EDGE_LBL_HUB));
+	(void) hwgraph_path_add(node_vertex, EDGE_LBL_HUB, &myhubv);
+	rc = device_master_set(myhubv, node_vertex);
+	hub_mon = hwgraph_register(myhubv, EDGE_LBL_PERFMON,
+		0, DEVFS_FL_AUTO_DEVNUM,
+		0, 0,
+		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
+		&shub_mon_fops, (void *)(long)cnode);
+}
+
+/* ARGSUSED */
+void
+klhwg_add_disabled_cpu(devfs_handle_t node_vertex, cnodeid_t cnode, klcpu_t *cpu, slotid_t slot)
+{
+        devfs_handle_t my_cpu;
+        char name[120];
+        cpuid_t cpu_id;
+	nasid_t nasid;
+
+	nasid = COMPACT_TO_NASID_NODEID(cnode);
+        cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid);
+        if(cpu_id != -1){
+		sprintf(name, "%s/%s/%c", EDGE_LBL_DISABLED, EDGE_LBL_CPU, 'a' + cpu->cpu_info.physid);
+		(void) hwgraph_path_add(node_vertex, name, &my_cpu);
+
+		mark_cpuvertex_as_cpu(my_cpu, cpu_id);
+		device_master_set(my_cpu, node_vertex);
+
+		klhwg_disabled_cpu_invent_info(my_cpu, cnode, cpu, slot);
+		return;
+        }
+}
+
+/* ARGSUSED */
+void
+klhwg_add_cpu(devfs_handle_t node_vertex, cnodeid_t cnode, klcpu_t *cpu)
+{
+        devfs_handle_t my_cpu, cpu_dir;
+        char name[120];
+        cpuid_t cpu_id;
+	nasid_t nasid;
+
+	nasid = COMPACT_TO_NASID_NODEID(cnode);
+        cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid);
+
+        sprintf(name, "%s/%d/%c",
+                EDGE_LBL_CPUBUS,
+                0,
+                'a' + cpu->cpu_info.physid);
+
+        GRPRINTF(("klhwg_add_cpu: adding %s to vertex 0x%p\n", name, node_vertex));
+        (void) hwgraph_path_add(node_vertex, name, &my_cpu);
+        mark_cpuvertex_as_cpu(my_cpu, cpu_id);
+        device_master_set(my_cpu, node_vertex);
+
+        /* Add an alias under the node's CPU directory */
+        if (hwgraph_edge_get(node_vertex, EDGE_LBL_CPU, &cpu_dir) == GRAPH_SUCCESS) {
+                sprintf(name, "%c", 'a' + cpu->cpu_info.physid);
+                (void) hwgraph_edge_add(cpu_dir, my_cpu, name);
+        }
+
+        klhwg_cpu_invent_info(my_cpu, cnode, cpu);
+}
+
+
+void
+klhwg_add_xbow(cnodeid_t cnode, nasid_t nasid)
+{
+	lboard_t *brd;
+	klxbow_t *xbow_p;
+	nasid_t hub_nasid;
+	cnodeid_t hub_cnode;
+	int widgetnum;
+	devfs_handle_t xbow_v, hubv;
+	/*REFERENCED*/
+	graph_error_t err;
+
+	if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW)) == NULL)
+			return;
+
+	if (KL_CONFIG_DUPLICATE_BOARD(brd))
+	    return;
+
+	GRPRINTF(("klhwg_add_xbow: adding cnode %d nasid %d xbow edges\n",
+			cnode, nasid));
+
+	if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW))
+	    == NULL)
+	    return;
+
+	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
+		if (!XBOW_PORT_TYPE_HUB(xbow_p, widgetnum)) 
+		    continue;
+
+		hub_nasid = XBOW_PORT_NASID(xbow_p, widgetnum);
+		if (hub_nasid == INVALID_NASID) {
+			printk(KERN_WARNING  "hub widget %d, skipping xbow graph\n", widgetnum);
+			continue;
+		}
+
+		hub_cnode = NASID_TO_COMPACT_NODEID(hub_nasid);
+
+		if (is_specified(arg_maxnodes) && hub_cnode == INVALID_CNODEID) {
+			continue;
+		}
+			
+		hubv = cnodeid_to_vertex(hub_cnode);
+
+		err = hwgraph_path_add(hubv, EDGE_LBL_XTALK, &xbow_v);
+                if (err != GRAPH_SUCCESS) {
+                        if (err == GRAPH_DUP)
+                                printk(KERN_WARNING  "klhwg_add_xbow: Check for "
+                                        "working routers and router links!");
+
+                        PRINT_PANIC("klhwg_add_xbow: Failed to add "
+                                "edge: vertex 0x%p to vertex 0x%p,"
+                                "error %d\n",
+                                (void *)hubv, (void *)xbow_v, err);
+                }
+		xswitch_vertex_init(xbow_v); 
+
+		NODEPDA(hub_cnode)->xbow_vhdl = xbow_v;
+
+		/*
+		 * XXX - This won't work is we ever hook up two hubs
+		 * by crosstown through a crossbow.
+		 */
+		if (hub_nasid != nasid) {
+			NODEPDA(hub_cnode)->xbow_peer = nasid;
+			NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->xbow_peer =
+				hub_nasid;
+		}
+
+		GRPRINTF(("klhwg_add_xbow: adding port nasid %d %s to vertex 0x%p\n",
+			hub_nasid, EDGE_LBL_XTALK, hubv));
+	}
+}
+
+
+/* ARGSUSED */
+void
+klhwg_add_node(devfs_handle_t hwgraph_root, cnodeid_t cnode, gda_t *gdap)
+{
+	nasid_t nasid;
+	lboard_t *brd;
+	klhub_t *hub;
+	devfs_handle_t node_vertex = NULL;
+	char path_buffer[100];
+	int rv;
+	char *s;
+	int board_disabled = 0;
+	klcpu_t *cpu;
+
+	nasid = COMPACT_TO_NASID_NODEID(cnode);
+	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+	GRPRINTF(("klhwg_add_node: Adding cnode %d, nasid %d, brd 0x%p\n",
+                cnode, nasid, brd));
+	ASSERT(brd);
+
+	do {
+		devfs_handle_t cpu_dir;
+
+		/* Generate a hardware graph path for this board. */
+		board_to_path(brd, path_buffer);
+
+		GRPRINTF(("klhwg_add_node: adding %s to vertex 0x%p\n",
+			path_buffer, hwgraph_root));
+		rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
+
+		if (rv != GRAPH_SUCCESS)
+			PRINT_PANIC("Node vertex creation failed.  "
+					  "Path == %s",
+				path_buffer);
+
+		hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
+		ASSERT(hub);
+		if(hub->hub_info.flags & KLINFO_ENABLE)
+			board_disabled = 0;
+		else
+			board_disabled = 1;
+		
+		if(!board_disabled) {
+			mark_nodevertex_as_node(node_vertex,
+					    cnode + board_disabled * numnodes);
+
+			s = dev_to_name(node_vertex, path_buffer, sizeof(path_buffer));
+			NODEPDA(cnode)->hwg_node_name =
+						kmalloc(strlen(s) + 1,
+						GFP_KERNEL);
+			ASSERT_ALWAYS(NODEPDA(cnode)->hwg_node_name != NULL);
+			strcpy(NODEPDA(cnode)->hwg_node_name, s);
+
+			hubinfo_set(node_vertex, NODEPDA(cnode)->pdinfo);
+
+			/* Set up node board's slot */
+			NODEPDA(cnode)->slotdesc = brd->brd_slot;
+
+			/* Set up the module we're in */
+			NODEPDA(cnode)->geoid = brd->brd_geoid;
+			NODEPDA(cnode)->module = module_lookup(geo_module(brd->brd_geoid));
+		}
+
+		/* Get the first CPU structure */
+		cpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
+
+		/*
+		* If there's at least 1 CPU, add a "cpu" directory to represent
+		* the collection of all CPUs attached to this node.
+		*/
+		if (cpu) {
+			graph_error_t rv;
+
+			rv = hwgraph_path_add(node_vertex, EDGE_LBL_CPU, &cpu_dir);
+			if (rv != GRAPH_SUCCESS)
+				panic("klhwg_add_node: Cannot create CPU directory\n");
+		}
+
+		/* Add each CPU */
+		while (cpu) {
+			cpuid_t cpu_id;
+			cpu_id = nasid_slice_to_cpuid(nasid,cpu->cpu_info.physid);
+			if (cpu_enabled(cpu_id))
+				klhwg_add_cpu(node_vertex, cnode, cpu);
+			else
+				klhwg_add_disabled_cpu(node_vertex, cnode, cpu, brd->brd_slot);
+
+			cpu = (klcpu_t *)
+				find_component(brd, (klinfo_t *)cpu, KLSTRUCT_CPU);
+		} /* while */
+
+		if(!board_disabled)
+			klhwg_add_hub(node_vertex, hub, cnode);
+		
+		brd = KLCF_NEXT(brd);
+		if (brd)
+			brd = find_lboard(brd, KLTYPE_SNIA);
+		else
+			break;
+	} while(brd);
+}
+
+
+/* ARGSUSED */
+void
+klhwg_add_all_routers(devfs_handle_t hwgraph_root)
+{
+	nasid_t nasid;
+	cnodeid_t cnode;
+	lboard_t *brd;
+	devfs_handle_t node_vertex;
+	char path_buffer[100];
+	int rv;
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+		GRPRINTF(("klhwg_add_all_routers: adding router on cnode %d\n",
+			cnode));
+
+		brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
+				KLTYPE_ROUTER);
+
+		if (!brd)
+			/* No routers stored in this node's memory */
+			continue;
+
+		do {
+			ASSERT(brd);
+			GRPRINTF(("Router board struct is %p\n", brd));
+
+			/* Don't add duplicate boards. */
+			if (brd->brd_flags & DUPLICATE_BOARD)
+				continue;
+
+			GRPRINTF(("Router 0x%p module number is %d\n", brd, brd->brd_geoid));
+			/* Generate a hardware graph path for this board. */
+			board_to_path(brd, path_buffer);
+
+			GRPRINTF(("Router path is %s\n", path_buffer));
+
+			/* Add the router */
+			GRPRINTF(("klhwg_add_all_routers: adding %s to vertex 0x%p\n",
+				path_buffer, hwgraph_root));
+			rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
+
+			if (rv != GRAPH_SUCCESS)
+				PRINT_PANIC("Router vertex creation "
+						  "failed.  Path == %s",
+					path_buffer);
+
+			GRPRINTF(("klhwg_add_all_routers: get next board from 0x%p\n",
+					brd));
+		/* Find the rest of the routers stored on this node. */
+		} while ( (brd = find_lboard_class(KLCF_NEXT(brd),
+			 KLTYPE_ROUTER)) );
+
+		GRPRINTF(("klhwg_add_all_routers: Done.\n"));
+	}
+
+}
+
+/* ARGSUSED */
+void
+klhwg_connect_one_router(devfs_handle_t hwgraph_root, lboard_t *brd,
+			 cnodeid_t cnode, nasid_t nasid)
+{
+	klrou_t *router;
+	char path_buffer[50];
+	char dest_path[50];
+	devfs_handle_t router_hndl;
+	devfs_handle_t dest_hndl;
+	int rc;
+	int port;
+	lboard_t *dest_brd;
+
+	GRPRINTF(("klhwg_connect_one_router: Connecting router on cnode %d\n",
+			cnode));
+
+	/* Don't add duplicate boards. */
+	if (brd->brd_flags & DUPLICATE_BOARD) {
+		GRPRINTF(("klhwg_connect_one_router: Duplicate router 0x%p on cnode %d\n",
+			brd, cnode));
+		return;
+	}
+
+	/* Generate a hardware graph path for this board. */
+	board_to_path(brd, path_buffer);
+
+	rc = hwgraph_traverse(hwgraph_root, path_buffer, &router_hndl);
+
+	if (rc != GRAPH_SUCCESS && is_specified(arg_maxnodes))
+			return;
+
+	if (rc != GRAPH_SUCCESS)
+		printk(KERN_WARNING  "Can't find router: %s", path_buffer);
+
+	/* We don't know what to do with multiple router components */
+	if (brd->brd_numcompts != 1) {
+		PRINT_PANIC("klhwg_connect_one_router: %d cmpts on router\n",
+			brd->brd_numcompts);
+		return;
+	}
+
+
+	/* Convert component 0 to klrou_t ptr */
+	router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd),
+					      brd->brd_compts[0]);
+
+	for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
+		/* See if the port's active */
+		if (router->rou_port[port].port_nasid == INVALID_NASID) {
+			GRPRINTF(("klhwg_connect_one_router: port %d inactive.\n",
+				 port));
+			continue;
+		}
+		if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(router->rou_port[port].port_nasid) 
+		    == INVALID_CNODEID) {
+			continue;
+		}
+
+		dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
+				router->rou_port[port].port_nasid,
+				router->rou_port[port].port_offset);
+
+		/* Generate a hardware graph path for this board. */
+		board_to_path(dest_brd, dest_path);
+
+		rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl);
+
+		if (rc != GRAPH_SUCCESS) {
+			if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd))
+				continue;
+			PRINT_PANIC("Can't find router: %s", dest_path);
+		}
+		GRPRINTF(("klhwg_connect_one_router: Link from %s/%d to %s\n",
+			  path_buffer, port, dest_path));
+
+		sprintf(dest_path, "%d", port);
+
+		rc = hwgraph_edge_add(router_hndl, dest_hndl, dest_path);
+
+		if (rc == GRAPH_DUP) {
+			GRPRINTF(("Skipping port %d. nasid %d %s/%s\n",
+				  port, router->rou_port[port].port_nasid,
+				  path_buffer, dest_path));
+			continue;
+		}
+
+		if (rc != GRAPH_SUCCESS && !is_specified(arg_maxnodes))
+			PRINT_PANIC("Can't create edge: %s/%s to vertex 0x%p error 0x%x\n",
+				path_buffer, dest_path, (void *)dest_hndl, rc);
+		
+	}
+}
+
+
+void
+klhwg_connect_routers(devfs_handle_t hwgraph_root)
+{
+	nasid_t nasid;
+	cnodeid_t cnode;
+	lboard_t *brd;
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+		GRPRINTF(("klhwg_connect_routers: Connecting routers on cnode %d\n",
+			cnode));
+
+		brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
+				KLTYPE_ROUTER);
+
+		if (!brd)
+			continue;
+
+		do {
+
+			nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+			klhwg_connect_one_router(hwgraph_root, brd,
+						 cnode, nasid);
+
+		/* Find the rest of the routers stored on this node. */
+		} while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) );
+	}
+}
+
+
+
+void
+klhwg_connect_hubs(devfs_handle_t hwgraph_root)
+{
+	nasid_t nasid;
+	cnodeid_t cnode;
+	lboard_t *brd;
+	klhub_t *hub;
+	lboard_t *dest_brd;
+	devfs_handle_t hub_hndl;
+	devfs_handle_t dest_hndl;
+	char path_buffer[50];
+	char dest_path[50];
+	graph_error_t rc;
+	int port;
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+		GRPRINTF(("klhwg_connect_hubs: Connecting hubs on cnode %d\n",
+			cnode));
+
+		brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+		ASSERT(brd);
+
+		hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
+		ASSERT(hub);
+
+		for (port = 1; port <= MAX_NI_PORTS; port++) {
+			/* See if the port's active */
+			if (hub->hub_port[port].port_nasid == INVALID_NASID) {
+				GRPRINTF(("klhwg_connect_hubs: port inactive.\n"));
+				continue;
+			}
+
+			if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(hub->hub_port[port].port_nasid) == INVALID_CNODEID)
+				continue;
+
+			/* Generate a hardware graph path for this board. */
+			board_to_path(brd, path_buffer);
+
+			GRPRINTF(("klhwg_connect_hubs: Hub path is %s.\n", path_buffer));
+			rc = hwgraph_traverse(hwgraph_root, path_buffer, &hub_hndl);
+
+			if (rc != GRAPH_SUCCESS)
+				printk(KERN_WARNING  "Can't find hub: %s", path_buffer);
+
+			dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
+					hub->hub_port[port].port_nasid,
+					hub->hub_port[port].port_offset);
+
+			/* Generate a hardware graph path for this board. */
+			board_to_path(dest_brd, dest_path);
+
+			rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl);
+
+			if (rc != GRAPH_SUCCESS) {
+				if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd))
+					continue;
+				PRINT_PANIC("Can't find board: %s", dest_path);
+			} else {
+				char buf[1024];
+		
+
+				GRPRINTF(("klhwg_connect_hubs: Link from %s to %s.\n",
+			  	path_buffer, dest_path));
+
+				rc = hwgraph_path_add(hub_hndl, EDGE_LBL_INTERCONNECT, &hub_hndl);
+				sprintf(buf,"%s/%s",path_buffer,EDGE_LBL_INTERCONNECT);
+				rc = hwgraph_traverse(hwgraph_root, buf, &hub_hndl);
+				sprintf(buf,"%d",port);
+				rc = hwgraph_edge_add(hub_hndl, dest_hndl, buf);
+
+				if (rc != GRAPH_SUCCESS)
+					PRINT_PANIC("Can't create edge: %s/%s to vertex 0x%p, error 0x%x\n",
+					path_buffer, dest_path, (void *)dest_hndl, rc);
+
+			}
+		}
+	}
+}
+
+/* Store the pci/vme disabled board information as extended administrative
+ * hints which can later be used by the drivers using the device/driver
+ * admin interface. 
+ */
+void
+klhwg_device_disable_hints_add(void)
+{
+	cnodeid_t	cnode; 		/* node we are looking at */
+	nasid_t		nasid;		/* nasid of the node */
+	lboard_t	*board;		/* board we are looking at */
+	int		comp_index;	/* component index */
+	klinfo_t	*component;	/* component in the board we are
+					 * looking at 
+					 */
+	char		device_name[MAXDEVNAME];
+	
+	for(cnode = 0; cnode < numnodes; cnode++) {
+		nasid = COMPACT_TO_NASID_NODEID(cnode);
+		board = (lboard_t *)KL_CONFIG_INFO(nasid);
+		/* Check out all the board info stored  on a node */
+		while(board) {
+			/* No need to look at duplicate boards or non-io 
+			 * boards
+			 */
+			if (KL_CONFIG_DUPLICATE_BOARD(board) ||
+			    KLCLASS(board->brd_type) != KLCLASS_IO) {
+				board = KLCF_NEXT(board);
+				continue;
+			}
+			/* Check out all the components of a board */
+			for (comp_index = 0; 
+			     comp_index < KLCF_NUM_COMPS(board);
+			     comp_index++) {
+				component = KLCF_COMP(board,comp_index);
+				/* If the component is enabled move on to
+				 * the next component
+				 */
+				if (KLCONFIG_INFO_ENABLED(component))
+					continue;
+				/* NOTE : Since the prom only supports
+				 * the disabling of pci devices the following
+				 * piece of code makes sense. 
+				 * Make sure that this assumption is valid
+				 */
+				/* This component is disabled. Store this
+				 * hint in the extended device admin table
+				 */
+				/* Get the canonical name of the pci device */
+				device_component_canonical_name_get(board,
+							    component,
+							    device_name);
+#ifdef DEBUG
+				printf("%s DISABLED\n",device_name);
+#endif				
+			}
+			/* go to the next board info stored on this 
+			 * node 
+			 */
+			board = KLCF_NEXT(board);
+		}
+	}
+}
+
+void
+klhwg_add_all_modules(devfs_handle_t hwgraph_root)
+{
+	cmoduleid_t	cm;
+	char		name[128];
+	devfs_handle_t	vhdl;
+	devfs_handle_t  module_vhdl;
+	int		rc;
+	char		buffer[16];
+
+	/* Add devices under each module */
+
+	for (cm = 0; cm < nummodules; cm++) {
+		/* Use module as module vertex fastinfo */
+
+		memset(buffer, 0, 16);
+		format_module_id(buffer, modules[cm]->id, MODULE_FORMAT_BRIEF);
+		sprintf(name, EDGE_LBL_MODULE "/%s", buffer);
+
+		rc = hwgraph_path_add(hwgraph_root, name, &module_vhdl);
+		ASSERT(rc == GRAPH_SUCCESS);
+		rc = rc;
+
+		hwgraph_fastinfo_set(module_vhdl, (arbitrary_info_t) modules[cm]);
+
+		/* Add system controller */
+		sprintf(name,
+			EDGE_LBL_MODULE "/%s/" EDGE_LBL_L1,
+			buffer);
+
+		rc = hwgraph_path_add(hwgraph_root, name, &vhdl);
+		ASSERT_ALWAYS(rc == GRAPH_SUCCESS); 
+		rc = rc;
+
+		hwgraph_info_add_LBL(vhdl,
+				     INFO_LBL_ELSC,
+				     (arbitrary_info_t) (__psint_t) 1);
+
+	}
+}
+
+void
+klhwg_add_all_nodes(devfs_handle_t hwgraph_root)
+{
+	cnodeid_t	cnode;
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		klhwg_add_node(hwgraph_root, cnode, NULL);
+	}
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		klhwg_add_xbow(cnode, cnodeid_to_nasid(cnode));
+	}
+
+	/*
+	 * As for router hardware inventory information, we set this
+	 * up in router.c. 
+	 */
+	
+	klhwg_add_all_routers(hwgraph_root);
+	klhwg_connect_routers(hwgraph_root);
+	klhwg_connect_hubs(hwgraph_root);
+
+	/* Go through the entire system's klconfig
+	 * to figure out which pci components have been disabled
+	 */
+	klhwg_device_disable_hints_add();
+
+}
diff -Nru a/arch/ia64/sn/io/sn2/l1.c b/arch/ia64/sn/io/sn2/l1.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/l1.c	Mon Feb 24 05:24:28 2003
@@ -0,0 +1,244 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc.  All rights reserved.
+ */
+
+/* In general, this file is organized in a hierarchy from lower-level
+ * to higher-level layers, as follows:
+ *
+ *	UART routines
+ *	Bedrock/L1 "PPP-like" protocol implementation
+ *	System controller "message" interface (allows multiplexing
+ *		of various kinds of requests and responses with
+ *		console I/O)
+ *	Console interface:
+ *	  "l1_cons", the glue that allows the L1 to act
+ *		as the system console for the stdio libraries
+ *
+ * Routines making use of the system controller "message"-style interface
+ * can be found in l1_command.c.
+ */
+
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/io.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/hcl_util.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/eeprom.h>
+#include <asm/sn/router.h>
+#include <asm/sn/module.h>
+#include <asm/sn/ksys/l1.h>
+#include <asm/sn/nodepda.h>
+#include <asm/sn/clksupport.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/uart16550.h>
+#include <asm/sn/simulator.h>
+
+
+#define UART_BAUD_RATE          57600
+
+int 
+get_L1_baud(void)
+{
+    return UART_BAUD_RATE;
+}
+
+
+
+/* Return the current interrupt level */
+int
+l1_get_intr_value( void )
+{
+	return(0);
+}
+
+/* Disconnect the callup functions - throw away interrupts */
+
+void
+l1_unconnect_intr(void)
+{
+}
+
+/* Set up uart interrupt handling for this node's uart */
+
+void
+l1_connect_intr(void *rx_notify, void *tx_notify)
+{
+#if 0
+	// Will need code here for sn2 - something like this
+	console_nodepda = NODEPDA(NASID_TO_COMPACT_NODEID(get_master_nasid());
+	intr_connect_level(console_nodepda->node_first_cpu,
+                                SGI_UART_VECTOR, INTPEND0_MAXMASK,
+                                dummy_intr_func);
+	request_irq(SGI_UART_VECTOR | (console_nodepda->node_first_cpu << 8),
+                                intr_func, SA_INTERRUPT | SA_SHIRQ,
+                                "l1_protocol_driver", (void *)sc);
+#endif
+}
+
+
+/* These are functions to use from serial_in/out when in protocol
+ * mode to send and receive uart control regs. These are external
+ * interfaces into the protocol driver.
+ */
+
+void
+l1_control_out(int offset, int value)
+{
+	/* quietly ignore unless simulator */
+	if ( IS_RUNNING_ON_SIMULATOR() ) {
+		extern u64 master_node_bedrock_address;
+		if ( master_node_bedrock_address != (u64)0 ) {
+			writeb(value, (unsigned long)master_node_bedrock_address +
+				(offset<< 3));
+		}
+		return;
+	}
+}
+
+/* Console input exported interface. Return a register value.  */
+
+int
+l1_control_in_polled(int offset)
+{
+	static int l1_control_in_local(int);
+
+	return(l1_control_in_local(offset));
+}
+
+int
+l1_control_in(int offset)
+{
+	static int l1_control_in_local(int);
+
+	return(l1_control_in_local(offset));
+}
+
+static int
+l1_control_in_local(int offset)
+{
+	int sal_call_status = 0, input;
+	int ret = 0;
+
+	if ( IS_RUNNING_ON_SIMULATOR() ) {
+		extern u64 master_node_bedrock_address;
+		ret = readb((unsigned long)master_node_bedrock_address +
+				(offset<< 3));
+		return(ret);
+	}		
+	if ( offset == REG_LSR ) {
+		ret = (LSR_XHRE | LSR_XSRE);	/* can send anytime */
+		sal_call_status = ia64_sn_console_check(&input);
+		if ( !sal_call_status && input ) {
+			/* input pending */
+			ret |= LSR_RCA;
+		}
+	}
+	return(ret);
+}
+
+/*
+ * Console input exported interface. Return a character (if one is available)
+ */
+
+int
+l1_serial_in_polled(void)
+{
+	static int l1_serial_in_local(void);
+
+	return(l1_serial_in_local());
+}
+
+int
+l1_serial_in(void)
+{
+	static int l1_serial_in_local(void);
+
+	if ( IS_RUNNING_ON_SIMULATOR() ) {
+		extern u64 master_node_bedrock_address;
+		return(readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3)));
+	}	
+	return(l1_serial_in_local());
+}
+
+static int
+l1_serial_in_local(void)
+{
+	int ch;
+
+	if ( IS_RUNNING_ON_SIMULATOR() ) {
+		extern u64 master_node_bedrock_address;
+		return(readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3)));
+	}		
+
+	if ( !(ia64_sn_console_getc(&ch)) )
+		return(ch);
+	else
+		return(0);
+}
+
+/* Console output exported interface. Write message to the console.  */
+
+int
+l1_serial_out( char *str, int len )
+{
+	int counter = len;
+
+	/* Ignore empty messages */
+	if ( len == 0 )
+		return(len);
+
+#if defined(CONFIG_IA64_EARLY_PRINTK)
+	/* Need to setup SAL calls so the PROM calls will work */
+	{
+		static int inited;
+		void early_sn_setup(void);
+		if(!inited) {
+			inited=1;
+			early_sn_setup();
+		}
+	}
+#endif
+
+	if ( IS_RUNNING_ON_SIMULATOR() ) {
+		extern u64 master_node_bedrock_address;
+		void early_sn_setup(void);
+		if (!master_node_bedrock_address)
+			early_sn_setup();
+		if ( master_node_bedrock_address != (u64)0 ) {
+#ifdef FLAG_DIRECT_CONSOLE_WRITES
+			/* This is an easy way to pre-pend the output to know whether the output
+			 * was done via sal or directly */
+			writeb('[', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+			writeb('+', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+			writeb(']', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+			writeb(' ', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+#endif	/* FLAG_DIRECT_CONSOLE_WRITES */
+			while ( counter > 0 ) {
+				writeb(*str, (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+				counter--;
+				str++;
+			}
+		}
+		return(len);
+	}
+
+	/* Attempt to write things out thru the sal */
+	if ( ia64_sn_console_putb(str, len) )
+		return(0);
+
+	return((counter <= 0) ? 0 : (len - counter));
+}
diff -Nru a/arch/ia64/sn/io/sn2/l1_command.c b/arch/ia64/sn/io/sn2/l1_command.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/l1_command.c	Mon Feb 24 05:24:42 2003
@@ -0,0 +1,207 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */ 
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/io.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/hcl_util.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/eeprom.h>
+#include <asm/sn/router.h>
+#include <asm/sn/module.h>
+#include <asm/sn/ksys/l1.h>
+#include <asm/sn/nodepda.h>
+#include <asm/sn/clksupport.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/sn_sal.h>
+#include <linux/ctype.h>
+
+#define ELSC_TIMEOUT	1000000		/* ELSC response timeout (usec) */
+#define LOCK_TIMEOUT	5000000		/* Hub lock timeout (usec) */
+
+#define hub_cpu_get()	0
+
+#define LBYTE(caddr)	(*(char *) caddr)
+
+extern char *bcopy(const char * src, char * dest, int count);
+
+#define LDEBUG		0
+
+/*
+ * ELSC data is in NVRAM page 7 at the following offsets.
+ */
+
+#define NVRAM_MAGIC_AD	0x700		/* magic number used for init */
+#define NVRAM_PASS_WD	0x701		/* password (4 bytes in length) */
+#define NVRAM_DBG1	0x705		/* virtual XOR debug switches */
+#define NVRAM_DBG2	0x706		/* physical XOR debug switches */
+#define NVRAM_CFG	0x707		/* ELSC Configuration info */
+#define NVRAM_MODULE	0x708		/* system module number */
+#define NVRAM_BIST_FLG	0x709		/* BIST flags (2 bits per nodeboard) */
+#define NVRAM_PARTITION 0x70a		/* module's partition id */
+#define	NVRAM_DOMAIN	0x70b		/* module's domain id */
+#define	NVRAM_CLUSTER	0x70c		/* module's cluster id */
+#define	NVRAM_CELL	0x70d		/* module's cellid */
+
+#define NVRAM_MAGIC_NO	0x37		/* value of magic number */
+#define NVRAM_SIZE	16		/* 16 bytes in nvram */
+
+
+/* elsc_display_line writes up to 12 characters to either the top or bottom
+ * line of the L1 display.  line points to a buffer containing the message
+ * to be displayed.  The zero-based line number is specified by lnum (so
+ * lnum == 0 specifies the top line and lnum == 1 specifies the bottom).
+ * Lines longer than 12 characters, or line numbers not less than
+ * L1_DISPLAY_LINES, cause elsc_display_line to return an error.
+ */
+int elsc_display_line(nasid_t nasid, char *line, int lnum)
+{
+    return 0;
+}
+
+/*
+ * iobrick routines
+ */
+
+/* iobrick_rack_bay_type_get fills in the three int * arguments with the
+ * rack number, bay number and brick type of the L1 being addressed.  Note
+ * that if the L1 operation fails and this function returns an error value, 
+ * garbage may be written to brick_type.
+ */
+
+
+int iobrick_rack_bay_type_get( nasid_t nasid, uint *rack, 
+			       uint *bay, uint *brick_type )
+{
+	int result = 0;
+
+	if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) )
+		return( ELSC_ERROR_CMD_SEND );
+
+	*rack = (result & L1_ADDR_RACK_MASK) >> L1_ADDR_RACK_SHFT;
+	*bay = (result & L1_ADDR_BAY_MASK) >> L1_ADDR_BAY_SHFT;
+	*brick_type = (result & L1_ADDR_TYPE_MASK) >> L1_ADDR_TYPE_SHFT;
+	*brick_type = toupper(*brick_type);
+
+	return 0;
+}
+
+
+int iomoduleid_get(nasid_t nasid)
+{
+
+	int result = 0;
+
+	if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) )
+		return( ELSC_ERROR_CMD_SEND );
+
+	return result;
+
+}
+
+int iobrick_module_get(nasid_t nasid)
+{
+    uint rnum, rack, bay, brick_type, t;
+    int ret;
+
+    /* construct module ID from rack and slot info */
+
+    if ((ret = iobrick_rack_bay_type_get(nasid, &rnum, &bay, &brick_type)) < 0)
+        return ret;
+
+    if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT)
+        return ELSC_ERROR_MODULE;
+
+    /* Build a moduleid_t-compatible rack number */
+
+    rack = 0;           
+    t = rnum / 100;             /* rack class (CPU/IO) */
+    if (t > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack))
+        return ELSC_ERROR_MODULE;
+    RACK_ADD_CLASS(rack, t);
+    rnum %= 100;
+
+    t = rnum / 10;              /* rack group */
+    if (t > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack))
+        return ELSC_ERROR_MODULE;
+    RACK_ADD_GROUP(rack, t);
+
+    t = rnum % 10;              /* rack number (one-based) */
+    if (t-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack))
+        return ELSC_ERROR_MODULE;
+    RACK_ADD_NUM(rack, t);
+
+    switch( brick_type ) {
+      case 'I': 
+	brick_type = MODULE_IBRICK; break;
+      case 'P':
+	brick_type = MODULE_PBRICK; break;
+      case 'X':
+	brick_type = MODULE_XBRICK; break;
+    }
+
+    ret = RBT_TO_MODULE(rack, bay, brick_type);
+
+    return ret;
+}
+
+/*
+ * iobrick_module_get_nasid() returns a module_id which has the brick
+ * type encoded in bits 15-12, but this is not the true brick type...
+ * The module_id returned by iobrick_module_get_nasid() is modified
+ * to make a PEBRICKs & PXBRICKs look like a PBRICK.  So this routine
+ * iobrick_type_get_nasid() returns the true unmodified brick type.
+ */
+int
+iobrick_type_get_nasid(nasid_t nasid)
+{
+    uint rack, bay, type;
+    int t, ret;
+    extern char brick_types[];
+
+    if ((ret = iobrick_rack_bay_type_get(nasid, &rack, &bay, &type)) < 0) {
+        return ret;
+    }
+
+    /* convert brick_type to lower case */
+    if ((type >= 'A') && (type <= 'Z'))
+        type = type - 'A' + 'a';
+
+    /* convert to a module.h brick type */
+    for( t = 0; t < MAX_BRICK_TYPES; t++ ) {
+        if( brick_types[t] == type )
+            return t;
+    }
+
+    return -1;    /* unknown brick */
+}
+
+int iobrick_module_get_nasid(nasid_t nasid)
+{
+    int io_moduleid;
+
+#ifdef PIC_LATER
+    uint rack, bay;
+
+    if (PEBRICK_NODE(nasid)) {
+        if (peer_iobrick_rack_bay_get(nasid, &rack, &bay)) {
+            printf("Could not read rack and bay location "
+                   "of PEBrick at nasid %d\n", nasid);
+        }
+
+        io_moduleid = peer_iobrick_module_get(sc, rack, bay);
+    }
+#endif	/* PIC_LATER */
+    io_moduleid = iobrick_module_get(nasid);
+    return io_moduleid;
+}
diff -Nru a/arch/ia64/sn/io/sn2/ml_SN_init.c b/arch/ia64/sn/io/sn2/ml_SN_init.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/ml_SN_init.c	Mon Feb 24 05:21:39 2003
@@ -0,0 +1,160 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/bootmem.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/io.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/snconfig.h>
+
+extern int numcpus;
+extern char arg_maxnodes[];
+extern cpuid_t master_procid;
+
+extern int hasmetarouter;
+
+int		maxcpus;
+cpumask_t	boot_cpumask;
+hubreg_t	region_mask = 0;
+
+
+extern xwidgetnum_t hub_widget_id(nasid_t);
+
+extern int valid_icache_reasons;	/* Reasons to flush the icache */
+extern int valid_dcache_reasons;	/* Reasons to flush the dcache */
+extern u_char miniroot;
+extern volatile int	need_utlbmiss_patch;
+extern void iograph_early_init(void);
+
+nasid_t master_nasid = INVALID_NASID;		/* This is the partition master nasid */
+nasid_t master_baseio_nasid = INVALID_NASID;	/* This is the master base I/O nasid */
+
+
+/*
+ * mlreset(void)
+ * 	very early machine reset - at this point NO interrupts have been
+ * 	enabled; nor is memory, tlb, p0, etc setup.
+ *
+ * 	slave is zero when mlreset is called for the master processor and
+ *	is nonzero thereafter.
+ */
+
+
+void
+mlreset(int slave)
+{
+	/*
+	 * We are the master cpu and node.
+	 */ 
+	master_nasid = get_nasid();
+	set_master_bridge_base();
+
+	/* We're the master processor */
+	master_procid = smp_processor_id();
+	master_nasid = cpuid_to_nasid(master_procid);
+
+	/*
+	 * master_nasid we get back better be same as one from
+	 * get_nasid()
+	 */
+	ASSERT_ALWAYS(master_nasid == get_nasid());
+
+	/* early initialization of iograph */
+	iograph_early_init();
+
+	/* Initialize Hub Pseudodriver Management */
+	hubdev_init();
+}
+
+
+/* XXX - Move the meat of this to intr.c ? */
+/*
+ * Set up the platform-dependent fields in the nodepda.
+ */
+void init_platform_nodepda(nodepda_t *npda, cnodeid_t node)
+{
+	hubinfo_t hubinfo;
+
+	extern void router_map_init(nodepda_t *);
+	extern void router_queue_init(nodepda_t *,cnodeid_t);
+	extern void intr_init_vecblk(nodepda_t *, cnodeid_t, int);
+
+	/* Allocate per-node platform-dependent data */
+	hubinfo = (hubinfo_t)alloc_bootmem_node(NODE_DATA(node), sizeof(struct hubinfo_s));
+
+	npda->pdinfo = (void *)hubinfo;
+	hubinfo->h_nodepda = npda;
+	hubinfo->h_cnodeid = node;
+	hubinfo->h_nasid = COMPACT_TO_NASID_NODEID(node);
+
+	spin_lock_init(&hubinfo->h_crblock);
+
+	hubinfo->h_widgetid = hub_widget_id(hubinfo->h_nasid);
+	npda->xbow_peer = INVALID_NASID;
+
+	/* 
+	 * Initialize the linked list of
+	 * router info pointers to the dependent routers
+	 */
+	npda->npda_rip_first = NULL;
+
+	/*
+	 * npda_rip_last always points to the place
+	 * where the next element is to be inserted
+	 * into the list 
+	 */
+	npda->npda_rip_last = &npda->npda_rip_first;
+	npda->geoid.any.type = GEO_TYPE_INVALID;
+
+	mutex_init_locked(&npda->xbow_sema); /* init it locked? */
+}
+
+/* XXX - Move the interrupt stuff to intr.c ? */
+/*
+ * Set up the platform-dependent fields in the processor pda.
+ * Must be done _after_ init_platform_nodepda().
+ * If we need a lock here, something else is wrong!
+ */
+void init_platform_pda(cpuid_t cpu)
+{
+}
+
+void
+update_node_information(cnodeid_t cnodeid)
+{
+	nodepda_t *npda = NODEPDA(cnodeid);
+	nodepda_router_info_t *npda_rip;
+	
+	/* Go through the list of router info 
+	 * structures and copy some frequently
+	 * accessed info from the info hanging
+	 * off the corresponding router vertices
+	 */
+	npda_rip = npda->npda_rip_first;
+	while(npda_rip) {
+		if (npda_rip->router_infop) {
+			npda_rip->router_portmask = 
+				npda_rip->router_infop->ri_portmask;
+			npda_rip->router_slot = 
+				npda_rip->router_infop->ri_slotnum;
+		} else {
+			/* No router, no ports. */
+			npda_rip->router_portmask = 0;
+		}
+		npda_rip = npda_rip->router_next;
+	}
+}
diff -Nru a/arch/ia64/sn/io/sn2/ml_iograph.c b/arch/ia64/sn/io/sn2/ml_iograph.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/ml_iograph.c	Mon Feb 24 05:24:56 2003
@@ -0,0 +1,1395 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/io.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/hcl_util.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/xtalk/xbow.h>
+#include <asm/sn/pci/bridge.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/eeprom.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/xtalk/xtalk.h>
+#include <asm/sn/xtalk/xswitch.h>
+#include <asm/sn/xtalk/xwidget.h>
+#include <asm/sn/xtalk/xtalk_private.h>
+#include <asm/sn/xtalk/xtalkaddrs.h>
+
+/* #define IOGRAPH_DEBUG */
+#ifdef IOGRAPH_DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* IOGRAPH_DEBUG */
+
+/* #define PROBE_TEST */
+
+/* At most 2 hubs can be connected to an xswitch */
+#define NUM_XSWITCH_VOLUNTEER 2
+
+extern unsigned char Is_pic_on_this_nasid[512];
+
+/*
+ * Track which hubs have volunteered to manage devices hanging off of
+ * a Crosstalk Switch (e.g. xbow).  This structure is allocated,
+ * initialized, and hung off the xswitch vertex early on when the
+ * xswitch vertex is created.
+ */
+typedef struct xswitch_vol_s {
+	mutex_t xswitch_volunteer_mutex;
+	int		xswitch_volunteer_count;
+	devfs_handle_t	xswitch_volunteer[NUM_XSWITCH_VOLUNTEER];
+} *xswitch_vol_t;
+
+void
+xswitch_vertex_init(devfs_handle_t xswitch)
+{
+	xswitch_vol_t xvolinfo;
+	int rc;
+	extern void * snia_kmem_zalloc(size_t size, int flag);
+
+	xvolinfo = snia_kmem_zalloc(sizeof(struct xswitch_vol_s), GFP_KERNEL);
+	mutex_init(&xvolinfo->xswitch_volunteer_mutex);
+	rc = hwgraph_info_add_LBL(xswitch, 
+			INFO_LBL_XSWITCH_VOL,
+			(arbitrary_info_t)xvolinfo);
+	ASSERT(rc == GRAPH_SUCCESS); rc = rc;
+}
+
+
+/*
+ * When assignment of hubs to widgets is complete, we no longer need the
+ * xswitch volunteer structure hanging around.  Destroy it.
+ */
+static void
+xswitch_volunteer_delete(devfs_handle_t xswitch)
+{
+	xswitch_vol_t xvolinfo;
+	int rc;
+	extern void snia_kmem_free(void *ptr, size_t size);
+
+	rc = hwgraph_info_remove_LBL(xswitch, 
+				INFO_LBL_XSWITCH_VOL,
+				(arbitrary_info_t *)&xvolinfo);
+	snia_kmem_free(xvolinfo, sizeof(struct xswitch_vol_s));
+}
+/*
+ * A Crosstalk master volunteers to manage xwidgets on the specified xswitch.
+ */
+/* ARGSUSED */
+static void
+volunteer_for_widgets(devfs_handle_t xswitch, devfs_handle_t master)
+{
+	xswitch_vol_t xvolinfo = NULL;
+	devfs_handle_t hubv;
+	hubinfo_t hubinfo;
+
+	(void)hwgraph_info_get_LBL(xswitch, 
+				INFO_LBL_XSWITCH_VOL, 
+				(arbitrary_info_t *)&xvolinfo);
+	if (xvolinfo == NULL) {
+	    if (!is_headless_node_vertex(master))
+		    printk(KERN_WARNING
+			"volunteer for widgets: vertex 0x%p has no info label",
+			(void *)xswitch);
+	    return;
+	}
+
+	mutex_lock(&xvolinfo->xswitch_volunteer_mutex);
+	ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER);
+	xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master;
+	xvolinfo->xswitch_volunteer_count++;
+
+	/*
+	 * if dual ported, make the lowest widgetid always be 
+	 * xswitch_volunteer[0].
+	 */
+	if (xvolinfo->xswitch_volunteer_count == NUM_XSWITCH_VOLUNTEER) {
+		hubv = xvolinfo->xswitch_volunteer[0];
+		hubinfo_get(hubv, &hubinfo);
+		if (hubinfo->h_widgetid != XBOW_HUBLINK_LOW) {
+			xvolinfo->xswitch_volunteer[0] = 
+						xvolinfo->xswitch_volunteer[1];
+			xvolinfo->xswitch_volunteer[1] = hubv;
+		}
+	}
+	mutex_unlock(&xvolinfo->xswitch_volunteer_mutex);
+}
+
+extern int xbow_port_io_enabled(nasid_t nasid, int widgetnum);
+
+/*
+ * Assign all the xwidgets hanging off the specified xswitch to the
+ * Crosstalk masters that have volunteered for xswitch duty.
+ */
+/* ARGSUSED */
+static void
+assign_widgets_to_volunteers(devfs_handle_t xswitch, devfs_handle_t hubv)
+{
+	xswitch_info_t xswitch_info;
+	xswitch_vol_t xvolinfo = NULL;
+	xwidgetnum_t widgetnum;
+	int num_volunteer;
+	nasid_t nasid;
+	hubinfo_t hubinfo;
+	extern int iobrick_type_get_nasid(nasid_t);
+
+
+	hubinfo_get(hubv, &hubinfo);
+	nasid = hubinfo->h_nasid;
+	
+	xswitch_info = xswitch_info_get(xswitch);
+	ASSERT(xswitch_info != NULL);
+
+	(void)hwgraph_info_get_LBL(xswitch, 
+				INFO_LBL_XSWITCH_VOL, 
+				(arbitrary_info_t *)&xvolinfo);
+	if (xvolinfo == NULL) {
+	    if (!is_headless_node_vertex(hubv))
+		    printk(KERN_WARNING
+			"assign_widgets_to_volunteers:vertex 0x%p has "
+			" no info label",
+			(void *)xswitch);
+	    return;
+	}
+
+	num_volunteer = xvolinfo->xswitch_volunteer_count;
+	ASSERT(num_volunteer > 0);
+
+	/* Assign master hub for xswitch itself.  */
+	if (HUB_WIDGET_ID_MIN > 0) {
+		hubv = xvolinfo->xswitch_volunteer[0];
+		xswitch_info_master_assignment_set(xswitch_info, (xwidgetnum_t)0, hubv);
+	}
+
+	/*
+	 * TBD: Use administrative information to alter assignment of
+	 * widgets to hubs.
+	 */
+	for (widgetnum=HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
+		int i;
+
+		/*
+		 * Ignore disabled/empty ports.
+		 */
+		if (!xbow_port_io_enabled(nasid, widgetnum)) 
+		    continue;
+
+		/*
+		 * If this is the master IO board, assign it to the same 
+		 * hub that owned it in the prom.
+		 */
+		if (is_master_baseio_nasid_widget(nasid, widgetnum)) {
+			extern nasid_t get_master_baseio_nasid(void);
+			for (i=0; i<num_volunteer; i++) {
+				hubv = xvolinfo->xswitch_volunteer[i];
+				hubinfo_get(hubv, &hubinfo);
+				nasid = hubinfo->h_nasid;
+				if (nasid == get_master_baseio_nasid())
+					goto do_assignment;
+			}
+			PRINT_PANIC("Nasid == %d, console nasid == %d",
+				nasid, get_master_baseio_nasid());
+		}
+
+		/*
+		 * Assuming that we're dual-hosted and that PCI cards 
+		 * are naturally placed left-to-right, alternate PCI 
+		 * buses across both Cbricks.   For Pbricks, and Ibricks,
+                 * io_brick_map_widget() returns the PCI bus number
+                 * associated with the given brick type and widget number.
+                 * For Xbricks, it returns the XIO slot number.
+		 */
+
+		i = 0;
+		if (num_volunteer > 1) {
+                        int	       bt;
+
+                       	bt = iobrick_type_get_nasid(nasid);
+                        if (bt >= 0) {
+				/*
+				 * PXBRICK has two busses per widget so this
+				 * algorithm wouldn't work (all busses would
+				 * be assigned to one volunteer). Change the
+				 * bricktype to PBRICK whose mapping is setup
+				 * suchthat 2 of the PICs will be assigned to
+				 * one volunteer and the other one will be
+				 * assigned to the other volunteer.
+				 */
+				if (bt == MODULE_PXBRICK) 
+					bt = MODULE_PBRICK;
+
+			        i = io_brick_map_widget(bt, widgetnum) & 1;
+                        }
+                }
+
+		hubv = xvolinfo->xswitch_volunteer[i];
+
+do_assignment:
+		/*
+		 * At this point, we want to make hubv the master of widgetnum.
+		 */
+		xswitch_info_master_assignment_set(xswitch_info, widgetnum, hubv);
+	}
+
+	xswitch_volunteer_delete(xswitch);
+}
+
+/*
+ * Early iograph initialization.  Called by master CPU in mlreset().
+ * Useful for including iograph.o in kernel.o.
+ */
+void
+iograph_early_init(void)
+{
+/*
+ * Need new way to get this information ..
+ */
+	cnodeid_t cnode;
+	nasid_t nasid;
+	lboard_t *board;
+	
+	/*
+	 * Init. the board-to-hwgraph link early, so FRU analyzer
+	 * doesn't trip on leftover values if we panic early on.
+	 */
+	for(cnode = 0; cnode < numnodes; cnode++) {
+		nasid = COMPACT_TO_NASID_NODEID(cnode);
+		board = (lboard_t *)KL_CONFIG_INFO(nasid);
+		DBG("iograph_early_init: Found board 0x%p\n", board);
+
+		/* Check out all the board info stored on a node */
+		while(board) {
+			board->brd_graph_link = GRAPH_VERTEX_NONE;
+			board = KLCF_NEXT(board);
+			DBG("iograph_early_init: Found board 0x%p\n", board);
+		}
+	}
+
+	hubio_init();
+}
+
+/*
+ * Let boot processor know that we're done initializing our node's IO
+ * and then exit.
+ */
+/* ARGSUSED */
+static void
+io_init_done(cnodeid_t cnodeid,cpu_cookie_t c)
+{
+	/* Let boot processor know that we're done. */
+}
+
+/* 
+ * Probe to see if this hub's xtalk link is active.  If so,
+ * return the Crosstalk Identification of the widget that we talk to.  
+ * This is called before any of the Crosstalk infrastructure for 
+ * this hub is set up.  It's usually called on the node that we're
+ * probing, but not always.
+ *
+ * TBD: Prom code should actually do this work, and pass through 
+ * hwid for our use.
+ */
+static void
+early_probe_for_widget(devfs_handle_t hubv, xwidget_hwid_t hwid)
+{
+	hubreg_t llp_csr_reg;
+	nasid_t nasid;
+	hubinfo_t hubinfo;
+
+	hubinfo_get(hubv, &hubinfo);
+	nasid = hubinfo->h_nasid;
+
+	llp_csr_reg = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
+	/* 
+	 * If link is up, read the widget's part number.
+	 * A direct connect widget must respond to widgetnum=0.
+	 */
+	if (llp_csr_reg & IIO_LLP_CSR_IS_UP) {
+		/* TBD: Put hub into "indirect" mode */
+		/*
+		 * We're able to read from a widget because our hub's 
+		 * WIDGET_ID was set up earlier.
+		 */
+		widgetreg_t widget_id = *(volatile widgetreg_t *)
+			(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);
+
+		DBG("early_probe_for_widget: Hub Vertex 0x%p is UP widget_id = 0x%x Register 0x%p\n", hubv, widget_id,
+		(volatile widgetreg_t *)(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID) );
+
+		hwid->part_num = XWIDGET_PART_NUM(widget_id);
+		hwid->rev_num = XWIDGET_REV_NUM(widget_id);
+		hwid->mfg_num = XWIDGET_MFG_NUM(widget_id);
+
+		/* TBD: link reset */
+	} else {
+
+		hwid->part_num = XWIDGET_PART_NUM_NONE;
+		hwid->rev_num = XWIDGET_REV_NUM_NONE;
+		hwid->mfg_num = XWIDGET_MFG_NUM_NONE;
+	}
+}
+
+/* Add inventory information to the widget vertex 
+ * Right now (module,slot,revision) is being
+ * added as inventory information.
+ */
+static void
+xwidget_inventory_add(devfs_handle_t 		widgetv,
+		      lboard_t 			*board,
+		      struct xwidget_hwid_s 	hwid)
+{
+	if (!board)
+		return;
+	/* Donot add inventory information for the baseio
+	 * on a speedo with an xbox. It has already been
+	 * taken care of in SN00_vmc.
+	 * Speedo with xbox's baseio comes in at slot io1 (widget 9)
+	 */
+	device_inventory_add(widgetv,INV_IOBD,board->brd_type,
+			     geo_module(board->brd_geoid),
+			     SLOTNUM_GETSLOT(board->brd_slot),
+			     hwid.rev_num);
+}
+
+/*
+ * io_xswitch_widget_init
+ *	
+ */
+
+void
+io_xswitch_widget_init(devfs_handle_t  	xswitchv,
+		       devfs_handle_t	hubv,
+		       xwidgetnum_t	widgetnum,
+		       async_attach_t	aa)
+{
+	xswitch_info_t		xswitch_info;
+	xwidgetnum_t		hub_widgetid;
+	devfs_handle_t		widgetv;
+	cnodeid_t		cnode;
+	widgetreg_t		widget_id;
+	nasid_t			nasid, peer_nasid;
+	struct xwidget_hwid_s 	hwid;
+	hubinfo_t		hubinfo;
+	/*REFERENCED*/
+	int			rc;
+	char 			pathname[128];
+	lboard_t		*board = NULL;
+	char			buffer[16];
+	char			bt;
+	moduleid_t		io_module;
+	slotid_t get_widget_slotnum(int xbow, int widget);
+	
+	DBG("\nio_xswitch_widget_init: hubv 0x%p, xswitchv 0x%p, widgetnum 0x%x\n", hubv, xswitchv, widgetnum);
+
+	/*
+	 * Verify that xswitchv is indeed an attached xswitch.
+	 */
+	xswitch_info = xswitch_info_get(xswitchv);
+	ASSERT(xswitch_info != NULL);
+
+	hubinfo_get(hubv, &hubinfo);
+	nasid = hubinfo->h_nasid;
+	cnode = NASID_TO_COMPACT_NODEID(nasid);
+	hub_widgetid = hubinfo->h_widgetid;
+
+	/*
+	 * Check that the widget is an io widget and is enabled
+	 * on this nasid or the `peer' nasid.  The peer nasid
+	 * is the other hub/bedrock connected to the xbow.
+	 */
+	peer_nasid = NODEPDA(cnode)->xbow_peer;
+	if (peer_nasid == INVALID_NASID)
+		/* If I don't have a peer, use myself. */
+		peer_nasid = nasid;
+	if (!xbow_port_io_enabled(nasid, widgetnum) &&
+	    !xbow_port_io_enabled(peer_nasid, widgetnum)) {
+		return;
+	}
+
+	if (xswitch_info_link_ok(xswitch_info, widgetnum)) {
+		char			name[4];
+		lboard_t dummy;
+
+		/*
+		 * If the current hub is not supposed to be the master 
+		 * for this widgetnum, then skip this widget.
+		 */
+		if (xswitch_info_master_assignment_get(xswitch_info,
+						       widgetnum) != hubv) {
+			return;
+		}
+
+		board = find_lboard_class(
+				(lboard_t *)KL_CONFIG_INFO(nasid),
+				KLCLASS_IOBRICK);
+		if (!board && NODEPDA(cnode)->xbow_peer != INVALID_NASID) {
+		    	board = find_lboard_class(
+					(lboard_t *)KL_CONFIG_INFO( NODEPDA(cnode)->xbow_peer),
+						KLCLASS_IOBRICK);
+		}
+
+		if (board) {
+			DBG("io_xswitch_widget_init: Found KLTYPE_IOBRICK Board 0x%p brd_type 0x%x\n", board, board->brd_type);
+		} else {
+			DBG("io_xswitch_widget_init: FIXME did not find IOBOARD\n");
+			board = &dummy;
+		}
+
+
+		/* Copy over the nodes' geoid info */
+		{
+			lboard_t *brd;
+
+			brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+			if ( brd != (lboard_t *)0 ) {
+				board->brd_geoid = brd->brd_geoid;
+			}
+		}
+
+		/*
+ 		 * Make sure we really want to say xbrick, pbrick,
+		 * etc. rather than XIO, graphics, etc.
+ 		 */
+
+		memset(buffer, 0, 16);
+		format_module_id(buffer, geo_module(board->brd_geoid), MODULE_FORMAT_BRIEF);
+		sprintf(pathname, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d" "/%cbrick" "/%s/%d",
+			buffer,
+			geo_slab(board->brd_geoid),
+			(board->brd_type == KLTYPE_IBRICK) ? 'I' :
+			(board->brd_type == KLTYPE_PBRICK) ? 'P' :
+			(board->brd_type == KLTYPE_XBRICK) ? 'X' : '?',
+			EDGE_LBL_XTALK, widgetnum);
+		
+		DBG("io_xswitch_widget_init: path= %s\n", pathname);
+		rc = hwgraph_path_add(hwgraph_root, pathname, &widgetv);
+		
+		ASSERT(rc == GRAPH_SUCCESS);
+
+		/* This is needed to let the user programs to map the
+		 * module,slot numbers to the corresponding widget numbers
+		 * on the crossbow.
+		 */
+		device_master_set(hwgraph_connectpt_get(widgetv), hubv);
+		sprintf(name, "%d", widgetnum);
+		DBG("io_xswitch_widget_init: FIXME hwgraph_edge_add %s xswitchv 0x%p, widgetv 0x%p\n", name, xswitchv, widgetv);
+		rc = hwgraph_edge_add(xswitchv, widgetv, name);
+		
+		/*
+		 * crosstalk switch code tracks which
+		 * widget is attached to each link.
+		 */
+		xswitch_info_vhdl_set(xswitch_info, widgetnum, widgetv);
+		
+		/*
+		 * Peek at the widget to get its crosstalk part and
+		 * mfgr numbers, then present it to the generic xtalk
+		 * bus provider to have its driver attach routine
+		 * called (or not).
+		 */
+		widget_id = XWIDGET_ID_READ(nasid, widgetnum);
+		hwid.part_num = XWIDGET_PART_NUM(widget_id);
+		hwid.rev_num = XWIDGET_REV_NUM(widget_id);
+		hwid.mfg_num = XWIDGET_MFG_NUM(widget_id);
+		/* Store some inventory information about
+		 * the xwidget in the hardware graph.
+		 */
+		xwidget_inventory_add(widgetv,board,hwid);
+
+		(void)xwidget_register(&hwid, widgetv, widgetnum,
+				       hubv, hub_widgetid,
+				       aa);
+
+		ia64_sn_sysctl_iobrick_module_get(nasid, &io_module);
+
+		if (io_module >= 0) {
+			char			buffer[16];
+			devfs_handle_t		to, from;
+
+			memset(buffer, 0, 16);
+			format_module_id(buffer, geo_module(board->brd_geoid), MODULE_FORMAT_BRIEF);
+
+			bt = toupper(MODULE_GET_BTCHAR(io_module));
+			/* Add a helper vertex so xbow monitoring
+			* can identify the brick type. It's simply
+			* an edge from the widget 0 vertex to the
+			*  brick vertex.
+			*/
+
+			sprintf(pathname, "/dev/hw/" EDGE_LBL_MODULE "/%s/"
+				EDGE_LBL_SLAB "/%d/"
+				EDGE_LBL_NODE "/" EDGE_LBL_XTALK "/"
+				"0",
+				buffer, geo_slab(board->brd_geoid));
+			from = hwgraph_path_to_vertex(pathname);
+			ASSERT_ALWAYS(from);
+			sprintf(pathname, "/dev/hw/" EDGE_LBL_MODULE "/%s/"
+				EDGE_LBL_SLAB "/%d/"
+				"%cbrick",
+				buffer, geo_slab(board->brd_geoid), bt);
+
+			to = hwgraph_path_to_vertex(pathname);
+			ASSERT_ALWAYS(to);
+			rc = hwgraph_edge_add(from, to,
+				EDGE_LBL_INTERCONNECT);
+			if (rc == -EEXIST)
+				goto link_done;
+			if (rc != GRAPH_SUCCESS) {
+				printk("%s: Unable to establish link"
+					" for xbmon.", pathname);
+			}
+link_done:
+		}
+
+#ifdef	SN0_USE_BTE
+		bte_bpush_war(cnode, (void *)board);
+#endif
+	}
+}
+
+
+static void
+io_init_xswitch_widgets(devfs_handle_t xswitchv, cnodeid_t cnode)
+{
+	xwidgetnum_t		widgetnum;
+	async_attach_t          aa;
+
+	aa = async_attach_new();
+	
+	DBG("io_init_xswitch_widgets: xswitchv 0x%p for cnode %d\n", xswitchv, cnode);
+
+	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; 
+	     widgetnum++) {
+		io_xswitch_widget_init(xswitchv,
+				       cnodeid_to_vertex(cnode),
+				       widgetnum, aa);
+	}
+	/* 
+	 * Wait for parallel attach threads, if any, to complete.
+	 */
+	async_attach_waitall(aa);
+	async_attach_free(aa);
+}
+
+/*
+ * For each PCI bridge connected to the xswitch, add a link from the
+ * board's klconfig info to the bridge's hwgraph vertex.  This lets
+ * the FRU analyzer find the bridge without traversing the hardware
+ * graph and risking hangs.
+ */
+static void
+io_link_xswitch_widgets(devfs_handle_t xswitchv, cnodeid_t cnodeid)
+{
+	xwidgetnum_t		widgetnum;
+	char 			pathname[128];
+	devfs_handle_t		vhdl;
+	nasid_t			nasid, peer_nasid;
+	lboard_t		*board;
+
+
+
+	/* And its connected hub's nasids */
+	nasid = COMPACT_TO_NASID_NODEID(cnodeid);
+	peer_nasid = NODEPDA(cnodeid)->xbow_peer;
+
+	/* 
+	 * Look for paths matching "<widgetnum>/pci" under xswitchv.
+	 * For every widget, init. its lboard's hwgraph link.  If the
+	 * board has a PCI bridge, point the link to it.
+	 */
+	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX;
+		 widgetnum++) {
+		sprintf(pathname, "%d", widgetnum);
+		if (hwgraph_traverse(xswitchv, pathname, &vhdl) !=
+		    GRAPH_SUCCESS)
+			continue;
+
+		board = find_lboard_module((lboard_t *)KL_CONFIG_INFO(nasid),
+				NODEPDA(cnodeid)->geoid);
+		if (board == NULL && peer_nasid != INVALID_NASID) {
+			/*
+			 * Try to find the board on our peer
+			 */
+			board = find_lboard_module(
+				(lboard_t *)KL_CONFIG_INFO(peer_nasid),
+				NODEPDA(cnodeid)->geoid);
+		}
+		if (board == NULL) {
+			printk(KERN_WARNING  "Could not find PROM info for vertex 0x%p, "
+				"FRU analyzer may fail",
+				(void *)vhdl);
+			return;
+		}
+
+		if ( Is_pic_on_this_nasid[nasid] ) {
+			/* Check both buses */
+			sprintf(pathname, "%d/"EDGE_LBL_PCIX_0, widgetnum);
+			if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS)
+				board->brd_graph_link = vhdl;
+			else {
+				sprintf(pathname, "%d/"EDGE_LBL_PCIX_1, widgetnum);
+				if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS)
+					board->brd_graph_link = vhdl;
+				else
+					board->brd_graph_link = GRAPH_VERTEX_NONE;
+			}
+		}
+		else {
+			sprintf(pathname, "%d/"EDGE_LBL_PCI, widgetnum);
+			if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS)
+				board->brd_graph_link = vhdl;
+			else
+				board->brd_graph_link = GRAPH_VERTEX_NONE;
+		}
+	}
+}
+
+/*
+ * Initialize all I/O on the specified node.
+ */
+static void
+io_init_node(cnodeid_t cnodeid)
+{
+	/*REFERENCED*/
+	devfs_handle_t hubv, switchv, widgetv;
+	struct xwidget_hwid_s hwid;
+	hubinfo_t hubinfo;
+	int is_xswitch;
+	nodepda_t	*npdap;
+	struct semaphore *peer_sema = 0;
+	uint32_t	widget_partnum;
+	nodepda_router_info_t *npda_rip;
+	cpu_cookie_t	c = 0;
+	extern int hubdev_docallouts(devfs_handle_t);
+
+	npdap = NODEPDA(cnodeid);
+
+	/*
+	 * Get the "top" vertex for this node's hardware
+	 * graph; it will carry the per-hub hub-specific
+	 * data, and act as the crosstalk provider master.
+	 * It's canonical path is probably something of the
+	 * form /hw/module/%M/slot/%d/node
+	 */
+	hubv = cnodeid_to_vertex(cnodeid);
+	DBG("io_init_node: Initialize IO for cnode %d hubv(node) 0x%p npdap 0x%p\n", cnodeid, hubv, npdap);
+
+	ASSERT(hubv != GRAPH_VERTEX_NONE);
+
+	hubdev_docallouts(hubv);
+
+	/*
+	 * Set up the dependent routers if we have any.
+	 */
+	npda_rip = npdap->npda_rip_first;
+
+	while(npda_rip) {
+		/* If the router info has not been initialized
+		 * then we need to do the router initialization
+		 */
+		if (!npda_rip->router_infop) {
+			router_init(cnodeid,0,npda_rip);
+		}
+		npda_rip = npda_rip->router_next;
+	}
+
+	/*
+	 * Read mfg info on this hub
+	 */
+
+	/* 
+	 * If nothing connected to this hub's xtalk port, we're done.
+	 */
+	early_probe_for_widget(hubv, &hwid);
+	if (hwid.part_num == XWIDGET_PART_NUM_NONE) {
+#ifdef PROBE_TEST
+		if ((cnodeid == 1) || (cnodeid == 2)) {
+			int index;
+
+			for (index = 0; index < 600; index++)
+				DBG("Interfering with device probing!!!\n");
+		}
+#endif
+		/* io_init_done takes cpu cookie as 2nd argument 
+		 * to do a restorenoderun for the setnoderun done 
+		 * at the start of this thread 
+		 */
+		
+		DBG("**** io_init_node: Node's 0x%p hub widget has XWIDGET_PART_NUM_NONE ****\n", hubv);
+		return;
+		/* NOTREACHED */
+	}
+
+	/* 
+	 * attach our hub_provider information to hubv,
+	 * so we can use it as a crosstalk provider "master"
+	 * vertex.
+	 */
+	xtalk_provider_register(hubv, &hub_provider);
+	xtalk_provider_startup(hubv);
+
+	/*
+	 * Create a vertex to represent the crosstalk bus
+	 * attached to this hub, and a vertex to be used
+	 * as the connect point for whatever is out there
+	 * on the other side of our crosstalk connection.
+	 *
+	 * Crosstalk Switch drivers "climb up" from their
+	 * connection point to try and take over the switch
+	 * point.
+	 *
+	 * Of course, the edges and verticies may already
+	 * exist, in which case our net effect is just to
+	 * associate the "xtalk_" driver with the connection
+	 * point for the device.
+	 */
+
+	(void)hwgraph_path_add(hubv, EDGE_LBL_XTALK, &switchv);
+
+	DBG("io_init_node: Created 'xtalk' entry to '../node/' xtalk vertex 0x%p\n", switchv);
+
+	ASSERT(switchv != GRAPH_VERTEX_NONE);
+
+	(void)hwgraph_edge_add(hubv, switchv, EDGE_LBL_IO);
+
+	DBG("io_init_node: Created symlink 'io' from ../node/io to ../node/xtalk \n");
+
+	/*
+	 * We need to find the widget id and update the basew_id field
+	 * accordingly. In particular, SN00 has direct connected bridge,
+	 * and hence widget id is Not 0.
+	 */
+
+	widget_partnum = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + WIDGET_ID))) & WIDGET_PART_NUM) >> WIDGET_PART_NUM_SHFT;
+
+	if (widget_partnum == BRIDGE_WIDGET_PART_NUM ||
+				widget_partnum == XBRIDGE_WIDGET_PART_NUM){
+		npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID);
+
+		DBG("io_init_node: Found XBRIDGE widget_partnum= 0x%x\n", widget_partnum);
+
+	} else if ((widget_partnum == XBOW_WIDGET_PART_NUM) ||
+			(widget_partnum == XXBOW_WIDGET_PART_NUM) ||
+			(widget_partnum == PXBOW_WIDGET_PART_NUM) ) {
+		/* 
+		 * Xbow control register does not have the widget ID field.
+		 * So, hard code the widget ID to be zero.
+		 */
+		DBG("io_init_node: Found XBOW widget_partnum= 0x%x\n", widget_partnum);
+		npdap->basew_id = 0;
+
+	} else {
+		npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID);
+
+		panic(" ****io_init_node: Unknown Widget Part Number 0x%x Widget ID 0x%x attached to Hubv 0x%p ****\n", widget_partnum, npdap->basew_id, (void *)hubv);
+
+		/*NOTREACHED*/
+	}
+	{
+		char widname[10];
+		sprintf(widname, "%x", npdap->basew_id);
+		(void)hwgraph_path_add(switchv, widname, &widgetv);
+		DBG("io_init_node: Created '%s' to '..node/xtalk/' vertex 0x%p\n", widname, widgetv);
+		ASSERT(widgetv != GRAPH_VERTEX_NONE);
+	}
+	
+	nodepda->basew_xc = widgetv;
+
+	is_xswitch = xwidget_hwid_is_xswitch(&hwid);
+
+	/* 
+	 * Try to become the master of the widget.  If this is an xswitch
+	 * with multiple hubs connected, only one will succeed.  Mastership
+	 * of an xswitch is used only when touching registers on that xswitch.
+	 * The slave xwidgets connected to the xswitch can be owned by various
+	 * masters.
+	 */
+	if (device_master_set(widgetv, hubv) == 0) {
+
+		/* Only one hub (thread) per Crosstalk device or switch makes
+		 * it to here.
+		 */
+
+		/* 
+		 * Initialize whatever xwidget is hanging off our hub.
+		 * Whatever it is, it's accessible through widgetnum 0.
+		 */
+		hubinfo_get(hubv, &hubinfo);
+
+		(void)xwidget_register(&hwid, widgetv, npdap->basew_id, hubv, hubinfo->h_widgetid, NULL);
+
+		if (!is_xswitch) {
+			/* io_init_done takes cpu cookie as 2nd argument 
+			 * to do a restorenoderun for the setnoderun done 
+			 * at the start of this thread 
+			 */
+			io_init_done(cnodeid,c);
+			/* NOTREACHED */
+		}
+
+		/* 
+		 * Special handling for Crosstalk Switches (e.g. xbow).
+		 * We need to do things in roughly the following order:
+		 *	1) Initialize xswitch hardware (done above)
+		 *	2) Determine which hubs are available to be widget masters
+		 *	3) Discover which links are active from the xswitch
+		 *	4) Assign xwidgets hanging off the xswitch to hubs
+		 *	5) Initialize all xwidgets on the xswitch
+		 */
+
+		volunteer_for_widgets(switchv, hubv);
+
+		/* If there's someone else on this crossbow, recognize him */
+		if (npdap->xbow_peer != INVALID_NASID) {
+			nodepda_t *peer_npdap = NODEPDA(NASID_TO_COMPACT_NODEID(npdap->xbow_peer));
+			peer_sema = &peer_npdap->xbow_sema;
+			volunteer_for_widgets(switchv, peer_npdap->node_vertex);
+		}
+
+		assign_widgets_to_volunteers(switchv, hubv);
+
+		/* Signal that we're done */
+		if (peer_sema) {
+			mutex_unlock(peer_sema);
+		}
+		
+	}
+	else {
+	    /* Wait 'til master is done assigning widgets. */
+	    mutex_lock(&npdap->xbow_sema);
+	}
+
+#ifdef PROBE_TEST
+	if ((cnodeid == 1) || (cnodeid == 2)) {
+		int index;
+
+		for (index = 0; index < 500; index++)
+			DBG("Interfering with device probing!!!\n");
+	}
+#endif
+	/* Now both nodes can safely inititialize widgets */
+	io_init_xswitch_widgets(switchv, cnodeid);
+	io_link_xswitch_widgets(switchv, cnodeid);
+
+	/* io_init_done takes cpu cookie as 2nd argument 
+	 * to do a restorenoderun for the setnoderun done 
+	 * at the start of this thread 
+	 */
+	io_init_done(cnodeid,c);
+
+	DBG("\nio_init_node: DONE INITIALIZED ALL I/O FOR CNODEID %d\n\n", cnodeid);
+}
+
+
+#define IOINIT_STKSZ	(16 * 1024)
+
+#define __DEVSTR1 	"/../.master/"
+#define __DEVSTR2 	"/target/"
+#define __DEVSTR3 	"/lun/0/disk/partition/"
+#define	__DEVSTR4	"/../ef"
+
+/*
+ * ioconfig starts numbering SCSI's at NUM_BASE_IO_SCSI_CTLR.
+ */
+#define NUM_BASE_IO_SCSI_CTLR 6
+/*
+ * This tells ioconfig where it can start numbering scsi controllers.
+ * Below this base number, platform-specific handles the numbering.
+ * XXX Irix legacy..controller numbering should be part of devfsd's job
+ */
+int num_base_io_scsi_ctlr = 2; /* used by syssgi */
+devfs_handle_t		base_io_scsi_ctlr_vhdl[NUM_BASE_IO_SCSI_CTLR];
+static devfs_handle_t	baseio_enet_vhdl,baseio_console_vhdl;
+
+/*
+ * Put the logical controller number information in the 
+ * scsi controller vertices for each scsi controller that
+ * is in a "fixed position".
+ */
+static void
+scsi_ctlr_nums_add(devfs_handle_t pci_vhdl)
+{
+	{
+		int i;
+
+		num_base_io_scsi_ctlr = NUM_BASE_IO_SCSI_CTLR;
+
+		/* Initialize base_io_scsi_ctlr_vhdl array */
+		for (i=0; i<num_base_io_scsi_ctlr; i++)
+			base_io_scsi_ctlr_vhdl[i] = GRAPH_VERTEX_NONE;
+	}
+	{
+	/*
+	 * May want to consider changing the SN0 code, above, to work more like
+	 * the way this works.
+	 */
+	devfs_handle_t base_ibrick_xbridge_vhdl;
+	devfs_handle_t base_ibrick_xtalk_widget_vhdl;
+	devfs_handle_t scsi_ctlr_vhdl;
+	int i;
+	graph_error_t rv;
+
+	/*
+	 * This is a table of "well-known" SCSI controllers and their well-known
+	 * controller numbers.  The names in the table start from the base IBrick's
+	 * Xbridge vertex, so the first component is the xtalk widget number.
+	 */
+	static struct {
+		char	*base_ibrick_scsi_path;
+		int	controller_number;
+	} hardwired_scsi_controllers[] = {
+		{"15/" EDGE_LBL_PCI "/1/" EDGE_LBL_SCSI_CTLR "/0", 0},
+		{"15/" EDGE_LBL_PCI "/2/" EDGE_LBL_SCSI_CTLR "/0", 1},
+		{"15/" EDGE_LBL_PCI "/3/" EDGE_LBL_SCSI_CTLR "/0", 2},
+		{"14/" EDGE_LBL_PCI "/1/" EDGE_LBL_SCSI_CTLR "/0", 3},
+		{"14/" EDGE_LBL_PCI "/2/" EDGE_LBL_SCSI_CTLR "/0", 4},
+		{"15/" EDGE_LBL_PCI "/6/ohci/0/" EDGE_LBL_SCSI_CTLR "/0", 5},
+		{NULL, -1} /* must be last */
+	};
+
+	base_ibrick_xtalk_widget_vhdl = hwgraph_connectpt_get(pci_vhdl);
+	ASSERT_ALWAYS(base_ibrick_xtalk_widget_vhdl != GRAPH_VERTEX_NONE);
+
+	base_ibrick_xbridge_vhdl = hwgraph_connectpt_get(base_ibrick_xtalk_widget_vhdl);
+	ASSERT_ALWAYS(base_ibrick_xbridge_vhdl != GRAPH_VERTEX_NONE);
+	hwgraph_vertex_unref(base_ibrick_xtalk_widget_vhdl);
+
+	/*
+	 * Iterate through the list of well-known SCSI controllers.
+	 * For each controller found, set it's controller number according
+	 * to the table.
+	 */
+	for (i=0; hardwired_scsi_controllers[i].base_ibrick_scsi_path != NULL; i++) {
+		rv = hwgraph_path_lookup(base_ibrick_xbridge_vhdl,
+			hardwired_scsi_controllers[i].base_ibrick_scsi_path, &scsi_ctlr_vhdl, NULL);
+
+		if (rv != GRAPH_SUCCESS) /* No SCSI at this path */
+			continue;
+
+		ASSERT(hardwired_scsi_controllers[i].controller_number < NUM_BASE_IO_SCSI_CTLR);
+		base_io_scsi_ctlr_vhdl[hardwired_scsi_controllers[i].controller_number] = scsi_ctlr_vhdl;
+		device_controller_num_set(scsi_ctlr_vhdl, hardwired_scsi_controllers[i].controller_number);
+		hwgraph_vertex_unref(scsi_ctlr_vhdl); /* (even though we're actually keeping a reference) */
+	}
+
+	hwgraph_vertex_unref(base_ibrick_xbridge_vhdl);
+	}
+}
+
+
+#include <asm/sn/ioerror_handling.h>
+devfs_handle_t		sys_critical_graph_root = GRAPH_VERTEX_NONE;
+
+/* Define the system critical vertices and connect them through
+ * a canonical parent-child relationships for easy traversal
+ * during io error handling.
+ */
+static void
+sys_critical_graph_init(void)
+{
+	devfs_handle_t		bridge_vhdl,master_node_vhdl;
+	devfs_handle_t  		xbow_vhdl = GRAPH_VERTEX_NONE;
+	extern devfs_handle_t	hwgraph_root;
+	devfs_handle_t		pci_slot_conn;
+	int			slot;
+	devfs_handle_t		baseio_console_conn;
+
+	DBG("sys_critical_graph_init: FIXME.\n");
+	baseio_console_conn = hwgraph_connectpt_get(baseio_console_vhdl);
+
+	if (baseio_console_conn == NULL) {
+		return;
+	}
+
+	/* Get the vertex handle for the baseio bridge */
+	bridge_vhdl = device_master_get(baseio_console_conn);
+
+	/* Get the master node of the baseio card */
+	master_node_vhdl = cnodeid_to_vertex(
+				master_node_get(baseio_console_vhdl));
+	
+	/* Add the "root->node" part of the system critical graph */
+
+	sys_critical_graph_vertex_add(hwgraph_root,master_node_vhdl);
+
+	/* Check if we have a crossbow */
+	if (hwgraph_traverse(master_node_vhdl,
+			     EDGE_LBL_XTALK"/0",
+			     &xbow_vhdl) == GRAPH_SUCCESS) {
+		/* We have a crossbow.Add "node->xbow" part of the system 
+		 * critical graph.
+		 */
+		sys_critical_graph_vertex_add(master_node_vhdl,xbow_vhdl);
+		
+		/* Add "xbow->baseio bridge" of the system critical graph */
+		sys_critical_graph_vertex_add(xbow_vhdl,bridge_vhdl);
+
+		hwgraph_vertex_unref(xbow_vhdl);
+	} else 
+		/* We donot have a crossbow. Add "node->baseio_bridge"
+		 * part of the system critical graph.
+		 */
+		sys_critical_graph_vertex_add(master_node_vhdl,bridge_vhdl);
+
+	/* Add all the populated PCI slot vertices to the system critical
+	 * graph with the bridge vertex as the parent.
+	 */
+	for (slot = 0 ; slot < 8; slot++) {
+		char	slot_edge[10];
+
+		sprintf(slot_edge,"%d",slot);
+		if (hwgraph_traverse(bridge_vhdl,slot_edge, &pci_slot_conn)
+		    != GRAPH_SUCCESS)
+			continue;
+		sys_critical_graph_vertex_add(bridge_vhdl,pci_slot_conn);
+		hwgraph_vertex_unref(pci_slot_conn);
+	}
+
+	hwgraph_vertex_unref(bridge_vhdl);
+
+	/* Add the "ioc3 pci connection point  -> console ioc3" part 
+	 * of the system critical graph
+	 */
+
+	if (hwgraph_traverse(baseio_console_vhdl,"..",&pci_slot_conn) ==
+	    GRAPH_SUCCESS) {
+		sys_critical_graph_vertex_add(pci_slot_conn, 
+					      baseio_console_vhdl);
+		hwgraph_vertex_unref(pci_slot_conn);
+	}
+
+	/* Add the "ethernet pci connection point  -> base ethernet" part of 
+	 * the system  critical graph
+	 */
+	if (hwgraph_traverse(baseio_enet_vhdl,"..",&pci_slot_conn) ==
+	    GRAPH_SUCCESS) {
+		sys_critical_graph_vertex_add(pci_slot_conn, 
+					      baseio_enet_vhdl);
+		hwgraph_vertex_unref(pci_slot_conn);
+	}
+
+	/* Add the "scsi controller pci connection point  -> base scsi 
+	 * controller" part of the system critical graph
+	 */
+	if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[0],
+			     "../..",&pci_slot_conn) == GRAPH_SUCCESS) {
+		sys_critical_graph_vertex_add(pci_slot_conn, 
+					      base_io_scsi_ctlr_vhdl[0]);
+		hwgraph_vertex_unref(pci_slot_conn);
+	}
+	if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[1],
+			     "../..",&pci_slot_conn) == GRAPH_SUCCESS) {
+		sys_critical_graph_vertex_add(pci_slot_conn, 
+					      base_io_scsi_ctlr_vhdl[1]);
+		hwgraph_vertex_unref(pci_slot_conn);
+	}
+	hwgraph_vertex_unref(baseio_console_conn);
+
+}
+
+static void
+baseio_ctlr_num_set(void)
+{
+	char 			name[MAXDEVNAME];
+	devfs_handle_t		console_vhdl, pci_vhdl, enet_vhdl;
+	devfs_handle_t		ioc3_console_vhdl_get(void);
+
+
+	DBG("baseio_ctlr_num_set; FIXME\n");
+	console_vhdl = ioc3_console_vhdl_get();
+	if (console_vhdl == GRAPH_VERTEX_NONE)
+		return;
+	/* Useful for setting up the system critical graph */
+	baseio_console_vhdl = console_vhdl;
+
+	vertex_to_name(console_vhdl,name,MAXDEVNAME);
+
+	strcat(name,__DEVSTR1);
+	pci_vhdl =  hwgraph_path_to_vertex(name);
+	scsi_ctlr_nums_add(pci_vhdl);
+	/* Unref the pci_vhdl due to the reference by hwgraph_path_to_vertex
+	 */
+	hwgraph_vertex_unref(pci_vhdl);
+
+	vertex_to_name(console_vhdl, name, MAXDEVNAME);
+	strcat(name, __DEVSTR4);
+	enet_vhdl = hwgraph_path_to_vertex(name);
+
+	/* Useful for setting up the system critical graph */
+	baseio_enet_vhdl = enet_vhdl;
+
+	device_controller_num_set(enet_vhdl, 0);
+	/* Unref the enet_vhdl due to the reference by hwgraph_path_to_vertex
+	 */
+	hwgraph_vertex_unref(enet_vhdl);
+}
+/* #endif */
+
+/*
+ * Initialize all I/O devices.  Starting closest to nodes, probe and
+ * initialize outward.
+ */
+void
+init_all_devices(void)
+{
+	/* Governor on init threads..bump up when safe 
+	 * (beware many devfs races) 
+	 */
+	cnodeid_t cnodeid, active;
+
+	active = 0;
+	for (cnodeid = 0; cnodeid < numnodes; cnodeid++) {
+                DBG("init_all_devices: Calling io_init_node() for cnode %d\n", cnodeid);
+                io_init_node(cnodeid);
+
+		DBG("init_all_devices: Done io_init_node() for cnode %d\n", cnodeid);
+	}
+
+	for (cnodeid = 0; cnodeid < numnodes; cnodeid++)
+		/*
+	 	 * Update information generated by IO init.
+		 */
+		update_node_information(cnodeid);
+
+	baseio_ctlr_num_set();
+	/* Setup the system critical graph (which is a subgraph of the
+	 * main hwgraph). This information is useful during io error
+	 * handling.
+	 */
+	sys_critical_graph_init();
+
+#if HWG_PRINT
+	hwgraph_print();
+#endif
+
+}
+
+#define toint(x) ((int)(x) - (int)('0'))
+
+void
+devnamefromarcs(char *devnm)
+{
+	int 			val;
+	char 			tmpnm[MAXDEVNAME];
+	char 			*tmp1, *tmp2;
+	
+	val = strncmp(devnm, "dks", 3);
+	if (val != 0) 
+		return;
+	tmp1 = devnm + 3;
+	if (!isdigit(*tmp1))
+		return;
+
+	val = 0;
+	while (isdigit(*tmp1)) {
+		val = 10*val+toint(*tmp1);
+		tmp1++;
+	}
+
+	if(*tmp1 != 'd')
+		return;
+	else
+		tmp1++;
+
+	if ((val < 0) || (val >= num_base_io_scsi_ctlr)) {
+		int i;
+		int viable_found = 0;
+
+		DBG("Only controller numbers 0..%d  are supported for\n", NUM_BASE_IO_SCSI_CTLR-1);
+		DBG("prom \"root\" variables of the form dksXdXsX.\n");
+		DBG("To use another disk you must use the full hardware graph path\n\n");
+		DBG("Possible controller numbers for use in 'dksXdXsX' on this system: ");
+		for (i=0; i<NUM_BASE_IO_SCSI_CTLR; i++) {
+			if (base_io_scsi_ctlr_vhdl[i] != GRAPH_VERTEX_NONE) {
+				DBG("%d ", i);
+				viable_found=1;
+			}
+		}
+		if (viable_found)
+			DBG("\n");
+		else
+			DBG("none found!\n");
+
+		DELAY(15000000);
+		//prom_reboot();
+		panic("FIXME: devnamefromarcs: should call prom_reboot here.\n");
+		/* NOTREACHED */
+	}
+		
+	ASSERT(base_io_scsi_ctlr_vhdl[val] != GRAPH_VERTEX_NONE);
+	vertex_to_name(base_io_scsi_ctlr_vhdl[val],
+		       tmpnm,
+		       MAXDEVNAME);
+	tmp2 = 	tmpnm + strlen(tmpnm);
+	strcpy(tmp2, __DEVSTR2);
+	tmp2 += strlen(__DEVSTR2);
+	while (*tmp1 != 's') {
+		if((*tmp2++ = *tmp1++) == '\0')
+			return;
+	}	
+	tmp1++;
+	strcpy(tmp2, __DEVSTR3);
+	tmp2 += strlen(__DEVSTR3);
+	while ( (*tmp2++ = *tmp1++) )
+		;
+	tmp2--;
+	*tmp2++ = '/';
+	strcpy(tmp2, EDGE_LBL_BLOCK);
+	strcpy(devnm,tmpnm);
+}
+
+static
+struct io_brick_map_s io_brick_tab[] = {
+
+/* Ibrick widget number to PCI bus number map */
+ {      MODULE_IBRICK,                          /* Ibrick type    */ 
+    /*  PCI Bus #                                  Widget #       */
+    {   0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
+        0,                                      /* 0x8            */
+        0,                                      /* 0x9            */
+        0, 0,                                   /* 0xa - 0xb      */
+        0,                                      /* 0xc            */
+        0,                                      /* 0xd            */
+        2,                                      /* 0xe            */
+        1                                       /* 0xf            */
+     }
+ },
+
+/* Pbrick widget number to PCI bus number map */
+ {      MODULE_PBRICK,                          /* Pbrick type    */ 
+    /*  PCI Bus #                                  Widget #       */
+    {   0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
+        2,                                      /* 0x8            */
+        1,                                      /* 0x9            */
+        0, 0,                                   /* 0xa - 0xb      */
+        4,                                      /* 0xc            */
+        6,                                      /* 0xd            */
+        3,                                      /* 0xe            */
+        5                                       /* 0xf            */
+    }
+ },
+
+/* PXbrick widget number to PCI bus number map */
+ {      MODULE_PXBRICK,                         /* PXbrick type   */ 
+    /*  PCI Bus #                                  Widget #       */
+    {   0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
+        0,                                      /* 0x8            */
+        0,                                      /* 0x9            */
+        0, 0,                                   /* 0xa - 0xb      */
+        1,                                      /* 0xc            */
+        5,                                      /* 0xd            */
+        0,                                      /* 0xe            */
+        3                                       /* 0xf            */
+    }
+ },
+
+/* Xbrick widget to XIO slot map */
+ {      MODULE_XBRICK,                          /* Xbrick type    */ 
+    /*  XIO Slot #                                 Widget #       */
+    {   0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
+        1,                                      /* 0x8            */
+        3,                                      /* 0x9            */
+        0, 0,                                   /* 0xa - 0xb      */
+        2,                                      /* 0xc            */
+        4,                                      /* 0xd            */
+        0,                                      /* 0xe            */
+        0                                       /* 0xf            */
+    }
+ }
+};
+
+/*
+ * Use the brick's type to map a widget number to a meaningful int
+ */
+int
+io_brick_map_widget(int brick_type, int widget_num)
+{
+        int num_bricks, i;
+
+        /* Calculate number of bricks in table */
+        num_bricks = sizeof(io_brick_tab)/sizeof(io_brick_tab[0]);
+
+        /* Look for brick prefix in table */
+        for (i = 0; i < num_bricks; i++) {
+               if (brick_type == io_brick_tab[i].ibm_type)
+                       return(io_brick_tab[i].ibm_map_wid[widget_num]);
+        }
+
+        return 0;
+
+}
+
+/*
+ * Use the device's vertex to map the device's widget to a meaningful int
+ */
+int
+io_path_map_widget(devfs_handle_t vertex)
+{
+        char hw_path_name[MAXDEVNAME];
+        char *wp, *bp, *sp = NULL;
+        int  widget_num;
+	long atoi(char *);
+	int hwgraph_vertex_name_get(devfs_handle_t vhdl, char *buf, uint buflen);
+
+
+        /* Get the full path name of the vertex */
+        if (GRAPH_SUCCESS != hwgraph_vertex_name_get(vertex, hw_path_name,
+                                                     MAXDEVNAME))
+                return 0;
+
+        /* Find the widget number in the path name */
+        wp = strstr(hw_path_name, "/"EDGE_LBL_XTALK"/");
+        if (wp == NULL)
+                return 0;
+        widget_num = atoi(wp+7);
+        if (widget_num < XBOW_PORT_8 || widget_num > XBOW_PORT_F)
+                return 0;
+
+        /* Find "brick" in the path name */
+        bp = strstr(hw_path_name, "brick");
+        if (bp == NULL)
+                return 0;
+
+        /* Find preceding slash */
+        sp = bp;
+        while (sp > hw_path_name) {
+                sp--;
+                if (*sp == '/')
+                        break;
+        }
+
+        /* Invalid if no preceding slash */
+        if (!sp)
+                return 0;
+
+        /* Bump slash pointer to "brick" prefix */
+        sp++;
+        /*
+         * Verify "brick" prefix length;  valid exaples:
+         * 'I' from "/Ibrick"
+         * 'P' from "/Pbrick"
+         * 'X' from "/Xbrick"
+         */
+         if ((bp - sp) != 1)
+                return 0;
+
+        return (io_brick_map_widget((int)*sp, widget_num));
+
+}
diff -Nru a/arch/ia64/sn/io/sn2/module.c b/arch/ia64/sn/io/sn2/module.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/module.c	Mon Feb 24 05:25:25 2003
@@ -0,0 +1,280 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/io.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/xtalk/xbow.h>
+#include <asm/sn/pci/bridge.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/sn1/hubdev.h>
+#include <asm/sn/module.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/xtalk/xswitch.h>
+#include <asm/sn/nodepda.h>
+#include <asm/sn/sn_cpuid.h>
+
+
+/* #define LDEBUG	1  */
+
+#ifdef LDEBUG
+#define DPRINTF		printk
+#define printf		printk
+#else
+#define DPRINTF(x...)
+#endif
+
+module_t	       *modules[MODULE_MAX];
+int			nummodules;
+
+#define SN00_SERIAL_FUDGE	0x3b1af409d513c2
+#define SN0_SERIAL_FUDGE	0x6e
+
+void
+encode_int_serial(uint64_t src,uint64_t *dest)
+{
+    uint64_t val;
+    int i;
+
+    val = src + SN00_SERIAL_FUDGE;
+
+
+    for (i = 0; i < sizeof(long long); i++) {
+	((char*)dest)[i] =
+	    ((char*)&val)[sizeof(long long)/2 +
+			 ((i%2) ? ((i/2 * -1) - 1) : (i/2))];
+    }
+}
+
+
+void
+decode_int_serial(uint64_t src, uint64_t *dest)
+{
+    uint64_t val;
+    int i;
+
+    for (i = 0; i < sizeof(long long); i++) {
+	((char*)&val)[sizeof(long long)/2 +
+		     ((i%2) ? ((i/2 * -1) - 1) : (i/2))] =
+	    ((char*)&src)[i];
+    }
+
+    *dest = val - SN00_SERIAL_FUDGE;
+}
+
+
+void
+encode_str_serial(const char *src, char *dest)
+{
+    int i;
+
+    for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) {
+
+	dest[i] = src[MAX_SERIAL_NUM_SIZE/2 +
+		     ((i%2) ? ((i/2 * -1) - 1) : (i/2))] +
+	    SN0_SERIAL_FUDGE;
+    }
+}
+
+void
+decode_str_serial(const char *src, char *dest)
+{
+    int i;
+
+    for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) {
+	dest[MAX_SERIAL_NUM_SIZE/2 +
+	    ((i%2) ? ((i/2 * -1) - 1) : (i/2))] = src[i] -
+	    SN0_SERIAL_FUDGE;
+    }
+}
+
+
+module_t *module_lookup(moduleid_t id)
+{
+    int			i;
+
+    for (i = 0; i < nummodules; i++)
+	if (modules[i]->id == id) {
+	    DPRINTF("module_lookup: found m=0x%p\n", modules[i]);
+	    return modules[i];
+	}
+
+    return NULL;
+}
+
+/*
+ * module_add_node
+ *
+ *   The first time a new module number is seen, a module structure is
+ *   inserted into the module list in order sorted by module number
+ *   and the structure is initialized.
+ *
+ *   The node number is added to the list of nodes in the module.
+ */
+
+module_t *module_add_node(geoid_t geoid, cnodeid_t cnodeid)
+{
+    module_t	       *m;
+    int			i;
+    char		buffer[16];
+    moduleid_t		moduleid;
+
+    memset(buffer, 0, 16);
+    moduleid = geo_module(geoid);
+    format_module_id(buffer, moduleid, MODULE_FORMAT_BRIEF);
+    DPRINTF("module_add_node: moduleid=%s node=%d\n", buffer, cnodeid);
+
+    if ((m = module_lookup(moduleid)) == 0) {
+	m = kmalloc(sizeof (module_t), GFP_KERNEL);
+	memset(m, 0 , sizeof(module_t));
+	ASSERT_ALWAYS(m);
+
+	m->id = moduleid;
+	spin_lock_init(&m->lock);
+
+	mutex_init_locked(&m->thdcnt);
+
+	/* Insert in sorted order by module number */
+
+	for (i = nummodules; i > 0 && modules[i - 1]->id > moduleid; i--)
+	    modules[i] = modules[i - 1];
+
+	modules[i] = m;
+	nummodules++;
+    }
+
+    m->nodes[m->nodecnt] = cnodeid;
+    m->geoid[m->nodecnt] = geoid;
+    m->nodecnt++;
+
+    DPRINTF("module_add_node: module %s now has %d nodes\n", buffer, m->nodecnt);
+
+    return m;
+}
+
+int module_probe_snum(module_t *m, nasid_t nasid)
+{
+    lboard_t	       *board;
+    klmod_serial_num_t *comp;
+    char * bcopy(const char * src, char * dest, int count);
+    char serial_number[16];
+
+    /*
+     * record brick serial number
+     */
+    board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+
+    if (! board || KL_CONFIG_DUPLICATE_BOARD(board))
+    {
+#if	LDEBUG
+	printf ("module_probe_snum: no IP35 board found!\n");
+#endif
+	return 0;
+    }
+
+    board_serial_number_get( board, serial_number );
+    if( serial_number[0] != '\0' ) {
+	encode_str_serial( serial_number, m->snum.snum_str );
+	m->snum_valid = 1;
+    }
+#if	LDEBUG
+    else {
+	printf("module_probe_snum: brick serial number is null!\n");
+    }
+    printf("module_probe_snum: brick serial number == %s\n", serial_number);
+#endif /* DEBUG */
+
+    board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid),
+			KLTYPE_IOBRICK_XBOW);
+
+    if (! board || KL_CONFIG_DUPLICATE_BOARD(board))
+	return 0;
+
+    comp = GET_SNUM_COMP(board);
+
+    if (comp) {
+#if LDEBUG
+	    int i;
+
+	    printf("********found module with id %x and string", m->id);
+
+	    for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++)
+		printf(" %x ", comp->snum.snum_str[i]);
+
+	    printf("\n");	/* Fudged string is not ASCII */
+#endif
+
+	    if (comp->snum.snum_str[0] != '\0') {
+		bcopy(comp->snum.snum_str,
+		      m->sys_snum,
+		      MAX_SERIAL_NUM_SIZE);
+		m->sys_snum_valid = 1;
+	    }
+    }
+
+    if (m->sys_snum_valid)
+	return 1;
+    else {
+	DPRINTF("Invalid serial number for module %d, "
+		"possible missing or invalid NIC.", m->id);
+	return 0;
+    }
+}
+
+void
+io_module_init(void)
+{
+    cnodeid_t		node;
+    lboard_t	       *board;
+    nasid_t		nasid;
+    int			nserial;
+    module_t	       *m;
+
+    DPRINTF("*******module_init\n");
+
+    nserial = 0;
+
+    for (node = 0; node < numnodes; node++) {
+	nasid = COMPACT_TO_NASID_NODEID(node);
+
+	board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+	ASSERT(board);
+
+	m = module_add_node(board->brd_geoid, node);
+
+	if (! m->snum_valid && module_probe_snum(m, nasid))
+	    nserial++;
+    }
+
+    DPRINTF("********found total of %d serial numbers in the system\n",
+	    nserial);
+
+    if (nserial == 0)
+	DPRINTF(KERN_WARNING  "io_module_init: No serial number found.\n");
+}
+
+int
+get_kmod_info(cmoduleid_t cmod, module_info_t *mod_info)
+{
+    if (cmod < 0 || cmod >= nummodules)
+	return -EINVAL;
+
+    mod_info->mod_num = modules[cmod]->id;
+
+    ia64_sn_sys_serial_get(mod_info->serial_str);
+    
+    mod_info->serial_num = ia64_sn_partition_serial_get();
+
+    return 0;
+}
diff -Nru a/arch/ia64/sn/io/sn2/pci_bus_cvlink.c b/arch/ia64/sn/io/sn2/pci_bus_cvlink.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/pci_bus_cvlink.c	Mon Feb 24 05:25:42 2003
@@ -0,0 +1,725 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <asm/sn/types.h>
+#include <asm/sn/hack.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/io.h>
+#include <asm/sn/driver.h>
+#include <asm/sn/iograph.h>
+#include <asm/param.h>
+#include <asm/sn/pio.h>
+#include <asm/sn/xtalk/xwidget.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/hcl_util.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/xtalk/xtalkaddrs.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/nodepda.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/pci/pcibr_private.h>
+#include <asm/sn/pci/pci_bus_cvlink.h>
+#include <asm/sn/simulator.h>
+#include <asm/sn/sn_cpuid.h>
+
+extern int bridge_rev_b_data_check_disable;
+
+devfs_handle_t busnum_to_pcibr_vhdl[MAX_PCI_XWIDGET];
+nasid_t busnum_to_nid[MAX_PCI_XWIDGET];
+void * busnum_to_atedmamaps[MAX_PCI_XWIDGET];
+unsigned char num_bridges;
+static int done_probing = 0;
+
+static int pci_bus_map_create(devfs_handle_t xtalk, char * io_moduleid);
+devfs_handle_t devfn_to_vertex(unsigned char busnum, unsigned int devfn);
+
+extern unsigned char Is_pic_on_this_nasid[512];
+
+extern void sn_init_irq_desc(void);
+extern void register_pcibr_intr(int irq, pcibr_intr_t intr);
+
+
+/*
+ * For the given device, initialize whether it is a PIC device.
+ */
+static void
+set_isPIC(struct sn_device_sysdata *device_sysdata)
+{
+	pciio_info_t pciio_info = pciio_info_get(device_sysdata->vhdl);
+	pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
+
+	device_sysdata->isPIC = IS_PIC_SOFT(pcibr_soft);;
+}
+
+/*
+ * pci_bus_cvlink_init() - To be called once during initialization before 
+ *	SGI IO Infrastructure init is called.
+ */
+void
+pci_bus_cvlink_init(void)
+{
+
+	extern void ioconfig_bus_init(void);
+
+	memset(busnum_to_pcibr_vhdl, 0x0, sizeof(devfs_handle_t) * MAX_PCI_XWIDGET);
+	memset(busnum_to_nid, 0x0, sizeof(nasid_t) * MAX_PCI_XWIDGET);
+
+	memset(busnum_to_atedmamaps, 0x0, sizeof(void *) * MAX_PCI_XWIDGET);
+
+	num_bridges = 0;
+
+	ioconfig_bus_init();
+}
+
+/*
+ * pci_bus_to_vertex() - Given a logical Linux Bus Number returns the associated 
+ *	pci bus vertex from the SGI IO Infrastructure.
+ */
+devfs_handle_t
+pci_bus_to_vertex(unsigned char busnum)
+{
+
+	devfs_handle_t	pci_bus = NULL;
+
+
+	/*
+	 * First get the xwidget vertex.
+	 */
+	pci_bus = busnum_to_pcibr_vhdl[busnum];
+	return(pci_bus);
+}
+
+/*
+ * devfn_to_vertex() - returns the vertex of the device given the bus, slot, 
+ *	and function numbers.
+ */
+devfs_handle_t
+devfn_to_vertex(unsigned char busnum, unsigned int devfn)
+{
+
+	int slot = 0;
+	int func = 0;
+	char	name[16];
+	devfs_handle_t  pci_bus = NULL;
+	devfs_handle_t	device_vertex = (devfs_handle_t)NULL;
+
+	/*
+	 * Go get the pci bus vertex.
+	 */
+	pci_bus = pci_bus_to_vertex(busnum);
+	if (!pci_bus) {
+		/*
+		 * During probing, the Linux pci code invents non existant
+		 * bus numbers and pci_dev structures and tries to access
+		 * them to determine existance. Don't crib during probing.
+		 */
+		if (done_probing)
+			printk("devfn_to_vertex: Invalid bus number %d given.\n", busnum);
+		return(NULL);
+	}
+
+
+	/*
+	 * Go get the slot&function vertex.
+	 * Should call pciio_slot_func_to_name() when ready.
+	 */
+	slot = PCI_SLOT(devfn);
+	func = PCI_FUNC(devfn);
+
+	/*
+	 * For a NON Multi-function card the name of the device looks like:
+	 * ../pci/1, ../pci/2 ..
+	 */
+	if (func == 0) {
+        	sprintf(name, "%d", slot);
+		if (hwgraph_traverse(pci_bus, name, &device_vertex) == 
+			GRAPH_SUCCESS) {
+			if (device_vertex) {
+				return(device_vertex);
+			}
+		}
+	}
+			
+	/*
+	 * This maybe a multifunction card.  It's names look like:
+	 * ../pci/1a, ../pci/1b, etc.
+	 */
+	sprintf(name, "%d%c", slot, 'a'+func);
+	if (hwgraph_traverse(pci_bus, name, &device_vertex) != GRAPH_SUCCESS) {
+		if (!device_vertex) {
+			return(NULL);
+		}
+	}
+
+	return(device_vertex);
+}
+
+/*
+ * For the given device, initialize the addresses for both the Device(x) Flush 
+ * Write Buffer register and the Xbow Flush Register for the port the PCI bus 
+ * is connected.
+ */
+static void
+set_flush_addresses(struct pci_dev *device_dev, 
+	struct sn_device_sysdata *device_sysdata)
+{
+	pciio_info_t pciio_info = pciio_info_get(device_sysdata->vhdl);
+	pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info);
+	pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
+    	bridge_t               *bridge = pcibr_soft->bs_base;
+	nasid_t			nasid;
+
+	/*
+	 * Get the nasid from the bridge.
+	 */
+	nasid = NASID_GET(device_sysdata->dma_buf_sync);
+	if (IS_PIC_DEVICE(device_dev)) {
+		device_sysdata->dma_buf_sync = (volatile unsigned int *)
+			&bridge->b_wr_req_buf[pciio_slot].reg;
+		device_sysdata->xbow_buf_sync = (volatile unsigned int *)
+			XBOW_PRIO_LINKREGS_PTR(NODE_SWIN_BASE(nasid, 0),
+			pcibr_soft->bs_xid);
+	} else {
+		/*
+		 * Accessing Xbridge and Xbow register when SHUB swapoper is on!.
+		 */
+		device_sysdata->dma_buf_sync = (volatile unsigned int *)
+			((uint64_t)&(bridge->b_wr_req_buf[pciio_slot].reg)^4);
+		device_sysdata->xbow_buf_sync = (volatile unsigned int *)
+			((uint64_t)(XBOW_PRIO_LINKREGS_PTR(
+			NODE_SWIN_BASE(nasid, 0), pcibr_soft->bs_xid)) ^ 4);
+	}
+
+#ifdef DEBUG
+	printk("set_flush_addresses: dma_buf_sync %p xbow_buf_sync %p\n", 
+		device_sysdata->dma_buf_sync, device_sysdata->xbow_buf_sync);
+
+printk("set_flush_addresses: dma_buf_sync\n");
+	while((volatile unsigned int )*device_sysdata->dma_buf_sync);
+printk("set_flush_addresses: xbow_buf_sync\n");
+	while((volatile unsigned int )*device_sysdata->xbow_buf_sync);
+#endif
+
+}
+
+/*
+ * Most drivers currently do not properly tell the arch specific pci dma
+ * interfaces whether they can handle A64. Here is where we privately
+ * keep track of this.
+ */
+static void __init
+set_sn_pci64(struct pci_dev *dev)
+{
+	unsigned short vendor = dev->vendor;
+	unsigned short device = dev->device;
+
+	if (vendor == PCI_VENDOR_ID_QLOGIC) {
+		if ((device == PCI_DEVICE_ID_QLOGIC_ISP2100) ||
+				(device == PCI_DEVICE_ID_QLOGIC_ISP2200)) {
+			SET_PCIA64(dev);
+			return;
+		}
+	}
+
+	if (vendor == PCI_VENDOR_ID_SGI) {
+		if (device == PCI_DEVICE_ID_SGI_IOC3) {
+			SET_PCIA64(dev);
+			return;
+		}
+	}
+
+}
+
+/*
+ * sn_pci_fixup() - This routine is called when platform_pci_fixup() is 
+ *	invoked at the end of pcibios_init() to link the Linux pci 
+ *	infrastructure to SGI IO Infrasturcture - ia64/kernel/pci.c
+ *
+ *	Other platform specific fixup can also be done here.
+ */
+void
+sn_pci_fixup(int arg)
+{
+	struct list_head *ln;
+	struct pci_bus *pci_bus = NULL;
+	struct pci_dev *device_dev = NULL;
+	struct sn_widget_sysdata *widget_sysdata;
+	struct sn_device_sysdata *device_sysdata;
+	pciio_intr_t intr_handle;
+	int cpuid, bit;
+	devfs_handle_t device_vertex;
+	pciio_intr_line_t lines;
+	extern void sn_pci_find_bios(void);
+	extern int numnodes;
+	int cnode;
+	extern void io_sh_swapper(int, int);
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		if ( !Is_pic_on_this_nasid[cnodeid_to_nasid(cnode)] )
+			io_sh_swapper((cnodeid_to_nasid(cnode)), 0);
+	}
+
+	if (arg == 0) {
+#ifdef CONFIG_PROC_FS
+		extern void register_sn_procfs(void);
+#endif
+
+		sn_init_irq_desc();
+		sn_pci_find_bios();
+		for (cnode = 0; cnode < numnodes; cnode++) {
+			extern void intr_init_vecblk(nodepda_t *npda, cnodeid_t, int);
+			intr_init_vecblk(NODEPDA(cnode), cnode, 0);
+		} 
+
+		/*
+		 * When we return to generic Linux, Swapper is always on ..
+		 */
+		for (cnode = 0; cnode < numnodes; cnode++) {
+			if ( !Is_pic_on_this_nasid[cnodeid_to_nasid(cnode)] )
+				io_sh_swapper((cnodeid_to_nasid(cnode)), 1);
+		}
+#ifdef CONFIG_PROC_FS
+		register_sn_procfs();
+#endif
+		return;
+	}
+
+
+	done_probing = 1;
+
+	/*
+	 * Initialize the pci bus vertex in the pci_bus struct.
+	 */
+	for( ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
+		pci_bus = pci_bus_b(ln);
+		widget_sysdata = kmalloc(sizeof(struct sn_widget_sysdata), 
+					GFP_KERNEL);
+		widget_sysdata->vhdl = pci_bus_to_vertex(pci_bus->number);
+		pci_bus->sysdata = (void *)widget_sysdata;
+	}
+
+	/*
+ 	 * set the root start and end so that drivers calling check_region()
+	 * won't see a conflict
+	 */
+	ioport_resource.start  = 0xc000000000000000;
+	ioport_resource.end =    0xcfffffffffffffff;
+
+	/*
+	 * Set the root start and end for Mem Resource.
+	 */
+	iomem_resource.start = 0;
+	iomem_resource.end = 0xffffffffffffffff;
+
+	/*
+	 * Initialize the device vertex in the pci_dev struct.
+	 */
+	pci_for_each_dev(device_dev) {
+		unsigned int irq;
+		int idx;
+		u16 cmd;
+		devfs_handle_t vhdl;
+		unsigned long size;
+		extern int bit_pos_to_irq(int);
+
+		if (device_dev->vendor == PCI_VENDOR_ID_SGI &&
+				device_dev->device == PCI_DEVICE_ID_SGI_IOC3) {
+			extern void pci_fixup_ioc3(struct pci_dev *d);
+			pci_fixup_ioc3(device_dev);
+		}
+
+		/* Set the device vertex */
+
+		device_sysdata = kmalloc(sizeof(struct sn_device_sysdata),
+					GFP_KERNEL);
+		device_sysdata->vhdl = devfn_to_vertex(device_dev->bus->number, device_dev->devfn);
+		device_sysdata->isa64 = 0;
+		/*
+		 * Set the xbridge Device(X) Write Buffer Flush and Xbow Flush 
+		 * register addresses.
+		 */
+		(void) set_flush_addresses(device_dev, device_sysdata);
+
+		device_dev->sysdata = (void *) device_sysdata;
+		set_sn_pci64(device_dev);
+		set_isPIC(device_sysdata);
+
+		pci_read_config_word(device_dev, PCI_COMMAND, &cmd);
+
+		/*
+		 * Set the resources address correctly.  The assumption here 
+		 * is that the addresses in the resource structure has been
+		 * read from the card and it was set in the card by our
+		 * Infrastructure ..
+		 */
+		vhdl = device_sysdata->vhdl;
+		for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
+			size = 0;
+			size = device_dev->resource[idx].end -
+				device_dev->resource[idx].start;
+			if (size) {
+				device_dev->resource[idx].start = (unsigned long)pciio_pio_addr(vhdl, 0, PCIIO_SPACE_WIN(idx), 0, size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM);
+				device_dev->resource[idx].start |= __IA64_UNCACHED_OFFSET;
+			}
+			else
+				continue;
+
+			device_dev->resource[idx].end = 
+				device_dev->resource[idx].start + size;
+
+			if (device_dev->resource[idx].flags & IORESOURCE_IO)
+				cmd |= PCI_COMMAND_IO;
+
+			if (device_dev->resource[idx].flags & IORESOURCE_MEM)
+				cmd |= PCI_COMMAND_MEMORY;
+		}
+#if 0
+	/*
+	 * Software WAR for a Software BUG.
+	 * This is only temporary.
+	 * See PV 872791
+	 */
+
+		/*
+		 * Now handle the ROM resource ..
+		 */
+		size = device_dev->resource[PCI_ROM_RESOURCE].end -
+			device_dev->resource[PCI_ROM_RESOURCE].start;
+
+		if (size) {
+			device_dev->resource[PCI_ROM_RESOURCE].start =
+			(unsigned long) pciio_pio_addr(vhdl, 0, PCIIO_SPACE_ROM, 0, 
+				size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM);
+			device_dev->resource[PCI_ROM_RESOURCE].start |= __IA64_UNCACHED_OFFSET;
+			device_dev->resource[PCI_ROM_RESOURCE].end =
+			device_dev->resource[PCI_ROM_RESOURCE].start + size;
+		}
+#endif
+
+		/*
+		 * Update the Command Word on the Card.
+		 */
+		cmd |= PCI_COMMAND_MASTER; /* If the device doesn't support */
+					   /* bit gets dropped .. no harm */
+		pci_write_config_word(device_dev, PCI_COMMAND, cmd);
+
+		pci_read_config_byte(device_dev, PCI_INTERRUPT_PIN, (unsigned char *)&lines);
+		if (device_dev->vendor == PCI_VENDOR_ID_SGI &&
+			device_dev->device == PCI_DEVICE_ID_SGI_IOC3 ) {
+				lines = 1;
+		}
+ 
+		device_sysdata = (struct sn_device_sysdata *)device_dev->sysdata;
+		device_vertex = device_sysdata->vhdl;
+ 
+		intr_handle = pciio_intr_alloc(device_vertex, NULL, lines, device_vertex);
+
+		bit = intr_handle->pi_irq;
+		cpuid = intr_handle->pi_cpu;
+		irq = bit;
+		irq = irq + (cpuid << 8);
+		pciio_intr_connect(intr_handle, (intr_func_t)0, (intr_arg_t)0);
+		device_dev->irq = irq;
+		register_pcibr_intr(irq, (pcibr_intr_t)intr_handle);
+#ifdef ajmtestintr
+		{
+			int slot = PCI_SLOT(device_dev->devfn);
+			static int timer_set = 0;
+			pcibr_intr_t	pcibr_intr = (pcibr_intr_t)intr_handle;
+			pcibr_soft_t	pcibr_soft = pcibr_intr->bi_soft;
+			extern void intr_test_handle_intr(int, void*, struct pt_regs *);
+
+			if (!timer_set) {
+				intr_test_set_timer();
+				timer_set = 1;
+			}
+			intr_test_register_irq(irq, pcibr_soft, slot);
+			request_irq(irq, intr_test_handle_intr,0,NULL, NULL);
+		}
+#endif
+
+	}
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		if ( !Is_pic_on_this_nasid[cnodeid_to_nasid(cnode)] )
+			io_sh_swapper((cnodeid_to_nasid(cnode)), 1);
+	}
+}
+
+/*
+ * linux_bus_cvlink() Creates a link between the Linux PCI Bus number 
+ *	to the actual hardware component that it represents:
+ *	/dev/hw/linux/busnum/0 -> ../../../hw/module/001c01/slab/0/Ibrick/xtalk/15/pci
+ *
+ *	The bus vertex, when called to devfs_generate_path() returns:
+ *		hw/module/001c01/slab/0/Ibrick/xtalk/15/pci
+ *		hw/module/001c01/slab/1/Pbrick/xtalk/12/pci-x/0
+ *		hw/module/001c01/slab/1/Pbrick/xtalk/12/pci-x/1
+ */
+void
+linux_bus_cvlink(void)
+{
+	char name[8];
+	int index;
+	
+	for (index=0; index < MAX_PCI_XWIDGET; index++) {
+		if (!busnum_to_pcibr_vhdl[index])
+			continue;
+
+		sprintf(name, "%x", index);
+		(void) hwgraph_edge_add(linux_busnum, busnum_to_pcibr_vhdl[index], 
+				name);
+	}
+}
+
+/*
+ * pci_bus_map_create() - Called by pci_bus_to_hcl_cvlink() to finish the job.
+ *
+ *	Linux PCI Bus numbers are assigned from lowest module_id numbers
+ *	(rack/slot etc.) starting from HUB_WIDGET_ID_MAX down to 
+ *	HUB_WIDGET_ID_MIN:
+ *		widgetnum 15 gets lower Bus Number than widgetnum 14 etc.
+ *
+ *	Given 2 modules 001c01 and 001c02 we get the following mappings:
+ *		001c01, widgetnum 15 = Bus number 0
+ *		001c01, widgetnum 14 = Bus number 1
+ *		001c02, widgetnum 15 = Bus number 3
+ *		001c02, widgetnum 14 = Bus number 4
+ *		etc.
+ *
+ * The rational for starting Bus Number 0 with Widget number 15 is because 
+ * the system boot disks are always connected via Widget 15 Slot 0 of the 
+ * I-brick.  Linux creates /dev/sd* devices(naming) strating from Bus Number 0 
+ * Therefore, /dev/sda1 will be the first disk, on Widget 15 of the lowest 
+ * module id(Master Cnode) of the system.
+ *	
+ */
+static int 
+pci_bus_map_create(devfs_handle_t xtalk, char * io_moduleid)
+{
+
+	devfs_handle_t master_node_vertex = NULL;
+	devfs_handle_t xwidget = NULL;
+	devfs_handle_t pci_bus = NULL;
+	hubinfo_t hubinfo = NULL;
+	xwidgetnum_t widgetnum;
+	char pathname[128];
+	graph_error_t rv;
+	int bus;
+	int basebus_num;
+	int bus_number;
+
+	/*
+	 * Loop throught this vertex and get the Xwidgets ..
+	 */
+
+
+	/* PCI devices */
+
+	for (widgetnum = HUB_WIDGET_ID_MAX; widgetnum >= HUB_WIDGET_ID_MIN; widgetnum--) {
+		sprintf(pathname, "%d", widgetnum);
+		xwidget = NULL;
+		
+		/*
+		 * Example - /hw/module/001c16/Pbrick/xtalk/8 is the xwidget
+		 *	     /hw/module/001c16/Pbrick/xtalk/8/pci/1 is device
+		 */
+		rv = hwgraph_traverse(xtalk, pathname, &xwidget);
+		if ( (rv != GRAPH_SUCCESS) ) {
+			if (!xwidget) {
+				continue;
+			}
+		}
+
+		sprintf(pathname, "%d/"EDGE_LBL_PCI, widgetnum);
+		pci_bus = NULL;
+		if (hwgraph_traverse(xtalk, pathname, &pci_bus) != GRAPH_SUCCESS)
+			if (!pci_bus) {
+				continue;
+}
+
+		/*
+		 * Assign the correct bus number and also the nasid of this 
+		 * pci Xwidget.
+		 * 
+		 * Should not be any race here ...
+		 */
+		num_bridges++;
+		busnum_to_pcibr_vhdl[num_bridges - 1] = pci_bus;
+
+		/*
+		 * Get the master node and from there get the NASID.
+		 */
+		master_node_vertex = device_master_get(xwidget);
+		if (!master_node_vertex) {
+			printk("WARNING: pci_bus_map_create: Unable to get .master for vertex 0x%p\n", (void *)xwidget);
+		}
+	
+		hubinfo_get(master_node_vertex, &hubinfo);
+		if (!hubinfo) {
+			printk("WARNING: pci_bus_map_create: Unable to get hubinfo for master node vertex 0x%p\n", (void *)master_node_vertex);
+			return(1);
+		} else {
+			busnum_to_nid[num_bridges - 1] = hubinfo->h_nasid;
+		}
+
+		/*
+		 * Pre assign DMA maps needed for 32 Bits Page Map DMA.
+		 */
+		busnum_to_atedmamaps[num_bridges - 1] = (void *) kmalloc(
+			sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS, GFP_KERNEL);
+		if (!busnum_to_atedmamaps[num_bridges - 1])
+			printk("WARNING: pci_bus_map_create: Unable to precreate ATE DMA Maps for busnum %d vertex 0x%p\n", num_bridges - 1, (void *)xwidget);
+
+		memset(busnum_to_atedmamaps[num_bridges - 1], 0x0, 
+			sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS);
+
+	}
+
+	/*
+	 * PCIX devices
+	 * We number busses differently for PCI-X devices.
+	 * We start from Lowest Widget on up ..
+	 */
+
+        (void) ioconfig_get_busnum((char *)io_moduleid, &basebus_num);
+
+	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
+
+		/* Do both buses */
+		for ( bus = 0; bus < 2; bus++ ) {
+			sprintf(pathname, "%d", widgetnum);
+			xwidget = NULL;
+			
+			/*
+			 * Example - /hw/module/001c16/Pbrick/xtalk/8 is the xwidget
+			 *	     /hw/module/001c16/Pbrick/xtalk/8/pci-x/0 is the bus
+			 *	     /hw/module/001c16/Pbrick/xtalk/8/pci-x/0/1 is device
+			 */
+			rv = hwgraph_traverse(xtalk, pathname, &xwidget);
+			if ( (rv != GRAPH_SUCCESS) ) {
+				if (!xwidget) {
+					continue;
+				}
+			}
+	
+			if ( bus == 0 )
+				sprintf(pathname, "%d/"EDGE_LBL_PCIX_0, widgetnum);
+			else
+				sprintf(pathname, "%d/"EDGE_LBL_PCIX_1, widgetnum);
+			pci_bus = NULL;
+			if (hwgraph_traverse(xtalk, pathname, &pci_bus) != GRAPH_SUCCESS)
+				if (!pci_bus) {
+					continue;
+				}
+	
+			/*
+			 * Assign the correct bus number and also the nasid of this 
+			 * pci Xwidget.
+			 * 
+			 * Should not be any race here ...
+			 */
+			bus_number = basebus_num + bus + io_brick_map_widget(MODULE_PXBRICK, widgetnum);
+#ifdef DEBUG
+			printk("bus_number %d basebus_num %d bus %d io %d\n", 
+				bus_number, basebus_num, bus, 
+				io_brick_map_widget(MODULE_PXBRICK, widgetnum));
+#endif
+			busnum_to_pcibr_vhdl[bus_number] = pci_bus;
+	
+			/*
+			 * Pre assign DMA maps needed for 32 Bits Page Map DMA.
+			 */
+			busnum_to_atedmamaps[bus_number] = (void *) kmalloc(
+				sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS, GFP_KERNEL);
+			if (!busnum_to_atedmamaps[bus_number])
+				printk("WARNING: pci_bus_map_create: Unable to precreate ATE DMA Maps for busnum %d vertex 0x%p\n", num_bridges - 1, (void *)xwidget);
+	
+			memset(busnum_to_atedmamaps[bus_number], 0x0, 
+				sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS);
+		}
+	}
+
+        return(0);
+}
+
+/*
+ * pci_bus_to_hcl_cvlink() - This routine is called after SGI IO Infrastructure   
+ *      initialization has completed to set up the mappings between Xbridge
+ *      and logical pci bus numbers.  We also set up the NASID for each of these
+ *      xbridges.
+ *
+ *      Must be called before pci_init() is invoked.
+ */
+int
+pci_bus_to_hcl_cvlink(void) 
+{
+
+	devfs_handle_t devfs_hdl = NULL;
+	devfs_handle_t xtalk = NULL;
+	int rv = 0;
+	char name[256];
+	char tmp_name[256];
+	int i, ii;
+
+	/*
+	 * Figure out which IO Brick is connected to the Compute Bricks.
+	 */
+	for (i = 0; i < nummodules; i++) {
+		extern int iomoduleid_get(nasid_t);
+		moduleid_t iobrick_id;
+		nasid_t nasid = -1;
+		int nodecnt;
+		int n = 0;
+
+		nodecnt = modules[i]->nodecnt;
+		for ( n = 0; n < nodecnt; n++ ) {
+			nasid = cnodeid_to_nasid(modules[i]->nodes[n]);
+			iobrick_id = iomoduleid_get(nasid);
+			if ((int)iobrick_id > 0) { /* Valid module id */
+				char name[12];
+				memset(name, 0, 12);
+				format_module_id((char *)&(modules[i]->io[n].moduleid), iobrick_id, MODULE_FORMAT_BRIEF);
+			}
+		}
+	}
+				
+	devfs_hdl = hwgraph_path_to_vertex("/dev/hw/module");
+	for (i = 0; i < nummodules ; i++) {
+		for ( ii = 0; ii < 2 ; ii++ ) {
+			memset(name, 0, 256);
+			memset(tmp_name, 0, 256);
+			format_module_id(name, modules[i]->id, MODULE_FORMAT_BRIEF);
+			sprintf(tmp_name, "/slab/%d/Pbrick/xtalk", geo_slab(modules[i]->geoid[ii]));
+			strcat(name, tmp_name);
+			xtalk = NULL;
+			rv = hwgraph_edge_get(devfs_hdl, name, &xtalk);
+			pci_bus_map_create(xtalk, (char *)&(modules[i]->io[ii].moduleid));
+		}
+	}
+
+	/*
+	 * Create the Linux PCI bus number vertex link.
+	 */
+	(void)linux_bus_cvlink();
+	(void)ioconfig_bus_new_entries();
+
+	return(0);
+}
diff -Nru a/arch/ia64/sn/io/sn2/pcibr/Makefile b/arch/ia64/sn/io/sn2/pcibr/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/pcibr/Makefile	Mon Feb 24 05:40:54 2003
@@ -0,0 +1,19 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2002-2003 Silicon Graphics, Inc.  All Rights Reserved.
+#
+# Makefile for the sn2 specific pci bridge routines.
+
+EXTRA_CFLAGS    := -DLITTLE_ENDIAN
+
+ifdef CONFIG_IA64_SGI_SN2
+EXTRA_CFLAGS    += -DSHUB_SWAP_WAR
+endif
+
+obj-$(CONFIG_IA64_SGI_SN2)	+= pcibr_dvr.o pcibr_ate.o pcibr_config.o \
+                                   pcibr_dvr.o pcibr_hints.o \
+				   pcibr_intr.o pcibr_rrb.o pcibr_slot.o \
+				   pcibr_error.o
diff -Nru a/arch/ia64/sn/io/sn2/pciio.c b/arch/ia64/sn/io/sn2/pciio.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/pciio.c	Mon Feb 24 05:30:35 2003
@@ -0,0 +1,1877 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#define	USRPCI	0
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/xtalk/xbow.h>	/* Must be before iograph.h to get MAX_PORT_NUM */
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/hcl_util.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/pci/bridge.h>
+#include <asm/sn/ioerror_handling.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/pci/pciio_private.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/io.h>
+#include <asm/sn/pci/pci_bus_cvlink.h>
+#include <asm/sn/ate_utils.h>
+#include <asm/sn/simulator.h>
+
+#ifdef __ia64
+#define rmallocmap atemapalloc
+#define rmfreemap atemapfree
+#define rmfree atefree
+#define rmalloc atealloc
+#endif
+
+#define DEBUG_PCIIO
+#undef DEBUG_PCIIO	/* turn this on for yet more console output */
+
+
+#define GET_NEW(ptr)	(ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL))
+#define DO_DEL(ptr)	(kfree(ptr))
+
+char                    pciio_info_fingerprint[] = "pciio_info";
+
+cdl_p                   pciio_registry = NULL;
+
+int
+badaddr_val(volatile void *addr, int len, volatile void *ptr)
+{
+	int ret = 0;
+	volatile void *new_addr;
+
+	switch (len) {
+		case 4:
+			new_addr = (void *) addr;
+			ret = ia64_sn_probe_io_slot((long)new_addr, len, (void *)ptr);
+			break;
+		default:
+			printk(KERN_WARNING "badaddr_val given len %x but supports len of 4 only\n", len);
+	}
+
+	if (ret < 0)
+		panic("badaddr_val: unexpected status (%d) in probing", ret);
+	return(ret);
+
+}
+
+
+nasid_t
+get_console_nasid(void)
+{
+	extern nasid_t console_nasid;
+	extern nasid_t master_baseio_nasid;
+
+	if (console_nasid < 0) {
+		console_nasid = ia64_sn_get_console_nasid();
+		if (console_nasid < 0) {
+// ZZZ What do we do if we don't get a console nasid on the hardware????
+			if (IS_RUNNING_ON_SIMULATOR() )
+				console_nasid = master_baseio_nasid;
+		}
+	} 
+	return console_nasid;
+}
+
+nasid_t
+get_master_baseio_nasid(void)
+{
+	extern nasid_t master_baseio_nasid;
+	extern char master_baseio_wid;
+
+	if (master_baseio_nasid < 0) {
+		nasid_t tmp;
+
+		master_baseio_nasid = ia64_sn_get_master_baseio_nasid();
+
+		if ( master_baseio_nasid >= 0 ) {
+        		master_baseio_wid = WIDGETID_GET(KL_CONFIG_CH_CONS_INFO(master_baseio_nasid)->memory_base);
+		}
+	} 
+	return master_baseio_nasid;
+}
+
+int
+hub_dma_enabled(devfs_handle_t xconn_vhdl)
+{
+	return(0);
+}
+
+int
+hub_error_devenable(devfs_handle_t xconn_vhdl, int devnum, int error_code)
+{
+	return(0);
+}
+
+void
+ioerror_dump(char *name, int error_code, int error_mode, ioerror_t *ioerror)
+{
+}
+
+/******
+ ****** end hack defines ......
+ ******/
+
+
+
+
+/* =====================================================================
+ *    PCI Generic Bus Provider
+ * Implement PCI provider operations.  The pciio* layer provides a
+ * platform-independent interface for PCI devices.  This layer
+ * switches among the possible implementations of a PCI adapter.
+ */
+
+/* =====================================================================
+ *    Provider Function Location SHORTCUT
+ *
+ * On platforms with only one possible PCI provider, macros can be
+ * set up at the top that cause the table lookups and indirections to
+ * completely disappear.
+ */
+
+
+/* =====================================================================
+ *    Function Table of Contents
+ */
+
+#if !defined(DEV_FUNC)
+static pciio_provider_t *pciio_to_provider_fns(devfs_handle_t dev);
+#endif
+
+pciio_piomap_t          pciio_piomap_alloc(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, size_t, unsigned);
+void                    pciio_piomap_free(pciio_piomap_t);
+caddr_t                 pciio_piomap_addr(pciio_piomap_t, iopaddr_t, size_t);
+
+void                    pciio_piomap_done(pciio_piomap_t);
+caddr_t                 pciio_piotrans_addr(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, unsigned);
+caddr_t			pciio_pio_addr(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, pciio_piomap_t *, unsigned);
+
+iopaddr_t               pciio_piospace_alloc(devfs_handle_t, device_desc_t, pciio_space_t, size_t, size_t);
+void                    pciio_piospace_free(devfs_handle_t, pciio_space_t, iopaddr_t, size_t);
+
+pciio_dmamap_t          pciio_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned);
+void                    pciio_dmamap_free(pciio_dmamap_t);
+iopaddr_t               pciio_dmamap_addr(pciio_dmamap_t, paddr_t, size_t);
+alenlist_t              pciio_dmamap_list(pciio_dmamap_t, alenlist_t, unsigned);
+void                    pciio_dmamap_done(pciio_dmamap_t);
+iopaddr_t               pciio_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned);
+alenlist_t              pciio_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned);
+void			pciio_dmamap_drain(pciio_dmamap_t);
+void			pciio_dmaaddr_drain(devfs_handle_t, paddr_t, size_t);
+void			pciio_dmalist_drain(devfs_handle_t, alenlist_t);
+iopaddr_t               pciio_dma_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, pciio_dmamap_t *, unsigned);
+
+pciio_intr_t            pciio_intr_alloc(devfs_handle_t, device_desc_t, pciio_intr_line_t, devfs_handle_t);
+void                    pciio_intr_free(pciio_intr_t);
+int                     pciio_intr_connect(pciio_intr_t, intr_func_t, intr_arg_t);
+void                    pciio_intr_disconnect(pciio_intr_t);
+devfs_handle_t            pciio_intr_cpu_get(pciio_intr_t);
+
+void			pciio_slot_func_to_name(char *, pciio_slot_t, pciio_function_t);
+
+void                    pciio_provider_startup(devfs_handle_t);
+void                    pciio_provider_shutdown(devfs_handle_t);
+
+pciio_endian_t          pciio_endian_set(devfs_handle_t, pciio_endian_t, pciio_endian_t);
+pciio_priority_t        pciio_priority_set(devfs_handle_t, pciio_priority_t);
+devfs_handle_t            pciio_intr_dev_get(pciio_intr_t);
+
+devfs_handle_t            pciio_pio_dev_get(pciio_piomap_t);
+pciio_slot_t            pciio_pio_slot_get(pciio_piomap_t);
+pciio_space_t           pciio_pio_space_get(pciio_piomap_t);
+iopaddr_t               pciio_pio_pciaddr_get(pciio_piomap_t);
+ulong                   pciio_pio_mapsz_get(pciio_piomap_t);
+caddr_t                 pciio_pio_kvaddr_get(pciio_piomap_t);
+
+devfs_handle_t            pciio_dma_dev_get(pciio_dmamap_t);
+pciio_slot_t            pciio_dma_slot_get(pciio_dmamap_t);
+
+pciio_info_t            pciio_info_chk(devfs_handle_t);
+pciio_info_t            pciio_info_get(devfs_handle_t);
+void                    pciio_info_set(devfs_handle_t, pciio_info_t);
+devfs_handle_t            pciio_info_dev_get(pciio_info_t);
+pciio_slot_t            pciio_info_slot_get(pciio_info_t);
+pciio_function_t        pciio_info_function_get(pciio_info_t);
+pciio_vendor_id_t       pciio_info_vendor_id_get(pciio_info_t);
+pciio_device_id_t       pciio_info_device_id_get(pciio_info_t);
+devfs_handle_t            pciio_info_master_get(pciio_info_t);
+arbitrary_info_t        pciio_info_mfast_get(pciio_info_t);
+pciio_provider_t       *pciio_info_pops_get(pciio_info_t);
+error_handler_f	       *pciio_info_efunc_get(pciio_info_t);
+error_handler_arg_t    *pciio_info_einfo_get(pciio_info_t);
+pciio_space_t		pciio_info_bar_space_get(pciio_info_t, int);
+iopaddr_t		pciio_info_bar_base_get(pciio_info_t, int);
+size_t			pciio_info_bar_size_get(pciio_info_t, int);
+iopaddr_t		pciio_info_rom_base_get(pciio_info_t);
+size_t			pciio_info_rom_size_get(pciio_info_t);
+
+void                    pciio_init(void);
+int                     pciio_attach(devfs_handle_t);
+
+void                    pciio_provider_register(devfs_handle_t, pciio_provider_t *pciio_fns);
+void                    pciio_provider_unregister(devfs_handle_t);
+pciio_provider_t       *pciio_provider_fns_get(devfs_handle_t);
+
+int                     pciio_driver_register(pciio_vendor_id_t, pciio_device_id_t, char *driver_prefix, unsigned);
+void                    pciio_driver_unregister(char *driver_prefix);
+
+devfs_handle_t            pciio_device_register(devfs_handle_t, devfs_handle_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t);
+
+void			pciio_device_unregister(devfs_handle_t);
+pciio_info_t		pciio_device_info_new(pciio_info_t, devfs_handle_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t);
+void			pciio_device_info_free(pciio_info_t);
+devfs_handle_t		pciio_device_info_register(devfs_handle_t, pciio_info_t);
+void			pciio_device_info_unregister(devfs_handle_t, pciio_info_t);
+int                     pciio_device_attach(devfs_handle_t, int);
+int			pciio_device_detach(devfs_handle_t, int);
+void                    pciio_error_register(devfs_handle_t, error_handler_f *, error_handler_arg_t);
+
+int                     pciio_reset(devfs_handle_t);
+int                     pciio_write_gather_flush(devfs_handle_t);
+int                     pciio_slot_inuse(devfs_handle_t);
+
+/* =====================================================================
+ *    Provider Function Location
+ *
+ *      If there is more than one possible provider for
+ *      this platform, we need to examine the master
+ *      vertex of the current vertex for a provider
+ *      function structure, and indirect through the
+ *      appropriately named member.
+ */
+
+#if !defined(DEV_FUNC)
+
+static pciio_provider_t *
+pciio_to_provider_fns(devfs_handle_t dev)
+{
+    pciio_info_t            card_info;
+    pciio_provider_t       *provider_fns;
+
+    /*
+     * We're called with two types of vertices, one is
+     * the bridge vertex (ends with "pci") and the other is the
+     * pci slot vertex (ends with "pci/[0-8]").  For the first type
+     * we need to get the provider from the PFUNCS label.  For
+     * the second we get it from fastinfo/c_pops.
+     */
+    provider_fns = pciio_provider_fns_get(dev);
+    if (provider_fns == NULL) {
+	card_info = pciio_info_get(dev);
+	if (card_info != NULL) {
+		provider_fns = pciio_info_pops_get(card_info);
+	}
+    }
+
+    if (provider_fns == NULL)
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+	PRINT_PANIC("%v: provider_fns == NULL", dev);
+#else
+	PRINT_PANIC("0x%p: provider_fns == NULL", (void *)dev);
+#endif
+
+    return provider_fns;
+
+}
+
+#define DEV_FUNC(dev,func)	pciio_to_provider_fns(dev)->func
+#define CAST_PIOMAP(x)		((pciio_piomap_t)(x))
+#define CAST_DMAMAP(x)		((pciio_dmamap_t)(x))
+#define CAST_INTR(x)		((pciio_intr_t)(x))
+#endif
+
+/*
+ * Many functions are not passed their vertex
+ * information directly; rather, they must
+ * dive through a resource map. These macros
+ * are available to coordinate this detail.
+ */
+#define PIOMAP_FUNC(map,func)		DEV_FUNC((map)->pp_dev,func)
+#define DMAMAP_FUNC(map,func)		DEV_FUNC((map)->pd_dev,func)
+#define INTR_FUNC(intr_hdl,func)	DEV_FUNC((intr_hdl)->pi_dev,func)
+
+/* =====================================================================
+ *          PIO MANAGEMENT
+ *
+ *      For mapping system virtual address space to
+ *      pciio space on a specified card
+ */
+
+pciio_piomap_t
+pciio_piomap_alloc(devfs_handle_t dev,	/* set up mapping for this device */
+		   device_desc_t dev_desc,	/* device descriptor */
+		   pciio_space_t space,	/* CFG, MEM, IO, or a device-decoded window */
+		   iopaddr_t addr,	/* lowest address (or offset in window) */
+		   size_t byte_count,	/* size of region containing our mappings */
+		   size_t byte_count_max,	/* maximum size of a mapping */
+		   unsigned flags)
+{					/* defined in sys/pio.h */
+    return (pciio_piomap_t) DEV_FUNC(dev, piomap_alloc)
+	(dev, dev_desc, space, addr, byte_count, byte_count_max, flags);
+}
+
+void
+pciio_piomap_free(pciio_piomap_t pciio_piomap)
+{
+    PIOMAP_FUNC(pciio_piomap, piomap_free)
+	(CAST_PIOMAP(pciio_piomap));
+}
+
+caddr_t
+pciio_piomap_addr(pciio_piomap_t pciio_piomap,	/* mapping resources */
+		  iopaddr_t pciio_addr,	/* map for this pciio address */
+		  size_t byte_count)
+{					/* map this many bytes */
+    pciio_piomap->pp_kvaddr = PIOMAP_FUNC(pciio_piomap, piomap_addr)
+	(CAST_PIOMAP(pciio_piomap), pciio_addr, byte_count);
+
+    return pciio_piomap->pp_kvaddr;
+}
+
+void
+pciio_piomap_done(pciio_piomap_t pciio_piomap)
+{
+    PIOMAP_FUNC(pciio_piomap, piomap_done)
+	(CAST_PIOMAP(pciio_piomap));
+}
+
+caddr_t
+pciio_piotrans_addr(devfs_handle_t dev,	/* translate for this device */
+		    device_desc_t dev_desc,	/* device descriptor */
+		    pciio_space_t space,	/* CFG, MEM, IO, or a device-decoded window */
+		    iopaddr_t addr,	/* starting address (or offset in window) */
+		    size_t byte_count,	/* map this many bytes */
+		    unsigned flags)
+{					/* (currently unused) */
+    return DEV_FUNC(dev, piotrans_addr)
+	(dev, dev_desc, space, addr, byte_count, flags);
+}
+
+caddr_t
+pciio_pio_addr(devfs_handle_t dev,	/* translate for this device */
+	       device_desc_t dev_desc,	/* device descriptor */
+	       pciio_space_t space,	/* CFG, MEM, IO, or a device-decoded window */
+	       iopaddr_t addr,		/* starting address (or offset in window) */
+	       size_t byte_count,	/* map this many bytes */
+	       pciio_piomap_t *mapp,	/* where to return the map pointer */
+	       unsigned flags)
+{					/* PIO flags */
+    pciio_piomap_t          map = 0;
+    int			    errfree = 0;
+    caddr_t                 res;
+
+    if (mapp) {
+	map = *mapp;			/* possible pre-allocated map */
+	*mapp = 0;			/* record "no map used" */
+    }
+
+    res = pciio_piotrans_addr
+	(dev, dev_desc, space, addr, byte_count, flags);
+    if (res)
+	return res;			/* pciio_piotrans worked */
+
+    if (!map) {
+	map = pciio_piomap_alloc
+	    (dev, dev_desc, space, addr, byte_count, byte_count, flags);
+	if (!map)
+	    return res;			/* pciio_piomap_alloc failed */
+	errfree = 1;
+    }
+
+    res = pciio_piomap_addr
+	(map, addr, byte_count);
+    if (!res) {
+	if (errfree)
+	    pciio_piomap_free(map);
+	return res;			/* pciio_piomap_addr failed */
+    }
+    if (mapp)
+	*mapp = map;			/* pass back map used */
+
+    return res;				/* pciio_piomap_addr succeeded */
+}
+
+iopaddr_t
+pciio_piospace_alloc(devfs_handle_t dev,	/* Device requiring space */
+		     device_desc_t dev_desc,	/* Device descriptor */
+		     pciio_space_t space,	/* MEM32/MEM64/IO */
+		     size_t byte_count,	/* Size of mapping */
+		     size_t align)
+{					/* Alignment needed */
+    if (align < NBPP)
+	align = NBPP;
+    return DEV_FUNC(dev, piospace_alloc)
+	(dev, dev_desc, space, byte_count, align);
+}
+
+void
+pciio_piospace_free(devfs_handle_t dev,	/* Device freeing space */
+		    pciio_space_t space,	/* Type of space        */
+		    iopaddr_t pciaddr,	/* starting address */
+		    size_t byte_count)
+{					/* Range of address   */
+    DEV_FUNC(dev, piospace_free)
+	(dev, space, pciaddr, byte_count);
+}
+
+/* =====================================================================
+ *          DMA MANAGEMENT
+ *
+ *      For mapping from pci space to system
+ *      physical space.
+ */
+
+pciio_dmamap_t
+pciio_dmamap_alloc(devfs_handle_t dev,	/* set up mappings for this device */
+		   device_desc_t dev_desc,	/* device descriptor */
+		   size_t byte_count_max,	/* max size of a mapping */
+		   unsigned flags)
+{					/* defined in dma.h */
+    return (pciio_dmamap_t) DEV_FUNC(dev, dmamap_alloc)
+	(dev, dev_desc, byte_count_max, flags);
+}
+
+void
+pciio_dmamap_free(pciio_dmamap_t pciio_dmamap)
+{
+    DMAMAP_FUNC(pciio_dmamap, dmamap_free)
+	(CAST_DMAMAP(pciio_dmamap));
+}
+
+iopaddr_t
+pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap,	/* use these mapping resources */
+		  paddr_t paddr,	/* map for this address */
+		  size_t byte_count)
+{					/* map this many bytes */
+    return DMAMAP_FUNC(pciio_dmamap, dmamap_addr)
+	(CAST_DMAMAP(pciio_dmamap), paddr, byte_count);
+}
+
+alenlist_t
+pciio_dmamap_list(pciio_dmamap_t pciio_dmamap,	/* use these mapping resources */
+		  alenlist_t alenlist,	/* map this Address/Length List */
+		  unsigned flags)
+{
+    return DMAMAP_FUNC(pciio_dmamap, dmamap_list)
+	(CAST_DMAMAP(pciio_dmamap), alenlist, flags);
+}
+
+void
+pciio_dmamap_done(pciio_dmamap_t pciio_dmamap)
+{
+    DMAMAP_FUNC(pciio_dmamap, dmamap_done)
+	(CAST_DMAMAP(pciio_dmamap));
+}
+
+iopaddr_t
+pciio_dmatrans_addr(devfs_handle_t dev,	/* translate for this device */
+		    device_desc_t dev_desc,	/* device descriptor */
+		    paddr_t paddr,	/* system physical address */
+		    size_t byte_count,	/* length */
+		    unsigned flags)
+{					/* defined in dma.h */
+    return DEV_FUNC(dev, dmatrans_addr)
+	(dev, dev_desc, paddr, byte_count, flags);
+}
+
+alenlist_t
+pciio_dmatrans_list(devfs_handle_t dev,	/* translate for this device */
+		    device_desc_t dev_desc,	/* device descriptor */
+		    alenlist_t palenlist,	/* system address/length list */
+		    unsigned flags)
+{					/* defined in dma.h */
+    return DEV_FUNC(dev, dmatrans_list)
+	(dev, dev_desc, palenlist, flags);
+}
+
+iopaddr_t
+pciio_dma_addr(devfs_handle_t dev,	/* translate for this device */
+	       device_desc_t dev_desc,	/* device descriptor */
+	       paddr_t paddr,		/* system physical address */
+	       size_t byte_count,	/* length */
+	       pciio_dmamap_t *mapp,	/* map to use, then map we used */
+	       unsigned flags)
+{					/* PIO flags */
+    pciio_dmamap_t          map = 0;
+    int			    errfree = 0;
+    iopaddr_t               res;
+
+    if (mapp) {
+	map = *mapp;			/* possible pre-allocated map */
+	*mapp = 0;			/* record "no map used" */
+    }
+
+    res = pciio_dmatrans_addr
+	(dev, dev_desc, paddr, byte_count, flags);
+    if (res)
+	return res;			/* pciio_dmatrans worked */
+
+    if (!map) {
+	map = pciio_dmamap_alloc
+	    (dev, dev_desc, byte_count, flags);
+	if (!map)
+	    return res;			/* pciio_dmamap_alloc failed */
+	errfree = 1;
+    }
+
+    res = pciio_dmamap_addr
+	(map, paddr, byte_count);
+    if (!res) {
+	if (errfree)
+	    pciio_dmamap_free(map);
+	return res;			/* pciio_dmamap_addr failed */
+    }
+    if (mapp)
+	*mapp = map;			/* pass back map used */
+
+    return res;				/* pciio_dmamap_addr succeeded */
+}
+
+void
+pciio_dmamap_drain(pciio_dmamap_t map)
+{
+    DMAMAP_FUNC(map, dmamap_drain)
+	(CAST_DMAMAP(map));
+}
+
+void
+pciio_dmaaddr_drain(devfs_handle_t dev, paddr_t addr, size_t size)
+{
+    DEV_FUNC(dev, dmaaddr_drain)
+	(dev, addr, size);
+}
+
+void
+pciio_dmalist_drain(devfs_handle_t dev, alenlist_t list)
+{
+    DEV_FUNC(dev, dmalist_drain)
+	(dev, list);
+}
+
+/* =====================================================================
+ *          INTERRUPT MANAGEMENT
+ *
+ *      Allow crosstalk devices to establish interrupts
+ */
+
+/*
+ * Allocate resources required for an interrupt as specified in intr_desc.
+ * Return resource handle in intr_hdl.
+ */
+pciio_intr_t
+pciio_intr_alloc(devfs_handle_t dev,	/* which Crosstalk device */
+		 device_desc_t dev_desc,	/* device descriptor */
+		 pciio_intr_line_t lines,	/* INTR line(s) to attach */
+		 devfs_handle_t owner_dev)
+{					/* owner of this interrupt */
+    return (pciio_intr_t) DEV_FUNC(dev, intr_alloc)
+	(dev, dev_desc, lines, owner_dev);
+}
+
+/*
+ * Free resources consumed by intr_alloc.
+ */
+void
+pciio_intr_free(pciio_intr_t intr_hdl)
+{
+    INTR_FUNC(intr_hdl, intr_free)
+	(CAST_INTR(intr_hdl));
+}
+
+/*
+ * Associate resources allocated with a previous pciio_intr_alloc call with the
+ * described handler, arg, name, etc.
+ *
+ * Returns 0 on success, returns <0 on failure.
+ */
+int
+pciio_intr_connect(pciio_intr_t intr_hdl,
+		intr_func_t intr_func, intr_arg_t intr_arg)	/* pciio intr resource handle */
+{
+    return INTR_FUNC(intr_hdl, intr_connect)
+	(CAST_INTR(intr_hdl), intr_func, intr_arg);
+}
+
+/*
+ * Disassociate handler with the specified interrupt.
+ */
+void
+pciio_intr_disconnect(pciio_intr_t intr_hdl)
+{
+    INTR_FUNC(intr_hdl, intr_disconnect)
+	(CAST_INTR(intr_hdl));
+}
+
+/*
+ * Return a hwgraph vertex that represents the CPU currently
+ * targeted by an interrupt.
+ */
+devfs_handle_t
+pciio_intr_cpu_get(pciio_intr_t intr_hdl)
+{
+    return INTR_FUNC(intr_hdl, intr_cpu_get)
+	(CAST_INTR(intr_hdl));
+}
+
+void
+pciio_slot_func_to_name(char		       *name,
+			pciio_slot_t		slot,
+			pciio_function_t	func)
+{
+    /*
+     * standard connection points:
+     *
+     * PCIIO_SLOT_NONE:	.../pci/direct
+     * PCIIO_FUNC_NONE: .../pci/<SLOT>			ie. .../pci/3
+     * multifunction:   .../pci/<SLOT><FUNC>		ie. .../pci/3c
+     */
+
+    if (slot == PCIIO_SLOT_NONE)
+	sprintf(name, EDGE_LBL_DIRECT);
+    else if (func == PCIIO_FUNC_NONE)
+	sprintf(name, "%d", slot);
+    else
+	sprintf(name, "%d%c", slot, 'a'+func);
+}
+
+/*
+ * pciio_cardinfo_get
+ *
+ * Get the pciio info structure corresponding to the
+ * specified PCI "slot" (we like it when the same index
+ * number is used for the PCI IDSEL, the REQ/GNT pair,
+ * and the interrupt line being used for INTA. We like
+ * it so much we call it the slot number).
+ */
+static pciio_info_t
+pciio_cardinfo_get(
+		      devfs_handle_t pciio_vhdl,
+		      pciio_slot_t pci_slot)
+{
+    char                    namebuf[16];
+    pciio_info_t	    info = 0;
+    devfs_handle_t	    conn;
+
+    pciio_slot_func_to_name(namebuf, pci_slot, PCIIO_FUNC_NONE);
+    if (GRAPH_SUCCESS ==
+	hwgraph_traverse(pciio_vhdl, namebuf, &conn)) {
+	info = pciio_info_chk(conn);
+	hwgraph_vertex_unref(conn);
+    }
+
+    return info;
+}
+
+
+/*
+ * pciio_error_handler:
+ * dispatch an error to the appropriate
+ * pciio connection point, or process
+ * it as a generic pci error.
+ * Yes, the first parameter is the
+ * provider vertex at the middle of
+ * the bus; we get to the pciio connect
+ * point using the ioerror widgetdev field.
+ *
+ * This function is called by the
+ * specific PCI provider, after it has figured
+ * out where on the PCI bus (including which slot,
+ * if it can tell) the error came from.
+ */
+/*ARGSUSED */
+int
+pciio_error_handler(
+		       devfs_handle_t pciio_vhdl,
+		       int error_code,
+		       ioerror_mode_t mode,
+		       ioerror_t *ioerror)
+{
+    pciio_info_t            pciio_info;
+    devfs_handle_t            pconn_vhdl;
+#if USRPCI
+    devfs_handle_t            usrpci_v;
+#endif
+    pciio_slot_t            slot;
+
+    int                     retval;
+#ifdef EHE_ENABLE
+    error_state_t	    e_state;
+#endif /* EHE_ENABLE */
+
+#if DEBUG && ERROR_DEBUG
+    printk("%v: pciio_error_handler\n", pciio_vhdl);
+#endif
+
+    IOERR_PRINTF(printk(KERN_NOTICE "%v: PCI Bus Error: Error code: %d Error mode: %d\n",
+			 pciio_vhdl, error_code, mode));
+
+    /* If there is an error handler sitting on
+     * the "no-slot" connection point, give it
+     * first crack at the error. NOTE: it is
+     * quite possible that this function may
+     * do further refining of the ioerror.
+     */
+    pciio_info = pciio_cardinfo_get(pciio_vhdl, PCIIO_SLOT_NONE);
+    if (pciio_info && pciio_info->c_efunc) {
+	pconn_vhdl = pciio_info_dev_get(pciio_info);
+
+#ifdef EHE_ENABLE
+	e_state = error_state_get(pciio_vhdl);
+
+	if (e_state == ERROR_STATE_ACTION)
+	    (void)error_state_set(pciio_vhdl, ERROR_STATE_NONE);
+
+	if (error_state_set(pconn_vhdl,e_state) == ERROR_RETURN_CODE_CANNOT_SET_STATE)
+	    return(IOERROR_UNHANDLED);
+#endif 
+
+	retval = pciio_info->c_efunc
+	    (pciio_info->c_einfo, error_code, mode, ioerror);
+	if (retval != IOERROR_UNHANDLED)
+	    return retval;
+    }
+
+    /* Is the error associated with a particular slot?
+     */
+    if (IOERROR_FIELDVALID(ioerror, widgetdev)) {
+	short widgetdev;
+	/*
+	 * NOTE : 
+	 * widgetdev is a 4byte value encoded as slot in the higher order
+	 * 2 bytes and function in the lower order 2 bytes.
+	 */
+	IOERROR_GETVALUE(widgetdev, ioerror, widgetdev);
+	slot = pciio_widgetdev_slot_get(widgetdev);
+
+	/* If this slot has an error handler,
+	 * deliver the error to it.
+	 */
+	pciio_info = pciio_cardinfo_get(pciio_vhdl, slot);
+	if (pciio_info != NULL) {
+	    if (pciio_info->c_efunc != NULL) {
+
+		pconn_vhdl = pciio_info_dev_get(pciio_info);
+
+#ifdef EHE_ENABLE
+		e_state = error_state_get(pciio_vhdl);
+
+		if (e_state == ERROR_STATE_ACTION)
+		    (void)error_state_set(pciio_vhdl, ERROR_STATE_NONE);
+
+		if (error_state_set(pconn_vhdl,e_state) ==
+		    ERROR_RETURN_CODE_CANNOT_SET_STATE)
+		    return(IOERROR_UNHANDLED);
+#endif /* EHE_ENABLE */
+
+		retval = pciio_info->c_efunc
+		    (pciio_info->c_einfo, error_code, mode, ioerror);
+		if (retval != IOERROR_UNHANDLED)
+		    return retval;
+	    }
+
+#if USRPCI
+	    /* If the USRPCI driver is available and
+	     * knows about this connection point,
+	     * deliver the error to it.
+	     *
+	     * OK to use pconn_vhdl here, even though we
+	     * have already UNREF'd it, since we know that
+	     * it is not going away.
+	     */
+	    pconn_vhdl = pciio_info_dev_get(pciio_info);
+	    if (GRAPH_SUCCESS == hwgraph_traverse(pconn_vhdl, EDGE_LBL_USRPCI, &usrpci_v)) {
+		iopaddr_t busaddr;
+		IOERROR_GETVALUE(busaddr, ioerror, busaddr);
+		retval = usrpci_error_handler (usrpci_v, error_code, busaddr);
+		hwgraph_vertex_unref(usrpci_v);
+		if (retval != IOERROR_UNHANDLED) {
+		    /*
+		     * This unref is not needed.  If this code is called often enough,
+		     * the system will crash, due to vertex reference count reaching 0,
+		     * causing vertex to be unallocated.  -jeremy
+		     * hwgraph_vertex_unref(pconn_vhdl);
+		     */
+		    return retval;
+		}
+	    }
+#endif
+	}
+    }
+
+    return (mode == MODE_DEVPROBE)
+	? IOERROR_HANDLED	/* probes are OK */
+	: IOERROR_UNHANDLED;	/* otherwise, foo! */
+}
+
+/* =====================================================================
+ *          CONFIGURATION MANAGEMENT
+ */
+
+/*
+ * Startup a crosstalk provider
+ */
+void
+pciio_provider_startup(devfs_handle_t pciio_provider)
+{
+    DEV_FUNC(pciio_provider, provider_startup)
+	(pciio_provider);
+}
+
+/*
+ * Shutdown a crosstalk provider
+ */
+void
+pciio_provider_shutdown(devfs_handle_t pciio_provider)
+{
+    DEV_FUNC(pciio_provider, provider_shutdown)
+	(pciio_provider);
+}
+
+/*
+ * Specify endianness constraints.  The driver tells us what the device
+ * does and how it would like to see things in memory.  We reply with
+ * how things will actually appear in memory.
+ */
+pciio_endian_t
+pciio_endian_set(devfs_handle_t dev,
+		 pciio_endian_t device_end,
+		 pciio_endian_t desired_end)
+{
+    ASSERT((device_end == PCIDMA_ENDIAN_BIG) || (device_end == PCIDMA_ENDIAN_LITTLE));
+    ASSERT((desired_end == PCIDMA_ENDIAN_BIG) || (desired_end == PCIDMA_ENDIAN_LITTLE));
+
+#if DEBUG
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+    printk(KERN_ALERT  "%v: pciio_endian_set is going away.\n"
+	    "\tplease use PCIIO_BYTE_STREAM or PCIIO_WORD_VALUES in your\n"
+	    "\tpciio_dmamap_alloc and pciio_dmatrans calls instead.\n",
+	    dev);
+#else
+    printk(KERN_ALERT  "0x%x: pciio_endian_set is going away.\n"
+	    "\tplease use PCIIO_BYTE_STREAM or PCIIO_WORD_VALUES in your\n"
+	    "\tpciio_dmamap_alloc and pciio_dmatrans calls instead.\n",
+	    dev);
+#endif
+#endif
+
+    return DEV_FUNC(dev, endian_set)
+	(dev, device_end, desired_end);
+}
+
+/*
+ * Specify PCI arbitration priority.
+ */
+pciio_priority_t
+pciio_priority_set(devfs_handle_t dev,
+		   pciio_priority_t device_prio)
+{
+    ASSERT((device_prio == PCI_PRIO_HIGH) || (device_prio == PCI_PRIO_LOW));
+
+    return DEV_FUNC(dev, priority_set)
+	(dev, device_prio);
+}
+
+/*
+ * Read value of configuration register
+ */
+uint64_t
+pciio_config_get(devfs_handle_t	dev,
+		 unsigned	reg,
+		 unsigned	size)
+{
+    uint64_t	value = 0;
+    unsigned	shift = 0;
+
+    /* handle accesses that cross words here,
+     * since that's common code between all
+     * possible providers.
+     */
+    while (size > 0) {
+	unsigned	biw = 4 - (reg&3);
+	if (biw > size)
+	    biw = size;
+
+	value |= DEV_FUNC(dev, config_get)
+	    (dev, reg, biw) << shift;
+
+	shift += 8*biw;
+	reg += biw;
+	size -= biw;
+    }
+    return value;
+}
+
+/*
+ * Change value of configuration register
+ */
+void
+pciio_config_set(devfs_handle_t	dev,
+		 unsigned	reg,
+		 unsigned	size,
+		 uint64_t	value)
+{
+    /* handle accesses that cross words here,
+     * since that's common code between all
+     * possible providers.
+     */
+    while (size > 0) {
+	unsigned	biw = 4 - (reg&3);
+	if (biw > size)
+	    biw = size;
+	    
+	DEV_FUNC(dev, config_set)
+	    (dev, reg, biw, value);
+	reg += biw;
+	size -= biw;
+	value >>= biw * 8;
+    }
+}
+
+/* =====================================================================
+ *          GENERIC PCI SUPPORT FUNCTIONS
+ */
+
+/*
+ * Issue a hardware reset to a card.
+ */
+int
+pciio_reset(devfs_handle_t dev)
+{
+    return DEV_FUNC(dev, reset) (dev);
+}
+
+/*
+ * flush write gather buffers
+ */
+int
+pciio_write_gather_flush(devfs_handle_t dev)
+{
+    return DEV_FUNC(dev, write_gather_flush) (dev);
+}
+
+devfs_handle_t
+pciio_intr_dev_get(pciio_intr_t pciio_intr)
+{
+    return (pciio_intr->pi_dev);
+}
+
+/****** Generic crosstalk pio interfaces ******/
+devfs_handle_t
+pciio_pio_dev_get(pciio_piomap_t pciio_piomap)
+{
+    return (pciio_piomap->pp_dev);
+}
+
+pciio_slot_t
+pciio_pio_slot_get(pciio_piomap_t pciio_piomap)
+{
+    return (pciio_piomap->pp_slot);
+}
+
+pciio_space_t
+pciio_pio_space_get(pciio_piomap_t pciio_piomap)
+{
+    return (pciio_piomap->pp_space);
+}
+
+iopaddr_t
+pciio_pio_pciaddr_get(pciio_piomap_t pciio_piomap)
+{
+    return (pciio_piomap->pp_pciaddr);
+}
+
+ulong
+pciio_pio_mapsz_get(pciio_piomap_t pciio_piomap)
+{
+    return (pciio_piomap->pp_mapsz);
+}
+
+caddr_t
+pciio_pio_kvaddr_get(pciio_piomap_t pciio_piomap)
+{
+    return (pciio_piomap->pp_kvaddr);
+}
+
+/****** Generic crosstalk dma interfaces ******/
+devfs_handle_t
+pciio_dma_dev_get(pciio_dmamap_t pciio_dmamap)
+{
+    return (pciio_dmamap->pd_dev);
+}
+
+pciio_slot_t
+pciio_dma_slot_get(pciio_dmamap_t pciio_dmamap)
+{
+    return (pciio_dmamap->pd_slot);
+}
+
+/****** Generic pci slot information interfaces ******/
+
+pciio_info_t
+pciio_info_chk(devfs_handle_t pciio)
+{
+    arbitrary_info_t        ainfo = 0;
+
+    hwgraph_info_get_LBL(pciio, INFO_LBL_PCIIO, &ainfo);
+    return (pciio_info_t) ainfo;
+}
+
+pciio_info_t
+pciio_info_get(devfs_handle_t pciio)
+{
+    pciio_info_t            pciio_info;
+
+    pciio_info = (pciio_info_t) hwgraph_fastinfo_get(pciio);
+
+#ifdef DEBUG_PCIIO
+    {
+	int pos;
+	char dname[256];
+	pos = devfs_generate_path(pciio, dname, 256);
+	printk("%s : path= %s\n", __FUNCTION__, &dname[pos]);
+    }
+#endif /* DEBUG_PCIIO */
+
+    if ((pciio_info != NULL) &&
+	(pciio_info->c_fingerprint != pciio_info_fingerprint)
+	&& (pciio_info->c_fingerprint != NULL)) {
+
+	return((pciio_info_t)-1); /* Should panic .. */
+    }
+	
+
+    return pciio_info;
+}
+
+void
+pciio_info_set(devfs_handle_t pciio, pciio_info_t pciio_info)
+{
+    if (pciio_info != NULL)
+	pciio_info->c_fingerprint = pciio_info_fingerprint;
+    hwgraph_fastinfo_set(pciio, (arbitrary_info_t) pciio_info);
+
+    /* Also, mark this vertex as a PCI slot
+     * and use the pciio_info, so pciio_info_chk
+     * can work (and be fairly efficient).
+     */
+    hwgraph_info_add_LBL(pciio, INFO_LBL_PCIIO,
+			 (arbitrary_info_t) pciio_info);
+}
+
+devfs_handle_t
+pciio_info_dev_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_vertex);
+}
+
+pciio_slot_t
+pciio_info_slot_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_slot);
+}
+
+pciio_function_t
+pciio_info_function_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_func);
+}
+
+pciio_vendor_id_t
+pciio_info_vendor_id_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_vendor);
+}
+
+pciio_device_id_t
+pciio_info_device_id_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_device);
+}
+
+devfs_handle_t
+pciio_info_master_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_master);
+}
+
+arbitrary_info_t
+pciio_info_mfast_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_mfast);
+}
+
+pciio_provider_t       *
+pciio_info_pops_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_pops);
+}
+
+error_handler_f	       *
+pciio_info_efunc_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_efunc);
+}
+
+error_handler_arg_t    *
+pciio_info_einfo_get(pciio_info_t pciio_info)
+{
+    return (pciio_info->c_einfo);
+}
+
+pciio_space_t
+pciio_info_bar_space_get(pciio_info_t info, int win)
+{
+    return info->c_window[win].w_space;
+}
+
+iopaddr_t
+pciio_info_bar_base_get(pciio_info_t info, int win)
+{
+    return info->c_window[win].w_base;
+}
+
+size_t
+pciio_info_bar_size_get(pciio_info_t info, int win)
+{
+    return info->c_window[win].w_size;
+}
+
+iopaddr_t
+pciio_info_rom_base_get(pciio_info_t info)
+{
+    return info->c_rbase;
+}
+
+size_t
+pciio_info_rom_size_get(pciio_info_t info)
+{
+    return info->c_rsize;
+}
+
+
+/* =====================================================================
+ *          GENERIC PCI INITIALIZATION FUNCTIONS
+ */
+
+/*
+ *    pciioinit: called once during device driver
+ *      initializtion if this driver is configured into
+ *      the system.
+ */
+void
+pciio_init(void)
+{
+    cdl_p                   cp;
+
+#if DEBUG && ATTACH_DEBUG
+    printf("pciio_init\n");
+#endif
+    /* Allocate the registry.
+     * We might already have one.
+     * If we don't, go get one.
+     * MPness: someone might have
+     * set one up for us while we
+     * were not looking; use an atomic
+     * compare-and-swap to commit to
+     * using the new registry if and
+     * only if nobody else did first.
+     * If someone did get there first,
+     * toss the one we allocated back
+     * into the pool.
+     */
+    if (pciio_registry == NULL) {
+	cp = cdl_new(EDGE_LBL_PCI, "vendor", "device");
+	if (!compare_and_swap_ptr((void **) &pciio_registry, NULL, (void *) cp)) {
+	    cdl_del(cp);
+	}
+    }
+    ASSERT(pciio_registry != NULL);
+}
+
+/*
+ *    pciioattach: called for each vertex in the graph
+ *      that is a PCI provider.
+ */
+/*ARGSUSED */
+int
+pciio_attach(devfs_handle_t pciio)
+{
+#if DEBUG && ATTACH_DEBUG
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+    printk("%v: pciio_attach\n", pciio);
+#else
+    printk("0x%x: pciio_attach\n", pciio);
+#endif
+#endif
+    return 0;
+}
+
+/*
+ * Associate a set of pciio_provider functions with a vertex.
+ */
+void
+pciio_provider_register(devfs_handle_t provider, pciio_provider_t *pciio_fns)
+{
+    hwgraph_info_add_LBL(provider, INFO_LBL_PFUNCS, (arbitrary_info_t) pciio_fns);
+}
+
+/*
+ * Disassociate a set of pciio_provider functions with a vertex.
+ */
+void
+pciio_provider_unregister(devfs_handle_t provider)
+{
+    arbitrary_info_t        ainfo;
+
+    hwgraph_info_remove_LBL(provider, INFO_LBL_PFUNCS, (long *) &ainfo);
+}
+
+/*
+ * Obtain a pointer to the pciio_provider functions for a specified Crosstalk
+ * provider.
+ */
+pciio_provider_t       *
+pciio_provider_fns_get(devfs_handle_t provider)
+{
+    arbitrary_info_t        ainfo = 0;
+
+    (void) hwgraph_info_get_LBL(provider, INFO_LBL_PFUNCS, &ainfo);
+    return (pciio_provider_t *) ainfo;
+}
+
+/*ARGSUSED4 */
+int
+pciio_driver_register(
+			 pciio_vendor_id_t vendor_id,
+			 pciio_device_id_t device_id,
+			 char *driver_prefix,
+			 unsigned flags)
+{
+    /* a driver's init routine might call
+     * pciio_driver_register before the
+     * system calls pciio_init; so we
+     * make the init call ourselves here.
+     */
+    if (pciio_registry == NULL)
+	pciio_init();
+
+    return cdl_add_driver(pciio_registry,
+			  vendor_id, device_id,
+			  driver_prefix, flags, NULL);
+}
+
+/*
+ * Remove an initialization function.
+ */
+void
+pciio_driver_unregister(
+			   char *driver_prefix)
+{
+    /* before a driver calls unregister,
+     * it must have called register; so
+     * we can assume we have a registry here.
+     */
+    ASSERT(pciio_registry != NULL);
+
+    cdl_del_driver(pciio_registry, driver_prefix, NULL);
+}
+
+/* 
+ * Set the slot status for a device supported by the 
+ * driver being registered.
+ */
+void
+pciio_driver_reg_callback(
+                           devfs_handle_t pconn_vhdl,
+			   int key1,
+			   int key2,
+                           int error)
+{
+}
+
+/* 
+ * Set the slot status for a device supported by the 
+ * driver being unregistered.
+ */
+void
+pciio_driver_unreg_callback(
+                           devfs_handle_t pconn_vhdl,
+			   int key1,
+			   int key2,
+                           int error)
+{
+}
+
+/*
+ * Call some function with each vertex that
+ * might be one of this driver's attach points.
+ */
+void
+pciio_iterate(char *driver_prefix,
+	      pciio_iter_f * func)
+{
+    /* a driver's init routine might call
+     * pciio_iterate before the
+     * system calls pciio_init; so we
+     * make the init call ourselves here.
+     */
+    if (pciio_registry == NULL)
+	pciio_init();
+
+    ASSERT(pciio_registry != NULL);
+
+    cdl_iterate(pciio_registry, driver_prefix, (cdl_iter_f *) func);
+}
+
+devfs_handle_t
+pciio_device_register(
+		devfs_handle_t connectpt,	/* vertex for /hw/.../pciio/%d */
+		devfs_handle_t master,	/* card's master ASIC (PCI provider) */
+		pciio_slot_t slot,	/* card's slot */
+		pciio_function_t func,	/* card's func */
+		pciio_vendor_id_t vendor_id,
+		pciio_device_id_t device_id)
+{
+    return pciio_device_info_register
+	(connectpt, pciio_device_info_new (NULL, master, slot, func,
+					   vendor_id, device_id));
+}
+
+void
+pciio_device_unregister(devfs_handle_t pconn)
+{
+    DEV_FUNC(pconn,device_unregister)(pconn);
+}
+
+pciio_info_t
+pciio_device_info_new(
+		pciio_info_t pciio_info,
+		devfs_handle_t master,
+		pciio_slot_t slot,
+		pciio_function_t func,
+		pciio_vendor_id_t vendor_id,
+		pciio_device_id_t device_id)
+{
+    if (!pciio_info)
+	GET_NEW(pciio_info);
+    ASSERT(pciio_info != NULL);
+
+    pciio_info->c_slot = slot;
+    pciio_info->c_func = func;
+    pciio_info->c_vendor = vendor_id;
+    pciio_info->c_device = device_id;
+    pciio_info->c_master = master;
+    pciio_info->c_mfast = hwgraph_fastinfo_get(master);
+    pciio_info->c_pops = pciio_provider_fns_get(master);
+    pciio_info->c_efunc = 0;
+    pciio_info->c_einfo = 0;
+
+    return pciio_info;
+}
+
+void
+pciio_device_info_free(pciio_info_t pciio_info)
+{
+    /* NOTE : pciio_info is a structure within the pcibr_info
+     *	      and not a pointer to memory allocated on the heap !!
+     */
+    BZERO((char *)pciio_info,sizeof(pciio_info));
+}
+
+devfs_handle_t
+pciio_device_info_register(
+		devfs_handle_t connectpt,		/* vertex at center of bus */
+		pciio_info_t pciio_info)	/* details about the connectpt */
+{
+    char		name[32];
+    devfs_handle_t	pconn;
+    int device_master_set(devfs_handle_t, devfs_handle_t);
+
+    pciio_slot_func_to_name(name,
+			    pciio_info->c_slot,
+			    pciio_info->c_func);
+
+    if (GRAPH_SUCCESS !=
+	hwgraph_path_add(connectpt, name, &pconn))
+	return pconn;
+
+    pciio_info->c_vertex = pconn;
+    pciio_info_set(pconn, pciio_info);
+#ifdef DEBUG_PCIIO
+    {
+	int pos;
+	char dname[256];
+	pos = devfs_generate_path(pconn, dname, 256);
+	printk("%s : pconn path= %s \n", __FUNCTION__, &dname[pos]);
+    }
+#endif /* DEBUG_PCIIO */
+
+    /*
+     * create link to our pci provider
+     */
+
+    device_master_set(pconn, pciio_info->c_master);
+
+#if USRPCI
+    /*
+     * Call into usrpci provider to let it initialize for
+     * the given slot.
+     */
+    if (pciio_info->c_slot != PCIIO_SLOT_NONE)
+	usrpci_device_register(pconn, pciio_info->c_master, pciio_info->c_slot);
+#endif
+
+    return pconn;
+}
+
+void
+pciio_device_info_unregister(devfs_handle_t connectpt,
+			     pciio_info_t pciio_info)
+{
+    char		name[32];
+    devfs_handle_t	pconn;
+
+    if (!pciio_info)
+	return;
+
+    pciio_slot_func_to_name(name,
+			    pciio_info->c_slot,
+			    pciio_info->c_func);
+
+    hwgraph_edge_remove(connectpt,name,&pconn);
+    pciio_info_set(pconn,0);
+
+    /* Remove the link to our pci provider */
+    hwgraph_edge_remove(pconn, EDGE_LBL_MASTER, NULL);
+
+
+    hwgraph_vertex_unref(pconn);
+    hwgraph_vertex_destroy(pconn);
+    
+}
+/* Add the pci card inventory information to the hwgraph
+ */
+static void
+pciio_device_inventory_add(devfs_handle_t pconn_vhdl)
+{
+    pciio_info_t	pciio_info = pciio_info_get(pconn_vhdl);
+
+    ASSERT(pciio_info);
+    ASSERT(pciio_info->c_vertex == pconn_vhdl);
+
+    /* Donot add inventory  for non-existent devices */
+    if ((pciio_info->c_vendor == PCIIO_VENDOR_ID_NONE)	||
+	(pciio_info->c_device == PCIIO_DEVICE_ID_NONE))
+	return;
+    device_inventory_add(pconn_vhdl,INV_IOBD,INV_PCIADAP,
+			 pciio_info->c_vendor,pciio_info->c_device,
+			 pciio_info->c_slot);
+}
+
+/*ARGSUSED */
+int
+pciio_device_attach(devfs_handle_t pconn,
+		    int          drv_flags)
+{
+    pciio_info_t            pciio_info;
+    pciio_vendor_id_t       vendor_id;
+    pciio_device_id_t       device_id;
+
+
+    pciio_device_inventory_add(pconn);
+    pciio_info = pciio_info_get(pconn);
+
+    vendor_id = pciio_info->c_vendor;
+    device_id = pciio_info->c_device;
+
+    /* we don't start attaching things until
+     * all the driver init routines (including
+     * pciio_init) have been called; so we
+     * can assume here that we have a registry.
+     */
+    ASSERT(pciio_registry != NULL);
+
+    return(cdl_add_connpt(pciio_registry, vendor_id, device_id, pconn, drv_flags));
+}
+
+int
+pciio_device_detach(devfs_handle_t pconn,
+		    int          drv_flags)
+{
+    pciio_info_t            pciio_info;
+    pciio_vendor_id_t       vendor_id;
+    pciio_device_id_t       device_id;
+
+    pciio_info = pciio_info_get(pconn);
+
+    vendor_id = pciio_info->c_vendor;
+    device_id = pciio_info->c_device;
+
+    /* we don't start attaching things until
+     * all the driver init routines (including
+     * pciio_init) have been called; so we
+     * can assume here that we have a registry.
+     */
+    ASSERT(pciio_registry != NULL);
+
+    return(cdl_del_connpt(pciio_registry, vendor_id, device_id,
+		          pconn, drv_flags));
+
+}
+
+/* SN2 */
+/*
+ * Allocate (if necessary) and initialize a PCI window mapping structure.
+ */
+pciio_win_map_t
+pciio_device_win_map_new(pciio_win_map_t win_map,
+			 size_t region_size,
+			 size_t page_size)
+{
+	ASSERT((page_size & (page_size - 1)) == 0);
+	ASSERT((region_size & (page_size - 1)) == 0);
+
+	if (win_map == NULL)
+		NEW(win_map);
+
+	/*
+	 * The map array tracks the free ``pages'' in the region.  The worst
+	 * case scenario is when every other page in the region is free --
+	 * e.i. maximum fragmentation.  This leads to (max pages + 1) / 2 + 1
+	 * map entries.  The first "+1" handles the divide by 2 rounding; the
+	 * second handles the need for an end marker sentinel.
+	 */
+	win_map->wm_map = rmallocmap((region_size / page_size + 1) / 2 + 1);
+	win_map->wm_page_size = page_size;
+	ASSERT(win_map->wm_map != NULL);
+
+	return win_map;
+}
+
+/*
+ * Free resources associated with a PCI window mapping structure.
+ */
+extern void
+pciio_device_win_map_free(pciio_win_map_t win_map)
+{
+	rmfreemap(win_map->wm_map);
+	bzero(win_map, sizeof *win_map);
+}
+
+/*
+ * Populate window map with specified free range.
+ */
+void
+pciio_device_win_populate(pciio_win_map_t win_map,
+                          iopaddr_t ioaddr,
+                          size_t size)
+{
+	ASSERT((size & (win_map->wm_page_size - 1)) == 0);
+	ASSERT((ioaddr & (win_map->wm_page_size - 1)) == 0);
+
+	rmfree(win_map->wm_map,
+	       size / win_map->wm_page_size,
+	       (unsigned long)ioaddr / win_map->wm_page_size);
+	       
+}
+/*
+ * Allocate space from the specified PCI window mapping resource.  On
+ * success record information about the allocation in the supplied window
+ * allocation cookie (if non-NULL) and return the address of the allocated
+ * window.  On failure return NULL.
+ *
+ * The "size" parameter is usually from a PCI device's Base Address Register
+ * (BAR) decoder.  As such, the allocation must be aligned to be a multiple of
+ * that.  The "align" parameter acts as a ``minimum alignment'' allocation
+ * constraint.  The alignment contraint reflects system or device addressing
+ * restrictions such as the inability to share higher level ``windows''
+ * between devices, etc.  The returned PCI address allocation will be a
+ * multiple of the alignment constraint both in alignment and size.  Thus, the
+ * returned PCI address block is aligned to the maximum of the requested size
+ * and alignment.
+ */
+iopaddr_t
+pciio_device_win_alloc(pciio_win_map_t win_map,
+		       pciio_win_alloc_t win_alloc,
+		       size_t start, size_t size, size_t align)
+{
+	unsigned long base;
+
+#ifdef PIC_LATER
+	ASSERT((size & (size - 1)) == 0);
+	ASSERT((align & (align - 1)) == 0);
+
+	/*
+	 * Convert size and alignment to pages.  If size is greated than the
+	 * requested alignment, we bump the alignment up to size; otherwise
+	 * convert the size into a multiple of the alignment request.
+	 */
+	size = (size + win_map->wm_page_size - 1) / win_map->wm_page_size;
+	align = align / win_map->wm_page_size;
+	if (size > align)
+		align = size;
+	else
+		size = (size + align - 1) & ~(align - 1);
+
+	/* XXXX */
+	base = rmalloc_align(win_map->wm_map, size, align, VM_NOSLEEP);
+	if (base == RMALLOC_FAIL)
+		return((iopaddr_t)NULL);
+#else
+    int                 index_page, index_page_align;
+    int                 align_pages, size_pages;
+    int                 alloc_pages, free_pages;
+    int                 addr_align;
+
+    /* Convert PCI bus alignment from bytes to pages */
+    align_pages = align / win_map->wm_page_size;
+
+    /* Convert PCI request from bytes to pages */
+    size_pages = (size / win_map->wm_page_size) +
+                  ((size % win_map->wm_page_size) ? 1 : 0);
+
+    /* Align address with the larger of the size or the requested slot align */
+    if (size_pages > align_pages)
+        align_pages = size_pages;
+  
+    /*
+     * Avoid wasting space by aligning - 1; this will prevent crossing
+     * another alignment boundary.
+     */
+    alloc_pages = size_pages + (align_pages - 1);
+
+    /* Allocate PCI bus space in pages */
+    index_page = (int) rmalloc(win_map->wm_map,
+                               (size_t) alloc_pages);
+
+    /* Error if no PCI bus address space available */
+    if (!index_page)
+        return 0;
+
+    /* PCI bus address index starts at 0 */
+    index_page--;
+
+    /* Align the page offset as requested */
+    index_page_align = (index_page + (align_pages - 1)) -
+                       ((index_page + (align_pages - 1)) % align_pages);
+
+    free_pages = (align_pages - 1) - (index_page_align - index_page);
+
+    /* Free unused PCI bus pages adjusting the index to start at 1 */
+    rmfree(win_map->wm_map, 
+           free_pages,
+           (index_page_align + 1) + size_pages);
+
+    /* Return aligned PCI bus space in bytes */ 
+    addr_align = (index_page_align * win_map->wm_page_size); 
+    base = index_page;
+    size = alloc_pages - free_pages;
+#endif	/* PIC_LATER */
+
+	/*
+	 * If a window allocation cookie has been supplied, use it to keep
+	 * track of all the allocated space assigned to this window.
+	 */
+	if (win_alloc) {
+		win_alloc->wa_map = win_map;
+		win_alloc->wa_base = base;
+		win_alloc->wa_pages = size;
+	}
+
+	return base * win_map->wm_page_size;
+}
+
+/*
+ * Free the specified window allocation back into the PCI window mapping
+ * resource.  As noted above, we keep page addresses offset by 1 ...
+ */
+void
+pciio_device_win_free(pciio_win_alloc_t win_alloc)
+{
+	if (win_alloc->wa_pages)
+		rmfree(win_alloc->wa_map->wm_map,
+		       win_alloc->wa_pages,
+		       win_alloc->wa_base);
+}
+
+/*
+ * pciio_error_register:
+ * arrange for a function to be called with
+ * a specified first parameter plus other
+ * information when an error is encountered
+ * and traced to the pci slot corresponding
+ * to the connection point pconn.
+ *
+ * may also be called with a null function
+ * pointer to "unregister" the error handler.
+ *
+ * NOTE: subsequent calls silently overwrite
+ * previous data for this vertex. We assume that
+ * cooperating drivers, well, cooperate ...
+ */
+void
+pciio_error_register(devfs_handle_t pconn,
+		     error_handler_f *efunc,
+		     error_handler_arg_t einfo)
+{
+    pciio_info_t            pciio_info;
+
+    pciio_info = pciio_info_get(pconn);
+    ASSERT(pciio_info != NULL);
+    pciio_info->c_efunc = efunc;
+    pciio_info->c_einfo = einfo;
+}
+
+/*
+ * Check if any device has been found in this slot, and return
+ * true or false
+ * vhdl is the vertex for the slot
+ */
+int
+pciio_slot_inuse(devfs_handle_t pconn_vhdl)
+{
+    pciio_info_t            pciio_info = pciio_info_get(pconn_vhdl);
+
+    ASSERT(pciio_info);
+    ASSERT(pciio_info->c_vertex == pconn_vhdl);
+    if (pciio_info->c_vendor) {
+	/*
+	 * Non-zero value for vendor indicate
+	 * a board being found in this slot.
+	 */
+	return 1;
+    }
+    return 0;
+}
+
+int
+pciio_dma_enabled(devfs_handle_t pconn_vhdl)
+{
+	return DEV_FUNC(pconn_vhdl, dma_enabled)(pconn_vhdl);
+}
+
+int
+pciio_info_type1_get(pciio_info_t pci_info)
+{
+	return(0);
+}
+
+
+/*
+ * These are complementary Linux interfaces that takes in a pci_dev * as the 
+ * first arguement instead of devfs_handle_t.
+ */
+iopaddr_t               snia_pciio_dmatrans_addr(struct pci_dev *, device_desc_t, paddr_t, size_t, unsigned);
+pciio_dmamap_t          snia_pciio_dmamap_alloc(struct pci_dev *, device_desc_t, size_t, unsigned);
+void                    snia_pciio_dmamap_free(pciio_dmamap_t);
+iopaddr_t               snia_pciio_dmamap_addr(pciio_dmamap_t, paddr_t, size_t);
+void                    snia_pciio_dmamap_done(pciio_dmamap_t);
+pciio_endian_t          snia_pciio_endian_set(struct pci_dev *pci_dev, pciio_endian_t device_end,
+					      pciio_endian_t desired_end);
+
+#include <linux/module.h>
+EXPORT_SYMBOL(snia_pciio_dmatrans_addr);
+EXPORT_SYMBOL(snia_pciio_dmamap_alloc);
+EXPORT_SYMBOL(snia_pciio_dmamap_free);
+EXPORT_SYMBOL(snia_pciio_dmamap_addr);
+EXPORT_SYMBOL(snia_pciio_dmamap_done);
+EXPORT_SYMBOL(snia_pciio_endian_set);
+
+int
+snia_pcibr_rrb_alloc(struct pci_dev *pci_dev,
+	int *count_vchan0,
+	int *count_vchan1)
+{
+	devfs_handle_t dev = PCIDEV_VERTEX(pci_dev);
+
+	return pcibr_rrb_alloc(dev, count_vchan0, count_vchan1);
+}
+EXPORT_SYMBOL(snia_pcibr_rrb_alloc);
+
+pciio_endian_t
+snia_pciio_endian_set(struct pci_dev *pci_dev,
+	pciio_endian_t device_end,
+	pciio_endian_t desired_end)
+{
+	devfs_handle_t dev = PCIDEV_VERTEX(pci_dev);
+	
+	return DEV_FUNC(dev, endian_set)
+		(dev, device_end, desired_end);
+}
+
+iopaddr_t
+snia_pciio_dmatrans_addr(struct pci_dev *pci_dev, /* translate for this device */
+                    device_desc_t dev_desc,     /* device descriptor */
+                    paddr_t paddr,      /* system physical address */
+                    size_t byte_count,  /* length */
+                    unsigned flags)
+{                                       /* defined in dma.h */
+
+    devfs_handle_t dev = PCIDEV_VERTEX(pci_dev);
+
+    /*
+     * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be 
+     * set.  Otherwise, it must not be set.  This applies to SN1 and SN2.
+     */
+    return DEV_FUNC(dev, dmatrans_addr)
+        (dev, dev_desc, paddr, byte_count, (IS_PIC_DEVICE(pci_dev)) ? (flags & ~PCIIO_BYTE_STREAM) : flags | PCIIO_BYTE_STREAM);
+}
+
+pciio_dmamap_t
+snia_pciio_dmamap_alloc(struct pci_dev *pci_dev,  /* set up mappings for this device */
+                   device_desc_t dev_desc,      /* device descriptor */
+                   size_t byte_count_max,       /* max size of a mapping */
+                   unsigned flags)
+{                                       /* defined in dma.h */
+
+    devfs_handle_t dev = PCIDEV_VERTEX(pci_dev);
+
+    /*
+     * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be
+     * set.  Otherwise, it must not be set.  This applies to SN1 and SN2.
+     */
+    return (pciio_dmamap_t) DEV_FUNC(dev, dmamap_alloc)
+        (dev, dev_desc, byte_count_max, (IS_PIC_DEVICE(pci_dev)) ? (flags & ~PCIIO_BYTE_STREAM) : flags | PCIIO_BYTE_STREAM);
+}
+
+void
+snia_pciio_dmamap_free(pciio_dmamap_t pciio_dmamap)
+{
+    DMAMAP_FUNC(pciio_dmamap, dmamap_free)
+        (CAST_DMAMAP(pciio_dmamap));
+}
+
+iopaddr_t
+snia_pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap,  /* use these mapping resources */
+                  paddr_t paddr,        /* map for this address */
+                  size_t byte_count)
+{                                       /* map this many bytes */
+    return DMAMAP_FUNC(pciio_dmamap, dmamap_addr)
+        (CAST_DMAMAP(pciio_dmamap), paddr, byte_count);
+}
+
+void
+snia_pciio_dmamap_done(pciio_dmamap_t pciio_dmamap)
+{
+    DMAMAP_FUNC(pciio_dmamap, dmamap_done)
+        (CAST_DMAMAP(pciio_dmamap));
+}
+
diff -Nru a/arch/ia64/sn/io/sn2/pic.c b/arch/ia64/sn/io/sn2/pic.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/pic.c	Mon Feb 24 05:30:53 2003
@@ -0,0 +1,325 @@
+/*
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/xtalk/xwidget.h>
+#include <asm/sn/pci/bridge.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/pci/pcibr_private.h>
+#include <asm/sn/pci/pci_defs.h>
+#include <asm/sn/prio.h>
+#include <asm/sn/xtalk/xbow.h>
+#include <asm/sn/ioc3.h>
+#include <asm/sn/eeprom.h>
+#include <asm/sn/io.h>
+#include <asm/sn/sn_private.h>
+
+extern char *bcopy(const char * src, char * dest, int count);
+
+
+#define PCI_BUS_NO_1 1
+
+int pic_devflag = D_MP;
+
+extern int pcibr_attach2(devfs_handle_t, bridge_t *, devfs_handle_t, int, pcibr_soft_t *);
+extern void pcibr_driver_reg_callback(devfs_handle_t, int, int, int);
+extern void pcibr_driver_unreg_callback(devfs_handle_t, int, int, int);
+
+
+void
+pic_init(void)
+{
+	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INIT, NULL, "pic_init()\n"));	
+
+	xwidget_driver_register(PIC_WIDGET_PART_NUM_BUS0,
+			    PIC_WIDGET_MFGR_NUM,
+			    "pic_",
+			    0);
+}
+
+/*
+ * copy inventory_t from conn_v to peer_conn_v
+ */
+int
+pic_bus1_inventory_dup(devfs_handle_t conn_v, devfs_handle_t peer_conn_v)
+{
+	inventory_t *pinv, *peer_pinv;
+
+	if (hwgraph_info_get_LBL(conn_v, INFO_LBL_INVENT,
+				(arbitrary_info_t *)&pinv) == GRAPH_SUCCESS)
+ {
+		NEW(peer_pinv);
+		bcopy(pinv, peer_pinv, sizeof(inventory_t));
+		if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_INVENT,
+			    (arbitrary_info_t)peer_pinv) != GRAPH_SUCCESS) {
+			DEL(peer_pinv);
+			return 0;
+		}
+		return 1;
+	}
+
+	printk("pic_bus1_inventory_dup: cannot get INFO_LBL_INVENT from 0x%lx\n ",
+								conn_v);
+	return 0;
+}
+
+/*
+ * copy xwidget_info_t from conn_v to peer_conn_v
+ */
+int
+pic_bus1_widget_info_dup(devfs_handle_t conn_v, devfs_handle_t peer_conn_v,
+							cnodeid_t xbow_peer)
+{
+	xwidget_info_t widget_info, peer_widget_info;
+	char peer_path[256];
+	char *p;
+	devfs_handle_t peer_hubv;
+	hubinfo_t peer_hub_info;
+
+	/* get the peer hub's widgetid */
+	peer_hubv = NODEPDA(xbow_peer)->node_vertex;
+	peer_hub_info = NULL;
+	hubinfo_get(peer_hubv, &peer_hub_info);
+	if (peer_hub_info == NULL)
+		return 0;
+
+	if (hwgraph_info_get_LBL(conn_v, INFO_LBL_XWIDGET,
+			(arbitrary_info_t *)&widget_info) == GRAPH_SUCCESS) {
+		NEW(peer_widget_info);
+		peer_widget_info->w_vertex = peer_conn_v;
+		peer_widget_info->w_id = widget_info->w_id;
+		peer_widget_info->w_master = peer_hubv;
+		peer_widget_info->w_masterid = peer_hub_info->h_widgetid;
+		/* structure copy */
+		peer_widget_info->w_hwid = widget_info->w_hwid;
+		peer_widget_info->w_efunc = 0;
+		peer_widget_info->w_einfo = 0;
+		peer_widget_info->w_name = kmalloc(strlen(peer_path) + 1, GFP_KERNEL);
+		strcpy(peer_widget_info->w_name, peer_path);
+
+		if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_XWIDGET,
+			(arbitrary_info_t)peer_widget_info) != GRAPH_SUCCESS) {
+				DEL(peer_widget_info);
+				return 0;
+		}
+
+		xwidget_info_set(peer_conn_v, peer_widget_info);
+
+		return 1;
+	}
+
+	printk("pic_bus1_widget_info_dup: "
+			"cannot get INFO_LBL_XWIDGET from 0x%lx\n", conn_v);
+	return 0;
+}
+
+/*
+ * If this PIC is attached to two Cbricks ("dual-ported") then
+ * attach each bus to opposite Cbricks.
+ *
+ * If successful, return a new vertex suitable for attaching the PIC bus.
+ * If not successful, return zero and both buses will attach to the
+ * vertex passed into pic_attach().
+ */
+devfs_handle_t
+pic_bus1_redist(nasid_t nasid, devfs_handle_t conn_v)
+{
+	cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid);
+	cnodeid_t xbow_peer = -1;
+	char pathname[256], peer_path[256], tmpbuf[256];
+	char *p;
+	int rc;
+	devfs_handle_t peer_conn_v;
+	int pos;
+	slabid_t slab;
+
+	if (NODEPDA(cnode)->xbow_peer >= 0) {			/* if dual-ported */
+		/* create a path for this widget on the peer Cbrick */
+		/* pcibr widget hw/module/001c11/slab/0/Pbrick/xtalk/12 */
+		/* sprintf(pathname, "%v", conn_v); */
+		xbow_peer = NASID_TO_COMPACT_NODEID(NODEPDA(cnode)->xbow_peer);
+		pos = devfs_generate_path(conn_v, tmpbuf, 256);
+		strcpy(pathname, &tmpbuf[pos]);
+		p = pathname + strlen("hw/module/001c01/slab/0/");
+
+		memset(tmpbuf, 0, 16);
+		format_module_id(tmpbuf, geo_module((NODEPDA(xbow_peer))->geoid), MODULE_FORMAT_BRIEF);
+		slab = geo_slab((NODEPDA(xbow_peer))->geoid);
+		sprintf(peer_path, "module/%s/slab/%d/%s", tmpbuf, (int)slab, p); 
+		
+		/* Look for vertex for this widget on the peer Cbrick.
+		 * Expect GRAPH_NOT_FOUND.
+		 */
+		rc = hwgraph_traverse(hwgraph_root, peer_path, &peer_conn_v);
+		if (GRAPH_SUCCESS == rc)
+			printk("pic_attach: found unexpected vertex: 0x%lx\n",
+								peer_conn_v);
+		else if (GRAPH_NOT_FOUND != rc) {
+			printk("pic_attach: hwgraph_traverse unexpectedly"
+					" returned 0x%x\n", rc);
+		} else {
+			/* try to add the widget vertex to the peer Cbrick */
+			rc = hwgraph_path_add(hwgraph_root, peer_path, &peer_conn_v);
+
+			if (GRAPH_SUCCESS != rc)
+			    printk("pic_attach: hwgraph_path_add"
+						" failed with 0x%x\n", rc);
+			else {
+			    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v,
+					"pic_bus1_redist: added vertex %v\n", peer_conn_v)); 
+
+			    /* Now hang appropiate stuff off of the new
+			     * vertex.	We bail out if we cannot add something.
+			     * In that case, we don't remove the newly added
+			     * vertex but that should be safe and we don't
+			     * really expect the additions to fail anyway.
+			     */
+#if 0
+			    if (!pic_bus1_inventory_dup(conn_v, peer_conn_v))
+					return 0;
+			    pic_bus1_device_desc_dup(conn_v, peer_conn_v);
+#endif
+			    if (!pic_bus1_widget_info_dup(conn_v, peer_conn_v, xbow_peer))
+					return 0;
+
+			    return peer_conn_v;
+			}
+		}
+	}
+	return 0;
+}
+
+
+int
+pic_attach(devfs_handle_t conn_v)
+{
+	int		rc;
+	bridge_t	*bridge0, *bridge1 = (bridge_t *)0;
+	devfs_handle_t	pcibr_vhdl0, pcibr_vhdl1 = (devfs_handle_t)0;
+	pcibr_soft_t	bus0_soft, bus1_soft = (pcibr_soft_t)0;
+	devfs_handle_t  conn_v0, conn_v1, peer_conn_v;
+
+	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach()\n"));
+
+	bridge0 = (bridge_t *) xtalk_piotrans_addr(conn_v, NULL,
+	                        0, sizeof(bridge_t), 0);
+	bridge1 = (bridge_t *)((char *)bridge0 + PIC_BUS1_OFFSET);
+
+	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v,
+		    "pic_attach: bridge0=0x%x, bridge1=0x%x\n", 
+		    bridge0, bridge1));
+
+	conn_v0 = conn_v1 = conn_v;
+
+	/* If dual-ported then split the two PIC buses across both Cbricks */
+	if (peer_conn_v = pic_bus1_redist(NASID_GET(bridge0), conn_v))
+		conn_v1 = peer_conn_v;
+
+	/*
+	 * Create the vertex for the PCI buses, which week
+	 * will also use to hold the pcibr_soft and
+	 * which will be the "master" vertex for all the
+	 * pciio connection points we will hang off it.
+	 * This needs to happen before we call nic_bridge_vertex_info
+	 * as we are some of the *_vmc functions need access to the edges.
+	 *
+	 * Opening this vertex will provide access to
+	 * the Bridge registers themselves.
+	 */
+	/* FIXME: what should the hwgraph path look like ? */
+	rc = hwgraph_path_add(conn_v0, EDGE_LBL_PCIX_0, &pcibr_vhdl0);
+	ASSERT(rc == GRAPH_SUCCESS);
+	rc = hwgraph_path_add(conn_v1, EDGE_LBL_PCIX_1, &pcibr_vhdl1);
+	ASSERT(rc == GRAPH_SUCCESS);
+
+	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v,
+		    "pic_attach: pcibr_vhdl0=%v, pcibr_vhdl1=%v\n",
+		    pcibr_vhdl0, pcibr_vhdl1));
+
+	/* register pci provider array */
+	pciio_provider_register(pcibr_vhdl0, &pci_pic_provider);
+	pciio_provider_register(pcibr_vhdl1, &pci_pic_provider);
+
+	pciio_provider_startup(pcibr_vhdl0);
+	pciio_provider_startup(pcibr_vhdl1);
+
+	pcibr_attach2(conn_v0, bridge0, pcibr_vhdl0, 0, &bus0_soft);
+	pcibr_attach2(conn_v1, bridge1, pcibr_vhdl1, 1, &bus1_soft);
+
+	/* save a pointer to the PIC's other bus's soft struct */
+        bus0_soft->bs_peers_soft = bus1_soft;
+        bus1_soft->bs_peers_soft = bus0_soft;
+        bus0_soft->bs_peers_soft = (pcibr_soft_t)0;
+
+	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v,
+		    "pic_attach: bus0_soft=0x%x, bus1_soft=0x%x\n",
+		    bus0_soft, bus1_soft));
+
+	return 0;
+}
+
+/*
+ * pci provider functions
+ *
+ * mostly in pcibr.c but if any are needed here then
+ * this might be a way to get them here.
+ */
+pciio_provider_t        pci_pic_provider =
+{
+    (pciio_piomap_alloc_f *) pcibr_piomap_alloc,
+    (pciio_piomap_free_f *) pcibr_piomap_free,
+    (pciio_piomap_addr_f *) pcibr_piomap_addr,
+    (pciio_piomap_done_f *) pcibr_piomap_done,
+    (pciio_piotrans_addr_f *) pcibr_piotrans_addr,
+    (pciio_piospace_alloc_f *) pcibr_piospace_alloc,
+    (pciio_piospace_free_f *) pcibr_piospace_free,
+
+    (pciio_dmamap_alloc_f *) pcibr_dmamap_alloc,
+    (pciio_dmamap_free_f *) pcibr_dmamap_free,
+    (pciio_dmamap_addr_f *) pcibr_dmamap_addr,
+    (pciio_dmamap_list_f *) pcibr_dmamap_list,
+    (pciio_dmamap_done_f *) pcibr_dmamap_done,
+    (pciio_dmatrans_addr_f *) pcibr_dmatrans_addr,
+    (pciio_dmatrans_list_f *) pcibr_dmatrans_list,
+    (pciio_dmamap_drain_f *) pcibr_dmamap_drain,
+    (pciio_dmaaddr_drain_f *) pcibr_dmaaddr_drain,
+    (pciio_dmalist_drain_f *) pcibr_dmalist_drain,
+
+    (pciio_intr_alloc_f *) pcibr_intr_alloc,
+    (pciio_intr_free_f *) pcibr_intr_free,
+    (pciio_intr_connect_f *) pcibr_intr_connect,
+    (pciio_intr_disconnect_f *) pcibr_intr_disconnect,
+    (pciio_intr_cpu_get_f *) pcibr_intr_cpu_get,
+
+    (pciio_provider_startup_f *) pcibr_provider_startup,
+    (pciio_provider_shutdown_f *) pcibr_provider_shutdown,
+    (pciio_reset_f *) pcibr_reset,
+    (pciio_write_gather_flush_f *) pcibr_write_gather_flush,
+    (pciio_endian_set_f *) pcibr_endian_set,
+    (pciio_priority_set_f *) pcibr_priority_set,
+    (pciio_config_get_f *) pcibr_config_get,
+    (pciio_config_set_f *) pcibr_config_set,
+    (pciio_error_devenable_f *) 0,
+    (pciio_error_extract_f *) 0,
+    (pciio_driver_reg_callback_f *) pcibr_driver_reg_callback,
+    (pciio_driver_unreg_callback_f *) pcibr_driver_unreg_callback,
+    (pciio_device_unregister_f 	*) pcibr_device_unregister,
+    (pciio_dma_enabled_f		*) pcibr_dma_enabled,
+};
diff -Nru a/arch/ia64/sn/io/sn2/sgi_io_init.c b/arch/ia64/sn/io/sn2/sgi_io_init.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/sgi_io_init.c	Mon Feb 24 05:34:00 2003
@@ -0,0 +1,226 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/io.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/pci/pciba.h>
+#include <linux/smp.h>
+
+extern void mlreset(void);
+extern int init_hcl(void);
+extern void klgraph_hack_init(void);
+extern void hubspc_init(void);
+extern void pciio_init(void);
+extern void pcibr_init(void);
+extern void xtalk_init(void);
+extern void xbow_init(void);
+extern void xbmon_init(void);
+extern void pciiox_init(void);
+extern void pic_init(void);
+extern void usrpci_init(void);
+extern void ioc3_init(void);
+extern void initialize_io(void);
+extern void klhwg_add_all_modules(devfs_handle_t);
+extern void klhwg_add_all_nodes(devfs_handle_t);
+
+void sn_mp_setup(void);
+extern devfs_handle_t hwgraph_root;
+extern void io_module_init(void);
+extern void pci_bus_cvlink_init(void);
+extern void temp_hack(void);
+
+extern int pci_bus_to_hcl_cvlink(void);
+
+/* #define DEBUG_IO_INIT 1 */
+#ifdef DEBUG_IO_INIT
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* DEBUG_IO_INIT */
+
+/*
+ * per_hub_init
+ *
+ * 	This code is executed once for each Hub chip.
+ */
+static void
+per_hub_init(cnodeid_t cnode)
+{
+	nasid_t		nasid;
+	nodepda_t	*npdap;
+	ii_icmr_u_t	ii_icmr;
+	ii_ibcr_u_t	ii_ibcr;
+
+	nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+	ASSERT(nasid != INVALID_NASID);
+	ASSERT(NASID_TO_COMPACT_NODEID(nasid) == cnode);
+
+	npdap = NODEPDA(cnode);
+
+	REMOTE_HUB_S(nasid, IIO_IWEIM, 0x8000);
+
+	/*
+	 * Set the total number of CRBs that can be used.
+	 */
+	ii_icmr.ii_icmr_regval= 0x0;
+	ii_icmr.ii_icmr_fld_s.i_c_cnt = 0xf;
+	REMOTE_HUB_S(nasid, IIO_ICMR, ii_icmr.ii_icmr_regval);
+
+	/*
+	 * Set the number of CRBs that both of the BTEs combined
+	 * can use minus 1.
+	 */
+	ii_ibcr.ii_ibcr_regval= 0x0;
+	ii_ibcr.ii_ibcr_fld_s.i_count = 0x8;
+	REMOTE_HUB_S(nasid, IIO_IBCR, ii_ibcr.ii_ibcr_regval);
+
+	/*
+	 * Set CRB timeout to be 10ms.
+	 */
+#ifdef BRINGUP2
+	REMOTE_HUB_S(nasid, IIO_ICTP, 0xffffff );
+	REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);
+	//REMOTE_HUB_S(nasid, IIO_IWI, 0x00FF00FF00FFFFFF);
+#endif
+
+	/* Initialize error interrupts for this hub. */
+	hub_error_init(cnode);
+}
+
+/*
+ * This routine is responsible for the setup of all the IRIX hwgraph style
+ * stuff that's been pulled into linux.  It's called by sn_pci_find_bios which
+ * is called just before the generic Linux PCI layer does its probing (by 
+ * platform_pci_fixup aka sn_pci_fixup).
+ *
+ * It is very IMPORTANT that this call is only made by the Master CPU!
+ *
+ */
+
+void
+sgi_master_io_infr_init(void)
+{
+	int cnode;
+	extern void kdba_io_init();
+
+	/*
+	 * Do any early init stuff .. einit_tbl[] etc.
+	 */
+	init_hcl(); /* Sets up the hwgraph compatibility layer with devfs */
+
+	/*
+	 * initialize the Linux PCI to xwidget vertexes ..
+	 */
+	pci_bus_cvlink_init();
+
+	kdba_io_init();
+
+#ifdef BRINGUP
+	/*
+	 * Hack to provide statically initialzed klgraph entries.
+	 */
+	DBG("--> sgi_master_io_infr_init: calling klgraph_hack_init()\n");
+	klgraph_hack_init();
+#endif /* BRINGUP */
+
+	/*
+	 * This is the Master CPU.  Emulate mlsetup and main.c in Irix.
+	 */
+	mlreset();
+
+	/*
+	 * allowboot() is called by kern/os/main.c in main()
+	 * Emulate allowboot() ...
+	 *   per_cpu_init() - only need per_hub_init()
+	 *   cpu_io_setup() - Nothing to do.
+	 * 
+	 */
+	sn_mp_setup();
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		per_hub_init(cnode);
+	}
+
+	/* We can do headless hub cnodes here .. */
+
+	/*
+	 * io_init[] stuff.
+	 *
+	 * Get SGI IO Infrastructure drivers to init and register with 
+	 * each other etc.
+	 */
+
+	hubspc_init();
+	pciio_init();
+	pcibr_init();
+	pic_init();
+	xtalk_init();
+	xbow_init();
+	xbmon_init();
+	pciiox_init();
+	usrpci_init();
+	ioc3_init();
+
+	/*
+	 *
+	 * Our IO Infrastructure drivers are in place .. 
+	 * Initialize the whole IO Infrastructure .. xwidget/device probes.
+	 *
+	 */
+	initialize_io();
+	pci_bus_to_hcl_cvlink();
+
+#ifdef CONFIG_PCIBA
+	DBG("--> sgi_master_io_infr_init: calling pciba_init()\n");
+#ifndef BRINGUP2
+ 	pciba_init();
+#endif
+#endif
+}
+
+/*
+ * One-time setup for MP SN.
+ * Allocate per-node data, slurp prom klconfig information and
+ * convert it to hwgraph information.
+ */
+void
+sn_mp_setup(void)
+{
+	cpuid_t		cpu;
+
+	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		/* Skip holes in CPU space */
+		if (cpu_enabled(cpu)) {
+			init_platform_pda(cpu);
+		}
+	}
+
+	/*
+	 * Initialize platform-dependent vertices in the hwgraph:
+	 *	module
+	 *	node
+	 *	cpu
+	 *	memory
+	 *	slot
+	 *	hub
+	 *	router
+	 *	xbow
+	 */
+
+	io_module_init(); /* Use to be called module_init() .. */
+	klhwg_add_all_modules(hwgraph_root);
+	klhwg_add_all_nodes(hwgraph_root);
+}
diff -Nru a/arch/ia64/sn/io/sn2/shub.c b/arch/ia64/sn/io/sn2/shub.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/shub.c	Mon Feb 24 05:34:25 2003
@@ -0,0 +1,233 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#ident  "$Revision: 1.167 $"
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <asm/smp.h>
+#include <asm/irq.h>
+#include <asm/hw_irq.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/io.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/xtalk/xtalk.h>
+#include <asm/sn/pci/pcibr_private.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn2/shub_mmr_t.h>
+#include <asm/sal.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/sndrv.h>
+
+/*
+ * Shub WAR for Xbridge Little Endian problem:
+ *	Xbridge has to run in BIG ENDIAN even with Shub.
+ */
+
+
+/*
+ * io_sh_swapper: Turn on Shub byte swapping.
+ *	All data destined to and from Shub to XIO are byte-swapped.
+ */
+void
+io_sh_swapper(nasid_t nasid, int onoff)
+{
+    ii_iwc_u_t      ii_iwc;
+
+    ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC);
+
+    ii_iwc.ii_iwc_fld_s.i_dma_byte_swap = onoff;
+    REMOTE_HUB_S(nasid, IIO_IWC, ii_iwc.ii_iwc_regval);
+    ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC);
+
+}
+
+/*
+ * io_get_sh_swapper: Return current Swap mode.
+ *	1 = Swap on, 0 = Swap off.
+ */
+int
+io_get_sh_swapper(nasid_t nasid)
+{
+    ii_iwc_u_t      ii_iwc;
+
+    ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC);
+    return(ii_iwc.ii_iwc_fld_s.i_dma_byte_swap);
+
+}
+
+#define SHUB_NUM_ECF_REGISTERS 8
+
+static uint32_t	shub_perf_counts[SHUB_NUM_ECF_REGISTERS];
+
+static shubreg_t shub_perf_counts_regs[SHUB_NUM_ECF_REGISTERS] = {
+	SH_PERFORMANCE_COUNTER0,
+	SH_PERFORMANCE_COUNTER1,
+	SH_PERFORMANCE_COUNTER2,
+	SH_PERFORMANCE_COUNTER3,
+	SH_PERFORMANCE_COUNTER4,
+	SH_PERFORMANCE_COUNTER5,
+	SH_PERFORMANCE_COUNTER6,
+	SH_PERFORMANCE_COUNTER7
+};
+
+static inline void
+shub_mmr_write(cnodeid_t cnode, shubreg_t reg, uint64_t val)
+{
+	int		   nasid = cnodeid_to_nasid(cnode);
+	volatile uint64_t *addr = (uint64_t *)(GLOBAL_MMR_ADDR(nasid, reg));
+
+	*addr = val;
+	__ia64_mf_a();
+}
+
+static inline void
+shub_mmr_write32(cnodeid_t cnode, shubreg_t reg, uint32_t val)
+{
+	int		   nasid = cnodeid_to_nasid(cnode);
+	volatile uint32_t *addr = (uint32_t *)(GLOBAL_MMR_ADDR(nasid, reg));
+
+	*addr = val;
+	__ia64_mf_a();
+}
+
+static inline uint64_t
+shub_mmr_read(cnodeid_t cnode, shubreg_t reg)
+{
+	int		  nasid = cnodeid_to_nasid(cnode);
+	volatile uint64_t val;
+
+	val = *(uint64_t *)(GLOBAL_MMR_ADDR(nasid, reg));
+	__ia64_mf_a();
+
+	return val;
+}
+
+static inline uint32_t
+shub_mmr_read32(cnodeid_t cnode, shubreg_t reg)
+{
+	int		  nasid = cnodeid_to_nasid(cnode);
+	volatile uint32_t val;
+
+	val = *(uint32_t *)(GLOBAL_MMR_ADDR(nasid, reg));
+	__ia64_mf_a();
+
+	return val;
+}
+
+static int
+reset_shub_stats(cnodeid_t cnode)
+{
+	int i;
+
+	for (i=0; i < SHUB_NUM_ECF_REGISTERS; i++) {
+		shub_perf_counts[i] = 0;
+		shub_mmr_write32(cnode, shub_perf_counts_regs[i], 0);
+	}
+	return 0;
+}
+
+static int
+configure_shub_stats(cnodeid_t cnode, unsigned long arg)
+{
+	uint64_t	*p = (uint64_t *)arg;
+	uint64_t	i;
+	uint64_t	regcnt;
+	uint64_t	regval[2];
+
+	if (copy_from_user((void *)&regcnt, p, sizeof(regcnt)))
+	    return -EFAULT;
+
+	for (p++, i=0; i < regcnt; i++, p += 2) {
+		if (copy_from_user((void *)regval, (void *)p, sizeof(regval)))
+		    return -EFAULT;
+		if (regval[0] & 0x7) {
+		    printk("Error: configure_shub_stats: unaligned address 0x%016lx\n", regval[0]);
+		    return -EINVAL;
+		}
+		shub_mmr_write(cnode, (shubreg_t)regval[0], regval[1]);
+	}
+	return 0;
+}
+
+static int
+capture_shub_stats(cnodeid_t cnode, uint32_t *counts)
+{
+	int 		i;
+
+	for (i=0; i < SHUB_NUM_ECF_REGISTERS; i++) {
+		counts[i] = shub_mmr_read32(cnode, shub_perf_counts_regs[i]);
+	}
+	return 0;
+}
+
+static int
+shubstats_ioctl(struct inode *inode, struct file *file,
+        unsigned int cmd, unsigned long arg)
+{
+        cnodeid_t       cnode;
+        uint64_t        longarg;
+        devfs_handle_t  d;
+	int		nasid;
+
+        if ((d = devfs_get_handle_from_inode(inode)) == NULL)
+                return -ENODEV;
+        cnode = (cnodeid_t)hwgraph_fastinfo_get(d);
+
+        switch (cmd) {
+	case SNDRV_SHUB_CONFIGURE:
+		return configure_shub_stats(cnode, arg);
+		break;
+
+	case SNDRV_SHUB_RESETSTATS:
+		reset_shub_stats(cnode);
+		break;
+
+	case SNDRV_SHUB_INFOSIZE:
+		longarg = sizeof(shub_perf_counts);
+		if (copy_to_user((void *)arg, &longarg, sizeof(longarg))) {
+		    return -EFAULT;
+		}
+		break;
+
+	case SNDRV_SHUB_GETSTATS:
+		capture_shub_stats(cnode, shub_perf_counts);
+		if (copy_to_user((void *)arg, shub_perf_counts,
+				       	sizeof(shub_perf_counts))) {
+		    return -EFAULT;
+		}
+		break;
+
+	case SNDRV_SHUB_GETNASID:
+		nasid = cnodeid_to_nasid(cnode);
+		if (copy_to_user((void *)arg, &nasid,
+				       	sizeof(nasid))) {
+		    return -EFAULT;
+		}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+struct file_operations shub_mon_fops = {
+	        ioctl:          shubstats_ioctl,
+};
diff -Nru a/arch/ia64/sn/io/sn2/shubio.c b/arch/ia64/sn/io/sn2/shubio.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/shubio.c	Mon Feb 24 05:34:49 2003
@@ -0,0 +1,510 @@
+/* $Id: shubio.c,v 1.1 2002/02/28 17:31:25 marcelo Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000,2002-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/smp.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/io.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/xtalk/xtalk.h>
+#include <asm/sn/pci/pcibr_private.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/ioerror_handling.h>
+#include <asm/sn/ioerror.h>
+#include <asm/sn/sn2/shubio.h>
+
+
+error_state_t error_state_get(devfs_handle_t v);
+error_return_code_t error_state_set(devfs_handle_t v,error_state_t new_state);
+
+
+/*
+ * Get the xtalk provider function pointer for the
+ * specified hub.
+ */
+
+/*ARGSUSED*/
+int
+hub_xp_error_handler(
+	devfs_handle_t 	hub_v, 
+	nasid_t		nasid, 
+	int		error_code, 
+	ioerror_mode_t	mode, 
+	ioerror_t	*ioerror)
+{
+	/*REFERENCED*/
+	hubreg_t	iio_imem;
+	devfs_handle_t	xswitch;
+	error_state_t	e_state;
+	cnodeid_t	cnode;
+
+	/*
+	 * Before walking down to the next level, check if
+	 * the I/O link is up. If it's been disabled by the 
+	 * hub ii for some reason, we can't even touch the
+	 * widget registers.
+	 */
+	iio_imem = REMOTE_HUB_L(nasid, IIO_IMEM);
+
+	if (!(iio_imem & (IIO_IMEM_B0ESD|IIO_IMEM_W0ESD))){
+		/* 
+		 * IIO_IMEM_B0ESD getting set, indicates II shutdown
+		 * on HUB0 parts.. Hopefully that's not true for 
+		 * Hub1 parts..
+		 *
+		 *
+		 * If either one of them is shut down, can't
+		 * go any further.
+		 */
+		return IOERROR_XTALKLEVEL;
+	}
+
+	/* Get the error state of the hub */
+	e_state = error_state_get(hub_v);
+
+	cnode = NASID_TO_COMPACT_NODEID(nasid);
+
+	xswitch = NODEPDA(cnode)->basew_xc;
+
+	/* Set the error state of the crosstalk device to that of
+	 * hub.
+	 */
+	if (error_state_set(xswitch , e_state) == 
+	    ERROR_RETURN_CODE_CANNOT_SET_STATE)
+		return(IOERROR_UNHANDLED);
+
+	/* Clean the error state of the hub if we are in the action handling
+	 * phase.
+	 */
+	if (e_state == ERROR_STATE_ACTION)
+		(void)error_state_set(hub_v, ERROR_STATE_NONE);
+	/* hand the error off to the switch or the directly
+	 * connected crosstalk device.
+	 */
+	return  xtalk_error_handler(xswitch,
+				    error_code, mode, ioerror);
+
+}
+
+/* 
+ * Check if the widget in error has been enabled for PIO accesses
+ */
+int
+is_widget_pio_enabled(ioerror_t *ioerror)
+{
+	cnodeid_t	src_node;
+	nasid_t		src_nasid;
+	hubreg_t	ii_iowa;
+	xwidgetnum_t	widget;
+	iopaddr_t	p;
+
+	/* Get the node where the PIO error occurred */
+	IOERROR_GETVALUE(p,ioerror, srcnode);
+	src_node = p;
+	if (src_node == CNODEID_NONE)
+		return(0);
+
+	/* Get the nasid for the cnode */
+	src_nasid = COMPACT_TO_NASID_NODEID(src_node);
+	if (src_nasid == INVALID_NASID)
+		return(0);
+
+	/* Read the Outbound widget access register for this hub */
+	ii_iowa = REMOTE_HUB_L(src_nasid, IIO_IOWA);
+	IOERROR_GETVALUE(p,ioerror, widgetnum);
+	widget = p;
+
+	/* Check if the PIOs to the widget with PIO error have been
+	 * enabled.
+	 */
+	if (ii_iowa & IIO_IOWA_WIDGET(widget))
+		return(1);
+
+	return(0);
+}
+
+/*
+ * Hub IO error handling.
+ *
+ *	Gets invoked for different types of errors found at the hub. 
+ *	Typically this includes situations from bus error or due to 
+ *	an error interrupt (mostly generated at the hub).
+ */
+int
+hub_ioerror_handler(
+	devfs_handle_t 	hub_v, 
+	int		error_code,
+	int		mode,
+	struct io_error_s	*ioerror)
+{
+	hubinfo_t 	hinfo; 		/* Hub info pointer */
+	nasid_t		nasid;
+	int		retval = 0;
+	/*REFERENCED*/
+	iopaddr_t 	p;
+
+	IOERROR_DUMP("hub_ioerror_handler", error_code, mode, ioerror);
+
+	hubinfo_get(hub_v, &hinfo);
+
+	if (!hinfo){
+		/* Print an error message and return */
+		goto end;
+	}
+	nasid = hinfo->h_nasid;
+
+	switch(error_code) {
+
+	case PIO_READ_ERROR:
+		/* 
+		 * Cpu got a bus error while accessing IO space.
+		 * hubaddr field in ioerror structure should have
+		 * the IO address that caused access error.
+		 */
+
+		/*
+		 * Identify if  the physical address in hub_error_data
+		 * corresponds to small/large window, and accordingly,
+		 * get the xtalk address.
+		 */
+
+		/*
+		 * Evaluate the widget number and the widget address that
+		 * caused the error. Use 'vaddr' if it's there.
+		 * This is typically true either during probing
+		 * or a kernel driver getting into trouble. 
+		 * Otherwise, use paddr to figure out widget details
+		 * This is typically true for user mode bus errors while
+		 * accessing I/O space.
+		 */
+		 IOERROR_GETVALUE(p,ioerror,vaddr);
+		 if (p){
+		    /* 
+		     * If neither in small window nor in large window range,
+		     * outright reject it.
+		     */
+		    IOERROR_GETVALUE(p,ioerror,vaddr);
+		    if (NODE_SWIN_ADDR(nasid, (paddr_t)p)){
+			iopaddr_t	hubaddr;
+			xwidgetnum_t	widgetnum;
+			iopaddr_t	xtalkaddr;
+
+			IOERROR_GETVALUE(p,ioerror,hubaddr);
+			hubaddr = p;
+			widgetnum = SWIN_WIDGETNUM(hubaddr);
+			xtalkaddr = SWIN_WIDGETADDR(hubaddr);
+			/* 
+			 * differentiate local register vs IO space access
+			 */
+			IOERROR_SETVALUE(ioerror,widgetnum,widgetnum);
+			IOERROR_SETVALUE(ioerror,xtalkaddr,xtalkaddr);
+
+
+		    } else if (NODE_BWIN_ADDR(nasid, (paddr_t)p)){
+			/* 
+			 * Address corresponds to large window space. 
+			 * Convert it to xtalk address.
+			 */
+			int		bigwin;
+			hub_piomap_t    bw_piomap;
+			xtalk_piomap_t	xt_pmap = NULL;
+			iopaddr_t	hubaddr;
+			xwidgetnum_t	widgetnum;
+			iopaddr_t	xtalkaddr;
+
+			IOERROR_GETVALUE(p,ioerror,hubaddr);
+			hubaddr = p;
+
+			/*
+			 * Have to loop to find the correct xtalk_piomap 
+			 * because the're not allocated on a one-to-one
+			 * basis to the window number.
+			 */
+			for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) {
+				bw_piomap = hubinfo_bwin_piomap_get(hinfo,
+								    bigwin);
+
+				if (bw_piomap->hpio_bigwin_num ==
+				    (BWIN_WINDOWNUM(hubaddr) - 1)) {
+					xt_pmap = hub_piomap_xt_piomap(bw_piomap);
+					break;
+				}
+			}
+
+			ASSERT(xt_pmap);
+
+			widgetnum = xtalk_pio_target_get(xt_pmap);
+			xtalkaddr = xtalk_pio_xtalk_addr_get(xt_pmap) + BWIN_WIDGETADDR(hubaddr);
+
+			IOERROR_SETVALUE(ioerror,widgetnum,widgetnum);
+			IOERROR_SETVALUE(ioerror,xtalkaddr,xtalkaddr);
+
+			/* 
+			 * Make sure that widgetnum doesnot map to hub 
+			 * register widget number, as we never use
+			 * big window to access hub registers. 
+			 */
+			ASSERT(widgetnum != HUB_REGISTER_WIDGET);
+		    }
+		} else if (IOERROR_FIELDVALID(ioerror,hubaddr)) {
+			iopaddr_t	hubaddr;
+			xwidgetnum_t	widgetnum;
+			iopaddr_t	xtalkaddr;
+
+			IOERROR_GETVALUE(p,ioerror,hubaddr);
+			hubaddr = p;
+			if (BWIN_WINDOWNUM(hubaddr)){
+				int 	window = BWIN_WINDOWNUM(hubaddr) - 1;
+				hubreg_t itte;
+				itte = (hubreg_t)HUB_L(IIO_ITTE_GET(nasid, window));
+				widgetnum =  (itte >> IIO_ITTE_WIDGET_SHIFT) & 
+						IIO_ITTE_WIDGET_MASK;
+				xtalkaddr = (((itte >> IIO_ITTE_OFFSET_SHIFT) &
+					IIO_ITTE_OFFSET_MASK) << 
+					     BWIN_SIZE_BITS) +
+					BWIN_WIDGETADDR(hubaddr);
+			} else {
+				widgetnum = SWIN_WIDGETNUM(hubaddr);
+				xtalkaddr = SWIN_WIDGETADDR(hubaddr);
+			}
+			IOERROR_SETVALUE(ioerror,widgetnum,widgetnum);
+			IOERROR_SETVALUE(ioerror,xtalkaddr,xtalkaddr);
+		} else {
+			IOERROR_DUMP("hub_ioerror_handler", error_code, 
+						mode, ioerror);
+			IOERR_PRINTF(printk(
+				"hub_ioerror_handler: Invalid address passed"));
+
+			return IOERROR_INVALIDADDR;
+		}
+
+
+		IOERROR_GETVALUE(p,ioerror,widgetnum);
+		if ((p) == HUB_REGISTER_WIDGET) {
+			/* 
+			 * Error in accessing Hub local register
+			 * This should happen mostly in SABLE mode..
+			 */
+			retval = 0;
+		} else {
+			/* Make sure that the outbound widget access for this
+			 * widget is enabled.
+			 */
+			if (!is_widget_pio_enabled(ioerror)) {
+				if (error_state_get(hub_v) == 
+				    ERROR_STATE_ACTION)
+					ioerror_dump("No outbound widget"
+						     " access - ", 
+						     error_code, mode, ioerror);
+				return(IOERROR_HANDLED);
+			}
+		  
+
+			retval = hub_xp_error_handler(
+				hub_v, nasid, error_code, mode, ioerror);
+
+		}
+
+		IOERR_PRINTF(printk(
+			"hub_ioerror_handler:PIO_READ_ERROR return: %d",
+				retval));
+
+		break;
+
+	case PIO_WRITE_ERROR:
+		/*
+		 * This hub received an interrupt indicating a widget 
+		 * attached to this hub got a timeout. 
+		 * widgetnum field should be filled to indicate the
+		 * widget that caused error.
+		 *
+		 * NOTE: This hub may have nothing to do with this error.
+		 * We are here since the widget attached to the xbow 
+		 * gets its PIOs through this hub.
+		 *
+		 * There is nothing that can be done at this level. 
+		 * Just invoke the xtalk error handling mechanism.
+		 */
+		IOERROR_GETVALUE(p,ioerror,widgetnum);
+		if ((p) == HUB_REGISTER_WIDGET) {
+		} else {
+			/* Make sure that the outbound widget access for this
+			 * widget is enabled.
+			 */
+
+			if (!is_widget_pio_enabled(ioerror)) {
+				if (error_state_get(hub_v) == 
+				    ERROR_STATE_ACTION)
+					ioerror_dump("No outbound widget"
+						     " access - ", 
+						     error_code, mode, ioerror);
+				return(IOERROR_HANDLED);
+			}
+		  
+			retval = hub_xp_error_handler(
+				hub_v, nasid, error_code, mode, ioerror);
+		}
+		break;
+	
+	case DMA_READ_ERROR:
+		/* 
+		 * DMA Read error always ends up generating an interrupt
+		 * at the widget level, and never at the hub level. So,
+		 * we don't expect to come here any time
+		 */
+		ASSERT(0);
+		retval = IOERROR_UNHANDLED;
+		break;
+
+	case DMA_WRITE_ERROR:
+		/*
+		 * DMA Write error is generated when a write by an I/O 
+		 * device could not be completed. Problem is, device is
+		 * totally unaware of this problem, and would continue
+		 * writing to system memory. So, hub has a way to send
+		 * an error interrupt on the first error, and bitbucket
+		 * all further write transactions.
+		 * Coming here indicates that hub detected one such error,
+		 * and we need to handle it.
+		 *
+		 * Hub interrupt handler would have extracted physaddr, 
+		 * widgetnum, and widgetdevice from the CRB 
+		 *
+		 * There is nothing special to do here, since gathering
+		 * data from crb's is done elsewhere. Just pass the 
+		 * error to xtalk layer.
+		 */
+		retval = hub_xp_error_handler(hub_v, nasid, error_code, mode,
+					      ioerror);
+		break;
+	
+	default:
+		ASSERT(0);
+		return IOERROR_BADERRORCODE;
+	
+	}
+	
+	/*
+	 * If error was not handled, we may need to take certain action
+	 * based on the error code.
+	 * For e.g. in case of PIO_READ_ERROR, we may need to release the
+	 * PIO Read entry table (they are sticky after errors).
+	 * Similarly other cases. 
+	 *
+	 * Further Action TBD 
+	 */
+end:	
+	if (retval == IOERROR_HWGRAPH_LOOKUP) {
+		/*
+		 * If we get errors very early, we can't traverse
+		 * the path using hardware graph. 
+		 * To handle this situation, we need a functions
+		 * which don't depend on the hardware graph vertex to 
+		 * handle errors. This break the modularity of the
+		 * existing code. Instead we print out the reason for
+		 * not handling error, and return. On return, all the
+		 * info collected would be dumped. This should provide 
+		 * sufficient info to analyse the error.
+		 */
+		printk("Unable to handle IO error: hardware graph not setup\n");
+	}
+
+	return retval;
+}
+
+#define L_BITSMINOR 18
+#define L_MAXMAJ 0x1ff
+#define emajor(x) (int )(((unsigned )(x)>>L_BITSMINOR) & L_MAXMAJ)
+#define dev_is_vertex(dev) (emajor((dev_t)(dev)) == 0)
+
+#define INFO_LBL_ERROR_STATE    "error_state"
+
+#define v_error_state_get(v,s)                                          \
+(hwgraph_info_get_LBL(v,INFO_LBL_ERROR_STATE, (arbitrary_info_t *)&s))
+
+#define v_error_state_set(v,s,replace)                                  \
+(replace ?                                                              \
+hwgraph_info_replace_LBL(v,INFO_LBL_ERROR_STATE,(arbitrary_info_t)s,0) :\
+hwgraph_info_add_LBL(v,INFO_LBL_ERROR_STATE, (arbitrary_info_t)s))
+
+
+#define v_error_state_clear(v)                                          \
+(hwgraph_info_remove_LBL(v,INFO_LBL_ERROR_STATE,0))
+
+/*
+ * error_state_get
+ *              Get the state of the vertex.
+ *              Returns ERROR_STATE_INVALID on failure
+ *                      current state otherwise
+ */
+error_state_t
+error_state_get(devfs_handle_t v)
+{
+        error_state_t   s;
+
+        /* Check if we have a valid hwgraph vertex */
+        if (!dev_is_vertex(v))
+                return(ERROR_STATE_NONE);
+
+        /* Get the labelled info hanging off the vertex which corresponds
+         * to the state.
+         */
+        if (v_error_state_get(v, s) != GRAPH_SUCCESS) {
+                return(ERROR_STATE_NONE);
+        }
+        return(s);
+}
+
+
+/*
+ * error_state_set
+ *              Set the state of the vertex
+ *              Returns ERROR_RETURN_CODE_CANNOT_SET_STATE on failure
+ *                      ERROR_RETURN_CODE_SUCCESS otherwise
+ */
+error_return_code_t
+error_state_set(devfs_handle_t v,error_state_t new_state)
+{
+        error_state_t   old_state;
+        boolean_t       replace = B_TRUE;
+
+        /* Check if we have a valid hwgraph vertex */
+        if (!dev_is_vertex(v))
+                return(ERROR_RETURN_CODE_GENERAL_FAILURE);
+
+
+        /* This means that the error state needs to be cleaned */
+        if (new_state == ERROR_STATE_NONE) {
+                /* Make sure that we have an error state */
+                if (v_error_state_get(v,old_state) == GRAPH_SUCCESS)
+                        v_error_state_clear(v);
+                return(ERROR_RETURN_CODE_SUCCESS);
+        }
+
+        /* Check if the state information has been set at least once
+         * for this vertex.
+         */
+        if (v_error_state_get(v,old_state) != GRAPH_SUCCESS)
+                replace = B_FALSE;
+
+        if (v_error_state_set(v,new_state,replace) != GRAPH_SUCCESS) {
+                return(ERROR_RETURN_CODE_CANNOT_SET_STATE);
+        }
+        return(ERROR_RETURN_CODE_SUCCESS);
+}
diff -Nru a/arch/ia64/sn/io/sn2/xbow.c b/arch/ia64/sn/io/sn2/xbow.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/xbow.c	Mon Feb 24 05:39:15 2003
@@ -0,0 +1,1681 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn2/sn_private.h>
+#include <asm/sn/sn2/shubio.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/hack.h>
+#include <asm/sn/pci/bridge.h>
+#include <asm/sn/xtalk/xtalk_private.h>
+#include <asm/sn/simulator.h>
+
+/* #define DEBUG		1 */
+/* #define XBOW_DEBUG	1 */
+/* #define DEBUG_ERROR	1 */
+
+
+/*
+ * Files needed to get the device driver entry points
+ */
+
+#include <asm/sn/xtalk/xbow.h>
+#include <asm/sn/xtalk/xtalk.h>
+#include <asm/sn/xtalk/xswitch.h>
+#include <asm/sn/xtalk/xwidget.h>
+
+#include <asm/sn/prio.h>
+#include <asm/sn/hcl_util.h>
+
+
+#define NEW(ptr)	(ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL))
+#define DEL(ptr)	(kfree(ptr))
+
+int                     xbow_devflag = D_MP;
+
+/*
+ * This file supports the Xbow chip.  Main functions: initializtion,
+ * error handling, and GBR.
+ */
+
+/*
+ * each vertex corresponding to an xbow chip
+ * has a "fastinfo" pointer pointing at one
+ * of these things.
+ */
+typedef struct xbow_soft_s *xbow_soft_t;
+
+struct xbow_soft_s {
+    devfs_handle_t            conn;	/* our connection point */
+    devfs_handle_t            vhdl;	/* xbow's private vertex */
+    devfs_handle_t            busv;	/* the xswitch vertex */
+    xbow_t                 *base;	/* PIO pointer to crossbow chip */
+    char                   *name;	/* hwgraph name */
+
+    xbow_perf_t             xbow_perfcnt[XBOW_PERF_COUNTERS];
+    xbow_perf_link_t        xbow_perflink[MAX_XBOW_PORTS];
+    xbow_link_status_t      xbow_link_status[MAX_XBOW_PORTS];
+    spinlock_t              xbow_perf_lock;
+    int                     link_monitor;
+    widget_cfg_t	   *wpio[MAX_XBOW_PORTS];	/* cached PIO pointer */
+
+    /* Bandwidth allocation state. Bandwidth values are for the
+     * destination port since contention happens there.
+     * Implicit mapping from xbow ports (8..f) -> (0..7) array indices.
+     */
+    spinlock_t		    xbow_bw_alloc_lock;		/* bw allocation lock */
+    unsigned long long	    bw_hiwm[MAX_XBOW_PORTS];	/* hiwater mark values */
+    unsigned long long      bw_cur_used[MAX_XBOW_PORTS]; /* bw used currently */
+};
+
+#define xbow_soft_set(v,i)	hwgraph_fastinfo_set((v), (arbitrary_info_t)(i))
+#define xbow_soft_get(v)	((xbow_soft_t)hwgraph_fastinfo_get((v)))
+
+/*
+ * Function Table of Contents
+ */
+
+void                    xbow_mlreset(xbow_t *);
+void                    xbow_init(void);
+int                     xbow_attach(devfs_handle_t);
+
+int                     xbow_open(devfs_handle_t *, int, int, cred_t *);
+int                     xbow_close(devfs_handle_t, int, int, cred_t *);
+
+int                     xbow_map(devfs_handle_t, vhandl_t *, off_t, size_t, uint);
+int                     xbow_unmap(devfs_handle_t, vhandl_t *);
+int                     xbow_ioctl(devfs_handle_t, int, void *, int, struct cred *, int *);
+
+int                     xbow_widget_present(xbow_t *, int);
+static int              xbow_link_alive(xbow_t *, int);
+devfs_handle_t            xbow_widget_lookup(devfs_handle_t, int);
+
+void                    xbow_intr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t);
+
+
+
+void                    xbow_update_perf_counters(devfs_handle_t);
+xbow_perf_link_t       *xbow_get_perf_counters(devfs_handle_t);
+int                     xbow_enable_perf_counter(devfs_handle_t, int, int, int);
+xbow_link_status_t     *xbow_get_llp_status(devfs_handle_t);
+void                    xbow_update_llp_status(devfs_handle_t);
+
+int                     xbow_disable_llp_monitor(devfs_handle_t);
+int                     xbow_enable_llp_monitor(devfs_handle_t);
+int                     xbow_prio_bw_alloc(devfs_handle_t, xwidgetnum_t, xwidgetnum_t,
+                                unsigned long long, unsigned long long);
+static void		xbow_setwidint(xtalk_intr_t);
+void                    idbg_xbowregs(int64_t);
+
+xswitch_reset_link_f    xbow_reset_link;
+
+xswitch_provider_t      xbow_provider =
+{
+    xbow_reset_link,
+};
+
+/*
+ * This is the file operation table for the pcibr driver.
+ * As each of the functions are implemented, put the
+ * appropriate function name below.
+ */
+static int xbow_mmap(struct file * file, struct vm_area_struct * vma);
+struct file_operations xbow_fops = {
+        owner:  THIS_MODULE,
+        llseek: NULL,
+        read: NULL,
+        write: NULL,
+        readdir: NULL,
+        poll: NULL,
+        ioctl: NULL,
+        mmap: xbow_mmap,
+        open: xbow_open,
+        flush: NULL,
+        release: NULL,
+        fsync: NULL,
+        fasync: NULL,
+        lock: NULL,
+        readv: NULL,
+        writev: NULL,
+        sendpage: NULL,
+        get_unmapped_area: NULL
+};
+
+static int
+xbow_mmap(struct file * file, struct vm_area_struct * vma)
+{
+        unsigned long           phys_addr;
+        int                     error = 0;
+
+        phys_addr = (unsigned long)file->private_data & ~0xc000000000000000; /* Mask out the Uncache bits */
+        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+        vma->vm_flags |= VM_RESERVED | VM_IO;
+        error = io_remap_page_range(vma, vma->vm_start, phys_addr,
+                                   vma->vm_end - vma->vm_start,
+                                   vma->vm_page_prot);
+        return(error);
+}
+
+
+/*
+ *    xbow_mlreset: called at mlreset time if the
+ *      platform specific code determines that there is
+ *      a crossbow in a critical path that must be
+ *      functional before the driver would normally get
+ *      the device properly set up.
+ *
+ *      what do we need to do, that the boot prom can
+ *      not be counted on to have already done, that is
+ *      generic across all platforms using crossbows?
+ */
+/*ARGSUSED */
+void
+xbow_mlreset(xbow_t * xbow)
+{
+}
+
+/*
+ *    xbow_init: called with the rest of the device
+ *      driver XXX_init routines. This platform *might*
+ *      have a Crossbow chip, or even several, but it
+ *      might have none. Register with the crosstalk
+ *      generic provider so when we encounter the chip
+ *      the right magic happens.
+ */
+void
+xbow_init(void)
+{
+
+#if DEBUG && ATTACH_DEBUG
+    printk("xbow_init\n");
+#endif
+
+    xwidget_driver_register(PXBOW_WIDGET_PART_NUM,
+			    0, /* XXBOW_WIDGET_MFGR_NUM, */
+			    "xbow_",
+			    CDL_PRI_HI);	/* attach before friends */
+
+
+    xwidget_driver_register(XXBOW_WIDGET_PART_NUM,
+			    0, /* XXBOW_WIDGET_MFGR_NUM, */
+			    "xbow_",
+			    CDL_PRI_HI);	/* attach before friends */
+
+    xwidget_driver_register(XBOW_WIDGET_PART_NUM,
+			    XBOW_WIDGET_MFGR_NUM,
+			    "xbow_",
+			    CDL_PRI_HI);	/* attach before friends */
+}
+
+#ifdef XBRIDGE_REGS_SIM
+/*    xbow_set_simulated_regs: sets xbow regs as needed
+ *	for powering through the boot
+ */
+void
+xbow_set_simulated_regs(xbow_t *xbow, int port)
+{
+    /*
+     * turn on link
+     */
+    xbow->xb_link(port).link_status = (1<<31);
+    /*
+     * and give it a live widget too
+     */
+    xbow->xb_link(port).link_aux_status = XB_AUX_STAT_PRESENT;
+    /*
+     * zero the link control reg
+     */
+    xbow->xb_link(port).link_control = 0x0;
+}
+#endif /* XBRIDGE_REGS_SIM */
+
+/*
+ *    xbow_attach: the crosstalk provider has
+ *      determined that there is a crossbow widget
+ *      present, and has handed us the connection
+ *      point for that vertex.
+ *
+ *      We not only add our own vertex, but add
+ *      some "xtalk switch" data to the switch
+ *      vertex (at the connect point's parent) if
+ *      it does not have any.
+ */
+
+/*ARGSUSED */
+int
+xbow_attach(devfs_handle_t conn)
+{
+    /*REFERENCED */
+    devfs_handle_t            vhdl;
+    devfs_handle_t            busv;
+    xbow_t                 *xbow;
+    xbow_soft_t             soft;
+    int                     port;
+    xswitch_info_t          info;
+    xtalk_intr_t            intr_hdl;
+    char                    devnm[MAXDEVNAME], *s;
+    xbowreg_t               id;
+    int                     rev;
+    int			    i;
+    int			    xbow_num;
+    static void xbow_errintr_handler(int, void *, struct pt_regs *);
+
+	
+#if DEBUG && ATTACH_DEBUG
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+    printk("%v: xbow_attach\n", conn);
+#else
+    printk("0x%x: xbow_attach\n", conn);
+#endif
+#endif
+
+    /*
+     * Get a PIO pointer to the base of the crossbow
+     * chip.
+     */
+#ifdef XBRIDGE_REGS_SIM
+    printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: allocating %ld bytes for xbow_s\n", sizeof(xbow_t));
+    xbow = (xbow_t *) kmalloc(sizeof(xbow_t), GFP_KERNEL);
+    /*
+     * turn on ports e and f like in a real live ibrick
+     */
+    xbow_set_simulated_regs(xbow, 0xe);
+    xbow_set_simulated_regs(xbow, 0xf);
+#else
+    xbow = (xbow_t *) xtalk_piotrans_addr(conn, 0, 0, sizeof(xbow_t), 0);
+#endif /* XBRIDGE_REGS_SIM */
+
+    /*
+     * Locate the "switch" vertex: it is the parent
+     * of our connection point.
+     */
+    busv = hwgraph_connectpt_get(conn);
+#if DEBUG && ATTACH_DEBUG
+    printk("xbow_attach: Bus Vertex 0x%p, conn 0x%p, xbow register 0x%p wid= 0x%x\n", busv, conn, xbow, *(volatile u32 *)xbow);
+#endif
+
+    ASSERT(busv != GRAPH_VERTEX_NONE);
+
+    /*
+     * Create our private vertex, and connect our
+     * driver information to it. This makes it possible
+     * for diagnostic drivers to open the crossbow
+     * vertex for access to registers.
+     */
+
+    /*
+     * Register a xbow driver with devfs.
+     * file ops.
+     */
+    vhdl = NULL;
+    vhdl = devfs_register(conn, EDGE_LBL_XBOW,
+		DEVFS_FL_AUTO_DEVNUM, 0, 0,
+		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
+		&xbow_fops, (void *)xbow);
+    if (!vhdl) {
+        printk(KERN_WARNING "xbow_attach: Unable to create char device for xbow conn %p\n",
+                (void *)conn);
+    }
+
+    /*
+     * Allocate the soft state structure and attach
+     * it to the xbow's vertex
+     */
+    NEW(soft);
+    soft->conn = conn;
+    soft->vhdl = vhdl;
+    soft->busv = busv;
+    soft->base = xbow;
+    /* does the universe really need another macro?  */
+    /* xbow_soft_set(vhdl, (arbitrary_info_t) soft); */
+    /* hwgraph_fastinfo_set(vhdl, (arbitrary_info_t) soft); */
+
+#define XBOW_NUM_SUFFIX_FORMAT	"[xbow# %d]"
+
+    /* Add xbow number as a suffix to the hwgraph name of the xbow.
+     * This is helpful while looking at the error/warning messages.
+     */
+    xbow_num = 0;
+
+    /*
+     * get the name of this xbow vertex and keep the info.
+     * This is needed during errors and interupts, but as
+     * long as we have it, we can use it elsewhere.
+     */
+    s = dev_to_name(vhdl, devnm, MAXDEVNAME);
+    soft->name = kmalloc(strlen(s) + strlen(XBOW_NUM_SUFFIX_FORMAT) + 1, 
+			    GFP_KERNEL);
+    sprintf(soft->name,"%s"XBOW_NUM_SUFFIX_FORMAT, s,xbow_num);
+
+#ifdef XBRIDGE_REGS_SIM
+    /* my o200/ibrick has id=0x2d002049, but XXBOW_WIDGET_PART_NUM is defined
+     * as 0xd000, so I'm using that for the partnum bitfield.
+     */
+    printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: need xb_wid_id value!!\n");
+    id = 0x2d000049;
+#else
+    id = xbow->xb_wid_id;
+#endif /* XBRIDGE_REGS_SIM */
+    rev = XWIDGET_PART_REV_NUM(id);
+
+    mutex_spinlock_init(&soft->xbow_perf_lock);
+    soft->xbow_perfcnt[0].xp_perf_reg = &xbow->xb_perf_ctr_a;
+    soft->xbow_perfcnt[1].xp_perf_reg = &xbow->xb_perf_ctr_b;
+
+    /* Initialization for GBR bw allocation */
+    mutex_spinlock_init(&soft->xbow_bw_alloc_lock);
+
+#define	XBOW_8_BIT_PORT_BW_MAX		(400 * 1000 * 1000)	/* 400 MB/s */
+#define XBOW_16_BIT_PORT_BW_MAX		(800 * 1000 * 1000)	/* 800 MB/s */
+
+    /* Set bandwidth hiwatermark and current values */
+    for (i = 0; i < MAX_XBOW_PORTS; i++) {
+	soft->bw_hiwm[i] = XBOW_16_BIT_PORT_BW_MAX;	/* for now */
+	soft->bw_cur_used[i] = 0;
+    }
+
+     /*
+      * attach the crossbow error interrupt.
+      */
+     intr_hdl = xtalk_intr_alloc(conn, (device_desc_t)0, vhdl);
+     ASSERT(intr_hdl != NULL);
+ 
+     xtalk_intr_connect(intr_hdl,
+                        (intr_func_t) xbow_errintr_handler,
+                        (intr_arg_t) soft,
+                        (xtalk_intr_setfunc_t) xbow_setwidint,
+                        (void *) xbow);
+
+     request_irq(CPU_VECTOR_TO_IRQ(((hub_intr_t)intr_hdl)->i_cpuid,
+			((hub_intr_t)intr_hdl)->i_bit),
+			(intr_func_t)xbow_errintr_handler, 0, "XBOW error",
+			(intr_arg_t) soft);
+
+#ifdef BUS_INT_WAR_NOT_YET
+    {
+	void sn_add_polled_interrupt(int, int);
+        sn_add_polled_interrupt(CPU_VECTOR_TO_IRQ(((hub_intr_t)intr_hdl)->i_cpuid,
+                                ((hub_intr_t)intr_hdl)->i_bit), 5000);
+    }
+#endif
+
+ 
+    /*
+     * Enable xbow error interrupts
+     */
+    xbow->xb_wid_control = (XB_WID_CTRL_REG_ACC_IE | XB_WID_CTRL_XTALK_IE);
+
+    /*
+     * take a census of the widgets present,
+     * leaving notes at the switch vertex.
+     */
+    info = xswitch_info_new(busv);
+
+    for (port = MAX_PORT_NUM - MAX_XBOW_PORTS;
+	 port < MAX_PORT_NUM; ++port) {
+	if (!xbow_link_alive(xbow, port)) {
+#if DEBUG && XBOW_DEBUG
+	    printk(KERN_INFO "0x%p link %d is not alive\n",
+		    (void *)busv, port);
+#endif
+	    continue;
+	}
+	if (!xbow_widget_present(xbow, port)) {
+#if DEBUG && XBOW_DEBUG
+	    printk(KERN_INFO "0x%p link %d is alive but no widget is present\n", (void *)busv, port);
+#endif
+	    continue;
+	}
+#if DEBUG && XBOW_DEBUG
+	printk(KERN_INFO "0x%p link %d has a widget\n",
+		(void *)busv, port);
+#endif
+
+	xswitch_info_link_is_ok(info, port);
+	/*
+	 * Turn some error interrupts on
+	 * and turn others off. The PROM has
+	 * some things turned on we don't
+	 * want to see (bandwidth allocation
+	 * errors for instance); so if it
+	 * is not listed here, it is not on.
+	 */
+	xbow->xb_link(port).link_control =
+	    ( (xbow->xb_link(port).link_control
+	/*
+	 * Turn off these bits; they are non-fatal,
+	 * but we might want to save some statistics
+	 * on the frequency of these errors.
+	 * XXX FIXME XXX
+	 */
+	    & ~XB_CTRL_RCV_CNT_OFLOW_IE
+	    & ~XB_CTRL_XMT_CNT_OFLOW_IE
+	    & ~XB_CTRL_BNDWDTH_ALLOC_IE
+	    & ~XB_CTRL_RCV_IE)
+	/*
+	 * These are the ones we want to turn on.
+	 */
+	    | (XB_CTRL_ILLEGAL_DST_IE
+	    | XB_CTRL_OALLOC_IBUF_IE
+	    | XB_CTRL_XMT_MAX_RTRY_IE
+	    | XB_CTRL_MAXREQ_TOUT_IE
+	    | XB_CTRL_XMT_RTRY_IE
+	    | XB_CTRL_SRC_TOUT_IE) );
+    }
+
+    xswitch_provider_register(busv, &xbow_provider);
+
+    return 0;				/* attach successful */
+}
+
+/*ARGSUSED */
+int
+xbow_open(devfs_handle_t *devp, int oflag, int otyp, cred_t *credp)
+{
+    return 0;
+}
+
+/*ARGSUSED */
+int
+xbow_close(devfs_handle_t dev, int oflag, int otyp, cred_t *crp)
+{
+    return 0;
+}
+
+/*ARGSUSED */
+int
+xbow_map(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot)
+{
+    devfs_handle_t            vhdl = dev_to_vhdl(dev);
+    xbow_soft_t             soft = xbow_soft_get(vhdl);
+    int                     error;
+
+    ASSERT(soft);
+    len = ctob(btoc(len));
+    /* XXX- this ignores the offset!!! */
+    error = v_mapphys(vt, (void *) soft->base, len);
+    return error;
+}
+
+/*ARGSUSED */
+int
+xbow_unmap(devfs_handle_t dev, vhandl_t *vt)
+{
+    return 0;
+}
+
+/* This contains special-case code for grio. There are plans to make
+ * this general sometime in the future, but till then this should
+ * be good enough.
+ */
+xwidgetnum_t
+xbow_widget_num_get(devfs_handle_t dev)
+{
+	devfs_handle_t	tdev;
+	char		devname[MAXDEVNAME];
+	xwidget_info_t	xwidget_info;
+	int		i;
+
+	vertex_to_name(dev, devname, MAXDEVNAME);
+
+	/* If this is a pci controller vertex, traverse up using
+	 * the ".." links to get to the widget.
+	 */
+	if (strstr(devname, EDGE_LBL_PCI) &&
+			strstr(devname, EDGE_LBL_CONTROLLER)) {
+		tdev = dev;
+		for (i=0; i< 2; i++) {
+			if (hwgraph_edge_get(tdev,
+				HWGRAPH_EDGELBL_DOTDOT, &tdev) !=
+					GRAPH_SUCCESS)
+				return XWIDGET_NONE;
+		}
+
+		if ((xwidget_info = xwidget_info_chk(tdev)) != NULL) {
+			return (xwidget_info_id_get(xwidget_info));
+		} else {
+			return XWIDGET_NONE;
+		}
+	}
+
+	return XWIDGET_NONE;
+}
+
+int
+xbow_ioctl(devfs_handle_t dev,
+	   int cmd,
+	   void *arg,
+	   int flag,
+	   struct cred *cr,
+	   int *rvalp)
+{
+    devfs_handle_t            vhdl;
+    int                     error = 0;
+
+#if defined (DEBUG)
+    int                     rc;
+    devfs_handle_t            conn;
+    struct xwidget_info_s  *xwidget_info;
+    xbow_soft_t             xbow_soft;
+#endif
+    *rvalp = 0;
+
+    vhdl = dev_to_vhdl(dev);
+#if defined (DEBUG)
+    xbow_soft = xbow_soft_get(vhdl);
+    conn = xbow_soft->conn;
+
+    xwidget_info = xwidget_info_get(conn);
+    ASSERT_ALWAYS(xwidget_info != NULL);
+
+    rc = xwidget_hwid_is_xswitch(&xwidget_info->w_hwid);
+    ASSERT_ALWAYS(rc != 0);
+#endif
+    switch (cmd) {
+
+    case XBOWIOC_LLP_ERROR_ENABLE:
+	if ((error = xbow_enable_llp_monitor(vhdl)) != 0)
+	    error = EINVAL;
+
+	break;
+
+    case XBOWIOC_LLP_ERROR_DISABLE:
+
+	if ((error = xbow_disable_llp_monitor(vhdl)) != 0)
+	    error = EINVAL;
+
+	break;
+
+    default:
+	break;
+
+    }
+    return error;
+}
+
+/*
+ * xbow_widget_present: See if a device is present
+ * on the specified port of this crossbow.
+ */
+int
+xbow_widget_present(xbow_t *xbow, int port)
+{
+	if ( IS_RUNNING_ON_SIMULATOR() ) {
+		if ( (port == 14) || (port == 15) ) {
+			return 1;
+		}
+		else {
+			return 0;
+		}
+	}
+	else {
+		/* WAR: port 0xf on PIC is missing present bit */
+		if (XBOW_WAR_ENABLED(PV854827, xbow->xb_wid_id) &&
+					IS_PIC_XBOW(xbow->xb_wid_id) && port==0xf) {
+			return 1;
+		}
+		return xbow->xb_link(port).link_aux_status & XB_AUX_STAT_PRESENT;
+	}
+}
+
+static int
+xbow_link_alive(xbow_t * xbow, int port)
+{
+    xbwX_stat_t             xbow_linkstat;
+
+    xbow_linkstat.linkstatus = xbow->xb_link(port).link_status;
+    return (xbow_linkstat.link_alive);
+}
+
+/*
+ * xbow_widget_lookup
+ *      Lookup the edges connected to the xbow specified, and
+ *      retrieve the handle corresponding to the widgetnum
+ *      specified.
+ *      If not found, return 0.
+ */
+devfs_handle_t
+xbow_widget_lookup(devfs_handle_t vhdl,
+		   int widgetnum)
+{
+    xswitch_info_t          xswitch_info;
+    devfs_handle_t            conn;
+
+    xswitch_info = xswitch_info_get(vhdl);
+    conn = xswitch_info_vhdl_get(xswitch_info, widgetnum);
+    return conn;
+}
+
+/*
+ * xbow_setwidint: called when xtalk
+ * is establishing or migrating our
+ * interrupt service.
+ */
+static void
+xbow_setwidint(xtalk_intr_t intr)
+{
+    xwidgetnum_t            targ = xtalk_intr_target_get(intr);
+    iopaddr_t               addr = xtalk_intr_addr_get(intr);
+    xtalk_intr_vector_t     vect = xtalk_intr_vector_get(intr);
+    xbow_t                 *xbow = (xbow_t *) xtalk_intr_sfarg_get(intr);
+
+    xbow_intr_preset((void *) xbow, 0, targ, addr, vect);
+}
+
+/*
+ * xbow_intr_preset: called during mlreset time
+ * if the platform specific code needs to route
+ * an xbow interrupt before the xtalk infrastructure
+ * is available for use.
+ *
+ * Also called from xbow_setwidint, so we don't
+ * replicate the guts of the routine.
+ *
+ * XXX- probably should be renamed xbow_wid_intr_set or
+ * something to reduce confusion.
+ */
+/*ARGSUSED3 */
+void
+xbow_intr_preset(void *which_widget,
+		 int which_widget_intr,
+		 xwidgetnum_t targ,
+		 iopaddr_t addr,
+		 xtalk_intr_vector_t vect)
+{
+    xbow_t                 *xbow = (xbow_t *) which_widget;
+
+    xbow->xb_wid_int_upper = ((0xFF000000 & (vect << 24)) |
+			      (0x000F0000 & (targ << 16)) |
+			      XTALK_ADDR_TO_UPPER(addr));
+    xbow->xb_wid_int_lower = XTALK_ADDR_TO_LOWER(addr);
+
+}
+
+#define	XEM_ADD_STR(s)		printk("%s", (s))
+#define	XEM_ADD_NVAR(n,v)	printk("\t%20s: 0x%llx\n", (n), ((unsigned long long)v))
+#define	XEM_ADD_VAR(v)		XEM_ADD_NVAR(#v,(v))
+#define XEM_ADD_IOEF(p,n)	if (IOERROR_FIELDVALID(ioe,n)) {	\
+				    IOERROR_GETVALUE(p,ioe,n);		\
+				    XEM_ADD_NVAR("ioe." #n, p);		\
+				}
+
+#ifdef LATER
+static void
+xem_add_ioe(ioerror_t *ioe)
+{
+    union tmp {
+	ushort stmp;
+	unsigned long long lltmp;
+	cpuid_t cputmp;
+	cnodeid_t cntmp;
+	iopaddr_t iotmp;
+	caddr_t catmp;
+	paddr_t patmp;
+    } tmp;
+
+    XEM_ADD_IOEF(tmp.stmp, errortype);
+    XEM_ADD_IOEF(tmp.stmp, widgetnum);
+    XEM_ADD_IOEF(tmp.stmp, widgetdev);
+    XEM_ADD_IOEF(tmp.cputmp, srccpu);
+    XEM_ADD_IOEF(tmp.cntmp, srcnode);
+    XEM_ADD_IOEF(tmp.cntmp, errnode);
+    XEM_ADD_IOEF(tmp.iotmp, sysioaddr);
+    XEM_ADD_IOEF(tmp.iotmp, xtalkaddr);
+    XEM_ADD_IOEF(tmp.iotmp, busspace);
+    XEM_ADD_IOEF(tmp.iotmp, busaddr);
+    XEM_ADD_IOEF(tmp.catmp, vaddr);
+    XEM_ADD_IOEF(tmp.patmp, memaddr);
+    XEM_ADD_IOEF(tmp.catmp, epc);
+    XEM_ADD_IOEF(tmp.catmp, ef);
+    XEM_ADD_IOEF(tmp.stmp, tnum);
+}
+
+#define XEM_ADD_IOE()   (xem_add_ioe(ioe))
+#endif	/* LATER */
+
+int                     xbow_xmit_retry_errors = 0;
+
+int
+xbow_xmit_retry_error(xbow_soft_t soft,
+		      int port)
+{
+    xswitch_info_t          info;
+    devfs_handle_t            vhdl;
+    widget_cfg_t           *wid;
+    widgetreg_t             id;
+    int                     part;
+    int                     mfgr;
+
+    wid = soft->wpio[port - BASE_XBOW_PORT];
+    if (wid == NULL) {
+	/* If we can't track down a PIO
+	 * pointer to our widget yet,
+	 * leave our caller knowing that
+	 * we are interested in this
+	 * interrupt if it occurs in
+	 * the future.
+	 */
+	info = xswitch_info_get(soft->busv);
+	if (!info)
+	    return 1;
+	vhdl = xswitch_info_vhdl_get(info, port);
+	if (vhdl == GRAPH_VERTEX_NONE)
+	    return 1;
+	wid = (widget_cfg_t *) xtalk_piotrans_addr
+	    (vhdl, 0, 0, sizeof *wid, 0);
+	if (!wid)
+	    return 1;
+	soft->wpio[port - BASE_XBOW_PORT] = wid;
+    }
+    id = wid->w_id;
+    part = XWIDGET_PART_NUM(id);
+    mfgr = XWIDGET_MFG_NUM(id);
+
+    /* If this thing is not a Bridge,
+     * do not activate the WAR, and
+     * tell our caller we do not need
+     * to be called again.
+     */
+    if ((part != BRIDGE_WIDGET_PART_NUM) ||
+	(mfgr != BRIDGE_WIDGET_MFGR_NUM)) {
+		/* FIXME: add Xbridge to the WAR.
+		 * Shouldn't hurt anything.  Later need to
+		 * check if we can remove this.
+                 */
+    		if ((part != XBRIDGE_WIDGET_PART_NUM) ||
+		    (mfgr != XBRIDGE_WIDGET_MFGR_NUM))
+			return 0;
+    }
+
+    /* count how many times we
+     * have picked up after
+     * LLP Transmit problems.
+     */
+    xbow_xmit_retry_errors++;
+
+    /* rewrite the control register
+     * to fix things up.
+     */
+    wid->w_control = wid->w_control;
+    wid->w_control;
+
+    return 1;
+}
+
+/*
+ * xbow_errintr_handler will be called if the xbow
+ * sends an interrupt request to report an error.
+ */
+static void
+xbow_errintr_handler(int irq, void *arg, struct pt_regs *ep)
+{
+    ioerror_t               ioe[1];
+    xbow_soft_t             soft = (xbow_soft_t) arg;
+    xbow_t                 *xbow = soft->base;
+    xbowreg_t               wid_control;
+    xbowreg_t               wid_stat;
+    xbowreg_t               wid_err_cmdword;
+    xbowreg_t               wid_err_upper;
+    xbowreg_t               wid_err_lower;
+    w_err_cmd_word_u        wid_err;
+    unsigned long long      wid_err_addr;
+
+    int                     fatal = 0;
+    int                     dump_ioe = 0;
+    static int xbow_error_handler(void *, int, ioerror_mode_t, ioerror_t *);
+
+    wid_control = xbow->xb_wid_control;
+    wid_stat = xbow->xb_wid_stat_clr;
+    wid_err_cmdword = xbow->xb_wid_err_cmdword;
+    wid_err_upper = xbow->xb_wid_err_upper;
+    wid_err_lower = xbow->xb_wid_err_lower;
+    xbow->xb_wid_err_cmdword = 0;
+
+    wid_err_addr = wid_err_lower | (((iopaddr_t) wid_err_upper & WIDGET_ERR_UPPER_ADDR_ONLY) << 32);
+
+    if (wid_stat & XB_WID_STAT_LINK_INTR_MASK) {
+	int                     port;
+
+	wid_err.r = wid_err_cmdword;
+
+	for (port = MAX_PORT_NUM - MAX_XBOW_PORTS;
+	     port < MAX_PORT_NUM; port++) {
+	    if (wid_stat & XB_WID_STAT_LINK_INTR(port)) {
+		xb_linkregs_t          *link = &(xbow->xb_link(port));
+		xbowreg_t               link_control = link->link_control;
+		xbowreg_t               link_status = link->link_status_clr;
+		xbowreg_t               link_aux_status = link->link_aux_status;
+		xbowreg_t               link_pend;
+
+		link_pend = link_status & link_control &
+		    (XB_STAT_ILLEGAL_DST_ERR
+		     | XB_STAT_OALLOC_IBUF_ERR
+		     | XB_STAT_RCV_CNT_OFLOW_ERR
+		     | XB_STAT_XMT_CNT_OFLOW_ERR
+		     | XB_STAT_XMT_MAX_RTRY_ERR
+		     | XB_STAT_RCV_ERR
+		     | XB_STAT_XMT_RTRY_ERR
+		     | XB_STAT_MAXREQ_TOUT_ERR
+		     | XB_STAT_SRC_TOUT_ERR
+		    );
+
+		if (link_pend & XB_STAT_ILLEGAL_DST_ERR) {
+		    if (wid_err.f.sidn == port) {
+			IOERROR_INIT(ioe);
+			IOERROR_SETVALUE(ioe, widgetnum, port);
+			IOERROR_SETVALUE(ioe, xtalkaddr, wid_err_addr);
+			if (IOERROR_HANDLED ==
+			    xbow_error_handler(soft,
+					       IOECODE_DMA,
+					       MODE_DEVERROR,
+					       ioe)) {
+			    link_pend &= ~XB_STAT_ILLEGAL_DST_ERR;
+			} else {
+			    dump_ioe++;
+			}
+		    }
+		}
+		/* Xbow/Bridge WAR:
+		 * if the bridge signals an LLP Transmitter Retry,
+		 * rewrite its control register.
+		 * If someone else triggers this interrupt,
+		 * ignore (and disable) the interrupt.
+		 */
+		if (link_pend & XB_STAT_XMT_RTRY_ERR) {
+		    if (!xbow_xmit_retry_error(soft, port)) {
+			link_control &= ~XB_CTRL_XMT_RTRY_IE;
+			link->link_control = link_control;
+			link->link_control;	/* stall until written */
+		    }
+		    link_pend &= ~XB_STAT_XMT_RTRY_ERR;
+		}
+		if (link_pend) {
+		    devfs_handle_t	xwidget_vhdl;
+		    char		*xwidget_name;
+		    
+		    /* Get the widget name corresponding to the current
+		     * xbow link.
+		     */
+		    xwidget_vhdl = xbow_widget_lookup(soft->busv,port);
+		    xwidget_name = xwidget_name_get(xwidget_vhdl);
+
+		    printk("%s port %X[%s] XIO Bus Error",
+			    soft->name, port, xwidget_name);
+		    if (link_status & XB_STAT_MULTI_ERR)
+			XEM_ADD_STR("\tMultiple Errors\n");
+		    if (link_status & XB_STAT_ILLEGAL_DST_ERR)
+			XEM_ADD_STR("\tInvalid Packet Destination\n");
+		    if (link_status & XB_STAT_OALLOC_IBUF_ERR)
+			XEM_ADD_STR("\tInput Overallocation Error\n");
+		    if (link_status & XB_STAT_RCV_CNT_OFLOW_ERR)
+			XEM_ADD_STR("\tLLP receive error counter overflow\n");
+		    if (link_status & XB_STAT_XMT_CNT_OFLOW_ERR)
+			XEM_ADD_STR("\tLLP transmit retry counter overflow\n");
+		    if (link_status & XB_STAT_XMT_MAX_RTRY_ERR)
+			XEM_ADD_STR("\tLLP Max Transmitter Retry\n");
+		    if (link_status & XB_STAT_RCV_ERR)
+			XEM_ADD_STR("\tLLP Receiver error\n");
+		    if (link_status & XB_STAT_XMT_RTRY_ERR)
+			XEM_ADD_STR("\tLLP Transmitter Retry\n");
+		    if (link_status & XB_STAT_MAXREQ_TOUT_ERR)
+			XEM_ADD_STR("\tMaximum Request Timeout\n");
+		    if (link_status & XB_STAT_SRC_TOUT_ERR)
+			XEM_ADD_STR("\tSource Timeout Error\n");
+
+		    {
+			int                     other_port;
+
+			for (other_port = 8; other_port < 16; ++other_port) {
+			    if (link_aux_status & (1 << other_port)) {
+				/* XXX- need to go to "other_port"
+				 * and clean up after the timeout?
+				 */
+				XEM_ADD_VAR(other_port);
+			    }
+			}
+		    }
+
+#if !DEBUG
+		    if (kdebug) {
+#endif
+			XEM_ADD_VAR(link_control);
+			XEM_ADD_VAR(link_status);
+			XEM_ADD_VAR(link_aux_status);
+
+#ifdef LATER
+			if (dump_ioe) {
+			    XEM_ADD_IOE();
+			    dump_ioe = 0;
+			}
+#endif
+#if !DEBUG
+		    }
+#endif
+		    fatal++;
+		}
+	    }
+	}
+    }
+    if (wid_stat & wid_control & XB_WID_STAT_WIDGET0_INTR) {
+	/* we have a "widget zero" problem */
+
+	if (wid_stat & (XB_WID_STAT_MULTI_ERR
+			| XB_WID_STAT_XTALK_ERR
+			| XB_WID_STAT_REG_ACC_ERR)) {
+
+	    printk("%s Port 0 XIO Bus Error",
+		    soft->name);
+	    if (wid_stat & XB_WID_STAT_MULTI_ERR)
+		XEM_ADD_STR("\tMultiple Error\n");
+	    if (wid_stat & XB_WID_STAT_XTALK_ERR)
+		XEM_ADD_STR("\tXIO Error\n");
+	    if (wid_stat & XB_WID_STAT_REG_ACC_ERR)
+		XEM_ADD_STR("\tRegister Access Error\n");
+
+	    fatal++;
+	}
+    }
+    if (fatal) {
+	XEM_ADD_VAR(wid_stat);
+	XEM_ADD_VAR(wid_control);
+	XEM_ADD_VAR(wid_err_cmdword);
+	XEM_ADD_VAR(wid_err_upper);
+	XEM_ADD_VAR(wid_err_lower);
+	XEM_ADD_VAR(wid_err_addr);
+	PRINT_PANIC("XIO Bus Error");
+    }
+}
+
+/*
+ * XBOW ERROR Handling routines.
+ * These get invoked as part of walking down the error handling path
+ * from hub/heart towards the I/O device that caused the error.
+ */
+
+/*
+ * xbow_error_handler
+ *      XBow error handling dispatch routine.
+ *      This is the primary interface used by external world to invoke
+ *      in case of an error related to a xbow.
+ *      Only functionality in this layer is to identify the widget handle
+ *      given the widgetnum. Otherwise, xbow does not gathers any error
+ *      data.
+ */
+static int
+xbow_error_handler(
+		      void *einfo,
+		      int error_code,
+		      ioerror_mode_t mode,
+		      ioerror_t *ioerror)
+{
+    int                     retval = IOERROR_WIDGETLEVEL;
+
+    xbow_soft_t             soft = (xbow_soft_t) einfo;
+    int                     port;
+    devfs_handle_t          conn;
+    devfs_handle_t          busv;
+
+    xbow_t                 *xbow = soft->base;
+    xbowreg_t               wid_stat;
+    xbowreg_t               wid_err_cmdword;
+    xbowreg_t               wid_err_upper;
+    xbowreg_t               wid_err_lower;
+    unsigned long long      wid_err_addr;
+
+    xb_linkregs_t          *link;
+    xbowreg_t               link_control;
+    xbowreg_t               link_status;
+    xbowreg_t               link_aux_status;
+
+    ASSERT(soft != 0);
+    busv = soft->busv;
+
+#if DEBUG && ERROR_DEBUG
+    printk("%s: xbow_error_handler\n", soft->name, busv);
+#endif
+
+    IOERROR_GETVALUE(port, ioerror, widgetnum);
+
+    if (port == 0) {
+	/* error during access to xbow:
+	 * do NOT attempt to access xbow regs.
+	 */
+	if (mode == MODE_DEVPROBE)
+	    return IOERROR_HANDLED;
+
+	if (error_code & IOECODE_DMA) {
+	    printk(KERN_ALERT
+		    "DMA error blamed on Crossbow at %s\n"
+		    "\tbut Crosbow never initiates DMA!",
+		    soft->name);
+	}
+	if (error_code & IOECODE_PIO) {
+	    iopaddr_t tmp;
+	    IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);
+	    printk(KERN_ALERT "PIO Error on XIO Bus %s\n"
+		    "\tattempting to access XIO controller\n"
+		    "\twith offset 0x%lx",
+		    soft->name, tmp);
+	}
+	/* caller will dump contents of ioerror
+	 * in DEBUG and kdebug kernels.
+	 */
+
+	return retval;
+    }
+    /*
+     * error not on port zero:
+     * safe to read xbow registers.
+     */
+    wid_stat = xbow->xb_wid_stat;
+    wid_err_cmdword = xbow->xb_wid_err_cmdword;
+    wid_err_upper = xbow->xb_wid_err_upper;
+    wid_err_lower = xbow->xb_wid_err_lower;
+
+    wid_err_addr =
+	wid_err_lower
+	| (((iopaddr_t) wid_err_upper
+	    & WIDGET_ERR_UPPER_ADDR_ONLY)
+	   << 32);
+
+    if ((port < BASE_XBOW_PORT) ||
+	(port >= MAX_PORT_NUM)) {
+
+	if (mode == MODE_DEVPROBE)
+	    return IOERROR_HANDLED;
+
+	if (error_code & IOECODE_DMA) {
+	    printk(KERN_ALERT
+		    "DMA error blamed on XIO port at %s/%d\n"
+		    "\tbut Crossbow does not support that port",
+		    soft->name, port);
+	}
+	if (error_code & IOECODE_PIO) {
+	    iopaddr_t tmp;
+	    IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);
+	    printk(KERN_ALERT
+		    "PIO Error on XIO Bus %s\n"
+		    "\tattempting to access XIO port %d\n"
+		    "\t(which Crossbow does not support)"
+		    "\twith offset 0x%lx",
+		    soft->name, port, tmp);
+	}
+#if !DEBUG
+	if (kdebug) {
+#endif
+	    XEM_ADD_STR("Raw status values for Crossbow:\n");
+	    XEM_ADD_VAR(wid_stat);
+	    XEM_ADD_VAR(wid_err_cmdword);
+	    XEM_ADD_VAR(wid_err_upper);
+	    XEM_ADD_VAR(wid_err_lower);
+	    XEM_ADD_VAR(wid_err_addr);
+#if !DEBUG
+	}
+#endif
+
+	/* caller will dump contents of ioerror
+	 * in DEBUG and kdebug kernels.
+	 */
+
+	return retval;
+    }
+    /* access to valid port:
+     * ok to check port status.
+     */
+
+    link = &(xbow->xb_link(port));
+    link_control = link->link_control;
+    link_status = link->link_status;
+    link_aux_status = link->link_aux_status;
+
+    /* Check that there is something present
+     * in that XIO port.
+     */
+    /* WAR: PIC widget 0xf is missing prescense bit */
+    if (XBOW_WAR_ENABLED(PV854827, xbow->xb_wid_id) &&
+		IS_PIC_XBOW(xbow->xb_wid_id) && (port==0xf))
+		;
+    else
+    if (!(link_aux_status & XB_AUX_STAT_PRESENT)) {
+	/* nobody connected. */
+	if (mode == MODE_DEVPROBE)
+	    return IOERROR_HANDLED;
+
+	if (error_code & IOECODE_DMA) {
+	    printk(KERN_ALERT
+		    "DMA error blamed on XIO port at %s/%d\n"
+		    "\tbut there is no device connected there.",
+		    soft->name, port);
+	}
+	if (error_code & IOECODE_PIO) {
+	    iopaddr_t tmp;
+	    IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);
+	    printk(KERN_ALERT
+		    "PIO Error on XIO Bus %s\n"
+		    "\tattempting to access XIO port %d\n"
+		    "\t(which has no device connected)"
+		    "\twith offset 0x%lx",
+		    soft->name, port, tmp);
+	}
+#if !DEBUG
+	if (kdebug) {
+#endif
+	    XEM_ADD_STR("Raw status values for Crossbow:\n");
+	    XEM_ADD_VAR(wid_stat);
+	    XEM_ADD_VAR(wid_err_cmdword);
+	    XEM_ADD_VAR(wid_err_upper);
+	    XEM_ADD_VAR(wid_err_lower);
+	    XEM_ADD_VAR(wid_err_addr);
+	    XEM_ADD_VAR(port);
+	    XEM_ADD_VAR(link_control);
+	    XEM_ADD_VAR(link_status);
+	    XEM_ADD_VAR(link_aux_status);
+#if !DEBUG
+	}
+#endif
+	return retval;
+
+    }
+    /* Check that the link is alive.
+     */
+    if (!(link_status & XB_STAT_LINKALIVE)) {
+	iopaddr_t tmp;
+	/* nobody connected. */
+	if (mode == MODE_DEVPROBE)
+	    return IOERROR_HANDLED;
+
+	printk(KERN_ALERT
+		"%s%sError on XIO Bus %s port %d",
+		(error_code & IOECODE_DMA) ? "DMA " : "",
+		(error_code & IOECODE_PIO) ? "PIO " : "",
+		soft->name, port);
+
+	IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);
+	if ((error_code & IOECODE_PIO) &&
+	    (IOERROR_FIELDVALID(ioerror, xtalkaddr))) {
+		printk("\tAccess attempted to offset 0x%lx\n", tmp);
+	}
+	if (link_aux_status & XB_AUX_LINKFAIL_RST_BAD)
+	    XEM_ADD_STR("\tLink never came out of reset\n");
+	else
+	    XEM_ADD_STR("\tLink failed while transferring data\n");
+
+    }
+    /* get the connection point for the widget
+     * involved in this error; if it exists and
+     * is not our connectpoint, cycle back through
+     * xtalk_error_handler to deliver control to
+     * the proper handler (or to report a generic
+     * crosstalk error).
+     *
+     * If the downstream handler won't handle
+     * the problem, we let our upstream caller
+     * deal with it, after (in DEBUG and kdebug
+     * kernels) dumping the xbow state for this
+     * port.
+     */
+    conn = xbow_widget_lookup(busv, port);
+    if ((conn != GRAPH_VERTEX_NONE) &&
+	(conn != soft->conn)) {
+	retval = xtalk_error_handler(conn, error_code, mode, ioerror);
+	if (retval == IOERROR_HANDLED)
+	    return IOERROR_HANDLED;
+    }
+    if (mode == MODE_DEVPROBE)
+	return IOERROR_HANDLED;
+
+    if (retval == IOERROR_UNHANDLED) {
+	iopaddr_t tmp;
+	retval = IOERROR_PANIC;
+
+	printk(KERN_ALERT
+		"%s%sError on XIO Bus %s port %d",
+		(error_code & IOECODE_DMA) ? "DMA " : "",
+		(error_code & IOECODE_PIO) ? "PIO " : "",
+		soft->name, port);
+
+	IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);
+	if ((error_code & IOECODE_PIO) &&
+	    (IOERROR_FIELDVALID(ioerror, xtalkaddr))) {
+	    printk("\tAccess attempted to offset 0x%lx\n", tmp);
+	}
+    }
+
+#if !DEBUG
+    if (kdebug) {
+#endif
+	XEM_ADD_STR("Raw status values for Crossbow:\n");
+	XEM_ADD_VAR(wid_stat);
+	XEM_ADD_VAR(wid_err_cmdword);
+	XEM_ADD_VAR(wid_err_upper);
+	XEM_ADD_VAR(wid_err_lower);
+	XEM_ADD_VAR(wid_err_addr);
+	XEM_ADD_VAR(port);
+	XEM_ADD_VAR(link_control);
+	XEM_ADD_VAR(link_status);
+	XEM_ADD_VAR(link_aux_status);
+#if !DEBUG
+    }
+#endif
+    /* caller will dump raw ioerror data
+     * in DEBUG and kdebug kernels.
+     */
+
+    return retval;
+}
+
+void
+xbow_update_perf_counters(devfs_handle_t vhdl)
+{
+    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
+    xbow_perf_t            *xbow_perf = xbow_soft->xbow_perfcnt;
+    xbow_perf_link_t       *xbow_plink = xbow_soft->xbow_perflink;
+    xbow_perfcount_t        perf_reg;
+    unsigned long           s;
+    int                     link, i;
+
+    for (i = 0; i < XBOW_PERF_COUNTERS; i++, xbow_perf++) {
+	if (xbow_perf->xp_mode == XBOW_MONITOR_NONE)
+	    continue;
+
+	s = mutex_spinlock(&xbow_soft->xbow_perf_lock);
+
+	perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg;
+
+	link = perf_reg.xb_perf.link_select;
+
+	(xbow_plink + link)->xlp_cumulative[xbow_perf->xp_curmode] +=
+	    ((perf_reg.xb_perf.count - xbow_perf->xp_current) & XBOW_COUNTER_MASK);
+	xbow_perf->xp_current = perf_reg.xb_perf.count;
+
+	mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
+    }
+}
+
+xbow_perf_link_t       *
+xbow_get_perf_counters(devfs_handle_t vhdl)
+{
+    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
+    xbow_perf_link_t       *xbow_perf_link = xbow_soft->xbow_perflink;
+
+    return xbow_perf_link;
+}
+
+int
+xbow_enable_perf_counter(devfs_handle_t vhdl, int link, int mode, int counter)
+{
+    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
+    xbow_perf_t            *xbow_perf = xbow_soft->xbow_perfcnt;
+    xbow_linkctrl_t         xbow_link_ctrl;
+    xbow_t                 *xbow = xbow_soft->base;
+    xbow_perfcount_t        perf_reg;
+    unsigned long           s;
+    int                     i;
+
+    link -= BASE_XBOW_PORT;
+    if ((link < 0) || (link >= MAX_XBOW_PORTS))
+	return -1;
+
+    if ((mode < XBOW_MONITOR_NONE) || (mode > XBOW_MONITOR_DEST_LINK))
+	return -1;
+
+    if ((counter < 0) || (counter >= XBOW_PERF_COUNTERS))
+	return -1;
+
+    s = mutex_spinlock(&xbow_soft->xbow_perf_lock);
+
+    if ((xbow_perf + counter)->xp_mode && mode) {
+	mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
+	return -1;
+    }
+    for (i = 0; i < XBOW_PERF_COUNTERS; i++) {
+	if (i == counter)
+	    continue;
+	if (((xbow_perf + i)->xp_link == link) &&
+	    ((xbow_perf + i)->xp_mode)) {
+	    mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
+	    return -1;
+	}
+    }
+    xbow_perf += counter;
+
+    xbow_perf->xp_curlink = xbow_perf->xp_link = link;
+    xbow_perf->xp_curmode = xbow_perf->xp_mode = mode;
+
+    xbow_link_ctrl.xbl_ctrlword = xbow->xb_link_raw[link].link_control;
+    xbow_link_ctrl.xb_linkcontrol.perf_mode = mode;
+    xbow->xb_link_raw[link].link_control = xbow_link_ctrl.xbl_ctrlword;
+
+    perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg;
+    perf_reg.xb_perf.link_select = link;
+    *(xbowreg_t *) xbow_perf->xp_perf_reg = perf_reg.xb_counter_val;
+    xbow_perf->xp_current = perf_reg.xb_perf.count;
+
+    mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
+    return 0;
+}
+
+xbow_link_status_t     *
+xbow_get_llp_status(devfs_handle_t vhdl)
+{
+    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
+    xbow_link_status_t     *xbow_llp_status = xbow_soft->xbow_link_status;
+
+    return xbow_llp_status;
+}
+
+void
+xbow_update_llp_status(devfs_handle_t vhdl)
+{
+    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
+    xbow_link_status_t     *xbow_llp_status = xbow_soft->xbow_link_status;
+    xbow_t                 *xbow;
+    xbwX_stat_t             lnk_sts;
+    xbow_aux_link_status_t  aux_sts;
+    int                     link;
+    devfs_handle_t	    xwidget_vhdl;
+    char		   *xwidget_name;	
+
+    xbow = (xbow_t *) xbow_soft->base;
+    for (link = 0; link < MAX_XBOW_PORTS; link++, xbow_llp_status++) {
+	/* Get the widget name corresponding the current link.
+	 * Note : 0 <= link < MAX_XBOW_PORTS(8).
+	 * 	  BASE_XBOW_PORT(0x8) <= xwidget number < MAX_PORT_NUM (0x10)
+	 */
+	xwidget_vhdl = xbow_widget_lookup(xbow_soft->busv,link+BASE_XBOW_PORT);
+	xwidget_name = xwidget_name_get(xwidget_vhdl);
+	aux_sts.aux_linkstatus
+	    = xbow->xb_link_raw[link].link_aux_status;
+	lnk_sts.linkstatus = xbow->xb_link_raw[link].link_status_clr;
+
+	if (lnk_sts.link_alive == 0)
+	    continue;
+
+	xbow_llp_status->rx_err_count +=
+	    aux_sts.xb_aux_linkstatus.rx_err_cnt;
+
+	xbow_llp_status->tx_retry_count +=
+	    aux_sts.xb_aux_linkstatus.tx_retry_cnt;
+
+	if (lnk_sts.linkstatus & ~(XB_STAT_RCV_ERR | XB_STAT_XMT_RTRY_ERR | XB_STAT_LINKALIVE)) {
+#ifdef	LATER
+	    printk(KERN_WARNING  "link %d[%s]: bad status 0x%x\n",
+		    link, xwidget_name, lnk_sts.linkstatus);
+#endif
+	}
+    }
+}
+
+int
+xbow_disable_llp_monitor(devfs_handle_t vhdl)
+{
+    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
+    int                     port;
+
+    for (port = 0; port < MAX_XBOW_PORTS; port++) {
+	xbow_soft->xbow_link_status[port].rx_err_count = 0;
+	xbow_soft->xbow_link_status[port].tx_retry_count = 0;
+    }
+
+    xbow_soft->link_monitor = 0;
+    return 0;
+}
+
+int
+xbow_enable_llp_monitor(devfs_handle_t vhdl)
+{
+    xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
+
+    xbow_soft->link_monitor = 1;
+    return 0;
+}
+
+
+int
+xbow_reset_link(devfs_handle_t xconn_vhdl)
+{
+    xwidget_info_t          widget_info;
+    xwidgetnum_t            port;
+    xbow_t                 *xbow;
+    xbowreg_t               ctrl;
+    xbwX_stat_t             stat;
+    unsigned                itick;
+    unsigned                dtick;
+    static int              ticks_per_ms = 0;
+
+    if (!ticks_per_ms) {
+	itick = get_timestamp();
+	us_delay(1000);
+	ticks_per_ms = get_timestamp() - itick;
+    }
+    widget_info = xwidget_info_get(xconn_vhdl);
+    port = xwidget_info_id_get(widget_info);
+
+#ifdef XBOW_K1PTR			/* defined if we only have one xbow ... */
+    xbow = XBOW_K1PTR;
+#else
+    {
+	devfs_handle_t            xbow_vhdl;
+	xbow_soft_t             xbow_soft;
+
+	hwgraph_traverse(xconn_vhdl, ".master/xtalk/0/xbow", &xbow_vhdl);
+	xbow_soft = xbow_soft_get(xbow_vhdl);
+	xbow = xbow_soft->base;
+    }
+#endif
+
+    /*
+     * This requires three PIOs (reset the link, check for the
+     * reset, restore the control register for the link) plus
+     * 10us to wait for the reset. We allow up to 1ms for the
+     * widget to come out of reset before giving up and
+     * returning a failure.
+     */
+    ctrl = xbow->xb_link(port).link_control;
+    xbow->xb_link(port).link_reset = 0;
+    itick = get_timestamp();
+    while (1) {
+	stat.linkstatus = xbow->xb_link(port).link_status;
+	if (stat.link_alive)
+	    break;
+	dtick = get_timestamp() - itick;
+	if (dtick > ticks_per_ms) {
+	    return -1;			/* never came out of reset */
+	}
+	DELAY(2);			/* don't beat on link_status */
+    }
+    xbow->xb_link(port).link_control = ctrl;
+    return 0;
+}
+
+/*
+ * Dump xbow registers.
+ * input parameter is either a pointer to
+ * the xbow chip or the vertex handle for
+ * an xbow vertex.
+ */
+void
+idbg_xbowregs(int64_t regs)
+{
+    xbow_t                 *xbow;
+    int                     i;
+    xb_linkregs_t          *link;
+
+    xbow = (xbow_t *) regs;
+
+#ifdef LATER
+    qprintf("Printing xbow registers starting at 0x%x\n", xbow);
+    qprintf("wid %x status %x erruppr %x errlower %x control %x timeout %x\n",
+	    xbow->xb_wid_id, xbow->xb_wid_stat, xbow->xb_wid_err_upper,
+	    xbow->xb_wid_err_lower, xbow->xb_wid_control,
+	    xbow->xb_wid_req_timeout);
+    qprintf("intr uppr %x lower %x errcmd %x llp ctrl %x arb_reload %x\n",
+	    xbow->xb_wid_int_upper, xbow->xb_wid_int_lower,
+	    xbow->xb_wid_err_cmdword, xbow->xb_wid_llp,
+	    xbow->xb_wid_arb_reload);
+#endif
+
+    for (i = 8; i <= 0xf; i++) {
+	link = &xbow->xb_link(i);
+#ifdef LATER
+	qprintf("Link %d registers\n", i);
+	qprintf("\tctrl %x stat %x arbuppr %x arblowr %x auxstat %x\n",
+		link->link_control, link->link_status,
+		link->link_arb_upper, link->link_arb_lower,
+		link->link_aux_status);
+#endif
+    }
+}
+
+
+#define XBOW_ARB_RELOAD_TICKS		25
+					/* granularity: 4 MB/s, max: 124 MB/s */
+#define GRANULARITY			((100 * 1000000) / XBOW_ARB_RELOAD_TICKS)
+
+#define XBOW_BYTES_TO_GBR(BYTES_per_s)	(int) (BYTES_per_s / GRANULARITY)
+
+#define XBOW_GBR_TO_BYTES(cnt)		(bandwidth_t) ((cnt) * GRANULARITY)
+
+#define CEILING_BYTES_TO_GBR(gbr, bytes_per_sec)	\
+			((XBOW_GBR_TO_BYTES(gbr) < bytes_per_sec) ? gbr+1 : gbr)
+
+#define XBOW_ARB_GBR_MAX		31
+
+#define ABS(x)				((x > 0) ? (x) : (-1 * x))
+					/* absolute value */
+
+int
+xbow_bytes_to_gbr(bandwidth_t old_bytes_per_sec, bandwidth_t bytes_per_sec)
+{
+    int                     gbr_granted;
+    int                     new_total_gbr;
+    int                     change_gbr;
+    bandwidth_t             new_total_bw;
+
+#ifdef GRIO_DEBUG
+    printk("xbow_bytes_to_gbr: old_bytes_per_sec %lld bytes_per_sec %lld\n",
+		old_bytes_per_sec, bytes_per_sec);
+#endif	/* GRIO_DEBUG */
+
+    gbr_granted = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(old_bytes_per_sec)),
+			old_bytes_per_sec);
+    new_total_bw = old_bytes_per_sec + bytes_per_sec;
+    new_total_gbr = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(new_total_bw)),
+			new_total_bw);
+
+    change_gbr = new_total_gbr - gbr_granted;
+
+#ifdef GRIO_DEBUG
+    printk("xbow_bytes_to_gbr: gbr_granted %d new_total_gbr %d change_gbr %d\n",
+		gbr_granted, new_total_gbr, change_gbr);
+#endif	/* GRIO_DEBUG */
+
+    return (change_gbr);
+}
+
+/* Conversion from GBR to bytes */
+bandwidth_t
+xbow_gbr_to_bytes(int gbr)
+{
+    return (XBOW_GBR_TO_BYTES(gbr));
+}
+
+/* Given the vhdl for the desired xbow, the src and dest. widget ids
+ * and the req_bw value, this xbow driver entry point accesses the
+ * xbow registers and allocates the desired bandwidth if available.
+ *
+ * If bandwidth allocation is successful, return success else return failure.
+ */
+int
+xbow_prio_bw_alloc(devfs_handle_t vhdl,
+		xwidgetnum_t src_wid,
+		xwidgetnum_t dest_wid,
+		unsigned long long old_alloc_bw,
+		unsigned long long req_bw)
+{
+    xbow_soft_t             soft = xbow_soft_get(vhdl);
+    volatile xbowreg_t     *xreg;
+    xbowreg_t               mask;
+    unsigned long           s;
+    int                     error = 0;
+    bandwidth_t             old_bw_BYTES, req_bw_BYTES;
+    xbowreg_t               old_xreg;
+    int                     old_bw_GBR, req_bw_GBR, new_bw_GBR;
+
+#ifdef GRIO_DEBUG
+    printk("xbow_prio_bw_alloc: vhdl %d src_wid %d dest_wid %d req_bw %lld\n",
+		(int) vhdl, (int) src_wid, (int) dest_wid, req_bw);
+#endif
+
+    ASSERT(XBOW_WIDGET_IS_VALID(src_wid));
+    ASSERT(XBOW_WIDGET_IS_VALID(dest_wid));
+
+    s = mutex_spinlock(&soft->xbow_bw_alloc_lock);
+
+    /* Get pointer to the correct register */
+    xreg = XBOW_PRIO_ARBREG_PTR(soft->base, dest_wid, src_wid);
+
+    /* Get mask for GBR count value */
+    mask = XB_ARB_GBR_MSK << XB_ARB_GBR_SHFT(src_wid);
+
+    req_bw_GBR = xbow_bytes_to_gbr(old_alloc_bw, req_bw);
+    req_bw_BYTES = (req_bw_GBR < 0) ? (-1 * xbow_gbr_to_bytes(ABS(req_bw_GBR)))
+		: xbow_gbr_to_bytes(req_bw_GBR);
+
+#ifdef GRIO_DEBUG
+    printk("req_bw %lld req_bw_BYTES %lld req_bw_GBR %d\n",
+		req_bw, req_bw_BYTES, req_bw_GBR);
+#endif	/* GRIO_DEBUG */
+
+    old_bw_BYTES = soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS];
+    old_xreg = *xreg;
+    old_bw_GBR = (((*xreg) & mask) >> XB_ARB_GBR_SHFT(src_wid));
+
+#ifdef GRIO_DEBUG
+    ASSERT(XBOW_BYTES_TO_GBR(old_bw_BYTES) == old_bw_GBR);
+
+    printk("old_bw_BYTES %lld old_bw_GBR %d\n", old_bw_BYTES, old_bw_GBR);
+
+    printk("req_bw_BYTES %lld old_bw_BYTES %lld soft->bw_hiwm %lld\n",
+		req_bw_BYTES, old_bw_BYTES,
+		soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]);
+	   
+#endif				/* GRIO_DEBUG */
+
+    /* Accept the request only if we don't exceed the destination
+     * port HIWATER_MARK *AND* the max. link GBR arbitration count
+     */
+    if (((old_bw_BYTES + req_bw_BYTES) <=
+		soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]) &&
+		(req_bw_GBR + old_bw_GBR <= XBOW_ARB_GBR_MAX)) {
+
+	new_bw_GBR = (old_bw_GBR + req_bw_GBR);
+
+	/* Set this in the xbow link register */
+	*xreg = (old_xreg & ~mask) | \
+	    (new_bw_GBR << XB_ARB_GBR_SHFT(src_wid) & mask);
+
+	soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS] =
+			xbow_gbr_to_bytes(new_bw_GBR);
+    } else {
+	error = 1;
+    }
+
+    mutex_spinunlock(&soft->xbow_bw_alloc_lock, s);
+
+    return (error);
+}
diff -Nru a/arch/ia64/sn/io/sn2/xtalk.c b/arch/ia64/sn/io/sn2/xtalk.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/xtalk.c	Mon Feb 24 05:35:59 2003
@@ -0,0 +1,1087 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/driver.h>
+#include <asm/sn/io.h>
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/hcl_util.h>
+#include <asm/sn/xtalk/xtalk.h>
+#include <asm/sn/xtalk/xswitch.h>
+#include <asm/sn/xtalk/xwidget.h>
+#include <asm/sn/xtalk/xtalk_private.h>
+
+/*
+ * Implement crosstalk provider operations.  The xtalk* layer provides a
+ * platform-independent interface for crosstalk devices.  This layer
+ * switches among the possible implementations of a crosstalk adapter.
+ *
+ * On platforms with only one possible xtalk provider, macros can be
+ * set up at the top that cause the table lookups and indirections to
+ * completely disappear.
+ */
+
+#define	NEW(ptr)	(ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL))
+#define	DEL(ptr)	(kfree(ptr))
+
+char                    widget_info_fingerprint[] = "widget_info";
+
+cdl_p                   xtalk_registry = NULL;
+
+#define	DEV_FUNC(dev,func)	hub_##func
+#define	CAST_PIOMAP(x)		((hub_piomap_t)(x))
+#define	CAST_DMAMAP(x)		((hub_dmamap_t)(x))
+#define	CAST_INTR(x)		((hub_intr_t)(x))
+
+/* =====================================================================
+ *            Function Table of Contents
+ */
+xtalk_piomap_t          xtalk_piomap_alloc(devfs_handle_t, device_desc_t, iopaddr_t, size_t, size_t, unsigned);
+void                    xtalk_piomap_free(xtalk_piomap_t);
+caddr_t                 xtalk_piomap_addr(xtalk_piomap_t, iopaddr_t, size_t);
+void                    xtalk_piomap_done(xtalk_piomap_t);
+caddr_t                 xtalk_piotrans_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, unsigned);
+caddr_t                 xtalk_pio_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, xtalk_piomap_t *, unsigned);
+void                    xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *);
+caddr_t                 xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned);
+static caddr_t          null_xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned);
+xtalk_dmamap_t          xtalk_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned);
+void                    xtalk_dmamap_free(xtalk_dmamap_t);
+iopaddr_t               xtalk_dmamap_addr(xtalk_dmamap_t, paddr_t, size_t);
+alenlist_t              xtalk_dmamap_list(xtalk_dmamap_t, alenlist_t, unsigned);
+void                    xtalk_dmamap_done(xtalk_dmamap_t);
+iopaddr_t               xtalk_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned);
+alenlist_t              xtalk_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned);
+void			xtalk_dmamap_drain(xtalk_dmamap_t);
+void			xtalk_dmaaddr_drain(devfs_handle_t, iopaddr_t, size_t);
+void			xtalk_dmalist_drain(devfs_handle_t, alenlist_t);
+xtalk_intr_t            xtalk_intr_alloc(devfs_handle_t, device_desc_t, devfs_handle_t);
+xtalk_intr_t            xtalk_intr_alloc_nothd(devfs_handle_t, device_desc_t, devfs_handle_t);
+void                    xtalk_intr_free(xtalk_intr_t);
+int                     xtalk_intr_connect(xtalk_intr_t, intr_func_t, intr_arg_t, xtalk_intr_setfunc_t, void *);
+void                    xtalk_intr_disconnect(xtalk_intr_t);
+devfs_handle_t            xtalk_intr_cpu_get(xtalk_intr_t);
+int                     xtalk_error_handler(devfs_handle_t, int, ioerror_mode_t, ioerror_t *);
+int                     xtalk_error_devenable(devfs_handle_t, int, int);
+void                    xtalk_provider_startup(devfs_handle_t);
+void                    xtalk_provider_shutdown(devfs_handle_t);
+devfs_handle_t            xtalk_intr_dev_get(xtalk_intr_t);
+xwidgetnum_t            xtalk_intr_target_get(xtalk_intr_t);
+xtalk_intr_vector_t     xtalk_intr_vector_get(xtalk_intr_t);
+iopaddr_t               xtalk_intr_addr_get(struct xtalk_intr_s *);
+void                   *xtalk_intr_sfarg_get(xtalk_intr_t);
+devfs_handle_t            xtalk_pio_dev_get(xtalk_piomap_t);
+xwidgetnum_t            xtalk_pio_target_get(xtalk_piomap_t);
+iopaddr_t               xtalk_pio_xtalk_addr_get(xtalk_piomap_t);
+ulong                   xtalk_pio_mapsz_get(xtalk_piomap_t);
+caddr_t                 xtalk_pio_kvaddr_get(xtalk_piomap_t);
+devfs_handle_t            xtalk_dma_dev_get(xtalk_dmamap_t);
+xwidgetnum_t            xtalk_dma_target_get(xtalk_dmamap_t);
+xwidget_info_t          xwidget_info_chk(devfs_handle_t);
+xwidget_info_t          xwidget_info_get(devfs_handle_t);
+void                    xwidget_info_set(devfs_handle_t, xwidget_info_t);
+devfs_handle_t            xwidget_info_dev_get(xwidget_info_t);
+xwidgetnum_t            xwidget_info_id_get(xwidget_info_t);
+devfs_handle_t            xwidget_info_master_get(xwidget_info_t);
+xwidgetnum_t            xwidget_info_masterid_get(xwidget_info_t);
+xwidget_part_num_t      xwidget_info_part_num_get(xwidget_info_t);
+xwidget_mfg_num_t       xwidget_info_mfg_num_get(xwidget_info_t);
+char 			*xwidget_info_name_get(xwidget_info_t);
+void                    xtalk_init(void);
+void                    xtalk_provider_register(devfs_handle_t, xtalk_provider_t *);
+void                    xtalk_provider_unregister(devfs_handle_t);
+xtalk_provider_t       *xtalk_provider_fns_get(devfs_handle_t);
+int                     xwidget_driver_register(xwidget_part_num_t, 
+						xwidget_mfg_num_t, 
+						char *, unsigned);
+void                    xwidget_driver_unregister(char *);
+int                     xwidget_register(xwidget_hwid_t, devfs_handle_t, 
+					 xwidgetnum_t, devfs_handle_t, 
+					 xwidgetnum_t, async_attach_t);
+int			xwidget_unregister(devfs_handle_t);
+void                    xwidget_reset(devfs_handle_t);
+char			*xwidget_name_get(devfs_handle_t);
+#if !defined(DEV_FUNC)
+/*
+ * There is more than one possible provider
+ * for this platform. We need to examine the
+ * master vertex of the current vertex for
+ * a provider function structure, and indirect
+ * through the appropriately named member.
+ */
+#define	DEV_FUNC(dev,func)	xwidget_to_provider_fns(dev)->func
+#define	CAST_PIOMAP(x)		((xtalk_piomap_t)(x))
+#define	CAST_DMAMAP(x)		((xtalk_dmamap_t)(x))
+#define	CAST_INTR(x)		((xtalk_intr_t)(x))
+
+static xtalk_provider_t *
+xwidget_to_provider_fns(devfs_handle_t xconn)
+{
+    xwidget_info_t          widget_info;
+    xtalk_provider_t       *provider_fns;
+
+    widget_info = xwidget_info_get(xconn);
+    ASSERT(widget_info != NULL);
+
+    provider_fns = xwidget_info_pops_get(widget_info);
+    ASSERT(provider_fns != NULL);
+
+    return (provider_fns);
+}
+#endif
+
+/*
+ * Many functions are not passed their vertex
+ * information directly; rather, they must
+ * dive through a resource map. These macros
+ * are available to coordinate this detail.
+ */
+#define	PIOMAP_FUNC(map,func)	DEV_FUNC(map->xp_dev,func)
+#define	DMAMAP_FUNC(map,func)	DEV_FUNC(map->xd_dev,func)
+#define	INTR_FUNC(intr,func)	DEV_FUNC(intr_hdl->xi_dev,func)
+
+/* =====================================================================
+ *                    PIO MANAGEMENT
+ *
+ *      For mapping system virtual address space to
+ *      xtalk space on a specified widget
+ */
+
+xtalk_piomap_t
+xtalk_piomap_alloc(devfs_handle_t dev,	/* set up mapping for this device */
+		   device_desc_t dev_desc,	/* device descriptor */
+		   iopaddr_t xtalk_addr,	/* map for this xtalk_addr range */
+		   size_t byte_count,
+		   size_t byte_count_max,	/* maximum size of a mapping */
+		   unsigned flags)
+{				/* defined in sys/pio.h */
+    return (xtalk_piomap_t) DEV_FUNC(dev, piomap_alloc)
+	(dev, dev_desc, xtalk_addr, byte_count, byte_count_max, flags);
+}
+
+
+void
+xtalk_piomap_free(xtalk_piomap_t xtalk_piomap)
+{
+    PIOMAP_FUNC(xtalk_piomap, piomap_free)
+	(CAST_PIOMAP(xtalk_piomap));
+}
+
+
+caddr_t
+xtalk_piomap_addr(xtalk_piomap_t xtalk_piomap,	/* mapping resources */
+		  iopaddr_t xtalk_addr,		/* map for this xtalk address */
+		  size_t byte_count)
+{				/* map this many bytes */
+    return PIOMAP_FUNC(xtalk_piomap, piomap_addr)
+	(CAST_PIOMAP(xtalk_piomap), xtalk_addr, byte_count);
+}
+
+
+void
+xtalk_piomap_done(xtalk_piomap_t xtalk_piomap)
+{
+    PIOMAP_FUNC(xtalk_piomap, piomap_done)
+	(CAST_PIOMAP(xtalk_piomap));
+}
+
+
+caddr_t
+xtalk_piotrans_addr(devfs_handle_t dev,	/* translate for this device */
+		    device_desc_t dev_desc,	/* device descriptor */
+		    iopaddr_t xtalk_addr,	/* Crosstalk address */
+		    size_t byte_count,	/* map this many bytes */
+		    unsigned flags)
+{				/* (currently unused) */
+    return DEV_FUNC(dev, piotrans_addr)
+	(dev, dev_desc, xtalk_addr, byte_count, flags);
+}
+
+caddr_t
+xtalk_pio_addr(devfs_handle_t dev,	/* translate for this device */
+	       device_desc_t dev_desc,	/* device descriptor */
+	       iopaddr_t addr,		/* starting address (or offset in window) */
+	       size_t byte_count,	/* map this many bytes */
+	       xtalk_piomap_t *mapp,	/* where to return the map pointer */
+	       unsigned flags)
+{					/* PIO flags */
+    xtalk_piomap_t          map = 0;
+    caddr_t                 res;
+
+    if (mapp)
+	*mapp = 0;			/* record "no map used" */
+
+    res = xtalk_piotrans_addr
+	(dev, dev_desc, addr, byte_count, flags);
+    if (res)
+	return res;			/* xtalk_piotrans worked */
+
+    map = xtalk_piomap_alloc
+	(dev, dev_desc, addr, byte_count, byte_count, flags);
+    if (!map)
+	return res;			/* xtalk_piomap_alloc failed */
+
+    res = xtalk_piomap_addr
+	(map, addr, byte_count);
+    if (!res) {
+	xtalk_piomap_free(map);
+	return res;			/* xtalk_piomap_addr failed */
+    }
+    if (mapp)
+	*mapp = map;			/* pass back map used */
+
+    return res;				/* xtalk_piomap_addr succeeded */
+}
+
+/* =====================================================================
+ *            EARLY PIOTRANS SUPPORT
+ *
+ *      There are places where drivers (mgras, for instance)
+ *      need to get PIO translations before the infrastructure
+ *      is extended to them (setting up textports, for
+ *      instance). These drivers should call
+ *      xtalk_early_piotrans_addr with their xtalk ID
+ *      information, a sequence number (so we can use the second
+ *      mgras for instance), and the usual piotrans parameters.
+ *
+ *      Machine specific code should provide an implementation
+ *      of early_piotrans_addr, and present a pointer to this
+ *      function to xtalk_set_early_piotrans_addr so it can be
+ *      used by clients without the clients having to know what
+ *      platform or what xtalk provider is in use.
+ */
+
+static xtalk_early_piotrans_addr_f null_xtalk_early_piotrans_addr;
+
+xtalk_early_piotrans_addr_f *impl_early_piotrans_addr = null_xtalk_early_piotrans_addr;
+
+/* xtalk_set_early_piotrans_addr:
+ * specify the early_piotrans_addr implementation function.
+ */
+void
+xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *impl)
+{
+    impl_early_piotrans_addr = impl;
+}
+
+/* xtalk_early_piotrans_addr:
+ * figure out a PIO address for the "nth" crosstalk widget that
+ * matches the specified part and mfgr number. Returns NULL if
+ * there is no such widget, or if the requested mapping can not
+ * be constructed.
+ * Limitations on which crosstalk slots (and busses) are
+ * checked, and definitions of the ordering of the search across
+ * the crosstalk slots, are defined by the platform.
+ */
+caddr_t
+xtalk_early_piotrans_addr(xwidget_part_num_t part_num,
+			  xwidget_mfg_num_t mfg_num,
+			  int which,
+			  iopaddr_t xtalk_addr,
+			  size_t byte_count,
+			  unsigned flags)
+{
+    return impl_early_piotrans_addr
+	(part_num, mfg_num, which, xtalk_addr, byte_count, flags);
+}
+
+/* null_xtalk_early_piotrans_addr:
+ * used as the early_piotrans_addr implementation until and
+ * unless a real implementation is provided. In DEBUG kernels,
+ * we want to know who is calling before the implementation is
+ * registered; in non-DEBUG kernels, return NULL representing
+ * lack of mapping support.
+ */
+/*ARGSUSED */
+static caddr_t
+null_xtalk_early_piotrans_addr(xwidget_part_num_t part_num,
+			       xwidget_mfg_num_t mfg_num,
+			       int which,
+			       iopaddr_t xtalk_addr,
+			       size_t byte_count,
+			       unsigned flags)
+{
+#if DEBUG
+    PRINT_PANIC("null_xtalk_early_piotrans_addr");
+#endif
+    return NULL;
+}
+
+/* =====================================================================
+ *                    DMA MANAGEMENT
+ *
+ *      For mapping from crosstalk space to system
+ *      physical space.
+ */
+
+xtalk_dmamap_t
+xtalk_dmamap_alloc(devfs_handle_t dev,	/* set up mappings for this device */
+		   device_desc_t dev_desc,	/* device descriptor */
+		   size_t byte_count_max,	/* max size of a mapping */
+		   unsigned flags)
+{				/* defined in dma.h */
+    return (xtalk_dmamap_t) DEV_FUNC(dev, dmamap_alloc)
+	(dev, dev_desc, byte_count_max, flags);
+}
+
+
+void
+xtalk_dmamap_free(xtalk_dmamap_t xtalk_dmamap)
+{
+    DMAMAP_FUNC(xtalk_dmamap, dmamap_free)
+	(CAST_DMAMAP(xtalk_dmamap));
+}
+
+
+iopaddr_t
+xtalk_dmamap_addr(xtalk_dmamap_t xtalk_dmamap,	/* use these mapping resources */
+		  paddr_t paddr,	/* map for this address */
+		  size_t byte_count)
+{				/* map this many bytes */
+    return DMAMAP_FUNC(xtalk_dmamap, dmamap_addr)
+	(CAST_DMAMAP(xtalk_dmamap), paddr, byte_count);
+}
+
+
+alenlist_t
+xtalk_dmamap_list(xtalk_dmamap_t xtalk_dmamap,	/* use these mapping resources */
+		  alenlist_t alenlist,	/* map this Address/Length List */
+		  unsigned flags)
+{
+    return DMAMAP_FUNC(xtalk_dmamap, dmamap_list)
+	(CAST_DMAMAP(xtalk_dmamap), alenlist, flags);
+}
+
+
+void
+xtalk_dmamap_done(xtalk_dmamap_t xtalk_dmamap)
+{
+    DMAMAP_FUNC(xtalk_dmamap, dmamap_done)
+	(CAST_DMAMAP(xtalk_dmamap));
+}
+
+
+iopaddr_t
+xtalk_dmatrans_addr(devfs_handle_t dev,	/* translate for this device */
+		    device_desc_t dev_desc,	/* device descriptor */
+		    paddr_t paddr,	/* system physical address */
+		    size_t byte_count,	/* length */
+		    unsigned flags)
+{				/* defined in dma.h */
+    return DEV_FUNC(dev, dmatrans_addr)
+	(dev, dev_desc, paddr, byte_count, flags);
+}
+
+
+alenlist_t
+xtalk_dmatrans_list(devfs_handle_t dev,	/* translate for this device */
+		    device_desc_t dev_desc,	/* device descriptor */
+		    alenlist_t palenlist,	/* system address/length list */
+		    unsigned flags)
+{				/* defined in dma.h */
+    return DEV_FUNC(dev, dmatrans_list)
+	(dev, dev_desc, palenlist, flags);
+}
+
+void
+xtalk_dmamap_drain(xtalk_dmamap_t map)
+{
+    DMAMAP_FUNC(map, dmamap_drain)
+	(CAST_DMAMAP(map));
+}
+
+void
+xtalk_dmaaddr_drain(devfs_handle_t dev, paddr_t addr, size_t size)
+{
+    DEV_FUNC(dev, dmaaddr_drain)
+	(dev, addr, size);
+}
+
+void
+xtalk_dmalist_drain(devfs_handle_t dev, alenlist_t list)
+{
+    DEV_FUNC(dev, dmalist_drain)
+	(dev, list);
+}
+
+/* =====================================================================
+ *                    INTERRUPT MANAGEMENT
+ *
+ *      Allow crosstalk devices to establish interrupts
+ */
+
+/*
+ * Allocate resources required for an interrupt as specified in intr_desc.
+ * Return resource handle in intr_hdl.
+ */
+xtalk_intr_t
+xtalk_intr_alloc(devfs_handle_t dev,	/* which Crosstalk device */
+		 device_desc_t dev_desc,	/* device descriptor */
+		 devfs_handle_t owner_dev)
+{				/* owner of this interrupt */
+    return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc)
+	(dev, dev_desc, owner_dev);
+}
+
+/*
+ * Allocate resources required for an interrupt as specified in dev_desc.
+ * Unconditionally setup resources to be non-threaded.
+ * Return resource handle in intr_hdl.
+ */
+xtalk_intr_t
+xtalk_intr_alloc_nothd(devfs_handle_t dev,	/* which Crosstalk device */
+		 	device_desc_t dev_desc,	/* device descriptor */
+		 	devfs_handle_t owner_dev)	/* owner of this interrupt */
+{
+    return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc_nothd)
+	(dev, dev_desc, owner_dev);
+}
+
+/*
+ * Free resources consumed by intr_alloc.
+ */
+void
+xtalk_intr_free(xtalk_intr_t intr_hdl)
+{
+    INTR_FUNC(intr_hdl, intr_free)
+	(CAST_INTR(intr_hdl));
+}
+
+
+/*
+ * Associate resources allocated with a previous xtalk_intr_alloc call with the
+ * described handler, arg, name, etc.
+ *
+ * Returns 0 on success, returns <0 on failure.
+ */
+int
+xtalk_intr_connect(xtalk_intr_t intr_hdl,	/* xtalk intr resource handle */
+		   intr_func_t intr_func,       /* xtalk intr handler */
+		   intr_arg_t intr_arg,         /* arg to intr handler */
+		   xtalk_intr_setfunc_t setfunc,	/* func to set intr hw */
+		   void *setfunc_arg)	/* arg to setfunc */
+{
+    return INTR_FUNC(intr_hdl, intr_connect)
+	(CAST_INTR(intr_hdl), intr_func, intr_arg, setfunc, setfunc_arg);
+}
+
+
+/*
+ * Disassociate handler with the specified interrupt.
+ */
+void
+xtalk_intr_disconnect(xtalk_intr_t intr_hdl)
+{
+    INTR_FUNC(intr_hdl, intr_disconnect)
+	(CAST_INTR(intr_hdl));
+}
+
+
+/*
+ * Return a hwgraph vertex that represents the CPU currently
+ * targeted by an interrupt.
+ */
+devfs_handle_t
+xtalk_intr_cpu_get(xtalk_intr_t intr_hdl)
+{
+    return INTR_FUNC(intr_hdl, intr_cpu_get)
+	(CAST_INTR(intr_hdl));
+}
+
+
+/*
+ * =====================================================================
+ *                      ERROR MANAGEMENT
+ */
+
+/*
+ * xtalk_error_handler:
+ * pass this error on to the handler registered
+ * at the specified xtalk connecdtion point,
+ * or complain about it here if there is no handler.
+ *
+ * This routine plays two roles during error delivery
+ * to most widgets: first, the external agent (heart,
+ * hub, or whatever) calls in with the error and the
+ * connect point representing the crosstalk switch,
+ * or whatever crosstalk device is directly connected
+ * to the agent.
+ *
+ * If there is a switch, it will generally look at the
+ * widget number stashed in the ioerror structure; and,
+ * if the error came from some widget other than the
+ * switch, it will call back into xtalk_error_handler
+ * with the connection point of the offending port.
+ */
+int
+xtalk_error_handler(
+		       devfs_handle_t xconn,
+		       int error_code,
+		       ioerror_mode_t mode,
+		       ioerror_t *ioerror)
+{
+    xwidget_info_t          xwidget_info;
+
+    xwidget_info = xwidget_info_get(xconn);
+    /* Make sure that xwidget_info is a valid pointer before derefencing it.
+     * We could come in here during very early initialization. 
+     */
+    if (xwidget_info && xwidget_info->w_efunc)
+	return xwidget_info->w_efunc
+	    (xwidget_info->w_einfo,
+	     error_code, mode, ioerror);
+    /*
+     * no error handler registered for
+     * the offending port. it's not clear
+     * what needs to be done, but reporting
+     * it would be a good thing, unless it
+     * is a mode that requires nothing.
+     */
+    if ((mode == MODE_DEVPROBE) || (mode == MODE_DEVUSERERROR) ||
+	(mode == MODE_DEVREENABLE))
+	return IOERROR_HANDLED;
+
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+    printk(KERN_WARNING "Xbow at %v encountered Fatal error", xconn);
+#else
+    printk(KERN_WARNING "Xbow at 0x%p encountered Fatal error", xconn);
+#endif
+    ioerror_dump("xtalk", error_code, mode, ioerror);
+
+    return IOERROR_UNHANDLED;
+}
+
+int
+xtalk_error_devenable(devfs_handle_t xconn_vhdl, int devnum, int error_code)
+{
+    return DEV_FUNC(xconn_vhdl, error_devenable) (xconn_vhdl, devnum, error_code);
+}
+
+
+/* =====================================================================
+ *                    CONFIGURATION MANAGEMENT
+ */
+
+/*
+ * Startup a crosstalk provider
+ */
+void
+xtalk_provider_startup(devfs_handle_t xtalk_provider)
+{
+    DEV_FUNC(xtalk_provider, provider_startup)
+	(xtalk_provider);
+}
+
+
+/*
+ * Shutdown a crosstalk provider
+ */
+void
+xtalk_provider_shutdown(devfs_handle_t xtalk_provider)
+{
+    DEV_FUNC(xtalk_provider, provider_shutdown)
+	(xtalk_provider);
+}
+
+/* 
+ * Enable a device on a xtalk widget 
+ */
+void
+xtalk_widgetdev_enable(devfs_handle_t xconn_vhdl, int devnum)
+{
+    DEV_FUNC(xconn_vhdl, widgetdev_enable) (xconn_vhdl, devnum);
+}
+
+/* 
+ * Shutdown a device on a xtalk widget 
+ */
+void
+xtalk_widgetdev_shutdown(devfs_handle_t xconn_vhdl, int devnum)
+{
+    DEV_FUNC(xconn_vhdl, widgetdev_shutdown) (xconn_vhdl, devnum);
+}
+
+int
+xtalk_dma_enabled(devfs_handle_t xconn_vhdl)
+{
+    return DEV_FUNC(xconn_vhdl, dma_enabled) (xconn_vhdl);
+}
+/*
+ * Generic crosstalk functions, for use with all crosstalk providers
+ * and all crosstalk devices.
+ */
+
+/****** Generic crosstalk interrupt interfaces ******/
+devfs_handle_t
+xtalk_intr_dev_get(xtalk_intr_t xtalk_intr)
+{
+    return (xtalk_intr->xi_dev);
+}
+
+xwidgetnum_t
+xtalk_intr_target_get(xtalk_intr_t xtalk_intr)
+{
+    return (xtalk_intr->xi_target);
+}
+
+xtalk_intr_vector_t
+xtalk_intr_vector_get(xtalk_intr_t xtalk_intr)
+{
+    return (xtalk_intr->xi_vector);
+}
+
+iopaddr_t
+xtalk_intr_addr_get(struct xtalk_intr_s *xtalk_intr)
+{
+    return (xtalk_intr->xi_addr);
+}
+
+void                   *
+xtalk_intr_sfarg_get(xtalk_intr_t xtalk_intr)
+{
+    return (xtalk_intr->xi_sfarg);
+}
+
+/****** Generic crosstalk pio interfaces ******/
+devfs_handle_t
+xtalk_pio_dev_get(xtalk_piomap_t xtalk_piomap)
+{
+    return (xtalk_piomap->xp_dev);
+}
+
+xwidgetnum_t
+xtalk_pio_target_get(xtalk_piomap_t xtalk_piomap)
+{
+    return (xtalk_piomap->xp_target);
+}
+
+iopaddr_t
+xtalk_pio_xtalk_addr_get(xtalk_piomap_t xtalk_piomap)
+{
+    return (xtalk_piomap->xp_xtalk_addr);
+}
+
+ulong
+xtalk_pio_mapsz_get(xtalk_piomap_t xtalk_piomap)
+{
+    return (xtalk_piomap->xp_mapsz);
+}
+
+caddr_t
+xtalk_pio_kvaddr_get(xtalk_piomap_t xtalk_piomap)
+{
+    return (xtalk_piomap->xp_kvaddr);
+}
+
+
+/****** Generic crosstalk dma interfaces ******/
+devfs_handle_t
+xtalk_dma_dev_get(xtalk_dmamap_t xtalk_dmamap)
+{
+    return (xtalk_dmamap->xd_dev);
+}
+
+xwidgetnum_t
+xtalk_dma_target_get(xtalk_dmamap_t xtalk_dmamap)
+{
+    return (xtalk_dmamap->xd_target);
+}
+
+
+/****** Generic crosstalk widget information interfaces ******/
+
+/* xwidget_info_chk:
+ * check to see if this vertex is a widget;
+ * if so, return its widget_info (if any).
+ * if not, return NULL.
+ */
+xwidget_info_t
+xwidget_info_chk(devfs_handle_t xwidget)
+{
+    arbitrary_info_t        ainfo = 0;
+
+    hwgraph_info_get_LBL(xwidget, INFO_LBL_XWIDGET, &ainfo);
+    return (xwidget_info_t) ainfo;
+}
+
+
+xwidget_info_t
+xwidget_info_get(devfs_handle_t xwidget)
+{
+    xwidget_info_t          widget_info;
+
+    widget_info = (xwidget_info_t)
+	hwgraph_fastinfo_get(xwidget);
+
+#ifdef	LATER
+    if ((widget_info != NULL) &&
+	(widget_info->w_fingerprint != widget_info_fingerprint))
+#ifdef SUPPORT_PRINTING_V_FORMAT
+	PRINT_PANIC("%v bad xwidget_info", xwidget);
+#else
+	PRINT_PANIC("%x bad xwidget_info", xwidget);
+#endif
+#endif	/* LATER */
+
+    return (widget_info);
+}
+
+void
+xwidget_info_set(devfs_handle_t xwidget, xwidget_info_t widget_info)
+{
+    if (widget_info != NULL)
+	widget_info->w_fingerprint = widget_info_fingerprint;
+
+    hwgraph_fastinfo_set(xwidget, (arbitrary_info_t) widget_info);
+
+    /* Also, mark this vertex as an xwidget,
+     * and use the widget_info, so xwidget_info_chk
+     * can work (and be fairly efficient).
+     */
+    hwgraph_info_add_LBL(xwidget, INFO_LBL_XWIDGET,
+			 (arbitrary_info_t) widget_info);
+}
+
+devfs_handle_t
+xwidget_info_dev_get(xwidget_info_t xwidget_info)
+{
+    if (xwidget_info == NULL)
+	panic("null xwidget_info");
+    return (xwidget_info->w_vertex);
+}
+
+xwidgetnum_t
+xwidget_info_id_get(xwidget_info_t xwidget_info)
+{
+    if (xwidget_info == NULL)
+	panic("null xwidget_info");
+    return (xwidget_info->w_id);
+}
+
+
+devfs_handle_t
+xwidget_info_master_get(xwidget_info_t xwidget_info)
+{
+    if (xwidget_info == NULL)
+	panic("null xwidget_info");
+    return (xwidget_info->w_master);
+}
+
+xwidgetnum_t
+xwidget_info_masterid_get(xwidget_info_t xwidget_info)
+{
+    if (xwidget_info == NULL)
+	panic("null xwidget_info");
+    return (xwidget_info->w_masterid);
+}
+
+xwidget_part_num_t
+xwidget_info_part_num_get(xwidget_info_t xwidget_info)
+{
+    if (xwidget_info == NULL)
+	panic("null xwidget_info");
+    return (xwidget_info->w_hwid.part_num);
+}
+
+xwidget_mfg_num_t
+xwidget_info_mfg_num_get(xwidget_info_t xwidget_info)
+{
+    if (xwidget_info == NULL)
+	panic("null xwidget_info");
+    return (xwidget_info->w_hwid.mfg_num);
+}
+/* Extract the widget name from the widget information
+ * for the xtalk widget.
+ */
+char *
+xwidget_info_name_get(xwidget_info_t xwidget_info)
+{
+    if (xwidget_info == NULL)
+	panic("null xwidget info");
+    return(xwidget_info->w_name);
+}
+/****** Generic crosstalk initialization interfaces ******/
+
+/*
+ * One-time initialization needed for systems that support crosstalk.
+ */
+void
+xtalk_init(void)
+{
+    cdl_p                   cp;
+
+#if DEBUG && ATTACH_DEBUG
+    printf("xtalk_init\n");
+#endif
+    /* Allocate the registry.
+     * We might already have one.
+     * If we don't, go get one.
+     * MPness: someone might have
+     * set one up for us while we
+     * were not looking; use an atomic
+     * compare-and-swap to commit to
+     * using the new registry if and
+     * only if nobody else did first.
+     * If someone did get there first,
+     * toss the one we allocated back
+     * into the pool.
+     */
+    if (xtalk_registry == NULL) {
+	cp = cdl_new(EDGE_LBL_XIO, "part", "mfgr");
+	if (!compare_and_swap_ptr((void **) &xtalk_registry, NULL, (void *) cp)) {
+	    cdl_del(cp);
+	}
+    }
+    ASSERT(xtalk_registry != NULL);
+}
+
+/*
+ * Associate a set of xtalk_provider functions with a vertex.
+ */
+void
+xtalk_provider_register(devfs_handle_t provider, xtalk_provider_t *xtalk_fns)
+{
+    hwgraph_fastinfo_set(provider, (arbitrary_info_t) xtalk_fns);
+}
+
+/*
+ * Disassociate a set of xtalk_provider functions with a vertex.
+ */
+void
+xtalk_provider_unregister(devfs_handle_t provider)
+{
+    hwgraph_fastinfo_set(provider, (arbitrary_info_t)NULL);
+}
+
+/*
+ * Obtain a pointer to the xtalk_provider functions for a specified Crosstalk
+ * provider.
+ */
+xtalk_provider_t       *
+xtalk_provider_fns_get(devfs_handle_t provider)
+{
+    return ((xtalk_provider_t *) hwgraph_fastinfo_get(provider));
+}
+
+/*
+ * Announce a driver for a particular crosstalk part.
+ * Returns 0 on success or -1 on failure.  Failure occurs if the
+ * specified hardware already has a driver.
+ */
+/*ARGSUSED4 */
+int
+xwidget_driver_register(xwidget_part_num_t part_num,
+			xwidget_mfg_num_t mfg_num,
+			char *driver_prefix,
+			unsigned flags)
+{
+    /* a driver's init routine could call
+     * xwidget_driver_register before the
+     * system calls xtalk_init; so, we
+     * make the call here.
+     */
+    if (xtalk_registry == NULL)
+	xtalk_init();
+
+    return cdl_add_driver(xtalk_registry,
+			  part_num, mfg_num,
+			  driver_prefix, flags, NULL);
+}
+
+/*
+ * Inform xtalk infrastructure that a driver is no longer available for
+ * handling any widgets.
+ */
+void
+xwidget_driver_unregister(char *driver_prefix)
+{
+    /* before a driver calls unregister,
+     * it must have called registger; so we
+     * can assume we have a registry here.
+     */
+    ASSERT(xtalk_registry != NULL);
+
+    cdl_del_driver(xtalk_registry, driver_prefix, NULL);
+}
+
+/*
+ * Call some function with each vertex that
+ * might be one of this driver's attach points.
+ */
+void
+xtalk_iterate(char *driver_prefix,
+	      xtalk_iter_f *func)
+{
+    ASSERT(xtalk_registry != NULL);
+
+    cdl_iterate(xtalk_registry, driver_prefix, (cdl_iter_f *)func);
+}
+
+/*
+ * xwidget_register:
+ *	Register a xtalk device (xwidget) by doing the following.
+ *      -allocate and initialize xwidget_info data
+ *      -allocate a hwgraph vertex with name based on widget number (id)
+ *      -look up the widget's initialization function and call it,
+ *      or remember the vertex for later initialization.
+ *
+ */
+int
+xwidget_register(xwidget_hwid_t hwid,		/* widget's hardware ID */
+		 devfs_handle_t 	widget,		/* widget to initialize */
+		 xwidgetnum_t 	id,		/* widget's target id (0..f) */
+		 devfs_handle_t 	master,		/* widget's master vertex */
+		 xwidgetnum_t 	targetid,	/* master's target id (9/a) */
+		 async_attach_t aa)
+{			
+    xwidget_info_t          widget_info;
+    char		    *s,devnm[MAXDEVNAME];
+
+    /* Allocate widget_info and associate it with widget vertex */
+    NEW(widget_info);
+
+    /* Initialize widget_info */
+    widget_info->w_vertex = widget;
+    widget_info->w_id = id;
+    widget_info->w_master = master;
+    widget_info->w_masterid = targetid;
+    widget_info->w_hwid = *hwid;	/* structure copy */
+    widget_info->w_efunc = 0;
+    widget_info->w_einfo = 0;
+    /*
+     * get the name of this xwidget vertex and keep the info.
+     * This is needed during errors and interupts, but as
+     * long as we have it, we can use it elsewhere.
+     */
+    s = dev_to_name(widget,devnm,MAXDEVNAME);
+    widget_info->w_name = kmalloc(strlen(s) + 1, GFP_KERNEL);
+    strcpy(widget_info->w_name,s);
+    
+    xwidget_info_set(widget, widget_info);
+
+    device_master_set(widget, master);
+
+    /* All the driver init routines (including
+     * xtalk_init) are called before we get into
+     * attaching devices, so we can assume we
+     * have a registry here.
+     */
+    ASSERT(xtalk_registry != NULL);
+
+    /* 
+     * Add pointer to async attach info -- tear down will be done when
+     * the particular descendant is done with the info.
+     */
+    if (aa)
+	    async_attach_add_info(widget, aa);
+
+    return cdl_add_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num,
+                          widget, 0);
+}
+
+/*
+ * xwidget_unregister :
+ *	Unregister the xtalk device and detach all its hwgraph namespace.
+ */
+int
+xwidget_unregister(devfs_handle_t widget)
+{
+    xwidget_info_t	widget_info;
+    xwidget_hwid_t	hwid;
+
+    /* Make sure that we have valid widget information initialized */
+    if (!(widget_info = xwidget_info_get(widget)))
+	return(1);
+
+    /* Remove the inventory information associated
+     * with the widget.
+     */
+    hwgraph_inventory_remove(widget, -1, -1, -1, -1, -1);
+    
+    hwid = &(widget_info->w_hwid);
+
+    cdl_del_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num,
+                   widget, 0);
+
+    /* Clean out the xwidget information */
+    (void)kfree(widget_info->w_name);
+    BZERO((void *)widget_info, sizeof(widget_info));
+    DEL(widget_info);
+    
+    return(0);
+}
+
+void
+xwidget_error_register(devfs_handle_t xwidget,
+		       error_handler_f *efunc,
+		       error_handler_arg_t einfo)
+{
+    xwidget_info_t          xwidget_info;
+
+    xwidget_info = xwidget_info_get(xwidget);
+    ASSERT(xwidget_info != NULL);
+    xwidget_info->w_efunc = efunc;
+    xwidget_info->w_einfo = einfo;
+}
+
+/*
+ * Issue a link reset to a widget.
+ */
+void
+xwidget_reset(devfs_handle_t xwidget)
+{
+    xswitch_reset_link(xwidget);
+
+}
+
+
+void
+xwidget_gfx_reset(devfs_handle_t xwidget)
+{
+    xwidget_info_t info;
+
+    xswitch_reset_link(xwidget);
+    info = xwidget_info_get(xwidget);
+#ifdef LATER
+    ASSERT_ALWAYS(info != NULL);
+#endif
+
+    /*
+     * Enable this for other architectures once we add widget_reset to the
+     * xtalk provider interface.
+     */
+    DEV_FUNC(xtalk_provider, widget_reset)
+	(xwidget_info_master_get(info), xwidget_info_id_get(info));
+}
+
+#define ANON_XWIDGET_NAME	"No Name"	/* Default Widget Name */
+
+/* Get the canonical hwgraph  name of xtalk widget */
+char *
+xwidget_name_get(devfs_handle_t xwidget_vhdl)
+{
+	xwidget_info_t  info;
+
+	/* If we have a bogus widget handle then return
+	 * a default anonymous widget name.
+	 */
+	if (xwidget_vhdl == GRAPH_VERTEX_NONE)
+	    return(ANON_XWIDGET_NAME);
+	/* Read the widget name stored in the widget info
+	 * for the widget setup during widget initialization.
+	 */
+	info = xwidget_info_get(xwidget_vhdl);
+	ASSERT(info != NULL);
+	return(xwidget_info_name_get(info));
+}
diff -Nru a/arch/ia64/sn/kernel/iomv.c b/arch/ia64/sn/kernel/iomv.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/kernel/iomv.c	Mon Feb 24 04:47:33 2003
@@ -0,0 +1,115 @@
+/* 
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <asm/io.h>
+#include <linux/module.h>
+
+extern void * sn_io_addr(unsigned long port); /* defined in sn[12]/iomv.c */
+
+/**
+ * sn_inb - read a byte from a port
+ * @port: port to read from
+ *
+ * Reads a byte from @port and returns it to the caller.
+ */
+unsigned int
+sn_inb (unsigned long port)
+{
+	volatile unsigned char *addr = sn_io_addr(port);
+	unsigned char ret;
+
+	ret = *addr;
+	__ia64_mf_a();
+	return ret;
+}
+
+/**
+ * sn_inw - read a word from a port
+ * @port: port to read from
+ *
+ * Reads a word from @port and returns it to the caller.
+ */
+unsigned int
+sn_inw (unsigned long port)
+{
+	volatile unsigned short *addr = sn_io_addr(port);
+	unsigned short ret;
+
+	ret = *addr;
+	__ia64_mf_a();
+	return ret;
+}
+
+/**
+ * sn_inl - read a word from a port
+ * @port: port to read from
+ *
+ * Reads a word from @port and returns it to the caller.
+ */
+unsigned int
+sn_inl (unsigned long port)
+{
+	volatile unsigned int *addr = sn_io_addr(port);
+	unsigned int ret;
+
+	ret = *addr;
+	__ia64_mf_a();
+	return ret;
+}
+
+/**
+ * sn_outb - write a byte to a port
+ * @port: port to write to
+ * @val: value to write
+ *
+ * Writes @val to @port.
+ */
+void
+sn_outb (unsigned char val, unsigned long port)
+{
+	volatile unsigned char *addr = sn_io_addr(port);
+
+	*addr = val;
+}
+
+/**
+ * sn_outw - write a word to a port
+ * @port: port to write to
+ * @val: value to write
+ *
+ * Writes @val to @port.
+ */
+void
+sn_outw (unsigned short val, unsigned long port)
+{
+	volatile unsigned short *addr = sn_io_addr(port);
+
+	*addr = val;
+}
+
+/**
+ * sn_outl - write a word to a port
+ * @port: port to write to
+ * @val: value to write
+ *
+ * Writes @val to @port.
+ */
+void
+sn_outl (unsigned int val, unsigned long port)
+{
+	volatile unsigned int *addr = sn_io_addr(port);
+
+	*addr = val;
+}
+
+EXPORT_SYMBOL(sn_inb);
+EXPORT_SYMBOL(sn_inw);
+EXPORT_SYMBOL(sn_inl);
+EXPORT_SYMBOL(sn_outb);
+EXPORT_SYMBOL(sn_outw);
+EXPORT_SYMBOL(sn_outl);
diff -Nru a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c
--- a/arch/ia64/sn/kernel/mca.c	Tue Nov  5 06:25:20 2002
+++ b/arch/ia64/sn/kernel/mca.c	Mon Feb 24 04:50:23 2003
@@ -40,7 +40,10 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/smp_lock.h>
+#include <linux/acpi.h>
+#ifdef CONFIG_KDB
 #include <linux/kdb.h>
+#endif
 
 #include <asm/machvec.h>
 #include <asm/page.h>
@@ -53,7 +56,6 @@
 
 #include <asm/irq.h>
 #include <asm/hw_irq.h>
-#include <asm/acpi-ext.h>
 #include <asm/smp.h>
 #include <asm/sn/sn_cpuid.h>
 
diff -Nru a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
--- a/arch/ia64/sn/kernel/setup.c	Tue Feb 25 02:08:11 2003
+++ b/arch/ia64/sn/kernel/setup.c	Thu Mar  6 11:40:52 2003
@@ -267,7 +267,7 @@
 	/* PROM has wrong value on SN1 */
 	sn_rtc_cycles_per_second = 990177;
 #endif
-	sn_rtc_usec_per_cyc = ((1000000UL<<IA64_USEC_PER_CYC_SHIFT)
+	sn_rtc_usec_per_cyc = ((1000000000UL<<IA64_NSEC_PER_CYC_SHIFT)
 			       + sn_rtc_cycles_per_second/2) / sn_rtc_cycles_per_second;
 		
 	for (i=0;i<NR_CPUS;i++)
diff -Nru a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile
--- a/arch/ia64/sn/kernel/sn2/Makefile	Mon Dec 16 15:47:54 2002
+++ b/arch/ia64/sn/kernel/sn2/Makefile	Mon Feb 24 05:15:44 2003
@@ -32,5 +32,7 @@
 # http://oss.sgi.com/projects/GenInfo/NoticeExplan
 #
 
-
 EXTRA_CFLAGS    := -DLITTLE_ENDIAN
+
+obj-y += cache.o iomv.o ptc_deadlock.o sn2_smp.o \
+         sn_proc_fs.o
diff -Nru a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S	Mon Feb 24 05:16:29 2003
@@ -0,0 +1,82 @@
+/* 
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <asm/sn/sn2/shub_mmr.h>
+
+#define ZEROVAL		0x3f		// "zero" value for outstanding PIO requests
+#define DEADLOCKBIT	SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK_SHFT
+#define WRITECOUNT	SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_SHFT
+#define ALIAS_OFFSET	(SH_PIO_WRITE_STATUS_0_ALIAS-SH_PIO_WRITE_STATUS_0)
+
+
+	.global	sn2_ptc_deadlock_recovery_core
+	.proc  	sn2_ptc_deadlock_recovery_core
+
+sn2_ptc_deadlock_recovery_core:
+	.regstk 5,0,0,0
+
+	ptc0  	 = in0
+	data0 	 = in1
+	ptc1  	 = in2
+	data1 	 = in3
+	piowc 	 = in4
+	piowcphy = r30
+	psrsave  = r2
+	zeroval  = r3
+	scr1	 = r16
+	scr2	 = r17
+
+
+	extr.u	piowcphy=piowc,0,61;;	// Convert piowc to uncached physical address
+	dep	piowcphy=-1,piowcphy,63,1
+
+	mov	zeroval=ZEROVAL		// "zero" value for PIO write count
+
+1:
+	add	scr2=ALIAS_OFFSET,piowc	// Address of WRITE_STATUS alias register 
+	mov	scr1=7;;		// Clear DEADLOCK, WRITE_ERROR, MULTI_WRITE_ERROR
+	st8.rel	[scr2]=scr1;;
+
+5:	ld8.acq	scr1=[piowc];;		// Wait for PIOs to complete.
+	extr.u	scr2=scr1,WRITECOUNT,7;;// PIO count
+	cmp.ne	p6,p0=zeroval,scr2
+(p6)	br.cond.sptk 5b
+	
+
+
+	////////////// BEGIN PHYSICAL MODE ////////////////////
+	mov psrsave=psr			// Disable IC (no PMIs)
+	rsm psr.i | psr.dt | psr.ic;;
+	srlz.i;;
+
+	st8.rel [ptc0]=data0		// Write PTC0 & wait for completion.
+
+5:	ld8.acq	scr1=[piowcphy];;	// Wait for PIOs to complete.
+	extr.u	scr2=scr1,WRITECOUNT,7;;// PIO count
+	cmp.ne	p6,p0=zeroval,scr2
+(p6)	br.cond.sptk 5b;;
+
+	tbit.nz	p8,p7=scr1,DEADLOCKBIT;;// Test for DEADLOCK
+	
+(p7)	st8.rel [ptc1]=data1;;		// Now write PTC1.
+
+5:	ld8.acq	scr1=[piowcphy];;	// Wait for PIOs to complete.
+	extr.u	scr2=scr1,WRITECOUNT,7;;// PIO count
+	cmp.ne	p6,p0=zeroval,scr2
+(p6)	br.cond.sptk 5b
+	
+	tbit.nz	p8,p0=scr1,DEADLOCKBIT;;// Test for DEADLOCK
+
+	mov psr.l=psrsave;;		// Reenable IC
+	srlz.i;;
+	////////////// END   PHYSICAL MODE ////////////////////
+
+(p8)	br.cond.spnt 1b;;		// Repeat if DEADLOCK occurred.
+
+	br.ret.sptk	rp
+	.endp sn2_ptc_deadlock_recovery_core
diff -Nru a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c	Mon Feb 24 05:17:16 2003
@@ -0,0 +1,145 @@
+/*
+ *
+ * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of version 2 of the GNU General Public License 
+ * as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * 
+ * Further, this software is distributed without any warranty that it is 
+ * free of the rightful claim of any third person regarding infringement 
+ * or the like.  Any license provided herein, whether implied or 
+ * otherwise, applies only to this software file.  Patent licenses, if 
+ * any, provided herein do not apply to combinations of this program with 
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program; if not, write the Free Software 
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+#include <linux/config.h>
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#include <asm/sn/sn_sal.h>
+
+
+static int partition_id_read_proc(char *page, char **start, off_t off,
+		int count, int *eof, void *data) {
+
+	return sprintf(page, "%d\n", sn_local_partid());
+}
+
+struct proc_dir_entry * sgi_proc_dir = NULL;
+
+void
+register_sn_partition_id(void) {
+	struct proc_dir_entry *entry;
+
+	if (!sgi_proc_dir) {
+		sgi_proc_dir = proc_mkdir("sgi_sn", 0);
+	}
+	entry = create_proc_entry("partition_id", 0444, sgi_proc_dir);
+	if (entry) {
+		entry->nlink = 1;
+		entry->data = 0;
+		entry->read_proc = partition_id_read_proc;
+		entry->write_proc = NULL;
+	}
+}
+
+static int
+system_serial_number_read_proc(char *page, char **start, off_t off,
+		int count, int *eof, void *data) {
+	return sprintf(page, "%s\n", sn_system_serial_number());
+}
+
+static int
+licenseID_read_proc(char *page, char **start, off_t off,
+		int count, int *eof, void *data) {
+	return sprintf(page, "0x%lx\n",sn_partition_serial_number_val());
+}
+
+void
+register_sn_serial_numbers(void) {
+	struct proc_dir_entry *entry;
+
+	if (!sgi_proc_dir) {
+		sgi_proc_dir = proc_mkdir("sgi_sn", 0);
+	}
+	entry = create_proc_entry("system_serial_number", 0444, sgi_proc_dir);
+	if (entry) {
+		entry->nlink = 1;
+		entry->data = 0;
+		entry->read_proc = system_serial_number_read_proc;
+		entry->write_proc = NULL;
+	}
+	entry = create_proc_entry("licenseID", 0444, sgi_proc_dir);
+	if (entry) {
+		entry->nlink = 1;
+		entry->data = 0;
+		entry->read_proc = licenseID_read_proc;
+		entry->write_proc = NULL;
+	}
+}
+
+// Disable forced interrupts, but leave the code in, just in case.
+int sn_force_interrupt_flag = 0;
+
+static int
+sn_force_interrupt_read_proc(char *page, char **start, off_t off,
+		int count, int *eof, void *data) {
+	if (sn_force_interrupt_flag) {
+		return sprintf(page, "Force interrupt is enabled\n");
+	}
+	return sprintf(page, "Force interrupt is disabled\n");
+}
+
+static int 
+sn_force_interrupt_write_proc(struct file *file, const char *buffer,
+                                        unsigned long count, void *data)
+{
+	if (*buffer == '0') {
+		sn_force_interrupt_flag = 0;
+	} else {
+		sn_force_interrupt_flag = 1;
+	}
+	return 1;
+}
+
+void
+register_sn_force_interrupt(void) {
+	struct proc_dir_entry *entry;
+
+	if (!sgi_proc_dir) {
+		sgi_proc_dir = proc_mkdir("sgi_sn", 0);
+	}
+	entry = create_proc_entry("sn_force_interrupt",0444, sgi_proc_dir);
+	if (entry) {
+		entry->nlink = 1;
+		entry->data = 0;
+		entry->read_proc = sn_force_interrupt_read_proc;
+		entry->write_proc = sn_force_interrupt_write_proc;
+	}
+}
+void
+register_sn_procfs(void) {
+	register_sn_partition_id();
+	register_sn_serial_numbers();
+	register_sn_force_interrupt();
+}
+
+#endif /* CONFIG_PROC_FS */
diff -Nru a/arch/ia64/tools/print_offsets.c b/arch/ia64/tools/print_offsets.c
--- a/arch/ia64/tools/print_offsets.c	Wed Jan 29 22:16:51 2003
+++ b/arch/ia64/tools/print_offsets.c	Fri Feb 28 15:27:56 2003
@@ -10,7 +10,7 @@
  * gets translated into an assembly file which, in turn, is processed
  * by awk to generate offsets.h.  So if you make any changes to this
  * file, be sure to verify that the awk procedure still works (see
- * prin_offsets.awk).
+ * print_offsets.awk).
  */
 #include <linux/config.h>
 
@@ -170,6 +170,12 @@
     /* for assembly files which can't include sched.h: */
     { "IA64_CLONE_VFORK",		CLONE_VFORK },
     { "IA64_CLONE_VM",			CLONE_VM },
+    /* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */
+    { "IA64_CPUINFO_ITM_DELTA_OFFSET", 		offsetof (struct cpuinfo_ia64, itm_delta) },
+    { "IA64_CPUINFO_ITM_NEXT_OFFSET", 		offsetof (struct cpuinfo_ia64, itm_next) },
+    { "IA64_CPUINFO_NSEC_PER_CYC_OFFSET",	offsetof (struct cpuinfo_ia64, nsec_per_cyc) },
+    { "IA64_TIMESPEC_TV_NSEC_OFFSET", 		offsetof (struct timespec, tv_nsec) },
+
 };
 
 static const char *tabs = "\t\t\t\t\t\t\t\t\t\t";
diff -Nru a/arch/ia64/vmlinux.lds.S b/arch/ia64/vmlinux.lds.S
--- a/arch/ia64/vmlinux.lds.S	Wed Jan 29 22:16:51 2003
+++ b/arch/ia64/vmlinux.lds.S	Fri Feb 14 15:08:44 2003
@@ -133,6 +133,10 @@
 	  *(.initcall7.init)
 	  __initcall_end = .;
 	}
+   __con_initcall_start = .;
+  .con_initcall.init : AT(ADDR(.con_initcall.init) - PAGE_OFFSET)
+	{ *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
 
diff -Nru a/arch/m68k/Kconfig b/arch/m68k/Kconfig
--- a/arch/m68k/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/m68k/Kconfig	Sat Mar  8 14:50:37 2003
@@ -10,10 +10,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 	default y
diff -Nru a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
--- a/arch/m68k/atari/stram.c	Mon Jan 13 17:54:26 2003
+++ b/arch/m68k/atari/stram.c	Sat Mar  8 14:50:21 2003
@@ -1052,8 +1052,7 @@
 	if (!stram_disk)
 		return -ENOMEM;
 
-	if (register_blkdev( STRAM_MAJOR, "stram", &stram_fops)) {
-		printk(KERN_ERR "stram: Unable to get major %d\n", STRAM_MAJOR);
+	if (register_blkdev(STRAM_MAJOR, "stram")) {
 		put_disk(stram_disk);
 		return -ENXIO;
 	}
diff -Nru a/arch/m68k/vmlinux-std.lds b/arch/m68k/vmlinux-std.lds
--- a/arch/m68k/vmlinux-std.lds	Wed Jan 15 09:48:42 2003
+++ b/arch/m68k/vmlinux-std.lds	Fri Feb 14 15:09:22 2003
@@ -60,6 +60,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(8192);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
diff -Nru a/arch/m68k/vmlinux-sun3.lds b/arch/m68k/vmlinux-sun3.lds
--- a/arch/m68k/vmlinux-sun3.lds	Wed Jan 15 09:48:42 2003
+++ b/arch/m68k/vmlinux-sun3.lds	Fri Feb 14 15:09:22 2003
@@ -53,6 +53,9 @@
 		*(.initcall7.init)
 	}
 	__initcall_end = .;
+	__con_initcall_start = .;
+	.con_initcall.init : { *(.con_initcall.init) }
+	__con_initcall_end = .;
 	. = ALIGN(8192);
 	__initramfs_start = .;
 	.init.ramfs : { *(.init.ramfs) }
diff -Nru a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
--- a/arch/m68knommu/Kconfig	Tue Feb 18 02:27:38 2003
+++ b/arch/m68knommu/Kconfig	Sat Mar  8 14:50:37 2003
@@ -9,10 +9,6 @@
 	bool
 	default n
 
-config SWAP
-	bool
-	default n
-
 config FPU
 	bool
 	default n
diff -Nru a/arch/mips/Kconfig b/arch/mips/Kconfig
--- a/arch/mips/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/mips/Kconfig	Sat Mar  8 14:50:37 2003
@@ -10,10 +10,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config SMP
 	bool
 	---help---
diff -Nru a/arch/mips/arc/arc_con.c b/arch/mips/arc/arc_con.c
--- a/arch/mips/arc/arc_con.c	Tue Feb  5 10:12:45 2002
+++ b/arch/mips/arc/arc_con.c	Fri Feb 14 15:09:50 2003
@@ -63,7 +63,8 @@
  *    Register console.
  */
 
-void __init arc_console_init(void)
+static void __init arc_console_init(void)
 {
 	register_console(&arc_cons);
 }
+console_initcall(arc_console_init);
diff -Nru a/arch/mips/au1000/common/serial.c b/arch/mips/au1000/common/serial.c
--- a/arch/mips/au1000/common/serial.c	Mon Feb 24 10:28:52 2003
+++ b/arch/mips/au1000/common/serial.c	Thu Mar  6 09:10:40 2003
@@ -3054,10 +3054,11 @@
 /*
  *	Register console.
  */
-void __init au1000_serial_console_init(void)
+static void __init au1000_serial_console_init(void)
 {
 	register_console(&sercons);
 }
+console_initcall(au1000_serial_console_init);
 #endif
 
 /*
diff -Nru a/arch/mips/baget/irq.c b/arch/mips/baget/irq.c
--- a/arch/mips/baget/irq.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips/baget/irq.c	Sat Mar  8 14:50:43 2003
@@ -146,11 +146,13 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < BAGET_IRQ_NR ; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 			i, kstat_cpu(0).irqs[i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -161,6 +163,8 @@
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/mips/dec/irq.c b/arch/mips/dec/irq.c
--- a/arch/mips/dec/irq.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips/dec/irq.c	Sat Mar  8 14:50:43 2003
@@ -97,11 +97,13 @@
 {
 	int i;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < 32; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action)
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 				i, kstat_cpu(0).irqs[i],
 				(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -112,6 +114,8 @@
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/mips/ite-boards/generic/irq.c b/arch/mips/ite-boards/generic/irq.c
--- a/arch/mips/ite-boards/generic/irq.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips/ite-boards/generic/irq.c	Sat Mar  8 14:50:43 2003
@@ -222,6 +222,7 @@
 {
         int i, j;
         struct irqaction * action;
+	unsigned long flags;
 
         seq_printf(p, "           ");
         for (j=0; j<smp_num_cpus; j++)
@@ -229,20 +230,25 @@
 	seq_putc(p, '\n');
 
         for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
                 action = irq_desc[i].action;
+
                 if ( !action || !action->handler )
-                        continue;
+                        goto skip;
                 seq_printf(p, "%3d: ", i);		
                 seq_printf(p, "%10u ", kstat_irqs(i));
                 if ( irq_desc[i].handler )		
                         seq_printf(p, " %s ", irq_desc[i].handler->typename );
                 else
                         seq_puts(p, "  None      ");
+
                 seq_printf(p, "    %s",action->name);
                 for (action=action->next; action; action = action->next) {
                         seq_printf(p, ", %s", action->name);
                 }
                 seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
         }
         seq_printf(p, "BAD: %10lu\n", spurious_count);
         return 0;
@@ -437,6 +443,7 @@
 		irq_desc[i].action	= 0;
 		irq_desc[i].depth	= 1;
 		irq_desc[i].handler	= &it8172_irq_type;
+		spin_lock_init(&irq_desc[i].lock);
 	}
 
 	/*
diff -Nru a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
--- a/arch/mips/kernel/irq.c	Tue Feb 25 01:38:35 2003
+++ b/arch/mips/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -73,17 +73,19 @@
 int show_interrupts(struct seq_file *p, void *v)
 {
 	struct irqaction * action;
+	unsigned long flags;
 	int i;
-
+	
 	seq_puts(p, "           ");
 	for (i=0; i < 1 /*smp_num_cpus*/; i++)
 		seq_printf(p, "CPU%d       ", i);
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto unlock;
 		seq_printf(p, "%3d: ",i);
 		seq_printf(p, "%10u ", kstat_irqs(i));
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
@@ -92,6 +94,8 @@
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "ERR: %10lu\n", irq_err_count);
 	return 0;
diff -Nru a/arch/mips/kernel/old-irq.c b/arch/mips/kernel/old-irq.c
--- a/arch/mips/kernel/old-irq.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips/kernel/old-irq.c	Sat Mar  8 14:50:43 2003
@@ -128,11 +128,13 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < 32 ; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 			i, kstat_cpu(0).irqs[i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -143,6 +145,8 @@
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
--- a/arch/mips/mips-boards/atlas/atlas_int.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips/mips-boards/atlas/atlas_int.c	Sat Mar  8 14:50:43 2003
@@ -99,11 +99,13 @@
 	int i;
 	int num = 0;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < ATLASINT_END; i++, num++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -114,6 +116,8 @@
 				action->name);
 		}
 		seq_printf(p, " [hw0]\n");
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	return 0;
 }
@@ -243,6 +247,7 @@
 		irq_desc[i].action	= 0;
 		irq_desc[i].depth	= 1;
 		irq_desc[i].handler	= &atlas_irq_type;
+		spin_lock_init(&irq_desc[i].lock);
 	}
 
 #ifdef CONFIG_REMOTE_DEBUG
diff -Nru a/arch/mips/philips/nino/irq.c b/arch/mips/philips/nino/irq.c
--- a/arch/mips/philips/nino/irq.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips/philips/nino/irq.c	Sat Mar  8 14:50:43 2003
@@ -119,11 +119,13 @@
 {
     int i;
     struct irqaction *action;
+    unsigned long flags;
 
     for (i = 0; i < NR_IRQS; i++) {
+	local_irq_save(flags);
 	action = irq_action[i];
 	if (!action)
-	    continue;
+	    goto skip;
 	seq_printf(p, "%2d: %8d %c %s",
 		       i, kstat_cpu(0).irqs[i],
 		       (action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -134,6 +136,8 @@
 			   action->name);
 	}
 	seq_putc(p, '\n');
+skip:
+	local_irq_restore(flags);
     }
     return 0;
 }
diff -Nru a/arch/mips/vmlinux.lds.S b/arch/mips/vmlinux.lds.S
--- a/arch/mips/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/mips/vmlinux.lds.S	Fri Feb 14 15:09:55 2003
@@ -51,6 +51,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(4096);	/* Align double page for init_task_union */
   __init_end = .;
 
diff -Nru a/arch/mips64/Kconfig b/arch/mips64/Kconfig
--- a/arch/mips64/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/mips64/Kconfig	Sat Mar  8 14:50:37 2003
@@ -9,10 +9,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 source "init/Kconfig"
 
 
diff -Nru a/arch/mips64/kernel/linux32.c b/arch/mips64/kernel/linux32.c
--- a/arch/mips64/kernel/linux32.c	Tue Feb 18 10:25:13 2003
+++ b/arch/mips64/kernel/linux32.c	Thu Mar  6 11:06:44 2003
@@ -729,12 +729,10 @@
 	return sys_llseek(fd, offset_high, offset_low, result, origin);
 }
 
-struct iovec32 { unsigned int iov_base; int iov_len; };
-
 typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *);
 
 static long
-do_readv_writev32(int type, struct file *file, const struct iovec32 *vector,
+do_readv_writev32(int type, struct file *file, const struct compat_iovec *vector,
 		  u32 count)
 {
 	unsigned long tot_len;
@@ -749,7 +747,7 @@
 	 */
 	if (!count)
 		return 0;
-	if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+	if(verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count))
 		return -EFAULT;
 	if (count > UIO_MAXIOV)
 		return -EINVAL;
@@ -835,7 +833,7 @@
 }
 
 asmlinkage long
-sys32_readv(int fd, struct iovec32 *vector, u32 count)
+sys32_readv(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	ssize_t ret;
@@ -855,7 +853,7 @@
 }
 
 asmlinkage long
-sys32_writev(int fd, struct iovec32 *vector, u32 count)
+sys32_writev(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	ssize_t ret;
@@ -1155,48 +1153,6 @@
 	return ret;
 }
 
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
-asmlinkage int sys32_setsockopt(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	if (optname == SO_ATTACH_FILTER) {
-		struct sock_fprog32 {
-			__u16 len;
-			__u32 filter;
-		} *fprog32 = (struct sock_fprog32 *)optval;
-		struct sock_fprog kfprog;
-		struct sock_filter *kfilter;
-		unsigned int fsize;
-		mm_segment_t old_fs;
-		__u32 uptr;
-		int ret;
-
-		if (get_user(kfprog.len, &fprog32->len) ||
-		    __get_user(uptr, &fprog32->filter))
-			return -EFAULT;
-		kfprog.filter = (struct sock_filter *)A(uptr);
-		fsize = kfprog.len * sizeof(struct sock_filter);
-		kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
-		if (kfilter == NULL)
-			return -ENOMEM;
-		if (copy_from_user(kfilter, kfprog.filter, fsize)) {
-			kfree(kfilter);
-			return -EFAULT;
-		}
-		kfprog.filter = kfilter;
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		ret = sys_setsockopt(fd, level, optname,
-				     (char *)&kfprog, sizeof(kfprog));
-		set_fs(old_fs);
-		kfree(kfilter);
-		return ret;
-	}
-	return sys_setsockopt(fd, level, optname, optval, optlen);
-}
-
 struct flock32 {
 	short l_type;
 	short l_whence;
@@ -1873,256 +1829,3 @@
 	return ret;
 }
 
-/*
- *  Declare the 32-bit version of the msghdr
- */
- 
-struct msghdr32 {
-	unsigned int    msg_name;	/* Socket name			*/
-	int		msg_namelen;	/* Length of name		*/
-	unsigned int    msg_iov;	/* Data blocks			*/
-	unsigned int	msg_iovlen;	/* Number of blocks		*/
-	unsigned int    msg_control;	/* Per protocol magic (eg BSD file descriptor passing) */
-	unsigned int	msg_controllen;	/* Length of cmsg list */
-	unsigned	msg_flags;
-};
-
-static inline int
-shape_msg(struct msghdr *mp, struct msghdr32 *mp32)
-{
-	int ret;
-	unsigned int i;
-
-	if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32)))
-		return(-EFAULT);
-	ret = __get_user(i, &mp32->msg_name);
-	mp->msg_name = (void *)A(i);
-	ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen);
-	ret |= __get_user(i, &mp32->msg_iov);
-	mp->msg_iov = (struct iovec *)A(i);
-	ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen);
-	ret |= __get_user(i, &mp32->msg_control);
-	mp->msg_control = (void *)A(i);
-	ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen);
-	ret |= __get_user(mp->msg_flags, &mp32->msg_flags);
-	return(ret ? -EFAULT : 0);
-}
-
-/*
- *	Verify & re-shape IA32 iovec. The caller must ensure that the
- *      iovec is big enough to hold the re-shaped message iovec.
- *
- *	Save time not doing verify_area. copy_*_user will make this work
- *	in any case.
- *
- *	Don't need to check the total size for overflow (cf net/core/iovec.c),
- *	32-bit sizes can't overflow a 64-bit count.
- */
-
-static inline int
-verify_iovec32(struct msghdr *m, struct iovec *iov, char *address, int mode)
-{
-	int size, err, ct;
-	struct iovec32 *iov32;
-	
-	if(m->msg_namelen)
-	{
-		if(mode==VERIFY_READ)
-		{
-			err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address);
-			if(err<0)
-				goto out;
-		}
-		
-		m->msg_name = address;
-	} else
-		m->msg_name = NULL;
-
-	err = -EFAULT;
-	size = m->msg_iovlen * sizeof(struct iovec32);
-	if (copy_from_user(iov, m->msg_iov, size))
-		goto out;
-	m->msg_iov=iov;
-
-	err = 0;
-	iov32 = (struct iovec32 *)iov;
-	for (ct = m->msg_iovlen; ct-- > 0; ) {
-		iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len;
-		iov[ct].iov_base = (void *) A(iov32[ct].iov_base);
-		err += iov[ct].iov_len;
-	}
-out:
-	return err;
-}
-
-/* XXX This really belongs in some header file... -DaveM */
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
-					   16 for IP, 16 for IPX,
-					   24 for IPv6,
-					   about 80 for AX.25 */
-
-/*
- *	BSD sendmsg interface
- */
-
-int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags)
-{
-	struct socket *sock;
-	char address[MAX_SOCK_ADDR];
-	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
-	unsigned char ctl[sizeof(struct cmsghdr) + 20];	/* 20 is size of ipv6_pktinfo */
-	unsigned char *ctl_buf = ctl;
-	struct msghdr msg_sys;
-	int err, ctl_len, iov_size, total_len;
-	
-	err = -EFAULT;
-	if (shape_msg(&msg_sys, msg))
-		goto out; 
-
-	sock = sockfd_lookup(fd, &err);
-	if (!sock) 
-		goto out;
-
-	/* do not move before msg_sys is valid */
-	err = -EINVAL;
-	if (msg_sys.msg_iovlen > UIO_MAXIOV)
-		goto out_put;
-
-	/* Check whether to allocate the iovec area*/
-	err = -ENOMEM;
-	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32);
-	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
-		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
-		if (!iov)
-			goto out_put;
-	}
-
-	/* This will also move the address data into kernel space */
-	err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ);
-	if (err < 0) 
-		goto out_freeiov;
-	total_len = err;
-
-	err = -ENOBUFS;
-
-	if (msg_sys.msg_controllen > INT_MAX)
-		goto out_freeiov;
-	ctl_len = msg_sys.msg_controllen; 
-	if (ctl_len) 
-	{
-		if (ctl_len > sizeof(ctl))
-		{
-			err = -ENOBUFS;
-			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
-			if (ctl_buf == NULL) 
-				goto out_freeiov;
-		}
-		err = -EFAULT;
-		if (copy_from_user(ctl_buf, msg_sys.msg_control, ctl_len))
-			goto out_freectl;
-		msg_sys.msg_control = ctl_buf;
-	}
-	msg_sys.msg_flags = flags;
-
-	if (sock->file->f_flags & O_NONBLOCK)
-		msg_sys.msg_flags |= MSG_DONTWAIT;
-	err = sock_sendmsg(sock, &msg_sys, total_len);
-
-out_freectl:
-	if (ctl_buf != ctl)    
-		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
-out_freeiov:
-	if (iov != iovstack)
-		sock_kfree_s(sock->sk, iov, iov_size);
-out_put:
-	sockfd_put(sock);
-out:       
-	return err;
-}
-
-/*
- *	BSD recvmsg interface
- */
-
-int
-sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags)
-{
-	struct socket *sock;
-	struct iovec iovstack[UIO_FASTIOV];
-	struct iovec *iov=iovstack;
-	struct msghdr msg_sys;
-	unsigned long cmsg_ptr;
-	int err, iov_size, total_len, len;
-
-	/* kernel mode address */
-	char addr[MAX_SOCK_ADDR];
-
-	/* user mode address pointers */
-	struct sockaddr *uaddr;
-	int *uaddr_len;
-	
-	err=-EFAULT;
-	if (shape_msg(&msg_sys, msg))
-		goto out;
-
-	sock = sockfd_lookup(fd, &err);
-	if (!sock)
-		goto out;
-
-	err = -EINVAL;
-	if (msg_sys.msg_iovlen > UIO_MAXIOV)
-		goto out_put;
-	
-	/* Check whether to allocate the iovec area*/
-	err = -ENOMEM;
-	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
-	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
-		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
-		if (!iov)
-			goto out_put;
-	}
-
-	/*
-	 *	Save the user-mode address (verify_iovec will change the
-	 *	kernel msghdr to use the kernel address space)
-	 */
-	 
-	uaddr = msg_sys.msg_name;
-	uaddr_len = &msg->msg_namelen;
-	err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE);
-	if (err < 0)
-		goto out_freeiov;
-	total_len=err;
-
-	cmsg_ptr = (unsigned long)msg_sys.msg_control;
-	msg_sys.msg_flags = 0;
-	
-	if (sock->file->f_flags & O_NONBLOCK)
-		flags |= MSG_DONTWAIT;
-	err = sock_recvmsg(sock, &msg_sys, total_len, flags);
-	if (err < 0)
-		goto out_freeiov;
-	len = err;
-
-	if (uaddr != NULL) {
-		err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
-		if (err < 0)
-			goto out_freeiov;
-	}
-	err = __put_user(msg_sys.msg_flags, &msg->msg_flags);
-	if (err)
-		goto out_freeiov;
-	err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, 
-							 &msg->msg_controllen);
-	if (err)
-		goto out_freeiov;
-	err = len;
-
-out_freeiov:
-	if (iov != iovstack)
-		sock_kfree_s(sock->sk, iov, iov_size);
-out_put:
-	sockfd_put(sock);
-out:
-	return err;
-}
diff -Nru a/arch/mips64/kernel/scall_o32.S b/arch/mips64/kernel/scall_o32.S
--- a/arch/mips64/kernel/scall_o32.S	Wed Dec 11 16:14:42 2002
+++ b/arch/mips64/kernel/scall_o32.S	Thu Mar  6 11:06:44 2003
@@ -378,8 +378,8 @@
 	sys	sys32_select	5
 	sys	sys_flock	2
 	sys	sys_msync	3
-	sys	sys32_readv	3			/* 4145 */
-	sys	sys32_writev	3
+	sys	compat_sys_readv	3			/* 4145 */
+	sys	compat_sys_writev	3
 	sys	sys_cacheflush	3
 	sys	sys_cachectl	3
 	sys	sys_sysmips	4
@@ -410,11 +410,11 @@
 	sys	sys_listen	2
 	sys	sys_recv	4			/* 4175 */
 	sys	sys_recvfrom	6
-	sys	sys32_recvmsg	3
+	sys	compat_sys_recvmsg	3
 	sys	sys_send	4
-	sys	sys32_sendmsg	3
+	sys	compat_sys_sendmsg	3
 	sys	sys_sendto	6			/* 4180 */
-	sys	sys32_setsockopt	5
+	sys	compat_sys_setsockopt	5
 	sys	sys_shutdown	2
 	sys	sys_socket	3
 	sys	sys_socketpair	4
diff -Nru a/arch/mips64/mips-boards/atlas/atlas_int.c b/arch/mips64/mips-boards/atlas/atlas_int.c
--- a/arch/mips64/mips-boards/atlas/atlas_int.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips64/mips-boards/atlas/atlas_int.c	Sat Mar  8 14:50:43 2003
@@ -95,11 +95,13 @@
 	int i;
 	int num = 0;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < ATLASINT_END; i++, num++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto unlock;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -110,6 +112,8 @@
 				action->name);
 		}
 		seq_puts(p, " [hw0]\n");
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	return 0;
 }
@@ -239,6 +243,7 @@
 		irq_desc[i].action	= 0;
 		irq_desc[i].depth	= 1;
 		irq_desc[i].handler	= &atlas_irq_type;
+		spin_lock_init(&irq_desc[i].lock);
 	}
 
 #ifdef CONFIG_REMOTE_DEBUG
diff -Nru a/arch/mips64/mips-boards/malta/malta_int.c b/arch/mips64/mips-boards/malta/malta_int.c
--- a/arch/mips64/mips-boards/malta/malta_int.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips64/mips-boards/malta/malta_int.c	Sat Mar  8 14:50:43 2003
@@ -125,11 +125,13 @@
 	int i;
 	int num = 0;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < 8; i++, num++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_1;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -140,11 +142,14 @@
 				action->name);
 		}
 		seq_puts(p, " [on-chip]\n");
+skip_1:
+		local_irq_restore(flags);
 	}
 	for (i = 0; i < MALTAINT_END; i++, num++) {
+		local_irq_save(flags);
 		action = hw0_irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_2;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -155,6 +160,8 @@
 				action->name);
 		}
 		seq_puts(p, " [hw0]\n");
+skip_2:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/mips64/sgi-ip22/ip22-int.c b/arch/mips64/sgi-ip22/ip22-int.c
--- a/arch/mips64/sgi-ip22/ip22-int.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips64/sgi-ip22/ip22-int.c	Sat Mar  8 14:50:43 2003
@@ -237,11 +237,13 @@
 	int i;
 	int num = 0;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < 16 ; i++, num++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_1;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -252,11 +254,14 @@
 				action->name);
 		}
 		seq_puts(p, " [on-chip]\n");
+skip_1:
+		local_irq_restore(flags);
 	}
 	for (i = 0 ; i < 24 ; i++, num++) {
+		local_irq_save(flags);
 		action = local_irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_2;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -267,6 +272,8 @@
 				action->name);
 		}
 		seq_puts(p, " [local]\n");
+skip_2:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/mips64/sgi-ip27/ip27-irq.c b/arch/mips64/sgi-ip27/ip27-irq.c
--- a/arch/mips64/sgi-ip27/ip27-irq.c	Thu Oct 31 07:28:36 2002
+++ b/arch/mips64/sgi-ip27/ip27-irq.c	Sat Mar  8 14:50:43 2003
@@ -141,11 +141,13 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i],
 		               (action->flags & SA_INTERRUPT) ? '+' : ' ',
 		               action->name);
@@ -156,6 +158,8 @@
 			                action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/mips64/vmlinux.lds.S b/arch/mips64/vmlinux.lds.S
--- a/arch/mips64/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/mips64/vmlinux.lds.S	Fri Feb 14 15:10:00 2003
@@ -50,6 +50,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(4096);	/* Align double page for init_task_union */
   __init_end = .;
 
diff -Nru a/arch/parisc/Kconfig b/arch/parisc/Kconfig
--- a/arch/parisc/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/parisc/Kconfig	Sat Mar  8 14:50:37 2003
@@ -18,10 +18,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config STACK_GROWSUP
 	bool
 	default y
diff -Nru a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
--- a/arch/parisc/kernel/sys_parisc32.c	Sat Feb 15 19:30:17 2003
+++ b/arch/parisc/kernel/sys_parisc32.c	Thu Mar  6 11:06:44 2003
@@ -919,12 +919,10 @@
 
 
 /* readv/writev stolen from mips64 */
-struct iovec32 { unsigned int iov_base; int iov_len; };
-
 typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *);
 
 static long
-do_readv_writev32(int type, struct file *file, const struct iovec32 *vector,
+do_readv_writev32(int type, struct file *file, const struct compat_iovec *vector,
 		  u32 count)
 {
 	unsigned long tot_len;
@@ -939,7 +937,7 @@
 	 */
 	if (!count)
 		return 0;
-	if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+	if(verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count))
 		return -EFAULT;
 	if (count > UIO_MAXIOV)
 		return -EINVAL;
@@ -1025,7 +1023,7 @@
 }
 
 asmlinkage long
-sys32_readv(int fd, struct iovec32 *vector, u32 count)
+sys32_readv(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	ssize_t ret;
@@ -1045,7 +1043,7 @@
 }
 
 asmlinkage long
-sys32_writev(int fd, struct iovec32 *vector, u32 count)
+sys32_writev(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	ssize_t ret;
@@ -1062,747 +1060,6 @@
 bad_file:
 	return ret;
 }
-
-/********** Borrowed from sparc64 -- hardly reviewed, not tested *****/
-#include <linux/net.h>
-#include <net/scm.h>
-/* XXX This really belongs in some header file... -DaveM */
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
-					   16 for IP, 16 for IPX,
-					   24 for IPv6,
-					   about 80 for AX.25 */
-
-extern struct socket *sockfd_lookup(int fd, int *err);
-
-struct msghdr32 {
-	u32		msg_name;
-	int		msg_namelen;
-	u32		msg_iov;
-	compat_size_t	msg_iovlen;
-	u32		msg_control;
-	compat_size_t	msg_controllen;
-	unsigned	msg_flags;
-};
-
-struct cmsghdr32 {
-	compat_size_t	cmsg_len;
-	int		cmsg_level;
-	int		cmsg_type;
-};
-
-/* Bleech... */
-#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
-#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
-
-#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
-
-#define CMSG32_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
-#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
-#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
-
-#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
-				    (struct cmsghdr32 *)(ctl) : \
-				    (struct cmsghdr32 *)NULL)
-#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-
-__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
-					      struct cmsghdr32 *__cmsg, int __cmsg_len)
-{
-	struct cmsghdr32 * __ptr;
-
-	__ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
-				     CMSG32_ALIGN(__cmsg_len));
-	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
-		return NULL;
-
-	return __ptr;
-}
-
-__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
-					    struct cmsghdr32 *__cmsg,
-					    int __cmsg_len)
-{
-	return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
-			       __cmsg, __cmsg_len);
-}
-
-static inline int iov_from_user32_to_kern(struct iovec *kiov,
-					  struct iovec32 *uiov32,
-					  int niov)
-{
-	int tot_len = 0;
-
-	while(niov > 0) {
-		u32 len, buf;
-
-		if(get_user(len, &uiov32->iov_len) ||
-		   get_user(buf, &uiov32->iov_base)) {
-			tot_len = -EFAULT;
-			break;
-		}
-		tot_len += len;
-		kiov->iov_base = (void *)A(buf);
-		kiov->iov_len = (__kernel_size_t) len;
-		uiov32++;
-		kiov++;
-		niov--;
-	}
-	return tot_len;
-}
-
-static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
-					     struct msghdr32 *umsg)
-{
-	u32 tmp1, tmp2, tmp3;
-	int err;
-
-	err = get_user(tmp1, &umsg->msg_name);
-	err |= __get_user(tmp2, &umsg->msg_iov);
-	err |= __get_user(tmp3, &umsg->msg_control);
-	if (err)
-		return -EFAULT;
-
-	kmsg->msg_name = (void *)A(tmp1);
-	kmsg->msg_iov = (struct iovec *)A(tmp2);
-	kmsg->msg_control = (void *)A(tmp3);
-
-	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
-	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
-	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
-	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
-	
-	return err;
-}
-
-/* I've named the args so it is easy to tell whose space the pointers are in. */
-static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
-			  char *kern_address, int mode)
-{
-	int tot_len;
-
-	if(kern_msg->msg_namelen) {
-		if(mode==VERIFY_READ) {
-			int err = move_addr_to_kernel(kern_msg->msg_name,
-						      kern_msg->msg_namelen,
-						      kern_address);
-			if(err < 0)
-				return err;
-		}
-		kern_msg->msg_name = kern_address;
-	} else
-		kern_msg->msg_name = NULL;
-
-	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
-		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
-				   GFP_KERNEL);
-		if(!kern_iov)
-			return -ENOMEM;
-	}
-
-	tot_len = iov_from_user32_to_kern(kern_iov,
-					  (struct iovec32 *)kern_msg->msg_iov,
-					  kern_msg->msg_iovlen);
-	if(tot_len >= 0)
-		kern_msg->msg_iov = kern_iov;
-	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
-		kfree(kern_iov);
-
-	return tot_len;
-}
-
-/* There is a lot of hair here because the alignment rules (and
- * thus placement) of cmsg headers and length are different for
- * 32-bit apps.  -DaveM
- */
-static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
-				       unsigned char *stackbuf, int stackbuf_size)
-{
-	struct cmsghdr32 *ucmsg;
-	struct cmsghdr *kcmsg, *kcmsg_base;
-	compat_size_t ucmlen;
-	__kernel_size_t kcmlen, tmp;
-
-	kcmlen = 0;
-	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		if(get_user(ucmlen, &ucmsg->cmsg_len))
-			return -EFAULT;
-
-		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
-			return -EINVAL;
-
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmlen += tmp;
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-	if(kcmlen == 0)
-		return -EINVAL;
-
-	/* The kcmlen holds the 64-bit version of the control length.
-	 * It may not be modified as we do not stick it into the kmsg
-	 * until we have successfully copied over all of the data
-	 * from the user.
-	 */
-	if(kcmlen > stackbuf_size)
-		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
-	if(kcmsg == NULL)
-		return -ENOBUFS;
-
-	/* Now copy them over neatly. */
-	memset(kcmsg, 0, kcmlen);
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		__get_user(ucmlen, &ucmsg->cmsg_len);
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmsg->cmsg_len = tmp;
-		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
-		/* Copy over the data. */
-		if(copy_from_user(CMSG_DATA(kcmsg),
-				  CMSG32_DATA(ucmsg),
-				  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
-			goto out_free_efault;
-
-		/* Advance. */
-		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-
-	/* Ok, looks like we made it.  Hook it up and return success. */
-	kmsg->msg_control = kcmsg_base;
-	kmsg->msg_controllen = kcmlen;
-	return 0;
-
-out_free_efault:
-	if(kcmsg_base != (struct cmsghdr *)stackbuf)
-		kfree(kcmsg_base);
-	return -EFAULT;
-}
-
-static void put_cmsg32(struct msghdr *kmsg, int level, int type,
-		       int len, void *data)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	struct cmsghdr32 cmhdr;
-	int cmlen = CMSG32_LEN(len);
-
-	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		return;
-	}
-
-	if(kmsg->msg_controllen < cmlen) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		cmlen = kmsg->msg_controllen;
-	}
-	cmhdr.cmsg_level = level;
-	cmhdr.cmsg_type = type;
-	cmhdr.cmsg_len = cmlen;
-
-	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
-		return;
-	if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
-		return;
-	cmlen = CMSG32_SPACE(len);
-	kmsg->msg_control += cmlen;
-	kmsg->msg_controllen -= cmlen;
-}
-
-static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
-	int fdnum = scm->fp->count;
-	struct file **fp = scm->fp->fp;
-	int *cmfptr;
-	int err = 0, i;
-
-	if (fdnum < fdmax)
-		fdmax = fdnum;
-
-	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
-		int new_fd;
-		err = get_unused_fd();
-		if (err < 0)
-			break;
-		new_fd = err;
-		err = put_user(new_fd, cmfptr);
-		if (err) {
-			put_unused_fd(new_fd);
-			break;
-		}
-		/* Bump the usage count and install the file. */
-		get_file(fp[i]);
-		fd_install(new_fd, fp[i]);
-	}
-
-	if (i > 0) {
-		int cmlen = CMSG32_LEN(i * sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
-		if (!err)
-			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
-		if (!err)
-			err = put_user(cmlen, &cm->cmsg_len);
-		if (!err) {
-			cmlen = CMSG32_SPACE(i * sizeof(int));
-			kmsg->msg_control += cmlen;
-			kmsg->msg_controllen -= cmlen;
-		}
-	}
-	if (i < fdnum)
-		kmsg->msg_flags |= MSG_CTRUNC;
-
-	/*
-	 * All of the files that fit in the message have had their
-	 * usage counts incremented, so we just free the list.
-	 */
-	__scm_destroy(scm);
-}
-
-/* In these cases we (currently) can just copy to data over verbatim
- * because all CMSGs created by the kernel have well defined types which
- * have the same layout in both the 32-bit and 64-bit API.  One must add
- * some special cased conversions here if we start sending control messages
- * with incompatible types.
- *
- * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
- * we do our work.  The remaining cases are:
- *
- * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
- *		IP_TTL		int			32-bit clean
- *		IP_TOS		__u8			32-bit clean
- *		IP_RECVOPTS	variable length		32-bit clean
- *		IP_RETOPTS	variable length		32-bit clean
- *		(these last two are clean because the types are defined
- *		 by the IPv4 protocol)
- *		IP_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in	32-bit clean
- * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in6	32-bit clean
- *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
- *		IPV6_HOPLIMIT	int			32-bit clean
- *		IPV6_FLOWINFO	u32			32-bit clean
- *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
- *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
- *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
- *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
- */
-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
-{
-	unsigned char *workbuf, *wp;
-	unsigned long bufsz, space_avail;
-	struct cmsghdr *ucmsg;
-
-	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
-	space_avail = kmsg->msg_controllen + bufsz;
-	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
-	if(workbuf == NULL)
-		goto fail;
-
-	/* To make this more sane we assume the kernel sends back properly
-	 * formatted control messages.  Because of how the kernel will truncate
-	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
-	 */
-	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
-	while(((unsigned long)ucmsg) <=
-	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
-		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
-		int clen64, clen32;
-
-		/* UCMSG is the 64-bit format CMSG entry in user-space.
-		 * KCMSG32 is within the kernel space temporary buffer
-		 * we use to convert into a 32-bit style CMSG.
-		 */
-		__get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
-		__get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
-
-		clen64 = kcmsg32->cmsg_len;
-		copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
-			       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
-		clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
-			  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
-		kcmsg32->cmsg_len = clen32;
-
-		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
-		wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
-	}
-
-	/* Copy back fixed up data, and adjust pointers. */
-	bufsz = (wp - workbuf);
-	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
-
-	kmsg->msg_control = (struct cmsghdr *)
-		(((char *)orig_cmsg_uptr) + bufsz);
-	kmsg->msg_controllen = space_avail - bufsz;
-
-	kfree(workbuf);
-	return;
-
-fail:
-	/* If we leave the 64-bit format CMSG chunks in there,
-	 * the application could get confused and crash.  So to
-	 * ensure greater recovery, we report no CMSGs.
-	 */
-	kmsg->msg_controllen += bufsz;
-	kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
-{
-	struct socket *sock;
-	char address[MAX_SOCK_ADDR];
-	struct iovec iov[UIO_FASTIOV];
-	unsigned char ctl[sizeof(struct cmsghdr) + 20];
-	unsigned char *ctl_buf = ctl;
-	struct msghdr kern_msg;
-	int err, total_len;
-
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-	err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	if(kern_msg.msg_controllen) {
-		err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
-		if(err)
-			goto out_freeiov;
-		ctl_buf = kern_msg.msg_control;
-	}
-	kern_msg.msg_flags = user_flags;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		if (sock->file->f_flags & O_NONBLOCK)
-			kern_msg.msg_flags |= MSG_DONTWAIT;
-		err = sock_sendmsg(sock, &kern_msg, total_len);
-		sockfd_put(sock);
-	}
-
-	/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
-	if(ctl_buf != ctl)
-		kfree(ctl_buf);
-out_freeiov:
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	return err;
-}
-
-asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
-{
-	struct iovec iovstack[UIO_FASTIOV];
-	struct msghdr kern_msg;
-	char addr[MAX_SOCK_ADDR];
-	struct socket *sock;
-	struct iovec *iov = iovstack;
-	struct sockaddr *uaddr;
-	int *uaddr_len;
-	unsigned long cmsg_ptr;
-	int err, total_len, len = 0;
-
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-
-	uaddr = kern_msg.msg_name;
-	uaddr_len = &user_msg->msg_namelen;
-	err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	cmsg_ptr = (unsigned long) kern_msg.msg_control;
-	kern_msg.msg_flags = 0;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		struct sock_iocb *si;
-		struct kiocb iocb;
-
-		if (sock->file->f_flags & O_NONBLOCK)
-			user_flags |= MSG_DONTWAIT;
-
-		init_sync_kiocb(&iocb, NULL);
-		si = kiocb_to_siocb(&iocb);
-		si->sock = sock;
-		si->scm = &si->async_scm;
-		si->msg = &kern_msg;
-		si->size = total_len;
-		si->flags = user_flags;
-		memset(si->scm, 0, sizeof(*si->scm));
-
-		err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len,
-					 user_flags, si->scm);
-		if (-EIOCBQUEUED == err)
-			err = wait_on_sync_kiocb(&iocb);
-
-		if(err >= 0) {
-			len = err;
-			if(!kern_msg.msg_control) {
-				if(sock->passcred || si->scm->fp)
-					kern_msg.msg_flags |= MSG_CTRUNC;
-				if(si->scm->fp)
-					__scm_destroy(si->scm);
-			} else {
-				/* If recvmsg processing itself placed some
-				 * control messages into user space, it's is
-				 * using 64-bit CMSG processing, so we need
-				 * to fix it up before we tack on more stuff.
-				 */
-				if((unsigned long) kern_msg.msg_control != cmsg_ptr)
-					cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
-
-				/* Wheee... */
-				if(sock->passcred)
-					put_cmsg32(&kern_msg,
-						   SOL_SOCKET, SCM_CREDENTIALS,
-						   sizeof(si->scm->creds),
-						   &si->scm->creds);
-				if(si->scm->fp != NULL)
-					scm_detach_fds32(&kern_msg, si->scm);
-			}
-		}
-		sockfd_put(sock);
-	}
-
-	if(uaddr != NULL && err >= 0)
-		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
-	if(cmsg_ptr != 0 && err >= 0) {
-		unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
-		compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr);
-		err |= __put_user(uclen, &user_msg->msg_controllen);
-	}
-	if(err >= 0)
-		err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	if(err < 0)
-		return err;
-	return len;
-}
-
-
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
-static int do_set_attach_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct sock_fprog32 {
-		__u16 len;
-		__u32 filter;
-	} *fprog32 = (struct sock_fprog32 *)optval;
-	struct sock_fprog kfprog;
-	struct sock_filter *kfilter;
-	unsigned int fsize;
-	mm_segment_t old_fs;
-	__u32 uptr;
-	int ret;
-
-	if (get_user(kfprog.len, &fprog32->len) ||
-	    __get_user(uptr, &fprog32->filter))
-		return -EFAULT;
-
-	kfprog.filter = (struct sock_filter *)A(uptr);
-	fsize = kfprog.len * sizeof(struct sock_filter);
-
-	kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
-	if (kfilter == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(kfilter, kfprog.filter, fsize)) {
-		kfree(kfilter);
-		return -EFAULT;
-	}
-
-	kfprog.filter = kfilter;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *)&kfprog, sizeof(kfprog));
-	set_fs(old_fs);
-
-	kfree(kfilter);
-
-	return ret;
-}
-
-static int do_set_icmpv6_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct icmp6_filter kfilter;
-	mm_segment_t old_fs;
-	int ret, i;
-
-	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
-		return -EFAULT;
-
-
-	for (i = 0; i < 8; i += 2) {
-		u32 tmp = kfilter.data[i];
-
-		kfilter.data[i] = kfilter.data[i + 1];
-		kfilter.data[i + 1] = tmp;
-	}
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *) &kfilter, sizeof(kfilter));
-	set_fs(old_fs);
-
-	return ret;
-}
-
-
-static int do_ipv4_set_replace(int fd, int level, int optname,
-				char *optval, int optlen)
-#if 1
-/* Fields happen to be padded such that this works.
-** Don't need to change iptables.h:struct ipt_replace
-*/
-{
-	struct ipt_replace *repl = (struct ipt_replace *) optval;
-	unsigned long ptr64;
-	unsigned int ptr32;
-	int ret;
-
-	if (copy_from_user(&ptr32, &repl->counters, sizeof(ptr32)))
-		return -EFAULT;
-	ptr64 = (unsigned long) ptr32;
-	if (copy_to_user(&repl->counters, &ptr64, sizeof(ptr64)))
-		return -EFAULT;
-
-	ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen);
-
-	/* Restore 32-bit ptr */
-	if (copy_to_user(&repl->counters, &ptr32, sizeof(ptr32)))
-		return -EFAULT;
-
-	return ret;
-}
-#else
-/* This version tries to "do it right". ie allocate kernel buffers for
-** everything and copy data in/out. Way too complicated.
-** NOT TESTED for correctness!
-*/
-{
-	struct ipt_replace  *kern_repl;
-	struct ipt_counters *kern_counters;
-	unsigned int user_counters;
-	mm_segment_t old_fs;
-	int ret = 0;
-
-	kern_repl = (struct ipt_replace *) kmalloc(optlen+8, GFP_KERNEL);
-	if (!kern_repl)
-		return -ENOMEM;
-
-	if (copy_from_user(kern_repl, optval, optlen)) {
-		ret = -EFAULT;
-		goto err02;
-	}
-
-	/* 32-bit ptr is in the MSB's */
-	user_counters = (unsigned int) (((unsigned long) kern_repl->counters) >> 32);
-	/*
-	** We are going to set_fs() to kernel space - and thus need
-	** "relocate" the counters buffer to the kernel space.
-	*/
-	kern_counters = (struct ipt_counters *) kmalloc(kern_repl->num_counters * sizeof(struct ipt_counters), GFP_KERNEL);
-	if (!user_counters) {
-		ret = -ENOMEM;
-		goto err02;
-	}
-
-	if (copy_from_user(kern_counters, (char *) user_counters, optlen)) {
-		ret = -EFAULT;
-		goto err01;
-	}
-
-	/* We can update the kernel ptr now that we have the data. */
-	kern_repl->counters = kern_counters;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-
-	ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen);
-
-	set_fs(old_fs);
-
-	/* Copy counters back out to user space */
-	if (copy_to_user((char *) user_counters, kern_counters,
-			kern_repl->num_counters * sizeof(struct ipt_counters)))
-	{
-		ret = -EFAULT;
-		goto err01;
-	}
-
-	/* restore counters so userspace can consume it */
-	kern_repl->counters = NULL;
-	(unsigned int) kern_repl->counters = user_counters;
-
-	/* Copy repl back out to user space */
-	if (copy_to_user(optval, kern_repl, optlen))
-	{
-		ret = -EFAULT;
-	}
-
-err01:
-	kfree(kern_counters);
-err02:
-	kfree(kern_repl);
-	return ret;
-}
-#endif
-
-
-asmlinkage int sys32_setsockopt(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	if (optname == SO_ATTACH_FILTER)
-		return do_set_attach_filter(fd, level, optname, optval, optlen);
-
-	if (level == SOL_ICMPV6   && optname == ICMPV6_FILTER)
-		return do_set_icmpv6_filter(fd, level, optname, optval, optlen);
-
-	/*
-	** Beware:    IPT_SO_SET_REPLACE == IP6T_SO_SET_REPLACE
-	*/
-	if (level == IPPROTO_IP   && optname == IPT_SO_SET_REPLACE)
-		return do_ipv4_set_replace(fd, level, optname, optval, optlen);
-
-	if (level == IPPROTO_IPV6 && optname == IP6T_SO_SET_REPLACE)
-#if 0
-		/* FIXME: I don't (yet) use IPV6. -ggg */
-		return do_ipv6_set_replace(fd, level, optname, optval, optlen);
-#else
-	{
-		BUG();
-		return -ENXIO;
-	}
-#endif
-
-	return sys_setsockopt(fd, level, optname, optval, optlen);
-}
-
 
 /*** copied from mips64 ***/
 /*
diff -Nru a/arch/parisc/vmlinux.lds.S b/arch/parisc/vmlinux.lds.S
--- a/arch/parisc/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/parisc/vmlinux.lds.S	Fri Feb 14 15:10:04 2003
@@ -73,6 +73,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
diff -Nru a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c
--- a/arch/ppc/8xx_io/uart.c	Mon Feb  3 05:47:46 2003
+++ b/arch/ppc/8xx_io/uart.c	Mon Mar  3 11:33:06 2003
@@ -2522,12 +2522,11 @@
 /*
  *	Register console.
  */
-long __init console_8xx_init(long kmem_start, long kmem_end)
+static void __init console_8xx_init(long kmem_start, long kmem_end)
 {
 	register_console(&sercons);
-	return kmem_start;
 }
-
+console_initcall(console_8xx_init);
 #endif
 
 /* Index in baud rate table of the default console baud rate.
diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig
--- a/arch/ppc/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/ppc/Kconfig	Sat Mar  8 14:50:37 2003
@@ -1126,22 +1126,6 @@
 config PIN_TLB
 	bool "Pinned Kernel TLBs (860 ONLY)"
 	depends on ADVANCED_OPTIONS && 8xx
-
-config SWAP
-	bool "Enable support for swap"
-	depends on ADVANCED_OPTIONS
-	help
-	  This option allows you to turn off support for swapfiles in
-	  the kernel.  This can be useful if you know that your system
-	  will never have swap.
-
-	  Say Y here unless you know what you are doing.
-
-config SWAP
-	bool
-	depends on !ADVANCED_OPTIONS
-	default y
-
 endmenu
 
 source "drivers/mtd/Kconfig"
diff -Nru a/arch/ppc/boot/simple/rw4/ppc_40x.h b/arch/ppc/boot/simple/rw4/ppc_40x.h
--- a/arch/ppc/boot/simple/rw4/ppc_40x.h	Fri Feb 14 15:10:29 2003
+++ b/arch/ppc/boot/simple/rw4/ppc_40x.h	Wed Feb 19 07:23:15 2003
@@ -42,7 +42,7 @@
 #define dccr            0x3fa               /* data cache control reg.       */
 #define dcwr            0x3ba               /* data cache write-thru reg     */
 #define dear            0x3d5               /* data exception address reg    */
-#define esr             0x3d4               /* exception syndrome registe    */
+#define esr             0x3d4               /* exception syndrome register   */
 #define evpr            0x3d6               /* exception vector prefix reg   */
 #define iccr            0x3fb               /* instruction cache cntrl re    */
 #define icdbdr          0x3d3               /* instr cache dbug data reg     */
diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
--- a/arch/ppc/kernel/irq.c	Sat Feb 15 13:50:01 2003
+++ b/arch/ppc/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -346,6 +346,7 @@
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
@@ -354,9 +355,10 @@
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if ( !action || !action->handler )
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ", i);		
 #ifdef CONFIG_SMP
 		for (j = 0; j < NR_CPUS; j++)
@@ -373,8 +375,10 @@
 		seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge  ");
 		seq_printf(p, "    %s", action->name);
 		for (action = action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
+				seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 #ifdef CONFIG_TAU_INT
 	if (tau_initialized){
diff -Nru a/arch/ppc/vmlinux.lds.S b/arch/ppc/vmlinux.lds.S
--- a/arch/ppc/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/ppc/vmlinux.lds.S	Fri Feb 14 15:10:39 2003
@@ -107,6 +107,10 @@
   }
   __initcall_end = .;
 
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
+
   __start___ftr_fixup = .;
   __ftr_fixup : { *(__ftr_fixup) }
   __stop___ftr_fixup = .;
diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
--- a/arch/ppc64/Kconfig	Thu Feb 13 00:47:26 2003
+++ b/arch/ppc64/Kconfig	Sat Mar  8 14:50:37 2003
@@ -7,10 +7,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 
diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c
--- a/arch/ppc64/kernel/irq.c	Mon Dec 16 19:26:01 2002
+++ b/arch/ppc64/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -341,6 +341,7 @@
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_printf(p, "           ");
 	for (j=0; j<NR_CPUS; j++) {
@@ -350,9 +351,10 @@
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action || !action->handler)
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ", i);		
 #ifdef CONFIG_SMP
 		for (j = 0; j < NR_CPUS; j++) {
@@ -371,6 +373,8 @@
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
 	return 0;
diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	Sat Feb 22 00:17:10 2003
+++ b/arch/ppc64/kernel/misc.S	Thu Mar  6 11:06:44 2003
@@ -604,7 +604,7 @@
 	.llong .compat_sys_statfs
 	.llong .compat_sys_fstatfs		/* 100 */
 	.llong .sys_ioperm
-	.llong .sys32_socketcall
+	.llong .compat_sys_socketcall
 	.llong .sys32_syslog
 	.llong .compat_sys_setitimer
 	.llong .compat_sys_getitimer		/* 105 */
diff -Nru a/arch/ppc64/kernel/sys32.S b/arch/ppc64/kernel/sys32.S
--- a/arch/ppc64/kernel/sys32.S	Tue Feb 18 10:25:13 2003
+++ b/arch/ppc64/kernel/sys32.S	Thu Mar  6 11:06:44 2003
@@ -25,7 +25,7 @@
 	extsw		r4,r4		/* sign extend off_t offset parm */
 	b		.sys_lseek
 
-_GLOBAL(sys32_socketcall)	/* r3=call, r4=args */
+_GLOBAL(compat_sys_socketcall)	/* r3=call, r4=args */
 	cmpwi		r3, 1
 	blt-		.do_einval
 	cmpwi		r3, 17
@@ -221,14 +221,14 @@
 	.llong		2b,.do_efault
 	.previous
 
-_STATIC(do_sys_setsockopt) /* sys32_setsockopt(int, int, int, char *, int) */
+_STATIC(do_sys_setsockopt) /* compat_sys_setsockopt(int, int, int, char *, int) */
 	mr		r10,r4
 1:	lwa		r3,0(r10)
 2:	lwa		r4,4(r10)
 3:	lwa		r5,8(r10)
 4:	lwz		r6,12(r10)
 5:	lwa		r7,16(r10)
-	b		.sys32_setsockopt
+	b		.compat_sys_setsockopt
 	.section	__ex_table,"a"
 	.align		3
 	.llong		1b,.do_efault
@@ -238,14 +238,14 @@
 	.llong		5b,.do_efault
 	.previous
 
-_STATIC(do_sys_getsockopt) /* sys32_getsockopt(int, int, int, u32, u32) */
+_STATIC(do_sys_getsockopt) /* compat_sys_getsockopt(int, int, int, u32, u32) */
 	mr		r10,r4
 1:	lwa		r3,0(r10)
 2:	lwa		r4,4(r10)
 3:	lwa		r5,8(r10)
 4:	lwz		r6,12(r10)
 5:	lwz		r7,16(r10)
-	b		.sys32_getsockopt
+	b		.compat_sys_getsockopt
 	.section	__ex_table,"a"
 	.align		3
 	.llong		1b,.do_efault
@@ -255,12 +255,12 @@
 	.llong		5b,.do_efault
 	.previous
 
-_STATIC(do_sys_sendmsg) /* sys32_sendmsg(int, struct msghdr32 *, unsigned int) */
+_STATIC(do_sys_sendmsg) /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */
 	mr		r10,r4
 1:	lwa		r3,0(r10)
 2:	lwz		r4,4(r10)
 3:	lwa		r5,8(r10)
-	b		.sys32_sendmsg
+	b		.compat_sys_sendmsg
 	.section	__ex_table,"a"
 	.align		3
 	.llong		1b,.do_efault
@@ -268,12 +268,12 @@
 	.llong		3b,.do_efault
 	.previous
 
-_STATIC(do_sys_recvmsg) /* sys32_recvmsg(int, struct msghdr32 *, unsigned int) */
+_STATIC(do_sys_recvmsg) /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */
 	mr		r10,r4
 1:	lwa		r3,0(r10)
 2:	lwz		r4,4(r10)
 3:	lwa		r5,8(r10)
-	b		.sys32_recvmsg
+	b		.compat_sys_recvmsg
 	.section	__ex_table,"a"
 	.align		3
 	.llong		1b,.do_efault
diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
--- a/arch/ppc64/kernel/sys_ppc32.c	Tue Feb 18 10:25:13 2003
+++ b/arch/ppc64/kernel/sys_ppc32.c	Thu Mar  6 11:06:44 2003
@@ -74,13 +74,11 @@
 #include <asm/ppc32.h>
 #include <asm/mmu_context.h>
 
-struct iovec32 { u32 iov_base; compat_size_t iov_len; };
-
 typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
 typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
 
 static long do_readv_writev32(int type, struct file *file,
-			      const struct iovec32 *vector, u32 count)
+			      const struct compat_iovec *vector, u32 count)
 {
 	compat_ssize_t tot_len;
 	struct iovec iovstack[UIO_FASTIOV];
@@ -114,7 +112,7 @@
 			goto out;
 	}
 	retval = -EFAULT;
-	if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+	if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count))
 		goto out;
 
 	/*
@@ -206,7 +204,7 @@
 	return retval;
 }
 
-asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
+asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	int ret = -EBADF;
@@ -227,7 +225,7 @@
 	return ret;
 }
 
-asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
+asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	int ret = -EBADF;
@@ -2133,708 +2131,6 @@
 		return -EFAULT;
 		
 	return ret;
-}
-
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname, char *optval, int optlen);
-
-static int do_set_attach_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct sock_fprog32 {
-		__u16 len;
-		__u32 filter;
-	} *fprog32 = (struct sock_fprog32 *)optval;
-	struct sock_fprog kfprog;
-	struct sock_filter *kfilter;
-	unsigned int fsize;
-	mm_segment_t old_fs;
-	__u32 uptr;
-	int ret;
-
-	if (get_user(kfprog.len, &fprog32->len) ||
-	    __get_user(uptr, &fprog32->filter))
-		return -EFAULT;
-
-	kfprog.filter = (struct sock_filter *)A(uptr);
-	fsize = kfprog.len * sizeof(struct sock_filter);
-
-	kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
-	if (kfilter == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(kfilter, kfprog.filter, fsize)) {
-		kfree(kfilter);
-		return -EFAULT;
-	}
-
-	kfprog.filter = kfilter;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *)&kfprog, sizeof(kfprog));
-	set_fs(old_fs);
-
-	kfree(kfilter);
-
-	return ret;
-}
-
-static int do_set_icmpv6_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct icmp6_filter kfilter;
-	mm_segment_t old_fs;
-	int ret, i;
-
-	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
-		return -EFAULT;
-
-
-	for (i = 0; i < 8; i += 2) {
-		u32 tmp = kfilter.data[i];
-
-		kfilter.data[i] = kfilter.data[i + 1];
-		kfilter.data[i + 1] = tmp;
-	}
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *) &kfilter, sizeof(kfilter));
-	set_fs(old_fs);
-
-	return ret;
-}
-
-static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen)
-{
-	struct compat_timeval *up = (struct compat_timeval *) optval;
-	struct timeval ktime;
-	mm_segment_t old_fs;
-	int err;
-
-	if (optlen < sizeof(*up))
-		return -EINVAL;
-	if (get_user(ktime.tv_sec, &up->tv_sec) ||
-	    __get_user(ktime.tv_usec, &up->tv_usec))
-		return -EFAULT;
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime));
-	set_fs(old_fs);
-
-	return err;
-}
-
-asmlinkage long sys32_setsockopt(int fd, int level, int optname, char* optval, int optlen)
-{
-	if (optname == SO_ATTACH_FILTER)
-		return do_set_attach_filter(fd, level, optname,
-					    optval, optlen);
-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
-		return do_set_sock_timeout(fd, level, optname, optval, optlen);
-	if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER)
-		return do_set_icmpv6_filter(fd, level, optname,
-					    optval, optlen);
-
-	return sys_setsockopt(fd, level, optname, optval, optlen);
-}
-
-extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
-				      char *optval, int *optlen);
-
-static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
-{
-	struct compat_timeval *up = (struct compat_timeval *) optval;
-	struct timeval ktime;
-	mm_segment_t old_fs;
-	int len, err;
-
-	if (get_user(len, optlen))
-		return -EFAULT;
-	if (len < sizeof(*up))
-		return -EINVAL;
-	len = sizeof(ktime);
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len);
-	set_fs(old_fs);
-
-	if (!err) {
-		if (put_user(sizeof(*up), optlen) ||
-		    put_user(ktime.tv_sec, &up->tv_sec) ||
-		    __put_user(ktime.tv_usec, &up->tv_usec))
-			err = -EFAULT;
-	}
-	return err;
-}
-
-asmlinkage int sys32_getsockopt(int fd, int level, int optname,
-				char *optval, int *optlen)
-{
-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
-		return do_get_sock_timeout(fd, level, optname, optval, optlen);
-	return sys_getsockopt(fd, level, optname, optval, optlen);
-}
-
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain -  16 for IP, 16 for IPX, 24 for IPv6, about 80 for AX.25 */
-#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
-#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
-
-#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
-
-#define CMSG32_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
-#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
-#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
-#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
-				    (struct cmsghdr32 *)(ctl) : \
-				    (struct cmsghdr32 *)NULL)
-#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-
-struct msghdr32
-{
-	u32               msg_name;
-	int               msg_namelen;
-	u32               msg_iov;
-	compat_size_t msg_iovlen;
-	u32               msg_control;
-	compat_size_t msg_controllen;
-	unsigned          msg_flags;
-};
-
-struct cmsghdr32
-{
-	compat_size_t cmsg_len;
-	int               cmsg_level;
-	int               cmsg_type;
-};
-
-__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
-					     struct cmsghdr32 *__cmsg, int __cmsg_len)
-{
-	struct cmsghdr32 * __ptr;
-
-	__ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
-				     CMSG32_ALIGN(__cmsg_len));
-	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
-		return NULL;
-
-	return __ptr;
-}
-
-__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
-					    struct cmsghdr32 *__cmsg,
-					    int __cmsg_len)
-{
-	return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
-			       __cmsg, __cmsg_len);
-}
-
-static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, struct msghdr32 *umsg)
-{
-	u32 tmp1, tmp2, tmp3;
-	int err;
-
-	err = get_user(tmp1, &umsg->msg_name);
-	err |= __get_user(tmp2, &umsg->msg_iov);
-	err |= __get_user(tmp3, &umsg->msg_control);
-	if (err)
-		return -EFAULT;
-
-	kmsg->msg_name = (void *)A(tmp1);
-	kmsg->msg_iov = (struct iovec *)A(tmp2);
-	kmsg->msg_control = (void *)A(tmp3);
-
-	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
-	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
-	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
-	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
-	
-	return err;
-}
-
-static inline int iov_from_user32_to_kern(struct iovec *kiov,
-					  struct iovec32 *uiov32,
-					  int niov)
-{
-	int tot_len = 0;
-
-	while(niov > 0) {
-		u32 len, buf;
-
-		if(get_user(len, &uiov32->iov_len) ||
-		   get_user(buf, &uiov32->iov_base)) {
-			tot_len = -EFAULT;
-			break;
-		}
-		tot_len += len;
-		kiov->iov_base = (void *)A(buf);
-		kiov->iov_len = (__kernel_size_t) len;
-		uiov32++;
-		kiov++;
-		niov--;
-	}
-	return tot_len;
-}
-
-/* I've named the args so it is easy to tell whose space the pointers are in. */
-static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
-			  char *kern_address, int mode)
-{
-	int tot_len;
-
-	if(kern_msg->msg_namelen) {
-		if(mode==VERIFY_READ) {
-			int err = move_addr_to_kernel(kern_msg->msg_name,
-						      kern_msg->msg_namelen,
-						      kern_address);
-			if(err < 0)
-				return err;
-		}
-		kern_msg->msg_name = kern_address;
-	} else
-		kern_msg->msg_name = NULL;
-
-	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
-		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
-				   GFP_KERNEL);
-		if(!kern_iov)
-			return -ENOMEM;
-	}
-
-	tot_len = iov_from_user32_to_kern(kern_iov,
-					  (struct iovec32 *)kern_msg->msg_iov,
-					  kern_msg->msg_iovlen);
-	if(tot_len >= 0)
-		kern_msg->msg_iov = kern_iov;
-	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
-		kfree(kern_iov);
-
-	return tot_len;
-}
-
-/* There is a lot of hair here because the alignment rules (and
- * thus placement) of cmsg headers and length are different for
- * 32-bit apps.  -DaveM
- */
-static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
-				       unsigned char *stackbuf, int stackbuf_size)
-{
-	struct cmsghdr32 *ucmsg;
-	struct cmsghdr *kcmsg, *kcmsg_base;
-	compat_size_t ucmlen;
-	__kernel_size_t kcmlen, tmp;
-
-	kcmlen = 0;
-	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		if(get_user(ucmlen, &ucmsg->cmsg_len))
-			return -EFAULT;
-
-		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
-			return -EINVAL;
-
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmlen += tmp;
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-	if (kcmlen == 0)
-		return -EINVAL;
-
-	/* The kcmlen holds the 64-bit version of the control length.
-	 * It may not be modified as we do not stick it into the kmsg
-	 * until we have successfully copied over all of the data
-	 * from the user.
-	 */
-	if (kcmlen > stackbuf_size)
-		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
-	if (kcmsg == NULL)
-		return -ENOBUFS;
-
-	/* Now copy them over neatly. */
-	memset(kcmsg, 0, kcmlen);
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while (ucmsg != NULL) {
-		__get_user(ucmlen, &ucmsg->cmsg_len);
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmsg->cmsg_len = tmp;
-		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
-		/* Copy over the data. */
-		if(copy_from_user(CMSG_DATA(kcmsg),
-				  CMSG32_DATA(ucmsg),
-				  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
-			goto out_free_efault;
-
-		/* Advance. */
-		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-
-	/* Ok, looks like we made it.  Hook it up and return success. */
-	kmsg->msg_control = kcmsg_base;
-	kmsg->msg_controllen = kcmlen;
-	return 0;
-
-out_free_efault:
-	if(kcmsg_base != (struct cmsghdr *)stackbuf)
-		kfree(kcmsg_base);
-	return -EFAULT;
-}
-
-asmlinkage long sys32_sendmsg(int fd, struct msghdr32* user_msg, unsigned int user_flags)
-{
-	struct socket *sock;
-	char address[MAX_SOCK_ADDR];
-	struct iovec iov[UIO_FASTIOV];
-	unsigned char ctl[sizeof(struct cmsghdr) + 20];
-	unsigned char *ctl_buf = ctl;
-	struct msghdr kern_msg;
-	int err, total_len;
-	
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-	err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	if(kern_msg.msg_controllen) {
-		err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
-		if(err)
-			goto out_freeiov;
-		ctl_buf = kern_msg.msg_control;
-	}
-	kern_msg.msg_flags = user_flags;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		if (sock->file->f_flags & O_NONBLOCK)
-			kern_msg.msg_flags |= MSG_DONTWAIT;
-		err = sock_sendmsg(sock, &kern_msg, total_len);
-		sockfd_put(sock);
-	}
-
-	/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
-	if(ctl_buf != ctl)
-		kfree(ctl_buf);
-out_freeiov:
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	return err;
-}
-
-static void put_cmsg32(struct msghdr *kmsg, int level, int type,
-		       int len, void *data)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	struct cmsghdr32 cmhdr;
-	int cmlen = CMSG32_LEN(len);
-
-	if (cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		return;
-	}
-
-	if (kmsg->msg_controllen < cmlen) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		cmlen = kmsg->msg_controllen;
-	}
-	cmhdr.cmsg_level = level;
-	cmhdr.cmsg_type = type;
-	cmhdr.cmsg_len = cmlen;
-
-	if (copy_to_user(cm, &cmhdr, sizeof cmhdr))
-		return;
-	if (copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
-		return;
-	cmlen = CMSG32_SPACE(len);
-	kmsg->msg_control += cmlen;
-	kmsg->msg_controllen -= cmlen;
-}
-
-
-static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
-	int fdnum = scm->fp->count;
-	struct file **fp = scm->fp->fp;
-	int *cmfptr;
-	int err = 0, i;
-
-	if (fdnum < fdmax)
-		fdmax = fdnum;
-
-	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
-		int new_fd;
-		err = get_unused_fd();
-		if (err < 0)
-			break;
-		new_fd = err;
-		err = put_user(new_fd, cmfptr);
-		if (err) {
-			put_unused_fd(new_fd);
-			break;
-		}
-		/* Bump the usage count and install the file. */
-		get_file(fp[i]);
-		fd_install(new_fd, fp[i]);
-	}
-
-	if (i > 0) {
-		int cmlen = CMSG32_LEN(i * sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
-		if (!err)
-			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
-		if (!err)
-			err = put_user(cmlen, &cm->cmsg_len);
-		if (!err) {
-			cmlen = CMSG32_SPACE(i * sizeof(int));
-			kmsg->msg_control += cmlen;
-			kmsg->msg_controllen -= cmlen;
-		}
-	}
-	if (i < fdnum)
-		kmsg->msg_flags |= MSG_CTRUNC;
-
-	/*
-	 * All of the files that fit in the message have had their
-	 * usage counts incremented, so we just free the list.
-	 */
-	__scm_destroy(scm);
-}
-
-/* In these cases we (currently) can just copy to data over verbatim
- * because all CMSGs created by the kernel have well defined types which
- * have the same layout in both the 32-bit and 64-bit API.  One must add
- * some special cased conversions here if we start sending control messages
- * with incompatible types.
- *
- * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
- * we do our work.  The remaining cases are:
- *
- * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
- *		IP_TTL		int			32-bit clean
- *		IP_TOS		__u8			32-bit clean
- *		IP_RECVOPTS	variable length		32-bit clean
- *		IP_RETOPTS	variable length		32-bit clean
- *		(these last two are clean because the types are defined
- *		 by the IPv4 protocol)
- *		IP_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in	32-bit clean
- * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in6	32-bit clean
- *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
- *		IPV6_HOPLIMIT	int			32-bit clean
- *		IPV6_FLOWINFO	u32			32-bit clean
- *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
- *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
- *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
- *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
- */
-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
-{
-	unsigned char *workbuf, *wp;
-	unsigned long bufsz, space_avail;
-	struct cmsghdr *ucmsg;
-
-	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
-	space_avail = kmsg->msg_controllen + bufsz;
-	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
-	if(workbuf == NULL)
-		goto fail;
-
-	/* To make this more sane we assume the kernel sends back properly
-	 * formatted control messages.  Because of how the kernel will truncate
-	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
-	 */
-	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
-	while(((unsigned long)ucmsg) <=
-	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
-		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
-		int clen64, clen32;
-
-		/* UCMSG is the 64-bit format CMSG entry in user-space.
-		 * KCMSG32 is within the kernel space temporary buffer
-		 * we use to convert into a 32-bit style CMSG.
-		 */
-		__get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
-		__get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
-
-		clen64 = kcmsg32->cmsg_len;
-		if (kcmsg32->cmsg_level == SOL_SOCKET &&
-		    kcmsg32->cmsg_type == SO_TIMESTAMP) {
-			struct timeval tv;
-			struct compat_timeval *tv32;
-
-			if (clen64 != CMSG_LEN(sizeof(struct timeval))) {
-				kfree(workbuf);
-				goto fail;
-			}
-			copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv));
-			tv32 = (struct compat_timeval *) CMSG32_DATA(kcmsg32);
-			tv32->tv_sec = tv.tv_sec;
-			tv32->tv_usec = tv.tv_usec;
-			clen32 = sizeof(*tv32) +
-				CMSG32_ALIGN(sizeof(struct cmsghdr32));
-		} else {
-			copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
-				       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
-			clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
-				  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
-		}
-		kcmsg32->cmsg_len = clen32;
-
-		switch (kcmsg32->cmsg_type) {
-			/*
-			 * The timestamp type's data needs to be converted
-			 * from 64-bit time values to 32-bit time values
-			 */
-		case SO_TIMESTAMP: {
-			compat_time_t* ptr_time32 = CMSG32_DATA(kcmsg32);
-			__kernel_time_t*   ptr_time   = CMSG_DATA(ucmsg);
-			*ptr_time32     = *ptr_time;
-			*(ptr_time32+1) = *(ptr_time+1);
-			kcmsg32->cmsg_len -= 2*(sizeof(__kernel_time_t) -
-						sizeof(compat_time_t));
-		}
-		default:;
-		}
-
-		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
-		wp = (((char *)kcmsg32) + CMSG32_ALIGN(kcmsg32->cmsg_len));
-	}
-
-	/* Copy back fixed up data, and adjust pointers. */
-	bufsz = (wp - workbuf);
-	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
-
-	kmsg->msg_control = (struct cmsghdr *)
-		(((char *)orig_cmsg_uptr) + bufsz);
-	kmsg->msg_controllen = space_avail - bufsz;
-
-	kfree(workbuf);
-	return;
-
-fail:
-	/* If we leave the 64-bit format CMSG chunks in there,
-	 * the application could get confused and crash.  So to
-	 * ensure greater recovery, we report no CMSGs.
-	 */
-	kmsg->msg_controllen += bufsz;
-	kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-asmlinkage long sys32_recvmsg(int fd, struct msghdr32* user_msg, unsigned int user_flags)
-{
-	struct iovec iovstack[UIO_FASTIOV];
-	struct msghdr kern_msg;
-	char addr[MAX_SOCK_ADDR];
-	struct socket *sock;
-	struct iovec *iov = iovstack;
-	struct sockaddr *uaddr;
-	int *uaddr_len;
-	unsigned long cmsg_ptr;
-	int err, total_len, len = 0;
-	
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-
-	uaddr = kern_msg.msg_name;
-	uaddr_len = &user_msg->msg_namelen;
-	err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	cmsg_ptr = (unsigned long) kern_msg.msg_control;
-	kern_msg.msg_flags = 0;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		struct sock_iocb *si;
-		struct kiocb iocb;
-
-		if (sock->file->f_flags & O_NONBLOCK)
-			user_flags |= MSG_DONTWAIT;
-
-		init_sync_kiocb(&iocb, NULL);
-		si = kiocb_to_siocb(&iocb);
-		si->sock = sock;
-		si->scm = &si->async_scm;
-		si->msg = &kern_msg;
-		si->size = total_len;
-		si->flags = user_flags;
-		memset(si->scm, 0, sizeof(*si->scm));
-
-		err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len,
-					 user_flags, si->scm);
-		if (-EIOCBQUEUED == err)
-			err = wait_on_sync_kiocb(&iocb);
-
-		if(err >= 0) {
-			len = err;
-			if(!kern_msg.msg_control) {
-				if(sock->passcred || si->scm->fp)
-					kern_msg.msg_flags |= MSG_CTRUNC;
-				if(si->scm->fp)
-					__scm_destroy(si->scm);
-			} else {
-				/* If recvmsg processing itself placed some
-				 * control messages into user space, it's is
-				 * using 64-bit CMSG processing, so we need
-				 * to fix it up before we tack on more stuff.
-				 */
-				if((unsigned long) kern_msg.msg_control != cmsg_ptr)
-					cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
-
-				/* Wheee... */
-				if(sock->passcred)
-					put_cmsg32(&kern_msg,
-						   SOL_SOCKET, SCM_CREDENTIALS,
-						   sizeof(si->scm->creds),
-						   &si->scm->creds);
-				if(si->scm->fp != NULL)
-					scm_detach_fds32(&kern_msg, si->scm);
-			}
-		}
-		sockfd_put(sock);
-	}
-
-  if (uaddr != NULL && err >= 0 && kern_msg.msg_namelen)
-		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
-	if(cmsg_ptr != 0 && err >= 0) {
-		unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
-		compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr);
-		err |= __put_user(uclen, &user_msg->msg_controllen);
-	}
-	if(err >= 0)
-		err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	if(err < 0)
-		return err;
-	
-	return len;
 }
 
 /*
diff -Nru a/arch/ppc64/vmlinux.lds.S b/arch/ppc64/vmlinux.lds.S
--- a/arch/ppc64/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/ppc64/vmlinux.lds.S	Fri Feb 14 15:10:57 2003
@@ -97,6 +97,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
diff -Nru a/arch/s390/Kconfig b/arch/s390/Kconfig
--- a/arch/s390/Kconfig	Mon Feb 24 10:24:34 2003
+++ b/arch/s390/Kconfig	Sat Mar  8 14:50:37 2003
@@ -7,10 +7,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 	default y
diff -Nru a/arch/s390/vmlinux.lds.S b/arch/s390/vmlinux.lds.S
--- a/arch/s390/vmlinux.lds.S	Mon Feb 24 10:24:21 2003
+++ b/arch/s390/vmlinux.lds.S	Mon Mar  3 11:37:38 2003
@@ -78,6 +78,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(256);
   __initramfs_start = .;
   .init.ramfs : { *(.init.initramfs) }
diff -Nru a/arch/s390x/Kconfig b/arch/s390x/Kconfig
--- a/arch/s390x/Kconfig	Mon Feb 24 10:24:34 2003
+++ b/arch/s390x/Kconfig	Sat Mar  8 14:50:37 2003
@@ -7,10 +7,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config RWSEM_GENERIC_SPINLOCK
 	bool
 
diff -Nru a/arch/s390x/kernel/entry.S b/arch/s390x/kernel/entry.S
--- a/arch/s390x/kernel/entry.S	Mon Feb 24 10:25:00 2003
+++ b/arch/s390x/kernel/entry.S	Thu Mar  6 11:06:44 2003
@@ -499,7 +499,7 @@
         .long  SYSCALL(sys_statfs,compat_sys_statfs_wrapper)
         .long  SYSCALL(sys_fstatfs,compat_sys_fstatfs_wrapper)   /* 100 */
         .long  SYSCALL(sys_ni_syscall,sys_ni_syscall)
-        .long  SYSCALL(sys_socketcall,sys32_socketcall_wrapper)
+        .long  SYSCALL(sys_socketcall,compat_sys_socketcall_wrapper)
         .long  SYSCALL(sys_syslog,sys32_syslog_wrapper)
         .long  SYSCALL(sys_setitimer,compat_sys_setitimer_wrapper)
         .long  SYSCALL(sys_getitimer,compat_sys_getitimer_wrapper)   /* 105 */
diff -Nru a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c
--- a/arch/s390x/kernel/linux32.c	Mon Feb 24 10:25:00 2003
+++ b/arch/s390x/kernel/linux32.c	Thu Mar  6 11:06:44 2003
@@ -904,13 +904,11 @@
 		return sys_ftruncate(fd, (high << 32) | low);
 }
 
-struct iovec32 { u32 iov_base; compat_size_t iov_len; };
-
 typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
 typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
 
 static long do_readv_writev32(int type, struct file *file,
-			      const struct iovec32 *vector, u32 count)
+			      const struct compat_iovec *vector, u32 count)
 {
 	unsigned long tot_len;
 	struct iovec iovstack[UIO_FASTIOV];
@@ -925,7 +923,7 @@
 	 */
 	if (!count)
 		return 0;
-	if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+	if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count))
 		return -EFAULT;
 	if (count > UIO_MAXIOV)
 		return -EINVAL;
@@ -996,7 +994,7 @@
 	return retval;
 }
 
-asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
+asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	long ret = -EBADF;
@@ -1014,7 +1012,7 @@
 	return ret;
 }
 
-asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
+asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	int ret = -EBADF;
@@ -1867,740 +1865,6 @@
 	return ret;
 }
 
-/* XXX This really belongs in some header file... -DaveM */
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
-					   16 for IP, 16 for IPX,
-					   24 for IPv6,
-					   about 80 for AX.25 */
-
-struct msghdr32 {
-        u32               msg_name;
-        int               msg_namelen;
-        u32               msg_iov;
-        compat_size_t msg_iovlen;
-        u32               msg_control;
-        compat_size_t msg_controllen;
-        unsigned          msg_flags;
-};
-
-struct cmsghdr32 {
-        compat_size_t cmsg_len;
-        int               cmsg_level;
-        int               cmsg_type;
-};
-
-/* Bleech... */
-#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
-#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
-
-#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
-
-#define CMSG32_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
-#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
-#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
-
-#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
-				    (struct cmsghdr32 *)(ctl) : \
-				    (struct cmsghdr32 *)NULL)
-#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-
-__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
-					      struct cmsghdr32 *__cmsg, int __cmsg_len)
-{
-	struct cmsghdr32 * __ptr;
-
-	__ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
-				     CMSG32_ALIGN(__cmsg_len));
-	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
-		return NULL;
-
-	return __ptr;
-}
-
-__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
-					    struct cmsghdr32 *__cmsg,
-					    int __cmsg_len)
-{
-	return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
-			       __cmsg, __cmsg_len);
-}
-
-static inline int iov_from_user32_to_kern(struct iovec *kiov,
-					  struct iovec32 *uiov32,
-					  int niov)
-{
-	int tot_len = 0;
-
-	while(niov > 0) {
-		u32 len, buf;
-
-		if(get_user(len, &uiov32->iov_len) ||
-		   get_user(buf, &uiov32->iov_base)) {
-			tot_len = -EFAULT;
-			break;
-		}
-		tot_len += len;
-		kiov->iov_base = (void *)A(buf);
-		kiov->iov_len = (__kernel_size_t) len;
-		uiov32++;
-		kiov++;
-		niov--;
-	}
-	return tot_len;
-}
-
-static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
-					     struct msghdr32 *umsg)
-{
-	u32 tmp1, tmp2, tmp3;
-	int err;
-
-	err = get_user(tmp1, &umsg->msg_name);
-	err |= __get_user(tmp2, &umsg->msg_iov);
-	err |= __get_user(tmp3, &umsg->msg_control);
-	if (err)
-		return -EFAULT;
-
-	kmsg->msg_name = (void *)A(tmp1);
-	kmsg->msg_iov = (struct iovec *)A(tmp2);
-	kmsg->msg_control = (void *)A(tmp3);
-
-	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
-	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
-	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
-	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
-	
-	return err;
-}
-
-/* I've named the args so it is easy to tell whose space the pointers are in. */
-static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
-			  char *kern_address, int mode)
-{
-	int tot_len;
-
-	if(kern_msg->msg_namelen) {
-		if(mode==VERIFY_READ) {
-			int err = move_addr_to_kernel(kern_msg->msg_name,
-						      kern_msg->msg_namelen,
-						      kern_address);
-			if(err < 0)
-				return err;
-		}
-		kern_msg->msg_name = kern_address;
-	} else
-		kern_msg->msg_name = NULL;
-
-	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
-		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
-				   GFP_KERNEL);
-		if(!kern_iov)
-			return -ENOMEM;
-	}
-
-	tot_len = iov_from_user32_to_kern(kern_iov,
-					  (struct iovec32 *)kern_msg->msg_iov,
-					  kern_msg->msg_iovlen);
-	if(tot_len >= 0)
-		kern_msg->msg_iov = kern_iov;
-	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
-		kfree(kern_iov);
-
-	return tot_len;
-}
-
-/* There is a lot of hair here because the alignment rules (and
- * thus placement) of cmsg headers and length are different for
- * 32-bit apps.  -DaveM
- */
-static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
-				       unsigned char *stackbuf, int stackbuf_size)
-{
-	struct cmsghdr32 *ucmsg;
-	struct cmsghdr *kcmsg, *kcmsg_base;
-	compat_size_t ucmlen;
-	__kernel_size_t kcmlen, tmp;
-
-	kcmlen = 0;
-	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		if(get_user(ucmlen, &ucmsg->cmsg_len))
-			return -EFAULT;
-
-		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
-			return -EINVAL;
-
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmlen += tmp;
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-	if(kcmlen == 0)
-		return -EINVAL;
-
-	/* The kcmlen holds the 64-bit version of the control length.
-	 * It may not be modified as we do not stick it into the kmsg
-	 * until we have successfully copied over all of the data
-	 * from the user.
-	 */
-	if(kcmlen > stackbuf_size)
-		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
-	if(kcmsg == NULL)
-		return -ENOBUFS;
-
-	/* Now copy them over neatly. */
-	memset(kcmsg, 0, kcmlen);
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		__get_user(ucmlen, &ucmsg->cmsg_len);
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmsg->cmsg_len = tmp;
-		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
-		/* Copy over the data. */
-		if(copy_from_user(CMSG_DATA(kcmsg),
-				  CMSG32_DATA(ucmsg),
-				  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
-			goto out_free_efault;
-
-		/* Advance. */
-		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-
-	/* Ok, looks like we made it.  Hook it up and return success. */
-	kmsg->msg_control = kcmsg_base;
-	kmsg->msg_controllen = kcmlen;
-	return 0;
-
-out_free_efault:
-	if(kcmsg_base != (struct cmsghdr *)stackbuf)
-		kfree(kcmsg_base);
-	return -EFAULT;
-}
-
-static void put_cmsg32(struct msghdr *kmsg, int level, int type,
-		       int len, void *data)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	struct cmsghdr32 cmhdr;
-	int cmlen = CMSG32_LEN(len);
-
-	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		return;
-	}
-
-	if(kmsg->msg_controllen < cmlen) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		cmlen = kmsg->msg_controllen;
-	}
-	cmhdr.cmsg_level = level;
-	cmhdr.cmsg_type = type;
-	cmhdr.cmsg_len = cmlen;
-
-	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
-		return;
-	if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
-		return;
-	cmlen = CMSG32_SPACE(len);
-	kmsg->msg_control += cmlen;
-	kmsg->msg_controllen -= cmlen;
-}
-
-static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
-	int fdnum = scm->fp->count;
-	struct file **fp = scm->fp->fp;
-	int *cmfptr;
-	int err = 0, i;
-
-	if (fdnum < fdmax)
-		fdmax = fdnum;
-
-	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
-		int new_fd;
-		err = get_unused_fd();
-		if (err < 0)
-			break;
-		new_fd = err;
-		err = put_user(new_fd, cmfptr);
-		if (err) {
-			put_unused_fd(new_fd);
-			break;
-		}
-		/* Bump the usage count and install the file. */
-		get_file(fp[i]);
-		fd_install(new_fd, fp[i]);
-	}
-
-	if (i > 0) {
-		int cmlen = CMSG32_LEN(i * sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
-		if (!err)
-			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
-		if (!err)
-			err = put_user(cmlen, &cm->cmsg_len);
-		if (!err) {
-			cmlen = CMSG32_SPACE(i * sizeof(int));
-			kmsg->msg_control += cmlen;
-			kmsg->msg_controllen -= cmlen;
-		}
-	}
-	if (i < fdnum)
-		kmsg->msg_flags |= MSG_CTRUNC;
-
-	/*
-	 * All of the files that fit in the message have had their
-	 * usage counts incremented, so we just free the list.
-	 */
-	__scm_destroy(scm);
-}
-
-/* In these cases we (currently) can just copy to data over verbatim
- * because all CMSGs created by the kernel have well defined types which
- * have the same layout in both the 32-bit and 64-bit API.  One must add
- * some special cased conversions here if we start sending control messages
- * with incompatible types.
- *
- * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
- * we do our work.  The remaining cases are:
- *
- * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
- *		IP_TTL		int			32-bit clean
- *		IP_TOS		__u8			32-bit clean
- *		IP_RECVOPTS	variable length		32-bit clean
- *		IP_RETOPTS	variable length		32-bit clean
- *		(these last two are clean because the types are defined
- *		 by the IPv4 protocol)
- *		IP_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in	32-bit clean
- * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in6	32-bit clean
- *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
- *		IPV6_HOPLIMIT	int			32-bit clean
- *		IPV6_FLOWINFO	u32			32-bit clean
- *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
- *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
- *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
- *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
- */
-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
-{
-	unsigned char *workbuf, *wp;
-	unsigned long bufsz, space_avail;
-	struct cmsghdr *ucmsg;
-
-	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
-	space_avail = kmsg->msg_controllen + bufsz;
-	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
-	if(workbuf == NULL)
-		goto fail;
-
-	/* To make this more sane we assume the kernel sends back properly
-	 * formatted control messages.  Because of how the kernel will truncate
-	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
-	 */
-	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
-	while(((unsigned long)ucmsg) <=
-	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
-		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
-		int clen64, clen32;
-
-		/* UCMSG is the 64-bit format CMSG entry in user-space.
-		 * KCMSG32 is within the kernel space temporary buffer
-		 * we use to convert into a 32-bit style CMSG.
-		 */
-		__get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
-		__get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
-
-		clen64 = kcmsg32->cmsg_len;
-		copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
-			       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
-		clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
-			  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
-		kcmsg32->cmsg_len = clen32;
-
-		switch (kcmsg32->cmsg_type) {
-			/*
-			 * The timestamp type's data needs to be converted
-			 * from 64-bit time values to 32-bit time values
-			*/
-		case SO_TIMESTAMP: {
-			compat_time_t* ptr_time32 = CMSG32_DATA(kcmsg32);
-			__kernel_time_t*   ptr_time   = CMSG_DATA(ucmsg);
-			get_user(*ptr_time32, ptr_time);
-			get_user(*(ptr_time32+1), ptr_time+1);
-			kcmsg32->cmsg_len -= 2*(sizeof(__kernel_time_t) -
-						sizeof(compat_time_t));
-		}
-		default:;
-		}
-		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
-		wp = (((char *)kcmsg32) + CMSG32_ALIGN(kcmsg32->cmsg_len));
-	}
-
-	/* Copy back fixed up data, and adjust pointers. */
-	bufsz = (wp - workbuf);
-	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
-
-	kmsg->msg_control = (struct cmsghdr *)
-		(((char *)orig_cmsg_uptr) + bufsz);
-	kmsg->msg_controllen = space_avail - bufsz;
-
-	kfree(workbuf);
-	return;
-
-fail:
-	/* If we leave the 64-bit format CMSG chunks in there,
-	 * the application could get confused and crash.  So to
-	 * ensure greater recovery, we report no CMSGs.
-	 */
-	kmsg->msg_controllen += bufsz;
-	kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-/*
- *	BSD sendmsg interface
- */
-
-int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags)
-{
-	struct socket *sock;
-	char address[MAX_SOCK_ADDR];
-	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
-	unsigned char ctl[sizeof(struct cmsghdr) + 20];	/* 20 is size of ipv6_pktinfo */
-	unsigned char *ctl_buf = ctl;
-	struct msghdr msg_sys;
-	int err, ctl_len, iov_size, total_len;
-	
-	err = -EFAULT;
-	if (msghdr_from_user32_to_kern(&msg_sys, msg))
-		goto out; 
-
-	sock = sockfd_lookup(fd, &err);
-	if (!sock) 
-		goto out;
-
-	/* do not move before msg_sys is valid */
-	err = -EINVAL;
-	if (msg_sys.msg_iovlen > UIO_MAXIOV)
-		goto out_put;
-
-	/* Check whether to allocate the iovec area*/
-	err = -ENOMEM;
-	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32);
-	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
-		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
-		if (!iov)
-			goto out_put;
-	}
-
-	/* This will also move the address data into kernel space */
-	err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ);
-	if (err < 0) 
-		goto out_freeiov;
-	total_len = err;
-
-	err = -ENOBUFS;
-
-	if (msg_sys.msg_controllen > INT_MAX)
-		goto out_freeiov;
-	ctl_len = msg_sys.msg_controllen; 
-	if (ctl_len) 
-	{
-		if (ctl_len > sizeof(ctl))
-		{
-			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
-			if (ctl_buf == NULL) 
-				goto out_freeiov;
-		}
-		else if (ctl_len < sizeof(struct cmsghdr))
-		{
-			/* to get same error message as on 31 bit native */
-			err = EOPNOTSUPP;
-			goto out_freeiov;
-		}
-		err = -EFAULT;
-		if (cmsghdr_from_user32_to_kern(&msg_sys, ctl_buf, ctl_len))
-			goto out_freectl;
-//		msg_sys.msg_control = ctl_buf;
-	}
-	msg_sys.msg_flags = flags;
-
-	if (sock->file->f_flags & O_NONBLOCK)
-		msg_sys.msg_flags |= MSG_DONTWAIT;
-	err = sock_sendmsg(sock, &msg_sys, total_len);
-
-out_freectl:
-	if (ctl_buf != ctl)    
-		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
-out_freeiov:
-	if (iov != iovstack)
-		sock_kfree_s(sock->sk, iov, iov_size);
-out_put:
-	sockfd_put(sock);
-out:       
-	return err;
-}
-
-static __inline__ void
-scm_recv32(struct socket *sock, struct msghdr *msg,
-		struct scm_cookie *scm, int flags, unsigned long cmsg_ptr)
-{
-	if(!msg->msg_control)
-	{
-		if(sock->passcred || scm->fp)
-			msg->msg_flags |= MSG_CTRUNC;
-		scm_destroy(scm);
-		return;
-	}
-	/* If recvmsg processing itself placed some
-	 * control messages into user space, it's is
-	 * using 64-bit CMSG processing, so we need
-	 * to fix it up before we tack on more stuff.
-	 */
-	if((unsigned long) msg->msg_control != cmsg_ptr)
-		cmsg32_recvmsg_fixup(msg, cmsg_ptr);
-	/* Wheee... */
-	if(sock->passcred)
-		put_cmsg32(msg,
-			SOL_SOCKET, SCM_CREDENTIALS,
-			sizeof(scm->creds), &scm->creds);
-	if(!scm->fp)
-		return;
-
-	scm_detach_fds32(msg, scm);
-}
-
-static int  
-sock_recvmsg32(struct socket *sock, struct msghdr *msg, int size, int flags,
-               unsigned long cmsg_ptr)
-{
-	struct sock_iocb *si;
-	struct kiocb iocb;
-
-	init_sync_kiocb(&iocb, NULL);
-
-	si = kiocb_to_siocb(&iocb);
-	si->sock = sock;
-	si->scm = &si->async_scm;
-	si->msg = msg;
-	si->size = size;
-	si->flags = flags;
-
-	memset(si->scm, 0, sizeof(*si->scm));
-
-	size = sock->ops->recvmsg(&iocb, sock, msg, size, flags, si->scm);
-	if (size >= 0)
-		scm_recv32(sock, msg, si->scm, flags, cmsg_ptr);
-
-	if (-EIOCBQUEUED == size)
-		size = wait_on_sync_kiocb(&iocb);
-
-	return size;
-}
-
-/*
- *	BSD recvmsg interface
- */
-
-int
-sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags)
-{
-	struct socket *sock;
-	struct iovec iovstack[UIO_FASTIOV];
-	struct iovec *iov=iovstack;
-	struct msghdr msg_sys;
-	unsigned long cmsg_ptr;
-	int err, iov_size, total_len, len;
-
-	/* kernel mode address */
-	char addr[MAX_SOCK_ADDR];
-
-	/* user mode address pointers */
-	struct sockaddr *uaddr;
-	int *uaddr_len;
-	
-	err=-EFAULT;
-	if (msghdr_from_user32_to_kern(&msg_sys, msg))
-		goto out;
-
-	sock = sockfd_lookup(fd, &err);
-	if (!sock)
-		goto out;
-
-	err = -EINVAL;
-	if (msg_sys.msg_iovlen > UIO_MAXIOV)
-		goto out_put;
-	
-	/* Check whether to allocate the iovec area*/
-	err = -ENOMEM;
-	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
-	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
-		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
-		if (!iov)
-			goto out_put;
-	}
-
-	/*
-	 *	Save the user-mode address (verify_iovec will change the
-	 *	kernel msghdr to use the kernel address space)
-	 */
-	 
-	uaddr = msg_sys.msg_name;
-	uaddr_len = &msg->msg_namelen;
-	err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE);
-	if (err < 0)
-		goto out_freeiov;
-	total_len=err;
-
-	cmsg_ptr = (unsigned long)msg_sys.msg_control;
-	msg_sys.msg_flags = 0;
-	
-	if (sock->file->f_flags & O_NONBLOCK)
-		flags |= MSG_DONTWAIT;
-	err = sock_recvmsg32(sock, &msg_sys, total_len, flags, cmsg_ptr);
-	if (err < 0)
-		goto out_freeiov;
-	len = err;
-
-	if (uaddr != NULL && 
-	/* in order to get same error message as on native 31 bit */
-		msg_sys.msg_namelen > 0) {
-		err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
-		if (err < 0)
-			goto out_freeiov;
-	}
-	err = __put_user(msg_sys.msg_flags, &msg->msg_flags);
-	if (err)
-		goto out_freeiov;
-	err = __put_user((compat_size_t) ((unsigned long)msg_sys.msg_control - cmsg_ptr), &msg->msg_controllen);
-	if (err)
-		goto out_freeiov;
-	err = len;
-
-out_freeiov:
-	if (iov != iovstack)
-		sock_kfree_s(sock->sk, iov, iov_size);
-out_put:
-	sockfd_put(sock);
-out:
-	return err;
-}
-
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
-static int do_set_attach_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct sock_fprog32 {
-		__u16 len;
-		__u32 filter;
-	} *fprog32 = (struct sock_fprog32 *)optval;
-	struct sock_fprog kfprog;
-	struct sock_filter *kfilter;
-	unsigned int fsize;
-	mm_segment_t old_fs;
-	__u32 uptr;
-	int ret;
-
-	if (get_user(kfprog.len, &fprog32->len) ||
-	    __get_user(uptr, &fprog32->filter))
-		return -EFAULT;
-
-	kfprog.filter = (struct sock_filter *)A(uptr);
-	fsize = kfprog.len * sizeof(struct sock_filter);
-
-	kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
-	if (kfilter == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(kfilter, kfprog.filter, fsize)) {
-		kfree(kfilter);
-		return -EFAULT;
-	}
-
-	kfprog.filter = kfilter;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *)&kfprog, sizeof(kfprog));
-	set_fs(old_fs);
-
-	kfree(kfilter);
-
-	return ret;
-}
-
-static int do_set_icmpv6_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct icmp6_filter kfilter;
-	mm_segment_t old_fs;
-	int ret, i;
-
-	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
-		return -EFAULT;
-
-
-	for (i = 0; i < 8; i += 2) {
-		u32 tmp = kfilter.data[i];
-
-		kfilter.data[i] = kfilter.data[i + 1];
-		kfilter.data[i + 1] = tmp;
-	}
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *) &kfilter, sizeof(kfilter));
-	set_fs(old_fs);
-
-	return ret;
-}
-
-asmlinkage int sys32_setsockopt(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	if (optname == SO_ATTACH_FILTER)
-		return do_set_attach_filter(fd, level, optname,
-					    optval, optlen);
-	if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER)
-		return do_set_icmpv6_filter(fd, level, optname,
-					    optval, optlen);
-	if (level == SOL_SOCKET && 
-	    (optname == SO_SNDTIMEO || optname == SO_RCVTIMEO)) {
-		long ret;
-		struct timeval tmp;
-		mm_segment_t old_fs;
-
-		if (get_tv32(&tmp, (struct compat_timeval *)optval ))
-			return -EFAULT;
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		ret = sys_setsockopt(fd, level, optname, (char *) &tmp, sizeof(struct timeval));
-		set_fs(old_fs);
-		return ret; 
-	}
-
-	return sys_setsockopt(fd, level, optname, optval, optlen);
-}
-
 extern void check_pending(int signum);
 
 /*
@@ -3663,104 +2927,6 @@
 	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
 out:
 	return error;
-}
-
-extern asmlinkage long sys_socket(int family, int type, int protocol);
-extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
-extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
-extern asmlinkage long sys_listen(int fd, int backlog);
-extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen);
-extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len);
-extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len);
-extern asmlinkage long sys_socketpair(int family, int type, int protocol, int usockvec[2]);
-extern asmlinkage long sys_send(int fd, void * buff, size_t len, unsigned flags);
-extern asmlinkage long sys_sendto(int fd, void * buff, size_t len, unsigned flags,
-                           struct sockaddr *addr, int addr_len);
-extern asmlinkage long sys_recv(int fd, void * ubuf, size_t size, unsigned flags);
-extern asmlinkage long sys_recvfrom(int fd, void * ubuf, size_t size, unsigned flags,
-                             struct sockaddr *addr, int *addr_len);
-extern asmlinkage long sys_shutdown(int fd, int how);
-extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char *optval, int * optlen);
-
-/* Argument list sizes for sys_socketcall */
-#define AL(x) ((x) * sizeof(u32))
-static unsigned char nas[18] = {AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
-                                AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
-                                AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
-#undef AL
-
-asmlinkage long sys32_socketcall(int call, u32 *args)
-{
-	int ret;
-	u32 a[6];
-				 
-	if (call < SYS_SOCKET || call > SYS_RECVMSG)
-		return -EINVAL;
-	if (copy_from_user(a, args, nas[call]))
-		return -EFAULT;
-	switch(call) {
-	case SYS_SOCKET:
-		ret = sys_socket(a[0], a[1], a[2]);
-		break;
-	case SYS_BIND:
-		ret = sys_bind(a[0], (struct sockaddr *) A(a[1]), a[2]);
-		break;
-	case SYS_CONNECT:
-		ret = sys_connect(a[0], (struct sockaddr *) A(a[1]), a[2]);
-		break;
-	case SYS_LISTEN:
-		ret = sys_listen(a[0], a[1]);
-		break;
-	case SYS_ACCEPT:
-		ret = sys_accept(a[0], (struct sockaddr *) A(a[1]),
-				 (int *) A(a[2]));
-		break;
-	case SYS_GETSOCKNAME:
-		ret = sys_getsockname(a[0], (struct sockaddr *) A(a[1]),
-				      (int *) A(a[2]));
-		break;
-	case SYS_GETPEERNAME:
-		ret = sys_getpeername(a[0], (struct sockaddr *) A(a[1]),
-				      (int *) A(a[2]));
-		break;
-	case SYS_SOCKETPAIR:
-		ret = sys_socketpair(a[0], a[1], a[2], (int *) A(a[3]));
-		break;
-	case SYS_SEND:
-		ret = sys_send(a[0], (void *) A(a[1]), a[2], a[3]);
-		break;
-	case SYS_SENDTO:
-		ret = sys_sendto(a[0], (void*) A(a[1]), a[2], a[3], (struct sockaddr *) A(a[4]), a[5]);
-		break;
-	case SYS_RECV:
-		ret = sys_recv(a[0], (void *) A(a[1]), a[2], a[3]);
-		break;
-	case SYS_RECVFROM:
-		ret = sys_recvfrom(a[0], (void *) A(a[1]), a[2], a[3], (struct sockaddr *) A(a[4]), (int *) A(a[5]) );
-		break;
-	case SYS_SHUTDOWN:
-		ret = sys_shutdown(a[0], a[1]);
-		break;
-	case SYS_SETSOCKOPT:
-		ret = sys32_setsockopt(a[0], a[1], a[2], (char *) A(a[3]),
-				     a[4]);
-		break;
-	case SYS_GETSOCKOPT:
-		ret = sys_getsockopt(a[0], a[1], a[2], (char *) A(a[3]), (int *) A(a[4]) );
-		break;
-	case SYS_SENDMSG:
-		ret = sys32_sendmsg(a[0], (struct msghdr32 *) A(a[1]),
-				    a[2]);
-		break;
-	case SYS_RECVMSG:
-		ret = sys32_recvmsg(a[0], (struct msghdr32 *) A(a[1]),
-				    a[2]);
-		break;
-	default:
-		ret = EINVAL;
-		break;
-	}
-	return ret;
 }
 
 extern asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len,
diff -Nru a/arch/s390x/kernel/wrapper32.S b/arch/s390x/kernel/wrapper32.S
--- a/arch/s390x/kernel/wrapper32.S	Mon Feb 24 10:25:00 2003
+++ b/arch/s390x/kernel/wrapper32.S	Thu Mar  6 11:06:44 2003
@@ -452,11 +452,11 @@
 	llgtr	%r3,%r3			# struct compat_statfs *
 	jg	compat_sys_fstatfs	# branch to system call
 
-	.globl  sys32_socketcall_wrapper 
-sys32_socketcall_wrapper:
+	.globl  compat_sys_socketcall_wrapper 
+compat_sys_socketcall_wrapper:
 	lgfr	%r2,%r2			# int
 	llgtr	%r3,%r3			# u32 *
-	jg	sys32_socketcall	# branch to system call
+	jg	compat_sys_socketcall	# branch to system call
 
 	.globl  sys32_syslog_wrapper 
 sys32_syslog_wrapper:
diff -Nru a/arch/s390x/vmlinux.lds.S b/arch/s390x/vmlinux.lds.S
--- a/arch/s390x/vmlinux.lds.S	Mon Feb 24 10:24:21 2003
+++ b/arch/s390x/vmlinux.lds.S	Mon Mar  3 11:44:26 2003
@@ -78,6 +78,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(256);
   __initramfs_start = .;
   .init.ramfs : { *(.init.initramfs) }
diff -Nru a/arch/sh/Kconfig b/arch/sh/Kconfig
--- a/arch/sh/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/arch/sh/Kconfig	Sat Mar  8 14:50:37 2003
@@ -18,10 +18,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 	default y
diff -Nru a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
--- a/arch/sh/kernel/irq.c	Tue Feb 25 01:38:48 2003
+++ b/arch/sh/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -90,6 +90,7 @@
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (j=0; j<smp_num_cpus; j++)
@@ -97,9 +98,10 @@
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < ACTUAL_NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
-		if (!action) 
-			continue;
+		if (!action)
+			goto unlock;
 		seq_printf(p, "%3d: ",i);
 		seq_printf(p, "%10u ", kstat_irqs(i));
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
@@ -108,6 +110,8 @@
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	return 0;
 }
diff -Nru a/arch/sh/vmlinux.lds.S b/arch/sh/vmlinux.lds.S
--- a/arch/sh/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/sh/vmlinux.lds.S	Fri Feb 14 15:11:24 2003
@@ -68,6 +68,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   __machvec_start = .;
   .machvec.init : { *(.machvec.init) }
   __machvec_end = .;
diff -Nru a/arch/sparc/Kconfig b/arch/sparc/Kconfig
--- a/arch/sparc/Kconfig	Mon Mar  3 00:33:45 2003
+++ b/arch/sparc/Kconfig	Sat Mar  8 14:50:37 2003
@@ -9,10 +9,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 	default y
diff -Nru a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
--- a/arch/sparc/kernel/irq.c	Sun Dec  8 14:33:46 2002
+++ b/arch/sparc/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -104,6 +104,7 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 #ifdef CONFIG_SMP
 	int j;
 #endif
@@ -114,9 +115,10 @@
 		return show_sun4d_interrupts(p, v);
 	}
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		local_irq_save(flags);
 	        action = *(i + irq_action);
 		if (!action) 
-		        continue;
+		        goto skip;
 		seq_printf(p, "%3d: ", i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -136,6 +138,8 @@
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -Nru a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
--- a/arch/sparc/kernel/sys_sunos.c	Fri Feb  7 07:59:17 2003
+++ b/arch/sparc/kernel/sys_sunos.c	Sat Mar  8 11:39:01 2003
@@ -1107,38 +1107,16 @@
 	return ret;
 }
 
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
-asmlinkage int sunos_socket(int family, int type, int protocol)
-{
-	int ret, one = 1;
-
-	ret = sys_socket(family, type, protocol);
-	if (ret < 0)
-		goto out;
-
-	sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
-		       (char *)&one, sizeof(one));
-out:
-	return ret;
-}
-
 asmlinkage int sunos_accept(int fd, struct sockaddr *sa, int *addrlen)
 {
-	int ret, one = 1;
+	int ret;
 
 	while (1) {
 		ret = check_nonblock(sys_accept(fd,sa,addrlen),fd);	
 		if (ret != -ENETUNREACH && ret != -EHOSTUNREACH)
 			break;
 	}
-	if (ret < 0)
-		goto out;
 
-	sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
-		       (char *)&one, sizeof(one));
-out:
 	return ret;
 }
 
diff -Nru a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
--- a/arch/sparc/kernel/systbls.S	Sun Dec  8 12:19:41 2002
+++ b/arch/sparc/kernel/systbls.S	Sat Mar  8 11:39:01 2003
@@ -110,7 +110,7 @@
 	.long sys_getitimer, sys_gethostname, sys_sethostname
 	.long sunos_getdtablesize, sys_dup2, sunos_nop
 	.long sys_fcntl, sunos_select, sunos_nop
-	.long sys_fsync, sys_setpriority, sunos_socket
+	.long sys_fsync, sys_setpriority, sys_socket
 	.long sys_connect, sunos_accept
 /*100*/	.long sys_getpriority, sunos_send, sunos_recv
 	.long sunos_nosys, sys_bind, sunos_setsockopt
diff -Nru a/arch/sparc/vmlinux.lds.S b/arch/sparc/vmlinux.lds.S
--- a/arch/sparc/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/sparc/vmlinux.lds.S	Fri Feb 14 15:11:32 2003
@@ -55,6 +55,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
--- a/arch/sparc64/Kconfig	Mon Mar  3 00:34:40 2003
+++ b/arch/sparc64/Kconfig	Sat Mar  8 14:50:37 2003
@@ -9,10 +9,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 source "init/Kconfig"
 
 
@@ -151,9 +147,14 @@
 	  If in doubt, say N.
 
 config CPU_FREQ_TABLE
-       tristate
+       tristate "CPU frequency table helpers"
+       depends on CPU_FREQ
        default y
+       help
+         Many CPUFreq drivers use these helpers, so only say N here if
+	 the CPUFreq driver of your choice doesn't need these helpers.
 
+	 If in doubt, say Y.
 
 config US3_FREQ
 	tristate "UltraSPARC-III CPU Frequency driver"
diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig
--- a/arch/sparc64/defconfig	Sun Mar  2 23:23:54 2003
+++ b/arch/sparc64/defconfig	Fri Mar  7 19:26:39 2003
@@ -39,9 +39,11 @@
 # CONFIG_PREEMPT is not set
 CONFIG_NR_CPUS=4
 CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_PROC_INTF=y
 CONFIG_CPU_FREQ_TABLE=y
 CONFIG_US3_FREQ=m
+CONFIG_CPU_FREQ_PROC_INTF=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+# CONFIG_CPU_FREQ_24_API is not set
 CONFIG_SPARC64=y
 CONFIG_HOTPLUG=y
 CONFIG_HAVE_DEC_LOCK=y
@@ -354,6 +356,8 @@
 CONFIG_XFRM_USER=m
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -872,6 +876,7 @@
 CONFIG_USB_HIDDEV=y
 # CONFIG_USB_AIPTEK is not set
 CONFIG_USB_WACOM=m
+CONFIG_USB_KBTAB=m
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_XPAD is not set
 
@@ -928,6 +933,7 @@
 # CONFIG_USB_SERIAL_EDGEPORT_TI is not set
 CONFIG_USB_SERIAL_KEYSPAN_PDA=m
 CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
@@ -938,6 +944,7 @@
 # CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
 CONFIG_USB_SERIAL_KLSI=m
 # CONFIG_USB_SERIAL_KOBIL_SCT is not set
 CONFIG_USB_SERIAL_MCT_U232=m
diff -Nru a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
--- a/arch/sparc64/kernel/ioctl32.c	Tue Feb 25 10:47:17 2003
+++ b/arch/sparc64/kernel/ioctl32.c	Fri Mar  7 23:00:48 2003
@@ -38,6 +38,7 @@
 #include <linux/cdrom.h>
 #include <linux/loop.h>
 #include <linux/auto_fs.h>
+#include <linux/auto_fs4.h>
 #include <linux/devfs_fs.h>
 #include <linux/tty.h>
 #include <linux/vt_kern.h>
@@ -4850,6 +4851,7 @@
 COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC)
 COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER)
 COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE)
+COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI)
 /* DEVFS */
 COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV)
 COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK)
diff -Nru a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
--- a/arch/sparc64/kernel/pci_common.c	Tue Feb 25 10:47:17 2003
+++ b/arch/sparc64/kernel/pci_common.c	Fri Mar  7 19:08:16 2003
@@ -78,20 +78,6 @@
 	return 0;
 }
 
-/* Remove a PCI device from the device trees, then
- * free it up.  Note that this must run before
- * the device's resources are registered because we
- * do not handle unregistering them here.
- */
-static void pci_device_delete(struct pci_dev *pdev)
-{
-	list_del(&pdev->global_list);
-	list_del(&pdev->bus_list);
-
-	/* Ok, all references are gone, free it up. */
-	kfree(pdev);
-}
-
 /* Older versions of OBP on PCI systems encode 64-bit MEM
  * space assignments incorrectly, this fixes them up.  We also
  * take the opportunity here to hide other kinds of bogus
@@ -164,7 +150,7 @@
 		 * second EBUS/HappyMeal pair if the external
 		 * connector for it is not present.
 		 */
-		pci_device_delete(pdev);
+		pci_remove_bus_device(pdev);
 		return;
 	}
 
diff -Nru a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
--- a/arch/sparc64/kernel/smp.c	Sat Feb 22 00:03:07 2003
+++ b/arch/sparc64/kernel/smp.c	Sat Mar  8 07:52:56 2003
@@ -1137,16 +1137,16 @@
 	do {
 		sparc64_do_profile(regs);
 		if (!--prof_counter(cpu)) {
-			if (cpu == boot_cpu_id) {
-				irq_enter();
+			irq_enter();
 
+			if (cpu == boot_cpu_id) {
 				kstat_cpu(cpu).irqs[0]++;
 				timer_tick_interrupt(regs);
-
-				irq_exit();
 			}
 
 			update_process_times(user);
+
+			irq_exit();
 
 			prof_counter(cpu) = prof_multiplier(cpu);
 		}
diff -Nru a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
--- a/arch/sparc64/kernel/sparc64_ksyms.c	Thu Feb 27 05:46:56 2003
+++ b/arch/sparc64/kernel/sparc64_ksyms.c	Thu Mar  6 12:08:45 2003
@@ -20,6 +20,7 @@
 #include <linux/interrupt.h>
 #include <linux/fs_struct.h>
 #include <linux/mm.h>
+#include <linux/socket.h>
 
 #include <asm/oplib.h>
 #include <asm/delay.h>
@@ -243,6 +244,7 @@
 
 /* Solaris/SunOS binary compatibility */
 EXPORT_SYMBOL(_sigpause_common);
+EXPORT_SYMBOL(verify_compat_iovec);
 
 /* Should really be in linux/kernel/ksyms.c */
 EXPORT_SYMBOL(dump_thread);
diff -Nru a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S
--- a/arch/sparc64/kernel/sys32.S	Tue Feb 18 10:25:13 2003
+++ b/arch/sparc64/kernel/sys32.S	Thu Mar  6 11:06:44 2003
@@ -202,38 +202,38 @@
 	nop
 	nop
 	nop
-do_sys_setsockopt: /* sys32_setsockopt(int, int, int, char *, int) */
+do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */
 	ldswa		[%o1 + 0x0] %asi, %o0
-	sethi		%hi(sys32_setsockopt), %g1
+	sethi		%hi(compat_sys_setsockopt), %g1
 	ldswa		[%o1 + 0x8] %asi, %o2
 	lduwa		[%o1 + 0xc] %asi, %o3
 	ldswa		[%o1 + 0x10] %asi, %o4
-	jmpl		%g1 + %lo(sys32_setsockopt), %g0
+	jmpl		%g1 + %lo(compat_sys_setsockopt), %g0
 	 ldswa		[%o1 + 0x4] %asi, %o1
 	nop
-do_sys_getsockopt: /* sys32_getsockopt(int, int, int, u32, u32) */
+do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */
 	ldswa		[%o1 + 0x0] %asi, %o0
-	sethi		%hi(sys32_getsockopt), %g1
+	sethi		%hi(compat_sys_getsockopt), %g1
 	ldswa		[%o1 + 0x8] %asi, %o2
 	lduwa		[%o1 + 0xc] %asi, %o3
 	lduwa		[%o1 + 0x10] %asi, %o4
-	jmpl		%g1 + %lo(sys32_getsockopt), %g0
+	jmpl		%g1 + %lo(compat_sys_getsockopt), %g0
 	 ldswa		[%o1 + 0x4] %asi, %o1
 	nop
-do_sys_sendmsg: /* sys32_sendmsg(int, struct msghdr32 *, unsigned int) */
+do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */
 	ldswa		[%o1 + 0x0] %asi, %o0
-	sethi		%hi(sys32_sendmsg), %g1
+	sethi		%hi(compat_sys_sendmsg), %g1
 	lduwa		[%o1 + 0x8] %asi, %o2
-	jmpl		%g1 + %lo(sys32_sendmsg), %g0
+	jmpl		%g1 + %lo(compat_sys_sendmsg), %g0
 	 lduwa		[%o1 + 0x4] %asi, %o1
 	nop
 	nop
 	nop
-do_sys_recvmsg: /* sys32_recvmsg(int, struct msghdr32 *, unsigned int) */
+do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */
 	ldswa		[%o1 + 0x0] %asi, %o0
-	sethi		%hi(sys32_recvmsg), %g1
+	sethi		%hi(compat_sys_recvmsg), %g1
 	lduwa		[%o1 + 0x8] %asi, %o2
-	jmpl		%g1 + %lo(sys32_recvmsg), %g0
+	jmpl		%g1 + %lo(compat_sys_recvmsg), %g0
 	 lduwa		[%o1 + 0x4] %asi, %o1
 	nop
 	nop
diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
--- a/arch/sparc64/kernel/sys_sparc32.c	Tue Feb 18 10:25:13 2003
+++ b/arch/sparc64/kernel/sys_sparc32.c	Thu Mar  6 11:06:44 2003
@@ -63,8 +63,6 @@
 #include <asm/semaphore.h>
 #include <asm/mmu_context.h>
 
-#include <net/scm.h>
-
 /* Use this to get at 32-bit user passed pointers. */
 /* Things to consider: the low-level assembly stub does
    srl x, 0, x for first four arguments, so if you have
@@ -860,13 +858,11 @@
 		return sys_ftruncate(fd, (high << 32) | low);
 }
 
-struct iovec32 { u32 iov_base; compat_size_t iov_len; };
-
 typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
 typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
 
 static long do_readv_writev32(int type, struct file *file,
-			      const struct iovec32 *vector, u32 count)
+			      const struct compat_iovec *vector, u32 count)
 {
 	compat_ssize_t tot_len;
 	struct iovec iovstack[UIO_FASTIOV];
@@ -900,7 +896,7 @@
 			goto out;
 	}
 	retval = -EFAULT;
-	if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+	if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count))
 		goto out;
 
 	/*
@@ -992,7 +988,7 @@
 	return retval;
 }
 
-asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
+asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	int ret;
@@ -1015,7 +1011,7 @@
 	return ret;
 }
 
-asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
+asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct file *file;
 	int ret;
@@ -1905,773 +1901,6 @@
 	set_fs (old_fs);
 	if (put_rusage (ru, &r)) return -EFAULT;
 	return ret;
-}
-
-/* XXX This really belongs in some header file... -DaveM */
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
-					   16 for IP, 16 for IPX,
-					   24 for IPv6,
-					   about 80 for AX.25 */
-
-struct msghdr32 {
-        u32               msg_name;
-        int               msg_namelen;
-        u32               msg_iov;
-        compat_size_t msg_iovlen;
-        u32               msg_control;
-        compat_size_t msg_controllen;
-        unsigned          msg_flags;
-};
-
-struct cmsghdr32 {
-        compat_size_t cmsg_len;
-        int               cmsg_level;
-        int               cmsg_type;
-};
-
-/* Bleech... */
-#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
-#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
-
-#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
-
-#define CMSG32_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
-#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
-#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
-
-#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
-				    (struct cmsghdr32 *)(ctl) : \
-				    (struct cmsghdr32 *)NULL)
-#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-
-__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
-					      struct cmsghdr32 *__cmsg, int __cmsg_len)
-{
-	struct cmsghdr32 * __ptr;
-
-	__ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
-				     CMSG32_ALIGN(__cmsg_len));
-	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
-		return NULL;
-
-	return __ptr;
-}
-
-__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
-					    struct cmsghdr32 *__cmsg,
-					    int __cmsg_len)
-{
-	return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
-			       __cmsg, __cmsg_len);
-}
-
-static inline int iov_from_user32_to_kern(struct iovec *kiov,
-					  struct iovec32 *uiov32,
-					  int niov)
-{
-	int tot_len = 0;
-
-	while(niov > 0) {
-		u32 len, buf;
-
-		if(get_user(len, &uiov32->iov_len) ||
-		   get_user(buf, &uiov32->iov_base)) {
-			tot_len = -EFAULT;
-			break;
-		}
-		tot_len += len;
-		kiov->iov_base = (void *)A(buf);
-		kiov->iov_len = (__kernel_size_t) len;
-		uiov32++;
-		kiov++;
-		niov--;
-	}
-	return tot_len;
-}
-
-static int msghdr_from_user32_to_kern(struct msghdr *kmsg,
-				      struct msghdr32 *umsg)
-{
-	u32 tmp1, tmp2, tmp3;
-	int err;
-
-	err = get_user(tmp1, &umsg->msg_name);
-	err |= __get_user(tmp2, &umsg->msg_iov);
-	err |= __get_user(tmp3, &umsg->msg_control);
-	if (err)
-		return -EFAULT;
-
-	kmsg->msg_name = (void *)A(tmp1);
-	kmsg->msg_iov = (struct iovec *)A(tmp2);
-	kmsg->msg_control = (void *)A(tmp3);
-
-	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
-	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
-	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
-	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
-	
-	return err;
-}
-
-/* I've named the args so it is easy to tell whose space the pointers are in. */
-static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
-			  char *kern_address, int mode)
-{
-	int tot_len;
-
-	if(kern_msg->msg_namelen) {
-		if(mode==VERIFY_READ) {
-			int err = move_addr_to_kernel(kern_msg->msg_name,
-						      kern_msg->msg_namelen,
-						      kern_address);
-			if(err < 0)
-				return err;
-		}
-		kern_msg->msg_name = kern_address;
-	} else
-		kern_msg->msg_name = NULL;
-
-	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
-		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
-				   GFP_KERNEL);
-		if(!kern_iov)
-			return -ENOMEM;
-	}
-
-	tot_len = iov_from_user32_to_kern(kern_iov,
-					  (struct iovec32 *)kern_msg->msg_iov,
-					  kern_msg->msg_iovlen);
-	if(tot_len >= 0)
-		kern_msg->msg_iov = kern_iov;
-	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
-		kfree(kern_iov);
-
-	return tot_len;
-}
-
-/* There is a lot of hair here because the alignment rules (and
- * thus placement) of cmsg headers and length are different for
- * 32-bit apps.  -DaveM
- */
-static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
-				       unsigned char *stackbuf, int stackbuf_size)
-{
-	struct cmsghdr32 *ucmsg;
-	struct cmsghdr *kcmsg, *kcmsg_base;
-	compat_size_t ucmlen;
-	__kernel_size_t kcmlen, tmp;
-
-	kcmlen = 0;
-	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		if(get_user(ucmlen, &ucmsg->cmsg_len))
-			return -EFAULT;
-
-		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
-			return -EINVAL;
-
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmlen += tmp;
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-	if(kcmlen == 0)
-		return -EINVAL;
-
-	/* The kcmlen holds the 64-bit version of the control length.
-	 * It may not be modified as we do not stick it into the kmsg
-	 * until we have successfully copied over all of the data
-	 * from the user.
-	 */
-	if(kcmlen > stackbuf_size)
-		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
-	if(kcmsg == NULL)
-		return -ENOBUFS;
-
-	/* Now copy them over neatly. */
-	memset(kcmsg, 0, kcmlen);
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		__get_user(ucmlen, &ucmsg->cmsg_len);
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmsg->cmsg_len = tmp;
-		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
-		/* Copy over the data. */
-		if(copy_from_user(CMSG_DATA(kcmsg),
-				  CMSG32_DATA(ucmsg),
-				  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
-			goto out_free_efault;
-
-		/* Advance. */
-		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-
-	/* Ok, looks like we made it.  Hook it up and return success. */
-	kmsg->msg_control = kcmsg_base;
-	kmsg->msg_controllen = kcmlen;
-	return 0;
-
-out_free_efault:
-	if(kcmsg_base != (struct cmsghdr *)stackbuf)
-		kfree(kcmsg_base);
-	return -EFAULT;
-}
-
-static void put_cmsg32(struct msghdr *kmsg, int level, int type,
-		       int len, void *data)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	struct cmsghdr32 cmhdr;
-	int cmlen = CMSG32_LEN(len);
-
-	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		return;
-	}
-
-	if(kmsg->msg_controllen < cmlen) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		cmlen = kmsg->msg_controllen;
-	}
-	cmhdr.cmsg_level = level;
-	cmhdr.cmsg_type = type;
-	cmhdr.cmsg_len = cmlen;
-
-	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
-		return;
-	if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
-		return;
-	cmlen = CMSG32_SPACE(len);
-	kmsg->msg_control += cmlen;
-	kmsg->msg_controllen -= cmlen;
-}
-
-static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
-	int fdnum = scm->fp->count;
-	struct file **fp = scm->fp->fp;
-	int *cmfptr;
-	int err = 0, i;
-
-	if (fdnum < fdmax)
-		fdmax = fdnum;
-
-	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
-		int new_fd;
-		err = get_unused_fd();
-		if (err < 0)
-			break;
-		new_fd = err;
-		err = put_user(new_fd, cmfptr);
-		if (err) {
-			put_unused_fd(new_fd);
-			break;
-		}
-		/* Bump the usage count and install the file. */
-		get_file(fp[i]);
-		fd_install(new_fd, fp[i]);
-	}
-
-	if (i > 0) {
-		int cmlen = CMSG32_LEN(i * sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
-		if (!err)
-			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
-		if (!err)
-			err = put_user(cmlen, &cm->cmsg_len);
-		if (!err) {
-			cmlen = CMSG32_SPACE(i * sizeof(int));
-			kmsg->msg_control += cmlen;
-			kmsg->msg_controllen -= cmlen;
-		}
-	}
-	if (i < fdnum)
-		kmsg->msg_flags |= MSG_CTRUNC;
-
-	/*
-	 * All of the files that fit in the message have had their
-	 * usage counts incremented, so we just free the list.
-	 */
-	__scm_destroy(scm);
-}
-
-/* In these cases we (currently) can just copy to data over verbatim
- * because all CMSGs created by the kernel have well defined types which
- * have the same layout in both the 32-bit and 64-bit API.  One must add
- * some special cased conversions here if we start sending control messages
- * with incompatible types.
- *
- * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
- * we do our work.  The remaining cases are:
- *
- * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
- *		IP_TTL		int			32-bit clean
- *		IP_TOS		__u8			32-bit clean
- *		IP_RECVOPTS	variable length		32-bit clean
- *		IP_RETOPTS	variable length		32-bit clean
- *		(these last two are clean because the types are defined
- *		 by the IPv4 protocol)
- *		IP_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in	32-bit clean
- * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in6	32-bit clean
- *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
- *		IPV6_HOPLIMIT	int			32-bit clean
- *		IPV6_FLOWINFO	u32			32-bit clean
- *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
- *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
- *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
- *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
- */
-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
-{
-	unsigned char *workbuf, *wp;
-	unsigned long bufsz, space_avail;
-	struct cmsghdr *ucmsg;
-
-	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
-	space_avail = kmsg->msg_controllen + bufsz;
-	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
-	if(workbuf == NULL)
-		goto fail;
-
-	/* To make this more sane we assume the kernel sends back properly
-	 * formatted control messages.  Because of how the kernel will truncate
-	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
-	 */
-	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
-	while(((unsigned long)ucmsg) <=
-	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
-		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
-		int clen64, clen32;
-
-		/* UCMSG is the 64-bit format CMSG entry in user-space.
-		 * KCMSG32 is within the kernel space temporary buffer
-		 * we use to convert into a 32-bit style CMSG.
-		 */
-		__get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
-		__get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
-
-		clen64 = kcmsg32->cmsg_len;
-		if (kcmsg32->cmsg_level == SOL_SOCKET &&
-		    kcmsg32->cmsg_type == SO_TIMESTAMP) {
-			struct timeval tv;
-			struct compat_timeval *tv32;
-
-			if (clen64 != CMSG_LEN(sizeof(struct timeval))) {
-				kfree(workbuf);
-				goto fail;
-			}
-			copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv));
-			tv32 = (struct compat_timeval *) CMSG32_DATA(kcmsg32);
-			tv32->tv_sec = tv.tv_sec;
-			tv32->tv_usec = tv.tv_usec;
-			clen32 = sizeof(*tv32) +
-				CMSG32_ALIGN(sizeof(struct cmsghdr32));
-		} else {
-			copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
-				       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
-			clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
-				  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
-		}
-		kcmsg32->cmsg_len = clen32;
-
-		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
-		wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
-	}
-
-	/* Copy back fixed up data, and adjust pointers. */
-	bufsz = (wp - workbuf);
-	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
-
-	kmsg->msg_control = (struct cmsghdr *)
-		(((char *)orig_cmsg_uptr) + bufsz);
-	kmsg->msg_controllen = space_avail - bufsz;
-
-	kfree(workbuf);
-	return;
-
-fail:
-	/* If we leave the 64-bit format CMSG chunks in there,
-	 * the application could get confused and crash.  So to
-	 * ensure greater recovery, we report no CMSGs.
-	 */
-	kmsg->msg_controllen += bufsz;
-	kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
-{
-	struct socket *sock;
-	char address[MAX_SOCK_ADDR];
-	struct iovec iov[UIO_FASTIOV];
-	unsigned char ctl[sizeof(struct cmsghdr) + 20];
-	unsigned char *ctl_buf = ctl;
-	struct msghdr kern_msg;
-	int err, total_len;
-
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-	err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	if(kern_msg.msg_controllen) {
-		err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
-		if(err)
-			goto out_freeiov;
-		ctl_buf = kern_msg.msg_control;
-	}
-	kern_msg.msg_flags = user_flags;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		if (sock->file->f_flags & O_NONBLOCK)
-			kern_msg.msg_flags |= MSG_DONTWAIT;
-		err = sock_sendmsg(sock, &kern_msg, total_len);
-		sockfd_put(sock);
-	}
-
-	/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
-	if(ctl_buf != ctl)
-		kfree(ctl_buf);
-out_freeiov:
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	return err;
-}
-
-asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
-{
-	struct iovec iovstack[UIO_FASTIOV];
-	struct msghdr kern_msg;
-	char addr[MAX_SOCK_ADDR];
-	struct socket *sock;
-	struct iovec *iov = iovstack;
-	struct sockaddr *uaddr;
-	int *uaddr_len;
-	unsigned long cmsg_ptr;
-	int err, total_len, len = 0;
-
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-
-	uaddr = kern_msg.msg_name;
-	uaddr_len = &user_msg->msg_namelen;
-	err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	cmsg_ptr = (unsigned long) kern_msg.msg_control;
-	kern_msg.msg_flags = 0;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		struct sock_iocb *si;
-		struct kiocb iocb;
-
-		if (sock->file->f_flags & O_NONBLOCK)
-			user_flags |= MSG_DONTWAIT;
-
-		init_sync_kiocb(&iocb, NULL);
-		si = kiocb_to_siocb(&iocb);
-		si->sock = sock;
-		si->scm = &si->async_scm;
-		si->msg = &kern_msg;
-		si->size = total_len;
-		si->flags = user_flags;
-		memset(si->scm, 0, sizeof(*si->scm));
-
-		err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len,
-					 user_flags, si->scm);
-		if (-EIOCBQUEUED == err)
-			err = wait_on_sync_kiocb(&iocb);
-
-		if(err >= 0) {
-			len = err;
-			if(!kern_msg.msg_control) {
-				if(sock->passcred || si->scm->fp)
-					kern_msg.msg_flags |= MSG_CTRUNC;
-				if(si->scm->fp)
-					__scm_destroy(si->scm);
-			} else {
-				/* If recvmsg processing itself placed some
-				 * control messages into user space, it's is
-				 * using 64-bit CMSG processing, so we need
-				 * to fix it up before we tack on more stuff.
-				 */
-				if((unsigned long) kern_msg.msg_control != cmsg_ptr)
-					cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
-
-				/* Wheee... */
-				if(sock->passcred)
-					put_cmsg32(&kern_msg,
-						   SOL_SOCKET, SCM_CREDENTIALS,
-						   sizeof(si->scm->creds),
-						   &si->scm->creds);
-				if(si->scm->fp != NULL)
-					scm_detach_fds32(&kern_msg, si->scm);
-			}
-		}
-		sockfd_put(sock);
-	}
-
-	if(uaddr != NULL && err >= 0)
-		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
-	if(cmsg_ptr != 0 && err >= 0) {
-		unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
-		compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr);
-		err |= __put_user(uclen, &user_msg->msg_controllen);
-	}
-	if(err >= 0)
-		err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	if(err < 0)
-		return err;
-	return len;
-}
-
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
-static int do_netfilter_replace(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct ipt_replace32 {
-		char name[IPT_TABLE_MAXNAMELEN];
-		__u32 valid_hooks;
-		__u32 num_entries;
-		__u32 size;
-		__u32 hook_entry[NF_IP_NUMHOOKS];
-		__u32 underflow[NF_IP_NUMHOOKS];
-		__u32 num_counters;
-		__u32 counters;
-		struct ipt_entry entries[0];
-	} *repl32 = (struct ipt_replace32 *)optval;
-	struct ipt_replace *krepl;
-	struct ipt_counters *counters32;
-	__u32 origsize;
-	unsigned int kreplsize, kcountersize;
-	mm_segment_t old_fs;
-	int ret;
-
-	if (optlen < sizeof(repl32))
-		return -EINVAL;
-
-	if (copy_from_user(&origsize,
-			&repl32->size,
-			sizeof(origsize)))
-		return -EFAULT;
-
-	kreplsize = sizeof(*krepl) + origsize;
-	kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
-
-	/* Hack: Causes ipchains to give correct error msg --RR */
-	if (optlen != kreplsize)
-		return -ENOPROTOOPT;
-
-	krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL);
-	if (krepl == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(krepl, optval, kreplsize)) {
-		kfree(krepl);
-		return -EFAULT;
-	}
-
-	counters32 = (struct ipt_counters *)AA(
-		((struct ipt_replace32 *)krepl)->counters);
-
-	kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
-	krepl->counters = (struct ipt_counters *)kmalloc(
-					kcountersize, GFP_KERNEL);
-	if (krepl->counters == NULL) {
-		kfree(krepl);
-		return -ENOMEM;
-	}
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *)krepl, kreplsize);
-	set_fs(old_fs);
-
-	if (ret == 0 &&
-		copy_to_user(counters32, krepl->counters, kcountersize))
-			ret = -EFAULT;
-
-	kfree(krepl->counters);
-	kfree(krepl);
-
-	return ret;
-}
-
-static int do_set_attach_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct sock_fprog32 {
-		__u16 len;
-		__u32 filter;
-	} *fprog32 = (struct sock_fprog32 *)optval;
-	struct sock_fprog kfprog;
-	struct sock_filter *kfilter;
-	unsigned int fsize;
-	mm_segment_t old_fs;
-	__u32 uptr;
-	int ret;
-
-	if (get_user(kfprog.len, &fprog32->len) ||
-	    __get_user(uptr, &fprog32->filter))
-		return -EFAULT;
-
-	kfprog.filter = (struct sock_filter *)A(uptr);
-	fsize = kfprog.len * sizeof(struct sock_filter);
-
-	kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
-	if (kfilter == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(kfilter, kfprog.filter, fsize)) {
-		kfree(kfilter);
-		return -EFAULT;
-	}
-
-	kfprog.filter = kfilter;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *)&kfprog, sizeof(kfprog));
-	set_fs(old_fs);
-
-	kfree(kfilter);
-
-	return ret;
-}
-
-static int do_set_icmpv6_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct icmp6_filter kfilter;
-	mm_segment_t old_fs;
-	int ret, i;
-
-	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
-		return -EFAULT;
-
-
-	for (i = 0; i < 8; i += 2) {
-		u32 tmp = kfilter.data[i];
-
-		kfilter.data[i] = kfilter.data[i + 1];
-		kfilter.data[i + 1] = tmp;
-	}
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *) &kfilter, sizeof(kfilter));
-	set_fs(old_fs);
-
-	return ret;
-}
-
-static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen)
-{
-	struct compat_timeval *up = (struct compat_timeval *) optval;
-	struct timeval ktime;
-	mm_segment_t old_fs;
-	int err;
-
-	if (optlen < sizeof(*up))
-		return -EINVAL;
-	if (get_user(ktime.tv_sec, &up->tv_sec) ||
-	    __get_user(ktime.tv_usec, &up->tv_usec))
-		return -EFAULT;
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime));
-	set_fs(old_fs);
-
-	return err;
-}
-
-asmlinkage int sys32_setsockopt(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	if (optname == IPT_SO_SET_REPLACE)
-		return do_netfilter_replace(fd, level, optname,
-					    optval, optlen);
-	if (optname == SO_ATTACH_FILTER)
-		return do_set_attach_filter(fd, level, optname,
-					    optval, optlen);
-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
-		return do_set_sock_timeout(fd, level, optname, optval, optlen);
-	if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER)
-		return do_set_icmpv6_filter(fd, level, optname,
-					    optval, optlen);
-
-	return sys_setsockopt(fd, level, optname, optval, optlen);
-}
-
-extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
-				      char *optval, int *optlen);
-
-static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
-{
-	struct compat_timeval *up = (struct compat_timeval *) optval;
-	struct timeval ktime;
-	mm_segment_t old_fs;
-	int len, err;
-
-	if (get_user(len, optlen))
-		return -EFAULT;
-	if (len < sizeof(*up))
-		return -EINVAL;
-	len = sizeof(ktime);
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len);
-	set_fs(old_fs);
-
-	if (!err) {
-		if (put_user(sizeof(*up), optlen) ||
-		    put_user(ktime.tv_sec, &up->tv_sec) ||
-		    __put_user(ktime.tv_usec, &up->tv_usec))
-			err = -EFAULT;
-	}
-	return err;
-}
-
-asmlinkage int sys32_getsockopt(int fd, int level, int optname,
-				char *optval, int *optlen)
-{
-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
-		return do_get_sock_timeout(fd, level, optname, optval, optlen);
-	return sys_getsockopt(fd, level, optname, optval, optlen);
 }
 
 extern void check_pending(int signum);
diff -Nru a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
--- a/arch/sparc64/kernel/sys_sunos32.c	Tue Feb 18 10:25:13 2003
+++ b/arch/sparc64/kernel/sys_sunos32.c	Sat Mar  8 11:39:01 2003
@@ -54,6 +54,7 @@
 #include <linux/personality.h>
 
 /* For SOCKET_I */
+#include <linux/socket.h>
 #include <net/sock.h>
 
 /* Use this to get at 32-bit user passed pointers. */
@@ -1253,26 +1254,9 @@
 	return ret;
 }
 
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
-asmlinkage int sunos_socket(int family, int type, int protocol)
-{
-	int ret, one = 1;
-
-	ret = sys_socket(family, type, protocol);
-	if (ret < 0)
-		goto out;
-
-	sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
-		       (char *)&one, sizeof(one));
-out:
-	return ret;
-}
-
 asmlinkage int sunos_accept(int fd, u32 sa, u32 addrlen)
 {
-	int ret, one = 1;
+	int ret;
 
 	while (1) {
 		ret = check_nonblock(sys_accept(fd, (struct sockaddr *)A(sa),
@@ -1280,12 +1264,6 @@
 		if (ret != -ENETUNREACH && ret != -EHOSTUNREACH)
 			break;
 	}
-	if (ret < 0)
-		goto out;
-
-	sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
-		       (char *)&one, sizeof(one));
-out:
 	return ret;
 }
 
@@ -1324,8 +1302,6 @@
 
 extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
 				     char *optval, int optlen);
-extern asmlinkage int sys32_getsockopt(int fd, int level, int optname,
-				     u32 optval, u32 optlen);
 
 asmlinkage int sunos_setsockopt(int fd, int level, int optname, u32 optval,
 				int optlen)
@@ -1353,6 +1329,6 @@
 		if (tr_opt >=2 && tr_opt <= 6)
 			tr_opt += 30;
 	}
-	ret = sys32_getsockopt(fd, level, tr_opt, optval, optlen);
+	ret = compat_sys_getsockopt(fd, level, tr_opt, (void*)(unsigned long)optval, (void*)(unsigned long)optlen);
 	return ret;
 }
diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
--- a/arch/sparc64/kernel/systbls.S	Tue Feb 18 23:56:15 2003
+++ b/arch/sparc64/kernel/systbls.S	Sat Mar  8 11:39:01 2003
@@ -173,13 +173,13 @@
 	.word compat_sys_getitimer, sys_gethostname, sys_sethostname
 	.word sunos_getdtablesize, sys_dup2, sunos_nop
 	.word sys32_fcntl, sunos_select, sunos_nop
-	.word sys_fsync, sys_setpriority32, sunos_socket
+	.word sys_fsync, sys_setpriority32, sys_socket
 	.word sys_connect, sunos_accept
 /*100*/	.word sys_getpriority, sunos_send, sunos_recv
 	.word sunos_nosys, sys_bind, sunos_setsockopt
 	.word sys_listen, sunos_nosys, sunos_sigaction
 	.word sunos_sigblock, sunos_sigsetmask, sys_sigpause
-	.word sys32_sigstack, sys32_recvmsg, sys32_sendmsg
+	.word sys32_sigstack, compat_sys_recvmsg, compat_sys_sendmsg
 	.word sunos_nosys, sys32_gettimeofday, sys32_getrusage
 	.word sunos_getsockopt, sunos_nosys, sunos_readv
 	.word sunos_writev, sys32_settimeofday, sys32_fchown16
diff -Nru a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc64/kernel/us3_cpufreq.c
--- a/arch/sparc64/kernel/us3_cpufreq.c	Mon Mar  3 00:34:40 2003
+++ b/arch/sparc64/kernel/us3_cpufreq.c	Sat Mar  8 01:37:35 2003
@@ -276,6 +276,7 @@
 		driver->target = us3freq_target;
 		driver->init = us3freq_cpu_init;
 		driver->exit = us3freq_cpu_exit;
+		driver->owner = THIS_MODULE,
 		strcpy(driver->name, "UltraSPARC-III");
 
 		cpufreq_us3_driver = driver;
diff -Nru a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c
--- a/arch/sparc64/solaris/socket.c	Wed Dec  4 11:05:21 2002
+++ b/arch/sparc64/solaris/socket.c	Thu Mar  6 12:08:45 2003
@@ -267,35 +267,6 @@
 	unsigned char	cmsg_data[0];
 };
 
-struct iovec32 {
-	u32		iov_base;
-	u32 iov_len;
-};
-
-static inline int iov_from_user32_to_kern(struct iovec *kiov,
-					  struct iovec32 *uiov32,
-					  int niov)
-{
-	int tot_len = 0;
-
-	while(niov > 0) {
-		u32 len, buf;
-
-		if(get_user(len, &uiov32->iov_len) ||
-		   get_user(buf, &uiov32->iov_base)) {
-			tot_len = -EFAULT;
-			break;
-		}
-		tot_len += len;
-		kiov->iov_base = (void *)A(buf);
-		kiov->iov_len = (__kernel_size_t) len;
-		uiov32++;
-		kiov++;
-		niov--;
-	}
-	return tot_len;
-}
-
 static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
 					     struct sol_nmsghdr *umsg)
 {
@@ -321,42 +292,6 @@
 	return err;
 }
 
-/* I've named the args so it is easy to tell whose space the pointers are in. */
-static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
-			  char *kern_address, int mode)
-{
-	int tot_len;
-
-	if(kern_msg->msg_namelen) {
-		if(mode==VERIFY_READ) {
-			int err = move_addr_to_kernel(kern_msg->msg_name,
-						      kern_msg->msg_namelen,
-						      kern_address);
-			if(err < 0)
-				return err;
-		}
-		kern_msg->msg_name = kern_address;
-	} else
-		kern_msg->msg_name = NULL;
-
-	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
-		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
-				   GFP_KERNEL);
-		if(!kern_iov)
-			return -ENOMEM;
-	}
-
-	tot_len = iov_from_user32_to_kern(kern_iov,
-					  (struct iovec32 *)kern_msg->msg_iov,
-					  kern_msg->msg_iovlen);
-	if(tot_len >= 0)
-		kern_msg->msg_iov = kern_iov;
-	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
-		kfree(kern_iov);
-
-	return tot_len;
-}
-
 asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr *user_msg, unsigned user_flags)
 {
 	struct socket *sock;
@@ -371,7 +306,7 @@
 		return -EFAULT;
 	if(kern_msg.msg_iovlen > UIO_MAXIOV)
 		return -EINVAL;
-	err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
+	err = verify_compat_iovec(&kern_msg, iov, address, VERIFY_READ);
 	if (err < 0)
 		goto out;
 	total_len = err;
@@ -439,7 +374,7 @@
 
 	uaddr = kern_msg.msg_name;
 	uaddr_len = &user_msg->msg_namelen;
-	err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
+	err = verify_compat_iovec(&kern_msg, iov, addr, VERIFY_WRITE);
 	if (err < 0)
 		goto out;
 	total_len = err;
diff -Nru a/arch/sparc64/vmlinux.lds.S b/arch/sparc64/vmlinux.lds.S
--- a/arch/sparc64/vmlinux.lds.S	Wed Jan 15 09:48:42 2003
+++ b/arch/sparc64/vmlinux.lds.S	Fri Feb 14 15:11:44 2003
@@ -61,6 +61,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(8192); 
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
diff -Nru a/arch/um/Kconfig b/arch/um/Kconfig
--- a/arch/um/Kconfig	Wed Feb  5 20:16:01 2003
+++ b/arch/um/Kconfig	Sat Mar  8 14:50:37 2003
@@ -7,10 +7,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 mainmenu "Linux/Usermode Kernel Configuration"
 
 config ISA
diff -Nru a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
--- a/arch/um/drivers/stdio_console.c	Sat Dec 28 12:28:00 2002
+++ b/arch/um/drivers/stdio_console.c	Fri Feb 14 15:11:51 2003
@@ -214,12 +214,13 @@
 					       console_device, console_setup,
 					       CON_PRINTBUFFER);
 
-void stdio_console_init(void)
+static void __init stdio_console_init(void)
 {
 	INIT_LIST_HEAD(&vts[0].chan_list);
 	list_add(&init_console_chan.list, &vts[0].chan_list);
 	register_console(&stdiocons);
 }
+console_initcall(stdio_console_init);
 
 static int console_chan_setup(char *str)
 {
diff -Nru a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
--- a/arch/um/drivers/ubd_kern.c	Wed Feb  5 20:16:02 2003
+++ b/arch/um/drivers/ubd_kern.c	Sat Mar  8 14:50:21 2003
@@ -673,7 +673,7 @@
 static int ubd_mc_init(void)
 {
 	mconsole_register_dev(&ubd_mc);
-	return(0);
+	return 0;
 }
 
 __initcall(ubd_mc_init);
@@ -682,29 +682,24 @@
 {
         int i;
 
-	ubd_dir_handle = devfs_mk_dir (NULL, "ubd", NULL);
-	if(register_blkdev(MAJOR_NR, "ubd", &ubd_blops)){
-		printk(KERN_ERR "ubd: unable to get major %d\n", MAJOR_NR);
+	ubd_dir_handle = devfs_mk_dir(NULL, "ubd", NULL);
+	if (register_blkdev(MAJOR_NR, "ubd"))
 		return -1;
-	}
 
 	blk_init_queue(&ubd_queue, do_ubd_request, &ubd_io_lock);
 	elevator_init(&ubd_queue, &elevator_noop);
 
-	if(fake_major != 0){
+	if (fake_major != 0) {
 		char name[sizeof("ubd_nnn\0")];
 
 		snprintf(name, sizeof(name), "ubd_%d", fake_major);
 		ubd_fake_dir_handle = devfs_mk_dir(NULL, name, NULL);
-		if(register_blkdev(fake_major, "ubd", &ubd_blops)){
-			printk(KERN_ERR "ubd: unable to get major %d\n",
-			       fake_major);
+		if (register_blkdev(fake_major, "ubd"))
 			return -1;
-		}
 	}
-	for(i = 0; i < MAX_DEV; i++) 
+	for (i = 0; i < MAX_DEV; i++) 
 		ubd_add(i);
-	return(0);
+	return 0;
 }
 
 late_initcall(ubd_init);
diff -Nru a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
--- a/arch/um/kernel/mem.c	Wed Feb  5 20:16:02 2003
+++ b/arch/um/kernel/mem.c	Thu Mar  6 08:19:07 2003
@@ -154,8 +154,8 @@
 	unsigned long vaddr;
 
 	vaddr = start;
-	i = __pgd_offset(vaddr);
-	j = __pmd_offset(vaddr);
+	i = pgd_index(vaddr);
+	j = pmd_index(vaddr);
 	pgd = pgd_base + i;
 
 	for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
@@ -257,7 +257,7 @@
 	vaddr = PKMAP_BASE;
 	fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, swapper_pg_dir);
 
-	pgd = swapper_pg_dir + __pgd_offset(vaddr);
+	pgd = swapper_pg_dir + pgd_index(vaddr);
 	pmd = pmd_offset(pgd, vaddr);
 	pte = pte_offset_kernel(pmd, vaddr);
 	pkmap_page_table = pte;
diff -Nru a/arch/v850/Kconfig b/arch/v850/Kconfig
--- a/arch/v850/Kconfig	Tue Feb 18 18:40:02 2003
+++ b/arch/v850/Kconfig	Sat Mar  8 14:50:37 2003
@@ -10,9 +10,6 @@
 config MMU
        	bool
 	default n
-config SWAP
-	bool
-	default n
 config UID16
 	bool
 	default n
diff -Nru a/arch/v850/kernel/irq.c b/arch/v850/kernel/irq.c
--- a/arch/v850/kernel/irq.c	Tue Feb 25 01:38:52 2003
+++ b/arch/v850/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -78,6 +78,7 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (i=0; i < 1 /*smp_num_cpus*/; i++)
@@ -87,10 +88,10 @@
 	for (i = 0 ; i < NR_IRQS ; i++) {
 		int j, count, num;
 		const char *type_name = irq_desc[i].handler->typename;
-
+		spin_lock_irqsave(&irq_desc[j].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 
 		count = 0;
 		num = -1;
@@ -108,11 +109,13 @@
 			seq_printf(p, " %*s%d", 14 - prec, type_name, num);
 		} else
 			seq_printf(p, " %14s", type_name);
+		
 		seq_printf(p, "  %s", action->name);
-
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[j].lock, flags);
 	}
 	seq_printf(p, "ERR: %10lu\n", irq_err_count);
 	return 0;
diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
--- a/arch/x86_64/Kconfig	Wed Feb 12 05:38:20 2003
+++ b/arch/x86_64/Kconfig	Sat Mar  8 14:50:37 2003
@@ -24,10 +24,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config ISA
 	bool
 
diff -Nru a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile
--- a/arch/x86_64/boot/Makefile	Wed Jan 29 20:41:18 2003
+++ b/arch/x86_64/boot/Makefile	Fri Mar  7 14:11:39 2003
@@ -62,33 +62,33 @@
 # Set this if you want to pass append arguments to the zdisk/fdimage kernel
 FDARGS = 
 
-$(obj)/mtools.conf: $(obj)/mtools.conf.in
+$(obj)/mtools.conf: $(src)/mtools.conf.in
 	sed -e 's|@OBJ@|$(obj)|g' < $< > $@
 
 # This requires write access to /dev/fd0
 zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
-	MTOOLSRC=$(src)/mtools.conf mformat a:			; sync
+	MTOOLSRC=$(obj)/mtools.conf mformat a:			; sync
 	syslinux /dev/fd0					; sync
 	echo 'default linux $(FDARGS)' | \
-		MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg
-	MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) a:linux	; sync
+		MTOOLSRC=$(obj)/mtools.conf mcopy - a:syslinux.cfg
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux	; sync
 
-# These require being root or having syslinux run setuid
-fdimage fdimage144: $(BOOTIMAGE) $(src)/mtools.conf
+# These require being root or having syslinux 2.02 or higher installed
+fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf
 	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
-	MTOOLSRC=$(src)/mtools.conf mformat v:			; sync
+	MTOOLSRC=$(obj)/mtools.conf mformat v:			; sync
 	syslinux $(obj)/fdimage					; sync
 	echo 'default linux $(FDARGS)' | \
-		MTOOLSRC=$(src)/mtools.conf mcopy - v:syslinux.cfg
-	MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) v:linux	; sync
+		MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux	; sync
 
-fdimage288: $(BOOTIMAGE) $(src)/mtools.conf
+fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
 	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880
-	MTOOLSRC=$(src)/mtools.conf mformat w:			; sync
+	MTOOLSRC=$(obj)/mtools.conf mformat w:			; sync
 	syslinux $(obj)/fdimage					; sync
 	echo 'default linux $(FDARGS)' | \
-		MTOOLSRC=$(src)/mtools.conf mcopy - w:syslinux.cfg
-	MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) w:linux	; sync
+		MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux	; sync
 
 zlilo: $(BOOTIMAGE)
 	if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
diff -Nru a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S
--- a/arch/x86_64/boot/setup.S	Fri May 10 14:10:51 2002
+++ b/arch/x86_64/boot/setup.S	Wed Mar  5 01:43:54 2003
@@ -829,13 +829,6 @@
 	.word	0x9200				# data read/write
 	.word	0x00CF				# granularity = 4096, 386
 						#  (+5th nibble of limit)
-# this is 64bit descriptor for code
-	.word	0xFFFF
-	.word	0
-	.word	0x9A00				# code read/exec
-	.word	0x00AF				# as above, but it is long mode and with D=0
-						# it does not seem to do the trick.
-
 idt_48:
 	.word	0				# idt limit = 0
 	.word	0, 0				# idt base = 0L
diff -Nru a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile
--- a/arch/x86_64/ia32/Makefile	Mon Feb  3 14:19:36 2003
+++ b/arch/x86_64/ia32/Makefile	Thu Mar  6 11:06:44 2003
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o \
 	ia32_signal.o \
-	ia32_binfmt.o fpu32.o socket32.o ptrace32.o ipc32.o syscall32.o
+	ia32_binfmt.o fpu32.o ptrace32.o ipc32.o syscall32.o
diff -Nru a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c
--- a/arch/x86_64/ia32/ia32_signal.c	Mon Feb 10 17:21:29 2003
+++ b/arch/x86_64/ia32/ia32_signal.c	Sat Mar  8 18:05:09 2003
@@ -106,20 +106,24 @@
 	stack_t uss,uoss; 
 	int ret;
 	mm_segment_t seg; 
+	if (uss_ptr) { 
+		u32 ptr;
 	if (!access_ok(VERIFY_READ,uss_ptr,sizeof(stack_ia32_t)) ||
-	    __get_user(ptr_to_u32(uss.ss_sp), &uss_ptr->ss_sp) ||
-	    __get_user((u32)uss.ss_flags, &uss_ptr->ss_flags) ||
-	    __get_user((u32)uss.ss_size, &uss_ptr->ss_size))
+		    __get_user(ptr, &uss_ptr->ss_sp) ||
+		    __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
+		    __get_user(uss.ss_size, &uss_ptr->ss_size))
 		return -EFAULT;
+		uss.ss_sp = (void *)(u64)ptr;
+	}
 	seg = get_fs(); 
 	set_fs(KERNEL_DS); 
-	ret = do_sigaltstack(&uss, &uoss, regs.rsp);
+	ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs.rsp);
 	set_fs(seg); 
 	if (ret >= 0 && uoss_ptr)  {
-		if (!access_ok(VERIFY_WRITE,uss_ptr,sizeof(stack_ia32_t)) ||
-		    __put_user(ptr_to_u32(uss.ss_sp), &uss_ptr->ss_sp) ||
-		    __put_user((u32)uss.ss_flags, &uss_ptr->ss_flags) ||
-		    __put_user((u32)uss.ss_size, &uss_ptr->ss_size))
+		if (!access_ok(VERIFY_WRITE,uoss_ptr,sizeof(stack_ia32_t)) ||
+		    __put_user((u32)(u64)uss.ss_sp, &uoss_ptr->ss_sp) ||
+		    __put_user(uss.ss_flags, &uoss_ptr->ss_flags) ||
+		    __put_user(uss.ss_size, &uoss_ptr->ss_size))
 			ret = -EFAULT;
 	} 	
 	return ret;	
diff -Nru a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
--- a/arch/x86_64/ia32/ia32entry.S	Sat Feb 15 04:39:48 2003
+++ b/arch/x86_64/ia32/ia32entry.S	Sat Mar  8 15:58:09 2003
@@ -302,7 +302,7 @@
 	.quad compat_sys_statfs
 	.quad compat_sys_fstatfs		/* 100 */
 	.quad sys_ioperm
-	.quad sys32_socketcall
+	.quad compat_sys_socketcall
 	.quad sys_syslog
 	.quad compat_sys_setitimer
 	.quad compat_sys_getitimer	/* 105 */
@@ -443,8 +443,8 @@
 	.quad compat_sys_futex		/* 240 */
         .quad sys32_sched_setaffinity
         .quad sys32_sched_getaffinity
-	.quad sys_set_thread_area
-	.quad sys_get_thread_area
+	.quad sys32_set_thread_area
+	.quad sys32_get_thread_area
 	.quad sys32_io_setup
 	.quad sys_io_destroy
 	.quad sys32_io_getevents
diff -Nru a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c
--- a/arch/x86_64/ia32/ptrace32.c	Sat Oct 26 14:02:33 2002
+++ b/arch/x86_64/ia32/ptrace32.c	Sat Mar  8 17:56:51 2003
@@ -22,6 +22,8 @@
 #include <asm/errno.h>
 #include <asm/debugreg.h>
 #include <asm/i387.h>
+#include <asm/desc.h>
+#include <asm/ldt.h>
 #include <asm/fpu32.h>
 #include <linux/mm.h>
 #include <linux/ptrace.h>
diff -Nru a/arch/x86_64/ia32/socket32.c b/arch/x86_64/ia32/socket32.c
--- a/arch/x86_64/ia32/socket32.c	Fri Dec 20 16:51:21 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,756 +0,0 @@
-/* 
- * 32bit Socket syscall emulation. Based on arch/sparc64/kernel/sys_sparc32.c.
- *
- * Copyright (C) 2000		VA Linux Co
- * Copyright (C) 2000		Don Dugger <n0ano@valinux.com>
- * Copyright (C) 1999 		Arun Sharma <arun.sharma@intel.com>
- * Copyright (C) 1997,1998 	Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Copyright (C) 1997 		David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 2000		Hewlett-Packard Co.
- * Copyright (C) 2000		David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 2000,2001	Andi Kleen, SuSE Labs 
- */
-
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/file.h>
-#include <linux/icmpv6.h>
-#include <linux/socket.h>
-#include <linux/filter.h>
-#include <linux/compat.h>
-
-#include <net/scm.h>
-#include <net/sock.h>
-#include <asm/ia32.h>
-#include <asm/uaccess.h>
-#include <asm/socket32.h>
-
-#define A(__x)		((unsigned long)(__x))
-#define AA(__x)		((unsigned long)(__x))
-
-extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
-				       void * optval, int *optlen);
-
-
-static inline int iov_from_user32_to_kern(struct iovec *kiov,
-					  struct iovec32 *uiov32,
-					  int niov)
-{
-	int tot_len = 0;
-
-	while(niov > 0) {
-		u32 len, buf;
-
-		if(get_user(len, &uiov32->iov_len) ||
-		   get_user(buf, &uiov32->iov_base)) {
-			tot_len = -EFAULT;
-			break;
-		}
-		tot_len += len;
-		kiov->iov_base = (void *)A(buf);
-		kiov->iov_len = (__kernel_size_t) len;
-		uiov32++;
-		kiov++;
-		niov--;
-	}
-	return tot_len;
-}
-
-static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
-					     struct msghdr32 *umsg)
-{
-	u32 tmp1, tmp2, tmp3;
-	int err;
-
-	err = get_user(tmp1, &umsg->msg_name);
-	err |= __get_user(tmp2, &umsg->msg_iov);
-	err |= __get_user(tmp3, &umsg->msg_control);
-	if (err)
-		return -EFAULT;
-
-	kmsg->msg_name = (void *)A(tmp1);
-	kmsg->msg_iov = (struct iovec *)A(tmp2);
-	kmsg->msg_control = (void *)A(tmp3);
-
-	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
-	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
-	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
-	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
-	
-	return err;
-}
-
-/* I've named the args so it is easy to tell whose space the pointers are in. */
-static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
-			  char *kern_address, int mode)
-{
-	int tot_len;
-
-	if(kern_msg->msg_namelen) {
-		if(mode==VERIFY_READ) {
-			int err = move_addr_to_kernel(kern_msg->msg_name,
-						      kern_msg->msg_namelen,
-						      kern_address);
-			if(err < 0)
-				return err;
-		}
-		kern_msg->msg_name = kern_address;
-	} else
-		kern_msg->msg_name = NULL;
-
-	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
-		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
-				   GFP_KERNEL);
-		if(!kern_iov)
-			return -ENOMEM;
-	}
-
-	tot_len = iov_from_user32_to_kern(kern_iov,
-					  (struct iovec32 *)kern_msg->msg_iov,
-					  kern_msg->msg_iovlen);
-	if(tot_len >= 0)
-		kern_msg->msg_iov = kern_iov;
-	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
-		kfree(kern_iov);
-
-	return tot_len;
-}
-
-/* There is a lot of hair here because the alignment rules (and
- * thus placement) of cmsg headers and length are different for
- * 32-bit apps.  -DaveM
- */
-static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
-				       unsigned char *stackbuf, int stackbuf_size)
-{
-	struct cmsghdr32 *ucmsg;
-	struct cmsghdr *kcmsg, *kcmsg_base;
-	compat_size_t ucmlen;
-	__kernel_size_t kcmlen, tmp;
-
-	kcmlen = 0;
-	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		if(get_user(ucmlen, &ucmsg->cmsg_len))
-			return -EFAULT;
-
-		/* Catch bogons. */
-		if(CMSG32_ALIGN(ucmlen) <
-		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
-			return -EINVAL;
-		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
-				   + ucmlen) > kmsg->msg_controllen)
-			return -EINVAL;
-
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmlen += tmp;
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-	if(kcmlen == 0)
-		return -EINVAL;
-
-	/* The kcmlen holds the 64-bit version of the control length.
-	 * It may not be modified as we do not stick it into the kmsg
-	 * until we have successfully copied over all of the data
-	 * from the user.
-	 */
-	if(kcmlen > stackbuf_size)
-		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
-	if(kcmsg == NULL)
-		return -ENOBUFS;
-
-	/* Now copy them over neatly. */
-	memset(kcmsg, 0, kcmlen);
-	ucmsg = CMSG32_FIRSTHDR(kmsg);
-	while(ucmsg != NULL) {
-		__get_user(ucmlen, &ucmsg->cmsg_len);
-		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
-		       CMSG_ALIGN(sizeof(struct cmsghdr)));
-		kcmsg->cmsg_len = tmp;
-		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
-		/* Copy over the data. */
-		if(copy_from_user(CMSG_DATA(kcmsg),
-				  CMSG32_DATA(ucmsg),
-				  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
-			goto out_free_efault;
-
-		/* Advance. */
-		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
-		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
-	}
-
-	/* Ok, looks like we made it.  Hook it up and return success. */
-	kmsg->msg_control = kcmsg_base;
-	kmsg->msg_controllen = kcmlen;
-	return 0;
-
-out_free_efault:
-	if(kcmsg_base != (struct cmsghdr *)stackbuf)
-		kfree(kcmsg_base);
-	return -EFAULT;
-}
-
-static void put_cmsg32(struct msghdr *kmsg, int level, int type,
-		       int len, void *data)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	struct cmsghdr32 cmhdr;
-	int cmlen = CMSG32_LEN(len);
-
-	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		return;
-	}
-
-	if(kmsg->msg_controllen < cmlen) {
-		kmsg->msg_flags |= MSG_CTRUNC;
-		cmlen = kmsg->msg_controllen;
-	}
-	cmhdr.cmsg_level = level;
-	cmhdr.cmsg_type = type;
-	cmhdr.cmsg_len = cmlen;
-
-	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
-		return;
-	if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
-		return;
-	cmlen = CMSG32_SPACE(len);
-	kmsg->msg_control += cmlen;
-	kmsg->msg_controllen -= cmlen;
-}
-
-static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
-{
-	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
-	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
-	int fdnum = scm->fp->count;
-	struct file **fp = scm->fp->fp;
-	int *cmfptr;
-	int err = 0, i;
-
-	if (fdnum < fdmax)
-		fdmax = fdnum;
-
-	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
-		int new_fd;
-		err = get_unused_fd();
-		if (err < 0)
-			break;
-		new_fd = err;
-		err = put_user(new_fd, cmfptr);
-		if (err) {
-			put_unused_fd(new_fd);
-			break;
-		}
-		/* Bump the usage count and install the file. */
-		get_file(fp[i]);
-		fd_install(new_fd, fp[i]);
-	}
-
-	if (i > 0) {
-		int cmlen = CMSG32_LEN(i * sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
-		if (!err)
-			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
-		if (!err)
-			err = put_user(cmlen, &cm->cmsg_len);
-		if (!err) {
-			cmlen = CMSG32_SPACE(i * sizeof(int));
-			kmsg->msg_control += cmlen;
-			kmsg->msg_controllen -= cmlen;
-		}
-	}
-	if (i < fdnum)
-		kmsg->msg_flags |= MSG_CTRUNC;
-
-	/*
-	 * All of the files that fit in the message have had their
-	 * usage counts incremented, so we just free the list.
-	 */
-	__scm_destroy(scm);
-}
-
-/* In these cases we (currently) can just copy to data over verbatim
- * because all CMSGs created by the kernel have well defined types which
- * have the same layout in both the 32-bit and 64-bit API.  One must add
- * some special cased conversions here if we start sending control messages
- * with incompatible types.
- *
- * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
- * we do our work.  The remaining cases are:
- *
- * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
- *		IP_TTL		int			32-bit clean
- *		IP_TOS		__u8			32-bit clean
- *		IP_RECVOPTS	variable length		32-bit clean
- *		IP_RETOPTS	variable length		32-bit clean
- *		(these last two are clean because the types are defined
- *		 by the IPv4 protocol)
- *		IP_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in	32-bit clean
- * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
- *				struct sockaddr_in6	32-bit clean
- *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
- *		IPV6_HOPLIMIT	int			32-bit clean
- *		IPV6_FLOWINFO	u32			32-bit clean
- *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
- *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
- *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
- *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
- */
-static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
-{
-	unsigned char *workbuf, *wp;
-	unsigned long bufsz, space_avail;
-	struct cmsghdr *ucmsg;
-
-	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
-	space_avail = kmsg->msg_controllen + bufsz;
-	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
-	if(workbuf == NULL)
-		goto fail;
-
-	/* To make this more sane we assume the kernel sends back properly
-	 * formatted control messages.  Because of how the kernel will truncate
-	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
-	 */
-	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
-	while(((unsigned long)ucmsg) <=
-	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
-		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
-		int clen64, clen32;
-
-		/* UCMSG is the 64-bit format CMSG entry in user-space.
-		 * KCMSG32 is within the kernel space temporary buffer
-		 * we use to convert into a 32-bit style CMSG.
-		 */
-		__get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
-		__get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
-		__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
-
-		clen64 = kcmsg32->cmsg_len;
-		copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
-			       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
-		clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
-			  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
-		kcmsg32->cmsg_len = clen32;
-
-		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
-		wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
-	}
-
-	/* Copy back fixed up data, and adjust pointers. */
-	bufsz = (wp - workbuf);
-	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
-
-	kmsg->msg_control = (struct cmsghdr *)
-		(((char *)orig_cmsg_uptr) + bufsz);
-	kmsg->msg_controllen = space_avail - bufsz;
-
-	kfree(workbuf);
-	return;
-
-fail:
-	/* If we leave the 64-bit format CMSG chunks in there,
-	 * the application could get confused and crash.  So to
-	 * ensure greater recovery, we report no CMSGs.
-	 */
-	kmsg->msg_controllen += bufsz;
-	kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-asmlinkage long sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
-{
-	struct socket *sock;
-	char address[MAX_SOCK_ADDR];
-	struct iovec iov[UIO_FASTIOV];
-	unsigned char ctl[sizeof(struct cmsghdr) + 20];
-	unsigned char *ctl_buf = ctl;
-	struct msghdr kern_msg;
-	int err, total_len;
-
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-	err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	if(kern_msg.msg_controllen) {
-		err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
-		if(err)
-			goto out_freeiov;
-		ctl_buf = kern_msg.msg_control;
-	}
-	kern_msg.msg_flags = user_flags;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		if (sock->file->f_flags & O_NONBLOCK)
-			kern_msg.msg_flags |= MSG_DONTWAIT;
-		err = sock_sendmsg(sock, &kern_msg, total_len);
-		sockfd_put(sock);
-	}
-
-	/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
-	if(ctl_buf != ctl)
-		kfree(ctl_buf);
-out_freeiov:
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	return err;
-}
-
-asmlinkage long sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
-{
-	struct iovec iovstack[UIO_FASTIOV];
-	struct msghdr kern_msg;
-	char addr[MAX_SOCK_ADDR];
-	struct socket *sock;
-	struct iovec *iov = iovstack;
-	struct sockaddr *uaddr;
-	int *uaddr_len;
-	unsigned long cmsg_ptr;
-	int err, total_len, len = 0;
-
-	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
-		return -EFAULT;
-	if(kern_msg.msg_iovlen > UIO_MAXIOV)
-		return -EINVAL;
-
-	uaddr = kern_msg.msg_name;
-	uaddr_len = &user_msg->msg_namelen;
-	err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
-	if (err < 0)
-		goto out;
-	total_len = err;
-
-	cmsg_ptr = (unsigned long) kern_msg.msg_control;
-	kern_msg.msg_flags = 0;
-
-	sock = sockfd_lookup(fd, &err);
-	if (sock != NULL) {
-		struct sock_iocb *si;
-		struct kiocb iocb;
-
-		if (sock->file->f_flags & O_NONBLOCK)
-			user_flags |= MSG_DONTWAIT;
-
-		init_sync_kiocb(&iocb, NULL);
-		si = kiocb_to_siocb(&iocb);
-		si->sock = sock;
-		si->scm = &si->async_scm;
-		si->msg = &kern_msg;
-		si->size = total_len;
-		si->flags = user_flags;
-		memset(si->scm, 0, sizeof(*si->scm));
-
-		err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len,
-					 user_flags, si->scm);
-		if (-EIOCBQUEUED == err)
-			err = wait_on_sync_kiocb(&iocb);
-
-		if(err >= 0) {
-			len = err;
-			if(!kern_msg.msg_control) {
-				if(sock->passcred || si->scm->fp)
-					kern_msg.msg_flags |= MSG_CTRUNC;
-				if(si->scm->fp)
-					__scm_destroy(si->scm);
-			} else {
-				/* If recvmsg processing itself placed some
-				 * control messages into user space, it's is
-				 * using 64-bit CMSG processing, so we need
-				 * to fix it up before we tack on more stuff.
-				 */
-				if((unsigned long) kern_msg.msg_control != cmsg_ptr)
-					cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
-
-				/* Wheee... */
-				if(sock->passcred)
-					put_cmsg32(&kern_msg,
-						   SOL_SOCKET, SCM_CREDENTIALS,
-						   sizeof(si->scm->creds),
-						   &si->scm->creds);
-				if(si->scm->fp != NULL)
-					scm_detach_fds32(&kern_msg, si->scm);
-			}
-		}
-		sockfd_put(sock);
-	}
-
-	if(uaddr != NULL && err >= 0)
-		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
-	if(cmsg_ptr != 0 && err >= 0) {
-		unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
-		compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr);
-		err |= __put_user(uclen, &user_msg->msg_controllen);
-	}
-	if(err >= 0)
-		err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
-	if(kern_msg.msg_iov != iov)
-		kfree(kern_msg.msg_iov);
-out:
-	if(err < 0)
-		return err;
-	return len;
-}
-
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
-
-static int do_set_attach_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct sock_fprog32 {
-		__u16 len;
-		__u32 filter;
-	} *fprog32 = (struct sock_fprog32 *)optval;
-	struct sock_fprog kfprog;
-	struct sock_filter *kfilter;
-	unsigned int fsize;
-	mm_segment_t old_fs;
-	__u32 uptr;
-	int ret;
-
-	if (get_user(kfprog.len, &fprog32->len) ||
-	    __get_user(uptr, &fprog32->filter))
-		return -EFAULT;
-
-	kfprog.filter = (struct sock_filter *)A(uptr);
-	fsize = kfprog.len * sizeof(struct sock_filter);
-
-	kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
-	if (kfilter == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(kfilter, kfprog.filter, fsize)) {
-		kfree(kfilter);
-		return -EFAULT;
-	}
-
-	kfprog.filter = kfilter;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *)&kfprog, sizeof(kfprog));
-	set_fs(old_fs);
-
-	kfree(kfilter);
-
-	return ret;
-}
-
-static int do_set_icmpv6_filter(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	struct icmp6_filter kfilter;
-	mm_segment_t old_fs;
-	int ret, i;
-
-	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
-		return -EFAULT;
-
-
-	for (i = 0; i < 8; i += 2) {
-		u32 tmp = kfilter.data[i];
-
-		kfilter.data[i] = kfilter.data[i + 1];
-		kfilter.data[i + 1] = tmp;
-	}
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_setsockopt(fd, level, optname,
-			     (char *) &kfilter, sizeof(kfilter));
-	set_fs(old_fs);
-
-	return ret;
-}
-
-static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen)
-{
-	struct compat_timeval *up = (struct compat_timeval *) optval;
-	struct timeval ktime;
-	mm_segment_t old_fs;
-	int err;
-
-	if (optlen < sizeof(*up))
-		return -EINVAL;
-	if (get_user(ktime.tv_sec, &up->tv_sec) ||
-	    __get_user(ktime.tv_usec, &up->tv_usec))
-		return -EFAULT;
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime));
-	set_fs(old_fs);
-
-	return err;
-}
-
-asmlinkage long sys32_setsockopt(int fd, int level, int optname,
-				char *optval, int optlen)
-{
-	if (optname == SO_ATTACH_FILTER)
-		return do_set_attach_filter(fd, level, optname,
-					    optval, optlen);
-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
-		return do_set_sock_timeout(fd, level, optname, optval, optlen);
-	if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER)
-		return do_set_icmpv6_filter(fd, level, optname,
-					    optval, optlen);
-
-	return sys_setsockopt(fd, level, optname, optval, optlen);
-}
-
-static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
-{
-	struct compat_timeval *up = (struct compat_timeval *) optval;
-	struct timeval ktime;
-	mm_segment_t old_fs;
-	int len, err;
-
-	if (get_user(len, optlen))
-		return -EFAULT;
-	if (len < sizeof(*up))
-		return -EINVAL;
-	len = sizeof(ktime);
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len);
-	set_fs(old_fs);
-
-	if (!err) {
-		if (put_user(sizeof(*up), optlen) ||
-		    put_user(ktime.tv_sec, &up->tv_sec) ||
-		    __put_user(ktime.tv_usec, &up->tv_usec))
-			err = -EFAULT;
-	}
-	return err;
-}
-
-asmlinkage long sys32_getsockopt(int fd, int level, int optname,
-				char *optval, int *optlen)
-{
-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
-		return do_get_sock_timeout(fd, level, optname, optval, optlen);
-	return sys_getsockopt(fd, level, optname, optval, optlen);
-}
-
-/* Argument list sizes for sys_socketcall */
-#define AL(x) ((x) * sizeof(u32))
-static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
-                                AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
-                                AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
-#undef AL
-
-extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
-extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr,
-				  int addrlen);
-extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr,
-				 int *upeer_addrlen); 
-extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr,
-				      int *usockaddr_len);
-extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr,
-				      int *usockaddr_len);
-extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags);
-extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len,
-				   unsigned flags, u32 addr, int addr_len);
-extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
-extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size,
-				     unsigned flags, u32 addr, u32 addr_len);
-extern asmlinkage long sys_socket(int family, int type, int protocol);
-extern asmlinkage long sys_socketpair(int family, int type, int protocol,
-				     int usockvec[2]);
-extern asmlinkage long sys_shutdown(int fd, int how);
-extern asmlinkage long sys_listen(int fd, int backlog);
-
-asmlinkage long sys32_socketcall(int call, u32 *args)
-{
-	int ret;
-	u32 a[6];
-	u32 a0,a1;
-				 
-	if (call<SYS_SOCKET||call>SYS_RECVMSG)
-		return -EINVAL;
-	if (copy_from_user(a, args, nas[call]))
-		return -EFAULT;
-	a0=a[0];
-	a1=a[1];
-	
-	switch(call) 
-	{
-		case SYS_SOCKET:
-			ret = sys_socket(a0, a1, a[2]);
-			break;
-		case SYS_BIND:
-			ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]);
-			break;
-		case SYS_CONNECT:
-			ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]);
-			break;
-		case SYS_LISTEN:
-			ret = sys_listen(a0, a1);
-			break;
-		case SYS_ACCEPT:
-			ret = sys_accept(a0, (struct sockaddr *)A(a1),
-					  (int *)A(a[2]));
-			break;
-		case SYS_GETSOCKNAME:
-			ret = sys_getsockname(a0, (struct sockaddr *)A(a1),
-					       (int *)A(a[2]));
-			break;
-		case SYS_GETPEERNAME:
-			ret = sys_getpeername(a0, (struct sockaddr *)A(a1),
-					       (int *)A(a[2]));
-			break;
-		case SYS_SOCKETPAIR:
-			ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
-			break;
-		case SYS_SEND:
-			ret = sys_send(a0, (void *)A(a1), a[2], a[3]);
-			break;
-		case SYS_SENDTO:
-			ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]);
-			break;
-		case SYS_RECV:
-			ret = sys_recv(a0, (void *)A(a1), a[2], a[3]);
-			break;
-		case SYS_RECVFROM:
-			ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
-			break;
-		case SYS_SHUTDOWN:
-			ret = sys_shutdown(a0,a1);
-			break;
-		case SYS_SETSOCKOPT:
-			ret = sys32_setsockopt(a0, a1, a[2], (char *)A(a[3]),
-					      a[4]);
-			break;
-		case SYS_GETSOCKOPT:
-			ret = sys32_getsockopt(a0, a1, a[2], (char *)(u64)a[3], (int *)(u64)a[4]);
-			break;
-		case SYS_SENDMSG:
-			ret = sys32_sendmsg(a0, (struct msghdr32 *)A(a1),
-					     a[2]);
-			break;
-		case SYS_RECVMSG:
-			ret = sys32_recvmsg(a0, (struct msghdr32 *)A(a1),
-					     a[2]);
-			break;
-		default:
-			ret = -EINVAL;
-			break;
-	}
-	return ret;
-}
diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
--- a/arch/x86_64/ia32/sys_ia32.c	Tue Feb 18 10:25:13 2003
+++ b/arch/x86_64/ia32/sys_ia32.c	Sun Mar  9 07:56:11 2003
@@ -738,7 +738,7 @@
 asmlinkage ssize_t sys_writev(unsigned long,const struct iovec *,unsigned long);
 
 static struct iovec *
-get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type, int *errp)
+get_compat_iovec(struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type, int *errp)
 {
 	int i;
 	u32 buf, len;
@@ -751,7 +751,7 @@
 		return 0;
 	if (count > UIO_MAXIOV)
 		return(struct iovec *)0;
-	if(verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count))
+	if(verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*count))
 		return(struct iovec *)0;
 	if (count > UIO_FASTIOV) {
 		*errp = -ENOMEM; 
@@ -792,14 +792,14 @@
 }
 
 asmlinkage long
-sys32_readv(int fd, struct iovec32 *vector, u32 count)
+sys32_readv(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct iovec iovstack[UIO_FASTIOV];
 	struct iovec *iov;
 	int ret;
 	mm_segment_t old_fs = get_fs();
 
-	if ((iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE, &ret)) == NULL)
+	if ((iov = get_compat_iovec(vector, iovstack, count, VERIFY_WRITE, &ret)) == NULL)
 		return ret;
 	set_fs(KERNEL_DS);
 	ret = sys_readv(fd, iov, count);
@@ -810,14 +810,14 @@
 }
 
 asmlinkage long
-sys32_writev(int fd, struct iovec32 *vector, u32 count)
+sys32_writev(int fd, struct compat_iovec *vector, u32 count)
 {
 	struct iovec iovstack[UIO_FASTIOV];
 	struct iovec *iov;
 	int ret;
 	mm_segment_t old_fs = get_fs();
 
-	if ((iov = get_iovec32(vector, iovstack, count, VERIFY_READ, &ret)) == NULL)
+	if ((iov = get_compat_iovec(vector, iovstack, count, VERIFY_READ, &ret)) == NULL)
 		return ret;
 	set_fs(KERNEL_DS);
 	ret = sys_writev(fd, iov, count);
@@ -1261,8 +1261,8 @@
 	if (s->si_signo >= SIGRTMIN) {
 		d->si_pid = s->si_pid;
 		d->si_uid = s->si_uid;
-		/* XXX: Ouch, how to find this out??? */
-		d->si_int = s->si_int;
+		memcpy(&d->si_int, &s->si_int, 
+                       sizeof(siginfo_t) - offsetof(siginfo_t,si_int));
 	} else switch (s->si_signo) {
 	/* XXX: What about POSIX1.b timers */
 	case SIGCHLD:
@@ -1299,8 +1299,9 @@
 	if (s->si_signo >= SIGRTMIN) {
 		d->si_pid = s->si_pid;
 		d->si_uid = s->si_uid;
-		/* XXX: Ouch, how to find this out??? */
-		d->si_int = s->si_int;
+		memcpy(&d->si_int,
+                       &s->si_int,
+                       sizeof(siginfo_t) - offsetof(siginfo_t, si_int)); 
 	} else switch (s->si_signo) {
 	/* XXX: What about POSIX1.b timers */
 	case SIGCHLD:
diff -Nru a/arch/x86_64/ia32/tls32.c b/arch/x86_64/ia32/tls32.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/x86_64/ia32/tls32.c	Sun Mar  9 07:30:05 2003
@@ -0,0 +1,162 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/user.h>
+
+#include <asm/uaccess.h>
+#include <asm/desc.h>
+#include <asm/system.h>
+#include <asm/ldt.h>
+#include <asm/processor.h>
+#include <asm/proto.h>
+
+/*
+ * sys_alloc_thread_area: get a yet unused TLS descriptor index.
+ */
+static int get_free_idx(void)
+{
+	struct thread_struct *t = &current->thread;
+	int idx;
+
+	for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
+		if (desc_empty((struct n_desc_struct *)(t->tls_array) + idx))
+			return idx + GDT_ENTRY_TLS_MIN;
+	return -ESRCH;
+}
+
+/*
+ * Set a given TLS descriptor:
+ * When you want addresses > 32bit use arch_prctl() 
+ */
+int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info)
+{
+	struct user_desc info;
+	struct n_desc_struct *desc;
+	int cpu, idx;
+
+	if (copy_from_user(&info, u_info, sizeof(info)))
+		return -EFAULT;
+
+	idx = info.entry_number;
+
+	/*
+	 * index -1 means the kernel should try to find and
+	 * allocate an empty descriptor:
+	 */
+	if (idx == -1) {
+		idx = get_free_idx();
+		if (idx < 0)
+			return idx;
+		if (put_user(idx, &u_info->entry_number))
+			return -EFAULT;
+	}
+
+	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+		return -EINVAL;
+
+	desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN;
+
+	/*
+	 * We must not get preempted while modifying the TLS.
+	 */
+	cpu = get_cpu();
+
+	if (LDT_empty(&info)) {
+		desc->a = 0;
+		desc->b = 0;
+	} else {
+		desc->a = LDT_entry_a(&info);
+		desc->b = LDT_entry_b(&info);
+	}
+	if (t == &current->thread)
+		load_TLS(t, cpu);
+
+	put_cpu();
+	return 0;
+}
+
+asmlinkage long sys32_set_thread_area(struct user_desc *u_info)
+{ 
+	return do_set_thread_area(&current->thread, u_info); 
+} 
+
+
+/*
+ * Get the current Thread-Local Storage area:
+ */
+
+#define GET_BASE(desc) ( \
+	(((desc)->a >> 16) & 0x0000ffff) | \
+	(((desc)->b << 16) & 0x00ff0000) | \
+	( (desc)->b        & 0xff000000)   )
+
+#define GET_LIMIT(desc) ( \
+	((desc)->a & 0x0ffff) | \
+	 ((desc)->b & 0xf0000) )
+	
+#define GET_32BIT(desc)		(((desc)->b >> 23) & 1)
+#define GET_CONTENTS(desc)	(((desc)->b >> 10) & 3)
+#define GET_WRITABLE(desc)	(((desc)->b >>  9) & 1)
+#define GET_LIMIT_PAGES(desc)	(((desc)->b >> 23) & 1)
+#define GET_PRESENT(desc)	(((desc)->b >> 15) & 1)
+#define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)
+#define GET_LONGMODE(desc)	(((desc)->b >> 21) & 1)
+
+int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info)
+{
+	struct user_desc info;
+	struct n_desc_struct *desc;
+	int idx;
+
+	if (get_user(idx, &u_info->entry_number))
+		return -EFAULT;
+	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+		return -EINVAL;
+
+	desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN;
+
+	memset(&info, 0, sizeof(struct user_desc));
+	info.entry_number = idx;
+	info.base_addr = GET_BASE(desc);
+	info.limit = GET_LIMIT(desc);
+	info.seg_32bit = GET_32BIT(desc);
+	info.contents = GET_CONTENTS(desc);
+	info.read_exec_only = !GET_WRITABLE(desc);
+	info.limit_in_pages = GET_LIMIT_PAGES(desc);
+	info.seg_not_present = !GET_PRESENT(desc);
+	info.useable = GET_USEABLE(desc);
+	info.lm = GET_LONGMODE(desc);
+
+	if (copy_to_user(u_info, &info, sizeof(info)))
+		return -EFAULT;
+	return 0;
+}
+
+asmlinkage long sys32_get_thread_area(struct user_desc *u_info)
+{
+	return do_get_thread_area(&current->thread, u_info);
+} 
+
+
+int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs)
+{
+	struct n_desc_struct *desc;
+	struct user_desc info, *cp;
+	int idx;
+	
+	cp = (void *)childregs->rsi;
+	if (copy_from_user(&info, cp, sizeof(info)))
+		return -EFAULT;
+	if (LDT_empty(&info))
+		return -EINVAL;
+	
+	idx = info.entry_number;
+	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+		return -EINVAL;
+	
+	desc = (struct n_desc_struct *)(p->thread.tls_array) + idx - GDT_ENTRY_TLS_MIN;
+	desc->a = LDT_entry_a(&info);
+	desc->b = LDT_entry_b(&info);
+
+	return 0;
+}
diff -Nru a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
--- a/arch/x86_64/kernel/apic.c	Tue Feb 25 10:47:30 2003
+++ b/arch/x86_64/kernel/apic.c	Sat Mar  8 18:01:10 2003
@@ -981,9 +981,6 @@
 asmlinkage void smp_spurious_interrupt(void)
 {
 	unsigned int v;
-	static unsigned long last_warning; 
-	static unsigned long skipped; 
-
 	irq_enter();
 	/*
 	 * Check if this really is a spurious interrupt and ACK it
@@ -994,8 +991,12 @@
 	if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
 		ack_APIC_irq();
 
+#if 0
+	static unsigned long last_warning; 
+	static unsigned long skipped; 
+
 	/* see sw-dev-man vol 3, chapter 7.4.13.5 */
-	if (last_warning+30*HZ < jiffies) { 
+	if (time_before(last_warning+30*HZ,jiffies)) { 
 		printk(KERN_INFO "spurious APIC interrupt on CPU#%d, %ld skipped.\n",
 		       smp_processor_id(), skipped);
 		last_warning = jiffies; 
@@ -1003,6 +1004,7 @@
 	} else { 
 		skipped++; 
 	} 
+#endif 
 	irq_exit();
 }
 
diff -Nru a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c
--- a/arch/x86_64/kernel/head64.c	Tue Feb 11 06:03:03 2003
+++ b/arch/x86_64/kernel/head64.c	Sun Mar  9 08:28:23 2003
@@ -79,6 +79,9 @@
 	clear_bss();
 	pda_init(0);
 	copy_bootdata(real_mode_data);
+	/* default console: */
+	if (!strstr(saved_command_line, "console="))
+		strcat(saved_command_line, " console=tty0"); 
 	s = strstr(saved_command_line, "earlyprintk="); 
 	if (s != NULL)
 		setup_early_printk(s+12); 
diff -Nru a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
--- a/arch/x86_64/kernel/io_apic.c	Sun Mar  2 18:13:32 2003
+++ b/arch/x86_64/kernel/io_apic.c	Sat Mar  8 18:03:40 2003
@@ -1110,7 +1110,7 @@
  */
 static int __init timer_irq_works(void)
 {
-	unsigned int t1 = jiffies;
+	unsigned long t1 = jiffies;
 
 	local_irq_enable();
 	/* Let ten ticks pass... */
@@ -1123,6 +1123,8 @@
 	 * might have cached one ExtINT interrupt.  Finally, at
 	 * least one tick may be lost due to delays.
 	 */
+
+	/* jiffies wrap? */
 	if (jiffies - t1 > 4)
 		return 1;
 	return 0;
diff -Nru a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
--- a/arch/x86_64/kernel/irq.c	Tue Feb 25 01:39:01 2003
+++ b/arch/x86_64/kernel/irq.c	Sat Mar  8 14:50:43 2003
@@ -135,6 +135,7 @@
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_printf(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
@@ -143,9 +144,10 @@
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -156,11 +158,13 @@
 				kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
-		seq_printf(p, "  %s", action->name);
 
+		seq_printf(p, "  %s", action->name);
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "NMI: ");
 	for (j = 0; j < NR_CPUS; j++)
diff -Nru a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
--- a/arch/x86_64/kernel/process.c	Sat Feb 22 08:39:06 2003
+++ b/arch/x86_64/kernel/process.c	Sun Mar  9 16:22:16 2003
@@ -19,46 +19,37 @@
 #define __KERNEL_SYSCALLS__
 #include <stdarg.h>
 
-#include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/elfcore.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/vmalloc.h>
 #include <linux/user.h>
 #include <linux/module.h>
 #include <linux/a.out.h>
 #include <linux/interrupt.h>
-#include <linux/config.h>
 #include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/ctype.h>
-#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/ptrace.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/ldt.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
-#include <asm/desc.h>
 #include <asm/mmu_context.h>
 #include <asm/pda.h>
 #include <asm/prctl.h>
 #include <asm/kdebug.h>
-
-#include <linux/irq.h>
+#include <asm/desc.h>
+#include <asm/proto.h>
+#include <asm/ia32.h>
 
 asmlinkage extern void ret_from_fork(void);
-int sys_arch_prctl(int code, unsigned long addr);
 
 unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED;
 
@@ -245,10 +236,36 @@
 	}
 }
 
+static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
+{
+	struct user_desc ud = { 
+		.base_addr = addr,
+		.limit = 0xfffff,
+		.seg_32bit = 1,
+		.limit_in_pages = 1,
+		.useable = 1,
+	};
+	struct n_desc_struct *desc = (void *)t->thread.tls_array;
+	desc += tls;
+	desc->a = LDT_entry_a(&ud); 
+	desc->b = LDT_entry_b(&ud); 
+}
+
+static inline u32 read_32bit_tls(struct task_struct *t, int tls)
+{
+	struct desc_struct *desc = (void *)t->thread.tls_array;
+	desc += tls;
+	return desc->base0 | 
+		(((u32)desc->base1) << 16) | 
+		(((u32)desc->base2) << 24);
+}
+
+
 int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, 
 		unsigned long unused,
 	struct task_struct * p, struct pt_regs * regs)
 {
+	int err;
 	struct pt_regs * childregs;
 	struct task_struct *me = current;
 
@@ -265,7 +282,7 @@
 
 	p->thread.rsp = (unsigned long) childregs;
 	p->thread.rsp0 = (unsigned long) (childregs+1);
-	p->thread.userrsp = current->thread.userrsp; 
+	p->thread.userrsp = me->thread.userrsp; 
 
 	p->thread.rip = (unsigned long) ret_from_fork;
 
@@ -277,8 +294,8 @@
 	asm("movl %%es,%0" : "=m" (p->thread.es));
 	asm("movl %%ds,%0" : "=m" (p->thread.ds));
 
-	unlazy_fpu(current);	
-	p->thread.i387 = current->thread.i387;
+	unlazy_fpu(me);	
+	p->thread.i387 = me->thread.i387;
 
 	if (unlikely(me->thread.io_bitmap_ptr != NULL)) { 
 		p->thread.io_bitmap_ptr = kmalloc((IO_BITMAP_SIZE+1)*4, GFP_KERNEL);
@@ -292,27 +309,20 @@
 	 * Set a new TLS for the child thread?
 	 */
 	if (clone_flags & CLONE_SETTLS) {
-		struct n_desc_struct *desc;
-		struct user_desc info;
-		int idx;
-
-		if (copy_from_user(&info, test_thread_flag(TIF_IA32) ? 
-								  (void *)childregs->rsi : 
-								  (void *)childregs->rdx, sizeof(info)))
-			return -EFAULT;
-		if (LDT_empty(&info))
-			return -EINVAL;
-
-		idx = info.entry_number;
-		if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
-			return -EINVAL;
-
-		desc = (struct n_desc_struct *)(p->thread.tls_array) + idx - GDT_ENTRY_TLS_MIN;
-		desc->a = LDT_entry_a(&info);
-		desc->b = LDT_entry_b(&info);
-	}
-
-	return 0;
+#ifdef CONFIG_IA32_EMULATION
+		if (test_thread_flag(TIF_IA32))
+			err = ia32_child_tls(p, childregs); 
+		else 			
+#endif	 
+			err = do_arch_prctl(p, ARCH_SET_FS, childregs->r10); 
+		if (err) 
+			goto out;
+	}
+	err = 0;
+out:
+	if (err && p->thread.io_bitmap_ptr)
+		kfree(p->thread.io_bitmap_ptr);
+	return err;
 }
 
 /*
@@ -422,7 +432,7 @@
 	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
 		if (next->io_bitmap_ptr) {
 			/*
-			 * 4 cachelines copy ... not good, but not that
+			 * 2 cachelines copy ... not good, but not that
 			 * bad either. Anyone got something better?
 			 * This only affects processes which use ioperm().
 			 */
@@ -537,19 +547,35 @@
 #undef last_sched
 #undef first_sched
 
-int sys_arch_prctl(int code, unsigned long addr)
+long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
 { 
 	int ret = 0; 
+	int doit = task == current;
+	int cpu;
 
 	switch (code) { 
 	case ARCH_SET_GS:
 		if (addr >= TASK_SIZE) 
 			return -EPERM; 
-		get_cpu();
+		cpu = get_cpu();
+		/* handle small bases via the GDT because that's faster to 
+		   switch. */
+		if (addr <= 0xffffffff) {  
+			set_32bit_tls(task, GS_TLS, addr); 
+			if (doit) { 
+				load_TLS(&task->thread, cpu);
+				load_gs_index(GS_TLS_SEL); 
+			}
+			task->thread.gsindex = GS_TLS_SEL; 
+			task->thread.gs = 0;
+		} else { 
+			task->thread.gsindex = 0;
+			task->thread.gs = addr;
+			if (doit) {
 		load_gs_index(0);
-		current->thread.gsindex = 0;
-		current->thread.gs = addr;
 		ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr); 
+			} 
+		}
 		put_cpu();
 		break;
 	case ARCH_SET_FS:
@@ -557,22 +583,51 @@
 		   with gs */
 		if (addr >= TASK_SIZE)
 			return -EPERM; 
-		get_cpu();
+		cpu = get_cpu();
+		/* handle small bases via the GDT because that's faster to 
+		   switch. */
+		if (addr <= 0xffffffff) { 
+			set_32bit_tls(task, FS_TLS, addr);
+			if (doit) { 
+				load_TLS(&task->thread, cpu); 
+				asm volatile("movl %0,%%fs" :: "r" (FS_TLS_SEL));
+			}
+			task->thread.fsindex = FS_TLS_SEL;
+			task->thread.fs = 0;
+		} else { 
+			task->thread.fsindex = 0;
+			task->thread.fs = addr;
+			if (doit) {
+				/* set the selector to 0 to not confuse
+				   __switch_to */
 		asm volatile("movl %0,%%fs" :: "r" (0));
-		current->thread.fsindex = 0;
-		current->thread.fs = addr;
 		ret = checking_wrmsrl(MSR_FS_BASE, addr); 
+			}
+		}
 		put_cpu();
 		break;
-
-		/* Returned value may not be correct when the user changed fs/gs */ 
-	case ARCH_GET_FS:
-		ret = put_user(current->thread.fs, (unsigned long *)addr); 
+	case ARCH_GET_FS: { 
+		unsigned long base; 
+		if (task->thread.fsindex == FS_TLS_SEL)
+			base = read_32bit_tls(task, FS_TLS);
+		else if (doit) {
+			rdmsrl(MSR_FS_BASE, base);
+		} else
+			base = task->thread.fs;
+		ret = put_user(base, (unsigned long *)addr); 
 		break; 
-
-	case ARCH_GET_GS: 
-		ret = put_user(current->thread.gs, (unsigned long *)addr); 
+	}
+	case ARCH_GET_GS: { 
+		unsigned long base;
+		if (task->thread.gsindex == GS_TLS_SEL)
+			base = read_32bit_tls(task, GS_TLS);
+		else if (doit) {
+			rdmsrl(MSR_KERNEL_GS_BASE, base);
+		} else
+			base = task->thread.gs;
+		ret = put_user(base, (unsigned long *)addr); 
 		break;
+	}
 
 	default:
 		ret = -EINVAL;
@@ -582,131 +637,9 @@
 	return ret;	
 } 
 
-/*
- * sys_alloc_thread_area: get a yet unused TLS descriptor index.
- */
-static int get_free_idx(void)
-{
-	struct thread_struct *t = &current->thread;
-	int idx;
-
-	for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
-		if (desc_empty((struct n_desc_struct *)(t->tls_array) + idx))
-			return idx + GDT_ENTRY_TLS_MIN;
-	return -ESRCH;
-}
-
-/*
- * Set a given TLS descriptor:
- * When you want addresses > 32bit use arch_prctl() 
- */
-int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info)
-{
-	struct user_desc info;
-	struct n_desc_struct *desc;
-	int cpu, idx;
-
-	if (copy_from_user(&info, u_info, sizeof(info)))
-		return -EFAULT;
-
-	idx = info.entry_number;
-
-	/*
-	 * index -1 means the kernel should try to find and
-	 * allocate an empty descriptor:
-	 */
-	if (idx == -1) {
-		idx = get_free_idx();
-		if (idx < 0)
-			return idx;
-		if (put_user(idx, &u_info->entry_number))
-			return -EFAULT;
-	}
-
-	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
-		return -EINVAL;
-
-	desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN;
-
-	/*
-	 * We must not get preempted while modifying the TLS.
-	 */
-	cpu = get_cpu();
-
-	if (LDT_empty(&info)) {
-		desc->a = 0;
-		desc->b = 0;
-	} else {
-		desc->a = LDT_entry_a(&info);
-		desc->b = LDT_entry_b(&info);
-	}
-	if (t == &current->thread)
-	load_TLS(t, cpu);
-
-	put_cpu();
-	return 0;
-}
-
-asmlinkage int sys_set_thread_area(struct user_desc *u_info)
-{ 
-	return do_set_thread_area(&current->thread, u_info); 
-} 
-
-
-/*
- * Get the current Thread-Local Storage area:
- */
-
-#define GET_BASE(desc) ( \
-	(((desc)->a >> 16) & 0x0000ffff) | \
-	(((desc)->b << 16) & 0x00ff0000) | \
-	( (desc)->b        & 0xff000000)   )
-
-#define GET_LIMIT(desc) ( \
-	((desc)->a & 0x0ffff) | \
-	 ((desc)->b & 0xf0000) )
-	
-#define GET_32BIT(desc)		(((desc)->b >> 23) & 1)
-#define GET_CONTENTS(desc)	(((desc)->b >> 10) & 3)
-#define GET_WRITABLE(desc)	(((desc)->b >>  9) & 1)
-#define GET_LIMIT_PAGES(desc)	(((desc)->b >> 23) & 1)
-#define GET_PRESENT(desc)	(((desc)->b >> 15) & 1)
-#define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)
-#define GET_LONGMODE(desc)	(((desc)->b >> 21) & 1)
-
-int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info)
-{
-	struct user_desc info;
-	struct n_desc_struct *desc;
-	int idx;
-
-	if (get_user(idx, &u_info->entry_number))
-		return -EFAULT;
-	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
-		return -EINVAL;
-
-	desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN;
-
-	memset(&info, 0, sizeof(struct user_desc));
-	info.entry_number = idx;
-	info.base_addr = GET_BASE(desc);
-	info.limit = GET_LIMIT(desc);
-	info.seg_32bit = GET_32BIT(desc);
-	info.contents = GET_CONTENTS(desc);
-	info.read_exec_only = !GET_WRITABLE(desc);
-	info.limit_in_pages = GET_LIMIT_PAGES(desc);
-	info.seg_not_present = !GET_PRESENT(desc);
-	info.useable = GET_USEABLE(desc);
-	info.lm = GET_LONGMODE(desc);
-
-	if (copy_to_user(u_info, &info, sizeof(info)))
-		return -EFAULT;
-	return 0;
-}
-
-asmlinkage int sys_get_thread_area(struct user_desc *u_info)
+long sys_arch_prctl(int code, unsigned long addr)
 {
-	return do_get_thread_area(&current->thread, u_info);
+	return do_arch_prctl(current, code, addr);
 } 
 
 /* 
diff -Nru a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
--- a/arch/x86_64/kernel/ptrace.c	Sat Feb 15 01:42:03 2003
+++ b/arch/x86_64/kernel/ptrace.c	Sun Mar  9 04:38:18 2003
@@ -26,6 +26,7 @@
 #include <asm/ldt.h>
 #include <asm/desc.h>
 #include <asm/proto.h>
+#include <asm/ia32.h>
 
 /*
  * does not yet catch signals sent when the child dies.
@@ -322,6 +323,13 @@
 		wake_up_process(child);
 		ret = 0;
 		break;
+	}
+
+#ifdef CONFIG_IA32_EMULATION
+		/* This makes only sense with 32bit programs. Allow a
+		   64bit debugger to fully examine them too. Better
+		   don't use it against 64bit processes, use
+		   PTRACE_ARCH_PRCTL instead. */
 	case PTRACE_SET_THREAD_AREA: {
 		int old; 
 		get_user(old,  &((struct user_desc *)data)->entry_number); 
@@ -338,7 +346,13 @@
 		put_user(old,  &((struct user_desc *)data)->entry_number); 
 		break;
 	} 
-	}
+#endif
+		/* normal 64bit interface to access TLS data. 
+		   Works just like arch_prctl, except that the arguments
+		   are reversed. */
+	case PTRACE_ARCH_PRCTL: 
+		ret = do_arch_prctl(child, data, addr);
+		break;
 
 /*
  * make the child exit.  Best I can do is send it a sigkill. 
diff -Nru a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
--- a/arch/x86_64/kernel/setup64.c	Fri Feb 21 08:55:38 2003
+++ b/arch/x86_64/kernel/setup64.c	Wed Mar  5 01:43:54 2003
@@ -22,6 +22,7 @@
 #include <asm/i387.h>
 #include <asm/percpu.h>
 #include <asm/mtrr.h>
+#include <asm/proto.h>
 
 char x86_boot_params[2048] __initdata = {0,};
 
@@ -29,9 +30,6 @@
 
 struct x8664_pda cpu_pda[NR_CPUS] __cacheline_aligned; 
 
-extern void system_call(void); 
-extern void ia32_cstar_target(void); 
-
 extern struct task_struct init_task;
 
 extern unsigned char __per_cpu_start[], __per_cpu_end[]; 
@@ -130,6 +128,24 @@
 #define EXCEPTION_STK_ORDER 0 /* >= N_EXCEPTION_STACKS*EXCEPTION_STKSZ */
 char boot_exception_stacks[N_EXCEPTION_STACKS*EXCEPTION_STKSZ];
 
+void syscall_init(void)
+{
+	/* 
+	 * LSTAR and STAR live in a bit strange symbiosis.
+	 * They both write to the same internal register. STAR allows to set CS/DS
+	 * but only a 32bit target. LSTAR sets the 64bit rip. 	 
+	 */ 
+	wrmsrl(MSR_STAR,  ((u64)__USER32_CS)<<48  | ((u64)__KERNEL_CS)<<32); 
+	wrmsrl(MSR_LSTAR, system_call); 
+
+#ifdef CONFIG_IA32_EMULATION   		
+	wrmsrl(MSR_CSTAR, ia32_cstar_target); 
+#endif
+
+	/* Flags to clear on syscall */
+	wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000); 
+}
+
 /*
  * cpu_init() initializes state that is per-CPU. Some data is already
  * initialized (naturally) in the bootstrap process, such as the GDT
@@ -188,20 +204,7 @@
 
 	asm volatile("pushfq ; popq %%rax ; btr $14,%%rax ; pushq %%rax ; popfq" ::: "eax");
 
-	/* 
-	 * LSTAR and STAR live in a bit strange symbiosis.
-	 * They both write to the same internal register. STAR allows to set CS/DS
-	 * but only a 32bit target. LSTAR sets the 64bit rip. 	 
-	 */ 
-	wrmsrl(MSR_STAR,  ((u64)__USER32_CS)<<48  | ((u64)__KERNEL_CS)<<32); 
-	wrmsrl(MSR_LSTAR, system_call); 
-
-#ifdef CONFIG_IA32_EMULATION   		
-	wrmsrl(MSR_CSTAR, ia32_cstar_target); 
-#endif
-
-	/* Flags to clear on syscall */
-	wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000); 
+	syscall_init();
 
 	wrmsrl(MSR_FS_BASE, 0);
 	wrmsrl(MSR_KERNEL_GS_BASE, 0);
diff -Nru a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
--- a/arch/x86_64/kernel/signal.c	Tue Feb 11 02:37:45 2003
+++ b/arch/x86_64/kernel/signal.c	Wed Mar  5 01:43:54 2003
@@ -96,14 +96,6 @@
 
 #define COPY(x)		err |= __get_user(regs->x, &sc->x)
 
-	{ 
-		unsigned int seg; 
-		err |= __get_user(seg, &sc->gs); 
-		load_gs_index(seg); 
-		err |= __get_user(seg, &sc->fs);
-		loadsegment(fs,seg);
-	}
-
 	COPY(rdi); COPY(rsi); COPY(rbp); COPY(rsp); COPY(rbx);
 	COPY(rdx); COPY(rcx); COPY(rip);
 	COPY(r8);
@@ -189,13 +181,10 @@
 static inline int
 setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me)
 {
-	int tmp, err = 0;
+	int err = 0;
 
-	tmp = 0;
-	__asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
-	err |= __put_user(tmp, (unsigned int *)&sc->gs);
-	__asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp));
-	err |= __put_user(tmp, (unsigned int *)&sc->fs);
+	err |= __put_user(0, &sc->gs);
+	err |= __put_user(0, &sc->fs);
 
 	err |= __put_user(regs->rdi, &sc->rdi);
 	err |= __put_user(regs->rsi, &sc->rsi);
diff -Nru a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c
--- a/arch/x86_64/kernel/suspend.c	Fri Dec 20 21:36:57 2002
+++ b/arch/x86_64/kernel/suspend.c	Wed Mar  5 01:43:54 2003
@@ -26,6 +26,7 @@
 #include <asm/acpi.h>
 #include <asm/tlbflush.h>
 #include <asm/io.h>
+#include <asm/proto.h>
 
 static struct saved_context saved_context;
 
@@ -58,10 +59,9 @@
 	asm volatile ("movw %%gs, %0" : "=m" (saved_context.gs));
 	asm volatile ("movw %%ss, %0" : "=m" (saved_context.ss));
 
-	asm volatile ("swapgs");
-	rdmsrl(0xc0000100, saved_context.fs_base);
-	rdmsrl(0xc0000101, saved_context.gs_base);
-	asm volatile ("swapgs");
+	rdmsrl(MSR_FS_BASE, saved_context.fs_base);
+	rdmsrl(MSR_GS_BASE, saved_context.gs_base);
+	rdmsrl(MSR_KERNEL_GS_BASE, saved_context.gs_kernel_base);
 
 	/*
 	 * control registers 
@@ -99,10 +99,9 @@
 	load_gs_index(saved_context.gs);
 	asm volatile ("movw %0, %%ss" :: "r" (saved_context.ss));
 
-	asm volatile ("swapgs");
-	wrmsrl(0xc0000100, saved_context.fs_base);
-	wrmsrl(0xc0000101, saved_context.gs_base);
-	asm volatile ("swapgs");
+	wrmsrl(MSR_FS_BASE, saved_context.fs_base);
+	wrmsrl(MSR_GS_BASE, saved_context.gs_base);
+	wrmsrl(MSR_KERNEL_GS_BASE, saved_context.gs_kernel_base);
 
 	/*
 	 * now restore the descriptor tables to their proper values
diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
--- a/arch/x86_64/kernel/time.c	Mon Feb 24 23:13:09 2003
+++ b/arch/x86_64/kernel/time.c	Sun Mar  9 04:26:46 2003
@@ -30,7 +30,7 @@
 #include <asm/apic.h>
 #endif
 
-u64 jiffies_64;
+u64 jiffies_64 = INITIAL_JIFFIES;
 
 extern int using_apic_timer;
 
@@ -47,8 +47,8 @@
 
 struct hpet_data __hpet __section_hpet;			/* address, quotient, trigger, hz */
 
-volatile unsigned long __jiffies __section_jiffies;
-unsigned long __wall_jiffies __section_wall_jiffies;
+volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
+unsigned long __wall_jiffies __section_wall_jiffies = INITIAL_JIFFIES;
 struct timespec __xtime __section_xtime;
 struct timezone __sys_tz __section_sys_tz;
 
diff -Nru a/arch/x86_64/lib/getuser.S b/arch/x86_64/lib/getuser.S
--- a/arch/x86_64/lib/getuser.S	Mon Feb 11 00:16:29 2002
+++ b/arch/x86_64/lib/getuser.S	Sun Mar  9 16:12:06 2003
@@ -30,7 +30,7 @@
 #include <asm/thread_info.h>
 
 	.text
-	.p2align
+	.p2align 4
 .globl __get_user_1
 __get_user_1:	
 	GET_THREAD_INFO(%rbx)
@@ -40,7 +40,7 @@
 	xorq %rax,%rax
 	ret
 
-	.p2align	
+	.p2align 4
 .globl __get_user_2
 __get_user_2:
 	GET_THREAD_INFO(%rbx) 
@@ -52,7 +52,7 @@
 	xorq %rax,%rax
 	ret
 
-	.p2align
+	.p2align 4
 .globl __get_user_4
 __get_user_4:
 	GET_THREAD_INFO(%rbx) 
@@ -64,7 +64,7 @@
 	xorq %rax,%rax
 	ret
 
-	.p2align
+	.p2align 4
 .globl __get_user_8
 __get_user_8:
 	GET_THREAD_INFO(%rbx) 
diff -Nru a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c
--- a/arch/x86_64/mm/pageattr.c	Sun Mar  2 18:13:32 2003
+++ b/arch/x86_64/mm/pageattr.c	Wed Mar  5 03:08:42 2003
@@ -53,7 +53,7 @@
 
 static void flush_kernel_map(void *address) 
 {
-	if (address && cpu_has_clflush) {
+	if (0 && address && cpu_has_clflush) {
 		/* is this worth it? */ 
 		int i;
 		for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) 
diff -Nru a/arch/x86_64/pci/direct.c b/arch/x86_64/pci/direct.c
--- a/arch/x86_64/pci/direct.c	Fri Aug 30 06:59:56 2002
+++ b/arch/x86_64/pci/direct.c	Wed Mar  5 03:01:42 2003
@@ -196,21 +196,35 @@
 static int __devinit pci_sanity_check(struct pci_ops *o)
 {
 	u32 x = 0;
-	struct pci_bus bus;		/* Fake bus and device */
-	struct pci_dev dev;
+	int retval = 0;
+	struct pci_bus *bus;		/* Fake bus and device */
+	struct pci_dev *dev;
 
 	if (pci_probe & PCI_NO_CHECKS)
 		return 1;
-	bus.number = 0;
-	dev.bus = &bus;
-	for(dev.devfn=0; dev.devfn < 0x100; dev.devfn++)
-		if ((!o->read(&bus, dev.devfn, PCI_CLASS_DEVICE, 2, &x) &&
+
+	bus = kmalloc(sizeof(*bus), GFP_ATOMIC);
+	dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
+	if (!bus || !dev) {
+		printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__);
+		goto exit;
+	}
+
+	bus->number = 0;
+	dev->bus = bus;
+	for(dev->devfn=0; dev->devfn < 0x100; dev->devfn++)
+		if ((!o->read(bus, dev->devfn, PCI_CLASS_DEVICE, 2, &x) &&
 		     (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) ||
-		    (!o->read(&bus, dev.devfn, PCI_VENDOR_ID, 2, &x) &&
-		     (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)))
-			return 1;
+		    (!o->read(bus, dev->devfn, PCI_VENDOR_ID, 2, &x) &&
+		     (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ))) {
+			retval = 1;
+			goto exit;
+		}
 	DBG("PCI: Sanity check failed\n");
-	return 0;
+exit:
+	kfree(dev);
+	kfree(bus);
+	return retval;
 }
 
 static int __init pci_direct_init(void)
@@ -218,7 +232,7 @@
 	unsigned int tmp;
 	unsigned long flags;
 
-	local_save_flags(flags); local_irq_disable();
+	local_irq_save(flags);
 
 	/*
 	 * Check if configuration type 1 works.
@@ -261,7 +275,6 @@
 	}
 
 	local_irq_restore(flags);
-	pci_root_ops = NULL;
 	return 0;
 }
 
diff -Nru a/arch/x86_64/pci/irq.c b/arch/x86_64/pci/irq.c
--- a/arch/x86_64/pci/irq.c	Fri Nov 15 01:01:33 2002
+++ b/arch/x86_64/pci/irq.c	Wed Mar  5 03:54:28 2003
@@ -109,7 +109,7 @@
 		 */
 		if (busmap[i] && pci_scan_bus(i, pci_root_bus->ops, NULL))
 			printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i);
-	pcibios_last_bus = -1;
+	//pcibios_last_bus = -1;
 }
 
 /*
@@ -291,14 +291,14 @@
 	{
 		irq = read_config_nybble(router, 0x56, pirq - 1);
 	}
-	printk(KERN_INFO "AMD: dev %04x:%04x, router pirq : %d get irq : %2d\n",
+	printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n",
 		dev->vendor, dev->device, pirq, irq);
 	return irq;
 }
 
 static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
 {
-	printk(KERN_INFO "AMD: dev %04x:%04x, router pirq : %d SET irq : %2d\n", 
+	printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n", 
 		dev->vendor, dev->device, pirq, irq);
 	if (pirq <= 4)
 	{
diff -Nru a/arch/x86_64/pci/legacy.c b/arch/x86_64/pci/legacy.c
--- a/arch/x86_64/pci/legacy.c	Wed Oct 30 02:51:28 2002
+++ b/arch/x86_64/pci/legacy.c	Wed Mar  5 03:55:39 2003
@@ -1,8 +1,8 @@
 /*
  * legacy.c - traditional, old school PCI bus probing
  */
-#include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/pci.h>
 #include "pci.h"
 
 /*
@@ -12,28 +12,39 @@
 void __devinit pcibios_fixup_peer_bridges(void)
 {
 	int n;
-	struct pci_bus bus;
-	struct pci_dev dev;
+	struct pci_bus *bus;
+	struct pci_dev *dev;
 	u16 l;
 
-	if (pcibios_last_bus <= 0 || pcibios_last_bus > 0xff)
+	if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
 		return;
 	DBG("PCI: Peer bridge fixup\n");
+
+	bus = kmalloc(sizeof(*bus), GFP_ATOMIC);
+	dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
+	if (!bus || !dev) {
+		printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__);
+		goto exit;
+	}
+
 	for (n=0; n <= pcibios_last_bus; n++) {
 		if (pci_bus_exists(&pci_root_buses, n))
 			continue;
-		bus.number = n;
-		bus.ops = pci_root_ops;
-		dev.bus = &bus;
-		for(dev.devfn=0; dev.devfn<256; dev.devfn += 8)
-			if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) &&
+		bus->number = n;
+		bus->ops = pci_root_ops;
+		dev->bus = bus;
+		for (dev->devfn=0; dev->devfn<256; dev->devfn += 8)
+			if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) &&
 			    l != 0x0000 && l != 0xffff) {
-				DBG("Found device at %02x:%02x [%04x]\n", n, dev.devfn, l);
+				DBG("Found device at %02x:%02x [%04x]\n", n, dev->devfn, l);
 				printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
 				pci_scan_bus(n, pci_root_ops, NULL);
 				break;
 			}
 	}
+exit:
+	kfree(dev);
+	kfree(bus);
 }
 
 static int __init pci_legacy_init(void)
diff -Nru a/arch/x86_64/pci/pci.h b/arch/x86_64/pci/pci.h
--- a/arch/x86_64/pci/pci.h	Wed Oct 30 02:47:30 2002
+++ b/arch/x86_64/pci/pci.h	Wed Mar  5 03:53:36 2003
@@ -67,7 +67,6 @@
 extern int pcibios_scanned;
 extern spinlock_t pci_config_lock;
 
-void pcibios_fixup_irqs(void);
 int pirq_enable_irq(struct pci_dev *dev);
 
 extern int (*pcibios_enable_irq)(struct pci_dev *dev);
diff -Nru a/arch/x86_64/vmlinux.lds.S b/arch/x86_64/vmlinux.lds.S
--- a/arch/x86_64/vmlinux.lds.S	Tue Feb 11 03:00:35 2003
+++ b/arch/x86_64/vmlinux.lds.S	Fri Feb 14 17:50:07 2003
@@ -98,6 +98,9 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
diff -Nru a/crypto/api.c b/crypto/api.c
--- a/crypto/api.c	Mon Dec 30 13:39:58 2002
+++ b/crypto/api.c	Sat Mar  8 11:46:18 2003
@@ -128,8 +128,6 @@
 
 	memset(tfm, 0, sizeof(*tfm));
 	
-	tfm->crt_ctx = (void*) &tfm[1];
-
 	tfm->__crt_alg = alg;
 	
 	if (crypto_init_flags(tfm, flags))
diff -Nru a/crypto/cipher.c b/crypto/cipher.c
--- a/crypto/cipher.c	Sun Feb  2 23:34:59 2003
+++ b/crypto/cipher.c	Sat Mar  8 11:46:18 2003
@@ -23,7 +23,8 @@
 #include "internal.h"
 
 typedef void (cryptfn_t)(void *, u8 *, const u8 *);
-typedef void (procfn_t)(struct crypto_tfm *, u8 *, u8*, cryptfn_t, int enc);
+typedef void (procfn_t)(struct crypto_tfm *, u8 *,
+                        u8*, cryptfn_t, int enc, void *);
 
 struct scatter_walk {
 	struct scatterlist	*sg;
@@ -34,6 +35,13 @@
 	unsigned int		offset;
 };
 
+enum km_type crypto_km_types[] = {
+	KM_USER0,
+	KM_USER1,
+	KM_SOFTIRQ0,
+	KM_SOFTIRQ1,
+};
+
 static inline void xor_64(u8 *a, const u8 *b)
 {
 	((u32 *)a)[0] ^= ((u32 *)b)[0];
@@ -159,7 +167,8 @@
 static int crypt(struct crypto_tfm *tfm,
 		 struct scatterlist *dst,
 		 struct scatterlist *src,
-                 unsigned int nbytes, cryptfn_t crfn, procfn_t prfn, int enc)
+                 unsigned int nbytes, cryptfn_t crfn,
+                 procfn_t prfn, int enc, void *info)
 {
 	struct scatter_walk walk_in, walk_out;
 	const unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
@@ -189,7 +198,7 @@
 
 		copy_chunks(src_p, &walk_in, bsize, 0);
 
-		prfn(tfm, dst_p, src_p, crfn, enc);
+		prfn(tfm, dst_p, src_p, crfn, enc, info);
 
 		scatter_done(&walk_in, 0, nbytes);
 
@@ -204,35 +213,35 @@
 }
 
 static void cbc_process(struct crypto_tfm *tfm,
-                        u8 *dst, u8 *src, cryptfn_t fn, int enc)
+                        u8 *dst, u8 *src, cryptfn_t fn, int enc, void *info)
 {
+	u8 *iv = info;
+	
 	/* Null encryption */
-	if (!tfm->crt_cipher.cit_iv)
+	if (!iv)
 		return;
 		
 	if (enc) {
-		tfm->crt_u.cipher.cit_xor_block(tfm->crt_cipher.cit_iv, src);
-		fn(tfm->crt_ctx, dst, tfm->crt_cipher.cit_iv);
-		memcpy(tfm->crt_cipher.cit_iv, dst,
-		       crypto_tfm_alg_blocksize(tfm));
+		tfm->crt_u.cipher.cit_xor_block(iv, src);
+		fn(crypto_tfm_ctx(tfm), dst, iv);
+		memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm));
 	} else {
 		const int need_stack = (src == dst);
 		u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0];
 		u8 *buf = need_stack ? stack : dst;
 		
-		fn(tfm->crt_ctx, buf, src);
-		tfm->crt_u.cipher.cit_xor_block(buf, tfm->crt_cipher.cit_iv);
-		memcpy(tfm->crt_cipher.cit_iv, src,
-		       crypto_tfm_alg_blocksize(tfm));
+		fn(crypto_tfm_ctx(tfm), buf, src);
+		tfm->crt_u.cipher.cit_xor_block(buf, iv);
+		memcpy(iv, src, crypto_tfm_alg_blocksize(tfm));
 		if (buf != dst)
 			memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm));
 	}
 }
 
 static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
-                        cryptfn_t fn, int enc)
+                        cryptfn_t fn, int enc, void *info)
 {
-	fn(tfm->crt_ctx, dst, src);
+	fn(crypto_tfm_ctx(tfm), dst, src);
 }
 
 static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
@@ -243,7 +252,7 @@
 		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 		return -EINVAL;
 	} else
-		return cia->cia_setkey(tfm->crt_ctx, key, keylen,
+		return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen,
 		                       &tfm->crt_flags);
 }
 
@@ -252,7 +261,8 @@
                        struct scatterlist *src, unsigned int nbytes)
 {
 	return crypt(tfm, dst, src, nbytes,
-	             tfm->__crt_alg->cra_cipher.cia_encrypt, ecb_process, 1);
+	             tfm->__crt_alg->cra_cipher.cia_encrypt,
+	             ecb_process, 1, NULL);
 }
 
 static int ecb_decrypt(struct crypto_tfm *tfm,
@@ -261,7 +271,8 @@
 		       unsigned int nbytes)
 {
 	return crypt(tfm, dst, src, nbytes,
-	             tfm->__crt_alg->cra_cipher.cia_decrypt, ecb_process, 1);
+	             tfm->__crt_alg->cra_cipher.cia_decrypt,
+	             ecb_process, 1, NULL);
 }
 
 static int cbc_encrypt(struct crypto_tfm *tfm,
@@ -270,7 +281,18 @@
 		       unsigned int nbytes)
 {
 	return crypt(tfm, dst, src, nbytes,
-	             tfm->__crt_alg->cra_cipher.cia_encrypt, cbc_process, 1);
+	             tfm->__crt_alg->cra_cipher.cia_encrypt,
+	             cbc_process, 1, tfm->crt_cipher.cit_iv);
+}
+
+static int cbc_encrypt_iv(struct crypto_tfm *tfm,
+                          struct scatterlist *dst,
+                          struct scatterlist *src,
+                          unsigned int nbytes, u8 *iv)
+{
+	return crypt(tfm, dst, src, nbytes,
+	             tfm->__crt_alg->cra_cipher.cia_encrypt,
+	             cbc_process, 1, iv);
 }
 
 static int cbc_decrypt(struct crypto_tfm *tfm,
@@ -279,7 +301,18 @@
 		       unsigned int nbytes)
 {
 	return crypt(tfm, dst, src, nbytes,
-	             tfm->__crt_alg->cra_cipher.cia_decrypt, cbc_process, 0);
+	             tfm->__crt_alg->cra_cipher.cia_decrypt,
+	             cbc_process, 0, tfm->crt_cipher.cit_iv);
+}
+
+static int cbc_decrypt_iv(struct crypto_tfm *tfm,
+                          struct scatterlist *dst,
+                          struct scatterlist *src,
+                          unsigned int nbytes, u8 *iv)
+{
+	return crypt(tfm, dst, src, nbytes,
+	             tfm->__crt_alg->cra_cipher.cia_decrypt,
+	             cbc_process, 0, iv);
 }
 
 static int nocrypt(struct crypto_tfm *tfm,
@@ -290,6 +323,14 @@
 	return -ENOSYS;
 }
 
+static int nocrypt_iv(struct crypto_tfm *tfm,
+                      struct scatterlist *dst,
+                      struct scatterlist *src,
+                      unsigned int nbytes, u8 *iv)
+{
+	return -ENOSYS;
+}
+
 int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags)
 {
 	u32 mode = flags & CRYPTO_TFM_MODE_MASK;
@@ -318,16 +359,22 @@
 	case CRYPTO_TFM_MODE_CBC:
 		ops->cit_encrypt = cbc_encrypt;
 		ops->cit_decrypt = cbc_decrypt;
+		ops->cit_encrypt_iv = cbc_encrypt_iv;
+		ops->cit_decrypt_iv = cbc_decrypt_iv;
 		break;
 		
 	case CRYPTO_TFM_MODE_CFB:
 		ops->cit_encrypt = nocrypt;
 		ops->cit_decrypt = nocrypt;
+		ops->cit_encrypt_iv = nocrypt_iv;
+		ops->cit_decrypt_iv = nocrypt_iv;
 		break;
 	
 	case CRYPTO_TFM_MODE_CTR:
 		ops->cit_encrypt = nocrypt;
 		ops->cit_decrypt = nocrypt;
+		ops->cit_encrypt_iv = nocrypt_iv;
+		ops->cit_decrypt_iv = nocrypt_iv;
 		break;
 
 	default:
diff -Nru a/crypto/digest.c b/crypto/digest.c
--- a/crypto/digest.c	Sun Feb  2 23:34:59 2003
+++ b/crypto/digest.c	Sat Mar  8 11:46:18 2003
@@ -19,7 +19,7 @@
 
 static void init(struct crypto_tfm *tfm)
 {
-	tfm->__crt_alg->cra_digest.dia_init(tfm->crt_ctx);
+	tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm));
 }
 
 static void update(struct crypto_tfm *tfm,
@@ -29,7 +29,7 @@
 	
 	for (i = 0; i < nsg; i++) {
 		char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset;
-		tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx,
+		tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
 		                                      p, sg[i].length);
 		crypto_kunmap(p, 0);
 		crypto_yield(tfm);
@@ -38,7 +38,7 @@
 
 static void final(struct crypto_tfm *tfm, u8 *out)
 {
-	tfm->__crt_alg->cra_digest.dia_final(tfm->crt_ctx, out);
+	tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
 }
 
 static void digest(struct crypto_tfm *tfm,
@@ -50,7 +50,7 @@
 		
 	for (i = 0; i < nsg; i++) {
 		char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset;
-		tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx,
+		tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
 		                                      p, sg[i].length);
 		crypto_kunmap(p, 0);
 		crypto_yield(tfm);
diff -Nru a/crypto/internal.h b/crypto/internal.h
--- a/crypto/internal.h	Sun Feb  2 23:34:59 2003
+++ b/crypto/internal.h	Sat Mar  8 11:46:18 2003
@@ -18,18 +18,12 @@
 #include <asm/softirq.h>
 #include <asm/kmap_types.h>
 
-static enum km_type km_types[] = {
-	KM_USER0,
-	KM_USER1,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,
-};
+extern enum km_type crypto_km_types[];
 
 static inline enum km_type crypto_kmap_type(int out)
 {
-	return km_types[(in_softirq() ? 2 : 0) + out];
+	return crypto_km_types[(in_softirq() ? 2 : 0) + out];
 }
-	
 
 static inline void *crypto_kmap(struct page *page, int out)
 {
@@ -50,6 +44,11 @@
 static inline u32 crypto_cipher_flags(u32 flags)
 {
 	return flags & (CRYPTO_TFM_MODE_MASK|CRYPTO_TFM_REQ_WEAK_KEY);
+}
+
+static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm)
+{
+	return (void *)&tfm[1];
 }
 
 struct crypto_alg *crypto_alg_lookup(const char *name);
diff -Nru a/drivers/Makefile b/drivers/Makefile
--- a/drivers/Makefile	Sat Feb 15 01:15:00 2003
+++ b/drivers/Makefile	Mon Mar 10 22:34:21 2003
@@ -11,9 +11,13 @@
 # PnP must come after ACPI since it will eventually need to check if acpi
 # was used and do nothing if so
 obj-$(CONFIG_PNP)		+= pnp/
+
+# char/ comes before serial/ etc so that the VT console is the boot-time
+# default.
+obj-y				+= char/
 obj-y				+= serial/
 obj-$(CONFIG_PARPORT)		+= parport/
-obj-y				+= base/ char/ block/ misc/ net/ media/
+obj-y				+= base/ block/ misc/ net/ media/
 obj-$(CONFIG_NUBUS)		+= nubus/
 obj-$(CONFIG_ATM)		+= atm/
 obj-$(CONFIG_IDE)		+= ide/
diff -Nru a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
--- a/drivers/acorn/block/fd1772.c	Tue Feb 25 10:27:18 2003
+++ b/drivers/acorn/block/fd1772.c	Sat Mar  8 14:50:21 2003
@@ -1539,11 +1539,9 @@
 			goto err_disk;
 	}
 
-	err = register_blkdev(MAJOR_NR, "fd", &floppy_fops);
-	if (err) {
-		printk("Unable to get major %d for floppy\n", MAJOR_NR);
+	err = register_blkdev(MAJOR_NR, "fd");
+	if (err)
 		goto err_disk;
-	}
 
 	err = -EBUSY;
 	if (request_dma(FLOPPY_DMA, "fd1772")) {
diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
--- a/drivers/acorn/block/mfmhd.c	Tue Feb 25 10:27:22 2003
+++ b/drivers/acorn/block/mfmhd.c	Sat Mar  8 14:50:21 2003
@@ -1267,11 +1267,9 @@
 	if (!request_region (mfm_addr, 10, "mfm"))
 		goto out1;
 
-	ret = register_blkdev(MAJOR_NR, "mfm", &mfm_fops);
-	if (ret) {
-		printk("mfm_init: unable to get major number %d\n", MAJOR_NR);
+	ret = register_blkdev(MAJOR_NR, "mfm");
+	if (ret)
 		goto out2;
-	}
 
 	/* Stuff for the assembler routines to get to */
 	hdc63463_baseaddress	= ioaddr(mfm_addr);
diff -Nru a/drivers/acorn/net/ether1.c b/drivers/acorn/net/ether1.c
--- a/drivers/acorn/net/ether1.c	Sun Nov 17 13:36:31 2002
+++ b/drivers/acorn/net/ether1.c	Thu Mar  6 05:00:32 2003
@@ -973,23 +973,6 @@
 	return &priv->stats;
 }
 
-static int
-ether1_set_mac_address(struct net_device *dev, void *p)
-{
-	struct sockaddr *addr = p;
-
-	if (netif_running(dev))
-		return -EBUSY;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
-	/*
-	 * We'll set the MAC address on the chip when we open it.
-	 */
-
-	return 0;
-}
-
 /*
  * Set or clear the multicast filter for this adaptor.
  * num_addrs == -1	Promiscuous mode, receive all packets.
@@ -1062,7 +1045,6 @@
 	dev->hard_start_xmit    = ether1_sendpacket;
 	dev->get_stats		= ether1_getstats;
 	dev->set_multicast_list = ether1_setmulticastlist;
-	dev->set_mac_address	= ether1_set_mac_address;
 	dev->tx_timeout		= ether1_timeout;
 	dev->watchdog_timeo	= 5 * HZ / 100;
 
diff -Nru a/drivers/acorn/net/ether3.c b/drivers/acorn/net/ether3.c
--- a/drivers/acorn/net/ether3.c	Tue Feb 25 10:47:06 2003
+++ b/drivers/acorn/net/ether3.c	Thu Mar  6 05:00:32 2003
@@ -461,23 +461,6 @@
 	return &priv->stats;
 }
 
-static int
-ether3_set_mac_address(struct net_device *dev, void *p)
-{
-	struct sockaddr *addr = p;
-
-	if (netif_running(dev))
-		return -EBUSY;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
-	/*
-	 * We'll set the MAC address on the chip when we open it.
-	 */
-
-	return 0;
-}
-
 /*
  * Set or clear promiscuous/multicast mode filter for this adaptor.
  *
@@ -903,7 +886,6 @@
 	dev->hard_start_xmit	= ether3_sendpacket;
 	dev->get_stats		= ether3_getstats;
 	dev->set_multicast_list	= ether3_setmulticastlist;
-	dev->set_mac_address	= ether3_set_mac_address;
 	dev->tx_timeout		= ether3_timeout;
 	dev->watchdog_timeo	= 5 * HZ / 100;
 
diff -Nru a/drivers/acorn/net/etherh.c b/drivers/acorn/net/etherh.c
--- a/drivers/acorn/net/etherh.c	Sun Nov 17 13:36:32 2002
+++ b/drivers/acorn/net/etherh.c	Thu Mar  6 05:00:33 2003
@@ -482,23 +482,6 @@
 	return 0;
 }
 
-static int
-etherh_set_mac_address(struct net_device *dev, void *p)
-{
-	struct sockaddr *addr = p;
-
-	if (netif_running(dev))
-		return -EBUSY;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
-	/*
-	 * We'll set the MAC address on the chip when we open it.
-	 */
-
-	return 0;
-}
-
 /*
  * Initialisation
  */
@@ -585,7 +568,6 @@
 
 	dev->open		= etherh_open;
 	dev->stop		= etherh_close;
-	dev->set_mac_address	= etherh_set_mac_address;
 	dev->set_config		= etherh_set_config;
 	dev->irq		= ec->irq;
 	dev->base_addr		= ecard_address(ec, ECARD_MEMC, 0);
diff -Nru a/drivers/atm/Makefile b/drivers/atm/Makefile
--- a/drivers/atm/Makefile	Mon Feb  3 14:19:36 2003
+++ b/drivers/atm/Makefile	Sat Mar  8 13:46:23 2003
@@ -46,7 +46,7 @@
 ifeq ($(CONFIG_ATM_FORE200E_SBA),y)
   fore_200e-objs		+= fore200e_sba_fw.o
   ifeq ($(CONFIG_ATM_FORE200E_SBA_DEFAULT_FW),y)
-    CONFIG_ATM_FORE200E_SBA_FW	:= sba200e_ecd.bin2
+    CONFIG_ATM_FORE200E_SBA_FW	:= $(obj)/sba200e_ecd.bin2
   endif
 endif
 
diff -Nru a/drivers/atm/firestream.c b/drivers/atm/firestream.c
--- a/drivers/atm/firestream.c	Tue Feb 25 10:47:34 2003
+++ b/drivers/atm/firestream.c	Thu Mar  6 09:14:50 2003
@@ -1792,7 +1792,7 @@
 		write_fs (dev, RAC, 0);
 
 		/* Manual (AN9, page 6) says ASF1=0 means compare Utopia address
-		 * too.  I can't find ASF1 anywhere. Anyway, we AND with just hte
+		 * too.  I can't find ASF1 anywhere. Anyway, we AND with just the
 		 * other bits, then compare with 0, which is exactly what we
 		 * want. */
 		write_fs (dev, RAM, (1 << (28 - FS155_VPI_BITS - FS155_VCI_BITS)) - 1);
diff -Nru a/drivers/base/platform.c b/drivers/base/platform.c
--- a/drivers/base/platform.c	Tue Mar  4 08:20:34 2003
+++ b/drivers/base/platform.c	Wed Mar  5 15:33:09 2003
@@ -59,12 +59,9 @@
 
 static int platform_match(struct device * dev, struct device_driver * drv)
 {
-	char name[BUS_ID_SIZE];
+	struct platform_device *pdev = container_of(dev, struct platform_device, dev);
 
-	if (sscanf(dev->bus_id,"%s",name))
-		return (strcmp(name,drv->name) == 0);
-
-	return 0;
+	return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
 }
 
 struct bus_type platform_bus_type = {
diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c
--- a/drivers/block/DAC960.c	Mon Feb 10 19:20:39 2003
+++ b/drivers/block/DAC960.c	Sat Mar  8 14:50:22 2003
@@ -13,9 +13,6 @@
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   for complete details.
 
-  The author respectfully requests that any modifications to this software be
-  sent directly to him for evaluation and testing.
-
 */
 
 
@@ -2381,13 +2378,9 @@
   /*
     Register the Block Device Major Number for this DAC960 Controller.
   */
-  if (register_blkdev(MajorNumber, "dac960",
-			    &DAC960_BlockDeviceOperations) < 0)
-    {
-      DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n",
-		   Controller, MajorNumber);
+  if (register_blkdev(MajorNumber, "dac960") < 0)
       return false;
-    }
+
   /*
     Initialize the I/O Request Queue.
   */
diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c
--- a/drivers/block/acsi.c	Thu Nov  7 15:02:52 2002
+++ b/drivers/block/acsi.c	Sat Mar  8 14:50:22 2003
@@ -1613,7 +1613,6 @@
 
 
 int acsi_init( void )
-
 {
 	int err = 0;
 	int i, target, lun;
@@ -1623,8 +1622,7 @@
 #endif
 	if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ACSI))
 		return 0;
-	if (register_blkdev( ACSI_MAJOR, "ad", &acsi_fops )) {
-		printk( KERN_ERR "Unable to get major %d for ACSI\n", ACSI_MAJOR );
+	if (register_blkdev(ACSI_MAJOR, "ad")) {
 		err = -EBUSY;
 		goto out1;
 	}
diff -Nru a/drivers/block/amiflop.c b/drivers/block/amiflop.c
--- a/drivers/block/amiflop.c	Mon Nov 18 07:04:31 2002
+++ b/drivers/block/amiflop.c	Sat Mar  8 14:50:22 2003
@@ -1754,10 +1754,9 @@
 	if (!AMIGAHW_PRESENT(AMI_FLOPPY))
 		return -ENXIO;
 
-	if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) {
-		printk("fd: Unable to get major %d for floppy\n",FLOPPY_MAJOR);
+	if (register_blkdev(FLOPPY_MAJOR,"fd"))
 		return -EBUSY;
-	}
+
 	/*
 	 *  We request DSKPTR, DSKLEN and DSKDATA only, because the other
 	 *  floppy registers are too spreaded over the custom register space
diff -Nru a/drivers/block/ataflop.c b/drivers/block/ataflop.c
--- a/drivers/block/ataflop.c	Mon Nov 11 05:05:00 2002
+++ b/drivers/block/ataflop.c	Sat Mar  8 14:50:22 2003
@@ -1929,10 +1929,8 @@
 		/* Hades doesn't have Atari-compatible floppy */
 		return -ENXIO;
 
-	if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) {
-		printk(KERN_ERR "Unable to get major %d for floppy\n",FLOPPY_MAJOR);
+	if (register_blkdev(FLOPPY_MAJOR,"fd"))
 		return -EBUSY;
-	}
 
 	for (i = 0; i < FD_MAX_UNITS; i++) {
 		unit[i].disk = alloc_disk(1);
diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	Thu Feb 27 17:05:57 2003
+++ b/drivers/block/cciss.c	Sat Mar  8 14:50:22 2003
@@ -2064,7 +2064,7 @@
 	unchar cache_line_size, latency_timer;
 	unchar irq, revision;
 	uint addr[6];
-	__u32 board_id;
+	__u32 board_id, scratchpad = 0;
 	int cfg_offset;
 	int cfg_base_addr;
 	int cfg_base_addr_index;
@@ -2156,6 +2156,20 @@
 #endif /* CCISS_DEBUG */ 
 	c->vaddr = remap_pci_mem(c->paddr, 200);
 
+	/* Wait for the board to become ready.  (PCI hotplug needs this.)
+	 * We poll for up to 120 secs, once per 100ms. */
+	for (i=0; i < 1200; i++) {
+		scratchpad = readl(c->vaddr + SA5_SCRATCHPAD_OFFSET);
+		if (scratchpad == CCISS_FIRMWARE_READY)
+			break;
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ / 10); /* wait 100ms */
+	}
+	if (scratchpad != CCISS_FIRMWARE_READY) {
+		printk(KERN_WARNING "cciss: Board not ready.  Timed out.\n");
+		return -1;
+	}
+
 	/* get the address index number */
 	cfg_base_addr = readl(c->vaddr + SA5_CTCFG_OFFSET);
 	/* I am not prepared to deal with a 64 bit address value */
@@ -2437,14 +2451,12 @@
 		return -ENODEV;
 	}
 
-	if( register_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname, &cciss_fops))
-	{
-		printk(KERN_ERR "cciss:  Unable to get major number "
-			"%d for %s\n", COMPAQ_CISS_MAJOR+i, hba[i]->devname);
+	if (register_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname)) {
 		release_io_mem(hba[i]);
 		free_hba(i);
-		return(-1);
+		return -1;
 	}
+
 	/* make sure the board interrupts are off */
 	hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
 	if( request_irq(hba[i]->intr, do_cciss_intr, 
diff -Nru a/drivers/block/cciss.h b/drivers/block/cciss.h
--- a/drivers/block/cciss.h	Thu Dec  5 08:03:43 2002
+++ b/drivers/block/cciss.h	Mon Mar  3 13:52:06 2003
@@ -95,6 +95,7 @@
 #define SA5_REPLY_INTR_MASK_OFFSET	0x34
 #define SA5_REPLY_PORT_OFFSET		0x44
 #define SA5_INTR_STATUS		0x30
+#define SA5_SCRATCHPAD_OFFSET	0xB0
 
 #define SA5_CTCFG_OFFSET	0xB4
 #define SA5_CTMEM_OFFSET	0xB8
@@ -104,6 +105,7 @@
 #define SA5_INTR_PENDING	0x08
 #define SA5B_INTR_PENDING	0x04
 #define FIFO_EMPTY		0xffffffff	
+#define CCISS_FIRMWARE_READY	0xffff0000 /* value in scratchpad register */
 
 #define  CISS_ERROR_BIT		0x02
 
diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
--- a/drivers/block/cpqarray.c	Tue Feb 25 11:05:27 2003
+++ b/drivers/block/cpqarray.c	Sat Mar  8 14:50:22 2003
@@ -339,11 +339,9 @@
 	for(i=0; i < nr_ctlr; i++) {
 	  	/* If this successful it should insure that we are the only */
 		/* instance of the driver */	
-		if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname, &ida_fops)) {
-                        printk(KERN_ERR "cpqarray: Unable to get major number %d for ida\n",
-                                COMPAQ_SMART2_MAJOR+i);
+		if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname))
                         continue;
-                }
+
 		hba[i]->access.set_intr_mask(hba[i], 0);
 		if (request_irq(hba[i]->intr, do_ida_intr,
 			SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i])) {
diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c
--- a/drivers/block/floppy.c	Tue Feb 18 10:44:43 2003
+++ b/drivers/block/floppy.c	Sat Mar  8 14:50:22 2003
@@ -4232,8 +4232,7 @@
 	}
 
 	devfs_mk_dir (NULL, "floppy", NULL);
-	if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) {
-		printk("Unable to get major %d for floppy\n",FLOPPY_MAJOR);
+	if (register_blkdev(FLOPPY_MAJOR,"fd")) {
 		err = -EBUSY;
 		goto out;
 	}
diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c
--- a/drivers/block/genhd.c	Mon Feb 24 23:13:25 2003
+++ b/drivers/block/genhd.c	Mon Mar 10 11:47:07 2003
@@ -14,10 +14,16 @@
 #include <linux/slab.h>
 #include <linux/kmod.h>
 
+#define MAX_PROBE_HASH 255	/* random */
 
 static struct subsystem block_subsys;
 
-#define MAX_PROBE_HASH 23	/* random */
+/* Can be merged with blk_probe or deleted altogether. Later. */
+static struct blk_major_name {
+	struct blk_major_name *next;
+	int major;
+	char name[16];
+} *major_names[MAX_PROBE_HASH];
 
 static struct blk_probe {
 	struct blk_probe *next;
@@ -30,9 +36,125 @@
 } *probes[MAX_PROBE_HASH];
 
 /* index in the above - for now: assume no multimajor ranges */
+static inline int major_to_index(int major)
+{
+	return major % MAX_PROBE_HASH;
+}
+
 static inline int dev_to_index(dev_t dev)
 {
-	return MAJOR(dev) % MAX_PROBE_HASH;
+	return major_to_index(MAJOR(dev));
+}
+
+const char *__bdevname(dev_t dev)
+{
+	static char buffer[40];
+	char *name = "unknown-block";
+	unsigned int major = MAJOR(dev);
+	unsigned int minor = MINOR(dev);
+	int index = major_to_index(major);
+	struct blk_major_name *n;
+
+	down_read(&block_subsys.rwsem);
+	for (n = major_names[index]; n; n = n->next)
+		if (n->major == major)
+			break;
+	if (n)
+		name = &(n->name[0]);
+	sprintf(buffer, "%s(%u,%u)", name, major, minor);
+	up_read(&block_subsys.rwsem);
+
+	return buffer;
+}
+
+/* get block device names in somewhat random order */
+int get_blkdev_list(char *p)
+{
+	struct blk_major_name *n;
+	int i, len;
+
+	len = sprintf(p, "\nBlock devices:\n");
+
+	down_read(&block_subsys.rwsem);
+	for (i = 0; i < ARRAY_SIZE(major_names); i++) {
+		for (n = major_names[i]; n; n = n->next)
+			len += sprintf(p+len, "%3d %s\n",
+				       n->major, n->name);
+	}
+	up_read(&block_subsys.rwsem);
+
+	return len;
+}
+
+int register_blkdev(unsigned int major, const char *name)
+{
+	struct blk_major_name **n, *p;
+	int index, ret = 0;
+
+	/* temporary */
+	if (major == 0) {
+		down_read(&block_subsys.rwsem);
+		for (index = ARRAY_SIZE(major_names)-1; index > 0; index--)
+			if (major_names[index] == NULL)
+				break;
+		up_read(&block_subsys.rwsem);
+
+		if (index == 0) {
+			printk("register_blkdev: failed to get major for %s\n",
+			       name);
+			return -EBUSY;
+		}
+		ret = major = index;
+	}
+
+	p = kmalloc(sizeof(struct blk_major_name), GFP_KERNEL);
+	if (p == NULL)
+		return -ENOMEM;
+
+	p->major = major;
+	strncpy(p->name, name, sizeof(p->name)-1);
+	p->name[sizeof(p->name)-1] = 0;
+	p->next = 0;
+	index = major_to_index(major);
+
+	down_write(&block_subsys.rwsem);
+	for (n = &major_names[index]; *n; n = &(*n)->next)
+		if ((*n)->major == major)
+			break;
+	if (!*n)
+		*n = p;
+	else
+		ret = -EBUSY;
+	up_write(&block_subsys.rwsem);
+
+	if (ret < 0)
+		printk("register_blkdev: cannot get major %d for %s\n",
+		       major, name);
+
+	return ret;
+}
+
+/* todo: make void - error printk here */
+int unregister_blkdev(unsigned int major, const char *name)
+{
+	struct blk_major_name **n, *p;
+	int index = major_to_index(major);
+	int ret = 0;
+
+	down_write(&block_subsys.rwsem);
+	for (n = &major_names[index]; *n; n = &(*n)->next)
+		if ((*n)->major == major)
+			break;
+	if (!*n || strcmp((*n)->name, name))
+		ret = -EINVAL;
+	else {
+		p = *n;
+		*n = p->next;
+		kfree(p);
+	}
+	up_write(&block_subsys.rwsem);
+
+	return ret;
 }
 
 /*
@@ -48,6 +170,9 @@
 	struct blk_probe *p = kmalloc(sizeof(struct blk_probe), GFP_KERNEL);
 	struct blk_probe **s;
 
+	if (p == NULL)
+		return;
+
 	p->owner = module;
 	p->get = probe;
 	p->lock = lock;
@@ -98,9 +223,9 @@
 
 /**
  * add_gendisk - add partitioning information to kernel list
- * @gp: per-device partitioning information
+ * @disk: per-device partitioning information
  *
- * This function registers the partitioning information in @gp
+ * This function registers the partitioning information in @disk
  * with the kernel.
  */
 void add_disk(struct gendisk *disk)
@@ -318,7 +443,7 @@
 	return (jif / HZ) * 1000 + (jif % HZ) * 1000 / HZ;
 #endif
 }
-static ssize_t disk_stat_read(struct gendisk * disk, char *page)
+static ssize_t disk_stats_read(struct gendisk * disk, char *page)
 {
 	disk_round_stats(disk);
 	return sprintf(page,
@@ -326,14 +451,16 @@
 		"%8u %8u %8llu %8u "
 		"%8u %8u %8u"
 		"\n",
-		disk->reads, disk->read_merges,
-		(unsigned long long)disk->read_sectors,
-		jiffies_to_msec(disk->read_ticks),
-		disk->writes, disk->write_merges,
-		(unsigned long long)disk->write_sectors,
-		jiffies_to_msec(disk->write_ticks),
-		disk->in_flight, jiffies_to_msec(disk->io_ticks),
-		jiffies_to_msec(disk->time_in_queue));
+		disk_stat_read(disk, reads), disk_stat_read(disk, read_merges),
+		(unsigned long long)disk_stat_read(disk, read_sectors),
+		jiffies_to_msec(disk_stat_read(disk, read_ticks)),
+		disk_stat_read(disk, writes), 
+		disk_stat_read(disk, write_merges),
+		(unsigned long long)disk_stat_read(disk, write_sectors),
+		jiffies_to_msec(disk_stat_read(disk, write_ticks)),
+		disk_stat_read(disk, in_flight), 
+		jiffies_to_msec(disk_stat_read(disk, io_ticks)),
+		jiffies_to_msec(disk_stat_read(disk, time_in_queue)));
 }
 static struct disk_attribute disk_attr_dev = {
 	.attr = {.name = "dev", .mode = S_IRUGO },
@@ -349,7 +476,7 @@
 };
 static struct disk_attribute disk_attr_stat = {
 	.attr = {.name = "stat", .mode = S_IRUGO },
-	.show	= disk_stat_read
+	.show	= disk_stats_read
 };
 
 static struct attribute * default_attrs[] = {
@@ -365,6 +492,7 @@
 	struct gendisk *disk = to_disk(kobj);
 	kfree(disk->random);
 	kfree(disk->part);
+	free_disk_stats(disk);
 	kfree(disk);
 }
 
@@ -384,6 +512,10 @@
 	struct gendisk *disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
 	if (disk) {
 		memset(disk, 0, sizeof(struct gendisk));
+		if (!init_disk_stats(disk)) {
+			kfree(disk);
+			return NULL;
+		}
 		if (minors > 1) {
 			int size = (minors - 1) * sizeof(struct hd_struct);
 			disk->part = kmalloc(size, GFP_KERNEL);
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	Tue Feb 25 10:47:06 2003
+++ b/drivers/block/ll_rw_blk.c	Sat Mar  8 14:50:30 2003
@@ -1475,17 +1475,17 @@
 		return;
 
 	if (rw == READ) {
-		rq->rq_disk->read_sectors += nr_sectors;
+		disk_stat_add(rq->rq_disk, read_sectors, nr_sectors);
 		if (!new_io)
-			rq->rq_disk->read_merges++;
+			disk_stat_inc(rq->rq_disk, read_merges);
 	} else if (rw == WRITE) {
-		rq->rq_disk->write_sectors += nr_sectors;
+		disk_stat_add(rq->rq_disk, write_sectors, nr_sectors);
 		if (!new_io)
-			rq->rq_disk->write_merges++;
+			disk_stat_inc(rq->rq_disk, write_merges);
 	}
 	if (new_io) {
 		disk_round_stats(rq->rq_disk);
-		rq->rq_disk->in_flight++;
+		disk_stat_inc(rq->rq_disk, in_flight);
 	}
 }
 
@@ -1525,11 +1525,12 @@
 {
 	unsigned long now = jiffies;
 
-	disk->time_in_queue += disk->in_flight * (now - disk->stamp);
+	disk_stat_add(disk, time_in_queue, 
+			disk_stat_read(disk, in_flight) * (now - disk->stamp));
 	disk->stamp = now;
 
-	if (disk->in_flight)
-		disk->io_ticks += (now - disk->stamp_idle);
+	if (disk_stat_read(disk, in_flight))
+		disk_stat_add(disk, io_ticks, (now - disk->stamp_idle));
 	disk->stamp_idle = now;
 }
 
@@ -1647,7 +1648,7 @@
 
 		if (req->rq_disk) {
 			disk_round_stats(req->rq_disk);
-			req->rq_disk->in_flight--;
+			disk_stat_dec(req->rq_disk, in_flight);
 		}
 
 		__blk_put_request(q, next);
@@ -2199,16 +2200,16 @@
 		unsigned long duration = jiffies - req->start_time;
 		switch (rq_data_dir(req)) {
 		    case WRITE:
-			disk->writes++;
-			disk->write_ticks += duration;
+			disk_stat_inc(disk, writes);
+			disk_stat_add(disk, write_ticks, duration);
 			break;
 		    case READ:
-			disk->reads++;
-			disk->read_ticks += duration;
+			disk_stat_inc(disk, reads);
+			disk_stat_add(disk, read_ticks, duration);
 			break;
 		}
 		disk_round_stats(disk);
-		disk->in_flight--;
+		disk_stat_dec(disk, in_flight);
 	}
 	__blk_put_request(req->q, req);
 }
diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c
--- a/drivers/block/loop.c	Sun Mar  2 18:13:25 2003
+++ b/drivers/block/loop.c	Sat Mar  8 14:50:22 2003
@@ -1017,11 +1017,8 @@
 		max_loop = 8;
 	}
 
-	if (register_blkdev(LOOP_MAJOR, "loop", &lo_fops)) {
-		printk(KERN_WARNING "Unable to get major number %d for loop"
-				    " device\n", LOOP_MAJOR);
+	if (register_blkdev(LOOP_MAJOR, "loop"))
 		return -EIO;
-	}
 
 	devfs_mk_dir(NULL, "loop", NULL);
 
diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c
--- a/drivers/block/nbd.c	Thu Feb 13 09:34:46 2003
+++ b/drivers/block/nbd.c	Sat Mar  8 14:50:22 2003
@@ -564,9 +564,7 @@
 		nbd_dev[i].disk = disk;
 	}
 
-	if (register_blkdev(NBD_MAJOR, "nbd", &nbd_fops)) {
-		printk("Unable to get major number %d for NBD\n",
-		       NBD_MAJOR);
+	if (register_blkdev(NBD_MAJOR, "nbd")) {
 		err = -EIO;
 		goto out;
 	}
diff -Nru a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
--- a/drivers/block/paride/pcd.c	Thu Dec  5 08:07:02 2002
+++ b/drivers/block/paride/pcd.c	Sat Mar  8 14:50:22 2003
@@ -942,8 +942,7 @@
 	/* get the atapi capabilities page */
 	pcd_probe_capabilities();
 
-	if (register_blkdev(major, name, &pcd_bdops)) {
-		printk("pcd: unable to get major number %d\n", major);
+	if (register_blkdev(major, name)) {
 		for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
 			put_disk(cd->disk);
 		return -1;
diff -Nru a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
--- a/drivers/block/paride/pd.c	Thu Dec  5 08:07:21 2002
+++ b/drivers/block/paride/pd.c	Sat Mar  8 14:50:22 2003
@@ -890,10 +890,9 @@
 {
 	if (disable)
 		return -1;
-	if (register_blkdev(major, name, &pd_fops)) {
-		printk("%s: unable to get major number %d\n", name, major);
+	if (register_blkdev(major, name))
 		return -1;
-	}
+
 	blk_init_queue(&pd_queue, do_pd_request, &pd_lock);
 	blk_queue_max_sectors(&pd_queue, cluster);
 
diff -Nru a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
--- a/drivers/block/paride/pf.c	Thu Dec  5 08:06:39 2002
+++ b/drivers/block/paride/pf.c	Sat Mar  8 14:50:22 2003
@@ -957,8 +957,7 @@
 		return -1;
 	pf_busy = 0;
 
-	if (register_blkdev(major, name, &pf_fops)) {
-		printk("pf_init: unable to get major number %d\n", major);
+	if (register_blkdev(major, name)) {
 		for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++)
 			put_disk(pf->disk);
 		return -1;
@@ -969,6 +968,7 @@
 
 	for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
 		struct gendisk *disk = pf->disk;
+
 		if (!pf->present)
 			continue;
 		disk->private_data = pf;
diff -Nru a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
--- a/drivers/block/ps2esdi.c	Thu Dec  5 07:58:13 2002
+++ b/drivers/block/ps2esdi.c	Sat Mar  8 14:50:22 2003
@@ -146,13 +146,10 @@
 
 	int error = 0;
 
-	/* register the device - pass the name, major number and operations
-	   vector .                                                 */
-	if (register_blkdev(PS2ESDI_MAJOR, "ed", &ps2esdi_fops)) {
-		printk("%s: Unable to get major number %d\n", DEVICE_NAME,
-				PS2ESDI_MAJOR);
+	/* register the device - pass the name and major number */
+	if (register_blkdev(PS2ESDI_MAJOR, "ed"))
 		return -1;
-	}
+
 	/* set up some global information - indicating device specific info */
 	blk_init_queue(&ps2esdi_queue, do_ps2esdi_request, &ps2esdi_lock);
 
diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c
--- a/drivers/block/rd.c	Sat Dec 14 09:40:55 2002
+++ b/drivers/block/rd.c	Sat Mar  8 14:50:22 2003
@@ -409,8 +409,7 @@
 			goto out;
 	}
 
-	if (register_blkdev(RAMDISK_MAJOR, "ramdisk", &rd_bd_op)) {
-		printk("RAMDISK: Could not get major %d", RAMDISK_MAJOR);
+	if (register_blkdev(RAMDISK_MAJOR, "ramdisk")) {
 		err = -EIO;
 		goto out;
 	}
diff -Nru a/drivers/block/swim3.c b/drivers/block/swim3.c
--- a/drivers/block/swim3.c	Thu Dec  5 07:57:01 2002
+++ b/drivers/block/swim3.c	Sat Mar  8 14:50:22 2003
@@ -1004,9 +1004,7 @@
 			goto out;
 	}
 
-	if (register_blkdev(FLOPPY_MAJOR, "fd", &floppy_fops)) {
-		printk(KERN_ERR"Unable to get major %d for floppy\n",
-				FLOPPY_MAJOR);
+	if (register_blkdev(FLOPPY_MAJOR, "fd")) {
 		err = -EBUSY;
 		goto out;
 	}
diff -Nru a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
--- a/drivers/block/swim_iop.c	Mon Nov 11 03:13:21 2002
+++ b/drivers/block/swim_iop.c	Sat Mar  8 14:50:22 2003
@@ -137,13 +137,12 @@
 	current_req = NULL;
 	floppy_count = 0;
 
-	if (!iop_ism_present) return -ENODEV;
+	if (!iop_ism_present)
+		return -ENODEV;
 
-	if (register_blkdev(FLOPPY_MAJOR, "fd", &floppy_fops)) {
-		printk(KERN_ERR "SWIM-IOP: Unable to get major %d for floppy\n",
-		       FLOPPY_MAJOR);
+	if (register_blkdev(FLOPPY_MAJOR, "fd"))
 		return -EBUSY;
-	}
+
 	blk_init_queue(&swim_queue, do_fd_request, &swim_iop_lock);
 	printk("SWIM-IOP: %s by Joshua M. Thompson (funaho@jurai.org)\n",
 		DRIVER_VERSION);
diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c
--- a/drivers/block/umem.c	Fri Jan 10 17:00:19 2003
+++ b/drivers/block/umem.c	Sat Mar  8 14:50:22 2003
@@ -1145,11 +1145,9 @@
 	if (retval)
 		return -ENOMEM;
 
-	err = major_nr = register_blkdev(0, "umem", &mm_fops);
-	if (err < 0) {
-		printk(KERN_ERR "MM: Could not register block device\n");
+	err = major_nr = register_blkdev(0, "umem");
+	if (err < 0)
 		return -EIO;
-	}
 
 	for (i = 0; i < num_cards; i++) {
 		mm_gendisk[i] = alloc_disk(1 << MM_SHIFT);
diff -Nru a/drivers/block/xd.c b/drivers/block/xd.c
--- a/drivers/block/xd.c	Thu Dec  5 07:53:02 2002
+++ b/drivers/block/xd.c	Sat Mar  8 14:50:22 2003
@@ -154,9 +154,9 @@
 
 #ifdef MODULE
 	for (i = 4; i > 0; i--)
-		if(((xd[i] = xd[i-1]) >= 0) && !count)
+		if (((xd[i] = xd[i-1]) >= 0) && !count)
 			count = i;
-	if((xd[0] = count))
+	if ((xd[0] = count))
 		do_xd_setup(xd);
 #endif
 
@@ -170,10 +170,9 @@
 	}
 
 	err = -EBUSY;
-	if (register_blkdev(XT_DISK_MAJOR,"xd",&xd_fops)) {
-		printk("xd: Unable to get major number %d\n",XT_DISK_MAJOR);
+	if (register_blkdev(XT_DISK_MAJOR, "xd"))
 		goto out1;
-	}
+
 	devfs_mk_dir(NULL, "xd", NULL);
 	blk_init_queue(&xd_queue, do_xd_request, &xd_lock);
 	if (xd_detect(&controller,&address)) {
diff -Nru a/drivers/block/z2ram.c b/drivers/block/z2ram.c
--- a/drivers/block/z2ram.c	Wed Nov  6 08:13:59 2002
+++ b/drivers/block/z2ram.c	Sat Mar  8 14:50:22 2003
@@ -331,21 +331,18 @@
 static struct request_queue z2_queue;
 
 int __init 
-z2_init( void )
+z2_init(void)
 {
 
-    if ( !MACH_IS_AMIGA )
+    if (!MACH_IS_AMIGA)
 	return -ENXIO;
 
-    if ( register_blkdev( Z2RAM_MAJOR, DEVICE_NAME, &z2_fops ) )
-    {
-	printk( KERN_ERR DEVICE_NAME ": Unable to get major %d\n",
-	    Z2RAM_MAJOR );
+    if (register_blkdev(Z2RAM_MAJOR, DEVICE_NAME))
 	return -EBUSY;
-    }
+
     z2ram_gendisk = alloc_disk(1);
     if (!z2ram_gendisk) {
-	unregister_blkdev( Z2RAM_MAJOR, DEVICE_NAME );
+	unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
 	return -ENOMEM;
     }
     z2ram_gendisk->major = Z2RAM_MAJOR;
diff -Nru a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
--- a/drivers/cdrom/aztcd.c	Tue Dec  3 09:50:14 2002
+++ b/drivers/cdrom/aztcd.c	Sat Mar  8 14:50:22 2003
@@ -1910,12 +1910,12 @@
 	azt_disk = alloc_disk(1);
 	if (!azt_disk)
 		goto err_out;
-	if (register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) {
-		printk(KERN_WARNING "aztcd: Unable to get major %d for Aztech"
-		       " CD-ROM\n", MAJOR_NR);
+
+	if (register_blkdev(MAJOR_NR, "aztcd")) {
 		ret = -EIO;
 		goto err_out2;
 	}
+
 	blk_init_queue(&azt_queue, do_aztcd_request, &aztSpin);
 	blk_queue_hardsect_size(&azt_queue, 2048);
 	azt_disk->major = MAJOR_NR;
@@ -1931,7 +1931,7 @@
 	azt_invalidate_buffers();
 	aztPresent = 1;
 	aztCloseDoor();
-	return (0);
+	return 0;
 err_out2:
 	put_disk(azt_disk);
 err_out:
diff -Nru a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
--- a/drivers/cdrom/cdu31a.c	Fri Oct 18 03:55:37 2002
+++ b/drivers/cdrom/cdu31a.c	Sat Mar  8 14:50:22 2003
@@ -3368,11 +3368,8 @@
 	if (!request_region(cdu31a_port, 4, "cdu31a"))
 		goto errout3;
 
-	if (register_blkdev(MAJOR_NR, "cdu31a", &scd_bdops)) {
-		printk("Unable to get major %d for CDU-31a\n",
-		       MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "cdu31a"))
 		goto errout2;
-	}
 
 	disk = alloc_disk(1);
 	if (!disk)
diff -Nru a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
--- a/drivers/cdrom/cm206.c	Mon Nov 11 05:59:04 2002
+++ b/drivers/cdrom/cm206.c	Sat Mar  8 14:50:22 2003
@@ -1489,10 +1489,10 @@
 		goto out_probe;
 	}
 	printk(".\n");
-	if (register_blkdev(MAJOR_NR, "cm206", &cm206_bdops) != 0) {
-		printk(KERN_INFO "Cannot register for major %d!\n", MAJOR_NR);
+
+	if (register_blkdev(MAJOR_NR, "cm206"))
 		goto out_blkdev;
-	}
+
 	disk = alloc_disk(1);
 	if (!disk)
 		goto out_disk;
diff -Nru a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
--- a/drivers/cdrom/gscd.c	Sat Dec  7 18:57:27 2002
+++ b/drivers/cdrom/gscd.c	Sat Mar  8 14:50:22 2003
@@ -959,12 +959,11 @@
 	gscd_disk->fops = &gscd_fops;
 	sprintf(gscd_disk->disk_name, "gscd");
 
-	if (register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) {
-		printk(KERN_WARNING "GSCD: Unable to get major %d for GoldStar "
-		       "CD-ROM\n", MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "gscd")) {
 		ret = -EIO;
 		goto err_out2;
 	}
+
 	devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
 		       S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL);
 
diff -Nru a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
--- a/drivers/cdrom/mcd.c	Sun Nov 17 11:28:18 2002
+++ b/drivers/cdrom/mcd.c	Sat Mar  8 14:50:22 2003
@@ -1068,8 +1068,7 @@
 		put_disk(disk);
 		return -EIO;
 	}
-	if (register_blkdev(MAJOR_NR, "mcd", &mcd_bdops) != 0) {
-		printk(KERN_ERR "mcd: Unable to get major %d for Mitsumi CD-ROM\n", MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "mcd")) {
 		put_disk(disk);
 		return -EIO;
 	}
diff -Nru a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
--- a/drivers/cdrom/mcdx.c	Mon Nov 18 06:04:22 2002
+++ b/drivers/cdrom/mcdx.c	Sat Mar  8 14:50:22 2003
@@ -1193,11 +1193,9 @@
 	}
 
 	xtrace(INIT, "init() register blkdev\n");
-	if (register_blkdev(MAJOR_NR, "mcdx", &mcdx_bdops) != 0) {
+	if (register_blkdev(MAJOR_NR, "mcdx")) {
 		release_region((unsigned long) stuffp->wreg_data,
 			       MCDX_IO_SIZE);
-		xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n",
-		      MCDX, stuffp->wreg_data, stuffp->irq, MAJOR_NR);
 		kfree(stuffp);
 		put_disk(disk);
 		return 1;
diff -Nru a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
--- a/drivers/cdrom/optcd.c	Sun Nov 17 23:09:33 2002
+++ b/drivers/cdrom/optcd.c	Sat Mar  8 14:50:22 2003
@@ -2047,8 +2047,7 @@
 		put_disk(optcd_disk);
 		return -EIO;
 	}
-	if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0) {
-		printk(KERN_ERR "optcd: unable to get major %d\n", MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "optcd")) {
 		release_region(optcd_port, 4);
 		put_disk(optcd_disk);
 		return -EIO;
diff -Nru a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
--- a/drivers/cdrom/sbpcd.c	Mon Feb 24 12:16:14 2003
+++ b/drivers/cdrom/sbpcd.c	Sat Mar  8 14:50:22 2003
@@ -5795,15 +5795,14 @@
 	OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */
 #endif /* SOUND_BASE */
 
-	if (register_blkdev(MAJOR_NR, major_name, &sbpcd_bdops) != 0)
-	{
-		msg(DBG_INF, "Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, major_name)) {
 #ifdef MODULE
 		return -EIO;
 #else
 		goto init_done;
 #endif /* MODULE */
 	}
+
 	blk_init_queue(&sbpcd_queue, do_sbpcd_request, &sbpcd_lock);
 
 	devfs_mk_dir (NULL, "sbp", NULL);
diff -Nru a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
--- a/drivers/cdrom/sjcd.c	Fri Nov 15 11:38:00 2002
+++ b/drivers/cdrom/sjcd.c	Sat Mar  8 14:50:22 2003
@@ -1677,11 +1677,8 @@
 	printk("SJCD: sjcd=0x%x: ", sjcd_base);
 #endif
 
-	if (register_blkdev(MAJOR_NR, "sjcd", &sjcd_fops) != 0) {
-		printk("SJCD: Unable to get major %d for Sanyo CD-ROM\n",
-		       MAJOR_NR);
-		return (-EIO);
-	}
+	if (register_blkdev(MAJOR_NR, "sjcd"))
+		return -EIO;
 
 	blk_init_queue(&sjcd_queue, do_sjcd_request, &sjcd_lock);
 	blk_queue_hardsect_size(&sjcd_queue, 2048);
diff -Nru a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
--- a/drivers/cdrom/sonycd535.c	Mon Dec 30 20:26:12 2002
+++ b/drivers/cdrom/sonycd535.c	Sat Mar  8 14:50:22 2003
@@ -1546,9 +1546,7 @@
 		printk("IRQ%d, ", tmp_irq);
 	printk("using %d byte buffer\n", sony_buffer_size);
 
-	if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) {
-		printk("Unable to get major %d for %s\n",
-				MAJOR_NR, CDU535_MESSAGE_NAME);
+	if (register_blkdev(MAJOR_NR, CDU535_HANDLE)) {
 		err = -EIO;
 		goto out1;
 	}
diff -Nru a/drivers/char/amiserial.c b/drivers/char/amiserial.c
--- a/drivers/char/amiserial.c	Mon Feb  3 05:47:46 2003
+++ b/drivers/char/amiserial.c	Mon Mar  3 12:04:08 2003
@@ -2320,10 +2320,11 @@
 /*
  *	Register console.
  */
-void __init serial_console_init(void)
+static void __init amiserial_console_init(void)
 {
 	register_console(&sercons);
 }
+console_initcall(amiserial_console_init);
 #endif
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/decserial.c b/drivers/char/decserial.c
--- a/drivers/char/decserial.c	Mon Feb  4 23:45:05 2002
+++ b/drivers/char/decserial.c	Fri Feb 14 15:14:03 2003
@@ -75,7 +75,7 @@
 /* serial_console_init handles the special case of starting
  *   up the console on the serial port
  */
-void __init serial_console_init(void)
+static void __init decserial_console_init(void)
 {
 #if defined(CONFIG_ZS) && defined(CONFIG_DZ)
     if (IOASIC)
@@ -94,5 +94,6 @@
 
 #endif
 }
+console_initcall(decserial_console_init);
 
 #endif
diff -Nru a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
--- a/drivers/char/hvc_console.c	Tue Feb 11 14:57:50 2003
+++ b/drivers/char/hvc_console.c	Fri Feb 14 15:14:16 2003
@@ -346,11 +346,12 @@
 	.index		= -1,
 };
 
-int __init hvc_console_init(void)
+static int __init hvc_console_init(void)
 {
 	register_console(&hvc_con_driver);
 	return 0;
 }
+console_initcall(hvc_console_init);
 
 module_init(hvc_init);
 module_exit(hvc_exit);
diff -Nru a/drivers/char/random.c b/drivers/char/random.c
--- a/drivers/char/random.c	Mon Feb 17 14:45:20 2003
+++ b/drivers/char/random.c	Mon Mar  3 04:08:26 2003
@@ -1228,10 +1228,8 @@
  * at which point we do a "catastrophic reseeding".
  */
 static inline void xfer_secondary_pool(struct entropy_store *r,
-				       size_t nbytes)
+				       size_t nbytes, __u32 *tmp)
 {
-	__u32	tmp[TMP_BUF_SIZE];
-
 	if (r->entropy_count < nbytes * 8 &&
 	    r->entropy_count < r->poolinfo.POOLBITS) {
 		int nwords = min_t(int,
@@ -1284,7 +1282,7 @@
 		r->entropy_count = r->poolinfo.POOLBITS;
 
 	if (flags & EXTRACT_ENTROPY_SECONDARY)
-		xfer_secondary_pool(r, nbytes);
+		xfer_secondary_pool(r, nbytes, tmp);
 
 	DEBUG_ENT("%s has %d bits, want %d bits\n",
 		  r == sec_random_state ? "secondary" :
diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c
--- a/drivers/char/raw.c	Tue Jan  7 14:52:26 2003
+++ b/drivers/char/raw.c	Sat Mar  8 14:50:48 2003
@@ -19,14 +19,16 @@
 
 #include <asm/uaccess.h>
 
+#define MAX_RAW_MINORS	256
+
 struct raw_device_data {
 	struct block_device *binding;
 	int inuse;
 };
 
-static struct raw_device_data raw_devices[256];
+static struct raw_device_data raw_devices[MAX_RAW_MINORS];
 static DECLARE_MUTEX(raw_mutex);
-static struct file_operations raw_ctl_fops;
+static struct file_operations raw_ctl_fops;	     /* forward declaration */
 
 /*
  * Open/close code for raw IO.
@@ -85,11 +87,16 @@
 {
 	const int minor= minor(inode->i_rdev);
 	struct block_device *bdev;
-	
+
 	down(&raw_mutex);
 	bdev = raw_devices[minor].binding;
 	raw_devices[minor].inuse--;
 	up(&raw_mutex);
+
+	/* Here  inode->i_mapping == bdev->bd_inode->i_mapping  */
+	inode->i_mapping = &inode->i_data;
+	inode->i_mapping->backing_dev_info = &default_backing_dev_info;
+	
 	bd_release(bdev);
 	blkdev_put(bdev, BDEV_RAW);
 	return 0;
@@ -130,11 +137,13 @@
 			goto out;
 		
 		err = -EINVAL;
-		if (rq.raw_minor < 0 || rq.raw_minor > MINORMASK)
+		if (rq.raw_minor < 0 || rq.raw_minor >= MAX_RAW_MINORS)
 			goto out;
 		rawdev = &raw_devices[rq.raw_minor];
 
 		if (command == RAW_SETBIND) {
+			dev_t dev;
+
 			/*
 			 * This is like making block devices, so demand the
 			 * same capability
@@ -151,9 +160,10 @@
 			 */
 
 			err = -EINVAL;
+			dev = MKDEV(rq.block_major, rq.block_minor);
 			if ((rq.block_major == 0 && rq.block_minor != 0) ||
-					rq.block_major > MAX_BLKDEV ||
-					rq.block_minor > MINORMASK)
+			    MAJOR(dev) != rq.block_major ||
+			    MINOR(dev) != rq.block_minor)
 				goto out;
 			
 			down(&raw_mutex);
@@ -170,10 +180,7 @@
 				/* unbind */
 				rawdev->binding = NULL;
 			} else {
-				kdev_t kdev;
-
-				kdev = mk_kdev(rq.block_major, rq.block_minor);
-				rawdev->binding = bdget(kdev_t_to_nr(kdev));
+				rawdev->binding = bdget(dev);
 				MOD_INC_USE_COUNT;
 			}
 			up(&raw_mutex);
diff -Nru a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
--- a/drivers/char/rio/rio_linux.c	Tue Feb 25 02:08:22 2003
+++ b/drivers/char/rio/rio_linux.c	Thu Mar  6 09:17:26 2003
@@ -59,7 +59,6 @@
 #include <linux/miscdevice.h>
 #include <linux/init.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 #if BITS_PER_LONG != 32
@@ -725,14 +724,14 @@
   switch (cmd) {
 #if 0
   case TIOCGSOFTCAR:
-    rc = Put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
+    rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
                   (unsigned int *) arg);
     break;
 #endif
   case TIOCSSOFTCAR:
     if ((rc = verify_area(VERIFY_READ, (void *) arg,
                           sizeof(int))) == 0) {
-      Get_user(ival, (unsigned int *) arg);
+      get_user(ival, (unsigned int *) arg);
       tty->termios->c_cflag =
         (tty->termios->c_cflag & ~CLOCAL) |
         (ival ? CLOCAL : 0);
@@ -784,7 +783,7 @@
   case TIOCMBIS:
     if ((rc = verify_area(VERIFY_READ, (void *) arg,
                           sizeof(unsigned int))) == 0) {
-      Get_user(ival, (unsigned int *) arg);
+      get_user(ival, (unsigned int *) arg);
       rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
                            ((ival & TIOCM_RTS) ? 1 : -1));
     }
@@ -792,7 +791,7 @@
   case TIOCMBIC:
     if ((rc = verify_area(VERIFY_READ, (void *) arg,
                           sizeof(unsigned int))) == 0) {
-      Get_user(ival, (unsigned int *) arg);
+      get_user(ival, (unsigned int *) arg);
       rio_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
                            ((ival & TIOCM_RTS) ? 0 : -1));
     }
@@ -800,7 +799,7 @@
   case TIOCMSET:
     if ((rc = verify_area(VERIFY_READ, (void *) arg,
                           sizeof(unsigned int))) == 0) {
-      Get_user(ival, (unsigned int *) arg);
+      get_user(ival, (unsigned int *) arg);
       rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
                            ((ival & TIOCM_RTS) ? 1 : 0));
     }
@@ -1126,7 +1125,7 @@
             t, CNTRL_REG_GOODVALUE); 
     writel (CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);  
   }
-  my_iounmap (hwbase, rebase);
+  iounmap((char*) rebase);
 }
 #endif
 
@@ -1201,7 +1200,7 @@
 
       hp = &p->RIOHosts[p->RIONumHosts];
       hp->PaddrP =  tint & PCI_BASE_ADDRESS_MEM_MASK;
-      hp->Ivec = get_irq (pdev);
+      hp->Ivec = pdev->irq;
       if (((1 << hp->Ivec) & rio_irqmask) == 0)
               hp->Ivec = 0;
       hp->CardP	= (struct DpRam *)
@@ -1234,8 +1233,7 @@
               p->RIONumHosts++;
               found++;
       } else {
-              my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, 
-                          p->RIOHosts[p->RIONumHosts].Caddr);
+              iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr));
       }
       
 #ifdef TWO_ZERO
@@ -1272,7 +1270,7 @@
 
       hp = &p->RIOHosts[p->RIONumHosts];
       hp->PaddrP =  tint & PCI_BASE_ADDRESS_MEM_MASK;
-      hp->Ivec = get_irq (pdev);
+      hp->Ivec = pdev->irq;
       if (((1 << hp->Ivec) & rio_irqmask) == 0) 
       	hp->Ivec = 0;
       hp->Ivec |= 0x8000; /* Mark as non-sharable */
@@ -1307,8 +1305,7 @@
         p->RIONumHosts++;
         found++;
       } else {
-        my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, 
-                    p->RIOHosts[p->RIONumHosts].Caddr);
+        iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr));
       }
 #else
       printk (KERN_ERR "Found an older RIO PCI card, but the driver is not "
@@ -1361,7 +1358,7 @@
       }
 
     if (!okboard)
-      my_iounmap (hp->PaddrP, hp->Caddr);
+      iounmap ((char*) (hp->Caddr));
     }
   }
 
diff -Nru a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
--- a/drivers/char/rio/rioboot.c	Sat Feb 15 13:50:01 2003
+++ b/drivers/char/rio/rioboot.c	Sun Feb 16 16:15:30 2003
@@ -48,7 +48,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 
diff -Nru a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
--- a/drivers/char/rio/riocmd.c	Thu Nov 21 09:58:01 2002
+++ b/drivers/char/rio/riocmd.c	Sun Feb 16 16:15:30 2003
@@ -47,7 +47,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 #include "linux_compat.h"
diff -Nru a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
--- a/drivers/char/rio/rioctrl.c	Tue Dec  3 13:17:27 2002
+++ b/drivers/char/rio/rioctrl.c	Sun Feb 16 16:15:30 2003
@@ -47,7 +47,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 
diff -Nru a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
--- a/drivers/char/rio/rioinit.c	Tue Feb 25 09:44:30 2003
+++ b/drivers/char/rio/rioinit.c	Thu Mar  6 09:17:26 2003
@@ -47,7 +47,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 
diff -Nru a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c
--- a/drivers/char/rio/riointr.c	Mon Feb  4 23:45:07 2002
+++ b/drivers/char/rio/riointr.c	Sun Feb 16 16:15:30 2003
@@ -48,7 +48,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 #include <linux/delay.h>
diff -Nru a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c
--- a/drivers/char/rio/rioparam.c	Mon Feb 24 12:42:23 2003
+++ b/drivers/char/rio/rioparam.c	Thu Mar  6 09:17:26 2003
@@ -48,7 +48,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 
diff -Nru a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c
--- a/drivers/char/rio/rioroute.c	Tue Feb 25 11:05:23 2003
+++ b/drivers/char/rio/rioroute.c	Thu Mar  6 09:17:26 2003
@@ -46,7 +46,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 
diff -Nru a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c
--- a/drivers/char/rio/riotable.c	Tue Feb 25 11:05:23 2003
+++ b/drivers/char/rio/riotable.c	Thu Mar  6 09:17:26 2003
@@ -48,7 +48,6 @@
 #include <linux/termios.h>
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 
diff -Nru a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
--- a/drivers/char/rio/riotty.c	Tue Feb 25 02:17:56 2003
+++ b/drivers/char/rio/riotty.c	Thu Mar  6 09:17:26 2003
@@ -51,7 +51,6 @@
 
 #include <linux/serial.h>
 
-#include <linux/compatmac.h>
 #include <linux/generic_serial.h>
 
 
diff -Nru a/drivers/char/rtc.c b/drivers/char/rtc.c
--- a/drivers/char/rtc.c	Sat Feb 15 04:17:36 2003
+++ b/drivers/char/rtc.c	Thu Mar  6 08:17:53 2003
@@ -152,6 +152,9 @@
 static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */
 
 #if RTC_IRQ
+/*
+ * rtc_task_lock nests inside rtc_lock.
+ */
 static spinlock_t rtc_task_lock = SPIN_LOCK_UNLOCKED;
 static rtc_task_t *rtc_callback = NULL;
 #endif
@@ -746,13 +749,15 @@
 #else
 	unsigned char tmp;
 
-	spin_lock_irq(&rtc_task_lock);
+	spin_lock_irq(&rtc_lock);
+	spin_lock(&rtc_task_lock);
 	if (rtc_callback != task) {
-		spin_unlock_irq(&rtc_task_lock);
+		spin_unlock(&rtc_task_lock);
+		spin_unlock_irq(&rtc_lock);
 		return -ENXIO;
 	}
 	rtc_callback = NULL;
-	spin_lock(&rtc_lock);
+	
 	/* disable controls */
 	tmp = CMOS_READ(RTC_CONTROL);
 	tmp &= ~RTC_PIE;
@@ -765,8 +770,8 @@
 		del_timer(&rtc_irq_timer);
 	}
 	rtc_status &= ~RTC_IS_OPEN;
-	spin_unlock(&rtc_lock);
-	spin_unlock_irq(&rtc_task_lock);
+	spin_unlock(&rtc_task_lock);
+	spin_unlock_irq(&rtc_lock);
 	return 0;
 #endif
 }
diff -Nru a/drivers/char/serial167.c b/drivers/char/serial167.c
--- a/drivers/char/serial167.c	Mon Nov 11 03:13:26 2002
+++ b/drivers/char/serial167.c	Fri Feb 14 15:16:47 2003
@@ -2836,7 +2836,7 @@
 };
 
 
-void __init serial167_console_init(void)
+static void __init serial167_console_init(void)
 {
 	if (vme_brdtype == VME_TYPE_MVME166 ||
 			vme_brdtype == VME_TYPE_MVME167 ||
@@ -2845,6 +2845,7 @@
 		register_console(&sercons);
 	}
 }
+console_initcall(serial167_console_init);
 
 #ifdef CONFIG_REMOTE_DEBUG
 void putDebugChar (int c)
diff -Nru a/drivers/char/serial_tx3912.c b/drivers/char/serial_tx3912.c
--- a/drivers/char/serial_tx3912.c	Tue Nov  5 07:39:55 2002
+++ b/drivers/char/serial_tx3912.c	Fri Feb 14 15:16:47 2003
@@ -1054,9 +1054,10 @@
 	.index    = -1
 };
 
-void __init tx3912_console_init(void)
+static void __init tx3912_console_init(void)
 {
 	register_console(&sercons);
 }
+console_initcall(tx3912_console_init);
 
 #endif
diff -Nru a/drivers/char/sh-sci.c b/drivers/char/sh-sci.c
--- a/drivers/char/sh-sci.c	Tue Nov  5 07:39:53 2002
+++ b/drivers/char/sh-sci.c	Fri Feb 14 15:16:47 2003
@@ -1275,7 +1275,7 @@
 extern void sh_console_unregister (void);
 #endif
 
-void __init sci_console_init(void)
+static void __init sci_console_init(void)
 {
 	register_console(&sercons);
 #ifdef CONFIG_SH_EARLY_PRINTK
@@ -1285,4 +1285,6 @@
 	sh_console_unregister();
 #endif
 }
+console_initcall(sci_console_init);
+
 #endif /* CONFIG_SERIAL_CONSOLE */
diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c
--- a/drivers/char/tty_io.c	Mon Mar  3 08:49:44 2003
+++ b/drivers/char/tty_io.c	Thu Mar  6 09:17:26 2003
@@ -113,7 +113,15 @@
 #define TTY_PARANOIA_CHECK 1
 #define CHECK_TTY_COUNT 1
 
-struct termios tty_std_termios;		/* for the benefit of tty drivers  */
+struct termios tty_std_termios = {	/* for the benefit of tty drivers  */
+	.c_iflag = ICRNL | IXON,
+	.c_oflag = OPOST | ONLCR,
+	.c_cflag = B38400 | CS8 | CREAD | HUPCL,
+	.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
+		   ECHOCTL | ECHOKE | IEXTEN,
+	.c_cc = INIT_C_CC
+};
+
 LIST_HEAD(tty_drivers);			/* linked list of tty drivers */
 struct tty_ldisc ldiscs[NR_LDISCS];	/* line disc dispatch table	*/
 
@@ -141,26 +149,13 @@
 	      unsigned int cmd, unsigned long arg);
 static int tty_fasync(int fd, struct file * filp, int on);
 extern int vme_scc_init (void);
-extern long vme_scc_console_init(void);
 extern int serial167_init(void);
-extern long serial167_console_init(void);
-extern void console_8xx_init(void);
 extern int rs_8xx_init(void);
-extern void mac_scc_console_init(void);
-extern void sclp_console_init(void);
-extern void sclp_tty_init(void);
-extern void con3215_init(void);
-extern void tub3270_con_init(void);
+extern void hwc_tty_init(void);
+extern void tty3215_init(void);
 extern void tub3270_init(void);
-extern void uart_console_init(void);
-extern void sgi_serial_console_init(void);
-extern void sci_console_init(void);
-extern void m68328_console_init(void);
-extern void mcfrs_console_init(void);
 extern void rs_360_init(void);
-extern void tx3912_console_init(void);
 extern void tx3912_rs_init(void);
-extern void hvc_console_init(void);
 
 static struct tty_struct *alloc_tty_struct(void)
 {
@@ -306,13 +301,9 @@
 	if (tty->ldisc.open)
 		retval = (tty->ldisc.open)(tty);
 	if (retval < 0) {
-		module_put(tty->ldisc.owner);
-		
 		tty->ldisc = o_ldisc;
 		tty->termios->c_line = tty->ldisc.num;
 		if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) {
-			module_put(tty->ldisc.owner);
-
 			tty->ldisc = ldiscs[N_TTY];
 			tty->termios->c_line = N_TTY;
 			if (tty->ldisc.open) {
@@ -2206,91 +2197,28 @@
  */
 void __init console_init(void)
 {
+	initcall_t *call;
+
 	/* Setup the default TTY line discipline. */
-	memset(ldiscs, 0, sizeof(ldiscs));
 	(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
 
 	/*
-	 * Set up the standard termios.  Individual tty drivers may 
-	 * deviate from this; this is used as a template.
-	 */
-	memset(&tty_std_termios, 0, sizeof(struct termios));
-	memcpy(tty_std_termios.c_cc, INIT_C_CC, NCCS);
-	tty_std_termios.c_iflag = ICRNL | IXON;
-	tty_std_termios.c_oflag = OPOST | ONLCR;
-	tty_std_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL;
-	tty_std_termios.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
-		ECHOCTL | ECHOKE | IEXTEN;
-
-	/*
 	 * set up the console device so that later boot sequences can 
 	 * inform about problems etc..
 	 */
 #ifdef CONFIG_EARLY_PRINTK
 	disable_early_printk();
 #endif
-#ifdef CONFIG_VT
-	con_init();
-#endif
-#ifdef CONFIG_AU1000_SERIAL_CONSOLE
-	au1000_serial_console_init();
-#endif
-#ifdef CONFIG_SERIAL_CONSOLE
-#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
-	console_8xx_init();
-#elif defined(CONFIG_MAC_SERIAL)
- 	mac_scc_console_init();
-#elif defined(CONFIG_PARISC)
-	pdc_console_init();
-#elif defined(CONFIG_SERIAL)
-	serial_console_init();
-#endif /* CONFIG_8xx */
-#ifdef CONFIG_SGI_SERIAL
-	sgi_serial_console_init();
-#endif
-#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC)
-	vme_scc_console_init();
-#endif
-#if defined(CONFIG_SERIAL167)
-	serial167_console_init();
-#endif
-#if defined(CONFIG_SH_SCI)
-	sci_console_init();
-#endif
-#endif
-#ifdef CONFIG_TN3270_CONSOLE
-	tub3270_con_init();
-#endif
-#ifdef CONFIG_TN3215_CONSOLE
-	con3215_init();
-#endif
-#ifdef CONFIG_SCLP_CONSOLE
-        sclp_console_init();
-#endif
-#ifdef CONFIG_STDIO_CONSOLE
-	stdio_console_init();
-#endif
-#ifdef CONFIG_SERIAL_CORE_CONSOLE
-	uart_console_init();
-#endif
-#ifdef CONFIG_ARC_CONSOLE
-	arc_console_init();
-#endif
-#ifdef CONFIG_SERIAL_68328
-	m68328_console_init();
-#endif
-#ifdef CONFIG_SERIAL_COLDFIRE
-	mcfrs_console_init();
-#endif
 #ifdef CONFIG_SERIAL_68360
-	rs_360_init();
-#endif
-#ifdef CONFIG_SERIAL_TX3912_CONSOLE
-	tx3912_console_init();
-#endif
-#ifdef CONFIG_HVC_CONSOLE
-	hvc_console_init();
-#endif
+ 	/* This is not a console initcall. I know not what it's doing here.
+	   So I haven't moved it. dwmw2 */
+        rs_360_init();
+#endif
+	call = &__con_initcall_start;
+	while (call < &__con_initcall_end) {
+		(*call)();
+		call++;
+	}
 }
 
 static struct tty_driver dev_tty_driver, dev_syscons_driver;
diff -Nru a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
--- a/drivers/char/vme_scc.c	Thu Nov  7 15:06:42 2002
+++ b/drivers/char/vme_scc.c	Fri Feb 14 15:18:33 2003
@@ -1091,7 +1091,7 @@
 };
 
 
-void __init vme_scc_console_init(void)
+static void __init vme_scc_console_init(void)
 {
 	if (vme_brdtype == VME_TYPE_MVME147 ||
 			vme_brdtype == VME_TYPE_MVME162 ||
@@ -1100,4 +1100,4 @@
 			vme_brdtype == VME_TYPE_BVME6000)
 		register_console(&sercons);
 }
-
+console_initcall(vme_scc_console_init);
diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c
--- a/drivers/char/vt.c	Tue Feb 25 09:17:44 2003
+++ b/drivers/char/vt.c	Fri Mar  7 11:25:45 2003
@@ -747,8 +747,10 @@
 	screenbuf_size = new_screen_size;
 
 	err = resize_screen(currcons, new_cols, new_rows);
-	if (err)
+	if (err) {
+		kfree(newscreen);
 		return err;
+	}
 
 	rlth = min(old_row_size, new_row_size);
 	rrem = new_row_size - rlth;
@@ -2443,7 +2445,7 @@
 struct tty_driver console_driver;
 static int console_refcount;
 
-void __init con_init(void)
+static int __init con_init(void)
 {
 	const char *display_desc = NULL;
 	unsigned int currcons = 0;
@@ -2452,7 +2454,7 @@
 		display_desc = conswitchp->con_startup();
 	if (!display_desc) {
 		fg_console = 0;
-		return;
+		return 0;
 	}
 
 	init_timer(&console_timer);
@@ -2491,7 +2493,9 @@
 #ifdef CONFIG_VT_CONSOLE
 	register_console(&vt_console_driver);
 #endif
+	return 0;
 }
+console_initcall(con_init);
 
 int __init vty_init(void)
 {
diff -Nru a/drivers/char/watchdog/amd7xx_tco.c b/drivers/char/watchdog/amd7xx_tco.c
--- a/drivers/char/watchdog/amd7xx_tco.c	Thu Feb 27 17:28:13 2003
+++ b/drivers/char/watchdog/amd7xx_tco.c	Sat Mar  8 02:46:43 2003
@@ -1,6 +1,6 @@
 /*
  *	AMD 766/768 TCO Timer Driver
- *	(c) Copyright 2002 Zwane Mwaikambo <zwane@commfireservices.com>
+ *	(c) Copyright 2002 Zwane Mwaikambo <zwane@holomorphy.com>
  *	All Rights Reserved.
  *
  *	Parts from;
@@ -34,35 +34,48 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 
-#define AMDTCO_MODULE_VER	"build 20020601"
+#define AMDTCO_MODULE_VER	"build 20021116"
 #define AMDTCO_MODULE_NAME	"amd7xx_tco"
 #define PFX			AMDTCO_MODULE_NAME ": "
 
-#define	MAX_TIMEOUT	38	/* max of 38 seconds */
+#define	MAX_TIMEOUT	38	/* max of 38 seconds, although the system will only
+				 * reset itself after the second timeout */
 
 /* pmbase registers */
-#define GLOBAL_SMI_REG	0x2a
-#define TCO_EN		(1 << 1)	/* bit 1 in global SMI register */
 #define TCO_RELOAD_REG	0x40		/* bits 0-5 are current count, 6-7 are reserved */
 #define TCO_INITVAL_REG	0x41		/* bits 0-5 are value to load, 6-7 are reserved */
 #define TCO_TIMEOUT_MASK	0x3f
+#define TCO_STATUS1_REG 0x44
 #define TCO_STATUS2_REG	0x46
 #define NDTO_STS2	(1 << 1)	/* we're interested in the second timeout */ 
 #define BOOT_STS	(1 << 2)	/* will be set if NDTO_STS2 was set before reboot */
 #define TCO_CTRL1_REG	0x48
 #define TCO_HALT	(1 << 11)
+#define NO_REBOOT	(1 << 10)	/* in DevB:3x48 */
 
-static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER;
-static int timeout = 38;
+static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER "\n";
+static int timeout = MAX_TIMEOUT;
 static u32 pmbase;		/* PMxx I/O base */
 static struct pci_dev *dev;
 static struct semaphore open_sem;
-spinlock_t amdtco_lock;	/* only for device access */
+static spinlock_t amdtco_lock;	/* only for device access */
 static int expect_close = 0;
 
 MODULE_PARM(timeout, "i");
 MODULE_PARM_DESC(timeout, "range is 0-38 seconds, default is 38");
 
+static inline u8 seconds_to_ticks(int seconds)
+{
+	/* the internal timer is stored as ticks which decrement
+	 * every 0.6 seconds */
+	return (seconds * 10) / 6;
+}
+
+static inline int ticks_to_seconds(u8 ticks)
+{
+	return (ticks * 6) / 10;
+}
+
 static inline int amdtco_status(void)
 {
 	u16 reg;
@@ -81,28 +94,19 @@
 
 static inline void amdtco_ping(void)
 {
-	u8 reg;
-
-	spin_lock(&amdtco_lock);
-	reg = inb(pmbase+TCO_RELOAD_REG);
-	outb(1 | reg, pmbase+TCO_RELOAD_REG);
-	spin_unlock(&amdtco_lock);
+	outb(1, pmbase+TCO_RELOAD_REG);
 }
 
 static inline int amdtco_gettimeout(void)
 {
-	return inb(TCO_RELOAD_REG) & TCO_TIMEOUT_MASK;
+	u8 reg = inb(pmbase+TCO_RELOAD_REG) & TCO_TIMEOUT_MASK;
+	return ticks_to_seconds(reg);
 }
 
 static inline void amdtco_settimeout(unsigned int timeout)
 {
-	u8 reg;
-
-	spin_lock(&amdtco_lock);
-	reg = inb(pmbase+TCO_INITVAL_REG);
-	reg |= timeout & TCO_TIMEOUT_MASK;
+	u8 reg = seconds_to_ticks(timeout) & TCO_TIMEOUT_MASK;
 	outb(reg, pmbase+TCO_INITVAL_REG);
-	spin_unlock(&amdtco_lock);
 }
 
 static inline void amdtco_global_enable(void)
@@ -110,9 +114,12 @@
 	u16 reg;
 
 	spin_lock(&amdtco_lock);
-	reg = inw(pmbase+GLOBAL_SMI_REG);
-	reg |= TCO_EN;
-	outw(reg, pmbase+GLOBAL_SMI_REG);
+
+	/* clear NO_REBOOT on DevB:3x48 p97 */
+	pci_read_config_word(dev, 0x48, &reg);
+	reg &= ~NO_REBOOT;
+	pci_write_config_word(dev, 0x48, reg);
+
 	spin_unlock(&amdtco_lock);
 }
 
@@ -146,10 +153,12 @@
 	if (timeout > MAX_TIMEOUT)
 		timeout = MAX_TIMEOUT;
 
+	amdtco_disable();
 	amdtco_settimeout(timeout);	
 	amdtco_global_enable();
+	amdtco_enable();
 	amdtco_ping();
-	printk(KERN_INFO PFX "Watchdog enabled, timeout = %d/%d seconds",
+	printk(KERN_INFO PFX "Watchdog enabled, timeout = %ds of %ds\n",
 		amdtco_gettimeout(), timeout);
 	
 	return 0;
@@ -198,7 +207,7 @@
 
 		case WDIOC_GETTIMEOUT:
 			return put_user(amdtco_gettimeout(), (int *)arg);
-	
+		
 		case WDIOC_SETOPTIONS:
 			if (copy_from_user(&tmp, (int *)arg, sizeof tmp))
                                 return -EFAULT;
@@ -221,7 +230,7 @@
 		printk(KERN_INFO PFX "Watchdog disabled\n");
 	} else {
 		amdtco_ping();
-		printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds)\n", timeout);
+		printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds\n", timeout);
 	}	
 	
 	up(&open_sem);
@@ -249,10 +258,9 @@
 		}
 #endif
 		amdtco_ping();
-		return len;
 	}
 
-	return 0;
+	return len;
 }
 
 
@@ -357,6 +365,9 @@
 	if (ints[0] > 0)
 		timeout = ints[1];
 
+	if (!timeout || timeout > MAX_TIMEOUT)
+		timeout = MAX_TIMEOUT;
+
 	return 1;
 }
 
@@ -366,8 +377,7 @@
 module_init(amdtco_init);
 module_exit(amdtco_exit);
 
-MODULE_AUTHOR("Zwane Mwaikambo <zwane@commfireservices.com>");
+MODULE_AUTHOR("Zwane Mwaikambo <zwane@holomorphy.com>");
 MODULE_DESCRIPTION("AMD 766/768 TCO Timer Driver");
 MODULE_LICENSE("GPL");
-EXPORT_NO_SYMBOLS;
 
diff -Nru a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
--- a/drivers/cpufreq/freq_table.c	Sat Feb 15 01:16:27 2003
+++ b/drivers/cpufreq/freq_table.c	Sat Mar  8 01:39:17 2003
@@ -77,56 +77,6 @@
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
 
 
-int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy,
-				      struct cpufreq_frequency_table *table,
-				      unsigned int *index)
-{
-	struct cpufreq_frequency_table optimal = { .index = ~0, };
-	unsigned int i;
-
-	switch (policy->policy) {
-	case CPUFREQ_POLICY_PERFORMANCE:
-		optimal.frequency = 0;
-		break;
-	case CPUFREQ_POLICY_POWERSAVE:
-		optimal.frequency = ~0;
-		break;
-	}
-
-	if (!cpu_online(policy->cpu))
-		return -EINVAL;
-
-	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-		unsigned int freq = table[i].frequency;
-		if (freq == CPUFREQ_ENTRY_INVALID)
-			continue;
-		if ((freq < policy->min) || (freq > policy->max))
-			continue;
-		switch(policy->policy) {
-		case CPUFREQ_POLICY_PERFORMANCE:
-			if (optimal.frequency <= freq) {
-				optimal.frequency = freq;
-				optimal.index = i;
-			}
-			break;
-		case CPUFREQ_POLICY_POWERSAVE:
-			if (optimal.frequency >= freq) {
-				optimal.frequency = freq;
-				optimal.index = i;
-			}
-			break;
-		}
-	}
-	if (optimal.index > i)
-		return -EINVAL;
-
-	*index = optimal.index;
-	
-	return 0;
-}
-EXPORT_SYMBOL_GPL(cpufreq_frequency_table_setpolicy);
-
-
 int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
 				   struct cpufreq_frequency_table *table,
 				   unsigned int target_freq,
@@ -196,6 +146,56 @@
 	return 0;
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
+
+static struct cpufreq_frequency_table *show_table[NR_CPUS];
+/**
+ * show_scaling_governor - show the current policy for the specified CPU
+ */
+static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
+{
+	unsigned int i = 0;
+	unsigned int cpu = policy->cpu;
+	ssize_t count = 0;
+	struct cpufreq_frequency_table *table;
+
+	if (!show_table[cpu])
+		return -ENODEV;
+
+	table = show_table[cpu];
+
+	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
+			continue;
+		count += sprintf(&buf[count], "%d ", table[i].frequency);
+	}
+	count += sprintf(&buf[count], "\n");
+
+	return count;
+
+}
+
+struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
+	.attr = { .name = "scaling_available_frequencies", .mode = 0444 },
+	.show = show_available_freqs,
+};
+EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
+
+/*
+ * if you use these, you must assure that the frequency table is valid
+ * all the time between get_attr and put_attr!
+ */
+void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, 
+				      unsigned int cpu)
+{
+	show_table[cpu] = table;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
+
+void cpufreq_frequency_table_put_attr(unsigned int cpu)
+{
+	show_table[cpu] = NULL;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
 
 
 MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
diff -Nru a/drivers/cpufreq/userspace.c b/drivers/cpufreq/userspace.c
--- a/drivers/cpufreq/userspace.c	Sun Feb 16 05:23:39 2003
+++ b/drivers/cpufreq/userspace.c	Sat Mar  8 01:37:35 2003
@@ -23,6 +23,7 @@
 #include <linux/sysctl.h>
 #include <linux/types.h>
 #include <linux/fs.h>
+#include <linux/sysfs.h>
 
 #include <asm/uaccess.h>
 
@@ -112,7 +113,7 @@
 	if (freq > cpu_max_freq[cpu])
 		freq = cpu_max_freq[cpu];
 
-	ret = cpufreq_driver_target_l(&current_policy[cpu], freq, 
+	ret = cpufreq_driver_target(&current_policy[cpu], freq, 
 	      CPUFREQ_RELATION_L);
 
  err:
@@ -465,23 +466,14 @@
 
 
 /************************** sysfs interface ************************/
-static inline int to_cpu_nr (struct device *dev)
+static ssize_t show_speed (struct cpufreq_policy *policy, char *buf)
 {
-	struct sys_device * cpu_sys_dev = container_of(dev, struct sys_device, dev);
-	return (cpu_sys_dev->id);
-}
-
-static ssize_t show_speed (struct device *dev, char *buf)
-{
-	unsigned int cpu = to_cpu_nr(dev);
-
-	return sprintf (buf, "%u\n", cpu_cur_freq[cpu]);
+	return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]);
 }
 
 static ssize_t 
-store_speed (struct device *dev, const char *buf, size_t count) 
+store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) 
 {
-	unsigned int cpu = to_cpu_nr(dev);
 	unsigned int freq = 0;
 	unsigned int ret;
 
@@ -489,13 +481,16 @@
 	if (ret != 1)
 		return -EINVAL;
 
-	cpufreq_set(freq, cpu);
+	cpufreq_set(freq, policy->cpu);
 
 	return count;
 }
 
-static DEVICE_ATTR(scaling_setspeed, (S_IRUGO | S_IWUSR), show_speed, store_speed);
-
+static struct freq_attr freq_attr_scaling_setspeed = {
+	.attr = { .name = "scaling_setspeed", .mode = 0644 },
+	.show = show_speed,
+	.store = store_speed,
+};
 
 static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
 				   unsigned int event)
@@ -511,7 +506,7 @@
 		cpu_min_freq[cpu] = policy->min;
 		cpu_max_freq[cpu] = policy->max;
 		cpu_cur_freq[cpu] = policy->cur;
-		device_create_file (policy->intf.dev, &dev_attr_scaling_setspeed);
+		sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
 		memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
 		up(&userspace_sem);
 		break;
@@ -520,7 +515,7 @@
 		cpu_is_managed[cpu] = 0;
 		cpu_min_freq[cpu] = 0;
 		cpu_max_freq[cpu] = 0;
-		device_remove_file (policy->intf.dev, &dev_attr_scaling_setspeed);
+		sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
 		up(&userspace_sem);
 		module_put(THIS_MODULE);
 		break;
diff -Nru a/drivers/hotplug/acpiphp_glue.c b/drivers/hotplug/acpiphp_glue.c
--- a/drivers/hotplug/acpiphp_glue.c	Thu Feb 27 16:27:27 2003
+++ b/drivers/hotplug/acpiphp_glue.c	Mon Feb 24 03:28:46 2003
@@ -801,7 +801,7 @@
 static int enable_device (struct acpiphp_slot *slot)
 {
 	u8 bus;
-	struct pci_dev dev0, *dev;
+	struct pci_dev *dev;
 	struct pci_bus *child;
 	struct list_head *l;
 	struct acpiphp_func *func;
@@ -824,16 +824,8 @@
 	if (retval)
 		goto err_exit;
 
-	memset(&dev0, 0, sizeof (struct pci_dev));
-
-	dev0.bus = slot->bridge->pci_bus;
-	dev0.devfn = PCI_DEVFN(slot->device, 0);
-	dev0.sysdata = dev0.bus->sysdata;
-	dev0.dev.parent = dev0.bus->dev;
-	dev0.dev.bus = &pci_bus_type;
-
 	/* returned `dev' is the *first function* only! */
-	dev = pci_scan_slot (&dev0);
+	dev = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0));
 
 	if (!dev) {
 		err("No new device found\n");
diff -Nru a/drivers/hotplug/cpci_hotplug_pci.c b/drivers/hotplug/cpci_hotplug_pci.c
--- a/drivers/hotplug/cpci_hotplug_pci.c	Mon Feb 24 08:17:14 2003
+++ b/drivers/hotplug/cpci_hotplug_pci.c	Mon Feb 24 03:29:36 2003
@@ -574,19 +574,13 @@
 
 	/* Still NULL? Well then scan for it! */
 	if(slot->dev == NULL) {
-		struct pci_dev dev0;
-
 		dbg("pci_dev still null");
-		memset(&dev0, 0, sizeof (struct pci_dev));
-		dev0.bus = slot->bus;
-		dev0.devfn = slot->devfn;
-		dev0.sysdata = slot->bus->self->sysdata;
 
 		/*
 		 * This will generate pci_dev structures for all functions, but
 		 * we will only call this case when lookup fails.
 		 */
-		slot->dev = pci_scan_slot(&dev0);
+		slot->dev = pci_scan_slot(slot->bus, slot->devfn);
 		if(slot->dev == NULL) {
 			err("Could not find PCI device for slot %02x", slot->number);
 			return 0;
diff -Nru a/drivers/hotplug/cpqphp_pci.c b/drivers/hotplug/cpqphp_pci.c
--- a/drivers/hotplug/cpqphp_pci.c	Mon Feb 24 08:17:34 2003
+++ b/drivers/hotplug/cpqphp_pci.c	Mon Feb 24 03:31:07 2003
@@ -84,24 +84,19 @@
 int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)  
 {
 	unsigned char bus;
-	struct pci_dev dev0;
 	struct pci_bus *child;
 	int rc = 0;
 
-	memset(&dev0, 0, sizeof(struct pci_dev));
-
 	if (func->pci_dev == NULL)
 		func->pci_dev = pci_find_slot(func->bus, (func->device << 3) | (func->function & 0x7));
 
 	//Still NULL ? Well then scan for it !
 	if (func->pci_dev == NULL) {
 		dbg("INFO: pci_dev still null\n");
-		dev0.bus = ctrl->pci_dev->bus;
-		dev0.devfn = (func->device << 3) + (func->function & 0x7);
-		dev0.sysdata = ctrl->pci_dev->sysdata;
 
 		//this will generate pci_dev structures for all functions, but we will only call this case when lookup fails
-		func->pci_dev = pci_scan_slot(&dev0);
+		func->pci_dev = pci_scan_slot(ctrl->pci_dev->bus,
+				 (func->device << 3) + (func->function & 0x7));
 		if (func->pci_dev == NULL) {
 			dbg("ERROR: pci_dev still null\n");
 			return 0;
diff -Nru a/drivers/hotplug/ibmphp_core.c b/drivers/hotplug/ibmphp_core.c
--- a/drivers/hotplug/ibmphp_core.c	Thu Feb 27 13:49:39 2003
+++ b/drivers/hotplug/ibmphp_core.c	Mon Feb 24 03:32:11 2003
@@ -845,26 +845,22 @@
 static int ibm_configure_device (struct pci_func *func)
 {
 	unsigned char bus;
-	struct pci_dev dev0;
 	struct pci_bus *child;
 	int rc = 0;
 	int flag = 0;	/* this is to make sure we don't double scan the bus, for bridged devices primarily */
 
-	memset (&dev0, 0, sizeof (struct pci_dev));
-
 	if (!(bus_structure_fixup (func->busno)))
 		flag = 1;
 	if (func->dev == NULL)
 		func->dev = pci_find_slot (func->busno, (func->device << 3) | (func->function & 0x7));
 
 	if (func->dev == NULL) {
-		dev0.bus = ibmphp_find_bus (func->busno);
-		if (!dev0.bus)
+		struct pci_bus *bus = ibmphp_find_bus (func->busno);
+		if (!bus)
 			return 0;
-		dev0.devfn = ((func->device << 3) + (func->function & 0x7));
-		dev0.sysdata = dev0.bus->sysdata;
 
-		func->dev = pci_scan_slot (&dev0);
+		func->dev = pci_scan_slot(bus,
+				 (func->device << 3) + (func->function & 0x7));
 
 		if (func->dev == NULL) {
 			err ("ERROR... : pci_dev still NULL \n");
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c	Thu Feb 20 11:58:55 2003
+++ b/drivers/i2c/i2c-core.c	Sat Mar  1 06:39:04 2003
@@ -68,22 +68,12 @@
 /**** debug level */
 static int i2c_debug;
 
-/* ---------------------------------------------------
- * /proc entry declarations
- *----------------------------------------------------
- */
-
 #ifdef CONFIG_PROC_FS
-static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count, 
-                                loff_t *ppos);
-static int read_bus_i2c(char *buf, char **start, off_t offset, int len,
-                           int *eof , void *private);
-
-/* To implement the dynamic /proc/bus/i2c-? files, we need our own 
-   implementation of the read hook */
-static struct file_operations i2cproc_operations = {
-	.read		= i2cproc_bus_read,
-};
+static int i2cproc_register(struct i2c_adapter *adap, int bus);
+static void i2cproc_remove(int bus);
+#else
+# define i2cproc_register(adap, bus)	0
+# define i2cproc_remove(bus)		do { } while (0)
 #endif /* CONFIG_PROC_FS */
 
 
@@ -109,8 +99,7 @@
 		printk(KERN_WARNING 
 		       " i2c-core.o: register_adapter(%s) - enlarge I2C_ADAP_MAX.\n",
 			adap->name);
-		res = -ENOMEM;
-		goto ERROR0;
+		goto fail;
 	}
 
 	adapters[i] = adap;
@@ -119,26 +108,9 @@
 	/* init data types */
 	init_MUTEX(&adap->lock);
 
-#ifdef CONFIG_PROC_FS
-	{
-		char name[8];
-		struct proc_dir_entry *proc_entry;
-
-		sprintf(name,"i2c-%d", i);
-
-		proc_entry = create_proc_entry(name,0,proc_bus);
-		if (! proc_entry) {
-			printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/%s\n",
-			       name);
-			res = -ENOENT;
-			goto ERROR1;
-		}
-
-		proc_entry->proc_fops = &i2cproc_operations;
-		proc_entry->owner = THIS_MODULE;
-		adap->inode = proc_entry->low_ino;
-	}
-#endif /* def CONFIG_PROC_FS */
+	res = i2cproc_register(adap, i);
+	if (res)
+		return res;
 
 	/* inform drivers of new adapters */
 	DRV_LOCK();	
@@ -154,13 +126,9 @@
 
 	return 0;	
 
-
-ERROR1:
-	ADAP_LOCK();
-	adapters[i] = NULL;
-ERROR0:
+ fail:
 	ADAP_UNLOCK();
-	return res;
+	return -ENOMEM;
 }
 
 
@@ -214,13 +182,8 @@
 				goto ERROR0;
 			}
 	}
-#ifdef CONFIG_PROC_FS
-	{
-		char name[8];
-		sprintf(name,"i2c-%d", i);
-		remove_proc_entry(name, proc_bus);
-	}
-#endif /* def CONFIG_PROC_FS */
+
+	i2cproc_remove(i);
 
 	adapters[i] = NULL;
 	
@@ -501,10 +464,9 @@
  */
 
 #ifdef CONFIG_PROC_FS
-
 /* This function generates the output for /proc/bus/i2c */
-int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof, 
-                 void *private)
+static int read_bus_i2c(char *buf, char **start, off_t offset,
+			int len, int *eof, void *private)
 {
 	int i;
 	int nr = 0;
@@ -529,10 +491,10 @@
 }
 
 /* This function generates the output for /proc/bus/i2c-? */
-ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count, 
-                         loff_t *ppos)
+static ssize_t i2cproc_bus_read(struct file *file, char *buf,
+				size_t count, loff_t *ppos)
 {
-	struct inode * inode = file->f_dentry->d_inode;
+	struct inode *inode = file->f_dentry->d_inode;
 	char *kbuf;
 	struct i2c_client *client;
 	int i,j,k,order_nr,len=0;
@@ -593,6 +555,38 @@
 	return -ENOENT;
 }
 
+static struct file_operations i2cproc_operations = {
+	.read		= i2cproc_bus_read,
+};
+
+static int i2cproc_register(struct i2c_adapter *adap, int bus)
+{
+	struct proc_dir_entry *proc_entry;
+	char name[8];
+
+	sprintf(name, "i2c-%d", bus);
+
+	proc_entry = create_proc_entry(name, 0, proc_bus);
+	if (!proc_entry)
+		goto fail;
+
+	proc_entry->proc_fops = &i2cproc_operations;
+	proc_entry->owner = THIS_MODULE;
+	adap->inode = proc_entry->low_ino;
+	return 0;
+ fail:
+	printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/%s\n", name);
+	return -ENOENT;
+}
+
+static void i2cproc_remove(int bus)
+{
+	char name[8];
+
+	sprintf(name,"i2c-%d", bus);
+	remove_proc_entry(name, proc_bus);
+}
+
 static int i2cproc_init(void)
 {
 
@@ -611,7 +605,6 @@
 
 static void __exit i2cproc_cleanup(void)
 {
-
 	remove_proc_entry("i2c",proc_bus);
 }
 
diff -Nru a/drivers/ide/Makefile b/drivers/ide/Makefile
--- a/drivers/ide/Makefile	Wed Feb 19 09:48:49 2003
+++ b/drivers/ide/Makefile	Mon Mar  3 12:06:45 2003
@@ -28,3 +28,4 @@
 endif
 
 obj-$(CONFIG_BLK_DEV_IDE)		+= legacy/ ppc/ arm/
+obj-$(CONFIG_BLK_DEV_HD)		+= legacy/
diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
--- a/drivers/ide/ide-disk.c	Wed Nov 13 14:49:14 2002
+++ b/drivers/ide/ide-disk.c	Tue Feb 18 10:06:17 2003
@@ -38,9 +38,11 @@
  * Version 1.15		convert all calls to ide_raw_taskfile
  *				since args will return register content.
  * Version 1.16		added suspend-resume-checkpower
+ * Version 1.17		do flush on standy, do flush on ATA < ATA6
+ *			fix wcache setup.
  */
 
-#define IDEDISK_VERSION	"1.16"
+#define IDEDISK_VERSION	"1.17"
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
 
@@ -140,7 +142,7 @@
 static ide_startstop_t read_intr (ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	int i = 0, nsect	= 0, msect = drive->mult_count;
+	u32 i = 0, nsect	= 0, msect = drive->mult_count;
 	struct request *rq;
 	unsigned long flags;
 	u8 stat;
@@ -157,7 +159,7 @@
 		ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
 		return ide_started;
 	}
-
+	
 read_next:
 	rq = HWGROUP(drive)->rq;
 	if (msect) {
@@ -203,7 +205,7 @@
 	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct request *rq	= hwgroup->rq;
-	int i = 0;
+	u32 i = 0;
 	u8 stat;
 
 	if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),
@@ -506,14 +508,10 @@
 		if (drive->using_dma && !hwif->ide_dma_read(drive))
 			return ide_started;
 
-		if (HWGROUP(drive)->handler != NULL)
-			BUG();
-		ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
-
 		command = ((drive->mult_count) ?
 			   ((lba48) ? WIN_MULTREAD_EXT : WIN_MULTREAD) :
 			   ((lba48) ? WIN_READ_EXT : WIN_READ));
-		hwif->OUTB(command, IDE_COMMAND_REG);
+		ide_execute_command(drive, command, &read_intr, WAIT_CMD, NULL);
 		return ide_started;
 	} else if (rq_data_dir(rq) == WRITE) {
 		ide_startstop_t startstop;
@@ -628,11 +626,7 @@
 
 static task_ioreg_t get_command (ide_drive_t *drive, int cmd)
 {
-	int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0;
-
-#if 1
-	lba48bit = (drive->addressing == 1) ? 1 : 0;
-#endif
+	int lba48bit = (drive->addressing == 1) ? 1 : 0;
 
 	if ((cmd == READ) && drive->using_tcq)
 		return lba48bit ? WIN_READDMA_QUEUED_EXT : WIN_READDMA_QUEUED;
@@ -1412,32 +1406,6 @@
 	return call_idedisk_standby(drive, 0);
 }
 
-#if 0
-static int call_idedisk_checkpower (ide_drive_t *drive, int arg)
-{
-	ide_task_t args;
-	u8 ckpw = (arg) ? WIN_CHECKPOWERMODE2 : WIN_CHECKPOWERMODE1;
-	memset(&args, 0, sizeof(ide_task_t));
-	args.tfRegister[IDE_COMMAND_OFFSET]	= ckpw;
-	args.command_type			= ide_cmd_type_parser(&args);
-	ide_raw_taskfile(drive, &args, NULL);
-#if 0
-if (errno != EIO || args[0] != 0 || args[1] != 0)
-   state = "unknown";
-else
-   state = "sleeping";
-} else {
-   state = (args[2] == 255) ? "active/idle" : "standby";
-#endif
-	return 0;
-}
-
-static int do_idedisk_checkpower (ide_drive_t *drive)
-{
-	return call_idedisk_checkpower(drive, 0);
-}
-#endif
-
 static int do_idedisk_flushcache (ide_drive_t *drive)
 {
 	ide_task_t args;
@@ -1596,13 +1564,8 @@
 			drive->doorlocking = 1;
 		}
 	}
-#if 1
+
 	(void) probe_lba_addressing(drive, 1);
-#else
-	/* if using 48-bit addressing bump the request size up */
-	if (probe_lba_addressing(drive, 1))
-		blk_queue_max_sectors(&drive->queue, 2048);
-#endif
 
 	/* Extract geometry if we did not already have one for the drive */
 	if (!drive->cyl || !drive->head || !drive->sect) {
@@ -1675,13 +1638,9 @@
 
 static int idedisk_cleanup (ide_drive_t *drive)
 {
+	static int ide_cacheflush_p(ide_drive_t *drive);
 	struct gendisk *g = drive->disk;
-
-	do_idedisk_standby(drive);
-	if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
-		if (do_idedisk_flushcache(drive))
-			printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
-				drive->name);
+	ide_cacheflush_p(drive);
 	if (ide_unregister_subdriver(drive))
 		return 1;
 	del_gendisk(g);
@@ -1725,6 +1684,7 @@
 	drive->usage++;
 	if (drive->removable && drive->usage == 1) {
 		ide_task_t args;
+		u8 cf;
 		memset(&args, 0, sizeof(ide_task_t));
 		args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK;
 		args.command_type = ide_cmd_type_parser(&args);
@@ -1736,6 +1696,32 @@
 		 */
 		if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
 			drive->doorlocking = 0;
+		drive->wcache = 0;
+		/* Cache enabled ? */
+		if (drive->id->csfo & 1)
+		drive->wcache = 1;
+		/* Cache command set available ? */
+		if (drive->id->cfs_enable_1 & (1<<5))
+			drive->wcache = 1;
+		/* ATA6 cache extended commands */
+		cf = drive->id->command_set_2 >> 24;
+		if((cf & 0xC0) == 0x40 && (cf & 0x30) != 0)
+			drive->wcache = 1;
+	}
+	return 0;
+}
+
+static int ide_cacheflush_p(ide_drive_t *drive)
+{
+	if(drive->wcache)
+	{
+		if (do_idedisk_flushcache(drive))
+		{
+			printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
+				drive->name);
+			return -EIO;
+		}
+		return 1;
 	}
 	return 0;
 }
@@ -1752,10 +1738,7 @@
 		if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
 			drive->doorlocking = 0;
 	}
-	if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
-		if (do_idedisk_flushcache(drive))
-			printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
-				drive->name);
+	ide_cacheflush_p(drive);
 	drive->usage--;
 	return 0;
 }
diff -Nru a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
--- a/drivers/ide/ide-dma.c	Tue Feb 25 02:43:50 2003
+++ b/drivers/ide/ide-dma.c	Thu Mar  6 09:21:37 2003
@@ -664,11 +664,6 @@
 	if (drive->media != ide_disk)
 		return 0;
 
-	/* paranoia check */
-	if (HWGROUP(drive)->handler != NULL)
-		BUG();
-	ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
-
 	command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA;
 	
 	if (drive->vdma)
@@ -680,8 +675,7 @@
 	}
 
 	/* issue cmd to drive */
-	hwif->OUTB(command, IDE_COMMAND_REG);
-
+	ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
 	return HWIF(drive)->ide_dma_count(drive);
 }
 
@@ -702,11 +696,6 @@
 	if (drive->media != ide_disk)
 		return 0;
 
-	/* paranoia check */
-	if (HWGROUP(drive)->handler != NULL)
-		BUG();
-	ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
-
 	command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
 	if (drive->vdma)
 		command = (lba48) ? WIN_WRITE_EXT: WIN_WRITE;
@@ -717,7 +706,7 @@
 	}
 
 	/* issue cmd to drive */
-	hwif->OUTB(command, IDE_COMMAND_REG);
+	ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
 
 	return HWIF(drive)->ide_dma_count(drive);
 }
diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
--- a/drivers/ide/ide-floppy.c	Tue Feb 18 10:06:17 2003
+++ b/drivers/ide/ide-floppy.c	Tue Feb 18 10:06:17 2003
@@ -1077,14 +1077,11 @@
 	}
 	
 	if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) {
-		if (HWGROUP(drive)->handler != NULL)
-			BUG();
-		ide_set_handler(drive,
+		/* Issue the packet command */
+		ide_execute_command(drive, WIN_PACKETCMD,
 				pkt_xfer_routine,
 				IDEFLOPPY_WAIT_CMD,
 				NULL);
-		/* Issue the packet command */
-		HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
 		return ide_started;
 	} else {
 		/* Issue the packet command */
diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
--- a/drivers/ide/ide-io.c	Mon Feb 24 10:30:38 2003
+++ b/drivers/ide/ide-io.c	Thu Mar  6 09:21:48 2003
@@ -358,18 +358,15 @@
  *	Issue a simple drive command with interrupts.
  *	The drive must be selected beforehand.
  */
- 
+
 void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	if (HWGROUP(drive)->handler != NULL)
-		BUG();
-	ide_set_handler(drive, handler, WAIT_CMD, NULL);
 	if (IDE_CONTROL_REG)
 		hwif->OUTB(drive->ctl,IDE_CONTROL_REG);	/* clear nIEN */
 	SELECT_MASK(drive,0);
 	hwif->OUTB(nsect,IDE_NSECTOR_REG);
-	hwif->OUTB(cmd,IDE_COMMAND_REG);
+	ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL);
 }
 
 EXPORT_SYMBOL(ide_cmd);
@@ -841,14 +838,14 @@
 		 * happens anyway when any interrupt comes in, IDE or otherwise
 		 *  -- the kernel masks the IRQ while it is being handled.
 		 */
-		if (masked_irq && hwif->irq != masked_irq)
+		if (hwif->irq != masked_irq)
 			disable_irq_nosync(hwif->irq);
 		spin_unlock(&ide_lock);
 		local_irq_enable();
 			/* allow other IRQs while we start this request */
 		startstop = start_request(drive, rq);
 		spin_lock_irq(&ide_lock);
-		if (masked_irq && hwif->irq != masked_irq)
+		if (hwif->irq != masked_irq)
 			enable_irq(hwif->irq);
 		if (startstop == ide_released)
 			goto queue_next;
@@ -864,7 +861,7 @@
  */
 void do_ide_request(request_queue_t *q)
 {
-	ide_do_request(q->queuedata, 0);
+	ide_do_request(q->queuedata, IDE_NO_IRQ);
 }
 
 /*
@@ -1012,7 +1009,7 @@
 				hwgroup->busy = 0;
 		}
 	}
-	ide_do_request(hwgroup, 0);
+	ide_do_request(hwgroup, IDE_NO_IRQ);
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
@@ -1302,7 +1299,7 @@
 		insert_end = 0;
 	}
 	__elv_add_request(&drive->queue, rq, insert_end, 0);
-	ide_do_request(hwgroup, 0);
+	ide_do_request(hwgroup, IDE_NO_IRQ);
 	spin_unlock_irqrestore(&ide_lock, flags);
 
 	err = 0;
diff -Nru a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
--- a/drivers/ide/ide-iops.c	Tue Feb 18 10:06:17 2003
+++ b/drivers/ide/ide-iops.c	Thu Feb 20 08:50:44 2003
@@ -59,11 +59,11 @@
 {
 }
 
-static void ide_unplugged_outb (u8 addr, unsigned long port)
+static void ide_unplugged_outb (u8 val, unsigned long port)
 {
 }
 
-static void ide_unplugged_outw (u16 addr, unsigned long port)
+static void ide_unplugged_outw (u16 val, unsigned long port)
 {
 }
 
@@ -71,7 +71,7 @@
 {
 }
 
-static void ide_unplugged_outl (u32 addr, unsigned long port)
+static void ide_unplugged_outl (u32 val, unsigned long port)
 {
 }
 
@@ -125,14 +125,14 @@
 	insl(port, addr, count);
 }
 
-static void ide_outb (u8 addr, unsigned long port)
+static void ide_outb (u8 val, unsigned long port)
 {
-	outb(addr, port);
+	outb(val, port);
 }
 
-static void ide_outw (u16 addr, unsigned long port)
+static void ide_outw (u16 val, unsigned long port)
 {
-	outw(addr, port);
+	outw(val, port);
 }
 
 static void ide_outsw (unsigned long port, void *addr, u32 count)
@@ -140,9 +140,9 @@
 	outsw(port, addr, count);
 }
 
-static void ide_outl (u32 addr, unsigned long port)
+static void ide_outl (u32 val, unsigned long port)
 {
-	outl(addr, port);
+	outl(val, port);
 }
 
 static void ide_outsl (unsigned long port, void *addr, u32 count)
diff -Nru a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
--- a/drivers/ide/ide-lib.c	Thu Nov 14 09:12:22 2002
+++ b/drivers/ide/ide-lib.c	Tue Feb 18 10:06:17 2003
@@ -171,7 +171,7 @@
 		BUG();
 	return min(speed, speed_max[mode]);
 #else /* !CONFIG_BLK_DEV_IDEDMA */
-	return min(speed, (u8)XFER_PIO_4);
+	return min(speed, XFER_PIO_4);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
--- a/drivers/ide/ide-probe.c	Tue Feb 18 10:06:17 2003
+++ b/drivers/ide/ide-probe.c	Sat Mar  8 14:50:22 2003
@@ -1292,11 +1292,8 @@
 	/* we set it back to 1 if all is ok below */	
 	hwif->present = 0;
 
-	if (register_blkdev (hwif->major, hwif->name, ide_fops)) {
-		printk("%s: UNABLE TO GET MAJOR NUMBER %d\n",
-			hwif->name, hwif->major);
+	if (register_blkdev(hwif->major, hwif->name))
 		return 0;
-	}
 
 	if (alloc_disks(hwif) < 0)
 		goto out;
diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
--- a/drivers/ide/ide-taskfile.c	Wed Nov 13 07:06:17 2002
+++ b/drivers/ide/ide-taskfile.c	Tue Feb 18 10:06:17 2003
@@ -177,8 +177,7 @@
 
 	hwif->OUTB((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
 	if (task->handler != NULL) {
-		ide_set_handler(drive, task->handler, WAIT_WORSTCASE, NULL);
-		hwif->OUTB(taskfile->command, IDE_COMMAND_REG);
+		ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
 		if (task->prehandler != NULL)
 			return task->prehandler(drive, task->rq);
 		return ide_started;
@@ -1880,9 +1879,8 @@
  			if (task->handler == NULL)
 				return ide_stopped;
 
-			ide_set_handler(drive, task->handler, WAIT_WORSTCASE, NULL);
 			/* Issue the command */
-			hwif->OUTB(taskfile->command, IDE_COMMAND_REG);
+			ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
 			if (task->prehandler != NULL)
 				return task->prehandler(drive, HWGROUP(drive)->rq);
 	}
diff -Nru a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
--- a/drivers/ide/legacy/hd.c	Wed Nov 20 17:00:00 2002
+++ b/drivers/ide/legacy/hd.c	Sat Mar  8 14:50:22 2003
@@ -708,10 +708,10 @@
 static int __init hd_init(void)
 {
 	int drive;
-	if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
-		printk("hd: unable to get major %d for hard disk\n",MAJOR_NR);
+
+	if (register_blkdev(MAJOR_NR,"hd"))
 		return -1;
-	}
+
 	blk_init_queue(&hd_queue, do_hd_request, &hd_lock);
 	blk_queue_max_sectors(&hd_queue, 255);
 	init_timer(&device_timer);
diff -Nru a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
--- a/drivers/ide/pci/amd74xx.c	Wed Feb 19 12:15:57 2003
+++ b/drivers/ide/pci/amd74xx.c	Mon Mar  3 12:09:31 2003
@@ -82,7 +82,7 @@
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 
-static long amd_base;
+static unsigned long amd_base;
 static struct pci_dev *bmide_dev;
 extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */
 
@@ -102,7 +102,7 @@
 
 	amd_print("----------AMD BusMastering IDE Configuration----------------");
 
-	amd_print("Driver Version:                     2.8");
+	amd_print("Driver Version:                     2.9");
 	amd_print("South Bridge:                       %s", bmide_dev->dev.name);
 
 	pci_read_config_byte(dev, PCI_REVISION_ID, &t);
@@ -284,7 +284,7 @@
  * and initialize its drive independent registers.
  */
 
-unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char *name)
+static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char *name)
 {
 	unsigned char t;
 	unsigned int u;
@@ -378,12 +378,12 @@
 	return 0;
 }
 
-unsigned int __init ata66_amd74xx(ide_hwif_t *hwif)
+static unsigned int __init ata66_amd74xx(ide_hwif_t *hwif)
 {
 	return ((amd_enabled & amd_80w) >> hwif->channel) & 1;
 }
 
-void __init init_hwif_amd74xx(ide_hwif_t *hwif)
+static void __init init_hwif_amd74xx(ide_hwif_t *hwif)
 {
 	int i;
 
diff -Nru a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
--- a/drivers/ide/pci/via82cxxx.c	Wed Feb 19 12:13:48 2003
+++ b/drivers/ide/pci/via82cxxx.c	Mon Mar  3 12:11:59 2003
@@ -1,16 +1,6 @@
 /*
- * $Id: via82cxxx.c,v 3.35-ac2 2002/09/111 Alan Exp $
  *
- *  Copyright (c) 2000-2001 Vojtech Pavlik
- *
- *  Based on the work of:
- *	Michel Aubry
- *	Jeff Garzik
- *	Andre Hedrick
- */
-
-/*
- * Version 3.35
+ * Version 3.36
  *
  * VIA IDE driver for Linux. Supported southbridges:
  *
@@ -24,6 +14,10 @@
  *	Michel Aubry
  *	Jeff Garzik
  *	Andre Hedrick
+ *
+ * Documentation:
+ *	Obsolete device documentation publically available from via.com.tw
+ *	Current device documentation available under NDA only
  */
 
 /*
@@ -67,6 +61,7 @@
 #define VIA_SET_FIFO		0x040	/* Needs to have FIFO split set */
 #define VIA_NO_UNMASK		0x080	/* Doesn't work with IRQ unmasking on */
 #define VIA_BAD_ID		0x100	/* Has wrong vendor ID (0x1107) */
+#define VIA_BAD_AST		0x200	/* Don't touch Address Setup Timing */
 
 /*
  * VIA SouthBridge chips.
@@ -82,8 +77,8 @@
 #ifdef FUTURE_BRIDGES
 	{ "vt8237",	PCI_DEVICE_ID_VIA_8237,     0x00, 0x2f, VIA_UDMA_133 },
 #endif
-	{ "vt8235",	PCI_DEVICE_ID_VIA_8235,     0x00, 0x2f, VIA_UDMA_133 },
-	{ "vt8233a",	PCI_DEVICE_ID_VIA_8233A,    0x00, 0x2f, VIA_UDMA_133 },
+	{ "vt8235",	PCI_DEVICE_ID_VIA_8235,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
+	{ "vt8233a",	PCI_DEVICE_ID_VIA_8233A,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
 	{ "vt8233c",	PCI_DEVICE_ID_VIA_8233C_0,  0x00, 0x2f, VIA_UDMA_100 },
 	{ "vt8233",	PCI_DEVICE_ID_VIA_8233_0,   0x00, 0x2f, VIA_UDMA_100 },
 	{ "vt8231",	PCI_DEVICE_ID_VIA_8231,     0x00, 0x2f, VIA_UDMA_100 },
@@ -152,7 +147,7 @@
 	via_print("----------VIA BusMastering IDE Configuration"
 		"----------------");
 
-	via_print("Driver Version:                     3.35-ac");
+	via_print("Driver Version:                     3.36");
 	via_print("South Bridge:                       VIA %s",
 		via_config->name);
 
@@ -292,9 +287,11 @@
 {
 	u8 t;
 
-	pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);
-	t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
-	pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t);
+	if (~via_config->flags & VIA_BAD_AST) {
+		pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);
+		t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
+		pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t);
+	}
 
 	pci_write_config_byte(dev, VIA_8BIT_TIMING + (1 - (dn >> 1)),
 		((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1));
diff -Nru a/drivers/isdn/hardware/avm/b1pci.c b/drivers/isdn/hardware/avm/b1pci.c
--- a/drivers/isdn/hardware/avm/b1pci.c	Thu Aug 15 15:01:13 2002
+++ b/drivers/isdn/hardware/avm/b1pci.c	Sat Feb 22 09:42:22 2003
@@ -343,12 +343,16 @@
 
 static void __devexit b1pci_pci_remove(struct pci_dev *pdev)
 {
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
 	avmcard *card = pci_get_drvdata(pdev);
 
 	if (card->dma)
 		b1pciv4_remove(pdev);
 	else
 		b1pci_remove(pdev);
+#else
+	b1pci_remove(pdev);
+#endif
 }
 
 static struct pci_driver b1pci_pci_driver = {
diff -Nru a/drivers/isdn/hisax/amd7930.c b/drivers/isdn/hisax/amd7930.c
--- a/drivers/isdn/hisax/amd7930.c	Sun Jan 12 16:05:35 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,717 +0,0 @@
-/* $Id: amd7930.c,v 1.5.6.4 2001/09/23 22:24:46 kai Exp $
- *
- * HiSax ISDN driver - chip specific routines for AMD 7930
- *
- * Author       Brent Baccala
- * Copyright    by Brent Baccala <baccala@FreeSoft.org>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- *    - Existing ISDN HiSax driver provides all the smarts
- *    - it compiles, runs, talks to an isolated phone switch, connects
- *      to a Cisco, pings go through
- *    - AMD 7930 support only (no DBRI yet)
- *    - no US NI-1 support (may not work on US phone system - untested)
- *    - periodic packet loss, apparently due to lost interrupts
- *    - ISDN sometimes freezes, requiring reboot before it will work again
- *
- * The code is unreliable enough to be consider alpha
- *
- * This file is (c) under GNU General Public License
- *
- * Advanced Micro Devices' Am79C30A is an ISDN/audio chip used in the
- * SparcStation 1+.  The chip provides microphone and speaker interfaces
- * which provide mono-channel audio at 8K samples per second via either
- * 8-bit A-law or 8-bit mu-law encoding.  Also, the chip features an
- * ISDN BRI Line Interface Unit (LIU), I.430 S/T physical interface,
- * which performs basic D channel LAPD processing and provides raw
- * B channel data.  The digital audio channel, the two ISDN B channels,
- * and two 64 Kbps channels to the microprocessor are all interconnected
- * via a multiplexer.
- *
- * This driver interfaces to the Linux HiSax ISDN driver, which performs
- * all high-level Q.921 and Q.931 ISDN functions.  The file is not
- * itself a hardware driver; rather it uses functions exported by
- * the AMD7930 driver in the sparcaudio subsystem (drivers/sbus/audio),
- * allowing the chip to be simultaneously used for both audio and ISDN data.
- * The hardware driver does _no_ buffering, but provides several callbacks
- * which are called during interrupt service and should therefore run quickly.
- *
- * D channel transmission is performed by passing the hardware driver the
- * address and size of an skb's data area, then waiting for a callback
- * to signal successful transmission of the packet.  A task is then
- * queued to notify the HiSax driver that another packet may be transmitted.
- *
- * D channel reception is quite simple, mainly because of:
- *   1) the slow speed of the D channel - 16 kbps, and
- *   2) the presence of an 8- or 32-byte (depending on chip version) FIFO
- *      to buffer the D channel data on the chip
- * Worst case scenario of back-to-back packets with the 8 byte buffer
- * at 16 kbps yields an service time of 4 ms - long enough to preclude
- * the need for fancy buffering.  We queue a background task that copies
- * data out of the receive buffer into an skb, and the hardware driver
- * simply does nothing until we're done with the receive buffer and
- * reset it for a new packet.
- *
- * B channel processing is more complex, because of:
- *   1) the faster speed - 64 kbps,
- *   2) the lack of any on-chip buffering (it interrupts for every byte), and
- *   3) the lack of any chip support for HDLC encapsulation
- *
- * The HiSax driver can put each B channel into one of three modes -
- * L1_MODE_NULL (channel disabled), L1_MODE_TRANS (transparent data relay),
- * and L1_MODE_HDLC (HDLC encapsulation by low-level driver).
- * L1_MODE_HDLC is the most common, used for almost all "pure" digital
- * data sessions.  L1_MODE_TRANS is used for ISDN audio.
- *
- * HDLC B channel transmission is performed via a large buffer into
- * which the skb is copied while performing HDLC bit-stuffing.  A CRC
- * is computed and attached to the end of the buffer, which is then
- * passed to the low-level routines for raw transmission.  Once
- * transmission is complete, the hardware driver is set to enter HDLC
- * idle by successive transmission of mark (all 1) bytes, waiting for
- * the ISDN driver to prepare another packet for transmission and
- * deliver it.
- *
- * HDLC B channel reception is performed via an X-byte ring buffer
- * divided into N sections of X/N bytes each.  Defaults: X=256 bytes, N=4.
- * As the hardware driver notifies us that each section is full, we
- * hand it the next section and schedule a background task to peruse
- * the received section, bit-by-bit, with an HDLC decoder.  As
- * packets are detected, they are copied into a large buffer while
- * decoding HDLC bit-stuffing.  The ending CRC is verified, and if
- * it is correct, we alloc a new skb of the correct length (which we
- * now know), copy the packet into it, and hand it to the upper layers.
- * Optimization: for large packets, we hand the buffer (which also
- * happens to be an skb) directly to the upper layer after an skb_trim,
- * and alloc a new large buffer for future packets, thus avoiding a copy.
- * Then we return to HDLC processing; state is saved between calls.
- * 
- */
-
-#include "hisax.h"
-#include "../../sbus/audio/amd7930.h"
-#include "isac.h"
-#include "isdnl1.h"
-#include "rawhdlc.h"
-#include <linux/interrupt.h>
-
-static const char *amd7930_revision = "$Revision: 1.5.6.4 $";
-
-#define RCV_BUFSIZE	1024	/* Size of raw receive buffer in bytes */
-#define RCV_BUFBLKS	4	/* Number of blocks to divide buffer into
-				 * (must divide RCV_BUFSIZE) */
-
-static void Bchan_fill_fifo(struct BCState *, struct sk_buff *);
-
-static void
-Bchan_xmt_bh(void *data)
-{
-	struct BCState *bcs = data;
-	struct sk_buff *skb;
-
-	if (bcs->hw.amd7930.tx_skb != NULL) {
-		dev_kfree_skb(bcs->hw.amd7930.tx_skb);
-		bcs->hw.amd7930.tx_skb = NULL;
-	}
-	xmit_ready_b(bcs);
-}
-
-static void
-Bchan_xmit_callback(struct BCState *bcs)
-{
-	schedule_work(&bcs->hw.amd7930.xmt_work);
-}
-
-/* B channel transmission: two modes (three, if you count L1_MODE_NULL)
- *
- * L1_MODE_HDLC - We need to do HDLC encapsulation before transmiting
- * the packet (i.e. make_raw_hdlc_data).  Since this can be a
- * time-consuming operation, our completion callback just schedules
- * a bottom half to do encapsulation for the next packet.  In between,
- * the link will just idle
- *
- * L1_MODE_TRANS - Data goes through, well, transparent.  No HDLC encap,
- * and we can't just let the link idle, so the "bottom half" actually
- * gets called during the top half (it's our callback routine in this case),
- * but it's a lot faster now since we don't call make_raw_hdlc_data
- */
-
-static void
-Bchan_fill_fifo(struct BCState *bcs, struct sk_buff *skb)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	int len;
-
-	if ((cs->debug & L1_DEB_HSCX) || (cs->debug & L1_DEB_HSCX_FIFO)) {
-		char tmp[1024];
-		char *t = tmp;
-
-		t += sprintf(t, "amd7930_fill_fifo %c cnt %d",
-			     bcs->channel ? 'B' : 'A', skb->len);
-		if (cs->debug & L1_DEB_HSCX_FIFO)
-			QuickHex(t, skb->data, skb->len);
-		debugl1(cs, tmp);
-	}
-
-	if (bcs->mode == L1_MODE_HDLC) {
-		len = make_raw_hdlc_data(skb->data, skb->len,
-					 bcs->hw.amd7930.tx_buff, RAW_BUFMAX);
-		if (len > 0)
-			amd7930_bxmit(0, bcs->channel,
-				      bcs->hw.amd7930.tx_buff, len,
-				      (void *) &Bchan_xmit_callback,
-				      (void *) bcs);
-		dev_kfree_skb(skb);
-	} else if (bcs->mode == L1_MODE_TRANS) {
-		amd7930_bxmit(0, bcs->channel,
-			      bcs->hw.amd7930.tx_buff, skb->len,
-			      (void *) &Bchan_xmt_bh,
-			      (void *) bcs);
-		bcs->hw.amd7930.tx_skb = skb;
-	} else {
-		dev_kfree_skb(skb);
-	}
-}
-
-static void
-Bchan_mode(struct BCState *bcs, int mode, int bc)
-{
-	struct IsdnCardState *cs = bcs->cs;
-
-	if (cs->debug & L1_DEB_HSCX) {
-		char tmp[40];
-		sprintf(tmp, "AMD 7930 mode %d bchan %d/%d",
-			mode, bc, bcs->channel);
-		debugl1(cs, tmp);
-	}
-	bcs->mode = mode;
-}
-
-/* Bchan_l2l1 is the entry point for upper layer routines that want to
- * transmit on the B channel.  PH_DATA_REQ is a normal packet that
- * we either start transmitting (if idle) or queue (if busy).
- * PH_PULL_REQ can be called to request a callback message (PH_PULL_CNF)
- * once the link is idle.  After a "pull" callback, the upper layer
- * routines can use PH_PULL_IND to send data.
- */
-
-static void
-Bchan_l2l1(struct PStack *st, int pr, void *arg)
-{
-	struct sk_buff *skb = arg;
-
-	switch (pr) {
-		case (PH_DATA_REQ):
-			if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
-				skb_queue_tail(&st->l1.bcs->squeue, skb);
-			} else {
-				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-				Bchan_fill_fifo(st->l1.bcs, skb);
-			}
-			break;
-		case (PH_PULL_IND):
-			if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
-				printk(KERN_WARNING "amd7930: this shouldn't happen\n");
-				break;
-			}
-			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			Bchan_fill_fifo(st->l1.bcs, skb);
-			break;
-		case (PH_PULL_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
-				clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
-			} else
-				set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-			break;
-	}
-}
-
-/* Receiver callback and bottom half - decodes HDLC at leisure (if
- * L1_MODE_HDLC) and passes newly received skb on via bcs->rqueue.  If
- * a large packet is received, stick rv_skb (the buffer that the
- * packet has been decoded into) on the receive queue and alloc a new
- * (large) skb to act as buffer for future receives.  If a small
- * packet is received, leave rv_skb alone, alloc a new skb of the
- * correct size, and copy the packet into it
- */
-
-static void
-Bchan_recv_callback(struct BCState *bcs)
-{
-	struct amd7930_hw *hw = &bcs->hw.amd7930;
-
-	hw->rv_buff_in += RCV_BUFSIZE/RCV_BUFBLKS;
-	hw->rv_buff_in %= RCV_BUFSIZE;
-
-	if (hw->rv_buff_in != hw->rv_buff_out) {
-		amd7930_brecv(0, bcs->channel,
-			      hw->rv_buff + hw->rv_buff_in,
-			      RCV_BUFSIZE/RCV_BUFBLKS,
-			      (void *) &Bchan_recv_callback, (void *) bcs);
-	}
-
-	schedule_work(&hw->rcv_work);
-}
-
-static void
-Bchan_rcv_bh(void *data)
-{
-	struct BCState *bcs = data;
-	struct IsdnCardState *cs = bcs->cs;
-	struct amd7930_hw *hw = &bcs->hw.amd7930;
-	struct sk_buff *skb;
-	int len;
-
-	if (cs->debug & L1_DEB_HSCX) {
-		char tmp[1024];
-
-		sprintf(tmp, "amd7930_Bchan_rcv (%d/%d)",
-			hw->rv_buff_in, hw->rv_buff_out);
-		debugl1(cs, tmp);
-		QuickHex(tmp, hw->rv_buff + hw->rv_buff_out,
-			 RCV_BUFSIZE/RCV_BUFBLKS);
-		debugl1(cs, tmp);
-	}
-
-	do {
-		if (bcs->mode == L1_MODE_HDLC) {
-			while ((len = read_raw_hdlc_data(hw->hdlc_state,
-							 hw->rv_buff + hw->rv_buff_out, RCV_BUFSIZE/RCV_BUFBLKS,
-							 hw->rv_skb->tail, HSCX_BUFMAX))) {
-				if (len > 0 && (cs->debug & L1_DEB_HSCX_FIFO)) {
-					char tmp[1024];
-					char *t = tmp;
-
-					t += sprintf(t, "amd7930_Bchan_rcv %c cnt %d", bcs->channel ? 'B' : 'A', len);
-					QuickHex(t, hw->rv_skb->tail, len);
-					debugl1(cs, tmp);
-				}
-
-				if (len > HSCX_BUFMAX/2) {
-					/* Large packet received */
-
-					if (!(skb = dev_alloc_skb(HSCX_BUFMAX))) {
-						printk(KERN_WARNING "amd7930: receive out of memory");
-					} else {
-						skb_put(hw->rv_skb, len);
-						skb_queue_tail(&bcs->rqueue, hw->rv_skb);
-						hw->rv_skb = skb;
-						bcs->event |= 1 << B_RCVBUFREADY;
-						schedule_work(&bcs->work);
-					}
-				} else if (len > 0) {
-					/* Small packet received */
-
-					if (!(skb = dev_alloc_skb(len))) {
-						printk(KERN_WARNING "amd7930: receive out of memory\n");
-					} else {
-						memcpy(skb_put(skb, len), hw->rv_skb->tail, len);
-						skb_queue_tail(&bcs->rqueue, skb);
-						bcs->event |= 1 << B_RCVBUFREADY;
-						schedule_work(&bcs->work);
-					}
-				} else {
-					/* Reception Error */
-					/* printk("amd7930: B channel receive error\n"); */
-				}
-			}
-		} else if (bcs->mode == L1_MODE_TRANS) {
-			if (!(skb = dev_alloc_skb(RCV_BUFSIZE/RCV_BUFBLKS))) {
-				printk(KERN_WARNING "amd7930: receive out of memory\n");
-			} else {
-				memcpy(skb_put(skb, RCV_BUFSIZE/RCV_BUFBLKS),
-				       hw->rv_buff + hw->rv_buff_out,
-				       RCV_BUFSIZE/RCV_BUFBLKS);
-				skb_queue_tail(&bcs->rqueue, skb);
-				bcs->event |= 1 << B_RCVBUFREADY;
-				schedule_work(&bcs->work);
-			}
-		}
-
-		if (hw->rv_buff_in == hw->rv_buff_out) {
-			/* Buffer was filled up - need to restart receiver */
-			amd7930_brecv(0, bcs->channel,
-				      hw->rv_buff + hw->rv_buff_in,
-				      RCV_BUFSIZE/RCV_BUFBLKS,
-				      (void *) &Bchan_recv_callback,
-				      (void *) bcs);
-		}
-
-		hw->rv_buff_out += RCV_BUFSIZE/RCV_BUFBLKS;
-		hw->rv_buff_out %= RCV_BUFSIZE;
-
-	} while (hw->rv_buff_in != hw->rv_buff_out);
-}
-
-static void
-Bchan_close(struct BCState *bcs)
-{
-	struct sk_buff *skb;
-
-	Bchan_mode(bcs, 0, 0);
-	amd7930_bclose(0, bcs->channel);
-
-	if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
-		skb_queue_purge(&bcs->rqueue);
-		skb_queue_purge(&bcs->squeue);
-	}
-	test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
-}
-
-static int
-Bchan_open(struct BCState *bcs)
-{
-	struct amd7930_hw *hw = &bcs->hw.amd7930;
-
-	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
-		skb_queue_head_init(&bcs->rqueue);
-		skb_queue_head_init(&bcs->squeue);
-	}
-	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-
-	amd7930_bopen(0, bcs->channel, 0xff);
-	hw->rv_buff_in = 0;
-	hw->rv_buff_out = 0;
-	hw->tx_skb = NULL;
-	init_hdlc_state(hw->hdlc_state, 0);
-	amd7930_brecv(0, bcs->channel,
-		      hw->rv_buff + hw->rv_buff_in, RCV_BUFSIZE/RCV_BUFBLKS,
-		      (void *) &Bchan_recv_callback, (void *) bcs);
-
-	bcs->event = 0;
-	bcs->tx_cnt = 0;
-	return (0);
-}
-
-static void
-Bchan_init(struct BCState *bcs)
-{
-	if (!(bcs->hw.amd7930.tx_buff = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for amd7930.tx_buff\n");
-		return;
-	}
-	if (!(bcs->hw.amd7930.rv_buff = kmalloc(RCV_BUFSIZE, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for amd7930.rv_buff\n");
-		return;
-	}
-	if (!(bcs->hw.amd7930.rv_skb = dev_alloc_skb(HSCX_BUFMAX))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for amd7930.rv_skb\n");
-		return;
-	}
-	if (!(bcs->hw.amd7930.hdlc_state = kmalloc(sizeof(struct hdlc_state),
-						   GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for amd7930.hdlc_state\n");
-		return;
-	}
-
-	INIT_WORK(&bcs->hw.amd7930.rcv_work, &Bchan_rcv_bh, bcs);
-	INIT_WORK(&bcs->hw.amd7930.xmt_work, &Bchan_xmt_bh, bcs);
-}
-
-static void
-Bchan_manl1(struct PStack *st, int pr,
-	  void *arg)
-{
-	switch (pr) {
-		case (PH_ACTIVATE_REQ):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			Bchan_mode(st->l1.bcs, st->l1.mode, st->l1.bc);
-			st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
-			break;
-		case (PH_DEACTIVATE_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
-				Bchan_mode(st->l1.bcs, 0, 0);
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			break;
-	}
-}
-
-int
-setstack_amd7930(struct PStack *st, struct BCState *bcs)
-{
-	if (Bchan_open(bcs))
-		return (-1);
-	st->l1.bcs = bcs;
-	st->l2.l2l1 = Bchan_l2l1;
-	st->ma.manl1 = Bchan_manl1;
-	setstack_manager(st);
-	bcs->st = st;
-	return (0);
-}
-
-
-static void
-amd7930_drecv_callback(void *arg, int error, unsigned int count)
-{
-	struct IsdnCardState *cs = (struct IsdnCardState *) arg;
-	static struct work_struct task;
-	struct sk_buff *skb;
-
-        /* NOTE: This function is called directly from an interrupt handler */
-
-	if (1) {
-		if (!(skb = alloc_skb(count, GFP_ATOMIC)))
-			printk(KERN_WARNING "HiSax: D receive out of memory\n");
-		else {
-			memcpy(skb_put(skb, count), cs->rcvbuf, count);
-			skb_queue_tail(&cs->rq, skb);
-		}
-
-		INIT_WORK(&task, (void *) DChannel_proc_rcv, (void *) cs);
-		schedule_work(&task);
-	}
-
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char tmp[128];
-		char *t = tmp;
-
-		t += sprintf(t, "amd7930 Drecv cnt %d", count);
-		if (error) t += sprintf(t, " ERR %x", error);
-		QuickHex(t, cs->rcvbuf, count);
-		debugl1(cs, tmp);
-	}
-
-	amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
-		      &amd7930_drecv_callback, cs);
-}
-
-static void
-amd7930_dxmit_callback(void *arg, int error)
-{
-	struct IsdnCardState *cs = (struct IsdnCardState *) arg;
-	static struct work_struct task;
-
-        /* NOTE: This function is called directly from an interrupt handler */
-
-	/* may wish to do retransmission here, if error indicates collision */
-
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char tmp[128];
-		char *t = tmp;
-
-		t += sprintf(t, "amd7930 Dxmit cnt %d", cs->tx_skb->len);
-		if (error) t += sprintf(t, " ERR %x", error);
-		QuickHex(t, cs->tx_skb->data, cs->tx_skb->len);
-		debugl1(cs, tmp);
-	}
-
-	cs->tx_skb = NULL;
-
-	INIT_WORK(&task, (void *) DChannel_proc_xmt, (void *) cs);
-	schedule_work(&task);
-}
-
-static void
-amd7930_Dchan_l2l1(struct PStack *st, int pr, void *arg)
-{
-	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
-	struct sk_buff *skb = arg;
-	char str[64];
-
-	switch (pr) {
-		case (PH_DATA_REQ):
-			if (cs->tx_skb) {
-				skb_queue_tail(&cs->sq, skb);
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
-#endif
-			} else {
-				if ((cs->dlogflag) && (!(skb->data[2] & 1))) {
-					/* I-FRAME */
-					LogFrame(cs, skb->data, skb->len);
-					sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-					dlogframe(cs, skb->data+4, skb->len-4,
-						  str);
-				}
-				cs->tx_skb = skb;
-				cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA", 0);
-#endif
-				amd7930_dxmit(0, skb->data, skb->len,
-					      &amd7930_dxmit_callback, cs);
-			}
-			break;
-		case (PH_PULL_IND):
-			if (cs->tx_skb) {
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
-				skb_queue_tail(&cs->sq, skb);
-				break;
-			}
-			if ((cs->dlogflag) && (!(skb->data[2] & 1))) {	/* I-FRAME */
-				LogFrame(cs, skb->data, skb->len);
-				sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-				dlogframe(cs, skb->data + 4, skb->len - 4,
-					  str);
-			}
-			cs->tx_skb = skb;
-			cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
-#endif
-			amd7930_dxmit(0, cs->tx_skb->data, cs->tx_skb->len,
-				      &amd7930_dxmit_callback, cs);
-			break;
-		case (PH_PULL_REQ):
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				debugl1(cs, "-> PH_REQUEST_PULL");
-#endif
-			if (!cs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-			break;
-	}
-}
-
-int
-setDstack_amd7930(struct PStack *st, struct IsdnCardState *cs)
-{
-	st->l2.l2l1 = amd7930_Dchan_l2l1;
-	if (! cs->rcvbuf) {
-		printk("setDstack_amd7930: No cs->rcvbuf!\n");
-	} else {
-		amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
-			      &amd7930_drecv_callback, cs);
-	}
-	return (0);
-}
-
-static void
-manl1_msg(struct IsdnCardState *cs, int msg, void *arg) {
-	struct PStack *st;
-
-	st = cs->stlist;
-	while (st) {
-		st->ma.manl1(st, msg, arg);
-		st = st->next;
-	}
-}
-
-static void
-amd7930_new_ph(struct IsdnCardState *cs)
-{
-	switch (amd7930_get_liu_state(0)) {
-	        case 3:
-			manl1_msg(cs, PH_POWERUP_CNF, NULL);
-                        break;
-
-	        case 7:
-			manl1_msg(cs, PH_I4_P8_IND, NULL);
-			break;
-
-	        case 8:
-			manl1_msg(cs, PH_RSYNC_IND, NULL);
-			break;
-	}
-}
-
-/* amd7930 LIU state change callback */
-
-static void
-amd7930_liu_callback(struct IsdnCardState *cs)
-{
-	static struct work_struct task;
-
-	if (!cs)
-		return;
-
-	if (cs->debug & L1_DEB_ISAC) {
-		char tmp[32];
-		sprintf(tmp, "amd7930_liu state %d", amd7930_get_liu_state(0));
-		debugl1(cs, tmp);
-	}
-
-	INIT_WORK(&task, (void *) &amd7930_new_ph, (void *) cs);
-	schedule_work(&task);
-}
-
-void
-amd7930_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
-{
-	u8 val;
-	char tmp[32];
-	
-	if (cs->debug & L1_DEB_ISAC) {
-		char tmp[32];
-		sprintf(tmp, "amd7930_l1cmd msg %x", msg);
-		debugl1(cs, tmp);
-	}
-
-	switch(msg) {
-		case PH_RESET_REQ:
-			if (amd7930_get_liu_state(0) <= 3)
-				amd7930_liu_activate(0,0);
-			else
-				amd7930_liu_deactivate(0);
-			break;
-		case PH_ENABLE_REQ:
-			break;
-		case PH_INFO3_REQ:
-			amd7930_liu_activate(0,0);
-			break;
-		case PH_TESTLOOP_REQ:
-			break;
-		default:
-			if (cs->debug & L1_DEB_WARN) {
-				sprintf(tmp, "amd7930_l1cmd unknown %4x", msg);
-				debugl1(cs, tmp);
-			}
-			break;
-	}
-}
-
-static void init_amd7930(struct IsdnCardState *cs)
-{
-	Bchan_init(&cs->bcs[0]);
-	Bchan_init(&cs->bcs[1]);
-	cs->bcs[0].BC_SetStack = setstack_amd7930;
-	cs->bcs[1].BC_SetStack = setstack_amd7930;
-	cs->bcs[0].BC_Close = Bchan_close;
-	cs->bcs[1].BC_Close = Bchan_close;
-	Bchan_mode(cs->bcs, 0, 0);
-	Bchan_mode(cs->bcs + 1, 0, 0);
-}
-
-static int
-amd7930_init(struct IsdnCardState *cs)
-{
-	cs->l1cmd = amd7930_l1cmd;
-	amd7930_liu_init(0, &amd7930_liu_callback, (void *)cs);
-	init_amd7930(cs);
-	return 0;
-}
-
-static struct card_ops amd7930_ops = {
-	.init     = amd7930_init,
-};
-
-int __init
-setup_amd7930(struct IsdnCard *card)
-{
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, amd7930_revision);
-	printk(KERN_INFO "HiSax: AMD7930 driver Rev. %s\n", HiSax_getrev(tmp));
-
-        cs->irq = amd7930_get_irqnum(0);
-        if (cs->irq == 0)
-		return 0;
-
-	cs->card_ops = &amd7930_ops;
-	return 1;
-}
diff -Nru a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
--- a/drivers/isdn/hisax/asuscom.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/asuscom.c	Thu Mar  6 22:52:04 2003
@@ -231,6 +231,51 @@
 	.irq_func = ipac_irq,
 };
 
+static int __init
+asuscom_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	int rc;
+	u8 val;
+
+	printk(KERN_INFO "ISDNLink: defined at %#lx IRQ %lu\n",
+	       card->para[1], card->para[0]);
+
+	cs->hw.asus.cfg_reg = card->para[1];
+	cs->irq = card->para[0];
+
+	rc = -EBUSY;
+	if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, 8, "asuscom isdn"))
+		goto err;
+
+	rc = -ENODEV;
+	cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
+	val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
+	if ((val == 1) || (val == 2)) {
+		cs->subtyp = ASUS_IPAC;
+		cs->card_ops = &asuscom_ipac_ops;
+		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
+		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+			goto err;
+	} else {
+		cs->subtyp = ASUS_ISACHSCX;
+		cs->card_ops = &asuscom_ops;
+		cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
+		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
+		cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
+		cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
+		cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
+		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+			goto err;
+	}
+	printk(KERN_INFO "ISDNLink: resetting card\n");
+	cs->card_ops->reset(cs);
+	return 0;
+
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id asus_ids[] __initdata = {
 	{ ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
@@ -255,9 +300,6 @@
 int __init
 setup_asuscom(struct IsdnCard *card)
 {
-	int bytecnt;
-	struct IsdnCardState *cs = card->cs;
-	u8 val;
 	char tmp[64];
 
 	strcpy(tmp, Asuscom_revision);
@@ -310,36 +352,7 @@
 		}
 	}
 #endif
-	bytecnt = 8;
-	cs->hw.asus.cfg_reg = card->para[1];
-	cs->irq = card->para[0];
-	if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn"))
-		goto err;
-	printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n",
-		cs->hw.asus.cfg_reg, cs->irq);
-	cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
-	val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
-	if ((val == 1) || (val == 2)) {
-		cs->subtyp = ASUS_IPAC;
-		cs->card_ops = &asuscom_ipac_ops;
-		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-	} else {
-		cs->subtyp = ASUS_ISACHSCX;
-		cs->card_ops = &asuscom_ops;
-		cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
-		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
-		cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
-		cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
-		cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
-		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-			goto err;
-	}
-	printk(KERN_INFO "ISDNLink: resetting card\n");
-	cs->card_ops->reset(cs);
+	if (asuscom_probe(card->cs, card) < 0)
+		return 0;
 	return 1;
- err:
-	hisax_release_resources(cs);
-	return 0;
 }
diff -Nru a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c
--- a/drivers/isdn/hisax/avm_a1.c	Sun Jan 12 16:12:36 2003
+++ b/drivers/isdn/hisax/avm_a1.c	Thu Mar  6 22:52:04 2003
@@ -160,16 +160,16 @@
 	.irq_func = avm_a1_interrupt,
 };
 
-int __init
-setup_avm_a1(struct IsdnCard *card)
+static int __init
+avm_a1_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
+	int rc;
 	u8 val;
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
 
-	strcpy(tmp, avm_revision);
-	printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp));
+	printk(KERN_INFO "AVM A1: defined at %#lx IRQ %lu\n",
+	       card->para[1], card->para[0]);
 
+	rc = -EBUSY;
 	cs->hw.avm.cfg_reg     = request_io(&cs->rs, card->para[1] + 0x1800,  8, "avm cfg");
 	if (!cs->hw.avm.cfg_reg) goto err;
 	cs->hw.avm.isac        = request_io(&cs->rs, card->para[1] + 0x1400, 32, "HiSax isac");
@@ -216,23 +216,24 @@
 	printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
 	       cs->hw.avm.cfg_reg, val);
 
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d cfg:0x%X\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.avm.cfg_reg);
-	printk(KERN_INFO
-	       "HiSax: isac:0x%X/0x%X\n",
-	       cs->hw.avm.isac + 32, cs->hw.avm.isacfifo);
-	printk(KERN_INFO
-	       "HiSax: hscx A:0x%X/0x%X  hscx B:0x%X/0x%X\n",
-	       cs->hw.avm.hscx[0] + 32, cs->hw.avm.hscxfifo[0],
-	       cs->hw.avm.hscx[1] + 32, cs->hw.avm.hscxfifo[1]);
-
 	cs->card_ops = &avm_a1_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
-	return 0;
+	return rc;
+}
+
+int __init
+setup_avm_a1(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, avm_revision);
+	printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp));
+
+	if (avm_a1_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c
--- a/drivers/isdn/hisax/avm_a1p.c	Sun Jan 12 16:12:36 2003
+++ b/drivers/isdn/hisax/avm_a1p.c	Thu Mar  6 22:52:04 2003
@@ -215,20 +215,13 @@
 	.irq_func = avm_a1p_interrupt,
 };
 
-int __devinit
-setup_avm_a1_pcmcia(struct IsdnCard *card)
+static int __init
+avm_a1p_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
 	u8 model, vers;
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
 
-
-	strcpy(tmp, avm_revision);
-	printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
-	       HiSax_getrev(tmp));
-	cs->hw.avm.cfg_reg = card->para[1];
 	cs->irq = card->para[0];
-
+	cs->hw.avm.cfg_reg = card->para[1];
 
 	outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0);
 
@@ -244,11 +237,26 @@
 	vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET);
 
 	printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n",
-				cs->hw.avm.cfg_reg, cs->irq, model, vers);
+	       cs->hw.avm.cfg_reg, cs->irq, model, vers);
 
 	cs->card_ops = &avm_a1p_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		return 0;
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+int __devinit
+setup_avm_a1_pcmcia(struct IsdnCard *card)
+{
+	char tmp[64];
 
+	strcpy(tmp, avm_revision);
+	printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
+	       HiSax_getrev(tmp));
+	if (avm_a1p_probe(card->cs, card))
+		return 0;
 	return 1;
 }
diff -Nru a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
--- a/drivers/isdn/hisax/avm_pci.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/avm_pci.c	Thu Mar  6 22:52:04 2003
@@ -497,7 +497,7 @@
 	.close     = close_hdlcstate,
 };
 
-void __init
+static void __init
 inithdlc(struct IsdnCardState *cs)
 {
 	u_int val;
@@ -596,6 +596,82 @@
 	.irq_func = avm_pcipnp_interrupt,
 };
 
+static int __init
+avm_pcipnp_hw_init(struct IsdnCardState *cs)
+{
+	cs->bc_hw_ops = &hdlc_hw_ops;
+	cs->bc_l1_ops = &hdlc_l1_ops;
+	cs->card_ops = &avm_pci_ops;
+	avm_pcipnp_reset(cs);
+	return isac_setup(cs, &isac_ops);
+}
+
+static int __init
+avm_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	int rc;
+	u32 val;
+
+	printk(KERN_INFO "AVM PCI: defined at %#lx IRQ %u\n",
+	       pci_resource_start(pdev, 1), pdev->irq);
+	
+	rc = -EBUSY;
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->subtyp = AVM_FRITZ_PCI;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1);
+	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
+	if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PCI"))
+		goto err;
+
+	val = inl(cs->hw.avm.cfg_reg);
+	printk(KERN_INFO "AVM PCI: stat %#x\n", val);
+	printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
+	       val & 0xff, (val>>8) & 0xff);
+
+	if (avm_pcipnp_hw_init(cs))
+		goto err;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
+static int __init
+avm_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	int rc;
+	u8 val, ver;
+
+	printk(KERN_INFO "AVM PnP: defined at %#lx IRQ %lu\n",
+	       card->para[1], card->para[0]);
+
+	cs->subtyp = AVM_FRITZ_PNP;
+	cs->irq = card->para[0];
+	cs->hw.avm.cfg_reg = card->para[1];
+	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
+
+	rc = -EBUSY;
+	if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PnP"))
+		goto err;
+	
+	val = inb(cs->hw.avm.cfg_reg);
+	ver = inb(cs->hw.avm.cfg_reg + 1);
+	printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
+
+	if (avm_pcipnp_hw_init(cs))
+		goto err;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
 static struct pci_dev *dev_avm __initdata = NULL;
 #ifdef __ISAPNP__
 static struct pnp_card *card_avm __initdata = NULL;
@@ -605,17 +681,15 @@
 int __init
 setup_avm_pcipnp(struct IsdnCard *card)
 {
-	u_int val, ver;
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, avm_pci_rev);
 	printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp));
 	if (card->para[1]) {
 		/* old manual method */
-		cs->hw.avm.cfg_reg = card->para[1];
-		cs->irq = card->para[0];
-		cs->subtyp = AVM_FRITZ_PNP;
+		if (avm_pnp_probe(card->cs, card))
+			return 0;
+		return 1;
 	} else {
 #ifdef __ISAPNP__
 		if (isapnp_present()) {
@@ -647,69 +721,24 @@
 						pnp_device_detach(pnp_avm);
 						return(0);
 					}
-					cs->hw.avm.cfg_reg = pnp_port_start(pnp_avm, 0);
-					cs->irq = pnp_irq(pnp_avm, 0);
-					cs->subtyp = AVM_FRITZ_PNP;
-					goto ready;
+					card->para[1] = pnp_port_start(pnp_avm, 0);
+					card->para[0] = pnp_irq(pnp_avm, 0);
+					if (avm_pnp_probe(card->cs, card))
+						return 0;
+					return 1;
 				}
 			}
-		} else {
-			printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
 		}
 #endif
 #if CONFIG_PCI
 		if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
 			PCI_DEVICE_ID_AVM_A1,  dev_avm))) {
-			cs->irq = dev_avm->irq;
-			if (!cs->irq) {
-				printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
-				return(0);
-			}
-			if (pci_enable_device(dev_avm))
-				return(0);
-			cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
-			if (!cs->hw.avm.cfg_reg) {
-				printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-			cs->subtyp = AVM_FRITZ_PCI;
-		} else {
-			printk(KERN_WARNING "FritzPCI: No PCI card found\n");
-			return(0);
+			if (avm_pci_probe(card->cs, dev_avm))
+				return 0;
+			return 1;
 		}
-		cs->irq_flags |= SA_SHIRQ;
 #endif /* CONFIG_PCI */
 	}
-ready:
-	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
-	if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32,
-		 cs->subtyp == AVM_FRITZ_PCI ? "avm PCI" : "avm PnP"))
-		goto err;
-	
-	switch (cs->subtyp) {
-	  case AVM_FRITZ_PCI:
-		val = inl(cs->hw.avm.cfg_reg);
-		printk(KERN_INFO "AVM PCI: stat %#x\n", val);
-		printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
-			val & 0xff, (val>>8) & 0xff);
-		break;
-	  case AVM_FRITZ_PNP:
-		val = inb(cs->hw.avm.cfg_reg);
-		ver = inb(cs->hw.avm.cfg_reg + 1);
-		printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
-		avm_pcipnp_reset(cs);
-		break;
-	}
-	printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n",
-		(cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP",
-		cs->irq, cs->hw.avm.cfg_reg);
-
-	cs->bc_hw_ops = &hdlc_hw_ops;
-	cs->bc_l1_ops = &hdlc_l1_ops;
-	cs->card_ops = &avm_pci_ops;
-	isac_setup(cs, &isac_ops);
-	return 1;
- err:
-	hisax_release_resources(cs);
+	printk(KERN_WARNING "FritzPCI: No card found\n");
 	return 0;
 }
diff -Nru a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
--- a/drivers/isdn/hisax/bkm_a4t.c	Sun Jan 12 16:12:36 2003
+++ b/drivers/isdn/hisax/bkm_a4t.c	Thu Mar  6 22:52:04 2003
@@ -21,11 +21,11 @@
 #include "bkm_ax.h"
 
 extern const char *CardType[];
+// FIXME needs per card lock
 static spinlock_t bkm_a4t_lock = SPIN_LOCK_UNLOCKED;
 
 const char *bkm_a4t_revision = "$Revision: 1.13.6.6 $";
 
-
 static inline u8
 readreg(unsigned int ale, unsigned long adr, u8 off)
 {
@@ -249,15 +249,57 @@
 	.irq_func = bkm_interrupt,
 };
 
+static int __init
+bkm_a4t_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	I20_REGISTER_FILE *pI20_Regs;
+	int rc;
+
+	printk(KERN_INFO "BKM A4T: defined at %#lx IRQ %u\n",
+	       pci_resource_start(pdev, 0), pdev->irq);
+	
+	rc = -EBUSY;
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1);
+
+	cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "Telekom A4T");
+	if (!cs->hw.ax.base)
+		goto err;
+	
+	/* Check suspicious address */
+	// FIXME needs to use read[bl]
+	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+	if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
+		printk(KERN_WARNING "HiSax: address %lx suspicious\n",
+		       cs->hw.ax.base);
+		goto err;
+	}
+	cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
+	cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
+	cs->hw.ax.isac_ale = GCS_1;
+	cs->hw.ax.jade_ale = GCS_3;
+
+	reset_bkm(cs);
+	cs->card_ops = &bkm_a4t_ops;
+	isac_setup(cs, &isac_ops);
+	jade_setup(cs, &jade_ops);
+	return 0;
+
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
 static struct pci_dev *dev_a4t __initdata = NULL;
 
 int __init
 setup_bkm_a4t(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-	u_int pci_memaddr = 0, found = 0;
-	I20_REGISTER_FILE *pI20_Regs;
 
 	strcpy(tmp, bkm_a4t_revision);
 	printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
@@ -268,49 +310,13 @@
 
 		sub_vendor = dev_a4t->subsystem_vendor;
 		sub_sys = dev_a4t->subsystem_device;
-		if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) {
-			if (pci_enable_device(dev_a4t))
-				return(0);
-			found = 1;
-			pci_memaddr = pci_resource_start(dev_a4t, 0);
-			cs->irq = dev_a4t->irq;
-			break;
+		if (sub_sys == PCI_DEVICE_ID_BERKOM_A4T && 
+		    sub_vendor == PCI_VENDOR_ID_BERKOM) {
+			if (bkm_a4t_probe(card->cs, dev_a4t))
+				return 0;
+			return 1;
 		}
 	}
-	if (!found) {
-		printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
-		return (0);
-	}
-	if (!cs->irq) {		/* IRQ range check ?? */
-		printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
-		return (0);
-	}
-	cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs,pci_memaddr, 4096, "Telekom A4T");
-	if (!cs->hw.ax.base) {
-		printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
-		return (0);
-	}
-	
-	/* Check suspecious address */
-	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
-	if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
-		printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n",
-		       CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096);
-		hisax_release_resources(cs);
-		return (0);
-	}
-	cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
-	cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
-	cs->hw.ax.isac_ale = GCS_1;
-	cs->hw.ax.jade_ale = GCS_3;
-
-	printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n",
-	       CardType[card->typ], cs->hw.ax.base, cs->irq);
-
-	reset_bkm(cs);
-	cs->irq_flags |= SA_SHIRQ;
-	cs->card_ops = &bkm_a4t_ops;
-	isac_setup(cs, &isac_ops);
-	jade_setup(cs, &jade_ops);
-	return 1;
+	printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
--- a/drivers/isdn/hisax/config.c	Wed Jan 15 08:20:56 2003
+++ b/drivers/isdn/hisax/config.c	Thu Mar  6 23:20:18 2003
@@ -490,125 +490,36 @@
 __setup("hisax=", HiSax_setup);
 #endif /* MODULES */
 
-#if CARD_TELES0
 extern int setup_teles0(struct IsdnCard *card);
-#endif
-
-#if CARD_TELES3
 extern int setup_teles3(struct IsdnCard *card);
-#endif
-
-#if CARD_S0BOX
 extern int setup_s0box(struct IsdnCard *card);
-#endif
-
-#if CARD_TELESPCI
 extern int setup_telespci(struct IsdnCard *card);
-#endif
-
-#if CARD_AVM_A1
 extern int setup_avm_a1(struct IsdnCard *card);
-#endif
-
-#if CARD_AVM_A1_PCMCIA
 extern int setup_avm_a1_pcmcia(struct IsdnCard *card);
-#endif
-
-#if CARD_FRITZPCI
 extern int setup_avm_pcipnp(struct IsdnCard *card);
-#endif
-
-#if CARD_ELSA
 extern int setup_elsa(struct IsdnCard *card);
-#endif
-
-#if CARD_IX1MICROR2
 extern int setup_ix1micro(struct IsdnCard *card);
-#endif
-
-#if CARD_DIEHLDIVA
 extern int setup_diva(struct IsdnCard *card);
-#endif
-
-#if CARD_ASUSCOM
 extern int setup_asuscom(struct IsdnCard *card);
-#endif
-
-#if CARD_TELEINT
 extern int setup_TeleInt(struct IsdnCard *card);
-#endif
-
-#if CARD_SEDLBAUER
 extern int setup_sedlbauer(struct IsdnCard *card);
-#endif
-
-#if CARD_SPORTSTER
 extern int setup_sportster(struct IsdnCard *card);
-#endif
-
-#if CARD_MIC
 extern int setup_mic(struct IsdnCard *card);
-#endif
-
-#if CARD_NETJET_S
 extern int setup_netjet_s(struct IsdnCard *card);
-#endif
-
-#if CARD_HFCS
 extern int setup_hfcs(struct IsdnCard *card);
-#endif
-
-#if CARD_HFC_PCI
 extern int setup_hfcpci(struct IsdnCard *card);
-#endif
-
-#if CARD_HFC_SX
 extern int setup_hfcsx(struct IsdnCard *card);
-#endif
-
-#if CARD_AMD7930
 extern int setup_amd7930(struct IsdnCard *card);
-#endif
-
-#if CARD_NICCY
 extern int setup_niccy(struct IsdnCard *card);
-#endif
-
-#if CARD_ISURF
 extern int setup_isurf(struct IsdnCard *card);
-#endif
-
-#if CARD_HSTSAPHIR
 extern int setup_saphir(struct IsdnCard *card);
-#endif
-
-#if CARD_TESTEMU
 extern int setup_testemu(struct IsdnCard *card);
-#endif
-
-#if CARD_BKM_A4T
 extern int setup_bkm_a4t(struct IsdnCard *card);
-#endif
-
-#if CARD_SCT_QUADRO
 extern int setup_sct_quadro(struct IsdnCard *card);
-#endif
-
-#if CARD_GAZEL
 extern int setup_gazel(struct IsdnCard *card);
-#endif
-
-#if CARD_W6692
 extern int setup_w6692(struct IsdnCard *card);
-#endif
-
-#if CARD_NETJET_U
 extern int setup_netjet_u(struct IsdnCard *card);
-#endif
-
-#if CARD_FN_ENTERNOW_PCI
 extern int setup_enternow_pci(struct IsdnCard *card);
-#endif
 
 /*
  * Find card with given driverId
@@ -703,16 +614,16 @@
 	return 8;
 }
 
-static u8 tmpbuf[HISAX_STATUS_BUFSIZE];
+static char tmpbuf[HISAX_STATUS_BUFSIZE];
 
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt,
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt,
 		      va_list args)
 {
 	/* if head == NULL the fmt contains the full info */
 
 	unsigned long flags;
 	int count, i;
-	u8 *p;
+	char *p;
 	isdn_ctrl ic;
 	int len;
 
@@ -727,7 +638,7 @@
 		len = p - tmpbuf;
 		p = tmpbuf;
 	} else {
-		p = fmt;
+		p = (char *) fmt;
 		len = strlen(fmt);
 	}
 	if (!cs) {
@@ -814,12 +725,6 @@
 	ic.command = ISDN_STAT_UNLOAD;
 	ic.driver = cs->myid;
 	cs->iif.statcallb(&ic);
-	if (cs->status_buf)
-		kfree(cs->status_buf);
-	cs->status_read = NULL;
-	cs->status_write = NULL;
-	cs->status_end = NULL;
-	kfree(cs->dlog);
 }
 
 static void closecard(int cardnr)
@@ -893,59 +798,97 @@
 	return 3;
 }
 
+static struct IsdnCardState *
+alloc_IsdnCardState(void)
+{
+	struct IsdnCardState *cs;
+
+	cs = kmalloc(sizeof(*cs), GFP_ATOMIC); // FIXME
+	if (!cs)
+		goto err;
+
+	memset(cs, 0, sizeof(*cs));
+
+	cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC);
+	if (!cs->dlog)
+		goto err_cs;
+
+	cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC);
+	if (!cs->status_buf)
+		goto err_dlog;
+
+	cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC);
+	if (!cs->rcvbuf)
+		goto err_status_buf;
+
+	cs->chanlimit = 2;	/* maximum B-channel number */
+	cs->debug = L1_DEB_WARN;
+	cs->irq_flags = I4L_IRQ_FLAG;
+	cs->stlist = NULL;
+	cs->status_read = cs->status_buf;
+	cs->status_write = cs->status_buf;
+	cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
+	cs->rcvidx = 0;
+	cs->tx_skb = NULL;
+	cs->tx_cnt = 0;
+	cs->event = 0;
+
+	skb_queue_head_init(&cs->rq);
+	skb_queue_head_init(&cs->sq);
+
+	spin_lock_init(&cs->lock);
+	resources_init(&cs->rs);
+	return cs;
+
+ err_status_buf:
+	kfree(cs->status_buf);
+ err_dlog:
+	kfree(cs->dlog);
+ err_cs:
+	kfree(cs);
+ err:
+	return NULL;
+}
+
+static void
+free_IsdnCardState(struct IsdnCardState *cs)
+{
+	kfree(cs->rcvbuf);
+	kfree(cs->status_buf);
+	kfree(cs->dlog);
+	kfree(cs);
+}
+
 static int __devinit checkcard(int cardnr, char *id, int *busy_flag)
 {
 	int ret = 0;
 	struct IsdnCard *card = cards + cardnr;
 	struct IsdnCardState *cs;
 
-	cs = kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC);
+	cs = alloc_IsdnCardState();
 	if (!cs) {
 		printk(KERN_WARNING
 		       "HiSax: No memory for IsdnCardState(card %d)\n",
 		       cardnr + 1);
 		goto out;
 	}
-	memset(cs, 0, sizeof(struct IsdnCardState));
 	card->cs = cs;
-	cs->chanlimit = 2;	/* maximum B-channel number */
-	cs->logecho = 0;	/* No echo logging */
-	cs->cardnr = cardnr;
-	cs->debug = L1_DEB_WARN;
-	cs->HW_Flags = 0;
-	cs->busy_flag = busy_flag;
-	cs->irq_flags = I4L_IRQ_FLAG;
 #if TEI_PER_CARD
 	if (card->protocol == ISDN_PTYPE_NI1)
 		test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
 #else
 	test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
 #endif
+	cs->cardnr = cardnr;
 	cs->protocol = card->protocol;
+	cs->typ = card->typ;
+	cs->busy_flag = busy_flag;
 
 	if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) {
 		printk(KERN_WARNING
 		       "HiSax: Card Type %d out of range\n", card->typ);
 		goto outf_cs;
 	}
-	if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for dlog(card %d)\n", cardnr + 1);
-		goto outf_cs;
-	}
-	if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for status_buf(card %d)\n",
-		       cardnr + 1);
-		goto outf_dlog;
-	}
-	cs->stlist = NULL;
-	cs->status_read = cs->status_buf;
-	cs->status_write = cs->status_buf;
-	cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
-	cs->typ = card->typ;
-	spin_lock_init(&cs->lock);
-	resources_init(&cs->rs);
 	SET_MODULE_OWNER(&cs->iif);
 	strcpy(cs->iif.id, id);
 	cs->iif.channels = 2;
@@ -982,13 +925,13 @@
 	       (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
 	       "NONE", cs->iif.id, cs->myid);
 	switch (card->typ) {
-#if CARD_TELES0
+#ifdef CONFIG_HISAX_16_0
 	case ISDN_CTYPE_16_0:
 	case ISDN_CTYPE_8_0:
 		ret = setup_teles0(card);
 		break;
 #endif
-#if CARD_TELES3
+#ifdef CONFIG_HISAX_16_3
 	case ISDN_CTYPE_16_3:
 	case ISDN_CTYPE_PNP:
 	case ISDN_CTYPE_TELESPCMCIA:
@@ -996,32 +939,32 @@
 		ret = setup_teles3(card);
 		break;
 #endif
-#if CARD_S0BOX
+#ifdef CONFIG_HISAX_S0BOX
 	case ISDN_CTYPE_S0BOX:
 		ret = setup_s0box(card);
 		break;
 #endif
-#if CARD_TELESPCI
+#ifdef CONFIG_HISAX_TELESPCI
 	case ISDN_CTYPE_TELESPCI:
 		ret = setup_telespci(card);
 		break;
 #endif
-#if CARD_AVM_A1
+#ifdef CONFIG_HISAX_AVM_A1
 	case ISDN_CTYPE_A1:
 		ret = setup_avm_a1(card);
 		break;
 #endif
-#if CARD_AVM_A1_PCMCIA
+#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
 	case ISDN_CTYPE_A1_PCMCIA:
 		ret = setup_avm_a1_pcmcia(card);
 		break;
 #endif
-#if CARD_FRITZPCI
+#ifdef CONFIG_HISAX_FRITZPCI
 	case ISDN_CTYPE_FRITZPCI:
 		ret = setup_avm_pcipnp(card);
 		break;
 #endif
-#if CARD_ELSA
+#ifdef CONFIG_HISAX_ELSA
 	case ISDN_CTYPE_ELSA:
 	case ISDN_CTYPE_ELSA_PNP:
 	case ISDN_CTYPE_ELSA_PCMCIA:
@@ -1029,115 +972,115 @@
 		ret = setup_elsa(card);
 		break;
 #endif
-#if CARD_IX1MICROR2
+#ifdef CONFIG_HISAX_IX1MICROR2
 	case ISDN_CTYPE_IX1MICROR2:
 		ret = setup_ix1micro(card);
 		break;
 #endif
-#if CARD_DIEHLDIVA
+#ifdef CONFIG_HISAX_DIEHLDIVA
 	case ISDN_CTYPE_DIEHLDIVA:
 		ret = setup_diva(card);
 		break;
 #endif
-#if CARD_ASUSCOM
+#ifdef CONFIG_HISAX_ASUSCOM
 	case ISDN_CTYPE_ASUSCOM:
 		ret = setup_asuscom(card);
 		break;
 #endif
-#if CARD_TELEINT
+#ifdef CONFIG_HISAX_TELEINT
 	case ISDN_CTYPE_TELEINT:
 		ret = setup_TeleInt(card);
 		break;
 #endif
-#if CARD_SEDLBAUER
+#ifdef CONFIG_HISAX_SEDLBAUER
 	case ISDN_CTYPE_SEDLBAUER:
 	case ISDN_CTYPE_SEDLBAUER_PCMCIA:
 	case ISDN_CTYPE_SEDLBAUER_FAX:
 		ret = setup_sedlbauer(card);
 		break;
 #endif
-#if CARD_SPORTSTER
+#ifdef CONFIG_HISAX_SPORTSTER
 	case ISDN_CTYPE_SPORTSTER:
 		ret = setup_sportster(card);
 		break;
 #endif
-#if CARD_MIC
+#ifdef CONFIG_HISAX_MIC
 	case ISDN_CTYPE_MIC:
 		ret = setup_mic(card);
 		break;
 #endif
-#if CARD_NETJET_S
+#ifdef CONFIG_HISAX_NETJET
 	case ISDN_CTYPE_NETJET_S:
 		ret = setup_netjet_s(card);
 		break;
 #endif
-#if CARD_HFCS
+#ifdef CONFIG_HISAX_HFCS
 	case ISDN_CTYPE_TELES3C:
 	case ISDN_CTYPE_ACERP10:
 		ret = setup_hfcs(card);
 		break;
 #endif
-#if CARD_HFC_PCI
+#ifdef CONFIG_HISAX_HFC_PCI
 	case ISDN_CTYPE_HFC_PCI:
 		ret = setup_hfcpci(card);
 		break;
 #endif
-#if CARD_HFC_SX
+#ifdef CONFIG_HISAX_HFC_SX
 	case ISDN_CTYPE_HFC_SX:
 		ret = setup_hfcsx(card);
 		break;
 #endif
-#if CARD_NICCY
+#ifdef CONFIG_HISAX_NICCY
 	case ISDN_CTYPE_NICCY:
 		ret = setup_niccy(card);
 		break;
 #endif
-#if CARD_AMD7930
+#ifdef CONFIG_HISAX_AMD7930
 	case ISDN_CTYPE_AMD7930:
 		ret = setup_amd7930(card);
 		break;
 #endif
-#if CARD_ISURF
+#ifdef CONFIG_HISAX_ISURF
 	case ISDN_CTYPE_ISURF:
 		ret = setup_isurf(card);
 		break;
 #endif
-#if CARD_HSTSAPHIR
+#ifdef CONFIG_HISAX_HSTSAPHIR
 	case ISDN_CTYPE_HSTSAPHIR:
 		ret = setup_saphir(card);
 		break;
 #endif
-#if CARD_TESTEMU
+#ifdef CONFIG_HISAX_TESTEMU
 	case ISDN_CTYPE_TESTEMU:
 		ret = setup_testemu(card);
 		break;
 #endif
-#if	CARD_BKM_A4T
+#ifdef CONFIG_HISAX_BKM_A4T
 	case ISDN_CTYPE_BKM_A4T:
 		ret = setup_bkm_a4t(card);
 		break;
 #endif
-#if	CARD_SCT_QUADRO
+#ifdef CONFIG_HISAX_SCT_QUADRO
 	case ISDN_CTYPE_SCT_QUADRO:
 		ret = setup_sct_quadro(card);
 		break;
 #endif
-#if CARD_GAZEL
+#ifdef CONFIG_HISAX_GAZEL
 	case ISDN_CTYPE_GAZEL:
 		ret = setup_gazel(card);
 		break;
 #endif
-#if CARD_W6692
+#ifdef CONFIG_HISAX_W6692
 	case ISDN_CTYPE_W6692:
 		ret = setup_w6692(card);
 		break;
 #endif
-#if CARD_NETJET_U
+#ifdef CONFIG_HISAX_NETJET_U
 	case ISDN_CTYPE_NETJET_U:
 		ret = setup_netjet_u(card);
 		break;
 #endif
-#if CARD_FN_ENTERNOW_PCI
+#ifdef CONFIG_HISAX_ENTERNOW_PCI
 	case ISDN_CTYPE_ENTERNOW:
 		ret = setup_enternow_pci(card);
 		break;
@@ -1156,19 +1099,6 @@
 		ll_unload(cs);
 		goto outf_cs;
 	}
-	if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
-		printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n");
-		ll_unload(cs);
-		goto outf_cs;
-	}
-	cs->rcvidx = 0;
-	cs->tx_skb = NULL;
-	cs->tx_cnt = 0;
-	cs->event = 0;
-
-	skb_queue_head_init(&cs->rq);
-	skb_queue_head_init(&cs->sq);
-
 	init_bcstate(cs, 0);
 	init_bcstate(cs, 1);
 
@@ -1201,10 +1131,8 @@
 	ret = 1;
 	goto out;
 
- outf_dlog:
-	kfree(cs->dlog);
  outf_cs:
-	kfree(cs);
+	free_IsdnCardState(cs);
 	card->cs = NULL;
  out:
 	return ret;
@@ -1253,8 +1181,8 @@
 			i++;
 		} else {
 			printk(KERN_WARNING
-			       "HiSax: Card %s not installed !\n",
-			       CardType[cards[i].typ]);
+			       "HiSax: Card type %d not installed !\n",
+			       cards[i].typ);
 			HiSax_shiftcards(i);
 			nrcards--;
 		}
diff -Nru a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
--- a/drivers/isdn/hisax/diva.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/diva.c	Thu Mar  6 22:52:04 2003
@@ -362,7 +362,7 @@
 static void
 diva_release(struct IsdnCardState *cs)
 {
-	del_timer(&cs->hw.diva.tl);
+	del_timer_sync(&cs->hw.diva.tl);
 	if (cs->hw.diva.cfg_reg)
 		byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */
 
@@ -515,6 +515,162 @@
 	.irq_func    = diva_ipacx_pci_irq,
 };
 
+static int __init
+diva_ipac_probe(struct IsdnCardState *cs)
+{
+	u8 val;
+
+	// request_io
+	val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
+		      cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
+	printk(KERN_INFO "Diva: IPAC version %x\n", val);
+	return (val == 1 || val == 2);
+}
+
+static int __init
+diva_ipac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = DIVA_IPAC_ISA;
+	cs->irq = card->para[0];
+	cs->hw.diva.cfg_reg  = card->para[1];
+	cs->hw.diva.isac     = card->para[1] + DIVA_IPAC_DATA;
+	cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
+	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
+	       "IPAC ISA", cs->hw.diva.cfg_reg, cs->irq);
+	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn"))
+		goto err;
+	diva_ipac_isa_reset(cs);
+	cs->card_ops = &diva_ipac_isa_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+diva_isac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = DIVA_ISA;
+	cs->irq = card->para[0];
+	cs->hw.diva.cfg_reg  = card->para[1];
+	cs->hw.diva.ctrl     = card->para[1] + DIVA_ISA_CTRL;
+	cs->hw.diva.isac     = card->para[1] + DIVA_ISA_ISAC_DATA;
+	cs->hw.diva.hscx     = card->para[1] + DIVA_HSCX_DATA;
+	cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
+	cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
+	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
+	       "ISA", cs->hw.diva.cfg_reg, cs->irq);
+	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn"))
+		goto err;
+	diva_reset(cs);
+	init_timer(&cs->hw.diva.tl);
+	cs->hw.diva.tl.function = (void *) diva_led_handler;
+	cs->hw.diva.tl.data = (long) cs;
+	cs->card_ops = &diva_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+diva_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	int is_ipac;
+	cs->hw.diva.cfg_reg  = card->para[1];
+	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn"))
+		return -EBUSY;
+
+	is_ipac = diva_ipac_probe(cs);
+	hisax_release_resources(cs);
+
+	if (is_ipac)
+		return diva_ipac_isa_probe(cs, card);
+	else
+		return diva_isac_isa_probe(cs, card);
+}
+
+static int __init
+diva_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = DIVA_PCI;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.diva.cfg_reg  = pci_resource_start(pdev, 2);
+	cs->hw.diva.ctrl     = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
+	cs->hw.diva.isac     = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
+	cs->hw.diva.hscx     = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
+	cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
+	cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
+	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
+	       "PCI", cs->hw.diva.cfg_reg, cs->irq);
+	printk(KERN_INFO "Diva: %s space at %#lx\n",
+	       "PCI", cs->hw.diva.pci_cfg);
+	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 32, "diva isdn"))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+diva_ipac_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = DIVA_IPAC_PCI;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.diva.pci_cfg = (unsigned long)request_mmio(
+		&cs->rs, pci_resource_start(pdev, 0), 4096, "diva");
+	cs->hw.diva.cfg_reg = (unsigned long)request_mmio(
+		&cs->rs, pci_resource_start(pdev, 1), 4096, "diva");
+	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
+	       "IPAC PCI", cs->hw.diva.cfg_reg, cs->irq);
+	printk(KERN_INFO "Diva: %s space at %#lx\n",
+	       "IPAC PCI", cs->hw.diva.pci_cfg);
+	diva_ipac_pci_reset(cs);
+	cs->card_ops = &diva_ipac_pci_ops;
+	if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+diva_ipacx_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = DIVA_IPACX_PCI;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
+	       "IPACX PCI", cs->hw.diva.cfg_reg, cs->irq);
+	printk(KERN_INFO "Diva: %s space at %#lx\n",
+	       "IPACX PCI", cs->hw.diva.pci_cfg);
+	diva_ipacx_pci_reset(cs);
+	cs->card_ops = &diva_ipacx_pci_ops;
+	if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *dev_diva __initdata = NULL;
 static struct pci_dev *dev_diva_u __initdata = NULL;
 static struct pci_dev *dev_diva201 __initdata = NULL;
@@ -545,101 +701,60 @@
 static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
-
 int __init
 setup_diva(struct IsdnCard *card)
 {
-	int bytecnt = 8;
-	u8 val;
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, Diva_revision);
 	printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp));
 	if (card->para[1]) {
-		cs->hw.diva.ctrl_reg = 0;
-		cs->hw.diva.cfg_reg = card->para[1];
-		val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
-			cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
-		printk(KERN_INFO "Diva: IPAC version %x\n", val);
-		if ((val == 1) || (val==2)) {
-			cs->subtyp = DIVA_IPAC_ISA;
-			cs->hw.diva.ctrl = 0;
-			cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA;
-			cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA;
-			cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
-			cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR;
-		} else {
-			cs->subtyp = DIVA_ISA;
-			cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;
-			cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA;
-			cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA;
-			cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
-			cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
-		}
-		cs->irq = card->para[0];
-	} else {
+		if (diva_isa_probe(card->cs, card) < 0)
+			return 0;
+		return 1;
+		
+	}
 #ifdef __ISAPNP__
-		if (isapnp_present()) {
-			struct pnp_card *pb;
-			struct pnp_dev *pd;
-
-			while(pdev->card_vendor) {
-				if ((pb = pnp_find_card(pdev->card_vendor,
-							pdev->card_device,
-							pnp_c))) {
-					pnp_c = pb;
-					pd = NULL;
-					if ((pd = pnp_find_dev(pnp_c,
-							       pdev->vendor,
-							       pdev->function,
-							       pd))) {
-						printk(KERN_INFO "HiSax: %s detected\n",
-							(char *)pdev->driver_data);
-						if (pnp_device_attach(pd) < 0) {
-							printk(KERN_ERR "Diva PnP: attach failed\n");
+	if (isapnp_present()) {
+		struct pnp_card *pb;
+		struct pnp_dev *pd;
+		
+		while(pdev->card_vendor) {
+			if ((pb = pnp_find_card(pdev->card_vendor,
+						pdev->card_device, pnp_c))) {
+				pnp_c = pb;
+				pd = NULL;
+				if ((pd = pnp_find_dev(pnp_c,
+						       pdev->vendor,
+						       pdev->function,
+						       pd))) {
+					printk(KERN_INFO "HiSax: %s detected\n",
+					       (char *)pdev->driver_data);
+					if (pnp_device_attach(pd) < 0) {
+						printk(KERN_ERR "Diva PnP: attach failed\n");
+						return 0;
+					}
+					if (pnp_activate_dev(pd) < 0) {
+						printk(KERN_ERR "Diva PnP: activate failed\n");
+						pnp_device_detach(pd);
+						return 0;
+					}
+					if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
+						printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
+						       pnp_irq(pd, 0), pnp_port_start(pd, 0));
+						pnp_device_detach(pd);
+						return(0);
+					}
+					card->para[1] = pnp_port_start(pd, 0);
+					card->para[0] = pnp_irq(pd, 0);
+					if (pdev->function == ISAPNP_FUNCTION(0xA1)) {
+						if (diva_ipac_isa_probe(cs->card, cs))
 							return 0;
-						}
-						if (pnp_activate_dev(pd) < 0) {
-							printk(KERN_ERR "Diva PnP: activate failed\n");
-							pnp_device_detach(pd);
+						return 1;
+					} else {
+						if (diva_isac_isa_probe(cs->card, cs))
 							return 0;
-						}
-						if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
-							printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
-								pnp_irq(pd, 0), pnp_port_start(pd, 0));
-							pnp_device_detach(pd);
-							return(0);
-						}
-						card->para[1] = pnp_port_start(pd, 0);
-						card->para[0] = pnp_irq(pd, 0);
-						cs->hw.diva.cfg_reg  = card->para[1];
-						cs->irq = card->para[0];
-						if (pdev->function == ISAPNP_FUNCTION(0xA1)) {
-							cs->subtyp = DIVA_IPAC_ISA;
-							cs->hw.diva.ctrl = 0;
-							cs->hw.diva.isac =
-								card->para[1] + DIVA_IPAC_DATA;
-							cs->hw.diva.hscx =
-								card->para[1] + DIVA_IPAC_DATA;
-							cs->hw.diva.isac_adr =
-								card->para[1] + DIVA_IPAC_ADR;
-							cs->hw.diva.hscx_adr =
-								card->para[1] + DIVA_IPAC_ADR;
-						} else {
-							cs->subtyp = DIVA_ISA;
-							cs->hw.diva.ctrl =
-								card->para[1] + DIVA_ISA_CTRL;
-							cs->hw.diva.isac =
-								card->para[1] + DIVA_ISA_ISAC_DATA;
-							cs->hw.diva.hscx =
-								card->para[1] + DIVA_HSCX_DATA;
-							cs->hw.diva.isac_adr =
-								card->para[1] + DIVA_ISA_ISAC_ADR;
-							cs->hw.diva.hscx_adr =
-								card->para[1] + DIVA_HSCX_ADR;
-						}
-						goto ready;
+						return 1;
 					} else {
 						printk(KERN_ERR "Diva PnP: PnP error card found, no device\n");
 						return(0);
@@ -652,111 +767,29 @@
 				printk(KERN_INFO "Diva PnP: no ISAPnP card found\n");
 			}
 		}
+	}
 #endif
 #if CONFIG_PCI
-		cs->subtyp = 0;
-		if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
-			PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) {
-			if (pci_enable_device(dev_diva))
-				return(0);
-			cs->subtyp = DIVA_PCI;
-			cs->irq = dev_diva->irq;
-			cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2);
-		} else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
-			PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) {
-			if (pci_enable_device(dev_diva_u))
-				return(0);
-			cs->subtyp = DIVA_PCI;
-			cs->irq = dev_diva_u->irq;
-			cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2);
-		} else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
-			PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) {
-			if (pci_enable_device(dev_diva201))
-				return(0);
-			cs->subtyp = DIVA_IPAC_PCI;
-			cs->irq = dev_diva201->irq;
-			cs->hw.diva.pci_cfg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 0), 4096, "diva");
-			cs->hw.diva.cfg_reg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 1), 4096, "diva");
-		} else {
-			printk(KERN_WARNING "Diva: No PCI card found\n");
-			return(0);
-		}
-
-		if (!cs->irq) {
-			printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");
-			goto err;
-		}
-
-		if (!cs->hw.diva.cfg_reg) {
-			printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
-			goto err;
-		}
-		cs->irq_flags |= SA_SHIRQ;
-#endif /* CONFIG_PCI */
-		if ((cs->subtyp == DIVA_IPAC_PCI) ||
-		    (cs->subtyp == DIVA_IPACX_PCI)   ) {
-			cs->hw.diva.ctrl = 0;
-			cs->hw.diva.isac = 0;
-			cs->hw.diva.hscx = 0;
-			cs->hw.diva.isac_adr = 0;
-			cs->hw.diva.hscx_adr = 0;
-			bytecnt = 0;
-		} else {
-			cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
-			cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
-			cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
-			cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
-			cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
-			bytecnt = 32;
-		}
-	}
-ready:
-	printk(KERN_INFO
-		"Diva: %s card configured at %#lx IRQ %d\n",
-		(cs->subtyp == DIVA_PCI) ? "PCI" :
-		(cs->subtyp == DIVA_ISA) ? "ISA" : 
-		(cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" :
-		(cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
-		cs->hw.diva.cfg_reg, cs->irq);
-	if ((cs->subtyp == DIVA_IPAC_PCI)  || 
-	    (cs->subtyp == DIVA_IPACX_PCI) || 
-	    (cs->subtyp == DIVA_PCI)         )
-		printk(KERN_INFO "Diva: %s space at %#lx\n",
-			(cs->subtyp == DIVA_PCI) ? "PCI" :
-			(cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
-			cs->hw.diva.pci_cfg);
-	if ((cs->subtyp != DIVA_IPAC_PCI) &&
-	    (cs->subtyp != DIVA_IPACX_PCI)   ) {
-		if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, bytecnt, "diva isdn"))
+	if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
+					PCI_DEVICE_ID_EICON_DIVA20,
+					dev_diva))) {
+		if (diva_pci_probe(card->cs, dev_diva))
 			return 0;
+		return 1;
+	} else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
+						 PCI_DEVICE_ID_EICON_DIVA20_U,
+						 dev_diva_u))) {
+		if (diva_pci_probe(card->cs, dev_diva_u))
+			return 0;
+		return 1;
+	} else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
+						  PCI_DEVICE_ID_EICON_DIVA201,
+						  dev_diva201))) {
+		if (diva_ipac_pci_probe(card->cs, dev_diva201))
+			return 0;
+		return 1;
 	}
-	if (cs->subtyp == DIVA_IPAC_ISA) {
-		diva_ipac_isa_reset(cs);
-		cs->card_ops = &diva_ipac_isa_ops;
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-	} else if (cs->subtyp == DIVA_IPAC_PCI) {
-		diva_ipac_pci_reset(cs);
-		cs->card_ops = &diva_ipac_pci_ops;
-		if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops))
-			goto err;
-	} else if (cs->subtyp == DIVA_IPACX_PCI) {
-		diva_ipacx_pci_reset(cs);
-		cs->card_ops = &diva_ipacx_pci_ops;
-		if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops))
-			goto err;
-	} else { /* DIVA 2.0 */
-		diva_reset(cs);
-		cs->hw.diva.tl.function = (void *) diva_led_handler;
-		cs->hw.diva.tl.data = (long) cs;
-		init_timer(&cs->hw.diva.tl);
-		cs->card_ops = &diva_ops;
-		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-			goto err;
-	}
-	return 1;
- err:
-	diva_release(cs);
+	printk(KERN_WARNING "Diva: No PCI card found\n");
+#endif /* CONFIG_PCI */
 	return 0;
-
 }
diff -Nru a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
--- a/drivers/isdn/hisax/elsa.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/elsa.c	Thu Mar  6 22:52:04 2003
@@ -690,7 +690,47 @@
 	.irq_func    = elsa_interrupt_ipac,
 };
 
-static unsigned char
+static void __init
+elsa_arcofi_init(struct IsdnCardState *cs)
+{
+#if ARCOFI_USE
+	init_arcofi(cs);
+#endif
+}
+
+static void __init
+elsa_timer_init(struct IsdnCardState *cs)
+{
+	cs->hw.elsa.tl.function = (void *) elsa_led_handler;
+	cs->hw.elsa.tl.data = (long) cs;
+	init_timer(&cs->hw.elsa.tl);
+}
+
+static int __init
+elsa_timer_test(struct IsdnCardState *cs)
+{
+	/* test timer */
+	byteout(cs->hw.elsa.trig, 0xff);
+	byteout(cs->hw.elsa.timer, 0);
+	if (!TimerRun(cs)) {
+		byteout(cs->hw.elsa.timer, 0);	/* second attempt */
+		if (!TimerRun(cs)) {
+			printk(KERN_WARNING "Elsa: timer does not start\n");
+			goto err;
+		}
+	}
+	HZDELAY(10 * HZ / 1000); /* wait >=10 ms */
+	if (TimerRun(cs)) {
+		printk(KERN_WARNING "Elsa: timer does not run\n");
+		goto err;
+	}
+	printk(KERN_INFO "Elsa: timer OK; resetting card\n");
+	return 0;
+ err:
+	return -EBUSY;
+}
+
+static unsigned char __init
 probe_elsa_adr(unsigned int adr, int typ)
 {
 	int i, in1, in2, p16_1 = 0, p16_2 = 0, p8_1 = 0, p8_2 = 0, pc_1 = 0,
@@ -699,15 +739,13 @@
 	/* In case of the elsa pcmcia card, this region is in use,
 	   reserved for us by the card manager. So we do not check it
 	   here, it would fail. */
-	if (typ != ISDN_CTYPE_ELSA_PCMCIA && check_region(adr, 8)) {
-		printk(KERN_WARNING
-		       "Elsa: Probing Port 0x%x: already in use\n",
-		       adr);
-		return (0);
+	if (typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(adr, 8, "elsa")) {
+		printk(KERN_WARNING "Elsa: probing port 0x%x: in use\n",  adr);
+		return 0;
 	}
 	for (i = 0; i < 16; i++) {
-		in1 = inb(adr + ELSA_CONFIG);	/* 'toggelt' bei */
-		in2 = inb(adr + ELSA_CONFIG);	/* jedem Zugriff */
+		in1 = inb(adr + ELSA_CONFIG);	/* 'toggels' at */
+		in2 = inb(adr + ELSA_CONFIG);	/* each access  */
 		p16_1 += 0x04 & in1;
 		p16_2 += 0x04 & in2;
 		p8_1 += 0x02 & in1;
@@ -717,6 +755,7 @@
 		pfp_1 += 0x40 & in1;
 		pfp_2 += 0x40 & in2;
 	}
+	release_region(adr, 8);
 	printk(KERN_INFO "Elsa: Probing IO 0x%x", adr);
 	if (65 == ++p16_1 * ++p16_2) {
 		printk(" PCC-16/PCF found\n");
@@ -736,18 +775,227 @@
 	}
 }
 
-static unsigned int
-probe_elsa(struct IsdnCardState *cs)
+static int __init
+elsa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	int i;
-	unsigned int CARD_portlist[] =
-	{0x160, 0x170, 0x260, 0x360, 0};
-
-	for (i = 0; CARD_portlist[i]; i++) {
-		if ((cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ)))
+	u8 val;
+	int i, bytecnt = 8;
+	unsigned int CARD_portlist[] = {0x160, 0x170, 0x260, 0x360, 0};
+
+	cs->hw.elsa.base = card->para[0];
+	printk(KERN_INFO "Elsa: Microlink IO probing\n");
+	if (cs->hw.elsa.base) {
+		cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, cs->typ);
+		if (!cs->subtyp) {
+			printk(KERN_WARNING "Elsa: no Microlink at %#lx\n",
+			       cs->hw.elsa.base);
+			goto err;
+		}
+	} else {
+		for (i = 0; CARD_portlist[i]; i++) {
+			cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ);
+			if (cs->subtyp)
+				cs->hw.elsa.base = CARD_portlist[i];
 			break;
+		}
+	}
+	if (!cs->hw.elsa.base)
+		goto err;
+		
+	cs->hw.elsa.cfg   = cs->hw.elsa.base + ELSA_CONFIG;
+	cs->hw.elsa.ctrl  = cs->hw.elsa.base + ELSA_CONTROL;
+	cs->hw.elsa.ale   = cs->hw.elsa.base + ELSA_ALE;
+	cs->hw.elsa.isac  = cs->hw.elsa.base + ELSA_ISAC;
+	cs->hw.elsa.itac  = cs->hw.elsa.base + ELSA_ITAC;
+	cs->hw.elsa.hscx  = cs->hw.elsa.base + ELSA_HSCX;
+	cs->hw.elsa.trig  = cs->hw.elsa.base + ELSA_TRIG_IRQ;
+	cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
+	val = bytein(cs->hw.elsa.cfg);
+	if (cs->subtyp == ELSA_PC) {
+		const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0};
+		cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2];
+	} else if (cs->subtyp == ELSA_PCC8) {
+		const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0};
+		cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4];
+	} else {
+		const u8 CARD_IrqTab[8] = {15, 10, 15, 3, 11, 5, 11, 9};
+		cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3];
 	}
-	return (CARD_portlist[i]);
+	val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE;
+	if (val < 3)
+		val |= 8;
+	val += 'A' - 3;
+	if (val == 'B' || val == 'C')
+		val ^= 1;
+	if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G'))
+		val = 'C';
+	printk(KERN_INFO "Elsa: %s found at %#lx Rev.:%c IRQ %d\n",
+	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, val, cs->irq);
+	val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD;
+	if (val) {
+		printk(KERN_WARNING "Elsa: Microlink S0 bus power bad\n");
+		cs->hw.elsa.status |= ELSA_BAD_PWR;
+	}
+	switch (cs->subtyp) {
+	case ELSA_PCFPRO: bytecnt = 16;	break;
+	}
+	if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
+		goto err;
+	elsa_arcofi_init(cs);
+	elsa_timer_init(cs);
+	if (elsa_timer_test(cs))
+		goto err;
+	elsa_reset(cs);
+	cs->card_ops = &elsa_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	if (cs->subtyp == ELSA_PC) {
+		val = readitac(cs, ITAC_SYS);
+		printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]);
+		writeitac(cs, ITAC_ISEN, 0);
+		writeitac(cs, ITAC_RFIE, 0);
+		writeitac(cs, ITAC_XFIE, 0);
+		writeitac(cs, ITAC_SCIE, 0);
+		writeitac(cs, ITAC_STIE, 0);
+	}
+	return 0;
+ err:
+	elsa_release(cs);
+	return -EBUSY;
+}
+
+static int __init
+elsa_qs_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	int bytecnt = 8;
+
+	cs->irq           = card->para[0];
+	cs->hw.elsa.base  = card->para[1];
+	cs->hw.elsa.cfg   = cs->hw.elsa.base + ELSA_CONFIG;
+	cs->hw.elsa.ale   = cs->hw.elsa.base + ELSA_ALE;
+	cs->hw.elsa.isac  = cs->hw.elsa.base + ELSA_ISAC;
+	cs->hw.elsa.hscx  = cs->hw.elsa.base + ELSA_HSCX;
+	cs->hw.elsa.trig  = cs->hw.elsa.base + ELSA_TRIG_IRQ;
+	cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
+	cs->hw.elsa.ctrl  = cs->hw.elsa.base + ELSA_CONTROL;
+	printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n",
+	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq);
+	switch (cs->subtyp) {
+	case ELSA_QS3000: bytecnt = 16;	break;
+	}
+	if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
+		goto err;
+	elsa_arcofi_init(cs);
+	elsa_timer_init(cs);
+	if (elsa_timer_test(cs))
+		goto err;
+	elsa_reset(cs);
+	cs->card_ops = &elsa_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 0;
+ err:
+	elsa_release(cs);
+	return -EBUSY;
+}
+
+static int __init
+elsa_qs1000_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = ELSA_QS1000;
+	return elsa_qs_probe(cs, card);
+}
+
+static int __init
+elsa_qs3000_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = ELSA_QS3000;
+	return elsa_qs_probe(cs, card);
+}
+
+static int __init
+elsa_pcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	u8 val;
+
+	cs->irq = card->para[0];
+	cs->hw.elsa.base = card->para[1];
+	cs->hw.elsa.ale = cs->hw.elsa.base + 0;
+	val = readreg(cs, cs->hw.elsa.base + 2, IPAC_ID);
+	if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */
+		cs->subtyp = ELSA_PCMCIA_IPAC;
+		cs->hw.elsa.isac = cs->hw.elsa.base + 2;
+	} else {
+		cs->subtyp = ELSA_PCMCIA;
+		cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
+		cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM;
+		cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
+	}
+	cs->hw.elsa.timer = 0;
+	cs->hw.elsa.trig = 0;
+	cs->hw.elsa.ctrl = 0;
+	printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n",
+	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq);
+	elsa_arcofi_init(cs);
+	elsa_reset(cs);
+	if (cs->subtyp == ELSA_PCMCIA_IPAC) {
+		cs->card_ops = &elsa_ipac_ops;
+		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+			goto err;
+	} else {
+		cs->card_ops = &elsa_ops;
+		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+			goto err;
+	}
+	return 0;
+ err:
+	elsa_release(cs);
+	return -EBUSY;
+}
+
+static int __init
+elsa_qs_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev,
+		  int subtyp)
+{
+	int bytecnt = 2;
+	u8 pci_rev;
+
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = subtyp;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.elsa.cfg = pci_resource_start(pdev, 1);
+	cs->hw.elsa.base = pci_resource_start(pdev, 3);
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
+	if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) {
+		printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n");
+		__set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
+	}
+	cs->hw.elsa.ale  = cs->hw.elsa.base;
+	cs->hw.elsa.isac = cs->hw.elsa.base +1;
+	cs->hw.elsa.hscx = cs->hw.elsa.base +1; 
+	printk(KERN_INFO "Elsa: %s defined at %#lx/%#x IRQ %d\n",
+	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->hw.elsa.cfg,
+	       cs->irq);
+	switch (cs->subtyp) {
+	case ELSA_QS3000PCI: bytecnt = 16; break;
+	}
+	if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci"))
+		goto err;
+	elsa_arcofi_init(cs);
+	elsa_timer_init(cs);
+	elsa_reset(cs);
+	cs->card_ops = &elsa_ipac_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		goto err;
+	return 0;
+ err:
+	elsa_release(cs);
+	return -EBUSY;
 }
 
 static 	struct pci_dev *dev_qs1000 __devinitdata = NULL;
@@ -771,83 +1019,21 @@
 int __devinit
 setup_elsa(struct IsdnCard *card)
 {
-	int bytecnt;
-	u8 val, pci_rev;
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, Elsa_revision);
 	printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp));
-	cs->hw.elsa.ctrl_reg = 0;
-	cs->hw.elsa.status = 0;
-	cs->hw.elsa.MFlag = 0;
-	cs->subtyp = 0;
-	if (cs->typ == ISDN_CTYPE_ELSA) {
-		cs->hw.elsa.base = card->para[0];
-		printk(KERN_INFO "Elsa: Microlink IO probing\n");
-		if (cs->hw.elsa.base) {
-			if (!(cs->subtyp = probe_elsa_adr(cs->hw.elsa.base,
-							  cs->typ))) {
-				printk(KERN_WARNING
-				       "Elsa: no Elsa Microlink at %#lx\n",
-				       cs->hw.elsa.base);
-				return (0);
-			}
-		} else
-			cs->hw.elsa.base = probe_elsa(cs);
-		if (cs->hw.elsa.base) {
-			cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
-			cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
-			cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
-			cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
-			cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC;
-			cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
-			cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
-			cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
-			val = bytein(cs->hw.elsa.cfg);
-			if (cs->subtyp == ELSA_PC) {
-				const u8 CARD_IrqTab[8] =
-				{7, 3, 5, 9, 0, 0, 0, 0};
-				cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2];
-			} else if (cs->subtyp == ELSA_PCC8) {
-				const u8 CARD_IrqTab[8] =
-				{7, 3, 5, 9, 0, 0, 0, 0};
-				cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4];
-			} else {
-				const u8 CARD_IrqTab[8] =
-				{15, 10, 15, 3, 11, 5, 11, 9};
-				cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3];
-			}
-			val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE;
-			if (val < 3)
-				val |= 8;
-			val += 'A' - 3;
-			if (val == 'B' || val == 'C')
-				val ^= 1;
-			if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G'))
-				val = 'C';
-			printk(KERN_INFO
-			       "Elsa: %s found at %#lx Rev.:%c IRQ %d\n",
-			       Elsa_Types[cs->subtyp],
-			       cs->hw.elsa.base,
-			       val, cs->irq);
-			val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD;
-			if (val) {
-				printk(KERN_WARNING
-				   "Elsa: Microlink S0 bus power bad\n");
-				cs->hw.elsa.status |= ELSA_BAD_PWR;
-			}
-		} else {
-			printk(KERN_WARNING
-			       "No Elsa Microlink found\n");
-			return (0);
-		}
-	} else if (cs->typ == ISDN_CTYPE_ELSA_PNP) {
+
+	if (card->typ == ISDN_CTYPE_ELSA) {
+		if (elsa_probe(card->cs, card))
+			return 0;
+		return 1;
+	} else if (card->typ == ISDN_CTYPE_ELSA_PNP) {
 #ifdef __ISAPNP__
 		if (!card->para[1] && isapnp_present()) {
 			struct pnp_card *pb;
 			struct pnp_dev *pd;
-
+			
 			while(pdev->card_vendor) {
 				if ((pb = pnp_find_card(pdev->card_vendor,
 							pdev->card_device,
@@ -878,10 +1064,15 @@
 						}
 						card->para[1] = pnp_port_start(pd, 0);
 						card->para[0] = pnp_irq(pd, 0);
-						if (pdev->function == ISAPNP_FUNCTION(0x133))
-							cs->subtyp = ELSA_QS1000;
-						else
-							cs->subtyp = ELSA_QS3000;
+						if (pdev->function == ISAPNP_FUNCTION(0x133)) {
+							if (elsa_qs1000_probe(card->cs, card))
+								return 0;
+							return 1;
+						} else {
+							if (elsa_qs3000_probe(card->cs, card))
+								return 0;
+							return 1;
+						}
 						break;
 					} else {
 						printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n");
@@ -897,184 +1088,33 @@
 			}
 		}
 #endif
-		if (card->para[1] && card->para[0]) { 
-			cs->hw.elsa.base = card->para[1];
-			cs->irq = card->para[0];
-			if (!cs->subtyp)
-				cs->subtyp = ELSA_QS1000;
-		} else {
-			printk(KERN_ERR "Elsa PnP: no parameter\n");
-		}
-		cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
-		cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
-		cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
-		cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
-		cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
-		cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
-		cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
-		printk(KERN_INFO
-		       "Elsa: %s defined at %#lx IRQ %d\n",
-		       Elsa_Types[cs->subtyp],
-		       cs->hw.elsa.base,
-		       cs->irq);
-	} else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA) {
-		cs->hw.elsa.base = card->para[1];
-		cs->irq = card->para[0];
-		cs->hw.elsa.ale = cs->hw.elsa.base + 0;
-		val = readreg(cs, cs->hw.elsa.base + 2, IPAC_ID);
-		if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */
-			cs->subtyp = ELSA_PCMCIA_IPAC;
-			cs->hw.elsa.isac = cs->hw.elsa.base + 2;
-			cs->hw.elsa.hscx = cs->hw.elsa.base + 2;
-		} else {
-			cs->subtyp = ELSA_PCMCIA;
-			cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
-			cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM;
-			cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
-		}
-		cs->hw.elsa.timer = 0;
-		cs->hw.elsa.trig = 0;
-		cs->hw.elsa.ctrl = 0;
-		printk(KERN_INFO
-		       "Elsa: %s defined at %#lx IRQ %d\n",
-		       Elsa_Types[cs->subtyp],
-		       cs->hw.elsa.base,
-		       cs->irq);
-	} else if (cs->typ == ISDN_CTYPE_ELSA_PCI) {
+		if (elsa_qs1000_probe(card->cs, card))
+			return 0;
+		return 1;
+
+	} else if (card->typ == ISDN_CTYPE_ELSA_PCMCIA) {
+		if (elsa_pcmcia_probe(card->cs, card))
+			return 0;
+		return 1;
+	} else if (card->typ == ISDN_CTYPE_ELSA_PCI) {
 #if CONFIG_PCI
-		cs->subtyp = 0;
 		if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA,
 			PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) {
-			if (pci_enable_device(dev_qs1000))
-				return(0);
-			cs->subtyp = ELSA_QS1000PCI;
-			cs->irq = dev_qs1000->irq;
-			cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1);
-			cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3);
-			pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev);
+			if (elsa_qs_pci_probe(card->cs, dev_qs1000,
+					      ELSA_QS1000PCI))
+				return 0;
+			return 1;
 		} else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA,
 			PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) {
-			if (pci_enable_device(dev_qs3000))
-				return(0);
-			cs->subtyp = ELSA_QS3000PCI;
-			cs->irq = dev_qs3000->irq;
-			cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1);
-			cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3);
-			pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev);
+			if (elsa_qs_pci_probe(card->cs, dev_qs3000,
+					      ELSA_QS3000PCI))
+				return 0;
+			return 1;
 		} else {
 			printk(KERN_WARNING "Elsa: No PCI card found\n");
-			return(0);
+			return 0;
 		}
-		if (!cs->irq) {
-			printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n");
-			return(0);
-		}
-
-		if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) {
-			printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n");
-			return(0);
-		}
-		if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) {
-			printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n");
-			set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
-		}
-		cs->hw.elsa.ale  = cs->hw.elsa.base;
-		cs->hw.elsa.isac = cs->hw.elsa.base +1;
-		cs->hw.elsa.hscx = cs->hw.elsa.base +1; 
-		cs->hw.elsa.timer = 0;
-		cs->hw.elsa.trig  = 0;
-		cs->irq_flags |= SA_SHIRQ;
-		printk(KERN_INFO
-		       "Elsa: %s defined at %#lx/0x%x IRQ %d\n",
-		       Elsa_Types[cs->subtyp],
-		       cs->hw.elsa.base,
-		       cs->hw.elsa.cfg,
-		       cs->irq);
 #endif /* CONFIG_PCI */
-	} else 
-		return (0);
-
-	switch (cs->subtyp) {
-		case ELSA_PC:
-		case ELSA_PCC8:
-		case ELSA_PCC16:
-		case ELSA_QS1000:
-		case ELSA_PCMCIA:
-		case ELSA_PCMCIA_IPAC:
-			bytecnt = 8;
-			break;
-		case ELSA_PCFPRO:
-		case ELSA_PCF:
-		case ELSA_QS3000:
-		case ELSA_QS3000PCI:
-			bytecnt = 16;
-			break;
-		case ELSA_QS1000PCI:
-			bytecnt = 2;
-			break;
-		default:
-			printk(KERN_WARNING
-			       "Unknown ELSA subtype %d\n", cs->subtyp);
-			return (0);
-	}
-	/* In case of the elsa pcmcia card, this region is in use,
-	   reserved for us by the card manager. So we do not check it
-	   here, it would fail. */
-	if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA)
-		if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
-			goto err;
-	
-	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI))
-		if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci"))
-			goto err;
-
-#if ARCOFI_USE
-	init_arcofi(cs);
-#endif
-
-	cs->hw.elsa.tl.function = (void *) elsa_led_handler;
-	cs->hw.elsa.tl.data = (long) cs;
-	init_timer(&cs->hw.elsa.tl);
-	/* Teste Timer */
-	if (cs->hw.elsa.timer) {
-		byteout(cs->hw.elsa.trig, 0xff);
-		byteout(cs->hw.elsa.timer, 0);
-		if (!TimerRun(cs)) {
-			byteout(cs->hw.elsa.timer, 0);	/* 2. Versuch */
-			if (!TimerRun(cs)) {
-				printk(KERN_WARNING
-				       "Elsa: timer do not start\n");
-				goto err;
-			}
-		}
-		HZDELAY(1);	/* wait >=10 ms */
-		if (TimerRun(cs)) {
-			printk(KERN_WARNING "Elsa: timer do not run down\n");
-			goto err;
-		}
-		printk(KERN_INFO "Elsa: timer OK; resetting card\n");
-	}
-	elsa_reset(cs);
-	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) {
-		cs->card_ops = &elsa_ipac_ops;
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-	} else {
-		cs->card_ops = &elsa_ops;
-		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-			goto err;
 	}
-	if (cs->subtyp == ELSA_PC) {
-		val = readitac(cs, ITAC_SYS);
-		printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]);
-		writeitac(cs, ITAC_ISEN, 0);
-		writeitac(cs, ITAC_RFIE, 0);
-		writeitac(cs, ITAC_XFIE, 0);
-		writeitac(cs, ITAC_SCIE, 0);
-		writeitac(cs, ITAC_STIE, 0);
-	}
-	return 1;
- err:
-	elsa_release(cs);
 	return 0;
 }
diff -Nru a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
--- a/drivers/isdn/hisax/enternow_pci.c	Mon Feb 24 10:29:08 2003
+++ b/drivers/isdn/hisax/enternow_pci.c	Thu Mar  6 22:52:04 2003
@@ -263,13 +263,65 @@
 	.irq_func    = enpci_interrupt,
 };
 
+static int __init
+enpci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.njet.base = pci_resource_start(pdev, 0);
+	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN"))
+		goto err;
+
+	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+	cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
+
+	/* Reset an */
+	cs->hw.njet.ctrl_reg = 0x07;  // geändert von 0xff
+	OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	/* 50 ms Pause */
+	schedule_timeout((50*HZ)/1000);
+	
+	cs->hw.njet.ctrl_reg = 0x30;  /* Reset Off and status read clear */
+	OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	
+	cs->hw.njet.auxd = 0x00; // war 0xc0
+	cs->hw.njet.dmactrl = 0;
+	
+	OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
+	OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
+	OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd);
+	
+	printk(KERN_INFO
+	       "enter:now PCI: PCI card configured at 0x%lx IRQ %d\n",
+	       cs->hw.njet.base, cs->irq);
+	reset_enpci(cs);
+	cs->hw.njet.last_is0 = 0;
+	cs->hw.njet.bc_activate = enpci_bc_activate;
+	cs->hw.njet.bc_deactivate = enpci_bc_deactivate;
+	amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask);
+
+	cs->card_ops = &enpci_ops;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *dev_netjet __initdata = NULL;
 
 /* called by config.c */
 int __init
 setup_enternow_pci(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 #ifdef __BIG_ENDIAN
@@ -278,72 +330,22 @@
         strcpy(tmp, enternow_pci_rev);
 	printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp));
 
-	for ( ;; ) {
-		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
-			if (pci_enable_device(dev_netjet))
-				return(0);
-			cs->irq = dev_netjet->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "enter:now PCI: No IRQ for PCI card found\n");
-				return(0);
-			}
-			cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
-			if (!cs->hw.njet.base) {
-				printk(KERN_WARNING "enter:now PCI: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-                        /* checks Sub-Vendor ID because system crashes with Traverse-Card */
-			if ((dev_netjet->subsystem_vendor != 0x55) ||
-				(dev_netjet->subsystem_device != 0x02)) {
-				printk(KERN_WARNING "enter:now: You tried to load this driver with an incompatible TigerJet-card\n");
-                                printk(KERN_WARNING "Use type=20 for Traverse NetJet PCI Card.\n");
-                                return(0);
-                        }
-		} else {
-                        printk(KERN_WARNING "enter:now PCI: No PCI card found\n");
-			return(0);
+	dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+				     PCI_DEVICE_ID_TIGERJET_300, dev_netjet);
+	if (dev_netjet) {
+		if (dev_netjet->subsystem_vendor != 0x55 ||
+		    dev_netjet->subsystem_device != 0x02) {
+			printk(KERN_WARNING "enter:now: You tried to load "
+			       "this driver with an incompatible "
+			       "TigerJet-card\n");
+			printk(KERN_WARNING "Use type=20 for Traverse "
+			       "NetJet PCI Card.\n");
+			return 0;
 		}
-
-		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-		cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
-
-		/* Reset an */
-		cs->hw.njet.ctrl_reg = 0x07;  // geändert von 0xff
-		OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		/* 50 ms Pause */
-		schedule_timeout((50*HZ)/1000);
-
-		cs->hw.njet.ctrl_reg = 0x30;  /* Reset Off and status read clear */
-		OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		cs->hw.njet.auxd = 0x00; // war 0xc0
-		cs->hw.njet.dmactrl = 0;
-
-		OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
-		OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
-		OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd);
-
-			   break;
-	}
-	printk(KERN_INFO
-		"enter:now PCI: PCI card configured at 0x%lx IRQ %d\n",
-		cs->hw.njet.base, cs->irq);
-	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN"))
+		if (enpci_probe(card->cs, dev_netjet))
+			return 1;
 		return 0;
-	reset_enpci(cs);
-	cs->hw.njet.last_is0 = 0;
-	cs->hw.njet.bc_activate = enpci_bc_activate;
-	cs->hw.njet.bc_deactivate = enpci_bc_deactivate;
-	amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask);
-
-	cs->irq_flags |= SA_SHIRQ;
-	cs->card_ops = &enpci_ops;
-
-        return 1;
+	}
+	printk(KERN_WARNING "enter:now PCI: No PCI card found\n");
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
--- a/drivers/isdn/hisax/gazel.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/gazel.c	Thu Mar  6 22:52:04 2003
@@ -294,60 +294,6 @@
 	inithscxisac(cs);
 }
 
-static int
-r647_reserve_regions(struct IsdnCardState *cs)
-{
-	int i, base = cs->hw.gazel.hscx[0];
-
-	for (i = 0; i < 0xc000; i += 0x1000) {
-		if (!request_io(&cs->rs, i + base, 16, "gazel"))
-			goto err;
-	}
-	if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel"))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int
-r685_reserve_regions(struct IsdnCardState *cs)
-{
-	if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel"))
-		goto err;
-	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int
-r742_reserve_regions(struct IsdnCardState *cs)
-{
-	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int
-r753_reserve_regions(struct IsdnCardState *cs)
-{
-	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
-		goto err;
-	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
 static struct card_ops r647_ops = {
 	.init     = gazel_init,
 	.reset    = r647_reset,
@@ -377,194 +323,213 @@
 };
 
 static int __init
-setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
+gazel647_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n");
-	// we got an irq parameter, assume it is an ISA card
-	// R742 decodes address even in not started...
-	// R647 returns FF if not present or not started
-	// eventually needs improvment
-	cs->hw.gazel.ipac = card->para[1];
-	if (ipac_read(cs, IPAC_ID) == 1)
-		cs->subtyp = R742;
-	else
-		cs->subtyp = R647;
+	int i, base;
 
+	cs->subtyp = R647;
+	cs->irq = card->para[0];
 	cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
+
+	printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
+	cs->dc.isac.adf2 = 0x87;
+	printk(KERN_INFO "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
+	       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
+	printk(KERN_INFO
+	       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
+	       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
+
 	cs->hw.gazel.isac = card->para[1] + 0x8000;
 	cs->hw.gazel.hscx[0] = card->para[1];
 	cs->hw.gazel.hscx[1] = card->para[1] + 0x4000;
-	cs->irq = card->para[0];
 	cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
 	cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
 	cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
 
-	switch (cs->subtyp) {
-	case R647:
-		printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
-		cs->dc.isac.adf2 = 0x87;
-		printk(KERN_INFO
-		       "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
-		       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
-		printk(KERN_INFO
-		       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
-		       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
-		
-		return r647_reserve_regions(cs);
-	case R742:
-		printk(KERN_INFO "Gazel: Card ISA R742 found\n");
-		printk(KERN_INFO
-		       "Gazel: config irq:%d ipac:0x%X\n",
-		       cs->irq, cs->hw.gazel.ipac);
-		return r742_reserve_regions(cs);
+	base = cs->hw.gazel.hscx[0];
+	for (i = 0; i < 0xc000; i += 0x1000) {
+		if (!request_io(&cs->rs, base + i, 16, "gazel"))
+			goto err;
 	}
+	if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel"))
+		goto err;
+
+	cs->card_ops = &r647_ops;
+	if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops))
+		goto err;
+
+	cs->card_ops->reset(cs);
 	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
 }
 
-static struct pci_dev *dev_tel __initdata = NULL;
-
 static int __init
-setup_gazelpci(struct IsdnCardState *cs)
+gazel742_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0;
-	u8 pci_irq = 0, found;
-	u_int nbseek, seekcard;
-	u8 pci_rev;
+	cs->subtyp = R742;
+	cs->irq = card->para[0];
+	cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
 
-	printk(KERN_WARNING "Gazel: PCI card automatic recognition\n");
+	printk(KERN_INFO "Gazel: Card ISA R742 found\n");
+	printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X\n",
+	       cs->irq, cs->hw.gazel.ipac);
 
-	found = 0;
-	if (!pci_present()) {
-		printk(KERN_WARNING "Gazel: No PCI bus present\n");
-		return 1;
-	}
-	seekcard = PCI_DEVICE_ID_PLX_R685;
-	for (nbseek = 0; nbseek < 3; nbseek++) {
-		if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, seekcard, dev_tel))) {
-			if (pci_enable_device(dev_tel))
-				return 1;
-			pci_irq = dev_tel->irq;
-			pci_ioaddr0 = pci_resource_start(dev_tel, 1);
-			pci_ioaddr1 = pci_resource_start(dev_tel, 2);
-			found = 1;
-		}
-		if (found)
-			break;
-		else {
-			switch (seekcard) {
-			case PCI_DEVICE_ID_PLX_R685:
-				seekcard = PCI_DEVICE_ID_PLX_R753;
-				break;
-			case PCI_DEVICE_ID_PLX_R753:
-				seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO;
-				break;
-			}
-		}
-	}
-	if (!found) {
-		printk(KERN_WARNING "Gazel: No PCI card found\n");
-		return -ENODEV;
-	}
-	if (!pci_irq) {
-		printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n");
-		return -ENODEV;
-	}
-	cs->hw.gazel.pciaddr[0] = pci_ioaddr0;
-	cs->hw.gazel.pciaddr[1] = pci_ioaddr1;
+	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
+		goto err;
 
-	pci_ioaddr1 &= 0xfffe;
-	cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe;
-	cs->hw.gazel.ipac = pci_ioaddr1;
-	cs->hw.gazel.isac = pci_ioaddr1 + 0x80;
-	cs->hw.gazel.hscx[0] = pci_ioaddr1;
-	cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40;
-	cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
+	cs->card_ops = &r742_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		goto err;
+
+	cs->card_ops->reset(cs);
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+gazel685_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->subtyp               = R685;
+	cs->irq                  = pdev->irq;
+	cs->irq_flags           |= SA_SHIRQ;
+	cs->hw.gazel.cfg_reg     = pci_resource_start(pdev, 1);
+	cs->hw.gazel.isac        = pci_resource_start(pdev, 2) + 0x80;
+	cs->hw.gazel.hscx[0]     = pci_resource_start(pdev, 2);
+	cs->hw.gazel.hscx[1]     = pci_resource_start(pdev, 2) + 0x40;
+	cs->hw.gazel.isacfifo    = cs->hw.gazel.isac;
 	cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
 	cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
-	cs->irq = pci_irq;
-	cs->irq_flags |= SA_SHIRQ;
+	cs->dc.isac.adf2 = 0x87;
 
-	switch (seekcard) {
-	case PCI_DEVICE_ID_PLX_R685:
-		printk(KERN_INFO "Gazel: Card PCI R685 found\n");
-		cs->subtyp = R685;
-		cs->dc.isac.adf2 = 0x87;
-		printk(KERN_INFO
-		       "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
-		       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
-		printk(KERN_INFO
-		       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
-		       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
-		return r685_reserve_regions(cs);
-	case PCI_DEVICE_ID_PLX_R753:
-	case PCI_DEVICE_ID_PLX_DJINN_ITOO:
-		printk(KERN_INFO "Gazel: Card PCI R753 found\n");
-		cs->subtyp = R753;
-		printk(KERN_INFO
-		       "Gazel: config irq:%d ipac:0x%X  cfg:0x%X\n",
-		       cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
-		/* 
-		 * Erratum for PLX9050, revision 1:
-		 * If bit 7 of BAR 0/1 is set, local config registers
-		 * can not be read (write is okay)
-		 */
-		if (cs->hw.gazel.cfg_reg & 0x80) {
-			pci_read_config_byte(dev_tel, PCI_REVISION_ID, &pci_rev);
-			if (pci_rev == 1) {
-				printk(KERN_INFO "Gazel: PLX9050 rev1 workaround activated\n");
-				set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
-			}
+	if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
+		goto err;
+
+	printk(KERN_INFO "Gazel: Card PCI R685 found\n");
+	printk(KERN_INFO "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
+	       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
+	printk(KERN_INFO "Gazel: hscx A:0x%X  hscx B:0x%X\n",
+	       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
+
+	cs->card_ops  = &r685_ops;
+	if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops))
+		goto err;
+
+	cs->card_ops->reset(cs);
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+gazel753_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	u8 pci_rev;
+
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->subtyp           = R753;
+	cs->irq              = pdev->irq;
+	cs->irq_flags       |= SA_SHIRQ;
+	cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1);
+	cs->hw.gazel.ipac    = pci_resource_start(pdev, 2);
+
+	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
+		goto err;
+
+	printk(KERN_INFO "Gazel: Card PCI R753 found\n");
+	printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X  cfg:0x%X\n",
+	       cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
+	/* 
+	 * Erratum for PLX9050, revision 1:
+	 * If bit 7 of BAR 0/1 is set, local config registers
+	 * can not be read (write is okay)
+	 */
+	if (cs->hw.gazel.cfg_reg & 0x80) {
+		pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
+		if (pci_rev == 1) {
+			printk(KERN_INFO "Gazel: PLX9050 rev1 workaround "
+			       "activated\n");
+			__set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
 		}
-		return r753_reserve_regions(cs);
 	}
+	cs->card_ops = &r753_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		goto err;
+
+	cs->card_ops->reset(cs);
 	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
 }
 
+static struct pci_dev *dev_tel __initdata = NULL;
+static u16 __initdata dev_id = PCI_DEVICE_ID_PLX_R685;
+
 int __init
 setup_gazel(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, gazel_revision);
 	printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp));
 
 	if (card->para[0]) {
-		if (setup_gazelisa(card, cs))
-			return (0);
-	} else {
-		if (setup_gazelpci(cs))
-			return (0);
+		printk(KERN_INFO "Gazel: ISA card automatic recognition\n");
+		// we got an irq parameter, assume it is an ISA card
+		// R742 decodes address even in not started...
+		// R647 returns FF if not present or not started
+		// eventually needs improvment
+		card->cs->hw.gazel.ipac = card->para[1];
+		if (ipac_read(card->cs, IPAC_ID) == 1) {
+			if (gazel742_probe(card->cs, card))
+				return 0;
+		} else {
+			if (gazel647_probe(card->cs, card))
+				return 0;
+		}
+		return 1;
 	}
 
-	switch (cs->subtyp) {
-	case R647:
-	case R685:
-		if (cs->subtyp == R647) {
-			cs->card_ops  = &r647_ops;
-			if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops))
-				goto err;
-		} else {
-			cs->card_ops  = &r685_ops;
-			if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops))
-				goto err;
+	for (;;) {
+		dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, dev_id, dev_tel);
+		if (dev_tel) {
+			switch (dev_id) {
+			case PCI_DEVICE_ID_PLX_R685:
+				if (gazel685_probe(card->cs, dev_tel))
+					return 0;
+				return 1;
+			case PCI_DEVICE_ID_PLX_R753:
+			case PCI_DEVICE_ID_PLX_DJINN_ITOO:
+				if (gazel753_probe(card->cs, dev_tel))
+					return 0;
+				return 1;
+			}
 		}
-		cs->card_ops->reset(cs);
-		break;
-	case R742:
-	case R753:
-		if (cs->subtyp == R742) {
-			cs->card_ops = &r742_ops;
-		} else {
-			cs->card_ops = &r753_ops;
+		switch (dev_id) {
+		case PCI_DEVICE_ID_PLX_R685:
+			dev_id = PCI_DEVICE_ID_PLX_R753;
+		case PCI_DEVICE_ID_PLX_R753:
+			dev_id = PCI_DEVICE_ID_PLX_DJINN_ITOO;
+		default:
+			break;
 		}
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-		cs->card_ops->reset(cs);
-		break;
 	}
-	return 1;
- err:
-	hisax_release_resources(cs);
+	printk(KERN_WARNING "Gazel: No PCI card found\n");
 	return 0;
 }
+
+
diff -Nru a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
--- a/drivers/isdn/hisax/hfc_pci.c	Sun Jan 12 16:05:35 2003
+++ b/drivers/isdn/hisax/hfc_pci.c	Thu Mar  6 22:52:04 2003
@@ -1382,72 +1382,41 @@
 };
 
 
-/* this variable is used as card index when more than one cards are present */
-static struct pci_dev *dev_hfcpci __initdata = NULL;
-
-int __init
-setup_hfcpci(struct IsdnCard *card)
+static int __init
+niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev, int i)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-	int i;
-	struct pci_dev *tmp_hfcpci = NULL;
+	int rc;
 
-	strcpy(tmp, hfcpci_revision);
-	printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
-	cs->hw.hfcpci.int_s1 = 0;
-	cs->dc.hfcpci.ph_state = 0;
-	cs->hw.hfcpci.fifo = 255;
+	rc = -EBUSY;
+	if (pci_enable_device(pdev))
+		goto err;
 
-	i = 0;
-	while (id_list[i].vendor_id) {
-		tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
-					     id_list[i].device_id,
-					     dev_hfcpci);
-		i++;
-		if (tmp_hfcpci) {
-			if (pci_enable_device(tmp_hfcpci))
-				continue;
-			pci_set_master(tmp_hfcpci);
-			if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
-				continue;
-			else
-				break;
-		}
-	}
+	pci_set_master(pdev);
+
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.hfcpci.pdev = pdev;
+
+	cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, 
+					    pci_resource_start(pdev, 1), 128,
+					    "hfc_pci");
+	if (!cs->hw.hfcpci.pci_io)
+		goto err;
 	
-	if (tmp_hfcpci) {
-		i--;
-		dev_hfcpci = tmp_hfcpci;	/* old device */
-		cs->irq = dev_hfcpci->irq;
-		cs->hw.hfcpci.pdev = tmp_hfcpci;
-		if (!cs->irq) {
-			printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
-			return (0);
-		}
-		printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
-	} else {
-		printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
-		return (0);
-	}
 	/* Allocate memory for FIFOS */
-	cs->hw.hfcpci.fifos = pci_alloc_consistent(tmp_hfcpci, 32768, &cs->hw.hfcpci.fifos_dma);
-	if (!cs->hw.hfcpci.fifos) {
-		printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
-		return 0;
-	}
+	rc = -ENOMEM;
+	cs->hw.hfcpci.fifos = pci_alloc_consistent(pdev, 32768, 
+						   &cs->hw.hfcpci.fifos_dma);
+	if (!cs->hw.hfcpci.fifos)
+		goto err;
+
 	pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80,
 			       (u_int)cs->hw.hfcpci.fifos_dma);
-	cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, dev_hfcpci->resource[ 1].start, 256, "hfc_pci");
-	if (!cs->hw.hfcpci.pci_io)
-		goto err;
-	
-	printk(KERN_INFO
-	       "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
-	       (u_int) cs->hw.hfcpci.pci_io,
-	       (u_int) cs->hw.hfcpci.fifos,
-	       (u_int) cs->hw.hfcpci.fifos_dma,
-	       cs->irq, HZ);
+	printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s name: %s\n",
+	       id_list[i].vendor_name, id_list[i].card_name);
+	printk(KERN_INFO "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d\n",
+	       (u_int) cs->hw.hfcpci.pci_io, (u_int) cs->hw.hfcpci.fifos,
+	       (u_int) cs->hw.hfcpci.fifos_dma, cs->irq);
 	printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID));
 	cs->hw.hfcpci.int_m2 = 0;	/* disable alle interrupts */
 	cs->hw.hfcpci.int_m1 = 0;
@@ -1456,17 +1425,46 @@
 	/* At this point the needed PCI config is done */
 	/* fifos are still not enabled */
 
-	cs->irq_flags |= SA_SHIRQ;
-
+	init_timer(&cs->hw.hfcpci.timer);
 	cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer;
 	cs->hw.hfcpci.timer.data = (long) cs;
-	init_timer(&cs->hw.hfcpci.timer);
 
 	hfcpci_reset(cs);
 	cs->auxcmd = &hfcpci_auxcmd;
 	cs->card_ops = &hfcpci_ops;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+/* this variable is used as card index when more than one cards are present */
+static struct pci_dev *dev_hfcpci __initdata = NULL;
+
+int __init
+setup_hfcpci(struct IsdnCard *card)
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+	int i;
+	struct pci_dev *tmp_hfcpci = NULL;
+
+	strcpy(tmp, hfcpci_revision);
+	printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
+	cs->hw.hfcpci.int_s1 = 0;
+	cs->dc.hfcpci.ph_state = 0;
+	cs->hw.hfcpci.fifo = 255;
+
+	for (i = 0; id_list[i].vendor_id; i++) {
+		tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
+					     id_list[i].device_id,
+					     dev_hfcpci);
+		if (!tmp_hfcpci)
+			continue;
+
+		if (niccy_pci_probe(card->cs, tmp_hfcpci, i) < 0)
+			return 0;
+		return 1;
+	}
 	return 0;
 }
diff -Nru a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
--- a/drivers/isdn/hisax/hfc_sx.c	Tue Feb 25 11:05:23 2003
+++ b/drivers/isdn/hisax/hfc_sx.c	Thu Mar  6 22:52:04 2003
@@ -1159,6 +1159,74 @@
 	.irq_func = hfcsx_interrupt,
 };
 
+static int __init
+hfcsx_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	int rc;
+	char c;
+
+	cs->irq = card->para[0];
+	cs->hw.hfcsx.base = card->para[1] & 0xfffe;
+
+	cs->hw.hfcsx.fifo = 255;
+	cs->hw.hfcsx.int_s1 = 0;
+	cs->dc.hfcsx.ph_state = 0;
+
+	rc = -EBUSY;
+	if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn"))
+		goto err;
+
+	rc = -ENODEV;
+	byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
+	byteout(cs->hw.hfcsx.base + 1, ((cs->hw.hfcsx.base >> 8) & 3) | 0x54);
+	udelay(10);
+	cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);
+	switch (cs->hw.hfcsx.chip >> 4) {
+	case 1: 
+		c ='+';
+		break;
+	case 9: 
+		c ='P';
+		break;
+	default:
+		printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n",
+		       cs->hw.hfcsx.chip >> 4);
+		goto err;
+	}  
+	if (!ccd_sp_irqtab[cs->irq & 0xF]) {
+		printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n",
+		       cs->irq & 0xF);
+		goto err;
+	}
+	rc = -ENOMEM;
+	cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC);
+	if (!cs->hw.hfcsx.extra) {
+		printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
+		goto err;
+	}
+	printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d\n",
+	       c, (u_int) cs->hw.hfcsx.base, cs->irq);
+
+	cs->hw.hfcsx.int_m2 = 0;	/* disable alle interrupts */
+	cs->hw.hfcsx.int_m1 = 0;
+	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
+
+	init_timer(&cs->hw.hfcsx.timer);
+	cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer;
+	cs->hw.hfcsx.timer.data = (long) cs;
+	cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */
+	cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not eval. */
+
+	hfcsx_reset(cs);
+	cs->auxcmd = &hfcsx_auxcmd;
+	cs->card_ops = &hfcsx_ops;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id hfc_ids[] __initdata = {
 	{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
@@ -1174,7 +1242,6 @@
 int __devinit
 setup_hfcsx(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, hfcsx_revision);
@@ -1227,62 +1294,7 @@
 		}
 	}
 #endif
-	cs->hw.hfcsx.base = card->para[1] & 0xfffe;
-	cs->irq = card->para[0];
-	cs->hw.hfcsx.int_s1 = 0;
-	cs->dc.hfcsx.ph_state = 0;
-	cs->hw.hfcsx.fifo = 255;
-
-	if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn"))
-		return 0;
-	byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
-	byteout(cs->hw.hfcsx.base + 1,
-		((cs->hw.hfcsx.base >> 8) & 3) | 0x54);
-	udelay(10);
-	cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);
-	switch (cs->hw.hfcsx.chip >> 4) {
-	case 1: 
-		tmp[0] ='+';
-		break;
-	case 9: 
-		tmp[0] ='P';
-		break;
-	default:
-		printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n",
-		       cs->hw.hfcsx.chip >> 4);
-		hisax_release_resources(cs);
+	if (hfcsx_probe(card->cs, card) < 0)
 		return 0;
-	}  
-	if (!ccd_sp_irqtab[cs->irq & 0xF]) {
-		printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n",
-		       cs->irq & 0xF);
-		hisax_release_resources(cs);
-		return 0;
-	}  
-	cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), 
-				     GFP_ATOMIC);
-	if (!cs->hw.hfcsx.extra) {
-		hisax_release_resources(cs);
-		printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
-		return 0;
-	}
-	
-	printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n",
-	       tmp[0], (u_int) cs->hw.hfcsx.base,
-	       cs->irq, HZ);
-	cs->hw.hfcsx.int_m2 = 0;	/* disable alle interrupts */
-	cs->hw.hfcsx.int_m1 = 0;
-	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
-	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
-
-	cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer;
-	cs->hw.hfcsx.timer.data = (long) cs;
-	cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */
-	cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */
-	init_timer(&cs->hw.hfcsx.timer);
-
-	hfcsx_reset(cs);
-	cs->auxcmd = &hfcsx_auxcmd;
-	cs->card_ops = &hfcsx_ops;
 	return 1;
 }
diff -Nru a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c
--- a/drivers/isdn/hisax/hfcscard.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/hfcscard.c	Thu Mar  6 22:52:04 2003
@@ -133,6 +133,50 @@
 	.irq_func = hfcs_interrupt,
 };
 
+static int __init
+hfcs_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->irq = card->para[0];
+	cs->hw.hfcD.addr = card->para[1];
+
+	if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn"))
+		goto err;
+
+	printk(KERN_INFO "HFCS: defined at 0x%x IRQ %d\n",
+	       cs->hw.hfcD.addr, cs->irq);
+
+	cs->hw.hfcD.cip = 0;
+	cs->hw.hfcD.int_s1 = 0;
+	cs->hw.hfcD.send = NULL;
+	cs->bcs[0].hw.hfc.send = NULL;
+	cs->bcs[1].hw.hfc.send = NULL;
+	cs->hw.hfcD.dfifosize = 512;
+	cs->dc.hfcd.ph_state = 0;
+	cs->hw.hfcD.fifo = 255;
+
+	if (cs->typ == ISDN_CTYPE_TELES3C) {
+		cs->hw.hfcD.bfifosize = 1024 + 512;
+		/* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
+		outb(0x00, cs->hw.hfcD.addr);
+		outb(0x56, cs->hw.hfcD.addr | 1);
+	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
+		cs->hw.hfcD.bfifosize = 7*1024 + 512;
+		/* Acer P10 IO ADR is 0x300 */
+		outb(0x00, cs->hw.hfcD.addr);
+		outb(0x57, cs->hw.hfcD.addr | 1);
+	}
+	set_cs_func(cs);
+	init_timer(&cs->hw.hfcD.timer);
+	cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
+	cs->hw.hfcD.timer.data = (long) cs;
+	hfcs_reset(cs);
+	cs->card_ops = &hfcs_ops;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id hfc_ids[] __initdata = {
 	{ ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
@@ -166,7 +210,6 @@
 int __init
 setup_hfcs(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, hfcs_revision);
@@ -220,42 +263,8 @@
 		}
 	}
 #endif
-	cs->hw.hfcD.addr = card->para[1] & 0xfffe;
-	cs->irq = card->para[0];
-	cs->hw.hfcD.cip = 0;
-	cs->hw.hfcD.int_s1 = 0;
-	cs->hw.hfcD.send = NULL;
-	cs->bcs[0].hw.hfc.send = NULL;
-	cs->bcs[1].hw.hfc.send = NULL;
-	cs->hw.hfcD.dfifosize = 512;
-	cs->dc.hfcd.ph_state = 0;
-	cs->hw.hfcD.fifo = 255;
-	if (cs->typ == ISDN_CTYPE_TELES3C) {
-		cs->hw.hfcD.bfifosize = 1024 + 512;
-	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
-		cs->hw.hfcD.bfifosize = 7*1024 + 512;
-	} else
-		return (0);
-	if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn"))
+	if (hfcs_probe(card->cs, card) < 0)
 		return 0;
-	printk(KERN_INFO
-	       "HFCS: defined at 0x%x IRQ %d HZ %d\n",
-	       cs->hw.hfcD.addr,
-	       cs->irq, HZ);
-	if (cs->typ == ISDN_CTYPE_TELES3C) {
-		/* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
-		outb(0x00, cs->hw.hfcD.addr);
-		outb(0x56, cs->hw.hfcD.addr | 1);
-	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
-		/* Acer P10 IO ADR is 0x300 */
-		outb(0x00, cs->hw.hfcD.addr);
-		outb(0x57, cs->hw.hfcD.addr | 1);
-	}
-	set_cs_func(cs);
-	cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
-	cs->hw.hfcD.timer.data = (long) cs;
-	init_timer(&cs->hw.hfcD.timer);
-	hfcs_reset(cs);
-	cs->card_ops = &hfcs_ops;
-	return (1);
+	return 1;
+	
 }
diff -Nru a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
--- a/drivers/isdn/hisax/hisax.h	Sun Jan 12 16:03:30 2003
+++ b/drivers/isdn/hisax/hisax.h	Thu Mar  6 23:20:18 2003
@@ -782,7 +782,6 @@
 
 struct gazel_hw {
 	unsigned int cfg_reg;
-	unsigned int pciaddr[2];
         signed   int ipac;
 	signed   int isac;
 	signed   int hscx[2];
@@ -1073,264 +1072,17 @@
 #define  ISDN_CTYPE_COUNT	41
 
 
-#ifdef ISDN_CHIP_ISAC
-#undef ISDN_CHIP_ISAC
-#endif
-
-#ifdef	CONFIG_HISAX_16_0
-#define  CARD_TELES0 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_TELES0  0
-#endif
-
-#ifdef	CONFIG_HISAX_16_3
-#define  CARD_TELES3 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_TELES3  0
-#endif
-
-#ifdef	CONFIG_HISAX_TELESPCI
-#define  CARD_TELESPCI 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_TELESPCI  0
-#endif
-
-#ifdef	CONFIG_HISAX_AVM_A1
-#define  CARD_AVM_A1 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_AVM_A1  0
-#endif
-
-#ifdef	CONFIG_HISAX_AVM_A1_PCMCIA
-#define  CARD_AVM_A1_PCMCIA 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_AVM_A1_PCMCIA  0
-#endif
-
-#ifdef	CONFIG_HISAX_FRITZPCI
-#define  CARD_FRITZPCI 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_FRITZPCI  0
-#endif
-
-#ifdef	CONFIG_HISAX_ELSA
-#define  CARD_ELSA 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_ELSA  0
-#endif
-
-#ifdef	CONFIG_HISAX_IX1MICROR2
-#define	CARD_IX1MICROR2 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_IX1MICROR2 0
-#endif
-
-#ifdef  CONFIG_HISAX_DIEHLDIVA
-#define CARD_DIEHLDIVA 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_DIEHLDIVA 0
-#endif
-
-#ifdef  CONFIG_HISAX_ASUSCOM
-#define CARD_ASUSCOM 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_ASUSCOM 0
-#endif
-
-#ifdef  CONFIG_HISAX_TELEINT
-#define CARD_TELEINT 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_TELEINT 0
-#endif
-
-#ifdef  CONFIG_HISAX_SEDLBAUER
-#define CARD_SEDLBAUER 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_SEDLBAUER 0
-#endif
-
-#ifdef  CONFIG_HISAX_SPORTSTER
-#define CARD_SPORTSTER 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_SPORTSTER 0
-#endif
-
-#ifdef  CONFIG_HISAX_MIC
-#define CARD_MIC 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_MIC 0
-#endif
-
-#ifdef  CONFIG_HISAX_NETJET
-#define CARD_NETJET_S 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_NETJET_S 0
-#endif
-
-#ifdef	CONFIG_HISAX_HFCS
-#define  CARD_HFCS 1
-#else
-#define  CARD_HFCS 0
-#endif
-
-#ifdef	CONFIG_HISAX_HFC_PCI
-#define  CARD_HFC_PCI 1
-#else
-#define  CARD_HFC_PCI 0
-#endif
-
-#ifdef	CONFIG_HISAX_HFC_SX
-#define  CARD_HFC_SX 1
-#else
-#define  CARD_HFC_SX 0
-#endif
-
-#ifdef  CONFIG_HISAX_AMD7930
-#define CARD_AMD7930 1
-#else
-#define CARD_AMD7930 0
-#endif
-
-#ifdef	CONFIG_HISAX_NICCY
-#define	CARD_NICCY 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_NICCY 0
-#endif
-
-#ifdef	CONFIG_HISAX_ISURF
-#define	CARD_ISURF 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_ISURF 0
-#endif
-
-#ifdef	CONFIG_HISAX_S0BOX
-#define	CARD_S0BOX 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_S0BOX 0
-#endif
-
-#ifdef	CONFIG_HISAX_HSTSAPHIR
-#define	CARD_HSTSAPHIR 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_HSTSAPHIR 0
-#endif
-
 #ifdef	CONFIG_HISAX_TESTEMU
-#define	CARD_TESTEMU 1
 #define ISDN_CTYPE_TESTEMU 99
 #undef ISDN_CTYPE_COUNT
 #define  ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU
-#else
-#define CARD_TESTEMU 0
-#endif
-
-#ifdef	CONFIG_HISAX_BKM_A4T
-#define	CARD_BKM_A4T 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_BKM_A4T 0
-#endif
-
-#ifdef	CONFIG_HISAX_SCT_QUADRO
-#define	CARD_SCT_QUADRO 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_SCT_QUADRO 0
-#endif
-
-#ifdef	CONFIG_HISAX_GAZEL
-#define  CARD_GAZEL 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_GAZEL  0
-#endif
-
-#ifdef	CONFIG_HISAX_W6692
-#define	CARD_W6692	1
-#ifndef	ISDN_CHIP_W6692
-#define	ISDN_CHIP_W6692	1
-#endif
-#else
-#define	CARD_W6692	0
 #endif
 
 #ifdef  CONFIG_HISAX_NETJET_U
-#define CARD_NETJET_U 1
-#ifndef ISDN_CHIP_ICC
-#define ISDN_CHIP_ICC 1
-#endif
 #ifndef HISAX_UINTERFACE
 #define HISAX_UINTERFACE 1
 #endif
 #else
-#define CARD_NETJET_U 0
-#endif
-
-#ifdef CONFIG_HISAX_ENTERNOW_PCI
-#define CARD_FN_ENTERNOW_PCI 1
 #endif
 
 #define TEI_PER_CARD 1
@@ -1402,7 +1154,7 @@
 int HiSax_command(isdn_ctrl * ic);
 int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
 void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args);
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, va_list args);
 void HiSax_reportcard(int cardnr, int sel);
 int QuickHex(char *txt, u8 * p, int cnt);
 void LogFrame(struct IsdnCardState *cs, u8 * p, int size);
diff -Nru a/drivers/isdn/hisax/hisax_fcclassic.c b/drivers/isdn/hisax/hisax_fcclassic.c
--- a/drivers/isdn/hisax/hisax_fcclassic.c	Sat Jan  4 07:35:38 2003
+++ b/drivers/isdn/hisax/hisax_fcclassic.c	Sat Feb 22 08:50:25 2003
@@ -231,7 +231,7 @@
 	adapter->isac.write_isac      = &fcclassic_write_isac;
 	adapter->isac.read_isac_fifo  = &fcclassic_read_isac_fifo;
 	adapter->isac.write_isac_fifo = &fcclassic_write_isac_fifo;
-	isac_setup(&adapter->isac);
+	hisax_isac_setup(&adapter->isac);
 	for (i = 0; i < 2; i++) {
 		hscx_init(&adapter->hscx[i]);
 		adapter->hscx[i].priv            = adapter;
diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c	Wed Jan 15 08:22:25 2003
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c	Sat Feb 22 10:05:19 2003
@@ -46,24 +46,22 @@
 MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
 MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver");
 
-// FIXME temporary hack until I sort out the new PnP stuff
-#define __ISAPNP__
-
 static struct pci_device_id fcpci_ids[] __devinitdata = {
-	{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1   , PCI_ANY_ID, PCI_ANY_ID,
-	  0, 0, (unsigned long) "Fritz!Card PCI" },
-	{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1_V2, PCI_ANY_ID, PCI_ANY_ID,
-	  0, 0, (unsigned long) "Fritz!Card PCI v2" },
-	{ }
+	{ .vendor      = PCI_VENDOR_ID_AVM,
+	  .device      = PCI_DEVICE_ID_AVM_A1,
+	  .subvendor   = PCI_ANY_ID,
+	  .subdevice   = PCI_ANY_ID,
+	  .driver_data = (unsigned long) "Fritz!Card PCI",
+	},
+	{ .vendor      = PCI_VENDOR_ID_AVM,
+	  .device      = PCI_DEVICE_ID_AVM_A1_V2,
+	  .subvendor   = PCI_ANY_ID,
+	  .subdevice   = PCI_ANY_ID,
+	  .driver_data = (unsigned long) "Fritz!Card PCI v2" },
+	{}
 };
-MODULE_DEVICE_TABLE(pci, fcpci_ids);
 
-static struct pnp_card_device_id fcpnp_ids[] __devinitdata = {
-	{ .id = "AVM0900", 
-	  .driver_data = (unsigned long) "Fritz!Card PnP",
-	  .devs = { { "AVM0900" } } }
-};
-MODULE_DEVICE_TABLE(pnp_card, fcpnp_ids);
+MODULE_DEVICE_TABLE(pci, fcpci_ids);
 
 static int protocol = 2;       /* EURO-ISDN Default */
 MODULE_PARM(protocol, "i");
@@ -782,7 +780,7 @@
 	case AVM_FRITZ_PCI:
 	case AVM_FRITZ_PNP:
 		fcpci_init(adapter);
-		isac_setup(&adapter->isac);
+		hisax_isac_setup(&adapter->isac);
 		break;
 	}
 	val = adapter->read_hdlc_status(adapter, 0);
@@ -908,10 +906,10 @@
 	.id_table = fcpci_ids,
 };
 
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP_CARD
 
 static int __devinit fcpnp_probe(struct pnp_card *card,
-				 const struct pnp_card_device_id *card_id)
+				 const struct pnp_card_id *card_id)
 {
 	struct fritz_adapter *adapter;
 	struct pnp_dev *pnp_dev;
@@ -957,6 +955,14 @@
 	delete_adapter(adapter);
 }
 
+static struct pnp_card_id fcpnp_ids[] __devinitdata = {
+	{ .id          = "AVM0900", 
+	  .driver_data = (unsigned long) "Fritz!Card PnP",
+	  .devs        = { { "AVM0900" } },
+	},
+	{}
+};
+
 static struct pnpc_driver fcpnp_driver = {
 	.name     = "fcpnp",
 	.probe    = fcpnp_probe,
@@ -968,7 +974,7 @@
 
 static int __init hisax_fcpcipnp_init(void)
 {
-	int retval, pci_nr_found;
+	int retval = 0, pci_nr_found;
 
 	printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n");
 
@@ -977,10 +983,8 @@
 		goto out;
 	pci_nr_found = retval;
 
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP_CARD
 	retval = pnpc_register_driver(&fcpnp_driver);
-#else
-	retval = 0;
 #endif
 	if (retval < 0)
 		goto out_unregister_pci;
@@ -988,14 +992,14 @@
 #if !defined(CONFIG_HOTPLUG) || defined(MODULE)
 	if (pci_nr_found + retval == 0) {
 		retval = -ENODEV;
-		goto out_unregister_isapnp;
+		goto out_unregister_pnp;
 	}
 #endif
 	return 0;
 
 #if !defined(CONFIG_HOTPLUG) || defined(MODULE)
- out_unregister_isapnp:
-#ifdef __ISAPNP__
+ out_unregister_pnp:
+#ifdef CONFIG_PNP_CARD
 	pnpc_unregister_driver(&fcpnp_driver);
 #endif
 #endif
@@ -1007,7 +1011,7 @@
 
 static void __exit hisax_fcpcipnp_exit(void)
 {
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP_CARD
 	pnpc_unregister_driver(&fcpnp_driver);
 #endif
 	pci_unregister_driver(&fcpci_driver);
diff -Nru a/drivers/isdn/hisax/hisax_isac.c b/drivers/isdn/hisax/hisax_isac.c
--- a/drivers/isdn/hisax/hisax_isac.c	Sat Jan  4 07:35:38 2003
+++ b/drivers/isdn/hisax/hisax_isac.c	Sat Feb 22 08:50:25 2003
@@ -770,7 +770,7 @@
 	FsmInitTimer(&isac->l1m, &isac->timer);
 }
 
-void isac_setup(struct isac *isac)
+void hisax_isac_setup(struct isac *isac)
 {
 	int val, eval;
 
@@ -890,7 +890,7 @@
 EXPORT_SYMBOL(isacsx_setup);
 EXPORT_SYMBOL(isacsx_irq);
 
-EXPORT_SYMBOL(isac_setup);
+EXPORT_SYMBOL(hisax_isac_setup);
 EXPORT_SYMBOL(isac_irq);
 
 module_init(hisax_isac_init);
diff -Nru a/drivers/isdn/hisax/hisax_isac.h b/drivers/isdn/hisax/hisax_isac.h
--- a/drivers/isdn/hisax/hisax_isac.h	Sat Jan  4 07:35:38 2003
+++ b/drivers/isdn/hisax/hisax_isac.h	Sat Feb 22 08:50:25 2003
@@ -36,7 +36,7 @@
 void isac_init(struct isac *isac);
 void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg);
 
-void isac_setup(struct isac *isac);
+void hisax_isac_setup(struct isac *isac);
 void isac_irq(struct isac *isac);
 
 void isacsx_setup(struct isac *isac);
diff -Nru a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c
--- a/drivers/isdn/hisax/isdnl1.c	Sat Jan 11 11:24:09 2003
+++ b/drivers/isdn/hisax/isdnl1.c	Sat Feb 22 09:10:42 2003
@@ -126,7 +126,7 @@
 };
 
 void
-debugl1(struct IsdnCardState *cs, char *fmt, ...)
+debugl1(struct IsdnCardState *cs, const char *fmt, ...)
 {
 	va_list args;
 	char tmp[8];
diff -Nru a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h
--- a/drivers/isdn/hisax/isdnl1.h	Sat Jan 11 11:24:09 2003
+++ b/drivers/isdn/hisax/isdnl1.h	Sat Feb 22 09:10:42 2003
@@ -28,7 +28,7 @@
 #define B_LL_CONNECT	9
 #define B_LL_OK		10
 
-extern void debugl1(struct IsdnCardState *cs, char *fmt, ...);
+extern void debugl1(struct IsdnCardState *cs, const char *fmt, ...);
 extern void DChannel_proc_xmt(struct IsdnCardState *cs);
 extern void DChannel_proc_rcv(struct IsdnCardState *cs);
 extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg);
diff -Nru a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
--- a/drivers/isdn/hisax/isurf.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/isurf.c	Thu Mar  6 22:52:04 2003
@@ -187,95 +187,92 @@
 static struct pnp_card *pnp_surf __devinitdata = NULL;
 #endif
 
-int __init
-setup_isurf(struct IsdnCard *card)
+static int __init
+isurf_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	unsigned long phymem;
-	char tmp[64];
 
-	strcpy(tmp, ISurf_revision);
-	printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp));
-	
-	if (card->para[1] && card->para[2]) {
-		cs->hw.isurf.reset = card->para[1];
-		phymem = card->para[2];
-		cs->irq = card->para[0];
-	} else {
-#ifdef __ISAPNP__
-		struct pnp_card *pb;
-		struct pnp_dev *pd;
+	phymem = card->para[2];
+	cs->hw.isurf.reset = card->para[1];
+	cs->irq = card->para[0];
 
-		if (isapnp_present()) {
-			cs->subtyp = 0;
-			if ((pb = pnp_find_card(
-				ISAPNP_VENDOR('S', 'I', 'E'),
-				ISAPNP_FUNCTION(0x0010), pnp_surf))) {
-				pnp_surf = pb;
-				pd = NULL;
-				if (!(pd = pnp_find_dev(pnp_surf,
-					ISAPNP_VENDOR('S', 'I', 'E'),
-					ISAPNP_FUNCTION(0x0010), pd))) {
-					printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
-					return (0);
-				}
-				if (pnp_device_attach(pd) < 0) {
-					printk(KERN_ERR "ISurfPnP: attach failed\n");
-					return 0;
-				}
-				if (pnp_activate_dev(pd) < 0) {
-					printk(KERN_ERR "ISurfPnP: activate failed\n");
-					pnp_device_detach(pd);
-					return 0;
-				}
-				if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) {
-					printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n",
-						pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1));
-					pnp_device_detach(pd);
-					return(0);
-				}
-				cs->hw.isurf.reset = pnp_port_start(pd, 0);
-				phymem = pnp_port_start(pd, 1);
-				cs->irq = pnp_irq(pd, 0);
-			} else {
-				printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
-				return(0);
-			}
-		} else {
-			printk(KERN_INFO "ISurfPnP: no ISAPnP bus found\n");
-			return(0);
-		}
-#else
-		printk(KERN_WARNING "HiSax: %s port/mem not set\n",
-			CardType[card->typ]);
-		return (0);
-#endif
-	}
 	if (!request_io(&cs->rs, cs->hw.isurf.reset, 1, "isurf isdn"))
 		goto err;
-	cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE, "isurf iomem");
+
+	cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE,
+					 "isurf iomem");
 	if (!cs->hw.isurf.isar)
 		goto err;
 
 	cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET;
-	printk(KERN_INFO
-	       "ISurf: defined at 0x%x 0x%lx IRQ %d\n",
-	       cs->hw.isurf.reset,
-	       card->para[2],
-	       cs->irq);
+	printk(KERN_INFO "ISurf: defined at 0x%x 0x%lx IRQ %d\n",
+	       cs->hw.isurf.reset, phymem, cs->irq);
 
 	cs->auxcmd = &isurf_auxcmd;
 	cs->card_ops = &isurf_ops;
 	cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r;
 	cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r;
 	reset_isurf(cs, ISURF_RESET);
-	test_and_set_bit(HW_ISAR, &cs->HW_Flags);
+	__set_bit(HW_ISAR, &cs->HW_Flags);
 	isac_setup(cs, &isac_ops);
 	if (isar_setup(cs, &isar_ops))
 		goto err;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
-	return 0;
+	return -EBUSY;
+}
 
+int __init
+setup_isurf(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, ISurf_revision);
+	printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp));
+	
+#ifdef __ISAPNP__
+	if (!card->para[1] || !card->para[2]) {
+		struct pnp_card *pb;
+		struct pnp_dev *pd;
+	
+		cs->subtyp = 0;
+		if ((pb = pnp_find_card(
+			     ISAPNP_VENDOR('S', 'I', 'E'),
+			     ISAPNP_FUNCTION(0x0010), pnp_surf))) {
+			pnp_surf = pb;
+			pd = NULL;
+			if (!(pd = pnp_find_dev(pnp_surf,
+						ISAPNP_VENDOR('S', 'I', 'E'),
+						ISAPNP_FUNCTION(0x0010), pd))) {
+				printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
+				return (0);
+			}
+			if (pnp_device_attach(pd) < 0) {
+				printk(KERN_ERR "ISurfPnP: attach failed\n");
+				return 0;
+			}
+			if (pnp_activate_dev(pd) < 0) {
+				printk(KERN_ERR "ISurfPnP: activate failed\n");
+				pnp_device_detach(pd);
+				return 0;
+			}
+			if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) {
+				printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n",
+				       pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1));
+				pnp_device_detach(pd);
+				return(0);
+			}
+			card->para[1] = pnp_port_start(pd, 0);
+			card->para[2] = pnp_port_start(pd, 1);
+			card->para[0] = pnp_irq(pd, 0);
+		} else {
+			printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
+			return 0;
+		}
+	}
+#endif
+	if (isurf_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c
--- a/drivers/isdn/hisax/ix1_micro.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/ix1_micro.c	Thu Mar  6 22:52:04 2003
@@ -162,6 +162,29 @@
 	.irq_func = hscxisac_irq,
 };
 
+static int __init
+ix1_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->irq             = card->para[0];
+	cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET;
+	cs->hw.ix1.isac     = card->para[1] + ISAC_DATA_OFFSET;
+	cs->hw.ix1.hscx     = card->para[1] + HSCX_DATA_OFFSET;
+	cs->hw.ix1.cfg_reg  = card->para[1];
+	if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg"))
+		goto err;
+	
+	printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
+	       CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg);
+	ix1_reset(cs);
+	cs->card_ops = &ix1_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id itk_ids[] __initdata = {
 	{ ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25),
@@ -181,14 +204,18 @@
 int __init
 setup_ix1micro(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, ix1_revision);
 	printk(KERN_INFO "HiSax: ITK IX1 driver Rev. %s\n", HiSax_getrev(tmp));
 
+	if (card->para[1]) {
+		if (ix1_probe(card->cs, card))
+			return 0;
+		return 1;
+	}
 #ifdef __ISAPNP__
-	if (!card->para[1] && isapnp_present()) {
+	if (isapnp_present()) {
 		struct pnp_card *pb;
 		struct pnp_dev *pd;
 
@@ -221,7 +248,9 @@
 					}
 					card->para[1] = pnp_port_start(pd, 0);
 					card->para[0] = pnp_irq(pd, 0);
-					break;
+					if (ix1_probe(card->cs, card))
+						return 0;
+					return 1;
 				} else {
 					printk(KERN_ERR "ITK PnP: PnP error card found, no device\n");
 				}
@@ -231,27 +260,8 @@
 		} 
 		if (!idev->card_vendor) {
 			printk(KERN_INFO "ITK PnP: no ISAPnP card found\n");
-			return(0);
 		}
 	}
 #endif
-	/* IO-Ports */
-	cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET;
-	cs->hw.ix1.isac = card->para[1] + ISAC_DATA_OFFSET;
-	cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET;
-	cs->hw.ix1.cfg_reg = card->para[1];
-	cs->irq = card->para[0];
-	if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg"))
-		goto err;
-	
-	printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
-	       CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg);
-	ix1_reset(cs);
-	cs->card_ops = &ix1_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	return 1;
- err:
-	hisax_release_resources(cs);
 	return 0;
 }
diff -Nru a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
--- a/drivers/isdn/hisax/mic.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/mic.c	Thu Mar  6 22:52:04 2003
@@ -138,17 +138,11 @@
 	.irq_func = hscxisac_irq,
 };
 
-int __init
-setup_mic(struct IsdnCard *card)
+static int __init
+mic_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, mic_revision);
-	printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp));
-
-	cs->hw.mic.cfg_reg = card->para[1];
 	cs->irq = card->para[0];
+	cs->hw.mic.cfg_reg = card->para[1];
 	cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR;
 	cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC;
 	cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX;
@@ -158,11 +152,25 @@
   
 	printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n",
 	       cs->hw.mic.cfg_reg, cs->irq);
+
 	cs->card_ops = &mic_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
-	return 0;
+	return -EBUSY;
+}
+
+int __init
+setup_mic(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, mic_revision);
+	printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp));
+
+	if (mic_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
--- a/drivers/isdn/hisax/niccy.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/niccy.c	Thu Mar  6 22:52:04 2003
@@ -199,6 +199,70 @@
 	.irq_func = niccy_interrupt,
 };
 
+static int __init
+niccy_probe(struct IsdnCardState *cs)
+{
+	printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
+	       CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
+	       cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
+	cs->card_ops = &niccy_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		return -EBUSY;
+	return 0;
+}
+
+static int __init
+niccy_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = NICCY_PNP;
+	cs->irq = card->para[0];
+	cs->hw.niccy.isac = card->para[1] + ISAC_PNP;
+	cs->hw.niccy.hscx = card->para[1] + HSCX_PNP;
+	cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP;
+	cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP;
+	cs->hw.niccy.cfg_reg = 0;
+
+	if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr"))
+		goto err;
+	if (niccy_probe(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	u32 pci_ioaddr;
+
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = NICCY_PCI;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.niccy.cfg_reg = pci_resource_start(pdev, 0);
+	pci_ioaddr = pci_resource_start(pdev, 1);
+	cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
+	cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
+	cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
+	cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
+	if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci"))
+		goto err;
+	if (niccy_probe(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *niccy_dev __initdata = NULL;
 #ifdef __ISAPNP__
 static struct pnp_card *pnp_c __devinitdata = NULL;
@@ -207,7 +271,6 @@
 int __init
 setup_niccy(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, niccy_revision);
@@ -252,66 +315,18 @@
 	}
 #endif
 	if (card->para[1]) {
-		cs->hw.niccy.isac = card->para[1] + ISAC_PNP;
-		cs->hw.niccy.hscx = card->para[1] + HSCX_PNP;
-		cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP;
-		cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP;
-		cs->hw.niccy.cfg_reg = 0;
-		cs->subtyp = NICCY_PNP;
-		cs->irq = card->para[0];
-		if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data"))
-			goto err;
-		if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr"))
-			goto err;
+		if (niccy_pnp_probe(card->cs, card) < 0)
+			return 0;
+		return 1;
 	} else {
 #if CONFIG_PCI
-		u_int pci_ioaddr;
-		cs->subtyp = 0;
 		if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM,
 			PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) {
-			if (pci_enable_device(niccy_dev))
-				return(0);
-			/* get IRQ */
-			if (!niccy_dev->irq) {
-				printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n");
-				return(0);
-			}
-			cs->irq = niccy_dev->irq;
-			cs->hw.niccy.cfg_reg = pci_resource_start(niccy_dev, 0);
-			if (!cs->hw.niccy.cfg_reg) {
-				printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n");
-				return(0);
-			}
-			pci_ioaddr = pci_resource_start(niccy_dev, 1);
-			if (!pci_ioaddr) {
-				printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-			cs->subtyp = NICCY_PCI;
-		} else {
-			printk(KERN_WARNING "Niccy: No PCI card found\n");
-			return(0);
+			if (niccy_pci_probe(card->cs, niccy_dev) < 0)
+				return 0;
+			return 1;
 		}
-		cs->irq_flags |= SA_SHIRQ;
-		cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
-		cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
-		cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
-		cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
-
-		if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy"))
-			goto err;
-		if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci"))
-			goto err;
 #endif /* CONFIG_PCI */
 	}
-	printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
-		CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
-		cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
-	cs->card_ops = &niccy_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	return 1;
- err:
-	niccy_release(cs);
 	return 0;
 }
diff -Nru a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
--- a/drivers/isdn/hisax/nj_s.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/nj_s.c	Thu Mar  6 22:52:04 2003
@@ -106,96 +106,99 @@
 	.irq_func = nj_s_interrupt,
 };
 
+static int __init
+nj_s_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	pci_set_master(pdev);
+
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.njet.pdev = pdev;
+	cs->hw.njet.base = pci_resource_start(pdev, 0);
+	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn"))
+		return 0;
+	
+	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+	cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
+	
+	cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
+	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	
+	cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
+	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	
+	cs->hw.njet.auxd = 0xC0;
+	cs->hw.njet.dmactrl = 0;
+	
+	byteout(cs->hw.njet.auxa, 0);
+	byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
+	byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
+	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+
+	switch ((NETjet_ReadIC(cs, ISAC_RBCH) >> 5) & 3) {
+	case 0 :
+		break;
+	case 3 :
+		printk(KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" );
+		goto err;
+	default :
+		printk(KERN_WARNING "NETjet-S: No PCI card found\n" );
+		goto err;
+	}
+	printk(KERN_INFO
+		"NETjet-S: PCI card configured at %#lx IRQ %d\n",
+		cs->hw.njet.base, cs->irq);
+	
+	nj_s_reset(cs);
+	cs->irq_flags |= SA_SHIRQ;
+	cs->card_ops = &nj_s_ops;
+	isac_setup(cs, &netjet_dc_ops);
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *dev_netjet __initdata = NULL;
 
 int __init
 setup_netjet_s(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
 	strcpy(tmp, NETjet_S_revision);
-	printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp));
+	printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n",
+	       HiSax_getrev(tmp));
 
-	for ( ;; ) {
-		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
-			if (pci_enable_device(dev_netjet))
-				return(0);
-			pci_set_master(dev_netjet);
-			cs->irq = dev_netjet->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n");
-				return(0);
-			}
-			cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
-			if (!cs->hw.njet.base) {
-				printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n");
-				return(0);
-			}
- 			/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
- 			if ((dev_netjet->subsystem_vendor == 0x55) &&
- 				(dev_netjet->subsystem_device == 0x02)) {
- 				printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n");
- 				printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n");
- 				return(0);
- 			}
- 			/* end new code */
-			cs->hw.njet.pdev = dev_netjet;
-		} else {
-			printk(KERN_WARNING "NETjet-S: No PCI card found\n");
-			return(0);
+	dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+				     PCI_DEVICE_ID_TIGERJET_300, dev_netjet);
+	if (dev_netjet) {
+		/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
+		if (dev_netjet->subsystem_vendor == 0x55 &&
+		    dev_netjet->subsystem_device == 0x02) {
+			printk(KERN_WARNING "Netjet: You tried to load this "
+			       "driver with an incompatible TigerJet-card\n");
+			printk(KERN_WARNING "Use type=41 for Formula-n "
+			       "enter:now ISDN PCI and compatible\n");
+			return 0;
 		}
-
-		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-		cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
-
-		cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
-		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
-		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		cs->hw.njet.auxd = 0xC0;
-		cs->hw.njet.dmactrl = 0;
-
-		byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
-		byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
-		byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
-
-		switch ( ( ( NETjet_ReadIC( cs, ISAC_RBCH ) >> 5 ) & 3 ) )
-		{
-			case 0 :
-				break;
-
-			case 3 :
-				printk( KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" );
-				continue;
-
-			default :
-				printk( KERN_WARNING "NETjet-S: No PCI card found\n" );
-				return 0;
-                }
-                break;
-	}
-	printk(KERN_INFO
-		"NETjet-S: PCI card configured at %#lx IRQ %d\n",
-		cs->hw.njet.base, cs->irq);
-	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn"))
+		if (nj_s_probe(card->cs, dev_netjet))
+			return 1;
 		return 0;
-	
-	nj_s_reset(cs);
-	cs->irq_flags |= SA_SHIRQ;
-	cs->card_ops = &nj_s_ops;
-	isac_setup(cs, &netjet_dc_ops);
-	return 1;
+	}
+	printk(KERN_WARNING "NETjet-S: No PCI card found\n");
+	return 0;
 }
+
diff -Nru a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
--- a/drivers/isdn/hisax/nj_u.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/nj_u.c	Thu Mar  6 22:52:05 2003
@@ -110,88 +110,85 @@
 	.irq_func = nj_u_interrupt,
 };
 
+static int __init
+nj_u_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	pci_set_master(pdev);
+
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.njet.pdev = pdev;
+	cs->hw.njet.base = pci_resource_start(pdev, 0);
+	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netspider-u isdn"))
+		goto err;
+	
+	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+	cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
+
+	cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
+	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	
+	cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
+	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	
+	cs->hw.njet.auxd = 0xC0;
+	cs->hw.njet.dmactrl = 0;
+	
+	byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
+	byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
+	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+
+	switch ((NETjet_ReadIC(cs, ICC_RBCH) >> 5) & 3)	{
+	case 3:
+		break;
+	case 0:
+		printk(KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" );
+		goto err;
+	default:
+		printk(KERN_WARNING "NETspider-U: No PCI card found\n" );
+		goto err;
+	}
+	printk(KERN_INFO "NETspider-U: PCI card configured at %#lx IRQ %d\n",
+	       cs->hw.njet.base, cs->irq);
+
+	nj_u_reset(cs);
+	cs->card_ops = &nj_u_ops;
+	icc_setup(cs, &netjet_dc_ops);
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *dev_netjet __initdata = NULL;
 
 int __init
 setup_netjet_u(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
 	strcpy(tmp, NETjet_U_revision);
-	printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp));
-
-	for ( ;; ) {
-		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
-			if (pci_enable_device(dev_netjet))
-				return(0);
-			pci_set_master(dev_netjet);
-			cs->irq = dev_netjet->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n");
-				return(0);
-			}
-			cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
-			if (!cs->hw.njet.base) {
-				printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-			cs->hw.njet.pdev = dev_netjet;
-		} else {
-			printk(KERN_WARNING "NETspider-U: No PCI card found\n");
-			return(0);
-		}
-
-		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-		cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
-
-		cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
-		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
-		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		cs->hw.njet.auxd = 0xC0;
-		cs->hw.njet.dmactrl = 0;
-
-		byteout(cs->hw.njet.auxa, 0);
-		byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
-		byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
-		byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
-
-		switch ( ( ( NETjet_ReadIC( cs, ICC_RBCH ) >> 5 ) & 3 ) )
-		{
-			case 3 :
-				break;
-
-			case 0 :
-				printk( KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" );
-				continue;
-
-			default :
-				printk( KERN_WARNING "NETspider-U: No PCI card found\n" );
-				return 0;
-                }
-                break;
-	}
-	printk(KERN_INFO
-		"NETspider-U: PCI card configured at %#lx IRQ %d\n",
-		cs->hw.njet.base, cs->irq);
-	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn"))
-		return 0;
+	printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n",
+	       HiSax_getrev(tmp));
 	
-	nj_u_reset(cs);
-	cs->irq_flags |= SA_SHIRQ;
-	cs->card_ops = &nj_u_ops;
-	icc_setup(cs, &netjet_dc_ops);
-	return 1;
+	dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+				     PCI_DEVICE_ID_TIGERJET_300, dev_netjet);
+	if (dev_netjet) {
+		if (nj_u_probe(card->cs, dev_netjet))
+			return 1;
+		return 0;
+	}
+	printk(KERN_WARNING "NETspider-U: No PCI card found\n");
+	return 0;
 }
diff -Nru a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c
--- a/drivers/isdn/hisax/s0box.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/s0box.c	Thu Mar  6 22:52:05 2003
@@ -172,14 +172,9 @@
 	.irq_func = hscxisac_irq,
 };
 
-int __init
-setup_s0box(struct IsdnCard *card)
+static int __init
+s0box_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, s0box_revision);
-	printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
 	cs->hw.teles3.cfg_reg = card->para[1];
 	cs->hw.teles3.hscx[0] = -0x20;
 	cs->hw.teles3.hscx[1] = 0x0;
@@ -200,8 +195,20 @@
 	cs->card_ops = &s0box_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
-	return 0;
+	return -EBUSY;
+}
+
+int __init
+setup_s0box(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, s0box_revision);
+	printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
+	if (s0box_probe(card->cs, card))
+		return 0;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c
--- a/drivers/isdn/hisax/saphir.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/saphir.c	Thu Mar  6 22:52:05 2003
@@ -201,36 +201,21 @@
 	.irq_func = saphir_interrupt,
 };
 
-int __init
-setup_saphir(struct IsdnCard *card)
+static int __init
+saphir_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, saphir_rev);
-	printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_HSTSAPHIR)
-		return (0);
-
-	init_timer(&cs->hw.saphir.timer);
-	/* IO-Ports */
 	cs->hw.saphir.cfg_reg = card->para[1];
 	cs->hw.saphir.isac = card->para[1] + ISAC_DATA;
 	cs->hw.saphir.hscx = card->para[1] + HSCX_DATA;
 	cs->hw.saphir.ale = card->para[1] + ADDRESS_REG;
 	cs->irq = card->para[0];
+
 	if (!request_io(&cs->rs, cs->hw.saphir.cfg_reg, 6, "saphir"))
 		goto err;
 
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d io:0x%X\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.saphir.cfg_reg);
+	printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
+	       CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg);
 
-	cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
-	cs->hw.saphir.timer.data = (long) cs;
-	cs->hw.saphir.timer.expires = jiffies + 4*HZ;
-	add_timer(&cs->hw.saphir.timer);
 	if (saphir_reset(cs))
 		goto err;
 
@@ -238,8 +223,27 @@
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
 
-	return 1;
- err:
-	saphir_release(cs);
+	init_timer(&cs->hw.saphir.timer);
+	cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
+	cs->hw.saphir.timer.data = (long) cs;
+	cs->hw.saphir.timer.expires = jiffies + 4*HZ;
+	add_timer(&cs->hw.saphir.timer);
 	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+int __init
+setup_saphir(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, saphir_rev);
+	printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n",
+	       HiSax_getrev(tmp));
+
+	if (saphir_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
--- a/drivers/isdn/hisax/sedlbauer.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/sedlbauer.c	Thu Mar  6 22:52:05 2003
@@ -73,7 +73,6 @@
 #define SEDL_SPEEDFAX_PYRAMID	7
 #define SEDL_SPEEDFAX_PCI	8
 
-#define SEDL_CHIP_TEST		0
 #define SEDL_CHIP_ISAC_HSCX	1
 #define SEDL_CHIP_ISAC_ISAR	2
 #define SEDL_CHIP_IPAC		3
@@ -452,6 +451,241 @@
 	.irq_func    = sedlbauer_isar_interrupt,
 };
 
+static int __init
+sedl_ipac_probe(struct IsdnCardState *cs)
+{
+	u8 val;
+
+	cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
+	val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID);
+	printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val);
+	return (val == 1 || val == 2);
+}
+
+static int __init
+sedl_ipac_init(struct IsdnCardState *cs)
+{
+	cs->card_ops = &sedlbauer_ipac_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		return -ENODEV;
+	sedlbauer_reset(cs);
+	return 0;
+}
+
+static int __init
+sedl_isac_isar_init(struct IsdnCardState *cs)
+{
+	cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
+	cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
+	__set_bit(HW_ISAR, &cs->HW_Flags);
+	cs->card_ops = &sedlbauer_isar_ops;
+	cs->auxcmd = &isar_auxcmd;
+	isac_setup(cs, &isac_ops);
+	return isar_setup(cs, &isar_ops);
+}
+
+static int __init
+sedl_isac_hscx_init(struct IsdnCardState *cs)
+{
+	cs->card_ops = &sedlbauer_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		return -ENODEV;
+	sedlbauer_reset(cs);
+	return 0;
+}
+
+static int __init
+sedl_card_win_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->irq = card->para[0];
+	cs->hw.sedl.cfg_reg = card->para[1];
+	cs->hw.sedl.bus = SEDL_BUS_ISA;
+	if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 8, "sedlbauer isdn"))
+		goto err;
+
+	if (sedl_ipac_probe(cs)) {
+		cs->subtyp = SEDL_SPEED_WIN2_PC104;
+		cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+		cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
+		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+		if (sedl_ipac_init(cs))
+			goto err;
+	} else {
+		cs->subtyp = SEDL_SPEED_CARD_WIN;
+		cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
+		cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
+		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
+		cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
+		cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
+		cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
+		if (sedl_isac_hscx_init(cs))
+			goto err;
+	}
+	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
+	       Sedlbauer_Types[cs->subtyp],
+	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq);
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+sedl_star_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
+	if (sedl_ipac_probe(cs)) {
+		cs->subtyp = SEDL_SPEED_STAR2;
+		cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+		cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
+		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+		if (sedl_ipac_init(cs))
+			goto err;
+	} else {
+		cs->subtyp = SEDL_SPEED_STAR;
+		cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
+		cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
+		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
+		cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
+		cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+		cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+		if (sedl_isac_hscx_init(cs))
+			goto err;
+	}
+	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
+	       Sedlbauer_Types[cs->subtyp],
+	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq);
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+sedl_fax_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = SEDL_SPEED_FAX;
+	cs->hw.sedl.bus = SEDL_BUS_ISA;
+	cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+	if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 16, "sedlbauer isdn"))
+		goto err;
+
+	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
+	       Sedlbauer_Types[cs->subtyp],
+	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 16, cs->irq);
+
+	cs->hw.sedl.adr = cs->hw.sedl.cfg_reg  + SEDL_ISAR_ISA_ADR;
+	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAC;
+	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR;
+	cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_ON;
+	cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_OFF;
+	if (sedl_isac_isar_init(cs))
+		goto err;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+sedl_pci_init(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.sedl.cfg_reg = pci_resource_start(pdev, 0);
+	cs->hw.sedl.bus = SEDL_BUS_PCI;
+
+	if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 256, "sedlbauer isdn"))
+		return -EBUSY;
+
+	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
+	       Sedlbauer_Types[cs->subtyp],
+	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 256, cs->irq);
+
+	cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
+	cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
+	byteout(cs->hw.sedl.cfg_reg, 0xff);
+	byteout(cs->hw.sedl.cfg_reg, 0x00);
+	byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
+	byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
+	byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
+	current->state = TASK_UNINTERRUPTIBLE;
+	schedule_timeout((10*HZ)/1000);
+	byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
+	return 0;
+}
+
+static int __init
+sedl_fax_pyramid_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
+	cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+	if (sedl_pci_init(cs, pdev))
+		goto err;
+
+	cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR;
+	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC;
+	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR;
+	if (sedl_isac_isar_init(cs))
+		goto err;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+sedl_fax_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = SEDL_SPEEDFAX_PCI;
+	cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+
+	if (sedl_pci_init(cs, pdev))
+		goto err;
+
+	cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR;
+	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC;
+	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR;
+	if (sedl_isac_isar_init(cs))
+		goto err;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+sedl_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = SEDL_SPEED_PCI;
+	cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+	if (sedl_pci_init(cs, pdev))
+		goto err;
+
+	cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
+	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
+	if (sedl_ipac_init(cs))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *dev_sedl __devinitdata = NULL;
 
 #ifdef __ISAPNP__
@@ -472,265 +706,117 @@
 int __devinit
 setup_sedlbauer(struct IsdnCard *card)
 {
-	int bytecnt, val;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 	u16 sub_vendor_id, sub_id;
 
 	strcpy(tmp, Sedlbauer_revision);
-	printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp));
+	printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n",
+	       HiSax_getrev(tmp));
 	
- 	if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
- 		cs->subtyp = SEDL_SPEED_CARD_WIN;
-		cs->hw.sedl.bus = SEDL_BUS_ISA;
-		cs->hw.sedl.chip = SEDL_CHIP_TEST;
- 	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {	
- 		cs->subtyp = SEDL_SPEED_STAR;
-		cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
-		cs->hw.sedl.chip = SEDL_CHIP_TEST;
- 	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {	
- 		cs->subtyp = SEDL_SPEED_FAX;
-		cs->hw.sedl.bus = SEDL_BUS_ISA;
-		cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
- 	} else
-		return (0);
-
-	bytecnt = 8;
 	if (card->para[1]) {
-		cs->hw.sedl.cfg_reg = card->para[1];
-		cs->irq = card->para[0];
-		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
-			bytecnt = 16;
+		if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
+			if (sedl_card_win_probe(card->cs, card) < 0)
+				return 0;
+			return 1;
+		} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {	
+			if (sedl_star_probe(card->cs, card) < 0)
+				return 0;
+			return 1;
+		} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {	
+			if (sedl_fax_probe(card->cs, card) < 0)
+				return 0;
+			return 1;
 		}
-	} else {
+	}
 #ifdef __ISAPNP__
-		if (isapnp_present()) {
-			struct pnp_card *pb;
-			struct pnp_dev *pd;
-
-			while(pdev->card_vendor) {
-				if ((pb = pnp_find_card(pdev->card_vendor,
-						        pdev->card_device,
-						        pnp_c))) {
-					pnp_c = pb;
-					pd = NULL;
-					if ((pd = pnp_find_dev(pnp_c,
-							       pdev->vendor,
-							       pdev->function,
-							       pd))) {
-						printk(KERN_INFO "HiSax: %s detected\n",
-							(char *)pdev->driver_data);
-						if (pnp_device_attach(pd) < 0) {
-							printk(KERN_ERR "Sedlbauer PnP: attach failed\n");
-							return 0;
-						}
-						if (pnp_activate_dev(pd) < 0) {
-							printk(KERN_ERR "Sedlbauer PnP: activate failed\n");
-							pnp_device_detach(pd);
+	if (isapnp_present()) {
+		struct pnp_card *pb;
+		struct pnp_dev *pd;
+		
+		while(pdev->card_vendor) {
+			if ((pb = pnp_find_card(pdev->card_vendor,
+						pdev->card_device,
+						pnp_c))) {
+				pnp_c = pb;
+				pd = NULL;
+				if ((pd = pnp_find_dev(pnp_c,
+						       pdev->vendor,
+						       pdev->function,
+						       pd))) {
+					printk(KERN_INFO "HiSax: %s detected\n",
+					       (char *)pdev->driver_data);
+					if (pnp_device_attach(pd) < 0) {
+						printk(KERN_ERR "Sedlbauer PnP: attach failed\n");
+						return 0;
+					}
+					if (pnp_activate_dev(pd) < 0) {
+						printk(KERN_ERR "Sedlbauer PnP: activate failed\n");
+						pnp_device_detach(pd);
+						return 0;
+					}
+					if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
+						printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
+						       pnp_irq(pd, 0), pnp_port_start(pd, 0));
+						pnp_device_detach(pd);
+						goto err;
+					}
+					card->para[1] = pnp_port_start(pd, 0);
+					card->para[0] = pnp_irq(pd, 0);
+					cs->hw.sedl.cfg_reg = card->para[1];
+					cs->irq = card->para[0];
+					if (pdev->function == ISAPNP_FUNCTION(0x2)) {
+						if (sedl_fax_probe(card->cs, card))
 							return 0;
-						}
-						if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
-							printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
-								pnp_irq(pd, 0), pnp_port_start(pd, 0));
-							pnp_device_detach(pd);
-							goto err;
-						}
-						card->para[1] = pnp_port_start(pd, 0);
-						card->para[0] = pnp_irq(pd, 0);
-						cs->hw.sedl.cfg_reg = card->para[1];
-						cs->irq = card->para[0];
-						if (pdev->function == ISAPNP_FUNCTION(0x2)) {
-							cs->subtyp = SEDL_SPEED_FAX;
-							cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
-							bytecnt = 16;
-						} else {
-							cs->subtyp = SEDL_SPEED_CARD_WIN;
-							cs->hw.sedl.chip = SEDL_CHIP_TEST;
-						}
-						goto ready;
+						return 1;
 					} else {
-						printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
-						goto err;
+						if (sedl_card_win_probe(card->cs, card))
+							return 0;
+						return 1;
 					}
+				} else {
+					printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
+					goto err;
 				}
-				pdev++;
-				pnp_c=NULL;
-			} 
-			if (!pdev->card_vendor) {
-				printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
 			}
+			pdev++;
+			pnp_c=NULL;
+		} 
+		if (!pdev->card_vendor) {
+			printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
 		}
+	}
 #endif
 /* Probe for Sedlbauer speed pci */
 #if CONFIG_PCI
-		if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-				PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) {
-			if (pci_enable_device(dev_sedl))
-				goto err;
-			cs->irq = dev_sedl->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
-				goto err;
-			}
-			cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0);
-		} else {
-			printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
-			goto err;
-		}
-		cs->irq_flags |= SA_SHIRQ;
-		cs->hw.sedl.bus = SEDL_BUS_PCI;
+	dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+				   PCI_DEVICE_ID_TIGERJET_100, dev_sedl);
+	if (dev_sedl) {
 		sub_vendor_id = dev_sedl->subsystem_vendor;
 		sub_id = dev_sedl->subsystem_device;
 		printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n",
-			sub_vendor_id, sub_id);
-		printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n",
-			cs->hw.sedl.cfg_reg);
+		       sub_vendor_id, sub_id);
 		if (sub_id != PCI_SUB_ID_SEDLBAUER) {
 			printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id);
-			goto err;
+			return 0;
 		}
 		if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) {
-			cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
-			cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
+			if (sedl_fax_pyramid_probe(cs, dev_sedl))
+				return 0;
+			return 1;
 		} else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) {
-			cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
-			cs->subtyp = SEDL_SPEEDFAX_PCI;
+			if (sedl_fax_pci_probe(cs, dev_sedl))
+				return 0;
+			return 1;
 		} else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) {
-			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
-			cs->subtyp = SEDL_SPEED_PCI;
-		} else {
-			printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
-				sub_vendor_id);
-			goto err;
-		}
-		bytecnt = 256;
-		cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
-		cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
-		byteout(cs->hw.sedl.cfg_reg, 0xff);
-		byteout(cs->hw.sedl.cfg_reg, 0x00);
-		byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
-		byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
-		byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
-		current->state = TASK_UNINTERRUPTIBLE;
-		schedule_timeout((10*HZ)/1000);
-		byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
-#endif /* CONFIG_PCI */
-	}	
-ready:	
-	/* In case of the sedlbauer pcmcia card, this region is in use,
-	 * reserved for us by the card manager. So we do not check it
-	 * here, it would fail.
-	 */
-	if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA) {
-		if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn"))
-			goto err;
-	}
-
-	printk(KERN_INFO
-	       "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n",
-	       cs->hw.sedl.cfg_reg,
-	       cs->hw.sedl.cfg_reg + bytecnt,
-	       cs->irq);
-
-/*
- * testing ISA and PCMCIA Cards for IPAC, default is ISAC
- * do not test for PCI card, because ports are different
- * and PCI card uses only IPAC (for the moment)
- */	
-	if (cs->hw.sedl.bus != SEDL_BUS_PCI) {
-		cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
-		val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC,
-			      IPAC_ID);
-		printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val);
-	        if ((val == 1) || (val == 2)) {
-			/* IPAC */
-			cs->subtyp = SEDL_SPEED_WIN2_PC104;
-			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
-				cs->subtyp = SEDL_SPEED_STAR2;
-			}
-			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
-		} else {
-			/* ISAC_HSCX oder ISAC_ISAR */
-			if (cs->hw.sedl.chip == SEDL_CHIP_TEST) {
-				cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
-			}
-		}
-	}
-
-/*
- * hw.sedl.chip is now properly set
- */
-	printk(KERN_INFO "Sedlbauer: %s detected\n",
-		Sedlbauer_Types[cs->subtyp]);
-
-
-	if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
-		if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
-	                cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
-			cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
-			cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
-		} else {
-	                cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
-			cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
-			cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
-		}
-		cs->card_ops = &sedlbauer_ipac_ops;
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-		sedlbauer_reset(cs);
-	} else {
-		/* ISAC_HSCX oder ISAC_ISAR */
-		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
-			if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
-				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_PCI_ADR;
-				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_PCI_ISAC;
-				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_PCI_ISAR;
-			} else {
-				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_ISA_ADR;
-				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_ISA_ISAC;
-				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_ISA_ISAR;
-				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_ISA_ISAR_RESET_ON;
-				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_ISA_ISAR_RESET_OFF;
-			}
-			cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
-			cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
-			test_and_set_bit(HW_ISAR, &cs->HW_Flags);
-			cs->card_ops = &sedlbauer_isar_ops;
-			cs->auxcmd = &isar_auxcmd;
-			isac_setup(cs, &isac_ops);
-			if (isar_setup(cs, &isar_ops))
-				goto err;
-		} else {
-			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
-				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
-				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
-				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
-				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
-				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
-			} else {
-				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
-				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
-				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
-				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
-				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
-			}
-			cs->card_ops = &sedlbauer_ops;
-			if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-				goto err;
-
-			sedlbauer_reset(cs);
+			if (sedl_pci_probe(cs, dev_sedl))
+				return 0;
+			return 1;
 		}
+		printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
+		       sub_vendor_id);
+		return 0;
 	}
-	return 1;
- err:
-	hisax_release_resources(cs);
+#endif /* CONFIG_PCI */
 	return 0;
 }
diff -Nru a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
--- a/drivers/isdn/hisax/sportster.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/sportster.c	Thu Mar  6 22:52:05 2003
@@ -189,42 +189,29 @@
 	}
 	return 0;
 }
-  
-int __init
-setup_sportster(struct IsdnCard *card)
-{
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, sportster_revision);
-	printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", HiSax_getrev(tmp));
 
-	cs->hw.spt.cfg_reg = card->para[1];
+static int __init
+sportster_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
 	cs->irq = card->para[0];
+	cs->hw.spt.cfg_reg = card->para[1];
 	if (!get_io_range(cs))
-		return (0);
+		return -EBUSY;
 	cs->hw.spt.isac = cs->hw.spt.cfg_reg + SPORTSTER_ISAC;
 	cs->hw.spt.hscx[0] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXA;
 	cs->hw.spt.hscx[1] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXB;
 	
 	switch(cs->irq) {
-		case 5:	cs->hw.spt.res_irq = 1;
-			break;
-		case 7:	cs->hw.spt.res_irq = 2;
-			break;
-		case 10:cs->hw.spt.res_irq = 3;
-			break;
-		case 11:cs->hw.spt.res_irq = 4;
-			break;
-		case 12:cs->hw.spt.res_irq = 5;
-			break;
-		case 14:cs->hw.spt.res_irq = 6;
-			break;
-		case 15:cs->hw.spt.res_irq = 7;
-			break;
-		default:sportster_release(cs);
-			printk(KERN_WARNING "Sportster: wrong IRQ\n");
-			return(0);
+	case 5:	cs->hw.spt.res_irq = 1;	break;
+	case 7:	cs->hw.spt.res_irq = 2;	break;
+	case 10:cs->hw.spt.res_irq = 3;	break;
+	case 11:cs->hw.spt.res_irq = 4;	break;
+	case 12:cs->hw.spt.res_irq = 5;	break;
+	case 14:cs->hw.spt.res_irq = 6;	break;
+	case 15:cs->hw.spt.res_irq = 7;	break;
+	default:
+		printk(KERN_WARNING "Sportster: wrong IRQ\n");
+		goto err;
 	}
 	sportster_reset(cs);
 	printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n",
@@ -234,8 +221,22 @@
 	cs->card_ops = &sportster_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
-	return 1;
- err:
-	hisax_release_resources(cs);
 	return 0;
+ err:
+	sportster_release(cs);
+	return -EBUSY;
+}
+
+int __init
+setup_sportster(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, sportster_revision);
+	printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n",
+	       HiSax_getrev(tmp));
+
+	if (sportster_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
--- a/drivers/isdn/hisax/teleint.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/teleint.c	Thu Mar  6 22:52:05 2003
@@ -256,15 +256,9 @@
 	.irq_func = teleint_interrupt,
 };
 
-int __init
-setup_TeleInt(struct IsdnCard *card)
+static int __init
+teleint_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, TeleInt_revision);
-	printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp));
-
 	cs->hw.hfc.addr = card->para[1] & 0x3fe;
 	cs->irq = card->para[0];
 	cs->hw.hfc.cirm = HFC_CIRM;
@@ -284,42 +278,54 @@
 	byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff);
 	byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54);
 	switch (cs->irq) {
-		case 3:
-			cs->hw.hfc.cirm |= HFC_INTA;
-			break;
-		case 4:
-			cs->hw.hfc.cirm |= HFC_INTB;
-			break;
-		case 5:
-			cs->hw.hfc.cirm |= HFC_INTC;
-			break;
-		case 7:
-			cs->hw.hfc.cirm |= HFC_INTD;
-			break;
-		case 10:
-			cs->hw.hfc.cirm |= HFC_INTE;
-			break;
-		case 11:
-			cs->hw.hfc.cirm |= HFC_INTF;
-			break;
-		default:
-			printk(KERN_WARNING "TeleInt: wrong IRQ\n");
-			goto err;
+	case 3:
+		cs->hw.hfc.cirm |= HFC_INTA;
+		break;
+	case 4:
+		cs->hw.hfc.cirm |= HFC_INTB;
+		break;
+	case 5:
+		cs->hw.hfc.cirm |= HFC_INTC;
+		break;
+	case 7:
+		cs->hw.hfc.cirm |= HFC_INTD;
+		break;
+	case 10:
+		cs->hw.hfc.cirm |= HFC_INTE;
+		break;
+	case 11:
+		cs->hw.hfc.cirm |= HFC_INTF;
+		break;
+	default:
+		printk(KERN_WARNING "TeleInt: wrong IRQ\n");
+		goto err;
 	}
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt);
 
-	printk(KERN_INFO
-	       "TeleInt: defined at 0x%x IRQ %d\n",
-	       cs->hw.hfc.addr,
-	       cs->irq);
+	printk(KERN_INFO "TeleInt: defined at 0x%x IRQ %d\n",
+	       cs->hw.hfc.addr, cs->irq);
 
 	cs->card_ops = &teleint_ops;
 	teleint_reset(cs);
 	isac_setup(cs, &isac_ops);
 	hfc_setup(cs, &hfc_ops);
-	return 1;
- err:
-	teleint_release(cs);
 	return 0;
+
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+int __init
+setup_TeleInt(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, TeleInt_revision);
+	printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp));
+
+	if (teleint_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c
--- a/drivers/isdn/hisax/teles0.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/teles0.c	Thu Mar  6 22:52:05 2003
@@ -165,72 +165,95 @@
 	.irq_func = hscxisac_irq,
 };
 
-int __init
-setup_teles0(struct IsdnCard *card)
+static int __init
+teles0_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	u8 val;
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, teles0_revision);
-	printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ == ISDN_CTYPE_16_0)
-		cs->hw.teles0.cfg_reg = card->para[2];
-	else			/* 8.0 */
-		cs->hw.teles0.cfg_reg = 0;
-
-	if (card->para[1] < 0x10000) {
-		card->para[1] <<= 4;
-		printk(KERN_INFO
-		   "Teles0: membase configured DOSish, assuming 0x%lx\n",
-		       (unsigned long) card->para[1]);
-	}
 	cs->irq = card->para[0];
-	if (cs->hw.teles0.cfg_reg) {
-		if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg"))
-			goto err;
-
-		if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) {
-			printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
-			       cs->hw.teles0.cfg_reg + 0, val);
-			goto err;
-		}
-		if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) {
-			printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
-			       cs->hw.teles0.cfg_reg + 1, val);
-			goto err;
-		}
-		val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB
-							 * 0x1f=with AB
-							 * 0x1c 16.3 ???
-							 */
-		if (val != 0x1e && val != 0x1f) {
-			printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
-			       cs->hw.teles0.cfg_reg + 2, val);
-			goto err;
-		}
-	}
 	/* 16.0 and 8.0 designed for IOM1 */
 	test_and_set_bit(HW_IOM1, &cs->HW_Flags);
 	cs->hw.teles0.phymem = card->para[1];
-	cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem, TELES_IOMEM_SIZE, "teles iomem");
+	cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem,
+					     TELES_IOMEM_SIZE, "teles iomem");
 	if (!cs->hw.teles0.membase)
-		goto err;
+		return -EBUSY;
 
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d mem:0x%p cfg:0x%X\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.teles0.membase, cs->hw.teles0.cfg_reg);
 	if (teles0_reset(cs)) {
 		printk(KERN_WARNING "Teles0: wrong IRQ\n");
-		goto err;
+		return -EBUSY;
 	}
 	cs->card_ops = &teles0_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-  		goto err;
-	return 1;
+		return -EBUSY;
 
+	return 0;
+}
+
+static int __init
+teles16_0_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	u8 val;
+
+	cs->hw.teles0.cfg_reg = card->para[2];
+	if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg"))
+		goto err;
+		
+	if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) {
+		printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
+		       cs->hw.teles0.cfg_reg + 0, val);
+		goto err;
+	}
+	if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) {
+		printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
+		       cs->hw.teles0.cfg_reg + 1, val);
+		goto err;
+	}
+	val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB
+						 * 0x1f=with AB
+						 * 0x1c 16.3 ???
+						 */
+	if (val != 0x1e && val != 0x1f) {
+		printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
+		       cs->hw.teles0.cfg_reg + 2, val);
+		goto err;
+	}
+	if (teles0_probe(cs, card) < 0)
+		goto err;
+
+	return 0;
  err:
 	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+teles8_0_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->hw.teles0.cfg_reg = 0;
+
+	if (teles0_probe(cs, card) < 0)
+		goto err;
+
 	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+int __init
+setup_teles0(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, teles0_revision);
+	printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n",
+	       HiSax_getrev(tmp));
+
+	if (card->cs->typ == ISDN_CTYPE_16_0) {
+		if (teles16_0_probe(card->cs, card) < 0)
+			return 0;
+	} else {
+		if (teles8_0_probe(card->cs, card) < 0)
+			return 0;
+	}
+	return 1;
 }
diff -Nru a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c
--- a/drivers/isdn/hisax/teles3.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/isdn/hisax/teles3.c	Thu Mar  6 22:52:05 2003
@@ -176,6 +176,152 @@
 	.irq_func = hscxisac_irq,
 };
 
+static int
+teles_hw_init(struct IsdnCardState *cs)
+{
+	
+	printk(KERN_INFO "HiSax: %s config irq:%d isac:0x%X  cfg:0x%X\n",
+	       CardType[cs->typ], cs->irq,
+	       cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg);
+	printk(KERN_INFO "HiSax: hscx A:0x%X  hscx B:0x%X\n",
+	       cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32);
+
+	if (teles3_reset(cs)) {
+		printk(KERN_WARNING "Teles3: wrong IRQ\n");
+		return -EBUSY;
+	}
+	cs->card_ops = &teles3_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		return -EBUSY;
+	return 0;
+}
+
+static void __init
+teles_setup_io(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->irq = card->para[0];
+	cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
+	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
+	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
+}
+
+static int __init
+telespcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->hw.teles3.cfg_reg = 0;
+	cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
+	cs->hw.teles3.hscx[1] = card->para[1];
+	cs->hw.teles3.isac = card->para[1] + 0x20;
+	teles_setup_io(cs, card);
+	if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, 
+			"HiSax Teles PCMCIA"))
+		goto err;
+	if (teles_hw_init(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+teles_request_io(struct IsdnCardState *cs)
+{
+	if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac"))
+		return -EBUSY;
+	if (!request_io(&cs->rs, cs->hw.teles3.hscx[0]+32, 32, "HiSax hscx A"))
+		return -EBUSY;
+	if (!request_io(&cs->rs, cs->hw.teles3.hscx[1]+32, 32, "HiSax hscx B"))
+		return -EBUSY;
+	return 0;
+}
+
+static int __init
+teles16_3_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	u8 val;
+
+	cs->hw.teles3.cfg_reg = card->para[1];
+	switch (cs->hw.teles3.cfg_reg) {
+	case 0x180:
+	case 0x280:
+	case 0x380:
+		cs->hw.teles3.cfg_reg |= 0xc00;
+		break;
+	}
+	cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420;
+	cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
+	cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
+	teles_setup_io(cs, card);
+	if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg"))
+		goto err;
+	if (teles_request_io(cs) < 0)
+		goto err;
+	if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) {
+		printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
+		       cs->hw.teles3.cfg_reg + 0, val);
+		goto err;
+	}
+	if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) {
+		printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
+		       cs->hw.teles3.cfg_reg + 1, val);
+		goto err;
+	}
+	/* 0x1e without AB, 0x1f with AB,  0x1c 16.3 ???, 
+	 * 0x39 16.3 1.1,   0x38 16.3 1.3, 0x46 16.3 with AB + Video */
+	val = bytein(cs->hw.teles3.cfg_reg + 2);
+	if (val != 0x46 && val != 0x39 && val != 0x38 && 
+	    val != 0x1c && val != 0x1e && val != 0x1f) {
+		printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
+		       cs->hw.teles3.cfg_reg + 2, val);
+		goto err;
+	}
+	if (teles_hw_init(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+compaq_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->hw.teles3.cfg_reg = card->para[3];
+	cs->hw.teles3.isac = card->para[2] - 32;
+	cs->hw.teles3.hscx[0] = card->para[1] - 32;
+	cs->hw.teles3.hscx[1] = card->para[1];
+	teles_setup_io(cs, card);
+	if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg"))
+		goto err;
+	if (teles_request_io(cs) < 0)
+		goto err;
+	if (teles_hw_init(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+telespnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->hw.teles3.cfg_reg = 0;
+	cs->hw.teles3.isac = card->para[1] - 32;
+	cs->hw.teles3.hscx[0] = card->para[2] - 32;
+	cs->hw.teles3.hscx[1] = card->para[2];
+	teles_setup_io(cs, card);
+	if (teles_request_io(cs) < 0)
+		goto err;
+	if (teles_hw_init(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id teles_ids[] __initdata = {
 	{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
@@ -197,16 +343,10 @@
 int __devinit
 setup_teles3(struct IsdnCard *card)
 {
-	u8 val;
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, teles3_revision);
 	printk(KERN_INFO "HiSax: Teles IO driver Rev. %s\n", HiSax_getrev(tmp));
-	if ((cs->typ != ISDN_CTYPE_16_3) && (cs->typ != ISDN_CTYPE_PNP)
-	    && (cs->typ != ISDN_CTYPE_TELESPCMCIA) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA))
-		return (0);
-
 #ifdef __ISAPNP__
 	if (!card->para[1] && isapnp_present()) {
 		struct pnp_card *pnp_card;
@@ -258,100 +398,18 @@
 		}
 	}
 #endif
-	if (cs->typ == ISDN_CTYPE_16_3) {
-		cs->hw.teles3.cfg_reg = card->para[1];
-		switch (cs->hw.teles3.cfg_reg) {
-			case 0x180:
-			case 0x280:
-			case 0x380:
-				cs->hw.teles3.cfg_reg |= 0xc00;
-				break;
-		}
-		cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420;
-		cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
-		cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
-	} else if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
-		cs->hw.teles3.cfg_reg = 0;
-		cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
-		cs->hw.teles3.hscx[1] = card->para[1];
-		cs->hw.teles3.isac = card->para[1] + 0x20;
-	} else if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
-		cs->hw.teles3.cfg_reg = card->para[3];
-		cs->hw.teles3.isac = card->para[2] - 32;
-		cs->hw.teles3.hscx[0] = card->para[1] - 32;
-		cs->hw.teles3.hscx[1] = card->para[1];
+	if (card->cs->typ == ISDN_CTYPE_16_3) {
+		if (teles16_3_probe(card->cs, card) < 0)
+			return 0;
+	} else if (card->cs->typ == ISDN_CTYPE_TELESPCMCIA) {
+		if (telespcmcia_probe(card->cs, card) < 0)
+			return 0;
+	} else if (card->cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
+		if (compaq_probe(card->cs, card) < 0)
+			return 0;
 	} else {	/* PNP */
-		cs->hw.teles3.cfg_reg = 0;
-		cs->hw.teles3.isac = card->para[1] - 32;
-		cs->hw.teles3.hscx[0] = card->para[2] - 32;
-		cs->hw.teles3.hscx[1] = card->para[2];
-	}
-	cs->irq = card->para[0];
-	cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
-	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
-	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
-	if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
-		if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA"))
-			goto err;
-	} else {
-		if (cs->hw.teles3.cfg_reg) {
-			if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
-				if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg"))
-					goto err;
-			} else {
-				if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg"))
-					goto err;
-			}
-		}
-		if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac"))
-			goto err;
-		if (!request_io(&cs->rs, cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A"))
-			goto err;
-		if (!request_io(&cs->rs, cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B"))
-			goto err;
-	}
-	if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) {
-		if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) {
-			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
-			       cs->hw.teles3.cfg_reg + 0, val);
-			goto err;
-		}
-		if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) {
-			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
-			       cs->hw.teles3.cfg_reg + 1, val);
-			goto err;
-		}
-		val = bytein(cs->hw.teles3.cfg_reg + 2);/* 0x1e=without AB
-							 * 0x1f=with AB
-							 * 0x1c 16.3 ???
-							 * 0x39 16.3 1.1
-							 * 0x38 16.3 1.3
-							 * 0x46 16.3 with AB + Video (Teles-Vision)
-							 */
-		if (val != 0x46 && val != 0x39 && val != 0x38 && val != 0x1c && val != 0x1e && val != 0x1f) {
-			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
-			       cs->hw.teles3.cfg_reg + 2, val);
-			goto err;
-		}
-	}
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d isac:0x%X  cfg:0x%X\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg);
-	printk(KERN_INFO
-	       "HiSax: hscx A:0x%X  hscx B:0x%X\n",
-	       cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32);
-
-	if (teles3_reset(cs)) {
-		printk(KERN_WARNING "Teles3: wrong IRQ\n");
-		goto err;
+		if (telespnp_probe(card->cs, card) < 0)
+			return 0;
 	}
-	cs->card_ops = &teles3_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
 	return 1;
- err:
-	hisax_release_resources(cs);
-	return 0;
-
 }
diff -Nru a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
--- a/drivers/isdn/hisax/telespci.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/telespci.c	Thu Mar  6 22:52:05 2003
@@ -231,36 +231,23 @@
 	.irq_func = telespci_interrupt,
 };
 
-static struct pci_dev *dev_tel __initdata = NULL;
-
-int __init
-setup_telespci(struct IsdnCard *card)
+static int __init
+telespci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
+	int rc;
 
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-	strcpy(tmp, telespci_revision);
-	printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
-	if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) {
-		if (pci_enable_device(dev_tel))
-			return(0);
-		cs->irq = dev_tel->irq;
-		if (!cs->irq) {
-			printk(KERN_WARNING "Teles: No IRQ for PCI card found\n");
-			return(0);
-		}
-		cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(dev_tel, 0), 4096, "telespci");
-		if (!cs->hw.teles0.membase)
-			goto err;
-		printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n",
-			pci_resource_start(dev_tel, 0), dev_tel->irq);
-	} else {
-		printk(KERN_WARNING "TelesPCI: No PCI card found\n");
-		return(0);
-	}
+	printk(KERN_INFO "TelesPCI: defined at %#lx IRQ %d\n",
+	       pci_resource_start(pdev, 0), pdev->irq);
+	
+	rc = -EBUSY;
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "telespci");
+	if (!cs->hw.teles0.membase)
+		goto err;
 
 	/* Initialize Zoran PCI controller */
 	writel(0x00000000, cs->hw.teles0.membase + 0x28);
@@ -270,17 +257,36 @@
 	writel(0x70000000, cs->hw.teles0.membase + 0x3C);
 	writel(0x61000000, cs->hw.teles0.membase + 0x40);
 	/* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d mem:%p\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.teles0.membase);
 
-	cs->irq_flags |= SA_SHIRQ;
 	cs->card_ops = &telespci_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
+	return rc;
+}
+
+static struct pci_dev *dev_tel __initdata = NULL;
+
+int __init
+setup_telespci(struct IsdnCard *card)
+{
+	char tmp[64];
+
+#ifdef __BIG_ENDIAN
+#error "not running on big endian machines now"
+#endif
+	strcpy(tmp, telespci_revision);
+	printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n",
+	       HiSax_getrev(tmp));
+	dev_tel = pci_find_device(PCI_VENDOR_ID_ZORAN, 
+				  PCI_DEVICE_ID_ZORAN_36120, dev_tel);
+	if (dev_tel) {
+		if (telespci_probe(card->cs, dev_tel) < 0)
+			return 0;
+		return 1;
+	}
+	printk(KERN_WARNING "TelesPCI: No PCI card found\n");
 	return 0;
 }
diff -Nru a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
--- a/drivers/isdn/hisax/w6692.c	Sun Jan 12 16:12:37 2003
+++ b/drivers/isdn/hisax/w6692.c	Thu Mar  6 22:52:05 2003
@@ -669,11 +669,11 @@
 static struct pci_dev *dev_w6692 __initdata = NULL;
 
 static int
-w6692_setup(struct IsdnCardState *cs, struct dc_hw_ops *dc_ops,
-	    struct bc_hw_ops *bc_ops)
+w6692_hw_init(struct IsdnCardState *cs)
 {
-	cs->dc_hw_ops = dc_ops;
-	cs->bc_hw_ops = bc_ops;
+	cs->card_ops = &w6692_ops;
+	cs->dc_hw_ops = &w6692_dc_hw_ops, 
+	cs->bc_hw_ops = &w6692_bc_hw_ops;
 	dc_l1_init(cs, &w6692_dc_l1_ops);
 	cs->bc_l1_ops = &w6692_bc_l1_ops;
 	W6692Version(cs, "W6692:");
@@ -685,14 +685,45 @@
 	return 0;
 }
 
+static int __init
+w6692_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	int rc;
+
+	printk(KERN_INFO "W6692: %s %s at %#lx IRQ %d\n",
+	       id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
+	       pci_resource_start(pdev, 1), pdev->irq);
+	
+	rc = -EBUSY;
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	/* USR ISDN PCI card TA need some special handling */
+	if (cs->subtyp == W6692_WINBOND) {
+		if (pdev->subsystem_vendor == W6692_SV_USR  &&
+		    pdev->subsystem_device == W6692_SD_USR) {
+			cs->subtyp = W6692_USR;
+		}
+	}
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.w6692.iobase = pci_resource_start(pdev, 1);
+	
+	if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100,
+			id_list[cs->subtyp].card_name))
+		goto err;
+
+	w6692_hw_init(cs);
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
 int __init 
 setup_w6692(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-	u8 found = 0;
-	u8 pci_irq = 0;
-	u_int pci_ioaddr = 0;
 
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
@@ -704,54 +735,13 @@
 					    id_list[id_idx].device_id,
 					    dev_w6692);
 		if (dev_w6692) {
-			if (pci_enable_device(dev_w6692))
-				continue;
-			cs->subtyp = id_idx;
-			break;
+			card->cs->subtyp = id_idx;
+			if (w6692_probe(card->cs, dev_w6692) < 0)
+				return 0;
+			return 1;
 		}
 		id_idx++;
 	}
-	if (dev_w6692) {
-		found = 1;
-		pci_irq = dev_w6692->irq;
-		/* I think address 0 is allways the configuration area */
-		/* and address 1 is the real IO space KKe 03.09.99 */
-		pci_ioaddr = pci_resource_start(dev_w6692, 1);
-		/* USR ISDN PCI card TA need some special handling */
-		if (cs->subtyp == W6692_WINBOND) {
-			if ((W6692_SV_USR == dev_w6692->subsystem_vendor) &&
-			    (W6692_SD_USR == dev_w6692->subsystem_device)) {
-				cs->subtyp = W6692_USR;
-			}
-		}
-	}
-	if (!found) {
-		printk(KERN_WARNING "W6692: No PCI card found\n");
-		return (0);
-	}
-	cs->irq = pci_irq;
-	if (!cs->irq) {
-		printk(KERN_WARNING "W6692: No IRQ for PCI card found\n");
-		return (0);
-	}
-	if (!pci_ioaddr) {
-		printk(KERN_WARNING "W6692: NO I/O Base Address found\n");
-		return (0);
-	}
-	cs->hw.w6692.iobase = pci_ioaddr;
-	printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n",
-	       id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
-	       pci_ioaddr, pci_irq);
-	if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100, id_list[cs->subtyp].card_name))
-		return 0;
-	
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d I/O:%x\n",
-	       id_list[cs->subtyp].card_name, cs->irq,
-	       cs->hw.w6692.iobase);
-
-	cs->card_ops = &w6692_ops;
-	w6692_setup(cs, &w6692_dc_hw_ops, &w6692_bc_hw_ops);
-	cs->irq_flags |= SA_SHIRQ;
-	return (1);
+	printk(KERN_WARNING "W6692: No PCI card found\n");
+	return 0;
 }
diff -Nru a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
--- a/drivers/isdn/i4l/Kconfig	Tue Nov 12 12:48:13 2002
+++ b/drivers/isdn/i4l/Kconfig	Sat Feb 22 09:17:33 2003
@@ -85,7 +85,7 @@
 
 config ISDN_X25
 	bool "X.25 PLP on top of ISDN"
-	depends on X25
+	depends on X25 && BROKEN
 	help
 	  This feature provides the X.25 protocol over ISDN connections.
 	  See <file:Documentation/isdn/README.x25> for more information
diff -Nru a/drivers/isdn/i4l/isdn_net_lib.c b/drivers/isdn/i4l/isdn_net_lib.c
--- a/drivers/isdn/i4l/isdn_net_lib.c	Tue Nov 12 13:33:35 2002
+++ b/drivers/isdn/i4l/isdn_net_lib.c	Sat Feb 22 09:17:33 2003
@@ -58,6 +58,7 @@
 #include "isdn_net.h"
 #include "isdn_ppp.h"
 #include "isdn_ciscohdlck.h"
+#include "isdn_concap.h"
 
 #define ISDN_NET_TX_TIMEOUT (20*HZ) 
 
diff -Nru a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
--- a/drivers/isdn/i4l/isdn_ppp.c	Tue Nov 12 13:34:48 2002
+++ b/drivers/isdn/i4l/isdn_ppp.c	Sat Mar  1 13:01:59 2003
@@ -867,7 +867,7 @@
 		skb_pull(skb, 1);
 	} else {
 		if (skb->len < 2)
-			return -1;
+			return -EINVAL;
 		get_u16(skb->data, proto);
 		skb_pull(skb, 2);
 	}
@@ -1037,7 +1037,7 @@
                 isdn_ppp_frame_log("xmit1", skb->data, skb->len, 32, ipppd->unit, -1);
 
 	ippp_push_proto(ind_ppp, skb, proto);
-	ippp_mp_xmit(idev, skb, proto);
+	ippp_mp_xmit(idev, skb);
 	return 0;
 
  drop:
diff -Nru a/drivers/isdn/i4l/isdn_ppp_mp.c b/drivers/isdn/i4l/isdn_ppp_mp.c
--- a/drivers/isdn/i4l/isdn_ppp_mp.c	Tue Oct 29 18:41:43 2002
+++ b/drivers/isdn/i4l/isdn_ppp_mp.c	Sat Feb 22 10:03:46 2003
@@ -91,12 +91,13 @@
 }
 
 void
-ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
+ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb)
 {
 	struct ind_ppp *ind_ppp = idev->ind_priv;
 	struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
 	unsigned char *p;
-	long txseq;
+	u32 txseq;
+	u16 proto;
 
 	if (!(inl_ppp->mp_cfg & SC_MP_PROT)) {
 		return ippp_xmit(idev, skb);
diff -Nru a/drivers/isdn/i4l/isdn_ppp_mp.h b/drivers/isdn/i4l/isdn_ppp_mp.h
--- a/drivers/isdn/i4l/isdn_ppp_mp.h	Tue Oct 29 18:28:25 2002
+++ b/drivers/isdn/i4l/isdn_ppp_mp.h	Sat Feb 22 10:03:46 2003
@@ -19,7 +19,7 @@
 int  ippp_mp_bind(isdn_net_dev *idev);
 void ippp_mp_disconnected(isdn_net_dev *idev);
 int  ippp_mp_bundle(isdn_net_dev *idev, int val);
-void ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto);
+void ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb);
 void ippp_mp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto);
 
 #else
@@ -42,9 +42,9 @@
 }
 
 static inline void
-ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
+ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb)
 {
-	ippp_xmit(idev, skb, proto);
+	ippp_xmit(idev, skb);
 }
 
 static inline void 
diff -Nru a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c
--- a/drivers/macintosh/macserial.c	Mon Nov 11 05:18:24 2002
+++ b/drivers/macintosh/macserial.c	Fri Feb 14 15:20:31 2003
@@ -3043,10 +3043,12 @@
 /*
  *	Register console.
  */
-void __init mac_scc_console_init(void)
+static void __init mac_scc_console_init(void)
 {
 	register_console(&sercons);
 }
+console_initcall(mac_scc_console_init);
+
 #endif /* ifdef CONFIG_SERIAL_CONSOLE */
 
 #ifdef CONFIG_KGDB
diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c
--- a/drivers/md/dm.c	Thu Jan  2 03:27:23 2003
+++ b/drivers/md/dm.c	Sat Mar  8 14:50:22 2003
@@ -79,9 +79,8 @@
 		return -ENOMEM;
 
 	_major = major;
-	r = register_blkdev(_major, _name, &dm_blk_dops);
+	r = register_blkdev(_major, _name);
 	if (r < 0) {
-		DMERR("register_blkdev failed");
 		kmem_cache_destroy(_io_cache);
 		return r;
 	}
diff -Nru a/drivers/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c	Tue Feb 25 02:44:05 2003
+++ b/drivers/md/md.c	Sat Mar  8 14:50:30 2003
@@ -2803,7 +2803,9 @@
 	idle = 1;
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
-		curr_events = disk->read_sectors + disk->write_sectors - disk->sync_io;
+		curr_events = disk_stat_read(disk, read_sectors) + 
+				disk_stat_read(disk, write_sectors) - 
+				disk->sync_io;
 		if ((curr_events - rdev->last_events) > 32) {
 			rdev->last_events = curr_events;
 			idle = 0;
@@ -3214,11 +3216,10 @@
 			MD_MAJOR_VERSION, MD_MINOR_VERSION,
 			MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS);
 
-	if (register_blkdev (MAJOR_NR, "md", &md_fops)) {
-		printk(KERN_ALERT "md: Unable to get major %d for md\n", MAJOR_NR);
-		return (-1);
-	}
-	devfs_mk_dir (NULL, "md", NULL);
+	if (register_blkdev(MAJOR_NR, "md"))
+		return -1;
+
+	devfs_mk_dir(NULL, "md", NULL);
 	blk_register_region(MKDEV(MAJOR_NR, 0), MAX_MD_DEVS, THIS_MODULE,
 				md_probe, NULL, NULL);
 	for (minor=0; minor < MAX_MD_DEVS; ++minor) {
diff -Nru a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
--- a/drivers/media/video/bw-qcam.c	Fri Nov 29 08:30:40 2002
+++ b/drivers/media/video/bw-qcam.c	Sun Feb 16 16:16:53 2003
@@ -83,11 +83,9 @@
 static unsigned int yieldlines=4;  /* Yield after this many during capture */
 static int video_nr = -1;
 
-#if LINUX_VERSION_CODE >= 0x020117
 MODULE_PARM(maxpoll,"i");
 MODULE_PARM(yieldlines,"i");   
 MODULE_PARM(video_nr,"i");
-#endif
 
 static inline int read_lpstatus(struct qcam_device *q)
 {
diff -Nru a/drivers/media/video/planb.c b/drivers/media/video/planb.c
--- a/drivers/media/video/planb.c	Fri Nov 29 08:30:40 2002
+++ b/drivers/media/video/planb.c	Sun Feb 16 16:16:53 2003
@@ -181,12 +181,7 @@
 
 	/* Let's wait 30msec for this one */
 	current->state = TASK_INTERRUPTIBLE;
-#if LINUX_VERSION_CODE >= 0x02017F
 	schedule_timeout(30 * HZ / 1000);
-#else
-	current->timeout = jiffies + 30 * HZ / 1000;	/* 30 ms */;
-	schedule();
-#endif
 
 	return (unsigned char)in_8 (&planb_regs->saa_status);
 }
diff -Nru a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
--- a/drivers/media/video/video-buf.c	Wed Jan  8 01:59:58 2003
+++ b/drivers/media/video/video-buf.c	Thu Mar  6 07:10:08 2003
@@ -83,6 +83,8 @@
 		return NULL;
 	memset(sglist, 0, sizeof(*sglist) * nr_pages);
 
+	if (NULL == pages[0])
+		goto nopage;
 	if (PageHighMem(pages[0]))
 		/* DMA to highmem pages might not work */
 		goto highmem;
@@ -118,7 +120,7 @@
 	for (i = 0; i < nr_pages; i++)
 		if (TryLockPage(pages[i]))
 			goto err;
-	dprintk(2,"lock ok\n");
+	dprintk(2,"lock ok [%d pages]\n",nr_pages);
 	return 0;
 
  err:
@@ -136,7 +138,7 @@
 	dprintk(2,"unlock start ...\n");
 	for (i = 0; i < nr_pages; i++)
 		unlock_page(pages[i]);
-	dprintk(2,"unlock ok\n");
+	dprintk(2,"unlock ok [%d pages]\n",nr_pages);
 	return 0;
 }
 
@@ -270,7 +272,7 @@
 
 /* --------------------------------------------------------------------- */
 
-void* videobuf_alloc(int size)
+void* videobuf_alloc(unsigned int size)
 {
 	struct videobuf_buffer *vb;
 
@@ -340,7 +342,7 @@
 		    spinlock_t *irqlock,
 		    enum v4l2_buf_type type,
 		    enum v4l2_field field,
-		    int msize)
+		    unsigned int msize)
 {
 	memset(q,0,sizeof(*q));
 
@@ -417,11 +419,11 @@
 
 	if (V4L2_FIELD_ALTERNATE == field) {
 		if (V4L2_FIELD_TOP == q->last) {
-			field   = V4L2_FIELD_TOP;
-			q->last = V4L2_FIELD_TOP;
-		} else {
 			field   = V4L2_FIELD_BOTTOM;
 			q->last = V4L2_FIELD_BOTTOM;
+		} else {
+			field   = V4L2_FIELD_TOP;
+			q->last = V4L2_FIELD_TOP;
 		}
 	}
 	return field;
@@ -463,7 +465,8 @@
 videobuf_reqbufs(struct file *file, struct videobuf_queue *q,
 		 struct v4l2_requestbuffers *req)
 {
-	int size,count,retval;
+	unsigned int size,count;
+	int retval;
 
 	if (req->type != q->type)
 		return -EINVAL;
@@ -477,6 +480,8 @@
 	size = 0;
 	q->ops->buf_setup(file,&count,&size);
 	size = PAGE_ALIGN(size);
+	dprintk(1,"reqbufs: bufs=%d, size=0x%x [%d pages total]\n",
+		count, size, (count*size)>>PAGE_SHIFT);
 
 	retval = videobuf_mmap_setup(file,q,count,size);
 	if (retval < 0)
@@ -660,7 +665,10 @@
         retval = videobuf_waiton(q->read_buf,0,0);
         if (0 == retval) {
 		videobuf_dma_pci_sync(q->pci,&q->read_buf->dma);
-                retval = q->read_buf->size;
+		if (STATE_ERROR == q->read_buf->state)
+			retval = -EIO;
+		else
+			retval = q->read_buf->size;
 	}
 
  done:
@@ -676,7 +684,8 @@
 {
 	enum v4l2_field field;
 	unsigned long flags;
-	int retval, bytes, size, nbufs;
+	unsigned size, nbufs, bytes;
+	int retval;
 
 	down(&q->lock);
 
@@ -686,7 +695,7 @@
 	    count >= size        &&
 	    !(file->f_flags & O_NONBLOCK)) {
 		retval = videobuf_read_zerocopy(file,q,data,count,ppos);
-		if (retval >= 0)
+		if (retval >= 0  ||  retval == -EIO)
 			/* ok, all done */
 			goto done;
 		/* fallback to kernel bounce buffer on failures */
@@ -714,6 +723,15 @@
 		goto done;
 	videobuf_dma_pci_sync(q->pci,&q->read_buf->dma);
 
+	if (STATE_ERROR == q->read_buf->state) {
+		/* catch I/O errors */
+		q->ops->buf_release(file,q->read_buf);
+		kfree(q->read_buf);
+		q->read_buf = NULL;
+		retval = -EIO;
+		goto done;
+	}
+
 	/* copy to userspace */
 	bytes = count;
 	if (bytes > q->read_buf->size - q->read_off)
@@ -788,8 +806,8 @@
 			     char *data, size_t count, loff_t *ppos,
 			     int vbihack)
 {
-	unsigned int *fc;
-	int err, bytes, retval;
+	unsigned int *fc, bytes;
+	int err, retval;
 	unsigned long flags;
 	
 	down(&q->lock);
@@ -968,9 +986,10 @@
 };
 
 int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q,
-			int bcount, int bsize)
+			unsigned int bcount, unsigned int bsize)
 {
-	int i,err;
+	unsigned int i;
+	int err;
 
 	err = videobuf_mmap_free(file,q);
 	if (0 != err)
@@ -1008,7 +1027,8 @@
 			 struct videobuf_queue *q)
 {
 	struct videobuf_mapping *map;
-	int first,last,size,i,retval;
+	unsigned int first,last,size,i;
+	int retval;
 
 	down(&q->lock);
 	retval = -EINVAL;
@@ -1025,7 +1045,7 @@
 	for (first = 0; first < VIDEO_MAX_FRAME; first++) {
 		if (NULL == q->bufs[first])
 			continue;
-		if (q->bufs[first]->boff  == (vma->vm_pgoff << PAGE_SHIFT))
+		if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT))
 			break;
 	}
 	if (VIDEO_MAX_FRAME == first) {
diff -Nru a/drivers/media/video/video-buf.h b/drivers/media/video/video-buf.h
--- a/drivers/media/video/video-buf.h	Wed Jan  8 01:59:58 2003
+++ b/drivers/media/video/video-buf.h	Thu Mar  6 06:29:59 2003
@@ -110,7 +110,7 @@
 struct videobuf_queue;
 
 struct videobuf_mapping {
-	int count;
+	unsigned int count;
 	int highmem_ok;
 	unsigned long start;
 	unsigned long end;
@@ -128,19 +128,19 @@
 };
 
 struct videobuf_buffer {
-	int                     i;
+	unsigned int            i;
 
 	/* info about the buffer */
-	int                     width;
-	int                     height;
-	long                    size;
+	unsigned int            width;
+	unsigned int            height;
+	unsigned long           size;
 	enum v4l2_field         field;
 	enum videobuf_state     state;
 	struct videobuf_dmabuf  dma;
 	struct list_head        stream;  /* QBUF/DQBUF list */
 
 	/* for mmap'ed buffers */
-	off_t                   boff;    /* buffer offset (mmap) */
+	size_t                  boff;    /* buffer offset (mmap) */
 	size_t                  bsize;   /* buffer size */
 	unsigned long           baddr;   /* buffer addr (userland ptr!) */
 	struct videobuf_mapping *map;
@@ -148,12 +148,13 @@
 	/* touched by irq handler */
 	struct list_head        queue;
 	wait_queue_head_t       done;
-	int                     field_count;
+	unsigned int            field_count;
 	struct timeval          ts;
 };
 
 struct videobuf_queue_ops {
-	int (*buf_setup)(struct file *file, int *count, int *size);
+	int (*buf_setup)(struct file *file,
+			 unsigned int *count, unsigned int *size);
 	int (*buf_prepare)(struct file *file,struct videobuf_buffer *vb,
 			   enum v4l2_field field);
 	void (*buf_queue)(struct file *file,struct videobuf_buffer *vb);
@@ -166,23 +167,23 @@
 	struct pci_dev             *pci;
 
 	enum v4l2_buf_type         type;
-	int                        msize;
+	unsigned int               msize;
 	enum v4l2_field            field;
 	enum v4l2_field            last; /* for field=V4L2_FIELD_ALTERNATE */
 	struct videobuf_buffer     *bufs[VIDEO_MAX_FRAME];
 	struct videobuf_queue_ops  *ops;
 
 	/* capture via mmap() + ioctl(QBUF/DQBUF) */
-	int                        streaming;
+	unsigned int               streaming;
 	struct list_head           stream;
 
 	/* capture via read() */
-	int                        reading;
-	int                        read_off;
+	unsigned int               reading;
+	unsigned int               read_off;
 	struct videobuf_buffer     *read_buf;
 };
 
-void* videobuf_alloc(int size);
+void* videobuf_alloc(unsigned int size);
 int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr);
 int videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb);
 
@@ -190,7 +191,8 @@
 			 struct videobuf_queue_ops *ops,
 			 struct pci_dev *pci, spinlock_t *irqlock,
 			 enum v4l2_buf_type type,
-			 enum v4l2_field field, int msize);
+			 enum v4l2_field field,
+			 unsigned int msize);
 int  videobuf_queue_is_busy(struct videobuf_queue *q);
 void videobuf_queue_cancel(struct file *file, struct videobuf_queue *q);
 
@@ -218,7 +220,7 @@
 				  poll_table *wait);
 
 int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q,
-			int bcount, int bsize);
+			unsigned int bcount, unsigned int bsize);
 int videobuf_mmap_free(struct file *file, struct videobuf_queue *q);
 int videobuf_mmap_mapper(struct vm_area_struct *vma,
 			 struct videobuf_queue *q);
diff -Nru a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h
--- a/drivers/media/video/zoran.h	Tue Feb  5 11:10:31 2002
+++ b/drivers/media/video/zoran.h	Sun Feb 16 16:16:53 2003
@@ -32,10 +32,6 @@
 
 #include <linux/config.h>
 
-#if LINUX_VERSION_CODE < 0x20212
-typedef struct wait_queue *wait_queue_head_t;
-#endif
-
 /* The Buz only supports a maximum width of 720, but some V4L
    applications (e.g. xawtv are more happy with 768).
    If XAWTV_HACK is defined, we try to fake a device with bigger width */
diff -Nru a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c
--- a/drivers/media/video/zr36120.c	Thu Feb  6 07:33:47 2003
+++ b/drivers/media/video/zr36120.c	Sun Feb 16 16:16:53 2003
@@ -943,7 +943,6 @@
 	return -EINVAL;
 }
 
-#if LINUX_VERSION_CODE >= 0x020100
 static
 unsigned int zoran_poll(struct video_device *dev, struct file *file, poll_table *wait)
 {
@@ -964,7 +963,6 @@
 
 	return mask;
 }
-#endif
 
 /* append a new clipregion to the vector of video_clips */
 static
@@ -1745,7 +1743,6 @@
 	return count;
 }
 
-#if LINUX_VERSION_CODE >= 0x020100
 static
 unsigned int vbi_poll(struct video_device *dev, struct file *file, poll_table *wait)
 {
@@ -1766,7 +1763,6 @@
 
 	return mask;
 }
-#endif
 
 static
 int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
diff -Nru a/drivers/message/fusion/lsi/mpi_raid.h b/drivers/message/fusion/lsi/mpi_raid.h
--- a/drivers/message/fusion/lsi/mpi_raid.h	Fri Feb 21 06:26:38 2003
+++ b/drivers/message/fusion/lsi/mpi_raid.h	Thu Feb 20 08:33:15 2003
@@ -184,7 +184,7 @@
 
 
 /****************************************************************************/
-/* Mailbox reqeust structure */
+/* Mailbox request structure */
 /****************************************************************************/
 
 typedef struct _MSG_MAILBOX_REQUEST
diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
--- a/drivers/message/i2o/i2o_block.c	Tue Feb 25 11:05:27 2003
+++ b/drivers/message/i2o/i2o_block.c	Sat Mar  8 14:50:22 2003
@@ -1608,12 +1608,8 @@
 	/*
 	 *	Register the block device interfaces
 	 */
-
-	if (register_blkdev(MAJOR_NR, "i2o_block", &i2ob_fops)) {
-		printk(KERN_ERR "Unable to get major number %d for i2o_block\n",
-		       MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "i2o_block"))
 		return -EIO;
-	}
 
 	for (i = 0; i < MAX_I2OB; i++) {
 		struct gendisk *disk = alloc_disk(16);
diff -Nru a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
--- a/drivers/mtd/ftl.c	Wed Feb 26 05:35:35 2003
+++ b/drivers/mtd/ftl.c	Sat Mar  8 14:50:22 2003
@@ -1281,11 +1281,9 @@
 	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
 	DEBUG(0, "$Id: ftl.c,v 1.39 2001/10/02 15:05:11 dwmw2 Exp $\n");
 
-	if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) {
-		printk(KERN_NOTICE "ftl_cs: unable to grab major "
-		       "device number!\n");
+	if (register_blkdev(FTL_MAJOR, "ftl"))
 		return -EAGAIN;
-	}
+
 	blk_init_queue(&ftl_queue, &do_ftl_request, &lock);
 	register_mtd_user(&ftl_notifier);
 	return 0;
diff -Nru a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
--- a/drivers/mtd/mtdblock.c	Tue Feb 11 14:57:51 2003
+++ b/drivers/mtd/mtdblock.c	Sat Mar  8 14:50:22 2003
@@ -570,11 +570,10 @@
 int __init init_mtdblock(void)
 {
 	spin_lock_init(&mtdblks_lock);
-	if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) {
-		printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
-		       MTD_BLOCK_MAJOR);
+
+	if (register_blkdev(MAJOR_NR, DEVICE_NAME))
 		return -EAGAIN;
-	}
+
 #ifdef CONFIG_DEVFS_FS
 	devfs_mk_dir(NULL, DEVICE_NAME, NULL);
 #endif
diff -Nru a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c
--- a/drivers/mtd/mtdblock_ro.c	Mon Oct 28 11:57:56 2002
+++ b/drivers/mtd/mtdblock_ro.c	Sat Mar  8 14:50:22 2003
@@ -240,20 +240,13 @@
 
 int __init init_mtdblock(void)
 {
-	int err;
-
-	if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) {
-		printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
-		       MTD_BLOCK_MAJOR);
-		err = -EAGAIN;
-		goto out;
-	}
+	if (register_blkdev(MAJOR_NR, DEVICE_NAME))
+		return -EAGAIN;
 
 	blk_init_queue(&mtdro_queue, &mtdblock_request, &mtdro_lock);
 	register_mtd_user(&notifier);
-	err = 0;
- out:
-	return err;
+
+	return 0;
 }
 
 static void __exit cleanup_mtdblock(void)
diff -Nru a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
--- a/drivers/mtd/nftlcore.c	Wed Feb 26 05:35:01 2003
+++ b/drivers/mtd/nftlcore.c	Sat Mar  8 14:50:22 2003
@@ -928,10 +928,8 @@
 	printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.82 $, nftlmount.c %s\n", nftlmountrev);
 #endif
 
-	if (register_blkdev(MAJOR_NR, "nftl", &nftl_fops)) {
-		printk("unable to register NFTL block device on major %d\n", MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "nftl"))
 		return -EBUSY;
-	}
 
 	blk_register_region(MKDEV(MAJOR_NR, 0), 256,
 			THIS_MODULE, nftl_probe, NULL, NULL);
diff -Nru a/drivers/net/bonding.c b/drivers/net/bonding.c
--- a/drivers/net/bonding.c	Tue Feb 18 10:50:38 2003
+++ b/drivers/net/bonding.c	Sat Mar  8 14:50:38 2003
@@ -2574,6 +2574,13 @@
 		return 0;
 	}
 
+	if (bond->slave_cnt == 0) {
+		/* no slaves in the bond, frame not sent */
+		dev_kfree_skb(skb);
+		read_unlock_irqrestore(&bond->lock, flags);
+		return 0;
+	}
+	
 	slave_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % bond->slave_cnt;
 
 	while ( (slave_no > 0) && (slave != (slave_t *)bond) ) {
diff -Nru a/drivers/net/dgrs.c b/drivers/net/dgrs.c
--- a/drivers/net/dgrs.c	Tue Feb 25 11:05:27 2003
+++ b/drivers/net/dgrs.c	Tue Mar  4 22:44:07 2003
@@ -981,7 +981,7 @@
 {
 	DGRS_PRIV	*priv0 = (DGRS_PRIV *) dev0->priv;
 	int		is;
-	int		i;
+	unsigned long	i;
 
 	static int	iv2is[16] = {
 				0, 0, 0, ES4H_IS_INT3,
@@ -1140,7 +1140,7 @@
 dgrs_probe1(struct net_device *dev)
 {
 	DGRS_PRIV	*priv = (DGRS_PRIV *) dev->priv;
-	int		i;
+	unsigned long	i;
 	int		rc;
 
 	printk("%s: Digi RightSwitch io=%lx mem=%lx irq=%d plx=%lx dma=%lx\n",
diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c
--- a/drivers/net/eepro100.c	Mon Feb 24 10:34:28 2003
+++ b/drivers/net/eepro100.c	Sat Mar  8 18:51:49 2003
@@ -529,8 +529,6 @@
 static int eepro100_init_one(struct pci_dev *pdev,
 		const struct pci_device_id *ent);
 
-static void eepro100_remove_one (struct pci_dev *pdev);
-
 static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len);
 static int mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
@@ -843,6 +841,7 @@
 	sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE);
 	sp->lstats_dma = TX_RING_ELEM_DMA(sp, TX_RING_SIZE);
 	init_timer(&sp->timer); /* used in ioctl() */
+	spin_lock_init(&sp->lock);
 
 	sp->mii_if.full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
 	if (card_idx >= 0) {
@@ -994,7 +993,6 @@
 	sp->dirty_tx = 0;
 	sp->last_cmd = 0;
 	sp->tx_full = 0;
-	spin_lock_init(&sp->lock);
 	sp->in_interrupt = 0;
 
 	/* .. we can safely take handler calls during init. */
diff -Nru a/drivers/net/eth16i.c b/drivers/net/eth16i.c
--- a/drivers/net/eth16i.c	Tue Feb 25 02:08:43 2003
+++ b/drivers/net/eth16i.c	Thu Mar  6 09:23:56 2003
@@ -1404,7 +1404,6 @@
 static char* mediatype[MAX_ETH16I_CARDS];
 static int debug = -1;
 
-#if (LINUX_VERSION_CODE >= 0x20115) 
 MODULE_AUTHOR("Mika Kuoppala <miku@iki.fi>");
 MODULE_DESCRIPTION("ICL EtherTeam 16i/32 driver");
 MODULE_LICENSE("GPL");
@@ -1423,7 +1422,6 @@
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "eth16i debug level (0-6)");
-#endif
 
 int init_module(void)
 {
diff -Nru a/drivers/net/mac8390.c b/drivers/net/mac8390.c
--- a/drivers/net/mac8390.c	Sun Feb  9 17:29:54 2003
+++ b/drivers/net/mac8390.c	Sun Feb 16 16:17:32 2003
@@ -376,11 +376,9 @@
 }
 
 #ifdef MODULE
-#if LINUX_VERSION_CODE > 0x20118
 MODULE_AUTHOR("David Huggins-Daines <dhd@debian.org> and others");
 MODULE_DESCRIPTION("Macintosh NS8390-based Nubus Ethernet driver");
 MODUEL_LICENSE("GPL");
-#endif
 
 int init_module(void)
 {
diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c
--- a/drivers/net/pppoe.c	Tue Feb 25 09:17:47 2003
+++ b/drivers/net/pppoe.c	Thu Mar  6 11:06:44 2003
@@ -538,7 +538,7 @@
 	if (!sk)
 		return 0;
 
-	if (sk->dead != 0)
+	if (test_bit(SOCK_DEAD, &sk->flags))
 		return -EBADF;
 
 	pppox_unbind_sock(sk);
@@ -777,7 +777,7 @@
 
 
 int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-		  int total_len, struct scm_cookie *scm)
+		  int total_len)
 {
 	struct sk_buff *skb = NULL;
 	struct sock *sk = sock->sk;
@@ -788,7 +788,7 @@
 	struct net_device *dev;
 	char *start;
 
-	if (sk->dead || !(sk->state & PPPOX_CONNECTED)) {
+	if (test_bit(SOCK_DEAD, &sk->flags) || !(sk->state & PPPOX_CONNECTED)) {
 		error = -ENOTCONN;
 		goto end;
 	}
@@ -864,7 +864,7 @@
 	int data_len = skb->len;
 	struct sk_buff *skb2;
 
-	if (sk->dead  || !(sk->state & PPPOX_CONNECTED))
+	if (test_bit(SOCK_DEAD, &sk->flags)  || !(sk->state & PPPOX_CONNECTED))
 		goto abort;
 
 	hdr.ver	= 1;
@@ -937,7 +937,8 @@
 
 struct ppp_channel_ops pppoe_chan_ops = { pppoe_xmit , NULL };
 
-int pppoe_rcvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, int total_len, int flags, struct scm_cookie *scm)
+int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
+		  struct msghdr *m, int total_len, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb = NULL;
@@ -1089,7 +1090,7 @@
     .setsockopt		= sock_no_setsockopt,
     .getsockopt		= sock_no_getsockopt,
     .sendmsg		= pppoe_sendmsg,
-    .recvmsg		= pppoe_rcvmsg,
+    .recvmsg		= pppoe_recvmsg,
     .mmap		= sock_no_mmap
 };
 
diff -Nru a/drivers/net/shaper.c b/drivers/net/shaper.c
--- a/drivers/net/shaper.c	Sat Feb 15 11:32:47 2003
+++ b/drivers/net/shaper.c	Tue Mar  4 22:44:07 2003
@@ -88,10 +88,10 @@
 #include <net/arp.h>
 
 struct shaper_cb { 
+	unsigned long	shapeclock;		/* Time it should go out */
+	unsigned long	shapestamp;		/* Stamp for shaper    */
 	__u32		shapelatency;		/* Latency on frame */
-	__u32		shapeclock;		/* Time it should go out */
 	__u32		shapelen;		/* Frame length in clocks */
-	__u32		shapestamp;		/* Stamp for shaper    */
 	__u16		shapepend;		/* Pending */
 }; 
 #define SHAPERCB(skb) ((struct shaper_cb *) ((skb)->cb))
@@ -335,7 +335,7 @@
 		 */
 		 
 		if(sh_debug)
-			printk("Clock = %d, jiffies = %ld\n", SHAPERCB(skb)->shapeclock, jiffies);
+			printk("Clock = %ld, jiffies = %ld\n", SHAPERCB(skb)->shapeclock, jiffies);
 		if(time_before_eq(SHAPERCB(skb)->shapeclock - jiffies, SHAPER_BURST))
 		{
 			/*
diff -Nru a/drivers/net/sis900.c b/drivers/net/sis900.c
--- a/drivers/net/sis900.c	Tue Feb 25 02:45:05 2003
+++ b/drivers/net/sis900.c	Tue Mar  4 22:44:07 2003
@@ -509,7 +509,7 @@
 {
 	struct sis900_private * sis_priv = net_dev->priv;
 	u16 poll_bit = MII_STAT_LINK, status = 0;
-	unsigned int timeout = jiffies + 5 * HZ;
+	unsigned long timeout = jiffies + 5 * HZ;
 	int phy_addr;
 	u8 revision;
 
diff -Nru a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h
--- a/drivers/net/sk98lin/h/skgepnm2.h	Mon Feb  4 23:42:03 2002
+++ b/drivers/net/sk98lin/h/skgepnm2.h	Thu Mar  6 08:18:07 2003
@@ -341,7 +341,7 @@
 #if SK_TICKS_PER_SEC == 100
 #define SK_PNMI_HUNDREDS_SEC(t)	(t)
 #else
-#define SK_PNMI_HUNDREDS_SEC(t)	(((t) * 100) / (SK_TICKS_PER_SEC))
+#define SK_PNMI_HUNDREDS_SEC(t)	((((long)t) * 100) / (SK_TICKS_PER_SEC))
 #endif
 
 /*
diff -Nru a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c
--- a/drivers/net/sk_mca.c	Mon Feb 24 12:16:14 2003
+++ b/drivers/net/sk_mca.c	Thu Mar  6 09:24:43 2003
@@ -649,9 +649,7 @@
 				skb->protocol = eth_type_trans(skb, dev);
 				skb->ip_summed = CHECKSUM_NONE;
 				priv->stat.rx_packets++;
-#if LINUX_VERSION_CODE >= 0x020119	/* byte counters for >= 2.1.25 */
 				priv->stat.rx_bytes += descr.Len;
-#endif
 				netif_rx(skb);
 				dev->last_rx = jiffies;
 			}
@@ -709,9 +707,7 @@
 		/* update statistics */
 		if ((descr.Flags & TXDSCR_FLAGS_ERR) == 0) {
 			priv->stat.tx_packets++;
-#if LINUX_VERSION_CODE >= 0x020119	/* byte counters for >= 2.1.25 */
 			priv->stat.tx_bytes++;
-#endif
 		} else {
 			priv->stat.tx_errors++;
 			if ((descr.Status & TXDSCR_STATUS_UFLO) != 0) {
@@ -1001,13 +997,8 @@
 
       tx_done:
 
-	/* When did that change exactly ? */
-
-#if LINUX_VERSION_CODE >= 0x020200
 	dev_kfree_skb(skb);
-#else
-	dev_kfree_skb(skb, FREE_WRITE);
-#endif
+
 	return retval;
 }
 
@@ -1146,9 +1137,7 @@
 		mca_set_adapter_name(slot, "SKNET MC2+ Ethernet Adapter");
 	mca_set_adapter_procfn(slot, (MCA_ProcFn) skmca_getinfo, dev);
 
-#if LINUX_VERSION_CODE >= 0x020200
 	mca_mark_as_used(slot);
-#endif
 
 	/* announce success */
 	printk("%s: SKNet %s adapter found in slot %d\n", dev->name,
@@ -1283,9 +1272,7 @@
 				free_irq(dev->irq, dev);
 			dev->irq = 0;
 			unregister_netdev(dev);
-#if LINUX_VERSION_CODE >= 0x020200
 			mca_mark_as_unused(priv->slot);
-#endif
 			mca_set_adapter_procfn(priv->slot, NULL, NULL);
 			kfree(dev->priv);
 			dev->priv = NULL;
diff -Nru a/drivers/net/wan/comx-hw-munich.c b/drivers/net/wan/comx-hw-munich.c
--- a/drivers/net/wan/comx-hw-munich.c	Tue Feb 25 02:45:14 2003
+++ b/drivers/net/wan/comx-hw-munich.c	Thu Mar  6 09:25:13 2003
@@ -812,13 +812,8 @@
 
 	printk("munich_probe: munich chip found, IRQ %d\n", pci->irq);
 
-#if (LINUX_VERSION_CODE < 0x02030d)
-	bar1 = ioremap_nocache(pci->base_address[0], 0x100);
-	lbi = ioremap_nocache(pci->base_address[1], 0x100);
-#else
 	bar1 = ioremap_nocache(pci->resource[0].start, 0x100);
 	lbi = ioremap_nocache(pci->resource[1].start, 0x100);
-#endif
 
 	if (bar1 && lbi)
 	{
diff -Nru a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
--- a/drivers/net/wan/pc300_tty.c	Thu Nov 21 14:06:12 2002
+++ b/drivers/net/wan/pc300_tty.c	Sun Feb 16 16:22:42 2003
@@ -198,12 +198,6 @@
 	int port, aux;
 	st_cpc_tty_area * cpc_tty;
 
-	if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) {
-		printk("%s-tty: Error: TTY driver is supported on 2.4.X kernel!\n",
-			((struct net_device*)(pc300dev->hdlc))->name);
-		return;
-	}
-	
 	/* hdlcX - X=interface number */
 	port = ((struct net_device*)(pc300dev->hdlc))->name[4] - '0';
 	if (port >= CPC_TTY_NPORTS) {
diff -Nru a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c
--- a/drivers/net/wan/sdla_chdlc.c	Tue Feb 25 02:45:24 2003
+++ b/drivers/net/wan/sdla_chdlc.c	Thu Mar  6 09:25:13 2003
@@ -60,14 +60,9 @@
 #include <linux/if_arp.h>	/* ARPHRD_* defines */
 
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
- #include <asm/uaccess.h>
- #include <linux/inetdevice.h>
- #include <linux/netdevice.h>
-#else 				
- #include <asm/segment.h>
- #include <net/route.h>          /* Adding new route entries : 2.0.X kernels */
-#endif
+#include <asm/uaccess.h>
+#include <linux/inetdevice.h>
+#include <linux/netdevice.h>
 
 #include <linux/in.h>		/* sockaddr_in */
 #include <linux/inet.h>	
@@ -153,13 +148,11 @@
 	unsigned short timer_int_enabled;
 	char update_comms_stats;		/* updating comms stats */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	bh_data_t *bh_head;	  	  /* Circular buffer for chdlc_bh */
 	unsigned long  tq_working;
 	volatile int  bh_write;
 	volatile int  bh_read;
 	atomic_t  bh_buff_used;
-#endif
 	
 	unsigned char interface_down;
 
@@ -204,15 +197,8 @@
 static int if_header (struct sk_buff* skb, netdevice_t* dev,
 	unsigned short type, void* daddr, void* saddr, unsigned len);
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-  static int if_rebuild_hdr (struct sk_buff *skb);
-  static struct net_device_stats* if_stats (netdevice_t* dev);
-
-#else
-  static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr,
-        struct sk_buff* skb);
-  static struct enet_statistics* if_stats (netdevice_t* dev);
-#endif
+static int if_rebuild_hdr (struct sk_buff *skb);
+static struct net_device_stats* if_stats (netdevice_t* dev);
   
 static int if_send (struct sk_buff* skb, netdevice_t* dev);
 
@@ -228,9 +214,7 @@
 
 
 static int chdlc_disable_comm_shutdown (sdla_t *card);
-#ifdef LINUX_2_4
-  static void if_tx_timeout (netdevice_t *dev);
-#endif
+static void if_tx_timeout (netdevice_t *dev);
 
 /* Miscellaneous CHDLC Functions */
 static int set_chdlc_config (sdla_t* card);
@@ -260,12 +244,10 @@
 static void rx_intr (sdla_t* card);
 static void timer_intr(sdla_t *);
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-  /* Bottom half handlers */
-  static void chdlc_work (netdevice_t *);
-  static int chdlc_work_cleanup (netdevice_t *);
-  static int bh_enqueue (netdevice_t *, struct sk_buff *);
-#endif
+/* Bottom half handlers */
+static void chdlc_work (netdevice_t *);
+static int chdlc_work_cleanup (netdevice_t *);
+static int bh_enqueue (netdevice_t *, struct sk_buff *);
 
 /* Miscellaneous functions */
 static int chk_bcast_mcast_addr(sdla_t* card, netdevice_t* dev,
@@ -287,8 +269,6 @@
 
 /* TTY Global Definitions */
 
-#if defined(LINUX_2_4) || defined(LINUX_2_1)
-
 #define NR_PORTS 4
 #define WAN_TTY_MAJOR 226
 #define WAN_TTY_MINOR 0
@@ -321,8 +301,6 @@
 
 static void* tty_card_map[NR_PORTS] = {NULL,NULL,NULL,NULL};
 
-#endif
-
 
 /****** Public Functions ****************************************************/
 
@@ -569,7 +547,6 @@
 	}
 
 	if ((card->tty_opt=conf->tty) == WANOPT_YES){
-#if defined(LINUX_2_4) || defined(LINUX_2_1)	
 		int err;
 		card->tty_minor = conf->tty_minor;
 
@@ -582,11 +559,6 @@
 		if (err){
 			return err;
 		}
-#else
-		printk(KERN_INFO "%s: Error: TTY driver is not supported on 2.0.X kernels!\n",
-				card->devname);	
-		return -EINVAL;  
-#endif
 	}else{
 	
 
@@ -851,18 +823,6 @@
 			min_t(unsigned int, conf->slarp_timer, MAX_SLARP_REQ_TIMER) :
 			DEFAULT_SLARP_REQ_TIMER;
 
-#ifdef LINUX_2_0
-		if (card->u.c.slarp_timer){
-			printk(KERN_INFO 
-				"%s: Error: Dynamic IP support not available for 2.0.X kernels\n",
-					card->devname);
-			printk(KERN_INFO "%s:        Defaulting to Static IP addressing\n",
-						card->devname);
-		}
-		card->u.c.slarp_timer=0;
-#endif	
-
-
 		if (conf->hdlc_streaming == WANOPT_YES) {
 			printk(KERN_INFO "%s: Enabling HDLC STREAMING Mode\n",
 				wandev->name);
@@ -892,40 +852,24 @@
 			} 
 
 		} else if( strcmp(conf->usedby, "API") == 0) {
-#if defined(LINUX_2_1) || defined(LINUX_2_4) 
 			card->u.c.usedby = API;
 			printk(KERN_INFO "%s: Running in API mode !\n",
 				wandev->name);
-#else
-			printk(KERN_INFO "%s: API Mode is not supported for kernels lower than 2.2.X!\n",
-				wandev->name);
-			printk(KERN_INFO "%s: Please upgrade to a 2.2.X kernel fro the API support\n",
-				wandev->name);
-	                kfree(chdlc_priv_area);
-			return -EINVAL;
-#endif
 		}
 	}
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	/* Tells us that if this interface is a
          * gateway or not */
 	if ((chdlc_priv_area->gateway = conf->gateway) == WANOPT_YES){
 		printk(KERN_INFO "%s: Interface %s is set as a gateway.\n",
 			card->devname,card->u.c.if_name);
 	}
-#endif
 
 	/* Get Multicast Information */
 	chdlc_priv_area->mc = conf->mc;
 
 	/* prepare network device data space for registration */
-#ifdef LINUX_2_4
 	strcpy(dev->name,card->u.c.if_name);
-#else
-	dev->name = (char *)kmalloc(strlen(card->u.c.if_name) + 2, GFP_KERNEL); 
-	sprintf(dev->name, "%s", card->u.c.if_name);
-#endif
 
 	dev->init = &if_init;
 	dev->priv = chdlc_priv_area;
@@ -958,9 +902,6 @@
 	chdlc_private_area_t* chdlc_priv_area = dev->priv;
 	sdla_t* card = chdlc_priv_area->card;
 	wan_device_t* wandev = &card->wandev;
-#ifdef LINUX_2_0
-	int i;
-#endif
 
 	/* Initialize device driver entry points */
 	dev->open		= &if_open;
@@ -969,10 +910,8 @@
 	dev->rebuild_header	= &if_rebuild_hdr;
 	dev->hard_start_xmit	= &if_send;
 	dev->get_stats		= &if_stats;
-#ifdef LINUX_2_4
 	dev->tx_timeout		= &if_tx_timeout;
 	dev->watchdog_timeo	= TX_TIMEOUT;
-#endif
 
 	
 	/* Initialize media-specific parameters */
@@ -984,16 +923,8 @@
 		dev->flags 	|= IFF_MULTICAST;
 	}
 	
-#ifdef LINUX_2_0
-	dev->family		= AF_INET;
-#endif	
-
 	if (chdlc_priv_area->true_if_encoding){
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 		dev->type	= ARPHRD_HDLC; /* This breaks the tcpdump */
-#else
-		dev->type	= ARPHRD_PPP;
-#endif
 	}else{
 		dev->type	= ARPHRD_PPP;
 	}
@@ -1019,11 +950,6 @@
 	 */
         dev->tx_queue_len = 100;
    
-	/* Initialize socket buffers */
-#if !defined(LINUX_2_1) && !defined(LINUX_2_4)
-        for (i = 0; i < DEV_NUMBUFFS; ++i)
-                skb_queue_head_init(&dev->buffs[i]);
-#endif
 	return 0;
 }
 
@@ -1043,10 +969,9 @@
 
 	/* Only one open per interface is allowed */
 
-	if (is_dev_running(dev))
+	if (netif_running(dev))
 		return -EBUSY;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	/* Initialize the work queue entry */
 	chdlc_priv_area->tq_working=0;
 
@@ -1058,18 +983,11 @@
 	chdlc_priv_area->bh_head = kmalloc((sizeof(bh_data_t)*(MAX_BH_BUFF+1)),GFP_ATOMIC);
 	memset(chdlc_priv_area->bh_head,0,(sizeof(bh_data_t)*(MAX_BH_BUFF+1)));
 	atomic_set(&chdlc_priv_area->bh_buff_used, 0);
-#endif
  
 	do_gettimeofday(&tv);
 	chdlc_priv_area->router_start_time = tv.tv_sec;
 
-#ifdef LINUX_2_4
 	netif_start_queue(dev);
-#else
-	dev->interrupt = 0;
-	dev->tbusy = 0;
-	dev->start = 1;
-#endif
 
 	wanpipe_open(card);
 
@@ -1100,8 +1018,6 @@
 	chdlc_private_area_t* chdlc_priv_area = dev->priv;
 	sdla_t* card = chdlc_priv_area->card;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 	if (chdlc_priv_area->bh_head){
 		int i;
 		struct sk_buff *skb;
@@ -1109,18 +1025,14 @@
 		for (i=0; i<(MAX_BH_BUFF+1); i++){
 			skb = ((bh_data_t *)&chdlc_priv_area->bh_head[i])->skb;
 			if (skb != NULL){
-                		wan_dev_kfree_skb(skb, FREE_READ);
+                		dev_kfree_skb_any(skb);
 			}
 		}
 		kfree(chdlc_priv_area->bh_head);
 		chdlc_priv_area->bh_head=NULL;
 	}
-#endif
 
-	stop_net_queue(dev);
-#ifndef LINUX_2_4
-	dev->start=0;
-#endif
+	netif_stop_queue(dev);
 	wanpipe_close(card);
 	del_timer(&chdlc_priv_area->poll_delay_timer);
 	return 0;
@@ -1136,7 +1048,6 @@
 		flags->interrupt_info_struct.interrupt_permission = 0;	
 	}
 
-#if defined(LINUX_2_4) || defined(LINUX_2_1)	
 	if (!tty_init_cnt)
 		return;
 
@@ -1160,7 +1071,6 @@
 		state = &rs_table[card->tty_minor];
 		memset(state,0,sizeof(state));
 	}
-#endif
 	return;
 }
 
@@ -1183,7 +1093,6 @@
 }
 
 
-#ifdef LINUX_2_4
 /*============================================================================
  * Handle transmit timeout event from netif watchdog
  */
@@ -1203,7 +1112,6 @@
 	printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);
 	netif_wake_queue (dev);
 }
-#endif
 
 
 
@@ -1213,18 +1121,11 @@
  * Return:	1	physical address resolved.
  *		0	physical address not resolved
  */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static int if_rebuild_hdr (struct sk_buff *skb)
 {
 	return 1;
 }
-#else
-static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr,
-                           struct sk_buff* skb)
-{
-        return 1;
-}
-#endif
+
 
 /*============================================================================
  * Send a packet on a network interface.
@@ -1253,9 +1154,7 @@
 	unsigned long smp_flags;
 	int err=0;
 
-#ifdef LINUX_2_4
 	netif_stop_queue(dev);
-#endif
 	
 	if (skb == NULL){
 		/* If we get here, some higher layer thinks we've missed an
@@ -1264,31 +1163,10 @@
 		printk(KERN_INFO "%s: interface %s got kicked!\n",
 			card->devname, dev->name);
 
-		wake_net_dev(dev);
+		netif_wake_queue(dev);
 		return 0;
 	}
 
-#ifndef LINUX_2_4
-	if (dev->tbusy){
-
-		/* If our device stays busy for at least 5 seconds then we will
-		 * kick start the device by making dev->tbusy = 0.  We expect 
-		 * that our device never stays busy more than 5 seconds. So this
-		 * is only used as a last resort. 
-		 */
-                ++card->wandev.stats.collisions;
-		if((jiffies - chdlc_priv_area->tick_counter) < (5 * HZ)) {
-			return 1;
-		}
-
-		printk (KERN_INFO "%s: Transmit timeout !\n",
-			card->devname);
-
-		/* unbusy the interface */
-		clear_bit(0,&dev->tbusy);
-	}
-#endif
-
    	if (ntohs(skb->protocol) != htons(PVC_PROT)){
 
 		/* check the udp packet type */
@@ -1301,7 +1179,7 @@
 	                	chdlc_int->interrupt_permission |=
 					APP_INT_ON_TIMER;
 			}
-			start_net_queue(dev);
+			netif_start_queue(dev);
 			return 0;
 		}
 
@@ -1309,8 +1187,8 @@
 		/* multicast IP address */
                 if(chk_bcast_mcast_addr(card, dev, skb)){
 			++card->wandev.stats.tx_dropped;
-			wan_dev_kfree_skb(skb,FREE_WRITE);
-			start_net_queue(dev);
+			dev_kfree_skb_any(skb);
+			netif_start_queue(dev);
 			return 0;
 		}
         }
@@ -1325,17 +1203,17 @@
 		printk(KERN_INFO "%s: Critical in if_send: %lx\n",
 					card->wandev.name,card->wandev.critical);
                 ++card->wandev.stats.tx_dropped;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		goto if_send_exit_crit;
 	}
 
 	if(card->u.c.state != WAN_CONNECTED){
        		++card->wandev.stats.tx_dropped;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		
 	}else if(!skb->protocol){
         	++card->wandev.stats.tx_errors;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		
 	}else {
 		void* data = skb->data;
@@ -1355,7 +1233,7 @@
 				(len <= sizeof(api_tx_hdr_t))) {
 				
 				++card->wandev.stats.tx_dropped;
-				start_net_queue(dev);
+				netif_start_queue(dev);
 				goto if_send_exit_crit;
 			}
 				
@@ -1366,25 +1244,21 @@
 		}
 
 		if(chdlc_send(card, data, len)) {
-			stop_net_queue(dev);
+			netif_stop_queue(dev);
 		}else{
 			++card->wandev.stats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
                         card->wandev.stats.tx_bytes += len;
-#endif
 			
-			start_net_queue(dev);
+			netif_start_queue(dev);
 			
-#ifdef LINUX_2_4
 		 	dev->trans_start = jiffies;
-#endif
 		}	
 	}
 
 if_send_exit_crit:
 	
-	if (!(err=is_queue_stopped(dev))) {
-		wan_dev_kfree_skb(skb, FREE_WRITE);
+	if (!(err=netif_queue_stopped(dev))) {
+		dev_kfree_skb_any(skb);
 	}else{
 		chdlc_priv_area->tick_counter = jiffies;
 		chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
@@ -1409,14 +1283,12 @@
 {
 	u32 src_ip_addr;
         u32 broadcast_ip_addr = 0;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         struct in_device *in_dev;
-#endif
+
         /* read the IP source address from the outgoing packet */
         src_ip_addr = *(u32 *)(skb->data + 12);
 
 	/* read the IP broadcast address for the device */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         in_dev = dev->ip_ptr;
         if(in_dev != NULL) {
                 struct in_ifaddr *ifa= in_dev->ifa_list;
@@ -1425,9 +1297,6 @@
                 else
                         return 0;
         }
-#else
-        broadcast_ip_addr = dev->pa_brdaddr;
-#endif
  
         /* check if the IP Source Address is a Broadcast address */
         if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {
@@ -1552,7 +1421,6 @@
  * Get ethernet-style interface statistics.
  * Return a pointer to struct enet_statistics.
  */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static struct net_device_stats* if_stats (netdevice_t* dev)
 {
 	sdla_t *my_card;
@@ -1564,19 +1432,7 @@
 	my_card = chdlc_priv_area->card;
 	return &my_card->wandev.stats; 
 }
-#else
-static struct enet_statistics* if_stats (netdevice_t* dev)
-{
-        sdla_t *my_card;
-        chdlc_private_area_t* chdlc_priv_area = dev->priv;
 
-	if ((chdlc_priv_area=dev->priv) == NULL)
-		return NULL;
-
-        my_card = chdlc_priv_area->card;
-        return &my_card->wandev.stats;
-}
-#endif
 
 /****** Cisco HDLC Firmware Interface Functions *******************************/
 
@@ -1846,7 +1702,7 @@
 	return 0;
 }
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
+
 /********** Bottom Half Handlers ********************************************/
 
 /* NOTE: There is no API, BH support for Kernels lower than 2.2.X.
@@ -1873,7 +1729,7 @@
 
 			if (chan->common.sk == NULL || chan->common.func == NULL){
 				++card->wandev.stats.rx_dropped;
-				wan_dev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb_any(skb);
 				chdlc_work_cleanup(dev);
 				continue;
 			}
@@ -1921,7 +1777,7 @@
 
 	if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){
 		++card->wandev.stats.rx_dropped;
-		wan_dev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb_any(skb);
 		return 1; 
 	}
 
@@ -1940,7 +1796,6 @@
 
 /* END OF API BH Support */
 
-#endif
 
 /****** Interrupt Handlers **************************************************/
 
@@ -2017,24 +1872,19 @@
 		flags->interrupt_info_struct.interrupt_permission &=
 			 ~APP_INT_ON_TX_FRAME;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 		if (card->tty_opt){
 			wanpipe_tty_trigger_poll(card);
 			break;
 		}
 
-		if (dev && is_queue_stopped(dev)){
+		if (dev && netif_queue_stopped(dev)){
 			if (card->u.c.usedby == API){
-				start_net_queue(dev);
+				netif_start_queue(dev);
 				wakeup_sk_bh(dev);
 			}else{
-				wake_net_dev(dev);
+				netif_wake_queue(dev);
 			}
 		}
-#else
-		wake_net_dev(dev);
-#endif
 		break;
 
 	case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */
@@ -2120,7 +1970,6 @@
 
 	len  = rxbuf->frame_length;
 
-#if defined(LINUX_2_4) || defined(LINUX_2_1)	
 	if (card->tty_opt){
 
 		if (rxbuf->error_flag){	
@@ -2138,7 +1987,6 @@
 		wanpipe_tty_receive(card,addr,len);
 		goto rx_exit;
 	}
-#endif
 
 	dev = card->wandev.dev;
 
@@ -2146,7 +1994,7 @@
 		goto rx_exit;
 	}
 
-	if (!is_dev_running(dev))
+	if (!netif_running(dev))
 		goto rx_exit;
 
 	chdlc_priv_area = dev->priv;
@@ -2177,9 +2025,7 @@
 	skb->protocol = htons(ETH_P_IP);
 
 	card->wandev.stats.rx_packets ++;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	card->wandev.stats.rx_bytes += skb->len;
-#endif
 	udp_type = udp_pkt_type( skb, card );
 
 	if(udp_type == UDP_CPIPE_TYPE) {
@@ -2189,7 +2035,6 @@
 						interrupt_permission |= 
 							APP_INT_ON_TIMER; 
 		}
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	} else if(card->u.c.usedby == API) {
 
 		api_rx_hdr_t* api_rx_hdr;
@@ -2207,7 +2052,6 @@
 
 		if (!test_and_set_bit(0,&chdlc_priv_area->tq_working))
 			wanpipe_queue_work(&chdlc_priv_area->common.wanpipe_work);
-#endif
 	}else{
 		/* FIXME: we should check to see if the received packet is a 
                           multicast packet so that we can increment the multicast 
@@ -2331,7 +2175,6 @@
 		netdevice_t * dev = card->wandev.dev;
 		chdlc_private_area_t *chdlc_priv_area = dev->priv;
 		
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
                 struct in_device *in_dev = dev->ip_ptr;
 
 		if(in_dev != NULL) {
@@ -2344,12 +2187,6 @@
 				chdlc_priv_area->IP_netmask = ntohl(ifa->ifa_mask); 
 			}
 		}
-#else
-                cfg.IP_address          = ntohl(dev->pa_addr);
-                cfg.IP_netmask          = ntohl(dev->pa_mask);
-		chdlc_priv_area->IP_address = ntohl(dev->pa_addr);
-		chdlc_priv_area->IP_netmask = ntohl(dev->pa_mask);
-#endif
 
 		/* FIXME: We must re-think this message in next release
 		if((cfg.IP_address & 0x000000FF) > 2) {
@@ -2647,15 +2484,10 @@
 	u32 remote_IP_addr = 0;
 	u32 IP_netmask, IP_addr;
         int err = 0;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct in_device *in_dev;
 	mm_segment_t fs;
 	struct ifreq if_info;
         struct sockaddr_in *if_data1, *if_data2;
-#else
-	unsigned long fs = 0;
-        struct rtentry route;
-#endif
 	
         chdlc_priv_area = dev->priv;
         port_num = card->u.c.comm_port;
@@ -2705,7 +2537,6 @@
 	                return;
         	}
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
                 in_dev = dev->ip_ptr;
 
                 if(in_dev != NULL) {
@@ -2715,11 +2546,6 @@
                                 IP_netmask  = ifa->ifa_mask;
                         }
                 }
-#else
-                local_IP_addr = dev->pa_addr;
-                remote_IP_addr = dev->pa_dstaddr;
-                IP_netmask = dev->pa_mask;
-#endif
 	}else{ 
        		/* According to Cisco HDLC, if the point-to-point address is
 		   A.B.C.1, then we are the opposite (A.B.C.2), and vice-versa.
@@ -2749,44 +2575,20 @@
         fs = get_fs();                  /* Save file system  */
         set_fs(get_ds());               /* Get user space block */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         /* Setup a structure for adding/removing routes */
         memset(&if_info, 0, sizeof(if_info));
         strcpy(if_info.ifr_name, dev->name);
 
-#else
-	/* Setup a structure for adding/removing routes */
-	dev->pa_mask = IP_netmask;
-	dev->pa_dstaddr = remote_IP_addr;
-	dev->pa_addr = local_IP_addr;
-
-	memset(&route, 0, sizeof(route));
-	route.rt_dev = dev->name;
-	route.rt_flags = 0;
-	((struct sockaddr_in *)&(route.rt_dst))->sin_addr.s_addr =
-			dev->pa_dstaddr;
-	((struct sockaddr_in *)&(route.rt_dst))->sin_family = AF_INET;
-	((struct sockaddr_in *)&(route.rt_genmask))->sin_addr.s_addr =
-			0xFFFFFFFF;
-        ((struct sockaddr_in *)&(route.rt_genmask))->sin_family =
-			AF_INET;
-#endif
-
 	switch (chdlc_priv_area->route_status) {
 
 	case ADD_ROUTE:
 
 		if(!card->u.c.slarp_timer) {
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
 			if_data2->sin_addr.s_addr = remote_IP_addr;
 			if_data2->sin_family = AF_INET;
 			err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
-#else
-                        err = ip_rt_new(&route);
-#endif
 		} else { 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
 			if_data1->sin_addr.s_addr = local_IP_addr;
 			if_data1->sin_family = AF_INET;
@@ -2796,9 +2598,6 @@
 				if_data2->sin_family = AF_INET;
 				err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
 			}
-#else
-               		err = ip_rt_new(&route);
-#endif
 		}
 
                if(err) {
@@ -2819,7 +2618,6 @@
 
 	case REMOVE_ROUTE:
 	
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 		/* Change the local ip address of the interface to 0.
 		 * This will also delete the destination route.
 		 */
@@ -2835,11 +2633,6 @@
 			err = devinet_ioctl(SIOCSIFADDR,&if_info);
 		
 		}
-#else
-		/* set the point-to-point IP address to 0.0.0.0 */
-		dev->pa_dstaddr = 0; 
-		err = ip_rt_kill(&route);
-#endif
 		if(err) {
 			printk(KERN_INFO
 				"%s: Remove route %u.%u.%u.%u failed, (err %d)\n",
@@ -2880,9 +2673,9 @@
 	}
 
 	if(udp_pkt_src == UDP_PKT_FRM_STACK){
-		wan_dev_kfree_skb(skb, FREE_WRITE);
+		dev_kfree_skb_any(skb);
 	}else{
-                wan_dev_kfree_skb(skb, FREE_READ);
+                dev_kfree_skb_any(skb);
 	}
 		
 	return(udp_pkt_stored);
@@ -3256,9 +3049,7 @@
 		
 			if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) {
 				++ card->wandev.stats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 				card->wandev.stats.tx_bytes += len;
-#endif
 			}
 		}
 	} else {	
@@ -3808,30 +3599,21 @@
 
 void s508_lock (sdla_t *card, unsigned long *smp_flags)
 {
-#if defined(__SMP__) || defined(LINUX_2_4)
 	spin_lock_irqsave(&card->wandev.lock, *smp_flags);
         if (card->next){
         	spin_lock(&card->next->wandev.lock);
 	}
-#else
-        disable_irq(card->hw.irq);
-#endif                                                                     
 }
 
 void s508_unlock (sdla_t *card, unsigned long *smp_flags)
 {
-#if defined(__SMP__) || defined(LINUX_2_4)
         if (card->next){
         	spin_unlock(&card->next->wandev.lock);
         }
         spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-#else
-        enable_irq(card->hw.irq);
-#endif           
 }
 
 //*********** TTY SECTION ****************
-#if defined(LINUX_2_4) || defined(LINUX_2_1)
 
 static void wanpipe_tty_trigger_tx_irq(sdla_t *card)
 {
@@ -3858,8 +3640,7 @@
 		(tty->ldisc.write_wakeup)(tty);
 	}
 	wake_up_interruptible(&tty->write_wait);
-#if defined(SERIAL_HAVE_POLL_WAIT) || \
-         (defined LINUX_2_1 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15))
+#if defined(SERIAL_HAVE_POLL_WAIT)
 	wake_up_interruptible(&tty->poll_wait);
 #endif	
 	return;
@@ -4479,8 +4260,7 @@
 		return;
 	
 	wake_up_interruptible(&tty->write_wait);
-#if defined(SERIAL_HAVE_POLL_WAIT) || \
-         (defined LINUX_2_1 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15))
+#if defined(SERIAL_HAVE_POLL_WAIT)
 	wake_up_interruptible(&tty->poll_wait);
 #endif
 	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
@@ -4721,8 +4501,6 @@
 	INIT_WORK(&card->tty_work, tty_poll_work, (void*)card);
 	return 0;
 }
-
-#endif
 
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
--- a/drivers/net/wan/sdla_fr.c	Tue Feb 25 11:05:23 2003
+++ b/drivers/net/wan/sdla_fr.c	Thu Mar  6 09:25:30 2003
@@ -229,11 +229,7 @@
 	int inarp_interval;		/* Time between InArp Requests */
 	unsigned long inarp_tick;	/* InArp jiffies tick counter */
 	long interface_down;		/* Bring interface down on disconnect */
-      #if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct net_device_stats ifstats;	/* interface statistics */
-      #else
-	struct enet_statistics ifstats;
-      #endif	
 	if_send_stat_t drvstats_if_send;
         rx_intr_stat_t drvstats_rx_intr;
         pipe_mgmt_stat_t drvstats_gen;
@@ -242,14 +238,11 @@
 	unsigned short transmit_length;
 	struct sk_buff *delay_skb;
 
-
-      #if defined(LINUX_2_1) || defined(LINUX_2_4)
 	bh_data_t *bh_head;	  	  /* Circular buffer for chdlc_bh */
 	unsigned long  tq_working;
 	volatile int  bh_write;
 	volatile int  bh_read;
 	atomic_t  bh_buff_used;
-      #endif
 
 	/* Polling task queue. Each interface
          * has its own task queue, which is used
@@ -343,26 +336,14 @@
 static int if_open(netdevice_t *dev);
 static int if_close(netdevice_t *dev);
 
-
-#ifdef LINUX_2_4
 static void if_tx_timeout (netdevice_t *dev);
-#endif
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static int if_rebuild_hdr (struct sk_buff *skb);
-#else
-static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr,
-        struct sk_buff* skb);
-#endif
 
 static int if_send(struct sk_buff *skb, netdevice_t *dev);
 static int chk_bcast_mcast_addr(sdla_t *card, netdevice_t* dev,
                                 struct sk_buff *skb);
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static struct net_device_stats *if_stats(netdevice_t *dev);
-#else
-static struct enet_statistics* if_stats (netdevice_t* dev);
-#endif
 
 /* Interrupt handlers */
 static void fr_isr(sdla_t *card);
@@ -417,13 +398,11 @@
 netdevice_t * move_dev_to_next (sdla_t *, netdevice_t *);
 static int check_tx_status(sdla_t *, netdevice_t *);
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 /* Frame Relay Socket API */
 static void trigger_fr_bh (fr_channel_t *);
 static void fr_bh (netdevice_t *);
 static int fr_bh_cleanup (netdevice_t *);
 static int bh_enqueue (netdevice_t *, struct sk_buff *);
-#endif
 
 static void trigger_fr_poll (netdevice_t *);
 static void fr_poll (netdevice_t *);
@@ -886,26 +865,14 @@
 			
 			chan->common.usedby = BRIDGE;
 			
-#if defined(LINUX_2_1) || defined(LINUX_2_4) 
 			printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE) mode.\n", 
 					card->devname);
-#else
-			printk(KERN_INFO "%s: WANPIPE Bridging mode not supported in 2.0.X kernels.\n",
-					card->devname);
-			err = -EPROTONOSUPPORT;
-#endif
 		}else if( strcmp(conf->usedby, "BRIDGE_N") == 0 ){
 			
 			chan->common.usedby = BRIDGE_NODE;
 		
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE_NODE) mode.\n", 
 					card->devname);
-#else
-			printk(KERN_INFO "%s: WANPIPE Bridging mode not supported in 2.0.X kernels.\n",
-					card->devname);
-			err = -EPROTONOSUPPORT;
-#endif
 		}
 
 		if (!err){
@@ -922,18 +889,9 @@
 
         } else if(strcmp(conf->usedby, "API") == 0){
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4) 
                 chan->common.usedby = API;
                 printk(KERN_INFO "%s: Running in API mode.\n",
 			wandev->name);
-#else
-                printk(KERN_INFO "%s: The API Mode is not supported for"
-				 "kernels lower than 2.2.X !\n",
-					wandev->name);
-		printk(KERN_INFO "%s: Please upgrade to a 2.2.X kernel for the API support\n",
-					wandev->name);
-                err = -EINVAL;
-#endif
         }
 
 	if (err) {
@@ -980,16 +938,9 @@
 	chan->mc = conf->mc;
 
 	if (conf->inarp == WANOPT_YES){
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 		printk(KERN_INFO "%s: Inverse ARP Support Enabled\n",card->devname);
 		chan->inarp = conf->inarp ? INARP_REQUEST : INARP_NONE;
 		chan->inarp_interval = conf->inarp_interval ? conf->inarp_interval : 10;
-#else
-		printk(KERN_INFO "%s: Warning, Inverse ARP Support not available for 2.0.X kernels!\n",
-				card->devname);
-		chan->inarp = INARP_NONE;
-		chan->inarp_interval = 10;
-#endif
 	}else{
 		printk(KERN_INFO "%s: Inverse ARP Support Disabled\n",card->devname);
 		chan->inarp = INARP_NONE;
@@ -1023,17 +974,7 @@
 	chan->transmit_length = 0;
 
 	/* prepare network device data space for registration */
-#ifdef LINUX_2_4
 	strcpy(dev->name,chan->name);
-#else
-	dev->name = (char *)kmalloc(strlen(chan->name) + 2, GFP_KERNEL); 
-	if(dev->name == NULL)
-	{
-		kfree(chan);
-		return -ENOMEM;
-	}
-	sprintf(dev->name, "%s", chan->name);
-#endif
 	
 	dev->init = &if_init;
 	dev->priv = chan;
@@ -1042,9 +983,6 @@
          * We need a poll routine for each network
          * interface. 
          */
-#ifndef LINUX_2_4
-	chan->fr_poll_task.next = NULL;
-#endif
 	chan->fr_poll_task.sync = 0;
 	chan->fr_poll_task.routine = (void *)(void *)fr_poll;
 	chan->fr_poll_task.data = dev;
@@ -1138,8 +1076,6 @@
 	int err, len;
 	fr_cmd_t cmd;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 	if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd)))
 		return -EFAULT;
 	
@@ -1169,44 +1105,6 @@
 	if (len && u_data && !copy_to_user(u_data, (void*)&mbox->data, len))
 		return -EFAULT;
 	return 0;
-
-#else
-        if (!u_cmd || verify_area(VERIFY_WRITE, u_cmd, sizeof(fr_cmd_t)))
-                return -EFAULT;
-
-        memcpy_fromfs((void*)&cmd, u_cmd, sizeof(cmd));
-
-        if (cmd.length) {
-
-                if (!u_data || verify_area(VERIFY_READ, u_data, cmd.length))
-                        return -EFAULT;
-        }
-
-        /* execute command */
-        do
-        {
-                memcpy(&mbox->cmd, &cmd, sizeof(cmd));
-
-                if (cmd.length)
-                        memcpy_fromfs((void*)&mbox->data, u_data, cmd.length);
-
-                if (sdla_exec(mbox))
-                        err = mbox->cmd.result;
-
-                else return -EIO;
-        } while (err && retry-- && fr_event(card, err, mbox));
-
-        /* return result */
-        memcpy_tofs(u_cmd, (void*)&mbox->cmd, sizeof(fr_cmd_t));
-        len = mbox->cmd.length;
-
-        if (len && u_data && !verify_area(VERIFY_WRITE, u_data, len))
-                memcpy_tofs(u_data, (void*)&mbox->data, len);
-
-        return 0;
-
-#endif
-
 }
 
 /****** Network Device Interface ********************************************/
@@ -1223,9 +1121,6 @@
 	fr_channel_t* chan = dev->priv;
 	sdla_t* card = chan->card;
 	wan_device_t* wandev = &card->wandev;
-#ifdef LINUX_2_0
-	int i;
-#endif
 
 	/* Initialize device driver entry points */
 	dev->open		= &if_open;
@@ -1234,15 +1129,11 @@
 	dev->rebuild_header	= &if_rebuild_hdr;
 	dev->hard_start_xmit	= &if_send;
 	dev->get_stats		= &if_stats;
-#ifdef LINUX_2_4
 	dev->tx_timeout		= &if_tx_timeout;
 	dev->watchdog_timeo	= TX_TIMEOUT;
-#endif
 	
 	if (chan->common.usedby == WANPIPE || chan->common.usedby == API){
-#ifdef LINUX_2_0
-		dev->family = AF_INET;
-#endif
+
 		/* Initialize media-specific parameters */
 		if (chan->true_if_encoding){
 			dev->type 		= ARPHRD_DLCI;  /* This breaks tcpdump */
@@ -1274,11 +1165,6 @@
 		/* Set transmit buffer queue length */
         	dev->tx_queue_len = 100;
 
-			/* Initialize socket buffers */
-#if !defined(LINUX_2_1) && !defined(LINUX_2_4)
-	        for (i = 0; i < DEV_NUMBUFFS; ++i)
-			skb_queue_head_init(&dev->buffs[i]);
-#endif
 	}else{
 
 		/* Setup the interface for Bridging */
@@ -1315,16 +1201,12 @@
 	int err = 0;
 	struct timeval tv;
 
-	if (is_dev_running(dev))
+	if (netif_running(dev))
 		return -EBUSY;
 	
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	/* Initialize the task queue */
 	chan->tq_working=0;
 
-#ifndef LINUX_2_4
-	chan->common.wanpipe_task.next = NULL;
-#endif
 	chan->common.wanpipe_task.sync = 0;
 	chan->common.wanpipe_task.routine = (void *)(void *)fr_bh;
 	chan->common.wanpipe_task.data = dev;
@@ -1333,15 +1215,8 @@
 	chan->bh_head = kmalloc((sizeof(bh_data_t)*MAX_BH_BUFF),GFP_ATOMIC);
 	memset(chan->bh_head,0,(sizeof(bh_data_t)*MAX_BH_BUFF));
 	atomic_set(&chan->bh_buff_used, 0);
-#endif
 
-#ifdef LINUX_2_4
 	netif_start_queue(dev);
-#else	
-	dev->interrupt = 0;
-	dev->tbusy = 0;
-	dev->start = 1;
-#endif
 
 	wanpipe_open(card);
 	do_gettimeofday( &tv );
@@ -1370,10 +1245,7 @@
 		chan->inarp = INARP_REQUEST;
 	}
 
-	stop_net_queue(dev);
-#ifndef LINUX_2_4
-	dev->start=0;
-#endif
+	netif_stop_queue(dev);
 	wanpipe_close(card);
 
 	return 0;
@@ -1385,18 +1257,10 @@
  * Return:	1	physical address resolved.
  *		0	physical address not resolved
  */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static int if_rebuild_hdr (struct sk_buff* skb)
 {
-#else
-static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr,
-                           struct sk_buff* skb)
-{
-#endif
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4) 
 	netdevice_t *dev = skb->dev;
-#endif
 	fr_channel_t* chan = dev->priv;
 	sdla_t* card = chan->card;
 
@@ -1405,7 +1269,6 @@
 	return 1;
 }
 
-#ifdef LINUX_2_4
 /*============================================================================
  * Handle transmit timeout event from netif watchdog
  */
@@ -1429,7 +1292,7 @@
 	netif_wake_queue (dev);
 
 }
-#endif
+
 
 /*============================================================================
  * Send a packet on a network interface.
@@ -1448,7 +1311,7 @@
  * 1. This routine is called either by the protocol stack or by the "net
  *    bottom half" (with interrupts enabled).
  * 
- * 2. Using the start_net_queue() and stop_net_queue() MACROS
+ * 2. Using netif_start_queue() and netif_stop_queue()
  *    will inhibit further transmit requests from the protocol stack 
  *    and can be used for flow control with protocol layer.
  */
@@ -1466,9 +1329,7 @@
 
 	chan->drvstats_if_send.if_send_entry++;
 
-#ifdef LINUX_2_4
 	netif_stop_queue(dev);
-#endif
 	
         if (skb == NULL) {             
 		/* if we get here, some higher layer thinks we've missed an
@@ -1478,7 +1339,7 @@
 			card->devname, dev->name);
 		chan->drvstats_if_send.if_send_skb_null ++;
 
-		wake_net_dev(dev);
+		netif_wake_queue(dev);
 		return 0;
 	}
 
@@ -1488,8 +1349,8 @@
 		printk(KERN_INFO "%s: Critical in if_send(): Peripheral running!\n",
 				card->devname);
 		
-		wan_dev_kfree_skb(skb,FREE_WRITE);
-		start_net_queue(dev);
+		dev_kfree_skb_any(skb);
+		netif_start_queue(dev);
 		return 0;
 	}
 
@@ -1500,37 +1361,13 @@
 	*/
 	set_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);
         if(chan->transmit_length) {
-		stop_net_queue(dev);
+		netif_stop_queue(dev);
 		chan->tick_counter = jiffies;
  		clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);
 		return 1;
 	}
        	clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);
  
-#ifndef LINUX_2_4
-    	if (dev->tbusy) {
-
-		/* If our device stays busy for at least 5 seconds then we will
-                 * kick start the device by making dev->tbusy = 0.  We expect
-                 * that our device never stays busy more than 5 seconds. So this                 
-		 * is only used as a last resort.
-                 */
-		
-		chan->drvstats_if_send.if_send_tbusy++;
-		++chan->ifstats.collisions;
-
-		if ((jiffies - chan->tick_counter) < (5 * HZ)) {
-			return 1;
-		}
-
-		printk(KERN_INFO "%s: Transmit timed out on %s\n", 
-				card->devname, chan->name);
-		chan->drvstats_if_send.if_send_tbusy_timeout ++;
-		dev->tbusy = 0;
-    	}
-#endif
-
-	
 	/* Move the if_header() code to here. By inserting frame
 	 * relay header in if_header() we would break the
 	 * tcpdump and other packet sniffers */
@@ -1539,8 +1376,8 @@
 		++chan->ifstats.tx_dropped;
 		++card->wandev.stats.tx_dropped;
 		
-		wan_dev_kfree_skb(skb,FREE_WRITE);
-		start_net_queue(dev);	
+		dev_kfree_skb_any(skb);
+		netif_start_queue(dev);	
 		return 0;
 	}
 
@@ -1557,7 +1394,7 @@
 					if_send_PIPE_request ++;
 			}
                 }
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		return 0;
 	}
 
@@ -1569,8 +1406,8 @@
                 if(chk_bcast_mcast_addr(card, dev, skb)){
             		++chan->ifstats.tx_dropped;
 			++card->wandev.stats.tx_dropped;
-                	wan_dev_kfree_skb(skb, FREE_WRITE);
-			start_net_queue(dev);
+                	dev_kfree_skb_any(skb);
+			netif_start_queue(dev);
 			return 0;
 		}
 	}
@@ -1691,26 +1528,22 @@
 				++chan->ifstats.tx_packets;
 				++card->wandev.stats.tx_packets;
 				
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
                                 chan->ifstats.tx_bytes += skb->len;
                                 card->wandev.stats.tx_bytes += skb->len;
-#endif
-#ifdef LINUX_2_4
 				dev->trans_start = jiffies;
-#endif
 			}
 		}
 	}
 
 if_send_start_and_exit:
 
-	start_net_queue(dev);
+	netif_start_queue(dev);
 	
 	/* If we queued the packet for transmission, we must not
 	 * deallocate it. The packet is unlinked from the IP stack
 	 * not copied. Therefore, we must keep the original packet */
 	if (!test_bit(1,&delay_tx_queued)) {
-                wan_dev_kfree_skb(skb, FREE_WRITE);
+                dev_kfree_skb_any(skb);
 	}else{
 		adptr_flags->imask |= FR_INTR_TXRDY;
 		card->u.f.tx_interrupts_pending ++;
@@ -1786,16 +1619,13 @@
 {
         u32 src_ip_addr;
         u32 broadcast_ip_addr = 0;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         struct in_device *in_dev;
-#endif
         fr_channel_t* chan = dev->priv;
  
         /* read the IP source address from the outgoing packet */
         src_ip_addr = *(u32 *)(skb->data + 14);
 
         /* read the IP broadcast address for the device */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         in_dev = dev->ip_ptr;
         if(in_dev != NULL) {
                 struct in_ifaddr *ifa= in_dev->ifa_list;
@@ -1804,9 +1634,6 @@
                 else
                         return 0;
         }
-#else
-        broadcast_ip_addr = dev->pa_brdaddr;
-#endif
 
         /* check if the IP Source Address is a Broadcast address */
         if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {
@@ -1999,11 +1826,7 @@
  * Get ethernet-style interface statistics.
  * Return a pointer to struct enet_statistics.
  */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static struct net_device_stats *if_stats(netdevice_t *dev)
-#else
-static struct enet_statistics* if_stats (netdevice_t* dev)
-#endif
 {
 	fr_channel_t* chan = dev->priv;
 	
@@ -2193,7 +2016,7 @@
 
 	skb = dev_alloc_skb(len); 
 
-	if (!is_dev_running(dev) || (skb == NULL)){
+	if (!netif_running(dev) || (skb == NULL)){
 
 		++chan->ifstats.rx_dropped;
 	
@@ -2206,11 +2029,11 @@
 			chan->drvstats_rx_intr.rx_intr_no_socket ++;
 		} 
 
-		if (!is_dev_running(dev)){
+		if (!netif_running(dev)){
 			chan->drvstats_rx_intr.
 				rx_intr_dev_not_started ++;
 			if (skb){
-				wan_dev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb_any(skb);
 			}
 		}
 		goto rx_done;
@@ -2252,7 +2075,6 @@
 			}
 		}
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	}else if (chan->common.usedby == API) {
 
 		/* We are in API mode. 
@@ -2281,7 +2103,6 @@
 		bh_enqueue(dev, skb);
 
 		trigger_fr_bh(chan);
-	#endif
 
 	}else if (handle_IPXWAN(skb->data,chan->name,chan->enable_IPX, chan->network_number)){
 
@@ -2289,7 +2110,7 @@
 		//if (chan->enable_IPX) {
 		//	fr_send(card, dlci, 0, skb->len,skb->data);
 		//}
-		wan_dev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb_any(skb);
 
 	} else if (is_arp(skb->data)) {
 
@@ -2304,7 +2125,7 @@
 					card->devname);
 			}
 		}
-		wan_dev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb_any(skb);
 
 	} else if (skb->data[0] != 0x03) {
 
@@ -2312,7 +2133,7 @@
 			printk(KERN_INFO "%s: Non IETF packet discarded.\n", 
 				card->devname);
 		}
-		wan_dev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb_any(skb);
 
 	} else {
 
@@ -2341,7 +2162,7 @@
 			if (!wanrouter_type_trans(skb, dev)) {
 				
 				/* can't decapsulate packet */
-				wan_dev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb_any(skb);
 
 				++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack;
 				++chan->ifstats.rx_errors;
@@ -2359,10 +2180,8 @@
 		++chan->ifstats.rx_packets;
 		++card->wandev.stats.rx_packets;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 		chan->ifstats.rx_bytes += len_incl_hdr;
 		card->wandev.stats.rx_bytes += len_incl_hdr;
-#endif
 	}
 
 rx_done:
@@ -2454,36 +2273,28 @@
 
 		++chan->ifstats.tx_packets;
 		++card->wandev.stats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 		chan->ifstats.tx_bytes += chan->transmit_length;
 		card->wandev.stats.tx_bytes += chan->transmit_length;
-#endif
 
 		/* We must free an sk buffer, which we used
 		 * for delayed transmission; Otherwise, the sock
 		 * will run out of memory */
-                wan_dev_kfree_skb(chan->delay_skb, FREE_WRITE);
+                dev_kfree_skb_any(chan->delay_skb);
 
 		chan->delay_skb = NULL;				
         	chan->transmit_length = 0;
 
-#ifdef LINUX_2_4
 		dev->trans_start = jiffies;
-#endif
 
-#ifdef LINUX_2_0
-		wake_net_dev(dev);
-#else
-		if (is_queue_stopped(dev)){
+		if (netif_queue_stopped(dev)){
 			/* If using API, than wakeup socket BH handler */
 			if (chan->common.usedby == API){
-				start_net_queue(dev);
+				netif_start_queue(dev);
 				wakeup_sk_bh(dev);
 			}else{
-				wake_net_dev(dev);
+				netif_wake_queue(dev);
 			}
 		}
-#endif
 	}
 
 end_of_tx_intr:
@@ -2778,8 +2589,6 @@
 	fr_channel_t *chan = dev->priv;
 	sdla_t *card = chan->card;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 	struct ifreq if_info;
 	struct sockaddr_in *if_data;
 	mm_segment_t fs = get_fs();
@@ -2851,66 +2660,6 @@
 
 	} /* Case Statement */
 
-#else
-        /* Dynamic Route adding/removing */
-	struct rtentry route;
-        int err = 0;
-        unsigned long fs = get_fs();
-
-	memset(&route, 0, sizeof(route));
-	route.rt_dev   = dev->name;
-	route.rt_flags = 0;
-
-	((struct sockaddr_in *) &(route.rt_dst)) ->
-					sin_addr.s_addr=dev->pa_dstaddr;
-	((struct sockaddr_in *) &(route.rt_dst)) ->
-						sin_family = AF_INET;
-	((struct sockaddr_in *) &(route.rt_genmask)) ->
-				sin_addr.s_addr = 0xFFFFFFFF;
-	((struct sockaddr_in *) &(route.rt_genmask)) ->
-						sin_family = AF_INET;
-	switch(chan->route_flag) {
-
-	case ADD_ROUTE:
-
-		set_fs(get_ds());     /* get user space block */
-		err = ip_rt_new(&route);
-		set_fs(fs);           /* restore old block */
-
-		if (err) {
-			printk(KERN_INFO "%s: Adding of route failed.  Error: %d\n", 
-						card->devname,err);
-			printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n",
-				chan->name, NIPQUAD(dev->pa_dstaddr) );
-			}
-		else {
-			chan->route_flag = ROUTE_ADDED;
-		}
-		break;
-
-	case REMOVE_ROUTE:
-
-		set_fs(get_ds());     /* get user space block */
-		err = ip_rt_kill(&route);
-		set_fs(fs);           /* restore old block */
-
-		if (err) {
-		     printk(KERN_INFO "%s: Deleting of route failed.  Error: %d\n", 
-				card->devname,err);
-		     printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n",
-				dev->name,NIPQUAD(dev->pa_dstaddr) );
-		} else {
-
-		     printk(KERN_INFO "%s: Removed route.\n",
-			((fr_channel_t*)dev->priv)->name);
-		     chan->route_flag = NO_ROUTE;
-
-		}
-		break;
-	}
-
-#endif	
-
 }
 
 
@@ -3468,7 +3217,7 @@
 					"%s: DLCI %u is inactive!\n",
 					card->devname, dlci);
 
-				if (dev && is_dev_running(dev))
+				if (dev && netif_running(dev))
 					set_chan_state(dev, WAN_DISCONNECTED);
 			}
 	
@@ -3478,7 +3227,7 @@
 					"%s: DLCI %u has been deleted!\n",
 					card->devname, dlci);
 
-				if (dev && is_dev_running(dev)){
+				if (dev && netif_running(dev)){
 
 					fr_channel_t *chan = dev->priv;
 
@@ -3743,9 +3492,9 @@
 	}
 
         if(udp_pkt_src == UDP_PKT_FRM_STACK){
-                wan_dev_kfree_skb(skb, FREE_WRITE);
+                dev_kfree_skb_any(skb);
 	}else{
-                wan_dev_kfree_skb(skb, FREE_READ);
+                dev_kfree_skb_any(skb);
 	}
 		
         return(udp_pkt_stored);
@@ -4173,8 +3922,6 @@
 {
 	int err=0;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 	arphdr_1490_t *ArpPacket;
 	arphdr_fr_t *arphdr;
 	fr_channel_t *chan = dev->priv;
@@ -4225,47 +3972,6 @@
 		return 1;
 	}
 
-#else
-        arphdr_1490_t *ArpPacket;
-        arphdr_fr_t *arphdr;
-        fr_channel_t *chan = dev->priv;
-
-        ArpPacket = kmalloc(sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t), GFP_ATOMIC);
-        /* SNAP Header indicating ARP */
-        ArpPacket->control      = 0x03;
-        ArpPacket->pad          = 0x00;
-        ArpPacket->NLPID        = 0x80;
-        ArpPacket->OUI[0]       = 0;
-        ArpPacket->OUI[1]       = 0;
-        ArpPacket->OUI[2]       = 0;
-        ArpPacket->PID          = 0x0608;
-
-        arphdr = (arphdr_fr_t *)(ArpPacket + 1); // Go to ARP Packet
-       /* InARP request */
-        arphdr->ar_hrd = 0x0F00;        /* Frame Relay HW type */
-        arphdr->ar_pro = 0x0008;        /* IP Protocol         */
-        arphdr->ar_hln = 2;             /* HW addr length      */
-        arphdr->ar_pln = 4;             /* IP addr length      */
-        arphdr->ar_op = htons(0x08);    /* InARP Request       */
-        arphdr->ar_sha = 0;             /* src HW DLCI - Doesn't matter */
-        arphdr->ar_sip = dev->pa_addr;  /* Local Address       */
-        arphdr->ar_tha = 0;             /* dst HW DLCI - Doesn't matter */
-        arphdr->ar_tip = 0;             /* Remote Address -- what we want */
-
-        printk(KERN_INFO "%s: Sending InARP request on DLCI %d.\n", card->devname, chan->dlci);
-        err = fr_send(card, chan->dlci, 0,
-                   sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t),
-                   (void *)ArpPacket);
-	
-	if (!err){
-         	printk(KERN_INFO "\n%s: Sending InARP request on DLCI %d.\n",
-                        card->devname, chan->dlci);
-                clear_bit(ARP_CRIT,&card->wandev.critical);
-        }
-
-        kfree(ArpPacket);
-#endif
-
 	return 0;
 }
 	
@@ -4293,15 +3999,10 @@
 {
 
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	arphdr_fr_t *arphdr = (arphdr_fr_t *)(ArpPacket + 1); /* Skip header */
 	fr_rx_buf_ctl_t* frbuf = card->rxmb;
 	struct in_device *in_dev;
 	fr_channel_t *chan = dev->priv;		
-#else
-  	arphdr_fr_t *arphdr = (arphdr_fr_t *)(ArpPacket + 1); /* Skip header */
-        fr_rx_buf_ctl_t* frbuf = card->rxmb;
-#endif
 	
 	/* Before we transmit ARP packet, we must check 
 	 * to see that we are not currently transmitting a 
@@ -4316,8 +4017,6 @@
 		return 0;
 	}
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 	in_dev = dev->ip_ptr;
 
 	/* Check that IP addresses exist for our network address */
@@ -4434,87 +4133,6 @@
 	}
 
 	return 0;	
-#else
-
-        switch (ntohs(arphdr->ar_op)) {
-
-                case 0x08:  // Inverse ARP request  -- Send Reply, add route.
-
-                        /* Check for valid Address */
-                        printk(KERN_INFO "%s: Recvd PtP addr %u.%u.%u.%u -InArp Req\n", 
-				((fr_channel_t *)dev->priv)->name, NIPQUAD(arphdr->ar_sip));
-
-
-			if (dev->pa_mask != 0xFFFFFFFF){
-
-	                        if ((dev->pa_mask & arphdr->ar_sip) != (dev->pa_mask & dev->pa_addr)) {
-        	                        printk(KERN_INFO "%s: Invalid PtP address.  InARP ignored.\n", 
-							card->devname);
-                        	        return -1;
-                        	}
-			}
-
-                        if (dev->pa_addr == arphdr->ar_sip) {
-                                printk(KERN_INFO "%s: Local addr = PtP addr.  InARP ignored.\n", 
-						card->devname);
-                                return -1;
-                        }
-
-                        arphdr->ar_op = htons(0x09);    /* InARP Reply */
-
-                        /* Set addresses */
-                        arphdr->ar_tip = arphdr->ar_sip;
-                        arphdr->ar_sip = dev->pa_addr;
-
-                        fr_send(card, frbuf->dlci, 0, frbuf->length, (void *)ArpPacket);
-
-			clear_bit(ARP_CRIT,&card->wandev.critical);
-
-                        /* Modify Point-to-Point Address */
-                        dev->pa_dstaddr = arphdr->ar_tip;
-
-                        /* Add Route Flag */
-                        /* The route will be added in the polling routine so
-                           that it is not interrupt context. */
-                        ((fr_channel_t *) dev->priv)->route_flag = ADD_ROUTE;
-			trigger_fr_poll(dev);
-
-                        break;
-                case 0x09:  // Inverse ARP reply
-
-                        /* Check for valid Address */
-                        printk(KERN_INFO "%s: Recvd PtP addr %u.%u.%u.%u -InArp Reply\n", 
-				((fr_channel_t *)dev->priv)->name, NIPQUAD(arphdr->ar_sip));
-
-                        if ((dev->pa_mask & arphdr->ar_sip) != (dev->pa_mask & dev->pa_addr)) {
-                                printk(KERN_INFO "%s: Invalid PtP address.  InARP ignored.\n", 
-					card->devname);
-                                return -1;
-                        }
-
-                        if (dev->pa_addr == arphdr->ar_sip) {
-                                printk(KERN_INFO "%s: Local addr = PtP addr.  InARP ignored.\n", 
-					card->devname);
-                                return -1;
-                        }
-
-                        /* Modify Point-to-Point Address */
-                        dev->pa_dstaddr = arphdr->ar_sip;
-                        /* Add Route Flag */
-                        /* The route will be added in the polling routine so
-                           that it is not interrupt context. */
-
-                        ((fr_channel_t *) dev->priv)->route_flag = ADD_ROUTE;
-                        ((fr_channel_t *) dev->priv)->inarp = INARP_CONFIGURED;
-			trigger_fr_poll(dev);
-
-                        break;
-                default:  // ARP's and RARP's -- Shouldn't happen.
-        }
-
-        return 0;
-
-#endif
 }
 
 
@@ -4706,15 +4324,9 @@
 {
 	if (card->hw.type != SDLA_S514){
 
-#if defined(__SMP__) || defined(LINUX_2_4)
 		spin_lock_irqsave(&card->wandev.lock, *smp_flags);
-#else
-          	disable_irq(card->hw.irq);
-#endif
 	}else{
-#if defined(__SMP__) || defined(LINUX_2_4)
 		spin_lock(&card->u.f.if_send_lock);
-#endif
 	}
 	return;
 }
@@ -4724,23 +4336,15 @@
 {
 	if (card->hw.type != SDLA_S514){
 
-#if defined(__SMP__) || defined(LINUX_2_4)
 		spin_unlock_irqrestore (&card->wandev.lock, *smp_flags);
-#else
-          	enable_irq(card->hw.irq);
-#endif
 	}else{
-#if defined(__SMP__) || defined(LINUX_2_4)
 		spin_unlock(&card->u.f.if_send_lock);
-#endif
 	}
 	return;
 }
 
 
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 /*----------------------------------------------------------------------
                   RECEIVE INTERRUPT: BOTTOM HALF HANDLERS 
  ----------------------------------------------------------------------*/
@@ -4770,7 +4374,7 @@
 
 	if (atomic_read(&chan->bh_buff_used) == MAX_BH_BUFF){
 		++card->wandev.stats.rx_dropped;
-		wan_dev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb_any(skb);
 		return 1; 
 	}
 
@@ -4859,7 +4463,7 @@
 			if (chan->common.sk == NULL || chan->common.func == NULL){
 				++card->wandev.stats.rx_dropped;
 				++chan->ifstats.rx_dropped;
-				wan_dev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb_any(skb);
 				fr_bh_cleanup(dev);
 				continue;
 			}
@@ -4896,7 +4500,6 @@
 	atomic_dec(&chan->bh_buff_used);
 	return 0;
 }
-#endif
 
 
 /*----------------------------------------------------------------------
@@ -4919,11 +4522,7 @@
 static void trigger_fr_poll (netdevice_t *dev)
 {
 	fr_channel_t* chan = dev->priv;
-#ifdef LINUX_2_4
 	schedule_task(&chan->fr_poll_task);
-#else
-	queue_task(&chan->fr_poll_task, &tq_scheduler);
-#endif
 	return;
 }
 
@@ -5047,7 +4646,7 @@
 		}
 	}
 
-	if (is_queue_stopped(dev) || (card->u.f.tx_interrupts_pending))
+	if (netif_queue_stopped(dev) || (card->u.f.tx_interrupts_pending))
      		return 1; 
 
 	return 0;
@@ -5295,7 +4894,6 @@
 	 * an Ethernet header */
 	if (op_mode == BRIDGE || op_mode == BRIDGE_NODE){
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 
 		/* Encapsulate the packet as a bridged Ethernet frame. */
 #ifdef DEBUG
@@ -5316,12 +4914,6 @@
 		skb->protocol = ETH_P_802_3;
 		return 8;
 
-#else
-
-		/* BRIDGING is not supported in 2.0.X */
-		return -EINVAL;
-
-#endif
 	}
 		
 	return 0;
diff -Nru a/drivers/net/wan/sdla_ft1.c b/drivers/net/wan/sdla_ft1.c
--- a/drivers/net/wan/sdla_ft1.c	Mon Aug 26 11:35:50 2002
+++ b/drivers/net/wan/sdla_ft1.c	Sun Feb 16 16:22:42 2003
@@ -252,8 +252,6 @@
 	CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
 	int len;
 
-	
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	if (copy_from_user((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t))){
 		return -EFAULT;
 	}
@@ -281,36 +279,6 @@
 	if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)){
 		return -EFAULT;
 	}
-
-#else
-
-        if (!u_cmd || verify_area(VERIFY_WRITE, u_cmd, sizeof(ft1_exec_cmd_t))){
-                return -EFAULT;
-	}
-
-        memcpy_fromfs((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t));
-
-	len = mbox->buffer_length;
-
-        if (len) {
-                if (!u_data || verify_area(VERIFY_READ, u_data, len))
-                        return -EFAULT;
-		memcpy_fromfs((void*)&mbox->data, u_data, len);
-        }
-
-        /* execute command */
-        if (!sdla_exec(mbox))
-               	return -EIO;
-
-        /* return result */
-        memcpy_tofs(u_cmd, (void*)&mbox->command, sizeof(ft1_exec_cmd_t));
-        len = mbox->buffer_length;
-
-        if (len && u_data && !verify_area(VERIFY_WRITE, u_data, len)){
-                memcpy_tofs(u_data, (void*)&mbox->data, len);
-	}
-
-#endif
 
 	return 0;
 
diff -Nru a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c
--- a/drivers/net/wan/sdla_ppp.c	Tue Feb 25 11:05:23 2003
+++ b/drivers/net/wan/sdla_ppp.c	Thu Mar  6 09:25:30 2003
@@ -104,15 +104,9 @@
 #include <linux/in.h>		/* sockaddr_in */
 
 
-/* ---- 2.4.X KERNEL SUPPORT -----------------------*/
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
- #include <asm/uaccess.h>
- #include <linux/inetdevice.h>
- #include <linux/netdevice.h>
-#else
- #include <asm/segment.h>
- #include <net/route.h>          /* Adding new route entries : 2.0.X kernels */
-#endif
+#include <asm/uaccess.h>
+#include <linux/inetdevice.h>
+#include <linux/netdevice.h>
 
 #include <linux/if.h>
 #include <linux/sdla_ppp.h>		/* PPP firmware API definitions */
@@ -163,10 +157,6 @@
 #define NUM_AUTH_REQ_WITHOUT_REPLY      10
 
 #define END_OFFSET 0x1F0
-#if LINUX_VERSION_CODE < 0x020125
-#define test_and_set_bit set_bit
-#define net_ratelimit() 1
-#endif
 
 
 /******Data Structures*****************************************************/
@@ -255,18 +245,10 @@
 static int if_header(struct sk_buff *skb, netdevice_t *dev, unsigned short type, 
 		     void *daddr, void *saddr, unsigned len);
 
-#ifdef LINUX_2_4
 static void if_tx_timeout (netdevice_t *dev);
-#endif
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static int if_rebuild_hdr(struct sk_buff *skb);
 static struct net_device_stats *if_stats(netdevice_t *dev);
-#else
-static struct enet_statistics *if_stats(netdevice_t *dev);
-static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr,
-        struct sk_buff* skb);
-#endif
 static int if_send(struct sk_buff *skb, netdevice_t *dev);
 
 
@@ -615,17 +597,7 @@
 	}
 
 	/* prepare network device data space for registration */
-#ifdef LINUX_2_4
  	strcpy(dev->name,card->u.p.if_name);
-#else
-	dev->name = (char *)kmalloc(strlen(card->u.p.if_name) + 2, GFP_KERNEL); 
-	if(dev->name == NULL)
-	{
-		kfree(ppp_priv_area);
-		return -ENOMEM;
-	}
-	sprintf(dev->name, "%s", card->u.p.if_name);
-#endif
 	
 	dev->init = &if_init;
 	dev->priv = ppp_priv_area;
@@ -673,7 +645,6 @@
 	ppp_mbox_t *mbox = card->mbox;
 	int len;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	if (copy_from_user((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t)))
 		return -EFAULT;
 
@@ -698,35 +669,6 @@
 	if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len))
 		return -EFAULT;
 
-#else
-
-        if (!u_cmd || verify_area(VERIFY_WRITE, u_cmd, sizeof(ppp_cmd_t)))
-                return -EFAULT;
-
-        memcpy_fromfs((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t));
-
-	len = mbox->cmd.length;
-
-        if (len) {
-
-                if (!u_data || verify_area(VERIFY_READ, u_data, len))
-                        return -EFAULT;
-        }
-
-        /* execute command */
-        if (!sdla_exec(mbox))
-               	return -EIO;
-
-        /* return result */
-        memcpy_tofs(u_cmd, (void*)&mbox->cmd, sizeof(ppp_cmd_t));
-        len = mbox->cmd.length;
-
-        if (len && u_data && !verify_area(VERIFY_WRITE, u_data, len))
-                memcpy_tofs(u_data, (void*)&mbox->data, len);
-
-
-#endif
-
 	return 0;
 }
 
@@ -744,9 +686,6 @@
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 	sdla_t *card = ppp_priv_area->card;
 	wan_device_t *wandev = &card->wandev;
-#ifdef LINUX_2_0
-	int i;
-#endif
 
 	/* Initialize device driver entry points */
 	dev->open		= &if_open;
@@ -755,10 +694,8 @@
 	dev->rebuild_header	= &if_rebuild_hdr;
 	dev->hard_start_xmit	= &if_send;
 	dev->get_stats		= &if_stats;
-#ifdef LINUX_2_4
 	dev->tx_timeout		= &if_tx_timeout;
 	dev->watchdog_timeo	= TX_TIMEOUT;
-#endif
 
 	/* Initialize media-specific parameters */
 	dev->type		= ARPHRD_PPP;	/* ARP h/w type */
@@ -770,9 +707,6 @@
 		dev->flags	|= IFF_MULTICAST;
 	}
 
-#ifdef LINUX_2_0
-	dev->family		= AF_INET;
-#endif	
 	dev->mtu		= wandev->mtu;
 	dev->hard_header_len	= PPP_HDR_LEN;	/* media header length */
 
@@ -786,12 +720,6 @@
         /* Set transmit buffer queue length */
         dev->tx_queue_len = 100;
    
-	/* Initialize socket buffers */
-      #if !defined(LINUX_2_1) && !defined(LINUX_2_4)
-        for (i = 0; i < DEV_NUMBUFFS; ++i)
-                skb_queue_head_init(&dev->buffs[i]);
-      #endif
-
 	return 0;
 }
 
@@ -809,18 +737,12 @@
 	struct timeval tv;
 	//unsigned long smp_flags;
 
-	if (is_dev_running(dev))
+	if (netif_running(dev))
 		return -EBUSY;
 
 	wanpipe_open(card);
 
-#ifdef LINUX_2_4
 	netif_start_queue(dev);
-#else
-	dev->interrupt = 0;
-	dev->tbusy = 0;
-	dev->start = 1;
-#endif
 	
 	do_gettimeofday( &tv );
 	ppp_priv_area->router_start_time = tv.tv_sec;
@@ -852,10 +774,7 @@
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 	sdla_t *card = ppp_priv_area->card;
 
-	stop_net_queue(dev);
-#ifndef LINUX_2_4
-	dev->start=0;
-#endif
+	netif_stop_queue(dev);
 	wanpipe_close(card);
 
 	del_timer (&ppp_priv_area->poll_delay_timer);
@@ -894,7 +813,6 @@
  * Return:	1	physical address resolved.
  *		0	physical address not resolved
  */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static int if_rebuild_hdr (struct sk_buff *skb)
 {
 	netdevice_t *dev = skb->dev;
@@ -906,16 +824,6 @@
 	return 1;
 }
 
-#else
-static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr,
-                           struct sk_buff* skb)
-{
-	return 1;
-
-}
-#endif
-
-#ifdef LINUX_2_4
 /*============================================================================
  * Handle transmit timeout event from netif watchdog
  */
@@ -937,7 +845,6 @@
 	++chan->if_send_stat.if_send_tbusy_timeout;
 	netif_wake_queue (dev);
 }
-#endif
 
 
 
@@ -970,9 +877,7 @@
 	
 	++ppp_priv_area->if_send_stat.if_send_entry;
 
-#ifdef LINUX_2_4
 	netif_stop_queue(dev);
-#endif
 	
 	if (skb == NULL) {
 
@@ -984,36 +889,10 @@
 		
 		++ppp_priv_area->if_send_stat.if_send_skb_null;
 	
-		wake_net_dev(dev);
+		netif_wake_queue(dev);
 		return 0;
 	}
 
-#ifndef LINUX_2_4
-	if (dev->tbusy) {
-
-		/* If our device stays busy for at least 5 seconds then we will
-		 * kick start the device by making dev->tbusy = 0.  We expect 
-		 * that our device never stays busy more than 5 seconds. So this
-		 * is only used as a last resort. 
-		 */
-              
-		++ppp_priv_area->if_send_stat.if_send_tbusy;
-        	++card->wandev.stats.collisions;
-
-		if ((jiffies - ppp_priv_area->tick_counter) < (5*HZ)) {
-			return 1;
-		}
-
-		printk (KERN_INFO "%s: Transmit times out on %s\n",card->devname,dev->name);
-	
-		++ppp_priv_area->if_send_stat.if_send_tbusy_timeout;
-		++card->wandev.stats.collisions;
-
-		/* unbusy the card (because only one interface per card)*/
-		dev->tbusy = 0;
-	}	
-#endif
-	
 	sendpacket = skb->data;
 
 	udp_type = udp_pkt_type( skb, card );
@@ -1025,7 +904,7 @@
 	               	flags->imask |= PPP_INTR_TIMER;
 		}
 		++ppp_priv_area->if_send_stat.if_send_PIPE_request;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		return 0;
 	}
 
@@ -1034,8 +913,8 @@
 	 */
 	if(chk_bcast_mcast_addr(card, dev, skb)){
 		++card->wandev.stats.tx_dropped;
-		wan_dev_kfree_skb(skb,FREE_WRITE);
-		start_net_queue(dev);
+		dev_kfree_skb_any(skb);
+		netif_start_queue(dev);
 		return 0;
 	}
 
@@ -1051,7 +930,7 @@
 		
 		++card->wandev.stats.tx_dropped;
 		++ppp_priv_area->if_send_stat.if_send_critical_non_ISR;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		goto if_send_exit_crit;
 	}
 
@@ -1059,12 +938,12 @@
 
 		++ppp_priv_area->if_send_stat.if_send_wan_disconnected;
         	++card->wandev.stats.tx_dropped;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		
      	} else if (!skb->protocol) {
 		++ppp_priv_area->if_send_stat.if_send_protocol_error;
         	++card->wandev.stats.tx_errors;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		
 	} else {
 
@@ -1075,32 +954,28 @@
 					ppp_priv_area->network_number, 0);
 			} else {
 				++card->wandev.stats.tx_dropped;
-				start_net_queue(dev);
+				netif_start_queue(dev);
 				goto if_send_exit_crit;
 			}
 		}
 
 		if (ppp_send(card, skb->data, skb->len, skb->protocol)) {
-			stop_net_queue(dev);
+			netif_stop_queue(dev);
 			++ppp_priv_area->if_send_stat.if_send_adptr_bfrs_full;
 			++ppp_priv_area->if_send_stat.if_send_tx_int_enabled;
 		} else {
 			++ppp_priv_area->if_send_stat.if_send_bfr_passed_to_adptr;
 			++card->wandev.stats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			card->wandev.stats.tx_bytes += skb->len;
-#endif
-			start_net_queue(dev);
-#ifdef LINUX_2_4
+			netif_start_queue(dev);
 			dev->trans_start = jiffies;
-#endif
 		}
     	}
 	
 if_send_exit_crit:
 	
-	if (!(err=is_queue_stopped(dev))){
-      		wan_dev_kfree_skb(skb, FREE_WRITE);
+	if (!(err=netif_queue_stopped(dev))){
+      		dev_kfree_skb_any(skb);
 	}else{
 		ppp_priv_area->tick_counter = jiffies;
 		flags->imask |= PPP_INTR_TXRDY;	/* unmask Tx interrupts */
@@ -1134,13 +1009,8 @@
 		udp_pkt_stored = 1;
 	}else{
 		if (skb->len > MAX_LGTH_UDP_MGNT_PKT){
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			printk(KERN_INFO "%s: PIPEMON UDP request too long : %i\n",
 				card->devname, skb->len);
-#else
-			printk(KERN_INFO "%s: PIPEMON UDP request too long : %li\n",
-				card->devname, skb->len);
-#endif
 		}else{
 			printk(KERN_INFO "%s: PIPEMON UPD request already pending\n",
 				card->devname);
@@ -1149,9 +1019,9 @@
 	}
 
 	if(udp_pkt_src == UDP_PKT_FRM_STACK){
-		wan_dev_kfree_skb(skb, FREE_WRITE);
+		dev_kfree_skb_any(skb);
 	}else{
-                wan_dev_kfree_skb(skb, FREE_READ);
+                dev_kfree_skb_any(skb);
 	}
 
 	return(udp_pkt_stored);
@@ -1319,11 +1189,7 @@
  * Get ethernet-style interface statistics.
  * Return a pointer to struct net_device_stats.
  */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static struct net_device_stats *if_stats(netdevice_t *dev)
-#else
-static struct enet_statistics *if_stats(netdevice_t *dev)
-#endif
 {
 
 	ppp_private_area_t *ppp_priv_area = dev->priv;
@@ -1743,7 +1609,7 @@
 		case PPP_INTR_TXRDY:	/* transmit interrupt  0x02 (bit 1)*/
 			++card->statistics.isr_tx;
 			flags->imask &= ~PPP_INTR_TXRDY;
-			wake_net_dev(dev);
+			netif_wake_queue(dev);
 			break;
 
 		case PPP_INTR_CMD:      /* interface command completed */
@@ -1821,7 +1687,7 @@
 		return;
 	}
       
-	if (dev && is_dev_running(dev) && dev->priv){
+	if (dev && netif_running(dev) && dev->priv){
 	
 		len  = rxbuf->length;
 		ppp_priv_area = dev->priv;
@@ -1881,7 +1747,7 @@
 					if (!test_bit(SEND_CRIT, &card->wandev.critical)){
 					 	ppp_send(card, skb->data, skb->len, htons(ETH_P_IPX));
 					}
-					wan_dev_kfree_skb(skb,FREE_READ);
+					dev_kfree_skb_any(skb);
 
 				} else {
 					++card->wandev.stats.rx_dropped;
@@ -1892,9 +1758,7 @@
 				skb->mac.raw  = skb->data;
 
 			    	++card->wandev.stats.rx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 				card->wandev.stats.rx_bytes += skb->len;
-#endif
 		    		++ppp_priv_area->rx_intr_stat.rx_intr_bfr_passed_to_stack;	
 				netif_rx(skb);
 				dev->last_rx = jiffies;
@@ -2244,8 +2108,6 @@
 	netdevice_t *dev = card->wandev.dev;
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 	
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 	if ((card->u.p.ip_mode == WANOPT_PPP_PEER) &&
 	    (flags->ip_state == 0x09)){ 
 
@@ -2276,29 +2138,6 @@
 			}
 		}
 	}
-#else
-
-	if ((card->u.p.ip_mode == WANOPT_PPP_PEER) &&
-	    (flags->ip_state == 0x09)){ 
-	
-		if (ppp_priv_area->ip_local == 0)
-			return;
-	
-		printk(KERN_INFO "%s: IPCP State Opened.\n", card->devname);
-		if (read_info( card )) {
-			printk(KERN_INFO 
-				"%s: An error occurred in IP assignment.\n", 
-				card->devname);
-		} else {
-			printk(KERN_INFO "%s: Assigned Lcl. Addr: %u.%u.%u.%u\n", 
-					card->devname, NIPQUAD(dev->pa_addr));
-			printk(KERN_INFO "%s: Assigned Rmt. Addr: %u.%u.%u.%U\n", 
-					card->devname, NIPQUAD(dev->pa_dstaddr));
-		}
-	}
-
-#endif
-
 }
 
 /*============================================================================
@@ -2328,9 +2167,7 @@
 static int config508(netdevice_t *dev, sdla_t *card)
 {
 	ppp508_conf_t cfg;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct in_device *in_dev = dev->ip_ptr;
-#endif
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 
 	/* Prepare PPP configuration structure */
@@ -2393,14 +2230,8 @@
 			printk(KERN_INFO "%s: PPP IP Mode: STATIC\n",card->devname);
 			cfg.ip_options		= L_AND_R_IP_NO_ASSIG | 
 							    ENABLE_IP;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			cfg.ip_local		= in_dev->ifa_list->ifa_local;
 			cfg.ip_remote		= in_dev->ifa_list->ifa_address;
-#else
-			cfg.ip_local		= dev->pa_addr;
-			cfg.ip_remote		= dev->pa_dstaddr;
-#endif
-
 			/* Debugging code used to check that IP addresses
                          * obtained from the kernel are correct */
 
@@ -2414,14 +2245,8 @@
 			cfg.ip_options		= L_IP_LOCAL_ASSIG |
 						  R_IP_LOCAL_ASSIG | 
 						  ENABLE_IP;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			cfg.ip_local		= in_dev->ifa_list->ifa_local;
 			cfg.ip_remote		= in_dev->ifa_list->ifa_address;
-#else
-			cfg.ip_local		= dev->pa_addr;
-			cfg.ip_remote		= dev->pa_dstaddr;
-#endif
-
 			/* Debugging code used to check that IP addresses
                          * obtained from the kernel are correct */
                         NEX_PRINTK (KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n",
@@ -2431,8 +2256,6 @@
 	
 		case WANOPT_PPP_PEER:
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-
 			printk(KERN_INFO "%s: PPP IP Mode: PEER\n",card->devname);
 			cfg.ip_options		= L_IP_REMOTE_ASSIG | 
 						  R_IP_REMOTE_ASSIG | 
@@ -2441,16 +2264,6 @@
 			cfg.ip_remote		= 0x00;
 			break;
 
-#else
-
-			/* No PEER support for 2.0.X kernels, drop down to default
-   			 * condition */
-
-			printk(KERN_INFO "%s: ERROR, PEER mode is not supported in 2.0.X kernels\n",
-						card->devname);
-			
-#endif
-
 		default:
 			printk(KERN_INFO "%s: ERROR: Unsupported PPP Mode Selected\n",
 					card->devname);
@@ -3038,19 +2851,9 @@
 	ppp_private_area_t *ppp_priv_area = dev->priv;
 	int err;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct ifreq if_info;
 	struct sockaddr_in *if_data1, *if_data2;
 	mm_segment_t fs;
-#else
-#ifdef _DYNAMIC_ROUTE_20X_SUPPORT_
-        struct rtentry route;
-#endif
-#endif
-
-
-	
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 
 	/* Set Local and remote addresses */
 	memset(&if_info, 0, sizeof(if_info));
@@ -3074,39 +2877,6 @@
 
 	set_fs(fs);           /* restore old block */
 	
-#else
-	/* FIXME: Dynamic Routing in 2.0.X kernels is not
-         * supported. Sorry ! I'll come back to it when I get
-         * a chance. */
-	
-	printk(KERN_INFO "%s: ERROR, Dynamic routing is not supported in 2.0.X kernels\n",
-				card->devname);
-	printk(KERN_INFO "%s:        Please use the STATIC IP mode!\n",
-				card->devname);
-
-	err = 0;
-
-#ifdef _DYNAMIC_ROUTE_20X_SUPPORT_
-	dev->pa_dstaddr = ppp_priv_area->ip_remote;
-	dev->pa_addr = ppp_priv_area->ip_local;
-
-	memset(&route, 0, sizeof(route));
-	route.rt_dev = dev->name;
-	route.rt_flags = 0;
-	((struct sockaddr_in *)&(route.rt_dst))->sin_addr.s_addr =
-		dev->pa_dstaddr;
-	((struct sockaddr_in *)&(route.rt_dst))->sin_family = AF_INET;
-	((struct sockaddr_in *)&(route.rt_genmask))->sin_addr.s_addr =
-			0xFFFFFFFF;
-	((struct sockaddr_in *)&(route.rt_genmask))->sin_family =
-			AF_INET;
-	
-	err = ip_rt_new(&route);
-
-#endif
-
-#endif
-
 	if (err) {
 		printk (KERN_INFO "%s: Adding of route failed: %i\n",
 			card->devname,err);
@@ -3130,32 +2900,21 @@
 	long ip_addr;
 	int err;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         mm_segment_t fs;
 	struct ifreq if_info;
 	struct sockaddr_in *if_data1;
         struct in_device *in_dev = dev->ip_ptr;
         struct in_ifaddr *ifa = in_dev->ifa_list;	
-#else
-	unsigned long fs = 0;
-        struct rtentry route;
-#endif
-
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	ip_addr = ifa->ifa_local;
 
 	/* Set Local and remote addresses */
 	memset(&if_info, 0, sizeof(if_info));
 	strcpy(if_info.ifr_name, dev->name);
-#endif
-
 
 	fs = get_fs();
        	set_fs(get_ds());     /* get user space block */ 
 
-
-#if defined(LINUX_2_1) || defined(LINUX_2_4)	
 	/* Change the local ip address of the interface to 0.
 	 * This will also delete the destination route.
 	 */	
@@ -3163,26 +2922,6 @@
 	if_data1->sin_addr.s_addr = 0;
 	if_data1->sin_family = AF_INET;
 	err = devinet_ioctl( SIOCSIFADDR, &if_info );
-#else
-
-	ip_addr = dev->pa_addr;
-	dev->pa_dstaddr = 0;
-
-	memset(&route, 0, sizeof(route));
-	route.rt_dev = dev->name;
-	route.rt_flags = 0;
-	((struct sockaddr_in *)&(route.rt_dst))->sin_addr.s_addr =
-			dev->pa_dstaddr;
-	((struct sockaddr_in *)&(route.rt_dst))->sin_family = AF_INET;
-	((struct sockaddr_in *)&(route.rt_genmask))->sin_addr.s_addr =
-			0xFFFFFFFF;
-        ((struct sockaddr_in *)&(route.rt_genmask))->sin_family =
-			AF_INET;
-
-
-	err = ip_rt_kill(&route);
-
-#endif
 
         set_fs(fs);           /* restore old block */
 
@@ -3288,14 +3027,12 @@
 {
 	u32 src_ip_addr;
         u32 broadcast_ip_addr = 0;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         struct in_device *in_dev;
-#endif
+
         /* read the IP source address from the outgoing packet */
         src_ip_addr = *(u32 *)(skb->data + 12);
 
 	/* read the IP broadcast address for the device */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         in_dev = dev->ip_ptr;
         if(in_dev != NULL) {
                 struct in_ifaddr *ifa= in_dev->ifa_list;
@@ -3304,9 +3041,6 @@
                 else
                         return 0;
         }
-#else
-        broadcast_ip_addr = dev->pa_brdaddr;
-#endif
  
         /* check if the IP Source Address is a Broadcast address */
         if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {
@@ -3328,20 +3062,12 @@
 
 void s508_lock (sdla_t *card, unsigned long *smp_flags)
 {
-#if defined(__SMP__) || defined(LINUX_2_4)
 	spin_lock_irqsave(&card->wandev.lock, *smp_flags);
-#else
-	disable_irq(card->hw.irq);
-#endif                                                                     
 }
 
 void s508_unlock (sdla_t *card, unsigned long *smp_flags)
 {
-#if defined(__SMP__) || defined(LINUX_2_4)
         spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-#else
-	enable_irq(card->hw.irq);
-#endif           
 }
 
 static int read_connection_info (sdla_t *card)
diff -Nru a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c
--- a/drivers/net/wan/sdla_x25.c	Tue Feb 25 11:05:23 2003
+++ b/drivers/net/wan/sdla_x25.c	Thu Mar  6 09:25:30 2003
@@ -95,12 +95,7 @@
 #include <asm/atomic.h>
 #include <linux/delay.h>	/* Experimental delay */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
- #include <asm/uaccess.h>
-#else
- #include <asm/segment.h>
- #include <net/route.h>
-#endif
+#include <asm/uaccess.h>
 
 #include <linux/if.h>
 #include <linux/if_arp.h>
@@ -281,11 +276,7 @@
 	int ch_idx;
 	unsigned char enable_IPX;
 	unsigned long network_number;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct net_device_stats ifstats;	/* interface statistics */
-#else
-	struct enet_statistics ifstats;
-#endif	
 	unsigned short transmit_length;
 	unsigned short tx_offset;
 	char transmit_buffer[X25_CHAN_MTU+sizeof(x25api_hdr_t)];
@@ -369,9 +360,7 @@
 static int if_send (struct sk_buff* skb, netdevice_t* dev);
 static struct net_device_stats *if_stats (netdevice_t* dev);
 
-#ifdef LINUX_2_4
 static void if_tx_timeout (netdevice_t *dev);
-#endif
 
 /*=================================================  
  * 	Interrupt handlers 
@@ -792,9 +781,6 @@
 	
 	init_global_statistics(card);	
 
-#ifndef LINUX_2_4
-	card->u.x.x25_poll_task.next = NULL;
-#endif
 	card->u.x.x25_poll_task.sync=0;
 	card->u.x.x25_poll_task.routine = (void*)(void*)wpx_poll;
 	card->u.x.x25_poll_task.data = card;
@@ -1011,18 +997,8 @@
 		chan->network_number = 0xDEADBEEF;
 
 	/* prepare network device data space for registration */
-#ifdef LINUX_2_4
 	strcpy(dev->name,chan->name);
-#else
-	dev->name = (char *)kmalloc(strlen(chan->name) + 2, GFP_KERNEL); 
-	if(dev->name == NULL)
-	{
-		kfree(chan);
-		dev->priv = NULL;
-		return -ENOMEM;
-	}
-	sprintf(dev->name, "%s", chan->name);
-#endif
+
 	dev->init = &if_init;
 
 	init_x25_channel_struct(chan);
@@ -1124,9 +1100,6 @@
 	x25_channel_t* chan = dev->priv;
 	sdla_t* card = chan->card;
 	wan_device_t* wandev = &card->wandev;
-#ifdef LINUX_2_0
-	int i;
-#endif
 
 	/* Initialize device driver entry points */
 	dev->open		= &if_open;
@@ -1135,19 +1108,11 @@
 	dev->rebuild_header	= &if_rebuild_hdr;
 	dev->hard_start_xmit	= &if_send;
 	dev->get_stats		= &if_stats;
-
-#ifdef LINUX_2_4
 	dev->tx_timeout		= &if_tx_timeout;
 	dev->watchdog_timeo	= TX_TIMEOUT;
-#endif
 
 	/* Initialize media-specific parameters */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	dev->type		= ARPHRD_PPP;		/* ARP h/w type */
-#else
-        dev->family             = AF_INET;      /* address family */
-        dev->type               = ARPHRD_PPP;   /* no x25 type */
-#endif
 	dev->flags		|= IFF_POINTOPOINT;
 	dev->flags		|= IFF_NOARP;
 
@@ -1174,11 +1139,6 @@
         /* Set transmit buffer queue length */
         dev->tx_queue_len = 100;
 
-	/* Initialize socket buffers */
-#if !defined(LINUX_2_1) && !defined(LINUX_2_4)
-        for (i = 0; i < DEV_NUMBUFFS; ++i)
-                skb_queue_head_init(&dev->buffs[i]);
-#endif
 	/* FIXME Why are we doing this */
 	set_chan_state(dev, WAN_DISCONNECTED);
 	return 0;
@@ -1214,15 +1174,12 @@
 	struct timeval tv;
 	unsigned long smp_flags;
 	
-	if (is_dev_running(dev))
+	if (netif_running(dev))
 		return -EBUSY;
 
 	chan->tq_working = 0;
 
 	/* Initialize the task queue */
-#ifndef LINUX_2_4
-	chan->common.wanpipe_task.next = NULL;
-#endif
 	chan->common.wanpipe_task.sync = 0;
 	chan->common.wanpipe_task.routine = (void *)(void *)x25api_bh;
 	chan->common.wanpipe_task.data = dev;
@@ -1276,13 +1233,8 @@
 	do_gettimeofday( &tv );
 	chan->router_start_time = tv.tv_sec;
 
-#ifdef LINUX_2_4
 	netif_start_queue(dev);
-#else	
-	dev->interrupt = 0;
-	dev->tbusy = 0;
-	dev->start = 1;
-#endif
+
 	return 0;
 }
 
@@ -1314,10 +1266,7 @@
 	sdla_t* card = chan->card;
 	unsigned long smp_flags;
 	
-	stop_net_queue(dev);
-#ifndef LINUX_2_4
-	dev->start=0;
-#endif
+	netif_stop_queue(dev);
 
 	if ((chan->common.state == WAN_CONNECTED) || 
 	    (chan->common.state == WAN_CONNECTING)){
@@ -1336,7 +1285,7 @@
 		for (i=0; i<(MAX_BH_BUFF+1); i++){
 			skb = ((bh_data_t *)&chan->bh_head[i])->skb;
 			if (skb != NULL){
-                		wan_dev_kfree_skb(skb, FREE_READ);
+                		dev_kfree_skb_any(skb);
 			}
 		}
 		kfree(chan->bh_head);
@@ -1405,7 +1354,6 @@
 }
 
 
-#ifdef LINUX_2_4
 /*============================================================================
  * Handle transmit timeout event from netif watchdog
  */
@@ -1425,7 +1373,6 @@
 			card->devname, dev->name);
 	netif_wake_queue (dev);
 }
-#endif
 
 
 /*=========================================================================
@@ -1457,33 +1404,11 @@
 
 	++chan->if_send_stat.if_send_entry;
 
-#ifdef LINUX_2_4
 	netif_stop_queue(dev);
-#endif
 
 	/* No need to check frame length, since socket code
          * will perform the check for us */
 
-#ifndef LINUX_2_4
-	if (dev->tbusy){
-		netdevice_t *dev2;
-		
-		++chan->if_send_stat.if_send_tbusy;
-		if ((jiffies - chan->tick_counter) < (5*HZ)){
-			return 1;
-		}
-		printk(KERN_INFO "%s: Transmit time out %s!\n",
-			card->devname, dev->name);
-		
-		for( dev2 = card->wandev.dev; dev2; 
-		     dev2 = *((netdevice_t**)dev2->priv)){
-
-	        	dev2->tbusy = 0;
-		}
-		++chan->if_send_stat.if_send_tbusy_timeout;
-	}
-#endif
-
 	chan->tick_counter = jiffies;
 	
 	/* Critical region starts here */
@@ -1506,7 +1431,7 @@
                                 chan->if_send_stat.if_send_PIPE_request++;
 			}
                	}
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
 		S508_S514_unlock(card, &smp_flags);
 		return 0;
@@ -1518,7 +1443,7 @@
 			chan->transmit_length=0;
 			atomic_set(&chan->common.driver_busy,0);
 		}else{
-			stop_net_queue(dev);
+			netif_stop_queue(dev);
 			++card->u.x.tx_interrupts_pending;
 		        status->imask |= INTR_ON_TX_FRAME;
 			clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
@@ -1589,9 +1514,9 @@
 
 if_send_crit_exit:
 	
-       	wan_dev_kfree_skb(skb, FREE_WRITE);
+       	dev_kfree_skb_any(skb);
 
-	start_net_queue(dev);
+	netif_start_queue(dev);
 	clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
 	S508_S514_unlock(card, &smp_flags);
 	return 0;
@@ -1787,14 +1712,12 @@
 			++chan->ifstats.rx_dropped;
 			++card->wandev.stats.rx_dropped;
 			++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
-			wan_dev_kfree_skb(skb, FREE_READ);
+			dev_kfree_skb_any(skb);
 			return;
 		}		
 
 		++chan->ifstats.rx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 		chan->ifstats.rx_bytes += skb->len;
-#endif
 		
 
 		chan->rx_skb = NULL;
@@ -1814,7 +1737,7 @@
 	/* Decapsulate packet, if necessary */
 	if (!skb->protocol && !wanrouter_type_trans(skb, dev)){
 		/* can't decapsulate packet */
-                wan_dev_kfree_skb(skb, FREE_READ);
+                dev_kfree_skb_any(skb);
 		++chan->ifstats.rx_errors;
 		++chan->ifstats.rx_dropped;
 		++card->wandev.stats.rx_dropped;
@@ -1829,7 +1752,7 @@
 				if(chan_send(dev, skb->data, skb->len,0)){
 					chan->tx_skb = skb;
 				}else{
-                                        wan_dev_kfree_skb(skb, FREE_WRITE);
+                                        dev_kfree_skb_any(skb);
 					++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
 				}
 			}else{
@@ -1839,9 +1762,7 @@
 			}
 		}else{
 			skb->mac.raw = skb->data;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			chan->ifstats.rx_bytes += skb->len;
-#endif
 			++chan->ifstats.rx_packets;
 			++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack;
 			netif_rx(skb);
@@ -1898,7 +1819,7 @@
 
 	if (skb_tailroom(new_skb) < len){
 		/* No room for the packet. Call off the whole thing! */
-                wan_dev_kfree_skb(new_skb, FREE_READ);
+                dev_kfree_skb_any(new_skb);
 		if (chan->common.usedby == WANPIPE){
 			chan->rx_skb = NULL;
 			if (qdm & 0x01){ 
@@ -1985,12 +1906,12 @@
 				chan->transmit_length = 0;
 				atomic_set(&chan->common.driver_busy,0);
 				chan->tx_offset=0;
-				if (is_queue_stopped(dev)){
+				if (netif_queue_stopped(dev)){
 					if (chan->common.usedby == API){
-						start_net_queue(dev);
+						netif_start_queue(dev);
 						wakeup_sk_bh(dev);
 					}else{
-						wake_net_dev(dev);
+						netif_wake_queue(dev);
 					}
 				}
 				dev = move_dev_to_next(card,dev);
@@ -2092,12 +2013,12 @@
 
 	/* If we are in API mode, wakeup the 
          * sock BH handler, not the NET_BH */
-	if (is_queue_stopped(dev)){
+	if (netif_queue_stopped(dev)){
 		if (chan->common.usedby == API){
-			start_net_queue(dev);
+			netif_start_queue(dev);
 			wakeup_sk_bh(dev);
 		}else{
-			wake_net_dev(dev);
+			netif_wake_queue(dev);
 		}
 	}
 	return 0;
@@ -2342,11 +2263,7 @@
 
 static void trigger_x25_poll(sdla_t *card)
 {
-#ifdef LINUX_2_4
 	schedule_task(&card->u.x.x25_poll_task);
-#else
-	queue_task(&card->u.x.x25_poll_task, &tq_scheduler);
-#endif
 }
 
 /*====================================================================
@@ -3658,8 +3575,8 @@
 					chan->transmit_length=0;
 					atomic_set(&chan->common.driver_busy,0);
 					chan->tx_offset=0;
-					if (is_queue_stopped(dev)){
-						wake_net_dev(dev);
+					if (netif_queue_stopped(dev)){
+						netif_wake_queue(dev);
 					}
 				}
 				atomic_set(&chan->common.command,0);
@@ -3766,9 +3683,7 @@
 		case 0x00:	/* success */
 			chan->i_timeout_sofar = jiffies;
 
-#ifdef LINUX_2_4
 			dev->trans_start=jiffies;
-#endif
 			
 			if ((qdm & M_BIT) && !card->u.x.LAPB_hdlc){
 				if (!tx_intr){
@@ -3780,9 +3695,7 @@
 					chan->tx_offset += len;
 
 					++chan->ifstats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 					chan->ifstats.tx_bytes += len;
-#endif
 					
 					if (chan->tx_offset < orig_len){
 						setup_for_delayed_transmit (dev, buff, data_len);
@@ -3795,9 +3708,7 @@
                                          * be X number of times larger than max data size.
 					 */
 					++chan->ifstats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 					chan->ifstats.tx_bytes += len;
-#endif
 					
 					++chan->if_send_stat.if_send_bfr_passed_to_adptr;
 					chan->tx_offset += len;
@@ -3817,9 +3728,7 @@
 				}
 			}else{
 				++chan->ifstats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 				chan->ifstats.tx_bytes += len;
-#endif
 				++chan->if_send_stat.if_send_bfr_passed_to_adptr;
 				res=0;
 			}
@@ -4288,7 +4197,7 @@
 			if (chan->common.sk == NULL || chan->common.func == NULL){
 				printk(KERN_INFO "%s: BH: Socket disconnected, dropping\n",
 						card->devname);
-				wan_dev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb_any(skb);
 				x25api_bh_cleanup(dev);
 				++chan->ifstats.rx_dropped;
 				++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
@@ -4745,7 +4654,7 @@
 
 	if (card->func(skb,card->sk) < 0){
 		printk(KERN_INFO "%s: MAJOR ERROR: Failed to send up place call \n",card->devname);
-                wan_dev_kfree_skb(skb, FREE_READ);
+                dev_kfree_skb_any(skb);
 		return 1;
 	}
 
@@ -4912,7 +4821,7 @@
 	if (chan->common.func(skb,dev,chan->common.sk) < 0){
 		if (bh_enqueue(dev,skb)){
 			printk(KERN_INFO "%s: Dropping OOB MSG\n",card->devname);
-                	wan_dev_kfree_skb(skb, FREE_READ);
+                	dev_kfree_skb_any(skb);
 		}
 	}
 
@@ -4940,7 +4849,7 @@
 
 	if (skb_tailroom(new_skb) < len){
 		/* No room for the packet. Call off the whole thing! */
-                wan_dev_kfree_skb(new_skb, FREE_READ);
+                dev_kfree_skb_any(new_skb);
 		printk(KERN_INFO "%s: Listen: unexpectedly long packet sequence\n"
 			,card->devname);
 		*skb = NULL;
@@ -5448,9 +5357,9 @@
 	}
 
         if(udp_pkt_src == UDP_PKT_FRM_STACK){
-                wan_dev_kfree_skb(skb, FREE_WRITE);
+                dev_kfree_skb_any(skb);
 	}else{
-                wan_dev_kfree_skb(skb, FREE_READ);
+                dev_kfree_skb_any(skb);
 	}
 
         return(udp_pkt_stored);
diff -Nru a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c
--- a/drivers/net/wan/sdladrv.c	Wed May 22 11:16:37 2002
+++ b/drivers/net/wan/sdladrv.c	Sun Feb 16 16:22:42 2003
@@ -108,16 +108,8 @@
 #define _OUTB(port, byte)	(outb((byte),(port)))
 #define	SYSTEM_TICK		jiffies
 
+#include <linux/init.h>
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4) 
- #include <linux/init.h>
-#else
- #include <linux/bios32.h>/* BIOS32, PCI BIOS functions and definitions */
- #define ioremap vremap
- #define iounmap vfree
- extern void * vremap (unsigned long offset, unsigned long size);
- extern void vfree (void *addr);
-#endif
 
 #elif	defined(_SCO_UNIX_)	/****** SCO Unix ****************************/
 
@@ -381,9 +373,7 @@
  *		< 0	error
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4) 
 EXPORT_SYMBOL(sdla_setup);
-#endif
 
 int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len)
 {
@@ -528,9 +518,7 @@
  * Shut down SDLA: disable shared memory access and interrupts, stop CPU, etc.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_down);
-#endif
 
 int sdla_down (sdlahw_t* hw)
 {
@@ -572,7 +560,6 @@
                 *(char *)hw->vector = S514_CPU_HALT;
         	CPU_no = hw->S514_cpu_no[0];
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 		/* disable the PCI IRQ and disable memory access */
                 pci_read_config_dword(hw->pci_dev, PCI_INT_CONFIG, &int_config);
 	        int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A :	~PCI_DISABLE_IRQ_CPU_B;
@@ -585,22 +572,6 @@
 		else
                         pci_write_config_dword(hw->pci_dev, PCI_MAP1_DWORD,
 				PCI_CPU_B_MEM_DISABLE);
-#else
-                /* disable the PCI IRQ and disable memory access */
-             	pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func,
-			PCI_INT_CONFIG, &int_config);
-	        int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A :	~PCI_DISABLE_IRQ_CPU_B;
-        	pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func,
-			PCI_INT_CONFIG, int_config);
-                read_S514_int_stat(hw, &int_status);
-                S514_intack(hw, int_status);
-     		// disable PCI memory access
-		if(CPU_no == S514_CPU_A)
-	     		pcibios_write_config_dword(hw->pci_bus,hw->pci_dev_func,
-				PCI_MAP0_DWORD, PCI_CPU_A_MEM_DISABLE);
-		else
-                        pcibios_write_config_dword(hw->pci_bus,hw->pci_dev_func,							PCI_MAP1_DWORD, PCI_CPU_B_MEM_DISABLE);
-#endif
 
 		/* free up the allocated virtual memory */
  		iounmap((void *)hw->dpmbase);
@@ -618,9 +589,7 @@
  * Map shared memory window into SDLA address space.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_mapmem);
-#endif
 
 int sdla_mapmem (sdlahw_t* hw, unsigned long addr)
 {
@@ -681,9 +650,7 @@
  * Enable interrupt generation.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_inten);
-#endif
 
 int sdla_inten (sdlahw_t* hw)
 {
@@ -739,9 +706,7 @@
  * Disable interrupt generation.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_intde);
-#endif
 
 int sdla_intde (sdlahw_t* hw)
 {
@@ -796,9 +761,7 @@
  * Acknowledge SDLA hardware interrupt.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_intack);
-#endif
 
 int sdla_intack (sdlahw_t* hw)
 {
@@ -848,18 +811,11 @@
  * Acknowledge S514 hardware interrupt.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(S514_intack);
-#endif
 
 void S514_intack (sdlahw_t* hw, u32 int_status)
 {
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         pci_write_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);
-#else
-	pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func,
-                PCI_INT_STATUS, int_status);
-#endif
 }
 
 
@@ -867,18 +823,11 @@
  * Read the S514 hardware interrupt status.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(read_S514_int_stat);
-#endif
 
 void read_S514_int_stat (sdlahw_t* hw, u32* int_status)
 {
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	pci_read_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);
-#else
-        pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, PCI_INT_STATUS,
-		int_status);
-#endif
 }
 
 
@@ -886,9 +835,7 @@
  * Generate an interrupt to adapter's CPU.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_intr);
-#endif
 
 int sdla_intr (sdlahw_t* hw)
 {
@@ -932,9 +879,7 @@
  * o Return number of loops made, or 0 if command timed out.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_exec);
-#endif
 
 int sdla_exec (void* opflag)
 {
@@ -970,9 +915,7 @@
  * interrupt routines are accessing adapter shared memory.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_peek);
-#endif
 
 int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
 {
@@ -1054,9 +997,7 @@
  * interrupt routines are accessing adapter shared memory.
  */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(sdla_poke);
-#endif
  
 int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
 {
@@ -1961,20 +1902,11 @@
 	int number_S514_cards = 0;
 	u32 S514_mem_base_addr = 0;
 	u32 ut_u32;
-
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct pci_dev *pci_dev;
-#else
-	u8 ut_u8;
-#endif
 
 
 #ifdef CONFIG_PCI
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         if(!pci_present())
-#else
-	if(!pcibios_present())
-#endif
         {
                 printk(KERN_INFO "%s: PCI BIOS not present!\n", modname);
                 return 0;
@@ -2029,26 +1961,12 @@
 		}
 	}
 
-      #if defined(LINUX_2_4)
 	pci_dev = hw->pci_dev;
 	/* read the physical memory base address */
 	S514_mem_base_addr = (CPU_no == S514_CPU_A) ? 
 		(pci_dev->resource[1].start) :
 		(pci_dev->resource[2].start);
 	
-      #elif defined (LINUX_2_1)
-	pci_dev = hw->pci_dev;
-	/* read the physical memory base address */
-	S514_mem_base_addr = (CPU_no == S514_CPU_A) ? 
-		(pci_dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK) :
-		(pci_dev->base_address[2] & PCI_BASE_ADDRESS_MEM_MASK);
-	
-      #else
-	pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func,
-		(CPU_no == S514_CPU_A) ? PCI_MEM_BASE0_DWORD :
-		PCI_MEM_BASE1_DWORD, &S514_mem_base_addr);
-      #endif
-
 	printk(KERN_INFO "%s: S514 PCI memory at 0x%X\n",
 		modname, S514_mem_base_addr);
 	if(!S514_mem_base_addr) {
@@ -2060,24 +1978,14 @@
 	}
 
 	/* enable the PCI memory */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	pci_read_config_dword(pci_dev, 
 		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
 		&ut_u32);
 	pci_write_config_dword(pci_dev,
 		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
 		(ut_u32 | PCI_MEMORY_ENABLE));
-#else
-        pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func,
-		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
-		&ut_u32); 
-        pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func,
-		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
-		(ut_u32 | PCI_MEMORY_ENABLE));
-#endif
 
 	/* check the IRQ allocated and enable IRQ usage */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	if(!(hw->irq = pci_dev->irq)) {
 		printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n",
 			modname);
@@ -2099,29 +2007,6 @@
         ut_u32 |= (CPU_no == S514_CPU_A) ?
                 PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B;
         pci_write_config_dword(pci_dev, PCI_INT_CONFIG, ut_u32);
-#else
-	/* the INTPIN must not be 0 - if it is, then the S514 adapter is not */
-	/* configured for IRQ usage */
-	pcibios_read_config_byte(hw->pci_bus, hw->pci_dev_func,
-		PCI_INT_PIN_BYTE, &ut_u8);
-        if(!ut_u8) {
-                printk(KERN_INFO "%s: invalid setting for INTPIN on S514 card\n", modname);
-                printk(KERN_INFO "Please contact your Sangoma representative\n");
-                return 0;
-        }
-        pcibios_read_config_byte(hw->pci_bus, hw->pci_dev_func,
-		PCI_INT_LINE_BYTE, (unsigned char *)&hw->irq);
-        if(hw->irq == PCI_IRQ_NOT_ALLOCATED) {
-                printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n",
-			modname);
-                return 0;
-        }
-	pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, PCI_INT_CONFIG, &ut_u32);
-	ut_u32 |= (CPU_no == S514_CPU_A) ?
-		PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B;
-        pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func, 
-		PCI_INT_CONFIG, ut_u32);
-#endif
 
 	printk(KERN_INFO "%s: IRQ %d allocated to the S514 card\n",
 		modname, hw->irq);
@@ -2157,15 +2042,10 @@
 	char S514_found_in_slot = 0;
         u16 PCI_subsys_vendor;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         struct pci_dev *pci_dev = NULL;
-#else
-        int pci_index;
-#endif
  
        slot_no = hw->S514_slot_no;
   
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))
         	!= NULL) {
                 
@@ -2197,40 +2077,6 @@
                 }
         }
 
-#else
-	//LINUX VERSION 2.0.X 
-        for (pci_index = 0; pci_index < MAX_S514_CARDS; pci_index ++) {
-                if (pcibios_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_index,
-                        &hw->pci_bus, &hw->pci_dev_func)!=PCIBIOS_SUCCESSFUL) {
-                                break;
-                }
-                
-		pcibios_read_config_word(hw->pci_bus, hw->pci_dev_func,
-                        PCI_SUBSYS_VENDOR_WORD, &PCI_subsys_vendor);
-                
-		if (PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
-                        continue;
-                
-		if (find_first_S514_card)
-                        return(1);
-           	
-		number_S514_cards ++;
-		
-                printk(KERN_INFO "%s: S514 card found, bus #%d, slot #%d\n",
-                        modname, hw->pci_bus,
-                        ((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK));
-
-		if (hw->auto_pci_cfg){
-			hw->S514_slot_no = ((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK)
-			slot_no = hw->S514_slot_no;
-				
-		}else if (((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK) == slot_no) {
-                        S514_found_in_slot = 1;
-                        break;
-                }
-        }
-#endif
-
 	/* if no S514 adapter has been found, then exit */
         if (!number_S514_cards) {
                 printk(KERN_INFO "%s: Error, no S514 adapters found\n", modname);
@@ -2408,17 +2254,11 @@
         u16 PCI_subsys_vendor;
 	u16 PCI_card_type;
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
         struct pci_dev *pci_dev = NULL;
 	struct pci_bus *bus = NULL;
-#else
-        int pci_index;
-	u8 irq;
-#endif
  
        slot_no = 0;
   
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))
         	!= NULL) {
 		
@@ -2453,52 +2293,13 @@
 		}
         }
 
-#else
-        for (pci_index = 0; pci_index < MAX_S514_CARDS; pci_index ++) {
-		
-                if(pcibios_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_index,
-                        &hw->pci_bus, &hw->pci_dev_func)!=PCIBIOS_SUCCESSFUL) {
-                                break;
-                }
-                pcibios_read_config_word(hw->pci_bus, hw->pci_dev_func,
-                        PCI_SUBSYS_VENDOR_WORD, &PCI_subsys_vendor);
-                if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
-                        continue;
-		
-		pcibios_read_config_word(hw->pci_bus,hw->pci_dev_func,PCI_CARD_TYPE,
-                        &PCI_card_type);
-
-		pcibios_read_config_byte(hw->pci_bus, hw->pci_dev_func,
-				PCI_INT_LINE_BYTE, &irq);
-
-		/* A dual cpu card can support up to 4 physical connections,
-		 * where a single cpu card can support up to 2 physical
-		 * connections.  The FT1 card can only support a single 
-		 * connection, however we cannot distinguish between a Single
-		 * CPU card and an FT1 card. */
-		if (PCI_card_type == S514_DUAL_CPU){
-                	number_S514_cards += 4;
-			 printk(KERN_INFO "%s: S514-PCI card found, cpu(s) 2, bus #%d, slot #%d, irq #%d\n",
-                        	modname, hw->pci_bus,
-                        	((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK),irq);
-		}else{
-			printk(KERN_INFO "%s: S514-PCI card found, cpu(s) 1, bus #%d, slot #%d, irq #%d\n",
-                        	modname, hw->pci_bus,
-                        	((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK),irq);
-			number_S514_cards += 2;
-		}
-        }
-#endif
-
 	return number_S514_cards;
 
 }
 
 
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 EXPORT_SYMBOL(wanpipe_hw_probe);
-#endif
 
 unsigned wanpipe_hw_probe(void)
 {
diff -Nru a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c
--- a/drivers/net/wan/sdlamain.c	Tue Feb 25 11:05:23 2003
+++ b/drivers/net/wan/sdlamain.c	Thu Mar  6 09:25:30 2003
@@ -64,26 +64,10 @@
 #include <linux/sdlapci.h>
 #include <linux/if_wanpipe_common.h>
 
-#if defined(LINUX_2_4)
+#define netdevice_t struct net_device
 
- #include <asm/uaccess.h>	/* kernel <-> user copy */
- #include <linux/inetdevice.h>
- #define netdevice_t struct net_device 
-
-#elif defined(LINUX_2_1)
-
- #include <asm/uaccess.h>	/* kernel <-> user copy */
- #include <linux/inetdevice.h>
- #define netdevice_t struct device 
-
-#else
-
- #include <asm/segment.h>
- #define devinet_ioctl(x,y) dev_ioctl(x,y)
- #define netdevice_t struct device 
- #define test_and_set_bit set_bit
- typedef unsigned long mm_segment_t; 
-#endif
+#include <asm/uaccess.h>	/* kernel <-> user copy */
+#include <linux/inetdevice.h>
 
 #include <linux/ip.h>
 #include <net/route.h>
@@ -240,23 +224,12 @@
  * function, which will execute all pending,
  * tasks in wanpipe_tq_custom queue */
 
-#ifdef LINUX_2_4
 DECLARE_TASK_QUEUE(wanpipe_tq_custom);
 static struct tq_struct wanpipe_tq_task = 
 {
 	.routine = (void (*)(void *)) run_wanpipe_tq,
 	.data = &wanpipe_tq_custom
 };
-#else
-static struct tq_struct *wanpipe_tq_custom = NULL;
-static struct tq_struct wanpipe_tq_task = 
-{
-	NULL,
-	0,
-	(void *)(void *) run_wanpipe_tq,
-	&wanpipe_tq_custom
-};
-#endif
 
 static int wanpipe_bh_critical=0;
 
@@ -511,9 +484,7 @@
 	if (!card->configured){
 
 		/* Initialize the Spin lock */
-#if defined(__SMP__) || defined(LINUX_2_4) 
 		printk(KERN_INFO "%s: Initializing for SMP\n",wandev->name);
-#endif
 
 		/* Piggyback spin lock has already been initialized,
 		 * in check_s514/s508_conflicts() */
@@ -974,26 +945,13 @@
 	unsigned long smp_flags;
 	int err = 0;
 
-      #if defined(LINUX_2_1) || defined(LINUX_2_4)
 	if(copy_from_user((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t)))
 		return -EFAULT;
-      #else
-        if ((u_dump == NULL) ||
-            verify_area(VERIFY_READ, u_dump, sizeof(sdla_dump_t)))
-                return -EFAULT;
-        memcpy_fromfs((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t));
-      #endif
 		
 	if ((dump.magic != WANPIPE_MAGIC) ||
 	    (dump.offset + dump.length > card->hw.memory))
 		return -EINVAL;
 	
-      #ifdef LINUX_2_0
-        if ((dump.ptr == NULL) ||
-            verify_area(VERIFY_WRITE, dump.ptr, dump.length))
-                return -EFAULT;
-      #endif	
-
 	winsize = card->hw.dpmsize;
 
 	if(card->hw.type != SDLA_S514) {
@@ -1014,17 +972,13 @@
                                 break;
                         }
 			
-                      #if defined(LINUX_2_1) || defined(LINUX_2_4)
                         if(copy_to_user((void *)dump.ptr,
                                 (u8 *)card->hw.dpmbase + pos, len)){ 
 				
 				unlock_adapter_irq(&card->wandev.lock, &smp_flags);
 				return -EFAULT;
 			}
-                      #else
-			memcpy_tofs((void*)(dump.ptr),
-                        	(void*)(card->hw.dpmbase + pos), len);
-                      #endif
+
                         dump.length     -= len;
                         dump.offset     += len;
                         (char*)dump.ptr += len;
@@ -1035,15 +989,10 @@
         
 	}else {
 
-	     #if defined(LINUX_2_1) || defined(LINUX_2_4) 
                if(copy_to_user((void *)dump.ptr,
 			       (u8 *)card->hw.dpmbase + dump.offset, dump.length)){
 			return -EFAULT;
 		}
-             #else
-                memcpy_tofs((void*)(dump.ptr),
-                (void*)(card->hw.dpmbase + dump.offset), dump.length);
-             #endif
 	}
 
 	return err;
@@ -1064,15 +1013,8 @@
 		return -ENODEV;
 	}
 
-      #if defined(LINUX_2_1) || defined(LINUX_2_4)	
 	if(copy_from_user((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t)))
 		return -EFAULT;
-      #else
-        if ((u_exec == NULL) ||
-            verify_area(VERIFY_READ, u_exec, sizeof(sdla_exec_t)))
-                return -EFAULT;
-        memcpy_fromfs((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t));
-      #endif
 
 	if ((exec.magic != WANPIPE_MAGIC) || (exec.cmd == NULL))
 		return -EINVAL;
@@ -1345,60 +1287,33 @@
 unsigned long get_ip_address (netdevice_t *dev, int option)
 {
 	
-      #ifdef LINUX_2_4
 	struct in_ifaddr *ifaddr;
 	struct in_device *in_dev;
 
 	if ((in_dev = __in_dev_get(dev)) == NULL){
 		return 0;
 	}
-      #elif defined(LINUX_2_1)
-	struct in_ifaddr *ifaddr;
-	struct in_device *in_dev;
-	
-	if ((in_dev = dev->ip_ptr) == NULL){
-		return 0;
-	}
-      #endif
 
-      #if defined(LINUX_2_1) || defined(LINUX_2_4)
 	if ((ifaddr = in_dev->ifa_list)== NULL ){
 		return 0;
 	}
-      #endif
 	
 	switch (option){
 
 	case WAN_LOCAL_IP:
-	      #ifdef LINUX_2_0
-		return dev->pa_addr;
-	      #else	
 		return ifaddr->ifa_local;
-	      #endif	
 		break;
 	
 	case WAN_POINTOPOINT_IP:
-	      #ifdef LINUX_2_0
-		return dev->pa_dstaddr;
-	      #else	
 		return ifaddr->ifa_address;
-	      #endif	
 		break;	
 
 	case WAN_NETMASK_IP:
-	      #ifdef LINUX_2_0
-		return dev->pa_mask;
-	      #else	
 		return ifaddr->ifa_mask;
-	      #endif	
 		break;
 
 	case WAN_BROADCAST_IP:
-	      #ifdef LINUX_2_0
-		return dev->pa_brdaddr;
-	      #else	
 		return ifaddr->ifa_broadcast;
-	      #endif	
 		break;
 	default:
 		return 0;
@@ -1431,11 +1346,7 @@
 
 	oldfs = get_fs();
 	set_fs(get_ds());
-      #if defined(LINUX_2_1) || defined(LINUX_2_4)
 	res = ip_rt_ioctl(SIOCADDRT,&route);
-      #else
-	res = ip_rt_new(&route);
-      #endif
 	set_fs(oldfs);
 
 	if (res == 0){
diff -Nru a/drivers/net/wan/wanpipe_multppp.c b/drivers/net/wan/wanpipe_multppp.c
--- a/drivers/net/wan/wanpipe_multppp.c	Mon Feb 24 09:56:18 2003
+++ b/drivers/net/wan/wanpipe_multppp.c	Thu Mar  6 09:25:30 2003
@@ -42,19 +42,11 @@
 #include <linux/if_wanpipe.h>		
 
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
-  #include <linux/inetdevice.h>
-  #include <asm/uaccess.h>
+#include <linux/inetdevice.h>
+#include <asm/uaccess.h>
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
- #include <net/syncppp.h>
-#else
- #include "syncppp.h"
-#endif
+#include <net/syncppp.h>
 
-#else
-  #include <net/route.h>          /* Adding new route entries */
-#endif
 
 /****** Defines & Macros ****************************************************/
 
@@ -148,15 +140,9 @@
 static int if_open   (netdevice_t* dev);
 static int if_close  (netdevice_t* dev);
 static int if_send (struct sk_buff* skb, netdevice_t* dev);
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static struct net_device_stats* if_stats (netdevice_t* dev);
-#else
-static struct enet_statistics* if_stats (netdevice_t* dev);
-#endif
 
-#ifdef LINUX_2_4
 static void if_tx_timeout (netdevice_t *dev);
-#endif
 
 /* CHDLC Firmware interface functions */
 static int chdlc_configure 	(sdla_t* card, void* data);
@@ -601,18 +587,8 @@
 
 	/* prepare network device data space for registration */
 
-#ifdef LINUX_2_4
 	strcpy(dev->name,card->u.c.if_name);
-#else
-	dev->name = (char *)kmalloc(strlen(card->u.c.if_name) + 2, GFP_KERNEL); 
-	if(dev->name == NULL)
-	{
-		kfree(chdlc_priv_area);	
-		return -ENOMEM;
-	}
-	sprintf(dev->name, "%s", card->u.c.if_name);
-#endif
-	
+
 	/* Attach PPP protocol layer to pppdev
 	 * The sppp_attach() will initilize the dev structure
          * and setup ppp layer protocols.
@@ -620,11 +596,7 @@
          *        if_open(), if_close(), if_send() and get_stats() functions.
          */
 	sppp_attach(pppdev);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16)
 	dev = pppdev->dev;
-#else
-	dev = &pppdev->dev;
-#endif
 	sp = &pppdev->sppp;
 	
 	/* Enable PPP Debugging */
@@ -684,9 +656,6 @@
 	chdlc_private_area_t* chdlc_priv_area = dev->priv;
 	sdla_t* card = chdlc_priv_area->card;
 	wan_device_t* wandev = &card->wandev;
-#ifdef LINUX_2_0
-	int i;
-#endif
 	
 	/* NOTE: Most of the dev initialization was
          *       done in sppp_attach(), called by new_if() 
@@ -699,16 +668,10 @@
 	dev->stop		= &if_close;
 	dev->hard_start_xmit	= &if_send;
 	dev->get_stats		= &if_stats;
-#ifdef LINUX_2_4
 	dev->tx_timeout		= &if_tx_timeout;
 	dev->watchdog_timeo	= TX_TIMEOUT;
-#endif
 
 
-#ifdef LINUX_2_0
-	dev->family		= AF_INET;
-#endif	
- 
 	/* Initialize hardware parameters */
 	dev->irq	= wandev->irq;
 	dev->dma	= wandev->dma;
@@ -724,17 +687,10 @@
 	 */
         dev->tx_queue_len = 100;
    
-	/* Initialize socket buffers */
-#if !defined(LINUX_2_1) && !defined(LINUX_2_4)
-        for (i = 0; i < DEV_NUMBUFFS; ++i)
-                skb_queue_head_init(&dev->buffs[i]);
-#endif
-
 	return 0;
 }
 
 
-#ifdef LINUX_2_4
 /*============================================================================
  * Handle transmit timeout event from netif watchdog
  */
@@ -754,8 +710,6 @@
 	printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);
 	netif_wake_queue (dev);
 }
-#endif
-
 
 
 /*============================================================================
@@ -773,14 +727,8 @@
 	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
 
 	/* Only one open per interface is allowed */
-
-#ifdef LINUX_2_4
 	if (netif_running(dev))
 		return -EBUSY;
-#else
-	if (dev->start)
-		return -EBUSY;		/* only one open is allowed */
-#endif
 
 	/* Start PPP Layer */
 	if (sppp_open(dev)){
@@ -790,13 +738,7 @@
 	do_gettimeofday(&tv);
 	chdlc_priv_area->router_start_time = tv.tv_sec;
  
-#ifdef LINUX_2_4
 	netif_start_queue(dev);
-#else
-	dev->interrupt = 0;
-	dev->tbusy = 0;
-	dev->start = 1;
-#endif
 	
 	wanpipe_open(card);
 
@@ -817,11 +759,7 @@
 
 	/* Stop the PPP Layer */
 	sppp_close(dev);
-	stop_net_queue(dev);
-
-#ifndef LINUX_2_4
-	dev->start=0;
-#endif
+	netif_stop_queue(dev);
 
 	wanpipe_close(card);
 	
@@ -855,9 +793,7 @@
 	unsigned long smp_flags;
 	int err=0;
 
-#ifdef LINUX_2_4
 	netif_stop_queue(dev);
-#endif
 
 	
 	if (skb == NULL){
@@ -867,32 +803,10 @@
 		printk(KERN_INFO "%s: Received NULL skb buffer! interface %s got kicked!\n",
 			card->devname, dev->name);
 
-		wake_net_dev(dev);
+		netif_wake_queue(dev);
 		return 0;
 	}
 
-#ifndef LINUX_2_4
-	if (dev->tbusy){
-
-		/* If our device stays busy for at least 5 seconds then we will
-		 * kick start the device by making dev->tbusy = 0.  We expect 
-		 * that our device never stays busy more than 5 seconds. So this
-		 * is only used as a last resort. 
-		 */
-                ++card->wandev.stats.collisions;
-
-		if((jiffies - chdlc_priv_area->tick_counter) < (5 * HZ)) {
-			return 1;
-		}
-
-		printk (KERN_INFO "%s: Transmit (tbusy) timeout !\n",
-			card->devname);
-
-		/* unbusy the interface */
-		dev->tbusy = 0;
-	}
-#endif
-
    	if (ntohs(skb->protocol) != htons(PVC_PROT)){
 		/* check the udp packet type */
 		
@@ -903,7 +817,7 @@
 				chdlc_int->interrupt_permission |=
 					APP_INT_ON_TIMER;
 			}
-			start_net_queue(dev);
+			netif_start_queue(dev);
 			return 0;
 		}
         }
@@ -918,33 +832,29 @@
 		printk(KERN_INFO "%s: Critical in if_send: %lx\n",
 					card->wandev.name,card->wandev.critical);
                 ++card->wandev.stats.tx_dropped;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		goto if_send_crit_exit;
 	}
 
 	if (card->wandev.state != WAN_CONNECTED){
 		++card->wandev.stats.tx_dropped;
-		start_net_queue(dev);
+		netif_start_queue(dev);
 		goto if_send_crit_exit;
 	}
 	
 	if (chdlc_send(card, skb->data, skb->len)){
-		stop_net_queue(dev);
+		netif_stop_queue(dev);
 
 	}else{
 		++card->wandev.stats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
        		card->wandev.stats.tx_bytes += skb->len;
-#endif
-#ifdef LINUX_2_4
 		dev->trans_start = jiffies;
-#endif
-		start_net_queue(dev);
+		netif_start_queue(dev);
 	}	
 
 if_send_crit_exit:
-	if (!(err=is_queue_stopped(dev))){
-                wan_dev_kfree_skb(skb, FREE_WRITE);
+	if (!(err=netif_queue_stopped(dev))){
+                dev_kfree_skb_any(skb);
 	}else{
 		chdlc_priv_area->tick_counter = jiffies;
 		chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
@@ -1063,7 +973,6 @@
  * Get ethernet-style interface statistics.
  * Return a pointer to struct enet_statistics.
  */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 static struct net_device_stats* if_stats (netdevice_t* dev)
 {
 	sdla_t *my_card;
@@ -1079,23 +988,7 @@
 	my_card = chdlc_priv_area->card;
 	return &my_card->wandev.stats; 
 }
-#else
-static struct enet_statistics* if_stats (netdevice_t* dev)
-{
-        sdla_t *my_card;
-        chdlc_private_area_t* chdlc_priv_area = dev->priv;
 
-	/* Shutdown bug fix. In del_if() we kill
-         * dev->priv pointer. This function, gets
-         * called after del_if(), thus check
-         * if pointer has been deleted */
-	if ((chdlc_priv_area=dev->priv) == NULL)
-		return NULL;
-
-        my_card = chdlc_priv_area->card;
-        return &my_card->wandev.stats;
-}
-#endif
 
 /****** Cisco HDLC Firmware Interface Functions *******************************/
 
@@ -1417,7 +1310,7 @@
 			flags->interrupt_info_struct.interrupt_permission &=
 				 ~APP_INT_ON_TX_FRAME;
 
-			wake_net_dev(dev);
+			netif_wake_queue(dev);
 			break;
 
 		case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */
@@ -1505,15 +1398,9 @@
 		goto rx_exit;
 	}
 	
-#ifdef LINUX_2_4
 	if (!netif_running(dev)){
 		goto rx_exit;
 	}
-#else
-	if (!dev->start){ 
-		goto rx_exit;
-	}
-#endif
 
 	chdlc_priv_area = dev->priv;
 
@@ -1555,9 +1442,7 @@
 	skb->protocol = htons(ETH_P_WAN_PPP);
 
 	card->wandev.stats.rx_packets ++;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	card->wandev.stats.rx_bytes += skb->len;
-#endif
 	udp_type = udp_pkt_type( skb, card );
 
 	if(udp_type == UDP_CPIPE_TYPE) {
@@ -1795,9 +1680,9 @@
 	}
 
 	if(udp_pkt_src == UDP_PKT_FRM_STACK)
-		wan_dev_kfree_skb(skb, FREE_WRITE);
+		dev_kfree_skb_any(skb);
 	else
-                wan_dev_kfree_skb(skb, FREE_READ);
+                dev_kfree_skb_any(skb);
 	
 	return(udp_pkt_stored);
 }
@@ -2156,9 +2041,7 @@
      	if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
 		if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) {
 			++ card->wandev.stats.tx_packets;
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 			card->wandev.stats.tx_bytes += len;
-#endif
 		}
 	} else {	
 	
@@ -2360,28 +2243,20 @@
 
 void s508_lock (sdla_t *card, unsigned long *smp_flags)
 {
-#if defined(__SMP__) || defined(LINUX_2_4)
 	spin_lock_irqsave(&card->wandev.lock, *smp_flags);
         if (card->next){
 		/* It is ok to use spin_lock here, since we
 		 * already turned off interrupts */
         	spin_lock(&card->next->wandev.lock);
 	}
-#else
-	disable_irq(card->hw.irq);
-#endif
 }
 
 void s508_unlock (sdla_t *card, unsigned long *smp_flags)
 {
-#if defined(__SMP__) || defined(LINUX_2_4)
 	if (card->next){
 		spin_unlock(&card->next->wandev.lock);
 	}
 	spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-#else
-	enable_irq(card->hw.irq);
-#endif           
 }
 
 
diff -Nru a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
--- a/drivers/oprofile/buffer_sync.c	Thu Feb 20 10:06:22 2003
+++ b/drivers/oprofile/buffer_sync.c	Sun Mar  2 22:46:44 2003
@@ -277,10 +277,7 @@
  */
 static struct mm_struct * take_task_mm(struct task_struct * task)
 {
-	struct mm_struct * mm;
-	task_lock(task);
-	mm = task->mm;
-	task_unlock(task);
+	struct mm_struct * mm = task->mm;
  
 	/* if task->mm !NULL, mm_count must be at least 1. It cannot
 	 * drop to 0 without the task exiting, which will have to sleep
@@ -310,6 +307,32 @@
 }
  
 
+/* compute number of filled slots in cpu_buffer queue */
+static unsigned long nr_filled_slots(struct oprofile_cpu_buffer * b)
+{
+	unsigned long head = b->head_pos;
+	unsigned long tail = b->tail_pos;
+
+	if (head >= tail)
+		return head - tail;
+
+	return head + (b->buffer_size - tail);
+}
+
+
+static void increment_tail(struct oprofile_cpu_buffer * b)
+{
+	unsigned long new_tail = b->tail_pos + 1;
+
+	rmb();
+
+	if (new_tail < (b->buffer_size))
+		b->tail_pos = new_tail;
+	else
+		b->tail_pos = 0;
+}
+
+
 /* Sync one of the CPU's buffers into the global event buffer.
  * Here we need to go through each batch of samples punctuated
  * by context switch notes, taking the task's mmap_sem and doing
@@ -322,10 +345,14 @@
 	struct task_struct * new;
 	unsigned long cookie;
 	int in_kernel = 1;
-	int i;
+	unsigned int i;
  
-	for (i=0; i < cpu_buf->pos; ++i) {
-		struct op_sample * s = &cpu_buf->buffer[i];
+	/* Remember, only we can modify tail_pos */
+
+	unsigned long const available_elements = nr_filled_slots(cpu_buf);
+  
+	for (i=0; i < available_elements; ++i) {
+		struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos];
  
 		if (is_ctx_switch(s->eip)) {
 			if (s->event <= 1) {
@@ -345,6 +372,8 @@
 		} else {
 			add_sample(mm, s, in_kernel);
 		}
+
+		increment_tail(cpu_buf);
 	}
 	release_mm(mm);
 
@@ -369,17 +398,8 @@
  
 		cpu_buf = &cpu_buffer[i];
  
-		/* We take a spin lock even though we might
-		 * sleep. It's OK because other users are try
-		 * lockers only, and this region is already
-		 * protected by buffer_sem. It's raw to prevent
-		 * the preempt bogometer firing. Fruity, huh ? */
-		if (cpu_buf->pos > 0) {
-			_raw_spin_lock(&cpu_buf->int_lock);
-			add_cpu_switch(i);
-			sync_buffer(cpu_buf);
-			_raw_spin_unlock(&cpu_buf->int_lock);
-		}
+		add_cpu_switch(i);
+		sync_buffer(cpu_buf);
 	}
 
 	up(&buffer_sem);
diff -Nru a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
--- a/drivers/oprofile/cpu_buffer.c	Thu Jan 23 12:24:53 2003
+++ b/drivers/oprofile/cpu_buffer.c	Thu Mar  6 08:24:34 2003
@@ -26,8 +26,6 @@
 
 struct oprofile_cpu_buffer cpu_buffer[NR_CPUS] __cacheline_aligned;
 
-static unsigned long buffer_size;
- 
 static void __free_cpu_buffers(int num)
 {
 	int i;
@@ -47,7 +45,7 @@
 {
 	int i;
  
-	buffer_size = fs_cpu_buffer_size;
+	unsigned long buffer_size = fs_cpu_buffer_size;
  
 	for (i=0; i < NR_CPUS; ++i) {
 		struct oprofile_cpu_buffer * b = &cpu_buffer[i];
@@ -59,12 +57,12 @@
 		if (!b->buffer)
 			goto fail;
  
-		spin_lock_init(&b->int_lock);
-		b->pos = 0;
 		b->last_task = 0;
 		b->last_is_kernel = -1;
+		b->buffer_size = buffer_size;
+		b->tail_pos = 0;
+		b->head_pos = 0;
 		b->sample_received = 0;
-		b->sample_lost_locked = 0;
 		b->sample_lost_overflow = 0;
 		b->sample_lost_task_exit = 0;
 	}
@@ -80,11 +78,38 @@
 	__free_cpu_buffers(NR_CPUS);
 }
 
- 
-/* Note we can't use a semaphore here as this is supposed to
- * be safe from any context. Instead we trylock the CPU's int_lock.
- * int_lock is taken by the processing code in sync_cpu_buffers()
- * so we avoid disturbing that.
+
+/* compute number of available slots in cpu_buffer queue */
+static unsigned long nr_available_slots(struct oprofile_cpu_buffer const * b)
+{
+	unsigned long head = b->head_pos;
+	unsigned long tail = b->tail_pos;
+
+	if (tail > head)
+		return tail - head;
+
+	return tail + (b->buffer_size - head);
+}
+
+
+static void increment_head(struct oprofile_cpu_buffer * b)
+{
+	unsigned long new_head = b->head_pos + 1;
+
+	/* Ensure anything written to the slot before we
+	 * increment is visible */
+	wmb();
+
+	if (new_head < (b->buffer_size))
+		b->head_pos = new_head;
+	else
+		b->head_pos = 0;
+}
+
+
+/* This must be safe from any context. It's safe writing here
+ * because of the head/tail separation of the writer and reader
+ * of the CPU buffer.
  *
  * is_kernel is needed because on some architectures you cannot
  * tell if you are in kernel or user space simply by looking at
@@ -101,14 +126,10 @@
 
 	cpu_buf->sample_received++;
  
-	if (!spin_trylock(&cpu_buf->int_lock)) {
-		cpu_buf->sample_lost_locked++;
-		return;
-	}
 
-	if (cpu_buf->pos > buffer_size - 2) {
+	if (nr_available_slots(cpu_buf) < 3) {
 		cpu_buf->sample_lost_overflow++;
-		goto out;
+		return;
 	}
 
 	task = current;
@@ -116,18 +137,18 @@
 	/* notice a switch from user->kernel or vice versa */
 	if (cpu_buf->last_is_kernel != is_kernel) {
 		cpu_buf->last_is_kernel = is_kernel;
-		cpu_buf->buffer[cpu_buf->pos].eip = ~0UL;
-		cpu_buf->buffer[cpu_buf->pos].event = is_kernel;
-		cpu_buf->pos++;
+		cpu_buf->buffer[cpu_buf->head_pos].eip = ~0UL;
+		cpu_buf->buffer[cpu_buf->head_pos].event = is_kernel;
+		increment_head(cpu_buf);
 	}
 
 	/* notice a task switch */
 	if (cpu_buf->last_task != task) {
 		cpu_buf->last_task = task;
 		if (!(task->flags & PF_EXITING)) {
-			cpu_buf->buffer[cpu_buf->pos].eip = ~0UL;
-			cpu_buf->buffer[cpu_buf->pos].event = (unsigned long)task;
-			cpu_buf->pos++;
+			cpu_buf->buffer[cpu_buf->head_pos].eip = ~0UL;
+			cpu_buf->buffer[cpu_buf->head_pos].event = (unsigned long)task;
+			increment_head(cpu_buf);
 		}
 	}
  
@@ -138,23 +159,20 @@
 	 */
 	if (task->flags & PF_EXITING) {
 		cpu_buf->sample_lost_task_exit++;
-		goto out;
+		return;
 	}
  
-	cpu_buf->buffer[cpu_buf->pos].eip = eip;
-	cpu_buf->buffer[cpu_buf->pos].event = event;
-	cpu_buf->pos++;
-out:
-	spin_unlock(&cpu_buf->int_lock);
+	cpu_buf->buffer[cpu_buf->head_pos].eip = eip;
+	cpu_buf->buffer[cpu_buf->head_pos].event = event;
+	increment_head(cpu_buf);
 }
 
+
 /* resets the cpu buffer to a sane state - should be called with 
  * cpu_buf->int_lock held
  */
 void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf)
 {
-	cpu_buf->pos = 0;
-
 	/* reset these to invalid values; the next sample
 	 * collected will populate the buffer with proper
 	 * values to initialize the buffer
@@ -162,4 +180,3 @@
 	cpu_buf->last_is_kernel = -1;
 	cpu_buf->last_task = 0;
 }
-
diff -Nru a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h
--- a/drivers/oprofile/cpu_buffer.h	Thu Jan 23 12:24:53 2003
+++ b/drivers/oprofile/cpu_buffer.h	Wed Mar  5 13:56:22 2003
@@ -30,14 +30,13 @@
 };
  
 struct oprofile_cpu_buffer {
-	spinlock_t int_lock;
-	/* protected by int_lock */
-	unsigned long pos;
+	volatile unsigned long head_pos;
+	volatile unsigned long tail_pos;
+	unsigned long buffer_size;
 	struct task_struct * last_task;
 	int last_is_kernel;
 	struct op_sample * buffer;
 	unsigned long sample_received;
-	unsigned long sample_lost_locked;
 	unsigned long sample_lost_overflow;
 	unsigned long sample_lost_task_exit;
 } ____cacheline_aligned;
diff -Nru a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c
--- a/drivers/oprofile/oprofile_stats.c	Sun Dec 22 04:53:01 2002
+++ b/drivers/oprofile/oprofile_stats.c	Tue Feb 25 05:56:06 2003
@@ -27,7 +27,6 @@
 
 		cpu_buf = &cpu_buffer[i]; 
 		cpu_buf->sample_received = 0;
-		cpu_buf->sample_lost_locked = 0;
 		cpu_buf->sample_lost_overflow = 0;
 		cpu_buf->sample_lost_task_exit = 0;
 	}
@@ -63,8 +62,6 @@
 		 */
 		oprofilefs_create_ro_ulong(sb, cpudir, "sample_received",
 			&cpu_buf->sample_received);
-		oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_locked",
-			&cpu_buf->sample_lost_locked);
 		oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_overflow",
 			&cpu_buf->sample_lost_overflow);
 		oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_task_exit",
diff -Nru a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c
--- a/drivers/parport/ieee1284.c	Mon Nov 18 14:18:05 2002
+++ b/drivers/parport/ieee1284.c	Wed Mar  5 21:39:37 2003
@@ -170,7 +170,7 @@
 {
 	int ret;
 	int usec;
-	long deadline;
+	unsigned long deadline;
 	unsigned char status;
 
 	usec = port->physport->spintime; /* usecs of fast polling */
diff -Nru a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c
--- a/drivers/parport/ieee1284_ops.c	Sat Nov 23 06:29:46 2002
+++ b/drivers/parport/ieee1284_ops.c	Wed Mar  5 21:39:37 2003
@@ -58,7 +58,7 @@
 	parport_write_control (port, ctl);
 	parport_data_forward (port);
 	while (count < len) {
-		long expire = jiffies + dev->timeout;
+		unsigned long expire = jiffies + dev->timeout;
 		long wait = (HZ + 99) / 100;
 		unsigned char mask = (PARPORT_STATUS_ERROR
 				      | PARPORT_STATUS_BUSY);
@@ -431,7 +431,7 @@
 			      | PARPORT_CONTROL_INIT,
 			      PARPORT_CONTROL_INIT);
 	for (written = 0; written < len; written++, buf++) {
-		long expire = jiffies + port->cad->timeout;
+		unsigned long expire = jiffies + port->cad->timeout;
 		unsigned char byte;
 
 		byte = *buf;
@@ -520,7 +520,7 @@
 	parport_write_control (port,
 			       ctl | PARPORT_CONTROL_AUTOFD);
 	while (count < len) {
-		long expire = jiffies + dev->timeout;
+		unsigned long expire = jiffies + dev->timeout;
 		unsigned char byte;
 		int command;
 
@@ -668,7 +668,7 @@
 			      PARPORT_CONTROL_AUTOFD
 			      | PARPORT_CONTROL_INIT);
 	for (written = 0; written < len; written++, buf++) {
-		long expire = jiffies + port->cad->timeout;
+		unsigned long expire = jiffies + port->cad->timeout;
 		unsigned char byte;
 
 		byte = *buf;
diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile
--- a/drivers/pci/Makefile	Tue Feb 18 18:58:56 2003
+++ b/drivers/pci/Makefile	Sat Mar  1 07:41:20 2003
@@ -2,7 +2,7 @@
 # Makefile for the PCI bus specific drivers.
 #
 
-obj-y		+= access.o probe.o pci.o pool.o quirks.o \
+obj-y		+= access.o bus.o probe.o pci.o pool.o quirks.o \
 			names.o pci-driver.o search.o hotplug.o \
 			pci-sysfs.o
 obj-$(CONFIG_PM)  += power.o
diff -Nru a/drivers/pci/bus.c b/drivers/pci/bus.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/bus.c	Mon Mar  3 13:26:41 2003
@@ -0,0 +1,127 @@
+/*
+ *	drivers/pci/bus.c
+ *
+ * From setup-res.c, by:
+ *	Dave Rusling (david.rusling@reo.mts.dec.com)
+ *	David Mosberger (davidm@cs.arizona.edu)
+ *	David Miller (davem@redhat.com)
+ *	Ivan Kokshaysky (ink@jurassic.park.msu.ru)
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+
+#include "pci.h"
+
+/**
+ * pci_bus_alloc_resource - allocate a resource from a parent bus
+ * @bus: PCI bus
+ * @res: resource to allocate
+ * @size: size of resource to allocate
+ * @align: alignment of resource to allocate
+ * @min: minimum /proc/iomem address to allocate
+ * @type_mask: IORESOURCE_* type flags
+ * @alignf: resource alignment function
+ * @alignf_data: data argument for resource alignment function
+ *
+ * Given the PCI bus a device resides on, the size, minimum address,
+ * alignment and type, try to find an acceptable resource allocation
+ * for a specific device resource.
+ */
+int
+pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
+	unsigned long size, unsigned long align, unsigned long min,
+	unsigned int type_mask,
+	void (*alignf)(void *, struct resource *,
+			unsigned long, unsigned long),
+	void *alignf_data)
+{
+	int i, ret = -ENOMEM;
+
+	type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
+
+	for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
+		struct resource *r = bus->resource[i];
+		if (!r)
+			continue;
+
+		/* type_mask must match */
+		if ((res->flags ^ r->flags) & type_mask)
+			continue;
+
+		/* We cannot allocate a non-prefetching resource
+		   from a pre-fetching area */
+		if ((r->flags & IORESOURCE_PREFETCH) &&
+		    !(res->flags & IORESOURCE_PREFETCH))
+			continue;
+
+		/* Ok, try it out.. */
+		ret = allocate_resource(r, res, size, min, -1, align,
+					alignf, alignf_data);
+		if (ret == 0)
+			break;
+	}
+	return ret;
+}
+
+/**
+ * pci_bus_add_devices - insert newly discovered PCI devices
+ * @bus: bus to check for new devices
+ *
+ * Add newly discovered PCI devices (which are on the bus->devices
+ * list) to the global PCI device list, add the sysfs and procfs
+ * entries.  Where a bridge is found, add the discovered bus to
+ * the parents list of child buses, and recurse.
+ *
+ * Call hotplug for each new devices.
+ */
+void __devinit pci_bus_add_devices(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		/*
+		 * Skip already-present devices (which are on the
+		 * global device list.)
+		 */
+		if (!list_empty(&dev->global_list))
+			continue;
+
+		device_register(&dev->dev);
+		list_add_tail(&dev->global_list, &pci_devices);
+#ifdef CONFIG_PROC_FS
+		pci_proc_attach_device(dev);
+#endif
+		pci_create_sysfs_dev_files(dev);
+
+		/*
+		 * If there is an unattached subordinate bus, attach
+		 * it and then scan for unattached PCI devices.
+		 */
+		if (dev->subordinate && list_empty(&dev->subordinate->node)) {
+			list_add_tail(&dev->subordinate->node, &dev->bus->children);
+			pci_bus_add_devices(dev->subordinate);
+		}
+	}
+}
+
+void pci_enable_bridges(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		if (dev->subordinate) {
+			pci_enable_device(dev);
+			pci_set_master(dev);
+			pci_enable_bridges(dev->subordinate);
+		}
+	}
+}
+
+EXPORT_SYMBOL(pci_bus_alloc_resource);
+EXPORT_SYMBOL(pci_bus_add_devices);
+EXPORT_SYMBOL(pci_enable_bridges);
diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c
--- a/drivers/pci/probe.c	Mon Feb 24 08:17:19 2003
+++ b/drivers/pci/probe.c	Tue Feb 25 15:47:51 2003
@@ -221,47 +221,64 @@
 	b = kmalloc(sizeof(*b), GFP_KERNEL);
 	if (b) {
 		memset(b, 0, sizeof(*b));
+		INIT_LIST_HEAD(&b->node);
 		INIT_LIST_HEAD(&b->children);
 		INIT_LIST_HEAD(&b->devices);
 	}
 	return b;
 }
 
-struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
+static struct pci_bus * __devinit
+pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
 {
 	struct pci_bus *child;
-	int i;
 
 	/*
 	 * Allocate a new bus, and inherit stuff from the parent..
 	 */
 	child = pci_alloc_bus();
 
-	list_add_tail(&child->node, &parent->children);
-	child->self = dev;
-	dev->subordinate = child;
-	child->parent = parent;
-	child->ops = parent->ops;
-	child->sysdata = parent->sysdata;
-	child->dev = &dev->dev;
+	if (child) {
+		int i;
 
-	/*
-	 * Set up the primary, secondary and subordinate
-	 * bus numbers.
-	 */
-	child->number = child->secondary = busnr;
-	child->primary = parent->secondary;
-	child->subordinate = 0xff;
-
-	/* Set up default resource pointers and names.. */
-	for (i = 0; i < 4; i++) {
-		child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
-		child->resource[i]->name = child->name;
+		child->self = bridge;
+		child->parent = parent;
+		child->ops = parent->ops;
+		child->sysdata = parent->sysdata;
+		child->dev = &bridge->dev;
+
+		/*
+		 * Set up the primary, secondary and subordinate
+		 * bus numbers.
+		 */
+		child->number = child->secondary = busnr;
+		child->primary = parent->secondary;
+		child->subordinate = 0xff;
+
+		/* Set up default resource pointers and names.. */
+		for (i = 0; i < 4; i++) {
+			child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i];
+			child->resource[i]->name = child->name;
+		}
+
+		bridge->subordinate = child;
 	}
 
 	return child;
 }
 
+struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
+{
+	struct pci_bus *child;
+
+	child = pci_alloc_child_bus(parent, dev, busnr);
+	if (child)
+		list_add_tail(&child->node, &parent->children);
+	return child;
+}
+
+static unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus);
+
 /*
  * If it's a bridge, configure it and scan the bus behind it.
  * For CardBus bridges, we don't scan behind as the devices will
@@ -288,12 +305,12 @@
 		 */
 		if (pass)
 			return max;
-		child = pci_add_new_bus(bus, dev, 0);
+		child = pci_alloc_child_bus(bus, dev, 0);
 		child->primary = buses & 0xFF;
 		child->secondary = (buses >> 8) & 0xFF;
 		child->subordinate = (buses >> 16) & 0xFF;
 		child->number = child->secondary;
-		cmax = pci_do_scan_bus(child);
+		cmax = pci_scan_child_bus(child);
 		if (cmax > max) max = cmax;
 	} else {
 		/*
@@ -306,18 +323,27 @@
 		/* Clear errors */
 		pci_write_config_word(dev, PCI_STATUS, 0xffff);
 
-		child = pci_add_new_bus(bus, dev, ++max);
+		child = pci_alloc_child_bus(bus, dev, ++max);
 		buses = (buses & 0xff000000)
 		      | ((unsigned int)(child->primary)     <<  0)
 		      | ((unsigned int)(child->secondary)   <<  8)
 		      | ((unsigned int)(child->subordinate) << 16);
+
+		/*
+		 * yenta.c forces a secondary latency timer of 176.
+		 * Copy that behaviour here.
+		 */
+		if (is_cardbus)
+			buses = (buses & 0x00ffffff) | (176 << 24);
+			
 		/*
 		 * We need to blast all three values with a single write.
 		 */
 		pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
+
 		if (!is_cardbus) {
 			/* Now we can scan all subordinate buses... */
-			max = pci_do_scan_bus(child);
+			max = pci_scan_child_bus(child);
 		} else {
 			/*
 			 * For CardBus bridges, we leave 4 bus numbers
@@ -374,7 +400,8 @@
 	dev->class = class;
 	class >>= 8;
 
-	DBG("Found %02x:%02x [%04x/%04x] %06x %02x\n", dev->bus->number, dev->devfn, dev->vendor, dev->device, class, dev->hdr_type);
+	DBG("Found %02x:%02x [%04x/%04x] %06x %02x\n", dev->bus->number, dev->devfn,
+		dev->vendor, dev->device, class, dev->hdr_type);
 
 	/* "Unknown power state" */
 	dev->current_state = 4;
@@ -427,23 +454,35 @@
  * Read the config data for a PCI device, sanity-check it
  * and fill in the dev structure...
  */
-struct pci_dev * __devinit pci_scan_device(struct pci_dev *temp)
+static struct pci_dev * __devinit
+pci_scan_device(struct pci_bus *bus, int devfn)
 {
 	struct pci_dev *dev;
 	u32 l;
+	u8 hdr_type;
+
+	if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type))
+		return NULL;
 
-	if (pci_read_config_dword(temp, PCI_VENDOR_ID, &l))
+	if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
 		return NULL;
 
 	/* some broken boards return 0 or ~0 if a slot is empty: */
 	if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000)
 		return NULL;
 
-	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
 	if (!dev)
 		return NULL;
 
-	memcpy(dev, temp, sizeof(*dev));
+	memset(dev, 0, sizeof(struct pci_dev));
+	dev->bus = bus;
+	dev->sysdata = bus->sysdata;
+	dev->dev.parent = bus->dev;
+	dev->dev.bus = &pci_bus_type;
+	dev->devfn = devfn;
+	dev->hdr_type = hdr_type & 0x7f;
+	dev->multifunction = !!(hdr_type & 0x80);
 	dev->vendor = l & 0xffff;
 	dev->device = (l >> 16) & 0xffff;
 
@@ -461,74 +500,63 @@
 	strcpy(dev->dev.bus_id,dev->slot_name);
 	dev->dev.dma_mask = &dev->dma_mask;
 
-	device_register(&dev->dev);
 	return dev;
 }
 
-struct pci_dev * __devinit pci_scan_slot(struct pci_dev *temp)
+/**
+ * pci_scan_slot - scan a PCI slot on a bus for devices.
+ * @bus: PCI bus to scan
+ * @devfn: slot number to scan (must have zero function.)
+ *
+ * Scan a PCI slot on the specified PCI bus for devices, adding
+ * discovered devices to the @bus->devices list.  New devices
+ * will have an empty dev->global_list head.
+ */
+int __devinit pci_scan_slot(struct pci_bus *bus, int devfn)
 {
-	struct pci_bus *bus = temp->bus;
-	struct pci_dev *dev;
-	struct pci_dev *first_dev = NULL;
-	int func = 0;
-	int is_multi = 0;
-	u8 hdr_type;
+	int func, nr = 0;
 
-	for (func = 0; func < 8; func++, temp->devfn++) {
-		if (func && !is_multi)		/* not a multi-function device */
-			continue;
-		if (pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type))
-			continue;
-		temp->hdr_type = hdr_type & 0x7f;
+	for (func = 0; func < 8; func++, devfn++) {
+		struct pci_dev *dev;
 
-		dev = pci_scan_device(temp);
+		dev = pci_scan_device(bus, devfn);
 		if (!dev)
 			continue;
-		if (!func) {
-			is_multi = hdr_type & 0x80;
-			first_dev = dev;
-		}
 
-		/*
-		 * Link the device to both the global PCI device chain and
-		 * the per-bus list of devices and add the /proc entry.
-		 */
-		pci_insert_device (dev, bus);
+		if (func != 0)
+			dev->multifunction = 1;
 
 		/* Fix up broken headers */
 		pci_fixup_device(PCI_FIXUP_HEADER, dev);
+
+		/*
+		 * Add the device to our list of discovered devices
+		 * and the bus list for fixup functions, etc.
+		 */
+		INIT_LIST_HEAD(&dev->global_list);
+		list_add_tail(&dev->bus_list, &bus->devices);
+		nr++;
+
+		/*
+		 * If this is a single function device,
+		 * don't scan past the first function.
+		 */
+		if (!dev->multifunction)
+			break;
 	}
-	return first_dev;
+	return nr;
 }
 
-unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
+static unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
 {
-	unsigned int devfn, max, pass;
-	struct list_head *ln;
+	unsigned int devfn, pass, max = bus->secondary;
 	struct pci_dev *dev;
 
-	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev) {
-		printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__);
-		return 0;
-	}
-
 	DBG("Scanning bus %02x\n", bus->number);
-	max = bus->secondary;
-
-	/* Create a device template */
-	memset(dev, 0, sizeof(*dev));
-	dev->bus = bus;
-	dev->sysdata = bus->sysdata;
-	dev->dev.parent = bus->dev;
-	dev->dev.bus = &pci_bus_type;
 
 	/* Go find them, Rover! */
-	for (devfn = 0; devfn < 0x100; devfn += 8) {
-		dev->devfn = devfn;
-		pci_scan_slot(dev);
-	}
-	kfree(dev);
+	for (devfn = 0; devfn < 0x100; devfn += 8)
+		pci_scan_slot(bus, devfn);
 
 	/*
 	 * After performing arch-dependent fixup of the bus, look behind
@@ -537,9 +565,9 @@
 	DBG("Fixups for bus %02x\n", bus->number);
 	pcibios_fixup_bus(bus);
 	for (pass=0; pass < 2; pass++)
-		for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
-			dev = pci_dev_b(ln);
-			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+		list_for_each_entry(dev, &bus->devices, bus_list) {
+			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+			    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
 				max = pci_scan_bridge(bus, dev, max, pass);
 		}
 
@@ -551,6 +579,20 @@
 	 * Return how far we've got finding sub-buses.
 	 */
 	DBG("Bus scan for %02x returning with max=%02x\n", bus->number, max);
+	return max;
+}
+
+unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
+{
+	unsigned int max;
+
+	max = pci_scan_child_bus(bus);
+
+	/*
+	 * Make the discovered devices available.
+	 */
+	pci_bus_add_devices(bus);
+
 	return max;
 }
 
diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c
--- a/drivers/pci/quirks.c	Sat Feb 15 04:56:07 2003
+++ b/drivers/pci/quirks.c	Thu Feb 20 08:59:29 2003
@@ -167,6 +167,22 @@
 	}
 }
 
+/*
+ *	Ali Magik requires workarounds to be used by the drivers
+ *	that DMA to AGP space. Latency must be set to 0xA and triton
+ *	workaround applied too
+ *	[Info kindly provided by ALi]
+ */	
+ 
+static void __init quirk_alimagik(struct pci_dev *dev)
+{
+	if((pci_pci_problems&PCIPCI_ALIMAGIK)==0)
+	{
+		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+		pci_pci_problems|=PCIPCI_ALIMAGIK|PCIPCI_TRITON;
+	}
+}
+
 
 /*
  *	Natoma has some interesting boundary conditions with Zoran stuff
@@ -219,7 +235,7 @@
 static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev)
 {
 	printk(KERN_INFO "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb.\n");
-	/* Mae rhaid in i beidio a edrych ar y lleoliad I/O hyn */
+	/* Mae rhaid i ni beidio ag edrych ar y lleoliadiau I/O hyn */
 	request_region(0x3b0, 0x0C, "RadeonIGP");
 	request_region(0x3d3, 0x01, "RadeonIGP");
 }
@@ -535,6 +551,92 @@
 	}
 }
 
+/*
+ * As per PCI spec, ignore base address registers 0-3 of the IDE controllers
+ * running in Compatible mode (bits 0 and 2 in the ProgIf for primary and
+ * secondary channels respectively). If the device reports Compatible mode
+ * but does use BAR0-3 for address decoding, we assume that firmware has
+ * programmed these BARs with standard values (0x1f0,0x3f4 and 0x170,0x374).
+ * Exceptions (if they exist) must be handled in chip/architecture specific
+ * fixups.
+ *
+ * Note: for non x86 people. You may need an arch specific quirk to handle
+ * moving IDE devices to native mode as well. Some plug in card devices power
+ * up in compatible mode and assume the BIOS will adjust them.
+ *
+ * Q: should we load the 0x1f0,0x3f4 into the registers or zap them as
+ * we do now ? We don't want is pci_enable_device to come along
+ * and assign new resources. Both approaches work for that.
+ */ 
+
+static void __devinit quirk_ide_bases(struct pci_dev *dev)
+{
+       struct resource *res;
+       int first_bar = 2, last_bar = 0;
+
+       if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
+               return;
+
+       res = &dev->resource[0];
+
+       /* primary channel: ProgIf bit 0, BAR0, BAR1 */
+       if (!(dev->class & 1) && (res[0].flags || res[1].flags)) { 
+               res[0].start = res[0].end = res[0].flags = 0;
+               res[1].start = res[1].end = res[1].flags = 0;
+               first_bar = 0;
+               last_bar = 1;
+       }
+
+       /* secondary channel: ProgIf bit 2, BAR2, BAR3 */
+       if (!(dev->class & 4) && (res[2].flags || res[3].flags)) { 
+               res[2].start = res[2].end = res[2].flags = 0;
+               res[3].start = res[3].end = res[3].flags = 0;
+               last_bar = 3;
+       }
+
+       if (!last_bar)
+               return;
+
+       printk(KERN_INFO "PCI: Ignoring BAR%d-%d of IDE controller %s\n",
+              first_bar, last_bar, dev->slot_name);
+}
+
+/*
+ *	Ensure C0 rev restreaming is off. This is normally done by
+ *	the BIOS but in the odd case it is not the results are corruption
+ *	hence the presence of a Linux check
+ */
+ 
+static void __init quirk_disable_pxb(struct pci_dev *pdev)
+{
+	u16 config;
+	u8 rev;
+	
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+	if(rev != 0x04)		/* Only C0 requires this */
+		return;
+	pci_read_config_word(pdev, 0x40, &config);
+	if(config & (1<<6))
+	{
+		config &= ~(1<<6);
+		pci_write_config_word(pdev, 0x40, config);
+		printk(KERN_INFO "PCI: C0 revision 450NX. Disabling PCI restreaming.\n");
+	}
+}
+
+/*
+ *	VIA northbridges care about PCI_INTERRUPT_LINE
+ */
+ 
+int interrupt_line_quirk;
+
+static void __init quirk_via_bridge(struct pci_dev *pdev)
+{
+	if(pdev->devfn == 0)
+		interrupt_line_quirk = 1;
+}
+	
+
 /* This was originally an Alpha specific thing, but it really fits here.
  * The i82375 PCI/EISA bridge appears as non-classified. Fix that.
  */
@@ -559,7 +661,10 @@
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_0,	quirk_isa_dma_hangs },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C596,	quirk_isa_dma_hangs },
 	{ PCI_FIXUP_FINAL,      PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82371SB_0,  quirk_isa_dma_hangs },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454NX,	quirk_disable_pxb },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_1,	quirk_isa_dma_hangs },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_2,	quirk_isa_dma_hangs },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_3,	quirk_isa_dma_hangs },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_868,		quirk_s3_64M },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_968,		quirk_s3_64M },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437, 	quirk_triton }, 
@@ -574,6 +679,8 @@
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_2, 	quirk_natoma },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5597,		quirk_nopcipci },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_496,		quirk_nopcipci },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1647, 	quirk_alimagik },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1651, 	quirk_alimagik },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8363_0,	quirk_vialatency },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8371_1,	quirk_vialatency },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,	quirk_vialatency },
@@ -586,6 +693,8 @@
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M7101,		quirk_ali7101_acpi },
  	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371SB_2,	quirk_piix3_usb },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_2,	quirk_piix3_usb },
+	{ PCI_FIXUP_HEADER,     PCI_ANY_ID,             PCI_ANY_ID,                     quirk_ide_bases },
+	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_VIA,	PCI_ANY_ID,                     quirk_via_bridge },
 	{ PCI_FIXUP_FINAL,	PCI_ANY_ID,		PCI_ANY_ID,			quirk_cardbus_legacy },
 
 #ifdef CONFIG_X86_IO_APIC 
diff -Nru a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
--- a/drivers/pci/setup-bus.c	Tue Feb 18 03:27:06 2003
+++ b/drivers/pci/setup-bus.c	Tue Feb 25 03:17:33 2003
@@ -350,6 +350,7 @@
 {
 	struct pci_bus *b;
 	int found_vga = pbus_assign_resources_sorted(bus);
+	struct pci_dev *dev;
 
 	if (found_vga) {
 		/* Propagate presence of the VGA to upstream bridges */
@@ -357,9 +358,12 @@
 			b->resource[0]->flags |= IORESOURCE_BUS_HAS_VGA;
 		}
 	}
-	list_for_each_entry(b, &bus->children, node) {
-		pci_bus_assign_resources(b);
-		pci_setup_bridge(b);
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		b = dev->subordinate;
+		if (b) {
+			pci_bus_assign_resources(b);
+			pci_setup_bridge(b);
+		}
 	}
 }
 EXPORT_SYMBOL(pci_bus_assign_resources);
diff -Nru a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
--- a/drivers/pci/setup-res.c	Tue Dec 10 01:15:16 2002
+++ b/drivers/pci/setup-res.c	Sat Mar  1 02:11:51 2003
@@ -55,84 +55,47 @@
 	return err;
 }
 
-/*
- * Given the PCI bus a device resides on, try to
- * find an acceptable resource allocation for a
- * specific device resource..
- */
-static int pci_assign_bus_resource(const struct pci_bus *bus,
-	struct pci_dev *dev,
-	struct resource *res,
-	unsigned long size,
-	unsigned long min,
-	unsigned int type_mask,
-	int resno)
+int pci_assign_resource(struct pci_dev *dev, int resno)
 {
-	unsigned long align;
-	int i;
-
-	type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
-	for (i = 0 ; i < PCI_BUS_NUM_RESOURCES; i++) {
-		struct resource *r = bus->resource[i];
-		if (!r)
-			continue;
-
-		/* type_mask must match */
-		if ((res->flags ^ r->flags) & type_mask)
-			continue;
-
-		/* We cannot allocate a non-prefetching resource
-		   from a pre-fetching area */
-		if ((r->flags & IORESOURCE_PREFETCH) &&
-		    !(res->flags & IORESOURCE_PREFETCH))
-			continue;
-
-		/* The bridge resources are special, as their
-		   size != alignment. Sizing routines return
-		   required alignment in the "start" field. */
-		align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start;
-
-		/* Ok, try it out.. */
-		if (allocate_resource(r, res, size, min, -1, align,
-				      pcibios_align_resource, dev) < 0)
-			continue;
-
-		/* Update PCI config space.  */
-		pcibios_update_resource(dev, r, res, resno);
-		return 0;
-	}
-	return -EBUSY;
-}
-
-int 
-pci_assign_resource(struct pci_dev *dev, int i)
-{
-	const struct pci_bus *bus = dev->bus;
-	struct resource *res = dev->resource + i;
-	unsigned long size, min;
+	struct pci_bus *bus = dev->bus;
+	struct resource *res = dev->resource + resno;
+	unsigned long size, min, align;
+	int ret;
 
 	size = res->end - res->start + 1;
 	min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
+	/* The bridge resources are special, as their
+	   size != alignment. Sizing routines return
+	   required alignment in the "start" field. */
+	align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start;
 
 	/* First, try exact prefetching match.. */
-	if (pci_assign_bus_resource(bus, dev, res, size, min, IORESOURCE_PREFETCH, i) < 0) {
+	ret = pci_bus_alloc_resource(bus, res, size, align, min,
+				     IORESOURCE_PREFETCH,
+				     pcibios_align_resource, dev);
+
+	if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) {
 		/*
 		 * That failed.
 		 *
 		 * But a prefetching area can handle a non-prefetching
 		 * window (it will just not perform as well).
 		 */
-		if (!(res->flags & IORESOURCE_PREFETCH) || pci_assign_bus_resource(bus, dev, res, size, min, 0, i) < 0) {
-			printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n",
-			       i, res->start, res->end, dev->slot_name);
-			return -EBUSY;
-		}
+		ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
+					     pcibios_align_resource, dev);
 	}
 
-	DBGC((KERN_ERR "  got res[%lx:%lx] for resource %d of %s\n", res->start,
-						res->end, i, dev->dev.name));
+	if (ret) {
+		printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n",
+		       resno, res->start, res->end, dev->slot_name);
+	} else {
+		DBGC((KERN_ERR "  got res[%lx:%lx] for resource %d of %s\n",
+		      res->start, res->end, i, dev->dev.name));
+		/* Update PCI config space.  */
+		pcibios_update_resource(dev, res->parent, res, resno);
+	}
 
-	return 0;
+	return ret;
 }
 
 /* Sort resources by alignment */
diff -Nru a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
--- a/drivers/pcmcia/hd64465_ss.c	Fri Feb 21 13:05:18 2003
+++ b/drivers/pcmcia/hd64465_ss.c	Tue Mar  4 22:35:34 2003
@@ -1070,8 +1070,8 @@
 	}
 
 /*	hd64465_io_debug = 0; */
-	platform_device_register(&hd64465_device);
 	hd64465_device.dev.class_data = &hd64465_data;
+	platform_device_register(&hd64465_device);
 
 	return 0;
 }
diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
--- a/drivers/pcmcia/i82365.c	Tue Feb 25 11:50:51 2003
+++ b/drivers/pcmcia/i82365.c	Tue Mar  4 22:35:34 2003
@@ -1628,11 +1628,11 @@
 	request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
 #endif
     
-    platform_device_register(&i82365_device);
-
     i82365_data.nsock = sockets;
     i82365_device.dev.class_data = &i82365_data;
     
+    platform_device_register(&i82365_device);
+
     /* Finally, schedule a polling interrupt */
     if (poll_interval != 0) {
 	poll_timer.function = pcic_interrupt_wrapper;
diff -Nru a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
--- a/drivers/pcmcia/sa1100_generic.c	Sun Mar  2 12:59:19 2003
+++ b/drivers/pcmcia/sa1100_generic.c	Thu Mar  6 08:48:29 2003
@@ -47,7 +47,6 @@
 #include <linux/notifier.h>
 #include <linux/proc_fs.h>
 #include <linux/version.h>
-#include <linux/cpufreq.h>
 
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
--- a/drivers/pcmcia/tcic.c	Fri Feb 21 13:05:24 2003
+++ b/drivers/pcmcia/tcic.c	Tue Mar  4 22:35:34 2003
@@ -452,8 +452,6 @@
 	sockets++;
     }
 
-    platform_device_register(&tcic_device);
-
     switch (socket_table[0].id) {
     case TCIC_ID_DB86082:
 	printk("DB86082"); break;
@@ -526,6 +524,8 @@
 
     tcic_data.nsock = sockets;
     tcic_device.dev.class_data = &tcic_data;
+
+    platform_device_register(&tcic_device);
 
     return 0;
     
diff -Nru a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig
--- a/drivers/pnp/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/drivers/pnp/Kconfig	Sun Mar  9 15:37:55 2003
@@ -30,15 +30,6 @@
 
 	  If unsure, say Y.
 
-config PNP_CARD
-	bool "Plug and Play card services"
-	depends on PNP
-	help
-	  Select Y if you want the PnP Layer to manage cards.  Cards are groups
-	  of PnP devices.  Some drivers, especially PnP sound card drivers, use
-	  these cards.  If you want to use the protocol ISAPNP you will need to
-	  say Y here.
-
 config PNP_DEBUG
 	bool "PnP Debug Messages"
 	depends on PNP
@@ -51,7 +42,7 @@
 
 config ISAPNP
 	bool "ISA Plug and Play support (EXPERIMENTAL)"
-	depends on PNP && EXPERIMENTAL && PNP_CARD
+	depends on PNP && EXPERIMENTAL
 	help
 	  Say Y here if you would like support for ISA Plug and Play devices.
 	  Some information is in <file:Documentation/isapnp.txt>.
diff -Nru a/drivers/pnp/Makefile b/drivers/pnp/Makefile
--- a/drivers/pnp/Makefile	Wed Feb 19 08:45:42 2003
+++ b/drivers/pnp/Makefile	Sun Mar  9 15:37:55 2003
@@ -2,9 +2,7 @@
 # Makefile for the Linux Plug-and-Play Support.
 #
 
-pnp-card-$(CONFIG_PNP_CARD) = card.o
-
-obj-y		:= core.o driver.o resource.o manager.o support.o interface.o quirks.o names.o system.o $(pnp-card-y)
+obj-y		:= core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o names.o system.o
 
 obj-$(CONFIG_PNPBIOS)		+= pnpbios/
 obj-$(CONFIG_ISAPNP)		+= isapnp/
diff -Nru a/drivers/pnp/card.c b/drivers/pnp/card.c
--- a/drivers/pnp/card.c	Wed Feb 19 09:51:16 2003
+++ b/drivers/pnp/card.c	Sun Mar  9 15:44:14 2003
@@ -16,15 +16,14 @@
 #endif
 
 #include <linux/pnp.h>
-#include <linux/init.h>
 #include "base.h"
 
-
 LIST_HEAD(pnp_cards);
 
-static const struct pnp_card_id * match_card(struct pnpc_driver *drv, struct pnp_card *card)
+
+static const struct pnp_card_id * match_card(struct pnp_card_driver * drv, struct pnp_card * card)
 {
-	const struct pnp_card_id *drv_id = drv->id_table;
+	const struct pnp_card_id * drv_id = drv->id_table;
 	while (*drv_id->id){
 		if (compare_pnp_id(card->id,drv_id->id))
 			return drv_id;
@@ -33,31 +32,33 @@
 	return NULL;
 }
 
-static int card_bus_match(struct device *dev, struct device_driver *drv)
+static void generic_card_remove(struct pnp_dev * dev)
 {
-	struct pnp_card * card = to_pnp_card(dev);
-	struct pnpc_driver * pnp_drv = to_pnpc_driver(drv);
-	if (match_card(pnp_drv, card) == NULL)
-		return 0;
-	return 1;
+	dev->card_link = NULL;
 }
 
-struct bus_type pnpc_bus_type = {
-	.name	= "pnp_card",
-	.match	= card_bus_match,
-};
-
+static void generic_card_remove_first(struct pnp_dev * dev)
+{
+	struct pnp_card_driver * drv = to_pnp_card_driver(dev->driver);
+	if (!dev->card || !drv)
+		return;
+	if (drv->remove)
+		drv->remove(dev->card_link);
+	drv->link.remove = &generic_card_remove;
+	kfree(dev->card_link);
+	generic_card_remove(dev);
+}
 
 /**
- * pnpc_add_id - adds an EISA id to the specified card
+ * pnp_add_card_id - adds an EISA id to the specified card
  * @id: pointer to a pnp_id structure
  * @card: pointer to the desired card
  *
  */
 
-int pnpc_add_id(struct pnp_id *id, struct pnp_card *card)
+int pnp_add_card_id(struct pnp_id *id, struct pnp_card * card)
 {
-	struct pnp_id *ptr;
+	struct pnp_id * ptr;
 	if (!id)
 		return -EINVAL;
 	if (!card)
@@ -73,7 +74,7 @@
 	return 0;
 }
 
-static void pnpc_free_ids(struct pnp_card *card)
+static void pnp_free_card_ids(struct pnp_card * card)
 {
 	struct pnp_id * id;
 	struct pnp_id *next;
@@ -90,47 +91,51 @@
 static void pnp_release_card(struct device *dmdev)
 {
 	struct pnp_card * card = to_pnp_card(dmdev);
-	pnpc_free_ids(card);
+	pnp_free_card_ids(card);
 	kfree(card);
 }
 
 /**
- * pnpc_add_card - adds a PnP card to the PnP Layer
+ * pnp_add_card - adds a PnP card to the PnP Layer
  * @card: pointer to the card to add
  */
 
-int pnpc_add_card(struct pnp_card *card)
+int pnp_add_card(struct pnp_card * card)
 {
-	int error = 0;
+	int error;
+	struct list_head * pos;
 	if (!card || !card->protocol)
 		return -EINVAL;
+
 	sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number, card->number);
-	INIT_LIST_HEAD(&card->rdevs);
 	card->dev.parent = &card->protocol->dev;
-	card->dev.bus = &pnpc_bus_type;
+	card->dev.bus = NULL;
 	card->dev.release = &pnp_release_card;
-	card->status = PNP_READY;
 	error = device_register(&card->dev);
-	if (error == 0){
-		struct list_head *pos;
+	if (error == 0) {
 		spin_lock(&pnp_lock);
 		list_add_tail(&card->global_list, &pnp_cards);
 		list_add_tail(&card->protocol_list, &card->protocol->cards);
 		spin_unlock(&pnp_lock);
+
+		/* we wait until now to add devices in order to ensure the drivers
+		 * will be able to use all of the related devices on the card
+		 * without waiting any unresonable length of time */
 		list_for_each(pos,&card->devices){
 			struct pnp_dev *dev = card_to_pnp_dev(pos);
 			__pnp_add_device(dev);
 		}
-	}
+	} else
+		pnp_err("sysfs failure, card '%s' will be unavailable", card->dev.bus_id);
 	return error;
 }
 
 /**
- * pnpc_remove_card - removes a PnP card from the PnP Layer
+ * pnp_remove_card - removes a PnP card from the PnP Layer
  * @card: pointer to the card to remove
  */
 
-void pnpc_remove_card(struct pnp_card *card)
+void pnp_remove_card(struct pnp_card * card)
 {
 	struct list_head *pos, *temp;
 	if (!card)
@@ -142,22 +147,24 @@
 	spin_unlock(&pnp_lock);
 	list_for_each_safe(pos,temp,&card->devices){
 		struct pnp_dev *dev = card_to_pnp_dev(pos);
-		pnpc_remove_device(dev);
+		pnp_remove_card_device(dev);
 	}
 }
 
 /**
- * pnpc_add_device - adds a device to the specified card
+ * pnp_add_card_device - adds a device to the specified card
  * @card: pointer to the card to add to
  * @dev: pointer to the device to add
  */
 
-int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev)
+int pnp_add_card_device(struct pnp_card * card, struct pnp_dev * dev)
 {
-	if (!dev || !dev->protocol || !card)
+	if (!card || !dev || !dev->protocol)
 		return -EINVAL;
 	dev->dev.parent = &card->dev;
-	sprintf(dev->dev.bus_id, "%02x:%02x.%02x", dev->protocol->number, card->number,dev->number);
+	dev->card_link = NULL;
+	snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%02x:%02x.%02x", dev->protocol->number,
+		 card->number,dev->number);
 	spin_lock(&pnp_lock);
 	dev->card = card;
 	list_add_tail(&dev->card_list, &card->devices);
@@ -166,12 +173,12 @@
 }
 
 /**
- * pnpc_remove_device- removes a device from the specified card
+ * pnp_remove_card_device- removes a device from the specified card
  * @card: pointer to the card to remove from
  * @dev: pointer to the device to remove
  */
 
-void pnpc_remove_device(struct pnp_dev *dev)
+void pnp_remove_card_device(struct pnp_dev * dev)
 {
 	spin_lock(&pnp_lock);
 	dev->card = NULL;
@@ -182,20 +189,21 @@
 
 /**
  * pnp_request_card_device - Searches for a PnP device under the specified card
- * @card: pointer to the card to search under, cannot be NULL
+ * @lcard: pointer to the card link, cannot be NULL
  * @id: pointer to a PnP ID structure that explains the rules for finding the device
  * @from: Starting place to search from. If NULL it will start from the begining.
- *
- * Will activate the device
  */
 
-struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, struct pnp_dev *from)
+struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char * id, struct pnp_dev * from)
 {
-	struct list_head *pos;
-	struct pnp_dev *dev;
-	struct pnpc_driver *cdrv;
-	if (!card || !id)
+	struct list_head * pos;
+	struct pnp_dev * dev;
+	struct pnp_card_driver * drv;
+	struct pnp_card * card;
+	if (!clink || !id)
 		goto done;
+	card = clink->card;
+	drv = clink->driver;
 	if (!from) {
 		pos = card->devices.next;
 	} else {
@@ -205,7 +213,7 @@
 	}
 	while (pos != &card->devices) {
 		dev = card_to_pnp_dev(pos);
-		if (compare_pnp_id(dev->id,id))
+		if ((!dev->card_link) && compare_pnp_id(dev->id,id))
 			goto found;
 		pos = pos->next;
 	}
@@ -214,168 +222,93 @@
 	return NULL;
 
 found:
-	if (pnp_device_attach(dev) < 0)
-		return NULL;
-	cdrv = to_pnpc_driver(card->dev.driver);
-	if (dev->active == 0) {
-		if (!(cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE)) {
-			if(pnp_activate_dev(dev)<0) {
-				pnp_device_detach(dev);
-				return NULL;
-			}
+	down_write(&dev->dev.bus->subsys.rwsem);
+	dev->card_link = clink;
+	dev->dev.driver = &drv->link.driver;
+	if (drv->link.driver.probe) {
+		if (drv->link.driver.probe(&dev->dev)) {
+			dev->dev.driver = NULL;
+			return NULL;
 		}
-	} else {
-		if ((cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE))
-			pnp_disable_dev(dev);
 	}
-	spin_lock(&pnp_lock);
-	list_add_tail(&dev->rdev_list, &card->rdevs);
-	spin_unlock(&pnp_lock);
+	device_bind_driver(&dev->dev);
+	up_write(&dev->dev.bus->subsys.rwsem);
+
 	return dev;
 }
 
 /**
  * pnp_release_card_device - call this when the driver no longer needs the device
  * @dev: pointer to the PnP device stucture
- *
- * Will disable the device
  */
 
-void pnp_release_card_device(struct pnp_dev *dev)
-{
-	spin_lock(&pnp_lock);
-	list_del(&dev->rdev_list);
-	spin_unlock(&pnp_lock);
-	pnp_device_detach(dev);
-}
-
-static void pnpc_recover_devices(struct pnp_card *card)
-{
-	struct list_head *pos, *temp;
-	list_for_each_safe(pos,temp,&card->rdevs){
-		struct pnp_dev *dev = list_entry(pos, struct pnp_dev, rdev_list);
-		pnp_release_card_device(dev);
-	}
-}
-
-int pnpc_attach(struct pnp_card *pnp_card)
-{
-	spin_lock(&pnp_lock);
-	if(pnp_card->status != PNP_READY){
-		spin_unlock(&pnp_lock);
-		return -EBUSY;
-	}
-	pnp_card->status = PNP_ATTACHED;
-	spin_unlock(&pnp_lock);
-	return 0;
-}
- 
-void pnpc_detach(struct pnp_card *pnp_card)
-{
-	spin_lock(&pnp_lock);
-	if (pnp_card->status == PNP_ATTACHED)
-		pnp_card->status = PNP_READY;
-	spin_unlock(&pnp_lock);
-	pnpc_recover_devices(pnp_card);
-}
-
-static int pnpc_card_probe(struct device *dev)
-{
-	int error = 0;
-	struct pnpc_driver *drv = to_pnpc_driver(dev->driver);
-	struct pnp_card *card = to_pnp_card(dev);
-	const struct pnp_card_id *card_id = NULL;
-
-	pnp_dbg("pnp: match found with the PnP card '%s' and the driver '%s'", dev->bus_id,drv->name);
-
-	error = pnpc_attach(card);
-	if (error < 0)
-		return error;
-	if (drv->probe) {
-		card_id = match_card(drv, card);
-		if (card_id != NULL)
-			error = drv->probe(card, card_id);
-		if (error >= 0){
-			card->driver = drv;
-			error = 0;
-		} else
-			pnpc_detach(card);
-	}
-	return error;
-}
-
-static int pnpc_card_remove(struct device *dev)
+void pnp_release_card_device(struct pnp_dev * dev)
 {
-	struct pnp_card * card = to_pnp_card(dev);
-	struct pnpc_driver * drv = card->driver;
-
-	if (drv) {
-		if (drv->remove)
-			drv->remove(card);
-		card->driver = NULL;
-	}
-	pnpc_detach(card);
-	return 0;
+	struct pnp_card_driver * drv = dev->card_link->driver;
+	if (!drv)
+		return;
+	down_write(&dev->dev.bus->subsys.rwsem);
+	drv->link.remove = &generic_card_remove;
+	device_release_driver(&dev->dev);
+	drv->link.remove = &generic_card_remove_first;
+	up_write(&dev->dev.bus->subsys.rwsem);
 }
 
 /**
- * pnpc_register_driver - registers a PnP card driver with the PnP Layer
- * @cdrv: pointer to the driver to register
+ * pnp_register_card_driver - registers a PnP card driver with the PnP Layer
+ * @drv: pointer to the driver to register
  */
 
-int pnpc_register_driver(struct pnpc_driver * drv)
+int pnp_register_card_driver(struct pnp_card_driver * drv)
 {
-	int count;
-	struct list_head *pos;
-
-	drv->driver.name = drv->name;
-	drv->driver.bus = &pnpc_bus_type;
-	drv->driver.probe = pnpc_card_probe;
-	drv->driver.remove = pnpc_card_remove;
-
-	pnp_dbg("the card driver '%s' has been registered", drv->name);
-
-	count = driver_register(&drv->driver);
+	int count = 0;
+	struct list_head *pos, *temp;
 
-	/* get the number of initial matches */
-	if (count >= 0){
-		count = 0;
-		list_for_each(pos,&drv->driver.devices){
-			count++;
+	drv->link.name = drv->name;
+	drv->link.id_table = NULL;	/* this will disable auto matching */
+	drv->link.flags = drv->flags;
+	drv->link.probe = NULL;
+	drv->link.remove = &generic_card_remove_first;
+
+	pnp_register_driver(&drv->link);
+
+	list_for_each_safe(pos,temp,&pnp_cards){
+		struct pnp_card *card = list_entry(pos, struct pnp_card, global_list);
+		const struct pnp_card_id *id = match_card(drv,card);
+		if (id) {
+			struct pnp_card_link * clink = pnp_alloc(sizeof(struct pnp_card_link));
+			if (!clink)
+				continue;
+			clink->card = card;
+			clink->driver = drv;
+			if (drv->probe) {
+				if (drv->probe(clink, id)>=0)
+					count++;
+			} else
+				count++;
 		}
 	}
 	return count;
 }
 
 /**
- * pnpc_unregister_driver - unregisters a PnP card driver from the PnP Layer
- * @cdrv: pointer to the driver to unregister
- *
- * Automatically disables requested devices
+ * pnp_unregister_card_driver - unregisters a PnP card driver from the PnP Layer
+ * @drv: pointer to the driver to unregister
  */
 
-void pnpc_unregister_driver(struct pnpc_driver *drv)
+void pnp_unregister_card_driver(struct pnp_card_driver * drv)
 {
-	driver_unregister(&drv->driver);
-	pnp_dbg("the card driver '%s' has been unregistered", drv->name);
-}
+	pnp_unregister_driver(&drv->link);
 
-static int __init pnp_card_init(void)
-{
-	printk(KERN_INFO "pnp: Enabling Plug and Play Card Services.\n");
-	return bus_register(&pnpc_bus_type);
+	pnp_dbg("the card driver '%s' has been unregistered", drv->name);
 }
 
-subsys_initcall(pnp_card_init);
-
-EXPORT_SYMBOL(pnpc_add_card);
-EXPORT_SYMBOL(pnpc_remove_card);
-EXPORT_SYMBOL(pnpc_add_device);
-EXPORT_SYMBOL(pnpc_remove_device);
+EXPORT_SYMBOL(pnp_add_card);
+EXPORT_SYMBOL(pnp_remove_card);
+EXPORT_SYMBOL(pnp_add_card_device);
+EXPORT_SYMBOL(pnp_remove_card_device);
+EXPORT_SYMBOL(pnp_add_card_id);
 EXPORT_SYMBOL(pnp_request_card_device);
 EXPORT_SYMBOL(pnp_release_card_device);
-EXPORT_SYMBOL(pnpc_register_driver);
-EXPORT_SYMBOL(pnpc_unregister_driver);
-EXPORT_SYMBOL(pnpc_add_id);
-EXPORT_SYMBOL(pnpc_attach);
-EXPORT_SYMBOL(pnpc_detach);
+EXPORT_SYMBOL(pnp_register_card_driver);
+EXPORT_SYMBOL(pnp_unregister_card_driver);
diff -Nru a/drivers/pnp/driver.c b/drivers/pnp/driver.c
--- a/drivers/pnp/driver.c	Wed Feb 19 09:54:46 2003
+++ b/drivers/pnp/driver.c	Sun Mar  9 15:44:14 2003
@@ -53,12 +53,11 @@
 static const struct pnp_device_id * match_device(struct pnp_driver *drv, struct pnp_dev *dev)
 {
 	const struct pnp_device_id *drv_id = drv->id_table;
-	if (!drv)
+	if (!drv_id)
 		return NULL;
-	if (!dev)
-		return NULL;
-	while (*drv_id->id){
-		if (compare_pnp_id(dev->id,drv_id->id))
+
+	while (*drv_id->id) {
+		if (compare_pnp_id(dev->id, drv_id->id))
 			return drv_id;
 		drv_id++;
 	}
@@ -102,14 +101,19 @@
 		return error;
 
 	if (pnp_dev->active == 0) {
-		if (!(pnp_drv->flags & PNP_DRIVER_DO_NOT_ACTIVATE)) {
+		if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
 			error = pnp_activate_dev(pnp_dev);
 			if (error < 0)
 				return error;
 		}
+	} else if ((pnp_drv->flags & PNP_DRIVER_RES_DISABLE)
+		    == PNP_DRIVER_RES_DISABLE) {
+		error = pnp_disable_dev(pnp_dev);
+		if (error < 0)
+			return error;
 	}
 	error = 0;
-	if (pnp_drv->probe && pnp_dev->active) {
+	if (pnp_drv->probe) {
 		dev_id = match_device(pnp_drv, pnp_dev);
 		if (dev_id != NULL)
 			error = pnp_drv->probe(pnp_dev, dev_id);
@@ -117,9 +121,8 @@
 	if (error >= 0){
 		pnp_dev->driver = pnp_drv;
 		error = 0;
-	}
-	else
-	goto fail;
+	} else
+		goto fail;
 	return error;
 
 fail:
diff -Nru a/drivers/pnp/interface.c b/drivers/pnp/interface.c
--- a/drivers/pnp/interface.c	Tue Mar  4 09:12:57 2003
+++ b/drivers/pnp/interface.c	Sun Mar  9 15:17:52 2003
@@ -332,11 +332,18 @@
 	buffer->buffer = buf;
 	buffer->curr = buffer->buffer;
 
+	pnp_printf(buffer,"mode = ");
+	if (dev->config_mode & PNP_CONFIG_MANUAL)
+		pnp_printf(buffer,"manual\n");
+	else
+		pnp_printf(buffer,"auto\n");
+
 	pnp_printf(buffer,"state = ");
 	if (dev->active)
 		pnp_printf(buffer,"active\n");
 	else
 		pnp_printf(buffer,"disabled\n");
+
 	for (i = 0; i < PNP_MAX_PORT; i++) {
 		if (pnp_port_valid(dev, i)) {
 			pnp_printf(buffer,"io");
@@ -402,13 +409,13 @@
 		retval = pnp_activate_dev(dev);
 		goto done;
 	}
-	if (!strnicmp(buf,"auto-config",11)) {
+	if (!strnicmp(buf,"auto",4)) {
 		if (dev->active)
 			goto done;
 		retval = pnp_auto_config_dev(dev);
 		goto done;
 	}
-	if (!strnicmp(buf,"clear-config",12)) {
+	if (!strnicmp(buf,"clear",5)) {
 		if (dev->active)
 			goto done;
 		spin_lock(&pnp_lock);
diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
--- a/drivers/pnp/isapnp/core.c	Wed Feb 19 09:54:46 2003
+++ b/drivers/pnp/isapnp/core.c	Sun Mar  9 15:37:55 2003
@@ -626,7 +626,7 @@
 		isapnp_peek(name, size1);
 		name[size1] = '\0';
 		*size -= size1;
-		
+
 		/* clean whitespace from end of string */
 		while (size1 > 0  &&  name[--size1] == ' ')
 			name[size1] = '\0';
@@ -647,7 +647,7 @@
 		return 1;
 	if (pnp_build_resource(dev, 0) == NULL)
 		return 1;
-	pnpc_add_device(card,dev);
+	pnp_add_card_device(card,dev);
 	while (1) {
 		if (isapnp_read_tag(&type, &size)<0)
 			return 1;
@@ -659,7 +659,7 @@
 				if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
 					return 1;
 				pnp_build_resource(dev,0);
-				pnpc_add_device(card,dev);
+				pnp_add_card_device(card,dev);
 				size = 0;
 				skip = 0;
 			} else {
@@ -852,7 +852,7 @@
 			device & 0x0f,
 			(device >> 12) & 0x0f,
 			(device >> 8) & 0x0f);
-	pnpc_add_id(id,card);
+	pnp_add_card_id(id,card);
 }
 
 
@@ -962,7 +962,7 @@
 			isapnp_parse_current_resources(dev, &dev->res);
 		}
 
-		pnpc_add_card(card);
+		pnp_add_card(card);
 	}
 	isapnp_wait();
 	return 0;
diff -Nru a/drivers/pnp/manager.c b/drivers/pnp/manager.c
--- a/drivers/pnp/manager.c	Sat Feb 22 13:40:31 2003
+++ b/drivers/pnp/manager.c	Thu Mar  6 13:50:22 2003
@@ -532,6 +532,39 @@
 	return error;
 }
 
+static void pnp_process_manual_resources(struct pnp_resource_table * ctab, struct pnp_resource_table * ntab)
+{
+	int idx;
+	for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
+		if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO)
+			continue;
+		ctab->irq_resource[idx].start = ntab->irq_resource[idx].start;
+		ctab->irq_resource[idx].end = ntab->irq_resource[idx].end;
+		ctab->irq_resource[idx].flags = ntab->irq_resource[idx].flags;
+	}
+	for (idx = 0; idx < PNP_MAX_DMA; idx++) {
+		if (ntab->dma_resource[idx].flags & IORESOURCE_AUTO)
+			continue;
+		ctab->dma_resource[idx].start = ntab->dma_resource[idx].start;
+		ctab->dma_resource[idx].end = ntab->dma_resource[idx].end;
+		ctab->dma_resource[idx].flags = ntab->dma_resource[idx].flags;
+	}
+	for (idx = 0; idx < PNP_MAX_PORT; idx++) {
+		if (ntab->port_resource[idx].flags & IORESOURCE_AUTO)
+			continue;
+		ctab->port_resource[idx].start = ntab->port_resource[idx].start;
+		ctab->port_resource[idx].end = ntab->port_resource[idx].end;
+		ctab->port_resource[idx].flags = ntab->port_resource[idx].flags;
+	}
+	for (idx = 0; idx < PNP_MAX_MEM; idx++) {
+		if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO)
+			continue;
+		ctab->irq_resource[idx].start = ntab->mem_resource[idx].start;
+		ctab->irq_resource[idx].end = ntab->mem_resource[idx].end;
+		ctab->irq_resource[idx].flags = ntab->mem_resource[idx].flags;
+	}
+}
+
 /**
  * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table
  * @dev: pointer to the desired device
@@ -554,7 +587,7 @@
 	*bak = dev->res;
 
 	spin_lock(&pnp_lock);
-	dev->res = *res;
+	pnp_process_manual_resources(&dev->res, res);
 	if (!(mode & PNP_CONFIG_FORCE)) {
 		for (i = 0; i < PNP_MAX_PORT; i++) {
 			if(pnp_check_port(dev,i))
@@ -681,7 +714,7 @@
 		return -1;
 	}
 	dev->active = 0; /* just in case the protocol doesn't do this */
-	pnp_dbg("the device '%s' has been disabled.", dev->dev.bus_id);
+	pnp_dbg("res: the device '%s' has been disabled.", dev->dev.bus_id);
 	return 0;
 }
 
diff -Nru a/drivers/pnp/resource.c b/drivers/pnp/resource.c
--- a/drivers/pnp/resource.c	Sat Feb 22 13:40:31 2003
+++ b/drivers/pnp/resource.c	Thu Mar  6 13:50:22 2003
@@ -558,25 +558,25 @@
 		table->irq_resource[idx].name = NULL;
 		table->irq_resource[idx].start = -1;
 		table->irq_resource[idx].end = -1;
-		table->irq_resource[idx].flags = 0;
+		table->irq_resource[idx].flags = IORESOURCE_AUTO;
 	}
 	for (idx = 0; idx < PNP_MAX_DMA; idx++) {
 		table->dma_resource[idx].name = NULL;
 		table->dma_resource[idx].start = -1;
 		table->dma_resource[idx].end = -1;
-		table->dma_resource[idx].flags = 0;
+		table->dma_resource[idx].flags = IORESOURCE_AUTO;
 	}
 	for (idx = 0; idx < PNP_MAX_PORT; idx++) {
 		table->port_resource[idx].name = NULL;
 		table->port_resource[idx].start = 0;
 		table->port_resource[idx].end = 0;
-		table->port_resource[idx].flags = 0;
+		table->port_resource[idx].flags = IORESOURCE_AUTO;
 	}
 	for (idx = 0; idx < PNP_MAX_MEM; idx++) {
 		table->mem_resource[idx].name = NULL;
 		table->mem_resource[idx].start = 0;
 		table->mem_resource[idx].end = 0;
-		table->mem_resource[idx].flags = 0;
+		table->mem_resource[idx].flags = IORESOURCE_AUTO;
 	}
 }
 
diff -Nru a/drivers/pnp/system.c b/drivers/pnp/system.c
--- a/drivers/pnp/system.c	Wed Feb 19 09:54:46 2003
+++ b/drivers/pnp/system.c	Sun Mar  9 15:44:14 2003
@@ -93,8 +93,8 @@
 
 static struct pnp_driver system_pnp_driver = {
 	.name		= "system",
-	.flags		= PNP_DRIVER_DO_NOT_ACTIVATE, 
 	.id_table	= pnp_dev_table,
+	.flags		= PNP_DRIVER_RES_DO_NOT_CHANGE,
 	.probe		= system_pnp_probe,
 	.remove		= NULL,
 };
diff -Nru a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
--- a/drivers/s390/block/dasd_3990_erp.c	Mon Feb 24 10:29:29 2003
+++ b/drivers/s390/block/dasd_3990_erp.c	Thu Mar  6 09:25:58 2003
@@ -2445,7 +2445,7 @@
  *     - exit with permanent error
  *
  * PARAMETER
- *   erp		ERP which is in progress wiht no retry left
+ *   erp		ERP which is in progress with no retry left
  *
  * RETURN VALUES
  *   erp		modified/additional ERP
diff -Nru a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
--- a/drivers/s390/block/dasd_genhd.c	Fri Dec  6 11:37:54 2002
+++ b/drivers/s390/block/dasd_genhd.c	Sat Mar  8 14:50:22 2003
@@ -60,11 +60,8 @@
 	}
 
 	/* Register block device. */
-	new_major = register_blkdev(major, "dasd", &dasd_device_operations);
+	new_major = register_blkdev(major, "dasd");
 	if (new_major < 0) {
-		MESSAGE(KERN_WARNING,
-			"Cannot register to major no %d, rc = %d",
-			major, new_major);
 		kfree(mi);
 		return new_major;
 	}
diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
--- a/drivers/s390/block/xpram.c	Tue Dec  3 09:21:05 2002
+++ b/drivers/s390/block/xpram.c	Sat Mar  8 14:50:22 2003
@@ -430,13 +430,11 @@
 	/*
 	 * Register xpram major.
 	 */
-	rc = register_blkdev(XPRAM_MAJOR, XPRAM_NAME, &xpram_devops);
-	if (rc < 0) {
-		PRINT_ERR("Can't get xpram major %d\n", XPRAM_MAJOR);
+	rc = register_blkdev(XPRAM_MAJOR, XPRAM_NAME);
+	if (rc < 0)
 		goto out;
-	}
 
-	devfs_mk_dir (NULL, "slram", NULL);
+	devfs_mk_dir(NULL, "slram", NULL);
 
 	/*
 	 * Assign the other needed values: make request function, sizes and
@@ -452,6 +450,7 @@
 	for (i = 0; i < xpram_devs; i++) {
 		struct gendisk *disk = xpram_disks[i];
 		char name[16];
+
 		xpram_devices[i].size = xpram_sizes[i] / 4;
 		xpram_devices[i].offset = offset;
 		offset += xpram_devices[i].size;
diff -Nru a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
--- a/drivers/s390/char/con3215.c	Tue Feb 25 10:27:52 2003
+++ b/drivers/s390/char/con3215.c	Thu Mar  6 09:25:58 2003
@@ -862,7 +862,7 @@
 	spin_unlock_irqrestore(raw->lock, flags);
 }
 
-static int __init
+static int __init 
 con3215_consetup(struct console *co, char *options)
 {
 	return 0;
@@ -884,7 +884,7 @@
  * 3215 console initialization code called from console_init().
  * NOTE: This is called before kmalloc is available.
  */
-void __init
+static void __init
 con3215_init(void)
 {
 	struct ccw_device *cdev;
@@ -1122,6 +1122,7 @@
 		spin_unlock_irqrestore(raw->lock, flags);
 	}
 }
+console_initcall(con3215_init);
 
 /*
  * Disable writing to a 3215 tty
diff -Nru a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c
--- a/drivers/s390/char/sclp_con.c	Thu Dec 12 10:03:31 2002
+++ b/drivers/s390/char/sclp_con.c	Fri Feb 14 15:23:21 2003
@@ -237,3 +237,5 @@
 	/* enable printk-access to this driver */
 	register_console(&sclp_console);
 }
+
+console_initcall(sclp_console_init);
diff -Nru a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
--- a/drivers/s390/char/sclp_tty.c	Thu Feb  6 07:33:47 2003
+++ b/drivers/s390/char/sclp_tty.c	Fri Feb 14 15:23:21 2003
@@ -797,3 +797,6 @@
 	if (tty_register_driver(&sclp_tty_driver))
 		panic("Couldn't register sclp_tty driver\n");
 }
+
+console_initcall(sclp_tty_init);
+
diff -Nru a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
--- a/drivers/s390/char/tape_block.c	Fri Dec  6 16:20:07 2002
+++ b/drivers/s390/char/tape_block.c	Sat Mar  8 14:50:22 2003
@@ -333,12 +333,10 @@
 	int rc;
 
 	/* Register the tape major number to the kernel */
-	rc = register_blkdev(tapeblock_major, "tBLK", &tapeblock_fops);
-	if (rc < 0) {
-		PRINT_ERR("can't get major %d for block device\n",
-			  tapeblock_major);
+	rc = register_blkdev(tapeblock_major, "tBLK");
+	if (rc < 0)
 		return rc;
-	}
+
 	if (tapeblock_major == 0)
 		tapeblock_major = rc;
 	PRINT_INFO("tape gets major %d for block device\n", tapeblock_major);
diff -Nru a/drivers/s390/char/tuball.c b/drivers/s390/char/tuball.c
--- a/drivers/s390/char/tuball.c	Wed Oct  9 07:01:46 2002
+++ b/drivers/s390/char/tuball.c	Fri Feb 14 15:24:00 2003
@@ -131,7 +131,7 @@
 #else
 #define tub3270_con_devno console_device
 
-void __init tub3270_con_init(void)
+static void __init tub3270_con_init(void)
 {
 	tub3270_con_bcb.bc_len = 65536;
 	if (!CONSOLE_IS_3270)
@@ -140,6 +140,8 @@
 		tub3270_con_bcb.bc_len);
 	register_console(&tub3270_con);
 }
+console_initcall(tub3270_con_init);
+
 #endif
 
 static kdev_t
diff -Nru a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
--- a/drivers/sbus/char/jsflash.c	Mon Oct 28 11:57:56 2002
+++ b/drivers/sbus/char/jsflash.c	Sat Mar  8 14:50:22 2003
@@ -570,9 +570,7 @@
 		jsfd_disk[i] = disk;
 	}
 
-	if (register_blkdev(JSFD_MAJOR, "jsfd", &jsfd_fops)) {
-		printk("jsfd_init: unable to get major number %d\n",
-		    JSFD_MAJOR);
+	if (register_blkdev(JSFD_MAJOR, "jsfd")) {
 		err = -EIO;
 		goto out;
 	}
diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
--- a/drivers/scsi/Kconfig	Tue Feb 18 01:04:49 2003
+++ b/drivers/scsi/Kconfig	Wed Mar  5 23:02:07 2003
@@ -946,16 +946,6 @@
 	  Please read <file:drivers/scsi/sym53c8xx_2/Documentation.txt> for more
 	  information.
 
-config SCSI_ZALON
-	tristate "Zalon SCSI support"
-	depends on GSC && SCSI
-	help
-	  The Zalon is a GSC/HSC bus interface chip that sits between the
-	  PA-RISC processor and the NCR 53c720 SCSI controller on C100,
-	  C110, J200, J210 and some D, K & R-class machines.  It's also
-	  used on the add-in Bluefish, Barracuda & Shrike SCSI cards.
-	  Say Y here if you have one of these machines or cards.
-
 config SCSI_SYM53C8XX_DMA_ADDRESSING_MODE
 	int "DMA addressing mode"
 	depends on SCSI_SYM53C8XX_2
@@ -1010,9 +1000,19 @@
 	  If you say Y here, the driver will preferently use normal IO rather than 
 	  memory mapped IO.
 
+config SCSI_ZALON
+	tristate "Zalon SCSI support"
+	depends on GSC && SCSI
+	help
+	  The Zalon is a GSC/HSC bus interface chip that sits between the
+	  PA-RISC processor and the NCR 53c720 SCSI controller on C100,
+	  C110, J200, J210 and some D, K & R-class machines.  It's also
+	  used on the add-in Bluefish, Barracuda & Shrike SCSI cards.
+	  Say Y here if you have one of these machines or cards.
+
 config SCSI_NCR53C8XX
 	tristate "NCR53C8XX SCSI support"
-	depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI
+	depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI_ZALON!=y && SCSI
 	---help---
 	  This is the BSD ncr driver adapted to Linux for the NCR53C8XX family
 	  of PCI-SCSI controllers.  This driver supports parity checking,
diff -Nru a/drivers/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile
--- a/drivers/scsi/aic7xxx/aicasm/Makefile	Tue Dec 10 11:02:52 2002
+++ b/drivers/scsi/aic7xxx/aicasm/Makefile	Thu Feb 20 08:39:57 2003
@@ -10,9 +10,10 @@
 GENSRCS=	$(YSRCS:.y=.c) $(LSRCS:.l=.c)
 
 SRCS=	${CSRCS} ${GENSRCS}
+LIBS=	-ldb
 CLEANFILES= ${GENSRCS} ${GENHDRS} $(YSRCS:.y=.output)
 # Override default kernel CFLAGS.  This is a userland app.
-AICASM_CFLAGS:= -I/usr/include -I. -ldb
+AICASM_CFLAGS:= -I/usr/include -I.
 YFLAGS= -d
 
 NOMAN=	noman
@@ -30,7 +31,7 @@
 endif
 
 $(PROG):  ${GENHDRS} $(SRCS)
-	$(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG)
+	$(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) $(LIBS)
 
 aicdb.h:
 	@if [ -e "/usr/include/db3/db_185.h" ]; then		\
@@ -45,8 +46,9 @@
 		echo "*** Install db development libraries";	\
 	 fi
 
+clean-files := $(CLEANFILES) $(PROG)
 clean:
-	rm -f $(CLEANFILES) $(PROG)
+	rm -f $(clean-files)
 
 aicasm_gram.c aicasm_gram.h: aicasm_gram.y
 	$(YACC) $(YFLAGS) -b $(<:.y=) $<
diff -Nru a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
--- a/drivers/scsi/fdomain.c	Thu Feb 20 04:16:32 2003
+++ b/drivers/scsi/fdomain.c	Thu Feb 27 09:39:04 2003
@@ -271,13 +271,8 @@
 
  **************************************************************************/
 
+#include <linux/config.h>
 #include <linux/module.h>
-
-#ifdef PCMCIA
-#undef MODULE
-#endif
-
-#include <linux/config.h>	/* for CONFIG_PCI */
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/blk.h>
@@ -295,9 +290,13 @@
 
 #include "scsi.h"
 #include "hosts.h"
-#include "fdomain.h"
+
+MODULE_AUTHOR("Rickard E. Faith");
+MODULE_DESCRIPTION("Future domain SCSI driver");
+MODULE_LICENSE("GPL");
+
   
-#define VERSION          "$Revision: 5.50 $"
+#define VERSION          "$Revision: 5.51 $"
 
 /* START OF USER DEFINABLE OPTIONS */
 
@@ -421,15 +420,12 @@
 
 static void              do_fdomain_16x0_intr( int irq, void *dev_id,
 					    struct pt_regs * regs );
+int		 	fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt);
 
-#ifdef MODULE
-				/* Allow insmod parameters to be like LILO
-                                   parameters.  For example:
-				   insmod fdomain fdomain=0x140,11
-				*/
+/* Allow insmod parameters to be like LILO parameters.  For example:
+   insmod fdomain fdomain=0x140,11 */
 static char * fdomain = NULL;
 MODULE_PARM(fdomain, "s");
-#endif
 
 static unsigned long addresses[] = {
    0xc8000,
@@ -561,7 +557,7 @@
    printk( "\n" );
 }
 
-static int __init fdomain_setup(char *str)
+int __init fdomain_setup(char *str)
 {
 	int ints[4];
 
@@ -862,7 +858,7 @@
 }
 #endif
 
-static int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
+struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt )
 {
    int              retcode;
    struct Scsi_Host *shpnt;
@@ -879,13 +875,6 @@
    unsigned char    buf[buflen];
 #endif
 
-   tpnt->proc_name = "fdomain";
-
-#ifdef MODULE
-	if (fdomain)
-		fdomain_setup(fdomain);
-#endif
-   
    if (setup_called) {
 #if DEBUG_DETECT
       printk( "scsi: <fdomain> No BIOS, using port_base = 0x%x, irq = %d\n",
@@ -895,7 +884,7 @@
 	 printk( "scsi: <fdomain> Cannot locate chip at port base 0x%x\n",
 		 port_base );
 	 printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
-	 return 0;
+	 return NULL;
       }
    } else {
       int flag = 0;
@@ -910,7 +899,7 @@
 
 	 if (!flag) {
 	    printk( "scsi: <fdomain> Detection failed (no card)\n" );
-	    return 0;
+	    return NULL;
 	 }
       }
    }
@@ -936,7 +925,7 @@
       if (setup_called) {
 	 printk(KERN_ERR "scsi: <fdomain> Bad LILO/INSMOD parameters?\n");
       }
-      return 0;
+      return NULL;
    }
 
    if (this_id) {
@@ -957,7 +946,7 @@
 
    shpnt = scsi_register( tpnt, 0 );
    if(shpnt == NULL)
-   	return 0;
+   	return NULL;
    shpnt->irq = interrupt_level;
    shpnt->io_port = port_base;
    scsi_set_device(shpnt, &pdev->dev);
@@ -967,7 +956,7 @@
    /* Log IRQ with kernel */   
    if (!interrupt_level) {
       printk(KERN_ERR "scsi: <fdomain> Card Detected, but driver not loaded (no IRQ)\n" );
-      return 0;
+      return NULL;
    } else {
       /* Register the IRQ with the kernel */
 
@@ -988,7 +977,7 @@
 	    printk(KERN_ERR "                Send mail to faith@acm.org\n" );
 	 }
 	 printk(KERN_ERR "scsi: <fdomain> Detected, but driver not loaded (IRQ)\n" );
-	 return 0;
+	 return NULL;
       }
    }
 
@@ -1048,7 +1037,14 @@
    }
 #endif
 
-   return 1;			/* Maximum of one adapter will be detected. */
+   return shpnt;
+}
+
+static int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
+{
+	if (fdomain)
+		fdomain_setup(fdomain);
+	return (__fdomain_16x0_detect(tpnt) != NULL);
 }
 
 static const char *fdomain_16x0_info( struct Scsi_Host *ignore )
@@ -1150,8 +1146,9 @@
 {
    int           status;
    unsigned long timeout;
+#if ERRORS_ONLY
    static int    flag = 0;
-
+#endif
 
    outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
    outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
@@ -1574,6 +1571,7 @@
 
 /* End of code derived from Tommy Thorn's work. */
 
+#if DEBUG_ABORT
 static void print_info(Scsi_Cmnd *SCpnt)
 {
    unsigned int imr;
@@ -1643,6 +1641,7 @@
 	 printk( "Configuration 2  = 0x%02x\n",
 		 inb( port_base + Configuration2 ) );
 }
+#endif
 
 static int fdomain_16x0_abort( Scsi_Cmnd *SCpnt)
 {
@@ -1670,7 +1669,7 @@
    return SUCCESS;
 }
 
-static int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt)
+int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt)
 {
    outb( 1, SCSI_Cntl_port );
    do_pause( 2 );
@@ -1866,9 +1865,29 @@
 	return 0;
 }
 
-MODULE_LICENSE("GPL");
-
-/* Eventually this will go into an include file, but this will be later */
-static Scsi_Host_Template driver_template = FDOMAIN_16X0;
+Scsi_Host_Template fdomain_driver_template = {
+	.module			= THIS_MODULE,
+	.name			= "fdomain",
+	.proc_name		= "fdomain",
+	.proc_info		= fdomain_16x0_proc_info,
+	.detect			= fdomain_16x0_detect,
+	.info			= fdomain_16x0_info,
+	.command		= fdomain_16x0_command,
+	.queuecommand		= fdomain_16x0_queue,
+	.eh_abort_handler	= fdomain_16x0_abort,
+	.eh_bus_reset_handler	= fdomain_16x0_bus_reset,
+	.eh_device_reset_handler = fdomain_16x0_device_reset,
+	.eh_host_reset_handler	= fdomain_16x0_host_reset,
+	.bios_param		= fdomain_16x0_biosparam,
+	.release		= fdomain_16x0_release,
+	.can_queue		= 1,
+	.this_id		= 6,
+	.sg_tablesize		= 64,
+	.cmd_per_lun		= 1,
+	.use_clustering		= DISABLE_CLUSTERING,
+};
 
+#ifndef PCMCIA
+#define driver_template fdomain_driver_template
 #include "scsi_module.c"
+#endif
diff -Nru a/drivers/scsi/fdomain.h b/drivers/scsi/fdomain.h
--- a/drivers/scsi/fdomain.h	Tue Dec 10 12:28:33 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,59 +0,0 @@
-/* fdomain.h -- Header for Future Domain TMC-16x0 driver
- * Created: Sun May  3 18:47:33 1992 by faith@cs.unc.edu
- * Revised: Thu Oct 12 13:21:35 1995 by faith@acm.org
- * Author: Rickard E. Faith, faith@cs.unc.edu
- * Copyright 1992, 1993, 1994, 1995 Rickard E. Faith
- *
- * $Id: fdomain.h,v 5.12 1995/10/12 19:01:09 root Exp $
-
- * 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, 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.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
-#ifndef _FDOMAIN_H
-#define _FDOMAIN_H
-
-static int        fdomain_16x0_detect( Scsi_Host_Template *);
-static int        fdomain_16x0_command( Scsi_Cmnd *);
-static int        fdomain_16x0_abort(Scsi_Cmnd *);
-static const char *fdomain_16x0_info(struct Scsi_Host *);
-static int        fdomain_16x0_bus_reset(Scsi_Cmnd *); 
-static int        fdomain_16x0_host_reset(Scsi_Cmnd *); 
-static int        fdomain_16x0_device_reset(Scsi_Cmnd *); 
-static int        fdomain_16x0_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-static int        fdomain_16x0_biosparam(struct scsi_device *,
-		struct block_device *, sector_t, int * );
-static int        fdomain_16x0_proc_info(char *buffer, char **start, off_t offset,
-				   int length, int hostno, int inout );
-static int        fdomain_16x0_release(struct Scsi_Host *shpnt);
-
-#define FDOMAIN_16X0 { .proc_info      		= fdomain_16x0_proc_info,           \
-		       .detect         		= fdomain_16x0_detect,              \
-		       .info           		= fdomain_16x0_info,                \
-		       .command        		= fdomain_16x0_command,             \
-		       .queuecommand   		= fdomain_16x0_queue,               \
-		       .eh_abort_handler	= fdomain_16x0_abort,               \
-		       .eh_bus_reset_handler	= fdomain_16x0_bus_reset,           \
-		       .eh_device_reset_handler	= fdomain_16x0_device_reset,        \
-		       .eh_host_reset_handler	= fdomain_16x0_host_reset,          \
-		       .bios_param		= fdomain_16x0_biosparam,           \
-		       .release			= fdomain_16x0_release,		  \
-		       .can_queue		= 1, 				  \
-		       .this_id  		= 6, 				  \
-		       .sg_tablesize		= 64, 				  \
-		       .cmd_per_lun		= 1, 				  \
-		       .use_clustering		= DISABLE_CLUSTERING		  \
-}
-#endif
diff -Nru a/drivers/scsi/i91uscsi.h b/drivers/scsi/i91uscsi.h
--- a/drivers/scsi/i91uscsi.h	Mon Feb  4 23:52:37 2002
+++ b/drivers/scsi/i91uscsi.h	Sun Feb 16 16:20:08 2003
@@ -70,12 +70,6 @@
 #ifndef NULL
 #define NULL     0		/* zero          */
 #endif
-#ifndef TRUE
-#define TRUE     (1)		/* boolean true  */
-#endif
-#ifndef FALSE
-#define FALSE    (0)		/* boolean false */
-#endif
 #ifndef FAILURE
 #define FAILURE  (-1)
 #endif
@@ -597,11 +591,9 @@
 	TCS HCS_Tcs[MAX_TARGETS];	/* 78 */
 	ULONG pSRB_head;	/* SRB save queue header     */
 	ULONG pSRB_tail;	/* SRB save queue tail       */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spinlock_t HCS_AvailLock;
 	spinlock_t HCS_SemaphLock;
 	spinlock_t pSRB_lock;	/* SRB queue lock            */
-#endif
 } HCS;
 
 /* Bit Definition for HCB_Config */
diff -Nru a/drivers/scsi/imm.c b/drivers/scsi/imm.c
--- a/drivers/scsi/imm.c	Mon Feb 17 17:02:24 2003
+++ b/drivers/scsi/imm.c	Thu Mar  6 15:50:31 2003
@@ -174,6 +174,7 @@
 	    parport_unregister_device(imm_hosts[i].dev);
 	    continue;
 	}
+
 	/* now the glue ... */
 	switch (imm_hosts[i].mode) {
 	case IMM_NIBBLE:
@@ -218,7 +219,7 @@
 
 /* This is to give the imm driver a way to modify the timings (and other
  * parameters) by writing to the /proc/scsi/imm/0 file.
- * Very simple method really... (To simple, no error checking :( )
+ * Very simple method really... (Too simple, no error checking :( )
  * Reason: Kernel hackers HATE having to unload and reload modules for
  * testing...
  * Also gives a method to use a script to obtain optimum timings (TODO)
@@ -948,7 +949,7 @@
     unsigned char l = 0, h = 0;
     int retv, x;
 
-    /* First check for any errors that may of occurred
+    /* First check for any errors that may have occurred
      * Here we check for internal errors
      */
     if (tmp->failed)
diff -Nru a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c
--- a/drivers/scsi/inia100.c	Fri Jan  3 10:58:49 2003
+++ b/drivers/scsi/inia100.c	Sun Feb 16 16:18:17 2003
@@ -67,12 +67,6 @@
  *          - Fix allocation of scsi host structs and private data
  **************************************************************************/
 
-#define CVT_LINUX_VERSION(V,P,S)        (V * 65536 + P * 256 + S)
-
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
 #include <linux/module.h>
 
 #include <linux/errno.h>
diff -Nru a/drivers/scsi/inia100.h b/drivers/scsi/inia100.h
--- a/drivers/scsi/inia100.h	Tue Dec 10 12:28:32 2002
+++ b/drivers/scsi/inia100.h	Sun Feb 16 16:18:17 2003
@@ -63,14 +63,6 @@
  *		   merged them into a single header used by both .c files.
  ****************************************************************************/
 
-#ifndef	CVT_LINUX_VERSION
-#define	CVT_LINUX_VERSION(V,P,S)	(((V) * 65536) + ((P) * 256) + (S))
-#endif
-
-#ifndef	LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/pci.h>
@@ -116,12 +108,6 @@
 
 #ifndef NULL
 #define NULL     0		/* zero          */
-#endif
-#ifndef TRUE
-#define TRUE     (1)		/* boolean true  */
-#endif
-#ifndef FALSE
-#define FALSE    (0)		/* boolean false */
 #endif
 #ifndef FAILURE
 #define FAILURE  (-1)
diff -Nru a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
--- a/drivers/scsi/ncr53c8xx.c	Tue Feb 25 02:46:22 2003
+++ b/drivers/scsi/ncr53c8xx.c	Wed Mar  5 23:02:17 2003
@@ -5024,7 +5024,6 @@
 **==========================================================
 */
 
-#ifdef MODULE
 static int ncr_detach(ncb_p np)
 {
 	ccb_p cp;
@@ -5160,7 +5159,6 @@
 
 	return 1;
 }
-#endif
 
 /*==========================================================
 **
@@ -8935,7 +8933,6 @@
 }
 
 
-#ifdef MODULE
 int ncr53c8xx_release(struct Scsi_Host *host)
 {
 #ifdef DEBUG_NCR53C8XX
@@ -8945,7 +8942,6 @@
 
      return 1;
 }
-#endif
 
 
 /*
diff -Nru a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h
--- a/drivers/scsi/ncr53c8xx.h	Tue Dec 10 12:28:33 2002
+++ b/drivers/scsi/ncr53c8xx.h	Mon Feb 17 12:02:10 2003
@@ -60,17 +60,12 @@
 int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int ncr53c8xx_reset(Scsi_Cmnd *, unsigned int);
 int ncr53c8xx_slave_configure(Scsi_Device *);
-
-#ifdef MODULE
 int ncr53c8xx_release(struct Scsi_Host *);
-#else
-#define ncr53c8xx_release NULL
-#endif
 
 
 #if	LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75)
 
-#define NCR53C8XX {     .name           = "",			\
+#define NCR53C8XX {     .name           = "ncr53c8xx",		\
 			.detect         = ncr53c8xx_detect,	\
 			.release        = ncr53c8xx_release,	\
 			.info           = ncr53c8xx_info, 	\
diff -Nru a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig
--- a/drivers/scsi/pcmcia/Kconfig	Sun Feb  9 17:29:49 2003
+++ b/drivers/scsi/pcmcia/Kconfig	Thu Feb 27 08:33:17 2003
@@ -3,22 +3,11 @@
 #
 
 menu "PCMCIA SCSI adapter support"
-	depends on SCSI!=n && HOTPLUG && PCMCIA!=n
-
-config SCSI_PCMCIA
-	bool "PCMCIA SCSI adapter support"
-	help
-	  Say Y here if you intend to attach a PCMCIA or CardBus card to your
-	  computer which acts as a SCSI host adapter. These are credit card
-	  size devices often used with laptops.
-
-	  Note that the answer to this question won't directly affect the
-	  kernel: saying N will just cause the configurator to skip all
-	  the questions PCMCIA SCSI host adapters.
+	depends on SCSI!=n && PCMCIA!=n
 
 config PCMCIA_AHA152X
 	tristate "Adaptec AHA152X PCMCIA support"
-	depends on SCSI_PCMCIA && m
+	depends on m
 	help
 	  Say Y here if you intend to attach this type of PCMCIA SCSI host
 	  adapter to your computer.
@@ -30,7 +19,7 @@
 
 config PCMCIA_FDOMAIN
 	tristate "Future Domain PCMCIA support"
-	depends on SCSI_PCMCIA && m
+	depends on m
 	help
 	  Say Y here if you intend to attach this type of PCMCIA SCSI host
 	  adapter to your computer.
@@ -42,7 +31,7 @@
 
 config PCMCIA_NINJA_SCSI
 	tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support"
-	depends on SCSI_PCMCIA && m
+	depends on m
 	help
 	  If you intend to attach this type of PCMCIA SCSI host adapter to
 	  your computer, say Y here and read
@@ -55,7 +44,7 @@
 
 config PCMCIA_QLOGIC
 	tristate "Qlogic PCMCIA support"
-	depends on SCSI_PCMCIA && m
+	depends on m
 	help
 	  Say Y here if you intend to attach this type of PCMCIA SCSI host
 	  adapter to your computer.
@@ -65,10 +54,4 @@
 	  whenever you want).  If you want to compile it as a module, say M
 	  here and read <file:Documentation/modules.txt>.
 
-config PCMCIA_SCSICARD
-	bool
-	depends on PCMCIA_QLOGIC=y || PCMCIA_AHA152X=y || PCMCIA_FDOMAIN=y || PCMCIA_NINJA_SCSI=y
-	default y
-
 endmenu
-
diff -Nru a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
--- a/drivers/scsi/pcmcia/fdomain_stub.c	Tue Feb  4 12:12:27 2003
+++ b/drivers/scsi/pcmcia/fdomain_stub.c	Thu Feb 27 09:35:58 2003
@@ -61,15 +61,15 @@
 MODULE_DESCRIPTION("Future Domain PCMCIA SCSI driver");
 MODULE_LICENSE("Dual MPL/GPL");
 
-#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
-
 /* Bit map of interrupts to choose from */
-INT_MODULE_PARM(irq_mask, 0xdeb8);
+static int irq_mask = 0xdeb8;
+MODULE_PARM(irq_mask, "i");
 static int irq_list[4] = { -1 };
 MODULE_PARM(irq_list, "1-4i");
 
 #ifdef PCMCIA_DEBUG
-INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+static int pc_debug = PCMCIA_DEBUG;
+MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
 "fdomain_cs.c 1.47 2001/10/13 00:08:52 (David Hinds)";
@@ -81,11 +81,15 @@
 
 typedef struct scsi_info_t {
     dev_link_t		link;
+    struct Scsi_Host	*host;
     int			ndev;
     dev_node_t		node[8];
 } scsi_info_t;
 
+extern Scsi_Host_Template fdomain_driver_template;
 extern void fdomain_setup(char *str, int *ints);
+extern struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt );
+extern int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt);
 
 static void fdomain_release(u_long arg);
 static int fdomain_event(event_t event, int priority,
@@ -94,8 +98,6 @@
 static dev_link_t *fdomain_attach(void);
 static void fdomain_detach(dev_link_t *);
 
-#define driver_template fdomain_driver_template
-extern Scsi_Host_Template fdomain_driver_template;
 
 static dev_link_t *dev_list = NULL;
 
@@ -231,7 +233,6 @@
     link->conf.ConfigBase = parse.config.base;
 
     /* Configure card */
-    driver_template.module = &__this_module;
     link->state |= DEV_CONFIG;
     
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
@@ -260,14 +261,18 @@
     sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ);
     fdomain_setup(str, ints);
     
-    scsi_register_host(&driver_template);
+    host = __fdomain_16x0_detect(&fdomain_driver_template);
+    if (!host) {
+        printk(KERN_INFO "fdomain_cs: no SCSI devices found\n");
+	goto cs_failed;
+    }
+ 
+    scsi_add_host(host, NULL);
 
     tail = &link->dev;
     info->ndev = 0;
-    for (host = scsi_host_get_next(NULL); host;
-	 host = scsi_host_get_next(host))
-	if (host->hostt == &driver_template)
-	    list_for_each_entry (dev, &host->my_devices, siblings) {
+   
+    list_for_each_entry (dev, &host->my_devices, siblings) {
 	    u_long arg[2], id;
 	    kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
 	    id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) +
@@ -296,10 +301,11 @@
 	    }
 	    *tail = node; tail = &node->next;
 	    info->ndev++;
-	}
+
+    }
+
     *tail = NULL;
-    if (info->ndev == 0)
-	printk(KERN_INFO "fdomain_cs: no SCSI devices found\n");
+    info->host = host;
     
     link->state &= ~DEV_CONFIG_PENDING;
     return;
@@ -316,30 +322,22 @@
 static void fdomain_release(u_long arg)
 {
     dev_link_t *link = (dev_link_t *)arg;
+    scsi_info_t *info = link->priv;
 
     DEBUG(0, "fdomain_release(0x%p)\n", link);
 
-#warning This does not protect you.  You need some real fix for your races.
-#if 0
-    if (GET_USE_COUNT(&__this_module) != 0) {
-	DEBUG(1, "fdomain_cs: release postponed, "
-	      "device still open\n");
-	link->state |= DEV_STALE_CONFIG;
-	return;
-    }
-#endif
-
-    scsi_unregister_host(&driver_template);
+    scsi_remove_host(info->host);
     link->dev = NULL;
     
     CardServices(ReleaseConfiguration, link->handle);
     CardServices(ReleaseIO, link->handle, &link->io);
     CardServices(ReleaseIRQ, link->handle, &link->irq);
-    
+
+    scsi_unregister(info->host);
+
     link->state &= ~DEV_CONFIG;
     if (link->state & DEV_STALE_LINK)
 	fdomain_detach(link);
-    
 } /* fdomain_release */
 
 /*====================================================================*/
@@ -374,7 +372,7 @@
     case CS_EVENT_CARD_RESET:
 	if (link->state & DEV_CONFIG) {
 	    CardServices(RequestConfiguration, link->handle, &link->conf);
-	    fdomain_16x0_reset(NULL, 0);
+	    fdomain_16x0_bus_reset(NULL);
 	}
 	break;
     }
diff -Nru a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
--- a/drivers/scsi/pcmcia/qlogic_stub.c	Mon Feb  3 23:47:00 2003
+++ b/drivers/scsi/pcmcia/qlogic_stub.c	Thu Feb 27 09:12:48 2003
@@ -55,7 +55,11 @@
 #include <pcmcia/ds.h>
 #include <pcmcia/ciscode.h>
 
+
+extern Scsi_Host_Template qlogicfas_driver_template;
 extern void qlogicfas_preset(int port, int irq);
+extern struct Scsi_Host *__qlogicfas_detect(Scsi_Host_Template *);
+extern int qlogicfas_bus_reset(Scsi_Cmnd *);
 
 #ifdef PCMCIA_DEBUG
 static int pc_debug = PCMCIA_DEBUG;
@@ -81,6 +85,7 @@
 
 typedef struct scsi_info_t {
 	dev_link_t link;
+	struct Scsi_Host *host;
 	unsigned short manf_id;
 	int ndev;
 	dev_node_t node[8];
@@ -92,9 +97,6 @@
 static dev_link_t *qlogic_attach(void);
 static void qlogic_detach(dev_link_t *);
 
-/* Import our driver template */
-extern Scsi_Host_Template qlogicfas_driver_template;
-#define driver_template qlogicfas_driver_template
 
 static dev_link_t *dev_list = NULL;
 
@@ -233,7 +235,6 @@
 		info->manf_id = le16_to_cpu(tuple.TupleData[0]);
 
 	/* Configure card */
-	driver_template.module = &__this_module;
 	link->state |= DEV_CONFIG;
 
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
@@ -272,46 +273,52 @@
 	else
 		qlogicfas_preset(link->io.BasePort1, link->irq.AssignedIRQ);
 
-	scsi_register_host(&driver_template);
-
 	tail = &link->dev;
 	info->ndev = 0;
-	for (host = scsi_host_get_next(NULL); host; host = scsi_host_get_next(host))
-		if (host->hostt == &driver_template)
-			list_for_each_entry (dev, &host->my_devices, siblings) {
-				u_long arg[2], id;
-				kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
-				id = (arg[0] & 0x0f) + ((arg[0] >> 4) & 0xf0) + ((arg[0] >> 8) & 0xf00) + ((arg[0] >> 12) & 0xf000);
-				node = &info->node[info->ndev];
-				node->minor = 0;
-				switch (dev->type) {
-				case TYPE_TAPE:
-					node->major = SCSI_TAPE_MAJOR;
-					sprintf(node->dev_name, "st#%04lx", id);
-					break;
-				case TYPE_DISK:
-				case TYPE_MOD:
-					node->major = SCSI_DISK0_MAJOR;
-					sprintf(node->dev_name, "sd#%04lx", id);
-					break;
-				case TYPE_ROM:
-				case TYPE_WORM:
-					node->major = SCSI_CDROM_MAJOR;
-					sprintf(node->dev_name, "sr#%04lx", id);
-					break;
-				default:
-					node->major = SCSI_GENERIC_MAJOR;
-					sprintf(node->dev_name, "sg#%04lx", id);
-					break;
-				}
-				*tail = node;
-				tail = &node->next;
-				info->ndev++;
-			}
-	*tail = NULL;
-	if (info->ndev == 0)
+
+	host = __qlogicfas_detect(&qlogicfas_driver_template);
+	if (!host) {
 		printk(KERN_INFO "qlogic_cs: no SCSI devices found\n");
+		goto out;
+	}
+
+	scsi_add_host(host, NULL);
+
+	list_for_each_entry(dev, &host->my_devices, siblings) {
+		u_long arg[2], id;
+		kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
+		id = (arg[0] & 0x0f) + ((arg[0] >> 4) & 0xf0) + ((arg[0] >> 8) & 0xf00) + ((arg[0] >> 12) & 0xf000);
+		node = &info->node[info->ndev];
+		node->minor = 0;
+		switch (dev->type) {
+		case TYPE_TAPE:
+			node->major = SCSI_TAPE_MAJOR;
+			sprintf(node->dev_name, "st#%04lx", id);
+			break;
+		case TYPE_DISK:
+		case TYPE_MOD:
+			node->major = SCSI_DISK0_MAJOR;
+			sprintf(node->dev_name, "sd#%04lx", id);
+			break;
+		case TYPE_ROM:
+		case TYPE_WORM:
+			node->major = SCSI_CDROM_MAJOR;
+			sprintf(node->dev_name, "sr#%04lx", id);
+			break;
+		default:
+			node->major = SCSI_GENERIC_MAJOR;
+			sprintf(node->dev_name, "sg#%04lx", id);
+			break;
+		}
+		*tail = node;
+		tail = &node->next;
+		info->ndev++;
+	}
 
+	*tail = NULL;
+	info->host = host;
+
+out:
 	link->state &= ~DEV_CONFIG_PENDING;
 	return;
 
@@ -327,29 +334,22 @@
 static void qlogic_release(u_long arg)
 {
 	dev_link_t *link = (dev_link_t *) arg;
+	scsi_info_t *info = link->priv;
 
 	DEBUG(0, "qlogic_release(0x%p)\n", link);
 
-#warning This does not protect you.  You need some real fix for your races.
-#if 0
-	if (GET_USE_COUNT(&__this_module) != 0) {
-		DEBUG(0, "qlogic_cs: release postponed, device still open\n");
-		link->state |= DEV_STALE_CONFIG;
-		return;
-	}
-#endif
-
-	scsi_unregister_host(&driver_template);
+	scsi_remove_host(info->host);
 	link->dev = NULL;
 
 	CardServices(ReleaseConfiguration, link->handle);
 	CardServices(ReleaseIO, link->handle, &link->io);
 	CardServices(ReleaseIRQ, link->handle, &link->irq);
 
+	scsi_unregister(info->host);
+
 	link->state &= ~DEV_CONFIG;
 	if (link->state & DEV_STALE_LINK)
 		qlogic_detach(link);
-
 }				/* qlogic_release */
 
 /*====================================================================*/
@@ -390,7 +390,7 @@
 				outb(0x04, link->io.BasePort1 + 0xd);
 			}
 			/* Ugggglllyyyy!!! */
-			driver_template.eh_bus_reset_handler(NULL);
+			qlogicfas_bus_reset(NULL);
 		}
 		break;
 	}
diff -Nru a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c
--- a/drivers/scsi/qlogicfas.c	Tue Feb  4 01:41:00 2003
+++ b/drivers/scsi/qlogicfas.c	Thu Feb 27 09:13:04 2003
@@ -127,11 +127,6 @@
 #endif
 
 #include <linux/module.h>
-
-#ifdef PCMCIA
-#undef MODULE
-#endif
-
 #include <linux/blk.h>		/* to get disk capacity */
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -148,7 +143,6 @@
 
 #include "scsi.h"
 #include "hosts.h"
-#include "qlogicfas.h"
 
 /*----------------------------------------------------------------*/
 /* driver state info, local to driver */
@@ -166,6 +160,8 @@
 static int qlcfg9 = ((XTALFREQ + 4) / 5);
 static int qlcfgc = (FASTCLK << 3) | (FASTSCSI << 4);
 
+int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *));
+
 /*----------------------------------------------------------------*/
 /* The qlogic card uses two register maps - These macros select which one */
 #define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd ))
@@ -631,14 +627,12 @@
  *	Look for qlogic card and init if found 
  */
  
-int __devinit qlogicfas_detect(Scsi_Host_Template * host)
+struct Scsi_Host *__qlogicfas_detect(Scsi_Host_Template *host)
 {
 	int i, j;		/* these are only used by IRQ detect */
 	int qltyp;		/* type of chip */
 	struct Scsi_Host *hreg;	/* registered host structure */
 
-	host->proc_name = "qlogicfas";
-
 	/*	Qlogic Cards only exist at 0x230 or 0x330 (the chip itself
 	 *	decodes the address - I check 230 first since MIDI cards are
 	 *	typically at 0x330
@@ -659,7 +653,7 @@
 			release_region(qbase, 0x10);
 		}
 		if (qbase == 0x430)
-			return 0;
+			return NULL;;
 	} else
 		printk(KERN_INFO "Ql: Using preset base address of %03x\n", qbase);
 
@@ -726,16 +720,21 @@
 		qltyp, qbase, qlirq, QL_TURBO_PDMA);
 	host->name = qinfo;
 
-	return 1;
+	return hreg;
 
 err_release_mem:
 	release_region(qbase, 0x10);
 	if (host->can_queue)
 		free_irq(qlirq, do_ql_ihandl);
-	return 0;
+	return NULL;;
 
 }
 
+int __devinit qlogicfas_detect(Scsi_Host_Template *sht)
+{
+	return (__qlogicfas_detect(sht) != NULL);
+}
+
 /* 
  *	Return bios parameters 
  */
@@ -777,7 +776,7 @@
  *	the PCMCIA qlogic_stub code. This wants fixing
  */
 
-static int qlogicfas_bus_reset(Scsi_Cmnd * cmd)
+int qlogicfas_bus_reset(Scsi_Cmnd * cmd)
 {
 	qabort = 2;
 	ql_zap();
@@ -818,9 +817,27 @@
 /*
  *	The driver template is also needed for PCMCIA
  */
- 
-Scsi_Host_Template qlogicfas_driver_template = QLOGICFAS;
-#define driver_template qlogicfas_driver_template
+Scsi_Host_Template qlogicfas_driver_template = {
+	.module			= THIS_MODULE,
+	.name			= "qlogicfas",
+	.proc_name		= "qlogicfas",
+	.detect			= qlogicfas_detect,
+	.info			= qlogicfas_info,
+	.command		= qlogicfas_command,
+	.queuecommand		= qlogicfas_queuecommand,
+	.eh_abort_handler	= qlogicfas_abort,
+	.eh_bus_reset_handler	= qlogicfas_bus_reset,
+	.eh_device_reset_handler= qlogicfas_device_reset,
+	.eh_host_reset_handler	= qlogicfas_host_reset,
+	.bios_param		= qlogicfas_biosparam,
+	.can_queue		= 0,
+	.this_id		= -1,
+	.sg_tablesize		= SG_ALL,
+	.cmd_per_lun		= 1,
+	.use_clustering		= DISABLE_CLUSTERING,
+};
 
+#ifndef PCMCIA
+#define driver_template qlogicfas_driver_template
 #include "scsi_module.c"
-
+#endif
diff -Nru a/drivers/scsi/qlogicfas.h b/drivers/scsi/qlogicfas.h
--- a/drivers/scsi/qlogicfas.h	Tue Dec 10 12:28:33 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,34 +0,0 @@
-#ifndef _QLOGICFAS_H
-#define _QLOGICFAS_H
-
-static int qlogicfas_detect(Scsi_Host_Template * );
-static const char * qlogicfas_info(struct Scsi_Host *);
-static int qlogicfas_command(Scsi_Cmnd *);
-static int qlogicfas_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
-static int qlogicfas_abort(Scsi_Cmnd *);
-static int qlogicfas_bus_reset(Scsi_Cmnd *);
-static int qlogicfas_device_reset(Scsi_Cmnd *);
-static int qlogicfas_host_reset(Scsi_Cmnd *);
-static int qlogicfas_biosparam(struct scsi_device *, struct block_device *,
-			       sector_t, int[]);
-
-#define QLOGICFAS {						\
-	.detect         		= qlogicfas_detect,	\
-	.info           		= qlogicfas_info,		\
-	.command     			= qlogicfas_command, 	\
-	.queuecommand			= qlogicfas_queuecommand,	\
-	.eh_abort_handler          	= qlogicfas_abort,	\
-	.eh_bus_reset_handler		= qlogicfas_bus_reset,	\
-	.eh_device_reset_handler        = qlogicfas_device_reset,	\
-	.eh_host_reset_handler          = qlogicfas_host_reset,	\
-	.bios_param     = qlogicfas_biosparam,			\
-	.can_queue      = 0,					\
-	.this_id        = -1,					\
-	.sg_tablesize   = SG_ALL,					\
-	.cmd_per_lun    = 1,					\
-	.use_clustering = DISABLE_CLUSTERING			\
-}
-#endif /* _QLOGICFAS_H */
-
-
-
diff -Nru a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c
--- a/drivers/scsi/qlogicfc.c	Tue Feb 25 02:46:27 2003
+++ b/drivers/scsi/qlogicfc.c	Tue Mar  4 22:44:07 2003
@@ -694,7 +694,7 @@
 int isp2x00_detect(Scsi_Host_Template * tmpt)
 {
 	int hosts = 0;
-	int wait_time;
+	unsigned long wait_time;
 	struct Scsi_Host *host = NULL;
 	struct isp2x00_hostdata *hostdata;
 	struct pci_dev *pdev;
diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
--- a/drivers/scsi/scsi.h	Sun Feb 23 10:34:55 2003
+++ b/drivers/scsi/scsi.h	Thu Mar  6 15:50:31 2003
@@ -280,26 +280,7 @@
 #define SCSI_SET_IOCTL_LOGGING(LEVEL)  \
         SCSI_SET_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL);
 
-/*
- *  the return of the status word will be in the following format :
- *  The low byte is the status returned by the SCSI command, 
- *  with vendor specific bits masked.
- *  
- *  The next byte is the message which followed the SCSI status.
- *  This allows a stos to be used, since the Intel is a little
- *  endian machine.
- *  
- *  The final byte is a host return code, which is one of the following.
- *  
- *  IE 
- *  lsb     msb
- *  status  msg host code   
- *  
- *  Our errors returned by OUR driver, NOT SCSI message.  Or'd with
- *  SCSI message passed back to driver <IF any>.
- */
-
-
+/* host byte codes */
 #define DID_OK          0x00	/* NO error                                */
 #define DID_NO_CONNECT  0x01	/* Couldn't connect before timeout period  */
 #define DID_BUS_BUSY    0x02	/* BUS stayed busy through time out period */
diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
--- a/drivers/scsi/scsi_error.c	Sat Feb 22 08:17:01 2003
+++ b/drivers/scsi/scsi_error.c	Sat Mar  8 07:03:27 2003
@@ -92,10 +92,8 @@
  *
  * Notes:
  *    This should be turned into an inline function.  Each scsi command
- *    has it's own timer, and as it is added to the queue, we set up the
- *    timer.  When the command completes, we cancel the timer.  Pretty
- *    simple, really, especially compared to the old way of handling this
- *    crap.
+ *    has its own timer, and as it is added to the queue, we set up the
+ *    timer.  When the command completes, we cancel the timer.
  **/
 void scsi_add_timer(struct scsi_cmnd *scmd, int timeout,
 		    void (*complete)(struct scsi_cmnd *))
@@ -249,6 +247,7 @@
 {
 	if (!SCSI_SENSE_VALID(scmd))
 		return FAILED;
+
 	if (scmd->sense_buffer[2] & 0xe0)
 		return SUCCESS;
 
@@ -515,7 +514,7 @@
 	 * actually did complete normally.
 	 */
 	if (rtn == SUCCESS) {
-		int rtn = scsi_eh_completed_normally(scmd);
+		rtn = scsi_eh_completed_normally(scmd);
 		SCSI_LOG_ERROR_RECOVERY(3,
 			printk("%s: scsi_eh_completed_normally %x\n",
 			       __FUNCTION__, rtn));
@@ -545,20 +544,20 @@
 static int scsi_request_sense(struct scsi_cmnd *scmd)
 {
 	static unsigned char generic_sense[6] =
-	{REQUEST_SENSE, 0, 0, 0, 255, 0};
-	unsigned char scsi_result0[256], *scsi_result = &scsi_result0[0];
+	{REQUEST_SENSE, 0, 0, 0, 254, 0};
+	unsigned char *scsi_result;
 	int saved_result;
 	int rtn;
 
 	memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense));
 
-	if (scmd->device->host->hostt->unchecked_isa_dma) {
-		scsi_result = kmalloc(512, GFP_ATOMIC | __GFP_DMA);
-		if (unlikely(!scsi_result)) {
-			printk(KERN_ERR "%s: cannot allocate scsi_result.\n",
-					__FUNCTION__);
-			return FAILED;
-		}
+	scsi_result = kmalloc(254, GFP_ATOMIC | (scmd->device->host->hostt->unchecked_isa_dma) ? __GFP_DMA : 0);
+
+
+	if (unlikely(!scsi_result)) {
+		printk(KERN_ERR "%s: cannot allocate scsi_result.\n",
+		       __FUNCTION__);
+		return FAILED;
 	}
 
 	/*
@@ -568,11 +567,11 @@
 	 * address (db).  0 is not a valid sense code. 
 	 */
 	memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
-	memset(scsi_result, 0, 256);
+	memset(scsi_result, 0, 254);
 
 	saved_result = scmd->result;
 	scmd->request_buffer = scsi_result;
-	scmd->request_bufflen = 256;
+	scmd->request_bufflen = 254;
 	scmd->use_sg = 0;
 	scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
 	scmd->sc_data_direction = SCSI_DATA_READ;
@@ -581,13 +580,12 @@
 	rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT);
 
 	/* last chance to have valid sense data */
-	if (!SCSI_SENSE_VALID(scmd)) {
+	if(!SCSI_SENSE_VALID(scmd)) {
 		memcpy(scmd->sense_buffer, scmd->request_buffer,
-				sizeof(scmd->sense_buffer));
+		       sizeof(scmd->sense_buffer));
 	}
 
-	if (scsi_result != &scsi_result0[0])
-		kfree(scsi_result);
+	kfree(scsi_result);
 
 	/*
 	 * when we eventually call scsi_finish, we really wish to complete
@@ -703,25 +701,14 @@
 		 * upper level.
 		 */
 		if (rtn == SUCCESS)
-			scsi_eh_finish_cmd(scmd, done_q);
-		if (rtn != NEEDS_RETRY)
-			continue;
-
-		/*
-		 * we only come in here if we want to retry a
-		 * command.  the test to see whether the command
-		 * should be retried should be keeping track of the
-		 * number of tries, so we don't end up looping, of
-		 * course.
-		 */
-		scmd->state = NEEDS_RETRY;
-		rtn = scsi_eh_retry_cmd(scmd);
-		if (rtn != SUCCESS)
+			/* we don't want this command reissued, just
+			 * finished with the sense data, so set
+			 * retries to the max allowed to ensure it
+			 * won't get reissued */
+			scmd->retries = scmd->allowed;
+		else if (rtn != NEEDS_RETRY)
 			continue;
 
-		/*
-		 * we eventually hand this one back to the top level.
-		 */
 		scsi_eh_finish_cmd(scmd, done_q);
 	}
 
@@ -1193,12 +1180,12 @@
  * Notes:
  *    This is *only* called when we are examining the status after sending
  *    out the actual data command.  any commands that are queued for error
- *    recovery (i.e. test_unit_ready) do *not* come through here.
+ *    recovery (e.g. test_unit_ready) do *not* come through here.
  *
  *    When this routine returns failed, it means the error handler thread
- *    is woken.  in cases where the error code indicates an error that
+ *    is woken.  In cases where the error code indicates an error that
  *    doesn't require the error handler read (i.e. we don't need to
- *    abort/reset), then this function should return SUCCESS.
+ *    abort/reset), this function should return SUCCESS.
  **/
 int scsi_decide_disposition(struct scsi_cmnd *scmd)
 {
@@ -1214,11 +1201,11 @@
 						  __FUNCTION__));
 		return SUCCESS;
 	}
+
 	/*
 	 * first check the host byte, to see if there is anything in there
 	 * that would indicate what we need to do.
 	 */
-
 	switch (host_byte(scmd->result)) {
 	case DID_PASSTHROUGH:
 		/*
@@ -1296,11 +1283,11 @@
 	/*
 	 * next, check the message byte.
 	 */
-	if (msg_byte(scmd->result) != COMMAND_COMPLETE) {
+	if (msg_byte(scmd->result) != COMMAND_COMPLETE)
 		return FAILED;
-	}
+
 	/*
-	 * now, check the status byte to see if this indicates anything special.
+	 * check the status byte to see if this indicates anything special.
 	 */
 	switch (status_byte(scmd->result)) {
 	case QUEUE_FULL:
@@ -1321,9 +1308,12 @@
 		return SUCCESS;
 	case CHECK_CONDITION:
 		rtn = scsi_check_sense(scmd);
-		if (rtn == NEEDS_RETRY) {
+		if (rtn == NEEDS_RETRY)
 			goto maybe_retry;
-		}
+		/* if rtn == FAILED, we have no sense information;
+		 * returning FAILED will wake the error handler thread
+		 * to collect the sense and redo the decide
+		 * disposition */
 		return rtn;
 	case CONDITION_GOOD:
 	case INTERMEDIATE_GOOD:
@@ -1490,9 +1480,9 @@
 			       struct list_head *work_q,
 			       struct list_head *done_q)
 {
-	if (scsi_eh_bus_device_reset(shost, work_q, done_q))
-		if (scsi_eh_bus_reset(shost, work_q, done_q))
-			if (scsi_eh_host_reset(work_q, done_q))
+	if (!scsi_eh_bus_device_reset(shost, work_q, done_q))
+		if (!scsi_eh_bus_reset(shost, work_q, done_q))
+			if (!scsi_eh_host_reset(work_q, done_q))
 				scsi_eh_offline_sdevs(work_q, done_q);
 }
 
diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c	Sat Feb 22 12:35:33 2003
+++ b/drivers/scsi/scsi_lib.c	Sat Mar  8 07:03:27 2003
@@ -265,7 +265,6 @@
 	cmd->serial_number = 0;
 	cmd->serial_number_at_timeout = 0;
 	cmd->flags = 0;
-	cmd->retries = 0;
 	cmd->abort_reason = 0;
 
 	memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer);
diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	Fri Feb 28 12:45:00 2003
+++ b/drivers/scsi/scsi_scan.c	Thu Mar  6 16:02:09 2003
@@ -960,7 +960,6 @@
 	SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: host %d channel %d"
 	    " id %d lun %d name/id: '%s'\n", sdev->host->host_no,
 	    sdev->channel, sdev->id, sdev->lun, sdev->sdev_driverfs_dev.name));
-	return;
 }
 
 /**
diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c	Mon Feb 24 10:18:07 2003
+++ b/drivers/scsi/sd.c	Sun Mar  9 06:48:19 2003
@@ -1197,7 +1197,7 @@
 		return;
 	}
 
-	buffer = kmalloc(512, GFP_DMA);
+	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
 	if (!buffer) {
 		printk(KERN_WARNING "(sd_init_onedisk:) Memory allocation "
 		       "failure.\n");
@@ -1389,14 +1389,9 @@
 
 	SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
 
-	for (i = 0; i < SD_MAJORS; i++) {
-		if (register_blkdev(sd_major(i), "sd", &sd_fops))
-			printk(KERN_NOTICE
-			       "Unable to get major %d for SCSI disk\n",
-			       sd_major(i));
-		else
+	for (i = 0; i < SD_MAJORS; i++)
+		if (register_blkdev(sd_major(i), "sd") == 0)
 			majors++;
-	}
 
 	if (!majors)
 		return -ENODEV;
@@ -1409,7 +1404,7 @@
 }
 
 /**
- *	exit_sd - exit point for this driver (when it is	a module).
+ *	exit_sd - exit point for this driver (when it is a module).
  *
  *	Note: this function unregisters this driver from the scsi mid-level.
  **/
diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c
--- a/drivers/scsi/sr.c	Mon Feb 24 12:16:14 2003
+++ b/drivers/scsi/sr.c	Sun Mar  9 06:48:19 2003
@@ -604,7 +604,7 @@
 	struct scsi_request *SRpnt = NULL;
 	request_queue_t *queue;
 
-	buffer = kmalloc(512, GFP_DMA);
+	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
 	if (!buffer)
 		goto Enomem;
 	SRpnt = scsi_allocate_request(cd->device);
@@ -698,7 +698,7 @@
 	goto out;
 }
 
-void get_capabilities(struct scsi_cd *cd)
+static void get_capabilities(struct scsi_cd *cd)
 {
 	struct cdrom_generic_command cgc;
 	unsigned char *buffer;
@@ -716,9 +716,8 @@
 		""
 	};
 
-	buffer = kmalloc(512, GFP_DMA);
-	if (!buffer)
-	{
+	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
+	if (!buffer) {
 		printk(KERN_ERR "sr: out of memory.\n");
 		return;
 	}
@@ -835,7 +834,7 @@
 {
 	int rc;
 
-	rc = register_blkdev(SCSI_CDROM_MAJOR, "sr", &sr_bdops);
+	rc = register_blkdev(SCSI_CDROM_MAJOR, "sr");
 	if (rc)
 		return rc;
 	return scsi_register_device(&sr_template);
diff -Nru a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c
--- a/drivers/scsi/sym53c8xx.c	Wed Feb 26 19:03:06 2003
+++ b/drivers/scsi/sym53c8xx.c	Wed Mar  5 23:02:24 2003
@@ -112,8 +112,8 @@
 #include <asm/spinlock.h>
 #endif
 #include <linux/delay.h>
+#include <linux/interrupt.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/pci.h>
 #include <linux/string.h>
@@ -7214,7 +7214,6 @@
 **==========================================================
 */
 
-#ifdef MODULE
 static int ncr_detach(ncb_p np)
 {
 	int i;
@@ -7260,7 +7259,6 @@
 
 	return 1;
 }
-#endif
 
 /*==========================================================
 **
@@ -12958,6 +12956,7 @@
 		}
 		if (i != count)	/* Ignore this device if we already have it */
 			continue;
+		pci_set_master(pcidev);
 		devp = &devtbl[count];
 		devp->host_id = driver_setup.host_id;
 		devp->attach_done = 0;
@@ -13798,7 +13797,6 @@
 }
 
 
-#ifdef MODULE
 int sym53c8xx_release(struct Scsi_Host *host)
 {
 #ifdef DEBUG_SYM53C8XX
@@ -13808,7 +13806,6 @@
 
      return 1;
 }
-#endif
 
 
 /*
diff -Nru a/drivers/scsi/sym53c8xx.h b/drivers/scsi/sym53c8xx.h
--- a/drivers/scsi/sym53c8xx.h	Tue Dec 10 12:28:33 2002
+++ b/drivers/scsi/sym53c8xx.h	Mon Feb 17 12:02:12 2003
@@ -75,17 +75,11 @@
 int sym53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int sym53c8xx_reset(Scsi_Cmnd *, unsigned int);
 int sym53c8xx_slave_configure(Scsi_Device *);
-
-#ifdef MODULE
 int sym53c8xx_release(struct Scsi_Host *);
-#else
-#define sym53c8xx_release NULL
-#endif
-
 
 #if	LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75)
 
-#define SYM53C8XX {     .name           = "",			\
+#define SYM53C8XX {     .name           = "sym53c8xx",		\
 			.detect         = sym53c8xx_detect,	\
 			.release        = sym53c8xx_release,	\
 			.info           = sym53c8xx_info, 	\
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c	Mon Feb 24 07:25:23 2003
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c	Sat Mar  8 14:50:22 2003
@@ -221,7 +221,7 @@
  */
 static void sym_soft_reset (hcb_p np)
 {
-	u_char istat;
+	u_char istat = 0;
 	int i;
 
 	if (!(np->features & FE_ISTAT1) || !(INB (nc_istat1) & SCRUN))
diff -Nru a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
--- a/drivers/scsi/zalon.c	Sat Jan  4 12:04:10 2003
+++ b/drivers/scsi/zalon.c	Mon Feb 17 12:02:12 2003
@@ -151,7 +151,6 @@
 	return (hosts_used != 0);
 }
 
-#ifdef MODULE
 extern int ncr53c8xx_release(struct Scsi_Host *host);
 
 int zalon7xx_release(struct Scsi_Host *host)
@@ -160,4 +159,3 @@
 	unregister_parisc_driver(&zalon_driver);
 	return 1;
 }
-#endif
diff -Nru a/drivers/scsi/zalon.h b/drivers/scsi/zalon.h
--- a/drivers/scsi/zalon.h	Sat Jan  4 12:04:11 2003
+++ b/drivers/scsi/zalon.h	Mon Feb 17 12:02:12 2003
@@ -15,12 +15,7 @@
 int zalon7xx_detect(Scsi_Host_Template *tpnt);
 const char *ncr53c8xx_info(struct Scsi_Host *host);
 int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-
-#ifdef MODULE
 int zalon7xx_release(struct Scsi_Host *);
-#else
-#define zalon7xx_release NULL
-#endif
 
 #define GSC_SCSI_ZALON_OFFSET 0x800
 
diff -Nru a/drivers/serial/21285.c b/drivers/serial/21285.c
--- a/drivers/serial/21285.c	Sat Feb 22 09:59:10 2003
+++ b/drivers/serial/21285.c	Thu Mar  6 09:27:42 2003
@@ -501,11 +501,12 @@
 	.index		= -1,
 };
 
-void __init rs285_console_init(void)
+static void __init rs285_console_init(void)
 {
 	serial21285_setup_ports();
 	register_console(&serial21285_console);
 }
+console_initcall(rs285_console_init);
 
 #define SERIAL_21285_CONSOLE	&serial21285_console
 #else
diff -Nru a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
--- a/drivers/serial/68328serial.c	Sun Nov 17 23:09:28 2002
+++ b/drivers/serial/68328serial.c	Fri Feb 14 15:26:21 2003
@@ -1691,8 +1691,9 @@
 };
 
 
-void m68328_console_init(void)
+static void __init m68328_console_init(void)
 {
 	register_console(&m68328_driver);
 }
 
+console_initcall(m68328_console_init);
diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c
--- a/drivers/serial/8250.c	Tue Feb 25 18:39:37 2003
+++ b/drivers/serial/8250.c	Sat Mar  8 16:01:37 2003
@@ -1982,11 +1982,13 @@
 	.index		= -1,
 };
 
-void __init serial8250_console_init(void)
+static int __init serial8250_console_init(void)
 {
 	serial8250_isa_init_ports();
 	register_console(&serial8250_console);
+	return 0;
 }
+console_initcall(serial8250_console_init);
 
 #define SERIAL8250_CONSOLE	&serial8250_console
 #else
diff -Nru a/drivers/serial/amba.c b/drivers/serial/amba.c
--- a/drivers/serial/amba.c	Sat Feb 22 09:59:10 2003
+++ b/drivers/serial/amba.c	Thu Mar  6 09:28:07 2003
@@ -705,10 +705,11 @@
 	.index		= -1,
 };
 
-void __init ambauart_console_init(void)
+static void __init ambauart_console_init(void)
 {
 	register_console(&amba_console);
 }
+console_initcall(ambauart_console_init);
 
 #define AMBA_CONSOLE	&amba_console
 #else
diff -Nru a/drivers/serial/anakin.c b/drivers/serial/anakin.c
--- a/drivers/serial/anakin.c	Sat Feb 22 09:59:10 2003
+++ b/drivers/serial/anakin.c	Thu Mar  6 09:28:07 2003
@@ -502,11 +502,12 @@
 	.index		= -1,
 };
 
-void __init
+static void __init
 anakin_console_init(void)
 {
 	register_console(&anakin_console);
 }
+console_initcall(anakin_console_init);
 
 #define ANAKIN_CONSOLE		&anakin_console
 #else
diff -Nru a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
--- a/drivers/serial/clps711x.c	Sat Feb 22 09:59:10 2003
+++ b/drivers/serial/clps711x.c	Thu Mar  6 09:28:07 2003
@@ -567,10 +567,11 @@
 	.index		= -1,
 };
 
-void __init clps711xuart_console_init(void)
+static void __init clps711xuart_console_init(void)
 {
 	register_console(&clps711x_console);
 }
+console_initcall(clps711xuart_console_init);
 
 #define CLPS711X_CONSOLE	&clps711x_console
 #else
diff -Nru a/drivers/serial/core.c b/drivers/serial/core.c
--- a/drivers/serial/core.c	Mon Feb 24 15:32:22 2003
+++ b/drivers/serial/core.c	Thu Mar  6 09:28:07 2003
@@ -1890,42 +1890,6 @@
 
 	return 0;
 }
-
-extern void ambauart_console_init(void);
-extern void anakin_console_init(void);
-extern void clps711xuart_console_init(void);
-extern void rs285_console_init(void);
-extern void sa1100_rs_console_init(void);
-extern void serial8250_console_init(void);
-extern void uart00_console_init(void);
-
-/*
- * Central "initialise all serial consoles" container.  Needs to be killed.
- */
-void __init uart_console_init(void)
-{
-#ifdef CONFIG_SERIAL_AMBA_CONSOLE
-	ambauart_console_init();
-#endif
-#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE
-	anakin_console_init();
-#endif
-#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
-	clps711xuart_console_init();
-#endif
-#ifdef CONFIG_SERIAL_21285_CONSOLE
-	rs285_console_init();
-#endif
-#ifdef CONFIG_SERIAL_SA1100_CONSOLE
-	sa1100_rs_console_init();
-#endif
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-	serial8250_console_init();
-#endif
-#ifdef CONFIG_SERIAL_UART00_CONSOLE
-	uart00_console_init();
-#endif
-}
 #endif /* CONFIG_SERIAL_CORE_CONSOLE */
 
 #ifdef CONFIG_PM
diff -Nru a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
--- a/drivers/serial/mcfserial.c	Tue Feb 18 02:28:34 2003
+++ b/drivers/serial/mcfserial.c	Mon Mar  3 12:25:14 2003
@@ -1853,9 +1853,11 @@
 	.index		= -1,
 };
 
-void __init mcfrs_console_init(void)
+static void __init mcfrs_console_init(void)
 {
 	register_console(&mcfrs_console);
 }
+
+console_initcall(mcfrs_console_init);
 
 /****************************************************************************/
diff -Nru a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
--- a/drivers/serial/sa1100.c	Tue Feb 25 18:39:37 2003
+++ b/drivers/serial/sa1100.c	Thu Mar  6 09:28:07 2003
@@ -835,11 +835,12 @@
 	.index		= -1,
 };
 
-void __init sa1100_rs_console_init(void)
+static void __init sa1100_rs_console_init(void)
 {
 	sa1100_init_ports();
 	register_console(&sa1100_console);
 }
+console_initcall(sa1100_rs_console_init);
 
 #define SA1100_CONSOLE	&sa1100_console
 #else
diff -Nru a/drivers/serial/uart00.c b/drivers/serial/uart00.c
--- a/drivers/serial/uart00.c	Sun Feb 16 11:33:25 2003
+++ b/drivers/serial/uart00.c	Thu Mar  6 09:30:07 2003
@@ -645,10 +645,11 @@
 	.index		= 0,
 };
 
-void __init uart00_console_init(void)
+static void __init uart00_console_init(void)
 {
 	register_console(&uart00_console);
 }
+console_initcall(uart00_console_init);
 
 #define UART00_CONSOLE	&uart00_console
 #else
diff -Nru a/drivers/sgi/char/sgiserial.c b/drivers/sgi/char/sgiserial.c
--- a/drivers/sgi/char/sgiserial.c	Sun Nov 17 23:09:37 2002
+++ b/drivers/sgi/char/sgiserial.c	Fri Feb 14 15:27:26 2003
@@ -2269,8 +2269,10 @@
 /*
  *	Register console.
  */
-void __init sgi_serial_console_init(void)
+static void __init sgi_serial_console_init(void)
 {
 	register_console(&sgi_console_driver);
 }
+console_initcall(sgi_serial_console_init);
+
 __initcall(rs_init);
diff -Nru a/drivers/usb/class/usb-midi.h b/drivers/usb/class/usb-midi.h
--- a/drivers/usb/class/usb-midi.h	Fri Feb 21 03:06:06 2003
+++ b/drivers/usb/class/usb-midi.h	Wed Mar  5 03:07:27 2003
@@ -54,6 +54,10 @@
 #define USB_VENDOR_ID_STEINBERG		0x0763
 #define USBMIDI_STEINBERG_USB2MIDI	0x1001
 
+/* Mark of the Unicorn MIDI Devices */
+#define USB_VENDOR_ID_MOTU		0x07fd
+#define USBMIDI_MOTU_FASTLANE		0x0001
+
 /* ------------------------------------------------------------------------- */
 /* Supported devices */
 
@@ -101,8 +105,15 @@
   { /* Roland SC8850 */
     "Roland SC8850",
     USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850, 2, -1,
-    { { 0x81, 15 }, {-1, -1} }, /** cables 0,1,2, and 3 **/
-    { { 0x01, 15 }, {-1, -1} },
+    { { 0x81, 0x3f }, {-1, -1} },
+    { { 0x01, 0x3f }, {-1, -1} },
+  },
+
+  { /* Roland SC8820 */
+    "Roland SC8820",
+    USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820, 2, -1,
+    { { 0x81, 0x13 }, {-1, -1} },
+    { { 0x01, 0x13 }, {-1, -1} },
   },
 
   { /* Roland SC8820 */
@@ -123,6 +134,12 @@
     USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300, 2, -1, 
     { { 0x81, 1 }, {-1, -1} },
     { { 0x01, 1 }, {-1, -1} },
+  },
+  { /* MOTU Fastlane USB */
+    "MOTU Fastlane USB",
+    USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE, 1, 0,
+    { { 0x82, 3 }, {-1, -1} },
+    { { 0x02, 3 }, {-1, -1} },
   }
 };
 
@@ -138,7 +155,9 @@
 	{ USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UA100G ) },
 	{ USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300 ) },
 	{ USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850 ) },
+	{ USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820 ) },
 	{ USB_DEVICE( USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000 ) },
+	{ USB_DEVICE( USB_VENDOR_ID_MOTU,   USBMIDI_MOTU_FASTLANE ) },
 /*	{ USB_DEVICE( USB_VENDOR_ID_STEINBERG, USBMIDI_STEINBERG_USB2MIDI ) },*/
 	{ } /* Terminating entry */
 };
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	Wed Feb 26 03:17:57 2003
+++ b/drivers/usb/core/hub.c	Wed Mar  5 07:24:34 2003
@@ -876,6 +876,7 @@
 		}
 
 		hub->children[port] = dev;
+		dev->state = USB_STATE_POWERED;
 
 		/* Reset the device, and detect its speed */
 		if (usb_hub_port_reset(hub, port, dev, delay)) {
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c	Sat Feb 15 04:07:33 2003
+++ b/drivers/usb/core/message.c	Wed Mar  5 07:24:34 2003
@@ -904,17 +904,29 @@
 			break;
 		}
 	}
-	if (!cp) {
+	if ((!cp && configuration != 0) || (cp && configuration == 0)) {
 		warn("selecting invalid configuration %d", configuration);
 		return -EINVAL;
 	}
 
+	/* if it's already configured, clear out old state first. */
+	if (dev->state != USB_STATE_ADDRESS) {
+		/* FIXME unbind drivers from all "old" interfaces.
+		 * handshake with hcd to reset cached hc endpoint state.
+		 */
+	}
+
 	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
 			NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
 		return ret;
-
+	if (configuration)
+		dev->state = USB_STATE_CONFIGURED;
+	else
+		dev->state = USB_STATE_ADDRESS;
 	dev->actconfig = cp;
+
+	/* reset more hc/hcd endpoint state */
 	dev->toggle[0] = 0;
 	dev->toggle[1] = 0;
 	usb_set_maxpacket(dev);
diff -Nru a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
--- a/drivers/usb/core/urb.c	Tue Feb 18 07:50:22 2003
+++ b/drivers/usb/core/urb.c	Thu Mar  6 07:46:03 2003
@@ -195,7 +195,9 @@
 
 	if (!urb || urb->hcpriv || !urb->complete)
 		return -EINVAL;
-	if (!(dev = urb->dev) || !dev->present || !dev->bus || dev->devnum <= 0)
+	if (!(dev = urb->dev) ||
+	    (dev->state < USB_STATE_DEFAULT) ||
+	    (!dev->bus) || (dev->devnum <= 0))
 		return -ENODEV;
 	if (!(op = dev->bus->op) || !op->submit_urb)
 		return -ENODEV;
@@ -211,6 +213,9 @@
 	temp = usb_pipetype (pipe);
 	is_out = usb_pipeout (pipe);
 
+	if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED)
+		return -ENODEV;
+
 	/* (actually HCDs may need to duplicate this, endpoint might yet
 	 * stall due to queued bulk/intr transactions that complete after
 	 * we check)
@@ -376,7 +381,16 @@
  */
 int usb_unlink_urb(struct urb *urb)
 {
-	if (urb && urb->dev && urb->dev->present && urb->dev->bus && urb->dev->bus->op)
+	/* FIXME
+	 * We should not care about the state here, but the host controllers
+	 * die a horrible death if we submit a urb for a device that has been
+	 * physically removed.
+	 */
+	if (urb &&
+	    urb->dev &&
+	    (urb->dev->state >= USB_STATE_DEFAULT) &&
+	    urb->dev->bus &&
+	    urb->dev->bus->op)
 		return urb->dev->bus->op->unlink_urb(urb);
 	else
 		return -ENODEV;
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	Tue Feb 18 07:50:22 2003
+++ b/drivers/usb/core/usb.c	Wed Mar  5 07:29:53 2003
@@ -679,7 +679,7 @@
 	memset(dev, 0, sizeof(*dev));
 
 	device_initialize(&dev->dev);
-	dev->present = 1;
+	dev->state = USB_STATE_ATTACHED;
 
 	usb_bus_get(bus);
 
@@ -828,6 +828,11 @@
 
 	*pdev = NULL;
 
+	/* mark the device as inactive, so any further urb submissions for
+	 * this device will fail.
+	 */
+	dev->state = USB_STATE_NOTATTACHED;
+
 	dev_info (&dev->dev, "USB disconnect, address %d\n", dev->devnum);
 
 	/* Free up all the children before we remove this device */
@@ -855,10 +860,6 @@
 	}
 	device_unregister(&dev->dev);
 
-	/* mark the device as not present so any further urb submissions for
-	 * this device will fail. */
-	dev->present = 0;
-
 	/* Decrement the reference count, it'll auto free everything when */
 	/* it hits 0 which could very well be now */
 	usb_put_dev(dev);
@@ -906,9 +907,17 @@
 // otherwise used internally, for usb_new_device()
 int usb_set_address(struct usb_device *dev)
 {
-	return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,
-		// FIXME USB_CTRL_SET_TIMEOUT
-		0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_GET_TIMEOUT);
+	int retval;
+
+	if (dev->devnum == 0)
+		return -EINVAL;
+	if (dev->state != USB_STATE_DEFAULT && dev->state != USB_STATE_ADDRESS)
+		return -EINVAL;
+	retval = usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,
+		0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+	if (retval == 0)
+		dev->state = USB_STATE_ADDRESS;
+	return retval;
 }
 
 
@@ -1014,7 +1023,8 @@
 	/* dma masks come from the controller; readonly, except to hcd */
 	dev->dev.dma_mask = parent->dma_mask;
 
-	/* USB device state == default ... it's not usable yet */
+	/* it's not usable yet */
+	dev->state = USB_STATE_DEFAULT;
 
 	/* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
 	 * it's fixed size except for full speed devices.
@@ -1049,6 +1059,7 @@
 		if (err < 0) {
 			dev_err(&dev->dev, "USB device not accepting new address=%d (error=%d)\n",
 				dev->devnum, err);
+			dev->state = USB_STATE_DEFAULT;
 			clear_bit(dev->devnum, dev->bus->devmap.devicemap);
 			dev->devnum = -1;
 			return 1;
diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
--- a/drivers/usb/host/ohci-pci.c	Mon Feb 24 03:30:39 2003
+++ b/drivers/usb/host/ohci-pci.c	Thu Mar  6 20:32:12 2003
@@ -18,6 +18,7 @@
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 #include <asm/pci-bridge.h>
+#include <asm/prom.h>
 #ifndef CONFIG_PM
 #	define CONFIG_PM
 #endif
diff -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
--- a/drivers/usb/serial/io_edgeport.c	Tue Jan  7 06:50:11 2003
+++ b/drivers/usb/serial/io_edgeport.c	Wed Mar  5 03:35:49 2003
@@ -522,7 +522,7 @@
 		case EDGE_DOWNLOAD_FILE_I930:
 			BootMajorVersion	= BootCodeImageVersion_GEN1.MajorVersion;
 			BootMinorVersion	= BootCodeImageVersion_GEN1.MinorVersion;
-			BootBuildNumber		= BootCodeImageVersion_GEN1.BuildNumber;
+			BootBuildNumber		= cpu_to_le16(BootCodeImageVersion_GEN1.BuildNumber);
 			BootImage		= &BootCodeImage_GEN1[0];
 			BootSize		= sizeof( BootCodeImage_GEN1 );
 			break;
@@ -530,7 +530,7 @@
 		case EDGE_DOWNLOAD_FILE_80251:
 			BootMajorVersion	= BootCodeImageVersion_GEN2.MajorVersion;
 			BootMinorVersion	= BootCodeImageVersion_GEN2.MinorVersion;
-			BootBuildNumber		= BootCodeImageVersion_GEN2.BuildNumber;
+			BootBuildNumber		= cpu_to_le16(BootCodeImageVersion_GEN2.BuildNumber);
 			BootImage		= &BootCodeImage_GEN2[0];
 			BootSize		= sizeof( BootCodeImage_GEN2 );
 			break;
@@ -542,26 +542,26 @@
 	// Check Boot Image Version
 	BootCurVer = (edge_serial->boot_descriptor.MajorVersion << 24) +
 		     (edge_serial->boot_descriptor.MinorVersion << 16) +
-		      edge_serial->boot_descriptor.BuildNumber;
+		      le16_to_cpu(edge_serial->boot_descriptor.BuildNumber);
 
 	BootNewVer = (BootMajorVersion << 24) +
 		     (BootMinorVersion << 16) +
-		      BootBuildNumber;
+		      le16_to_cpu(BootBuildNumber);
 
 	dbg("Current Boot Image version %d.%d.%d",
 	    edge_serial->boot_descriptor.MajorVersion,
 	    edge_serial->boot_descriptor.MinorVersion,
-	    edge_serial->boot_descriptor.BuildNumber);
+	    le16_to_cpu(edge_serial->boot_descriptor.BuildNumber));
 
 
 	if (BootNewVer > BootCurVer) {
 		dbg("**Update Boot Image from %d.%d.%d to %d.%d.%d",
 		    edge_serial->boot_descriptor.MajorVersion,
 		    edge_serial->boot_descriptor.MinorVersion,
-		    edge_serial->boot_descriptor.BuildNumber,
+		    le16_to_cpu(edge_serial->boot_descriptor.BuildNumber),
 		    BootMajorVersion,
 		    BootMinorVersion,
-		    BootBuildNumber);
+		    le16_to_cpu(BootBuildNumber));
 
 
 		dbg("Downloading new Boot Image");
@@ -570,12 +570,12 @@
 
 		for (;;) {
 			record = (struct edge_firmware_image_record *)firmware;
-			response = rom_write (edge_serial->serial, record->ExtAddr, record->Addr, record->Len, &record->Data[0]);
+			response = rom_write (edge_serial->serial, le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len), &record->Data[0]);
 			if (response < 0) {
-				dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", record->ExtAddr, record->Addr, record->Len);
+				dev_err(&edge_serial->serial->dev->dev, "rom_write failed (%x, %x, %d)\n", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len));
 				break;
 			}
-			firmware += sizeof (struct edge_firmware_image_record) + record->Len;
+			firmware += sizeof (struct edge_firmware_image_record) + le16_to_cpu(record->Len);
 			if (firmware >= &BootImage[BootSize]) {
 				break;
 			}
@@ -678,12 +678,12 @@
 	if (edge_serial->serial->dev->descriptor.idProduct & ION_DEVICE_ID_GENERATION_2) {
 		product_info->FirmwareMajorVersion	= OperationalCodeImageVersion_GEN2.MajorVersion;
 		product_info->FirmwareMinorVersion	= OperationalCodeImageVersion_GEN2.MinorVersion;
-		product_info->FirmwareBuildNumber	= OperationalCodeImageVersion_GEN2.BuildNumber;
+		product_info->FirmwareBuildNumber	= cpu_to_le16(OperationalCodeImageVersion_GEN2.BuildNumber);
 		product_info->iDownloadFile		= EDGE_DOWNLOAD_FILE_80251;
 	} else {
 		product_info->FirmwareMajorVersion	= OperationalCodeImageVersion_GEN1.MajorVersion;
 		product_info->FirmwareMinorVersion	= OperationalCodeImageVersion_GEN1.MinorVersion;
-		product_info->FirmwareBuildNumber	= OperationalCodeImageVersion_GEN1.BuildNumber;
+		product_info->FirmwareBuildNumber	= cpu_to_le16(OperationalCodeImageVersion_GEN1.BuildNumber);
 		product_info->iDownloadFile		= EDGE_DOWNLOAD_FILE_I930;
 	}
 
@@ -729,10 +729,10 @@
 	dbg("  BoardRev              %x", product_info->BoardRev);
 	dbg("  BootMajorVersion      %d.%d.%d", product_info->BootMajorVersion,
 	    product_info->BootMinorVersion,
-	    product_info->BootBuildNumber);
+	    le16_to_cpu(product_info->BootBuildNumber));
 	dbg("  FirmwareMajorVersion  %d.%d.%d", product_info->FirmwareMajorVersion,
 	    product_info->FirmwareMinorVersion,
-	    product_info->FirmwareBuildNumber);
+	    le16_to_cpu(product_info->FirmwareBuildNumber));
 	dbg("  ManufactureDescDate   %d/%d/%d", product_info->ManufactureDescDate[0],
 	    product_info->ManufactureDescDate[1],
 	    product_info->ManufactureDescDate[2]+1900);
@@ -2326,7 +2326,7 @@
 	__u16 current_length;
 	unsigned char *transfer_buffer;
 
-//	dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
+	dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
 
 	transfer_buffer =  kmalloc (64, GFP_KERNEL);
 	if (!transfer_buffer) {
@@ -2811,12 +2811,13 @@
  *	Turns a string from Unicode into ASCII.
  *	Doesn't do a good job with any characters that are outside the normal
  *	ASCII range, but it's only for debugging...
+ *	NOTE: expects the unicode in LE format
  ****************************************************************************/
 static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
 {
 	int i;
 	for (i = 0; i < unicode_size; ++i) {
-		string[i] = (char)(unicode[i]);
+		string[i] = (char)(le16_to_cpu(unicode[i]));
 	}
 	string[unicode_size] = 0x00;
 }
@@ -2880,11 +2881,11 @@
 		dev_err(&edge_serial->serial->dev->dev, "error in getting boot descriptor\n");
 	} else {
 		dbg("**Boot Descriptor:");
-		dbg("  BootCodeLength: %d", edge_serial->boot_descriptor.BootCodeLength);
+		dbg("  BootCodeLength: %d", le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength));
 		dbg("  MajorVersion:   %d", edge_serial->boot_descriptor.MajorVersion);
 		dbg("  MinorVersion:   %d", edge_serial->boot_descriptor.MinorVersion);
-		dbg("  BuildNumber:    %d", edge_serial->boot_descriptor.BuildNumber);
-		dbg("  Capabilities:   0x%x", edge_serial->boot_descriptor.Capabilities);
+		dbg("  BuildNumber:    %d", le16_to_cpu(edge_serial->boot_descriptor.BuildNumber));
+		dbg("  Capabilities:   0x%x", le16_to_cpu(edge_serial->boot_descriptor.Capabilities));
 		dbg("  UConfig0:       %d", edge_serial->boot_descriptor.UConfig0);
 		dbg("  UConfig1:       %d", edge_serial->boot_descriptor.UConfig1);
 	}
@@ -2936,12 +2937,12 @@
 
 	for (;;) {
 		record = (struct edge_firmware_image_record *)firmware;
-		response = sram_write (edge_serial->serial, record->ExtAddr, record->Addr, record->Len, &record->Data[0]);
+		response = sram_write (edge_serial->serial, le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len), &record->Data[0]);
 		if (response < 0) {
-			dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", record->ExtAddr, record->Addr, record->Len);
+			dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), record->Len);
 			break;
 		}
-		firmware += sizeof (struct edge_firmware_image_record) + record->Len;
+		firmware += sizeof (struct edge_firmware_image_record) + le16_to_cpu(record->Len);
 		if (firmware >= &FirmwareImage[ImageSize]) {
 			break;
 		}
diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
--- a/drivers/usb/serial/pl2303.c	Fri Feb 21 09:00:54 2003
+++ b/drivers/usb/serial/pl2303.c	Wed Mar  5 04:06:21 2003
@@ -75,6 +75,7 @@
 	{ USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) },
 	{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) },
 	{ USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) },
+	{ USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
 
diff -Nru a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
--- a/drivers/usb/serial/pl2303.h	Tue Feb  4 06:10:14 2003
+++ b/drivers/usb/serial/pl2303.h	Wed Mar  5 04:06:21 2003
@@ -31,3 +31,6 @@
 
 #define TRIPP_VENDOR_ID		0x2478
 #define TRIPP_PRODUCT_ID	0x2008
+
+#define RADIOSHACK_VENDOR_ID	0x1453
+#define RADIOSHACK_PRODUCT_ID	0x4026
diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
--- a/drivers/usb/serial/usb-serial.c	Tue Feb 18 07:50:15 2003
+++ b/drivers/usb/serial/usb-serial.c	Thu Mar  6 21:31:07 2003
@@ -634,6 +634,7 @@
 		serial->type->throttle(port);
 
 exit:
+	;
 }
 
 static void serial_unthrottle (struct tty_struct * tty)
@@ -656,6 +657,7 @@
 		serial->type->unthrottle(port);
 
 exit:
+	;
 }
 
 static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
@@ -704,6 +706,7 @@
 		serial->type->set_termios(port, old);
 
 exit:
+	;
 }
 
 static void serial_break (struct tty_struct *tty, int break_state)
@@ -726,6 +729,7 @@
 		serial->type->break_ctl(port, break_state);
 
 exit:
+	;
 }
 
 static void serial_shutdown (struct usb_serial *serial)
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c	Fri Feb 21 09:00:45 2003
+++ b/drivers/usb/serial/visor.c	Wed Mar  5 03:04:53 2003
@@ -12,6 +12,9 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
+ * (03/05/2003) gkh
+ *	Think Treo support is now working.
+ *
  * (04/03/2002) gkh
  *	Added support for the Sony OS 4.1 devices.  Thanks to Hiroyuki ARAKI
  *	<hiro@zob.ne.jp> for the information.
@@ -156,7 +159,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v2.0"
+#define DRIVER_VERSION "v2.1"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
 #define DRIVER_DESC "USB HandSpring Visor, Palm m50x, Sony Clié driver"
 
@@ -177,6 +180,7 @@
 static void visor_read_bulk_callback	(struct urb *urb, struct pt_regs *regs);
 static void visor_read_int_callback	(struct urb *urb, struct pt_regs *regs);
 static int  clie_3_5_startup	(struct usb_serial *serial);
+static int  treo_attach		(struct usb_serial *serial);
 static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id);
 static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id);
 
@@ -262,6 +266,7 @@
 	.close =		visor_close,
 	.throttle =		visor_throttle,
 	.unthrottle =		visor_unthrottle,
+	.attach =		treo_attach,
 	.probe =		visor_probe,
 	.calc_num_ports =	visor_calc_num_ports,
 	.shutdown =		visor_shutdown,
@@ -797,6 +802,48 @@
 	if (result != 1) {
 		dev_err(dev, "%s: get interface number bad return length: %d\n", __FUNCTION__, result);
 		return -EIO;
+	}
+
+	return 0;
+}
+ 
+static int treo_attach (struct usb_serial *serial)
+{
+	struct usb_serial_port *port;
+	int i;
+
+	/* Only do this endpoint hack for the Handspring devices with
+	 * interrupt in endpoints, which for now are the Treo devices. */
+	if ((serial->dev->descriptor.idVendor != HANDSPRING_VENDOR_ID) ||
+	    (serial->num_interrupt_in == 0))
+		return 0;
+
+	dbg("%s", __FUNCTION__);
+
+	/* Ok, this is pretty ugly, but these devices want to use the
+	 * interrupt endpoint as paired up with a bulk endpoint for a
+	 * "virtual serial port".  So let's force the endpoints to be
+	 * where we want them to be. */
+	for (i = serial->num_bulk_in; i < serial->num_ports; ++i) {
+		port = &serial->port[i];
+		port->read_urb = serial->port[0].read_urb;
+		port->bulk_in_endpointAddress = serial->port[0].bulk_in_endpointAddress;
+		port->bulk_in_buffer = serial->port[0].bulk_in_buffer;
+	}
+
+	for (i = serial->num_bulk_out; i < serial->num_ports; ++i) {
+		port = &serial->port[i];
+		port->write_urb = serial->port[0].write_urb;
+		port->bulk_out_size = serial->port[0].bulk_out_size;
+		port->bulk_out_endpointAddress = serial->port[0].bulk_out_endpointAddress;
+		port->bulk_out_buffer = serial->port[0].bulk_out_buffer;
+	}
+
+	for (i = serial->num_interrupt_in; i < serial->num_ports; ++i) {
+		port = &serial->port[i];
+		port->interrupt_in_urb = serial->port[0].interrupt_in_urb;
+		port->interrupt_in_endpointAddress = serial->port[0].interrupt_in_endpointAddress;
+		port->interrupt_in_buffer = serial->port[0].interrupt_in_buffer;
 	}
 
 	return 0;
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c	Wed Jan 22 03:55:34 2003
+++ b/drivers/usb/storage/transport.c	Tue Mar  4 01:58:24 2003
@@ -582,20 +582,26 @@
 		unsigned short old_sg;
 		unsigned old_request_bufflen;
 		unsigned char old_sc_data_direction;
+		unsigned char old_cmd_len;
 		unsigned char old_cmnd[MAX_COMMAND_SIZE];
 
 		US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
 
 		/* save the old command */
 		memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE);
+		old_cmd_len = srb->cmd_len;
 
 		/* set the command and the LUN */
+		memset(srb->cmnd, 0, MAX_COMMAND_SIZE);
 		srb->cmnd[0] = REQUEST_SENSE;
 		srb->cmnd[1] = old_cmnd[1] & 0xE0;
-		srb->cmnd[2] = 0;
-		srb->cmnd[3] = 0;
 		srb->cmnd[4] = 18;
-		srb->cmnd[5] = 0;
+
+		/* FIXME: we must do the protocol translation here */
+		if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI)
+			srb->cmd_len = 6;
+		else
+			srb->cmd_len = 12;
 
 		/* set the transfer direction */
 		old_sc_data_direction = srb->sc_data_direction;
@@ -621,6 +627,7 @@
 		srb->request_bufflen = old_request_bufflen;
 		srb->use_sg = old_sg;
 		srb->sc_data_direction = old_sc_data_direction;
+		srb->cmd_len = old_cmd_len;
 		memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);
 
 		if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile
--- a/drivers/video/Makefile	Sun Mar  2 23:19:23 2003
+++ b/drivers/video/Makefile	Fri Mar  7 18:42:54 2003
@@ -70,9 +70,6 @@
 obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
 obj-$(CONFIG_FB_VOODOO1)          += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 
-# One by one these are being converted over to the new APIs
-#obj-$(CONFIG_FB_LEO)              += leofb.o sbusfb.o
-
 obj-$(CONFIG_FB_FFB)               += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
 obj-$(CONFIG_FB_CG6)               += cg6.o sbuslib.o cfbimgblt.o cfbcopyarea.o
 obj-$(CONFIG_FB_CG3)               += cg3.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
@@ -84,6 +81,8 @@
 obj-$(CONFIG_FB_P9100)             += p9100.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
 				      cfbfillrect.o
 obj-$(CONFIG_FB_TCX)               += tcx.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+				      cfbfillrect.o
+obj-$(CONFIG_FB_LEO)               += leo.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
 				      cfbfillrect.o
 
 # Files generated that shall be removed upon make clean
diff -Nru a/drivers/video/bw2.c b/drivers/video/bw2.c
--- a/drivers/video/bw2.c	Thu Feb 27 12:32:45 2003
+++ b/drivers/video/bw2.c	Tue Mar  4 09:55:26 2003
@@ -33,11 +33,11 @@
  * Local functions.
  */
 
-static int bw2_check_var(struct fb_var_screeninfo *, struct fb_info *);
-static int bw2_set_par(struct fb_info *);
 static int bw2_blank(int, struct fb_info *);
 
 static int bw2_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+static int bw2_ioctl(struct inode *, struct file *, unsigned int,
+		     unsigned long, struct fb_info *);
 
 /*
  *  Frame buffer operations
@@ -45,13 +45,12 @@
 
 static struct fb_ops bw2_ops = {
 	.owner			= THIS_MODULE,
-	.fb_check_var		= bw2_check_var,
-	.fb_set_par		= bw2_set_par,
 	.fb_blank		= bw2_blank,
 	.fb_fillrect		= cfb_fillrect,
 	.fb_copyarea		= cfb_copyarea,
 	.fb_imageblit		= cfb_imageblit,
 	.fb_mmap		= bw2_mmap,
+	.fb_ioctl		= bw2_ioctl,
 	.fb_cursor		= soft_cursor,
 };
 
@@ -124,39 +123,6 @@
 };
 
 /**
- *      bw2_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int bw2_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->bits_per_pixel != 8)
-		return -EINVAL;
-
-	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
-		return -EINVAL;
-	if (var->nonstd)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if (var->xres != info->var.xres || var->yres != info->var.yres)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- *      bw2_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-bw2_set_par(struct fb_info *info)
-{
-	return 0;
-}
-
-/**
  *      bw2_blank - Optional function.  Blanks the display.
  *      @blank_mode: the blank mode we want.
  *      @info: frame buffer structure that represents a single frame buffer
@@ -212,6 +178,15 @@
 				  vma);
 }
 
+static int bw2_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg, struct fb_info *info)
+{
+	struct bw2_par *par = (struct bw2_par *) info->par;
+
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUN2BW, 1, par->fbsize);
+}
+
 /*
  *  Initialisation
  */
@@ -387,7 +362,6 @@
 
 	bw2_blank(0, &all->info);
 
-	bw2_set_par(&all->info);
 	bw2_init_fix(&all->info, linebytes);
 
 	if (register_framebuffer(&all->info) < 0) {
diff -Nru a/drivers/video/cg14.c b/drivers/video/cg14.c
--- a/drivers/video/cg14.c	Sun Mar  2 22:28:03 2003
+++ b/drivers/video/cg14.c	Tue Mar  4 09:55:26 2003
@@ -28,8 +28,6 @@
  * Local functions.
  */
 
-static int cg14_check_var(struct fb_var_screeninfo *, struct fb_info *);
-static int cg14_set_par(struct fb_info *);
 static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned,
 			 unsigned, struct fb_info *);
 
@@ -43,8 +41,6 @@
 
 static struct fb_ops cg14_ops = {
 	.owner			= THIS_MODULE,
-	.fb_check_var		= cg14_check_var,
-	.fb_set_par		= cg14_set_par,
 	.fb_setcolreg		= cg14_setcolreg,
 	.fb_fillrect		= cfb_fillrect,
 	.fb_copyarea		= cfb_copyarea,
@@ -220,39 +216,6 @@
 }
 
 /**
- *      cg14_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int cg14_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->bits_per_pixel != 8)
-		return -EINVAL;
-
-	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
-		return -EINVAL;
-	if (var->nonstd)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if (var->xres != info->var.xres || var->yres != info->var.yres)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- *      cg14_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-cg14_set_par(struct fb_info *info)
-{
-	return 0;
-}
-
-/**
  *      cg14_setcolreg - Optional function. Sets a color register.
  *      @regno: boolean, 0 copy local, 1 get_user() function
  *      @red: frame buffer colormap structure
@@ -358,7 +321,8 @@
 		break;
 
 	default:
-		ret = -EINVAL;
+		ret = sbusfb_ioctl_helper(cmd, arg, info,
+					  FBTYPE_MDICOLOR, 24, par->fbsize);
 		break;
 	};
 
@@ -523,7 +487,6 @@
 		return;
 	}
 
-	cg14_set_par(&all->info);
 	cg14_init_fix(&all->info, linebytes);
 
 	if (register_framebuffer(&all->info) < 0) {
diff -Nru a/drivers/video/cg3.c b/drivers/video/cg3.c
--- a/drivers/video/cg3.c	Thu Feb 27 12:32:45 2003
+++ b/drivers/video/cg3.c	Tue Mar  4 09:55:26 2003
@@ -29,13 +29,13 @@
  * Local functions.
  */
 
-static int cg3_check_var(struct fb_var_screeninfo *, struct fb_info *);
-static int cg3_set_par(struct fb_info *);
 static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned,
 			 unsigned, struct fb_info *);
 static int cg3_blank(int, struct fb_info *);
 
 static int cg3_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+static int cg3_ioctl(struct inode *, struct file *, unsigned int,
+		     unsigned long, struct fb_info *);
 
 /*
  *  Frame buffer operations
@@ -43,14 +43,13 @@
 
 static struct fb_ops cg3_ops = {
 	.owner			= THIS_MODULE,
-	.fb_check_var		= cg3_check_var,
-	.fb_set_par		= cg3_set_par,
 	.fb_setcolreg		= cg3_setcolreg,
 	.fb_blank		= cg3_blank,
 	.fb_fillrect		= cfb_fillrect,
 	.fb_copyarea		= cfb_copyarea,
 	.fb_imageblit		= cfb_imageblit,
 	.fb_mmap		= cg3_mmap,
+	.fb_ioctl		= cg3_ioctl,
 	.fb_cursor		= soft_cursor,
 };
 
@@ -127,39 +126,6 @@
 };
 
 /**
- *      cg3_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int cg3_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->bits_per_pixel != 8)
-		return -EINVAL;
-
-	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
-		return -EINVAL;
-	if (var->nonstd)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if (var->xres != info->var.xres || var->yres != info->var.yres)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- *      cg3_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-cg3_set_par(struct fb_info *info)
-{
-	return 0;
-}
-
-/**
  *      cg3_setcolreg - Optional function. Sets a color register.
  *      @regno: boolean, 0 copy local, 1 get_user() function
  *      @red: frame buffer colormap structure
@@ -269,6 +235,15 @@
 				  vma);
 }
 
+static int cg3_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg, struct fb_info *info)
+{
+	struct cg3_par *par = (struct cg3_par *) info->par;
+
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUN3COLOR, 8, par->fbsize);
+}
+
 /*
  *  Initialisation
  */
@@ -445,7 +420,6 @@
 		return;
 	}
 
-	cg3_set_par(&all->info);
 	cg3_init_fix(&all->info, linebytes);
 
 	if (register_framebuffer(&all->info) < 0) {
diff -Nru a/drivers/video/cg6.c b/drivers/video/cg6.c
--- a/drivers/video/cg6.c	Thu Feb 27 12:32:45 2003
+++ b/drivers/video/cg6.c	Tue Mar  4 09:55:26 2003
@@ -29,8 +29,6 @@
  * Local functions.
  */
 
-static int cg6_check_var(struct fb_var_screeninfo *, struct fb_info *);
-static int cg6_set_par(struct fb_info *);
 static int cg6_setcolreg(unsigned, unsigned, unsigned, unsigned,
 			 unsigned, struct fb_info *);
 static int cg6_blank(int, struct fb_info *);
@@ -39,6 +37,8 @@
 static void cg6_fillrect(struct fb_info *, struct fb_fillrect *);
 static int cg6_sync(struct fb_info *);
 static int cg6_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+static int cg6_ioctl(struct inode *, struct file *, unsigned int,
+		     unsigned long, struct fb_info *);
 
 /*
  *  Frame buffer operations
@@ -46,8 +46,6 @@
 
 static struct fb_ops cg6_ops = {
 	.owner			= THIS_MODULE,
-	.fb_check_var		= cg6_check_var,
-	.fb_set_par		= cg6_set_par,
 	.fb_setcolreg		= cg6_setcolreg,
 	.fb_blank		= cg6_blank,
 	.fb_fillrect		= cg6_fillrect,
@@ -55,6 +53,7 @@
 	.fb_imageblit		= cg6_imageblit,
 	.fb_sync		= cg6_sync,
 	.fb_mmap		= cg6_mmap,
+	.fb_ioctl		= cg6_ioctl,
 	.fb_cursor		= soft_cursor,
 };
 
@@ -406,39 +405,6 @@
 }
 
 /**
- *      cg6_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int cg6_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->bits_per_pixel != 8)
-		return -EINVAL;
-
-	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
-		return -EINVAL;
-	if (var->nonstd)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if (var->xres != info->var.xres || var->yres != info->var.yres)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- *      cg6_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-cg6_set_par(struct fb_info *info)
-{
-	return 0;
-}
-
-/**
  *      cg6_setcolreg - Optional function. Sets a color register.
  *      @regno: boolean, 0 copy local, 1 get_user() function
  *      @red: frame buffer colormap structure
@@ -535,6 +501,15 @@
 				  vma);
 }
 
+static int cg6_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg, struct fb_info *info)
+{
+	struct cg6_par *par = (struct cg6_par *) info->par;
+
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUNFAST_COLOR, 8, par->fbsize);
+}
+
 /*
  *  Initialisation
  */
@@ -731,7 +706,6 @@
 		return;
 	}
 
-	cg6_set_par(&all->info);
 	cg6_init_fix(&all->info, linebytes);
 
 	if (register_framebuffer(&all->info) < 0) {
diff -Nru a/drivers/video/fbmem.c b/drivers/video/fbmem.c
--- a/drivers/video/fbmem.c	Sun Mar  2 23:19:23 2003
+++ b/drivers/video/fbmem.c	Fri Mar  7 18:42:54 2003
@@ -158,6 +158,8 @@
 extern int p9100_setup(char*);
 extern int tcx_init(void);
 extern int tcx_setup(char*);
+extern int leo_init(void);
+extern int leo_setup(char*);
 
 static struct {
 	const char *name;
@@ -269,6 +271,9 @@
 #endif
 #ifdef CONFIG_FB_TCX
 	{ "tcx", tcx_init, tcx_setup },
+#endif
+#ifdef CONFIG_FB_LEO
+	{ "leo", leo_init, leo_setup },
 #endif
 
 	/*
diff -Nru a/drivers/video/ffb.c b/drivers/video/ffb.c
--- a/drivers/video/ffb.c	Thu Feb 27 04:19:27 2003
+++ b/drivers/video/ffb.c	Tue Mar  4 09:55:26 2003
@@ -20,6 +20,7 @@
 #include <asm/io.h>
 #include <asm/upa.h>
 #include <asm/oplib.h>
+#include <asm/fbio.h>
 
 #include "sbuslib.h"
 
@@ -27,8 +28,6 @@
  * Local functions.
  */
 
-static int ffb_check_var(struct fb_var_screeninfo *, struct fb_info *);
-static int ffb_set_par(struct fb_info *);
 static int ffb_setcolreg(unsigned, unsigned, unsigned, unsigned,
 			 unsigned, struct fb_info *);
 static int ffb_blank(int, struct fb_info *);
@@ -39,6 +38,8 @@
 static void ffb_copyarea(struct fb_info *, struct fb_copyarea *);
 static int ffb_sync(struct fb_info *);
 static int ffb_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+static int ffb_ioctl(struct inode *, struct file *, unsigned int,
+		     unsigned long, struct fb_info *);
 
 /*
  *  Frame buffer operations
@@ -46,8 +47,6 @@
 
 static struct fb_ops ffb_ops = {
 	.owner			= THIS_MODULE,
-	.fb_check_var		= ffb_check_var,
-	.fb_set_par		= ffb_set_par,
 	.fb_setcolreg		= ffb_setcolreg,
 	.fb_blank		= ffb_blank,
 	.fb_fillrect		= ffb_fillrect,
@@ -55,6 +54,7 @@
 	.fb_imageblit		= ffb_imageblit,
 	.fb_sync		= ffb_sync,
 	.fb_mmap		= ffb_mmap,
+	.fb_ioctl		= ffb_ioctl,
 
 	/* XXX Use FFB hw cursor once fb cursor API is better understood... */
 	.fb_cursor		= soft_cursor,
@@ -673,41 +673,6 @@
 }
 
 /**
- *      ffb_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int ffb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->bits_per_pixel != 32)
-		return -EINVAL;
-
-	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
-		return -EINVAL;
-	if (var->nonstd)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if (var->xres != info->var.xres || var->yres != info->var.yres)
-		return -EINVAL;
-
-	ffb_fixup_var_rgb(var);
-
-	return 0;
-}
-
-/**
- *      ffb_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-ffb_set_par(struct fb_info *info)
-{
-	return 0;
-}
-
-/**
  *      ffb_setcolreg - Optional function. Sets a color register.
  *      @regno: boolean, 0 copy local, 1 get_user() function
  *      @red: frame buffer colormap structure
@@ -818,6 +783,15 @@
 				  0, vma);
 }
 
+static int ffb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg, struct fb_info *info)
+{
+	struct ffb_par *par = (struct ffb_par *) info->par;
+
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_CREATOR, 24, par->fbsize);
+}
+
 /*
  *  Initialisation
  */
@@ -972,7 +946,6 @@
 		return;
 	}
 
-	ffb_set_par(&all->info);
 	ffb_init_fix(&all->info);
 
 	if (register_framebuffer(&all->info) < 0) {
diff -Nru a/drivers/video/leo.c b/drivers/video/leo.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/video/leo.c	Fri Mar  7 18:42:32 2003
@@ -0,0 +1,587 @@
+/* leo.c: LEO frame buffer driver
+ *
+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
+ *
+ * Driver layout based loosely on tgafb.c, see that file for credits.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/sbus.h>
+#include <asm/oplib.h>
+#include <asm/fbio.h>
+
+#include "sbuslib.h"
+
+/*
+ * Local functions.
+ */
+
+static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned,
+			 unsigned, struct fb_info *);
+static int leo_blank(int, struct fb_info *);
+
+static int leo_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+static int leo_ioctl(struct inode *, struct file *, unsigned int,
+		     unsigned long, struct fb_info *);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops leo_ops = {
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= leo_setcolreg,
+	.fb_blank		= leo_blank,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+	.fb_mmap		= leo_mmap,
+	.fb_ioctl		= leo_ioctl,
+	.fb_cursor		= soft_cursor,
+};
+
+#define LEO_OFF_LC_SS0_KRN	0x00200000UL
+#define LEO_OFF_LC_SS0_USR	0x00201000UL
+#define LEO_OFF_LC_SS1_KRN	0x01200000UL
+#define LEO_OFF_LC_SS1_USR	0x01201000UL
+#define LEO_OFF_LD_SS0		0x00400000UL
+#define LEO_OFF_LD_SS1		0x01400000UL
+#define LEO_OFF_LD_GBL		0x00401000UL
+#define LEO_OFF_LX_KRN		0x00600000UL
+#define LEO_OFF_LX_CURSOR	0x00601000UL
+#define LEO_OFF_SS0		0x00800000UL
+#define LEO_OFF_SS1		0x01800000UL
+#define LEO_OFF_UNK		0x00602000UL
+#define LEO_OFF_UNK2		0x00000000UL
+
+#define LEO_CUR_ENABLE		0x00000080
+#define LEO_CUR_UPDATE		0x00000030
+#define LEO_CUR_PROGRESS	0x00000006
+#define LEO_CUR_UPDATECMAP	0x00000003
+
+#define LEO_CUR_TYPE_MASK	0x00000000
+#define LEO_CUR_TYPE_IMAGE	0x00000020
+#define LEO_CUR_TYPE_CMAP	0x00000050
+
+struct leo_cursor {
+	u8		xxx0[16];
+	volatile u32	cur_type;
+	volatile u32	cur_misc;
+	volatile u32	cur_cursxy;
+	volatile u32	cur_data;
+};
+
+#define LEO_KRN_TYPE_CLUT0	0x00001000
+#define LEO_KRN_TYPE_CLUT1	0x00001001
+#define LEO_KRN_TYPE_CLUT2	0x00001002
+#define LEO_KRN_TYPE_WID	0x00001003
+#define LEO_KRN_TYPE_UNK	0x00001006
+#define LEO_KRN_TYPE_VIDEO	0x00002003
+#define LEO_KRN_TYPE_CLUTDATA	0x00004000
+#define LEO_KRN_CSR_ENABLE	0x00000008
+#define LEO_KRN_CSR_PROGRESS	0x00000004
+#define LEO_KRN_CSR_UNK		0x00000002
+#define LEO_KRN_CSR_UNK2	0x00000001
+
+struct leo_lx_krn {
+	volatile u32	krn_type;
+	volatile u32	krn_csr;
+	volatile u32	krn_value;
+};
+
+struct leo_lc_ss0_krn {
+	volatile u32 	misc;
+	u8		xxx0[0x800-4];
+	volatile u32	rev;
+};
+
+struct leo_lc_ss0_usr {
+	volatile u32	csr;
+	volatile u32	addrspace;
+	volatile u32 	fontmsk;
+	volatile u32	fontt;
+	volatile u32	extent;
+	volatile u32	src;
+	u32		dst;
+	volatile u32	copy;
+	volatile u32	fill;
+};
+
+struct leo_lc_ss1_krn {
+	u8	unknown;
+};
+
+struct leo_lc_ss1_usr {
+	u8	unknown;
+};
+
+struct leo_ld {
+	u8		xxx0[0xe00];
+	volatile u32	csr;
+	volatile u32	wid;
+	volatile u32	wmask;
+	volatile u32	widclip;
+	volatile u32	vclipmin;
+	volatile u32	vclipmax;
+	volatile u32	pickmin;	/* SS1 only */
+	volatile u32	pickmax;	/* SS1 only */
+	volatile u32	fg;
+	volatile u32	bg;
+	volatile u32	src;		/* Copy/Scroll (SS0 only) */
+	volatile u32	dst;		/* Copy/Scroll/Fill (SS0 only) */
+	volatile u32	extent;		/* Copy/Scroll/Fill size (SS0 only) */
+	u32		xxx1[3];
+	volatile u32	setsem;		/* SS1 only */
+	volatile u32	clrsem;		/* SS1 only */
+	volatile u32	clrpick;	/* SS1 only */
+	volatile u32	clrdat;		/* SS1 only */
+	volatile u32	alpha;		/* SS1 only */
+	u8		xxx2[0x2c];
+	volatile u32	winbg;
+	volatile u32	planemask;
+	volatile u32	rop;
+	volatile u32	z;
+	volatile u32	dczf;		/* SS1 only */
+	volatile u32	dczb;		/* SS1 only */
+	volatile u32	dcs;		/* SS1 only */
+	volatile u32	dczs;		/* SS1 only */
+	volatile u32	pickfb;		/* SS1 only */
+	volatile u32	pickbb;		/* SS1 only */
+	volatile u32	dcfc;		/* SS1 only */
+	volatile u32	forcecol;	/* SS1 only */
+	volatile u32	door[8];	/* SS1 only */
+	volatile u32	pick[5];	/* SS1 only */
+};
+
+#define LEO_SS1_MISC_ENABLE	0x00000001
+#define LEO_SS1_MISC_STEREO	0x00000002
+struct leo_ld_ss1 {
+	u8		xxx0[0xef4];
+	volatile u32	ss1_misc;
+};
+
+struct leo_ld_gbl {
+	u8	unknown;
+};
+
+struct leo_par {
+	spinlock_t		lock;
+	struct leo_lx_krn	*lx_krn;
+	struct leo_lc_ss0_usr	*lc_ss0_usr;
+	struct leo_ld_ss0	*ld_ss0;
+	struct leo_ld_ss1	*ld_ss1;
+	struct leo_cursor	*cursor;
+	u32			extent;
+	u32			clut_data[256];
+
+	u32			flags;
+#define LEO_FLAG_BLANKED	0x00000001
+
+	unsigned long		physbase;
+	unsigned long		fbsize;
+
+	struct sbus_dev		*sdev;
+	struct list_head	list;
+};
+
+static void leo_wait(struct leo_lx_krn *lx_krn)
+{
+	int i;
+	
+	for (i = 0;
+	     (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && i < 300000;
+	     i++)
+		udelay (1); /* Busy wait at most 0.3 sec */
+	return;
+}
+
+/**
+ *      leo_setcolreg - Optional function. Sets a color register.
+ *      @regno: boolean, 0 copy local, 1 get_user() function
+ *      @red: frame buffer colormap structure
+ *      @green: The green value which can be up to 16 bits wide
+ *      @blue:  The blue value which can be up to 16 bits wide.
+ *      @transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ */
+static int leo_setcolreg(unsigned regno,
+			 unsigned red, unsigned green, unsigned blue,
+			 unsigned transp, struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+        struct leo_lx_krn *lx_krn = par->lx_krn;
+	unsigned long flags;
+	u32 val;
+	int i;
+
+	if (regno >= 256)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	par->clut_data[regno] = red | (green << 8) | (blue << 16);
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	leo_wait(lx_krn);
+
+	sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type);
+	for (i = 0; i < 256; i++)
+		sbus_writel(par->clut_data[i], &lx_krn->krn_value);
+	sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
+
+	val = sbus_readl(&lx_krn->krn_csr);
+	val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2);
+	sbus_writel(val, &lx_krn->krn_csr);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+/**
+ *      leo_blank - Optional function.  Blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int leo_blank(int blank, struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+	struct leo_lx_krn *lx_krn = par->lx_krn;
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	switch (blank) {
+	case 0: /* Unblanking */
+		val = sbus_readl(&lx_krn->krn_csr);
+		val |= LEO_KRN_CSR_ENABLE;
+		sbus_writel(val, &lx_krn->krn_csr);
+		par->flags &= ~LEO_FLAG_BLANKED;
+		break;
+
+	case 1: /* Normal blanking */
+	case 2: /* VESA blank (vsync off) */
+	case 3: /* VESA blank (hsync off) */
+	case 4: /* Poweroff */
+		val = sbus_readl(&lx_krn->krn_csr);
+		val &= ~LEO_KRN_CSR_ENABLE;
+		sbus_writel(val, &lx_krn->krn_csr);
+		par->flags |= LEO_FLAG_BLANKED;
+		break;
+	}
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+static struct sbus_mmap_map leo_mmap_map[] = {
+	{ LEO_SS0_MAP,		LEO_OFF_SS0,		0x800000	},
+	{ LEO_LC_SS0_USR_MAP,	LEO_OFF_LC_SS0_USR,	0x1000		},
+	{ LEO_LD_SS0_MAP,	LEO_OFF_LD_SS0,		0x1000		},
+	{ LEO_LX_CURSOR_MAP,	LEO_OFF_LX_CURSOR,	0x1000		},
+	{ LEO_SS1_MAP,		LEO_OFF_SS1,		0x800000	},
+	{ LEO_LC_SS1_USR_MAP,	LEO_OFF_LC_SS1_USR,	0x1000		},
+	{ LEO_LD_SS1_MAP,	LEO_OFF_LD_SS1,		0x1000		},
+	{ LEO_UNK_MAP,		LEO_OFF_UNK,		0x1000		},
+	{ LEO_LX_KRN_MAP,	LEO_OFF_LX_KRN,		0x1000		},
+	{ LEO_LC_SS0_KRN_MAP,	LEO_OFF_LC_SS0_KRN,	0x1000		},
+	{ LEO_LC_SS1_KRN_MAP,	LEO_OFF_LC_SS1_KRN,	0x1000		},
+	{ LEO_LD_GBL_MAP,	LEO_OFF_LD_GBL,		0x1000		},
+	{ LEO_UNK2_MAP,		LEO_OFF_UNK2,		0x100000	},
+	{ 0,			0,			0	  	}
+};
+
+static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+{
+	struct leo_par *par = (struct leo_par *)info->par;
+
+	return sbusfb_mmap_helper(leo_mmap_map,
+				  par->physbase, par->fbsize,
+				  par->sdev->reg_addrs[0].which_io,
+				  vma);
+}
+
+static int leo_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg, struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUNLEO, 32, par->fbsize);
+}
+
+/*
+ *  Initialisation
+ */
+
+static void
+leo_init_fix(struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *)info->par;
+
+	strncpy(info->fix.id, par->sdev->prom_name, sizeof(info->fix.id) - 1);
+	info->fix.id[sizeof(info->fix.id)-1] = 0;
+
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	info->fix.line_length = 8192;
+
+	info->fix.accel = FB_ACCEL_SUN_LEO;
+}
+
+static void leo_wid_put(struct fb_info *info, struct fb_wid_list *wl)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+	struct leo_lx_krn *lx_krn = par->lx_krn;
+	struct fb_wid_item *wi;
+	unsigned long flags;
+	u32 val;
+	int i, j;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	leo_wait(lx_krn);
+
+	for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) {
+		switch(wi->wi_type) {
+		case FB_WID_DBL_8:
+			j = (wi->wi_index & 0xf) + 0x40;
+			break;
+
+		case FB_WID_DBL_24:
+			j = wi->wi_index & 0x3f;
+			break;
+
+		default:
+			continue;
+		};
+		sbus_writel(0x5800 + j, &lx_krn->krn_type);
+		sbus_writel(wi->wi_values[0], &lx_krn->krn_value);
+	}
+	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
+
+	val = sbus_readl(&lx_krn->krn_csr);
+	val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2);
+	sbus_writel(val, &lx_krn->krn_csr);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+}
+
+static void leo_init_wids(struct fb_info *info)
+{
+	struct fb_wid_item wi;
+	struct fb_wid_list wl;
+
+	wl.wl_count = 1;
+	wl.wl_list = &wi;
+	wi.wi_type = FB_WID_DBL_8;
+	wi.wi_index = 0;
+	wi.wi_values [0] = 0x2c0;
+	leo_wid_put(info, &wl);
+	wi.wi_index = 1;
+	wi.wi_values [0] = 0x30;
+	leo_wid_put(info, &wl);
+	wi.wi_index = 2;
+	wi.wi_values [0] = 0x20;
+	leo_wid_put(info, &wl);
+	wi.wi_type = FB_WID_DBL_24;
+	wi.wi_index = 1;
+	wi.wi_values [0] = 0x30;
+	leo_wid_put(info, &wl);
+
+}
+
+static void leo_init_hw(struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+	struct leo_ld *ss = (struct leo_ld *) par->ld_ss0;
+	u32 val;
+
+	val = sbus_readl(&par->ld_ss1->ss1_misc);
+	val |= LEO_SS1_MISC_ENABLE;
+	sbus_writel(val, &par->ld_ss1->ss1_misc);
+
+	par->extent = ((info->var.xres - 1) |
+		       ((info->var.yres - 1) << 16));
+
+	sbus_writel(0xffffffff, &ss->wid);
+	sbus_writel(0xffff, &ss->wmask);
+	sbus_writel(0, &ss->vclipmin);
+	sbus_writel(par->extent, &ss->vclipmax);
+	sbus_writel(0, &ss->fg);
+	sbus_writel(0xff000000, &ss->planemask);
+	sbus_writel(0x310850, &ss->rop);
+	sbus_writel(0, &ss->widclip);
+	sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11),
+		    &par->lc_ss0_usr->extent);
+	sbus_writel(4, &par->lc_ss0_usr->addrspace);
+	sbus_writel(0x80000000, &par->lc_ss0_usr->fill);
+	sbus_writel(0, &par->lc_ss0_usr->fontt);
+	do {
+		val = sbus_readl(&par->lc_ss0_usr->csr);
+	} while (val & 0x20000000);
+}
+
+static void leo_fixup_var_rgb(struct fb_var_screeninfo *var)
+{
+	var->red.offset = 0;
+	var->red.length = 8;
+	var->green.offset = 8;
+	var->green.length = 8;
+	var->blue.offset = 16;
+	var->blue.length = 8;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+}
+
+struct all_info {
+	struct fb_info info;
+	struct leo_par par;
+	struct list_head list;
+};
+static LIST_HEAD(leo_list);
+
+static void leo_init_one(struct sbus_dev *sdev)
+{
+	struct all_info *all;
+	int linebytes;
+
+	all = kmalloc(sizeof(*all), GFP_KERNEL);
+	if (!all) {
+		printk(KERN_ERR "leo: Cannot allocate memory.\n");
+		return;
+	}
+	memset(all, 0, sizeof(*all));
+
+	INIT_LIST_HEAD(&all->list);
+
+	spin_lock_init(&all->par.lock);
+	all->par.sdev = sdev;
+
+	all->par.physbase = sdev->reg_addrs[0].phys_addr;
+
+	sbusfb_fill_var(&all->info.var, sdev->prom_node, 32);
+	leo_fixup_var_rgb(&all->info.var);
+
+	linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
+				       all->info.var.xres);
+	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
+
+#ifdef CONFIG_SPARC32
+	all->info.screen_base = (char *)
+		prom_getintdefault(sdev->prom_node, "address", 0);
+#endif
+	if (!all->info.screen_base)
+		all->info.screen_base = (char *)
+			sbus_ioremap(&sdev->resource[0], LEO_OFF_SS0,
+				     0x800000, "leo ram");
+
+	all->par.lc_ss0_usr = (struct leo_lc_ss0_usr *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LC_SS0_USR,
+			     0x1000, "leolc ss0usr");
+	all->par.ld_ss0 = (struct leo_ld_ss0 *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS0,
+			     0x1000, "leold ss0");
+	all->par.ld_ss1 = (struct leo_ld_ss1 *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS1,
+			     0x1000, "leold ss1");
+	all->par.lx_krn = (struct leo_lx_krn *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_KRN,
+			     0x1000, "leolx krn");
+	all->par.cursor = (struct leo_cursor *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR,
+			     sizeof(struct leo_cursor), "leolx cursor");
+
+	all->info.node = NODEV;
+	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.fbops = &leo_ops;
+	all->info.currcon = -1;
+	all->info.par = &all->par;
+
+	leo_init_wids(&all->info);
+	leo_init_hw(&all->info);
+
+	leo_blank(0, &all->info);
+
+	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
+		printk(KERN_ERR "leo: Could not allocate color map.\n");
+		kfree(all);
+		return;
+	}
+
+	leo_init_fix(&all->info);
+
+	if (register_framebuffer(&all->info) < 0) {
+		printk(KERN_ERR "leo: Could not register framebuffer.\n");
+		fb_dealloc_cmap(&all->info.cmap);
+		kfree(all);
+		return;
+	}
+
+	list_add(&all->list, &leo_list);
+
+	printk("leo: %s at %lx:%lx\n",
+	       sdev->prom_name,
+	       (long) sdev->reg_addrs[0].which_io,
+	       (long) sdev->reg_addrs[0].phys_addr);
+}
+
+int __init leo_init(void)
+{
+	struct sbus_bus *sbus;
+	struct sbus_dev *sdev;
+
+	for_all_sbusdev(sdev, sbus) {
+		if (!strcmp(sdev->prom_name, "leo"))
+			leo_init_one(sdev);
+	}
+
+	return 0;
+}
+
+void __exit leo_exit(void)
+{
+	struct list_head *pos, *tmp;
+
+	list_for_each_safe(pos, tmp, &leo_list) {
+		struct all_info *all = list_entry(pos, typeof(*all), list);
+
+		unregister_framebuffer(&all->info);
+		fb_dealloc_cmap(&all->info.cmap);
+		kfree(all);
+	}
+}
+
+int __init
+leo_setup(char *arg)
+{
+	/* No cmdline options yet... */
+	return 0;
+}
+
+#ifdef MODULE
+module_init(leo_init);
+module_exit(leo_exit);
+#endif
+
+MODULE_DESCRIPTION("framebuffer driver for LEO chipsets");
+MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/leofb.c b/drivers/video/leofb.c
--- a/drivers/video/leofb.c	Mon Oct 28 05:41:23 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,764 +0,0 @@
-/* $Id: leofb.c,v 1.14 2001/10/16 05:44:44 davem Exp $
- * leofb.c: Leo (ZX) 24/8bit frame buffer driver
- *
- * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/selection.h>
-
-#include <video/sbusfb.h>
-#include <asm/io.h>
-
-#define LEO_OFF_LC_SS0_KRN	0x00200000UL
-#define LEO_OFF_LC_SS0_USR	0x00201000UL
-#define LEO_OFF_LC_SS1_KRN	0x01200000UL
-#define LEO_OFF_LC_SS1_USR	0x01201000UL
-#define LEO_OFF_LD_SS0		0x00400000UL
-#define LEO_OFF_LD_SS1		0x01400000UL
-#define LEO_OFF_LD_GBL		0x00401000UL
-#define LEO_OFF_LX_KRN		0x00600000UL
-#define LEO_OFF_LX_CURSOR	0x00601000UL
-#define LEO_OFF_SS0		0x00800000UL
-#define LEO_OFF_SS1		0x01800000UL
-#define LEO_OFF_UNK		0x00602000UL
-#define LEO_OFF_UNK2		0x00000000UL
-
-#define LEO_CUR_ENABLE		0x00000080
-#define LEO_CUR_UPDATE		0x00000030
-#define LEO_CUR_PROGRESS	0x00000006
-#define LEO_CUR_UPDATECMAP	0x00000003
-
-#define LEO_CUR_TYPE_MASK	0x00000000
-#define LEO_CUR_TYPE_IMAGE	0x00000020
-#define LEO_CUR_TYPE_CMAP	0x00000050
-
-struct leo_cursor {
-	u8		xxx0[16];
-	volatile u32	cur_type;
-	volatile u32	cur_misc;
-	volatile u32	cur_cursxy;
-	volatile u32	cur_data;
-};
-
-#define LEO_KRN_TYPE_CLUT0	0x00001000
-#define LEO_KRN_TYPE_CLUT1	0x00001001
-#define LEO_KRN_TYPE_CLUT2	0x00001002
-#define LEO_KRN_TYPE_WID	0x00001003
-#define LEO_KRN_TYPE_UNK	0x00001006
-#define LEO_KRN_TYPE_VIDEO	0x00002003
-#define LEO_KRN_TYPE_CLUTDATA	0x00004000
-#define LEO_KRN_CSR_ENABLE	0x00000008
-#define LEO_KRN_CSR_PROGRESS	0x00000004
-#define LEO_KRN_CSR_UNK		0x00000002
-#define LEO_KRN_CSR_UNK2	0x00000001
-
-struct leo_lx_krn {
-	volatile u32	krn_type;
-	volatile u32	krn_csr;
-	volatile u32	krn_value;
-};
-
-struct leo_lc_ss0_krn {
-	volatile u32 	misc;
-	u8		xxx0[0x800-4];
-	volatile u32	rev;
-};
-
-struct leo_lc_ss0_usr {
-	volatile u32	csr;
-	volatile u32	addrspace;
-	volatile u32 	fontmsk;
-	volatile u32	fontt;
-	volatile u32	extent;
-	volatile u32	src;
-	u32		dst;
-	volatile u32	copy;
-	volatile u32	fill;
-};
-
-struct leo_lc_ss1_krn {
-	u8	unknown;
-};
-
-struct leo_lc_ss1_usr {
-	u8	unknown;
-};
-
-struct leo_ld {
-	u8		xxx0[0xe00];
-	volatile u32	csr;
-	volatile u32	wid;
-	volatile u32	wmask;
-	volatile u32	widclip;
-	volatile u32	vclipmin;
-	volatile u32	vclipmax;
-	volatile u32	pickmin;	/* SS1 only */
-	volatile u32	pickmax;	/* SS1 only */
-	volatile u32	fg;
-	volatile u32	bg;
-	volatile u32	src;		/* Copy/Scroll (SS0 only) */
-	volatile u32	dst;		/* Copy/Scroll/Fill (SS0 only) */
-	volatile u32	extent;		/* Copy/Scroll/Fill size (SS0 only) */
-	u32		xxx1[3];
-	volatile u32	setsem;		/* SS1 only */
-	volatile u32	clrsem;		/* SS1 only */
-	volatile u32	clrpick;	/* SS1 only */
-	volatile u32	clrdat;		/* SS1 only */
-	volatile u32	alpha;		/* SS1 only */
-	u8		xxx2[0x2c];
-	volatile u32	winbg;
-	volatile u32	planemask;
-	volatile u32	rop;
-	volatile u32	z;
-	volatile u32	dczf;		/* SS1 only */
-	volatile u32	dczb;		/* SS1 only */
-	volatile u32	dcs;		/* SS1 only */
-	volatile u32	dczs;		/* SS1 only */
-	volatile u32	pickfb;		/* SS1 only */
-	volatile u32	pickbb;		/* SS1 only */
-	volatile u32	dcfc;		/* SS1 only */
-	volatile u32	forcecol;	/* SS1 only */
-	volatile u32	door[8];	/* SS1 only */
-	volatile u32	pick[5];	/* SS1 only */
-};
-
-#define LEO_SS1_MISC_ENABLE	0x00000001
-#define LEO_SS1_MISC_STEREO	0x00000002
-struct leo_ld_ss1 {
-	u8		xxx0[0xef4];
-	volatile u32	ss1_misc;
-};
-
-struct leo_ld_gbl {
-	u8	unknown;
-};
-
-static struct sbus_mmap_map leo_mmap_map[] = {
-	{ LEO_SS0_MAP,		LEO_OFF_SS0,		0x800000	},
-	{ LEO_LC_SS0_USR_MAP,	LEO_OFF_LC_SS0_USR,	0x1000		},
-	{ LEO_LD_SS0_MAP,	LEO_OFF_LD_SS0,		0x1000		},
-	{ LEO_LX_CURSOR_MAP,	LEO_OFF_LX_CURSOR,	0x1000		},
-	{ LEO_SS1_MAP,		LEO_OFF_SS1,		0x800000	},
-	{ LEO_LC_SS1_USR_MAP,	LEO_OFF_LC_SS1_USR,	0x1000		},
-	{ LEO_LD_SS1_MAP,	LEO_OFF_LD_SS1,		0x1000		},
-	{ LEO_UNK_MAP,		LEO_OFF_UNK,		0x1000		},
-	{ LEO_LX_KRN_MAP,	LEO_OFF_LX_KRN,		0x1000		},
-	{ LEO_LC_SS0_KRN_MAP,	LEO_OFF_LC_SS0_KRN,	0x1000		},
-	{ LEO_LC_SS1_KRN_MAP,	LEO_OFF_LC_SS1_KRN,	0x1000		},
-	{ LEO_LD_GBL_MAP,	LEO_OFF_LD_GBL,		0x1000		},
-	{ LEO_UNK2_MAP,		LEO_OFF_UNK2,		0x100000	},
-	{ 0,			0,			0	  	}
-};
-
-static void leo_setup(struct display *p)
-{
-	p->next_line = 8192;
-	p->next_plane = 0;
-}
-
-static void leo_clear(struct vc_data *conp, struct display *p, int sy, int sx,
-		      int height, int width)
-{
-	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	unsigned long flags;
-	int x, y, w, h;
-	int i;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	do {
-		i = sbus_readl(&us->csr);
-	} while (i & 0x20000000);
-	sbus_writel((attr_bgcol_ec(p,conp)<<24), &ss->fg);
-	if (fontheightlog(p)) {
-		y = sy << fontheightlog(p); h = height << fontheightlog(p);
-	} else {
-		y = sy * fontheight(p); h = height * fontheight(p);
-	}
-	if (fontwidthlog(p)) {
-		x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
-	} else {
-		x = sx * fontwidth(p); w = width * fontwidth(p);
-	}
-	sbus_writel((w - 1) | ((h - 1) << 11), &us->extent);
-	sbus_writel((x + fb->x_margin) | ((y + fb->y_margin) << 11) | 0x80000000,
-		    &us->fill);
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
-		     int count, unsigned short *boxes)
-{
-	int i;
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	unsigned long flags;
-	
-	spin_lock_irqsave(&fb->lock, flags);
-	sbus_writel((attr_bgcol(p,s)<<24), &ss->fg);
-	while (count-- > 0) {
-		do {
-			i = sbus_readl(&us->csr);
-		} while (i & 0x20000000);
-		sbus_writel((boxes[2] - boxes[0] - 1) | 
-			    ((boxes[3] - boxes[1] - 1) << 11),
-			    &us->extent);
-		sbus_writel(boxes[0] | (boxes[1] << 11) | 0x80000000,
-			    &us->fill);
-		boxes += 4;
-	}
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
-{
-	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	unsigned long flags;
-	int i, x, y;
-	u8 *fd;
-	u32 *u;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	if (fontheightlog(p)) {
-		y = yy << (fontheightlog(p) + 11);
-		i = (c & p->charmask) << fontheightlog(p);
-	} else {
-		y = (yy * fontheight(p)) << 11;
-		i = (c & p->charmask) * fontheight(p);
-	}
-	if (fontwidth(p) <= 8)
-		fd = p->fontdata + i;
-	else
-		fd = p->fontdata + (i << 1);
-	if (fontwidthlog(p))
-		x = xx << fontwidthlog(p);
-	else
-		x = xx * fontwidth(p);
-	do {
-		i = sbus_readl(&us->csr);
-	} while (i & 0x20000000);
-	sbus_writel(attr_fgcol(p,c) << 24, &ss->fg);
-	sbus_writel(attr_bgcol(p,c) << 24, &ss->bg);
-	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)),
-		    &us->fontmsk);
-	u = ((u32 *)fb->info.screen_base) + y + x;
-	if (fontwidth(p) <= 8) {
-		for (i = 0; i < fontheight(p); i++, u += 2048) {
-			u32 val = *fd++ << 24;
-
-			sbus_writel(val, u);
-		}
-	} else {
-		for (i = 0; i < fontheight(p); i++, u += 2048) {
-			u32 val = *(u16 *)fd << 16;
-
-			sbus_writel(val, u);
-			fd += 2;
-		}
-	}
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
-		      int count, int yy, int xx)
-{
-	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	unsigned long flags;
-	int i, x, y;
-	u8 *fd1, *fd2, *fd3, *fd4;
-	u16 c;
-	u32 *u;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	do {
-		i = sbus_readl(&us->csr);
-	} while (i & 0x20000000);
-	c = scr_readw(s);
-	sbus_writel(attr_fgcol(p, c) << 24, &ss->fg);
-	sbus_writel(attr_bgcol(p, c) << 24, &ss->bg);
-	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk);
-	if (fontwidthlog(p))
-		x = (xx << fontwidthlog(p));
-	else
-		x = xx * fontwidth(p);
-	if (fontheightlog(p))
-		y = yy << (fontheightlog(p) + 11);
-	else
-		y = (yy * fontheight(p)) << 11;
-	u = ((u32 *)fb->info.screen_base) + y + x;
-	if (fontwidth(p) <= 8) {
-		sbus_writel(0xFFFFFFFF<<(32-4*fontwidth(p)), &us->fontmsk);
-		x = 4*fontwidth(p) - fontheight(p)*2048;
-		while (count >= 4) {
-			count -= 4;
-			if (fontheightlog(p)) {
-				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-			} else {
-				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-			}
-			if (fontwidth(p) == 8) {
-				for (i = 0; i < fontheight(p); i++, u += 2048) {
-					u32 val;
-
-					val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
-						<< 8)) << 8)) << 8);
-					sbus_writel(val, u);
-				}
-				u += x;
-			} else {
-				for (i = 0; i < fontheight(p); i++, u += 2048) {
-					u32 val;
-
-					val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
-						<< fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
-					sbus_writel(val, u);
-				}
-				u += x;
-			}
-		}
-	} else {
-		sbus_writel(0xFFFFFFFF<<(32-2*fontwidth(p)), &us->fontmsk);
-		x = 2*fontwidth(p) - fontheight(p)*2048;
-		while (count >= 2) {
-			count -= 2;
-			if (fontheightlog(p)) {
-				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
-				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
-			} else {
-				fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
-				fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
-			}
-			for (i = 0; i < fontheight(p); i++, u += 2048) {
-				u32 val;
-
-				val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
-				sbus_writel(val, u);
-				fd1 += 2; fd2 += 2;
-			}
-			u += x;
-		}
-	}
-	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk);
-	x = fontwidth(p) - fontheight(p)*2048;
-	while (count) {
-		count--;
-		if (fontheightlog(p))
-			i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-		else
-			i = ((scr_readw(s++) & p->charmask) * fontheight(p));
-		if (fontwidth(p) <= 8) {
-			fd1 = p->fontdata + i;
-			for (i = 0; i < fontheight(p); i++, u += 2048) {
-				u32 val = *fd1++ << 24;
-
-				sbus_writel(val, u);
-			}
-		} else {
-			fd1 = p->fontdata + (i << 1);
-			for (i = 0; i < fontheight(p); i++, u += 2048) {
-				u32 val = *(u16 *)fd1 << 16;
-
-				sbus_writel(val, u);
-				fd1 += 2;
-			}
-		}
-		u += x;
-	}
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void leo_revc(struct display *p, int xx, int yy)
-{
-	/* Not used if hw cursor */
-}
-
-static int leo_wait (struct leo_lx_krn *lx_krn)
-{
-	int i;
-	
-	for (i = 0; (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && i < 300000; i++)
-		udelay (1); /* Busy wait at most 0.3 sec */
-	if (i == 300000)
-		return -EFAULT; /* Timed out - should we print some message? */
-	return 0;
-}
-
-static void leo_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
-{
-        struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
-	unsigned long flags;
-	u32 tmp;
-	int i;
-	
-	spin_lock_irqsave(&fb->lock, flags);
-	sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
-	i = leo_wait (lx_krn);
-	if (i)
-		goto out;
-	sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type);
-	for (i = 0; i < 256; i++) {
-		u32 val;
-
-		val = fb->color_map CM(i,0) |
-			(fb->color_map CM(i,1) << 8) |
-			(fb->color_map CM(i,2) << 16);
-
-		sbus_writel(val, &lx_krn->krn_value); /* Throw colors there :)) */
-	}
-	sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
-	tmp = sbus_readl(&lx_krn->krn_csr);
-	tmp |= (LEO_KRN_CSR_UNK|LEO_KRN_CSR_UNK2);
-	sbus_writel(tmp, &lx_krn->krn_csr);
-out:
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void leo_restore_palette (struct fb_info_sbusfb *fb)
-{
-	u32 tmp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	tmp = sbus_readl(&fb->s.leo.ld_ss1->ss1_misc);
-	tmp &= ~(LEO_SS1_MISC_ENABLE);
-	sbus_writel(tmp, &fb->s.leo.ld_ss1->ss1_misc);
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static struct display_switch leo_dispsw __initdata = {
-	.setup =	leo_setup,
-	.bmove =	fbcon_redraw_bmove,
-	.clear =	leo_clear,
-	.putc =		leo_putc,
-	.putcs =	leo_putcs,
-	.revc =		leo_revc, 
-	.fontwidthmask =FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
-};
-
-static void leo_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
-{
-        struct leo_cursor *l = fb->s.leo.cursor;
-	unsigned long flags;
-	int i;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	for (i = 0; (sbus_readl(&l->cur_misc) & LEO_CUR_PROGRESS) && i < 300000; i++)
-		udelay (1); /* Busy wait at most 0.3 sec */
-	if (i == 300000)
-		goto out; /* Timed out - should we print some message? */
-	sbus_writel(LEO_CUR_TYPE_CMAP, &l->cur_type);
-	sbus_writel((red[0] | (green[0]<<8) | (blue[0]<<16)), &l->cur_data);
-	sbus_writel((red[1] | (green[1]<<8) | (blue[1]<<16)), &l->cur_data);
-	sbus_writel(LEO_CUR_UPDATECMAP, &l->cur_misc);
-out:
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-/* Set cursor shape */
-static void leo_setcurshape (struct fb_info_sbusfb *fb)
-{
-	int i, j, k;
-	u32 m, n, mask;
-	struct leo_cursor *l = fb->s.leo.cursor;
-	u32 tmp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	tmp = sbus_readl(&l->cur_misc);
-	tmp &= ~LEO_CUR_ENABLE;
-	sbus_writel(tmp, &l->cur_misc);
-	for (k = 0; k < 2; k ++) {
-		sbus_writel((k * LEO_CUR_TYPE_IMAGE), &l->cur_type);
-		for (i = 0; i < 32; i++) {
-			mask = 0;
-			m = fb->cursor.bits[k][i];
-			/* mask = m with reversed bit order */
-			for (j = 0, n = 1; j < 32; j++, n <<= 1)
-				if (m & n)
-					mask |= (0x80000000 >> j);
-			sbus_writel(mask, &l->cur_data);
-		}
-	}
-	tmp = sbus_readl(&l->cur_misc);
-	tmp |= LEO_CUR_ENABLE;
-	sbus_writel(tmp, &l->cur_misc);
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-/* Load cursor information */
-static void leo_setcursor (struct fb_info_sbusfb *fb)
-{
-	struct cg_cursor *c = &fb->cursor;
-	struct leo_cursor *l = fb->s.leo.cursor;
-	unsigned long flags;
-	u32 tmp;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	tmp = sbus_readl(&l->cur_misc);
-	tmp &= ~LEO_CUR_ENABLE;
-	sbus_writel(tmp, &l->cur_misc);
-
-	sbus_writel(((c->cpos.fbx - c->chot.fbx) & 0x7ff) |
-		    (((c->cpos.fby - c->chot.fby) & 0x7ff) << 11),
-		    &l->cur_cursxy);
-
-	tmp = sbus_readl(&l->cur_misc);
-	tmp |= LEO_CUR_UPDATE;
-	if (c->enable)
-		tmp |= LEO_CUR_ENABLE;
-	sbus_writel(tmp, &l->cur_misc);
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static int leo_blank (struct fb_info_sbusfb *fb)
-{
-	unsigned long flags;
-	u32 tmp;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type);
-
-	tmp = sbus_readl(&fb->s.leo.lx_krn->krn_csr);
-	tmp &= ~LEO_KRN_CSR_ENABLE;
-	sbus_writel(tmp, &fb->s.leo.lx_krn->krn_csr);
-	spin_unlock_irqrestore(&fb->lock, flags);
-	return 0;
-}
-
-static int leo_unblank (struct fb_info_sbusfb *fb)
-{
-	unsigned long flags;
-	u32 tmp;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type);
-
-	tmp = sbus_readl(&fb->s.leo.lx_krn->krn_csr);
-	if (!(tmp & LEO_KRN_CSR_ENABLE)) {
-		tmp |= LEO_KRN_CSR_ENABLE;
-		sbus_writel(tmp, &fb->s.leo.lx_krn->krn_csr);
-	}
-	spin_unlock_irqrestore(&fb->lock, flags);
-	return 0;
-}
-
-static int __init
-leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl)
-{
-	struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
-	struct fb_wid_item *wi;
-	int i, j;
-
-	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
-	i = leo_wait (lx_krn);
-	if (i)
-		return i;
-	for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) {
-		switch (wi->wi_type) {
-		case FB_WID_DBL_8: j = (wi->wi_index & 0xf) + 0x40; break;
-		case FB_WID_DBL_24: j = wi->wi_index & 0x3f; break;
-		default: return -EINVAL;
-		}
-		sbus_writel(0x5800 + j, &lx_krn->krn_type);
-		sbus_writel(wi->wi_values[0], &lx_krn->krn_value);
-	}
-	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
-	sbus_writel(3, &lx_krn->krn_csr);
-	return 0;
-}
-
-static void leo_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
-{
-	fb->info.screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
-}
-
-static void leo_switch_from_graph (struct fb_info_sbusfb *fb)
-{
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	sbus_writel(0xffffffff, &ss->wid);
-	sbus_writel(0xffff, &ss->wmask);
-	sbus_writel(0, &ss->vclipmin);
-	sbus_writel(fb->s.leo.extent, &ss->vclipmax);
-	sbus_writel(0xff000000, &ss->planemask);
-	sbus_writel(0x310850, &ss->rop);
-	sbus_writel(0, &ss->widclip);
-	sbus_writel(4, &us->addrspace);
-	sbus_writel(0, &us->fontt);
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static int __init leo_rasterimg (struct fb_info *info, int start)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-
-	if (start) {
-		sbus_writel(1, &ss->wid);
-		sbus_writel(0xffffff, &ss->planemask); 
-		sbus_writel(0x310b90, &ss->rop);
-		sbus_writel(0, &us->addrspace);
-	} else {
-		sbus_writel(0xffffffff, &ss->wid);
-		sbus_writel(0xff000000, &ss->planemask);
-		sbus_writel(0x310850, &ss->rop);
-		sbus_writel(4, &us->addrspace);
-	}
-	return 0;
-}
-
-static char idstring[40] __initdata = { 0 };
-
-char * __init leofb_init(struct fb_info_sbusfb *fb)
-{
-	struct fb_fix_screeninfo *fix = &fb->info.fix;
-	struct fb_var_screeninfo *var = &fb->info.var;
-	struct display *disp = &fb->disp;
-	struct fbtype *type = &fb->type;
-	struct sbus_dev *sdev = fb->sbdp;
-	unsigned long phys = sdev->reg_addrs[0].phys_addr;
-	struct fb_wid_item wi;
-	struct fb_wid_list wl;
-	int i;
-	register struct leo_lc_ss0_usr *us;
-	register struct leo_ld *ss;
-	struct fb_ops *fbops;
-	u32 tmp;
-
-	strcpy(fb->info.modename, "Leo");
-		
-	strcpy(fix->id, "Leo");
-	fix->visual = FB_VISUAL_TRUECOLOR;
-	fix->line_length = 8192;
-	fix->accel = FB_ACCEL_SUN_LEO;
-	
-	var->bits_per_pixel = 32;
-	var->green.offset = 8;
-	var->blue.offset = 16;
-	var->accel_flags = FB_ACCELF_TEXT;
-	
-	fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
-	if (fbops == NULL)
-		return NULL;
-	
-	*fbops = *fb->info.fbops;
-	fbops->fb_rasterimg = leo_rasterimg;
-	fb->info.fbops = fbops;
-	
-	disp->scrollmode = SCROLL_YREDRAW;
-	if (!fb->info.screen_base) {
-		fb->info.screen_base = (char *)
-			sbus_ioremap(&sdev->resource[0], LEO_OFF_SS0,
-				     0x800000, "leo ram");
-	}
-	fb->info.screen_base += 8192 * fb->y_margin + 4 * fb->x_margin;
-	us = fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *)
-		sbus_ioremap(&sdev->resource[0], LEO_OFF_LC_SS0_USR,
-			     0x1000, "leolc ss0usr");
-	fb->s.leo.ld_ss0 = (struct leo_ld_ss0 *)
-		sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS0,
-			     0x1000, "leold ss0");
-	ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	fb->s.leo.ld_ss1 = (struct leo_ld_ss1 *)
-		sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS1,
-			     0x1000, "leold ss1");
-	fb->s.leo.lx_krn = (struct leo_lx_krn *)
-		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_KRN,
-			     0x1000, "leolx krn");
-	fb->s.leo.cursor = (struct leo_cursor *)
-		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR,
-			     sizeof(struct leo_cursor), "leolx cursor");
-	fb->dispsw = leo_dispsw;
-	
-	fb->s.leo.extent = (type->fb_width-1) | ((type->fb_height-1) << 16);
-
-	wl.wl_count = 1;
-	wl.wl_list = &wi;
-	wi.wi_type = FB_WID_DBL_8;
-	wi.wi_index = 0;
-	wi.wi_values [0] = 0x2c0;
-	leo_wid_put (fb, &wl);
-	wi.wi_index = 1;
-	wi.wi_values [0] = 0x30;
-	leo_wid_put (fb, &wl);
-	wi.wi_index = 2;
-	wi.wi_values [0] = 0x20;
-	leo_wid_put (fb, &wl);
-	wi.wi_type = FB_WID_DBL_24;
-	wi.wi_index = 1;
-	wi.wi_values [0] = 0x30;
-	leo_wid_put (fb, &wl);
-
-	tmp = sbus_readl(&fb->s.leo.ld_ss1->ss1_misc);
-	tmp |= LEO_SS1_MISC_ENABLE;
-	sbus_writel(tmp, &fb->s.leo.ld_ss1->ss1_misc);
-
-	sbus_writel(0xffffffff, &ss->wid);
-	sbus_writel(0xffff, &ss->wmask);
-	sbus_writel(0, &ss->vclipmin);
-	sbus_writel(fb->s.leo.extent, &ss->vclipmax);
-	sbus_writel(0, &ss->fg);
-	sbus_writel(0xff000000, &ss->planemask);
-	sbus_writel(0x310850, &ss->rop);
-	sbus_writel(0, &ss->widclip);
-	sbus_writel((type->fb_width-1) | ((type->fb_height-1) << 11), &us->extent);
-	sbus_writel(4, &us->addrspace);
-	sbus_writel(0x80000000, &us->fill);
-	sbus_writel(0, &us->fontt);
-	do {
-		i = sbus_readl(&us->csr);
-	} while (i & 0x20000000);
-
-	fb->margins = leo_margins;
-	fb->loadcmap = leo_loadcmap;
-	fb->setcursor = leo_setcursor;
-	fb->setcursormap = leo_setcursormap;
-	fb->setcurshape = leo_setcurshape;
-	fb->restore_palette = leo_restore_palette;
-	fb->switch_from_graph = leo_switch_from_graph;
-	fb->fill = leo_fill;
-	fb->blank = leo_blank;
-	fb->unblank = leo_unblank;
-	
-	fb->physbase = phys;
-	fb->mmap_map = leo_mmap_map;
-	
-#ifdef __sparc_v9__
-	sprintf(idstring, "leo at %016lx", phys);
-#else	
-	sprintf(idstring, "leo at %x.%08lx", fb->iospace, phys);
-#endif
-		    
-	return idstring;
-}
-
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/p9100.c b/drivers/video/p9100.c
--- a/drivers/video/p9100.c	Sun Mar  2 22:51:11 2003
+++ b/drivers/video/p9100.c	Tue Mar  4 09:55:26 2003
@@ -27,13 +27,13 @@
  * Local functions.
  */
 
-static int p9100_check_var(struct fb_var_screeninfo *, struct fb_info *);
-static int p9100_set_par(struct fb_info *);
 static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned,
 			   unsigned, struct fb_info *);
 static int p9100_blank(int, struct fb_info *);
 
 static int p9100_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+static int p9100_ioctl(struct inode *, struct file *, unsigned int,
+		       unsigned long, struct fb_info *);
 
 /*
  *  Frame buffer operations
@@ -41,14 +41,13 @@
 
 static struct fb_ops p9100_ops = {
 	.owner			= THIS_MODULE,
-	.fb_check_var		= p9100_check_var,
-	.fb_set_par		= p9100_set_par,
 	.fb_setcolreg		= p9100_setcolreg,
 	.fb_blank		= p9100_blank,
 	.fb_fillrect		= cfb_fillrect,
 	.fb_copyarea		= cfb_copyarea,
 	.fb_imageblit		= cfb_imageblit,
 	.fb_mmap		= p9100_mmap,
+	.fb_ioctl		= p9100_ioctl,
 	.fb_cursor		= soft_cursor,
 };
 
@@ -143,39 +142,6 @@
 };
 
 /**
- *      p9100_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int p9100_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->bits_per_pixel != 8)
-		return -EINVAL;
-
-	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
-		return -EINVAL;
-	if (var->nonstd)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if (var->xres != info->var.xres || var->yres != info->var.yres)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- *      p9100_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-p9100_set_par(struct fb_info *info)
-{
-	return 0;
-}
-
-/**
  *      p9100_setcolreg - Optional function. Sets a color register.
  *      @regno: boolean, 0 copy local, 1 get_user() function
  *      @red: frame buffer colormap structure
@@ -265,6 +231,16 @@
 				  vma);
 }
 
+static int p9100_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		       unsigned long arg, struct fb_info *info)
+{
+	struct p9100_par *par = (struct p9100_par *) info->par;
+
+	/* Make it look like a cg3. */
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUN3COLOR, 8, par->fbsize);
+}
+
 /*
  *  Initialisation
  */
@@ -344,7 +320,6 @@
 		return;
 	}
 
-	p9100_set_par(&all->info);
 	p9100_init_fix(&all->info, linebytes);
 
 	if (register_framebuffer(&all->info) < 0) {
diff -Nru a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
--- a/drivers/video/sa1100fb.c	Tue Feb 25 02:46:52 2003
+++ b/drivers/video/sa1100fb.c	Thu Mar  6 08:48:29 2003
@@ -1590,11 +1590,21 @@
 	struct sa1100fb_info *fbi = TO_INF(nb, freq_policy);
 	struct cpufreq_policy *policy = data;
 
-	if (val == CPUFREQ_INCOMPATIBLE) {
+	switch (val) {
+	case CPUFREQ_ADJUST:
+	case CPUFREQ_INCOMPATIBLE:
 		printk(KERN_DEBUG "min dma period: %d ps, "
 			"new clock %d kHz\n", sa1100fb_min_dma_period(fbi),
 			policy->max);
 		/* todo: fill in min/max values */
+		break;
+	case CPUFREQ_NOTIFY:
+		do {} while(0);
+		/* todo: panic if min/max values aren't fulfilled 
+		 * [can't really happen unless there's a bug in the
+		 * CPU policy verififcation process *
+		 */
+		break;
 	}
 	return 0;
 }
diff -Nru a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c
--- a/drivers/video/sbuslib.c	Thu Feb 27 04:19:21 2003
+++ b/drivers/video/sbuslib.c	Tue Mar  4 09:55:26 2003
@@ -9,6 +9,7 @@
 #include <linux/fb.h>
 
 #include <asm/oplib.h>
+#include <asm/fbio.h>
 
 #include "sbuslib.h"
 
@@ -83,3 +84,84 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(sbusfb_mmap_helper);
+
+int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
+			struct fb_info *info,
+			int type, int fb_depth, unsigned long fb_size)
+{
+	switch(cmd) {
+	case FBIOGTYPE: {
+		struct fbtype *f = (struct fbtype *) arg;
+
+		if (put_user(type, &f->fb_type) ||
+		    __put_user(info->var.yres, &f->fb_height) ||
+		    __put_user(info->var.xres, &f->fb_width) ||
+		    __put_user(fb_depth, &f->fb_depth) ||
+		    __put_user(0, &f->fb_cmsize) ||
+		    __put_user(fb_size, &f->fb_cmsize))
+			return -EFAULT;
+		return 0;
+	}
+	case FBIOPUTCMAP_SPARC: {
+		struct fbcmap *c = (struct fbcmap *) arg;
+		struct fb_cmap cmap;
+		u16 red, green, blue;
+		unsigned char *ured, *ugreen, *ublue;
+		int index, count, i;
+
+		if (get_user(index, &c->index) ||
+		    __get_user(count, &c->count) ||
+		    __get_user(ured, &c->red) ||
+		    __get_user(ugreen, &c->green) ||
+		    __get_user(ublue, &c->blue))
+			return -EFAULT;
+
+		cmap.len = 1;
+		cmap.red = &red;
+		cmap.green = &green;
+		cmap.blue = &blue;
+		for (i = 0; i < count; i++) {
+			int err;
+
+			if (get_user(red, &ured[i]) ||
+			    get_user(green, &ugreen[i]) ||
+			    get_user(blue, &ublue[i]))
+				return -EFAULT;
+
+			cmap.start = index + i;
+			err = fb_set_cmap(&cmap, 0, info);
+			if (err)
+				return err;
+		}
+		return 0;
+	}
+	case FBIOGETCMAP_SPARC: {
+		struct fbcmap *c = (struct fbcmap *) arg;
+		unsigned char *ured, *ugreen, *ublue;
+		struct fb_cmap *cmap = &info->cmap;
+		int index, count, i;
+
+		if (get_user(index, &c->index) ||
+		    __get_user(count, &c->count) ||
+		    __get_user(ured, &c->red) ||
+		    __get_user(ugreen, &c->green) ||
+		    __get_user(ublue, &c->blue))
+			return -EFAULT;
+
+		if (index + count > cmap->len)
+			return -EINVAL;
+
+		for (i = 0; i < count; i++) {
+			if (put_user(cmap->red[index + i], &ured[i]) ||
+			    put_user(cmap->green[index + i], &ugreen[i]) ||
+			    put_user(cmap->blue[index + i], &ublue[i]))
+				return -EFAULT;
+		}
+		return 0;
+	}
+	default:
+		return -EINVAL;
+	};
+}
+EXPORT_SYMBOL(sbusfb_ioctl_helper);
diff -Nru a/drivers/video/sbuslib.h b/drivers/video/sbuslib.h
--- a/drivers/video/sbuslib.h	Thu Feb 27 04:19:22 2003
+++ b/drivers/video/sbuslib.h	Tue Mar  4 09:55:26 2003
@@ -17,5 +17,8 @@
 			      unsigned long physbase, unsigned long fbsize,
 			      unsigned long iospace,
 			      struct vm_area_struct *vma);
+int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
+			struct fb_info *info,
+			int type, int fb_depth, unsigned long fb_size);
 
 #endif /* _SBUSLIB_H */
diff -Nru a/drivers/video/tcx.c b/drivers/video/tcx.c
--- a/drivers/video/tcx.c	Sun Mar  2 23:19:15 2003
+++ b/drivers/video/tcx.c	Tue Mar  4 09:55:26 2003
@@ -29,13 +29,13 @@
  * Local functions.
  */
 
-static int tcx_check_var(struct fb_var_screeninfo *, struct fb_info *);
-static int tcx_set_par(struct fb_info *);
 static int tcx_setcolreg(unsigned, unsigned, unsigned, unsigned,
 			 unsigned, struct fb_info *);
 static int tcx_blank(int, struct fb_info *);
 
 static int tcx_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+static int tcx_ioctl(struct inode *, struct file *, unsigned int,
+		     unsigned long, struct fb_info *);
 
 /*
  *  Frame buffer operations
@@ -43,14 +43,13 @@
 
 static struct fb_ops tcx_ops = {
 	.owner			= THIS_MODULE,
-	.fb_check_var		= tcx_check_var,
-	.fb_set_par		= tcx_set_par,
 	.fb_setcolreg		= tcx_setcolreg,
 	.fb_blank		= tcx_blank,
 	.fb_fillrect		= cfb_fillrect,
 	.fb_copyarea		= cfb_copyarea,
 	.fb_imageblit		= cfb_imageblit,
 	.fb_mmap		= tcx_mmap,
+	.fb_ioctl		= tcx_ioctl,
 	.fb_cursor		= soft_cursor,
 };
 
@@ -155,39 +154,6 @@
 }
 
 /**
- *      tcx_check_var - Optional function.  Validates a var passed in.
- *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int tcx_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	if (var->bits_per_pixel != 8)
-		return -EINVAL;
-
-	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
-		return -EINVAL;
-	if (var->nonstd)
-		return -EINVAL;
-	if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-
-	if (var->xres != info->var.xres || var->yres != info->var.yres)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- *      tcx_set_par - Optional function.  Alters the hardware state.
- *      @info: frame buffer structure that represents a single frame buffer
- */
-static int
-tcx_set_par(struct fb_info *info)
-{
-	return 0;
-}
-
-/**
  *      tcx_setcolreg - Optional function. Sets a color register.
  *      @regno: boolean, 0 copy local, 1 get_user() function
  *      @red: frame buffer colormap structure
@@ -298,6 +264,17 @@
 				  vma);
 }
 
+static int tcx_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg, struct fb_info *info)
+{
+	struct tcx_par *par = (struct tcx_par *) info->par;
+
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_TCXCOLOR,
+				   (par->lowdepth ? 8 : 24),
+				   par->fbsize);
+}
+
 /*
  *  Initialisation
  */
@@ -431,7 +408,6 @@
 		return;
 	}
 
-	tcx_set_par(&all->info);
 	tcx_init_fix(&all->info, linebytes);
 
 	if (register_framebuffer(&all->info) < 0) {
diff -Nru a/fs/aio.c b/fs/aio.c
--- a/fs/aio.c	Tue Jan  7 14:52:20 2003
+++ b/fs/aio.c	Fri Mar  7 02:24:44 2003
@@ -76,7 +76,7 @@
 
 	aio_wq = create_workqueue("aio");
 
-	printk(KERN_NOTICE "aio_setup: sizeof(struct page) = %d\n", (int)sizeof(struct page));
+	pr_debug("aio_setup: sizeof(struct page) = %d\n", (int)sizeof(struct page));
 
 	return 0;
 }
@@ -1193,7 +1193,7 @@
 
 	if (NULL != cancel) {
 		struct io_event tmp;
-		printk("calling cancel\n");
+		pr_debug("calling cancel\n");
 		memset(&tmp, 0, sizeof(tmp));
 		tmp.obj = (u64)(unsigned long)kiocb->ki_user_obj;
 		tmp.data = kiocb->ki_user_data;
diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c	Thu Feb  6 07:33:47 2003
+++ b/fs/binfmt_elf.c	Sat Mar  8 14:50:42 2003
@@ -10,7 +10,7 @@
  */
 
 #include <linux/module.h>
-
+#include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/time.h>
@@ -256,8 +256,8 @@
 
 #ifndef elf_map
 
-static inline unsigned long
-elf_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
+static unsigned long elf_map(struct file *filep, unsigned long addr,
+			struct elf_phdr *eppnt, int prot, int type)
 {
 	unsigned long map_addr;
 
@@ -390,7 +390,6 @@
 	unsigned long text_data, elf_entry = ~0UL;
 	char * addr;
 	loff_t offset;
-	int retval;
 
 	current->mm->end_code = interp_ex->a_text;
 	text_data = interp_ex->a_text + interp_ex->a_data;
@@ -412,11 +411,9 @@
 	}
 
 	do_brk(0, text_data);
-	retval = -ENOEXEC;
 	if (!interpreter->f_op || !interpreter->f_op->read)
 		goto out;
-	retval = interpreter->f_op->read(interpreter, addr, text_data, &offset);
-	if (retval < 0)
+	if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0)
 		goto out;
 	flush_icache_range((unsigned long)addr,
 	                   (unsigned long)addr + text_data);
@@ -638,7 +635,7 @@
 	retval = setup_arg_pages(bprm);
 	if (retval < 0) {
 		send_sig(SIGKILL, current, 0);
-		return retval;
+		goto out_free_dentry;
 	}
 	
 	current->mm->start_stack = bprm->p;
@@ -742,7 +739,8 @@
 			printk(KERN_ERR "Unable to load interpreter\n");
 			kfree(elf_phdata);
 			send_sig(SIGSEGV, current, 0);
-			return 0;
+			retval = -ENOEXEC; /* Nobody gets to see this, but.. */
+			goto out;
 		}
 	} else {
 		elf_entry = elf_ex.e_entry;
@@ -934,7 +932,7 @@
  *
  * I think we should skip something. But I am not sure how. H.J.
  */
-static inline int maydump(struct vm_area_struct *vma)
+static int maydump(struct vm_area_struct *vma)
 {
 	/*
 	 * If we may not read the contents, don't allow us to dump
@@ -1046,7 +1044,7 @@
 	return;
 }
 
-static inline void fill_note(struct memelfnote *note, const char *name, int type, 
+static void fill_note(struct memelfnote *note, const char *name, int type, 
 		unsigned int sz, void *data)
 {
 	note->name = name;
@@ -1060,7 +1058,8 @@
  * fill up all the fields in prstatus from the given task struct, except registers
  * which need to be filled up separately.
  */
-static inline void fill_prstatus(struct elf_prstatus *prstatus, struct task_struct *p, long signr) 
+static void fill_prstatus(struct elf_prstatus *prstatus,
+			struct task_struct *p, long signr) 
 {
 	prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
 	prstatus->pr_sigpend = p->pending.signal.sig[0];
@@ -1075,7 +1074,7 @@
 	jiffies_to_timeval(p->cstime, &prstatus->pr_cstime);
 }
 
-static inline void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p)
+static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p)
 {
 	int i, len;
 	
@@ -1175,41 +1174,64 @@
  */
 static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
 {
+#define	NUM_NOTES	5
 	int has_dumped = 0;
 	mm_segment_t fs;
 	int segs;
 	size_t size = 0;
 	int i;
 	struct vm_area_struct *vma;
-	struct elfhdr elf;
+	struct elfhdr *elf = NULL;
 	off_t offset = 0, dataoff;
 	unsigned long limit = current->rlim[RLIMIT_CORE].rlim_cur;
-	int numnote = 5;
-	struct memelfnote notes[5];
-	struct elf_prstatus prstatus;	/* NT_PRSTATUS */
-	struct elf_prpsinfo psinfo;	/* NT_PRPSINFO */
+	int numnote = NUM_NOTES;
+	struct memelfnote *notes = NULL;
+	struct elf_prstatus *prstatus = NULL;	/* NT_PRSTATUS */
+	struct elf_prpsinfo *psinfo = NULL;	/* NT_PRPSINFO */
  	struct task_struct *g, *p;
  	LIST_HEAD(thread_list);
  	struct list_head *t;
-	elf_fpregset_t fpu;
+	elf_fpregset_t *fpu = NULL;
 #ifdef ELF_CORE_COPY_XFPREGS
-	elf_fpxregset_t xfpu;
+	elf_fpxregset_t *xfpu = NULL;
 #endif
 	int thread_status_size = 0;
-	
-	/* We no longer stop all vm operations
+
+	/*
+	 * We no longer stop all VM operations.
 	 * 
-	 * This because those proceses that could possibly 
-	 * change map_count or the mmap / vma pages are now blocked in do_exit on current finishing
+	 * This is because those proceses that could possibly change map_count or
+	 * the mmap / vma pages are now blocked in do_exit on current finishing
 	 * this core dump.
 	 *
 	 * Only ptrace can touch these memory addresses, but it doesn't change
-	 * the map_count or the pages allocated.  So no possibility of crashing exists while dumping
-	 * the mm->vm_next areas to the core file.
-	 *
+	 * the map_count or the pages allocated.  So no possibility of crashing
+	 * exists while dumping the mm->vm_next areas to the core file.
 	 */
-  	
-	 /* capture the status of all other threads */
+  
+	/* alloc memory for large data structures: too large to be on stack */
+	elf = kmalloc(sizeof(*elf), GFP_KERNEL);
+	if (!elf)
+		goto cleanup;
+	prstatus = kmalloc(sizeof(*prstatus), GFP_KERNEL);
+	if (!prstatus)
+		goto cleanup;
+	psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL);
+	if (!psinfo)
+		goto cleanup;
+	notes = kmalloc(NUM_NOTES * sizeof(struct memelfnote), GFP_KERNEL);
+	if (!notes)
+		goto cleanup;
+	fpu = kmalloc(sizeof(*fpu), GFP_KERNEL);
+	if (!fpu)
+		goto cleanup;
+#ifdef ELF_CORE_COPY_XFPREGS
+	xfpu = kmalloc(sizeof(*xfpu), GFP_KERNEL);
+	if (!xfpu)
+		goto cleanup;
+#endif
+
+	/* capture the status of all other threads */
 	if (signr) {
 		read_lock(&tasklist_lock);
 		do_each_thread(g,p)
@@ -1226,14 +1248,14 @@
 	}
 
 	/* now collect the dump for the current */
-	memset(&prstatus, 0, sizeof(prstatus));
-	fill_prstatus(&prstatus, current, signr);
-	elf_core_copy_regs(&prstatus.pr_reg, regs);
+	memset(prstatus, 0, sizeof(*prstatus));
+	fill_prstatus(prstatus, current, signr);
+	elf_core_copy_regs(&prstatus->pr_reg, regs);
 	
 	segs = current->mm->map_count;
 
 	/* Set up header */
-	fill_elf_header(&elf, segs+1); /* including notes section*/
+	fill_elf_header(elf, segs+1);	/* including notes section */
 
 	has_dumped = 1;
 	current->flags |= PF_DUMPCORE;
@@ -1243,32 +1265,32 @@
 	 * with info from their /proc.
 	 */
 
-	fill_note(&notes[0], "CORE", NT_PRSTATUS, sizeof(prstatus), &prstatus);
+	fill_note(notes +0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus);
 	
-	fill_psinfo(&psinfo, current->group_leader);
-	fill_note(&notes[1], "CORE", NT_PRPSINFO, sizeof(psinfo), &psinfo);
+	fill_psinfo(psinfo, current->group_leader);
+	fill_note(notes +1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
 	
-	fill_note(&notes[2], "CORE", NT_TASKSTRUCT, sizeof(*current), current);
+	fill_note(notes +2, "CORE", NT_TASKSTRUCT, sizeof(*current), current);
   
   	/* Try to dump the FPU. */
-	if ((prstatus.pr_fpvalid = elf_core_copy_task_fpregs(current, &fpu)))
-		fill_note(&notes[3], "CORE", NT_PRFPREG, sizeof(fpu), &fpu);
+	if ((prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, fpu)))
+		fill_note(notes +3, "CORE", NT_PRFPREG, sizeof(*fpu), fpu);
 	else
 		--numnote;
 #ifdef ELF_CORE_COPY_XFPREGS
-	if (elf_core_copy_task_xfpregs(current, &xfpu))
-		fill_note(&notes[4], "LINUX", NT_PRXFPREG, sizeof(xfpu), &xfpu);
+	if (elf_core_copy_task_xfpregs(current, xfpu))
+		fill_note(notes +4, "LINUX", NT_PRXFPREG, sizeof(*xfpu), xfpu);
 	else
 		--numnote;
 #else
-	numnote --;
+	numnote--;
 #endif	
   
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 
-	DUMP_WRITE(&elf, sizeof(elf));
-	offset += sizeof(elf);				/* Elf header */
+	DUMP_WRITE(elf, sizeof(*elf));
+	offset += sizeof(*elf);				/* Elf header */
 	offset += (segs+1) * sizeof(struct elf_phdr);	/* Program headers */
 
 	/* Write notes phdr entry */
@@ -1276,8 +1298,8 @@
 		struct elf_phdr phdr;
 		int sz = 0;
 
-		for(i = 0; i < numnote; i++)
-			sz += notesize(&notes[i]);
+		for (i = 0; i < numnote; i++)
+			sz += notesize(notes + i);
 		
 		sz += thread_status_size;
 
@@ -1290,7 +1312,7 @@
 	dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
 
 	/* Write program headers for segments dump */
-	for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
+	for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
 		struct elf_phdr phdr;
 		size_t sz;
 
@@ -1312,8 +1334,8 @@
 	}
 
  	/* write out the notes section */
-	for(i = 0; i < numnote; i++)
-		if (!writenote(&notes[i], file))
+	for (i = 0; i < numnote; i++)
+		if (!writenote(notes + i, file))
 			goto end_coredump;
 
 	/* write out the thread status notes section */
@@ -1326,7 +1348,7 @@
  
 	DUMP_SEEK(dataoff);
 
-	for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
+	for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
 		unsigned long addr;
 
 		if (!maydump(vma))
@@ -1373,7 +1395,16 @@
 		kfree(list_entry(tmp, struct elf_thread_status, list));
 	}
 
+	kfree(elf);
+	kfree(prstatus);
+	kfree(psinfo);
+	kfree(notes);
+	kfree(fpu);
+#ifdef ELF_CORE_COPY_XFPREGS
+	kfree(xfpu);
+#endif
 	return has_dumped;
+#undef NUM_NOTES
 }
 
 #endif		/* USE_ELF_CORE_DUMP */
diff -Nru a/fs/block_dev.c b/fs/block_dev.c
--- a/fs/block_dev.c	Wed Jan 15 12:51:33 2003
+++ b/fs/block_dev.c	Sat Mar  8 14:50:22 2003
@@ -436,56 +436,6 @@
 	spin_unlock(&bdev_lock);
 }
 
-static const char *blkdevs[MAX_BLKDEV];
-
-int get_blkdev_list(char * p)
-{
-	int i;
-	int len;
-
-	len = sprintf(p, "\nBlock devices:\n");
-	for (i = 0; i < MAX_BLKDEV ; i++) {
-		if (blkdevs[i])
-			len += sprintf(p+len, "%3d %s\n", i, blkdevs[i]);
-	}
-	return len;
-}
-
-int register_blkdev(unsigned int major, const char * name, struct block_device_operations *bdops)
-{
-	if (devfs_only())
-		return 0;
-	if (major == 0) {
-		for (major = MAX_BLKDEV-1; major > 0; major--) {
-			if (blkdevs[major] == NULL) {
-				blkdevs[major] = name;
-				return major;
-			}
-		}
-		return -EBUSY;
-	}
-	if (major >= MAX_BLKDEV)
-		return -EINVAL;
-	if (blkdevs[major])
-		return -EBUSY;
-	blkdevs[major] = name;
-	return 0;
-}
-
-int unregister_blkdev(unsigned int major, const char * name)
-{
-	if (devfs_only())
-		return 0;
-	if (major >= MAX_BLKDEV)
-		return -EINVAL;
-	if (!blkdevs[major])
-		return -EINVAL;
-	if (strcmp(blkdevs[major], name))
-		return -EINVAL;
-	blkdevs[major] = NULL;
-	return 0;
-}
-
 /*
  * This routine checks whether a removable media has been changed,
  * and invalidates all buffer-cache-entries in that case. This
@@ -784,18 +734,6 @@
 	res = blkdev_ioctl(bdev->bd_inode, NULL, cmd, arg);
 	set_fs(old_fs);
 	return res;
-}
-
-const char *__bdevname(dev_t dev)
-{
-	static char buffer[32];
-	const char * name = blkdevs[MAJOR(dev)];
-
-	if (!name)
-		name = "unknown-block";
-
-	sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
-	return buffer;
 }
 
 /**
diff -Nru a/fs/char_dev.c b/fs/char_dev.c
--- a/fs/char_dev.c	Thu Feb  6 16:20:33 2003
+++ b/fs/char_dev.c	Mon Mar 10 12:22:35 2003
@@ -191,8 +191,6 @@
 
 int register_chrdev(unsigned int major, const char * name, struct file_operations *fops)
 {
-	if (devfs_only())
-		return 0;
 	if (major == 0) {
 		write_lock(&chrdevs_lock);
 		for (major = MAX_CHRDEV-1; major > 0; major--) {
@@ -221,8 +219,6 @@
 
 int unregister_chrdev(unsigned int major, const char * name)
 {
-	if (devfs_only())
-		return 0;
 	if (major >= MAX_CHRDEV)
 		return -EINVAL;
 	write_lock(&chrdevs_lock);
diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES
--- a/fs/cifs/CHANGES	Sun Feb 23 14:23:53 2003
+++ b/fs/cifs/CHANGES	Fri Mar  7 15:01:07 2003
@@ -1,3 +1,16 @@
+Version 0.70
+------------
+Fix oops in get dfs referral (triggered when null path sent in to
+mount).  Add support for overriding rsize at mount time.
+
+Version 0.69
+------------
+Fix buffer overrun in readdir which caused intermittent kernel oopses.
+Fix writepage code to release kmap on write data.  Allow "-ip=" new 
+mount option to be passed in on parameter distinct from the first part
+(server name portion of) the UNC name.  Allow override of the
+tcp port of the target server via new mount option "-port="  
+
 Version 0.68
 ------------
 Fix search handle leak on rewind.  Fix setuid and gid so that they are 
diff -Nru a/fs/cifs/TODO b/fs/cifs/TODO
--- a/fs/cifs/TODO	Sat Feb 15 14:10:22 2003
+++ b/fs/cifs/TODO	Fri Mar  7 15:01:07 2003
@@ -42,13 +42,24 @@
 
 m) finish support for IPv6
 
-KNOWN BUGS (updated February 15, 2003)
+n) send oplock break response when sent (oplock currently disabled in
+/proc/fs/cifs)
+
+o) remove calls to set end of file by name when we already have file open
+(use the existing handle since some servers only support that and it
+reduces the oplock breaks coming from windows).  Piggyback identical
+file opens on top of each other by incrementing reference count rather
+than resending (helps reduce server resource utilization and avoid
+spurious oplock breaks).
+
+KNOWN BUGS (updated March 7, 2003)
 ====================================
 1) existing symbolic links (Windows reparse points) are recognized but
 can not be created remotely. They are implemented for Samba and those that
 support the CIFS Unix extensions but Samba has a bug currently handling
 symlink text beginning with slash
 2) delete of file with read-only attribute set will fail (may be ok)
+3) mount helper syntax not quite matching man page
 
 Misc testing to do
 =================
diff -Nru a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
--- a/fs/cifs/cifs_debug.c	Sat Feb 15 14:10:23 2003
+++ b/fs/cifs/cifs_debug.c	Fri Mar  7 15:01:07 2003
@@ -227,7 +227,7 @@
 	if (pde)
 		pde->write_proc = traceSMB_write;
 
-	pde = create_proc_read_entry("oplockEnabled", 0, proc_fs_cifs,
+	pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
 				     oplockEnabled_read, 0);
 	if (pde)
 		pde->write_proc = oplockEnabled_write;
@@ -269,7 +269,7 @@
 	remove_proc_entry("SimultaneousOps", proc_fs_cifs);
 	remove_proc_entry("TotalOps", proc_fs_cifs);
 	remove_proc_entry("MultiuserMount", proc_fs_cifs);
-	remove_proc_entry("oplockEnabled", proc_fs_cifs);
+	remove_proc_entry("OplockEnabled", proc_fs_cifs);
 	remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
 	remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
 	remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
diff -Nru a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
--- a/fs/cifs/cifs_fs_sb.h	Thu Oct 10 12:16:09 2002
+++ b/fs/cifs/cifs_fs_sb.h	Fri Mar  7 15:01:07 2003
@@ -20,8 +20,9 @@
 
 struct cifs_sb_info {
 	struct cifsTconInfo *tcon;	/* primary mount */
-	/* list of implicit mounts beneath this mount point - needed in dfs case */
 	struct list_head nested_tcon_q;
 	struct nls_table *local_nls;
+    unsigned int rsize;
+    unsigned int wsize;
 };
 #endif				/* _CIFS_FS_SB_H */
diff -Nru a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
--- a/fs/cifs/cifsfs.c	Sun Feb 23 14:23:53 2003
+++ b/fs/cifs/cifsfs.c	Fri Mar  7 15:01:07 2003
@@ -52,6 +52,7 @@
 unsigned int extended_security = 0;
 unsigned int ntlmv2_support = 0;
 unsigned int sign_CIFS_PDUs = 0;
+unsigned int CIFSMaximumBufferSize = CIFS_MAX_MSGSIZE;
 
 extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
 			char *);
@@ -83,8 +84,11 @@
 
 	sb->s_magic = CIFS_MAGIC_NUMBER;
 	sb->s_op = &cifs_super_ops;
-	sb->s_blocksize = CIFS_MAX_MSGSIZE;	/* BB check SMBSessSetup negotiated size */
-	sb->s_blocksize_bits = 10;	/* 2**10 = CIFS_MAX_MSGSIZE */
+	if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
+	    sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
+	else
+		sb->s_blocksize = CIFSMaximumBufferSize;
+	sb->s_blocksize_bits = 14;	/* default 2**14 = CIFS_MAX_MSGSIZE */
 	inode = iget(sb, ROOT_I);
 
 	if (!inode)
@@ -162,6 +166,12 @@
 	return 0;		/* always return success? what if volume is no longer available? */
 }
 
+static int cifs_permission(struct inode * inode, int mask)
+{
+	/* the server does permission checks, we do not need to do it here */
+	return 0;
+}
+
 static kmem_cache_t *cifs_inode_cachep;
 kmem_cache_t *cifs_req_cachep;
 kmem_cache_t *cifs_mid_cachep;
@@ -270,6 +280,7 @@
 	.mkdir = cifs_mkdir,
 	.rmdir = cifs_rmdir,
 	.rename = cifs_rename,
+	.permission = cifs_permission,
 /*	revalidate:cifs_revalidate,   */
 	.setattr = cifs_setattr,
 	.symlink = cifs_symlink,
@@ -280,18 +291,19 @@
 	.setattr = cifs_setattr,
 	.getattr = cifs_getattr, /* do we need this anymore? */
 	.rename = cifs_rename,
+	.permission = cifs_permission,
 #ifdef CIFS_XATTR
 	.setxattr = cifs_setxattr,
 	.getxattr = cifs_getxattr,
 	.listxattr = cifs_listxattr,
 	.removexattr = cifs_removexattr,
-	.permission = cifs_permission,
 #endif 
 };
 
 struct inode_operations cifs_symlink_inode_ops = {
 	.readlink = cifs_readlink,
 	.follow_link = cifs_follow_link,
+	.permission = cifs_permission,
 	/* BB add the following two eventually */
 	/* revalidate: cifs_revalidate,
 	   setattr:    cifs_notify_change, *//* BB do we need notify change */
@@ -318,6 +330,7 @@
 struct file_operations cifs_dir_ops = {
 	.readdir = cifs_readdir,
 	.release = cifs_closedir,
+	.read    = generic_read_dir,
 };
 
 static void
diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
--- a/fs/cifs/cifssmb.c	Wed Feb 19 15:31:55 2003
+++ b/fs/cifs/cifssmb.c	Fri Mar  7 15:01:07 2003
@@ -519,8 +519,7 @@
 	pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
 	pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
 	pSMB->Remaining = 0;
-	pSMB->MaxCount = cpu_to_le16(min_t(const unsigned int, count,
-		(tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00));
+	pSMB->MaxCount = cpu_to_le16(count);
 	pSMB->MaxCountHigh = 0;
 	pSMB->ByteCount = 0;  /* no need to do le conversion since it is 0 */
 
@@ -710,9 +709,9 @@
 				  , nls_codepage);
 		name_len++;	/* trailing null */
 		name_len *= 2;
-		pSMB->OldFileName[name_len] = 0;	/* pad */
+		pSMB->OldFileName[name_len] = 0x04;	/* pad */
 	/* protocol requires ASCII signature byte on Unicode string */
-		pSMB->OldFileName[name_len + 1] = 0x04;
+		pSMB->OldFileName[name_len + 1] = 0x00;
 		name_len2 =
 		    cifs_strtoUCS((wchar_t *) & pSMB->
 				  OldFileName[name_len + 2], toName, 530,
diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c
--- a/fs/cifs/connect.c	Sun Feb 23 14:23:54 2003
+++ b/fs/cifs/connect.c	Fri Mar  7 15:01:07 2003
@@ -25,6 +25,7 @@
 #include <linux/wait.h>
 #include <linux/version.h>
 #include <linux/ipv6.h>
+#include <linux/pagemap.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 #include "cifspdu.h"
@@ -56,6 +57,9 @@
 	mode_t file_mode;
 	mode_t dir_mode;
 	int rw;
+    unsigned int rsize;
+    unsigned int wsize;
+	unsigned short int port;
 };
 
 int ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket);
@@ -343,11 +347,7 @@
 	char *value;
 	char *data;
 
-	vol->username = NULL;
-	vol->password = NULL;
-	vol->domainname = NULL;
-	vol->UNC = NULL;
-	vol->UNCip = NULL;
+	memset(vol,0,sizeof(struct smb_vol));
 	vol->linux_uid = current->uid;	/* current->euid instead? */
 	vol->linux_gid = current->gid;
 	vol->rw = TRUE;
@@ -381,6 +381,15 @@
 				printk(KERN_WARNING "CIFS: password too long\n");
 				return 1;
 			}
+		} else if (strnicmp(data, "ip", 2) == 0) {
+			if (!value || !*value) {
+				vol->UNCip = NULL;
+			} else if (strnlen(value, 35) < 35) {
+				vol->UNCip = value;
+			} else {
+				printk(KERN_WARNING "CIFS: ip address too long\n");
+				return 1;
+			}
 		} else if ((strnicmp(data, "unc", 3) == 0)
 			   || (strnicmp(data, "target", 6) == 0)
 			   || (strnicmp(data, "path", 4) == 0)) {
@@ -399,7 +408,6 @@
 					       "CIFS: UNC Path does not begin with // or \\\\ \n");
 					return 1;
 				}
-				vol->UNCip = &vol->UNC[2];
 			} else {
 				printk(KERN_WARNING "CIFS: UNC name too long\n");
 				return 1;
@@ -420,22 +428,37 @@
 		} else if (strnicmp(data, "uid", 3) == 0) {
 			if (value && *value) {
 				vol->linux_uid =
-				    simple_strtoul(value, &value, 0);
+					simple_strtoul(value, &value, 0);
 			}
 		} else if (strnicmp(data, "gid", 3) == 0) {
 			if (value && *value) {
 				vol->linux_gid =
-				    simple_strtoul(value, &value, 0);
+					simple_strtoul(value, &value, 0);
 			}
 		} else if (strnicmp(data, "file_mode", 4) == 0) {
 			if (value && *value) {
 				vol->file_mode =
-				    simple_strtoul(value, &value, 0);
+					simple_strtoul(value, &value, 0);
 			}
 		} else if (strnicmp(data, "dir_mode", 3) == 0) {
 			if (value && *value) {
 				vol->dir_mode =
-				    simple_strtoul(value, &value, 0);
+					simple_strtoul(value, &value, 0);
+			}
+		} else if (strnicmp(data, "port", 4) == 0) {
+			if (value && *value) {
+				vol->port =
+					simple_strtoul(value, &value, 0);
+			}
+		} else if (strnicmp(data, "rsize", 5) == 0) {
+			if (value && *value) {
+				vol->rsize =
+					simple_strtoul(value, &value, 0);
+			}
+		} else if (strnicmp(data, "wsize", 5) == 0) {
+			if (value && *value) {
+				vol->wsize =
+					simple_strtoul(value, &value, 0);
 			}
 		} else if (strnicmp(data, "version", 3) == 0) {
 			/* ignore */
@@ -458,12 +481,14 @@
 				printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
 				return 1;
 			}
-			vol->UNCip = &vol->UNC[2];
 		} else {
 			printk(KERN_WARNING "CIFS: UNC name too long\n");
 			return 1;
 		}
 	}
+	if(vol->UNCip == 0)
+		vol->UNCip = &vol->UNC[2];
+
 	return 0;
 }
 
@@ -553,20 +578,16 @@
 	unsigned char *referrals = NULL;
 
 	if (pSesInfo->ipc_tid == 0) {
-		temp_unc =
-		    kmalloc(2 +
-			    strnlen(pSesInfo->serverName,
-				    SERVER_NAME_LEN_WITH_NULL * 2) + 1 +
-			    4 /* IPC$ */  + 1, GFP_KERNEL);
+		temp_unc = kmalloc(2 /* for slashes */ +
+			strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
+				 + 1 + 4 /* slash IPC$ */  + 2,
+				GFP_KERNEL);
 		if (temp_unc == NULL)
 			return -ENOMEM;
 		temp_unc[0] = '\\';
 		temp_unc[1] = '\\';
-		strncpy(temp_unc + 2, pSesInfo->serverName,
-			SERVER_NAME_LEN_WITH_NULL * 2);
-		strncpy(temp_unc + 2 +
-			strnlen(pSesInfo->serverName,
-				SERVER_NAME_LEN_WITH_NULL * 2), "\\IPC$", 6);
+		strcpy(temp_unc + 2, pSesInfo->serverName);
+		strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
 		rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
 		cFYI(1,
 		     ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
@@ -587,6 +608,7 @@
 	char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
 	int ntlmv2_flag = FALSE;
 
+    /* what if server changes its buffer size after dropping the session? */
 	if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */
 		rc = CIFSSMBNegotiate(xid, pSesInfo);
 	pSesInfo->capabilities = pSesInfo->server->capabilities;
@@ -670,11 +692,23 @@
 	}
 
 	psin_server->sin_family = AF_INET;
-	psin_server->sin_port = htons(CIFS_PORT);
+	if(psin_server->sin_port) { /* user overrode default port */
+		rc = (*csocket)->ops->connect(*csocket,
+				(struct sockaddr *) psin_server,
+				sizeof (struct sockaddr_in),0);
+		if (rc >= 0) {
+			return rc;
+		}
+	}
+
+	/* do not retry on the same port we just failed on */
+	if(psin_server->sin_port != htons(CIFS_PORT)) {
+		psin_server->sin_port = htons(CIFS_PORT);
 
-	rc = (*csocket)->ops->connect(*csocket,
+		rc = (*csocket)->ops->connect(*csocket,
 					(struct sockaddr *) psin_server,
 					sizeof (struct sockaddr_in),0);
+	}
 	if (rc < 0) {
 		psin_server->sin_port = htons(RFC1001_PORT);
 		rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
@@ -703,13 +737,24 @@
 	}
 
 	psin_server->sin6_family = AF_INET6;
-	psin_server->sin6_port = htons(CIFS_PORT);
+	if(psin_server->sin6_port) { /* user overrode default port */
+		rc = (*csocket)->ops->connect(*csocket,
+				(struct sockaddr *) psin_server,
+				sizeof (struct sockaddr_in6),0);
+		if (rc >= 0) {
+			return rc;
+		}
+	}
 
-	rc = (*csocket)->ops->connect(*csocket,
-				      (struct sockaddr *) psin_server,
-				      sizeof (struct sockaddr_in6), 0
-/* BB fix the timeout to be shorter - and check flags */
-	    );
+	/* do not retry on the same port we just failed on */
+	if(psin_server->sin6_port != htons(CIFS_PORT)) {
+		psin_server->sin6_port = htons(CIFS_PORT);
+
+		rc = (*csocket)->ops->connect(*csocket,
+				(struct sockaddr *) psin_server,
+				sizeof (struct sockaddr_in6), 0);
+/* BB fix the timeout to be shorter above - and check flags */
+	}
 	if (rc < 0) {
 		psin_server->sin6_port = htons(RFC1001_PORT);
 		rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
@@ -744,7 +789,7 @@
 	struct TCP_Server_Info *srvTcp = NULL;
 
 	xid = GetXid();
-	cFYI(0, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data));
+	cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data));
 
 	if(parse_mount_options(mount_data, devname, &volume_info)) {
 		FreeXid(xid);
@@ -778,7 +823,9 @@
 			     volume_info.username, &srvTcp);
 	if (srvTcp) {
 		cFYI(1, ("Existing tcp session with server found "));                
-	} else {		/* create socket */
+	} else {	/* create socket */
+		if(volume_info.port)
+			sin_server.sin_port = htons(volume_info.port);
 		rc = ipv4_connect(&sin_server, &csocket);
 		if (rc < 0) {
 			cERROR(1,
@@ -839,9 +886,23 @@
 				atomic_inc(&srvTcp->socketUseCount);
 		}
 	}
-
+    
 	/* search for existing tcon to this server share */
 	if (!rc) {
+		if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
+			cifs_sb->rsize = volume_info.rsize;
+		else
+			cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
+		if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
+			cifs_sb->wsize = volume_info.wsize;
+		else
+			cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
+		if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
+			cifs_sb->rsize = PAGE_CACHE_SIZE;
+			cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
+		}
+
+
 		tcon =
 		    find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
 			     volume_info.username);
@@ -944,7 +1005,7 @@
 	if (smb_buffer == 0) {
 		return -ENOMEM;
 	}
-    smb_buffer_response = smb_buffer;
+	smb_buffer_response = smb_buffer;
 	pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
 
 	/* send SMBsessionSetup here */
diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c
--- a/fs/cifs/file.c	Sun Feb 23 14:23:54 2003
+++ b/fs/cifs/file.c	Fri Mar  7 15:01:07 2003
@@ -393,7 +393,7 @@
 {
 	struct address_space *mapping = page->mapping;
 	loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
-	char * write_data = kmap(page);
+	char * write_data;
 	int rc = -EFAULT;
 	int bytes_written = 0;
 	struct cifs_sb_info *cifs_sb;
@@ -411,8 +411,9 @@
 
 	/* figure out which file struct to use 
 	if (file->private_data == NULL) {
-	   FreeXid(xid);
-	   return -EBADF;
+		kunmap(page);
+		FreeXid(xid);
+		return -EBADF;
 	}     
 	 */
 	if (!mapping) {
@@ -424,15 +425,17 @@
 	}
 
 	offset += (loff_t)from;
+	write_data = kmap(page);
 	write_data += from;
 
 	if((to > PAGE_CACHE_SIZE) || (from > to) || (offset > mapping->host->i_size)) {
+		kunmap(page);
 		FreeXid(xid);
 		return -EIO;
 	}
 
 	/* check to make sure that we are not extending the file */
-    if(mapping->host->i_size - offset < (loff_t)to)
+	if(mapping->host->i_size - offset < (loff_t)to)
 		to = (unsigned)(mapping->host->i_size - offset); 
 		
 
@@ -459,6 +462,7 @@
 		rc = -EIO;
 	}
 
+	kunmap(page);
 	FreeXid(xid);
 	return rc;
 }
@@ -604,6 +608,7 @@
 	int rc = -EACCES;
 	int bytes_read = 0;
 	int total_read;
+	int current_read_size;
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *pTcon;
 	int xid;
@@ -620,10 +625,11 @@
 
 	for (total_read = 0,current_offset=read_data; read_size > total_read;
 				total_read += bytes_read,current_offset+=bytes_read) {
+		current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
 		rc = CIFSSMBRead(xid, pTcon,
 				 ((struct cifsFileInfo *) file->
 				  private_data)->netfid,
-				 read_size - total_read, *poffset,
+				 current_read_size, *poffset,
 				 &bytes_read, &current_offset);
 		if (rc || (bytes_read == 0)) {
 			if (total_read) {
@@ -740,6 +746,8 @@
 			num_pages-i, (unsigned long) offset)); 
 		
 		read_size = (num_pages - i) * PAGE_CACHE_SIZE;
+		/* Read size needs to be in multiples of one page */
+		read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
 		rc = CIFSSMBRead(xid, pTcon,
 			((struct cifsFileInfo *) file->
 			 private_data)->netfid,
@@ -1061,11 +1069,11 @@
 
 	xid = GetXid();
 
-	data = kmalloc(4096, GFP_KERNEL);
-	pfindData = (FILE_DIRECTORY_INFO *) data;
-
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
 	pTcon = cifs_sb->tcon;
+	data = kmalloc(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE,
+			GFP_KERNEL);
+	pfindData = (FILE_DIRECTORY_INFO *) data;
 
 	full_path = build_wildcard_path_from_dentry(file->f_dentry);
 
diff -Nru a/fs/cifs/misc.c b/fs/cifs/misc.c
--- a/fs/cifs/misc.c	Tue Feb 18 19:15:11 2003
+++ b/fs/cifs/misc.c	Fri Mar  7 15:01:07 2003
@@ -153,7 +153,8 @@
 
 /* We could use negotiated size instead of max_msgsize - 
    but it may be more efficient to always alloc same size 
-   albeit slightly larger */
+   albeit slightly larger than necessary and maxbuffersize 
+   defaults to this and can not be bigger */
 	ret_buf =
 	    (struct smb_hdr *) kmem_cache_alloc(cifs_req_cachep, SLAB_KERNEL);
 
diff -Nru a/fs/cifs/transport.c b/fs/cifs/transport.c
--- a/fs/cifs/transport.c	Tue Feb 18 19:15:11 2003
+++ b/fs/cifs/transport.c	Fri Mar  7 15:01:07 2003
@@ -159,7 +159,7 @@
 	midQ = AllocMidQEntry(in_buf, ses);
 	if (midQ == NULL)
 		return -EIO;
-	if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
+	if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4) {
 		cERROR(1,
 		       ("Illegal length, greater than maximum frame, %d ",
 			in_buf->smb_buf_length));
diff -Nru a/fs/devfs/base.c b/fs/devfs/base.c
--- a/fs/devfs/base.c	Tue Feb 25 10:47:06 2003
+++ b/fs/devfs/base.c	Mon Mar 10 12:22:35 2003
@@ -729,7 +729,6 @@
 
 #define OPTION_NONE             0x00
 #define OPTION_MOUNT            0x01
-#define OPTION_ONLY             0x02
 
 #define PRINTK(format, args...) \
    {printk (KERN_ERR "%s" format, __FUNCTION__ , ## args);}
@@ -773,7 +772,6 @@
 {
     struct block_device_operations *ops;
     dev_t dev;
-    unsigned char autogen:1;
     unsigned char removable:1;
 };
 
@@ -938,8 +936,6 @@
     if ( S_ISLNK (de->mode) ) kfree (de->u.symlink.linkname);
     if ( S_ISCHR (de->mode) && de->u.cdev.autogen )
 	devfs_dealloc_devnum (de->mode, de->u.cdev.dev);
-    if ( S_ISBLK (de->mode) && de->u.bdev.autogen )
-	devfs_dealloc_devnum (de->mode, de->u.bdev.dev);
     WRITE_ENTRY_MAGIC (de, 0);
 #ifdef CONFIG_DEVFS_DEBUG
     spin_lock (&stat_lock);
@@ -1495,17 +1491,6 @@
 	PRINTK ("(%s): creating symlinks is not allowed\n", name);
 	return NULL;
     }
-    if ( ( S_ISCHR (mode) || S_ISBLK (mode) ) &&
-	 (flags & DEVFS_FL_AUTO_DEVNUM) )
-    {
-	devnum = devfs_alloc_devnum (mode);
-	if (!devnum) {
-	    PRINTK ("(%s): exhausted %s device numbers\n",
-		    name, S_ISCHR (mode) ? "char" : "block");
-	    return NULL;
-	}
-	dev = devnum;
-    }
     if ( ( de = _devfs_prepare_leaf (&dir, name, mode) ) == NULL )
     {
 	PRINTK ("(%s): could not prepare leaf\n", name);
@@ -1870,18 +1855,6 @@
 
 
 /**
- *	devfs_only - returns true if "devfs=only" is a boot option
- *
- *	If "devfs=only" this function will return 1, otherwise 0 is returned.
- */
-
-int devfs_only (void)
-{
-    return (boot_options & OPTION_ONLY) ? 1 : 0;
-}   /*  End Function devfs_only  */
-
-
-/**
  *	devfs_setup - Process kernel boot options.
  *	@str: The boot options after the "devfs=".
  */
@@ -1909,7 +1882,6 @@
 	{"dilookup",  DEBUG_I_LOOKUP,     &devfs_debug_init},
 	{"diunlink",  DEBUG_I_UNLINK,     &devfs_debug_init},
 #endif  /*  CONFIG_DEVFS_DEBUG  */
-	{"only",      OPTION_ONLY,        &boot_options},
 	{"mount",     OPTION_MOUNT,       &boot_options},
 	{NULL,        0,                  NULL}
     };
diff -Nru a/fs/ext2/dir.c b/fs/ext2/dir.c
--- a/fs/ext2/dir.c	Sun Mar  2 18:14:28 2003
+++ b/fs/ext2/dir.c	Mon Mar 10 22:34:32 2003
@@ -337,6 +337,9 @@
 	struct ext2_inode_info *ei = EXT2_I(dir);
 	ext2_dirent * de;
 
+	if (npages == 0)
+		goto out;
+
 	/* OFFSET_CACHE */
 	*res_page = NULL;
 
diff -Nru a/fs/ext2/super.c b/fs/ext2/super.c
--- a/fs/ext2/super.c	Wed Feb  5 08:27:03 2003
+++ b/fs/ext2/super.c	Sat Mar  8 14:50:40 2003
@@ -781,7 +781,6 @@
 		if (!sbi->s_group_desc[i]) {
 			for (j = 0; j < i; j++)
 				brelse (sbi->s_group_desc[j]);
-			kfree(sbi->s_group_desc);
 			printk ("EXT2-fs: unable to read group descriptors\n");
 			goto failed_mount_group_desc;
 		}
diff -Nru a/fs/ext2/xattr.c b/fs/ext2/xattr.c
--- a/fs/ext2/xattr.c	Tue Feb 25 08:21:08 2003
+++ b/fs/ext2/xattr.c	Sat Mar  8 14:50:42 2003
@@ -731,7 +731,7 @@
 			 * The old block will be released after updating
 			 * the inode.
 			 */
-			ea_bdebug(old_bh, "reusing block %ld",
+			ea_bdebug(new_bh, "reusing block %ld",
 				new_bh->b_blocknr);
 			
 			error = -EDQUOT;
diff -Nru a/fs/ext3/dir.c b/fs/ext3/dir.c
--- a/fs/ext3/dir.c	Mon Feb 24 23:13:19 2003
+++ b/fs/ext3/dir.c	Tue Mar  4 08:34:07 2003
@@ -105,8 +105,10 @@
 
 	if (is_dx(inode)) {
 		err = ext3_dx_readdir(filp, dirent, filldir);
-		if (err != ERR_BAD_DX_DIR)
+		if (err != ERR_BAD_DX_DIR) {
+			unlock_kernel();
 			return err;
+		}
 		/*
 		 * We don't set the inode dirty flag since it's not
 		 * critical that it get flushed back to the disk.
diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c
--- a/fs/ext3/super.c	Mon Feb 10 19:42:01 2003
+++ b/fs/ext3/super.c	Mon Mar 10 22:34:32 2003
@@ -141,8 +141,11 @@
 		printk (KERN_CRIT "Remounting filesystem read-only\n");
 		sb->s_flags |= MS_RDONLY;
 	} else {
+		journal_t *journal = EXT3_SB(sb)->s_journal;
+
 		EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT;
-		journal_abort(EXT3_SB(sb)->s_journal, -EIO);
+		if (journal)
+			journal_abort(journal, -EIO);
 	}
 	ext3_commit_super(sb, es, 1);
 }
@@ -1154,7 +1157,7 @@
 		if (!bh) {
 			printk(KERN_ERR 
 			       "EXT3-fs: Can't read superblock on 2nd try.\n");
-			return -EINVAL;
+			goto failed_mount;
 		}
 		es = (struct ext3_super_block *)(((char *)bh->b_data) + offset);
 		sbi->s_es = es;
@@ -1622,11 +1625,15 @@
 			       struct ext3_super_block * es,
 			       int sync)
 {
+	struct buffer_head *sbh = EXT3_SB(sb)->s_sbh;
+
+	if (!sbh)
+		return;
 	es->s_wtime = cpu_to_le32(get_seconds());
-	BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "marking dirty");
-	mark_buffer_dirty(EXT3_SB(sb)->s_sbh);
+	BUFFER_TRACE(sbh, "marking dirty");
+	mark_buffer_dirty(sbh);
 	if (sync)
-		sync_dirty_buffer(EXT3_SB(sb)->s_sbh);
+		sync_dirty_buffer(sbh);
 }
 
 
diff -Nru a/fs/ext3/xattr.c b/fs/ext3/xattr.c
--- a/fs/ext3/xattr.c	Tue Feb 25 08:21:08 2003
+++ b/fs/ext3/xattr.c	Sat Mar  8 14:50:42 2003
@@ -732,7 +732,7 @@
 			 * The old block will be released after updating
 			 * the inode.
 			 */
-			ea_bdebug(old_bh, "reusing block %ld",
+			ea_bdebug(new_bh, "reusing block %ld",
 				new_bh->b_blocknr);
 			
 			error = -EDQUOT;
diff -Nru a/fs/file_table.c b/fs/file_table.c
--- a/fs/file_table.c	Fri Feb 21 11:46:34 2003
+++ b/fs/file_table.c	Tue Mar  4 23:49:20 2003
@@ -27,7 +27,7 @@
 /* And here the free ones sit */
 static LIST_HEAD(free_list);
 /* public *and* exported. Not pretty! */
-spinlock_t files_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t files_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 /* Find an unused file structure and return a pointer to it.
  * Returns NULL, if there are no more free file structures or
diff -Nru a/fs/filesystems.c b/fs/filesystems.c
--- a/fs/filesystems.c	Tue Mar  4 10:13:12 2003
+++ b/fs/filesystems.c	Wed Mar  5 15:38:04 2003
@@ -125,9 +125,7 @@
 	if (!res) {
 		/* we implicitly possess reference to @fs during registration,
 		 * so it cannot be unregister from under us. */
-		if (register_fs_subsys(fs))
-			printk(KERN_WARNING "Failed to register '%s' in sysfs\n",
-			       fs->name);
+		register_fs_subsys(fs);
 	}
 	return res;
 }
diff -Nru a/fs/inode.c b/fs/inode.c
--- a/fs/inode.c	Tue Mar  4 14:30:07 2003
+++ b/fs/inode.c	Thu Mar  6 08:18:38 2003
@@ -453,8 +453,13 @@
 }
 
 /*
- * This is called from kswapd when we think we need some
- * more memory. 
+ * shrink_icache_memory() will attempt to reclaim some unused inodes.  Here,
+ * "unused" means that no dentries are referring to the inodes: the files are
+ * not open and the dcache references to those inodes have already been
+ * reclaimed.
+ *
+ * This function is passed the number of inodes to scan, and it returns the
+ * total number of remaining possibly-reclaimable inodes.
  */
 static int shrink_icache_memory(int nr, unsigned int gfp_mask)
 {
@@ -467,7 +472,7 @@
 		if (gfp_mask & __GFP_FS)
 			prune_icache(nr);
 	}
-	return inodes_stat.nr_inodes;
+	return inodes_stat.nr_unused;
 }
 
 /*
diff -Nru a/fs/intermezzo/cache.c b/fs/intermezzo/cache.c
--- a/fs/intermezzo/cache.c	Fri Dec 13 17:27:18 2002
+++ b/fs/intermezzo/cache.c	Sun Feb 16 16:14:54 2003
@@ -22,7 +22,6 @@
 
 #define __NO_VERSION__
 #include <linux/module.h>
-#include <stdarg.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff -Nru a/fs/intermezzo/dir.c b/fs/intermezzo/dir.c
--- a/fs/intermezzo/dir.c	Fri Dec 13 17:27:18 2002
+++ b/fs/intermezzo/dir.c	Sun Feb 16 16:14:54 2003
@@ -22,8 +22,6 @@
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <stdarg.h>
-
 #include <asm/bitops.h>
 #include <asm/ioctls.h>
 #include <asm/uaccess.h>
diff -Nru a/fs/intermezzo/file.c b/fs/intermezzo/file.c
--- a/fs/intermezzo/file.c	Fri Dec 13 17:27:18 2002
+++ b/fs/intermezzo/file.c	Sun Feb 16 16:14:54 2003
@@ -29,8 +29,6 @@
  * 
  */
 
-#include <stdarg.h>
-
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff -Nru a/fs/intermezzo/fileset.c b/fs/intermezzo/fileset.c
--- a/fs/intermezzo/fileset.c	Fri Dec 13 17:27:18 2002
+++ b/fs/intermezzo/fileset.c	Sun Feb 16 16:14:54 2003
@@ -23,7 +23,6 @@
  */
 
 #define __NO_VERSION__
-#include <stdarg.h>
 
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
diff -Nru a/fs/intermezzo/intermezzo_lib.h b/fs/intermezzo/intermezzo_lib.h
--- a/fs/intermezzo/intermezzo_lib.h	Fri Dec 13 17:17:29 2002
+++ b/fs/intermezzo/intermezzo_lib.h	Sun Feb 16 16:14:54 2003
@@ -32,12 +32,6 @@
 # include <sys/types.h>
 #endif
 
-#undef MIN
-#define MIN(a,b) (((a)<(b)) ? (a): (b))
-#undef MAX
-#define MAX(a,b) (((a)>(b)) ? (a): (b))
-#define MKSTR(ptr) ((ptr))? (ptr) : ""
-
 static inline int size_round (int val)
 {
 	return (val + 3) & (~0x3);
diff -Nru a/fs/intermezzo/methods.c b/fs/intermezzo/methods.c
--- a/fs/intermezzo/methods.c	Fri Dec 13 17:27:19 2002
+++ b/fs/intermezzo/methods.c	Sun Feb 16 16:14:54 2003
@@ -25,8 +25,6 @@
  *
  */
 
-#include <stdarg.h>
-
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff -Nru a/fs/intermezzo/replicator.c b/fs/intermezzo/replicator.c
--- a/fs/intermezzo/replicator.c	Fri Dec 13 17:27:19 2002
+++ b/fs/intermezzo/replicator.c	Sun Feb 16 16:14:54 2003
@@ -25,7 +25,6 @@
 
 #define __NO_VERSION__
 #include <linux/module.h>
-#include <stdarg.h>
 #include <asm/uaccess.h>
 
 #include <linux/errno.h>
diff -Nru a/fs/intermezzo/super.c b/fs/intermezzo/super.c
--- a/fs/intermezzo/super.c	Sun Mar  2 18:13:30 2003
+++ b/fs/intermezzo/super.c	Thu Mar  6 09:33:04 2003
@@ -26,8 +26,6 @@
 static char rcsid[] __attribute ((unused)) = "$Id: super.c,v 1.4 2002/10/12 02:16:19 rread Exp $";
 #define INTERMEZZO_VERSION "$Revision: 1.4 $"
 
-#include <stdarg.h>
-
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff -Nru a/fs/locks.c b/fs/locks.c
--- a/fs/locks.c	Thu Feb 13 09:25:01 2003
+++ b/fs/locks.c	Mon Mar 10 12:09:00 2003
@@ -107,22 +107,22 @@
  *  Use slab allocator instead of kmalloc/kfree.
  *  Use generic list implementation from <linux/list.h>.
  *  Sped up posix_locks_deadlock by only considering blocked locks.
- *  Matthew Wilcox <willy@thepuffingroup.com>, March, 2000.
+ *  Matthew Wilcox <willy@debian.org>, March, 2000.
  *
  *  Leases and LOCK_MAND
- *  Matthew Wilcox <willy@linuxcare.com>, June, 2000.
+ *  Matthew Wilcox <willy@debian.org>, June, 2000.
  *  Stephen Rothwell <sfr@canb.auug.org.au>, June, 2000.
  */
 
-#include <linux/slab.h>
-#include <linux/file.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
 #include <linux/capability.h>
-#include <linux/timer.h>
-#include <linux/time.h>
+#include <linux/file.h>
 #include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/security.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/time.h>
 
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
@@ -143,15 +143,9 @@
 static kmem_cache_t *filelock_cache;
 
 /* Allocate an empty lock structure. */
-static struct file_lock *locks_alloc_lock(int account)
+static struct file_lock *locks_alloc_lock(void)
 {
-	struct file_lock *fl;
-	if (account && current->locks >= current->rlim[RLIMIT_LOCKS].rlim_cur)
-		return NULL;
-	fl = kmem_cache_alloc(filelock_cache, SLAB_KERNEL);
-	if (fl)
-		current->locks++;
-	return fl;
+	return kmem_cache_alloc(filelock_cache, SLAB_KERNEL);
 }
 
 /* Free a lock which is not in use. */
@@ -161,7 +155,6 @@
 		BUG();
 		return;
 	}
-	current->locks--;
 	if (waitqueue_active(&fl->fl_wait))
 		panic("Attempting to free lock with active wait queue");
 
@@ -248,7 +241,7 @@
 	if (type < 0)
 		return type;
 	
-	fl = locks_alloc_lock(1);
+	fl = locks_alloc_lock();
 	if (fl == NULL)
 		return -ENOMEM;
 
@@ -382,7 +375,7 @@
 /* Allocate a file_lock initialised to this type of lease */
 static int lease_alloc(struct file *filp, int type, struct file_lock **flp)
 {
-	struct file_lock *fl = locks_alloc_lock(1);
+	struct file_lock *fl = locks_alloc_lock();
 	if (fl == NULL)
 		return -ENOMEM;
 
@@ -427,13 +420,22 @@
 /* Remove waiter from blocker's block list.
  * When blocker ends up pointing to itself then the list is empty.
  */
-static void locks_delete_block(struct file_lock *waiter)
+static inline void __locks_delete_block(struct file_lock *waiter)
 {
 	list_del_init(&waiter->fl_block);
 	list_del_init(&waiter->fl_link);
 	waiter->fl_next = NULL;
 }
 
+/*
+ */
+static void locks_delete_block(struct file_lock *waiter)
+{
+	lock_kernel();
+	__locks_delete_block(waiter);
+	unlock_kernel();
+}
+
 /* Insert waiter into blocker's block list.
  * We use a circular list so that processes can be easily woken up in
  * the order they blocked. The documentation doesn't require this but
@@ -446,7 +448,7 @@
 		printk(KERN_ERR "locks_insert_block: removing duplicated lock "
 			"(pid=%d %Ld-%Ld type=%d)\n", waiter->fl_pid,
 			waiter->fl_start, waiter->fl_end, waiter->fl_type);
-		locks_delete_block(waiter);
+		__locks_delete_block(waiter);
 	}
 	list_add_tail(&waiter->fl_block, &blocker->fl_block);
 	waiter->fl_next = blocker;
@@ -462,7 +464,7 @@
 	while (!list_empty(&blocker->fl_block)) {
 		struct file_lock *waiter = list_entry(blocker->fl_block.next,
 				struct file_lock, fl_block);
-		locks_delete_block(waiter);
+		__locks_delete_block(waiter);
 		if (waiter->fl_notify)
 			waiter->fl_notify(waiter);
 		else
@@ -517,19 +519,11 @@
  */
 static int locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl)
 {
-	switch (caller_fl->fl_type) {
-	case F_RDLCK:
-		return (sys_fl->fl_type == F_WRLCK);
-
-	case F_WRLCK:
-		return (1);
-
-	default:
-		printk(KERN_ERR "locks_conflict(): impossible lock type - %d\n",
-		       caller_fl->fl_type);
-		break;
-	}
-	return (0);	/* This should never happen */
+	if (sys_fl->fl_type == F_WRLCK)
+		return 1;
+	if (caller_fl->fl_type == F_WRLCK)
+		return 1;
+	return 0;
 }
 
 /* Determine if lock sys_fl blocks lock caller_fl. POSIX specific
@@ -589,7 +583,7 @@
 	int result;
 	locks_insert_block(blocker, waiter);
 	result = interruptible_sleep_on_locked(&waiter->fl_wait, time);
-	locks_delete_block(waiter);
+	__locks_delete_block(waiter);
 	return result;
 }
 
@@ -726,8 +720,8 @@
 	 * We may need two file_lock structures for this operation,
 	 * so we get them in advance to avoid races.
 	 */
-	new_fl = locks_alloc_lock(0);
-	new_fl2 = locks_alloc_lock(0);
+	new_fl = locks_alloc_lock();
+	new_fl2 = locks_alloc_lock();
 
 	lock_kernel();
 	if (request->fl_type != F_UNLCK) {
@@ -977,9 +971,7 @@
 				continue;
 		}
 
-		lock_kernel();
 		locks_delete_block(&fl);
-		unlock_kernel();
 		break;
 	}
 
@@ -1332,9 +1324,7 @@
 		if (!error)
 			continue;
 
-		lock_kernel();
 		locks_delete_block(lock);
-		unlock_kernel();
 		break;
 	}
 
@@ -1416,7 +1406,7 @@
  */
 int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock *l)
 {
-	struct file_lock *file_lock = locks_alloc_lock(0);
+	struct file_lock *file_lock = locks_alloc_lock();
 	struct flock flock;
 	struct inode *inode;
 	int error;
@@ -1489,9 +1479,7 @@
 		if (!error)
 			continue;
 
-		lock_kernel();
 		locks_delete_block(file_lock);
-		unlock_kernel();
 		break;
 	}
 
@@ -1556,7 +1544,7 @@
  */
 int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 *l)
 {
-	struct file_lock *file_lock = locks_alloc_lock(0);
+	struct file_lock *file_lock = locks_alloc_lock();
 	struct flock64 flock;
 	struct inode *inode;
 	int error;
@@ -1629,9 +1617,7 @@
 		if (!error)
 			continue;
 
-		lock_kernel();
 		locks_delete_block(file_lock);
-		unlock_kernel();
 		break;
 	}
 
@@ -1648,14 +1634,15 @@
  */
 void locks_remove_posix(struct file *filp, fl_owner_t owner)
 {
-	struct file_lock lock;
+	struct file_lock lock, **before;
 
 	/*
 	 * If there are no locks held on this file, we don't need to call
 	 * posix_lock_file().  Another process could be setting a lock on this
 	 * file at the same time, but we wouldn't remove that lock anyway.
 	 */
-	if (!filp->f_dentry->d_inode->i_flock)
+	before = &filp->f_dentry->d_inode->i_flock;
+	if (*before == NULL)
 		return;
 
 	lock.fl_type = F_UNLCK;
@@ -1671,7 +1658,19 @@
 		/* Ignore any error -- we must remove the locks anyway */
 	}
 
-	posix_lock_file(filp, &lock);
+	/* Can't use posix_lock_file here; we need to remove it no matter
+	 * which pid we have.
+	 */
+	lock_kernel();
+	while (*before != NULL) {
+		struct file_lock *fl = *before;
+		if (IS_POSIX(fl) && (fl->fl_owner == owner)) {
+			locks_delete_lock(before);
+			continue;
+		}
+		before = &fl->fl_next;
+	}
+	unlock_kernel();
 }
 
 /*
@@ -1699,6 +1698,7 @@
 				lease_modify(before, F_UNLCK);
 				continue;
 			}
+			BUG();
  		}
 		before = &fl->fl_next;
 	}
@@ -1733,7 +1733,7 @@
 	 */
 	lock_kernel();
 	if (waiter->fl_next) {
-		locks_delete_block(waiter);
+		__locks_delete_block(waiter);
 		unlock_kernel();
 	} else {
 		unlock_kernel();
@@ -1785,19 +1785,19 @@
 			       ? (fl->fl_type & F_UNLCK) ? "UNLCK" : "READ "
 			       : (fl->fl_type & F_WRLCK) ? "WRITE" : "READ ");
 	}
-#if WE_CAN_BREAK_LSLK_NOW
 	if (inode) {
+#if WE_CAN_BREAK_LSLK_NOW
 		out += sprintf(out, "%d %s:%ld ", fl->fl_pid,
 				inode->i_sb->s_id, inode->i_ino);
+#else
+		/* userspace relies on this representation of dev_t ;-( */
+		out += sprintf(out, "%d %02x:%02x:%ld ", fl->fl_pid,
+				MAJOR(inode->i_sb->s_dev),
+				MINOR(inode->i_sb->s_dev), inode->i_ino);
+#endif
 	} else {
 		out += sprintf(out, "%d <none>:0 ", fl->fl_pid);
 	}
-#else
-	/* kdevname is a broken interface.  but we expose it to userspace */
-	out += sprintf(out, "%d %s:%ld ", fl->fl_pid,
-			inode ? kdevname(to_kdev_t(inode->i_sb->s_dev)) : "<none>",
-			inode ? inode->i_ino : 0);
-#endif
 	if (IS_POSIX(fl)) {
 		if (fl->fl_end == OFFSET_MAX)
 			out += sprintf(out, "%Ld EOF\n", fl->fl_start);
@@ -1958,3 +1958,13 @@
 }
 
 module_init(filelock_init)
+
+EXPORT_SYMBOL(file_lock_list);
+EXPORT_SYMBOL(locks_init_lock);
+EXPORT_SYMBOL(locks_copy_lock);
+EXPORT_SYMBOL(posix_lock_file);
+EXPORT_SYMBOL(posix_test_lock);
+EXPORT_SYMBOL(posix_block_lock);
+EXPORT_SYMBOL(posix_unblock_lock);
+EXPORT_SYMBOL(posix_locks_deadlock);
+EXPORT_SYMBOL(locks_mandatory_area);
diff -Nru a/fs/mbcache.c b/fs/mbcache.c
--- a/fs/mbcache.c	Thu Nov 14 14:03:01 2002
+++ b/fs/mbcache.c	Sat Mar  8 14:50:42 2003
@@ -433,6 +433,7 @@
 		list_add(&ce->e_indexes[n].o_list,
 			 &cache->c_indexes_hash[n][bucket]);
 	}
+	error = 0;
 out:
 	spin_unlock(&mb_cache_spinlock);
 	return error;
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	Fri Feb 14 18:23:59 2003
+++ b/fs/namei.c	Mon Mar 10 23:39:31 2003
@@ -342,8 +342,18 @@
 	 *
 	 * FIXME! This could use version numbering or similar to
 	 * avoid unnecessary cache lookups.
+	 *
+	 * The "dcache_lock" is purely to protect the RCU list walker
+	 * from concurrent renames at this point (we mustn't get false
+	 * negatives from the RCU list walk here, unlike the optimistic
+	 * fast walk).
+	 *
+	 * We really should do a sequence number thing to avoid this
+	 * all.
 	 */
+	spin_lock(&dcache_lock);
 	result = d_lookup(parent, name);
+	spin_unlock(&dcache_lock);
 	if (!result) {
 		struct dentry * dentry = d_alloc(parent, name);
 		result = ERR_PTR(-ENOMEM);
@@ -388,10 +398,7 @@
 		goto loop;
 	if (current->total_link_count >= 40)
 		goto loop;
-	if (need_resched()) {
-		current->state = TASK_RUNNING;
-		schedule();
-	}
+	cond_resched();
 	err = security_inode_follow_link(dentry, nd);
 	if (err)
 		goto loop;
diff -Nru a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
--- a/fs/ncpfs/ioctl.c	Fri Sep 20 11:13:41 2002
+++ b/fs/ncpfs/ioctl.c	Mon Mar 10 22:34:29 2003
@@ -440,7 +440,7 @@
 			oldprivatelen = server->priv.len;
 			server->auth.auth_type = user.auth_type;
 			server->auth.object_name_len = user.object_name_len;
-			server->auth.object_name = user.object_name;
+			server->auth.object_name = newname;
 			server->priv.len = 0;
 			server->priv.data = NULL;
 			/* leave critical section */
diff -Nru a/fs/nfs/file.c b/fs/nfs/file.c
--- a/fs/nfs/file.c	Wed Dec 18 09:37:07 2002
+++ b/fs/nfs/file.c	Sat Mar  8 14:50:27 2003
@@ -35,6 +35,7 @@
 #define NFSDBG_FACILITY		NFSDBG_FILE
 
 static int  nfs_file_mmap(struct file *, struct vm_area_struct *);
+static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
 static ssize_t nfs_file_read(struct kiocb *, char *, size_t, loff_t);
 static ssize_t nfs_file_write(struct kiocb *, const char *, size_t, loff_t);
 static int  nfs_file_flush(struct file *);
@@ -52,6 +53,7 @@
 	.release	= nfs_release,
 	.fsync		= nfs_fsync,
 	.lock		= nfs_lock,
+	.sendfile	= nfs_file_sendfile,
 };
 
 struct inode_operations nfs_file_inode_operations = {
@@ -100,6 +102,24 @@
 	if (!result)
 		result = generic_file_aio_read(iocb, buf, count, pos);
 	return result;
+}
+
+static ssize_t
+nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
+		read_actor_t actor, void *target)
+{
+	struct dentry *dentry = filp->f_dentry;
+	struct inode *inode = dentry->d_inode;
+	ssize_t res;
+
+	dfprintk(VFS, "nfs: sendfile(%s/%s, %lu@%Lu)\n",
+		dentry->d_parent->d_name.name, dentry->d_name.name,
+		(unsigned long) count, (unsigned long long) *ppos);
+
+	res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	if (!res)
+		res = generic_file_sendfile(filp, ppos, count, actor, target);
+	return res;
 }
 
 static int
diff -Nru a/fs/partitions/check.c b/fs/partitions/check.c
--- a/fs/partitions/check.c	Mon Feb 10 23:22:51 2003
+++ b/fs/partitions/check.c	Sat Mar  8 14:50:30 2003
@@ -503,13 +503,7 @@
 	disk->capacity = 0;
 	disk->flags &= ~GENHD_FL_UP;
 	unlink_gendisk(disk);
-	disk->reads = disk->writes = 0;
-	disk->read_sectors = disk->write_sectors = 0;
-	disk->read_merges = disk->write_merges = 0;
-	disk->read_ticks = disk->write_ticks = 0;
-	disk->in_flight = 0;
-	disk->io_ticks = 0;
-	disk->time_in_queue = 0;
+	disk_stat_set_all(disk, 0);
 	disk->stamp = disk->stamp_idle = 0;
 	devfs_remove_partitions(disk);
 	if (disk->driverfs_dev) {
diff -Nru a/fs/partitions/ldm.c b/fs/partitions/ldm.c
--- a/fs/partitions/ldm.c	Fri Feb  7 00:20:33 2003
+++ b/fs/partitions/ldm.c	Mon Mar 10 22:34:29 2003
@@ -1162,8 +1162,10 @@
 		return FALSE;
 	}
 
-	if (!ldm_parse_vblk (data, len, vb))
+	if (!ldm_parse_vblk (data, len, vb)) {
+		kfree(vb);
 		return FALSE;			/* Already logged */
+	}
 
 	/* Put vblk into the correct list. */
 	switch (vb->type) {
diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
--- a/fs/proc/proc_misc.c	Mon Feb 24 23:13:09 2003
+++ b/fs/proc/proc_misc.c	Sat Mar  8 14:50:46 2003
@@ -389,11 +389,7 @@
 extern int show_interrupts(struct seq_file *p, void *v);
 static int interrupts_open(struct inode *inode, struct file *file)
 {
-	unsigned size = PAGE_SIZE;
-	/*
-	 * probably should depend on NR_CPUS, but that's only rough estimate;
-	 * if we'll need more it will be given,
-	 */
+	unsigned size = PAGE_SIZE * (1 + NR_CPUS / 8);
 	char *buf = kmalloc(size, GFP_KERNEL);
 	struct seq_file *m;
 	int res;
diff -Nru a/fs/readdir.c b/fs/readdir.c
--- a/fs/readdir.c	Sun Jan  5 07:28:41 2003
+++ b/fs/readdir.c	Sat Mar  8 14:50:39 2003
@@ -72,11 +72,16 @@
 		return -EINVAL;
 	buf->count++;
 	dirent = buf->dirent;
-	put_user(ino, &dirent->d_ino);
-	put_user(offset, &dirent->d_offset);
-	put_user(namlen, &dirent->d_namlen);
-	copy_to_user(dirent->d_name, name, namlen);
-	put_user(0, dirent->d_name + namlen);
+	if (!access_ok(VERIFY_WRITE, (unsigned long)dirent,
+			(unsigned long)(dirent->d_name + namlen + 1) -
+				(unsigned long)dirent))
+		return -EFAULT;
+	if (	__put_user(ino, &dirent->d_ino) ||
+		__put_user(offset, &dirent->d_offset) ||
+		__put_user(namlen, &dirent->d_namlen) ||
+		__copy_to_user(dirent->d_name, name, namlen) ||
+		__put_user(0, dirent->d_name + namlen))
+		return -EFAULT;
 	return 0;
 }
 
diff -Nru a/fs/smbfs/sock.c b/fs/smbfs/sock.c
--- a/fs/smbfs/sock.c	Sun Nov 17 12:38:34 2002
+++ b/fs/smbfs/sock.c	Thu Mar  6 11:06:44 2003
@@ -41,8 +41,6 @@
 {
 	struct iovec iov;
 	struct msghdr msg;
-	struct kiocb iocb;
-	struct sock_iocb *si;
 	mm_segment_t fs;
 
 	fs = get_fs();
@@ -58,21 +56,7 @@
 	iov.iov_base = ubuf;
 	iov.iov_len = size;
 
-	init_sync_kiocb(&iocb, NULL);
-	si = kiocb_to_siocb(&iocb);
-	si->sock = socket;
-	si->scm = &si->async_scm;
-	si->msg = &msg;
-	si->size = size;
-	si->flags = flags;
-
-	memset(si->scm, 0, sizeof(*si->scm));
-
-	size = socket->ops->recvmsg(&iocb, socket, &msg, size, flags, si->scm);
-	if (size >= 0)
-		scm_recv(socket, &msg, si->scm, flags);
-	if (-EIOCBQUEUED == size)
-		size = wait_on_sync_kiocb(&iocb);
+	size = sock_recvmsg(socket, &msg, size, flags);
 
 	set_fs(fs);
 	return size;
@@ -299,8 +283,6 @@
 	unsigned int flags;
 	struct iovec iov;
 	struct msghdr msg;
-	struct kiocb iocb;
-	struct sock_iocb *si;
 	mm_segment_t fs;
 	int rlen = smb_len(server->header) - server->smb_read + 4;
 	int result = -EIO;
@@ -327,21 +309,7 @@
 	if (rlen > PAGE_SIZE)
 		rlen = PAGE_SIZE;
 
-	init_sync_kiocb(&iocb, NULL);
-	si = kiocb_to_siocb(&iocb);
-	si->sock = sock;
-	si->scm = &si->async_scm;
-	si->msg = &msg;
-	si->size = rlen;
-	si->flags = flags;
-
-	memset(si->scm, 0, sizeof(*si->scm));
-
-	result = sock->ops->recvmsg(&iocb, sock, &msg, rlen, flags, si->scm);
-	if (result >= 0)
-		scm_recv(sock, &msg, si->scm, flags);
-	if (-EIOCBQUEUED == result)
-		result = wait_on_sync_kiocb(&iocb);
+	result = sock_recvmsg(sock, &msg, rlen, flags);
 
 	set_fs(fs);
 
@@ -370,8 +338,6 @@
 	unsigned int flags;
 	struct iovec iov[4];
 	struct msghdr msg;
-	struct kiocb iocb;
-	struct sock_iocb *si;
 	mm_segment_t fs;
 	int rlen;
 	int result = -EIO;
@@ -398,21 +364,7 @@
 	if (req->rq_rlen < rlen)
 		rlen = req->rq_rlen;
 
-	init_sync_kiocb(&iocb, NULL);
-	si = kiocb_to_siocb(&iocb);
-	si->sock = sock;
-	si->scm = &si->async_scm;
-	si->msg = &msg;
-	si->size = rlen;
-	si->flags = flags;
-
-	memset(si->scm, 0, sizeof(*si->scm));
-
-	result = sock->ops->recvmsg(&iocb, sock, &msg, rlen, flags, si->scm);
-	if (result >= 0)
-		scm_recv(sock, &msg, si->scm, flags);
-	if (-EIOCBQUEUED == result)
-		result = wait_on_sync_kiocb(&iocb);
+	result = sock_recvmsg(sock, &msg, rlen, flags);
 
 	set_fs(fs);
 
@@ -440,8 +392,6 @@
 	mm_segment_t fs;
 	struct smb_sb_info *server = req->rq_server;
 	struct socket *sock;
-	struct kiocb iocb;
-	struct sock_iocb *si;
 	struct msghdr msg;
         int slen = req->rq_slen - req->rq_bytes_sent;
 	int result = -EIO;
@@ -465,23 +415,9 @@
 	if (req->rq_bytes_sent)
 		smb_move_iov(&msg, iov, req->rq_bytes_sent);
 
-	init_sync_kiocb(&iocb, NULL);
-	si = kiocb_to_siocb(&iocb);
-	si->scm = &si->async_scm;
-	si->sock = sock;
-	si->msg = &msg;
-	si->size = slen;
-
 	fs = get_fs();
 	set_fs(get_ds());
-	result = scm_send(sock, &msg, si->scm);
-	if (result >= 0) {
-		result = sock->ops->sendmsg(&iocb, sock, &msg, slen, si->scm);
-		if (-EIOCBQUEUED != result)
-			scm_destroy(si->scm);
-	}
-	if (-EIOCBQUEUED == result)
-		result = wait_on_sync_kiocb(&iocb);
+	result = sock_sendmsg(sock, &msg, slen);
 	set_fs(fs);
 
 	if (result >= 0) {
diff -Nru a/fs/sysfs/bin.c b/fs/sysfs/bin.c
--- a/fs/sysfs/bin.c	Tue Mar  4 06:57:37 2003
+++ b/fs/sysfs/bin.c	Thu Mar  6 18:21:39 2003
@@ -50,6 +50,10 @@
 		ret = count;
 	}
  Done:
+	if (buffer && buffer->data) {
+		kfree(buffer->data);
+		buffer->data = NULL;
+	}
 	return ret;
 }
 
@@ -66,7 +70,7 @@
 static int fill_write(struct file * file, const char * userbuf, 
 		      struct sysfs_bin_buffer * buffer)
 {
-	return copy_from_user(buffer,userbuf,buffer->count) ?
+	return copy_from_user(buffer->data,userbuf,buffer->count) ?
 		-EFAULT : 0;
 }
 
diff -Nru a/fs/sysfs/dir.c b/fs/sysfs/dir.c
--- a/fs/sysfs/dir.c	Thu Jan 30 15:10:06 2003
+++ b/fs/sysfs/dir.c	Sat Mar  8 21:42:32 2003
@@ -71,7 +71,7 @@
 
 void sysfs_remove_dir(struct kobject * kobj)
 {
-	struct list_head * node, * next;
+	struct list_head * node;
 	struct dentry * dentry = dget(kobj->dentry);
 	struct dentry * parent;
 
@@ -83,33 +83,30 @@
 	down(&parent->d_inode->i_sem);
 	down(&dentry->d_inode->i_sem);
 
-	list_for_each_safe(node,next,&dentry->d_subdirs) {
-		struct dentry * d = dget(list_entry(node,struct dentry,d_child));
-		/** 
-		 * Make sure dentry is still there 
-		 */
-		pr_debug(" o %s: ",d->d_name.name);
-		if (d->d_inode) {
+	spin_lock(&dcache_lock);
+	node = dentry->d_subdirs.next;
+	while (node != &dentry->d_subdirs) {
+		struct dentry * d = list_entry(node,struct dentry,d_child);
+		list_del_init(node);
 
+		pr_debug(" o %s (%d): ",d->d_name.name,atomic_read(&d->d_count));
+		if (d->d_inode) {
+			d = dget_locked(d);
 			pr_debug("removing");
+
 			/**
 			 * Unlink and unhash.
 			 */
-			simple_unlink(dentry->d_inode,d);
+			spin_unlock(&dcache_lock);
 			d_delete(d);
-
-			/**
-			 * Drop reference from initial sysfs_get_dentry().
-			 */
+			simple_unlink(dentry->d_inode,d);
 			dput(d);
+			spin_lock(&dcache_lock);
 		}
-		pr_debug(" done (%d)\n",atomic_read(&d->d_count));
-		/**
-		 * drop reference from dget() above.
-		 */
-		dput(d);
+		pr_debug(" done\n");
+		node = dentry->d_subdirs.next;
 	}
-
+	spin_unlock(&dcache_lock);
 	up(&dentry->d_inode->i_sem);
 	d_invalidate(dentry);
 	simple_rmdir(parent->d_inode,dentry);
diff -Nru a/fs/sysfs/mount.c b/fs/sysfs/mount.c
--- a/fs/sysfs/mount.c	Tue Mar  4 10:17:14 2003
+++ b/fs/sysfs/mount.c	Wed Mar  5 15:26:59 2003
@@ -33,7 +33,7 @@
 	sb->s_op = &sysfs_ops;
 	sysfs_sb = sb;
 
-	inode = sysfs_new_inode(S_IFDIR | S_IRUGO | S_IWUSR);
+	inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
 	if (inode) {
 		inode->i_op = &simple_dir_inode_operations;
 		inode->i_fop = &simple_dir_operations;
diff -Nru a/include/asm-alpha/core_cia.h b/include/asm-alpha/core_cia.h
--- a/include/asm-alpha/core_cia.h	Sun Dec  8 03:50:30 2002
+++ b/include/asm-alpha/core_cia.h	Sun Feb 16 16:35:48 2003
@@ -293,7 +293,7 @@
 #ifdef __KERNEL__
 
 #ifndef __EXTERN_INLINE
-#define __EXTERN_INLINE extern inline
+#define __EXTERN_INLINE static inline
 #define __IO_EXTERN_INLINE
 #endif
 
diff -Nru a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
--- a/include/asm-alpha/pgtable.h	Mon Dec 30 07:03:59 2002
+++ b/include/asm-alpha/pgtable.h	Thu Mar  6 08:19:03 2003
@@ -273,7 +273,6 @@
 
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address)	((address >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
-#define __pgd_offset(address)	pgd_index(address)
 #define pgd_offset(mm, address)	((mm)->pgd+pgd_index(address))
 
 /* Find an entry in the second-level page table.. */
diff -Nru a/include/asm-alpha/processor.h b/include/asm-alpha/processor.h
--- a/include/asm-alpha/processor.h	Thu Nov 21 10:03:05 2002
+++ b/include/asm-alpha/processor.h	Mon Mar 10 10:20:30 2003
@@ -51,6 +51,9 @@
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 /* Create a kernel thread without removing it from tasklists.  */
 extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
 
diff -Nru a/include/asm-arm/arch-anakin/time.h b/include/asm-arm/arch-anakin/time.h
--- a/include/asm-arm/arch-anakin/time.h	Mon Feb 25 11:43:22 2002
+++ b/include/asm-arm/arch-anakin/time.h	Thu Mar  6 05:40:54 2003
@@ -23,7 +23,6 @@
 void __init time_init(void)
 {
 	timer_irq.handler = anakin_timer_interrupt;
-	timer_irq.flags = SA_INTERRUPT;
 	setup_irq(IRQ_TICK, &timer_irq);
 }
 
diff -Nru a/include/asm-arm/arch-sa1100/time.h b/include/asm-arm/arch-sa1100/time.h
--- a/include/asm-arm/arch-sa1100/time.h	Sat Feb 15 11:11:56 2003
+++ b/include/asm-arm/arch-sa1100/time.h	Thu Mar  6 05:40:54 2003
@@ -75,15 +75,12 @@
 static void sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned int next_match;
-	unsigned long flags;
 
 	do {
 		do_leds();
-		local_irq_save(flags);
 		do_timer(regs);
 		OSSR = OSSR_M0;  /* Clear match on timer 0 */
 		next_match = (OSMR0 += LATCH);
-		local_irq_restore(flags);
 		do_set_rtc();
 	} while ((signed long)(next_match - OSCR) <= 0);
 
diff -Nru a/include/asm-arm/arch-shark/time.h b/include/asm-arm/arch-shark/time.h
--- a/include/asm-arm/arch-shark/time.h	Mon Feb 25 15:24:09 2002
+++ b/include/asm-arm/arch-shark/time.h	Thu Mar  6 05:40:55 2003
@@ -34,6 +34,5 @@
 	xtime.tv_sec = 0;
 
 	timer_irq.handler = timer_interrupt;
-	timer_irq.flags = SA_INTERRUPT; /* FIXME: really? */
 	setup_irq(IRQ_TIMER, &timer_irq);
 }
diff -Nru a/include/asm-arm/ecard.h b/include/asm-arm/ecard.h
--- a/include/asm-arm/ecard.h	Sun Jan 26 06:44:21 2003
+++ b/include/asm-arm/ecard.h	Thu Mar  6 05:14:05 2003
@@ -267,6 +267,7 @@
 struct ecard_driver {
 	int			(*probe)(struct expansion_card *, const struct ecard_id *id);
 	void			(*remove)(struct expansion_card *);
+	void			(*shutdown)(struct expansion_card *);
 	const struct ecard_id	*id_table;
 	unsigned int		id;
 	struct device_driver	drv;
diff -Nru a/include/asm-arm/ide.h b/include/asm-arm/ide.h
--- a/include/asm-arm/ide.h	Tue Jan 14 15:31:20 2003
+++ b/include/asm-arm/ide.h	Thu Mar  6 06:43:42 2003
@@ -26,16 +26,10 @@
 #define ide_default_io_base(i)		((ide_ioreg_t)0)
 #define ide_default_irq(b)		(0)
 
-#define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
-#define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
-#define ide_check_region(from,extent)		check_region((from), (extent))
-#define ide_request_region(from,extent,name)	request_region((from), (extent), (name))
-#define ide_release_region(from,extent)		release_region((from), (extent))
-
-/*
- * The following are not needed for the non-m68k ports
- */
-#define ide_ack_intr(hwif)		(1)
+#define __ide_mm_insw(port,addr,len)	readsw(port,addr,len)
+#define __ide_mm_insl(port,addr,len)	readsl(port,addr,len)
+#define __ide_mm_outsw(port,addr,len)	writesw(port,addr,len)
+#define __ide_mm_outsl(port,addr,len)	writesl(port,addr,len)
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/asm-arm/pci.h b/include/asm-arm/pci.h
--- a/include/asm-arm/pci.h	Fri Jan 10 13:40:12 2003
+++ b/include/asm-arm/pci.h	Thu Mar  6 06:02:22 2003
@@ -131,7 +131,10 @@
 /*
  * Return the index of the PCI controller for device PDEV.
  */
-#define pci_controller_num(PDEV)	(0)
+static inline int pci_controller_num(struct pci_dev *dev)
+{
+	return 0;
+}
 
 
 #if defined(CONFIG_SA1111) && !defined(CONFIG_PCI)
diff -Nru a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
--- a/include/asm-arm/pgtable.h	Sun Oct 13 03:46:44 2002
+++ b/include/asm-arm/pgtable.h	Thu Mar  6 08:19:03 2003
@@ -110,13 +110,13 @@
 #define pgd_bad(pgd)		(0)
 #define pgd_present(pgd)	(1)
 #define pgd_clear(pgdp)		do { } while (0)
+#define set_pgd(pgd,pgdp)	do { } while (0)
 
 #define page_pte_prot(page,prot)	mk_pte(page, prot)
 #define page_pte(page)		mk_pte(page, __pgprot(0))
 
 /* to find an entry in a page-table-directory */
 #define pgd_index(addr)		((addr) >> PGDIR_SHIFT)
-#define __pgd_offset(addr)	pgd_index(addr)
 
 #define pgd_offset(mm, addr)	((mm)->pgd+pgd_index(addr))
 
diff -Nru a/include/asm-arm/posix_types.h b/include/asm-arm/posix_types.h
--- a/include/asm-arm/posix_types.h	Tue Feb  5 09:39:52 2002
+++ b/include/asm-arm/posix_types.h	Thu Mar  6 05:53:11 2003
@@ -34,6 +34,8 @@
 typedef long			__kernel_time_t;
 typedef long			__kernel_suseconds_t;
 typedef long			__kernel_clock_t;
+typedef int			__kernel_timer_t;
+typedef int			__kernel_clockid_t;
 typedef int			__kernel_daddr_t;
 typedef char *			__kernel_caddr_t;
 typedef unsigned short		__kernel_uid16_t;
diff -Nru a/include/asm-arm/proc-armv/tlbflush.h b/include/asm-arm/proc-armv/tlbflush.h
--- a/include/asm-arm/proc-armv/tlbflush.h	Sun Oct 13 03:46:44 2002
+++ b/include/asm-arm/proc-armv/tlbflush.h	Thu Mar  6 06:52:18 2003
@@ -1,7 +1,7 @@
 /*
  *  linux/include/asm-arm/proc-armv/tlbflush.h
  *
- *  Copyright (C) 1999-2002 Russell King
+ *  Copyright (C) 1999-2003 Russell King
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -38,21 +38,31 @@
 #define v3_tlb_flags	(TLB_V3_FULL | TLB_V3_PAGE)
 
 #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
+# define v3_possible_flags	v3_tlb_flags
+# define v3_always_flags	v3_tlb_flags
 # ifdef _TLB
 #  define MULTI_TLB 1
 # else
 #  define _TLB v3
 # endif
+#else
+# define v3_possible_flags	0
+# define v3_always_flags	(-1UL)
 #endif
 
 #define v4_tlb_flags	(TLB_V4_U_FULL | TLB_V4_U_PAGE)
 
 #if defined(CONFIG_CPU_ARM720T)
+# define v4_possible_flags	v4_tlb_flags
+# define v4_always_flags	v4_tlb_flags
 # ifdef _TLB
 #  define MULTI_TLB 1
 # else
 #  define _TLB v4
 # endif
+#else
+# define v4_possible_flags	0
+# define v4_always_flags	(-1UL)
 #endif
 
 #define v4wbi_tlb_flags	(TLB_WB | \
@@ -62,11 +72,16 @@
 #if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
     defined(CONFIG_CPU_ARM926T) || defined(CONFIG_CPU_ARM1020) || \
     defined(CONFIG_CPU_XSCALE)
+# define v4wbi_possible_flags	v4wbi_tlb_flags
+# define v4wbi_always_flags	v4wbi_tlb_flags
 # ifdef _TLB
 #  define MULTI_TLB 1
 # else
 #  define _TLB v4wbi
 # endif
+#else
+# define v4wbi_possible_flags	0
+# define v4wbi_always_flags	(-1UL)
 #endif
 
 #define v4wb_tlb_flags	(TLB_WB | \
@@ -74,11 +89,16 @@
 			 TLB_V4_D_PAGE)
 
 #if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100)
+# define v4wb_possible_flags	v4wb_tlb_flags
+# define v4wb_always_flags	v4wb_tlb_flags
 # ifdef _TLB
 #  define MULTI_TLB 1
 # else
 #  define _TLB v4wb
 # endif
+#else
+# define v4wb_possible_flags	0
+# define v4wb_always_flags	(-1UL)
 #endif
 
 #ifndef _TLB
@@ -98,23 +118,23 @@
  */
 #ifdef MULTI_TLB
 
-extern struct cpu_tlb_fns cpu_tlb;
-
 #define __cpu_flush_user_tlb_range	cpu_tlb.flush_user_range
 #define __cpu_flush_kern_tlb_range	cpu_tlb.flush_kern_range
-#define __cpu_tlb_flags			cpu_tlb.tlb_flags
 
 #else
 
 #define __cpu_flush_user_tlb_range	__glue(_TLB,_flush_user_tlb_range)
 #define __cpu_flush_kern_tlb_range	__glue(_TLB,_flush_kern_tlb_range)
-#define __cpu_tlb_flags			__glue(_TLB,_tlb_flags)
 
 extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *);
 extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long);
 
 #endif
 
+extern struct cpu_tlb_fns cpu_tlb;
+
+#define __cpu_tlb_flags			cpu_tlb.tlb_flags
+
 /*
  *	TLB Management
  *	==============
@@ -158,11 +178,34 @@
  *		- kaddr - Kernel virtual memory address
  */
 
-#define tlb_flag(f)	(__cpu_tlb_flags & (f))
+/*
+ * We optimise the code below by:
+ *  - building a set of TLB flags that might be set in __cpu_tlb_flags
+ *  - building a set of TLB flags that will always be set in __cpu_tlb_flags
+ *  - if we're going to need __cpu_tlb_flags, access it once and only once
+ *
+ * This allows us to build optimal assembly for the single-CPU type case,
+ * and as close to optimal given the compiler constrants for multi-CPU
+ * case.  We could do better for the multi-CPU case if the compiler
+ * implemented the "%?" method, but this has been discontinued due to too
+ * many people getting it wrong.
+ */
+#define possible_tlb_flags	(v3_possible_flags | \
+				 v4_possible_flags | \
+				 v4wbi_possible_flags | \
+				 v4wb_possible_flags)
+
+#define always_tlb_flags	(v3_always_flags & \
+				 v4_always_flags & \
+				 v4wbi_always_flags & \
+				 v4wb_always_flags)
+
+#define tlb_flag(f)	((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f)))
 
 static inline void flush_tlb_all(void)
 {
 	const int zero = 0;
+	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	if (tlb_flag(TLB_WB))
 		asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
@@ -180,6 +223,7 @@
 static inline void flush_tlb_mm(struct mm_struct *mm)
 {
 	const int zero = 0;
+	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	if (tlb_flag(TLB_WB))
 		asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
@@ -200,6 +244,7 @@
 flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
 {
 	const int zero = 0;
+	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	uaddr &= PAGE_MASK;
 
@@ -223,6 +268,7 @@
 static inline void flush_tlb_kernel_page(unsigned long kaddr)
 {
 	const int zero = 0;
+	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	kaddr &= PAGE_MASK;
 
@@ -240,6 +286,10 @@
 	if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
 		asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
 }
+
+#undef tlb_flag
+#undef always_tlb_flags
+#undef possible_tlb_flags
 
 /*
  * Convert calls to our calling convention.
diff -Nru a/include/asm-arm/proc-fns.h b/include/asm-arm/proc-fns.h
--- a/include/asm-arm/proc-fns.h	Tue Feb 25 02:23:37 2003
+++ b/include/asm-arm/proc-fns.h	Thu Mar  6 06:06:19 2003
@@ -122,15 +122,4 @@
 #include CPU_INCLUDE_NAME
 
 #endif /* __KERNEL__ */
-
-#if 0
- * The following is to fool mkdep into generating the correct
- * dependencies.  Without this, it can't figure out that this
- * file does indeed depend on the cpu-*.h files.
-#include <asm/cpu-single.h>
-#include <asm/cpu-multi26.h>
-#include <asm/cpu-multi32.h>
- *
-#endif
-
 #endif /* __ASM_PROCFNS_H */
diff -Nru a/include/asm-arm/processor.h b/include/asm-arm/processor.h
--- a/include/asm-arm/processor.h	Mon Nov  4 02:28:26 2002
+++ b/include/asm-arm/processor.h	Mon Mar 10 10:20:30 2003
@@ -62,6 +62,9 @@
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 unsigned long get_wchan(struct task_struct *p);
 
 #define cpu_relax()			barrier()
diff -Nru a/include/asm-arm/system.h b/include/asm-arm/system.h
--- a/include/asm-arm/system.h	Wed Oct 30 03:55:14 2002
+++ b/include/asm-arm/system.h	Thu Mar  6 08:26:25 2003
@@ -14,16 +14,6 @@
 extern unsigned int system_serial_high;
 extern unsigned int mem_fclk_21285;
 
-/*
- * This tells us if we have an ISA bridge
- * present in a PCI system.
- */
-#ifdef CONFIG_PCI
-extern int have_isa_bridge;
-#else
-#define have_isa_bridge		(0)
-#endif
-
 struct pt_regs;
 
 void die(const char *msg, struct pt_regs *regs, int err)
@@ -75,7 +65,7 @@
  * The `mb' is to tell GCC not to cache `current' across this call.
  */
 struct thread_info;
-extern struct task_struct *__switch_to(struct thread_info *, struct thread_info *);
+extern struct thread_info *__switch_to(struct thread_info *, struct thread_info *);
 
 #define switch_to(prev,next,last)					\
 	do {			 					\
diff -Nru a/include/asm-cris/processor.h b/include/asm-cris/processor.h
--- a/include/asm-cris/processor.h	Mon Feb 24 10:10:20 2003
+++ b/include/asm-cris/processor.h	Mon Mar 10 10:20:30 2003
@@ -123,6 +123,9 @@
         /* Nothing needs to be done.  */
 }
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 /*
  * Return saved PC of a blocked thread.
  */
diff -Nru a/include/asm-i386/bug.h b/include/asm-i386/bug.h
--- a/include/asm-i386/bug.h	Tue Feb 26 05:19:26 2002
+++ b/include/asm-i386/bug.h	Sun Feb 16 15:52:20 2003
@@ -4,8 +4,7 @@
 #include <linux/config.h>
 
 /*
- * Tell the user there is some problem. Beep too, so we can
- * see^H^H^Hhear bugs in early bootup as well!
+ * Tell the user there is some problem.
  * The offending file and line are encoded after the "officially
  * undefined" opcode for parsing in the trap handler.
  */
diff -Nru a/include/asm-i386/hdreg.h b/include/asm-i386/hdreg.h
--- a/include/asm-i386/hdreg.h	Wed Sep 11 00:06:00 2002
+++ b/include/asm-i386/hdreg.h	Tue Feb 18 06:32:42 2003
@@ -7,6 +7,5 @@
 #ifndef __ASMi386_HDREG_H
 #define __ASMi386_HDREG_H
 
-typedef unsigned long ide_ioreg_t;
 
 #endif /* __ASMi386_HDREG_H */
diff -Nru a/include/asm-i386/i387.h b/include/asm-i386/i387.h
--- a/include/asm-i386/i387.h	Fri Apr 19 12:34:03 2002
+++ b/include/asm-i386/i387.h	Mon Mar 10 10:20:30 2003
@@ -21,23 +21,41 @@
 /*
  * FPU lazy state save handling...
  */
-extern void save_init_fpu( struct task_struct *tsk );
 extern void restore_fpu( struct task_struct *tsk );
 
 extern void kernel_fpu_begin(void);
 #define kernel_fpu_end() do { stts(); preempt_enable(); } while(0)
 
 
+static inline void __save_init_fpu( struct task_struct *tsk )
+{
+	if ( cpu_has_fxsr ) {
+		asm volatile( "fxsave %0 ; fnclex"
+			      : "=m" (tsk->thread.i387.fxsave) );
+	} else {
+		asm volatile( "fnsave %0 ; fwait"
+			      : "=m" (tsk->thread.i387.fsave) );
+	}
+	tsk->thread_info->status &= ~TS_USEDFPU;
+}
+
+static inline void save_init_fpu( struct task_struct *tsk )
+{
+	__save_init_fpu(tsk);
+	stts();
+}
+
+
 #define unlazy_fpu( tsk ) do { \
-	if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) \
+	if ((tsk)->thread_info->status & TS_USEDFPU) \
 		save_init_fpu( tsk ); \
 } while (0)
 
 #define clear_fpu( tsk )					\
 do {								\
-	if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {		\
+	if ((tsk)->thread_info->status & TS_USEDFPU) {		\
 		asm volatile("fwait");				\
-		clear_tsk_thread_flag(tsk, TIF_USEDFPU);	\
+		(tsk)->thread_info->status &= ~TS_USEDFPU;	\
 		stts();						\
 	}							\
 } while (0)
diff -Nru a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
--- a/include/asm-i386/mmzone.h	Mon Feb 24 23:13:14 2003
+++ b/include/asm-i386/mmzone.h	Tue Mar  4 23:41:55 2003
@@ -10,14 +10,6 @@
 
 #ifdef CONFIG_DISCONTIGMEM
 
-#ifdef CONFIG_X86_NUMAQ
-#include <asm/numaq.h>
-#elif CONFIG_X86_SUMMIT
-#include <asm/srat.h>
-#else
-#define pfn_to_nid(pfn)		(0)
-#endif /* CONFIG_X86_NUMAQ */
-
 extern struct pglist_data *node_data[];
 
 /*
@@ -101,5 +93,41 @@
  * ( pfn_to_pgdat(pfn) && ((pfn) < node_end_pfn(pfn_to_nid(pfn))) ) 
  */ 
 #define pfn_valid(pfn)          ((pfn) < num_physpages)
+
+/*
+ * generic node memory support, the following assumptions apply:
+ *
+ * 1) memory comes in 256Mb contigious chunks which are either present or not
+ * 2) we will not have more than 64Gb in total
+ *
+ * for now assume that 64Gb is max amount of RAM for whole system
+ *    64Gb / 4096bytes/page = 16777216 pages
+ */
+#define MAX_NR_PAGES 16777216
+#define MAX_ELEMENTS 256
+#define PAGES_PER_ELEMENT (MAX_NR_PAGES/MAX_ELEMENTS)
+
+extern u8 physnode_map[];
+
+static inline int pfn_to_nid(unsigned long pfn)
+{
+	return(physnode_map[(pfn) / PAGES_PER_ELEMENT]);
+}
+static inline struct pglist_data *pfn_to_pgdat(unsigned long pfn)
+{
+	return(NODE_DATA(pfn_to_nid(pfn)));
+}
+
+#ifdef CONFIG_X86_NUMAQ
+#include <asm/numaq.h>
+#elif CONFIG_X86_SUMMIT
+#include <asm/srat.h>
+#elif CONFIG_X86_PC
+#define get_memcfg_numa get_memcfg_numa_flat
+#define get_zholes_size(n) (0)
+#else
+#define pfn_to_nid(pfn)		(0)
+#endif /* CONFIG_X86_NUMAQ */
+
 #endif /* CONFIG_DISCONTIGMEM */
 #endif /* _ASM_MMZONE_H_ */
diff -Nru a/include/asm-i386/numaq.h b/include/asm-i386/numaq.h
--- a/include/asm-i386/numaq.h	Fri Feb 28 15:03:59 2003
+++ b/include/asm-i386/numaq.h	Tue Mar  4 23:43:31 2003
@@ -28,18 +28,6 @@
 
 #ifdef CONFIG_X86_NUMAQ
 
-/*
- * for now assume that 64Gb is max amount of RAM for whole system
- *    64Gb / 4096bytes/page = 16777216 pages
- */
-#define MAX_NR_PAGES 16777216
-#define MAX_ELEMENTS 256
-#define PAGES_PER_ELEMENT (16777216/256)
-
-extern int physnode_map[];
-#define pfn_to_nid(pfn)	({ physnode_map[(pfn) / PAGES_PER_ELEMENT]; })
-#define pfn_to_pgdat(pfn) NODE_DATA(pfn_to_nid(pfn))
-#define PHYSADDR_TO_NID(pa) pfn_to_nid(pa >> PAGE_SHIFT)
 #define MAX_NUMNODES		8
 extern void get_memcfg_numaq(void);
 #define get_memcfg_numa() get_memcfg_numaq()
@@ -169,7 +157,7 @@
         struct	eachquadmem eq[MAX_NUMNODES];	/* indexed by quad id */
 };
 
-static inline unsigned long get_zholes_size(int nid)
+static inline unsigned long *get_zholes_size(int nid)
 {
 	return 0;
 }
diff -Nru a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h
--- a/include/asm-i386/pgtable-3level.h	Mon Feb  3 23:46:49 2003
+++ b/include/asm-i386/pgtable-3level.h	Thu Mar  6 08:19:07 2003
@@ -69,7 +69,7 @@
 
 /* Find an entry in the second-level page table.. */
 #define pmd_offset(dir, address) ((pmd_t *) pgd_page(*(dir)) + \
-			__pmd_offset(address))
+			pmd_index(address))
 
 static inline pte_t ptep_get_and_clear(pte_t *ptep)
 {
diff -Nru a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
--- a/include/asm-i386/pgtable.h	Tue Feb 18 18:58:46 2003
+++ b/include/asm-i386/pgtable.h	Thu Mar  6 17:44:46 2003
@@ -49,8 +49,6 @@
 
 #endif
 
-#define __beep() asm("movb $0x3,%al; outb %al,$0x61")
-
 #define PMD_SIZE	(1UL << PMD_SHIFT)
 #define PMD_MASK	(~(PMD_SIZE-1))
 #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
@@ -236,32 +234,30 @@
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
 
-#define __pgd_offset(address) pgd_index(address)
-
 #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
 
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
-#define __pmd_offset(address) \
+#define pmd_index(address) \
 		(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
 
 /* Find an entry in the third-level page table.. */
-#define __pte_offset(address) \
+#define pte_index(address) \
 		(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir, address) \
-	((pte_t *) pmd_page_kernel(*(dir)) +  __pte_offset(address))
+	((pte_t *) pmd_page_kernel(*(dir)) +  pte_index(address))
 
 #if defined(CONFIG_HIGHPTE)
 #define pte_offset_map(dir, address) \
-	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + __pte_offset(address))
+	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
 #define pte_offset_map_nested(dir, address) \
-	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + __pte_offset(address))
+	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + pte_index(address))
 #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
 #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
 #else
 #define pte_offset_map(dir, address) \
-	((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
+	((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
 #define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
 #define pte_unmap(pte) do { } while (0)
 #define pte_unmap_nested(pte) do { } while (0)
diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h
--- a/include/asm-i386/processor.h	Wed Feb 19 17:48:55 2003
+++ b/include/asm-i386/processor.h	Mon Mar 10 14:41:23 2003
@@ -347,7 +347,7 @@
 	unsigned long	esp0;
 	unsigned short	ss0,__ss0h;
 	unsigned long	esp1;
-	unsigned short	ss1,__ss1h;
+	unsigned short	ss1,__ss1h;	/* ss1 is used to cache MSR_IA32_SYSENTER_CS */
 	unsigned long	esp2;
 	unsigned short	ss2,__ss2h;
 	unsigned long	__cr3;
@@ -404,6 +404,8 @@
 #define INIT_TSS  {							\
 	.esp0		= sizeof(init_stack) + (long)&init_stack,	\
 	.ss0		= __KERNEL_DS,					\
+	.esp1		= sizeof(init_tss[0]) + (long)&init_tss[0],	\
+	.ss1		= __KERNEL_CS,					\
 	.ldt		= GDT_ENTRY_LDT,				\
 	.bitmap		= INVALID_IO_BITMAP_OFFSET,			\
 	.io_bitmap	= { [ 0 ... IO_BITMAP_SIZE ] = ~0 },		\
@@ -412,16 +414,19 @@
 static inline void load_esp0(struct tss_struct *tss, unsigned long esp0)
 {
 	tss->esp0 = esp0;
-	if (cpu_has_sep) {
+	/* This can only happen when SEP is enabled, no need to test "SEP"arately */
+	if (tss->ss1 != __KERNEL_CS) {
+		tss->ss1 = __KERNEL_CS;
 		wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
-		wrmsr(MSR_IA32_SYSENTER_ESP, esp0, 0);
 	}
 }
 
-static inline void disable_sysenter(void)
+static inline void disable_sysenter(struct tss_struct *tss)
 {
-	if (cpu_has_sep)  
+	if (cpu_has_sep)  {
+		tss->ss1 = 0;
 		wrmsr(MSR_IA32_SYSENTER_CS, 0, 0);
+	}
 }
 
 #define start_thread(regs, new_eip, new_esp) do {		\
@@ -441,6 +446,10 @@
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
+
+/* Prepare to copy thread state - unlazy all lazy status */
+extern void prepare_to_copy(struct task_struct *tsk);
+
 /*
  * create a kernel thread without removing it from tasklists
  */
diff -Nru a/include/asm-i386/serial.h b/include/asm-i386/serial.h
--- a/include/asm-i386/serial.h	Mon Feb  4 23:43:09 2002
+++ b/include/asm-i386/serial.h	Thu Feb 20 08:30:58 2003
@@ -50,12 +50,19 @@
 
 #define C_P(card,port) (((card)<<6|(port)<<3) + 1)
 
+#ifndef CONFIG_X86_PC9800
 #define STD_SERIAL_PORT_DEFNS			\
 	/* UART CLK   PORT IRQ     FLAGS        */			\
 	{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },	/* ttyS0 */	\
 	{ 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },	/* ttyS1 */	\
 	{ 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },	/* ttyS2 */	\
 	{ 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },	/* ttyS3 */
+#else
+#define STD_SERIAL_PORT_DEFNS			\
+	/* UART CLK   PORT IRQ     FLAGS        */			\
+	{ 0, BASE_BAUD, 0x30, 4, STD_COM_FLAGS },	/* ttyS0 */	\
+	{ 0, BASE_BAUD, 0x238, 5, STD_COM_FLAGS },	/* ttyS1 */
+#endif /* CONFIG_X86_PC9800 */
 
 
 #ifdef CONFIG_SERIAL_MANY_PORTS
diff -Nru a/include/asm-i386/srat.h b/include/asm-i386/srat.h
--- a/include/asm-i386/srat.h	Mon Feb 24 23:13:14 2003
+++ b/include/asm-i386/srat.h	Tue Mar  4 23:41:55 2003
@@ -27,17 +27,6 @@
 #ifndef _ASM_SRAT_H_
 #define _ASM_SRAT_H_
 
-/*
- * each element in pfnnode_map represents 256 MB (2^28) of pages.
- * so, to represent 64GB we need 256 elements.
- */
-#define MAX_ELEMENTS 256
-#define PFN_TO_ELEMENT(pfn) ((pfn)>>(28 - PAGE_SHIFT))
-
-extern int pfnnode_map[];
-#define pfn_to_nid(pfn) ({ pfnnode_map[PFN_TO_ELEMENT(pfn)]; })
-#define pfn_to_pgdat(pfn) NODE_DATA(pfn_to_nid(pfn))
-#define PHYSADDR_TO_NID(pa) pfn_to_nid(pa >> PAGE_SHIFT)
 #define MAX_NUMNODES		8
 extern void get_memcfg_from_srat(void);
 extern unsigned long *get_zholes_size(int);
diff -Nru a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
--- a/include/asm-i386/thread_info.h	Sat Jan  4 10:06:07 2003
+++ b/include/asm-i386/thread_info.h	Mon Mar 10 10:20:30 2003
@@ -25,6 +25,7 @@
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain	*exec_domain;	/* execution domain */
 	unsigned long		flags;		/* low level flags */
+	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
 	__s32			preempt_count; /* 0 => preemptable, <0 => BUG */
 
@@ -43,10 +44,11 @@
 #define TI_TASK		0x00000000
 #define TI_EXEC_DOMAIN	0x00000004
 #define TI_FLAGS	0x00000008
-#define TI_CPU		0x0000000C
-#define TI_PRE_COUNT	0x00000010
-#define TI_ADDR_LIMIT	0x00000014
-#define TI_RESTART_BLOCK 0x0000018
+#define TI_STATUS	0x0000000C
+#define TI_CPU		0x00000010
+#define TI_PRE_COUNT	0x00000014
+#define TI_ADDR_LIMIT	0x00000018
+#define TI_RESTART_BLOCK 0x000001C
 
 #endif
 
@@ -111,8 +113,7 @@
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_IRET		5	/* return with iret */
-#define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
-#define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
+#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
@@ -120,11 +121,19 @@
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_IRET		(1<<TIF_IRET)
-#define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
+
+/*
+ * Thread-synchronous status.
+ *
+ * This is different from the flags in that nobody else
+ * ever touches our thread-synchronous status, so we don't
+ * have to worry about atomic accesses.
+ */
+#define TS_USEDFPU		0x0001	/* FPU was used by this task this quantum (SMP) */
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/asm-i386/xor.h b/include/asm-i386/xor.h
--- a/include/asm-i386/xor.h	Wed Nov 20 14:42:33 2002
+++ b/include/asm-i386/xor.h	Mon Mar 10 14:36:17 2003
@@ -18,22 +18,6 @@
  * Copyright (C) 1998 Ingo Molnar.
  */
 
-#define FPU_SAVE							\
-  do {									\
-	preempt_disable();						\
-	if (!test_thread_flag(TIF_USEDFPU))				\
-		__asm__ __volatile__ (" clts;\n");			\
-	__asm__ __volatile__ ("fsave %0; fwait": "=m"(fpu_save[0]));	\
-  } while (0)
-
-#define FPU_RESTORE							\
-  do {									\
-	__asm__ __volatile__ ("frstor %0": : "m"(fpu_save[0]));		\
-	if (!test_thread_flag(TIF_USEDFPU))				\
-		stts();							\
-	preempt_enable();						\
-  } while (0)
-
 #define LD(x,y)		"       movq   8*("#x")(%1), %%mm"#y"   ;\n"
 #define ST(x,y)		"       movq %%mm"#y",   8*("#x")(%1)   ;\n"
 #define XO1(x,y)	"       pxor   8*("#x")(%2), %%mm"#y"   ;\n"
@@ -46,9 +30,8 @@
 xor_pII_mmx_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
 {
 	unsigned long lines = bytes >> 7;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	__asm__ __volatile__ (
 #undef BLOCK
@@ -83,7 +66,7 @@
 	:
 	: "memory");
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -91,9 +74,8 @@
 	      unsigned long *p3)
 {
 	unsigned long lines = bytes >> 7;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	__asm__ __volatile__ (
 #undef BLOCK
@@ -133,7 +115,7 @@
 	:
 	: "memory");
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -141,9 +123,8 @@
 	      unsigned long *p3, unsigned long *p4)
 {
 	unsigned long lines = bytes >> 7;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	__asm__ __volatile__ (
 #undef BLOCK
@@ -188,7 +169,7 @@
 	:
 	: "memory");
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 
@@ -197,9 +178,8 @@
 	      unsigned long *p3, unsigned long *p4, unsigned long *p5)
 {
 	unsigned long lines = bytes >> 7;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	/* need to save/restore p4/p5 manually otherwise gcc's 10 argument
 	   limit gets exceeded (+ counts as two arguments) */
@@ -255,7 +235,7 @@
 	: "r" (p4), "r" (p5) 
 	: "memory");
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 #undef LD
@@ -270,9 +250,8 @@
 xor_p5_mmx_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
 {
 	unsigned long lines = bytes >> 6;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	__asm__ __volatile__ (
 	" .align 32	             ;\n"
@@ -311,7 +290,7 @@
 	:
 	: "memory");
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -319,9 +298,8 @@
 	     unsigned long *p3)
 {
 	unsigned long lines = bytes >> 6;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	__asm__ __volatile__ (
 	" .align 32,0x90             ;\n"
@@ -369,7 +347,7 @@
 	:
 	: "memory" );
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -377,9 +355,8 @@
 	     unsigned long *p3, unsigned long *p4)
 {
 	unsigned long lines = bytes >> 6;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	__asm__ __volatile__ (
 	" .align 32,0x90             ;\n"
@@ -436,7 +413,7 @@
 	:
 	: "memory");
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -444,9 +421,8 @@
 	     unsigned long *p3, unsigned long *p4, unsigned long *p5)
 {
 	unsigned long lines = bytes >> 6;
-	char fpu_save[108];
 
-	FPU_SAVE;
+	kernel_fpu_begin();
 
 	/* need to save p4/p5 manually to not exceed gcc's 10 argument limit */
 	__asm__ __volatile__ (
@@ -517,7 +493,7 @@
 	: "r" (p4), "r" (p5)
 	: "memory");
 
-	FPU_RESTORE;
+	kernel_fpu_end();
 }
 
 static struct xor_block_template xor_block_pII_mmx = {
@@ -535,9 +511,6 @@
 	.do_4 = xor_p5_mmx_4,
 	.do_5 = xor_p5_mmx_5,
 };
-
-#undef FPU_SAVE
-#undef FPU_RESTORE
 
 /*
  * Cache avoiding checksumming functions utilizing KNI instructions
diff -Nru a/include/asm-ia64/hardirq.h b/include/asm-ia64/hardirq.h
--- a/include/asm-ia64/hardirq.h	Tue Sep 17 23:22:09 2002
+++ b/include/asm-ia64/hardirq.h	Wed Feb  5 03:03:22 2003
@@ -32,18 +32,18 @@
  *
  * - bits 0-7 are the preemption count (max preemption depth: 256)
  * - bits 8-15 are the softirq count (max # of softirqs: 256)
- * - bits 16-31 are the hardirq count (max # of hardirqs: 65536)
+ * - bits 16-29 are the hardirq count (max # of hardirqs: 16384)
  *
  * - (bit 63 is the PREEMPT_ACTIVE flag---not currently implemented.)
  *
  * PREEMPT_MASK: 0x000000ff
  * SOFTIRQ_MASK: 0x0000ff00
- * HARDIRQ_MASK: 0xffff0000
+ * HARDIRQ_MASK: 0x3fff0000
  */
 
 #define PREEMPT_BITS	8
 #define SOFTIRQ_BITS	8
-#define HARDIRQ_BITS	16
+#define HARDIRQ_BITS	14
 
 #define PREEMPT_SHIFT	0
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
@@ -83,13 +83,13 @@
 #define hardirq_trylock()	(!in_interrupt())
 #define hardirq_endlock()	do { } while (0)
 
-#define in_atomic()		(preempt_count() != 0)
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 
 #if CONFIG_PREEMPT
-# error CONFIG_PREEMT currently not supported.
+# define in_atomic()		((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
 # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
 #else
+# define in_atomic()		(preempt_count() != 0)
 # define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
 #endif
 
diff -Nru a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h
--- a/include/asm-ia64/ide.h	Thu Oct 31 21:45:22 2002
+++ b/include/asm-ia64/ide.h	Thu Mar  6 21:11:46 2003
@@ -91,6 +91,8 @@
 #endif
 }
 
+#include <asm-generic/ide_iops.h>
+
 #endif /* __KERNEL__ */
 
 #endif /* __ASM_IA64_IDE_H */
diff -Nru a/include/asm-ia64/intrinsics.h b/include/asm-ia64/intrinsics.h
--- a/include/asm-ia64/intrinsics.h	Wed Jan 15 16:26:26 2003
+++ b/include/asm-ia64/intrinsics.h	Thu Mar  6 11:22:21 2003
@@ -35,24 +35,34 @@
 	}									\
 })
 
-#define ia64_fetch_and_add(i,v)							\
-({										\
-	__u64 _tmp;								\
-	volatile __typeof__(*(v)) *_v = (v);					\
-	switch (i) {								\
-	      case -16:	IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v))); break;	\
-	      case  -8:	IA64_FETCHADD(_tmp, _v,  -8, sizeof(*(v))); break;	\
-	      case  -4:	IA64_FETCHADD(_tmp, _v,  -4, sizeof(*(v))); break;	\
-	      case  -1:	IA64_FETCHADD(_tmp, _v,  -1, sizeof(*(v))); break;	\
-	      case   1:	IA64_FETCHADD(_tmp, _v,   1, sizeof(*(v))); break;	\
-	      case   4:	IA64_FETCHADD(_tmp, _v,   4, sizeof(*(v))); break;	\
-	      case   8:	IA64_FETCHADD(_tmp, _v,   8, sizeof(*(v))); break;	\
-	      case  16:	IA64_FETCHADD(_tmp, _v,  16, sizeof(*(v))); break;	\
-	      default:								\
-		_tmp = __bad_increment_for_ia64_fetch_and_add();		\
-		break;								\
-	}									\
-	(__typeof__(*(v))) (_tmp + (i));	/* return new value */		\
+#define ia64_fetch_and_add(i,v)								\
+({											\
+	__u64 _tmp;									\
+	volatile __typeof__(*(v)) *_v = (v);						\
+	/* Can't use a switch () here: gcc isn't always smart enough for that... */	\
+	if ((i) == -16)									\
+		IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v)));				\
+	else if ((i) == -8)								\
+		IA64_FETCHADD(_tmp, _v, -8, sizeof(*(v)));				\
+	else if ((i) == -4)								\
+		IA64_FETCHADD(_tmp, _v, -4, sizeof(*(v)));				\
+	else if ((i) == -2)								\
+		IA64_FETCHADD(_tmp, _v, -2, sizeof(*(v)));				\
+	else if ((i) == -1)								\
+		IA64_FETCHADD(_tmp, _v, -1, sizeof(*(v)));				\
+	else if ((i) == 1)								\
+		IA64_FETCHADD(_tmp, _v, 1, sizeof(*(v)));				\
+	else if ((i) == 2)								\
+		IA64_FETCHADD(_tmp, _v, 2, sizeof(*(v)));				\
+	else if ((i) == 4)								\
+		IA64_FETCHADD(_tmp, _v, 4, sizeof(*(v)));				\
+	else if ((i) == 8)								\
+		IA64_FETCHADD(_tmp, _v, 8, sizeof(*(v)));				\
+	else if ((i) == 16)								\
+		IA64_FETCHADD(_tmp, _v, 16, sizeof(*(v)));				\
+	else										\
+		_tmp = __bad_increment_for_ia64_fetch_and_add();			\
+	(__typeof__(*(v))) (_tmp + (i));	/* return new value */			\
 })
 
 /*
diff -Nru a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h
--- a/include/asm-ia64/iosapic.h	Wed Sep 25 19:04:16 2002
+++ b/include/asm-ia64/iosapic.h	Wed Feb 19 09:02:36 2003
@@ -51,26 +51,23 @@
 
 #ifndef __ASSEMBLY__
 
-extern void __devinit iosapic_init (unsigned long address,
-				    unsigned int gsi_base,
-				    int pcat_compat);
+extern void __init iosapic_system_init (int pcat_compat);
+extern void __init iosapic_init (unsigned long address,
+				    unsigned int gsi_base);
 extern int gsi_to_vector (unsigned int gsi);
 extern int gsi_to_irq (unsigned int gsi);
-extern void iosapic_parse_prt (void);
+extern void __init iosapic_parse_prt (void);
 extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity,
-				  unsigned long edge_triggered,
-				  u32 gsi_base, char *iosapic_address);
-extern void iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
+				  unsigned long trigger);
+extern void __init iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
 				      unsigned long polarity,
-				      unsigned long edge_triggered);
-extern int iosapic_register_platform_intr (u32 int_type,
+				      unsigned long trigger);
+extern int __init iosapic_register_platform_intr (u32 int_type,
 					   unsigned int gsi,
 					   int pmi_vector,
 					   u16 eid, u16 id,
 					   unsigned long polarity,
-					   unsigned long edge_triggered,
-					   unsigned int gsi_base,
-					   char *iosapic_address);
+					   unsigned long trigger);
 extern unsigned int iosapic_version (char *addr);
 
 extern void iosapic_pci_fixup (int);
diff -Nru a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
--- a/include/asm-ia64/machvec.h	Sat Sep 21 01:25:52 2002
+++ b/include/asm-ia64/machvec.h	Thu Feb 20 05:59:35 2003
@@ -23,8 +23,6 @@
 typedef void ia64_mv_setup_t (char **);
 typedef void ia64_mv_cpu_init_t(void);
 typedef void ia64_mv_irq_init_t (void);
-typedef void ia64_mv_pci_fixup_t (int);
-typedef unsigned long ia64_mv_map_nr_t (unsigned long);
 typedef void ia64_mv_mca_init_t (void);
 typedef void ia64_mv_mca_handler_t (void);
 typedef void ia64_mv_cmci_handler_t (int, void *, struct pt_regs *);
@@ -115,13 +113,16 @@
 #  define platofrm_mmiob        ia64_mv.mmiob
 # endif
 
+/* __attribute__((__aligned__(16))) is required to make size of the
+ * structure multiple of 16 bytes.
+ * This will fillup the holes created because of section 3.3.1 in 
+ * Software Conventions guide.
+ */
 struct ia64_machine_vector {
 	const char *name;
 	ia64_mv_setup_t *setup;
 	ia64_mv_cpu_init_t *cpu_init;
 	ia64_mv_irq_init_t *irq_init;
-	ia64_mv_pci_fixup_t *pci_fixup;
-	ia64_mv_map_nr_t *map_nr;
 	ia64_mv_mca_init_t *mca_init;
 	ia64_mv_mca_handler_t *mca_handler;
 	ia64_mv_cmci_handler_t *cmci_handler;
@@ -149,7 +150,7 @@
 	ia64_mv_outw_t *outw;
 	ia64_mv_outl_t *outl;
 	ia64_mv_mmiob_t *mmiob;
-};
+} __attribute__((__aligned__(16)));
 
 #define MACHVEC_INIT(name)			\
 {						\
diff -Nru a/include/asm-ia64/machvec_dig.h b/include/asm-ia64/machvec_dig.h
--- a/include/asm-ia64/machvec_dig.h	Sat Sep 21 01:25:52 2002
+++ b/include/asm-ia64/machvec_dig.h	Thu Feb 20 03:14:25 2003
@@ -3,8 +3,6 @@
 
 extern ia64_mv_setup_t dig_setup;
 extern ia64_mv_irq_init_t dig_irq_init;
-extern ia64_mv_pci_fixup_t iosapic_pci_fixup;
-extern ia64_mv_map_nr_t map_nr_dense;
 
 /*
  * This stuff has dual use!
diff -Nru a/include/asm-ia64/machvec_hpsim.h b/include/asm-ia64/machvec_hpsim.h
--- a/include/asm-ia64/machvec_hpsim.h	Sat Sep 21 01:25:52 2002
+++ b/include/asm-ia64/machvec_hpsim.h	Thu Feb 20 03:14:12 2003
@@ -3,7 +3,6 @@
 
 extern ia64_mv_setup_t hpsim_setup;
 extern ia64_mv_irq_init_t hpsim_irq_init;
-extern ia64_mv_map_nr_t map_nr_dense;
 
 /*
  * This stuff has dual use!
diff -Nru a/include/asm-ia64/machvec_hpzx1.h b/include/asm-ia64/machvec_hpzx1.h
--- a/include/asm-ia64/machvec_hpzx1.h	Sat Sep 21 01:25:52 2002
+++ b/include/asm-ia64/machvec_hpzx1.h	Thu Feb 20 03:31:21 2003
@@ -2,8 +2,6 @@
 #define _ASM_IA64_MACHVEC_HPZX1_h
 
 extern ia64_mv_setup_t dig_setup;
-extern ia64_mv_pci_fixup_t hpzx1_pci_fixup;
-extern ia64_mv_map_nr_t map_nr_dense;
 extern ia64_mv_pci_alloc_consistent sba_alloc_consistent;
 extern ia64_mv_pci_free_consistent sba_free_consistent;
 extern ia64_mv_pci_map_single sba_map_single;
diff -Nru a/include/asm-ia64/machvec_sn1.h b/include/asm-ia64/machvec_sn1.h
--- a/include/asm-ia64/machvec_sn1.h	Sat Sep 21 01:25:52 2002
+++ b/include/asm-ia64/machvec_sn1.h	Thu Feb 20 03:34:17 2003
@@ -36,10 +36,8 @@
 extern ia64_mv_setup_t sn1_setup;
 extern ia64_mv_cpu_init_t sn_cpu_init;
 extern ia64_mv_irq_init_t sn1_irq_init;
-extern ia64_mv_map_nr_t sn1_map_nr;
 extern ia64_mv_send_ipi_t sn1_send_IPI;
 extern ia64_mv_global_tlb_purge_t sn1_global_tlb_purge;
-extern ia64_mv_pci_fixup_t sn1_pci_fixup;
 extern ia64_mv_inb_t sn1_inb;
 extern ia64_mv_inw_t sn1_inw;
 extern ia64_mv_inl_t sn1_inl;
diff -Nru a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h
--- a/include/asm-ia64/machvec_sn2.h	Tue Dec  3 10:07:32 2002
+++ b/include/asm-ia64/machvec_sn2.h	Thu Feb 20 03:59:23 2003
@@ -36,13 +36,11 @@
 extern ia64_mv_setup_t sn_setup;
 extern ia64_mv_cpu_init_t sn_cpu_init;
 extern ia64_mv_irq_init_t sn_irq_init;
-extern ia64_mv_map_nr_t sn2_map_nr;
 extern ia64_mv_send_ipi_t sn2_send_IPI;
 extern ia64_mv_global_tlb_purge_t sn2_global_tlb_purge;
 extern ia64_mv_irq_desc sn_irq_desc;
 extern ia64_mv_irq_to_vector sn_irq_to_vector;
 extern ia64_mv_local_vector_to_irq sn_local_vector_to_irq;
-extern ia64_mv_pci_fixup_t sn_pci_fixup;
 extern ia64_mv_inb_t sn_inb;
 extern ia64_mv_inw_t sn_inw;
 extern ia64_mv_inl_t sn_inl;
@@ -72,10 +70,8 @@
 #define platform_setup			sn_setup
 #define platform_cpu_init		sn_cpu_init
 #define platform_irq_init		sn_irq_init
-#define platform_map_nr			sn2_map_nr
 #define platform_send_ipi		sn2_send_IPI
 #define platform_global_tlb_purge       sn2_global_tlb_purge
-#define platform_pci_fixup		sn_pci_fixup
 #define platform_inb			sn_inb
 #define platform_inw			sn_inw
 #define platform_inl			sn_inl
diff -Nru a/include/asm-ia64/mmzone.h b/include/asm-ia64/mmzone.h
--- a/include/asm-ia64/mmzone.h	Tue Feb 25 02:08:52 2003
+++ b/include/asm-ia64/mmzone.h	Thu Mar  6 11:40:52 2003
@@ -76,7 +76,7 @@
 
 #define pfn_to_page(pfn)	(struct page *)(node_mem_map(pfn_to_nid(pfn)) + node_localnr(pfn, pfn_to_nid(pfn)))
 
-#define pfn_to_nid(pfn)		 local_node_data->node_id_map[(pfn << PAGE_SHIFT) >> DIG_BANKSHIFT]
+#define pfn_to_nid(pfn)		 local_node_data->node_id_map[(pfn << PAGE_SHIFT) >> BANKSHIFT]
 
 #define page_to_pfn(page)	(long)((page - page_zone(page)->zone_mem_map) + page_zone(page)->zone_start_pfn)
 
@@ -110,15 +110,15 @@
  */
 #define NR_BANKS_PER_NODE	32
 #if defined(CONFIG_IA64_NODESIZE_16GB)
-# define DIG_BANKSHIFT		29
+# define BANKSHIFT		29
 #elif defined(CONFIG_IA64_NODESIZE_64GB)
-# define DIG_BANKSHIFT		31
+# define BANKSHIFT		31
 #elif defined(CONFIG_IA64_NODESIZE_256GB)
-# define DIG_BANKSHIFT		33
+# define BANKSHIFT		33
 #else
 # error Unsupported bank and nodesize!
 #endif
-#define BANKSIZE		(1UL << DIG_BANKSHIFT)
+#define BANKSIZE		(1UL << BANKSHIFT)
 #define BANK_OFFSET(addr)	((unsigned long)(addr) & (BANKSIZE-1))
 #define NR_BANKS		(NR_BANKS_PER_NODE * NR_NODES)
 
@@ -134,7 +134,30 @@
  * entry for the first page of the bank.
  */
 #define BANK_MEM_MAP_INDEX(kaddr) \
-	(((unsigned long)(kaddr) & (MAX_PHYS_MEMORY-1)) >> DIG_BANKSHIFT)
+	(((unsigned long)(kaddr) & (MAX_PHYS_MEMORY-1)) >> BANKSHIFT)
+
+#elif defined(CONFIG_IA64_SGI_SN2)
+/*
+ * SGI SN2 discontig definitions
+ */
+#define MAX_PHYSNODE_ID	2048	/* 2048 node ids (also called nasid) */
+#define NR_NODES	128	/* Maximum number of nodes in SSI */
+#define MAX_PHYS_MEMORY	(1UL << 49)
+
+#define BANKSHIFT		38
+#define NR_BANKS_PER_NODE	4
+#define SN2_NODE_SIZE		(64UL*1024*1024*1024)	/* 64GB per node */
+#define BANKSIZE		(SN2_NODE_SIZE/NR_BANKS_PER_NODE)
+#define BANK_OFFSET(addr)	((unsigned long)(addr) & (BANKSIZE-1))
+#define NR_BANKS		(NR_BANKS_PER_NODE * NR_NODES)
+#define VALID_MEM_KADDR(kaddr)	1
+
+/*
+ * Given a nodeid & a bank number, find the address of the mem_map
+ * entry for the first page of the bank.
+ */
+#define BANK_MEM_MAP_INDEX(kaddr) \
+	(((unsigned long)(kaddr) & (MAX_PHYS_MEMORY-1)) >> BANKSHIFT)
 
 #endif /* CONFIG_IA64_DIG */
 #endif /* _ASM_IA64_MMZONE_H */
diff -Nru a/include/asm-ia64/page.h b/include/asm-ia64/page.h
--- a/include/asm-ia64/page.h	Sun Mar  2 18:14:37 2003
+++ b/include/asm-ia64/page.h	Thu Mar  6 13:34:27 2003
@@ -57,16 +57,7 @@
 # define REGION_SHIFT	61
 # define HPAGE_SIZE	(__IA64_UL_CONST(1) << HPAGE_SHIFT)
 # define HPAGE_MASK	(~(HPAGE_SIZE - 1))
-static inline int
-check_valid_hugepage_range(unsigned long addr, unsigned long len)
-{
-	if (REGION_NUMBER(addr) == REGION_HPAGE)
-		return -EINVAL;
-	if (REGION_NUMBER(addr+len) == REGION_HPAGE)
-		return -EINVAL;
-	return 0;
-}
-#define ARCH_HAS_VALID_HUGEPAGE_RANGE
+# define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
 #endif /* CONFIG_HUGETLB_PAGE */
 
 #ifdef __ASSEMBLY__
@@ -133,6 +124,9 @@
 # define htlbpage_to_page(x)	((REGION_NUMBER(x) << 61)				\
 				 | (REGION_OFFSET(x) >> (HPAGE_SHIFT-PAGE_SHIFT)))
 # define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
+extern int  is_invalid_hugepage_range(unsigned long addr, unsigned long len);
+#else
+#define is_invalid_hugepage_range(addr, len) 0
 #endif
 
 static __inline__ int
diff -Nru a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h
--- a/include/asm-ia64/pci.h	Fri Aug 30 06:59:50 2002
+++ b/include/asm-ia64/pci.h	Tue Mar  4 18:40:15 2003
@@ -44,6 +44,9 @@
 	/* We don't do dynamic PCI IRQ allocation */
 }
 
+#define HAVE_ARCH_PCI_MWI 1
+extern int pcibios_prep_mwi (struct pci_dev *);
+
 /*
  * Dynamic DMA mapping API.  See Documentation/DMA-mapping.txt for details.
  */
diff -Nru a/include/asm-ia64/perfmon.h b/include/asm-ia64/perfmon.h
--- a/include/asm-ia64/perfmon.h	Tue Jan 28 15:15:42 2003
+++ b/include/asm-ia64/perfmon.h	Thu Feb  6 08:45:24 2003
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001-2002 Hewlett-Packard Co
+ * Copyright (C) 2001-2003 Hewlett-Packard Co
  *               Stephane Eranian <eranian@hpl.hp.com>
  */
 
diff -Nru a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
--- a/include/asm-ia64/pgtable.h	Thu Oct 31 21:45:22 2002
+++ b/include/asm-ia64/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -317,8 +317,8 @@
  * Find an entry in the third-level page table.  This looks more complicated than it
  * should be because some platforms place page tables in high memory.
  */
-#define __pte_offset(addr)	 	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
-#define pte_offset_kernel(dir,addr)	((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(addr))
+#define pte_index(addr)	 	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset_kernel(dir,addr)	((pte_t *) pmd_page_kernel(*(dir)) + pte_index(addr))
 #define pte_offset_map(dir,addr)	pte_offset_kernel(dir, addr)
 #define pte_offset_map_nested(dir,addr)	pte_offset_map(dir, addr)
 #define pte_unmap(pte)			do { } while (0)
diff -Nru a/include/asm-ia64/posix_types.h b/include/asm-ia64/posix_types.h
--- a/include/asm-ia64/posix_types.h	Tue Feb  5 09:39:54 2002
+++ b/include/asm-ia64/posix_types.h	Thu Mar  6 21:11:46 2003
@@ -6,8 +6,8 @@
  * be a little careful about namespace pollution etc.  Also, we cannot
  * assume GCC is being used.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2000, 2003 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
 typedef unsigned int	__kernel_dev_t;
@@ -26,6 +26,8 @@
 typedef long		__kernel_time_t;
 typedef long		__kernel_suseconds_t;
 typedef long		__kernel_clock_t;
+typedef int		__kernel_timer_t;
+typedef int		__kernel_clockid_t;
 typedef int		__kernel_daddr_t;
 typedef char *		__kernel_caddr_t;
 typedef unsigned long	__kernel_sigset_t;	/* at least 32 bits */
diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
--- a/include/asm-ia64/processor.h	Tue Jan 14 22:14:16 2003
+++ b/include/asm-ia64/processor.h	Mon Mar 10 10:20:31 2003
@@ -68,11 +68,11 @@
 
 
 /*
- * This shift should be large enough to be able to represent
- * 1000000/itc_freq with good accuracy while being small enough to fit
- * 1000000<<IA64_USEC_PER_CYC_SHIFT in 64 bits.
+ * This shift should be large enough to be able to represent 1000000000/itc_freq with good
+ * accuracy while being small enough to fit 10*1000000000<<IA64_NSEC_PER_CYC_SHIFT in 64 bits
+ * (this will give enough slack to represent 10 seconds worth of time as a scaled number).
  */
-#define IA64_USEC_PER_CYC_SHIFT	41
+#define IA64_NSEC_PER_CYC_SHIFT	30
 
 #ifndef __ASSEMBLY__
 
@@ -161,7 +161,7 @@
 	__u64 itc_freq;		/* frequency of ITC counter */
 	__u64 proc_freq;	/* frequency of processor */
 	__u64 cyc_per_usec;	/* itc_freq/1000000 */
-	__u64 usec_per_cyc;	/* 2^IA64_USEC_PER_CYC_SHIFT*1000000/itc_freq */
+	__u64 nsec_per_cyc;	/* (1000000000<<IA64_NSEC_PER_CYC_SHIFT)/itc_freq */
 	__u64 unimpl_va_mask;	/* mask of unimplemented virtual address bits (from PAL) */
 	__u64 unimpl_pa_mask;	/* mask of unimplemented physical address bits (from PAL) */
 	__u64 ptce_base;
@@ -220,8 +220,6 @@
 		 (int *) (addr));								\
 })
 
-struct siginfo;
-
 struct thread_struct {
 	__u32 flags;			/* various thread flags (see IA64_THREAD_*) */
 	/* writing on_ustack is performance-critical, so it's worth spending 8 bits on it... */
@@ -230,7 +228,6 @@
 	__u64 ksp;			/* kernel stack pointer */
 	__u64 map_base;			/* base address for get_unmapped_area() */
 	__u64 task_size;		/* limit for task size */
-	struct siginfo *siginfo;	/* current siginfo struct for ptrace() */
 	int last_fph_cpu;		/* CPU that may hold the contents of f32-f127 */
 
 #ifdef CONFIG_IA32_SUPPORT
@@ -284,7 +281,6 @@
 	.ksp =		0,			\
 	.map_base =	DEFAULT_MAP_BASE,	\
 	.task_size =	DEFAULT_TASK_SIZE,	\
-	.siginfo =	0,			\
 	.last_fph_cpu =  0,			\
 	INIT_THREAD_IA32			\
 	INIT_THREAD_PM				\
@@ -347,6 +343,9 @@
 #else
 # define release_thread(dead_task)
 #endif
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
 
 /*
  * This is the mechanism for creating a new kernel thread.
diff -Nru a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h
--- a/include/asm-ia64/ptrace.h	Fri Jan 24 11:56:49 2003
+++ b/include/asm-ia64/ptrace.h	Wed Feb 12 00:11:33 2003
@@ -289,8 +289,8 @@
  * not overlap with any of the number assigned in <linux/ptrace.h>.
  */
 #define PTRACE_SINGLEBLOCK	12	/* resume execution until next branch */
-#define PTRACE_GETSIGINFO	13	/* get child's siginfo structure */
-#define PTRACE_SETSIGINFO	14	/* set child's siginfo structure */
+#define PTRACE_OLD_GETSIGINFO	13	/* (replaced by PTRACE_GETSIGINFO in <linux/ptrace.h>)  */
+#define PTRACE_OLD_SETSIGINFO	14	/* (replaced by PTRACE_SETSIGINFO in <linux/ptrace.h>)  */
 #define PTRACE_GETREGS		18	/* get all registers (pt_all_user_regs) in one shot */
 #define PTRACE_SETREGS		19	/* set all registers (pt_all_user_regs) in one shot */
 
diff -Nru a/include/asm-ia64/rwsem.h b/include/asm-ia64/rwsem.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ia64/rwsem.h	Thu Mar  6 11:22:21 2003
@@ -0,0 +1,188 @@
+/*
+ * asm-ia64/rwsem.h: R/W semaphores for ia64
+ *
+ * Copyright (C) 2003 Ken Chen <kenneth.w.chen@intel.com>
+ * Copyright (C) 2003 Asit Mallick <asit.k.mallick@intel.com>
+ *
+ * Based on asm-i386/rwsem.h and other architecture implementation.
+ *
+ * The MSW of the count is the negated number of active writers and
+ * waiting lockers, and the LSW is the total number of active locks.
+ *
+ * The lock count is initialized to 0 (no active and no waiting lockers).
+ *
+ * When a writer subtracts WRITE_BIAS, it'll get 0xffff0001 for the case
+ * of an uncontended lock. Readers increment by 1 and see a positive value
+ * when uncontended, negative if there are writers (and maybe) readers
+ * waiting (in which case it goes to sleep).
+ */
+
+#ifndef _ASM_IA64_RWSEM_H
+#define _ASM_IA64_RWSEM_H
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+/*
+ * the semaphore definition
+ */
+struct rw_semaphore {
+	signed int		count;
+	spinlock_t		wait_lock;
+	struct list_head	wait_list;
+#if RWSEM_DEBUG
+	int			debug;
+#endif
+};
+
+#define RWSEM_UNLOCKED_VALUE		0x00000000
+#define RWSEM_ACTIVE_BIAS		0x00000001
+#define RWSEM_ACTIVE_MASK		0x0000ffff
+#define RWSEM_WAITING_BIAS		(-0x00010000)
+#define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
+#define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+
+/*
+ * initialization
+ */
+#if RWSEM_DEBUG
+#define __RWSEM_DEBUG_INIT      , 0
+#else
+#define __RWSEM_DEBUG_INIT	/* */
+#endif
+
+#define __RWSEM_INITIALIZER(name) \
+	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
+	  LIST_HEAD_INIT((name).wait_list) \
+	  __RWSEM_DEBUG_INIT }
+
+#define DECLARE_RWSEM(name) \
+	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+
+extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
+
+static inline void
+init_rwsem (struct rw_semaphore *sem)
+{
+	sem->count = RWSEM_UNLOCKED_VALUE;
+	spin_lock_init(&sem->wait_lock);
+	INIT_LIST_HEAD(&sem->wait_list);
+#if RWSEM_DEBUG
+	sem->debug = 0;
+#endif
+}
+
+/*
+ * lock for reading
+ */
+static inline void
+__down_read (struct rw_semaphore *sem)
+{
+	int result;
+	__asm__ __volatile__ ("fetchadd4.acq %0=[%1],1" :
+			      "=r"(result) : "r"(&sem->count) : "memory");
+	if (result < 0)
+		rwsem_down_read_failed(sem);
+}
+
+/*
+ * lock for writing
+ */
+static inline void
+__down_write (struct rw_semaphore *sem)
+{
+	int old, new;
+
+	do {
+		old = sem->count;
+		new = old + RWSEM_ACTIVE_WRITE_BIAS;
+	} while (cmpxchg_acq(&sem->count, old, new) != old);
+
+	if (old != 0)
+		rwsem_down_write_failed(sem);
+}
+
+/*
+ * unlock after reading
+ */
+static inline void
+__up_read (struct rw_semaphore *sem)
+{
+	int result;
+	__asm__ __volatile__ ("fetchadd4.rel %0=[%1],-1" :
+			      "=r"(result) : "r"(&sem->count) : "memory");
+	if (result < 0 && (--result & RWSEM_ACTIVE_MASK) == 0)
+		rwsem_wake(sem);
+}
+
+/*
+ * unlock after writing
+ */
+static inline void
+__up_write (struct rw_semaphore *sem)
+{
+	int old, new;
+
+	do {
+		old = sem->count;
+		new = old - RWSEM_ACTIVE_WRITE_BIAS;
+	} while (cmpxchg_rel(&sem->count, old, new) != old);
+
+	if (new < 0 && (new & RWSEM_ACTIVE_MASK) == 0)
+		rwsem_wake(sem);
+}
+
+/*
+ * trylock for reading -- returns 1 if successful, 0 if contention
+ */
+static inline int
+__down_read_trylock (struct rw_semaphore *sem)
+{
+	int tmp;
+	while ((tmp = sem->count) >= 0) {
+		if (tmp == cmpxchg_acq(&sem->count, tmp, tmp+1)) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*
+ * trylock for writing -- returns 1 if successful, 0 if contention
+ */
+static inline int
+__down_write_trylock (struct rw_semaphore *sem)
+{
+	int tmp = cmpxchg_acq(&sem->count, RWSEM_UNLOCKED_VALUE,
+			      RWSEM_ACTIVE_WRITE_BIAS);
+	return tmp == RWSEM_UNLOCKED_VALUE;
+}
+
+/*
+ * downgrade write lock to read lock
+ */
+static inline void
+__downgrade_write (struct rw_semaphore *sem)
+{
+	int old, new;
+
+	do {
+		old = sem->count;
+		new = old - RWSEM_WAITING_BIAS;
+	} while (cmpxchg_rel(&sem->count, old, new) != old);
+
+	if (old < 0)
+		rwsem_downgrade_wake(sem);
+}
+
+/*
+ * Implement atomic add functionality.  These used to be "inline" functions, but GCC v3.1
+ * doesn't quite optimize this stuff right and ends up with bad calls to fetchandadd.
+ */
+#define rwsem_atomic_add(delta, sem)	atomic_add(delta, (atomic_t *)(&(sem)->count))
+#define rwsem_atomic_update(delta, sem)	atomic_add_return(delta, (atomic_t *)(&(sem)->count))
+
+#endif /* _ASM_IA64_RWSEM_H */
diff -Nru a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h
--- a/include/asm-ia64/sal.h	Mon Sep 16 09:26:30 2002
+++ b/include/asm-ia64/sal.h	Tue Mar  4 18:33:56 2003
@@ -10,8 +10,8 @@
  * Copyright (C) 2001 Intel
  * Copyright (C) 2002 Jenna Hall <jenna.s.hall@intel.com>
  * Copyright (C) 2001 Fred Lewis <frederick.v.lewis@intel.com>
- * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
- * Copyright (C) 1998, 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998, 1999, 2001, 2003 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
  * Copyright (C) 1999 Srinivasa Prasad Thirumalachar <sprasad@sprasad.engr.sgi.com>
  *
  * 02/01/04 J. Hall Updated Error Record Structures to conform to July 2001
@@ -19,7 +19,7 @@
  * 01/01/03 fvlewis Updated Error Record Structures to conform with Nov. 2000
  *                  revision of the SAL spec.
  * 99/09/29 davidm	Updated for SAL 2.6.
- * 00/03/29 cfleck      Updated SAL Error Logging info for processor (SAL 2.6) 
+ * 00/03/29 cfleck      Updated SAL Error Logging info for processor (SAL 2.6)
  *                      (plus examples of platform error info structures from smariset @ Intel)
  */
 
@@ -208,30 +208,30 @@
 
 /* SAL information type encodings */
 enum {
-	SAL_INFO_TYPE_MCA	=		0,	/* Machine check abort information */
-        SAL_INFO_TYPE_INIT	=		1,	/* Init information */
-        SAL_INFO_TYPE_CMC   =       2,  /* Corrected machine check information */
-        SAL_INFO_TYPE_CPE   =       3   /* Corrected platform error information */
+	SAL_INFO_TYPE_MCA  = 0,		/* Machine check abort information */
+        SAL_INFO_TYPE_INIT = 1,		/* Init information */
+        SAL_INFO_TYPE_CMC  = 2,		/* Corrected machine check information */
+        SAL_INFO_TYPE_CPE  = 3		/* Corrected platform error information */
 };
 
 /* Encodings for machine check parameter types */
 enum {
-        SAL_MC_PARAM_RENDEZ_INT		=	1,	/* Rendezevous interrupt */
-        SAL_MC_PARAM_RENDEZ_WAKEUP  =   2,  /* Wakeup */
-        SAL_MC_PARAM_CPE_INT        =   3   /* Corrected Platform Error Int */
+	SAL_MC_PARAM_RENDEZ_INT    = 1,	/* Rendezevous interrupt */
+	SAL_MC_PARAM_RENDEZ_WAKEUP = 2,	/* Wakeup */
+	SAL_MC_PARAM_CPE_INT	   = 3	/* Corrected Platform Error Int */
 };
 
 /* Encodings for rendezvous mechanisms */
 enum {
-        SAL_MC_PARAM_MECHANISM_INT	=	1,	/* Use interrupt */
-        SAL_MC_PARAM_MECHANISM_MEM	=	2	/* Use memory synchronization variable*/
+	SAL_MC_PARAM_MECHANISM_INT = 1,	/* Use interrupt */
+	SAL_MC_PARAM_MECHANISM_MEM = 2	/* Use memory synchronization variable*/
 };
 
 /* Encodings for vectors which can be registered by the OS with SAL */
 enum {
-	SAL_VECTOR_OS_MCA		= 0,
-	SAL_VECTOR_OS_INIT		= 1,
-	SAL_VECTOR_OS_BOOT_RENDEZ	= 2
+	SAL_VECTOR_OS_MCA	  = 0,
+	SAL_VECTOR_OS_INIT	  = 1,
+	SAL_VECTOR_OS_BOOT_RENDEZ = 2
 };
 
 /* Encodings for mca_opt parameter sent to SAL_MC_SET_PARAMS */
@@ -239,387 +239,370 @@
 #define	SAL_MC_PARAM_BINIT_ESCALATE	0x10
 
 /*
-** Definition of the SAL Error Log from the SAL spec
-*/
+ * Definition of the SAL Error Log from the SAL spec
+ */
 
 /* SAL Error Record Section GUID Definitions */
 #define SAL_PROC_DEV_ERR_SECT_GUID  \
-    EFI_GUID ( 0xe429faf1, 0x3cb7, 0x11d4,  0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf1, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_MEM_DEV_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf2, 0x3cb7, 0x11d4,  0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf2, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_SEL_DEV_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf3, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf3, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_PCI_BUS_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf4, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf4, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf5, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf5, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_PCI_COMP_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf6, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf6, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_SPECIFIC_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf7, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf7, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_HOST_CTLR_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf8, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf8, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 #define SAL_PLAT_BUS_ERR_SECT_GUID  \
-    EFI_GUID(  0xe429faf9, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 )
+    EFI_GUID(0xe429faf9, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
 
-#define MAX_CACHE_ERRORS			6
-#define MAX_TLB_ERRORS				6
-#define MAX_BUS_ERRORS				1
+#define MAX_CACHE_ERRORS	6
+#define MAX_TLB_ERRORS		6
+#define MAX_BUS_ERRORS		1
 
 /* Definition of version  according to SAL spec for logging purposes */
-typedef struct sal_log_revision
-{
-    u8  minor;              /* BCD (0..99) */
-    u8  major;              /* BCD (0..99) */
+typedef struct sal_log_revision {
+	u8 minor;		/* BCD (0..99) */
+	u8 major;		/* BCD (0..99) */
 } sal_log_revision_t;
 
 /* Definition of timestamp according to SAL spec for logging purposes */
-typedef struct sal_log_timestamp
-{
+typedef struct sal_log_timestamp {
 	u8 slh_second;		/* Second (0..59) */
-    u8 slh_minute;      /* Minute (0..59) */
-    u8 slh_hour;        /* Hour (0..23) */
-    u8 slh_reserved;
-    u8 slh_day;         /* Day (1..31) */
-    u8 slh_month;       /* Month (1..12) */
-    u8 slh_year;        /* Year (00..99) */
-    u8 slh_century;     /* Century (19, 20, 21, ...) */
+	u8 slh_minute;		/* Minute (0..59) */
+	u8 slh_hour;		/* Hour (0..23) */
+	u8 slh_reserved;
+	u8 slh_day;		/* Day (1..31) */
+	u8 slh_month;		/* Month (1..12) */
+	u8 slh_year;		/* Year (00..99) */
+	u8 slh_century;		/* Century (19, 20, 21, ...) */
 } sal_log_timestamp_t;
 
 /* Definition of log record  header structures */
-typedef struct sal_log_record_header
-{
-    u64                 id;             /* Unique monotonically increasing ID */
-    sal_log_revision_t  revision;       /* Major and Minor revision of header */
-    u16                 severity;       /* Error Severity */
-    u32                 len;            /* Length of this error log in bytes */
-    sal_log_timestamp_t timestamp;      /* Timestamp */
-    efi_guid_t          platform_guid;  /* Unique OEM Platform ID */
+typedef struct sal_log_record_header {
+	u64 id;				/* Unique monotonically increasing ID */
+	sal_log_revision_t revision;	/* Major and Minor revision of header */
+	u16 severity;			/* Error Severity */
+	u32 len;			/* Length of this error log in bytes */
+	sal_log_timestamp_t timestamp;	/* Timestamp */
+	efi_guid_t platform_guid;	/* Unique OEM Platform ID */
 } sal_log_record_header_t;
 
 /* Definition of log section header structures */
-typedef struct sal_log_sec_header
-{
-    efi_guid_t          guid;       /* Unique Section ID */
-    sal_log_revision_t  revision;   /* Major and Minor revision of Section */
-    u16                 reserved;
-    u32                 len;        /* Section length */
+typedef struct sal_log_sec_header {
+    efi_guid_t guid;			/* Unique Section ID */
+    sal_log_revision_t revision;	/* Major and Minor revision of Section */
+    u16 reserved;
+    u32 len;				/* Section length */
 } sal_log_section_hdr_t;
 
-typedef struct sal_log_mod_error_info
-{
-    struct
-    {
-        u64 check_info              : 1,
-            requestor_identifier    : 1,
-            responder_identifier    : 1,
-            target_identifier       : 1,
-            precise_ip              : 1,
-            reserved                : 59;
-    } valid;
-    u64 check_info;
-    u64 requestor_identifier;
-    u64 responder_identifier;
-    u64 target_identifier;
-    u64 precise_ip;
+typedef struct sal_log_mod_error_info {
+	struct {
+		u64 check_info              : 1,
+		    requestor_identifier    : 1,
+		    responder_identifier    : 1,
+		    target_identifier       : 1,
+		    precise_ip              : 1,
+		    reserved                : 59;
+	} valid;
+	u64 check_info;
+	u64 requestor_identifier;
+	u64 responder_identifier;
+	u64 target_identifier;
+	u64 precise_ip;
 } sal_log_mod_error_info_t;
 
-typedef struct sal_processor_static_info
-{
-    struct
-    {
-        u64 minstate        : 1,
-            br              : 1,
-            cr              : 1,
-            ar              : 1,
-            rr              : 1,
-            fr              : 1,
-            reserved        : 58;
-    } valid;
-    pal_min_state_area_t    min_state_area;
-    u64                     br[8];
-    u64                     cr[128];
-    u64                     ar[128];
-    u64                     rr[8];
-    struct ia64_fpreg       fr[128];
+typedef struct sal_processor_static_info {
+	struct {
+		u64 minstate        : 1,
+		    br              : 1,
+		    cr              : 1,
+		    ar              : 1,
+		    rr              : 1,
+		    fr              : 1,
+		    reserved        : 58;
+	} valid;
+	pal_min_state_area_t min_state_area;
+	u64 br[8];
+	u64 cr[128];
+	u64 ar[128];
+	u64 rr[8];
+	struct ia64_fpreg fr[128];
 } sal_processor_static_info_t;
 
-typedef struct sal_log_processor_info
-{
-    sal_log_section_hdr_t       header;
-    struct
-    {
-        u64 proc_error_map      : 1,
-            proc_state_param    : 1,
-            proc_cr_lid         : 1,
-            psi_static_struct   : 1,
-            num_cache_check     : 4,
-            num_tlb_check       : 4,
-            num_bus_check       : 4,
-            num_reg_file_check  : 4,
-            num_ms_check        : 4,
-            cpuid_info          : 1,
-            reserved1           : 39;
-    } valid;
-    u64                         proc_error_map;
-    u64                         proc_state_parameter;
-    u64                         proc_cr_lid;
-    sal_log_mod_error_info_t    cache_check_info[16];
-    sal_log_mod_error_info_t    tlb_check_info[16];
-    sal_log_mod_error_info_t    bus_check_info[16];
-    sal_log_mod_error_info_t    reg_file_check_info[16];
-    sal_log_mod_error_info_t    ms_check_info[16];
-    struct
-    {
-        u64 regs[5];
-        u64 reserved;
-    } cpuid_info;
-    sal_processor_static_info_t processor_static_info;
+struct sal_cpuid_info {
+	u64 regs[5];
+	u64 reserved;
+};
+
+typedef struct sal_log_processor_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 proc_error_map      : 1,
+		    proc_state_param    : 1,
+		    proc_cr_lid         : 1,
+		    psi_static_struct   : 1,
+		    num_cache_check     : 4,
+		    num_tlb_check       : 4,
+		    num_bus_check       : 4,
+		    num_reg_file_check  : 4,
+		    num_ms_check        : 4,
+		    cpuid_info          : 1,
+		    reserved1           : 39;
+	} valid;
+	u64 proc_error_map;
+	u64 proc_state_parameter;
+	u64 proc_cr_lid;
+	/*
+	 * The rest of this structure consists of variable-length arrays, which can't be
+	 * expressed in C.
+	 */
+	sal_log_mod_error_info_t info[0];
+	/*
+	 * This is what the rest looked like if C supported variable-length arrays:
+	 *
+	 * sal_log_mod_error_info_t cache_check_info[.valid.num_cache_check];
+	 * sal_log_mod_error_info_t tlb_check_info[.valid.num_tlb_check];
+	 * sal_log_mod_error_info_t bus_check_info[.valid.num_bus_check];
+	 * sal_log_mod_error_info_t reg_file_check_info[.valid.num_reg_file_check];
+	 * sal_log_mod_error_info_t ms_check_info[.valid.num_ms_check];
+	 * struct sal_cpuid_info cpuid_info;
+	 * sal_processor_static_info_t processor_static_info;
+	 */
 } sal_log_processor_info_t;
 
+/* Given a sal_log_processor_info_t pointer, return a pointer to the processor_static_info: */
+#define SAL_LPI_PSI_INFO(l)									\
+({	sal_log_processor_info_t *_l = (l);							\
+	((sal_processor_static_info_t *)							\
+	 ((char *) _l->info + ((_l->valid.num_cache_check + _l->valid.num_tlb_check		\
+				+ _l->valid.num_bus_check + _l->valid.num_reg_file_check	\
+				+ _l->valid.num_ms_check) * sizeof(sal_log_mod_error_info_t)	\
+			       + sizeof(struct sal_cpuid_info))));				\
+})
+
 /* platform error log structures */
 
-typedef struct sal_log_mem_dev_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 error_status    : 1,
-            physical_addr   : 1,
-            addr_mask       : 1,
-            node            : 1,
-            card            : 1,
-            module          : 1,
-            bank            : 1,
-            device          : 1,
-            row             : 1,
-            column          : 1,
-            bit_position    : 1,
-            requestor_id    : 1,
-            responder_id    : 1,
-            target_id       : 1,
-            bus_spec_data   : 1,
-            oem_id          : 1,
-            oem_data        : 1,
-            reserved        : 47;
-    } valid;
-    u64             error_status;
-    u64             physical_addr;
-    u64             addr_mask;
-    u16             node;
-    u16             card;
-    u16             module;
-    u16             bank;
-    u16             device;
-    u16             row;
-    u16             column;
-    u16             bit_position;
-    u64             requestor_id;
-    u64             responder_id;
-    u64             target_id;
-    u64             bus_spec_data;
-    u8              oem_id[16];
-    u8              oem_data[1];        /* Variable length data */
+typedef struct sal_log_mem_dev_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 error_status    : 1,
+		    physical_addr   : 1,
+		    addr_mask       : 1,
+		    node            : 1,
+		    card            : 1,
+		    module          : 1,
+		    bank            : 1,
+		    device          : 1,
+		    row             : 1,
+		    column          : 1,
+		    bit_position    : 1,
+		    requestor_id    : 1,
+		    responder_id    : 1,
+		    target_id       : 1,
+		    bus_spec_data   : 1,
+		    oem_id          : 1,
+		    oem_data        : 1,
+		    reserved        : 47;
+	} valid;
+	u64 error_status;
+	u64 physical_addr;
+	u64 addr_mask;
+	u16 node;
+	u16 card;
+	u16 module;
+	u16 bank;
+	u16 device;
+	u16 row;
+	u16 column;
+	u16 bit_position;
+	u64 requestor_id;
+	u64 responder_id;
+	u64 target_id;
+	u64 bus_spec_data;
+	u8 oem_id[16];
+	u8 oem_data[1];			/* Variable length data */
 } sal_log_mem_dev_err_info_t;
 
-typedef struct sal_log_sel_dev_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 record_id       : 1,
-            record_type     : 1,
-            generator_id    : 1,
-            evm_rev         : 1,
-            sensor_type     : 1,
-            sensor_num      : 1,
-            event_dir       : 1,
-            event_data1     : 1,
-            event_data2     : 1,
-            event_data3     : 1,
-            reserved        : 54;
-    } valid;
-    u16             record_id;
-    u8              record_type;
-    u8              timestamp[4];
-    u16             generator_id;
-    u8              evm_rev;
-    u8              sensor_type;
-    u8              sensor_num;
-    u8              event_dir;
-    u8              event_data1;
-    u8              event_data2;
-    u8              event_data3;
+typedef struct sal_log_sel_dev_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 record_id       : 1,
+		    record_type     : 1,
+		    generator_id    : 1,
+		    evm_rev         : 1,
+		    sensor_type     : 1,
+		    sensor_num      : 1,
+		    event_dir       : 1,
+		    event_data1     : 1,
+		    event_data2     : 1,
+		    event_data3     : 1,
+		    reserved        : 54;
+	} valid;
+	u16 record_id;
+	u8 record_type;
+	u8 timestamp[4];
+	u16 generator_id;
+	u8 evm_rev;
+	u8 sensor_type;
+	u8 sensor_num;
+	u8 event_dir;
+	u8 event_data1;
+	u8 event_data2;
+	u8 event_data3;
 } sal_log_sel_dev_err_info_t;
 
-typedef struct sal_log_pci_bus_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 err_status      : 1,
-            err_type        : 1,
-            bus_id          : 1,
-            bus_address     : 1,
-            bus_data        : 1,
-            bus_cmd         : 1,
-            requestor_id    : 1,
-            responder_id    : 1,
-            target_id       : 1,
-            oem_data        : 1,
-            reserved        : 54;
-    } valid;
-    u64             err_status;
-    u16             err_type;
-    u16             bus_id;
-    u32             reserved;
-    u64             bus_address;
-    u64             bus_data;
-    u64             bus_cmd;
-    u64             requestor_id;
-    u64             responder_id;
-    u64             target_id;
-    u8              oem_data[1];        /* Variable length data */
+typedef struct sal_log_pci_bus_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 err_status      : 1,
+		    err_type        : 1,
+		    bus_id          : 1,
+		    bus_address     : 1,
+		    bus_data        : 1,
+		    bus_cmd         : 1,
+		    requestor_id    : 1,
+		    responder_id    : 1,
+		    target_id       : 1,
+		    oem_data        : 1,
+		    reserved        : 54;
+	} valid;
+	u64 err_status;
+	u16 err_type;
+	u16 bus_id;
+	u32 reserved;
+	u64 bus_address;
+	u64 bus_data;
+	u64 bus_cmd;
+	u64 requestor_id;
+	u64 responder_id;
+	u64 target_id;
+	u8 oem_data[1];			/* Variable length data */
 } sal_log_pci_bus_err_info_t;
 
-typedef struct sal_log_smbios_dev_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 event_type      : 1,
-            length          : 1,
-            time_stamp      : 1,
-            data            : 1,
-            reserved1       : 60;
-    } valid;
-    u8              event_type;
-    u8              length;
-    u8              time_stamp[6];
-    u8              data[1];  // data of variable length, length == slsmb_length
+typedef struct sal_log_smbios_dev_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 event_type      : 1,
+		    length          : 1,
+		    time_stamp      : 1,
+		    data            : 1,
+		    reserved1       : 60;
+	} valid;
+	u8 event_type;
+	u8 length;
+	u8 time_stamp[6];
+	u8 data[1];			/* data of variable length, length == slsmb_length */
 } sal_log_smbios_dev_err_info_t;
 
-typedef struct sal_log_pci_comp_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 err_status      : 1,
-            comp_info       : 1,
-            num_mem_regs    : 1,
-            num_io_regs     : 1,
-            reg_data_pairs  : 1,
-            oem_data        : 1,
-            reserved        : 58;
-    } valid;
-    u64             err_status;
-    struct
-    {
-        u16 vendor_id;
-        u16 device_id;
-	u8  class_code[3];
-        u8  func_num;
-        u8  dev_num;
-        u8  bus_num;
-        u8  seg_num;
-        u8  reserved[5];
-    }               comp_info;
-    u32             num_mem_regs;
-    u32             num_io_regs;
-    u64             reg_data_pairs[1];
-    /* array of address/data register pairs is num_mem_regs + num_io_regs
-       elements long.  Each array element consists of a u64 address followed
-       by a u64 data value.  The oem_data array immediately follows the
-       reg_data_pairs array */
-    u8              oem_data[1];        /* Variable length data */
+typedef struct sal_log_pci_comp_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 err_status      : 1,
+		    comp_info       : 1,
+		    num_mem_regs    : 1,
+		    num_io_regs     : 1,
+		    reg_data_pairs  : 1,
+		    oem_data        : 1,
+		    reserved        : 58;
+	} valid;
+	u64 err_status;
+	struct {
+		u16 vendor_id;
+		u16 device_id;
+		u8 class_code[3];
+		u8 func_num;
+		u8 dev_num;
+		u8 bus_num;
+		u8 seg_num;
+		u8 reserved[5];
+	} comp_info;
+	u32 num_mem_regs;
+	u32 num_io_regs;
+	u64 reg_data_pairs[1];
+	/*
+	 * array of address/data register pairs is num_mem_regs + num_io_regs elements
+	 * long.  Each array element consists of a u64 address followed by a u64 data
+	 * value.  The oem_data array immediately follows the reg_data_pairs array
+	 */
+	u8 oem_data[1];			/* Variable length data */
 } sal_log_pci_comp_err_info_t;
 
-typedef struct sal_log_plat_specific_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 err_status      : 1,
-            guid            : 1,
-            oem_data        : 1,
-            reserved        : 61;
-    } valid;
-    u64             err_status;
-    efi_guid_t      guid;
-    u8              oem_data[1];      /* platform specific variable length data */
+typedef struct sal_log_plat_specific_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 err_status      : 1,
+		    guid            : 1,
+		    oem_data        : 1,
+		    reserved        : 61;
+	} valid;
+	u64 err_status;
+	efi_guid_t guid;
+	u8 oem_data[1];			/* platform specific variable length data */
 } sal_log_plat_specific_err_info_t;
 
-typedef struct sal_log_host_ctlr_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 err_status      : 1,
-            requestor_id    : 1,
-            responder_id    : 1,
-            target_id       : 1,
-            bus_spec_data   : 1,
-            oem_data        : 1,
-            reserved        : 58;
-    } valid;
-    u64             err_status;
-    u64             requestor_id;
-    u64             responder_id;
-    u64             target_id;
-    u64             bus_spec_data;
-    u8              oem_data[1];        /* Variable length OEM data */
+typedef struct sal_log_host_ctlr_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 err_status      : 1,
+		    requestor_id    : 1,
+		    responder_id    : 1,
+		    target_id       : 1,
+		    bus_spec_data   : 1,
+		    oem_data        : 1,
+		    reserved        : 58;
+	} valid;
+	u64 err_status;
+	u64 requestor_id;
+	u64 responder_id;
+	u64 target_id;
+	u64 bus_spec_data;
+	u8 oem_data[1];			/* Variable length OEM data */
 } sal_log_host_ctlr_err_info_t;
 
-typedef struct sal_log_plat_bus_err_info
-{
-    sal_log_section_hdr_t   header;
-    struct
-    {
-        u64 err_status      : 1,
-            requestor_id    : 1,
-            responder_id    : 1,
-            target_id       : 1,
-            bus_spec_data   : 1,
-            oem_data        : 1,
-            reserved        : 58;
-    } valid;
-    u64             err_status;
-    u64             requestor_id;
-    u64             responder_id;
-    u64             target_id;
-    u64             bus_spec_data;
-    u8              oem_data[1];        /* Variable length OEM data */
+typedef struct sal_log_plat_bus_err_info {
+	sal_log_section_hdr_t header;
+	struct {
+		u64 err_status      : 1,
+		    requestor_id    : 1,
+		    responder_id    : 1,
+		    target_id       : 1,
+		    bus_spec_data   : 1,
+		    oem_data        : 1,
+		    reserved        : 58;
+	} valid;
+	u64 err_status;
+	u64 requestor_id;
+	u64 responder_id;
+	u64 target_id;
+	u64 bus_spec_data;
+	u8 oem_data[1];			/* Variable length OEM data */
 } sal_log_plat_bus_err_info_t;
 
 /* Overall platform error section structure */
-typedef union sal_log_platform_err_info
-{
-    sal_log_mem_dev_err_info_t          mem_dev_err;
-    sal_log_sel_dev_err_info_t          sel_dev_err;
-    sal_log_pci_bus_err_info_t          pci_bus_err;
-    sal_log_smbios_dev_err_info_t       smbios_dev_err;
-    sal_log_pci_comp_err_info_t         pci_comp_err;
-    sal_log_plat_specific_err_info_t    plat_specific_err;
-    sal_log_host_ctlr_err_info_t        host_ctlr_err;
-    sal_log_plat_bus_err_info_t         plat_bus_err;
+typedef union sal_log_platform_err_info {
+	sal_log_mem_dev_err_info_t mem_dev_err;
+	sal_log_sel_dev_err_info_t sel_dev_err;
+	sal_log_pci_bus_err_info_t pci_bus_err;
+	sal_log_smbios_dev_err_info_t smbios_dev_err;
+	sal_log_pci_comp_err_info_t pci_comp_err;
+	sal_log_plat_specific_err_info_t plat_specific_err;
+	sal_log_host_ctlr_err_info_t host_ctlr_err;
+	sal_log_plat_bus_err_info_t plat_bus_err;
 } sal_log_platform_err_info_t;
 
 /* SAL log over-all, multi-section error record structure (processor+platform) */
-typedef struct err_rec
-{
-    sal_log_record_header_t     sal_elog_header;
-    sal_log_processor_info_t    proc_err;
-    sal_log_platform_err_info_t plat_err;
-    u8                          oem_data_pad[1024];
+typedef struct err_rec {
+	sal_log_record_header_t sal_elog_header;
+	sal_log_processor_info_t proc_err;
+	sal_log_platform_err_info_t plat_err;
+	u8 oem_data_pad[1024];
 } ia64_err_rec_t;
 
 /*
@@ -648,7 +631,6 @@
 }
 
 
-	
 /* Initialize all the processor and platform level instruction and data caches */
 static inline s64
 ia64_sal_cache_init (void)
@@ -658,8 +640,9 @@
 	return isrv.status;
 }
 
-/* Clear the processor and platform information logged by SAL with respect to the 
- * machine state at the time of MCA's, INITs, CMCs, or CPEs.
+/*
+ * Clear the processor and platform information logged by SAL with respect to the machine
+ * state at the time of MCA's, INITs, CMCs, or CPEs.
  */
 static inline s64
 ia64_sal_clear_state_info (u64 sal_info_type)
@@ -684,9 +667,11 @@
 		return 0;
 
 	return isrv.v0;
-}	
-/* Get the maximum size of the information logged by SAL with respect to the machine 
- * state at the time of MCAs, INITs, CMCs, or CPEs.
+}
+
+/*
+ * Get the maximum size of the information logged by SAL with respect to the machine state
+ * at the time of MCAs, INITs, CMCs, or CPEs.
  */
 static inline u64
 ia64_sal_get_state_info_size (u64 sal_info_type)
@@ -699,8 +684,9 @@
 	return isrv.v0;
 }
 
-/* Causes the processor to go into a spin loop within SAL where SAL awaits a wakeup
- * from the monarch processor.
+/*
+ * Causes the processor to go into a spin loop within SAL where SAL awaits a wakeup from
+ * the monarch processor.
  */
 static inline s64
 ia64_sal_mc_rendez (void)
@@ -710,15 +696,17 @@
 	return isrv.status;
 }
 
-/* Allow the OS to specify the interrupt number to be used by SAL to interrupt OS during
- * the machine check rendezvous sequence as well as the mechanism to wake up the 
+/*
+ * Allow the OS to specify the interrupt number to be used by SAL to interrupt OS during
+ * the machine check rendezvous sequence as well as the mechanism to wake up the
  * non-monarch processor at the end of machine check processing.
  */
 static inline s64
 ia64_sal_mc_set_params (u64 param_type, u64 i_or_m, u64 i_or_m_val, u64 timeout, u64 rz_always)
 {
 	struct ia64_sal_retval isrv;
-	SAL_CALL(isrv, SAL_MC_SET_PARAMS, param_type, i_or_m, i_or_m_val, timeout, rz_always, 0, 0);
+	SAL_CALL(isrv, SAL_MC_SET_PARAMS, param_type, i_or_m, i_or_m_val,
+		 timeout, rz_always, 0, 0);
 	return isrv.status;
 }
 
@@ -744,8 +732,8 @@
 }
 
 /*
- * Register physical addresses of locations needed by SAL when SAL
- * procedures are invoked in virtual mode.
+ * Register physical addresses of locations needed by SAL when SAL procedures are invoked
+ * in virtual mode.
  */
 static inline s64
 ia64_sal_register_physical_addr (u64 phys_entry, u64 phys_addr)
@@ -756,9 +744,10 @@
 	return isrv.status;
 }
 
-/* Register software dependent code locations within SAL. These locations are handlers
- * or entry points where SAL will pass control for the specified event. These event
- * handlers are for the bott rendezvous, MCAs and INIT scenarios.
+/*
+ * Register software dependent code locations within SAL. These locations are handlers or
+ * entry points where SAL will pass control for the specified event. These event handlers
+ * are for the bott rendezvous, MCAs and INIT scenarios.
  */
 static inline s64
 ia64_sal_set_vectors (u64 vector_type,
@@ -768,10 +757,11 @@
 	struct ia64_sal_retval isrv;
 	SAL_CALL(isrv, SAL_SET_VECTORS, vector_type,
 			handler_addr1, gp1, handler_len1,
-			handler_addr2, gp2, handler_len2);			
+			handler_addr2, gp2, handler_len2);
 
 	return isrv.status;
-}		
+}
+
 /* Update the contents of PAL block in the non-volatile storage device */
 static inline s64
 ia64_sal_update_pal (u64 param_buf, u64 scratch_buf, u64 scratch_buf_size,
diff -Nru a/include/asm-ia64/siginfo.h b/include/asm-ia64/siginfo.h
--- a/include/asm-ia64/siginfo.h	Tue Sep 24 12:15:49 2002
+++ b/include/asm-ia64/siginfo.h	Thu Mar  6 21:11:46 2003
@@ -33,8 +33,11 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;		/* timer id */
+			int _overrun;		/* overrun count */
+			char _pad[sizeof(__ARCH_SI_UID_T) - sizeof(int)];
+			sigval_t _sigval;	/* must overlay ._rt._sigval! */
+			int _sys_private;	/* not to be passed to user */
 		} _timer;
 
 		/* POSIX.1b signals */
diff -Nru a/include/asm-ia64/sn/geo.h b/include/asm-ia64/sn/geo.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ia64/sn/geo.h	Mon Feb 24 04:35:17 2003
@@ -0,0 +1,54 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#ifndef __SYS_GEO_H__
+#define __SYS_GEO_H__
+
+/* Include a platform-specific geo.h.  It must define at least:
+ *   geoid_t:		Geographic identifier data type
+ *   geo_type_t:	Data type for the kind of geoid this is
+ *   GEO_TYPE_xxx:	Values for geo_type_t vars, eg. GEO_TYPE_NODE
+ *   GEO_MAX_LEN:	The maximum length of a geoid, formatted for printing
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_IA64_SGI_SN2
+#include <asm/sn/sn2/geo.h>
+#else
+
+#error <<BOMB! need geo.h for this platform >>
+
+#endif /* !SN2 && ... */
+
+/* Declarations applicable to all platforms */
+
+/* parameter for hwcfg_format_geoid() */
+#define GEO_FORMAT_HWGRAPH	1
+#define GEO_FORMAT_BRIEF	2
+
+/* (the parameter for hwcfg_format_geoid_compt() is defined in the
+ * platform-specific geo.h file) */
+
+/* Routines for manipulating geoid_t values */
+
+extern moduleid_t geo_module(geoid_t g);
+extern slabid_t geo_slab(geoid_t g);
+extern geo_type_t geo_type(geoid_t g);
+extern int geo_valid(geoid_t g);
+extern int geo_cmp(geoid_t g0, geoid_t g1);
+extern geoid_t geo_new(geo_type_t type, ...);
+
+extern geoid_t hwcfg_parse_geoid(char *buffer);
+extern void hwcfg_format_geoid(char *buffer, geoid_t m, int fmt);
+extern void hwcfg_format_geoid_compt(char *buffer, geoid_t m, int compt);
+extern geoid_t hwcfg_geo_get_self(geo_type_t type);
+extern geoid_t hwcfg_geo_get_by_nasid(geo_type_t type, nasid_t nasid);
+
+#endif /* __SYS_GEO_H__ */
diff -Nru a/include/asm-ia64/sn/ioconfig_bus.h b/include/asm-ia64/sn/ioconfig_bus.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ia64/sn/ioconfig_bus.h	Mon Feb 24 04:55:34 2003
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of version 2 of the GNU General Public License 
+ * as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * 
+ * Further, this software is distributed without any warranty that it is 
+ * free of the rightful claim of any third person regarding infringement 
+ * or the like.  Any license provided herein, whether implied or 
+ * otherwise, applies only to this software file.  Patent licenses, if 
+ * any, provided herein do not apply to combinations of this program with 
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program; if not, write the Free Software 
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#define IOCONFIG_PCIBUS "/boot/efi/ioconfig_pcibus"
+#define POUND_CHAR                   '#'
+#define MAX_LINE_LEN	128
+#define MAXPATHLEN	128
+
+struct ioconfig_parm {
+	unsigned long ioconfig_activated;
+        unsigned long number;
+        void *buffer;
+};
+
+struct  ascii_moduleid{
+                unsigned char   io_moduleid[8]; /* pci path name */
+};
diff -Nru a/include/asm-ia64/sn/module.h b/include/asm-ia64/sn/module.h
--- a/include/asm-ia64/sn/module.h	Tue Dec  3 10:07:33 2002
+++ b/include/asm-ia64/sn/module.h	Mon Feb 24 05:28:24 2003
@@ -273,6 +273,9 @@
     cnodeid_t		nodes[MODULE_MAX_NODES];
 #ifdef CONFIG_IA64_SGI_SN2
     geoid_t		geoid[MODULE_MAX_NODES];
+    struct {
+		char	moduleid[8];
+    } io[MODULE_MAX_NODES];
 #endif
     int			nodecnt;	/* Number of nodes in array        */
 
diff -Nru a/include/asm-ia64/sn/pci/pic.h b/include/asm-ia64/sn/pci/pic.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ia64/sn/pci/pic.h	Mon Feb 24 04:49:11 2003
@@ -0,0 +1,2001 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+#ifndef _ASM_SN_PCI_PIC_H
+#define _ASM_SN_PCI_PIC_H
+
+
+/*
+ * The PIC ASIC is a follow-on to the Bridge and Xbridge ASICs.
+ * It shares many of the same registers as those chips and therefore
+ * the primary structure for the PIC will be bridge_s as defined
+ * in irix/kern/sys/PCI/bridge.h.   This file is intended as a complement
+ * to bridge.h, which includes this file.  
+ */
+
+/*
+ * PIC AS DEVICE ZERO
+ * ------------------
+ *
+ * PIC handles PCI/X busses.  PCI/X requires that the 'bridge' (i.e. PIC)
+ * be designated as 'device 0'.   That is a departure from earlier SGI
+ * PCI bridges.  Because of that we use config space 1 to access the
+ * config space of the first actual PCI device on the bus. 
+ * Here's what the PIC manual says:
+ *
+ *     The current PCI-X bus specification now defines that the parent
+ *     hosts bus bridge (PIC for example) must be device 0 on bus 0. PIC
+ *     reduced the total number of devices from 8 to 4 and removed the
+ *     device registers and windows, now only supporting devices 0,1,2, and
+ *     3. PIC did leave all 8 configuration space windows. The reason was
+ *     there was nothing to gain by removing them. Here in lies the problem.
+ *     The device numbering we do using 0 through 3 is unrelated to the device
+ *     numbering which PCI-X requires in configuration space. In the past we
+ *     correlated Configs pace and our device space 0 <-> 0, 1 <-> 1, etc.
+ *     PCI-X requires we start a 1, not 0 and currently the PX brick
+ *     does associate our:
+ * 
+ *         device 0 with configuration space window 1,
+ *         device 1 with configuration space window 2, 
+ *         device 2 with configuration space window 3,
+ *         device 3 with configuration space window 4.
+ *
+ * The net effect is that all config space access are off-by-one with 
+ * relation to other per-slot accesses on the PIC.   
+ * Here is a table that shows some of that:
+ *
+ *                               Internal Slot#
+ *           |
+ *           |     0         1        2         3
+ * ----------|---------------------------------------
+ * config    |  0x21000   0x22000  0x23000   0x24000
+ *           |
+ * even rrb  |  0[0]      n/a      1[0]      n/a	[] == implied even/odd
+ *           |
+ * odd rrb   |  n/a       0[1]     n/a       1[1]
+ *           |
+ * int dev   |  00       01        10        11
+ *           |
+ * ext slot# |  1        2         3         4
+ * ----------|---------------------------------------
+ */
+
+
+#ifndef __ASSEMBLY__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// #include <sys/types.h>
+#include <asm/sn/pci/pciio.h>
+
+
+/*********************************************************************
+ *    bus provider function table
+ *
+ *	Normally, this table is only handed off explicitly
+ *	during provider initialization, and the PCI generic
+ *	layer will stash a pointer to it in the vertex; however,
+ *	exporting it explicitly enables a performance hack in
+ *	the generic PCI provider where if we know at compile
+ *	time that the only possible PCI provider is a
+ *	pcibr, we can go directly to this ops table.
+ */
+
+extern pciio_provider_t pci_pic_provider;
+
+
+/*********************************************************************
+ * misc defines
+ *
+ */
+#define PIC_WIDGET_PART_NUM_BUS0 0xd102
+#define PIC_WIDGET_PART_NUM_BUS1 0xd112
+#define PIC_WIDGET_MFGR_NUM 0x24
+#define PIC_WIDGET_REV_A  0x1
+
+#define IS_PIC_PART_REV_A(rev) \
+	((rev == (PIC_WIDGET_PART_NUM_BUS0 << 4 | PIC_WIDGET_REV_A)) || \
+	(rev == (PIC_WIDGET_PART_NUM_BUS1 << 4 | PIC_WIDGET_REV_A)))
+
+/*********************************************************************
+ * register offset defines
+ *
+ */
+	/* Identification Register  -- read-only */
+#define PIC_IDENTIFICATION 0x00000000
+
+	/* Status Register  -- read-only */
+#define PIC_STATUS 0x00000008
+
+	/* Upper Address Holding Register Bus Side Errors  -- read-only */
+#define PIC_UPPER_ADDR_REG_BUS_SIDE_ERRS 0x00000010
+
+	/* Lower Address Holding Register Bus Side Errors  -- read-only */
+#define PIC_LOWER_ADDR_REG_BUS_SIDE_ERRS 0x00000018
+
+	/* Control Register  -- read/write */
+#define PIC_CONTROL 0x00000020
+
+	/* PCI Request Time-out Value Register  -- read/write */
+#define PIC_PCI_REQ_TIME_OUT_VALUE 0x00000028
+
+	/* Interrupt Destination Upper Address Register  -- read/write */
+#define PIC_INTR_DEST_UPPER_ADDR 0x00000030
+
+	/* Interrupt Destination Lower Address Register  -- read/write */
+#define PIC_INTR_DEST_LOWER_ADDR 0x00000038
+
+	/* Command Word Holding Register Bus Side  -- read-only */
+#define PIC_CMD_WORD_REG_BUS_SIDE 0x00000040
+
+	/* LLP Configuration Register (Bus 0 Only)  -- read/write */
+#define PIC_LLP_CFG_REG_(BUS_0_ONLY) 0x00000048
+
+	/* PCI Target Flush Register  -- read-only */
+#define PIC_PCI_TARGET_FLUSH 0x00000050
+
+	/* Command Word Holding Register Link Side  -- read-only */
+#define PIC_CMD_WORD_REG_LINK_SIDE 0x00000058
+
+	/* Response Buffer Error Upper Address Holding  -- read-only */
+#define PIC_RESP_BUF_ERR_UPPER_ADDR_ 0x00000060
+
+	/* Response Buffer Error Lower Address Holding  -- read-only */
+#define PIC_RESP_BUF_ERR_LOWER_ADDR_ 0x00000068
+
+	/* Test Pin Control Register  -- read/write */
+#define PIC_TEST_PIN_CONTROL 0x00000070
+
+	/* Address Holding Register Link Side Errors  -- read-only */
+#define PIC_ADDR_REG_LINK_SIDE_ERRS 0x00000078
+
+	/* Direct Map Register  -- read/write */
+#define PIC_DIRECT_MAP 0x00000080
+
+	/* PCI Map Fault Address Register  -- read-only */
+#define PIC_PCI_MAP_FAULT_ADDR 0x00000090
+
+	/* Arbitration Priority Register  -- read/write */
+#define PIC_ARBITRATION_PRIORITY 0x000000A0
+
+	/* Internal Ram Parity Error Register  -- read-only */
+#define PIC_INTERNAL_RAM_PARITY_ERR 0x000000B0
+
+	/* PCI Time-out Register  -- read/write */
+#define PIC_PCI_TIME_OUT 0x000000C0
+
+	/* PCI Type 1 Configuration Register  -- read/write */
+#define PIC_PCI_TYPE_1_CFG 0x000000C8
+
+	/* PCI Bus Error Upper Address Holding Register  -- read-only */
+#define PIC_PCI_BUS_ERR_UPPER_ADDR_ 0x000000D0
+
+	/* PCI Bus Error Lower Address Holding Register  -- read-only */
+#define PIC_PCI_BUS_ERR_LOWER_ADDR_ 0x000000D8
+
+	/* PCIX Error Address Register  -- read-only */
+#define PIC_PCIX_ERR_ADDR 0x000000E0
+
+	/* PCIX Error Attribute Register  -- read-only */
+#define PIC_PCIX_ERR_ATTRIBUTE 0x000000E8
+
+	/* PCIX Error Data Register  -- read-only */
+#define PIC_PCIX_ERR_DATA 0x000000F0
+
+	/* PCIX Read Request Timeout Error Register  -- read-only */
+#define PIC_PCIX_READ_REQ_TIMEOUT_ERR 0x000000F8
+
+	/* Interrupt Status Register  -- read-only */
+#define PIC_INTR_STATUS 0x00000100
+
+	/* Interrupt Enable Register  -- read/write */
+#define PIC_INTR_ENABLE 0x00000108
+
+	/* Reset Interrupt Status Register  -- write-only */
+#define PIC_RESET_INTR_STATUS 0x00000110
+
+	/* Interrupt Mode Register  -- read/write */
+#define PIC_INTR_MODE 0x00000118
+
+	/* Interrupt Device Register  -- read/write */
+#define PIC_INTR_DEVICE 0x00000120
+
+	/* Host Error Field Register  -- read/write */
+#define PIC_HOST_ERR_FIELD 0x00000128
+
+	/* Interrupt Pin 0 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_0_HOST_ADDR 0x00000130
+
+	/* Interrupt Pin 1 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_1_HOST_ADDR 0x00000138
+
+	/* Interrupt Pin 2 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_2_HOST_ADDR 0x00000140
+
+	/* Interrupt Pin 3 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_3_HOST_ADDR 0x00000148
+
+	/* Interrupt Pin 4 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_4_HOST_ADDR 0x00000150
+
+	/* Interrupt Pin 5 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_5_HOST_ADDR 0x00000158
+
+	/* Interrupt Pin 6 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_6_HOST_ADDR 0x00000160
+
+	/* Interrupt Pin 7 Host Address Register  -- read/write */
+#define PIC_INTR_PIN_7_HOST_ADDR 0x00000168
+
+	/* Error Interrupt View Register  -- read-only */
+#define PIC_ERR_INTR_VIEW 0x00000170
+
+	/* Multiple Interrupt Register  -- read-only */
+#define PIC_MULTIPLE_INTR 0x00000178
+
+	/* Force Always Interrupt 0 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_0 0x00000180
+
+	/* Force Always Interrupt 1 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_1 0x00000188
+
+	/* Force Always Interrupt 2 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_2 0x00000190
+
+	/* Force Always Interrupt 3 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_3 0x00000198
+
+	/* Force Always Interrupt 4 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_4 0x000001A0
+
+	/* Force Always Interrupt 5 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_5 0x000001A8
+
+	/* Force Always Interrupt 6 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_6 0x000001B0
+
+	/* Force Always Interrupt 7 Register  -- write-only */
+#define PIC_FORCE_ALWAYS_INTR_7 0x000001B8
+
+	/* Force w/Pin Interrupt 0 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_0 0x000001C0
+
+	/* Force w/Pin Interrupt 1 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_1 0x000001C8
+
+	/* Force w/Pin Interrupt 2 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_2 0x000001D0
+
+	/* Force w/Pin Interrupt 3 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_3 0x000001D8
+
+	/* Force w/Pin Interrupt 4 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_4 0x000001E0
+
+	/* Force w/Pin Interrupt 5 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_5 0x000001E8
+
+	/* Force w/Pin Interrupt 6 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_6 0x000001F0
+
+	/* Force w/Pin Interrupt 7 Register  -- write-only */
+#define PIC_FORCE_PIN_INTR_7 0x000001F8
+
+	/* Device 0 Register  -- read/write */
+#define PIC_DEVICE_0 0x00000200
+
+	/* Device 1 Register  -- read/write */
+#define PIC_DEVICE_1 0x00000208
+
+	/* Device 2 Register  -- read/write */
+#define PIC_DEVICE_2 0x00000210
+
+	/* Device 3 Register  -- read/write */
+#define PIC_DEVICE_3 0x00000218
+
+	/* Device 0 Write Request Buffer Register  -- read-only */
+#define PIC_DEVICE_0_WRITE_REQ_BUF 0x00000240
+
+	/* Device 1 Write Request Buffer Register  -- read-only */
+#define PIC_DEVICE_1_WRITE_REQ_BUF 0x00000248
+
+	/* Device 2 Write Request Buffer Register  -- read-only */
+#define PIC_DEVICE_2_WRITE_REQ_BUF 0x00000250
+
+	/* Device 3 Write Request Buffer Register  -- read-only */
+#define PIC_DEVICE_3_WRITE_REQ_BUF 0x00000258
+
+	/* Even Device Response Buffer Register  -- read/write */
+#define PIC_EVEN_DEVICE_RESP_BUF 0x00000280
+
+	/* Odd Device Response Buffer Register  -- read/write */
+#define PIC_ODD_DEVICE_RESP_BUF 0x00000288
+
+	/* Read Response Buffer Status Register  -- read-only */
+#define PIC_READ_RESP_BUF_STATUS 0x00000290
+
+	/* Read Response Buffer Clear Register  -- write-only */
+#define PIC_READ_RESP_BUF_CLEAR 0x00000298
+
+	/* PCI RR 0 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_0_UPPER_ADDR_MATCH 0x00000300
+
+	/* PCI RR 0 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_0_LOWER_ADDR_MATCH 0x00000308
+
+	/* PCI RR 1 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_1_UPPER_ADDR_MATCH 0x00000310
+
+	/* PCI RR 1 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_1_LOWER_ADDR_MATCH 0x00000318
+
+	/* PCI RR 2 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_2_UPPER_ADDR_MATCH 0x00000320
+
+	/* PCI RR 2 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_2_LOWER_ADDR_MATCH 0x00000328
+
+	/* PCI RR 3 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_3_UPPER_ADDR_MATCH 0x00000330
+
+	/* PCI RR 3 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_3_LOWER_ADDR_MATCH 0x00000338
+
+	/* PCI RR 4 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_4_UPPER_ADDR_MATCH 0x00000340
+
+	/* PCI RR 4 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_4_LOWER_ADDR_MATCH 0x00000348
+
+	/* PCI RR 5 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_5_UPPER_ADDR_MATCH 0x00000350
+
+	/* PCI RR 5 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_5_LOWER_ADDR_MATCH 0x00000358
+
+	/* PCI RR 6 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_6_UPPER_ADDR_MATCH 0x00000360
+
+	/* PCI RR 6 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_6_LOWER_ADDR_MATCH 0x00000368
+
+	/* PCI RR 7 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_7_UPPER_ADDR_MATCH 0x00000370
+
+	/* PCI RR 7 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_7_LOWER_ADDR_MATCH 0x00000378
+
+	/* PCI RR 8 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_8_UPPER_ADDR_MATCH 0x00000380
+
+	/* PCI RR 8 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_8_LOWER_ADDR_MATCH 0x00000388
+
+	/* PCI RR 9 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_9_UPPER_ADDR_MATCH 0x00000390
+
+	/* PCI RR 9 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_9_LOWER_ADDR_MATCH 0x00000398
+
+	/* PCI RR 10 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_10_UPPER_ADDR_MATCH 0x000003A0
+
+	/* PCI RR 10 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_10_LOWER_ADDR_MATCH 0x000003A8
+
+	/* PCI RR 11 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_11_UPPER_ADDR_MATCH 0x000003B0
+
+	/* PCI RR 11 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_11_LOWER_ADDR_MATCH 0x000003B8
+
+	/* PCI RR 12 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_12_UPPER_ADDR_MATCH 0x000003C0
+
+	/* PCI RR 12 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_12_LOWER_ADDR_MATCH 0x000003C8
+
+	/* PCI RR 13 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_13_UPPER_ADDR_MATCH 0x000003D0
+
+	/* PCI RR 13 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_13_LOWER_ADDR_MATCH 0x000003D8
+
+	/* PCI RR 14 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_14_UPPER_ADDR_MATCH 0x000003E0
+
+	/* PCI RR 14 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_14_LOWER_ADDR_MATCH 0x000003E8
+
+	/* PCI RR 15 Upper Address Match Register  -- read-only */
+#define PIC_PCI_RR_15_UPPER_ADDR_MATCH 0x000003F0
+
+	/* PCI RR 15 Lower Address Match Register  -- read-only */
+#define PIC_PCI_RR_15_LOWER_ADDR_MATCH 0x000003F8
+
+	/* Buffer 0 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_0_FLUSH_CNT_WITH_DATA_TOUCH 0x00000400
+
+	/* Buffer 0 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_0_FLUSH_CNT_W_O_DATA_TOUCH 0x00000408
+
+	/* Buffer 0 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_0_REQ_IN_FLIGHT_CNT 0x00000410
+
+	/* Buffer 0 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_0_PREFETCH_REQ_CNT 0x00000418
+
+	/* Buffer 0 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_0_TOTAL_PCI_RETRY_CNT 0x00000420
+
+	/* Buffer 0 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_0_MAX_PCI_RETRY_CNT 0x00000428
+
+	/* Buffer 0 Max Latency Count Register  -- read/write */
+#define PIC_BUF_0_MAX_LATENCY_CNT 0x00000430
+
+	/* Buffer 0 Clear All Register  -- read/write */
+#define PIC_BUF_0_CLEAR_ALL 0x00000438
+
+	/* Buffer 2 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_2_FLUSH_CNT_WITH_DATA_TOUCH 0x00000440
+
+	/* Buffer 2 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_2_FLUSH_CNT_W_O_DATA_TOUCH 0x00000448
+
+	/* Buffer 2 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_2_REQ_IN_FLIGHT_CNT 0x00000450
+
+	/* Buffer 2 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_2_PREFETCH_REQ_CNT 0x00000458
+
+	/* Buffer 2 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_2_TOTAL_PCI_RETRY_CNT 0x00000460
+
+	/* Buffer 2 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_2_MAX_PCI_RETRY_CNT 0x00000468
+
+	/* Buffer 2 Max Latency Count Register  -- read/write */
+#define PIC_BUF_2_MAX_LATENCY_CNT 0x00000470
+
+	/* Buffer 2 Clear All Register  -- read/write */
+#define PIC_BUF_2_CLEAR_ALL 0x00000478
+
+	/* Buffer 4 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_4_FLUSH_CNT_WITH_DATA_TOUCH 0x00000480
+
+	/* Buffer 4 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_4_FLUSH_CNT_W_O_DATA_TOUCH 0x00000488
+
+	/* Buffer 4 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_4_REQ_IN_FLIGHT_CNT 0x00000490
+
+	/* Buffer 4 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_4_PREFETCH_REQ_CNT 0x00000498
+
+	/* Buffer 4 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_4_TOTAL_PCI_RETRY_CNT 0x000004A0
+
+	/* Buffer 4 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_4_MAX_PCI_RETRY_CNT 0x000004A8
+
+	/* Buffer 4 Max Latency Count Register  -- read/write */
+#define PIC_BUF_4_MAX_LATENCY_CNT 0x000004B0
+
+	/* Buffer 4 Clear All Register  -- read/write */
+#define PIC_BUF_4_CLEAR_ALL 0x000004B8
+
+	/* Buffer 6 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_6_FLUSH_CNT_WITH_DATA_TOUCH 0x000004C0
+
+	/* Buffer 6 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_6_FLUSH_CNT_W_O_DATA_TOUCH 0x000004C8
+
+	/* Buffer 6 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_6_REQ_IN_FLIGHT_CNT 0x000004D0
+
+	/* Buffer 6 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_6_PREFETCH_REQ_CNT 0x000004D8
+
+	/* Buffer 6 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_6_TOTAL_PCI_RETRY_CNT 0x000004E0
+
+	/* Buffer 6 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_6_MAX_PCI_RETRY_CNT 0x000004E8
+
+	/* Buffer 6 Max Latency Count Register  -- read/write */
+#define PIC_BUF_6_MAX_LATENCY_CNT 0x000004F0
+
+	/* Buffer 6 Clear All Register  -- read/write */
+#define PIC_BUF_6_CLEAR_ALL 0x000004F8
+
+	/* Buffer 8 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_8_FLUSH_CNT_WITH_DATA_TOUCH 0x00000500
+
+	/* Buffer 8 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_8_FLUSH_CNT_W_O_DATA_TOUCH 0x00000508
+
+	/* Buffer 8 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_8_REQ_IN_FLIGHT_CNT 0x00000510
+
+	/* Buffer 8 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_8_PREFETCH_REQ_CNT 0x00000518
+
+	/* Buffer 8 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_8_TOTAL_PCI_RETRY_CNT 0x00000520
+
+	/* Buffer 8 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_8_MAX_PCI_RETRY_CNT 0x00000528
+
+	/* Buffer 8 Max Latency Count Register  -- read/write */
+#define PIC_BUF_8_MAX_LATENCY_CNT 0x00000530
+
+	/* Buffer 8 Clear All Register  -- read/write */
+#define PIC_BUF_8_CLEAR_ALL 0x00000538
+
+	/* Buffer 10 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_10_FLUSH_CNT_WITH_DATA_TOUCH 0x00000540
+
+	/* Buffer 10 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_10_FLUSH_CNT_W_O_DATA_TOUCH 0x00000548
+
+	/* Buffer 10 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_10_REQ_IN_FLIGHT_CNT 0x00000550
+
+	/* Buffer 10 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_10_PREFETCH_REQ_CNT 0x00000558
+
+	/* Buffer 10 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_10_TOTAL_PCI_RETRY_CNT 0x00000560
+
+	/* Buffer 10 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_10_MAX_PCI_RETRY_CNT 0x00000568
+
+	/* Buffer 10 Max Latency Count Register  -- read/write */
+#define PIC_BUF_10_MAX_LATENCY_CNT 0x00000570
+
+	/* Buffer 10 Clear All Register  -- read/write */
+#define PIC_BUF_10_CLEAR_ALL 0x00000578
+
+	/* Buffer 12 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_12_FLUSH_CNT_WITH_DATA_TOUCH 0x00000580
+
+	/* Buffer 12 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_12_FLUSH_CNT_W_O_DATA_TOUCH 0x00000588
+
+	/* Buffer 12 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_12_REQ_IN_FLIGHT_CNT 0x00000590
+
+	/* Buffer 12 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_12_PREFETCH_REQ_CNT 0x00000598
+
+	/* Buffer 12 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_12_TOTAL_PCI_RETRY_CNT 0x000005A0
+
+	/* Buffer 12 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_12_MAX_PCI_RETRY_CNT 0x000005A8
+
+	/* Buffer 12 Max Latency Count Register  -- read/write */
+#define PIC_BUF_12_MAX_LATENCY_CNT 0x000005B0
+
+	/* Buffer 12 Clear All Register  -- read/write */
+#define PIC_BUF_12_CLEAR_ALL 0x000005B8
+
+	/* Buffer 14 Flush Count with Data Touch Register  -- read/write */
+#define PIC_BUF_14_FLUSH_CNT_WITH_DATA_TOUCH 0x000005C0
+
+	/* Buffer 14 Flush Count w/o Data Touch Register  -- read/write */
+#define PIC_BUF_14_FLUSH_CNT_W_O_DATA_TOUCH 0x000005C8
+
+	/* Buffer 14 Request in Flight Count Register  -- read/write */
+#define PIC_BUF_14_REQ_IN_FLIGHT_CNT 0x000005D0
+
+	/* Buffer 14 Prefetch Request Count Register  -- read/write */
+#define PIC_BUF_14_PREFETCH_REQ_CNT 0x000005D8
+
+	/* Buffer 14 Total PCI Retry Count Register  -- read/write */
+#define PIC_BUF_14_TOTAL_PCI_RETRY_CNT 0x000005E0
+
+	/* Buffer 14 Max PCI Retry Count Register  -- read/write */
+#define PIC_BUF_14_MAX_PCI_RETRY_CNT 0x000005E8
+
+	/* Buffer 14 Max Latency Count Register  -- read/write */
+#define PIC_BUF_14_MAX_LATENCY_CNT 0x000005F0
+
+	/* Buffer 14 Clear All Register  -- read/write */
+#define PIC_BUF_14_CLEAR_ALL 0x000005F8
+
+	/* PCIX Read Buffer 0 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_0_ADDR 0x00000A00
+
+	/* PCIX Read Buffer 0 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_0_ATTRIBUTE 0x00000A08
+
+	/* PCIX Read Buffer 1 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_1_ADDR 0x00000A10
+
+	/* PCIX Read Buffer 1 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_1_ATTRIBUTE 0x00000A18
+
+	/* PCIX Read Buffer 2 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_2_ADDR 0x00000A20
+
+	/* PCIX Read Buffer 2 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_2_ATTRIBUTE 0x00000A28
+
+	/* PCIX Read Buffer 3 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_3_ADDR 0x00000A30
+
+	/* PCIX Read Buffer 3 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_3_ATTRIBUTE 0x00000A38
+
+	/* PCIX Read Buffer 4 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_4_ADDR 0x00000A40
+
+	/* PCIX Read Buffer 4 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_4_ATTRIBUTE 0x00000A48
+
+	/* PCIX Read Buffer 5 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_5_ADDR 0x00000A50
+
+	/* PCIX Read Buffer 5 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_5_ATTRIBUTE 0x00000A58
+
+	/* PCIX Read Buffer 6 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_6_ADDR 0x00000A60
+
+	/* PCIX Read Buffer 6 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_6_ATTRIBUTE 0x00000A68
+
+	/* PCIX Read Buffer 7 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_7_ADDR 0x00000A70
+
+	/* PCIX Read Buffer 7 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_7_ATTRIBUTE 0x00000A78
+
+	/* PCIX Read Buffer 8 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_8_ADDR 0x00000A80
+
+	/* PCIX Read Buffer 8 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_8_ATTRIBUTE 0x00000A88
+
+	/* PCIX Read Buffer 9 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_9_ADDR 0x00000A90
+
+	/* PCIX Read Buffer 9 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_9_ATTRIBUTE 0x00000A98
+
+	/* PCIX Read Buffer 10 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_10_ADDR 0x00000AA0
+
+	/* PCIX Read Buffer 10 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_10_ATTRIBUTE 0x00000AA8
+
+	/* PCIX Read Buffer 11 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_11_ADDR 0x00000AB0
+
+	/* PCIX Read Buffer 11 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_11_ATTRIBUTE 0x00000AB8
+
+	/* PCIX Read Buffer 12 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_12_ADDR 0x00000AC0
+
+	/* PCIX Read Buffer 12 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_12_ATTRIBUTE 0x00000AC8
+
+	/* PCIX Read Buffer 13 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_13_ADDR 0x00000AD0
+
+	/* PCIX Read Buffer 13 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_13_ATTRIBUTE 0x00000AD8
+
+	/* PCIX Read Buffer 14 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_14_ADDR 0x00000AE0
+
+	/* PCIX Read Buffer 14 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_14_ATTRIBUTE 0x00000AE8
+
+	/* PCIX Read Buffer 15 Address Register  -- read-only */
+#define PIC_PCIX_READ_BUF_15_ADDR 0x00000AF0
+
+	/* PCIX Read Buffer 15 Attribute Register  -- read-only */
+#define PIC_PCIX_READ_BUF_15_ATTRIBUTE 0x00000AF8
+
+	/* PCIX Write Buffer 0 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_0_ADDR 0x00000B00
+
+	/* PCIX Write Buffer 0 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_0_ATTRIBUTE 0x00000B08
+
+	/* PCIX Write Buffer 0 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_0_VALID 0x00000B10
+
+	/* PCIX Write Buffer 1 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_1_ADDR 0x00000B20
+
+	/* PCIX Write Buffer 1 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_1_ATTRIBUTE 0x00000B28
+
+	/* PCIX Write Buffer 1 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_1_VALID 0x00000B30
+
+	/* PCIX Write Buffer 2 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_2_ADDR 0x00000B40
+
+	/* PCIX Write Buffer 2 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_2_ATTRIBUTE 0x00000B48
+
+	/* PCIX Write Buffer 2 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_2_VALID 0x00000B50
+
+	/* PCIX Write Buffer 3 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_3_ADDR 0x00000B60
+
+	/* PCIX Write Buffer 3 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_3_ATTRIBUTE 0x00000B68
+
+	/* PCIX Write Buffer 3 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_3_VALID 0x00000B70
+
+	/* PCIX Write Buffer 4 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_4_ADDR 0x00000B80
+
+	/* PCIX Write Buffer 4 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_4_ATTRIBUTE 0x00000B88
+
+	/* PCIX Write Buffer 4 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_4_VALID 0x00000B90
+
+	/* PCIX Write Buffer 5 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_5_ADDR 0x00000BA0
+
+	/* PCIX Write Buffer 5 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_5_ATTRIBUTE 0x00000BA8
+
+	/* PCIX Write Buffer 5 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_5_VALID 0x00000BB0
+
+	/* PCIX Write Buffer 6 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_6_ADDR 0x00000BC0
+
+	/* PCIX Write Buffer 6 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_6_ATTRIBUTE 0x00000BC8
+
+	/* PCIX Write Buffer 6 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_6_VALID 0x00000BD0
+
+	/* PCIX Write Buffer 7 Address Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_7_ADDR 0x00000BE0
+
+	/* PCIX Write Buffer 7 Attribute Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_7_ATTRIBUTE 0x00000BE8
+
+	/* PCIX Write Buffer 7 Valid Register  -- read-only */
+#define PIC_PCIX_WRITE_BUF_7_VALID 0x00000BF0
+
+/*********************************************************************
+ * misc typedefs
+ *
+ */
+typedef uint64_t picreg_t;
+
+/*********************************************************************
+ * PIC register structures
+ *
+ */
+
+/*
+ * Identification Register
+ *
+ * The Identification register is a read only register used by the host CPU
+ * during configuration to determine the type of the widget. The format is
+ * the same as defined in IEEE 1149.1 JTAG Device Identification Register.
+ */
+	typedef union pic_id_reg_u {
+		picreg_t	pic_id_reg_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t rev_num  :	4; /* 31:28 */
+			picreg_t part_num :	16; /* 27:12 */
+			picreg_t mfg_num  :	11; /* 11:1 */
+			picreg_t          :	1; /* 0:0 */
+		} pic_id_reg_fld_s;
+	} pic_id_reg_u_t;
+/*
+ * Status Register
+ *
+ * The status register is a read register which holds status information of the
+ * Bus Subsection.
+ */
+	typedef union pic_stat_reg_u {
+		picreg_t	pic_stat_reg_regval;
+		struct {
+			picreg_t                :	28; /* 63:36 */
+			picreg_t pci_x_speed    :	2; /* 35:34 */
+			picreg_t pci_x_active   :	1; /* 33:33 */
+			picreg_t                :	1; /* 32:32 */
+			picreg_t llp_rec_cnt    :	8; /* 31:24 */
+			picreg_t llp_tx_cnt     :	8; /* 23:16 */
+			picreg_t rx_credit_cnt  :	4; /* 15:12 */
+			picreg_t tx_credit_cnt  :	4; /* 11:8 */
+			picreg_t pci_misc_input :	8; /* 7:0 */
+		} pic_stat_reg_fld_s;
+	} pic_stat_reg_u_t;
+/*
+ * Upper Address Holding Register Bus Side Errors
+ *
+ * The upper address holding register is a read only register which contains
+ * the upper 16-bits of the address when certain error occurs (see error cases
+ * chapter). Subsequent errors are not logged until the error is cleared. The
+ * last logged value is held until the group is cleared and enabled.
+ */
+	typedef union pic_upper_bus_err_u {
+		picreg_t	pic_upper_bus_err_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t          :	16; /* 31:16 */
+			picreg_t upp_addr :	16; /* 15:0 */
+		} pic_upper_bus_err_fld_s;
+	} pic_upper_bus_err_u_t;
+/*
+ * Lower Address Holding Register Bus Side Errors
+ *
+ * The lower address holding register is a read only register which contains
+ * the address which either can be accessed as a word or double word. Sub-
+ * sequent errors are not logged until the error is cleared. The last logged
+ * value is held until the group is cleared and enabled.
+ */
+	typedef union pic_lower_bus_err_u {
+		picreg_t	pic_lower_bus_err_regval;
+		struct {
+			picreg_t          :	16; /* 63:48 */
+			picreg_t upp_addr :	16; /* 47:32 */
+			picreg_t low_addr :	32; /* 31:0 */
+		} pic_lower_bus_err_fld_s;
+	} pic_lower_bus_err_u_t;
+/*
+ * Control Register
+ *
+ * The control register is a read/write register which holds control informa-
+ * tion for the bus subsection.
+ */
+	typedef union pic_control_reg_u {
+		picreg_t	pic_control_reg_regval;
+		struct {
+			picreg_t                :	32; /* 63:32 */
+			picreg_t                :	4; /* 31:28 */
+			picreg_t rst_pin_n      :	4; /* 27:24 */
+			picreg_t                :	1; /* 23:23 */
+			picreg_t mem_swap       :	1; /* 22:22 */
+			picreg_t page_size      :	1; /* 21:21 */
+			picreg_t                :	4; /* 20:17 */
+			picreg_t f_bad_pkt      :	1; /* 16:16 */
+			picreg_t llp_xbar_crd   :	4; /* 15:12 */
+			picreg_t clr_rllp_cnt   :	1; /* 11:11 */
+			picreg_t clr_tllp_cnt   :	1; /* 10:10 */
+			picreg_t sys_end        :	1; /* 9:9 */
+			picreg_t                :	3; /* 8:6 */
+			picreg_t pci_speed      :	2; /* 5:4 */
+			picreg_t widget_id      :	4; /* 3:0 */
+		} pic_control_reg_fld_s;
+	} pic_control_reg_u_t;
+/*
+ * PCI/PCI-X Request Time-out Value Register
+ *
+ * This register contains the reload value for the response timer. The request
+ * timer counts every 960 nS (32 PCI clocks)
+ */
+	typedef union pic_pci_req_to_u {
+		picreg_t	pic_pci_req_to_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t          :	12; /* 31:20 */
+			picreg_t time_out :	20; /* 19:0 */
+		} pic_pci_req_to_fld_s;
+	} pic_pci_req_to_u_t;
+/*
+ * Interrupt Destination Upper Address Register
+ *
+ * The interrupt destination upper address register is a read/write register
+ * containing the upper 16-bits of address of the host to which the interrupt
+ * is targeted. In addition the target ID is also contained in this register for
+ * use in Crosstalk mode.
+ */
+	typedef union pic_int_desc_upper_u {
+		picreg_t	pic_int_desc_upper_regval;
+		struct {
+			picreg_t           :	32; /* 63:32 */
+			picreg_t           :	12; /* 31:20 */
+			picreg_t target_id :	4; /* 19:16 */
+			picreg_t upp_addr  :	16; /* 15:0 */
+		} pic_int_desc_upper_fld_s;
+	} pic_int_desc_upper_u_t;
+/*
+ * Interrupt Destination Lower Address Register
+ *
+ * The interrupt destination lower address register is a read/write register
+ * which contains the entire address of the host to which the interrupt is tar-
+ * geted. In addition the target ID is also contained in this register for use in
+ * Crosstalk mode.
+ */
+	typedef union pic_int_desc_lower_u {
+		picreg_t	pic_int_desc_lower_regval;
+		struct {
+			picreg_t           :	12; /* 63:52 */
+			picreg_t target_id :	4; /* 51:48 */
+			picreg_t upp_addr  :	16; /* 47:32 */
+			picreg_t low_addr  :	32; /* 31:0 */
+		} pic_int_desc_lower_fld_s;
+	} pic_int_desc_lower_u_t;
+/*
+ * Command Word Holding Register Bus Side Errors
+ *
+ * The command word holding is a read register that holds the command
+ * word of a Crosstalk packet when errors occur on the link side (see error
+ * chapter). Errors are indicated with error bits in the interrupt status regis-
+ * ter. Subsequent errors are not logged until the interrupt is cleared..
+ */
+	typedef union pic_cmd_word_bus_err_u {
+		picreg_t	pic_cmd_word_bus_err_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t didn     :	4; /* 31:28 */
+			picreg_t sidn     :	4; /* 27:24 */
+			picreg_t pactyp   :	4; /* 23:20 */
+			picreg_t tnum     :	5; /* 19:15 */
+			picreg_t coherent :	1; /* 14:14 */
+			picreg_t ds       :	2; /* 13:12 */
+			picreg_t gbr      :	1; /* 11:11 */
+			picreg_t vbpm     :	1; /* 10:10 */
+			picreg_t error    :	1; /* 9:9 */
+			picreg_t barrier  :	1; /* 8:8 */
+			picreg_t          :	8; /* 7:0 */
+		} pic_cmd_word_bus_err_fld_s;
+	} pic_cmd_word_bus_err_u_t;
+/*
+ * LLP Configuration Register
+ *
+ * This register contains the configuration information for the LLP modules
+ * and is only valid on bus 0 side.
+ */
+	typedef union pic_llp_cfg_u {
+		picreg_t	pic_llp_cfg_regval;
+		struct {
+			picreg_t                 :	32; /* 63:32 */
+			picreg_t                 :	6; /* 31:26 */
+			picreg_t llp_maxretry    :	10; /* 25:16 */
+			picreg_t llp_nulltimeout :	6; /* 15:10 */
+			picreg_t llp_maxburst    :	10; /* 9:0 */
+		} pic_llp_cfg_fld_s;
+	} pic_llp_cfg_u_t;
+/*
+ * PCI/PCI-X Target Flush Register
+ *
+ * When read, this register will return a 0x00 after all previous transfers to
+ * the PCI bus subsection have completed.
+ */
+
+/*
+ * Command Word Holding Register Link Side Errors
+ *
+ * The command word holding is a read-only register that holds the com-
+ * mand word of a Crosstalk packet when request fifo overflow or unexpect-
+ * ed response errors occur. Errors are indicated with error bits in the
+ * interrupt status register. Subsequent errors are not logged until this inter-
+ * rupt is cleared.
+ */
+	typedef union pic_cmd_word_link_err_u {
+		picreg_t	pic_cmd_word_link_err_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t didn     :	4; /* 31:28 */
+			picreg_t sidn     :	4; /* 27:24 */
+			picreg_t pactyp   :	4; /* 23:20 */
+			picreg_t tnum     :	5; /* 19:15 */
+			picreg_t coherent :	1; /* 14:14 */
+			picreg_t ds       :	2; /* 13:12 */
+			picreg_t gbr      :	1; /* 11:11 */
+			picreg_t vbpm     :	1; /* 10:10 */
+			picreg_t error    :	1; /* 9:9 */
+			picreg_t barrier  :	1; /* 8:8 */
+			picreg_t          :	8; /* 7:0 */
+		} pic_cmd_word_link_err_fld_s;
+	} pic_cmd_word_link_err_u_t;
+/*
+ * PCI Response Buffer Error Upper Address Holding Reg
+ *
+ * The response buffer error upper address holding register is a read only
+ * register which contains the upper 16-bits of the address when error asso-
+ * ciated with response buffer entries occur. Subsequent errors are not
+ * logged until the interrupt is cleared.
+ */
+	typedef union pic_pci_rbuf_err_upper_u {
+		picreg_t	pic_pci_rbuf_err_upper_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t          :	9; /* 31:23 */
+			picreg_t dev_num  :	3; /* 22:20 */
+			picreg_t buff_num :	4; /* 19:16 */
+			picreg_t upp_addr :	16; /* 15:0 */
+		} pic_pci_rbuf_err_upper_fld_s;
+	} pic_pci_rbuf_err_upper_u_t;
+/*
+ * PCI Response Buffer Error Lower Address Holding Reg
+ *
+ * The response buffer error lower address holding register is a read only
+ * register which contains the address of the error associated with response
+ * buffer entries. Subsequent errors are not logged until the interrupt is
+ * cleared.
+ */
+	typedef union pic_pci_rbuf_err_lower_u {
+		picreg_t	pic_pci_rbuf_err_lower_regval;
+		struct {
+			picreg_t          :	9; /* 63:55 */
+			picreg_t dev_num  :	3; /* 54:52 */
+			picreg_t buff_num :	4; /* 51:48 */
+			picreg_t upp_addr :	16; /* 47:32 */
+			picreg_t low_addr :	32; /* 31:0 */
+		} pic_pci_rbuf_err_lower_fld_s;
+	} pic_pci_rbuf_err_lower_u_t;
+/*
+ * Test Pin Control Register
+ *
+ * This register selects the output function and value to the four test pins on
+ * the PIC .
+ */
+	typedef union pic_test_pin_cntl_u {
+		picreg_t	pic_test_pin_cntl_regval;
+		struct {
+			picreg_t            :	32; /* 63:32 */
+			picreg_t            :	8; /* 31:24 */
+			picreg_t tdata_out  :	8; /* 23:16 */
+			picreg_t sel_tpin_7 :	2; /* 15:14 */
+			picreg_t sel_tpin_6 :	2; /* 13:12 */
+			picreg_t sel_tpin_5 :	2; /* 11:10 */
+			picreg_t sel_tpin_4 :	2; /* 9:8 */
+			picreg_t sel_tpin_3 :	2; /* 7:6 */
+			picreg_t sel_tpin_2 :	2; /* 5:4 */
+			picreg_t sel_tpin_1 :	2; /* 3:2 */
+			picreg_t sel_tpin_0 :	2; /* 1:0 */
+		} pic_test_pin_cntl_fld_s;
+	} pic_test_pin_cntl_u_t;
+/*
+ * Address Holding Register Link Side Errors
+ *
+ * The address holding register is a read only register which contains the ad-
+ * dress which either can be accessed as a word or double word. Subsequent
+ * errors are not logged until the error is cleared. The last logged value is
+ * held until the group is cleared and enabled.
+ */
+	typedef union pic_p_addr_lkerr_u {
+		picreg_t	pic_p_addr_lkerr_regval;
+		struct {
+			picreg_t          :	16; /* 63:48 */
+			picreg_t upp_addr :	16; /* 47:32 */
+			picreg_t low_addr :	32; /* 31:0 */
+		} pic_p_addr_lkerr_fld_s;
+	} pic_p_addr_lkerr_u_t;
+/*
+ * PCI Direct Mapping Register
+ *
+ * This register is used to relocate a 2 GByte region for PCI to Crosstalk
+ * transfers.
+ */
+	typedef union pic_p_dir_map_u {
+		picreg_t	pic_p_dir_map_regval;
+		struct {
+			picreg_t            :	32; /* 63:32 */
+			picreg_t            :	8; /* 31:24 */
+			picreg_t dir_w_id   :	4; /* 23:20 */
+			picreg_t            :	2; /* 19:18 */
+			picreg_t dir_add512 :	1; /* 17:17 */
+			picreg_t dir_off    :	17; /* 16:0 */
+		} pic_p_dir_map_fld_s;
+	} pic_p_dir_map_u_t;
+/*
+ * PCI Page Map Fault Address Register
+ *
+ * This register contains the address and device number when a page map
+ * fault occurred.
+ */
+	typedef union pic_p_map_fault_u {
+		picreg_t	pic_p_map_fault_regval;
+		struct {
+			picreg_t             :	32; /* 63:32 */
+			picreg_t             :	10; /* 31:22 */
+			picreg_t pci_addr    :	18; /* 21:4 */
+			picreg_t             :	1; /* 3:3 */
+			picreg_t pci_dev_num :	3; /* 2:0 */
+		} pic_p_map_fault_fld_s;
+	} pic_p_map_fault_u_t;
+/*
+ * Arbitration Register
+ *
+ * This register defines the priority and bus time out timing in PCI bus arbi-
+ * tration.
+ */
+	typedef union pic_p_arb_u {
+		picreg_t	pic_p_arb_regval;
+		struct {
+			picreg_t               :	32; /* 63:32 */
+			picreg_t               :	8; /* 31:24 */
+			picreg_t dev_broke     :	4; /* 23:20 */
+			picreg_t               :	2; /* 19:18 */
+			picreg_t req_wait_tick :	2; /* 17:16 */
+			picreg_t               :	4; /* 15:12 */
+			picreg_t req_wait_en   :	4; /* 11:8 */
+			picreg_t disarb        :	1; /* 7:7 */
+			picreg_t freeze_gnt    :	1; /* 6:6 */
+			picreg_t               :	1; /* 5:5 */
+			picreg_t en_bridge_hi  :	2; /* 4:3 */
+			picreg_t               :	1; /* 2:2 */
+			picreg_t en_bridge_lo  :	2; /* 1:0 */
+		} pic_p_arb_fld_s;
+	} pic_p_arb_u_t;
+/*
+ * Internal Ram Parity Error Register
+ *
+ * This register logs information about parity errors on internal ram access.
+ */
+	typedef union pic_p_ram_perr_u {
+		picreg_t	pic_p_ram_perr_regval;
+		struct {
+			picreg_t         	     :	6; /* 63:58 */
+			picreg_t ate_err_addr        :	10; /* 57:48 */
+			picreg_t         	     :	7; /* 47:41 */
+			picreg_t rd_resp_err_addr    :	9; /* 40:32 */
+			picreg_t wrt_resp_err_addr   :	8; /* 31:24 */
+			picreg_t         	     :	2; /* 23:22 */
+			picreg_t ate_err 	     :	1; /* 21:21 */
+			picreg_t rd_resp_err         :	1; /* 20:20 */
+			picreg_t wrt_resp_err        :	1; /* 19:19 */
+			picreg_t dbe_ate 	     :	3; /* 18:16 */
+			picreg_t dbe_rd  	     :	8; /* 15:8 */
+			picreg_t dbe_wrt 	     :	8; /* 7:0 */
+		} pic_p_ram_perr_fld_s;
+	} pic_p_ram_perr_u_t;
+/*
+ * Time-out Register
+ *
+ * This register determines retry hold off and max retries allowed for PIO
+ * accesses to PCI/PCI-X.
+ */
+	typedef union pic_p_bus_timeout_u {
+		picreg_t	pic_p_bus_timeout_regval;
+		struct {
+			picreg_t               :	32; /* 63:32 */
+			picreg_t               :	11; /* 31:21 */
+			picreg_t pci_retry_hld :	5; /* 20:16 */
+			picreg_t               :	6; /* 15:10 */
+			picreg_t pci_retry_cnt :	10; /* 9:0 */
+		} pic_p_bus_timeout_fld_s;
+	} pic_p_bus_timeout_u_t;
+/*
+ * PCI/PCI-X Type 1 Configuration Register
+ *
+ * This register is use during accesses to the PCI/PCI-X type 1 configuration
+ * space. The bits in this register are used to supplement the address during
+ * the configuration cycle to select the correct secondary bus and device.
+ */
+	typedef union pic_type1_cfg_u {
+		picreg_t	pic_type1_cfg_regval;
+		struct {
+			picreg_t         :	32; /* 63:32 */
+			picreg_t         :	8; /* 31:24 */
+			picreg_t bus_num :	8; /* 23:16 */
+			picreg_t dev_num :	5; /* 15:11 */
+			picreg_t         :	11; /* 10:0 */
+		} pic_type1_cfg_fld_s;
+	} pic_type1_cfg_u_t;
+/*
+ * PCI Bus Error Upper Address Holding Register
+ *
+ * This register holds the value of the upper address on the PCI Bus when an
+ * error occurs.
+ */
+	typedef union pic_p_pci_err_upper_u {
+		picreg_t	pic_p_pci_err_upper_regval;
+		struct {
+			picreg_t                :	32; /* 63:32 */
+			picreg_t                :	4; /* 31:28 */
+			picreg_t pci_xtalk_did  :	4; /* 27:24 */
+			picreg_t                :	2; /* 23:22 */
+			picreg_t pci_dac        :	1; /* 21:21 */
+			picreg_t pci_dev_master :	1; /* 20:20 */
+			picreg_t pci_vdev       :	1; /* 19:19 */
+			picreg_t pci_dev_num    :	3; /* 18:16 */
+			picreg_t pci_uaddr_err  :	16; /* 15:0 */
+		} pic_p_pci_err_upper_fld_s;
+	} pic_p_pci_err_upper_u_t;
+/*
+ * PCI Bus Error Lower Address Holding Register
+ *
+ * This register holds the value of the lower address on the PCI Bus when an
+ * error occurs.
+ */
+	typedef union pic_p_pci_err_lower_u {
+		picreg_t	pic_p_pci_err_lower_regval;
+		struct {
+			picreg_t                :	4; /* 63:60 */
+			picreg_t pci_xtalk_did  :	4; /* 59:56 */
+			picreg_t                :	2; /* 55:54 */
+			picreg_t pci_dac        :	1; /* 53:53 */
+			picreg_t pci_dev_master :	1; /* 52:52 */
+			picreg_t pci_vdev       :	1; /* 51:51 */
+			picreg_t pci_dev_num    :	3; /* 50:48 */
+			picreg_t pci_uaddr_err  :	16; /* 47:32 */
+			picreg_t pci_laddr_err  :	32; /* 31:0 */
+		} pic_p_pci_err_lower_fld_s;
+	} pic_p_pci_err_lower_u_t;
+/*
+ * PCI-X Error Address Register
+ *
+ * This register contains the address on the PCI-X bus when an error oc-
+ * curred.
+ */
+	typedef union pic_p_pcix_err_addr_u {
+		picreg_t	pic_p_pcix_err_addr_regval;
+		struct {
+			picreg_t pcix_err_addr :	64; /* 63:0 */
+		} pic_p_pcix_err_addr_fld_s;
+	} pic_p_pcix_err_addr_u_t;
+/*
+ * PCI-X Error Attribute Register
+ *
+ * This register contains the attribute data on the PCI-X bus when an error
+ * occurred.
+ */
+	typedef union pic_p_pcix_err_attr_u {
+		picreg_t	pic_p_pcix_err_attr_regval;
+		struct {
+			picreg_t            :	16; /* 63:48 */
+			picreg_t bus_cmd    :	4; /* 47:44 */
+			picreg_t byte_cnt   :	12; /* 43:32 */
+			picreg_t            :	1; /* 31:31 */
+			picreg_t ns         :	1; /* 30:30 */
+			picreg_t ro         :	1; /* 29:29 */
+			picreg_t tag        :	5; /* 28:24 */
+			picreg_t bus_num    :	8; /* 23:16 */
+			picreg_t dev_num    :	5; /* 15:11 */
+			picreg_t fun_num    :	3; /* 10:8 */
+			picreg_t l_byte_cnt :	8; /* 7:0 */
+		} pic_p_pcix_err_attr_fld_s;
+	} pic_p_pcix_err_attr_u_t;
+/*
+ * PCI-X Error Data Register
+ *
+ * This register contains the Data on the PCI-X bus when an error occurred.
+ */
+	typedef union pic_p_pcix_err_data_u {
+		picreg_t	pic_p_pcix_err_data_regval;
+		struct {
+			picreg_t pcix_err_data :	64; /* 63:0 */
+		} pic_p_pcix_err_data_fld_s;
+	} pic_p_pcix_err_data_u_t;
+/*
+ * PCI-X Read Request Timeout Error Register
+ *
+ * This register contains a pointer into the PCI-X read data structure.
+ */
+	typedef union pic_p_pcix_read_req_to_u {
+		picreg_t	pic_p_pcix_read_req_to_regval;
+		struct {
+			picreg_t                :	55; /* 63:9 */
+			picreg_t rd_buff_loc    :	5; /* 8:4 */
+			picreg_t rd_buff_struct :	4; /* 3:0 */
+		} pic_p_pcix_read_req_to_fld_s;
+	} pic_p_pcix_read_req_to_u_t;
+/*
+ * INT_STATUS Register
+ *
+ * This is the current interrupt status register which maintains the current
+ * status of all the interrupting devices which generated a n interrupt. This
+ * register is read only and all the bits are active high. A high bit at
+ * INT_STATE means the corresponding INT_N pin has been asserted
+ * (low).
+ */
+	typedef union pic_p_int_status_u {
+		picreg_t	pic_p_int_status_regval;
+		struct {
+			picreg_t                  :	22; /* 63:42 */
+			picreg_t int_ram_perr     :	1; /* 41:41 */
+			picreg_t bus_arb_broke    :	1; /* 40:40 */
+			picreg_t pci_x_req_tout   :	1; /* 39:39 */
+			picreg_t pci_x_tabort     :	1; /* 38:38 */
+			picreg_t pci_x_perr       :	1; /* 37:37 */
+			picreg_t pci_x_serr       :	1; /* 36:36 */
+			picreg_t pci_x_mretry     :	1; /* 35:35 */
+			picreg_t pci_x_mtout      :	1; /* 34:34 */
+			picreg_t pci_x_da_parity  :	1; /* 33:33 */
+			picreg_t pci_x_ad_parity  :	1; /* 32:32 */
+			picreg_t                  :	1; /* 31:31 */
+			picreg_t pmu_page_fault   :	1; /* 30:30 */
+			picreg_t unexpected_resp  :	1; /* 29:29 */
+			picreg_t bad_xresp_packet :	1; /* 28:28 */
+			picreg_t bad_xreq_packet  :	1; /* 27:27 */
+			picreg_t resp_xtalk_error :	1; /* 26:26 */
+			picreg_t req_xtalk_error  :	1; /* 25:25 */
+			picreg_t invalid_access   :	1; /* 24:24 */
+			picreg_t unsupported_xop  :	1; /* 23:23 */
+			picreg_t xreq_fifo_oflow  :	1; /* 22:22 */
+			picreg_t llp_rec_snerror  :	1; /* 21:21 */
+			picreg_t llp_rec_cberror  :	1; /* 20:20 */
+			picreg_t llp_rcty         :	1; /* 19:19 */
+			picreg_t llp_tx_retry     :	1; /* 18:18 */
+			picreg_t llp_tcty         :	1; /* 17:17 */
+			picreg_t                  :	1; /* 16:16 */
+			picreg_t pci_abort        :	1; /* 15:15 */
+			picreg_t pci_parity       :	1; /* 14:14 */
+			picreg_t pci_serr         :	1; /* 13:13 */
+			picreg_t pci_perr         :	1; /* 12:12 */
+			picreg_t pci_master_tout  :	1; /* 11:11 */
+			picreg_t pci_retry_cnt    :	1; /* 10:10 */
+			picreg_t xread_req_tout   :	1; /* 9:9 */
+			picreg_t                  :	1; /* 8:8 */
+			picreg_t int_state        :	8; /* 7:0 */
+		} pic_p_int_status_fld_s;
+	} pic_p_int_status_u_t;
+/*
+ * Interrupt Enable Register
+ *
+ * This register enables the reporting of interrupt to the host. Each bit in this
+ * register corresponds to the same bit in Interrupt Status register. All bits
+ * are zero after reset.
+ */
+	typedef union pic_p_int_enable_u {
+		picreg_t	pic_p_int_enable_regval;
+		struct {
+			picreg_t                     :	22; /* 63:42 */
+			picreg_t en_int_ram_perr     :	1; /* 41:41 */
+			picreg_t en_bus_arb_broke    :	1; /* 40:40 */
+			picreg_t en_pci_x_req_tout   :	1; /* 39:39 */
+			picreg_t en_pci_x_tabort     :	1; /* 38:38 */
+			picreg_t en_pci_x_perr       :	1; /* 37:37 */
+			picreg_t en_pci_x_serr       :	1; /* 36:36 */
+			picreg_t en_pci_x_mretry     :	1; /* 35:35 */
+			picreg_t en_pci_x_mtout      :	1; /* 34:34 */
+			picreg_t en_pci_x_da_parity  :	1; /* 33:33 */
+			picreg_t en_pci_x_ad_parity  :	1; /* 32:32 */
+			picreg_t                     :	1; /* 31:31 */
+			picreg_t en_pmu_page_fault   :	1; /* 30:30 */
+			picreg_t en_unexpected_resp  :	1; /* 29:29 */
+			picreg_t en_bad_xresp_packet :	1; /* 28:28 */
+			picreg_t en_bad_xreq_packet  :	1; /* 27:27 */
+			picreg_t en_resp_xtalk_error :	1; /* 26:26 */
+			picreg_t en_req_xtalk_error  :	1; /* 25:25 */
+			picreg_t en_invalid_access   :	1; /* 24:24 */
+			picreg_t en_unsupported_xop  :	1; /* 23:23 */
+			picreg_t en_xreq_fifo_oflow  :	1; /* 22:22 */
+			picreg_t en_llp_rec_snerror  :	1; /* 21:21 */
+			picreg_t en_llp_rec_cberror  :	1; /* 20:20 */
+			picreg_t en_llp_rcty         :	1; /* 19:19 */
+			picreg_t en_llp_tx_retry     :	1; /* 18:18 */
+			picreg_t en_llp_tcty         :	1; /* 17:17 */
+			picreg_t                     :	1; /* 16:16 */
+			picreg_t en_pci_abort        :	1; /* 15:15 */
+			picreg_t en_pci_parity       :	1; /* 14:14 */
+			picreg_t en_pci_serr         :	1; /* 13:13 */
+			picreg_t en_pci_perr         :	1; /* 12:12 */
+			picreg_t en_pci_master_tout  :	1; /* 11:11 */
+			picreg_t en_pci_retry_cnt    :	1; /* 10:10 */
+			picreg_t en_xread_req_tout   :	1; /* 9:9 */
+			picreg_t                     :	1; /* 8:8 */
+			picreg_t en_int_state        :	8; /* 7:0 */
+		} pic_p_int_enable_fld_s;
+	} pic_p_int_enable_u_t;
+/*
+ * Reset Interrupt Register
+ *
+ * A write of a "1" clears the bit and rearms the error registers. Writes also
+ * clear the error view register.
+ */
+	typedef union pic_p_int_rst_u {
+		picreg_t	pic_p_int_rst_regval;
+		struct {
+			picreg_t                       :	22; /* 63:42 */
+			picreg_t logv_int_ram_perr     :	1; /* 41:41 */
+			picreg_t logv_bus_arb_broke    :	1; /* 40:40 */
+			picreg_t logv_pci_x_req_tout   :	1; /* 39:39 */
+			picreg_t logv_pci_x_tabort     :	1; /* 38:38 */
+			picreg_t logv_pci_x_perr       :	1; /* 37:37 */
+			picreg_t logv_pci_x_serr       :	1; /* 36:36 */
+			picreg_t logv_pci_x_mretry     :	1; /* 35:35 */
+			picreg_t logv_pci_x_mtout      :	1; /* 34:34 */
+			picreg_t logv_pci_x_da_parity  :	1; /* 33:33 */
+			picreg_t logv_pci_x_ad_parity  :	1; /* 32:32 */
+			picreg_t                       :	1; /* 31:31 */
+			picreg_t logv_pmu_page_fault   :	1; /* 30:30 */
+			picreg_t logv_unexpected_resp  :	1; /* 29:29 */
+			picreg_t logv_bad_xresp_packet :	1; /* 28:28 */
+			picreg_t logv_bad_xreq_packet  :	1; /* 27:27 */
+			picreg_t logv_resp_xtalk_error :	1; /* 26:26 */
+			picreg_t logv_req_xtalk_error  :	1; /* 25:25 */
+			picreg_t logv_invalid_access   :	1; /* 24:24 */
+			picreg_t logv_unsupported_xop  :	1; /* 23:23 */
+			picreg_t logv_xreq_fifo_oflow  :	1; /* 22:22 */
+			picreg_t logv_llp_rec_snerror  :	1; /* 21:21 */
+			picreg_t logv_llp_rec_cberror  :	1; /* 20:20 */
+			picreg_t logv_llp_rcty         :	1; /* 19:19 */
+			picreg_t logv_llp_tx_retry     :	1; /* 18:18 */
+			picreg_t logv_llp_tcty         :	1; /* 17:17 */
+			picreg_t                       :	1; /* 16:16 */
+			picreg_t logv_pci_abort        :	1; /* 15:15 */
+			picreg_t logv_pci_parity       :	1; /* 14:14 */
+			picreg_t logv_pci_serr         :	1; /* 13:13 */
+			picreg_t logv_pci_perr         :	1; /* 12:12 */
+			picreg_t logv_pci_master_tout  :	1; /* 11:11 */
+			picreg_t logv_pci_retry_cnt    :	1; /* 10:10 */
+			picreg_t logv_xread_req_tout   :	1; /* 9:9 */
+                        picreg_t                       :        2; /* 8:7 */
+			picreg_t multi_clr             :	1; /* 6:6 */
+			picreg_t                       :	6; /* 5:0 */
+		} pic_p_int_rst_fld_s;
+	} pic_p_int_rst_u_t;
+
+/*
+ * Interrupt Mode Register
+ *
+ * This register defines the interrupting mode of the INT_N pins.
+ */
+	typedef union pic_p_int_mode_u {
+		picreg_t	pic_p_int_mode_regval;
+		struct {
+			picreg_t            :	32; /* 63:32 */
+			picreg_t            :	24; /* 31:8 */
+			picreg_t en_clr_pkt :	8; /* 7:0 */
+		} pic_p_int_mode_fld_s;
+	} pic_p_int_mode_u_t;
+/*
+ * Interrupt Device Select Register
+ *
+ * This register associates interrupt pins with devices thus allowing buffer
+ * management (flushing) when a device interrupt occurs.
+ */
+	typedef union pic_p_int_device_u {
+		picreg_t	pic_p_int_device_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t          :	8; /* 31:24 */
+			picreg_t int7_dev :	3; /* 23:21 */
+			picreg_t int6_dev :	3; /* 20:18 */
+			picreg_t int5_dev :	3; /* 17:15 */
+			picreg_t int4_dev :	3; /* 14:12 */
+			picreg_t int3_dev :	3; /* 11:9 */
+			picreg_t int2_dev :	3; /* 8:6 */
+			picreg_t int1_dev :	3; /* 5:3 */
+			picreg_t int0_dev :	3; /* 2:0 */
+		} pic_p_int_device_fld_s;
+	} pic_p_int_device_u_t;
+/*
+ * Host Error Interrupt Field Register
+ *
+ * This register tells which bit location in the host's Interrupt Status register
+ * to set or reset when any error condition happens.
+ */
+	typedef union pic_p_int_host_err_u {
+		picreg_t	pic_p_int_host_err_regval;
+		struct {
+			picreg_t                :	32; /* 63:32 */
+			picreg_t                :	24; /* 31:8 */
+			picreg_t bridge_err_fld :	8; /* 7:0 */
+		} pic_p_int_host_err_fld_s;
+	} pic_p_int_host_err_u_t;
+/*
+ * Interrupt (x) Host Address Register
+ *
+ * This register allow different host address to be assigned to each interrupt
+ * pin and the bit in the host.
+ */
+	typedef union pic_p_int_addr_u {
+		picreg_t	pic_p_int_addr_regval;
+		struct {
+			picreg_t          :	8; /* 63:56 */
+			picreg_t int_fld  :	8; /* 55:48 */
+			picreg_t int_addr :	48; /* 47:0 */
+		} pic_p_int_addr_fld_s;
+	} pic_p_int_addr_u_t;
+/*
+ * Error Interrupt View Register
+ *
+ * This register contains the view of which interrupt occur even if they are
+ * not currently enabled. The group clear is used to clear these bits just like
+ * the interrupt status register bits.
+ */
+	typedef union pic_p_err_int_view_u {
+		picreg_t	pic_p_err_int_view_regval;
+		struct {
+			picreg_t                  :	22; /* 63:42 */
+			picreg_t int_ram_perr     :	1; /* 41:41 */
+			picreg_t bus_arb_broke    :	1; /* 40:40 */
+			picreg_t pci_x_req_tout   :	1; /* 39:39 */
+			picreg_t pci_x_tabort     :	1; /* 38:38 */
+			picreg_t pci_x_perr       :	1; /* 37:37 */
+			picreg_t pci_x_serr       :	1; /* 36:36 */
+			picreg_t pci_x_mretry     :	1; /* 35:35 */
+			picreg_t pci_x_mtout      :	1; /* 34:34 */
+			picreg_t pci_x_da_parity  :	1; /* 33:33 */
+			picreg_t pci_x_ad_parity  :	1; /* 32:32 */
+			picreg_t                  :	1; /* 31:31 */
+			picreg_t pmu_page_fault   :	1; /* 30:30 */
+			picreg_t unexpected_resp  :	1; /* 29:29 */
+			picreg_t bad_xresp_packet :	1; /* 28:28 */
+			picreg_t bad_xreq_packet  :	1; /* 27:27 */
+			picreg_t resp_xtalk_error :	1; /* 26:26 */
+			picreg_t req_xtalk_error  :	1; /* 25:25 */
+			picreg_t invalid_access   :	1; /* 24:24 */
+			picreg_t unsupported_xop  :	1; /* 23:23 */
+			picreg_t xreq_fifo_oflow  :	1; /* 22:22 */
+			picreg_t llp_rec_snerror  :	1; /* 21:21 */
+			picreg_t llp_rec_cberror  :	1; /* 20:20 */
+			picreg_t llp_rcty         :	1; /* 19:19 */
+			picreg_t llp_tx_retry     :	1; /* 18:18 */
+			picreg_t llp_tcty         :	1; /* 17:17 */
+			picreg_t                  :	1; /* 16:16 */
+			picreg_t pci_abort        :	1; /* 15:15 */
+			picreg_t pci_parity       :	1; /* 14:14 */
+			picreg_t pci_serr         :	1; /* 13:13 */
+			picreg_t pci_perr         :	1; /* 12:12 */
+			picreg_t pci_master_tout  :	1; /* 11:11 */
+			picreg_t pci_retry_cnt    :	1; /* 10:10 */
+			picreg_t xread_req_tout   :	1; /* 9:9 */
+			picreg_t                  :	9; /* 8:0 */
+		} pic_p_err_int_view_fld_s;
+	} pic_p_err_int_view_u_t;
+
+
+/*
+ * Multiple Interrupt Register
+ *
+ * This register indicates if any interrupt occurs more than once without be-
+ * ing cleared.
+ */
+	typedef union pic_p_mult_int_u {
+		picreg_t	pic_p_mult_int_regval;
+		struct {
+			picreg_t                  :	22; /* 63:42 */
+			picreg_t int_ram_perr     :	1; /* 41:41 */
+			picreg_t bus_arb_broke    :	1; /* 40:40 */
+			picreg_t pci_x_req_tout   :	1; /* 39:39 */
+			picreg_t pci_x_tabort     :	1; /* 38:38 */
+			picreg_t pci_x_perr       :	1; /* 37:37 */
+			picreg_t pci_x_serr       :	1; /* 36:36 */
+			picreg_t pci_x_mretry     :	1; /* 35:35 */
+			picreg_t pci_x_mtout      :	1; /* 34:34 */
+			picreg_t pci_x_da_parity  :	1; /* 33:33 */
+			picreg_t pci_x_ad_parity  :	1; /* 32:32 */
+			picreg_t                  :	1; /* 31:31 */
+			picreg_t pmu_page_fault   :	1; /* 30:30 */
+			picreg_t unexpected_resp  :	1; /* 29:29 */
+			picreg_t bad_xresp_packet :	1; /* 28:28 */
+			picreg_t bad_xreq_packet  :	1; /* 27:27 */
+			picreg_t resp_xtalk_error :	1; /* 26:26 */
+			picreg_t req_xtalk_error  :	1; /* 25:25 */
+			picreg_t invalid_access   :	1; /* 24:24 */
+			picreg_t unsupported_xop  :	1; /* 23:23 */
+			picreg_t xreq_fifo_oflow  :	1; /* 22:22 */
+			picreg_t llp_rec_snerror  :	1; /* 21:21 */
+			picreg_t llp_rec_cberror  :	1; /* 20:20 */
+			picreg_t llp_rcty         :	1; /* 19:19 */
+			picreg_t llp_tx_retry     :	1; /* 18:18 */
+			picreg_t llp_tcty         :	1; /* 17:17 */
+			picreg_t                  :	1; /* 16:16 */
+			picreg_t pci_abort        :	1; /* 15:15 */
+			picreg_t pci_parity       :	1; /* 14:14 */
+			picreg_t pci_serr         :	1; /* 13:13 */
+			picreg_t pci_perr         :	1; /* 12:12 */
+			picreg_t pci_master_tout  :	1; /* 11:11 */
+			picreg_t pci_retry_cnt    :	1; /* 10:10 */
+			picreg_t xread_req_tout   :	1; /* 9:9 */
+			picreg_t                  :	1; /* 8:8 */
+			picreg_t int_state        :	8; /* 7:0 */
+		} pic_p_mult_int_fld_s;
+	} pic_p_mult_int_u_t;
+/*
+ * Force Always Interrupt (x) Register
+ *
+ * A write to this data independent write only register will force a set inter-
+ * rupt to occur as if the interrupt line had transitioned. If the interrupt line
+ * is already active an addition set interrupt packet is set. All buffer flush op-
+ * erations also occur on this operation.
+ */
+
+
+/*
+ * Force Interrupt (x) Register
+ *
+ * A write to this data independent write only register in conjunction with
+ * the assertion of the corresponding interrupt line will force a set interrupt
+ * to occur as if the interrupt line had transitioned. The interrupt line must
+ * be active for this operation to generate a set packet, otherwise the write
+ * PIO is ignored. All buffer flush operations also occur when the set packet
+ * is sent on this operation.
+ */
+
+
+/*
+ * Device Registers
+ *
+ * The Device registers contain device specific and mapping information.
+ */
+	typedef union pic_device_reg_u {
+		picreg_t	pic_device_reg_regval;
+		struct {
+			picreg_t               :	32; /* 63:32 */
+			picreg_t               :	2; /* 31:30 */
+			picreg_t en_virtual1   :	1; /* 29:29 */
+			picreg_t en_error_lock :	1; /* 28:28 */
+			picreg_t en_page_chk   :	1; /* 27:27 */
+			picreg_t force_pci_par :	1; /* 26:26 */
+			picreg_t en_virtual0   :	1; /* 25:25 */
+			picreg_t               :	1; /* 24:24 */
+			picreg_t dir_wrt_gen   :	1; /* 23:23 */
+			picreg_t dev_size      :	1; /* 22:22 */
+			picreg_t real_time     :	1; /* 21:21 */
+			picreg_t               :	1; /* 20:20 */
+			picreg_t swap_direct   :	1; /* 19:19 */
+			picreg_t prefetch      :	1; /* 18:18 */
+			picreg_t precise       :	1; /* 17:17 */
+			picreg_t coherent      :	1; /* 16:16 */
+			picreg_t barrier       :	1; /* 15:15 */
+			picreg_t gbr           :	1; /* 14:14 */
+			picreg_t dev_swap      :	1; /* 13:13 */
+			picreg_t dev_io_mem    :	1; /* 12:12 */
+			picreg_t dev_off       :	12; /* 11:0 */
+		} pic_device_reg_fld_s;
+	} pic_device_reg_u_t;
+/*
+ * Device (x) Write Request Buffer Flush
+ *
+ * When read, this register will return a 0x00 after the write buffer associat-
+ * ed with the device has been flushed. (PCI Only)
+ */
+
+
+/*
+ * Even Device Read Response Buffer Register (PCI Only)
+ *
+ * This register is use to allocate the read response buffers for the even num-
+ * bered devices. (0,2)
+ */
+	typedef union pic_p_even_resp_u {
+		picreg_t	pic_p_even_resp_regval;
+		struct {
+			picreg_t              :	32; /* 63:32 */
+			picreg_t buff_14_en   :	1; /* 31:31 */
+			picreg_t buff_14_vdev :	2; /* 30:29 */
+			picreg_t buff_14_pdev :	1; /* 28:28 */
+			picreg_t buff_12_en   :	1; /* 27:27 */
+			picreg_t buff_12_vdev :	2; /* 26:25 */
+			picreg_t buff_12_pdev :	1; /* 24:24 */
+			picreg_t buff_10_en   :	1; /* 23:23 */
+			picreg_t buff_10_vdev :	2; /* 22:21 */
+			picreg_t buff_10_pdev :	1; /* 20:20 */
+			picreg_t buff_8_en    :	1; /* 19:19 */
+			picreg_t buff_8_vdev  :	2; /* 18:17 */
+			picreg_t buff_8_pdev  :	1; /* 16:16 */
+			picreg_t buff_6_en    :	1; /* 15:15 */
+			picreg_t buff_6_vdev  :	2; /* 14:13 */
+			picreg_t buff_6_pdev  :	1; /* 12:12 */
+			picreg_t buff_4_en    :	1; /* 11:11 */
+			picreg_t buff_4_vdev  :	2; /* 10:9 */
+			picreg_t buff_4_pdev  :	1; /* 8:8 */
+			picreg_t buff_2_en    :	1; /* 7:7 */
+			picreg_t buff_2_vdev  :	2; /* 6:5 */
+			picreg_t buff_2_pdev  :	1; /* 4:4 */
+			picreg_t buff_0_en    :	1; /* 3:3 */
+			picreg_t buff_0_vdev  :	2; /* 2:1 */
+			picreg_t buff_0_pdev  :	1; /* 0:0 */
+		} pic_p_even_resp_fld_s;
+	} pic_p_even_resp_u_t;
+/*
+ * Odd Device Read Response Buffer Register (PCI Only)
+ *
+ * This register is use to allocate the read response buffers for the odd num-
+ * bered devices. (1,3))
+ */
+	typedef union pic_p_odd_resp_u {
+		picreg_t	pic_p_odd_resp_regval;
+		struct {
+			picreg_t              :	32; /* 63:32 */
+			picreg_t buff_15_en   :	1; /* 31:31 */
+			picreg_t buff_15_vdev :	2; /* 30:29 */
+			picreg_t buff_15_pdev :	1; /* 28:28 */
+			picreg_t buff_13_en   :	1; /* 27:27 */
+			picreg_t buff_13_vdev :	2; /* 26:25 */
+			picreg_t buff_13_pdev :	1; /* 24:24 */
+			picreg_t buff_11_en   :	1; /* 23:23 */
+			picreg_t buff_11_vdev :	2; /* 22:21 */
+			picreg_t buff_11_pdev :	1; /* 20:20 */
+			picreg_t buff_9_en    :	1; /* 19:19 */
+			picreg_t buff_9_vdev  :	2; /* 18:17 */
+			picreg_t buff_9_pdev  :	1; /* 16:16 */
+			picreg_t buff_7_en    :	1; /* 15:15 */
+			picreg_t buff_7_vdev  :	2; /* 14:13 */
+			picreg_t buff_7_pdev  :	1; /* 12:12 */
+			picreg_t buff_5_en    :	1; /* 11:11 */
+			picreg_t buff_5_vdev  :	2; /* 10:9 */
+			picreg_t buff_5_pdev  :	1; /* 8:8 */
+			picreg_t buff_3_en    :	1; /* 7:7 */
+			picreg_t buff_3_vdev  :	2; /* 6:5 */
+			picreg_t buff_3_pdev  :	1; /* 4:4 */
+			picreg_t buff_1_en    :	1; /* 3:3 */
+			picreg_t buff_1_vdev  :	2; /* 2:1 */
+			picreg_t buff_1_pdev  :	1; /* 0:0 */
+		} pic_p_odd_resp_fld_s;
+	} pic_p_odd_resp_u_t;
+/*
+ * Read Response Buffer Status Register (PCI Only)
+ *
+ * This read only register contains the current response buffer status.
+ */
+	typedef union pic_p_resp_status_u {
+		picreg_t	pic_p_resp_status_regval;
+		struct {
+			picreg_t           :	32; /* 63:32 */
+			picreg_t rrb_valid :	16; /* 31:16 */
+			picreg_t rrb_inuse :	16; /* 15:0 */
+		} pic_p_resp_status_fld_s;
+	} pic_p_resp_status_u_t;
+/*
+ * Read Response Buffer Clear Register (PCI Only)
+ *
+ * A write to this register clears the current contents of the buffer.
+ */
+	typedef union pic_p_resp_clear_u {
+		picreg_t	pic_p_resp_clear_regval;
+		struct {
+			picreg_t           :	32; /* 63:32 */
+			picreg_t           :	16; /* 31:16 */
+			picreg_t rrb_clear :	16; /* 15:0 */
+		} pic_p_resp_clear_fld_s;
+	} pic_p_resp_clear_u_t;
+/*
+ * PCI Read Response Buffer (x) Upper Address Match
+ *
+ * The PCI Bridge read response buffer upper address register is a read only
+ * register which contains the upper 16-bits of the address and status used to
+ * select the buffer for a PCI transaction.
+ */
+	typedef union pic_p_buf_upper_addr_match_u {
+		picreg_t	pic_p_buf_upper_addr_match_regval;
+		struct {
+			picreg_t          :	32; /* 63:32 */
+			picreg_t filled   :	1; /* 31:31 */
+			picreg_t armed    :	1; /* 30:30 */
+			picreg_t flush    :	1; /* 29:29 */
+			picreg_t xerr     :	1; /* 28:28 */
+			picreg_t pkterr   :	1; /* 27:27 */
+			picreg_t timeout  :	1; /* 26:26 */
+			picreg_t prefetch :	1; /* 25:25 */
+			picreg_t precise  :	1; /* 24:24 */
+			picreg_t dw_be    :	8; /* 23:16 */
+			picreg_t upp_addr :	16; /* 15:0 */
+		} pic_p_buf_upper_addr_match_fld_s;
+	} pic_p_buf_upper_addr_match_u_t;
+/*
+ * PCI Read Response Buffer (x) Lower Address Match
+ *
+ * The PCI Bridge read response buffer lower address Match register is a
+ * read only register which contains the address and status used to select the
+ * buffer for a PCI transaction.
+ */
+	typedef union pic_p_buf_lower_addr_match_u {
+		picreg_t	pic_p_buf_lower_addr_match_regval;
+		struct {
+			picreg_t filled   :	1; /* 63:63 */
+			picreg_t armed    :	1; /* 62:62 */
+			picreg_t flush    :	1; /* 61:61 */
+			picreg_t xerr     :	1; /* 60:60 */
+			picreg_t pkterr   :	1; /* 59:59 */
+			picreg_t timeout  :	1; /* 58:58 */
+			picreg_t prefetch :	1; /* 57:57 */
+			picreg_t precise  :	1; /* 56:56 */
+			picreg_t dw_be    :	8; /* 55:48 */
+			picreg_t upp_addr :	16; /* 47:32 */
+			picreg_t low_addr :	32; /* 31:0 */
+		} pic_p_buf_lower_addr_match_fld_s;
+	} pic_p_buf_lower_addr_match_u_t;
+/*
+ * PCI Buffer (x) Flush Count with Data Touch Register
+ *
+ * This counter is incremented each time the corresponding response buffer
+ * is flushed after at least a single data element in the buffer is used. A word
+ * write to this address clears the count.
+ */
+	typedef union pic_flush_w_touch_u {
+		picreg_t	pic_flush_w_touch_regval;
+		struct {
+			picreg_t           :	32; /* 63:32 */
+			picreg_t           :	16; /* 31:16 */
+			picreg_t touch_cnt :	16; /* 15:0 */
+		} pic_flush_w_touch_fld_s;
+	} pic_flush_w_touch_u_t;
+/*
+ * PCI Buffer (x) Flush Count w/o Data Touch Register
+ *
+ * This counter is incremented each time the corresponding response buffer
+ * is flushed without any data element in the buffer being used. A word
+ * write to this address clears the count.
+ */
+	typedef union pic_flush_wo_touch_u {
+		picreg_t	pic_flush_wo_touch_regval;
+		struct {
+			picreg_t             :	32; /* 63:32 */
+			picreg_t             :	16; /* 31:16 */
+			picreg_t notouch_cnt :	16; /* 15:0 */
+		} pic_flush_wo_touch_fld_s;
+	} pic_flush_wo_touch_u_t;
+/*
+ * PCI Buffer (x) Request in Flight Count Register
+ *
+ * This counter is incremented on each bus clock while the request is in-
+ * flight. A word write to this address clears the count. ]
+ */
+	typedef union pic_inflight_u {
+		picreg_t	pic_inflight_regval;
+		struct {
+			picreg_t              :	32; /* 63:32 */
+			picreg_t              :	16; /* 31:16 */
+			picreg_t inflight_cnt :	16; /* 15:0 */
+		} pic_inflight_fld_s;
+	} pic_inflight_u_t;
+/*
+ * PCI Buffer (x) Prefetch Request Count Register
+ *
+ * This counter is incremented each time the request using this buffer was
+ * generated from the prefetcher. A word write to this address clears the
+ * count.
+ */
+	typedef union pic_prefetch_u {
+		picreg_t	pic_prefetch_regval;
+		struct {
+			picreg_t              :	32; /* 63:32 */
+			picreg_t              :	16; /* 31:16 */
+			picreg_t prefetch_cnt :	16; /* 15:0 */
+		} pic_prefetch_fld_s;
+	} pic_prefetch_u_t;
+/*
+ * PCI Buffer (x) Total PCI Retry Count Register
+ *
+ * This counter is incremented each time a PCI bus retry occurs and the ad-
+ * dress matches the tag for the selected buffer. The buffer must also has this
+ * request in-flight. A word write to this address clears the count.
+ */
+	typedef union pic_total_pci_retry_u {
+		picreg_t	pic_total_pci_retry_regval;
+		struct {
+			picreg_t           :	32; /* 63:32 */
+			picreg_t           :	16; /* 31:16 */
+			picreg_t retry_cnt :	16; /* 15:0 */
+		} pic_total_pci_retry_fld_s;
+	} pic_total_pci_retry_u_t;
+/*
+ * PCI Buffer (x) Max PCI Retry Count Register
+ *
+ * This counter is contains the maximum retry count for a single request
+ * which was in-flight for this buffer. A word write to this address clears the
+ * count.
+ */
+	typedef union pic_max_pci_retry_u {
+		picreg_t	pic_max_pci_retry_regval;
+		struct {
+			picreg_t               :	32; /* 63:32 */
+			picreg_t               :	16; /* 31:16 */
+			picreg_t max_retry_cnt :	16; /* 15:0 */
+		} pic_max_pci_retry_fld_s;
+	} pic_max_pci_retry_u_t;
+/*
+ * PCI Buffer (x) Max Latency Count Register
+ *
+ * This counter is contains the maximum count (in bus clocks) for a single
+ * request which was in-flight for this buffer. A word write to this address
+ * clears the count.
+ */
+	typedef union pic_max_latency_u {
+		picreg_t	pic_max_latency_regval;
+		struct {
+			picreg_t                 :	32; /* 63:32 */
+			picreg_t                 :	16; /* 31:16 */
+			picreg_t max_latency_cnt :	16; /* 15:0 */
+		} pic_max_latency_fld_s;
+	} pic_max_latency_u_t;
+/*
+ * PCI Buffer (x) Clear All Register
+ *
+ * Any access to this register clears all the count values for the (x) registers.
+ */
+
+
+/*
+ * PCI-X Registers
+ *
+ * This register contains the address in the read buffer structure. There are
+ * 16 read buffer structures.
+ */
+	typedef union pic_rd_buf_addr_u {
+		picreg_t	pic_rd_buf_addr_regval;
+		struct {
+			picreg_t pcix_err_addr :	64; /* 63:0 */
+		} pic_rd_buf_addr_fld_s;
+	} pic_rd_buf_addr_u_t;
+/*
+ * PCI-X Read Buffer (x) Attribute Register
+ *
+ * This register contains the attribute data in the read buffer structure. There
+ * are  16 read buffer structures.
+ */
+	typedef union pic_px_read_buf_attr_u {
+		picreg_t	pic_px_read_buf_attr_regval;
+		struct {
+			picreg_t                :	16; /* 63:48 */
+			picreg_t bus_cmd        :	4; /* 47:44 */
+			picreg_t byte_cnt       :	12; /* 43:32 */
+			picreg_t entry_valid    :	1; /* 31:31 */
+			picreg_t ns             :	1; /* 30:30 */
+			picreg_t ro             :	1; /* 29:29 */
+			picreg_t tag            :	5; /* 28:24 */
+			picreg_t bus_num        :	8; /* 23:16 */
+			picreg_t dev_num        :	5; /* 15:11 */
+			picreg_t fun_num        :	3; /* 10:8 */
+			picreg_t                :	2; /* 7:6 */
+			picreg_t f_buffer_index :	6; /* 5:0 */
+		} pic_px_read_buf_attr_fld_s;
+	} pic_px_read_buf_attr_u_t;
+/*
+ * PCI-X Write Buffer (x) Address Register
+ *
+ * This register contains the address in the write buffer structure. There are
+ * 8 write buffer structures.
+ */
+	typedef union pic_px_write_buf_addr_u {
+		picreg_t	pic_px_write_buf_addr_regval;
+		struct {
+			picreg_t pcix_err_addr :	64; /* 63:0 */
+		} pic_px_write_buf_addr_fld_s;
+	} pic_px_write_buf_addr_u_t;
+/*
+ * PCI-X Write Buffer (x) Attribute Register
+ *
+ * This register contains the attribute data in the write buffer structure.
+ * There are 8 write buffer structures.
+ */
+	typedef union pic_px_write_buf_attr_u {
+		picreg_t	pic_px_write_buf_attr_regval;
+		struct {
+			picreg_t                :	16; /* 63:48 */
+			picreg_t bus_cmd        :	4; /* 47:44 */
+			picreg_t byte_cnt       :	12; /* 43:32 */
+			picreg_t entry_valid    :	1; /* 31:31 */
+			picreg_t ns             :	1; /* 30:30 */
+			picreg_t ro             :	1; /* 29:29 */
+			picreg_t tag            :	5; /* 28:24 */
+			picreg_t bus_num        :	8; /* 23:16 */
+			picreg_t dev_num        :	5; /* 15:11 */
+			picreg_t fun_num        :	3; /* 10:8 */
+			picreg_t                :	2; /* 7:6 */
+			picreg_t f_buffer_index :	6; /* 5:0 */
+		} pic_px_write_buf_attr_fld_s;
+	} pic_px_write_buf_attr_u_t;
+/*
+ * PCI-X Write Buffer (x) Valid Register
+ *
+ * This register contains the valid or inuse cache lines for this buffer struc-
+ * ture.
+ */
+	typedef union pic_px_write_buf_valid_u {
+		picreg_t	pic_px_write_buf_valid_regval;
+		struct {
+			picreg_t                :	32; /* 63:32 */
+			picreg_t wrt_valid_buff :	32; /* 31:0 */
+		} pic_px_write_buf_valid_fld_s;
+	} pic_px_write_buf_valid_u_t;
+
+#endif				/* __ASSEMBLY__ */
+#endif                          /* _ASM_SN_PCI_PIC_H */
diff -Nru a/include/asm-ia64/sn/rw_mmr.h b/include/asm-ia64/sn/rw_mmr.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ia64/sn/rw_mmr.h	Mon Feb 24 05:16:55 2003
@@ -0,0 +1,73 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+#ifndef _ASM_IA64_SN_RW_MMR_H
+#define _ASM_IA64_SN_RW_MMR_H
+
+
+/*
+ * This file contains macros used to access MMR registers via
+ * uncached physical addresses.
+ * 	pio_phys_read_mmr  - read an MMR
+ * 	pio_phys_write_mmr - write an MMR
+ * 	pio_atomic_phys_write_mmrs - atomically write 2 MMRs with psr.ic=0
+ * 		(interrupt collection)
+ *
+ * Addresses passed to these routines should be uncached physical addresses
+ * ie., 0x80000....
+ */
+
+
+extern inline long
+pio_phys_read_mmr(volatile long *mmr) 
+{
+	long val;
+        asm volatile
+            ("mov r2=psr;;"
+             "rsm psr.i | psr.dt;;"
+             "srlz.i;;"
+             "ld8.acq %0=[%1];;"
+             "mov psr.l=r2;;"
+             "srlz.i;;"
+             : "=r"(val)
+             : "r"(mmr)
+	     : "r2");
+        return val;
+}
+
+
+
+extern inline void
+pio_phys_write_mmr(volatile long *mmr, long val) 
+{
+        asm volatile
+            ("mov r2=psr;;"
+             "rsm psr.i | psr.dt;;"
+             "srlz.i;;"
+             "st8.rel [%0]=%1;;"
+             "mov psr.l=r2;;"
+             "srlz.i;;"
+	     :: "r"(mmr), "r"(val)
+             : "r2", "memory");
+}            
+
+extern inline void
+pio_atomic_phys_write_mmrs(volatile long *mmr1, long val1, volatile long *mmr2, long val2) 
+{
+        asm volatile
+            ("mov r2=psr;;"
+             "rsm psr.i | psr.dt | psr.ic;;"
+             "srlz.i;;"
+             "st8.rel [%0]=%1;"
+             "st8.rel [%2]=%3;;"
+             "mov psr.l=r2;;"
+             "srlz.i;;"
+	     :: "r"(mmr1), "r"(val1), "r"(mmr2), "r"(val2)
+             : "r2", "memory");
+}            
+
+#endif /* _ASM_IA64_SN_RW_MMR_H */
diff -Nru a/include/asm-ia64/sn/sn2/geo.h b/include/asm-ia64/sn/sn2/geo.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ia64/sn/sn2/geo.h	Mon Feb 24 04:35:40 2003
@@ -0,0 +1,109 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#ifndef __SYS_SN_SN2_GEO_H__
+#define __SYS_SN_SN2_GEO_H__
+
+/* Headers required by declarations in this file */
+
+#include <asm/sn/slotnum.h>
+
+
+/* The geoid_t implementation below is based loosely on the pcfg_t
+   implementation in sys/SN/promcfg.h. */
+
+/* Type declaractions */
+
+/* Size of a geoid_t structure (must be before decl. of geoid_u) */
+#define GEOID_SIZE	8	/* Would 16 be better?  The size can
+				   be different on different platforms. */
+
+#define MAX_SLABS	0xe	/* slabs per module */
+
+typedef unsigned char	geo_type_t;
+
+/* Fields common to all substructures */
+typedef struct geo_any_s {
+    moduleid_t	module;		/* The module (box) this h/w lives in */
+    geo_type_t	type;		/* What type of h/w is named by this geoid_t */
+    slabid_t	slab;		/* The logical assembly within the module */
+} geo_any_t;
+
+/* Additional fields for particular types of hardware */
+typedef struct geo_node_s {
+    geo_any_t	any;		/* No additional fields needed */
+} geo_node_t;
+
+typedef struct geo_rtr_s {
+    geo_any_t	any;		/* No additional fields needed */
+} geo_rtr_t;
+
+typedef struct geo_iocntl_s {
+    geo_any_t	any;		/* No additional fields needed */
+} geo_iocntl_t;
+
+typedef struct geo_pcicard_s {
+    geo_iocntl_t	any;
+    char		bus;	/* Bus/widget number */
+    slotid_t		slot;	/* PCI slot number */
+} geo_pcicard_t;
+
+/* Subcomponents of a node */
+typedef struct geo_cpu_s {
+    geo_node_t	node;
+    char	slice;		/* Which CPU on the node */
+} geo_cpu_t;
+
+typedef struct geo_mem_s {
+    geo_node_t	node;
+    char	membus;		/* The memory bus on the node */
+    char	memslot;	/* The memory slot on the bus */
+} geo_mem_t;
+
+
+typedef union geoid_u {
+    geo_any_t	any;
+    geo_node_t	node;
+    geo_iocntl_t	iocntl;
+    geo_pcicard_t	pcicard;
+    geo_rtr_t	rtr;
+    geo_cpu_t	cpu;
+    geo_mem_t	mem;
+    char	padsize[GEOID_SIZE];
+} geoid_t;
+
+
+/* Preprocessor macros */
+
+#define GEO_MAX_LEN	48	/* max. formatted length, plus some pad:
+				   module/001c07/slab/5/node/memory/2/slot/4 */
+
+/* Values for geo_type_t */
+#define GEO_TYPE_INVALID	0
+#define GEO_TYPE_MODULE		1
+#define GEO_TYPE_NODE		2
+#define GEO_TYPE_RTR		3
+#define GEO_TYPE_IOCNTL		4
+#define GEO_TYPE_IOCARD		5
+#define GEO_TYPE_CPU		6
+#define GEO_TYPE_MEM		7
+#define GEO_TYPE_MAX		(GEO_TYPE_MEM+1)
+
+/* Parameter for hwcfg_format_geoid_compt() */
+#define GEO_COMPT_MODULE	1
+#define GEO_COMPT_SLAB		2
+#define GEO_COMPT_IOBUS		3
+#define GEO_COMPT_IOSLOT	4
+#define GEO_COMPT_CPU		5
+#define GEO_COMPT_MEMBUS	6
+#define GEO_COMPT_MEMSLOT	7
+
+#define GEO_INVALID_STR		"<invalid>"
+
+#endif /* __SYS_SN_SN2_GEO_H__ */
diff -Nru a/include/asm-ia64/spinlock.h b/include/asm-ia64/spinlock.h
--- a/include/asm-ia64/spinlock.h	Tue Jan 14 21:57:29 2003
+++ b/include/asm-ia64/spinlock.h	Tue Mar  4 18:38:46 2003
@@ -183,6 +183,19 @@
 		:: "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory");		\
 } while(0)
 
+#define _raw_write_trylock(rw)							\
+({										\
+	register long result;							\
+										\
+	__asm__ __volatile__ (							\
+		"mov ar.ccv = r0\n"						\
+		"dep r29 = -1, r0, 31, 1\n"					\
+		";;\n"								\
+		"cmpxchg4.acq %0 = [%1], r29, ar.ccv\n"				\
+		: "=r"(result) : "r"(rw) : "ar.ccv", "r29", "memory");		\
+	(result == 0);								\
+})
+
 #define _raw_write_unlock(x)								\
 ({											\
 	smp_mb__before_clear_bit();	/* need barrier before releasing lock... */	\
diff -Nru a/include/asm-ia64/system.h b/include/asm-ia64/system.h
--- a/include/asm-ia64/system.h	Fri Jan 24 11:56:49 2003
+++ b/include/asm-ia64/system.h	Thu Jan 30 06:15:28 2003
@@ -206,7 +206,7 @@
 
 #ifdef CONFIG_PERFMON
   DECLARE_PER_CPU(unsigned long, pfm_syst_info);
-# define PERFMON_IS_SYSWIDE() (get_cpu_var(pfm_syst_info) & 0x1)
+# define PERFMON_IS_SYSWIDE() (__get_cpu_var(pfm_syst_info) & 0x1)
 #else
 # define PERFMON_IS_SYSWIDE() (0)
 #endif
diff -Nru a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
--- a/include/asm-ia64/thread_info.h	Mon Dec 16 18:06:43 2002
+++ b/include/asm-ia64/thread_info.h	Thu Mar  6 21:11:46 2003
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002 Hewlett-Packard Co
+ * Copyright (C) 2002-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 #ifndef _ASM_IA64_THREAD_INFO_H
@@ -15,7 +15,8 @@
 #define TI_ADDR_LIMIT	0x10
 #define TI_PRE_COUNT	0x18
 
-#define PREEMPT_ACTIVE	0x4000000
+#define PREEMPT_ACTIVE_BIT 30
+#define PREEMPT_ACTIVE	(1 << PREEMPT_ACTIVE_BIT)
 
 #ifndef __ASSEMBLY__
 
@@ -50,6 +51,7 @@
 
 /* how to get the thread information struct from C */
 #define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
+#define free_thread_info(ti)	/* nothing */
 
 #endif /* !__ASSEMBLY */
 
diff -Nru a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h
--- a/include/asm-ia64/topology.h	Mon Feb  3 23:46:59 2003
+++ b/include/asm-ia64/topology.h	Mon Mar  3 16:00:00 2003
@@ -26,7 +26,7 @@
 /*
  * Returns a bitmask of CPUs on Node 'node'.
  */
-#define node_to_cpumask(node) (node_to_cpumask[node])
+#define node_to_cpumask(node) (node_to_cpu_mask[node])
 
 #else
 #define cpu_to_node(cpu) (0)
diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
--- a/include/asm-ia64/unistd.h	Tue Jan 21 18:31:31 2003
+++ b/include/asm-ia64/unistd.h	Thu Mar  6 14:56:33 2003
@@ -223,7 +223,7 @@
 #define __NR_sched_setaffinity		1231
 #define __NR_sched_getaffinity		1232
 #define __NR_set_tid_address		1233
-/* 1234 available for reuse */
+#define __NR_fadvise64			1234
 /* 1235 available for reuse */
 #define __NR_exit_group			1236
 #define __NR_lookup_dcookie		1237
@@ -237,6 +237,15 @@
 #define __NR_epoll_wait			1245
 #define __NR_restart_syscall		1246
 #define __NR_semtimedop			1247
+#define __NR_sys_timer_create		1248
+#define __NR_sys_timer_settime		1249
+#define __NR_sys_timer_gettime		1250
+#define __NR_sys_timer_getoverrun	1251
+#define __NR_sys_timer_delete		1252
+#define __NR_sys_clock_settime		1253
+#define __NR_sys_clock_gettime		1254
+#define __NR_sys_clock_getres		1255
+#define __NR_sys_clock_nanosleep	1256
 
 #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
 
diff -Nru a/include/asm-ia64/unwind.h b/include/asm-ia64/unwind.h
--- a/include/asm-ia64/unwind.h	Mon Feb  4 23:43:07 2002
+++ b/include/asm-ia64/unwind.h	Mon Mar  3 16:00:00 2003
@@ -60,6 +60,7 @@
 	unsigned long ip;		/* instruction pointer value */
 	unsigned long pr;		/* current predicate values */
 	unsigned long *cfm_loc;		/* cfm save location (or NULL) */
+	unsigned long pt;		/* struct pt_regs location */
 
 	struct task_struct *task;
 	struct switch_stack *sw;
diff -Nru a/include/asm-m68k/processor.h b/include/asm-m68k/processor.h
--- a/include/asm-m68k/processor.h	Mon Nov  4 02:28:50 2002
+++ b/include/asm-m68k/processor.h	Mon Mar 10 10:20:31 2003
@@ -112,6 +112,9 @@
 {
 }
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 /*
diff -Nru a/include/asm-m68k/sun3_pgtable.h b/include/asm-m68k/sun3_pgtable.h
--- a/include/asm-m68k/sun3_pgtable.h	Mon May 20 06:43:35 2002
+++ b/include/asm-m68k/sun3_pgtable.h	Thu Mar  6 08:19:09 2003
@@ -196,10 +196,10 @@
 }
 
 /* Find an entry in the third-level pagetable. */
-#define __pte_offset(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
-#define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + __pte_offset(address))
+#define pte_index(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
+#define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address))
 /* FIXME: should we bother with kmap() here? */
-#define pte_offset_map(pmd, address) ((pte_t *)kmap(pmd_page(*pmd)) + __pte_offset(address))
+#define pte_offset_map(pmd, address) ((pte_t *)kmap(pmd_page(*pmd)) + pte_index(address))
 #define pte_offset_map_nested(pmd, address) pte_offset_map(pmd, address)
 #define pte_unmap(pte) kunmap(pte)
 #define pte_unmap_nested(pte) kunmap(pte)
diff -Nru a/include/asm-m68knommu/processor.h b/include/asm-m68knommu/processor.h
--- a/include/asm-m68knommu/processor.h	Tue Dec 10 16:41:17 2002
+++ b/include/asm-m68knommu/processor.h	Mon Mar 10 10:20:31 2003
@@ -108,6 +108,9 @@
 {
 }
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 /*
diff -Nru a/include/asm-mips/processor.h b/include/asm-mips/processor.h
--- a/include/asm-mips/processor.h	Mon Feb 24 12:16:15 2003
+++ b/include/asm-mips/processor.h	Mon Mar 10 10:20:31 2003
@@ -208,6 +208,9 @@
 /* Free all resources held by a thread. */
 #define release_thread(thread) do { } while(0)
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 /*
diff -Nru a/include/asm-mips64/processor.h b/include/asm-mips64/processor.h
--- a/include/asm-mips64/processor.h	Mon Feb 24 12:16:15 2003
+++ b/include/asm-mips64/processor.h	Mon Mar 10 10:20:31 2003
@@ -231,6 +231,9 @@
 /* Free all resources held by a thread. */
 #define release_thread(thread) do { } while(0)
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 /*
diff -Nru a/include/asm-parisc/bug.h b/include/asm-parisc/bug.h
--- a/include/asm-parisc/bug.h	Sun Jan  6 03:51:59 2002
+++ b/include/asm-parisc/bug.h	Sun Feb 16 15:52:20 2003
@@ -2,10 +2,7 @@
 #define _PARISC_BUG_H
 
 /*
- * Tell the user there is some problem. Beep too, so we can
- * see^H^H^Hhear bugs in early bootup as well!
- *
- * We don't beep yet.  prumpf
+ * Tell the user there is some problem.
  */
 #define BUG() do { \
 	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
diff -Nru a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
--- a/include/asm-parisc/pgtable.h	Tue Feb 18 10:12:35 2003
+++ b/include/asm-parisc/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -329,9 +329,9 @@
 #endif
 
 /* Find an entry in the third-level page table.. */ 
-#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
+#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
 #define pte_offset_kernel(pmd, address) \
-	((pte_t *) pmd_page_kernel(*(pmd)) + __pte_offset(address))
+	((pte_t *) pmd_page_kernel(*(pmd)) + pte_index(address))
 #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_unmap(pte) do { } while (0)
diff -Nru a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h
--- a/include/asm-parisc/processor.h	Sun Nov 10 05:59:06 2002
+++ b/include/asm-parisc/processor.h	Mon Mar 10 10:20:31 2003
@@ -290,6 +290,9 @@
 extern void release_thread(struct task_struct *);
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm);
 
 static inline unsigned long get_wchan(struct task_struct *p)
diff -Nru a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
--- a/include/asm-ppc/pgtable.h	Mon Oct  7 15:51:14 2002
+++ b/include/asm-ppc/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -494,14 +494,14 @@
 }
 
 /* Find an entry in the third-level page table.. */
-#define __pte_offset(address)		\
+#define pte_index(address)		\
 	(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir, addr)	\
-	((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(addr))
+	((pte_t *) pmd_page_kernel(*(dir)) + pte_index(addr))
 #define pte_offset_map(dir, addr)		\
-	((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE0) + __pte_offset(addr))
+	((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE0) + pte_index(addr))
 #define pte_offset_map_nested(dir, addr)	\
-	((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE1) + __pte_offset(addr))
+	((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE1) + pte_index(addr))
 
 #define pte_unmap(pte)		kunmap_atomic(pte, KM_PTE0)
 #define pte_unmap_nested(pte)	kunmap_atomic(pte, KM_PTE1)
diff -Nru a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h
--- a/include/asm-ppc/processor.h	Wed Jan 15 20:09:48 2003
+++ b/include/asm-ppc/processor.h	Mon Mar 10 10:20:31 2003
@@ -608,6 +608,9 @@
 void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
 void release_thread(struct task_struct *);
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 /*
  * Create a new kernel thread.
  */
diff -Nru a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
--- a/include/asm-ppc64/processor.h	Wed Feb 19 09:35:28 2003
+++ b/include/asm-ppc64/processor.h	Mon Mar 10 10:20:31 2003
@@ -601,6 +601,9 @@
 void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
 void release_thread(struct task_struct *);
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 /*
  * Create a new kernel thread.
  */
diff -Nru a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
--- a/include/asm-s390/pgtable.h	Mon Nov 18 12:11:53 2002
+++ b/include/asm-s390/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -467,9 +467,9 @@
 }
 
 /* Find an entry in the third-level page table.. */
-#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
+#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
 #define pte_offset_kernel(pmd, address) \
-	((pte_t *) pmd_page_kernel(*(pmd)) + __pte_offset(address))
+	((pte_t *) pmd_page_kernel(*(pmd)) + pte_index(address))
 #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_unmap(pte) do { } while (0)
diff -Nru a/include/asm-s390/processor.h b/include/asm-s390/processor.h
--- a/include/asm-s390/processor.h	Mon Feb 24 10:19:06 2003
+++ b/include/asm-s390/processor.h	Mon Mar 10 10:20:31 2003
@@ -114,6 +114,9 @@
 extern void release_thread(struct task_struct *);
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 /*
  * Return saved PC of a blocked thread.
  */
diff -Nru a/include/asm-s390x/pgtable.h b/include/asm-s390x/pgtable.h
--- a/include/asm-s390x/pgtable.h	Mon Feb 24 10:25:00 2003
+++ b/include/asm-s390x/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -488,14 +488,14 @@
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
 /* Find an entry in the second-level page table.. */
-#define __pmd_offset(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
 #define pmd_offset(dir,addr) \
-	((pmd_t *) pgd_page_kernel(*(dir)) + __pmd_offset(addr))
+	((pmd_t *) pgd_page_kernel(*(dir)) + pmd_index(addr))
 
 /* Find an entry in the third-level page table.. */
-#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
+#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
 #define pte_offset_kernel(pmd, address) \
-	((pte_t *) pmd_page_kernel(*(pmd)) + __pte_offset(address))
+	((pte_t *) pmd_page_kernel(*(pmd)) + pte_index(address))
 #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_unmap(pte) do { } while (0)
diff -Nru a/include/asm-s390x/processor.h b/include/asm-s390x/processor.h
--- a/include/asm-s390x/processor.h	Mon Feb 24 10:19:08 2003
+++ b/include/asm-s390x/processor.h	Mon Mar 10 10:20:31 2003
@@ -129,6 +129,9 @@
 extern void release_thread(struct task_struct *);
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 /*
  * Return saved PC of a blocked thread.
  */
diff -Nru a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
--- a/include/asm-sh/pgtable.h	Mon Sep  9 14:01:14 2002
+++ b/include/asm-sh/pgtable.h	Thu Mar  6 17:44:46 2003
@@ -98,8 +98,6 @@
 
 #endif /* !__ASSEMBLY__ */
 
-#define __beep() asm("")
-
 #define PMD_SIZE	(1UL << PMD_SHIFT)
 #define PMD_MASK	(~(PMD_SIZE-1))
 #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
@@ -274,17 +272,16 @@
 
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
-#define __pgd_offset(address) pgd_index(address)
 #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
 
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
 /* Find an entry in the third-level page table.. */
-#define __pte_offset(address) \
+#define pte_index(address) \
 		((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset(dir, address) ((pte_t *) pmd_page(*(dir)) + \
-			__pte_offset(address))
+			pte_index(address))
 
 extern void update_mmu_cache(struct vm_area_struct * vma,
 			     unsigned long address, pte_t pte);
diff -Nru a/include/asm-sh/processor.h b/include/asm-sh/processor.h
--- a/include/asm-sh/processor.h	Thu Nov 21 10:04:20 2002
+++ b/include/asm-sh/processor.h	Mon Mar 10 10:20:31 2003
@@ -134,6 +134,10 @@
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 /*
  * create a kernel thread without removing it from tasklists
  */
diff -Nru a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h
--- a/include/asm-sparc/processor.h	Tue Dec  3 15:19:14 2002
+++ b/include/asm-sparc/processor.h	Mon Mar 10 10:20:31 2003
@@ -139,6 +139,9 @@
 #define release_thread(tsk)		do { } while(0)
 extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern unsigned long get_wchan(struct task_struct *);
 
 #define KSTK_EIP(tsk)  ((tsk)->thread.kregs->pc)
diff -Nru a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h
--- a/include/asm-sparc/termios.h	Mon Feb  4 23:41:04 2002
+++ b/include/asm-sparc/termios.h	Fri Mar  7 15:36:56 2003
@@ -92,7 +92,7 @@
 	reprint=^R	discard=^U	werase=^W	lnext=^V
 	vmin=\1         vtime=\0
 */
-#define INIT_C_CC "\003\034\177\025\004\000\000\000\021\023\032\031\022\025\027\026\001\000"
+#define INIT_C_CC "\003\034\177\025\004\000\000\000\021\023\032\031\022\025\027\026\001"
 
 /*
  * Translate a "termio" structure into a "termios". Ugh.
diff -Nru a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
--- a/include/asm-sparc64/pgtable.h	Thu Oct  3 11:02:09 2002
+++ b/include/asm-sparc64/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -273,11 +273,11 @@
 					((address >> PMD_SHIFT) & (REAL_PTRS_PER_PMD-1)))
 
 /* Find an entry in the third-level page table.. */
-#define __pte_offset(dir, address)	((pte_t *) __pmd_page(*(dir)) + \
+#define pte_index(dir, address)	((pte_t *) __pmd_page(*(dir)) + \
 					((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
-#define pte_offset_kernel		__pte_offset
-#define pte_offset_map			__pte_offset
-#define pte_offset_map_nested		__pte_offset
+#define pte_offset_kernel		pte_index
+#define pte_offset_map			pte_index
+#define pte_offset_map_nested		pte_index
 #define pte_unmap(pte)			do { } while (0)
 #define pte_unmap_nested(pte)		do { } while (0)
 
diff -Nru a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
--- a/include/asm-sparc64/processor.h	Fri Dec 20 18:49:02 2002
+++ b/include/asm-sparc64/processor.h	Mon Mar 10 10:20:31 2003
@@ -186,6 +186,9 @@
 /* Free all resources held by a thread. */
 #define release_thread(tsk)		do { } while (0)
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 extern unsigned long get_wchan(struct task_struct *task);
diff -Nru a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h
--- a/include/asm-sparc64/termios.h	Mon Feb  4 23:41:04 2002
+++ b/include/asm-sparc64/termios.h	Fri Mar  7 15:36:56 2003
@@ -91,7 +91,7 @@
 	reprint=^R	discard=^U	werase=^W	lnext=^V
 	vmin=\1         vtime=\0
 */
-#define INIT_C_CC "\003\034\177\025\004\000\000\000\021\023\032\031\022\025\027\026\001\000"
+#define INIT_C_CC "\003\034\177\025\004\000\000\000\021\023\032\031\022\025\027\026\001"
 
 /*
  * Translate a "termio" structure into a "termios". Ugh.
diff -Nru a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
--- a/include/asm-um/pgtable.h	Tue Feb 25 01:39:17 2003
+++ b/include/asm-um/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -357,7 +357,6 @@
 
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
-#define __pgd_offset(address) pgd_index(address)
 
 /* to find an entry in a page-table-directory */
 #define pgd_offset(mm, address) \
@@ -366,7 +365,7 @@
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
-#define __pmd_offset(address) \
+#define pmd_index(address) \
 		(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
 
 /* Find an entry in the second-level page table.. */
@@ -376,13 +375,13 @@
 }
 
 /* Find an entry in the third-level page table.. */ 
-#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir, address) \
-	((pte_t *) pmd_page_kernel(*(dir)) +  __pte_offset(address))
+	((pte_t *) pmd_page_kernel(*(dir)) +  pte_index(address))
 #define pte_offset_map(dir, address) \
-        ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + __pte_offset(address))
+        ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
 #define pte_offset_map_nested(dir, address) \
-	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + __pte_offset(address))
+	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + pte_index(address))
 #define pte_unmap(pte) kunmap_atomic((pte), KM_PTE0)
 #define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
 
diff -Nru a/include/asm-v850/processor.h b/include/asm-v850/processor.h
--- a/include/asm-v850/processor.h	Tue Dec 17 00:23:49 2002
+++ b/include/asm-v850/processor.h	Mon Mar 10 10:20:31 2003
@@ -81,6 +81,9 @@
 {
 }
 
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 extern int kernel_thread (int (*fn)(void *), void * arg, unsigned long flags);
 
 /* Free current thread data structures etc.  */
diff -Nru a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h
--- a/include/asm-x86_64/desc.h	Sat Jan 18 05:53:43 2003
+++ b/include/asm-x86_64/desc.h	Sun Mar  9 16:22:43 2003
@@ -138,9 +138,11 @@
 static inline void set_seg_base(unsigned cpu, int entry, void *base)
 { 
 	struct desc_struct *d = &cpu_gdt_table[cpu][entry];
-	d->base0 = PTR_LOW(base);
-	d->base1 = PTR_MIDDLE(base);
-	d->base2 = PTR_HIGH(base);
+	u32 addr = (u32)(u64)base;
+	BUG_ON((u64)base >> 32); 
+	d->base0 = addr & 0xffff;
+	d->base1 = (addr >> 16) & 0xff;
+	d->base2 = (addr >> 24) & 0xff;
 } 
 
 #define LDT_entry_a(info) \
diff -Nru a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h
--- a/include/asm-x86_64/ia32.h	Mon Feb 10 17:21:29 2003
+++ b/include/asm-x86_64/ia32.h	Sun Mar  9 04:31:44 2003
@@ -153,13 +153,15 @@
 	char			f_fpack[6];
 };
 
-struct iovec32 { 
-	unsigned int iov_base; 
-	int iov_len; 
-};
-
 #define IA32_PAGE_OFFSET 0xffffe000
 #define IA32_STACK_TOP IA32_PAGE_OFFSET
+
+#ifdef __KERNEL__
+struct user_desc;
+int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info);
+int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info);
+int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs);
+#endif
 
 #endif /* !CONFIG_IA32_SUPPORT */
  
diff -Nru a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
--- a/include/asm-x86_64/pgtable.h	Sat Feb 15 03:05:09 2003
+++ b/include/asm-x86_64/pgtable.h	Thu Mar  6 08:19:09 2003
@@ -321,9 +321,9 @@
 #define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK))
 #define pmd_page(pmd)		(pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
 
-#define __pmd_offset(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
 #define pmd_offset(dir, address) ((pmd_t *) pgd_page(*(dir)) + \
-			__pmd_offset(address))
+			pmd_index(address))
 #define pmd_none(x)	(!pmd_val(x))
 #define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
 #define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
@@ -353,10 +353,10 @@
        return pte; 
 }
 
-#define __pte_offset(address) \
+#define pte_index(address) \
 		((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_kernel(*(dir)) + \
-			__pte_offset(address))
+			pte_index(address))
 
 /* x86-64 always has all page tables mapped. */
 #define pte_offset_map(dir,address) pte_offset_kernel(dir,address)
diff -Nru a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
--- a/include/asm-x86_64/processor.h	Sat Feb 15 03:56:35 2003
+++ b/include/asm-x86_64/processor.h	Mon Mar 10 10:20:31 2003
@@ -267,6 +267,10 @@
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
 /*
  * create a kernel thread without removing it from tasklists
  */
diff -Nru a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
--- a/include/asm-x86_64/proto.h	Tue Feb 11 06:00:14 2003
+++ b/include/asm-x86_64/proto.h	Sun Mar  9 04:31:52 2003
@@ -57,11 +57,11 @@
 extern unsigned long end_pfn; 
 extern unsigned long table_start, table_end;
 
-struct thread_struct;
-struct user_desc;
+extern void syscall_init(void);
 
-int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info);
-int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info);
+struct pt_regs;
+
+long do_arch_prctl(struct task_struct *task, int code, unsigned long addr);
 
 #define round_up(x,y) (((x) + (y) - 1) & ~((y)-1))
 #define round_down(x,y) ((x) & ~((y)-1))
diff -Nru a/include/asm-x86_64/ptrace.h b/include/asm-x86_64/ptrace.h
--- a/include/asm-x86_64/ptrace.h	Thu Jan 16 06:08:20 2003
+++ b/include/asm-x86_64/ptrace.h	Sat Mar  8 17:17:13 2003
@@ -78,9 +78,11 @@
 #define PTRACE_GETFPXREGS         18
 #define PTRACE_SETFPXREGS         19
 
+/* only useful for access 32bit programs */
 #define PTRACE_GET_THREAD_AREA    25
 #define PTRACE_SET_THREAD_AREA    26
 
+#define PTRACE_ARCH_PRCTL	  30	/* arch_prctl for child */
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__) 
 #define user_mode(regs) (!!((regs)->cs & 3))
diff -Nru a/include/asm-x86_64/segment.h b/include/asm-x86_64/segment.h
--- a/include/asm-x86_64/segment.h	Mon Feb 10 13:23:03 2003
+++ b/include/asm-x86_64/segment.h	Sun Mar  9 07:03:05 2003
@@ -6,8 +6,6 @@
 
 #define __KERNEL32_CS   0x38
 
-#define __USER_LONGBASE	((GDT_ENTRY_LONGBASE * 8)  | 3)
-
 /* 
  * we cannot use the same code segment descriptor for user and kernel
  * -- not even in the long flat mode, because of different DPL /kkeil 
@@ -30,6 +28,13 @@
 #define GDT_ENTRY_KERNELCS16 15
 
 #define GDT_ENTRY_TLS_ENTRIES 3
+
+/* TLS indexes for 64bit - hardcoded in arch_prctl */
+#define FS_TLS 0	
+#define GS_TLS 1	
+
+#define GS_TLS_SEL ((GDT_ENTRY_TLS_MIN+GS_TLS)*8 + 3)
+#define FS_TLS_SEL ((GDT_ENTRY_TLS_MIN+FS_TLS)*8 + 3)
 
 #define IDT_ENTRIES 256
 #define GDT_ENTRIES 16
diff -Nru a/include/asm-x86_64/socket32.h b/include/asm-x86_64/socket32.h
--- a/include/asm-x86_64/socket32.h	Fri Dec 20 15:02:21 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,64 +0,0 @@
-#ifndef SOCKET32_H
-#define SOCKET32_H 1
-
-#include <linux/compat.h>
-
-/* XXX This really belongs in some header file... -DaveM */
-#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
-					   16 for IP, 16 for IPX,
-					   24 for IPv6,
-					   about 80 for AX.25 */
-
-struct msghdr32 {
-        u32               msg_name;
-        int               msg_namelen;
-        u32               msg_iov;
-        compat_size_t msg_iovlen;
-        u32               msg_control;
-        compat_size_t msg_controllen;
-        unsigned          msg_flags;
-};
-
-struct cmsghdr32 {
-        compat_size_t cmsg_len;
-        int               cmsg_level;
-        int               cmsg_type;
-};
-
-/* Bleech... */
-#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
-#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
-
-#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
-
-#define CMSG32_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
-#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
-#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
-
-#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
-				    (struct cmsghdr32 *)(ctl) : \
-				    (struct cmsghdr32 *)NULL)
-#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-
-__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
-					      struct cmsghdr32 *__cmsg, int __cmsg_len)
-{
-	struct cmsghdr32 * __ptr;
-
-	__ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
-				     CMSG32_ALIGN(__cmsg_len));
-	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
-		return NULL;
-
-	return __ptr;
-}
-
-__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
-					    struct cmsghdr32 *__cmsg,
-					    int __cmsg_len)
-{
-	return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
-			       __cmsg, __cmsg_len);
-}
-
-#endif
diff -Nru a/include/asm-x86_64/suspend.h b/include/asm-x86_64/suspend.h
--- a/include/asm-x86_64/suspend.h	Sat Nov 30 06:32:19 2002
+++ b/include/asm-x86_64/suspend.h	Wed Mar  5 01:43:59 2003
@@ -14,7 +14,7 @@
 /* image of the saved processor state */
 struct saved_context {
   	u16 ds, es, fs, gs, ss;
-	unsigned long gs_base, fs_base;
+	unsigned long gs_base, gs_kernel_base, fs_base;
 	unsigned long cr0, cr2, cr3, cr4;
 	u16 gdt_pad;
 	u16 gdt_limit;
diff -Nru a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
--- a/include/asm-x86_64/uaccess.h	Tue Feb 25 10:12:17 2003
+++ b/include/asm-x86_64/uaccess.h	Thu Mar  6 06:51:16 2003
@@ -5,6 +5,7 @@
  * User space memory access functions
  */
 #include <linux/config.h>
+#include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/prefetch.h>
@@ -47,7 +48,7 @@
 
 #define access_ok(type,addr,size) (__range_not_ok(addr,size) == 0)
 
-extern inline int verify_area(int type, const void * addr, unsigned long size)
+extern __force_inline int verify_area(int type, const void * addr, unsigned long size)
 {
 	return access_ok(type,addr,size) ? 0 : -EFAULT;
 }
@@ -237,7 +238,7 @@
 extern unsigned long copy_to_user(void *to, const void *from, unsigned len); 
 extern unsigned long copy_from_user(void *to, const void *from, unsigned len); 
 
-static inline int __copy_from_user(void *dst, const void *src, unsigned size) 
+static __force_inline int __copy_from_user(void *dst, const void *src, unsigned size) 
 { 
 	if (!__builtin_constant_p(size))
 		return copy_user_generic(dst,src,size);
@@ -266,7 +267,7 @@
 	}
 }	
 
-static inline int __copy_to_user(void *dst, const void *src, unsigned size) 
+static __force_inline int __copy_to_user(void *dst, const void *src, unsigned size) 
 { 
 	if (!__builtin_constant_p(size))
 		return copy_user_generic(dst,src,size);
diff -Nru a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
--- a/include/asm-x86_64/unistd.h	Sat Feb 22 02:24:04 2003
+++ b/include/asm-x86_64/unistd.h	Sat Mar  8 15:53:55 2003
@@ -469,7 +469,7 @@
 #define __NR_sched_getaffinity     204
 __SYSCALL(__NR_sched_getaffinity, sys_sched_getaffinity)
 #define __NR_set_thread_area	205
-__SYSCALL(__NR_set_thread_area, sys_set_thread_area)
+__SYSCALL(__NR_set_thread_area, sys_ni_syscall)	/* use arch_prctl */
 #define __NR_io_setup	206
 __SYSCALL(__NR_io_setup, sys_io_setup)
 #define __NR_io_destroy	207
@@ -481,7 +481,7 @@
 #define __NR_io_cancel	210
 __SYSCALL(__NR_io_cancel, sys_io_cancel)
 #define __NR_get_thread_area	211
-__SYSCALL(__NR_get_thread_area, sys_get_thread_area)
+__SYSCALL(__NR_get_thread_area, sys_ni_syscall)	/* use arch_prctl */
 #define __NR_lookup_dcookie	212
 __SYSCALL(__NR_lookup_dcookie, sys_lookup_dcookie)
 #define __NR_epoll_create	213
diff -Nru a/include/linux/atmdev.h b/include/linux/atmdev.h
--- a/include/linux/atmdev.h	Wed Feb 19 23:22:24 2003
+++ b/include/linux/atmdev.h	Sat Mar  8 13:09:15 2003
@@ -277,7 +277,6 @@
 
 struct atm_vcc {
 	unsigned long	flags;		/* VCC flags (ATM_VF_*) */
-	unsigned char	family;		/* address family; 0 if unused */
 	short		vpi;		/* VPI and VCI (types must be equal */
 					/* with sockaddr) */
 	int 		vci;
@@ -286,7 +285,6 @@
 	struct atm_dev	*dev;		/* device back pointer */
 	struct atm_qos	qos;		/* QOS */
 	struct atm_sap	sap;		/* SAP */
-	atomic_t	tx_inuse,rx_inuse; /* buffer space in use */
 	void (*push)(struct atm_vcc *vcc,struct sk_buff *skb);
 	void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */
 	struct sk_buff *(*alloc_tx)(struct atm_vcc *vcc,unsigned int size);
@@ -297,7 +295,6 @@
 	int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);
 	void		*dev_data;	/* per-device data */
 	void		*proto_data;	/* per-protocol data */
-	struct sk_buff_head recvq;	/* receive queue */
 	struct k_atm_aal_stats *stats;	/* pointer to AAL stats group */
 	wait_queue_head_t sleep;	/* if socket is busy */
 	struct sock	*sk;		/* socket backpointer */
@@ -346,7 +343,7 @@
 	struct proc_dir_entry *proc_entry; /* proc entry */
 	char *proc_name;		/* proc entry name */
 #endif
-	struct atm_dev	*prev,*next;	/* linkage */
+	struct list_head dev_list;	/* linkage */
 };
 
 
@@ -425,19 +422,19 @@
 
 static __inline__ void atm_force_charge(struct atm_vcc *vcc,int truesize)
 {
-	atomic_add(truesize+ATM_PDU_OVHD,&vcc->rx_inuse);
+	atomic_add(truesize+ATM_PDU_OVHD,&vcc->sk->rmem_alloc);
 }
 
 
 static __inline__ void atm_return(struct atm_vcc *vcc,int truesize)
 {
-	atomic_sub(truesize+ATM_PDU_OVHD,&vcc->rx_inuse);
+	atomic_sub(truesize+ATM_PDU_OVHD,&vcc->sk->rmem_alloc);
 }
 
 
 static __inline__ int atm_may_send(struct atm_vcc *vcc,unsigned int size)
 {
-	return size+atomic_read(&vcc->tx_inuse)+ATM_PDU_OVHD < vcc->sk->sndbuf;
+	return size+atomic_read(&vcc->sk->wmem_alloc)+ATM_PDU_OVHD < vcc->sk->sndbuf;
 }
 
 
diff -Nru a/include/linux/compat.h b/include/linux/compat.h
--- a/include/linux/compat.h	Tue Jan 14 21:33:09 2003
+++ b/include/linux/compat.h	Thu Mar  6 11:06:44 2003
@@ -45,5 +45,12 @@
 extern int get_compat_timespec(struct timespec *, struct compat_timespec *);
 extern int put_compat_timespec(struct timespec *, struct compat_timespec *);
 
+struct compat_iovec {
+	u32		iov_base;
+	compat_size_t	iov_len;
+};
+#else /* no CONFIG_COMPAT */
+#define compat_size_t	size_t
+
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
diff -Nru a/include/linux/compiler.h b/include/linux/compiler.h
--- a/include/linux/compiler.h	Fri Feb 21 19:50:41 2003
+++ b/include/linux/compiler.h	Mon Mar 10 22:34:24 2003
@@ -1,6 +1,12 @@
 #ifndef __LINUX_COMPILER_H
 #define __LINUX_COMPILER_H
 
+#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+#define inline		__inline__ __attribute__((always_inline))
+#define __inline__	__inline__ __attribute__((always_inline))
+#define __inline	__inline__ __attribute__((always_inline))
+#endif
+
 /* Somewhere in the middle of the GCC 2.96 development cycle, we implemented
    a mechanism by which the user can annotate likely branch directions and
    expect the blocks to be reordered appropriately.  Define __builtin_expect
diff -Nru a/include/linux/cpufreq.h b/include/linux/cpufreq.h
--- a/include/linux/cpufreq.h	Mon Mar  3 14:38:51 2003
+++ b/include/linux/cpufreq.h	Sat Mar  8 01:39:17 2003
@@ -18,7 +18,8 @@
 #include <linux/notifier.h>
 #include <linux/threads.h>
 #include <linux/device.h>
-
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
 
 #define CPUFREQ_NAME_LEN 16
 
@@ -69,6 +70,8 @@
 	struct cpufreq_cpuinfo  cpuinfo;     /* see above */
 	struct device		* dev;
 	struct kobject		kobj;
+ 	struct semaphore	lock;   /* CPU ->setpolicy or ->target may
+					   only be called once a time */
 };
 
 #define CPUFREQ_ADJUST          (0)
@@ -131,18 +134,13 @@
 };
 
 /* pass a target to the cpufreq driver 
- * _l : (cpufreq_driver_sem is not held)
  */
 inline int cpufreq_driver_target(struct cpufreq_policy *policy,
 				 unsigned int target_freq,
 				 unsigned int relation);
 
-inline int cpufreq_driver_target_l(struct cpufreq_policy *policy,
-				   unsigned int target_freq,
-				   unsigned int relation);
-
 /* pass an event to the cpufreq governor */
-int cpufreq_governor_l(unsigned int cpu, unsigned int event);
+int cpufreq_governor(unsigned int cpu, unsigned int event);
 
 int cpufreq_register_governor(struct cpufreq_governor *governor);
 void cpufreq_unregister_governor(struct cpufreq_governor *governor);
@@ -154,6 +152,8 @@
 #define CPUFREQ_RELATION_L 0  /* lowest frequency at or above target */
 #define CPUFREQ_RELATION_H 1  /* highest frequency below or at target */
 
+struct freq_attr;
+
 struct cpufreq_driver {
 	/* needed by all drivers */
 	int	(*verify)	(struct cpufreq_policy *policy);
@@ -164,16 +164,15 @@
 	int	(*target)	(struct cpufreq_policy *policy,
 				 unsigned int target_freq,
 				 unsigned int relation);
+	struct module           *owner;
 	/* optional, for the moment */
 	int	(*init)		(struct cpufreq_policy *policy);
 	int	(*exit)		(struct cpufreq_policy *policy);
+	struct freq_attr	**attr;
 };
 
 int cpufreq_register_driver(struct cpufreq_driver *driver_data);
 int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
-/* deprecated */
-#define cpufreq_register(x)   cpufreq_register_driver(x)
-#define cpufreq_unregister() cpufreq_unregister_driver(NULL)
 
 
 void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state);
@@ -194,6 +193,13 @@
 	return;
 }
 
+struct freq_attr {
+	struct attribute attr;
+	ssize_t (*show)(struct cpufreq_policy *, char *);
+	ssize_t (*store)(struct cpufreq_policy *, const char *, size_t count);
+};
+
+
 /*********************************************************************
  *                        CPUFREQ 2.6. INTERFACE                     *
  *********************************************************************/
@@ -289,15 +295,20 @@
 int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
 				   struct cpufreq_frequency_table *table);
 
-int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy,
-				      struct cpufreq_frequency_table *table,
-				      unsigned int *index);
-
 int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
 				   struct cpufreq_frequency_table *table,
 				   unsigned int target_freq,
 				   unsigned int relation,
 				   unsigned int *index);
+
+/* the following are really really optional */
+extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
+
+void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, 
+				      unsigned int cpu);
+
+void cpufreq_frequency_table_put_attr(unsigned int cpu);
+
 
 #endif /* CONFIG_CPU_FREQ_TABLE */
 
diff -Nru a/include/linux/crypto.h b/include/linux/crypto.h
--- a/include/linux/crypto.h	Sun Feb  2 23:34:59 2003
+++ b/include/linux/crypto.h	Sat Mar  8 11:46:18 2003
@@ -134,10 +134,18 @@
 			   struct scatterlist *dst,
 			   struct scatterlist *src,
 			   unsigned int nbytes);
+	int (*cit_encrypt_iv)(struct crypto_tfm *tfm,
+	                      struct scatterlist *dst,
+	                      struct scatterlist *src,
+	                      unsigned int nbytes, u8 *iv);
 	int (*cit_decrypt)(struct crypto_tfm *tfm,
 			   struct scatterlist *dst,
 			   struct scatterlist *src,
 			   unsigned int nbytes);
+	int (*cit_decrypt_iv)(struct crypto_tfm *tfm,
+			   struct scatterlist *dst,
+			   struct scatterlist *src,
+			   unsigned int nbytes, u8 *iv);
 	void (*cit_xor_block)(u8 *dst, const u8 *src);
 };
 
@@ -164,7 +172,6 @@
 
 struct crypto_tfm {
 
-	void *crt_ctx;
 	u32 crt_flags;
 	
 	union {
@@ -286,6 +293,16 @@
 	return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes);
 }                                        
 
+static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm,
+                                           struct scatterlist *dst,
+                                           struct scatterlist *src,
+                                           unsigned int nbytes, u8 *iv)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
+	return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv);
+}                                        
+
 static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
                                         struct scatterlist *dst,
                                         struct scatterlist *src,
@@ -293,6 +310,16 @@
 {
 	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
 	return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes);
+}
+
+static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm,
+                                           struct scatterlist *dst,
+                                           struct scatterlist *src,
+                                           unsigned int nbytes, u8 *iv)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
+	return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv);
 }
 
 static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm,
diff -Nru a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h
--- a/include/linux/devfs_fs_kernel.h	Wed Jan 15 12:56:40 2003
+++ b/include/linux/devfs_fs_kernel.h	Mon Mar 10 12:22:35 2003
@@ -13,8 +13,6 @@
 
 #define DEVFS_FL_NONE           0x000 /* This helps to make code more readable
 				       */
-#define DEVFS_FL_AUTO_DEVNUM    0x002 /* Automatically generate device number
-				       */
 #define DEVFS_FL_REMOVABLE      0x008 /* This is a removable media device    */
 #define DEVFS_FL_WAIT           0x010 /* Wait for devfsd to finish           */
 #define DEVFS_FL_CURRENT_OWNER  0x020 /* Set initial ownership to current    */
@@ -52,7 +50,6 @@
 				    void *info);
 extern int devfs_generate_path (devfs_handle_t de, char *path, int buflen);
 extern int devfs_set_file_size (devfs_handle_t de, unsigned long size);
-extern int devfs_only (void);
 extern int devfs_register_tape (devfs_handle_t de);
 extern void devfs_unregister_tape(int num);
 extern int devfs_alloc_unique_number (struct unique_numspace *space);
@@ -110,10 +107,6 @@
 static inline int devfs_set_file_size (devfs_handle_t de, unsigned long size)
 {
     return -ENOSYS;
-}
-static inline int devfs_only (void)
-{
-    return 0;
 }
 static inline int devfs_register_tape (devfs_handle_t de)
 {
diff -Nru a/include/linux/efs_fs.h b/include/linux/efs_fs.h
--- a/include/linux/efs_fs.h	Tue Dec 31 17:17:28 2002
+++ b/include/linux/efs_fs.h	Sun Feb 16 16:16:32 2003
@@ -15,14 +15,6 @@
 
 #include <asm/uaccess.h>
 
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
-#if LINUX_VERSION_CODE < 0x20200
-#error This code is only for linux-2.2 and later.
-#endif
-
 /* 1 block is 512 bytes */
 #define	EFS_BLOCKSIZE_BITS	9
 #define	EFS_BLOCKSIZE		(1 << EFS_BLOCKSIZE_BITS)
@@ -31,13 +23,6 @@
 #include <linux/efs_fs_i.h>
 #include <linux/efs_fs_sb.h>
 #include <linux/efs_dir.h>
-
-#ifndef MIN
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#endif
-#ifndef MAX
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-#endif
 
 static inline struct efs_inode_info *INODE_INFO(struct inode *inode)
 {
diff -Nru a/include/linux/elf.h b/include/linux/elf.h
--- a/include/linux/elf.h	Mon Feb 24 10:24:54 2003
+++ b/include/linux/elf.h	Mon Mar  3 13:04:56 2003
@@ -83,6 +83,8 @@
 
 #define EM_V850		87	/* NEC v850 */
 
+#define EM_H8_300H      47      /* Hitachi H8/300H */
+#define EM_H8S          48      /* Hitachi H8S     */
 
 /*
  * This is an interim value that we will use until the committee comes
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	Tue Mar  4 14:30:07 2003
+++ b/include/linux/fs.h	Sat Mar  8 14:50:22 2003
@@ -1033,7 +1033,7 @@
 #define putname(name)	kmem_cache_free(names_cachep, (void *)(name))
 
 enum {BDEV_FILE, BDEV_SWAP, BDEV_FS, BDEV_RAW};
-extern int register_blkdev(unsigned int, const char *, struct block_device_operations *);
+extern int register_blkdev(unsigned int, const char *);
 extern int unregister_blkdev(unsigned int, const char *);
 extern struct block_device *bdget(dev_t);
 extern int bd_acquire(struct inode *inode);
diff -Nru a/include/linux/genhd.h b/include/linux/genhd.h
--- a/include/linux/genhd.h	Thu Feb 13 10:14:34 2003
+++ b/include/linux/genhd.h	Sat Mar  8 14:50:30 2003
@@ -13,6 +13,8 @@
 #include <linux/types.h>
 #include <linux/major.h>
 #include <linux/device.h>
+#include <linux/smp.h>
+#include <linux/string.h>
 
 enum {
 /* These three have identical behaviour; use the second one if DOS FDISK gets
@@ -70,6 +72,16 @@
 #define GENHD_FL_CD	8
 #define GENHD_FL_UP	16
 
+struct disk_stats {
+	unsigned read_sectors, write_sectors;
+	unsigned reads, writes;
+	unsigned read_merges, write_merges;
+	unsigned read_ticks, write_ticks;
+	unsigned io_ticks;
+	int in_flight;
+	unsigned time_in_queue;
+};
+	
 struct gendisk {
 	int major;			/* major number of driver */
 	int first_minor;
@@ -94,15 +106,85 @@
 	int policy;
 
 	unsigned sync_io;		/* RAID */
-	unsigned read_sectors, write_sectors;
-	unsigned reads, writes;
-	unsigned read_merges, write_merges;
-	unsigned read_ticks, write_ticks;
-	unsigned io_ticks;
-	int in_flight;
 	unsigned long stamp, stamp_idle;
-	unsigned time_in_queue;
+#ifdef	CONFIG_SMP
+	struct disk_stats *dkstats;
+#else
+	struct disk_stats dkstats;
+#endif
 };
+
+/* 
+ * Macros to operate on percpu disk statistics:
+ * Since writes to disk_stats are serialised through the queue_lock,
+ * smp_processor_id() should be enough to get to the per_cpu versions
+ * of statistics counters
+ */
+#ifdef	CONFIG_SMP
+#define disk_stat_add(gendiskp, field, addnd) 	\
+	(per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd)
+#define disk_stat_read(gendiskp, field)					\
+({									\
+	typeof(gendiskp->dkstats->field) res = 0;			\
+	int i;								\
+	for (i=0; i < NR_CPUS; i++) {					\
+		if (!cpu_possible(i))					\
+			continue;					\
+		res += per_cpu_ptr(gendiskp->dkstats, i)->field;	\
+	}								\
+	res;								\
+})
+
+static inline void disk_stat_set_all(struct gendisk *gendiskp, int value)	{
+	int i;
+	for (i=0; i < NR_CPUS; i++) {
+		if (cpu_possible(i)) {
+			memset(per_cpu_ptr(gendiskp->dkstats, i), value,	
+					sizeof (struct disk_stats));
+		}
+	}
+}		
+				
+#else
+#define disk_stat_add(gendiskp, field, addnd) (gendiskp->dkstats.field += addnd)
+#define disk_stat_read(gendiskp, field)	(gendiskp->dkstats.field)
+
+static inline void disk_stat_set_all(struct gendisk *gendiskp, int value)	{
+	memset(&gendiskp->dkstats, value, sizeof (struct disk_stats));
+}
+#endif
+
+#define disk_stat_inc(gendiskp, field) disk_stat_add(gendiskp, field, 1)
+#define disk_stat_dec(gendiskp, field) disk_stat_add(gendiskp, field, -1)
+#define disk_stat_sub(gendiskp, field, subnd) \
+		disk_stat_add(gendiskp, field, -subnd)
+
+
+/* Inlines to alloc and free disk stats in struct gendisk */
+#ifdef  CONFIG_SMP
+static inline int init_disk_stats(struct gendisk *disk)
+{
+	disk->dkstats = kmalloc_percpu(sizeof (struct disk_stats), GFP_KERNEL);
+	if (!disk->dkstats)
+		return 0;
+	disk_stat_set_all(disk, 0);
+	return 1;
+}
+
+static inline void free_disk_stats(struct gendisk *disk)
+{
+	kfree_percpu(disk->dkstats);
+}
+#else	/* CONFIG_SMP */
+static inline int init_disk_stats(struct gendisk *disk)
+{
+	return 1;
+}
+
+static inline void free_disk_stats(struct gendisk *disk)
+{
+}
+#endif	/* CONFIG_SMP */
 
 /* drivers/block/ll_rw_blk.c */
 extern void disk_round_stats(struct gendisk *disk);
diff -Nru a/include/linux/hugetlb.h b/include/linux/hugetlb.h
--- a/include/linux/hugetlb.h	Sun Mar  2 18:14:37 2003
+++ b/include/linux/hugetlb.h	Sat Mar  8 14:50:40 2003
@@ -66,6 +66,7 @@
 
 #ifndef HPAGE_MASK
 #define HPAGE_MASK	0		/* Keep the compiler happy */
+#define HPAGE_SIZE	0
 #endif
 
 #endif /* !CONFIG_HUGETLB_PAGE */
diff -Nru a/include/linux/if_shaper.h b/include/linux/if_shaper.h
--- a/include/linux/if_shaper.h	Tue Feb  5 09:39:42 2002
+++ b/include/linux/if_shaper.h	Tue Mar  4 22:44:07 2003
@@ -21,7 +21,7 @@
 	__u32 bitspersec;
 	__u32 shapelatency;
 	__u32 shapeclock;
-	__u32 recovery;		/* Time we can next clock a packet out on
+	unsigned long recovery;	/* Time we can next clock a packet out on
 				   an empty queue */
         unsigned long locked;
         struct net_device_stats stats;
diff -Nru a/include/linux/if_wanpipe.h b/include/linux/if_wanpipe.h
--- a/include/linux/if_wanpipe.h	Sun Mar 17 20:03:30 2002
+++ b/include/linux/if_wanpipe.h	Sun Feb 16 16:22:42 2003
@@ -100,13 +100,9 @@
 #define WAN_PACKET_MR_ALLMULTI	2
 
 #ifdef __KERNEL__
+
 #ifndef netdevice_t
-#include <linux/version.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
- #define netdevice_t struct net_device
-#else
- #define netdevice_t struct device
-#endif
+#define netdevice_t struct net_device
 #endif
 
 /* Private wanpipe socket structures. */
diff -Nru a/include/linux/if_wanpipe_common.h b/include/linux/if_wanpipe_common.h
--- a/include/linux/if_wanpipe_common.h	Sun Dec  8 05:42:07 2002
+++ b/include/linux/if_wanpipe_common.h	Sun Feb 16 16:22:42 2003
@@ -19,11 +19,7 @@
 
 #include <linux/version.h>
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
- #define netdevice_t struct net_device
-#else
- #define netdevice_t struct device
-#endif
+#define netdevice_t struct net_device
 
 
 typedef struct {
diff -Nru a/include/linux/init.h b/include/linux/init.h
--- a/include/linux/init.h	Tue Feb 18 10:25:13 2003
+++ b/include/linux/init.h	Mon Mar  3 13:05:26 2003
@@ -62,8 +62,10 @@
  */
 typedef int (*initcall_t)(void);
 typedef void (*exitcall_t)(void);
-#endif
 
+extern initcall_t __con_initcall_start, __con_initcall_end;
+#endif
+  
 #ifndef MODULE
 
 #ifndef __ASSEMBLY__
@@ -90,6 +92,9 @@
 
 #define __exitcall(fn)							\
 	static exitcall_t __exitcall_##fn __exit_call = fn
+
+#define console_initcall(fn) \
+	static initcall_t __initcall_##fn __attribute__ ((unused,__section__ (".con_initcall.init")))=fn
 
 struct obs_kernel_param {
 	const char *str;
diff -Nru a/include/linux/ipv6.h b/include/linux/ipv6.h
--- a/include/linux/ipv6.h	Thu Oct 24 03:26:49 2002
+++ b/include/linux/ipv6.h	Wed Mar  5 15:45:36 2003
@@ -74,6 +74,21 @@
 #define rt0_type		rt_hdr.type;
 };
 
+struct ipv6_auth_hdr {
+	__u8  nexthdr;
+	__u8  hdrlen;           /* This one is measured in 32 bit units! */
+	__u16 reserved;
+	__u32 spi;
+	__u32 seq_no;           /* Sequence number */
+	__u8  auth_data[4];     /* Length variable but >=4. Mind the 64 bit alignment! */
+};
+
+struct ipv6_esp_hdr {
+	__u32 spi;
+	__u32 seq_no;           /* Sequence number */
+	__u8  enc_data[8];      /* Length variable but >=8. Mind the 64 bit alignment! */
+};
+
 /*
  *	IPv6 fixed header
  *
diff -Nru a/include/linux/jiffies.h b/include/linux/jiffies.h
--- a/include/linux/jiffies.h	Tue Feb 25 02:08:56 2003
+++ b/include/linux/jiffies.h	Wed Mar  5 21:22:52 2003
@@ -1,6 +1,7 @@
 #ifndef _LINUX_JIFFIES_H
 #define _LINUX_JIFFIES_H
 
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/seqlock.h>
@@ -37,10 +38,16 @@
  * good compiler would generate better code (and a really good compiler
  * wouldn't care). Gcc is currently neither.
  */
-#define time_after(a,b)		((long)(b) - (long)(a) < 0)
+#define time_after(a,b)		\
+	(typecheck(unsigned long, a) && \
+	 typecheck(unsigned long, b) && \
+	 ((long)(b) - (long)(a) < 0))
 #define time_before(a,b)	time_after(b,a)
 
-#define time_after_eq(a,b)	((long)(a) - (long)(b) >= 0)
+#define time_after_eq(a,b)	\
+	(typecheck(unsigned long, a) && \
+	 typecheck(unsigned long, b) && \
+	 ((long)(a) - (long)(b) >= 0))
 #define time_before_eq(a,b)	time_after_eq(b,a)
 
 #endif
diff -Nru a/include/linux/kernel.h b/include/linux/kernel.h
--- a/include/linux/kernel.h	Mon Nov 18 02:03:05 2002
+++ b/include/linux/kernel.h	Wed Mar  5 21:21:32 2003
@@ -188,6 +188,17 @@
         const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
         (type *)( (char *)__mptr - offsetof(type,member) );})
 
+/*
+ * Check at compile time that something is of a particular type.
+ * Always evaluates to 1 so you may use it easily in conparisons.
+ */
+#define typecheck(type,x) \
+({	type __dummy; \
+	typeof(x) __dummy2; \
+	(void)(&__dummy == &__dummy2); \
+	1; \
+})
+
 #endif /* __KERNEL__ */
 
 #define SI_LOAD_SHIFT	16
diff -Nru a/include/linux/list.h b/include/linux/list.h
--- a/include/linux/list.h	Tue Mar  4 05:50:39 2003
+++ b/include/linux/list.h	Wed Mar  5 22:31:27 2003
@@ -4,6 +4,7 @@
 #ifdef __KERNEL__
 
 #include <linux/prefetch.h>
+#include <linux/stddef.h>
 #include <asm/system.h>
 
 /*
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	Mon Feb 24 23:13:11 2003
+++ b/include/linux/mm.h	Sat Mar  8 14:50:29 2003
@@ -558,6 +558,7 @@
 /* readahead.c */
 #define VM_MAX_READAHEAD	128	/* kbytes */
 #define VM_MIN_READAHEAD	16	/* kbytes (includes current page) */
+
 int do_page_cache_readahead(struct address_space *mapping, struct file *filp,
 			unsigned long offset, unsigned long nr_to_read);
 void page_cache_readahead(struct address_space *mapping, 
@@ -569,7 +570,7 @@
 			   struct file *filp,
 			   unsigned long offset);
 void handle_ra_miss(struct address_space *mapping, 
-		    struct file_ra_state *ra);
+		    struct file_ra_state *ra, pgoff_t offset);
 unsigned long max_sane_readahead(unsigned long nr);
 
 /* Do stack extension */
diff -Nru a/include/linux/net.h b/include/linux/net.h
--- a/include/linux/net.h	Wed Feb 26 12:14:05 2003
+++ b/include/linux/net.h	Thu Mar  6 11:06:44 2003
@@ -78,7 +78,6 @@
 	unsigned char		passcred;
 };
 
-struct scm_cookie;
 struct vm_area_struct;
 struct page;
 struct kiocb;
@@ -106,11 +105,9 @@
   int	(*getsockopt)	(struct socket *sock, int level, int optname,
 			 char *optval, int *optlen);
   int   (*sendmsg)	(struct kiocb *iocb, struct socket *sock,
-			 struct msghdr *m, int total_len,
-			 struct scm_cookie *scm);
+			 struct msghdr *m, int total_len);
   int   (*recvmsg)	(struct kiocb *iocb, struct socket *sock,
-			 struct msghdr *m, int total_len, int flags,
-			 struct scm_cookie *scm);
+			 struct msghdr *m, int total_len, int flags);
   int	(*mmap)		(struct file *file, struct socket *sock, struct vm_area_struct * vma);
   ssize_t (*sendpage)	(struct socket *sock, struct page *page, int offset, size_t size, int flags);
 };
@@ -202,10 +199,10 @@
 			 char *optval, int optlen), (sock, level, optname, optval, optlen)) \
 SOCKCALL_WRAP(name, getsockopt, (struct socket *sock, int level, int optname, \
 			 char *optval, int *optlen), (sock, level, optname, optval, optlen)) \
-SOCKCALL_WRAP(name, sendmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len, struct scm_cookie *scm), \
-	      (iocb, sock, m, len, scm)) \
-SOCKCALL_WRAP(name, recvmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len, int flags, struct scm_cookie *scm), \
-	      (iocb, sock, m, len, flags, scm)) \
+SOCKCALL_WRAP(name, sendmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len), \
+	      (iocb, sock, m, len)) \
+SOCKCALL_WRAP(name, recvmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len, int flags), \
+	      (iocb, sock, m, len, flags)) \
 SOCKCALL_WRAP(name, mmap, (struct file *file, struct socket *sock, struct vm_area_struct *vma), \
 	      (file, sock, vma)) \
 	      \
diff -Nru a/include/linux/netfilter_bridge/ebt_ip.h b/include/linux/netfilter_bridge/ebt_ip.h
--- a/include/linux/netfilter_bridge/ebt_ip.h	Mon Oct 28 04:58:32 2002
+++ b/include/linux/netfilter_bridge/ebt_ip.h	Mon Mar  3 04:41:09 2003
@@ -25,7 +25,7 @@
  EBT_IP_SPORT | EBT_IP_DPORT )
 #define EBT_IP_MATCH "ip"
 
-// the same values are used for the invflags
+/* the same values are used for the invflags */
 struct ebt_ip_info
 {
 	uint32_t saddr;
diff -Nru a/include/linux/netfilter_bridge/ebt_log.h b/include/linux/netfilter_bridge/ebt_log.h
--- a/include/linux/netfilter_bridge/ebt_log.h	Sun Sep 22 20:14:05 2002
+++ b/include/linux/netfilter_bridge/ebt_log.h	Mon Mar  3 04:41:09 2003
@@ -1,7 +1,7 @@
 #ifndef __LINUX_BRIDGE_EBT_LOG_H
 #define __LINUX_BRIDGE_EBT_LOG_H
 
-#define EBT_LOG_IP 0x01 // if the frame is made by ip, log the ip information
+#define EBT_LOG_IP 0x01 /* if the frame is made by ip, log the ip information */
 #define EBT_LOG_ARP 0x02
 #define EBT_LOG_MASK (EBT_LOG_IP | EBT_LOG_ARP)
 #define EBT_LOG_PREFIX_SIZE 30
diff -Nru a/include/linux/netfilter_bridge/ebt_mark_t.h b/include/linux/netfilter_bridge/ebt_mark_t.h
--- a/include/linux/netfilter_bridge/ebt_mark_t.h	Sun Sep 22 20:14:05 2002
+++ b/include/linux/netfilter_bridge/ebt_mark_t.h	Mon Mar  3 04:41:09 2003
@@ -4,7 +4,7 @@
 struct ebt_mark_t_info
 {
 	unsigned long mark;
-	// EBT_ACCEPT, EBT_DROP or EBT_CONTINUE or EBT_RETURN
+	/* EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN */
 	int target;
 };
 #define EBT_MARK_TARGET "mark"
diff -Nru a/include/linux/netfilter_bridge/ebt_nat.h b/include/linux/netfilter_bridge/ebt_nat.h
--- a/include/linux/netfilter_bridge/ebt_nat.h	Sun Sep 22 20:14:05 2002
+++ b/include/linux/netfilter_bridge/ebt_nat.h	Mon Mar  3 04:41:09 2003
@@ -4,7 +4,7 @@
 struct ebt_nat_info
 {
 	unsigned char mac[ETH_ALEN];
-	// EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN
+	/* EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN */
 	int target;
 };
 #define EBT_SNAT_TARGET "snat"
diff -Nru a/include/linux/netfilter_bridge/ebt_redirect.h b/include/linux/netfilter_bridge/ebt_redirect.h
--- a/include/linux/netfilter_bridge/ebt_redirect.h	Sun Sep 22 20:14:05 2002
+++ b/include/linux/netfilter_bridge/ebt_redirect.h	Mon Mar  3 04:41:09 2003
@@ -3,7 +3,7 @@
 
 struct ebt_redirect_info
 {
-	// EBT_ACCEPT, EBT_DROP or EBT_CONTINUE or EBT_RETURN
+	/* EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN */
 	int target;
 };
 #define EBT_REDIRECT_TARGET "redirect"
diff -Nru a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h
--- a/include/linux/netfilter_bridge/ebtables.h	Mon Oct 28 05:00:13 2002
+++ b/include/linux/netfilter_bridge/ebtables.h	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebtables
  *
  *	Authors:
- *	Bart De Schuymer		<bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer		<bdschuym@pandora.be>
  *
  *  ebtables.c,v 2.0, April, 2002
  *
@@ -20,7 +20,7 @@
 #define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN
 #define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN
 
-// verdicts >0 are "branches"
+/* verdicts >0 are "branches" */
 #define EBT_ACCEPT   -1
 #define EBT_DROP     -2
 #define EBT_CONTINUE -3
@@ -34,33 +34,34 @@
 };
 
 struct ebt_entries {
-	// this field is always set to zero
-	// See EBT_ENTRY_OR_ENTRIES.
-	// Must be same size as ebt_entry.bitmask
+	/* this field is always set to zero
+	 * See EBT_ENTRY_OR_ENTRIES.
+	 * Must be same size as ebt_entry.bitmask */
 	unsigned int distinguisher;
-	// the chain name
+	/* the chain name */
 	char name[EBT_CHAIN_MAXNAMELEN];
-	// counter offset for this chain
+	/* counter offset for this chain */
 	unsigned int counter_offset;
-	// one standard (accept, drop, return) per hook
+	/* one standard (accept, drop, return) per hook */
 	int policy;
-	// nr. of entries
+	/* nr. of entries */
 	unsigned int nentries;
-	// entry list
+	/* entry list */
 	char data[0];
 };
 
-// used for the bitmask of struct ebt_entry
+/* used for the bitmask of struct ebt_entry */
 
-// This is a hack to make a difference between an ebt_entry struct and an
-// ebt_entries struct when traversing the entries from start to end.
-// Using this simplifies the code alot, while still being able to use
-// ebt_entries.
-// Contrary, iptables doesn't use something like ebt_entries and therefore uses
-// different techniques for naming the policy and such. So, iptables doesn't
-// need a hack like this.
+/* This is a hack to make a difference between an ebt_entry struct and an
+ * ebt_entries struct when traversing the entries from start to end.
+ * Using this simplifies the code alot, while still being able to use
+ * ebt_entries.
+ * Contrary, iptables doesn't use something like ebt_entries and therefore uses
+ * different techniques for naming the policy and such. So, iptables doesn't
+ * need a hack like this.
+ */
 #define EBT_ENTRY_OR_ENTRIES 0x01
-// these are the normal masks
+/* these are the normal masks */
 #define EBT_NOPROTO 0x02
 #define EBT_802_3 0x04
 #define EBT_SOURCEMAC 0x08
@@ -84,7 +85,7 @@
 		char name[EBT_FUNCTION_MAXNAMELEN];
 		struct ebt_match *match;
 	} u;
-	// size of data
+	/* size of data */
 	unsigned int match_size;
 	unsigned char data[0];
 };
@@ -95,7 +96,7 @@
 		char name[EBT_FUNCTION_MAXNAMELEN];
 		struct ebt_watcher *watcher;
 	} u;
-	// size of data
+	/* size of data */
 	unsigned int watcher_size;
 	unsigned char data[0];
 };
@@ -106,7 +107,7 @@
 		char name[EBT_FUNCTION_MAXNAMELEN];
 		struct ebt_target *target;
 	} u;
-	// size of data
+	/* size of data */
 	unsigned int target_size;
 	unsigned char data[0];
 };
@@ -118,29 +119,29 @@
 	int verdict;
 };
 
-// one entry
+/* one entry */
 struct ebt_entry {
-	// this needs to be the first field
+	/* this needs to be the first field */
 	unsigned int bitmask;
 	unsigned int invflags;
 	uint16_t ethproto;
-	// the physical in-dev
+	/* the physical in-dev */
 	char in[IFNAMSIZ];
-	// the logical in-dev
+	/* the logical in-dev */
 	char logical_in[IFNAMSIZ];
-	// the physical out-dev
+	/* the physical out-dev */
 	char out[IFNAMSIZ];
-	// the logical out-dev
+	/* the logical out-dev */
 	char logical_out[IFNAMSIZ];
 	unsigned char sourcemac[ETH_ALEN];
 	unsigned char sourcemsk[ETH_ALEN];
 	unsigned char destmac[ETH_ALEN];
 	unsigned char destmsk[ETH_ALEN];
-	// sizeof ebt_entry + matches
+	/* sizeof ebt_entry + matches */
 	unsigned int watchers_offset;
-	// sizeof ebt_entry + matches + watchers
+	/* sizeof ebt_entry + matches + watchers */
 	unsigned int target_offset;
-	// sizeof ebt_entry + matches + watchers + target
+	/* sizeof ebt_entry + matches + watchers + target */
 	unsigned int next_offset;
 	unsigned char elems[0];
 };
@@ -149,20 +150,20 @@
 {
 	char name[EBT_TABLE_MAXNAMELEN];
 	unsigned int valid_hooks;
-	// nr of rules in the table
+	/* nr of rules in the table */
 	unsigned int nentries;
-	// total size of the entries
+	/* total size of the entries */
 	unsigned int entries_size;
-	// start of the chains
+	/* start of the chains */
 	struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
-	// nr of counters userspace expects back
+	/* nr of counters userspace expects back */
 	unsigned int num_counters;
-	// where the kernel will put the old counters
+	/* where the kernel will put the old counters */
 	struct ebt_counter *counters;
 	char *entries;
 };
 
-// [gs]etsockopt numbers
+/* {g,s}etsockopt numbers */
 #define EBT_BASE_CTL            128
 
 #define EBT_SO_SET_ENTRIES      (EBT_BASE_CTL)
@@ -177,7 +178,7 @@
 
 #ifdef __KERNEL__
 
-// return values for match() functions
+/* return values for match() functions */
 #define EBT_MATCH 0
 #define EBT_NOMATCH 1
 
@@ -185,11 +186,11 @@
 {
 	struct list_head list;
 	const char name[EBT_FUNCTION_MAXNAMELEN];
-	// 0 == it matches
+	/* 0 == it matches */
 	int (*match)(const struct sk_buff *skb, const struct net_device *in,
 	   const struct net_device *out, const void *matchdata,
 	   unsigned int datalen);
-	// 0 == let it in
+	/* 0 == let it in */
 	int (*check)(const char *tablename, unsigned int hookmask,
 	   const struct ebt_entry *e, void *matchdata, unsigned int datalen);
 	void (*destroy)(void *matchdata, unsigned int datalen);
@@ -203,7 +204,7 @@
 	void (*watcher)(const struct sk_buff *skb, const struct net_device *in,
 	   const struct net_device *out, const void *watcherdata,
 	   unsigned int datalen);
-	// 0 == let it in
+	/* 0 == let it in */
 	int (*check)(const char *tablename, unsigned int hookmask,
 	   const struct ebt_entry *e, void *watcherdata, unsigned int datalen);
 	void (*destroy)(void *watcherdata, unsigned int datalen);
@@ -214,33 +215,33 @@
 {
 	struct list_head list;
 	const char name[EBT_FUNCTION_MAXNAMELEN];
-	// returns one of the standard verdicts
+	/* returns one of the standard verdicts */
 	int (*target)(struct sk_buff **pskb, unsigned int hooknr,
 	   const struct net_device *in, const struct net_device *out,
 	   const void *targetdata, unsigned int datalen);
-	// 0 == let it in
+	/* 0 == let it in */
 	int (*check)(const char *tablename, unsigned int hookmask,
 	   const struct ebt_entry *e, void *targetdata, unsigned int datalen);
 	void (*destroy)(void *targetdata, unsigned int datalen);
 	struct module *me;
 };
 
-// used for jumping from and into user defined chains (udc)
+/* used for jumping from and into user defined chains (udc) */
 struct ebt_chainstack
 {
-	struct ebt_entries *chaininfo; // pointer to chain data
-	struct ebt_entry *e; // pointer to entry data
-	unsigned int n; // n'th entry
+	struct ebt_entries *chaininfo; /* pointer to chain data */
+	struct ebt_entry *e; /* pointer to entry data */
+	unsigned int n; /* n'th entry */
 };
 
 struct ebt_table_info
 {
-	// total size of the entries
+	/* total size of the entries */
 	unsigned int entries_size;
 	unsigned int nentries;
-	// pointers to the start of the chains
+	/* pointers to the start of the chains */
 	struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
-	// room to maintain the stack used for jumping from and into udc
+	/* room to maintain the stack used for jumping from and into udc */
 	struct ebt_chainstack **chainstack;
 	char *entries;
 	struct ebt_counter counters[0] ____cacheline_aligned;
@@ -253,11 +254,11 @@
 	struct ebt_replace *table;
 	unsigned int valid_hooks;
 	rwlock_t lock;
-	// e.g. could be the table explicitly only allows certain
-	// matches, targets, ... 0 == let it in
+	/* e.g. could be the table explicitly only allows certain
+	 * matches, targets, ... 0 == let it in */
 	int (*check)(const struct ebt_table_info *info,
 	   unsigned int valid_hooks);
-	// the data used by the kernel
+	/* the data used by the kernel */
 	struct ebt_table_info *private;
 };
 
@@ -273,20 +274,20 @@
    const struct net_device *in, const struct net_device *out,
    struct ebt_table *table);
 
-   // Used in the kernel match() functions
+/* Used in the kernel match() functions */
 #define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg))
-// True if the hook mask denotes that the rule is in a base chain,
-// used in the check() functions
+/* True if the hook mask denotes that the rule is in a base chain,
+ * used in the check() functions */
 #define BASE_CHAIN (hookmask & (1 << NF_BR_NUMHOOKS))
-// Clear the bit in the hook mask that tells if the rule is on a base chain
+/* Clear the bit in the hook mask that tells if the rule is on a base chain */
 #define CLEAR_BASE_CHAIN_BIT (hookmask &= ~(1 << NF_BR_NUMHOOKS))
-// True if the target is not a standard target
+/* True if the target is not a standard target */
 #define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0)
 
 #endif /* __KERNEL__ */
 
-// blatently stolen from ip_tables.h
-// fn returns 0 to continue iteration
+/* blatently stolen from ip_tables.h
+ * fn returns 0 to continue iteration */
 #define EBT_MATCH_ITERATE(e, fn, args...)                   \
 ({                                                          \
 	unsigned int __i;                                   \
diff -Nru a/include/linux/netfilter_ipv4/ipchains_core.h b/include/linux/netfilter_ipv4/ipchains_core.h
--- a/include/linux/netfilter_ipv4/ipchains_core.h	Tue Feb  5 09:39:43 2002
+++ b/include/linux/netfilter_ipv4/ipchains_core.h	Sat Mar  8 11:30:11 2003
@@ -178,12 +178,8 @@
 
 #include <linux/config.h>
 #include <linux/version.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
 #include <linux/init.h>
 extern void ip_fw_init(void) __init;
-#else /* 2.0.x */
-extern void ip_fw_init(void);
-#endif /* 2.1.x */
 extern int ip_fw_ctl(int, void *, int);
 #ifdef CONFIG_IP_MASQUERADE
 extern int ip_masq_uctl(int, char *, int);
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h	Mon Feb 24 08:17:50 2003
+++ b/include/linux/pci.h	Tue Feb 25 15:37:27 2003
@@ -413,6 +413,7 @@
 
 	/* These fields are used by common fixups */
 	unsigned int	transparent:1;	/* Transparent PCI bridge */
+	unsigned int	multifunction:1;/* Part of multi-function device */
 };
 
 #define pci_dev_g(n) list_entry(n, struct pci_dev, global_list)
@@ -548,7 +549,8 @@
 {
 	return pci_alloc_primary_bus_parented(NULL, bus);
 }
-struct pci_dev *pci_scan_slot(struct pci_dev *temp);
+int pci_scan_slot(struct pci_bus *bus, int devfn);
+void pci_bus_add_devices(struct pci_bus *bus);
 int pci_proc_attach_device(struct pci_dev *dev);
 int pci_proc_detach_device(struct pci_dev *dev);
 int pci_proc_attach_bus(struct pci_bus *bus);
@@ -641,6 +643,16 @@
 int pci_request_region(struct pci_dev *, int, char *);
 void pci_release_region(struct pci_dev *, int);
 
+/* drivers/pci/bus.c */
+
+int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
+			   unsigned long size, unsigned long align,
+			   unsigned long min, unsigned int type_mask,
+			   void (*alignf)(void *, struct resource *,
+					  unsigned long, unsigned long),
+			   void *alignf_data);
+void pci_enable_bridges(struct pci_bus *bus);
+
 /* New-style probing supporting hot-pluggable devices */
 int pci_register_driver(struct pci_driver *);
 void pci_unregister_driver(struct pci_driver *);
@@ -844,7 +856,7 @@
 #define PCIPCI_NATOMA		4
 #define PCIPCI_VIAETBF		8
 #define PCIPCI_VSFX		16
-
+#define PCIPCI_ALIMAGIK		32
 
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	Thu Feb 27 13:23:56 2003
+++ b/include/linux/pci_ids.h	Sat Mar  8 01:46:02 2003
@@ -1854,6 +1854,7 @@
 #define PCI_DEVICE_ID_INTEL_82801DB_7	0x24c7
 #define PCI_DEVICE_ID_INTEL_82801DB_9	0x24cb
 #define PCI_DEVICE_ID_INTEL_82801DB_11	PCI_DEVICE_ID_INTEL_82801DB_9
+#define PCI_DEVICE_ID_INTEL_82801DB_12  0x24cc
 #define PCI_DEVICE_ID_INTEL_82801DB_13	0x24cd
 #define PCI_DEVICE_ID_INTEL_82820_HB	0x2500
 #define PCI_DEVICE_ID_INTEL_82820_UP_HB	0x2501
diff -Nru a/include/linux/pnp.h b/include/linux/pnp.h
--- a/include/linux/pnp.h	Fri Feb 21 15:46:20 2003
+++ b/include/linux/pnp.h	Mon Mar 10 22:34:19 2003
@@ -138,11 +138,8 @@
 	struct list_head global_list;	/* node in global list of cards */
 	struct list_head protocol_list;	/* node in protocol's list of cards */
 	struct list_head devices;	/* devices attached to the card */
-	struct list_head rdevs;		/* a list of devices requested by the card driver */
-	int status;
 
 	struct pnp_protocol * protocol;
-	struct pnpc_driver * driver;
 	struct pnp_id * id;		/* contains supported EISA IDs*/
 
 	void	      * protocol_data;	/* Used to store protocol specific data */
@@ -161,24 +158,30 @@
 	(card) != global_to_pnp_card(&pnp_cards); \
 	(card) = global_to_pnp_card((card)->global_list.next))
 
-static inline void *pnpc_get_drvdata (struct pnp_card *pcard)
+static inline void *pnp_get_card_protodata (struct pnp_card *pcard)
 {
-	return dev_get_drvdata(&pcard->dev);
+	return pcard->protocol_data;
 }
 
-static inline void pnpc_set_drvdata (struct pnp_card *pcard, void *data)
+static inline void pnp_set_card_protodata (struct pnp_card *pcard, void *data)
 {
-	dev_set_drvdata(&pcard->dev, data);
+	pcard->protocol_data = data;
 }
 
-static inline void *pnpc_get_protodata (struct pnp_card *pcard)
+struct pnp_card_link {
+	struct pnp_card * card;
+	struct pnp_card_driver * driver;
+	void * driver_data;
+};
+
+static inline void *pnp_get_card_drvdata (struct pnp_card_link *pcard)
 {
-	return pcard->protocol_data;
+	return pcard->driver_data;
 }
 
-static inline void pnpc_set_protodata (struct pnp_card *pcard, void *data)
+static inline void pnp_set_card_drvdata (struct pnp_card_link *pcard, void *data)
 {
-	pcard->protocol_data = data;
+	pcard->driver_data = data;
 }
 
 struct pnp_dev {
@@ -196,6 +199,7 @@
 	struct pnp_protocol * protocol;
 	struct pnp_card * card;		/* card the device is attached to, none if NULL */
 	struct pnp_driver * driver;
+	struct pnp_card_link * card_link;
 
 	struct pnp_id		      * id;		/* supported EISA IDs*/
 	struct pnp_resource_table	res;		/* contains the currently chosen resources */
@@ -299,11 +303,8 @@
 	} devs[PNP_MAX_DEVICES];	/* logical devices */
 };
 
-#define PNP_DRIVER_DO_NOT_ACTIVATE	(1<<0)
-
 struct pnp_driver {
-	struct list_head node;
-	char *name;
+	char * name;
 	const struct pnp_device_id *id_table;
 	unsigned int flags;
 	int  (*probe)  (struct pnp_dev *dev, const struct pnp_device_id *dev_id);
@@ -311,21 +312,22 @@
 	struct device_driver driver;
 };
 
-#define	to_pnp_driver(drv) container_of(drv,struct pnp_driver, driver)
-
-#define PNPC_DRIVER_DO_NOT_ACTIVATE	(1<<0)
+#define	to_pnp_driver(drv) container_of(drv, struct pnp_driver, driver)
 
-struct pnpc_driver {
-	struct list_head node;
-	char *name;
+struct pnp_card_driver {
+	char * name;
 	const struct pnp_card_id *id_table;
 	unsigned int flags;
-	int  (*probe)  (struct pnp_card *card, const struct pnp_card_id *card_id);
-	void (*remove) (struct pnp_card *card);
-	struct device_driver driver;
+	int  (*probe)  (struct pnp_card_link *card, const struct pnp_card_id *card_id);
+	void (*remove) (struct pnp_card_link *card);
+	struct pnp_driver link;
 };
 
-#define	to_pnpc_driver(drv) container_of(drv,struct pnpc_driver, driver)
+#define	to_pnp_card_driver(drv) container_of(drv, struct pnp_card_driver, link)
+
+/* pnp driver flags */
+#define PNP_DRIVER_RES_DO_NOT_CHANGE	0x0001	/* do not change the state of the device */
+#define PNP_DRIVER_RES_DISABLE		0x0003	/* ensure the device is disabled */
 
 
 /*
@@ -366,9 +368,21 @@
 void pnp_unregister_protocol(struct pnp_protocol *protocol);
 int pnp_add_device(struct pnp_dev *dev);
 void pnp_remove_device(struct pnp_dev *dev);
-extern struct list_head pnp_global;
 int pnp_device_attach(struct pnp_dev *pnp_dev);
 void pnp_device_detach(struct pnp_dev *pnp_dev);
+extern struct list_head pnp_global;
+
+/* card */
+int pnp_add_card(struct pnp_card *card);
+void pnp_remove_card(struct pnp_card *card);
+int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev);
+void pnp_remove_card_device(struct pnp_dev *dev);
+int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card);
+struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char * id, struct pnp_dev * from);
+void pnp_release_card_device(struct pnp_dev * dev);
+int pnp_register_card_driver(struct pnp_card_driver * drv);
+void pnp_unregister_card_driver(struct pnp_card_driver * drv);
+extern struct list_head pnp_cards;
 
 /* resource */
 struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent);
@@ -413,6 +427,17 @@
 static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; }
 static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; }
 
+/* card */
+static inline int pnp_add_card(struct pnp_card *card) { return -ENODEV; }
+static inline void pnp_remove_card(struct pnp_card *card) { ; }
+static inline int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev) { return -ENODEV; }
+static inline void pnp_remove_card_device(struct pnp_dev *dev) { ; }
+static inline int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card) { return -ENODEV; }
+static inline struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char * id, struct pnp_dev * from) { return NULL; }
+static inline void pnp_release_card_device(struct pnp_dev * dev) { ; }
+static inline int pnp_register_card_driver(struct pnp_card_driver * drv) { return -ENODEV; }
+static inline void pnp_unregister_card_driver(struct pnp_card_driver * drv) { ; }
+
 /* resource */
 static inline struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent) { return NULL; }
 static inline struct pnp_resources * pnp_find_resources(struct pnp_dev *dev, int depnum) { return NULL; }
@@ -445,37 +470,6 @@
 
 #endif /* CONFIG_PNP */
 
-
-#if defined(CONFIG_PNP_CARD)
-
-/* card */
-int pnpc_add_card(struct pnp_card *card);
-void pnpc_remove_card(struct pnp_card *card);
-int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev);
-void pnpc_remove_device(struct pnp_dev *dev);
-struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, struct pnp_dev *from);
-void pnp_release_card_device(struct pnp_dev *dev);
-int pnpc_register_driver(struct pnpc_driver * drv);
-void pnpc_unregister_driver(struct pnpc_driver *drv);
-int pnpc_add_id(struct pnp_id *id, struct pnp_card *card);
-extern struct list_head pnp_cards;
-int pnpc_attach(struct pnp_card *card);
-void pnpc_detach(struct pnp_card *card);
-
-#else
-
-/* card */
-static inline int pnpc_add_card(struct pnp_card *card) { return -ENODEV; }
-static inline void pnpc_remove_card(struct pnp_card *card) { ; }
-static inline int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev) { return -ENODEV; }
-static inline void pnpc_remove_device(struct pnp_dev *dev) { ; }
-static inline struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, struct pnp_dev *from) { return NULL; }
-static inline void pnp_release_card_device(struct pnp_dev *dev) { ; }
-static inline int pnpc_register_driver(struct pnpc_driver *drv) { return -ENODEV; }
-static inline void pnpc_unregister_driver(struct pnpc_driver *drv) { ; }
-static inline int pnpc_add_id(struct pnp_id *id, struct pnp_card *card) { return -ENODEV; }
-
-#endif /* CONFIG_PNP_CARD */
 
 #define pnp_err(format, arg...) printk(KERN_ERR "pnp: " format "\n" , ## arg)
 #define pnp_info(format, arg...) printk(KERN_INFO "pnp: " format "\n" , ## arg)
diff -Nru a/include/linux/profile.h b/include/linux/profile.h
--- a/include/linux/profile.h	Tue Feb 18 18:59:01 2003
+++ b/include/linux/profile.h	Wed Feb 26 18:41:10 2003
@@ -2,15 +2,15 @@
 #define _LINUX_PROFILE_H
 
 #ifdef __KERNEL__
- 
+
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/init.h>
 #include <asm/errno.h>
- 
+
 /* parse command line */
 int __init profile_setup(char * str);
- 
+
 /* init basic kernel profiler */
 void __init profile_init(void);
 
@@ -27,14 +27,14 @@
 };
 
 #ifdef CONFIG_PROFILING
- 
+
 struct notifier_block;
 struct task_struct;
 struct mm_struct;
- 
+
 /* task is in do_exit() */
 void profile_exit_task(struct task_struct * task);
- 
+
 /* change of vma mappings */
 void profile_exec_unmap(struct mm_struct * mm);
 
@@ -44,10 +44,10 @@
 int profile_event_register(enum profile_type, struct notifier_block * n);
 
 int profile_event_unregister(enum profile_type, struct notifier_block * n);
- 
+
 int register_profile_notifier(struct notifier_block * nb);
 int unregister_profile_notifier(struct notifier_block * nb);
- 
+
 /* profiling hook activated on each timer interrupt */
 void profile_hook(struct pt_regs * regs);
 
@@ -57,12 +57,12 @@
 {
 	return -ENOSYS;
 }
- 
+
 static inline int profile_event_unregister(enum profile_type t, struct notifier_block * n)
 {
 	return -ENOSYS;
 }
- 
+
 #define profile_exit_task(a) do { } while (0)
 #define profile_exec_unmap(a) do { } while (0)
 #define profile_exit_mmap(a) do { } while (0)
@@ -80,7 +80,7 @@
 #define profile_hook(regs) do { } while (0)
 
 #endif /* CONFIG_PROFILING */
- 
+
 #endif /* __KERNEL__ */
- 
+
 #endif /* _LINUX_PROFILE_H */
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Mon Feb 24 09:40:34 2003
+++ b/include/linux/sched.h	Wed Mar  5 16:00:00 2003
@@ -328,7 +328,7 @@
 	prio_array_t *array;
 
 	unsigned long sleep_avg;
-	unsigned long sleep_timestamp;
+	unsigned long last_run;
 
 	unsigned long policy;
 	unsigned long cpus_allowed;
diff -Nru a/include/linux/sdladrv.h b/include/linux/sdladrv.h
--- a/include/linux/sdladrv.h	Mon Feb  4 23:39:17 2002
+++ b/include/linux/sdladrv.h	Sun Feb 16 16:22:42 2003
@@ -19,19 +19,6 @@
 #ifndef	_SDLADRV_H
 #define	_SDLADRV_H
 
-#include <linux/version.h>
-
-#ifndef KERNEL_VERSION
-  #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-#define LINUX_2_4	
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
-#define LINUX_2_1
-#else
-#define LINUX_2_0
-#endif
 
 #define	SDLA_MAXIORANGE	4	/* maximum I/O port range */
 #define	SDLA_WINDOWSIZE	0x2000	/* default dual-port memory window size */
@@ -50,12 +37,7 @@
 	char S514_cpu_no[1];		/* PCI CPU Number */
 	unsigned char S514_slot_no;	/* PCI Slot Number */
 	char auto_pci_cfg;		/* Autodetect PCI Slot */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct pci_dev *pci_dev;	/* PCI device */
-#else
-	unsigned char pci_bus;		/* PCI bus number */
-	unsigned char pci_dev_func;	/* PCI device/function number */
-#endif
 	void * dpmbase;			/* dual-port memory base */
 	unsigned dpmsize;		/* dual-port memory size */
 	unsigned pclk;			/* CPU clock rate, kHz */
diff -Nru a/include/linux/slab.h b/include/linux/slab.h
--- a/include/linux/slab.h	Fri Feb  7 12:25:20 2003
+++ b/include/linux/slab.h	Sat Mar  8 14:50:35 2003
@@ -37,6 +37,7 @@
 #define	SLAB_HWCACHE_ALIGN	0x00002000UL	/* align objs on a h/w cache lines */
 #define SLAB_CACHE_DMA		0x00004000UL	/* use GFP_DMA memory */
 #define SLAB_MUST_HWCACHE_ALIGN	0x00008000UL	/* force alignment */
+#define SLAB_STORE_USER		0x00010000UL	/* store the last owner for bug hunting */
 
 /* flags passed to a constructor func */
 #define	SLAB_CTOR_CONSTRUCTOR	0x001UL		/* if not set, then deconstructor */
diff -Nru a/include/linux/socket.h b/include/linux/socket.h
--- a/include/linux/socket.h	Fri Feb 21 23:42:02 2003
+++ b/include/linux/socket.h	Thu Mar  6 11:06:44 2003
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
 
+#include <linux/linkage.h>
 #include <asm/socket.h>			/* arch-dependent defines	*/
 #include <linux/sockios.h>		/* the SIOCxxx I/O controls	*/
 #include <linux/uio.h>			/* iovec support		*/
@@ -234,6 +235,24 @@
 
 #define MSG_EOF         MSG_FIN
 
+#if defined(CONFIG_COMPAT)
+#define MSG_CMSG_COMPAT	0x80000000	/* This message needs 32 bit fixups */
+#else
+#define MSG_CMSG_COMPAT	0		/* We never have 32 bit fixups */
+#define compat_msghdr	msghdr		/* Needed to avoid compiler hoops */
+#endif
+
+struct compat_msghdr;
+extern int msghdr_from_user_compat_to_kern(struct msghdr *, struct compat_msghdr *);
+extern int verify_compat_iovec(struct msghdr *, struct iovec *, char *, int);
+extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr *,unsigned);
+extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr *,unsigned);
+extern asmlinkage long sys_sendmsg(int fd, struct msghdr *msg, unsigned flags);
+extern asmlinkage long sys_recvmsg(int fd, struct msghdr *msg, unsigned flags);
+extern asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
+				char *optval, int *optlen);
+
+
 
 /* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */
 #define SOL_IP		0
@@ -276,6 +295,11 @@
 extern int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen);
 extern int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr);
 extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
+extern int put_cmsg_compat(struct msghdr*, int level, int type, int len, void *data);
+extern void cmsg_compat_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr);
+extern int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg,
+			       unsigned char *stackbuf, int stackbuf_size);
+
 #endif
 #endif /* not kernel and not glibc */
 #endif /* _LINUX_SOCKET_H */
diff -Nru a/include/linux/tty.h b/include/linux/tty.h
--- a/include/linux/tty.h	Sun Dec 29 23:18:11 2002
+++ b/include/linux/tty.h	Thu Mar  6 21:27:16 2003
@@ -294,7 +294,7 @@
 	unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
 	unsigned char closing:1;
 	unsigned short minimum_to_wake;
-	unsigned overrun_time;
+	unsigned long overrun_time;
 	int num_overrun;
 	unsigned long process_char_map[256/(8*sizeof(unsigned long))];
 	char *read_buf;
@@ -348,7 +348,6 @@
 
 extern int kmsg_redirect;
 
-extern void con_init(void);
 extern void console_init(void);
 
 extern int lp_init(void);
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	Wed Feb 26 08:29:24 2003
+++ b/include/linux/usb.h	Wed Mar  5 07:24:34 2003
@@ -213,7 +213,7 @@
 struct usb_device {
 	int		devnum;		/* Address on USB bus */
 	char		devpath [16];	/* Use in messages: /port/port/... */
-
+	enum usb_device_state	state;	/* configured, not attached, etc */
 	enum usb_device_speed	speed;	/* high/full/low (or error) */
 
 	struct usb_tt	*tt; 		/* low/full speed dev, highspeed hub */
@@ -240,7 +240,6 @@
 
 	int have_langid;		/* whether string_langid is valid yet */
 	int string_langid;		/* language ID for strings */
-	int present;			/* if device is present or not */
 
 	void *hcpriv;			/* Host Controller private data */
 	
diff -Nru a/include/linux/usb_ch9.h b/include/linux/usb_ch9.h
--- a/include/linux/usb_ch9.h	Tue Oct 29 15:14:57 2002
+++ b/include/linux/usb_ch9.h	Wed Mar  5 07:28:25 2003
@@ -291,4 +291,25 @@
 	USB_SPEED_HIGH				/* usb 2.0 */
 };
 
+enum usb_device_state {
+	/* NOTATTACHED isn't in the USB spec, and this state acts
+	 * the same as ATTACHED ... but it's clearer this way.
+	 */
+	USB_STATE_NOTATTACHED = 0,
+
+	/* the chapter 9 device states */
+	USB_STATE_ATTACHED,
+	USB_STATE_POWERED,
+	USB_STATE_DEFAULT,			/* limited function */
+	USB_STATE_ADDRESS,
+	USB_STATE_CONFIGURED,			/* most functions */
+
+	USB_STATE_SUSPENDED
+
+	/* NOTE:  there are actually four different SUSPENDED
+	 * states, returning to POWERED, DEFAULT, ADDRESS, or
+	 * CONFIGURED respectively when SOF tokens flow again.
+	 */
+};
+
 #endif	/* __LINUX_USB_CH9_H */
diff -Nru a/include/linux/wanpipe.h b/include/linux/wanpipe.h
--- a/include/linux/wanpipe.h	Sun Dec  8 05:52:12 2002
+++ b/include/linux/wanpipe.h	Sun Feb 16 16:22:42 2003
@@ -39,59 +39,7 @@
 #ifndef	_WANPIPE_H
 #define	_WANPIPE_H
 
-#include <linux/version.h>
-
-#ifndef KERNEL_VERSION
-  #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
- 
- #define LINUX_2_4
- #define netdevice_t struct net_device
-
- #define FREE_READ 1
- #define FREE_WRITE 0
-
- #define stop_net_queue(a) 	netif_stop_queue(a) 
- #define start_net_queue(a) 	netif_start_queue(a)
- #define is_queue_stopped(a)	netif_queue_stopped(a)
- #define wake_net_dev(a)	netif_wake_queue(a)
- #define is_dev_running(a)	netif_running(a)
- #define wan_dev_kfree_skb(a,b)	dev_kfree_skb_any(a)
-
-
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
-
- #define LINUX_2_1
- #define netdevice_t struct device
- #define FREE_READ 1
- #define FREE_WRITE 0
-
- #define stop_net_queue(a) 	(set_bit(0, &##a->tbusy)) 
- #define start_net_queue(a) 	(clear_bit(0,&##a->tbusy))
- #define is_queue_stopped(a)	(##a->tbusy)
- #define wake_net_dev(a)	{clear_bit(0,&##a->tbusy);mark_bh(NET_BH);}
- #define is_dev_running(a)	(test_bit(0,&##a->start))
- #define wan_dev_kfree_skb(a,b)	dev_kfree_skb(a)
-
-#else
- #define LINUX_2_0
- #define netdevice_t struct device
-
- #define test_and_set_bit set_bit
- #define net_ratelimit() 1 
-
- #define stop_net_queue(a) 	(set_bit(0, &##a->tbusy)) 
- #define start_net_queue(a) 	(clear_bit(0,&##a->tbusy))
- #define is_queue_stopped(a)	(##a->tbusy)
- #define wake_net_dev(a)	{clear_bit(0,&##a->tbusy);mark_bh(NET_BH);}
- #define is_dev_running(a)	(test_bit(0,(void*)&##a->start))
- #define wan_dev_kfree_skb(a,b) dev_kfree_skb(a,b)  		 
- #define spin_lock_init(a)
- #define spin_lock(a)
- #define spin_unlock(a)
-#endif
+#define netdevice_t struct net_device
 
 #include <linux/wanrouter.h>
 
@@ -121,21 +69,11 @@
 #define MAX_LCN_NUM	4095	/* Maximum lcn number */
 #define MAX_FT1_RETRY 	100
 
-#ifdef LINUX_2_4
-  #ifndef AF_WANPIPE
+#ifndef AF_WANPIPE
 	#define AF_WANPIPE 25
 	#ifndef PF_WANPIPE
 		#define PF_WANPIPE AF_WANPIPE
 	#endif
-  #endif
-
-#else
-  #ifndef AF_WANPIPE
-	#define AF_WANPIPE 24
-	#ifndef PF_WANPIPE
-		#define PF_WANPIPE AF_WANPIPE
-	#endif
-  #endif
 #endif
 
 
@@ -321,12 +259,10 @@
 #include <linux/sdladrv.h>	/* SDLA support module API definitions */
 #include <linux/sdlasfm.h>	/* SDLA firmware module definitions */
 #include <linux/workqueue.h>
-#ifdef LINUX_2_4
-  #include <linux/serial.h>
-  #include <linux/serialP.h>
-  #include <linux/serial_reg.h>
-  #include <asm/serial.h>
-#endif
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+#include <asm/serial.h>
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
diff -Nru a/include/linux/wanrouter.h b/include/linux/wanrouter.h
--- a/include/linux/wanrouter.h	Wed Apr 24 10:11:41 2002
+++ b/include/linux/wanrouter.h	Sun Feb 16 16:22:42 2003
@@ -43,27 +43,10 @@
 * Jan 16, 1997	Gene Kozin	router_devlist made public
 * Jan 02, 1997	Gene Kozin	Initial version (based on wanpipe.h).
 *****************************************************************************/
-#include <linux/version.h>
 
-#ifndef KERNEL_VERSION
-  #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
- #define LINUX_2_4
- #define netdevice_t struct net_device
- #include <linux/spinlock.h>       /* Support for SMP Locking */
-
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
- #define LINUX_2_1
- #define netdevice_t struct device
- #include <asm/spinlock.h>       /* Support for SMP Locking */
-
-#else
- #define LINUX_2_0
- #define netdevice_t struct device
- #define spinlock_t int
-#endif
+#define netdevice_t struct net_device
+
+#include <linux/spinlock.h>       /* Support for SMP Locking */
 
 #ifndef	_ROUTER_H
 #define	_ROUTER_H
@@ -512,11 +495,7 @@
 					/****** status and statistics *******/
 	char state;			/* device state */
 	char api_status;		/* device api status */
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct net_device_stats stats; 	/* interface statistics */
-#else
-	struct enet_statistics stats;	/* interface statistics */
-#endif
 	unsigned reserved[16];		/* reserved for future use */
 	unsigned long critical;		/* critical section flag */
 	spinlock_t lock;                /* Support for SMP Locking */
@@ -534,11 +513,7 @@
 	struct wan_device* next;	/* -> next device */
 	netdevice_t* dev;		/* list of network interfaces */
 	unsigned ndev;			/* number of interfaces */
-#ifdef LINUX_2_4
 	struct proc_dir_entry *dent;	/* proc filesystem entry */
-#else
-	struct proc_dir_entry dent;	/* proc filesystem entry */
-#endif
 } wan_device_t;
 
 /* Public functions available for device drivers */
diff -Nru a/include/net/ah.h b/include/net/ah.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/net/ah.h	Thu Mar  6 16:15:33 2003
@@ -0,0 +1,35 @@
+#ifndef _NET_AH_H
+#define _NET_AH_H
+
+#include <net/xfrm.h>
+
+struct ah_data
+{
+	u8			*key;
+	int			key_len;
+	u8			*work_icv;
+	int			icv_full_len;
+	int			icv_trunc_len;
+
+	void			(*icv)(struct ah_data*,
+	                               struct sk_buff *skb, u8 *icv);
+
+	struct crypto_tfm	*tfm;
+};
+
+extern void skb_ah_walk(const struct sk_buff *skb,
+                        struct crypto_tfm *tfm, icv_update_fn_t icv_update);
+
+static inline void
+ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data)
+{
+	struct crypto_tfm *tfm = ahp->tfm;
+
+	memset(auth_data, 0, ahp->icv_trunc_len);
+	crypto_hmac_init(tfm, ahp->key, &ahp->key_len);
+	skb_ah_walk(skb, tfm, crypto_hmac_update);
+	crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_icv);
+	memcpy(auth_data, ahp->work_icv, ahp->icv_trunc_len);
+}
+
+#endif
diff -Nru a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
--- a/include/net/bluetooth/bluetooth.h	Thu Oct 31 18:06:05 2002
+++ b/include/net/bluetooth/bluetooth.h	Thu Mar  6 11:06:44 2003
@@ -128,7 +128,7 @@
 struct sock *bt_sock_alloc(struct socket *sock, int proto, int pi_size, int prio);
 void bt_sock_link(struct bt_sock_list *l, struct sock *s);
 void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
-int  bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags, struct scm_cookie *scm);
+int  bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags);
 uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
 int  bt_sock_w4_connect(struct sock *sk, int flags);
 
diff -Nru a/include/net/compat_socket.h b/include/net/compat_socket.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/net/compat_socket.h	Thu Mar  6 11:02:18 2003
@@ -0,0 +1,67 @@
+#ifndef NET_COMPAT_SOCKET_H
+#define NET_COMPAT_SOCKET_H 1
+
+#include <linux/compat.h>
+
+#if defined(CONFIG_COMPAT)
+
+/* XXX This really belongs in some header file... -DaveM */
+#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
+					   16 for IP, 16 for IPX,
+					   24 for IPv6,
+					   about 80 for AX.25 */
+
+struct compat_msghdr {
+	u32		msg_name;
+	int		msg_namelen;
+	u32		msg_iov;
+	compat_size_t	msg_iovlen;
+	u32		msg_control;
+	compat_size_t	msg_controllen;
+	unsigned	msg_flags;
+};
+
+struct compat_cmsghdr {
+	compat_size_t	cmsg_len;
+	int		cmsg_level;
+	int		cmsg_type;
+};
+
+/* Bleech... */
+#define __CMSG_COMPAT_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg_compat_nxthdr((ctl),(len),(cmsg),(cmsglen))
+#define CMSG_COMPAT_NXTHDR(mhdr, cmsg, cmsglen) cmsg_compat_nxthdr((mhdr), (cmsg), (cmsglen))
+
+#define CMSG_COMPAT_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
+
+#define CMSG_COMPAT_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr))))
+#define CMSG_COMPAT_SPACE(len) (CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + CMSG_COMPAT_ALIGN(len))
+#define CMSG_COMPAT_LEN(len) (CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + (len))
+
+#define __CMSG_COMPAT_FIRSTHDR(ctl,len) ((len) >= sizeof(struct compat_cmsghdr) ? \
+				    (struct compat_cmsghdr *)(ctl) : \
+				    (struct compat_cmsghdr *)NULL)
+#define CMSG_COMPAT_FIRSTHDR(msg)	__CMSG_COMPAT_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+
+static __inline__ struct compat_cmsghdr *__cmsg_compat_nxthdr(void *__ctl, __kernel_size_t __size,
+					      struct compat_cmsghdr *__cmsg, int __cmsg_len)
+{
+	struct compat_cmsghdr * __ptr;
+
+	__ptr = (struct compat_cmsghdr *)(((unsigned char *) __cmsg) +
+				     CMSG_COMPAT_ALIGN(__cmsg_len));
+	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
+		return NULL;
+
+	return __ptr;
+}
+
+static __inline__ struct compat_cmsghdr *cmsg_compat_nxthdr (struct msghdr *__msg,
+					    struct compat_cmsghdr *__cmsg,
+					    int __cmsg_len)
+{
+	return __cmsg_compat_nxthdr(__msg->msg_control, __msg->msg_controllen,
+			       __cmsg, __cmsg_len);
+}
+
+#endif /* CONFIG_COMPAT */
+#endif
diff -Nru a/include/net/dn_route.h b/include/net/dn_route.h
--- a/include/net/dn_route.h	Wed Feb 19 13:55:33 2003
+++ b/include/net/dn_route.h	Mon Mar  3 04:56:52 2003
@@ -134,7 +134,7 @@
 	}
 
 	sk->err = EHOSTUNREACH;
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 }
 
diff -Nru a/include/net/dst.h b/include/net/dst.h
--- a/include/net/dst.h	Sun Dec 22 23:29:59 2002
+++ b/include/net/dst.h	Wed Mar  5 15:45:36 2003
@@ -247,7 +247,10 @@
 struct flowi;
 extern int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
 		       struct sock *sk, int flags);
+extern int xfrm6_lookup(struct dst_entry **dst_p, struct flowi *fl,
+		       struct sock *sk, int flags);
 extern void xfrm_init(void);
+extern void xfrm6_init(void);
 
 #endif
 
diff -Nru a/include/net/esp.h b/include/net/esp.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/net/esp.h	Thu Mar  6 16:15:34 2003
@@ -0,0 +1,56 @@
+#ifndef _NET_ESP_H
+#define _NET_ESP_H
+
+#include <net/xfrm.h>
+
+struct esp_data
+{
+	/* Confidentiality */
+	struct {
+		u8			*key;		/* Key */
+		int			key_len;	/* Key length */
+		u8			*ivec;		/* ivec buffer */
+		/* ivlen is offset from enc_data, where encrypted data start.
+		 * It is logically different of crypto_tfm_alg_ivsize(tfm).
+		 * We assume that it is either zero (no ivec), or
+		 * >= crypto_tfm_alg_ivsize(tfm). */
+		int			ivlen;
+		int			padlen;		/* 0..255 */
+		struct crypto_tfm	*tfm;		/* crypto handle */
+	} conf;
+
+	/* Integrity. It is active when icv_full_len != 0 */
+	struct {
+		u8			*key;		/* Key */
+		int			key_len;	/* Length of the key */
+		u8			*work_icv;
+		int			icv_full_len;
+		int			icv_trunc_len;
+		void			(*icv)(struct esp_data*,
+		                               struct sk_buff *skb,
+		                               int offset, int len, u8 *icv);
+		struct crypto_tfm	*tfm;
+	} auth;
+};
+
+extern void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
+			 int offset, int len, icv_update_fn_t icv_update);
+extern int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len);
+extern int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer);
+extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len);
+
+static inline void
+esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset,
+                int len, u8 *auth_data)
+{
+	struct crypto_tfm *tfm = esp->auth.tfm;
+	char *icv = esp->auth.work_icv;
+
+	memset(auth_data, 0, esp->auth.icv_trunc_len);
+	crypto_hmac_init(tfm, esp->auth.key, &esp->auth.key_len);
+	skb_icv_walk(skb, tfm, offset, len, crypto_hmac_update);
+	crypto_hmac_final(tfm, esp->auth.key, &esp->auth.key_len, icv);
+	memcpy(auth_data, icv, esp->auth.icv_trunc_len);
+}
+
+#endif
diff -Nru a/include/net/inet_common.h b/include/net/inet_common.h
--- a/include/net/inet_common.h	Tue Oct  8 07:02:41 2002
+++ b/include/net/inet_common.h	Thu Mar  6 11:06:44 2003
@@ -23,11 +23,11 @@
 extern int			inet_recvmsg(struct kiocb *iocb,
 					     struct socket *sock, 
 					     struct msghdr *ubuf, 
-					     int size, int flags, struct scm_cookie *scm);
+					     int size, int flags);
 extern int			inet_sendmsg(struct kiocb *iocb,
 					     struct socket *sock, 
 					     struct msghdr *msg, 
-					     int size, struct scm_cookie *scm);
+					     int size);
 extern int			inet_shutdown(struct socket *sock, int how);
 extern unsigned int		inet_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait);
 extern int			inet_setsockopt(struct socket *sock, int level,
diff -Nru a/include/net/ip6_route.h b/include/net/ip6_route.h
--- a/include/net/ip6_route.h	Sun Feb 23 22:41:51 2003
+++ b/include/net/ip6_route.h	Wed Mar  5 15:45:36 2003
@@ -57,6 +57,8 @@
 					    struct in6_addr *saddr,
 					    int oif, int flags);
 
+extern struct rt6_info		*ndisc_get_dummy_rt(void);
+
 /*
  *	support functions for ND
  *
diff -Nru a/include/net/scm.h b/include/net/scm.h
--- a/include/net/scm.h	Fri Feb  8 19:10:55 2002
+++ b/include/net/scm.h	Thu Mar  6 11:06:44 2003
@@ -22,6 +22,7 @@
 };
 
 extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm);
+extern void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm);
 extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm);
 extern void __scm_destroy(struct scm_cookie *scm);
 extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl);
diff -Nru a/include/net/snmp.h b/include/net/snmp.h
--- a/include/net/snmp.h	Tue Jan  7 02:19:04 2003
+++ b/include/net/snmp.h	Mon Mar 10 11:55:44 2003
@@ -299,8 +299,8 @@
 #define DECLARE_SNMP_STAT(type, name)	\
 	extern __typeof__(type) *name[2]
 
-#define SNMP_STAT_USRPTR(name)	(name[0])
-#define SNMP_STAT_BHPTR(name)	(name[1])
+#define SNMP_STAT_BHPTR(name)	(name[0])
+#define SNMP_STAT_USRPTR(name)	(name[1])
 
 #define SNMP_INC_STATS_BH(mib, field) 	\
 	(per_cpu_ptr(mib[0], smp_processor_id())->field++)
diff -Nru a/include/net/sock.h b/include/net/sock.h
--- a/include/net/sock.h	Fri Feb  7 01:48:38 2003
+++ b/include/net/sock.h	Sat Mar  8 11:39:01 2003
@@ -29,6 +29,8 @@
  *              			protocol specific parts were moved to
  *              			respective headers and ipv4/v6, etc now
  *              			use private slabcaches for its socks
+ *              Pedro Hortas	:	New flags field for socket options
+ *
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -52,7 +54,6 @@
 
 #include <asm/atomic.h>
 #include <net/dst.h>
-#include <net/scm.h>
 
 /*
  * This structure really needs to be cleaned up.
@@ -60,6 +61,17 @@
  * the other protocols.
  */
 
+/* Sock flags */
+enum {
+	SOCK_DEAD,
+	SOCK_DONE,
+	SOCK_URGINLINE,
+	SOCK_KEEPOPEN,
+	SOCK_LINGER,
+	SOCK_DESTROY,
+	SOCK_BROADCAST,
+};
+
 /* Define this to get the sk->debug debugging facility. */
 #define SOCK_DEBUGGING
 #ifdef SOCK_DEBUGGING
@@ -120,18 +132,8 @@
 	int			sndbuf;		/* Size of send buffer in bytes		*/
 	struct sock		*prev;
 
-	/* Not all are volatile, but some are, so we might as well say they all are.
-	 * XXX Make this a flag word -DaveM
-	 */
-	volatile char		dead,
-				done,
-				urginline,
-				keepopen,
-				linger,
-				destroy,
-				no_check,
-				broadcast,
-				bsdism;
+	unsigned long 		flags;
+	char		 	no_check;
 	unsigned char		debug;
 	unsigned char		rcvtstamp;
 	unsigned char		no_largesend;
@@ -306,9 +308,9 @@
 	int			size;
 	struct socket		*sock;
 	struct sock		*sk;
+	struct scm_cookie	*scm;
 	struct msghdr		*msg, async_msg;
 	struct iovec		async_iov;
-	struct scm_cookie	*scm, async_scm;
 };
 
 static inline struct sock_iocb *kiocb_to_siocb(struct kiocb *iocb)
@@ -434,11 +436,9 @@
 extern int			sock_no_setsockopt(struct socket *, int, int,
 						   char *, int);
 extern int                      sock_no_sendmsg(struct kiocb *, struct socket *,
-						struct msghdr *, int,
-						struct scm_cookie *);
+						struct msghdr *, int);
 extern int                      sock_no_recvmsg(struct kiocb *, struct socket *,
-						struct msghdr *, int, int,
-						struct scm_cookie *);
+						struct msghdr *, int, int);
 extern int			sock_no_mmap(struct file *file,
 					     struct socket *sock,
 					     struct vm_area_struct *vma);
@@ -605,7 +605,7 @@
 static inline void sock_orphan(struct sock *sk)
 {
 	write_lock_bh(&sk->callback_lock);
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 	sk->socket = NULL;
 	sk->sleep = NULL;
 	write_unlock_bh(&sk->callback_lock);
@@ -769,7 +769,7 @@
 	skb->dev = NULL;
 	skb_set_owner_r(skb, sk);
 	skb_queue_tail(&sk->receive_queue, skb);
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->data_ready(sk,skb->len);
 out:
 	return err;
@@ -784,7 +784,7 @@
 		return -ENOMEM;
 	skb_set_owner_r(skb, sk);
 	skb_queue_tail(&sk->error_queue,skb);
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->data_ready(sk,skb->len);
 	return 0;
 }
@@ -895,6 +895,14 @@
 				remove_wait_queue((sk)->sleep, &wait); \
 				lock_sock(sk); \
 				}
+
+static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool)
+{
+	if (valbool)
+		__set_bit(bit, &sk->flags);
+	else
+		__clear_bit(bit, &sk->flags);
+}
 
 extern __u32 sysctl_wmem_max;
 extern __u32 sysctl_rmem_max;
diff -Nru a/include/net/tcp.h b/include/net/tcp.h
--- a/include/net/tcp.h	Mon Feb 10 14:44:43 2003
+++ b/include/net/tcp.h	Sat Mar  8 11:37:51 2003
@@ -144,6 +144,7 @@
 extern kmem_cache_t *tcp_bucket_cachep;
 extern struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head,
 						 unsigned short snum);
+extern void tcp_bucket_destroy(struct tcp_bind_bucket *tb);
 extern void tcp_bucket_unlock(struct sock *sk);
 extern int tcp_port_rover;
 extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
@@ -1422,7 +1423,7 @@
 
 	sk->shutdown = SHUTDOWN_MASK;
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 	else
 		tcp_destroy_sock(sk);
diff -Nru a/include/net/xfrm.h b/include/net/xfrm.h
--- a/include/net/xfrm.h	Thu Feb 13 01:26:32 2003
+++ b/include/net/xfrm.h	Thu Mar  6 16:16:15 2003
@@ -12,6 +12,7 @@
 
 #include <net/dst.h>
 #include <net/route.h>
+#include <net/ip6_fib.h>
 
 #define XFRM_ALIGN8(len)	(((len) + 7) & ~7)
 
@@ -223,7 +224,7 @@
 	char			*id;
 	int			(*notify)(struct xfrm_state *x, int event);
 	int			(*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
-	struct xfrm_policy	*(*compile_policy)(int opt, u8 *data, int len, int *dir);
+	struct xfrm_policy	*(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir);
 };
 
 extern int xfrm_register_km(struct xfrm_mgr *km);
@@ -282,6 +283,7 @@
 		struct xfrm_dst		*next;
 		struct dst_entry	dst;
 		struct rtable		rt;
+		struct rt6_info		rt6;
 	} u;
 };
 
@@ -308,26 +310,42 @@
 	if (sp && atomic_dec_and_test(&sp->refcnt))
 		__secpath_destroy(sp);
 }
-
-extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb);
+extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, unsigned short family);
 
 static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
 {
 	if (sk && sk->policy[XFRM_POLICY_IN])
-		return __xfrm_policy_check(sk, dir, skb);
+		return __xfrm_policy_check(sk, dir, skb, AF_INET);
+		
+	return	!xfrm_policy_list[dir] ||
+		(skb->dst->flags & DST_NOPOLICY) ||
+		__xfrm_policy_check(sk, dir, skb, AF_INET);
+}
+
+static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
+{
+	if (sk && sk->policy[XFRM_POLICY_IN])
+		return __xfrm_policy_check(sk, dir, skb, AF_INET6);
 		
 	return	!xfrm_policy_list[dir] ||
 		(skb->dst->flags & DST_NOPOLICY) ||
-		__xfrm_policy_check(sk, dir, skb);
+		__xfrm_policy_check(sk, dir, skb, AF_INET6);
 }
 
-extern int __xfrm_route_forward(struct sk_buff *skb);
+extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
 
 static inline int xfrm_route_forward(struct sk_buff *skb)
 {
 	return	!xfrm_policy_list[XFRM_POLICY_OUT] ||
 		(skb->dst->flags & DST_NOXFRM) ||
-		__xfrm_route_forward(skb);
+		__xfrm_route_forward(skb, AF_INET);
+}
+
+static inline int xfrm6_route_forward(struct sk_buff *skb)
+{
+	return	!xfrm_policy_list[XFRM_POLICY_OUT] ||
+		(skb->dst->flags & DST_NOXFRM) ||
+		__xfrm_route_forward(skb, AF_INET6);
 }
 
 extern int __xfrm_sk_clone_policy(struct sock *sk);
@@ -380,12 +398,16 @@
 extern void xfrm_input_init(void);
 extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *);
 extern struct xfrm_state *xfrm_state_alloc(void);
-extern struct xfrm_state *xfrm_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
-					  struct xfrm_policy *pol, int *err);
+extern struct xfrm_state *xfrm4_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
+					   struct xfrm_policy *pol, int *err);
+extern struct xfrm_state *xfrm6_state_find(struct in6_addr *daddr, struct in6_addr *saddr,
+					   struct flowi *fl, struct xfrm_tmpl *tmpl,
+					   struct xfrm_policy *pol, int *err);
 extern int xfrm_state_check_expire(struct xfrm_state *x);
 extern void xfrm_state_insert(struct xfrm_state *x);
 extern int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb);
-extern struct xfrm_state *xfrm_state_lookup(u32 daddr, u32 spi, u8 proto);
+extern struct xfrm_state *xfrm4_state_lookup(u32 daddr, u32 spi, u8 proto);
+extern struct xfrm_state *xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto);
 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
 extern void xfrm_state_delete(struct xfrm_state *x);
 extern void xfrm_state_flush(u8 proto);
@@ -393,17 +415,21 @@
 extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
 extern int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl);
 extern int xfrm4_rcv(struct sk_buff *skb);
+extern int xfrm6_rcv(struct sk_buff *skb);
+extern int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir);
 extern int xfrm_user_policy(struct sock *sk, int optname, u8 *optval, int optlen);
 
 struct xfrm_policy *xfrm_policy_alloc(int gfp);
 extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *);
-struct xfrm_policy *xfrm_policy_lookup(int dir, struct flowi *fl);
+struct xfrm_policy *xfrm_policy_lookup(int dir, struct flowi *fl, unsigned short family);
 int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
 struct xfrm_policy *xfrm_policy_delete(int dir, struct xfrm_selector *sel);
 struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete);
 void xfrm_policy_flush(void);
 void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
 struct xfrm_state * xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create);
+struct xfrm_state * xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr,
+				   struct in6_addr *saddr, int create);
 extern void xfrm_policy_flush(void);
 extern void xfrm_policy_kill(struct xfrm_policy *);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
@@ -425,23 +451,52 @@
 extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name);
 extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name);
 
+static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
+{
+	__u32 *a1 = token1;
+	__u32 *a2 = token2;
+	int pdw;
+	int pbi;
+
+	pdw = prefixlen >> 5;	  /* num of whole __u32 in prefix */
+	pbi = prefixlen &  0x1f;  /* num of bits in incomplete u32 in prefix */
+
+	if (pdw)
+		if (memcmp(a1, a2, pdw << 2))
+			return 0;
+
+	if (pbi) {
+		__u32 mask;
+
+		mask = htonl((0xffffffff) << (32 - pbi));
+
+		if ((a1[pdw] ^ a2[pdw]) & mask)
+			return 0;
+	}
+
+	return 1;
+}
+
 static inline int
 xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl)
 {
-      return  !memcmp(fl->fl6_dst, sel->daddr.a6, sizeof(struct in6_addr)) &&
-              !((fl->uli_u.ports.dport^sel->dport)&sel->dport_mask) &&
-              !((fl->uli_u.ports.sport^sel->sport)&sel->sport_mask) &&
-              (fl->proto == sel->proto || !sel->proto) &&
-              (fl->oif == sel->ifindex || !sel->ifindex) &&
-              !memcmp(fl->fl6_src, sel->saddr.a6, sizeof(struct in6_addr));
+	return  addr_match(fl->fl6_dst, &sel->daddr, sel->prefixlen_d) &&
+		addr_match(fl->fl6_src, &sel->saddr, sel->prefixlen_s) &&
+		!((fl->uli_u.ports.dport^sel->dport)&sel->dport_mask) &&
+		!((fl->uli_u.ports.sport^sel->sport)&sel->sport_mask) &&
+		(fl->proto == sel->proto || !sel->proto) &&
+		(fl->oif == sel->ifindex || !sel->ifindex);
 }
 
 extern int xfrm6_register_type(struct xfrm_type *type);
 extern int xfrm6_unregister_type(struct xfrm_type *type);
 extern struct xfrm_type *xfrm6_get_type(u8 proto);
 
-extern struct xfrm_state *xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto);
-struct xfrm_state * xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr, struct in6_addr *saddr, int create);
-void xfrm6_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
+struct crypto_tfm;
+typedef void (icv_update_fn_t)(struct crypto_tfm *, struct scatterlist *, unsigned int);
+
+typedef int (xfrm_dst_lookup_t)(struct xfrm_dst **dst, struct flowi *fl);
+int xfrm_dst_lookup_register(xfrm_dst_lookup_t *dst_lookup, unsigned short family);
+void xfrm_dst_lookup_unregister(unsigned short family);
 
 #endif	/* _NET_XFRM_H */
diff -Nru a/init/Kconfig b/init/Kconfig
--- a/init/Kconfig	Mon Feb  3 12:19:37 2003
+++ b/init/Kconfig	Mon Mar 10 22:34:13 2003
@@ -37,6 +37,16 @@
 
 menu "General setup"
 
+config SWAP
+	bool "Support for paging of anonymous memory"
+	depends on MMU
+	default y
+	help
+	  This option allows you to choose whether you want to have support
+	  for socalled swap devices or swap files in your kernel that are
+	  used to provide more virtual memory than the actual RAM present
+	  in your computer.  If unsure say Y.
+
 config SYSVIPC
 	bool "System V IPC"
 	---help---
diff -Nru a/init/do_mounts.c b/init/do_mounts.c
--- a/init/do_mounts.c	Sat Mar  1 11:25:53 2003
+++ b/init/do_mounts.c	Thu Mar  6 16:27:25 2003
@@ -17,7 +17,7 @@
 int __initdata rd_doload;	/* 1 = load RAM disk, 0 = don't load */
 
 int root_mountflags = MS_RDONLY | MS_VERBOSE;
-static char * __initdata root_device_name;
+char * __initdata root_device_name;
 static char __initdata saved_root_name[64];
 
 /* this is initialized in init/main.c */
diff -Nru a/init/do_mounts.h b/init/do_mounts.h
--- a/init/do_mounts.h	Fri Feb 21 23:12:30 2003
+++ b/init/do_mounts.h	Thu Mar  6 16:27:25 2003
@@ -27,6 +27,7 @@
 void  mount_block_root(char *name, int flags);
 void  mount_root(void);
 extern int root_mountflags;
+extern char *root_device_name;
 
 #ifdef CONFIG_DEVFS_FS
 
diff -Nru a/init/do_mounts_rd.c b/init/do_mounts_rd.c
--- a/init/do_mounts_rd.c	Fri Feb 21 23:12:30 2003
+++ b/init/do_mounts_rd.c	Thu Mar  6 16:27:25 2003
@@ -242,6 +242,7 @@
 {
 	if (rd_prompt)
 		change_floppy("root floppy disk to be loaded into RAM disk");
+	create_dev("/dev/root", ROOT_DEV, root_device_name);
 	create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL);
 	return rd_load_image("/dev/root");
 }
diff -Nru a/kernel/cpufreq.c b/kernel/cpufreq.c
--- a/kernel/cpufreq.c	Mon Mar  3 14:38:51 2003
+++ b/kernel/cpufreq.c	Sat Mar  8 01:39:17 2003
@@ -43,12 +43,40 @@
  */
 static struct notifier_block    *cpufreq_policy_notifier_list;
 static struct notifier_block    *cpufreq_transition_notifier_list;
-static DECLARE_MUTEX            (cpufreq_notifier_sem);
+static DECLARE_RWSEM		(cpufreq_notifier_rwsem);
 
 
 LIST_HEAD(cpufreq_governor_list);
+static DECLARE_MUTEX		(cpufreq_governor_sem);
 
-static int cpufreq_governor(unsigned int cpu, unsigned int event);
+static struct device_interface cpufreq_interface;
+
+static int cpufreq_cpu_get(unsigned int cpu) {
+	if (cpu >= NR_CPUS)
+		return 0;
+
+	if (!kset_get(&cpufreq_interface.kset))
+		return 0;
+
+	if (!try_module_get(cpufreq_driver->owner)) {
+		kset_put(&cpufreq_interface.kset);
+		return 0;
+	}
+
+	if (!kobject_get(&cpufreq_driver->policy[cpu].kobj)) {
+		module_put(cpufreq_driver->owner);
+		kset_put(&cpufreq_interface.kset);
+		return 0;
+	}
+
+	return 1;
+}
+
+static void cpufreq_cpu_put(unsigned int cpu) {
+	kobject_put(&cpufreq_driver->policy[cpu].kobj);
+	module_put(cpufreq_driver->owner);
+	kset_put(&cpufreq_interface.kset);
+}
 
 /*********************************************************************
  *                          SYSFS INTERFACE                          *
@@ -67,19 +95,19 @@
 		return 0;
 	} else 	{
 		struct cpufreq_governor *t;
-		down(&cpufreq_driver_sem);
+		down(&cpufreq_governor_sem);
 		if (!cpufreq_driver || !cpufreq_driver->target)
 			goto out;
 		list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
 			if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
 				*governor = t;
 				*policy = CPUFREQ_POLICY_GOVERNOR;
-				up(&cpufreq_driver_sem);
+				up(&cpufreq_governor_sem);
 				return 0;
 			}
 		}
 	out:
-		up(&cpufreq_driver_sem);
+		up(&cpufreq_governor_sem);
 	}
 	return -EINVAL;
 }
@@ -120,14 +148,7 @@
 static ssize_t show_##file_name 					\
 (struct cpufreq_policy * policy, char *buf)				\
 {									\
-	unsigned int value = 0;						\
-									\
-	down(&cpufreq_driver_sem);					\
-	if (cpufreq_driver)						\
-		value = policy->object;					\
-	up(&cpufreq_driver_sem);					\
-									\
-	return sprintf (buf, "%u\n", value);				\
+	return sprintf (buf, "%u\n", policy->object);			\
 }
 
 show_one(cpuinfo_min_freq, cpuinfo.min_freq);
@@ -143,12 +164,17 @@
 (struct cpufreq_policy * policy, const char *buf, size_t count)		\
 {									\
 	unsigned int ret = -EINVAL;					\
+	struct cpufreq_policy new_policy;				\
 									\
-	ret = sscanf (buf, "%u", &policy->object);			\
+	ret = cpufreq_get_policy(&new_policy, policy->cpu);		\
+	if (ret)							\
+		return -EINVAL;						\
+									\
+	ret = sscanf (buf, "%u", &new_policy.object);			\
 	if (ret != 1)							\
 		return -EINVAL;						\
 									\
-	ret = cpufreq_set_policy(policy);				\
+	ret = cpufreq_set_policy(&new_policy);				\
 									\
 	return ret ? ret : count;					\
 }
@@ -161,26 +187,16 @@
  */
 static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf)
 {
-	unsigned int value = 0;
-	char value2[CPUFREQ_NAME_LEN];
-
-	down(&cpufreq_driver_sem);
-	if (cpufreq_driver)
-		value = policy->policy;
-	if (value == CPUFREQ_POLICY_GOVERNOR)
-		strncpy(value2, policy->governor->name, CPUFREQ_NAME_LEN);
-	up(&cpufreq_driver_sem);
-
-	switch (value) {
+	switch (policy->policy) {
 	case CPUFREQ_POLICY_POWERSAVE:
 		return sprintf(buf, "powersave\n");
 	case CPUFREQ_POLICY_PERFORMANCE:
 		return sprintf(buf, "performance\n");
 	case CPUFREQ_POLICY_GOVERNOR:
-		return sprintf(buf, "%s\n", value2);
+		return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name);
+	default:
+		return -EINVAL;
 	}
-
-	return -EINVAL;
 }
 
 
@@ -192,25 +208,55 @@
 {
 	unsigned int ret = -EINVAL;
 	char	str_governor[16];
+	struct cpufreq_policy new_policy;
+
+	ret = cpufreq_get_policy(&new_policy, policy->cpu);
+	if (ret)
+		return ret;
 
 	ret = sscanf (buf, "%15s", str_governor);
 	if (ret != 1)
 		return -EINVAL;
 
-	if (cpufreq_parse_governor(str_governor, &policy->policy, &policy->governor))
+	if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor))
 		return -EINVAL;
 
-	ret = cpufreq_set_policy(policy);
+	ret = cpufreq_set_policy(&new_policy);
 
 	return ret ? ret : count;
 }
 
+/**
+ * show_scaling_driver - show the cpufreq driver currently loaded
+ */
+static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf)
+{
+	return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name);
+}
+
+/**
+ * show_scaling_available_governors - show the available CPUfreq governors
+ */
+static ssize_t show_scaling_available_governors(struct cpufreq_policy * policy, char *buf)
+{
+	ssize_t i = 0;
+	struct cpufreq_governor *t;
+
+	i += sprintf(buf, "performance powersave");
+
+	if (!cpufreq_driver->target)
+		goto out;
+
+	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
+		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2)))
+			goto out;
+		i += snprintf(&buf[i], CPUFREQ_NAME_LEN, " %s", t->name);
+	}
+ out:
+	i += sprintf(&buf[i], "\n");
+	return i;
+}
 
-struct freq_attr {
-	struct attribute attr;
-	ssize_t (*show)(struct cpufreq_policy *, char *);
-	ssize_t (*store)(struct cpufreq_policy *, const char *, size_t count);
-};
 
 #define define_one_ro(_name) \
 struct freq_attr _name = { \
@@ -227,6 +273,8 @@
 
 define_one_ro(cpuinfo_min_freq);
 define_one_ro(cpuinfo_max_freq);
+define_one_ro(scaling_available_governors);
+define_one_ro(scaling_driver);
 define_one_rw(scaling_min_freq);
 define_one_rw(scaling_max_freq);
 define_one_rw(scaling_governor);
@@ -237,10 +285,11 @@
 	&scaling_min_freq.attr,
 	&scaling_max_freq.attr,
 	&scaling_governor.attr,
+	&scaling_driver.attr,
+	&scaling_available_governors.attr,
 	NULL
 };
 
-
 #define to_policy(k) container_of(k,struct cpufreq_policy,kobj)
 #define to_attr(a) container_of(a,struct freq_attr,attr)
 
@@ -248,7 +297,12 @@
 {
 	struct cpufreq_policy * policy = to_policy(kobj);
 	struct freq_attr * fattr = to_attr(attr);
-	return fattr->show ? fattr->show(policy,buf) : 0;
+	ssize_t ret;
+	if (!cpufreq_cpu_get(policy->cpu))
+		return -EINVAL;
+	ret = fattr->show ? fattr->show(policy,buf) : 0;
+	cpufreq_cpu_put(policy->cpu);
+	return ret;
 }
 
 static ssize_t store(struct kobject * kobj, struct attribute * attr, 
@@ -256,7 +310,12 @@
 {
 	struct cpufreq_policy * policy = to_policy(kobj);
 	struct freq_attr * fattr = to_attr(attr);
-	return fattr->store ? fattr->store(policy,buf,count) : 0;
+	ssize_t ret;
+	if (!cpufreq_cpu_get(policy->cpu))
+		return -EINVAL;
+	ret = fattr->store ? fattr->store(policy,buf,count) : 0;
+	cpufreq_cpu_put(policy->cpu);
+	return ret;
 }
 
 static struct sysfs_ops sysfs_ops = {
@@ -271,56 +330,6 @@
 
 
 /**
- * show_scaling_governor - show the current policy for the specified CPU
- */
-static ssize_t show_scaling_driver (struct device *dev, char *buf)
-{
-	char value[CPUFREQ_NAME_LEN];
-
-	if (!dev)
-		return 0;
-
-	down(&cpufreq_driver_sem);
-	if (cpufreq_driver)
-		strncpy(value, cpufreq_driver->name, CPUFREQ_NAME_LEN);
-	up(&cpufreq_driver_sem);
-
-	return sprintf(buf, "%s\n", value);
-}
-
-/**
- * show_available_govs - show the available CPUfreq governors
- */
-static ssize_t show_available_govs(struct device *dev, char *buf)
-{
-	ssize_t i = 0;
-	struct cpufreq_governor *t;
-
-	if (!dev)
-		return 0;
-
-	i += sprintf(buf, "performance powersave");
-
-	down(&cpufreq_driver_sem);
-	if (!cpufreq_driver || !cpufreq_driver->target)
-		goto out;
-
-	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
-		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2)))
-			goto out;
-		i += snprintf(&buf[i], CPUFREQ_NAME_LEN, " %s", t->name);
-	}
- out:
-	up(&cpufreq_driver_sem);
-	i += sprintf(&buf[i], "\n");
-	return i;
-}
-
-
-static DEVICE_ATTR(scaling_driver, S_IRUGO, show_scaling_driver, NULL);
-static DEVICE_ATTR(available_scaling_governors, S_IRUGO, show_available_govs, NULL);
-
-/**
  * cpufreq_add_dev - add a CPU device
  *
  * Adds the cpufreq interface for a CPU device. 
@@ -329,50 +338,62 @@
 {
 	unsigned int cpu = to_cpu_nr(dev);
 	int ret = 0;
-	struct cpufreq_policy policy;
+	struct cpufreq_policy new_policy;
+	struct cpufreq_policy *policy;
+	struct freq_attr **drv_attr;
 
-	down(&cpufreq_driver_sem);
-	if (!cpufreq_driver) {
-		up(&cpufreq_driver_sem);
+	if (!kset_get(&cpufreq_interface.kset))
+		return -EINVAL;
+
+	if (!try_module_get(cpufreq_driver->owner)) {
+		kset_put(&cpufreq_interface.kset);
 		return -EINVAL;
 	}
 
 	/* call driver. From then on the cpufreq must be able
 	 * to accept all calls to ->verify and ->setpolicy for this CPU
 	 */
-	cpufreq_driver->policy[cpu].cpu = cpu;
+	policy = &cpufreq_driver->policy[cpu];
+	policy->cpu = cpu;
 	if (cpufreq_driver->init) {
-		ret = cpufreq_driver->init(&cpufreq_driver->policy[cpu]);
-		if (ret) {
-			up(&cpufreq_driver_sem);
-			return -ENODEV;
-		}
+		ret = cpufreq_driver->init(policy);
+		if (ret)
+			goto out;
 	}
 
 	/* set default policy on this CPU */
-	memcpy(&policy, 
-	       &cpufreq_driver->policy[cpu], 
+	down(&cpufreq_driver_sem);
+	memcpy(&new_policy, 
+	       policy, 
 	       sizeof(struct cpufreq_policy));
-
-	if (cpufreq_driver->target)
-		cpufreq_governor(cpu, CPUFREQ_GOV_START);
-
 	up(&cpufreq_driver_sem);
-	ret = cpufreq_set_policy(&policy);
-	if (ret)
-		return -EINVAL;
-	down(&cpufreq_driver_sem);
 
+	init_MUTEX(&policy->lock);
 	/* prepare interface data */
-	policy.kobj.parent = &dev->kobj;
-	policy.kobj.ktype = &ktype_cpufreq;
-	policy.dev = dev;
-	strncpy(policy.kobj.name, 
+	policy->kobj.parent = &dev->kobj;
+	policy->kobj.ktype = &ktype_cpufreq;
+	policy->dev = dev;
+	strncpy(policy->kobj.name, 
 		cpufreq_interface.name, KOBJ_NAME_LEN);
 
-	ret = kobject_register(&policy.kobj);
+	ret = kobject_register(&policy->kobj);
+	if (ret)
+		goto out;
 
-	up(&cpufreq_driver_sem);
+	drv_attr = cpufreq_driver->attr;
+	while ((drv_attr) && (*drv_attr)) {
+		sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
+		drv_attr++;
+	}
+
+	/* set default policy */
+	ret = cpufreq_set_policy(&new_policy);
+	if (ret)
+		kobject_unregister(&policy->kobj);
+
+ out:
+	module_put(cpufreq_driver->owner);
+	kset_put(&cpufreq_interface.kset);
 	return ret;
 }
 
@@ -380,21 +401,39 @@
 /**
  * cpufreq_remove_dev - remove a CPU device
  *
- * Removes the cpufreq interface for a CPU device. Is called with
- * cpufreq_driver_sem locked.
+ * Removes the cpufreq interface for a CPU device.
  */
 static int cpufreq_remove_dev (struct device * dev)
 {
 	unsigned int cpu = to_cpu_nr(dev);
 
-	if (cpufreq_driver->target)
-		cpufreq_governor(cpu, CPUFREQ_GOV_STOP);
+	if (!kset_get(&cpufreq_interface.kset))
+		return -EINVAL;
+
+	if (!kobject_get(&cpufreq_driver->policy[cpu].kobj)) {
+		kset_put(&cpufreq_interface.kset);
+		return -EINVAL;
+	}
 
+	down(&cpufreq_driver_sem);
+	if ((cpufreq_driver->target) && 
+	    (cpufreq_driver->policy[cpu].policy == CPUFREQ_POLICY_GOVERNOR)) {
+		cpufreq_driver->policy[cpu].governor->governor(&cpufreq_driver->policy[cpu], CPUFREQ_GOV_STOP);
+		module_put(cpufreq_driver->policy[cpu].governor->owner);
+	}
+
+	/* we may call driver->exit here without checking for try_module_exit
+	 * as it's either the driver which wants to unload or we have a CPU
+	 * removal AND driver removal at the same time...
+	 */
 	if (cpufreq_driver->exit)
 		cpufreq_driver->exit(&cpufreq_driver->policy[cpu]);
 
 	kobject_unregister(&cpufreq_driver->policy[cpu].kobj);
 
+	up(&cpufreq_driver_sem);
+	kobject_put(&cpufreq_driver->policy[cpu].kobj);
+	kset_put(&cpufreq_interface.kset);
 	return 0;
 }
 
@@ -420,7 +459,7 @@
 {
 	int ret;
 
-	down(&cpufreq_notifier_sem);
+	down_write(&cpufreq_notifier_rwsem);
 	switch (list) {
 	case CPUFREQ_TRANSITION_NOTIFIER:
 		ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb);
@@ -431,7 +470,7 @@
 	default:
 		ret = -EINVAL;
 	}
-	up(&cpufreq_notifier_sem);
+	up_write(&cpufreq_notifier_rwsem);
 
 	return ret;
 }
@@ -452,7 +491,7 @@
 {
 	int ret;
 
-	down(&cpufreq_notifier_sem);
+	down_write(&cpufreq_notifier_rwsem);
 	switch (list) {
 	case CPUFREQ_TRANSITION_NOTIFIER:
 		ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb);
@@ -463,7 +502,7 @@
 	default:
 		ret = -EINVAL;
 	}
-	up(&cpufreq_notifier_sem);
+	up_write(&cpufreq_notifier_rwsem);
 
 	return ret;
 }
@@ -474,71 +513,72 @@
  *                              GOVERNORS                            *
  *********************************************************************/
 
-inline int cpufreq_driver_target_l(struct cpufreq_policy *policy,
-				   unsigned int target_freq,
-				   unsigned int relation)
-{
-	unsigned int ret;
-	down(&cpufreq_driver_sem);
-	if (!cpufreq_driver)
-		ret = -EINVAL;
-	else
-		ret = cpufreq_driver->target(policy, target_freq, relation);
-	up(&cpufreq_driver_sem);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(cpufreq_driver_target_l);
-
-
 inline int cpufreq_driver_target(struct cpufreq_policy *policy,
 				 unsigned int target_freq,
 				 unsigned int relation)
 {
-	return cpufreq_driver->target(policy, target_freq, relation);
+	unsigned int ret;
+	unsigned int cpu = policy->cpu;
+
+	if (!cpufreq_cpu_get(cpu))
+		return -EINVAL;
+
+	down(&cpufreq_driver->policy[cpu].lock);
+
+	ret = cpufreq_driver->target(policy, target_freq, relation);
+
+	up(&cpufreq_driver->policy[cpu].lock);
+
+	cpufreq_cpu_put(cpu);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(cpufreq_driver_target);
 
 
-static int cpufreq_governor(unsigned int cpu, unsigned int event)
+int cpufreq_governor(unsigned int cpu, unsigned int event)
 {
 	int ret = 0;
 	struct cpufreq_policy *policy = &cpufreq_driver->policy[cpu];
 
+	if (!cpufreq_cpu_get(cpu))
+		return -EINVAL;
+
 	switch (policy->policy) {
 	case CPUFREQ_POLICY_POWERSAVE: 
-		if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START))
+		if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
+			down(&cpufreq_driver->policy[cpu].lock);
 			ret = cpufreq_driver->target(policy, policy->min, CPUFREQ_RELATION_L);
+			up(&cpufreq_driver->policy[cpu].lock);
+		}
 		break;
 	case CPUFREQ_POLICY_PERFORMANCE:
-		if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START))
+		if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
+			down(&cpufreq_driver->policy[cpu].lock);
 			ret = cpufreq_driver->target(policy, policy->max, CPUFREQ_RELATION_H);
+			up(&cpufreq_driver->policy[cpu].lock);
+		}
 		break;
 	case CPUFREQ_POLICY_GOVERNOR:
 		ret = -EINVAL;
-		if (event == CPUFREQ_GOV_START)
-			if (!try_module_get(cpufreq_driver->policy[cpu].governor->owner))
-				break;
+		if (!try_module_get(cpufreq_driver->policy[cpu].governor->owner))
+			break;
 		ret = cpufreq_driver->policy[cpu].governor->governor(policy, event);
-		if ((event == CPUFREQ_GOV_STOP) ||
-			(ret && (event == CPUFREQ_GOV_START)))
+		/* we keep one module reference alive for each CPU governed by this CPU */
+		if ((event != CPUFREQ_GOV_START) || ret)
+			module_put(cpufreq_driver->policy[cpu].governor->owner);
+		if ((event == CPUFREQ_GOV_STOP) && !ret)
 			module_put(cpufreq_driver->policy[cpu].governor->owner);
 		break;
 	default:
 		ret = -EINVAL;
 	}
-	return ret;
-}
 
+	cpufreq_cpu_put(cpu);
 
-int cpufreq_governor_l(unsigned int cpu, unsigned int event)
-{
-	int ret = 0;
-	down(&cpufreq_driver_sem);
-	ret = cpufreq_governor(cpu, event);
-	up(&cpufreq_driver_sem);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(cpufreq_governor_l);
+EXPORT_SYMBOL_GPL(cpufreq_governor);
 
 
 int cpufreq_register_governor(struct cpufreq_governor *governor)
@@ -553,16 +593,17 @@
 	if (!strnicmp(governor->name,"performance",CPUFREQ_NAME_LEN))
 		return -EBUSY;
 
-	down(&cpufreq_driver_sem);
+	down(&cpufreq_governor_sem);
 	
 	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
 		if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) {
-			up(&cpufreq_driver_sem);
+			up(&cpufreq_governor_sem);
 			return -EBUSY;
 		}
 	}
 	list_add(&governor->governor_list, &cpufreq_governor_list);
- 	up(&cpufreq_driver_sem);
+
+ 	up(&cpufreq_governor_sem);
 
 	return 0;
 }
@@ -576,7 +617,8 @@
 	if (!governor)
 		return;
 
-	down(&cpufreq_driver_sem);
+	down(&cpufreq_governor_sem);
+
 	/* 
 	 * Unless the user uses rmmod -f, we can be safe. But we never
 	 * know, so check whether if it's currently used. If so,
@@ -584,17 +626,21 @@
 	 */
 	for (i=0; i<NR_CPUS; i++)
 	{
-		if (cpufreq_driver && 
-		    (cpufreq_driver->policy[i].policy == CPUFREQ_POLICY_GOVERNOR) && 
+		if (!cpufreq_cpu_get(i))
+			continue;
+		if ((cpufreq_driver->policy[i].policy == CPUFREQ_POLICY_GOVERNOR) && 
 		    (cpufreq_driver->policy[i].governor == governor)) {
 			cpufreq_governor(i, CPUFREQ_GOV_STOP);
 			cpufreq_driver->policy[i].policy = CPUFREQ_POLICY_PERFORMANCE;
 			cpufreq_governor(i, CPUFREQ_GOV_START);
+			cpufreq_governor(i, CPUFREQ_GOV_LIMITS);
 		}
+		cpufreq_cpu_put(i);
 	}
+
 	/* now we can safely remove it from the list */
 	list_del(&governor->governor_list);
-	up(&cpufreq_driver_sem);
+	up(&cpufreq_governor_sem);
 	return;
 }
 EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
@@ -613,19 +659,17 @@
  */
 int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
 {
-	down(&cpufreq_driver_sem);
-	if (!cpufreq_driver  || !policy || 
-	    (cpu >= NR_CPUS) || (!cpu_online(cpu))) {
-		up(&cpufreq_driver_sem);
+	if (!policy || !cpufreq_cpu_get(cpu))
 		return -EINVAL;
-	}
 
+	down(&cpufreq_driver_sem);
 	memcpy(policy, 
 	       &cpufreq_driver->policy[cpu], 
 	       sizeof(struct cpufreq_policy));
-	
 	up(&cpufreq_driver_sem);
 
+	cpufreq_cpu_put(cpu);
+
 	return 0;
 }
 EXPORT_SYMBOL(cpufreq_get_policy);
@@ -639,27 +683,23 @@
  */
 int cpufreq_set_policy(struct cpufreq_policy *policy)
 {
-	int ret;
+	int ret = 0;
 
-	down(&cpufreq_driver_sem);
-	if (!cpufreq_driver || !policy ||
-	    (policy->cpu >= NR_CPUS) || (!cpu_online(policy->cpu))) {
-		up(&cpufreq_driver_sem);
+	if (!policy || !cpufreq_cpu_get(policy->cpu))
 		return -EINVAL;
-	}
 
+	down(&cpufreq_driver_sem);
 	memcpy(&policy->cpuinfo, 
 	       &cpufreq_driver->policy[policy->cpu].cpuinfo, 
 	       sizeof(struct cpufreq_cpuinfo));
+	up(&cpufreq_driver_sem);
 
 	/* verify the cpu speed can be set within this limit */
 	ret = cpufreq_driver->verify(policy);
-	if (ret) {
-		up(&cpufreq_driver_sem);
-		return ret;
-	}
+	if (ret)
+		goto error_out;
 
-	down(&cpufreq_notifier_sem);
+	down_read(&cpufreq_notifier_rwsem);
 
 	/* adjust if necessary - all reasons */
 	notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST,
@@ -673,17 +713,18 @@
 	   which might be different to the first one */
 	ret = cpufreq_driver->verify(policy);
 	if (ret) {
-		up(&cpufreq_notifier_sem);
-		up(&cpufreq_driver_sem);
-		return ret;
+		up_read(&cpufreq_notifier_rwsem);
+		goto error_out;
 	}
 
 	/* notification of the new policy */
 	notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY,
 			    policy);
 
-	up(&cpufreq_notifier_sem);
+	up_read(&cpufreq_notifier_rwsem);
 
+	/* from here on we limit it to one limit and/or governor change running at the moment */
+	down(&cpufreq_driver_sem);
 	cpufreq_driver->policy[policy->cpu].min    = policy->min;
 	cpufreq_driver->policy[policy->cpu].max    = policy->max;
 
@@ -711,9 +752,11 @@
 			cpufreq_governor(policy->cpu, CPUFREQ_GOV_LIMITS);
 		}
 	}
-	
 	up(&cpufreq_driver_sem);
 
+ error_out:	
+	cpufreq_cpu_put(policy->cpu);
+
 	return ret;
 }
 EXPORT_SYMBOL(cpufreq_set_policy);
@@ -759,7 +802,7 @@
  */
 void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
 {
-	down(&cpufreq_notifier_sem);
+	down_read(&cpufreq_notifier_rwsem);
 	switch (state) {
 	case CPUFREQ_PRECHANGE:
 		notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
@@ -771,7 +814,7 @@
 		cpufreq_driver->policy[freqs->cpu].cur = freqs->new;
 		break;
 	}
-	up(&cpufreq_notifier_sem);
+	up_read(&cpufreq_notifier_rwsem);
 }
 EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
 
@@ -793,38 +836,33 @@
  */
 int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 {
-	int ret = 0;
-
-	if (cpufreq_driver)
-		return -EBUSY;
-	
-	if (!driver_data || !driver_data->verify || 
+	if (!driver_data || !driver_data->verify || !driver_data->init ||
 	    ((!driver_data->setpolicy) && (!driver_data->target)))
 		return -EINVAL;
 
-	down(&cpufreq_driver_sem);
 
+	if (kset_get(&cpufreq_interface.kset)) {
+		kset_put(&cpufreq_interface.kset);
+		return -EBUSY;
+	}
+
+	down(&cpufreq_driver_sem);
+	if (cpufreq_driver) {
+		up(&cpufreq_driver_sem);		
+		return -EBUSY;
+	}
 	cpufreq_driver = driver_data;
+	up(&cpufreq_driver_sem);
 
+	cpufreq_driver->policy = kmalloc(NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
 	if (!cpufreq_driver->policy) {
-		/* then we need per-CPU init */
-		if (!cpufreq_driver->init) {
-			up(&cpufreq_driver_sem);
-			return -EINVAL;
-		}
-		cpufreq_driver->policy = kmalloc(NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
-		if (!cpufreq_driver->policy) {
-			up(&cpufreq_driver_sem);
-			return -ENOMEM;
-		}
-		memset(cpufreq_driver->policy, 0, NR_CPUS * sizeof(struct cpufreq_policy));
+		cpufreq_driver = NULL;
+		return -ENOMEM;
 	}
-	
-	up(&cpufreq_driver_sem);
 
-	ret = interface_register(&cpufreq_interface);
+	memset(cpufreq_driver->policy, 0, NR_CPUS * sizeof(struct cpufreq_policy));
 
-	return ret;
+	return interface_register(&cpufreq_interface);
 }
 EXPORT_SYMBOL_GPL(cpufreq_register_driver);
 
@@ -839,20 +877,20 @@
  */
 int cpufreq_unregister_driver(struct cpufreq_driver *driver)
 {
-	down(&cpufreq_driver_sem);
+	if (!kset_get(&cpufreq_interface.kset))
+		return 0;
 
-	if (!cpufreq_driver || 
-	    ((driver != cpufreq_driver) && (driver != NULL))) { /* compat */
-		up(&cpufreq_driver_sem);
+	if (!cpufreq_driver || (driver != cpufreq_driver)) {
+		kset_put(&cpufreq_interface.kset);
 		return -EINVAL;
 	}
 
+	kset_put(&cpufreq_interface.kset);
 	interface_unregister(&cpufreq_interface);
 
-	if (driver)
-		kfree(cpufreq_driver->policy);
+	down(&cpufreq_driver_sem);
+	kfree(cpufreq_driver->policy);
 	cpufreq_driver = NULL;
-
 	up(&cpufreq_driver_sem);
 
 	return 0;
@@ -876,21 +914,27 @@
 	if (in_interrupt())
 		panic("cpufreq_restore() called from interrupt context!");
 
+	if (!kset_get(&cpufreq_interface.kset))
+		return 0;
+
+	if (!try_module_get(cpufreq_driver->owner))
+		goto error_out;
+
 	for (i=0;i<NR_CPUS;i++) {
-		if (!cpu_online(i))
+		if (!cpu_online(i) || !cpufreq_cpu_get(i))
 			continue;
 
 		down(&cpufreq_driver_sem);
-		if (!cpufreq_driver) {
-			up(&cpufreq_driver_sem);
-			return 0;
-		}
-
 		memcpy(&policy, &cpufreq_driver->policy[i], sizeof(struct cpufreq_policy));
 		up(&cpufreq_driver_sem);
-
 		ret += cpufreq_set_policy(&policy);
+
+		cpufreq_cpu_put(i);
 	}
+
+	module_put(cpufreq_driver->owner);
+ error_out:
+	kset_put(&cpufreq_interface.kset);
 
 	return ret;
 }
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Thu Feb 27 23:02:30 2003
+++ b/kernel/fork.c	Mon Mar 10 22:34:31 2003
@@ -188,7 +188,7 @@
 	task_struct_cachep =
 		kmem_cache_create("task_struct",
 				  sizeof(struct task_struct),0,
-				  SLAB_HWCACHE_ALIGN, NULL, NULL);
+				  SLAB_MUST_HWCACHE_ALIGN, NULL, NULL);
 	if (!task_struct_cachep)
 		panic("fork_init(): cannot create task_struct SLAB cache");
 
@@ -214,6 +214,8 @@
 	struct thread_info *ti;
 	int cpu = get_cpu();
 
+	prepare_to_copy(orig);
+
 	tsk = task_cache[cpu];
 	task_cache[cpu] = NULL;
 	put_cpu();
@@ -916,7 +918,7 @@
 	 */
 	p->first_time_slice = 1;
 	current->time_slice >>= 1;
-	p->sleep_timestamp = jiffies;
+	p->last_run = jiffies;
 	if (!current->time_slice) {
 		/*
 	 	 * This case is rare, it happens when the parent has only
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Sun Mar  2 18:13:25 2003
+++ b/kernel/ksyms.c	Sun Mar  9 12:15:42 2003
@@ -57,6 +57,7 @@
 #include <linux/mount.h>
 #include <linux/ptrace.h>
 #include <linux/time.h>
+#include <linux/backing-dev.h>
 #include <asm/checksum.h>
 
 #if defined(CONFIG_PROC_FS)
@@ -234,15 +235,6 @@
 EXPORT_SYMBOL(generic_file_mmap);
 EXPORT_SYMBOL(generic_file_readonly_mmap);
 EXPORT_SYMBOL(generic_ro_fops);
-EXPORT_SYMBOL(file_lock_list);
-EXPORT_SYMBOL(locks_init_lock);
-EXPORT_SYMBOL(locks_copy_lock);
-EXPORT_SYMBOL(posix_lock_file);
-EXPORT_SYMBOL(posix_test_lock);
-EXPORT_SYMBOL(posix_block_lock);
-EXPORT_SYMBOL(posix_unblock_lock);
-EXPORT_SYMBOL(posix_locks_deadlock);
-EXPORT_SYMBOL(locks_mandatory_area);
 EXPORT_SYMBOL(dput);
 EXPORT_SYMBOL(have_submounts);
 EXPORT_SYMBOL(d_find_alias);
@@ -367,6 +359,7 @@
 EXPORT_SYMBOL(generic_file_readv);
 EXPORT_SYMBOL(generic_file_writev);
 EXPORT_SYMBOL(iov_shorten);
+EXPORT_SYMBOL_GPL(default_backing_dev_info);
 
 /* tty routines */
 EXPORT_SYMBOL(tty_wait_until_sent);
diff -Nru a/kernel/posix-timers.c b/kernel/posix-timers.c
--- a/kernel/posix-timers.c	Wed Feb 26 12:02:09 2003
+++ b/kernel/posix-timers.c	Sun Mar  9 18:48:02 2003
@@ -1273,7 +1273,7 @@
 		spin_unlock_irq(&nanosleep_abs_list_lock);
 	}
 	if (active) {
-		unsigned long jiffies_f = jiffies;
+		long jiffies_left;
 
 		/*
 		 * Always restart abs calls from scratch to pick up any
@@ -1282,7 +1282,12 @@
 		if (abs)
 			return -ERESTARTNOHAND;
 
-		jiffies_to_timespec(new_timer.expires - jiffies_f, tsave);
+		jiffies_left = new_timer.expires - jiffies;
+
+		if (jiffies_left < 0)
+			return 0;
+
+		jiffies_to_timespec(jiffies_left, tsave);
 
 		while (tsave->tv_nsec < 0) {
 			tsave->tv_nsec += NSEC_PER_SEC;
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Thu Feb 20 20:33:52 2003
+++ b/kernel/sched.c	Sat Mar  8 02:19:29 2003
@@ -33,6 +33,12 @@
 #include <linux/timer.h>
 #include <linux/rcupdate.h>
 
+#ifdef CONFIG_NUMA
+#define cpu_to_node_mask(cpu) node_to_cpumask(cpu_to_node(cpu))
+#else
+#define cpu_to_node_mask(cpu) (cpu_online_map)
+#endif
+
 /*
  * Convert user-nice values [ -20 ... 0 ... 19 ]
  * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
@@ -54,20 +60,20 @@
 /*
  * These are the 'tuning knobs' of the scheduler:
  *
- * Minimum timeslice is 10 msecs, default timeslice is 150 msecs,
- * maximum timeslice is 300 msecs. Timeslices get refilled after
+ * Minimum timeslice is 10 msecs, default timeslice is 100 msecs,
+ * maximum timeslice is 200 msecs. Timeslices get refilled after
  * they expire.
  */
 #define MIN_TIMESLICE		( 10 * HZ / 1000)
-#define MAX_TIMESLICE		(300 * HZ / 1000)
-#define CHILD_PENALTY		95
+#define MAX_TIMESLICE		(200 * HZ / 1000)
+#define CHILD_PENALTY		50
 #define PARENT_PENALTY		100
 #define EXIT_WEIGHT		3
 #define PRIO_BONUS_RATIO	25
 #define INTERACTIVE_DELTA	2
-#define MAX_SLEEP_AVG		(2*HZ)
-#define STARVATION_LIMIT	(2*HZ)
-#define NODE_THRESHOLD          125
+#define MAX_SLEEP_AVG		(10*HZ)
+#define STARVATION_LIMIT	(10*HZ)
+#define NODE_THRESHOLD		125
 
 /*
  * If a task is 'interactive' then we reinsert it in the active
@@ -154,10 +160,9 @@
 	task_t *curr, *idle;
 	struct mm_struct *prev_mm;
 	prio_array_t *active, *expired, arrays[2];
-	int prev_nr_running[NR_CPUS];
+	int prev_cpu_load[NR_CPUS];
 #ifdef CONFIG_NUMA
 	atomic_t *node_nr_running;
-	unsigned int nr_balanced;
 	int prev_node_load[MAX_NUMNODES];
 #endif
 	task_t *migration_thread;
@@ -302,10 +307,13 @@
  *
  * Both properties are important to certain workloads.
  */
-static inline int effective_prio(task_t *p)
+static int effective_prio(task_t *p)
 {
 	int bonus, prio;
 
+	if (rt_task(p))
+		return p->prio;
+
 	bonus = MAX_USER_PRIO*PRIO_BONUS_RATIO*p->sleep_avg/MAX_SLEEP_AVG/100 -
 			MAX_USER_PRIO*PRIO_BONUS_RATIO/100/2;
 
@@ -318,31 +326,65 @@
 }
 
 /*
- * activate_task - move a task to the runqueue.
+ * __activate_task - move a task to the runqueue.
+ */
+static inline void __activate_task(task_t *p, runqueue_t *rq)
+{
+	enqueue_task(p, rq->active);
+	nr_running_inc(rq);
+}
 
- * Also update all the scheduling statistics stuff. (sleep average
+/*
+ * activate_task - move a task to the runqueue and do priority recalculation
+ *
+ * Update all the scheduling statistics stuff. (sleep average
  * calculation, priority modifiers, etc.)
  */
-static inline void activate_task(task_t *p, runqueue_t *rq)
+static inline int activate_task(task_t *p, runqueue_t *rq)
 {
-	unsigned long sleep_time = jiffies - p->sleep_timestamp;
-	prio_array_t *array = rq->active;
+	unsigned long sleep_time = jiffies - p->last_run;
+	int requeue_waker = 0;
+
+	if (sleep_time) {
+		int sleep_avg;
 
-	if (!rt_task(p) && sleep_time) {
 		/*
-		 * This code gives a bonus to interactive tasks. We update
-		 * an 'average sleep time' value here, based on
-		 * sleep_timestamp. The more time a task spends sleeping,
-		 * the higher the average gets - and the higher the priority
-		 * boost gets as well.
+		 * This code gives a bonus to interactive tasks.
+		 *
+		 * The boost works by updating the 'average sleep time'
+		 * value here, based on ->last_run. The more time a task
+		 * spends sleeping, the higher the average gets - and the
+		 * higher the priority boost gets as well.
 		 */
-		p->sleep_avg += sleep_time;
-		if (p->sleep_avg > MAX_SLEEP_AVG)
-			p->sleep_avg = MAX_SLEEP_AVG;
-		p->prio = effective_prio(p);
+		sleep_avg = p->sleep_avg + sleep_time;
+
+		/*
+		 * 'Overflow' bonus ticks go to the waker as well, so the
+		 * ticks are not lost. This has the effect of further
+		 * boosting tasks that are related to maximum-interactive
+		 * tasks.
+		 */
+		if (sleep_avg > MAX_SLEEP_AVG) {
+			if (!in_interrupt()) {
+				sleep_avg += current->sleep_avg - MAX_SLEEP_AVG;
+				if (sleep_avg > MAX_SLEEP_AVG)
+					sleep_avg = MAX_SLEEP_AVG;
+
+				if (current->sleep_avg != sleep_avg) {
+					current->sleep_avg = sleep_avg;
+					requeue_waker = 1;
+				}
+			}
+			sleep_avg = MAX_SLEEP_AVG;
+		}
+		if (p->sleep_avg != sleep_avg) {
+			p->sleep_avg = sleep_avg;
+			p->prio = effective_prio(p);
+		}
 	}
-	enqueue_task(p, array);
-	nr_running_inc(rq);
+	__activate_task(p, rq);
+
+	return requeue_waker;
 }
 
 /*
@@ -455,8 +497,8 @@
  */
 static int try_to_wake_up(task_t * p, unsigned int state, int sync)
 {
+	int success = 0, requeue_waker = 0;
 	unsigned long flags;
-	int success = 0;
 	long old_state;
 	runqueue_t *rq;
 
@@ -479,16 +521,34 @@
 			}
 			if (old_state == TASK_UNINTERRUPTIBLE)
 				rq->nr_uninterruptible--;
-			activate_task(p, rq);
-	
-			if (p->prio < rq->curr->prio)
-				resched_task(rq->curr);
+			if (sync)
+				__activate_task(p, rq);
+			else {
+				requeue_waker = activate_task(p, rq);
+				if (p->prio < rq->curr->prio)
+					resched_task(rq->curr);
+			}
 			success = 1;
 		}
 		p->state = TASK_RUNNING;
 	}
 	task_rq_unlock(rq, &flags);
 
+	/*
+	 * We have to do this outside the other spinlock, the two
+	 * runqueues might be different:
+	 */
+	if (requeue_waker) {
+		prio_array_t *array;
+
+		rq = task_rq_lock(current, &flags);
+		array = current->array;
+		dequeue_task(current, array);
+		current->prio = effective_prio(current);
+		enqueue_task(current, array);
+		task_rq_unlock(rq, &flags);
+	}
+
 	return success;
 }
 
@@ -514,19 +574,25 @@
 	runqueue_t *rq = task_rq_lock(current, &flags);
 
 	p->state = TASK_RUNNING;
-	if (!rt_task(p)) {
-		/*
-		 * We decrease the sleep average of forking parents
-		 * and children as well, to keep max-interactive tasks
-		 * from forking tasks that are max-interactive.
-		 */
-		current->sleep_avg = current->sleep_avg * PARENT_PENALTY / 100;
-		p->sleep_avg = p->sleep_avg * CHILD_PENALTY / 100;
-		p->prio = effective_prio(p);
-	}
+	/*
+	 * We decrease the sleep average of forking parents
+	 * and children as well, to keep max-interactive tasks
+	 * from forking tasks that are max-interactive.
+	 */
+	current->sleep_avg = current->sleep_avg * PARENT_PENALTY / 100;
+	p->sleep_avg = p->sleep_avg * CHILD_PENALTY / 100;
+	p->prio = effective_prio(p);
 	set_task_cpu(p, smp_processor_id());
-	activate_task(p, rq);
 
+	if (unlikely(!current->array))
+		__activate_task(p, rq);
+	else {
+		p->prio = current->prio;
+		list_add_tail(&p->run_list, &current->run_list);
+		p->array = current->array;
+		p->array->nr_active++;
+		nr_running_inc(rq);
+	}
 	task_rq_unlock(rq, &flags);
 }
 
@@ -806,29 +872,6 @@
 	return node;
 }
 
-static inline unsigned long cpus_to_balance(int this_cpu, runqueue_t *this_rq)
-{
-	int this_node = cpu_to_node(this_cpu);
-	/*
-	 * Avoid rebalancing between nodes too often.
-	 * We rebalance globally once every NODE_BALANCE_RATE load balances.
-	 */
-	if (++(this_rq->nr_balanced) == NODE_BALANCE_RATE) {
-		int node = find_busiest_node(this_node);
-		this_rq->nr_balanced = 0;
-		if (node >= 0)
-			return (node_to_cpumask(node) | (1UL << this_cpu));
-	}
-	return node_to_cpumask(this_node);
-}
-
-#else /* !CONFIG_NUMA */
-
-static inline unsigned long cpus_to_balance(int this_cpu, runqueue_t *this_rq)
-{
-	return cpu_online_map;
-}
-
 #endif /* CONFIG_NUMA */
 
 #if CONFIG_SMP
@@ -848,10 +891,10 @@
 			spin_lock(&busiest->lock);
 			spin_lock(&this_rq->lock);
 			/* Need to recalculate nr_running */
-			if (idle || (this_rq->nr_running > this_rq->prev_nr_running[this_cpu]))
+			if (idle || (this_rq->nr_running > this_rq->prev_cpu_load[this_cpu]))
 				nr_running = this_rq->nr_running;
 			else
-				nr_running = this_rq->prev_nr_running[this_cpu];
+				nr_running = this_rq->prev_cpu_load[this_cpu];
 		} else
 			spin_lock(&busiest->lock);
 	}
@@ -888,10 +931,10 @@
 	 * that case we are less picky about moving a task across CPUs and
 	 * take what can be taken.
 	 */
-	if (idle || (this_rq->nr_running > this_rq->prev_nr_running[this_cpu]))
+	if (idle || (this_rq->nr_running > this_rq->prev_cpu_load[this_cpu]))
 		nr_running = this_rq->nr_running;
 	else
-		nr_running = this_rq->prev_nr_running[this_cpu];
+		nr_running = this_rq->prev_cpu_load[this_cpu];
 
 	busiest = NULL;
 	max_load = 1;
@@ -900,11 +943,11 @@
 			continue;
 
 		rq_src = cpu_rq(i);
-		if (idle || (rq_src->nr_running < this_rq->prev_nr_running[i]))
+		if (idle || (rq_src->nr_running < this_rq->prev_cpu_load[i]))
 			load = rq_src->nr_running;
 		else
-			load = this_rq->prev_nr_running[i];
-		this_rq->prev_nr_running[i] = rq_src->nr_running;
+			load = this_rq->prev_cpu_load[i];
+		this_rq->prev_cpu_load[i] = rq_src->nr_running;
 
 		if ((load > max_load) && (rq_src != this_rq)) {
 			busiest = rq_src;
@@ -953,6 +996,11 @@
 	 */
 	if (p->prio < this_rq->curr->prio)
 		set_need_resched();
+	else {
+		if (p->prio == this_rq->curr->prio &&
+				p->time_slice > this_rq->curr->time_slice)
+			set_need_resched();
+	}
 }
 
 /*
@@ -963,7 +1011,7 @@
  * We call this with the current runqueue locked,
  * irqs disabled.
  */
-static void load_balance(runqueue_t *this_rq, int idle)
+static void load_balance(runqueue_t *this_rq, int idle, unsigned long cpumask)
 {
 	int imbalance, idx, this_cpu = smp_processor_id();
 	runqueue_t *busiest;
@@ -971,8 +1019,7 @@
 	struct list_head *head, *curr;
 	task_t *tmp;
 
-	busiest = find_busiest_queue(this_rq, this_cpu, idle, &imbalance,
-					cpus_to_balance(this_cpu, this_rq));
+	busiest = find_busiest_queue(this_rq, this_cpu, idle, &imbalance, cpumask);
 	if (!busiest)
 		goto out;
 
@@ -1016,7 +1063,7 @@
 	 */
 
 #define CAN_MIGRATE_TASK(p,rq,this_cpu)					\
-	((jiffies - (p)->sleep_timestamp > cache_decay_ticks) &&	\
+	((jiffies - (p)->last_run > cache_decay_ticks) &&	\
 		!task_running(rq, p) &&					\
 			((p)->cpus_allowed & (1UL << (this_cpu))))
 
@@ -1047,21 +1094,75 @@
  * frequency and balancing agressivity depends on whether the CPU is
  * idle or not.
  *
- * busy-rebalance every 250 msecs. idle-rebalance every 1 msec. (or on
+ * busy-rebalance every 200 msecs. idle-rebalance every 1 msec. (or on
  * systems with HZ=100, every 10 msecs.)
+ *
+ * On NUMA, do a node-rebalance every 400 msecs.
  */
-#define BUSY_REBALANCE_TICK (HZ/4 ?: 1)
 #define IDLE_REBALANCE_TICK (HZ/1000 ?: 1)
+#define BUSY_REBALANCE_TICK (HZ/5 ?: 1)
+#define IDLE_NODE_REBALANCE_TICK (IDLE_REBALANCE_TICK * 5)
+#define BUSY_NODE_REBALANCE_TICK (BUSY_REBALANCE_TICK * 100)
 
-static inline void idle_tick(runqueue_t *rq)
+#if CONFIG_NUMA
+static void balance_node(runqueue_t *this_rq, int idle, int this_cpu)
 {
-	if (jiffies % IDLE_REBALANCE_TICK)
-		return;
-	spin_lock(&rq->lock);
-	load_balance(rq, 1);
-	spin_unlock(&rq->lock);
+	int node = find_busiest_node(cpu_to_node(this_cpu));
+	unsigned long cpumask, this_cpumask = 1UL << this_cpu;
+
+	if (node >= 0) {
+		cpumask = node_to_cpumask(node) | this_cpumask;
+		spin_lock(&this_rq->lock);
+		load_balance(this_rq, idle, cpumask);
+		spin_unlock(&this_rq->lock);
+	}
 }
+#endif
 
+static void rebalance_tick(runqueue_t *this_rq, int idle)
+{
+#if CONFIG_NUMA
+	int this_cpu = smp_processor_id();
+#endif
+	unsigned long j = jiffies;
+
+	/*
+	 * First do inter-node rebalancing, then intra-node rebalancing,
+	 * if both events happen in the same tick. The inter-node
+	 * rebalancing does not necessarily have to create a perfect
+	 * balance within the node, since we load-balance the most loaded
+	 * node with the current CPU. (ie. other CPUs in the local node
+	 * are not balanced.)
+	 */
+	if (idle) {
+#if CONFIG_NUMA
+		if (!(j % IDLE_NODE_REBALANCE_TICK))
+			balance_node(this_rq, idle, this_cpu);
+#endif
+		if (!(j % IDLE_REBALANCE_TICK)) {
+			spin_lock(&this_rq->lock);
+			load_balance(this_rq, 0, cpu_to_node_mask(this_cpu));
+			spin_unlock(&this_rq->lock);
+		}
+		return;
+	}
+#if CONFIG_NUMA
+	if (!(j % BUSY_NODE_REBALANCE_TICK))
+		balance_node(this_rq, idle, this_cpu);
+#endif
+	if (!(j % BUSY_REBALANCE_TICK)) {
+		spin_lock(&this_rq->lock);
+		load_balance(this_rq, idle, cpu_to_node_mask(this_cpu));
+		spin_unlock(&this_rq->lock);
+	}
+}
+#else
+/*
+ * on UP we do not need to balance between CPUs:
+ */
+static inline void rebalance_tick(runqueue_t *this_rq, int idle)
+{
+}
 #endif
 
 DEFINE_PER_CPU(struct kernel_stat, kstat) = { { 0 } };
@@ -1076,9 +1177,9 @@
  * increasing number of running tasks:
  */
 #define EXPIRED_STARVING(rq) \
-		((rq)->expired_timestamp && \
+		(STARVATION_LIMIT && ((rq)->expired_timestamp && \
 		(jiffies - (rq)->expired_timestamp >= \
-			STARVATION_LIMIT * ((rq)->nr_running) + 1))
+			STARVATION_LIMIT * ((rq)->nr_running) + 1)))
 
 /*
  * This function gets called by the timer code, with HZ frequency.
@@ -1104,9 +1205,7 @@
 			kstat_cpu(cpu).cpustat.iowait += sys_ticks;
 		else
 			kstat_cpu(cpu).cpustat.idle += sys_ticks;
-#if CONFIG_SMP
-		idle_tick(rq);
-#endif
+		rebalance_tick(rq, 1);
 		return;
 	}
 	if (TASK_NICE(p) > 0)
@@ -1121,6 +1220,16 @@
 		return;
 	}
 	spin_lock(&rq->lock);
+	/*
+	 * The task was running during this tick - update the
+	 * time slice counter and the sleep average. Note: we
+	 * do not update a thread's priority until it either
+	 * goes to sleep or uses up its timeslice. This makes
+	 * it possible for interactive tasks to use up their
+	 * timeslices at their highest priority levels.
+	 */
+	if (p->sleep_avg)
+		p->sleep_avg--;
 	if (unlikely(rt_task(p))) {
 		/*
 		 * RR tasks need a special form of timeslice management.
@@ -1137,16 +1246,6 @@
 		}
 		goto out;
 	}
-	/*
-	 * The task was running during this tick - update the
-	 * time slice counter and the sleep average. Note: we
-	 * do not update a thread's priority until it either
-	 * goes to sleep or uses up its timeslice. This makes
-	 * it possible for interactive tasks to use up their
-	 * timeslices at their highest priority levels.
-	 */
-	if (p->sleep_avg)
-		p->sleep_avg--;
 	if (!--p->time_slice) {
 		dequeue_task(p, rq->active);
 		set_tsk_need_resched(p);
@@ -1162,11 +1261,8 @@
 			enqueue_task(p, rq->active);
 	}
 out:
-#if CONFIG_SMP
-	if (!(jiffies % BUSY_REBALANCE_TICK))
-		load_balance(rq, 0);
-#endif
 	spin_unlock(&rq->lock);
+	rebalance_tick(rq, 0);
 }
 
 void scheduling_functions_start_here(void) { }
@@ -1201,7 +1297,7 @@
 	rq = this_rq();
 
 	release_kernel_lock(prev);
-	prev->sleep_timestamp = jiffies;
+	prev->last_run = jiffies;
 	spin_lock_irq(&rq->lock);
 
 	/*
@@ -1225,7 +1321,7 @@
 pick_next_task:
 	if (unlikely(!rq->nr_running)) {
 #if CONFIG_SMP
-		load_balance(rq, 1);
+		load_balance(rq, 1, cpu_to_node_mask(smp_processor_id()));
 		if (rq->nr_running)
 			goto pick_next_task;
 #endif
@@ -1701,7 +1797,7 @@
 	else
 		p->prio = p->static_prio;
 	if (array)
-		activate_task(p, task_rq(p));
+		__activate_task(p, task_rq(p));
 
 out_unlock:
 	task_rq_unlock(rq, &flags);
@@ -2315,7 +2411,7 @@
 			set_task_cpu(p, cpu_dest);
 			if (p->array) {
 				deactivate_task(p, rq_src);
-				activate_task(p, rq_dest);
+				__activate_task(p, rq_dest);
 				if (p->prio < rq_dest->curr->prio)
 					resched_task(rq_dest->curr);
 			}
@@ -2442,6 +2538,7 @@
 	rq->idle = current;
 	set_task_cpu(current, smp_processor_id());
 	wake_up_forked_process(current);
+	current->prio = MAX_PRIO;
 
 	init_timers();
 
diff -Nru a/kernel/softirq.c b/kernel/softirq.c
--- a/kernel/softirq.c	Tue Feb 11 14:57:54 2003
+++ b/kernel/softirq.c	Fri Mar  7 02:39:07 2003
@@ -92,10 +92,9 @@
 			mask &= ~pending;
 			goto restart;
 		}
-		__local_bh_enable();
-
 		if (pending)
 			wakeup_softirqd(cpu);
+		__local_bh_enable();
 	}
 
 	local_irq_restore(flags);
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Mon Feb 24 23:13:14 2003
+++ b/mm/filemap.c	Sat Mar  8 14:50:29 2003
@@ -562,7 +562,7 @@
 find_page:
 		page = find_get_page(mapping, index);
 		if (unlikely(page == NULL)) {
-			handle_ra_miss(mapping, ra);
+			handle_ra_miss(mapping, ra, index);
 			goto no_cached_page;
 		}
 		if (!PageUptodate(page))
@@ -978,7 +978,7 @@
 	page = find_get_page(mapping, pgoff);
 	if (!page) {
 		if (did_readahead) {
-			handle_ra_miss(mapping,ra);
+			handle_ra_miss(mapping, ra, pgoff);
 			did_readahead = 0;
 		}
 		goto no_cached_page;
diff -Nru a/mm/fremap.c b/mm/fremap.c
--- a/mm/fremap.c	Wed Feb  5 20:05:09 2003
+++ b/mm/fremap.c	Thu Feb 20 08:38:13 2003
@@ -1,5 +1,5 @@
 /*
- *   linux/mm/mpopulate.c
+ *   linux/mm/fremap.c
  * 
  * Explicit pagetable population and nonlinear (random) mappings support.
  *
diff -Nru a/mm/memory.c b/mm/memory.c
--- a/mm/memory.c	Mon Feb 24 23:13:16 2003
+++ b/mm/memory.c	Sat Mar  8 14:50:40 2003
@@ -286,9 +286,16 @@
 					goto cont_copy_pte_range_noset;
 				}
 				pfn = pte_pfn(pte);
+				/* the pte points outside of valid memory, the
+				 * mapping is assumed to be good, meaningful
+				 * and not mapped via rmap - duplicate the
+				 * mapping as is.
+				 */
+				if (!pfn_valid(pfn)) {
+					set_pte(dst_pte, pte);
+					goto cont_copy_pte_range_noset;
+				}
 				page = pfn_to_page(pfn);
-				if (!pfn_valid(pfn))
-					goto cont_copy_pte_range;
 				if (PageReserved(page))
 					goto cont_copy_pte_range;
 
@@ -477,6 +484,16 @@
 #define ZAP_BLOCK_SIZE	(~(0UL))
 #endif
 
+/*
+ * hugepage regions must be unmapped with HPAGE_SIZE granularity
+ */
+static inline unsigned long zap_block_size(struct vm_area_struct *vma)
+{
+	if (is_vm_hugetlb_page(vma))
+		return HPAGE_SIZE;
+	return ZAP_BLOCK_SIZE;
+}
+
 /**
  * unmap_vmas - unmap a range of memory covered by a list of vma's
  * @tlbp: address of the caller's struct mmu_gather
@@ -507,7 +524,7 @@
 		struct vm_area_struct *vma, unsigned long start_addr,
 		unsigned long end_addr, unsigned long *nr_accounted)
 {
-	unsigned long zap_bytes = ZAP_BLOCK_SIZE;
+	unsigned long zap_bytes = zap_block_size(vma);
 	unsigned long tlb_start;	/* For tlb_finish_mmu */
 	int tlb_start_valid = 0;
 	int ret = 0;
@@ -555,7 +572,7 @@
 				*tlbp = tlb_gather_mmu(mm, 0);
 				tlb_start_valid = 0;
 			}
-			zap_bytes = ZAP_BLOCK_SIZE;
+			zap_bytes = zap_block_size(vma);
 		}
 		if (vma->vm_next && vma->vm_next->vm_start < vma->vm_end)
 			printk("%s: VMA list is not sorted correctly!\n",
diff -Nru a/mm/mmap.c b/mm/mmap.c
--- a/mm/mmap.c	Sun Mar  2 18:14:37 2003
+++ b/mm/mmap.c	Sat Mar  8 14:50:32 2003
@@ -1258,20 +1258,24 @@
  
 	/*
 	 * If we need to split any vma, do it now to save pain later.
+	 *
+	 * Note: mremap's move_vma VM_ACCOUNT handling assumes a partially
+	 * unmapped vm_area_struct will remain in use: so lower split_vma
+	 * places tmp vma above, and higher split_vma places tmp vma below.
 	 */
 	if (start > mpnt->vm_start) {
 		if (split_vma(mm, mpnt, start, 0))
 			return -ENOMEM;
 		prev = mpnt;
-		mpnt = mpnt->vm_next;
 	}
 
 	/* Does it split the last one? */
 	last = find_vma(mm, end);
 	if (last && end > last->vm_start) {
-		if (split_vma(mm, last, end, 0))
+		if (split_vma(mm, last, end, 1))
 			return -ENOMEM;
 	}
+	mpnt = prev? prev->vm_next: mm->mmap;
 
 	/*
 	 * Remove the vma's, and unmap the actual pages
diff -Nru a/mm/mremap.c b/mm/mremap.c
--- a/mm/mremap.c	Wed Feb  5 20:05:32 2003
+++ b/mm/mremap.c	Thu Feb 20 08:37:02 2003
@@ -1,5 +1,5 @@
 /*
- *	mm/remap.c
+ *	mm/mremap.c
  *
  *	(C) Copyright 1996 Linus Torvalds
  *
diff -Nru a/mm/page-writeback.c b/mm/page-writeback.c
--- a/mm/page-writeback.c	Fri Feb 14 18:24:05 2003
+++ b/mm/page-writeback.c	Sat Mar  8 14:50:24 2003
@@ -139,6 +139,9 @@
 	struct page_state ps;
 	long background_thresh;
 	long dirty_thresh;
+	unsigned long pages_written = 0;
+	unsigned long write_chunk = sync_writeback_pages();
+
 	struct backing_dev_info *bdi = mapping->backing_dev_info;
 
 	get_dirty_limits(&ps, &background_thresh, &dirty_thresh);
@@ -147,7 +150,7 @@
 			.bdi		= bdi,
 			.sync_mode	= WB_SYNC_NONE,
 			.older_than_this = NULL,
-			.nr_to_write	= sync_writeback_pages(),
+			.nr_to_write	= write_chunk,
 		};
 
 		dirty_exceeded = 1;
@@ -158,10 +161,14 @@
 		get_dirty_limits(&ps, &background_thresh, &dirty_thresh);
 		if (ps.nr_dirty + ps.nr_writeback <= dirty_thresh)
 			break;
+		pages_written += write_chunk - wbc.nr_to_write;
+		if (pages_written >= write_chunk)
+			break;		/* We've done our duty */
 		blk_congestion_wait(WRITE, HZ/10);
 	}
 
-	dirty_exceeded = 0;
+	if (ps.nr_dirty + ps.nr_writeback <= dirty_thresh)
+		dirty_exceeded = 0;
 
 	if (!writeback_in_progress(bdi) && ps.nr_dirty > background_thresh)
 		pdflush_operation(background_writeout, 0);
diff -Nru a/mm/pdflush.c b/mm/pdflush.c
--- a/mm/pdflush.c	Fri Feb 21 01:41:33 2003
+++ b/mm/pdflush.c	Mon Mar 10 22:34:08 2003
@@ -106,6 +106,7 @@
 		schedule();
 		if (current->flags & PF_FREEZE) {
 			refrigerator(PF_IOTHREAD);
+			spin_lock_irq(&pdflush_lock);
 			continue;
 		}
 
diff -Nru a/mm/readahead.c b/mm/readahead.c
--- a/mm/readahead.c	Wed Feb  5 20:04:19 2003
+++ b/mm/readahead.c	Sat Mar  8 14:50:29 2003
@@ -136,6 +136,12 @@
  * ahead_size:  Together, these form the "ahead window".
  * ra_pages:	The externally controlled max readahead for this fd.
  *
+ * When readahead is in the "maximally shrunk" state (next_size == -1UL),
+ * readahead is disabled.  In this state, prev_page and size are used, inside
+ * handle_ra_miss(), to detect the resumption of sequential I/O.  Once there
+ * has been a decent run of sequential I/O (defined by get_min_readahead),
+ * readahead is reenabled.
+ *
  * The readahead code manages two windows - the "current" and the "ahead"
  * windows.  The intent is that while the application is walking the pages
  * in the current window, I/O is underway on the ahead window.  When the
@@ -168,6 +174,8 @@
  * will continue to perform linear reads.  Either at the new file position, or
  * at the old one after another seek.
  *
+ * After enough misses, readahead is fully disabled. (next_size = -1UL).
+ *
  * There is a special-case: if the first page which the application tries to
  * read happens to be the first page of the file, it is assumed that a linear
  * read is about to happen and the window is immediately set to half of the
@@ -253,14 +261,19 @@
 	int ret = 0;
 
 	while (nr_to_read) {
+		int err;
+
 		unsigned long this_chunk = (2 * 1024 * 1024) / PAGE_CACHE_SIZE;
 
 		if (this_chunk > nr_to_read)
 			this_chunk = nr_to_read;
-		ret = __do_page_cache_readahead(mapping, filp,
+		err = __do_page_cache_readahead(mapping, filp,
 						offset, this_chunk);
-		if (ret < 0)
+		if (err < 0) {
+			ret = err;
 			break;
+		}
+		ret += err;
 		offset += this_chunk;
 		nr_to_read -= this_chunk;
 	}
@@ -286,6 +299,7 @@
 				ra->ahead_size = ra->next_size;
 		} else {
 			ra->next_size = -1UL;
+			ra->size = 0;
 		}
 	}
 }
@@ -345,16 +359,19 @@
 		ra->next_size += 2;
 	} else {
 		/*
-		 * A miss - lseek, pread, etc.  Shrink the readahead
+		 * A miss - lseek, pagefault, pread, etc.  Shrink the readahead
 		 * window by 25%.
 		 */
-		ra->next_size -= ra->next_size / 4;
+		ra->next_size -= ra->next_size / 4 + 2;
 	}
 
-	if (ra->next_size > max)
+	if ((long)ra->next_size > (long)max)
 		ra->next_size = max;
-	if (ra->next_size < min)
-		ra->next_size = min;
+	if ((long)ra->next_size <= 0L) {
+		ra->next_size = -1UL;
+		ra->size = 0;
+		goto out;		/* Readahead is off */
+	}
 
 	/*
 	 * Is this request outside the current window?
@@ -374,6 +391,7 @@
 			ra->prev_page = ra->start;
 			ra->ahead_start = 0;
 			ra->ahead_size = 0;
+
 			/*
 			 * Control now returns, probably to sleep until I/O
 			 * completes against the first ahead page.
@@ -394,7 +412,6 @@
 		ra->size = ra->next_size;
 		ra->ahead_start = 0;		/* Invalidate these */
 		ra->ahead_size = 0;
-
 		actual = do_page_cache_readahead(mapping, filp, offset,
 						 ra->size);
 		check_ra_success(ra, ra->size, actual, orig_next_size);
@@ -455,21 +472,37 @@
  * not found.  This will happen if it was evicted by the VM (readahead
  * thrashing) or if the readahead window is maximally shrunk.
  *
- * If the window has been maximally shrunk (next_size == 0) then bump it up
- * again to resume readahead.
+ * If the window has been maximally shrunk (next_size == -1UL) then look to see
+ * if we are getting misses against sequential file offsets.  If so, and this
+ * persists then resume readahead.
  *
  * Otherwise we're thrashing, so shrink the readahead window by three pages.
  * This is because it is grown by two pages on a readahead hit.  Theory being
  * that the readahead window size will stabilise around the maximum level at
  * which there is no thrashing.
  */
-void handle_ra_miss(struct address_space *mapping, struct file_ra_state *ra)
+void handle_ra_miss(struct address_space *mapping,
+		struct file_ra_state *ra, pgoff_t offset)
 {
-	const unsigned long min = get_min_readahead(ra);
-
 	if (ra->next_size == -1UL) {
-		ra->next_size = min;
+		const unsigned long max = get_max_readahead(ra);
+
+		if (offset != ra->prev_page + 1) {
+			ra->size = 0;			/* Not sequential */
+		} else {
+			ra->size++;			/* A sequential read */
+			if (ra->size >= max) {		/* Resume readahead */
+				ra->start = offset - max;
+				ra->next_size = max;
+				ra->size = max;
+				ra->ahead_start = 0;
+				ra->ahead_size = 0;
+			}
+		}
+		ra->prev_page = offset;
 	} else {
+		const unsigned long min = get_min_readahead(ra);
+
 		ra->next_size -= 3;
 		if (ra->next_size < min)
 			ra->next_size = min;
diff -Nru a/mm/slab.c b/mm/slab.c
--- a/mm/slab.c	Sun Mar  2 18:13:32 2003
+++ b/mm/slab.c	Sat Mar  8 14:50:36 2003
@@ -82,6 +82,7 @@
 #include	<linux/compiler.h>
 #include	<linux/seq_file.h>
 #include	<linux/notifier.h>
+#include	<linux/kallsyms.h>
 #include	<asm/uaccess.h>
 
 /*
@@ -114,7 +115,7 @@
 # define CREATE_MASK	(SLAB_DEBUG_INITIAL | SLAB_RED_ZONE | \
 			 SLAB_POISON | SLAB_HWCACHE_ALIGN | \
 			 SLAB_NO_REAP | SLAB_CACHE_DMA | \
-			 SLAB_MUST_HWCACHE_ALIGN)
+			 SLAB_MUST_HWCACHE_ALIGN | SLAB_STORE_USER)
 #else
 # define CREATE_MASK	(SLAB_HWCACHE_ALIGN | SLAB_NO_REAP | \
 			 SLAB_CACHE_DMA | SLAB_MUST_HWCACHE_ALIGN)
@@ -280,9 +281,7 @@
 #endif
 };
 
-/* internal c_flags */
-#define	CFLGS_OFF_SLAB	0x010000UL	/* slab management in own cache */
-
+#define CFLGS_OFF_SLAB		(0x80000000UL)
 #define	OFF_SLAB(x)	((x)->flags & CFLGS_OFF_SLAB)
 
 #define BATCHREFILL_LIMIT	16
@@ -764,10 +763,28 @@
 		addr += BYTES_PER_WORD;
 		size -= 2*BYTES_PER_WORD;
 	}
+	if (cachep->flags & SLAB_STORE_USER) {
+		size -= BYTES_PER_WORD;
+	}
 	memset(addr, val, size);
 	*(unsigned char *)(addr+size-1) = POISON_END;
 }
 
+static void *fprob(unsigned char* addr, unsigned int size)
+{
+	unsigned char *end;
+	
+	end = addr + size - 1;
+
+	for (; addr < end; addr++) {
+		if (*addr != POISON_BEFORE && *addr != POISON_AFTER)
+			return addr;
+	}
+	if (*addr != POISON_END)
+		return addr;
+	return NULL;
+}
+
 static void check_poison_obj(kmem_cache_t *cachep, void *addr)
 {
 	int size = cachep->objsize;
@@ -776,9 +793,47 @@
 		addr += BYTES_PER_WORD;
 		size -= 2*BYTES_PER_WORD;
 	}
-	end = memchr(addr, POISON_END, size);
-	if (end != (addr+size-1))
+	if (cachep->flags & SLAB_STORE_USER) {
+		size -= BYTES_PER_WORD;
+	}
+	end = fprob(addr, size);
+	if (end) {
+		int s;
+		printk(KERN_ERR "Slab corruption: start=%p, expend=%p, "
+				"problemat=%p\n", addr, addr+size-1, end);
+		if (cachep->flags & SLAB_STORE_USER) {
+			void *pc;
+
+			if (cachep->flags & SLAB_RED_ZONE)
+				pc = *(void**)(addr+size+BYTES_PER_WORD);
+			else
+				pc = *(void**)(addr+size);
+			printk(KERN_ERR "Last user: [<%p>]", pc);
+			print_symbol("(%s)", (unsigned long)pc);
+			printk("\n");
+		}
+		printk(KERN_ERR "Data: ");
+		for (s = 0; s < size; s++) {
+			if (((char*)addr)[s] == POISON_BEFORE)
+				printk(".");
+			else if (((char*)addr)[s] == POISON_AFTER)
+				printk("*");
+			else
+				printk("%02X ", ((unsigned char*)addr)[s]);
+		}
+		printk("\n");
+		printk(KERN_ERR "Next: ");
+		for (; s < size + 32; s++) {
+			if (((char*)addr)[s] == POISON_BEFORE)
+				printk(".");
+			else if (((char*)addr)[s] == POISON_AFTER)
+				printk("*");
+			else
+				printk("%02X ", ((unsigned char*)addr)[s]);
+		}
+		printk("\n");
 		slab_error(cachep, "object was modified after freeing");
+	}
 }
 #endif
 
@@ -792,16 +847,19 @@
 	int i;
 	for (i = 0; i < cachep->num; i++) {
 		void *objp = slabp->s_mem + cachep->objsize * i;
+		int objlen = cachep->objsize;
 
 		if (cachep->flags & SLAB_POISON)
 			check_poison_obj(cachep, objp);
+		if (cachep->flags & SLAB_STORE_USER)
+			objlen -= BYTES_PER_WORD;
 
 		if (cachep->flags & SLAB_RED_ZONE) {
 			if (*((unsigned long*)(objp)) != RED_INACTIVE)
 				slab_error(cachep, "start of a freed object "
 							"was overwritten");
-			if (*((unsigned long*)(objp + cachep->objsize -
-					BYTES_PER_WORD)) != RED_INACTIVE)
+			if (*((unsigned long*)(objp + objlen - BYTES_PER_WORD))
+				       	!= RED_INACTIVE)
 				slab_error(cachep, "end of a freed object "
 							"was overwritten");
 			objp += BYTES_PER_WORD;
@@ -890,7 +948,7 @@
 		 * do not red zone large object, causes severe
 		 * fragmentation.
 		 */
-		flags |= SLAB_RED_ZONE;
+		flags |= SLAB_RED_ZONE|SLAB_STORE_USER;
 	flags |= SLAB_POISON;
 #endif
 #endif
@@ -927,6 +985,10 @@
 		flags &= ~SLAB_HWCACHE_ALIGN;
 		size += 2*BYTES_PER_WORD;	/* words for redzone */
 	}
+	if (flags & SLAB_STORE_USER) {
+		flags &= ~SLAB_HWCACHE_ALIGN;
+		size += BYTES_PER_WORD;		/* word for kfree caller address */
+	}
 #endif
 	align = BYTES_PER_WORD;
 	if (flags & SLAB_HWCACHE_ALIGN)
@@ -1283,15 +1345,20 @@
 	for (i = 0; i < cachep->num; i++) {
 		void* objp = slabp->s_mem+cachep->objsize*i;
 #if DEBUG
+		int objlen = cachep->objsize;
 		/* need to poison the objs? */
 		if (cachep->flags & SLAB_POISON)
 			poison_obj(cachep, objp, POISON_BEFORE);
+		if (cachep->flags & SLAB_STORE_USER) {
+			objlen -= BYTES_PER_WORD;
+			((unsigned long*)(objp+objlen))[0] = 0;
+		}
 
 		if (cachep->flags & SLAB_RED_ZONE) {
 			*((unsigned long*)(objp)) = RED_INACTIVE;
-			*((unsigned long*)(objp + cachep->objsize -
-					BYTES_PER_WORD)) = RED_INACTIVE;
 			objp += BYTES_PER_WORD;
+			objlen -= 2* BYTES_PER_WORD;
+			*((unsigned long*)(objp + objlen)) = RED_INACTIVE;
 		}
 		/*
 		 * Constructors are not allowed to allocate memory from
@@ -1302,14 +1369,13 @@
 			cachep->ctor(objp, cachep, ctor_flags);
 
 		if (cachep->flags & SLAB_RED_ZONE) {
+			if (*((unsigned long*)(objp + objlen)) != RED_INACTIVE)
+				slab_error(cachep, "constructor overwrote the"
+							" end of an object");
 			objp -= BYTES_PER_WORD;
 			if (*((unsigned long*)(objp)) != RED_INACTIVE)
 				slab_error(cachep, "constructor overwrote the"
 							" start of an object");
-			if (*((unsigned long*)(objp + cachep->objsize -
-					BYTES_PER_WORD)) != RED_INACTIVE)
-				slab_error(cachep, "constructor overwrote the"
-							" end of an object");
 		}
 #else
 		if (cachep->ctor)
@@ -1451,11 +1517,12 @@
 #endif 
 }
 
-static inline void *cache_free_debugcheck (kmem_cache_t * cachep, void * objp)
+static inline void *cache_free_debugcheck (kmem_cache_t * cachep, void * objp, void *caller)
 {
 #if DEBUG
 	struct page *page;
 	unsigned int objnr;
+	int objlen = cachep->objsize;
 	struct slab *slabp;
 
 	kfree_debugcheck(objp);
@@ -1464,16 +1531,21 @@
 	BUG_ON(GET_PAGE_CACHE(page) != cachep);
 	slabp = GET_PAGE_SLAB(page);
 
+	if (cachep->flags & SLAB_STORE_USER) {
+		objlen -= BYTES_PER_WORD;
+	}
 	if (cachep->flags & SLAB_RED_ZONE) {
 		objp -= BYTES_PER_WORD;
 		if (xchg((unsigned long *)objp, RED_INACTIVE) != RED_ACTIVE)
 			slab_error(cachep, "double free, or memory before"
 						" object was overwritten");
-		if (xchg((unsigned long *)(objp+cachep->objsize -
-				BYTES_PER_WORD), RED_INACTIVE) != RED_ACTIVE)
+		if (xchg((unsigned long *)(objp+objlen-BYTES_PER_WORD), RED_INACTIVE) != RED_ACTIVE)
 			slab_error(cachep, "double free, or memory after "
 						" object was overwritten");
 	}
+	if (cachep->flags & SLAB_STORE_USER) {
+		*((void**)(objp+objlen)) = caller;
+	}
 
 	objnr = (objp-slabp->s_mem)/cachep->objsize;
 
@@ -1626,22 +1698,31 @@
 
 static inline void *
 cache_alloc_debugcheck_after(kmem_cache_t *cachep,
-			unsigned long flags, void *objp)
+			unsigned long flags, void *objp, void *caller)
 {
 #if DEBUG
+	int objlen = cachep->objsize;
+
 	if (!objp)	
 		return objp;
 	if (cachep->flags & SLAB_POISON)
 		check_poison_obj(cachep, objp);
+	if (cachep->flags & SLAB_STORE_USER) {
+		objlen -= BYTES_PER_WORD;
+		*((void **)(objp+objlen)) = caller;
+	}
+
 	if (cachep->flags & SLAB_RED_ZONE) {
 		/* Set alloc red-zone, and check old one. */
-		if (xchg((unsigned long *)objp, RED_ACTIVE) != RED_INACTIVE)
+		if (xchg((unsigned long *)objp, RED_ACTIVE) != RED_INACTIVE) {
 			slab_error(cachep, "memory before object was "
 						"overwritten");
-		if (xchg((unsigned long *)(objp+cachep->objsize -
-			  BYTES_PER_WORD), RED_ACTIVE) != RED_INACTIVE)
+		}
+		if (xchg((unsigned long *)(objp+objlen - BYTES_PER_WORD),
+				       	RED_ACTIVE) != RED_INACTIVE) {
 			slab_error(cachep, "memory after object was "
 						"overwritten");
+		}
 		objp += BYTES_PER_WORD;
 	}
 	if (cachep->ctor && cachep->flags & SLAB_POISON) {
@@ -1676,7 +1757,7 @@
 		objp = cache_alloc_refill(cachep, flags);
 	}
 	local_irq_restore(save_flags);
-	objp = cache_alloc_debugcheck_after(cachep, flags, objp);
+	objp = cache_alloc_debugcheck_after(cachep, flags, objp, __builtin_return_address(0));
 	return objp;
 }
 
@@ -1783,7 +1864,7 @@
 	struct array_cache *ac = ac_data(cachep);
 
 	check_irq_off();
-	objp = cache_free_debugcheck(cachep, objp);
+	objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
 
 	if (likely(ac->avail < ac->limit)) {
 		STATS_INC_FREEHIT(cachep);
diff -Nru a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
--- a/net/8021q/vlanproc.c	Sat Aug  3 17:18:02 2002
+++ b/net/8021q/vlanproc.c	Sun Mar  9 14:00:21 2003
@@ -251,8 +251,10 @@
 	offs = file->f_pos;
 	if (offs < pos) {
 		len = min_t(int, pos - offs, count);
-		if (copy_to_user(buf, (page + offs), len))
+		if (copy_to_user(buf, (page + offs), len)) {
+			kfree(page);
 			return -EFAULT;
+		}
 
 		file->f_pos += len;
 	} else {
diff -Nru a/net/Makefile b/net/Makefile
--- a/net/Makefile	Mon Feb  3 14:19:38 2003
+++ b/net/Makefile	Thu Mar  6 11:06:44 2003
@@ -7,6 +7,8 @@
 
 obj-y	:= socket.o core/
 
+obj-$(CONFIG_COMPAT)		+= compat.o
+
 # LLC has to be linked before the files in net/802/
 obj-$(CONFIG_LLC)		+= llc/
 obj-$(CONFIG_NET)		+= ethernet/ 802/ sched/ netlink/
diff -Nru a/net/appletalk/ddp.c b/net/appletalk/ddp.c
--- a/net/appletalk/ddp.c	Fri Oct 11 19:45:27 2002
+++ b/net/appletalk/ddp.c	Thu Mar  6 11:06:44 2003
@@ -190,7 +190,7 @@
 	struct sock *sk = (struct sock *)data;
 
 	if (!atomic_read(&sk->wmem_alloc) &&
-	    !atomic_read(&sk->rmem_alloc) && sk->dead) {
+	    !atomic_read(&sk->rmem_alloc) && test_bit(SOCK_DEAD, &sk->flags)) {
 		sock_put(sk);
 		MOD_DEC_USE_COUNT;
 	} else {
@@ -205,7 +205,7 @@
 	skb_queue_purge(&sk->receive_queue);
 
 	if (!atomic_read(&sk->wmem_alloc) &&
-	    !atomic_read(&sk->rmem_alloc) && sk->dead) {
+	    !atomic_read(&sk->rmem_alloc) && test_bit(SOCK_DEAD, &sk->flags)) {
 		sock_put(sk);
 		MOD_DEC_USE_COUNT;
 	} else {
@@ -1016,9 +1016,9 @@
 	struct sock *sk = sock->sk;
 
 	if (sk) {
-		if (!sk->dead)
+		if (!test_bit(SOCK_DEAD, &sk->flags))
 			sk->state_change(sk);
-		sk->dead = 1;
+		__set_bit(SOCK_DEAD, &sk->flags);
 		sock->sk = NULL;
 		atalk_destroy_socket(sk);
 	}
@@ -1158,7 +1158,8 @@
 	if (addr->sat_family != AF_APPLETALK)
 		return -EAFNOSUPPORT;
 
-	if (addr->sat_addr.s_node == ATADDR_BCAST && !sk->broadcast) {
+	if (addr->sat_addr.s_node == ATADDR_BCAST &&
+			!test_bit(SOCK_BROADCAST, &sk->flags)) {
 #if 1	
 		printk(KERN_WARNING "%s is broken and did not set "
 				    "SO_BROADCAST. It will break when 2.2 is "
@@ -1492,7 +1493,7 @@
 }
 
 static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
-			 int len, struct scm_cookie *scm)
+			 int len)
 {
 	struct sock *sk = sock->sk;
 	struct atalk_sock *at = at_sk(sk);
@@ -1523,7 +1524,8 @@
 			return -EINVAL;
 
 		/* netatalk doesn't implement this check */
-		if (usat->sat_addr.s_node == ATADDR_BCAST && !sk->broadcast) {
+		if (usat->sat_addr.s_node == ATADDR_BCAST &&
+				!test_bit(SOCK_BROADCAST, &sk->flags)) {
 			printk(KERN_INFO "SO_BROADCAST: Fix your netatalk as "
 					 "it will break before 2.2\n");
 #if 0
@@ -1651,7 +1653,7 @@
 }
 
 static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
-			 int size, int flags, struct scm_cookie *scm)
+			 int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name;
diff -Nru a/net/atm/atm_misc.c b/net/atm/atm_misc.c
--- a/net/atm/atm_misc.c	Tue Feb  5 09:40:00 2002
+++ b/net/atm/atm_misc.c	Sat Mar  8 13:09:15 2003
@@ -16,7 +16,7 @@
 int atm_charge(struct atm_vcc *vcc,int truesize)
 {
 	atm_force_charge(vcc,truesize);
-	if (atomic_read(&vcc->rx_inuse) <= vcc->sk->rcvbuf) return 1;
+	if (atomic_read(&vcc->sk->rmem_alloc) <= vcc->sk->rcvbuf) return 1;
 	atm_return(vcc,truesize);
 	atomic_inc(&vcc->stats->rx_drop);
 	return 0;
@@ -29,11 +29,11 @@
 	int guess = atm_guess_pdu2truesize(pdu_size);
 
 	atm_force_charge(vcc,guess);
-	if (atomic_read(&vcc->rx_inuse) <= vcc->sk->rcvbuf) {
+	if (atomic_read(&vcc->sk->rmem_alloc) <= vcc->sk->rcvbuf) {
 		struct sk_buff *skb = alloc_skb(pdu_size,gfp_flags);
 
 		if (skb) {
-			atomic_add(skb->truesize-guess,&vcc->rx_inuse);
+			atomic_add(skb->truesize-guess,&vcc->sk->rmem_alloc);
 			return skb;
 		}
 	}
diff -Nru a/net/atm/clip.c b/net/atm/clip.c
--- a/net/atm/clip.c	Fri Oct 11 16:07:30 2002
+++ b/net/atm/clip.c	Sat Mar  8 13:09:15 2003
@@ -63,7 +63,7 @@
 	ctrl->itf_num = itf;
 	ctrl->ip = ip;
 	atm_force_charge(atmarpd,skb->truesize);
-	skb_queue_tail(&atmarpd->recvq,skb);
+	skb_queue_tail(&atmarpd->sk->receive_queue,skb);
 	wake_up(&atmarpd->sleep);
 	return 0;
 }
@@ -426,7 +426,7 @@
 		memcpy(here,llc_oui,sizeof(llc_oui));
 		((u16 *) here)[3] = skb->protocol;
 	}
-	atomic_add(skb->truesize,&vcc->tx_inuse);
+	atomic_add(skb->truesize,&vcc->sk->wmem_alloc);
 	ATM_SKB(skb)->iovcnt = 0;
 	ATM_SKB(skb)->atm_options = vcc->atm_options;
 	entry->vccs->last_use = jiffies;
@@ -485,7 +485,7 @@
 	vcc->push = clip_push;
 	vcc->pop = clip_pop;
 	skb_queue_head_init(&copy);
-	skb_migrate(&vcc->recvq,&copy);
+	skb_migrate(&vcc->sk->receive_queue,&copy);
 	/* re-process everything received between connection setup and MKIP */
 	while ((skb = skb_dequeue(&copy)))
 		if (!clip_devs) {
@@ -691,10 +691,10 @@
 	barrier();
 	unregister_inetaddr_notifier(&clip_inet_notifier);
 	unregister_netdevice_notifier(&clip_dev_notifier);
-	if (skb_peek(&vcc->recvq))
+	if (skb_peek(&vcc->sk->receive_queue))
 		printk(KERN_ERR "atmarpd_close: closing with requests "
 		    "pending\n");
-	skb_queue_purge(&vcc->recvq);
+	skb_queue_purge(&vcc->sk->receive_queue);
 	DPRINTK("(done)\n");
 }
 
diff -Nru a/net/atm/common.c b/net/atm/common.c
--- a/net/atm/common.c	Wed Feb 19 23:22:24 2003
+++ b/net/atm/common.c	Sat Mar  8 13:09:15 2003
@@ -85,14 +85,14 @@
 {
 	struct sk_buff *skb;
 
-	if (atomic_read(&vcc->tx_inuse) && !atm_may_send(vcc,size)) {
-		DPRINTK("Sorry: tx_inuse = %d, size = %d, sndbuf = %d\n",
-		    atomic_read(&vcc->tx_inuse),size,vcc->sk->sndbuf);
+	if (atomic_read(&vcc->sk->wmem_alloc) && !atm_may_send(vcc,size)) {
+		DPRINTK("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n",
+		    atomic_read(&vcc->sk->wmem_alloc),size,vcc->sk->sndbuf);
 		return NULL;
 	}
 	while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule();
-	DPRINTK("AlTx %d += %d\n",atomic_read(&vcc->tx_inuse),skb->truesize);
-	atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
+	DPRINTK("AlTx %d += %d\n",atomic_read(&vcc->sk->wmem_alloc),skb->truesize);
+	atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->sk->wmem_alloc);
 	return skb;
 }
 
@@ -108,21 +108,19 @@
 	vcc = atm_sk(sk);
 	memset(&vcc->flags,0,sizeof(vcc->flags));
 	vcc->dev = NULL;
-	vcc->family = sock->ops->family;
 	vcc->alloc_tx = alloc_tx;
 	vcc->callback = NULL;
 	memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc));
 	memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc));
 	vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
-	atomic_set(&vcc->tx_inuse,0);
-	atomic_set(&vcc->rx_inuse,0);
+	atomic_set(&vcc->sk->wmem_alloc,0);
+	atomic_set(&vcc->sk->rmem_alloc,0);
 	vcc->push = NULL;
 	vcc->pop = NULL;
 	vcc->push_oam = NULL;
 	vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
 	vcc->atm_options = vcc->aal_options = 0;
 	init_waitqueue_head(&vcc->sleep);
-	skb_queue_head_init(&vcc->recvq);
 	skb_queue_head_init(&vcc->listenq);
 	sk->sleep = &vcc->sleep;
 	sock->sk = sk;
@@ -139,7 +137,7 @@
 	if (vcc->dev) {
 		if (vcc->dev->ops->close) vcc->dev->ops->close(vcc);
 		if (vcc->push) vcc->push(vcc,NULL); /* atmarpd has no push */
-		while ((skb = skb_dequeue(&vcc->recvq))) {
+		while ((skb = skb_dequeue(&vcc->sk->receive_queue))) {
 			atm_return(vcc,skb->truesize);
 			if (vcc->dev->ops->free_rx_skb)
 				vcc->dev->ops->free_rx_skb(vcc,skb);
@@ -147,10 +145,10 @@
 		}
 		spin_lock (&atm_dev_lock);	
 		fops_put (vcc->dev->ops);
-		if (atomic_read(&vcc->rx_inuse))
+		if (atomic_read(&vcc->sk->rmem_alloc))
 			printk(KERN_WARNING "atm_release_vcc: strange ... "
-			    "rx_inuse == %d after closing\n",
-			    atomic_read(&vcc->rx_inuse));
+			    "rmem_alloc == %d after closing\n",
+			    atomic_read(&vcc->sk->rmem_alloc));
 		bind_vcc(vcc,NULL);
 	} else
 		spin_lock (&atm_dev_lock);	
@@ -305,11 +303,15 @@
 		if (error) return error;
 	}
 	else {
-		struct atm_dev *dev;
+		struct atm_dev *dev = NULL;
+		struct list_head *p;
 
 		spin_lock (&atm_dev_lock);
-		for (dev = atm_devs; dev; dev = dev->next)
+		list_for_each(p, &atm_devs) {
+			dev = list_entry(p, struct atm_dev, dev_list);
 			if (!atm_do_connect_dev(vcc,dev,vpi,vci)) break;
+			dev = NULL;
+		}
 		spin_unlock (&atm_dev_lock);
 		if (!dev) return -ENODEV;
 	}
@@ -336,7 +338,7 @@
 
 
 int atm_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-		int total_len, int flags, struct scm_cookie *scm)
+		int total_len, int flags)
 {
 	DECLARE_WAITQUEUE(wait,current);
 	struct atm_vcc *vcc;
@@ -354,7 +356,7 @@
 	add_wait_queue(&vcc->sleep,&wait);
 	set_current_state(TASK_INTERRUPTIBLE);
 	error = 1; /* <= 0 is error */
-	while (!(skb = skb_dequeue(&vcc->recvq))) {
+	while (!(skb = skb_dequeue(&vcc->sk->receive_queue))) {
 		if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
 		    test_bit(ATM_VF_CLOSE,&vcc->flags)) {
 			error = vcc->reply;
@@ -385,7 +387,7 @@
 	if (vcc->dev->ops->feedback)
 		vcc->dev->ops->feedback(vcc,skb,(unsigned long) skb->data,
 		    (unsigned long) buff,eff_len);
-	DPRINTK("RcvM %d -= %d\n",atomic_read(&vcc->rx_inuse),skb->truesize);
+	DPRINTK("RcvM %d -= %d\n",atomic_read(&vcc->sk->rmem_alloc),skb->truesize);
 	atm_return(vcc,skb->truesize);
 	if (ATM_SKB(skb)->iovcnt) { /* @@@ hack */
 		/* iovcnt set, use scatter-gather for receive */
@@ -417,7 +419,7 @@
 
 
 int atm_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-		int total_len, struct scm_cookie *scm)
+		int total_len)
 {
 	DECLARE_WAITQUEUE(wait,current);
 	struct atm_vcc *vcc;
@@ -488,14 +490,14 @@
 	vcc = ATM_SD(sock);
 	poll_wait(file,&vcc->sleep,wait);
 	mask = 0;
-	if (skb_peek(&vcc->recvq) || skb_peek(&vcc->listenq))
+	if (skb_peek(&vcc->sk->receive_queue) || skb_peek(&vcc->listenq))
 		mask |= POLLIN | POLLRDNORM;
 	if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
 	    test_bit(ATM_VF_CLOSE,&vcc->flags))
 		mask |= POLLHUP;
 	if (sock->state != SS_CONNECTING) {
 		if (vcc->qos.txtp.traffic_class != ATM_NONE &&
-		    vcc->qos.txtp.max_sdu+atomic_read(&vcc->tx_inuse)+
+		    vcc->qos.txtp.max_sdu+atomic_read(&vcc->sk->wmem_alloc)+
 		    ATM_PDU_OVHD <= vcc->sk->sndbuf)
 			mask |= POLLOUT | POLLWRNORM;
 	}
@@ -546,6 +548,7 @@
 int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
 {
 	struct atm_dev *dev;
+	struct list_head *p;
 	struct atm_vcc *vcc;
 	int *tmp_buf, *tmp_p;
 	void *buf;
@@ -562,7 +565,7 @@
 				goto done;
 			}
 			ret_val =  put_user(vcc->sk->sndbuf-
-			    atomic_read(&vcc->tx_inuse)-ATM_PDU_OVHD,
+			    atomic_read(&vcc->sk->wmem_alloc)-ATM_PDU_OVHD,
 			    (int *) arg) ? -EFAULT : 0;
 			goto done;
 		case SIOCINQ:
@@ -573,7 +576,7 @@
 					ret_val = -EINVAL;
 					goto done;
 				}
-				skb = skb_peek(&vcc->recvq);
+				skb = skb_peek(&vcc->sk->receive_queue);
 				ret_val = put_user(skb ? skb->len : 0,(int *) arg)
 				    ? -EFAULT : 0;
 				goto done;
@@ -590,7 +593,7 @@
 				goto done;
 			}
 			size = 0;
-			for (dev = atm_devs; dev; dev = dev->next)
+			list_for_each(p, &atm_devs)
 				size += sizeof(int);
 			if (size > len) {
 				ret_val = -E2BIG;
@@ -602,8 +605,10 @@
 				goto done;
 			}
 			tmp_p = tmp_buf;
-			for (dev = atm_devs; dev; dev = dev->next)
+			list_for_each(p, &atm_devs) {
+				dev = list_entry(p, struct atm_dev, dev_list);
 				*tmp_p++ = dev->number;
+			}
 		        ret_val = ((copy_to_user(buf, tmp_buf, size)) ||
 			    put_user(size, &((struct atm_iobuf *) arg)->length)
 			    ) ? -EFAULT : 0;
@@ -963,7 +968,7 @@
 	if (!error) error = adjust_tp(&qos->rxtp,qos->aal);
 	if (error) return error;
 	if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP;
-	if (vcc->family == AF_ATMPVC)
+	if (vcc->sk->family == AF_ATMPVC)
 		return vcc->dev->ops->change_qos(vcc,qos,ATM_MF_SET);
 	return svc_change_qos(vcc,qos);
 }
diff -Nru a/net/atm/common.h b/net/atm/common.h
--- a/net/atm/common.h	Tue Oct  8 07:02:41 2002
+++ b/net/atm/common.h	Thu Mar  6 11:06:44 2003
@@ -14,9 +14,9 @@
 int atm_release(struct socket *sock);
 int atm_connect(struct socket *sock,int itf,short vpi,int vci);
 int atm_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-		int total_len, int flags, struct scm_cookie *scm);
+		int total_len, int flags);
 int atm_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-		int total_len, struct scm_cookie *scm);
+		int total_len);
 unsigned int atm_poll(struct file *file,struct socket *sock,poll_table *wait);
 int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg);
 int atm_setsockopt(struct socket *sock,int level,int optname,char *optval,
diff -Nru a/net/atm/lec.c b/net/atm/lec.c
--- a/net/atm/lec.c	Mon Mar  3 01:16:42 2003
+++ b/net/atm/lec.c	Sat Mar  8 13:09:15 2003
@@ -125,7 +125,7 @@
 
                 priv = (struct lec_priv *)dev->priv;
                 atm_force_charge(priv->lecd, skb2->truesize);
-                skb_queue_tail(&priv->lecd->recvq, skb2);
+                skb_queue_tail(&priv->lecd->sk->receive_queue, skb2);
                 wake_up(&priv->lecd->sleep);
         }
 
@@ -202,7 +202,7 @@
 lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv)
 {
 	if (atm_may_send(vcc, skb->len)) {
-		atomic_add(skb->truesize, &vcc->tx_inuse);
+		atomic_add(skb->truesize, &vcc->sk->wmem_alloc);
 	        ATM_SKB(skb)->vcc = vcc;
 	        ATM_SKB(skb)->iovcnt = 0;
 	        ATM_SKB(skb)->atm_options = vcc->atm_options;
@@ -399,7 +399,7 @@
         int i;
         char *tmp; /* FIXME */
 
-	atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse);
+	atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->sk->wmem_alloc);
         mesg = (struct atmlec_msg *)skb->data;
         tmp = skb->data;
         tmp += sizeof(struct atmlec_msg);
@@ -505,7 +505,7 @@
                         skb2->len = sizeof(struct atmlec_msg);
                         memcpy(skb2->data, mesg, sizeof(struct atmlec_msg));
                         atm_force_charge(priv->lecd, skb2->truesize);
-                        skb_queue_tail(&priv->lecd->recvq, skb2);
+                        skb_queue_tail(&priv->lecd->sk->receive_queue, skb2);
                         wake_up(&priv->lecd->sleep);
                 }
                 if (f != NULL) br_fdb_put_hook(f);
@@ -534,10 +534,10 @@
         netif_stop_queue(dev);
         lec_arp_destroy(priv);
 
-        if (skb_peek(&vcc->recvq))
+        if (skb_peek(&vcc->sk->receive_queue))
 		printk("%s lec_atm_close: closing with messages pending\n",
                        dev->name);
-        while ((skb = skb_dequeue(&vcc->recvq))) {
+        while ((skb = skb_dequeue(&vcc->sk->receive_queue))) {
                 atm_return(vcc, skb->truesize);
 		dev_kfree_skb(skb);
         }
@@ -595,13 +595,13 @@
 		memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);
 
         atm_force_charge(priv->lecd, skb->truesize);
-	skb_queue_tail(&priv->lecd->recvq, skb);
+	skb_queue_tail(&priv->lecd->sk->receive_queue, skb);
         wake_up(&priv->lecd->sleep);
 
         if (data != NULL) {
                 DPRINTK("lec: about to send %d bytes of data\n", data->len);
                 atm_force_charge(priv->lecd, data->truesize);
-                skb_queue_tail(&priv->lecd->recvq, data);
+                skb_queue_tail(&priv->lecd->sk->receive_queue, data);
                 wake_up(&priv->lecd->sleep);
         }
 
@@ -683,7 +683,7 @@
 #endif /* DUMP_PACKETS > 0 */
         if (memcmp(skb->data, lec_ctrl_magic, 4) ==0) { /* Control frame, to daemon*/
                 DPRINTK("%s: To daemon\n",dev->name);
-                skb_queue_tail(&vcc->recvq, skb);
+                skb_queue_tail(&vcc->sk->receive_queue, skb);
                 wake_up(&vcc->sleep);
         } else { /* Data frame, queue to protocol handlers */
                 unsigned char *dst;
@@ -784,16 +784,20 @@
                 size = sizeof(struct lec_priv);
 #ifdef CONFIG_TR
                 if (is_trdev)
-                        dev_lec[i] = init_trdev(NULL, size);
+                        dev_lec[i] = alloc_trdev(size);
                 else
 #endif
-                dev_lec[i] = init_etherdev(NULL, size);
+                dev_lec[i] = alloc_etherdev(size);
                 if (!dev_lec[i])
                         return -ENOMEM;
+                snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
+                if (register_netdev(dev_lec[i])) {
+                        kfree(dev_lec[i]);
+                        return -EINVAL;
+                }
 
                 priv = dev_lec[i]->priv;
                 priv->is_trdev = is_trdev;
-                sprintf(dev_lec[i]->name, "lec%d", i);
                 lec_init(dev_lec[i]);
         } else {
                 priv = dev_lec[i]->priv;
diff -Nru a/net/atm/mpc.c b/net/atm/mpc.c
--- a/net/atm/mpc.c	Thu Jan 16 11:15:45 2003
+++ b/net/atm/mpc.c	Sat Mar  8 13:09:15 2003
@@ -520,7 +520,7 @@
 		memcpy(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr));
 	}
 
-	atomic_add(skb->truesize, &entry->shortcut->tx_inuse);
+	atomic_add(skb->truesize, &entry->shortcut->sk->wmem_alloc);
 	ATM_SKB(skb)->iovcnt = 0; /* just to be safe ... */
 	ATM_SKB(skb)->atm_options = entry->shortcut->atm_options;
 	entry->shortcut->send(entry->shortcut, skb);
@@ -665,7 +665,7 @@
 	skb->dev = dev;
 	if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) {
 		dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name);
-		skb_queue_tail(&vcc->recvq, skb);           /* Pass control packets to daemon */
+		skb_queue_tail(&vcc->sk->receive_queue, skb);           /* Pass control packets to daemon */
 		wake_up(&vcc->sleep);
 		return;
 	}
@@ -841,7 +841,7 @@
 	mpc->in_ops->destroy_cache(mpc);
 	mpc->eg_ops->destroy_cache(mpc);
 
-	while ( (skb = skb_dequeue(&vcc->recvq)) ){
+	while ( (skb = skb_dequeue(&vcc->sk->receive_queue)) ){
 		atm_return(vcc, skb->truesize);
 		kfree_skb(skb);
 	}
@@ -861,7 +861,7 @@
 	
 	struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
 	struct k_message *mesg = (struct k_message*)skb->data;
-	atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse);
+	atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->sk->wmem_alloc);
 	
 	if (mpc == NULL) {
 		printk("mpoa: msg_from_mpoad: no mpc found\n");
@@ -938,7 +938,7 @@
 	skb_put(skb, sizeof(struct k_message));
 	memcpy(skb->data, mesg, sizeof(struct k_message));
 	atm_force_charge(mpc->mpoad_vcc, skb->truesize);
-	skb_queue_tail(&mpc->mpoad_vcc->recvq, skb);
+	skb_queue_tail(&mpc->mpoad_vcc->sk->receive_queue, skb);
 	wake_up(&mpc->mpoad_vcc->sleep);
 
 	return 0;
@@ -1215,7 +1215,7 @@
 		purge_msg->content.eg_info = entry->ctrl_info;
 
 	atm_force_charge(vcc, skb->truesize);
-	skb_queue_tail(&vcc->recvq, skb);
+	skb_queue_tail(&vcc->sk->receive_queue, skb);
 	wake_up(&vcc->sleep);
 	dprintk("mpoa: purge_egress_shortcut: exiting:\n");
 
diff -Nru a/net/atm/proc.c b/net/atm/proc.c
--- a/net/atm/proc.c	Thu Nov 21 10:05:26 2002
+++ b/net/atm/proc.c	Sat Mar  8 13:09:15 2003
@@ -135,7 +135,7 @@
 	unsigned char *ip;
 	int svc,off,ip_len;
 
-	svc = !clip_vcc || clip_vcc->vcc->family == AF_ATMSVC;
+	svc = !clip_vcc || clip_vcc->vcc->sk->family == AF_ATMSVC;
 	off = sprintf(buf,"%-6s%-4s%-4s%5ld ",dev->name,svc ? "SVC" : "PVC",
 	    !clip_vcc || clip_vcc->encap ? "LLC" : "NULL",
 	    (jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh->used))/
@@ -210,7 +210,7 @@
 	if (!vcc->dev) here += sprintf(here,"Unassigned    ");
 	else here += sprintf(here,"%3d %3d %5d ",vcc->dev->number,vcc->vpi,
 		    vcc->vci);
-	switch (vcc->family) {
+	switch (vcc->sk->family) {
 		case AF_ATMPVC:
 			here += sprintf(here,"PVC");
 			break;
@@ -218,12 +218,12 @@
 			here += sprintf(here,"SVC");
 			break;
 		default:
-			here += sprintf(here,"%3d",vcc->family);
+			here += sprintf(here,"%3d",vcc->sk->family);
 	}
 	here += sprintf(here," %04lx  %5d %7d/%7d %7d/%7d\n",vcc->flags,
 	    vcc->reply,
-	    atomic_read(&vcc->tx_inuse),vcc->sk->sndbuf,
-	    atomic_read(&vcc->rx_inuse),vcc->sk->rcvbuf);
+	    atomic_read(&vcc->sk->wmem_alloc),vcc->sk->sndbuf,
+	    atomic_read(&vcc->sk->rmem_alloc),vcc->sk->rcvbuf);
 }
 
 
@@ -303,6 +303,7 @@
 static int atm_devices_info(loff_t pos,char *buf)
 {
 	struct atm_dev *dev;
+	struct list_head *p;
 	int left;
 
 	if (!pos) {
@@ -310,10 +311,14 @@
 		    "AAL(TX,err,RX,err,drop) ...\n");
 	}
 	left = pos-1;
-	for (dev = atm_devs; dev && left; dev = dev->next) left--;
-	if (!dev) return 0;
-	dev_info(dev,buf);
-	return strlen(buf);
+	list_for_each(p, &atm_devs) {
+		dev = list_entry(p, struct atm_dev, dev_list);
+		if (left-- == 0) {
+			dev_info(dev,buf);
+			return strlen(buf);
+		}
+	}
+	return 0;
 }
 
 /*
@@ -324,6 +329,7 @@
 static int atm_pvc_info(loff_t pos,char *buf)
 {
 	struct atm_dev *dev;
+	struct list_head *p;
 	struct atm_vcc *vcc;
 	int left;
 
@@ -332,13 +338,15 @@
 		    "TX(PCR,Class)\n");
 	}
 	left = pos-1;
-	for (dev = atm_devs; dev; dev = dev->next)
+	list_for_each(p, &atm_devs) {
+		dev = list_entry(p, struct atm_dev, dev_list);
 		for (vcc = dev->vccs; vcc; vcc = vcc->next)
-			if (vcc->family == PF_ATMPVC &&
+			if (vcc->sk->family == PF_ATMPVC &&
 			    vcc->dev && !left--) {
 				pvc_info(vcc,buf);
 				return strlen(buf);
 			}
+	}
 	return 0;
 }
 
@@ -346,6 +354,7 @@
 static int atm_vc_info(loff_t pos,char *buf)
 {
 	struct atm_dev *dev;
+	struct list_head *p;
 	struct atm_vcc *vcc;
 	int left;
 
@@ -354,12 +363,14 @@
 		    "Address"," Itf VPI VCI   Fam Flags Reply Send buffer"
 		    "     Recv buffer\n");
 	left = pos-1;
-	for (dev = atm_devs; dev; dev = dev->next)
+	list_for_each(p, &atm_devs) {
+		dev = list_entry(p, struct atm_dev, dev_list);
 		for (vcc = dev->vccs; vcc; vcc = vcc->next)
 			if (!left--) {
 				vc_info(vcc,buf);
 				return strlen(buf);
 			}
+	}
 	for (vcc = nodev_vccs; vcc; vcc = vcc->next)
 		if (!left--) {
 			vc_info(vcc,buf);
@@ -373,20 +384,23 @@
 static int atm_svc_info(loff_t pos,char *buf)
 {
 	struct atm_dev *dev;
+	struct list_head *p;
 	struct atm_vcc *vcc;
 	int left;
 
 	if (!pos)
 		return sprintf(buf,"Itf VPI VCI           State      Remote\n");
 	left = pos-1;
-	for (dev = atm_devs; dev; dev = dev->next)
+	list_for_each(p, &atm_devs) {
+		dev = list_entry(p, struct atm_dev, dev_list);
 		for (vcc = dev->vccs; vcc; vcc = vcc->next)
-			if (vcc->family == PF_ATMSVC && !left--) {
+			if (vcc->sk->family == PF_ATMSVC && !left--) {
 				svc_info(vcc,buf);
 				return strlen(buf);
 			}
+	}
 	for (vcc = nodev_vccs; vcc; vcc = vcc->next)
-		if (vcc->family == PF_ATMSVC && !left--) {
+		if (vcc->sk->family == PF_ATMSVC && !left--) {
 			svc_info(vcc,buf);
 			return strlen(buf);
 		}
diff -Nru a/net/atm/raw.c b/net/atm/raw.c
--- a/net/atm/raw.c	Tue Feb  5 09:40:00 2002
+++ b/net/atm/raw.c	Sat Mar  8 13:09:15 2003
@@ -28,7 +28,7 @@
 void atm_push_raw(struct atm_vcc *vcc,struct sk_buff *skb)
 {
 	if (skb) {
-		skb_queue_tail(&vcc->recvq,skb);
+		skb_queue_tail(&vcc->sk->receive_queue,skb);
 		wake_up(&vcc->sleep);
 	}
 }
@@ -36,8 +36,8 @@
 
 static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb)
 {
-	DPRINTK("APopR (%d) %d -= %d\n",vcc->vci,vcc->tx_inuse,skb->truesize);
-	atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
+	DPRINTK("APopR (%d) %d -= %d\n",vcc->vci,vcc->sk->wmem_alloc,skb->truesize);
+	atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->sk->wmem_alloc);
 	dev_kfree_skb_any(skb);
 	wake_up(&vcc->sleep);
 }
diff -Nru a/net/atm/resources.c b/net/atm/resources.c
--- a/net/atm/resources.c	Sat Jun  8 16:11:04 2002
+++ b/net/atm/resources.c	Sat Mar  8 13:09:15 2003
@@ -26,8 +26,7 @@
 #endif
 
 
-struct atm_dev *atm_devs = NULL;
-static struct atm_dev *last_dev = NULL;
+LIST_HEAD(atm_devs);
 struct atm_vcc *nodev_vccs = NULL;
 extern spinlock_t atm_dev_lock;
 
@@ -43,15 +42,7 @@
 	dev->type = type;
 	dev->signal = ATM_PHY_SIG_UNKNOWN;
 	dev->link_rate = ATM_OC3_PCR;
-	dev->next = NULL;
-
-	dev->prev = last_dev;
-
-	if (atm_devs)
-		last_dev->next = dev;
-	else
-		atm_devs = dev;
-	last_dev = dev;
+	list_add_tail(&dev->dev_list, &atm_devs);
 
 	return dev;
 }
@@ -59,14 +50,7 @@
 /* Caller must hold atm_dev_lock. */
 static void __free_atm_dev(struct atm_dev *dev)
 {
-	if (dev->prev)
-		dev->prev->next = dev->next;
-	else
-		atm_devs = dev->next;
-	if (dev->next)
-		dev->next->prev = dev->prev;
-	else
-		last_dev = dev->prev;
+	list_del(&dev->dev_list);
 	kfree(dev);
 }
 
@@ -74,10 +58,13 @@
 struct atm_dev *atm_find_dev(int number)
 {
 	struct atm_dev *dev;
+	struct list_head *p;
 
-	for (dev = atm_devs; dev; dev = dev->next)
+	list_for_each(p, &atm_devs) {
+		dev = list_entry(p, struct atm_dev, dev_list);
 		if (dev->ops && dev->number == number)
 			return dev;
+	}
 	return NULL;
 }
 
diff -Nru a/net/atm/resources.h b/net/atm/resources.h
--- a/net/atm/resources.h	Tue Feb  5 09:40:00 2002
+++ b/net/atm/resources.h	Sat Mar  8 13:09:15 2003
@@ -10,7 +10,7 @@
 #include <linux/atmdev.h>
 
 
-extern struct atm_dev *atm_devs;
+extern struct list_head atm_devs;
 extern struct atm_vcc *nodev_vccs; /* VCCs not linked to any device */
 
 
diff -Nru a/net/atm/signaling.c b/net/atm/signaling.c
--- a/net/atm/signaling.c	Thu Jul 18 23:16:19 2002
+++ b/net/atm/signaling.c	Sat Mar  8 13:09:15 2003
@@ -61,7 +61,7 @@
 	}
 #endif
 	atm_force_charge(sigd,skb->truesize);
-	skb_queue_tail(&sigd->recvq,skb);
+	skb_queue_tail(&sigd->sk->receive_queue,skb);
 	wake_up(&sigd->sleep);
 }
 
@@ -98,7 +98,7 @@
 	struct atm_vcc *session_vcc;
 
 	msg = (struct atmsvc_msg *) skb->data;
-	atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
+	atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->sk->wmem_alloc);
 	DPRINTK("sigd_send %d (0x%lx)\n",(int) msg->type,
 	  (unsigned long) msg->vcc);
 	vcc = *(struct atm_vcc **) &msg->vcc;
@@ -198,7 +198,7 @@
 static void purge_vccs(struct atm_vcc *vcc)
 {
 	while (vcc) {
-		if (vcc->family == PF_ATMSVC &&
+		if (vcc->sk->family == PF_ATMSVC &&
 		    !test_bit(ATM_VF_META,&vcc->flags)) {
 			set_bit(ATM_VF_RELEASED,&vcc->flags);
 			vcc->reply = -EUNATCH;
@@ -212,16 +212,20 @@
 static void sigd_close(struct atm_vcc *vcc)
 {
 	struct atm_dev *dev;
+	struct list_head *p;
 
 	DPRINTK("sigd_close\n");
 	sigd = NULL;
-	if (skb_peek(&vcc->recvq))
+	if (skb_peek(&vcc->sk->receive_queue))
 		printk(KERN_ERR "sigd_close: closing with requests pending\n");
-	skb_queue_purge(&vcc->recvq);
+	skb_queue_purge(&vcc->sk->receive_queue);
 	purge_vccs(nodev_vccs);
 
 	spin_lock (&atm_dev_lock);
-	for (dev = atm_devs; dev; dev = dev->next) purge_vccs(dev->vccs);
+	list_for_each(p, &atm_devs) {
+		dev = list_entry(p, struct atm_dev, dev_list);
+		purge_vccs(dev->vccs);
+	}
 	spin_unlock (&atm_dev_lock);
 }
 
diff -Nru a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
--- a/net/ax25/af_ax25.c	Sun Dec 29 02:00:21 2002
+++ b/net/ax25/af_ax25.c	Thu Mar  6 11:06:44 2003
@@ -330,7 +330,7 @@
 				ax25_cb *sax25 = ax25_sk(skb->sk);
 
 				/* Queue the unaccepted socket for death */
-				skb->sk->dead = 1;
+				__set_bit(SOCK_DEAD, &skb->sk->flags);
 
 				ax25_start_heartbeat(sax25);
 				sax25->state = AX25_STATE_0;
@@ -984,8 +984,8 @@
 			sk->state                = TCP_CLOSE;
 			sk->shutdown            |= SEND_SHUTDOWN;
 			sk->state_change(sk);
-			sk->dead                 = 1;
-			sk->destroy              = 1;
+			__set_bit(SOCK_DEAD, &sk->flags);
+			__set_bit(SOCK_DESTROY, &sk->flags);
 			break;
 
 		default:
@@ -995,7 +995,7 @@
 		sk->state     = TCP_CLOSE;
 		sk->shutdown |= SEND_SHUTDOWN;
 		sk->state_change(sk);
-		sk->dead      = 1;
+		__set_bit(SOCK_DEAD, &sk->flags);
 		ax25_destroy_socket(ax25);
 	}
 
@@ -1411,8 +1411,7 @@
 }
 
 static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
-			struct msghdr *msg, int len,
-	struct scm_cookie *scm)
+			struct msghdr *msg, int len)
 {
 	struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name;
 	struct sock *sk = sock->sk;
@@ -1590,7 +1589,7 @@
 }
 
 static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,
-	struct msghdr *msg, int size, int flags, struct scm_cookie *scm)
+	struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb;
diff -Nru a/net/ax25/ax25_ds_in.c b/net/ax25/ax25_ds_in.c
--- a/net/ax25/ax25_ds_in.c	Mon Aug  5 06:20:38 2002
+++ b/net/ax25/ax25_ds_in.c	Mon Mar  3 04:56:53 2003
@@ -67,7 +67,7 @@
 		if (ax25->sk != NULL) {
 			ax25->sk->state = TCP_ESTABLISHED;
 			/* For WAIT_SABM connections we will produce an accept ready socket here */
-			if (!ax25->sk->dead)
+			if (!test_bit(SOCK_DEAD, &ax25->sk->flags))
 				ax25->sk->state_change(ax25->sk);
 		}
 		ax25_dama_on(ax25);
diff -Nru a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c
--- a/net/ax25/ax25_ds_timer.c	Mon Aug  5 09:23:19 2002
+++ b/net/ax25/ax25_ds_timer.c	Mon Mar  3 04:56:53 2003
@@ -103,7 +103,7 @@
 	case AX25_STATE_0:
 		/* Magic here: If we listen() and a new link dies before it
 		   is accepted() it isn't 'dead' so doesn't get removed. */
-		if (ax25->sk == NULL || ax25->sk->destroy || (ax25->sk->state == TCP_LISTEN && ax25->sk->dead)) {
+		if (ax25->sk == NULL || test_bit(SOCK_DESTROY, &ax25->sk->flags) || (ax25->sk->state == TCP_LISTEN && test_bit(SOCK_DEAD, &ax25->sk->flags))) {
 			ax25_destroy_socket(ax25);
 			return;
 		}
@@ -157,9 +157,9 @@
 		ax25->sk->state     = TCP_CLOSE;
 		ax25->sk->err       = 0;
 		ax25->sk->shutdown |= SEND_SHUTDOWN;
-		if (!ax25->sk->dead)
+		if (!test_bit(SOCK_DEAD, &ax25->sk->flags))
 			ax25->sk->state_change(ax25->sk);
-		ax25->sk->dead      = 1;
+		__set_bit(SOCK_DEAD, &ax25->sk->flags);
 	}
 }
 
diff -Nru a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
--- a/net/ax25/ax25_in.c	Mon Aug  5 06:20:38 2002
+++ b/net/ax25/ax25_in.c	Mon Mar  3 04:56:53 2003
@@ -434,7 +434,7 @@
 	ax25_start_idletimer(ax25);
 
 	if (sk != NULL) {
-		if (!sk->dead)
+		if (!test_bit(SOCK_DEAD, &sk->flags))
 			sk->data_ready(sk, skb->len);
 	} else {
 		kfree_skb(skb);
diff -Nru a/net/ax25/ax25_std_in.c b/net/ax25/ax25_std_in.c
--- a/net/ax25/ax25_std_in.c	Mon Aug  5 06:20:38 2002
+++ b/net/ax25/ax25_std_in.c	Mon Mar  3 04:56:53 2003
@@ -75,7 +75,7 @@
 			if (ax25->sk != NULL) {
 				ax25->sk->state = TCP_ESTABLISHED;
 				/* For WAIT_SABM connections we will produce an accept ready socket here */
-				if (!ax25->sk->dead)
+				if (!test_bit(SOCK_DEAD, &ax25->sk->flags))
 					ax25->sk->state_change(ax25->sk);
 			}
 		}
diff -Nru a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c
--- a/net/ax25/ax25_std_timer.c	Mon Aug  5 06:20:38 2002
+++ b/net/ax25/ax25_std_timer.c	Mon Mar  3 04:56:53 2003
@@ -37,7 +37,7 @@
 	case AX25_STATE_0:
 		/* Magic here: If we listen() and a new link dies before it
 		   is accepted() it isn't 'dead' so doesn't get removed. */
-		if (ax25->sk == NULL || ax25->sk->destroy || (ax25->sk->state == TCP_LISTEN && ax25->sk->dead)) {
+		if (ax25->sk == NULL || test_bit(SOCK_DESTROY, &ax25->sk->flags) || (ax25->sk->state == TCP_LISTEN && test_bit(SOCK_DEAD, &ax25->sk->flags))) {
 			ax25_destroy_socket(ax25);
 			return;
 		}
@@ -94,9 +94,9 @@
 		ax25->sk->state     = TCP_CLOSE;
 		ax25->sk->err       = 0;
 		ax25->sk->shutdown |= SEND_SHUTDOWN;
-		if (!ax25->sk->dead)
+		if (!test_bit(SOCK_DEAD, &ax25->sk->flags))
 			ax25->sk->state_change(ax25->sk);
-		ax25->sk->dead      = 1;
+		__set_bit(SOCK_DEAD, &ax25->sk->flags);
 	}
 }
 
diff -Nru a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
--- a/net/ax25/ax25_subr.c	Mon Aug  5 06:20:38 2002
+++ b/net/ax25/ax25_subr.c	Mon Mar  3 04:56:53 2003
@@ -285,8 +285,8 @@
 		ax25->sk->state     = TCP_CLOSE;
 		ax25->sk->err       = reason;
 		ax25->sk->shutdown |= SEND_SHUTDOWN;
-		if (!ax25->sk->dead)
+		if (!test_bit(SOCK_DEAD, &ax25->sk->flags))
 			ax25->sk->state_change(ax25->sk);
-		ax25->sk->dead      = 1;
+		__set_bit(SOCK_DEAD, &ax25->sk->flags);
 	}
 }
diff -Nru a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
--- a/net/bluetooth/af_bluetooth.c	Wed Feb 19 21:05:12 2003
+++ b/net/bluetooth/af_bluetooth.c	Thu Mar  6 11:06:44 2003
@@ -212,7 +212,7 @@
 }
 
 int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
-	struct msghdr *msg, int len, int flags, struct scm_cookie *scm)
+	struct msghdr *msg, int len, int flags)
 {
 	int noblock = flags & MSG_DONTWAIT;
 	struct sock *sk = sock->sk;
diff -Nru a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
--- a/net/bluetooth/bnep/core.c	Wed Feb 19 21:05:12 2003
+++ b/net/bluetooth/bnep/core.c	Thu Mar  6 11:06:44 2003
@@ -97,26 +97,12 @@
 
 static int bnep_send(struct bnep_session *s, void *data, size_t len)
 {
-	struct kiocb iocb;
-	struct sock_iocb *si;
 	struct socket *sock = s->sock;
 	struct iovec iv = { data, len };
-	int err;
 
 	s->msg.msg_iov    = &iv;
 	s->msg.msg_iovlen = 1;
-	init_sync_kiocb(&iocb, NULL);
-	si = kiocb_to_siocb(&iocb);
-	si->scm = NULL;
-	si->sock = sock;
-	si->msg = &s->msg;
-	si->size = len;
-
-	err = sock->ops->sendmsg(&iocb, sock, &s->msg, len, NULL);
-	if (-EIOCBQUEUED == err)
-		err = wait_on_sync_kiocb(&iocb);
-
-	return err;
+	return sock_sendmsg(sock, &s->msg, len);
 }
 
 static int bnep_send_rsp(struct bnep_session *s, u8 ctrl, u16 resp)
@@ -444,20 +430,9 @@
 	
 	/* FIXME: linearize skb */
 	{
-		struct kiocb iocb;
-		struct sock_iocb *si;
-	
 		s->msg.msg_iov    = iv;
 		s->msg.msg_iovlen = il;
-		init_sync_kiocb(&iocb, NULL);
-		si = kiocb_to_siocb(&iocb);
-		si->scm = NULL;
-		si->sock = sock;
-		si->msg = &s->msg;
-		si->size = len;
-		len = sock->ops->sendmsg(&iocb, sock, &s->msg, len, NULL);
-		if (-EIOCBQUEUED == len)
-			len = wait_on_sync_kiocb(&iocb);
+		len = sock_sendmsg(sock, &s->msg, len);
 	}
 	kfree_skb(skb);
 
diff -Nru a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
--- a/net/bluetooth/hci_sock.c	Wed Feb 19 21:13:32 2003
+++ b/net/bluetooth/hci_sock.c	Thu Mar  6 11:06:44 2003
@@ -320,7 +320,7 @@
         	put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, sizeof(skb->stamp), &skb->stamp);
 }
  
-static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags, struct scm_cookie *scm)
+static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags)
 {
 	int noblock = flags & MSG_DONTWAIT;
 	struct sock *sk = sock->sk;
@@ -356,8 +356,7 @@
 	return err ? : copied;
 }
 
-static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len,
-                            struct scm_cookie *scm)
+static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct hci_dev *hdev;
diff -Nru a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
--- a/net/bluetooth/l2cap.c	Wed Feb 19 21:05:12 2003
+++ b/net/bluetooth/l2cap.c	Thu Mar  6 11:06:44 2003
@@ -272,7 +272,7 @@
 
 	/* Kill poor orphan */
 	bt_sock_unlink(&l2cap_sk_list, sk);
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 	sock_put(sk);
 }
 
@@ -712,7 +712,7 @@
 	return err;
 }
 
-static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm)
+static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	int err = 0;
diff -Nru a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
--- a/net/bluetooth/rfcomm/core.c	Wed Feb 19 21:05:12 2003
+++ b/net/bluetooth/rfcomm/core.c	Thu Mar  6 11:06:44 2003
@@ -605,29 +605,17 @@
 /* ---- RFCOMM frame sending ---- */
 static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len)
 {
-	struct kiocb iocb;
-	struct sock_iocb *si;
 	struct socket *sock = s->sock;
 	struct iovec iv = { data, len };
 	struct msghdr msg;
-	int err;
 
 	BT_DBG("session %p len %d", s, len);
 
 	memset(&msg, 0, sizeof(msg));
 	msg.msg_iovlen = 1;
 	msg.msg_iov = &iv;
-	init_sync_kiocb(&iocb, NULL);
-	si = kiocb_to_siocb(&iocb);
-	si->scm = NULL;
-	si->sock = sock;
-	si->msg = &msg;
-	si->size = len;
-
-	err = sock->ops->sendmsg(&iocb, sock, &msg, len, NULL);
-	if (-EIOCBQUEUED == err)
-		err = wait_on_sync_kiocb(&iocb);
-	return err;
+
+	return sock_sendmsg(sock, &msg, len);
 }
 
 static int rfcomm_send_sabm(struct rfcomm_session *s, u8 dlci)
@@ -839,13 +827,10 @@
 
 static int rfcomm_send_test(struct rfcomm_session *s, int cr, u8 *pattern, int len)
 {
-	struct kiocb iocb;
-	struct sock_iocb *si;
 	struct socket *sock = s->sock;
 	struct iovec iv[3];
 	struct msghdr msg;
 	unsigned char hdr[5], crc[1];
-	int err;
 
 	if (len > 125)
 		return -EINVAL;
@@ -870,18 +855,8 @@
 	memset(&msg, 0, sizeof(msg));
 	msg.msg_iovlen = 3;
 	msg.msg_iov = iv;
-	init_sync_kiocb(&iocb, NULL);
-	si = kiocb_to_siocb(&iocb);
-	si->scm = NULL;
-	si->sock = sock;
-	si->msg = &msg;
-	si->size = 6 + len;
-
-	err = sock->ops->sendmsg(&iocb, sock, &msg, 6 + len, NULL);
-	if (-EIOCBQUEUED == err)
-		err = wait_on_sync_kiocb(&iocb);
 
-	return err;
+	return sock_sendmsg(sock, &msg, 6 + len);
 }
 
 static int rfcomm_send_credits(struct rfcomm_session *s, u8 addr, u8 credits)
diff -Nru a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
--- a/net/bluetooth/rfcomm/sock.c	Wed Feb 19 21:05:12 2003
+++ b/net/bluetooth/rfcomm/sock.c	Thu Mar  6 11:06:44 2003
@@ -212,7 +212,7 @@
 
 	/* Kill poor orphan */
 	bt_sock_unlink(&rfcomm_sk_list, sk);
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 	sock_put(sk);
 }
 
@@ -479,7 +479,7 @@
 }
 
 static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
-			       struct msghdr *msg, int len, struct scm_cookie *scm)
+			       struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
@@ -553,8 +553,7 @@
 }
 
 static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
-			       struct msghdr *msg, int size, int flags,
-			       struct scm_cookie *scm)
+			       struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	int target, err = 0, copied = 0;
diff -Nru a/net/bluetooth/sco.c b/net/bluetooth/sco.c
--- a/net/bluetooth/sco.c	Wed Feb 19 21:05:12 2003
+++ b/net/bluetooth/sco.c	Thu Mar  6 11:06:44 2003
@@ -377,7 +377,7 @@
 
 	/* Kill poor orphan */
 	bt_sock_unlink(&sco_sk_list, sk);
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 	sock_put(sk);
 }
 
@@ -632,7 +632,7 @@
 	return 0;
 }
 
-static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm)
+static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	int err = 0;
diff -Nru a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c
--- a/net/bridge/netfilter/ebt_arp.c	Mon Sep 16 16:11:26 2002
+++ b/net/bridge/netfilter/ebt_arp.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebt_arp
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *	Tim Gardner <timg@tpi.com>
  *
  *  April, 2002
@@ -37,10 +37,10 @@
 		uint32_t dst;
 		uint32_t src;
 
-		// Make sure the packet is long enough.
+		/* Make sure the packet is long enough */
 		if ((((*skb).nh.raw) + arp_len) > (*skb).tail)
 			return EBT_NOMATCH;
-		// IPv4 addresses are always 4 bytes.
+		/* IPv4 addresses are always 4 bytes */
 		if (((*skb).nh.arph)->ar_pln != sizeof(uint32_t))
 			return EBT_NOMATCH;
 
@@ -82,8 +82,10 @@
 
 static struct ebt_match filter_arp =
 {
-	{NULL, NULL}, EBT_ARP_MATCH, ebt_filter_arp, ebt_arp_check, NULL,
-	THIS_MODULE
+	.name		= EBT_ARP_MATCH,
+	.match		= ebt_filter_arp,
+	.check		= ebt_arp_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c
--- a/net/bridge/netfilter/ebt_dnat.c	Mon Sep 16 16:11:26 2002
+++ b/net/bridge/netfilter/ebt_dnat.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebt_dnat
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  June, 2002
  *
@@ -45,8 +45,10 @@
 
 static struct ebt_target dnat =
 {
-	{NULL, NULL}, EBT_DNAT_TARGET, ebt_target_dnat, ebt_target_dnat_check,
-	NULL, THIS_MODULE
+	.name		= EBT_DNAT_TARGET,
+	.target		= ebt_target_dnat,
+	.check		= ebt_target_dnat_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
--- a/net/bridge/netfilter/ebt_ip.c	Mon Oct 28 04:58:32 2002
+++ b/net/bridge/netfilter/ebt_ip.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebt_ip
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  April, 2002
  *
@@ -86,7 +86,7 @@
 	if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK)
 		return -EINVAL;
 	if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) {
-		if (!info->bitmask & EBT_IPROTO)
+		if (!(info->bitmask & EBT_IPROTO))
 			return -EINVAL;
 		if (info->protocol != IPPROTO_TCP &&
 		    info->protocol != IPPROTO_UDP)
@@ -101,8 +101,10 @@
 
 static struct ebt_match filter_ip =
 {
-	{NULL, NULL}, EBT_IP_MATCH, ebt_filter_ip, ebt_ip_check, NULL,
-	THIS_MODULE
+	.name		= EBT_IP_MATCH,
+	.match		= ebt_filter_ip,
+	.check		= ebt_ip_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
--- a/net/bridge/netfilter/ebt_log.c	Mon Jan 13 17:12:01 2003
+++ b/net/bridge/netfilter/ebt_log.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebt_log
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  April, 2002
  *
@@ -80,8 +80,10 @@
 
 static struct ebt_watcher log =
 {
-	{NULL, NULL}, EBT_LOG_WATCHER, ebt_log, ebt_log_check, NULL,
-	THIS_MODULE
+	.name		= EBT_LOG_WATCHER,
+	.watcher	= ebt_log,
+	.check		= ebt_log_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
--- a/net/bridge/netfilter/ebt_mark.c	Mon Sep 16 16:11:27 2002
+++ b/net/bridge/netfilter/ebt_mark.c	Mon Mar  3 04:41:09 2003
@@ -2,15 +2,16 @@
  *  ebt_mark
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  July, 2002
  *
  */
 
-// The mark target can be used in any chain
-// I believe adding a mangle table just for marking is total overkill
-// Marking a frame doesn't really change anything in the frame anyway
+/* The mark target can be used in any chain,
+ * I believe adding a mangle table just for marking is total overkill.
+ * Marking a frame doesn't really change anything in the frame anyway.
+ */
 
 #include <linux/netfilter_bridge/ebtables.h>
 #include <linux/netfilter_bridge/ebt_mark_t.h>
@@ -46,8 +47,10 @@
 
 static struct ebt_target mark_target =
 {
-	{NULL, NULL}, EBT_MARK_TARGET, ebt_target_mark,
-	ebt_target_mark_check, NULL, THIS_MODULE
+	.name		= EBT_MARK_TARGET,
+	.target		= ebt_target_mark,
+	.check		= ebt_target_mark_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c
--- a/net/bridge/netfilter/ebt_mark_m.c	Mon Sep 16 16:11:27 2002
+++ b/net/bridge/netfilter/ebt_mark_m.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebt_mark_m
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  July, 2002
  *
@@ -41,8 +41,10 @@
 
 static struct ebt_match filter_mark =
 {
-	{NULL, NULL}, EBT_MARK_MATCH, ebt_filter_mark, ebt_mark_check, NULL,
-	THIS_MODULE
+	.name		= EBT_MARK_MATCH,
+	.match		= ebt_filter_mark,
+	.check		= ebt_mark_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
--- a/net/bridge/netfilter/ebt_redirect.c	Mon Sep 16 16:11:27 2002
+++ b/net/bridge/netfilter/ebt_redirect.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebt_redirect
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  April, 2002
  *
@@ -51,8 +51,10 @@
 
 static struct ebt_target redirect_target =
 {
-	{NULL, NULL}, EBT_REDIRECT_TARGET, ebt_target_redirect,
-	ebt_target_redirect_check, NULL, THIS_MODULE
+	.name		= EBT_REDIRECT_TARGET,
+	.target		= ebt_target_redirect,
+	.check		= ebt_target_redirect_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
--- a/net/bridge/netfilter/ebt_snat.c	Mon Sep 16 16:11:27 2002
+++ b/net/bridge/netfilter/ebt_snat.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebt_snat
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  June, 2002
  *
@@ -44,8 +44,10 @@
 
 static struct ebt_target snat =
 {
-	{NULL, NULL}, EBT_SNAT_TARGET, ebt_target_snat, ebt_target_snat_check,
-	NULL, THIS_MODULE
+	.name		= EBT_SNAT_TARGET,
+	.target		= ebt_target_snat,
+	.check		= ebt_target_snat_check,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
--- a/net/bridge/netfilter/ebt_vlan.c	Thu Dec  5 13:15:16 2002
+++ b/net/bridge/netfilter/ebt_vlan.c	Mon Mar  3 04:41:09 2003
@@ -1,7 +1,7 @@
 /*
  * Description: EBTables 802.1Q match extension kernelspace module.
  * Authors: Nick Fedchik <nick@fedchik.org.ua>
- *          Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *          Bart De Schuymer <bdschuym@pandora.be>
  *    
  * 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
@@ -226,12 +226,10 @@
 }
 
 static struct ebt_match filter_vlan = {
-	{NULL, NULL},
-	EBT_VLAN_MATCH,
-	ebt_filter_vlan,
-	ebt_check_vlan,
-	NULL,
-	THIS_MODULE
+	.name		= EBT_VLAN_MATCH,
+	.match		= ebt_filter_vlan,
+	.check		= ebt_check_vlan,
+	.me		= THIS_MODULE,
 };
 
 /*
diff -Nru a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
--- a/net/bridge/netfilter/ebtable_broute.c	Mon Mar  3 01:43:37 2003
+++ b/net/bridge/netfilter/ebtable_broute.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebtable_broute
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  April, 2002
  *
@@ -16,11 +16,12 @@
 #include <linux/if_bridge.h>
 #include <linux/brlock.h>
 
-// EBT_ACCEPT means the frame will be bridged
-// EBT_DROP means the frame will be routed
+/* EBT_ACCEPT means the frame will be bridged
+ * EBT_DROP means the frame will be routed
+ */
 static struct ebt_entries initial_chain = {
-	.name	= "BROUTING",
-	.policy	= EBT_ACCEPT,
+	.name		= "BROUTING",
+	.policy		= EBT_ACCEPT,
 };
 
 static struct ebt_replace initial_table =
@@ -31,7 +32,7 @@
 	.hook_entry	= {
 		[NF_BR_BROUTING]	= &initial_chain,
 	},
-	.entries	= (char *)&initial_chain
+	.entries	= (char *)&initial_chain,
 };
 
 static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
@@ -57,8 +58,8 @@
 	ret = ebt_do_table(NF_BR_BROUTING, pskb, (*pskb)->dev, NULL,
 	   &broute_table);
 	if (ret == NF_DROP)
-		return 1; // route it
-	return 0; // bridge it
+		return 1; /* route it */
+	return 0; /* bridge it */
 }
 
 static int __init init(void)
@@ -69,7 +70,7 @@
 	if (ret < 0)
 		return ret;
 	br_write_lock_bh(BR_NETPROTO_LOCK);
-	// see br_input.c
+	/* see br_input.c */
 	br_should_route_hook = ebt_broute;
 	br_write_unlock_bh(BR_NETPROTO_LOCK);
 	return ret;
diff -Nru a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
--- a/net/bridge/netfilter/ebtable_filter.c	Mon Mar  3 01:43:37 2003
+++ b/net/bridge/netfilter/ebtable_filter.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebtable_filter
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  April, 2002
  *
@@ -27,7 +27,7 @@
 	{
 		.name	= "OUTPUT",
 		.policy	= EBT_ACCEPT,
-	}
+	},
 };
 
 static struct ebt_replace initial_table =
@@ -35,12 +35,12 @@
 	.name		= "filter",
 	.valid_hooks	= FILTER_VALID_HOOKS,
 	.entries_size	= 3 * sizeof(struct ebt_entries),
-  	.hook_entry	= {
+	.hook_entry	= {
 		[NF_BR_LOCAL_IN]	= &initial_chains[0],
 		[NF_BR_FORWARD]		= &initial_chains[1],
-    		[NF_BR_LOCAL_OUT]	= &initial_chains[2],
+		[NF_BR_LOCAL_OUT]	= &initial_chains[2],
 	},
-	.entries	= (char *)initial_chains
+	.entries	= (char *)initial_chains,
 };
 
 static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
@@ -77,14 +77,14 @@
 		.hook		= ebt_hook,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_FORWARD,
-		.priority	= NF_BR_PRI_FILTER_BRIDGED
+		.priority	= NF_BR_PRI_FILTER_BRIDGED,
 	},
 	{
 		.hook		= ebt_hook,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_LOCAL_OUT,
-		.priority	= NF_BR_PRI_FILTER_OTHER
-	}
+		.priority	= NF_BR_PRI_FILTER_OTHER,
+	},
 };
 
 static int __init init(void)
diff -Nru a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
--- a/net/bridge/netfilter/ebtable_nat.c	Mon Mar  3 01:43:37 2003
+++ b/net/bridge/netfilter/ebtable_nat.c	Mon Mar  3 04:41:09 2003
@@ -2,7 +2,7 @@
  *  ebtable_nat
  *
  *	Authors:
- *	Bart De Schuymer <bart.de.schuymer@pandora.be>
+ *	Bart De Schuymer <bdschuym@pandora.be>
  *
  *  April, 2002
  *
@@ -39,7 +39,7 @@
 		[NF_BR_LOCAL_OUT]	= &initial_chains[1],
 		[NF_BR_POST_ROUTING]	= &initial_chains[2],
 	},
-	.entries	= (char *)initial_chains
+	.entries	= (char *)initial_chains,
 };
 
 static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
@@ -77,19 +77,19 @@
 		.hook		= ebt_nat_dst,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_LOCAL_OUT,
-		.priority	= NF_BR_PRI_NAT_DST_OTHER
+		.priority	= NF_BR_PRI_NAT_DST_OTHER,
 	},
 	{
 		.hook		= ebt_nat_src,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_POST_ROUTING,
-		.priority	= NF_BR_PRI_NAT_SRC
+		.priority	= NF_BR_PRI_NAT_SRC,
 	},
 	{
 		.hook		= ebt_nat_dst,
 		.pf		= PF_BRIDGE,
 		.hooknum	= NF_BR_PRE_ROUTING,
-		.priority	= NF_BR_PRI_NAT_DST_BRIDGED
+		.priority	= NF_BR_PRI_NAT_DST_BRIDGED,
 	},
 };
 
diff -Nru a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
--- a/net/bridge/netfilter/ebtables.c	Mon Jan 13 00:16:09 2003
+++ b/net/bridge/netfilter/ebtables.c	Mon Mar  3 04:41:09 2003
@@ -365,7 +365,7 @@
 	m->u.match = match;
 	if (!try_module_get(match->me)) {
 		up(&ebt_mutex);
-		return -EINVAL;
+		return -ENOENT;
 	}
 	up(&ebt_mutex);
 	if (match->check &&
@@ -394,7 +394,7 @@
 	w->u.watcher = watcher;
 	if (!try_module_get(watcher->me)) {
 		up(&ebt_mutex);
-		return -EINVAL;
+		return -ENOENT;
 	}
 	up(&ebt_mutex);
 	if (watcher->check &&
@@ -634,6 +634,7 @@
 		goto cleanup_watchers;
 	if (!try_module_get(target->me)) {
 		up(&ebt_mutex);
+		ret = -ENOENT;
 		goto cleanup_watchers;
 	}
 	up(&ebt_mutex);
diff -Nru a/net/compat.c b/net/compat.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/net/compat.c	Thu Mar  6 11:02:18 2003
@@ -0,0 +1,700 @@
+/* 
+ * 32bit Socket syscall emulation. Based on arch/sparc64/kernel/sys_sparc32.c.
+ *
+ * Copyright (C) 2000		VA Linux Co
+ * Copyright (C) 2000		Don Dugger <n0ano@valinux.com>
+ * Copyright (C) 1999 		Arun Sharma <arun.sharma@intel.com>
+ * Copyright (C) 1997,1998 	Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997 		David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 2000		Hewlett-Packard Co.
+ * Copyright (C) 2000		David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2000,2001	Andi Kleen, SuSE Labs 
+ */
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/file.h>
+#include <linux/icmpv6.h>
+#include <linux/socket.h>
+#include <linux/filter.h>
+#include <linux/compat.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+#include <net/scm.h>
+#include <net/sock.h>
+#include <asm/uaccess.h>
+#include <net/compat_socket.h>
+
+#define A(__x)		((unsigned long)(__x))
+#define AA(__x)		((unsigned long)(__x))
+
+extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
+				       void * optval, int *optlen);
+
+
+static inline int iov_from_user_compat_to_kern(struct iovec *kiov,
+					  struct compat_iovec *uiov32,
+					  int niov)
+{
+	int tot_len = 0;
+
+	while(niov > 0) {
+		u32 len, buf;
+
+		if(get_user(len, &uiov32->iov_len) ||
+		   get_user(buf, &uiov32->iov_base)) {
+			tot_len = -EFAULT;
+			break;
+		}
+		tot_len += len;
+		kiov->iov_base = (void *)A(buf);
+		kiov->iov_len = (__kernel_size_t) len;
+		uiov32++;
+		kiov++;
+		niov--;
+	}
+	return tot_len;
+}
+
+int msghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct compat_msghdr *umsg)
+{
+	u32 tmp1, tmp2, tmp3;
+	int err;
+
+	err = get_user(tmp1, &umsg->msg_name);
+	err |= __get_user(tmp2, &umsg->msg_iov);
+	err |= __get_user(tmp3, &umsg->msg_control);
+	if (err)
+		return -EFAULT;
+
+	kmsg->msg_name = (void *)A(tmp1);
+	kmsg->msg_iov = (struct iovec *)A(tmp2);
+	kmsg->msg_control = (void *)A(tmp3);
+
+	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
+	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
+	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
+	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
+	
+	return err;
+}
+
+/* I've named the args so it is easy to tell whose space the pointers are in. */
+int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov,
+		   char *kern_address, int mode)
+{
+	int tot_len;
+
+	if(kern_msg->msg_namelen) {
+		if(mode==VERIFY_READ) {
+			int err = move_addr_to_kernel(kern_msg->msg_name,
+						      kern_msg->msg_namelen,
+						      kern_address);
+			if(err < 0)
+				return err;
+		}
+		kern_msg->msg_name = kern_address;
+	} else
+		kern_msg->msg_name = NULL;
+
+	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
+		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
+				   GFP_KERNEL);
+		if(!kern_iov)
+			return -ENOMEM;
+	}
+
+	tot_len = iov_from_user_compat_to_kern(kern_iov,
+					  (struct compat_iovec *)kern_msg->msg_iov,
+					  kern_msg->msg_iovlen);
+	if(tot_len >= 0)
+		kern_msg->msg_iov = kern_iov;
+	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
+		kfree(kern_iov);
+
+	return tot_len;
+}
+
+/* There is a lot of hair here because the alignment rules (and
+ * thus placement) of cmsg headers and length are different for
+ * 32-bit apps.  -DaveM
+ */
+int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg,
+			       unsigned char *stackbuf, int stackbuf_size)
+{
+	struct compat_cmsghdr *ucmsg;
+	struct cmsghdr *kcmsg, *kcmsg_base;
+	compat_size_t ucmlen;
+	__kernel_size_t kcmlen, tmp;
+
+	kcmlen = 0;
+	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
+	ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg);
+	while(ucmsg != NULL) {
+		if(get_user(ucmlen, &ucmsg->cmsg_len))
+			return -EFAULT;
+
+		/* Catch bogons. */
+		if(CMSG_COMPAT_ALIGN(ucmlen) <
+		   CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)))
+			return -EINVAL;
+		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
+				   + ucmlen) > kmsg->msg_controllen)
+			return -EINVAL;
+
+		tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) +
+		       CMSG_ALIGN(sizeof(struct cmsghdr)));
+		kcmlen += tmp;
+		ucmsg = CMSG_COMPAT_NXTHDR(kmsg, ucmsg, ucmlen);
+	}
+	if(kcmlen == 0)
+		return -EINVAL;
+
+	/* The kcmlen holds the 64-bit version of the control length.
+	 * It may not be modified as we do not stick it into the kmsg
+	 * until we have successfully copied over all of the data
+	 * from the user.
+	 */
+	if(kcmlen > stackbuf_size)
+		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
+	if(kcmsg == NULL)
+		return -ENOBUFS;
+
+	/* Now copy them over neatly. */
+	memset(kcmsg, 0, kcmlen);
+	ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg);
+	while(ucmsg != NULL) {
+		__get_user(ucmlen, &ucmsg->cmsg_len);
+		tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) +
+		       CMSG_ALIGN(sizeof(struct cmsghdr)));
+		kcmsg->cmsg_len = tmp;
+		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
+		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
+
+		/* Copy over the data. */
+		if(copy_from_user(CMSG_DATA(kcmsg),
+				  CMSG_COMPAT_DATA(ucmsg),
+				  (ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg)))))
+			goto out_free_efault;
+
+		/* Advance. */
+		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
+		ucmsg = CMSG_COMPAT_NXTHDR(kmsg, ucmsg, ucmlen);
+	}
+
+	/* Ok, looks like we made it.  Hook it up and return success. */
+	kmsg->msg_control = kcmsg_base;
+	kmsg->msg_controllen = kcmlen;
+	return 0;
+
+out_free_efault:
+	if(kcmsg_base != (struct cmsghdr *)stackbuf)
+		kfree(kcmsg_base);
+	return -EFAULT;
+}
+
+int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data)
+{
+	struct compat_cmsghdr *cm = (struct compat_cmsghdr *) kmsg->msg_control;
+	struct compat_cmsghdr cmhdr;
+	int cmlen = CMSG_COMPAT_LEN(len);
+
+	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
+		kmsg->msg_flags |= MSG_CTRUNC;
+		return 0; /* XXX: return error? check spec. */
+	}
+
+	if(kmsg->msg_controllen < cmlen) {
+		kmsg->msg_flags |= MSG_CTRUNC;
+		cmlen = kmsg->msg_controllen;
+	}
+	cmhdr.cmsg_level = level;
+	cmhdr.cmsg_type = type;
+	cmhdr.cmsg_len = cmlen;
+
+	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
+		return -EFAULT;
+	if(copy_to_user(CMSG_COMPAT_DATA(cm), data, cmlen - sizeof(struct compat_cmsghdr)))
+		return -EFAULT;
+	cmlen = CMSG_COMPAT_SPACE(len);
+	kmsg->msg_control += cmlen;
+	kmsg->msg_controllen -= cmlen;
+	return 0;
+}
+
+void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm)
+{
+	struct compat_cmsghdr *cm = (struct compat_cmsghdr *) kmsg->msg_control;
+	int fdmax = (kmsg->msg_controllen - sizeof(struct compat_cmsghdr)) / sizeof(int);
+	int fdnum = scm->fp->count;
+	struct file **fp = scm->fp->fp;
+	int *cmfptr;
+	int err = 0, i;
+
+	if (fdnum < fdmax)
+		fdmax = fdnum;
+
+	for (i = 0, cmfptr = (int *) CMSG_COMPAT_DATA(cm); i < fdmax; i++, cmfptr++) {
+		int new_fd;
+		err = get_unused_fd();
+		if (err < 0)
+			break;
+		new_fd = err;
+		err = put_user(new_fd, cmfptr);
+		if (err) {
+			put_unused_fd(new_fd);
+			break;
+		}
+		/* Bump the usage count and install the file. */
+		get_file(fp[i]);
+		fd_install(new_fd, fp[i]);
+	}
+
+	if (i > 0) {
+		int cmlen = CMSG_COMPAT_LEN(i * sizeof(int));
+		if (!err)
+			err = put_user(SOL_SOCKET, &cm->cmsg_level);
+		if (!err)
+			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
+		if (!err)
+			err = put_user(cmlen, &cm->cmsg_len);
+		if (!err) {
+			cmlen = CMSG_COMPAT_SPACE(i * sizeof(int));
+			kmsg->msg_control += cmlen;
+			kmsg->msg_controllen -= cmlen;
+		}
+	}
+	if (i < fdnum)
+		kmsg->msg_flags |= MSG_CTRUNC;
+
+	/*
+	 * All of the files that fit in the message have had their
+	 * usage counts incremented, so we just free the list.
+	 */
+	__scm_destroy(scm);
+}
+
+/* In these cases we (currently) can just copy to data over verbatim
+ * because all CMSGs created by the kernel have well defined types which
+ * have the same layout in both the 32-bit and 64-bit API.  One must add
+ * some special cased conversions here if we start sending control messages
+ * with incompatible types.
+ *
+ * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg_compat right after
+ * we do our work.  The remaining cases are:
+ *
+ * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
+ *		IP_TTL		int			32-bit clean
+ *		IP_TOS		__u8			32-bit clean
+ *		IP_RECVOPTS	variable length		32-bit clean
+ *		IP_RETOPTS	variable length		32-bit clean
+ *		(these last two are clean because the types are defined
+ *		 by the IPv4 protocol)
+ *		IP_RECVERR	struct sock_extended_err +
+ *				struct sockaddr_in	32-bit clean
+ * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
+ *				struct sockaddr_in6	32-bit clean
+ *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
+ *		IPV6_HOPLIMIT	int			32-bit clean
+ *		IPV6_FLOWINFO	u32			32-bit clean
+ *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
+ *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
+ *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
+ *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
+ */
+void cmsg_compat_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
+{
+	unsigned char *workbuf, *wp;
+	unsigned long bufsz, space_avail;
+	struct cmsghdr *ucmsg;
+
+	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
+	space_avail = kmsg->msg_controllen + bufsz;
+	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
+	if(workbuf == NULL)
+		goto fail;
+
+	/* To make this more sane we assume the kernel sends back properly
+	 * formatted control messages.  Because of how the kernel will truncate
+	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
+	 */
+	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
+	while(((unsigned long)ucmsg) <=
+	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
+		struct compat_cmsghdr *kcmsg_compat = (struct compat_cmsghdr *) wp;
+		int clen64, clen32;
+
+		/* UCMSG is the 64-bit format CMSG entry in user-space.
+		 * KCMSG_COMPAT is within the kernel space temporary buffer
+		 * we use to convert into a 32-bit style CMSG.
+		 */
+		__get_user(kcmsg_compat->cmsg_len, &ucmsg->cmsg_len);
+		__get_user(kcmsg_compat->cmsg_level, &ucmsg->cmsg_level);
+		__get_user(kcmsg_compat->cmsg_type, &ucmsg->cmsg_type);
+
+		clen64 = kcmsg_compat->cmsg_len;
+		copy_from_user(CMSG_COMPAT_DATA(kcmsg_compat), CMSG_DATA(ucmsg),
+			       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
+		clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
+			  CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)));
+		kcmsg_compat->cmsg_len = clen32;
+
+		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
+		wp = (((char *)kcmsg_compat) + CMSG_COMPAT_ALIGN(clen32));
+	}
+
+	/* Copy back fixed up data, and adjust pointers. */
+	bufsz = (wp - workbuf);
+	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
+
+	kmsg->msg_control = (struct cmsghdr *)
+		(((char *)orig_cmsg_uptr) + bufsz);
+	kmsg->msg_controllen = space_avail - bufsz;
+
+	kfree(workbuf);
+	return;
+
+fail:
+	/* If we leave the 64-bit format CMSG chunks in there,
+	 * the application could get confused and crash.  So to
+	 * ensure greater recovery, we report no CMSGs.
+	 */
+	kmsg->msg_controllen += bufsz;
+	kmsg->msg_control = (void *) orig_cmsg_uptr;
+}
+
+extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
+				     char *optval, int optlen);
+
+static int do_netfilter_replace(int fd, int level, int optname,
+				char *optval, int optlen)
+{
+	struct ipt_replace32 {
+		char name[IPT_TABLE_MAXNAMELEN];
+		__u32 valid_hooks;
+		__u32 num_entries;
+		__u32 size;
+		__u32 hook_entry[NF_IP_NUMHOOKS];
+		__u32 underflow[NF_IP_NUMHOOKS];
+		__u32 num_counters;
+		__u32 counters;
+		struct ipt_entry entries[0];
+	} *repl32 = (struct ipt_replace32 *)optval;
+	struct ipt_replace *krepl;
+	struct ipt_counters *counters32;
+	__u32 origsize;
+	unsigned int kreplsize, kcountersize;
+	mm_segment_t old_fs;
+	int ret;
+
+	if (optlen < sizeof(repl32))
+		return -EINVAL;
+
+	if (copy_from_user(&origsize,
+			&repl32->size,
+			sizeof(origsize)))
+		return -EFAULT;
+
+	kreplsize = sizeof(*krepl) + origsize;
+	kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
+
+	/* Hack: Causes ipchains to give correct error msg --RR */
+	if (optlen != kreplsize)
+		return -ENOPROTOOPT;
+
+	krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL);
+	if (krepl == NULL)
+		return -ENOMEM;
+
+	if (copy_from_user(krepl, optval, kreplsize)) {
+		kfree(krepl);
+		return -EFAULT;
+	}
+
+	counters32 = (struct ipt_counters *)AA(
+		((struct ipt_replace32 *)krepl)->counters);
+
+	kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
+	krepl->counters = (struct ipt_counters *)kmalloc(
+					kcountersize, GFP_KERNEL);
+	if (krepl->counters == NULL) {
+		kfree(krepl);
+		return -ENOMEM;
+	}
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_setsockopt(fd, level, optname,
+			     (char *)krepl, kreplsize);
+	set_fs(old_fs);
+
+	if (ret == 0 &&
+		copy_to_user(counters32, krepl->counters, kcountersize))
+			ret = -EFAULT;
+
+	kfree(krepl->counters);
+	kfree(krepl);
+
+	return ret;
+}
+
+static int do_set_attach_filter(int fd, int level, int optname,
+				char *optval, int optlen)
+{
+	struct sock_fprog32 {
+		__u16 len;
+		__u32 filter;
+	} *fprog32 = (struct sock_fprog32 *)optval;
+	struct sock_fprog kfprog;
+	struct sock_filter *kfilter;
+	unsigned int fsize;
+	mm_segment_t old_fs;
+	__u32 uptr;
+	int ret;
+
+	if (get_user(kfprog.len, &fprog32->len) ||
+	    __get_user(uptr, &fprog32->filter))
+		return -EFAULT;
+
+	kfprog.filter = (struct sock_filter *)A(uptr);
+	fsize = kfprog.len * sizeof(struct sock_filter);
+
+	kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
+	if (kfilter == NULL)
+		return -ENOMEM;
+
+	if (copy_from_user(kfilter, kfprog.filter, fsize)) {
+		kfree(kfilter);
+		return -EFAULT;
+	}
+
+	kfprog.filter = kfilter;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_setsockopt(fd, level, optname,
+			     (char *)&kfprog, sizeof(kfprog));
+	set_fs(old_fs);
+
+	kfree(kfilter);
+
+	return ret;
+}
+
+static int do_set_icmpv6_filter(int fd, int level, int optname,
+				char *optval, int optlen)
+{
+	struct icmp6_filter kfilter;
+	mm_segment_t old_fs;
+	int ret, i;
+
+	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
+		return -EFAULT;
+
+
+	for (i = 0; i < 8; i += 2) {
+		u32 tmp = kfilter.data[i];
+
+		kfilter.data[i] = kfilter.data[i + 1];
+		kfilter.data[i + 1] = tmp;
+	}
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_setsockopt(fd, level, optname,
+			     (char *) &kfilter, sizeof(kfilter));
+	set_fs(old_fs);
+
+	return ret;
+}
+
+static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen)
+{
+	struct compat_timeval *up = (struct compat_timeval *) optval;
+	struct timeval ktime;
+	mm_segment_t old_fs;
+	int err;
+
+	if (optlen < sizeof(*up))
+		return -EINVAL;
+	if (get_user(ktime.tv_sec, &up->tv_sec) ||
+	    __get_user(ktime.tv_usec, &up->tv_usec))
+		return -EFAULT;
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime));
+	set_fs(old_fs);
+
+	return err;
+}
+
+asmlinkage int compat_sys_setsockopt(int fd, int level, int optname,
+				char *optval, int optlen)
+{
+	if (optname == IPT_SO_SET_REPLACE)
+		return do_netfilter_replace(fd, level, optname,
+					    optval, optlen);
+	if (optname == SO_ATTACH_FILTER)
+		return do_set_attach_filter(fd, level, optname,
+					    optval, optlen);
+	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
+		return do_set_sock_timeout(fd, level, optname, optval, optlen);
+	if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER)
+		return do_set_icmpv6_filter(fd, level, optname,
+					    optval, optlen);
+
+	return sys_setsockopt(fd, level, optname, optval, optlen);
+}
+
+static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
+{
+	struct compat_timeval *up = (struct compat_timeval *) optval;
+	struct timeval ktime;
+	mm_segment_t old_fs;
+	int len, err;
+
+	if (get_user(len, optlen))
+		return -EFAULT;
+	if (len < sizeof(*up))
+		return -EINVAL;
+	len = sizeof(ktime);
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len);
+	set_fs(old_fs);
+
+	if (!err) {
+		if (put_user(sizeof(*up), optlen) ||
+		    put_user(ktime.tv_sec, &up->tv_sec) ||
+		    __put_user(ktime.tv_usec, &up->tv_usec))
+			err = -EFAULT;
+	}
+	return err;
+}
+
+asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
+				char *optval, int *optlen)
+{
+	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
+		return do_get_sock_timeout(fd, level, optname, optval, optlen);
+	return sys_getsockopt(fd, level, optname, optval, optlen);
+}
+
+/* Argument list sizes for compat_sys_socketcall */
+#define AL(x) ((x) * sizeof(u32))
+static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
+				AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
+				AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
+#undef AL
+
+extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
+extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr,
+				  int addrlen);
+extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr,
+				 int *upeer_addrlen); 
+extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr,
+				      int *usockaddr_len);
+extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr,
+				      int *usockaddr_len);
+extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags);
+extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len,
+				   unsigned flags, u32 addr, int addr_len);
+extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
+extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size,
+				     unsigned flags, u32 addr, u32 addr_len);
+extern asmlinkage long sys_socket(int family, int type, int protocol);
+extern asmlinkage long sys_socketpair(int family, int type, int protocol,
+				     int usockvec[2]);
+extern asmlinkage long sys_shutdown(int fd, int how);
+extern asmlinkage long sys_listen(int fd, int backlog);
+
+
+asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr *msg, unsigned flags)
+{
+	return sys_sendmsg(fd, (struct msghdr *)msg, flags | MSG_CMSG_COMPAT);
+}
+
+asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr *msg, unsigned int flags)
+{
+	return sys_recvmsg(fd, (struct msghdr *)msg, flags | MSG_CMSG_COMPAT);
+}
+
+asmlinkage long compat_sys_socketcall(int call, u32 *args)
+{
+	int ret;
+	u32 a[6];
+	u32 a0, a1;
+				 
+	if (call < SYS_SOCKET || call > SYS_RECVMSG)
+		return -EINVAL;
+	if (copy_from_user(a, args, nas[call]))
+		return -EFAULT;
+	a0 = a[0];
+	a1 = a[1];
+	
+	switch(call) {
+	case SYS_SOCKET:
+		ret = sys_socket(a0, a1, a[2]);
+		break;
+	case SYS_BIND:
+		ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]);
+		break;
+	case SYS_CONNECT:
+		ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]);
+		break;
+	case SYS_LISTEN:
+		ret = sys_listen(a0, a1);
+		break;
+	case SYS_ACCEPT:
+		ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
+		break;
+	case SYS_GETSOCKNAME:
+		ret = sys_getsockname(a0, (struct sockaddr *)A(a1),
+				       (int *)A(a[2]));
+		break;
+	case SYS_GETPEERNAME:
+		ret = sys_getpeername(a0, (struct sockaddr *)A(a1),
+				       (int *)A(a[2]));
+		break;
+	case SYS_SOCKETPAIR:
+		ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
+		break;
+	case SYS_SEND:
+		ret = sys_send(a0, (void *)A(a1), a[2], a[3]);
+		break;
+	case SYS_SENDTO:
+		ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]);
+		break;
+	case SYS_RECV:
+		ret = sys_recv(a0, (void *)A(a1), a[2], a[3]);
+		break;
+	case SYS_RECVFROM:
+		ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
+		break;
+	case SYS_SHUTDOWN:
+		ret = sys_shutdown(a0,a1);
+		break;
+	case SYS_SETSOCKOPT:
+		ret = compat_sys_setsockopt(a0, a1, a[2], (char *)A(a[3]),
+				      a[4]);
+		break;
+	case SYS_GETSOCKOPT:
+		ret = compat_sys_getsockopt(a0, a1, a[2], (char *)(u64)a[3],
+					    (int *)(u64)a[4]);
+		break;
+	case SYS_SENDMSG:
+		ret = compat_sys_sendmsg(a0, (struct compat_msghdr *)A(a1),
+				         a[2]);
+		break;
+	case SYS_RECVMSG:
+		ret = compat_sys_recvmsg(a0, (struct compat_msghdr *)A(a1),
+				         a[2]);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
diff -Nru a/net/core/scm.c b/net/core/scm.c
--- a/net/core/scm.c	Wed Nov 27 15:12:41 2002
+++ b/net/core/scm.c	Thu Mar  6 11:06:44 2003
@@ -172,6 +172,9 @@
 	int cmlen = CMSG_LEN(len);
 	int err;
 
+	if (MSG_CMSG_COMPAT & msg->msg_flags)
+		return put_cmsg_compat(msg, level, type, len, data);
+
 	if (cm==NULL || msg->msg_controllen < sizeof(*cm)) {
 		msg->msg_flags |= MSG_CTRUNC;
 		return 0; /* XXX: return error? check spec. */
@@ -206,6 +209,9 @@
 	struct file **fp = scm->fp->fp;
 	int *cmfptr;
 	int err = 0, i;
+
+	if (MSG_CMSG_COMPAT & msg->msg_flags)
+		return scm_detach_fds_compat(msg, scm);
 
 	if (msg->msg_controllen > sizeof(struct cmsghdr))
 		fdmax = ((msg->msg_controllen - sizeof(struct cmsghdr))
diff -Nru a/net/core/skbuff.c b/net/core/skbuff.c
--- a/net/core/skbuff.c	Fri Jan 10 12:07:06 2003
+++ b/net/core/skbuff.c	Mon Mar  3 08:51:51 2003
@@ -196,40 +196,6 @@
 		goto nodata;
 
 	/* XXX: does not include slab overhead */
-	skb->truesize = size + sizeof(struct sk_buff);
-
-	/* Load the data pointers. */
-	skb->head = skb->data = skb->tail = data;
-	skb->end  = data + size;
-
-	/* Set up other state */
-	skb->len      = 0;
-	skb->cloned   = 0;
-	skb->data_len = 0;
-
-	atomic_set(&skb->users, 1);
-	atomic_set(&(skb_shinfo(skb)->dataref), 1);
-	skb_shinfo(skb)->nr_frags  = 0;
-	skb_shinfo(skb)->tso_size = 0;
-	skb_shinfo(skb)->tso_segs = 0;
-	skb_shinfo(skb)->frag_list = NULL;
-out:
-	return skb;
-nodata:
-	skb_head_to_pool(skb);
-	skb = NULL;
-	goto out;
-}
-
-
-/*
- *	Slab constructor for a skb head.
- */
-static void skb_headerinit(void *p, kmem_cache_t *cache,
-			   unsigned long flags)
-{
-	struct sk_buff *skb = p;
-
 	skb->next	  = skb->prev = NULL;
 	skb->list	  = NULL;
 	skb->sk		  = NULL;
@@ -238,27 +204,50 @@
 	skb->dst	  = NULL;
 	skb->sp		  = NULL;
 	memset(skb->cb, 0, sizeof(skb->cb));
+	/* Set up other state */
+	skb->len	  = 0;
+	skb->data_len	  = 0;
+	skb->csum	  = 0;
+	skb->cloned	  = 0;
 	skb->pkt_type	  = PACKET_HOST;	/* Default type */
 	skb->ip_summed	  = 0;
 	skb->priority	  = 0;
+	atomic_set(&skb->users, 1);
 	skb->security	  = 0;	/* By default packets are insecure */
-	skb->destructor	  = NULL;
+	skb->truesize = size + sizeof(struct sk_buff);
+	
+	/* Load the data pointers. */
+	skb->head = skb->data = skb->tail = data;
+	skb->end  = data + size;
 
+	skb->destructor	  = NULL;
 #ifdef CONFIG_NETFILTER
-	skb->nfmark	  = skb->nfcache = 0;
-	skb->nfct	  = NULL;
+	skb->nfmark	= skb->nfcache = 0;
+	skb->nfct	= NULL;
 #ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug	  = 0;
+	skb->nf_debug	= 0;
 #endif
 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
-	skb->nf_bridge	  = NULL;
+	skb->nf_bridge	= NULL;
 #endif
 #endif
 #ifdef CONFIG_NET_SCHED
-	skb->tc_index	  = 0;
-#endif
+	skb->tc_index	= 0;
+#endif	
+	atomic_set(&(skb_shinfo(skb)->dataref), 1);
+	skb_shinfo(skb)->nr_frags  = 0;
+	skb_shinfo(skb)->tso_size = 0;
+	skb_shinfo(skb)->tso_segs = 0;
+	skb_shinfo(skb)->frag_list = NULL;
+out:
+	return skb;
+nodata:
+	skb_head_to_pool(skb);
+	skb = NULL;
+	goto out;
 }
 
+
 static void skb_drop_fraglist(struct sk_buff *skb)
 {
 	struct sk_buff *list = skb_shinfo(skb)->frag_list;
@@ -339,7 +328,6 @@
 	nf_bridge_put(skb->nf_bridge);
 #endif
 #endif
-	skb_headerinit(skb, NULL, 0);  /* clean state */
 	kfree_skbmem(skb);
 }
 
@@ -1261,7 +1249,7 @@
 					      sizeof(struct sk_buff),
 					      0,
 					      SLAB_HWCACHE_ALIGN,
-					      skb_headerinit, NULL);
+					      NULL, NULL);
 	if (!skbuff_head_cache)
 		panic("cannot create skbuff cache");
 
diff -Nru a/net/core/sock.c b/net/core/sock.c
--- a/net/core/sock.c	Fri Oct 18 17:45:16 2002
+++ b/net/core/sock.c	Sat Mar  8 11:39:01 2003
@@ -153,6 +153,12 @@
 	return 0;
 }
 
+static void sock_warn_obsolete_bsdism(const char *name)
+{
+	printk(KERN_WARNING "process `%s' is using obsolete "
+	       "%s SO_BSDCOMPAT\n", current->comm, name);
+}
+
 /*
  *	This is meant for all protocols to use and covers goings on
  *	at the socket level. Everything here is generic.
@@ -178,7 +184,7 @@
 	switch(optname)
 	{
 		case SO_DONTLINGER:
-			sk->linger=0;
+			__clear_bit(SOCK_LINGER, &sk->flags);
 			return 0;
 	}
 #endif	
@@ -214,7 +220,7 @@
 			sk->localroute=valbool;
 			break;
 		case SO_BROADCAST:
-			sk->broadcast=valbool;
+			sock_valbool_flag(sk, SOCK_BROADCAST, valbool);
 			break;
 		case SO_SNDBUF:
 			/* Don't error on this BSD doesn't and if you think
@@ -262,11 +268,11 @@
 				tcp_set_keepalive(sk, valbool);
 			}
 #endif
-			sk->keepopen = valbool;
+			sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool);
 			break;
 
 	 	case SO_OOBINLINE:
-			sk->urginline = valbool;
+			sock_valbool_flag(sk, SOCK_URGINLINE, valbool);
 			break;
 
 	 	case SO_NO_CHECK:
@@ -290,7 +296,7 @@
 				break;
 			}
 			if(ling.l_onoff==0) {
-				sk->linger=0;
+				__clear_bit(SOCK_LINGER, &sk->flags);
 			} else {
 #if (BITS_PER_LONG == 32)
 				if (ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ)
@@ -298,12 +304,12 @@
 				else
 #endif
 					sk->lingertime=ling.l_linger*HZ;
-				sk->linger=1;
+				__set_bit(SOCK_LINGER, &sk->flags);
 			}
 			break;
 
 		case SO_BSDCOMPAT:
-			sk->bsdism = valbool;
+			sock_warn_obsolete_bsdism("setsockopt");
 			break;
 
 		case SO_PASSCRED:
@@ -443,7 +449,7 @@
 			break;
 		
 		case SO_BROADCAST:
-			v.val= sk->broadcast;
+			v.val= test_bit(SOCK_BROADCAST, &sk->flags);
 			break;
 
 		case SO_SNDBUF:
@@ -459,7 +465,7 @@
 			break;
 
 		case SO_KEEPALIVE:
-			v.val = sk->keepopen;
+			v.val = test_bit(SOCK_KEEPOPEN, &sk->flags);
 			break;
 
 		case SO_TYPE:
@@ -473,7 +479,7 @@
 			break;
 
 		case SO_OOBINLINE:
-			v.val = sk->urginline;
+			v.val = test_bit(SOCK_URGINLINE, &sk->flags);
 			break;
 	
 		case SO_NO_CHECK:
@@ -486,12 +492,12 @@
 		
 		case SO_LINGER:	
 			lv=sizeof(v.ling);
-			v.ling.l_onoff=sk->linger;
+			v.ling.l_onoff = test_bit(SOCK_LINGER, &sk->flags);
  			v.ling.l_linger=sk->lingertime/HZ;
 			break;
 					
 		case SO_BSDCOMPAT:
-			v.val = sk->bsdism;
+			sock_warn_obsolete_bsdism("getsockopt");
 			break;
 
 		case SO_TIMESTAMP:
@@ -806,6 +812,7 @@
 					page = alloc_pages(sk->allocation, 0);
 					if (!page) {
 						err = -ENOBUFS;
+						skb_shinfo(skb)->nr_frags = i;
 						kfree_skb(skb);
 						goto failure;
 					}
@@ -960,13 +967,13 @@
 }
 
 int sock_no_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-		    int flags, struct scm_cookie *scm)
+		    int flags)
 {
 	return -EOPNOTSUPP;
 }
 
 int sock_no_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-		    int len, int flags, struct scm_cookie *scm)
+		    int len, int flags)
 {
 	return -EOPNOTSUPP;
 }
diff -Nru a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
--- a/net/decnet/af_decnet.c	Fri Oct 25 14:52:23 2002
+++ b/net/decnet/af_decnet.c	Thu Mar  6 11:06:44 2003
@@ -1718,7 +1718,7 @@
 
 
 static int dn_recvmsg(struct kiocb *iocb, struct socket *sock,
-	struct msghdr *msg, int size, int flags, struct scm_cookie *scm)
+	struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct dn_scp *scp = DN_SK(sk);
@@ -1889,7 +1889,7 @@
 }
 
 static int dn_sendmsg(struct kiocb *iocb, struct socket *sock,
-	   struct msghdr *msg, int size, struct scm_cookie *scm)
+	   struct msghdr *msg, int size)
 {
 	struct sock *sk = sock->sk;
 	struct dn_scp *scp = DN_SK(sk);
diff -Nru a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
--- a/net/decnet/dn_nsp_in.c	Fri Feb  7 01:48:38 2003
+++ b/net/decnet/dn_nsp_in.c	Mon Mar  3 04:56:53 2003
@@ -118,7 +118,7 @@
 			break;
 	}
 
-	if (wakeup && !sk->dead)
+	if (wakeup && !test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 }
 
@@ -367,7 +367,7 @@
 			}
 		}
                 dn_nsp_send_link(sk, DN_NOCHANGE, 0);
-                if (!sk->dead)
+                if (!test_bit(SOCK_DEAD, &sk->flags))
                 	sk->state_change(sk);
         }
 
@@ -428,7 +428,7 @@
 			break;
 	}
 
-	if (!sk->dead) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		if (sk->socket->state != SS_UNCONNECTED)
 			sk->socket->state = SS_DISCONNECTING;
 		sk->state_change(sk);
@@ -477,7 +477,7 @@
 			scp->state = DN_CN;
 	}
 
-	if (!sk->dead) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		if (sk->socket->state != SS_UNCONNECTED)
 			sk->socket->state = SS_DISCONNECTING;
 		sk->state_change(sk);
@@ -549,7 +549,7 @@
 			}
 			break;
                 }
-		if (wake_up && !sk->dead)
+		if (wake_up && !test_bit(SOCK_DEAD, &sk->flags))
 			sk->state_change(sk);
         }
 
@@ -587,7 +587,7 @@
 	 * Therefore the plain read_lock is ok here. -DaveM
 	 */
 	read_lock(&sk->callback_lock);
-        if (!sk->dead) {
+        if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		struct socket *sock = sk->socket;
 		wake_up_interruptible(sk->sleep);
 		if (sock && sock->fasync_list &&
@@ -671,7 +671,7 @@
 	if (scp->state == DN_CI) {
 		scp->state = DN_NC;
 		sk->state = TCP_CLOSE;
-		if (!sk->dead)
+		if (!test_bit(SOCK_DEAD, &sk->flags))
 			sk->state_change(sk);
 	}
 
@@ -861,7 +861,7 @@
 		int other = 1;
 
 		/* both data and ack frames can kick a CC socket into RUN */
-		if ((scp->state == DN_CC) && !sk->dead) {
+		if ((scp->state == DN_CC) && !test_bit(SOCK_DEAD, &sk->flags)) {
 			scp->state = DN_RUN;
 			sk->state = TCP_ESTABLISHED;
 			sk->state_change(sk);
diff -Nru a/net/econet/af_econet.c b/net/econet/af_econet.c
--- a/net/econet/af_econet.c	Tue Feb 11 03:38:22 2003
+++ b/net/econet/af_econet.c	Thu Mar  6 11:06:44 2003
@@ -126,8 +126,7 @@
  */
 
 static int econet_recvmsg(struct kiocb *iocb, struct socket *sock,
-			  struct msghdr *msg, int len, int flags,
-			  struct scm_cookie *scm)
+			  struct msghdr *msg, int len, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb;
@@ -260,7 +259,7 @@
  */
 
 static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
-			  struct msghdr *msg, int len, struct scm_cookie *scm)
+			  struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_ec *saddr=(struct sockaddr_ec *)msg->msg_name;
@@ -533,7 +532,7 @@
 
 	sock->sk = NULL;
 	sk->socket = NULL;
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 
 	/* Purge queues */
 
diff -Nru a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
--- a/net/ipv4/af_inet.c	Wed Feb 19 23:27:40 2003
+++ b/net/ipv4/af_inet.c	Thu Mar  6 11:06:44 2003
@@ -146,7 +146,7 @@
 		       sk);
 		return;
 	}
-	if (!sk->dead) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		printk("Attempt to release alive inet socket %p\n", sk);
 		return;
 	}
@@ -454,7 +454,8 @@
 		 * linger..
 		 */
 		timeout = 0;
-		if (sk->linger && !(current->flags & PF_EXITING))
+		if (test_bit(SOCK_LINGER, &sk->flags) &&
+				!(current->flags & PF_EXITING))
 			timeout = sk->lingertime;
 		sock->sk = NULL;
 		sk->prot->close(sk, timeout);
@@ -730,7 +731,7 @@
 
 
 int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
-		 int size, int flags, struct scm_cookie *scm)
+		 int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	int addr_len = 0;
@@ -745,7 +746,7 @@
 
 
 int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
-		 int size, struct scm_cookie *scm)
+		 int size)
 {
 	struct sock *sk = sock->sk;
 
diff -Nru a/net/ipv4/ah.c b/net/ipv4/ah.c
--- a/net/ipv4/ah.c	Sun Feb  2 23:19:14 2003
+++ b/net/ipv4/ah.c	Thu Mar  6 16:16:15 2003
@@ -2,30 +2,14 @@
 #include <linux/module.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
+#include <net/ah.h>
 #include <linux/crypto.h>
 #include <linux/pfkeyv2.h>
 #include <net/icmp.h>
 #include <asm/scatterlist.h>
 
-#define AH_HLEN_NOICV	12
-
-typedef void (icv_update_fn_t)(struct crypto_tfm *,
-                               struct scatterlist *, unsigned int);
-
-struct ah_data
-{
-	u8			*key;
-	int			key_len;
-	u8			*work_icv;
-	int			icv_full_len;
-	int			icv_trunc_len;
-
-	void			(*icv)(struct ah_data*,
-	                               struct sk_buff *skb, u8 *icv);
-
-	struct crypto_tfm	*tfm;
-};
 
+#define AH_HLEN_NOICV	12
 
 /* Clear mutable options and find final destination to substitute
  * into IP header for icv calculation. Options are already checked
@@ -71,92 +55,6 @@
 	return 0;
 }
 
-static void skb_ah_walk(const struct sk_buff *skb,
-                        struct crypto_tfm *tfm, icv_update_fn_t icv_update)
-{
-	int offset = 0;
-	int len = skb->len;
-	int start = skb->len - skb->data_len;
-	int i, copy = start - offset;
-	struct scatterlist sg;
-
-	/* Checksum header. */
-	if (copy > 0) {
-		if (copy > len)
-			copy = len;
-		
-		sg.page = virt_to_page(skb->data + offset);
-		sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
-		sg.length = copy;
-		
-		icv_update(tfm, &sg, 1);
-		
-		if ((len -= copy) == 0)
-			return;
-		offset += copy;
-	}
-
-	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-		int end;
-
-		BUG_TRAP(start <= offset + len);
-
-		end = start + skb_shinfo(skb)->frags[i].size;
-		if ((copy = end - offset) > 0) {
-			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
-			if (copy > len)
-				copy = len;
-			
-			sg.page = frag->page;
-			sg.offset = frag->page_offset + offset-start;
-			sg.length = copy;
-			
-			icv_update(tfm, &sg, 1);
-			
-			if (!(len -= copy))
-				return;
-			offset += copy;
-		}
-		start = end;
-	}
-
-	if (skb_shinfo(skb)->frag_list) {
-		struct sk_buff *list = skb_shinfo(skb)->frag_list;
-
-		for (; list; list = list->next) {
-			int end;
-
-			BUG_TRAP(start <= offset + len);
-
-			end = start + list->len;
-			if ((copy = end - offset) > 0) {
-				if (copy > len)
-					copy = len;
-				skb_ah_walk(list, tfm, icv_update);
-				if ((len -= copy) == 0)
-					return;
-				offset += copy;
-			}
-			start = end;
-		}
-	}
-	if (len)
-		BUG();
-}
-
-static void
-ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data)
-{
-	struct crypto_tfm *tfm = ahp->tfm;
-
-	memset(auth_data, 0, ahp->icv_trunc_len);
- 	crypto_hmac_init(tfm, ahp->key, &ahp->key_len);
-  	skb_ah_walk(skb, tfm, crypto_hmac_update);
-	crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_icv);
-	memcpy(auth_data, ahp->work_icv, ahp->icv_trunc_len);
-}
-
 static int ah_output(struct sk_buff *skb)
 {
 	int err;
@@ -330,7 +228,7 @@
 	    skb->h.icmph->code != ICMP_FRAG_NEEDED)
 		return;
 
-	x = xfrm_state_lookup(iph->daddr, ah->spi, IPPROTO_AH);
+	x = xfrm4_state_lookup(iph->daddr, ah->spi, IPPROTO_AH);
 	if (!x)
 		return;
 	printk(KERN_DEBUG "pmtu discvovery on SA AH/%08x/%08x\n",
diff -Nru a/net/ipv4/esp.c b/net/ipv4/esp.c
--- a/net/ipv4/esp.c	Mon Mar  3 01:45:23 2003
+++ b/net/ipv4/esp.c	Thu Mar  6 16:16:15 2003
@@ -2,318 +2,15 @@
 #include <linux/module.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
+#include <net/esp.h>
 #include <asm/scatterlist.h>
 #include <linux/crypto.h>
 #include <linux/pfkeyv2.h>
 #include <linux/random.h>
 #include <net/icmp.h>
 
-#define MAX_SG_ONSTACK 4
-
-typedef void (icv_update_fn_t)(struct crypto_tfm *,
-                               struct scatterlist *, unsigned int);
-
-/* BUGS:
- * - we assume replay seqno is always present.
- */
-
-struct esp_data
-{
-	/* Confidentiality */
-	struct {
-		u8			*key;		/* Key */
-		int			key_len;	/* Key length */
-		u8			*ivec;		/* ivec buffer */
-		/* ivlen is offset from enc_data, where encrypted data start.
-		 * It is logically different of crypto_tfm_alg_ivsize(tfm).
-		 * We assume that it is either zero (no ivec), or
-		 * >= crypto_tfm_alg_ivsize(tfm). */
-		int			ivlen;
-		int			padlen;		/* 0..255 */
-		struct crypto_tfm	*tfm;		/* crypto handle */
-	} conf;
-
-	/* Integrity. It is active when icv_full_len != 0 */
-	struct {
-		u8			*key;		/* Key */
-		int			key_len;	/* Length of the key */
-		u8			*work_icv;
-		int			icv_full_len;
-		int			icv_trunc_len;
-		void			(*icv)(struct esp_data*,
-		                               struct sk_buff *skb,
-		                               int offset, int len, u8 *icv);
-		struct crypto_tfm	*tfm;
-	} auth;
-};
-
-/* Move to common area: it is shared with AH. */
-
-void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
-		  int offset, int len, icv_update_fn_t icv_update)
-{
-	int start = skb->len - skb->data_len;
-	int i, copy = start - offset;
-	struct scatterlist sg;
-
-	/* Checksum header. */
-	if (copy > 0) {
-		if (copy > len)
-			copy = len;
-		
-		sg.page = virt_to_page(skb->data + offset);
-		sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
-		sg.length = copy;
-		
-		icv_update(tfm, &sg, 1);
-		
-		if ((len -= copy) == 0)
-			return;
-		offset += copy;
-	}
-
-	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-		int end;
-
-		BUG_TRAP(start <= offset + len);
-
-		end = start + skb_shinfo(skb)->frags[i].size;
-		if ((copy = end - offset) > 0) {
-			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
-			if (copy > len)
-				copy = len;
-			
-			sg.page = frag->page;
-			sg.offset = frag->page_offset + offset-start;
-			sg.length = copy;
-			
-			icv_update(tfm, &sg, 1);
-
-			if (!(len -= copy))
-				return;
-			offset += copy;
-		}
-		start = end;
-	}
-
-	if (skb_shinfo(skb)->frag_list) {
-		struct sk_buff *list = skb_shinfo(skb)->frag_list;
-
-		for (; list; list = list->next) {
-			int end;
-
-			BUG_TRAP(start <= offset + len);
-
-			end = start + list->len;
-			if ((copy = end - offset) > 0) {
-				if (copy > len)
-					copy = len;
-				skb_icv_walk(list, tfm, offset-start, copy, icv_update);
-				if ((len -= copy) == 0)
-					return;
-				offset += copy;
-			}
-			start = end;
-		}
-	}
-	if (len)
-		BUG();
-}
-
-
-/* Looking generic it is not used in another places. */
-
-int
-skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
-{
-	int start = skb->len - skb->data_len;
-	int i, copy = start - offset;
-	int elt = 0;
-
-	if (copy > 0) {
-		if (copy > len)
-			copy = len;
-		sg[elt].page = virt_to_page(skb->data + offset);
-		sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
-		sg[elt].length = copy;
-		elt++;
-		if ((len -= copy) == 0)
-			return elt;
-		offset += copy;
-	}
-
-	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-		int end;
-
-		BUG_TRAP(start <= offset + len);
-
-		end = start + skb_shinfo(skb)->frags[i].size;
-		if ((copy = end - offset) > 0) {
-			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
-			if (copy > len)
-				copy = len;
-			sg[elt].page = frag->page;
-			sg[elt].offset = frag->page_offset+offset-start;
-			sg[elt].length = copy;
-			elt++;
-			if (!(len -= copy))
-				return elt;
-			offset += copy;
-		}
-		start = end;
-	}
 
-	if (skb_shinfo(skb)->frag_list) {
-		struct sk_buff *list = skb_shinfo(skb)->frag_list;
-
-		for (; list; list = list->next) {
-			int end;
-
-			BUG_TRAP(start <= offset + len);
-
-			end = start + list->len;
-			if ((copy = end - offset) > 0) {
-				if (copy > len)
-					copy = len;
-				elt += skb_to_sgvec(list, sg+elt, offset - start, copy);
-				if ((len -= copy) == 0)
-					return elt;
-				offset += copy;
-			}
-			start = end;
-		}
-	}
-	if (len)
-		BUG();
-	return elt;
-}
-
-/* Common with AH after some work on arguments. */
-
-static void
-esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset,
-		int len, u8 *auth_data)
-{
-	struct crypto_tfm *tfm = esp->auth.tfm;
-	char *icv = esp->auth.work_icv;
-
-	memset(auth_data, 0, esp->auth.icv_trunc_len);
- 	crypto_hmac_init(tfm, esp->auth.key, &esp->auth.key_len);
-	skb_icv_walk(skb, tfm, offset, len, crypto_hmac_update);
-	crypto_hmac_final(tfm, esp->auth.key, &esp->auth.key_len, icv);
-	memcpy(auth_data, icv, esp->auth.icv_trunc_len);
-}
-
-/* Check that skb data bits are writable. If they are not, copy data
- * to newly created private area. If "tailbits" is given, make sure that
- * tailbits bytes beyond current end of skb are writable.
- *
- * Returns amount of elements of scatterlist to load for subsequent
- * transformations and pointer to writable trailer skb.
- */
-
-int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
-{
-	int copyflag;
-	int elt;
-	struct sk_buff *skb1, **skb_p;
-
-	/* If skb is cloned or its head is paged, reallocate
-	 * head pulling out all the pages (pages are considered not writable
-	 * at the moment even if they are anonymous).
-	 */
-	if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) &&
-	    __pskb_pull_tail(skb, skb_pagelen(skb)-skb_headlen(skb)) == NULL)
-		return -ENOMEM;
-
-	/* Easy case. Most of packets will go this way. */
-	if (!skb_shinfo(skb)->frag_list) {
-		/* A little of trouble, not enough of space for trailer.
-		 * This should not happen, when stack is tuned to generate
-		 * good frames. OK, on miss we reallocate and reserve even more
-		 * space, 128 bytes is fair. */
-
-		if (skb_tailroom(skb) < tailbits &&
-		    pskb_expand_head(skb, 0, tailbits-skb_tailroom(skb)+128, GFP_ATOMIC))
-			return -ENOMEM;
-
-		/* Voila! */
-		*trailer = skb;
-		return 1;
-	}
-
-	/* Misery. We are in troubles, going to mincer fragments... */
-
-	elt = 1;
-	skb_p = &skb_shinfo(skb)->frag_list;
-	copyflag = 0;
-
-	while ((skb1 = *skb_p) != NULL) {
-		int ntail = 0;
-
-		/* The fragment is partially pulled by someone,
-		 * this can happen on input. Copy it and everything
-		 * after it. */
-
-		if (skb_shared(skb1))
-			copyflag = 1;
-
-		/* If the skb is the last, worry about trailer. */
-
-		if (skb1->next == NULL && tailbits) {
-			if (skb_shinfo(skb1)->nr_frags ||
-			    skb_shinfo(skb1)->frag_list ||
-			    skb_tailroom(skb1) < tailbits)
-				ntail = tailbits + 128;
-		}
-
-		if (copyflag ||
-		    skb_cloned(skb1) ||
-		    ntail ||
-		    skb_shinfo(skb1)->nr_frags ||
-		    skb_shinfo(skb1)->frag_list) {
-			struct sk_buff *skb2;
-
-			/* Fuck, we are miserable poor guys... */
-			if (ntail == 0)
-				skb2 = skb_copy(skb1, GFP_ATOMIC);
-			else
-				skb2 = skb_copy_expand(skb1,
-						       skb_headroom(skb1),
-						       ntail,
-						       GFP_ATOMIC);
-			if (unlikely(skb2 == NULL))
-				return -ENOMEM;
-
-			if (skb1->sk)
-				skb_set_owner_w(skb, skb1->sk);
-
-			/* Looking around. Are we still alive?
-			 * OK, link new skb, drop old one */
-
-			skb2->next = skb1->next;
-			*skb_p = skb2;
-			kfree_skb(skb1);
-			skb1 = skb2;
-		}
-		elt++;
-		*trailer = skb1;
-		skb_p = &skb1->next;
-	}
-
-	return elt;
-}
-
-void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len)
-{
-	if (tail != skb) {
-		skb->data_len += len;
-		skb->len += len;
-	}
-	return skb_put(tail, len);
-}
+#define MAX_SG_ONSTACK 4
 
 int esp_output(struct sk_buff *skb)
 {
@@ -575,7 +272,7 @@
 	    skb->h.icmph->code != ICMP_FRAG_NEEDED)
 		return;
 
-	x = xfrm_state_lookup(iph->daddr, esph->spi, IPPROTO_ESP);
+	x = xfrm4_state_lookup(iph->daddr, esph->spi, IPPROTO_ESP);
 	if (!x)
 		return;
 	printk(KERN_DEBUG "pmtu discvovery on SA ESP/%08x/%08x\n",
diff -Nru a/net/ipv4/icmp.c b/net/ipv4/icmp.c
--- a/net/ipv4/icmp.c	Mon Feb 24 03:18:25 2003
+++ b/net/ipv4/icmp.c	Thu Mar  6 16:30:30 2003
@@ -116,7 +116,7 @@
 DEFINE_SNMP_STAT(struct icmp_mib, icmp_statistics);
 
 /* An array of errno for error messages from dest unreach. */
-/* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOS_UNREACH and SR_FAIELD MUST be considered 'transient errs'. */
+/* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOST_UNREACH and SR_FAILED MUST be considered 'transient errs'. */
 
 struct icmp_err icmp_err_convert[] = {
 	{
diff -Nru a/net/ipv4/igmp.c b/net/ipv4/igmp.c
--- a/net/ipv4/igmp.c	Wed Feb 19 13:55:33 2003
+++ b/net/ipv4/igmp.c	Thu Mar  6 09:08:40 2003
@@ -606,7 +606,7 @@
 static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
 {
 	struct flowi fl = { .nl_u = { .ip4_u =
-				      { .daddr = imr->imr_address.s_addr } } };
+				      { .daddr = imr->imr_multiaddr.s_addr } } };
 	struct rtable *rt;
 	struct net_device *dev = NULL;
 	struct in_device *idev = NULL;
diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c
--- a/net/ipv4/raw.c	Sun Jan 12 08:52:15 2003
+++ b/net/ipv4/raw.c	Mon Mar  3 04:56:53 2003
@@ -450,7 +450,8 @@
 		goto done;
 
 	err = -EACCES;
-	if (rt->rt_flags & RTCF_BROADCAST && !sk->broadcast)
+	if (rt->rt_flags & RTCF_BROADCAST &&
+			!test_bit(SOCK_BROADCAST, &sk->flags))
 		goto done;
 
 	if (msg->msg_flags & MSG_CONFIRM)
diff -Nru a/net/ipv4/route.c b/net/ipv4/route.c
--- a/net/ipv4/route.c	Wed Feb 19 23:24:57 2003
+++ b/net/ipv4/route.c	Wed Mar  5 15:45:36 2003
@@ -96,6 +96,7 @@
 #include <net/arp.h>
 #include <net/tcp.h>
 #include <net/icmp.h>
+#include <net/xfrm.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -930,7 +931,7 @@
 				    rth->u.dst.dev != dev)
 					break;
 
-				dst_clone(&rth->u.dst);
+				dst_hold(&rth->u.dst);
 				rcu_read_unlock();
 
 				rt = dst_alloc(&ipv4_dst_ops);
@@ -2599,6 +2600,13 @@
 #endif /* CONFIG_PROC_FS */
 #endif /* CONFIG_NET_CLS_ROUTE */
 
+int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
+{
+        int err = 0;
+        err = __ip_route_output_key((struct rtable**)dst, fl);
+        return err;
+}
+
 int __init ip_rt_init(void)
 {
 	int i, order, goal, rc = 0;
@@ -2680,6 +2688,7 @@
 					ip_rt_gc_interval;
 	add_timer(&rt_periodic_timer);
 
+	xfrm_dst_lookup_register(xfrm_dst_lookup, AF_INET);
 #ifdef CONFIG_PROC_FS
 	if (rt_cache_proc_init())
 		goto out_enomem;
diff -Nru a/net/ipv4/tcp.c b/net/ipv4/tcp.c
--- a/net/ipv4/tcp.c	Tue Feb 25 11:05:23 2003
+++ b/net/ipv4/tcp.c	Mon Mar  3 04:56:53 2003
@@ -441,7 +441,7 @@
 		if ((tp->rcv_nxt != tp->copied_seq) &&
 		    (tp->urg_seq != tp->copied_seq ||
 		     tp->rcv_nxt != tp->copied_seq + 1 ||
-		     sk->urginline || !tp->urg_data))
+		     test_bit(SOCK_URGINLINE, &sk->flags) || !tp->urg_data))
 			mask |= POLLIN | POLLRDNORM;
 
 		if (!(sk->shutdown & SEND_SHUTDOWN)) {
@@ -497,7 +497,8 @@
 		lock_sock(sk);
 		if ((1 << sk->state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))
 			answ = 0;
-		else if (sk->urginline || !tp->urg_data ||
+		else if (test_bit(SOCK_URGINLINE, &sk->flags) ||
+			 !tp->urg_data ||
 			 before(tp->urg_seq, tp->copied_seq) ||
 			 !before(tp->urg_seq, tp->rcv_nxt)) {
 			answ = tp->rcv_nxt - tp->copied_seq;
@@ -1254,10 +1255,11 @@
 	struct tcp_opt *tp = tcp_sk(sk);
 
 	/* No URG data to read. */
-	if (sk->urginline || !tp->urg_data || tp->urg_data == TCP_URG_READ)
+	if (test_bit(SOCK_URGINLINE, &sk->flags) || !tp->urg_data ||
+			tp->urg_data == TCP_URG_READ)
 		return -EINVAL;	/* Yes this is right ! */
 
-	if (sk->state == TCP_CLOSE && !sk->done)
+	if (sk->state == TCP_CLOSE && !test_bit(SOCK_DONE, &sk->flags))
 		return -ENOTCONN;
 
 	if (tp->urg_data & TCP_URG_VALID) {
@@ -1588,7 +1590,7 @@
 			    (flags & MSG_PEEK))
 				break;
 		} else {
-			if (sk->done)
+			if (test_bit(SOCK_DONE, &sk->flags))
 				break;
 
 			if (sk->err) {
@@ -1600,7 +1602,7 @@
 				break;
 
 			if (sk->state == TCP_CLOSE) {
-				if (!sk->done) {
+				if (!test_bit(SOCK_DONE, &sk->flags)) {
 					/* This occurs when user tries to read
 					 * from never connected socket.
 					 */
@@ -1713,7 +1715,8 @@
 			u32 urg_offset = tp->urg_seq - *seq;
 			if (urg_offset < used) {
 				if (!urg_offset) {
-					if (!sk->urginline) {
+					if (!test_bit(SOCK_URGINLINE,
+								&sk->flags)) {
 						++*seq;
 						offset++;
 						used--;
@@ -1837,7 +1840,7 @@
 
 /*
  *	Shutdown the sending side of a connection. Much like close except
- *	that we don't receive shut down or set sk->dead.
+ *	that we don't receive shut down or set SOCK_DEAD in sk->flags.
  */
 
 void tcp_shutdown(struct sock *sk, int how)
@@ -1902,7 +1905,7 @@
 void tcp_destroy_sock(struct sock *sk)
 {
 	BUG_TRAP(sk->state == TCP_CLOSE);
-	BUG_TRAP(sk->dead);
+	BUG_TRAP(test_bit(SOCK_DEAD, &sk->flags));
 
 	/* It cannot be in hash table! */
 	BUG_TRAP(!sk->pprev);
@@ -1979,7 +1982,7 @@
 		NET_INC_STATS_USER(TCPAbortOnClose);
 		tcp_set_state(sk, TCP_CLOSE);
 		tcp_send_active_reset(sk, GFP_KERNEL);
-	} else if (sk->linger && !sk->lingertime) {
+	} else if (test_bit(SOCK_LINGER, &sk->flags) && !sk->lingertime) {
 		/* Check zero linger _after_ checking for unread data. */
 		sk->prot->disconnect(sk, 0);
 		NET_INC_STATS_USER(TCPAbortOnData);
@@ -2157,7 +2160,7 @@
 	}
 
 	sk->shutdown = 0;
-	sk->done = 0;
+	__clear_bit(SOCK_DONE, &sk->flags);
 	tp->srtt = 0;
 	if ((tp->write_seq += tp->max_window + 2) == 0)
 		tp->write_seq = 1;
@@ -2358,7 +2361,7 @@
 			err = -EINVAL;
 		else {
 			tp->keepalive_time = val * HZ;
-			if (sk->keepopen &&
+			if (test_bit(SOCK_KEEPOPEN, &sk->flags) &&
 			    !((1 << sk->state) & (TCPF_CLOSE | TCPF_LISTEN))) {
 				__u32 elapsed = tcp_time_stamp - tp->rcv_tstamp;
 				if (tp->keepalive_time > elapsed)
diff -Nru a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
--- a/net/ipv4/tcp_input.c	Wed Jan  8 01:03:24 2003
+++ b/net/ipv4/tcp_input.c	Mon Mar  3 04:56:53 2003
@@ -2352,7 +2352,7 @@
 			sk->err = ECONNRESET;
 	}
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->error_report(sk);
 
 	tcp_done(sk);
@@ -2379,7 +2379,7 @@
 	tcp_schedule_ack(tp);
 
 	sk->shutdown |= RCV_SHUTDOWN;
-	sk->done = 1;
+	__clear_bit(SOCK_DONE, &sk->flags);
 
 	switch(sk->state) {
 		case TCP_SYN_RECV:
@@ -2428,7 +2428,7 @@
 		tcp_sack_reset(tp);
 	tcp_mem_reclaim(sk);
 
-	if (!sk->dead) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		sk->state_change(sk);
 
 		/* Do not send POLL_HUP for half duplex close. */
@@ -2745,7 +2745,7 @@
 
 		if (eaten > 0) {
 			__kfree_skb(skb);
-		} else if (!sk->dead)
+		} else if (!test_bit(SOCK_DEAD, &sk->flags))
 			sk->data_ready(sk, 0);
 		return;
 	}
@@ -3247,7 +3247,7 @@
 	 * buggy users.
 	 */
 	if (tp->urg_seq == tp->copied_seq && tp->urg_data &&
-	    !sk->urginline &&
+	    !test_bit(SOCK_URGINLINE, &sk->flags) &&
 	    tp->copied_seq != tp->rcv_nxt) {
 		struct sk_buff *skb = skb_peek(&sk->receive_queue);
 		tp->copied_seq++;
@@ -3284,7 +3284,7 @@
 			if (skb_copy_bits(skb, ptr, &tmp, 1))
 				BUG();
 			tp->urg_data = TCP_URG_VALID | tmp;
-			if (!sk->dead)
+			if (!test_bit(SOCK_DEAD, &sk->flags))
 				sk->data_ready(sk,0);
 		}
 	}
@@ -3699,7 +3699,7 @@
 		tcp_init_metrics(sk);
 		tcp_init_buffer_space(sk);
 
-		if (sk->keepopen)
+		if (test_bit(SOCK_KEEPOPEN, &sk->flags))
 			tcp_reset_keepalive_timer(sk, keepalive_time_when(tp));
 
 		if (!tp->snd_wscale)
@@ -3714,7 +3714,7 @@
 		mb();
 		tcp_set_state(sk, TCP_ESTABLISHED);
 
-		if(!sk->dead) {
+		if(!test_bit(SOCK_DEAD, &sk->flags)) {
 			sk->state_change(sk);
 			sk_wake_async(sk, 0, POLL_OUT);
 		}
@@ -3977,7 +3977,7 @@
 				sk->shutdown |= SEND_SHUTDOWN;
 				dst_confirm(sk->dst_cache);
 
-				if (!sk->dead) {
+				if (!test_bit(SOCK_DEAD, &sk->flags)) {
 					/* Wake up lingering close() */
 					sk->state_change(sk);
 				} else {
diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
--- a/net/ipv4/tcp_ipv4.c	Fri Feb  7 01:48:38 2003
+++ b/net/ipv4/tcp_ipv4.c	Sat Mar  8 11:37:51 2003
@@ -142,6 +142,17 @@
 	return tb;
 }
 
+/* Caller must hold hashbucket lock for this tb with local BH disabled */
+void tcp_bucket_destroy(struct tcp_bind_bucket *tb)
+{
+	if (!tb->owners) {
+		if (tb->next)
+			tb->next->pprev = tb->pprev;
+		*(tb->pprev) = tb->next;
+		kmem_cache_free(tcp_bucket_cachep, tb);
+	}
+}
+
 /* Caller must disable local BH processing. */
 static __inline__ void __tcp_inherit_port(struct sock *sk, struct sock *child)
 {
@@ -300,12 +311,7 @@
 	*(sk->bind_pprev) = sk->bind_next;
 	sk->prev  = NULL;
 	inet->num = 0;
-	if (!tb->owners) {
-		if (tb->next)
-			tb->next->pprev = tb->pprev;
-		*(tb->pprev) = tb->next;
-		kmem_cache_free(tcp_bucket_cachep, tb);
-	}
+	tcp_bucket_destroy(tb);
 	spin_unlock(&head->lock);
 }
 
diff -Nru a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
--- a/net/ipv4/tcp_minisocks.c	Thu Jan 30 23:22:09 2003
+++ b/net/ipv4/tcp_minisocks.c	Sat Mar  8 11:37:51 2003
@@ -81,12 +81,7 @@
 		tw->bind_next->bind_pprev = tw->bind_pprev;
 	*(tw->bind_pprev) = tw->bind_next;
 	tw->tb = NULL;
-	if (tb->owners == NULL) {
-		if (tb->next)
-			tb->next->pprev = tb->pprev;
-		*(tb->pprev) = tb->next;
-		kmem_cache_free(tcp_bucket_cachep, tb);
-	}
+	tcp_bucket_destroy(tb);
 	spin_unlock(&bhead->lock);
 
 #ifdef INET_REFCNT_DEBUG
@@ -676,7 +671,7 @@
 		newsk->wmem_queued = 0;
 		newsk->forward_alloc = 0;
 
-		newsk->done = 0;
+		__clear_bit(SOCK_DONE, &newsk->flags);
 		newsk->userlocks = sk->userlocks & ~SOCK_BINDPORT_LOCK;
 		newsk->backlog.head = newsk->backlog.tail = NULL;
 		newsk->callback_lock = RW_LOCK_UNLOCKED;
@@ -761,7 +756,7 @@
 #endif
 		atomic_inc(&tcp_sockets_allocated);
 
-		if (newsk->keepopen)
+		if (test_bit(SOCK_KEEPOPEN, &newsk->flags))
 			tcp_reset_keepalive_timer(newsk, keepalive_time_when(newtp));
 		newsk->socket = NULL;
 		newsk->sleep = NULL;
diff -Nru a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
--- a/net/ipv4/tcp_output.c	Tue Feb 11 22:36:47 2003
+++ b/net/ipv4/tcp_output.c	Mon Mar  3 04:56:53 2003
@@ -1276,7 +1276,7 @@
 	tp->rcv_ssthresh = tp->rcv_wnd;
 
 	sk->err = 0;
-	sk->done = 0;
+	__clear_bit(SOCK_DONE, &sk->flags);
 	tp->snd_wnd = 0;
 	tcp_init_wl(tp, tp->write_seq, 0);
 	tp->snd_una = tp->write_seq;
diff -Nru a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
--- a/net/ipv4/tcp_timer.c	Tue Jan  7 02:19:05 2003
+++ b/net/ipv4/tcp_timer.c	Mon Mar  3 04:56:53 2003
@@ -189,7 +189,7 @@
 		}
 
 		retry_until = sysctl_tcp_retries2;
-		if (sk->dead) {
+		if (test_bit(SOCK_DEAD, &sk->flags)) {
 			int alive = (tp->rto < TCP_RTO_MAX);
  
 			retry_until = tcp_orphan_retries(sk, alive);
@@ -297,7 +297,7 @@
 	 */
 	max_probes = sysctl_tcp_retries2;
 
-	if (sk->dead) {
+	if (test_bit(SOCK_DEAD, &sk->flags)) {
 		int alive = ((tp->rto<<tp->backoff) < TCP_RTO_MAX);
  
 		max_probes = tcp_orphan_retries(sk, alive);
@@ -327,7 +327,7 @@
 
 	BUG_TRAP(!skb_queue_empty(&sk->write_queue));
 
-	if (tp->snd_wnd == 0 && !sk->dead &&
+	if (tp->snd_wnd == 0 && !test_bit(SOCK_DEAD, &sk->flags) &&
 	    !((1<<sk->state)&(TCPF_SYN_SENT|TCPF_SYN_RECV))) {
 		/* Receiver dastardly shrinks window. Our retransmits
 		 * become zero probes, but we should not timeout this
@@ -571,7 +571,7 @@
 	if ((1<<sk->state)&(TCPF_CLOSE|TCPF_LISTEN))
 		return;
 
-	if (val && !sk->keepopen)
+	if (val && !test_bit(SOCK_KEEPOPEN, &sk->flags))
 		tcp_reset_keepalive_timer(sk, keepalive_time_when(tcp_sk(sk)));
 	else if (!val)
 		tcp_delete_keepalive_timer(sk);
@@ -597,7 +597,7 @@
 		goto out;
 	}
 
-	if (sk->state == TCP_FIN_WAIT2 && sk->dead) {
+	if (sk->state == TCP_FIN_WAIT2 && test_bit(SOCK_DEAD, &sk->flags)) {
 		if (tp->linger2 >= 0) {
 			int tmo = tcp_fin_time(tp) - TCP_TIMEWAIT_LEN;
 
@@ -610,7 +610,7 @@
 		goto death;
 	}
 
-	if (!sk->keepopen || sk->state == TCP_CLOSE)
+	if (!test_bit(SOCK_KEEPOPEN, &sk->flags) || sk->state == TCP_CLOSE)
 		goto out;
 
 	elapsed = keepalive_time_when(tp);
diff -Nru a/net/ipv4/udp.c b/net/ipv4/udp.c
--- a/net/ipv4/udp.c	Tue Jan  7 02:19:05 2003
+++ b/net/ipv4/udp.c	Mon Mar  3 04:56:53 2003
@@ -606,7 +606,8 @@
 			goto out;
 
 		err = -EACCES;
-		if (rt->rt_flags&RTCF_BROADCAST && !sk->broadcast) 
+		if (rt->rt_flags&RTCF_BROADCAST &&
+				!test_bit(SOCK_BROADCAST, &sk->flags))
 			goto out;
 		if (connected)
 			sk_dst_set(sk, dst_clone(&rt->u.dst));
@@ -887,7 +888,8 @@
 			       inet->sport, usin->sin_port, sk);
 	if (err)
 		return err;
-	if ((rt->rt_flags&RTCF_BROADCAST) && !sk->broadcast) {
+	if ((rt->rt_flags&RTCF_BROADCAST) &&
+			!test_bit(SOCK_BROADCAST, &sk->flags)) {
 		ip_rt_put(rt);
 		return -EACCES;
 	}
diff -Nru a/net/ipv4/xfrm_algo.c b/net/ipv4/xfrm_algo.c
--- a/net/ipv4/xfrm_algo.c	Thu Jan  9 22:55:54 2003
+++ b/net/ipv4/xfrm_algo.c	Thu Mar  6 16:16:15 2003
@@ -8,9 +8,17 @@
  * Software Foundation; either version 2 of the License, or (at your option) 
  * any later version.
  */
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/pfkeyv2.h>
 #include <net/xfrm.h>
+#if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE)
+#include <net/ah.h>
+#endif
+#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
+#include <net/esp.h>
+#endif
+#include <asm/scatterlist.h>
 
 /*
  * Algorithms supported by IPsec.  These entries contain properties which
@@ -348,3 +356,333 @@
 			n++;
 	return n;
 }
+
+#if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE)
+void skb_ah_walk(const struct sk_buff *skb,
+                        struct crypto_tfm *tfm, icv_update_fn_t icv_update)
+{
+	int offset = 0;
+	int len = skb->len;
+	int start = skb->len - skb->data_len;
+	int i, copy = start - offset;
+	struct scatterlist sg;
+
+	/* Checksum header. */
+	if (copy > 0) {
+		if (copy > len)
+			copy = len;
+		
+		sg.page = virt_to_page(skb->data + offset);
+		sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
+		sg.length = copy;
+		
+		icv_update(tfm, &sg, 1);
+		
+		if ((len -= copy) == 0)
+			return;
+		offset += copy;
+	}
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		int end;
+
+		BUG_TRAP(start <= offset + len);
+
+		end = start + skb_shinfo(skb)->frags[i].size;
+		if ((copy = end - offset) > 0) {
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+			if (copy > len)
+				copy = len;
+			
+			sg.page = frag->page;
+			sg.offset = frag->page_offset + offset-start;
+			sg.length = copy;
+			
+			icv_update(tfm, &sg, 1);
+			
+			if (!(len -= copy))
+				return;
+			offset += copy;
+		}
+		start = end;
+	}
+
+	if (skb_shinfo(skb)->frag_list) {
+		struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+		for (; list; list = list->next) {
+			int end;
+
+			BUG_TRAP(start <= offset + len);
+
+			end = start + list->len;
+			if ((copy = end - offset) > 0) {
+				if (copy > len)
+					copy = len;
+				skb_ah_walk(list, tfm, icv_update);
+				if ((len -= copy) == 0)
+					return;
+				offset += copy;
+			}
+			start = end;
+		}
+	}
+	if (len)
+		BUG();
+}
+#endif
+
+#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
+/* Move to common area: it is shared with AH. */
+
+void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
+		  int offset, int len, icv_update_fn_t icv_update)
+{
+	int start = skb->len - skb->data_len;
+	int i, copy = start - offset;
+	struct scatterlist sg;
+
+	/* Checksum header. */
+	if (copy > 0) {
+		if (copy > len)
+			copy = len;
+		
+		sg.page = virt_to_page(skb->data + offset);
+		sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
+		sg.length = copy;
+		
+		icv_update(tfm, &sg, 1);
+		
+		if ((len -= copy) == 0)
+			return;
+		offset += copy;
+	}
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		int end;
+
+		BUG_TRAP(start <= offset + len);
+
+		end = start + skb_shinfo(skb)->frags[i].size;
+		if ((copy = end - offset) > 0) {
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+			if (copy > len)
+				copy = len;
+			
+			sg.page = frag->page;
+			sg.offset = frag->page_offset + offset-start;
+			sg.length = copy;
+			
+			icv_update(tfm, &sg, 1);
+
+			if (!(len -= copy))
+				return;
+			offset += copy;
+		}
+		start = end;
+	}
+
+	if (skb_shinfo(skb)->frag_list) {
+		struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+		for (; list; list = list->next) {
+			int end;
+
+			BUG_TRAP(start <= offset + len);
+
+			end = start + list->len;
+			if ((copy = end - offset) > 0) {
+				if (copy > len)
+					copy = len;
+				skb_icv_walk(list, tfm, offset-start, copy, icv_update);
+				if ((len -= copy) == 0)
+					return;
+				offset += copy;
+			}
+			start = end;
+		}
+	}
+	if (len)
+		BUG();
+}
+
+
+/* Looking generic it is not used in another places. */
+
+int
+skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
+{
+	int start = skb->len - skb->data_len;
+	int i, copy = start - offset;
+	int elt = 0;
+
+	if (copy > 0) {
+		if (copy > len)
+			copy = len;
+		sg[elt].page = virt_to_page(skb->data + offset);
+		sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE;
+		sg[elt].length = copy;
+		elt++;
+		if ((len -= copy) == 0)
+			return elt;
+		offset += copy;
+	}
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		int end;
+
+		BUG_TRAP(start <= offset + len);
+
+		end = start + skb_shinfo(skb)->frags[i].size;
+		if ((copy = end - offset) > 0) {
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+			if (copy > len)
+				copy = len;
+			sg[elt].page = frag->page;
+			sg[elt].offset = frag->page_offset+offset-start;
+			sg[elt].length = copy;
+			elt++;
+			if (!(len -= copy))
+				return elt;
+			offset += copy;
+		}
+		start = end;
+	}
+
+	if (skb_shinfo(skb)->frag_list) {
+		struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+		for (; list; list = list->next) {
+			int end;
+
+			BUG_TRAP(start <= offset + len);
+
+			end = start + list->len;
+			if ((copy = end - offset) > 0) {
+				if (copy > len)
+					copy = len;
+				elt += skb_to_sgvec(list, sg+elt, offset - start, copy);
+				if ((len -= copy) == 0)
+					return elt;
+				offset += copy;
+			}
+			start = end;
+		}
+	}
+	if (len)
+		BUG();
+	return elt;
+}
+
+/* Check that skb data bits are writable. If they are not, copy data
+ * to newly created private area. If "tailbits" is given, make sure that
+ * tailbits bytes beyond current end of skb are writable.
+ *
+ * Returns amount of elements of scatterlist to load for subsequent
+ * transformations and pointer to writable trailer skb.
+ */
+
+int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
+{
+	int copyflag;
+	int elt;
+	struct sk_buff *skb1, **skb_p;
+
+	/* If skb is cloned or its head is paged, reallocate
+	 * head pulling out all the pages (pages are considered not writable
+	 * at the moment even if they are anonymous).
+	 */
+	if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) &&
+	    __pskb_pull_tail(skb, skb_pagelen(skb)-skb_headlen(skb)) == NULL)
+		return -ENOMEM;
+
+	/* Easy case. Most of packets will go this way. */
+	if (!skb_shinfo(skb)->frag_list) {
+		/* A little of trouble, not enough of space for trailer.
+		 * This should not happen, when stack is tuned to generate
+		 * good frames. OK, on miss we reallocate and reserve even more
+		 * space, 128 bytes is fair. */
+
+		if (skb_tailroom(skb) < tailbits &&
+		    pskb_expand_head(skb, 0, tailbits-skb_tailroom(skb)+128, GFP_ATOMIC))
+			return -ENOMEM;
+
+		/* Voila! */
+		*trailer = skb;
+		return 1;
+	}
+
+	/* Misery. We are in troubles, going to mincer fragments... */
+
+	elt = 1;
+	skb_p = &skb_shinfo(skb)->frag_list;
+	copyflag = 0;
+
+	while ((skb1 = *skb_p) != NULL) {
+		int ntail = 0;
+
+		/* The fragment is partially pulled by someone,
+		 * this can happen on input. Copy it and everything
+		 * after it. */
+
+		if (skb_shared(skb1))
+			copyflag = 1;
+
+		/* If the skb is the last, worry about trailer. */
+
+		if (skb1->next == NULL && tailbits) {
+			if (skb_shinfo(skb1)->nr_frags ||
+			    skb_shinfo(skb1)->frag_list ||
+			    skb_tailroom(skb1) < tailbits)
+				ntail = tailbits + 128;
+		}
+
+		if (copyflag ||
+		    skb_cloned(skb1) ||
+		    ntail ||
+		    skb_shinfo(skb1)->nr_frags ||
+		    skb_shinfo(skb1)->frag_list) {
+			struct sk_buff *skb2;
+
+			/* Fuck, we are miserable poor guys... */
+			if (ntail == 0)
+				skb2 = skb_copy(skb1, GFP_ATOMIC);
+			else
+				skb2 = skb_copy_expand(skb1,
+						       skb_headroom(skb1),
+						       ntail,
+						       GFP_ATOMIC);
+			if (unlikely(skb2 == NULL))
+				return -ENOMEM;
+
+			if (skb1->sk)
+				skb_set_owner_w(skb, skb1->sk);
+
+			/* Looking around. Are we still alive?
+			 * OK, link new skb, drop old one */
+
+			skb2->next = skb1->next;
+			*skb_p = skb2;
+			kfree_skb(skb1);
+			skb1 = skb2;
+		}
+		elt++;
+		*trailer = skb1;
+		skb_p = &skb1->next;
+	}
+
+	return elt;
+}
+
+void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len)
+{
+	if (tail != skb) {
+		skb->data_len += len;
+		skb->len += len;
+	}
+	return skb_put(tail, len);
+}
+#endif
diff -Nru a/net/ipv4/xfrm_input.c b/net/ipv4/xfrm_input.c
--- a/net/ipv4/xfrm_input.c	Tue Nov 12 14:35:26 2002
+++ b/net/ipv4/xfrm_input.c	Wed Mar  5 15:45:36 2003
@@ -1,4 +1,14 @@
+/* Changes
+ *
+ *	Mitsuru KANDA @USAGI       : IPv6 Support 
+ * 	Kazunori MIYAZAWA @USAGI   :
+ * 	YOSHIFUJI Hideaki @USAGI   :
+ * 	Kunihiro Ishiguro          :
+ * 	
+ */
+
 #include <net/ip.h>
+#include <net/ipv6.h>
 #include <net/xfrm.h>
 
 static kmem_cache_t *secpath_cachep;
@@ -64,7 +74,7 @@
 		if (xfrm_nr == XFRM_MAX_DEPTH)
 			goto drop;
 
-		x = xfrm_state_lookup(iph->daddr, spi, iph->protocol);
+		x = xfrm4_state_lookup(iph->daddr, spi, iph->protocol);
 		if (x == NULL)
 			goto drop;
 
@@ -157,3 +167,288 @@
 	if (!secpath_cachep)
 		panic("IP: failed to allocate secpath_cache\n");
 }
+
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+
+/* Fetch spi and seq frpm ipsec header */
+
+static int xfrm6_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
+{
+	int offset, offset_seq;
+
+	switch (nexthdr) {
+	case IPPROTO_AH:
+		offset = offsetof(struct ip_auth_hdr, spi);
+		offset_seq = offsetof(struct ip_auth_hdr, seq_no);
+		break;
+	case IPPROTO_ESP:
+		offset = offsetof(struct ip_esp_hdr, spi);
+		offset_seq = offsetof(struct ip_esp_hdr, seq_no);
+		break;
+	case IPPROTO_COMP:
+		if (!pskb_may_pull(skb, 4))
+			return -EINVAL;
+		*spi = *(u16*)(skb->h.raw + 2);
+		*seq = 0;
+		return 0;
+	default:
+		return 1;
+	}
+
+	if (!pskb_may_pull(skb, 16))
+		return -EINVAL;
+
+	*spi = *(u32*)(skb->h.raw + offset);
+	*seq = *(u32*)(skb->h.raw + offset_seq);
+	return 0;
+}
+
+static int zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr)
+{
+	u8 *opt = (u8 *)opthdr;
+	int len = ipv6_optlen(opthdr);
+	int off = 0;
+	int optlen = 0;
+
+	off += 2;
+	len -= 2;
+
+	while (len > 0) {
+
+		switch (opt[off]) {
+
+		case IPV6_TLV_PAD0:
+			optlen = 1;
+			break;
+		default:
+			if (len < 2) 
+				goto bad;
+			optlen = opt[off+1]+2;
+			if (len < optlen)
+				goto bad;
+			if (opt[off] & 0x20)
+				memset(&opt[off+2], 0, opt[off+1]);
+			break;
+		}
+
+		off += optlen;
+		len -= optlen;
+	}
+	if (len == 0)
+		return 1;
+
+bad:
+	return 0;
+}
+
+int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir)
+{
+	u16 offset = sizeof(struct ipv6hdr);
+	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+	unsigned int packet_len = skb->tail - skb->nh.raw;
+	u8 nexthdr = skb->nh.ipv6h->nexthdr;
+	u8 nextnexthdr = 0;
+
+	*nh_offset = ((unsigned char *)&skb->nh.ipv6h->nexthdr) - skb->nh.raw;
+
+	while (offset + 1 <= packet_len) {
+
+		switch (nexthdr) {
+
+		case NEXTHDR_HOP:
+			*nh_offset = offset;
+			offset += ipv6_optlen(exthdr);
+			if (!zero_out_mutable_opts(exthdr)) {
+				if (net_ratelimit())
+					printk(KERN_WARNING "overrun hopopts\n"); 
+				return 0;
+			}
+			nexthdr = exthdr->nexthdr;
+			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+			break;
+
+		case NEXTHDR_ROUTING:
+			*nh_offset = offset;
+			offset += ipv6_optlen(exthdr);
+			((struct ipv6_rt_hdr*)exthdr)->segments_left = 0; 
+			nexthdr = exthdr->nexthdr;
+			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+			break;
+
+		case NEXTHDR_DEST:
+			*nh_offset = offset;
+			offset += ipv6_optlen(exthdr);
+			if (!zero_out_mutable_opts(exthdr))  {
+				if (net_ratelimit())
+					printk(KERN_WARNING "overrun destopt\n"); 
+				return 0;
+			}
+			nexthdr = exthdr->nexthdr;
+			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+			break;
+
+		case NEXTHDR_AUTH:
+			if (dir == XFRM_POLICY_OUT) {
+				memset(((struct ipv6_auth_hdr*)exthdr)->auth_data, 0, 
+				       (((struct ipv6_auth_hdr*)exthdr)->hdrlen - 1) << 2);
+			}
+			if (exthdr->nexthdr == NEXTHDR_DEST) {
+				offset += (((struct ipv6_auth_hdr*)exthdr)->hdrlen + 2) << 2;
+				exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+				nextnexthdr = exthdr->nexthdr;
+				if (!zero_out_mutable_opts(exthdr)) {
+					if (net_ratelimit())
+						printk(KERN_WARNING "overrun destopt\n");
+					return 0;
+				}
+			}
+			return nexthdr;
+		default :
+			return nexthdr;
+		}
+	}
+
+	return nexthdr;
+}
+
+int xfrm6_rcv(struct sk_buff *skb)
+{
+	int err;
+	u32 spi, seq;
+	struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
+	struct xfrm_state *x;
+	int xfrm_nr = 0;
+	int decaps = 0;
+	struct ipv6hdr *hdr = skb->nh.ipv6h;
+	unsigned char *tmp_hdr = NULL;
+	int hdr_len = 0;
+	u16 nh_offset = 0;
+	u8 nexthdr = 0;
+
+	if (hdr->nexthdr == IPPROTO_AH || hdr->nexthdr == IPPROTO_ESP) {
+		nh_offset = ((unsigned char*)&skb->nh.ipv6h->nexthdr) - skb->nh.raw;
+		hdr_len = sizeof(struct ipv6hdr);
+	} else {
+		hdr_len = skb->h.raw - skb->nh.raw;
+	}
+
+	tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC);
+	if (!tmp_hdr)
+		goto drop;
+	memcpy(tmp_hdr, skb->nh.raw, hdr_len);
+
+	nexthdr = xfrm6_clear_mutable_options(skb, &nh_offset, XFRM_POLICY_IN);
+	hdr->priority    = 0;
+	hdr->flow_lbl[0] = 0;
+	hdr->flow_lbl[1] = 0;
+	hdr->flow_lbl[2] = 0;
+	hdr->hop_limit   = 0;
+
+	if ((err = xfrm6_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
+		goto drop;
+	
+	do {
+		struct ipv6hdr *iph = skb->nh.ipv6h;
+
+		if (xfrm_nr == XFRM_MAX_DEPTH)
+			goto drop;
+
+		x = xfrm6_state_lookup(&iph->daddr, spi, nexthdr);
+		if (x == NULL)
+			goto drop;
+		spin_lock(&x->lock);
+		if (unlikely(x->km.state != XFRM_STATE_VALID))
+			goto drop_unlock;
+
+		if (x->props.replay_window && xfrm_replay_check(x, seq))
+			goto drop_unlock;
+
+		nexthdr = x->type->input(x, skb);
+		if (nexthdr <= 0)
+			goto drop_unlock;
+
+		if (x->props.replay_window)
+			xfrm_replay_advance(x, seq);
+
+		x->curlft.bytes += skb->len;
+		x->curlft.packets++;
+
+		spin_unlock(&x->lock);
+
+		xfrm_vec[xfrm_nr++] = x;
+
+		iph = skb->nh.ipv6h; /* ??? */ 
+
+		if (nexthdr == NEXTHDR_DEST) {
+			if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
+		    	!pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
+				err = -EINVAL;
+				goto drop;
+			}
+			nexthdr = skb->h.raw[0];
+			nh_offset = skb->h.raw - skb->nh.raw;
+			skb_pull(skb, (skb->h.raw[1]+1)<<3);
+			skb->h.raw = skb->data;
+		}
+
+		if (x->props.mode) { /* XXX */
+			if (iph->nexthdr != IPPROTO_IPV6)
+				goto drop;
+			skb->nh.raw = skb->data;
+			iph = skb->nh.ipv6h;
+			decaps = 1;
+			break;
+		}
+
+		if ((err = xfrm6_parse_spi(skb, nexthdr, &spi, &seq)) < 0)
+			goto drop;
+	} while (!err);
+
+	memcpy(skb->nh.raw, tmp_hdr, hdr_len);
+	skb->nh.raw[nh_offset] = nexthdr;
+	skb->nh.ipv6h->payload_len = htons(hdr_len + skb->len - sizeof(struct ipv6hdr));
+
+	/* Allocate new secpath or COW existing one. */
+	if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
+		struct sec_path *sp;
+		sp = kmem_cache_alloc(secpath_cachep, SLAB_ATOMIC);
+		if (!sp)
+			goto drop;
+		if (skb->sp) {
+			memcpy(sp, skb->sp, sizeof(struct sec_path));
+			secpath_put(skb->sp);
+		} else
+			sp->len = 0;
+		atomic_set(&sp->refcnt, 1);
+		skb->sp = sp;
+	}
+
+	if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
+		goto drop;
+
+	memcpy(skb->sp->xvec+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(void*));
+	skb->sp->len += xfrm_nr;
+
+	if (decaps) {
+		if (!(skb->dev->flags&IFF_LOOPBACK)) {
+			dst_release(skb->dst);
+			skb->dst = NULL;
+		}
+		netif_rx(skb);
+		return 0;
+	} else {
+		return -nexthdr;
+	}
+
+drop_unlock:
+	spin_unlock(&x->lock);
+	xfrm_state_put(x);
+drop:
+	if (tmp_hdr) kfree(tmp_hdr);
+	while (--xfrm_nr >= 0)
+		xfrm_state_put(xfrm_vec[xfrm_nr]);
+	kfree_skb(skb);
+	return 0;
+}
+
+#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
diff -Nru a/net/ipv4/xfrm_policy.c b/net/ipv4/xfrm_policy.c
--- a/net/ipv4/xfrm_policy.c	Wed Feb 19 14:32:20 2003
+++ b/net/ipv4/xfrm_policy.c	Wed Mar  5 15:45:36 2003
@@ -1,6 +1,16 @@
+/* Changes
+ *
+ *	Mitsuru KANDA @USAGI       : IPv6 Support 
+ * 	Kazunori MIYAZAWA @USAGI   :
+ * 	Kunihiro Ishiguro          :
+ * 	
+ */
+
 #include <linux/config.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
 
 DECLARE_MUTEX(xfrm_cfg_sem);
 
@@ -10,6 +20,11 @@
 struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
 
 extern struct dst_ops xfrm4_dst_ops;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+extern struct dst_ops xfrm6_dst_ops;
+#endif
+
+static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family);
 
 /* Limited flow cache. Its function now is to accelerate search for
  * policy rules.
@@ -48,6 +63,24 @@
 	return hash & (FLOWCACHE_HASH_SIZE-1);
 }
 
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+static inline u32 flow_hash6(struct flowi *fl)
+{
+	u32 hash = fl->fl6_src->s6_addr32[2] ^
+		   fl->fl6_src->s6_addr32[3] ^ 
+		   fl->uli_u.ports.sport;
+
+	hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4);
+
+	hash ^= fl->fl6_dst->s6_addr32[2] ^
+		fl->fl6_dst->s6_addr32[3] ^ 
+		fl->uli_u.ports.dport;
+	hash ^= (hash >> 10);
+	hash ^= (hash >> 20);
+	return hash & (FLOWCACHE_HASH_SIZE-1);
+}
+#endif
+
 static int flow_lwm = 2*FLOWCACHE_HASH_SIZE;
 static int flow_hwm = 4*FLOWCACHE_HASH_SIZE;
 
@@ -77,13 +110,27 @@
 	}
 }
 
-struct xfrm_policy *flow_lookup(int dir, struct flowi *fl)
+struct xfrm_policy *flow_lookup(int dir, struct flowi *fl, 
+				unsigned short family)
 {
-	struct xfrm_policy *pol;
+	struct xfrm_policy *pol = NULL;
 	struct flow_entry *fle;
-	u32 hash = flow_hash(fl);
+	u32 hash;
 	int cpu;
 
+	switch (family) {
+	case AF_INET:
+		hash = flow_hash(fl);
+		break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		hash = flow_hash6(fl);
+		break;
+#endif
+	default:
+		return NULL;
+	}
+
 	local_bh_disable();
 	cpu = smp_processor_id();
 
@@ -101,7 +148,7 @@
 		}
 	}
 
-	pol = xfrm_policy_lookup(dir, fl);
+	pol = xfrm_policy_lookup(dir, fl, family);
 
 	if (fle) {
 		/* Stale flow entry found. Update it. */
@@ -199,6 +246,46 @@
 	return type;
 }
 
+static  xfrm_dst_lookup_t *__xfrm_dst_lookup[AF_MAX];
+rwlock_t xdl_lock = RW_LOCK_UNLOCKED;
+
+int xfrm_dst_lookup_register(xfrm_dst_lookup_t *dst_lookup, 
+			     unsigned short family)
+{
+	int err = 0;
+
+	write_lock(&xdl_lock);
+	if (__xfrm_dst_lookup[family])
+		err = -ENOBUFS;
+	else { 
+		__xfrm_dst_lookup[family] = dst_lookup;
+	}
+	write_unlock(&xdl_lock);
+
+	return err;
+}
+
+void xfrm_dst_lookup_unregister(unsigned short family)
+{
+	write_lock(&xdl_lock);
+	if (__xfrm_dst_lookup[family])
+		__xfrm_dst_lookup[family] = 0;
+	write_unlock(&xdl_lock);
+}
+
+static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, 
+				  unsigned short family)
+{
+	int err = 0;
+	read_lock(&xdl_lock);
+	if (__xfrm_dst_lookup[family])
+		err = __xfrm_dst_lookup[family](dst, fl);
+	else
+		err = -EINVAL;
+	read_unlock(&xdl_lock);
+	return err;
+}
+
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 static struct xfrm_type *xfrm6_type_map[256];
 static rwlock_t xfrm6_type_lock = RW_LOCK_UNLOCKED;
@@ -506,15 +593,32 @@
 
 /* Find policy to apply to this flow. */
 
-struct xfrm_policy *xfrm_policy_lookup(int dir, struct flowi *fl)
+struct xfrm_policy *xfrm_policy_lookup(int dir, struct flowi *fl, 
+				       unsigned short family)
 {
 	struct xfrm_policy *pol;
 
 	read_lock_bh(&xfrm_policy_lock);
 	for (pol = xfrm_policy_list[dir]; pol; pol = pol->next) {
 		struct xfrm_selector *sel = &pol->selector;
+		int match;
+
+		if (pol->family != family)
+			continue;
 
-		if (xfrm4_selector_match(sel, fl)) {
+		switch (family) {
+		case AF_INET:
+			match = xfrm4_selector_match(sel, fl);
+			break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+		case AF_INET6:
+			match = xfrm6_selector_match(sel, fl);
+			break;
+#endif
+		default:
+			match = 0;
+		}
+		if (match) {
 			atomic_inc(&pol->refcnt);
 			break;
 		}
@@ -529,7 +633,21 @@
 
 	read_lock_bh(&xfrm_policy_lock);
 	if ((pol = sk->policy[dir]) != NULL) {
-		if (xfrm4_selector_match(&pol->selector, fl))
+		int match;
+
+		switch (sk->family) {
+		case AF_INET:
+			match = xfrm4_selector_match(&pol->selector, fl);
+			break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+		case AF_INET6:
+			match = xfrm6_selector_match(&pol->selector, fl);
+			break;
+#endif
+		default:
+			match = 0;
+		}
+		if (match)
 			atomic_inc(&pol->refcnt);
 		else
 			pol = NULL;
@@ -630,8 +748,8 @@
 /* Resolve list of templates for the flow, given policy. */
 
 static int
-xfrm_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl,
-		  struct xfrm_state **xfrm)
+xfrm4_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl,
+		   struct xfrm_state **xfrm)
 {
 	int nx;
 	int i, error;
@@ -649,7 +767,7 @@
 			local = tmpl->saddr.xfrm4_addr;
 		}
 
-		x = xfrm_state_find(remote, local, fl, tmpl, policy, &error);
+		x = xfrm4_state_find(remote, local, fl, tmpl, policy, &error);
 
 		if (x && x->km.state == XFRM_STATE_VALID) {
 			xfrm[nx++] = x;
@@ -674,6 +792,53 @@
 	return error;
 }
 
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+static int
+xfrm6_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl,
+		  struct xfrm_state **xfrm)
+{
+	int nx;
+	int i, error;
+	struct in6_addr *daddr = fl->fl6_dst;
+	struct in6_addr *saddr = fl->fl6_src;
+
+	for (nx=0, i = 0; i < policy->xfrm_nr; i++) {
+		struct xfrm_state *x=NULL;
+		struct in6_addr *remote = daddr;
+		struct in6_addr *local = saddr;
+		struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i];
+
+		if (tmpl->mode) {
+			remote = (struct in6_addr*)&tmpl->id.daddr;
+			local = (struct in6_addr*)&tmpl->saddr;
+		}
+
+		x = xfrm6_state_find(remote, local, fl, tmpl, policy, &error);
+
+		if (x && x->km.state == XFRM_STATE_VALID) {
+			xfrm[nx++] = x;
+			daddr = remote;
+			saddr = local;
+			continue;
+		}
+		if (x) {
+			error = (x->km.state == XFRM_STATE_ERROR ?
+				 -EINVAL : -EAGAIN);
+			xfrm_state_put(x);
+		}
+
+		if (!tmpl->optional)
+			goto fail;
+	}
+	return nx;
+
+fail:
+	for (nx--; nx>=0; nx--)
+		xfrm_state_put(xfrm[nx]);
+	return error;
+}
+#endif
+
 /* Check that the bundle accepts the flow and its components are
  * still valid.
  */
@@ -694,6 +859,24 @@
 	return 0;
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static int xfrm6_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl)
+{
+	do {
+		if (xdst->u.dst.ops != &xfrm6_dst_ops)
+			return 1;
+
+		if (!xfrm6_selector_match(&xdst->u.dst.xfrm->sel, fl))
+			return 0;
+		if (xdst->u.dst.xfrm->km.state != XFRM_STATE_VALID ||
+		    xdst->u.dst.path->obsolete > 0)
+			return 0;
+		xdst = (struct xfrm_dst*)xdst->u.dst.child;
+	} while (xdst);
+	return 0;
+}
+#endif
+
 
 /* Allocate chain of dst_entry's, attach known xfrm's, calculate
  * all the metrics... Shortly, bundle a bundle.
@@ -728,7 +911,7 @@
 		else {
 			dst_prev->child = dst1;
 			dst1->flags |= DST_NOHASH;
-			dst_clone(dst1);
+			dst_hold(dst1);
 		}
 		dst_prev = dst1;
 		if (xfrm[i]->props.mode) {
@@ -744,11 +927,11 @@
 						       .saddr = local }
 					           }
 				         };
-		err = __ip_route_output_key(&rt, &fl_tunnel);
+		err = xfrm_dst_lookup((struct xfrm_dst**)&rt, &fl_tunnel, AF_INET);
 		if (err)
 			goto error;
 	} else {
-		dst_clone(&rt->u.dst);
+		dst_hold(&rt->u.dst);
 	}
 	dst_prev->child = &rt->u.dst;
 	for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
@@ -791,6 +974,97 @@
 	return err;
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static int
+xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx,
+		   struct flowi *fl, struct dst_entry **dst_p)
+{
+	struct dst_entry *dst, *dst_prev;
+	struct rt6_info *rt0 = (struct rt6_info*)(*dst_p);
+	struct rt6_info *rt  = rt0;
+	struct in6_addr *remote = fl->fl6_dst;
+	struct in6_addr *local  = fl->fl6_src;
+	int i;
+	int err = 0;
+	int header_len = 0;
+
+	dst = dst_prev = NULL;
+
+	for (i = 0; i < nx; i++) {
+		struct dst_entry *dst1 = dst_alloc(&xfrm6_dst_ops);
+
+		if (unlikely(dst1 == NULL)) {
+			err = -ENOBUFS;
+			goto error;
+		}
+
+		dst1->xfrm = xfrm[i];
+		if (!dst)
+			dst = dst1;
+		else {
+			dst_prev->child = dst1;
+			dst1->flags |= DST_NOHASH;
+			dst_clone(dst1);
+		}
+		dst_prev = dst1;
+		if (xfrm[i]->props.mode) {
+			remote = (struct in6_addr*)&xfrm[i]->id.daddr;
+			local  = (struct in6_addr*)&xfrm[i]->props.saddr;
+		}
+		header_len += xfrm[i]->props.header_len;
+	}
+
+	if (ipv6_addr_cmp(remote, fl->fl6_dst)) {
+		struct flowi fl_tunnel = { .nl_u = { .ip6_u =
+						     { .daddr = remote,
+						       .saddr = local }
+					           }
+				         };
+		err = xfrm_dst_lookup((struct xfrm_dst**)&dst, &fl_tunnel, AF_INET6);
+		if (err)
+			goto error;
+	} else {
+		dst_clone(&rt->u.dst);
+	}
+	dst_prev->child = &rt->u.dst;
+	for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
+		struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
+		x->u.rt.fl = *fl;
+
+		dst_prev->dev = rt->u.dst.dev;
+		if (rt->u.dst.dev)
+			dev_hold(rt->u.dst.dev);
+		dst_prev->obsolete	= -1;
+		dst_prev->flags	       |= DST_HOST;
+		dst_prev->lastuse	= jiffies;
+		dst_prev->header_len	= header_len;
+		memcpy(&dst_prev->metrics, &rt->u.dst.metrics, sizeof(dst_prev->metrics));
+		dst_prev->path		= &rt->u.dst;
+
+		/* Copy neighbout for reachability confirmation */
+		dst_prev->neighbour	= neigh_clone(rt->u.dst.neighbour);
+		dst_prev->input		= rt->u.dst.input;
+		dst_prev->output	= dst_prev->xfrm->type->output;
+		/* Sheit... I remember I did this right. Apparently,
+		 * it was magically lost, so this code needs audit */
+		x->u.rt6.rt6i_flags    = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
+		x->u.rt6.rt6i_metric   = rt0->rt6i_metric;
+		x->u.rt6.rt6i_node     = rt0->rt6i_node;
+		x->u.rt6.rt6i_hoplimit = rt0->rt6i_hoplimit;
+		x->u.rt6.rt6i_gateway  = rt0->rt6i_gateway;
+		memcpy(&x->u.rt6.rt6i_gateway, &rt0->rt6i_gateway, sizeof(x->u.rt6.rt6i_gateway)); 
+		header_len -= x->u.dst.xfrm->props.header_len;
+	}
+	*dst_p = dst;
+	return 0;
+
+error:
+	if (dst)
+		dst_free(dst);
+	return err;
+}
+#endif
+
 /* Main function: finds/creates a bundle for given flow.
  *
  * At the moment we eat a raw IP route. Mostly to speed up lookups
@@ -806,9 +1080,7 @@
 	int nx = 0;
 	int err;
 	u32 genid;
-
-	fl->oif = rt->u.dst.dev->ifindex;
-	fl->fl4_src = rt->rt_src;
+	u16 family = (*dst_p)->ops->family;
 
 restart:
 	genid = xfrm_policy_genid;
@@ -821,11 +1093,12 @@
 		if ((rt->u.dst.flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
 			return 0;
 
-		policy = flow_lookup(XFRM_POLICY_OUT, fl);
-		if (!policy)
-			return 0;
+		policy = flow_lookup(XFRM_POLICY_OUT, fl, family);
 	}
 
+	if (!policy)
+		return 0;
+
 	policy->curlft.use_time = (unsigned long)xtime.tv_sec;
 
 	switch (policy->action) {
@@ -846,23 +1119,48 @@
 		 * LATER: help from flow cache. It is optional, this
 		 * is required only for output policy.
 		 */
-		read_lock_bh(&policy->lock);
-		for (dst = policy->bundles; dst; dst = dst->next) {
-			struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
-			if (xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
-			    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
-			    xdst->u.rt.fl.oif == fl->oif &&
-			    xfrm_bundle_ok(xdst, fl)) {
-				dst_clone(dst);
+		if (family == AF_INET) {
+			fl->oif = rt->u.dst.dev->ifindex;
+			fl->fl4_src = rt->rt_src;
+			read_lock_bh(&policy->lock);
+			for (dst = policy->bundles; dst; dst = dst->next) {
+				struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
+				if (xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
+				    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
+				    xdst->u.rt.fl.oif == fl->oif &&
+				    xfrm_bundle_ok(xdst, fl)) {
+					dst_clone(dst);
+					break;
+				}
+			}
+			read_unlock_bh(&policy->lock);
+			if (dst)
 				break;
+			nx = xfrm4_tmpl_resolve(policy, fl, xfrm);
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+		} else if (family == AF_INET6) {
+			read_lock_bh(&policy->lock);
+			for (dst = policy->bundles; dst; dst = dst->next) {
+				struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
+				if (!ipv6_addr_cmp(&xdst->u.rt6.rt6i_dst.addr, fl->fl6_dst) &&
+				    !ipv6_addr_cmp(&xdst->u.rt6.rt6i_src.addr, fl->fl6_src) &&
+				    xfrm6_bundle_ok(xdst, fl)) {
+					dst_clone(dst);
+					break;
+				}
 			}
+			read_unlock_bh(&policy->lock);
+			if (dst)
+				break;
+			nx = xfrm6_tmpl_resolve(policy, fl, xfrm);
+#endif
+		} else {
+			return -EINVAL;
 		}
-		read_unlock_bh(&policy->lock);
 
 		if (dst)
 			break;
 
-		nx = xfrm_tmpl_resolve(policy, fl, xfrm);
 		if (unlikely(nx<0)) {
 			err = nx;
 			if (err == -EAGAIN) {
@@ -873,7 +1171,18 @@
 
 				__set_task_state(tsk, TASK_INTERRUPTIBLE);
 				add_wait_queue(&km_waitq, &wait);
-				err = xfrm_tmpl_resolve(policy, fl, xfrm);
+				switch (family) {
+				case AF_INET:
+					err = xfrm4_tmpl_resolve(policy, fl, xfrm);
+					break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+				case AF_INET6:
+					err = xfrm6_tmpl_resolve(policy, fl, xfrm);
+					break;
+#endif
+				default:
+					err = -EINVAL;
+				}
 				if (err == -EAGAIN)
 					schedule();
 				__set_task_state(tsk, TASK_RUNNING);
@@ -896,7 +1205,19 @@
 		}
 
 		dst = &rt->u.dst;
-		err = xfrm_bundle_create(policy, xfrm, nx, fl, &dst);
+		switch (family) {
+		case AF_INET:
+			err = xfrm_bundle_create(policy, xfrm, nx, fl, &dst);
+			break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+		case AF_INET6:
+			err = xfrm6_bundle_create(policy, xfrm, nx, fl, &dst);
+			break;
+#endif
+		default:
+			err = -EINVAL;
+		}
+			
 		if (unlikely(err)) {
 			int i;
 			for (i=0; i<nx; i++)
@@ -919,7 +1240,7 @@
 		}
 		dst->next = policy->bundles;
 		policy->bundles = dst;
-		dst_clone(dst);
+		dst_hold(dst);
 		write_unlock_bh(&policy->lock);
 	}
 	*dst_p = dst;
@@ -962,7 +1283,7 @@
 }
 
 static void
-_decode_session(struct sk_buff *skb, struct flowi *fl)
+_decode_session4(struct sk_buff *skb, struct flowi *fl)
 {
 	struct iphdr *iph = skb->nh.iph;
 	u8 *xprth = skb->nh.raw + iph->ihl*4;
@@ -1008,18 +1329,109 @@
 	fl->fl4_src = iph->saddr;
 }
 
-int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+static inline int
+xfrm6_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x)
+{
+	return	x->id.proto == tmpl->id.proto &&
+		(x->id.spi == tmpl->id.spi || !tmpl->id.spi) &&
+		x->props.mode == tmpl->mode &&
+		(tmpl->aalgos & (1<<x->props.aalgo)) &&
+		(!x->props.mode || !ipv6_addr_any((struct in6_addr*)&x->props.saddr) ||
+		 !ipv6_addr_cmp((struct in6_addr *)&tmpl->saddr, (struct in6_addr*)&x->props.saddr));
+}
+
+static inline int
+xfrm6_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int idx)
+{
+	for (; idx < sp->len; idx++) {
+		if (xfrm6_state_ok(tmpl, sp->xvec[idx]))
+			return ++idx;
+	}
+	return -1;
+}
+
+static inline void
+_decode_session6(struct sk_buff *skb, struct flowi *fl)
+{
+	u16 offset = sizeof(struct ipv6hdr);
+	struct ipv6hdr *hdr = skb->nh.ipv6h;
+	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+	u8 nexthdr = skb->nh.ipv6h->nexthdr;
+
+	fl->fl6_dst = &hdr->daddr;
+	fl->fl6_src = &hdr->saddr;
+
+	while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) {
+		switch (nexthdr) {
+		case NEXTHDR_ROUTING:
+		case NEXTHDR_HOP:
+		case NEXTHDR_DEST:
+			offset += ipv6_optlen(exthdr);
+			nexthdr = exthdr->nexthdr;
+			exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+			break;
+
+		case IPPROTO_UDP:
+		case IPPROTO_TCP:
+		case IPPROTO_SCTP:
+			if (pskb_may_pull(skb, skb->nh.raw + offset + 4 - skb->data)) {
+				u16 *ports = (u16 *)exthdr;
+
+				fl->uli_u.ports.sport = ports[0];
+				fl->uli_u.ports.dport = ports[1];
+			}
+			return;
+
+		/* XXX Why are there these headers? */
+		case IPPROTO_AH:
+		case IPPROTO_ESP:
+		default:
+			fl->uli_u.spi = 0;
+			return;
+		};
+	}
+}
+#endif
+
+int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, 
+			unsigned short family)
 {
 	struct xfrm_policy *pol;
 	struct flowi fl;
 
-	_decode_session(skb, &fl);
+	switch (family) {
+	case AF_INET:
+		_decode_session4(skb, &fl);
+		break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		_decode_session6(skb, &fl);
+		break;
+#endif
+	default :
+		return 0;
+	}
 
 	/* First, check used SA against their selectors. */
 	if (skb->sp) {
 		int i;
+
 		for (i=skb->sp->len-1; i>=0; i--) {
-			if (!xfrm4_selector_match(&skb->sp->xvec[i]->sel, &fl))
+			int match;
+			switch (family) {
+			case AF_INET:
+				match = xfrm4_selector_match(&skb->sp->xvec[i]->sel, &fl);
+				break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+			case AF_INET6:
+				match = xfrm6_selector_match(&skb->sp->xvec[i]->sel, &fl);
+				break;
+#endif
+			default:
+				match = 0;
+			}
+			if (!match)
 				return 0;
 		}
 	}
@@ -1029,7 +1441,7 @@
 		pol = xfrm_sk_policy_lookup(sk, dir, &fl);
 
 	if (!pol)
-		pol = flow_lookup(dir, &fl);
+		pol = flow_lookup(dir, &fl, family);
 
 	if (!pol)
 		return 1;
@@ -1050,7 +1462,18 @@
 			 * are implied between each two transformations.
 			 */
 			for (i = pol->xfrm_nr-1, k = 0; i >= 0; i--) {
-				k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k);
+				switch (family) {
+				case AF_INET:
+					k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k);
+					break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+				case AF_INET6:
+					k = xfrm6_policy_ok(pol->xfrm_vec+i, sp, k);
+					break;
+#endif
+				default:
+					k = -1;
+				}
 				if (k < 0)
 					goto reject;
 			}
@@ -1064,18 +1487,29 @@
 	return 0;
 }
 
-int __xfrm_route_forward(struct sk_buff *skb)
+int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
 {
 	struct flowi fl;
 
-	_decode_session(skb, &fl);
+	switch (family) {
+	case AF_INET:
+		_decode_session4(skb, &fl);
+		break;
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		_decode_session6(skb, &fl);
+		break;
+#endif
+	default:
+		return 0;
+	}
 
 	return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0;
 }
 
 /* Optimize later using cookies and generation ids. */
 
-static struct dst_entry *xfrm4_dst_check(struct dst_entry *dst, u32 cookie)
+static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie)
 {
 	struct dst_entry *child = dst;
 
@@ -1091,19 +1525,19 @@
 	return dst;
 }
 
-static void xfrm4_dst_destroy(struct dst_entry *dst)
+static void xfrm_dst_destroy(struct dst_entry *dst)
 {
 	xfrm_state_put(dst->xfrm);
 	dst->xfrm = NULL;
 }
 
-static void xfrm4_link_failure(struct sk_buff *skb)
+static void xfrm_link_failure(struct sk_buff *skb)
 {
 	/* Impossible. Such dst must be popped before reaches point of failure. */
 	return;
 }
 
-static struct dst_entry *xfrm4_negative_advice(struct dst_entry *dst)
+static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst)
 {
 	if (dst) {
 		if (dst->obsolete) {
@@ -1114,8 +1548,7 @@
 	return dst;
 }
 
-
-static int xfrm4_garbage_collect(void)
+static void __xfrm_garbage_collect(void)
 {
 	int i;
 	struct xfrm_policy *pol;
@@ -1145,10 +1578,22 @@
 		gc_list = dst->next;
 		dst_free(dst);
 	}
+}
 
+static inline int xfrm4_garbage_collect(void)
+{
+	__xfrm_garbage_collect();
 	return (atomic_read(&xfrm4_dst_ops.entries) > xfrm4_dst_ops.gc_thresh*2);
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static inline int xfrm6_garbage_collect(void)
+{
+	__xfrm_garbage_collect();
+	return (atomic_read(&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2);
+}
+#endif
+
 static int bundle_depends_on(struct dst_entry *dst, struct xfrm_state *x)
 {
 	do {
@@ -1192,7 +1637,7 @@
 	return 0;
 }
 
-
+ 
 static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
 	struct dst_entry *path = dst->path;
@@ -1203,6 +1648,18 @@
 	path->ops->update_pmtu(path, mtu);
 }
 
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu)
+{
+	struct dst_entry *path = dst->path;
+
+	if (mtu >= 1280 && mtu < dst_pmtu(dst))
+		return;
+
+	path->ops->update_pmtu(path, mtu);
+}
+#endif
+
 /* Well... that's _TASK_. We need to scan through transformation
  * list and figure out what mss tcp should generate in order to
  * final datagram fit to mtu. Mama mia... :-)
@@ -1212,7 +1669,7 @@
  *
  * Consider this function as something like dark humour. :-)
  */
-static int xfrm4_get_mss(struct dst_entry *dst, u32 mtu)
+static int xfrm_get_mss(struct dst_entry *dst, u32 mtu)
 {
 	int res = mtu - dst->header_len;
 
@@ -1247,16 +1704,32 @@
 	.family =		AF_INET,
 	.protocol =		__constant_htons(ETH_P_IP),
 	.gc =			xfrm4_garbage_collect,
-	.check =		xfrm4_dst_check,
-	.destroy =		xfrm4_dst_destroy,
-	.negative_advice =	xfrm4_negative_advice,
-	.link_failure =		xfrm4_link_failure,
+	.check =		xfrm_dst_check,
+	.destroy =		xfrm_dst_destroy,
+	.negative_advice =	xfrm_negative_advice,
+	.link_failure =		xfrm_link_failure,
 	.update_pmtu =		xfrm4_update_pmtu,
-	.get_mss =		xfrm4_get_mss,
+	.get_mss =		xfrm_get_mss,
 	.gc_thresh =		1024,
 	.entry_size =		sizeof(struct xfrm_dst),
 };
 
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+struct dst_ops xfrm6_dst_ops = {
+	.family =		AF_INET6,
+	.protocol =		__constant_htons(ETH_P_IPV6),
+	.gc =			xfrm6_garbage_collect,
+	.check =		xfrm_dst_check,
+	.destroy =		xfrm_dst_destroy,
+	.negative_advice =	xfrm_negative_advice,
+	.link_failure =		xfrm_link_failure,
+	.update_pmtu =		xfrm6_update_pmtu,
+	.get_mss =		xfrm_get_mss,
+	.gc_thresh =		1024,
+	.entry_size =		sizeof(struct xfrm_dst),
+};
+#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
+
 void __init xfrm_init(void)
 {
 	xfrm4_dst_ops.kmem_cachep = kmem_cache_create("xfrm4_dst_cache",
@@ -1267,8 +1740,12 @@
 	if (!xfrm4_dst_ops.kmem_cachep)
 		panic("IP: failed to allocate xfrm4_dst_cache\n");
 
-	flow_cache_init();
+#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+	xfrm6_dst_ops.kmem_cachep = xfrm4_dst_ops.kmem_cachep;
+#endif
 
+	flow_cache_init();
 	xfrm_state_init();
 	xfrm_input_init();
 }
+
diff -Nru a/net/ipv4/xfrm_state.c b/net/ipv4/xfrm_state.c
--- a/net/ipv4/xfrm_state.c	Thu Feb 13 01:26:32 2003
+++ b/net/ipv4/xfrm_state.c	Wed Mar  5 15:45:36 2003
@@ -1,3 +1,11 @@
+/* Changes
+ *
+ *	Mitsuru KANDA @USAGI       : IPv6 Support 
+ * 	Kazunori MIYAZAWA @USAGI   :
+ * 	Kunihiro Ishiguro          :
+ * 	
+ */
+
 #include <net/xfrm.h>
 #include <linux/pfkeyv2.h>
 #include <linux/ipsec.h>
@@ -207,8 +215,8 @@
 }
 
 struct xfrm_state *
-xfrm_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
-		struct xfrm_policy *pol, int *err)
+xfrm4_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
+		 struct xfrm_policy *pol, int *err)
 {
 	unsigned h = ntohl(daddr);
 	struct xfrm_state *x;
@@ -290,6 +298,7 @@
 			x->props.saddr.xfrm4_addr = saddr;
 		x->props.mode = tmpl->mode;
 		x->props.reqid = tmpl->reqid;
+		x->props.family = AF_INET;
 
 		if (km_query(x, tmpl, pol) == 0) {
 			x->km.state = XFRM_STATE_ACQ;
@@ -318,14 +327,133 @@
 	return x;
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+struct xfrm_state *
+xfrm6_state_find(struct in6_addr *daddr, struct in6_addr *saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
+		struct xfrm_policy *pol, int *err)
+{
+	unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]);
+	struct xfrm_state *x;
+	int acquire_in_progress = 0;
+	int error = 0;
+	struct xfrm_state *best = NULL;
+
+	h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
+
+	spin_lock_bh(&xfrm_state_lock);
+	list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
+		if (x->props.family == AF_INET6&&
+		    !ipv6_addr_cmp(daddr, (struct in6_addr *)&x->id.daddr) &&
+		    x->props.reqid == tmpl->reqid &&
+		    (!ipv6_addr_cmp(saddr, (struct in6_addr *)&x->props.saddr)|| ipv6_addr_any(saddr)) &&
+		    tmpl->mode == x->props.mode &&
+		    tmpl->id.proto == x->id.proto) {
+			/* Resolution logic:
+			   1. There is a valid state with matching selector.
+			      Done.
+			   2. Valid state with inappropriate selector. Skip.
+
+			   Entering area of "sysdeps".
+
+			   3. If state is not valid, selector is temporary,
+			      it selects only session which triggered
+			      previous resolution. Key manager will do
+			      something to install a state with proper
+			      selector.
+			 */
+			if (x->km.state == XFRM_STATE_VALID) {
+				if (!xfrm6_selector_match(&x->sel, fl))
+					continue;
+				if (!best ||
+				    best->km.dying > x->km.dying ||
+				    (best->km.dying == x->km.dying &&
+				     best->curlft.add_time < x->curlft.add_time))
+					best = x;
+			} else if (x->km.state == XFRM_STATE_ACQ) {
+				acquire_in_progress = 1;
+			} else if (x->km.state == XFRM_STATE_ERROR ||
+				   x->km.state == XFRM_STATE_EXPIRED) {
+				if (xfrm6_selector_match(&x->sel, fl))
+					error = 1;
+			}
+		}
+	}
+
+	if (best) {
+		atomic_inc(&best->refcnt);
+		spin_unlock_bh(&xfrm_state_lock);
+		return best;
+	}
+	x = NULL;
+	if (!error && !acquire_in_progress &&
+	    ((x = xfrm_state_alloc()) != NULL)) {
+		/* Initialize temporary selector matching only
+		 * to current session. */
+		memcpy(&x->sel.daddr, fl->fl6_dst, sizeof(struct in6_addr));
+		memcpy(&x->sel.saddr, fl->fl6_src, sizeof(struct in6_addr));
+		x->sel.dport = fl->uli_u.ports.dport;
+		x->sel.dport_mask = ~0;
+		x->sel.sport = fl->uli_u.ports.sport;
+		x->sel.sport_mask = ~0;
+		x->sel.prefixlen_d = 128;
+		x->sel.prefixlen_s = 128;
+		x->sel.proto = fl->proto;
+		x->sel.ifindex = fl->oif;
+		x->id = tmpl->id;
+		if (ipv6_addr_any((struct in6_addr*)&x->id.daddr))
+			memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr));
+		memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr));
+		if (ipv6_addr_any((struct in6_addr*)&x->props.saddr))
+			memcpy(&x->props.saddr, &saddr, sizeof(x->sel.saddr));
+		x->props.mode = tmpl->mode;
+		x->props.reqid = tmpl->reqid;
+		x->props.family = AF_INET6;
+
+		if (km_query(x, tmpl, pol) == 0) {
+			x->km.state = XFRM_STATE_ACQ;
+			list_add_tail(&x->bydst, xfrm_state_bydst+h);
+			atomic_inc(&x->refcnt);
+			if (x->id.spi) {
+				struct in6_addr *addr = (struct in6_addr*)&x->id.daddr;
+				h = ntohl((addr->s6_addr32[2]^addr->s6_addr32[3])^x->id.spi^x->id.proto);
+				h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
+				list_add(&x->byspi, xfrm_state_byspi+h);
+				atomic_inc(&x->refcnt);
+			}
+			x->lft.hard_add_expires_seconds = ACQ_EXPIRES;
+			atomic_inc(&x->refcnt);
+			mod_timer(&x->timer, ACQ_EXPIRES*HZ);
+		} else {
+			x->km.state = XFRM_STATE_DEAD;
+			xfrm_state_put(x);
+			x = NULL;
+			error = 1;
+		}
+	}
+	spin_unlock_bh(&xfrm_state_lock);
+	if (!x)
+		*err = acquire_in_progress ? -EAGAIN :
+			(error ? -ESRCH : -ENOMEM);
+	return x;
+}
+#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
+
 void xfrm_state_insert(struct xfrm_state *x)
 {
 	unsigned h = 0;
 
-	if (x->props.family == AF_INET)
+	switch (x->props.family) {
+	case AF_INET:
 		h = ntohl(x->id.daddr.xfrm4_addr);
-	else if (x->props.family == AF_INET6)
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
 		h = ntohl(x->id.daddr.a6[2]^x->id.daddr.a6[3]);
+		break;
+#endif
+	default:
+		return;
+	}
 
 	h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
 
@@ -384,7 +512,7 @@
 }
 
 struct xfrm_state *
-xfrm_state_lookup(u32 daddr, u32 spi, u8 proto)
+xfrm4_state_lookup(u32 daddr, u32 spi, u8 proto)
 {
 	unsigned h = ntohl(daddr^spi^proto);
 	struct xfrm_state *x;
@@ -406,6 +534,31 @@
 	return NULL;
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+struct xfrm_state *
+xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto)
+{
+	unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]^spi^proto);
+	struct xfrm_state *x;
+
+	h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
+
+	spin_lock_bh(&xfrm_state_lock);
+	list_for_each_entry(x, xfrm_state_byspi+h, byspi) {
+		if (x->props.family == AF_INET6 &&
+		    spi == x->id.spi &&
+		    !ipv6_addr_cmp(daddr, (struct in6_addr *)x->id.daddr.a6) &&
+		    proto == x->id.proto) {
+			atomic_inc(&x->refcnt);
+			spin_unlock_bh(&xfrm_state_lock);
+			return x;
+		}
+	}
+	spin_unlock_bh(&xfrm_state_lock);
+	return NULL;
+}
+#endif
+
 struct xfrm_state *
 xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create)
 {
@@ -445,7 +598,59 @@
 		x0->km.state = XFRM_STATE_ACQ;
 		x0->id.daddr.xfrm4_addr = daddr;
 		x0->id.proto = proto;
+		x0->props.mode = mode;
+		x0->props.reqid = reqid;
 		x0->props.family = AF_INET;
+		x0->lft.hard_add_expires_seconds = ACQ_EXPIRES;
+		atomic_inc(&x0->refcnt);
+		mod_timer(&x0->timer, jiffies + ACQ_EXPIRES*HZ);
+		atomic_inc(&x0->refcnt);
+		list_add_tail(&x0->bydst, xfrm_state_bydst+h);
+		wake_up(&km_waitq);
+	}
+	spin_unlock_bh(&xfrm_state_lock);
+	return x0;
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+struct xfrm_state *
+xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr, struct in6_addr *saddr, int create)
+{
+	struct xfrm_state *x, *x0;
+	unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]);
+
+	h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
+	x0 = NULL;
+
+	spin_lock_bh(&xfrm_state_lock);
+	list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
+		if (x->props.family == AF_INET6 &&
+		    !ipv6_addr_cmp(daddr, (struct in6_addr *)x->id.daddr.a6) &&
+		    mode == x->props.mode &&
+		    proto == x->id.proto &&
+		    !ipv6_addr_cmp(saddr, (struct in6_addr *)x->props.saddr.a6) &&
+		    reqid == x->props.reqid &&
+		    x->km.state == XFRM_STATE_ACQ) {
+			    if (!x0)
+				    x0 = x;
+			    if (x->id.spi)
+				    continue;
+			    x0 = x;
+			    break;
+		    }
+	}
+	if (x0) {
+		atomic_inc(&x0->refcnt);
+	} else if (create && (x0 = xfrm_state_alloc()) != NULL) {
+		memcpy(x0->sel.daddr.a6, daddr, sizeof(struct in6_addr));
+		memcpy(x0->sel.saddr.a6, saddr, sizeof(struct in6_addr));
+		x0->sel.prefixlen_d = 128;
+		x0->sel.prefixlen_s = 128;
+		memcpy(x0->props.saddr.a6, saddr, sizeof(struct in6_addr));
+		x0->km.state = XFRM_STATE_ACQ;
+		memcpy(x0->id.daddr.a6, daddr, sizeof(struct in6_addr));
+		x0->id.proto = proto;
+		x0->props.family = AF_INET6;
 		x0->props.mode = mode;
 		x0->props.reqid = reqid;
 		x0->lft.hard_add_expires_seconds = ACQ_EXPIRES;
@@ -458,6 +663,7 @@
 	spin_unlock_bh(&xfrm_state_lock);
 	return x0;
 }
+#endif
 
 /* Silly enough, but I'm lazy to build resolution list */
 
@@ -491,7 +697,18 @@
 		return;
 
 	if (minspi == maxspi) {
-		x0 = xfrm_state_lookup(x->id.daddr.xfrm4_addr, minspi, x->id.proto);
+		switch(x->props.family) {
+		case AF_INET:
+			x0 = xfrm4_state_lookup(x->id.daddr.xfrm4_addr, minspi, x->id.proto);
+			break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+		case AF_INET6:
+			x0 = xfrm6_state_lookup((struct in6_addr*)x->id.daddr.a6, minspi, x->id.proto);
+			break;
+#endif
+		default:
+			x0 = NULL;
+		}
 		if (x0) {
 			xfrm_state_put(x0);
 			return;
@@ -503,7 +720,18 @@
 		maxspi = ntohl(maxspi);
 		for (h=0; h<maxspi-minspi+1; h++) {
 			spi = minspi + net_random()%(maxspi-minspi+1);
-			x0 = xfrm_state_lookup(x->id.daddr.xfrm4_addr, htonl(spi), x->id.proto);
+			switch(x->props.family) {
+			case AF_INET:
+				x0 = xfrm4_state_lookup(x->id.daddr.xfrm4_addr, minspi, x->id.proto);
+				break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+			case AF_INET6:
+				x0 = xfrm6_state_lookup((struct in6_addr*)x->id.daddr.a6, minspi, x->id.proto);
+				break;
+#endif
+			default:
+				x0 = NULL;
+			}
 			if (x0 == NULL)
 				break;
 			xfrm_state_put(x0);
@@ -512,7 +740,18 @@
 	}
 	if (x->id.spi) {
 		spin_lock_bh(&xfrm_state_lock);
-		h = ntohl(x->id.daddr.xfrm4_addr^x->id.spi^x->id.proto);
+		switch(x->props.family) {
+		case AF_INET:
+			h = ntohl(x->id.daddr.xfrm4_addr^x->id.spi^x->id.proto);
+			break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+		case AF_INET6:
+			h = ntohl(x->id.daddr.a6[2]^x->id.daddr.a6[3]^x->id.spi^x->id.proto);
+			break;
+#endif
+		default:
+			h = 0;	/* XXX */
+		}
 		h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
 		list_add(&x->byspi, xfrm_state_byspi+h);
 		atomic_inc(&x->refcnt);
@@ -605,14 +844,21 @@
 	int i;
 
 	for (i=0; i<n; i++) {
-		if (x[i]->props.family == AF_INET &&
-		    !xfrm4_selector_match(&x[i]->sel, fl))
-			return -EINVAL;
+		int match;
+		switch(x[i]->props.family) {
+		case AF_INET:
+			match = xfrm4_selector_match(&x[i]->sel, fl);
+			break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-		if (x[i]->props.family == AF_INET6 &&
-		    !xfrm6_selector_match(&x[i]->sel, fl))
-			return -EINVAL;
+		case AF_INET6:
+			match = xfrm6_selector_match(&x[i]->sel, fl);
+			break;
 #endif
+		default:
+			match = 0;
+		}
+		if (!match)
+			return -EINVAL;
 	}
 	return 0;
 }
@@ -680,7 +926,7 @@
 	err = -EINVAL;
 	read_lock(&xfrm_km_lock);
 	list_for_each_entry(km, &xfrm_km_list, list) {
-		pol = km->compile_policy(optname, data, optlen, &err);
+		pol = km->compile_policy(sk->family, optname, data, optlen, &err);
 		if (err >= 0)
 			break;
 	}
@@ -722,118 +968,3 @@
 	}
 }
 
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-struct xfrm_state *
-xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto)
-{
-	unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]^spi^proto);
-	struct xfrm_state *x;
-
-	h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
-
-	spin_lock_bh(&xfrm_state_lock);
-	list_for_each_entry(x, xfrm_state_byspi+h, byspi) {
-		if (x->props.family == AF_INET6 &&
-		    spi == x->id.spi &&
-		    !ipv6_addr_cmp(daddr, (struct in6_addr *)x->id.daddr.a6) &&
-		    proto == x->id.proto) {
-			atomic_inc(&x->refcnt);
-			spin_unlock_bh(&xfrm_state_lock);
-			return x;
-		}
-	}
-	spin_unlock_bh(&xfrm_state_lock);
-	return NULL;
-}
-
-struct xfrm_state *
-xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr, struct in6_addr *saddr, int create)
-{
-	struct xfrm_state *x, *x0;
-	unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]);
-
-	h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
-	x0 = NULL;
-
-	spin_lock_bh(&xfrm_state_lock);
-	list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
-		if (x->props.family == AF_INET6 &&
-		    !memcmp(daddr, x->id.daddr.a6, sizeof(struct in6_addr)) &&
-		    mode == x->props.mode &&
-		    proto == x->id.proto &&
-		    !memcmp(saddr, x->props.saddr.a6, sizeof(struct in6_addr)) &&
-		    reqid == x->props.reqid &&
-		    x->km.state == XFRM_STATE_ACQ) {
-			    if (!x0)
-				    x0 = x;
-			    if (x->id.spi)
-				    continue;
-			    x0 = x;
-			    break;
-		    }
-	}
-	if (x0) {
-		atomic_inc(&x0->refcnt);
-	} else if (create && (x0 = xfrm_state_alloc()) != NULL) {
-		memcpy(x0->sel.daddr.a6, daddr, sizeof(struct in6_addr));
-		memcpy(x0->sel.saddr.a6, saddr, sizeof(struct in6_addr));
-		x0->sel.prefixlen_d = 128;
-		x0->sel.prefixlen_s = 128;
-		memcpy(x0->props.saddr.a6, saddr, sizeof(struct in6_addr));
-		x0->km.state = XFRM_STATE_ACQ;
-		memcpy(x0->id.daddr.a6, daddr, sizeof(struct in6_addr));
-		x0->id.proto = proto;
-		x0->props.family = AF_INET6;
-		x0->props.mode = mode;
-		x0->props.reqid = reqid;
-		x0->lft.hard_add_expires_seconds = ACQ_EXPIRES;
-		atomic_inc(&x0->refcnt);
-		mod_timer(&x0->timer, jiffies + ACQ_EXPIRES*HZ);
-		atomic_inc(&x0->refcnt);
-		list_add_tail(&x0->bydst, xfrm_state_bydst+h);
-		wake_up(&km_waitq);
-	}
-	spin_unlock_bh(&xfrm_state_lock);
-	return x0;
-}
-
-void
-xfrm6_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi)
-{
-	u32 h;
-	struct xfrm_state *x0;
-
-	if (x->id.spi)
-		return;
-
-	if (minspi == maxspi) {
-		x0 = xfrm6_state_lookup((struct in6_addr*)x->id.daddr.a6, minspi, x->id.proto);
-		if (x0) {
-			xfrm_state_put(x0);
-			return;
-		}
-		x->id.spi = minspi;
-	} else {
-		u32 spi = 0;
-		minspi = ntohl(minspi);
-		maxspi = ntohl(maxspi);
-		for (h=0; h<maxspi-minspi+1; h++) {
-			spi = minspi + net_random()%(maxspi-minspi+1);
-			x0 = xfrm6_state_lookup((struct in6_addr*)x->id.daddr.a6, htonl(spi), x->id.proto);
-			if (x0 == NULL)
-				break;
-			xfrm_state_put(x0);
-		}
-		x->id.spi = htonl(spi);
-	}
-	if (x->id.spi) {
-		spin_lock_bh(&xfrm_state_lock);
-		h = ntohl(x->id.daddr.a6[2]^x->id.daddr.a6[3]^x->id.spi^x->id.proto);
-		h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
-		list_add(&x->byspi, xfrm_state_byspi+h);
-		atomic_inc(&x->refcnt);
-		spin_unlock_bh(&xfrm_state_lock);
-		wake_up(&km_waitq);
-	}
-}
-#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
diff -Nru a/net/ipv4/xfrm_user.c b/net/ipv4/xfrm_user.c
--- a/net/ipv4/xfrm_user.c	Wed Feb 19 14:02:51 2003
+++ b/net/ipv4/xfrm_user.c	Wed Mar  5 15:45:36 2003
@@ -234,8 +234,8 @@
 
 	switch (x->props.family) {
 	case AF_INET:
-		x1 = xfrm_state_lookup(x->props.saddr.xfrm4_addr,
-				       x->id.spi, x->id.proto);
+		x1 = xfrm4_state_lookup(x->props.saddr.xfrm4_addr,
+					x->id.spi, x->id.proto);
 		break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
@@ -265,7 +265,7 @@
 
 	switch (p->family) {
 	case AF_INET:
-		x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
+		x = xfrm4_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
 		break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
@@ -395,7 +395,7 @@
 
 	switch (p->family) {
 	case AF_INET:
-		x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
+		x = xfrm4_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
 		break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
@@ -538,6 +538,21 @@
 		return -EINVAL;
 	};
 
+	switch (p->family) {
+	case AF_INET:
+		break;
+
+	case AF_INET6:
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+		break;
+#else
+		return  -EAFNOSUPPORT;
+#endif
+
+	default:
+		return -EINVAL;
+	};
+
 	return verify_policy_dir(p->dir);
 }
 
@@ -1057,7 +1072,8 @@
 /* User gives us xfrm_user_policy_info followed by an array of 0
  * or more templates.
  */
-struct xfrm_policy *xfrm_compile_policy(int opt, u8 *data, int len, int *dir)
+struct xfrm_policy *xfrm_compile_policy(u16 family, int opt,
+                                        u8 *data, int len, int *dir)
 {
 	struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data;
 	struct xfrm_user_tmpl *ut = (struct xfrm_user_tmpl *) (p + 1);
diff -Nru a/net/ipv6/Kconfig b/net/ipv6/Kconfig
--- a/net/ipv6/Kconfig	Sun Feb 23 22:46:32 2003
+++ b/net/ipv6/Kconfig	Wed Mar  5 15:45:36 2003
@@ -17,5 +17,20 @@
 
 	  See <file:Documentation/networking/ip-sysctl.txt> for details.
 
-source "net/ipv6/netfilter/Kconfig"
+config INET6_AH
+	tristate "IPv6: AH transformation"
+	depends on IPV6
+	---help---
+	  Support for IPsec AH.
+
+	  If unsure, say Y.
+
+config INET6_ESP
+	tristate "IPv6: ESP transformation"
+	depends on IPV6
+	---help---
+	  Support for IPsec ESP.
 
+	  If unsure, say Y.
+
+source "net/ipv6/netfilter/Kconfig"
diff -Nru a/net/ipv6/Makefile b/net/ipv6/Makefile
--- a/net/ipv6/Makefile	Wed Feb 19 14:32:20 2003
+++ b/net/ipv6/Makefile	Wed Mar  5 15:45:36 2003
@@ -10,4 +10,6 @@
 		exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
 		ip6_flowlabel.o ipv6_syms.o
 
+obj-$(CONFIG_INET6_AH) += ah6.o
+obj-$(CONFIG_INET6_ESP) += esp6.o
 obj-$(CONFIG_NETFILTER)	+= netfilter/
diff -Nru a/net/ipv6/ah6.c b/net/ipv6/ah6.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/net/ipv6/ah6.c	Thu Mar  6 16:16:15 2003
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C)2002 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 @USAGI       : IPv6 Support 
+ * 	Kazunori MIYAZAWA @USAGI   :
+ * 	Kunihiro Ishiguro          :
+ * 	
+ * 	This file is derived from net/ipv4/ah.c.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+#include <net/ah.h>
+#include <linux/crypto.h>
+#include <linux/pfkeyv2.h>
+#include <net/icmp.h>
+#include <net/ipv6.h>
+#include <net/xfrm.h>
+#include <asm/scatterlist.h>
+
+#define AH_HLEN_NOICV	12
+
+/* XXX no ipv6 ah specific */
+#define NIP6(addr) \
+	ntohs((addr).s6_addr16[0]),\
+	ntohs((addr).s6_addr16[1]),\
+	ntohs((addr).s6_addr16[2]),\
+	ntohs((addr).s6_addr16[3]),\
+	ntohs((addr).s6_addr16[4]),\
+	ntohs((addr).s6_addr16[5]),\
+	ntohs((addr).s6_addr16[6]),\
+	ntohs((addr).s6_addr16[7])
+
+int ah6_output(struct sk_buff *skb)
+{
+	int err;
+	int hdr_len = sizeof(struct ipv6hdr);
+	struct dst_entry *dst = skb->dst;
+	struct xfrm_state *x  = dst->xfrm;
+	struct ipv6hdr *iph = NULL;
+	struct ip_auth_hdr *ah;
+	struct ah_data *ahp;
+	u16 nh_offset = 0;
+	u8 nexthdr;
+printk(KERN_DEBUG "%s\n", __FUNCTION__);
+	if (skb->ip_summed == CHECKSUM_HW && skb_checksum_help(skb) == NULL)
+		return -EINVAL;
+
+	spin_lock_bh(&x->lock);
+	if ((err = xfrm_state_check_expire(x)) != 0)
+		goto error;
+	if ((err = xfrm_state_check_space(x, skb)) != 0)
+		goto error;
+
+	if (x->props.mode) {
+		iph = skb->nh.ipv6h;
+		skb->nh.ipv6h = (struct ipv6hdr*)skb_push(skb, x->props.header_len);
+		skb->nh.ipv6h->version = 6;
+		skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+		skb->nh.ipv6h->nexthdr = IPPROTO_AH;
+		memcpy(&skb->nh.ipv6h->saddr, &x->props.saddr, sizeof(struct in6_addr));
+		memcpy(&skb->nh.ipv6h->daddr, &x->id.daddr, sizeof(struct in6_addr));
+		ah = (struct ip_auth_hdr*)(skb->nh.ipv6h+1);
+		ah->nexthdr = IPPROTO_IPV6;
+	} else {
+		hdr_len = skb->h.raw - skb->nh.raw;
+		iph = kmalloc(hdr_len, GFP_ATOMIC);
+		if (!iph) {
+			err = -ENOMEM;
+			goto error;
+		}
+		memcpy(iph, skb->data, hdr_len);
+		skb->nh.ipv6h = (struct ipv6hdr*)skb_push(skb, x->props.header_len);
+		memcpy(skb->nh.ipv6h, iph, hdr_len);
+		nexthdr = xfrm6_clear_mutable_options(skb, &nh_offset, XFRM_POLICY_OUT);
+		if (nexthdr == 0)
+			goto error;
+
+		skb->nh.raw[nh_offset] = IPPROTO_AH;
+		skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+		ah = (struct ip_auth_hdr*)(skb->nh.raw+hdr_len);
+		skb->h.raw = (unsigned char*) ah;
+		ah->nexthdr = nexthdr;
+	}
+
+	skb->nh.ipv6h->priority    = 0;
+	skb->nh.ipv6h->flow_lbl[0] = 0;
+	skb->nh.ipv6h->flow_lbl[1] = 0;
+	skb->nh.ipv6h->flow_lbl[2] = 0;
+	skb->nh.ipv6h->hop_limit    = 0;
+
+	ahp = x->data;
+	ah->hdrlen  = (XFRM_ALIGN8(ahp->icv_trunc_len +
+		AH_HLEN_NOICV) >> 2) - 2;
+
+	ah->reserved = 0;
+	ah->spi = x->id.spi;
+	ah->seq_no = htonl(++x->replay.oseq);
+	ahp->icv(ahp, skb, ah->auth_data);
+
+	if (x->props.mode) {
+		skb->nh.ipv6h->hop_limit   = iph->hop_limit;
+		skb->nh.ipv6h->priority    = iph->priority; 	
+		skb->nh.ipv6h->flow_lbl[0] = iph->flow_lbl[0];
+		skb->nh.ipv6h->flow_lbl[1] = iph->flow_lbl[1];
+		skb->nh.ipv6h->flow_lbl[2] = iph->flow_lbl[2];
+	} else {
+		memcpy(skb->nh.ipv6h, iph, hdr_len);
+		skb->nh.raw[nh_offset] = IPPROTO_AH;
+		skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+		kfree (iph);
+	}
+
+	skb->nh.raw = skb->data;
+
+	x->curlft.bytes += skb->len;
+	x->curlft.packets++;
+	spin_unlock_bh(&x->lock);
+	if ((skb->dst = dst_pop(dst)) == NULL)
+		goto error_nolock;
+	return NET_XMIT_BYPASS;
+error:
+	spin_unlock_bh(&x->lock);
+error_nolock:
+	kfree_skb(skb);
+	return err;
+}
+
+int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+	int ah_hlen;
+	struct ipv6hdr *iph;
+	struct ipv6_auth_hdr *ah;
+	struct ah_data *ahp;
+	unsigned char *tmp_hdr = NULL;
+	int hdr_len = skb->h.raw - skb->nh.raw;
+	u8 nexthdr = 0;
+
+	if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr)))
+		goto out;
+
+	ah = (struct ipv6_auth_hdr*)skb->data;
+	ahp = x->data;
+        ah_hlen = (ah->hdrlen + 2) << 2;
+
+        if (ah_hlen != XFRM_ALIGN8(ahp->icv_full_len + AH_HLEN_NOICV) &&
+            ah_hlen != XFRM_ALIGN8(ahp->icv_trunc_len + AH_HLEN_NOICV))
+                goto out;
+
+	if (!pskb_may_pull(skb, ah_hlen))
+		goto out;
+
+	/* We are going to _remove_ AH header to keep sockets happy,
+	 * so... Later this can change. */
+	if (skb_cloned(skb) &&
+	    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+		goto out;
+
+	tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC);
+	if (!tmp_hdr)
+		goto out;
+	memcpy(tmp_hdr, skb->nh.raw, hdr_len);
+	ah = (struct ipv6_auth_hdr*)skb->data;
+	iph = skb->nh.ipv6h;
+
+        {
+		u8 auth_data[ahp->icv_trunc_len];
+
+		memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
+		skb_push(skb, skb->data - skb->nh.raw);
+		ahp->icv(ahp, skb, ah->auth_data);
+		if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ipsec ah authentication error\n");
+			x->stats.integrity_failed++;
+			goto free_out;
+		}
+	}
+
+	nexthdr = ah->nexthdr;
+	skb->nh.raw = skb_pull(skb, (ah->hdrlen+2)<<2);
+	memcpy(skb->nh.raw, tmp_hdr, hdr_len);
+	skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+	skb_pull(skb, hdr_len);
+	skb->h.raw = skb->data;
+
+
+	kfree(tmp_hdr);
+
+	return nexthdr;
+
+free_out:
+	kfree(tmp_hdr);
+out:
+	return -EINVAL;
+}
+
+void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 
+	 int type, int code, int offset, __u32 info)
+{
+	struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
+	struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+offset);
+	struct xfrm_state *x;
+
+	if (type != ICMPV6_DEST_UNREACH ||
+	    type != ICMPV6_PKT_TOOBIG)
+		return;
+
+	x = xfrm6_state_lookup(&iph->daddr, ah->spi, IPPROTO_AH);
+	if (!x)
+		return;
+
+	printk(KERN_DEBUG "pmtu discvovery on SA AH/%08x/"
+			"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+	       ntohl(ah->spi), NIP6(iph->daddr));
+
+	xfrm_state_put(x);
+}
+
+static int ah6_init_state(struct xfrm_state *x, void *args)
+{
+	struct ah_data *ahp = NULL;
+	struct xfrm_algo_desc *aalg_desc;
+
+	/* null auth can use a zero length key */
+	if (x->aalg->alg_key_len > 512)
+		goto error;
+
+	ahp = kmalloc(sizeof(*ahp), GFP_KERNEL);
+	if (ahp == NULL)
+		return -ENOMEM;
+
+	memset(ahp, 0, sizeof(*ahp));
+
+	ahp->key = x->aalg->alg_key;
+	ahp->key_len = (x->aalg->alg_key_len+7)/8;
+	ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
+	if (!ahp->tfm)
+		goto error;
+	ahp->icv = ah_hmac_digest;
+	
+	/*
+	 * Lookup the algorithm description maintained by xfrm_algo,
+	 * verify crypto transform properties, and store information
+	 * we need for AH processing.  This lookup cannot fail here
+	 * after a successful crypto_alloc_tfm().
+	 */
+	aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name);
+	BUG_ON(!aalg_desc);
+
+	if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
+	    crypto_tfm_alg_digestsize(ahp->tfm)) {
+		printk(KERN_INFO "AH: %s digestsize %u != %hu\n",
+		       x->aalg->alg_name, crypto_tfm_alg_digestsize(ahp->tfm),
+		       aalg_desc->uinfo.auth.icv_fullbits/8);
+		goto error;
+	}
+	
+	ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
+	ahp->icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
+	
+	ahp->work_icv = kmalloc(ahp->icv_full_len, GFP_KERNEL);
+	if (!ahp->work_icv)
+		goto error;
+	
+	x->props.header_len = XFRM_ALIGN8(ahp->icv_trunc_len + AH_HLEN_NOICV);
+	if (x->props.mode)
+		x->props.header_len += 20;
+	x->data = ahp;
+
+	return 0;
+
+error:
+	if (ahp) {
+		if (ahp->work_icv)
+			kfree(ahp->work_icv);
+		if (ahp->tfm)
+			crypto_free_tfm(ahp->tfm);
+		kfree(ahp);
+	}
+	return -EINVAL;
+}
+
+static void ah6_destroy(struct xfrm_state *x)
+{
+	struct ah_data *ahp = x->data;
+
+	if (ahp->work_icv) {
+		kfree(ahp->work_icv);
+		ahp->work_icv = NULL;
+	}
+	if (ahp->tfm) {
+		crypto_free_tfm(ahp->tfm);
+		ahp->tfm = NULL;
+	}
+}
+
+static struct xfrm_type ah6_type =
+{
+	.description	= "AH6",
+	.proto	     	= IPPROTO_AH,
+	.init_state	= ah6_init_state,
+	.destructor	= ah6_destroy,
+	.input		= ah6_input,
+	.output		= ah6_output
+};
+
+static struct inet6_protocol ah6_protocol = {
+	.handler	=	xfrm6_rcv,
+	.err_handler	=	ah6_err,
+};
+
+int __init ah6_init(void)
+{
+	SET_MODULE_OWNER(&ah6_type);
+
+	if (xfrm6_register_type(&ah6_type) < 0) {
+		printk(KERN_INFO "ipv6 ah init: can't add xfrm type\n");
+		return -EAGAIN;
+	}
+
+	if (inet6_add_protocol(&ah6_protocol, IPPROTO_AH) < 0) {
+		printk(KERN_INFO "ipv6 ah init: can't add protocol\n");
+		xfrm6_unregister_type(&ah6_type);
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+static void __exit ah6_fini(void)
+{
+	if (inet6_del_protocol(&ah6_protocol, IPPROTO_AH) < 0)
+		printk(KERN_INFO "ipv6 ah close: can't remove protocol\n");
+
+	if (xfrm6_unregister_type(&ah6_type) < 0)
+		printk(KERN_INFO "ipv6 ah close: can't remove xfrm type\n");
+
+}
+
+module_init(ah6_init);
+module_exit(ah6_fini);
+
+MODULE_LICENSE("GPL");
diff -Nru a/net/ipv6/esp6.c b/net/ipv6/esp6.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/net/ipv6/esp6.c	Thu Mar  6 16:16:15 2003
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C)2002 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 @USAGI       : IPv6 Support 
+ * 	Kazunori MIYAZAWA @USAGI   :
+ * 	Kunihiro Ishiguro          :
+ * 	
+ * 	This file is derived from net/ipv4/esp.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+#include <net/esp.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+#include <linux/pfkeyv2.h>
+#include <linux/random.h>
+#include <net/icmp.h>
+#include <net/ipv6.h>
+#include <linux/icmpv6.h>
+
+#define MAX_SG_ONSTACK 4
+
+/* BUGS:
+ * - we assume replay seqno is always present.
+ */
+
+/* Move to common area: it is shared with AH. */
+/* Common with AH after some work on arguments. */
+
+/* XXX no ipv6 esp specific */
+#define NIP6(addr) \
+	ntohs((addr).s6_addr16[0]),\
+	ntohs((addr).s6_addr16[1]),\
+	ntohs((addr).s6_addr16[2]),\
+	ntohs((addr).s6_addr16[3]),\
+	ntohs((addr).s6_addr16[4]),\
+	ntohs((addr).s6_addr16[5]),\
+	ntohs((addr).s6_addr16[6]),\
+	ntohs((addr).s6_addr16[7])
+
+static int get_offset(u8 *packet, u32 packet_len, u8 *nexthdr, struct ipv6_opt_hdr **prevhdr)
+{
+	u16 offset = sizeof(struct ipv6hdr);
+	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(packet + offset);
+	u8 nextnexthdr;
+
+	*nexthdr = ((struct ipv6hdr*)packet)->nexthdr;
+
+	while (offset + 1 < packet_len) {
+
+		switch (*nexthdr) {
+
+		case NEXTHDR_HOP:
+		case NEXTHDR_ROUTING:
+			offset += ipv6_optlen(exthdr);
+			*nexthdr = exthdr->nexthdr;
+			*prevhdr = exthdr;
+			exthdr = (struct ipv6_opt_hdr*)(packet + offset);
+			break;
+
+		case NEXTHDR_DEST:
+			nextnexthdr =
+				((struct ipv6_opt_hdr*)(packet + offset + ipv6_optlen(exthdr)))->nexthdr;
+			/* XXX We know the option is inner dest opt
+			   with next next header check. */
+			if (nextnexthdr != NEXTHDR_HOP &&
+		    	    nextnexthdr != NEXTHDR_ROUTING &&
+			    nextnexthdr != NEXTHDR_DEST) {
+					return offset;
+			}
+			offset += ipv6_optlen(exthdr);
+			*nexthdr = exthdr->nexthdr;
+			*prevhdr = exthdr;
+			exthdr = (struct ipv6_opt_hdr*)(packet + offset);
+			break;
+
+		default :
+			return offset;
+		}
+	}
+
+	return offset;
+}
+
+int esp6_output(struct sk_buff *skb)
+{
+	int err;
+	int hdr_len = 0;
+	struct dst_entry *dst = skb->dst;
+	struct xfrm_state *x  = dst->xfrm;
+	struct ipv6hdr *iph = NULL, *top_iph;
+	struct ip_esp_hdr *esph;
+	struct crypto_tfm *tfm;
+	struct esp_data *esp;
+	struct sk_buff *trailer;
+	struct ipv6_opt_hdr *prevhdr = NULL;
+	int blksize;
+	int clen;
+	int alen;
+	int nfrags;
+	u8 nexthdr;
+printk(KERN_DEBUG "%s\n", __FUNCTION__);
+	/* First, if the skb is not checksummed, complete checksum. */
+	if (skb->ip_summed == CHECKSUM_HW && skb_checksum_help(skb) == NULL)
+		return -EINVAL;
+
+	spin_lock_bh(&x->lock);
+	if ((err = xfrm_state_check_expire(x)) != 0)
+		goto error;
+	if ((err = xfrm_state_check_space(x, skb)) != 0)
+		goto error;
+
+	err = -ENOMEM;
+
+	/* Strip IP header in transport mode. Save it. */
+
+	if (!x->props.mode) {
+		hdr_len = get_offset(skb->nh.raw, skb->len, &nexthdr, &prevhdr);
+		iph = kmalloc(hdr_len, GFP_ATOMIC);
+		if (!iph) {
+			err = -ENOMEM;
+			goto error;
+		}
+		memcpy(iph, skb->nh.raw, hdr_len);
+		__skb_pull(skb, hdr_len);
+	}
+
+	/* Now skb is pure payload to encrypt */
+
+	/* Round to block size */
+	clen = skb->len;
+
+	esp = x->data;
+	alen = esp->auth.icv_trunc_len;
+	tfm = esp->conf.tfm;
+	blksize = crypto_tfm_alg_blocksize(tfm);
+	clen = (clen + 2 + blksize-1)&~(blksize-1);
+	if (esp->conf.padlen)
+		clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1);
+
+	if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) {
+		if (!x->props.mode && iph) kfree(iph);
+		goto error;
+	}
+
+	/* Fill padding... */
+	do {
+		int i;
+		for (i=0; i<clen-skb->len - 2; i++)
+			*(u8*)(trailer->tail + i) = i+1;
+	} while (0);
+	*(u8*)(trailer->tail + clen-skb->len - 2) = (clen - skb->len)-2;
+	pskb_put(skb, trailer, clen - skb->len);
+
+	if (x->props.mode) {
+		iph = skb->nh.ipv6h;
+		top_iph = (struct ipv6hdr*)skb_push(skb, x->props.header_len);
+		esph = (struct ip_esp_hdr*)(top_iph+1);
+		*(u8*)(trailer->tail - 1) = IPPROTO_IPV6;
+		top_iph->version = 6;
+		top_iph->priority = iph->priority;
+		top_iph->flow_lbl[0] = iph->flow_lbl[0];
+		top_iph->flow_lbl[1] = iph->flow_lbl[1];
+		top_iph->flow_lbl[2] = iph->flow_lbl[2];
+		top_iph->nexthdr = IPPROTO_ESP;
+		top_iph->payload_len = htons(skb->len + alen);
+		top_iph->hop_limit = iph->hop_limit;
+		memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, sizeof(struct ipv6hdr));
+		memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct ipv6hdr));
+	} else { 
+		/* XXX exthdr */
+		esph = (struct ip_esp_hdr*)skb_push(skb, x->props.header_len);
+		skb->h.raw = (unsigned char*)esph;
+		top_iph = (struct ipv6hdr*)skb_push(skb, hdr_len);
+		memcpy(top_iph, iph, hdr_len);
+		kfree(iph);
+		top_iph->payload_len = htons(skb->len + alen - sizeof(struct ipv6hdr));
+		if (prevhdr) {
+			prevhdr->nexthdr = IPPROTO_ESP;
+		} else {
+			top_iph->nexthdr = IPPROTO_ESP;
+		}
+		*(u8*)(trailer->tail - 1) = nexthdr;
+	}
+
+	esph->spi = x->id.spi;
+	esph->seq_no = htonl(++x->replay.oseq);
+
+	if (esp->conf.ivlen)
+		crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
+
+	do {
+		struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags];
+		struct scatterlist *sg = sgbuf;
+
+		if (unlikely(nfrags > MAX_SG_ONSTACK)) {
+			sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
+			if (!sg)
+				goto error;
+		}
+		skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen);
+		crypto_cipher_encrypt(tfm, sg, sg, clen);
+		if (unlikely(sg != sgbuf))
+			kfree(sg);
+	} while (0);
+
+	if (esp->conf.ivlen) {
+		memcpy(esph->enc_data, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
+		crypto_cipher_get_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
+	}
+
+	if (esp->auth.icv_full_len) {
+		esp->auth.icv(esp, skb, (u8*)esph-skb->data,
+			8+esp->conf.ivlen+clen, trailer->tail);
+		pskb_put(skb, trailer, alen);
+	}
+
+	skb->nh.raw = skb->data;
+
+	x->curlft.bytes += skb->len;
+	x->curlft.packets++;
+	spin_unlock_bh(&x->lock);
+	if ((skb->dst = dst_pop(dst)) == NULL)
+		goto error_nolock;
+	return NET_XMIT_BYPASS;
+
+error:
+	spin_unlock_bh(&x->lock);
+error_nolock:
+	kfree_skb(skb);
+	return err;
+}
+
+int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+	struct ipv6hdr *iph;
+	struct ip_esp_hdr *esph;
+	struct esp_data *esp = x->data;
+	struct sk_buff *trailer;
+	int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
+	int alen = esp->auth.icv_trunc_len;
+	int elen = skb->len - 8 - esp->conf.ivlen - alen;
+
+	int hdr_len = skb->h.raw - skb->nh.raw;
+	int nfrags;
+	u8 ret_nexthdr = 0;
+	unsigned char *tmp_hdr = NULL;
+
+	if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr)))
+		goto out;
+
+	if (elen <= 0 || (elen & (blksize-1)))
+		goto out;
+
+	tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC);
+	if (!tmp_hdr)
+		goto out;
+	memcpy(tmp_hdr, skb->nh.raw, hdr_len);
+
+	/* If integrity check is required, do this. */
+        if (esp->auth.icv_full_len) {
+		u8 sum[esp->auth.icv_full_len];
+		u8 sum1[alen];
+
+		esp->auth.icv(esp, skb, 0, skb->len-alen, sum);
+
+		if (skb_copy_bits(skb, skb->len-alen, sum1, alen))
+			BUG();
+
+		if (unlikely(memcmp(sum, sum1, alen))) {
+			x->stats.integrity_failed++;
+			goto out;
+		}
+	}
+
+	if ((nfrags = skb_cow_data(skb, 0, &trailer)) < 0)
+		goto out;
+
+	skb->ip_summed = CHECKSUM_NONE;
+
+	esph = (struct ip_esp_hdr*)skb->data;
+	iph = skb->nh.ipv6h;
+
+	/* Get ivec. This can be wrong, check against another impls. */
+	if (esp->conf.ivlen)
+		crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm));
+
+        {
+		u8 nexthdr[2];
+		struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags];
+		struct scatterlist *sg = sgbuf;
+		u8 padlen;
+
+		if (unlikely(nfrags > MAX_SG_ONSTACK)) {
+			sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
+			if (!sg)
+				goto out;
+		}
+		skb_to_sgvec(skb, sg, 8+esp->conf.ivlen, elen);
+		crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen);
+		if (unlikely(sg != sgbuf))
+			kfree(sg);
+
+		if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
+			BUG();
+
+		padlen = nexthdr[0];
+		if (padlen+2 >= elen) {
+			if (net_ratelimit()) {
+				printk(KERN_WARNING "ipsec esp packet is garbage padlen=%d, elen=%d\n", padlen+2, elen);
+			}
+			goto out;
+		}
+		/* ... check padding bits here. Silly. :-) */ 
+
+		ret_nexthdr = nexthdr[1];
+		pskb_trim(skb, skb->len - alen - padlen - 2);
+		skb->h.raw = skb_pull(skb, 8 + esp->conf.ivlen);
+		skb->nh.raw += 8 + esp->conf.ivlen;
+		memcpy(skb->nh.raw, tmp_hdr, hdr_len);
+	}
+	kfree(tmp_hdr);
+	return ret_nexthdr;
+
+out:
+	return -EINVAL;
+}
+
+static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
+{
+	struct esp_data *esp = x->data;
+	u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm);
+
+	if (x->props.mode) {
+		mtu = (mtu + 2 + blksize-1)&~(blksize-1);
+	} else {
+		/* The worst case. */
+		mtu += 2 + blksize;
+	}
+	if (esp->conf.padlen)
+		mtu = (mtu + esp->conf.padlen-1)&~(esp->conf.padlen-1);
+
+	return mtu + x->props.header_len + esp->auth.icv_full_len;
+}
+
+void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+		int type, int code, int offset, __u32 info)
+{
+	struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
+	struct ip_esp_hdr *esph = (struct ip_esp_hdr*)(skb->data+offset);
+	struct xfrm_state *x;
+
+	if (type != ICMPV6_DEST_UNREACH ||
+	    type != ICMPV6_PKT_TOOBIG)
+		return;
+
+	x = xfrm6_state_lookup(&iph->daddr, esph->spi, IPPROTO_ESP);
+	if (!x)
+		return;
+	printk(KERN_DEBUG "pmtu discvovery on SA ESP/%08x/"
+			"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", 
+			ntohl(esph->spi), NIP6(iph->daddr));
+	xfrm_state_put(x);
+}
+
+void esp6_destroy(struct xfrm_state *x)
+{
+	struct esp_data *esp = x->data;
+
+	if (esp->conf.tfm) {
+		crypto_free_tfm(esp->conf.tfm);
+		esp->conf.tfm = NULL;
+	}
+	if (esp->conf.ivec) {
+		kfree(esp->conf.ivec);
+		esp->conf.ivec = NULL;
+	}
+	if (esp->auth.tfm) {
+		crypto_free_tfm(esp->auth.tfm);
+		esp->auth.tfm = NULL;
+	}
+	if (esp->auth.work_icv) {
+		kfree(esp->auth.work_icv);
+		esp->auth.work_icv = NULL;
+	}
+}
+
+int esp6_init_state(struct xfrm_state *x, void *args)
+{
+	struct esp_data *esp = NULL;
+
+	if (x->aalg) {
+		if (x->aalg->alg_key_len == 0 || x->aalg->alg_key_len > 512)
+			goto error;
+	}
+	if (x->ealg == NULL || x->ealg->alg_key_len == 0)
+		goto error;
+
+	esp = kmalloc(sizeof(*esp), GFP_KERNEL);
+	if (esp == NULL)
+		return -ENOMEM;
+
+	memset(esp, 0, sizeof(*esp));
+
+	if (x->aalg) {
+		struct xfrm_algo_desc *aalg_desc;
+
+		esp->auth.key = x->aalg->alg_key;
+		esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
+		esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
+		if (esp->auth.tfm == NULL)
+			goto error;
+		esp->auth.icv = esp_hmac_digest;
+ 
+		aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name);
+		BUG_ON(!aalg_desc);
+ 
+		if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
+			crypto_tfm_alg_digestsize(esp->auth.tfm)) {
+				printk(KERN_INFO "ESP: %s digestsize %u != %hu\n",
+					x->aalg->alg_name,
+					crypto_tfm_alg_digestsize(esp->auth.tfm),
+					aalg_desc->uinfo.auth.icv_fullbits/8);
+				goto error;
+		}
+ 
+		esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
+		esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
+ 
+		esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL);
+		if (!esp->auth.work_icv)
+			goto error;
+	}
+	esp->conf.key = x->ealg->alg_key;
+	esp->conf.key_len = (x->ealg->alg_key_len+7)/8;
+	esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC);
+	if (esp->conf.tfm == NULL)
+		goto error;
+	esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm);
+	esp->conf.padlen = 0;
+	if (esp->conf.ivlen) {
+		esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
+		get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
+	}
+	crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len);
+	x->props.header_len = 8 + esp->conf.ivlen;
+	if (x->props.mode)
+		x->props.header_len += 40;  /* XXX ext hdr */
+	x->data = esp;
+	return 0;
+
+error:
+	if (esp) {
+		if (esp->auth.tfm)
+			crypto_free_tfm(esp->auth.tfm);
+		if (esp->auth.work_icv)
+			kfree(esp->auth.work_icv);
+		if (esp->conf.tfm)
+			crypto_free_tfm(esp->conf.tfm);
+		kfree(esp);
+	}
+	return -EINVAL;
+}
+
+static struct xfrm_type esp6_type =
+{
+	.description	= "ESP6",
+	.proto	     	= IPPROTO_ESP,
+	.init_state	= esp6_init_state,
+	.destructor	= esp6_destroy,
+	.get_max_size	= esp6_get_max_size,
+	.input		= esp6_input,
+	.output		= esp6_output
+};
+
+static struct inet6_protocol esp6_protocol = {
+	.handler 	=	xfrm6_rcv,
+	.err_handler	=	esp6_err,
+};
+
+int __init esp6_init(void)
+{
+	SET_MODULE_OWNER(&esp6_type);
+	if (xfrm6_register_type(&esp6_type) < 0) {
+		printk(KERN_INFO "ipv6 esp init: can't add xfrm type\n");
+		return -EAGAIN;
+	}
+	if (inet6_add_protocol(&esp6_protocol, IPPROTO_ESP) < 0) {
+		printk(KERN_INFO "ipv6 esp init: can't add protocol\n");
+		xfrm6_unregister_type(&esp6_type);
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+static void __exit esp6_fini(void)
+{
+	if (inet6_del_protocol(&esp6_protocol, IPPROTO_ESP) < 0)
+		printk(KERN_INFO "ipv6 esp close: can't remove protocol\n");
+	if (xfrm6_unregister_type(&esp6_type) < 0)
+		printk(KERN_INFO "ipv6 esp close: can't remove xfrm type\n");
+}
+
+module_init(esp6_init);
+module_exit(esp6_fini);
+
+MODULE_LICENSE("GPL");
diff -Nru a/net/ipv6/icmp.c b/net/ipv6/icmp.c
--- a/net/ipv6/icmp.c	Mon Feb 24 03:18:25 2003
+++ b/net/ipv6/icmp.c	Thu Mar  6 16:30:30 2003
@@ -353,7 +353,7 @@
 	ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
 		       MSG_DONTWAIT);
 	if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
-		ICMP6_STATS_PTR_BH(Icmp6OutDestUnreachs) [type-1]++;
+		ICMP6_STATS_PTR_BH(Icmp6OutDestUnreachs) [type-ICMPV6_DEST_UNREACH]++;
 	ICMP6_INC_STATS_BH(Icmp6OutMsgs);
 out:
 	icmpv6_xmit_unlock();
@@ -524,7 +524,7 @@
 		break;
 
 	case ICMPV6_ECHO_REPLY:
-		/* we coulnd't care less */
+		/* we couldn't care less */
 		break;
 
 	case ICMPV6_PKT_TOOBIG:
@@ -577,7 +577,7 @@
 
 	default:
 		if (net_ratelimit())
-			printk(KERN_DEBUG "icmpv6: msg of unkown type\n");
+			printk(KERN_DEBUG "icmpv6: msg of unknown type\n");
 
 		/* informational */
 		if (type & ICMPV6_INFOMSG_MASK)
diff -Nru a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
--- a/net/ipv6/ip6_input.c	Wed Feb 19 13:55:33 2003
+++ b/net/ipv6/ip6_input.c	Wed Mar  5 15:45:36 2003
@@ -150,7 +150,8 @@
 	   It would be stupid to detect for optional headers,
 	   which are missing with probability of 200%
 	 */
-	if (nexthdr != IPPROTO_TCP && nexthdr != IPPROTO_UDP) {
+	if (nexthdr != IPPROTO_TCP && nexthdr != IPPROTO_UDP &&
+	    nexthdr != NEXTHDR_AUTH && nexthdr != NEXTHDR_ESP) {
 		nhoff = ipv6_parse_exthdrs(&skb, nhoff);
 		if (nhoff < 0)
 			return 0;
diff -Nru a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
--- a/net/ipv6/ip6_output.c	Sun Feb 23 22:41:51 2003
+++ b/net/ipv6/ip6_output.c	Wed Mar  5 15:45:36 2003
@@ -192,6 +192,11 @@
 	int seg_len = skb->len;
 	int hlimit;
 	u32 mtu;
+	int err = 0;
+
+	if ((err = xfrm_lookup(&skb->dst, fl, sk, 0)) < 0) {
+		return err;
+	}
 
 	if (opt) {
 		int head_room;
@@ -550,7 +555,7 @@
 		    || (fl->oif && fl->oif != dst->dev->ifindex)) {
 			dst = NULL;
 		} else
-			dst_clone(dst);
+			dst_hold(dst);
 	}
 
 	if (dst == NULL)
@@ -576,6 +581,13 @@
 	}
 	pktlength = length;
 
+        if (dst) {
+		if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) {
+			dst_release(dst);	
+			return -ENETUNREACH;
+		}
+        }
+
 	if (hlimit < 0) {
 		if (ipv6_addr_is_multicast(fl->fl6_dst))
 			hlimit = np->mcast_hops;
@@ -630,10 +642,8 @@
 		err = 0;
 		if (flags&MSG_PROBE)
 			goto out;
-
-		skb = sock_alloc_send_skb(sk, pktlength + 15 +
-					  dev->hard_header_len,
-					  flags & MSG_DONTWAIT, &err);
+		/* alloc skb with mtu as we do in the IPv4 stack for IPsec */
+		skb = sock_alloc_send_skb(sk, mtu, flags & MSG_DONTWAIT, &err);
 
 		if (skb == NULL) {
 			IP6_INC_STATS(Ip6OutDiscards);
@@ -663,6 +673,8 @@
 		err = getfrag(data, &hdr->saddr,
 			      ((char *) hdr) + (pktlength - length),
 			      0, length);
+		if (!opt || !opt->dst1opt)
+			skb->h.raw = ((char *) hdr) + (pktlength - length);
 
 		if (!err) {
 			IP6_INC_STATS(Ip6OutRequests);
diff -Nru a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
--- a/net/ipv6/ndisc.c	Tue Feb 25 09:45:41 2003
+++ b/net/ipv6/ndisc.c	Wed Mar  5 15:45:36 2003
@@ -71,6 +71,7 @@
 #include <net/addrconf.h>
 #include <net/icmp.h>
 
+#include <net/flow.h>
 #include <net/checksum.h>
 #include <linux/proc_fs.h>
 
@@ -335,8 +336,6 @@
 	unsigned char ha[MAX_ADDR_LEN];
 	unsigned char *h_dest = NULL;
 
-	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
-
 	if (dev->hard_header) {
 		if (ipv6_addr_type(daddr) & IPV6_ADDR_MULTICAST) {
 			ndisc_mc_map(daddr, ha, dev, 1);
@@ -373,10 +372,50 @@
  *	Send a Neighbour Advertisement
  */
 
+int ndisc_output(struct sk_buff *skb)
+{
+	if (skb) {
+		struct neighbour *neigh = (skb->dst ? skb->dst->neighbour : NULL);
+		if (ndisc_build_ll_hdr(skb, skb->dev, &skb->nh.ipv6h->daddr, neigh, skb->len) == 0) {
+			kfree_skb(skb);
+			return -EINVAL;
+		}
+		dev_queue_xmit(skb);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static inline void ndisc_rt_init(struct rt6_info *rt, struct net_device *dev,
+			    struct neighbour *neigh)
+{
+	rt->rt6i_dev	  = dev;
+	rt->rt6i_nexthop  = neigh;
+	rt->rt6i_expires  = 0;
+	rt->rt6i_flags    = RTF_LOCAL;
+	rt->rt6i_metric   = 0;
+	rt->rt6i_hoplimit = 255;
+	rt->u.dst.output  = ndisc_output;
+}
+
+static inline void ndisc_flow_init(struct flowi *fl, u8 type,
+			    struct in6_addr *saddr, struct in6_addr *daddr)
+{
+	memset(fl, 0, sizeof(*fl));
+	fl->fl6_src		= saddr;
+	fl->fl6_dst	 	= daddr;
+	fl->proto	 	= IPPROTO_ICMPV6;
+	fl->uli_u.icmpt.type	= type;
+	fl->uli_u.icmpt.code	= 0;
+}
+
 static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
 		   struct in6_addr *daddr, struct in6_addr *solicited_addr,
-		   int router, int solicited, int override, int inc_opt) 
+	 	   int router, int solicited, int override, int inc_opt) 
 {
+	struct flowi fl;
+	struct rt6_info *rt = NULL;
+	struct dst_entry* dst;
         struct sock *sk = ndisc_socket->sk;
         struct nd_msg *msg;
         int len;
@@ -385,6 +424,22 @@
 
 	len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
 
+	rt = ndisc_get_dummy_rt();
+	if (!rt) 
+		return;
+
+	ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, solicited_addr, daddr);
+	ndisc_rt_init(rt, dev, neigh);	
+
+	dst = (struct dst_entry*)rt;
+	dst_clone(dst);
+
+	err = xfrm_lookup(&dst, &fl, NULL, 0);
+	if (err < 0) {
+		dst_release(dst);
+		return;
+	}
+
 	if (inc_opt) {
 		if (dev->addr_len)
 			len += NDISC_OPT_SPACE(dev->addr_len);
@@ -400,14 +455,10 @@
 		return;
 	}
 
-	if (ndisc_build_ll_hdr(skb, dev, daddr, neigh, len) == 0) {
-		kfree_skb(skb);
-		return;
-	}
-
+	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
 	ip6_nd_hdr(sk, skb, dev, solicited_addr, daddr, IPPROTO_ICMPV6, len);
 
-	msg = (struct nd_msg *) skb_put(skb, len);
+	skb->h.raw = (unsigned char*) msg = (struct nd_msg *) skb_put(skb, len);
 
         msg->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
         msg->icmph.icmp6_code = 0;
@@ -430,7 +481,9 @@
 						 csum_partial((__u8 *) msg, 
 							      len, 0));
 
-	dev_queue_xmit(skb);
+	dst_clone(dst);
+	skb->dst = dst;
+	dst_output(skb);
 
 	ICMP6_INC_STATS(Icmp6OutNeighborAdvertisements);
 	ICMP6_INC_STATS(Icmp6OutMsgs);
@@ -440,6 +493,9 @@
 		   struct in6_addr *solicit,
 		   struct in6_addr *daddr, struct in6_addr *saddr) 
 {
+	struct flowi fl;
+	struct rt6_info *rt = NULL;
+	struct dst_entry* dst;
         struct sock *sk = ndisc_socket->sk;
         struct sk_buff *skb;
         struct nd_msg *msg;
@@ -454,6 +510,22 @@
 		saddr = &addr_buf;
 	}
 
+	rt = ndisc_get_dummy_rt();
+	if (!rt) 
+		return;
+
+	ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr);
+	ndisc_rt_init(rt, dev, neigh);	
+
+	dst = (struct dst_entry*)rt;
+	dst_clone(dst);
+
+	err = xfrm_lookup(&dst, &fl, NULL, 0);
+	if (err < 0) {
+		dst_release(dst);
+		return;
+	}
+
 	len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
 	send_llinfo = dev->addr_len && ipv6_addr_type(saddr) != IPV6_ADDR_ANY;
 	if (send_llinfo)
@@ -466,14 +538,10 @@
 		return;
 	}
 
-	if (ndisc_build_ll_hdr(skb, dev, daddr, neigh, len) == 0) {
-		kfree_skb(skb);
-		return;
-	}
-
+	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
 	ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
 
-	msg = (struct nd_msg *)skb_put(skb, len);
+	skb->h.raw = (unsigned char*) msg = (struct nd_msg *)skb_put(skb, len);
 	msg->icmph.icmp6_type = NDISC_NEIGHBOUR_SOLICITATION;
 	msg->icmph.icmp6_code = 0;
 	msg->icmph.icmp6_cksum = 0;
@@ -492,7 +560,9 @@
 						 csum_partial((__u8 *) msg, 
 							      len, 0));
 	/* send it! */
-	dev_queue_xmit(skb);
+	dst_clone(dst);
+	skb->dst = dst;
+	dst_output(skb);
 
 	ICMP6_INC_STATS(Icmp6OutNeighborSolicits);
 	ICMP6_INC_STATS(Icmp6OutMsgs);
@@ -501,6 +571,9 @@
 void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
 		   struct in6_addr *daddr)
 {
+	struct flowi fl;
+	struct rt6_info *rt = NULL;
+	struct dst_entry* dst;
 	struct sock *sk = ndisc_socket->sk;
         struct sk_buff *skb;
         struct icmp6hdr *hdr;
@@ -508,6 +581,22 @@
         int len;
 	int err;
 
+	rt = ndisc_get_dummy_rt();
+	if (!rt) 
+		return;
+
+	ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr);
+	ndisc_rt_init(rt, dev, NULL);
+
+	dst = (struct dst_entry*)rt;
+	dst_clone(dst);
+
+	err = xfrm_lookup(&dst, &fl, NULL, 0);
+	if (err < 0) {
+		dst_release(dst);
+		return;
+	}
+
 	len = sizeof(struct icmp6hdr);
 	if (dev->addr_len)
 		len += NDISC_OPT_SPACE(dev->addr_len);
@@ -519,14 +608,10 @@
 		return;
 	}
 
-	if (ndisc_build_ll_hdr(skb, dev, daddr, NULL, len) == 0) {
-		kfree_skb(skb);
-		return;
-	}
-
+	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
 	ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
 
-        hdr = (struct icmp6hdr *) skb_put(skb, len);
+        skb->h.raw = (unsigned char*) hdr = (struct icmp6hdr *) skb_put(skb, len);
         hdr->icmp6_type = NDISC_ROUTER_SOLICITATION;
         hdr->icmp6_code = 0;
         hdr->icmp6_cksum = 0;
@@ -543,7 +628,9 @@
 					   csum_partial((__u8 *) hdr, len, 0));
 
 	/* send it! */
-	dev_queue_xmit(skb);
+	dst_clone(dst);
+	skb->dst = dst;
+	dst_output(skb);
 
 	ICMP6_INC_STATS(Icmp6OutRouterSolicits);
 	ICMP6_INC_STATS(Icmp6OutMsgs);
@@ -1125,6 +1212,8 @@
 	struct in6_addr *addrp;
 	struct net_device *dev;
 	struct rt6_info *rt;
+	struct dst_entry *dst;
+	struct flowi fl;
 	u8 *opt;
 	int rd_len;
 	int err;
@@ -1136,6 +1225,22 @@
 	if (rt == NULL)
 		return;
 
+	dst = (struct dst_entry*)rt;
+
+	if (ipv6_get_lladdr(dev, &saddr_buf)) {
+ 		ND_PRINTK1("redirect: no link_local addr for dev\n");
+ 		return;
+ 	}
+
+	ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr);
+
+	dst_clone(dst);
+	err = xfrm_lookup(&dst, &fl, NULL, 0);
+	if (err) {
+		dst_release(dst);
+		return;
+	}
+
 	if (rt->rt6i_flags & RTF_GATEWAY) {
 		ND_PRINTK1("ndisc_send_redirect: not a neighbour\n");
 		dst_release(&rt->u.dst);
@@ -1164,11 +1269,6 @@
 	rd_len &= ~0x7;
 	len += rd_len;
 
-	if (ipv6_get_lladdr(dev, &saddr_buf)) {
- 		ND_PRINTK1("redirect: no link_local addr for dev\n");
- 		return;
- 	}
-
 	buff = sock_alloc_send_skb(sk, MAX_HEADER + len + dev->hard_header_len + 15,
 				   0, &err);
 	if (buff == NULL) {
@@ -1178,15 +1278,11 @@
 
 	hlen = 0;
 
-	if (ndisc_build_ll_hdr(buff, dev, &skb->nh.ipv6h->saddr, NULL, len) == 0) {
-		kfree_skb(buff);
-		return;
-	}
-
+	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
 	ip6_nd_hdr(sk, buff, dev, &saddr_buf, &skb->nh.ipv6h->saddr,
 		   IPPROTO_ICMPV6, len);
 
-	icmph = (struct icmp6hdr *) skb_put(buff, len);
+	skb->h.raw = (unsigned char*) icmph = (struct icmp6hdr *) skb_put(buff, len);
 
 	memset(icmph, 0, sizeof(struct icmp6hdr));
 	icmph->icmp6_type = NDISC_REDIRECT;
@@ -1224,7 +1320,8 @@
 					     len, IPPROTO_ICMPV6,
 					     csum_partial((u8 *) icmph, len, 0));
 
-	dev_queue_xmit(buff);
+	skb->dst = dst;
+	dst_output(skb);
 
 	ICMP6_INC_STATS(Icmp6OutRedirects);
 	ICMP6_INC_STATS(Icmp6OutMsgs);
diff -Nru a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
--- a/net/ipv6/netfilter/ip6t_ah.c	Mon Mar  3 01:40:34 2003
+++ b/net/ipv6/netfilter/ip6t_ah.c	Thu Mar  6 09:11:12 2003
@@ -9,7 +9,6 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_ah.h>
 
-EXPORT_NO_SYMBOLS;
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("IPv6 AH match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
diff -Nru a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
--- a/net/ipv6/netfilter/ip6t_dst.c	Mon Mar  3 01:40:34 2003
+++ b/net/ipv6/netfilter/ip6t_dst.c	Thu Mar  6 09:11:12 2003
@@ -15,7 +15,6 @@
 
 #define HOPBYHOP	0
 
-EXPORT_NO_SYMBOLS;
 MODULE_LICENSE("GPL");
 #if HOPBYHOP
 MODULE_DESCRIPTION("IPv6 HbH match");
diff -Nru a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
--- a/net/ipv6/netfilter/ip6t_esp.c	Mon Mar  3 01:40:34 2003
+++ b/net/ipv6/netfilter/ip6t_esp.c	Thu Mar  6 09:11:12 2003
@@ -9,7 +9,6 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_esp.h>
 
-EXPORT_NO_SYMBOLS;
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("IPv6 ESP match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
diff -Nru a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
--- a/net/ipv6/netfilter/ip6t_frag.c	Mon Mar  3 01:40:34 2003
+++ b/net/ipv6/netfilter/ip6t_frag.c	Thu Mar  6 09:11:12 2003
@@ -11,7 +11,6 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_frag.h>
 
-EXPORT_NO_SYMBOLS;
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("IPv6 FRAG match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
diff -Nru a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
--- a/net/ipv6/netfilter/ip6t_hbh.c	Mon Mar  3 01:40:34 2003
+++ b/net/ipv6/netfilter/ip6t_hbh.c	Thu Mar  6 09:11:12 2003
@@ -15,7 +15,6 @@
 
 #define HOPBYHOP	1
 
-EXPORT_NO_SYMBOLS;
 MODULE_LICENSE("GPL");
 #if HOPBYHOP
 MODULE_DESCRIPTION("IPv6 HbH match");
diff -Nru a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
--- a/net/ipv6/netfilter/ip6t_ipv6header.c	Mon Mar  3 01:40:34 2003
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c	Thu Mar  6 09:11:12 2003
@@ -14,7 +14,6 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_ipv6header.h>
 
-EXPORT_NO_SYMBOLS;
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("IPv6 headers match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
diff -Nru a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
--- a/net/ipv6/netfilter/ip6t_rt.c	Mon Mar  3 01:40:34 2003
+++ b/net/ipv6/netfilter/ip6t_rt.c	Thu Mar  6 09:11:12 2003
@@ -11,7 +11,6 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_rt.h>
 
-EXPORT_NO_SYMBOLS;
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("IPv6 RT match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
diff -Nru a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
--- a/net/ipv6/netfilter/ip6table_filter.c	Mon Feb 10 04:36:12 2003
+++ b/net/ipv6/netfilter/ip6table_filter.c	Sat Mar  8 11:40:17 2003
@@ -81,9 +81,13 @@
     }
 };
 
-static struct ip6t_table packet_filter
-= { { NULL, NULL }, "filter", &initial_table.repl,
-    FILTER_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE };
+static struct ip6t_table packet_filter = {
+	.name		= "filter",
+	.table		= &initial_table.repl,
+	.valid_hooks	= FILTER_VALID_HOOKS,
+	.lock		= RW_LOCK_UNLOCKED,
+	.me		= THIS_MODULE,
+};
 
 /* The work comes in here from netfilter.c. */
 static unsigned int
@@ -116,11 +120,25 @@
 	return ip6t_do_table(pskb, hook, in, out, &packet_filter, NULL);
 }
 
-static struct nf_hook_ops ip6t_ops[]
-= { { { NULL, NULL }, ip6t_hook, PF_INET6, NF_IP6_LOCAL_IN, NF_IP6_PRI_FILTER },
-    { { NULL, NULL }, ip6t_hook, PF_INET6, NF_IP6_FORWARD, NF_IP6_PRI_FILTER },
-    { { NULL, NULL }, ip6t_local_out_hook, PF_INET6, NF_IP6_LOCAL_OUT,
-		NF_IP6_PRI_FILTER }
+static struct nf_hook_ops ip6t_ops[] = {
+	{
+		.hook		= ip6t_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_LOCAL_IN,
+		.priority	= NF_IP6_PRI_FILTER,
+	},
+	{
+		.hook		= ip6t_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_FORWARD,
+		.priority	= NF_IP6_PRI_FILTER,
+	},
+	{
+		.hook		= ip6t_local_out_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_LOCAL_OUT,
+		.priority	= NF_IP6_PRI_FILTER,
+	},
 };
 
 /* Default to forward because I got too much mail already. */
diff -Nru a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
--- a/net/ipv6/netfilter/ip6table_mangle.c	Mon Feb 10 04:36:12 2003
+++ b/net/ipv6/netfilter/ip6table_mangle.c	Sat Mar  8 11:40:17 2003
@@ -111,9 +111,13 @@
     }
 };
 
-static struct ip6t_table packet_mangler
-= { { NULL, NULL }, "mangle", &initial_table.repl,
-    MANGLE_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE };
+static struct ip6t_table packet_mangler = {
+	.name		= "mangle",
+	.table		= &initial_table.repl,
+	.valid_hooks	= MANGLE_VALID_HOOKS,
+	.lock		= RW_LOCK_UNLOCKED,
+	.me		= THIS_MODULE,
+};
 
 /* The work comes in here from netfilter.c. */
 static unsigned int
@@ -175,12 +179,37 @@
 	return ret;
 }
 
-static struct nf_hook_ops ip6t_ops[]
-= { { { NULL, NULL }, ip6t_route_hook, PF_INET6, NF_IP6_PRE_ROUTING,  NF_IP6_PRI_MANGLE },
-    { { NULL, NULL }, ip6t_local_hook, PF_INET6, NF_IP6_LOCAL_IN,     NF_IP6_PRI_MANGLE },
-    { { NULL, NULL }, ip6t_route_hook, PF_INET6, NF_IP6_FORWARD,      NF_IP6_PRI_MANGLE },
-    { { NULL, NULL }, ip6t_local_hook, PF_INET6, NF_IP6_LOCAL_OUT,    NF_IP6_PRI_MANGLE },
-    { { NULL, NULL }, ip6t_route_hook, PF_INET6, NF_IP6_POST_ROUTING, NF_IP6_PRI_MANGLE }
+static struct nf_hook_ops ip6t_ops[] = {
+	{
+		.hook		= ip6t_route_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_PRE_ROUTING,
+		.priority	= NF_IP6_PRI_MANGLE,
+	},
+	{
+		.hook		= ip6t_local_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_LOCAL_IN,
+		.priority	= NF_IP6_PRI_MANGLE,
+	},
+	{
+		.hook		= ip6t_route_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_FORWARD,
+		.priority	= NF_IP6_PRI_MANGLE,
+	},
+	{
+		.hook		= ip6t_local_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_LOCAL_OUT,
+		.priority	= NF_IP6_PRI_MANGLE,
+	},
+	{
+		.hook		= ip6t_route_hook,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_POST_ROUTING,
+		.priority	= NF_IP6_PRI_MANGLE,
+	},
 };
 
 static int __init init(void)
diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c	Mon Oct 28 04:53:45 2002
+++ b/net/ipv6/raw.c	Wed Mar  5 15:45:36 2003
@@ -45,6 +45,7 @@
 #include <net/inet_common.h>
 
 #include <net/rawv6.h>
+#include <net/xfrm.h>
 
 struct sock *raw_v6_htable[RAWV6_HTABLE_SIZE];
 rwlock_t raw_v6_lock = RW_LOCK_UNLOCKED;
@@ -303,6 +304,11 @@
 {
 	struct inet_opt *inet = inet_sk(sk);
 	struct raw6_opt *raw_opt = raw6_sk(sk);
+
+        if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) {
+                kfree_skb(skb);
+                return NET_RX_DROP;
+        }
 
 	if (!raw_opt->checksum)
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
diff -Nru a/net/ipv6/route.c b/net/ipv6/route.c
--- a/net/ipv6/route.c	Mon Mar  3 01:47:43 2003
+++ b/net/ipv6/route.c	Wed Mar  5 15:45:36 2003
@@ -49,6 +49,8 @@
 #include <net/addrconf.h>
 #include <net/tcp.h>
 #include <linux/rtnetlink.h>
+#include <net/dst.h>
+#include <net/xfrm.h>
 
 #include <asm/uaccess.h>
 
@@ -128,6 +130,12 @@
 rwlock_t rt6_lock = RW_LOCK_UNLOCKED;
 
 
+/*	Dummy rt for ndisc */
+struct rt6_info *ndisc_get_dummy_rt()
+{
+	return dst_alloc(&ip6_dst_ops);
+}
+
 /*
  *	Route lookup. Any rt6_lock is implied.
  */
@@ -356,7 +364,7 @@
 
 		rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
 
-		dst_clone(&rt->u.dst);
+		dst_hold(&rt->u.dst);
 
 		err = rt6_ins(rt);
 		if (err == 0)
@@ -366,7 +374,7 @@
 
 		return rt;
 	}
-	dst_clone(&ip6_null_entry.u.dst);
+	dst_hold(&ip6_null_entry.u.dst);
 	return &ip6_null_entry;
 }
 
@@ -374,7 +382,7 @@
 if (rt == &ip6_null_entry && strict) { \
        while ((fn = fn->parent) != NULL) { \
 		if (fn->fn_flags & RTN_ROOT) { \
-			dst_clone(&rt->u.dst); \
+			dst_hold(&rt->u.dst); \
 			goto out; \
 		} \
 		if (fn->fn_flags & RTN_RTINFO) \
@@ -404,7 +412,7 @@
 	if ((rt->rt6i_flags & RTF_CACHE)) {
 		rt = rt6_device_match(rt, skb->dev->ifindex, strict);
 		BACKTRACK();
-		dst_clone(&rt->u.dst);
+		dst_hold(&rt->u.dst);
 		goto out;
 	}
 
@@ -424,7 +432,7 @@
 		*/
 		goto relookup;
 	}
-	dst_clone(&rt->u.dst);
+	dst_hold(&rt->u.dst);
 
 out:
 	read_unlock_bh(&rt6_lock);
@@ -455,7 +463,7 @@
 	if ((rt->rt6i_flags & RTF_CACHE)) {
 		rt = rt6_device_match(rt, fl->oif, strict);
 		BACKTRACK();
-		dst_clone(&rt->u.dst);
+		dst_hold(&rt->u.dst);
 		goto out;
 	}
 	if (rt->rt6i_flags & RTF_DEFAULT) {
@@ -480,7 +488,7 @@
 		*/
 		goto relookup;
 	}
-	dst_clone(&rt->u.dst);
+	dst_hold(&rt->u.dst);
 
 out:
 	read_unlock_bh(&rt6_lock);
@@ -815,7 +823,7 @@
 			if (rtmsg->rtmsg_metric &&
 			    rtmsg->rtmsg_metric != rt->rt6i_metric)
 				continue;
-			dst_clone(&rt->u.dst);
+			dst_hold(&rt->u.dst);
 			read_unlock_bh(&rt6_lock);
 
 			return ip6_del_rt(rt);
@@ -878,7 +886,7 @@
 			read_lock(&rt6_lock);
 			for (rt1 = ip6_routing_table.leaf; rt1; rt1 = rt1->u.next) {
 				if (!ipv6_addr_cmp(saddr, &rt1->rt6i_gateway)) {
-					dst_clone(&rt1->u.dst);
+					dst_hold(&rt1->u.dst);
 					dst_release(&rt->u.dst);
 					read_unlock(&rt6_lock);
 					rt = rt1;
@@ -1065,7 +1073,7 @@
 			break;
 	}
 	if (rt)
-		dst_clone(&rt->u.dst);
+		dst_hold(&rt->u.dst);
 	write_unlock_bh(&rt6_lock);
 	return rt;
 }
@@ -1859,6 +1867,14 @@
 
 #endif
 
+int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
+{
+	int err = 0;
+	*dst = (struct xfrm_dst*)ip6_route_output(NULL, fl);
+	if (!*dst)
+		err = -ENETUNREACH;
+	return err;
+}
 
 void __init ip6_route_init(void)
 {
@@ -1867,6 +1883,7 @@
 						     0, SLAB_HWCACHE_ALIGN,
 						     NULL, NULL);
 	fib6_init();
+	xfrm_dst_lookup_register(xfrm6_dst_lookup, AF_INET6);
 #ifdef 	CONFIG_PROC_FS
 	proc_net_create("ipv6_route", 0, rt6_proc_info);
 	proc_net_create("rt6_stats", 0, rt6_proc_stats);
@@ -1880,7 +1897,7 @@
 	proc_net_remove("ipv6_route");
 	proc_net_remove("rt6_stats");
 #endif
-
+	xfrm_dst_lookup_unregister(AF_INET6);
 	rt6_ifdown(NULL);
 	fib6_gc_cleanup();
 }
diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
--- a/net/ipv6/tcp_ipv6.c	Sat Feb 22 16:15:34 2003
+++ b/net/ipv6/tcp_ipv6.c	Wed Mar  5 15:45:36 2003
@@ -50,6 +50,7 @@
 #include <net/ip6_route.h>
 #include <net/inet_ecn.h>
 #include <net/protocol.h>
+#include <net/xfrm.h>
 
 #include <asm/uaccess.h>
 
@@ -677,6 +678,9 @@
 		fl.nl_u.ip6_u.daddr = rt0->addr;
 	}
 
+	if (!fl.fl6_src)
+		fl.fl6_src = &np->saddr;
+
 	dst = ip6_route_output(sk, &fl);
 
 	if ((err = dst->error) != 0) {
@@ -800,7 +804,7 @@
 
 			dst = ip6_route_output(sk, &fl);
 		} else
-			dst_clone(dst);
+			dst_hold(dst);
 
 		if (dst->error) {
 			sk->err_soft = -dst->error;
@@ -1637,6 +1641,9 @@
 	if (sk_filter(sk, skb, 0))
 		goto discard_and_relse;
 
+	if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
+		goto discard_it;
+
 	skb->dev = NULL;
 
 	bh_lock_sock(sk);
@@ -1652,6 +1659,9 @@
 	return ret;
 
 no_tcp_socket:
+	if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
+		goto discard_and_relse;
+
 	if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
 bad_packet:
 		TCP_INC_STATS_BH(TcpInErrs);
@@ -1671,8 +1681,11 @@
 discard_and_relse:
 	sock_put(sk);
 	goto discard_it;
-                
+
 do_time_wait:
+	if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
+		goto discard_and_relse;
+
 	if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
 		TCP_INC_STATS_BH(TcpInErrs);
 		sock_put(sk);
diff -Nru a/net/ipv6/udp.c b/net/ipv6/udp.c
--- a/net/ipv6/udp.c	Tue Jan  7 02:19:42 2003
+++ b/net/ipv6/udp.c	Wed Mar  5 15:45:36 2003
@@ -50,6 +50,7 @@
 #include <net/inet_common.h>
 
 #include <net/checksum.h>
+#include <net/xfrm.h>
 
 DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6);
 
@@ -541,6 +542,11 @@
 
 static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
 {
+	if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) {
+		kfree_skb(skb);
+		return -1;
+	}
+
 #if defined(CONFIG_FILTER)
 	if (sk->filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
 		if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) {
@@ -645,6 +651,9 @@
 
 	if (!pskb_may_pull(skb, sizeof(struct udphdr)))
 		goto short_packet;
+
+	if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
+                goto discard;
 
 	saddr = &skb->nh.ipv6h->saddr;
 	daddr = &skb->nh.ipv6h->daddr;
diff -Nru a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
--- a/net/ipx/af_ipx.c	Tue Feb 25 11:05:23 2003
+++ b/net/ipx/af_ipx.c	Thu Mar  6 11:06:44 2003
@@ -1719,10 +1719,10 @@
 	if (!sk)
 		goto out;
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 	sock->sk = NULL;
 	ipx_destroy_socket(sk);
 
@@ -2010,7 +2010,7 @@
 }
 
 static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,
-	struct msghdr *msg, int len, struct scm_cookie *scm)
+	struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct ipx_opt *ipxs = ipx_sk(sk);
@@ -2070,7 +2070,7 @@
 
 
 static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
-		struct msghdr *msg, int size, int flags, struct scm_cookie *scm)
+		struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct ipx_opt *ipxs = ipx_sk(sk);
diff -Nru a/net/irda/af_irda.c b/net/irda/af_irda.c
--- a/net/irda/af_irda.c	Thu Nov 14 09:20:05 2002
+++ b/net/irda/af_irda.c	Thu Mar  6 11:06:45 2003
@@ -133,13 +133,13 @@
 	}
 
 	/* Prevent race conditions with irda_release() and irda_shutdown() */
-	if ((!sk->dead) && (sk->state != TCP_CLOSE)) {
+	if ((!test_bit(SOCK_DEAD, &sk->flags)) && (sk->state != TCP_CLOSE)) {
 		sk->state     = TCP_CLOSE;
 		sk->err       = ECONNRESET;
 		sk->shutdown |= SEND_SHUTDOWN;
 
 		sk->state_change(sk);
-                sk->dead = 1;	/* Uh-oh... Should use sock_orphan ? */
+                __set_bit(SOCK_DEAD, &sk->flags);	/* Uh-oh... Should use sock_orphan ? */
 
 		/* Close our TSAP.
 		 * If we leave it open, IrLMP put it back into the list of
@@ -163,7 +163,7 @@
 	/* Note : once we are there, there is not much you want to do
 	 * with the socket anymore, apart from closing it.
 	 * For example, bind() and connect() won't reset sk->err,
-	 * sk->shutdown and sk->dead to valid values...
+	 * sk->shutdown and sk->flags to valid values...
 	 * Jean II
 	 */
 }
@@ -1253,14 +1253,14 @@
 }
 
 /*
- * Function irda_sendmsg (iocb, sock, msg, len, scm)
+ * Function irda_sendmsg (iocb, sock, msg, len)
  *
  *    Send message down to TinyTP. This function is used for both STREAM and
  *    SEQPACK services. This is possible since it forces the client to
  *    fragment the message if necessary
  */
 static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
-			struct msghdr *msg, int len, struct scm_cookie *scm)
+			struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct irda_sock *self;
@@ -1326,14 +1326,13 @@
 }
 
 /*
- * Function irda_recvmsg_dgram (iocb, sock, msg, size, flags, scm)
+ * Function irda_recvmsg_dgram (iocb, sock, msg, size, flags)
  *
  *    Try to receive message and copy it to user. The frame is discarded
  *    after being read, regardless of how much the user actually read
  */
 static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
-			      struct msghdr *msg, int size, int flags,
-			      struct scm_cookie *scm)
+			      struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct irda_sock *self = irda_sk(sk);
@@ -1380,11 +1379,10 @@
 }
 
 /*
- * Function irda_recvmsg_stream (iocb, sock, msg, size, flags, scm)
+ * Function irda_recvmsg_stream (iocb, sock, msg, size, flags)
  */
 static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
-			       struct msghdr *msg, int size, int flags,
-			       struct scm_cookie *scm)
+			       struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct irda_sock *self = irda_sk(sk);
@@ -1504,14 +1502,14 @@
 }
 
 /*
- * Function irda_sendmsg_dgram (iocb, sock, msg, len, scm)
+ * Function irda_sendmsg_dgram (iocb, sock, msg, len)
  *
  *    Send message down to TinyTP for the unreliable sequenced
  *    packet service...
  *
  */
 static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
-			      struct msghdr *msg, int len, struct scm_cookie *scm)
+			      struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct irda_sock *self;
@@ -1570,14 +1568,14 @@
 }
 
 /*
- * Function irda_sendmsg_ultra (iocb, sock, msg, len, scm)
+ * Function irda_sendmsg_ultra (iocb, sock, msg, len)
  *
  *    Send message down to IrLMP for the unreliable Ultra
  *    packet service...
  */
 #ifdef CONFIG_IRDA_ULTRA
 static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
-			      struct msghdr *msg, int len, struct scm_cookie *scm)
+			      struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct irda_sock *self;
diff -Nru a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
--- a/net/irda/ircomm/ircomm_core.c	Mon Sep 23 16:34:19 2002
+++ b/net/irda/ircomm/ircomm_core.c	Mon Mar 10 22:34:30 2003
@@ -119,8 +119,10 @@
 	} else
 		ret = ircomm_open_tsap(self);
 
-	if (ret < 0)
+	if (ret < 0) {
+		kfree(self);
 		return NULL;
+	}
 
 	self->service_type = service_type;
 	self->line = line;
diff -Nru a/net/key/af_key.c b/net/key/af_key.c
--- a/net/key/af_key.c	Wed Feb 19 13:45:59 2003
+++ b/net/key/af_key.c	Thu Mar  6 11:06:45 2003
@@ -51,7 +51,7 @@
 {
 	skb_queue_purge(&sk->receive_queue);
 
-	if (!sk->dead) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		printk("Attempt to release alive pfkey socket: %p\n", sk);
 		return;
 	}
@@ -550,8 +550,8 @@
 
 	switch (((struct sockaddr *)(addr + 1))->sa_family) {
 	case AF_INET:
-		x = xfrm_state_lookup(((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr,
-				      sa->sadb_sa_spi, proto);
+		x = xfrm4_state_lookup(((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr,
+				       sa->sadb_sa_spi, proto);
 		break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
@@ -1097,18 +1097,7 @@
 			min_spi = htonl(0x100);
 			max_spi = htonl(0x0fffffff);
 		}
-		switch (x->props.family) {
-		case AF_INET:
-			xfrm_alloc_spi(x, min_spi, max_spi);
-			break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-		case AF_INET6:
-			xfrm6_alloc_spi(x, min_spi, max_spi);
-			break;
-#endif
-		default:
-			break;
-		}
+		xfrm_alloc_spi(x, min_spi, max_spi);
 		if (x->id.spi)
 			resp_skb = pfkey_xfrm_state2msg(x, 0, 3);
 	}
@@ -2420,7 +2409,8 @@
 	return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL);
 }
 
-static struct xfrm_policy *pfkey_compile_policy(int opt, u8 *data, int len, int *dir)
+static struct xfrm_policy *pfkey_compile_policy(u16 family, int opt,
+                                                u8 *data, int len, int *dir)
 {
 	struct xfrm_policy *xp;
 	struct sadb_x_policy *pol = (struct sadb_x_policy*)data;
@@ -2451,6 +2441,7 @@
 	xp->lft.hard_byte_limit = XFRM_INF;
 	xp->lft.soft_packet_limit = XFRM_INF;
 	xp->lft.hard_packet_limit = XFRM_INF;
+	xp->family = family;
 
 	xp->xfrm_nr = 0;
 	if (pol->sadb_x_policy_type == IPSEC_POLICY_IPSEC &&
@@ -2466,8 +2457,7 @@
 }
 
 static int pfkey_sendmsg(struct kiocb *kiocb,
-			 struct socket *sock, struct msghdr *msg, int len,
-			 struct scm_cookie *scm)
+			 struct socket *sock, struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb = NULL;
@@ -2510,7 +2500,7 @@
 
 static int pfkey_recvmsg(struct kiocb *kiocb,
 			 struct socket *sock, struct msghdr *msg, int len,
-			 int flags, struct scm_cookie *scm)
+			 int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb;
diff -Nru a/net/llc/af_llc.c b/net/llc/af_llc.c
--- a/net/llc/af_llc.c	Tue Feb 25 10:47:07 2003
+++ b/net/llc/af_llc.c	Thu Mar  6 11:06:45 2003
@@ -672,14 +672,12 @@
  *	@msg: Various user space related information.
  *	@size: Size of user buffer.
  *	@flags: User specified flags.
- *	@scm: Unknown.
  *
  *	Copy received data to the socket user.
  *	Returns non-negative upon success, negative otherwise.
  */
 static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
-			  struct msghdr *msg, int size, int flags,
-			  struct scm_cookie *scm)
+			  struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name;
@@ -727,13 +725,12 @@
  *	@sock: Socket to transmit data from.
  *	@msg: Various user related information.
  *	@len: Length of data to transmit.
- *	@scm: Unknown.
  *
  *	Transmit data provided by the socket user.
  *	Returns non-negative upon success, negative otherwise.
  */
 static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock,
-			  struct msghdr *msg, int len, struct scm_cookie *scm)
+			  struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct llc_opt *llc = llc_sk(sk);
diff -Nru a/net/llc/llc_conn.c b/net/llc/llc_conn.c
--- a/net/llc/llc_conn.c	Mon Sep 30 12:17:03 2002
+++ b/net/llc/llc_conn.c	Mon Mar  3 04:56:53 2003
@@ -119,9 +119,9 @@
 			sk->shutdown       = SHUTDOWN_MASK;
 			sk->socket->state  = SS_UNCONNECTED;
 			sk->state          = TCP_CLOSE;
-			if (!sk->dead) {
+			if (!test_bit(SOCK_DEAD, &sk->flags)) {
 				sk->state_change(sk);
-				sk->dead = 1;
+				__set_bit(SOCK_DEAD, &sk->flags);
 			}
 		}
 		kfree_skb(skb);
diff -Nru a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
--- a/net/netlink/af_netlink.c	Sun Feb 23 22:14:05 2003
+++ b/net/netlink/af_netlink.c	Thu Mar  6 11:06:45 2003
@@ -90,7 +90,7 @@
 {
 	skb_queue_purge(&sk->receive_queue);
 
-	if (!sk->dead) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		printk("Freeing alive netlink socket %p\n", sk);
 		return;
 	}
@@ -457,7 +457,7 @@
 
 		if ((atomic_read(&sk->rmem_alloc) > sk->rcvbuf ||
 		    test_bit(0, &nlk->state)) &&
-		    !sk->dead)
+		    !test_bit(SOCK_DEAD, &sk->flags))
 			timeo = schedule_timeout(timeo);
 
 		__set_current_state(TASK_RUNNING);
@@ -595,10 +595,10 @@
 		wake_up_interruptible(&nlk->wait);
 }
 
-static int netlink_sendmsg(struct kiocb *iocb, struct socket *sock,
-			   struct msghdr *msg, int len,
-			   struct scm_cookie *scm)
+static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
+			   struct msghdr *msg, int len)
 {
+	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
 	struct sock *sk = sock->sk;
 	struct netlink_opt *nlk = nlk_sk(sk);
 	struct sockaddr_nl *addr=msg->msg_name;
@@ -606,10 +606,17 @@
 	u32 dst_groups;
 	struct sk_buff *skb;
 	int err;
+	struct scm_cookie scm;
 
 	if (msg->msg_flags&MSG_OOB)
 		return -EOPNOTSUPP;
 
+	if (NULL == siocb->scm)
+		siocb->scm = &scm;
+	err = scm_send(sock, msg, siocb->scm);
+	if (err < 0)
+		return err;
+
 	if (msg->msg_namelen) {
 		if (addr->nl_family != AF_NETLINK)
 			return -EINVAL;
@@ -640,7 +647,7 @@
 	NETLINK_CB(skb).groups	= nlk->groups;
 	NETLINK_CB(skb).dst_pid = dst_pid;
 	NETLINK_CB(skb).dst_groups = dst_groups;
-	memcpy(NETLINK_CREDS(skb), &scm->creds, sizeof(struct ucred));
+	memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
 
 	/* What can I do? Netlink is asynchronous, so that
 	   we will have to save current capabilities to
@@ -670,10 +677,12 @@
 	return err;
 }
 
-static int netlink_recvmsg(struct kiocb *iocb, struct socket *sock,
+static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
 			   struct msghdr *msg, int len,
-			   int flags, struct scm_cookie *scm)
+			   int flags)
 {
+	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
+	struct scm_cookie scm;
 	struct sock *sk = sock->sk;
 	struct netlink_opt *nlk = nlk_sk(sk);
 	int noblock = flags&MSG_DONTWAIT;
@@ -709,11 +718,17 @@
 		msg->msg_namelen = sizeof(*addr);
 	}
 
-	scm->creds = *NETLINK_CREDS(skb);
+	if (NULL == siocb->scm) {
+		memset(&scm, 0, sizeof(scm));
+		siocb->scm = &scm;
+	}
+	siocb->scm->creds = *NETLINK_CREDS(skb);
 	skb_free_datagram(sk, skb);
 
 	if (nlk->cb && atomic_read(&sk->rmem_alloc) <= sk->rcvbuf / 2)
 		netlink_dump(sk);
+
+	scm_recv(sock, msg, siocb->scm, flags);
 
 out:
 	netlink_rcv_wake(sk);
diff -Nru a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
--- a/net/netrom/af_netrom.c	Tue Oct  8 07:02:41 2002
+++ b/net/netrom/af_netrom.c	Thu Mar  6 11:06:45 2003
@@ -285,7 +285,7 @@
 
 	while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
 		if (skb->sk != sk) {			/* A pending connection */
-			skb->sk->dead = 1;	/* Queue the unaccepted socket for death */
+			__set_bit(SOCK_DEAD, &skb->sk->flags);	/* Queue the unaccepted socket for death */
 			nr_start_heartbeat(skb->sk);
 			nr_sk(skb->sk)->state = NR_STATE_0;
 		}
@@ -545,8 +545,8 @@
 		sk->state    = TCP_CLOSE;
 		sk->shutdown |= SEND_SHUTDOWN;
 		sk->state_change(sk);
-		sk->dead     = 1;
-		sk->destroy  = 1;
+		__set_bit(SOCK_DEAD, &sk->flags);
+		__set_bit(SOCK_DESTROY, &sk->flags);
 		sk->socket   = NULL;
 		break;
 
@@ -960,14 +960,14 @@
 	nr_start_heartbeat(make);
 	nr_start_idletimer(make);
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->data_ready(sk, skb->len);
 
 	return 1;
 }
 
 static int nr_sendmsg(struct kiocb *iocb, struct socket *sock,
-		      struct msghdr *msg, int len, struct scm_cookie *scm)
+		      struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	nr_cb *nr = nr_sk(sk);
@@ -1058,8 +1058,7 @@
 }
 
 static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,
-		      struct msghdr *msg, int size, int flags,
-		      struct scm_cookie *scm)
+		      struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name;
diff -Nru a/net/netrom/nr_in.c b/net/netrom/nr_in.c
--- a/net/netrom/nr_in.c	Mon Aug  5 08:44:44 2002
+++ b/net/netrom/nr_in.c	Mon Mar  3 04:56:53 2003
@@ -90,7 +90,7 @@
 		nr->n2count    = 0;
 		nr->window     = skb->data[20];
 		sk->state      = TCP_ESTABLISHED;
-		if (!sk->dead)
+		if (!test_bit(SOCK_DEAD, &sk->flags))
 			sk->state_change(sk);
 		break;
 	}
diff -Nru a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c
--- a/net/netrom/nr_subr.c	Mon Aug  5 08:44:44 2002
+++ b/net/netrom/nr_subr.c	Mon Mar  3 04:56:53 2003
@@ -276,8 +276,8 @@
 	sk->err       = reason;
 	sk->shutdown |= SEND_SHUTDOWN;
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 }
diff -Nru a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c
--- a/net/netrom/nr_timer.c	Mon Aug  5 09:14:03 2002
+++ b/net/netrom/nr_timer.c	Mon Mar  3 04:56:53 2003
@@ -141,7 +141,9 @@
 	case NR_STATE_0:
 		/* Magic here: If we listen() and a new link dies before it
 		   is accepted() it isn't 'dead' so doesn't get removed. */
-		if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) {
+		if (test_bit(SOCK_DESTROY, &sk->flags) ||
+				(sk->state == TCP_LISTEN &&
+					test_bit(SOCK_DEAD, &sk->flags))) {
 			nr_destroy_socket(sk);
 			return;
 		}
@@ -209,10 +211,10 @@
 	sk->err       = 0;
 	sk->shutdown |= SEND_SHUTDOWN;
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 	bh_unlock_sock(sk);
 }
 
diff -Nru a/net/netsyms.c b/net/netsyms.c
--- a/net/netsyms.c	Tue Feb 25 18:56:15 2003
+++ b/net/netsyms.c	Thu Mar  6 16:16:15 2003
@@ -54,6 +54,12 @@
 #include <linux/mroute.h>
 #include <linux/igmp.h>
 #include <net/xfrm.h>
+#if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE)
+#include <net/ah.h>
+#endif
+#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
+#include <net/esp.h>
+#endif
 
 extern struct net_proto_family inet_family_ops;
 
@@ -296,11 +302,11 @@
 EXPORT_SYMBOL(__xfrm_route_forward);
 EXPORT_SYMBOL(xfrm_state_alloc);
 EXPORT_SYMBOL(__xfrm_state_destroy);
-EXPORT_SYMBOL(xfrm_state_find);
+EXPORT_SYMBOL(xfrm4_state_find);
 EXPORT_SYMBOL(xfrm_state_insert);
 EXPORT_SYMBOL(xfrm_state_check_expire);
 EXPORT_SYMBOL(xfrm_state_check_space);
-EXPORT_SYMBOL(xfrm_state_lookup);
+EXPORT_SYMBOL(xfrm4_state_lookup);
 EXPORT_SYMBOL(xfrm_replay_check);
 EXPORT_SYMBOL(xfrm_replay_advance);
 EXPORT_SYMBOL(xfrm_check_selectors);
@@ -324,13 +330,17 @@
 EXPORT_SYMBOL(xfrm_policy_flush);
 EXPORT_SYMBOL(xfrm_policy_byid);
 EXPORT_SYMBOL(xfrm_policy_list);
+EXPORT_SYMBOL(xfrm_dst_lookup_register);
+EXPORT_SYMBOL(xfrm_dst_lookup_unregister);
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+EXPORT_SYMBOL(xfrm6_state_find);
+EXPORT_SYMBOL(xfrm6_rcv);
 EXPORT_SYMBOL(xfrm6_state_lookup);
 EXPORT_SYMBOL(xfrm6_find_acq);
-EXPORT_SYMBOL(xfrm6_alloc_spi);
 EXPORT_SYMBOL(xfrm6_register_type);
 EXPORT_SYMBOL(xfrm6_unregister_type);
 EXPORT_SYMBOL(xfrm6_get_type);
+EXPORT_SYMBOL(xfrm6_clear_mutable_options);
 #endif
 
 EXPORT_SYMBOL_GPL(xfrm_probe_algs);
@@ -342,6 +352,15 @@
 EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
 EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname);
 EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname);
+#if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE)
+EXPORT_SYMBOL_GPL(skb_ah_walk);
+#endif
+#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
+EXPORT_SYMBOL_GPL(skb_cow_data);
+EXPORT_SYMBOL_GPL(pskb_put);
+EXPORT_SYMBOL_GPL(skb_icv_walk);
+EXPORT_SYMBOL_GPL(skb_to_sgvec);
+#endif
 
 #if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_IP_SCTP_MODULE)
 /* inet functions common to v4 and v6 */
diff -Nru a/net/packet/af_packet.c b/net/packet/af_packet.c
--- a/net/packet/af_packet.c	Sat Nov  2 02:29:53 2002
+++ b/net/packet/af_packet.c	Thu Mar  6 11:06:45 2003
@@ -198,7 +198,7 @@
 	BUG_TRAP(atomic_read(&sk->rmem_alloc)==0);
 	BUG_TRAP(atomic_read(&sk->wmem_alloc)==0);
 
-	if (!sk->dead) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		printk("Attempt to release alive packet socket: %p\n", sk);
 		return;
 	}
@@ -280,8 +280,7 @@
  */
  
 static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
-			       struct msghdr *msg, int len,
-			       struct scm_cookie *scm)
+			       struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_pkt *saddr=(struct sockaddr_pkt *)msg->msg_name;
@@ -658,7 +657,7 @@
 
 
 static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
-			  struct msghdr *msg, int len, struct scm_cookie *scm)
+			  struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_ll *saddr=(struct sockaddr_ll *)msg->msg_name;
@@ -852,7 +851,7 @@
 			po->running = 1;
 		} else {
 			sk->err = ENETDOWN;
-			if (!sk->dead)
+			if (!test_bit(SOCK_DEAD, &sk->flags))
 				sk->error_report(sk);
 		}
 	} else {
@@ -1013,8 +1012,7 @@
  */
 
 static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
-			  struct msghdr *msg, int len,
-			  int flags, struct scm_cookie *scm)
+			  struct msghdr *msg, int len, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb;
@@ -1392,7 +1390,7 @@
 					__sock_put(sk);
 					po->running = 0;
 					sk->err = ENETDOWN;
-					if (!sk->dead)
+					if (!test_bit(SOCK_DEAD, &sk->flags))
 						sk->error_report(sk);
 				}
 				if (msg == NETDEV_UNREGISTER) {
diff -Nru a/net/rose/af_rose.c b/net/rose/af_rose.c
--- a/net/rose/af_rose.c	Tue Oct  8 07:02:41 2002
+++ b/net/rose/af_rose.c	Thu Mar  6 11:06:45 2003
@@ -365,7 +365,7 @@
 
 	while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
 		if (skb->sk != sk) {			/* A pending connection */
-			skb->sk->dead = 1;	/* Queue the unaccepted socket for death */
+			__set_bit(SOCK_DEAD, &skb->sk->flags);	/* Queue the unaccepted socket for death */
 			rose_start_heartbeat(skb->sk);
 			rose_sk(skb->sk)->state = ROSE_STATE_0;
 		}
@@ -646,8 +646,8 @@
 		sk->state    = TCP_CLOSE;
 		sk->shutdown |= SEND_SHUTDOWN;
 		sk->state_change(sk);
-		sk->dead     = 1;
-		sk->destroy  = 1;
+		__set_bit(SOCK_DEAD, &sk->flags);
+		__set_bit(SOCK_DESTROY, &sk->flags);
 		break;
 
 	default:
@@ -1019,14 +1019,14 @@
 
 	rose_start_heartbeat(make);
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->data_ready(sk, skb->len);
 
 	return 1;
 }
 
 static int rose_sendmsg(struct kiocb *iocb, struct socket *sock,
-			struct msghdr *msg, int len, struct scm_cookie *scm)
+			struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	rose_cb *rose = rose_sk(sk);
@@ -1190,8 +1190,7 @@
 
 
 static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
-			struct msghdr *msg, int size, int flags,
-			struct scm_cookie *scm)
+			struct msghdr *msg, int size, int flags)
 {
 	struct sock *sk = sock->sk;
 	rose_cb *rose = rose_sk(sk);
diff -Nru a/net/rose/rose_in.c b/net/rose/rose_in.c
--- a/net/rose/rose_in.c	Mon Aug  5 08:44:44 2002
+++ b/net/rose/rose_in.c	Mon Mar  3 04:56:53 2003
@@ -54,7 +54,7 @@
 		rose->vl        = 0;
 		rose->state     = ROSE_STATE_3;
 		sk->state                    = TCP_ESTABLISHED;
-		if (!sk->dead)
+		if (!test_bit(SOCK_DEAD, &sk->flags))
 			sk->state_change(sk);
 		break;
 
diff -Nru a/net/rose/rose_route.c b/net/rose/rose_route.c
--- a/net/rose/rose_route.c	Mon Aug  5 09:23:19 2002
+++ b/net/rose/rose_route.c	Mon Mar  3 04:56:53 2003
@@ -910,9 +910,9 @@
 			sk->state	 = TCP_CLOSE;
 			sk->err		 = 0;
 			sk->shutdown	 |= SEND_SHUTDOWN;
-			if (!sk->dead)
+			if (!test_bit(SOCK_DEAD, &sk->flags))
 				sk->state_change(sk);
-			sk->dead         = 1;
+			__set_bit(SOCK_DEAD, &sk->flags);
 		}
 		else {
 			skb->h.raw = skb->data;
diff -Nru a/net/rose/rose_subr.c b/net/rose/rose_subr.c
--- a/net/rose/rose_subr.c	Mon Aug  5 08:44:45 2002
+++ b/net/rose/rose_subr.c	Mon Mar  3 04:56:53 2003
@@ -510,8 +510,8 @@
 	sk->err       = reason;
 	sk->shutdown |= SEND_SHUTDOWN;
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 
-	sk->dead  = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 }
diff -Nru a/net/rose/rose_timer.c b/net/rose/rose_timer.c
--- a/net/rose/rose_timer.c	Mon Aug  5 09:14:03 2002
+++ b/net/rose/rose_timer.c	Mon Mar  3 04:56:53 2003
@@ -136,7 +136,9 @@
 	case ROSE_STATE_0:
 		/* Magic here: If we listen() and a new link dies before it
 		   is accepted() it isn't 'dead' so doesn't get removed. */
-		if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) {
+		if (test_bit(SOCK_DESTROY, &sk->flags) ||
+				(sk->state == TCP_LISTEN &&
+					test_bit(SOCK_DEAD, &sk->flags))) {
 			rose_destroy_socket(sk);
 			return;
 		}
@@ -207,9 +209,9 @@
 	sk->err       = 0;
 	sk->shutdown |= SEND_SHUTDOWN;
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 	bh_unlock_sock(sk);
 }
diff -Nru a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
--- a/net/sctp/ulpqueue.c	Mon Mar  3 01:00:55 2003
+++ b/net/sctp/ulpqueue.c	Mon Mar  3 04:56:53 2003
@@ -189,7 +189,7 @@
 	/* If the socket is just going to throw this away, do not
 	 * even try to deliver it.
 	 */
-	if (sk->dead || (sk->shutdown & RCV_SHUTDOWN))
+	if (test_bit(SOCK_DEAD, &sk->flags) || (sk->shutdown & RCV_SHUTDOWN))
 		goto out_free;
 
 	/* Check if the user wishes to receive this event.  */
diff -Nru a/net/socket.c b/net/socket.c
--- a/net/socket.c	Tue Feb 25 18:56:15 2003
+++ b/net/socket.c	Thu Mar  6 11:06:45 2003
@@ -78,6 +78,7 @@
 #include <linux/divert.h>
 #include <linux/mount.h>
 #include <linux/security.h>
+#include <linux/compat.h>
 
 #if defined(CONFIG_KMOD) && defined(CONFIG_NET)
 #include <linux/kmod.h>
@@ -88,9 +89,9 @@
 #endif	/* CONFIG_NET_RADIO */
 
 #include <asm/uaccess.h>
+#include <net/compat_socket.h>
 
 #include <net/sock.h>
-#include <net/scm.h>
 #include <linux/netfilter.h>
 
 static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
@@ -518,13 +519,13 @@
 	sock->file=NULL;
 }
 
-static int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size)
+static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size)
 {
 	struct sock_iocb *si = kiocb_to_siocb(iocb);
 	int err;
 
-	si->scm = &si->async_scm;
 	si->sock = sock;
+	si->scm = NULL;
 	si->msg = msg;
 	si->size = size;
 
@@ -532,13 +533,7 @@
 	if (err)
 		return err;
 
-	err = scm_send(sock, msg, si->scm);
-	if (err >= 0) {
-		err = sock->ops->sendmsg(iocb, sock, msg, size, si->scm);
-		if (-EIOCBQUEUED != err)
-			scm_destroy(si->scm);
-	}
-	return err;
+	return sock->ops->sendmsg(iocb, sock, msg, size);
 }
 
 int sock_sendmsg(struct socket *sock, struct msghdr *msg, int size)
@@ -554,14 +549,13 @@
 }
 
 
-int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size, int flags)
+static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size, int flags)
 {
 	int err;
 	struct sock_iocb *si = kiocb_to_siocb(iocb);
 
 	si->sock = sock;
-	si->scm = &si->async_scm;
-	si->sock = sock;
+	si->scm = NULL;
 	si->msg = msg;
 	si->size = size;
 	si->flags = flags;
@@ -570,13 +564,7 @@
 	if (err)
 		return err;
 
-	memset(si->scm, 0, sizeof(*si->scm));
-
-	size = sock->ops->recvmsg(iocb, sock, msg, size, flags, si->scm);
-	if (size >= 0)
-		scm_recv(sock, msg, si->scm, flags);
-
-	return size;
+	return sock->ops->recvmsg(iocb, sock, msg, size, flags);
 }
 
 int sock_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags)
@@ -1545,12 +1533,21 @@
 	return err;
 }
 
+/* A couple of helpful macros for getting the address of the 32/64 bit 
+ * fields which are the same type (int / unsigned) on our platforms.
+ */
+#define COMPAT_MSG(msg, member)	((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
+#define COMPAT_NAMELEN(msg)	COMPAT_MSG(msg, msg_namelen)
+#define COMPAT_FLAGS(msg)	COMPAT_MSG(msg, msg_flags)
+
+
 /*
  *	BSD sendmsg interface
  */
 
 asmlinkage long sys_sendmsg(int fd, struct msghdr *msg, unsigned flags)
 {
+	struct compat_msghdr *msg_compat = (struct compat_msghdr *)msg;
 	struct socket *sock;
 	char address[MAX_SOCK_ADDR];
 	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
@@ -1560,8 +1557,11 @@
 	int err, ctl_len, iov_size, total_len;
 	
 	err = -EFAULT;
-	if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
-		goto out; 
+	if (MSG_CMSG_COMPAT & flags) {
+		if (msghdr_from_user_compat_to_kern(&msg_sys, msg_compat))
+			return -EFAULT;
+	} else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
+		return -EFAULT;
 
 	sock = sockfd_lookup(fd, &err);
 	if (!sock) 
@@ -1582,7 +1582,10 @@
 	}
 
 	/* This will also move the address data into kernel space */
-	err = verify_iovec(&msg_sys, iov, address, VERIFY_READ);
+	if (MSG_CMSG_COMPAT & flags) {
+		err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ);
+	} else
+		err = verify_iovec(&msg_sys, iov, address, VERIFY_READ);
 	if (err < 0) 
 		goto out_freeiov;
 	total_len = err;
@@ -1592,8 +1595,12 @@
 	if (msg_sys.msg_controllen > INT_MAX)
 		goto out_freeiov;
 	ctl_len = msg_sys.msg_controllen; 
-	if (ctl_len) 
-	{
+	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
+		err = cmsghdr_from_user_compat_to_kern(&msg_sys, ctl, sizeof(ctl));
+		if (err)
+			goto out_freeiov;
+		ctl_buf = msg_sys.msg_control;
+	} else if (ctl_len) {
 		if (ctl_len > sizeof(ctl))
 		{
 			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
@@ -1629,6 +1636,7 @@
 
 asmlinkage long sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags)
 {
+	struct compat_msghdr *msg_compat = (struct compat_msghdr *)msg;
 	struct socket *sock;
 	struct iovec iovstack[UIO_FASTIOV];
 	struct iovec *iov=iovstack;
@@ -1643,9 +1651,12 @@
 	struct sockaddr *uaddr;
 	int *uaddr_len;
 	
-	err=-EFAULT;
-	if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
-		goto out;
+	if (MSG_CMSG_COMPAT & flags) {
+		if (msghdr_from_user_compat_to_kern(&msg_sys, msg_compat))
+			return -EFAULT;
+	} else
+		if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
+			return -EFAULT;
 
 	sock = sockfd_lookup(fd, &err);
 	if (!sock)
@@ -1670,8 +1681,11 @@
 	 */
 	 
 	uaddr = msg_sys.msg_name;
-	uaddr_len = &msg->msg_namelen;
-	err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
+	uaddr_len = COMPAT_NAMELEN(msg);
+	if (MSG_CMSG_COMPAT & flags) {
+		err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
+	} else
+		err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
 	if (err < 0)
 		goto out_freeiov;
 	total_len=err;
@@ -1691,11 +1705,20 @@
 		if (err < 0)
 			goto out_freeiov;
 	}
-	err = __put_user(msg_sys.msg_flags, &msg->msg_flags);
+	err = __put_user(msg_sys.msg_flags, COMPAT_FLAGS(msg));
 	if (err)
 		goto out_freeiov;
-	err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, 
-							 &msg->msg_controllen);
+	if (MSG_CMSG_COMPAT & flags) {
+		unsigned long ucmsg_ptr;
+		compat_size_t uclen;
+		if((unsigned long) msg_sys.msg_control != cmsg_ptr)
+			cmsg_compat_recvmsg_fixup(&msg_sys, cmsg_ptr);
+		ucmsg_ptr = ((unsigned long)msg_sys.msg_control);
+		uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr);
+		err = __put_user(uclen, &msg_compat->msg_controllen);
+	} else
+		err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, 
+				 &msg->msg_controllen);
 	if (err)
 		goto out_freeiov;
 	err = len;
diff -Nru a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
--- a/net/sunrpc/clnt.c	Sat Feb 15 12:05:02 2003
+++ b/net/sunrpc/clnt.c	Thu Mar  6 08:17:17 2003
@@ -208,7 +208,8 @@
 		rpcauth_destroy(clnt->cl_auth);
 		clnt->cl_auth = NULL;
 	}
-	rpc_rmdir(clnt->cl_pathname);
+	if (clnt->cl_pathname[0])
+		rpc_rmdir(clnt->cl_pathname);
 	if (clnt->cl_xprt) {
 		xprt_destroy(clnt->cl_xprt);
 		clnt->cl_xprt = NULL;
diff -Nru a/net/sunrpc/sched.c b/net/sunrpc/sched.c
--- a/net/sunrpc/sched.c	Tue Feb 11 14:57:54 2003
+++ b/net/sunrpc/sched.c	Sat Mar  8 15:47:51 2003
@@ -158,10 +158,8 @@
 static inline void
 rpc_delete_timer(struct rpc_task *task)
 {
-	if (timer_pending(&task->tk_timer)) {
+	if (del_timer_sync(&task->tk_timer))
 		dprintk("RPC: %4d deleting timer\n", task->tk_pid);
-		del_timer_sync(&task->tk_timer);
-	}
 }
 
 /*
diff -Nru a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
--- a/net/sunrpc/xprt.c	Thu Feb 13 05:17:10 2003
+++ b/net/sunrpc/xprt.c	Mon Mar  3 04:56:53 2003
@@ -967,7 +967,7 @@
 	dprintk("RPC:      tcp_state_change client %p...\n", xprt);
 	dprintk("RPC:      state %x conn %d dead %d zapped %d\n",
 				sk->state, xprt_connected(xprt),
-				sk->dead, sk->zapped);
+				test_bit(SOCK_DEAD, &sk->flags), sk->zapped);
 
 	switch (sk->state) {
 	case TCP_ESTABLISHED:
diff -Nru a/net/unix/af_unix.c b/net/unix/af_unix.c
--- a/net/unix/af_unix.c	Fri Feb  7 01:50:37 2003
+++ b/net/unix/af_unix.c	Thu Mar  6 11:06:45 2003
@@ -331,7 +331,8 @@
 		 * we signal error. Messages are lost. Do not make this,
 		 * when peer was not connected to us.
 		 */
-		if (!other->dead && unix_peer(other) == sk) {
+		if (!test_bit(SOCK_DEAD, &other->flags) &&
+				unix_peer(other) == sk) {
 			other->err = ECONNRESET;
 			other->error_report(other);
 		}
@@ -347,7 +348,7 @@
 	BUG_TRAP(atomic_read(&sk->wmem_alloc) == 0);
 	BUG_TRAP(!u->list);
 	BUG_TRAP(sk->socket==NULL);
-	if (sk->dead==0) {
+	if (!test_bit(SOCK_DEAD, &sk->flags)) {
 		printk("Attempt to release alive unix socket: %p\n", sk);
 		return;
 	}
@@ -863,7 +864,7 @@
 	__set_current_state(TASK_INTERRUPTIBLE);
 	add_wait_queue_exclusive(&u->peer_wait, &wait);
 
-	sched = (!other->dead &&
+	sched = (!test_bit(SOCK_DEAD, &other->flags) &&
 		 !(other->shutdown&RCV_SHUTDOWN) &&
 		 skb_queue_len(&other->receive_queue) > other->max_ack_backlog);
 
@@ -928,7 +929,7 @@
 	unix_state_rlock(other);
 
 	/* Apparently VFS overslept socket death. Retry. */
-	if (other->dead) {
+	if (test_bit(SOCK_DEAD, &other->flags)) {
 		unix_state_runlock(other);
 		sock_put(other);
 		goto restart;
@@ -1192,10 +1193,10 @@
  *	Send AF_UNIX data.
  */
 
-static int unix_dgram_sendmsg(struct kiocb *iocb, struct socket *sock,
-			      struct msghdr *msg, int len,
-			      struct scm_cookie *scm)
+static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
+			      struct msghdr *msg, int len)
 {
+	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
 	struct sock *sk = sock->sk;
 	struct unix_sock *u = unix_sk(sk);
 	struct sockaddr_un *sunaddr=msg->msg_name;
@@ -1205,6 +1206,13 @@
 	unsigned hash;
 	struct sk_buff *skb;
 	long timeo;
+	struct scm_cookie tmp_scm;
+
+	if (NULL == siocb->scm)
+		siocb->scm = &tmp_scm;
+	err = scm_send(sock, msg, siocb->scm);
+	if (err < 0)
+		return err;
 
 	err = -EOPNOTSUPP;
 	if (msg->msg_flags&MSG_OOB)
@@ -1234,9 +1242,9 @@
 	if (skb==NULL)
 		goto out;
 
-	memcpy(UNIXCREDS(skb), &scm->creds, sizeof(struct ucred));
-	if (scm->fp)
-		unix_attach_fds(scm, skb);
+	memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
+	if (siocb->scm->fp)
+		unix_attach_fds(siocb->scm, skb);
 
 	skb->h.raw = skb->data;
 	err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
@@ -1261,7 +1269,7 @@
 	if (!unix_may_send(sk, other))
 		goto out_unlock;
 
-	if (other->dead) {
+	if (test_bit(SOCK_DEAD, &other->flags)) {
 		/*
 		 *	Check with 1003.1g - what should
 		 *	datagram error
@@ -1316,6 +1324,7 @@
 	unix_state_runlock(other);
 	other->data_ready(other, len);
 	sock_put(other);
+	scm_destroy(siocb->scm);
 	return len;
 
 out_unlock:
@@ -1325,20 +1334,28 @@
 out:
 	if (other)
 		sock_put(other);
+	scm_destroy(siocb->scm);
 	return err;
 }
 
 		
-static int unix_stream_sendmsg(struct kiocb *iocb, struct socket *sock,
-			       struct msghdr *msg, int len,
-			       struct scm_cookie *scm)
+static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
+			       struct msghdr *msg, int len)
 {
+	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
 	struct sock *sk = sock->sk;
 	unix_socket *other = NULL;
 	struct sockaddr_un *sunaddr=msg->msg_name;
 	int err,size;
 	struct sk_buff *skb;
 	int sent=0;
+	struct scm_cookie tmp_scm;
+
+	if (NULL == siocb->scm)
+		siocb->scm = &tmp_scm;
+	err = scm_send(sock, msg, siocb->scm);
+	if (err < 0)
+		return err;
 
 	err = -EOPNOTSUPP;
 	if (msg->msg_flags&MSG_OOB)
@@ -1392,9 +1409,9 @@
 		 */
 		size = min_t(int, size, skb_tailroom(skb));
 
-		memcpy(UNIXCREDS(skb), &scm->creds, sizeof(struct ucred));
-		if (scm->fp)
-			unix_attach_fds(scm, skb);
+		memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
+		if (siocb->scm->fp)
+			unix_attach_fds(siocb->scm, skb);
 
 		if ((err = memcpy_fromiovec(skb_put(skb,size), msg->msg_iov, size)) != 0) {
 			kfree_skb(skb);
@@ -1403,7 +1420,8 @@
 
 		unix_state_rlock(other);
 
-		if (other->dead || (other->shutdown & RCV_SHUTDOWN))
+		if (test_bit(SOCK_DEAD, &other->flags) ||
+				(other->shutdown & RCV_SHUTDOWN))
 			goto pipe_err_free;
 
 		skb_queue_tail(&other->receive_queue, skb);
@@ -1412,6 +1430,10 @@
 		sent+=size;
 	}
 	sock_put(other);
+
+	scm_destroy(siocb->scm);
+	siocb->scm = NULL;
+
 	return sent;
 
 pipe_err_free:
@@ -1424,6 +1446,8 @@
 out_err:
         if (other)
 		sock_put(other);
+	scm_destroy(siocb->scm);
+	siocb->scm = NULL;
 	return sent ? : err;
 }
 
@@ -1440,8 +1464,10 @@
 
 static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
 			      struct msghdr *msg, int size,
-			      int flags, struct scm_cookie *scm)
+			      int flags)
 {
+	struct sock_iocb *siocb = kiocb_to_siocb(iocb);
+	struct scm_cookie tmp_scm;
 	struct sock *sk = sock->sk;
 	struct unix_sock *u = unix_sk(sk);
 	int noblock = flags & MSG_DONTWAIT;
@@ -1472,12 +1498,16 @@
 	if (err)
 		goto out_free;
 
-	scm->creds = *UNIXCREDS(skb);
+	if (!siocb->scm) {
+		siocb->scm = &tmp_scm;
+		memset(&tmp_scm, 0, sizeof(tmp_scm));
+	}
+	siocb->scm->creds = *UNIXCREDS(skb);
 
 	if (!(flags & MSG_PEEK))
 	{
 		if (UNIXCB(skb).fp)
-			unix_detach_fds(scm, skb);
+			unix_detach_fds(siocb->scm, skb);
 	}
 	else 
 	{
@@ -1494,10 +1524,12 @@
 		   
 		*/
 		if (UNIXCB(skb).fp)
-			scm->fp = scm_fp_dup(UNIXCB(skb).fp);
+			siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
 	}
 	err = size;
 
+	scm_recv(sock, msg, siocb->scm, flags);
+
 out_free:
 	skb_free_datagram(sk,skb);
 out:
@@ -1543,8 +1575,10 @@
 
 static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
 			       struct msghdr *msg, int size,
-			       int flags, struct scm_cookie *scm)
+			       int flags)
 {
+	struct sock_iocb *siocb = kiocb_to_siocb(iocb);
+	struct scm_cookie tmp_scm;
 	struct sock *sk = sock->sk;
 	struct unix_sock *u = unix_sk(sk);
 	struct sockaddr_un *sunaddr=msg->msg_name;
@@ -1571,6 +1605,11 @@
 	 * while sleeps in memcpy_tomsg
 	 */
 
+	if (!siocb->scm) {
+		siocb->scm = &tmp_scm;
+		memset(&tmp_scm, 0, sizeof(tmp_scm));
+	}
+
 	down(&u->readsem);
 
 	do
@@ -1609,13 +1648,13 @@
 
 		if (check_creds) {
 			/* Never glue messages from different writers */
-			if (memcmp(UNIXCREDS(skb), &scm->creds, sizeof(scm->creds)) != 0) {
+			if (memcmp(UNIXCREDS(skb), &siocb->scm->creds, sizeof(siocb->scm->creds)) != 0) {
 				skb_queue_head(&sk->receive_queue, skb);
 				break;
 			}
 		} else {
 			/* Copy credentials */
-			scm->creds = *UNIXCREDS(skb);
+			siocb->scm->creds = *UNIXCREDS(skb);
 			check_creds = 1;
 		}
 
@@ -1642,7 +1681,7 @@
 			skb_pull(skb, chunk);
 
 			if (UNIXCB(skb).fp)
-				unix_detach_fds(scm, skb);
+				unix_detach_fds(siocb->scm, skb);
 
 			/* put the skb back if we didn't use it up.. */
 			if (skb->len)
@@ -1653,7 +1692,7 @@
 
 			kfree_skb(skb);
 
-			if (scm->fp)
+			if (siocb->scm->fp)
 				break;
 		}
 		else
@@ -1661,7 +1700,7 @@
 			/* It is questionable, see note in unix_dgram_recvmsg.
 			 */
 			if (UNIXCB(skb).fp)
-				scm->fp = scm_fp_dup(UNIXCB(skb).fp);
+				siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
 
 			/* put message back and return */
 			skb_queue_head(&sk->receive_queue, skb);
@@ -1670,6 +1709,7 @@
 	} while (size);
 
 	up(&u->readsem);
+	scm_recv(sock, msg, siocb->scm, flags);
 out:
 	return copied ? : err;
 }
diff -Nru a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
--- a/net/wanrouter/af_wanpipe.c	Mon Feb 24 12:51:23 2003
+++ b/net/wanrouter/af_wanpipe.c	Sat Mar  8 11:30:11 2003
@@ -76,14 +76,7 @@
 	#define DBG_PRINTK(format, a...)
 #endif      
 
-#if defined(LINUX_2_1)
- #define dev_put(a)
- #define __sock_put(a)
- #define sock_hold(a)
- #define DECLARE_WAITQUEUE(a,b) \
-		struct wait_queue a = { b, NULL }
-#endif
-		
+
 /* SECURE SOCKET IMPLEMENTATION 
  * 
  *   TRANSMIT:
@@ -542,7 +535,7 @@
  *===========================================================*/
 
 static int wanpipe_sendmsg(struct kiocb *iocb, struct socket *sock,
-			   struct msghdr *msg, int len, struct scm_cookie *scm)
+			   struct msghdr *msg, int len)
 {
 	wanpipe_opt *wp;
 	struct sock *sk = sock->sk;
@@ -599,17 +592,8 @@
   		return -EMSGSIZE;
 	}
 
-      #ifndef LINUX_2_4
-	dev_lock_list();
-      #endif
-      
-      #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
 	skb = sock_alloc_send_skb(sk, len+dev->hard_header_len+15, 
 				msg->msg_flags & MSG_DONTWAIT, &err);
-      #else
-	skb = sock_alloc_send_skb(sk, len+dev->hard_header_len+15, 0, 
-				msg->msg_flags & MSG_DONTWAIT, &err);
-      #endif
 
 	if (skb==NULL){
 		goto out_unlock;
@@ -642,10 +626,6 @@
 	if (!(dev->flags & IFF_UP))
 		goto out_free;
 
-      #ifndef LINUX_2_4
-	dev_unlock_list();
-      #endif
-	
 	if (atomic_read(&sk->wmem_alloc) + skb->truesize > (unsigned int)sk->sndbuf){
 		kfree_skb(skb);
 		return -ENOBUFS;
@@ -665,9 +645,6 @@
 out_free:
 	kfree_skb(skb);
 out_unlock:
-#ifndef LINUX_2_4
-	dev_unlock_list();
-#endif
 	return err;
 }
 
@@ -862,16 +839,12 @@
 		kfree(wp);
 		wp_sk(sk) = NULL;
 		
-              #ifdef LINUX_2_4
 		if (atomic_read(&sk->refcnt) != 1){
 			atomic_set(&sk->refcnt,1);
 			DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :delay.\n",
 					atomic_read(&sk->refcnt));
 		}
 		sock_put(sk);
-              #else
-		sk_free(sk);
-              #endif
 		atomic_dec(&wanpipe_socks_nr);
 		MOD_DEC_USE_COUNT;
 		return;
@@ -970,16 +943,8 @@
  *      protocol entry in the device list.
  *===========================================================*/
 
-#ifdef LINUX_2_4
 static int wanpipe_release(struct socket *sock)
-#else
-static int wanpipe_release(struct socket *sock, struct socket *peersock)
-#endif
 {
-	
-#ifndef LINUX_2_4
-	struct sk_buff	*skb;
-#endif
 	wanpipe_opt *wp;
 	struct sock *sk = sock->sk;
 	struct sock **skp;
@@ -1039,25 +1004,13 @@
 
 	sock->sk = NULL;
 	sk->socket = NULL;
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 
 	/* Purge queues */
-#ifdef LINUX_2_4
 	skb_queue_purge(&sk->receive_queue);
 	skb_queue_purge(&sk->write_queue);
 	skb_queue_purge(&sk->error_queue);
-#else	
 
-	while ((skb=skb_dequeue(&sk->receive_queue))!=NULL){
-		kfree_skb(skb);
-	}
-	while ((skb=skb_dequeue(&sk->error_queue))!=NULL){
-		kfree_skb(skb);
-	}
-	while ((skb=skb_dequeue(&sk->write_queue))!=NULL){
-		kfree_skb(skb);
-	}
-#endif	
 	if (atomic_read(&sk->rmem_alloc) || atomic_read(&sk->wmem_alloc)) {
 		del_timer(&sk->timer);
 		printk(KERN_INFO "wansock: Killing in Timer R %i , W %i\n",
@@ -1072,16 +1025,12 @@
 	kfree(wp);
 	wp_sk(sk) = NULL;
 
-      #ifdef LINUX_2_4
 	if (atomic_read(&sk->refcnt) != 1){
 		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i !:release.\n",
 					atomic_read(&sk->refcnt));
 		atomic_set(&sk->refcnt,1);
 	}
 	sock_put(sk);
-      #else	
-	sk_free(sk);
-      #endif
 	atomic_dec(&wanpipe_socks_nr);
 	MOD_DEC_USE_COUNT;
 	return 0;
@@ -1128,7 +1077,7 @@
 		while ((skb=skb_dequeue(&sk->receive_queue))!=NULL){
 			if ((deadsk = get_newsk_from_skb(skb))){
 				DBG_PRINTK (KERN_INFO "wansock: RELEASE: FOUND DEAD SOCK\n");
-				deadsk->dead=1;
+				__set_bit(SOCK_DEAD, &deadsk->flags);
 				start_cleanup_timer(deadsk);
 			}
 			kfree_skb(skb);
@@ -1181,10 +1130,6 @@
 {
 
 	struct sock *sk = (struct sock *)data;
-#ifndef LINUX_2_4
-	struct sk_buff *skb;
-#endif
-
 	struct sock **skp;
 
 	if (!sk)
@@ -1226,21 +1171,9 @@
 	sk->socket = NULL;
 
 	/* Purge queues */
-#ifdef LINUX_2_4
 	skb_queue_purge(&sk->receive_queue);
 	skb_queue_purge(&sk->write_queue);
 	skb_queue_purge(&sk->error_queue);
-#else	
-	while ((skb=skb_dequeue(&sk->receive_queue)) != NULL){
-		kfree_skb(skb);
-	}
-	while ((skb=skb_dequeue(&sk->write_queue)) != NULL) {
-		kfree_skb(skb);
-	}
-	while ((skb=skb_dequeue(&sk->error_queue)) != NULL){
-		kfree_skb(skb);
-	}
-#endif
 	
 	if (atomic_read(&sk->rmem_alloc) || atomic_read(&sk->wmem_alloc)) {
 		del_timer(&sk->timer);
@@ -1257,16 +1190,12 @@
 		wp_sk(sk) = NULL;
 	}
 
-      #ifdef LINUX_2_4
 	if (atomic_read(&sk->refcnt) != 1){
 		atomic_set(&sk->refcnt,1);
 		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :timer.\n",
 					atomic_read(&sk->refcnt));
 	}
 	sock_put(sk);
-      #else
-	sk_free(sk);
-      #endif
 	atomic_dec(&wanpipe_socks_nr);
 	MOD_DEC_USE_COUNT;
 	return;
@@ -1301,16 +1230,12 @@
 		wp_sk(sk) = NULL;
 	}
 
-      #ifdef LINUX_2_4
 	if (atomic_read(&sk->refcnt) != 1){
 		atomic_set(&sk->refcnt,1);
 		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :timer.\n",
 					atomic_read(&sk->refcnt));
 	}
 	sock_put(sk);
-      #else
-	sk_free(sk);
-      #endif
 	atomic_dec(&wanpipe_socks_nr);
 	MOD_DEC_USE_COUNT;
 	return;
@@ -1330,16 +1255,12 @@
 		wp_sk(sk) = NULL;
 	}
 
-      #ifdef LINUX_2_4
 	if (atomic_read(&sk->refcnt) != 1){
 		atomic_set(&sk->refcnt,1);
 		DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i !:listen.\n",
 					atomic_read(&sk->refcnt));
 	}
 	sock_put(sk);
-      #else
-	sk_free(sk);
-      #endif
 	atomic_dec(&wanpipe_socks_nr);
 	MOD_DEC_USE_COUNT;
 	return;
@@ -1494,11 +1415,7 @@
                  */
 		strncpy(name,sll->sll_device,14);
 		name[14]=0;
-#ifdef LINUX_2_4
 		dev = dev_get_by_name(name);
-#else
-		dev = dev_get(name);
-#endif
 		if (dev == NULL){
 			printk(KERN_INFO "wansock: Failed to get Dev from name: %s,\n",
 					name);
@@ -1649,8 +1566,7 @@
  *===========================================================*/
 
 static int wanpipe_recvmsg(struct kiocb *iocb, struct socket *sock,
-			   struct msghdr *msg, int len, int flags,
-			   struct scm_cookie *scm)
+			   struct msghdr *msg, int len, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb;
@@ -1706,11 +1622,7 @@
 	if (err)
 		goto out_free;
 	
-#ifdef LINUX_2_1
-	sk->stamp=skb->stamp;
-#else
 	sock_recv_timestamp(msg, sk, skb);
-#endif
 	
 	if (msg->msg_name)
 		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
@@ -2212,11 +2124,7 @@
 	if (sock_writeable(sk)){
 		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
 	}else{
-	      #ifdef LINUX_2_4
 		set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
-	      #else
- 		sk->socket->flags |= SO_NOSPACE;
-	      #endif
 	}
 		
 	return mask;
@@ -2649,7 +2557,6 @@
 	return 0;
 }
 
-#ifdef LINUX_2_4
 struct proto_ops wanpipe_ops = {
 	.family = 	PF_WANPIPE,
 
@@ -2668,29 +2575,6 @@
 	.sendmsg = 	wanpipe_sendmsg,
 	.recvmsg = 	wanpipe_recvmsg
 };
-#else
-struct proto_ops wanpipe_ops = {
-	PF_WANPIPE,
-
-	sock_no_dup,
-	wanpipe_release,
-	wanpipe_bind,
-	wanpipe_connect,
-	sock_no_socketpair,
-	wanpipe_accept,
-	wanpipe_getname, 
-	wanpipe_poll,
-	wanpipe_ioctl,
-	wanpipe_listen, 
-	sock_no_shutdown,
-	sock_no_setsockopt,
-	sock_no_getsockopt,
-	sock_no_fcntl,
-	wanpipe_sendmsg,
-	wanpipe_recvmsg
-};
-#endif
-
 
 static struct net_proto_family wanpipe_family_ops = {
 	.family =PF_WANPIPE,
diff -Nru a/net/x25/af_x25.c b/net/x25/af_x25.c
--- a/net/x25/af_x25.c	Tue Oct  8 07:03:35 2002
+++ b/net/x25/af_x25.c	Thu Mar  6 11:06:45 2003
@@ -344,7 +344,7 @@
 			/*
 			 * Queue the unaccepted socket for death
 			 */
-			skb->sk->dead = 1;
+			__set_bit(SOCK_DEAD, &skb->sk->flags);
 			x25_start_heartbeat(skb->sk);
 			x25_sk(skb->sk)->state = X25_STATE_0;
 		}
@@ -580,8 +580,8 @@
 			sk->state               = TCP_CLOSE;
 			sk->shutdown           |= SEND_SHUTDOWN;
 			sk->state_change(sk);
-			sk->dead                = 1;
-			sk->destroy             = 1;
+			__set_bit(SOCK_DEAD, &sk->flags);
+			__set_bit(SOCK_DESTROY, &sk->flags);
 			break;
 	}
 
@@ -902,7 +902,7 @@
 
 	x25_start_heartbeat(make);
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->data_ready(sk, skb->len);
 	rc = 1;
 	sock_put(sk);
@@ -917,7 +917,7 @@
 }
 
 static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
-		       struct msghdr *msg, int len, struct scm_cookie *scm)
+		       struct msghdr *msg, int len)
 {
 	struct sock *sk = sock->sk;
 	struct x25_opt *x25 = x25_sk(sk);
@@ -1093,7 +1093,7 @@
 
 static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
 		       struct msghdr *msg, int size,
-		       int flags, struct scm_cookie *scm)
+		       int flags)
 {
 	struct sock *sk = sock->sk;
 	struct x25_opt *x25 = x25_sk(sk);
@@ -1112,7 +1112,8 @@
 
 	if (flags & MSG_OOB) {
 		rc = -EINVAL;
-		if (sk->urginline || !skb_peek(&x25->interrupt_in_queue))
+		if (test_bit(SOCK_URGINLINE, &sk->flags) ||
+				!skb_peek(&x25->interrupt_in_queue))
 			goto out;
 
 		skb = skb_dequeue(&x25->interrupt_in_queue);
diff -Nru a/net/x25/x25_in.c b/net/x25/x25_in.c
--- a/net/x25/x25_in.c	Sat Sep 28 02:28:53 2002
+++ b/net/x25/x25_in.c	Mon Mar  3 04:56:53 2003
@@ -86,7 +86,7 @@
 
 	skb_set_owner_r(skbn, sk);
 	skb_queue_tail(&sk->receive_queue, skbn);
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->data_ready(sk, skbn->len);
 
 	return 0;
@@ -129,7 +129,7 @@
 				       skb->len);
 				x25->calluserdata.cudlength = skb->len;
 			}
-			if (!sk->dead)
+			if (!test_bit(SOCK_DEAD, &sk->flags))
 				sk->state_change(sk);
 			break;
 		}
@@ -277,7 +277,7 @@
 			break;
 
 		case X25_INTERRUPT:
-			if (sk->urginline) {
+			if (test_bit(SOCK_URGINLINE, &sk->flags)) {
 				queued = (sock_queue_rcv_skb(sk, skb) == 0);
 			} else {
 				skb_set_owner_r(skb, sk);
diff -Nru a/net/x25/x25_subr.c b/net/x25/x25_subr.c
--- a/net/x25/x25_subr.c	Sat Sep 28 02:28:53 2002
+++ b/net/x25/x25_subr.c	Mon Mar  3 04:56:53 2003
@@ -344,10 +344,10 @@
 	sk->err       = reason;
 	sk->shutdown |= SEND_SHUTDOWN;
 
-	if (!sk->dead)
+	if (!test_bit(SOCK_DEAD, &sk->flags))
 		sk->state_change(sk);
 
-	sk->dead = 1;
+	__set_bit(SOCK_DEAD, &sk->flags);
 }
 
 /*
diff -Nru a/net/x25/x25_timer.c b/net/x25/x25_timer.c
--- a/net/x25/x25_timer.c	Tue Oct  8 17:45:17 2002
+++ b/net/x25/x25_timer.c	Mon Mar  3 04:56:53 2003
@@ -139,7 +139,7 @@
 		case X25_STATE_0:
 			/* Magic here: If we listen() and a new link dies before it
 			   is accepted() it isn't 'dead' so doesn't get removed. */
-			if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) {
+			if (test_bit(SOCK_DESTROY, &sk->flags) || (sk->state == TCP_LISTEN && test_bit(SOCK_DEAD, &sk->flags))) {
 				x25_destroy_socket(sk);
 				goto unlock;
 			}
diff -Nru a/scripts/Makefile.build b/scripts/Makefile.build
--- a/scripts/Makefile.build	Wed Feb 19 14:42:13 2003
+++ b/scripts/Makefile.build	Wed Mar  5 18:09:44 2003
@@ -163,12 +163,12 @@
 # Single-part modules are special since we need to mark them in $(MODVERDIR)
 
 $(single-used-m): %.o: %.c FORCE
-	$(touch-module)
 ifdef CONFIG_MODVERSIONS
 	$(call if_changed_rule,vcc_o_c)
 else
 	$(call if_changed_dep,cc_o_c)
 endif
+	$(touch-module)
 
 quiet_cmd_cc_lst_c = MKLST   $@
       cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
@@ -262,8 +262,8 @@
 	$(call if_changed,link_multi-y)
 
 $(multi-used-m) : %.o: $(multi-objs-m) FORCE
-	$(touch-module)
 	$(call if_changed,link_multi-m)
+	$(touch-module)
 
 targets += $(multi-used-y) $(multi-used-m)
 
diff -Nru a/scripts/Makefile.modpost b/scripts/Makefile.modpost
--- a/scripts/Makefile.modpost	Sun Mar  2 20:55:31 2003
+++ b/scripts/Makefile.modpost	Wed Mar  5 17:51:30 2003
@@ -37,7 +37,7 @@
 quiet_cmd_cc_o_c = CC      $@
       cmd_cc_o_c = $(CC) $(CFLAGS) $(CFLAGS_MODULE) -c -o $@ $<
 
-$(modules:.ko=.mod.o): %.mod.o: %.mod.c
+$(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
 	$(call if_changed,cc_o_c)
 
 targets += $(modules:.ko=.mod.o)
@@ -51,9 +51,9 @@
 # Extract all checksums for all exported symbols
 
 quiet_cmd_modpost = MODPOST
-      cmd_modpost = scripts/modpost $^
+      cmd_modpost = scripts/modpost $(filter-out FORCE,$^)
 
-__modpost: $(wildcard vmlinux) $(modules:.ko=.o)
+__modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE
 	$(call if_changed,modpost)
 
 targets += __modpost
diff -Nru a/scripts/modpost.c b/scripts/modpost.c
--- a/scripts/modpost.c	Fri Feb 21 19:50:41 2003
+++ b/scripts/modpost.c	Wed Mar  5 18:07:11 2003
@@ -293,6 +293,9 @@
 		/* undefined symbol */
 		if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL)
 			break;
+		/* ignore global offset table */
+		if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0)
+			break;
 		
 		if (memcmp(symname, MODULE_SYMBOL_PREFIX,
 			   strlen(MODULE_SYMBOL_PREFIX)) == 0) {
diff -Nru a/scripts/per-cpu-check.awk b/scripts/per-cpu-check.awk
--- a/scripts/per-cpu-check.awk	Fri Jan 24 12:27:01 2003
+++ b/scripts/per-cpu-check.awk	Wed Mar  5 17:53:22 2003
@@ -6,7 +6,7 @@
 	IN_PER_CPU=0
 }
 
-/__per_cpu$$/ && ! ( / __ksymtab_/ || / __kstrtab_/ || / __kcrctab_/ ) {
+/__per_cpu$$/ && ! ( / __ksymtab_/ || / __kstrtab_/ || / __kcrctab_/ || / __crc_/ ) {
 	if (!IN_PER_CPU) {
 		print $$3 " not in per-cpu section" > "/dev/stderr";
 		FOUND=1;
diff -Nru a/sound/isa/als100.c b/sound/isa/als100.c
--- a/sound/isa/als100.c	Tue Oct 22 06:04:00 2002
+++ b/sound/isa/als100.c	Sun Mar  9 15:44:14 2003
@@ -24,11 +24,7 @@
 #include <linux/init.h>
 #include <linux/wait.h>
 #include <linux/time.h>
-#ifndef LINUX_ISAPNP_H
-#include <linux/isapnp.h>
-#define isapnp_card pci_bus
-#define isapnp_dev pci_dev
-#endif
+#include <linux/pnp.h>
 #include <sound/core.h>
 #define SNDRV_GET_ID
 #include <sound/initval.h>
@@ -96,167 +92,124 @@
 MODULE_PARM_SYNTAX(dma16, SNDRV_DMA16_DESC);
 
 struct snd_card_als100 {
-#ifdef __ISAPNP__
-	struct isapnp_dev *dev;
-	struct isapnp_dev *devmpu;
-	struct isapnp_dev *devopl;
-#endif	/* __ISAPNP__ */
+	int dev_no;
+	struct pnp_dev *dev;
+	struct pnp_dev *devmpu;
+	struct pnp_dev *devopl;
 };
 
-static snd_card_t *snd_als100_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
-
-#ifdef __ISAPNP__
-static struct isapnp_card *snd_als100_isapnp_cards[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
-static const struct isapnp_card_id *snd_als100_isapnp_id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
-
-#define ISAPNP_ALS100(_va, _vb, _vc, _device, _audio, _mpu401, _opl) \
-        { \
-                ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
-                devs : { ISAPNP_DEVICE_ID('@', '@', '@', _audio), \
-                         ISAPNP_DEVICE_ID('@', 'X', '@', _mpu401), \
-			 ISAPNP_DEVICE_ID('@', 'H', '@', _opl) } \
-        }
-
-static struct isapnp_card_id snd_als100_pnpids[] __devinitdata = {
+static struct pnp_card_id snd_als100_pnpids[] __devinitdata = {
 	/* ALS100 - PRO16PNP */
-	ISAPNP_ALS100('A','L','S',0x0001,0x0001,0x0001,0x0001),
+	{ .id = "ALS0001", .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" }, } },
 	/* ALS110 - MF1000 - Digimate 3D Sound */
-	ISAPNP_ALS100('A','L','S',0x0110,0x1001,0x1001,0x1001),
+	{ .id = "ALS0110", .devs = { { "@@@1001" }, { "@X@1001" }, { "@H@1001" }, } },
 	/* ALS120 */
-	ISAPNP_ALS100('A','L','S',0x0120,0x2001,0x2001,0x2001),
+	{ .id = "ALS0120", .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" }, } },
 	/* ALS200 */
-	ISAPNP_ALS100('A','L','S',0x0200,0x0020,0x0020,0x0001),
+	{ .id = "ALS0200", .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0001" }, } },
 	/* RTL3000 */
-	ISAPNP_ALS100('R','T','L',0x3000,0x2001,0x2001,0x2001),
-	{ ISAPNP_CARD_END, }
+	{ .id = "RTL3000", .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" }, } },
+	{ .id = "", } /* end */
 };
 
-ISAPNP_CARD_TABLE(snd_als100_pnpids);
-
-#endif	/* __ISAPNP__ */
+MODULE_DEVICE_TABLE(pnp_card, snd_als100_pnpids);
 
 #define DRIVER_NAME	"snd-card-als100"
 
-
-#ifdef __ISAPNP__
-static int __init snd_card_als100_isapnp(int dev, struct snd_card_als100 *acard)
+static int __devinit snd_card_als100_isapnp(int dev, struct snd_card_als100 *acard,
+					    struct pnp_card_link *card,
+					    const struct pnp_card_id *id)
 {
-	const struct isapnp_card_id *id = snd_als100_isapnp_id[dev];
-	struct isapnp_card *card = snd_als100_isapnp_cards[dev];
-	struct isapnp_dev *pdev;
-
-	acard->dev = isapnp_find_dev(card, id->devs[0].vendor, id->devs[0].function, NULL);
-	if (acard->dev->active) {
-		acard->dev = NULL;
-		return -EBUSY;
-	}
-	acard->devmpu = isapnp_find_dev(card, id->devs[1].vendor, id->devs[1].function, NULL);
-	if (acard->devmpu->active) {
-		acard->dev = acard->devmpu = NULL;
-		return -EBUSY;
-	}
-	acard->devopl = isapnp_find_dev(card, id->devs[2].vendor, id->devs[2].function, NULL);
-	if (acard->devopl->active) {
-		acard->dev = acard->devmpu = acard->devopl = NULL;
-		return -EBUSY;
+	struct pnp_dev *pdev;
+	struct pnp_resource_table * cfg = kmalloc(GFP_ATOMIC, sizeof(struct pnp_resource_table));
+	int err;
+	if (!cfg)
+		return -ENOMEM;
+	acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
+	if (acard->dev == NULL) {
+		kfree(cfg);
+		return -ENODEV;
 	}
+	acard->devmpu = pnp_request_card_device(card, id->devs[1].id, acard->dev);
+	acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->devmpu);
 
 	pdev = acard->dev;
-	if (pdev->prepare(pdev)<0)
-		return -EAGAIN;
 
+	pnp_init_resource_table(cfg);
+
+	/* override resources */
 	if (port[dev] != SNDRV_AUTO_PORT)
-		isapnp_resource_change(&pdev->resource[0], port[dev], 16);
+		pnp_resource_change(&cfg->port_resource[0], port[dev], 16);
 	if (dma8[dev] != SNDRV_AUTO_DMA)
-		isapnp_resource_change(&pdev->dma_resource[0], dma8[dev],
-			1);
+		pnp_resource_change(&cfg->dma_resource[0], dma8[dev], 1);
 	if (dma16[dev] != SNDRV_AUTO_DMA)
-		isapnp_resource_change(&pdev->dma_resource[1], dma16[dev],
-			1);
+		pnp_resource_change(&cfg->dma_resource[1], dma16[dev], 1);
 	if (irq[dev] != SNDRV_AUTO_IRQ)
-		isapnp_resource_change(&pdev->irq_resource[0], irq[dev], 1);
-
-	if (pdev->activate(pdev)<0) {
-		printk(KERN_ERR PFX "AUDIO isapnp configure failure\n");
-		return -EBUSY;
-	}
-
-	port[dev] = pdev->resource[0].start;
-	dma8[dev] = pdev->dma_resource[1].start;
-	dma16[dev] = pdev->dma_resource[0].start;
-	irq[dev] = pdev->irq_resource[0].start;
+		pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
+	if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
+		printk(KERN_ERR PFX "AUDIO the requested resources are invalid, using auto config\n");
+	err = pnp_activate_dev(pdev);
+	if (err < 0) {
+		printk(KERN_ERR PFX "AUDIO pnp configure failure\n");
+		return err;
+	}
+	port[dev] = pnp_port_start(pdev, 0);
+	dma8[dev] = pnp_dma(pdev, 1);
+	dma16[dev] = pnp_dma(pdev, 0);
+	irq[dev] = pnp_irq(pdev, 0);
 
 	pdev = acard->devmpu;
-	if (pdev == NULL || pdev->prepare(pdev)<0) {
-		mpu_port[dev] = -1;
-		return 0;
-	}
-
-	if (mpu_port[dev] != SNDRV_AUTO_PORT)
-		isapnp_resource_change(&pdev->resource[0], mpu_port[dev],
-			2);
-	if (mpu_irq[dev] != SNDRV_AUTO_IRQ)
-		isapnp_resource_change(&pdev->irq_resource[0], mpu_irq[dev],
-			1);
-
-	if (pdev->activate(pdev)<0) {
-		printk(KERN_ERR PFX "MPU-401 isapnp configure failure\n");
-		mpu_port[dev] = -1;
-		acard->devmpu = NULL;
+	if (pdev != NULL) {
+		pnp_init_resource_table(cfg);
+		if (mpu_port[dev] != SNDRV_AUTO_PORT)
+			pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2);
+		if (mpu_irq[dev] != SNDRV_AUTO_IRQ)
+			pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1);
+		if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
+			printk(KERN_ERR PFX "MPU401 the requested resources are invalid, using auto config\n");
+		err = pnp_activate_dev(pdev);
+		if (err < 0)
+			goto __mpu_error;
+		mpu_port[dev] = pnp_port_start(pdev, 0);
+		mpu_irq[dev] = pnp_irq(pdev, 0);
 	} else {
-		mpu_port[dev] = pdev->resource[0].start;
-		mpu_irq[dev] = pdev->irq_resource[0].start;
+	     __mpu_error:
+	     	if (pdev) {
+		     	pnp_release_card_device(pdev);
+	     		printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n");
+	     	}
+	     	acard->devmpu = NULL;
+	     	mpu_port[dev] = -1;
 	}
 
 	pdev = acard->devopl;
-	if (pdev == NULL || pdev->prepare(pdev)<0) {
-		fm_port[dev] = -1;
-		return 0;
-	}
-
-	if (fm_port[dev] != SNDRV_AUTO_PORT)
-		isapnp_resource_change(&pdev->resource[0], fm_port[dev], 4);
-
-	if (pdev->activate(pdev)<0) {
-		printk(KERN_ERR PFX "OPL isapnp configure failure\n");
-		fm_port[dev] = -1;
-		acard->devopl = NULL;
+	if (pdev != NULL) {
+		pnp_init_resource_table(cfg);
+		if (fm_port[dev] != SNDRV_AUTO_PORT)
+			pnp_resource_change(&cfg->port_resource[0], fm_port[dev], 4);
+		if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
+			printk(KERN_ERR PFX "OPL3 the requested resources are invalid, using auto config\n");
+		err = pnp_activate_dev(pdev);
+		if (err < 0)
+			goto __fm_error;
+		fm_port[dev] = pnp_port_start(pdev, 0);
 	} else {
-		fm_port[dev] = pdev->resource[0].start;
+	      __fm_error:
+	     	if (pdev) {
+		     	pnp_release_card_device(pdev);
+	     		printk(KERN_ERR PFX "OPL3 pnp configure failure, skipping\n");
+	     	}
+	     	acard->devopl = NULL;
+	     	fm_port[dev] = -1;
 	}
 
+	kfree(cfg);
 	return 0;
 }
 
-static void snd_card_als100_deactivate(struct snd_card_als100 *acard)
-{
-	if (acard->dev) {
-		acard->dev->deactivate(acard->dev);
-		acard->dev = NULL;
-	}
-	if (acard->devmpu) {
-		acard->devmpu->deactivate(acard->devmpu);
-		acard->devmpu = NULL;
-	}
-	if (acard->devopl) {
-		acard->devopl->deactivate(acard->devopl);
-		acard->devopl = NULL;
-	}
-}
-#endif	/* __ISAPNP__ */
-
-static void snd_card_als100_free(snd_card_t *card)
-{
-	struct snd_card_als100 *acard = (struct snd_card_als100 *)card->private_data;
-
-	if (acard) {
-#ifdef __ISAPNP__
-		snd_card_als100_deactivate(acard);
-#endif	/* __ISAPNP__ */
-	}
-}
-
-static int __init snd_card_als100_probe(int dev)
+static int __init snd_card_als100_probe(int dev,
+					struct pnp_card_link *pcard,
+					const struct pnp_card_id *pid)
 {
 	int error;
 	sb_t *chip;
@@ -268,18 +221,11 @@
 				 sizeof(struct snd_card_als100))) == NULL)
 		return -ENOMEM;
 	acard = (struct snd_card_als100 *)card->private_data;
-	card->private_free = snd_card_als100_free;
 
-#ifdef __ISAPNP__
-	if ((error = snd_card_als100_isapnp(dev, acard))) {
+	if ((error = snd_card_als100_isapnp(dev, acard, pcard, pid))) {
 		snd_card_free(card);
 		return error;
 	}
-#else
-	printk(KERN_ERR PFX "you have to enable PnP support ...\n");
-	snd_card_free(card);
-	return -ENOSYS;
-#endif	/* __ISAPNP__ */
 
 	if ((error = snd_sbdsp_create(card, port[dev],
 				      irq[dev],
@@ -336,13 +282,12 @@
 		snd_card_free(card);
 		return error;
 	}
-	snd_als100_cards[dev] = card;
+	pnp_set_card_drvdata(pcard, card);
 	return 0;
 }
 
-#ifdef __ISAPNP__
-static int __init snd_als100_isapnp_detect(struct isapnp_card *card,
-					   const struct isapnp_card_id *id)
+static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card,
+					   const struct pnp_card_id *id)
 {
 	static int dev;
 	int res;
@@ -350,9 +295,7 @@
 	for ( ; dev < SNDRV_CARDS; dev++) {
 		if (!enable[dev])
 			continue;
-		snd_als100_isapnp_cards[dev] = card;
-		snd_als100_isapnp_id[dev] = id;
-		res = snd_card_als100_probe(dev);
+		res = snd_card_als100_probe(dev, card, id);
 		if (res < 0)
 			return res;
 		dev++;
@@ -360,17 +303,28 @@
 	}
 	return -ENODEV;
 }
-#endif
+
+static void __devexit snd_als100_pnp_remove(struct pnp_card_link * pcard)
+{
+	snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
+
+	snd_card_disconnect(card);
+	snd_card_free_in_thread(card);
+}
+
+static struct pnp_card_driver als100_pnpc_driver = {
+	.flags          = PNP_DRIVER_RES_DISABLE,
+        .name           = "als100",
+        .id_table       = snd_als100_pnpids,
+        .probe          = snd_als100_pnp_detect,
+        .remove         = __devexit_p(snd_als100_pnp_remove),
+};
 
 static int __init alsa_card_als100_init(void)
 {
 	int cards = 0;
 
-#ifdef __ISAPNP__
-	cards += isapnp_probe_cards(snd_als100_pnpids, snd_als100_isapnp_detect);
-#else
-	printk(KERN_ERR PFX "you have to enable ISA PnP support.\n");
-#endif
+	cards += pnp_register_card_driver(&als100_pnpc_driver);
 #ifdef MODULE
 	if (!cards)
 		printk(KERN_ERR "no ALS100 based soundcards found\n");
@@ -380,10 +334,7 @@
 
 static void __exit alsa_card_als100_exit(void)
 {
-	int dev;
-
-	for (dev = 0; dev < SNDRV_CARDS; dev++)
-		snd_card_free(snd_als100_cards[dev]);
+	pnp_unregister_card_driver(&als100_pnpc_driver);
 }
 
 module_init(alsa_card_als100_init)
diff -Nru a/sound/oss/sb_card.c b/sound/oss/sb_card.c
--- a/sound/oss/sb_card.c	Wed Feb 19 09:56:36 2003
+++ b/sound/oss/sb_card.c	Sun Mar  9 15:44:14 2003
@@ -32,9 +32,9 @@
 #include "sound_config.h"
 #include "sb_mixer.h"
 #include "sb.h"
-#ifdef CONFIG_PNP_CARD
+#ifdef CONFIG_PNP
 #include <linux/pnp.h>
-#endif
+#endif /* CONFIG_PNP */
 #include "sb_card.h"
 
 MODULE_DESCRIPTION("OSS Soundblaster ISA PnP and legacy sound driver");
@@ -54,7 +54,7 @@
 
 struct sb_card_config *legacy = NULL;
 
-#ifdef CONFIG_PNP_CARD
+#ifdef CONFIG_PNP
 static int __initdata pnp       = 1;
 /*
 static int __initdata uart401	= 0;
@@ -85,7 +85,7 @@
 MODULE_PARM_DESC(acer,	   "Set this to detect cards in some ACER notebooks "\
 		 "(doesn't work with pnp)");
 
-#ifdef CONFIG_PNP_CARD
+#ifdef CONFIG_PNP
 module_param(pnp, int, 000);
 MODULE_PARM_DESC(pnp,     "Went set to 0 will disable detection using PnP. "\
 		  "Default is 1.\n");
@@ -95,7 +95,7 @@
 MODULE_PARM_DESC(uart401,  "When set to 1, will attempt to detect and enable"\
 		 "the mpu on some clones");
 */
-#endif /* CONFIG_PNP_CARD */
+#endif /* CONFIG_PNP */
 
 /* OSS subsystem card registration shared by PnP and legacy routines */
 static int sb_register_oss(struct sb_card_config *scc, struct sb_module_options *sbmo)
@@ -157,7 +157,7 @@
 	return sb_register_oss(legacy, &sbmo);
 }
 
-#ifdef CONFIG_PNP_CARD
+#ifdef CONFIG_PNP
 
 /* Populate the OSS subsystem structures with information from PnP */
 static void sb_dev2cfg(struct pnp_dev *dev, struct sb_card_config *scc)
@@ -224,7 +224,7 @@
 }
 
 /* Probe callback function for the PnP API */
-static int sb_pnp_probe(struct pnp_card *card, const struct pnp_card_id *card_id)
+static int sb_pnp_probe(struct pnp_card_link *card, const struct pnp_card_id *card_id)
 {
 	struct sb_card_config *scc;
 	struct sb_module_options sbmo = {0}; /* Default to 0 for PnP */
@@ -252,14 +252,14 @@
 	       "dma=%d, dma16=%d\n", scc->conf.io_base, scc->conf.irq,
 	       scc->conf.dma, scc->conf.dma2);
 
-	pnpc_set_drvdata(card, scc);
+	pnp_set_card_drvdata(card, scc);
 
 	return sb_register_oss(scc, &sbmo);
 }
 
-static void sb_pnp_remove(struct pnp_card *card)
+static void sb_pnp_remove(struct pnp_card_link *card)
 {
-	struct sb_card_config *scc = pnpc_get_drvdata(card);
+	struct sb_card_config *scc = pnp_get_card_drvdata(card);
 
 	if(!scc)
 		return;
@@ -269,13 +269,13 @@
 	sb_unload(scc);
 }
 
-static struct pnpc_driver sb_pnp_driver = {
+static struct pnp_card_driver sb_pnp_driver = {
 	.name          = "OSS SndBlstr", /* 16 character limit */
 	.id_table      = sb_pnp_card_table,
 	.probe         = sb_pnp_probe,
 	.remove        = sb_pnp_remove,
 };
-#endif /* CONFIG_PNP_CARD */
+#endif /* CONFIG_PNP */
 
 static int __init sb_init(void)
 {
@@ -293,9 +293,9 @@
 		printk(KERN_ERR "sb: Error: At least io, irq, and dma "\
 		       "must be set for legacy cards.\n");
 
-#ifdef CONFIG_PNP_CARD
+#ifdef CONFIG_PNP
 	if(pnp) {
-		pres = pnpc_register_driver(&sb_pnp_driver);
+		pres = pnp_register_card_driver(&sb_pnp_driver);
 	}
 #endif
 	printk(KERN_INFO "sb: Init: Done\n");
@@ -315,8 +315,8 @@
 		sb_unload(legacy);
 	}
 
-#ifdef CONFIG_PNP_CARD
-	pnpc_unregister_driver(&sb_pnp_driver);
+#ifdef CONFIG_PNP
+	pnp_unregister_card_driver(&sb_pnp_driver);
 #endif
 
 	if (smw_free) {
diff -Nru a/sound/oss/sb_card.h b/sound/oss/sb_card.h
--- a/sound/oss/sb_card.h	Wed Feb 19 09:56:37 2003
+++ b/sound/oss/sb_card.h	Sun Mar  9 15:44:14 2003
@@ -16,7 +16,7 @@
 	int                 mpu;
 };
 
-#ifdef CONFIG_PNP_CARD
+#ifdef CONFIG_PNP
 
 /*
  * SoundBlaster PnP tables and structures.
diff -Nru a/sound/oss/trident.c b/sound/oss/trident.c
--- a/sound/oss/trident.c	Fri Feb 28 17:14:13 2003
+++ b/sound/oss/trident.c	Thu Mar  6 09:38:03 2003
@@ -221,7 +221,7 @@
 #define TRIDENT_STATE_MAGIC	0x63657373 /* "cess" */
 
 #define TRIDENT_DMA_MASK	0x3fffffff /* DMA buffer mask for pci_alloc_consist */
-#define ALI_DMA_MASK		0xffffffff /* ALI Tridents lack the 30-bit limitation */
+#define ALI_DMA_MASK		0x7fffffff /* ALI Tridents have 31-bit DMA. Wow. */
 
 #define NR_HW_CH		32
 
diff -Nru a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
--- a/sound/pci/ac97/ac97_codec.c	Fri Feb 21 18:52:09 2003
+++ b/sound/pci/ac97/ac97_codec.c	Wed Mar  5 21:39:37 2003
@@ -1808,7 +1808,7 @@
  */
 static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem)
 {
-	signed long end_time;
+	unsigned long end_time;
 	end_time = jiffies + timeout;
 	do {
 		unsigned short ext_mid;
@@ -1866,7 +1866,7 @@
 	int err;
 	ac97_t *ac97;
 	char name[64];
-	signed long end_time;
+	unsigned long end_time;
 	static snd_device_ops_t ops = {
 		.dev_free =	snd_ac97_dev_free,
 	};
diff -Nru a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
--- a/sound/pci/intel8x0.c	Sun Feb 16 05:47:43 2003
+++ b/sound/pci/intel8x0.c	Wed Mar  5 21:39:37 2003
@@ -1741,7 +1741,7 @@
 
 static int snd_intel8x0_ich_chip_init(intel8x0_t *chip)
 {
-	signed long end_time;
+	unsigned long end_time;
 	unsigned int cnt, status, nstatus;
 	
 	/* put logic to right state */
diff -Nru a/usr/Makefile b/usr/Makefile
--- a/usr/Makefile	Tue Nov  5 08:08:10 2002
+++ b/usr/Makefile	Fri Mar  7 16:46:05 2003
@@ -1,16 +1,34 @@
 
 obj-y := initramfs_data.o
 
-host-progs := gen_init_cpio
+host-progs  := gen_init_cpio
 
 clean-files := initramfs_data.cpio.gz
 
 LDFLAGS_initramfs_data.o := $(LDFLAGS_BLOB) -r -T
 
-$(obj)/initramfs_data.o: $(src)/initramfs_data.scr $(obj)/initramfs_data.cpio.gz FORCE
+$(obj)/initramfs_data.o: $(src)/initramfs_data.scr \
+			 $(obj)/initramfs_data.cpio.gz FORCE
 	$(call if_changed,ld)
 
-$(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio
-	./$< | gzip -9c > $@
+# initramfs-y are the programs which will be copied into the CPIO
+# archive. Currently, the filenames are hardcoded in gen_init_cpio,
+# but we need the information for the build as well, so it's duplicated
+# here.
 
+# Commented out for now
+# initramfs-y := $(obj)/root/hello
+
+quiet_cmd_cpio = CPIO    $@
+      cmd_cpio = ./$< > $@
+
+$(obj)/initramfs_data.cpio: $(obj)/gen_init_cpio $(initramfs-y) FORCE
+	$(call if_changed,cpio)
+
+targets += $(obj)/initramfs_data.cpio
+
+$(obj)/initramfs_data.cpio.gz: $(obj)/initramfs_data.cpio FORCE
+	$(call if_changed,gzip)
+
+targets += $(obj)/initramfs_data.cpio.gz
 
diff -Nru a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
--- a/usr/gen_init_cpio.c	Fri Nov  1 09:00:19 2002
+++ b/usr/gen_init_cpio.c	Fri Mar  7 16:36:36 2003
@@ -5,10 +5,28 @@
 #include <string.h>
 #include <unistd.h>
 #include <time.h>
+#include <fcntl.h>
 
 static unsigned int offset;
 static unsigned int ino = 721;
 
+static void push_string(const char *name)
+{
+	unsigned int name_len = strlen(name) + 1;
+
+	fputs(name, stdout);
+	putchar(0);
+	offset += name_len;
+}
+
+static void push_pad (void)
+{
+	while (offset & 3) {
+		putchar(0);
+		offset++;
+	}
+}
+
 static void push_rest(const char *name)
 {
 	unsigned int name_len = strlen(name) + 1;
@@ -118,6 +136,78 @@
 		0);			/* chksum */
 	push_hdr(s);
 	push_rest(name);
+}
+
+/* Not marked static to keep the compiler quiet, as no one uses this yet... */
+void cpio_mkfile(const char *filename, const char *location,
+			unsigned int mode, uid_t uid, gid_t gid)
+{
+	char s[256];
+	char *filebuf;
+	struct stat buf;
+	int file;
+	int retval;
+	int i;
+
+	mode |= S_IFREG;
+
+	retval = stat (filename, &buf);
+	if (retval) {
+		fprintf (stderr, "Filename %s could not be located\n", filename);
+		goto error;
+	}
+
+	file = open (filename, O_RDONLY);
+	if (file < 0) {
+		fprintf (stderr, "Filename %s could not be opened for reading\n", filename);
+		goto error;
+	}
+
+	filebuf = malloc(buf.st_size);
+	if (!filebuf) {
+		fprintf (stderr, "out of memory\n");
+		goto error_close;
+	}
+
+	retval = read (file, filebuf, buf.st_size);
+	if (retval < 0) {
+		fprintf (stderr, "Can not read %s file\n", filename);
+		goto error_free;
+	}
+
+	sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
+	       "%08X%08X%08X%08X%08X%08X%08X",
+		"070701",		/* magic */
+		ino++,			/* ino */
+		mode,			/* mode */
+		(long) uid,		/* uid */
+		(long) gid,		/* gid */
+		1,			/* nlink */
+		(long) buf.st_mtime,	/* mtime */
+		(int) buf.st_size,	/* filesize */
+		3,			/* major */
+		1,			/* minor */
+		0,			/* rmajor */
+		0,			/* rminor */
+		strlen(location) + 1,	/* namesize */
+		0);			/* chksum */
+	push_hdr(s);
+	push_string(location);
+	push_pad();
+
+	for (i = 0; i < buf.st_size; ++i)
+		fputc(filebuf[i], stdout);
+	close(file);
+	free(filebuf);
+	push_pad();
+	return;
+	
+error_free:
+	free(filebuf);
+error_close:
+	close(file);
+error:
+	exit(-1);
 }
 
 int main (int argc, char *argv[])
