## Automatically generated incremental diff
## From:   linux-2.5.69-bk6
## To:     linux-2.5.69-bk7
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.5.69-bk6/Documentation/BK-usage/bk-kernel-howto.txt linux-2.5.69-bk7/Documentation/BK-usage/bk-kernel-howto.txt
--- linux-2.5.69-bk6/Documentation/BK-usage/bk-kernel-howto.txt	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk7/Documentation/BK-usage/bk-kernel-howto.txt	2003-05-12 04:43:29.000000000 -0700
@@ -273,3 +273,11 @@
 A tag is just an alias for a specific changeset... and since changesets
 are ordered, a tag is thus a marker for a specific point in time (or
 specific state of the tree).
+
+
+3) Is there an easy way to generate One Big Patch versus mainline,
+   for my long-lived kernel branch?
+A. Yes.  This requires BK 3.x, though.
+
+	bk export -tpatch -r`bk repogca bk://linux.bkbits.net/linux-2.5`,+
+
diff -urN linux-2.5.69-bk6/Makefile linux-2.5.69-bk7/Makefile
--- linux-2.5.69-bk6/Makefile	2003-05-12 04:43:25.000000000 -0700
+++ linux-2.5.69-bk7/Makefile	2003-05-12 04:43:29.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 69
-EXTRAVERSION = -bk6
+EXTRAVERSION = -bk7
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
diff -urN linux-2.5.69-bk6/arch/alpha/kernel/sys_titan.c linux-2.5.69-bk7/arch/alpha/kernel/sys_titan.c
--- linux-2.5.69-bk6/arch/alpha/kernel/sys_titan.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk7/arch/alpha/kernel/sys_titan.c	2003-05-12 04:43:29.000000000 -0700
@@ -204,13 +204,14 @@
        .set_affinity   = titan_set_irq_affinity,
 };
 
-static void
+static irqreturn_t
 titan_intr_nop(int irq, void *dev_id, struct pt_regs *regs)                    
 {
       /*
        * This is a NOP interrupt handler for the purposes of
        * event counting -- just return.
        */                                                                     
+       return IRQ_HANDLED;
 }
 
 static void __init
diff -urN linux-2.5.69-bk6/arch/i386/kernel/Makefile linux-2.5.69-bk7/arch/i386/kernel/Makefile
--- linux-2.5.69-bk6/arch/i386/kernel/Makefile	2003-05-04 16:53:03.000000000 -0700
+++ linux-2.5.69-bk7/arch/i386/kernel/Makefile	2003-05-12 04:43:29.000000000 -0700
@@ -17,7 +17,7 @@
 obj-$(CONFIG_X86_MSR)		+= msr.o
 obj-$(CONFIG_X86_CPUID)		+= cpuid.o
 obj-$(CONFIG_MICROCODE)		+= microcode.o
-obj-$(CONFIG_APM)		+= apm.o
+obj-$(CONFIG_APM)		+= apm.o suspend.o
 obj-$(CONFIG_X86_SMP)		+= smp.o smpboot.o
 obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline.o
 obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
diff -urN linux-2.5.69-bk6/arch/i386/kernel/apm.c linux-2.5.69-bk7/arch/i386/kernel/apm.c
--- linux-2.5.69-bk6/arch/i386/kernel/apm.c	2003-05-04 16:53:00.000000000 -0700
+++ linux-2.5.69-bk7/arch/i386/kernel/apm.c	2003-05-12 04:43:29.000000000 -0700
@@ -226,6 +226,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/desc.h>
+#include <asm/suspend.h>
 
 #include "io_ports.h"
 
@@ -1212,7 +1213,9 @@
 	spin_unlock(&i8253_lock);
 	write_sequnlock_irq(&xtime_lock);
 
+	save_processor_state();
 	err = set_system_power_state(APM_STATE_SUSPEND);
+	restore_processor_state();
 
 	write_seqlock_irq(&xtime_lock);
 	spin_lock(&i8253_lock);
diff -urN linux-2.5.69-bk6/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c linux-2.5.69-bk7/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
--- linux-2.5.69-bk6/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk7/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c	2003-05-12 04:43:29.000000000 -0700
@@ -147,7 +147,7 @@
 #ifdef SUSPMOD_DEBUG
 #define dprintk(msg...) printk(KERN_DEBUG "cpufreq:" msg)
 #else
-#define dprintk(msg...) do { } while(0);
+#define dprintk(msg...) do { } while(0)
 #endif
 
 /**
diff -urN linux-2.5.69-bk6/arch/i386/kernel/cpu/cpufreq/longhaul.c linux-2.5.69-bk7/arch/i386/kernel/cpu/cpufreq/longhaul.c
--- linux-2.5.69-bk6/arch/i386/kernel/cpu/cpufreq/longhaul.c	2003-05-04 16:53:00.000000000 -0700
+++ linux-2.5.69-bk7/arch/i386/kernel/cpu/cpufreq/longhaul.c	2003-05-12 04:43:29.000000000 -0700
@@ -37,7 +37,7 @@
 #ifdef DEBUG
 #define dprintk(msg...) printk(msg)
 #else
-#define dprintk(msg...) do { } while(0);
+#define dprintk(msg...) do { } while(0)
 #endif
 
 static unsigned int numscales=16, numvscales;
diff -urN linux-2.5.69-bk6/arch/i386/kernel/cpu/cpufreq/powernow-k7.c linux-2.5.69-bk7/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
--- linux-2.5.69-bk6/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk7/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	2003-05-12 04:43:29.000000000 -0700
@@ -32,7 +32,7 @@
 #ifdef DEBUG
 #define dprintk(msg...) printk(msg)
 #else
-#define dprintk(msg...) do { } while(0);
+#define dprintk(msg...) do { } while(0)
 #endif
 
 #define PFX "powernow: "
@@ -89,7 +89,7 @@
 	rdmsr (msr, l__, h__);	\
 	val = l__;	\
 	val |= ((u64)h__<<32);	\
-} while(0);
+} while(0)
 #endif
 
 #ifndef wrmsrl
@@ -236,20 +236,24 @@
 
 	if (have_a0 == 1)	/* A0 errata 5 */
 		__asm__("\tcli\n");
-	rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
-	fidvidctl.bits.SGTC = latency;	/* Stop grant timeout counter */
 
-	fidvidctl.bits.FID = fid;
-	fidvidctl.bits.FIDC = 1;
+	/* First change the frequency. */
+	if (fidvidctl.bits.FID != fid) {
+		rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
+		fidvidctl.bits.SGTC = latency;	/* Stop grant timeout counter */
+		fidvidctl.bits.FID = fid;
+		fidvidctl.bits.FIDC = 1;
+		wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
+	}
 
-	/* Set the voltage lazily. Ie, only do voltage transition
-	   if its changed since last time (Some speeds have the same voltage) */
+	/* Now change voltage. */
 	if (fidvidctl.bits.VID != vid) {
+		rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
 		fidvidctl.bits.VID = vid;
 		fidvidctl.bits.VIDC = 1;
+		wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
 	}
 
-	wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
 	if (have_a0 == 1)
 		__asm__("\tsti\n");
 
@@ -386,6 +390,10 @@
 
 static int __init powernow_init (void)
 {
+	if (dmi_broken & BROKEN_CPUFREQ) {
+		printk (KERN_INFO PFX "Disabled at boot time by DMI,\n");
+		return -ENODEV;
+	}
 	if (check_powernow()==0)
 		return -ENODEV;
 	return cpufreq_register_driver(&powernow_driver);
diff -urN linux-2.5.69-bk6/arch/i386/kernel/dmi_scan.c linux-2.5.69-bk7/arch/i386/kernel/dmi_scan.c
--- linux-2.5.69-bk6/arch/i386/kernel/dmi_scan.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk7/arch/i386/kernel/dmi_scan.c	2003-05-12 04:43:29.000000000 -0700
@@ -511,6 +511,14 @@
 	return 0;
 }
 
+static __init int acer_cpufreq_pst(struct dmi_blacklist *d)
+{
+	printk(KERN_WARNING "%s laptop with broken PST tables in BIOS detected.\n", d->ident);
+	printk(KERN_WARNING "You need to downgrade to 3A21 (09/09/2002), or try a newer BIOS than 3A71 (01/20/2003)\n");
+	printk(KERN_WARNING "cpufreq scaling has been disabled as a result of this.\n");
+	dmi_broken |= BROKEN_CPUFREQ;
+	return 0;
+}
 
 
 /*
@@ -825,6 +833,17 @@
 			NO_MATCH, NO_MATCH, NO_MATCH
 			} },
 
+	/*
+	 * Some Athlon laptops have really fucked PST tables.
+	 * A BIOS update is all that can save them.
+	 * Mention this, and disable cpufreq.
+	 */
+	{ acer_cpufreq_pst, "Acer Aspire", {
+			MATCH(DMI_SYS_VENDOR, "Insyde Software"),
+			MATCH(DMI_BIOS_VERSION, "3A71"),
+			NO_MATCH, NO_MATCH, NO_MATCH
+			} },
+
 	{ NULL, }
 };
 	
diff -urN linux-2.5.69-bk6/arch/i386/kernel/suspend.c linux-2.5.69-bk7/arch/i386/kernel/suspend.c
--- linux-2.5.69-bk6/arch/i386/kernel/suspend.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk7/arch/i386/kernel/suspend.c	2003-05-12 04:43:29.000000000 -0700
@@ -27,9 +27,7 @@
 #include <asm/tlbflush.h>
 
 static struct saved_context saved_context;
-unsigned long saved_context_eax, saved_context_ebx, saved_context_ecx, saved_context_edx;
-unsigned long saved_context_esp, saved_context_ebp, saved_context_esi, saved_context_edi;
-unsigned long saved_context_eflags;
+static void fix_processor_context(void);
 
 extern void enable_sep_cpu(void *);
 
@@ -107,7 +105,7 @@
 	do_fpu_end();
 }
 
-void fix_processor_context(void)
+static void fix_processor_context(void)
 {
 	int cpu = smp_processor_id();
 	struct tss_struct * t = init_tss + cpu;
diff -urN linux-2.5.69-bk6/arch/i386/kernel/suspend_asm.S linux-2.5.69-bk7/arch/i386/kernel/suspend_asm.S
--- linux-2.5.69-bk6/arch/i386/kernel/suspend_asm.S	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk7/arch/i386/kernel/suspend_asm.S	2003-05-12 04:43:29.000000000 -0700
@@ -6,6 +6,28 @@
 #include <asm/segment.h>
 #include <asm/page.h>
 
+	.data
+saved_context_eax:
+	.long	0
+saved_context_ebx:
+	.long	0
+saved_context_ecx:
+	.long	0
+saved_context_edx:
+	.long	0
+saved_context_esp:
+	.long	0
+saved_context_ebp:
+	.long	0
+saved_context_esi:
+	.long	0
+saved_context_edi:
+	.long	0
+saved_context_eflags:
+	.long	0
+
+	.text
+
 ENTRY(do_magic)
 	pushl %ebx
 	cmpl $0,8(%esp)
diff -urN linux-2.5.69-bk6/arch/ia64/Kconfig linux-2.5.69-bk7/arch/ia64/Kconfig
--- linux-2.5.69-bk6/arch/ia64/Kconfig	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/Kconfig	2003-05-12 04:43:29.000000000 -0700
@@ -381,6 +381,10 @@
 	depends on MCKINLEY
 	bool "4GB"
 
+config HUGETLB_PAGE_SIZE_1GB
+	depends on MCKINLEY
+	bool "1GB"
+
 config HUGETLB_PAGE_SIZE_256MB
 	bool "256MB"
 
diff -urN linux-2.5.69-bk6/arch/ia64/Makefile linux-2.5.69-bk7/arch/ia64/Makefile
--- linux-2.5.69-bk6/arch/ia64/Makefile	2003-05-04 16:52:59.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/Makefile	2003-05-12 04:43:29.000000000 -0700
@@ -23,6 +23,7 @@
 CFLAGS_KERNEL	:= -mconstant-gp
 
 GCC_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.')
+GCC_MINOR_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f2 -d'.')
 
 GAS_STATUS=$(shell arch/ia64/scripts/check-gas $(CC) $(OBJDUMP))
 
@@ -35,7 +36,14 @@
 endif
 
 ifneq ($(GCC_VERSION),2)
-	cflags-y += -frename-registers --param max-inline-insns=5000
+	cflags-$(CONFIG_ITANIUM) += -frename-registers
+endif
+
+ifeq ($(GCC_VERSION),3)
+ ifeq ($(GCC_MINOR_VERSION),4)
+	cflags-$(CONFIG_ITANIUM) += -mtune=merced
+	cflags-$(CONFIG_MCKINLEY) += -mtune=mckinley
+ endif
 endif
 
 cflags-$(CONFIG_ITANIUM_BSTEP_SPECIFIC)	+= -mb-step
@@ -48,14 +56,14 @@
 core-y				+= arch/ia64/kernel/ arch/ia64/mm/
 core-$(CONFIG_IA32_SUPPORT)	+= arch/ia64/ia32/
 core-$(CONFIG_IA64_DIG) 	+= arch/ia64/dig/
-core-$(CONFIG_IA64_GENERIC) 	+= arch/ia64/dig/ arch/ia64/hp/common/ arch/ia64/hp/zx1/ \
-				   arch/ia64/hp/sim/
+core-$(CONFIG_IA64_GENERIC) 	+= arch/ia64/dig/
 core-$(CONFIG_IA64_HP_ZX1)	+= arch/ia64/dig/
 core-$(CONFIG_IA64_SGI_SN)	+= arch/ia64/sn/
 
 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_GENERIC)	+= arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/
 
 boot := arch/ia64/boot
 tools := arch/ia64/tools
diff -urN linux-2.5.69-bk6/arch/ia64/dig/machvec.c linux-2.5.69-bk7/arch/ia64/dig/machvec.c
--- linux-2.5.69-bk6/arch/ia64/dig/machvec.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/dig/machvec.c	2003-05-12 04:43:29.000000000 -0700
@@ -1,2 +1,3 @@
-#define MACHVEC_PLATFORM_NAME	dig
+#define MACHVEC_PLATFORM_NAME		dig
+#define MACHVEC_PLATFORM_HEADER		<asm/machvec_dig.h>
 #include <asm/machvec_init.h>
diff -urN linux-2.5.69-bk6/arch/ia64/hp/common/sba_iommu.c linux-2.5.69-bk7/arch/ia64/hp/common/sba_iommu.c
--- linux-2.5.69-bk6/arch/ia64/hp/common/sba_iommu.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/hp/common/sba_iommu.c	2003-05-12 04:43:29.000000000 -0700
@@ -1,9 +1,9 @@
 /*
 **  IA64 System Bus Adapter (SBA) I/O MMU manager
 **
-**	(c) Copyright 2002 Alex Williamson
-**	(c) Copyright 2002 Grant Grundler
-**	(c) Copyright 2002 Hewlett-Packard Company
+**	(c) Copyright 2002-2003 Alex Williamson
+**	(c) Copyright 2002-2003 Grant Grundler
+**	(c) Copyright 2002-2003 Hewlett-Packard Company
 **
 **	Portions (c) 2000 Grant Grundler (from parisc I/O MMU code)
 **	Portions (c) 1999 Dave S. Miller (from sparc64 I/O MMU code)
@@ -30,17 +30,39 @@
 #include <linux/string.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/acpi.h>
 #include <linux/efi.h>
 
 #include <asm/delay.h>		/* ia64_get_itc() */
 #include <asm/io.h>
 #include <asm/page.h>		/* PAGE_OFFSET */
+#include <asm/dma.h>
+#include <asm/system.h>		/* wmb() */
 
+#include <asm/acpi-ext.h>
 
-#define DRIVER_NAME "SBA"
+#define PFX "IOC: "
 
+/*
+** This option allows cards capable of 64bit DMA to bypass the IOMMU.  If
+** not defined, all DMA will be 32bit and go through the TLB.
+*/
 #define ALLOW_IOV_BYPASS
+
+/*
+** If a device prefetches beyond the end of a valid pdir entry, it will cause
+** a hard failure, ie. MCA.  Version 3.0 and later of the zx1 LBA should
+** disconnect on 4k boundaries and prevent such issues.  If the device is
+** particularly agressive, this option will keep the entire pdir valid such
+** that prefetching will hit a valid address.  This could severely impact
+** error containment, and is therefore off by default.  The page that is
+** used for spill-over is poisoned, so that should help debugging somewhat.
+*/
+#undef FULL_VALID_PDIR
+
 #define ENABLE_MARK_CLEAN
+
 /*
 ** The number of debug flags is a clue - this code is fragile.
 */
@@ -52,6 +74,10 @@
 #undef DEBUG_LARGE_SG_ENTRIES
 #undef DEBUG_BYPASS
 
+#if defined(FULL_VALID_PDIR) && defined(ASSERT_PDIR_SANITY)
+#error FULL_VALID_PDIR and ASSERT_PDIR_SANITY are mutually exclusive
+#endif
+
 #define SBA_INLINE	__inline__
 /* #define SBA_INLINE */
 
@@ -96,12 +122,8 @@
 #define ASSERT(expr)
 #endif
 
-#define KB(x) ((x) * 1024)
-#define MB(x) (KB (KB (x)))
-#define GB(x) (MB (KB (x)))
-
 /*
-** The number of pdir entries to "free" before issueing
+** The number of pdir entries to "free" before issuing
 ** a read to PCOM register to flush out PCOM writes.
 ** Interacts with allocation granularity (ie 4 or 8 entries
 ** allocated and free'd/purged at a time might make this
@@ -109,30 +131,24 @@
 */
 #define DELAYED_RESOURCE_CNT	16
 
-#define DEFAULT_DMA_HINT_REG(d)	0
-
-#define ZX1_FUNC_ID_VALUE    ((PCI_DEVICE_ID_HP_ZX1_SBA << 16) | PCI_VENDOR_ID_HP)
-#define ZX1_MC_ID    ((PCI_DEVICE_ID_HP_ZX1_MC << 16) | PCI_VENDOR_ID_HP)
+#define DEFAULT_DMA_HINT_REG	0
 
-#define SBA_FUNC_ID	0x0000	/* function id */
-#define SBA_FCLASS	0x0008	/* function class, bist, header, rev... */
+#define ZX1_IOC_ID	((PCI_DEVICE_ID_HP_ZX1_IOC << 16) | PCI_VENDOR_ID_HP)
+#define REO_IOC_ID	((PCI_DEVICE_ID_HP_REO_IOC << 16) | PCI_VENDOR_ID_HP)
+#define SX1000_IOC_ID	((PCI_DEVICE_ID_HP_SX1000_IOC << 16) | PCI_VENDOR_ID_HP)
 
-#define SBA_FUNC_SIZE	0x10000   /* SBA configuration function reg set */
-
-unsigned int __initdata zx1_func_offsets[] = {0x1000, 0x4000, 0x8000,
-                                              0x9000, 0xa000, -1};
-
-#define SBA_IOC_OFFSET	0x1000
-
-#define MAX_IOC		1	/* we only have 1 for now*/
+#define ZX1_IOC_OFFSET	0x1000	/* ACPI reports SBA, we want IOC */
 
+#define IOC_FUNC_ID	0x000
+#define IOC_FCLASS	0x008	/* function class, bist, header, rev... */
 #define IOC_IBASE	0x300	/* IO TLB */
 #define IOC_IMASK	0x308
 #define IOC_PCOM	0x310
 #define IOC_TCNFG	0x318
 #define IOC_PDIR_BASE	0x320
 
-#define IOC_IOVA_SPACE_BASE	0x40000000 /* IOVA ranges start at 1GB */
+/* AGP GART driver looks for this */
+#define ZX1_SBA_IOMMU_COOKIE	0x0000badbadc0ffeeUL
 
 /*
 ** IOC supports 4/8/16/64KB page sizes (see TCNFG register)
@@ -152,7 +168,7 @@
 #define IOVP_MASK	PAGE_MASK
 
 struct ioc {
-	unsigned long	ioc_hpa;	/* I/O MMU base address */
+	void		*ioc_hpa;	/* I/O MMU base address */
 	char		*res_map;	/* resource map, bit == pdir entry */
 	u64		*pdir_base;	/* physical base address */
 	unsigned long	ibase;		/* pdir IOV Space base */
@@ -193,37 +209,37 @@
 #endif
 #endif
 
-	/* STUFF We don't need in performance path */
+	/* Stuff we don't need in performance path */
+	struct ioc	*next;		/* list of IOC's in system */
+	acpi_handle	handle;		/* for multiple IOC's */
+	const char 	*name;
+	unsigned int	func_id;
+	unsigned int	rev;		/* HW revision of chip */
+	u32		iov_size;
 	unsigned int	pdir_size;	/* in bytes, determined by IOV Space size */
+	struct pci_dev	*sac_only_dev;
 };
 
-struct sba_device {
-	struct sba_device	*next;	/* list of SBA's in system */
-	const char 		*name;
-	unsigned long		sba_hpa; /* base address */
-	spinlock_t		sba_lock;
-	unsigned int		flags;  /* state/functionality enabled */
-	unsigned int		hw_rev;  /* HW revision of chip */
-
-	unsigned int		num_ioc;  /* number of on-board IOC's */
-	struct ioc		ioc[MAX_IOC];
-};
+static struct ioc *ioc_list;
+static int reserve_sba_gart = 1;
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#define sba_sg_address(sg)	(page_address((sg)->page) + (sg)->offset)
+#else
+#define sba_sg_address(sg)	((sg)->address ? (sg)->address : \
+                                  page_address((sg)->page) + (sg)->offset)
+#endif
 
-static struct sba_device *sba_list;
-static int sba_count;
-static int reserve_sba_gart = 1;
-static struct pci_dev sac_only_dev;
+#ifdef FULL_VALID_PDIR
+static u64 prefetch_spill_page;
+#endif
 
-#define sba_sg_address(sg) (page_address((sg)->page) + (sg)->offset)
-#define sba_sg_len(sg) (sg->length)
-#define sba_sg_iova(sg) (sg->dma_address)
-#define sba_sg_iova_len(sg) (sg->dma_length)
-
-/* REVISIT - fix me for multiple SBAs/IOCs */
-#define GET_IOC(dev) (sba_list->ioc)
-#define SBA_SET_AGP(sba_dev) (sba_dev->flags |= 0x1)
-#define SBA_GET_AGP(sba_dev) (sba_dev->flags & 0x1)
+#ifdef CONFIG_PCI
+# define GET_IOC(dev)	(((dev)->bus == &pci_bus_type)						\
+			 ? ((struct ioc *) PCI_CONTROLLER(to_pci_dev(dev))->iommu) : NULL)
+#else
+# define GET_IOC(dev)	NULL
+#endif
 
 /*
 ** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up
@@ -232,10 +248,7 @@
 ** rather than the HW. I/O MMU allocation alogorithms can be
 ** faster with smaller size is (to some degree).
 */
-#define DMA_CHUNK_SIZE  (BITS_PER_LONG*IOVP_SIZE)
-
-/* Looks nice and keeps the compiler happy */
-#define SBA_DEV(d) ((struct sba_device *) (d))
+#define DMA_CHUNK_SIZE  (BITS_PER_LONG*PAGE_SIZE)
 
 #define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1))
 
@@ -255,7 +268,7 @@
  * sba_dump_tlb - debugging only - print IOMMU operating parameters
  * @hpa: base address of the IOMMU
  *
- * Print the size/location of the IO MMU Pdir.
+ * Print the size/location of the IO MMU PDIR.
  */
 static void
 sba_dump_tlb(char *hpa)
@@ -273,19 +286,19 @@
 #ifdef ASSERT_PDIR_SANITY
 
 /**
- * sba_dump_pdir_entry - debugging only - print one IOMMU Pdir entry
+ * sba_dump_pdir_entry - debugging only - print one IOMMU PDIR entry
  * @ioc: IO MMU structure which owns the pdir we are interested in.
  * @msg: text to print ont the output line.
  * @pide: pdir index.
  *
- * Print one entry of the IO MMU Pdir in human readable form.
+ * Print one entry of the IO MMU PDIR in human readable form.
  */
 static void
 sba_dump_pdir_entry(struct ioc *ioc, char *msg, uint pide)
 {
 	/* start printing from lowest pde in rval */
-	u64 *ptr = &(ioc->pdir_base[pide  & ~(BITS_PER_LONG - 1)]);
-	unsigned long *rptr = (unsigned long *) &(ioc->res_map[(pide >>3) & ~(sizeof(unsigned long) - 1)]);
+	u64 *ptr = &ioc->pdir_base[pide  & ~(BITS_PER_LONG - 1)];
+	unsigned long *rptr = (unsigned long *) &ioc->res_map[(pide >>3) & -sizeof(unsigned long)];
 	uint rcnt;
 
 	printk(KERN_DEBUG "SBA: %s rp %p bit %d rval 0x%lx\n",
@@ -296,7 +309,7 @@
 		printk(KERN_DEBUG "%s %2d %p %016Lx\n",
 		       (rcnt == (pide & (BITS_PER_LONG - 1)))
 		       ? "    -->" : "       ",
-		       rcnt, ptr, *ptr );
+		       rcnt, ptr, (unsigned long long) *ptr );
 		rcnt++;
 		ptr++;
 	}
@@ -359,17 +372,18 @@
  * print the SG list so we can verify it's correct by hand.
  */
 static void
-sba_dump_sg(struct ioc *ioc, struct scatterlist *startsg, int nents)
+sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
 {
 	while (nents-- > 0) {
 		printk(KERN_DEBUG " %d : DMA %08lx/%05x CPU %p\n", nents,
-		       (unsigned long) sba_sg_iova(startsg), sba_sg_iova_len(startsg),
+		       startsg->dma_address, startsg->dma_length,
 		       sba_sg_address(startsg));
 		startsg++;
 	}
 }
+
 static void
-sba_check_sg(struct ioc *ioc, struct scatterlist *startsg, int nents)
+sba_check_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
 {
 	struct scatterlist *the_sg = startsg;
 	int the_nents = nents;
@@ -398,9 +412,11 @@
 #define PAGES_PER_RANGE 1	/* could increase this to 4 or 8 if needed */
 
 /* Convert from IOVP to IOVA and vice versa. */
-#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((ioc->ibase) | (iovp) | (offset) | ((hint_reg)<<(ioc->hint_shift_pdir)))
+#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((ioc->ibase) | (iovp) | (offset) |		\
+					    ((hint_reg)<<(ioc->hint_shift_pdir)))
 #define SBA_IOVP(ioc,iova) (((iova) & ioc->hint_mask_pdir) & ~(ioc->ibase))
 
+/* FIXME : review these macros to verify correctness and usage */
 #define PDIR_INDEX(iovp)   ((iovp)>>IOVP_SHIFT)
 
 #define RESMAP_MASK(n)    ~(~0UL << (n))
@@ -408,7 +424,7 @@
 
 
 /**
- * sba_search_bitmap - find free space in IO Pdir resource bitmap
+ * sba_search_bitmap - find free space in IO PDIR resource bitmap
  * @ioc: IO MMU structure which owns the pdir we are interested in.
  * @bits_wanted: number of entries we need.
  *
@@ -445,7 +461,7 @@
 		** We need the alignment to invalidate I/O TLB using
 		** SBA HW features in the unmap path.
 		*/
-		unsigned long o = 1UL << get_order(bits_wanted << IOVP_SHIFT);
+		unsigned long o = 1 << get_order(bits_wanted << PAGE_SHIFT);
 		uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o);
 		unsigned long mask;
 
@@ -491,7 +507,7 @@
 
 
 /**
- * sba_alloc_range - find free bits and mark them in IO Pdir resource bitmap
+ * sba_alloc_range - find free bits and mark them in IO PDIR resource bitmap
  * @ioc: IO MMU structure which owns the pdir we are interested in.
  * @size: number of bytes to create a mapping for
  *
@@ -520,7 +536,8 @@
 	if (pide >= (ioc->res_size << 3)) {
 		pide = sba_search_bitmap(ioc, pages_needed);
 		if (pide >= (ioc->res_size << 3))
-			panic(__FILE__ ": I/O MMU @ %lx is out of mapping resources\n", ioc->ioc_hpa);
+			panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n",
+			      ioc->ioc_hpa);
 	}
 
 #ifdef ASSERT_PDIR_SANITY
@@ -553,7 +570,7 @@
 
 
 /**
- * sba_free_range - unmark bits in IO Pdir resource bitmap
+ * sba_free_range - unmark bits in IO PDIR resource bitmap
  * @ioc: IO MMU structure which owns the pdir we are interested in.
  * @iova: IO virtual address which was previously allocated.
  * @size: number of bytes to create a mapping for
@@ -600,14 +617,14 @@
 
 
 /**
- * sba_io_pdir_entry - fill in one IO Pdir entry
- * @pdir_ptr:  pointer to IO Pdir entry
- * @phys_page: phys CPU address of page to map
+ * sba_io_pdir_entry - fill in one IO PDIR entry
+ * @pdir_ptr:  pointer to IO PDIR entry
+ * @vba: Virtual CPU address of buffer to map
  *
  * SBA Mapping Routine
  *
- * Given a physical address (phys_page, arg1) sba_io_pdir_entry()
- * loads the I/O Pdir entry pointed to by pdir_ptr (arg0).
+ * Given a virtual address (vba, arg1) sba_io_pdir_entry()
+ * loads the I/O PDIR entry pointed to by pdir_ptr (arg0).
  * Each IO Pdir entry consists of 8 bytes as shown below
  * (LSB == bit 0):
  *
@@ -619,12 +636,21 @@
  *  V  == Valid Bit
  *  U  == Unused
  * PPN == Physical Page Number
+ *
+ * The physical address fields are filled with the results of virt_to_phys()
+ * on the vba.
  */
 
-#define SBA_VALID_MASK	0x80000000000000FFULL
-#define sba_io_pdir_entry(pdir_ptr, phys_page) *pdir_ptr = (phys_page | SBA_VALID_MASK)
-#define sba_io_page(pdir_ptr) (*pdir_ptr & ~SBA_VALID_MASK)
-
+#if 1
+#define sba_io_pdir_entry(pdir_ptr, vba) *pdir_ptr = ((vba & ~0xE000000000000FFFULL)	\
+						      | 0x8000000000000000ULL)
+#else
+void SBA_INLINE
+sba_io_pdir_entry(u64 *pdir_ptr, unsigned long vba)
+{
+	*pdir_ptr = ((vba & ~0xE000000000000FFFULL) | 0x80000000000000FFULL);
+}
+#endif
 
 #ifdef ENABLE_MARK_CLEAN
 /**
@@ -640,7 +666,7 @@
 	pg_addr = PAGE_ALIGN((unsigned long) addr);
 	end = (unsigned long) addr + size;
 	while (pg_addr + PAGE_SIZE <= end) {
-		struct page *page = virt_to_page(pg_addr);
+		struct page *page = virt_to_page((void *)pg_addr);
 		set_bit(PG_arch_1, &page->flags);
 		pg_addr += PAGE_SIZE;
 	}
@@ -648,12 +674,12 @@
 #endif
 
 /**
- * sba_mark_invalid - invalidate one or more IO Pdir entries
+ * sba_mark_invalid - invalidate one or more IO PDIR entries
  * @ioc: IO MMU structure which owns the pdir we are interested in.
  * @iova:  IO Virtual Address mapped earlier
  * @byte_cnt:  number of bytes this mapping covers.
  *
- * Marking the IO Pdir entry(ies) as Invalid and invalidate
+ * Marking the IO PDIR entry(ies) as Invalid and invalidate
  * corresponding IO TLB entry. The PCOM (Purge Command Register)
  * is to purge stale entries in the IO TLB when unmapping entries.
  *
@@ -687,15 +713,24 @@
 
 		iovp |= IOVP_SHIFT;     /* set "size" field for PCOM */
 
+#ifndef FULL_VALID_PDIR
 		/*
-		** clear I/O Pdir entry "valid" bit
+		** clear I/O PDIR entry "valid" bit
 		** Do NOT clear the rest - save it for debugging.
 		** We should only clear bits that have previously
 		** been enabled.
 		*/
-		ioc->pdir_base[off] &= ~SBA_VALID_MASK;
+		ioc->pdir_base[off] &= ~(0x80000000000000FFULL);
+#else
+		/*
+  		** If we want to maintain the PDIR as valid, put in
+		** the spill page so devices prefetching won't
+		** cause a hard fail.
+		*/
+		ioc->pdir_base[off] = (0x80000000000000FFULL | prefetch_spill_page);
+#endif
 	} else {
-		u32 t = get_order(byte_cnt) + IOVP_SHIFT;
+		u32 t = get_order(byte_cnt) + PAGE_SHIFT;
 
 		iovp |= t;
 		ASSERT(t <= 31);   /* 2GB! Max value of "size" field */
@@ -703,14 +738,18 @@
 		do {
 			/* verify this pdir entry is enabled */
 			ASSERT(ioc->pdir_base[off]  >> 63);
+#ifndef FULL_VALID_PDIR
 			/* clear I/O Pdir entry "valid" bit first */
-			ioc->pdir_base[off] &= ~SBA_VALID_MASK;
+			ioc->pdir_base[off] &= ~(0x80000000000000FFULL);
+#else
+			ioc->pdir_base[off] = (0x80000000000000FFULL | prefetch_spill_page);
+#endif
 			off++;
 			byte_cnt -= IOVP_SIZE;
 		} while (byte_cnt > 0);
 	}
 
-	WRITE_REG(iovp, ioc->ioc_hpa+IOC_PCOM);
+	WRITE_REG(iovp | ioc->ibase, ioc->ioc_hpa+IOC_PCOM);
 }
 
 /**
@@ -718,26 +757,23 @@
  * @dev: instance of PCI owned by the driver that's asking.
  * @addr:  driver buffer to map.
  * @size:  number of bytes to map in driver buffer.
- * @direction:  R/W or both.
+ * @dir:  R/W or both.
  *
  * See Documentation/DMA-mapping.txt
  */
 dma_addr_t
-sba_map_single(struct pci_dev *dev, void *addr, size_t size, int direction)
+sba_map_single(struct device *dev, void *addr, size_t size, int dir)
 {
 	struct ioc *ioc;
-	unsigned long flags; 
+	unsigned long flags;
 	dma_addr_t iovp;
 	dma_addr_t offset;
 	u64 *pdir_start;
 	int pide;
 #ifdef ALLOW_IOV_BYPASS
-	unsigned long phys_addr = virt_to_phys(addr);
+	unsigned long pci_addr = virt_to_phys(addr);
 #endif
 
-	if (!sba_list)
-		panic("sba_map_single: no SBA found!\n");
-
 	ioc = GET_IOC(dev);
 	ASSERT(ioc);
 
@@ -745,7 +781,7 @@
 	/*
  	** Check if the PCI device can DMA to ptr... if so, just return ptr
  	*/
-	if ((phys_addr & ~dev->dma_mask) == 0) {
+	if (dev && dev->dma_mask && (pci_addr & ~*dev->dma_mask) == 0) {
 		/*
  		** Device is bit capable of DMA'ing to the buffer...
 		** just return the PCI address of ptr
@@ -756,8 +792,8 @@
 		spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif
 		DBG_BYPASS("sba_map_single() bypass mask/addr: 0x%lx/0x%lx\n",
-		           dev->dma_mask, phys_addr);
-		return phys_addr;
+		           *dev->dma_mask, pci_addr);
+		return pci_addr;
 	}
 #endif
 
@@ -790,8 +826,7 @@
 
 	while (size > 0) {
 		ASSERT(((u8 *)pdir_start)[7] == 0); /* verify availability */
-
-		sba_io_pdir_entry(pdir_start, virt_to_phys(addr));
+		sba_io_pdir_entry(pdir_start, (unsigned long) addr);
 
 		DBG_RUN("     pdir 0x%p %lx\n", pdir_start, *pdir_start);
 
@@ -799,12 +834,15 @@
 		size -= IOVP_SIZE;
 		pdir_start++;
 	}
+	/* force pdir update */
+	wmb();
+
 	/* form complete address */
 #ifdef ASSERT_PDIR_SANITY
 	sba_check_pdir(ioc,"Check after sba_map_single()");
 #endif
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
-	return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG(direction));
+	return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG);
 }
 
 /**
@@ -812,23 +850,19 @@
  * @dev: instance of PCI owned by the driver that's asking.
  * @iova:  IOVA of driver buffer previously mapped.
  * @size:  number of bytes mapped in driver buffer.
- * @direction:  R/W or both.
+ * @dir:  R/W or both.
  *
  * See Documentation/DMA-mapping.txt
  */
-void sba_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size,
-		int direction)
+void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, int dir)
 {
 	struct ioc *ioc;
 #if DELAYED_RESOURCE_CNT > 0
 	struct sba_dma_pair *d;
 #endif
-	unsigned long flags; 
+	unsigned long flags;
 	dma_addr_t offset;
 
-	if (!sba_list)
-		panic("sba_map_single: no SBA found!\n");
-
 	ioc = GET_IOC(dev);
 	ASSERT(ioc);
 
@@ -845,7 +879,7 @@
 		DBG_BYPASS("sba_unmap_single() bypass addr: 0x%lx\n", iova);
 
 #ifdef ENABLE_MARK_CLEAN
-		if (direction == PCI_DMA_FROMDEVICE) {
+		if (dir == DMA_FROM_DEVICE) {
 			mark_clean(phys_to_virt(iova), size);
 		}
 #endif
@@ -861,29 +895,6 @@
 	size += offset;
 	size = ROUNDUP(size, IOVP_SIZE);
 
-#ifdef ENABLE_MARK_CLEAN
-	/*
-	** Don't need to hold the spinlock while telling VM pages are "clean".
-	** The pages are "busy" in the resource map until we mark them free.
-	** But tell VM pages are clean *before* releasing the resource
-	** in order to avoid race conditions.
-	*/
-	if (direction == PCI_DMA_FROMDEVICE) {
-		u32 iovp = (u32) SBA_IOVP(ioc,iova);
-		unsigned int pide = PDIR_INDEX(iovp);
-		u64 *pdirp = &(ioc->pdir_base[pide]);
-		size_t byte_cnt = size;
-		void *addr;
-
-		do {
-			addr = phys_to_virt(sba_io_page(pdirp));
-			mark_clean(addr, min(byte_cnt, IOVP_SIZE));
-			pdirp++;
-			byte_cnt -= IOVP_SIZE;
-		} while (byte_cnt > 0);
-	}
-#endif
-
 	spin_lock_irqsave(&ioc->res_lock, flags);
 #ifdef CONFIG_PROC_FS
 	ioc->usingle_calls++;
@@ -909,7 +920,40 @@
 	sba_free_range(ioc, iova, size);
 	READ_REG(ioc->ioc_hpa+IOC_PCOM);	/* flush purges */
 #endif /* DELAYED_RESOURCE_CNT == 0 */
+#ifdef ENABLE_MARK_CLEAN
+	if (dir == DMA_FROM_DEVICE) {
+		u32 iovp = (u32) SBA_IOVP(ioc,iova);
+		int off = PDIR_INDEX(iovp);
+		void *addr;
+
+		if (size <= IOVP_SIZE) {
+			addr = phys_to_virt(ioc->pdir_base[off] &
+					    ~0xE000000000000FFFULL);
+			mark_clean(addr, size);
+		} else {
+			size_t byte_cnt = size;
+
+			do {
+				addr = phys_to_virt(ioc->pdir_base[off] &
+				                    ~0xE000000000000FFFULL);
+				mark_clean(addr, min(byte_cnt, IOVP_SIZE));
+				off++;
+				byte_cnt -= IOVP_SIZE;
+
+			   } while (byte_cnt > 0);
+		}
+	}
+#endif
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
+
+	/* XXX REVISIT for 2.5 Linux - need syncdma for zero-copy support.
+	** For Astro based systems this isn't a big deal WRT performance.
+	** As long as 2.4 kernels copyin/copyout data from/to userspace,
+	** we don't need the syncdma. The issue here is I/O MMU cachelines
+	** are *not* coherent in all cases.  May be hwrev dependent.
+	** Need to investigate more.
+	asm volatile("syncdma");
+	*/
 }
 
 
@@ -922,29 +966,25 @@
  * See Documentation/DMA-mapping.txt
  */
 void *
-sba_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
+sba_alloc_coherent (struct device *hwdev, size_t size, dma_addr_t *dma_handle, int flags)
 {
-	void *ret;
-
-	if (!hwdev) {
-		/* only support PCI */
-		*dma_handle = 0;
-		return 0;
-	}
+	struct ioc *ioc;
+	void *addr;
 
-        ret = (void *) __get_free_pages(GFP_ATOMIC, get_order(size));
+        addr = (void *) __get_free_pages(flags, get_order(size));
+	if (!addr)
+		return NULL;
 
-	if (ret) {
-		memset(ret, 0, size);
-		/*
-		 * REVISIT: if sba_map_single starts needing more
-		 * than dma_mask from the device, this needs to be
-		 * updated.
-		 */
-		*dma_handle = sba_map_single(&sac_only_dev, ret, size, 0);
-	}
+	/*
+	 * REVISIT: if sba_map_single starts needing more than dma_mask from the
+	 * device, this needs to be updated.
+	 */
+	ioc = GET_IOC(hwdev);
+	ASSERT(ioc);
+	*dma_handle = sba_map_single(&ioc->sac_only_dev->dev, addr, size, 0);
 
-	return ret;
+	memset(addr, 0, size);
+	return addr;
 }
 
 
@@ -957,117 +997,245 @@
  *
  * See Documentation/DMA-mapping.txt
  */
-void sba_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr,
-		dma_addr_t dma_handle)
+void sba_free_coherent (struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
 {
 	sba_unmap_single(hwdev, dma_handle, size, 0);
 	free_pages((unsigned long) vaddr, get_order(size));
 }
 
 
+/*
+** Since 0 is a valid pdir_base index value, can't use that
+** to determine if a value is valid or not. Use a flag to indicate
+** the SG list entry contains a valid pdir index.
+*/
+#define PIDE_FLAG 0x1UL
+
 #ifdef DEBUG_LARGE_SG_ENTRIES
 int dump_run_sg = 0;
 #endif
 
-#define SG_ENT_VIRT_PAGE(sg) page_address((sg)->page)
-#define SG_ENT_PHYS_PAGE(SG) virt_to_phys(SG_ENT_VIRT_PAGE(SG))
-
 
 /**
- * sba_coalesce_chunks - preprocess the SG list
+ * sba_fill_pdir - write allocated SG entries into IO PDIR
  * @ioc: IO MMU structure which owns the pdir we are interested in.
- * @startsg:  input=SG list	output=DMA addr/len pairs filled in
+ * @startsg:  list of IOVA/size pairs
  * @nents: number of entries in startsg list
- * @direction: R/W or both.
  *
- * Walk the SG list and determine where the breaks are in the DMA stream.
- * Allocate IO Pdir resources and fill them in separate loop.
- * Returns the number of DMA streams used for output IOVA list.
- * Note each DMA stream can consume multiple IO Pdir entries.
- *
- * Code is written assuming some coalescing is possible.
+ * Take preprocessed SG list and write corresponding entries
+ * in the IO PDIR.
  */
+
 static SBA_INLINE int
-sba_coalesce_chunks(struct ioc *ioc, struct scatterlist *startsg,
-	int nents, int direction)
+sba_fill_pdir(
+	struct ioc *ioc,
+	struct scatterlist *startsg,
+	int nents)
 {
-	struct scatterlist *dma_sg = startsg;	/* return array */
+	struct scatterlist *dma_sg = startsg;	/* pointer to current DMA */
 	int n_mappings = 0;
+	u64 *pdirp = 0;
+	unsigned long dma_offset = 0;
 
-	ASSERT(nents > 1);
+	dma_sg--;
+	while (nents-- > 0) {
+		int     cnt = startsg->dma_length;
+		startsg->dma_length = 0;
 
-	do {
-		unsigned int dma_cnt = 1; /* number of pages in DMA stream */
-		unsigned int pide;	/* index into IO Pdir array */
-		u64 *pdirp;		/* pointer into IO Pdir array */
-		unsigned long dma_offset, dma_len; /* cumulative DMA stream */
+#ifdef DEBUG_LARGE_SG_ENTRIES
+		if (dump_run_sg)
+			printk(" %2d : %08lx/%05x %p\n",
+				nents, startsg->dma_address, cnt,
+				sba_sg_address(startsg));
+#else
+		DBG_RUN_SG(" %d : %08lx/%05x %p\n",
+				nents, startsg->dma_address, cnt,
+				sba_sg_address(startsg));
+#endif
+		/*
+		** Look for the start of a new DMA stream
+		*/
+		if (startsg->dma_address & PIDE_FLAG) {
+			u32 pide = startsg->dma_address & ~PIDE_FLAG;
+			dma_offset = (unsigned long) pide & ~IOVP_MASK;
+			startsg->dma_address = 0;
+			dma_sg++;
+			dma_sg->dma_address = pide | ioc->ibase;
+			pdirp = &(ioc->pdir_base[pide >> IOVP_SHIFT]);
+			n_mappings++;
+		}
 
 		/*
-		** Prepare for first/next DMA stream
+		** Look for a VCONTIG chunk
 		*/
-		dma_len = sba_sg_len(startsg);
-		dma_offset = (unsigned long) sba_sg_address(startsg);
+		if (cnt) {
+			unsigned long vaddr = (unsigned long) sba_sg_address(startsg);
+			ASSERT(pdirp);
+
+			/* Since multiple Vcontig blocks could make up
+			** one DMA stream, *add* cnt to dma_len.
+			*/
+			dma_sg->dma_length += cnt;
+			cnt += dma_offset;
+			dma_offset=0;	/* only want offset on first chunk */
+			cnt = ROUNDUP(cnt, IOVP_SIZE);
+#ifdef CONFIG_PROC_FS
+			ioc->msg_pages += cnt >> IOVP_SHIFT;
+#endif
+			do {
+				sba_io_pdir_entry(pdirp, vaddr);
+				vaddr += IOVP_SIZE;
+				cnt -= IOVP_SIZE;
+				pdirp++;
+			} while (cnt > 0);
+		}
 		startsg++;
-		nents--;
+	}
+	/* force pdir update */
+	wmb();
+
+#ifdef DEBUG_LARGE_SG_ENTRIES
+	dump_run_sg = 0;
+#endif
+	return(n_mappings);
+}
+
+
+/*
+** Two address ranges are DMA contiguous *iff* "end of prev" and
+** "start of next" are both on a page boundry.
+**
+** (shift left is a quick trick to mask off upper bits)
+*/
+#define DMA_CONTIG(__X, __Y) \
+	(((((unsigned long) __X) | ((unsigned long) __Y)) << (BITS_PER_LONG - PAGE_SHIFT)) == 0UL)
+
+
+/**
+ * sba_coalesce_chunks - preprocess the SG list
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @startsg:  list of IOVA/size pairs
+ * @nents: number of entries in startsg list
+ *
+ * First pass is to walk the SG list and determine where the breaks are
+ * in the DMA stream. Allocates PDIR entries but does not fill them.
+ * Returns the number of DMA chunks.
+ *
+ * Doing the fill seperate from the coalescing/allocation keeps the
+ * code simpler. Future enhancement could make one pass through
+ * the sglist do both.
+ */
+static SBA_INLINE int
+sba_coalesce_chunks( struct ioc *ioc,
+	struct scatterlist *startsg,
+	int nents)
+{
+	struct scatterlist *vcontig_sg;    /* VCONTIG chunk head */
+	unsigned long vcontig_len;         /* len of VCONTIG chunk */
+	unsigned long vcontig_end;
+	struct scatterlist *dma_sg;        /* next DMA stream head */
+	unsigned long dma_offset, dma_len; /* start/len of DMA stream */
+	int n_mappings = 0;
+
+	while (nents > 0) {
+		unsigned long vaddr = (unsigned long) sba_sg_address(startsg);
 
 		/*
-		** We want to know how many entries can be coalesced
-		** before trying to allocate IO Pdir space.
-		** IOVAs can then be allocated "naturally" aligned
-		** to take advantage of the block IO TLB flush.
+		** Prepare for first/next DMA stream
 		*/
-		while (nents) {
-			unsigned long end_offset = dma_offset + dma_len;
+		dma_sg = vcontig_sg = startsg;
+		dma_len = vcontig_len = vcontig_end = startsg->length;
+		vcontig_end +=  vaddr;
+		dma_offset = vaddr & ~IOVP_MASK;
 
-			/* prev entry must end on a page boundary */
-			if (end_offset & IOVP_MASK)
-				break;
+		/* PARANOID: clear entries */
+		startsg->dma_address = startsg->dma_length = 0;
 
-			/* next entry start on a page boundary? */
-			if (startsg->offset)
-				break;
+		/*
+		** This loop terminates one iteration "early" since
+		** it's always looking one "ahead".
+		*/
+		while (--nents > 0) {
+			unsigned long vaddr;	/* tmp */
+
+			startsg++;
+
+			/* PARANOID */
+			startsg->dma_address = startsg->dma_length = 0;
+
+			/* catch brokenness in SCSI layer */
+			ASSERT(startsg->length <= DMA_CHUNK_SIZE);
 
 			/*
-			** make sure current dma stream won't exceed
-			** DMA_CHUNK_SIZE if coalescing entries.
+			** First make sure current dma stream won't
+			** exceed DMA_CHUNK_SIZE if we coalesce the
+			** next entry.
 			*/
-			if (((end_offset + startsg->length + ~IOVP_MASK)
-								& IOVP_MASK)
-					> DMA_CHUNK_SIZE)
+			if (((dma_len + dma_offset + startsg->length + ~IOVP_MASK) & IOVP_MASK)
+			    > DMA_CHUNK_SIZE)
 				break;
 
-			dma_len += sba_sg_len(startsg);
-			startsg++;
-			nents--;
-			dma_cnt++;
-		}
+			/*
+			** Then look for virtually contiguous blocks.
+			**
+			** append the next transaction?
+			*/
+			vaddr = (unsigned long) sba_sg_address(startsg);
+			if  (vcontig_end == vaddr)
+			{
+				vcontig_len += startsg->length;
+				vcontig_end += startsg->length;
+				dma_len     += startsg->length;
+				continue;
+			}
 
-		ASSERT(dma_len <= DMA_CHUNK_SIZE);
+#ifdef DEBUG_LARGE_SG_ENTRIES
+			dump_run_sg = (vcontig_len > IOVP_SIZE);
+#endif
 
-		/* allocate IO Pdir resource.
-		** returns index into (u64) IO Pdir array.
-		** IOVA is formed from this.
-		*/
-		pide = sba_alloc_range(ioc, dma_cnt << IOVP_SHIFT);
-		pdirp = &(ioc->pdir_base[pide]);
+			/*
+			** Not virtually contigous.
+			** Terminate prev chunk.
+			** Start a new chunk.
+			**
+			** Once we start a new VCONTIG chunk, dma_offset
+			** can't change. And we need the offset from the first
+			** chunk - not the last one. Ergo Successive chunks
+			** must start on page boundaries and dove tail
+			** with it's predecessor.
+			*/
+			vcontig_sg->dma_length = vcontig_len;
 
-		/* fill_pdir: write stream into IO Pdir */
-		while (dma_cnt--) {
-			sba_io_pdir_entry(pdirp, SG_ENT_PHYS_PAGE(startsg));
-			startsg++;
-			pdirp++;
-		}
+			vcontig_sg = startsg;
+			vcontig_len = startsg->length;
 
-		/* "output" IOVA */
-		sba_sg_iova(dma_sg) = SBA_IOVA(ioc,
-					((dma_addr_t) pide << IOVP_SHIFT),
-					dma_offset,
-					DEFAULT_DMA_HINT_REG(direction));
-		sba_sg_iova_len(dma_sg) = dma_len;
+			/*
+			** 3) do the entries end/start on page boundaries?
+			**    Don't update vcontig_end until we've checked.
+			*/
+			if (DMA_CONTIG(vcontig_end, vaddr))
+			{
+				vcontig_end = vcontig_len + vaddr;
+				dma_len += vcontig_len;
+				continue;
+			} else {
+				break;
+			}
+		}
 
-		dma_sg++;
+		/*
+		** End of DMA Stream
+		** Terminate last VCONTIG block.
+		** Allocate space for DMA stream.
+		*/
+		vcontig_sg->dma_length = vcontig_len;
+		dma_len = (dma_len + dma_offset + ~IOVP_MASK) & IOVP_MASK;
+		ASSERT(dma_len <= DMA_CHUNK_SIZE);
+		dma_sg->dma_address = (dma_addr_t) (PIDE_FLAG
+			| (sba_alloc_range(ioc, dma_len) << IOVP_SHIFT)
+			| dma_offset);
 		n_mappings++;
-	} while (nents);
+	}
 
 	return n_mappings;
 }
@@ -1075,60 +1243,51 @@
 
 /**
  * sba_map_sg - map Scatter/Gather list
- * @dev: instance of PCI device owned by the driver that's asking.
+ * @dev: instance of PCI owned by the driver that's asking.
  * @sglist:  array of buffer/length pairs
  * @nents:  number of entries in list
- * @direction:  R/W or both.
+ * @dir:  R/W or both.
  *
  * See Documentation/DMA-mapping.txt
  */
-int sba_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents,
-		int direction)
+int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int dir)
 {
 	struct ioc *ioc;
-	int filled = 0;
+	int coalesced, filled = 0;
 	unsigned long flags;
 #ifdef ALLOW_IOV_BYPASS
 	struct scatterlist *sg;
 #endif
 
-	DBG_RUN_SG("%s() START %d entries, 0x%p,0x%x\n", __FUNCTION__, nents,
-		sba_sg_address(sglist), sba_sg_len(sglist));
-
-	if (!sba_list)
-		panic("sba_map_single: no SBA found!\n");
-
+	DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents);
 	ioc = GET_IOC(dev);
 	ASSERT(ioc);
 
 #ifdef ALLOW_IOV_BYPASS
-	if (dev->dma_mask >= ioc->dma_mask) {
-		for (sg = sglist ; filled < nents ; filled++, sg++) {
-			sba_sg_iova(sg) = virt_to_phys(sba_sg_address(sg));
-			sba_sg_iova_len(sg) = sba_sg_len(sg);
+	if (dev && dev->dma_mask && (ioc->dma_mask & ~*dev->dma_mask) == 0) {
+		for (sg = sglist ; filled < nents ; filled++, sg++){
+			sg->dma_length = sg->length;
+			sg->dma_address = virt_to_phys(sba_sg_address(sg));
 		}
 #ifdef CONFIG_PROC_FS
 		spin_lock_irqsave(&ioc->res_lock, flags);
 		ioc->msg_bypass++;
 		spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif
-		DBG_RUN_SG("%s() DONE %d mappings bypassed\n", __FUNCTION__, filled);
 		return filled;
 	}
 #endif
 	/* Fast path single entry scatterlists. */
 	if (nents == 1) {
-		sba_sg_iova(sglist) = sba_map_single(dev,
-						     (void *) sba_sg_iova(sglist),
-						     sba_sg_len(sglist), direction);
-		sba_sg_iova_len(sglist) = sba_sg_len(sglist);
+		sglist->dma_length = sglist->length;
+		sglist->dma_address = sba_map_single(dev, sba_sg_address(sglist), sglist->length,
+						     dir);
 #ifdef CONFIG_PROC_FS
 		/*
 		** Should probably do some stats counting, but trying to
 		** be precise quickly starts wasting CPU time.
 		*/
 #endif
-		DBG_RUN_SG("%s() DONE 1 mapping\n", __FUNCTION__);
 		return 1;
 	}
 
@@ -1145,11 +1304,26 @@
 #ifdef CONFIG_PROC_FS
 	ioc->msg_calls++;
 #endif
- 
+
 	/*
-	** coalesce and program the I/O Pdir
+	** First coalesce the chunks and allocate I/O pdir space
+	**
+	** If this is one DMA stream, we can properly map using the
+	** correct virtual address associated with each DMA page.
+	** w/o this association, we wouldn't have coherent DMA!
+	** Access to the virtual address is what forces a two pass algorithm.
 	*/
-	filled = sba_coalesce_chunks(ioc, sglist, nents, direction);
+	coalesced = sba_coalesce_chunks(ioc, sglist, nents);
+
+	/*
+	** Program the I/O Pdir
+	**
+	** map the virtual addresses to the I/O Pdir
+	** o dma_address will contain the pdir index
+	** o dma_len will contain the number of bytes to map
+	** o address contains the virtual address.
+	*/
+	filled = sba_fill_pdir(ioc, sglist, nents);
 
 #ifdef ASSERT_PDIR_SANITY
 	if (sba_check_pdir(ioc,"Check after sba_map_sg()"))
@@ -1161,6 +1335,7 @@
 
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
 
+	ASSERT(coalesced == filled);
 	DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled);
 
 	return filled;
@@ -1172,23 +1347,19 @@
  * @dev: instance of PCI owned by the driver that's asking.
  * @sglist:  array of buffer/length pairs
  * @nents:  number of entries in list
- * @direction:  R/W or both.
+ * @dir:  R/W or both.
  *
  * See Documentation/DMA-mapping.txt
  */
-void sba_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents,
-		int direction)
+void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir)
 {
 	struct ioc *ioc;
 #ifdef ASSERT_PDIR_SANITY
 	unsigned long flags;
 #endif
 
-	DBG_RUN_SG("%s() START %d entries, 0x%p,0x%x\n",
-		__FUNCTION__, nents, sba_sg_address(sglist), sba_sg_len(sglist));
-
-	if (!sba_list)
-		panic("sba_map_single: no SBA found!\n");
+	DBG_RUN_SG("%s() START %d entries,  %p,%x\n",
+		__FUNCTION__, nents, sba_sg_address(sglist), sglist->length);
 
 	ioc = GET_IOC(dev);
 	ASSERT(ioc);
@@ -1203,10 +1374,9 @@
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif
 
-	while (sba_sg_len(sglist) && nents--) {
+	while (nents && sglist->dma_length) {
 
-		sba_unmap_single(dev, (dma_addr_t)sba_sg_iova(sglist),
-		                 sba_sg_iova_len(sglist), direction);
+		sba_unmap_single(dev, sglist->dma_address, sglist->dma_length, dir);
 #ifdef CONFIG_PROC_FS
 		/*
 		** This leaves inconsistent data in the stats, but we can't
@@ -1214,9 +1384,11 @@
 		** were coalesced to a single entry.  The stats are fun,
 		** but speed is more important.
 		*/
-		ioc->usg_pages += (((u64)sba_sg_iova(sglist) & ~IOVP_MASK) + sba_sg_len(sglist) + IOVP_SIZE - 1) >> IOVP_SHIFT;
+		ioc->usg_pages += ((sglist->dma_address & ~IOVP_MASK) + sglist->dma_length
+				   + IOVP_SIZE - 1) >> PAGE_SHIFT;
 #endif
-		++sglist;
+		sglist++;
+		nents--;
 	}
 
 	DBG_RUN_SG("%s() DONE (nents %d)\n", __FUNCTION__,  nents);
@@ -1229,87 +1401,76 @@
 
 }
 
-unsigned long
-sba_dma_address (struct scatterlist *sg)
-{
-	return ((unsigned long)sba_sg_iova(sg));
-}
-
-int
-sba_dma_supported (struct pci_dev *dev, u64 mask)
-{
-	return 1;
-}
-
 /**************************************************************
 *
 *   Initialization and claim
 *
 ***************************************************************/
 
-
-static void
-sba_ioc_init(struct sba_device *sba_dev, struct ioc *ioc, int ioc_num)
+static void __init
+ioc_iova_init(struct ioc *ioc)
 {
-	u32 iova_space_size, iova_space_mask;
-	void * pdir_base;
-	int pdir_size, iov_order, tcnfg;
+	u32 iova_space_mask;
+	int iov_order, tcnfg;
+	int agp_found = 0;
+	struct pci_dev *device;
+#ifdef FULL_VALID_PDIR
+	unsigned long index;
+#endif
 
 	/*
-	** Firmware programs the maximum IOV space size into the imask reg
+	** Firmware programs the base and size of a "safe IOVA space"
+	** (one that doesn't overlap memory or LMMIO space) in the
+	** IBASE and IMASK registers.
 	*/
-	iova_space_size = ~(READ_REG(ioc->ioc_hpa + IOC_IMASK) & 0xFFFFFFFFUL) + 1;
+	ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE) & ~0x1UL;
+	ioc->iov_size = ~(READ_REG(ioc->ioc_hpa + IOC_IMASK) & 0xFFFFFFFFUL) + 1;
 
 	/*
 	** iov_order is always based on a 1GB IOVA space since we want to
 	** turn on the other half for AGP GART.
 	*/
-	iov_order = get_order(iova_space_size >> (IOVP_SHIFT-PAGE_SHIFT));
-	ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64);
+	iov_order = get_order(ioc->iov_size >> (IOVP_SHIFT - PAGE_SHIFT));
+	ioc->pdir_size = (ioc->iov_size / IOVP_SIZE) * sizeof(u64);
 
-	DBG_INIT("%s() hpa 0x%lx IOV %dMB (%d bits) PDIR size 0x%0x\n",
-		__FUNCTION__, ioc->ioc_hpa, iova_space_size>>20,
-		iov_order + PAGE_SHIFT, ioc->pdir_size);
+	DBG_INIT("%s() hpa %p IOV %dMB (%d bits) PDIR size 0x%x\n",
+		 __FUNCTION__, ioc->ioc_hpa, ioc->iov_size >> 20,
+		 iov_order + PAGE_SHIFT, ioc->pdir_size);
 
-	/* XXX DMA HINTs not used */
+	/* FIXME : DMA HINTs not used */
 	ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
 	ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
 
-	ioc->pdir_base = pdir_base =
-		(void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size));
-	if (NULL == pdir_base)
-	{
-		panic(__FILE__ ":%s() could not allocate I/O Page Table\n", __FUNCTION__);
-	}
-	memset(pdir_base, 0, pdir_size);
+	ioc->pdir_base = (void *) __get_free_pages(GFP_KERNEL,
+						   get_order(ioc->pdir_size));
+	if (!ioc->pdir_base)
+		panic(PFX "Couldn't allocate I/O Page Table\n");
+
+	memset(ioc->pdir_base, 0, ioc->pdir_size);
 
 	DBG_INIT("%s() pdir %p size %x hint_shift_pdir %x hint_mask_pdir %lx\n",
-		__FUNCTION__, pdir_base, pdir_size,
+		__FUNCTION__, ioc->pdir_base, ioc->pdir_size,
 		ioc->hint_shift_pdir, ioc->hint_mask_pdir);
 
-	ASSERT((((unsigned long) pdir_base) & PAGE_MASK) == (unsigned long) pdir_base);
-	WRITE_REG(virt_to_phys(pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE);
+	ASSERT((((unsigned long) ioc->pdir_base) & PAGE_MASK) == (unsigned long) ioc->pdir_base);
+	WRITE_REG(virt_to_phys(ioc->pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE);
 
-	DBG_INIT(" base %p\n", pdir_base);
+	DBG_INIT(" base %p\n", ioc->pdir_base);
 
 	/* build IMASK for IOC and Elroy */
 	iova_space_mask =  0xffffffff;
-	iova_space_mask <<= (iov_order + IOVP_SHIFT);
-
-	ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE) & 0xFFFFFFFEUL;
-
-	ioc->imask = iova_space_mask;	/* save it */
+	iova_space_mask <<= (iov_order + PAGE_SHIFT);
+	ioc->imask = iova_space_mask;
 
 	DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n",
 		__FUNCTION__, ioc->ibase, ioc->imask);
 
 	/*
-	** XXX DMA HINT registers are programmed with default hint
+	** FIXME: Hint registers are programmed with default hint
 	** values during boot, so hints should be sane even if we
 	** can't reprogram them the way drivers want.
 	*/
-
-	WRITE_REG(ioc->imask, ioc->ioc_hpa+IOC_IMASK);
+	WRITE_REG(ioc->imask, ioc->ioc_hpa + IOC_IMASK);
 
 	/*
 	** Setting the upper bits makes checking for bypass addresses
@@ -1317,34 +1478,30 @@
 	*/
 	ioc->imask |= 0xFFFFFFFF00000000UL;
 
-	/* Set I/O Pdir page size to system page size */
-	switch (IOVP_SHIFT) {
-		case 12: /* 4K */
-			tcnfg = 0;
-			break;
-		case 13: /* 8K */
-			tcnfg = 1;
-			break;
-		case 14: /* 16K */
-			tcnfg = 2;
-			break;
-		case 16: /* 64K */
-			tcnfg = 3;
+	/* Set I/O PDIR Page size to system page size */
+	switch (PAGE_SHIFT) {
+		case 12: tcnfg = 0; break;	/*  4K */
+		case 13: tcnfg = 1; break;	/*  8K */
+		case 14: tcnfg = 2; break;	/* 16K */
+		case 16: tcnfg = 3; break;	/* 64K */
+		default:
+			panic(PFX "Unsupported system page size %d",
+				1 << PAGE_SHIFT);
 			break;
 	}
-	WRITE_REG(tcnfg, ioc->ioc_hpa+IOC_TCNFG);
+	WRITE_REG(tcnfg, ioc->ioc_hpa + IOC_TCNFG);
 
 	/*
 	** Program the IOC's ibase and enable IOVA translation
 	** Bit zero == enable bit.
 	*/
-	WRITE_REG(ioc->ibase | 1, ioc->ioc_hpa+IOC_IBASE);
+	WRITE_REG(ioc->ibase | 1, ioc->ioc_hpa + IOC_IBASE);
 
 	/*
 	** Clear I/O TLB of any possible entries.
 	** (Yes. This is a bit paranoid...but so what)
 	*/
-	WRITE_REG(0 | 31, ioc->ioc_hpa+IOC_PCOM);
+	WRITE_REG(ioc->ibase | (iov_order+PAGE_SHIFT), ioc->ioc_hpa + IOC_PCOM);
 
 	/*
 	** If an AGP device is present, only use half of the IOV space
@@ -1354,346 +1511,468 @@
 	** We program the next pdir index after we stop w/ a key for
 	** the GART code to handshake on.
 	*/
-	if (SBA_GET_AGP(sba_dev)) {
-		DBG_INIT("%s() AGP Device found, reserving 512MB for GART support\n", __FUNCTION__);
+	pci_for_each_dev(device)
+		agp_found |= pci_find_capability(device, PCI_CAP_ID_AGP);
+
+	if (agp_found && reserve_sba_gart) {
+		DBG_INIT("%s: AGP device found, reserving half of IOVA for GART support\n",
+			 __FUNCTION__);
 		ioc->pdir_size /= 2;
-		((u64 *)pdir_base)[PDIR_INDEX(iova_space_size/2)] = 0x0000badbadc0ffeeULL;
+		((u64 *)ioc->pdir_base)[PDIR_INDEX(ioc->iov_size/2)] = ZX1_SBA_IOMMU_COOKIE;
 	}
+#ifdef FULL_VALID_PDIR
+	/*
+  	** Check to see if the spill page has been allocated, we don't need more than
+	** one across multiple SBAs.
+	*/
+	if (!prefetch_spill_page) {
+		char *spill_poison = "SBAIOMMU POISON";
+		int poison_size = 16;
+		void *poison_addr, *addr;
+
+		addr = (void *)__get_free_pages(GFP_KERNEL, get_order(IOVP_SIZE));
+		if (!addr)
+			panic(PFX "Couldn't allocate PDIR spill page\n");
+
+		poison_addr = addr;
+		for ( ; (u64) poison_addr < addr + IOVP_SIZE; poison_addr += poison_size)
+			memcpy(poison_addr, spill_poison, poison_size);
+
+		prefetch_spill_page = virt_to_phys(addr);
+
+		DBG_INIT("%s() prefetch spill addr: 0x%lx\n", __FUNCTION__, prefetch_spill_page);
+	}
+	/*
+  	** Set all the PDIR entries valid w/ the spill page as the target
+	*/
+	for (index = 0 ; index < (ioc->pdir_size / sizeof(u64)) ; index++)
+		((u64 *)ioc->pdir_base)[index] = (0x80000000000000FF | prefetch_spill_page);
+#endif
 
-	DBG_INIT("%s() DONE\n", __FUNCTION__);
 }
 
+static void __init
+ioc_resource_init(struct ioc *ioc)
+{
+	spin_lock_init(&ioc->res_lock);
 
+	/* resource map size dictated by pdir_size */
+	ioc->res_size = ioc->pdir_size / sizeof(u64); /* entries */
+	ioc->res_size >>= 3;  /* convert bit count to byte count */
+	DBG_INIT("%s() res_size 0x%x\n", __FUNCTION__, ioc->res_size);
 
-/**************************************************************************
-**
-**   SBA initialization code (HW and SW)
-**
-**   o identify SBA chip itself
-**   o FIXME: initialize DMA hints for reasonable defaults
-**
-**************************************************************************/
+	ioc->res_map = (char *) __get_free_pages(GFP_KERNEL,
+						 get_order(ioc->res_size));
+	if (!ioc->res_map)
+		panic(PFX "Couldn't allocate resource map\n");
 
-static void
-sba_hw_init(struct sba_device *sba_dev)
-{ 
-	int i;
-	int num_ioc;
-	u64 dma_mask;
-	u32 func_id;
+	memset(ioc->res_map, 0, ioc->res_size);
+	/* next available IOVP - circular search */
+	ioc->res_hint = (unsigned long *) ioc->res_map;
 
-	/*
-	** Identify the SBA so we can set the dma_mask.  We can make a virtual
-	** dma_mask of the memory subsystem such that devices not implmenting
-	** a full 64bit mask might still be able to bypass efficiently.
-	*/
-	func_id = READ_REG(sba_dev->sba_hpa + SBA_FUNC_ID);
+#ifdef ASSERT_PDIR_SANITY
+	/* Mark first bit busy - ie no IOVA 0 */
+	ioc->res_map[0] = 0x1;
+	ioc->pdir_base[0] = 0x8000000000000000ULL | ZX1_SBA_IOMMU_COOKIE;
+#endif
+#ifdef FULL_VALID_PDIR
+	/* Mark the last resource used so we don't prefetch beyond IOVA space */
+	ioc->res_map[ioc->res_size - 1] |= 0x80UL; /* res_map is chars */
+	ioc->pdir_base[(ioc->pdir_size / sizeof(u64)) - 1] = (0x80000000000000FF
+							      | prefetch_spill_page);
+#endif
 
-	if (func_id == ZX1_FUNC_ID_VALUE) {
-		dma_mask = 0xFFFFFFFFFFUL;
-	} else {
-		dma_mask = 0xFFFFFFFFFFFFFFFFUL;
-	}
+	DBG_INIT("%s() res_map %x %p\n", __FUNCTION__,
+		 ioc->res_size, (void *) ioc->res_map);
+}
+
+static void __init
+ioc_sac_init(struct ioc *ioc)
+{
+	struct pci_dev *sac = NULL;
+	struct pci_controller *controller = NULL;
 
-	DBG_INIT("%s(): ioc->dma_mask == 0x%lx\n", __FUNCTION__, dma_mask);
-	
 	/*
-	** Leaving in the multiple ioc code from parisc for the future,
-	** currently there are no muli-ioc mckinley sbas
-	*/
-	sba_dev->ioc[0].ioc_hpa = SBA_IOC_OFFSET;
-	num_ioc = 1;
+	 * pci_alloc_coherent() must return a DMA address which is
+	 * SAC (single address cycle) addressable, so allocate a
+	 * pseudo-device to enforce that.
+	 */
+	sac = kmalloc(sizeof(*sac), GFP_KERNEL);
+	if (!sac)
+		panic(PFX "Couldn't allocate struct pci_dev");
+	memset(sac, 0, sizeof(*sac));
 
-	sba_dev->num_ioc = num_ioc;
-	for (i = 0; i < num_ioc; i++) {
-		sba_dev->ioc[i].dma_mask = dma_mask;
-		sba_dev->ioc[i].ioc_hpa += sba_dev->sba_hpa;
-		sba_ioc_init(sba_dev, &(sba_dev->ioc[i]), i);
-	}
+	controller = kmalloc(sizeof(*controller), GFP_KERNEL);
+	if (!controller)
+		panic(PFX "Couldn't allocate struct pci_controller");
+	memset(controller, 0, sizeof(*controller));
+
+	controller->iommu = ioc;
+	sac->sysdata = controller;
+	sac->dma_mask = 0xFFFFFFFFUL;
+#ifdef CONFIG_PCI
+	sac->dev.bus = &pci_bus_type;
+#endif
+	ioc->sac_only_dev = sac;
 }
 
-static void
-sba_common_init(struct sba_device *sba_dev)
+static void __init
+ioc_zx1_init(struct ioc *ioc)
 {
-	int i;
+	if (ioc->rev < 0x20)
+		panic(PFX "IOC 2.0 or later required for IOMMU support\n");
 
-	/* add this one to the head of the list (order doesn't matter)
-	** This will be useful for debugging - especially if we get coredumps
-	*/
-	sba_dev->next = sba_list;
-	sba_list = sba_dev;
-	sba_count++;
-
-	for(i=0; i< sba_dev->num_ioc; i++) {
-		int res_size;
-
-		/* resource map size dictated by pdir_size */
-		res_size = sba_dev->ioc[i].pdir_size/sizeof(u64); /* entries */
-		res_size >>= 3;  /* convert bit count to byte count */
-		DBG_INIT("%s() res_size 0x%x\n",
-			__FUNCTION__, res_size);
-
-		sba_dev->ioc[i].res_size = res_size;
-		sba_dev->ioc[i].res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size));
-
-		if (NULL == sba_dev->ioc[i].res_map)
-		{
-			panic(__FILE__ ":%s() could not allocate resource map\n", __FUNCTION__ );
-		}
+	ioc->dma_mask = 0xFFFFFFFFFFUL;
+}
 
-		memset(sba_dev->ioc[i].res_map, 0, res_size);
-		/* next available IOVP - circular search */
-		if ((sba_dev->hw_rev & 0xFF) >= 0x20) {
-			sba_dev->ioc[i].res_hint = (unsigned long *)
-			    sba_dev->ioc[i].res_map;
-		} else {
-			u64 reserved_iov;
+typedef void (initfunc)(struct ioc *);
 
-			/* Yet another 1.x hack */
-			printk(KERN_DEBUG "zx1 1.x: Starting resource hint offset into "
-			       "IOV space to avoid initial zero value IOVA\n");
-			sba_dev->ioc[i].res_hint = (unsigned long *)
-			    &(sba_dev->ioc[i].res_map[L1_CACHE_BYTES]);
-
-			sba_dev->ioc[i].res_map[0] = 0x1;
-			sba_dev->ioc[i].pdir_base[0] = 0x8000badbadc0ffeeULL;
-
-			for (reserved_iov = 0xA0000 ; reserved_iov < 0xC0000 ; reserved_iov += IOVP_SIZE) {
-				u64 *res_ptr = (u64 *) sba_dev->ioc[i].res_map;
-				int index = PDIR_INDEX(reserved_iov);
-				int res_word;
-				u64 mask;
-
-				res_word = (int)(index / BITS_PER_LONG);
-				mask =  0x1UL << (index - (res_word * BITS_PER_LONG));
-				res_ptr[res_word] |= mask;
-				sba_dev->ioc[i].pdir_base[PDIR_INDEX(reserved_iov)] = (SBA_VALID_MASK | reserved_iov);
+struct ioc_iommu {
+	u32 func_id;
+	char *name;
+	initfunc *init;
+};
 
-			}
-		}
+static struct ioc_iommu ioc_iommu_info[] __initdata = {
+	{ ZX1_IOC_ID, "zx1", ioc_zx1_init },
+	{ REO_IOC_ID, "REO" },
+	{ SX1000_IOC_ID, "sx1000" },
+};
 
-#ifdef ASSERT_PDIR_SANITY
-		/* Mark first bit busy - ie no IOVA 0 */
-		sba_dev->ioc[i].res_map[0] = 0x1;
-		sba_dev->ioc[i].pdir_base[0] = 0x8000badbadc0ffeeULL;
-#endif
+static struct ioc * __init
+ioc_init(u64 hpa, void *handle)
+{
+	struct ioc *ioc;
+	struct ioc_iommu *info;
+
+	ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
+	if (!ioc)
+		return NULL;
+
+	memset(ioc, 0, sizeof(*ioc));
 
-		DBG_INIT("%s() %d res_map %x %p\n", __FUNCTION__,
-		         i, res_size, (void *)sba_dev->ioc[i].res_map);
+	ioc->next = ioc_list;
+	ioc_list = ioc;
+
+	ioc->handle = handle;
+	ioc->ioc_hpa = ioremap(hpa, 0x1000);
+
+	ioc->func_id = READ_REG(ioc->ioc_hpa + IOC_FUNC_ID);
+	ioc->rev = READ_REG(ioc->ioc_hpa + IOC_FCLASS) & 0xFFUL;
+	ioc->dma_mask = 0xFFFFFFFFFFFFFFFFUL;	/* conservative */
+
+	for (info = ioc_iommu_info; info < ioc_iommu_info + ARRAY_SIZE(ioc_iommu_info); info++) {
+		if (ioc->func_id == info->func_id) {
+			ioc->name = info->name;
+			if (info->init)
+				(info->init)(ioc);
+		}
 	}
 
-	sba_dev->sba_lock = SPIN_LOCK_UNLOCKED;
+	if (!ioc->name) {
+		ioc->name = kmalloc(24, GFP_KERNEL);
+		if (ioc->name)
+			sprintf((char *) ioc->name, "Unknown (%04x:%04x)",
+				ioc->func_id & 0xFFFF, (ioc->func_id >> 16) & 0xFFFF);
+		else
+			ioc->name = "Unknown";
+	}
+
+	ioc_iova_init(ioc);
+	ioc_resource_init(ioc);
+	ioc_sac_init(ioc);
+
+	printk(KERN_INFO PFX
+		"%s %d.%d HPA 0x%lx IOVA space %dMb at 0x%lx\n",
+		ioc->name, (ioc->rev >> 4) & 0xF, ioc->rev & 0xF,
+		hpa, ioc->iov_size >> 20, ioc->ibase);
+
+	return ioc;
 }
 
+
+
+/**************************************************************************
+**
+**   SBA initialization code (HW and SW)
+**
+**   o identify SBA chip itself
+**   o FIXME: initialize DMA hints for reasonable defaults
+**
+**************************************************************************/
+
 #ifdef CONFIG_PROC_FS
-static int sba_proc_info(char *buf, char **start, off_t offset, int len)
+static void *
+ioc_start(struct seq_file *s, loff_t *pos)
 {
-	struct sba_device *sba_dev;
 	struct ioc *ioc;
-	int total_pages;
+	loff_t n = *pos;
+
+	for (ioc = ioc_list; ioc; ioc = ioc->next)
+		if (!n--)
+			return ioc;
+
+	return NULL;
+}
+
+static void *
+ioc_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	struct ioc *ioc = v;
+
+	++*pos;
+	return ioc->next;
+}
+
+static void
+ioc_stop(struct seq_file *s, void *v)
+{
+}
+
+static int
+ioc_show(struct seq_file *s, void *v)
+{
+	struct ioc *ioc = v;
+	int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */
 	unsigned long i = 0, avg = 0, min, max;
 
-	for (sba_dev = sba_list; sba_dev; sba_dev = sba_dev->next) {
-		ioc = &sba_dev->ioc[0];	/* FIXME: Multi-IOC support! */
-		total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */
-
-		sprintf(buf, "%s rev %d.%d\n", "Hewlett-Packard zx1 SBA",
-			((sba_dev->hw_rev >> 4) & 0xF), (sba_dev->hw_rev & 0xF));
-		sprintf(buf, "%sIO PDIR size    : %d bytes (%d entries)\n", buf,
-			(int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */ total_pages);
-
-		sprintf(buf, "%sIO PDIR entries : %ld free  %ld used (%d%%)\n", buf,
-			total_pages - ioc->used_pages, ioc->used_pages,
-			(int) (ioc->used_pages * 100 / total_pages));
-
-		sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", 
-			buf, ioc->res_size, ioc->res_size << 3);   /* 8 bits per byte */
-
-		min = max = ioc->avg_search[0];
-		for (i = 0; i < SBA_SEARCH_SAMPLE; i++) {
-			avg += ioc->avg_search[i];
-			if (ioc->avg_search[i] > max) max = ioc->avg_search[i];
-			if (ioc->avg_search[i] < min) min = ioc->avg_search[i];
-		}
-		avg /= SBA_SEARCH_SAMPLE;
-		sprintf(buf, "%s  Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
-			buf, min, avg, max);
-
-		sprintf(buf, "%spci_map_single(): %12ld calls  %12ld pages (avg %d/1000)\n",
-			buf, ioc->msingle_calls, ioc->msingle_pages,
-			(int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls));
+	seq_printf(s, "Hewlett Packard %s IOC rev %d.%d\n",
+		ioc->name, ((ioc->rev >> 4) & 0xF), (ioc->rev & 0xF));
+	seq_printf(s, "IO PDIR size    : %d bytes (%d entries)\n",
+		(int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */
+		total_pages);
+
+	seq_printf(s, "IO PDIR entries : %ld free  %ld used (%d%%)\n",
+		total_pages - ioc->used_pages, ioc->used_pages,
+		(int) (ioc->used_pages * 100 / total_pages));
+
+	seq_printf(s, "Resource bitmap : %d bytes (%d pages)\n",
+		ioc->res_size, ioc->res_size << 3);   /* 8 bits per byte */
+
+	min = max = ioc->avg_search[0];
+	for (i = 0; i < SBA_SEARCH_SAMPLE; i++) {
+		avg += ioc->avg_search[i];
+		if (ioc->avg_search[i] > max) max = ioc->avg_search[i];
+		if (ioc->avg_search[i] < min) min = ioc->avg_search[i];
+	}
+  	avg /= SBA_SEARCH_SAMPLE;
+	seq_printf(s, "  Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", min, avg, max);
+
+	seq_printf(s, "pci_map_single(): %12ld calls  %12ld pages (avg %d/1000)\n",
+		   ioc->msingle_calls, ioc->msingle_pages,
+		   (int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls));
 #ifdef ALLOW_IOV_BYPASS
-		sprintf(buf, "%spci_map_single(): %12ld bypasses\n",
-			buf, ioc->msingle_bypass);
+	seq_printf(s, "pci_map_single(): %12ld bypasses\n", ioc->msingle_bypass);
 #endif
 
-		sprintf(buf, "%spci_unmap_single: %12ld calls  %12ld pages (avg %d/1000)\n",
-			buf, ioc->usingle_calls, ioc->usingle_pages,
-			(int) ((ioc->usingle_pages * 1000)/ioc->usingle_calls));
+	seq_printf(s, "pci_unmap_single: %12ld calls  %12ld pages (avg %d/1000)\n",
+		   ioc->usingle_calls, ioc->usingle_pages,
+		   (int) ((ioc->usingle_pages * 1000)/ioc->usingle_calls));
 #ifdef ALLOW_IOV_BYPASS
-		sprintf(buf, "%spci_unmap_single: %12ld bypasses\n",
-			buf, ioc->usingle_bypass);
+	seq_printf(s, "pci_unmap_single: %12ld bypasses\n", ioc->usingle_bypass);
 #endif
 
-		sprintf(buf, "%spci_map_sg()    : %12ld calls  %12ld pages (avg %d/1000)\n",
-			buf, ioc->msg_calls, ioc->msg_pages,
-			(int) ((ioc->msg_pages * 1000)/ioc->msg_calls));
+	seq_printf(s, "pci_map_sg()    : %12ld calls  %12ld pages (avg %d/1000)\n",
+		   ioc->msg_calls, ioc->msg_pages,
+		   (int) ((ioc->msg_pages * 1000)/ioc->msg_calls));
 #ifdef ALLOW_IOV_BYPASS
-		sprintf(buf, "%spci_map_sg()    : %12ld bypasses\n",
-			buf, ioc->msg_bypass);
+	seq_printf(s, "pci_map_sg()    : %12ld bypasses\n", ioc->msg_bypass);
 #endif
 
-		sprintf(buf, "%spci_unmap_sg()  : %12ld calls  %12ld pages (avg %d/1000)\n",
-			buf, ioc->usg_calls, ioc->usg_pages,
-			(int) ((ioc->usg_pages * 1000)/ioc->usg_calls));
-	}
-	return strlen(buf);
+	seq_printf(s, "pci_unmap_sg()  : %12ld calls  %12ld pages (avg %d/1000)\n",
+		   ioc->usg_calls, ioc->usg_pages, (int) ((ioc->usg_pages * 1000)/ioc->usg_calls));
+
+	return 0;
 }
 
+static struct seq_operations ioc_seq_ops = {
+	.start = ioc_start,
+	.next  = ioc_next,
+	.stop  = ioc_stop,
+	.show  = ioc_show
+};
+
 static int
-sba_resource_map(char *buf, char **start, off_t offset, int len)
+ioc_open(struct inode *inode, struct file *file)
 {
-	struct ioc *ioc = sba_list->ioc;	/* FIXME: Multi-IOC support! */
-	unsigned int *res_ptr;
-	int i;
+	return seq_open(file, &ioc_seq_ops);
+}
 
-	if (!ioc)
-		return 0;
+static struct file_operations ioc_fops = {
+	.open    = ioc_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release
+};
 
-	res_ptr = (unsigned int *)ioc->res_map;
-	buf[0] = '\0';
-	for(i = 0; i < (ioc->res_size / sizeof(unsigned int)); ++i, ++res_ptr) {
-		if ((i & 7) == 0)
-		    strcat(buf,"\n   ");
-		sprintf(buf, "%s %08x", buf, *res_ptr);
-	}
-	strcat(buf, "\n");
+static int
+ioc_map_show(struct seq_file *s, void *v)
+{
+	struct ioc *ioc = v;
+	unsigned int i, *res_ptr = (unsigned int *)ioc->res_map;
 
-	return strlen(buf);
+	for (i = 0; i < ioc->res_size / sizeof(unsigned int); ++i, ++res_ptr)
+		seq_printf(s, "%s%08x", (i & 7) ? " " : "\n   ", *res_ptr);
+	seq_printf(s, "\n");
+
+	return 0;
 }
-#endif
 
-/*
-** Determine if sba should claim this chip (return 0) or not (return 1).
-** If so, initialize the chip and tell other partners in crime they
-** have work to do.
-*/
-void __init sba_init(void)
+static struct seq_operations ioc_map_ops = {
+	.start = ioc_start,
+	.next  = ioc_next,
+	.stop  = ioc_stop,
+	.show  = ioc_map_show
+};
+
+static int
+ioc_map_open(struct inode *inode, struct file *file)
 {
-	struct sba_device *sba_dev;
-	u32 func_id, hw_rev;
-	u32 *func_offset = NULL;
-	int i, agp_found = 0;
-	static char sba_rev[6];
-	struct pci_dev *device = NULL;
-	u64 hpa = 0;
+	return seq_open(file, &ioc_map_ops);
+}
 
-	if (!(device = pci_find_device(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_ZX1_SBA, NULL)))
-		return;
+static struct file_operations ioc_map_fops = {
+	.open    = ioc_map_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release
+};
 
-	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-		if (pci_resource_flags(device, i) == IORESOURCE_MEM) {
-			hpa = (u64) ioremap(pci_resource_start(device, i),
-					    pci_resource_len(device, i));
-			break;
-		}
+static void __init
+ioc_proc_init(void)
+{
+	if (ioc_list) {
+		struct proc_dir_entry *dir, *entry;
+
+		dir = proc_mkdir("bus/mckinley", 0);
+		entry = create_proc_entry(ioc_list->name, 0, dir);
+		if (entry)
+			entry->proc_fops = &ioc_fops;
+
+		entry = create_proc_entry("bitmap", 0, dir);
+		if (entry)
+			entry->proc_fops = &ioc_map_fops;
 	}
+}
+#endif
 
-	func_id = READ_REG(hpa + SBA_FUNC_ID);
-	if (func_id != ZX1_FUNC_ID_VALUE)
-		return;
+void
+sba_connect_bus(struct pci_bus *bus)
+{
+	acpi_handle handle, parent;
+	acpi_status status;
+	struct ioc *ioc;
 
-	strcpy(sba_rev, "zx1");
-	func_offset = zx1_func_offsets;
+	if (!PCI_CONTROLLER(bus))
+		panic(PFX "no sysdata on bus %d!\n",bus->number);
 
-	/* Read HW Rev First */
-	hw_rev = READ_REG(hpa + SBA_FCLASS) & 0xFFUL;
+	if (PCI_CONTROLLER(bus)->iommu)
+		return;
+
+	handle = PCI_CONTROLLER(bus)->acpi_handle;
+	if (!handle)
+		return;
 
 	/*
-	 * Not all revision registers of the chipset are updated on every
-	 * turn.  Must scan through all functions looking for the highest rev
+	 * The IOC scope encloses PCI root bridges in the ACPI
+	 * namespace, so work our way out until we find an IOC we
+	 * claimed previously.
 	 */
-	if (func_offset) {
-		for (i = 0 ; func_offset[i] != -1 ; i++) {
-			u32 func_rev;
-
-			func_rev = READ_REG(hpa + SBA_FCLASS + func_offset[i]) & 0xFFUL;
-			DBG_INIT("%s() func offset: 0x%x rev: 0x%x\n",
-			         __FUNCTION__, func_offset[i], func_rev);
-			if (func_rev > hw_rev)
-				hw_rev = func_rev;
-		}
-	}
-
-	printk(KERN_INFO "%s found %s %d.%d at %s, HPA 0x%lx\n", DRIVER_NAME,
-	       sba_rev, ((hw_rev >> 4) & 0xF), (hw_rev & 0xF),
-	       device->slot_name, hpa);
+	do {
+		for (ioc = ioc_list; ioc; ioc = ioc->next)
+			if (ioc->handle == handle) {
+				PCI_CONTROLLER(bus)->iommu = ioc;
+				return;
+			}
 
-	if ((hw_rev & 0xFF) < 0x20) {
-		printk(KERN_INFO "%s: SBA rev less than 2.0 not supported", DRIVER_NAME);
-		return;
-	}
+		status = acpi_get_parent(handle, &parent);
+		handle = parent;
+	} while (ACPI_SUCCESS(status));
 
-	sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
-	if (NULL == sba_dev) {
-		printk(KERN_ERR DRIVER_NAME " - couldn't alloc sba_device\n");
-		return;
-	}
+	printk(KERN_WARNING "No IOC for PCI Bus %02x:%02x in ACPI\n", PCI_SEGMENT(bus), bus->number);
+}
 
-	memset(sba_dev, 0, sizeof(struct sba_device));
+static int __init
+acpi_sba_ioc_add(struct acpi_device *device)
+{
+	struct ioc *ioc;
+	acpi_status status;
+	u64 hpa, length;
+	struct acpi_device_info dev_info;
 
-	for(i=0; i<MAX_IOC; i++)
-		spin_lock_init(&(sba_dev->ioc[i].res_lock));
+	status = hp_acpi_csr_space(device->handle, &hpa, &length);
+	if (ACPI_FAILURE(status))
+		return 1;
 
-	sba_dev->hw_rev = hw_rev;
-	sba_dev->sba_hpa = hpa;
+	status = acpi_get_object_info(device->handle, &dev_info);
+	if (ACPI_FAILURE(status))
+		return 1;
 
 	/*
-	 * We pass this fake device from alloc_consistent to ensure
-	 * we only use SAC for alloc_consistent mappings.
+	 * For HWP0001, only SBA appears in ACPI namespace.  It encloses the PCI
+	 * root bridges, and its CSR space includes the IOC function.
 	 */
-	sac_only_dev.dma_mask = 0xFFFFFFFFUL;
+	if (strncmp("HWP0001", dev_info.hardware_id, 7) == 0)
+		hpa += ZX1_IOC_OFFSET;
 
-	/*
-	 * We need to check for an AGP device, if we find one, then only
-	 * use part of the IOVA space for PCI DMA, the rest is for GART.
-	 * REVISIT for multiple IOC.
-	 */
-	pci_for_each_dev(device)
-		agp_found |= pci_find_capability(device, PCI_CAP_ID_AGP);
+	ioc = ioc_init(hpa, device->handle);
+	if (!ioc)
+		return 1;
 
-	if (agp_found && reserve_sba_gart)
-		SBA_SET_AGP(sba_dev);
+	return 0;
+}
 
-	sba_hw_init(sba_dev);
-	sba_common_init(sba_dev);
+static struct acpi_driver acpi_sba_ioc_driver = {
+	name:		"IOC IOMMU Driver",
+	ids:		"HWP0001,HWP0004",
+	ops: {
+		add:	acpi_sba_ioc_add,
+	},
+};
 
-#ifdef CONFIG_PROC_FS
-	{
-		struct proc_dir_entry * proc_mckinley_root;
+static int __init
+sba_init(void)
+{
+	MAX_DMA_ADDRESS = ~0UL;
+
+	acpi_bus_register_driver(&acpi_sba_ioc_driver);
 
-		proc_mckinley_root = proc_mkdir("bus/mckinley",0);
-		create_proc_info_entry(sba_rev, 0, proc_mckinley_root, sba_proc_info);
-		create_proc_info_entry("bitmap", 0, proc_mckinley_root, sba_resource_map);
+#ifdef CONFIG_PCI
+	{
+		struct pci_bus *b;
+		pci_for_each_bus(b)
+			sba_connect_bus(b);
 	}
 #endif
+
+#ifdef CONFIG_PROC_FS
+	ioc_proc_init();
+#endif
+	return 0;
 }
 
+subsys_initcall(sba_init); /* must be initialized after ACPI etc., but before any drivers... */
+
 static int __init
-nosbagart (char *str)
+nosbagart(char *str)
 {
 	reserve_sba_gart = 0;
 	return 1;
 }
 
-__setup("nosbagart",nosbagart);
+int
+sba_dma_supported (struct device *dev, u64 mask)
+{
+	/* make sure it's at least 32bit capable */
+	return ((mask & 0xFFFFFFFFUL) == 0xFFFFFFFFUL);
+}
+
+__setup("nosbagart", nosbagart);
 
-EXPORT_SYMBOL(sba_init);
 EXPORT_SYMBOL(sba_map_single);
 EXPORT_SYMBOL(sba_unmap_single);
 EXPORT_SYMBOL(sba_map_sg);
 EXPORT_SYMBOL(sba_unmap_sg);
-EXPORT_SYMBOL(sba_dma_address);
 EXPORT_SYMBOL(sba_dma_supported);
-EXPORT_SYMBOL(sba_alloc_consistent);
-EXPORT_SYMBOL(sba_free_consistent);
+EXPORT_SYMBOL(sba_alloc_coherent);
+EXPORT_SYMBOL(sba_free_coherent);
diff -urN linux-2.5.69-bk6/arch/ia64/hp/sim/hpsim_console.c linux-2.5.69-bk7/arch/ia64/hp/sim/hpsim_console.c
--- linux-2.5.69-bk6/arch/ia64/hp/sim/hpsim_console.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/hp/sim/hpsim_console.c	2003-05-12 04:43:29.000000000 -0700
@@ -59,7 +59,7 @@
 
 static struct tty_driver *simcons_console_device (struct console *c, int *index)
 {
-	extern struct tty_driver hp_serial_driver;
+	extern struct tty_driver hp_simserial_driver;
 	*index = c->index;
-	return &hp_serial_driver;
+	return &hp_simserial_driver;
 }
diff -urN linux-2.5.69-bk6/arch/ia64/hp/sim/hpsim_machvec.c linux-2.5.69-bk7/arch/ia64/hp/sim/hpsim_machvec.c
--- linux-2.5.69-bk6/arch/ia64/hp/sim/hpsim_machvec.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/hp/sim/hpsim_machvec.c	2003-05-12 04:43:29.000000000 -0700
@@ -1,2 +1,3 @@
-#define MACHVEC_PLATFORM_NAME	hpsim
+#define MACHVEC_PLATFORM_NAME		hpsim
+#define MACHVEC_PLATFORM_HEADER		<asm/machvec_hpsim.h>
 #include <asm/machvec_init.h>
diff -urN linux-2.5.69-bk6/arch/ia64/hp/sim/simeth.c linux-2.5.69-bk7/arch/ia64/hp/sim/simeth.c
--- linux-2.5.69-bk6/arch/ia64/hp/sim/simeth.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/hp/sim/simeth.c	2003-05-12 04:43:29.000000000 -0700
@@ -55,7 +55,7 @@
 static int simeth_tx(struct sk_buff *skb, struct net_device *dev);
 static int simeth_rx(struct net_device *dev);
 static struct net_device_stats *simeth_get_stats(struct net_device *dev);
-static void simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs);
 static void set_multicast_list(struct net_device *dev);
 static int simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr);
 
@@ -494,20 +494,21 @@
 /*
  * Interrupt handler (Yes, we can do it too !!!)
  */
-static void
+static irqreturn_t
 simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct net_device *dev = dev_id;
 
 	if ( dev == NULL ) {
 		printk(KERN_WARNING "simeth: irq %d for unknown device\n", irq);
-		return;
+		return IRQ_NONE;
 	}
 
 	/*
-	 * very simple loop because we get interrupts only when receving
+	 * very simple loop because we get interrupts only when receiving
 	 */
 	while (simeth_rx(dev));
+	return IRQ_HANDLED;
 }
 
 static struct net_device_stats *
diff -urN linux-2.5.69-bk6/arch/ia64/hp/sim/simserial.c linux-2.5.69-bk7/arch/ia64/hp/sim/simserial.c
--- linux-2.5.69-bk6/arch/ia64/hp/sim/simserial.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/hp/sim/simserial.c	2003-05-12 04:43:29.000000000 -0700
@@ -103,7 +103,8 @@
 	{ 0, 0}
 };
 
-static struct tty_driver hp_serial_driver, callout_driver;
+struct tty_driver hp_simserial_driver;
+static struct tty_driver callout_driver;
 static int serial_refcount;
 
 static struct async_struct *IRQ_ports[NR_IRQS];
@@ -184,7 +185,7 @@
 /*
  * This is the serial driver's interrupt routine for a single port
  */
-static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct async_struct * info;
 
@@ -195,13 +196,14 @@
 	info = IRQ_ports[irq];
 	if (!info || !info->tty) {
 		printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info);
-		return;
+		return IRQ_NONE;
 	}
 	/*
 	 * pretty simple in our case, because we only get interrupts
 	 * on inbound traffic
 	 */
 	receive_chars(info->tty, regs);
+	return IRQ_HANDLED;
 }
 
 /*
@@ -768,7 +770,7 @@
 {
 	unsigned long flags;
 	int	retval=0;
-	void (*handler)(int, void *, struct pt_regs *);
+	irqreturn_t (*handler)(int, void *, struct pt_regs *);
 	struct serial_state *state= info->state;
 	unsigned long page;
 
@@ -808,8 +810,7 @@
 		} else
 			handler = rs_interrupt_single;
 
-		retval = request_irq(state->irq, handler, IRQ_T(info),
-				     "simserial", NULL);
+		retval = request_irq(state->irq, handler, IRQ_T(info), "simserial", NULL);
 		if (retval) {
 			if (capable(CAP_SYS_ADMIN)) {
 				if (info->tty)
@@ -1028,43 +1029,43 @@
 
 	/* Initialize the tty_driver structure */
 
-	memset(&hp_serial_driver, 0, sizeof(struct tty_driver));
-	hp_serial_driver.magic = TTY_DRIVER_MAGIC;
-	hp_serial_driver.driver_name = "simserial";
-	hp_serial_driver.name = "ttyS";
-	hp_serial_driver.major = TTY_MAJOR;
-	hp_serial_driver.minor_start = 64;
-	hp_serial_driver.num = 1;
-	hp_serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	hp_serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	hp_serial_driver.init_termios = tty_std_termios;
-	hp_serial_driver.init_termios.c_cflag =
+	memset(&hp_simserial_driver, 0, sizeof(struct tty_driver));
+	hp_simserial_driver.magic = TTY_DRIVER_MAGIC;
+	hp_simserial_driver.driver_name = "simserial";
+	hp_simserial_driver.name = "ttyS";
+	hp_simserial_driver.major = TTY_MAJOR;
+	hp_simserial_driver.minor_start = 64;
+	hp_simserial_driver.num = 1;
+	hp_simserial_driver.type = TTY_DRIVER_TYPE_SERIAL;
+	hp_simserial_driver.subtype = SERIAL_TYPE_NORMAL;
+	hp_simserial_driver.init_termios = tty_std_termios;
+	hp_simserial_driver.init_termios.c_cflag =
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	hp_serial_driver.flags = TTY_DRIVER_REAL_RAW;
-	hp_serial_driver.refcount = &serial_refcount;
-	hp_serial_driver.table = serial_table;
-	hp_serial_driver.termios = serial_termios;
-	hp_serial_driver.termios_locked = serial_termios_locked;
-
-	hp_serial_driver.open = rs_open;
-	hp_serial_driver.close = rs_close;
-	hp_serial_driver.write = rs_write;
-	hp_serial_driver.put_char = rs_put_char;
-	hp_serial_driver.flush_chars = rs_flush_chars;
-	hp_serial_driver.write_room = rs_write_room;
-	hp_serial_driver.chars_in_buffer = rs_chars_in_buffer;
-	hp_serial_driver.flush_buffer = rs_flush_buffer;
-	hp_serial_driver.ioctl = rs_ioctl;
-	hp_serial_driver.throttle = rs_throttle;
-	hp_serial_driver.unthrottle = rs_unthrottle;
-	hp_serial_driver.send_xchar = rs_send_xchar;
-	hp_serial_driver.set_termios = rs_set_termios;
-	hp_serial_driver.stop = rs_stop;
-	hp_serial_driver.start = rs_start;
-	hp_serial_driver.hangup = rs_hangup;
-	hp_serial_driver.break_ctl = rs_break;
-	hp_serial_driver.wait_until_sent = rs_wait_until_sent;
-	hp_serial_driver.read_proc = rs_read_proc;
+	hp_simserial_driver.flags = TTY_DRIVER_REAL_RAW;
+	hp_simserial_driver.refcount = &serial_refcount;
+	hp_simserial_driver.table = serial_table;
+	hp_simserial_driver.termios = serial_termios;
+	hp_simserial_driver.termios_locked = serial_termios_locked;
+
+	hp_simserial_driver.open = rs_open;
+	hp_simserial_driver.close = rs_close;
+	hp_simserial_driver.write = rs_write;
+	hp_simserial_driver.put_char = rs_put_char;
+	hp_simserial_driver.flush_chars = rs_flush_chars;
+	hp_simserial_driver.write_room = rs_write_room;
+	hp_simserial_driver.chars_in_buffer = rs_chars_in_buffer;
+	hp_simserial_driver.flush_buffer = rs_flush_buffer;
+	hp_simserial_driver.ioctl = rs_ioctl;
+	hp_simserial_driver.throttle = rs_throttle;
+	hp_simserial_driver.unthrottle = rs_unthrottle;
+	hp_simserial_driver.send_xchar = rs_send_xchar;
+	hp_simserial_driver.set_termios = rs_set_termios;
+	hp_simserial_driver.stop = rs_stop;
+	hp_simserial_driver.start = rs_start;
+	hp_simserial_driver.hangup = rs_hangup;
+	hp_simserial_driver.break_ctl = rs_break;
+	hp_simserial_driver.wait_until_sent = rs_wait_until_sent;
+	hp_simserial_driver.read_proc = rs_read_proc;
 
 	/*
 	 * Let's have a little bit of fun !
@@ -1087,14 +1088,14 @@
 	 * The callout device is just like normal device except for
 	 * major number and the subtype code.
 	 */
-	callout_driver = hp_serial_driver;
+	callout_driver = hp_simserial_driver;
 	callout_driver.name = "cua";
 	callout_driver.major = TTYAUX_MAJOR;
 	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
 	callout_driver.read_proc = 0;
 	callout_driver.proc_entry = 0;
 
-	if (tty_register_driver(&hp_serial_driver))
+	if (tty_register_driver(&hp_simserial_driver))
 		panic("Couldn't register simserial driver\n");
 
 	if (tty_register_driver(&callout_driver))
diff -urN linux-2.5.69-bk6/arch/ia64/hp/zx1/Makefile linux-2.5.69-bk7/arch/ia64/hp/zx1/Makefile
--- linux-2.5.69-bk6/arch/ia64/hp/zx1/Makefile	2003-05-04 16:53:55.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/hp/zx1/Makefile	2003-05-12 04:43:29.000000000 -0700
@@ -5,5 +5,4 @@
 # Copyright (C) Alex Williamson (alex_williamson@hp.com)
 #
 
-obj-y := hpzx1_misc.o
 obj-$(CONFIG_IA64_GENERIC) += hpzx1_machvec.o
diff -urN linux-2.5.69-bk6/arch/ia64/hp/zx1/hpzx1_machvec.c linux-2.5.69-bk7/arch/ia64/hp/zx1/hpzx1_machvec.c
--- linux-2.5.69-bk6/arch/ia64/hp/zx1/hpzx1_machvec.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/hp/zx1/hpzx1_machvec.c	2003-05-12 04:43:29.000000000 -0700
@@ -1,2 +1,3 @@
-#define MACHVEC_PLATFORM_NAME	hpzx1
+#define MACHVEC_PLATFORM_NAME		hpzx1
+#define MACHVEC_PLATFORM_HEADER		<asm/machvec_hpzx1.h>
 #include <asm/machvec_init.h>
diff -urN linux-2.5.69-bk6/arch/ia64/hp/zx1/hpzx1_misc.c linux-2.5.69-bk7/arch/ia64/hp/zx1/hpzx1_misc.c
--- linux-2.5.69-bk6/arch/ia64/hp/zx1/hpzx1_misc.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/hp/zx1/hpzx1_misc.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,348 +0,0 @@
-/*
- * Misc. support for HP zx1 chipset support
- *
- * Copyright (C) 2002-2003 Hewlett-Packard Co
- *	Alex Williamson <alex_williamson@hp.com>
- *	Bjorn Helgaas <bjorn_helgaas@hp.com>
- */
-
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/acpi.h>
-#include <linux/efi.h>
-
-#include <asm/dma.h>
-#include <asm/iosapic.h>
-
-extern acpi_status acpi_evaluate_integer (acpi_handle, acpi_string, struct acpi_object_list *,
-					  unsigned long *);
-
-#define PFX "hpzx1: "
-
-static int hpzx1_devices;
-
-struct fake_pci_dev {
-	struct fake_pci_dev *next;
-	struct pci_dev *pci_dev;
-	unsigned long csr_base;
-	unsigned long csr_size;
-	unsigned long mapped_csrs;	// ioremapped
-	int sizing;			// in middle of BAR sizing operation?
-} *fake_pci_dev_list;
-
-static struct pci_ops *orig_pci_ops;
-
-struct fake_pci_dev *
-lookup_fake_dev (struct pci_bus *bus, unsigned int devfn)
-{
-	struct fake_pci_dev *fake_dev;
-
-	for (fake_dev = fake_pci_dev_list; fake_dev; fake_dev = fake_dev->next)
-		if (fake_dev->pci_dev->bus == bus && fake_dev->pci_dev->devfn == devfn)
-			return fake_dev;
-	return NULL;
-}
-
-static int
-hp_cfg_read (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
-{
-	struct fake_pci_dev *fake_dev = lookup_fake_dev(bus, devfn);
-
-	if (!fake_dev)
-		return (*orig_pci_ops->read)(bus, devfn, where, size, value);
-
-	if (where == PCI_BASE_ADDRESS_0) {
-		if (fake_dev->sizing)
-			*value = ~(fake_dev->csr_size - 1);
-		else
-			*value = ((fake_dev->csr_base & PCI_BASE_ADDRESS_MEM_MASK)
-				  | PCI_BASE_ADDRESS_SPACE_MEMORY);
-		fake_dev->sizing = 0;
-		return PCIBIOS_SUCCESSFUL;
-	}
-	switch (size) {
-	      case 1: *value = readb(fake_dev->mapped_csrs + where); break;
-	      case 2: *value = readw(fake_dev->mapped_csrs + where); break;
-	      case 4: *value = readl(fake_dev->mapped_csrs + where); break;
-	      default:
-		printk(KERN_WARNING"hp_cfg_read: bad size = %d bytes", size);
-		break;
-	}
-	if (where == PCI_COMMAND)
-		*value |= PCI_COMMAND_MEMORY; /* SBA omits this */
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-hp_cfg_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
-{
-	struct fake_pci_dev *fake_dev = lookup_fake_dev(bus, devfn);
-
-	if (!fake_dev)
-		return (*orig_pci_ops->write)(bus, devfn, where, size, value);
-
-	if (where == PCI_BASE_ADDRESS_0) {
-		if (value == ((1UL << 8*size) - 1))
-			fake_dev->sizing = 1;
-		return PCIBIOS_SUCCESSFUL;
-	}
-	switch (size) {
-	      case 1: writeb(value, fake_dev->mapped_csrs + where); break;
-	      case 2: writew(value, fake_dev->mapped_csrs + where); break;
-	      case 4: writel(value, fake_dev->mapped_csrs + where); break;
-	      default:
-		printk(KERN_WARNING"hp_cfg_write: bad size = %d bytes", size);
-		break;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops hp_pci_conf = {
-	.read =		hp_cfg_read,
-	.write =	hp_cfg_write
-};
-
-static void
-hpzx1_fake_pci_dev(char *name, unsigned int busnum, unsigned long addr, unsigned int size)
-{
-	struct fake_pci_dev *fake;
-	int slot, ret;
-	struct pci_dev *dev;
-	struct pci_bus *b, *bus = NULL;
-	u8 hdr;
-
-        fake = kmalloc(sizeof(*fake), GFP_KERNEL);
-	if (!fake) {
-		printk(KERN_ERR PFX "No memory for %s (0x%p) sysdata\n", name, (void *) addr);
-		return;
-	}
-
-	memset(fake, 0, sizeof(*fake));
-	fake->csr_base = addr;
-	fake->csr_size = size;
-	fake->mapped_csrs = (unsigned long) ioremap(addr, size);
-	fake->sizing = 0;
-
-	pci_for_each_bus(b)
-		if (busnum == b->number) {
-			bus = b;
-			break;
-		}
-
-	if (!bus) {
-		printk(KERN_ERR PFX "No host bus 0x%02x for %s (0x%p)\n",
-		       busnum, name, (void *) addr);
-		kfree(fake);
-		return;
-	}
-
-	for (slot = 0x1e; slot; slot--)
-		if (!pci_find_slot(busnum, PCI_DEVFN(slot, 0)))
-			break;
-
-	if (slot < 0) {
-		printk(KERN_ERR PFX "No space for %s (0x%p) on bus 0x%02x\n",
-		       name, (void *) addr, busnum);
-		kfree(fake);
-		return;
-	}
-
-        dev = kmalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev) {
-		printk(KERN_ERR PFX "No memory for %s (0x%p)\n", name, (void *) addr);
-		kfree(fake);
-		return;
-	}
-
-	bus->ops = &hp_pci_conf;	// replace pci ops for this bus
-
-	fake->pci_dev = dev;
-	fake->next = fake_pci_dev_list;
-	fake_pci_dev_list = fake;
-
-	memset(dev, 0, sizeof(*dev));
-	dev->bus = bus;
-	dev->sysdata = fake;
-	dev->dev.parent = bus->dev;
-	dev->dev.bus = &pci_bus_type;
-	dev->devfn = PCI_DEVFN(slot, 0);
-	pci_read_config_word(dev, PCI_VENDOR_ID, &dev->vendor);
-	pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
-	pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr);
-	dev->hdr_type = hdr & 0x7f;
-
-	pci_setup_device(dev);
-
-	// pci_insert_device() without running /sbin/hotplug
-	list_add_tail(&dev->bus_list, &bus->devices);
-	list_add_tail(&dev->global_list, &pci_devices);
-
-	strcpy(dev->dev.bus_id, dev->slot_name);
-	ret = device_register(&dev->dev);
-	if (ret < 0)
-		printk(KERN_INFO PFX "fake device registration failed (%d)\n", ret);
-
-	printk(KERN_INFO PFX "%s at 0x%lx; pci dev %s\n", name, addr, dev->slot_name);
-
-	hpzx1_devices++;
-}
-
-struct acpi_hp_vendor_long {
-	u8	guid_id;
-	u8	guid[16];
-	u8	csr_base[8];
-	u8	csr_length[8];
-};
-
-#define HP_CCSR_LENGTH	0x21
-#define HP_CCSR_TYPE	0x2
-#define HP_CCSR_GUID	EFI_GUID(0x69e9adf9, 0x924f, 0xab5f,				\
-				 0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad)
-
-extern acpi_status acpi_get_crs(acpi_handle, struct acpi_buffer *);
-extern struct acpi_resource *acpi_get_crs_next(struct acpi_buffer *, int *);
-extern union acpi_resource_data *acpi_get_crs_type(struct acpi_buffer *, int *, int);
-extern void acpi_dispose_crs(struct acpi_buffer *);
-
-static acpi_status
-hp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
-{
-	int i, offset = 0;
-	acpi_status status;
-	struct acpi_buffer buf;
-	struct acpi_resource_vendor *res;
-	struct acpi_hp_vendor_long *hp_res;
-	efi_guid_t vendor_guid;
-
-	*csr_base = 0;
-	*csr_length = 0;
-
-	status = acpi_get_crs(obj, &buf);
-	if (ACPI_FAILURE(status)) {
-		printk(KERN_ERR PFX "Unable to get _CRS data on object\n");
-		return status;
-	}
-
-	res = (struct acpi_resource_vendor *)acpi_get_crs_type(&buf, &offset, ACPI_RSTYPE_VENDOR);
-	if (!res) {
-		printk(KERN_ERR PFX "Failed to find config space for device\n");
-		acpi_dispose_crs(&buf);
-		return AE_NOT_FOUND;
-	}
-
-	hp_res = (struct acpi_hp_vendor_long *)(res->reserved);
-
-	if (res->length != HP_CCSR_LENGTH || hp_res->guid_id != HP_CCSR_TYPE) {
-		printk(KERN_ERR PFX "Unknown Vendor data\n");
-		acpi_dispose_crs(&buf);
-		return AE_TYPE; /* Revisit error? */
-	}
-
-	memcpy(&vendor_guid, hp_res->guid, sizeof(efi_guid_t));
-	if (efi_guidcmp(vendor_guid, HP_CCSR_GUID) != 0) {
-		printk(KERN_ERR PFX "Vendor GUID does not match\n");
-		acpi_dispose_crs(&buf);
-		return AE_TYPE; /* Revisit error? */
-	}
-
-	for (i = 0 ; i < 8 ; i++) {
-		*csr_base |= ((u64)(hp_res->csr_base[i]) << (i * 8));
-		*csr_length |= ((u64)(hp_res->csr_length[i]) << (i * 8));
-	}
-
-	acpi_dispose_crs(&buf);
-
-	return AE_OK;
-}
-
-static acpi_status
-hpzx1_sba_probe(acpi_handle obj, u32 depth, void *context, void **ret)
-{
-	u64 csr_base = 0, csr_length = 0;
-	acpi_status status;
-	char *name = context;
-	char fullname[16];
-
-	status = hp_csr_space(obj, &csr_base, &csr_length);
-	if (ACPI_FAILURE(status))
-		return status;
-
-	/*
-	 * Only SBA shows up in ACPI namespace, so its CSR space
-	 * includes both SBA and IOC.  Make SBA and IOC show up
-	 * separately in PCI space.
-	 */
-	sprintf(fullname, "%s SBA", name);
-	hpzx1_fake_pci_dev(fullname, 0, csr_base, 0x1000);
-	sprintf(fullname, "%s IOC", name);
-	hpzx1_fake_pci_dev(fullname, 0, csr_base + 0x1000, 0x1000);
-
-	return AE_OK;
-}
-
-static acpi_status
-hpzx1_lba_probe(acpi_handle obj, u32 depth, void *context, void **ret)
-{
-	u64 csr_base = 0, csr_length = 0;
-	acpi_status status;
-	acpi_native_uint busnum;
-	char *name = context;
-	char fullname[32];
-
-	status = hp_csr_space(obj, &csr_base, &csr_length);
-	if (ACPI_FAILURE(status))
-		return status;
-
-	status = acpi_evaluate_integer(obj, METHOD_NAME__BBN, NULL, &busnum);
-	if (ACPI_FAILURE(status)) {
-		printk(KERN_WARNING PFX "evaluate _BBN fail=0x%x\n", status);
-		busnum = 0;	// no _BBN; stick it on bus 0
-	}
-
-	sprintf(fullname, "%s _BBN 0x%02x", name, (unsigned int) busnum);
-	hpzx1_fake_pci_dev(fullname, busnum, csr_base, csr_length);
-
-	return AE_OK;
-}
-
-static void
-hpzx1_acpi_dev_init(void)
-{
-	extern struct pci_ops *pci_root_ops;
-
-	orig_pci_ops = pci_root_ops;
-
-	/*
-	 * Make fake PCI devices for the following hardware in the
-	 * ACPI namespace.  This makes it more convenient for drivers
-	 * because they can claim these devices based on PCI
-	 * information, rather than needing to know about ACPI.  The
-	 * 64-bit "HPA" space for this hardware is available as BAR
-	 * 0/1.
-	 *
-	 * HWP0001: Single IOC SBA w/o IOC in namespace
-	 * HWP0002: LBA device
-	 * HWP0003: AGP LBA device
-	 */
-	acpi_get_devices("HWP0001", hpzx1_sba_probe, "HWP0001", NULL);
-	acpi_get_devices("HWP0002", hpzx1_lba_probe, "HWP0002 PCI LBA", NULL);
-	acpi_get_devices("HWP0003", hpzx1_lba_probe, "HWP0003 AGP LBA", NULL);
-}
-
-extern void sba_init(void);
-
-static int
-hpzx1_init (void)
-{
-	/* zx1 has a hardware I/O TLB which lets us DMA from any device to any address */
-	MAX_DMA_ADDRESS = ~0UL;
-
-	hpzx1_acpi_dev_init();
-	sba_init();
-	return 0;
-}
-
-subsys_initcall(hpzx1_init);
diff -urN linux-2.5.69-bk6/arch/ia64/ia32/ia32_entry.S linux-2.5.69-bk7/arch/ia64/ia32/ia32_entry.S
--- linux-2.5.69-bk6/arch/ia64/ia32/ia32_entry.S	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/ia32/ia32_entry.S	2003-05-12 04:43:29.000000000 -0700
@@ -273,9 +273,9 @@
 	data8 sys32_sigsuspend
 	data8 compat_sys_sigpending
 	data8 sys_sethostname
-	data8 sys32_setrlimit	  /* 75 */
-	data8 sys32_old_getrlimit
-	data8 sys32_getrusage
+	data8 compat_sys_setrlimit	  /* 75 */
+	data8 compat_sys_old_getrlimit
+	data8 compat_sys_getrusage
 	data8 sys32_gettimeofday
 	data8 sys32_settimeofday
 	data8 sys32_getgroups16	  /* 80 */
@@ -312,7 +312,7 @@
 	data8 sys_vhangup
 	data8 sys32_ni_syscall		/* used to be sys_idle */
 	data8 sys32_ni_syscall
-	data8 sys32_wait4
+	data8 compat_sys_wait4
 	data8 sys_swapoff	  /* 115 */
 	data8 sys32_sysinfo
 	data8 sys32_ipc
@@ -389,7 +389,7 @@
 	data8 sys32_ni_syscall		  /* streams1 */
 	data8 sys32_ni_syscall		  /* streams2 */
 	data8 sys32_vfork	  /* 190 */
-	data8 sys32_getrlimit
+	data8 compat_sys_getrlimit
 	data8 sys32_mmap2
 	data8 sys32_truncate64
 	data8 sys32_ftruncate64
diff -urN linux-2.5.69-bk6/arch/ia64/ia32/ia32_ioctl.c linux-2.5.69-bk7/arch/ia64/ia32/ia32_ioctl.c
--- linux-2.5.69-bk6/arch/ia64/ia32/ia32_ioctl.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/ia32/ia32_ioctl.c	2003-05-12 04:43:29.000000000 -0700
@@ -3,13 +3,16 @@
  *
  * Copyright (C) 2000 VA Linux Co
  * Copyright (C) 2000 Don Dugger <n0ano@valinux.com>
- * Copyright (C) 2001-2002 Hewlett-Packard Co
+ * Copyright (C) 2001-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
 #include <linux/types.h>
 #include <linux/dirent.h>
 #include <linux/fs.h>		/* argh, msdos_fs.h isn't self-contained... */
+#include <linux/signal.h>	/* argh, msdos_fs.h isn't self-contained... */
+
+#include <asm/ia32.h>
 
 #include <linux/msdos_fs.h>
 #include <linux/mtio.h>
@@ -33,8 +36,6 @@
 #define	__KERNEL__
 #include <scsi/sg.h>
 
-#include <asm/ia32.h>
-
 #include <../drivers/char/drm/drm.h>
 #include <../drivers/char/drm/mga_drm.h>
 #include <../drivers/char/drm/i810_drm.h>
diff -urN linux-2.5.69-bk6/arch/ia64/ia32/ia32_traps.c linux-2.5.69-bk7/arch/ia64/ia32/ia32_traps.c
--- linux-2.5.69-bk6/arch/ia64/ia32/ia32_traps.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/ia32/ia32_traps.c	2003-05-12 04:43:29.000000000 -0700
@@ -103,7 +103,7 @@
 			 * C1 reg you need in case of a stack fault, 0x040 is the stack
 			 * fault bit.  We should only be taking one exception at a time,
 			 * so if this combination doesn't produce any single exception,
-			 * then we have a bad program that isn't syncronizing its FPU usage
+			 * then we have a bad program that isn't synchronizing its FPU usage
 			 * and it will suffer the consequences since we won't be able to
 			 * fully reproduce the context of the exception
 			 */
diff -urN linux-2.5.69-bk6/arch/ia64/ia32/sys_ia32.c linux-2.5.69-bk7/arch/ia64/ia32/sys_ia32.c
--- linux-2.5.69-bk6/arch/ia64/ia32/sys_ia32.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/ia32/sys_ia32.c	2003-05-12 04:43:29.000000000 -0700
@@ -53,10 +53,10 @@
 #include <asm/types.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
+#include <asm/ia32.h>
 
 #include <net/scm.h>
 #include <net/sock.h>
-#include <asm/ia32.h>
 
 #define DEBUG	0
 
@@ -177,7 +177,7 @@
 {
 	int err;
 
-	if (stat->size > MAX_NON_LFS)
+	if ((u64) stat->size > MAX_NON_LFS)
 		return -EOVERFLOW;
 
 	if (clear_user(ubuf, sizeof(*ubuf)))
@@ -243,8 +243,7 @@
 		return -ENOMEM;
 
 	if (old_prot)
-		if (copy_from_user(page, (void *) PAGE_START(start), PAGE_SIZE))
-			return -EFAULT;
+		copy_from_user(page, (void *) PAGE_START(start), PAGE_SIZE);
 
 	down_write(&current->mm->mmap_sem);
 	{
@@ -837,8 +836,9 @@
 		}
 	}
 
+	size = FDS_BYTES(n);
 	ret = -EINVAL;
-	if (n < 0)
+	if (n < 0 || size < n)
 		goto out_nofds;
 
 	if (n > current->files->max_fdset)
@@ -850,7 +850,6 @@
 	 * long-words.
 	 */
 	ret = -ENOMEM;
-	size = FDS_BYTES(n);
 	bits = kmalloc(6 * size, GFP_KERNEL);
 	if (!bits)
 		goto out_nofds;
@@ -928,8 +927,7 @@
 static struct iovec *
 get_compat_iovec (struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type)
 {
-	int i;
-	u32 buf, len;
+	u32 i, buf, len;
 	struct iovec *ivp, *iov;
 
 	/* Get the "struct iovec" from user memory */
@@ -1005,77 +1003,6 @@
 	return ret;
 }
 
-#define RLIM_INFINITY32	0x7fffffff
-#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
-
-struct rlimit32 {
-	int	rlim_cur;
-	int	rlim_max;
-};
-
-extern asmlinkage long sys_getrlimit (unsigned int resource, struct rlimit *rlim);
-
-asmlinkage long
-sys32_old_getrlimit (unsigned int resource, struct rlimit32 *rlim)
-{
-	mm_segment_t old_fs = get_fs();
-	struct rlimit r;
-	int ret;
-
-	set_fs(KERNEL_DS);
-	ret = sys_getrlimit(resource, &r);
-	set_fs(old_fs);
-	if (!ret) {
-		ret = put_user(RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
-		ret |= put_user(RESOURCE32(r.rlim_max), &rlim->rlim_max);
-	}
-	return ret;
-}
-
-asmlinkage long
-sys32_getrlimit (unsigned int resource, struct rlimit32 *rlim)
-{
-	mm_segment_t old_fs = get_fs();
-	struct rlimit r;
-	int ret;
-
-	set_fs(KERNEL_DS);
-	ret = sys_getrlimit(resource, &r);
-	set_fs(old_fs);
-	if (!ret) {
-		if (r.rlim_cur >= 0xffffffff)
-			r.rlim_cur = 0xffffffff;
-		if (r.rlim_max >= 0xffffffff)
-			r.rlim_max = 0xffffffff;
-		ret = put_user(r.rlim_cur, &rlim->rlim_cur);
-		ret |= put_user(r.rlim_max, &rlim->rlim_max);
-	}
-	return ret;
-}
-
-extern asmlinkage long sys_setrlimit (unsigned int resource, struct rlimit *rlim);
-
-asmlinkage long
-sys32_setrlimit (unsigned int resource, struct rlimit32 *rlim)
-{
-	struct rlimit r;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-
-	if (resource >= RLIM_NLIMITS)
-		return -EINVAL;
-	if (get_user(r.rlim_cur, &rlim->rlim_cur) || get_user(r.rlim_max, &rlim->rlim_max))
-		return -EFAULT;
-	if (r.rlim_cur == RLIM_INFINITY32)
-		r.rlim_cur = RLIM_INFINITY;
-	if (r.rlim_max == RLIM_INFINITY32)
-		r.rlim_max = RLIM_INFINITY;
-	set_fs(KERNEL_DS);
-	ret = sys_setrlimit(resource, &r);
-	set_fs(old_fs);
-	return ret;
-}
-
 /*
  * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
  *
@@ -1648,19 +1575,35 @@
 	return err;
 }
 
+extern int sem_ctls[];
+#define sc_semopm	(sem_ctls[2])
+
 static long
-semtimedop32(int semid, struct sembuf *tsems, int nsems,
-	     const struct compat_timespec *timeout32)
+semtimedop32(int semid, struct sembuf *tsops, int nsops,
+	     struct compat_timespec *timeout32)
 {
 	struct timespec t;
-	if (get_user (t.tv_sec, &timeout32->tv_sec) ||
-	    get_user (t.tv_nsec, &timeout32->tv_nsec))
+	mm_segment_t oldfs;
+	long ret;
+
+	/* parameter checking precedence should mirror sys_semtimedop() */
+	if (nsops < 1 || semid < 0)
+		return -EINVAL;
+	if (nsops > sc_semopm)
+		return -E2BIG;
+	if (!access_ok(VERIFY_READ, tsops, nsops * sizeof(struct sembuf)) ||
+	    get_compat_timespec(&t, timeout32))
 		return -EFAULT;
-	return sys_semtimedop(semid, tsems, nsems, &t);
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_semtimedop(semid, tsops, nsops, &t);
+	set_fs(oldfs);
+	return ret;
 }
 
 asmlinkage long
-sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
+sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
 {
 	int version;
 
@@ -1668,12 +1611,15 @@
 	call &= 0xffff;
 
 	switch (call) {
+	      case SEMTIMEDOP:
+		if (fifth)
+			return semtimedop32(first, (struct sembuf *)AA(ptr),
+				second, (struct compat_timespec *)AA(fifth));
+		/* else fall through for normal semop() */
 	      case SEMOP:
 		/* struct sembuf is the same on 32 and 64bit :)) */
-		return sys_semtimedop(first, (struct sembuf *)AA(ptr), second, NULL);
-	      case SEMTIMEDOP:
-		return semtimedop32(first, (struct sembuf *)AA(ptr), second,
-				    (const struct compat_timespec *)AA(fifth));
+		return sys_semtimedop(first, (struct sembuf *)AA(ptr), second,
+				      NULL);
 	      case SEMGET:
 		return sys_semget(first, second, third);
 	      case SEMCTL:
@@ -1724,98 +1670,10 @@
 	return i;
 }
 
-struct rusage32 {
-	struct compat_timeval ru_utime;
-	struct compat_timeval ru_stime;
-	int    ru_maxrss;
-	int    ru_ixrss;
-	int    ru_idrss;
-	int    ru_isrss;
-	int    ru_minflt;
-	int    ru_majflt;
-	int    ru_nswap;
-	int    ru_inblock;
-	int    ru_oublock;
-	int    ru_msgsnd;
-	int    ru_msgrcv;
-	int    ru_nsignals;
-	int    ru_nvcsw;
-	int    ru_nivcsw;
-};
-
-static int
-put_rusage (struct rusage32 *ru, struct rusage *r)
-{
-	int err;
-
-	if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)))
-		return -EFAULT;
-
-	err = __put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
-	err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
-	err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
-	err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
-	err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
-	err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
-	err |= __put_user (r->ru_idrss, &ru->ru_idrss);
-	err |= __put_user (r->ru_isrss, &ru->ru_isrss);
-	err |= __put_user (r->ru_minflt, &ru->ru_minflt);
-	err |= __put_user (r->ru_majflt, &ru->ru_majflt);
-	err |= __put_user (r->ru_nswap, &ru->ru_nswap);
-	err |= __put_user (r->ru_inblock, &ru->ru_inblock);
-	err |= __put_user (r->ru_oublock, &ru->ru_oublock);
-	err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
-	err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
-	err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
-	err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
-	err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
-	return err;
-}
-
-asmlinkage long
-sys32_wait4 (int pid, unsigned int *stat_addr, int options, struct rusage32 *ru)
-{
-	if (!ru)
-		return sys_wait4(pid, stat_addr, options, NULL);
-	else {
-		struct rusage r;
-		int ret;
-		unsigned int status;
-		mm_segment_t old_fs = get_fs();
-
-		set_fs(KERNEL_DS);
-		ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
-		set_fs(old_fs);
-		if (put_rusage(ru, &r))
-			return -EFAULT;
-		if (stat_addr && put_user(status, stat_addr))
-			return -EFAULT;
-		return ret;
-	}
-}
-
 asmlinkage long
 sys32_waitpid (int pid, unsigned int *stat_addr, int options)
 {
-	return sys32_wait4(pid, stat_addr, options, NULL);
-}
-
-
-extern asmlinkage long sys_getrusage (int who, struct rusage *ru);
-
-asmlinkage long
-sys32_getrusage (int who, struct rusage32 *ru)
-{
-	struct rusage r;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-
-	set_fs(KERNEL_DS);
-	ret = sys_getrusage(who, &r);
-	set_fs(old_fs);
-	if (put_rusage (ru, &r))
-		return -EFAULT;
-	return ret;
+	return compat_sys_wait4(pid, stat_addr, options, NULL);
 }
 
 static unsigned int
@@ -2211,7 +2069,7 @@
 			ret = -EIO;
 			break;
 		}
-		for (i = 0; i < 17*sizeof(int); i += sizeof(int) ) {
+		for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) {
 			put_user(getreg(child, i), (unsigned int *) A(data));
 			data += sizeof(int);
 		}
@@ -2223,7 +2081,7 @@
 			ret = -EIO;
 			break;
 		}
-		for (i = 0; i < 17*sizeof(int); i += sizeof(int) ) {
+		for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) {
 			get_user(tmp, (unsigned int *) A(data));
 			putreg(child, i, tmp);
 			data += sizeof(int);
@@ -2299,7 +2157,7 @@
 		return(-EINVAL);
 	/* Trying to gain more privileges? */
 	asm volatile ("mov %0=ar.eflag ;;" : "=r"(old));
-	if (level > ((old >> 12) & 3)) {
+	if ((unsigned int) level > ((old >> 12) & 3)) {
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
 	}
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/Makefile linux-2.5.69-bk7/arch/ia64/kernel/Makefile
--- linux-2.5.69-bk6/arch/ia64/kernel/Makefile	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/Makefile	2003-05-12 04:43:29.000000000 -0700
@@ -11,6 +11,8 @@
 obj-$(CONFIG_EFI_VARS)		+= efivars.o
 obj-$(CONFIG_FSYS)		+= fsys.o
 obj-$(CONFIG_IA64_BRL_EMU)	+= brl_emu.o
+obj-$(CONFIG_IA64_GENERIC)	+= acpi-ext.o
+obj-$(CONFIG_IA64_HP_ZX1)	+= acpi-ext.o
 obj-$(CONFIG_IA64_MCA)		+= mca.o mca_asm.o
 obj-$(CONFIG_IA64_PALINFO)	+= palinfo.o
 obj-$(CONFIG_IOSAPIC)		+= iosapic.o
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/acpi-ext.c linux-2.5.69-bk7/arch/ia64/kernel/acpi-ext.c
--- linux-2.5.69-bk6/arch/ia64/kernel/acpi-ext.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/acpi-ext.c	2003-05-12 04:43:29.000000000 -0700
@@ -3,69 +3,99 @@
  *
  * Copyright (C) 2003 Hewlett-Packard
  * Copyright (C) Alex Williamson
+ * Copyright (C) Bjorn Helgaas
  *
- * Vendor specific extensions to ACPI.  These are used by both
- * HP and NEC.
+ * Vendor specific extensions to ACPI.
  */
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/acpi.h>
 #include <linux/efi.h>
 
 #include <asm/acpi-ext.h>
 
-/*
- * Note: Strictly speaking, this is only needed for HP and NEC machines.
- *	 However, NEC machines identify themselves as DIG-compliant, so there is
- *	 no easy way to #ifdef this out.
- */
+struct acpi_vendor_descriptor {
+	u8				guid_id;
+	efi_guid_t			guid;
+};
+
+struct acpi_vendor_info {
+	struct acpi_vendor_descriptor	*descriptor;
+	u8				*data;
+	u32				length;
+};
+
 acpi_status
-hp_acpi_csr_space (acpi_handle obj, u64 *csr_base, u64 *csr_length)
+acpi_vendor_resource_match(struct acpi_resource *resource, void *context)
 {
-	int i, offset = 0;
-	acpi_status status;
-	struct acpi_buffer buf;
-	struct acpi_resource_vendor *res;
-	struct acpi_hp_vendor_long *hp_res;
-	efi_guid_t vendor_guid;
-
-	*csr_base = 0;
-	*csr_length = 0;
-
-	status = acpi_get_crs(obj, &buf);
-	if (ACPI_FAILURE(status)) {
-		printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n");
-		return status;
-	}
-
-	res = (struct acpi_resource_vendor *)acpi_get_crs_type(&buf, &offset, ACPI_RSTYPE_VENDOR);
-	if (!res) {
-		printk(KERN_ERR PREFIX "Failed to find config space for device\n");
-		acpi_dispose_crs(&buf);
+	struct acpi_vendor_info *info = (struct acpi_vendor_info *) context;
+	struct acpi_resource_vendor *vendor;
+	struct acpi_vendor_descriptor *descriptor;
+	u32 length;
+
+	if (resource->id != ACPI_RSTYPE_VENDOR)
+		return AE_OK;
+
+	vendor = (struct acpi_resource_vendor *) &resource->data;
+	descriptor = (struct acpi_vendor_descriptor *) vendor->reserved;
+	if (vendor->length <= sizeof(*info->descriptor) ||
+	    descriptor->guid_id != info->descriptor->guid_id ||
+	    efi_guidcmp(descriptor->guid, info->descriptor->guid))
+		return AE_OK;
+
+	length = vendor->length - sizeof(struct acpi_vendor_descriptor);
+	info->data = acpi_os_allocate(length);
+	if (!info->data)
+		return AE_NO_MEMORY;
+
+	memcpy(info->data, vendor->reserved + sizeof(struct acpi_vendor_descriptor), length);
+	info->length = length;
+	return AE_CTRL_TERMINATE;
+}
+
+acpi_status
+acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor *id,
+		u8 **data, u32 *length)
+{
+	struct acpi_vendor_info info;
+
+	info.descriptor = id;
+	info.data = 0;
+
+	acpi_walk_resources(obj, METHOD_NAME__CRS, acpi_vendor_resource_match, &info);
+	if (!info.data)
 		return AE_NOT_FOUND;
-	}
 
-	hp_res = (struct acpi_hp_vendor_long *)(res->reserved);
+	*data = info.data;
+	*length = info.length;
+	return AE_OK;
+}
+
+struct acpi_vendor_descriptor hp_ccsr_descriptor = {
+	.guid_id = 2,
+	.guid    = EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, 0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad)
+};
+
+acpi_status
+hp_acpi_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
+{
+	acpi_status status;
+	u8 *data;
+	u32 length;
+	int i;
+
+	status = acpi_find_vendor_resource(obj, &hp_ccsr_descriptor, &data, &length);
 
-	if (res->length != HP_CCSR_LENGTH || hp_res->guid_id != HP_CCSR_TYPE) {
-		printk(KERN_ERR PREFIX "Unknown Vendor data\n");
-		acpi_dispose_crs(&buf);
-		return AE_TYPE; /* Revisit error? */
-	}
-
-	memcpy(&vendor_guid, hp_res->guid, sizeof(efi_guid_t));
-	if (efi_guidcmp(vendor_guid, HP_CCSR_GUID) != 0) {
-		printk(KERN_ERR PREFIX "Vendor GUID does not match\n");
-		acpi_dispose_crs(&buf);
-		return AE_TYPE; /* Revisit error? */
-	}
-
-	for (i = 0 ; i < 8 ; i++) {
-		*csr_base |= ((u64)(hp_res->csr_base[i]) << (i * 8));
-		*csr_length |= ((u64)(hp_res->csr_length[i]) << (i * 8));
-	}
+	if (ACPI_FAILURE(status) || length != 16)
+		return AE_NOT_FOUND;
+
+	memcpy(csr_base, data, sizeof(*csr_base));
+	memcpy(csr_length, data + 8, sizeof(*csr_length));
+	acpi_os_free(data);
 
-	acpi_dispose_crs(&buf);
 	return AE_OK;
 }
+
+EXPORT_SYMBOL(hp_acpi_csr_space);
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/acpi.c linux-2.5.69-bk7/arch/ia64/kernel/acpi.c
--- linux-2.5.69-bk6/arch/ia64/kernel/acpi.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/acpi.c	2003-05-12 04:43:29.000000000 -0700
@@ -115,134 +115,6 @@
 #endif
 }
 
-#ifdef CONFIG_ACPI
-
-/**
- * acpi_get_crs - Return the current resource settings for a device
- * obj: A handle for this device
- * buf: A buffer to be populated by this call.
- *
- * Pass a valid handle, typically obtained by walking the namespace and a
- * pointer to an allocated buffer, and this function will fill in the buffer
- * with a list of acpi_resource structures.
- */
-acpi_status
-acpi_get_crs (acpi_handle obj, struct acpi_buffer *buf)
-{
-	acpi_status result;
-	buf->length = 0;
-	buf->pointer = NULL;
-
-	result = acpi_get_current_resources(obj, buf);
-	if (result != AE_BUFFER_OVERFLOW)
-		return result;
-	buf->pointer = kmalloc(buf->length, GFP_KERNEL);
-	if (!buf->pointer)
-		return -ENOMEM;
-
-	return acpi_get_current_resources(obj, buf);
-}
-
-struct acpi_resource *
-acpi_get_crs_next (struct acpi_buffer *buf, int *offset)
-{
-	struct acpi_resource *res;
-
-	if (*offset >= buf->length)
-		return NULL;
-
-	res = buf->pointer + *offset;
-	*offset += res->length;
-	return res;
-}
-
-union acpi_resource_data *
-acpi_get_crs_type (struct acpi_buffer *buf, int *offset, int type)
-{
-	for (;;) {
-		struct acpi_resource *res = acpi_get_crs_next(buf, offset);
-		if (!res)
-			return NULL;
-		if (res->id == type)
-			return &res->data;
-	}
-}
-
-void
-acpi_dispose_crs (struct acpi_buffer *buf)
-{
-	kfree(buf->pointer);
-}
-
-void
-acpi_get_crs_addr (struct acpi_buffer *buf, int type, u64 *base, u64 *size, u64 *tra)
-{
-	int offset = 0;
-	struct acpi_resource_address16 *addr16;
-	struct acpi_resource_address32 *addr32;
-	struct acpi_resource_address64 *addr64;
-
-	for (;;) {
-		struct acpi_resource *res = acpi_get_crs_next(buf, &offset);
-		if (!res)
-			return;
-		switch (res->id) {
-			case ACPI_RSTYPE_ADDRESS16:
-				addr16 = (struct acpi_resource_address16 *) &res->data;
-
-				if (type == addr16->resource_type) {
-					*base = addr16->min_address_range;
-					*size = addr16->address_length;
-					*tra = addr16->address_translation_offset;
-					return;
-				}
-				break;
-			case ACPI_RSTYPE_ADDRESS32:
-				addr32 = (struct acpi_resource_address32 *) &res->data;
-				if (type == addr32->resource_type) {
-					*base = addr32->min_address_range;
-					*size = addr32->address_length;
-					*tra = addr32->address_translation_offset;
-					return;
-				}
-				break;
-			case ACPI_RSTYPE_ADDRESS64:
-				addr64 = (struct acpi_resource_address64 *) &res->data;
-				if (type == addr64->resource_type) {
-					*base = addr64->min_address_range;
-					*size = addr64->address_length;
-					*tra = addr64->address_translation_offset;
-					return;
-				}
-				break;
-		}
-	}
-}
-
-int
-acpi_get_addr_space(void *obj, u8 type, u64 *base, u64 *length, u64 *tra)
-{
-	acpi_status status;
-	struct acpi_buffer buf;
-
-	*base = 0;
-	*length = 0;
-	*tra = 0;
-
-	status = acpi_get_crs((acpi_handle)obj, &buf);
-	if (ACPI_FAILURE(status)) {
-		printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n");
-		return status;
-	}
-
-	acpi_get_crs_addr(&buf, type, base, length, tra);
-
-	acpi_dispose_crs(&buf);
-
-	return AE_OK;
-}
-#endif /* CONFIG_ACPI */
-
 #ifdef CONFIG_ACPI_BOOT
 
 #define ACPI_MAX_PLATFORM_INTERRUPTS	256
@@ -324,7 +196,8 @@
 		printk(" enabled");
 #ifdef CONFIG_SMP
 		smp_boot_data.cpu_phys_id[total_cpus] = (lsapic->id << 8) | lsapic->eid;
-		if (hard_smp_processor_id() == smp_boot_data.cpu_phys_id[total_cpus])
+		if (hard_smp_processor_id()
+		    == (unsigned int) smp_boot_data.cpu_phys_id[total_cpus])
 			printk(" (BSP)");
 #endif
 	}
@@ -918,8 +791,7 @@
 		return 0;
 
 	/* Turn it on */
-	vector = iosapic_register_intr (gsi, polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
-			trigger ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
+	vector = iosapic_register_intr (gsi, polarity, trigger);
 	return vector;
 }
 
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/brl_emu.c linux-2.5.69-bk7/arch/ia64/kernel/brl_emu.c
--- linux-2.5.69-bk6/arch/ia64/kernel/brl_emu.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/brl_emu.c	2003-05-12 04:43:29.000000000 -0700
@@ -59,7 +59,7 @@
 	unsigned long next_ip;
 	struct siginfo siginfo;
 	struct illegal_op_return rv;
-	int tmp_taken, unimplemented_address;
+	long tmp_taken, unimplemented_address;
 
 	rv.fkt = (unsigned long) -1;
 
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/efi.c linux-2.5.69-bk7/arch/ia64/kernel/efi.c
--- linux-2.5.69-bk6/arch/ia64/kernel/efi.c	2003-05-04 16:52:59.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/efi.c	2003-05-12 04:43:29.000000000 -0700
@@ -203,16 +203,16 @@
 STUB_RESET_SYSTEM(virt, )
 
 void
-efi_gettimeofday (struct timeval *tv)
+efi_gettimeofday (struct timespec *ts)
 {
 	efi_time_t tm;
 
-	memset(tv, 0, sizeof(tv));
+	memset(ts, 0, sizeof(ts));
 	if ((*efi.get_time)(&tm, 0) != EFI_SUCCESS)
 		return;
 
-	tv->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
-	tv->tv_usec = tm.nanosecond / 1000;
+	ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
+	ts->tv_nsec = tm.nanosecond;
 }
 
 static int
@@ -512,7 +512,7 @@
 	/* Show what we know for posterity */
 	c16 = __va(efi.systab->fw_vendor);
 	if (c16) {
-		for (i = 0;i < sizeof(vendor) && *c16; ++i)
+		for (i = 0;i < (int) sizeof(vendor) && *c16; ++i)
 			vendor[i] = *c16++;
 		vendor[i] = '\0';
 	}
@@ -520,7 +520,7 @@
 	printk(KERN_INFO "EFI v%u.%.02u by %s:",
 	       efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor);
 
-	for (i = 0; i < efi.systab->nr_tables; i++) {
+	for (i = 0; i < (int) efi.systab->nr_tables; i++) {
 		if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
 			efi.mps = __va(config_tables[i].table);
 			printk(" MPS=0x%lx", config_tables[i].table);
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/efivars.c linux-2.5.69-bk7/arch/ia64/kernel/efivars.c
--- linux-2.5.69-bk6/arch/ia64/kernel/efivars.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/efivars.c	2003-05-12 04:43:29.000000000 -0700
@@ -138,8 +138,7 @@
 static inline unsigned long
 utf8_strsize(efi_char16_t *data, unsigned long maxlength)
 {
-	return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) *
-		sizeof(efi_char16_t);
+	return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
 }
 
 
@@ -170,8 +169,7 @@
 			 efi_guid_t *vendor_guid)
 {
 
-	int i, short_name_size = variable_name_size /
-		sizeof(efi_char16_t) + 38;
+	int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38;
 	char *short_name;
 	efivar_entry_t *new_efivar;
 
@@ -192,7 +190,7 @@
 
 	/* Convert Unicode to normal chars (assume top bits are 0),
 	   ala UTF-8 */
-	for (i=0; i<variable_name_size / sizeof(efi_char16_t); i++) {
+	for (i=0; i< (int) (variable_name_size / sizeof(efi_char16_t)); i++) {
 		short_name[i] = variable_name[i] & 0xFF;
 	}
 
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/fw-emu.c linux-2.5.69-bk7/arch/ia64/kernel/fw-emu.c
--- linux-2.5.69-bk6/arch/ia64/kernel/fw-emu.c	2003-05-04 16:53:00.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/fw-emu.c	2003-05-12 04:43:29.000000000 -0700
@@ -37,7 +37,7 @@
 		    + NUM_MEM_DESCS*(sizeof(efi_memory_desc_t))
 		    + 1024)] __attribute__ ((aligned (8)));
 
-#ifdef CONFIG_IA64_HP_SIM
+#if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC)
 
 /* Simulator system calls: */
 
@@ -233,7 +233,7 @@
 static efi_status_t
 efi_get_time (efi_time_t *tm, efi_time_cap_t *tc)
 {
-#ifdef CONFIG_IA64_HP_SIM
+#if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC)
 	struct {
 		int tv_sec;	/* must be 32bits to work */
 		int tv_usec;
@@ -255,7 +255,7 @@
 static void
 efi_reset_system (int reset_type, efi_status_t status, unsigned long data_size, efi_char16_t *data)
 {
-#ifdef CONFIG_IA64_HP_SIM
+#if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC)
 	ssc(status, 0, 0, 0, SSC_EXIT);
 #else
 #	error Not implemented yet...
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/head.S linux-2.5.69-bk7/arch/ia64/kernel/head.S
--- linux-2.5.69-bk6/arch/ia64/kernel/head.S	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/head.S	2003-05-12 04:43:29.000000000 -0700
@@ -733,3 +733,82 @@
 SET_REG(b5);
 
 #endif /* CONFIG_IA64_BRL_EMU */
+
+#ifdef CONFIG_SMP
+	/*
+	 * This routine handles spinlock contention.  It uses a non-standard calling
+	 * convention to avoid converting leaf routines into interior routines.  Because
+	 * of this special convention, there are several restrictions:
+	 *
+	 * - do not use gp relative variables, this code is called from the kernel
+	 *   and from modules, r1 is undefined.
+	 * - do not use stacked registers, the caller owns them.
+	 * - do not use the scratch stack space, the caller owns it.
+	 * - do not use any registers other than the ones listed below
+	 *
+	 * Inputs:
+	 *   ar.pfs - saved CFM of caller
+	 *   ar.ccv - 0 (and available for use)
+	 *   r28    - available for use.
+	 *   r29    - available for use.
+	 *   r30    - available for use.
+	 *   r31    - address of lock, available for use.
+	 *   b7     - return address
+	 *   p14    - available for use.
+	 *
+	 * If you patch this code to use more registers, do not forget to update
+	 * the clobber lists for spin_lock() in include/asm-ia64/spinlock.h.
+	 */
+
+#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
+
+GLOBAL_ENTRY(ia64_spinlock_contention_pre3_4)
+	.prologue
+	.save ar.pfs, r0	// this code effectively has a zero frame size
+	.save rp, r28
+	.body
+	nop 0
+	nop 0
+	.restore sp		// pop existing prologue after next insn
+	mov b6 = r28
+	.prologue
+	.save ar.pfs, r0
+	.altrp b6
+	.body
+.wait:
+	// exponential backoff, kdb, lockmeter etc. go in here
+	hint @pause
+	ld4.bias r30=[r31]
+	nop 0
+	;;
+	cmp4.eq p14,p0=r30,r0
+(p14)	br.cond.sptk.few b6	// lock is now free, try to acquire
+	br.cond.sptk.few .wait
+END(ia64_spinlock_contention_pre3_4)
+
+#else
+
+GLOBAL_ENTRY(ia64_spinlock_contention)
+	.prologue
+	.altrp b6
+	.body
+.wait:
+	// exponential backoff, kdb, lockmeter etc. go in here
+	hint @pause
+	ld4.bias r30=[r31]
+	;;
+	cmp4.ne p14,p0=r30,r0
+	mov r30 = 1
+(p14)	br.cond.sptk.few .wait
+	;;
+	cmpxchg4.acq r30=[r31], r30, ar.ccv
+	;;
+	cmp4.ne p14,p0=r0,r30
+(p14)	br.cond.sptk.few .wait
+
+	br.ret.sptk.many b6	// lock is now taken
+END(ia64_spinlock_contention)
+
+#endif
+
+#endif /* CONFIG_SMP */
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/ia64_ksyms.c linux-2.5.69-bk7/arch/ia64/kernel/ia64_ksyms.c
--- linux-2.5.69-bk6/arch/ia64/kernel/ia64_ksyms.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/ia64_ksyms.c	2003-05-12 04:43:29.000000000 -0700
@@ -46,6 +46,7 @@
 EXPORT_SYMBOL(__ia64_memcpy_fromio);
 EXPORT_SYMBOL(__ia64_memcpy_toio);
 EXPORT_SYMBOL(__ia64_memset_c_io);
+EXPORT_SYMBOL(io_space);
 
 #include <asm/semaphore.h>
 EXPORT_SYMBOL_NOVERS(__down);
@@ -56,6 +57,12 @@
 #include <asm/page.h>
 EXPORT_SYMBOL(clear_page);
 
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+#include <asm/pgtable.h>
+EXPORT_SYMBOL(vmalloc_end);
+EXPORT_SYMBOL(ia64_pfn_valid);
+#endif
+
 #include <asm/processor.h>
 EXPORT_SYMBOL(cpu_info__per_cpu);
 EXPORT_SYMBOL(kernel_thread);
@@ -161,3 +168,11 @@
 EXPORT_SYMBOL(unw_access_fr);
 EXPORT_SYMBOL(unw_access_ar);
 EXPORT_SYMBOL(unw_access_pr);
+
+#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
+extern void ia64_spinlock_contention_pre3_4 (void);
+EXPORT_SYMBOL(ia64_spinlock_contention_pre3_4);
+#else
+extern void ia64_spinlock_contention (void);
+EXPORT_SYMBOL(ia64_spinlock_contention);
+#endif
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/iosapic.c linux-2.5.69-bk7/arch/ia64/kernel/iosapic.c
--- linux-2.5.69-bk6/arch/ia64/kernel/iosapic.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/iosapic.c	2003-05-12 04:43:29.000000000 -0700
@@ -581,9 +581,8 @@
 	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 == IOSAPIC_POL_HIGH ? "high" : "low", trigger == IOSAPIC_EDGE ? "edge" : "level",
-	    dest, vector);
+	    isa_irq, gsi, polarity == IOSAPIC_POL_HIGH ? "high" : "low",
+	    trigger == IOSAPIC_EDGE ? "edge" : "level", dest, vector);
 
 	/* program the IOSAPIC routing table */
 	set_rte(vector, dest);
@@ -635,7 +634,6 @@
 	       (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1);
 
 	if ((gsi_base == 0) && pcat_compat) {
-
 		/*
 		 * Map the legacy ISA devices into the IOSAPIC data.  Some of these may
 		 * get reprogrammed later on with data from the ACPI Interrupt Source
@@ -646,20 +644,11 @@
 	}
 }
 
-static void __init
-fixup_vector (int vector, unsigned int gsi, const char *pci_id)
+void
+iosapic_enable_intr (unsigned int vector)
 {
-	struct hw_interrupt_type *irq_type = &irq_type_iosapic_level;
-	irq_desc_t *idesc;
 	unsigned int dest;
 
-	idesc = irq_desc(vector);
-	if (idesc->handler != irq_type) {
-		if (idesc->handler != &no_irq_type)
-			printk(KERN_INFO "IOSAPIC: changing vector %d from %s to %s\n",
-			       vector, idesc->handler->typename, irq_type->typename);
-		idesc->handler = irq_type;
-	}
 #ifdef CONFIG_SMP
 	/*
 	 * For platforms that do not support interrupt redirect via the XTP interface, we
@@ -687,10 +676,12 @@
 #endif
 	set_rte(vector, dest);
 
-	printk(KERN_INFO "IOSAPIC: %s -> GSI 0x%x -> CPU 0x%04x vector %d\n",
-	       pci_id, gsi, dest, vector);
+	printk(KERN_INFO "IOSAPIC: vector %d -> CPU 0x%04x, enabled\n",
+	       vector, dest);
 }
 
+#ifdef CONFIG_ACPI_PCI
+
 void __init
 iosapic_parse_prt (void)
 {
@@ -699,6 +690,8 @@
 	unsigned int gsi;
 	int vector;
 	char pci_id[16];
+	struct hw_interrupt_type *irq_type = &irq_type_iosapic_level;
+	irq_desc_t *idesc;
 
 	list_for_each(node, &acpi_prt.entries) {
 		entry = list_entry(node, struct acpi_prt_entry, node);
@@ -711,6 +704,9 @@
 
 		vector = gsi_to_vector(gsi);
 		if (vector < 0) {
+			if (find_iosapic(gsi) < 0)
+				continue;
+
 			/* allocate a vector for this interrupt line */
 			if (pcat_compat && (gsi < 16))
 				vector = isa_irq_to_vector(gsi);
@@ -718,11 +714,22 @@
 				/* new GSI; allocate a vector for it */
 				vector = ia64_alloc_vector();
 
-			register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, IOSAPIC_LEVEL);
+			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);
 
-		fixup_vector(vector, gsi, pci_id);
+		/*
+		 * If vector was previously initialized to a different
+		 * handler, re-initialize.
+		 */
+		idesc = irq_desc(vector);
+		if (idesc->handler != irq_type)
+			register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW,
+				      IOSAPIC_LEVEL);
+
 	}
 }
+
+#endif /* CONFIG_ACPI */
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/irq.c linux-2.5.69-bk7/arch/ia64/kernel/irq.c
--- linux-2.5.69-bk6/arch/ia64/kernel/irq.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/irq.c	2003-05-12 04:43:29.000000000 -0700
@@ -18,7 +18,6 @@
  */
 
 #include <linux/config.h>
-#include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -33,6 +32,7 @@
 #include <linux/irq.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/kallsyms.h>
 
 #include <asm/atomic.h>
 #include <asm/io.h>
@@ -50,7 +50,7 @@
  * Linux has a controller-independent x86 interrupt architecture.
  * every controller has a 'controller-template', that is used
  * by the main code to do the right thing. Each driver-visible
- * interrupt source is transparently wired to the apropriate
+ * interrupt source is transparently wired to the appropriate
  * controller. Thus drivers need not be aware of the
  * interrupt-controller.
  *
@@ -91,7 +91,8 @@
  * Special irq handlers.
  */
 
-void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
+{ return IRQ_NONE; }
 
 /*
  * Generic no controller code
@@ -141,9 +142,11 @@
 };
 
 atomic_t irq_err_count;
-#if defined(CONFIG_X86) && defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG)
+#ifdef CONFIG_X86_IO_APIC
+#ifdef APIC_MISMATCH_DEBUG
 atomic_t irq_mis_count;
 #endif
+#endif
 
 /*
  * Generic, controller-independent functions:
@@ -178,9 +181,10 @@
 #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);
@@ -190,17 +194,19 @@
 		if (cpu_online(j))
 			seq_printf(p, "%10u ", nmi_count(j));
 	seq_putc(p, '\n');
-#if defined(CONFIG_SMP) && defined(CONFIG_X86)
+#if CONFIG_X86_LOCAL_APIC
 	seq_puts(p, "LOC: ");
 	for (j = 0; j < NR_CPUS; j++)
 		if (cpu_online(j))
-			seq_printf(p, "%10u ", apic_timer_irqs[j]);
+			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));
-#if defined(CONFIG_X86) && defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG)
+#ifdef CONFIG_X86_IO_APIC
+#ifdef APIC_MISMATCH_DEBUG
 	seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
 #endif
+#endif
 	return 0;
 }
 
@@ -219,21 +225,46 @@
  * waste of time and is not what some drivers would
  * prefer.
  */
-int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
+int handle_IRQ_event(unsigned int irq,
+		struct pt_regs *regs, struct irqaction *action)
 {
 	int status = 1;	/* Force the "do bottom halves" bit */
+	int retval = 0;
+	struct irqaction *first_action = action;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
 		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		retval |= action->handler(irq, action->dev_id, regs);
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
 		add_interrupt_randomness(irq);
 	local_irq_disable();
+	if (retval != 1) {
+		static int count = 100;
+		if (count) {
+			count--;
+			if (retval) {
+				printk("irq event %d: bogus retval mask %x\n",
+					irq, retval);
+			} else {
+				printk("irq %d: nobody cared!\n", irq);
+			}
+			dump_stack();
+			printk("handlers:\n");
+			action = first_action;
+			do {
+				printk("[<%p>]", action->handler);
+				print_symbol(" (%s)",
+					(unsigned long)action->handler);
+				printk("\n");
+				action = action->next;
+			} while (action);
+		}
+	}
 
 	return status;
 }
@@ -455,7 +486,7 @@
  */
 
 int request_irq(unsigned int irq,
-		void (*handler)(int, void *, struct pt_regs *),
+		irqreturn_t (*handler)(int, void *, struct pt_regs *),
 		unsigned long irqflags,
 		const char * devname,
 		void *dev_id)
@@ -482,7 +513,7 @@
 		return -EINVAL;
 
 	action = (struct irqaction *)
-			kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+			kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
 	if (!action)
 		return -ENOMEM;
 
@@ -511,10 +542,7 @@
  *	does not return until any executing interrupts for this IRQ
  *	have completed.
  *
- *	This function may be called from interrupt context. 
- *
- *	Bugs: Attempting to free an irq in a handler for the same irq hangs
- *	      the machine.
+ *	This function must not be called from interrupt context.
  */
 
 void free_irq(unsigned int irq, void *dev_id)
@@ -545,11 +573,8 @@
 			}
 			spin_unlock_irqrestore(&desc->lock,flags);
 
-#ifdef CONFIG_SMP
 			/* Wait to make sure it's not being used on another CPU */
-			while (desc->status & IRQ_INPROGRESS)
-				synchronize_irq(irq);
-#endif
+			synchronize_irq(irq);
 			kfree(action);
 			return;
 		}
@@ -664,7 +689,6 @@
  *	only return ISA irq numbers - just so that we reset them
  *	all to a known state.
  */
-
 unsigned int probe_irq_mask(unsigned long val)
 {
 	int i;
@@ -705,7 +729,7 @@
  *	The interrupt probe logic state is returned to its previous
  *	value.
  *
- *	BUGS: When used in a module (which arguably shouldnt happen)
+ *	BUGS: When used in a module (which arguably shouldn't happen)
  *	nothing prevents two IRQ probe callers from overlapping. The
  *	results of this are non-optimal.
  */
@@ -748,6 +772,8 @@
 	struct irqaction *old, **p;
 	irq_desc_t *desc = irq_desc(irq);
 
+	if (desc->handler == &no_irq_type)
+		return -ENOSYS;
 	/*
 	 * Some drivers like serial.c use request_irq() heavily,
 	 * so we have to be careful not to interfere with a
@@ -808,11 +834,11 @@
 
 #define HEX_DIGITS 8
 
-static int parse_hex_value (const char *buffer, unsigned long count, unsigned long *ret)
+static unsigned int parse_hex_value (const char *buffer,
+		unsigned long count, unsigned long *ret)
 {
 	unsigned char hexnum [HEX_DIGITS];
-	unsigned long value;
-	int i;
+	unsigned long value, i;
 
 	if (!count)
 		return -EINVAL;
@@ -950,12 +976,13 @@
 #if CONFIG_SMP
 	{
 		struct proc_dir_entry *entry;
+
 		/* create /proc/irq/1234/smp_affinity */
 		entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
 
 		if (entry) {
 			entry->nlink = 1;
-			entry->data = (void *)(unsigned long)irq;
+			entry->data = (void *)(long)irq;
 			entry->read_proc = irq_affinity_read_proc;
 			entry->write_proc = irq_affinity_write_proc;
 		}
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/irq_ia64.c linux-2.5.69-bk7/arch/ia64/kernel/irq_ia64.c
--- linux-2.5.69-bk6/arch/ia64/kernel/irq_ia64.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/irq_ia64.c	2003-05-12 04:43:29.000000000 -0700
@@ -145,7 +145,7 @@
 }
 
 #ifdef CONFIG_SMP
-extern void handle_IPI (int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t handle_IPI (int irq, void *dev_id, struct pt_regs *regs);
 
 static struct irqaction ipi_irqaction = {
 	.handler =	handle_IPI,
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/machvec.c linux-2.5.69-bk7/arch/ia64/kernel/machvec.c
--- linux-2.5.69-bk6/arch/ia64/kernel/machvec.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/machvec.c	2003-05-12 04:43:29.000000000 -0700
@@ -1,12 +1,14 @@
 #include <linux/config.h>
 
+#include <asm/system.h>
+
 #ifdef CONFIG_IA64_GENERIC
 
 #include <linux/kernel.h>
 #include <linux/string.h>
 
-#include <asm/page.h>
 #include <asm/machvec.h>
+#include <asm/page.h>
 
 struct ia64_machine_vector ia64_mv;
 
@@ -43,3 +45,9 @@
 machvec_noop (void)
 {
 }
+
+void
+machvec_memory_fence (void)
+{
+	mb();
+}
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/mca.c linux-2.5.69-bk7/arch/ia64/kernel/mca.c
--- linux-2.5.69-bk6/arch/ia64/kernel/mca.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/mca.c	2003-05-12 04:43:29.000000000 -0700
@@ -3,6 +3,9 @@
  * Purpose:	Generic MCA handling layer
  *
  * Updated for latest kernel
+ * Copyright (C) 2003 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
+ *
  * Copyright (C) 2002 Dell Computer Corporation
  * Copyright (C) Matt Domsch (Matt_Domsch@dell.com)
  *
@@ -18,6 +21,7 @@
  * Copyright (C) 1999 Silicon Graphics, Inc.
  * Copyright (C) Vijay Chander(vijay@engr.sgi.com)
  *
+ * 03/04/15 D. Mosberger Added INIT backtrace support.
  * 02/03/25 M. Domsch	GUID cleanups
  *
  * 02/01/04 J. Hall	Aligned MCA stack to 16 bytes, added platform vs. CPU
@@ -39,6 +43,7 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/kallsyms.h>
 #include <linux/smp_lock.h>
 #include <linux/bootmem.h>
 #include <linux/acpi.h>
@@ -47,6 +52,7 @@
 #include <linux/kernel.h>
 #include <linux/smp.h>
 
+#include <asm/delay.h>
 #include <asm/machvec.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
@@ -139,7 +145,7 @@
 
 	/* Get the MCA error record */
 	if (!ia64_log_get(sal_info_type, (prfunc_t)printk))
-		return platform_err;                 // no record retrieved
+		return platform_err;		/* no record retrieved */
 
 	/* TODO:
 	 * 1. analyze error logs to determine recoverability
@@ -166,7 +172,7 @@
 
 }
 
-void
+irqreturn_t
 ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
 {
 	IA64_MCA_DEBUG("ia64_mca_cpe_int_handler: received interrupt. CPU:%d vector = %#x\n",
@@ -174,20 +180,186 @@
 
 	/* Get the CMC error record and log it */
 	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE, 0);
+	return IRQ_HANDLED;
+}
+
+static void
+show_min_state (pal_min_state_area_t *minstate)
+{
+	u64 iip = minstate->pmsa_iip + ((struct ia64_psr *)(&minstate->pmsa_ipsr))->ri;
+	u64 xip = minstate->pmsa_xip + ((struct ia64_psr *)(&minstate->pmsa_xpsr))->ri;
+
+	printk("NaT bits\t%016lx\n", minstate->pmsa_nat_bits);
+	printk("pr\t\t%016lx\n", minstate->pmsa_pr);
+	printk("b0\t\t%016lx ", minstate->pmsa_br0); print_symbol("%s\n", minstate->pmsa_br0);
+	printk("ar.rsc\t\t%016lx\n", minstate->pmsa_rsc);
+	printk("cr.iip\t\t%016lx ", iip); print_symbol("%s\n", iip);
+	printk("cr.ipsr\t\t%016lx\n", minstate->pmsa_ipsr);
+	printk("cr.ifs\t\t%016lx\n", minstate->pmsa_ifs);
+	printk("xip\t\t%016lx ", xip); print_symbol("%s\n", xip);
+	printk("xpsr\t\t%016lx\n", minstate->pmsa_xpsr);
+	printk("xfs\t\t%016lx\n", minstate->pmsa_xfs);
+	printk("b1\t\t%016lx ", minstate->pmsa_br1);
+	print_symbol("%s\n", minstate->pmsa_br1);
+
+	printk("\nstatic registers r0-r15:\n");
+	printk(" r0- 3 %016lx %016lx %016lx %016lx\n",
+	       0UL, minstate->pmsa_gr[0], minstate->pmsa_gr[1], minstate->pmsa_gr[2]);
+	printk(" r4- 7 %016lx %016lx %016lx %016lx\n",
+	       minstate->pmsa_gr[3], minstate->pmsa_gr[4],
+	       minstate->pmsa_gr[5], minstate->pmsa_gr[6]);
+	printk(" r8-11 %016lx %016lx %016lx %016lx\n",
+	       minstate->pmsa_gr[7], minstate->pmsa_gr[8],
+	       minstate->pmsa_gr[9], minstate->pmsa_gr[10]);
+	printk("r12-15 %016lx %016lx %016lx %016lx\n",
+	       minstate->pmsa_gr[11], minstate->pmsa_gr[12],
+	       minstate->pmsa_gr[13], minstate->pmsa_gr[14]);
+
+	printk("\nbank 0:\n");
+	printk("r16-19 %016lx %016lx %016lx %016lx\n",
+	       minstate->pmsa_bank0_gr[0], minstate->pmsa_bank0_gr[1],
+	       minstate->pmsa_bank0_gr[2], minstate->pmsa_bank0_gr[3]);
+	printk("r20-23 %016lx %016lx %016lx %016lx\n",
+	       minstate->pmsa_bank0_gr[4], minstate->pmsa_bank0_gr[5],
+	       minstate->pmsa_bank0_gr[6], minstate->pmsa_bank0_gr[7]);
+	printk("r24-27 %016lx %016lx %016lx %016lx\n",
+	       minstate->pmsa_bank0_gr[8], minstate->pmsa_bank0_gr[9],
+	       minstate->pmsa_bank0_gr[10], minstate->pmsa_bank0_gr[11]);
+	printk("r28-31 %016lx %016lx %016lx %016lx\n",
+	       minstate->pmsa_bank0_gr[12], minstate->pmsa_bank0_gr[13],
+	       minstate->pmsa_bank0_gr[14], minstate->pmsa_bank0_gr[15]);
+
+	printk("\nbank 1:\n");
+	printk("r16-19 %016lx %016lx %016lx %016lx\n",
+	       minstate->pmsa_bank1_gr[0], minstate->pmsa_bank1_gr[1],
+	       minstate->pmsa_bank1_gr[2], minstate->pmsa_bank1_gr[3]);
+	printk("r20-23 %016lx %016lx %016lx %016lx\n",
+	       minstate->pmsa_bank1_gr[4], minstate->pmsa_bank1_gr[5],
+	       minstate->pmsa_bank1_gr[6], minstate->pmsa_bank1_gr[7]);
+	printk("r24-27 %016lx %016lx %016lx %016lx\n",
+	       minstate->pmsa_bank1_gr[8], minstate->pmsa_bank1_gr[9],
+	       minstate->pmsa_bank1_gr[10], minstate->pmsa_bank1_gr[11]);
+	printk("r28-31 %016lx %016lx %016lx %016lx\n",
+	       minstate->pmsa_bank1_gr[12], minstate->pmsa_bank1_gr[13],
+	       minstate->pmsa_bank1_gr[14], minstate->pmsa_bank1_gr[15]);
+}
+
+static void
+fetch_min_state (pal_min_state_area_t *ms, struct pt_regs *pt, struct switch_stack *sw)
+{
+	u64 *dst_banked, *src_banked, bit, shift, nat_bits;
+	int i;
+
+	/*
+	 * First, update the pt-regs and switch-stack structures with the contents stored
+	 * in the min-state area:
+	 */
+	if (((struct ia64_psr *) &ms->pmsa_ipsr)->ic == 0) {
+		pt->cr_ipsr = ms->pmsa_xpsr;
+		pt->cr_iip = ms->pmsa_xip;
+		pt->cr_ifs = ms->pmsa_xfs;
+	} else {
+		pt->cr_ipsr = ms->pmsa_ipsr;
+		pt->cr_iip = ms->pmsa_iip;
+		pt->cr_ifs = ms->pmsa_ifs;
+	}
+	pt->ar_rsc = ms->pmsa_rsc;
+	pt->pr = ms->pmsa_pr;
+	pt->r1 = ms->pmsa_gr[0];
+	pt->r2 = ms->pmsa_gr[1];
+	pt->r3 = ms->pmsa_gr[2];
+	sw->r4 = ms->pmsa_gr[3];
+	sw->r5 = ms->pmsa_gr[4];
+	sw->r6 = ms->pmsa_gr[5];
+	sw->r7 = ms->pmsa_gr[6];
+	pt->r8 = ms->pmsa_gr[7];
+	pt->r9 = ms->pmsa_gr[8];
+	pt->r10 = ms->pmsa_gr[9];
+	pt->r11 = ms->pmsa_gr[10];
+	pt->r12 = ms->pmsa_gr[11];
+	pt->r13 = ms->pmsa_gr[12];
+	pt->r14 = ms->pmsa_gr[13];
+	pt->r15 = ms->pmsa_gr[14];
+	dst_banked = &pt->r16;		/* r16-r31 are contiguous in struct pt_regs */
+	src_banked = ms->pmsa_bank1_gr;
+	for (i = 0; i < 16; ++i)
+		dst_banked[i] = src_banked[i];
+	pt->b0 = ms->pmsa_br0;
+	sw->b1 = ms->pmsa_br1;
+
+	/* construct the NaT bits for the pt-regs structure: */
+#	define PUT_NAT_BIT(dst, addr)					\
+	do {								\
+		bit = nat_bits & 1; nat_bits >>= 1;			\
+		shift = ((unsigned long) addr >> 3) & 0x3f;		\
+		dst = ((dst) & ~(1UL << shift)) | (bit << shift);	\
+	} while (0)
+
+	/* Rotate the saved NaT bits such that bit 0 corresponds to pmsa_gr[0]: */
+	shift = ((unsigned long) &ms->pmsa_gr[0] >> 3) & 0x3f;
+	nat_bits = (ms->pmsa_nat_bits >> shift) | (ms->pmsa_nat_bits << (64 - shift));
+
+	PUT_NAT_BIT(sw->caller_unat, &pt->r1);
+	PUT_NAT_BIT(sw->caller_unat, &pt->r2);
+	PUT_NAT_BIT(sw->caller_unat, &pt->r3);
+	PUT_NAT_BIT(sw->ar_unat, &sw->r4);
+	PUT_NAT_BIT(sw->ar_unat, &sw->r5);
+	PUT_NAT_BIT(sw->ar_unat, &sw->r6);
+	PUT_NAT_BIT(sw->ar_unat, &sw->r7);
+	PUT_NAT_BIT(sw->caller_unat, &pt->r8);	PUT_NAT_BIT(sw->caller_unat, &pt->r9);
+	PUT_NAT_BIT(sw->caller_unat, &pt->r10);	PUT_NAT_BIT(sw->caller_unat, &pt->r11);
+	PUT_NAT_BIT(sw->caller_unat, &pt->r12);	PUT_NAT_BIT(sw->caller_unat, &pt->r13);
+	PUT_NAT_BIT(sw->caller_unat, &pt->r14);	PUT_NAT_BIT(sw->caller_unat, &pt->r15);
+	nat_bits >>= 16;	/* skip over bank0 NaT bits */
+	PUT_NAT_BIT(sw->caller_unat, &pt->r16);	PUT_NAT_BIT(sw->caller_unat, &pt->r17);
+	PUT_NAT_BIT(sw->caller_unat, &pt->r18);	PUT_NAT_BIT(sw->caller_unat, &pt->r19);
+	PUT_NAT_BIT(sw->caller_unat, &pt->r20);	PUT_NAT_BIT(sw->caller_unat, &pt->r21);
+	PUT_NAT_BIT(sw->caller_unat, &pt->r22);	PUT_NAT_BIT(sw->caller_unat, &pt->r23);
+	PUT_NAT_BIT(sw->caller_unat, &pt->r24);	PUT_NAT_BIT(sw->caller_unat, &pt->r25);
+	PUT_NAT_BIT(sw->caller_unat, &pt->r26);	PUT_NAT_BIT(sw->caller_unat, &pt->r27);
+	PUT_NAT_BIT(sw->caller_unat, &pt->r28);	PUT_NAT_BIT(sw->caller_unat, &pt->r29);
+	PUT_NAT_BIT(sw->caller_unat, &pt->r30);	PUT_NAT_BIT(sw->caller_unat, &pt->r31);
 }
 
-/*
- * This routine will be used to deal with platform specific handling
- * of the init, i.e. drop into the kernel debugger on server machine,
- * or if the processor is part of some parallel machine without a
- * console, then we would call the appropriate debug hooks here.
- */
 void
-init_handler_platform (struct pt_regs *regs)
+init_handler_platform (sal_log_processor_info_t *proc_ptr,
+		       struct pt_regs *pt, struct switch_stack *sw)
 {
+	struct unw_frame_info info;
+
 	/* if a kernel debugger is available call it here else just dump the registers */
 
-	show_regs(regs);		/* dump the state info */
+	/*
+	 * Wait for a bit.  On some machines (e.g., HP's zx2000 and zx6000, INIT can be
+	 * generated via the BMC's command-line interface, but since the console is on the
+	 * same serial line, the user will need some time to switch out of the BMC before
+	 * the dump begins.
+	 */
+	printk("Delaying for 5 seconds...\n");
+	udelay(5*1000000);
+	show_min_state(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area);
+
+	printk("Backtrace of current task (pid %d, %s)\n", current->pid, current->comm);
+	fetch_min_state(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area, pt, sw);
+	unw_init_from_interruption(&info, current, pt, sw);
+	ia64_do_show_stack(&info, NULL);
+
+	if (!tasklist_lock.write_lock)
+		read_lock(&tasklist_lock);
+	{
+		struct task_struct *g, *t;
+		do_each_thread (g, t) {
+			if (t == current)
+				continue;
+
+			printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm);
+			show_stack(t);
+		} while_each_thread (g, t);
+	}
+	if (!tasklist_lock.write_lock)
+		read_unlock(&tasklist_lock);
+
+	printk("\nINIT dump complete.  Please reboot now.\n");
 	while (1);			/* hang city if no debugger */
 }
 
@@ -263,7 +435,6 @@
 /*
  * routine to process and prepare to dump min_state_save
  * information for debugging purposes.
- *
  */
 void
 ia64_process_min_state_save (pal_min_state_area_t *pmss)
@@ -272,8 +443,6 @@
 	u64 *tpmss_ptr = (u64 *)pmss;
 	u64 *return_min_state_ptr = ia64_mca_min_state_save_info;
 
-	/* dump out the min_state_area information */
-
 	for (i=0;i<max;i++) {
 
 		/* copy min-state register info for eventual return to PAL */
@@ -676,7 +845,7 @@
  *  Inputs  :   None
  *  Outputs :   None
  */
-void
+irqreturn_t
 ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs)
 {
 	unsigned long flags;
@@ -699,6 +868,7 @@
 
 	/* Enable all interrupts */
 	local_irq_restore(flags);
+	return IRQ_HANDLED;
 }
 
 
@@ -717,10 +887,10 @@
  *  Outputs :   None
  *
  */
-void
+irqreturn_t
 ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg, struct pt_regs *ptregs)
 {
-
+	return IRQ_HANDLED;
 }
 
 /*
@@ -815,7 +985,7 @@
  * Outputs
  *	None
  */
-void
+irqreturn_t
 ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
 {
 	static unsigned long	cmc_history[CMC_HISTORY_LENGTH];
@@ -832,7 +1002,7 @@
 	if (!cmc_polling_enabled) {
 		int i, count = 1; /* we know 1 happened now */
 		unsigned long now = jiffies;
-		
+
 		for (i = 0; i < CMC_HISTORY_LENGTH; i++) {
 			if (now - cmc_history[i] <= HZ)
 				count++;
@@ -867,12 +1037,12 @@
 			 * something is generating more than we can handle.
 			 */
 			printk(KERN_WARNING "ia64_mca_cmc_int_handler: WARNING: Switching to polling CMC handler, error records may be lost\n");
-			
+
 
 			mod_timer(&cmc_poll_timer, jiffies + CMC_POLL_INTERVAL);
 
 			/* lock already released, get out now */
-			return;
+			return IRQ_HANDLED;
 		} else {
 			cmc_history[index++] = now;
 			if (index == CMC_HISTORY_LENGTH)
@@ -880,6 +1050,7 @@
 		}
 	}
 	spin_unlock(&cmc_history_lock);
+	return IRQ_HANDLED;
 }
 
 /*
@@ -944,7 +1115,7 @@
 static void
 ia64_mca_cmc_poll (unsigned long dummy)
 {
-	int start_count;
+	unsigned long start_count;
 
 	start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CMC);
 
@@ -986,7 +1157,7 @@
  *  ia64_mca_cpe_poll
  *
  *	Poll for Corrected Platform Errors (CPEs), dynamically adjust
- *	polling interval based on occurance of an event.
+ *	polling interval based on occurrence of an event.
  *
  * Inputs   :   dummy(unused)
  * Outputs  :   None
@@ -995,7 +1166,7 @@
 static void
 ia64_mca_cpe_poll (unsigned long dummy)
 {
-	int start_count;
+	unsigned long start_count;
 	static int poll_time = MAX_CPE_POLL_INTERVAL;
 
 	start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CPE);
@@ -1062,7 +1233,7 @@
  *
  */
 void
-ia64_init_handler (struct pt_regs *regs)
+ia64_init_handler (struct pt_regs *pt, struct switch_stack *sw)
 {
 	sal_log_processor_info_t *proc_ptr;
 	ia64_err_rec_t *plog_ptr;
@@ -1089,7 +1260,7 @@
 	/* Clear the INIT SAL logs now that they have been saved in the OS buffer */
 	ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT);
 
-	init_handler_platform(regs);              /* call platform specific routines */
+	init_handler_platform(proc_ptr, pt, sw);	/* call platform specific routines */
 }
 
 /*
@@ -1112,7 +1283,8 @@
 static void
 ia64_log_hexdump(unsigned char *p, unsigned long n_ch, prfunc_t prfunc)
 {
-	int i, j;
+	unsigned long i;
+	int j;
 
 	if (!p)
 		return;
@@ -1960,7 +2132,7 @@
 {
 	sal_log_section_hdr_t       *slsh;
 	int                         n_sects;
-	int                         ercd_pos;
+	u32                         ercd_pos;
 
 	if (!lh)
 		return;
@@ -2022,7 +2194,7 @@
 {
 	sal_log_section_hdr_t	*slsh;
 	int			n_sects;
-	int			ercd_pos;
+	u32			ercd_pos;
 	int			platform_err = 0;
 
 	if (!lh)
@@ -2139,7 +2311,8 @@
 	switch(sal_info_type) {
 	      case SAL_INFO_TYPE_MCA:
 		prfunc("+BEGIN HARDWARE ERROR STATE AT MCA\n");
-		platform_err = ia64_log_platform_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
+		platform_err = ia64_log_platform_info_print(IA64_LOG_CURR_BUFFER(sal_info_type),
+							    prfunc);
 		prfunc("+END HARDWARE ERROR STATE AT MCA\n");
 		break;
 	      case SAL_INFO_TYPE_INIT:
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/mca_asm.S linux-2.5.69-bk7/arch/ia64/kernel/mca_asm.S
--- linux-2.5.69-bk6/arch/ia64/kernel/mca_asm.S	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/mca_asm.S	2003-05-12 04:43:29.000000000 -0700
@@ -766,8 +766,6 @@
 	// stash the information the SAL passed to os
 	SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)
 	;;
-
-// now we want to save information so we can dump registers
 	SAVE_MIN_WITH_COVER
 	;;
 	mov r8=cr.ifa
@@ -798,10 +796,12 @@
 	//
 	// Let's call the C handler to get the rest of the state info
 	//
-	alloc r14=ar.pfs,0,0,1,0		// now it's safe (must be first in insn group!)
-	;;					//
+	alloc r14=ar.pfs,0,0,2,0		// now it's safe (must be first in insn group!)
+	;;
 	adds out0=16,sp				// out0 = pointer to pt_regs
 	;;
+	DO_SAVE_SWITCH_STACK
+	adds out1=16,sp				// out0 = pointer to switch_stack
 
 	br.call.sptk.many rp=ia64_init_handler
 .ret1:
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/palinfo.c linux-2.5.69-bk7/arch/ia64/kernel/palinfo.c
--- linux-2.5.69-bk6/arch/ia64/kernel/palinfo.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/palinfo.c	2003-05-12 04:43:29.000000000 -0700
@@ -91,7 +91,7 @@
 	"eager loads and stores"
 };
 
-#define RSE_HINTS_COUNT (sizeof(rse_hints)/sizeof(const char *))
+#define RSE_HINTS_COUNT ARRAY_SIZE(rse_hints)
 
 static const char *mem_attrib[]={
 	"WB",		/* 000 */
@@ -192,15 +192,15 @@
 
 	for (i=0; i < 8 ; i++ ) {
 		if (halt_info[i].pal_power_mgmt_info_s.im == 1) {
-			p += sprintf(p,	"Power level %d:\n" \
-					"\tentry_latency       : %d cycles\n" \
-					"\texit_latency        : %d cycles\n" \
-					"\tpower consumption   : %d mW\n" \
-					"\tCache+TLB coherency : %s\n", i,
-				halt_info[i].pal_power_mgmt_info_s.entry_latency,
-				halt_info[i].pal_power_mgmt_info_s.exit_latency,
-				halt_info[i].pal_power_mgmt_info_s.power_consumption,
-				halt_info[i].pal_power_mgmt_info_s.co ? "Yes" : "No");
+			p += sprintf(p,	"Power level %d:\n"
+				     "\tentry_latency       : %d cycles\n"
+				     "\texit_latency        : %d cycles\n"
+				     "\tpower consumption   : %d mW\n"
+				     "\tCache+TLB coherency : %s\n", i,
+				     halt_info[i].pal_power_mgmt_info_s.entry_latency,
+				     halt_info[i].pal_power_mgmt_info_s.exit_latency,
+				     halt_info[i].pal_power_mgmt_info_s.power_consumption,
+				     halt_info[i].pal_power_mgmt_info_s.co ? "Yes" : "No");
 		} else {
 			p += sprintf(p,"Power level %d: not implemented\n",i);
 		}
@@ -212,9 +212,9 @@
 cache_info(char *page)
 {
 	char *p = page;
-	u64 levels, unique_caches;
+	u64 i, levels, unique_caches;
 	pal_cache_config_info_t cci;
-	int i,j, k;
+	int j, k;
 	s64 status;
 
 	if ((status = ia64_pal_cache_summary(&levels, &unique_caches)) != 0) {
@@ -232,48 +232,50 @@
 			if ((status=ia64_pal_cache_config_info(i,j, &cci)) != 0) {
 				continue;
 			}
-			p += sprintf(p, "%s Cache level %d:\n" \
-					"\tSize           : %ld bytes\n" \
-					"\tAttributes     : ",
-					cache_types[j+cci.pcci_unified], i+1,
-					cci.pcci_cache_size);
+			p += sprintf(p,
+				     "%s Cache level %lu:\n"
+				     "\tSize           : %lu bytes\n"
+				     "\tAttributes     : ",
+				     cache_types[j+cci.pcci_unified], i+1,
+				     cci.pcci_cache_size);
 
 			if (cci.pcci_unified) p += sprintf(p, "Unified ");
 
 			p += sprintf(p, "%s\n", cache_mattrib[cci.pcci_cache_attr]);
 
-			p += sprintf(p, "\tAssociativity  : %d\n" \
-					"\tLine size      : %d bytes\n" \
-					"\tStride         : %d bytes\n",
-					cci.pcci_assoc,
-					1<<cci.pcci_line_size,
-					1<<cci.pcci_stride);
+			p += sprintf(p,
+				     "\tAssociativity  : %d\n"
+				     "\tLine size      : %d bytes\n"
+				     "\tStride         : %d bytes\n",
+				     cci.pcci_assoc, 1<<cci.pcci_line_size, 1<<cci.pcci_stride);
 			if (j == 1)
 				p += sprintf(p, "\tStore latency  : N/A\n");
 			else
 				p += sprintf(p, "\tStore latency  : %d cycle(s)\n",
 						cci.pcci_st_latency);
 
-			p += sprintf(p, "\tLoad latency   : %d cycle(s)\n" \
-					"\tStore hints    : ",
-					cci.pcci_ld_latency);
+			p += sprintf(p,
+				     "\tLoad latency   : %d cycle(s)\n"
+				     "\tStore hints    : ", cci.pcci_ld_latency);
 
 			for(k=0; k < 8; k++ ) {
-				if ( cci.pcci_st_hints & 0x1) p += sprintf(p, "[%s]", cache_st_hints[k]);
+				if ( cci.pcci_st_hints & 0x1)
+					p += sprintf(p, "[%s]", cache_st_hints[k]);
 				cci.pcci_st_hints >>=1;
 			}
 			p += sprintf(p, "\n\tLoad hints     : ");
 
 			for(k=0; k < 8; k++ ) {
-				if ( cci.pcci_ld_hints & 0x1) p += sprintf(p, "[%s]", cache_ld_hints[k]);
+				if (cci.pcci_ld_hints & 0x1)
+					p += sprintf(p, "[%s]", cache_ld_hints[k]);
 				cci.pcci_ld_hints >>=1;
 			}
-			p += sprintf(p, "\n\tAlias boundary : %d byte(s)\n" \
-					"\tTag LSB        : %d\n" \
-					"\tTag MSB        : %d\n",
-					1<<cci.pcci_alias_boundary,
-					cci.pcci_tag_lsb,
-					cci.pcci_tag_msb);
+			p += sprintf(p,
+				     "\n\tAlias boundary : %d byte(s)\n"
+				     "\tTag LSB        : %d\n"
+				     "\tTag MSB        : %d\n",
+				     1<<cci.pcci_alias_boundary, cci.pcci_tag_lsb,
+				     cci.pcci_tag_msb);
 
 			/* when unified, data(j=2) is enough */
 			if (cci.pcci_unified) break;
@@ -303,20 +305,20 @@
 	}
 
 
-	p += sprintf(p, "Physical Address Space         : %d bits\n" \
-			"Virtual Address Space          : %d bits\n" \
-			"Protection Key Registers(PKR)  : %d\n" \
-			"Implemented bits in PKR.key    : %d\n" \
-			"Hash Tag ID                    : 0x%x\n" \
-			"Size of RR.rid                 : %d\n",
-			vm_info_1.pal_vm_info_1_s.phys_add_size,
-			vm_info_2.pal_vm_info_2_s.impl_va_msb+1,
-			vm_info_1.pal_vm_info_1_s.max_pkr+1,
-			vm_info_1.pal_vm_info_1_s.key_size,
-			vm_info_1.pal_vm_info_1_s.hash_tag_id,
-			vm_info_2.pal_vm_info_2_s.rid_size);
+	p += sprintf(p,
+		     "Physical Address Space         : %d bits\n"
+		     "Virtual Address Space          : %d bits\n"
+		     "Protection Key Registers(PKR)  : %d\n"
+		     "Implemented bits in PKR.key    : %d\n"
+		     "Hash Tag ID                    : 0x%x\n"
+		     "Size of RR.rid                 : %d\n",
+		     vm_info_1.pal_vm_info_1_s.phys_add_size,
+		     vm_info_2.pal_vm_info_2_s.impl_va_msb+1, vm_info_1.pal_vm_info_1_s.max_pkr+1,
+		     vm_info_1.pal_vm_info_1_s.key_size, vm_info_1.pal_vm_info_1_s.hash_tag_id,
+		     vm_info_2.pal_vm_info_2_s.rid_size);
 
-	if (ia64_pal_mem_attrib(&attrib) != 0) return 0;
+	if (ia64_pal_mem_attrib(&attrib) != 0)
+		return 0;
 
 	p += sprintf(p, "Supported memory attributes    : ");
 	sep = "";
@@ -333,13 +335,14 @@
 		return 0;
 	}
 
-	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 ? "" : "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);
+	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 ? "" : "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);
 
 
 	p = bitvector_process(p, tr_pages);
@@ -353,21 +356,19 @@
 		return 0;
 	}
 
-	p += sprintf(p, "\nPurge base address             : 0x%016lx\n" \
-			"Purge outer loop count         : %d\n" \
-			"Purge inner loop count         : %d\n" \
-			"Purge outer loop stride        : %d\n" \
-			"Purge inner loop stride        : %d\n",
-			ptce.base,
-			ptce.count[0],
-			ptce.count[1],
-			ptce.stride[0],
-			ptce.stride[1]);
-
-	p += sprintf(p, "TC Levels                      : %d\n" \
-			"Unique TC(s)                   : %d\n",
-			vm_info_1.pal_vm_info_1_s.num_tc_levels,
-			vm_info_1.pal_vm_info_1_s.max_unique_tcs);
+	p += sprintf(p,
+		     "\nPurge base address             : 0x%016lx\n"
+		     "Purge outer loop count         : %d\n"
+		     "Purge inner loop count         : %d\n"
+		     "Purge outer loop stride        : %d\n"
+		     "Purge inner loop stride        : %d\n",
+		     ptce.base, ptce.count[0], ptce.count[1], ptce.stride[0], ptce.stride[1]);
+
+	p += sprintf(p,
+		     "TC Levels                      : %d\n"
+		     "Unique TC(s)                   : %d\n",
+		     vm_info_1.pal_vm_info_1_s.num_tc_levels,
+		     vm_info_1.pal_vm_info_1_s.max_unique_tcs);
 
 	for(i=0; i < vm_info_1.pal_vm_info_1_s.num_tc_levels; i++) {
 		for (j=2; j>0 ; j--) {
@@ -379,15 +380,14 @@
 				continue;
 			}
 
-			p += sprintf(p, "\n%s Translation Cache Level %d:\n" \
-					"\tHash sets           : %d\n" \
-					"\tAssociativity       : %d\n" \
-					"\tNumber of entries   : %d\n" \
-					"\tFlags               : ",
-					cache_types[j+tc_info.tc_unified], i+1,
-					tc_info.tc_num_sets,
-					tc_info.tc_associativity,
-					tc_info.tc_num_entries);
+			p += sprintf(p,
+				     "\n%s Translation Cache Level %d:\n"
+				     "\tHash sets           : %d\n"
+				     "\tAssociativity       : %d\n"
+				     "\tNumber of entries   : %d\n"
+				     "\tFlags               : ",
+				     cache_types[j+tc_info.tc_unified], i+1, tc_info.tc_num_sets,
+				     tc_info.tc_associativity, tc_info.tc_num_entries);
 
 			if (tc_info.tc_pf) p += sprintf(p, "PreferredPageSizeOptimized ");
 			if (tc_info.tc_unified) p += sprintf(p, "Unified ");
@@ -436,17 +436,18 @@
 
 	if (ia64_pal_rse_info(&phys_stacked, &hints) != 0) return 0;
 
-	p += sprintf(p, "RSE stacked physical registers   : %ld\n" \
-			"RSE load/store hints             : %ld (%s)\n",
-			phys_stacked,
-			hints.ph_data,
-			hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(\?\?)");
-
-	if (ia64_pal_debug_info(&iregs, &dregs)) return 0;
-
-	p += sprintf(p, "Instruction debug register pairs : %ld\n" \
-			"Data debug register pairs        : %ld\n",
-			iregs, dregs);
+	p += sprintf(p,
+		     "RSE stacked physical registers   : %ld\n"
+		     "RSE load/store hints             : %ld (%s)\n",
+		     phys_stacked, hints.ph_data,
+		     hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(\?\?)");
+
+	if (ia64_pal_debug_info(&iregs, &dregs))
+		return 0;
+
+	p += sprintf(p,
+		     "Instruction debug register pairs : %ld\n"
+		     "Data debug register pairs        : %ld\n", iregs, dregs);
 
 	return p - page;
 }
@@ -563,26 +564,21 @@
 	 */
 	if (ia64_pal_version(&min_ver, &cur_ver) != 0) return 0;
 
-	p += sprintf(p, "PAL_vendor : 0x%02x (min=0x%02x)\n" \
-			"PAL_A      : %x.%x.%x (min=%x.%x.%x)\n" \
-			"PAL_B      : %x.%x.%x (min=%x.%x.%x)\n",
-			cur_ver.pal_version_s.pv_pal_vendor,
-			min_ver.pal_version_s.pv_pal_vendor,
-
-			cur_ver.pal_version_s.pv_pal_a_model>>4,
-			cur_ver.pal_version_s.pv_pal_a_model&0xf,
-			cur_ver.pal_version_s.pv_pal_a_rev,
-			min_ver.pal_version_s.pv_pal_a_model>>4,
-			min_ver.pal_version_s.pv_pal_a_model&0xf,
-			min_ver.pal_version_s.pv_pal_a_rev,
-
-			cur_ver.pal_version_s.pv_pal_b_model>>4,
-			cur_ver.pal_version_s.pv_pal_b_model&0xf,
-			cur_ver.pal_version_s.pv_pal_b_rev,
-			min_ver.pal_version_s.pv_pal_b_model>>4,
-			min_ver.pal_version_s.pv_pal_b_model&0xf,
-			min_ver.pal_version_s.pv_pal_b_rev);
-
+	p += sprintf(p,
+		     "PAL_vendor : 0x%02x (min=0x%02x)\n"
+		     "PAL_A      : %x.%x.%x (min=%x.%x.%x)\n"
+		     "PAL_B      : %x.%x.%x (min=%x.%x.%x)\n",
+		     cur_ver.pal_version_s.pv_pal_vendor, min_ver.pal_version_s.pv_pal_vendor,
+
+		     cur_ver.pal_version_s.pv_pal_a_model>>4,
+		     cur_ver.pal_version_s.pv_pal_a_model&0xf, cur_ver.pal_version_s.pv_pal_a_rev,
+		     min_ver.pal_version_s.pv_pal_a_model>>4,
+		     min_ver.pal_version_s.pv_pal_a_model&0xf, min_ver.pal_version_s.pv_pal_a_rev,
+
+		     cur_ver.pal_version_s.pv_pal_b_model>>4,
+		     cur_ver.pal_version_s.pv_pal_b_model&0xf, cur_ver.pal_version_s.pv_pal_b_rev,
+		     min_ver.pal_version_s.pv_pal_b_model>>4,
+		     min_ver.pal_version_s.pv_pal_b_model&0xf, min_ver.pal_version_s.pv_pal_b_rev);
 	return p - page;
 }
 
@@ -595,26 +591,20 @@
 
 	if (ia64_pal_perf_mon_info(pm_buffer, &pm_info) != 0) return 0;
 
-	p += sprintf(p, "PMC/PMD pairs                 : %d\n" \
-			"Counter width                 : %d bits\n" \
-			"Cycle event number            : %d\n" \
-			"Retired event number          : %d\n" \
-			"Implemented PMC               : ",
-			pm_info.pal_perf_mon_info_s.generic,
-			pm_info.pal_perf_mon_info_s.width,
-			pm_info.pal_perf_mon_info_s.cycles,
-			pm_info.pal_perf_mon_info_s.retired);
+	p += sprintf(p,
+		     "PMC/PMD pairs                 : %d\n"
+		     "Counter width                 : %d bits\n"
+		     "Cycle event number            : %d\n"
+		     "Retired event number          : %d\n"
+		     "Implemented PMC               : ",
+		     pm_info.pal_perf_mon_info_s.generic, pm_info.pal_perf_mon_info_s.width,
+		     pm_info.pal_perf_mon_info_s.cycles, pm_info.pal_perf_mon_info_s.retired);
 
 	p = bitregister_process(p, pm_buffer, 256);
-
 	p += sprintf(p, "\nImplemented PMD               : ");
-
 	p = bitregister_process(p, pm_buffer+4, 256);
-
 	p += sprintf(p, "\nCycles count capable          : ");
-
 	p = bitregister_process(p, pm_buffer+8, 256);
-
 	p += sprintf(p, "\nRetired bundles count capable : ");
 
 #ifdef CONFIG_ITANIUM
@@ -646,12 +636,11 @@
 
 	if (ia64_pal_freq_ratios(&proc, &bus, &itc) != 0) return 0;
 
-	p += sprintf(p, "Processor/Clock ratio   : %ld/%ld\n" \
-			"Bus/Clock ratio         : %ld/%ld\n" \
-			"ITC/Clock ratio         : %ld/%ld\n",
-			proc.num, proc.den,
-			bus.num, bus.den,
-			itc.num, itc.den);
+	p += sprintf(p,
+		     "Processor/Clock ratio   : %ld/%ld\n"
+		     "Bus/Clock ratio         : %ld/%ld\n"
+		     "ITC/Clock ratio         : %ld/%ld\n",
+		     proc.num, proc.den, bus.num, bus.den, itc.num, itc.den);
 
 	return p - page;
 }
@@ -665,7 +654,7 @@
 	u64 tr_buffer[4];
 	pal_vm_info_1_u_t vm_info_1;
 	pal_vm_info_2_u_t vm_info_2;
-	int i, j;
+	u64 i, j;
 	u64 max[3], pgm;
 	struct ifa_reg {
 		u64 valid:1;
@@ -711,7 +700,7 @@
 
 		status = ia64_pal_tr_read(j, i, tr_buffer, &tr_valid);
 		if (status != 0) {
-			printk(KERN_ERR "palinfo: pal call failed on tr[%d:%d]=%ld\n",
+			printk(KERN_ERR "palinfo: pal call failed on tr[%lu:%lu]=%ld\n",
 			       i, j, status);
 			continue;
 		}
@@ -725,34 +714,29 @@
 		rid_reg  = (struct rid_reg *)&tr_buffer[3];
 
 		pgm	 = -1 << (itir_reg->ps - 12);
-		p += sprintf(p, "%cTR%d: av=%d pv=%d dv=%d mv=%d\n" \
-				"\tppn  : 0x%lx\n" \
-				"\tvpn  : 0x%lx\n" \
-				"\tps   : ",
-
-				"ID"[i],
-				j,
-				tr_valid.pal_tr_valid_s.access_rights_valid,
-				tr_valid.pal_tr_valid_s.priv_level_valid,
-				tr_valid.pal_tr_valid_s.dirty_bit_valid,
-				tr_valid.pal_tr_valid_s.mem_attr_valid,
-				(gr_reg->ppn & pgm)<< 12,
-				(ifa_reg->vpn & pgm)<< 12);
+		p += sprintf(p,
+			     "%cTR%lu: av=%d pv=%d dv=%d mv=%d\n"
+			     "\tppn  : 0x%lx\n"
+			     "\tvpn  : 0x%lx\n"
+			     "\tps   : ",
+			     "ID"[i], j,
+			     tr_valid.pal_tr_valid_s.access_rights_valid,
+			     tr_valid.pal_tr_valid_s.priv_level_valid,
+			     tr_valid.pal_tr_valid_s.dirty_bit_valid,
+			     tr_valid.pal_tr_valid_s.mem_attr_valid,
+			     (gr_reg->ppn & pgm)<< 12, (ifa_reg->vpn & pgm)<< 12);
 
 		p = bitvector_process(p, 1<< itir_reg->ps);
 
-		p += sprintf(p, "\n\tpl   : %d\n" \
-				"\tar   : %d\n" \
-				"\trid  : %x\n" \
-				"\tp    : %d\n" \
-				"\tma   : %d\n" \
-				"\td    : %d\n",
-				gr_reg->pl,
-				gr_reg->ar,
-				rid_reg->rid,
-				gr_reg->p,
-				gr_reg->ma,
-				gr_reg->d);
+		p += sprintf(p,
+			     "\n\tpl   : %d\n"
+			     "\tar   : %d\n"
+			     "\trid  : %x\n"
+			     "\tp    : %d\n"
+			     "\tma   : %d\n"
+			     "\td    : %d\n",
+			     gr_reg->pl, gr_reg->ar, rid_reg->rid, gr_reg->p, gr_reg->ma,
+			     gr_reg->d);
 		}
 	}
 	return p - page;
@@ -776,7 +760,7 @@
 	{ "tr_info",		tr_info, }
 };
 
-#define NR_PALINFO_ENTRIES	(sizeof(palinfo_entries)/sizeof(palinfo_entry_t))
+#define NR_PALINFO_ENTRIES	(int) ARRAY_SIZE(palinfo_entries)
 
 /*
  * this array is used to keep track of the proc entries we create. This is
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/perfmon.c linux-2.5.69-bk7/arch/ia64/kernel/perfmon.c
--- linux-2.5.69-bk6/arch/ia64/kernel/perfmon.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/perfmon.c	2003-05-12 04:43:29.000000000 -0700
@@ -2,7 +2,7 @@
  * This file implements the perfmon subsystem which is used
  * to program the IA-64 Performance Monitoring Unit (PMU).
  *
- * Originaly Written by Ganesh Venkitachalam, IBM Corp.
+ * Originally Written by Ganesh Venkitachalam, IBM Corp.
  * Copyright (C) 1999 Ganesh Venkitachalam <venkitac@us.ibm.com>
  *
  * Modifications by Stephane Eranian, Hewlett-Packard Co.
@@ -224,8 +224,9 @@
 	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 unsecure:1;	/* sp = 0 for non self-monitored task */
 	unsigned int trap_reason:2;	/* reason for going into pfm_block_ovfl_reset() */
-	unsigned int reserved:21;
+	unsigned int reserved:20;
 } pfm_context_flags_t;
 
 #define PFM_TRAP_REASON_NONE		0x0	/* default value */
@@ -278,6 +279,7 @@
 #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
+#define ctx_fl_unsecure		ctx_flags.unsecure
 
 /*
  * global information about all sessions
@@ -362,8 +364,9 @@
 
 #define PFM_CMD_IDX(cmd)	(cmd)
 
-#define PFM_CMD_IS_VALID(cmd)	((PFM_CMD_IDX(cmd) >= 0) && (PFM_CMD_IDX(cmd) < PFM_CMD_COUNT) \
-				  && pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func != NULL)
+#define PFM_CMD_IS_VALID(cmd)	((PFM_CMD_IDX(cmd) >= 0)				\
+				 && (PFM_CMD_IDX(cmd) < (int) PFM_CMD_COUNT)		\
+				 && pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func != NULL)
 
 #define PFM_CMD_USE_PID(cmd)	((pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_PID) != 0)
 #define PFM_CMD_READ_ARG(cmd)	((pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_ARG_READ) != 0)
@@ -646,7 +649,7 @@
 
 /*
  * This function is called from pfm_destroy_context() and also from pfm_inherit()
- * to explicitely remove the sampling buffer mapping from the user level address space.
+ * to explicitly remove the sampling buffer mapping from the user level address space.
  */
 static int
 pfm_remove_smpl_mapping(struct task_struct *task)
@@ -724,8 +727,7 @@
 static unsigned long
 pfm_smpl_entry_size(unsigned long *which, unsigned long size)
 {
-	unsigned long res = 0;
-	int i;
+	unsigned long i, res = 0;
 
 	for (i=0; i < size; i++, which++) res += hweight64(*which);
 
@@ -1076,10 +1078,15 @@
 		 * and it must be a valid CPU
 		 */
 		cpu = ffz(~pfx->ctx_cpu_mask);
+#ifdef CONFIG_SMP
 		if (cpu_online(cpu) == 0) {
+#else
+		if (cpu != 0) {
+#endif
 			DBprintk(("CPU%d is not online\n", cpu));
 			return -EINVAL;
 		}
+
 		/*
 		 * check for pre-existing pinning, if conflicting reject
 		 */
@@ -1225,6 +1232,7 @@
 	ctx->ctx_fl_block     = (ctx_flags & PFM_FL_NOTIFY_BLOCK) ? 1 : 0;
 	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_unsecure  = (ctx_flags & PFM_FL_UNSECURE) ? 1: 0;
 	ctx->ctx_fl_frozen    = 0;
 	ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE;
 
@@ -1251,9 +1259,11 @@
 	DBprintk(("context=%p, pid=%d notify_task=%p\n",
 			(void *)ctx, task->pid, ctx->ctx_notify_task));
 
-	DBprintk(("context=%p, pid=%d flags=0x%x inherit=%d block=%d system=%d excl_idle=%d\n", 
+	DBprintk(("context=%p, pid=%d flags=0x%x inherit=%d block=%d system=%d excl_idle=%d unsecure=%d\n", 
 			(void *)ctx, task->pid, ctx_flags, ctx->ctx_fl_inherit, 
-			ctx->ctx_fl_block, ctx->ctx_fl_system, ctx->ctx_fl_excl_idle));
+			ctx->ctx_fl_block, ctx->ctx_fl_system, 
+			ctx->ctx_fl_excl_idle,
+			ctx->ctx_fl_unsecure));
 
 	/*
 	 * when no notification is required, we can make this visible at the last moment
@@ -1659,7 +1669,7 @@
 		if (!PMD_IS_IMPL(cnum)) goto abort_mission;
 		/*
 		 * we can only read the register that we use. That includes
-		 * the one we explicitely initialize AND the one we want included
+		 * the one we explicitly initialize AND the one we want included
 		 * in the sampling buffer (smpl_regs).
 		 *
 		 * Having this restriction allows optimization in the ctxsw routine
@@ -1871,7 +1881,7 @@
 	 * if blocking, then post the semaphore.
 	 * if non-blocking, then we ensure that the task will go into
 	 * pfm_overflow_must_block() before returning to user mode. 
-	 * We cannot explicitely reset another task, it MUST always
+	 * We cannot explicitly reset another task, it MUST always
 	 * be done by the task itself. This works for system wide because
 	 * the tool that is controlling the session is doing "self-monitoring".
 	 *
@@ -1882,7 +1892,10 @@
 		DBprintk(("unblocking %d \n", task->pid));
 		up(sem);
 	} else {
+		struct thread_info *info = (struct thread_info *) ((char *) task + IA64_TASK_SIZE);
 		task->thread.pfm_ovfl_block_reset = 1;
+		ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_RESET;
+		set_bit(TIF_NOTIFY_RESUME, &info->flags);
 	}
 #if 0
 	/*
@@ -2051,7 +2064,7 @@
 	/*
 	 * reinforce secure monitoring: cannot toggle psr.up
 	 */
-	ia64_psr(regs)->sp = 1;
+	if (ctx->ctx_fl_unsecure == 0) ia64_psr(regs)->sp = 1;
 
 	return 0;
 }
@@ -2159,11 +2172,11 @@
 		 * never leaves the current CPU and the state
 		 * is shared by all processes running on it
 	 	 */
-		for (i=0; i < pmu_conf.num_ibrs; i++) {
+		for (i=0; i < (int) pmu_conf.num_ibrs; i++) {
 			ia64_set_ibr(i, 0UL);
 		}
 		ia64_srlz_i();
-		for (i=0; i < pmu_conf.num_dbrs; i++) {
+		for (i=0; i < (int) pmu_conf.num_dbrs; i++) {
 			ia64_set_dbr(i, 0UL);
 		}
 		ia64_srlz_d();
@@ -2505,7 +2518,7 @@
 /* 33 */{ pfm_write_dbrs, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_RW, PFM_CMD_ARG_MANY, sizeof(pfarg_dbreg_t)}
 #endif
 };
-#define PFM_CMD_COUNT	(sizeof(pfm_cmd_tab)/sizeof(pfm_cmd_desc_t))
+#define PFM_CMD_COUNT	ARRAY_SIZE(pfm_cmd_tab)
 
 static int
 check_task_state(struct task_struct *task)
@@ -2732,12 +2745,13 @@
 	 * again
 	 */
 	th->pfm_ovfl_block_reset = 0;
+	clear_thread_flag(TIF_NOTIFY_RESUME);
 
 	/*
 	 * do some sanity checks first
 	 */
 	if (!ctx) {
-		printk(KERN_DEBUG "perfmon: [%d] has no PFM context\n", current->pid);
+		printk(KERN_ERR "perfmon: [%d] has no PFM context\n", current->pid);
 		return;
 	}
 	/*
@@ -2899,15 +2913,18 @@
 
 /*
  * main overflow processing routine.
- * it can be called from the interrupt path or explicitely during the context switch code
+ * it can be called from the interrupt path or explicitly during the context switch code
+ * Arguments:
+ *	mode: 0=coming from PMU interrupt, 1=coming from ctxsw 
+ *	
  * Return:
  *	new value of pmc[0]. if 0x0 then unfreeze, else keep frozen
  */
 static unsigned long
-pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, struct pt_regs *regs)
+pfm_overflow_handler(int mode, struct task_struct *task, pfm_context_t *ctx, u64 pmc0, struct pt_regs *regs)
 {
-	unsigned long mask;
 	struct thread_struct *t;
+	unsigned long mask;
 	unsigned long old_val;
 	unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL;
 	int i;
@@ -2998,10 +3015,10 @@
 	/*
 	 * check for sampling buffer
 	 *
-	 * if present, record sample. We propagate notification ONLY when buffer
-	 * becomes full.
+	 * if present, record sample only when a 64-bit counter has overflowed.
+	 * We propagate notification ONLY when buffer becomes full.
 	 */
-	if(CTX_HAS_SMPL(ctx)) {
+	if(CTX_HAS_SMPL(ctx) && ovfl_pmds) {
 		ret = pfm_record_sample(task, ctx, ovfl_pmds, regs);
 		if (ret == 1) {
 			/*
@@ -3046,12 +3063,55 @@
 	 * 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 {
-		t->pfm_ovfl_block_reset = 1; /* will cause blocking */
 		ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_SIG;
 	}
+	/*
+	 * we cannot block in system wide mode and we do not go
+	 * through the PMU ctxsw code. Therefore we can generate
+	 * the notification here. In system wide mode, the current
+	 * task maybe different from the task controlling the session
+	 * on this CPU, therefore owner can be different from current.
+	 *
+	 * In per-process mode, this function gets called from 
+	 * the interrupt handler or pfm_load_regs(). The mode argument
+	 * tells where we are coming from. When coming from the interrupt
+	 * handler, it is safe to notify (send signal) right here because
+	 * we do not hold any runqueue locks needed by send_sig_info(). 
+	 *
+	 * However when coming from ctxsw, we cannot send the signal here.
+	 * It must be deferred until we are sure we do not hold any runqueue
+	 * related locks. The current task maybe different from the owner
+	 * only in UP mode. The deferral is implemented using the 
+	 * TIF_NOTIFY_RESUME mechanism. In this case, the pending work
+	 * is checked when the task is about to leave the kernel (see
+	 * entry.S). As of this version of perfmon, a kernel only
+	 * task cannot be monitored in per-process mode. Therefore,
+	 * when this function gets called from pfm_load_regs(), we know
+	 * we have a user level task which will eventually either exit
+	 * or leave the kernel, and thereby go through the checkpoint
+	 * for TIF_*.
+	 */
+	if (ctx->ctx_fl_system || mode == 0) {
+		pfm_notify_user(ctx);
+		ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE;
+	} else {
+		struct thread_info *info;
+
+		/*
+		 * given that TIF_NOTIFY_RESUME is not specific to
+		 * perfmon, we need to have a second level check to
+		 * verify the source of the notification.
+		 */
+		task->thread.pfm_ovfl_block_reset = 1;
+		/*
+		 * when coming from ctxsw, current still points to the
+		 * previous task, therefore we must work with task and not current.
+		 */
+		info = ((struct thread_info *) ((char *) task + IA64_TASK_SIZE));
+		set_bit(TIF_NOTIFY_RESUME, &info->flags);
+	}
 
 	/*
 	 * keep the PMU frozen until either pfm_restart() or 
@@ -3059,7 +3119,10 @@
 	 */
 	ctx->ctx_fl_frozen = 1;
 
-	DBprintk_ovfl(("return pmc0=0x%x must_block=%ld reason=%d\n",
+	DBprintk_ovfl(("current [%d] owner [%d] mode=%d return pmc0=0x%x must_block=%ld reason=%d\n",
+		current->pid, 
+		PMU_OWNER() ? PMU_OWNER()->pid : -1,
+		mode,
 		ctx->ctx_fl_frozen ? 0x1 : 0x0, 
 		t->pfm_ovfl_block_reset,
 		ctx->ctx_fl_trap_reason));
@@ -3068,7 +3131,7 @@
 	return 0x1UL;
 }
 
-static void
+static irqreturn_t
 pfm_interrupt_handler(int irq, void *arg, struct pt_regs *regs)
 {
 	u64 pmc0;
@@ -3083,7 +3146,7 @@
 	if (pfm_alternate_intr_handler) {
 		(*pfm_alternate_intr_handler->handler)(irq, arg, regs);
 		put_cpu();
-		return;
+		return IRQ_HANDLED;
 	}
 
 	/* 
@@ -3108,19 +3171,21 @@
 			printk(KERN_DEBUG "perfmon: Spurious overflow interrupt: process %d has "
 			       "no PFM context\n", task->pid);
 			put_cpu();
-			return;
+			return IRQ_HANDLED;
 		}
 
 		/* 
 		 * assume PMC[0].fr = 1 at this point 
 		 */
-		pmc0 = pfm_overflow_handler(task, ctx, pmc0, regs);
+		pmc0 = pfm_overflow_handler(0, task, ctx, pmc0, regs);
 		/*
 		 * 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
+		 * is for the current context or we are in system
+		 * wide mode. In UP (per-task) the current
+		 * task may not be the one owning the PMU,
+		 * same thing for system-wide.
 		 */
-		if (task == current) {
+		if (task == current || ctx->ctx_fl_system) {
 			/*
 		 	 * We always clear the overflow status bits and either unfreeze
 		 	 * or keep the PMU frozen.
@@ -3134,6 +3199,7 @@
 		pfm_stats[smp_processor_id()].pfm_spurious_ovfl_intr_count++;
 	}
 	put_cpu_no_resched();
+	return IRQ_HANDLED;
 }
 
 /* for debug only */
@@ -3387,11 +3453,11 @@
 	 * in the next version of perfmon.
 	 */
 	if (ctx->ctx_fl_using_dbreg) {
-		for (i=0; i < pmu_conf.num_ibrs; i++) {
+		for (i=0; i < (int) pmu_conf.num_ibrs; i++) {
 			ia64_set_ibr(i, t->ibr[i]);
 		}
 		ia64_srlz_i();
-		for (i=0; i < pmu_conf.num_dbrs; i++) {
+		for (i=0; i < (int) pmu_conf.num_dbrs; i++) {
 			ia64_set_dbr(i, t->dbr[i]);
 		}
 		ia64_srlz_d();
@@ -3402,7 +3468,7 @@
 	 * this path cannot be used in SMP
 	 */
 	if (owner == task) {
-		if (atomic_read(&ctx->ctx_last_cpu) != smp_processor_id())
+		if ((unsigned int) atomic_read(&ctx->ctx_last_cpu) != smp_processor_id())
 			DBprintk(("invalid last_cpu=%d for [%d]\n", 
 				atomic_read(&ctx->ctx_last_cpu), task->pid));
 
@@ -3454,7 +3520,7 @@
 	 * Side effect on ctx_fl_frozen is possible.
 	 */
 	if (t->pmc[0] & ~0x1) {
-		t->pmc[0] = pfm_overflow_handler(task, ctx, t->pmc[0], NULL);
+		t->pmc[0] = pfm_overflow_handler(1, task, ctx, t->pmc[0], NULL);
 	}
 
 	/*
@@ -3676,7 +3742,7 @@
 	 *
 	 */
 
-	if (atomic_read(&ctx->ctx_last_cpu) != smp_processor_id())
+	if ((unsigned int) atomic_read(&ctx->ctx_last_cpu) != smp_processor_id())
 		printk(KERN_DEBUG "perfmon: [%d] last_cpu=%d\n",
 		       task->pid, atomic_read(&ctx->ctx_last_cpu));
 
@@ -3754,16 +3820,20 @@
 
 	preempt_disable();
 	/*
-	 * make sure child cannot mess up the monitoring session
+	 * for secure sessions, make sure child cannot mess up 
+	 * the monitoring session.
 	 */
-	 ia64_psr(regs)->sp = 1;
-	 DBprintk(("enabling psr.sp for [%d]\n", task->pid));
-
+	if (ctx->ctx_fl_unsecure == 0) {
+		ia64_psr(regs)->sp = 1;
+	 	DBprintk(("enabling psr.sp for [%d]\n", task->pid));
+	} else {
+	 	DBprintk(("psr.sp=%d [%d]\n", ia64_psr(regs)->sp, task->pid));
+	}
 
 	/*
 	 * if there was a virtual mapping for the sampling buffer
 	 * the mapping is NOT inherited across fork() (see VM_DONTCOPY), 
-	 * so we don't have to explicitely remove it here. 
+	 * so we don't have to explicitly remove it here. 
 	 *
 	 *
 	 * Part of the clearing of fields is also done in
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/perfmon_mckinley.h linux-2.5.69-bk7/arch/ia64/kernel/perfmon_mckinley.h
--- linux-2.5.69-bk6/arch/ia64/kernel/perfmon_mckinley.h	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/perfmon_mckinley.h	2003-05-12 04:43:29.000000000 -0700
@@ -25,8 +25,8 @@
 /* pmc5  */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL,  pfm_mck_reserved, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
 /* pmc6  */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL,  pfm_mck_reserved, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
 /* pmc7  */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL,  pfm_mck_reserved, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
-/* pmc8  */ { PFM_REG_CONFIG  , 0, 0xffffffff3fffffffUL, 0xffffffff9fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
-/* pmc9  */ { PFM_REG_CONFIG  , 0, 0xffffffff3ffffffcUL, 0xffffffff9fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc8  */ { PFM_REG_CONFIG  , 0, 0xffffffff3fffffffUL, 0xffffffff3fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc9  */ { PFM_REG_CONFIG  , 0, 0xffffffff3ffffffcUL, 0xffffffff3fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
 /* pmc10 */ { PFM_REG_MONITOR , 4, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
 /* pmc11 */ { PFM_REG_MONITOR , 6, 0x0UL, 0x30f01cf, NULL,  pfm_mck_reserved, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
 /* pmc12 */ { PFM_REG_MONITOR , 6, 0x0UL, 0xffffUL, NULL,  pfm_mck_reserved, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
@@ -143,11 +143,8 @@
 		case  8: val8 = *val;
 			 val13 = th->pmc[13];
 			 val14 = th->pmc[14];
-			 *val |= 1UL << 2; /* bit 2 must always be 1 */
 			 check_case1 = 1;
 			 break;
-		case  9: *val |= 1UL << 2; /* bit 2 must always be 1 */
-			 break;
 		case 13: val8  = th->pmc[8];
 			 val13 = *val;
 			 val14 = th->pmc[14];
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/process.c linux-2.5.69-bk7/arch/ia64/kernel/process.c
--- linux-2.5.69-bk6/arch/ia64/kernel/process.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/process.c	2003-05-12 04:43:29.000000000 -0700
@@ -43,8 +43,8 @@
 
 #include "sigframe.h"
 
-static void
-do_show_stack (struct unw_frame_info *info, void *arg)
+void
+ia64_do_show_stack (struct unw_frame_info *info, void *arg)
 {
 	unsigned long ip, sp, bsp;
 	char buf[80];			/* don't make it so big that it overflows the stack! */
@@ -57,7 +57,7 @@
 
 		unw_get_sp(info, &sp);
 		unw_get_bsp(info, &bsp);
-		snprintf(buf, sizeof(buf), " [<%016lx>] %%s sp=0x%016lx bsp=0x%016lx\n",
+		snprintf(buf, sizeof(buf), " [<%016lx>] %%s\n\t\t\t\tsp=%016lx bsp=%016lx\n",
 			 ip, sp, bsp);
 		print_symbol(buf, ip);
 	} while (unw_unwind(info) >= 0);
@@ -73,12 +73,12 @@
 show_stack (struct task_struct *task)
 {
 	if (!task)
-		unw_init_running(do_show_stack, 0);
+		unw_init_running(ia64_do_show_stack, 0);
 	else {
 		struct unw_frame_info info;
 
 		unw_init_from_blocked_task(&info, task);
-		do_show_stack(&info, 0);
+		ia64_do_show_stack(&info, 0);
 	}
 }
 
@@ -123,8 +123,8 @@
 
 	if (user_mode(regs)) {
 		/* print the stacked registers */
-		unsigned long val, sof, *bsp, ndirty;
-		int i, is_nat = 0;
+		unsigned long val, *bsp, ndirty;
+		int i, sof, is_nat = 0;
 
 		sof = regs->cr_ifs & 0x7f;	/* size of frame */
 		ndirty = (regs->loadrs >> 19);
@@ -135,7 +135,7 @@
 			       ((i == sof - 1) || (i % 3) == 2) ? "\n" : " ");
 		}
 	} else
-		show_stack(0);
+		show_stack(NULL);
 }
 
 void
@@ -379,6 +379,7 @@
 #	define THREAD_FLAGS_TO_SET	0
 	p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR)
 			   | THREAD_FLAGS_TO_SET);
+	p->thread.last_fph_cpu = -1;
 #ifdef CONFIG_IA32_SUPPORT
 	/*
 	 * If we're cloning an IA32 task then save the IA32 extra
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/ptrace.c linux-2.5.69-bk7/arch/ia64/kernel/ptrace.c
--- linux-2.5.69-bk6/arch/ia64/kernel/ptrace.c	2003-05-04 16:53:56.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/ptrace.c	2003-05-12 04:43:29.000000000 -0700
@@ -202,17 +202,16 @@
 get_rnat (struct pt_regs *pt, struct switch_stack *sw,
 	  unsigned long *krbs, unsigned long *urnat_addr)
 {
-	unsigned long rnat0 = 0, rnat1 = 0, urnat = 0, *slot0_kaddr, kmask = ~0UL;
+	unsigned long rnat0 = 0, rnat1 = 0, urnat = 0, *slot0_kaddr, umask = 0UL;
 	unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift;
 	long num_regs;
 
 	kbsp = (unsigned long *) sw->ar_bspstore;
 	ubspstore = (unsigned long *) pt->ar_bspstore;
 	/*
-	 * First, figure out which bit number slot 0 in user-land maps
-	 * to in the kernel rnat.  Do this by figuring out how many
-	 * register slots we're beyond the user's backingstore and
-	 * then computing the equivalent address in kernel space.
+	 * First, figure out which bit number slot 0 in user-land maps to in the kernel
+	 * rnat.  Do this by figuring out how many register slots we're beyond the user's
+	 * backingstore and then computing the equivalent address in kernel space.
 	 */
 	num_regs = ia64_rse_num_regs(ubspstore, urnat_addr + 1);
 	slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs);
@@ -222,8 +221,8 @@
 
 	if (ubspstore + 63 > urnat_addr) {
 		/* some bits need to be merged in from pt->ar_rnat */
-		kmask = ~((1UL << ia64_rse_slot_num(ubspstore)) - 1);
-		urnat = (pt->ar_rnat & ~kmask);
+		umask = ((1UL << ia64_rse_slot_num(ubspstore)) - 1);
+		urnat = (pt->ar_rnat & umask);
 	}
 	if (rnat0_kaddr >= kbsp) {
 		rnat0 = sw->ar_rnat;
@@ -235,7 +234,7 @@
 	} else if (rnat1_kaddr > krbs) {
 		rnat1 = *rnat1_kaddr;
 	}
-	urnat |= ((rnat1 << (63 - shift)) | (rnat0 >> shift)) & kmask;
+	urnat |= ((rnat1 << (63 - shift)) | (rnat0 >> shift)) & ~umask;
 	return urnat;
 }
 
@@ -246,17 +245,19 @@
 put_rnat (struct pt_regs *pt, struct switch_stack *sw,
 	  unsigned long *krbs, unsigned long *urnat_addr, unsigned long urnat)
 {
-	unsigned long rnat0 = 0, rnat1 = 0, rnat = 0, *slot0_kaddr, kmask = ~0UL, mask;
-	unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift;
-	long num_regs;
+	unsigned long rnat0 = 0, rnat1 = 0, *slot0_kaddr, umask = 0, mask, m;
+	unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift, slot, ndirty;
+	long num_regs, nbits;
+
+	ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19));
+	nbits = ndirty % 63;
 
 	kbsp = (unsigned long *) sw->ar_bspstore;
 	ubspstore = (unsigned long *) pt->ar_bspstore;
 	/*
-	 * First, figure out which bit number slot 0 in user-land maps
-	 * to in the kernel rnat.  Do this by figuring out how many
-	 * register slots we're beyond the user's backingstore and
-	 * then computing the equivalent address in kernel space.
+	 * First, figure out which bit number slot 0 in user-land maps to in the kernel
+	 * rnat.  Do this by figuring out how many register slots we're beyond the user's
+	 * backingstore and then computing the equivalent address in kernel space.
 	 */
 	num_regs = (long) ia64_rse_num_regs(ubspstore, urnat_addr + 1);
 	slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs);
@@ -264,29 +265,37 @@
 	rnat1_kaddr = ia64_rse_rnat_addr(slot0_kaddr);
 	rnat0_kaddr = rnat1_kaddr - 64;
 
+printk("%s: ubspstore=%p urnat_addr=%p\n", __FUNCTION__, ubspstore, urnat_addr);
 	if (ubspstore + 63 > urnat_addr) {
 		/* some bits need to be place in pt->ar_rnat: */
-		kmask = ~((1UL << ia64_rse_slot_num(ubspstore)) - 1);
-		pt->ar_rnat = (pt->ar_rnat & kmask) | (rnat & ~kmask);
+		slot = ia64_rse_slot_num(ubspstore);
+		umask = ((1UL << slot) - 1);
+		pt->ar_rnat = (pt->ar_rnat & ~umask) | (urnat & umask);
+		nbits -= slot;
+		if (nbits <= 0)
+			return;
 	}
+	mask = (1UL << nbits) - 1;
 	/*
 	 * Note: Section 11.1 of the EAS guarantees that bit 63 of an
 	 * rnat slot is ignored. so we don't have to clear it here.
 	 */
 	rnat0 = (urnat << shift);
-	mask = ~0UL << shift;
+	m = mask << shift;
+printk("%s: rnat0=%016lx, m=%016lx, rnat0_kaddr=%p kbsp=%p\n", __FUNCTION__, rnat0, m, rnat0_kaddr, kbsp);
 	if (rnat0_kaddr >= kbsp) {
-		sw->ar_rnat = (sw->ar_rnat & ~mask) | (rnat0 & mask);
+		sw->ar_rnat = (sw->ar_rnat & ~m) | (rnat0 & m);
 	} else if (rnat0_kaddr > krbs) {
-		*rnat0_kaddr = ((*rnat0_kaddr & ~mask) | (rnat0 & mask));
+		*rnat0_kaddr = ((*rnat0_kaddr & ~m) | (rnat0 & m));
 	}
 
 	rnat1 = (urnat >> (63 - shift));
-	mask = ~0UL >> (63 - shift);
+	m = mask >> (63 - shift);
+printk("%s: rnat1=%016lx, m=%016lx, rnat1_kaddr=%p kbsp=%p\n", __FUNCTION__, rnat1, m, rnat1_kaddr, kbsp);
 	if (rnat1_kaddr >= kbsp) {
-		sw->ar_rnat = (sw->ar_rnat & ~mask) | (rnat1 & mask);
+		sw->ar_rnat = (sw->ar_rnat & ~m) | (rnat1 & m);
 	} else if (rnat1_kaddr > krbs) {
-		*rnat1_kaddr = ((*rnat1_kaddr & ~mask) | (rnat1 & mask));
+		*rnat1_kaddr = ((*rnat1_kaddr & ~m) | (rnat1 & m));
 	}
 }
 
@@ -589,6 +598,7 @@
 		psr->mfh = 0;
 		ia64_save_fpu(&task->thread.fph[0]);
 		task->thread.flags |= IA64_THREAD_FPH_VALID;
+		task->thread.last_fph_cpu = smp_processor_id();
 	}
 }
 
@@ -608,12 +618,11 @@
 	ia64_flush_fph(task);
 	if (!(task->thread.flags & IA64_THREAD_FPH_VALID)) {
 		task->thread.flags |= IA64_THREAD_FPH_VALID;
+		task->thread.last_fph_cpu = -1;		/* force reload */
 		memset(&task->thread.fph, 0, sizeof(task->thread.fph));
 	}
-#ifndef CONFIG_SMP
 	if (ia64_get_fpu_owner() == task)
 		ia64_set_fpu_owner(0);
-#endif
 	psr->dfh = 1;
 }
 
@@ -702,7 +711,9 @@
 		      case PT_R4: case PT_R5: case PT_R6: case PT_R7:
 			if (write_access) {
 				/* read NaT bit first: */
-				ret = unw_get_gr(&info, (addr - PT_R4)/8 + 4, data, &nat);
+				unsigned long dummy;
+
+				ret = unw_get_gr(&info, (addr - PT_R4)/8 + 4, &dummy, &nat);
 				if (ret < 0)
 					return ret;
 			}
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/sal.c linux-2.5.69-bk7/arch/ia64/kernel/sal.c
--- linux-2.5.69-bk6/arch/ia64/kernel/sal.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/sal.c	2003-05-12 04:43:29.000000000 -0700
@@ -116,7 +116,7 @@
 	p = (char *) (systab + 1);
 	for (i = 0; i < systab->entry_count; i++) {
 		/*
-		 * The first byte of each entry type contains the type desciptor.
+		 * The first byte of each entry type contains the type descriptor.
 		 */
 		switch (*p) {
 		      case SAL_DESC_ENTRY_POINT:
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/salinfo.c linux-2.5.69-bk7/arch/ia64/kernel/salinfo.c
--- linux-2.5.69-bk6/arch/ia64/kernel/salinfo.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/salinfo.c	2003-05-12 04:43:29.000000000 -0700
@@ -38,7 +38,7 @@
 	{ "itc_drift",		IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT, },
 };
 
-#define NR_SALINFO_ENTRIES (sizeof(salinfo_entries)/sizeof(salinfo_entry_t))
+#define NR_SALINFO_ENTRIES ARRAY_SIZE(salinfo_entries)
 
 /*
  * One for each feature and one more for the directory entry...
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/setup.c linux-2.5.69-bk7/arch/ia64/kernel/setup.c
--- linux-2.5.69-bk6/arch/ia64/kernel/setup.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/setup.c	2003-05-12 04:43:29.000000000 -0700
@@ -59,7 +59,10 @@
 struct ia64_boot_param *ia64_boot_param;
 struct screen_info screen_info;
 
+unsigned long ia64_max_cacheline_size;
 unsigned long ia64_iobase;	/* virtual address for I/O accesses */
+struct io_space io_space[MAX_IO_SPACES];
+unsigned int num_io_spaces;
 
 unsigned char aux_device_present = 0xaa;        /* XXX remove this when legacy I/O is gone */
 
@@ -412,6 +415,11 @@
 	}
 	ia64_iobase = (unsigned long) ioremap(phys_iobase, 0);
 
+	/* setup legacy IO port space */
+	io_space[0].mmio_base = ia64_iobase;
+	io_space[0].sparse = 1;
+	num_io_spaces = 1;
+
 #ifdef CONFIG_SMP
 	cpu_physical_id(0) = hard_smp_processor_id();
 #endif
@@ -421,7 +429,7 @@
 #ifdef CONFIG_ACPI_BOOT
 	acpi_boot_init();
 #endif
-#ifdef CONFIG_SERIAL_HCDP
+#ifdef CONFIG_SERIAL_8250_HCDP
 	if (efi.hcdp) {
 		void setup_serial_hcdp(void *);
 
@@ -494,7 +502,7 @@
 	memcpy(features, " standard", 10);
 	cp = features;
 	sep = 0;
-	for (i = 0; i < sizeof(feature_bits)/sizeof(feature_bits[0]); ++i) {
+	for (i = 0; i < (int) ARRAY_SIZE(feature_bits); ++i) {
 		if (mask & feature_bits[i].mask) {
 			if (sep)
 				*cp++ = sep;
@@ -625,6 +633,39 @@
 	/* start_kernel() requires this... */
 }
 
+static void
+get_max_cacheline_size (void)
+{
+	unsigned long line_size, max = 1;
+	u64 l, levels, unique_caches;
+        pal_cache_config_info_t cci;
+        s64 status;
+
+        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);
+                max = SMP_CACHE_BYTES;
+		goto out;
+        }
+
+	for (l = 0; l < levels; ++l) {
+		status = ia64_pal_cache_config_info(l, /* cache_type (data_or_unified)= */ 2,
+						    &cci);
+		if (status != 0) {
+			printk(KERN_ERR
+			       "%s: ia64_pal_cache_config_info(l=%lu) failed (status=%ld)\n",
+			       __FUNCTION__, l, status);
+			max = SMP_CACHE_BYTES;
+		}
+		line_size = 1 << cci.pcci_line_size;
+		if (line_size > max)
+			max = line_size;
+        }
+  out:
+	if (max > ia64_max_cacheline_size)
+		ia64_max_cacheline_size = max;
+}
 
 /*
  * cpu_init() initializes state that is per-CPU.  This function acts
@@ -668,6 +709,8 @@
 	cpu_info->node_data = get_node_data_ptr();
 #endif
 
+	get_max_cacheline_size();
+
 	/*
 	 * We can't pass "local_cpu_data" to identify_cpu() because we haven't called
 	 * ia64_mmu_init() yet.  And we can't call ia64_mmu_init() first because it
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/signal.c linux-2.5.69-bk7/arch/ia64/kernel/signal.c
--- linux-2.5.69-bk6/arch/ia64/kernel/signal.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/signal.c	2003-05-12 04:43:29.000000000 -0700
@@ -142,8 +142,13 @@
 
 		__copy_from_user(current->thread.fph, &sc->sc_fr[32], 96*16);
 		psr->mfh = 0;	/* drop signal handler's fph contents... */
-		if (!psr->dfh)
+		if (psr->dfh)
+			current->thread.last_fph_cpu = -1;
+		else {
 			__ia64_load_fpu(current->thread.fph);
+			ia64_set_fpu_owner(current);
+			current->thread.last_fph_cpu = smp_processor_id();
+		}
 	}
 	return err;
 }
@@ -523,7 +528,7 @@
 			else
 				errno = -errno;
 		}
-	} else if (scr->pt.r10 != -1)
+	} else if ((long) scr->pt.r10 != -1)
 		/*
 		 * A system calls has to be restarted only if one of the error codes
 		 * ERESTARTNOHAND, ERESTARTSYS, or ERESTARTNOINTR is returned.  If r10
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/smp.c linux-2.5.69-bk7/arch/ia64/kernel/smp.c
--- linux-2.5.69-bk6/arch/ia64/kernel/smp.c	2003-05-04 16:53:56.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/smp.c	2003-05-12 04:43:29.000000000 -0700
@@ -2,7 +2,7 @@
  * SMP Support
  *
  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999, 2001, 2003 David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * Lots of stuff stolen from arch/alpha/kernel/smp.c
  *
@@ -87,7 +87,7 @@
 	cpu_halt();
 }
 
-void
+irqreturn_t
 handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
 {
 	int this_cpu = get_cpu();
@@ -147,10 +147,11 @@
 		mb();	/* Order data access and bit testing. */
 	}
 	put_cpu();
+	return IRQ_HANDLED;
 }
 
 /*
- * Called with preeemption disabled 
+ * Called with preeemption disabled.
  */
 static inline void
 send_IPI_single (int dest_cpu, int op)
@@ -160,12 +161,12 @@
 }
 
 /*
- * Called with preeemption disabled 
+ * Called with preeemption disabled.
  */
 static inline void
 send_IPI_allbutself (int op)
 {
-	int i;
+	unsigned int i;
 
 	for (i = 0; i < NR_CPUS; i++) {
 		if (cpu_online(i) && i != smp_processor_id())
@@ -174,7 +175,7 @@
 }
 
 /*
- * Called with preeemption disabled 
+ * Called with preeemption disabled.
  */
 static inline void
 send_IPI_all (int op)
@@ -187,7 +188,7 @@
 }
 
 /*
- * Called with preeemption disabled 
+ * Called with preeemption disabled.
  */
 static inline void
 send_IPI_self (int op)
@@ -196,7 +197,7 @@
 }
 
 /*
- * Called with preeemption disabled 
+ * Called with preeemption disabled.
  */
 void
 smp_send_reschedule (int cpu)
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/smpboot.c linux-2.5.69-bk7/arch/ia64/kernel/smpboot.c
--- linux-2.5.69-bk6/arch/ia64/kernel/smpboot.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/smpboot.c	2003-05-12 04:43:29.000000000 -0700
@@ -192,6 +192,7 @@
 {
 	long i, delta, adj, adjust_latency = 0, done = 0;
 	unsigned long flags, rt, master_time_stamp, bound;
+	extern void ia64_cpu_local_tick (void);
 #if DEBUG_ITC_SYNC
 	struct {
 		long rt;	/* roundtrip time */
@@ -246,6 +247,16 @@
 
 	printk(KERN_INFO "CPU %d: synchronized ITC with CPU %u (last diff %ld cycles, "
 	       "maxerr %lu cycles)\n", smp_processor_id(), master, delta, rt);
+
+	/*
+	 * Check whether we sync'd the itc ahead of the next timer interrupt.  If so, just
+	 * reset it.
+	 */
+	if (time_after(ia64_get_itc(), local_cpu_data->itm_next)) {
+		Dprintk("CPU %d: oops, jumped a timer tick; resetting timer.\n",
+			smp_processor_id());
+		ia64_cpu_local_tick();
+	}
 }
 
 /*
@@ -279,15 +290,6 @@
 
 	smp_setup_percpu_timer();
 
-	if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
-		/*
-		 * Synchronize the ITC with the BP
-		 */
-		Dprintk("Going to syncup ITC with BP.\n");
-
-		ia64_sync_itc(0);
-	}
-
 	/*
 	 * Get our bogomips.
 	 */
@@ -310,6 +312,18 @@
 	local_irq_enable();
 	calibrate_delay();
 	local_cpu_data->loops_per_jiffy = loops_per_jiffy;
+
+	if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
+		/*
+		 * Synchronize the ITC with the BP.  Need to do this after irqs are
+		 * enabled because ia64_sync_itc() calls smp_call_function_single(), which
+		 * calls spin_unlock_bh(), which calls spin_unlock_bh(), which calls
+		 * local_bh_enable(), which bugs out if irqs are not enabled...
+		 */
+		Dprintk("Going to syncup ITC with BP.\n");
+		ia64_sync_itc(0);
+	}
+
 	/*
 	 * Allow the master to continue.
 	 */
@@ -394,13 +408,26 @@
 	return 0;
 }
 
-unsigned long cache_decay_ticks;	/* # of ticks an idle task is considered cache-hot */
+static int __init
+decay (char *str)
+{
+	int ticks;
+	get_option (&str, &ticks);
+	cache_decay_ticks = ticks;
+	return 1;
+}
+
+__setup("decay=", decay);
+
+/*
+ * # of ticks an idle task is considered cache-hot.  Highly application-dependent.  There
+ * are apps out there which are known to suffer significantly with values >= 4.
+ */
+unsigned long cache_decay_ticks = 10;	/* equal to MIN_TIMESLICE */
 
 static void
 smp_tune_scheduling (void)
 {
-	cache_decay_ticks = 10;	/* XXX base this on PAL info and cache-bandwidth estimate */
-
 	printk(KERN_INFO "task migration cache decay timeout: %ld msecs.\n",
 	       (cache_decay_ticks + 1) * 1000 / HZ);
 }
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/time.c linux-2.5.69-bk7/arch/ia64/kernel/time.c
--- linux-2.5.69-bk6/arch/ia64/kernel/time.c	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/time.c	2003-05-12 04:43:29.000000000 -0700
@@ -83,11 +83,26 @@
 	return (elapsed_cycles*local_cpu_data->nsec_per_cyc) >> IA64_NSEC_PER_CYC_SHIFT;
 }
 
+static inline void
+set_normalized_timespec (struct timespec *ts, time_t sec, long nsec)
+{
+	while (nsec > NSEC_PER_SEC) {
+		nsec -= NSEC_PER_SEC;
+		++sec;
+	}
+	while (nsec < 0) {
+		nsec += NSEC_PER_SEC;
+		--sec;
+	}
+	ts->tv_sec = sec;
+	ts->tv_nsec = nsec;
+}
+
 void
 do_settimeofday (struct timeval *tv)
 {
-	time_t sec = tv->tv_sec;
-	long nsec = tv->tv_usec * 1000;
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_usec * 1000;
 
 	write_seqlock_irq(&xtime_lock);
 	{
@@ -99,13 +114,12 @@
 		 */
 		nsec -= gettimeoffset();
 
-		while (nsec < 0) {
-			nsec += 1000000000;
-			sec--;
-		}
+		wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+		wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+		set_normalized_timespec(&xtime, sec, nsec);
+		set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-		xtime.tv_sec = sec;
-		xtime.tv_nsec = nsec;
 		time_adjust = 0;		/* stop active adjtime() */
 		time_status |= STA_UNSYNC;
 		time_maxerror = NTP_PHASE_LIMIT;
@@ -166,8 +180,8 @@
 
 	usec = (nsec + offset) / 1000;
 
-	while (unlikely(usec >= 1000000)) {
-		usec -= 1000000;
+	while (unlikely(usec >= USEC_PER_SEC)) {
+		usec -= USEC_PER_SEC;
 		++sec;
 	}
 
@@ -175,8 +189,8 @@
 	tv->tv_usec = usec;
 }
 
-static void
-timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t
+timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned long new_itm;
 
@@ -221,7 +235,7 @@
 	do {
 	    /*
 	     * If we're too close to the next clock tick for comfort, we increase the
-	     * saftey margin by intentionally dropping the next tick(s).  We do NOT update
+	     * safety margin by intentionally dropping the next tick(s).  We do NOT update
 	     * itm.next because that would force us to call do_timer() which in turn would
 	     * let our clock run too fast (with the potentially devastating effect of
 	     * losing monotony of time).
@@ -231,12 +245,13 @@
 	    ia64_set_itm(new_itm);
 	    /* double check, in case we got hit by a (slow) PMI: */
 	} while (time_after_eq(ia64_get_itc(), new_itm));
+	return IRQ_HANDLED;
 }
 
 /*
  * Encapsulate access to the itm structure for SMP.
  */
-void __init
+void
 ia64_cpu_local_tick (void)
 {
 	int cpu = smp_processor_id();
@@ -281,7 +296,7 @@
 	if (status != 0) {
 		/* invent "random" values */
 		printk(KERN_ERR
-		       "SAL/PAL failed to obtain frequency info---inventing reasonably values\n");
+		       "SAL/PAL failed to obtain frequency info---inventing reasonable values\n");
 		platform_base_freq = 100000000;
 		itc_ratio.num = 3;
 		itc_ratio.den = 1;
@@ -305,8 +320,8 @@
 
 	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->nsec_per_cyc = ((1000000000UL<<IA64_NSEC_PER_CYC_SHIFT)
+	local_cpu_data->cyc_per_usec = (itc_freq + USEC_PER_SEC/2) / USEC_PER_SEC;
+	local_cpu_data->nsec_per_cyc = ((NSEC_PER_SEC<<IA64_NSEC_PER_CYC_SHIFT)
 					+ itc_freq/2)/itc_freq;
 
 	/* Setup the CPU local timer tick */
@@ -323,6 +338,12 @@
 time_init (void)
 {
 	register_percpu_irq(IA64_TIMER_VECTOR, &timer_irqaction);
-	efi_gettimeofday((struct timeval *) &xtime);
+	efi_gettimeofday(&xtime);
 	ia64_init_itm();
+
+	/*
+	 * Initialize wall_to_monotonic such that adding it to xtime will yield zero, the
+	 * tv_nsec field must be normalized (i.e., 0 <= nsec < NSEC_PER_SEC).
+	 */
+	set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec);
 }
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/traps.c linux-2.5.69-bk7/arch/ia64/kernel/traps.c
--- linux-2.5.69-bk6/arch/ia64/kernel/traps.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/traps.c	2003-05-12 04:43:29.000000000 -0700
@@ -94,7 +94,7 @@
 {
 	static struct {
 		spinlock_t lock;
-		int lock_owner;
+		u32 lock_owner;
 		int lock_owner_depth;
 	} die = {
 		.lock =			SPIN_LOCK_UNLOCKED,
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/unaligned.c linux-2.5.69-bk7/arch/ia64/kernel/unaligned.c
--- linux-2.5.69-bk6/arch/ia64/kernel/unaligned.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/unaligned.c	2003-05-12 04:43:29.000000000 -0700
@@ -789,7 +789,7 @@
 	 *
 	 * ldX.a (advanced load):
 	 *	- suppose ldX.a r1=[r3]. If we get to the unaligned trap it's because the
-	 *	  address doesn't match requested size alignement. This means that we would
+	 *	  address doesn't match requested size alignment. This means that we would
 	 *	  possibly need more than one load to get the result.
 	 *
 	 *	  The load part can be handled just like a normal load, however the difficult
diff -urN linux-2.5.69-bk6/arch/ia64/kernel/unwind.c linux-2.5.69-bk7/arch/ia64/kernel/unwind.c
--- linux-2.5.69-bk6/arch/ia64/kernel/unwind.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/kernel/unwind.c	2003-05-12 04:43:29.000000000 -0700
@@ -682,7 +682,7 @@
 	 * First, resolve implicit register save locations (see Section "11.4.2.3 Rules
 	 * for Using Unwind Descriptors", rule 3):
 	 */
-	for (i = 0; i < (int) sizeof(unw.save_order)/sizeof(unw.save_order[0]); ++i) {
+	for (i = 0; i < (int) ARRAY_SIZE(unw.save_order); ++i) {
 		reg = sr->curr.reg + unw.save_order[i];
 		if (reg->where == UNW_WHERE_GR_SAVE) {
 			reg->where = UNW_WHERE_GR;
@@ -698,7 +698,7 @@
 	 */
 	if (sr->imask) {
 		unsigned char kind, mask = 0, *cp = sr->imask;
-		unsigned long t;
+		int t;
 		static const unsigned char limit[3] = {
 			UNW_REG_F31, UNW_REG_R7, UNW_REG_B5
 		};
@@ -1214,13 +1214,13 @@
 	spin_unlock(&unw.lock);
 
 	/*
-	 * XXX We'll deadlock here if we interrupt a thread that is
-	 * holding a read lock on script->lock.  A try_write_lock()
-	 * might be mighty handy here...  Alternatively, we could
-	 * disable interrupts whenever we hold a read-lock, but that
-	 * seems silly.
+	 * We'd deadlock here if we interrupted a thread that is holding a read lock on
+	 * script->lock.  Thus, if the write_trylock() fails, we simply bail out.  The
+	 * alternative would be to disable interrupts whenever we hold a read-lock, but
+	 * that seems silly.
 	 */
-	write_lock(&script->lock);
+	if (!write_trylock(&script->lock))
+		return NULL;
 
 	spin_lock(&unw.lock);
 	{
@@ -1888,22 +1888,21 @@
 	return -1;
 }
 
-void
-unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct switch_stack *sw)
+static void
+init_frame_info (struct unw_frame_info *info, struct task_struct *t,
+		 struct switch_stack *sw, unsigned long stktop)
 {
-	unsigned long rbslimit, rbstop, stklimit, stktop, sol;
+	unsigned long rbslimit, rbstop, stklimit;
 	STAT(unsigned long start, flags;)
 
 	STAT(local_irq_save(flags); ++unw.stat.api.inits; start = ia64_get_itc());
 
 	/*
-	 * Subtle stuff here: we _could_ unwind through the
-	 * switch_stack frame but we don't want to do that because it
-	 * would be slow as each preserved register would have to be
-	 * processed.  Instead, what we do here is zero out the frame
-	 * info and start the unwind process at the function that
-	 * created the switch_stack frame.  When a preserved value in
-	 * switch_stack needs to be accessed, run_script() will
+	 * Subtle stuff here: we _could_ unwind through the switch_stack frame but we
+	 * don't want to do that because it would be slow as each preserved register would
+	 * have to be processed.  Instead, what we do here is zero out the frame info and
+	 * start the unwind process at the function that created the switch_stack frame.
+	 * When a preserved value in switch_stack needs to be accessed, run_script() will
 	 * initialize the appropriate pointer on demand.
 	 */
 	memset(info, 0, sizeof(*info));
@@ -1914,7 +1913,6 @@
 		rbstop = rbslimit;
 
 	stklimit = (unsigned long) t + IA64_STK_OFFSET;
-	stktop   = (unsigned long) sw - 16;
 	if (stktop <= rbstop)
 		stktop = rbstop;
 
@@ -1924,34 +1922,58 @@
 	info->memstk.top   = stktop;
 	info->task = t;
 	info->sw  = sw;
-	info->sp = info->psp = (unsigned long) (sw + 1) - 16;
-	info->pt = 0;
+	info->sp = info->psp = stktop;
+	info->pr = sw->pr;
+	UNW_DPRINT(3, "unwind.%s:\n"
+		   "  task   0x%lx\n"
+		   "  rbs = [0x%lx-0x%lx)\n"
+		   "  stk = [0x%lx-0x%lx)\n"
+		   "  pr     0x%lx\n"
+		   "  sw     0x%lx\n"
+		   "  sp     0x%lx\n",
+		   __FUNCTION__, (unsigned long) t, rbslimit, rbstop, stktop, stklimit,
+		   info->pr, (unsigned long) info->sw, info->sp);
+	STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags));
+}
+
+void
+unw_init_from_interruption (struct unw_frame_info *info, struct task_struct *t,
+			    struct pt_regs *pt, struct switch_stack *sw)
+{
+	unsigned long sof;
+
+	init_frame_info(info, t, sw, pt->r12);
+	info->cfm_loc = &pt->cr_ifs;
+	info->unat_loc = &pt->ar_unat;
+	info->pfs_loc = &pt->ar_pfs;
+	sof = *info->cfm_loc & 0x7f;
+	info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sof);
+	info->ip = pt->cr_iip + ia64_psr(pt)->ri;
+	info->pt = (unsigned long) pt;
+	UNW_DPRINT(3, "unwind.%s:\n"
+		   "  bsp    0x%lx\n"
+		   "  sof    0x%lx\n"
+		   "  ip     0x%lx\n",
+		   __FUNCTION__, info->bsp, sof, info->ip);
+	find_save_locs(info);
+}
+
+void
+unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct switch_stack *sw)
+{
+	unsigned long sol;
+
+	init_frame_info(info, t, sw, (unsigned long) (sw + 1) - 16);
 	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);
-
+	UNW_DPRINT(3, "unwind.%s:\n"
+		   "  bsp    0x%lx\n"
+		   "  sol    0x%lx\n"
+		   "  ip     0x%lx\n",
+		   __FUNCTION__, info->bsp, sol, info->ip);
 	find_save_locs(info);
-	STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags));
 }
 
 void
diff -urN linux-2.5.69-bk6/arch/ia64/lib/copy_user.S linux-2.5.69-bk7/arch/ia64/lib/copy_user.S
--- linux-2.5.69-bk6/arch/ia64/lib/copy_user.S	2003-05-04 16:53:03.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/lib/copy_user.S	2003-05-12 04:43:29.000000000 -0700
@@ -316,7 +316,7 @@
 	// Beginning of long mempcy (i.e. > 16 bytes)
 	//
 .long_copy_user:
-	tbit.nz p6,p7=src1,0	// odd alignement
+	tbit.nz p6,p7=src1,0	// odd alignment
 	and tmp=7,tmp
 	;;
 	cmp.eq p10,p8=r0,tmp
diff -urN linux-2.5.69-bk6/arch/ia64/lib/do_csum.S linux-2.5.69-bk7/arch/ia64/lib/do_csum.S
--- linux-2.5.69-bk6/arch/ia64/lib/do_csum.S	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/lib/do_csum.S	2003-05-12 04:43:29.000000000 -0700
@@ -137,7 +137,7 @@
 	mov saved_pr=pr		// preserve predicates (rotation)
 (p6)	br.ret.spnt.many rp	// return if zero or negative length
 
-	mov hmask=-1		// intialize head mask
+	mov hmask=-1		// initialize head mask
 	tbit.nz p15,p0=buf,0	// is buf an odd address?
 	and first1=-8,buf	// 8-byte align down address of first1 element
 
diff -urN linux-2.5.69-bk6/arch/ia64/lib/io.c linux-2.5.69-bk7/arch/ia64/lib/io.c
--- linux-2.5.69-bk6/arch/ia64/lib/io.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/lib/io.c	2003-05-12 04:43:29.000000000 -0700
@@ -51,84 +51,79 @@
 
 #ifdef CONFIG_IA64_GENERIC
 
+#undef __ia64_inb
+#undef __ia64_inw
+#undef __ia64_inl
+#undef __ia64_outb
+#undef __ia64_outw
+#undef __ia64_outl
+#undef __ia64_readb
+#undef __ia64_readw
+#undef __ia64_readl
+#undef __ia64_readq
+#undef __ia64_writeb
+#undef __ia64_writew
+#undef __ia64_writel
+#undef __ia64_writeq
+
 unsigned int
-ia64_inb (unsigned long port)
+__ia64_inb (unsigned long port)
 {
-	return __ia64_inb(port);
+	return ___ia64_inb(port);
 }
 
 unsigned int
-ia64_inw (unsigned long port)
+__ia64_inw (unsigned long port)
 {
-	return __ia64_inw(port);
+	return ___ia64_inw(port);
 }
 
 unsigned int
-ia64_inl (unsigned long port)
+__ia64_inl (unsigned long port)
 {
-	return __ia64_inl(port);
+	return ___ia64_inl(port);
 }
 
 void
-ia64_outb (unsigned char val, unsigned long port)
+__ia64_outb (unsigned char val, unsigned long port)
 {
-	__ia64_outb(val, port);
+	___ia64_outb(val, port);
 }
 
 void
-ia64_outw (unsigned short val, unsigned long port)
+__ia64_outw (unsigned short val, unsigned long port)
 {
-	__ia64_outw(val, port);
+	___ia64_outw(val, port);
 }
 
 void
-ia64_outl (unsigned int val, unsigned long port)
+__ia64_outl (unsigned int val, unsigned long port)
 {
-	__ia64_outl(val, port);
+	___ia64_outl(val, port);
 }
 
 unsigned char
-ia64_readb (void *addr)
+__ia64_readb (void *addr)
 {
-	return __ia64_readb (addr);
+	return ___ia64_readb (addr);
 }
 
 unsigned short
-ia64_readw (void *addr)
+__ia64_readw (void *addr)
 {
-	return __ia64_readw (addr);
+	return ___ia64_readw (addr);
 }
 
 unsigned int
-ia64_readl (void *addr)
+__ia64_readl (void *addr)
 {
-	return __ia64_readl (addr);
+	return ___ia64_readl (addr);
 }
 
 unsigned long
-ia64_readq (void *addr)
+__ia64_readq (void *addr)
 {
-	return __ia64_readq (addr)
+	return ___ia64_readq (addr);
 }
 
-
-/* define aliases: */
-
-asm (".global __ia64_inb, __ia64_inw, __ia64_inl");
-asm ("__ia64_inb = ia64_inb");
-asm ("__ia64_inw = ia64_inw");
-asm ("__ia64_inl = ia64_inl");
-
-asm (".global __ia64_outb, __ia64_outw, __ia64_outl");
-asm ("__ia64_outb = ia64_outb");
-asm ("__ia64_outw = ia64_outw");
-asm ("__ia64_outl = ia64_outl");
-
-asm (".global __ia64_readb, __ia64_readw, __ia64_readl, __ia64_readq");
-asm ("__ia64_readb = ia64_readb");
-asm ("__ia64_readw = ia64_readw");
-asm ("__ia64_readl = ia64_readl");
-asm ("__ia64_readq = ia64_readq");
-
-
 #endif /* CONFIG_IA64_GENERIC */
diff -urN linux-2.5.69-bk6/arch/ia64/lib/swiotlb.c linux-2.5.69-bk7/arch/ia64/lib/swiotlb.c
--- linux-2.5.69-bk6/arch/ia64/lib/swiotlb.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/lib/swiotlb.c	2003-05-12 04:43:29.000000000 -0700
@@ -5,7 +5,10 @@
  * I/O TLBs (aka DMA address translation hardware).
  * Copyright (C) 2000 Asit Mallick <Asit.K.Mallick@intel.com>
  * Copyright (C) 2000 Goutham Rao <goutham.rao@intel.com>
+ * Copyright (C) 2000, 2003 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
  *
+ * 03/05/07 davidm	Switch from PCI-DMA to generic device DMA API.
  * 00/12/13 davidm	Rename to swiotlb.c and add mark_clean() to avoid
  *			unnecessary i-cache flushing.
  */
@@ -92,7 +95,7 @@
 void
 swiotlb_init (void)
 {
-	int i;
+	unsigned long i;
 
 	/*
 	 * Get IO TLB memory from the low pages
@@ -121,7 +124,7 @@
  * Allocates bounce buffer and returns its kernel virtual address.
  */
 static void *
-map_single (struct pci_dev *hwdev, char *buffer, size_t size, int direction)
+map_single (struct device *hwdev, char *buffer, size_t size, int dir)
 {
 	unsigned long flags;
 	char *dma_addr;
@@ -161,7 +164,7 @@
 			if (io_tlb_list[index] >= nslots) {
 				int count = 0;
 
-				for (i = index; i < index + nslots; i++)
+				for (i = index; i < (int) (index + nslots); i++)
 					io_tlb_list[i] = 0;
 				for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE -1)
 				       && io_tlb_list[i]; i--)
@@ -195,7 +198,7 @@
 	 * needed when we sync the memory.  Then we sync the buffer if needed.
 	 */
 	io_tlb_orig_addr[index] = buffer;
-	if (direction == PCI_DMA_TODEVICE || direction == PCI_DMA_BIDIRECTIONAL)
+	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
 		memcpy(dma_addr, buffer, size);
 
 	return dma_addr;
@@ -205,7 +208,7 @@
  * dma_addr is the kernel virtual address of the bounce buffer to unmap.
  */
 static void
-unmap_single (struct pci_dev *hwdev, char *dma_addr, size_t size, int direction)
+unmap_single (struct device *hwdev, char *dma_addr, size_t size, int dir)
 {
 	unsigned long flags;
 	int i, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
@@ -215,7 +218,7 @@
 	/*
 	 * First, sync the memory before unmapping the entry
 	 */
-	if ((direction == PCI_DMA_FROMDEVICE) || (direction == PCI_DMA_BIDIRECTIONAL))
+	if ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))
 		/*
 		 * bounce... copy the data back into the original buffer * and delete the
 		 * bounce buffer.
@@ -239,7 +242,7 @@
 		for (i = index + nslots - 1; i >= index; i--)
 			io_tlb_list[i] = ++count;
 		/*
-		 * Step 2: merge the returned slots with the preceeding slots, if
+		 * Step 2: merge the returned slots with the preceding slots, if
 		 * available (non zero)
 		 */
 		for (i = index - 1;  (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE -1) &&
@@ -250,49 +253,46 @@
 }
 
 static void
-sync_single (struct pci_dev *hwdev, char *dma_addr, size_t size, int direction)
+sync_single (struct device *hwdev, char *dma_addr, size_t size, int dir)
 {
 	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
 	char *buffer = io_tlb_orig_addr[index];
 
 	/*
 	 * bounce... copy the data back into/from the original buffer
-	 * XXX How do you handle PCI_DMA_BIDIRECTIONAL here ?
+	 * XXX How do you handle DMA_BIDIRECTIONAL here ?
 	 */
-	if (direction == PCI_DMA_FROMDEVICE)
+	if (dir == DMA_FROM_DEVICE)
 		memcpy(buffer, dma_addr, size);
-	else if (direction == PCI_DMA_TODEVICE)
+	else if (dir == DMA_TO_DEVICE)
 		memcpy(dma_addr, buffer, size);
 	else
 		BUG();
 }
 
 void *
-swiotlb_alloc_consistent (struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
+swiotlb_alloc_coherent (struct device *hwdev, size_t size, dma_addr_t *dma_handle, int flags)
 {
-	unsigned long pci_addr;
-	int gfp = GFP_ATOMIC;
+	unsigned long dev_addr;
 	void *ret;
 
-	/*
-	 * Alloc_consistent() is defined to return memory < 4GB, no matter what the DMA
-	 * mask says.
-	 */
-	gfp |= GFP_DMA; /* XXX fix me: should change this to GFP_32BIT or ZONE_32BIT */
-	ret = (void *)__get_free_pages(gfp, get_order(size));
+	/* XXX fix me: the DMA API should pass us an explicit DMA mask instead: */
+	flags |= GFP_DMA;
+
+	ret = (void *)__get_free_pages(flags, get_order(size));
 	if (!ret)
 		return NULL;
 
 	memset(ret, 0, size);
-	pci_addr = virt_to_phys(ret);
-	if (hwdev && (pci_addr & ~hwdev->dma_mask) != 0)
-		panic("swiotlb_alloc_consistent: allocated memory is out of range for PCI device");
-	*dma_handle = pci_addr;
+	dev_addr = virt_to_phys(ret);
+	if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0)
+		panic("swiotlb_alloc_consistent: allocated memory is out of range for device");
+	*dma_handle = dev_addr;
 	return ret;
 }
 
 void
-swiotlb_free_consistent (struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
+swiotlb_free_coherent (struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
 {
 	free_pages((unsigned long) vaddr, get_order(size));
 }
@@ -305,34 +305,34 @@
  * swiotlb_unmap_single or swiotlb_dma_sync_single is performed.
  */
 dma_addr_t
-swiotlb_map_single (struct pci_dev *hwdev, void *ptr, size_t size, int direction)
+swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, int dir)
 {
-	unsigned long pci_addr = virt_to_phys(ptr);
+	unsigned long dev_addr = virt_to_phys(ptr);
 
-	if (direction == PCI_DMA_NONE)
+	if (dir == DMA_NONE)
 		BUG();
 	/*
 	 * Check if the PCI device can DMA to ptr... if so, just return ptr
 	 */
-	if ((pci_addr & ~hwdev->dma_mask) == 0)
+	if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) == 0)
 		/*
 		 * Device is bit capable of DMA'ing to the buffer... just return the PCI
 		 * address of ptr
 		 */
-		return pci_addr;
+		return dev_addr;
 
 	/*
 	 * get a bounce buffer:
 	 */
-	pci_addr = virt_to_phys(map_single(hwdev, ptr, size, direction));
+	dev_addr = virt_to_phys(map_single(hwdev, ptr, size, dir));
 
 	/*
 	 * Ensure that the address returned is DMA'ble:
 	 */
-	if ((pci_addr & ~hwdev->dma_mask) != 0)
+	if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0)
 		panic("map_single: bounce buffer is not DMA'ble");
 
-	return pci_addr;
+	return dev_addr;
 }
 
 /*
@@ -363,15 +363,15 @@
  * device wrote there.
  */
 void
-swiotlb_unmap_single (struct pci_dev *hwdev, dma_addr_t pci_addr, size_t size, int direction)
+swiotlb_unmap_single (struct device *hwdev, dma_addr_t dev_addr, size_t size, int dir)
 {
-	char *dma_addr = phys_to_virt(pci_addr);
+	char *dma_addr = phys_to_virt(dev_addr);
 
-	if (direction == PCI_DMA_NONE)
+	if (dir == DMA_NONE)
 		BUG();
 	if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end)
-		unmap_single(hwdev, dma_addr, size, direction);
-	else if (direction == PCI_DMA_FROMDEVICE)
+		unmap_single(hwdev, dma_addr, size, dir);
+	else if (dir == DMA_FROM_DEVICE)
 		mark_clean(dma_addr, size);
 }
 
@@ -385,21 +385,21 @@
  * again owns the buffer.
  */
 void
-swiotlb_sync_single (struct pci_dev *hwdev, dma_addr_t pci_addr, size_t size, int direction)
+swiotlb_sync_single (struct device *hwdev, dma_addr_t dev_addr, size_t size, int dir)
 {
-	char *dma_addr = phys_to_virt(pci_addr);
+	char *dma_addr = phys_to_virt(dev_addr);
 
-	if (direction == PCI_DMA_NONE)
+	if (dir == DMA_NONE)
 		BUG();
 	if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end)
-		sync_single(hwdev, dma_addr, size, direction);
-	else if (direction == PCI_DMA_FROMDEVICE)
+		sync_single(hwdev, dma_addr, size, dir);
+	else if (dir == DMA_FROM_DEVICE)
 		mark_clean(dma_addr, size);
 }
 
 /*
  * Map a set of buffers described by scatterlist in streaming mode for DMA.  This is the
- * scather-gather version of the above swiotlb_map_single interface.  Here the scatter
+ * scatter-gather version of the above swiotlb_map_single interface.  Here the scatter
  * gather list elements are each tagged with the appropriate dma address and length.  They
  * are obtained via sg_dma_{address,length}(SG).
  *
@@ -412,23 +412,22 @@
  * Device ownership issues as mentioned above for swiotlb_map_single are the same here.
  */
 int
-swiotlb_map_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction)
+swiotlb_map_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int dir)
 {
 	void *addr;
-	unsigned long pci_addr;
+	unsigned long dev_addr;
 	int i;
 
-	if (direction == PCI_DMA_NONE)
+	if (dir == DMA_NONE)
 		BUG();
 
 	for (i = 0; i < nelems; i++, sg++) {
 		addr = SG_ENT_VIRT_ADDRESS(sg);
-		pci_addr = virt_to_phys(addr);
-		if ((pci_addr & ~hwdev->dma_mask) != 0)
-			sg->dma_address = (dma_addr_t)
-				map_single(hwdev, addr, sg->length, direction);
+		dev_addr = virt_to_phys(addr);
+		if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0)
+			sg->dma_address = (dma_addr_t) map_single(hwdev, addr, sg->length, dir);
 		else
-			sg->dma_address = pci_addr;
+			sg->dma_address = dev_addr;
 		sg->dma_length = sg->length;
 	}
 	return nelems;
@@ -439,17 +438,17 @@
  * here are the same as for swiotlb_unmap_single() above.
  */
 void
-swiotlb_unmap_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction)
+swiotlb_unmap_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int dir)
 {
 	int i;
 
-	if (direction == PCI_DMA_NONE)
+	if (dir == DMA_NONE)
 		BUG();
 
 	for (i = 0; i < nelems; i++, sg++)
 		if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
-			unmap_single(hwdev, (void *) sg->dma_address, sg->dma_length, direction);
-		else if (direction == PCI_DMA_FROMDEVICE)
+			unmap_single(hwdev, (void *) sg->dma_address, sg->dma_length, dir);
+		else if (dir == DMA_FROM_DEVICE)
 			mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
 }
 
@@ -461,16 +460,16 @@
  * usage.
  */
 void
-swiotlb_sync_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction)
+swiotlb_sync_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int dir)
 {
 	int i;
 
-	if (direction == PCI_DMA_NONE)
+	if (dir == DMA_NONE)
 		BUG();
 
 	for (i = 0; i < nelems; i++, sg++)
 		if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
-			sync_single(hwdev, (void *) sg->dma_address, sg->dma_length, direction);
+			sync_single(hwdev, (void *) sg->dma_address, sg->dma_length, dir);
 }
 
 /*
@@ -479,7 +478,7 @@
  * you would pass 0x00ffffff as the mask to this function.
  */
 int
-swiotlb_pci_dma_supported (struct pci_dev *hwdev, u64 mask)
+swiotlb_dma_supported (struct device *hwdev, u64 mask)
 {
 	return 1;
 }
@@ -491,6 +490,6 @@
 EXPORT_SYMBOL(swiotlb_unmap_sg);
 EXPORT_SYMBOL(swiotlb_sync_single);
 EXPORT_SYMBOL(swiotlb_sync_sg);
-EXPORT_SYMBOL(swiotlb_alloc_consistent);
-EXPORT_SYMBOL(swiotlb_free_consistent);
-EXPORT_SYMBOL(swiotlb_pci_dma_supported);
+EXPORT_SYMBOL(swiotlb_alloc_coherent);
+EXPORT_SYMBOL(swiotlb_free_coherent);
+EXPORT_SYMBOL(swiotlb_dma_supported);
diff -urN linux-2.5.69-bk6/arch/ia64/mm/fault.c linux-2.5.69-bk7/arch/ia64/mm/fault.c
--- linux-2.5.69-bk6/arch/ia64/mm/fault.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/mm/fault.c	2003-05-12 04:43:29.000000000 -0700
@@ -58,6 +58,18 @@
 	if (in_atomic() || !mm)
 		goto no_context;
 
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+	/*
+	 * If fault is in region 5 and we are in the kernel, we may already
+	 * have the mmap_sem (pfn_valid macro is called during mmap). There
+	 * is no vma for region 5 addr's anyway, so skip getting the semaphore
+	 * and go directly to the exception handling code.
+	 */
+
+	if ((REGION_NUMBER(address) == 5) && !user_mode(regs))
+		goto bad_area_no_up;
+#endif
+
 	down_read(&mm->mmap_sem);
 
 	vma = find_vma_prev(mm, address, &prev_vma);
@@ -139,6 +151,9 @@
 
   bad_area:
 	up_read(&mm->mmap_sem);
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+  bad_area_no_up:
+#endif
 	if ((isr & IA64_ISR_SP)
 	    || ((isr & IA64_ISR_NA) && (isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH))
 	{
diff -urN linux-2.5.69-bk6/arch/ia64/mm/init.c linux-2.5.69-bk7/arch/ia64/mm/init.c
--- linux-2.5.69-bk6/arch/ia64/mm/init.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/mm/init.c	2003-05-12 04:43:29.000000000 -0700
@@ -38,6 +38,13 @@
 
 unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL;
 
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+# define LARGE_GAP	0x40000000	/* Use virtual mem map if hole is > than this */
+  unsigned long vmalloc_end = VMALLOC_END_INIT;
+  static struct page *vmem_map;
+  static unsigned long num_dma_physpages;
+#endif
+
 static int pgt_cache_water[2] = { 25, 50 };
 
 void
@@ -48,13 +55,13 @@
 	low = pgt_cache_water[0];
 	high = pgt_cache_water[1];
 
-	if (pgtable_cache_size > high) {
+	if (pgtable_cache_size > (u64) high) {
 		do {
 			if (pgd_quicklist)
 				free_page((unsigned long)pgd_alloc_one_fast(0));
 			if (pmd_quicklist)
 				free_page((unsigned long)pmd_alloc_one_fast(0, 0));
-		} while (pgtable_cache_size > low);
+		} while (pgtable_cache_size > (u64) low);
 	}
 }
 
@@ -337,6 +344,139 @@
 	ia64_tlb_init();
 }
 
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+
+static int
+create_mem_map_page_table (u64 start, u64 end, void *arg)
+{
+	unsigned long address, start_page, end_page;
+	struct page *map_start, *map_end;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	map_start = vmem_map + (__pa(start) >> PAGE_SHIFT);
+	map_end   = vmem_map + (__pa(end) >> PAGE_SHIFT);
+
+	start_page = (unsigned long) map_start & PAGE_MASK;
+	end_page = PAGE_ALIGN((unsigned long) map_end);
+
+	for (address = start_page; address < end_page; address += PAGE_SIZE) {
+		pgd = pgd_offset_k(address);
+		if (pgd_none(*pgd))
+			pgd_populate(&init_mm, pgd, alloc_bootmem_pages(PAGE_SIZE));
+		pmd = pmd_offset(pgd, address);
+
+		if (pmd_none(*pmd))
+			pmd_populate_kernel(&init_mm, pmd, alloc_bootmem_pages(PAGE_SIZE));
+		pte = pte_offset_kernel(pmd, address);
+
+		if (pte_none(*pte))
+			set_pte(pte, pfn_pte(__pa(alloc_bootmem_pages(PAGE_SIZE)) >> PAGE_SHIFT,
+					     PAGE_KERNEL));
+	}
+	return 0;
+}
+
+struct memmap_init_callback_data {
+	struct page *start;
+	struct page *end;
+	int nid;
+	unsigned long zone;
+};
+
+static int
+virtual_memmap_init (u64 start, u64 end, void *arg)
+{
+	struct memmap_init_callback_data *args;
+	struct page *map_start, *map_end;
+
+	args = (struct memmap_init_callback_data *) arg;
+
+	map_start = vmem_map + (__pa(start) >> PAGE_SHIFT);
+	map_end   = vmem_map + (__pa(end) >> PAGE_SHIFT);
+
+	if (map_start < args->start)
+		map_start = args->start;
+	if (map_end > args->end)
+		map_end = args->end;
+
+	/*
+	 * We have to initialize "out of bounds" struct page elements that fit completely
+	 * on the same pages that were allocated for the "in bounds" elements because they
+	 * may be referenced later (and found to be "reserved").
+	 */
+	map_start -= ((unsigned long) map_start & (PAGE_SIZE - 1)) / sizeof(struct page);
+	map_end += ((PAGE_ALIGN((unsigned long) map_end) - (unsigned long) map_end)
+		    / sizeof(struct page));
+
+	if (map_start < map_end)
+		memmap_init_zone(map_start, (unsigned long) (map_end - map_start),
+				 args->nid, args->zone, page_to_pfn(map_start));
+	return 0;
+}
+
+void
+memmap_init (struct page *start, unsigned long size, int nid,
+	     unsigned long zone, unsigned long start_pfn)
+{
+	if (!vmem_map)
+		memmap_init_zone(start, size, nid, zone, start_pfn);
+	else {
+		struct memmap_init_callback_data args;
+
+		args.start = start;
+		args.end = start + size;
+		args.nid = nid;
+		args.zone = zone;
+
+		efi_memmap_walk(virtual_memmap_init, &args);
+	}
+}
+
+int
+ia64_pfn_valid (unsigned long pfn)
+{
+	char byte;
+
+	return __get_user(byte, (char *) pfn_to_page(pfn)) == 0;
+}
+
+static int
+count_dma_pages (u64 start, u64 end, void *arg)
+{
+	unsigned long *count = arg;
+
+	if (end <= MAX_DMA_ADDRESS)
+		*count += (end - start) >> PAGE_SHIFT;
+	return 0;
+}
+
+static int
+find_largest_hole (u64 start, u64 end, void *arg)
+{
+	u64 *max_gap = arg;
+
+	static u64 last_end = PAGE_OFFSET;
+
+	/* NOTE: this algorithm assumes efi memmap table is ordered */
+
+	if (*max_gap < (start - last_end))
+		*max_gap = start - last_end;
+	last_end = end;
+	return 0;
+}
+#endif /* CONFIG_VIRTUAL_MEM_MAP */
+
+static int
+count_pages (u64 start, u64 end, void *arg)
+{
+	unsigned long *count = arg;
+
+	*count += (end - start) >> PAGE_SHIFT;
+	return 0;
+}
+
 /*
  * Set up the page tables.
  */
@@ -348,18 +488,70 @@
 	extern void discontig_paging_init(void);
 
 	discontig_paging_init();
+	efi_memmap_walk(count_pages, &num_physpages);
 }
 #else /* !CONFIG_DISCONTIGMEM */
 void
 paging_init (void)
 {
-	unsigned long max_dma, zones_size[MAX_NR_ZONES];
+	unsigned long max_dma;
+	unsigned long zones_size[MAX_NR_ZONES];
+#  ifdef CONFIG_VIRTUAL_MEM_MAP
+	unsigned long zholes_size[MAX_NR_ZONES];
+	unsigned long max_gap;
+#  endif
 
 	/* initialize mem_map[] */
 
 	memset(zones_size, 0, sizeof(zones_size));
 
+	num_physpages = 0;
+	efi_memmap_walk(count_pages, &num_physpages);
+
 	max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+
+#  ifdef CONFIG_VIRTUAL_MEM_MAP
+	memset(zholes_size, 0, sizeof(zholes_size));
+
+	num_dma_physpages = 0;
+	efi_memmap_walk(count_dma_pages, &num_dma_physpages);
+
+	if (max_low_pfn < max_dma) {
+		zones_size[ZONE_DMA] = max_low_pfn;
+		zholes_size[ZONE_DMA] = max_low_pfn - num_dma_physpages;
+	} else {
+		zones_size[ZONE_DMA] = max_dma;
+		zholes_size[ZONE_DMA] = max_dma - num_dma_physpages;
+		if (num_physpages > num_dma_physpages) {
+			zones_size[ZONE_NORMAL] = max_low_pfn - max_dma;
+			zholes_size[ZONE_NORMAL] = ((max_low_pfn - max_dma)
+						    - (num_physpages - num_dma_physpages));
+		}
+	}
+
+	max_gap = 0;
+	efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
+	if (max_gap < LARGE_GAP) {
+		vmem_map = (struct page *) 0;
+		free_area_init_node(0, &contig_page_data, NULL, zones_size, 0, zholes_size);
+		mem_map = contig_page_data.node_mem_map;
+	}
+	else {
+		unsigned long map_size;
+
+		/* allocate virtual_mem_map */
+
+		map_size = PAGE_ALIGN(max_low_pfn * sizeof(struct page));
+		vmalloc_end -= map_size;
+		vmem_map = (struct page *) vmalloc_end;
+		efi_memmap_walk(create_mem_map_page_table, 0);
+
+		free_area_init_node(0, &contig_page_data, vmem_map, zones_size, 0, zholes_size);
+
+		mem_map = contig_page_data.node_mem_map;
+		printk("Virtual mem_map starts at 0x%p\n", mem_map);
+	}
+#  else /* !CONFIG_VIRTUAL_MEM_MAP */
 	if (max_low_pfn < max_dma)
 		zones_size[ZONE_DMA] = max_low_pfn;
 	else {
@@ -367,19 +559,11 @@
 		zones_size[ZONE_NORMAL] = max_low_pfn - max_dma;
 	}
 	free_area_init(zones_size);
+#  endif /* !CONFIG_VIRTUAL_MEM_MAP */
 }
 #endif /* !CONFIG_DISCONTIGMEM */
 
 static int
-count_pages (u64 start, u64 end, void *arg)
-{
-	unsigned long *count = arg;
-
-	*count += (end - start) >> PAGE_SHIFT;
-	return 0;
-}
-
-static int
 count_reserved_pages (u64 start, u64 end, void *arg)
 {
 	unsigned long num_reserved = 0;
@@ -406,7 +590,7 @@
 	 * any drivers that may need the PCI DMA interface are initialized or bootmem has
 	 * been freed.
 	 */
-	platform_pci_dma_init();
+	platform_dma_init();
 #endif
 
 #ifndef CONFIG_DISCONTIGMEM
@@ -415,9 +599,6 @@
 	max_mapnr = max_low_pfn;
 #endif
 
-	num_physpages = 0;
-	efi_memmap_walk(count_pages, &num_physpages);
-
 	high_memory = __va(max_low_pfn * PAGE_SIZE);
 
 	for_each_pgdat(pgdat)
@@ -445,7 +626,7 @@
 	num_pgt_pages = nr_free_pages() / PTRS_PER_PGD + NUM_TASKS;
 	if (num_pgt_pages > nr_free_pages() / 10)
 		num_pgt_pages = nr_free_pages() / 10;
-	if (num_pgt_pages > pgt_cache_water[1])
+	if (num_pgt_pages > (u64) pgt_cache_water[1])
 		pgt_cache_water[1] = num_pgt_pages;
 
 	/* install the gate page in the global page table: */
diff -urN linux-2.5.69-bk6/arch/ia64/pci/pci.c linux-2.5.69-bk7/arch/ia64/pci/pci.c
--- linux-2.5.69-bk6/arch/ia64/pci/pci.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/pci/pci.c	2003-05-12 04:43:29.000000000 -0700
@@ -5,6 +5,7 @@
  *
  * Copyright (C) 2002 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
+ *	Bjorn Helgaas <bjorn_helgaas@hp.com>
  *
  * Note: Above list of copyright holders is incomplete...
  */
@@ -116,31 +117,10 @@
 
 subsys_initcall(pci_acpi_init);
 
-static void __init
-pcibios_fixup_resource(struct resource *res, u64 offset)
-{
-	res->start += offset;
-	res->end += offset;
-}
-
-void __init
-pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus)
-{
-	int i;
-
-	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-		if (!dev->resource[i].start)
-			continue;
-		if (dev->resource[i].flags & IORESOURCE_MEM)
-			pcibios_fixup_resource(&dev->resource[i],
-			                       PCI_CONTROLLER(dev)->mem_offset);
-	}
-}
-
 /* Called by ACPI when it finds a new root bus.  */
 
 static struct pci_controller *
-alloc_pci_controller(int seg)
+alloc_pci_controller (int seg)
 {
 	struct pci_controller *controller;
 
@@ -153,8 +133,8 @@
 	return controller;
 }
 
-struct pci_bus *
-scan_root_bus(int bus, struct pci_ops *ops, void *sysdata)
+static struct pci_bus *
+scan_root_bus (int bus, struct pci_ops *ops, void *sysdata)
 {
 	struct pci_bus *b;
 
@@ -184,23 +164,185 @@
 	return b;
 }
 
+static int
+alloc_resource (char *name, struct resource *root, unsigned long start, unsigned long end, unsigned long flags)
+{
+	struct resource *res;
+
+	res = kmalloc(sizeof(*res), GFP_KERNEL);
+	if (!res)
+		return -ENOMEM;
+
+	memset(res, 0, sizeof(*res));
+	res->name = name;
+	res->start = start;
+	res->end = end;
+	res->flags = flags;
+
+	if (request_resource(root, res))
+		return -EBUSY;
+
+	return 0;
+}
+
+static u64
+add_io_space (struct acpi_resource_address64 *addr)
+{
+	u64 offset;
+	int sparse = 0;
+	int i;
+
+	if (addr->address_translation_offset == 0)
+		return IO_SPACE_BASE(0);	/* part of legacy IO space */
+
+	if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION)
+		sparse = 1;
+
+	offset = (u64) ioremap(addr->address_translation_offset, 0);
+	for (i = 0; i < num_io_spaces; i++)
+		if (io_space[i].mmio_base == offset &&
+		    io_space[i].sparse == sparse)
+			return IO_SPACE_BASE(i);
+
+	if (num_io_spaces == MAX_IO_SPACES) {
+		printk("Too many IO port spaces\n");
+		return ~0;
+	}
+
+	i = num_io_spaces++;
+	io_space[i].mmio_base = offset;
+	io_space[i].sparse = sparse;
+
+	return IO_SPACE_BASE(i);
+}
+
+static acpi_status
+count_window (struct acpi_resource *resource, void *data)
+{
+	unsigned int *windows = (unsigned int *) data;
+	struct acpi_resource_address64 addr;
+	acpi_status status;
+
+	status = acpi_resource_to_address64(resource, &addr);
+	if (ACPI_SUCCESS(status))
+		if (addr.resource_type == ACPI_MEMORY_RANGE ||
+		    addr.resource_type == ACPI_IO_RANGE)
+			(*windows)++;
+
+	return AE_OK;
+}
+
+struct pci_root_info {
+	struct pci_controller *controller;
+	char *name;
+};
+
+static acpi_status
+add_window (struct acpi_resource *res, void *data)
+{
+	struct pci_root_info *info = (struct pci_root_info *) data;
+	struct pci_window *window;
+	struct acpi_resource_address64 addr;
+	acpi_status status;
+	unsigned long flags, offset = 0;
+	struct resource *root;
+
+	status = acpi_resource_to_address64(res, &addr);
+	if (ACPI_SUCCESS(status)) {
+		if (addr.resource_type == ACPI_MEMORY_RANGE) {
+			flags = IORESOURCE_MEM;
+			root = &iomem_resource;
+			offset = addr.address_translation_offset;
+		} else if (addr.resource_type == ACPI_IO_RANGE) {
+			flags = IORESOURCE_IO;
+			root = &ioport_resource;
+			offset = add_io_space(&addr);
+			if (offset == ~0)
+				return AE_OK;
+		} else
+			return AE_OK;
+
+		window = &info->controller->window[info->controller->windows++];
+		window->resource.flags |= flags;
+		window->resource.start  = addr.min_address_range;
+		window->resource.end    = addr.max_address_range;
+		window->offset		= offset;
+
+		if (alloc_resource(info->name, root, addr.min_address_range + offset,
+			addr.max_address_range + offset, flags))
+			printk(KERN_ERR "alloc 0x%lx-0x%lx from %s for %s failed\n",
+				addr.min_address_range + offset, addr.max_address_range + offset,
+				root->name, info->name);
+	}
+
+	return AE_OK;
+}
+
 struct pci_bus *
-pcibios_scan_root(void *handle, int seg, int bus)
+pcibios_scan_root (void *handle, int seg, int bus)
 {
+	struct pci_root_info info;
 	struct pci_controller *controller;
-	u64 base, size, offset;
+	unsigned int windows = 0;
+	char *name;
 
 	printk("PCI: Probing PCI hardware on bus (%02x:%02x)\n", seg, bus);
 	controller = alloc_pci_controller(seg);
 	if (!controller)
-		return NULL;
+		goto out1;
 
 	controller->acpi_handle = handle;
 
-	acpi_get_addr_space(handle, ACPI_MEMORY_RANGE, &base, &size, &offset);
-	controller->mem_offset = offset;
+	acpi_walk_resources(handle, METHOD_NAME__CRS, count_window, &windows);
+	controller->window = kmalloc(sizeof(*controller->window) * windows, GFP_KERNEL);
+	if (!controller->window)
+		goto out2;
+
+	name = kmalloc(16, GFP_KERNEL);
+	if (!name)
+		goto out3;
+
+	sprintf(name, "PCI Bus %02x:%02x", seg, bus);
+	info.controller = controller;
+	info.name = name;
+	acpi_walk_resources(handle, METHOD_NAME__CRS, add_window, &info);
 
 	return scan_root_bus(bus, pci_root_ops, controller);
+
+out3:
+	kfree(controller->window);
+out2:
+	kfree(controller);
+out1:
+	return NULL;
+}
+
+void __init
+pcibios_fixup_device_resources (struct pci_dev *dev, struct pci_bus *bus)
+{
+	struct pci_controller *controller = PCI_CONTROLLER(dev);
+	struct pci_window *window;
+	int i, j;
+
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		if (!dev->resource[i].start)
+			continue;
+
+#define contains(win, res)	((res)->start >= (win)->start && \
+				 (res)->end   <= (win)->end)
+
+		for (j = 0; j < controller->windows; j++) {
+			window = &controller->window[j];
+			if (((dev->resource[i].flags & IORESOURCE_MEM &&
+			      window->resource.flags & IORESOURCE_MEM) ||
+			     (dev->resource[i].flags & IORESOURCE_IO &&
+			      window->resource.flags & IORESOURCE_IO)) &&
+			    contains(&window->resource, &dev->resource[i])) {
+				dev->resource[i].start += window->offset;
+				dev->resource[i].end   += window->offset;
+			}
+		}
+	}
 }
 
 /*
diff -urN linux-2.5.69-bk6/arch/ia64/sn/kernel/machvec.c linux-2.5.69-bk7/arch/ia64/sn/kernel/machvec.c
--- linux-2.5.69-bk6/arch/ia64/sn/kernel/machvec.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/sn/kernel/machvec.c	2003-05-12 04:43:29.000000000 -0700
@@ -33,9 +33,11 @@
 #include <linux/config.h>
 
 #ifdef CONFIG_IA64_SGI_SN1
-#define MACHVEC_PLATFORM_NAME	sn1
+#define MACHVEC_PLATFORM_NAME		sn1
+#define MACHVEC_PLATFORM_HEADER		<asm/machvec_sn1.h>
 #else CONFIG_IA64_SGI_SN1
-#define MACHVEC_PLATFORM_NAME	sn2
+#define MACHVEC_PLATFORM_NAME		sn2
+#define MACHVEC_PLATFORM_HEADER		<asm/machvec_sn2.h>
 #else
 #error "unknown platform"
 #endif
diff -urN linux-2.5.69-bk6/arch/ia64/tools/print_offsets.c linux-2.5.69-bk7/arch/ia64/tools/print_offsets.c
--- linux-2.5.69-bk6/arch/ia64/tools/print_offsets.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk7/arch/ia64/tools/print_offsets.c	2003-05-12 04:43:29.000000000 -0700
@@ -193,7 +193,7 @@
   printf ("/*\n * DO NOT MODIFY\n *\n * This file was generated by "
 	  "arch/ia64/tools/print_offsets.\n *\n */\n\n");
 
-  for (i = 0; i < sizeof (tab) / sizeof (tab[0]); ++i)
+  for (i = 0; i < (int) (sizeof (tab) / sizeof (tab[0])); ++i)
     {
       if (tab[i].name[0] == '\0')
 	printf ("\n");
diff -urN linux-2.5.69-bk6/drivers/Makefile linux-2.5.69-bk7/drivers/Makefile
--- linux-2.5.69-bk6/drivers/Makefile	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk7/drivers/Makefile	2003-05-12 04:43:29.000000000 -0700
@@ -37,6 +37,7 @@
 obj-$(CONFIG_PARIDE) 		+= block/paride/
 obj-$(CONFIG_TC)		+= tc/
 obj-$(CONFIG_USB)		+= usb/
+obj-$(CONFIG_USB_GADGET)	+= usb/gadget/
 obj-$(CONFIG_INPUT)		+= input/
 obj-$(CONFIG_GAMEPORT)		+= input/gameport/
 obj-$(CONFIG_SERIO)		+= input/serio/
diff -urN linux-2.5.69-bk6/drivers/char/agp/Kconfig linux-2.5.69-bk7/drivers/char/agp/Kconfig
--- linux-2.5.69-bk6/drivers/char/agp/Kconfig	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/Kconfig	2003-05-12 04:43:29.000000000 -0700
@@ -1,6 +1,6 @@
 config AGP
 	tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU
-	default AGP_GART if GART_IOMMU
+	default y if GART_IOMMU
 	---help---
 	  AGP (Accelerated Graphics Port) is a bus system mainly used to
 	  connect graphics cards to the rest of the system.
@@ -25,54 +25,66 @@
 	  a module, say M here and read <file:Documentation/modules.txt>.  The
 	  module will be called agpgart.
 
-config AGP_GART
-	bool "/dev/agpgart (AGP Support)"
-	depends on GART_IOMMU
-
-config AGP_INTEL
-	tristate "Intel 440LX/BX/GX, I8xx and E7x05 support"
-	depends on AGP && !X86_64
-	help
+config AGP_ALI
+	tristate "ALI chipset support"
+	depends on AGP && X86 && !X86_64
+	---help---
 	  This option gives you AGP support for the GLX component of the
-	  XFree86 4.x on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860
-	  E7205 and E7505 chipsets and full support for the 810, 815, 830M, 845G,
-	  852GM, 855GM and 865G integrated graphics chipsets.
+	  XFree86 4.x on the following ALi chipsets.  The supported chipsets
+	  include M1541, M1621, M1631, M1632, M1641,M1647,and M1651.
+	  For the ALi-chipset question, ALi suggests you refer to
+	  <http://www.ali.com.tw/eng/support/index.shtml>.
 
-	  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
-	  use GLX or DRI, or if you have any Intel integrated graphics
-	  chipsets.  If unsure, say Y.
+	  The M1541 chipset can do AGP 1x and 2x, but note that there is an
+	  acknowledged incompatibility with Matrox G200 cards. Due to
+	  timing issues, this chipset cannot do AGP 2x with the G200.
+	  This is a hardware limitation. AGP 1x seems to be fine, though.
 
-#config AGP_I810
-#	tristate "Intel I810/I815/I830M (on-board) support"
-#	depends on AGP && !X86_64
-#	help
-#	  This option gives you AGP support for the Xserver on the Intel 810
-#	  815 and 830m chipset boards for their on-board integrated graphics. This
-#	  is required to do any useful video modes with these boards.
+	  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
+	  use GLX or DRI.  If unsure, say N.
 
-config AGP_VIA
-	tristate "VIA chipset support"
-	depends on AGP && !X86_64
+config AGP_AMD
+	tristate "AMD Irongate, 761, and 762 chipset support"
+	depends on AGP && X86 && !X86_64
 	help
 	  This option gives you AGP support for the GLX component of the
-	  XFree86 4.x on VIA MPV3/Apollo Pro chipsets.
+	  XFree86 4.x on AMD Irongate, 761, and 762 chipsets.
 
 	  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
 	  use GLX or DRI.  If unsure, say N.
 
-config AGP_AMD
-	tristate "AMD Irongate, 761, and 762 support"
-	depends on AGP && !X86_64
+config AGP_AMD_8151
+	tristate "AMD 8151 chipset support"
+	depends on AGP && X86
+	default GART_IOMMU
+	help
+	  Say Y here to support the AMD 8151 AGP bridge and the builtin
+	  GART on the AMD Athlon64/Opteron ("Hammer") CPUs.
+
+config AGP_INTEL
+	tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support"
+	depends on AGP && X86 && !X86_64
 	help
 	  This option gives you AGP support for the GLX component of the
-	  XFree86 4.x on AMD Irongate, 761, and 762 chipsets.
+	  XFree86 4.x on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860
+	  E7205 and E7505 chipsets and full support for the 810, 815, 830M, 845G,
+	  852GM, 855GM and 865G integrated graphics chipsets.
 
 	  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
-	  use GLX or DRI.  If unsure, say N.
+	  use GLX or DRI, or if you have any Intel integrated graphics
+	  chipsets.  If unsure, say Y.
+
+config AGP_NVIDIA
+	tristate "NVIDIA nForce/nForce2 chipset support"
+	depends on AGP && X86 && !X86_64
+	help
+	  This option gives you AGP support for the GLX component of the
+	  XFree86 4.x on the following NVIDIA chipsets.  The supported chipsets
+	  include nForce and nForce2
 
 config AGP_SIS
-	tristate "Generic SiS support"
-	depends on AGP && !X86_64
+	tristate "SiS chipset support"
+	depends on AGP && X86 && !X86_64
 	help
 	  This option gives you AGP support for the GLX component of the "soon
 	  to be released" XFree86 4.x on Silicon Integrated Systems [SiS]
@@ -83,55 +95,39 @@
 	  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
 	  use GLX or DRI.  If unsure, say N.
 
-config AGP_ALI
-	tristate "ALI chipset support"
-	depends on AGP && !X86_64
-	---help---
-	  This option gives you AGP support for the GLX component of the
-	  XFree86 4.x on the following ALi chipsets.  The supported chipsets
-	  include M1541, M1621, M1631, M1632, M1641,M1647,and M1651.
-	  For the ALi-chipset question, ALi suggests you refer to
-	  <http://www.ali.com.tw/eng/support/index.shtml>.
-
-	  The M1541 chipset can do AGP 1x and 2x, but note that there is an
-	  acknowledged incompatibility with Matrox G200 cards. Due to
-	  timing issues, this chipset cannot do AGP 2x with the G200.
-	  This is a hardware limitation. AGP 1x seems to be fine, though.
-
-	  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
-	  use GLX or DRI.  If unsure, say N.
-
 config AGP_SWORKS
-	tristate "Serverworks LE/HE support"
-	depends on AGP && !X86_64
+	tristate "Serverworks LE/HE chipset support"
+	depends on AGP && X86 && !X86_64
 	help
 	  Say Y here to support the Serverworks AGP card.  See 
 	  <http://www.serverworks.com/> for product descriptions and images.
 
-config AGP_AMD_8151
-	tristate "AMD 8151 support"
-	depends on AGP
-	default GART_IOMMU
+config AGP_VIA
+	tristate "VIA chipset support"
+	depends on AGP && X86 && !X86_64
 	help
-	  Say Y here to support the AMD 8151 AGP bridge and the builtin
-	  GART on the AMD Athlon64/Opteron ("Hammer") CPUs.
+	  This option gives you AGP support for the GLX component of the
+	  XFree86 4.x on VIA MPV3/Apollo Pro chipsets.
+
+	  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
+	  use GLX or DRI.  If unsure, say N.
 
 config AGP_I460
-	tristate "Intel 460GX support"
+	tristate "Intel 460GX chipset support"
 	depends on AGP && IA64
 	help
 	  This option gives you AGP GART support for the Intel 460GX chipset
 	  for IA64 processors.
 
 config AGP_HP_ZX1
-	tristate "HP ZX1 AGP support"
+	tristate "HP ZX1 chipset AGP support"
 	depends on AGP && IA64
 	help
 	  This option gives you AGP GART support for the HP ZX1 chipset
 	  for IA64 processors.
 
 config AGP_ALPHA_CORE
-	tristate
+	tristate "Alpha AGP support"
 	depends on AGP && (ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL)
 	default AGP
 
diff -urN linux-2.5.69-bk6/drivers/char/agp/Makefile linux-2.5.69-bk7/drivers/char/agp/Makefile
--- linux-2.5.69-bk6/drivers/char/agp/Makefile	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/Makefile	2003-05-12 04:43:29.000000000 -0700
@@ -1,21 +1,15 @@
-#
-# Makefile for the agpgart device driver.  This driver adds a user
-# space ioctl interface to use agp memory.  It also adds a kernel interface
-# that other drivers could use to manipulate agp memory.
-
 agpgart-y := backend.o frontend.o generic.o generic-3.0.o
-agpgart-objs := $(agpgart-y)
-obj-$(CONFIG_AGP) += agpgart.o
 
-obj-$(CONFIG_AGP_INTEL)		+= intel-agp.o
-obj-$(CONFIG_AGP_VIA)		+= via-agp.o
-obj-$(CONFIG_AGP_AMD)		+= amd-k7-agp.o
-obj-$(CONFIG_AGP_SIS)		+= sis-agp.o
+obj-$(CONFIG_AGP)		+= agpgart.o
 obj-$(CONFIG_AGP_ALI)		+= ali-agp.o
-obj-$(CONFIG_AGP_SWORKS)	+= sworks-agp.o
-obj-$(CONFIG_AGP_I460)		+= i460-agp.o
-obj-$(CONFIG_AGP_HP_ZX1)	+= hp-agp.o
+obj-$(CONFIG_AGP_AMD)		+= amd-k7-agp.o
 obj-$(CONFIG_AGP_AMD_8151)	+= amd-k8-agp.o
 obj-$(CONFIG_AGP_ALPHA_CORE)	+= alpha-agp.o
-
+obj-$(CONFIG_AGP_HP_ZX1)	+= hp-agp.o
+obj-$(CONFIG_AGP_I460)		+= i460-agp.o
+obj-$(CONFIG_AGP_INTEL)		+= intel-agp.o
+obj-$(CONFIG_AGP_NVIDIA)	+= nvidia-agp.o
+obj-$(CONFIG_AGP_SIS)		+= sis-agp.o
+obj-$(CONFIG_AGP_SWORKS)	+= sworks-agp.o
+obj-$(CONFIG_AGP_VIA)		+= via-agp.o
 
diff -urN linux-2.5.69-bk6/drivers/char/agp/agp.h linux-2.5.69-bk7/drivers/char/agp/agp.h
--- linux-2.5.69-bk6/drivers/char/agp/agp.h	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/agp.h	2003-05-12 04:43:29.000000000 -0700
@@ -30,27 +30,16 @@
 
 #include <asm/agp.h>	/* for flush_agp_cache() */
 
-extern struct agp_bridge_data *agp_bridge;
-
 #define PFX "agpgart: "
 
-#ifdef CONFIG_SMP
-static void ipi_handler(void *null)
-{
-	flush_agp_cache();
-}
-
-static void __attribute__((unused)) global_cache_flush(void)
-{
-	if (on_each_cpu(ipi_handler, NULL, 1, 1) != 0)
-		panic(PFX "timed out waiting for the other CPUs!\n");
-}
+//#define AGP_DEBUG 1
+#ifdef AGP_DEBUG
+#define DBG(x,y...) printk (KERN_DEBUG PFX "%s: " x "\n", __FUNCTION__ , ## y)
 #else
-static void global_cache_flush(void)
-{
-	flush_agp_cache();
-}
-#endif	/* !CONFIG_SMP */
+#define DBG(x,y...) do { } while (0)
+#endif
+
+extern struct agp_bridge_data *agp_bridge;
 
 enum aper_size_type {
 	U8_APER_SIZE,
@@ -101,14 +90,41 @@
 	int page_order;
 };
 
+struct agp_bridge_driver {
+	struct module *owner;
+	void *aperture_sizes;
+	int num_aperture_sizes;
+	enum aper_size_type size_type;
+	int cant_use_aperture;
+	int needs_scratch_page;
+	struct gatt_mask *masks;
+	int (*fetch_size)(void);
+	int (*configure)(void);
+	void (*agp_enable)(u32);
+	void (*cleanup)(void);
+	void (*tlb_flush)(agp_memory *);
+	unsigned long (*mask_memory)(unsigned long, int);
+	void (*cache_flush)(void);
+	int (*create_gatt_table)(void);
+	int (*free_gatt_table)(void);
+	int (*insert_memory)(agp_memory *, off_t, int);
+	int (*remove_memory)(agp_memory *, off_t, int);
+	agp_memory *(*alloc_by_type) (size_t, int);
+	void (*free_by_type)(agp_memory *);
+	void *(*agp_alloc_page)(void);
+	void (*agp_destroy_page)(void *);
+	int (*suspend)(void);
+	void (*resume)(void);
+};
+
 struct agp_bridge_data {
 	struct agp_version *version;
-	void *aperture_sizes;
+	struct agp_bridge_driver *driver;
+	struct vm_operations_struct *vm_ops;
 	void *previous_size;
 	void *current_size;
 	void *dev_private_data;
 	struct pci_dev *dev;
-	struct gatt_mask *masks;
 	u32 *gatt_table;
 	u32 *gatt_table_real;
 	unsigned long scratch_page;
@@ -117,38 +133,12 @@
 	unsigned long gatt_bus_addr;
 	u32 mode;
 	enum chipset_type type;
-	enum aper_size_type size_type;
 	unsigned long *key_list;
 	atomic_t current_memory_agp;
 	atomic_t agp_in_use;
 	int max_memory_agp;	/* in number of pages */
-	int needs_scratch_page;
 	int aperture_size_idx;
-	int num_aperture_sizes;
 	int capndx;
-	int cant_use_aperture;
-	struct vm_operations_struct *vm_ops;
-
-	/* Links to driver specific functions */
-
-	int (*fetch_size) (void);
-	int (*configure) (void);
-	void (*agp_enable) (u32);
-	void (*cleanup) (void);
-	void (*tlb_flush) (agp_memory *);
-	unsigned long (*mask_memory) (unsigned long, int);
-	void (*cache_flush) (void);
-	int (*create_gatt_table) (void);
-	int (*free_gatt_table) (void);
-	int (*insert_memory) (agp_memory *, off_t, int);
-	int (*remove_memory) (agp_memory *, off_t, int);
-	agp_memory *(*alloc_by_type) (size_t, int);
-	void (*free_by_type) (agp_memory *);
-	void *(*agp_alloc_page) (void);
-	void (*agp_destroy_page) (void *);
-	int (*suspend)(void);
-	void (*resume)(void);
-	
 };
 
 #define OUTREG64(mmap, addr, val)	__raw_writeq((val), (mmap)+(addr))
@@ -165,20 +155,17 @@
 #define MB(x)	(KB (KB (x)))
 #define GB(x)	(MB (KB (x)))
 
-#define CACHE_FLUSH	agp_bridge->cache_flush
 #define A_SIZE_8(x)	((struct aper_size_info_8 *) x)
 #define A_SIZE_16(x)	((struct aper_size_info_16 *) x)
 #define A_SIZE_32(x)	((struct aper_size_info_32 *) x)
 #define A_SIZE_LVL2(x)	((struct aper_size_info_lvl2 *) x)
 #define A_SIZE_FIX(x)	((struct aper_size_info_fixed *) x)
-#define A_IDX8()	(A_SIZE_8(agp_bridge->aperture_sizes) + i)
-#define A_IDX16()	(A_SIZE_16(agp_bridge->aperture_sizes) + i)
-#define A_IDX32()	(A_SIZE_32(agp_bridge->aperture_sizes) + i)
-#define A_IDXLVL2()	(A_SIZE_LVL2(agp_bridge->aperture_sizes) + i)
-#define A_IDXFIX()	(A_SIZE_FIX(agp_bridge->aperture_sizes) + i)
+#define A_IDX8(bridge)	(A_SIZE_8((bridge)->driver->aperture_sizes) + i)
+#define A_IDX16(bridge)	(A_SIZE_16((bridge)->driver->aperture_sizes) + i)
+#define A_IDX32(bridge)	(A_SIZE_32((bridge)->driver->aperture_sizes) + i)
 #define MAXKEY		(4096 * 32)
 
-#define PGE_EMPTY(p)	(!(p) || (p) == (unsigned long) agp_bridge->scratch_page)
+#define PGE_EMPTY(b, p)	(!(p) || (p) == (unsigned long) (b)->scratch_page)
 
 /* intel register */
 #define INTEL_APBASE	0x10
@@ -374,11 +361,15 @@
 	int (*chipset_setup) (struct pci_dev *pdev);	/* used to override generic */
 };
 
-struct agp_driver {
-	struct module *owner;
-	struct pci_dev *dev;
-};
-
+/* Driver registration */
+struct agp_bridge_data *agp_alloc_bridge(void);
+void agp_put_bridge(struct agp_bridge_data *bridge);
+int agp_add_bridge(struct agp_bridge_data *bridge);
+void agp_remove_bridge(struct agp_bridge_data *bridge);
+
+/* Frontend routines. */
+int agp_frontend_initialize(void);
+void agp_frontend_cleanup(void);
 
 /* Generic routines. */
 void agp_generic_enable(u32 mode);
@@ -395,10 +386,29 @@
 void agp_generic_resume(void);
 void agp_free_key(int key);
 int agp_num_entries(void);
-int agp_register_driver (struct agp_driver *drv);
-int agp_unregister_driver(struct agp_driver *drv);
 u32 agp_collect_device_status(u32 mode, u32 command);
 void agp_device_command(u32 command, int agp_v3);
-int agp_3_0_node_enable(u32 mode, u32 minor);
+int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor);
+void global_cache_flush(void);
+
+/* Standard agp registers */
+#define AGPSTAT			0x4
+#define AGPCMD			0x8
+#define AGPNEPG			0x16
+
+#define AGP_MAJOR_VERSION_SHIFT	(20)
+#define AGP_MINOR_VERSION_SHIFT	(16)
+
+#define AGPSTAT_RQ_DEPTH	(0xff000000)
+
+#define AGPSTAT_ARQSZ_SHIFT	13
+
+#define AGPSTAT_AGP_ENABLE	(1<<8)
+#define AGPSTAT_SBA		(1<<9)
+
+#define AGPSTAT2_1X		(1<<0)
+#define AGPSTAT2_2X		(1<<1)
+#define AGPSTAT2_4X		(1<<2)
+#define AGPSTAT_FW		(1<<4)
 
 #endif				/* _AGP_BACKEND_PRIV_H */
diff -urN linux-2.5.69-bk6/drivers/char/agp/ali-agp.c linux-2.5.69-bk7/drivers/char/agp/ali-agp.c
--- linux-2.5.69-bk6/drivers/char/agp/ali-agp.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/ali-agp.c	2003-05-12 04:43:29.000000000 -0700
@@ -19,9 +19,9 @@
 
 	pci_read_config_dword(agp_bridge->dev, ALI_ATTBASE, &temp);
 	temp &= ~(0xfffffff0);
-	values = A_SIZE_32(agp_bridge->aperture_sizes);
+	values = A_SIZE_32(agp_bridge->driver->aperture_sizes);
 
-	for (i = 0; i < agp_bridge->num_aperture_sizes; i++) {
+	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
 		if (temp == values[i].size_value) {
 			agp_bridge->previous_size =
 			    agp_bridge->current_size = (void *) (values + i);
@@ -118,47 +118,51 @@
 {
 	/* Memory type is ignored */
 
-	return addr | agp_bridge->masks[0].mask;
+	return addr | agp_bridge->driver->masks[0].mask;
 }
 
-static void ali_cache_flush(void)
+static void m1541_cache_flush(void)
 {
-	global_cache_flush();
+	int i, page_count;
+	u32 temp;
 
-	if (agp_bridge->type == ALI_M1541) {
-		int i, page_count;
-		u32 temp;
+	global_cache_flush();
 
-		page_count = 1 << A_SIZE_32(agp_bridge->current_size)->page_order;
-		for (i = 0; i < PAGE_SIZE * page_count; i += PAGE_SIZE) {
-			pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
-			pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
-					(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
-					  (agp_bridge->gatt_bus_addr + i)) |
-					    ALI_CACHE_FLUSH_EN));
-		}
+	page_count = 1 << A_SIZE_32(agp_bridge->current_size)->page_order;
+	for (i = 0; i < PAGE_SIZE * page_count; i += PAGE_SIZE) {
+		pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
+				&temp);
+		pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
+				(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
+				  (agp_bridge->gatt_bus_addr + i)) |
+				 ALI_CACHE_FLUSH_EN));
 	}
 }
 
-static void *ali_alloc_page(void)
+static void *m1541_alloc_page(void)
 {
-	void *adr = agp_generic_alloc_page();
+	void *addr = agp_generic_alloc_page();
 	u32 temp;
 
-	if (adr == 0)
-		return 0;
+	if (!addr)
+		return NULL;
+	
+	pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
+	pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
+			(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
+			  virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN ));
+	return addr;
+}
 
-	if (agp_bridge->type == ALI_M1541) {
-		pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
-		pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
-				(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
-				  virt_to_phys(adr)) |
-				    ALI_CACHE_FLUSH_EN ));
+static void ali_destroy_page(void * addr)
+{
+	if (addr) {
+		global_cache_flush();	/* is this really needed?  --hch */
+		agp_generic_destroy_page(addr);
 	}
-	return adr;
 }
 
-static void ali_destroy_page(void * addr)
+static void m1541_destroy_page(void * addr)
 {
 	u32 temp;
 
@@ -167,17 +171,14 @@
 
 	global_cache_flush();
 
-	if (agp_bridge->type == ALI_M1541) {
-		pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
-		pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
-				(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
-				  virt_to_phys(addr)) |
-				    ALI_CACHE_FLUSH_EN));
-	}
-
+	pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
+	pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
+			(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
+			  virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN));
 	agp_generic_destroy_page(addr);
 }
 
+
 /* Setup function */
 static struct gatt_mask ali_generic_masks[] =
 {
@@ -195,170 +196,185 @@
 	{4, 1024, 0, 3}
 };
 
-static int __init ali_generic_setup (struct pci_dev *pdev)
-{
-	agp_bridge->masks = ali_generic_masks;
-	agp_bridge->aperture_sizes = (void *) ali_generic_sizes;
-	agp_bridge->size_type = U32_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 7;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = ali_configure;
-	agp_bridge->fetch_size = ali_fetch_size;
-	agp_bridge->cleanup = ali_cleanup;
-	agp_bridge->tlb_flush = ali_tlbflush;
-	agp_bridge->mask_memory = ali_mask_memory;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->cache_flush = ali_cache_flush;
-	agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
-	agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
-	agp_bridge->insert_memory = agp_generic_insert_memory;
-	agp_bridge->remove_memory = agp_generic_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = ali_alloc_page;
-	agp_bridge->agp_destroy_page = ali_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
-	return 0;
-}
+struct agp_bridge_driver ali_generic_bridge = {
+	.owner			= THIS_MODULE,
+	.masks			= ali_generic_masks,
+	.aperture_sizes		= ali_generic_sizes,
+	.size_type		= U32_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= ali_configure,
+	.fetch_size		= ali_fetch_size,
+	.cleanup		= ali_cleanup,
+	.tlb_flush		= ali_tlbflush,
+	.mask_memory		= ali_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= ali_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
+
+struct agp_bridge_driver ali_m1541_bridge = {
+	.owner			= THIS_MODULE,
+	.masks			= ali_generic_masks,
+	.aperture_sizes		= ali_generic_sizes,
+	.size_type		= U32_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= ali_configure,
+	.fetch_size		= ali_fetch_size,
+	.cleanup		= ali_cleanup,
+	.tlb_flush		= ali_tlbflush,
+	.mask_memory		= ali_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= m1541_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= m1541_alloc_page,
+	.agp_destroy_page	= m1541_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
+
 
 struct agp_device_ids ali_agp_device_ids[] __initdata =
 {
 	{
 		.device_id	= PCI_DEVICE_ID_AL_M1541,
-		.chipset	= ALI_M1541,
 		.chipset_name	= "M1541",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_AL_M1621,
-		.chipset	= ALI_M1621,
 		.chipset_name	= "M1621",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_AL_M1631,
-		.chipset	= ALI_M1631,
 		.chipset_name	= "M1631",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_AL_M1632,
-		.chipset	= ALI_M1632,
 		.chipset_name	= "M1632",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_AL_M1641,
-		.chipset	= ALI_M1641,
 		.chipset_name	= "M1641",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_AL_M1644,
-		.chipset	= ALI_M1644,
 		.chipset_name	= "M1644",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_AL_M1647,
-		.chipset	= ALI_M1647,
 		.chipset_name	= "M1647",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_AL_M1651,
-		.chipset	= ALI_M1651,
 		.chipset_name	= "M1651",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_AL_M1671,
-		.chipset	= ALI_M1671,
 		.chipset_name	= "M1671",
 	},
 	{ }, /* dummy final entry, always present */
 };
 
-/* scan table above for supported devices */
-static int __init agp_lookup_host_bridge (struct pci_dev *pdev)
+static int __init agp_ali_probe(struct pci_dev *pdev,
+				const struct pci_device_id *ent)
 {
-	int j=0;
-	struct agp_device_ids *devs;
-	
-	devs = ali_agp_device_ids;
+	struct agp_device_ids *devs = ali_agp_device_ids;
+	struct agp_bridge_data *bridge;
+	u8 hidden_1621_id, cap_ptr;
+	int j;
 
-	while (devs[j].chipset_name != NULL) {
-		if (pdev->device == devs[j].device_id) {
-			if (pdev->device == PCI_DEVICE_ID_AL_M1621) {
-				u8 hidden_1621_id;
-
-				pci_read_config_byte(pdev, 0xFB, &hidden_1621_id);
-				switch (hidden_1621_id) {
-				case 0x31:
-					devs[j].chipset_name="M1631";
-					break;
-				case 0x32:
-					devs[j].chipset_name="M1632";
-					break;
-				case 0x41:
-					devs[j].chipset_name="M1641";
-					break;
-				case 0x43:
-					break;
-				case 0x47:
-					devs[j].chipset_name="M1647";
-					break;
-				case 0x51:
-					devs[j].chipset_name="M1651";
-					break;
-				default:
-					break;
-				}
-			}
-
-			printk (KERN_INFO PFX "Detected ALi %s chipset\n",
-				devs[j].chipset_name);
-			agp_bridge->type = devs[j].chipset;
-
-			if (devs[j].chipset_setup != NULL)
-				return devs[j].chipset_setup(pdev);
-			else
-				return ali_generic_setup(pdev);
-		}
-		j++;
+	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+	if (!cap_ptr)
+		return -ENODEV;
+
+	/* probe for known chipsets */
+	for (j = 0; devs[j].chipset_name; j++) {
+		if (pdev->device == devs[j].device_id)
+			goto found;
 	}
 
-	/* try init anyway, if user requests it */
-	if (agp_try_unsupported) {
-		printk(KERN_WARNING PFX "Trying generic ALi routines"
-		       " for device id: %04x\n", pdev->device);
-		agp_bridge->type = ALI_GENERIC;
-		return ali_generic_setup(pdev);
+	if (!agp_try_unsupported) {
+		printk(KERN_ERR PFX
+		     "Unsupported ALi chipset (device id: %04x),"
+		     " you might want to try agp_try_unsupported=1.\n",
+		     pdev->device);
+		return -ENODEV;
 	}
 
-	printk(KERN_ERR PFX "Unsupported ALi chipset (device id: %04x),"
-		" you might want to try agp_try_unsupported=1.\n", pdev->device);
-	return -ENODEV;
-}
+	printk(KERN_WARNING PFX "Trying generic ALi routines"
+	       " for device id: %04x\n", pdev->device);
 
-static struct agp_driver ali_agp_driver = {
-	.owner = THIS_MODULE,
-};
+found:
+	bridge = agp_alloc_bridge();
+	if (!bridge)
+		return -ENOMEM;
+
+	bridge->dev = pdev;
+	bridge->capndx = cap_ptr;
+
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_AL_M1541:
+		bridge->driver = &ali_m1541_bridge;
+		break;
+	case PCI_DEVICE_ID_AL_M1621:
+		pci_read_config_byte(pdev, 0xFB, &hidden_1621_id);
+		switch (hidden_1621_id) {
+		case 0x31:
+			devs[j].chipset_name = "M1631";
+			break;
+		case 0x32:
+			devs[j].chipset_name = "M1632";
+			break;
+		case 0x41:
+			devs[j].chipset_name = "M1641";
+			break;
+		case 0x43:
+			break;
+		case 0x47:
+			devs[j].chipset_name = "M1647";
+			break;
+		case 0x51:
+			devs[j].chipset_name = "M1651";
+			break;
+		default:
+			break;
+		}
+		/*FALLTHROUGH*/
+	default:
+		bridge->driver = &ali_generic_bridge;
+	}
 
-static int __init agp_ali_probe (struct pci_dev *dev, const struct pci_device_id *ent)
-{
-	u8 cap_ptr = 0;
+	printk(KERN_INFO PFX "Detected ALi %s chipset\n",
+			devs[j].chipset_name);
 
-	cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
-	if (cap_ptr == 0)
-		return -ENODEV;
+	/* Fill in the mode register */
+	pci_read_config_dword(pdev,
+			bridge->capndx+PCI_AGP_STATUS,
+			&bridge->mode);
 
-	/* probe for known chipsets */
-	if (agp_lookup_host_bridge(dev) != -ENODEV) {
-		agp_bridge->dev = dev;
-		agp_bridge->capndx = cap_ptr;
-		/* Fill in the mode register */
-		pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode);
-		ali_agp_driver.dev = dev;
-		agp_register_driver(&ali_agp_driver);
-		return 0;
-	}
-	return -ENODEV;	
+	pci_set_drvdata(pdev, bridge);
+	return agp_add_bridge(bridge);
+}
+
+static void __devexit agp_ali_remove(struct pci_dev *pdev)
+{
+	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+
+	agp_remove_bridge(bridge);
+	agp_put_bridge(bridge);
 }
 
 static struct pci_device_id agp_ali_pci_table[] __initdata = {
@@ -379,22 +395,16 @@
 	.name		= "agpgart-ali",
 	.id_table	= agp_ali_pci_table,
 	.probe		= agp_ali_probe,
+	.remove		= agp_ali_remove,
 };
 
 static int __init agp_ali_init(void)
 {
-	int ret_val;
-
-	ret_val = pci_module_init(&agp_ali_pci_driver);
-	if (ret_val)
-		agp_bridge->type = NOT_SUPPORTED;
-
-	return ret_val;
+	return pci_module_init(&agp_ali_pci_driver);
 }
 
 static void __exit agp_ali_cleanup(void)
 {
-	agp_unregister_driver(&ali_agp_driver);
 	pci_unregister_driver(&agp_ali_pci_driver);
 }
 
diff -urN linux-2.5.69-bk6/drivers/char/agp/alpha-agp.c linux-2.5.69-bk7/drivers/char/agp/alpha-agp.c
--- linux-2.5.69-bk6/drivers/char/agp/alpha-agp.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/alpha-agp.c	2003-05-12 04:43:29.000000000 -0700
@@ -81,7 +81,7 @@
 static unsigned long alpha_core_agp_mask_memory(unsigned long addr, int type)
 {
 	/* Memory type is ignored */
-	return addr | agp_bridge->masks[0].mask;
+	return addr | agp_bridge->driver->masks[0].mask;
 }
 
 static void alpha_core_agp_enable(u32 mode)
@@ -109,7 +109,7 @@
 
 	status = agp->ops->bind(agp, pg_start, mem);
 	mb();
-	agp_bridge->tlb_flush(mem);
+	alpha_core_agp_tlbflush(mem);
 
 	return status;
 }
@@ -121,29 +121,57 @@
 	int status;
 
 	status = agp->ops->unbind(agp, pg_start, mem);
-	agp_bridge->tlb_flush(mem);
+	alpha_core_agp_tlbflush(mem);
 	return status;
 }
 
-
-static struct agp_driver alpha_core_agp_driver = {
-	.owner = THIS_MODULE,
+struct agp_bridge_driver alpha_core_agp_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= alpha_core_agp_masks,
+	.aperture_sizes		= aper_size,
+	.current_size		= aper_size,	/* only one entry */
+	.size_type		= FIXED_APER_SIZE,
+	.num_aperture_sizes	= 1,
+	.configure		= alpha_core_agp_configure,
+	.fetch_size		= alpha_core_agp_fetch_size,
+	.cleanup		= alpha_core_agp_cleanup,
+	.tlb_flush		= alpha_core_agp_tlbflush,
+	.mask_memory		= alpha_core_agp_mask_memory,
+	.agp_enable		= alpha_core_agp_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= alpha_core_agp_nop,
+	.free_gatt_table	= alpha_core_agp_nop,
+	.insert_memory		= alpha_core_agp_insert_memory,
+	.remove_memory		= alpha_core_agp_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.mode			= agp->capability.lw,
+	.cant_use_aperture	= 1,
+	.vm_ops			= &alpha_core_agp_vm_ops,
 };
 
+struct agp_bridge_data *alpha_bridge;
+
 int __init
 alpha_core_agp_setup(void)
 {
 	alpha_agp_info *agp = alpha_mv.agp_info();
+	struct pci_dev *pdev;	/* faked */
 	struct aper_size_info_fixed *aper_size;
 
-	if (!agp) return -ENODEV;
-	if (agp->ops->setup(agp)) return -ENODEV;
+	if (!agp)
+		return -ENODEV;
+	if (agp->ops->setup(agp))
+		return -ENODEV;
 
 	/*
 	 * Build the aperture size descriptor
 	 */
 	aper_size = alpha_core_agp_sizes;
-	if (!aper_size) return -ENOMEM;
+	if (!aper_size)
+		return -ENOMEM;
 	aper_size->size = agp->aperture.size / (1024 * 1024);
 	aper_size->num_entries = agp->aperture.size / PAGE_SIZE;
 	aper_size->page_order = ffs(aper_size->num_entries / 1024) - 1;
@@ -151,63 +179,40 @@
 	/*
 	 * Build a fake pci_dev struct
 	 */
-	if (!(agp_bridge->dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL))) {
+	pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+	if (!pdev)
 		return -ENOMEM;
-	}
-	agp_bridge->dev->vendor = 0xffff;
-	agp_bridge->dev->device = 0xffff;
-	agp_bridge->dev->sysdata = agp->hose;
-
-	/*
-	 * Fill in the rest of the agp_bridge struct
-	 */
-	agp_bridge->masks = alpha_core_agp_masks;
-	agp_bridge->aperture_sizes = aper_size;
-	agp_bridge->current_size = aper_size;	/* only one entry */
-	agp_bridge->size_type = FIXED_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 1;
-	agp_bridge->dev_private_data = agp;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = alpha_core_agp_configure;
-	agp_bridge->fetch_size = alpha_core_agp_fetch_size;
-	agp_bridge->cleanup = alpha_core_agp_cleanup;
-	agp_bridge->tlb_flush = alpha_core_agp_tlbflush;
-	agp_bridge->mask_memory = alpha_core_agp_mask_memory;
-	agp_bridge->agp_enable = alpha_core_agp_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = alpha_core_agp_nop;
-	agp_bridge->free_gatt_table = alpha_core_agp_nop;
-	agp_bridge->insert_memory = alpha_core_agp_insert_memory;
-	agp_bridge->remove_memory = alpha_core_agp_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->mode = agp->capability.lw;
-	agp_bridge->cant_use_aperture = 1;
-	agp_bridge->vm_ops =  &alpha_core_agp_vm_ops;
+	pdev->vendor = 0xffff;
+	pdev->device = 0xffff;
+	pdev->sysdata = agp->hose;
+
+	alpha_bridge = agp_alloc_bridge();
+	if (!alpha_bridge)
+		goto fail;
+
+	alpha_bridge->driver = &alpha_core_agp_driver;
+	alpha_bridge->dev_private_data = agp;
+	alpha_bridge->dev = pdev;
 
-	alpha_core_agp_driver.dev = agp_bridge->dev;
-	agp_register_driver(&alpha_core_agp_driver);
 	printk(KERN_INFO "Detected AGP on hose %d\n", agp->hose->index);
-	return 0;
+	return agp_add_bridge(alpha_bridge);
+
+ fail:
+	kfree(pdev);
+	return -ENOMEM;
 }
 
 static int __init agp_alpha_core_init(void)
 {
-	int ret_val = -ENODEV;
-	if (alpha_mv.agp_info) {
-		agp_bridge->type = ALPHA_CORE_AGP;
-		ret_val = alpha_core_agp_setup();
-	}
-
-	return ret_val;
+	if (alpha_mv.agp_info)
+		return alpha_core_agp_setup();
+	return -ENODEV;
 }
 
 static void __exit agp_alpha_core_cleanup(void)
 {
-	agp_unregister_driver(&alpha_core_agp_driver);
-	/* no pci driver for core */
+	agp_remove_bridge(alpha_bridge);
+	agp_put_bridge(alpha_bridge);
 }
 
 module_init(agp_alpha_core_init);
diff -urN linux-2.5.69-bk6/drivers/char/agp/amd-k7-agp.c linux-2.5.69-bk7/drivers/char/agp/amd-k7-agp.c
--- linux-2.5.69-bk6/drivers/char/agp/amd-k7-agp.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/amd-k7-agp.c	2003-05-12 04:43:29.000000000 -0700
@@ -33,7 +33,7 @@
 		return -ENOMEM;
 	}
 	SetPageReserved(virt_to_page(page_map->real));
-	CACHE_FLUSH();
+	global_cache_flush();
 	page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), 
 					    PAGE_SIZE);
 	if (page_map->remapped == NULL) {
@@ -42,7 +42,7 @@
 		page_map->real = NULL;
 		return -ENOMEM;
 	}
-	CACHE_FLUSH();
+	global_cache_flush();
 
 	for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
 		page_map->remapped[i] = agp_bridge->scratch_page;
@@ -75,6 +75,7 @@
 		}
 	}
 	kfree(tables);
+	amd_irongate_private.gatt_pages = NULL;
 }
 
 static int amd_create_gatt_pages(int nr_tables)
@@ -184,8 +185,8 @@
 
 	pci_read_config_dword(agp_bridge->dev, AMD_APSIZE, &temp);
 	temp = (temp & 0x0000000e);
-	values = A_SIZE_LVL2(agp_bridge->aperture_sizes);
-	for (i = 0; i < agp_bridge->num_aperture_sizes; i++) {
+	values = A_SIZE_LVL2(agp_bridge->driver->aperture_sizes);
+	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
 		if (temp == values[i].size_value) {
 			agp_bridge->previous_size =
 			    agp_bridge->current_size = (void *) (values + i);
@@ -274,7 +275,7 @@
 {
 	/* Only type 0 is supported by the irongate */
 
-	return addr | agp_bridge->masks[0].mask;
+	return addr | agp_bridge->driver->masks[0].mask;
 }
 
 static int amd_insert_memory(agp_memory * mem,
@@ -297,14 +298,13 @@
 	while (j < (pg_start + mem->page_count)) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		if (!PGE_EMPTY(cur_gatt[GET_GATT_OFF(addr)])) {
+		if (!PGE_EMPTY(agp_bridge, cur_gatt[GET_GATT_OFF(addr)]))
 			return -EBUSY;
-		}
 		j++;
 	}
 
 	if (mem->is_flushed == FALSE) {
-		CACHE_FLUSH();
+		global_cache_flush();
 		mem->is_flushed = TRUE;
 	}
 
@@ -312,9 +312,9 @@
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
 		cur_gatt[GET_GATT_OFF(addr)] =
-			agp_bridge->mask_memory(mem->memory[i], mem->type);
+			amd_irongate_mask_memory(mem->memory[i], mem->type);
 	}
-	agp_bridge->tlb_flush(mem);
+	amd_irongate_tlbflush(mem);
 	return 0;
 }
 
@@ -335,7 +335,7 @@
 			(unsigned long) agp_bridge->scratch_page;
 	}
 
-	agp_bridge->tlb_flush(mem);
+	amd_irongate_tlbflush(mem);
 	return 0;
 }
 
@@ -355,115 +355,104 @@
 	{.mask = 0x00000001, .type = 0}
 };
 
-static int __init amd_irongate_setup (struct pci_dev *pdev)
-{
-	agp_bridge->masks = amd_irongate_masks;
-	agp_bridge->aperture_sizes = (void *) amd_irongate_sizes;
-	agp_bridge->size_type = LVL2_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 7;
-	agp_bridge->dev_private_data = (void *) &amd_irongate_private;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = amd_irongate_configure;
-	agp_bridge->fetch_size = amd_irongate_fetch_size;
-	agp_bridge->cleanup = amd_irongate_cleanup;
-	agp_bridge->tlb_flush = amd_irongate_tlbflush;
-	agp_bridge->mask_memory = amd_irongate_mask_memory;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = amd_create_gatt_table;
-	agp_bridge->free_gatt_table = amd_free_gatt_table;
-	agp_bridge->insert_memory = amd_insert_memory;
-	agp_bridge->remove_memory = amd_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
-	return 0;
-}
+struct agp_bridge_driver amd_irongate_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= amd_irongate_masks,
+	.aperture_sizes		= amd_irongate_sizes,
+	.size_type		= LVL2_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= amd_irongate_configure,
+	.fetch_size		= amd_irongate_fetch_size,
+	.cleanup		= amd_irongate_cleanup,
+	.tlb_flush		= amd_irongate_tlbflush,
+	.mask_memory		= amd_irongate_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= amd_create_gatt_table,
+	.free_gatt_table	= amd_free_gatt_table,
+	.insert_memory		= amd_insert_memory,
+	.remove_memory		= amd_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
 
 struct agp_device_ids amd_agp_device_ids[] __initdata =
 {
 	{
 		.device_id	= PCI_DEVICE_ID_AMD_FE_GATE_7006,
-		.chipset	= AMD_IRONGATE,
 		.chipset_name	= "Irongate",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_AMD_FE_GATE_700E,
-		.chipset	= AMD_761,
 		.chipset_name	= "761",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_AMD_FE_GATE_700C,
-		.chipset	= AMD_762,
 		.chipset_name	= "760MP",
 	},
 	{ }, /* dummy final entry, always present */
 };
 
-
-/* scan table above for supported devices */
-static int __init agp_lookup_host_bridge (struct pci_dev *pdev)
+static int __init agp_amdk7_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *ent)
 {
-	int j=0;
-	struct agp_device_ids *devs;
-	
-	devs = amd_agp_device_ids;
+	struct agp_device_ids *devs = amd_agp_device_ids;
+	struct agp_bridge_data *bridge;
+	u8 cap_ptr;
+	int j;
 
-	while (devs[j].chipset_name != NULL) {
-		if (pdev->device == devs[j].device_id) {
-			printk (KERN_INFO PFX "Detected AMD %s chipset\n", devs[j].chipset_name);
-			agp_bridge->type = devs[j].chipset;
+	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+	if (!cap_ptr)
+		return -ENODEV;
 
-			if (devs[j].chipset_setup != NULL)
-				return devs[j].chipset_setup(pdev);
-			else
-				return amd_irongate_setup(pdev);
+	for (j = 0; devs[j].chipset_name; j++) {
+		if (pdev->device == devs[j].device_id) {
+			printk (KERN_INFO PFX "Detected AMD %s chipset\n",
+					devs[j].chipset_name);
+			goto found;
 		}
-		j++;
 	}
 
-	/* try init anyway, if user requests it */
-	if (agp_try_unsupported) {
-		printk(KERN_WARNING PFX "Trying generic AMD routines"
-		       " for device id: %04x\n", pdev->device);
-		agp_bridge->type = AMD_GENERIC;
-		return amd_irongate_setup(pdev);
+	if (!agp_try_unsupported) {
+		printk(KERN_ERR PFX
+		    "Unsupported AMD chipset (device id: %04x),"
+		    " you might want to try agp_try_unsupported=1.\n",
+		    pdev->device);
+		return -ENODEV;
 	}
 
-	printk(KERN_ERR PFX "Unsupported AMD chipset (device id: %04x),"
-		" you might want to try agp_try_unsupported=1.\n", pdev->device);
-	return -ENODEV;
-}
+	printk(KERN_WARNING PFX "Trying generic AMD routines"
+	       " for device id: %04x\n", pdev->device);
 
+found:
+	bridge = agp_alloc_bridge();
+	if (!bridge)
+		return -ENOMEM;
 
-static struct agp_driver amd_k7_agp_driver = {
-	.owner = THIS_MODULE,
-};
+	bridge->driver = &amd_irongate_driver;
+	bridge->dev_private_data = &amd_irongate_private,
+	bridge->dev = pdev;
+	bridge->capndx = cap_ptr;
 
-/* Supported Device Scanning routine */
+	/* Fill in the mode register */
+	pci_read_config_dword(pdev,
+			bridge->capndx+PCI_AGP_STATUS,
+			&bridge->mode);
 
-static int __init agp_amdk7_probe (struct pci_dev *dev, const struct pci_device_id *ent)
-{
-	u8 cap_ptr = 0;
+	pci_set_drvdata(pdev, bridge);
+	return agp_add_bridge(bridge);
+}
 
-	cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
-	if (cap_ptr == 0)
-		return -ENODEV;
+static void __devexit agp_amdk7_remove(struct pci_dev *pdev)
+{
+	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
-	if (agp_lookup_host_bridge(dev) != -ENODEV) {
-		agp_bridge->dev = dev;
-		agp_bridge->capndx = cap_ptr;
-		/* Fill in the mode register */
-		pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode);
-		amd_k7_agp_driver.dev = dev;
-		agp_register_driver(&amd_k7_agp_driver);
-		return 0;
-	}
-	return -ENODEV;
+	agp_remove_bridge(bridge);
+	agp_put_bridge(bridge);
 }
 
 static struct pci_device_id agp_amdk7_pci_table[] __initdata = {
@@ -484,22 +473,16 @@
 	.name		= "agpgart-amdk7",
 	.id_table	= agp_amdk7_pci_table,
 	.probe		= agp_amdk7_probe,
+	.remove		= agp_amdk7_remove,
 };
 
 static int __init agp_amdk7_init(void)
 {
-	int ret_val;
-
-	ret_val = pci_module_init(&agp_amdk7_pci_driver);
-	if (ret_val)
-		agp_bridge->type = NOT_SUPPORTED;
-
-	return ret_val;
+	return pci_module_init(&agp_amdk7_pci_driver);
 }
 
 static void __exit agp_amdk7_cleanup(void)
 {
-	agp_unregister_driver(&amd_k7_agp_driver);
 	pci_unregister_driver(&agp_amdk7_pci_driver);
 }
 
@@ -508,4 +491,3 @@
 
 MODULE_PARM(agp_try_unsupported, "1i");
 MODULE_LICENSE("GPL and additional rights");
-
diff -urN linux-2.5.69-bk6/drivers/char/agp/amd-k8-agp.c linux-2.5.69-bk7/drivers/char/agp/amd-k8-agp.c
--- linux-2.5.69-bk6/drivers/char/agp/amd-k8-agp.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/amd-k8-agp.c	2003-05-12 04:43:29.000000000 -0700
@@ -29,6 +29,21 @@
 static int gart_iterator;
 #define for_each_nb() for(gart_iterator=0;gart_iterator<nr_garts;gart_iterator++)
 
+static void flush_x86_64_tlb(struct pci_dev *dev)
+{
+	u32 tmp;
+
+	pci_read_config_dword (dev, AMD_X86_64_GARTCACHECTL, &tmp);
+	tmp |= 1<<0;
+	pci_write_config_dword (dev, AMD_X86_64_GARTCACHECTL, tmp);
+}
+
+static void amd_x86_64_tlbflush(agp_memory *temp)
+{
+	for_each_nb()
+		flush_x86_64_tlb(hammers[gart_iterator]);
+}
+
 static int x86_64_insert_memory(agp_memory * mem, off_t pg_start, int type)
 {
 	int i, j, num_entries;
@@ -50,18 +65,18 @@
 
 	/* gatt table should be empty. */
 	while (j < (pg_start + mem->page_count)) {
-		if (!PGE_EMPTY(agp_bridge->gatt_table[j]))
+		if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j]))
 			return -EBUSY;
 		j++;
 	}
 
 	if (mem->is_flushed == FALSE) {
-		CACHE_FLUSH();
+		global_cache_flush();
 		mem->is_flushed = TRUE;
 	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-		addr = agp_bridge->mask_memory(mem->memory[i], mem->type);
+		addr = agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
 
 		tmp = addr;
 		BUG_ON(tmp & 0xffffff0000000ffc);
@@ -71,7 +86,7 @@
 
 		agp_bridge->gatt_table[j] = pte;
 	}
-	agp_bridge->tlb_flush(mem);
+	amd_x86_64_tlbflush(mem);
 	return 0;
 }
 
@@ -113,7 +128,7 @@
 	temp = (temp & 0xe);
 	values = A_SIZE_32(x86_64_aperture_sizes);
 
-	for (i = 0; i < agp_bridge->num_aperture_sizes; i++) {
+	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
 		if (temp == values[i].size_value) {
 			agp_bridge->previous_size =
 			    agp_bridge->current_size = (void *) (values + i);
@@ -125,25 +140,6 @@
 	return 0;
 }
 
-
-static void flush_x86_64_tlb(struct pci_dev *dev)
-{
-	u32 tmp;
-
-	pci_read_config_dword (dev, AMD_X86_64_GARTCACHECTL, &tmp);
-	tmp |= 1<<0;
-	pci_write_config_dword (dev, AMD_X86_64_GARTCACHECTL, tmp);
-}
-
-
-static void amd_x86_64_tlbflush(agp_memory * temp)
-{
-	for_each_nb() {
-		flush_x86_64_tlb (hammers[gart_iterator]);
-	}
-}
-
-
 /*
  * In a multiprocessor x86-64 system, this function gets
  * called once for each CPU.
@@ -218,7 +214,7 @@
 
 static unsigned long amd_8151_mask_memory(unsigned long addr, int type)
 {
-	return addr | agp_bridge->masks[0].mask;
+	return addr | agp_bridge->driver->masks[0].mask;
 }
 
 
@@ -227,130 +223,84 @@
 	{.mask = 0x00000001, .type = 0}
 };
 
+struct agp_bridge_driver amd_8151_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= amd_8151_masks,
+	.aperture_sizes		= amd_8151_sizes,
+	.size_type		= U32_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= amd_8151_configure,
+	.fetch_size		= amd_x86_64_fetch_size,
+	.cleanup		= amd_8151_cleanup,
+	.tlb_flush		= amd_x86_64_tlbflush,
+	.mask_memory		= amd_8151_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= x86_64_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
 
-/*
- * Try to configure an AGP v3 capable setup.
- * If we fail (typically because we don't have an AGP v3
- * card in the system) we fall back to the generic AGP v2
- * routines.
- */
-static void agp_x86_64_agp_enable(u32 mode)
+static int __init agp_amdk8_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *ent)
 {
-	struct pci_dev *device = NULL;
-	u32 command, scratch; 
+	struct agp_bridge_data *bridge;
+	struct pci_dev *loop_dev;
 	u8 cap_ptr;
-	u8 v3_devs=0;
-
-	/* FIXME: If 'mode' is x1/x2/x4 should we call the AGPv2 routines directly ?
-	 * Messy, as some AGPv3 cards can only do x4 as a minimum.
-	 */
-
-	/* PASS1: Count # of devs capable of AGPv3 mode. */
-	pci_for_each_dev(device) {
-		cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
-		if (cap_ptr != 0x00) {
-			pci_read_config_dword(device, cap_ptr, &scratch);
-			scratch &= (1<<20|1<<21|1<<22|1<<23);
-			scratch = scratch>>20;
-			/* AGP v3 capable ? */
-			if (scratch>=3) {
-				v3_devs++;
-				printk (KERN_INFO "AGP: Found AGPv3 capable device at %d:%d:%d\n",
-					device->bus->number, PCI_FUNC(device->devfn), PCI_SLOT(device->devfn));
-			} else {
-				printk (KERN_INFO "AGP: Meh. version %x AGP device found.\n", scratch);
-			}
-		}
-	}
-	/* If not enough, go to AGP v2 setup */
-	if (v3_devs<2) {
-		printk (KERN_INFO "AGP: Only %d devices found, not enough, trying AGPv2\n", v3_devs);
-		return agp_generic_enable(mode);
-	} else {
-		printk (KERN_INFO "AGP: Enough AGPv3 devices found, setting up...\n");
-	}
-
-
-	pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &command);
-
-	command = agp_collect_device_status(mode, command);
-	command |= 0x100;
-
-	pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_COMMAND, command);
-
-	agp_device_command(command, 1);
-}
+	int i = 0;
 
+	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+	if (!cap_ptr)
+		return -ENODEV;
 
-static int __init amd_8151_setup (struct pci_dev *pdev)
-{
-	struct pci_dev *dev;
-	int i=0;
+	printk(KERN_INFO PFX "Detected Opteron/Athlon64 on-CPU GART\n");
 
-	agp_bridge->masks = amd_8151_masks;
-	agp_bridge->aperture_sizes = (void *) amd_8151_sizes;
-	agp_bridge->size_type = U32_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 7;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = amd_8151_configure;
-	agp_bridge->fetch_size = amd_x86_64_fetch_size;
-	agp_bridge->cleanup = amd_8151_cleanup;
-	agp_bridge->tlb_flush = amd_x86_64_tlbflush;
-	agp_bridge->mask_memory = amd_8151_mask_memory;
-	agp_bridge->agp_enable = agp_x86_64_agp_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
-	agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
-	agp_bridge->insert_memory = x86_64_insert_memory;
-	agp_bridge->remove_memory = agp_generic_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
+	bridge = agp_alloc_bridge();
+	if (!bridge)
+		return -ENOMEM;
+
+	bridge->driver = &amd_8151_driver;
+	bridge->dev = pdev;
+	bridge->capndx = cap_ptr;
 
+	/* Fill in the mode register */
+	pci_read_config_dword(pdev,
+			bridge->capndx+PCI_AGP_STATUS,
+			&bridge->mode);
 
 	/* cache pci_devs of northbridges. */
-	pci_for_each_dev(dev) {
-		if (dev->bus->number==0 && PCI_FUNC(dev->devfn)==3 &&
-			(PCI_SLOT(dev->devfn) >=24) && (PCI_SLOT(dev->devfn) <=31)) {
-
-			hammers[i++] = dev;
+	pci_for_each_dev(loop_dev) {
+		if (loop_dev->bus->number == 0 &&
+		    PCI_FUNC(loop_dev->devfn) == 3 &&
+		    PCI_SLOT(loop_dev->devfn) >=24 &&
+		    PCI_SLOT(loop_dev->devfn) <=31) {
+			hammers[i++] = loop_dev;
 			nr_garts = i;
-			if (i==MAX_HAMMER_GARTS)
-				return 0;
+			if (i == MAX_HAMMER_GARTS)
+				goto out_free;
 		}
 	}
 
-	return 0;
+	pci_set_drvdata(pdev, bridge);
+	return agp_add_bridge(bridge);
+ out_free:
+	agp_put_bridge(bridge);
+	return -ENOMEM;
 }
 
-static struct agp_driver amd_k8_agp_driver = {
-	.owner = THIS_MODULE,
-};
-
-static int __init agp_amdk8_probe (struct pci_dev *dev, const struct pci_device_id *ent)
+static void __devexit agp_amdk8_remove(struct pci_dev *pdev)
 {
-	u8 cap_ptr = 0;
-
-	cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
-	if (cap_ptr == 0)
-		return -ENODEV;
+	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
-	printk (KERN_INFO PFX "Detected Opteron/Athlon64 on-CPU GART\n");
-
-	agp_bridge->dev = dev;
-	agp_bridge->capndx = cap_ptr;
-
-	/* Fill in the mode register */
-	pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode);
-	amd_8151_setup(dev);
-	amd_k8_agp_driver.dev = dev;
-	agp_register_driver(&amd_k8_agp_driver);
-	return 0;
+	agp_remove_bridge(bridge);
+	agp_put_bridge(bridge);
 }
 
 static struct pci_device_id agp_amdk8_pci_table[] __initdata = {
@@ -371,25 +321,17 @@
 	.name		= "agpgart-amd-k8",
 	.id_table	= agp_amdk8_pci_table,
 	.probe		= agp_amdk8_probe,
+	.remove		= agp_amdk8_remove,
 };
 
 /* Not static due to IOMMU code calling it early. */
 int __init agp_amdk8_init(void)
 {
-	int ret_val;
-
-	ret_val = pci_module_init(&agp_amdk8_pci_driver);
-	if (ret_val)
-		agp_bridge->type = NOT_SUPPORTED;
-
-	agp_bridge->type = AMD_8151;
-
-	return ret_val;
+	return pci_module_init(&agp_amdk8_pci_driver);
 }
 
 static void __exit agp_amdk8_cleanup(void)
 {
-	agp_unregister_driver(&amd_k8_agp_driver);
 	pci_unregister_driver(&agp_amdk8_pci_driver);
 }
 
diff -urN linux-2.5.69-bk6/drivers/char/agp/backend.c linux-2.5.69-bk7/drivers/char/agp/backend.c
--- linux-2.5.69-bk6/drivers/char/agp/backend.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/backend.c	2003-05-12 04:43:29.000000000 -0700
@@ -43,37 +43,54 @@
  * past 0.99 at all due to some boolean logic error. */
 #define AGPGART_VERSION_MAJOR 0
 #define AGPGART_VERSION_MINOR 100
+static struct agp_version agp_current_version =
+{
+	.major = AGPGART_VERSION_MAJOR,
+	.minor = AGPGART_VERSION_MINOR,
+};
+
+static int agp_count=0;
 
 struct agp_bridge_data agp_bridge_dummy = { .type = NOT_SUPPORTED };
 struct agp_bridge_data *agp_bridge = &agp_bridge_dummy;
+EXPORT_SYMBOL(agp_bridge);
 
+
+/**
+ *	agp_backend_acquire  -  attempt to acquire the agp backend.
+ *
+ *	returns -EBUSY if agp is in use,
+ *	returns 0 if the caller owns the agp backend
+ */
 int agp_backend_acquire(void)
 {
 	if (agp_bridge->type == NOT_SUPPORTED)
 		return -EINVAL;
-
-	if (atomic_read(&agp_bridge->agp_in_use) != 0)
+	if (atomic_read(&agp_bridge->agp_in_use))
 		return -EBUSY;
-
 	atomic_inc(&agp_bridge->agp_in_use);
 	return 0;
 }
+EXPORT_SYMBOL(agp_backend_acquire);
 
+
+/**
+ *	agp_backend_release  -  release the lock on the agp backend.
+ *
+ *	The caller must insure that the graphics aperture translation table
+ *	is read for use by another entity.
+ *
+ *	(Ensure that all memory it bound is unbound.)
+ */
 void agp_backend_release(void)
 {
-	if (agp_bridge->type == NOT_SUPPORTED)
-		return;
-
-	atomic_dec(&agp_bridge->agp_in_use);
+	if (agp_bridge->type != NOT_SUPPORTED)
+		atomic_dec(&agp_bridge->agp_in_use);
 }
+EXPORT_SYMBOL(agp_backend_release);
 
-struct agp_max_table {
-	int mem;
-	int agp;
-};
 
-static struct agp_max_table maxes_table[9] =
-{
+struct { int mem, agp; } maxes_table[] = {
 	{0, 0},
 	{32, 4},
 	{64, 28},
@@ -85,7 +102,7 @@
 	{4096, 3932}
 };
 
-static int agp_find_max (void)
+static int agp_find_max(void)
 {
 	long memory, index, result;
 
@@ -105,48 +122,43 @@
 	return result;
 }
 
-static struct agp_version agp_current_version =
-{
-	.major = AGPGART_VERSION_MAJOR,
-	.minor = AGPGART_VERSION_MINOR,
-};
 
-static int agp_backend_initialize(struct pci_dev *dev)
+static int agp_backend_initialize(struct agp_bridge_data *bridge)
 {
 	int size_value, rc, got_gatt=0, got_keylist=0;
 
-	agp_bridge->max_memory_agp = agp_find_max();
-	agp_bridge->version = &agp_current_version;
+	bridge->max_memory_agp = agp_find_max();
+	bridge->version = &agp_current_version;
 
-	if (agp_bridge->needs_scratch_page == TRUE) {
-		void *addr;
-		addr = agp_bridge->agp_alloc_page();
+	if (bridge->driver->needs_scratch_page) {
+		void *addr = bridge->driver->agp_alloc_page();
 
-		if (addr == NULL) {
+		if (!addr) {
 			printk(KERN_ERR PFX "unable to get memory for scratch page.\n");
 			return -ENOMEM;
 		}
-		agp_bridge->scratch_page_real = virt_to_phys(addr);
-		agp_bridge->scratch_page =
-			agp_bridge->mask_memory(agp_bridge->scratch_page_real, 0);
-	}
 
-	size_value = agp_bridge->fetch_size();
+		bridge->scratch_page_real = virt_to_phys(addr);
+		bridge->scratch_page =
+		    bridge->driver->mask_memory(bridge->scratch_page_real, 0);
+	}
 
+	size_value = bridge->driver->fetch_size();
 	if (size_value == 0) {
 		printk(KERN_ERR PFX "unable to determine aperture size.\n");
 		rc = -EINVAL;
 		goto err_out;
 	}
-	if (agp_bridge->create_gatt_table()) {
-		printk(KERN_ERR PFX "unable to get memory for graphics translation table.\n");
+	if (bridge->driver->create_gatt_table()) {
+		printk(KERN_ERR PFX
+		    "unable to get memory for graphics translation table.\n");
 		rc = -ENOMEM;
 		goto err_out;
 	}
 	got_gatt = 1;
 	
-	agp_bridge->key_list = vmalloc(PAGE_SIZE * 4);
-	if (agp_bridge->key_list == NULL) {
+	bridge->key_list = vmalloc(PAGE_SIZE * 4);
+	if (bridge->key_list == NULL) {
 		printk(KERN_ERR PFX "error allocating memory for key lists.\n");
 		rc = -ENOMEM;
 		goto err_out;
@@ -154,61 +166,62 @@
 	got_keylist = 1;
 	
 	/* FIXME vmalloc'd memory not guaranteed contiguous */
-	memset(agp_bridge->key_list, 0, PAGE_SIZE * 4);
+	memset(bridge->key_list, 0, PAGE_SIZE * 4);
 
-	if (agp_bridge->configure()) {
+	if (bridge->driver->configure()) {
 		printk(KERN_ERR PFX "error configuring host chipset.\n");
 		rc = -EINVAL;
 		goto err_out;
 	}
 
 	printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n",
-	       size_value, agp_bridge->gart_bus_addr);
+	       size_value, bridge->gart_bus_addr);
 
 	return 0;
 
 err_out:
-	if (agp_bridge->needs_scratch_page == TRUE) {
-		agp_bridge->agp_destroy_page(phys_to_virt(agp_bridge->scratch_page_real));
-	}
+	if (bridge->driver->needs_scratch_page)
+		bridge->driver->agp_destroy_page(
+				phys_to_virt(bridge->scratch_page_real));
 	if (got_gatt)
-		agp_bridge->free_gatt_table();
-	if (got_keylist)
-		vfree(agp_bridge->key_list);
+		bridge->driver->free_gatt_table();
+	if (got_keylist) {
+		vfree(bridge->key_list);
+		bridge->key_list = NULL;
+	}
 	return rc;
 }
 
-
 /* cannot be __exit b/c as it could be called from __init code */
-static void agp_backend_cleanup(void)
+static void agp_backend_cleanup(struct agp_bridge_data *bridge)
 {
-	if (agp_bridge->cleanup != NULL)
-		agp_bridge->cleanup();
-	if (agp_bridge->free_gatt_table != NULL)
-		agp_bridge->free_gatt_table();
-	if (agp_bridge->key_list)
-		vfree(agp_bridge->key_list);
-
-	if ((agp_bridge->agp_destroy_page!=NULL) &&
-			(agp_bridge->needs_scratch_page == TRUE))
-		agp_bridge->agp_destroy_page(phys_to_virt(agp_bridge->scratch_page_real));
+	if (bridge->driver->cleanup)
+		bridge->driver->cleanup();
+	if (bridge->driver->free_gatt_table)
+		bridge->driver->free_gatt_table();
+	if (bridge->key_list) {
+		vfree(bridge->key_list);
+		bridge->key_list = NULL;
+	}
+
+	if (bridge->driver->agp_destroy_page &&
+	    bridge->driver->needs_scratch_page)
+		bridge->driver->agp_destroy_page(
+				phys_to_virt(bridge->scratch_page_real));
 }
 
 static int agp_power(struct pm_dev *dev, pm_request_t rq, void *data)
 {
-	switch(rq)
-	{
+	switch(rq) {
 		case PM_SUSPEND:
-			return agp_bridge->suspend();
+			return agp_bridge->driver->suspend();
 		case PM_RESUME:
-			agp_bridge->resume();
+			agp_bridge->driver->resume();
 			return 0;
 	}		
 	return 0;
 }
 
-extern int agp_frontend_initialize(void);
-extern void agp_frontend_cleanup(void);
 
 static const drm_agp_t drm_agp = {
 	&agp_free_memory,
@@ -221,78 +234,81 @@
 	&agp_copy_info
 };
 
-static int agp_count=0;
+/* XXX Kludge alert: agpgart isn't ready for multiple bridges yet */
+struct agp_bridge_data *agp_alloc_bridge(void)
+{
+	return agp_bridge;
+}
+EXPORT_SYMBOL(agp_alloc_bridge);
+
+
+void agp_put_bridge(struct agp_bridge_data *bridge)
+{
+}
+EXPORT_SYMBOL(agp_put_bridge);
 
-int agp_register_driver (struct agp_driver *drv)
+ 
+int agp_add_bridge(struct agp_bridge_data *bridge)
 {
-	int ret_val;
+	int error;
 
-	if (drv->dev == NULL) {
-		printk (KERN_DEBUG PFX "Erk, registering with no pci_dev!\n");
+	if (!bridge->dev) {
+		printk(KERN_DEBUG PFX "Erk, registering with no pci_dev!\n");
 		return -EINVAL;
 	}
 
-	if (agp_count==1) {
-		printk (KERN_DEBUG PFX "Only one agpgart device currently supported.\n");
+	if (agp_count) {
+		printk(KERN_DEBUG PFX
+		       "Only one agpgart device currently supported.\n");
 		return -ENODEV;
 	}
 
 	/* Grab reference on the chipset driver. */
-	if (!try_module_get(drv->owner))
+	if (!try_module_get(bridge->driver->owner))
 		return -EINVAL;
 
-	ret_val = agp_backend_initialize(drv->dev);
-	if (ret_val)
+	bridge->type = SUPPORTED;
+
+	error = agp_backend_initialize(agp_bridge);
+	if (error)
 		goto err_out;
 
-	ret_val = agp_frontend_initialize();
-	if (ret_val)
+	error = agp_frontend_initialize();
+	if (error)
 		goto frontend_err;
 
 	/* FIXME: What to do with this? */
 	inter_module_register("drm_agp", THIS_MODULE, &drm_agp);
 
-	pm_register(PM_PCI_DEV, PM_PCI_ID(agp_bridge->dev), agp_power);
+	pm_register(PM_PCI_DEV, PM_PCI_ID(bridge->dev), agp_power);
 	agp_count++;
 	return 0;
 
 frontend_err:
-	agp_backend_cleanup();
+	agp_backend_cleanup(agp_bridge);
 err_out:
-	agp_bridge->type = NOT_SUPPORTED;
-	module_put(drv->owner);
-	drv->dev = NULL;
-	return ret_val;
+	bridge->type = NOT_SUPPORTED;
+	module_put(bridge->driver->owner);
+	return error;
 }
+EXPORT_SYMBOL_GPL(agp_add_bridge);
 
-int agp_unregister_driver(struct agp_driver *drv)
-{
-	if (drv->dev==NULL)
-		return -ENODEV;
 
-	agp_bridge->type = NOT_SUPPORTED;
+void agp_remove_bridge(struct agp_bridge_data *bridge)
+{
+	bridge->type = NOT_SUPPORTED;
 	pm_unregister_all(agp_power);
 	agp_frontend_cleanup();
-	agp_backend_cleanup();
+	agp_backend_cleanup(bridge);
 	inter_module_unregister("drm_agp");
 	agp_count--;
-	module_put(drv->owner);
-	return 0;
+	module_put(bridge->driver->owner);
 }
+EXPORT_SYMBOL_GPL(agp_remove_bridge);
 
 
-int __init agp_init(void)
+static int __init agp_init(void)
 {
-	static int already_initialised=0;
-
-	if (already_initialised!=0)
-		return 0;
-
-	already_initialised = 1;
-
-	memset(agp_bridge, 0, sizeof(struct agp_bridge_data));
-	agp_bridge->type = NOT_SUPPORTED;
-
 	printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Dave Jones\n",
 	       AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR);
 	return 0;
@@ -300,19 +316,13 @@
 
 void __exit agp_exit(void)
 {
-	if (agp_count!=0)
-		BUG();
 }
 
-#ifndef CONFIG_GART_IOMMU
-module_init(agp_init);
-module_exit(agp_exit);
-#endif
-
-EXPORT_SYMBOL(agp_backend_acquire);
-EXPORT_SYMBOL(agp_backend_release);
-EXPORT_SYMBOL_GPL(agp_register_driver);
-EXPORT_SYMBOL_GPL(agp_unregister_driver);
 
 MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
+MODULE_DESCRIPTION("AGP GART driver");
 MODULE_LICENSE("GPL and additional rights");
+
+module_init(agp_init);
+module_exit(agp_exit);
+
diff -urN linux-2.5.69-bk6/drivers/char/agp/frontend.c linux-2.5.69-bk7/drivers/char/agp/frontend.c
--- linux-2.5.69-bk6/drivers/char/agp/frontend.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/frontend.c	2003-05-12 04:43:29.000000000 -0700
@@ -53,11 +53,12 @@
 
 	while (curr != NULL) {
 		if (curr->key == key)
-			return curr;
+			break;
 		curr = curr->next;
 	}
 
-	return NULL;
+	DBG("key=%d -> mem=%p", key, curr);
+	return curr;
 }
 
 static void agp_remove_from_pool(agp_memory * temp)
@@ -67,6 +68,7 @@
 
 	/* Check to see if this is even in the memory pool */
 
+	DBG("mem=%p", temp);
 	if (agp_find_mem_by_key(temp->key) != NULL) {
 		next = temp->next;
 		prev = temp->prev;
@@ -92,11 +94,12 @@
  * to each auth'ed client.
  */
 
-static agp_segment_priv *agp_find_seg_in_client(const agp_client * client,
+static struct
+agp_segment_priv *agp_find_seg_in_client(const struct agp_client *client,
 						unsigned long offset,
 					    int size, pgprot_t page_prot)
 {
-	agp_segment_priv *seg;
+	struct agp_segment_priv *seg;
 	int num_segments, i;
 	off_t pg_start;
 	size_t pg_count;
@@ -117,25 +120,32 @@
 	return NULL;
 }
 
-static void agp_remove_seg_from_client(agp_client * client)
+static void agp_remove_seg_from_client(struct agp_client *client)
 {
+	DBG("client=%p", client);
+
 	if (client->segments != NULL) {
-		if (*(client->segments) != NULL)
+		if (*(client->segments) != NULL) {
+			DBG("Freeing %p from client %p", *(client->segments), client);
 			kfree(*(client->segments));
+		}
+		DBG("Freeing %p from client %p", client->segments, client);
 		kfree(client->segments);
+		client->segments = NULL;
 	}
 }
 
-static void agp_add_seg_to_client(agp_client * client,
-			       agp_segment_priv ** seg, int num_segments)
+static void agp_add_seg_to_client(struct agp_client *client,
+			       struct agp_segment_priv ** seg, int num_segments)
 {
-	agp_segment_priv **prev_seg;
+	struct agp_segment_priv **prev_seg;
 
 	prev_seg = client->segments;
 
 	if (prev_seg != NULL)
 		agp_remove_seg_from_client(client);
 
+	DBG("Adding seg %p (%d segments) to client %p", seg, num_segments, client);
 	client->num_segments = num_segments;
 	client->segments = seg;
 }
@@ -171,19 +181,20 @@
 	return temp;
 }
 
-static int agp_create_segment(agp_client * client, agp_region * region)
+static int agp_create_segment(struct agp_client *client, struct agp_region *region)
 {
-	agp_segment_priv **ret_seg;
-	agp_segment_priv *seg;
-	agp_segment *user_seg;
+	struct agp_segment_priv **ret_seg;
+	struct agp_segment_priv *seg;
+	struct agp_segment *user_seg;
 	size_t i;
 
-	seg = kmalloc((sizeof(agp_segment_priv) * region->seg_count), GFP_KERNEL);
+	seg = kmalloc((sizeof(struct agp_segment_priv) * region->seg_count), GFP_KERNEL);
 	if (seg == NULL) {
 		kfree(region->seg_list);
+		region->seg_list = NULL;
 		return -ENOMEM;
 	}
-	memset(seg, 0, (sizeof(agp_segment_priv) * region->seg_count));
+	memset(seg, 0, (sizeof(struct agp_segment_priv) * region->seg_count));
 	user_seg = region->seg_list;
 
 	for (i = 0; i < region->seg_count; i++) {
@@ -191,14 +202,15 @@
 		seg[i].pg_count = user_seg[i].pg_count;
 		seg[i].prot = agp_convert_mmap_flags(user_seg[i].prot);
 	}
+	kfree(region->seg_list);
+	region->seg_list = NULL;
+
 	ret_seg = kmalloc(sizeof(void *), GFP_KERNEL);
 	if (ret_seg == NULL) {
-		kfree(region->seg_list);
 		kfree(seg);
 		return -ENOMEM;
 	}
 	*ret_seg = seg;
-	kfree(region->seg_list);
 	agp_add_seg_to_client(client, ret_seg, region->seg_count);
 	return 0;
 }
@@ -222,9 +234,9 @@
 
 /* File private list routines */
 
-agp_file_private *agp_find_private(pid_t pid)
+struct agp_file_private *agp_find_private(pid_t pid)
 {
-	agp_file_private *curr;
+	struct agp_file_private *curr;
 
 	curr = agp_fe.file_priv_list;
 
@@ -237,9 +249,9 @@
 	return NULL;
 }
 
-void agp_insert_file_private(agp_file_private * priv)
+void agp_insert_file_private(struct agp_file_private * priv)
 {
-	agp_file_private *prev;
+	struct agp_file_private *prev;
 
 	prev = agp_fe.file_priv_list;
 
@@ -249,10 +261,10 @@
 	agp_fe.file_priv_list = priv;
 }
 
-void agp_remove_file_private(agp_file_private * priv)
+void agp_remove_file_private(struct agp_file_private * priv)
 {
-	agp_file_private *next;
-	agp_file_private *prev;
+	struct agp_file_private *next;
+	struct agp_file_private *prev;
 
 	next = priv->next;
 	prev = priv->prev;
@@ -301,9 +313,9 @@
  * controllers
  */
 
-static agp_controller *agp_find_controller_by_pid(pid_t id)
+static struct agp_controller *agp_find_controller_by_pid(pid_t id)
 {
-	agp_controller *controller;
+	struct agp_controller *controller;
 
 	controller = agp_fe.controllers;
 
@@ -316,24 +328,24 @@
 	return NULL;
 }
 
-static agp_controller *agp_create_controller(pid_t id)
+static struct agp_controller *agp_create_controller(pid_t id)
 {
-	agp_controller *controller;
+	struct agp_controller *controller;
 
-	controller = kmalloc(sizeof(agp_controller), GFP_KERNEL);
+	controller = kmalloc(sizeof(struct agp_controller), GFP_KERNEL);
 
 	if (controller == NULL)
 		return NULL;
 
-	memset(controller, 0, sizeof(agp_controller));
+	memset(controller, 0, sizeof(struct agp_controller));
 	controller->pid = id;
 
 	return controller;
 }
 
-static int agp_insert_controller(agp_controller * controller)
+static int agp_insert_controller(struct agp_controller *controller)
 {
-	agp_controller *prev_controller;
+	struct agp_controller *prev_controller;
 
 	prev_controller = agp_fe.controllers;
 	controller->next = prev_controller;
@@ -346,15 +358,15 @@
 	return 0;
 }
 
-static void agp_remove_all_clients(agp_controller * controller)
+static void agp_remove_all_clients(struct agp_controller *controller)
 {
-	agp_client *client;
-	agp_client *temp;
+	struct agp_client *client;
+	struct agp_client *temp;
 
 	client = controller->clients;
 
 	while (client) {
-		agp_file_private *priv;
+		struct agp_file_private *priv;
 
 		temp = client;
 		agp_remove_seg_from_client(temp);
@@ -369,7 +381,7 @@
 	}
 }
 
-static void agp_remove_all_memory(agp_controller * controller)
+static void agp_remove_all_memory(struct agp_controller *controller)
 {
 	agp_memory *memory;
 	agp_memory *temp;
@@ -383,10 +395,10 @@
 	}
 }
 
-static int agp_remove_controller(agp_controller * controller)
+static int agp_remove_controller(struct agp_controller *controller)
 {
-	agp_controller *prev_controller;
-	agp_controller *next_controller;
+	struct agp_controller *prev_controller;
+	struct agp_controller *next_controller;
 
 	prev_controller = controller->prev;
 	next_controller = controller->next;
@@ -415,14 +427,14 @@
 	return 0;
 }
 
-static void agp_controller_make_current(agp_controller * controller)
+static void agp_controller_make_current(struct agp_controller *controller)
 {
-	agp_client *clients;
+	struct agp_client *clients;
 
 	clients = controller->clients;
 
 	while (clients != NULL) {
-		agp_file_private *priv;
+		struct agp_file_private *priv;
 
 		priv = agp_find_private(clients->pid);
 
@@ -436,16 +448,16 @@
 	agp_fe.current_controller = controller;
 }
 
-static void agp_controller_release_current(agp_controller * controller,
-				      agp_file_private * controller_priv)
+static void agp_controller_release_current(struct agp_controller *controller,
+				      struct agp_file_private *controller_priv)
 {
-	agp_client *clients;
+	struct agp_client *clients;
 
 	clear_bit(AGP_FF_IS_VALID, &controller_priv->access_flags);
 	clients = controller->clients;
 
 	while (clients != NULL) {
-		agp_file_private *priv;
+		struct agp_file_private *priv;
 
 		priv = agp_find_private(clients->pid);
 
@@ -465,10 +477,10 @@
  * These routines are for managing the list of auth'ed clients.
  */
 
-static agp_client *agp_find_client_in_controller(agp_controller * controller,
-						 pid_t id)
+static struct agp_client
+*agp_find_client_in_controller(struct agp_controller *controller, pid_t id)
 {
-	agp_client *client;
+	struct agp_client *client;
 
 	if (controller == NULL)
 		return NULL;
@@ -484,9 +496,9 @@
 	return NULL;
 }
 
-static agp_controller *agp_find_controller_for_client(pid_t id)
+static struct agp_controller *agp_find_controller_for_client(pid_t id)
 {
-	agp_controller *controller;
+	struct agp_controller *controller;
 
 	controller = agp_fe.controllers;
 
@@ -499,9 +511,9 @@
 	return NULL;
 }
 
-static agp_client *agp_find_client_by_pid(pid_t id)
+static struct agp_client *agp_find_client_by_pid(pid_t id)
 {
-	agp_client *temp;
+	struct agp_client *temp;
 
 	if (agp_fe.current_controller == NULL)
 		return NULL;
@@ -510,9 +522,9 @@
 	return temp;
 }
 
-static void agp_insert_client(agp_client * client)
+static void agp_insert_client(struct agp_client *client)
 {
-	agp_client *prev_client;
+	struct agp_client *prev_client;
 
 	prev_client = agp_fe.current_controller->clients;
 	client->next = prev_client;
@@ -524,16 +536,16 @@
 	agp_fe.current_controller->num_clients++;
 }
 
-static agp_client *agp_create_client(pid_t id)
+static struct agp_client *agp_create_client(pid_t id)
 {
-	agp_client *new_client;
+	struct agp_client *new_client;
 
-	new_client = kmalloc(sizeof(agp_client), GFP_KERNEL);
+	new_client = kmalloc(sizeof(struct agp_client), GFP_KERNEL);
 
 	if (new_client == NULL)
 		return NULL;
 
-	memset(new_client, 0, sizeof(agp_client));
+	memset(new_client, 0, sizeof(struct agp_client));
 	new_client->pid = id;
 	agp_insert_client(new_client);
 	return new_client;
@@ -541,10 +553,10 @@
 
 static int agp_remove_client(pid_t id)
 {
-	agp_client *client;
-	agp_client *prev_client;
-	agp_client *next_client;
-	agp_controller *controller;
+	struct agp_client *client;
+	struct agp_client *prev_client;
+	struct agp_client *next_client;
+	struct agp_controller *controller;
 
 	controller = agp_find_controller_for_client(id);
 	if (controller == NULL)
@@ -582,11 +594,11 @@
 {
 	unsigned int size, current_size;
 	unsigned long offset;
-	agp_client *client;
-	agp_file_private *priv = (agp_file_private *) file->private_data;
+	struct agp_client *client;
+	struct agp_file_private *priv = file->private_data;
 	agp_kern_info kerninfo;
 
-	AGP_LOCK();
+	down(&(agp_fe.agp_mutex));
 
 	if (agp_fe.backend_acquired != TRUE)
 		goto out_eperm;
@@ -599,6 +611,7 @@
 	current_size = kerninfo.aper_size;
 	current_size = current_size * 0x100000;
 	offset = vma->vm_pgoff << PAGE_SHIFT;
+	DBG("%lx:%lx", offset, offset+size);
 
 	if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) {
 		if ((size + offset) > current_size)
@@ -612,6 +625,7 @@
 		if (!agp_find_seg_in_client(client, offset, size, vma->vm_page_prot))
 			goto out_inval;
 
+		DBG("client vm_ops=%p", kerninfo.vm_ops);
 		if (kerninfo.vm_ops) {
 			vma->vm_ops = kerninfo.vm_ops;
 		} else if (remap_page_range(vma, vma->vm_start, 
@@ -619,7 +633,7 @@
 					    size, vma->vm_page_prot)) {
 			goto out_again;
 		}
-		AGP_UNLOCK();
+		up(&(agp_fe.agp_mutex));
 		return 0;
 	}
 
@@ -627,6 +641,7 @@
 		if (size != current_size)
 			goto out_inval;
 
+		DBG("controller vm_ops=%p", kerninfo.vm_ops);
 		if (kerninfo.vm_ops) {
 			vma->vm_ops = kerninfo.vm_ops;
 		} else if (remap_page_range(vma, vma->vm_start, 
@@ -634,68 +649,71 @@
 					    size, vma->vm_page_prot)) {
 			goto out_again;
 		}
-		AGP_UNLOCK();
+		up(&(agp_fe.agp_mutex));
 		return 0;
 	}
 
 out_eperm:
-	AGP_UNLOCK();
+	up(&(agp_fe.agp_mutex));
 	return -EPERM;
 
 out_inval:
-	AGP_UNLOCK();
+	up(&(agp_fe.agp_mutex));
 	return -EINVAL;
 
 out_again:
-	AGP_UNLOCK();
+	up(&(agp_fe.agp_mutex));
 	return -EAGAIN;
 }
 
 static int agp_release(struct inode *inode, struct file *file)
 {
-	agp_file_private *priv = (agp_file_private *) file->private_data;
+	struct agp_file_private *priv = file->private_data;
 
-	AGP_LOCK();
+	down(&(agp_fe.agp_mutex));
+
+	DBG("priv=%p", priv);
 
 	if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
-		agp_controller *controller;
+		struct agp_controller *controller;
 
 		controller = agp_find_controller_by_pid(priv->my_pid);
 
 		if (controller != NULL) {
-			if (controller == agp_fe.current_controller) {
-				agp_controller_release_current(controller,
-							       priv);
-			}
+			if (controller == agp_fe.current_controller)
+				agp_controller_release_current(controller, priv);
 			agp_remove_controller(controller);
+			controller = NULL;
 		}
 	}
-	if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) {
+
+	if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags))
 		agp_remove_client(priv->my_pid);
-	}
+
 	agp_remove_file_private(priv);
 	kfree(priv);
-	AGP_UNLOCK();
+	file->private_data = NULL;
+	up(&(agp_fe.agp_mutex));
 	return 0;
 }
 
 static int agp_open(struct inode *inode, struct file *file)
 {
 	int minor = minor(inode->i_rdev);
-	agp_file_private *priv;
-	agp_client *client;
+	struct agp_file_private *priv;
+	struct agp_client *client;
 	int rc = -ENXIO;
 
-	AGP_LOCK();
+	down(&(agp_fe.agp_mutex));
 
 	if (minor != AGPGART_MINOR)
 		goto err_out;
 
-	priv = kmalloc(sizeof(agp_file_private), GFP_KERNEL);
+	priv = kmalloc(sizeof(struct agp_file_private), GFP_KERNEL);
 	if (priv == NULL)
 		goto err_out_nomem;
 
-	memset(priv, 0, sizeof(agp_file_private));
+	memset(priv, 0, sizeof(struct agp_file_private));
 	set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags);
 	priv->my_pid = current->pid;
 
@@ -711,13 +729,14 @@
 	}
 	file->private_data = (void *) priv;
 	agp_insert_file_private(priv);
-	AGP_UNLOCK();
+	DBG("private=%p, client=%p", priv, client);
+	up(&(agp_fe.agp_mutex));
 	return 0;
 
 err_out_nomem:
 	rc = -ENOMEM;
 err_out:
-	AGP_UNLOCK();
+	up(&(agp_fe.agp_mutex));
 	return rc;
 }
 
@@ -734,9 +753,9 @@
 	return -EINVAL;
 }
 
-static int agpioc_info_wrap(agp_file_private * priv, unsigned long arg)
+static int agpioc_info_wrap(struct agp_file_private *priv, unsigned long arg)
 {
-	agp_info userinfo;
+	struct agp_info userinfo;
 	agp_kern_info kerninfo;
 
 	agp_copy_info(&kerninfo);
@@ -751,17 +770,19 @@
 	userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory;
 	userinfo.pg_used = kerninfo.current_memory;
 
-	if (copy_to_user((void *) arg, &userinfo, sizeof(agp_info)))
+	if (copy_to_user((void *) arg, &userinfo, sizeof(struct agp_info)))
 		return -EFAULT;
 
 	return 0;
 }
 
-static int agpioc_acquire_wrap(agp_file_private * priv, unsigned long arg)
+static int agpioc_acquire_wrap(struct agp_file_private *priv, unsigned long arg)
 {
 	int ret;
+	struct agp_controller *controller;
+
+	DBG("");
 
-	agp_controller *controller;
 	if (!(test_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags)))
 		return -EPERM;
 
@@ -795,33 +816,36 @@
 	return 0;
 }
 
-static int agpioc_release_wrap(agp_file_private * priv, unsigned long arg)
+static int agpioc_release_wrap(struct agp_file_private *priv, unsigned long arg)
 {
+	DBG("");
 	agp_controller_release_current(agp_fe.current_controller, priv);
 	return 0;
 }
 
-static int agpioc_setup_wrap(agp_file_private * priv, unsigned long arg)
+static int agpioc_setup_wrap(struct agp_file_private *priv, unsigned long arg)
 {
-	agp_setup mode;
+	struct agp_setup mode;
 
-	if (copy_from_user(&mode, (void *) arg, sizeof(agp_setup))) {
+	DBG("");
+	if (copy_from_user(&mode, (void *) arg, sizeof(struct agp_setup)))
 		return -EFAULT;
-	}
+
 	agp_enable(mode.agp_mode);
 	return 0;
 }
 
-static int agpioc_reserve_wrap(agp_file_private * priv, unsigned long arg)
+static int agpioc_reserve_wrap(struct agp_file_private *priv, unsigned long arg)
 {
-	agp_region reserve;
-	agp_client *client;
-	agp_file_private *client_priv;
+	struct agp_region reserve;
+	struct agp_client *client;
+	struct agp_file_private *client_priv;
 
-	if (copy_from_user(&reserve, (void *) arg, sizeof(agp_region)))
+	DBG("");
+	if (copy_from_user(&reserve, (void *) arg, sizeof(struct agp_region)))
 		return -EFAULT;
 
-	if ((unsigned) reserve.seg_count >= ~0U/sizeof(agp_segment))
+	if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment))
 		return -EFAULT;
 
 	client = agp_find_client_by_pid(reserve.pid);
@@ -831,10 +855,8 @@
 		client_priv = agp_find_private(reserve.pid);
 
 		if (client_priv != NULL) {
-			set_bit(AGP_FF_IS_CLIENT,
-				&client_priv->access_flags);
-			set_bit(AGP_FF_IS_VALID,
-				&client_priv->access_flags);
+			set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
+			set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
 		}
 		if (client == NULL) {
 			/* client is already removed */
@@ -842,19 +864,19 @@
 		}
 		return agp_remove_client(reserve.pid);
 	} else {
-		agp_segment *segment;
+		struct agp_segment *segment;
 
 		if (reserve.seg_count >= 16384)
 			return -EINVAL;
-			
-		segment = kmalloc((sizeof(agp_segment) * reserve.seg_count),
+
+		segment = kmalloc((sizeof(struct agp_segment) * reserve.seg_count),
 				  GFP_KERNEL);
 
 		if (segment == NULL)
 			return -ENOMEM;
 
 		if (copy_from_user(segment, (void *) reserve.seg_list,
-				   sizeof(agp_segment) * reserve.seg_count)) {
+				   sizeof(struct agp_segment) * reserve.seg_count)) {
 			kfree(segment);
 			return -EFAULT;
 		}
@@ -871,32 +893,30 @@
 			client_priv = agp_find_private(reserve.pid);
 
 			if (client_priv != NULL) {
-				set_bit(AGP_FF_IS_CLIENT,
-					&client_priv->access_flags);
-				set_bit(AGP_FF_IS_VALID,
-					&client_priv->access_flags);
+				set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
+				set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
 			}
-			return agp_create_segment(client, &reserve);
-		} else {
-			return agp_create_segment(client, &reserve);
 		}
+		return agp_create_segment(client, &reserve);
 	}
 	/* Will never really happen */
 	return -EINVAL;
 }
 
-static int agpioc_protect_wrap(agp_file_private * priv, unsigned long arg)
+static int agpioc_protect_wrap(struct agp_file_private *priv, unsigned long arg)
 {
+	DBG("");
 	/* This function is not currently implemented */
 	return -EINVAL;
 }
 
-static int agpioc_allocate_wrap(agp_file_private * priv, unsigned long arg)
+static int agpioc_allocate_wrap(struct agp_file_private *priv, unsigned long arg)
 {
 	agp_memory *memory;
-	agp_allocate alloc;
+	struct agp_allocate alloc;
 
-	if (copy_from_user(&alloc, (void *) arg, sizeof(agp_allocate)))
+	DBG("");
+	if (copy_from_user(&alloc, (void *) arg, sizeof(struct agp_allocate)))
 		return -EFAULT;
 
 	memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
@@ -907,17 +927,18 @@
 	alloc.key = memory->key;
 	alloc.physical = memory->physical;
 
-	if (copy_to_user((void *) arg, &alloc, sizeof(agp_allocate))) {
+	if (copy_to_user((void *) arg, &alloc, sizeof(struct agp_allocate))) {
 		agp_free_memory_wrap(memory);
 		return -EFAULT;
 	}
 	return 0;
 }
 
-static int agpioc_deallocate_wrap(agp_file_private * priv, unsigned long arg)
+static int agpioc_deallocate_wrap(struct agp_file_private *priv, unsigned long arg)
 {
 	agp_memory *memory;
 
+	DBG("");
 	memory = agp_find_mem_by_key((int) arg);
 
 	if (memory == NULL)
@@ -927,12 +948,13 @@
 	return 0;
 }
 
-static int agpioc_bind_wrap(agp_file_private * priv, unsigned long arg)
+static int agpioc_bind_wrap(struct agp_file_private *priv, unsigned long arg)
 {
-	agp_bind bind_info;
+	struct agp_bind bind_info;
 	agp_memory *memory;
 
-	if (copy_from_user(&bind_info, (void *) arg, sizeof(agp_bind)))
+	DBG("");
+	if (copy_from_user(&bind_info, (void *) arg, sizeof(struct agp_bind)))
 		return -EFAULT;
 
 	memory = agp_find_mem_by_key(bind_info.key);
@@ -943,12 +965,13 @@
 	return agp_bind_memory(memory, bind_info.pg_start);
 }
 
-static int agpioc_unbind_wrap(agp_file_private * priv, unsigned long arg)
+static int agpioc_unbind_wrap(struct agp_file_private *priv, unsigned long arg)
 {
 	agp_memory *memory;
-	agp_unbind unbind;
+	struct agp_unbind unbind;
 
-	if (copy_from_user(&unbind, (void *) arg, sizeof(agp_unbind)))
+	DBG("");
+	if (copy_from_user(&unbind, (void *) arg, sizeof(struct agp_unbind)))
 		return -EFAULT;
 
 	memory = agp_find_mem_by_key(unbind.key);
@@ -962,10 +985,11 @@
 static int agp_ioctl(struct inode *inode, struct file *file,
 		     unsigned int cmd, unsigned long arg)
 {
-	agp_file_private *curr_priv = (agp_file_private *) file->private_data;
+	struct agp_file_private *curr_priv = file->private_data;
 	int ret_val = -ENOTTY;
 
-	AGP_LOCK();
+	DBG("priv=%p, cmd=%x", curr_priv, cmd);
+	down(&(agp_fe.agp_mutex));
 
 	if ((agp_fe.current_controller == NULL) &&
 	    (cmd != AGPIOC_ACQUIRE)) {
@@ -1034,7 +1058,8 @@
 	}
 
 ioctl_out:
-	AGP_UNLOCK();
+	DBG("ioctl returns %d\n", ret_val);
+	up(&(agp_fe.agp_mutex));
 	return ret_val;
 }
 
@@ -1060,7 +1085,7 @@
 int agp_frontend_initialize(void)
 {
 	memset(&agp_fe, 0, sizeof(struct agp_front_data));
-	AGP_LOCK_INIT();
+	sema_init(&(agp_fe.agp_mutex), 1);
 
 	if (misc_register(&agp_miscdev)) {
 		printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR);
diff -urN linux-2.5.69-bk6/drivers/char/agp/generic-3.0.c linux-2.5.69-bk7/drivers/char/agp/generic-3.0.c
--- linux-2.5.69-bk6/drivers/char/agp/generic-3.0.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/generic-3.0.c	2003-05-12 04:43:29.000000000 -0700
@@ -18,7 +18,7 @@
 	struct pci_dev *dev;
 };
 
-static int agp_3_0_dev_list_insert(struct list_head *head, struct list_head *new)
+static void agp_3_0_dev_list_insert(struct list_head *head, struct list_head *new)
 {
 	struct agp_3_0_dev *cur, *n = list_entry(new, struct agp_3_0_dev, list);
 	struct list_head *pos;
@@ -29,11 +29,9 @@
 			break;
 	}
 	list_add_tail(new, pos);
-
-	return 0;
 }
 
-static int agp_3_0_dev_list_sort(struct agp_3_0_dev *list, unsigned int ndevs)
+static void agp_3_0_dev_list_sort(struct agp_3_0_dev *list, unsigned int ndevs)
 {
 	struct agp_3_0_dev *cur;
 	struct pci_dev *dev;
@@ -53,7 +51,6 @@
 		pos = pos->next;
 		agp_3_0_dev_list_insert(head, tmp);
 	}
-	return 0;
 }
 
 /* 
@@ -62,7 +59,8 @@
  * lying behind it...)
  */
 
-static int agp_3_0_isochronous_node_enable(struct agp_3_0_dev *dev_list, unsigned int ndevs)
+static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
+		struct agp_3_0_dev *dev_list, unsigned int ndevs)
 {
 	/*
 	 * Convenience structure to make the calculations clearer
@@ -77,7 +75,7 @@
 		struct agp_3_0_dev *dev;
 	};
 
-	struct pci_dev *td = agp_bridge->dev, *dev;
+	struct pci_dev *td = bridge->dev, *dev;
 	struct list_head *head = &dev_list->list, *pos;
 	struct agp_3_0_dev *cur;
 	struct isoch_data *master, target;
@@ -114,11 +112,10 @@
 	 * transfers are enabled and consequently whether maxbw will mean
 	 * anything.
 	 */
-	if((ret = agp_3_0_dev_list_sort(dev_list, ndevs)) != 0)
-		goto free_and_exit;
+	agp_3_0_dev_list_sort(dev_list, ndevs);
 
-	pci_read_config_dword(td, agp_bridge->capndx + 0x0c, &tnistat);
-	pci_read_config_dword(td, agp_bridge->capndx + 0x04, &tstatus);
+	pci_read_config_dword(td, bridge->capndx + 0x0c, &tnistat);
+	pci_read_config_dword(td, bridge->capndx+AGPSTAT, &tstatus);
 
 	/* Extract power-on defaults from the target */
 	target.maxbw = (tnistat >> 16) & 0xff;
@@ -170,13 +167,13 @@
 	 * in the target's NISTAT register, so we need to do this now
 	 * to get an accurate value for ISOCH_N later.
 	 */
-	pci_read_config_word(td, agp_bridge->capndx + 0x20, &tnicmd);
+	pci_read_config_word(td, bridge->capndx + 0x20, &tnicmd);
 	tnicmd &= ~(0x3 << 6);
 	tnicmd |= target.y << 6;
-	pci_write_config_word(td, agp_bridge->capndx + 0x20, tnicmd);
+	pci_write_config_word(td, bridge->capndx + 0x20, tnicmd);
 
 	/* Reread the target's ISOCH_N */
-	pci_read_config_dword(td, agp_bridge->capndx + 0x0c, &tnistat);
+	pci_read_config_dword(td, bridge->capndx + 0x0c, &tnistat);
 	target.n = (tnistat >> 8) & 0xff;
 
 	/* Calculate the minimum ISOCH_N needed by each master */
@@ -260,7 +257,7 @@
 		              ? (rem_async + rem_isoch) : step;
 
 		pci_read_config_word(dev, cur->capndx + 0x20, &mnicmd);
-		pci_read_config_dword(dev, cur->capndx + 0x08, &mcmd);
+		pci_read_config_dword(dev, cur->capndx+AGPCMD, &mcmd);
 
 		mnicmd &= ~(0xff << 8);
 		mnicmd &= ~(0x3  << 6);
@@ -270,7 +267,7 @@
 		mnicmd |= master[cdev].y  << 6;
 		mcmd   |= master[cdev].rq << 24;
 
-		pci_write_config_dword(dev, cur->capndx + 0x08, mcmd);
+		pci_write_config_dword(dev, cur->capndx+AGPCMD, mcmd);
 		pci_write_config_word(dev, cur->capndx + 0x20, mnicmd);
 	}
 
@@ -288,7 +285,8 @@
  * target by ndevs.  Distribute this many slots to each AGP 3.0 device,
  * giving any left over slots to the last device in dev_list.
  */
-static int agp_3_0_nonisochronous_node_enable(struct agp_3_0_dev *dev_list, unsigned int ndevs)
+static void agp_3_0_nonisochronous_node_enable(struct agp_bridge_data *bridge,
+		struct agp_3_0_dev *dev_list, unsigned int ndevs)
 {
 	struct agp_3_0_dev *cur;
 	struct list_head *head = &dev_list->list, *pos;
@@ -296,7 +294,7 @@
 	u32 trq, mrq, rem;
 	unsigned int cdev = 0;
 
-	pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + 0x04, &tstatus);
+	pci_read_config_dword(bridge->dev, bridge->capndx + 0x04, &tstatus);
 
 	trq = (tstatus >> 24) & 0xff;
 	mrq = trq / ndevs;
@@ -306,22 +304,20 @@
 	for(pos = head->next; cdev < ndevs; cdev++, pos = pos->next) {
 		cur = list_entry(pos, struct agp_3_0_dev, list);
 
-		pci_read_config_dword(cur->dev, cur->capndx + 0x08, &mcmd);
+		pci_read_config_dword(cur->dev, cur->capndx+AGPCMD, &mcmd);
 		mcmd &= ~(0xff << 24);
 		mcmd |= ((cdev == ndevs - 1) ? rem : mrq) << 24;
-		pci_write_config_dword(cur->dev, cur->capndx + 0x08, mcmd);
+		pci_write_config_dword(cur->dev, cur->capndx+AGPCMD, mcmd);
 	}
-
-	return 0;
 }
 
 /*
  * Fully configure and enable an AGP 3.0 host bridge and all the devices
  * lying behind it.
  */
-int agp_3_0_node_enable(u32 mode, u32 minor)
+int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor)
 {
-	struct pci_dev *td = agp_bridge->dev, *dev;
+	struct pci_dev *td = bridge->dev, *dev;
 	u8 mcapndx;
 	u32 isoch, arqsz, cal_cycle, tmp, rate;
 	u32 tstatus, tcmd, mcmd, mstatus, ncapid;
@@ -345,12 +341,22 @@
 
 	/* Find all AGP devices, and add them to dev_list. */
 	pci_for_each_dev(dev) { 
+		mcapndx = pci_find_capability(dev, PCI_CAP_ID_AGP);
 		switch ((dev->class >>8) & 0xff00) {
+			case 0x0600:    /* Bridge */
+				/* Skip bridges. We should call this function for each one. */
+				continue;
+
 			case 0x0001:    /* Unclassified device */
+				/* Don't know what this is, but log it for investigation. */
+				if (mcapndx != 0) {
+					printk (KERN_INFO PFX "Wacky, found unclassified AGP device. %x:%x\n",
+						dev->vendor, dev->device);
+				}
+				continue;
+
 			case 0x0300:    /* Display controller */
 			case 0x0400:    /* Multimedia controller */
-			case 0x0600:    /* Bridge */
-				mcapndx = pci_find_capability(dev, PCI_CAP_ID_AGP);
 				if (mcapndx == 0)
 					continue;
 
@@ -371,7 +377,7 @@
 	}
 
 	/* Extract some power-on defaults from the target */
-	pci_read_config_dword(td, agp_bridge->capndx + 0x04, &tstatus);
+	pci_read_config_dword(td, bridge->capndx + 0x04, &tstatus);
 	isoch     = (tstatus >> 17) & 0x1;
 	arqsz     = (tstatus >> 13) & 0x7;
 	cal_cycle = (tstatus >> 10) & 0x7;
@@ -409,8 +415,8 @@
 			goto free_and_exit;
 		}
 
-		mmajor = (ncapid >> 20) & 0xf;
-		mminor = (ncapid >> 16) & 0xf;
+		mmajor = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf;
+		mminor = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf;
 
 		if(mmajor < 3) {
 			printk(KERN_ERR PFX "woah!  AGP 2.0 device "
@@ -463,13 +469,15 @@
 	 * masters.  This process is dramatically different depending on
 	 * whether isochronous transfers are supported.
 	 */
-	if(isoch != 0) {
-		if((ret = agp_3_0_isochronous_node_enable(dev_list, ndevs)) != 0)
-			goto free_and_exit;
-	} else {
-		if((ret = agp_3_0_nonisochronous_node_enable(dev_list,ndevs)) != 0)
-			goto free_and_exit;
+	if (isoch) {
+		ret = agp_3_0_isochronous_node_enable(bridge, dev_list, ndevs);
+		if (ret) {
+			printk(KERN_INFO PFX "Something bad happened setting "
+			       "up isochronous xfers.  Falling back to "
+			       "non-isochronous xfer mode.\n");
+		}
 	}
+	agp_3_0_nonisochronous_node_enable(bridge, dev_list, ndevs);
 
 	/*
 	 * Set the calculated minimum supported cal_cycle and minimum
@@ -477,7 +485,7 @@
 	 * Also set the AGP_ENABLE bit, effectively 'turning on' the
 	 * target (this has to be done _before_ turning on the masters).
 	 */
-	pci_read_config_dword(td, agp_bridge->capndx + 0x08, &tcmd);
+	pci_read_config_dword(td, bridge->capndx+AGPCMD, &tcmd);
 
 	tcmd &= ~(0x7 << 10);
 	tcmd &= ~0x7;
@@ -486,7 +494,7 @@
 	tcmd |= 0x1 << 8;
 	tcmd |= rate;
 
-	pci_write_config_dword(td, agp_bridge->capndx + 0x08, tcmd);
+	pci_write_config_dword(td, bridge->capndx+AGPCMD, tcmd);
 
 	/*
 	 * Set the target's advertised arqsz value, the minimum supported
@@ -499,16 +507,16 @@
 
 		mcapndx = cur->capndx;
 
-		pci_read_config_dword(dev, cur->capndx + 0x08, &mcmd);
+		pci_read_config_dword(dev, cur->capndx+AGPCMD, &mcmd);
 
-		mcmd &= ~(0x7 << 13);
+		mcmd &= ~(0x7 << AGPSTAT_ARQSZ_SHIFT);
 		mcmd &= ~0x7;
 
 		mcmd |= arqsz << 13;
-		mcmd |= 0x1 << 8;
+		mcmd |= AGPSTAT_AGP_ENABLE;
 		mcmd |= rate;
 
-		pci_write_config_dword(dev, cur->capndx + 0x08, mcmd);
+		pci_write_config_dword(dev, cur->capndx+AGPCMD, mcmd);
 	}
 
 free_and_exit:
diff -urN linux-2.5.69-bk6/drivers/char/agp/generic.c linux-2.5.69-bk7/drivers/char/agp/generic.c
--- linux-2.5.69-bk6/drivers/char/agp/generic.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/generic.c	2003-05-12 04:43:29.000000000 -0700
@@ -1,6 +1,6 @@
 /*
  * AGPGART driver.
- * Copyright (C) 2002 Dave Jones.
+ * Copyright (C) 2002-2003 Dave Jones.
  * Copyright (C) 1999 Jeff Hartmann.
  * Copyright (C) 1999 Precision Insight, Inc.
  * Copyright (C) 1999 Xi Graphics, Inc.
@@ -42,19 +42,19 @@
 
 /* 
  * Generic routines for handling agp_memory structures -
- * They use the basic page allocation routines to do the
- * brunt of the work.
+ * They use the basic page allocation routines to do the brunt of the work.
  */
 
 void agp_free_key(int key)
 {
-
 	if (key < 0)
 		return;
 
 	if (key < MAXKEY)
 		clear_bit(key, agp_bridge->key_list);
 }
+EXPORT_SYMBOL(agp_free_key);
+
 
 static int agp_get_key(void)
 {
@@ -68,6 +68,7 @@
 	return -1;
 }
 
+
 agp_memory *agp_create_memory(int scratch_pages)
 {
 	agp_memory *new;
@@ -94,7 +95,16 @@
 	new->num_scratch_pages = scratch_pages;
 	return new;
 }
+EXPORT_SYMBOL(agp_create_memory);
 
+/**
+ *	agp_free_memory - free memory associated with an agp_memory pointer.
+ *
+ *	@curr:		agp_memory pointer to be freed.
+ *
+ *	It is the only function that can be called when the backend is not owned
+ *	by the caller.  (So it can free memory on client death.)
+ */
 void agp_free_memory(agp_memory * curr)
 {
 	size_t i;
@@ -106,21 +116,33 @@
 		agp_unbind_memory(curr);
 
 	if (curr->type != 0) {
-		agp_bridge->free_by_type(curr);
+		agp_bridge->driver->free_by_type(curr);
 		return;
 	}
 	if (curr->page_count != 0) {
 		for (i = 0; i < curr->page_count; i++) {
-			agp_bridge->agp_destroy_page(phys_to_virt(curr->memory[i]));
+			agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i]));
 		}
 	}
 	agp_free_key(curr->key);
 	vfree(curr->memory);
 	kfree(curr);
 }
+EXPORT_SYMBOL(agp_free_memory);
 
 #define ENTRIES_PER_PAGE		(PAGE_SIZE / sizeof(unsigned long))
 
+/**
+ *	agp_allocate_memory  -  allocate a group of pages of a certain type.
+ *
+ *	@page_count:	size_t argument of the number of pages
+ *	@type:	u32 argument of the type of memory to be allocated.  
+ *
+ *	Every agp bridge device will allow you to allocate AGP_NORMAL_MEMORY which
+ *	maps to physical ram.  Any other type is device dependent.
+ *
+ *	It returns NULL whenever memory is unavailable. 
+ */
 agp_memory *agp_allocate_memory(size_t page_count, u32 type)
 {
 	int scratch_pages;
@@ -134,7 +156,7 @@
 		return NULL;
 
 	if (type != 0) {
-		new = agp_bridge->alloc_by_type(page_count, type);
+		new = agp_bridge->driver->alloc_by_type(page_count, type);
 		return new;
 	}
 
@@ -146,7 +168,7 @@
 		return NULL;
 
 	for (i = 0; i < page_count; i++) {
-		void *addr = agp_bridge->agp_alloc_page();
+		void *addr = agp_bridge->driver->agp_alloc_page();
 
 		if (addr == NULL) {
 			agp_free_memory(new);
@@ -160,9 +182,12 @@
 
 	return new;
 }
+EXPORT_SYMBOL(agp_allocate_memory);
+
 
 /* End - Generic routines for handling agp_memory structures */
 
+
 static int agp_return_size(void)
 {
 	int current_size;
@@ -170,7 +195,7 @@
 
 	temp = agp_bridge->current_size;
 
-	switch (agp_bridge->size_type) {
+	switch (agp_bridge->driver->size_type) {
 	case U8_APER_SIZE:
 		current_size = A_SIZE_8(temp)->size;
 		break;
@@ -197,6 +222,7 @@
 	return current_size;
 }
 
+
 int agp_num_entries(void)
 {
 	int num_entries;
@@ -204,7 +230,7 @@
 
 	temp = agp_bridge->current_size;
 
-	switch (agp_bridge->size_type) {
+	switch (agp_bridge->driver->size_type) {
 	case U8_APER_SIZE:
 		num_entries = A_SIZE_8(temp)->num_entries;
 		break;
@@ -230,9 +256,17 @@
 		num_entries = 0;
 	return num_entries;
 }
+EXPORT_SYMBOL_GPL(agp_num_entries);
 
-/* Routine to copy over information structure */
 
+/**
+ *	agp_copy_info  -  copy bridge state information
+ *
+ *	@info:		agp_kern_info pointer.  The caller should insure that this pointer is valid. 
+ *
+ *	This function copies information about the agp bridge device and the state of
+ *	the agp backend into an agp_kern_info pointer.
+ */
 int agp_copy_info(agp_kern_info * info)
 {
 	memset(info, 0, sizeof(agp_kern_info));
@@ -249,20 +283,32 @@
 	info->aper_size = agp_return_size();
 	info->max_memory = agp_bridge->max_memory_agp;
 	info->current_memory = atomic_read(&agp_bridge->current_memory_agp);
-	info->cant_use_aperture = agp_bridge->cant_use_aperture;
+	info->cant_use_aperture = agp_bridge->driver->cant_use_aperture;
 	info->vm_ops = agp_bridge->vm_ops;
 	info->page_mask = ~0UL;
 	return 0;
 }
+EXPORT_SYMBOL(agp_copy_info);
+
 
 /* End - Routine to copy over information structure */
 
+
 /*
  * Routines for handling swapping of agp_memory into the GATT -
  * These routines take agp_memory and insert them into the GATT.
  * They call device specific routines to actually write to the GATT.
  */
 
+/**
+ *	agp_bind_memory  -  Bind an agp_memory structure into the GATT.
+ * 
+ *	@curr:		agp_memory pointer
+ *	@pg_start:	an offset into the graphics aperture translation table
+ *
+ *	It returns -EINVAL if the pointer == NULL.
+ *	It returns -EBUSY if the area of the table requested is already in use.
+ */
 int agp_bind_memory(agp_memory * curr, off_t pg_start)
 {
 	int ret_val;
@@ -272,10 +318,10 @@
 		return -EINVAL;
 	}
 	if (curr->is_flushed == FALSE) {
-		CACHE_FLUSH();
+		agp_bridge->driver->cache_flush();
 		curr->is_flushed = TRUE;
 	}
-	ret_val = agp_bridge->insert_memory(curr, pg_start, curr->type);
+	ret_val = agp_bridge->driver->insert_memory(curr, pg_start, curr->type);
 
 	if (ret_val != 0)
 		return ret_val;
@@ -284,7 +330,17 @@
 	curr->pg_start = pg_start;
 	return 0;
 }
+EXPORT_SYMBOL(agp_bind_memory);
+
 
+/**
+ *	agp_unbind_memory  -  Removes an agp_memory structure from the GATT
+ * 
+ * @curr:	agp_memory pointer to be removed from the GATT.
+ * 
+ * It returns -EINVAL if this piece of agp_memory is not currently bound to
+ * the graphics aperture translation table or if the agp_memory pointer == NULL
+ */
 int agp_unbind_memory(agp_memory * curr)
 {
 	int ret_val;
@@ -295,7 +351,7 @@
 	if (curr->is_bound != TRUE)
 		return -EINVAL;
 
-	ret_val = agp_bridge->remove_memory(curr, curr->pg_start, curr->type);
+	ret_val = agp_bridge->driver->remove_memory(curr, curr->pg_start, curr->type);
 
 	if (ret_val != 0)
 		return ret_val;
@@ -304,6 +360,7 @@
 	curr->pg_start = 0;
 	return 0;
 }
+EXPORT_SYMBOL(agp_unbind_memory);
 
 /* End - Routines for handling swapping of agp_memory into the GATT */
 
@@ -328,50 +385,44 @@
 		pci_read_config_dword(device, agp + PCI_AGP_STATUS, &scratch);
 
 		/* adjust RQ depth */
-		command = ((command & ~0xff000000) |
-		     min_t(u32, (mode & 0xff000000),
-			 min_t(u32, (command & 0xff000000),
-			     (scratch & 0xff000000))));
+		command = ((command & ~AGPSTAT_RQ_DEPTH) |
+		     min_t(u32, (mode & AGPSTAT_RQ_DEPTH),
+			 min_t(u32, (command & AGPSTAT_RQ_DEPTH),
+			     (scratch & AGPSTAT_RQ_DEPTH))));
 
 		/* disable SBA if it's not supported */
-		if (!((command & 0x00000200) &&
-		      (scratch & 0x00000200) &&
-		      (mode & 0x00000200)))
-			command &= ~0x00000200;
+		if (!((command & AGPSTAT_SBA) && (scratch & AGPSTAT_SBA) && (mode & AGPSTAT_SBA)))
+			command &= ~AGPSTAT_SBA;
 
 		/* disable FW if it's not supported */
-		if (!((command & 0x00000010) &&
-		      (scratch & 0x00000010) &&
-		      (mode & 0x00000010)))
-			command &= ~0x00000010;
-
-		if (!((command & 4) &&
-		      (scratch & 4) &&
-		      (mode & 4)))
-			command &= ~0x00000004;
-
-		if (!((command & 2) &&
-		      (scratch & 2) &&
-		      (mode & 2)))
-			command &= ~0x00000002;
-
-		if (!((command & 1) &&
-		      (scratch & 1) &&
-		      (mode & 1)))
-			command &= ~0x00000001;
+		if (!((command & AGPSTAT_FW) && (scratch & AGPSTAT_FW) && (mode & AGPSTAT_FW)))
+			command &= ~AGPSTAT_FW;
+
+		/* Set speed */
+		if (!((command & AGPSTAT2_4X) && (scratch & AGPSTAT2_4X) && (mode & AGPSTAT2_4X)))
+			command &= ~AGPSTAT2_4X;
+
+		if (!((command & AGPSTAT2_2X) && (scratch & AGPSTAT2_2X) && (mode & AGPSTAT2_2X)))
+			command &= ~AGPSTAT2_2X;
+
+		if (!((command & AGPSTAT2_1X) && (scratch & AGPSTAT2_1X) && (mode & AGPSTAT2_1X)))
+			command &= ~AGPSTAT2_1X;
 	}
 
-	if (command & 4)
-		command &= ~3;	/* 4X */
+	/* Now we know what mode it should be, clear out the unwanted bits. */
+	if (command & AGPSTAT2_4X)
+		command &= ~(AGPSTAT2_1X | AGPSTAT2_2X);	/* 4X */
 
-	if (command & 2)
-		command &= ~5;	/* 2X (8X for AGP3.0) */
+	if (command & AGPSTAT2_2X)
+		command &= ~(AGPSTAT2_1X | AGPSTAT2_4X);	/* 2X */
 
-	if (command & 1)
-		command &= ~6;	/* 1X (4X for AGP3.0) */
+	if (command & AGPSTAT2_1X)
+		command &= ~(AGPSTAT2_2X | AGPSTAT2_4X);	/* 1Xf */
 
 	return command;
 }
+EXPORT_SYMBOL(agp_collect_device_status);
+
 
 void agp_device_command(u32 command, int agp_v3)
 {
@@ -392,6 +443,8 @@
 		pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command);
 	}
 }
+EXPORT_SYMBOL(agp_device_command);
+
 
 void agp_generic_enable(u32 mode)
 {
@@ -408,7 +461,7 @@
 		pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + 0x4, &agp_3_0);
 		/* Check to see if we are operating in 3.0 mode */
 		if((agp_3_0 >> 3) & 0x1) {
-			agp_3_0_node_enable(mode, minor);
+			agp_3_0_node_enable(agp_bridge, mode, minor);
 			return;
 		} else {
 			printk (KERN_INFO PFX "not in AGP 3.0 mode, falling back to 2.x\n");
@@ -420,12 +473,14 @@
 		      agp_bridge->capndx + PCI_AGP_STATUS, &command);
 
 	command = agp_collect_device_status(mode, command);
-	command |= 0x100;
+	command |= AGPSTAT_AGP_ENABLE;
 
 	pci_write_config_dword(agp_bridge->dev,
 		       agp_bridge->capndx + PCI_AGP_COMMAND, command);
 	agp_device_command(command, 0);
 }
+EXPORT_SYMBOL(agp_generic_enable);
+
 
 int agp_generic_create_gatt_table(void)
 {
@@ -439,7 +494,7 @@
 	struct page *page;
 
 	/* The generic routines can't handle 2 level gatt's */
-	if (agp_bridge->size_type == LVL2_APER_SIZE)
+	if (agp_bridge->driver->size_type == LVL2_APER_SIZE)
 		return -EINVAL;
 
 	table = NULL;
@@ -447,9 +502,9 @@
 	temp = agp_bridge->current_size;
 	size = page_order = num_entries = 0;
 
-	if (agp_bridge->size_type != FIXED_APER_SIZE) {
+	if (agp_bridge->driver->size_type != FIXED_APER_SIZE) {
 		do {
-			switch (agp_bridge->size_type) {
+			switch (agp_bridge->driver->size_type) {
 			case U8_APER_SIZE:
 				size = A_SIZE_8(temp)->size;
 				page_order =
@@ -480,19 +535,17 @@
 
 			if (table == NULL) {
 				i++;
-				switch (agp_bridge->size_type) {
+				switch (agp_bridge->driver->size_type) {
 				case U8_APER_SIZE:
-					agp_bridge->current_size = A_IDX8();
+					agp_bridge->current_size = A_IDX8(agp_bridge);
 					break;
 				case U16_APER_SIZE:
-					agp_bridge->current_size = A_IDX16();
+					agp_bridge->current_size = A_IDX16(agp_bridge);
 					break;
 				case U32_APER_SIZE:
-					agp_bridge->current_size = A_IDX32();
+					agp_bridge->current_size = A_IDX32(agp_bridge);
 					break;
-					/* This case will never really 
-					 * happen. 
-					 */
+					/* This case will never really happen. */
 				case FIXED_APER_SIZE:
 				case LVL2_APER_SIZE:
 				default:
@@ -504,7 +557,7 @@
 			} else {
 				agp_bridge->aperture_size_idx = i;
 			}
-		} while ((table == NULL) && (i < agp_bridge->num_aperture_sizes));
+		} while (!table && (i < agp_bridge->driver->num_aperture_sizes));
 	} else {
 		size = ((struct aper_size_info_fixed *) temp)->size;
 		page_order = ((struct aper_size_info_fixed *) temp)->page_order;
@@ -522,10 +575,11 @@
 
 	agp_bridge->gatt_table_real = (u32 *) table;
 	agp_gatt_table = (void *)table; 
-	CACHE_FLUSH();
+
+	agp_bridge->driver->cache_flush();
 	agp_bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
 					(PAGE_SIZE * (1 << page_order)));
-	CACHE_FLUSH();
+	agp_bridge->driver->cache_flush();
 
 	if (agp_bridge->gatt_table == NULL) {
 		for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
@@ -543,16 +597,21 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(agp_generic_create_gatt_table);
 
 int agp_generic_suspend(void)
 {
 	return 0;
 }
+EXPORT_SYMBOL(agp_generic_suspend);
+
 
 void agp_generic_resume(void)
 {
 	return;
 }
+EXPORT_SYMBOL(agp_generic_resume);
+
 
 int agp_generic_free_gatt_table(void)
 {
@@ -563,7 +622,7 @@
 
 	temp = agp_bridge->current_size;
 
-	switch (agp_bridge->size_type) {
+	switch (agp_bridge->driver->size_type) {
 	case U8_APER_SIZE:
 		page_order = A_SIZE_8(temp)->page_order;
 		break;
@@ -587,8 +646,7 @@
 
 	/* Do not worry about freeing memory, because if this is
 	 * called, then all agp memory is deallocated and removed
-	 * from the table.
-	 */
+	 * from the table. */
 
 	iounmap(agp_bridge->gatt_table);
 	table = (char *) agp_bridge->gatt_table_real;
@@ -598,8 +656,16 @@
 		ClearPageReserved(page);
 
 	free_pages((unsigned long) agp_bridge->gatt_table_real, page_order);
+
+	agp_gatt_table = NULL;
+	agp_bridge->gatt_table = NULL;
+	agp_bridge->gatt_table_real = NULL;
+	agp_bridge->gatt_bus_addr = 0;
+
 	return 0;
 }
+EXPORT_SYMBOL(agp_generic_free_gatt_table);
+
 
 int agp_generic_insert_memory(agp_memory * mem, off_t pg_start, int type)
 {
@@ -610,7 +676,7 @@
 
 	temp = agp_bridge->current_size;
 
-	switch (agp_bridge->size_type) {
+	switch (agp_bridge->driver->size_type) {
 	case U8_APER_SIZE:
 		num_entries = A_SIZE_8(temp)->num_entries;
 		break;
@@ -647,24 +713,27 @@
 	j = pg_start;
 
 	while (j < (pg_start + mem->page_count)) {
-		if (!PGE_EMPTY(agp_bridge->gatt_table[j])) {
+		if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) {
 			return -EBUSY;
 		}
 		j++;
 	}
 
 	if (mem->is_flushed == FALSE) {
-		CACHE_FLUSH();
+		agp_bridge->driver->cache_flush();
 		mem->is_flushed = TRUE;
 	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++)
 		agp_bridge->gatt_table[j] =
-				agp_bridge->mask_memory(mem->memory[i], mem->type);
+				agp_bridge->driver->mask_memory(
+						mem->memory[i], mem->type);
 
-	agp_bridge->tlb_flush(mem);
+	agp_bridge->driver->tlb_flush(mem);
 	return 0;
 }
+EXPORT_SYMBOL(agp_generic_insert_memory);
+
 
 int agp_generic_remove_memory(agp_memory * mem, off_t pg_start, int type)
 {
@@ -681,14 +750,18 @@
 		    (unsigned long) agp_bridge->scratch_page;
 	}
 
-	agp_bridge->tlb_flush(mem);
+	agp_bridge->driver->tlb_flush(mem);
 	return 0;
 }
+EXPORT_SYMBOL(agp_generic_remove_memory);
+
 
 agp_memory *agp_generic_alloc_by_type(size_t page_count, int type)
 {
 	return NULL;
 }
+EXPORT_SYMBOL(agp_generic_alloc_by_type);
+
 
 void agp_generic_free_by_type(agp_memory * curr)
 {
@@ -698,13 +771,13 @@
 	agp_free_key(curr->key);
 	kfree(curr);
 }
+EXPORT_SYMBOL(agp_generic_free_by_type);
+
 
 /* 
  * Basic Page Allocation Routines -
- * These routines handle page allocation
- * and by default they reserve the allocated 
- * memory.  They also handle incrementing the
- * current_memory_agp value, Which is checked
+ * These routines handle page allocation and by default they reserve the allocated 
+ * memory.  They also handle incrementing the current_memory_agp value, Which is checked
  * against a maximum value.
  */
 
@@ -723,6 +796,8 @@
 	atomic_inc(&agp_bridge->current_memory_agp);
 	return page_address(page);
 }
+EXPORT_SYMBOL(agp_generic_alloc_page);
+
 
 void agp_generic_destroy_page(void *addr)
 {
@@ -738,41 +813,39 @@
 	free_page((unsigned long)addr);
 	atomic_dec(&agp_bridge->current_memory_agp);
 }
+EXPORT_SYMBOL(agp_generic_destroy_page);
 
 /* End Basic Page Allocation Routines */
 
+
+/** 
+ * agp_enable  -  initialise the agp point-to-point connection.
+ * 
+ * @mode:	agp mode register value to configure with.
+ */
 void agp_enable(u32 mode)
 {
 	if (agp_bridge->type == NOT_SUPPORTED)
 		return;
-	agp_bridge->agp_enable(mode);
+	agp_bridge->driver->agp_enable(mode);
 }
-
-EXPORT_SYMBOL(agp_free_memory);
-EXPORT_SYMBOL(agp_allocate_memory);
-EXPORT_SYMBOL(agp_copy_info);
-EXPORT_SYMBOL(agp_create_memory);
-EXPORT_SYMBOL(agp_bind_memory);
-EXPORT_SYMBOL(agp_unbind_memory);
-EXPORT_SYMBOL(agp_free_key);
 EXPORT_SYMBOL(agp_enable);
-EXPORT_SYMBOL(agp_bridge);
-
-EXPORT_SYMBOL(agp_generic_alloc_page);
-EXPORT_SYMBOL(agp_generic_destroy_page);
-EXPORT_SYMBOL(agp_generic_suspend);
-EXPORT_SYMBOL(agp_generic_resume);
-EXPORT_SYMBOL(agp_generic_enable);
-EXPORT_SYMBOL(agp_generic_create_gatt_table);
-EXPORT_SYMBOL(agp_generic_free_gatt_table);
-EXPORT_SYMBOL(agp_generic_insert_memory);
-EXPORT_SYMBOL(agp_generic_remove_memory);
-EXPORT_SYMBOL(agp_generic_alloc_by_type);
-EXPORT_SYMBOL(agp_generic_free_by_type);
-EXPORT_SYMBOL(global_cache_flush);
 
-EXPORT_SYMBOL(agp_device_command);
-EXPORT_SYMBOL(agp_collect_device_status);
+#ifdef CONFIG_SMP
+static void ipi_handler(void *null)
+{
+	flush_agp_cache();
+}
+#endif
 
-EXPORT_SYMBOL_GPL(agp_num_entries);
+void global_cache_flush(void)
+{
+#ifdef CONFIG_SMP
+	if (on_each_cpu(ipi_handler, NULL, 1, 1) != 0)
+		panic(PFX "timed out waiting for the other CPUs!\n");
+#else
+	flush_agp_cache();
+#endif
+}
+EXPORT_SYMBOL(global_cache_flush);
 
diff -urN linux-2.5.69-bk6/drivers/char/agp/hp-agp.c linux-2.5.69-bk7/drivers/char/agp/hp-agp.c
--- linux-2.5.69-bk6/drivers/char/agp/hp-agp.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/hp-agp.c	2003-05-12 04:43:29.000000000 -0700
@@ -285,7 +285,7 @@
 	}
 
 	if (mem->is_flushed == FALSE) {
-		CACHE_FLUSH();
+		global_cache_flush();
 		mem->is_flushed = TRUE;
 	}
 
@@ -296,11 +296,11 @@
 		for (k = 0;
 		     k < hp->io_pages_per_kpage;
 		     k++, j++, paddr += hp->io_page_size) {
-			hp->gatt[j] = agp_bridge->mask_memory(paddr, type);
+			hp->gatt[j] = agp_bridge->driver->mask_memory(paddr, type);
 		}
 	}
 
-	agp_bridge->tlb_flush(mem);
+	agp_bridge->driver->tlb_flush(mem);
 	return 0;
 }
 
@@ -319,7 +319,7 @@
 		hp->gatt[i] = agp_bridge->scratch_page;
 	}
 
-	agp_bridge->tlb_flush(mem);
+	agp_bridge->driver->tlb_flush(mem);
 	return 0;
 }
 
@@ -328,58 +328,62 @@
 	return HP_ZX1_PDIR_VALID_BIT | addr;
 }
 
-static int __init hp_zx1_setup (struct pci_dev *pdev __attribute__((unused)))
-{
-	agp_bridge->masks = hp_zx1_masks;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->size_type = FIXED_APER_SIZE;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = hp_zx1_configure;
-	agp_bridge->fetch_size = hp_zx1_fetch_size;
-	agp_bridge->cleanup = hp_zx1_cleanup;
-	agp_bridge->tlb_flush = hp_zx1_tlbflush;
-	agp_bridge->mask_memory = hp_zx1_mask_memory;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = hp_zx1_create_gatt_table;
-	agp_bridge->free_gatt_table = hp_zx1_free_gatt_table;
-	agp_bridge->insert_memory = hp_zx1_insert_memory;
-	agp_bridge->remove_memory = hp_zx1_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->cant_use_aperture = 1;
-	return hp_zx1_ioc_init();
-}
+struct agp_bridge_driver hp_zx1_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= hp_zx1_masks,
+	.size_type		= FIXED_APER_SIZE,
+	.configure		= hp_zx1_configure,
+	.fetch_size		= hp_zx1_fetch_size,
+	.cleanup		= hp_zx1_cleanup,
+	.tlb_flush		= hp_zx1_tlbflush,
+	.mask_memory		= hp_zx1_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= hp_zx1_create_gatt_table,
+	.free_gatt_table	= hp_zx1_free_gatt_table,
+	.insert_memory		= hp_zx1_insert_memory,
+	.remove_memory		= hp_zx1_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.cant_use_aperture	= 1,
+};
 
-static int __init agp_find_supported_device(struct pci_dev *dev)
+static int __init agp_hp_probe(struct pci_dev *pdev,
+			       const struct pci_device_id *ent)
 {
-	agp_bridge->dev = dev;
+	struct agp_bridge_data *bridge;
+	int error;
 
 	/* ZX1 LBAs can be either PCI or AGP bridges */
-	if (pci_find_capability(dev, PCI_CAP_ID_AGP)) {
-		printk(KERN_INFO PFX "Detected HP ZX1 AGP chipset at %s\n",
-			dev->slot_name);
-		agp_bridge->type = HP_ZX1;
-		agp_bridge->dev = dev;
-		return hp_zx1_setup(dev);
-	}
-	return -ENODEV;
-}
+	if (!pci_find_capability(pdev, PCI_CAP_ID_AGP))
+		return -ENODEV;
 
-static struct agp_driver hp_agp_driver = {
-	.owner = THIS_MODULE,
-};
+	printk(KERN_INFO PFX "Detected HP ZX1 AGP chipset at %s\n",
+			pdev->slot_name);
+
+	error = hp_zx1_ioc_init();
+	if (error)
+		return error;
+
+	bridge = agp_alloc_bridge();
+	if (!bridge)
+		return -ENOMEM;
 
-static int __init agp_hp_probe (struct pci_dev *dev, const struct pci_device_id *ent)
+	bridge->driver = &hp_zx1_driver;
+	bridge->dev = pdev;
+
+	pci_set_drvdata(pdev, bridge);
+	return agp_add_bridge(bridge);
+}
+
+static void __devexit agp_hp_remove(struct pci_dev *pdev)
 {
-	if (agp_find_supported_device(dev) == 0) {
-		hp_agp_driver.dev = dev;
-		agp_register_driver(&hp_agp_driver);
-		return 0;
-	}
-	return -ENODEV;
+	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+
+	agp_remove_bridge(bridge);
+	agp_put_bridge(bridge);
 }
 
 static struct pci_device_id agp_hp_pci_table[] __initdata = {
@@ -400,22 +404,16 @@
 	.name		= "agpgart-hp",
 	.id_table	= agp_hp_pci_table,
 	.probe		= agp_hp_probe,
+	.remove		= agp_hp_remove,
 };
 
 static int __init agp_hp_init(void)
 {
-	int ret_val;
-
-	ret_val = pci_module_init(&agp_hp_pci_driver);
-	if (ret_val)
-		agp_bridge->type = NOT_SUPPORTED;
-
-	return ret_val;
+	return pci_module_init(&agp_hp_pci_driver);
 }
 
 static void __exit agp_hp_cleanup(void)
 {
-	agp_unregister_driver(&hp_agp_driver);
 	pci_unregister_driver(&agp_hp_pci_driver);
 }
 
diff -urN linux-2.5.69-bk6/drivers/char/agp/i460-agp.c linux-2.5.69-bk7/drivers/char/agp/i460-agp.c
--- linux-2.5.69-bk6/drivers/char/agp/i460-agp.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/i460-agp.c	2003-05-12 04:43:29.000000000 -0700
@@ -69,7 +69,7 @@
 	} *lp_desc;
 } i460;
 
-static const struct aper_size_info_8 i460_sizes[3] =
+static struct aper_size_info_8 i460_sizes[3] =
 {
 	/*
 	 * The 32GB aperture is only available with a 4M GART page size.  Due to the
@@ -107,7 +107,7 @@
 		return 0;
 	}
 
-	values = A_SIZE_8(agp_bridge->aperture_sizes);
+	values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
 
 	pci_read_config_byte(agp_bridge->dev, INTEL_I460_AGPSIZ, &temp);
 
@@ -130,7 +130,7 @@
 	else
 		i460.dynamic_apbase = INTEL_I460_APBASE;
 
-	for (i = 0; i < agp_bridge->num_aperture_sizes; i++) {
+	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
 		/*
 		 * Dynamically calculate the proper num_entries and page_order values for
 		 * the define aperture sizes. Take care not to shift off the end of
@@ -140,7 +140,7 @@
 		values[i].page_order = log2((sizeof(u32)*values[i].num_entries) >> PAGE_SHIFT);
 	}
 
-	for (i = 0; i < agp_bridge->num_aperture_sizes; i++) {
+	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
 		/* Neglect control bits when matching up size_value */
 		if ((temp & I460_AGPSIZ_MASK) == values[i].size_value) {
 			agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i);
@@ -294,7 +294,7 @@
 
 	j = io_pg_start;
 	while (j < (io_pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count)) {
-		if (!PGE_EMPTY(RD_GATT(j))) {
+		if (!PGE_EMPTY(agp_bridge, RD_GATT(j))) {
 			pr_debug("i460_insert_memory_small_io_page: GATT[%d]=0x%x is busy\n",
 				 j, RD_GATT(j));
 			return -EBUSY;
@@ -306,7 +306,7 @@
 	for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
 		paddr = mem->memory[i];
 		for (k = 0; k < I460_IOPAGES_PER_KPAGE; k++, j++, paddr += io_page_size)
-			WR_GATT(j, agp_bridge->mask_memory(paddr, mem->type));
+			WR_GATT(j, agp_bridge->driver->mask_memory(paddr, mem->type));
 	}
 	WR_FLUSH_GATT(j - 1);
 	return 0;
@@ -417,7 +417,7 @@
 			if (i460_alloc_large_page(lp) < 0)
 				return -ENOMEM;
 			pg = lp - i460.lp_desc;
-			WR_GATT(pg, agp_bridge->mask_memory(lp->paddr, 0));
+			WR_GATT(pg, agp_bridge->driver->mask_memory(lp->paddr, 0));
 			WR_FLUSH_GATT(pg);
 		}
 
@@ -439,7 +439,7 @@
 	struct lp_desc *start, *end, *lp;
 	void *temp;
 
-	temp = agp_bridge->current_size;
+	temp = agp_bridge->driver->current_size;
 	num_entries = A_SIZE_8(temp)->num_entries;
 
 	/* Figure out what pg_start means in terms of our large GART pages */
@@ -519,64 +519,71 @@
 static unsigned long i460_mask_memory (unsigned long addr, int type)
 {
 	/* Make sure the returned address is a valid GATT entry */
-	return (agp_bridge->masks[0].mask
+	return (agp_bridge->driver->masks[0].mask
 		| (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xffffff000) >> 12));
 }
 
-static int __init intel_i460_setup (struct pci_dev *pdev __attribute__((unused)))
-{
-	agp_bridge->masks = i460_masks;
-	agp_bridge->aperture_sizes = (void *) i460_sizes;
-	agp_bridge->size_type = U8_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 3;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = i460_configure;
-	agp_bridge->fetch_size = i460_fetch_size;
-	agp_bridge->cleanup = i460_cleanup;
-	agp_bridge->tlb_flush = i460_tlb_flush;
-	agp_bridge->mask_memory = i460_mask_memory;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = i460_create_gatt_table;
-	agp_bridge->free_gatt_table = i460_free_gatt_table;
+struct agp_bridge_driver intel_i460_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= i460_masks,
+	.aperture_sizes		= i460_sizes,
+	.size_type		= U8_APER_SIZE,
+	.num_aperture_sizes	= 3,
+	.configure		= i460_configure,
+	.fetch_size		= i460_fetch_size,
+	.cleanup		= i460_cleanup,
+	.tlb_flush		= i460_tlb_flush,
+	.mask_memory		= i460_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= i460_create_gatt_table,
+	.free_gatt_table	= i460_free_gatt_table,
 #if I460_LARGE_IO_PAGES
-	agp_bridge->insert_memory = i460_insert_memory;
-	agp_bridge->remove_memory = i460_remove_memory;
-	agp_bridge->agp_alloc_page = i460_alloc_page;
-	agp_bridge->agp_destroy_page = i460_destroy_page;
+	.insert_memory		= i460_insert_memory,
+	.remove_memory		= i460_remove_memory,
+	.agp_alloc_page		= i460_alloc_page,
+	.agp_destroy_page	= i460_destroy_page,
 #else
-	agp_bridge->insert_memory = i460_insert_memory_small_io_page;
-	agp_bridge->remove_memory = i460_remove_memory_small_io_page;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
+	.insert_memory		= i460_insert_memory_small_io_page,
+	.remove_memory		= i460_remove_memory_small_io_page,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
 #endif
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 1;
-	return 0;
-}
-
-static struct agp_driver i460_agp_driver = {
-	.owner = THIS_MODULE,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+	.cant_use_aperture	= 1,
 };
 
-static int __init agp_intel_i460_probe (struct pci_dev *dev, const struct pci_device_id *ent)
+static int __init agp_intel_i460_probe(struct pci_dev *pdev,
+				       const struct pci_device_id *ent)
 {
-	u8 cap_ptr = 0;
+	struct agp_bridge_data *bridge;
+	u8 cap_ptr;
 
-	cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
-	if (cap_ptr == 0)
+	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+	if (!cap_ptr)
 		return -ENODEV;
 
-	agp_bridge->dev = dev;
-	agp_bridge->capndx = cap_ptr;
-	intel_i460_setup(dev);
-	i460_agp_driver.dev = dev;
-	agp_register_driver(&i460_agp_driver);
-	return 0;
+	bridge = agp_alloc_bridge();
+	if (!bridge)
+		return -ENOMEM;
+
+	bridge->driver = &intel_i460_driver;
+	bridge->dev = pdev;
+	bridge->capndx = cap_ptr;
+
+	pci_set_drvdata(pdev, bridge);
+	return agp_add_bridge(bridge);
+}
+
+static void __devexit agp_intel_i460_remove(struct pci_dev *pdev)
+{
+	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+
+	agp_remove_bridge(bridge);
+	agp_put_bridge(bridge);
 }
 
 static struct pci_device_id agp_intel_i460_pci_table[] __initdata = {
@@ -597,22 +604,16 @@
 	.name		= "agpgart-intel-i460",
 	.id_table	= agp_intel_i460_pci_table,
 	.probe		= agp_intel_i460_probe,
+	.remove		= agp_intel_i460_remove,
 };
 
 static int __init agp_intel_i460_init(void)
 {
-	int ret_val;
-
-	ret_val = pci_module_init(&agp_intel_i460_pci_driver);
-	if (ret_val)
-		agp_bridge->type = NOT_SUPPORTED;
-
-	return ret_val;
+	return pci_module_init(&agp_intel_i460_pci_driver);
 }
 
 static void __exit agp_intel_i460_cleanup(void)
 {
-	agp_unregister_driver(&i460_agp_driver);
 	pci_unregister_driver(&agp_intel_i460_pci_driver);
 }
 
diff -urN linux-2.5.69-bk6/drivers/char/agp/intel-agp.c linux-2.5.69-bk7/drivers/char/agp/intel-agp.c
--- linux-2.5.69-bk6/drivers/char/agp/intel-agp.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/intel-agp.c	2003-05-12 04:43:29.000000000 -0700
@@ -45,7 +45,7 @@
 	struct aper_size_info_fixed *values;
 
 	pci_read_config_dword(agp_bridge->dev, I810_SMRAM_MISCC, &smram_miscc);
-	values = A_SIZE_FIX(agp_bridge->aperture_sizes);
+	values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
 
 	if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) {
 		printk(KERN_WARNING PFX "i810 is disabled\n");
@@ -89,9 +89,9 @@
 	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
 	OUTREG32(intel_i810_private.registers, I810_PGETBL_CTL,
 		 agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED);
-	CACHE_FLUSH();
+	global_cache_flush();
 
-	if (agp_bridge->needs_scratch_page == TRUE) {
+	if (agp_bridge->driver->needs_scratch_page) {
 		for (i = 0; i < current_size->num_entries; i++) {
 			OUTREG32(intel_i810_private.registers,
 				 I810_PTE_BASE + (i * 4),
@@ -130,23 +130,22 @@
 		return -EINVAL;
 	}
 	for (j = pg_start; j < (pg_start + mem->page_count); j++) {
-		if (!PGE_EMPTY(agp_bridge->gatt_table[j])) {
+		if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j]))
 			return -EBUSY;
-		}
 	}
 
 	if (type != 0 || mem->type != 0) {
 		if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) {
 			/* special insert */
-			CACHE_FLUSH();
+			global_cache_flush();
 			for (i = pg_start; i < (pg_start + mem->page_count); i++) {
 				OUTREG32(intel_i810_private.registers,
 					 I810_PTE_BASE + (i * 4),
 					 (i * 4096) | I810_PTE_LOCAL |
 					 I810_PTE_VALID);
 			}
-			CACHE_FLUSH();
-			agp_bridge->tlb_flush(mem);
+			global_cache_flush();
+			agp_bridge->driver->tlb_flush(mem);
 			return 0;
 		}
 		if((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY))
@@ -155,15 +154,15 @@
 	}
 
 insert:
-	CACHE_FLUSH();
+	global_cache_flush();
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		OUTREG32(intel_i810_private.registers,
 			I810_PTE_BASE + (j * 4),
-			agp_bridge->mask_memory(mem->memory[i], mem->type));
+			agp_bridge->driver->mask_memory(mem->memory[i], mem->type));
 	}
-	CACHE_FLUSH();
+	global_cache_flush();
 
-	agp_bridge->tlb_flush(mem);
+	agp_bridge->driver->tlb_flush(mem);
 	return 0;
 }
 
@@ -178,58 +177,61 @@
 			 agp_bridge->scratch_page);
 	}
 
-	CACHE_FLUSH();
-	agp_bridge->tlb_flush(mem);
+	global_cache_flush();
+	agp_bridge->driver->tlb_flush(mem);
 	return 0;
 }
 
+/*
+ * The i810/i830 requires a physical address to program its mouse
+ * pointer into hardware.
+ * However the Xserver still writes to it through the agp aperture.
+ */
+static agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
+{
+	agp_memory *new;
+	void *addr;
+
+	if (pg_count != 1)
+		return NULL;
+
+	addr = agp_bridge->driver->agp_alloc_page();
+	if (addr == NULL)
+		return NULL;
+
+	new = agp_create_memory(1);
+	if (new == NULL)
+		return NULL;
+
+	new->memory[0] = virt_to_phys(addr);
+	new->page_count = 1;
+	new->num_scratch_pages = 1;
+	new->type = AGP_PHYS_MEMORY;
+	new->physical = new->memory[0];
+	return new;
+}
+
 static agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
 {
 	agp_memory *new;
 
 	if (type == AGP_DCACHE_MEMORY) {
-		if (pg_count != intel_i810_private.num_dcache_entries) {
+		if (pg_count != intel_i810_private.num_dcache_entries)
 			return NULL;
-		}
-		new = agp_create_memory(1);
 
-		if (new == NULL) {
+		new = agp_create_memory(1);
+		if (new == NULL)
 			return NULL;
-		}
+
 		new->type = AGP_DCACHE_MEMORY;
 		new->page_count = pg_count;
 		new->num_scratch_pages = 0;
 		vfree(new->memory);
 		return new;
 	}
-	if(type == AGP_PHYS_MEMORY) {
-		void *addr;
-		/* The I810 requires a physical address to program
-		 * it's mouse pointer into hardware.  However the
-		 * Xserver still writes to it through the agp
-		 * aperture
-		 */
-		if (pg_count != 1)
-			return NULL;
-
-		new = agp_create_memory(1);
-		if (new == NULL)
-			return NULL;
-
-		addr = agp_bridge->agp_alloc_page();
+	if (type == AGP_PHYS_MEMORY)
+		return(alloc_agpphysmem_i8xx(pg_count, type));
 
-		if (addr == NULL) {
-			/* Free this structure */
-			agp_free_memory(new);
-			return NULL;
-		}
-		new->memory[0] = virt_to_phys(addr);
-		new->page_count = 1;
-		new->num_scratch_pages = 1;
-		new->type = AGP_PHYS_MEMORY;
-		new->physical = new->memory[0];
-		return new;
-	}
 	return NULL;
 }
 
@@ -237,7 +239,7 @@
 {
 	agp_free_key(curr->key);
 	if(curr->type == AGP_PHYS_MEMORY) {
-		agp_bridge->agp_destroy_page(phys_to_virt(curr->memory[0]));
+		agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[0]));
 		vfree(curr->memory);
 	}
 	kfree(curr);
@@ -246,39 +248,7 @@
 static unsigned long intel_i810_mask_memory(unsigned long addr, int type)
 {
 	/* Type checking must be done elsewhere */
-	return addr | agp_bridge->masks[type].mask;
-}
-
-static int __init intel_i810_setup(struct pci_dev *i810_dev)
-{
-	intel_i810_private.i810_dev = i810_dev;
-
-	agp_bridge->masks = intel_i810_masks;
-	agp_bridge->aperture_sizes = (void *) intel_i810_sizes;
-	agp_bridge->size_type = FIXED_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 2;
-	agp_bridge->dev_private_data = (void *) &intel_i810_private;
-	agp_bridge->needs_scratch_page = TRUE;
-	agp_bridge->configure = intel_i810_configure;
-	agp_bridge->fetch_size = intel_i810_fetch_size;
-	agp_bridge->cleanup = intel_i810_cleanup;
-	agp_bridge->tlb_flush = intel_i810_tlbflush;
-	agp_bridge->mask_memory = intel_i810_mask_memory;
-	agp_bridge->agp_enable = intel_i810_agp_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
-	agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
-	agp_bridge->insert_memory = intel_i810_insert_entries;
-	agp_bridge->remove_memory = intel_i810_remove_entries;
-	agp_bridge->alloc_by_type = intel_i810_alloc_by_type;
-	agp_bridge->free_by_type = intel_i810_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
-
-	return 0;
+	return addr | agp_bridge->driver->masks[type].mask;
 }
 
 static struct aper_size_info_fixed intel_i830_sizes[] =
@@ -379,10 +349,11 @@
 	temp &= 0xfff80000;
 
 	intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096);
-	if (!intel_i830_private.registers) return (-ENOMEM);
+	if (!intel_i830_private.registers)
+		return (-ENOMEM);
 
 	temp = INREG32(intel_i830_private.registers,I810_PGETBL_CTL) & 0xfffff000;
-	CACHE_FLUSH();
+	global_cache_flush();
 
 	/* we have to call this as early as possible after the MMIO base address is known */
 	intel_i830_init_gtt_entries();
@@ -407,7 +378,7 @@
 	u16 gmch_ctrl;
 	struct aper_size_info_fixed *values;
 
-	values = A_SIZE_FIX(agp_bridge->aperture_sizes);
+	values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
 
 	if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB &&
 	    agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) {
@@ -449,9 +420,9 @@
 	pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
 
 	OUTREG32(intel_i830_private.registers,I810_PGETBL_CTL,agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED);
-	CACHE_FLUSH();
+	global_cache_flush();
 
-	if (agp_bridge->needs_scratch_page == TRUE)
+	if (agp_bridge->driver->needs_scratch_page)
 		for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++)
 			OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge->scratch_page);
 
@@ -490,15 +461,15 @@
 		(mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
 		return (-EINVAL);
 
-	CACHE_FLUSH();
+	global_cache_flush();
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++)
 		OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4),
-			agp_bridge->mask_memory(mem->memory[i], mem->type));
+			agp_bridge->driver->mask_memory(mem->memory[i], mem->type));
 
-	CACHE_FLUSH();
+	global_cache_flush();
 
-	agp_bridge->tlb_flush(mem);
+	agp_bridge->driver->tlb_flush(mem);
 
 	return(0);
 }
@@ -507,7 +478,7 @@
 {
 	int i;
 
-	CACHE_FLUSH ();
+	global_cache_flush();
 
 	if (pg_start < intel_i830_private.gtt_entries) {
 		printk ("Trying to disable local/stolen memory\n");
@@ -517,90 +488,22 @@
 	for (i = pg_start; i < (mem->page_count + pg_start); i++)
 		OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge->scratch_page);
 
-	CACHE_FLUSH();
+	global_cache_flush();
 
-	agp_bridge->tlb_flush(mem);
+	agp_bridge->driver->tlb_flush(mem);
 
 	return (0);
 }
 
 static agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
 {
-	agp_memory *nw;
-
-	/* always return NULL for now */
-	if (type == AGP_DCACHE_MEMORY) return(NULL);
-
-	if (type == AGP_PHYS_MEMORY) {
-		void *addr;
-
-		/* The i830 requires a physical address to program
-		 * it's mouse pointer into hardware. However the
-		 * Xserver still writes to it through the agp
-		 * aperture
-		 */
-
-		if (pg_count != 1) return(NULL);
-
-		nw = agp_create_memory(1);
-
-		if (nw == NULL) return(NULL);
-
-		addr = agp_bridge->agp_alloc_page();
-		if (addr == NULL) {
-			/* free this structure */
-			agp_free_memory(nw);
-			return(NULL);
-		}
-
-		nw->memory[0] = virt_to_phys(addr);
-		nw->page_count = 1;
-		nw->num_scratch_pages = 1;
-		nw->type = AGP_PHYS_MEMORY;
-		nw->physical = nw->memory[0];
-		return(nw);
-	}
+	if (type == AGP_PHYS_MEMORY)
+		return(alloc_agpphysmem_i8xx(pg_count, type));
 
+	/* always return NULL for other allocation types for now */
 	return(NULL);
 }
 
-static int __init intel_i830_setup(struct pci_dev *i830_dev)
-{
-	intel_i830_private.i830_dev = i830_dev;
-
-	agp_bridge->masks = intel_i810_masks;
-	agp_bridge->aperture_sizes = (void *) intel_i830_sizes;
-	agp_bridge->size_type = FIXED_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 2;
-
-	agp_bridge->dev_private_data = (void *) &intel_i830_private;
-	agp_bridge->needs_scratch_page = TRUE;
-
-	agp_bridge->configure = intel_i830_configure;
-	agp_bridge->fetch_size = intel_i830_fetch_size;
-	agp_bridge->cleanup = intel_i830_cleanup;
-	agp_bridge->tlb_flush = intel_i810_tlbflush;
-	agp_bridge->mask_memory = intel_i810_mask_memory;
-	agp_bridge->agp_enable = intel_i810_agp_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-
-	agp_bridge->create_gatt_table = intel_i830_create_gatt_table;
-	agp_bridge->free_gatt_table = intel_i830_free_gatt_table;
-
-	agp_bridge->insert_memory = intel_i830_insert_entries;
-	agp_bridge->remove_memory = intel_i830_remove_entries;
-	agp_bridge->alloc_by_type = intel_i830_alloc_by_type;
-	agp_bridge->free_by_type = intel_i810_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
-
-	return(0);
-}
-
 static int intel_fetch_size(void)
 {
 	int i;
@@ -608,9 +511,9 @@
 	struct aper_size_info_16 *values;
 
 	pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp);
-	values = A_SIZE_16(agp_bridge->aperture_sizes);
+	values = A_SIZE_16(agp_bridge->driver->aperture_sizes);
 
-	for (i = 0; i < agp_bridge->num_aperture_sizes; i++) {
+	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
 		if (temp == values[i].size_value) {
 			agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i);
 			agp_bridge->aperture_size_idx = i;
@@ -621,22 +524,14 @@
 	return 0;
 }
 
-static int intel_8xx_fetch_size(void)
+static int __intel_8xx_fetch_size(u8 temp)
 {
 	int i;
-	u8 temp;
 	struct aper_size_info_8 *values;
 
-	pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
-
-	/* Intel 815 chipsets have a _weird_ APSIZE register with only
-	 * one non-reserved bit, so mask the others out ... */
-	if (agp_bridge->type == INTEL_I815)
-		temp &= (1 << 3);
+	values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
 
-	values = A_SIZE_8(agp_bridge->aperture_sizes);
-
-	for (i = 0; i < agp_bridge->num_aperture_sizes; i++) {
+	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
 		if (temp == values[i].size_value) {
 			agp_bridge->previous_size =
 				agp_bridge->current_size = (void *) (values + i);
@@ -647,6 +542,25 @@
 	return 0;
 }
 
+static int intel_8xx_fetch_size(void)
+{
+	u8 temp;
+
+	pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
+	return __intel_8xx_fetch_size(temp);
+}
+
+static int intel_815_fetch_size(void)
+{
+	u8 temp;
+
+	/* Intel 815 chipsets have a _weird_ APSIZE register with only
+	 * one non-reserved bit, so mask the others out ... */
+	pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
+	temp &= (1 << 3);
+
+	return __intel_8xx_fetch_size(temp);
+}
 
 static void intel_tlbflush(agp_memory * mem)
 {
@@ -991,7 +905,7 @@
 static unsigned long intel_mask_memory(unsigned long addr, int type)
 {
 	/* Memory type is ignored */
-	return addr | agp_bridge->masks[0].mask;
+	return addr | agp_bridge->driver->masks[0].mask;
 }
 
 static void intel_resume(void)
@@ -1041,584 +955,485 @@
 	{32, 8192, 3, 56}
 };
 
-static int __init intel_generic_setup (struct pci_dev *pdev)
-{
-	agp_bridge->masks = intel_generic_masks;
-	agp_bridge->aperture_sizes = (void *) intel_generic_sizes;
-	agp_bridge->size_type = U16_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 7;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = intel_configure;
-	agp_bridge->fetch_size = intel_fetch_size;
-	agp_bridge->cleanup = intel_cleanup;
-	agp_bridge->tlb_flush = intel_tlbflush;
-	agp_bridge->mask_memory = intel_mask_memory;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
-	agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
-	agp_bridge->insert_memory = agp_generic_insert_memory;
-	agp_bridge->remove_memory = agp_generic_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = intel_resume;
-	agp_bridge->cant_use_aperture = 0;
-	return 0;
-}
+struct agp_bridge_driver intel_generic_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= intel_generic_masks,
+	.aperture_sizes		= intel_generic_sizes,
+	.size_type		= U16_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= intel_configure,
+	.fetch_size		= intel_fetch_size,
+	.cleanup		= intel_cleanup,
+	.tlb_flush		= intel_tlbflush,
+	.mask_memory		= intel_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= intel_resume,
+};
 
-static int __init intel_815_setup (struct pci_dev *pdev)
-{
-	agp_bridge->masks = intel_generic_masks;
-	agp_bridge->aperture_sizes = (void *) intel_815_sizes;
-	agp_bridge->size_type = U8_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 2;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = intel_815_configure;
-	agp_bridge->fetch_size = intel_8xx_fetch_size;
-	agp_bridge->cleanup = intel_8xx_cleanup;
-	agp_bridge->tlb_flush = intel_8xx_tlbflush;
-	agp_bridge->mask_memory = intel_mask_memory;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
-	agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
-	agp_bridge->insert_memory = agp_generic_insert_memory;
-	agp_bridge->remove_memory = agp_generic_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
-	return 0;
-}
+struct agp_bridge_driver intel_810_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= intel_i810_masks,
+	.aperture_sizes		= intel_i810_sizes,
+	.size_type		= FIXED_APER_SIZE,
+	.num_aperture_sizes	= 2,
+	.needs_scratch_page	= TRUE,
+	.configure		= intel_i810_configure,
+	.fetch_size		= intel_i810_fetch_size,
+	.cleanup		= intel_i810_cleanup,
+	.tlb_flush		= intel_i810_tlbflush,
+	.mask_memory		= intel_i810_mask_memory,
+	.agp_enable		= intel_i810_agp_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= intel_i810_insert_entries,
+	.remove_memory		= intel_i810_remove_entries,
+	.alloc_by_type		= intel_i810_alloc_by_type,
+	.free_by_type		= intel_i810_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
 
 
-static int __init intel_820_setup (struct pci_dev *pdev)
-{
-	agp_bridge->masks = intel_generic_masks;
-	agp_bridge->aperture_sizes = (void *) intel_8xx_sizes;
-	agp_bridge->size_type = U8_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 7;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = intel_820_configure;
-	agp_bridge->fetch_size = intel_8xx_fetch_size;
-	agp_bridge->cleanup = intel_820_cleanup;
-	agp_bridge->tlb_flush = intel_820_tlbflush;
-	agp_bridge->mask_memory = intel_mask_memory;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
-	agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
-	agp_bridge->insert_memory = agp_generic_insert_memory;
-	agp_bridge->remove_memory = agp_generic_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
-	return 0;
-}
+struct agp_bridge_driver intel_815_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= intel_generic_masks,
+	.aperture_sizes		= intel_815_sizes,
+	.size_type		= U8_APER_SIZE,
+	.num_aperture_sizes	= 2,
+	.configure		= intel_815_configure,
+	.fetch_size		= intel_815_fetch_size,
+	.cleanup		= intel_8xx_cleanup,
+	.tlb_flush		= intel_8xx_tlbflush,
+	.mask_memory		= intel_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
 
-static int __init intel_830mp_setup (struct pci_dev *pdev)
-{
-	agp_bridge->masks = intel_generic_masks;
-	agp_bridge->aperture_sizes = (void *) intel_830mp_sizes;
-	agp_bridge->size_type = U8_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 4;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = intel_830mp_configure;
-	agp_bridge->fetch_size = intel_8xx_fetch_size;
-	agp_bridge->cleanup = intel_8xx_cleanup;
-	agp_bridge->tlb_flush = intel_8xx_tlbflush;
-	agp_bridge->mask_memory = intel_mask_memory;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
-	agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
-	agp_bridge->insert_memory = agp_generic_insert_memory;
-	agp_bridge->remove_memory = agp_generic_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
-	return 0;
-}
+struct agp_bridge_driver intel_830_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= intel_i810_masks,
+	.aperture_sizes		= intel_i830_sizes,
+	.size_type		= FIXED_APER_SIZE,
+	.num_aperture_sizes 	= 2,
+	.needs_scratch_page	= TRUE,
+	.configure		= intel_i830_configure,
+	.fetch_size		= intel_i830_fetch_size,
+	.cleanup		= intel_i830_cleanup,
+	.tlb_flush		= intel_i810_tlbflush,
+	.mask_memory		= intel_i810_mask_memory,
+	.agp_enable		= intel_i810_agp_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= intel_i830_create_gatt_table,
+	.free_gatt_table	= intel_i830_free_gatt_table,
+	.insert_memory		= intel_i830_insert_entries,
+	.remove_memory		= intel_i830_remove_entries,
+	.alloc_by_type		= intel_i830_alloc_by_type,
+	.free_by_type		= intel_i810_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
 
-static int __init intel_840_setup (struct pci_dev *pdev)
-{
-	agp_bridge->masks = intel_generic_masks;
-	agp_bridge->aperture_sizes = (void *) intel_8xx_sizes;
-	agp_bridge->size_type = U8_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 7;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = intel_840_configure;
-	agp_bridge->fetch_size = intel_8xx_fetch_size;
-	agp_bridge->cleanup = intel_8xx_cleanup;
-	agp_bridge->tlb_flush = intel_8xx_tlbflush;
-	agp_bridge->mask_memory = intel_mask_memory;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
-	agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
-	agp_bridge->insert_memory = agp_generic_insert_memory;
-	agp_bridge->remove_memory = agp_generic_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
-	return 0;
-}
 
-static int __init intel_845_setup (struct pci_dev *pdev)
-{
-	agp_bridge->masks = intel_generic_masks;
-	agp_bridge->aperture_sizes = (void *) intel_8xx_sizes;
-	agp_bridge->size_type = U8_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 7;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = intel_845_configure;
-	agp_bridge->fetch_size = intel_8xx_fetch_size;
-	agp_bridge->cleanup = intel_8xx_cleanup;
-	agp_bridge->tlb_flush = intel_8xx_tlbflush;
-	agp_bridge->mask_memory = intel_mask_memory;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
-	agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
-	agp_bridge->insert_memory = agp_generic_insert_memory;
-	agp_bridge->remove_memory = agp_generic_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = intel_845_resume;
-	agp_bridge->cant_use_aperture = 0;
-	return 0;
-}
+struct agp_bridge_driver intel_820_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= intel_generic_masks,
+	.aperture_sizes		= intel_8xx_sizes,
+	.size_type		= U8_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= intel_820_configure,
+	.fetch_size		= intel_8xx_fetch_size,
+	.cleanup		= intel_820_cleanup,
+	.tlb_flush		= intel_820_tlbflush,
+	.mask_memory		= intel_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
 
-static int __init intel_850_setup (struct pci_dev *pdev)
-{
-	agp_bridge->masks = intel_generic_masks;
-	agp_bridge->aperture_sizes = (void *) intel_8xx_sizes;
-	agp_bridge->size_type = U8_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 7;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = intel_850_configure;
-	agp_bridge->fetch_size = intel_8xx_fetch_size;
-	agp_bridge->cleanup = intel_8xx_cleanup;
-	agp_bridge->tlb_flush = intel_8xx_tlbflush;
-	agp_bridge->mask_memory = intel_mask_memory;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
-	agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
-	agp_bridge->insert_memory = agp_generic_insert_memory;
-	agp_bridge->remove_memory = agp_generic_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
-	return 0;
-}
+struct agp_bridge_driver intel_830mp_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= intel_generic_masks,
+	.aperture_sizes		= intel_830mp_sizes,
+	.size_type		= U8_APER_SIZE,
+	.num_aperture_sizes	= 4,
+	.configure		= intel_830mp_configure,
+	.fetch_size		= intel_8xx_fetch_size,
+	.cleanup		= intel_8xx_cleanup,
+	.tlb_flush		= intel_8xx_tlbflush,
+	.mask_memory		= intel_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
 
-static int __init intel_860_setup (struct pci_dev *pdev)
-{
-	agp_bridge->masks = intel_generic_masks;
-	agp_bridge->aperture_sizes = (void *) intel_8xx_sizes;
-	agp_bridge->size_type = U8_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 7;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = intel_860_configure;
-	agp_bridge->fetch_size = intel_8xx_fetch_size;
-	agp_bridge->cleanup = intel_8xx_cleanup;
-	agp_bridge->tlb_flush = intel_8xx_tlbflush;
-	agp_bridge->mask_memory = intel_mask_memory;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
-	agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
-	agp_bridge->insert_memory = agp_generic_insert_memory;
-	agp_bridge->remove_memory = agp_generic_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
-	return 0;
-}
+struct agp_bridge_driver intel_840_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= intel_generic_masks,
+	.aperture_sizes		= intel_8xx_sizes,
+	.size_type		= U8_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= intel_840_configure,
+	.fetch_size		= intel_8xx_fetch_size,
+	.cleanup		= intel_8xx_cleanup,
+	.tlb_flush		= intel_8xx_tlbflush,
+	.mask_memory		= intel_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
 
-static int __init intel_7505_setup (struct pci_dev *pdev)
-{
-	agp_bridge->masks = intel_generic_masks;
-	agp_bridge->aperture_sizes = (void *) intel_8xx_sizes;
-	agp_bridge->size_type = U8_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 7;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = intel_7505_configure;
-	agp_bridge->fetch_size = intel_8xx_fetch_size;
-	agp_bridge->cleanup = intel_8xx_cleanup;
-	agp_bridge->tlb_flush = intel_8xx_tlbflush;
-	agp_bridge->mask_memory = intel_mask_memory;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
-	agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
-	agp_bridge->insert_memory = agp_generic_insert_memory;
-	agp_bridge->remove_memory = agp_generic_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
-	return 0;
-}
-struct agp_device_ids intel_agp_device_ids[] __initdata =
-{
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_82443LX_0,
-		.chipset	= INTEL_LX,
-		.chipset_name	= "440LX",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_82443BX_0,
-		.chipset	= INTEL_BX,
-		.chipset_name	= "440BX",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_82443GX_0,
-		.chipset	= INTEL_GX,
-		.chipset_name	= "440GX",
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_82815_MC,
-		.chipset	= INTEL_I815,
-		.chipset_name	= "i815",
-		.chipset_setup	= intel_815_setup
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_82820_HB,
-		.chipset	= INTEL_I820,
-		.chipset_name	= "i820",
-		.chipset_setup	= intel_820_setup
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_82820_UP_HB,
-		.chipset	= INTEL_I820,
-		.chipset_name	= "i820",
-		.chipset_setup	= intel_820_setup
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_82830_HB,
-		.chipset	= INTEL_I830_M,
-		.chipset_name	= "830M",
-		.chipset_setup	= intel_830mp_setup
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_82840_HB,
-		.chipset	= INTEL_I840,
-		.chipset_name	= "i840",
-		.chipset_setup	= intel_840_setup
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_82845_HB,
-		.chipset	= INTEL_I845,
-		.chipset_name	= "i845",
-		.chipset_setup	= intel_845_setup
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_82845G_HB,
-		.chipset	= INTEL_I845_G,
-		.chipset_name	= "845G",
-		.chipset_setup	= intel_845_setup
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_82850_HB,
-		.chipset	= INTEL_I850,
-		.chipset_name	= "i850",
-		.chipset_setup	= intel_850_setup
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_82855_HB,
-		.chipset	= INTEL_I855_PM,
-		.chipset_name	= "855PM",
-		.chipset_setup	= intel_845_setup
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_82860_HB,
-		.chipset	= INTEL_I860,
-		.chipset_name	= "i860",
-		.chipset_setup	= intel_860_setup
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_82865_HB,
-		.chipset	= INTEL_I865_G,
-		.chipset_name	= "865G",
-		.chipset_setup	= intel_845_setup
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_7505_0,
-		.chipset	= INTEL_E7505,
-		.chipset_name	= "E7505",
-		.chipset_setup	= intel_7505_setup
-	},
-	{
-		.device_id	= PCI_DEVICE_ID_INTEL_7205_0,
-		.chipset	= INTEL_E7505,
-		.chipset_name	= "E7205",
-		.chipset_setup	= intel_7505_setup
-	},
-	{ }, /* dummy final entry, always present */
+struct agp_bridge_driver intel_845_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= intel_generic_masks,
+	.aperture_sizes		= intel_8xx_sizes,
+	.size_type		= U8_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= intel_845_configure,
+	.fetch_size		= intel_8xx_fetch_size,
+	.cleanup		= intel_8xx_cleanup,
+	.tlb_flush		= intel_8xx_tlbflush,
+	.mask_memory		= intel_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= intel_845_resume,
 };
 
+struct agp_bridge_driver intel_850_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= intel_generic_masks,
+	.aperture_sizes		= intel_8xx_sizes,
+	.size_type		= U8_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= intel_850_configure,
+	.fetch_size		= intel_8xx_fetch_size,
+	.cleanup		= intel_8xx_cleanup,
+	.tlb_flush		= intel_8xx_tlbflush,
+	.mask_memory		= intel_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
+
+struct agp_bridge_driver intel_860_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= intel_generic_masks,
+	.aperture_sizes		= intel_8xx_sizes,
+	.size_type		= U8_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= intel_860_configure,
+	.fetch_size		= intel_8xx_fetch_size,
+	.cleanup		= intel_8xx_cleanup,
+	.tlb_flush		= intel_8xx_tlbflush,
+	.mask_memory		= intel_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
 
-/* scan table above for supported devices */
-static int __init agp_lookup_host_bridge (struct pci_dev *pdev)
+struct agp_bridge_driver intel_7505_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= intel_generic_masks,
+	.aperture_sizes		= intel_8xx_sizes,
+	.size_type		= U8_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= intel_7505_configure,
+	.fetch_size		= intel_8xx_fetch_size,
+	.cleanup		= intel_8xx_cleanup,
+	.tlb_flush		= intel_8xx_tlbflush,
+	.mask_memory		= intel_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
+
+static int find_i810(u16 device, const char *name)
 {
-	int j=0;
-	struct agp_device_ids *devs;
-	
-	devs = intel_agp_device_ids;
+	struct pci_dev *i810_dev;
 
-	while (devs[j].chipset_name != NULL) {
-		if (pdev->device == devs[j].device_id) {
-			printk (KERN_INFO PFX "Detected Intel %s chipset\n",
-				devs[j].chipset_name);
-			agp_bridge->type = devs[j].chipset;
-
-			if (devs[j].chipset_setup != NULL)
-				return devs[j].chipset_setup(pdev);
-			else
-				return intel_generic_setup(pdev);
-		}
-		j++;
+	i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, device, NULL);
+	if (!i810_dev) {
+		printk(KERN_ERR PFX "Detected an Intel %s Chipset, "
+				"but could not find the secondary device.\n",
+				name);
+		return 0;
 	}
-	j--;
+	
+	intel_i810_private.i810_dev = i810_dev;
+	return 1;
+}
 
-	/* try init anyway, if user requests it */
-	if (agp_try_unsupported) {
-		printk(KERN_WARNING PFX "Trying generic Intel routines"
-			" for device id: %04x\n", pdev->device);
-		agp_bridge->type = INTEL_GENERIC;
-		return intel_generic_setup(pdev);
-	}
+static int find_i830(u16 device)
+{
+	struct pci_dev *i830_dev;
 
-	printk(KERN_ERR PFX "Unsupported Intel chipset (device id: %04x),"
-		" you might want to try agp_try_unsupported=1.\n", pdev->device);
-	return -ENODEV;
-}
+	i830_dev = pci_find_device(PCI_VENDOR_ID_INTEL, device, NULL);
+	if (i830_dev && PCI_FUNC(i830_dev->devfn) != 0) {
+		i830_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
+				device, i830_dev);
+	}
 
+	if (!i830_dev)
+		return 0;
 
-/* Supported Device Scanning routine */
+	intel_i830_private.i830_dev = i830_dev;
+	return 1;
+}
 
-static int __init agp_find_supported_device(struct pci_dev *dev)
+static int __init agp_intel_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *ent)
 {
-	struct pci_dev *i810_dev;
+	struct agp_bridge_data *bridge;
+	char *name = "(unknown)";
 	u8 cap_ptr = 0;
 
-	agp_bridge->dev = dev;
+	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+	if (!cap_ptr)
+		return -ENODEV;
 
-	/* This shit needs moving into tables/init-routines. */
-	switch (dev->device) {
+	bridge = agp_alloc_bridge();
+	if (!bridge)
+		return -ENOMEM;
+
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_INTEL_82443LX_0:
+		bridge->driver = &intel_generic_driver;
+		name = "440LX";
+		break;
+	case PCI_DEVICE_ID_INTEL_82443BX_0:
+		bridge->driver = &intel_generic_driver;
+		name = "440BX";
+		break;
+	case PCI_DEVICE_ID_INTEL_82443GX_0:
+		bridge->driver = &intel_generic_driver;
+		name = "440GX";
+		break;
 	case PCI_DEVICE_ID_INTEL_82810_MC1:
-		i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1, NULL);
-		if (i810_dev == NULL) {
-			printk(KERN_ERR PFX "Detected an Intel i810,"
-				" but could not find the secondary device.\n");
-			return -ENODEV;
-		}
-		printk(KERN_INFO PFX "Detected an Intel i810 Chipset.\n");
-		agp_bridge->type = INTEL_I810;
-		return intel_i810_setup (i810_dev);
-
+		if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1, "i810"))
+			goto fail;
+		bridge->driver = &intel_810_driver;
+		name = "i810";
+		break;
 	case PCI_DEVICE_ID_INTEL_82810_MC3:
-		i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3, NULL);
-		if (i810_dev == NULL) {
-			printk(KERN_ERR PFX "Detected an Intel i810 DC100, but could not find the "
-				"secondary device.\n");
-			return -ENODEV;
-		}
-		printk(KERN_INFO PFX "Detected an Intel i810 DC100 Chipset.\n");
-		agp_bridge->type = INTEL_I810;
-		return intel_i810_setup(i810_dev);
-
+		if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3, "i810 DC100"))
+			goto fail;
+		bridge->driver = &intel_810_driver;
+		name = "i810 DC100";
+		break;
 	case PCI_DEVICE_ID_INTEL_82810E_MC:
-		i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG, NULL);
-		if (i810_dev == NULL) {
-			printk(KERN_ERR PFX "Detected an Intel i810 E"
-				", but could not find the secondary device.\n");
-			return -ENODEV;
-		}
-		printk(KERN_INFO PFX "Detected an Intel i810 E Chipset.\n");
-		agp_bridge->type = INTEL_I810;
-		return intel_i810_setup(i810_dev);
-
+		if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG, "i810 E"))
+			goto fail;
+		bridge->driver = &intel_810_driver;
+		name = "i810 E";
+		break;
 	 case PCI_DEVICE_ID_INTEL_82815_MC:
-		/* The i815 can operate either as an i810 style
+		/*
+		 * The i815 can operate either as an i810 style
 		 * integrated device, or as an AGP4X motherboard.
-		 *
-		 * This only addresses the first mode:
 		 */
-		i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC, NULL);
-		if (i810_dev == NULL) {
-			printk(KERN_ERR PFX "agpgart: Detected an "
-				"Intel i815, but could not find the"
-				" secondary device. Assuming a "
-				"non-integrated video card.\n");
-			break;
-		}
-		printk(KERN_INFO PFX "agpgart: Detected an Intel i815 Chipset.\n");
-		agp_bridge->type = INTEL_I810;
-		return intel_i810_setup(i810_dev);
-
-	case PCI_DEVICE_ID_INTEL_82845G_HB:
-		i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
-				PCI_DEVICE_ID_INTEL_82845G_IG, NULL);
-		if (i810_dev && PCI_FUNC(i810_dev->devfn) != 0) {
-			i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
-				PCI_DEVICE_ID_INTEL_82845G_IG, i810_dev);
-		}
-
-		if (i810_dev == NULL) {
-			/* 
-			 * We probably have a I845G chipset with an external graphics
-			 * card. It will be initialized later 
-			 */
-			agp_bridge->type = INTEL_I845_G;
-			break;
-		}
-		printk(KERN_INFO PFX "Detected an Intel(R) 845G Chipset.\n");
-		agp_bridge->type = INTEL_I810;
-		return intel_i830_setup(i810_dev);
-
+		if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC, "i815"))
+			bridge->driver = &intel_810_driver;
+		else
+			bridge->driver = &intel_815_driver;
+		name = "i815";
+		break;
+	case PCI_DEVICE_ID_INTEL_82820_HB:
+	case PCI_DEVICE_ID_INTEL_82820_UP_HB:
+		bridge->driver = &intel_820_driver;
+		name = "i820";
+		break;
 	case PCI_DEVICE_ID_INTEL_82830_HB:
-		i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82830_CGC, NULL);
-		if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0)
-			i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82830_CGC, i810_dev);
-
-		if (i810_dev == NULL) {
-			/* Intel 830MP with external graphic card */
-			/* It will be initialized later */
-			agp_bridge->type = INTEL_I830_M;
-			break;
+		if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC)) {
+			bridge->driver = &intel_830_driver;
+		} else {
+			bridge->driver = &intel_830mp_driver;
 		}
-		printk(KERN_INFO PFX "Detected an Intel(R) 830M Chipset.\n");
-		agp_bridge->type = INTEL_I810;
-		return intel_i830_setup(i810_dev);
-
-	case PCI_DEVICE_ID_INTEL_82855_HB:
-		i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855_IG, NULL);
-		if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0)
-			i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855_IG, i810_dev);
-
-		if (i810_dev == NULL) {
-			/* Intel 855PM with external graphic card */
-			/* It will be initialized later */
-			agp_bridge->type = INTEL_I855_PM;
-			break;
+		name = "830M";
+		break;
+	case PCI_DEVICE_ID_INTEL_82840_HB:
+		bridge->driver = &intel_840_driver;
+		name = "i840";
+		break;
+	case PCI_DEVICE_ID_INTEL_82845_HB:
+		bridge->driver = &intel_845_driver;
+		name = "i845";
+		break;
+	case PCI_DEVICE_ID_INTEL_82845G_HB:
+		if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG)) {
+			bridge->driver = &intel_830_driver;
+		} else {
+			bridge->driver = &intel_845_driver;
 		}
-		{
-			u32 capval = 0;
-			const char *name = "855GM/852GM";
-			pci_read_config_dword(dev, I85X_CAPID, &capval);
-			switch ((capval >> I85X_VARIANT_SHIFT) &
-				I85X_VARIANT_MASK) {
-			case I855_GME:
-				name = "855GME";
-				break;
-			case I855_GM:
-				name = "855GM";
-				break;
-			case I852_GME:
-				name = "852GME";
-				break;
-			case I852_GM:
-				name = "852GM";
-				break;
-			}
-			printk(KERN_INFO PFX
-			       "Detected an Intel(R) %s Chipset.\n", name);
+		name = "845G";
+		break;
+	case PCI_DEVICE_ID_INTEL_82850_HB:
+		bridge->driver = &intel_850_driver;
+		name = "i850";
+		break;
+	case PCI_DEVICE_ID_INTEL_82855PM_HB:
+		bridge->driver = &intel_845_driver;
+		name = "855PM";
+		break;
+	case PCI_DEVICE_ID_INTEL_82855GM_HB:
+		if (find_i830(PCI_DEVICE_ID_INTEL_82855GM_IG)) {
+			bridge->driver = &intel_830_driver;
+			name = "855";
+		} else {
+			bridge->driver = &intel_845_driver;
+			name = "855GM";
 		}
-		agp_bridge->type = INTEL_I810;
-		return intel_i830_setup(i810_dev);
-
+		break;
+	case PCI_DEVICE_ID_INTEL_82860_HB:
+		bridge->driver = &intel_860_driver;
+		name = "i860";
+		break;
 	case PCI_DEVICE_ID_INTEL_82865_HB:
-		i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
-				PCI_DEVICE_ID_INTEL_82865_IG, NULL);
-		if (i810_dev && PCI_FUNC(i810_dev->devfn) != 0) {
-			i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
-				PCI_DEVICE_ID_INTEL_82865_IG, i810_dev);
-		}
-
-		if (i810_dev == NULL) {
-			/* 
-			 * We probably have a 865G chipset with an external graphics
-			 * card. It will be initialized later 
-			 */
-			agp_bridge->type = INTEL_I865_G;
-			break;
+		if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG)) {
+			bridge->driver = &intel_830_driver;
+		} else {
+			bridge->driver = &intel_845_driver;
 		}
-		printk(KERN_INFO PFX "Detected an Intel(R) 865G Chipset.\n");
-		agp_bridge->type = INTEL_I810;
-		return intel_i830_setup(i810_dev);
-
+		name = "865";
+		break;
+	case PCI_DEVICE_ID_INTEL_82875_HB:
+		bridge->driver = &intel_845_driver;
+		name = "i875";
+		break;
+	case PCI_DEVICE_ID_INTEL_7505_0:
+		bridge->driver = &intel_7505_driver;
+		name =  "E7505";
+		break;
+	case PCI_DEVICE_ID_INTEL_7205_0:
+		bridge->driver = &intel_7505_driver;
+		name = "E7205";
+		break;
 	default:
+		if (!agp_try_unsupported) {
+			printk(KERN_ERR PFX
+			    "Unsupported Intel chipset (device id: %04x),"
+			    " you might want to try agp_try_unsupported=1.\n",
+			    pdev->device);
+			return -ENODEV;
+		}
+		bridge->driver = &intel_generic_driver;
 		break;
-	}
+	};
 
-	cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
-	if (cap_ptr == 0)
-		return -ENODEV;
-	agp_bridge->capndx = cap_ptr;
+	bridge->dev = pdev;
+	bridge->capndx = cap_ptr;
 
-	/* Fill in the mode register */
-	pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode);
+	if (bridge->driver == &intel_810_driver)
+		bridge->dev_private_data = &intel_i810_private;
+	else if (bridge->driver == &intel_830_driver)
+		bridge->dev_private_data = &intel_i830_private;
 
-	/* probe for known chipsets */
-	return agp_lookup_host_bridge(dev);
-}
+	printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name);
 
-static struct agp_driver intel_agp_driver = {
-	.owner = THIS_MODULE,
-};
+	/* Fill in the mode register */
+	pci_read_config_dword(pdev,
+			bridge->capndx+PCI_AGP_STATUS,
+			&bridge->mode);
+
+	pci_set_drvdata(pdev, bridge);
+	return agp_add_bridge(bridge);
+ fail:
+	agp_put_bridge(bridge);
+	return -ENODEV;
+}
 
-static int __init agp_intel_probe (struct pci_dev *dev, const struct pci_device_id *ent)
+static void __devexit agp_intel_remove(struct pci_dev *pdev)
 {
-	if (agp_find_supported_device(dev) == 0) {
-		intel_agp_driver.dev = dev;	
-		agp_register_driver(&intel_agp_driver);
-		return 0;
-	}
-	return -ENODEV;	
+	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+
+	agp_remove_bridge(bridge);
+	agp_put_bridge(bridge);
 }
 
 static struct pci_device_id agp_intel_pci_table[] __initdata = {
@@ -1639,29 +1454,24 @@
 	.name		= "agpgart-intel",
 	.id_table	= agp_intel_pci_table,
 	.probe		= agp_intel_probe,
+	.remove		= agp_intel_remove,
 };
 
 /* intel_agp_init() must not be declared static for explicit
    early initialization to work (ie i810fb) */
 int __init agp_intel_init(void)
 {
-	int ret_val;
 	static int agp_initialised=0;
 
-	if (agp_initialised==1)
+	if (agp_initialised == 1)
 		return 0;
 	agp_initialised=1;
 
-	ret_val = pci_module_init(&agp_intel_pci_driver);
-	if (ret_val)
-		agp_bridge->type = NOT_SUPPORTED;
-
-	return ret_val;
+	return pci_module_init(&agp_intel_pci_driver);
 }
 
 static void __exit agp_intel_cleanup(void)
 {
-	agp_unregister_driver(&intel_agp_driver);
 	pci_unregister_driver(&agp_intel_pci_driver);
 }
 
diff -urN linux-2.5.69-bk6/drivers/char/agp/nvidia-agp.c linux-2.5.69-bk7/drivers/char/agp/nvidia-agp.c
--- linux-2.5.69-bk6/drivers/char/agp/nvidia-agp.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk7/drivers/char/agp/nvidia-agp.c	2003-05-12 04:43:29.000000000 -0700
@@ -0,0 +1,380 @@
+/*
+ * Nvidia AGPGART routines.
+ * Based upon a 2.4 agpgart diff by the folks from NVIDIA, and hacked up
+ * to work in 2.5 by Dave Jones <davej@codemonkey.org.uk>
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/agp_backend.h>
+#include <linux/gfp.h>
+#include <linux/page-flags.h>
+#include <linux/mm.h>
+#include "agp.h"
+
+
+/* registers */
+#define NVIDIA_0_APBASE		0x10
+#define NVIDIA_0_APSIZE		0x80
+#define NVIDIA_1_WBC		0xf0
+#define NVIDIA_2_GARTCTRL	0xd0
+#define NVIDIA_2_APBASE		0xd8
+#define NVIDIA_2_APLIMIT	0xdc
+#define NVIDIA_2_ATTBASE(i)	(0xe0 + (i) * 4)
+#define NVIDIA_3_APBASE		0x50
+#define NVIDIA_3_APLIMIT	0x54
+
+
+static int agp_try_unsupported __initdata = 0;
+
+static struct _nvidia_private {
+	struct pci_dev *dev_1;
+	struct pci_dev *dev_2;
+	struct pci_dev *dev_3;
+	volatile u32 *aperture;
+	int num_active_entries;
+	off_t pg_offset;
+	u32 wbc_mask;
+} nvidia_private;
+
+
+static int nvidia_fetch_size(void)
+{
+	int i;
+	u8 size_value;
+	struct aper_size_info_8 *values;
+
+	pci_read_config_byte(agp_bridge->dev, NVIDIA_0_APSIZE, &size_value);
+	size_value &= 0x0f;
+	values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
+
+	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
+		if (size_value == values[i].size_value) {
+			agp_bridge->previous_size =
+				agp_bridge->current_size = (void *) (values + i);
+			agp_bridge->aperture_size_idx = i;
+			return values[i].size;
+		}
+	}
+
+	return 0;
+}
+
+
+static int nvidia_configure(void)
+{
+	int i, num_dirs;
+	u32 apbase, aplimit;
+	struct aper_size_info_8 *current_size;
+	u32 temp;
+
+	current_size = A_SIZE_8(agp_bridge->current_size);
+
+	/* aperture size */
+	pci_write_config_byte(agp_bridge->dev, NVIDIA_0_APSIZE,
+		current_size->size_value);
+
+    /* address to map to */
+	pci_read_config_dword(agp_bridge->dev, NVIDIA_0_APBASE, &apbase);
+	apbase &= PCI_BASE_ADDRESS_MEM_MASK;
+	agp_bridge->gart_bus_addr = apbase;
+	aplimit = apbase + (current_size->size * 1024 * 1024) - 1;
+	pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_APBASE, apbase);
+	pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_APLIMIT, aplimit);
+	pci_write_config_dword(nvidia_private.dev_3, NVIDIA_3_APBASE, apbase);
+	pci_write_config_dword(nvidia_private.dev_3, NVIDIA_3_APLIMIT, aplimit);
+
+	/* directory size is 64k */
+	num_dirs = current_size->size / 64;
+	nvidia_private.num_active_entries = current_size->num_entries;
+	nvidia_private.pg_offset = 0;
+	if (num_dirs == 0) {
+		num_dirs = 1;
+		nvidia_private.num_active_entries /= (64 / current_size->size);
+		nvidia_private.pg_offset = (apbase & (64 * 1024 * 1024 - 1) &
+			~(current_size->size * 1024 * 1024 - 1)) / PAGE_SIZE;
+	}
+
+	/* attbase */
+	for(i = 0; i < 8; i++) {
+		pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_ATTBASE(i),
+			(agp_bridge->gatt_bus_addr + (i % num_dirs) * 64 * 1024) | 1);
+	}
+
+	/* gtlb control */
+	pci_read_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, &temp);
+	pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, temp | 0x11);
+
+	/* gart control */
+	pci_read_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, &temp);
+	pci_write_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, temp | 0x100);
+
+	/* map aperture */
+	nvidia_private.aperture =
+		(volatile u32 *) ioremap(apbase, 33 * PAGE_SIZE);
+
+	return 0;
+}
+
+static void nvidia_cleanup(void)
+{
+	struct aper_size_info_8 *previous_size;
+	u32 temp;
+
+	/* gart control */
+	pci_read_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, &temp);
+	pci_write_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, temp & ~(0x100));
+
+	/* gtlb control */
+	pci_read_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, &temp);
+	pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, temp & ~(0x11));
+
+	/* unmap aperture */
+	iounmap((void *) nvidia_private.aperture);
+
+	/* restore previous aperture size */
+	previous_size = A_SIZE_8(agp_bridge->previous_size);
+	pci_write_config_byte(agp_bridge->dev, NVIDIA_0_APSIZE,
+		previous_size->size_value);
+}
+
+
+static unsigned long nvidia_mask_memory(unsigned long addr, int type)
+{
+	/* Memory type is ignored */
+	return addr | agp_bridge->driver->masks[0].mask;
+}
+
+#if 0
+extern int agp_memory_reserved;
+
+static int nvidia_insert_memory(agp_memory * mem, off_t pg_start, int type)
+{
+	int i, j;
+	
+	if ((type != 0) || (mem->type != 0))
+		return -EINVAL;
+	
+	if ((pg_start + mem->page_count) >
+		(nvidia_private.num_active_entries - agp_memory_reserved/PAGE_SIZE))
+		return -EINVAL;
+	
+	for(j = pg_start; j < (pg_start + mem->page_count); j++) {
+		if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[nvidia_private.pg_offset + j]))
+			return -EBUSY;
+	}
+
+	if (mem->is_flushed == FALSE) {
+		global_cache_flush();
+		mem->is_flushed = TRUE;
+	}
+	for (i = 0, j = pg_start; i < mem->page_count; i++, j++)
+		agp_bridge->gatt_table[nvidia_private.pg_offset + j] = mem->memory[i];
+
+	agp_bridge->tlb_flush(mem);
+	return 0;
+}
+
+static int nvidia_remove_memory(agp_memory * mem, off_t pg_start, int type)
+{
+	int i;
+
+	if ((type != 0) || (mem->type != 0))
+		return -EINVAL;
+	
+	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
+		agp_bridge->gatt_table[nvidia_private.pg_offset + i] =
+		    (unsigned long) agp_bridge->scratch_page;
+	}
+
+	agp_bridge->tlb_flush(mem);
+	return 0;
+}
+#endif
+
+
+static void nvidia_tlbflush(agp_memory * mem)
+{
+	unsigned long end;
+	u32 wbc_reg, temp;
+	int i;
+
+	/* flush chipset */
+	if (nvidia_private.wbc_mask) {
+		pci_read_config_dword(nvidia_private.dev_1, NVIDIA_1_WBC, &wbc_reg);
+		wbc_reg |= nvidia_private.wbc_mask;
+		pci_write_config_dword(nvidia_private.dev_1, NVIDIA_1_WBC, wbc_reg);
+
+		end = jiffies + 3*HZ;
+		do {
+			pci_read_config_dword(nvidia_private.dev_1,
+					NVIDIA_1_WBC, &wbc_reg);
+			if ((signed)(end - jiffies) <= 0) {
+				printk(KERN_ERR
+				    "TLB flush took more than 3 seconds.\n");
+			}
+		} while (wbc_reg & nvidia_private.wbc_mask);
+	}
+
+	/* flush TLB entries */
+	for(i = 0; i < 32 + 1; i++)
+		temp = nvidia_private.aperture[i * PAGE_SIZE / sizeof(u32)];
+	for(i = 0; i < 32 + 1; i++)
+		temp = nvidia_private.aperture[i * PAGE_SIZE / sizeof(u32)];
+}
+
+
+static struct aper_size_info_8 nvidia_generic_sizes[5] =
+{
+	{512, 131072, 7, 0},
+	{256, 65536, 6, 8},
+	{128, 32768, 5, 12},
+	{64, 16384, 4, 14},
+	/* The 32M mode still requires a 64k gatt */
+	{32, 16384, 4, 15}
+};
+
+
+static struct gatt_mask nvidia_generic_masks[] =
+{
+	{0x00000001, 0}
+};
+
+
+struct agp_bridge_driver nvidia_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= nvidia_generic_masks,
+	.aperture_sizes		= nvidia_generic_sizes,
+	.size_type		= U8_APER_SIZE,
+	.num_aperture_sizes	= 5,
+	.configure		= nvidia_configure,
+	.fetch_size		= nvidia_fetch_size,
+	.cleanup		= nvidia_cleanup,
+	.tlb_flush		= nvidia_tlbflush,
+	.mask_memory		= nvidia_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
+
+static int __init agp_nvidia_probe(struct pci_dev *pdev,
+				   const struct pci_device_id *ent)
+{
+	struct agp_bridge_data *bridge;
+	u8 cap_ptr;
+
+	nvidia_private.dev_1 =
+		pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1));
+	nvidia_private.dev_2 =
+		pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2));
+	nvidia_private.dev_3 =
+		pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0));
+	
+	if (!nvidia_private.dev_1 || !nvidia_private.dev_2 || !nvidia_private.dev_3) {
+		printk(KERN_INFO PFX "agpgart: Detected an NVIDIA "
+			"nForce/nForce2 chipset, but could not find "
+			"the secondary devices.\n");
+		return -ENODEV;
+	}
+
+	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+	if (!cap_ptr)
+		return -ENODEV;
+
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_NVIDIA_NFORCE:
+		printk(KERN_INFO PFX "Detected NVIDIA nForce chipset\n");
+		nvidia_private.wbc_mask = 0x00010000;
+		break;
+	case PCI_DEVICE_ID_NVIDIA_NFORCE2:
+		printk(KERN_INFO PFX "Detected NVIDIA nForce2 chipset\n");
+		nvidia_private.wbc_mask = 0x80000000;
+		break;
+	default:
+		if (!agp_try_unsupported) {
+			printk(KERN_ERR PFX
+			    "Unsupported NVIDIA chipset (device id: %04x),"
+			    " you might want to try agp_try_unsupported=1.\n",
+			    pdev->device);
+			return -ENODEV;
+		}
+		printk(KERN_WARNING PFX
+		    "Trying generic NVIDIA routines for device id: %04x\n",
+		    pdev->device);
+		break;
+	}
+
+	bridge = agp_alloc_bridge();
+	if (!bridge)
+		return -ENOMEM;
+
+	bridge->driver = &nvidia_driver;
+	bridge->dev_private_data = &nvidia_private,
+	bridge->dev = pdev;
+	bridge->capndx = cap_ptr;
+
+	/* Fill in the mode register */
+	pci_read_config_dword(pdev,
+			bridge->capndx+PCI_AGP_STATUS,
+			&bridge->mode);
+
+	pci_set_drvdata(pdev, bridge);
+	return agp_add_bridge(bridge);
+}
+
+static void __devexit agp_nvidia_remove(struct pci_dev *pdev)
+{
+	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+
+	agp_remove_bridge(bridge);
+	agp_put_bridge(bridge);
+}
+
+static struct pci_device_id agp_nvidia_pci_table[] __initdata = {
+	{
+	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+	.class_mask	= ~0,
+	.vendor		= PCI_VENDOR_ID_NVIDIA,
+	.device		= PCI_ANY_ID,
+	.subvendor	= PCI_ANY_ID,
+	.subdevice	= PCI_ANY_ID,
+	},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, agp_nvidia_pci_table);
+
+static struct __initdata pci_driver agp_nvidia_pci_driver = {
+	.name		= "agpgart-nvidia",
+	.id_table	= agp_nvidia_pci_table,
+	.probe		= agp_nvidia_probe,
+	.remove		= agp_nvidia_remove,
+};
+
+static int __init agp_nvidia_init(void)
+{
+	return pci_module_init(&agp_nvidia_pci_driver);
+}
+
+static void __exit agp_nvidia_cleanup(void)
+{
+	pci_unregister_driver(&agp_nvidia_pci_driver);
+}
+
+module_init(agp_nvidia_init);
+module_exit(agp_nvidia_cleanup);
+
+MODULE_PARM(agp_try_unsupported, "1i");
+MODULE_LICENSE("GPL and additional rights");
+MODULE_AUTHOR("NVIDIA Corporation");
+
diff -urN linux-2.5.69-bk6/drivers/char/agp/sis-agp.c linux-2.5.69-bk7/drivers/char/agp/sis-agp.c
--- linux-2.5.69-bk6/drivers/char/agp/sis-agp.c	2003-05-04 16:53:00.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/sis-agp.c	2003-05-12 04:43:29.000000000 -0700
@@ -17,8 +17,8 @@
 	struct aper_size_info_8 *values;
 
 	pci_read_config_byte(agp_bridge->dev, SIS_APSIZE, &temp_size);
-	values = A_SIZE_8(agp_bridge->aperture_sizes);
-	for (i = 0; i < agp_bridge->num_aperture_sizes; i++) {
+	values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
+	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
 		if ((temp_size == values[i].size_value) ||
 		    ((temp_size & ~(0x03)) ==
 		     (values[i].size_value & ~(0x03)))) {
@@ -67,7 +67,7 @@
 {
 	/* Memory type is ignored */
 
-	return addr | agp_bridge->masks[0].mask;
+	return addr | agp_bridge->driver->masks[0].mask;
 }
 
 static struct aper_size_info_8 sis_generic_sizes[7] =
@@ -86,164 +86,144 @@
 	{.mask = 0x00000000, .type = 0}
 };
 
-static int __init sis_generic_setup (struct pci_dev *pdev)
-{
-	agp_bridge->masks = sis_generic_masks;
-	agp_bridge->aperture_sizes = (void *) sis_generic_sizes;
-	agp_bridge->size_type = U8_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 7;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = sis_configure;
-	agp_bridge->fetch_size = sis_fetch_size;
-	agp_bridge->cleanup = sis_cleanup;
-	agp_bridge->tlb_flush = sis_tlbflush;
-	agp_bridge->mask_memory = sis_mask_memory;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
-	agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
-	agp_bridge->insert_memory = agp_generic_insert_memory;
-	agp_bridge->remove_memory = agp_generic_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
-
-	return 0;
-}
+struct agp_bridge_driver sis_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= sis_generic_masks,
+	.aperture_sizes 	= sis_generic_sizes,
+	.size_type		= U8_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= sis_configure,
+	.fetch_size		= sis_fetch_size,
+	.cleanup		= sis_cleanup,
+	.tlb_flush		= sis_tlbflush,
+	.mask_memory		= sis_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
 
 struct agp_device_ids sis_agp_device_ids[] __initdata =
 {
 	{
 		.device_id	= PCI_DEVICE_ID_SI_740,
-		.chipset	= SIS_GENERIC,
 		.chipset_name	= "740",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_SI_650,
-		.chipset	= SIS_GENERIC,
 		.chipset_name	= "650",
 	},
 	{
 		.device_id  = PCI_DEVICE_ID_SI_651,
-		.chipset    = SIS_GENERIC,
 		.chipset_name   = "651",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_SI_645,
-		.chipset	= SIS_GENERIC,
 		.chipset_name	= "645",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_SI_646,
-		.chipset	= SIS_GENERIC,
 		.chipset_name	= "646",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_SI_735,
-		.chipset	= SIS_GENERIC,
 		.chipset_name	= "735",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_SI_745,
-		.chipset	= SIS_GENERIC,
 		.chipset_name	= "745",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_SI_730,
-		.chipset	= SIS_GENERIC,
 		.chipset_name	= "730",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_SI_630,
-		.chipset	= SIS_GENERIC,
 		.chipset_name	= "630",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_SI_540,
-		.chipset	= SIS_GENERIC,
 		.chipset_name	= "540",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_SI_620,
-		.chipset	= SIS_GENERIC,
 		.chipset_name	= "620",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_SI_530,
-		.chipset	= SIS_GENERIC,
 		.chipset_name	= "530",
 	},
 	{
 		.device_id	= PCI_DEVICE_ID_SI_550,
-		.chipset	= SIS_GENERIC,
 		.chipset_name	= "550",
 	},
 	{ }, /* dummy final entry, always present */
 };
 
-/* scan table above for supported devices */
-static int __init agp_lookup_host_bridge (struct pci_dev *pdev)
+static int __init agp_sis_probe(struct pci_dev *pdev,
+				const struct pci_device_id *ent)
 {
-	int j=0;
-	struct agp_device_ids *devs;
-	
-	devs = sis_agp_device_ids;
+	struct agp_device_ids *devs = sis_agp_device_ids;
+	struct agp_bridge_data *bridge;
+	u8 cap_ptr;
+	int j;
 
-	while (devs[j].chipset_name != NULL) {
+	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+	if (!cap_ptr)
+		return -ENODEV;
+
+	/* probe for known chipsets */
+	for (j = 0; devs[j].chipset_name; j++) {
 		if (pdev->device == devs[j].device_id) {
-			printk (KERN_INFO PFX "Detected SiS %s chipset\n",
-				devs[j].chipset_name);
-			agp_bridge->type = devs[j].chipset;
-
-			if (devs[j].chipset_setup != NULL)
-				return devs[j].chipset_setup(pdev);
-			else
-				return sis_generic_setup(pdev);
+			printk(KERN_INFO PFX "Detected SiS %s chipset\n",
+					devs[j].chipset_name);
+			goto found;
 		}
-		j++;
 	}
 
-	/* try init anyway, if user requests it */
-	if (agp_try_unsupported) {
-		printk(KERN_WARNING PFX "Trying generic SiS routines"
-		       " for device id: %04x\n", pdev->device);
-		agp_bridge->type = SIS_GENERIC;
-		return sis_generic_setup(pdev);
+	if (!agp_try_unsupported) {
+		printk(KERN_ERR PFX
+		    "Unsupported SiS chipset (device id: %04x),"
+		    " you might want to try agp_try_unsupported=1.\n",
+		    pdev->device);
+		return -ENODEV;
 	}
 
-	printk(KERN_ERR PFX "Unsupported SiS chipset (device id: %04x),"
-		" you might want to try agp_try_unsupported=1.\n", pdev->device);
-	return -ENODEV;
-}
+	printk(KERN_WARNING PFX "Trying generic SiS routines"
+	       " for device id: %04x\n", pdev->device);
 
-static struct agp_driver sis_agp_driver = {
-	.owner = THIS_MODULE,
-};
+found:
+	bridge = agp_alloc_bridge();
+	if (!bridge)
+		return -ENOMEM;
 
-static int __init agp_sis_probe (struct pci_dev *dev, const struct pci_device_id *ent)
-{
-	u8 cap_ptr = 0;
+	bridge->driver = &sis_driver;
+	bridge->dev = pdev;
+	bridge->capndx = cap_ptr;
 
-	cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
-	if (cap_ptr == 0)
-		return -ENODEV;
+	/* Fill in the mode register */
+	pci_read_config_dword(pdev,
+			bridge->capndx+PCI_AGP_STATUS,
+			&bridge->mode);
 
-	/* probe for known chipsets */
-	if (agp_lookup_host_bridge(dev) != -ENODEV) {
-		agp_bridge->dev = dev;
-		agp_bridge->capndx = cap_ptr;
-		/* Fill in the mode register */
-		pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode);
-		sis_agp_driver.dev = dev;
-		agp_register_driver(&sis_agp_driver);
-		return 0;
-	}
-	return -ENODEV;
+	pci_set_drvdata(pdev, bridge);
+	return agp_add_bridge(bridge);
+}
+
+static void __devexit agp_sis_remove(struct pci_dev *pdev)
+{
+	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+
+	agp_remove_bridge(bridge);
+	agp_put_bridge(bridge);
 }
 
 static struct pci_device_id agp_sis_pci_table[] __initdata = {
@@ -264,22 +244,16 @@
 	.name		= "agpgart-sis",
 	.id_table	= agp_sis_pci_table,
 	.probe		= agp_sis_probe,
+	.remove		= agp_sis_remove,
 };
 
 static int __init agp_sis_init(void)
 {
-	int ret_val;
-
-	ret_val = pci_module_init(&agp_sis_pci_driver);
-	if (ret_val)
-		agp_bridge->type = NOT_SUPPORTED;
-
-	return ret_val;
+	return pci_module_init(&agp_sis_pci_driver);
 }
 
 static void __exit agp_sis_cleanup(void)
 {
-	agp_unregister_driver(&sis_agp_driver);
 	pci_unregister_driver(&agp_sis_pci_driver);
 }
 
diff -urN linux-2.5.69-bk6/drivers/char/agp/sworks-agp.c linux-2.5.69-bk7/drivers/char/agp/sworks-agp.c
--- linux-2.5.69-bk6/drivers/char/agp/sworks-agp.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/sworks-agp.c	2003-05-12 04:43:29.000000000 -0700
@@ -35,7 +35,7 @@
 		return -ENOMEM;
 	}
 	SetPageReserved(virt_to_page(page_map->real));
-	CACHE_FLUSH();
+	global_cache_flush();
 	page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), 
 					    PAGE_SIZE);
 	if (page_map->remapped == NULL) {
@@ -44,7 +44,7 @@
 		page_map->real = NULL;
 		return -ENOMEM;
 	}
-	CACHE_FLUSH();
+	global_cache_flush();
 
 	for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
 		page_map->remapped[i] = agp_bridge->scratch_page;
@@ -203,7 +203,7 @@
 	u32 temp2;
 	struct aper_size_info_lvl2 *values;
 
-	values = A_SIZE_LVL2(agp_bridge->aperture_sizes);
+	values = A_SIZE_LVL2(agp_bridge->driver->aperture_sizes);
 	pci_read_config_dword(agp_bridge->dev,serverworks_private.gart_addr_ofs,&temp);
 	pci_write_config_dword(agp_bridge->dev,serverworks_private.gart_addr_ofs,
 					SVWRKS_SIZE_MASK);
@@ -211,7 +211,7 @@
 	pci_write_config_dword(agp_bridge->dev,serverworks_private.gart_addr_ofs,temp);
 	temp2 &= SVWRKS_SIZE_MASK;
 
-	for (i = 0; i < agp_bridge->num_aperture_sizes; i++) {
+	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
 		if (temp2 == values[i].size_value) {
 			agp_bridge->previous_size =
 			    agp_bridge->current_size = (void *) (values + i);
@@ -224,6 +224,37 @@
 	return 0;
 }
 
+/*
+ * This routine could be implemented by taking the addresses
+ * written to the GATT, and flushing them individually.  However
+ * currently it just flushes the whole table.  Which is probably
+ * more efficent, since agp_memory blocks can be a large number of
+ * entries.
+ */
+static void serverworks_tlbflush(agp_memory * temp)
+{
+	unsigned long end;
+
+	OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 0x01);
+	end = jiffies + 3*HZ;
+	while(INREG8(serverworks_private.registers, 
+		     SVWRKS_POSTFLUSH) == 0x01) {
+		if((signed)(end - jiffies) <= 0) {
+			printk(KERN_ERR "Posted write buffer flush took more"
+			       "then 3 seconds\n");
+		}
+	}
+	OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 0x00000001);
+	end = jiffies + 3*HZ;
+	while(INREG32(serverworks_private.registers, 
+		     SVWRKS_DIRFLUSH) == 0x00000001) {
+		if((signed)(end - jiffies) <= 0) {
+			printk(KERN_ERR "TLB flush took more"
+			       "then 3 seconds\n");
+		}
+	}
+}
+
 static int serverworks_configure(void)
 {
 	struct aper_size_info_lvl2 *current_size;
@@ -253,7 +284,7 @@
 	enable_reg |= 0x1; /* Agp Enable bit */
 	pci_write_config_byte(serverworks_private.svrwrks_dev,
 			      SVWRKS_AGP_ENABLE, enable_reg);
-	agp_bridge->tlb_flush(NULL);
+	serverworks_tlbflush(NULL);
 
 	agp_bridge->capndx = pci_find_capability(serverworks_private.svrwrks_dev, PCI_CAP_ID_AGP);
 
@@ -277,43 +308,11 @@
 	iounmap((void *) serverworks_private.registers);
 }
 
-/*
- * This routine could be implemented by taking the addresses
- * written to the GATT, and flushing them individually.  However
- * currently it just flushes the whole table.  Which is probably
- * more efficent, since agp_memory blocks can be a large number of
- * entries.
- */
-
-static void serverworks_tlbflush(agp_memory * temp)
-{
-	unsigned long end;
-
-	OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 0x01);
-	end = jiffies + 3*HZ;
-	while(INREG8(serverworks_private.registers, 
-		     SVWRKS_POSTFLUSH) == 0x01) {
-		if((signed)(end - jiffies) <= 0) {
-			printk(KERN_ERR "Posted write buffer flush took more"
-			       "then 3 seconds\n");
-		}
-	}
-	OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 0x00000001);
-	end = jiffies + 3*HZ;
-	while(INREG32(serverworks_private.registers, 
-		     SVWRKS_DIRFLUSH) == 0x00000001) {
-		if((signed)(end - jiffies) <= 0) {
-			printk(KERN_ERR "TLB flush took more"
-			       "then 3 seconds\n");
-		}
-	}
-}
-
 static unsigned long serverworks_mask_memory(unsigned long addr, int type)
 {
 	/* Only type 0 is supported by the serverworks chipsets */
 
-	return addr | agp_bridge->masks[0].mask;
+	return addr | agp_bridge->driver->masks[0].mask;
 }
 
 static int serverworks_insert_memory(agp_memory * mem,
@@ -336,14 +335,14 @@
 	while (j < (pg_start + mem->page_count)) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = SVRWRKS_GET_GATT(addr);
-		if (!PGE_EMPTY(cur_gatt[GET_GATT_OFF(addr)])) {
+		if (!PGE_EMPTY(agp_bridge, cur_gatt[GET_GATT_OFF(addr)])) {
 			return -EBUSY;
 		}
 		j++;
 	}
 
 	if (mem->is_flushed == FALSE) {
-		CACHE_FLUSH();
+		global_cache_flush();
 		mem->is_flushed = TRUE;
 	}
 
@@ -351,9 +350,9 @@
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = SVRWRKS_GET_GATT(addr);
 		cur_gatt[GET_GATT_OFF(addr)] =
-			agp_bridge->mask_memory(mem->memory[i], mem->type);
+			agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
 	}
-	agp_bridge->tlb_flush(mem);
+	serverworks_tlbflush(mem);
 	return 0;
 }
 
@@ -368,8 +367,8 @@
 		return -EINVAL;
 	}
 
-	CACHE_FLUSH();
-	agp_bridge->tlb_flush(mem);
+	global_cache_flush();
+	serverworks_tlbflush(mem);
 
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
 		addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
@@ -378,7 +377,7 @@
 			(unsigned long) agp_bridge->scratch_page;
 	}
 
-	agp_bridge->tlb_flush(mem);
+	serverworks_tlbflush(mem);
 	return 0;
 }
 
@@ -420,123 +419,103 @@
 	agp_device_command(command, 0);
 }
 
-static int __init serverworks_setup (struct pci_dev *pdev)
+struct agp_bridge_driver sworks_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= serverworks_masks,
+	.aperture_sizes		= serverworks_sizes,
+	.size_type		= LVL2_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= serverworks_configure,
+	.fetch_size		= serverworks_fetch_size,
+	.cleanup		= serverworks_cleanup,
+	.tlb_flush		= serverworks_tlbflush,
+	.mask_memory		= serverworks_mask_memory,
+	.agp_enable		= serverworks_agp_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= serverworks_create_gatt_table,
+	.free_gatt_table	= serverworks_free_gatt_table,
+	.insert_memory		= serverworks_insert_memory,
+	.remove_memory		= serverworks_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
+
+static int __init agp_serverworks_probe(struct pci_dev *pdev,
+					const struct pci_device_id *ent)
 {
-	u32 temp;
-	u32 temp2;
+	struct agp_bridge_data *bridge;
+	struct pci_dev *bridge_dev;
+	u32 temp, temp2;
 
-	serverworks_private.svrwrks_dev = pdev;
+	/* Everything is on func 1 here so we are hardcoding function one */
+	bridge_dev = pci_find_slot((unsigned int)pdev->bus->number,
+			PCI_DEVFN(0, 1));
+	if (!bridge_dev) {
+		printk(KERN_INFO PFX "agpgart: Detected a Serverworks "
+		       "Chipset, but could not find the secondary "
+		       "device.\n");
+		return -ENODEV;
+	}
 
-	agp_bridge->masks = serverworks_masks;
-	agp_bridge->aperture_sizes = (void *) serverworks_sizes;
-	agp_bridge->size_type = LVL2_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 7;
-	agp_bridge->dev_private_data = (void *) &serverworks_private;
-	agp_bridge->needs_scratch_page = TRUE;
-	agp_bridge->configure = serverworks_configure;
-	agp_bridge->fetch_size = serverworks_fetch_size;
-	agp_bridge->cleanup = serverworks_cleanup;
-	agp_bridge->tlb_flush = serverworks_tlbflush;
-	agp_bridge->mask_memory = serverworks_mask_memory;
-	agp_bridge->agp_enable = serverworks_agp_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = serverworks_create_gatt_table;
-	agp_bridge->free_gatt_table = serverworks_free_gatt_table;
-	agp_bridge->insert_memory = serverworks_insert_memory;
-	agp_bridge->remove_memory = serverworks_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
-
-	pci_read_config_dword(agp_bridge->dev,
-			      SVWRKS_APSIZE,
-			      &temp);
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_SERVERWORKS_HE:
+	case PCI_DEVICE_ID_SERVERWORKS_LE:
+	case 0x0007:
+		break;
+	default:
+		if (!agp_try_unsupported)
+			return -ENODEV;
+		break;
+	}
 
+	serverworks_private.svrwrks_dev = bridge_dev;
 	serverworks_private.gart_addr_ofs = 0x10;
-
-	if(temp & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-		pci_read_config_dword(agp_bridge->dev,
-				      SVWRKS_APSIZE + 4,
-				      &temp2);
-		if(temp2 != 0) {
+	
+	pci_read_config_dword(pdev, SVWRKS_APSIZE, &temp);
+	if (temp & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+		pci_read_config_dword(pdev, SVWRKS_APSIZE + 4, &temp2);
+		if (temp2 != 0) {
 			printk("Detected 64 bit aperture address, but top "
 			       "bits are not zero.  Disabling agp\n");
 			return -ENODEV;
 		}
 		serverworks_private.mm_addr_ofs = 0x18;
-	} else {
+	} else
 		serverworks_private.mm_addr_ofs = 0x14;
-	}
 
-	pci_read_config_dword(agp_bridge->dev,
-			      serverworks_private.mm_addr_ofs,
-			      &temp);
-	if(temp & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-		pci_read_config_dword(agp_bridge->dev,
-				      serverworks_private.mm_addr_ofs + 4,
-				      &temp2);
-		if(temp2 != 0) {
+	pci_read_config_dword(pdev, serverworks_private.mm_addr_ofs, &temp);
+	if (temp & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+		pci_read_config_dword(pdev,
+				serverworks_private.mm_addr_ofs + 4, &temp2);
+		if (temp2 != 0) {
 			printk("Detected 64 bit MMIO address, but top "
 			       "bits are not zero.  Disabling agp\n");
 			return -ENODEV;
 		}
 	}
 
-	return 0;
-}
-
-
-static int __init agp_find_supported_device(struct pci_dev *dev)
-{
-	struct pci_dev *bridge_dev;
-
-	/* Everything is on func 1 here so we are hardcoding function one */
-	bridge_dev = pci_find_slot ((unsigned int)dev->bus->number, PCI_DEVFN(0, 1));
-	if(bridge_dev == NULL) {
-		printk(KERN_INFO PFX "agpgart: Detected a Serverworks "
-		       "Chipset, but could not find the secondary "
-		       "device.\n");
-		return -ENODEV;
-	}
-
-	agp_bridge->dev = dev;
-
-	switch (dev->device) {
-	case PCI_DEVICE_ID_SERVERWORKS_HE:
-		agp_bridge->type = SVWRKS_HE;
-		return serverworks_setup(bridge_dev);
+	bridge = agp_alloc_bridge();
+	if (!bridge)
+		return -ENOMEM;
 
-	case PCI_DEVICE_ID_SERVERWORKS_LE:
-	case 0x0007:
-		agp_bridge->type = SVWRKS_LE;
-		return serverworks_setup(bridge_dev);
+	bridge->driver = &sworks_driver;
+	bridge->dev_private_data = &serverworks_private,
+	bridge->dev = pdev;
 
-	default:
-		if(agp_try_unsupported) {
-			agp_bridge->type = SVWRKS_GENERIC;
-			return serverworks_setup(bridge_dev);
-		}
-		break;
-	}
-	return -ENODEV;
+	pci_set_drvdata(pdev, bridge);
+	return agp_add_bridge(bridge);
 }
 
-static struct agp_driver serverworks_agp_driver = {
-	.owner = THIS_MODULE,
-};
-
-static int __init agp_serverworks_probe (struct pci_dev *dev, const struct pci_device_id *ent)
+static void __devexit agp_serverworks_remove(struct pci_dev *pdev)
 {
-	if (agp_find_supported_device(dev) == 0) {
-		serverworks_agp_driver.dev = dev;
-		agp_register_driver(&serverworks_agp_driver);
-		return 0;
-	}
-	return -ENODEV;	
+	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+
+	agp_remove_bridge(bridge);
+	agp_put_bridge(bridge);
 }
 
 static struct pci_device_id agp_serverworks_pci_table[] __initdata = {
@@ -557,22 +536,16 @@
 	.name		= "agpgart-serverworks",
 	.id_table	= agp_serverworks_pci_table,
 	.probe		= agp_serverworks_probe,
+	.remove		= agp_serverworks_remove,
 };
 
 static int __init agp_serverworks_init(void)
 {
-	int ret_val;
-
-	ret_val = pci_module_init(&agp_serverworks_pci_driver);
-	if (ret_val)
-		agp_bridge->type = NOT_SUPPORTED;
-
-	return ret_val;
+	return pci_module_init(&agp_serverworks_pci_driver);
 }
 
 static void __exit agp_serverworks_cleanup(void)
 {
-	agp_unregister_driver(&serverworks_agp_driver);
 	pci_unregister_driver(&agp_serverworks_pci_driver);
 }
 
diff -urN linux-2.5.69-bk6/drivers/char/agp/via-agp.c linux-2.5.69-bk7/drivers/char/agp/via-agp.c
--- linux-2.5.69-bk6/drivers/char/agp/via-agp.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk7/drivers/char/agp/via-agp.c	2003-05-12 04:43:29.000000000 -0700
@@ -18,9 +18,9 @@
 	u8 temp;
 	struct aper_size_info_8 *values;
 
-	values = A_SIZE_8(agp_bridge->aperture_sizes);
+	values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
 	pci_read_config_byte(agp_bridge->dev, VIA_APSIZE, &temp);
-	for (i = 0; i < agp_bridge->num_aperture_sizes; i++) {
+	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
 		if (temp == values[i].size_value) {
 			agp_bridge->previous_size =
 			    agp_bridge->current_size = (void *) (values + i);
@@ -79,7 +79,7 @@
 {
 	/* Memory type is ignored */
 
-	return addr | agp_bridge->masks[0].mask;
+	return addr | agp_bridge->driver->masks[0].mask;
 }
 
 
@@ -107,11 +107,11 @@
 	u16 temp;
 	struct aper_size_info_16 *values;
 
-	values = A_SIZE_16(agp_bridge->aperture_sizes);
+	values = A_SIZE_16(agp_bridge->driver->aperture_sizes);
 	pci_read_config_word(agp_bridge->dev, VIA_AGP3_APSIZE, &temp);
 	temp &= 0xfff;
 
-	for (i = 0; i < agp_bridge->num_aperture_sizes; i++) {
+	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
 		if (temp == values[i].size_value) {
 			agp_bridge->previous_size =
 				agp_bridge->current_size = (void *) (values + i);
@@ -174,99 +174,55 @@
 	{ 2048, 524288, 9, 1<<11}	/* 2GB <- Max supported */
 };
 
+struct agp_bridge_driver via_agp3_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= via_generic_masks,
+	.aperture_sizes		= via_generic_agp3_sizes,
+	.size_type		= U8_APER_SIZE,
+	.num_aperture_sizes	= 10,
+	.configure		= via_configure_agp3,
+	.fetch_size		= via_fetch_size_agp3,
+	.cleanup		= via_cleanup_agp3,
+	.tlb_flush		= via_tlbflush_agp3,
+	.mask_memory		= via_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
 
-static int __init via_generic_agp3_setup (struct pci_dev *pdev)
-{
-	agp_bridge->dev = pdev;
-	agp_bridge->type = VIA_GENERIC;
-	agp_bridge->masks = via_generic_masks;
-	agp_bridge->aperture_sizes = (void *) via_generic_agp3_sizes;
-	agp_bridge->size_type = U16_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 10;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->configure = via_configure_agp3;
-	agp_bridge->fetch_size = via_fetch_size_agp3;
-	agp_bridge->cleanup = via_cleanup_agp3;
-	agp_bridge->tlb_flush = via_tlbflush_agp3;
-	agp_bridge->mask_memory = via_mask_memory;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
-	agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
-	agp_bridge->insert_memory = agp_generic_insert_memory;
-	agp_bridge->remove_memory = agp_generic_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
-	return 0;
-}
-
-
-static int __init via_generic_setup (struct pci_dev *pdev)
-{
-	/* Garg, there are KT400s with KT266 IDs. */
-	if (pdev->device == PCI_DEVICE_ID_VIA_8367_0) {
-
-		/* Is there a KT400 subsystem ? */
-		if (pdev->subsystem_device==PCI_DEVICE_ID_VIA_8377_0) {
-			u8 reg;
-
-			printk (KERN_INFO PFX "Found KT400 in disguise as a KT266.\n");
-
-			/* Check AGP compatibility mode. */
-			pci_read_config_byte(pdev, VIA_AGPSEL, &reg);
-			if ((reg & (1<<1))==0)
-				return via_generic_agp3_setup(pdev);
-
-			/* Its in 2.0 mode, drop through. */
-		}
-	}
-
-	agp_bridge->masks = via_generic_masks;
-	agp_bridge->aperture_sizes = (void *) via_generic_sizes;
-	agp_bridge->size_type = U8_APER_SIZE;
-	agp_bridge->num_aperture_sizes = 7;
-	agp_bridge->dev_private_data = NULL;
-	agp_bridge->needs_scratch_page = FALSE;
-	agp_bridge->configure = via_configure;
-	agp_bridge->fetch_size = via_fetch_size;
-	agp_bridge->cleanup = via_cleanup;
-	agp_bridge->tlb_flush = via_tlbflush;
-	agp_bridge->mask_memory = via_mask_memory;
-	agp_bridge->agp_enable = agp_generic_enable;
-	agp_bridge->cache_flush = global_cache_flush;
-	agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
-	agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
-	agp_bridge->insert_memory = agp_generic_insert_memory;
-	agp_bridge->remove_memory = agp_generic_remove_memory;
-	agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
-	agp_bridge->free_by_type = agp_generic_free_by_type;
-	agp_bridge->agp_alloc_page = agp_generic_alloc_page;
-	agp_bridge->agp_destroy_page = agp_generic_destroy_page;
-	agp_bridge->suspend = agp_generic_suspend;
-	agp_bridge->resume = agp_generic_resume;
-	agp_bridge->cant_use_aperture = 0;
-	return 0;
-}
-
-
-/* The KT400 does magick to put the AGP bridge compliant with the same
- * standards version as the graphics card. */
-static int __init via_kt400_setup(struct pci_dev *pdev)
-{
-	u8 reg;
-	pci_read_config_byte(pdev, VIA_AGPSEL, &reg);
-	/* Check AGP 2.0 compatibility mode. */
-	if ((reg & (1<<1))==0)
-		return via_generic_agp3_setup(pdev);
-	return via_generic_setup(pdev);
-}
-
+struct agp_bridge_driver via_driver = {
+	.owner			= THIS_MODULE,
+	.masks			= via_generic_masks,
+	.aperture_sizes		= via_generic_sizes,
+	.size_type		= U8_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= via_configure,
+	.fetch_size		= via_fetch_size,
+	.cleanup		= via_cleanup,
+	.tlb_flush		= via_tlbflush,
+	.mask_memory		= via_mask_memory,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.suspend		= agp_generic_suspend,
+	.resume			= agp_generic_resume,
+};
 
 static struct agp_device_ids via_agp_device_ids[] __initdata =
 {
@@ -310,7 +266,7 @@
 
 	/* VT8361 */
 	{
-		.device_id	= PCI_DEVICE_ID_VIA_8361,	// 0x3112
+		.device_id	= PCI_DEVICE_ID_VIA_8361,
 		.chipset_name	= "Apollo KLE133",
 	},
 
@@ -353,7 +309,6 @@
 	{
 		.device_id	= PCI_DEVICE_ID_VIA_8377_0,
 		.chipset_name	= "Apollo Pro KT400",
-		.chipset_setup	= via_kt400_setup,
 	},
 
 	/* VT8604 / VT8605 / VT8603 / TwisterT
@@ -402,74 +357,99 @@
 	/* P4M400 */
 	{
 		.device_id	= PCI_DEVICE_ID_VIA_P4M400,
-		.chipset_name	= "PM400",
+		.chipset_name	= "P4M400",
 	},
 
 	{ }, /* dummy final entry, always present */
 };
 
-
-/* scan table above for supported devices */
-static int __init agp_lookup_host_bridge (struct pci_dev *pdev)
+static int __init agp_via_probe(struct pci_dev *pdev,
+				const struct pci_device_id *ent)
 {
-	int j=0;
-	struct agp_device_ids *devs;
-	
-	devs = via_agp_device_ids;
+	struct agp_device_ids *devs = via_agp_device_ids;
+	struct agp_bridge_data *bridge;
+	int j = 0;
+	u8 cap_ptr, reg;
 
-	while (devs[j].chipset_name != NULL) {
-		if (pdev->device == devs[j].device_id) {
-			printk (KERN_INFO PFX "Detected VIA %s chipset\n", devs[j].chipset_name);
-			agp_bridge->type = VIA_GENERIC;
+	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+	if (!cap_ptr)
+		return -ENODEV;
 
-			if (devs[j].chipset_setup != NULL)
-				return devs[j].chipset_setup(pdev);
-			else
-				return via_generic_setup(pdev);
+	/* probe for known chipsets */
+	for (j = 0; devs[j].chipset_name; j++) {
+		if (pdev->device == devs[j].device_id) {
+			printk (KERN_INFO PFX "Detected VIA %s chipset\n",
+					devs[j].chipset_name);
+			goto found;
 		}
-		j++;
 	}
 
-	/* try init anyway, if user requests it */
 	if (agp_try_unsupported) {
-		printk(KERN_WARNING PFX "Trying generic VIA routines"
-		       " for device id: %04x\n", pdev->device);
-		agp_bridge->type = VIA_GENERIC;
-		return via_generic_setup(pdev);
+		printk(KERN_ERR PFX 
+		    "Unsupported VIA chipset (device id: %04x),"
+		    " you might want to try agp_try_unsupported=1.\n",
+		    pdev->device);
+		return -ENODEV;
 	}
 
-	printk(KERN_ERR PFX "Unsupported VIA chipset (device id: %04x),"
-		" you might want to try agp_try_unsupported=1.\n", pdev->device);
-	return -ENODEV;
-}
+	printk(KERN_WARNING PFX "Trying generic VIA routines"
+	       " for device id: %04x\n", pdev->device);
 
-
-static struct agp_driver via_agp_driver = {
-	.owner = THIS_MODULE,
-};
+found:
+	bridge = agp_alloc_bridge();
+	if (!bridge)
+		return -ENOMEM;
+
+	bridge->dev = pdev;
+	bridge->capndx = cap_ptr;
+
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_VIA_8367_0:
+		/*
+		 * Garg, there are KT400s with KT266 IDs.
+		 */
+		/* Is there a KT400 subsystem ? */
+		if (pdev->subsystem_device != PCI_DEVICE_ID_VIA_8377_0)
+			break;
+		
+		printk(KERN_INFO PFX "Found KT400 in disguise as a KT266.\n");
+		/*FALLTHROUGH*/
+	case PCI_DEVICE_ID_VIA_8377_0:
+		/*
+		 * The KT400 does magick to put the AGP bridge compliant
+		 * with the same standards version as the graphics card.
+		 */
+		pci_read_config_byte(pdev, VIA_AGPSEL, &reg);
+		/* Check AGP 2.0 compatibility mode. */
+		if ((reg & (1<<1))==0) {
+			bridge->driver = &via_agp3_driver;
+			break;
+		}
+		/*FALLTHROUGH*/
+	default:
+		bridge->driver = &via_driver;
+		break;
+	}
 
 
-static int __init agp_via_probe (struct pci_dev *dev, const struct pci_device_id *ent)
-{
-	u8 cap_ptr = 0;
+	bridge->dev = pdev;
+	bridge->capndx = cap_ptr;
 
-	cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
-	if (cap_ptr == 0)
-		return -ENODEV;
+	/* Fill in the mode register */
+	pci_read_config_dword(pdev,
+			bridge->capndx+PCI_AGP_STATUS, &bridge->mode);
 
-	/* probe for known chipsets */
-	if (agp_lookup_host_bridge (dev) != -ENODEV) {
-		agp_bridge->dev = dev;
-		agp_bridge->capndx = cap_ptr;
-		/* Fill in the mode register */
-		pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode);
-		via_agp_driver.dev = dev;
-		agp_register_driver(&via_agp_driver);
-		return 0;
-	}
-	return -ENODEV;	
+	pci_set_drvdata(pdev, bridge);
+	return agp_add_bridge(bridge);
 }
 
+static void __devexit agp_via_remove(struct pci_dev *pdev)
+{
+	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+
+	agp_remove_bridge(bridge);
+	agp_put_bridge(bridge);
+}
 
 static struct pci_device_id agp_via_pci_table[] __initdata = {
 	{
@@ -490,28 +470,20 @@
 	.name		= "agpgart-via",
 	.id_table	= agp_via_pci_table,
 	.probe		= agp_via_probe,
+	.remove		= agp_via_remove,
 };
 
 
 static int __init agp_via_init(void)
 {
-	int ret_val;
-
-	ret_val = pci_module_init(&agp_via_pci_driver);
-	if (ret_val)
-		agp_bridge->type = NOT_SUPPORTED;
-
-	return ret_val;
+	return pci_module_init(&agp_via_pci_driver);
 }
 
-
 static void __exit agp_via_cleanup(void)
 {
-	agp_unregister_driver(&via_agp_driver);
 	pci_unregister_driver(&agp_via_pci_driver);
 }
 
-
 module_init(agp_via_init);
 module_exit(agp_via_cleanup);
 
diff -urN linux-2.5.69-bk6/drivers/ide/ide-io.c linux-2.5.69-bk7/drivers/ide/ide-io.c
--- linux-2.5.69-bk6/drivers/ide/ide-io.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk7/drivers/ide/ide-io.c	2003-05-12 04:43:29.000000000 -0700
@@ -850,14 +850,14 @@
 		 * happens anyway when any interrupt comes in, IDE or otherwise
 		 *  -- the kernel masks the IRQ while it is being handled.
 		 */
-		if (hwif->irq != masked_irq)
+		if (masked_irq != IDE_NO_IRQ && 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 (hwif->irq != masked_irq)
+		if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
 			enable_irq(hwif->irq);
 		if (startstop == ide_released)
 			goto queue_next;
diff -urN linux-2.5.69-bk6/drivers/net/Kconfig linux-2.5.69-bk7/drivers/net/Kconfig
--- linux-2.5.69-bk6/drivers/net/Kconfig	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk7/drivers/net/Kconfig	2003-05-12 04:43:29.000000000 -0700
@@ -158,7 +158,7 @@
 
 config NET_SB1000
 	tristate "General Instruments Surfboard 1000"
-	depends on NETDEVICES && ISAPNP
+	depends on NETDEVICES && PNP
 	---help---
 	  This is a driver for the General Instrument (also known as
 	  NextLevel) SURFboard 1000 internal
diff -urN linux-2.5.69-bk6/drivers/net/bmac.c linux-2.5.69-bk7/drivers/net/bmac.c
--- linux-2.5.69-bk6/drivers/net/bmac.c	2003-05-04 16:52:50.000000000 -0700
+++ linux-2.5.69-bk7/drivers/net/bmac.c	2003-05-12 04:43:29.000000000 -0700
@@ -17,6 +17,7 @@
 #include <linux/timer.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
+#include <linux/spinlock.h>
 #include <linux/crc32.h>
 #include <asm/prom.h>
 #include <asm/dbdma.h>
@@ -82,6 +83,7 @@
 	int opened;
 	unsigned short hash_use_count[64];
 	unsigned short hash_table_mask[4];
+	spinlock_t lock;
 	struct net_device *next_bmac;
 };
 
@@ -159,9 +161,9 @@
 static void bmac_init_registers(struct net_device *dev);
 static void bmac_enable_and_reset_chip(struct net_device *dev);
 static int bmac_set_address(struct net_device *dev, void *addr);
-static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs);
-static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs);
-static void bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs);
 static void bmac_set_timeout(struct net_device *dev);
 static void bmac_tx_timeout(unsigned long data);
 static int bmac_proc_info ( char *buffer, char **start, off_t offset, int length);
@@ -485,7 +487,7 @@
 	case PBOOK_SLEEP_NOW:
 		netif_device_detach(dev);
 		/* prolly should wait for dma to finish & turn off the chip */
-		save_flags(flags); cli();
+		spin_lock_irqsave(&bp->lock, flags);
 		if (bp->timeout_active) {
 			del_timer(&bp->tx_timeout);
 			bp->timeout_active = 0;
@@ -494,7 +496,7 @@
 		disable_irq(bp->tx_dma_intr);
 		disable_irq(bp->rx_dma_intr);
 		bp->sleeping = 1;
-		restore_flags(flags);
+		spin_unlock_irqrestore(&bp->lock, flags);
 		if (bp->opened) {
 			volatile struct dbdma_regs *rd = bp->rx_dma;
 			volatile struct dbdma_regs *td = bp->tx_dma;
@@ -539,13 +541,14 @@
 
 static int bmac_set_address(struct net_device *dev, void *addr)
 {
+	struct bmac_data *bp = (struct bmac_data *) dev->priv;
 	unsigned char *p = addr;
 	unsigned short *pWord16;
 	unsigned long flags;
 	int i;
 
 	XXDEBUG(("bmac: enter set_address\n"));
-	save_flags(flags); cli();
+	spin_lock_irqsave(&bp->lock, flags);
 
 	for (i = 0; i < 6; ++i) {
 		dev->dev_addr[i] = p[i];
@@ -556,7 +559,7 @@
 	bmwrite(dev, MADD1, *pWord16++);
 	bmwrite(dev, MADD2, *pWord16);
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&bp->lock, flags);
 	XXDEBUG(("bmac: exit set_address\n"));
 	return 0;
 }
@@ -566,8 +569,7 @@
 	struct bmac_data *bp = (struct bmac_data *) dev->priv;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&bp->lock, flags);
 	if (bp->timeout_active)
 		del_timer(&bp->tx_timeout);
 	bp->tx_timeout.expires = jiffies + TX_TIMEOUT;
@@ -575,7 +577,7 @@
 	bp->tx_timeout.data = (unsigned long) dev;
 	add_timer(&bp->tx_timeout);
 	bp->timeout_active = 1;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&bp->lock, flags);
 }
 
 static void
@@ -703,7 +705,7 @@
 
 static int rxintcount;
 
-static void bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct bmac_data *bp = (struct bmac_data *) dev->priv;
@@ -715,7 +717,7 @@
 	int last;
 	unsigned long flags;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&bp->lock, flags);
 
 	if (++rxintcount < 10) {
 		XXDEBUG(("bmac_rxdma_intr\n"));
@@ -769,18 +771,18 @@
 		bp->rx_empty = i;
 	}
 
-	restore_flags(flags);
-
 	dbdma_continue(rd);
+	spin_unlock_irqrestore(&bp->lock, flags);
 
 	if (rxintcount < 10) {
 		XXDEBUG(("bmac_rxdma_intr done\n"));
 	}
+	return IRQ_HANDLED;
 }
 
 static int txintcount;
 
-static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct bmac_data *bp = (struct bmac_data *) dev->priv;
@@ -788,7 +790,7 @@
 	int stat;
 	unsigned long flags;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&bp->lock, flags);
 
 	if (txintcount++ < 10) {
 		XXDEBUG(("bmac_txdma_intr\n"));
@@ -824,13 +826,14 @@
 			break;
 	}
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&bp->lock, flags);
 
 	if (txintcount < 10) {
 		XXDEBUG(("bmac_txdma_intr done->bmac_start\n"));
 	}
 
 	bmac_start(dev);
+	return IRQ_HANDLED;
 }
 
 static struct net_device_stats *bmac_stats(struct net_device *dev)
@@ -1096,7 +1099,7 @@
 
 static int miscintcount;
 
-static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct bmac_data *bp = (struct bmac_data *)dev->priv;
@@ -1117,6 +1120,7 @@
 	if (status & TxErrorMask) bp->stats.tx_errors++;
 	if (status & TxUnderrun) bp->stats.tx_fifo_errors++;
 	if (status & TxNormalCollExp) bp->stats.collisions++;
+	return IRQ_HANDLED;
 }
 
 /*
@@ -1249,7 +1253,7 @@
 	struct sk_buff *skb;
 	unsigned char *data;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&bp->lock, flags);
 	bmac_enable_and_reset_chip(dev);
 	bmac_init_tx_ring(bp);
 	bmac_init_rx_ring(bp);
@@ -1270,7 +1274,7 @@
 		memcpy(data+6, dev->dev_addr, 6);
 		bmac_transmit_packet(skb, dev);
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&bp->lock, flags);
 }
 
 static int __init bmac_probe(void)
@@ -1336,6 +1340,7 @@
 	bp = (struct bmac_data *) dev->priv;
 	SET_MODULE_OWNER(dev);
 	bp->node = bmac;
+	spin_lock_init(&bp->lock);
 
 	if (!request_OF_resource(bmac, 0, " (bmac)")) {
 		printk(KERN_ERR "BMAC: can't request IO resource !\n");
@@ -1522,7 +1527,7 @@
 	if (bp->sleeping)
 		return;
 		
-	save_flags(flags); cli();
+	spin_lock_irqsave(&bp->lock, flags);
 	while (1) {
 		i = bp->tx_fill + 1;
 		if (i >= N_TX_RING)
@@ -1534,7 +1539,7 @@
 			break;
 		bmac_transmit_packet(skb, dev);
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&bp->lock, flags);
 }
 
 static int
@@ -1558,7 +1563,7 @@
 	int i;
 
 	XXDEBUG(("bmac: tx_timeout called\n"));
-	save_flags(flags); cli();
+	spin_lock_irqsave(&bp->lock, flags);
 	bp->timeout_active = 0;
 
 	/* update various counters */
@@ -1614,7 +1619,7 @@
 	oldConfig = bmread(dev, TXCFG);		
 	bmwrite(dev, TXCFG, oldConfig | TxMACEnable );
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&bp->lock, flags);
 }
 
 #if 0
diff -urN linux-2.5.69-bk6/drivers/net/depca.c linux-2.5.69-bk7/drivers/net/depca.c
--- linux-2.5.69-bk6/drivers/net/depca.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk7/drivers/net/depca.c	2003-05-12 04:43:29.000000000 -0700
@@ -230,6 +230,7 @@
       			   by acme@conectiva.com.br
       0.54    08-Nov-01	  use library crc32 functions
       			   by Matt_Domsch@dell.com
+      0.55    01-Mar-03   Use EISA/sysfs framework <maz@wild-wind.fr.eu.org>
 
     =========================================================================
 */
@@ -263,6 +264,11 @@
 #include <linux/mca.h>
 #endif
 
+#ifdef CONFIG_EISA
+#include <linux/device.h>
+#include <linux/eisa.h>
+#endif
+
 #include "depca.h"
 
 static char version[] __initdata = "depca.c:v0.53 2001/1/12 davies@maniac.ultranet.com\n";
@@ -328,6 +334,25 @@
 	DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown
 } adapter;
 
+#ifdef CONFIG_EISA
+struct eisa_device_id depca_eisa_ids[] = {
+	{ "DEC4220" },
+	{ "" }
+};
+
+static int depca_eisa_probe  (struct device *device);
+static int depca_eisa_remove (struct device *device);
+
+struct eisa_driver depca_eisa_driver = {
+	.id_table = depca_eisa_ids,
+	.driver   = {
+		.name    = "depca",
+		.probe   = depca_eisa_probe,
+		.remove  = __devexit_p (depca_eisa_remove)
+	}
+};
+#endif
+
 /*
 ** Miscellaneous info...
 */
@@ -388,6 +413,8 @@
 	void *rx_buff[NUM_RX_DESC];	/* CPU virt address of sh'd memory buffs  */
 	void *tx_buff[NUM_TX_DESC];	/* CPU virt address of sh'd memory buffs  */
 	void *sh_mem;		/* CPU mapped virt address of device RAM  */
+	u_long mem_start;	/* Bus address of device RAM (before remap) */
+	u_long mem_len;		/* device memory size */
 /* Device address space fields */
 	u_long device_ram_start;	/* Start of RAM in device addr space      */
 /* Offsets used in both address spaces */
@@ -450,10 +477,8 @@
 static void DepcaSignature(char *name, u_long paddr);
 static int DevicePresent(u_long ioaddr);
 static int get_hw_addr(struct net_device *dev);
-static int EISA_signature(char *name, s32 eisa_id);
 static void SetMulticastFilter(struct net_device *dev);
 static void isa_probe(struct net_device *dev, u_long iobase);
-static void eisa_probe(struct net_device *dev, u_long iobase);
 #ifdef CONFIG_MCA
 static void mca_probe(struct net_device *dev, u_long iobase);
 #endif
@@ -503,7 +528,9 @@
 		mca_probe(dev, iobase);
 #endif
 		isa_probe(dev, iobase);
-		eisa_probe(dev, iobase);
+#ifdef CONFIG_EISA
+		eisa_driver_register (&depca_eisa_driver);
+#endif
 
 		if ((tmp == num_depcas) && (iobase != 0) && loading_module) {
 			printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, iobase);
@@ -530,6 +557,7 @@
 	int i, j, offset, netRAM, mem_len, status = 0;
 	s16 nicsr;
 	u_long mem_start = 0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES;
+	int is_eisa = ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS);
 
 	STOP_DEPCA;
 
@@ -555,7 +583,7 @@
 
 	if (mca_slot != -1) {
 		printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, ioaddr, mca_slot);
-	} else if ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS) {	/* EISA slot address */
+	} else if (is_eisa) {	/* EISA slot address */
 		printk("%s: %s at 0x%04lx (EISA slot %d)", dev->name, name, ioaddr, (int) ((ioaddr >> 12) & 0x0f));
 	} else {		/* ISA port address */
 		printk("%s: %s at 0x%04lx", dev->name, name, ioaddr);
@@ -600,9 +628,11 @@
 	}
 
 	/* Define the device private memory */
-	dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL);
-	if (dev->priv == NULL)
-		return -ENOMEM;
+	if (!is_eisa) {
+		dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL);
+		if (dev->priv == NULL)
+			return -ENOMEM;
+	}
 	lp = (struct depca_private *) dev->priv;
 	memset((char *) dev->priv, 0, sizeof(struct depca_private));
 	lp->adapter = adapter;
@@ -610,18 +640,23 @@
 	lp->lock = SPIN_LOCK_UNLOCKED;
 	sprintf(lp->adapter_name, "%s (%s)", name, dev->name);
 	status = -EBUSY;
-	if (!request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name)) {
-		printk(KERN_ERR "depca: I/O resource 0x%x @ 0x%lx busy\n", DEPCA_TOTAL_SIZE, ioaddr);
-		goto out_priv;
-	}
 
 	/* Initialisation Block */
-	lp->sh_mem = ioremap(mem_start, mem_len);
+	if (!request_mem_region (mem_start, mem_len, lp->adapter_name)) {
+		printk(KERN_ERR "depca: cannot request ISA memory, aborting\n");
+		goto out_priv;
+	}
+		
 	status = -EIO;
+	lp->sh_mem = ioremap(mem_start, mem_len);
 	if (lp->sh_mem == NULL) {
 		printk(KERN_ERR "depca: cannot remap ISA memory, aborting\n");
-		goto out_region;
+		release_mem_region (mem_start, mem_len);
+		goto out_priv;
 	}
+
+	lp->mem_start = mem_start;
+	lp->mem_len   = mem_len;
 	lp->device_ram_start = mem_start & LA_MASK;
 
 	offset = 0;
@@ -703,7 +738,7 @@
 		status = -ENXIO;
 		if (!irqnum) {
 			printk(" and failed to detect IRQ line.\n");
-			goto out_region;
+			goto out_priv;
 		} else {
 			for (dev->irq = 0, i = 0; (depca_irq[i]) && (!dev->irq); i++)
 				if (irqnum == depca_irq[i]) {
@@ -714,7 +749,7 @@
 			status = -ENXIO;
 			if (!dev->irq) {
 				printk(" but incorrect IRQ line detected.\n");
-				goto out_region;
+				goto out_priv;
 			}
 		}
 #endif				/* MODULE */
@@ -739,13 +774,16 @@
 	dev->mem_start = 0;
 
 	/* Fill in the generic field of the device structure. */
-	ether_setup(dev);
+	if (!is_eisa)
+		ether_setup(dev);
 	return 0;
-      out_region:
-	release_region(ioaddr, DEPCA_TOTAL_SIZE);
       out_priv:
-	kfree(dev->priv);
-	dev->priv = NULL;
+	if (!is_eisa) {
+		kfree(dev->priv);
+		dev->priv = NULL;
+	} else {
+		unregister_netdev (dev);
+	}
 	return status;
 }
 
@@ -1351,31 +1389,35 @@
 			   ** Get everything allocated and initialized...  (almost just
 			   ** like the ISA and EISA probes)
 			 */
+			if (!request_region (iobase, DEPCA_TOTAL_SIZE, "depca")) {
+				if (autoprobed)
+					printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
+				goto next;
+			}
 			if (DevicePresent(iobase) != 0) {
 				/*
 				   ** If the MCA configuration says the card should be here,
 				   ** it really should be here.
 				 */
 				printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not responding.\n", dev->name, iobase);
+				goto release_next;
 			}
 
-			if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) {
-				if ((dev = alloc_device(dev, iobase)) != NULL) {
-					dev->irq = irq;
-					if (depca_hw_init(dev, iobase, slot) == 0) {
-						/*
-						   ** Adapter initialized correctly:  Name it in
-						   ** /proc/mca.
-						 */
-						mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter");
-						mca_mark_as_used(slot);
-						num_depcas++;
-					}
-					num_eth++;
-				}
-			} else if (autoprobed) {
-				printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
-			}
+			if (!(dev = alloc_device(dev, iobase)))
+				goto release_next;
+
+			num_eth++;
+			dev->irq = irq;
+			if (depca_hw_init(dev, iobase, slot))
+				goto release_next;
+			
+			/*
+			** Adapter initialized correctly:  Name it in
+			** /proc/mca.
+			*/
+			mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter");
+			mca_mark_as_used(slot);
+			num_depcas++;
 
 			/*
 			   ** If this is a probe by a module, return after setting up the
@@ -1385,9 +1427,15 @@
 				return;
 
 			/*
-			   ** Set up to check the next slot and loop.
+			** Set up to check the next slot and loop.
 			 */
 			slot++;
+			continue;
+
+	release_next:
+			release_region (iobase, DEPCA_TOTAL_SIZE);
+	next:
+			slot++;
 		}
 	}
 
@@ -1418,69 +1466,100 @@
 	}
 
 	for (; (i < maxSlots) && (dev != NULL) && ports[i]; i++) {
-		if (check_region(ports[i], DEPCA_TOTAL_SIZE) == 0) {
-			if (DevicePresent(ports[i]) == 0) {
-				if ((dev = alloc_device(dev, ports[i])) != NULL) {
-					if (depca_hw_init(dev, ports[i], -1) == 0) {
-						num_depcas++;
-					}
-					num_eth++;
-				}
-			}
-		} else if (autoprobed) {
-			printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]);
+		if (!request_region (ports[i], DEPCA_TOTAL_SIZE, "depca")) {
+			if (autoprobed)
+				printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]);
+			continue;
 		}
+
+		if (DevicePresent(ports[i])) {
+			release_region (ports[i], DEPCA_TOTAL_SIZE);
+			continue;
+		}
+
+		if (!(dev = alloc_device(dev, ports[i]))) {
+			release_region (ports[i], DEPCA_TOTAL_SIZE);
+			continue;
+		}
+
+		num_eth++;
+
+		if (depca_hw_init(dev, ports[i], -1)) {
+			release_region (ports[i], DEPCA_TOTAL_SIZE);
+			continue;
+		}
+
+		num_depcas++;
 	}
 
 	return;
 }
 
 /*
-** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
-** the motherboard. Upto 15 EISA devices are supported.
+** EISA callbacks from sysfs.
 */
-static void __init eisa_probe(struct net_device *dev, u_long ioaddr)
+
+#ifdef CONFIG_EISA
+static int __init depca_eisa_probe (struct device *device)
 {
-	int i, maxSlots;
+	struct eisa_device *edev;
+	struct net_device *dev;
 	u_long iobase;
-	char name[DEPCA_STRLEN];
+	int status = 0;
 
-	if (!ioaddr && autoprobed)
-		return;		/* Been here before ! */
-	if ((ioaddr < 0x400) && (ioaddr > 0))
-		return;		/* ISA Address */
+	edev = to_eisa_device (device);
+	iobase = edev->base_addr + DEPCA_EISA_IO_PORTS;
 
-	if (ioaddr == 0) {	/* Autoprobing */
-		iobase = EISA_SLOT_INC;	/* Get the first slot address */
-		i = 1;
-		maxSlots = MAX_EISA_SLOTS;
-	} else {		/* Probe a specific location */
-		iobase = ioaddr;
-		i = (ioaddr >> 12);
-		maxSlots = i + 1;
+	if (!request_region (iobase, DEPCA_TOTAL_SIZE, "depca")) {
+		status = -EBUSY;
+		goto out;
+	}
+	
+	if (DevicePresent(iobase)) {
+		status = -ENODEV;
+		goto out_release;
 	}
-	if ((iobase & 0x0fff) == 0)
-		iobase += DEPCA_EISA_IO_PORTS;
 
-	for (; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) {
-		if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) {
-			if (EISA_signature(name, EISA_ID)) {
-				if (DevicePresent(iobase) == 0) {
-					if ((dev = alloc_device(dev, iobase)) != NULL) {
-						if (depca_hw_init(dev, iobase, -1) == 0) {
-							num_depcas++;
-						}
-						num_eth++;
-					}
-				}
-			}
-		} else if (autoprobed) {
-			printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
-		}
+	if (!(dev = init_etherdev (NULL, sizeof (struct depca_private)))) {
+		status = -ENOMEM;
+		goto out_release;
 	}
+		
+	eisa_set_drvdata (edev, dev);
 
-	return;
+	if ((status = depca_hw_init(dev, iobase, -1)))
+		goto out_free;
+
+	num_depcas++;
+	return 0;
+
+ out_free:
+	kfree (dev);
+ out_release:
+	release_region (iobase, DEPCA_TOTAL_SIZE);
+ out:
+	return status;
+}
+
+static int __devexit depca_eisa_remove (struct device *device)
+{
+	struct net_device *dev;
+	struct eisa_device *edev;
+	struct depca_private *lp;
+
+	edev = to_eisa_device (device);
+	dev  = eisa_get_drvdata (edev);
+	lp   = dev->priv;
+
+	unregister_netdev (dev);
+	iounmap (lp->sh_mem);
+	release_mem_region (lp->mem_start, lp->mem_len);
+	release_region (dev->base_addr, DEPCA_TOTAL_SIZE);
+	kfree (dev);
+
+	return 0;
 }
+#endif
 
 /*
 ** Search the entire 'eth' device list for a fixed probe. If a match isn't
@@ -1781,40 +1860,6 @@
 	return status;
 }
 
-/*
-** Look for a particular board name in the EISA configuration space
-*/
-static int __init EISA_signature(char *name, s32 eisa_id)
-{
-	u_int i;
-	const char *signatures[] = DEPCA_SIGNATURE;
-	char ManCode[DEPCA_STRLEN];
-	union {
-		s32 ID;
-		char Id[4];
-	} Eisa;
-	int status = 0;
-
-	*name = '\0';
-	Eisa.ID = inl(eisa_id);
-
-	ManCode[0] = (((Eisa.Id[0] >> 2) & 0x1f) + 0x40);
-	ManCode[1] = (((Eisa.Id[1] & 0xe0) >> 5) + ((Eisa.Id[0] & 0x03) << 3) + 0x40);
-	ManCode[2] = (((Eisa.Id[2] >> 4) & 0x0f) + 0x30);
-	ManCode[3] = ((Eisa.Id[2] & 0x0f) + 0x30);
-	ManCode[4] = (((Eisa.Id[3] >> 4) & 0x0f) + 0x30);
-	ManCode[5] = '\0';
-
-	for (i = 0; (*signatures[i] != '\0') && (*name == '\0'); i++) {
-		if (strstr(ManCode, signatures[i]) != NULL) {
-			strcpy(name, ManCode);
-			status = 1;
-		}
-	}
-
-	return status;
-}
-
 static void depca_dbg_open(struct net_device *dev)
 {
 	struct depca_private *lp = (struct depca_private *) dev->priv;
@@ -2067,6 +2112,7 @@
 	unregister_netdev(&thisDepca);
 	if (lp) {
 		iounmap(lp->sh_mem);
+		release_mem_region (lp->mem_start, lp->mem_len);
 #ifdef CONFIG_MCA
 		if (lp->mca_slot != -1)
 			mca_mark_as_unused(lp->mca_slot);
diff -urN linux-2.5.69-bk6/drivers/net/mace.c linux-2.5.69-bk7/drivers/net/mace.c
--- linux-2.5.69-bk6/drivers/net/mace.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk7/drivers/net/mace.c	2003-05-12 04:43:29.000000000 -0700
@@ -86,9 +86,9 @@
 static void mace_set_multicast(struct net_device *dev);
 static void mace_reset(struct net_device *dev);
 static int mace_set_address(struct net_device *dev, void *addr);
-static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs);
-static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs);
 static void mace_set_timeout(struct net_device *dev);
 static void mace_tx_timeout(unsigned long data);
 static inline void dbdma_reset(volatile struct dbdma_regs *dma);
@@ -622,7 +622,7 @@
 	    printk(KERN_DEBUG "mace: jabbering transceiver\n");
 }
 
-static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
     struct net_device *dev = (struct net_device *) dev_id;
     struct mace_data *mp = (struct mace_data *) dev->priv;
@@ -765,6 +765,7 @@
 	mace_set_timeout(dev);
     }
     spin_unlock_irqrestore(&mp->lock, flags);
+    return IRQ_HANDLED;
 }
 
 static void mace_tx_timeout(unsigned long data)
@@ -833,11 +834,12 @@
     spin_unlock_irqrestore(&mp->lock, flags);
 }
 
-static void mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
+	return IRQ_HANDLED;
 }
 
-static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
     struct net_device *dev = (struct net_device *) dev_id;
     struct mace_data *mp = (struct mace_data *) dev->priv;
@@ -947,6 +949,7 @@
 	mp->rx_fill = i;
     }
     spin_unlock_irqrestore(&mp->lock, flags);
+    return IRQ_HANDLED;
 }
 
 MODULE_AUTHOR("Paul Mackerras");
diff -urN linux-2.5.69-bk6/drivers/net/sb1000.c linux-2.5.69-bk7/drivers/net/sb1000.c
--- linux-2.5.69-bk6/drivers/net/sb1000.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk7/drivers/net/sb1000.c	2003-05-12 04:43:29.000000000 -0700
@@ -49,7 +49,7 @@
 #include <linux/skbuff.h>
 #include <linux/delay.h>	/* for udelay() */
 #include <linux/etherdevice.h>
-#include <linux/isapnp.h>
+#include <linux/pnp.h>
 
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -131,146 +131,122 @@
 static inline int sb1000_rx(struct net_device *dev);
 static inline void sb1000_error_dpc(struct net_device *dev);
 
-static struct isapnp_device_id id_table[] = {
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('G','I','C'), ISAPNP_FUNCTION(0x1000), 0 },
-	{0}
+static const struct pnp_device_id sb1000_pnp_ids[] = {
+	{ "GIC1000", 0 },
+	{ "", 0 }
 };
+MODULE_DEVICE_TABLE(pnp, sb1000_pnp_ids);
 
-MODULE_DEVICE_TABLE(isapnp, id_table);
-
-/* probe for SB1000 using Plug-n-Play mechanism */
-int
-sb1000_probe(struct net_device *dev)
+static void
+sb1000_setup(struct net_device *dev)
 {
+	dev->type		= ARPHRD_ETHER;
+	dev->mtu		= 1500;
+	dev->addr_len		= ETH_ALEN;
+
+	/* New-style flags. */
+	dev->flags		= IFF_POINTOPOINT|IFF_NOARP;
+}
 
+static int
+sb1000_probe_one(struct pnp_dev *pdev, const struct pnp_device_id *id)
+{
+	struct net_device *dev;
 	unsigned short ioaddr[2], irq;
-	struct pnp_dev *idev=NULL;
 	unsigned int serial_number;
+	int error = -ENODEV;
 	
-	while(1)
-	{
-		/*
-		 *	Find the card
-		 */
-		 
-		idev=pnp_find_dev(NULL, ISAPNP_VENDOR('G','I','C'),
-			ISAPNP_FUNCTION(0x1000), idev);
-			
-		/*
-		 *	No card
-		 */
-		 
-		if(idev==NULL || idev->card == NULL)
-			return -ENODEV;
-			
-		/*
-		 *	Bring it online
-		 */
-		 
-		if (pnp_device_attach(idev) < 0)
-			continue;
-		if (pnp_activate_dev(idev) < 0) {
-		      __again:
-			pnp_device_detach(idev);
-			continue;
-		}
-		
-		/*
-		 *	Ports free ?
-		 */
-		 
-		if(!pnp_port_valid(idev, 0) || !pnp_port_valid(idev, 1) || !pnp_irq_valid(idev, 0))
-			goto __again;
+	if (pnp_device_attach(pdev) < 0)
+		return -ENODEV;
+	if (pnp_activate_dev(pdev) < 0)
+		goto out_detach;
+
+	if (!pnp_port_valid(pdev, 0) || !pnp_port_valid(pdev, 1))
+		goto out_disable;
+	if (!pnp_irq_valid(pdev, 0))
+		goto out_disable;
 		
-		serial_number = idev->card->serial;
+	serial_number = pdev->card->serial;
 		
-		ioaddr[0]=pnp_port_start(idev, 0);
-		ioaddr[1]=pnp_port_start(idev, 0);
+	ioaddr[0] = pnp_port_start(pdev, 0);
+	ioaddr[1] = pnp_port_start(pdev, 0);
 		
-		irq = pnp_irq(idev, 0);
+	irq = pnp_irq(pdev, 0);
 
-		/* check I/O base and IRQ */
-		if (dev->base_addr != 0 && dev->base_addr != ioaddr[0])
-			goto __again;
-		if (dev->mem_start != 0 && dev->mem_start != ioaddr[1])
-			goto __again;
-		if (dev->irq != 0 && dev->irq != irq)
-			goto __again;
-			
-		/*
-		 *	Ok set it up.
-		 */
-		if (!request_region(ioaddr[0], 16, dev->name))
-			goto __again;
-		if (!request_region(ioaddr[1], 16, dev->name)) {
-			release_region(ioaddr[0], 16);
-			goto __again;
-		}
+	if (!request_region(ioaddr[0], 16, dev->name))
+		goto out_disable;
+	if (!request_region(ioaddr[1], 16, dev->name))
+		goto out_release_region0;
 		 
-		dev->base_addr = ioaddr[0];
-		/* mem_start holds the second I/O address */
-		dev->mem_start = ioaddr[1];
-		dev->irq = irq;
-
-		if (sb1000_debug > 0)
-			printk(KERN_NOTICE "%s: sb1000 at (%#3.3lx,%#3.3lx), "
-				"S/N %#8.8x, IRQ %d.\n", dev->name, dev->base_addr,
-				dev->mem_start, serial_number, dev->irq);
-
-		dev = init_etherdev(dev, 0);
-		if (!dev) {
-			pnp_device_detach(idev);
-			release_region(ioaddr[1], 16);
-			release_region(ioaddr[0], 16);
-			return -ENOMEM;
-		}
-		SET_MODULE_OWNER(dev);
-
-		/* Make up a SB1000-specific-data structure. */
-		dev->priv = kmalloc(sizeof(struct sb1000_private), GFP_KERNEL);
-		if (dev->priv == NULL)
-			return -ENOMEM;
-		memset(dev->priv, 0, sizeof(struct sb1000_private));
-
-		if (sb1000_debug > 0)
-			printk(KERN_NOTICE "%s", version);
-
-		/* The SB1000-specific entries in the device structure. */
-		dev->open = sb1000_open;
-		dev->do_ioctl = sb1000_dev_ioctl;
-		dev->hard_start_xmit = sb1000_start_xmit;
-		dev->stop = sb1000_close;
-		dev->get_stats = sb1000_stats;
-
-		/* Fill in the generic fields of the device structure. */
-		dev->change_mtu		= NULL;
-		dev->hard_header	= NULL;
-		dev->rebuild_header 	= NULL;
-		dev->set_mac_address 	= NULL;
-		dev->header_cache_update= NULL;
-
-		dev->type		= ARPHRD_ETHER;
-		dev->hard_header_len 	= 0;
-		dev->mtu		= 1500;
-		dev->addr_len		= ETH_ALEN;
-		/* hardware address is 0:0:serial_number */
-		dev->dev_addr[0] = 0;
-		dev->dev_addr[1] = 0;
-		dev->dev_addr[2] = serial_number >> 24 & 0xff;
-		dev->dev_addr[3] = serial_number >> 16 & 0xff;
-		dev->dev_addr[4] = serial_number >>  8 & 0xff;
-		dev->dev_addr[5] = serial_number >>  0 & 0xff;
-		dev->tx_queue_len	= 0;
-	
-		/* New-style flags. */
-		dev->flags		= IFF_POINTOPOINT|IFF_NOARP;
+	dev->base_addr = ioaddr[0];
+	/* mem_start holds the second I/O address */
+	dev->mem_start = ioaddr[1];
+	dev->irq = irq;
 
-		/* Lock resources */
+	if (sb1000_debug > 0)
+		printk(KERN_NOTICE "%s: sb1000 at (%#3.3lx,%#3.3lx), "
+			"S/N %#8.8x, IRQ %d.\n", dev->name, dev->base_addr,
+			dev->mem_start, serial_number, dev->irq);
+
+	dev = alloc_netdev(sizeof(struct sb1000_private), "cm%d", sb1000_setup);
+	if (!dev) {
+		error = -ENOMEM;
+		goto out_release_regions;
+	}
+	SET_MODULE_OWNER(dev);
+
+	if (sb1000_debug > 0)
+		printk(KERN_NOTICE "%s", version);
+
+	/* The SB1000-specific entries in the device structure. */
+	dev->open		= sb1000_open;
+	dev->do_ioctl		= sb1000_dev_ioctl;
+	dev->hard_start_xmit	= sb1000_start_xmit;
+	dev->stop		= sb1000_close;
+	dev->get_stats		= sb1000_stats;
+
+	/* hardware address is 0:0:serial_number */
+	dev->dev_addr[2]	= serial_number >> 24 & 0xff;
+	dev->dev_addr[3]	= serial_number >> 16 & 0xff;
+	dev->dev_addr[4]	= serial_number >>  8 & 0xff;
+	dev->dev_addr[5]	= serial_number >>  0 & 0xff;
+
+	pnp_set_drvdata(pdev, dev);
+
+	error = register_netdev(dev);
+	if (error)
+		goto out_unregister;
+	return 0;
 
-		return 0;
-	}
-}
+ out_unregister:
+	unregister_netdev(dev);
+ out_release_regions:
+	release_region(ioaddr[1], 16);
+ out_release_region0:
+	release_region(ioaddr[0], 16);
+ out_disable:
+	pnp_disable_dev(pdev);
+ out_detach:
+	pnp_device_detach(pdev);
+	return error;
+}
+
+static void
+sb1000_remove_one(struct pnp_dev *pdev)
+{
+	struct net_device *dev = pnp_get_drvdata(pdev);
+
+	unregister_netdev(dev);
+	release_region(dev->base_addr, 16);
+	release_region(dev->mem_start, 16);
+}
+
+static struct pnp_driver sb1000_driver = {
+	.name		= "sb1000",
+	.id_table	= sb1000_pnp_ids,
+	.probe		= sb1000_probe_one,
+	.remove		= sb1000_remove_one,
+};
 
 
 /*
@@ -1207,60 +1183,21 @@
 	return 0;
 }
 
-#ifdef MODULE
 MODULE_AUTHOR("Franco Venturi <fventuri@mediaone.net>");
 MODULE_DESCRIPTION("General Instruments SB1000 driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(io, "1-2i");
-MODULE_PARM(irq, "i");
-MODULE_PARM_DESC(io, "SB1000 I/O base addresses");
-MODULE_PARM_DESC(irq, "SB1000 IRQ number");
-
-static struct net_device dev_sb1000;
-static int io[2];
-static int irq;
-
-int
-init_module(void)
+static int __init
+sb1000_init(void)
 {
-	int i;
-	for (i = 0; i < 100; i++) {
-		sprintf(dev_sb1000.name, "cm%d", i);
-		if (dev_get(dev_sb1000.name) == 0) break;
-	}
-	if (i == 100) {
-		printk(KERN_ERR "sb1000: can't register any device cm<n>\n");
-		return -ENFILE;
-	}
-	dev_sb1000.init = sb1000_probe;
-	dev_sb1000.base_addr = io[0];
-	/* mem_start holds the second I/O address */
-	dev_sb1000.mem_start = io[1];
-	dev_sb1000.irq = irq;
-	if (register_netdev(&dev_sb1000) != 0) {
-		printk(KERN_ERR "sb1000: failed to register device (io: %03x,%03x   "
-			"irq: %d)\n", io[0], io[1], irq);
-		return -EIO;
-	}
-	return 0;
+	return pnp_register_driver(&sb1000_driver);
 }
 
-void cleanup_module(void)
+static void __exit
+sb1000_exit(void)
 {
-	unregister_netdev(&dev_sb1000);
-	release_region(dev_sb1000.base_addr, 16);
-	release_region(dev_sb1000.mem_start, 16);
-	kfree(dev_sb1000.priv);
-	dev_sb1000.priv = NULL;
+	pnp_unregister_driver(&sb1000_driver);
 }
-#endif /* MODULE */
-
-/*
- * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -DMODULE -Wall -Wstrict-prototypes -O -m486 -c sb1000.c"
- *  version-control: t
- *  tab-width: 4
- *  c-basic-offset: 4
- * End:
- */
+
+module_init(sb1000_init);
+module_exit(sb1000_exit);
diff -urN linux-2.5.69-bk6/drivers/net/setup.c linux-2.5.69-bk7/drivers/net/setup.c
--- linux-2.5.69-bk6/drivers/net/setup.c	2003-05-12 04:43:26.000000000 -0700
+++ linux-2.5.69-bk7/drivers/net/setup.c	2003-05-12 04:43:29.000000000 -0700
@@ -21,14 +21,6 @@
 
 extern int madgemc_probe(void);
 
-/* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is string of 9 zeros. */
-#define __PAD6 "\0\0\0\0\0\0\0\0\0"
-#define __PAD5 __PAD6 "\0"
-#define __PAD4 __PAD5 "\0"
-#define __PAD3 __PAD4 "\0"
-#define __PAD2 __PAD3 "\0"
-
-
 /*
  *	Devices in this list must do new style probing. That is they must
  *	allocate their own device objects and do their own bus scans.
@@ -84,7 +76,7 @@
  *	into them.
  */
  
-static void __init network_probe(void)
+void __init net_device_init(void)
 {
 	struct net_probe *p = pci_probes;
 
@@ -94,28 +86,3 @@
 		p++;
 	}
 }
-
-static void __init special_device_init(void)
-{
-#ifdef CONFIG_NET_SB1000
-	extern int sb1000_probe(struct net_device *dev);
-
-	static struct net_device sb1000_dev = {
-		.name = "cm0" __PAD3,
-		.init = sb1000_probe,
-	};
-	register_netdev(&sb1000_dev);
-#endif
-}
-
-/*
- *	Initialise network devices
- */
- 
-void __init net_device_init(void)
-{
-	/* Devices supporting the new^H^H^Hold probing API */
-	network_probe();
-	/* Special devices */
-	special_device_init();
-}
diff -urN linux-2.5.69-bk6/drivers/net/tulip/tulip_core.c linux-2.5.69-bk7/drivers/net/tulip/tulip_core.c
--- linux-2.5.69-bk6/drivers/net/tulip/tulip_core.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk7/drivers/net/tulip/tulip_core.c	2003-05-12 04:43:29.000000000 -0700
@@ -223,6 +223,7 @@
 	{ 0x1626, 0x8410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x1737, 0xAB09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ 	{ 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },	/* ALi 1563 integrated ethernet */
 	{ } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, tulip_pci_tbl);
@@ -1325,12 +1326,14 @@
 		csr0 &= ~0xfff10000; /* zero reserved bits 31:20, 16 */
 
 	/* DM9102A has troubles with MRM & clear reserved bits 24:22, 20, 16, 7:1 */
-	if (pdev->vendor == 0x1282 && pdev->device == 0x9102)
+	if ((pdev->vendor == 0x1282 && pdev->device == 0x9102)
+		|| (pdev->vendor == 0x10b9 && pdev->device == 0x5261))
 		csr0 &= ~0x01f100ff;
 
 #if defined(__sparc__)
         /* DM9102A needs 32-dword alignment/burst length on sparc - chip bug? */
-        if (pdev->vendor == 0x1282 && pdev->device == 0x9102)
+	if ((pdev->vendor == 0x1282 && pdev->device == 0x9102)
+		|| (pdev->vendor == 0x10b9 && pdev->device == 0x5261))
                 csr0 = (csr0 & ~0xff00) | 0xe000;
 #endif
 
diff -urN linux-2.5.69-bk6/drivers/net/wireless/netwave_cs.c linux-2.5.69-bk7/drivers/net/wireless/netwave_cs.c
--- linux-2.5.69-bk6/drivers/net/wireless/netwave_cs.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk7/drivers/net/wireless/netwave_cs.c	2003-05-12 04:43:29.000000000 -0700
@@ -227,7 +227,7 @@
 static int netwave_rx( struct net_device *dev);
 
 /* Interrupt routines */
-static void netwave_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t netwave_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void netwave_watchdog(struct net_device *);
 
 /* Statistics */
@@ -1456,7 +1456,7 @@
  *	     ready to transmit another packet.
  *	  3. A command has completed execution.
  */
-static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) {
+static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) {
     ioaddr_t iobase;
     u_char *ramBase;
     struct net_device *dev = (struct net_device *)dev_id;
@@ -1465,7 +1465,7 @@
     int i;
     
     if (!netif_device_present(dev))
-	return;
+	return IRQ_NONE;
     
     iobase = dev->base_addr;
     ramBase = priv->ramBase;
@@ -1476,7 +1476,7 @@
 		
 	wait_WOC(iobase);	
 	if (!(inb(iobase+NETWAVE_REG_CCSR) & 0x02))
-	    break; /* None of the interrupt sources asserted */
+	    break; /* None of the interrupt sources asserted (normal exit) */
 	
         status = inb(iobase + NETWAVE_REG_ASR);
 		
@@ -1569,6 +1569,8 @@
 	   }
 	   */
     }
+    /* Handled if we looped at least one time - Jean II */
+    return IRQ_RETVAL(i);
 } /* netwave_interrupt */
 
 /*
diff -urN linux-2.5.69-bk6/drivers/net/wireless/wavelan.c linux-2.5.69-bk7/drivers/net/wireless/wavelan.c
--- linux-2.5.69-bk6/drivers/net/wireless/wavelan.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk7/drivers/net/wireless/wavelan.c	2003-05-12 04:43:29.000000000 -0700
@@ -1717,31 +1717,28 @@
 	return (i);
 }
 
-#ifdef WIRELESS_SPY
+#ifdef IW_WIRELESS_SPY
 /*------------------------------------------------------------------*/
 /*
  * Gather wireless spy statistics:  for each packet, compare the source
  * address with our list, and if they match, get the statistics.
  * Sorry, but this function really needs the wireless extensions.
  */
-static inline void wl_spy_gather(device * dev, u8 * mac,	/* MAC address */
-				 u8 * stats)
-{				/* Statistics to gather */
-	net_local *lp = (net_local *) dev->priv;
-	int i;
+static inline void wl_spy_gather(device * dev,
+				 u8 *	mac,	/* MAC address */
+				 u8 *	stats)	/* Statistics to gather */
+{
+	struct iw_quality wstats;
 
-	/* Check all addresses. */
-	for (i = 0; i < lp->spy_number; i++)
-		/* If match */
-		if (!memcmp(mac, lp->spy_address[i], WAVELAN_ADDR_SIZE)) {
-			/* Update statistics */
-			lp->spy_stat[i].qual = stats[2] & MMR_SGNL_QUAL;
-			lp->spy_stat[i].level = stats[0] & MMR_SIGNAL_LVL;
-			lp->spy_stat[i].noise = stats[1] & MMR_SILENCE_LVL;
-			lp->spy_stat[i].updated = 0x7;
-		}
+	wstats.qual = stats[2] & MMR_SGNL_QUAL;
+	wstats.level = stats[0] & MMR_SIGNAL_LVL;
+	wstats.noise = stats[1] & MMR_SILENCE_LVL;
+	wstats.updated = 0x7;
+
+	/* Update spy records */
+	wireless_spy_update(dev, mac, &wstats);
 }
-#endif				/* WIRELESS_SPY */
+#endif /* IW_WIRELESS_SPY */
 
 #ifdef HISTOGRAM
 /*------------------------------------------------------------------*/
@@ -1767,7 +1764,7 @@
 	/* Increment interval counter. */
 	(lp->his_sum[i])++;
 }
-#endif				/* HISTOGRAM */
+#endif /* HISTOGRAM */
 
 /*------------------------------------------------------------------*/
 /*
@@ -2203,93 +2200,6 @@
 	return ret;
 }
 
-#ifdef WIRELESS_SPY
-/*------------------------------------------------------------------*/
-/*
- * Wireless Handler : set spy list
- */
-static int wavelan_set_spy(struct net_device *dev,
-			   struct iw_request_info *info,
-			   union iwreq_data *wrqu,
-			   char *extra)
-{
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
-	struct sockaddr *address = (struct sockaddr *) extra;
-	int i;
-	int ret = 0;
-
-	/* Disable spy while we copy the addresses.
-	 * As we don't disable interrupts, we need to do this */
-	lp->spy_number = 0;
-
-	/* Are there are addresses to copy? */
-	if (wrqu->data.length > 0) {
-		/* Copy addresses to the lp structure. */
-		for (i = 0; i < wrqu->data.length; i++) {
-			memcpy(lp->spy_address[i], address[i].sa_data,
-			       WAVELAN_ADDR_SIZE);
-		}
-
-		/* Reset structure. */
-		memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);
-
-#ifdef DEBUG_IOCTL_INFO
-		printk(KERN_DEBUG
-		       "SetSpy:  set of new addresses is: \n");
-		for (i = 0; i < wrqu->data.length; i++)
-			printk(KERN_DEBUG
-			       "%02X:%02X:%02X:%02X:%02X:%02X \n",
-			       lp->spy_address[i][0],
-			       lp->spy_address[i][1],
-			       lp->spy_address[i][2],
-			       lp->spy_address[i][3],
-			       lp->spy_address[i][4],
-			       lp->spy_address[i][5]);
-#endif			/* DEBUG_IOCTL_INFO */
-	}
-
-	/* Now we can set the number of addresses */
-	lp->spy_number = wrqu->data.length;
-
-	return ret;
-}
-
-/*------------------------------------------------------------------*/
-/*
- * Wireless Handler : get spy list
- */
-static int wavelan_get_spy(struct net_device *dev,
-			   struct iw_request_info *info,
-			   union iwreq_data *wrqu,
-			   char *extra)
-{
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
-	struct sockaddr *address = (struct sockaddr *) extra;
-	int i;
-
-	/* Set the number of addresses */
-	wrqu->data.length = lp->spy_number;
-
-	/* Copy addresses from the lp structure. */
-	for (i = 0; i < lp->spy_number; i++) {
-		memcpy(address[i].sa_data,
-		       lp->spy_address[i],
-		       WAVELAN_ADDR_SIZE);
-		address[i].sa_family = AF_UNIX;
-	}
-	/* Copy stats to the user buffer (just after). */
-	if(lp->spy_number > 0)
-		memcpy(extra  + (sizeof(struct sockaddr) * lp->spy_number),
-		       lp->spy_stat, sizeof(iw_qual) * lp->spy_number);
-
-	/* Reset updated flags. */
-	for (i = 0; i < lp->spy_number; i++)
-		lp->spy_stat[i].updated = 0x0;
-
-	return(0);
-}
-#endif			/* WIRELESS_SPY */
-
 /*------------------------------------------------------------------*/
 /*
  * Wireless Private Handler : set quality threshold
@@ -2439,15 +2349,10 @@
 	NULL,				/* SIOCGIWPRIV */
 	NULL,				/* SIOCSIWSTATS */
 	NULL,				/* SIOCGIWSTATS */
-#ifdef WIRELESS_SPY
-	wavelan_set_spy,		/* SIOCSIWSPY */
-	wavelan_get_spy,		/* SIOCGIWSPY */
-#else	/* WIRELESS_SPY */
-	NULL,				/* SIOCSIWSPY */
-	NULL,				/* SIOCGIWSPY */
-#endif	/* WIRELESS_SPY */
-	NULL,				/* -- hole -- */
-	NULL,				/* -- hole -- */
+	iw_handler_set_spy,		/* SIOCSIWSPY */
+	iw_handler_get_spy,		/* SIOCGIWSPY */
+	iw_handler_set_thrspy,		/* SIOCSIWTHRSPY */
+	iw_handler_get_thrspy,		/* SIOCGIWTHRSPY */
 	NULL,				/* SIOCSIWAP */
 	NULL,				/* SIOCGIWAP */
 	NULL,				/* -- hole -- */
@@ -2501,6 +2406,8 @@
 	.standard	= (iw_handler *) wavelan_handler,
 	.private	= (iw_handler *) wavelan_private_handler,
 	.private_args	= (struct iw_priv_args *) wavelan_private_args,
+	.spy_offset	= ((void *) (&((net_local *) NULL)->spy_data) -
+			   (void *) NULL),
 };
 
 /*------------------------------------------------------------------*/
@@ -2618,22 +2525,23 @@
 #endif				/* DEBUG_RX_INFO */
 
 	/* Statistics-gathering and associated stuff.
-	 * It seem a bit messy with all the define, but it's really simple... */
-#if defined(WIRELESS_SPY) || defined(HISTOGRAM)
+	 * It seem a bit messy with all the define, but it's really
+	 * simple... */
 	if (
-#ifdef WIRELESS_SPY
-		   (lp->spy_number > 0) ||
-#endif				/* WIRELESS_SPY */
+#ifdef IW_WIRELESS_SPY		/* defined in iw_handler.h */
+		   (lp->spy_data.spy_number > 0) ||
+#endif /* IW_WIRELESS_SPY */
 #ifdef HISTOGRAM
 		   (lp->his_number > 0) ||
-#endif				/* HISTOGRAM */
+#endif /* HISTOGRAM */
 		   0) {
 		u8 stats[3];	/* signal level, noise level, signal quality */
 
-		/* Read signal level, silence level and signal quality bytes. */
-		/* Note: in the PCMCIA hardware, these are part of the frame.  It seems
-		 * that for the ISA hardware, it's nowhere to be found in the frame,
-		 * so I'm obliged to do this (it has a side effect on /proc/net/wireless).
+		/* Read signal level, silence level and signal quality bytes */
+		/* Note: in the PCMCIA hardware, these are part of the frame.
+		 * It seems that for the ISA hardware, it's nowhere to be
+		 * found in the frame, so I'm obliged to do this (it has a
+		 * side effect on /proc/net/wireless).
 		 * Any ideas?
 		 */
 		mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
@@ -2648,15 +2556,14 @@
 #endif
 
 		/* Spying stuff */
-#ifdef WIRELESS_SPY
+#ifdef IW_WIRELESS_SPY
 		wl_spy_gather(dev, skb->mac.raw + WAVELAN_ADDR_SIZE,
 			      stats);
-#endif				/* WIRELESS_SPY */
+#endif /* IW_WIRELESS_SPY */
 #ifdef HISTOGRAM
 		wl_his_gather(dev, stats);
-#endif				/* HISTOGRAM */
+#endif /* HISTOGRAM */
 	}
-#endif				/* defined(WIRELESS_SPY) || defined(HISTOGRAM) */
 
 	/*
 	 * Hand the packet to the network module.
@@ -2884,10 +2791,6 @@
 	       length);
 #endif
 
-	/* Do we need some padding? */
-	if (clen < ETH_ZLEN)
-		clen = ETH_ZLEN;
-
 	spin_lock_irqsave(&lp->spinlock, flags);
 
 	/* Check nothing bad has happened */
@@ -3008,12 +2911,6 @@
 	       (unsigned) skb);
 #endif
 
-	if (skb->len < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
-			return 0;
-	}
-
 	/*
 	 * Block a timer-based transmit from overlapping.
 	 * In other words, prevent reentering this routine.
@@ -3036,6 +2933,17 @@
 		printk(KERN_INFO "skb has next\n");
 #endif
 
+	/* Do we need some padding? */
+	/* Note : on wireless the propagation time is in the order of 1us,
+	 * and we don't have the Ethernet specific requirement of beeing
+	 * able to detect collisions, therefore in theory we don't really
+	 * need to pad. Jean II */
+	if (skb->len < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+	}
+
 	/* Write packet on the card */
 	if(wv_packet_write(dev, skb->data, skb->len))
 		return 1;	/* We failed */
diff -urN linux-2.5.69-bk6/drivers/net/wireless/wavelan.p.h linux-2.5.69-bk7/drivers/net/wireless/wavelan.p.h
--- linux-2.5.69-bk6/drivers/net/wireless/wavelan.p.h	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk7/drivers/net/wireless/wavelan.p.h	2003-05-12 04:43:29.000000000 -0700
@@ -509,13 +509,9 @@
 
 #ifdef WIRELESS_EXT
   iw_stats	wstats;		/* Wireless-specific statistics */
-#endif
 
-#ifdef WIRELESS_SPY
-  int		spy_number;			/* number of addresses to spy */
-  mac_addr	spy_address[IW_MAX_SPY];	/* the addresses to spy */
-  iw_qual	spy_stat[IW_MAX_SPY];		/* statistics gathered */
-#endif	/* WIRELESS_SPY */
+  struct iw_spy_data	spy_data;
+#endif
 
 #ifdef HISTOGRAM
   int		his_number;		/* number of intervals */
diff -urN linux-2.5.69-bk6/drivers/net/wireless/wavelan_cs.c linux-2.5.69-bk7/drivers/net/wireless/wavelan_cs.c
--- linux-2.5.69-bk6/drivers/net/wireless/wavelan_cs.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk7/drivers/net/wireless/wavelan_cs.c	2003-05-12 04:43:29.000000000 -0700
@@ -1757,10 +1757,8 @@
   u_short	table[10];	/* Authorized frequency table */
   long		freq = 0L;	/* offset to 2.4 GHz in .5 MHz + 12 MHz */
   int		i;		/* index in the table */
-#if WIRELESS_EXT > 7
   const int	BAND_NUM = 10;	/* Number of bands */
   int		c = 0;		/* Channel number */
-#endif /* WIRELESS_EXT */
 
   /* Read the frequency table */
   fee_read(base, 0x71 /* frequency table */,
@@ -1772,13 +1770,11 @@
     /* Look in the table if the frequency is allowed */
     if(table[9 - (freq / 16)] & (1 << (freq % 16)))
       {
-#if WIRELESS_EXT > 7
 	/* Compute approximate channel number */
 	while((((channel_bands[c] >> 1) - 24) < freq) &&
 	      (c < BAND_NUM))
 	  c++;
 	list[i].i = c;	/* Set the list index */
-#endif /* WIRELESS_EXT */
 
 	/* put in the list */
 	list[i].m = (((freq + 24) * 5) + 24000L) * 10000;
@@ -1792,7 +1788,7 @@
   return(i);
 }
 
-#ifdef WIRELESS_SPY
+#ifdef IW_WIRELESS_SPY
 /*------------------------------------------------------------------*/
 /*
  * Gather wireless spy statistics : for each packet, compare the source
@@ -1804,22 +1800,17 @@
 	      u_char *	mac,		/* MAC address */
 	      u_char *	stats)		/* Statistics to gather */
 {
-  net_local *	lp = (net_local *) dev->priv;
-  int		i;
+  struct iw_quality wstats;
 
-  /* Look all addresses */
-  for(i = 0; i < lp->spy_number; i++)
-    /* If match */
-    if(!memcmp(mac, lp->spy_address[i], WAVELAN_ADDR_SIZE))
-      {
-	/* Update statistics */
-	lp->spy_stat[i].qual = stats[2] & MMR_SGNL_QUAL;
-	lp->spy_stat[i].level = stats[0] & MMR_SIGNAL_LVL;
-	lp->spy_stat[i].noise = stats[1] & MMR_SILENCE_LVL;
-	lp->spy_stat[i].updated = 0x7;
-      }
+  wstats.qual = stats[2] & MMR_SGNL_QUAL;
+  wstats.level = stats[0] & MMR_SIGNAL_LVL;
+  wstats.noise = stats[1] & MMR_SILENCE_LVL;
+  wstats.updated = 0x7;
+
+  /* Update spy records */
+  wireless_spy_update(dev, mac, &wstats);
 }
-#endif	/* WIRELESS_SPY */
+#endif	/* IW_WIRELESS_SPY */
 
 #ifdef HISTOGRAM
 /*------------------------------------------------------------------*/
@@ -1904,17 +1895,10 @@
 	spin_lock_irqsave(&lp->spinlock, flags);
 	
 	/* Set NWID in WaveLAN. */
-#if WIRELESS_EXT > 8
 	if (!wrqu->nwid.disabled) {
 		/* Set NWID in psa */
 		psa.psa_nwid[0] = (wrqu->nwid.value & 0xFF00) >> 8;
 		psa.psa_nwid[1] = wrqu->nwid.value & 0xFF;
-#else	/* WIRELESS_EXT > 8 */
-	if(wrq->u.nwid.on) {
-		/* Set NWID in psa */
-		psa.psa_nwid[0] = (wrq->u.nwid.nwid & 0xFF00) >> 8;
-		psa.psa_nwid[1] = wrq->u.nwid.nwid & 0xFF;
-#endif	/* WIRELESS_EXT > 8 */
 		psa.psa_nwid_select = 0x01;
 		psa_write(dev,
 			  (char *) psa.psa_nwid - (char *) &psa,
@@ -1971,14 +1955,9 @@
 	psa_read(dev,
 		 (char *) psa.psa_nwid - (char *) &psa,
 		 (unsigned char *) psa.psa_nwid, 3);
-#if WIRELESS_EXT > 8
 	wrqu->nwid.value = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
 	wrqu->nwid.disabled = !(psa.psa_nwid_select);
 	wrqu->nwid.fixed = 1;	/* Superfluous */
-#else	/* WIRELESS_EXT > 8 */
-	wrq->u.nwid.nwid = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
-	wrq->u.nwid.on = psa.psa_nwid_select;
-#endif	/* WIRELESS_EXT > 8 */
 
 	/* Enable interrupts and restore flags. */
 	spin_unlock_irqrestore(&lp->spinlock, flags);
@@ -2081,13 +2060,9 @@
 	spin_lock_irqsave(&lp->spinlock, flags);
 	
 	/* Set the level threshold. */
-#if WIRELESS_EXT > 7
 	/* We should complain loudly if wrqu->sens.fixed = 0, because we
 	 * can't set auto mode... */
 	psa.psa_thr_pre_set = wrqu->sens.value & 0x3F;
-#else	/* WIRELESS_EXT > 7 */
-	psa.psa_thr_pre_set = wrq->u.sensitivity & 0x3F;
-#endif	/* WIRELESS_EXT > 7 */
 	psa_write(dev,
 		  (char *) &psa.psa_thr_pre_set - (char *) &psa,
 		  (unsigned char *) &psa.psa_thr_pre_set, 1);
@@ -2123,12 +2098,8 @@
 	psa_read(dev,
 		 (char *) &psa.psa_thr_pre_set - (char *) &psa,
 		 (unsigned char *) &psa.psa_thr_pre_set, 1);
-#if WIRELESS_EXT > 7
 	wrqu->sens.value = psa.psa_thr_pre_set & 0x3F;
 	wrqu->sens.fixed = 1;
-#else	/* WIRELESS_EXT > 7 */
-	wrq->u.sensitivity = psa.psa_thr_pre_set & 0x3F;
-#endif	/* WIRELESS_EXT > 7 */
 
 	/* Enable interrupts and restore flags. */
 	spin_unlock_irqrestore(&lp->spinlock, flags);
@@ -2136,7 +2107,6 @@
 	return ret;
 }
 
-#if WIRELESS_EXT > 8
 /*------------------------------------------------------------------*/
 /*
  * Wireless Handler : set encryption key
@@ -2253,10 +2223,8 @@
 
 	return ret;
 }
-#endif	/* WIRELESS_EXT > 8 */
 
 #ifdef WAVELAN_ROAMING_EXT
-#if WIRELESS_EXT > 5
 /*------------------------------------------------------------------*/
 /*
  * Wireless Handler : set ESSID (domain)
@@ -2367,10 +2335,8 @@
 
 	return -EOPNOTSUPP;
 }
-#endif	/* WIRELESS_EXT > 5 */
 #endif	/* WAVELAN_ROAMING_EXT */
 
-#if WIRELESS_EXT > 8
 #ifdef WAVELAN_ROAMING
 /*------------------------------------------------------------------*/
 /*
@@ -2429,7 +2395,6 @@
 	return 0;
 }
 #endif	/* WAVELAN_ROAMING */
-#endif /* WIRELESS_EXT > 8 */
 
 /*------------------------------------------------------------------*/
 /*
@@ -2452,11 +2417,9 @@
 	/* Set all the info we don't care or don't know about to zero */
 	memset(range, 0, sizeof(struct iw_range));
 
-#if WIRELESS_EXT > 10
 	/* Set the Wireless Extension versions */
 	range->we_version_compiled = WIRELESS_EXT;
 	range->we_version_source = 9;
-#endif /* WIRELESS_EXT > 10 */
 
 	/* Set information in the range struct.  */
 	range->throughput = 1.4 * 1000 * 1000;	/* don't argue on this ! */
@@ -2467,17 +2430,13 @@
 	range->max_qual.qual = MMR_SGNL_QUAL;
 	range->max_qual.level = MMR_SIGNAL_LVL;
 	range->max_qual.noise = MMR_SILENCE_LVL;
-#if WIRELESS_EXT > 11
 	range->avg_qual.qual = MMR_SGNL_QUAL; /* Always max */
 	/* Need to get better values for those two */
 	range->avg_qual.level = 30;
 	range->avg_qual.noise = 8;
-#endif /* WIRELESS_EXT > 11 */
 
-#if WIRELESS_EXT > 7
 	range->num_bitrates = 1;
 	range->bitrate[0] = 2000000;	/* 2 Mb/s */
-#endif /* WIRELESS_EXT > 7 */
 
 	/* Disable interrupts and save flags. */
 	spin_lock_irqsave(&lp->spinlock, flags);
@@ -2491,7 +2450,6 @@
 	} else
 		range->num_channels = range->num_frequency = 0;
 
-#if WIRELESS_EXT > 8
 	/* Encryption supported ? */
 	if (mmc_encr(base)) {
 		range->encoding_size[0] = 8;	/* DES = 64 bits key */
@@ -2501,7 +2459,6 @@
 		range->num_encoding_sizes = 0;
 		range->max_encoding_tokens = 0;
 	}
-#endif /* WIRELESS_EXT > 8 */
 
 	/* Enable interrupts and restore flags. */
 	spin_unlock_irqrestore(&lp->spinlock, flags);
@@ -2509,93 +2466,6 @@
 	return ret;
 }
 
-#ifdef WIRELESS_SPY
-/*------------------------------------------------------------------*/
-/*
- * Wireless Handler : set spy list
- */
-static int wavelan_set_spy(struct net_device *dev,
-			   struct iw_request_info *info,
-			   union iwreq_data *wrqu,
-			   char *extra)
-{
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
-	struct sockaddr *address = (struct sockaddr *) extra;
-	int i;
-	int ret = 0;
-
-	/* Disable spy while we copy the addresses.
-	 * As we don't disable interrupts, we need to do this */
-	lp->spy_number = 0;
-
-	/* Are there are addresses to copy? */
-	if (wrqu->data.length > 0) {
-		/* Copy addresses to the lp structure. */
-		for (i = 0; i < wrqu->data.length; i++) {
-			memcpy(lp->spy_address[i], address[i].sa_data,
-			       WAVELAN_ADDR_SIZE);
-		}
-
-		/* Reset structure. */
-		memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);
-
-#ifdef DEBUG_IOCTL_INFO
-		printk(KERN_DEBUG
-		       "SetSpy:  set of new addresses is: \n");
-		for (i = 0; i < wrqu->data.length; i++)
-			printk(KERN_DEBUG
-			       "%02X:%02X:%02X:%02X:%02X:%02X \n",
-			       lp->spy_address[i][0],
-			       lp->spy_address[i][1],
-			       lp->spy_address[i][2],
-			       lp->spy_address[i][3],
-			       lp->spy_address[i][4],
-			       lp->spy_address[i][5]);
-#endif			/* DEBUG_IOCTL_INFO */
-	}
-
-	/* Now we can set the number of addresses */
-	lp->spy_number = wrqu->data.length;
-
-	return ret;
-}
-
-/*------------------------------------------------------------------*/
-/*
- * Wireless Handler : get spy list
- */
-static int wavelan_get_spy(struct net_device *dev,
-			   struct iw_request_info *info,
-			   union iwreq_data *wrqu,
-			   char *extra)
-{
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
-	struct sockaddr *address = (struct sockaddr *) extra;
-	int i;
-
-	/* Set the number of addresses */
-	wrqu->data.length = lp->spy_number;
-
-	/* Copy addresses from the lp structure. */
-	for (i = 0; i < lp->spy_number; i++) {
-		memcpy(address[i].sa_data,
-		       lp->spy_address[i],
-		       WAVELAN_ADDR_SIZE);
-		address[i].sa_family = AF_UNIX;
-	}
-	/* Copy stats to the user buffer (just after). */
-	if(lp->spy_number > 0)
-		memcpy(extra  + (sizeof(struct sockaddr) * lp->spy_number),
-		       lp->spy_stat, sizeof(iw_qual) * lp->spy_number);
-
-	/* Reset updated flags. */
-	for (i = 0; i < lp->spy_number; i++)
-		lp->spy_stat[i].updated = 0x0;
-
-	return(0);
-}
-#endif			/* WIRELESS_SPY */
-
 /*------------------------------------------------------------------*/
 /*
  * Wireless Private Handler : set quality threshold
@@ -2781,8 +2651,6 @@
   { SIOCGIPHISTO, 0,                     IW_PRIV_TYPE_INT | 16, "gethisto" },
 };
 
-#if WIRELESS_EXT > 12
-
 static const iw_handler		wavelan_handler[] =
 {
 	NULL,				/* SIOCSIWNAME */
@@ -2806,15 +2674,10 @@
 	NULL,				/* SIOCGIWPRIV */
 	NULL,				/* SIOCSIWSTATS */
 	NULL,				/* SIOCGIWSTATS */
-#ifdef WIRELESS_SPY
-	wavelan_set_spy,		/* SIOCSIWSPY */
-	wavelan_get_spy,		/* SIOCGIWSPY */
-#else	/* WIRELESS_SPY */
-	NULL,				/* SIOCSIWSPY */
-	NULL,				/* SIOCGIWSPY */
-#endif	/* WIRELESS_SPY */
-	NULL,				/* -- hole -- */
-	NULL,				/* -- hole -- */
+	iw_handler_set_spy,		/* SIOCSIWSPY */
+	iw_handler_get_spy,		/* SIOCGIWSPY */
+	iw_handler_set_thrspy,		/* SIOCSIWTHRSPY */
+	iw_handler_get_thrspy,		/* SIOCGIWTHRSPY */
 #ifdef WAVELAN_ROAMING_EXT
 	wavelan_set_wap,		/* SIOCSIWAP */
 	wavelan_get_wap,		/* SIOCGIWAP */
@@ -2834,7 +2697,6 @@
 	NULL,				/* SIOCSIWESSID */
 	NULL,				/* SIOCGIWESSID */
 #endif	/* WAVELAN_ROAMING_EXT */
-#if WIRELESS_EXT > 8
 	NULL,				/* SIOCSIWNICKN */
 	NULL,				/* SIOCGIWNICKN */
 	NULL,				/* -- hole -- */
@@ -2851,7 +2713,6 @@
 	NULL,				/* SIOCGIWRETRY */
 	wavelan_set_encode,		/* SIOCSIWENCODE */
 	wavelan_get_encode,		/* SIOCGIWENCODE */
-#endif	/* WIRELESS_EXT > 8 */
 };
 
 static const iw_handler		wavelan_private_handler[] =
@@ -2879,8 +2740,9 @@
 	.standard	= (iw_handler *) wavelan_handler,
 	.private	= (iw_handler *) wavelan_private_handler,
 	.private_args	= (struct iw_priv_args *) wavelan_private_args,
+	.spy_offset	= ((void *) (&((net_local *) NULL)->spy_data) -
+			   (void *) NULL),
 };
-#endif /* WIRELESS_EXT > 12 */
 
 /*------------------------------------------------------------------*/
 /*
@@ -2892,9 +2754,6 @@
 	      struct ifreq *	rq,	/* Data passed */
 	      int		cmd)	/* Ioctl number */
 {
-#if WIRELESS_EXT <= 12
-  struct iwreq *	wrq = (struct iwreq *) rq;
-#endif
   int			ret = 0;
 
 #ifdef DEBUG_IOCTL_TRACE
@@ -2908,284 +2767,6 @@
       ret = wl_netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
       break;
 
-#if WIRELESS_EXT <= 12
-      /* --------------- WIRELESS EXTENSIONS --------------- */
-      /* Now done as iw_handler - Jean II */
-    case SIOCGIWNAME:
-      wavelan_get_name(dev, NULL, &(wrq->u), NULL);
-      break;
-
-    case SIOCSIWNWID:
-      ret = wavelan_set_nwid(dev, NULL, &(wrq->u), NULL);
-      break;
-
-    case SIOCGIWNWID:
-      ret = wavelan_get_nwid(dev, NULL, &(wrq->u), NULL);
-      break;
-
-    case SIOCSIWFREQ:
-      ret = wavelan_set_freq(dev, NULL, &(wrq->u), NULL);
-      break;
-
-    case SIOCGIWFREQ:
-      ret = wavelan_get_freq(dev, NULL, &(wrq->u), NULL);
-      break;
-
-    case SIOCSIWSENS:
-      ret = wavelan_set_sens(dev, NULL, &(wrq->u), NULL);
-      break;
-
-    case SIOCGIWSENS:
-      ret = wavelan_get_sens(dev, NULL, &(wrq->u), NULL);
-      break;
-
-#if WIRELESS_EXT > 8
-    case SIOCSIWENCODE:
-      {
-	char keybuf[8];
-	if (wrq->u.encoding.pointer) {
-	  /* We actually have a key to set */
-	  if (wrq->u.encoding.length != 8) {
-	    ret = -EINVAL;
-	    break;
-	  }
-	  if (copy_from_user(keybuf,
-			     wrq->u.encoding.pointer,
-			     wrq->u.encoding.length)) {
-	    ret = -EFAULT;
-	    break;
-	  }
-	} else if (wrq->u.encoding.length != 0) {
-	  ret = -EINVAL;
-	  break;
-	}
-	ret = wavelan_set_encode(dev, NULL, &(wrq->u), keybuf);
-      }
-      break;
-
-    case SIOCGIWENCODE:
-      if (! capable(CAP_NET_ADMIN)) {
-	ret = -EPERM;
-	break;
-      }
-      {
-	char keybuf[8];
-	ret = wavelan_get_encode(dev, NULL,
-				 &(wrq->u),
-				 keybuf);
-	if (wrq->u.encoding.pointer) {
-	  if (copy_to_user(wrq->u.encoding.pointer,
-			   keybuf,
-			   wrq->u.encoding.length))
-	    ret = -EFAULT;
-	}
-      }
-      break;
-#endif	/* WIRELESS_EXT > 8 */
-
-#ifdef WAVELAN_ROAMING_EXT
-#if WIRELESS_EXT > 5
-    case SIOCSIWESSID:
-      {
-	char essidbuf[IW_ESSID_MAX_SIZE+1];
-	if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) {
-	  ret = -E2BIG;
-	  break;
-	}
-	if (copy_from_user(essidbuf, wrq->u.essid.pointer,
-			   wrq->u.essid.length)) {
-	  ret = -EFAULT;
-	  break;
-	}
-	ret = wavelan_set_essid(dev, NULL,
-				&(wrq->u),
-				essidbuf);
-      }
-      break;
-
-    case SIOCGIWESSID:
-      {
-	char essidbuf[IW_ESSID_MAX_SIZE+1];
-	ret = wavelan_get_essid(dev, NULL,
-				&(wrq->u),
-				essidbuf);
-	if (wrq->u.essid.pointer)
-	  if ( copy_to_user(wrq->u.essid.pointer,
-			    essidbuf,
-			    wrq->u.essid.length) )
-	    ret = -EFAULT;
-      }
-      break;
-
-    case SIOCSIWAP:
-      ret = wavelan_set_wap(dev, NULL, &(wrq->u), NULL);
-      break;
-
-    case SIOCGIWAP:
-      ret = wavelan_get_wap(dev, NULL, &(wrq->u), NULL);
-      break;
-#endif	/* WIRELESS_EXT > 5 */
-#endif	/* WAVELAN_ROAMING_EXT */
-
-#if WIRELESS_EXT > 8
-#ifdef WAVELAN_ROAMING
-    case SIOCSIWMODE:
-      ret = wavelan_set_mode(dev, NULL, &(wrq->u), NULL);
-      break;
-
-    case SIOCGIWMODE:
-      ret = wavelan_get_mode(dev, NULL, &(wrq->u), NULL);
-      break;
-#endif	/* WAVELAN_ROAMING */
-#endif /* WIRELESS_EXT > 8 */
-
-    case SIOCGIWRANGE:
-      {
-	struct iw_range range;
-	ret = wavelan_get_range(dev, NULL,
-				&(wrq->u),
-				(char *) &range);
-	if (copy_to_user(wrq->u.data.pointer, &range,
-			 sizeof(struct iw_range)))
-	  ret = -EFAULT;
-      }
-      break;
-
-    case SIOCGIWPRIV:
-      /* Basic checking... */
-      if(wrq->u.data.pointer != (caddr_t) 0)
-	{
-	  /* Set the number of ioctl available */
-	  wrq->u.data.length = sizeof(wavelan_private_args) / sizeof(wavelan_private_args[0]);
-
-	  /* Copy structure to the user buffer */
-	  if(copy_to_user(wrq->u.data.pointer, (u_char *) wavelan_private_args,
-		       sizeof(wavelan_private_args)))
-	    ret = -EFAULT;
-	}
-      break;
-
-#ifdef WIRELESS_SPY
-    case SIOCSIWSPY:
-      {
-	struct sockaddr address[IW_MAX_SPY];
-	/* Check the number of addresses */
-	if (wrq->u.data.length > IW_MAX_SPY) {
-	  ret = -E2BIG;
-	  break;
-	}
-	/* Get the data in the driver */
-	if (wrq->u.data.pointer) {
-	  if (copy_from_user((char *) address,
-			     wrq->u.data.pointer,
-			     sizeof(struct sockaddr) *
-			     wrq->u.data.length)) {
-	    ret = -EFAULT;
-	    break;
-	  }
-	} else if (wrq->u.data.length != 0) {
-	  ret = -EINVAL;
-	  break;
-	}
-	ret = wavelan_set_spy(dev, NULL, &(wrq->u),
-			      (char *) address);
-      }
-      break;
-
-    case SIOCGIWSPY:
-      {
-	char buffer[IW_MAX_SPY * (sizeof(struct sockaddr) +
-				  sizeof(struct iw_quality))];
-	ret = wavelan_get_spy(dev, NULL, &(wrq->u),
-			      buffer);
-	if (wrq->u.data.pointer) {
-	  if (copy_to_user(wrq->u.data.pointer,
-			   buffer,
-			   (wrq->u.data.length *
-			    (sizeof(struct sockaddr) +
-			     sizeof(struct iw_quality)))
-			   ))
-	    ret = -EFAULT;
-	}
-      }
-      break;
-#endif	/* WIRELESS_SPY */
-
-      /* ------------------ PRIVATE IOCTL ------------------ */
-
-    case SIOCSIPQTHR:
-      if(!capable(CAP_NET_ADMIN))
-	{
-	  ret = -EPERM;
-	  break;
-	}
-      ret = wavelan_set_qthr(dev, NULL, &(wrq->u), NULL);
-      break;
-
-    case SIOCGIPQTHR:
-      ret = wavelan_get_qthr(dev, NULL, &(wrq->u), NULL);
-      break;
-
-#ifdef WAVELAN_ROAMING
-    case SIOCSIPROAM:
-      /* Note : should check if user == root */
-      ret = wavelan_set_roam(dev, NULL, &(wrq->u), NULL);
-      break;
-
-    case SIOCGIPROAM:
-      ret = wavelan_get_roam(dev, NULL, &(wrq->u), NULL);
-      break;
-#endif	/* WAVELAN_ROAMING */
-
-#ifdef HISTOGRAM
-    case SIOCSIPHISTO:
-      /* Verif if the user is root */
-      if(!capable(CAP_NET_ADMIN))
-	{
-	  ret = -EPERM;
-	}
-      {
-	char buffer[16];
-	/* Check the number of intervals */
-	if(wrq->u.data.length > 16)
-	  {
-	    ret = -E2BIG;
-	    break;
-	}
-	/* Get the data in the driver */
-	if (wrq->u.data.pointer) {
-	  if (copy_from_user(buffer,
-			     wrq->u.data.pointer,
-			     sizeof(struct sockaddr) *
-			     wrq->u.data.length)) {
-	    ret = -EFAULT;
-	    break;
-	  }
-	} else if (wrq->u.data.length != 0) {
-	  ret = -EINVAL;
-	  break;
-	}
-	ret = wavelan_set_histo(dev, NULL, &(wrq->u),
-				buffer);
-      }
-      break;
-
-    case SIOCGIPHISTO:
-      {
-	long buffer[16];
-	ret = wavelan_get_histo(dev, NULL, &(wrq->u),
-				(char *) buffer);
-	if (wrq->u.data.pointer) {
-	  if (copy_to_user(wrq->u.data.pointer,
-			   buffer,
-			   (wrq->u.data.length * sizeof(long))))
-	    ret = -EFAULT;
-	}
-      }
-      break;
-#endif	/* HISTOGRAM */
-#endif /* WIRELESS_EXT <= 12 */
-
       /* ------------------- OTHER IOCTL ------------------- */
 
     default:
@@ -3368,9 +2949,9 @@
   /* Statistics gathering & stuff associated.
    * It seem a bit messy with all the define, but it's really simple... */
   if(
-#ifdef WIRELESS_SPY
-     (lp->spy_number > 0) ||
-#endif	/* WIRELESS_SPY */
+#ifdef IW_WIRELESS_SPY
+     (lp->spy_data.spy_number > 0) ||
+#endif	/* IW_WIRELESS_SPY */
 #ifdef HISTOGRAM
      (lp->his_number > 0) ||
 #endif	/* HISTOGRAM */
@@ -3581,10 +3162,6 @@
 
   spin_lock_irqsave(&lp->spinlock, flags);
 
-  /* Check if we need some padding */
-  if(clen < ETH_ZLEN)
-    clen = ETH_ZLEN;
-
   /* Write the length of data buffer followed by the buffer */
   outb(xmtdata_base & 0xff, PIORL(base));
   outb(((xmtdata_base >> 8) & PIORH_MASK) | PIORH_SEL_TX, PIORH(base));
@@ -3664,6 +3241,17 @@
 		printk(KERN_INFO "skb has next\n");
 #endif
 
+	/* Check if we need some padding */
+	/* Note : on wireless the propagation time is in the order of 1us,
+	 * and we don't have the Ethernet specific requirement of beeing
+	 * able to detect collisions, therefore in theory we don't really
+	 * need to pad. Jean II */
+	if (skb->len < ETH_ZLEN) {
+		skb = skb_padto(skb, ETH_ZLEN);
+		if (skb == NULL)
+			return 0;
+	}
+
   wv_packet_write(dev, skb->data, skb->len);
 
   dev_kfree_skb(skb);
@@ -4644,7 +4232,7 @@
  *	   ready to transmit another packet.
  *	3. A command has completed execution.
  */
-static void
+static irqreturn_t
 wavelan_interrupt(int		irq,
 		  void *	dev_id,
 		  struct pt_regs * regs)
@@ -4661,7 +4249,7 @@
       printk(KERN_WARNING "wavelan_interrupt(): irq %d for unknown device.\n",
 	     irq);
 #endif
-      return;
+      return IRQ_NONE;
     }
 
 #ifdef DEBUG_INTERRUPT_TRACE
@@ -4883,6 +4471,24 @@
 #ifdef DEBUG_INTERRUPT_TRACE
   printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name);
 #endif
+
+  /* We always return IRQ_HANDLED, because we will receive empty
+   * interrupts under normal operations. Anyway, it doesn't matter
+   * as we are dealing with an ISA interrupt that can't be shared.
+   *
+   * Explanation : under heavy receive, the following happens :
+   * ->wavelan_interrupt()
+   *    (status0 & SR0_INTERRUPT) != 0
+   *       ->wv_packet_rcv()
+   *    (status0 & SR0_INTERRUPT) != 0
+   *       ->wv_packet_rcv()
+   *    (status0 & SR0_INTERRUPT) == 0	// i.e. no more event
+   * <-wavelan_interrupt()
+   * ->wavelan_interrupt()
+   *    (status0 & SR0_INTERRUPT) == 0	// i.e. empty interrupt
+   * <-wavelan_interrupt()
+   * Jean II */
+  return IRQ_HANDLED;
 } /* wv_interrupt */
 
 /*------------------------------------------------------------------*/
@@ -5189,9 +4795,7 @@
   dev->watchdog_timeo	= WATCHDOG_JIFFIES;
 
 #ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
-#if WIRELESS_EXT > 12
   dev->wireless_handlers = (struct iw_handler_def *)&wavelan_handler_def;
-#endif /* WIRELESS_EXT > 12 */
   dev->do_ioctl = wavelan_ioctl;	/* old wireless extensions */
   dev->get_wireless_stats = wavelan_get_wireless_stats;
 #endif
diff -urN linux-2.5.69-bk6/drivers/net/wireless/wavelan_cs.p.h linux-2.5.69-bk7/drivers/net/wireless/wavelan_cs.p.h
--- linux-2.5.69-bk6/drivers/net/wireless/wavelan_cs.p.h	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk7/drivers/net/wireless/wavelan_cs.p.h	2003-05-12 04:43:29.000000000 -0700
@@ -443,9 +443,7 @@
 
 #ifdef CONFIG_NET_RADIO
 #include <linux/wireless.h>		/* Wireless extensions */
-#if WIRELESS_EXT > 12
-#include <net/iw_handler.h>
-#endif	/* WIRELESS_EXT > 12 */
+#include <net/iw_handler.h>		/* New driver API */
 #endif
 
 /* Pcmcia headers that we need */
@@ -527,13 +525,6 @@
 
 /* ------------------------ PRIVATE IOCTL ------------------------ */
 
-/* Wireless Extension Backward compatibility - Jean II
- * If the new wireless device private ioctl range is not defined,
- * default to standard device private ioctl range */
-#ifndef SIOCIWFIRSTPRIV
-#define SIOCIWFIRSTPRIV	SIOCDEVPRIVATE
-#endif /* SIOCIWFIRSTPRIV */
-
 #define SIOCSIPQTHR	SIOCIWFIRSTPRIV		/* Set quality threshold */
 #define SIOCGIPQTHR	SIOCIWFIRSTPRIV + 1	/* Get quality threshold */
 #define SIOCSIPROAM     SIOCIWFIRSTPRIV + 2	/* Set roaming state */
@@ -605,16 +596,6 @@
 typedef struct net_local	net_local;
 typedef struct timer_list	timer_list;
 
-#if WIRELESS_EXT <= 12
-/* Wireless extensions backward compatibility */
-/* Part of iw_handler prototype we need */
-struct iw_request_info
-{
-	__u16		cmd;		/* Wireless Extension command */
-	__u16		flags;		/* More to come ;-) */
-};
-#endif	/* WIRELESS_EXT <= 12 */
-
 /* Basic types */
 typedef u_char		mac_addr[WAVELAN_ADDR_SIZE];	/* Hardware address */
 
@@ -647,13 +628,10 @@
 
 #ifdef WIRELESS_EXT
   iw_stats	wstats;		/* Wireless specific stats */
+
+  struct iw_spy_data	spy_data;
 #endif
 
-#ifdef WIRELESS_SPY
-  int		spy_number;		/* Number of addresses to spy */
-  mac_addr	spy_address[IW_MAX_SPY];	/* The addresses to spy */
-  iw_qual	spy_stat[IW_MAX_SPY];		/* Statistics gathered */
-#endif	/* WIRELESS_SPY */
 #ifdef HISTOGRAM
   int		his_number;		/* Number of intervals */
   u_char	his_range[16];		/* Boundaries of interval ]n-1; n] */
@@ -686,11 +664,6 @@
 void wv_roam_cleanup(struct net_device *dev);
 #endif	/* WAVELAN_ROAMING */
 
-/* ----------------------- MISC SUBROUTINES ------------------------ */
-static void
-	cs_error(client_handle_t,	/* Report error to cardmgr */
-		 int,
-		 int);
 /* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */
 static inline u_char		/* data */
 	hasr_read(u_long);	/* Read the host interface : base address */
@@ -791,7 +764,7 @@
 	wv_pcmcia_release(u_long),	/* Remove a device */
 	wv_flush_stale_links(void);	/* "detach" all possible devices */
 /* ---------------------- INTERRUPT HANDLING ---------------------- */
-static void
+static irqreturn_t
 	wavelan_interrupt(int,	/* Interrupt handler */
 			  void *,
 			  struct pt_regs *);
diff -urN linux-2.5.69-bk6/drivers/usb/Makefile linux-2.5.69-bk7/drivers/usb/Makefile
--- linux-2.5.69-bk6/drivers/usb/Makefile	2003-05-12 04:43:26.000000000 -0700
+++ linux-2.5.69-bk7/drivers/usb/Makefile	2003-05-12 04:43:30.000000000 -0700
@@ -59,6 +59,3 @@
 obj-$(CONFIG_USB_TIGL)		+= misc/
 obj-$(CONFIG_USB_USS720)	+= misc/
 
-obj-$(CONFIG_USB_NET2280)	+= gadget/
-obj-$(CONFIG_USB_ZERO)		+= gadget/
-obj-$(CONFIG_USB_ETH)		+= gadget/
diff -urN linux-2.5.69-bk6/drivers/usb/gadget/Kconfig linux-2.5.69-bk7/drivers/usb/gadget/Kconfig
--- linux-2.5.69-bk6/drivers/usb/gadget/Kconfig	2003-05-12 04:43:26.000000000 -0700
+++ linux-2.5.69-bk7/drivers/usb/gadget/Kconfig	2003-05-12 04:43:30.000000000 -0700
@@ -10,7 +10,7 @@
 	tristate "Support for USB Gadgets"
 	depends on EXPERIMENTAL
 	help
-	   USB is a master/slave protocol, organized with with one master
+	   USB is a master/slave protocol, organized with one master
 	   host (such as a PC) controlling up to 127 peripheral devices.
 	   The USB hardware is asymmetric, which makes it easier to set up:
 	   you can't connect two "to-the-host" connectors to each other.
diff -urN linux-2.5.69-bk6/drivers/usb/gadget/ether.c linux-2.5.69-bk7/drivers/usb/gadget/ether.c
--- linux-2.5.69-bk6/drivers/usb/gadget/ether.c	2003-05-12 04:43:26.000000000 -0700
+++ linux-2.5.69-bk7/drivers/usb/gadget/ether.c	2003-05-12 04:43:30.000000000 -0700
@@ -168,7 +168,7 @@
  */
 #ifdef	CONFIG_USB_ETH_NET2280
 #define CHIP			"net2280"
-#define DRIVER_VERSION_NUM	cpu_to_le16(0x0101)
+#define DRIVER_VERSION_NUM	0x0101
 #define EP0_MAXPACKET		64
 static const char EP_OUT_NAME [] = "ep-a";
 #define EP_OUT_NUM	2
@@ -201,7 +201,7 @@
  */
 #ifdef	CONFIG_USB_ETH_PXA250
 #define CHIP			"pxa250"
-#define DRIVER_VERSION_NUM	cpu_to_le16(0x0103)
+#define DRIVER_VERSION_NUM	0x0103
 #define EP0_MAXPACKET		16
 static const char EP_OUT_NAME [] = "ep12out-bulk";
 #define EP_OUT_NUM	12
@@ -225,7 +225,7 @@
  */
 #ifdef	CONFIG_USB_ETH_SA1100
 #define CHIP			"sa1100"
-#define DRIVER_VERSION_NUM	cpu_to_le16(0x0105)
+#define DRIVER_VERSION_NUM	0x0105
 #define EP0_MAXPACKET		8
 static const char EP_OUT_NAME [] = "ep1out-bulk";
 #define EP_OUT_NUM	1
@@ -329,15 +329,15 @@
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
 
-	.bcdUSB =		cpu_to_le16 (0x0200),
+	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
 	.bDeviceClass =		USB_CLASS_COMM,
 	.bDeviceSubClass =	0,
 	.bDeviceProtocol =	0,
 	.bMaxPacketSize0 =	EP0_MAXPACKET,
 
-	.idVendor =		cpu_to_le16 (DRIVER_VENDOR_NUM),
-	.idProduct =		cpu_to_le16 (DRIVER_PRODUCT_NUM),
-	.bcdDevice =		cpu_to_le16 (DRIVER_VERSION_NUM),
+	.idVendor =		__constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
+	.idProduct =		__constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
+	.bcdDevice =		__constant_cpu_to_le16 (DRIVER_VERSION_NUM),
 	.iManufacturer =	STRING_MANUFACTURER,
 	.iProduct =		STRING_PRODUCT,
 	.bNumConfigurations =	1,
@@ -389,7 +389,7 @@
 	.bDescriptorType =	0x24,
 	.bDescriptorSubType =	0,
 
-	.bcdCDC =		cpu_to_le16 (0x0110),
+	.bcdCDC =		__constant_cpu_to_le16 (0x0110),
 };
 
 /* "Union Functional Descriptor" from CDC spec 5.2.3.X */
@@ -432,9 +432,9 @@
 
 	/* this descriptor actually adds value, surprise! */
 	.iMACAddress =		STRING_ETHADDR,
-	.bmEthernetStatistics =	cpu_to_le32 (0),	/* no statistics */
-	.wMaxSegmentSize =	cpu_to_le16 (MAX_PACKET + ETH_HLEN),
-	.wNumberMCFilters =	cpu_to_le16 (0),
+	.bmEthernetStatistics =	__constant_cpu_to_le32 (0), /* no statistics */
+	.wMaxSegmentSize =	__constant_cpu_to_le16 (MAX_PACKET + ETH_HLEN),
+	.wNumberMCFilters =	__constant_cpu_to_le16 (0),
 	.bNumberPowerFilters =	0,
 };
 
@@ -457,7 +457,7 @@
 
 	.bEndpointAddress =	EP_STATUS_NUM | USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	cpu_to_le16 (STATUS_BYTECOUNT),
+	.wMaxPacketSize =	__constant_cpu_to_le16 (STATUS_BYTECOUNT),
 	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
 };
 #endif
@@ -501,7 +501,7 @@
 
 	.bEndpointAddress =	EP_IN_NUM | USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16 (64),
+	.wMaxPacketSize =	__constant_cpu_to_le16 (64),
 };
 
 static const struct usb_endpoint_descriptor
@@ -511,7 +511,7 @@
 
 	.bEndpointAddress =	EP_OUT_NUM,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16 (64),
+	.wMaxPacketSize =	__constant_cpu_to_le16 (64),
 };
 
 #ifdef	HIGHSPEED
@@ -529,7 +529,7 @@
 
 	.bEndpointAddress =	EP_STATUS_NUM | USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	cpu_to_le16 (STATUS_BYTECOUNT),
+	.wMaxPacketSize =	__constant_cpu_to_le16 (STATUS_BYTECOUNT),
 	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 3,
 };
 #endif
@@ -541,7 +541,7 @@
 
 	.bEndpointAddress =	EP_IN_NUM | USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16 (512),
+	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
 	.bInterval =		1,
 };
 
@@ -552,7 +552,7 @@
 
 	.bEndpointAddress =	EP_OUT_NUM,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16 (512),
+	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
 	.bInterval =		1,
 };
 
@@ -561,7 +561,7 @@
 	.bLength =		sizeof dev_qualifier,
 	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
 
-	.bcdUSB =		cpu_to_le16 (0x0200),
+	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
 	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
 
 	/* assumes ep0 uses the same value for both speeds ... */
@@ -627,7 +627,7 @@
 	memcpy (buf, &eth_config, USB_DT_CONFIG_SIZE);
 	buf [1] = type;
 	((struct usb_config_descriptor *) buf)->wTotalLength
-		= cpu_to_le16 (config_len);
+		= __constant_cpu_to_le16 (config_len);
 	buf += USB_DT_CONFIG_SIZE;
 #ifdef	HIGHSPEED
 	hs = (speed == USB_SPEED_HIGH);
@@ -858,9 +858,9 @@
 			&& value == 0) {
 		event->bmRequestType = 0xA1;
 		event->bNotificationType = CDC_NOTIFY_SPEED_CHANGE;
-		event->wValue = cpu_to_le16 (0);
-		event->wIndex = cpu_to_le16 (1);
-		event->wLength = cpu_to_le16 (8);
+		event->wValue = __constant_cpu_to_le16 (0);
+		event->wIndex = __constant_cpu_to_le16 (1);
+		event->wLength = __constant_cpu_to_le16 (8);
 
 		/* SPEED_CHANGE data is up/down speeds in bits/sec */
 		event->data [0] = event->data [1] =
@@ -920,8 +920,8 @@
 	event = req->buf;
 	event->bmRequestType = 0xA1;
 	event->bNotificationType = CDC_NOTIFY_NETWORK_CONNECTION;
-	event->wValue = cpu_to_le16 (1);	/* connected */
-	event->wIndex = cpu_to_le16 (1);
+	event->wValue = __constant_cpu_to_le16 (1);	/* connected */
+	event->wIndex = __constant_cpu_to_le16 (1);
 	event->wLength = 0;
 
 	req->length = 8;
diff -urN linux-2.5.69-bk6/drivers/usb/gadget/net2280.c linux-2.5.69-bk7/drivers/usb/gadget/net2280.c
--- linux-2.5.69-bk6/drivers/usb/gadget/net2280.c	2003-05-12 04:43:26.000000000 -0700
+++ linux-2.5.69-bk7/drivers/usb/gadget/net2280.c	2003-05-12 04:43:30.000000000 -0700
@@ -114,8 +114,8 @@
 
 #include "net2280.h"
 
-#define valid_bit	cpu_to_le32 (1 << VALID_BIT)
-#define dma_done_ie	cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE)
+#define valid_bit	__constant_cpu_to_le32 (1 << VALID_BIT)
+#define dma_done_ie	__constant_cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE)
 
 /*-------------------------------------------------------------------------*/
 
@@ -371,7 +371,7 @@
 			return 0;
 		}
 		td->dmacount = 0;	/* not VALID */
-		td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
+		td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID);
 		req->td = td;
 	}
 	return &req->req;
@@ -756,7 +756,7 @@
 		| (ep->is_in << DMA_DIRECTION)
 		| 0, &dma->dmacount);
 #else
-	req->td->dmacount |= cpu_to_le32 (1 << END_OF_CHAIN);
+	req->td->dmacount |= __constant_cpu_to_le32 (1 << END_OF_CHAIN);
 #endif
 
 	writel (req->td_dma, &dma->dmadesc);
@@ -2157,9 +2157,9 @@
 
 			if (readl (&e->regs->ep_rsp)
 					& (1 << SET_ENDPOINT_HALT))
-				status = cpu_to_le16 (1);
+				status = __constant_cpu_to_le16 (1);
 			else
-				status = cpu_to_le16 (0);
+				status = __constant_cpu_to_le16 (0);
 
 			/* don't bother with a request object! */
 			writel (0, &dev->epregs [0].ep_irqenb);
@@ -2574,7 +2574,7 @@
 			goto done;
 		}
 		td->dmacount = 0;	/* not VALID */
-		td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
+		td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID);
 		dev->ep [i].dummy = td;
 	}
 
diff -urN linux-2.5.69-bk6/drivers/usb/gadget/zero.c linux-2.5.69-bk7/drivers/usb/gadget/zero.c
--- linux-2.5.69-bk6/drivers/usb/gadget/zero.c	2003-05-12 04:43:26.000000000 -0700
+++ linux-2.5.69-bk7/drivers/usb/gadget/zero.c	2003-05-12 04:43:30.000000000 -0700
@@ -137,7 +137,7 @@
  */
 #ifdef	CONFIG_USB_ZERO_NET2280
 #define CHIP			"net2280"
-#define DRIVER_VERSION_NUM	cpu_to_le16(0x0101)
+#define DRIVER_VERSION_NUM	0x0101
 #define EP0_MAXPACKET		64
 static const char EP_OUT_NAME [] = "ep-a";
 #define EP_OUT_NUM	2
@@ -172,7 +172,7 @@
  */
 #ifdef	CONFIG_USB_ZERO_PXA250
 #define CHIP			"pxa250"
-#define DRIVER_VERSION_NUM	cpu_to_le16(0x0103)
+#define DRIVER_VERSION_NUM	0x0103
 #define EP0_MAXPACKET		16
 static const char EP_OUT_NAME [] = "ep12out-bulk";
 #define EP_OUT_NUM	12
@@ -199,7 +199,7 @@
  */
 #ifdef	CONFIG_USB_ZERO_SA1100
 #define CHIP			"sa1100"
-#define DRIVER_VERSION_NUM	cpu_to_le16(0x0105)
+#define DRIVER_VERSION_NUM	0x0105
 #define EP0_MAXPACKET		8
 static const char EP_OUT_NAME [] = "ep1out-bulk";
 #define EP_OUT_NUM	1
@@ -340,13 +340,13 @@
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
 
-	.bcdUSB =		cpu_to_le16 (0x0200),
+	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
 	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
 	.bMaxPacketSize0 =	EP0_MAXPACKET,
 
-	.idVendor =		cpu_to_le16 (DRIVER_VENDOR_NUM),
-	.idProduct =		cpu_to_le16 (DRIVER_PRODUCT_NUM),
-	.bcdDevice =		cpu_to_le16 (DRIVER_VERSION_NUM),
+	.idVendor =		__constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
+	.idProduct =		__constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
+	.bcdDevice =		__constant_cpu_to_le16 (DRIVER_VERSION_NUM),
 	.iManufacturer =	STRING_MANUFACTURER,
 	.iProduct =		STRING_PRODUCT,
 	.iSerialNumber =	STRING_SERIAL,
@@ -410,7 +410,7 @@
 
 	.bEndpointAddress =	EP_IN_NUM | USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16 (64),
+	.wMaxPacketSize =	__constant_cpu_to_le16 (64),
 };
 
 static const struct usb_endpoint_descriptor
@@ -420,7 +420,7 @@
 
 	.bEndpointAddress =	EP_OUT_NUM,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16 (64),
+	.wMaxPacketSize =	__constant_cpu_to_le16 (64),
 };
 
 #ifdef	HIGHSPEED
@@ -441,7 +441,7 @@
 
 	.bEndpointAddress =	EP_IN_NUM | USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16 (512),
+	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
 };
 
 static const struct usb_endpoint_descriptor
@@ -451,7 +451,7 @@
 
 	.bEndpointAddress =	EP_OUT_NUM,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	cpu_to_le16 (512),
+	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
 };
 
 static const struct usb_qualifier_descriptor
@@ -459,7 +459,7 @@
 	.bLength =		sizeof dev_qualifier,
 	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
 
-	.bcdUSB =		cpu_to_le16 (0x0200),
+	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
 	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
 
 	/* assumes ep0 uses the same value for both speeds ... */
@@ -538,7 +538,7 @@
 		memcpy (buf, &loopback_config, USB_DT_CONFIG_SIZE);
 	buf [1] = type;
 	((struct usb_config_descriptor *) buf)->wTotalLength
-		= cpu_to_le16 (config_len);
+		= __constant_cpu_to_le16 (config_len);
 	buf += USB_DT_CONFIG_SIZE;
 
 	/* one interface */
diff -urN linux-2.5.69-bk6/fs/fs-writeback.c linux-2.5.69-bk7/fs/fs-writeback.c
--- linux-2.5.69-bk6/fs/fs-writeback.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk7/fs/fs-writeback.c	2003-05-12 04:43:30.000000000 -0700
@@ -367,7 +367,8 @@
 	};
 
 	get_page_state(&ps);
-	wbc.nr_to_write = ps.nr_dirty + ps.nr_dirty / 4;
+	wbc.nr_to_write = ps.nr_dirty + ps.nr_unstable +
+		(ps.nr_dirty + ps.nr_unstable) / 4;
 	spin_lock(&inode_lock);
 	sync_sb_inodes(sb, &wbc);
 	spin_unlock(&inode_lock);
diff -urN linux-2.5.69-bk6/fs/lockd/host.c linux-2.5.69-bk7/fs/lockd/host.c
--- linux-2.5.69-bk6/fs/lockd/host.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk7/fs/lockd/host.c	2003-05-12 04:43:30.000000000 -0700
@@ -187,15 +187,7 @@
 					host->h_nextrebind - jiffies);
 		}
 	} else {
-		uid_t saved_fsuid = current->fsuid;
-		kernel_cap_t saved_cap = current->cap_effective;
-
-		/* Create RPC socket as root user so we get a priv port */
-		current->fsuid = 0;
-		cap_raise (current->cap_effective, CAP_NET_BIND_SERVICE);
 		xprt = xprt_create_proto(host->h_proto, &host->h_addr, NULL);
-		current->fsuid = saved_fsuid;
-		current->cap_effective = saved_cap;
 		if (xprt == NULL)
 			goto forgetit;
 
@@ -209,6 +201,7 @@
 		}
 		clnt->cl_autobind = 1;	/* turn on pmap queries */
 		xprt->nocong = 1;	/* No congestion control for NLM */
+		xprt->resvport = 1;	/* NLM requires a reserved port */
 
 		host->h_rpcclnt = clnt;
 	}
@@ -276,7 +269,7 @@
 	dprintk("lockd: nuking all hosts...\n");
 	for (i = 0; i < NLM_HOST_NRHASH; i++) {
 		for (host = nlm_hosts[i]; host; host = host->h_next)
-			host->h_expires = 0;
+			host->h_expires = jiffies - 1;
 	}
 
 	/* Then, perform a garbage collection pass */
@@ -323,6 +316,9 @@
 		while ((host = *q) != NULL) {
 			if (host->h_count || host->h_inuse
 			 || time_before(jiffies, host->h_expires)) {
+				dprintk("nlm_gc_hosts skipping %s (cnt %d use %d exp %ld)\n",
+					host->h_name, host->h_count,
+					host->h_inuse, host->h_expires);
 				q = &host->h_next;
 				continue;
 			}
diff -urN linux-2.5.69-bk6/fs/lockd/mon.c linux-2.5.69-bk7/fs/lockd/mon.c
--- linux-2.5.69-bk6/fs/lockd/mon.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk7/fs/lockd/mon.c	2003-05-12 04:43:30.000000000 -0700
@@ -123,6 +123,7 @@
 	clnt->cl_softrtry = 1;
 	clnt->cl_chatty   = 1;
 	clnt->cl_oneshot  = 1;
+	xprt->resvport = 1;	/* NSM requires a reserved port */
 out:
 	return clnt;
 
diff -urN linux-2.5.69-bk6/fs/nfs/dir.c linux-2.5.69-bk7/fs/nfs/dir.c
--- linux-2.5.69-bk6/fs/nfs/dir.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk7/fs/nfs/dir.c	2003-05-12 04:43:30.000000000 -0700
@@ -83,7 +83,7 @@
 
 	lock_kernel();
 	/* Do cto revalidation */
-	if (server->flags & NFS_MOUNT_NOCTO)
+	if (!(server->flags & NFS_MOUNT_NOCTO))
 		res = __nfs_revalidate_inode(server, inode);
 	/* Call generic open code in order to cache credentials */
 	if (!res)
diff -urN linux-2.5.69-bk6/fs/nfs/file.c linux-2.5.69-bk7/fs/nfs/file.c
--- linux-2.5.69-bk6/fs/nfs/file.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk7/fs/nfs/file.c	2003-05-12 04:43:30.000000000 -0700
@@ -83,7 +83,7 @@
 	if ((open = server->rpc_ops->file_open) != NULL)
 		res = open(inode, filp);
 	/* Do cto revalidation */
-	else if (server->flags & NFS_MOUNT_NOCTO)
+	else if (!(server->flags & NFS_MOUNT_NOCTO))
 		res = __nfs_revalidate_inode(server, inode);
 	/* Call generic open code in order to cache credentials */
 	if (!res)
diff -urN linux-2.5.69-bk6/fs/nfs/write.c linux-2.5.69-bk7/fs/nfs/write.c
--- linux-2.5.69-bk6/fs/nfs/write.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk7/fs/nfs/write.c	2003-05-12 04:43:30.000000000 -0700
@@ -280,8 +280,6 @@
 		err = nfs_wb_all(inode);
 	} else
 		nfs_commit_file(inode, NULL, 0, 0, 0);
-	/* Avoid races. Tell upstream we've done all we were told to do */
-	wbc->nr_to_write = 0;
 out:
 	return err;
 }
@@ -490,7 +488,6 @@
 	int	res;
 	res = nfs_scan_list(&nfsi->commit, dst, file, idx_start, npages);
 	nfsi->ncommit -= res;
-	sub_page_state(nr_unstable,res);
 	if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))
 		printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");
 	return res;
@@ -1009,6 +1006,7 @@
 {
 	struct nfs_write_data	*data = (struct nfs_write_data *)task->tk_calldata;
 	struct nfs_page		*req;
+	int res = 0;
 
         dprintk("NFS: %4d nfs_commit_done (status %d)\n",
                                 task->tk_pid, task->tk_status);
@@ -1043,7 +1041,9 @@
 		nfs_mark_request_dirty(req);
 	next:
 		nfs_unlock_request(req);
+		res++;
 	}
+	sub_page_state(nr_unstable,res);
 }
 #endif
 
diff -urN linux-2.5.69-bk6/include/asm-i386/suspend.h linux-2.5.69-bk7/include/asm-i386/suspend.h
--- linux-2.5.69-bk6/include/asm-i386/suspend.h	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-i386/suspend.h	2003-05-12 04:43:30.000000000 -0700
@@ -30,18 +30,14 @@
 	unsigned long return_address;
 } __attribute__((packed));
 
-/* We'll access these from assembly, so we'd better have them outside struct */
-extern unsigned long saved_context_eax, saved_context_ebx, saved_context_ecx, saved_context_edx;
-extern unsigned long saved_context_esp, saved_context_ebp, saved_context_esi, saved_context_edi;
-extern unsigned long saved_context_eflags;
-
-
 #define loaddebug(thread,register) \
                __asm__("movl %0,%%db" #register  \
                        : /* no output */ \
                        :"r" ((thread)->debugreg[register]))
 
-extern void fix_processor_context(void);
+extern void save_processor_state(void);
+extern void restore_processor_state(void);
+
 extern void do_magic(int resume);
 
 #ifdef CONFIG_ACPI_SLEEP
diff -urN linux-2.5.69-bk6/include/asm-i386/system.h linux-2.5.69-bk7/include/asm-i386/system.h
--- linux-2.5.69-bk6/include/asm-i386/system.h	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-i386/system.h	2003-05-12 04:43:30.000000000 -0700
@@ -474,5 +474,6 @@
 #define BROKEN_ACPI_Sx		0x0001
 #define BROKEN_INIT_AFTER_S1	0x0002
 #define BROKEN_PNP_BIOS		0x0004
+#define BROKEN_CPUFREQ		0x0008
 
 #endif
diff -urN linux-2.5.69-bk6/include/asm-ia64/acpi-ext.h linux-2.5.69-bk7/include/asm-ia64/acpi-ext.h
--- linux-2.5.69-bk6/include/asm-ia64/acpi-ext.h	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/acpi-ext.h	2003-05-12 04:43:30.000000000 -0700
@@ -3,30 +3,15 @@
  *
  * Copyright (C) 2003 Hewlett-Packard
  * Copyright (C) Alex Williamson
+ * Copyright (C) Bjorn Helgaas
  *
- * Vendor specific extensions to ACPI.  The HP-specific extensiosn are also used by NEC.
+ * Vendor specific extensions to ACPI.
  */
 #ifndef _ASM_IA64_ACPI_EXT_H
 #define _ASM_IA64_ACPI_EXT_H
 
 #include <linux/types.h>
 
-#define HP_CCSR_LENGTH	0x21
-#define HP_CCSR_TYPE	0x2
-#define HP_CCSR_GUID	EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, \
-				 0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad)
-
-struct acpi_hp_vendor_long {
-	u8      guid_id;
-	u8      guid[16];
-	u8      csr_base[8];
-	u8      csr_length[8];
-};
-
 extern acpi_status hp_acpi_csr_space (acpi_handle, u64 *base, u64 *length);
-extern acpi_status acpi_get_crs (acpi_handle, struct acpi_buffer *);
-extern struct acpi_resource *acpi_get_crs_next (struct acpi_buffer *, int *);
-extern union acpi_resource_data *acpi_get_crs_type (struct acpi_buffer *, int *, int);
-extern void acpi_dispose_crs (struct acpi_buffer *);
 
 #endif /* _ASM_IA64_ACPI_EXT_H */
diff -urN linux-2.5.69-bk6/include/asm-ia64/atomic.h linux-2.5.69-bk7/include/asm-ia64/atomic.h
--- linux-2.5.69-bk6/include/asm-ia64/atomic.h	2003-05-04 16:53:06.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/atomic.h	2003-05-12 04:43:30.000000000 -0700
@@ -56,11 +56,16 @@
 }
 
 #define atomic_add_return(i,v)						\
-	((__builtin_constant_p(i) &&					\
-	  (   (i ==  1) || (i ==  4) || (i ==  8) || (i ==  16)		\
-	   || (i == -1) || (i == -4) || (i == -8) || (i == -16)))	\
-	 ? ia64_fetch_and_add(i, &(v)->counter)				\
-	 : ia64_atomic_add(i, v))
+({									\
+	int __ia64_aar_i = (i);						\
+	(__builtin_constant_p(i)					\
+	 && (   (__ia64_aar_i ==  1) || (__ia64_aar_i ==   4)		\
+	     || (__ia64_aar_i ==  8) || (__ia64_aar_i ==  16)		\
+	     || (__ia64_aar_i == -1) || (__ia64_aar_i ==  -4)		\
+	     || (__ia64_aar_i == -8) || (__ia64_aar_i == -16)))		\
+		? ia64_fetch_and_add(__ia64_aar_i, &(v)->counter)	\
+		: ia64_atomic_add(__ia64_aar_i, v);			\
+})
 
 /*
  * Atomically add I to V and return TRUE if the resulting value is
@@ -72,13 +77,17 @@
 	return atomic_add_return(i, v) < 0;
 }
 
-
 #define atomic_sub_return(i,v)						\
-	((__builtin_constant_p(i) &&					\
-	  (   (i ==  1) || (i ==  4) || (i ==  8) || (i ==  16)		\
-	   || (i == -1) || (i == -4) || (i == -8) || (i == -16)))	\
-	 ? ia64_fetch_and_add(-(i), &(v)->counter)			\
-	 : ia64_atomic_sub(i, v))
+({									\
+	int __ia64_asr_i = (i);						\
+	(__builtin_constant_p(i)					\
+	 && (   (__ia64_asr_i ==   1) || (__ia64_asr_i ==   4)		\
+	     || (__ia64_asr_i ==   8) || (__ia64_asr_i ==  16)		\
+	     || (__ia64_asr_i ==  -1) || (__ia64_asr_i ==  -4)		\
+	     || (__ia64_asr_i ==  -8) || (__ia64_asr_i == -16)))	\
+		? ia64_fetch_and_add(-__ia64_asr_i, &(v)->counter)	\
+		: ia64_atomic_sub(__ia64_asr_i, v);			\
+})
 
 #define atomic_dec_return(v)		atomic_sub_return(1, (v))
 #define atomic_inc_return(v)		atomic_add_return(1, (v))
diff -urN linux-2.5.69-bk6/include/asm-ia64/bitops.h linux-2.5.69-bk7/include/asm-ia64/bitops.h
--- linux-2.5.69-bk6/include/asm-ia64/bitops.h	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/bitops.h	2003-05-12 04:43:30.000000000 -0700
@@ -450,15 +450,15 @@
 
 #ifdef __KERNEL__
 
-#define __clear_bit(nr, addr)        clear_bit(nr, addr)
+#define __clear_bit(nr, addr)		clear_bit(nr, addr)
 
-#define ext2_set_bit                 test_and_set_bit
-#define ext2_set_atomic(l,n,a)	     test_and_set_bit(n,a)
-#define ext2_clear_bit               test_and_clear_bit
-#define ext2_clear_atomic(l,n,a)     test_and_clear_bit(n,a)
-#define ext2_test_bit                test_bit
-#define ext2_find_first_zero_bit     find_first_zero_bit
-#define ext2_find_next_zero_bit      find_next_zero_bit
+#define ext2_set_bit			test_and_set_bit
+#define ext2_set_bit_atomic(l,n,a)	test_and_set_bit(n,a)
+#define ext2_clear_bit			test_and_clear_bit
+#define ext2_clear_bit_atomic(l,n,a)	test_and_clear_bit(n,a)
+#define ext2_test_bit			test_bit
+#define ext2_find_first_zero_bit	find_first_zero_bit
+#define ext2_find_next_zero_bit		find_next_zero_bit
 
 /* Bitmap functions for the minix filesystem.  */
 #define minix_test_and_set_bit(nr,addr)		test_and_set_bit(nr,addr)
diff -urN linux-2.5.69-bk6/include/asm-ia64/compat.h linux-2.5.69-bk7/include/asm-ia64/compat.h
--- linux-2.5.69-bk6/include/asm-ia64/compat.h	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/compat.h	2003-05-12 04:43:30.000000000 -0700
@@ -102,6 +102,9 @@
 	int		f_spare[6];
 };
 
+#define COMPAT_RLIM_OLD_INFINITY       0x7fffffff
+#define COMPAT_RLIM_INFINITY           0xffffffff
+
 typedef u32		compat_old_sigset_t;	/* at least 32 bits */
 
 #define _COMPAT_NSIG		64
diff -urN linux-2.5.69-bk6/include/asm-ia64/dma-mapping.h linux-2.5.69-bk7/include/asm-ia64/dma-mapping.h
--- linux-2.5.69-bk6/include/asm-ia64/dma-mapping.h	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/dma-mapping.h	2003-05-12 04:43:30.000000000 -0700
@@ -1 +1,63 @@
-#include <asm-generic/dma-mapping.h>
+#ifndef _ASM_IA64_DMA_MAPPING_H
+#define _ASM_IA64_DMA_MAPPING_H
+
+/*
+ * Copyright (C) 2003 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#define dma_alloc_coherent	platform_dma_alloc_coherent
+#define dma_alloc_noncoherent	platform_dma_alloc_coherent	/* coherent mem. is cheap */
+#define dma_free_coherent	platform_dma_free_coherent
+#define dma_free_noncoherent	platform_dma_free_coherent
+#define dma_map_single		platform_dma_map_single
+#define dma_map_sg		platform_dma_map_sg
+#define dma_unmap_single	platform_dma_unmap_single
+#define dma_unmap_sg		platform_dma_unmap_sg
+#define dma_sync_single		platform_dma_sync_single
+#define dma_sync_sg		platform_dma_sync_sg
+
+#define dma_map_page(dev, pg, off, size, dir)				\
+	dma_map_single(dev, page_address(pg) + (off), (size), (dir))
+#define dma_unmap_page(dev, dma_addr, size, dir)			\
+	dma_unmap_single(dev, dma_addr, size, dir)
+
+/*
+ * Rest of this file is part of the "Advanced DMA API".  Use at your own risk.
+ * See Documentation/DMA-API.txt for details.
+ */
+
+#define dma_sync_single_range(dev, dma_handle, offset, size, dir)	\
+	dma_sync_single(dev, dma_handle, size, dir)
+
+#define dma_supported		platform_dma_supported
+
+static inline int
+dma_set_mask (struct device *dev, u64 mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, mask))
+		return -EIO;
+	*dev->dma_mask = mask;
+	return 0;
+}
+
+static inline int
+dma_get_cache_alignment (void)
+{
+	extern int ia64_max_cacheline_size;
+	return ia64_max_cacheline_size;
+}
+
+static inline void
+dma_cache_sync (void *vaddr, size_t size, enum dma_data_direction dir)
+{
+	/*
+	 * IA-64 is cache-coherent, so this is mostly a no-op.  However, we do need to
+	 * ensure that dma_cache_sync() enforces order, hence the mb().
+	 */
+	mb();
+}
+
+#define dma_is_consistent(dma_handle)	(1)	/* all we do is coherent memory... */
+
+#endif /* _ASM_IA64_DMA_MAPPING_H */
diff -urN linux-2.5.69-bk6/include/asm-ia64/ia32.h linux-2.5.69-bk7/include/asm-ia64/ia32.h
--- linux-2.5.69-bk6/include/asm-ia64/ia32.h	2003-05-04 16:53:56.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/ia32.h	2003-05-12 04:43:30.000000000 -0700
@@ -453,8 +453,6 @@
 struct linux_binprm;
 
 extern void ia32_gdt_init (void);
-extern int ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info,
-			       sigset_t *set, struct pt_regs *regs);
 extern void ia32_init_addr_space (struct pt_regs *regs);
 extern int ia32_setup_arg_pages (struct linux_binprm *bprm);
 extern int ia32_exception (struct pt_regs *regs, unsigned long isr);
@@ -476,4 +474,8 @@
 
 #endif /* !CONFIG_IA32_SUPPORT */
 
+/* Declare this uncondiontally, so we don't get warnings for unreachable code.  */
+extern int ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info,
+			      sigset_t *set, struct pt_regs *regs);
+
 #endif /* _ASM_IA64_IA32_H */
diff -urN linux-2.5.69-bk6/include/asm-ia64/intrinsics.h linux-2.5.69-bk7/include/asm-ia64/intrinsics.h
--- linux-2.5.69-bk6/include/asm-ia64/intrinsics.h	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/intrinsics.h	2003-05-12 04:43:30.000000000 -0700
@@ -17,16 +17,16 @@
 extern unsigned long __bad_size_for_ia64_fetch_and_add (void);
 extern unsigned long __bad_increment_for_ia64_fetch_and_add (void);
 
-#define IA64_FETCHADD(tmp,v,n,sz)						\
+#define IA64_FETCHADD(tmp,v,n,sz,sem)						\
 ({										\
 	switch (sz) {								\
 	      case 4:								\
-		__asm__ __volatile__ ("fetchadd4.rel %0=[%1],%2"		\
+		__asm__ __volatile__ ("fetchadd4."sem" %0=[%1],%2"		\
 				      : "=r"(tmp) : "r"(v), "i"(n) : "memory");	\
 		break;								\
 										\
 	      case 8:								\
-		__asm__ __volatile__ ("fetchadd8.rel %0=[%1],%2"		\
+		__asm__ __volatile__ ("fetchadd8."sem" %0=[%1],%2"		\
 				      : "=r"(tmp) : "r"(v), "i"(n) : "memory");	\
 		break;								\
 										\
@@ -35,32 +35,34 @@
 	}									\
 })
 
-#define ia64_fetch_and_add(i,v)								\
+#define ia64_fetchadd(i,v,sem)								\
 ({											\
 	__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)));				\
+		IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v)), sem);			\
 	else if ((i) == -8)								\
-		IA64_FETCHADD(_tmp, _v, -8, sizeof(*(v)));				\
+		IA64_FETCHADD(_tmp, _v, -8, sizeof(*(v)), sem);				\
 	else if ((i) == -4)								\
-		IA64_FETCHADD(_tmp, _v, -4, sizeof(*(v)));				\
+		IA64_FETCHADD(_tmp, _v, -4, sizeof(*(v)), sem);				\
 	else if ((i) == -1)								\
-		IA64_FETCHADD(_tmp, _v, -1, sizeof(*(v)));				\
+		IA64_FETCHADD(_tmp, _v, -1, sizeof(*(v)), sem);				\
 	else if ((i) == 1)								\
-		IA64_FETCHADD(_tmp, _v, 1, sizeof(*(v)));				\
+		IA64_FETCHADD(_tmp, _v, 1, sizeof(*(v)), sem);				\
 	else if ((i) == 4)								\
-		IA64_FETCHADD(_tmp, _v, 4, sizeof(*(v)));				\
+		IA64_FETCHADD(_tmp, _v, 4, sizeof(*(v)), sem);				\
 	else if ((i) == 8)								\
-		IA64_FETCHADD(_tmp, _v, 8, sizeof(*(v)));				\
+		IA64_FETCHADD(_tmp, _v, 8, sizeof(*(v)), sem);				\
 	else if ((i) == 16)								\
-		IA64_FETCHADD(_tmp, _v, 16, sizeof(*(v)));				\
+		IA64_FETCHADD(_tmp, _v, 16, sizeof(*(v)), sem);				\
 	else										\
 		_tmp = __bad_increment_for_ia64_fetch_and_add();			\
-	(__typeof__(*(v))) (_tmp + (i));	/* return new value */			\
+	(__typeof__(*(v))) (_tmp);	/* return old value */				\
 })
 
+#define ia64_fetch_and_add(i,v)	(ia64_fetchadd(i, v, "rel") + (i)) /* return new value */
+
 /*
  * This function doesn't exist, so you'll get a linker error if
  * something tries to do an invalid xchg().
@@ -127,7 +129,7 @@
 	      case 8: _o_ = (__u64) (long) (old); break;				\
 	      default: break;								\
 	}										\
-	 __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO"(_o_));				\
+	__asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO"(_o_));				\
 	switch (size) {									\
 	      case 1:									\
 		__asm__ __volatile__ ("cmpxchg1."sem" %0=[%1],%2,ar.ccv"		\
diff -urN linux-2.5.69-bk6/include/asm-ia64/io.h linux-2.5.69-bk7/include/asm-ia64/io.h
--- linux-2.5.69-bk6/include/asm-ia64/io.h	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/io.h	2003-05-12 04:43:30.000000000 -0700
@@ -13,7 +13,7 @@
  * over and over again with slight variations and possibly making a
  * mistake somewhere.
  *
- * Copyright (C) 1998-2002 Hewlett-Packard Co
+ * Copyright (C) 1998-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
  * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
@@ -32,6 +32,24 @@
  */
 #define IO_SPACE_LIMIT		0xffffffffffffffffUL
 
+#define MAX_IO_SPACES			16
+#define IO_SPACE_BITS			24
+#define IO_SPACE_SIZE			(1UL << IO_SPACE_BITS)
+
+#define IO_SPACE_NR(port)		((port) >> IO_SPACE_BITS)
+#define IO_SPACE_BASE(space)		((space) << IO_SPACE_BITS)
+#define IO_SPACE_PORT(port)		((port) & (IO_SPACE_SIZE - 1))
+
+#define IO_SPACE_SPARSE_ENCODING(p)	((((p) >> 2) << 12) | (p & 0xfff))
+
+struct io_space {
+	unsigned long mmio_base;	/* base in MMIO space */
+	int sparse;
+};
+
+extern struct io_space io_space[];
+extern unsigned int num_io_spaces;
+
 # ifdef __KERNEL__
 
 #include <asm/machvec.h>
@@ -80,12 +98,33 @@
 static inline void*
 __ia64_mk_io_addr (unsigned long port)
 {
-	const unsigned long io_base = __ia64_get_io_port_base();
-	unsigned long addr;
+	struct io_space *space;
+	unsigned long offset;
 
-	addr = io_base | ((port >> 2) << 12) | (port & 0xfff);
-	return (void *) addr;
-}
+	space = &io_space[IO_SPACE_NR(port)];
+	port = IO_SPACE_PORT(port);
+	if (space->sparse)
+		offset = IO_SPACE_SPARSE_ENCODING(port);
+	else
+		offset = port;
+
+	return (void *) (space->mmio_base | offset);
+}
+
+#define __ia64_inb	___ia64_inb
+#define __ia64_inw	___ia64_inw
+#define __ia64_inl	___ia64_inl
+#define __ia64_outb	___ia64_outb
+#define __ia64_outw	___ia64_outw
+#define __ia64_outl	___ia64_outl
+#define __ia64_readb	___ia64_readb
+#define __ia64_readw	___ia64_readw
+#define __ia64_readl	___ia64_readl
+#define __ia64_readq	___ia64_readq
+#define __ia64_writeb	___ia64_writeb
+#define __ia64_writew	___ia64_writew
+#define __ia64_writel	___ia64_writel
+#define __ia64_writeq	___ia64_writeq
 
 /*
  * For the in/out routines, we need to do "mf.a" _after_ doing the I/O access to ensure
@@ -96,7 +135,7 @@
  */
 
 static inline unsigned int
-__ia64_inb (unsigned long port)
+___ia64_inb (unsigned long port)
 {
 	volatile unsigned char *addr = __ia64_mk_io_addr(port);
 	unsigned char ret;
@@ -107,7 +146,7 @@
 }
 
 static inline unsigned int
-__ia64_inw (unsigned long port)
+___ia64_inw (unsigned long port)
 {
 	volatile unsigned short *addr = __ia64_mk_io_addr(port);
 	unsigned short ret;
@@ -118,7 +157,7 @@
 }
 
 static inline unsigned int
-__ia64_inl (unsigned long port)
+___ia64_inl (unsigned long port)
 {
 	volatile unsigned int *addr = __ia64_mk_io_addr(port);
 	unsigned int ret;
@@ -129,7 +168,7 @@
 }
 
 static inline void
-__ia64_outb (unsigned char val, unsigned long port)
+___ia64_outb (unsigned char val, unsigned long port)
 {
 	volatile unsigned char *addr = __ia64_mk_io_addr(port);
 
@@ -138,7 +177,7 @@
 }
 
 static inline void
-__ia64_outw (unsigned short val, unsigned long port)
+___ia64_outw (unsigned short val, unsigned long port)
 {
 	volatile unsigned short *addr = __ia64_mk_io_addr(port);
 
@@ -147,7 +186,7 @@
 }
 
 static inline void
-__ia64_outl (unsigned int val, unsigned long port)
+___ia64_outl (unsigned int val, unsigned long port)
 {
 	volatile unsigned int *addr = __ia64_mk_io_addr(port);
 
@@ -160,17 +199,8 @@
 {
 	unsigned char *dp = dst;
 
-	if (platform_inb == __ia64_inb) {
-		volatile unsigned char *addr = __ia64_mk_io_addr(port);
-
-		__ia64_mf_a();
-		while (count--)
-			*dp++ = *addr;
-		__ia64_mf_a();
-	} else
-		while (count--)
-			*dp++ = platform_inb(port);
-	return;
+	while (count--)
+		*dp++ = platform_inb(port);
 }
 
 static inline void
@@ -178,17 +208,8 @@
 {
 	unsigned short *dp = dst;
 
-	if (platform_inw == __ia64_inw) {
-		volatile unsigned short *addr = __ia64_mk_io_addr(port);
-
-		__ia64_mf_a();
-		while (count--)
-			*dp++ = *addr;
-		__ia64_mf_a();
-	} else
-		while (count--)
-			*dp++ = platform_inw(port);
-	return;
+	while (count--)
+		*dp++ = platform_inw(port);
 }
 
 static inline void
@@ -196,17 +217,8 @@
 {
 	unsigned int *dp = dst;
 
-	if (platform_inl == __ia64_inl) {
-		volatile unsigned int *addr = __ia64_mk_io_addr(port);
-
-		__ia64_mf_a();
-		while (count--)
-			*dp++ = *addr;
-		__ia64_mf_a();
-	} else
-		while (count--)
-			*dp++ = platform_inl(port);
-	return;
+	while (count--)
+		*dp++ = platform_inl(port);
 }
 
 static inline void
@@ -214,16 +226,8 @@
 {
 	const unsigned char *sp = src;
 
-	if (platform_outb == __ia64_outb) {
-		volatile unsigned char *addr = __ia64_mk_io_addr(port);
-
-		while (count--)
-			*addr = *sp++;
-		__ia64_mf_a();
-	} else
-		while (count--)
-			platform_outb(*sp++, port);
-	return;
+	while (count--)
+		platform_outb(*sp++, port);
 }
 
 static inline void
@@ -231,16 +235,8 @@
 {
 	const unsigned short *sp = src;
 
-	if (platform_outw == __ia64_outw) {
-		volatile unsigned short *addr = __ia64_mk_io_addr(port);
-
-		while (count--)
-			*addr = *sp++;
-		__ia64_mf_a();
-	} else
-		while (count--)
-			platform_outw(*sp++, port);
-	return;
+	while (count--)
+		platform_outw(*sp++, port);
 }
 
 static inline void
@@ -248,16 +244,8 @@
 {
 	const unsigned int *sp = src;
 
-	if (platform_outl == __ia64_outl) {
-		volatile unsigned int *addr = __ia64_mk_io_addr(port);
-
-		while (count--)
-			*addr = *sp++;
-		__ia64_mf_a();
-	} else
-		while (count--)
-			platform_outl(*sp++, port);
-	return;
+	while (count--)
+		platform_outl(*sp++, port);
 }
 
 /*
@@ -294,25 +282,25 @@
  * hopefully it'll stay that way).
  */
 static inline unsigned char
-__ia64_readb (void *addr)
+___ia64_readb (void *addr)
 {
 	return *(volatile unsigned char *)addr;
 }
 
 static inline unsigned short
-__ia64_readw (void *addr)
+___ia64_readw (void *addr)
 {
 	return *(volatile unsigned short *)addr;
 }
 
 static inline unsigned int
-__ia64_readl (void *addr)
+___ia64_readl (void *addr)
 {
 	return *(volatile unsigned int *) addr;
 }
 
 static inline unsigned long
-__ia64_readq (void *addr)
+___ia64_readq (void *addr)
 {
 	return *(volatile unsigned long *) addr;
 }
diff -urN linux-2.5.69-bk6/include/asm-ia64/iosapic.h linux-2.5.69-bk7/include/asm-ia64/iosapic.h
--- linux-2.5.69-bk6/include/asm-ia64/iosapic.h	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/iosapic.h	2003-05-12 04:43:30.000000000 -0700
@@ -57,6 +57,7 @@
 extern int gsi_to_vector (unsigned int gsi);
 extern int gsi_to_irq (unsigned int gsi);
 extern void __init iosapic_parse_prt (void);
+extern void iosapic_enable_intr (unsigned int vector);
 extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity,
 				  unsigned long trigger);
 extern void __init iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
diff -urN linux-2.5.69-bk6/include/asm-ia64/machvec.h linux-2.5.69-bk7/include/asm-ia64/machvec.h
--- linux-2.5.69-bk6/include/asm-ia64/machvec.h	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/machvec.h	2003-05-12 04:43:30.000000000 -0700
@@ -4,7 +4,7 @@
  * Copyright (C) 1999 Silicon Graphics, Inc.
  * Copyright (C) Srinivasa Thirumalachar <sprasad@engr.sgi.com>
  * Copyright (C) Vijay Chander <vijay@engr.sgi.com>
- * Copyright (C) 1999-2001 Hewlett-Packard Co.
+ * Copyright (C) 1999-2001, 2003 Hewlett-Packard Co.
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 #ifndef _ASM_IA64_MACHVEC_H
@@ -14,7 +14,7 @@
 #include <linux/types.h>
 
 /* forward declarations: */
-struct pci_dev;
+struct device;
 struct pt_regs;
 struct scatterlist;
 struct irq_desc;
@@ -33,17 +33,17 @@
 typedef u8 ia64_mv_irq_to_vector (u8);
 typedef unsigned int ia64_mv_local_vector_to_irq (u8 vector);
 
-/* PCI-DMA interface: */
-typedef void ia64_mv_pci_dma_init (void);
-typedef void *ia64_mv_pci_alloc_consistent (struct pci_dev *, size_t, dma_addr_t *);
-typedef void ia64_mv_pci_free_consistent (struct pci_dev *, size_t, void *, dma_addr_t);
-typedef dma_addr_t ia64_mv_pci_map_single (struct pci_dev *, void *, size_t, int);
-typedef void ia64_mv_pci_unmap_single (struct pci_dev *, dma_addr_t, size_t, int);
-typedef int ia64_mv_pci_map_sg (struct pci_dev *, struct scatterlist *, int, int);
-typedef void ia64_mv_pci_unmap_sg (struct pci_dev *, struct scatterlist *, int, int);
-typedef void ia64_mv_pci_dma_sync_single (struct pci_dev *, dma_addr_t, size_t, int);
-typedef void ia64_mv_pci_dma_sync_sg (struct pci_dev *, struct scatterlist *, int, int);
-typedef int ia64_mv_pci_dma_supported (struct pci_dev *, u64);
+/* DMA-mapping interface: */
+typedef void ia64_mv_dma_init (void);
+typedef void *ia64_mv_dma_alloc_coherent (struct device *, size_t, dma_addr_t *, int);
+typedef void ia64_mv_dma_free_coherent (struct device *, size_t, void *, dma_addr_t);
+typedef dma_addr_t ia64_mv_dma_map_single (struct device *, void *, size_t, int);
+typedef void ia64_mv_dma_unmap_single (struct device *, dma_addr_t, size_t, int);
+typedef int ia64_mv_dma_map_sg (struct device *, struct scatterlist *, int, int);
+typedef void ia64_mv_dma_unmap_sg (struct device *, struct scatterlist *, int, int);
+typedef void ia64_mv_dma_sync_single (struct device *, dma_addr_t, size_t, int);
+typedef void ia64_mv_dma_sync_sg (struct device *, struct scatterlist *, int, int);
+typedef int ia64_mv_dma_supported (struct device *, u64);
 
 /*
  * WARNING: The legacy I/O space is _architected_.  Platforms are
@@ -66,6 +66,7 @@
 typedef unsigned long ia64_mv_readq_t (void *);
 
 extern void machvec_noop (void);
+extern void machvec_memory_fence (void);
 
 # if defined (CONFIG_IA64_HP_SIM)
 #  include <asm/machvec_hpsim.h>
@@ -92,16 +93,16 @@
 #  define platform_log_print	ia64_mv.log_print
 #  define platform_send_ipi	ia64_mv.send_ipi
 #  define platform_global_tlb_purge	ia64_mv.global_tlb_purge
-#  define platform_pci_dma_init		ia64_mv.dma_init
-#  define platform_pci_alloc_consistent	ia64_mv.alloc_consistent
-#  define platform_pci_free_consistent	ia64_mv.free_consistent
-#  define platform_pci_map_single	ia64_mv.map_single
-#  define platform_pci_unmap_single	ia64_mv.unmap_single
-#  define platform_pci_map_sg		ia64_mv.map_sg
-#  define platform_pci_unmap_sg		ia64_mv.unmap_sg
-#  define platform_pci_dma_sync_single	ia64_mv.sync_single
-#  define platform_pci_dma_sync_sg	ia64_mv.sync_sg
-#  define platform_pci_dma_supported	ia64_mv.dma_supported
+#  define platform_dma_init		ia64_mv.dma_init
+#  define platform_dma_alloc_coherent	ia64_mv.dma_alloc_coherent
+#  define platform_dma_free_coherent	ia64_mv.dma_free_coherent
+#  define platform_dma_map_single	ia64_mv.dma_map_single
+#  define platform_dma_unmap_single	ia64_mv.dma_unmap_single
+#  define platform_dma_map_sg		ia64_mv.dma_map_sg
+#  define platform_dma_unmap_sg		ia64_mv.dma_unmap_sg
+#  define platform_dma_sync_single	ia64_mv.dma_sync_single
+#  define platform_dma_sync_sg		ia64_mv.dma_sync_sg
+#  define platform_dma_supported	ia64_mv.dma_supported
 #  define platform_irq_desc		ia64_mv.irq_desc
 #  define platform_irq_to_vector	ia64_mv.irq_to_vector
 #  define platform_local_vector_to_irq	ia64_mv.local_vector_to_irq
@@ -119,7 +120,7 @@
 
 /* __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 
+ * This will fillup the holes created because of section 3.3.1 in
  * Software Conventions guide.
  */
 struct ia64_machine_vector {
@@ -133,16 +134,16 @@
 	ia64_mv_log_print_t *log_print;
 	ia64_mv_send_ipi_t *send_ipi;
 	ia64_mv_global_tlb_purge_t *global_tlb_purge;
-	ia64_mv_pci_dma_init *dma_init;
-	ia64_mv_pci_alloc_consistent *alloc_consistent;
-	ia64_mv_pci_free_consistent *free_consistent;
-	ia64_mv_pci_map_single *map_single;
-	ia64_mv_pci_unmap_single *unmap_single;
-	ia64_mv_pci_map_sg *map_sg;
-	ia64_mv_pci_unmap_sg *unmap_sg;
-	ia64_mv_pci_dma_sync_single *sync_single;
-	ia64_mv_pci_dma_sync_sg *sync_sg;
-	ia64_mv_pci_dma_supported *dma_supported;
+	ia64_mv_dma_init *dma_init;
+	ia64_mv_dma_alloc_coherent *dma_alloc_coherent;
+	ia64_mv_dma_free_coherent *dma_free_coherent;
+	ia64_mv_dma_map_single *dma_map_single;
+	ia64_mv_dma_unmap_single *dma_unmap_single;
+	ia64_mv_dma_map_sg *dma_map_sg;
+	ia64_mv_dma_unmap_sg *dma_unmap_sg;
+	ia64_mv_dma_sync_single *dma_sync_single;
+	ia64_mv_dma_sync_sg *dma_sync_sg;
+	ia64_mv_dma_supported *dma_supported;
 	ia64_mv_irq_desc *irq_desc;
 	ia64_mv_irq_to_vector *irq_to_vector;
 	ia64_mv_local_vector_to_irq *local_vector_to_irq;
@@ -170,16 +171,16 @@
 	platform_log_print,			\
 	platform_send_ipi,			\
 	platform_global_tlb_purge,		\
-	platform_pci_dma_init,			\
-	platform_pci_alloc_consistent,		\
-	platform_pci_free_consistent,		\
-	platform_pci_map_single,		\
-	platform_pci_unmap_single,		\
-	platform_pci_map_sg,			\
-	platform_pci_unmap_sg,			\
-	platform_pci_dma_sync_single,		\
-	platform_pci_dma_sync_sg,		\
-	platform_pci_dma_supported,		\
+	platform_dma_init,			\
+	platform_dma_alloc_coherent,		\
+	platform_dma_free_coherent,		\
+	platform_dma_map_single,		\
+	platform_dma_unmap_single,		\
+	platform_dma_map_sg,			\
+	platform_dma_unmap_sg,			\
+	platform_dma_sync_single,		\
+	platform_dma_sync_sg,			\
+	platform_dma_supported,			\
 	platform_irq_desc,			\
 	platform_irq_to_vector,			\
 	platform_local_vector_to_irq,		\
@@ -205,16 +206,16 @@
 /*
  * Declare default routines which aren't declared anywhere else:
  */
-extern ia64_mv_pci_dma_init swiotlb_init;
-extern ia64_mv_pci_alloc_consistent swiotlb_alloc_consistent;
-extern ia64_mv_pci_free_consistent swiotlb_free_consistent;
-extern ia64_mv_pci_map_single swiotlb_map_single;
-extern ia64_mv_pci_unmap_single swiotlb_unmap_single;
-extern ia64_mv_pci_map_sg swiotlb_map_sg;
-extern ia64_mv_pci_unmap_sg swiotlb_unmap_sg;
-extern ia64_mv_pci_dma_sync_single swiotlb_sync_single;
-extern ia64_mv_pci_dma_sync_sg swiotlb_sync_sg;
-extern ia64_mv_pci_dma_supported swiotlb_pci_dma_supported;
+extern ia64_mv_dma_init			swiotlb_init;
+extern ia64_mv_dma_alloc_coherent	swiotlb_alloc_coherent;
+extern ia64_mv_dma_free_coherent	swiotlb_free_coherent;
+extern ia64_mv_dma_map_single		swiotlb_map_single;
+extern ia64_mv_dma_unmap_single		swiotlb_unmap_single;
+extern ia64_mv_dma_map_sg		swiotlb_map_sg;
+extern ia64_mv_dma_unmap_sg		swiotlb_unmap_sg;
+extern ia64_mv_dma_sync_single		swiotlb_sync_single;
+extern ia64_mv_dma_sync_sg		swiotlb_sync_sg;
+extern ia64_mv_dma_supported		swiotlb_dma_supported;
 
 /*
  * Define default versions so we can extend machvec for new platforms without having
@@ -247,35 +248,35 @@
 #ifndef platform_global_tlb_purge
 # define platform_global_tlb_purge	ia64_global_tlb_purge /* default to architected version */
 #endif
-#ifndef platform_pci_dma_init
-# define platform_pci_dma_init		swiotlb_init
+#ifndef platform_dma_init
+# define platform_dma_init		swiotlb_init
 #endif
-#ifndef platform_pci_alloc_consistent
-# define platform_pci_alloc_consistent	swiotlb_alloc_consistent
+#ifndef platform_dma_alloc_coherent
+# define platform_dma_alloc_coherent	swiotlb_alloc_coherent
 #endif
-#ifndef platform_pci_free_consistent
-# define platform_pci_free_consistent	swiotlb_free_consistent
+#ifndef platform_dma_free_coherent
+# define platform_dma_free_coherent	swiotlb_free_coherent
 #endif
-#ifndef platform_pci_map_single
-# define platform_pci_map_single	swiotlb_map_single
+#ifndef platform_dma_map_single
+# define platform_dma_map_single	swiotlb_map_single
 #endif
-#ifndef platform_pci_unmap_single
-# define platform_pci_unmap_single	swiotlb_unmap_single
+#ifndef platform_dma_unmap_single
+# define platform_dma_unmap_single	swiotlb_unmap_single
 #endif
-#ifndef platform_pci_map_sg
-# define platform_pci_map_sg		swiotlb_map_sg
+#ifndef platform_dma_map_sg
+# define platform_dma_map_sg		swiotlb_map_sg
 #endif
-#ifndef platform_pci_unmap_sg
-# define platform_pci_unmap_sg		swiotlb_unmap_sg
+#ifndef platform_dma_unmap_sg
+# define platform_dma_unmap_sg		swiotlb_unmap_sg
 #endif
-#ifndef platform_pci_dma_sync_single
-# define platform_pci_dma_sync_single	swiotlb_sync_single
+#ifndef platform_dma_sync_single
+# define platform_dma_sync_single	swiotlb_sync_single
 #endif
-#ifndef platform_pci_dma_sync_sg
-# define platform_pci_dma_sync_sg	swiotlb_sync_sg
+#ifndef platform_dma_sync_sg
+# define platform_dma_sync_sg		swiotlb_sync_sg
 #endif
-#ifndef platform_pci_dma_supported
-# define  platform_pci_dma_supported	swiotlb_pci_dma_supported
+#ifndef platform_dma_supported
+# define  platform_dma_supported	swiotlb_dma_supported
 #endif
 #ifndef platform_irq_desc
 # define platform_irq_desc		__ia64_irq_desc
diff -urN linux-2.5.69-bk6/include/asm-ia64/machvec_hpzx1.h linux-2.5.69-bk7/include/asm-ia64/machvec_hpzx1.h
--- linux-2.5.69-bk6/include/asm-ia64/machvec_hpzx1.h	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/machvec_hpzx1.h	2003-05-12 04:43:30.000000000 -0700
@@ -2,13 +2,13 @@
 #define _ASM_IA64_MACHVEC_HPZX1_h
 
 extern ia64_mv_setup_t dig_setup;
-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;
-extern ia64_mv_pci_unmap_single sba_unmap_single;
-extern ia64_mv_pci_map_sg sba_map_sg;
-extern ia64_mv_pci_unmap_sg sba_unmap_sg;
-extern ia64_mv_pci_dma_supported sba_dma_supported;
+extern ia64_mv_dma_alloc_coherent	sba_alloc_coherent;
+extern ia64_mv_dma_free_coherent	sba_free_coherent;
+extern ia64_mv_dma_map_single		sba_map_single;
+extern ia64_mv_dma_unmap_single		sba_unmap_single;
+extern ia64_mv_dma_map_sg		sba_map_sg;
+extern ia64_mv_dma_unmap_sg		sba_unmap_sg;
+extern ia64_mv_dma_supported		sba_dma_supported;
 
 /*
  * This stuff has dual use!
@@ -19,15 +19,15 @@
  */
 #define platform_name			"hpzx1"
 #define platform_setup			dig_setup
-#define platform_pci_dma_init		((ia64_mv_pci_dma_init *) machvec_noop)
-#define platform_pci_alloc_consistent	sba_alloc_consistent
-#define platform_pci_free_consistent	sba_free_consistent
-#define platform_pci_map_single		sba_map_single
-#define platform_pci_unmap_single	sba_unmap_single
-#define platform_pci_map_sg		sba_map_sg
-#define platform_pci_unmap_sg		sba_unmap_sg
-#define platform_pci_dma_sync_single	((ia64_mv_pci_dma_sync_single *) machvec_noop)
-#define platform_pci_dma_sync_sg	((ia64_mv_pci_dma_sync_sg *) machvec_noop)
-#define platform_pci_dma_supported	sba_dma_supported
+#define platform_dma_init		((ia64_mv_dma_init *) machvec_noop)
+#define platform_dma_alloc_coherent	sba_alloc_coherent
+#define platform_dma_free_coherent	sba_free_coherent
+#define platform_dma_map_single		sba_map_single
+#define platform_dma_unmap_single	sba_unmap_single
+#define platform_dma_map_sg		sba_map_sg
+#define platform_dma_unmap_sg		sba_unmap_sg
+#define platform_dma_sync_single	((ia64_mv_dma_sync_single *) machvec_memory_fence)
+#define platform_dma_sync_sg		((ia64_mv_dma_sync_sg *) machvec_memory_fence)
+#define platform_dma_supported		sba_dma_supported
 
 #endif /* _ASM_IA64_MACHVEC_HPZX1_h */
diff -urN linux-2.5.69-bk6/include/asm-ia64/machvec_init.h linux-2.5.69-bk7/include/asm-ia64/machvec_init.h
--- linux-2.5.69-bk6/include/asm-ia64/machvec_init.h	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/machvec_init.h	2003-05-12 04:43:30.000000000 -0700
@@ -1,7 +1,3 @@
-#define __MACHVEC_HDR(n)		<asm/machvec_##n##.h>
-#define __MACHVEC_EXPAND(n)		__MACHVEC_HDR(n)
-#define MACHVEC_PLATFORM_HEADER		__MACHVEC_EXPAND(MACHVEC_PLATFORM_NAME)
-
 #include <asm/machvec.h>
 
 extern ia64_mv_send_ipi_t ia64_send_ipi;
@@ -16,6 +12,10 @@
 extern ia64_mv_outb_t __ia64_outb;
 extern ia64_mv_outw_t __ia64_outw;
 extern ia64_mv_outl_t __ia64_outl;
+extern ia64_mv_readb_t __ia64_readb;
+extern ia64_mv_readw_t __ia64_readw;
+extern ia64_mv_readl_t __ia64_readl;
+extern ia64_mv_readq_t __ia64_readq;
 
 #define MACHVEC_HELPER(name)									\
  struct ia64_machine_vector machvec_##name __attribute__ ((unused, __section__ (".machvec")))	\
diff -urN linux-2.5.69-bk6/include/asm-ia64/machvec_sn1.h linux-2.5.69-bk7/include/asm-ia64/machvec_sn1.h
--- linux-2.5.69-bk6/include/asm-ia64/machvec_sn1.h	2003-05-04 16:53:34.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/machvec_sn1.h	2003-05-12 04:43:30.000000000 -0700
@@ -44,14 +44,14 @@
 extern ia64_mv_outb_t sn1_outb;
 extern ia64_mv_outw_t sn1_outw;
 extern ia64_mv_outl_t sn1_outl;
-extern ia64_mv_pci_alloc_consistent	sn1_pci_alloc_consistent;
-extern ia64_mv_pci_free_consistent	sn1_pci_free_consistent;
-extern ia64_mv_pci_map_single		sn1_pci_map_single;
-extern ia64_mv_pci_unmap_single		sn1_pci_unmap_single;
-extern ia64_mv_pci_map_sg		sn1_pci_map_sg;
-extern ia64_mv_pci_unmap_sg		sn1_pci_unmap_sg;
-extern ia64_mv_pci_dma_sync_single	sn1_pci_dma_sync_single;
-extern ia64_mv_pci_dma_sync_sg		sn1_pci_dma_sync_sg;
+extern ia64_mv_dma_alloc_coherent	sn1_dma_alloc_coherent;
+extern ia64_mv_dma_free_coherent	sn1_dma_free_coherent;
+extern ia64_mv_dma_map_single		sn1_dma_map_single;
+extern ia64_mv_dma_unmap_single		sn1_dma_unmap_single;
+extern ia64_mv_dma_map_sg		sn1_dma_map_sg;
+extern ia64_mv_dma_unmap_sg		sn1_dma_unmap_sg;
+extern ia64_mv_dma_sync_single		sn1_dma_sync_single;
+extern ia64_mv_dma_sync_sg		sn1_dma_sync_sg;
 
 /*
  * This stuff has dual use!
@@ -72,14 +72,14 @@
 #define platform_outb		sn1_outb
 #define platform_outw		sn1_outw
 #define platform_outl		sn1_outl
-#define platform_pci_dma_init	machvec_noop
-#define platform_pci_alloc_consistent	sn1_pci_alloc_consistent
-#define platform_pci_free_consistent	sn1_pci_free_consistent
-#define platform_pci_map_single		sn1_pci_map_single
-#define platform_pci_unmap_single	sn1_pci_unmap_single
-#define platform_pci_map_sg		sn1_pci_map_sg
-#define platform_pci_unmap_sg		sn1_pci_unmap_sg
-#define platform_pci_dma_sync_single	sn1_pci_dma_sync_single
-#define platform_pci_dma_sync_sg	sn1_pci_dma_sync_sg
+#define platform_dma_init	machvec_noop
+#define platform_dma_alloc_coherent	sn1_dma_alloc_coherent
+#define platform_dma_free_coherent	sn1_dma_free_coherent
+#define platform_dma_map_single		sn1_dma_map_single
+#define platform_dma_unmap_single	sn1_dma_unmap_single
+#define platform_dma_map_sg		sn1_dma_map_sg
+#define platform_dma_unmap_sg		sn1_dma_unmap_sg
+#define platform_dma_sync_single	sn1_dma_sync_single
+#define platform_dma_sync_sg		sn1_dma_sync_sg
 
 #endif /* _ASM_IA64_MACHVEC_SN1_h */
diff -urN linux-2.5.69-bk6/include/asm-ia64/machvec_sn2.h linux-2.5.69-bk7/include/asm-ia64/machvec_sn2.h
--- linux-2.5.69-bk6/include/asm-ia64/machvec_sn2.h	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/machvec_sn2.h	2003-05-12 04:43:30.000000000 -0700
@@ -51,15 +51,15 @@
 extern ia64_mv_readw_t __sn_readw;
 extern ia64_mv_readl_t __sn_readl;
 extern ia64_mv_readq_t __sn_readq;
-extern ia64_mv_pci_alloc_consistent	sn_pci_alloc_consistent;
-extern ia64_mv_pci_free_consistent	sn_pci_free_consistent;
-extern ia64_mv_pci_map_single		sn_pci_map_single;
-extern ia64_mv_pci_unmap_single		sn_pci_unmap_single;
-extern ia64_mv_pci_map_sg		sn_pci_map_sg;
-extern ia64_mv_pci_unmap_sg		sn_pci_unmap_sg;
-extern ia64_mv_pci_dma_sync_single	sn_pci_dma_sync_single;
-extern ia64_mv_pci_dma_sync_sg		sn_pci_dma_sync_sg;
-extern ia64_mv_pci_dma_supported	sn_pci_dma_supported;
+extern ia64_mv_dma_alloc_coherent	sn_dma_alloc_coherent;
+extern ia64_mv_dma_free_coherent	sn_dma_free_coherent;
+extern ia64_mv_dma_map_single		sn_dma_map_single;
+extern ia64_mv_dma_unmap_single		sn_dma_unmap_single;
+extern ia64_mv_dma_map_sg		sn_dma_map_sg;
+extern ia64_mv_dma_unmap_sg		sn_dma_unmap_sg;
+extern ia64_mv_dma_sync_single		sn_dma_sync_single;
+extern ia64_mv_dma_sync_sg		sn_dma_sync_sg;
+extern ia64_mv_dma_supported		sn_dma_supported;
 
 /*
  * This stuff has dual use!
@@ -88,15 +88,15 @@
 #define platform_irq_desc		sn_irq_desc
 #define platform_irq_to_vector		sn_irq_to_vector
 #define platform_local_vector_to_irq	sn_local_vector_to_irq
-#define platform_pci_dma_init		machvec_noop
-#define platform_pci_alloc_consistent	sn_pci_alloc_consistent
-#define platform_pci_free_consistent	sn_pci_free_consistent
-#define platform_pci_map_single		sn_pci_map_single
-#define platform_pci_unmap_single	sn_pci_unmap_single
-#define platform_pci_map_sg		sn_pci_map_sg
-#define platform_pci_unmap_sg		sn_pci_unmap_sg
-#define platform_pci_dma_sync_single	sn_pci_dma_sync_single
-#define platform_pci_dma_sync_sg	sn_pci_dma_sync_sg
-#define platform_pci_dma_supported	sn_pci_dma_supported
+#define platform_dma_init		machvec_noop
+#define platform_dma_alloc_coherent	sn_dma_alloc_coherent
+#define platform_dma_free_coherent	sn_dma_free_coherent
+#define platform_dma_map_single		sn_dma_map_single
+#define platform_dma_unmap_single	sn_dma_unmap_single
+#define platform_dma_map_sg		sn_dma_map_sg
+#define platform_dma_unmap_sg		sn_dma_unmap_sg
+#define platform_dma_sync_single	sn_dma_sync_single
+#define platform_dma_sync_sg		sn_dma_sync_sg
+#define platform_dma_supported		sn_dma_supported
 
 #endif /* _ASM_IA64_MACHVEC_SN2_H */
diff -urN linux-2.5.69-bk6/include/asm-ia64/mca.h linux-2.5.69-bk7/include/asm-ia64/mca.h
--- linux-2.5.69-bk6/include/asm-ia64/mca.h	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/mca.h	2003-05-12 04:43:30.000000000 -0700
@@ -11,7 +11,10 @@
 #define _ASM_IA64_MCA_H
 
 #if !defined(__ASSEMBLY__)
+
+#include <linux/interrupt.h>
 #include <linux/types.h>
+
 #include <asm/param.h>
 #include <asm/sal.h>
 #include <asm/processor.h>
@@ -129,10 +132,10 @@
 extern void ia64_mca_ucmc_handler(void);
 extern void ia64_monarch_init_handler(void);
 extern void ia64_slave_init_handler(void);
-extern void ia64_mca_rendez_int_handler(int,void *,struct pt_regs *);
-extern void ia64_mca_wakeup_int_handler(int,void *,struct pt_regs *);
-extern void ia64_mca_cmc_int_handler(int,void *,struct pt_regs *);
-extern void ia64_mca_cpe_int_handler(int,void *,struct pt_regs *);
+extern irqreturn_t ia64_mca_rendez_int_handler(int,void *,struct pt_regs *);
+extern irqreturn_t ia64_mca_wakeup_int_handler(int,void *,struct pt_regs *);
+extern irqreturn_t ia64_mca_cmc_int_handler(int,void *,struct pt_regs *);
+extern irqreturn_t ia64_mca_cpe_int_handler(int,void *,struct pt_regs *);
 extern int  ia64_log_print(int,prfunc_t);
 extern void ia64_mca_cmc_vector_setup(void);
 extern int  ia64_mca_check_errors(void);
diff -urN linux-2.5.69-bk6/include/asm-ia64/page.h linux-2.5.69-bk7/include/asm-ia64/page.h
--- linux-2.5.69-bk6/include/asm-ia64/page.h	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/page.h	2003-05-12 04:43:30.000000000 -0700
@@ -37,6 +37,8 @@
 
 # if defined(CONFIG_HUGETLB_PAGE_SIZE_4GB)
 #  define HPAGE_SHIFT	32
+# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1GB)
+#  define HPAGE_SHIFT	30
 # elif defined(CONFIG_HUGETLB_PAGE_SIZE_256MB)
 #  define HPAGE_SHIFT	28
 # elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB)
@@ -89,7 +91,12 @@
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
 #ifndef CONFIG_DISCONTIGMEM
-#define pfn_valid(pfn)		((pfn) < max_mapnr)
+# ifdef CONFIG_VIRTUAL_MEM_MAP
+   extern int ia64_pfn_valid (unsigned long pfn);
+#  define pfn_valid(pfn)	(((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
+# else
+#  define pfn_valid(pfn)	((pfn) < max_mapnr)
+# endif
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 #define page_to_pfn(page)	((unsigned long) (page - mem_map))
 #define pfn_to_page(pfn)	(mem_map + (pfn))
diff -urN linux-2.5.69-bk6/include/asm-ia64/pal.h linux-2.5.69-bk7/include/asm-ia64/pal.h
--- linux-2.5.69-bk6/include/asm-ia64/pal.h	2003-05-04 16:53:34.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/pal.h	2003-05-12 04:43:30.000000000 -0700
@@ -622,7 +622,8 @@
 	u64	pmsa_xip;		/* previous iip		   */
 	u64	pmsa_xpsr;		/* previous psr		   */
 	u64	pmsa_xfs;		/* previous ifs		   */
-	u64	pmsa_reserved[71];	/* pal_min_state_area should total to 1KB */
+	u64	pmsa_br1;		/* branch register 1	   */
+	u64	pmsa_reserved[70];	/* pal_min_state_area should total to 1KB */
 } pal_min_state_area_t;
 
 
diff -urN linux-2.5.69-bk6/include/asm-ia64/pci.h linux-2.5.69-bk7/include/asm-ia64/pci.h
--- linux-2.5.69-bk6/include/asm-ia64/pci.h	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/pci.h	2003-05-12 04:43:30.000000000 -0700
@@ -47,18 +47,7 @@
 #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.
- */
-#define pci_alloc_consistent		platform_pci_alloc_consistent
-#define pci_free_consistent		platform_pci_free_consistent
-#define pci_map_single			platform_pci_map_single
-#define pci_unmap_single		platform_pci_unmap_single
-#define pci_map_sg			platform_pci_map_sg
-#define pci_unmap_sg			platform_pci_unmap_sg
-#define pci_dma_sync_single		platform_pci_dma_sync_single
-#define pci_dma_sync_sg			platform_pci_dma_sync_sg
-#define pci_dma_supported		platform_pci_dma_supported
+#include <asm-generic/pci-dma-compat.h>
 
 /* pci_unmap_{single,page} is not a nop, thus... */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
@@ -74,18 +63,12 @@
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
 	(((PTR)->LEN_NAME) = (VAL))
 
-#define pci_map_page(dev,pg,off,size,dir)				\
-	pci_map_single((dev), page_address(pg) + (off), (size), (dir))
-#define pci_unmap_page(dev,dma_addr,size,dir)				\
-	pci_unmap_single((dev), (dma_addr), (size), (dir))
-
 /* The ia64 platform always supports 64-bit addressing. */
-#define pci_dac_dma_supported(pci_dev, mask)	(1)
-
-#define pci_dac_page_to_dma(dev,pg,off,dir)	((dma_addr_t) page_to_bus(pg) + (off))
-#define pci_dac_dma_to_page(dev,dma_addr)	(virt_to_page(bus_to_virt(dma_addr)))
-#define pci_dac_dma_to_offset(dev,dma_addr)	((dma_addr) & ~PAGE_MASK)
-#define pci_dac_dma_sync_single(dev,dma_addr,len,dir)	do { /* nothing */ } while (0)
+#define pci_dac_dma_supported(pci_dev, mask)		(1)
+#define pci_dac_page_to_dma(dev,pg,off,dir)		((dma_addr_t) page_to_bus(pg) + (off))
+#define pci_dac_dma_to_page(dev,dma_addr)		(virt_to_page(bus_to_virt(dma_addr)))
+#define pci_dac_dma_to_offset(dev,dma_addr)		((dma_addr) & ~PAGE_MASK)
+#define pci_dac_dma_sync_single(dev,dma_addr,len,dir)	do { mb(); } while (0)
 
 /* Return the index of the PCI controller for device PDEV. */
 #define pci_controller_num(PDEV)	(0)
@@ -97,12 +80,18 @@
 extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
 				enum pci_mmap_state mmap_state, int write_combine);
 
+struct pci_window {
+	struct resource resource;
+	u64 offset;
+};
+
 struct pci_controller {
 	void *acpi_handle;
 	void *iommu;
 	int segment;
 
-	u64 mem_offset;
+	unsigned int windows;
+	struct pci_window *window;
 };
 
 #define PCI_CONTROLLER(busdev) ((struct pci_controller *) busdev->sysdata)
diff -urN linux-2.5.69-bk6/include/asm-ia64/percpu.h linux-2.5.69-bk7/include/asm-ia64/percpu.h
--- linux-2.5.69-bk6/include/asm-ia64/percpu.h	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/percpu.h	2003-05-12 04:43:30.000000000 -0700
@@ -5,7 +5,7 @@
 #include <linux/compiler.h>
 
 /*
- * Copyright (C) 2002 Hewlett-Packard Co
+ * Copyright (C) 2002-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
@@ -35,6 +35,8 @@
 #define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(var##__per_cpu)
 #define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(var##__per_cpu)
 
+extern void setup_per_cpu_areas (void);
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _ASM_IA64_PERCPU_H */
diff -urN linux-2.5.69-bk6/include/asm-ia64/perfmon.h linux-2.5.69-bk7/include/asm-ia64/perfmon.h
--- linux-2.5.69-bk6/include/asm-ia64/perfmon.h	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/perfmon.h	2003-05-12 04:43:30.000000000 -0700
@@ -41,6 +41,7 @@
 #define PFM_FL_NOTIFY_BLOCK    	 0x04	/* block task on user level notifications */
 #define PFM_FL_SYSTEM_WIDE	 0x08	/* create a system wide context */
 #define PFM_FL_EXCL_IDLE         0x20   /* exclude idle task from system wide session */
+#define PFM_FL_UNSECURE		 0x40   /* allow unsecure monitoring for non self-monitoring task */
 
 /*
  * PMC flags
@@ -125,7 +126,7 @@
  * Define the version numbers for both perfmon as a whole and the sampling buffer format.
  */
 #define PFM_VERSION_MAJ		1U
-#define PFM_VERSION_MIN		3U
+#define PFM_VERSION_MIN		4U
 #define PFM_VERSION		(((PFM_VERSION_MAJ&0xffff)<<16)|(PFM_VERSION_MIN & 0xffff))
 
 #define PFM_SMPL_VERSION_MAJ	1U
diff -urN linux-2.5.69-bk6/include/asm-ia64/processor.h linux-2.5.69-bk7/include/asm-ia64/processor.h
--- linux-2.5.69-bk6/include/asm-ia64/processor.h	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/processor.h	2003-05-12 04:43:30.000000000 -0700
@@ -39,6 +39,14 @@
 #define TASK_SIZE		(current->thread.task_size)
 
 /*
+ * MM_VM_SIZE(mm) gives the maximum address (plus 1) which may contain a mapping for
+ * address-space MM.  Note that with 32-bit tasks, this is still DEFAULT_TASK_SIZE,
+ * because the kernel may have installed helper-mappings above TASK_SIZE.  For example,
+ * for x86 emulation, the LDT and GDT are mapped above TASK_SIZE.
+ */
+#define MM_VM_SIZE(mm)		DEFAULT_TASK_SIZE
+
+/*
  * This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
@@ -291,7 +299,7 @@
 
 #define start_thread(regs,new_ip,new_sp) do {							\
 	set_fs(USER_DS);									\
-	regs->cr_ipsr = ((regs->cr_ipsr | (IA64_PSR_BITS_TO_SET | IA64_PSR_CPL | IA64_PSR_SP))	\
+	regs->cr_ipsr = ((regs->cr_ipsr | (IA64_PSR_BITS_TO_SET | IA64_PSR_CPL))		\
 			 & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_RI | IA64_PSR_IS));		\
 	regs->cr_iip = new_ip;									\
 	regs->ar_rsc = 0xf;		/* eager mode, privilege level 3 */			\
diff -urN linux-2.5.69-bk6/include/asm-ia64/ptrace.h linux-2.5.69-bk7/include/asm-ia64/ptrace.h
--- linux-2.5.69-bk6/include/asm-ia64/ptrace.h	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/ptrace.h	2003-05-12 04:43:30.000000000 -0700
@@ -227,8 +227,10 @@
   })
 
   struct task_struct;			/* forward decl */
+  struct unw_frame_info;		/* forward decl */
 
   extern void show_regs (struct pt_regs *);
+  extern void ia64_do_show_stack (struct unw_frame_info *, void *);
   extern unsigned long ia64_get_user_rbs_end (struct task_struct *, struct pt_regs *,
 					      unsigned long *);
   extern long ia64_peek (struct task_struct *, struct switch_stack *, unsigned long,
diff -urN linux-2.5.69-bk6/include/asm-ia64/sal.h linux-2.5.69-bk7/include/asm-ia64/sal.h
--- linux-2.5.69-bk6/include/asm-ia64/sal.h	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/sal.h	2003-05-12 04:43:30.000000000 -0700
@@ -226,7 +226,7 @@
 
 /* Encodings for machine check parameter types */
 enum {
-	SAL_MC_PARAM_RENDEZ_INT    = 1,	/* Rendezevous interrupt */
+	SAL_MC_PARAM_RENDEZ_INT    = 1,	/* Rendezvous interrupt */
 	SAL_MC_PARAM_RENDEZ_WAKEUP = 2,	/* Wakeup */
 	SAL_MC_PARAM_CPE_INT	   = 3	/* Corrected Platform Error Int */
 };
diff -urN linux-2.5.69-bk6/include/asm-ia64/serial.h linux-2.5.69-bk7/include/asm-ia64/serial.h
--- linux-2.5.69-bk6/include/asm-ia64/serial.h	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/serial.h	2003-05-12 04:43:30.000000000 -0700
@@ -59,7 +59,6 @@
 	{ 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },	/* ttyS2 */	\
 	{ 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },	/* ttyS3 */
 
-
 #ifdef CONFIG_SERIAL_MANY_PORTS
 #define EXTRA_SERIAL_PORT_DEFNS			\
 	{ 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, 	/* ttyS4 */	\
diff -urN linux-2.5.69-bk6/include/asm-ia64/spinlock.h linux-2.5.69-bk7/include/asm-ia64/spinlock.h
--- linux-2.5.69-bk6/include/asm-ia64/spinlock.h	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/spinlock.h	2003-05-12 04:43:30.000000000 -0700
@@ -22,26 +22,72 @@
 #define SPIN_LOCK_UNLOCKED			(spinlock_t) { 0 }
 #define spin_lock_init(x)			((x)->lock = 0)
 
-#define DEBUG_SPIN_LOCK	0
+#define NEW_LOCK
+#ifdef NEW_LOCK
 
-#if DEBUG_SPIN_LOCK
+/*
+ * Try to get the lock.  If we fail to get the lock, make a non-standard call to
+ * ia64_spinlock_contention().  We do not use a normal call because that would force all
+ * callers of spin_lock() to be non-leaf routines.  Instead, ia64_spinlock_contention() is
+ * carefully coded to touch only those registers that spin_lock() marks "clobbered".
+ */
 
-#include <ia64intrin.h>
-
-#define _raw_spin_lock(x)								\
-do {											\
-	unsigned long _timeout = 1000000000;						\
-	volatile unsigned int _old = 0, _new = 1, *_ptr = &((x)->lock);			\
-	do {										\
-		if (_timeout-- == 0) {							\
-			extern void dump_stack (void);					\
-			printk("kernel DEADLOCK at %s:%d?\n", __FILE__, __LINE__);	\
-			dump_stack();							\
-		}									\
-	} while (__sync_val_compare_and_swap(_ptr, _old, _new) != _old);		\
-} while (0)
+#define IA64_SPINLOCK_CLOBBERS "ar.pfs", "p14", "r28", "r29", "r30", "b6", "memory"
 
+static inline void
+_raw_spin_lock (spinlock_t *lock)
+{
+	register volatile unsigned int *ptr asm ("r31") = &lock->lock;
+
+#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
+# ifdef CONFIG_ITANIUM
+	/* don't use brl on Itanium... */
+	asm volatile ("{\n\t"
+		      "  mov ar.ccv = r0\n\t"
+		      "  mov r28 = ip\n\t"
+		      "  mov r30 = 1;;\n\t"
+		      "}\n\t"
+		      "cmpxchg4.acq r30 = [%1], r30, ar.ccv\n\t"
+		      "movl r29 = ia64_spinlock_contention_pre3_4;;\n\t"
+		      "cmp4.ne p14, p0 = r30, r0\n\t"
+		      "mov b6 = r29;;\n"
+		      "(p14) br.cond.spnt.many b6"
+		      : "=r"(ptr) : "r"(ptr) : IA64_SPINLOCK_CLOBBERS);
+# else
+	asm volatile ("{\n\t"
+		      "  mov ar.ccv = r0\n\t"
+		      "  mov r28 = ip\n\t"
+		      "  mov r30 = 1;;\n\t"
+		      "}\n\t"
+		      "cmpxchg4.acq r30 = [%1], r30, ar.ccv;;\n\t"
+		      "cmp4.ne p14, p0 = r30, r0\n"
+		      "(p14) brl.cond.spnt.many ia64_spinlock_contention_pre3_4"
+		      : "=r"(ptr) : "r"(ptr) : IA64_SPINLOCK_CLOBBERS);
+# endif /* CONFIG_MCKINLEY */
 #else
+# ifdef CONFIG_ITANIUM
+	/* don't use brl on Itanium... */
+	/* mis-declare, so we get the entry-point, not it's function descriptor: */
+	asm volatile ("mov r30 = 1\n\t"
+		      "mov ar.ccv = r0;;\n\t"
+		      "cmpxchg4.acq r30 = [%0], r30, ar.ccv\n\t"
+		      "movl r29 = ia64_spinlock_contention;;\n\t"
+		      "cmp4.ne p14, p0 = r30, r0\n\t"
+		      "mov b6 = r29;;\n"
+		      "(p14) br.call.spnt.many b6 = b6"
+		      : "=r"(ptr) : "r"(ptr) : IA64_SPINLOCK_CLOBBERS);
+# else
+	asm volatile ("mov r30 = 1\n\t"
+		      "mov ar.ccv = r0;;\n\t"
+		      "cmpxchg4.acq r30 = [%0], r30, ar.ccv;;\n\t"
+		      "cmp4.ne p14, p0 = r30, r0\n\t"
+		      "(p14) brl.call.spnt.many b6=ia64_spinlock_contention"
+		      : "=r"(ptr) : "r"(ptr) : IA64_SPINLOCK_CLOBBERS);
+# endif /* CONFIG_MCKINLEY */
+#endif
+}
+
+#else /* !NEW_LOCK */
 
 /*
  * Streamlined test_and_set_bit(0, (x)).  We use test-and-test-and-set
@@ -64,7 +110,7 @@
 	";;\n"							\
 	:: "r"(&(x)->lock) : "ar.ccv", "p7", "r2", "r29", "memory")
 
-#endif /* !DEBUG_SPIN_LOCK */
+#endif /* !NEW_LOCK */
 
 #define spin_is_locked(x)	((x)->lock != 0)
 #define _raw_spin_unlock(x)	do { barrier(); ((spinlock_t *) x)->lock = 0; } while (0)
@@ -72,43 +118,31 @@
 #define spin_unlock_wait(x)	do { barrier(); } while ((x)->lock)
 
 typedef struct {
-	volatile int read_counter:31;
-	volatile int write_lock:1;
+	volatile int read_counter	: 31;
+	volatile int write_lock		:  1;
 } rwlock_t;
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
 
 #define rwlock_init(x)		do { *(x) = RW_LOCK_UNLOCKED; } while(0)
 #define rwlock_is_locked(x)	(*(volatile int *) (x) != 0)
 
-#define _raw_read_lock(rw)							\
-do {										\
-	int __read_lock_tmp = 0;						\
-	__asm__ __volatile__ ("1:\tfetchadd4.acq %0 = [%1], 1\n"		\
-			      ";;\n"						\
-			      "tbit.nz p6,p0 = %0, 31\n"			\
-			      "(p6) br.cond.sptk.few 2f\n"			\
-			      ".section .text.lock,\"ax\"\n"			\
-			      "2:\tfetchadd4.rel %0 = [%1], -1\n"		\
-			      ";;\n"						\
-			      "3:\tld4.acq %0 = [%1]\n"				\
-			      ";;\n"						\
-			      "tbit.nz p6,p0 = %0, 31\n"			\
-			      "(p6) br.cond.sptk.few 3b\n"			\
-			      "br.cond.sptk.few 1b\n"				\
-			      ";;\n"						\
-			      ".previous\n"					\
-			      : "=&r" (__read_lock_tmp)				\
-			      : "r" (rw) : "p6", "memory");			\
-} while(0)
+#define _raw_read_lock(rw)								\
+do {											\
+	rwlock_t *__read_lock_ptr = (rw);						\
+											\
+	while (unlikely(ia64_fetchadd(1, (int *) __read_lock_ptr, "acq") < 0)) {	\
+		ia64_fetchadd(-1, (int *) __read_lock_ptr, "rel");			\
+		while (*(volatile int *)__read_lock_ptr < 0)				\
+			barrier();							\
+											\
+	}										\
+} while (0)
 
-#define _raw_read_unlock(rw)							\
-do {										\
-	int __read_unlock_tmp = 0;						\
-	__asm__ __volatile__ ("fetchadd4.rel %0 = [%1], -1\n"			\
-			      : "=r" (__read_unlock_tmp)			\
-			      : "r" (rw)					\
-			      : "memory");					\
-} while(0)
+#define _raw_read_unlock(rw)					\
+do {								\
+	rwlock_t *__read_lock_ptr = (rw);			\
+	ia64_fetchadd(-1, (int *) __read_lock_ptr, "rel");	\
+} while (0)
 
 #define _raw_write_lock(rw)							\
 do {										\
diff -urN linux-2.5.69-bk6/include/asm-ia64/system.h linux-2.5.69-bk7/include/asm-ia64/system.h
--- linux-2.5.69-bk6/include/asm-ia64/system.h	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/system.h	2003-05-12 04:43:30.000000000 -0700
@@ -212,48 +212,39 @@
 # define PERFMON_IS_SYSWIDE() (0)
 #endif
 
-#define __switch_to(prev,next,last) do {						\
-	if (((prev)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID))	\
-	    || IS_IA32_PROCESS(ia64_task_regs(prev)) || PERFMON_IS_SYSWIDE())		\
-		ia64_save_extra(prev);							\
-	if (((next)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID))	\
-	    || IS_IA32_PROCESS(ia64_task_regs(next)) || PERFMON_IS_SYSWIDE())		\
-		ia64_load_extra(next);							\
-	(last) = ia64_switch_to((next));						\
+#define IA64_HAS_EXTRA_STATE(t)							\
+	((t)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID)	\
+	 || IS_IA32_PROCESS(ia64_task_regs(t)) || PERFMON_IS_SYSWIDE())
+
+#define __switch_to(prev,next,last) do {							 \
+	struct task_struct *__fpu_owner = ia64_get_fpu_owner();					 \
+	if (IA64_HAS_EXTRA_STATE(prev))								 \
+		ia64_save_extra(prev);								 \
+	if (IA64_HAS_EXTRA_STATE(next))								 \
+		ia64_load_extra(next);								 \
+	ia64_psr(ia64_task_regs(next))->dfh =							 \
+		!(__fpu_owner == (next) && ((next)->thread.last_fph_cpu == smp_processor_id())); \
+	(last) = ia64_switch_to((next));							 \
 } while (0)
 
 #ifdef CONFIG_SMP
-
 /*
- * In the SMP case, we save the fph state when context-switching
- * away from a thread that modified fph.  This way, when the thread
- * gets scheduled on another CPU, the CPU can pick up the state from
- * task->thread.fph, avoiding the complication of having to fetch
- * the latest fph state from another CPU.
+ * In the SMP case, we save the fph state when context-switching away from a thread that
+ * modified fph.  This way, when the thread gets scheduled on another CPU, the CPU can
+ * pick up the state from task->thread.fph, avoiding the complication of having to fetch
+ * the latest fph state from another CPU.  In other words: eager save, lazy restore.
  */
-# define switch_to(prev,next,last) do {					\
-	if (ia64_psr(ia64_task_regs(prev))->mfh) {			\
-		ia64_psr(ia64_task_regs(prev))->mfh = 0;		\
-		(prev)->thread.flags |= IA64_THREAD_FPH_VALID;		\
-		__ia64_save_fpu((prev)->thread.fph);			\
-		(prev)->thread.last_fph_cpu = smp_processor_id();	\
-	}								\
-	if ((next)->thread.flags & IA64_THREAD_FPH_VALID) {		\
-		if (((next)->thread.last_fph_cpu == smp_processor_id())	\
-		    && (ia64_get_fpu_owner() == next))			\
-		{							\
-			ia64_psr(ia64_task_regs(next))->dfh = 0;	\
-			ia64_psr(ia64_task_regs(next))->mfh = 0;	\
-		} else							\
-			ia64_psr(ia64_task_regs(next))->dfh = 1;	\
-	}								\
-	__switch_to(prev,next,last);					\
-  } while (0)
-#else
 # define switch_to(prev,next,last) do {						\
-	ia64_psr(ia64_task_regs(next))->dfh = (ia64_get_fpu_owner() != (next));	\
-	__switch_to(prev,next,last);						\
+	if (ia64_psr(ia64_task_regs(prev))->mfh) {				\
+		ia64_psr(ia64_task_regs(prev))->mfh = 0;			\
+		(prev)->thread.flags |= IA64_THREAD_FPH_VALID;			\
+		__ia64_save_fpu((prev)->thread.fph);				\
+		(prev)->thread.last_fph_cpu = smp_processor_id();		\
+	}									\
+	__switch_to(prev, next, last);						\
 } while (0)
+#else
+# define switch_to(prev,next,last)	__switch_to(prev, next, last)
 #endif
 
 /*
diff -urN linux-2.5.69-bk6/include/asm-ia64/uaccess.h linux-2.5.69-bk7/include/asm-ia64/uaccess.h
--- linux-2.5.69-bk6/include/asm-ia64/uaccess.h	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/uaccess.h	2003-05-12 04:43:30.000000000 -0700
@@ -8,7 +8,7 @@
  * addresses.  Thus, we need to be careful not to let the user to
  * trick us into accessing kernel memory that would normally be
  * inaccessible.  This code is also fairly performance sensitive,
- * so we want to spend as little time doing saftey checks as
+ * so we want to spend as little time doing safety checks as
  * possible.
  *
  * To make matters a bit more interesting, these macros sometimes also
diff -urN linux-2.5.69-bk6/include/asm-ia64/unwind.h linux-2.5.69-bk7/include/asm-ia64/unwind.h
--- linux-2.5.69-bk6/include/asm-ia64/unwind.h	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk7/include/asm-ia64/unwind.h	2003-05-12 04:43:30.000000000 -0700
@@ -2,8 +2,8 @@
 #define _ASM_IA64_UNWIND_H
 
 /*
- * Copyright (C) 1999-2000 Hewlett-Packard Co
- * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999-2000, 2003 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * A simple API for unwinding kernel stacks.  This is used for
  * debugging and error reporting purposes.  The kernel doesn't need
@@ -107,6 +107,13 @@
  */
 extern void unw_init_from_blocked_task (struct unw_frame_info *info, struct task_struct *t);
 
+/*
+ * Prepare to unwind from interruption.  The pt-regs and switch-stack structures must have
+ * be "adjacent" (no state modifications between pt-regs and switch-stack).
+ */
+extern void unw_init_from_interruption (struct unw_frame_info *info, struct task_struct *t,
+					struct pt_regs *pt, struct switch_stack *sw);
+
 extern void unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t,
 				 struct switch_stack *sw);
 
diff -urN linux-2.5.69-bk6/include/linux/agp_backend.h linux-2.5.69-bk7/include/linux/agp_backend.h
--- linux-2.5.69-bk6/include/linux/agp_backend.h	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk7/include/linux/agp_backend.h	2003-05-12 04:43:30.000000000 -0700
@@ -1,5 +1,6 @@
 /*
- * AGPGART module version 0.99
+ * AGPGART module version 0.100
+ * Copyright (C) 2002-2003 Dave Jones
  * Copyright (C) 1999 Jeff Hartmann
  * Copyright (C) 1999 Precision Insight, Inc.
  * Copyright (C) 1999 Xi Graphics, Inc.
@@ -37,45 +38,7 @@
 
 enum chipset_type {
 	NOT_SUPPORTED,
-	INTEL_GENERIC,
-	INTEL_LX,
-	INTEL_BX,
-	INTEL_GX,
-	INTEL_I810,
-	INTEL_I815,
-	INTEL_I820,
-	INTEL_I830_M,
-	INTEL_I845_G,
-	INTEL_I855_PM,
-	INTEL_I865_G,
-	INTEL_I840,
-	INTEL_I845,
-	INTEL_I850,
-	INTEL_I860,
-	INTEL_460GX,
-	INTEL_E7505,
-	VIA_GENERIC,
-	SIS_GENERIC,
-	AMD_GENERIC,
-	AMD_IRONGATE,
-	AMD_761,
-	AMD_762,
-	AMD_8151,
-	ALI_M1541,
-	ALI_M1621,
-	ALI_M1631,
-	ALI_M1632,
-	ALI_M1641,
-	ALI_M1644,
-	ALI_M1647,
-	ALI_M1651,
-	ALI_M1671,
-	ALI_GENERIC,
-	SVWRKS_HE,
-	SVWRKS_LE,
-	SVWRKS_GENERIC,
-	HP_ZX1,
-	ALPHA_CORE_AGP,
+	SUPPORTED,
 };
 
 struct agp_version {
@@ -98,16 +61,11 @@
 } agp_kern_info;
 
 /* 
- * The agp_memory structure has information
- * about the block of agp memory allocated.
- * A caller may manipulate the next and prev
- * pointers to link each allocated item into
- * a list.  These pointers are ignored by the 
- * backend.  Everything else should never be
- * written to, but the caller may read any of
- * the items to detrimine the status of this
- * block of agp memory.
- * 
+ * The agp_memory structure has information about the block of agp memory
+ * allocated.  A caller may manipulate the next and prev pointers to link
+ * each allocated item into a list.  These pointers are ignored by the backend.
+ * Everything else should never be written to, but the caller may read any of
+ * the items to detrimine the status of this block of agp memory. 
  */
 
 typedef struct _agp_memory {
@@ -127,126 +85,19 @@
 #define AGP_NORMAL_MEMORY 0
 
 extern void agp_free_memory(agp_memory *);
-
-/*
- * agp_free_memory :
- * 
- * This function frees memory associated with
- * an agp_memory pointer.  It is the only function
- * that can be called when the backend is not owned
- * by the caller.  (So it can free memory on client
- * death.)
- * 
- * It takes an agp_memory pointer as an argument.
- * 
- */
-
 extern agp_memory *agp_allocate_memory(size_t, u32);
-
-/*
- * agp_allocate_memory :
- * 
- * This function allocates a group of pages of
- * a certain type.
- * 
- * It takes a size_t argument of the number of pages, and
- * an u32 argument of the type of memory to be allocated.  
- * Every agp bridge device will allow you to allocate 
- * AGP_NORMAL_MEMORY which maps to physical ram.  Any other
- * type is device dependent.
- * 
- * It returns NULL whenever memory is unavailable.
- * 
- */
-
 extern int agp_copy_info(agp_kern_info *);
-
-/*
- * agp_copy_info :
- * 
- * This function copies information about the
- * agp bridge device and the state of the agp
- * backend into an agp_kern_info pointer.
- * 
- * It takes an agp_kern_info pointer as an
- * argument.  The caller should insure that
- * this pointer is valid.
- * 
- */
-
 extern int agp_bind_memory(agp_memory *, off_t);
-
-/*
- * agp_bind_memory :
- * 
- * This function binds an agp_memory structure
- * into the graphics aperture translation table.
- * 
- * It takes an agp_memory pointer and an offset into
- * the graphics aperture translation table as arguments
- * 
- * It returns -EINVAL if the pointer == NULL.
- * It returns -EBUSY if the area of the table
- * requested is already in use.
- * 
- */
-
 extern int agp_unbind_memory(agp_memory *);
-
-/* 
- * agp_unbind_memory :
- * 
- * This function removes an agp_memory structure
- * from the graphics aperture translation table.
- * 
- * It takes an agp_memory pointer as an argument.
- * 
- * It returns -EINVAL if this piece of agp_memory
- * is not currently bound to the graphics aperture
- * translation table or if the agp_memory 
- * pointer == NULL
- * 
- */
-
 extern void agp_enable(u32);
-
-/* 
- * agp_enable :
- * 
- * This function initializes the agp point-to-point
- * connection.
- * 
- * It takes an agp mode register as an argument
- * 
- */
-
 extern int agp_backend_acquire(void);
-
-/*
- * agp_backend_acquire :
- * 
- * This Function attempts to acquire the agp
- * backend.
- * 
- * returns -EBUSY if agp is in use,
- * returns 0 if the caller owns the agp backend
- */
-
 extern void agp_backend_release(void);
 
 /*
- * agp_backend_release :
- * 
- * This Function releases the lock on the agp
- * backend.
- * 
- * The caller must insure that the graphics
- * aperture translation table is read for use
- * by another entity.  (Ensure that all memory
- * it bound is unbound.)
- * 
+ * Interface between drm and agp code.  When agp initializes, it makes
+ * the below structure available via inter_module_register(), drm might
+ * use it.  Keith Owens <kaos@ocs.com.au> 28 Oct 2000.
  */
-
 typedef struct {
 	void       (*free_memory)(agp_memory *);
 	agp_memory *(*allocate_memory)(size_t, u32);
@@ -260,10 +111,4 @@
 
 extern const drm_agp_t *drm_agp_p;
 
-/*
- * Interface between drm and agp code.  When agp initializes, it makes
- * the above structure available via inter_module_register(), drm might
- * use it.  Keith Owens <kaos@ocs.com.au> 28 Oct 2000.
- */
-
 #endif				/* _AGP_BACKEND_H */
diff -urN linux-2.5.69-bk6/include/linux/agpgart.h linux-2.5.69-bk7/include/linux/agpgart.h
--- linux-2.5.69-bk6/include/linux/agpgart.h	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk7/include/linux/agpgart.h	2003-05-12 04:43:30.000000000 -0700
@@ -27,17 +27,19 @@
 #ifndef _AGP_H
 #define _AGP_H 1
 
+#include <linux/agp_backend.h>
+
 #define AGPIOC_BASE       'A'
-#define AGPIOC_INFO       _IOR (AGPIOC_BASE, 0, agp_info*)
+#define AGPIOC_INFO       _IOR (AGPIOC_BASE, 0, struct agp_info*)
 #define AGPIOC_ACQUIRE    _IO  (AGPIOC_BASE, 1)
 #define AGPIOC_RELEASE    _IO  (AGPIOC_BASE, 2)
-#define AGPIOC_SETUP      _IOW (AGPIOC_BASE, 3, agp_setup*)
-#define AGPIOC_RESERVE    _IOW (AGPIOC_BASE, 4, agp_region*)
-#define AGPIOC_PROTECT    _IOW (AGPIOC_BASE, 5, agp_region*)
-#define AGPIOC_ALLOCATE   _IOWR(AGPIOC_BASE, 6, agp_allocate*)
+#define AGPIOC_SETUP      _IOW (AGPIOC_BASE, 3, struct agp_setup*)
+#define AGPIOC_RESERVE    _IOW (AGPIOC_BASE, 4, struct agp_region*)
+#define AGPIOC_PROTECT    _IOW (AGPIOC_BASE, 5, struct agp_region*)
+#define AGPIOC_ALLOCATE   _IOWR(AGPIOC_BASE, 6, struct agp_allocate*)
 #define AGPIOC_DEALLOCATE _IOW (AGPIOC_BASE, 7, int)
-#define AGPIOC_BIND       _IOW (AGPIOC_BASE, 8, agp_bind*)
-#define AGPIOC_UNBIND     _IOW (AGPIOC_BASE, 9, agp_unbind*)
+#define AGPIOC_BIND       _IOW (AGPIOC_BASE, 8, struct agp_bind*)
+#define AGPIOC_UNBIND     _IOW (AGPIOC_BASE, 9, struct agp_unbind*)
 
 #define AGP_DEVICE      "/dev/agpgart"
 
@@ -112,19 +114,7 @@
 
 #define AGPGART_MINOR 175
 
-#define AGP_UNLOCK()      	up(&(agp_fe.agp_mutex));
-#define AGP_LOCK()    		down(&(agp_fe.agp_mutex));
-#define AGP_LOCK_INIT() 	sema_init(&(agp_fe.agp_mutex), 1)
-
-#ifndef _AGP_BACKEND_H
-struct _agp_version {
-	u16 major;
-	u16 minor;
-} agp_version;
-
-#endif
-
-typedef struct _agp_info {
+struct agp_info {
 	struct agp_version version;	/* version of the driver        */
 	u32 bridge_id;		/* bridge vendor/device         */
 	u32 agp_mode;		/* mode info of bridge          */
@@ -133,34 +123,34 @@
 	size_t pg_total;	/* max pages (swap + system)    */
 	size_t pg_system;	/* max pages (system)           */
 	size_t pg_used;		/* current pages used           */
-} agp_info;
+};
 
-typedef struct _agp_setup {
+struct agp_setup {
 	u32 agp_mode;		/* mode info of bridge          */
-} agp_setup;
+};
 
 /*
  * The "prot" down below needs still a "sleep" flag somehow ...
  */
-typedef struct _agp_segment {
+struct agp_segment {
 	off_t pg_start;		/* starting page to populate    */
 	size_t pg_count;	/* number of pages              */
 	int prot;		/* prot flags for mmap          */
-} agp_segment;
+};
 
-typedef struct _agp_segment_priv {
+struct agp_segment_priv {
 	off_t pg_start;
 	size_t pg_count;
 	pgprot_t prot;
-} agp_segment_priv;
+};
 
-typedef struct _agp_region {
+struct agp_region {
 	pid_t pid;		/* pid of process               */
 	size_t seg_count;	/* number of segments           */
-	struct _agp_segment *seg_list;
-} agp_region;
+	struct agp_segment *seg_list;
+};
 
-typedef struct _agp_allocate {
+struct agp_allocate {
 	int key;		/* tag of allocation            */
 	size_t pg_count;	/* number of pages              */
 	u32 type;		/* 0 == normal, other devspec   */
@@ -168,34 +158,34 @@
 				 * need a phys address of the     
 				 * actual page behind the gatt    
 				 * table)                        */
-} agp_allocate;
+};
 
-typedef struct _agp_bind {
+struct agp_bind {
 	int key;		/* tag of allocation            */
 	off_t pg_start;		/* starting page to populate    */
-} agp_bind;
+};
 
-typedef struct _agp_unbind {
+struct agp_unbind {
 	int key;		/* tag of allocation            */
 	u32 priority;		/* priority for paging out      */
-} agp_unbind;
+};
 
-typedef struct _agp_client {
-	struct _agp_client *next;
-	struct _agp_client *prev;
+struct agp_client {
+	struct agp_client *next;
+	struct agp_client *prev;
 	pid_t pid;
 	int num_segments;
-	agp_segment_priv **segments;
-} agp_client;
+	struct agp_segment_priv **segments;
+};
 
-typedef struct _agp_controller {
-	struct _agp_controller *next;
-	struct _agp_controller *prev;
+struct agp_controller {
+	struct agp_controller *next;
+	struct agp_controller *prev;
 	pid_t pid;
 	int num_clients;
 	agp_memory *pool;
-	agp_client *clients;
-} agp_controller;
+	struct agp_client *clients;
+};
 
 #define AGP_FF_ALLOW_CLIENT		0
 #define AGP_FF_ALLOW_CONTROLLER 	1
@@ -203,18 +193,18 @@
 #define AGP_FF_IS_CONTROLLER		3
 #define AGP_FF_IS_VALID 		4
 
-typedef struct _agp_file_private {
-	struct _agp_file_private *next;
-	struct _agp_file_private *prev;
+struct agp_file_private {
+	struct agp_file_private *next;
+	struct agp_file_private *prev;
 	pid_t my_pid;
 	long access_flags;	/* long req'd for set_bit --RR */
-} agp_file_private;
+};
 
 struct agp_front_data {
 	struct semaphore agp_mutex;
-	agp_controller *current_controller;
-	agp_controller *controllers;
-	agp_file_private *file_priv_list;
+	struct agp_controller *current_controller;
+	struct agp_controller *controllers;
+	struct agp_file_private *file_priv_list;
 	u8 used_by_controller;
 	u8 backend_acquired;
 };
diff -urN linux-2.5.69-bk6/include/linux/efi.h linux-2.5.69-bk7/include/linux/efi.h
--- linux-2.5.69-bk6/include/linux/efi.h	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk7/include/linux/efi.h	2003-05-12 04:43:30.000000000 -0700
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1999 VA Linux Systems
  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 1999, 2002 Hewlett-Packard Co.
+ * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co.
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *	Stephane Eranian <eranian@hpl.hp.com>
  */
@@ -21,12 +21,12 @@
 #include <asm/system.h>
 
 #define EFI_SUCCESS		0
-#define EFI_LOAD_ERROR          (1L | (1L << 63))
-#define EFI_INVALID_PARAMETER	(2L | (1L << 63))
-#define EFI_UNSUPPORTED		(3L | (1L << 63))
-#define EFI_BAD_BUFFER_SIZE     (4L | (1L << 63))
-#define EFI_BUFFER_TOO_SMALL	(5L | (1L << 63))
-#define EFI_NOT_FOUND          (14L | (1L << 63))
+#define EFI_LOAD_ERROR          ( 1 | (1UL << 63))
+#define EFI_INVALID_PARAMETER	( 2 | (1UL << 63))
+#define EFI_UNSUPPORTED		( 3 | (1UL << 63))
+#define EFI_BAD_BUFFER_SIZE     ( 4 | (1UL << 63))
+#define EFI_BUFFER_TOO_SMALL	( 5 | (1UL << 63))
+#define EFI_NOT_FOUND		(14 | (1UL << 63))
 
 typedef unsigned long efi_status_t;
 typedef u8 efi_bool_t;
@@ -260,7 +260,7 @@
 extern void efi_init (void);
 extern void efi_map_pal_code (void);
 extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
-extern void efi_gettimeofday (struct timeval *tv);
+extern void efi_gettimeofday (struct timespec *ts);
 extern void efi_enter_virtual_mode (void);	/* switch EFI to virtual mode, if possible */
 extern u64 efi_get_iobase (void);
 extern u32 efi_mem_type (unsigned long phys_addr);
diff -urN linux-2.5.69-bk6/include/linux/pci_ids.h linux-2.5.69-bk7/include/linux/pci_ids.h
--- linux-2.5.69-bk6/include/linux/pci_ids.h	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk7/include/linux/pci_ids.h	2003-05-12 04:43:30.000000000 -0700
@@ -605,6 +605,7 @@
 #define PCI_DEVICE_ID_HP_ZX1_SBA	0x1229
 #define PCI_DEVICE_ID_HP_ZX1_IOC	0x122a
 #define PCI_DEVICE_ID_HP_ZX1_LBA	0x122e
+#define PCI_DEVICE_ID_HP_SX1000_IOC	0x127c
 #define PCI_DEVICE_ID_HP_DIVA_EVEREST	0x1282
 #define PCI_DEVICE_ID_HP_DIVA_AUX	0x1290
 
@@ -1007,7 +1008,9 @@
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL	0x017B
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL	0x017C
 #define PCI_DEVICE_ID_NVIDIA_IGEFORCE2		0x01a0
+#define PCI_DEVICE_ID_NVIDIA_NFORCE		0x01a4
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE		0x01bc
+#define PCI_DEVICE_ID_NVIDIA_NFORCE2		0x01e0
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3		0x0200
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1		0x0201
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3_2		0x0202
@@ -1902,10 +1905,13 @@
 #define PCI_DEVICE_ID_INTEL_82845G_IG	0x2562
 #define PCI_DEVICE_ID_INTEL_82865_HB	0x2570
 #define PCI_DEVICE_ID_INTEL_82865_IG	0x2572
+#define PCI_DEVICE_ID_INTEL_82875_HB	0x2578
+#define PCI_DEVICE_ID_INTEL_82875_IG	0x257b
+#define PCI_DEVICE_ID_INTEL_82855PM_HB	0x3340
 #define PCI_DEVICE_ID_INTEL_82830_HB	0x3575
 #define PCI_DEVICE_ID_INTEL_82830_CGC	0x3577
-#define PCI_DEVICE_ID_INTEL_82855_HB	0x3580
-#define PCI_DEVICE_ID_INTEL_82855_IG	0x3582
+#define PCI_DEVICE_ID_INTEL_82855GM_HB	0x3580
+#define PCI_DEVICE_ID_INTEL_82855GM_IG	0x3582
 #define PCI_DEVICE_ID_INTEL_80310	0x530d
 #define PCI_DEVICE_ID_INTEL_82371SB_0	0x7000
 #define PCI_DEVICE_ID_INTEL_82371SB_1	0x7010
diff -urN linux-2.5.69-bk6/include/linux/sunrpc/xdr.h linux-2.5.69-bk7/include/linux/sunrpc/xdr.h
--- linux-2.5.69-bk6/include/linux/sunrpc/xdr.h	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk7/include/linux/sunrpc/xdr.h	2003-05-12 04:43:30.000000000 -0700
@@ -157,6 +157,11 @@
 extern void xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int,
 		skb_reader_t *, skb_read_actor_t);
 
+struct socket;
+struct sockaddr;
+extern int xdr_sendpages(struct socket *, struct sockaddr *, int,
+		struct xdr_buf *, unsigned int, int);
+
 /*
  * Provide some simple tools for XDR buffer overflow-checking etc.
  */
diff -urN linux-2.5.69-bk6/include/linux/sunrpc/xprt.h linux-2.5.69-bk7/include/linux/sunrpc/xprt.h
--- linux-2.5.69-bk6/include/linux/sunrpc/xprt.h	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk7/include/linux/sunrpc/xprt.h	2003-05-12 04:43:30.000000000 -0700
@@ -198,7 +198,7 @@
 
 #define XPRT_CONNECT	0
 
-#define xprt_connected(xp)		(!(xp)->stream || test_bit(XPRT_CONNECT, &(xp)->sockstate))
+#define xprt_connected(xp)		(test_bit(XPRT_CONNECT, &(xp)->sockstate))
 #define xprt_set_connected(xp)		(set_bit(XPRT_CONNECT, &(xp)->sockstate))
 #define xprt_test_and_set_connected(xp)	(test_and_set_bit(XPRT_CONNECT, &(xp)->sockstate))
 #define xprt_clear_connected(xp)	(clear_bit(XPRT_CONNECT, &(xp)->sockstate))
diff -urN linux-2.5.69-bk6/include/linux/wireless.h linux-2.5.69-bk7/include/linux/wireless.h
--- linux-2.5.69-bk6/include/linux/wireless.h	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk7/include/linux/wireless.h	2003-05-12 04:43:30.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * This file define a set of standard wireless extensions
  *
- * Version :	15	12.7.02
+ * Version :	16	2.4.03
  *
  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
  * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
@@ -69,6 +69,8 @@
 
 /***************************** INCLUDES *****************************/
 
+/* To minimise problems in user space, I might remove those headers
+ * at some point. Jean II */
 #include <linux/types.h>		/* for "caddr_t" et al		*/
 #include <linux/socket.h>		/* for "struct sockaddr" et al	*/
 #include <linux/if.h>			/* for IFNAMSIZ and co... */
@@ -80,7 +82,7 @@
  * (there is some stuff that will be added in the future...)
  * I just plan to increment with each new version.
  */
-#define WIRELESS_EXT	15
+#define WIRELESS_EXT	16
 
 /*
  * Changes :
@@ -163,6 +165,16 @@
  *	- Add IW_TXPOW_RANGE for range of Tx Powers
  *	- Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
  *	- Add IW_MODE_MONITOR for passive monitor
+ *
+ * V15 to V16
+ * ----------
+ *	- Increase the number of bitrates in iw_range to 32 (for 802.11g)
+ *	- Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
+ *	- Reshuffle struct iw_range for increases, add filler
+ *	- Increase IW_MAX_AP to 64 for driver returning a lot of addresses
+ *	- Remove IW_MAX_GET_SPY because conflict with enhanced spy support
+ *	- Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
+ *	- Add IW_ENCODE_TEMP and iw_range->encoding_login_index
  */
 
 /**************************** CONSTANTS ****************************/
@@ -196,9 +208,11 @@
 /* SIOCGIWSTATS is strictly used between user space and the kernel, and
  * is never passed to the driver (i.e. the driver will never see it). */
 
-/* Mobile IP support (statistics per MAC address) */
+/* Spy support (statistics per MAC address - used for Mobile IP support) */
 #define SIOCSIWSPY	0x8B10		/* set spy addresses */
 #define SIOCGIWSPY	0x8B11		/* get spy info (quality of link) */
+#define SIOCSIWTHRSPY	0x8B12		/* set spy threshold (spy event) */
+#define SIOCGIWTHRSPY	0x8B13		/* get spy threshold */
 
 /* Access Point manipulation */
 #define SIOCSIWAP	0x8B14		/* set access point MAC addresses */
@@ -306,13 +320,13 @@
 /* ----------------------- OTHER CONSTANTS ----------------------- */
 
 /* Maximum frequencies in the range struct */
-#define IW_MAX_FREQUENCIES	16
+#define IW_MAX_FREQUENCIES	32
 /* Note : if you have something like 80 frequencies,
  * don't increase this constant and don't fill the frequency list.
  * The user will be able to set by channel anyway... */
 
 /* Maximum bit rates in the range struct */
-#define IW_MAX_BITRATES		8
+#define IW_MAX_BITRATES		32
 
 /* Maximum tx powers in the range struct */
 #define IW_MAX_TXPOWER		8
@@ -320,12 +334,11 @@
  * a few of them in the struct iw_range. */
 
 /* Maximum of address that you may set with SPY */
-#define IW_MAX_SPY		8	/* set */
-#define IW_MAX_GET_SPY		64	/* get */
+#define IW_MAX_SPY		8
 
 /* Maximum of address that you may get in the
    list of access points in range */
-#define IW_MAX_AP		8
+#define IW_MAX_AP		64
 
 /* Maximum size of the ESSID and NICKN strings */
 #define IW_ESSID_MAX_SIZE	32
@@ -354,7 +367,8 @@
 #define IW_ENCODE_ENABLED	0x0000	/* Encoding enabled */
 #define IW_ENCODE_RESTRICTED	0x4000	/* Refuse non-encoded packets */
 #define IW_ENCODE_OPEN		0x2000	/* Accept non-encoded packets */
-#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
+#define IW_ENCODE_NOKEY		0x0800  /* Key is write only, so not present */
+#define IW_ENCODE_TEMP		0x0400  /* Temporary key */
 
 /* Power management flags available (along with the value, if any) */
 #define IW_POWER_ON		0x0000	/* No details... */
@@ -482,6 +496,17 @@
 	__u32		beacon;		/* Missed beacons/superframe */
 };
 
+/*
+ *	Quality range (for spy threshold)
+ */
+struct	iw_thrspy
+{
+	struct sockaddr		addr;		/* Source address (hw/mac) */
+	struct iw_quality	qual;		/* Quality of the link */
+	struct iw_quality	low;		/* Low threshold */
+	struct iw_quality	high;		/* High threshold */
+};
+
 /* ------------------------ WIRELESS STATS ------------------------ */
 /*
  * Wireless statistics (used for /proc/net/wireless)
@@ -534,7 +559,7 @@
 	struct iw_quality qual;		/* Quality part of statistics */
 
 	struct sockaddr	ap_addr;	/* Access point address */
-	struct sockaddr	addr;		/* Destination address (hw) */
+	struct sockaddr	addr;		/* Destination address (hw/mac) */
 
 	struct iw_param	param;		/* Other small parameters */
 	struct iw_point	data;		/* Other large parameters */
@@ -582,17 +607,31 @@
 	__u32		min_nwid;	/* Minimal NWID we are able to set */
 	__u32		max_nwid;	/* Maximal NWID we are able to set */
 
-	/* Frequency */
-	__u16		num_channels;	/* Number of channels [0; num - 1] */
-	__u8		num_frequency;	/* Number of entry in the list */
-	struct iw_freq	freq[IW_MAX_FREQUENCIES];	/* list */
-	/* Note : this frequency list doesn't need to fit channel numbers */
+	/* Old Frequency (backward compat - moved lower ) */
+	__u16		old_num_channels;
+	__u8		old_num_frequency;
+	/* Filler to keep "version" at the same offset */
+	__s32		old_freq[6];
 
 	/* signal level threshold range */
 	__s32	sensitivity;
 
 	/* Quality of link & SNR stuff */
+	/* Quality range (link, level, noise)
+	 * If the quality is absolute, it will be in the range [0 ; max_qual],
+	 * if the quality is dBm, it will be in the range [max_qual ; 0].
+	 * Don't forget that we use 8 bit arithmetics... */
 	struct iw_quality	max_qual;	/* Quality of the link */
+	/* This should contain the average/typical values of the quality
+	 * indicator. This should be the threshold between a "good" and
+	 * a "bad" link (example : monitor going from green to orange).
+	 * Currently, user space apps like quality monitors don't have any
+	 * way to calibrate the measurement. With this, they can split
+	 * the range between 0 and max_qual in different quality level
+	 * (using a geometric subdivision centered on the average).
+	 * I expect that people doing the user space apps will feedback
+	 * us on which value we need to put in each driver... */
+	struct iw_quality	avg_qual;	/* Quality of the link */
 
 	/* Rates */
 	__u8		num_bitrates;	/* Number of entries in the list */
@@ -619,6 +658,8 @@
 	__u16	encoding_size[IW_MAX_ENCODING_SIZES];	/* Different token sizes */
 	__u8	num_encoding_sizes;	/* Number of entry in the list */
 	__u8	max_encoding_tokens;	/* Max number of tokens */
+	/* For drivers that need a "login/passwd" form */
+	__u8	encoding_login_index;	/* token index for login token */
 
 	/* Transmit power */
 	__u16		txpower_capa;	/* What options are supported */
@@ -638,18 +679,12 @@
 	__s32		min_r_time;	/* Minimal retry lifetime */
 	__s32		max_r_time;	/* Maximal retry lifetime */
 
-	/* Average quality of link & SNR */
-	struct iw_quality	avg_qual;	/* Quality of the link */
-	/* This should contain the average/typical values of the quality
-	 * indicator. This should be the threshold between a "good" and
-	 * a "bad" link (example : monitor going from green to orange).
-	 * Currently, user space apps like quality monitors don't have any
-	 * way to calibrate the measurement. With this, they can split
-	 * the range between 0 and max_qual in different quality level
-	 * (using a geometric subdivision centered on the average).
-	 * I expect that people doing the user space apps will feedback
-	 * us on which value we need to put in each driver...
-	 */
+	/* Frequency */
+	__u16		num_channels;	/* Number of channels [0; num - 1] */
+	__u8		num_frequency;	/* Number of entry in the list */
+	struct iw_freq	freq[IW_MAX_FREQUENCIES];	/* list */
+	/* Note : this frequency list doesn't need to fit channel numbers,
+	 * because each entry contain its channel index */
 };
 
 /*
diff -urN linux-2.5.69-bk6/include/net/iw_handler.h linux-2.5.69-bk7/include/net/iw_handler.h
--- linux-2.5.69-bk6/include/net/iw_handler.h	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk7/include/net/iw_handler.h	2003-05-12 04:43:30.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * This file define the new driver API for Wireless Extensions
  *
- * Version :	4	21.6.02
+ * Version :	5	4.12.02
  *
  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
  * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
@@ -206,7 +206,7 @@
  * will be needed...
  * I just plan to increment with each new version.
  */
-#define IW_HANDLER_VERSION	4
+#define IW_HANDLER_VERSION	5
 
 /*
  * Changes :
@@ -220,10 +220,18 @@
  * V3 to V4
  * --------
  *	- Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
+ *
+ * V4 to V5
+ * --------
+ *	- Add new spy support : struct iw_spy_data & prototypes
  */
 
 /**************************** CONSTANTS ****************************/
 
+/* Enable enhanced spy support. Disable to reduce footprint */
+#define IW_WIRELESS_SPY
+#define IW_WIRELESS_THRSPY
+
 /* Special error message for the driver to indicate that we
  * should do a commit after return from the iw_handler */
 #define EIWCOMMIT	EINPROGRESS
@@ -315,6 +323,9 @@
 	 * We will automatically export that to user space... */
 	struct iw_priv_args *	private_args;
 
+	/* Driver enhanced spy support */
+	long			spy_offset;	/* Spy data offset */
+
 	/* In the long term, get_wireless_stats will move from
 	 * 'struct net_device' to here, to minimise bloat. */
 };
@@ -350,6 +361,33 @@
 
 /* Need to think of short header translation table. Later. */
 
+/* --------------------- ENHANCED SPY SUPPORT --------------------- */
+/*
+ * In the old days, the driver was handling spy support all by itself.
+ * Now, the driver can delegate this task to Wireless Extensions.
+ * It needs to include this struct in its private part and use the
+ * standard spy iw_handler.
+ */
+
+/*
+ * Instance specific spy data, i.e. addresses spied and quality for them.
+ */
+struct iw_spy_data
+{
+#ifdef IW_WIRELESS_SPY
+	/* --- Standard spy support --- */
+	int			spy_number;
+	u_char			spy_address[IW_MAX_SPY][ETH_ALEN];
+	struct iw_quality	spy_stat[IW_MAX_SPY];
+#ifdef IW_WIRELESS_THRSPY
+	/* --- Enhanced spy support (event) */
+	struct iw_quality	spy_thr_low;	/* Low threshold */
+	struct iw_quality	spy_thr_high;	/* High threshold */
+	u_char			spy_thr_under[IW_MAX_SPY];
+#endif /* IW_WIRELESS_THRSPY */
+#endif /* IW_WIRELESS_SPY */
+};
+
 /**************************** PROTOTYPES ****************************/
 /*
  * Functions part of the Wireless Extensions (defined in net/core/wireless.c).
@@ -376,6 +414,31 @@
 /* We may need a function to send a stream of events to user space.
  * More on that later... */
 
+/* Standard handler for SIOCSIWSPY */
+extern int iw_handler_set_spy(struct net_device *	dev,
+			      struct iw_request_info *	info,
+			      union iwreq_data *	wrqu,
+			      char *			extra);
+/* Standard handler for SIOCGIWSPY */
+extern int iw_handler_get_spy(struct net_device *	dev,
+			      struct iw_request_info *	info,
+			      union iwreq_data *	wrqu,
+			      char *			extra);
+/* Standard handler for SIOCSIWTHRSPY */
+extern int iw_handler_set_thrspy(struct net_device *	dev,
+				 struct iw_request_info *info,
+				 union iwreq_data *	wrqu,
+				 char *			extra);
+/* Standard handler for SIOCGIWTHRSPY */
+extern int iw_handler_get_thrspy(struct net_device *	dev,
+				 struct iw_request_info *info,
+				 union iwreq_data *	wrqu,
+				 char *			extra);
+/* Driver call to update spy records */
+extern void wireless_spy_update(struct net_device *	dev,
+				unsigned char *		address,
+				struct iw_quality *	wstats);
+
 /************************* INLINE FUNTIONS *************************/
 /*
  * Function that are so simple that it's more efficient inlining them
diff -urN linux-2.5.69-bk6/mm/page-writeback.c linux-2.5.69-bk7/mm/page-writeback.c
--- linux-2.5.69-bk6/mm/page-writeback.c	2003-05-12 04:43:26.000000000 -0700
+++ linux-2.5.69-bk7/mm/page-writeback.c	2003-05-12 04:43:30.000000000 -0700
@@ -270,7 +270,7 @@
 		struct page_state ps;
 
 		get_page_state(&ps);
-		nr_pages = ps.nr_dirty;
+		nr_pages = ps.nr_dirty + ps.nr_unstable;
 	}
 	return pdflush_operation(background_writeout, nr_pages);
 }
diff -urN linux-2.5.69-bk6/net/core/wireless.c linux-2.5.69-bk7/net/core/wireless.c
--- linux-2.5.69-bk6/net/core/wireless.c	2003-05-12 04:43:26.000000000 -0700
+++ linux-2.5.69-bk7/net/core/wireless.c	2003-05-12 04:43:31.000000000 -0700
@@ -2,7 +2,7 @@
  * This file implement the Wireless Extensions APIs.
  *
  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved.
  *
  * (As all part of the Linux kernel, this file is GPL)
  */
@@ -43,6 +43,11 @@
  *	o Turn on WE_STRICT_WRITE by default + kernel warning
  *	o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num)
  *	o Fix off-by-one in test (extra_size <= IFNAMSIZ)
+ *
+ * v6 - 9.01.03 - Jean II
+ *	o Add common spy support : iw_handler_set_spy(), wireless_spy_update()
+ *	o Add enhanced spy support : iw_handler_set_thrspy() and event.
+ *	o Add WIRELESS_EXT version display in /proc/net/wireless
  */
 
 /***************************** INCLUDES *****************************/
@@ -53,9 +58,10 @@
 #include <linux/proc_fs.h>
 #include <linux/rtnetlink.h>		/* rtnetlink stuff */
 #include <linux/seq_file.h>
-#include <linux/wireless.h>		/* Pretty obvious */
 #include <linux/init.h>			/* for __init */
+#include <linux/if_arp.h>		/* ARPHRD_ETHER */
 
+#include <linux/wireless.h>		/* Pretty obvious */
 #include <net/iw_handler.h>		/* New driver API */
 
 #include <asm/uaccess.h>		/* copy_to_user() */
@@ -69,6 +75,7 @@
 /* Debugging stuff */
 #undef WE_IOCTL_DEBUG		/* Debug IOCTL API */
 #undef WE_EVENT_DEBUG		/* Debug Event dispatcher */
+#undef WE_SPY_DEBUG		/* Debug enhanced spy support */
 
 /* Options */
 #define WE_EVENT_NETLINK	/* Propagate events using rtnetlink */
@@ -76,7 +83,7 @@
 
 /************************* GLOBAL VARIABLES *************************/
 /*
- * You should not use global variables, because or re-entrancy.
+ * You should not use global variables, because of re-entrancy.
  * On our case, it's only const, so it's OK...
  */
 /*
@@ -152,7 +159,19 @@
 		.header_type	= IW_HEADER_TYPE_POINT,
 		.token_size	= sizeof(struct sockaddr) +
 				  sizeof(struct iw_quality),
-		.max_tokens	= IW_MAX_GET_SPY,
+		.max_tokens	= IW_MAX_SPY,
+	},
+	[SIOCSIWTHRSPY	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= sizeof(struct iw_thrspy),
+		.min_tokens	= 1,
+		.max_tokens	= 1,
+	},
+	[SIOCGIWTHRSPY	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= sizeof(struct iw_thrspy),
+		.min_tokens	= 1,
+		.max_tokens	= 1,
 	},
 	[SIOCSIWAP	- SIOCIWFIRST] = {
 		.header_type	= IW_HEADER_TYPE_ADDR,
@@ -440,9 +459,10 @@
 {
 	if (v == (void *)1)
 		seq_printf(seq, "Inter-| sta-|   Quality        |   Discarded "
-				"packets               | Missed\n"
+				"packets               | Missed | WE\n"
 				" face | tus | link level noise |  nwid  "
-				"crypt   frag  retry   misc | beacon\n");
+				"crypt   frag  retry   misc | beacon | %d\n",
+			   WIRELESS_EXT);
 	else
 		wireless_seq_printf_stats(seq, v);
 	return 0;
@@ -1100,3 +1120,252 @@
 
 	return;		/* Always success, I guess ;-) */
 }
+
+/********************** ENHANCED IWSPY SUPPORT **********************/
+/*
+ * In the old days, the driver was handling spy support all by itself.
+ * Now, the driver can delegate this task to Wireless Extensions.
+ * It needs to use those standard spy iw_handler in struct iw_handler_def,
+ * push data to us via wireless_spy_update() and include struct iw_spy_data
+ * in its private part (and advertise it in iw_handler_def->spy_offset).
+ * One of the main advantage of centralising spy support here is that
+ * it becomes much easier to improve and extend it without having to touch
+ * the drivers. One example is the addition of the Spy-Threshold events.
+ * Note : IW_WIRELESS_SPY is defined in iw_handler.h
+ */
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : set Spy List
+ */
+int iw_handler_set_spy(struct net_device *	dev,
+		       struct iw_request_info *	info,
+		       union iwreq_data *	wrqu,
+		       char *			extra)
+{
+#ifdef IW_WIRELESS_SPY
+	struct iw_spy_data *	spydata = (dev->priv +
+					   dev->wireless_handlers->spy_offset);
+	struct sockaddr *	address = (struct sockaddr *) extra;
+
+	/* Disable spy collection while we copy the addresses.
+	 * As we don't disable interrupts, we need to do this to avoid races.
+	 * As we are the only writer, this is good enough. */
+	spydata->spy_number = 0;
+
+	/* Are there are addresses to copy? */
+	if(wrqu->data.length > 0) {
+		int i;
+
+		/* Copy addresses */
+		for(i = 0; i < wrqu->data.length; i++)
+			memcpy(spydata->spy_address[i], address[i].sa_data,
+			       ETH_ALEN);
+		/* Reset stats */
+		memset(spydata->spy_stat, 0,
+		       sizeof(struct iw_quality) * IW_MAX_SPY);
+
+#ifdef WE_SPY_DEBUG
+		printk(KERN_DEBUG "iw_handler_set_spy() :  offset %ld, spydata %p, num %d\n", dev->wireless_handlers->spy_offset, spydata, wrqu->data.length);
+		for (i = 0; i < wrqu->data.length; i++)
+			printk(KERN_DEBUG
+			       "%02X:%02X:%02X:%02X:%02X:%02X \n",
+			       spydata->spy_address[i][0],
+			       spydata->spy_address[i][1],
+			       spydata->spy_address[i][2],
+			       spydata->spy_address[i][3],
+			       spydata->spy_address[i][4],
+			       spydata->spy_address[i][5]);
+#endif	/* WE_SPY_DEBUG */
+	}
+	/* Enable addresses */
+	spydata->spy_number = wrqu->data.length;
+
+	return 0;
+#else /* IW_WIRELESS_SPY */
+	return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_SPY */
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : get Spy List
+ */
+int iw_handler_get_spy(struct net_device *	dev,
+		       struct iw_request_info *	info,
+		       union iwreq_data *	wrqu,
+		       char *			extra)
+{
+#ifdef IW_WIRELESS_SPY
+	struct iw_spy_data *	spydata = (dev->priv +
+					   dev->wireless_handlers->spy_offset);
+	struct sockaddr *	address = (struct sockaddr *) extra;
+	int			i;
+
+	wrqu->data.length = spydata->spy_number;
+
+	/* Copy addresses. */
+	for(i = 0; i < spydata->spy_number; i++) 	{
+		memcpy(address[i].sa_data, spydata->spy_address[i], ETH_ALEN);
+		address[i].sa_family = AF_UNIX;
+	}
+	/* Copy stats to the user buffer (just after). */
+	if(spydata->spy_number > 0)
+		memcpy(extra  + (sizeof(struct sockaddr) *spydata->spy_number),
+		       spydata->spy_stat,
+		       sizeof(struct iw_quality) * spydata->spy_number);
+	/* Reset updated flags. */
+	for(i = 0; i < spydata->spy_number; i++)
+		spydata->spy_stat[i].updated = 0;
+	return 0;
+#else /* IW_WIRELESS_SPY */
+	return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_SPY */
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : set spy threshold
+ */
+int iw_handler_set_thrspy(struct net_device *	dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *	wrqu,
+			  char *		extra)
+{
+#ifdef IW_WIRELESS_THRSPY
+	struct iw_spy_data *	spydata = (dev->priv +
+					   dev->wireless_handlers->spy_offset);
+	struct iw_thrspy *	threshold = (struct iw_thrspy *) extra;
+
+	/* Just do it */
+	memcpy(&(spydata->spy_thr_low), &(threshold->low),
+	       2 * sizeof(struct iw_quality));
+
+	/* Clear flag */
+	memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under));
+
+#ifdef WE_SPY_DEBUG
+	printk(KERN_DEBUG "iw_handler_set_thrspy() :  low %d ; high %d\n", spydata->spy_thr_low.level, spydata->spy_thr_high.level);
+#endif	/* WE_SPY_DEBUG */
+
+	return 0;
+#else /* IW_WIRELESS_THRSPY */
+	return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_THRSPY */
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : get spy threshold
+ */
+int iw_handler_get_thrspy(struct net_device *	dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *	wrqu,
+			  char *		extra)
+{
+#ifdef IW_WIRELESS_THRSPY
+	struct iw_spy_data *	spydata = (dev->priv +
+					   dev->wireless_handlers->spy_offset);
+	struct iw_thrspy *	threshold = (struct iw_thrspy *) extra;
+
+	/* Just do it */
+	memcpy(&(threshold->low), &(spydata->spy_thr_low),
+	       2 * sizeof(struct iw_quality));
+
+	return 0;
+#else /* IW_WIRELESS_THRSPY */
+	return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_THRSPY */
+}
+
+#ifdef IW_WIRELESS_THRSPY
+/*------------------------------------------------------------------*/
+/*
+ * Prepare and send a Spy Threshold event
+ */
+static void iw_send_thrspy_event(struct net_device *	dev,
+				 struct iw_spy_data *	spydata,
+				 unsigned char *	address,
+				 struct iw_quality *	wstats)
+{
+	union iwreq_data	wrqu;
+	struct iw_thrspy	threshold;
+
+	/* Init */
+	wrqu.data.length = 1;
+	wrqu.data.flags = 0;
+	/* Copy address */
+	memcpy(threshold.addr.sa_data, address, ETH_ALEN);
+	threshold.addr.sa_family = ARPHRD_ETHER;
+	/* Copy stats */
+	memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality));
+	/* Copy also thresholds */
+	memcpy(&(threshold.low), &(spydata->spy_thr_low),
+	       2 * sizeof(struct iw_quality));
+
+#ifdef WE_SPY_DEBUG
+	printk(KERN_DEBUG "iw_send_thrspy_event() : address %02X:%02X:%02X:%02X:%02X:%02X, level %d, up = %d\n",
+	       threshold.addr.sa_data[0],
+	       threshold.addr.sa_data[1],
+	       threshold.addr.sa_data[2],
+	       threshold.addr.sa_data[3],
+	       threshold.addr.sa_data[4],
+	       threshold.addr.sa_data[5], threshold.qual.level);
+#endif	/* WE_SPY_DEBUG */
+
+	/* Send event to user space */
+	wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
+}
+#endif /* IW_WIRELESS_THRSPY */
+
+/* ---------------------------------------------------------------- */
+/*
+ * Call for the driver to update the spy data.
+ * For now, the spy data is a simple array. As the size of the array is
+ * small, this is good enough. If we wanted to support larger number of
+ * spy addresses, we should use something more efficient...
+ */
+void wireless_spy_update(struct net_device *	dev,
+			 unsigned char *	address,
+			 struct iw_quality *	wstats)
+{
+#ifdef IW_WIRELESS_SPY
+	struct iw_spy_data *	spydata = (dev->priv +
+					   dev->wireless_handlers->spy_offset);
+	int			i;
+	int			match = -1;
+
+#ifdef WE_SPY_DEBUG
+	printk(KERN_DEBUG "wireless_spy_update() :  offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]);
+#endif	/* WE_SPY_DEBUG */
+
+	/* Update all records that match */
+	for(i = 0; i < spydata->spy_number; i++)
+		if(!memcmp(address, spydata->spy_address[i], ETH_ALEN)) {
+			memcpy(&(spydata->spy_stat[i]), wstats,
+			       sizeof(struct iw_quality));
+			match = i;
+		}
+#ifdef IW_WIRELESS_THRSPY
+	/* Generate an event if we cross the spy threshold.
+	 * To avoid event storms, we have a simple hysteresis : we generate
+	 * event only when we go under the low threshold or above the
+	 * high threshold. */
+	if(match >= 0) {
+		if(spydata->spy_thr_under[match]) {
+			if(wstats->level > spydata->spy_thr_high.level) {
+				spydata->spy_thr_under[match] = 0;
+				iw_send_thrspy_event(dev, spydata,
+						     address, wstats);
+			}
+		} else {
+			if(wstats->level < spydata->spy_thr_low.level) {
+				spydata->spy_thr_under[match] = 1;
+				iw_send_thrspy_event(dev, spydata,
+						     address, wstats);
+			}
+		}
+	}
+#endif /* IW_WIRELESS_THRSPY */
+#endif /* IW_WIRELESS_SPY */
+}
diff -urN linux-2.5.69-bk6/net/ipv4/netfilter/ip_fw_compat_masq.c linux-2.5.69-bk7/net/ipv4/netfilter/ip_fw_compat_masq.c
--- linux-2.5.69-bk6/net/ipv4/netfilter/ip_fw_compat_masq.c	2003-05-12 04:43:26.000000000 -0700
+++ linux-2.5.69-bk7/net/ipv4/netfilter/ip_fw_compat_masq.c	2003-05-12 04:43:31.000000000 -0700
@@ -35,16 +35,15 @@
 unsigned int
 do_masquerade(struct sk_buff **pskb, const struct net_device *dev)
 {
-	struct iphdr *iph = (*pskb)->nh.iph;
 	struct ip_nat_info *info;
 	enum ip_conntrack_info ctinfo;
 	struct ip_conntrack *ct;
 	unsigned int ret;
 
 	/* Sorry, only ICMP, TCP and UDP. */
-	if (iph->protocol != IPPROTO_ICMP
-	    && iph->protocol != IPPROTO_TCP
-	    && iph->protocol != IPPROTO_UDP)
+	if ((*pskb)->nh.iph->protocol != IPPROTO_ICMP
+	    && (*pskb)->nh.iph->protocol != IPPROTO_TCP
+	    && (*pskb)->nh.iph->protocol != IPPROTO_UDP)
 		return NF_DROP;
 
 	/* Feed it to connection tracking; in fact we're in NF_IP_FORWARD,
@@ -68,7 +67,7 @@
 	/* Setup the masquerade, if not already */
 	if (!info->initialized) {
 		u_int32_t newsrc;
-		struct flowi fl = { .nl_u = { .ip4_u = { .daddr = iph->daddr } } };
+		struct flowi fl = { .nl_u = { .ip4_u = { .daddr = (*pskb)->nh.iph->daddr } } };
 		struct rtable *rt;
 		struct ip_nat_multi_range range;
 
@@ -124,19 +123,18 @@
 check_for_demasq(struct sk_buff **pskb)
 {
 	struct ip_conntrack_tuple tuple;
-	struct iphdr *iph = (*pskb)->nh.iph;
 	struct ip_conntrack_protocol *protocol;
 	struct ip_conntrack_tuple_hash *h;
 	enum ip_conntrack_info ctinfo;
 	struct ip_conntrack *ct;
 	int ret;
 
-	protocol = ip_ct_find_proto(iph->protocol);
+	protocol = ip_ct_find_proto((*pskb)->nh.iph->protocol);
 
 	/* We don't feed packets to conntrack system unless we know
            they're part of an connection already established by an
            explicit masq command. */
-	switch (iph->protocol) {
+	switch ((*pskb)->nh.iph->protocol) {
 	case IPPROTO_ICMP:
 		/* ICMP errors. */
 		ct = icmp_error_track(*pskb, &ctinfo, NF_IP_PRE_ROUTING);
@@ -146,12 +144,6 @@
 			   server here (== DNAT).  Do SNAT icmp manips
 			   in POST_ROUTING handling. */
 			if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) {
-				/* FIXME: Remove once NAT handled non-linear.
-				 */
-				if (skb_is_nonlinear(*pskb)
-				    && skb_linearize(*pskb, GFP_ATOMIC) != 0)
-					return NF_DROP;
-
 				icmp_reply_translation(pskb, ct,
 						       NF_IP_PRE_ROUTING,
 						       CTINFO2DIR(ctinfo));
@@ -166,7 +158,7 @@
 	case IPPROTO_UDP:
 		IP_NF_ASSERT(((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
 
-		if (!get_tuple(iph, *pskb, iph->ihl*4, &tuple, protocol)) {
+		if (!get_tuple((*pskb)->nh.iph, *pskb, (*pskb)->nh.iph->ihl*4, &tuple, protocol)) {
 			if (net_ratelimit())
 				printk("ip_fw_compat_masq: Can't get tuple\n");
 			return NF_ACCEPT;
diff -urN linux-2.5.69-bk6/net/ipv4/netfilter/ip_nat_core.c linux-2.5.69-bk7/net/ipv4/netfilter/ip_nat_core.c
--- linux-2.5.69-bk6/net/ipv4/netfilter/ip_nat_core.c	2003-05-12 04:43:26.000000000 -0700
+++ linux-2.5.69-bk7/net/ipv4/netfilter/ip_nat_core.c	2003-05-12 04:43:31.000000000 -0700
@@ -717,10 +717,13 @@
 	iph = (void *)(*pskb)->data + iphdroff;
 
 	/* Manipulate protcol part. */
-	if (!find_nat_proto(proto)->manip_pkt(pskb, iphdroff + iph->ihl*4,
+	if (!find_nat_proto(proto)->manip_pkt(pskb,
+					      iphdroff + iph->ihl*4,
 					      manip, maniptype))
 		return 0;
 
+	iph = (void *)(*pskb)->data + iphdroff;
+
 	if (maniptype == IP_NAT_MANIP_SRC) {
 		iph->check = ip_nat_cheat_check(~iph->saddr, manip->ip,
 						iph->check);
@@ -953,6 +956,8 @@
 
 	hdrlen = (*pskb)->nh.iph->ihl * 4;
 
+	inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
+
 	inside->icmp.checksum = 0;
 	inside->icmp.checksum = csum_fold(skb_checksum(*pskb, hdrlen,
 						       (*pskb)->len - hdrlen,
diff -urN linux-2.5.69-bk6/net/ipv4/protocol.c linux-2.5.69-bk7/net/ipv4/protocol.c
--- linux-2.5.69-bk6/net/ipv4/protocol.c	2003-05-12 04:43:26.000000000 -0700
+++ linux-2.5.69-bk7/net/ipv4/protocol.c	2003-05-12 04:43:31.000000000 -0700
@@ -91,6 +91,7 @@
 	}
 	spin_unlock_bh(&inet_proto_lock);
 
+	synchronize_net();
 
 	return ret;
 }
diff -urN linux-2.5.69-bk6/net/ipv6/protocol.c linux-2.5.69-bk7/net/ipv6/protocol.c
--- linux-2.5.69-bk6/net/ipv6/protocol.c	2003-05-12 04:43:26.000000000 -0700
+++ linux-2.5.69-bk7/net/ipv6/protocol.c	2003-05-12 04:43:31.000000000 -0700
@@ -80,5 +80,7 @@
 
 	spin_unlock_bh(&inet6_proto_lock);
 
+	synchronize_net();
+
 	return ret;
 }
diff -urN linux-2.5.69-bk6/net/ipv6/udp.c linux-2.5.69-bk7/net/ipv6/udp.c
--- linux-2.5.69-bk6/net/ipv6/udp.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk7/net/ipv6/udp.c	2003-05-12 04:43:31.000000000 -0700
@@ -575,7 +575,7 @@
 	for(; s; s = s->next) {
 		struct inet_opt *inet = inet_sk(s);
 
-		if (inet->num == num) {
+		if (inet->num == num && sk->family == PF_INET6) {
 			struct ipv6_pinfo *np = inet6_sk(s);
 			if (inet->dport) {
 				if (inet->dport != rmt_port)
diff -urN linux-2.5.69-bk6/net/netsyms.c linux-2.5.69-bk7/net/netsyms.c
--- linux-2.5.69-bk6/net/netsyms.c	2003-05-12 04:43:26.000000000 -0700
+++ linux-2.5.69-bk7/net/netsyms.c	2003-05-12 04:43:31.000000000 -0700
@@ -666,10 +666,13 @@
 EXPORT_SYMBOL(softnet_data);
 
 #ifdef CONFIG_NET_RADIO
-/* Don't include the whole header mess for a single function */
-union iwreq_data;
-extern void wireless_send_event(struct net_device *dev, unsigned int cmd, union iwreq_data *wrqu, char *extra);
+#include <net/iw_handler.h>		/* Wireless Extensions driver API */
 EXPORT_SYMBOL(wireless_send_event);
+EXPORT_SYMBOL(iw_handler_set_spy);
+EXPORT_SYMBOL(iw_handler_get_spy);
+EXPORT_SYMBOL(iw_handler_set_thrspy);
+EXPORT_SYMBOL(iw_handler_get_thrspy);
+EXPORT_SYMBOL(wireless_spy_update);
 #endif	/* CONFIG_NET_RADIO */
 
 EXPORT_SYMBOL(linkwatch_fire_event);
diff -urN linux-2.5.69-bk6/net/sunrpc/clnt.c linux-2.5.69-bk7/net/sunrpc/clnt.c
--- linux-2.5.69-bk6/net/sunrpc/clnt.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk7/net/sunrpc/clnt.c	2003-05-12 04:43:31.000000000 -0700
@@ -57,8 +57,7 @@
 static void	call_refreshresult(struct rpc_task *task);
 static void	call_timeout(struct rpc_task *task);
 static void	call_connect(struct rpc_task *task);
-static void	child_connect(struct rpc_task *task);
-static void	child_connect_status(struct rpc_task *task);
+static void	call_connect_status(struct rpc_task *task);
 static u32 *	call_header(struct rpc_task *task);
 static u32 *	call_verify(struct rpc_task *task);
 
@@ -602,40 +601,48 @@
 call_connect(struct rpc_task *task)
 {
 	struct rpc_clnt *clnt = task->tk_client;
-	struct rpc_task *child;
 
 	dprintk("RPC: %4d call_connect status %d\n",
 				task->tk_pid, task->tk_status);
 
-	task->tk_action = call_transmit;
-	if (task->tk_status < 0 || !clnt->cl_xprt->stream)
+	if (xprt_connected(clnt->cl_xprt)) {
+		task->tk_action = call_transmit;
 		return;
-
-	/* Run as a child to ensure it runs as an rpciod task.  Rpciod
-	 * guarantees we have the correct capabilities for socket bind
-	 * to succeed. */
-	child = rpc_new_child(clnt, task);
-	if (child) {
-		child->tk_action = child_connect;
-		rpc_run_child(task, child, NULL);
 	}
+	task->tk_action = call_connect_status;
+	if (task->tk_status < 0)
+		return;
+	xprt_connect(task);
 }
 
+/*
+ * 4b. Sort out connect result
+ */
 static void
-child_connect(struct rpc_task *task)
+call_connect_status(struct rpc_task *task)
 {
+	struct rpc_clnt *clnt = task->tk_client;
+	int status = task->tk_status;
+
 	task->tk_status = 0;
-	task->tk_action = child_connect_status;
-	xprt_connect(task);
-}
+	if (status >= 0) {
+		clnt->cl_stats->netreconn++;
+		task->tk_action = call_transmit;
+		return;
+	}
 
-static void
-child_connect_status(struct rpc_task *task)
-{
-	if (task->tk_status == -EAGAIN)
-		task->tk_action = child_connect;
-	else
-		task->tk_action = NULL;
+	/* Something failed: we may have to rebind */
+	if (clnt->cl_autobind)
+		clnt->cl_port = 0;
+	switch (status) {
+	case -ENOTCONN:
+	case -ETIMEDOUT:
+	case -EAGAIN:
+		task->tk_action = (clnt->cl_port == 0) ? call_bind : call_connect;
+		break;
+	default:
+		rpc_exit(task, -EIO);
+	}
 }
 
 /*
@@ -696,6 +703,7 @@
 		break;
 	case -ECONNREFUSED:
 	case -ENOTCONN:
+		req->rq_bytes_sent = 0;
 		if (clnt->cl_autobind)
 			clnt->cl_port = 0;
 		task->tk_action = call_bind;
diff -urN linux-2.5.69-bk6/net/sunrpc/sched.c linux-2.5.69-bk7/net/sunrpc/sched.c
--- linux-2.5.69-bk6/net/sunrpc/sched.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk7/net/sunrpc/sched.c	2003-05-12 04:43:31.000000000 -0700
@@ -1110,9 +1110,10 @@
 	alltask_for_each(t, le, &all_tasks)
 		printk("%05d %04d %04x %06d %8p %6d %8p %08ld %8s %8p %8p\n",
 			t->tk_pid,
-			(t->tk_msg.rpc_proc->p_proc ? t->tk_msg.rpc_proc->p_proc : -1),
+			(t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
 			t->tk_flags, t->tk_status,
-			t->tk_client, t->tk_client->cl_prog,
+			t->tk_client,
+			(t->tk_client ? t->tk_client->cl_prog : 0),
 			t->tk_rqstp, t->tk_timeout,
 			rpc_qname(t->tk_rpcwait),
 			t->tk_action, t->tk_exit);
diff -urN linux-2.5.69-bk6/net/sunrpc/xdr.c linux-2.5.69-bk7/net/sunrpc/xdr.c
--- linux-2.5.69-bk6/net/sunrpc/xdr.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk7/net/sunrpc/xdr.c	2003-05-12 04:43:31.000000000 -0700
@@ -13,6 +13,8 @@
 #include <linux/pagemap.h>
 #include <linux/errno.h>
 #include <linux/in.h>
+#include <linux/net.h>
+#include <net/sock.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/msg_prot.h>
 
@@ -314,8 +316,113 @@
 	} while ((pglen -= len) != 0);
 copy_tail:
 	len = xdr->tail[0].iov_len;
-	if (len)
-		copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len);
+	if (base < len)
+		copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base);
+}
+
+
+int
+xdr_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
+		struct xdr_buf *xdr, unsigned int base, int msgflags)
+{
+	struct page **ppage = xdr->pages;
+	unsigned int len, pglen = xdr->page_len;
+	int err, ret = 0;
+	ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
+	mm_segment_t oldfs;
+
+	len = xdr->head[0].iov_len;
+	if (base < len || (addr != NULL && base == 0)) {
+		struct iovec iov = {
+			.iov_base = xdr->head[0].iov_base + base,
+			.iov_len  = len - base,
+		};
+		struct msghdr msg = {
+			.msg_name    = addr,
+			.msg_namelen = addrlen,
+			.msg_flags   = msgflags,
+		};
+
+		if (iov.iov_len != 0) {
+			msg.msg_iov     = &iov;
+			msg.msg_iovlen  = 1;
+		}
+		if (xdr->len > len)
+			msg.msg_flags |= MSG_MORE;
+		oldfs = get_fs(); set_fs(get_ds());
+		err = sock_sendmsg(sock, &msg, iov.iov_len);
+		set_fs(oldfs);
+		if (ret == 0)
+			ret = err;
+		else if (err > 0)
+			ret += err;
+		if (err != iov.iov_len)
+			goto out;
+		base = 0;
+	} else
+		base -= len;
+
+	if (pglen == 0)
+		goto copy_tail;
+	if (base >= pglen) {
+		base -= pglen;
+		goto copy_tail;
+	}
+	if (base || xdr->page_base) {
+		pglen -= base;
+		base  += xdr->page_base;
+		ppage += base >> PAGE_CACHE_SHIFT;
+		base &= ~PAGE_CACHE_MASK;
+	}
+
+	sendpage = sock->ops->sendpage ? : sock_no_sendpage;
+	do {
+		int flags = msgflags;
+
+		len = PAGE_CACHE_SIZE;
+		if (base)
+			len -= base;
+		if (pglen < len)
+			len = pglen;
+
+		if (pglen != len || xdr->tail[0].iov_len != 0)
+			flags |= MSG_MORE;
+
+		/* Hmm... We might be dealing with highmem pages */
+		if (PageHighMem(*ppage))
+			sendpage = sock_no_sendpage;
+		err = sendpage(sock, *ppage, base, len, flags);
+		if (ret == 0)
+			ret = err;
+		else if (err > 0)
+			ret += err;
+		if (err != len)
+			goto out;
+		base = 0;
+		ppage++;
+	} while ((pglen -= len) != 0);
+copy_tail:
+	len = xdr->tail[0].iov_len;
+	if (base < len) {
+		struct iovec iov = {
+			.iov_base = xdr->tail[0].iov_base + base,
+			.iov_len  = len - base,
+		};
+		struct msghdr msg = {
+			.msg_iov     = &iov,
+			.msg_iovlen  = 1,
+			.msg_flags   = msgflags,
+		};
+		oldfs = get_fs(); set_fs(get_ds());
+		err = sock_sendmsg(sock, &msg, iov.iov_len);
+		set_fs(oldfs);
+		if (ret == 0)
+			ret = err;
+		else if (err > 0)
+			ret += err;
+	}
+out:
+	return ret;
 }
 
 
diff -urN linux-2.5.69-bk6/net/sunrpc/xprt.c linux-2.5.69-bk7/net/sunrpc/xprt.c
--- linux-2.5.69-bk6/net/sunrpc/xprt.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk7/net/sunrpc/xprt.c	2003-05-12 04:43:31.000000000 -0700
@@ -85,7 +85,7 @@
 static void	xprt_request_init(struct rpc_task *, struct rpc_xprt *);
 static inline void	do_xprt_reserve(struct rpc_task *);
 static void	xprt_disconnect(struct rpc_xprt *);
-static void	xprt_conn_status(struct rpc_task *task);
+static void	xprt_connect_status(struct rpc_task *task);
 static struct rpc_xprt * xprt_setup(int proto, struct sockaddr_in *ap,
 						struct rpc_timeout *to);
 static struct socket *xprt_create_socket(int, struct rpc_timeout *, int);
@@ -213,11 +213,10 @@
 xprt_sendmsg(struct rpc_xprt *xprt, struct rpc_rqst *req)
 {
 	struct socket	*sock = xprt->sock;
-	struct msghdr	msg;
 	struct xdr_buf	*xdr = &req->rq_snd_buf;
-	struct iovec	niv[MAX_IOVEC];
-	unsigned int	niov, slen, skip;
-	mm_segment_t	oldfs;
+	struct sockaddr *addr = NULL;
+	int addrlen = 0;
+	unsigned int	skip;
 	int		result;
 
 	if (!sock)
@@ -227,27 +226,18 @@
 				req->rq_svec->iov_base,
 				req->rq_svec->iov_len);
 
+	/* For UDP, we need to provide an address */
+	if (!xprt->stream) {
+		addr = (struct sockaddr *) &xprt->addr;
+		addrlen = sizeof(xprt->addr);
+	}
 	/* Dont repeat bytes */
 	skip = req->rq_bytes_sent;
-	slen = xdr->len - skip;
-	niov = xdr_kmap(niv, xdr, skip);
-
-	msg.msg_flags   = MSG_DONTWAIT|MSG_NOSIGNAL;
-	msg.msg_iov	= niv;
-	msg.msg_iovlen	= niov;
-	msg.msg_name	= (struct sockaddr *) &xprt->addr;
-	msg.msg_namelen = sizeof(xprt->addr);
-	msg.msg_control = NULL;
-	msg.msg_controllen = 0;
 
-	oldfs = get_fs(); set_fs(get_ds());
 	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
-	result = sock_sendmsg(sock, &msg, slen);
-	set_fs(oldfs);
+	result = xdr_sendpages(sock, addr, addrlen, xdr, skip, MSG_DONTWAIT);
 
-	xdr_kunmap(xdr, skip);
-
-	dprintk("RPC:      xprt_sendmsg(%d) = %d\n", slen, result);
+	dprintk("RPC:      xprt_sendmsg(%d) = %d\n", xdr->len - skip, result);
 
 	if (result >= 0)
 		return result;
@@ -259,6 +249,7 @@
 		 */
 	case -EAGAIN:
 		break;
+	case -ECONNRESET:
 	case -ENOTCONN:
 	case -EPIPE:
 		/* connection broken */
@@ -376,6 +367,7 @@
 	if (!sk)
 		return;
 
+	write_lock_bh(&sk->callback_lock);
 	xprt->inet = NULL;
 	xprt->sock = NULL;
 
@@ -383,6 +375,7 @@
 	sk->data_ready   = xprt->old_data_ready;
 	sk->state_change = xprt->old_state_change;
 	sk->write_space  = xprt->old_write_space;
+	write_unlock_bh(&sk->callback_lock);
 
 	xprt_disconnect(xprt);
 	sk->no_check	 = 0;
@@ -397,14 +390,15 @@
 xprt_disconnect(struct rpc_xprt *xprt)
 {
 	dprintk("RPC:      disconnected transport %p\n", xprt);
+	spin_lock_bh(&xprt->sock_lock);
 	xprt_clear_connected(xprt);
 	rpc_wake_up_status(&xprt->pending, -ENOTCONN);
+	spin_unlock_bh(&xprt->sock_lock);
 }
 
 /*
  * Attempt to connect a TCP socket.
  *
- * NB: This never collides with TCP reads, as both run from rpciod
  */
 void
 xprt_connect(struct rpc_task *task)
@@ -442,6 +436,10 @@
 		goto out_write;
 	}
 	xprt_bind_socket(xprt, sock);
+
+	if (!xprt->stream)
+		goto out_write;
+
 	inet = sock->sk;
 
 	/*
@@ -452,6 +450,9 @@
 	dprintk("RPC: %4d  connect status %d connected %d sock state %d\n",
 		task->tk_pid, -status, xprt_connected(xprt), inet->state);
 
+	if (status >= 0)
+		return;
+
 	switch (status) {
 	case -EINPROGRESS:
 	case -EALREADY:
@@ -464,53 +465,37 @@
 			/* if the socket is already closing, delay briefly */
 			if ((1 << inet->state) & ~(TCPF_SYN_SENT|TCPF_SYN_RECV))
 				task->tk_timeout = RPC_REESTABLISH_TIMEOUT;
-			rpc_sleep_on(&xprt->pending, task, xprt_conn_status,
+			rpc_sleep_on(&xprt->pending, task, xprt_connect_status,
 									NULL);
-			release_sock(inet);
-			/* task status set when task wakes up again */
-			return;
 		}
 		release_sock(inet);
-		task->tk_status = 0;
 		break;
-
-	case 0:
-	case -EISCONN:	/* not likely, but just in case */
-		/* Half closed state.  No race -- this socket is dead. */
-		if (inet->state != TCP_ESTABLISHED) {
-			xprt_close(xprt);
-			task->tk_status = -EAGAIN;
-			goto out_write;
+	case -ECONNREFUSED:
+	case -ECONNRESET:
+	case -ENOTCONN:
+		if (!task->tk_client->cl_softrtry) {
+			rpc_delay(task, RPC_REESTABLISH_TIMEOUT);
+			task->tk_status = -ENOTCONN;
+			break;
 		}
-
-		/* Otherwise, the connection is already established. */
-		task->tk_status = 0;
-		break;
-
-	case -EPIPE:
-		xprt_close(xprt);
-		task->tk_status = -ENOTCONN;
-		goto out_write;
-
 	default:
 		/* Report myriad other possible returns.  If this file
 		 * system is soft mounted, just error out, like Solaris.  */
-		xprt_close(xprt);
 		if (task->tk_client->cl_softrtry) {
 			printk(KERN_WARNING
 			"RPC: error %d connecting to server %s, exiting\n",
 					-status, task->tk_client->cl_server);
 			task->tk_status = -EIO;
-		} else {
-			printk(KERN_WARNING
-			"RPC: error %d connecting to server %s\n",
-					-status, task->tk_client->cl_server);
-			rpc_delay(task, RPC_REESTABLISH_TIMEOUT);
-			task->tk_status = status;
+			goto out_write;
 		}
+		printk(KERN_WARNING "RPC: error %d connecting to server %s\n",
+				-status, task->tk_client->cl_server);
+		/* This will prevent anybody else from reconnecting */
+		rpc_delay(task, RPC_REESTABLISH_TIMEOUT);
+		task->tk_status = status;
 		break;
 	}
-
+	return;
  out_write:
 	xprt_release_write(xprt, task);
 }
@@ -519,33 +504,32 @@
  * We arrive here when awoken from waiting on connection establishment.
  */
 static void
-xprt_conn_status(struct rpc_task *task)
+xprt_connect_status(struct rpc_task *task)
 {
 	struct rpc_xprt	*xprt = task->tk_xprt;
 
-	switch (task->tk_status) {
-	case 0:
-		dprintk("RPC: %4d xprt_conn_status: connection established\n",
+	if (task->tk_status >= 0) {
+		dprintk("RPC: %4d xprt_connect_status: connection established\n",
 				task->tk_pid);
-		goto out;
+		return;
+	}
+
+	/* if soft mounted, just cause this RPC to fail */
+	if (task->tk_client->cl_softrtry)
+		task->tk_status = -EIO;
+
+	switch (task->tk_status) {
+	case -ENOTCONN:
+		rpc_delay(task, RPC_REESTABLISH_TIMEOUT);
+		return;
 	case -ETIMEDOUT:
-		dprintk("RPC: %4d xprt_conn_status: timed out\n",
+		dprintk("RPC: %4d xprt_connect_status: timed out\n",
 				task->tk_pid);
-		/* prevent TCP from continuing to retry SYNs */
-		xprt_close(xprt);
 		break;
 	default:
 		printk(KERN_ERR "RPC: error %d connecting to server %s\n",
 				-task->tk_status, task->tk_client->cl_server);
-		xprt_close(xprt);
-		rpc_delay(task, RPC_REESTABLISH_TIMEOUT);
-		break;
 	}
-	/* if soft mounted, cause this RPC to fail */
-	if (task->tk_client->cl_softrtry)
-		task->tk_status = -EIO;
-
- out:
 	xprt_release_write(xprt, task);
 }
 
@@ -695,6 +679,7 @@
 	struct sk_buff	*skb;
 	int		err, repsize, copied;
 
+	read_lock(&sk->callback_lock);
 	dprintk("RPC:      udp_data_ready...\n");
 	if (!(xprt = xprt_from_sock(sk))) {
 		printk("RPC:      udp_data_ready request not found!\n");
@@ -745,6 +730,7 @@
  out:
 	if (sk->sleep && waitqueue_active(sk->sleep))
 		wake_up_interruptible(sk->sleep);
+	read_unlock(&sk->callback_lock);
 }
 
 /*
@@ -939,7 +925,7 @@
 		}
 		/* Skip over any trailing bytes on short reads */
 		tcp_read_discard(xprt, &desc);
-	} while (desc.count && xprt_connected(xprt));
+	} while (desc.count);
 	dprintk("RPC:      tcp_data_recv done\n");
 	return len - desc.count;
 }
@@ -949,18 +935,21 @@
 	struct rpc_xprt *xprt;
 	read_descriptor_t rd_desc;
 
+	read_lock(&sk->callback_lock);
 	dprintk("RPC:      tcp_data_ready...\n");
 	if (!(xprt = xprt_from_sock(sk))) {
 		printk("RPC:      tcp_data_ready socket info not found!\n");
-		return;
+		goto out;
 	}
 	if (xprt->shutdown)
-		return;
+		goto out;
 
 	/* We use rd_desc to pass struct xprt to tcp_data_recv */
 	rd_desc.buf = (char *)xprt;
 	rd_desc.count = 65536;
 	tcp_read_sock(sk, &rd_desc, tcp_data_recv);
+out:
+	read_unlock(&sk->callback_lock);
 }
 
 static void
@@ -968,6 +957,7 @@
 {
 	struct rpc_xprt	*xprt;
 
+	read_lock(&sk->callback_lock);
 	if (!(xprt = xprt_from_sock(sk)))
 		goto out;
 	dprintk("RPC:      tcp_state_change client %p...\n", xprt);
@@ -977,19 +967,19 @@
 
 	switch (sk->state) {
 	case TCP_ESTABLISHED:
-		if (xprt_test_and_set_connected(xprt))
-			break;
+		spin_lock_bh(&xprt->sock_lock);
+		if (!xprt_test_and_set_connected(xprt)) {
+			/* Reset TCP record info */
+			xprt->tcp_offset = 0;
+			xprt->tcp_reclen = 0;
+			xprt->tcp_copied = 0;
+			xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
 
-		/* Reset TCP record info */
-		xprt->tcp_offset = 0;
-		xprt->tcp_reclen = 0;
-		xprt->tcp_copied = 0;
-		xprt->tcp_flags = XPRT_COPY_RECM | XPRT_COPY_XID;
-
-		spin_lock(&xprt->sock_lock);
-		if (xprt->snd_task && xprt->snd_task->tk_rpcwait == &xprt->pending)
-			rpc_wake_up_task(xprt->snd_task);
-		spin_unlock(&xprt->sock_lock);
+			if (xprt->snd_task)
+				rpc_wake_up_task(xprt->snd_task);
+			rpc_wake_up(&xprt->pending);
+		}
+		spin_unlock_bh(&xprt->sock_lock);
 		break;
 	case TCP_SYN_SENT:
 	case TCP_SYN_RECV:
@@ -1001,6 +991,7 @@
  out:
 	if (sk->sleep && waitqueue_active(sk->sleep))
 		wake_up_interruptible_all(sk->sleep);
+	read_unlock(&sk->callback_lock);
 }
 
 /*
@@ -1015,24 +1006,25 @@
 	struct rpc_xprt	*xprt;
 	struct socket	*sock;
 
+	read_lock(&sk->callback_lock);
 	if (!(xprt = xprt_from_sock(sk)) || !(sock = sk->socket))
-		return;
+		goto out;
 	if (xprt->shutdown)
-		return;
+		goto out;
 
 	/* Wait until we have enough socket memory */
 	if (xprt->stream) {
 		/* from net/ipv4/tcp.c:tcp_write_space */
 		if (tcp_wspace(sk) < tcp_min_write_space(sk))
-			return;
+			goto out;
 	} else {
 		/* from net/core/sock.c:sock_def_write_space */
 		if (!sock_writeable(sk))
-			return;
+			goto out;
 	}
 
 	if (!test_and_clear_bit(SOCK_NOSPACE, &sock->flags))
-		return;
+		goto out;
 
 	spin_lock_bh(&xprt->sock_lock);
 	if (xprt->snd_task && xprt->snd_task->tk_rpcwait == &xprt->pending)
@@ -1040,6 +1032,8 @@
 	spin_unlock_bh(&xprt->sock_lock);
 	if (sk->sleep && waitqueue_active(sk->sleep))
 		wake_up_interruptible(sk->sleep);
+out:
+	read_unlock(&sk->callback_lock);
 }
 
 /*
@@ -1107,9 +1101,6 @@
 	if (xprt->shutdown)
 		return -EIO;
 
-	if (!xprt_connected(xprt))
-		return -ENOTCONN;
-
 	if (task->tk_rpcwait)
 		rpc_remove_wait_queue(task);
 
@@ -1118,6 +1109,12 @@
 		err = -EAGAIN;
 		goto out_unlock;
 	}
+
+	if (!xprt_connected(xprt)) {
+		err = -ENOTCONN;
+		goto out_unlock;
+	}
+
 	if (list_empty(&req->rq_list)) {
 		list_add_tail(&req->rq_list, &xprt->recv);
 		req->rq_received = 0;
@@ -1192,7 +1189,10 @@
 		if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
 			/* Protect against races with xprt_write_space */
 			spin_lock_bh(&xprt->sock_lock);
-			if (test_bit(SOCK_NOSPACE, &xprt->sock->flags)) {
+			/* Don't race with disconnect */
+			if (!xprt_connected(xprt))
+				task->tk_status = -ENOTCONN;
+			else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags)) {
 				task->tk_timeout = req->rq_timeout.to_current;
 				rpc_sleep_on(&xprt->pending, task, NULL, NULL);
 			}
@@ -1203,20 +1203,17 @@
 		rpc_delay(task, HZ>>4);
 		return;
 	case -ECONNREFUSED:
+		task->tk_timeout = RPC_REESTABLISH_TIMEOUT;
+		rpc_sleep_on(&xprt->sending, task, NULL, NULL);
 	case -ENOTCONN:
-		if (!xprt->stream) {
-			task->tk_timeout = RPC_REESTABLISH_TIMEOUT;
-			rpc_sleep_on(&xprt->sending, task, NULL, NULL);
-			return;
-		}
-		/* fall through */
+		return;
 	default:
 		if (xprt->stream)
 			xprt_disconnect(xprt);
-		req->rq_bytes_sent = 0;
 	}
  out_release:
 	xprt_release_write(xprt, task);
+	req->rq_bytes_sent = 0;
 	return;
  out_receive:
 	dprintk("RPC: %4d xmit complete\n", task->tk_pid);
@@ -1230,10 +1227,14 @@
 	} else
 		task->tk_timeout = req->rq_timeout.to_current;
 	spin_lock_bh(&xprt->sock_lock);
-	if (!req->rq_received)
+	/* Don't race with disconnect */
+	if (!xprt_connected(xprt))
+		task->tk_status = -ENOTCONN;
+	else if (!req->rq_received)
 		rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
 	__xprt_release_write(xprt, task);
 	spin_unlock_bh(&xprt->sock_lock);
+	req->rq_bytes_sent = 0;
 }
 
 /*
@@ -1417,6 +1418,9 @@
 	req->rq_next = NULL;
 	xprt->free = xprt->slot;
 
+	/* Check whether we want to use a reserved port */
+	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
+
 	dprintk("RPC:      created transport %p\n", xprt);
 	
 	return xprt;
@@ -1430,6 +1434,12 @@
 {
 	struct sockaddr_in myaddr;
 	int		err, port;
+	kernel_cap_t saved_cap = current->cap_effective;
+
+	/* Override capabilities.
+	 * They were checked in xprt_create_proto i.e. at mount time
+	 */
+	cap_raise(current->cap_effective, CAP_NET_BIND_SERVICE);
 
 	memset(&myaddr, 0, sizeof(myaddr));
 	myaddr.sin_family = AF_INET;
@@ -1439,6 +1449,7 @@
 		err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
 						sizeof(myaddr));
 	} while (err == -EADDRINUSE && --port > 0);
+	current->cap_effective = saved_cap;
 
 	if (err < 0)
 		printk("RPC: Can't bind to reserved port (%d).\n", -err);
@@ -1454,6 +1465,7 @@
 	if (xprt->inet)
 		return;
 
+	write_lock_bh(&sk->callback_lock);
 	sk->user_data = xprt;
 	xprt->old_data_ready = sk->data_ready;
 	xprt->old_state_change = sk->state_change;
@@ -1474,6 +1486,7 @@
 	/* Reset to new socket */
 	xprt->sock = sock;
 	xprt->inet = sk;
+	write_unlock_bh(&sk->callback_lock);
 
 	return;
 }
@@ -1544,16 +1557,6 @@
 	if (!xprt)
 		goto out_bad;
 
-	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
-	if (!xprt->stream) {
-		struct socket *sock;
-
-		sock = xprt_create_socket(proto, to, xprt->resvport);
-		if (!sock)
-			goto out_bad;
-		xprt_bind_socket(xprt, sock);
-	}
-
 	dprintk("RPC:      xprt_create_proto created xprt %p\n", xprt);
 	return xprt;
  out_bad:
