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

diff -urN linux-2.5.69-bk2/CREDITS linux-2.5.69-bk3/CREDITS
--- linux-2.5.69-bk2/CREDITS	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk3/CREDITS	2003-05-08 04:38:16.000000000 -0700
@@ -3027,8 +3027,8 @@
 W: http://www.cs.helsinki.fi/Linus.Torvalds
 P: 1024/A86B35C5 96 54 50 29 EC 11 44 7A  BE 67 3C 24 03 13 62 C8
 D: Original kernel hacker
-S: 1050 Woodduck Avenue
-S: Santa Clara, California 95051
+S: 3990 Freedom Circle
+S: Santa Clara, California 95054
 S: USA
 
 N: Marcelo W. Tosatti
diff -urN linux-2.5.69-bk2/Documentation/Changes linux-2.5.69-bk3/Documentation/Changes
--- linux-2.5.69-bk2/Documentation/Changes	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk3/Documentation/Changes	2003-05-08 04:38:16.000000000 -0700
@@ -50,7 +50,7 @@
 
 o  Gnu C                  2.95.3                  # gcc --version
 o  Gnu make               3.78                    # make --version
-o  binutils               2.9.5.0.25              # ld -v
+o  binutils               2.12                    # ld -v
 o  util-linux             2.10o                   # fdformat --version
 o  module-init-tools      0.9.9                   # depmod -V
 o  e2fsprogs              1.29                    # tune2fs
diff -urN linux-2.5.69-bk2/MAINTAINERS linux-2.5.69-bk3/MAINTAINERS
--- linux-2.5.69-bk2/MAINTAINERS	2003-05-08 04:38:12.000000000 -0700
+++ linux-2.5.69-bk3/MAINTAINERS	2003-05-08 04:38:16.000000000 -0700
@@ -679,7 +679,7 @@
 
 EXT3 FILE SYSTEM
 P:	Stephen Tweedie, Andrew Morton
-M:	sct@redhat.com, akpm@zip.com.au, adilger@clusterfs.com
+M:	sct@redhat.com, akpm@digeo.com, adilger@clusterfs.com
 L:	ext3-users@redhat.com
 S:	Maintained
 
@@ -1257,7 +1257,7 @@
 
 NETWORK DEVICE DRIVERS
 P:	Andrew Morton
-M:	akpm@zip.com.au
+M:	akpm@digeo.com
 P:	Jeff Garzik
 M:	jgarzik@pobox.com
 L:	linux-net@vger.kernel.org
diff -urN linux-2.5.69-bk2/Makefile linux-2.5.69-bk3/Makefile
--- linux-2.5.69-bk2/Makefile	2003-05-08 04:38:12.000000000 -0700
+++ linux-2.5.69-bk3/Makefile	2003-05-08 04:38:16.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 69
-EXTRAVERSION = -bk2
+EXTRAVERSION = -bk3
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -90,7 +90,7 @@
   KBUILD_MODULES := 1
 endif
 
-export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE
+export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE KBUILD_CHECKSRC
 
 # Beautify output
 # ---------------------------------------------------------------------------
@@ -118,6 +118,16 @@
   KBUILD_VERBOSE = 1
 endif
 
+ifdef C
+  ifeq ("$(origin C)", "command line")
+    KBUILD_CHECKSRC = $(C)
+  endif
+endif
+ifndef KBUILD_CHECKSRC
+  KBUILD_CHECKSRC = 0
+endif
+
+
 MAKEFLAGS += --no-print-directory
 
 # For maximum performance (+ possibly random breakage, uncomment
@@ -172,6 +182,7 @@
 DEPMOD		= /sbin/depmod
 KALLSYMS	= scripts/kallsyms
 PERL		= perl
+CHECK		= /home/torvalds/parser/check
 MODFLAGS	= -DMODULE
 CFLAGS_MODULE   = $(MODFLAGS)
 AFLAGS_MODULE   = $(MODFLAGS)
@@ -189,7 +200,7 @@
 export	VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \
 	CONFIG_SHELL TOPDIR HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
 	CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \
-	HOSTCXX HOSTCXXFLAGS LDFLAGS_BLOB LDFLAGS_MODULE
+	HOSTCXX HOSTCXXFLAGS LDFLAGS_BLOB LDFLAGS_MODULE CHECK
 
 export CPPFLAGS NOSTDINC_FLAGS OBJCOPYFLAGS LDFLAGS
 export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE 
diff -urN linux-2.5.69-bk2/arch/i386/Kconfig linux-2.5.69-bk3/arch/i386/Kconfig
--- linux-2.5.69-bk2/arch/i386/Kconfig	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk3/arch/i386/Kconfig	2003-05-08 04:38:16.000000000 -0700
@@ -65,19 +65,16 @@
 
 config X86_SUMMIT
 	bool "Summit/EXA (IBM x440)"
+	depends on SMP
 	help
 	  This option is needed for IBM systems that use the Summit/EXA chipset.
 	  In particular, it is needed for the x440.
 
 	  If you don't have one of these computers, you should say N here.
 
-config ACPI_SRAT
-	bool
-	default y
-	depends on NUMA && X86_SUMMIT
-
 config X86_BIGSMP
 	bool "Support for other sub-arch SMP systems with more than 8 CPUs"
+	depends on SMP
 	help
 	  This option is needed for the systems that have more than 8 CPUs
 	  and if the system is not of any sub-arch type above.
@@ -95,8 +92,24 @@
 	  A kernel compiled for the Visual Workstation will not run on PCs
 	  and vice versa. See <file:Documentation/sgi-visws.txt> for details.
 
+config X86_GENERICARCH
+       bool "Generic architecture (Summit, bigsmp, default)"
+       depends on SMP
+       help
+          This option compiles in the Summit, bigsmp, default subarchitectures.
+	  It is intended for a generic binary kernel.
+
 endchoice
 
+config ACPI_SRAT
+	bool
+	default y
+	depends on NUMA && (X86_SUMMIT || X86_GENERICARCH)
+
+config X86_CYCLONE_TIMER
+       bool 
+       default y
+       depends on X86_SUMMIT || X86_GENERICARCH
 
 choice
 	prompt "Processor family"
@@ -666,7 +679,7 @@
 # Common NUMA Features
 config NUMA
 	bool "Numa Memory Allocation Support"
-	depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY))
+	depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY))
 	default n if X86_PC
 	default y if (X86_NUMAQ || X86_SUMMIT)
 
@@ -764,7 +777,7 @@
 # Summit needs it only when NUMA is on
 config BOOT_IOREMAP
 	bool
-	depends on (X86_SUMMIT && NUMA)
+	depends on ((X86_SUMMIT || X86_GENERICARCH) && NUMA)
 	default y
 
 endmenu
diff -urN linux-2.5.69-bk2/arch/i386/Makefile linux-2.5.69-bk3/arch/i386/Makefile
--- linux-2.5.69-bk2/arch/i386/Makefile	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk3/arch/i386/Makefile	2003-05-08 04:38:16.000000000 -0700
@@ -73,6 +73,11 @@
 mflags-$(CONFIG_X86_SUMMIT) := -Iinclude/asm-i386/mach-summit
 mcore-$(CONFIG_X86_SUMMIT)  := mach-default
 
+# generic subarchitecture
+mflags-$(CONFIG_X86_GENERICARCH) := -Iinclude/asm-i386/mach-generic
+mcore-$(CONFIG_X86_GENERICARCH) := mach-default
+core-$(CONFIG_X86_GENERICARCH) += arch/i386/mach-generic/
+
 # default subarch .h files
 mflags-y += -Iinclude/asm-i386/mach-default
 
diff -urN linux-2.5.69-bk2/arch/i386/kernel/io_apic.c linux-2.5.69-bk3/arch/i386/kernel/io_apic.c
--- linux-2.5.69-bk2/arch/i386/kernel/io_apic.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk3/arch/i386/kernel/io_apic.c	2003-05-08 04:38:16.000000000 -0700
@@ -280,7 +280,9 @@
 extern unsigned long irq_affinity[NR_IRQS];
 
 static int __cacheline_aligned pending_irq_balance_apicid[NR_IRQS];
-static int irqbalance_disabled = NO_BALANCE_IRQ;
+
+#define IRQBALANCE_CHECK_ARCH -999
+static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH;
 static int physical_balance = 0;
 
 struct irq_cpu_info {
@@ -342,8 +344,10 @@
 	unsigned long allowed_mask;
 	unsigned int new_cpu;
 		
-	if (irqbalance_disabled)
+	if (irqbalance_disabled == IRQBALANCE_CHECK_ARCH && NO_BALANCE_IRQ)
 		return;
+	else if (irqbalance_disabled) 
+		return; 
 
 	allowed_mask = cpu_online_map & irq_affinity[irq];
 	new_cpu = move(cpu, allowed_mask, now, 1);
diff -urN linux-2.5.69-bk2/arch/i386/kernel/mpparse.c linux-2.5.69-bk3/arch/i386/kernel/mpparse.c
--- linux-2.5.69-bk2/arch/i386/kernel/mpparse.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk3/arch/i386/kernel/mpparse.c	2003-05-08 04:38:16.000000000 -0700
@@ -73,7 +73,9 @@
 /* Bitmask of physically existing CPUs */
 unsigned long phys_cpu_present_map;
 
+#ifndef CONFIG_X86_GENERICARCH
 int x86_summit = 0;
+#endif
 u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
 
 /*
diff -urN linux-2.5.69-bk2/arch/i386/kernel/setup.c linux-2.5.69-bk3/arch/i386/kernel/setup.c
--- linux-2.5.69-bk2/arch/i386/kernel/setup.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk3/arch/i386/kernel/setup.c	2003-05-08 04:38:16.000000000 -0700
@@ -91,6 +91,7 @@
 
 extern void early_cpu_init(void);
 extern void dmi_scan_machine(void);
+extern void generic_apic_probe(char *);
 extern int root_mountflags;
 extern char _text, _etext, _edata, _end;
 extern int blk_nohighio;
@@ -959,6 +960,13 @@
 	smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
 #endif
 	paging_init();
+
+	dmi_scan_machine();
+
+#ifdef CONFIG_X86_GENERICARCH
+	generic_apic_probe(*cmdline_p);
+#endif	
+
 #ifdef CONFIG_ACPI_BOOT
 	/*
 	 * Parse the ACPI tables for possible boot-time SMP configuration.
@@ -980,7 +988,6 @@
 	conswitchp = &dummy_con;
 #endif
 #endif
-	dmi_scan_machine();
 }
 
 static int __init highio_setup(char *str)
diff -urN linux-2.5.69-bk2/arch/i386/kernel/smp.c linux-2.5.69-bk3/arch/i386/kernel/smp.c
--- linux-2.5.69-bk2/arch/i386/kernel/smp.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk3/arch/i386/kernel/smp.c	2003-05-08 04:38:16.000000000 -0700
@@ -123,7 +123,7 @@
 	return SET_APIC_DEST_FIELD(mask);
 }
 
-static inline void __send_IPI_shortcut(unsigned int shortcut, int vector)
+inline void __send_IPI_shortcut(unsigned int shortcut, int vector)
 {
 	/*
 	 * Subtle. In the case of the 'never do double writes' workaround
@@ -155,7 +155,7 @@
 	__send_IPI_shortcut(APIC_DEST_SELF, vector);
 }
 
-static inline void send_IPI_mask_bitmask(int mask, int vector)
+inline void send_IPI_mask_bitmask(int mask, int vector)
 {
 	unsigned long cfg;
 	unsigned long flags;
@@ -186,7 +186,7 @@
 	local_irq_restore(flags);
 }
 
-static inline void send_IPI_mask_sequence(int mask, int vector)
+inline void send_IPI_mask_sequence(int mask, int vector)
 {
 	unsigned long cfg, flags;
 	unsigned int query_cpu, query_mask;
diff -urN linux-2.5.69-bk2/arch/i386/kernel/timers/Makefile linux-2.5.69-bk3/arch/i386/kernel/timers/Makefile
--- linux-2.5.69-bk2/arch/i386/kernel/timers/Makefile	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk3/arch/i386/kernel/timers/Makefile	2003-05-08 04:38:16.000000000 -0700
@@ -4,4 +4,4 @@
 
 obj-y := timer.o timer_none.o timer_tsc.o timer_pit.o
 
-obj-$(CONFIG_X86_SUMMIT)	+= timer_cyclone.o
+obj-$(CONFIG_X86_CYCLONE_TIMER)	+= timer_cyclone.o
diff -urN linux-2.5.69-bk2/arch/i386/kernel/timers/timer.c linux-2.5.69-bk3/arch/i386/kernel/timers/timer.c
--- linux-2.5.69-bk2/arch/i386/kernel/timers/timer.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk3/arch/i386/kernel/timers/timer.c	2003-05-08 04:38:16.000000000 -0700
@@ -6,12 +6,12 @@
 /* list of externed timers */
 extern struct timer_opts timer_pit;
 extern struct timer_opts timer_tsc;
-#ifdef CONFIG_X86_SUMMIT
+#ifdef CONFIG_X86_CYCLONE_TIMER
 extern struct timer_opts timer_cyclone;
 #endif
 /* list of timers, ordered by preference, NULL terminated */
 static struct timer_opts* timers[] = {
-#ifdef CONFIG_X86_SUMMIT
+#ifdef CONFIG_X86_CYCLONE_TIMER
 	&timer_cyclone,
 #endif
 	&timer_tsc,
diff -urN linux-2.5.69-bk2/arch/i386/lib/usercopy.c linux-2.5.69-bk3/arch/i386/lib/usercopy.c
--- linux-2.5.69-bk2/arch/i386/lib/usercopy.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk3/arch/i386/lib/usercopy.c	2003-05-08 04:38:16.000000000 -0700
@@ -6,6 +6,9 @@
  * Copyright 1997 Linus Torvalds
  */
 #include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/blkdev.h>
 #include <asm/uaccess.h>
 #include <asm/mmx.h>
 
@@ -483,6 +486,53 @@
 
 unsigned long __copy_to_user_ll(void *to, const void *from, unsigned long n)
 {
+#ifndef CONFIG_X86_WP_WORKS_OK
+	if (unlikely(boot_cpu_data.wp_works_ok == 0) &&
+			((unsigned long )to) < TASK_SIZE) {
+		/* 
+		 * CPU does not honor the WP bit when writing
+		 * from supervisory mode, and due to preemption or SMP,
+		 * the page tables can change at any time.
+		 * Do it manually.	Manfred <manfred@colorfullife.com>
+		 */
+		while (n) {
+		      	unsigned long offset = ((unsigned long)to)%PAGE_SIZE;
+			unsigned long len = PAGE_SIZE - offset;
+			int retval;
+			struct page *pg;
+			void *maddr;
+			
+			if (len > n)
+				len = n;
+
+survive:
+			down_read(&current->mm->mmap_sem);
+			retval = get_user_pages(current, current->mm,
+					(unsigned long )to, 1, 1, 0, &pg, NULL);
+
+			if (retval == -ENOMEM && current->pid == 1) {
+				up_read(&current->mm->mmap_sem);
+				blk_congestion_wait(WRITE, HZ/50);
+				goto survive;
+			}
+
+			if (retval != 1)
+		       		break;
+
+			maddr = kmap_atomic(pg, KM_USER0);
+			memcpy(maddr + offset, from, len);
+			kunmap_atomic(maddr, KM_USER0);
+			set_page_dirty_lock(pg);
+			put_page(pg);
+			up_read(&current->mm->mmap_sem);
+
+			from += len;
+			to += len;
+			n -= len;
+		}
+		return n;
+	}
+#endif
 	if (movsl_is_ok(to, from, n))
 		__copy_user(to, from, n);
 	else
diff -urN linux-2.5.69-bk2/arch/i386/mach-generic/Makefile linux-2.5.69-bk3/arch/i386/mach-generic/Makefile
--- linux-2.5.69-bk2/arch/i386/mach-generic/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/arch/i386/mach-generic/Makefile	2003-05-08 04:38:16.000000000 -0700
@@ -0,0 +1,18 @@
+#
+# Makefile for the generic architecture
+#
+
+EXTRA_CFLAGS	+= -I../kernel
+
+obj-y				:= probe.o summit.o bigsmp.o default.o
+
+
+#
+# Makefile for the generic architecture
+#
+
+EXTRA_CFLAGS	+= -I../kernel
+
+obj-y				:= probe.o summit.o bigsmp.o default.o
+
+
diff -urN linux-2.5.69-bk2/arch/i386/mach-generic/bigsmp.c linux-2.5.69-bk3/arch/i386/mach-generic/bigsmp.c
--- linux-2.5.69-bk2/arch/i386/mach-generic/bigsmp.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/arch/i386/mach-generic/bigsmp.c	2003-05-08 04:38:16.000000000 -0700
@@ -0,0 +1,23 @@
+/* 
+ * APIC driver for "bigsmp" XAPIC machines with more than 8 virtual CPUs.
+ * Drives the local APIC in "clustered mode".
+ */
+#define APIC_DEFINITION 1
+#include <asm/genapic.h>
+#include <asm/fixmap.h>
+#include <asm/apicdef.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <asm/mach-bigsmp/mach_apic.h>
+#include <asm/mach-bigsmp/mach_ipi.h>
+#include <asm/mach-default/mach_mpparse.h>
+
+int dmi_bigsmp; /* can be set by dmi scanners */
+
+static __init int probe_bigsmp(void)
+{ 
+	return dmi_bigsmp; 
+} 
+
+struct genapic apic_bigsmp = APIC_INIT("bigsmp", probe_bigsmp); 
diff -urN linux-2.5.69-bk2/arch/i386/mach-generic/default.c linux-2.5.69-bk3/arch/i386/mach-generic/default.c
--- linux-2.5.69-bk2/arch/i386/mach-generic/default.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/arch/i386/mach-generic/default.c	2003-05-08 04:38:16.000000000 -0700
@@ -0,0 +1,22 @@
+/* 
+ * Default generic APIC driver. This handles upto 8 CPUs.
+ */
+#define APIC_DEFINITION 1
+#include <asm/genapic.h>
+#include <asm/fixmap.h>
+#include <asm/apicdef.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <asm/mach-default/mach_apic.h>
+#include <asm/mach-default/mach_ipi.h>
+#include <asm/mach-default/mach_mpparse.h>
+
+/* should be called last. */
+static __init int probe_default(void)
+{ 
+	return 1;
+} 
+
+struct genapic apic_default = APIC_INIT("default", probe_default); 
diff -urN linux-2.5.69-bk2/arch/i386/mach-generic/probe.c linux-2.5.69-bk3/arch/i386/mach-generic/probe.c
--- linux-2.5.69-bk2/arch/i386/mach-generic/probe.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/arch/i386/mach-generic/probe.c	2003-05-08 04:38:16.000000000 -0700
@@ -0,0 +1,96 @@
+/* Copyright 2003 Andi Kleen, SuSE Labs. 
+ * Subject to the GNU Public License, v.2 
+ * 
+ * Generic x86 APIC driver probe layer.
+ */  
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <asm/fixmap.h>
+#include <asm/apicdef.h>
+#include <asm/genapic.h>
+
+extern struct genapic apic_summit;
+extern struct genapic apic_bigsmp;
+extern struct genapic apic_default;
+
+struct genapic *genapic = &apic_default;
+
+struct genapic *apic_probe[] __initdata = { 
+	&apic_summit,
+	&apic_bigsmp, 
+	&apic_default,	/* must be last */
+	NULL,
+};
+
+void __init generic_apic_probe(char *command_line) 
+{ 
+	char *s;
+	int i;
+	int changed = 0;
+
+	s = strstr(command_line, "apic=");
+	if (s && (s == command_line || isspace(s[-1]))) { 
+		char *p = strchr(s, ' '), old; 
+		if (!p)
+			p = strchr(s, '\0'); 
+		old = *p; 
+		*p = 0; 
+		for (i = 0; !changed && apic_probe[i]; i++) {
+			if (!strcmp(apic_probe[i]->name, s+5)) { 
+				changed = 1;
+				genapic = apic_probe[i];
+			}
+		}
+		if (!changed)
+			printk(KERN_ERR "Unknown genapic `%s' specified.\n", s);
+		*p = old;
+	} 
+	for (i = 0; !changed && apic_probe[i]; i++) { 
+		if (apic_probe[i]->probe()) {
+			changed = 1;
+			genapic = apic_probe[i]; 
+		} 
+	}
+	/* Not visible without early console */ 
+	if (!changed) 
+		panic("Didn't find an APIC driver"); 
+
+	printk(KERN_INFO "Using APIC driver %s\n", genapic->name);
+} 
+
+/* These functions can switch the APIC even after the initial ->probe() */
+
+int __init mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid)
+{ 
+	int i;
+	for (i = 0; apic_probe[i]; ++i) { 
+		if (apic_probe[i]->mps_oem_check(mpc,oem,productid)) { 
+			genapic = apic_probe[i];
+			printk(KERN_INFO "Switched to APIC driver `%s'.\n", 
+			       genapic->name);
+			return 1;
+		} 
+	} 
+	return 0;
+} 
+
+int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+	int i;
+	for (i = 0; apic_probe[i]; ++i) { 
+		if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) { 
+			genapic = apic_probe[i];
+			printk(KERN_INFO "Switched to APIC driver `%s'.\n", 
+			       genapic->name);
+			return 1;
+		} 
+	} 
+	return 0;	
+}
+
+int hard_smp_processor_id(void)
+{
+	return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID));
+}
diff -urN linux-2.5.69-bk2/arch/i386/mach-generic/summit.c linux-2.5.69-bk3/arch/i386/mach-generic/summit.c
--- linux-2.5.69-bk2/arch/i386/mach-generic/summit.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/arch/i386/mach-generic/summit.c	2003-05-08 04:38:16.000000000 -0700
@@ -0,0 +1,22 @@
+/* 
+ * APIC driver for the IBM "Summit" chipset.
+ */
+#define APIC_DEFINITION 1
+#include <asm/genapic.h>
+#include <asm/fixmap.h>
+#include <asm/apicdef.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <asm/mach-summit/mach_apic.h>
+#include <asm/mach-summit/mach_ipi.h>
+#include <asm/mach-summit/mach_mpparse.h>
+
+static __init int probe_summit(void)
+{ 
+	/* probed later in mptable/ACPI hooks */
+	return 0;
+} 
+
+struct genapic apic_summit = APIC_INIT("summit", probe_summit); 
diff -urN linux-2.5.69-bk2/arch/i386/mm/fault.c linux-2.5.69-bk3/arch/i386/mm/fault.c
--- linux-2.5.69-bk2/arch/i386/mm/fault.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk3/arch/i386/mm/fault.c	2003-05-08 04:38:16.000000000 -0700
@@ -29,87 +29,6 @@
 
 extern void die(const char *,struct pt_regs *,long);
 
-#ifndef CONFIG_X86_WP_WORKS_OK
-/*
- * Ugly, ugly, but the goto's result in better assembly..
- */
-int __verify_write(const void * addr, unsigned long size)
-{
-	struct mm_struct *mm = current->mm;
-	struct vm_area_struct * vma;
-	unsigned long start = (unsigned long) addr;
-
-	if (!size || segment_eq(get_fs(),KERNEL_DS))
-		return 1;
-
-	down_read(&mm->mmap_sem);
-	vma = find_vma(current->mm, start);
-	if (!vma)
-		goto bad_area;
-	if (vma->vm_start > start)
-		goto check_stack;
-
-good_area:
-	if (!(vma->vm_flags & VM_WRITE))
-		goto bad_area;
-	size--;
-	size += start & ~PAGE_MASK;
-	size >>= PAGE_SHIFT;
-	start &= PAGE_MASK;
-
-	for (;;) {
-	survive:
-		switch (handle_mm_fault(current->mm, vma, start, 1)) {
-			case VM_FAULT_SIGBUS:
-				goto bad_area;
-			case VM_FAULT_OOM:
-				goto out_of_memory;
-			case VM_FAULT_MINOR:
-			case VM_FAULT_MAJOR:
-				break;
-			default:
-				BUG();
-		}
-		if (!size)
-			break;
-		size--;
-		start += PAGE_SIZE;
-		if (start < vma->vm_end)
-			continue;
-		vma = vma->vm_next;
-		if (!vma || vma->vm_start != start)
-			goto bad_area;
-		if (!(vma->vm_flags & VM_WRITE))
-			goto bad_area;;
-	}
-	/*
-	 * We really need to hold mmap_sem over the whole access to
-	 * userspace, else another thread could change permissions.
-	 * This is unfixable, so don't use i386-class machines for
-	 * critical servers.
-	 */
-	up_read(&mm->mmap_sem);
-	return 1;
-
-check_stack:
-	if (!(vma->vm_flags & VM_GROWSDOWN))
-		goto bad_area;
-	if (expand_stack(vma, start) == 0)
-		goto good_area;
-
-bad_area:
-	up_read(&mm->mmap_sem);
-	return 0;
-
-out_of_memory:
-	if (current->pid == 1) {
-		yield();
-		goto survive;
-	}
-	goto bad_area;
-}
-#endif
-
 /*
  * Unlock any spinlocks which will prevent us from getting the
  * message out 
@@ -405,8 +324,12 @@
 
 		if (!pgd_present(*pgd_k))
 			goto no_context;
-		set_pgd(pgd, *pgd_k);
-		
+
+		/*
+		 * set_pgd(pgd, *pgd_k); here would be useless on PAE
+		 * and redundant with the set_pmd() on non-PAE.
+		 */
+
 		pmd = pmd_offset(pgd, address);
 		pmd_k = pmd_offset(pgd_k, address);
 		if (!pmd_present(*pmd_k))
diff -urN linux-2.5.69-bk2/arch/i386/vmlinux.lds.S linux-2.5.69-bk3/arch/i386/vmlinux.lds.S
--- linux-2.5.69-bk2/arch/i386/vmlinux.lds.S	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk3/arch/i386/vmlinux.lds.S	2003-05-08 04:38:16.000000000 -0700
@@ -85,7 +85,11 @@
   __alt_instructions = .;
   .altinstructions : { *(.altinstructions) } 
   __alt_instructions_end = .; 
- .altinstr_replacement : { *(.altinstr_replacement) }
+ .altinstr_replacement : { *(.altinstr_replacement) } 
+  /* .exit.text is discard at runtime, not link time, to deal with references
+     from .altinstructions and .eh_frame */
+  .exit.text : { *(.exit.text) }
+  .exit.data : { *(.exit.data) }
   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
@@ -106,8 +110,6 @@
 
   /* Sections to be discarded */
   /DISCARD/ : {
-	*(.exit.text)
-	*(.exit.data)
 	*(.exitcall.exit)
 	}
 
diff -urN linux-2.5.69-bk2/arch/mips/au1000/common/serial.c linux-2.5.69-bk3/arch/mips/au1000/common/serial.c
--- linux-2.5.69-bk2/arch/mips/au1000/common/serial.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk3/arch/mips/au1000/common/serial.c	2003-05-08 04:38:16.000000000 -0700
@@ -2681,8 +2681,8 @@
 		       (state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
 		       state->port, state->irq,
 		       uart_config[state->type].name);
-		tty_register_device(&serial_driver, state->line);
-		tty_register_device(&callout_driver, state->line);
+		tty_register_device(&serial_driver, state->line, NULL);
+		tty_register_device(&callout_driver, state->line, NULL);
 	}
 	return 0;
 }
@@ -2769,8 +2769,8 @@
 	      state->iomem_base ? "iomem" : "port",
 	      state->iomem_base ? (unsigned long)state->iomem_base :
 	      state->port, state->irq, uart_config[state->type].name);
-	tty_register_device(&serial_driver, state->line); 
-	tty_register_device(&callout_driver, state->line);
+	tty_register_device(&serial_driver, state->line, NULL); 
+	tty_register_device(&callout_driver, state->line, NULL);
 	return state->line + SERIAL_DEV_OFFSET;
 }
 
diff -urN linux-2.5.69-bk2/arch/sparc64/solaris/socksys.c linux-2.5.69-bk3/arch/sparc64/solaris/socksys.c
--- linux-2.5.69-bk2/arch/sparc64/solaris/socksys.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk3/arch/sparc64/solaris/socksys.c	2003-05-08 04:38:16.000000000 -0700
@@ -191,10 +191,9 @@
 		printk ("Couldn't create socket\n");
 		return ret;
 	}
-	devfs_register (NULL, "socksys", DEVFS_FL_DEFAULT,
-		       30, 0,
-		       S_IFCHR | S_IRUSR | S_IWUSR,
-		       &socksys_fops, NULL);
+
+	devfs_mk_cdev(MKDEV(30, 0), S_IFCHR|S_IRUSR|S_IWUSR, "socksys");
+
 	file = fcheck(ret);
 	/* N.B. Is this valid? Suppose the f_ops are in a module ... */
 	socksys_file_ops = *file->f_op;
diff -urN linux-2.5.69-bk2/arch/um/drivers/mmapper_kern.c linux-2.5.69-bk3/arch/um/drivers/mmapper_kern.c
--- linux-2.5.69-bk2/arch/um/drivers/mmapper_kern.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk3/arch/um/drivers/mmapper_kern.c	2003-05-08 04:38:16.000000000 -0700
@@ -124,9 +124,7 @@
 
 	p_buf = __pa(v_buf);
 
-	devfs_register (NULL, "mmapper", DEVFS_FL_DEFAULT, 
-			30, 0, S_IFCHR | S_IRUGO | S_IWUGO, 
-			&mmapper_fops, NULL); 
+	devfs_mk_cdev(MKDEV(30, 0), S_IFCHR|S_IRUGO|S_IWUGO, "mmapper");
 	devfs_mk_symlink("mmapper0", "mmapper");
 	return(0);
 }
diff -urN linux-2.5.69-bk2/drivers/atm/Kconfig linux-2.5.69-bk3/drivers/atm/Kconfig
--- linux-2.5.69-bk2/drivers/atm/Kconfig	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk3/drivers/atm/Kconfig	2003-05-08 04:38:16.000000000 -0700
@@ -440,5 +440,19 @@
 	default m if ATM_FORE200E_MAYBE!=y
 	default y if ATM_FORE200E_MAYBE=y
 
+config ATM_HE
+	tristate "ForeRunner HE Series"
+	depends on PCI && ATM
+	help
+	  This is a driver for the Marconi ForeRunner HE-series ATM adapter
+	  cards. It simultaneously supports the 155 and 622 versions.
+
+config ATM_HE_USE_SUNI
+	bool "Use S/UNI PHY driver"
+	depends on ATM_HE
+	help
+	  Support for the S/UNI-Ultra and S/UNI-622 found in the ForeRunner
+	  HE cards.  This driver provides carrier detection some statistics.
+
 endmenu
 
diff -urN linux-2.5.69-bk2/drivers/atm/Makefile linux-2.5.69-bk3/drivers/atm/Makefile
--- linux-2.5.69-bk2/drivers/atm/Makefile	2003-05-04 16:52:59.000000000 -0700
+++ linux-2.5.69-bk3/drivers/atm/Makefile	2003-05-08 04:38:16.000000000 -0700
@@ -49,6 +49,10 @@
     CONFIG_ATM_FORE200E_SBA_FW	:= $(obj)/sba200e_ecd.bin2
   endif
 endif
+obj-$(CONFIG_ATM_HE)		+= he.o
+ifeq ($(CONFIG_ATM_HE_USE_SUNI),y)
+  obj-$(CONFIG_ATM_HE)		+= suni.o
+endif
 
 # FORE Systems 200E-series firmware magic
 $(obj)/fore200e_pca_fw.c: $(patsubst "%", %, $(CONFIG_ATM_FORE200E_PCA_FW)) \
diff -urN linux-2.5.69-bk2/drivers/atm/he.c linux-2.5.69-bk3/drivers/atm/he.c
--- linux-2.5.69-bk2/drivers/atm/he.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/drivers/atm/he.c	2003-05-08 04:38:16.000000000 -0700
@@ -0,0 +1,3419 @@
+/* $Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $ */
+
+/*
+
+  he.c
+
+  ForeRunnerHE ATM Adapter driver for ATM on Linux
+  Copyright (C) 1999-2001  Naval Research Laboratory
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/*
+
+  he.c
+
+  ForeRunnerHE ATM Adapter driver for ATM on Linux
+  Copyright (C) 1999-2001  Naval Research Laboratory
+
+  Permission to use, copy, modify and distribute this software and its
+  documentation is hereby granted, provided that both the copyright
+  notice and this permission notice appear in all copies of the software,
+  derivative works or modified versions, and any portions thereof, and
+  that both notices appear in supporting documentation.
+
+  NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
+  DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
+  RESULTING FROM THE USE OF THIS SOFTWARE.
+
+  This driver was written using the "Programmer's Reference Manual for
+  ForeRunnerHE(tm)", MANU0361-01 - Rev. A, 08/21/98.
+
+  AUTHORS:
+	chas williams <chas@cmf.nrl.navy.mil>
+	eric kinzie <ekinzie@cmf.nrl.navy.mil>
+
+  NOTES:
+	4096 supported 'connections'
+	group 0 is used for all traffic
+	interrupt queue 0 is used for all interrupts
+	aal0 support for receive only
+
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#include <linux/atmdev.h>
+#include <linux/atm.h>
+#include <linux/sonet.h>
+#ifndef ATM_OC12_PCR
+#define ATM_OC12_PCR (622080000/1080*1040/8/53)
+#endif
+
+#ifdef BUS_INT_WAR
+void sn_add_polled_interrupt(int irq, int interval);
+void sn_delete_polled_interrupt(int irq);
+#endif
+
+#define USE_TASKLET
+#define USE_HE_FIND_VCC
+#undef USE_SCATTERGATHER
+#undef USE_CHECKSUM_HW			/* still confused about this */
+#define USE_RBPS
+#undef USE_RBPS_POOL			/* if memory is tight try this */
+#undef USE_RBPL_POOL			/* if memory is tight try this */
+#define USE_TPD_POOL
+/* #undef CONFIG_ATM_HE_USE_SUNI */
+
+/* 2.2 kernel support */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
+#define dev_kfree_skb_irq(skb)		dev_kfree_skb(skb)
+#define dev_kfree_skb_any(skb)		dev_kfree_skb(skb)
+#undef USE_TASKLET
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)
+#define set_current_state(x)		current->state = (x);
+#endif
+
+#include "he.h"
+
+#include "suni.h"
+
+#include <linux/atm_he.h>
+
+#define hprintk(fmt,args...)	printk(DEV_LABEL "%d: " fmt, he_dev->number, args)
+#define hprintk1(fmt)		printk(DEV_LABEL "%d: " fmt, he_dev->number)
+
+#undef DEBUG
+#ifdef DEBUG
+#define HPRINTK(fmt,args...)	hprintk(fmt,args)
+#define HPRINTK1(fmt)		hprintk1(fmt)
+#else
+#define HPRINTK(fmt,args...)
+#define HPRINTK1(fmt,args...)
+#endif /* DEBUG */
+
+
+/* version definition */
+
+static char *version = "$Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $";
+
+/* defines */
+#define ALIGN_ADDRESS(addr, alignment) \
+	((((unsigned long) (addr)) + (((unsigned long) (alignment)) - 1)) & ~(((unsigned long) (alignment)) - 1))
+
+/* declarations */
+
+static int he_open(struct atm_vcc *vcc, short vpi, int vci);
+static void he_close(struct atm_vcc *vcc);
+static int he_send(struct atm_vcc *vcc, struct sk_buff *skb);
+static int he_sg_send(struct atm_vcc *vcc, unsigned long start, unsigned long size);
+static int he_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,69)
+static irqreturn_t he_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
+#else
+static void he_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
+#endif
+static void he_tasklet(unsigned long data);
+static int he_proc_read(struct atm_dev *dev,loff_t *pos,char *page);
+static int he_start(struct atm_dev *dev);
+static void he_stop(struct he_dev *dev);
+static void he_phy_put(struct atm_dev *, unsigned char, unsigned long);
+static unsigned char he_phy_get(struct atm_dev *, unsigned long);
+
+static u8 read_prom_byte(struct he_dev *he_dev, int addr);
+
+/* globals */
+
+struct he_dev *he_devs = NULL;
+static short disable64 = -1;
+static short nvpibits = -1;
+static short nvcibits = -1;
+static short rx_skb_reserve = 16;
+static short irq_coalesce = 1;
+static short sdh = 1;
+
+static struct atmdev_ops he_ops =
+{
+   open:	he_open,
+   close:	he_close,	
+   ioctl:	he_ioctl,	
+   send:	he_send,
+   sg_send:	he_sg_send,	
+   phy_put:	he_phy_put,
+   phy_get:	he_phy_get,
+   proc_read:	he_proc_read,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,1)
+   owner:	THIS_MODULE
+#endif
+};
+
+/* see the comments in he.h about global_lock */
+
+#define HE_SPIN_LOCK(dev, flags)	spin_lock_irqsave(&(dev)->global_lock, flags)
+#define HE_SPIN_UNLOCK(dev, flags)	spin_unlock_irqrestore(&(dev)->global_lock, flags)
+
+#define he_writel(dev, val, reg)	do { writel(val, (dev)->membase + (reg)); wmb(); } while(0)
+#define he_readl(dev, reg)		readl((dev)->membase + (reg))
+
+/* section 2.12 connection memory access */
+
+static __inline__ void
+he_writel_internal(struct he_dev *he_dev, unsigned val, unsigned addr,
+								unsigned flags)
+{
+	he_writel(he_dev, val, CON_DAT);
+#ifdef CONFIG_IA64_SGI_SN2
+	(void) he_readl(he_dev, CON_DAT);
+#endif
+	he_writel(he_dev, flags | CON_CTL_WRITE | CON_CTL_ADDR(addr), CON_CTL);
+	while(he_readl(he_dev, CON_CTL) & CON_CTL_BUSY);
+}
+
+#define he_writel_rcm(dev, val, reg) 				\
+			he_writel_internal(dev, val, reg, CON_CTL_RCM)
+
+#define he_writel_tcm(dev, val, reg) 				\
+			he_writel_internal(dev, val, reg, CON_CTL_TCM)
+
+#define he_writel_mbox(dev, val, reg) 				\
+			he_writel_internal(dev, val, reg, CON_CTL_MBOX)
+
+static unsigned
+he_readl_internal(struct he_dev *he_dev, unsigned addr, unsigned flags)
+{
+	he_writel(he_dev, flags | CON_CTL_READ | CON_CTL_ADDR(addr), CON_CTL);
+	while(he_readl(he_dev, CON_CTL) & CON_CTL_BUSY);
+	return he_readl(he_dev, CON_DAT);
+}
+
+#define he_readl_rcm(dev, reg) \
+			he_readl_internal(dev, reg, CON_CTL_RCM)
+
+#define he_readl_tcm(dev, reg) \
+			he_readl_internal(dev, reg, CON_CTL_TCM)
+
+#define he_readl_mbox(dev, reg) \
+			he_readl_internal(dev, reg, CON_CTL_MBOX)
+
+
+/* figure 2.2 connection id */
+
+#define he_mkcid(dev, vpi, vci)		(((vpi<<(dev)->vcibits) | vci) & 0x1fff)
+
+/* 2.5.1 per connection transmit state registers */
+
+#define he_writel_tsr0(dev, val, cid) \
+		he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 0)
+#define he_readl_tsr0(dev, cid) \
+		he_readl_tcm(dev, CONFIG_TSRA | (cid<<3) | 0)
+
+#define he_writel_tsr1(dev, val, cid) \
+		he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 1)
+
+#define he_writel_tsr2(dev, val, cid) \
+		he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 2)
+
+#define he_writel_tsr3(dev, val, cid) \
+		he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 3)
+
+#define he_writel_tsr4(dev, val, cid) \
+		he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 4)
+
+	/* from page 2-20
+	 *
+	 * NOTE While the transmit connection is active, bits 23 through 0
+	 *      of this register must not be written by the host.  Byte
+	 *      enables should be used during normal operation when writing
+	 *      the most significant byte.
+	 */
+
+#define he_writel_tsr4_upper(dev, val, cid) \
+		he_writel_internal(dev, val, CONFIG_TSRA | (cid<<3) | 4, \
+							CON_CTL_TCM \
+							| CON_BYTE_DISABLE_2 \
+							| CON_BYTE_DISABLE_1 \
+							| CON_BYTE_DISABLE_0)
+
+#define he_readl_tsr4(dev, cid) \
+		he_readl_tcm(dev, CONFIG_TSRA | (cid<<3) | 4)
+
+#define he_writel_tsr5(dev, val, cid) \
+		he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 5)
+
+#define he_writel_tsr6(dev, val, cid) \
+		he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 6)
+
+#define he_writel_tsr7(dev, val, cid) \
+		he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 7)
+
+
+#define he_writel_tsr8(dev, val, cid) \
+		he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 0)
+
+#define he_writel_tsr9(dev, val, cid) \
+		he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 1)
+
+#define he_writel_tsr10(dev, val, cid) \
+		he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 2)
+
+#define he_writel_tsr11(dev, val, cid) \
+		he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 3)
+
+
+#define he_writel_tsr12(dev, val, cid) \
+		he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<1) | 0)
+
+#define he_writel_tsr13(dev, val, cid) \
+		he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<1) | 1)
+
+
+#define he_writel_tsr14(dev, val, cid) \
+		he_writel_tcm(dev, val, CONFIG_TSRD | cid)
+
+#define he_writel_tsr14_upper(dev, val, cid) \
+		he_writel_internal(dev, val, CONFIG_TSRD | cid, \
+							CON_CTL_TCM \
+							| CON_BYTE_DISABLE_2 \
+							| CON_BYTE_DISABLE_1 \
+							| CON_BYTE_DISABLE_0)
+
+/* 2.7.1 per connection receive state registers */
+
+#define he_writel_rsr0(dev, val, cid) \
+		he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 0)
+#define he_readl_rsr0(dev, cid) \
+		he_readl_rcm(dev, 0x00000 | (cid<<3) | 0)
+
+#define he_writel_rsr1(dev, val, cid) \
+		he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 1)
+
+#define he_writel_rsr2(dev, val, cid) \
+		he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 2)
+
+#define he_writel_rsr3(dev, val, cid) \
+		he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 3)
+
+#define he_writel_rsr4(dev, val, cid) \
+		he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 4)
+
+#define he_writel_rsr5(dev, val, cid) \
+		he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 5)
+
+#define he_writel_rsr6(dev, val, cid) \
+		he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 6)
+
+#define he_writel_rsr7(dev, val, cid) \
+		he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 7)
+
+static __inline__ struct atm_vcc*
+he_find_vcc(struct he_dev *he_dev, unsigned cid)
+{
+	struct atm_vcc *vcc;
+	short vpi;
+	int vci;
+
+	vpi = cid >> he_dev->vcibits;
+	vci = cid & ((1<<he_dev->vcibits)-1);
+
+	for (vcc = he_dev->atm_dev->vccs; vcc; vcc = vcc->next)
+		if (vcc->vci == vci && vcc->vpi == vpi
+			&& vcc->qos.rxtp.traffic_class != ATM_NONE) return vcc;
+
+	return NULL;
+}
+
+static int __devinit
+he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
+{
+	struct atm_dev *atm_dev;
+	struct he_dev *he_dev;
+
+	printk(KERN_INFO "he: %s\n", version);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,43)
+	if (pci_enable_device(pci_dev)) return -EIO;
+#endif
+	if (pci_set_dma_mask(pci_dev, HE_DMA_MASK) != 0)
+	{
+		printk(KERN_WARNING "he: no suitable dma available\n");
+		return -EIO;
+	}
+
+	atm_dev = atm_dev_register(DEV_LABEL, &he_ops, -1, 0);
+	if (!atm_dev) return -ENODEV;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3)
+	pci_set_drvdata(pci_dev, atm_dev);
+#else
+	pci_dev->driver_data = atm_dev;
+#endif
+
+	he_dev = (struct he_dev *) kmalloc(sizeof(struct he_dev),
+							GFP_KERNEL);
+	if (!he_dev) return -ENOMEM;
+	memset(he_dev, 0, sizeof(struct he_dev));
+
+	he_dev->pci_dev = pci_dev;
+	he_dev->atm_dev = atm_dev;
+	he_dev->atm_dev->dev_data = he_dev;
+	HE_DEV(atm_dev) = he_dev;
+	he_dev->number = atm_dev->number;	/* was devs */
+	if (he_start(atm_dev)) {
+		atm_dev_deregister(atm_dev);
+		he_stop(he_dev);
+		kfree(he_dev);
+		return -ENODEV;
+	}
+	he_dev->next = NULL;
+	if (he_devs) he_dev->next = he_devs;
+	he_devs = he_dev;
+
+	return 0;
+}
+
+static void __devexit
+he_remove_one (struct pci_dev *pci_dev)
+{
+	struct atm_dev *atm_dev;
+	struct he_dev *he_dev;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3)
+	atm_dev = pci_get_drvdata(pci_dev);
+#else
+	atm_dev = pci_dev->driver_data;
+#endif
+	he_dev = HE_DEV(atm_dev);
+
+	/* need to remove from he_devs */
+
+	he_stop(he_dev);
+	atm_dev_deregister(atm_dev);
+	kfree(he_dev);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3)
+	pci_set_drvdata(pci_dev, NULL);
+#else
+	pci_dev->driver_data = NULL;
+#endif
+}
+
+
+static unsigned
+rate_to_atmf(unsigned rate)		/* cps to atm forum format */
+{
+#define NONZERO (1<<14)
+
+        unsigned exp = 0;
+
+        if (rate == 0) return(0);
+
+        rate <<= 9;
+        while (rate > 0x3ff)
+        {
+                ++exp;
+                rate >>= 1;
+        }
+
+        return (NONZERO | (exp << 9) | (rate & 0x1ff));
+}
+
+static void __init
+he_init_rx_lbfp0(struct he_dev *he_dev)
+{
+        unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
+        unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
+        unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD;
+        unsigned row_offset = he_dev->r0_startrow * he_dev->bytes_per_row;
+        
+	lbufd_index = 0;
+        lbm_offset = he_readl(he_dev, RCMLBM_BA);
+
+	he_writel(he_dev, lbufd_index, RLBF0_H);
+
+        for (i = 0, lbuf_count = 0; i < he_dev->r0_numbuffs; ++i)
+        {
+		lbufd_index += 2;
+                lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
+
+		he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
+		he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
+
+                if (++lbuf_count == lbufs_per_row)
+                {
+                        lbuf_count = 0;
+                        row_offset += he_dev->bytes_per_row;
+                }
+		lbm_offset += 4;
+        }
+                
+        he_writel(he_dev, lbufd_index - 2, RLBF0_T);
+	he_writel(he_dev, he_dev->r0_numbuffs, RLBF0_C);
+}
+
+static void __init
+he_init_rx_lbfp1(struct he_dev *he_dev)
+{
+        unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
+        unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
+        unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD;
+        unsigned row_offset = he_dev->r1_startrow * he_dev->bytes_per_row;
+        
+	lbufd_index = 1;
+        lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index);
+
+	he_writel(he_dev, lbufd_index, RLBF1_H);
+
+        for (i = 0, lbuf_count = 0; i < he_dev->r1_numbuffs; ++i)
+        {
+		lbufd_index += 2;
+                lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
+
+		he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
+		he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
+
+                if (++lbuf_count == lbufs_per_row)
+                {
+                        lbuf_count = 0;
+                        row_offset += he_dev->bytes_per_row;
+                }
+		lbm_offset += 4;
+        }
+                
+        he_writel(he_dev, lbufd_index - 2, RLBF1_T);
+	he_writel(he_dev, he_dev->r1_numbuffs, RLBF1_C);
+}
+
+static void __init
+he_init_tx_lbfp(struct he_dev *he_dev)
+{
+        unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
+        unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
+        unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD;
+        unsigned row_offset = he_dev->tx_startrow * he_dev->bytes_per_row;
+        
+	lbufd_index = he_dev->r0_numbuffs + he_dev->r1_numbuffs;
+        lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index);
+
+	he_writel(he_dev, lbufd_index, TLBF_H);
+
+        for (i = 0, lbuf_count = 0; i < he_dev->tx_numbuffs; ++i)
+        {
+		lbufd_index += 1;
+                lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
+
+		he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
+		he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
+
+                if (++lbuf_count == lbufs_per_row)
+                {
+                        lbuf_count = 0;
+                        row_offset += he_dev->bytes_per_row;
+                }
+		lbm_offset += 2;
+        }
+                
+        he_writel(he_dev, lbufd_index - 1, TLBF_T);
+}
+
+static int __init
+he_init_tpdrq(struct he_dev *he_dev)
+{
+	he_dev->tpdrq_base = pci_alloc_consistent(he_dev->pci_dev,
+		CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq), &he_dev->tpdrq_phys);
+	if (he_dev->tpdrq_base == NULL) 
+	{
+		hprintk1("failed to alloc tpdrq\n");
+		return -ENOMEM;
+	}
+	memset(he_dev->tpdrq_base, 0,
+				CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq));
+
+	he_dev->tpdrq_tail = he_dev->tpdrq_base;
+	he_dev->tpdrq_head = he_dev->tpdrq_base;
+
+	he_writel(he_dev, he_dev->tpdrq_phys, TPDRQ_B_H);
+	he_writel(he_dev, 0, TPDRQ_T);	
+	he_writel(he_dev, CONFIG_TPDRQ_SIZE - 1, TPDRQ_S);
+
+	return 0;
+}
+
+static void __init
+he_init_cs_block(struct he_dev *he_dev)
+{
+	unsigned clock, rate, delta;
+	int reg;
+
+	/* 5.1.7 cs block initialization */
+
+	for(reg = 0; reg < 0x20; ++reg)
+		he_writel_mbox(he_dev, 0x0, CS_STTIM0 + reg);
+
+	/* rate grid timer reload values */
+
+	clock = he_is622(he_dev) ? 66667000 : 50000000;
+	rate = he_dev->atm_dev->link_rate;
+	delta = rate / 16 / 2;
+
+	for(reg = 0; reg < 0x10; ++reg)
+	{
+		/* 2.4 internal transmit function
+		 *
+	 	 * we initialize the first row in the rate grid.
+		 * values are period (in clock cycles) of timer
+		 */
+		unsigned period = clock / rate;
+
+		he_writel_mbox(he_dev, period, CS_TGRLD0 + reg);
+		rate -= delta;
+	}
+
+	if (he_is622(he_dev))
+	{
+		/* table 5.2 (4 cells per lbuf) */
+		he_writel_mbox(he_dev, 0x000800fa, CS_ERTHR0);
+		he_writel_mbox(he_dev, 0x000c33cb, CS_ERTHR1);
+		he_writel_mbox(he_dev, 0x0010101b, CS_ERTHR2);
+		he_writel_mbox(he_dev, 0x00181dac, CS_ERTHR3);
+		he_writel_mbox(he_dev, 0x00280600, CS_ERTHR4);
+
+		/* table 5.3, 5.4, 5.5, 5.6, 5.7 */
+		he_writel_mbox(he_dev, 0x023de8b3, CS_ERCTL0);
+		he_writel_mbox(he_dev, 0x1801, CS_ERCTL1);
+		he_writel_mbox(he_dev, 0x68b3, CS_ERCTL2);
+		he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0);
+		he_writel_mbox(he_dev, 0x68b3, CS_ERSTAT1);
+		he_writel_mbox(he_dev, 0x14585, CS_RTFWR);
+
+		he_writel_mbox(he_dev, 0x4680, CS_RTATR);
+
+		/* table 5.8 */
+		he_writel_mbox(he_dev, 0x00159ece, CS_TFBSET);
+		he_writel_mbox(he_dev, 0x68b3, CS_WCRMAX);
+		he_writel_mbox(he_dev, 0x5eb3, CS_WCRMIN);
+		he_writel_mbox(he_dev, 0xe8b3, CS_WCRINC);
+		he_writel_mbox(he_dev, 0xdeb3, CS_WCRDEC);
+		he_writel_mbox(he_dev, 0x68b3, CS_WCRCEIL);
+
+		/* table 5.9 */
+		he_writel_mbox(he_dev, 0x5, CS_OTPPER);
+		he_writel_mbox(he_dev, 0x14, CS_OTWPER);
+	}
+	else
+	{
+		/* table 5.1 (4 cells per lbuf) */
+		he_writel_mbox(he_dev, 0x000400ea, CS_ERTHR0);
+		he_writel_mbox(he_dev, 0x00063388, CS_ERTHR1);
+		he_writel_mbox(he_dev, 0x00081018, CS_ERTHR2);
+		he_writel_mbox(he_dev, 0x000c1dac, CS_ERTHR3);
+		he_writel_mbox(he_dev, 0x0014051a, CS_ERTHR4);
+
+		/* table 5.3, 5.4, 5.5, 5.6, 5.7 */
+		he_writel_mbox(he_dev, 0x0235e4b1, CS_ERCTL0);
+		he_writel_mbox(he_dev, 0x4701, CS_ERCTL1);
+		he_writel_mbox(he_dev, 0x64b1, CS_ERCTL2);
+		he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0);
+		he_writel_mbox(he_dev, 0x64b1, CS_ERSTAT1);
+		he_writel_mbox(he_dev, 0xf424, CS_RTFWR);
+
+		he_writel_mbox(he_dev, 0x4680, CS_RTATR);
+
+		/* table 5.8 */
+		he_writel_mbox(he_dev, 0x000563b7, CS_TFBSET);
+		he_writel_mbox(he_dev, 0x64b1, CS_WCRMAX);
+		he_writel_mbox(he_dev, 0x5ab1, CS_WCRMIN);
+		he_writel_mbox(he_dev, 0xe4b1, CS_WCRINC);
+		he_writel_mbox(he_dev, 0xdab1, CS_WCRDEC);
+		he_writel_mbox(he_dev, 0x64b1, CS_WCRCEIL);
+
+		/* table 5.9 */
+		he_writel_mbox(he_dev, 0x6, CS_OTPPER);
+		he_writel_mbox(he_dev, 0x1e, CS_OTWPER);
+
+	}
+
+	he_writel_mbox(he_dev, 0x8, CS_OTTLIM);
+
+	for(reg = 0; reg < 0x8; ++reg)
+		he_writel_mbox(he_dev, 0x0, CS_HGRRT0 + reg);
+
+}
+
+static void __init
+he_init_cs_block_rcm(struct he_dev *he_dev)
+{
+	unsigned rategrid[16][16];
+	unsigned rate, delta;
+	int i, j, reg;
+
+	unsigned rate_atmf, exp, man;
+	unsigned long long rate_cps;
+        int mult, buf, buf_limit = 4;
+
+	/* initialize rate grid group table */
+
+	for (reg = 0x0; reg < 0xff; ++reg)
+		he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg);
+
+	/* initialize rate controller groups */
+
+	for (reg = 0x100; reg < 0x1ff; ++reg)
+		he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg);
+	
+	/* initialize tNrm lookup table */
+
+	/* the manual makes reference to a routine in a sample driver
+	   for proper configuration; fortunately, we only need this
+	   in order to support abr connection */
+	
+	/* initialize rate to group table */
+
+	rate = he_dev->atm_dev->link_rate;
+	delta = rate / 32;
+
+	/*
+	 * 2.4 transmit internal functions
+	 * 
+	 * we construct a copy of the rate grid used by the scheduler
+	 * in order to construct the rate to group table below
+	 */
+
+	for (j = 0; j < 16; j++)
+	{
+		rategrid[0][j] = rate;
+		rate -= delta;
+	}
+
+	for (i = 1; i < 16; i++)
+		for (j = 0; j < 16; j++)
+			if (i > 14)
+				rategrid[i][j] = rategrid[i - 1][j] / 4;
+			else
+				rategrid[i][j] = rategrid[i - 1][j] / 2;
+
+	/*
+	 * 2.4 transmit internal function
+	 *
+	 * this table maps the upper 5 bits of exponent and mantissa
+	 * of the atm forum representation of the rate into an index
+	 * on rate grid  
+	 */
+
+	rate_atmf = 0;
+	while (rate_atmf < 0x400)
+	{
+		man = (rate_atmf & 0x1f) << 4;
+		exp = rate_atmf >> 5;
+
+		/* 
+			instead of '/ 512', use '>> 9' to prevent a call
+			to divdu3 on x86 platforms
+		*/
+		rate_cps = (unsigned long long) (1 << exp) * (man + 512) >> 9;
+
+		if (rate_cps < 10) rate_cps = 10;
+				/* 2.2.1 minimum payload rate is 10 cps */
+
+		for (i = 255; i > 0; i--)
+			if (rategrid[i/16][i%16] >= rate_cps) break;
+				/* pick nearest rate instead? */
+
+		/*
+		 * each table entry is 16 bits: (rate grid index (8 bits)
+		 * and a buffer limit (8 bits)
+		 * there are two table entries in each 32-bit register
+		 */
+
+#ifdef notdef
+                buf = rate_cps * he_dev->tx_numbuffs /
+				(he_dev->atm_dev->link_rate * 2);
+#else
+		/* this is pretty, but avoids _divdu3 and is mostly correct */
+                buf = 0;
+                mult = he_dev->atm_dev->link_rate / ATM_OC3_PCR;
+                if (rate_cps > (68 * mult)) buf = 1;
+                if (rate_cps > (136 * mult)) buf = 2;
+                if (rate_cps > (204 * mult)) buf = 3;
+                if (rate_cps > (272 * mult)) buf = 4;
+#endif
+                if (buf > buf_limit) buf = buf_limit;
+		reg = (reg<<16) | ((i<<8) | buf);
+
+#define RTGTBL_OFFSET 0x400
+	  
+		if (rate_atmf & 0x1)
+			he_writel_rcm(he_dev, reg,
+				CONFIG_RCMABR + RTGTBL_OFFSET + (rate_atmf>>1));
+
+		++rate_atmf;
+	}
+}
+
+static int __init
+he_init_group(struct he_dev *he_dev, int group)
+{
+	int i;
+
+#ifdef USE_RBPS
+	/* small buffer pool */
+#ifdef USE_RBPS_POOL
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
+	he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
+			CONFIG_RBPS_BUFSIZE, 8, 0, SLAB_KERNEL);
+#else
+	he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
+			CONFIG_RBPS_BUFSIZE, 8, 0);
+#endif
+	if (he_dev->rbps_pool == NULL)
+	{
+		hprintk1("unable to create rbps pages\n");
+		return -ENOMEM;
+	}
+#else /* !USE_RBPS_POOL */
+	he_dev->rbps_pages = pci_alloc_consistent(he_dev->pci_dev,
+		CONFIG_RBPS_SIZE * CONFIG_RBPS_BUFSIZE, &he_dev->rbps_pages_phys);
+	if (he_dev->rbps_pages == NULL) {
+		hprintk1("unable to create rbps page pool\n");
+		return -ENOMEM;
+	}
+#endif /* USE_RBPS_POOL */
+
+	he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev,
+		CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys);
+	if (he_dev->rbps_base == NULL)
+	{
+		hprintk1("failed to alloc rbps\n");
+		return -ENOMEM;
+	}
+	memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp));
+	he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL);
+
+	for (i = 0; i < CONFIG_RBPS_SIZE; ++i)
+	{
+		dma_addr_t dma_handle;
+		void *cpuaddr;
+
+#ifdef USE_RBPS_POOL 
+		cpuaddr = pci_pool_alloc(he_dev->rbps_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle);
+		if (cpuaddr == NULL)
+			return -ENOMEM;
+#else
+		cpuaddr = he_dev->rbps_pages + (i * CONFIG_RBPS_BUFSIZE);
+		dma_handle = he_dev->rbps_pages_phys + (i * CONFIG_RBPS_BUFSIZE);
+#endif
+
+		he_dev->rbps_virt[i].virt = cpuaddr;
+		he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF);
+		he_dev->rbps_base[i].phys = dma_handle;
+
+	}
+	he_dev->rbps_tail = &he_dev->rbps_base[CONFIG_RBPS_SIZE-1];
+
+	he_writel(he_dev, he_dev->rbps_phys, G0_RBPS_S + (group * 32));
+	he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail),
+						G0_RBPS_T + (group * 32));
+	he_writel(he_dev, CONFIG_RBPS_BUFSIZE/4,
+						G0_RBPS_BS + (group * 32));
+	he_writel(he_dev,
+			RBP_THRESH(CONFIG_RBPS_THRESH) |
+			RBP_QSIZE(CONFIG_RBPS_SIZE-1) |
+			RBP_INT_ENB,
+						G0_RBPS_QI + (group * 32));
+#else /* !USE_RBPS */
+	he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32));
+	he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32));
+	he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32));
+	he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
+						G0_RBPS_BS + (group * 32));
+#endif /* USE_RBPS */
+
+	/* large buffer pool */
+#ifdef USE_RBPL_POOL
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
+	he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev,
+			CONFIG_RBPL_BUFSIZE, 8, 0, SLAB_KERNEL);
+#else
+	he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev,
+			CONFIG_RBPL_BUFSIZE, 8, 0);
+#endif
+	if (he_dev->rbpl_pool == NULL)
+	{
+		hprintk1("unable to create rbpl pool\n");
+		return -ENOMEM;
+	}
+#else /* !USE_RBPL_POOL */
+	he_dev->rbpl_pages = (void *) pci_alloc_consistent(he_dev->pci_dev,
+		CONFIG_RBPL_SIZE * CONFIG_RBPL_BUFSIZE, &he_dev->rbpl_pages_phys);
+	if (he_dev->rbpl_pages == NULL)
+	{
+		hprintk1("unable to create rbpl pages\n");
+		return -ENOMEM;
+	}
+#endif /* USE_RBPL_POOL */
+
+	he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
+		CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
+	if (he_dev->rbpl_base == NULL)
+	{
+		hprintk1("failed to alloc rbpl\n");
+		return -ENOMEM;
+	}
+	memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
+	he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL);
+
+	for (i = 0; i < CONFIG_RBPL_SIZE; ++i)
+	{
+		dma_addr_t dma_handle;
+		void *cpuaddr;
+
+#ifdef USE_RBPL_POOL
+		cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle);
+		if (cpuaddr == NULL)
+			return -ENOMEM;
+#else
+		cpuaddr = he_dev->rbpl_pages + (i * CONFIG_RBPL_BUFSIZE);
+		dma_handle = he_dev->rbpl_pages_phys + (i * CONFIG_RBPL_BUFSIZE);
+#endif
+
+		he_dev->rbpl_virt[i].virt = cpuaddr;
+		he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF);
+		he_dev->rbpl_base[i].phys = dma_handle;
+
+	}
+	he_dev->rbpl_tail = &he_dev->rbpl_base[CONFIG_RBPL_SIZE-1];
+
+	he_writel(he_dev, he_dev->rbpl_phys, G0_RBPL_S + (group * 32));
+	he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail),
+						G0_RBPL_T + (group * 32));
+	he_writel(he_dev, CONFIG_RBPL_BUFSIZE/4,
+						G0_RBPL_BS + (group * 32));
+	he_writel(he_dev,
+			RBP_THRESH(CONFIG_RBPL_THRESH) |
+			RBP_QSIZE(CONFIG_RBPL_SIZE-1) |
+			RBP_INT_ENB,
+						G0_RBPL_QI + (group * 32));
+
+	/* rx buffer ready queue */
+
+	he_dev->rbrq_base = pci_alloc_consistent(he_dev->pci_dev,
+		CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
+	if (he_dev->rbrq_base == NULL)
+	{
+		hprintk1("failed to allocate rbrq\n");
+		return -ENOMEM;
+	}
+	memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
+
+	he_dev->rbrq_head = he_dev->rbrq_base;
+	he_writel(he_dev, he_dev->rbrq_phys, G0_RBRQ_ST + (group * 16));
+	he_writel(he_dev, 0, G0_RBRQ_H + (group * 16));
+	he_writel(he_dev,
+		RBRQ_THRESH(CONFIG_RBRQ_THRESH) | RBRQ_SIZE(CONFIG_RBRQ_SIZE-1),
+						G0_RBRQ_Q + (group * 16));
+	if (irq_coalesce)
+	{
+		hprintk1("coalescing interrupts\n");
+		he_writel(he_dev, RBRQ_TIME(768) | RBRQ_COUNT(7),
+						G0_RBRQ_I + (group * 16));
+	}
+	else
+		he_writel(he_dev, RBRQ_TIME(0) | RBRQ_COUNT(1),
+						G0_RBRQ_I + (group * 16));
+
+	/* tx buffer ready queue */
+
+	he_dev->tbrq_base = pci_alloc_consistent(he_dev->pci_dev,
+		CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
+	if (he_dev->tbrq_base == NULL)
+	{
+		hprintk1("failed to allocate tbrq\n");
+		return -ENOMEM;
+	}
+	memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
+
+	he_dev->tbrq_head = he_dev->tbrq_base;
+
+	he_writel(he_dev, he_dev->tbrq_phys, G0_TBRQ_B_T + (group * 16));
+	he_writel(he_dev, 0, G0_TBRQ_H + (group * 16));
+	he_writel(he_dev, CONFIG_TBRQ_SIZE - 1, G0_TBRQ_S + (group * 16));
+	he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16));
+
+	return 0;
+}
+
+static int __init
+he_init_irq(struct he_dev *he_dev)
+{
+	int i;
+
+	/* 2.9.3.5  tail offset for each interrupt queue is located after the
+		    end of the interrupt queue */
+
+        he_dev->irq_base = pci_alloc_consistent(he_dev->pci_dev,
+			(CONFIG_IRQ_SIZE+1) * sizeof(struct he_irq), &he_dev->irq_phys);
+	if (he_dev->irq_base == NULL)
+	{
+		hprintk1("failed to allocate irq\n");
+		return -ENOMEM;
+	}
+	he_dev->irq_tailoffset = (unsigned *)
+					&he_dev->irq_base[CONFIG_IRQ_SIZE];
+	*he_dev->irq_tailoffset = 0;
+	he_dev->irq_head = he_dev->irq_base;
+	he_dev->irq_tail = he_dev->irq_base;
+
+	for(i=0; i < CONFIG_IRQ_SIZE; ++i)
+		he_dev->irq_base[i].isw = ITYPE_INVALID;
+
+	he_writel(he_dev, he_dev->irq_phys, IRQ0_BASE);
+	he_writel(he_dev,
+		IRQ_SIZE(CONFIG_IRQ_SIZE) | IRQ_THRESH(CONFIG_IRQ_THRESH),
+								IRQ0_HEAD);
+	he_writel(he_dev, IRQ_INT_A | IRQ_TYPE_LINE, IRQ0_CNTL);
+	he_writel(he_dev, 0x0, IRQ0_DATA);
+
+	he_writel(he_dev, 0x0, IRQ1_BASE);
+	he_writel(he_dev, 0x0, IRQ1_HEAD);
+	he_writel(he_dev, 0x0, IRQ1_CNTL);
+	he_writel(he_dev, 0x0, IRQ1_DATA);
+
+	he_writel(he_dev, 0x0, IRQ2_BASE);
+	he_writel(he_dev, 0x0, IRQ2_HEAD);
+	he_writel(he_dev, 0x0, IRQ2_CNTL);
+	he_writel(he_dev, 0x0, IRQ2_DATA);
+
+	he_writel(he_dev, 0x0, IRQ3_BASE);
+	he_writel(he_dev, 0x0, IRQ3_HEAD);
+	he_writel(he_dev, 0x0, IRQ3_CNTL);
+	he_writel(he_dev, 0x0, IRQ3_DATA);
+
+	/* 2.9.3.2 interrupt queue mapping registers */
+
+	he_writel(he_dev, 0x0, GRP_10_MAP);
+	he_writel(he_dev, 0x0, GRP_32_MAP);
+	he_writel(he_dev, 0x0, GRP_54_MAP);
+	he_writel(he_dev, 0x0, GRP_76_MAP);
+
+	if (request_irq(he_dev->pci_dev->irq, he_irq_handler, SA_INTERRUPT|SA_SHIRQ, DEV_LABEL, he_dev))
+	{
+		hprintk("irq %d already in use\n", he_dev->pci_dev->irq);
+		return -EINVAL;
+        }   
+
+	he_dev->irq = he_dev->pci_dev->irq;
+
+#ifdef BUS_INT_WAR
+        HPRINTK("sn_add_polled_interrupt(irq %d, 1)\n", he_dev->irq);
+        sn_add_polled_interrupt(he_dev->irq, 1);
+#endif
+
+	return 0;
+}
+
+static int __init
+he_start(struct atm_dev *dev)
+{
+        struct he_dev *he_dev;
+        struct pci_dev *pci_dev;
+
+	u16 command;
+	u32 gen_cntl_0, host_cntl, lb_swap;
+	u8 cache_size, timer;
+	
+	unsigned err;
+	unsigned int status, reg;
+	int i, group;
+
+        he_dev = HE_DEV(dev);
+        pci_dev = he_dev->pci_dev;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,3)
+	he_dev->membase = pci_dev->resource[0].start;
+#else
+	he_dev->membase = pci_dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
+#endif
+	HPRINTK("membase = 0x%lx  irq = %d.\n", he_dev->membase, pci_dev->irq);
+
+	/*
+	 * pci bus controller initialization 
+	 */
+
+	/* 4.3 pci bus controller-specific initialization */
+	if (pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0) != 0)
+	{
+		hprintk1("can't read GEN_CNTL_0\n");
+		return -EINVAL;
+	}
+	gen_cntl_0 |= (MRL_ENB | MRM_ENB | IGNORE_TIMEOUT);
+	if (pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0) != 0)
+	{
+		hprintk1("can't write GEN_CNTL_0.\n");
+		return -EINVAL;
+	}
+
+	if (pci_read_config_word(pci_dev, PCI_COMMAND, &command) != 0)
+	{
+		hprintk1("can't read PCI_COMMAND.\n");
+		return -EINVAL;
+	}
+
+	command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
+	if (pci_write_config_word(pci_dev, PCI_COMMAND, command) != 0)
+	{
+		hprintk1("can't enable memory.\n");
+		return -EINVAL;
+	}
+
+	if (pci_read_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, &cache_size))
+	{
+		hprintk1("can't read cache line size?\n");
+		return -EINVAL;
+	}
+
+	if (cache_size < 16)
+	{
+		cache_size = 16;
+		if (pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, cache_size))
+			hprintk("can't set cache line size to %d\n", cache_size);
+	}
+
+	if (pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &timer))
+	{
+		hprintk1("can't read latency timer?\n");
+		return -EINVAL;
+	}
+
+	/* from table 3.9
+	 *
+	 * LAT_TIMER = 1 + AVG_LAT + BURST_SIZE/BUS_SIZE
+	 * 
+	 * AVG_LAT: The average first data read/write latency [maximum 16 clock cycles]
+	 * BURST_SIZE: 1536 bytes (read) for 622, 768 bytes (read) for 155 [192 clock cycles]
+	 *
+	 */ 
+#define LAT_TIMER 209
+	if (timer < LAT_TIMER)
+	{
+		HPRINTK("latency timer was %d, setting to %d\n", timer, LAT_TIMER);
+		timer = LAT_TIMER;
+		if (pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, timer))
+			hprintk("can't set latency timer to %d\n", timer);
+	}
+
+	if (!(he_dev->membase = (unsigned long) ioremap(he_dev->membase, HE_REGMAP_SIZE))) {
+		hprintk1("can't set up page mapping\n");
+		return -EINVAL;
+	}
+	      
+	/* 4.4 card reset */
+	he_writel(he_dev, 0x0, RESET_CNTL);
+	he_writel(he_dev, 0xff, RESET_CNTL);
+
+	udelay(16*1000);	/* 16 ms */
+	status = he_readl(he_dev, RESET_CNTL);
+	if ((status & BOARD_RST_STATUS) == 0)
+	{
+		hprintk1("reset failed\n");
+		return -EINVAL;
+	}
+
+	/* 4.5 set bus width */
+	host_cntl = he_readl(he_dev, HOST_CNTL);
+	if (host_cntl & PCI_BUS_SIZE64)
+		gen_cntl_0 |= ENBL_64;
+	else
+		gen_cntl_0 &= ~ENBL_64;
+
+	if (disable64 == 1)
+	{
+		hprintk1("disabling 64-bit pci bus transfers\n");
+		gen_cntl_0 &= ~ENBL_64;
+	}
+
+	if (gen_cntl_0 & ENBL_64) hprintk1("64-bit transfers enabled\n");
+
+	pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
+
+	/* 4.7 read prom contents */
+	for(i=0; i<PROD_ID_LEN; ++i)
+		he_dev->prod_id[i] = read_prom_byte(he_dev, PROD_ID + i);
+
+	he_dev->media = read_prom_byte(he_dev, MEDIA);
+
+	for(i=0; i<6; ++i)
+		dev->esi[i] = read_prom_byte(he_dev, MAC_ADDR + i);
+
+	hprintk("%s%s, %x:%x:%x:%x:%x:%x\n",
+				he_dev->prod_id,
+					he_dev->media & 0x40 ? "SM" : "MM",
+						dev->esi[0],
+						dev->esi[1],
+						dev->esi[2],
+						dev->esi[3],
+						dev->esi[4],
+						dev->esi[5]);
+	he_dev->atm_dev->link_rate = he_is622(he_dev) ?
+						ATM_OC12_PCR : ATM_OC3_PCR;
+
+	/* 4.6 set host endianess */
+	lb_swap = he_readl(he_dev, LB_SWAP);
+	if (he_is622(he_dev))
+		lb_swap &= ~XFER_SIZE;		/* 4 cells */
+	else
+		lb_swap |= XFER_SIZE;		/* 8 cells */
+#ifdef __BIG_ENDIAN
+	lb_swap |= DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST;
+#else
+	lb_swap &= ~(DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST |
+			DATA_WR_SWAP | DATA_RD_SWAP | DESC_RD_SWAP);
+#endif /* __BIG_ENDIAN */
+	he_writel(he_dev, lb_swap, LB_SWAP);
+
+	/* 4.8 sdram controller initialization */
+	he_writel(he_dev, he_is622(he_dev) ? LB_64_ENB : 0x0, SDRAM_CTL);
+
+	/* 4.9 initialize rnum value */
+	lb_swap |= SWAP_RNUM_MAX(0xf);
+	he_writel(he_dev, lb_swap, LB_SWAP);
+
+	/* 4.10 initialize the interrupt queues */
+	if ((err = he_init_irq(he_dev)) != 0) return err;
+
+#ifdef USE_TASKLET
+	tasklet_init(&he_dev->tasklet, he_tasklet, (unsigned long) he_dev);
+#endif
+	spin_lock_init(&he_dev->global_lock);
+
+	/* 4.11 enable pci bus controller state machines */
+	host_cntl |= (OUTFF_ENB | CMDFF_ENB |
+				QUICK_RD_RETRY | QUICK_WR_RETRY | PERR_INT_ENB);
+	he_writel(he_dev, host_cntl, HOST_CNTL);
+
+	gen_cntl_0 |= INT_PROC_ENBL|INIT_ENB;
+	pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
+
+	/*
+	 * atm network controller initialization
+	 */
+
+	/* 5.1.1 generic configuration state */
+
+	/*
+	 *		local (cell) buffer memory map
+	 *                    
+	 *             HE155                          HE622
+	 *                                                      
+	 *        0 ____________1023 bytes  0 _______________________2047 bytes
+	 *         |            |            |                   |   |
+	 *         |  utility   |            |        rx0        |   |
+	 *        5|____________|         255|___________________| u |
+	 *        6|            |         256|                   | t |
+	 *         |            |            |                   | i |
+	 *         |    rx0     |     row    |        tx         | l |
+	 *         |            |            |                   | i |
+	 *         |            |         767|___________________| t |
+	 *      517|____________|         768|                   | y |
+	 * row  518|            |            |        rx1        |   |
+	 *         |            |        1023|___________________|___|
+	 *         |            |
+	 *         |    tx      |
+	 *         |            |
+	 *         |            |
+	 *     1535|____________|
+	 *     1536|            |
+	 *         |    rx1     |
+	 *     2047|____________|
+	 *
+	 */
+
+	/* total 4096 connections */
+	he_dev->vcibits = CONFIG_DEFAULT_VCIBITS;
+	he_dev->vpibits = CONFIG_DEFAULT_VPIBITS;
+
+	if (nvpibits != -1 && nvcibits != -1 && nvpibits+nvcibits != HE_MAXCIDBITS)
+	{
+		hprintk("nvpibits + nvcibits != %d\n", HE_MAXCIDBITS);
+		return -ENODEV;
+	}
+
+	if (nvpibits != -1)
+	{
+		he_dev->vpibits = nvpibits;
+		he_dev->vcibits = HE_MAXCIDBITS - nvpibits;
+	}
+
+	if (nvcibits != -1)
+	{
+		he_dev->vcibits = nvcibits;
+		he_dev->vpibits = HE_MAXCIDBITS - nvcibits;
+	}
+
+
+	if (he_is622(he_dev))
+	{
+		he_dev->cells_per_row = 40;
+		he_dev->bytes_per_row = 2048;
+		he_dev->r0_numrows = 256;
+		he_dev->tx_numrows = 512;
+		he_dev->r1_numrows = 256;
+		he_dev->r0_startrow = 0;
+		he_dev->tx_startrow = 256;
+		he_dev->r1_startrow = 768;
+	}
+	else
+	{
+		he_dev->cells_per_row = 20;
+		he_dev->bytes_per_row = 1024;
+		he_dev->r0_numrows = 512;
+		he_dev->tx_numrows = 1018;
+		he_dev->r1_numrows = 512;
+		he_dev->r0_startrow = 6;
+		he_dev->tx_startrow = 518;
+		he_dev->r1_startrow = 1536;
+	}
+
+	he_dev->cells_per_lbuf = 4;
+	he_dev->buffer_limit = 4;
+	he_dev->r0_numbuffs = he_dev->r0_numrows *
+				he_dev->cells_per_row / he_dev->cells_per_lbuf;
+	if (he_dev->r0_numbuffs > 2560) he_dev->r0_numbuffs = 2560;
+
+	he_dev->r1_numbuffs = he_dev->r1_numrows *
+				he_dev->cells_per_row / he_dev->cells_per_lbuf;
+	if (he_dev->r1_numbuffs > 2560) he_dev->r1_numbuffs = 2560;
+
+	he_dev->tx_numbuffs = he_dev->tx_numrows *
+				he_dev->cells_per_row / he_dev->cells_per_lbuf;
+	if (he_dev->tx_numbuffs > 5120) he_dev->tx_numbuffs = 5120;
+
+	/* 5.1.2 configure hardware dependent registers */
+
+	he_writel(he_dev, 
+		SLICE_X(0x2) | ARB_RNUM_MAX(0xf) | TH_PRTY(0x3) |
+		RH_PRTY(0x3) | TL_PRTY(0x2) | RL_PRTY(0x1) |
+		(he_is622(he_dev) ? BUS_MULTI(0x28) : BUS_MULTI(0x46)) |
+		(he_is622(he_dev) ? NET_PREF(0x50) : NET_PREF(0x8c)),
+								LBARB);
+
+	he_writel(he_dev, BANK_ON |
+		(he_is622(he_dev) ? (REF_RATE(0x384) | WIDE_DATA) : REF_RATE(0x150)),
+								SDRAMCON);
+
+	he_writel(he_dev,
+		(he_is622(he_dev) ? RM_BANK_WAIT(1) : RM_BANK_WAIT(0)) |
+						RM_RW_WAIT(1), RCMCONFIG);
+	he_writel(he_dev,
+		(he_is622(he_dev) ? TM_BANK_WAIT(2) : TM_BANK_WAIT(1)) |
+						TM_RW_WAIT(1), TCMCONFIG);
+
+	he_writel(he_dev, he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD, LB_CONFIG);
+
+	he_writel(he_dev, 
+		(he_is622(he_dev) ? UT_RD_DELAY(8) : UT_RD_DELAY(0)) |
+		(he_is622(he_dev) ? RC_UT_MODE(0) : RC_UT_MODE(1)) |
+		RX_VALVP(he_dev->vpibits) |
+		RX_VALVC(he_dev->vcibits),			 RC_CONFIG);
+
+	he_writel(he_dev, DRF_THRESH(0x20) |
+		(he_is622(he_dev) ? TX_UT_MODE(0) : TX_UT_MODE(1)) |
+		TX_VCI_MASK(he_dev->vcibits) |
+		LBFREE_CNT(he_dev->tx_numbuffs), 		TX_CONFIG);
+
+	he_writel(he_dev, 0x0, TXAAL5_PROTO);
+
+	he_writel(he_dev, PHY_INT_ENB |
+		(he_is622(he_dev) ? PTMR_PRE(67-1) : PTMR_PRE(50-1)),
+								RH_CONFIG);
+
+	/* 5.1.3 initialize connection memory */
+
+	for(i=0; i < TCM_MEM_SIZE; ++i)
+		he_writel_tcm(he_dev, 0, i);
+
+	for(i=0; i < RCM_MEM_SIZE; ++i)
+		he_writel_rcm(he_dev, 0, i);
+
+	/*
+	 *	transmit connection memory map
+	 *
+	 *                  tx memory
+	 *          0x0 ___________________
+	 *             |                   |
+	 *             |                   |
+	 *             |       TSRa        |
+	 *             |                   |
+	 *             |                   |
+	 *       0x8000|___________________|
+	 *             |                   |
+	 *             |       TSRb        |
+	 *       0xc000|___________________|
+	 *             |                   |
+	 *             |       TSRc        |
+	 *       0xe000|___________________|
+	 *             |       TSRd        |
+	 *       0xf000|___________________|
+	 *             |       tmABR       |
+	 *      0x10000|___________________|
+	 *             |                   |
+	 *             |       tmTPD       |
+	 *             |___________________|
+	 *             |                   |
+	 *                      ....
+	 *      0x1ffff|___________________|
+	 *
+	 *
+	 */
+
+	he_writel(he_dev, CONFIG_TSRB, TSRB_BA);
+	he_writel(he_dev, CONFIG_TSRC, TSRC_BA);
+	he_writel(he_dev, CONFIG_TSRD, TSRD_BA);
+	he_writel(he_dev, CONFIG_TMABR, TMABR_BA);
+	he_writel(he_dev, CONFIG_TPDBA, TPD_BA);
+
+
+	/*
+	 *	receive connection memory map
+	 *
+	 *          0x0 ___________________
+	 *             |                   |
+	 *             |                   |
+	 *             |       RSRa        |
+	 *             |                   |
+	 *             |                   |
+	 *       0x8000|___________________|
+	 *             |                   |
+	 *             |             rx0/1 |
+	 *             |       LBM         |   link lists of local
+	 *             |             tx    |   buffer memory 
+	 *             |                   |
+	 *       0xd000|___________________|
+	 *             |                   |
+	 *             |      rmABR        |
+	 *       0xe000|___________________|
+	 *             |                   |
+	 *             |       RSRb        |
+	 *             |___________________|
+	 *             |                   |
+	 *                      ....
+	 *       0xffff|___________________|
+	 */
+
+	he_writel(he_dev, 0x08000, RCMLBM_BA);
+	he_writel(he_dev, 0x0e000, RCMRSRB_BA);
+	he_writel(he_dev, 0x0d800, RCMABR_BA);
+
+	/* 5.1.4 initialize local buffer free pools linked lists */
+
+	he_init_rx_lbfp0(he_dev);
+	he_init_rx_lbfp1(he_dev);
+
+	he_writel(he_dev, 0x0, RLBC_H);
+	he_writel(he_dev, 0x0, RLBC_T);
+	he_writel(he_dev, 0x0, RLBC_H2);
+
+	he_writel(he_dev, 512, RXTHRSH);	/* 10% of r0+r1 buffers */
+	he_writel(he_dev, 256, LITHRSH); 	/* 5% of r0+r1 buffers */
+
+	he_init_tx_lbfp(he_dev);
+
+	he_writel(he_dev, he_is622(he_dev) ? 0x104780 : 0x800, UBUFF_BA);
+
+	/* 5.1.5 initialize intermediate receive queues */
+
+	if (he_is622(he_dev))
+	{
+		he_writel(he_dev, 0x000f, G0_INMQ_S);
+		he_writel(he_dev, 0x200f, G0_INMQ_L);
+
+		he_writel(he_dev, 0x001f, G1_INMQ_S);
+		he_writel(he_dev, 0x201f, G1_INMQ_L);
+
+		he_writel(he_dev, 0x002f, G2_INMQ_S);
+		he_writel(he_dev, 0x202f, G2_INMQ_L);
+
+		he_writel(he_dev, 0x003f, G3_INMQ_S);
+		he_writel(he_dev, 0x203f, G3_INMQ_L);
+
+		he_writel(he_dev, 0x004f, G4_INMQ_S);
+		he_writel(he_dev, 0x204f, G4_INMQ_L);
+
+		he_writel(he_dev, 0x005f, G5_INMQ_S);
+		he_writel(he_dev, 0x205f, G5_INMQ_L);
+
+		he_writel(he_dev, 0x006f, G6_INMQ_S);
+		he_writel(he_dev, 0x206f, G6_INMQ_L);
+
+		he_writel(he_dev, 0x007f, G7_INMQ_S);
+		he_writel(he_dev, 0x207f, G7_INMQ_L);
+	}
+	else
+	{
+		he_writel(he_dev, 0x0000, G0_INMQ_S);
+		he_writel(he_dev, 0x0008, G0_INMQ_L);
+
+		he_writel(he_dev, 0x0001, G1_INMQ_S);
+		he_writel(he_dev, 0x0009, G1_INMQ_L);
+
+		he_writel(he_dev, 0x0002, G2_INMQ_S);
+		he_writel(he_dev, 0x000a, G2_INMQ_L);
+
+		he_writel(he_dev, 0x0003, G3_INMQ_S);
+		he_writel(he_dev, 0x000b, G3_INMQ_L);
+
+		he_writel(he_dev, 0x0004, G4_INMQ_S);
+		he_writel(he_dev, 0x000c, G4_INMQ_L);
+
+		he_writel(he_dev, 0x0005, G5_INMQ_S);
+		he_writel(he_dev, 0x000d, G5_INMQ_L);
+
+		he_writel(he_dev, 0x0006, G6_INMQ_S);
+		he_writel(he_dev, 0x000e, G6_INMQ_L);
+
+		he_writel(he_dev, 0x0007, G7_INMQ_S);
+		he_writel(he_dev, 0x000f, G7_INMQ_L);
+	}
+
+	/* 5.1.6 application tunable parameters */
+
+	he_writel(he_dev, 0x0, MCC);
+	he_writel(he_dev, 0x0, OEC);
+	he_writel(he_dev, 0x0, DCC);
+	he_writel(he_dev, 0x0, CEC);
+	
+	/* 5.1.7 cs block initialization */
+
+	he_init_cs_block(he_dev);
+
+	/* 5.1.8 cs block connection memory initialization */
+	
+	he_init_cs_block_rcm(he_dev);
+
+	/* 5.1.10 initialize host structures */
+
+	he_init_tpdrq(he_dev);
+
+#ifdef USE_TPD_POOL
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
+	he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev,
+		sizeof(struct he_tpd), TPD_ALIGNMENT, 0, SLAB_KERNEL);
+#else
+	he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev,
+		sizeof(struct he_tpd), TPD_ALIGNMENT, 0);
+#endif
+	if (he_dev->tpd_pool == NULL)
+	{
+		hprintk1("unable to create tpd pci_pool\n");
+		return -ENOMEM;         
+	}
+
+	INIT_LIST_HEAD(&he_dev->outstanding_tpds);
+#else
+	he_dev->tpd_base = (void *) pci_alloc_consistent(he_dev->pci_dev,
+			CONFIG_NUMTPDS * sizeof(struct he_tpd), &he_dev->tpd_base_phys);
+	if (!he_dev->tpd_base)
+		return -ENOMEM;
+
+	for(i = 0; i < CONFIG_NUMTPDS; ++i)
+	{
+		he_dev->tpd_base[i].status = (i << TPD_ADDR_SHIFT);
+		he_dev->tpd_base[i].inuse = 0;
+	}
+		
+	he_dev->tpd_head = he_dev->tpd_base;
+	he_dev->tpd_end = &he_dev->tpd_base[CONFIG_NUMTPDS-1];
+#endif
+
+	if (he_init_group(he_dev, 0) != 0)
+		return -ENOMEM;
+
+	for (group = 1; group < HE_NUM_GROUPS; ++group)
+	{
+		he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32));
+		he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32));
+		he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32));
+		he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
+						G0_RBPS_BS + (group * 32));
+
+		he_writel(he_dev, 0x0, G0_RBPL_S + (group * 32));
+		he_writel(he_dev, 0x0, G0_RBPL_T + (group * 32));
+		he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
+						G0_RBPL_QI + (group * 32));
+		he_writel(he_dev, 0x0, G0_RBPL_BS + (group * 32));
+
+		he_writel(he_dev, 0x0, G0_RBRQ_ST + (group * 16));
+		he_writel(he_dev, 0x0, G0_RBRQ_H + (group * 16));
+		he_writel(he_dev, RBRQ_THRESH(0x1) | RBRQ_SIZE(0x0),
+						G0_RBRQ_Q + (group * 16));
+		he_writel(he_dev, 0x0, G0_RBRQ_I + (group * 16));
+
+		he_writel(he_dev, 0x0, G0_TBRQ_B_T + (group * 16));
+		he_writel(he_dev, 0x0, G0_TBRQ_H + (group * 16));
+		he_writel(he_dev, TBRQ_THRESH(0x1),
+						G0_TBRQ_THRESH + (group * 16));
+		he_writel(he_dev, 0x0, G0_TBRQ_S + (group * 16));
+	}
+
+	/* host status page */
+
+	he_dev->hsp = pci_alloc_consistent(he_dev->pci_dev,
+				sizeof(struct he_hsp), &he_dev->hsp_phys);
+	if (he_dev->hsp == NULL)
+	{
+		hprintk1("failed to allocate host status page\n");
+		return -ENOMEM;
+	}
+	memset(he_dev->hsp, 0, sizeof(struct he_hsp));
+	he_writel(he_dev, he_dev->hsp_phys, HSP_BA);
+
+	/* initialize framer */
+
+#ifdef CONFIG_ATM_HE_USE_SUNI
+	suni_init(he_dev->atm_dev);
+	if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->start)
+		he_dev->atm_dev->phy->start(he_dev->atm_dev);
+#endif /* CONFIG_ATM_HE_USE_SUNI */
+
+	if (sdh)
+	{
+		/* this really should be in suni.c but for now... */
+
+		int val;
+
+		val = he_phy_get(he_dev->atm_dev, SUNI_TPOP_APM);
+		val = (val & ~SUNI_TPOP_APM_S) | ( 0x2 << SUNI_TPOP_APM_S_SHIFT);
+		he_phy_put(he_dev->atm_dev, val, SUNI_TPOP_APM);
+	}
+
+	/* 5.1.12 enable transmit and receive */
+
+	reg = he_readl_mbox(he_dev, CS_ERCTL0);
+	reg |= TX_ENABLE|ER_ENABLE;
+	he_writel_mbox(he_dev, reg, CS_ERCTL0);
+
+	reg = he_readl(he_dev, RC_CONFIG);
+	reg |= RX_ENABLE;
+	he_writel(he_dev, reg, RC_CONFIG);
+
+#ifndef USE_HE_FIND_VCC
+	he_dev->he_vcc_table = kmalloc(sizeof(struct he_vcc_table) * 
+			(1 << (he_dev->vcibits + he_dev->vpibits)), GFP_KERNEL);
+	if (he_dev->he_vcc_table == NULL)
+	{
+		hprintk1("failed to alloc he_vcc_table\n");
+		return -ENOMEM;
+	}
+	memset(he_dev->he_vcc_table, 0, sizeof(struct he_vcc_table) *
+				(1 << (he_dev->vcibits + he_dev->vpibits)));
+#endif
+
+	for (i = 0; i < HE_NUM_CS_STPER; ++i)
+	{
+		he_dev->cs_stper[i].inuse = 0;
+		he_dev->cs_stper[i].pcr = -1;
+	}
+	he_dev->total_bw = 0;
+
+
+	/* atm linux initialization */
+
+	he_dev->atm_dev->ci_range.vpi_bits = he_dev->vpibits;
+	he_dev->atm_dev->ci_range.vci_bits = he_dev->vcibits;
+
+	he_dev->irq_peak = 0;
+	he_dev->rbrq_peak = 0;
+        he_dev->rbpl_peak = 0;
+        he_dev->tbrq_peak = 0;
+
+	HPRINTK("hell bent for leather!\n");
+
+	return 0;
+}
+
+static void
+he_stop(struct he_dev *he_dev)
+{
+	u16 command;
+	u32 gen_cntl_0, reg;
+	struct pci_dev *pci_dev;
+
+	pci_dev = he_dev->pci_dev;
+
+	/* disable interrupts */
+
+	if (he_dev->membase)
+	{
+		pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0);
+		gen_cntl_0 &= ~(INT_PROC_ENBL | INIT_ENB);
+		pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
+
+#ifdef USE_TASKLET
+		tasklet_disable(&he_dev->tasklet);
+#endif
+
+		/* disable recv and transmit */
+
+		reg = he_readl_mbox(he_dev, CS_ERCTL0);
+		reg &= ~(TX_ENABLE|ER_ENABLE);
+		he_writel_mbox(he_dev, reg, CS_ERCTL0);
+
+		reg = he_readl(he_dev, RC_CONFIG);
+		reg &= ~(RX_ENABLE);
+		he_writel(he_dev, reg, RC_CONFIG);
+	}
+
+#ifdef CONFIG_ATM_HE_USE_SUNI
+	if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->stop)
+		he_dev->atm_dev->phy->stop(he_dev->atm_dev);
+#endif /* CONFIG_ATM_HE_USE_SUNI */
+
+	if (he_dev->irq)
+	{
+#ifdef BUS_INT_WAR
+		sn_delete_polled_interrupt(he_dev->irq);
+#endif
+		free_irq(he_dev->irq, he_dev);
+	}
+
+	if (he_dev->irq_base)
+		pci_free_consistent(he_dev->pci_dev, (CONFIG_IRQ_SIZE+1)
+			* sizeof(struct he_irq), he_dev->irq_base, he_dev->irq_phys);
+
+	if (he_dev->hsp)
+		pci_free_consistent(he_dev->pci_dev, sizeof(struct he_hsp),
+						he_dev->hsp, he_dev->hsp_phys);
+
+	if (he_dev->rbpl_base)
+	{
+#ifdef USE_RBPL_POOL
+		for (i=0; i<CONFIG_RBPL_SIZE; ++i)
+		{
+			void *cpuaddr = he_dev->rbpl_virt[i].virt;
+			dma_addr_t dma_handle = he_dev->rbpl_base[i].phys;
+
+			pci_pool_free(he_dev->rbpl_pool, cpuaddr, dma_handle);
+		}
+#else
+		pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE
+			* CONFIG_RBPL_BUFSIZE, he_dev->rbpl_pages, he_dev->rbpl_pages_phys);
+#endif
+		pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE
+			* sizeof(struct he_rbp), he_dev->rbpl_base, he_dev->rbpl_phys);
+	}
+
+#ifdef USE_RBPL_POOL
+	if (he_dev->rbpl_pool)
+		pci_pool_destroy(he_dev->rbpl_pool);
+#endif
+
+#ifdef USE_RBPS
+	if (he_dev->rbps_base)
+	{
+#ifdef USE_RBPS_POOL
+		for (i=0; i<CONFIG_RBPS_SIZE; ++i)
+		{
+			void *cpuaddr = he_dev->rbps_virt[i].virt;
+			dma_addr_t dma_handle = he_dev->rbps_base[i].phys;
+
+			pci_pool_free(he_dev->rbps_pool, cpuaddr, dma_handle);
+		}
+#else
+		pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE
+			* CONFIG_RBPS_BUFSIZE, he_dev->rbps_pages, he_dev->rbps_pages_phys);
+#endif
+		pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE
+			* sizeof(struct he_rbp), he_dev->rbps_base, he_dev->rbps_phys);
+	}
+
+#ifdef USE_RBPS_POOL
+	if (he_dev->rbps_pool)
+		pci_pool_destroy(he_dev->rbps_pool);
+#endif
+
+#endif /* USE_RBPS */
+
+	if (he_dev->rbrq_base)
+		pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
+							he_dev->rbrq_base, he_dev->rbrq_phys);
+
+	if (he_dev->tbrq_base)
+		pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
+							he_dev->tbrq_base, he_dev->tbrq_phys);
+
+	if (he_dev->tpdrq_base)
+		pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
+							he_dev->tpdrq_base, he_dev->tpdrq_phys);
+
+#ifdef USE_TPD_POOL
+	if (he_dev->tpd_pool)
+		pci_pool_destroy(he_dev->tpd_pool);
+#else
+	if (he_dev->tpd_base)
+		pci_free_consistent(he_dev->pci_dev, CONFIG_NUMTPDS * sizeof(struct he_tpd),
+							he_dev->tpd_base, he_dev->tpd_base_phys);
+#endif
+
+#ifndef USE_HE_FIND_VCC
+	if (he_dev->he_vcc_table)
+		kfree(he_dev->he_vcc_table);
+#endif
+
+	if (he_dev->pci_dev)
+	{
+		pci_read_config_word(he_dev->pci_dev, PCI_COMMAND, &command);
+		command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+		pci_write_config_word(he_dev->pci_dev, PCI_COMMAND, command);
+	}
+	
+	if (he_dev->membase) iounmap((void *) he_dev->membase);
+}
+
+static struct he_tpd *
+__alloc_tpd(struct he_dev *he_dev)
+{
+#ifdef USE_TPD_POOL
+	struct he_tpd *tpd;
+	dma_addr_t dma_handle; 
+
+	tpd = pci_pool_alloc(he_dev->tpd_pool, SLAB_ATOMIC|SLAB_DMA, &dma_handle);              
+	if (tpd == NULL)
+		return NULL;
+			
+	tpd->status = TPD_ADDR(dma_handle);
+	tpd->reserved = 0; 
+	tpd->iovec[0].addr = 0; tpd->iovec[0].len = 0;
+	tpd->iovec[1].addr = 0; tpd->iovec[1].len = 0;
+	tpd->iovec[2].addr = 0; tpd->iovec[2].len = 0;
+
+	return tpd;
+#else
+	int i;
+
+	for(i = 0; i < CONFIG_NUMTPDS; ++i)
+	{
+		++he_dev->tpd_head;
+		if (he_dev->tpd_head > he_dev->tpd_end) {
+			he_dev->tpd_head = he_dev->tpd_base;
+		}
+
+		if (!he_dev->tpd_head->inuse) {
+			he_dev->tpd_head->inuse = 1;
+			he_dev->tpd_head->status &= TPD_MASK;
+			he_dev->tpd_head->iovec[0].addr = 0; he_dev->tpd_head->iovec[0].len = 0;
+			he_dev->tpd_head->iovec[1].addr = 0; he_dev->tpd_head->iovec[1].len = 0;
+			he_dev->tpd_head->iovec[2].addr = 0; he_dev->tpd_head->iovec[2].len = 0;
+			return he_dev->tpd_head;
+		}
+	}
+	hprintk("out of tpds -- increase CONFIG_NUMTPDS (%d)\n", CONFIG_NUMTPDS);
+	return NULL;
+#endif
+}
+
+#define AAL5_LEN(buf,len) 						\
+			((((unsigned char *)(buf))[(len)-6]<<8) |	\
+				(((unsigned char *)(buf))[(len)-5]))
+
+/* 2.10.1.2 receive
+ *
+ * aal5 packets can optionally return the tcp checksum in the lower
+ * 16 bits of the crc (RSR0_TCP_CKSUM)
+ */
+
+#define TCP_CKSUM(buf,len) 						\
+			((((unsigned char *)(buf))[(len)-2]<<8) |	\
+				(((unsigned char *)(buf))[(len-1)]))
+
+static int
+he_service_rbrq(struct he_dev *he_dev, int group)
+{
+	struct he_rbrq *rbrq_tail = (struct he_rbrq *)
+				((unsigned long)he_dev->rbrq_base |
+					he_dev->hsp->group[group].rbrq_tail);
+	struct he_rbp *rbp = NULL;
+	unsigned cid, lastcid = -1;
+	unsigned buf_len = 0;
+	struct sk_buff *skb;
+	struct atm_vcc *vcc = NULL;
+	struct he_vcc *he_vcc;
+	struct iovec *iov;
+	int pdus_assembled = 0;
+	int updated = 0;
+
+	while (he_dev->rbrq_head != rbrq_tail)
+	{
+		++updated;
+
+		HPRINTK("%p rbrq%d 0x%x len=%d cid=0x%x %s%s%s%s%s%s\n",
+			he_dev->rbrq_head, group,
+			RBRQ_ADDR(he_dev->rbrq_head),
+			RBRQ_BUFLEN(he_dev->rbrq_head),
+			RBRQ_CID(he_dev->rbrq_head),
+			RBRQ_CRC_ERR(he_dev->rbrq_head) ? " CRC_ERR" : "",
+			RBRQ_LEN_ERR(he_dev->rbrq_head) ? " LEN_ERR" : "",
+			RBRQ_END_PDU(he_dev->rbrq_head) ? " END_PDU" : "",
+			RBRQ_AAL5_PROT(he_dev->rbrq_head) ? " AAL5_PROT" : "",
+			RBRQ_CON_CLOSED(he_dev->rbrq_head) ? " CON_CLOSED" : "",
+			RBRQ_HBUF_ERR(he_dev->rbrq_head) ? " HBUF_ERR" : "");
+
+#ifdef USE_RBPS
+		if (RBRQ_ADDR(he_dev->rbrq_head) & RBP_SMALLBUF)
+			rbp = &he_dev->rbps_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))];
+		else
+#endif
+			rbp = &he_dev->rbpl_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))];
+		
+		buf_len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4;
+		cid = RBRQ_CID(he_dev->rbrq_head);
+
+#ifdef USE_HE_FIND_VCC
+		if (cid != lastcid)
+			vcc = he_find_vcc(he_dev, cid);
+		lastcid = cid;
+#else
+		vcc = HE_LOOKUP_VCC(he_dev, cid);
+#endif
+		if (vcc == NULL)
+		{
+			hprintk("vcc == NULL  (cid 0x%x)\n", cid);
+			if (!RBRQ_HBUF_ERR(he_dev->rbrq_head))
+					rbp->status &= ~RBP_LOANED;
+					
+			goto next_rbrq_entry;
+		}
+
+		he_vcc = HE_VCC(vcc);
+		if (he_vcc == NULL)
+		{
+			hprintk("he_vcc == NULL  (cid 0x%x)\n", cid);
+			if (!RBRQ_HBUF_ERR(he_dev->rbrq_head))
+					rbp->status &= ~RBP_LOANED;
+			goto next_rbrq_entry;
+		}
+
+		if (RBRQ_HBUF_ERR(he_dev->rbrq_head))
+		{
+			hprintk("HBUF_ERR!  (cid 0x%x)\n", cid);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+				++vcc->stats->rx_drop;
+#else
+				atomic_inc(&vcc->stats->rx_drop);
+#endif
+			goto return_host_buffers;
+		}
+
+		he_vcc->iov_tail->iov_base = (void *) RBRQ_ADDR(he_dev->rbrq_head);
+		he_vcc->iov_tail->iov_len = buf_len;
+		he_vcc->pdu_len += buf_len;
+		++he_vcc->iov_tail;
+
+		if (RBRQ_CON_CLOSED(he_dev->rbrq_head))
+		{
+			lastcid = -1;
+			HPRINTK("wake_up rx_waitq  (cid 0x%x)\n", cid);
+			wake_up(&he_vcc->rx_waitq);
+			goto return_host_buffers;
+		}
+
+#ifdef notdef
+		if (he_vcc->iov_tail - he_vcc->iov_head > 32)
+		{
+			hprintk("iovec full!  cid 0x%x\n", cid);
+			goto return_host_buffers;
+		}
+#endif
+		if (!RBRQ_END_PDU(he_dev->rbrq_head)) goto next_rbrq_entry;
+
+		if (RBRQ_LEN_ERR(he_dev->rbrq_head)
+				|| RBRQ_CRC_ERR(he_dev->rbrq_head))
+		{
+			HPRINTK("%s%s (%d.%d)\n",
+				RBRQ_CRC_ERR(he_dev->rbrq_head)
+							? "CRC_ERR " : "",
+				RBRQ_LEN_ERR(he_dev->rbrq_head)
+							? "LEN_ERR" : "",
+							vcc->vpi, vcc->vci);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+			++vcc->stats->rx_err;
+#else
+			atomic_inc(&vcc->stats->rx_err);
+#endif
+			goto return_host_buffers;
+		}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,15)
+		skb = atm_alloc_charge(vcc, he_vcc->pdu_len + rx_skb_reserve,
+							GFP_ATOMIC);
+#else
+		if (!atm_charge(vcc, atm_pdu2truesize(he_vcc->pdu_len + rx_skb_reserve)))
+			skb = NULL;
+		else
+		{
+			skb = alloc_skb(he_vcc->pdu_len + rx_skb_reserve, GFP_ATOMIC);
+			if (!skb) atm_return(vcc,
+				atm_pdu2truesize(he_vcc->pdu_len + rx_skb_reserve));
+		}
+#endif
+		if (!skb)
+		{
+			HPRINTK("charge failed (%d.%d)\n", vcc->vpi, vcc->vci);
+			goto return_host_buffers;
+		}
+
+		if (rx_skb_reserve > 0) skb_reserve(skb, rx_skb_reserve);
+
+		do_gettimeofday(&skb->stamp);
+
+		for(iov = he_vcc->iov_head;
+				iov < he_vcc->iov_tail; ++iov)
+		{
+#ifdef USE_RBPS
+			if ((u32)iov->iov_base & RBP_SMALLBUF)
+				memcpy(skb_put(skb, iov->iov_len),
+					he_dev->rbps_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len);
+			else
+#endif
+				memcpy(skb_put(skb, iov->iov_len),
+					he_dev->rbpl_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len);
+		}
+
+		switch(vcc->qos.aal)
+		{
+			case ATM_AAL0:
+				/* 2.10.1.5 raw cell receive */
+				skb->len = ATM_AAL0_SDU;
+				skb->tail = skb->data + skb->len;
+				break;
+			case ATM_AAL5:
+				/* 2.10.1.2 aal5 receive */
+
+				skb->len = AAL5_LEN(skb->data, he_vcc->pdu_len);
+				skb->tail = skb->data + skb->len;
+#ifdef USE_CHECKSUM_HW
+				if (vcc->vpi == 0 && vcc->vci >= ATM_NOT_RSV_VCI) 
+				{
+					skb->ip_summed = CHECKSUM_HW;
+					skb->csum = TCP_CKSUM(skb->data,
+							he_vcc->pdu_len);
+				}
+#endif
+				break;
+		}
+
+#ifdef should_never_happen
+		if (skb->len > vcc->qos.rxtp.max_sdu)
+			hprintk("pdu_len (%d) > vcc->qos.rxtp.max_sdu (%d)!  cid 0x%x\n", skb->len, vcc->qos.rxtp.max_sdu, cid);
+#endif
+
+#ifdef notdef
+		ATM_SKB(skb)->vcc = vcc;
+#endif
+		vcc->push(vcc, skb);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+		++vcc->stats->rx;
+#else
+		atomic_inc(&vcc->stats->rx);
+#endif
+
+return_host_buffers:
+		++pdus_assembled;
+
+		for(iov = he_vcc->iov_head;
+				iov < he_vcc->iov_tail; ++iov)
+		{
+#ifdef USE_RBPS
+			if ((u32)iov->iov_base & RBP_SMALLBUF)
+				rbp = &he_dev->rbps_base[RBP_INDEX(iov->iov_base)];
+			else
+#endif
+				rbp = &he_dev->rbpl_base[RBP_INDEX(iov->iov_base)];
+
+			rbp->status &= ~RBP_LOANED;
+		}
+
+		he_vcc->iov_tail = he_vcc->iov_head;
+		he_vcc->pdu_len = 0;
+
+next_rbrq_entry:
+		he_dev->rbrq_head = (struct he_rbrq *)
+				((unsigned long) he_dev->rbrq_base |
+					RBRQ_MASK(++he_dev->rbrq_head));
+
+	}
+
+	if (updated)
+	{
+		if (updated > he_dev->rbrq_peak) he_dev->rbrq_peak = updated;
+
+		he_writel(he_dev, RBRQ_MASK(he_dev->rbrq_head),
+						G0_RBRQ_H + (group * 16));
+#ifdef CONFIG_IA64_SGI_SN2
+		(void) he_readl(he_dev, G0_RBRQ_H + (group * 16));
+#endif
+	}
+
+	return pdus_assembled;
+}
+
+static void
+he_service_tbrq(struct he_dev *he_dev, int group)
+{
+	struct he_tbrq *tbrq_tail = (struct he_tbrq *)
+				((unsigned long)he_dev->tbrq_base |
+					he_dev->hsp->group[group].tbrq_tail);
+	struct he_tpd *tpd;
+	int slot, updated = 0;
+#ifdef USE_TPD_POOL
+	struct list_head *p;
+#endif
+
+	/* 2.1.6 transmit buffer return queue */
+
+	while (he_dev->tbrq_head != tbrq_tail)
+	{
+		++updated;
+
+		HPRINTK("tbrq%d 0x%x%s%s\n",
+			group,
+			TBRQ_TPD(he_dev->tbrq_head), 
+			TBRQ_EOS(he_dev->tbrq_head) ? " EOS" : "",
+			TBRQ_MULTIPLE(he_dev->tbrq_head) ? " MULTIPLE" : "");
+#ifdef USE_TPD_POOL
+		tpd = NULL;
+		p = &he_dev->outstanding_tpds;
+		while ((p = p->next) != &he_dev->outstanding_tpds)
+		{
+			struct he_tpd *__tpd = list_entry(p, struct he_tpd, entry);
+			if (TPD_ADDR(__tpd->status) == TBRQ_TPD(he_dev->tbrq_head))
+			{
+				tpd = __tpd;
+				list_del(&__tpd->entry);
+				break;
+			}
+		}
+
+		if (tpd == NULL)
+		{
+			hprintk("unable to locate tpd for dma buffer %x\n",
+						TBRQ_TPD(he_dev->tbrq_head));
+			goto next_tbrq_entry;
+		}
+#else
+		tpd = &he_dev->tpd_base[ TPD_INDEX(TBRQ_TPD(he_dev->tbrq_head)) ];
+#endif
+
+		if (TBRQ_EOS(he_dev->tbrq_head))
+		{
+			HPRINTK("wake_up(tx_waitq) cid 0x%x\n",
+				he_mkcid(he_dev, tpd->vcc->vpi, tpd->vcc->vci));
+			if (tpd->vcc)
+				wake_up(&HE_VCC(tpd->vcc)->tx_waitq);
+
+			goto next_tbrq_entry;
+		}
+
+		for(slot = 0; slot < TPD_MAXIOV; ++slot)
+		{
+			if (tpd->iovec[slot].addr)
+				pci_unmap_single(he_dev->pci_dev,
+					tpd->iovec[slot].addr,
+					tpd->iovec[slot].len & TPD_LEN_MASK,
+							PCI_DMA_TODEVICE);
+			if (tpd->iovec[slot].len & TPD_LST) break;
+				
+		}
+
+		if (tpd->skb)	/* && !TBRQ_MULTIPLE(he_dev->tbrq_head) */
+		{
+			if (tpd->vcc && tpd->vcc->pop)
+				tpd->vcc->pop(tpd->vcc, tpd->skb);
+			else
+				dev_kfree_skb_any(tpd->skb);
+		}
+
+next_tbrq_entry:
+#ifdef USE_TPD_POOL
+		if (tpd) pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status));
+#else
+		tpd->inuse = 0;
+#endif
+		he_dev->tbrq_head = (struct he_tbrq *)
+				((unsigned long) he_dev->tbrq_base |
+					TBRQ_MASK(++he_dev->tbrq_head));
+	}
+
+	if (updated)
+	{
+		if (updated > he_dev->tbrq_peak) he_dev->tbrq_peak = updated;
+
+		he_writel(he_dev, TBRQ_MASK(he_dev->tbrq_head),
+						G0_TBRQ_H + (group * 16));
+#ifdef CONFIG_IA64_SGI_SN2
+		(void) he_readl(he_dev, G0_TBRQ_H + (group * 16));
+#endif
+	}
+}
+
+
+static void
+he_service_rbpl(struct he_dev *he_dev, int group)
+{
+	struct he_rbp *newtail;
+	struct he_rbp *rbpl_head;
+	int moved = 0;
+
+	rbpl_head = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base |
+					RBPL_MASK(he_readl(he_dev, G0_RBPL_S)));
+
+	for(;;)
+	{
+		newtail = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base |
+						RBPL_MASK(he_dev->rbpl_tail+1));
+
+		/* table 3.42 -- rbpl_tail should never be set to rbpl_head */
+		if ((newtail == rbpl_head) || (newtail->status & RBP_LOANED))
+			break;
+
+		newtail->status |= RBP_LOANED;
+		he_dev->rbpl_tail = newtail;
+		++moved;
+
+	} 
+
+	if (moved) {
+		he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T);
+#ifdef CONFIG_IA64_SGI_SN2
+                (void) he_readl(he_dev, G0_RBPL_T);
+#endif
+	}
+}
+
+#ifdef USE_RBPS
+static void
+he_service_rbps(struct he_dev *he_dev, int group)
+{
+	struct he_rbp *newtail;
+	struct he_rbp *rbps_head;
+	int moved = 0;
+
+	rbps_head = (struct he_rbp *) ((unsigned long)he_dev->rbps_base |
+					RBPS_MASK(he_readl(he_dev, G0_RBPS_S)));
+
+	for(;;)
+	{
+		newtail = (struct he_rbp *) ((unsigned long)he_dev->rbps_base |
+						RBPS_MASK(he_dev->rbps_tail+1));
+
+		/* table 3.42 -- rbps_tail should never be set to rbps_head */
+		if ((newtail == rbps_head) || (newtail->status & RBP_LOANED))
+			break;
+
+		newtail->status |= RBP_LOANED;
+		he_dev->rbps_tail = newtail;
+		++moved;
+
+	} 
+
+	if (moved) {
+		he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), G0_RBPS_T);
+#ifdef CONFIG_IA64_SGI_SN2
+                (void) he_readl(he_dev, G0_RBPS_T);
+#endif
+	}
+}
+#endif /* USE_RBPS */
+
+static void
+he_tasklet(unsigned long data)
+{
+	unsigned long flags;
+	struct he_dev *he_dev = (struct he_dev *) data;
+	int group, type;
+	int updated = 0;
+
+	HPRINTK("tasklet (0x%lx)\n", data);
+#ifdef USE_TASKLET
+	HE_SPIN_LOCK(he_dev, flags);
+#endif
+
+	while(he_dev->irq_head != he_dev->irq_tail)
+	{
+		++updated;
+
+		type = ITYPE_TYPE(he_dev->irq_head->isw);
+		group = ITYPE_GROUP(he_dev->irq_head->isw);
+
+		switch (type)
+		{
+			case ITYPE_RBRQ_THRESH:
+				hprintk("rbrq%d threshold\n", group);
+			case ITYPE_RBRQ_TIMER:
+				if (he_service_rbrq(he_dev, group))
+				{
+					he_service_rbpl(he_dev, group);
+#ifdef USE_RBPS
+					he_service_rbps(he_dev, group);
+#endif /* USE_RBPS */
+				}
+				break;
+			case ITYPE_TBRQ_THRESH:
+				hprintk("tbrq%d threshold\n", group);
+			case ITYPE_TPD_COMPLETE:
+				he_service_tbrq(he_dev, group);
+				break;
+			case ITYPE_RBPL_THRESH:
+				he_service_rbpl(he_dev, group);
+				break;
+			case ITYPE_RBPS_THRESH:
+#ifdef USE_RBPS
+				he_service_rbps(he_dev, group);
+#endif /* USE_RBPS */
+				break;
+			case ITYPE_PHY:
+#ifdef CONFIG_ATM_HE_USE_SUNI
+				HE_SPIN_UNLOCK(he_dev, flags);
+				if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->interrupt)
+					he_dev->atm_dev->phy->interrupt(he_dev->atm_dev);
+				HE_SPIN_LOCK(he_dev, flags);
+#endif
+				HPRINTK1("phy interrupt\n");
+				break;
+			case ITYPE_OTHER:
+				switch (type|group)
+				{
+					case ITYPE_PARITY:
+						hprintk1("parity error\n");
+						break;
+					case ITYPE_ABORT:
+						hprintk("abort 0x%x\n", he_readl(he_dev, ABORT_ADDR));
+						break;
+				}
+				break;
+			default:
+				if (he_dev->irq_head->isw == ITYPE_INVALID)
+				{
+					/* see 8.1.1 -- check all queues */
+
+					HPRINTK("isw not updated 0x%x\n",
+						he_dev->irq_head->isw);
+
+					he_service_rbrq(he_dev, 0);
+					he_service_rbpl(he_dev, 0);
+#ifdef USE_RBPS
+					he_service_rbps(he_dev, 0);
+#endif /* USE_RBPS */
+					he_service_tbrq(he_dev, 0);
+				}
+				else
+					hprintk("bad isw = 0x%x?\n",
+						he_dev->irq_head->isw);
+		}
+
+		he_dev->irq_head->isw = ITYPE_INVALID;
+
+		he_dev->irq_head = (struct he_irq *) NEXT_ENTRY(he_dev->irq_base, he_dev->irq_head, IRQ_MASK);
+	}
+
+	if (updated)
+	{
+		if (updated > he_dev->irq_peak) he_dev->irq_peak = updated;
+
+		he_writel(he_dev,
+			IRQ_SIZE(CONFIG_IRQ_SIZE) |
+			IRQ_THRESH(CONFIG_IRQ_THRESH) |
+			IRQ_TAIL(he_dev->irq_tail), IRQ0_HEAD);
+		(void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata */
+	}
+#ifdef USE_TASKLET
+	HE_SPIN_UNLOCK(he_dev, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,69)
+static irqreturn_t
+#else
+static void
+#endif
+he_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned long flags;
+	struct he_dev *he_dev = (struct he_dev * )dev_id;
+	int handled = 0;
+
+	if (he_dev == NULL)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,69)
+		return IRQ_NONE;
+#else
+		return;
+#endif
+
+	HE_SPIN_LOCK(he_dev, flags);
+
+	he_dev->irq_tail = (struct he_irq *) (((unsigned long)he_dev->irq_base) |
+						(*he_dev->irq_tailoffset << 2));
+
+	if (he_dev->irq_tail == he_dev->irq_head)
+	{
+		HPRINTK1("tailoffset not updated?\n");
+		he_dev->irq_tail = (struct he_irq *) ((unsigned long)he_dev->irq_base |
+			((he_readl(he_dev, IRQ0_BASE) & IRQ_MASK) << 2));
+		(void) he_readl(he_dev, INT_FIFO);	/* 8.1.2 controller errata */
+	}
+
+#ifdef DEBUG
+	if (he_dev->irq_head == he_dev->irq_tail /* && !IRQ_PENDING */)
+		hprintk1("spurious (or shared) interrupt?\n");
+#endif
+
+	if (he_dev->irq_head != he_dev->irq_tail)
+	{
+		handled = 1;
+#ifdef USE_TASKLET
+		tasklet_schedule(&he_dev->tasklet);
+#else
+		he_tasklet((unsigned long) he_dev);
+#endif
+		he_writel(he_dev, INT_CLEAR_A, INT_FIFO);
+							/* clear interrupt */
+#ifdef CONFIG_IA64_SGI_SN2
+		(void) he_readl(he_dev, INT_FIFO);
+#endif
+	}
+	HE_SPIN_UNLOCK(he_dev, flags);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,69)
+	return IRQ_RETVAL(handled);
+#else
+	return;
+#endif
+
+}
+
+static __inline__ void
+__enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid)
+{
+	struct he_tpdrq *new_tail;
+
+	HPRINTK("tpdrq %p cid 0x%x -> tpdrq_tail %p\n",
+					tpd, cid, he_dev->tpdrq_tail);
+
+	/* new_tail = he_dev->tpdrq_tail; */
+	new_tail = (struct he_tpdrq *) ((unsigned long) he_dev->tpdrq_base |
+					TPDRQ_MASK(he_dev->tpdrq_tail+1));
+
+	/*
+	 * check to see if we are about to set the tail == head
+	 * if true, update the head pointer from the adapter
+	 * to see if this is really the case (reading the queue
+	 * head for every enqueue would be unnecessarily slow)
+	 */
+
+	if (new_tail == he_dev->tpdrq_head)
+	{
+		he_dev->tpdrq_head = (struct he_tpdrq *)
+			(((unsigned long)he_dev->tpdrq_base) |
+				TPDRQ_MASK(he_readl(he_dev, TPDRQ_B_H)));
+
+		if (new_tail == he_dev->tpdrq_head)
+		{
+			hprintk("tpdrq full (cid 0x%x)\n", cid);
+			/*
+			 * FIXME
+			 * push tpd onto a transmit backlog queue
+			 * after service_tbrq, service the backlog
+			 * for now, we just drop the pdu
+			 */
+			if (tpd->skb)
+			{
+				if (tpd->vcc->pop)
+					tpd->vcc->pop(tpd->vcc, tpd->skb);
+				else
+					dev_kfree_skb_any(tpd->skb);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+				++tpd->vcc->stats->tx_err;
+#else
+				atomic_inc(&tpd->vcc->stats->tx_err);
+#endif
+			}
+#ifdef USE_TPD_POOL
+			pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status));
+#else
+			tpd->inuse = 0;
+#endif
+			return;
+		}
+	}
+
+	/* 2.1.5 transmit packet descriptor ready queue */
+#ifdef USE_TPD_POOL
+	list_add_tail(&tpd->entry, &he_dev->outstanding_tpds);
+	he_dev->tpdrq_tail->tpd = TPD_ADDR(tpd->status);
+#else
+	he_dev->tpdrq_tail->tpd = he_dev->tpd_base_phys +
+				(TPD_INDEX(tpd->status) * sizeof(struct he_tpd));
+#endif
+	he_dev->tpdrq_tail->cid = cid;
+	wmb();
+
+	he_dev->tpdrq_tail = new_tail;
+
+	he_writel(he_dev, TPDRQ_MASK(he_dev->tpdrq_tail), TPDRQ_T);
+#ifdef CONFIG_IA64_SGI_SN2
+	(void) he_readl(he_dev, TPDRQ_T);
+#endif
+}
+
+static int
+he_open(struct atm_vcc *vcc, short vpi, int vci)
+{
+	unsigned long flags;
+	struct he_dev *he_dev = HE_DEV(vcc->dev);
+	struct he_vcc *he_vcc;
+	int err = 0;
+	unsigned cid, rsr0, rsr1, rsr4, tsr0, tsr0_aal, tsr4, period, reg, clock;
+
+	
+	if ((err = atm_find_ci(vcc, &vpi, &vci)))
+	{
+		HPRINTK("atm_find_ci err = %d\n", err);
+		return err;
+	}
+	if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) return 0;
+	vcc->vpi = vpi;
+	vcc->vci = vci;
+
+	HPRINTK("open vcc %p %d.%d\n", vcc, vpi, vci);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
+	vcc->flags |= ATM_VF_ADDR;
+#else
+	set_bit(ATM_VF_ADDR, &vcc->flags);
+#endif
+
+	cid = he_mkcid(he_dev, vpi, vci);
+
+	he_vcc = (struct he_vcc *) kmalloc(sizeof(struct he_vcc), GFP_ATOMIC);
+	if (he_vcc == NULL)
+	{
+		hprintk1("unable to allocate he_vcc during open\n");
+		return -ENOMEM;
+	}
+
+	he_vcc->iov_tail = he_vcc->iov_head;
+	he_vcc->pdu_len = 0;
+	he_vcc->rc_index = -1;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
+	init_waitqueue(&he_vcc->rx_waitq);
+	init_waitqueue(&he_vcc->tx_waitq);
+#else
+	init_waitqueue_head(&he_vcc->rx_waitq);
+	init_waitqueue_head(&he_vcc->tx_waitq);
+#endif
+
+	HE_VCC(vcc) = he_vcc;
+
+	if (vcc->qos.txtp.traffic_class != ATM_NONE)
+	{
+		int pcr_goal;
+
+                pcr_goal = atm_pcr_goal(&vcc->qos.txtp);
+                if (pcr_goal == 0)
+                        pcr_goal = he_dev->atm_dev->link_rate;
+                if (pcr_goal < 0)	/* means round down, technically */
+                        pcr_goal = -pcr_goal;
+
+		HPRINTK("open tx cid 0x%x pcr_goal %d\n", cid, pcr_goal);
+
+		switch (vcc->qos.aal)
+		{
+			case ATM_AAL5:
+				tsr0_aal = TSR0_AAL5;
+				tsr4 = TSR4_AAL5;
+				break;
+			case ATM_AAL0:
+				tsr0_aal = TSR0_AAL0_SDU;
+				tsr4 = TSR4_AAL0_SDU;
+				break;
+			default:
+				err = -EINVAL;
+				goto open_failed;
+		}
+
+		HE_SPIN_LOCK(he_dev, flags);
+		tsr0 = he_readl_tsr0(he_dev, cid);
+		HE_SPIN_UNLOCK(he_dev, flags);
+
+		if (TSR0_CONN_STATE(tsr0) != 0)
+		{
+			hprintk("cid 0x%x not idle (tsr0 = 0x%x)\n", cid, tsr0);
+			err = -EBUSY;
+			goto open_failed;
+		}
+
+		switch(vcc->qos.txtp.traffic_class)
+		{
+			case ATM_UBR:
+				/* 2.3.3.1 open connection ubr */
+
+				tsr0 = TSR0_UBR | TSR0_GROUP(0) | tsr0_aal |
+					TSR0_USE_WMIN | TSR0_UPDATE_GER;
+				break;
+
+			case ATM_CBR:
+				/* 2.3.3.2 open connection cbr */
+
+				/* 8.2.3 cbr scheduler wrap problem -- limit to 90% total link rate */
+				if ((he_dev->total_bw + pcr_goal)
+					> (he_dev->atm_dev->link_rate * 9 / 10))
+				{
+					err = -EBUSY;
+					goto open_failed;
+				}
+
+				HE_SPIN_LOCK(he_dev, flags);			/* also protects he_dev->cs_stper[] */
+
+				/* find an unused cs_stper register */
+				for(reg = 0; reg < HE_NUM_CS_STPER; ++reg)
+					if (he_dev->cs_stper[reg].inuse == 0 || 
+						he_dev->cs_stper[reg].pcr == pcr_goal)
+					break;
+
+				if (reg == HE_NUM_CS_STPER)
+				{
+					err = -EBUSY;
+					HE_SPIN_UNLOCK(he_dev, flags);
+					goto open_failed;
+				}
+
+				he_dev->total_bw += pcr_goal;
+
+				he_vcc->rc_index = reg;
+				++he_dev->cs_stper[reg].inuse;
+				he_dev->cs_stper[reg].pcr = pcr_goal;
+
+				clock = he_is622(he_dev) ? 66667000 : 50000000;
+				period = clock / pcr_goal;
+				
+				HPRINTK("rc_index = %d period = %d\n",
+								reg, period);
+
+				he_writel_mbox(he_dev, rate_to_atmf(period/2),
+							CS_STPER0 + reg);
+				HE_SPIN_UNLOCK(he_dev, flags);
+
+				tsr0 = TSR0_CBR | TSR0_GROUP(0) | tsr0_aal |
+							TSR0_RC_INDEX(reg);
+
+				break;
+			default:
+				err = -EINVAL;
+				goto open_failed;
+		}
+
+		HE_SPIN_LOCK(he_dev, flags);
+
+		he_writel_tsr0(he_dev, tsr0, cid);
+		he_writel_tsr4(he_dev, tsr4 | 1, cid);
+		he_writel_tsr1(he_dev, TSR1_MCR(rate_to_atmf(0)) |
+					TSR1_PCR(rate_to_atmf(pcr_goal)), cid);
+		he_writel_tsr2(he_dev, TSR2_ACR(rate_to_atmf(pcr_goal)), cid);
+		he_writel_tsr9(he_dev, TSR9_OPEN_CONN, cid);
+
+		he_writel_tsr3(he_dev, 0x0, cid);
+		he_writel_tsr5(he_dev, 0x0, cid);
+		he_writel_tsr6(he_dev, 0x0, cid);
+		he_writel_tsr7(he_dev, 0x0, cid);
+		he_writel_tsr8(he_dev, 0x0, cid);
+		he_writel_tsr10(he_dev, 0x0, cid);
+		he_writel_tsr11(he_dev, 0x0, cid);
+		he_writel_tsr12(he_dev, 0x0, cid);
+		he_writel_tsr13(he_dev, 0x0, cid);
+		he_writel_tsr14(he_dev, 0x0, cid);
+#ifdef CONFIG_IA64_SGI_SN2
+		(void) he_readl_tsr0(he_dev, cid);
+#endif
+		HE_SPIN_UNLOCK(he_dev, flags);
+	}
+
+	if (vcc->qos.rxtp.traffic_class != ATM_NONE)
+	{
+		unsigned aal;
+
+		HPRINTK("open rx cid 0x%x (rx_waitq %p)\n", cid,
+		 				&HE_VCC(vcc)->rx_waitq);
+
+		switch (vcc->qos.aal)
+		{
+			case ATM_AAL5:
+				aal = RSR0_AAL5;
+				break;
+			case ATM_AAL0:
+				aal = RSR0_RAWCELL;
+				break;
+			default:
+				err = -EINVAL;
+				goto open_failed;
+		}
+
+		HE_SPIN_LOCK(he_dev, flags);
+
+		rsr0 = he_readl_rsr0(he_dev, cid);
+		if (rsr0 & RSR0_OPEN_CONN)
+		{
+			HE_SPIN_UNLOCK(he_dev, flags);
+
+			hprintk("cid 0x%x not idle (rsr0 = 0x%x)\n", cid, rsr0);
+			err = -EBUSY;
+			goto open_failed;
+		}
+
+#ifdef USE_RBPS
+		rsr1 = RSR1_GROUP(0);
+		rsr4 = RSR4_GROUP(0);
+#else /* !USE_RBPS */
+		rsr1 = RSR1_GROUP(0)|RSR1_RBPL_ONLY;
+		rsr4 = RSR4_GROUP(0)|RSR4_RBPL_ONLY;
+#endif /* USE_RBPS */
+		rsr0 = vcc->qos.rxtp.traffic_class == ATM_UBR ? 
+				(RSR0_EPD_ENABLE|RSR0_PPD_ENABLE) : 0;
+
+#ifdef USE_CHECKSUM_HW
+		if (vpi == 0 && vci >= ATM_NOT_RSV_VCI) rsr0 |= RSR0_TCP_CKSUM;
+#endif
+
+		he_writel_rsr4(he_dev, rsr4, cid);
+		he_writel_rsr1(he_dev, rsr1, cid);
+		/* 5.1.11 last parameter initialized should be
+		          the open/closed indication in rsr0 */
+		he_writel_rsr0(he_dev,
+			rsr0 | RSR0_START_PDU | RSR0_OPEN_CONN | aal, cid);
+#ifdef CONFIG_IA64_SGI_SN2
+		(void) he_readl_rsr0(he_dev, cid);
+#endif
+
+		HE_SPIN_UNLOCK(he_dev, flags);
+
+#ifndef USE_HE_FIND_VCC
+		HE_LOOKUP_VCC(he_dev, cid) = vcc;
+#endif
+	}
+
+open_failed:
+
+	if (err)
+	{
+		if (he_vcc) kfree(he_vcc);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
+		vcc->flags &= ~ATM_VF_ADDR;
+#else
+		clear_bit(ATM_VF_ADDR, &vcc->flags);
+#endif
+	}
+	else
+	{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
+		vcc->flags |= ATM_VF_READY;
+#else
+		set_bit(ATM_VF_READY, &vcc->flags);
+#endif
+	}
+
+	return err;
+}
+
+static void
+he_close(struct atm_vcc *vcc)
+{
+	unsigned long flags;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,1)
+	DECLARE_WAITQUEUE(wait, current);
+#else
+	struct wait_queue wait = { current, NULL };
+#endif
+	struct he_dev *he_dev = HE_DEV(vcc->dev);
+	struct he_tpd *tpd;
+	unsigned cid;
+	struct he_vcc *he_vcc = HE_VCC(vcc);
+#define MAX_RETRY 30
+	int retry = 0, sleep = 1, tx_inuse;
+
+	HPRINTK("close vcc %p %d.%d\n", vcc, vcc->vpi, vcc->vci);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
+	vcc->flags &= ~ATM_VF_READY;
+#else
+	clear_bit(ATM_VF_READY, &vcc->flags);
+#endif
+	cid = he_mkcid(he_dev, vcc->vpi, vcc->vci);
+
+	if (vcc->qos.rxtp.traffic_class != ATM_NONE)
+	{
+		int timeout;
+
+		HPRINTK("close rx cid 0x%x\n", cid);
+
+		/* 2.7.2.2 close receive operation */
+
+		/* wait for previous close (if any) to finish */
+
+		HE_SPIN_LOCK(he_dev, flags);
+		while(he_readl(he_dev, RCC_STAT) & RCC_BUSY)
+		{
+			HPRINTK("close cid 0x%x RCC_BUSY\n", cid);
+			udelay(250);
+		}
+
+		add_wait_queue(&he_vcc->rx_waitq, &wait);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+
+		he_writel_rsr0(he_dev, RSR0_CLOSE_CONN, cid);
+#ifdef CONFIG_IA64_SGI_SN2
+		(void) he_readl_rsr0(he_dev, cid);
+#endif
+		he_writel_mbox(he_dev, cid, RXCON_CLOSE);
+		HE_SPIN_UNLOCK(he_dev, flags);
+
+		timeout = schedule_timeout(30*HZ);
+
+		remove_wait_queue(&he_vcc->rx_waitq, &wait);
+		set_current_state(TASK_RUNNING);
+
+		if (timeout == 0)
+			hprintk("close rx timeout cid 0x%x\n", cid);
+
+#ifndef USE_HE_FIND_VCC
+		HE_LOOKUP_VCC(he_dev, cid) = NULL;
+#endif
+		HPRINTK("close rx cid 0x%x complete\n", cid);
+
+	}
+
+	if (vcc->qos.txtp.traffic_class != ATM_NONE)
+	{
+		volatile unsigned tsr4, tsr0;
+		int timeout;
+
+		HPRINTK("close tx cid 0x%x\n", cid);
+		
+		/* 2.1.2
+		 *
+		 * ... the host must first stop queueing packets to the TPDRQ
+		 * on the connection to be closed, then wait for all outstanding
+		 * packets to be transmitted and their buffers returned to the
+		 * TBRQ. When the last packet on the connection arrives in the
+		 * TBRQ, the host issues the close command to the adapter.
+		 */
+
+		while (((tx_inuse = atomic_read(&vcc->sk->wmem_alloc)) > 0)
+							&& (retry < MAX_RETRY))
+		{
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			(void) schedule_timeout(sleep);
+			set_current_state(TASK_RUNNING);
+			if (sleep < HZ) sleep = sleep * 2;
+
+			++retry;
+		}
+
+		if (tx_inuse) hprintk("close tx cid 0x%x tx_inuse = %d\n",
+								cid, tx_inuse);
+
+		/* 2.3.1.1 generic close operations with flush */
+
+		HE_SPIN_LOCK(he_dev, flags);
+		he_writel_tsr4_upper(he_dev, TSR4_FLUSH_CONN, cid);
+					/* also clears TSR4_SESSION_ENDED */
+#ifdef CONFIG_IA64_SGI_SN2
+		(void) he_readl_tsr4(he_dev, cid);
+#endif
+
+		switch(vcc->qos.txtp.traffic_class)
+		{
+			case ATM_UBR:
+				he_writel_tsr1(he_dev, 
+					TSR1_MCR(rate_to_atmf(200000))
+					| TSR1_PCR(0), cid);
+				break;
+			case ATM_CBR:
+				he_writel_tsr14_upper(he_dev, TSR14_DELETE, cid);
+				break;
+		}
+
+
+		tpd = __alloc_tpd(he_dev);
+		if (tpd == NULL)
+		{
+			hprintk("close tx he_alloc_tpd failed cid 0x%x\n", cid);
+			goto close_tx_incomplete;
+		}
+		tpd->status |= TPD_EOS | TPD_INT;
+		tpd->skb = NULL;
+		tpd->vcc = vcc;
+		wmb();
+
+		add_wait_queue(&he_vcc->tx_waitq, &wait);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		__enqueue_tpd(he_dev, tpd, cid);
+		HE_SPIN_UNLOCK(he_dev, flags);
+
+		timeout = schedule_timeout(30*HZ);
+
+		remove_wait_queue(&he_vcc->tx_waitq, &wait);
+		set_current_state(TASK_RUNNING);
+
+		if (timeout == 0)
+		{
+			hprintk("close tx timeout cid 0x%x\n", cid);
+			goto close_tx_incomplete;
+		}
+
+		HE_SPIN_LOCK(he_dev, flags);
+		while (!((tsr4 = he_readl_tsr4(he_dev, cid))
+							& TSR4_SESSION_ENDED))
+		{
+			HPRINTK("close tx cid 0x%x !TSR4_SESSION_ENDED (tsr4 = 0x%x)\n", cid, tsr4);
+			udelay(250);
+		}
+
+		while (TSR0_CONN_STATE(tsr0 = he_readl_tsr0(he_dev, cid)) != 0)
+		{
+			HPRINTK("close tx cid 0x%x TSR0_CONN_STATE != 0 (tsr0 = 0x%x)\n", cid, tsr0);
+			udelay(250);
+		}
+
+close_tx_incomplete:
+
+		if (vcc->qos.txtp.traffic_class == ATM_CBR)
+		{
+			int reg = he_vcc->rc_index;
+
+			HPRINTK("cs_stper reg = %d\n", reg);
+
+			if (he_dev->cs_stper[reg].inuse == 0)
+				hprintk("cs_stper[%d].inuse = 0!\n", reg);
+			else
+				--he_dev->cs_stper[reg].inuse;
+
+			he_dev->total_bw -= he_dev->cs_stper[reg].pcr;
+		}
+		HE_SPIN_UNLOCK(he_dev, flags);
+
+		HPRINTK("close tx cid 0x%x complete\n", cid);
+	}
+
+	kfree(he_vcc);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
+	vcc->flags &= ~ATM_VF_ADDR;
+#else
+	clear_bit(ATM_VF_ADDR, &vcc->flags);
+#endif
+}
+
+static int
+he_sg_send(struct atm_vcc *vcc, unsigned long start, unsigned long size)
+{
+#ifdef USE_SCATTERGATHER
+	return 1;
+#else
+	return 0;
+#endif
+}
+
+static int
+he_send(struct atm_vcc *vcc, struct sk_buff *skb)
+{
+	unsigned long flags;
+	struct he_dev *he_dev = HE_DEV(vcc->dev);
+	unsigned cid = he_mkcid(he_dev, vcc->vpi, vcc->vci);
+	struct he_tpd *tpd;
+#ifdef USE_SCATTERGATHER
+	int i, slot = 0;
+#endif
+
+#define HE_TPD_BUFSIZE 0xffff
+
+	HPRINTK("send %d.%d\n", vcc->vpi, vcc->vci);
+
+	if ((skb->len > HE_TPD_BUFSIZE) ||
+		((vcc->qos.aal == ATM_AAL0) && (skb->len != ATM_AAL0_SDU)))
+	{
+		hprintk("buffer too large (or small) -- %d bytes\n", skb->len );
+		if (vcc->pop)
+			vcc->pop(vcc, skb);
+		else
+			dev_kfree_skb_any(skb);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+		++vcc->stats->tx_err;
+#else
+		atomic_inc(&vcc->stats->tx_err);
+#endif
+		return -EINVAL;
+	}
+
+#ifndef USE_SCATTERGATHER
+	if (skb_shinfo(skb)->nr_frags)
+	{
+		hprintk1("no scatter/gather support\n");
+		if (vcc->pop)
+			vcc->pop(vcc, skb);
+		else
+			dev_kfree_skb_any(skb);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+		++vcc->stats->tx_err;
+#else
+		atomic_inc(&vcc->stats->tx_err);
+#endif
+		return -EINVAL;
+	}
+#endif
+	HE_SPIN_LOCK(he_dev, flags);
+
+	tpd = __alloc_tpd(he_dev);
+	if (tpd == NULL)
+	{
+		if (vcc->pop)
+			vcc->pop(vcc, skb);
+		else
+			dev_kfree_skb_any(skb);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+		++vcc->stats->tx_err;
+#else
+		atomic_inc(&vcc->stats->tx_err);
+#endif
+		HE_SPIN_UNLOCK(he_dev, flags);
+		return -ENOMEM;
+	}
+
+	if (vcc->qos.aal == ATM_AAL5)
+		tpd->status |= TPD_CELLTYPE(TPD_USERCELL);
+	else
+	{
+		char *pti_clp = (void *) (skb->data + 3);
+		int clp, pti;
+
+		pti = (*pti_clp & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT; 
+		clp = (*pti_clp & ATM_HDR_CLP);
+		tpd->status |= TPD_CELLTYPE(pti);
+		if (clp) tpd->status |= TPD_CLP;
+
+		skb_pull(skb, ATM_AAL0_SDU - ATM_CELL_PAYLOAD);
+	}
+
+#ifdef USE_SCATTERGATHER
+	tpd->iovec[slot].addr = pci_map_single(he_dev->pci_dev, skb->data,
+				skb->len - skb->data_len, PCI_DMA_TODEVICE);
+	tpd->iovec[slot].len = skb->len - skb->data_len;
+	++slot;
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+	{
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+		if (slot == TPD_MAXIOV)		/* send tpd; start new tpd */
+		{
+			tpd->vcc = vcc;
+			tpd->skb = NULL;	/* not the last fragment
+						   so dont ->push() yet */
+			wmb();
+
+			__enqueue_tpd(he_dev, tpd, cid);
+			tpd = __alloc_tpd(he_dev);
+			if (tpd == NULL)
+			{
+				if (vcc->pop)
+					vcc->pop(vcc, skb);
+				else
+					dev_kfree_skb_any(skb);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+				++vcc->stats->tx_err;
+#else
+				atomic_inc(&vcc->stats->tx_err);
+				HE_SPIN_UNLOCK(he_dev, flags);
+#endif
+				return -ENOMEM;
+			}
+			tpd->status |= TPD_USERCELL;
+			slot = 0;
+		}
+
+		tpd->iovec[slot].addr = pci_map_single(he_dev->pci_dev,
+			(void *) page_address(frag->page) + frag->page_offset,
+				frag->size, PCI_DMA_TODEVICE);
+		tpd->iovec[slot].len = frag->size;
+		++slot;
+
+	}
+
+	tpd->iovec[slot-1].len |= TPD_LST;
+#else
+	tpd->address0 = pci_map_single(he_dev->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
+	tpd->length0 = skb->len | TPD_LST;
+#endif
+	tpd->status |= TPD_INT;
+
+	tpd->vcc = vcc;
+	tpd->skb = skb;
+	wmb();
+	ATM_SKB(skb)->vcc = vcc;
+
+	__enqueue_tpd(he_dev, tpd, cid);
+	HE_SPIN_UNLOCK(he_dev, flags);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+	++vcc->stats->tx;
+#else
+	atomic_inc(&vcc->stats->tx);
+#endif
+
+	return 0;
+}
+
+static int
+he_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void *arg)
+{
+	unsigned long flags;
+	struct he_dev *he_dev = HE_DEV(atm_dev);
+	struct he_ioctl_reg reg;
+	int err = 0;
+
+	switch (cmd)
+	{
+		case HE_GET_REG:
+			if (!capable(CAP_NET_ADMIN)) return -EPERM;
+
+			copy_from_user(&reg, (struct he_ioctl_reg *) arg,
+						sizeof(struct he_ioctl_reg));
+			HE_SPIN_LOCK(he_dev, flags);
+			switch (reg.type)
+			{
+				case HE_REGTYPE_PCI:
+					reg.val = he_readl(he_dev, reg.addr);
+					break;
+				case HE_REGTYPE_RCM:
+					reg.val =
+						he_readl_rcm(he_dev, reg.addr);
+					break;
+				case HE_REGTYPE_TCM:
+					reg.val =
+						he_readl_tcm(he_dev, reg.addr);
+					break;
+				case HE_REGTYPE_MBOX:
+					reg.val =
+						he_readl_mbox(he_dev, reg.addr);
+					break;
+				default:
+					err = -EINVAL;
+					break;
+			}
+			HE_SPIN_UNLOCK(he_dev, flags);
+			if (err == 0) copy_to_user((struct he_ioctl_reg *) arg, &reg,
+							sizeof(struct he_ioctl_reg));
+			break;
+		default:
+#ifdef CONFIG_ATM_HE_USE_SUNI
+			if (atm_dev->phy && atm_dev->phy->ioctl)
+				err = atm_dev->phy->ioctl(atm_dev, cmd, arg);
+#else /* CONFIG_ATM_HE_USE_SUNI */
+			return -EINVAL;
+#endif /* CONFIG_ATM_HE_USE_SUNI */
+			break;
+	}
+
+	return err;
+}
+
+static void
+he_phy_put(struct atm_dev *atm_dev, unsigned char val, unsigned long addr)
+{
+	unsigned long flags;
+	struct he_dev *he_dev = HE_DEV(atm_dev);
+
+	HPRINTK("phy_put(val 0x%x, addr 0x%lx)\n", val, addr);
+
+	HE_SPIN_LOCK(he_dev, flags);
+        he_writel(he_dev, val, FRAMER + (addr*4));
+#ifdef CONFIG_IA64_SGI_SN2
+	(void) he_readl(he_dev, FRAMER + (addr*4));
+#endif
+	HE_SPIN_UNLOCK(he_dev, flags);
+}
+ 
+        
+static unsigned char
+he_phy_get(struct atm_dev *atm_dev, unsigned long addr)
+{ 
+	unsigned long flags;
+	struct he_dev *he_dev = HE_DEV(atm_dev);
+	unsigned reg;
+
+	HE_SPIN_LOCK(he_dev, flags);
+        reg = he_readl(he_dev, FRAMER + (addr*4));
+	HE_SPIN_UNLOCK(he_dev, flags);
+
+	HPRINTK("phy_get(addr 0x%lx) =0x%x\n", addr, reg);
+	return reg;
+}
+
+static int
+he_proc_read(struct atm_dev *dev, loff_t *pos, char *page)
+{
+	unsigned long flags;
+	struct he_dev *he_dev = HE_DEV(dev);
+	int left, i;
+#ifdef notdef
+	struct he_rbrq *rbrq_tail;
+	struct he_tpdrq *tpdrq_head;
+        int rbpl_head, rbpl_tail;
+#endif
+	static long mcc = 0, oec = 0, dcc = 0, cec = 0;
+
+
+	left = *pos;
+	if (!left--)
+		return sprintf(page, "%s\n", version);
+
+	if (!left--)
+		return sprintf(page, "%s%s\n\n",
+			he_dev->prod_id, he_dev->media & 0x40 ? "SM" : "MM");
+
+	if (!left--)
+		return sprintf(page, "Mismatched Cells  VPI/VCI Not Open  Dropped Cells  RCM Dropped Cells\n");
+
+	HE_SPIN_LOCK(he_dev, flags);
+	mcc += he_readl(he_dev, MCC);
+	oec += he_readl(he_dev, OEC);
+	dcc += he_readl(he_dev, DCC);
+	cec += he_readl(he_dev, CEC);
+	HE_SPIN_UNLOCK(he_dev, flags);
+
+	if (!left--)
+		return sprintf(page, "%16ld  %16ld  %13ld  %17ld\n\n", 
+							mcc, oec, dcc, cec);
+
+	if (!left--)
+		return sprintf(page, "irq_size = %d  inuse = ?  peak = %d\n",
+				CONFIG_IRQ_SIZE, he_dev->irq_peak);
+
+	if (!left--)
+		return sprintf(page, "tpdrq_size = %d  inuse = ?\n",
+						CONFIG_TPDRQ_SIZE);
+
+	if (!left--)
+		return sprintf(page, "rbrq_size = %d  inuse = ?  peak = %d\n",
+				CONFIG_RBRQ_SIZE, he_dev->rbrq_peak);
+
+	if (!left--)
+		return sprintf(page, "tbrq_size = %d  peak = %d\n",
+					CONFIG_TBRQ_SIZE, he_dev->tbrq_peak);
+
+
+#ifdef notdef
+        rbpl_head = RBPL_MASK(he_readl(he_dev, G0_RBPL_S));
+        rbpl_tail = RBPL_MASK(he_readl(he_dev, G0_RBPL_T));
+
+	inuse = rbpl_head - rbpl_tail;
+	if (inuse < 0) inuse += CONFIG_RBPL_SIZE * sizeof(struct he_rbp);
+	inuse /= sizeof(struct he_rbp);
+
+	if (!left--)
+		return sprintf(page, "rbpl_size = %d  inuse = %d\n\n",
+						CONFIG_RBPL_SIZE, inuse);
+#endif
+
+	if (!left--)
+		return sprintf(page, "rate controller periods (cbr)\n                 pcr  #vc\n");
+
+	for (i = 0; i < HE_NUM_CS_STPER; ++i)
+		if (!left--)
+			return sprintf(page, "cs_stper%-2d  %8ld  %3d\n", i,
+						he_dev->cs_stper[i].pcr,
+						he_dev->cs_stper[i].inuse);
+
+	if (!left--)
+		return sprintf(page, "total bw (cbr): %d  (limit %d)\n",
+			he_dev->total_bw, he_dev->atm_dev->link_rate * 10 / 9);
+
+	return 0;
+}
+
+/* eeprom routines  -- see 4.7 */
+
+u8
+read_prom_byte(struct he_dev *he_dev, int addr)
+{
+	u32 val = 0, tmp_read = 0;
+	int i, j = 0;
+	u8 byte_read = 0;
+
+	val = readl(he_dev->membase + HOST_CNTL);
+	val &= 0xFFFFE0FF;
+       
+	/* Turn on write enable */
+	val |= 0x800;
+	he_writel(he_dev, val, HOST_CNTL);
+       
+	/* Send READ instruction */
+	for (i=0; i<sizeof(readtab)/sizeof(readtab[0]); i++) {
+		he_writel(he_dev, val | readtab[i], HOST_CNTL);
+		udelay(EEPROM_DELAY);
+	}
+       
+        /* Next, we need to send the byte address to read from */
+	for (i=7; i>=0; i--) {
+		he_writel(he_dev, val | clocktab[j++] | (((addr >> i) & 1) << 9), HOST_CNTL);
+		udelay(EEPROM_DELAY);
+		he_writel(he_dev, val | clocktab[j++] | (((addr >> i) & 1) << 9), HOST_CNTL);
+		udelay(EEPROM_DELAY);
+	}
+       
+	j=0;
+
+	val &= 0xFFFFF7FF;      /* Turn off write enable */
+	he_writel(he_dev, val, HOST_CNTL);
+       
+	/* Now, we can read data from the EEPROM by clocking it in */
+	for (i=7; i>=0; i--) {
+		he_writel(he_dev, val | clocktab[j++], HOST_CNTL);
+	        udelay(EEPROM_DELAY);
+	        tmp_read = he_readl(he_dev, HOST_CNTL);
+	        byte_read |= (unsigned char)
+	                        ((tmp_read & ID_DOUT)
+	                         >> ID_DOFFSET << i);
+		he_writel(he_dev, val | clocktab[j++], HOST_CNTL);
+		udelay(EEPROM_DELAY);
+	}
+       
+	he_writel(he_dev, val | ID_CS, HOST_CNTL);
+	udelay(EEPROM_DELAY);
+
+        return (byte_read);
+}
+
+MODULE_AUTHOR("chas williams <chas@cmf.nrl.navy.mil>");
+MODULE_DESCRIPTION("ForeRunnerHE ATM Adapter driver");
+MODULE_PARM(disable64, "h");
+MODULE_PARM_DESC(disable64, "disable 64-bit pci bus transfers");
+MODULE_PARM(nvpibits, "i");
+MODULE_PARM_DESC(nvpibits, "numbers of bits for vpi (default 0)");
+MODULE_PARM(nvcibits, "i");
+MODULE_PARM_DESC(nvcibits, "numbers of bits for vci (default 12)");
+MODULE_PARM(rx_skb_reserve, "i");
+MODULE_PARM_DESC(rx_skb_reserve, "padding for receive skb (default 16)");
+MODULE_PARM(irq_coalesce, "i");
+MODULE_PARM_DESC(irq_coalesce, "use interrupt coalescing (default 1)");
+MODULE_PARM(sdh, "i");
+MODULE_PARM_DESC(sdh, "use SDH framing (default 0)");
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,1)
+static struct pci_device_id he_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_HE, PCI_ANY_ID, PCI_ANY_ID,
+	  0, 0, 0 },
+        { 0, }
+};
+
+static struct pci_driver he_driver = {
+	.name =		"he",
+	.probe =	he_init_one,
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,9)
+	.remove =	__devexit_p(he_remove_one),
+#else
+	.remove =	he_remove_one,
+#endif
+	.id_table =	he_pci_tbl,
+};
+
+static int __init he_init(void)
+{
+        return pci_module_init(&he_driver);
+}
+
+static void __exit he_cleanup(void)
+{
+        pci_unregister_driver(&he_driver);
+}
+
+module_init(he_init);
+module_exit(he_cleanup);
+#else
+static int __init
+he_init()
+{
+	if (!pci_present())
+		return -EIO;
+
+#ifdef CONFIG_ATM_HE_USE_SUNI_MODULE
+	/* request_module("suni"); */
+#endif
+
+	pci_dev = NULL;
+	while ((pci_dev = pci_find_device(PCI_VENDOR_ID_FORE,
+					PCI_DEVICE_ID_FORE_HE, pci_dev)) != NULL)
+		if (he_init_one(pci_dev, NULL) == 0)
+			++ndevs;
+
+	return (ndevs ? 0 : -ENODEV);
+}
+
+static void __devexit
+he_cleanup(void)
+{
+	while (he_devs)
+	{
+		struct he_dev *next = he_devs->next;
+		he_stop(he_devs);
+		atm_dev_deregister(he_devs->atm_dev);
+		kfree(he_devs);
+
+		he_devs = next;
+	}
+
+}
+
+int init_module(void)
+{
+	return he_init();
+}
+
+void cleanup_module(void)
+{
+	he_cleanup();
+}
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,7)
+MODULE_LICENSE("GPL");
+#endif
diff -urN linux-2.5.69-bk2/drivers/atm/he.h linux-2.5.69-bk3/drivers/atm/he.h
--- linux-2.5.69-bk2/drivers/atm/he.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/drivers/atm/he.h	2003-05-08 04:38:16.000000000 -0700
@@ -0,0 +1,935 @@
+/* $Id: he.h,v 1.4 2003/05/06 22:48:00 chas Exp $ */
+
+/*
+
+  he.h
+
+  ForeRunnerHE ATM Adapter driver for ATM on Linux
+  Copyright (C) 1999-2001  Naval Research Laboratory
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/*
+
+  he.h
+
+  ForeRunnerHE ATM Adapter driver for ATM on Linux
+  Copyright (C) 1999-2000  Naval Research Laboratory
+
+  Permission to use, copy, modify and distribute this software and its
+  documentation is hereby granted, provided that both the copyright
+  notice and this permission notice appear in all copies of the software,
+  derivative works or modified versions, and any portions thereof, and
+  that both notices appear in supporting documentation.
+
+  NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
+  DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
+  RESULTING FROM THE USE OF THIS SOFTWARE.
+
+ */
+
+#ifndef _HE_H_
+#define _HE_H_
+
+#define DEV_LABEL       "he"
+
+#define CONFIG_DEFAULT_VCIBITS	12
+#define CONFIG_DEFAULT_VPIBITS	0
+
+#define CONFIG_IRQ_SIZE		128
+#define CONFIG_IRQ_THRESH	(CONFIG_IRQ_SIZE/2)
+
+#define CONFIG_NUMTPDS		256
+
+#define CONFIG_TPDRQ_SIZE	512
+#define TPDRQ_MASK(x)		(((unsigned long)(x))&((CONFIG_TPDRQ_SIZE<<3)-1))
+
+#define CONFIG_RBRQ_SIZE	512
+#define CONFIG_RBRQ_THRESH	400
+#define RBRQ_MASK(x)		(((unsigned long)(x))&((CONFIG_RBRQ_SIZE<<3)-1))
+
+#define CONFIG_TBRQ_SIZE	512
+#define CONFIG_TBRQ_THRESH	400
+#define TBRQ_MASK(x)		(((unsigned long)(x))&((CONFIG_TBRQ_SIZE<<2)-1))
+
+#define CONFIG_RBPL_SIZE	512
+#define CONFIG_RBPL_THRESH	64
+#define CONFIG_RBPL_BUFSIZE	4096
+#define RBPL_MASK(x)		(((unsigned long)(x))&((CONFIG_RBPL_SIZE<<3)-1))
+
+#define CONFIG_RBPS_SIZE	1024
+#define CONFIG_RBPS_THRESH	64
+#define CONFIG_RBPS_BUFSIZE	128
+#define RBPS_MASK(x)		(((unsigned long)(x))&((CONFIG_RBPS_SIZE<<3)-1))
+
+/* 5.1.3 initialize connection memory */
+
+#define CONFIG_RSRA		0x00000
+#define CONFIG_RCMLBM		0x08000
+#define CONFIG_RCMABR		0x0d800
+#define CONFIG_RSRB		0x0e000
+
+#define CONFIG_TSRA		0x00000
+#define CONFIG_TSRB		0x08000
+#define CONFIG_TSRC		0x0c000
+#define CONFIG_TSRD		0x0e000
+#define CONFIG_TMABR		0x0f000
+#define CONFIG_TPDBA		0x10000
+
+#define HE_MAXCIDBITS		12
+
+/* 2.9.3.3 interrupt encodings */
+
+struct he_irq {
+	volatile u32 isw;
+};
+
+#define IRQ_ALIGNMENT		0x1000
+
+#define NEXT_ENTRY(base, tail, mask) \
+				(((unsigned long)base)|(((unsigned long)(tail+1))&mask))
+
+#define ITYPE_INVALID		0xffffffff
+#define ITYPE_TBRQ_THRESH	(0<<3)
+#define ITYPE_TPD_COMPLETE	(1<<3)
+#define ITYPE_RBPS_THRESH	(2<<3)
+#define ITYPE_RBPL_THRESH	(3<<3)
+#define ITYPE_RBRQ_THRESH	(4<<3)
+#define ITYPE_RBRQ_TIMER	(5<<3)
+#define ITYPE_PHY		(6<<3)
+#define ITYPE_OTHER		0x80
+#define ITYPE_PARITY		0x81
+#define ITYPE_ABORT		0x82
+
+#define ITYPE_GROUP(x)		(x & 0x7)
+#define ITYPE_TYPE(x)		(x & 0xf8)
+
+#define HE_NUM_GROUPS 8
+
+/* 2.1.4 transmit packet descriptor */
+
+struct he_tpd {
+
+	/* read by the adapter */
+
+	volatile u32 status;
+	volatile u32 reserved;
+
+#define TPD_MAXIOV	3
+	struct {
+		u32 addr, len;
+	} iovec[TPD_MAXIOV];
+
+#define address0 iovec[0].addr
+#define length0 iovec[0].len
+
+	/* linux-atm extensions */
+
+	struct sk_buff *skb;
+	struct atm_vcc *vcc;
+
+#ifdef USE_TPD_POOL
+	struct list_head entry;
+#else
+	u32 inuse;
+	char padding[32 - sizeof(u32) - (2*sizeof(void*))];
+#endif
+};
+
+#define TPD_ALIGNMENT	64
+#define TPD_LEN_MASK	0xffff
+
+#define TPD_ADDR_SHIFT  6
+#define TPD_MASK	0xffffffc0
+#define TPD_ADDR(x)	((x) & TPD_MASK)
+#define TPD_INDEX(x)	(TPD_ADDR(x) >> TPD_ADDR_SHIFT)
+
+
+/* table 2.3 transmit buffer return elements */
+
+struct he_tbrq {
+	volatile u32 tbre;
+};
+
+#define TBRQ_ALIGNMENT	CONFIG_TBRQ_SIZE
+
+#define TBRQ_TPD(tbrq)		((tbrq)->tbre & 0xffffffc0)
+#define TBRQ_EOS(tbrq)		((tbrq)->tbre & (1<<3))
+#define TBRQ_MULTIPLE(tbrq)	((tbrq)->tbre & (1))
+
+/* table 2.21 receive buffer return queue element field organization */
+
+struct he_rbrq {
+	volatile u32 addr;
+	volatile u32 cidlen;
+};
+
+#define RBRQ_ALIGNMENT	CONFIG_RBRQ_SIZE
+
+#define RBRQ_ADDR(rbrq)		((rbrq)->addr & 0xffffffc0)
+#define RBRQ_CRC_ERR(rbrq)	((rbrq)->addr & (1<<5))
+#define RBRQ_LEN_ERR(rbrq)	((rbrq)->addr & (1<<4))
+#define RBRQ_END_PDU(rbrq)	((rbrq)->addr & (1<<3))
+#define RBRQ_AAL5_PROT(rbrq)	((rbrq)->addr & (1<<2))
+#define RBRQ_CON_CLOSED(rbrq)	((rbrq)->addr & (1<<1))
+#define RBRQ_HBUF_ERR(rbrq)	((rbrq)->addr & 1)
+#define RBRQ_CID(rbrq)		(((rbrq)->cidlen >> 16) & 0x1fff)
+#define RBRQ_BUFLEN(rbrq)	((rbrq)->cidlen & 0xffff)
+
+/* figure 2.3 transmit packet descriptor ready queue */
+
+struct he_tpdrq {
+	volatile u32 tpd;
+	volatile u32 cid;
+};
+
+#define TPDRQ_ALIGNMENT CONFIG_TPDRQ_SIZE
+
+/* table 2.30 host status page detail */
+
+#define HSP_ALIGNMENT	0x400		/* must align on 1k boundary */
+
+struct he_hsp {
+	struct he_hsp_entry {
+		volatile u32 tbrq_tail; 
+		volatile u32 reserved1[15];
+		volatile u32 rbrq_tail; 
+		volatile u32 reserved2[15];
+	} group[HE_NUM_GROUPS];
+};
+
+/* figure 2.9 receive buffer pools */
+
+struct he_rbp {
+	volatile u32 phys;
+	volatile u32 status;
+};
+
+/* NOTE: it is suggested that virt be the virtual address of the host
+   buffer.  on a 64-bit machine, this would not work.  Instead, we
+   store the real virtual address in another list, and store an index
+   (and buffer status) in the virt member.
+*/
+
+#define RBP_INDEX_OFF	6
+#define RBP_INDEX(x)	(((long)(x) >> RBP_INDEX_OFF) & 0xffff)
+#define RBP_LOANED	0x80000000
+#define RBP_SMALLBUF	0x40000000
+
+struct he_virt {
+	void *virt;
+};
+
+#define RBPL_ALIGNMENT CONFIG_RBPL_SIZE
+#define RBPS_ALIGNMENT CONFIG_RBPS_SIZE
+
+#ifdef notyet
+struct he_group {
+	u32 rpbs_size, rpbs_qsize;
+	struct he_rbp rbps_ba;
+
+	u32 rpbl_size, rpbl_qsize;
+	struct he_rpb_entry *rbpl_ba;
+};
+#endif
+
+#define HE_LOOKUP_VCC(dev, cid) ((dev)->he_vcc_table[(cid)].vcc)
+
+struct he_vcc_table 
+{
+	struct atm_vcc *vcc;
+};
+
+struct he_cs_stper
+{
+	long pcr;
+	int inuse;
+};
+
+#define HE_NUM_CS_STPER		16
+
+struct he_dev {
+	unsigned int number;
+	unsigned int irq;
+	unsigned long membase;
+
+	char prod_id[30];
+	char mac_addr[6];
+	int media;			/*  
+					 *  0x26 = HE155 MM 
+					 *  0x27 = HE622 MM 
+					 *  0x46 = HE155 SM 
+					 *  0x47 = HE622 SM 
+					 */
+
+
+	unsigned int vcibits, vpibits;
+	unsigned int cells_per_row;
+	unsigned int bytes_per_row;
+	unsigned int cells_per_lbuf;
+	unsigned int r0_numrows, r0_startrow, r0_numbuffs;
+	unsigned int r1_numrows, r1_startrow, r1_numbuffs;
+	unsigned int tx_numrows, tx_startrow, tx_numbuffs;
+	unsigned int buffer_limit;
+
+	struct he_vcc_table *he_vcc_table;
+
+#ifdef notyet
+	struct he_group group[HE_NUM_GROUPS];
+#endif
+	struct he_cs_stper cs_stper[HE_NUM_CS_STPER];
+	unsigned total_bw;
+
+	dma_addr_t irq_phys;
+	struct he_irq *irq_base, *irq_head, *irq_tail;
+	volatile unsigned *irq_tailoffset;
+	int irq_peak;
+
+#ifdef USE_TASKLET
+	struct tasklet_struct tasklet;
+#endif
+#ifdef USE_TPD_POOL
+	struct pci_pool *tpd_pool;
+	struct list_head outstanding_tpds;
+#else
+	struct he_tpd *tpd_head, *tpd_base, *tpd_end;
+	dma_addr_t tpd_base_phys;
+#endif
+
+	dma_addr_t tpdrq_phys;
+	struct he_tpdrq *tpdrq_base, *tpdrq_tail, *tpdrq_head;
+
+	spinlock_t global_lock;		/* 8.1.5 pci transaction ordering
+					  error problem */
+	dma_addr_t rbrq_phys;
+	struct he_rbrq *rbrq_base, *rbrq_head;
+	int rbrq_peak;
+
+#ifdef USE_RBPL_POOL
+	struct pci_pool *rbpl_pool;
+#else
+	void *rbpl_pages;
+	dma_addr_t rbpl_pages_phys;
+#endif
+	dma_addr_t rbpl_phys;
+	struct he_rbp *rbpl_base, *rbpl_tail;
+	struct he_virt *rbpl_virt;
+	int rbpl_peak;
+
+#ifdef USE_RBPS
+#ifdef USE_RBPS_POOL
+	struct pci_pool *rbps_pool;
+#else
+	void *rbps_pages;
+	dma_addr_t rbps_pages_phys;
+#endif
+#endif
+	dma_addr_t rbps_phys;
+	struct he_rbp *rbps_base, *rbps_tail;
+	struct he_virt *rbps_virt;
+	int rbps_peak;
+
+	dma_addr_t tbrq_phys;
+	struct he_tbrq *tbrq_base, *tbrq_head;
+	int tbrq_peak;
+
+	dma_addr_t hsp_phys;
+	struct he_hsp *hsp;
+
+	struct pci_dev *pci_dev;
+	struct atm_dev *atm_dev;
+	struct he_dev *next;
+};
+
+struct he_vcc
+{
+	struct iovec iov_head[32];
+	struct iovec *iov_tail;
+	int pdu_len;
+
+	int rc_index;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
+	struct wait_queue *rx_waitq;
+	atruct wait_queue *tx_waitq;
+#else
+	wait_queue_head_t rx_waitq;
+	wait_queue_head_t tx_waitq;
+#endif
+};
+
+#define HE_VCC(vcc)	((struct he_vcc *)(vcc->dev_data))
+
+#define PCI_VENDOR_ID_FORE	0x1127
+#define PCI_DEVICE_ID_FORE_HE	0x400
+
+#define HE_DMA_MASK		0xffffffff
+
+#define GEN_CNTL_0				0x40
+#define  INT_PROC_ENBL		(1<<25)
+#define  SLAVE_ENDIAN_MODE	(1<<16)
+#define  MRL_ENB		(1<<5)
+#define  MRM_ENB		(1<<4)
+#define  INIT_ENB		(1<<2)
+#define  IGNORE_TIMEOUT		(1<<1)
+#define  ENBL_64		(1<<0)
+
+#define MIN_PCI_LATENCY		32	/* errata 8.1.3 */
+
+#define HE_DEV(dev) ((struct he_dev *) (dev)->dev_data)
+
+#define he_is622(dev)	((dev)->media & 0x1)
+
+#define HE_REGMAP_SIZE	0x100000
+
+#define RESET_CNTL	0x80000
+#define  BOARD_RST_STATUS	(1<<6)
+
+#define HOST_CNTL	0x80004
+#define  PCI_BUS_SIZE64			(1<<27)
+#define  DESC_RD_STATIC_64		(1<<26)
+#define  DATA_RD_STATIC_64		(1<<25)
+#define  DATA_WR_STATIC_64		(1<<24)
+#define  ID_CS				(1<<12)
+#define  ID_WREN			(1<<11)
+#define  ID_DOUT			(1<<10)
+#define   ID_DOFFSET			10
+#define  ID_DIN				(1<<9)
+#define  ID_CLOCK			(1<<8)
+#define  QUICK_RD_RETRY			(1<<7)
+#define  QUICK_WR_RETRY			(1<<6)
+#define  OUTFF_ENB			(1<<5)
+#define  CMDFF_ENB			(1<<4)
+#define  PERR_INT_ENB			(1<<2)
+#define  IGNORE_INTR			(1<<0)
+
+#define LB_SWAP		0x80008
+#define  SWAP_RNUM_MAX(x)	(x<<27)
+#define  DATA_WR_SWAP		(1<<20)
+#define  DESC_RD_SWAP		(1<<19)
+#define  DATA_RD_SWAP		(1<<18)
+#define  INTR_SWAP		(1<<17)
+#define  DESC_WR_SWAP		(1<<16)
+#define  SDRAM_INIT		(1<<15)
+#define  BIG_ENDIAN_HOST	(1<<14)
+#define  XFER_SIZE		(1<<7)
+
+#define LB_MEM_ADDR	0x8000c
+#define LB_MEM_DATA	0x80010
+
+#define LB_MEM_ACCESS	0x80014
+#define  LB_MEM_HNDSHK		(1<<30)
+#define  LM_MEM_WRITE		(0x7)
+#define  LM_MEM_READ		(0x3)
+
+#define SDRAM_CTL	0x80018
+#define  LB_64_ENB		(1<<3)
+#define  LB_TWR			(1<<2)
+#define  LB_TRP			(1<<1)
+#define  LB_TRAS		(1<<0)
+
+#define INT_FIFO	0x8001c
+#define  INT_MASK_D		(1<<15)
+#define  INT_MASK_C		(1<<14)
+#define  INT_MASK_B		(1<<13)
+#define  INT_MASK_A		(1<<12)
+#define  INT_CLEAR_D		(1<<11)
+#define  INT_CLEAR_C		(1<<10)
+#define  INT_CLEAR_B		(1<<9)
+#define  INT_CLEAR_A		(1<<8)
+
+#define ABORT_ADDR	0x80020
+
+#define IRQ0_BASE	0x80080
+#define  IRQ_BASE(x)		(x<<12)
+#define  IRQ_MASK		((CONFIG_IRQ_SIZE<<2)-1)	/* was 0x3ff */
+#define  IRQ_TAIL(x)		(((unsigned long)(x)) & IRQ_MASK)
+#define IRQ0_HEAD	0x80084
+#define  IRQ_SIZE(x)		(x<<22)
+#define  IRQ_THRESH(x)		(x<<12)
+#define  IRQ_HEAD(x)		(x<<2)
+/* #define  IRQ_PENDING		(1) 		conflict with linux/irq.h */
+#define IRQ0_CNTL	0x80088
+#define  IRQ_ADDRSEL(x)		(x<<2)
+#define  IRQ_INT_A		(0<<2)
+#define  IRQ_INT_B		(1<<2)
+#define  IRQ_INT_C		(2<<2)
+#define  IRQ_INT_D		(3<<2)
+#define  IRQ_TYPE_ADDR		0x1
+#define  IRQ_TYPE_LINE		0x0
+#define IRQ0_DATA	0x8008c
+
+#define IRQ1_BASE	0x80090
+#define IRQ1_HEAD	0x80094
+#define IRQ1_CNTL	0x80098
+#define IRQ1_DATA	0x8009c
+
+#define IRQ2_BASE	0x800a0
+#define IRQ2_HEAD	0x800a4
+#define IRQ2_CNTL	0x800a8
+#define IRQ2_DATA	0x800ac
+
+#define IRQ3_BASE	0x800b0
+#define IRQ3_HEAD	0x800b4
+#define IRQ3_CNTL	0x800b8
+#define IRQ3_DATA	0x800bc
+
+#define GRP_10_MAP	0x800c0
+#define GRP_32_MAP	0x800c4
+#define GRP_54_MAP	0x800c8
+#define GRP_76_MAP	0x800cc
+
+#define	G0_RBPS_S	0x80400
+#define G0_RBPS_T	0x80404
+#define  RBP_TAIL(x)		((x)<<3)
+#define  RBP_MASK(x)		((x)|0x1fff)
+#define G0_RBPS_QI	0x80408
+#define  RBP_QSIZE(x)		((x)<<14)
+#define  RBP_INT_ENB		(1<<13)
+#define  RBP_THRESH(x)		(x)
+#define G0_RBPS_BS	0x8040c
+#define G0_RBPL_S	0x80410
+#define G0_RBPL_T	0x80414
+#define G0_RBPL_QI	0x80418 
+#define G0_RBPL_BS	0x8041c
+
+#define	G1_RBPS_S	0x80420
+#define G1_RBPS_T	0x80424
+#define G1_RBPS_QI	0x80428
+#define G1_RBPS_BS	0x8042c
+#define G1_RBPL_S	0x80430
+#define G1_RBPL_T	0x80434
+#define G1_RBPL_QI	0x80438
+#define G1_RBPL_BS	0x8043c
+
+#define	G2_RBPS_S	0x80440
+#define G2_RBPS_T	0x80444
+#define G2_RBPS_QI	0x80448
+#define G2_RBPS_BS	0x8044c
+#define G2_RBPL_S	0x80450
+#define G2_RBPL_T	0x80454
+#define G2_RBPL_QI	0x80458
+#define G2_RBPL_BS	0x8045c
+
+#define	G3_RBPS_S	0x80460
+#define G3_RBPS_T	0x80464
+#define G3_RBPS_QI	0x80468
+#define G3_RBPS_BS	0x8046c
+#define G3_RBPL_S	0x80470
+#define G3_RBPL_T	0x80474
+#define G3_RBPL_QI	0x80478
+#define G3_RBPL_BS	0x8047c
+
+#define	G4_RBPS_S	0x80480
+#define G4_RBPS_T	0x80484
+#define G4_RBPS_QI	0x80488
+#define G4_RBPS_BS	0x8048c
+#define G4_RBPL_S	0x80490
+#define G4_RBPL_T	0x80494
+#define G4_RBPL_QI	0x80498
+#define G4_RBPL_BS	0x8049c
+
+#define	G5_RBPS_S	0x804a0
+#define G5_RBPS_T	0x804a4
+#define G5_RBPS_QI	0x804a8
+#define G5_RBPS_BS	0x804ac
+#define G5_RBPL_S	0x804b0
+#define G5_RBPL_T	0x804b4
+#define G5_RBPL_QI	0x804b8
+#define G5_RBPL_BS	0x804bc
+
+#define	G6_RBPS_S	0x804c0
+#define G6_RBPS_T	0x804c4
+#define G6_RBPS_QI	0x804c8
+#define G6_RBPS_BS	0x804cc
+#define G6_RBPL_S	0x804d0
+#define G6_RBPL_T	0x804d4
+#define G6_RBPL_QI	0x804d8
+#define G6_RBPL_BS	0x804dc
+
+#define	G7_RBPS_S	0x804e0
+#define G7_RBPS_T	0x804e4
+#define G7_RBPS_QI	0x804e8
+#define G7_RBPS_BS	0x804ec
+
+#define G7_RBPL_S	0x804f0
+#define G7_RBPL_T	0x804f4
+#define G7_RBPL_QI	0x804f8
+#define G7_RBPL_BS	0x804fc
+
+#define G0_RBRQ_ST	0x80500
+#define G0_RBRQ_H	0x80504
+#define G0_RBRQ_Q	0x80508
+#define  RBRQ_THRESH(x)		((x)<<13)
+#define  RBRQ_SIZE(x)		(x)
+#define G0_RBRQ_I	0x8050c
+#define  RBRQ_TIME(x)		((x)<<8)
+#define  RBRQ_COUNT(x)		(x)
+
+/* fill in 1 ... 7 later */
+
+#define G0_TBRQ_B_T	0x80600
+#define G0_TBRQ_H	0x80604
+#define G0_TBRQ_S	0x80608
+#define G0_TBRQ_THRESH	0x8060c
+#define  TBRQ_THRESH(x)		(x)
+
+/* fill in 1 ... 7 later */
+
+#define RH_CONFIG	0x805c0
+#define  PHY_INT_ENB	(1<<10)
+#define  OAM_GID(x)	(x<<7)
+#define  PTMR_PRE(x)	(x)
+
+#define G0_INMQ_S	0x80580
+#define G0_INMQ_L	0x80584
+#define G1_INMQ_S	0x80588
+#define G1_INMQ_L	0x8058c
+#define G2_INMQ_S	0x80590
+#define G2_INMQ_L	0x80594
+#define G3_INMQ_S	0x80598
+#define G3_INMQ_L	0x8059c
+#define G4_INMQ_S	0x805a0
+#define G4_INMQ_L	0x805a4
+#define G5_INMQ_S	0x805a8
+#define G5_INMQ_L	0x805ac
+#define G6_INMQ_S	0x805b0
+#define G6_INMQ_L	0x805b4
+#define G7_INMQ_S	0x805b8
+#define G7_INMQ_L	0x805bc
+
+#define TPDRQ_B_H	0x80680
+#define TPDRQ_T		0x80684
+#define TPDRQ_S		0x80688
+
+#define UBUFF_BA	0x8068c
+
+#define RLBF0_H		0x806c0
+#define RLBF0_T		0x806c4
+#define RLBF1_H		0x806c8
+#define RLBF1_T		0x806cc
+#define RLBC_H		0x806d0
+#define RLBC_T		0x806d4
+#define RLBC_H2		0x806d8
+#define TLBF_H		0x806e0
+#define TLBF_T		0x806e4
+#define RLBF0_C		0x806e8
+#define RLBF1_C		0x806ec
+#define RXTHRSH		0x806f0
+#define LITHRSH		0x806f4
+
+#define LBARB		0x80700
+#define  SLICE_X(x)		 (x<<28)
+#define  ARB_RNUM_MAX(x)	 (x<<23)
+#define  TH_PRTY(x)		 (x<<21)
+#define  RH_PRTY(x)		 (x<<19)
+#define  TL_PRTY(x)		 (x<<17)
+#define  RL_PRTY(x)		 (x<<15)
+#define  BUS_MULTI(x)		 (x<<8)
+#define  NET_PREF(x)		 (x)
+
+#define SDRAMCON	0x80704
+#define	 BANK_ON		(1<<14)
+#define	 WIDE_DATA		(1<<13)
+#define	 TWR_WAIT		(1<<12)
+#define	 TRP_WAIT		(1<<11)
+#define	 TRAS_WAIT		(1<<10)
+#define	 REF_RATE(x)		(x)
+
+#define LBSTAT		0x80708
+
+#define RCC_STAT	0x8070c
+#define  RCC_BUSY		(1)
+
+#define TCMCONFIG	0x80740
+#define  TM_DESL2		(1<<10)
+#define	 TM_BANK_WAIT(x)	(x<<6)
+#define	 TM_ADD_BANK4(x)	(x<<4)
+#define  TM_PAR_CHECK(x)	(x<<3)
+#define  TM_RW_WAIT(x)		(x<<2)
+#define  TM_SRAM_TYPE(x)	(x)
+
+#define TSRB_BA		0x80744	
+#define TSRC_BA		0x80748	
+#define TMABR_BA	0x8074c	
+#define TPD_BA		0x80750	
+#define TSRD_BA		0x80758	
+
+#define TX_CONFIG	0x80760
+#define  DRF_THRESH(x)		(x<<22)
+#define  TX_UT_MODE(x)		(x<<21)
+#define  TX_VCI_MASK(x)		(x<<17)
+#define  LBFREE_CNT(x)		(x)
+
+#define TXAAL5_PROTO	0x80764
+#define  CPCS_UU(x)		(x<<8)
+#define  CPI(x)			(x)
+
+#define RCMCONFIG	0x80780
+#define  RM_DESL2(x)		(x<<10)
+#define  RM_BANK_WAIT(x)	(x<<6)
+#define  RM_ADD_BANK(x)		(x<<4)
+#define  RM_PAR_CHECK(x)	(x<<3)
+#define  RM_RW_WAIT(x)		(x<<2)
+#define  RM_SRAM_TYPE(x)	(x)
+
+#define RCMRSRB_BA	0x80784
+#define RCMLBM_BA	0x80788
+#define RCMABR_BA	0x8078c
+
+#define RC_CONFIG	0x807c0
+#define  UT_RD_DELAY(x)		(x<<11)
+#define  WRAP_MODE(x)		(x<<10)
+#define  RC_UT_MODE(x)		(x<<9)
+#define  RX_ENABLE		(1<<8)
+#define  RX_VALVP(x)		(x<<4)
+#define  RX_VALVC(x)		(x)
+
+#define MCC		0x807c4
+#define OEC		0x807c8
+#define DCC		0x807cc
+#define CEC		0x807d0
+
+#define HSP_BA		0x807f0
+
+#define LB_CONFIG	0x807f4
+#define  LB_SIZE(x)		(x)
+
+#define CON_DAT		0x807f8
+#define CON_CTL		0x807fc
+#define  CON_CTL_MBOX		(2<<30)
+#define  CON_CTL_TCM		(1<<30)
+#define  CON_CTL_RCM		(0<<30)
+#define  CON_CTL_WRITE		(1<<29)
+#define  CON_CTL_READ		(0<<29)
+#define  CON_CTL_BUSY		(1<<28)
+#define  CON_BYTE_DISABLE_3	(1<<22)		/* 24..31 */
+#define  CON_BYTE_DISABLE_2	(1<<21)		/* 16..23 */
+#define  CON_BYTE_DISABLE_1	(1<<20)		/* 8..15 */
+#define  CON_BYTE_DISABLE_0	(1<<19)		/* 0..7 */
+#define  CON_CTL_ADDR(x)	(x)
+
+#define FRAMER		0x80800		/* to 0x80bfc */
+
+/* 3.3 network controller (internal) mailbox registers */
+
+#define CS_STPER0	0x0
+	/* ... */
+#define CS_STPER31	0x01f
+
+#define CS_STTIM0	0x020
+	/* ... */
+#define CS_STTIM31	0x03f
+
+#define CS_TGRLD0	0x040
+	/* ... */
+#define CS_TGRLD15	0x04f
+
+#define CS_ERTHR0	0x050
+#define CS_ERTHR1	0x051
+#define CS_ERTHR2	0x052
+#define CS_ERTHR3	0x053
+#define CS_ERTHR4	0x054
+#define CS_ERCTL0	0x055
+#define  TX_ENABLE		(1<<28)
+#define  ER_ENABLE		(1<<27)
+#define CS_ERCTL1	0x056
+#define CS_ERCTL2	0x057
+#define CS_ERSTAT0	0x058
+#define CS_ERSTAT1	0x059
+
+#define CS_RTCCT	0x060
+#define CS_RTFWC	0x061
+#define CS_RTFWR	0x062
+#define CS_RTFTC	0x063
+#define CS_RTATR	0x064
+
+#define CS_TFBSET	0x070
+#define CS_TFBADD	0x071
+#define CS_TFBSUB	0x072
+#define CS_WCRMAX	0x073
+#define CS_WCRMIN	0x074
+#define CS_WCRINC	0x075
+#define CS_WCRDEC	0x076
+#define CS_WCRCEIL	0x077
+#define CS_BWDCNT	0x078
+
+#define CS_OTPPER	0x080
+#define CS_OTWPER	0x081
+#define CS_OTTLIM	0x082
+#define CS_OTTCNT	0x083
+
+#define CS_HGRRT0	0x090
+	/* ... */
+#define CS_HGRRT7	0x097
+
+#define CS_ORPTRS	0x0a0
+
+#define RXCON_CLOSE	0x100
+
+
+#define RCM_MEM_SIZE	0x10000		/* 1M of 32-bit registers */
+#define TCM_MEM_SIZE	0x20000		/* 2M of 32-bit registers */
+
+/* 2.5 transmit connection memory registers */
+
+#define TSR0_CONN_STATE(x)	((x>>28) & 0x7)
+#define TSR0_USE_WMIN		(1<<23)
+#define TSR0_GROUP(x)		((x & 0x7)<<18)
+#define TSR0_ABR		(2<<16)
+#define TSR0_UBR		(1<<16)
+#define TSR0_CBR		(0<<16)
+#define TSR0_PROT		(1<<15)
+#define TSR0_AAL0_SDU		(2<<12)
+#define TSR0_AAL0		(1<<12)
+#define TSR0_AAL5		(0<<12)
+#define TSR0_HALT_ER		(1<<11)
+#define TSR0_MARK_CI		(1<<10)
+#define TSR0_MARK_ER		(1<<9)
+#define TSR0_UPDATE_GER		(1<<8)
+#define TSR0_RC_INDEX(x)	(x & 0x1F)
+
+#define TSR1_PCR(x)		((x & 0x7FFF)<<16)
+#define TSR1_MCR(x)		(x & 0x7FFF)
+
+#define TSR2_ACR(x)		((x & 0x7FFF)<<16)
+
+#define TSR3_NRM_CNT(x)		((x & 0xFF)<<24)
+#define TSR3_CRM_CNT(x)		(x & 0xFFFF)
+
+#define TSR4_FLUSH_CONN		(1<<31)
+#define TSR4_SESSION_ENDED	(1<<30)
+#define TSR4_CRC10		(1<<28)
+#define TSR4_NULL_CRC10		(1<<27)
+#define TSR4_PROT		(1<<26)
+#define TSR4_AAL0_SDU		(2<<23)
+#define TSR4_AAL0		(1<<23)
+#define TSR4_AAL5		(0<<23)
+
+#define TSR9_OPEN_CONN		(1<<20)
+
+#define TSR11_ICR(x)		((x & 0x7FFF)<<16)
+#define TSR11_TRM(x)		((x & 0x7)<<13)
+#define TSR11_NRM(x)		((x & 0x7)<<10)
+#define TSR11_ADTF(x)		(x & 0x3FF)
+
+#define TSR13_RDF(x)		((x & 0xF)<<23)
+#define TSR13_RIF(x)		((x & 0xF)<<19)
+#define TSR13_CDF(x)		((x & 0x7)<<16)
+#define TSR13_CRM(x)		(x & 0xFFFF)
+
+#define TSR14_DELETE		(1<<31)
+#define TSR14_ABR_CLOSE		(1<<16)
+
+/* 2.7.1 per connection receieve state registers */
+
+#define RSR0_START_PDU	(1<<10)
+#define RSR0_OPEN_CONN	(1<<6)
+#define RSR0_CLOSE_CONN	(0<<6)
+#define RSR0_PPD_ENABLE	(1<<5)
+#define RSR0_EPD_ENABLE	(1<<4)
+#define RSR0_TCP_CKSUM	(1<<3)
+#define RSR0_AAL5		(0)
+#define RSR0_AAL0		(1)
+#define RSR0_AAL0_SDU		(2)
+#define RSR0_RAWCELL		(3)
+#define RSR0_RAWCELL_CRC10	(4)
+
+#define RSR1_AQI_ENABLE	(1<<20)
+#define RSR1_RBPL_ONLY	(1<<19)
+#define RSR1_GROUP(x)	((x)<<16)
+
+#define RSR4_AQI_ENABLE (1<<30)
+#define RSR4_GROUP(x)	((x)<<27)
+#define RSR4_RBPL_ONLY	(1<<26)
+
+/* 2.1.4 transmit packet descriptor */
+
+#define	TPD_USERCELL		0x0
+#define	TPD_SEGMENT_OAMF5	0x4
+#define	TPD_END2END_OAMF5	0x5
+#define	TPD_RMCELL		0x6
+#define TPD_CELLTYPE(x)		(x<<3)
+#define TPD_EOS			(1<<2)
+#define TPD_CLP			(1<<1)
+#define TPD_INT			(1<<0)
+#define TPD_LST		(1<<31)
+
+/* table 4.3 serial eeprom information */
+
+#define PROD_ID		0x08	/* char[] */
+#define  PROD_ID_LEN	30
+#define HW_REV		0x26	/* char[] */
+#define M_SN		0x3a	/* integer */
+#define MEDIA		0x3e	/* integer */
+#define  HE155MM	0x26
+#define  HE155SM	0x27
+#define  HE622MM	0x46
+#define  HE622SM	0x47
+#define MAC_ADDR	0x42	/* char[] */
+
+#define CS_LOW		0x0
+#define CS_HIGH		ID_CS /* HOST_CNTL_ID_PROM_SEL */
+#define CLK_LOW		0x0
+#define CLK_HIGH	ID_CLOCK /* HOST_CNTL_ID_PROM_CLOCK */
+#define SI_HIGH		ID_DIN /* HOST_CNTL_ID_PROM_DATA_IN */
+#define EEPROM_DELAY	400 /* microseconds */
+
+/* Read from EEPROM = 0000 0011b */
+unsigned int readtab[] = {
+	CS_HIGH | CLK_HIGH,
+	CS_LOW | CLK_LOW,
+	CLK_HIGH,               /* 0 */
+	CLK_LOW,
+	CLK_HIGH,               /* 0 */
+	CLK_LOW,
+	CLK_HIGH,               /* 0 */
+	CLK_LOW,
+	CLK_HIGH,               /* 0 */
+	CLK_LOW,
+	CLK_HIGH,               /* 0 */
+	CLK_LOW,
+	CLK_HIGH,               /* 0 */
+	CLK_LOW | SI_HIGH,
+	CLK_HIGH | SI_HIGH,     /* 1 */
+	CLK_LOW | SI_HIGH,
+	CLK_HIGH | SI_HIGH      /* 1 */
+};     
+ 
+/* Clock to read from/write to the EEPROM */
+unsigned int clocktab[] = {
+	CLK_LOW,
+	CLK_HIGH,
+	CLK_LOW,
+	CLK_HIGH,
+	CLK_LOW,
+	CLK_HIGH,
+	CLK_LOW,
+	CLK_HIGH,
+	CLK_LOW,
+	CLK_HIGH,
+	CLK_LOW,
+	CLK_HIGH,
+	CLK_LOW,
+	CLK_HIGH,
+	CLK_LOW,
+	CLK_HIGH,
+	CLK_LOW
+};     
+
+
+#endif /* _HE_H_ */
diff -urN linux-2.5.69-bk2/drivers/block/acsi_slm.c linux-2.5.69-bk3/drivers/block/acsi_slm.c
--- linux-2.5.69-bk2/drivers/block/acsi_slm.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk3/drivers/block/acsi_slm.c	2003-05-08 04:38:16.000000000 -0700
@@ -1008,11 +1008,8 @@
 	
 	devfs_mk_dir("slm");
 	for (i = 0; i < MAX_SLM; i++) {
-		char name[16];
-		sprintf(name, "slm/%d", i);
-		devfs_register(NULL, name, DEVFS_FL_DEFAULT,
-			       ACSI_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR,
-			       &slm_fops, NULL);
+		devfs_mk_cdev(MKDEV(ACSI_MAJOR, i),
+				S_IFCHR|S_IRUSR|S_IWUSR, "slm/%d", i);
 	}
 	return 0;
 }
diff -urN linux-2.5.69-bk2/drivers/block/paride/pg.c linux-2.5.69-bk3/drivers/block/paride/pg.c
--- linux-2.5.69-bk2/drivers/block/paride/pg.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk3/drivers/block/paride/pg.c	2003-05-08 04:38:16.000000000 -0700
@@ -652,11 +652,8 @@
 	devfs_mk_dir ("pg");
 	for (unit=0; unit<PG_UNITS; unit++)
 		if (PG.present) {
-			char name[16];
-			sprintf(name, "pg/%u", unit);
-			devfs_register(NULL, name, DEVFS_FL_DEFAULT,
-			       major, unit, S_IFCHR | S_IRUSR | S_IWUSR,
-			       &pg_fops, NULL);
+			devfs_mk_cdev(MKDEV(major, unit),
+				S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u", unit);
 		}
 	return 0;
 }
diff -urN linux-2.5.69-bk2/drivers/block/paride/pt.c linux-2.5.69-bk3/drivers/block/paride/pt.c
--- linux-2.5.69-bk2/drivers/block/paride/pt.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk3/drivers/block/paride/pt.c	2003-05-08 04:38:16.000000000 -0700
@@ -914,15 +914,12 @@
 	devfs_mk_dir ("pt");
 	for (unit=0;unit<PT_UNITS;unit++)
 		if (PT.present) {
-			char name[16];
-			sprintf(name, "pt/%d", unit);
-			devfs_register(NULL, name, DEVFS_FL_DEFAULT,
-			       major, unit, S_IFCHR | S_IRUSR | S_IWUSR,
-			       &pt_fops, NULL);
-			sprintf(name, "pt/%dn", unit);
-			devfs_register(NULL, name, DEVFS_FL_DEFAULT,
-			       major, 128 + unit, S_IFCHR | S_IRUSR | S_IWUSR,
-			       &pt_fops, NULL);
+			devfs_mk_cdev(MKDEV(major, unit),
+					S_IFCHR | S_IRUSR | S_IWUSR,
+					"pt/%d", unit);
+			devfs_mk_cdev(MKDEV(major, unit + 128),
+					S_IFCHR | S_IRUSR | S_IWUSR,
+					"pt/%dn", unit);
 		}
 	return 0;
 }
diff -urN linux-2.5.69-bk2/drivers/char/amiserial.c linux-2.5.69-bk3/drivers/char/amiserial.c
--- linux-2.5.69-bk2/drivers/char/amiserial.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/amiserial.c	2003-05-08 04:38:16.000000000 -0700
@@ -1528,7 +1528,6 @@
 
 	if (tty_hung_up_p(filp)) {
 		DBG_CNT("before DEC-hung");
-		MOD_DEC_USE_COUNT;
 		local_irq_restore(flags);
 		return;
 	}
@@ -1555,7 +1554,6 @@
 	}
 	if (state->count) {
 		DBG_CNT("before DEC-2");
-		MOD_DEC_USE_COUNT;
 		local_irq_restore(flags);
 		return;
 	}
@@ -1615,7 +1613,6 @@
 	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
 			 ASYNC_CLOSING);
 	wake_up_interruptible(&info->close_wait);
-	MOD_DEC_USE_COUNT;
 	local_irq_restore(flags);
 }
 
@@ -1894,15 +1891,12 @@
 	int 			retval, line;
 	unsigned long		page;
 
-	MOD_INC_USE_COUNT;
 	line = tty->index;
 	if ((line < 0) || (line >= NR_PORTS)) {
-		MOD_DEC_USE_COUNT;
 		return -ENODEV;
 	}
 	retval = get_async_struct(line, &info);
 	if (retval) {
-		MOD_DEC_USE_COUNT;
 		return retval;
 	}
 	tty->driver_data = info;
@@ -2116,6 +2110,7 @@
 
 	memset(&serial_driver, 0, sizeof(struct tty_driver));
 	serial_driver.magic = TTY_DRIVER_MAGIC;
+	serial_driver.owner = THIS_MODULE;
 	serial_driver.driver_name = "amiserial";
 	serial_driver.name = "ttyS";
 	serial_driver.major = TTY_MAJOR;
diff -urN linux-2.5.69-bk2/drivers/char/cyclades.c linux-2.5.69-bk3/drivers/char/cyclades.c
--- linux-2.5.69-bk2/drivers/char/cyclades.c	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/cyclades.c	2003-05-08 04:38:16.000000000 -0700
@@ -2579,15 +2579,12 @@
   int retval, line;
   unsigned long page;
 
-    MOD_INC_USE_COUNT;
     line = tty->index;
     if ((line < 0) || (NR_PORTS <= line)){
-	MOD_DEC_USE_COUNT;
         return -ENODEV;
     }
     info = &cy_port[line];
     if (info->line < 0){
-	MOD_DEC_USE_COUNT;
         return -ENODEV;
     }
     
@@ -2607,7 +2604,6 @@
 	    } else {
 		printk("cyc:Cyclades-Z firmware not yet loaded\n");
 	    }
-	    MOD_DEC_USE_COUNT;
 	    return -ENODEV;
 	}
 #ifdef CONFIG_CYZ_INTR
@@ -2803,7 +2799,6 @@
     CY_LOCK(info, flags);
     /* If the TTY is being hung up, nothing to do */
     if (tty_hung_up_p(filp)) {
-	MOD_DEC_USE_COUNT;
 	CY_UNLOCK(info, flags);
         return;
     }
@@ -2834,7 +2829,6 @@
         info->count = 0;
     }
     if (info->count) {
-	MOD_DEC_USE_COUNT;
 	CY_UNLOCK(info, flags);
         return;
     }
@@ -2931,7 +2925,6 @@
     printk(" cyc:cy_close done\n");
 #endif
 
-    MOD_DEC_USE_COUNT;
     CY_UNLOCK(info, flags);
     return;
 } /* cy_close */
@@ -5494,6 +5487,7 @@
     
     memset(&cy_serial_driver, 0, sizeof(struct tty_driver));
     cy_serial_driver.magic = TTY_DRIVER_MAGIC;
+    cy_serial_driver.owner = THIS_MODULE;
     cy_serial_driver.driver_name = "cyclades";
     cy_serial_driver.name = "ttyC";
     cy_serial_driver.major = CYCLADES_MAJOR;
diff -urN linux-2.5.69-bk2/drivers/char/drm/drm_drv.h linux-2.5.69-bk3/drivers/char/drm/drm_drv.h
--- linux-2.5.69-bk2/drivers/char/drm/drm_drv.h	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/drm/drm_drv.h	2003-05-08 04:38:16.000000000 -0700
@@ -334,7 +334,6 @@
 	dev->last_context = 0;
 	dev->last_switch = 0;
 	dev->last_checked = 0;
-	init_timer( &dev->timer );
 	init_waitqueue_head( &dev->context_wait );
 
 	dev->ctx_start = 0;
@@ -590,6 +589,7 @@
 		dev = &(DRM(device)[i]);
 		memset( (void *)dev, 0, sizeof(*dev) );
 		dev->count_lock = SPIN_LOCK_UNLOCKED;
+		init_timer( &dev->timer );
 		sema_init( &dev->struct_sem, 1 );
 
 		if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
diff -urN linux-2.5.69-bk2/drivers/char/drm/radeon_cp.c linux-2.5.69-bk3/drivers/char/drm/radeon_cp.c
--- linux-2.5.69-bk2/drivers/char/drm/radeon_cp.c	2003-05-04 16:53:06.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/drm/radeon_cp.c	2003-05-08 04:38:16.000000000 -0700
@@ -903,8 +903,8 @@
 
 		RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
 			     entry->busaddr[page_ofs]);
-		DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n",
-			   entry->busaddr[page_ofs],
+		DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
+			   (unsigned long) entry->busaddr[page_ofs],
 			   entry->handle + tmp_ofs );
 	}
 
diff -urN linux-2.5.69-bk2/drivers/char/dsp56k.c linux-2.5.69-bk3/drivers/char/dsp56k.c
--- linux-2.5.69-bk2/drivers/char/dsp56k.c	2003-05-04 16:53:29.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/dsp56k.c	2003-05-08 04:38:17.000000000 -0700
@@ -512,10 +512,9 @@
 		printk("DSP56k driver: Unable to register driver\n");
 		return -ENODEV;
 	}
-	devfs_register(NULL, "dsp56k", DEVFS_FL_DEFAULT,
-		      DSP56K_MAJOR, 0,
-		      S_IFCHR | S_IRUSR | S_IWUSR,
-		      &dsp56k_fops, NULL);
+
+	devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0),
+		      S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k");
 
 	printk(banner);
 	return 0;
diff -urN linux-2.5.69-bk2/drivers/char/dtlk.c linux-2.5.69-bk3/drivers/char/dtlk.c
--- linux-2.5.69-bk2/drivers/char/dtlk.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/dtlk.c	2003-05-08 04:38:17.000000000 -0700
@@ -345,10 +345,9 @@
 	}
 	if (dtlk_dev_probe() == 0)
 		printk(", MAJOR %d\n", dtlk_major);
-	devfs_register(NULL, "dtlk", DEVFS_FL_DEFAULT,
-		       dtlk_major, DTLK_MINOR,
-		       S_IFCHR | S_IRUSR | S_IWUSR,
-		       &dtlk_fops, NULL);
+
+	devfs_mk_cdev(MKDEV(dtlk_major, DTLK_MINOR),
+		       S_IFCHR | S_IRUSR | S_IWUSR, "dtlk");
 
 	init_timer(&dtlk_timer);
 	dtlk_timer.function = dtlk_timer_tick;
diff -urN linux-2.5.69-bk2/drivers/char/dz.c linux-2.5.69-bk3/drivers/char/dz.c
--- linux-2.5.69-bk2/drivers/char/dz.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/dz.c	2003-05-08 04:38:17.000000000 -0700
@@ -1332,6 +1332,7 @@
 
 	memset(&serial_driver, 0, sizeof(struct tty_driver));
 	serial_driver.magic = TTY_DRIVER_MAGIC;
+	serial_driver.owner = THIS_MODULE;
 #if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
 	serial_driver.name = "ttyS";
 #else
@@ -1425,8 +1426,8 @@
 		printk("ttyS%02d at 0x%08x (irq = %d)\n", info->line,
 		       info->port, SERIAL);
 
-		tty_register_device(&serial_driver, info->line);
-		tty_register_device(&callout_driver, info->line);
+		tty_register_device(&serial_driver, info->line, NULL);
+		tty_register_device(&callout_driver, info->line, NULL);
 	}
 
 	/* Reset the chip */
diff -urN linux-2.5.69-bk2/drivers/char/esp.c linux-2.5.69-bk3/drivers/char/esp.c
--- linux-2.5.69-bk2/drivers/char/esp.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/esp.c	2003-05-08 04:38:17.000000000 -0700
@@ -643,9 +643,7 @@
 #ifdef SERIAL_DEBUG_OPEN
 			printk("scheduling hangup...");
 #endif
-			MOD_INC_USE_COUNT;
-			if (schedule_task(&info->tqueue_hangup) == 0)
-				MOD_DEC_USE_COUNT;
+			schedule_task(&info->tqueue_hangup);
 		}
 	}
 }
@@ -811,7 +809,6 @@
 	tty = info->tty;
 	if (tty)
 		tty_hangup(tty);
-	MOD_DEC_USE_COUNT;
 }
 
 /*
@@ -2132,7 +2129,7 @@
 	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
 			 ASYNC_CLOSING);
 	wake_up_interruptible(&info->close_wait);
-out:	MOD_DEC_USE_COUNT;
+out:
 	restore_flags(flags);
 }
 
@@ -2375,7 +2372,6 @@
 #ifdef SERIAL_DEBUG_OPEN
 	printk("esp_open %s, count = %d\n", tty->name, info->count);
 #endif
-	MOD_INC_USE_COUNT;
 	info->count++;
 	tty->driver_data = info;
 	info->tty = tty;
@@ -2551,6 +2547,7 @@
 	
 	memset(&esp_driver, 0, sizeof(struct tty_driver));
 	esp_driver.magic = TTY_DRIVER_MAGIC;
+	esp_driver.owner = THIS_MODULE;
 	esp_driver.name = "ttyP";
 	esp_driver.major = ESP_IN_MAJOR;
 	esp_driver.minor_start = 0;
diff -urN linux-2.5.69-bk2/drivers/char/ftape/zftape/zftape-init.c linux-2.5.69-bk3/drivers/char/ftape/zftape/zftape-init.c
--- linux-2.5.69-bk2/drivers/char/ftape/zftape/zftape-init.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/ftape/zftape/zftape-init.c	2003-05-08 04:38:17.000000000 -0700
@@ -342,38 +342,24 @@
 	TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),);
 
 	for (i = 0; i < 4; i++) {
-		char devname[9];
-
-		sprintf (devname, "qft%i", i);
-		devfs_register (NULL, devname, DEVFS_FL_DEFAULT,
-			        QIC117_TAPE_MAJOR, i,
-				S_IFCHR | S_IRUSR | S_IWUSR,
-				&zft_cdev, NULL);
-		sprintf (devname, "nqft%i", i);
-		devfs_register (NULL, devname, DEVFS_FL_DEFAULT,
-				QIC117_TAPE_MAJOR, i + 4,
-				S_IFCHR | S_IRUSR | S_IWUSR,
-				&zft_cdev, NULL);
-		sprintf (devname, "zqft%i", i);
-		devfs_register (NULL, devname, DEVFS_FL_DEFAULT,
-				QIC117_TAPE_MAJOR, i + 16,
-				S_IFCHR | S_IRUSR | S_IWUSR,
-				&zft_cdev, NULL);
-		sprintf (devname, "nzqft%i", i);
-		devfs_register (NULL, devname, DEVFS_FL_DEFAULT,
-				QIC117_TAPE_MAJOR, i + 20,
-				S_IFCHR | S_IRUSR | S_IWUSR,
-				&zft_cdev, NULL);
-		sprintf (devname, "rawqft%i", i);
-		devfs_register (NULL, devname, DEVFS_FL_DEFAULT,
-				QIC117_TAPE_MAJOR, i + 32,
-				S_IFCHR | S_IRUSR | S_IWUSR,
-				&zft_cdev, NULL);
-		sprintf (devname, "nrawqft%i", i);
-		devfs_register (NULL, devname, DEVFS_FL_DEFAULT,
-				QIC117_TAPE_MAJOR, i + 36,
+		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i),
+				S_IFCHR | S_IRUSR | S_IWUSR,
+				"qft%i", i);
+		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4),
+				S_IFCHR | S_IRUSR | S_IWUSR,
+				"nqft%i", i);
+		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16),
+				S_IFCHR | S_IRUSR | S_IWUSR,
+				"zqft%i", i);
+		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20),
+				S_IFCHR | S_IRUSR | S_IWUSR,
+				"nzqft%i", i);
+		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32),
+				S_IFCHR | S_IRUSR | S_IWUSR,
+				"rawqft%i", i);
+		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36),
 				S_IFCHR | S_IRUSR | S_IWUSR,
-				&zft_cdev, NULL);
+				"nrawqft%i", i);
 	}
 
 #ifdef CONFIG_ZFT_COMPRESSOR
diff -urN linux-2.5.69-bk2/drivers/char/hvc_console.c linux-2.5.69-bk3/drivers/char/hvc_console.c
--- linux-2.5.69-bk2/drivers/char/hvc_console.c	2003-05-08 04:38:12.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/hvc_console.c	2003-05-08 04:38:17.000000000 -0700
@@ -257,6 +257,7 @@
 	memset(&hvc_driver, 0, sizeof(struct tty_driver));
 
 	hvc_driver.magic = TTY_DRIVER_MAGIC;
+	hvc_driver.owner = THIS_MODULE;
 	hvc_driver.driver_name = "hvc";
 	hvc_driver.name = "hvc/";
 	hvc_driver.major = HVC_MAJOR;
@@ -282,7 +283,7 @@
 	for (i = 0; i < hvc_driver.num; i++) {
 		hvc_struct[i].lock = SPIN_LOCK_UNLOCKED;
 		hvc_struct[i].index = i;
-		tty_register_device(&hvc_driver, i);
+		tty_register_device(&hvc_driver, i, NULL);
 	}
 
 	if (tty_register_driver(&hvc_driver))
diff -urN linux-2.5.69-bk2/drivers/char/ip2main.c linux-2.5.69-bk3/drivers/char/ip2main.c
--- linux-2.5.69-bk2/drivers/char/ip2main.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/ip2main.c	2003-05-08 04:38:17.000000000 -0700
@@ -793,6 +793,7 @@
 
 	/* Initialise the relevant fields. */
 	ip2_tty_driver.magic                = TTY_DRIVER_MAGIC;
+	ip2_tty_driver.owner		    = THIS_MODULE;
 	ip2_tty_driver.name                 = pcTty;
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
 	ip2_tty_driver.driver_name          = pcDriver_name;
@@ -869,29 +870,19 @@
 		 */
 
 		for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-#ifdef	CONFIG_DEVFS_FS
-			char name[16];
-#endif
-
 			if ( 0 == ip2config.addr[i] ) {
 				continue;
 			}
 
 #ifdef	CONFIG_DEVFS_FS
 			if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
-				sprintf( name, "ip2/ipl%d", i );
-				devfs_register(NULL, name,
-						DEVFS_FL_DEFAULT,
-						IP2_IPL_MAJOR, 4 * i,
+				devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i),
 						S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
-						&ip2_ipl, NULL);
+						"ip2/ipl%d", i);
 
-				sprintf( name, "ip2/stat%d", i );
-				devfs_register(NULL, name,
-						DEVFS_FL_DEFAULT,
-						IP2_IPL_MAJOR, 4 * i + 1,
+				devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
 						S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
-						&ip2_ipl, NULL);
+						"ip2/stat%d", i);
 
 			    for ( box = 0; box < ABS_MAX_BOXES; ++box )
 			    {
@@ -901,10 +892,10 @@
 				    {
 				        tty_register_device(&ip2_tty_driver,
 					    j + ABS_BIGGEST_BOX *
-						    (box+i*ABS_MAX_BOXES));
+						    (box+i*ABS_MAX_BOXES), NULL);
 				            tty_register_device(&ip2_callout_driver,
 					    j + ABS_BIGGEST_BOX *
-						    (box+i*ABS_MAX_BOXES));
+						    (box+i*ABS_MAX_BOXES), NULL);
 			    	    }
 			        }
 			    }
@@ -1577,7 +1568,6 @@
 	/* Setup pointer links in device and tty structures */
 	pCh->pTTY = tty;
 	tty->driver_data = pCh;
-	MOD_INC_USE_COUNT;
 
 #ifdef IP2DEBUG_OPEN
 	printk(KERN_DEBUG \
@@ -1777,14 +1767,12 @@
 #endif
 
 	if ( tty_hung_up_p ( pFile ) ) {
-		MOD_DEC_USE_COUNT;
 
 		ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 );
 
 		return;
 	}
 	if ( tty->count > 1 ) { /* not the last close */
-		MOD_DEC_USE_COUNT;
 
 		ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 );
 
@@ -1852,7 +1840,6 @@
 	DBG_CNT("ip2_close: after wakeups--");
 #endif
 
-	MOD_DEC_USE_COUNT;
 
 	ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 );
 
diff -urN linux-2.5.69-bk2/drivers/char/ipmi/ipmi_devintf.c linux-2.5.69-bk3/drivers/char/ipmi/ipmi_devintf.c
--- linux-2.5.69-bk2/drivers/char/ipmi/ipmi_devintf.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/ipmi/ipmi_devintf.c	2003-05-08 04:38:17.000000000 -0700
@@ -441,24 +441,17 @@
 
 static void ipmi_new_smi(int if_num)
 {
-	char name[10];
-
-	if (if_num > MAX_DEVICES)
-		return;
-
-	snprintf(name, sizeof(name), "ipmidev/%d", if_num);
-
-	devfs_register(NULL, name, 0, ipmi_major, if_num,
-			S_IFCHR | S_IRUSR | S_IWUSR,
-			&ipmi_fops, NULL);
+	if (if_num <= MAX_DEVICES) {
+		devfs_mk_cdev(MKDEV(ipmi_major, if_num),
+				S_IFCHR | S_IRUSR | S_IWUSR,
+				"ipmidev/%d", if_num);
+	}
 }
 
 static void ipmi_smi_gone(int if_num)
 {
-	if (if_num > MAX_DEVICES)
-		return;
-
-	devfs_remove("ipmidev/%d", if_num);
+	if (if_num <= MAX_DEVICES)
+		devfs_remove("ipmidev/%d", if_num);
 }
 
 static struct ipmi_smi_watcher smi_watcher =
diff -urN linux-2.5.69-bk2/drivers/char/isicom.c linux-2.5.69-bk3/drivers/char/isicom.c
--- linux-2.5.69-bk2/drivers/char/isicom.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/isicom.c	2003-05-08 04:38:17.000000000 -0700
@@ -590,9 +590,7 @@
 							port->status &= ~ISI_DCD;
 							if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
 								(port->flags & ASYNC_CALLOUT_NOHUP))) {
-								MOD_INC_USE_COUNT;
-								if (schedule_task(&port->hangup_tq) == 0)
-									MOD_DEC_USE_COUNT;
+								schedule_task(&port->hangup_tq);
 							}
 						}
 					}
@@ -846,7 +844,6 @@
 #endif	
 	
 	bp->status |= BOARD_ACTIVE;
-	MOD_INC_USE_COUNT;
 	return;
 }
  
@@ -1104,7 +1101,6 @@
 	for(channel = 0; channel < bp->port_count; channel++, port++) {
 		drop_dtr_rts(port);
 	}	
-	MOD_DEC_USE_COUNT;
 }
 
 static void isicom_shutdown_port(struct isi_port * port)
@@ -1644,7 +1640,6 @@
 	tty = port->tty;
 	if (tty)
 		tty_hangup(tty);	/* FIXME: module removal race here - AKPM */
-	MOD_DEC_USE_COUNT;
 }
 
 static void isicom_hangup(struct tty_struct * tty)
@@ -1715,6 +1710,7 @@
 	/* tty driver structure initialization */
 	memset(&isicom_normal, 0, sizeof(struct tty_driver));
 	isicom_normal.magic	= TTY_DRIVER_MAGIC;
+	isicom_normal.owner	= THIS_MODULE;
 	isicom_normal.name 	= "ttyM";
 	isicom_normal.major	= ISICOM_NMAJOR;
 	isicom_normal.minor_start	= 0;
diff -urN linux-2.5.69-bk2/drivers/char/istallion.c linux-2.5.69-bk3/drivers/char/istallion.c
--- linux-2.5.69-bk2/drivers/char/istallion.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/istallion.c	2003-05-08 04:38:17.000000000 -0700
@@ -1054,7 +1054,6 @@
 	if (portp->devnr < 1)
 		return(-ENODEV);
 
-	MOD_INC_USE_COUNT;
 
 /*
  *	Check if this port is in the middle of closing. If so then wait
@@ -1170,14 +1169,12 @@
 	save_flags(flags);
 	cli();
 	if (tty_hung_up_p(filp)) {
-		MOD_DEC_USE_COUNT;
 		restore_flags(flags);
 		return;
 	}
 	if ((tty->count == 1) && (portp->refcount != 1))
 		portp->refcount = 1;
 	if (portp->refcount-- > 1) {
-		MOD_DEC_USE_COUNT;
 		restore_flags(flags);
 		return;
 	}
@@ -1232,7 +1229,6 @@
 	portp->flags &= ~(ASYNC_CALLOUT_ACTIVE | ASYNC_NORMAL_ACTIVE |
 		ASYNC_CLOSING);
 	wake_up_interruptible(&portp->close_wait);
-	MOD_DEC_USE_COUNT;
 	restore_flags(flags);
 }
 
@@ -2369,7 +2365,6 @@
 			tty_hangup(portp->tty);
 		}
 	}
-	MOD_DEC_USE_COUNT;
 }
 
 /*****************************************************************************/
@@ -3004,9 +2999,7 @@
 					if (! ((portp->flags & ASYNC_CALLOUT_ACTIVE) &&
 					    (portp->flags & ASYNC_CALLOUT_NOHUP))) {
 						if (tty != (struct tty_struct *) NULL) {
-							MOD_INC_USE_COUNT;
-							if (schedule_task(&portp->tqhangup) == 0)
-								MOD_DEC_USE_COUNT;
+							schedule_task(&portp->tqhangup);
 						}
 					}
 				}
@@ -5336,12 +5329,9 @@
 
 	devfs_mk_dir("staliomem");
 	for (i = 0; i < 4; i++) {
-		char name[16];
-		sprintf(name, "staliomem/%d", i);
-		devfs_register(NULL, name, DEVFS_FL_DEFAULT,
-			       STL_SIOMEMMAJOR, i,
+		devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
 			       S_IFCHR | S_IRUSR | S_IWUSR,
-			       &stli_fsiomem, NULL);
+			       "staliomem/%d", i);
 	}
 
 /*
@@ -5350,6 +5340,7 @@
  */
 	memset(&stli_serial, 0, sizeof(struct tty_driver));
 	stli_serial.magic = TTY_DRIVER_MAGIC;
+	stli_serial.owner = THIS_MODULE;
 	stli_serial.driver_name = stli_drvname;
 	stli_serial.name = stli_serialname;
 	stli_serial.major = STL_SERIALMAJOR;
diff -urN linux-2.5.69-bk2/drivers/char/keyboard.c linux-2.5.69-bk3/drivers/char/keyboard.c
--- linux-2.5.69-bk2/drivers/char/keyboard.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/keyboard.c	2003-05-08 04:38:17.000000000 -0700
@@ -1047,8 +1047,8 @@
 				printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
 
 #ifdef CONFIG_MAGIC_SYSRQ	       /* Handle the SysRq Hack */
-	if (keycode == KEY_SYSRQ && !rep) {
-		sysrq_down = sysrq_alt && down;
+	if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) {
+		sysrq_down = down;
 		return;
 	}
 	if (sysrq_down && down && !rep) {
diff -urN linux-2.5.69-bk2/drivers/char/lp.c linux-2.5.69-bk3/drivers/char/lp.c
--- linux-2.5.69-bk2/drivers/char/lp.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/lp.c	2003-05-08 04:38:17.000000000 -0700
@@ -784,8 +784,6 @@
 
 static int lp_register(int nr, struct parport *port)
 {
-	char name[16];
-
 	lp_table[nr].dev = parport_register_device(port, "lp", 
 						   lp_preempt, NULL, NULL, 0,
 						   (void *) &lp_table[nr]);
@@ -796,11 +794,8 @@
 	if (reset)
 		lp_reset(nr);
 
-	sprintf (name, "printers/%d", nr);
-	devfs_register (NULL, name,
-			DEVFS_FL_DEFAULT, LP_MAJOR, nr,
-			S_IFCHR | S_IRUGO | S_IWUGO,
-			&lp_fops, NULL);
+	devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO,
+			"printers/%d", nr);
 
 	printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, 
 	       (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
diff -urN linux-2.5.69-bk2/drivers/char/mem.c linux-2.5.69-bk3/drivers/char/mem.c
--- linux-2.5.69-bk2/drivers/char/mem.c	2003-05-04 16:53:29.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/mem.c	2003-05-08 04:38:17.000000000 -0700
@@ -660,15 +660,16 @@
 	return 0;
 }
 
-void __init memory_devfs_register (void)
-{
-    /*  These are never unregistered  */
-    static const struct {
-	unsigned short minor;
-	char *name;
-	umode_t mode;
-	struct file_operations *fops;
-    } list[] = { /* list of minor devices */
+static struct file_operations memory_fops = {
+	.open		= memory_open,	/* just a selector for the real open */
+};
+
+static const struct {
+	unsigned int		minor;
+	char			*name;
+	umode_t			mode;
+	struct file_operations	*fops;
+} devlist[] = { /* list of minor devices */
 	{1, "mem",     S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
 	{2, "kmem",    S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
 	{3, "null",    S_IRUGO | S_IWUGO,           &null_fops},
@@ -680,25 +681,20 @@
 	{8, "random",  S_IRUGO | S_IWUSR,           &random_fops},
 	{9, "urandom", S_IRUGO | S_IWUSR,           &urandom_fops},
 	{11,"kmsg",    S_IRUGO | S_IWUSR,           &kmsg_fops},
-    };
-    int i;
-
-    for (i=0; i<(sizeof(list)/sizeof(*list)); i++)
-	devfs_register (NULL, list[i].name, DEVFS_FL_NONE,
-			MEM_MAJOR, list[i].minor,
-			list[i].mode | S_IFCHR,
-			list[i].fops, NULL);
-}
-
-static struct file_operations memory_fops = {
-	.open		= memory_open,	/* just a selector for the real open */
 };
 
-int __init chr_dev_init(void)
+static int __init chr_dev_init(void)
 {
+	int i;
+
 	if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
 		printk("unable to get major %d for memory devs\n", MEM_MAJOR);
-	memory_devfs_register();
+
+	for (i = 0; i < ARRAY_SIZE(devlist); i++) {
+		devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor),
+				S_IFCHR | devlist[i].mode, devlist[i].name);
+	}
+	
 	rand_initialize();
 #if defined (CONFIG_FB)
 	fbmem_init();
diff -urN linux-2.5.69-bk2/drivers/char/misc.c linux-2.5.69-bk3/drivers/char/misc.c
--- linux-2.5.69-bk2/drivers/char/misc.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/misc.c	2003-05-08 04:38:17.000000000 -0700
@@ -200,8 +200,8 @@
 				"misc/%s", misc->name);
 	}
 
-	devfs_register(NULL, misc->devfs_name, 0, MISC_MAJOR, misc->minor,
-			S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, misc->fops, NULL);
+	devfs_mk_cdev(MKDEV(MISC_MAJOR, misc->minor),
+			S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, misc->devfs_name);
 
 	/*
 	 * Add it to the front, so that later devices can "override"
diff -urN linux-2.5.69-bk2/drivers/char/moxa.c linux-2.5.69-bk3/drivers/char/moxa.c
--- linux-2.5.69-bk2/drivers/char/moxa.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/moxa.c	2003-05-08 04:38:17.000000000 -0700
@@ -341,6 +341,7 @@
 	memset(&moxaDriver, 0, sizeof(struct tty_driver));
 	memset(&moxaCallout, 0, sizeof(struct tty_driver));
 	moxaDriver.magic = TTY_DRIVER_MAGIC;
+	moxaDriver.owner = THIS_MODULE;
 	moxaDriver.name = "ttya";
 	moxaDriver.major = ttymajor;
 	moxaDriver.minor_start = 0;
@@ -544,7 +545,6 @@
 			ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);
 		}
 	}
-	MOD_DEC_USE_COUNT;
 }
 
 static int moxa_open(struct tty_struct *tty, struct file *filp)
@@ -556,7 +556,6 @@
 
 	port = PORTNO(tty);
 	if (port == MAX_PORTS) {
-		MOD_INC_USE_COUNT;
 		return (0);
 	}
 	if (!MoxaPortIsValid(port)) {
@@ -579,7 +578,6 @@
 	}
 	up(&moxaBuffSem);
 
-	MOD_INC_USE_COUNT;
 	ch = &moxaChannels[port];
 	ch->count++;
 	tty->driver_data = ch;
@@ -619,7 +617,6 @@
 
 	port = PORTNO(tty);
 	if (port == MAX_PORTS) {
-		MOD_DEC_USE_COUNT;
 		return;
 	}
 	if (!MoxaPortIsValid(port)) {
@@ -633,7 +630,6 @@
 		return;
 	}
 	if (tty_hung_up_p(filp)) {
-		MOD_DEC_USE_COUNT;
 		return;
 	}
 	ch = (struct moxa_str *) tty->driver_data;
@@ -649,7 +645,6 @@
 		ch->count = 0;
 	}
 	if (ch->count) {
-		MOD_DEC_USE_COUNT;
 		return;
 	}
 	ch->asyncflags |= ASYNC_CLOSING;
@@ -688,7 +683,6 @@
 	ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE |
 			    ASYNC_CLOSING);
 	wake_up_interruptible(&ch->close_wait);
-	MOD_DEC_USE_COUNT;
 }
 
 static int moxa_write(struct tty_struct *tty, int from_user,
@@ -1024,9 +1018,7 @@
 						wake_up_interruptible(&ch->open_wait);
 					else {
 						set_bit(MOXA_EVENT_HANGUP, &ch->event);
-						MOD_DEC_USE_COUNT;
-						if (schedule_work(&ch->tqueue) == 0)
-							MOD_INC_USE_COUNT;
+						schedule_work(&ch->tqueue);
 					}
 				}
 			}
diff -urN linux-2.5.69-bk2/drivers/char/mwave/mwavedd.h linux-2.5.69-bk3/drivers/char/mwave/mwavedd.h
--- linux-2.5.69-bk2/drivers/char/mwave/mwavedd.h	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/mwave/mwavedd.h	2003-05-08 04:38:17.000000000 -0700
@@ -50,9 +50,11 @@
 #define _LINUX_MWAVEDD_H
 #include "3780i.h"
 #include "tp3780i.h"
+#include "smapi.h"
 #include "mwavepub.h"
 #include <linux/ioctl.h>
 #include <asm/uaccess.h>
+#include <linux/wait.h>
 
 extern int mwave_debug;
 extern int mwave_3780i_irq;
diff -urN linux-2.5.69-bk2/drivers/char/mxser.c linux-2.5.69-bk3/drivers/char/mxser.c
--- linux-2.5.69-bk2/drivers/char/mxser.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/mxser.c	2003-05-08 04:38:17.000000000 -0700
@@ -501,6 +501,7 @@
 
 	memset(&mxvar_sdriver, 0, sizeof(struct tty_driver));
 	mxvar_sdriver.magic = TTY_DRIVER_MAGIC;
+	mxvar_sdriver.owner = THIS_MODULE;
 	mxvar_sdriver.name = "ttyM";
 	mxvar_sdriver.major = ttymajor;
 	mxvar_sdriver.minor_start = 0;
@@ -708,7 +709,6 @@
 			tty_hangup(tty);	/* FIXME: module removal race here - AKPM */
 		}
 	}
-	MOD_DEC_USE_COUNT;
 }
 
 /*
@@ -767,8 +767,6 @@
 	info->session = current->session;
 	info->pgrp = current->pgrp;
 
-	MOD_INC_USE_COUNT;
-
 	return (0);
 }
 
@@ -795,7 +793,6 @@
 
 	if (tty_hung_up_p(filp)) {
 		restore_flags(flags);
-		MOD_DEC_USE_COUNT;
 		return;
 	}
 	if ((tty->count == 1) && (info->count != 1)) {
@@ -817,7 +814,6 @@
 	}
 	if (info->count) {
 		restore_flags(flags);
-		MOD_DEC_USE_COUNT;
 		return;
 	}
 	info->flags |= ASYNC_CLOSING;
@@ -881,7 +877,6 @@
 	wake_up_interruptible(&info->close_wait);
 	restore_flags(flags);
 
-	MOD_DEC_USE_COUNT;
 }
 
 static int mxser_write(struct tty_struct *tty, int from_user,
@@ -1492,9 +1487,7 @@
 
 	if (info->xmit_cnt < WAKEUP_CHARS) {
 		set_bit(MXSER_EVENT_TXLOW, &info->event);
-		MOD_INC_USE_COUNT;
-		if (schedule_work(&info->tqueue) == 0)
-		    MOD_DEC_USE_COUNT;
+		schedule_work(&info->tqueue);
 	}
 	if (info->xmit_cnt <= 0) {
 		info->IER &= ~UART_IER_THRI;
@@ -1523,9 +1516,7 @@
 		else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
 			   (info->flags & ASYNC_CALLOUT_NOHUP)))
 			set_bit(MXSER_EVENT_HANGUP, &info->event);
-		MOD_INC_USE_COUNT;
-		if (schedule_work(&info->tqueue) == 0)
-		    MOD_DEC_USE_COUNT;
+		schedule_work(&info->tqueue);
 	}
 	if (info->flags & ASYNC_CTS_FLOW) {
 		if (info->tty->hw_stopped) {
@@ -1535,9 +1526,7 @@
 				outb(info->IER, info->base + UART_IER);
 
 				set_bit(MXSER_EVENT_TXLOW, &info->event);
-				MOD_INC_USE_COUNT;
-				if (schedule_work(&info->tqueue) == 0)
-					MOD_DEC_USE_COUNT;
+				schedule_work(&info->tqueue);
 			}
 		} else {
 			if (!(status & UART_MSR_CTS)) {
diff -urN linux-2.5.69-bk2/drivers/char/pcxx.c linux-2.5.69-bk3/drivers/char/pcxx.c
--- linux-2.5.69-bk2/drivers/char/pcxx.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/pcxx.c	2003-05-08 04:38:17.000000000 -0700
@@ -431,8 +431,6 @@
 		return(-ENODEV);
 	}
 
-	/* flag the kernel that there is somebody using this guy */
-	MOD_INC_USE_COUNT;
 	/*
 	 * If the device is in the middle of being closed, then block
 	 * until it's done, and then try again.
@@ -576,7 +574,6 @@
 
 		if(tty_hung_up_p(filp)) {
 			/* flag that somebody is done with this module */
-			MOD_DEC_USE_COUNT;
 			restore_flags(flags);
 			return;
 		}
@@ -594,7 +591,6 @@
 		}
 		if (info->count-- > 1) {
 			restore_flags(flags);
-			MOD_DEC_USE_COUNT;
 			return;
 		}
 		if (info->count < 0) {
@@ -651,7 +647,6 @@
 		info->asyncflags &= ~(ASYNC_NORMAL_ACTIVE|
 							  ASYNC_CALLOUT_ACTIVE|ASYNC_CLOSING);
 		wake_up_interruptible(&info->close_wait);
-		MOD_DEC_USE_COUNT;
 		restore_flags(flags);
 	}
 }
@@ -1228,6 +1223,7 @@
 
 	memset(&pcxe_driver, 0, sizeof(struct tty_driver));
 	pcxe_driver.magic = TTY_DRIVER_MAGIC;
+	pcxe_driver.owner = THIS_MODULE;
 	pcxe_driver.name = "ttyD";
 	pcxe_driver.major = DIGI_MAJOR; 
 	pcxe_driver.minor_start = 0;
diff -urN linux-2.5.69-bk2/drivers/char/ppdev.c linux-2.5.69-bk3/drivers/char/ppdev.c
--- linux-2.5.69-bk2/drivers/char/ppdev.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/ppdev.c	2003-05-08 04:38:17.000000000 -0700
@@ -760,10 +760,8 @@
 	}
 	devfs_mk_dir("parports");
 	for (i = 0; i < PARPORT_MAX; i++) {
-		char name[16];
-		sprintf(name, "parports/%d", i);
-		devfs_register(NULL, name, DEVFS_FL_DEFAULT, PP_MAJOR, i,
-			       S_IFCHR | S_IRUGO | S_IWUGO, &pp_fops, NULL);
+		devfs_mk_cdev(MKDEV(PP_MAJOR, i),
+				S_IFCHR | S_IRUGO | S_IWUGO, "parports/%d", i);
 	}
 
 	printk (KERN_INFO PP_VERSION "\n");
diff -urN linux-2.5.69-bk2/drivers/char/random.c linux-2.5.69-bk3/drivers/char/random.c
--- linux-2.5.69-bk2/drivers/char/random.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/random.c	2003-05-08 04:38:17.000000000 -0700
@@ -1527,7 +1527,7 @@
 	 * If we gave the user some bytes, update the access time.
 	 */
 	if (count != 0) {
-		UPDATE_ATIME(file->f_dentry->d_inode);
+		update_atime(file->f_dentry->d_inode);
 	}
 	
 	return (count ? count : retval);
diff -urN linux-2.5.69-bk2/drivers/char/raw.c linux-2.5.69-bk3/drivers/char/raw.c
--- linux-2.5.69-bk2/drivers/char/raw.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/raw.c	2003-05-08 04:38:17.000000000 -0700
@@ -181,7 +181,7 @@
 			}
 			if (rawdev->binding) {
 				bdput(rawdev->binding);
-				MOD_DEC_USE_COUNT;
+				module_put(THIS_MODULE);
 			}
 			if (rq.block_major == 0 && rq.block_minor == 0) {
 				/* unbind */
@@ -191,7 +191,7 @@
 				if (rawdev->binding == NULL)
 					err = -ENOMEM;
 				else
-					try_module_get(THIS_MODULE);
+					__module_get(THIS_MODULE);
 			}
 			up(&raw_mutex);
 		} else {
diff -urN linux-2.5.69-bk2/drivers/char/rio/rio_linux.c linux-2.5.69-bk3/drivers/char/rio/rio_linux.c
--- linux-2.5.69-bk2/drivers/char/rio/rio_linux.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/rio/rio_linux.c	2003-05-08 04:38:17.000000000 -0700
@@ -389,29 +389,6 @@
   udelay (usecs);
 }
 
-
-void rio_inc_mod_count (void)
-{
-#ifdef MODULE
-  func_enter ();
-  rio_dprintk (RIO_DEBUG_MOD_COUNT, "rio_inc_mod_count\n");
-  MOD_INC_USE_COUNT; 
-  func_exit ();
-#endif
-}
-
-
-void rio_dec_mod_count (void)
-{
-#ifdef MODULE
-  func_enter ();
-  rio_dprintk (RIO_DEBUG_MOD_COUNT, "rio_dec_mod_count\n");
-  MOD_DEC_USE_COUNT; 
-  func_exit ();
-#endif
-}
-
-
 static int rio_set_real_termios (void *ptr)
 {
   int rv, modem;
@@ -660,7 +637,6 @@
   
   PortP = (struct Port *)ptr;
   PortP->gs.tty = NULL;
-  rio_dec_mod_count (); 
 
   func_exit ();
 }
@@ -686,7 +662,6 @@
   }                
 
   PortP->gs.tty = NULL;
-  rio_dec_mod_count ();
   func_exit ();
 }
 
@@ -908,6 +883,7 @@
 
   memset(&rio_driver, 0, sizeof(rio_driver));
   rio_driver.magic = TTY_DRIVER_MAGIC;
+  rio_driver.owner = THIS_MODULE;
   rio_driver.driver_name = "specialix_rio";
   rio_driver.name = "ttySR";
   rio_driver.major = RIO_NORMAL_MAJOR0;
diff -urN linux-2.5.69-bk2/drivers/char/rio/rio_linux.h linux-2.5.69-bk3/drivers/char/rio/rio_linux.h
--- linux-2.5.69-bk2/drivers/char/rio/rio_linux.h	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/rio/rio_linux.h	2003-05-08 04:38:17.000000000 -0700
@@ -87,9 +87,6 @@
 #endif
 
 
-void rio_dec_mod_count (void);
-void rio_inc_mod_count (void);
-
 /* Allow us to debug "in the field" without requiring clients to
    recompile.... */
 #if 1
diff -urN linux-2.5.69-bk2/drivers/char/rio/riotty.c linux-2.5.69-bk3/drivers/char/rio/riotty.c
--- linux-2.5.69-bk2/drivers/char/rio/riotty.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/rio/riotty.c	2003-05-08 04:38:17.000000000 -0700
@@ -139,7 +139,6 @@
 
 
 extern struct rio_info *p;
-extern void rio_inc_mod_count (void);
 
 
 int
@@ -205,8 +204,6 @@
 	tty->driver_data = PortP;
 
 	PortP->gs.tty = tty;
-	if (!PortP->gs.count)
-		rio_inc_mod_count ();
 	PortP->gs.count++;
 
 	rio_dprintk (RIO_DEBUG_TTY, "%d bytes in tx buffer\n",
@@ -215,8 +212,6 @@
 	retval = gs_init_port (&PortP->gs);
 	if (retval) {
 		PortP->gs.count--;
-		if (PortP->gs.count)
-			rio_dec_mod_count ();
 		return -ENXIO;
 	}
 	/*
diff -urN linux-2.5.69-bk2/drivers/char/riscom8.c linux-2.5.69-bk3/drivers/char/riscom8.c
--- linux-2.5.69-bk2/drivers/char/riscom8.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/riscom8.c	2003-05-08 04:38:17.000000000 -0700
@@ -552,9 +552,7 @@
 			wake_up_interruptible(&port->open_wait);
 		else if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
 			   (port->flags & ASYNC_CALLOUT_NOHUP))) {
-			MOD_INC_USE_COUNT;
-			if (schedule_task(&port->tqueue_hangup) == 0)
-				MOD_DEC_USE_COUNT;
+			schedule_task(&port->tqueue_hangup);
 		}
 	}
 	
@@ -676,7 +674,6 @@
 	IRQ_to_board[bp->irq] = bp;
 	bp->flags |= RC_BOARD_ACTIVE;
 	
-	MOD_INC_USE_COUNT;
 	return 0;
 }
 
@@ -694,7 +691,6 @@
 	bp->DTR = ~0;
 	rc_out(bp, RC_DTR, bp->DTR);	       /* Drop DTR on all ports */
 	
-	MOD_DEC_USE_COUNT;
 }
 
 /*
@@ -1678,7 +1674,6 @@
 	tty = port->tty;
 	if (tty)
 		tty_hangup(tty);	/* FIXME: module removal race still here */
-	MOD_DEC_USE_COUNT;
 }
 
 static void rc_hangup(struct tty_struct * tty)
@@ -1757,6 +1752,7 @@
 	memset(IRQ_to_board, 0, sizeof(IRQ_to_board));
 	memset(&riscom_driver, 0, sizeof(riscom_driver));
 	riscom_driver.magic = TTY_DRIVER_MAGIC;
+	riscom_driver.owner = THIS_MODULE;
 	riscom_driver.name = "ttyL";
 	riscom_driver.major = RISCOM8_NORMAL_MAJOR;
 	riscom_driver.num = RC_NBOARD * RC_NPORT;
diff -urN linux-2.5.69-bk2/drivers/char/rocket.c linux-2.5.69-bk3/drivers/char/rocket.c
--- linux-2.5.69-bk2/drivers/char/rocket.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/rocket.c	2003-05-08 04:38:17.000000000 -0700
@@ -874,9 +874,6 @@
 	}
 
 	if (info->count++ == 0) {
-#ifdef MODULE
-		MOD_INC_USE_COUNT;
-#endif
 		rp_num_ports_open++;
 #ifdef ROCKET_DEBUG_OPEN
 		printk("rocket mod++ = %d...", rp_num_ports_open);
@@ -1071,9 +1068,6 @@
 	tty->closing = 0;
 	wake_up_interruptible(&info->close_wait);
 	
-#ifdef MODULE
-	MOD_DEC_USE_COUNT;
-#endif
 	rp_num_ports_open--;
 #ifdef ROCKET_DEBUG_OPEN
 	printk("rocket mod-- = %d...", rp_num_ports_open);
@@ -1504,9 +1498,6 @@
 		return;
 	}
 	if (info->count) {
-#ifdef MODULE
-		MOD_DEC_USE_COUNT;
-#endif
 		rp_num_ports_open--;
 	}
 	
@@ -2012,6 +2003,7 @@
 	 */
 	memset(&rocket_driver, 0, sizeof(struct tty_driver));
 	rocket_driver.magic = TTY_DRIVER_MAGIC;
+	rocket_driver.owner = THIS_MODULE;
 #ifdef CONFIG_DEVFS_FS
 	rocket_driver.name = "tts/R";
 #else
diff -urN linux-2.5.69-bk2/drivers/char/ser_a2232.c linux-2.5.69-bk3/drivers/char/ser_a2232.c
--- linux-2.5.69-bk2/drivers/char/ser_a2232.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/ser_a2232.c	2003-05-08 04:38:17.000000000 -0700
@@ -272,7 +272,6 @@
 		not in "a2232_close()". See the comment in "sx.c", too.
 		If you run into problems, compile this driver into the
 		kernel instead of compiling it as a module. */
-	MOD_DEC_USE_COUNT;
 }
 
 static int  a2232_set_real_termios(void *ptr)
@@ -414,7 +413,6 @@
 	a2232_disable_tx_interrupts(ptr);
 	a2232_disable_rx_interrupts(ptr);
 	/* see the comment in a2232_shutdown_port above. */
-	/* MOD_DEC_USE_COUNT; */
 }
 
 static void a2232_hungup(void *ptr)
@@ -468,13 +466,9 @@
 		return retval;
 	}
 	port->gs.flags |= GS_ACTIVE;
-	if (port->gs.count == 1) {
-		MOD_INC_USE_COUNT;
-	}
 	retval = gs_block_til_ready(port, filp);
 
 	if (retval) {
-		MOD_DEC_USE_COUNT;
 		port->gs.count--;
 		return retval;
 	}
@@ -711,6 +705,7 @@
 
 	memset(&a2232_driver, 0, sizeof(a2232_driver));
 	a2232_driver.magic = TTY_DRIVER_MAGIC;
+	a2232_driver.owner = THIS_MODULE;
 	a2232_driver.driver_name = "commodore_a2232";
 	a2232_driver.name = "ttyY";
 	a2232_driver.major = A2232_NORMAL_MAJOR;
diff -urN linux-2.5.69-bk2/drivers/char/serial167.c linux-2.5.69-bk3/drivers/char/serial167.c
--- linux-2.5.69-bk2/drivers/char/serial167.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/serial167.c	2003-05-08 04:38:17.000000000 -0700
@@ -2395,6 +2395,7 @@
     
     memset(&cy_serial_driver, 0, sizeof(struct tty_driver));
     cy_serial_driver.magic = TTY_DRIVER_MAGIC;
+    cy_serial_driver.owner = THIS_MODULE;
 #ifdef CONFIG_DEVFS_FS
     cy_serial_driver.name = "tts/";
 #else
diff -urN linux-2.5.69-bk2/drivers/char/serial_tx3912.c linux-2.5.69-bk3/drivers/char/serial_tx3912.c
--- linux-2.5.69-bk2/drivers/char/serial_tx3912.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/serial_tx3912.c	2003-05-08 04:38:17.000000000 -0700
@@ -41,8 +41,6 @@
 static void rs_shutdown_port (void * ptr); 
 static int rs_set_real_termios (void *ptr);
 static int rs_chars_in_buffer (void * ptr); 
-static void rs_hungup (void *ptr);
-static void rs_close (void *ptr);
 
 /*
  * Used by generic serial driver to access hardware
@@ -56,8 +54,6 @@
 	.shutdown_port         = rs_shutdown_port,  
 	.set_real_termios      = rs_set_real_termios,  
 	.chars_in_buffer       = rs_chars_in_buffer, 
-	.close                 = rs_close, 
-	.hungup                = rs_hungup,
 }; 
 
 /*
@@ -579,9 +575,6 @@
 
 	rs_dprintk (TX3912_UART_DEBUG_OPEN, "before inc_use_count (count=%d.\n", 
 	            port->gs.count);
-	if (port->gs.count == 1) {
-		MOD_INC_USE_COUNT;
-	}
 	rs_dprintk (TX3912_UART_DEBUG_OPEN, "after inc_use_count\n");
 
 	/* Jim: Initialize port hardware here */
@@ -595,7 +588,6 @@
 	            retval, port->gs.count);
 
 	if (retval) {
-		MOD_DEC_USE_COUNT;
 		port->gs.count--;
 		return retval;
 	}
@@ -621,32 +613,6 @@
 }
 
 
-
-static void rs_close (void *ptr)
-{
-	func_enter ();
-
-	/* Anything to do here? */
-
-	MOD_DEC_USE_COUNT;
-	func_exit ();
-}
-
-
-/* I haven't the foggiest why the decrement use count has to happen
-   here. The whole linux serial drivers stuff needs to be redesigned.
-   My guess is that this is a hack to minimize the impact of a bug
-   elsewhere. Thinking about it some more. (try it sometime) Try
-   running minicom on a serial port that is driven by a modularized
-   driver. Have the modem hangup. Then remove the driver module. Then
-   exit minicom.  I expect an "oops".  -- REW */
-static void rs_hungup (void *ptr)
-{
-	func_enter ();
-	MOD_DEC_USE_COUNT;
-	func_exit ();
-}
-
 static int rs_ioctl (struct tty_struct * tty, struct file * filp, 
                      unsigned int cmd, unsigned long arg)
 {
@@ -839,6 +805,7 @@
 
 	memset(&rs_driver, 0, sizeof(rs_driver));
 	rs_driver.magic = TTY_DRIVER_MAGIC;
+	rs_driver.owner = THIS_MODULE;
 	rs_driver.driver_name = "serial";
 	rs_driver.name = "ttyS";
 	rs_driver.major = TTY_MAJOR;
diff -urN linux-2.5.69-bk2/drivers/char/sh-sci.c linux-2.5.69-bk3/drivers/char/sh-sci.c
--- linux-2.5.69-bk2/drivers/char/sh-sci.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/sh-sci.c	2003-05-08 04:38:17.000000000 -0700
@@ -71,8 +71,6 @@
 static int  sci_get_CD(void *ptr);
 static void sci_shutdown_port(void *ptr);
 static int sci_set_real_termios(void *ptr);
-static void sci_hungup(void *ptr);
-static void sci_close(void *ptr);
 static int sci_chars_in_buffer(void *ptr);
 static int sci_request_irq(struct sci_port *port);
 static void sci_free_irq(struct sci_port *port);
@@ -216,8 +214,6 @@
 	sci_shutdown_port,
 	sci_set_real_termios,
 	sci_chars_in_buffer,
-	sci_close,
-	sci_hungup,
 	NULL
 };
 
@@ -838,12 +834,7 @@
 	sci_setsignals(port, 1,1);
 
 	if (port->gs.count == 1) {
-		MOD_INC_USE_COUNT;
-
 		retval = sci_request_irq(port);
-		if (retval) {
-			goto failed_2;
-		}
 	}
 
 	retval = gs_block_til_ready(port, filp);
@@ -878,23 +869,11 @@
 
 failed_3:
 	sci_free_irq(port);
-failed_2:
-	MOD_DEC_USE_COUNT;
 failed_1:
 	port->gs.count--;
 	return retval;
 }
 
-static void sci_hungup(void *ptr)
-{
-	MOD_DEC_USE_COUNT;
-}
-
-static void sci_close(void *ptr)
-{
-	MOD_DEC_USE_COUNT;
-}
-
 static int sci_ioctl(struct tty_struct * tty, struct file * filp, 
                      unsigned int cmd, unsigned long arg)
 {
@@ -1019,6 +998,7 @@
 
 	memset(&sci_driver, 0, sizeof(sci_driver));
 	sci_driver.magic = TTY_DRIVER_MAGIC;
+	sci_driver.owner = THIS_MODULE;
 	sci_driver.driver_name = "sci";
 #ifdef CONFIG_DEVFS_FS
 	sci_driver.name = "ttsc/";
diff -urN linux-2.5.69-bk2/drivers/char/specialix.c linux-2.5.69-bk3/drivers/char/specialix.c
--- linux-2.5.69-bk2/drivers/char/specialix.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/specialix.c	2003-05-08 04:38:17.000000000 -0700
@@ -833,9 +833,7 @@
 #ifdef SPECIALIX_DEBUG
 			printk ( "Sending HUP.\n");
 #endif
-			MOD_INC_USE_COUNT;
-			if (schedule_task(&port->tqueue_hangup) == 0)
-				MOD_DEC_USE_COUNT;
+			schedule_task(&port->tqueue_hangup);
 		} else {
 #ifdef SPECIALIX_DEBUG
 			printk ( "Don't need to send HUP.\n");
@@ -980,7 +978,6 @@
 	turn_ints_on (bp);
 	bp->flags |= SX_BOARD_ACTIVE;
 
-	MOD_INC_USE_COUNT;
 	return 0;
 }
 
@@ -1000,7 +997,6 @@
 
 	turn_ints_off (bp);
 
-	MOD_DEC_USE_COUNT;
 }
 
 
@@ -2150,7 +2146,6 @@
 	tty = port->tty;
 	if (tty)
 		tty_hangup(tty);	/* FIXME: module removal race here */
-	MOD_DEC_USE_COUNT;
 }
 
 
@@ -2233,6 +2228,7 @@
 	init_bh(SPECIALIX_BH, do_specialix_bh);
 	memset(&specialix_driver, 0, sizeof(specialix_driver));
 	specialix_driver.magic = TTY_DRIVER_MAGIC;
+	specialix_driver.owner = THIS_MODULE;
 	specialix_driver.name = "ttyW";
 	specialix_driver.major = SPECIALIX_NORMAL_MAJOR;
 	specialix_driver.num = SX_NBOARD * SX_NPORT;
diff -urN linux-2.5.69-bk2/drivers/char/stallion.c linux-2.5.69-bk3/drivers/char/stallion.c
--- linux-2.5.69-bk2/drivers/char/stallion.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/stallion.c	2003-05-08 04:38:17.000000000 -0700
@@ -1044,8 +1044,6 @@
 	if (portp == (stlport_t *) NULL)
 		return(-ENODEV);
 
-	MOD_INC_USE_COUNT;
-
 /*
  *	On the first open of the device setup the port hardware, and
  *	initialize the per port data structure.
@@ -1207,14 +1205,12 @@
 	save_flags(flags);
 	cli();
 	if (tty_hung_up_p(filp)) {
-		MOD_DEC_USE_COUNT;
 		restore_flags(flags);
 		return;
 	}
 	if ((tty->count == 1) && (portp->refcount != 1))
 		portp->refcount = 1;
 	if (portp->refcount-- > 1) {
-		MOD_DEC_USE_COUNT;
 		restore_flags(flags);
 		return;
 	}
@@ -1267,7 +1263,6 @@
 	portp->flags &= ~(ASYNC_CALLOUT_ACTIVE | ASYNC_NORMAL_ACTIVE |
 		ASYNC_CLOSING);
 	wake_up_interruptible(&portp->close_wait);
-	MOD_DEC_USE_COUNT;
 	restore_flags(flags);
 }
 
@@ -2241,11 +2236,11 @@
 #endif
 
 	if (portp == (stlport_t *) NULL)
-		goto out;
+		return;
 
 	tty = portp->tty;
 	if (tty == (struct tty_struct *) NULL)
-		goto out;
+		return;
 
 	lock_kernel();
 	if (test_bit(ASYI_TXLOW, &portp->istate)) {
@@ -2270,8 +2265,6 @@
 		}
 	}
 	unlock_kernel();
-out:
-	MOD_DEC_USE_COUNT;
 }
 
 /*****************************************************************************/
@@ -3216,13 +3209,11 @@
 	if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
 		printk("STALLION: failed to register serial board device\n");
 	devfs_mk_dir("staliomem");
+
 	for (i = 0; i < 4; i++) {
-		char name[16];
-		sprintf(name, "staliomem/%d", i);
-		devfs_register(NULL, name, DEVFS_FL_DEFAULT,
-			       STL_SIOMEMMAJOR, i,
-			       S_IFCHR | S_IRUSR | S_IWUSR,
-			       &stl_fsiomem, NULL);
+		devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
+				S_IFCHR|S_IRUSR|S_IWUSR,
+				&stl_fsiomem, NULL, "staliomem/%d", i);
 	}
 
 /*
@@ -3231,6 +3222,7 @@
  */
 	memset(&stl_serial, 0, sizeof(struct tty_driver));
 	stl_serial.magic = TTY_DRIVER_MAGIC;
+	stl_serial.owner = THIS_MODULE;
 	stl_serial.driver_name = stl_drvname;
 	stl_serial.name = stl_serialname;
 	stl_serial.major = STL_SERIALMAJOR;
@@ -4136,9 +4128,7 @@
 	if ((len == 0) || ((len < STL_TXBUFLOW) &&
 	    (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
 		set_bit(ASYI_TXLOW, &portp->istate);
-		MOD_INC_USE_COUNT;
-		if (schedule_work(&portp->tqueue) == 0)
-			MOD_DEC_USE_COUNT;
+		schedule_work(&portp->tqueue);
 	}
 
 	if (len == 0) {
@@ -4318,9 +4308,7 @@
 	misr = inb(ioaddr + EREG_DATA);
 	if (misr & MISR_DCD) {
 		set_bit(ASYI_DCDCHANGE, &portp->istate);
-		MOD_INC_USE_COUNT;
-		if (schedule_task(&portp->tqueue) == 0)
-			MOD_DEC_USE_COUNT;
+		schedule_task(&portp->tqueue);
 		portp->stats.modem++;
 	}
 
@@ -5117,9 +5105,7 @@
 	if ((len == 0) || ((len < STL_TXBUFLOW) &&
 	    (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
 		set_bit(ASYI_TXLOW, &portp->istate);
-		MOD_INC_USE_COUNT;
-		if (schedule_task(&portp->tqueue) == 0)
-			MOD_DEC_USE_COUNT;
+		schedule_task(&portp->tqueue); 
 	}
 
 	if (len == 0) {
@@ -5336,9 +5322,7 @@
 		ipr = stl_sc26198getreg(portp, IPR);
 		if (ipr & IPR_DCDCHANGE) {
 			set_bit(ASYI_DCDCHANGE, &portp->istate);
-			MOD_INC_USE_COUNT;
-			if (schedule_task(&portp->tqueue) == 0)
-				MOD_DEC_USE_COUNT;
+			schedule_task(&portp->tqueue); 
 			portp->stats.modem++;
 		}
 		break;
diff -urN linux-2.5.69-bk2/drivers/char/sysrq.c linux-2.5.69-bk3/drivers/char/sysrq.c
--- linux-2.5.69-bk2/drivers/char/sysrq.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/sysrq.c	2003-05-08 04:38:18.000000000 -0700
@@ -101,131 +101,19 @@
 {
 	machine_restart(NULL);
 }
+
 static struct sysrq_key_op sysrq_reboot_op = {
 	.handler	= sysrq_handle_reboot,
 	.help_msg	= "reBoot",
 	.action_msg	= "Resetting",
 };
 
-
-
-/* SYNC SYSRQ HANDLERS BLOCK */
-
-/* do_emergency_sync helper function */
-/* Guesses if the device is a local hard drive */
-static int is_local_disk(struct block_device *bdev)
-{
-	switch (MAJOR(bdev->bd_dev)) {
-	case IDE0_MAJOR:
-	case IDE1_MAJOR:
-	case IDE2_MAJOR:
-	case IDE3_MAJOR:
-	case IDE4_MAJOR:
-	case IDE5_MAJOR:
-	case IDE6_MAJOR:
-	case IDE7_MAJOR:
-	case IDE8_MAJOR:
-	case IDE9_MAJOR:
-	case SCSI_DISK0_MAJOR:
-	case SCSI_DISK1_MAJOR:
-	case SCSI_DISK2_MAJOR:
-	case SCSI_DISK3_MAJOR:
-	case SCSI_DISK4_MAJOR:
-	case SCSI_DISK5_MAJOR:
-	case SCSI_DISK6_MAJOR:
-	case SCSI_DISK7_MAJOR:
-	case XT_DISK_MAJOR:
-		return 1;
-	default:
-		return 0;
-	}
-}
-
-/* do_emergency_sync helper function */
-static void go_sync(struct super_block *sb, int remount_flag)
-{
-	int orig_loglevel;
-	orig_loglevel = console_loglevel;
-	console_loglevel = 7;
-	printk(KERN_INFO "%sing device %s ... ",
-	       remount_flag ? "Remount" : "Sync",
-	       sb->s_id);
-
-	if (remount_flag) { /* Remount R/O */
-		int ret, flags;
-		struct file *file;
-
-		if (sb->s_flags & MS_RDONLY) {
-			printk("R/O\n");
-			return;
-		}
-
-		file_list_lock();
-		list_for_each_entry(file, &sb->s_files, f_list) {
-			if (file->f_dentry && file_count(file)
-				&& S_ISREG(file->f_dentry->d_inode->i_mode))
-				file->f_mode &= ~2;
-		}
-		file_list_unlock();
-		DQUOT_OFF(sb);
-		fsync_bdev(sb->s_bdev);
-		flags = MS_RDONLY;
-		if (sb->s_op && sb->s_op->remount_fs) {
-			ret = sb->s_op->remount_fs(sb, &flags, NULL);
-			if (ret)
-				printk("error %d\n", ret);
-			else {
-				sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
-				printk("OK\n");
-			}
-		} else
-			printk("nothing to do\n");
-	} else { /* Sync only */
-		fsync_bdev(sb->s_bdev);
-		printk("OK\n");
-	}
-	console_loglevel = orig_loglevel;
-}
-/*
- * Emergency Sync or Unmount. We cannot do it directly, so we set a special
- * flag and wake up the bdflush kernel thread which immediately calls this function.
- * We process all mounted hard drives first to recover from crashed experimental
- * block devices and malfunctional network filesystems.
- */
-
-int emergency_sync_scheduled;
-
-void do_emergency_sync(void) {
-	struct super_block *sb;
-	int remount_flag;
-	int orig_loglevel;
-
-	lock_kernel();
-	remount_flag = (emergency_sync_scheduled == EMERG_REMOUNT);
-	emergency_sync_scheduled = 0;
-
-	list_for_each_entry(sb, &super_blocks, s_list)
-		if (sb->s_bdev && is_local_disk(sb->s_bdev))
-			go_sync(sb, remount_flag);
-
-	list_for_each_entry(sb, &super_blocks, s_list)
-		if (sb->s_bdev && !is_local_disk(sb->s_bdev))
-			go_sync(sb, remount_flag);
-
-	unlock_kernel();
-
-	orig_loglevel = console_loglevel;
-	console_loglevel = 7;
-	printk(KERN_INFO "Done.\n");
-	console_loglevel = orig_loglevel;
-}
-
 static void sysrq_handle_sync(int key, struct pt_regs *pt_regs,
 			      struct tty_struct *tty) 
 {
-	emergency_sync_scheduled = EMERG_SYNC;
-	wakeup_bdflush(0);
+	emergency_sync();
 }
+
 static struct sysrq_key_op sysrq_sync_op = {
 	.handler	= sysrq_handle_sync,
 	.help_msg	= "Sync",
@@ -235,9 +123,9 @@
 static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
 				 struct tty_struct *tty) 
 {
-	emergency_sync_scheduled = EMERG_REMOUNT;
-	wakeup_bdflush(0);
+	emergency_remount();
 }
+
 static struct sysrq_key_op sysrq_mountro_op = {
 	.handler	= sysrq_handle_mountro,
 	.help_msg	= "Unmount",
diff -urN linux-2.5.69-bk2/drivers/char/tipar.c linux-2.5.69-bk3/drivers/char/tipar.c
--- linux-2.5.69-bk2/drivers/char/tipar.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/tipar.c	2003-05-08 04:38:18.000000000 -0700
@@ -421,8 +421,6 @@
 static int
 tipar_register(int nr, struct parport *port)
 {
-	char name[32];
-
 	/* Register our module into parport */
 	table[nr].dev = parport_register_device(port, "tipar",
 						NULL, NULL, NULL, 0,
@@ -432,13 +430,9 @@
 		return 1;
 
 	/* Use devfs, tree: /dev/ticables/par/[0..2] */
-	sprintf(name, "ticables/par/%d", nr);
-	printk
-	    ("tipar: registering to devfs : major = %d, minor = %d, node = %s\n",
-	     TISER_MAJOR, (TIPAR_MINOR + nr), name);
-	devfs_register(NULL, name, DEVFS_FL_DEFAULT, TIPAR_MAJOR,
-		       TIPAR_MINOR + nr, S_IFCHR | S_IRUGO | S_IWUGO,
-		       &tipar_fops, NULL);
+	devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr),
+			S_IFCHR | S_IRUGO | S_IWUGO,
+			"ticables/par/%d", nr);
 
 	/* Display informations */
 	printk(KERN_INFO "tipar%d: using %s (%s).\n", nr, port->name,
diff -urN linux-2.5.69-bk2/drivers/char/tpqic02.c linux-2.5.69-bk3/drivers/char/tpqic02.c
--- linux-2.5.69-bk2/drivers/char/tpqic02.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/tpqic02.c	2003-05-08 04:38:18.000000000 -0700
@@ -2694,38 +2694,27 @@
 #endif
 		return -ENODEV;
 	}
-	devfs_register(NULL, "ntpqic11", DEVFS_FL_DEFAULT,
-		       QIC02_TAPE_MAJOR, 2,
-		       S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
-		       &qic02_tape_fops, NULL);
-	devfs_register(NULL, "tpqic11", DEVFS_FL_DEFAULT,
-		       QIC02_TAPE_MAJOR, 3,
-		       S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
-		       &qic02_tape_fops, NULL);
-	devfs_register(NULL, "ntpqic24", DEVFS_FL_DEFAULT,
-		       QIC02_TAPE_MAJOR, 4,
-		       S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
-		       &qic02_tape_fops, NULL);
-	devfs_register(NULL, "tpqic24", DEVFS_FL_DEFAULT,
-		       QIC02_TAPE_MAJOR, 5,
-		       S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
-		       &qic02_tape_fops, NULL);
-	devfs_register(NULL, "ntpqic120", DEVFS_FL_DEFAULT,
-		       QIC02_TAPE_MAJOR, 6,
-		       S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
-		       &qic02_tape_fops, NULL);
-	devfs_register(NULL, "tpqic120", DEVFS_FL_DEFAULT,
-		       QIC02_TAPE_MAJOR, 7,
-		       S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
-		       &qic02_tape_fops, NULL);
-	devfs_register(NULL, "ntpqic150", DEVFS_FL_DEFAULT,
-		       QIC02_TAPE_MAJOR, 8,
-		       S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
-		       &qic02_tape_fops, NULL);
-	devfs_register(NULL, "tpqic150", DEVFS_FL_DEFAULT,
-		       QIC02_TAPE_MAJOR, 9,
-		       S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
-		       &qic02_tape_fops, NULL);
+
+	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 2),
+		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic11");
+	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 3),
+		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic11");
+
+	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 4),
+		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic24");
+	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 5),
+		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic24");
+
+	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 6),
+		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic120");
+	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 7),
+		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic120");
+
+	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 8),
+		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic150");
+	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 9),
+		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic150");
+
 	init_waitqueue_head(&qic02_tape_transfer);
 	/* prepare timer */
 	TIMEROFF;
diff -urN linux-2.5.69-bk2/drivers/char/tty_io.c linux-2.5.69-bk3/drivers/char/tty_io.c
--- linux-2.5.69-bk2/drivers/char/tty_io.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/tty_io.c	2003-05-08 04:38:18.000000000 -0700
@@ -2088,22 +2088,6 @@
 }
 
 #ifdef CONFIG_DEVFS_FS
-static void tty_register_devfs(struct tty_driver *driver, unsigned index)
-{
-	dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
-	char buf[32];
-
-	if (index >= driver->num) {
-		printk(KERN_ERR "Attempt to register invalid tty line number "
-		       "with devfs (%d).\n", index);
-		return;
-	}
-
-	tty_line_name(driver, index, buf);
-	devfs_register(NULL, buf, 0, MAJOR(dev), MINOR(dev),
-		S_IFCHR | S_IRUSR | S_IWUSR, &tty_fops, NULL);
-}
-
 static void tty_unregister_devfs(struct tty_driver *driver, int index)
 {
 	char path[64];
@@ -2111,21 +2095,131 @@
 	devfs_remove(path);
 }
 #else
-# define tty_register_devfs(driver, index)	do { } while (0)
 # define tty_unregister_devfs(driver, index)	do { } while (0)
 #endif /* CONFIG_DEVFS_FS */
 
-/*
- * Register a tty device described by <driver>, with minor number <minor>.
- */
-void tty_register_device(struct tty_driver *driver, unsigned index)
+static struct class tty_class = {
+	.name	= "tty",
+};
+
+struct tty_dev {
+	struct list_head node;
+	dev_t dev;
+	struct class_device class_dev;
+};
+#define to_tty_dev(d) container_of(d, struct tty_dev, class_dev)
+
+static LIST_HEAD(tty_dev_list);
+
+static ssize_t show_dev(struct class_device *class_dev, char *buf)
 {
-	tty_register_devfs(driver, index);
+	struct tty_dev *tty_dev = to_tty_dev(class_dev);
+	return sprintf(buf, "%04x\n", tty_dev->dev);
 }
+static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
+
+static void tty_add_class_device(char *name, dev_t dev, struct device *device)
+{
+	struct tty_dev *tty_dev = NULL;
+	char *temp;
+	int retval;
 
+	tty_dev = kmalloc(sizeof(*tty_dev), GFP_KERNEL);
+	if (!tty_dev)
+		return;
+	memset(tty_dev, 0x00, sizeof(*tty_dev));
+
+	/* stupid '/' in tty name strings... */
+	temp = strchr(name, '/');
+	if (temp && (temp[1] != 0x00))
+		++temp;
+	else
+		temp = name;
+
+	tty_dev->class_dev.dev = device;
+	tty_dev->class_dev.class = &tty_class;
+	snprintf(tty_dev->class_dev.class_id, BUS_ID_SIZE, "%s", temp);
+	retval = class_device_register(&tty_dev->class_dev);
+	if (retval)
+		goto error;
+	class_device_create_file (&tty_dev->class_dev, &class_device_attr_dev);
+	tty_dev->dev = dev;
+	list_add(&tty_dev->node, &tty_dev_list);
+	return;
+error:
+	kfree(tty_dev);
+}
+
+void tty_remove_class_device(dev_t dev)
+{
+	struct tty_dev *tty_dev = NULL;
+	struct list_head *tmp;
+	int found = 0;
+
+	list_for_each (tmp, &tty_dev_list) {
+		tty_dev = list_entry(tmp, struct tty_dev, node);
+		if ((MAJOR(tty_dev->dev) == MAJOR(dev)) &&
+		    (MINOR(tty_dev->dev) == MINOR(dev))) {
+			found = 1;
+			break;
+		}
+	}
+	if (found) {
+		list_del(&tty_dev->node);
+		class_device_unregister(&tty_dev->class_dev);
+		kfree(tty_dev);
+	}
+}
+
+/**
+ * tty_register_device - register a tty device
+ * @driver: the tty driver that describes the tty device
+ * @index: the index in the tty driver for this tty device
+ * @device: a struct device that is associated with this tty device.
+ *	This field is optional, if there is no known struct device for this
+ *	tty device it can be set to NULL safely.
+ *
+ * This call is required to be made to register an individual tty device if
+ * the tty driver's flags have the TTY_DRIVER_NO_DEVFS bit set.  If that
+ * bit is not set, this function should not be called.
+ */
+void tty_register_device(struct tty_driver *driver, unsigned index,
+			 struct device *device)
+{
+	dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
+	char name[64];
+
+	if (index >= driver->num) {
+		printk(KERN_ERR "Attempt to register invalid tty line number "
+		       " (%d).\n", index);
+		return;
+	}
+
+	tty_line_name(driver, index, name);
+	devfs_register(NULL, name, 0, MAJOR(dev), MINOR(dev),
+		S_IFCHR | S_IRUSR | S_IWUSR, &tty_fops, NULL);
+
+	/* stupid console driver devfs names... change vc/X into ttyX */
+	if (driver->type == TTY_DRIVER_TYPE_CONSOLE)
+		sprintf(name, "tty%d", MINOR(dev));
+
+	/* we don't care about the ptys */
+	if (driver->type != TTY_DRIVER_TYPE_PTY)
+		tty_add_class_device (name, dev, device);
+}
+
+/**
+ * tty_unregister_device - unregister a tty device
+ * @driver: the tty driver that describes the tty device
+ * @index: the index in the tty driver for this tty device
+ *
+ * If a tty device is registered with a call to tty_register_device() then
+ * this function must be made when the tty device is gone.
+ */
 void tty_unregister_device(struct tty_driver *driver, unsigned index)
 {
 	tty_unregister_devfs(driver, index);
+	tty_remove_class_device(MKDEV(driver->major, driver->minor_start) + index);
 }
 
 EXPORT_SYMBOL(tty_register_device);
@@ -2207,7 +2301,7 @@
 	
 	if ( !(driver->flags & TTY_DRIVER_NO_DEVFS) ) {
 		for(i = 0; i < driver->num; i++)
-		    tty_register_device(driver, i);
+		    tty_register_device(driver, i, NULL);
 	}
 	proc_tty_register_driver(driver);
 	return error;
@@ -2288,10 +2382,6 @@
 extern int vty_init(void);
 #endif
 
-static struct class tty_class = {
-	.name	= "tty",
-};
-
 static int __init tty_class_init(void)
 {
 	return class_register(&tty_class);
@@ -2308,33 +2398,29 @@
 	if (register_chrdev_region(TTYAUX_MAJOR, 0, 1,
 				   "/dev/tty", &tty_fops) < 0)
 		panic("Couldn't register /dev/tty driver\n");
-
-	devfs_register (NULL, "tty", 0, TTYAUX_MAJOR, 0,
-			S_IFCHR | S_IRUGO | S_IWUGO, &tty_fops, NULL);
+	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
+	tty_add_class_device ("tty", MKDEV(TTYAUX_MAJOR, 0), NULL);
 
 	if (register_chrdev_region(TTYAUX_MAJOR, 1, 1,
 				   "/dev/console", &tty_fops) < 0)
 		panic("Couldn't register /dev/console driver\n");
-
-	devfs_register (NULL, "console", 0, TTYAUX_MAJOR, 1,
-			S_IFCHR | S_IRUSR | S_IWUSR, &tty_fops, NULL);
+	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
+	tty_add_class_device ("console", MKDEV(TTYAUX_MAJOR, 1), NULL);
 
 #ifdef CONFIG_UNIX98_PTYS
 	if (register_chrdev_region(TTYAUX_MAJOR, 2, 1,
 				   "/dev/ptmx", &tty_fops) < 0)
 		panic("Couldn't register /dev/ptmx driver\n");
-
-	devfs_register (NULL, "ptmx", 0, TTYAUX_MAJOR, 2,
-			S_IFCHR | S_IRUGO | S_IWUGO, &tty_fops, NULL);
+	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
+	tty_add_class_device ("ptmx", MKDEV(TTYAUX_MAJOR, 2), NULL);
 #endif
 	
 #ifdef CONFIG_VT
 	if (register_chrdev_region(TTY_MAJOR, 0, 1,
 				   "/dev/vc/0", &tty_fops) < 0)
 		panic("Couldn't register /dev/tty0 driver\n");
-
-	devfs_register (NULL, "vc/0", 0, TTY_MAJOR, 0,
-			S_IFCHR | S_IRUSR | S_IWUSR, &tty_fops, NULL);
+	devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0");
+	tty_add_class_device ("tty0", MKDEV(TTY_MAJOR, 0), NULL);
 
 	vty_init();
 #endif
diff -urN linux-2.5.69-bk2/drivers/char/vc_screen.c linux-2.5.69-bk3/drivers/char/vc_screen.c
--- linux-2.5.69-bk2/drivers/char/vc_screen.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/vc_screen.c	2003-05-08 04:38:18.000000000 -0700
@@ -469,40 +469,27 @@
 	.open		= vcs_open,
 };
 
-void vcs_make_devfs (unsigned int index, int unregister)
+void vcs_make_devfs(struct tty_struct *tty)
 {
-#ifdef CONFIG_DEVFS_FS
-
-	if (unregister) {
-		devfs_remove("vcc/%u", index + 1);
-		devfs_remove("vcc/a%u", index + 1);
-	} else {
-		char name[16];
-		sprintf(name, "vcc/%u", index + 1);
-		devfs_register(NULL, name, DEVFS_FL_DEFAULT,
-				VCS_MAJOR, index + 1,
-				S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL);
-		sprintf(name, "vcc/a%u", index + 1);
-		devfs_register(NULL, name, DEVFS_FL_DEFAULT,
-				VCS_MAJOR, index + 129,
-				S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL);
-	}
-#endif /* CONFIG_DEVFS_FS */
+	devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 1),
+			S_IFCHR|S_IRUSR|S_IWUSR,
+			"vcc/%u", tty->index + 1);
+	devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129),
+			S_IFCHR|S_IRUSR|S_IWUSR,
+			"vcc/a%u", tty->index + 1);
+}
+void vcs_remove_devfs(struct tty_struct *tty)
+{
+	devfs_remove("vcc/%u", tty->index + 1);
+	devfs_remove("vcc/a%u", tty->index + 1);
 }
 
 int __init vcs_init(void)
 {
-	int error;
-
-	error = register_chrdev(VCS_MAJOR, "vcs", &vcs_fops);
-
-	if (error)
-		printk("unable to get major %d for vcs device", VCS_MAJOR);
-
-	devfs_register(NULL, "vcc/0", DEVFS_FL_DEFAULT, VCS_MAJOR, 0,
-			S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL);
-	devfs_register(NULL, "vcc/a", DEVFS_FL_DEFAULT, VCS_MAJOR, 128,
-			S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL);
+	if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
+		panic("unable to get major %d for vcs device", VCS_MAJOR);
 
-	return error;
+	devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0");
+	devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0");
+	return 0;
 }
diff -urN linux-2.5.69-bk2/drivers/char/vme_scc.c linux-2.5.69-bk3/drivers/char/vme_scc.c
--- linux-2.5.69-bk2/drivers/char/vme_scc.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/vme_scc.c	2003-05-08 04:38:18.000000000 -0700
@@ -129,6 +129,7 @@
 
 	memset(&scc_driver, 0, sizeof(scc_driver));
 	scc_driver.magic = TTY_DRIVER_MAGIC;
+	scc_driver.owner = THIS_MODULE;
 	scc_driver.driver_name = "scc";
 #ifdef CONFIG_DEVFS_FS
 	scc_driver.name = "tts/";
@@ -795,7 +796,6 @@
 {
 	scc_disable_tx_interrupts(ptr);
 	scc_disable_rx_interrupts(ptr);
-	MOD_DEC_USE_COUNT;
 }
 
 
@@ -803,7 +803,6 @@
 {
 	scc_disable_tx_interrupts(ptr);
 	scc_disable_rx_interrupts(ptr);
-	MOD_DEC_USE_COUNT;
 }
 
 
@@ -938,13 +937,9 @@
 		return retval;
 	}
 	port->gs.flags |= GS_ACTIVE;
-	if (port->gs.count == 1) {
-		MOD_INC_USE_COUNT;
-	}
 	retval = gs_block_til_ready(port, filp);
 
 	if (retval) {
-		MOD_DEC_USE_COUNT;
 		port->gs.count--;
 		return retval;
 	}
diff -urN linux-2.5.69-bk2/drivers/char/vt.c linux-2.5.69-bk3/drivers/char/vt.c
--- linux-2.5.69-bk2/drivers/char/vt.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk3/drivers/char/vt.c	2003-05-08 04:38:18.000000000 -0700
@@ -124,7 +124,9 @@
 #define DEFAULT_BELL_PITCH	750
 #define DEFAULT_BELL_DURATION	(HZ/8)
 
-extern void vcs_make_devfs (unsigned int index, int unregister);
+extern void vcs_make_devfs(struct tty_struct *tty);
+extern void vcs_remove_devfs(struct tty_struct *tty);
+
 extern void console_map_init(void);
 #ifdef CONFIG_PROM_CONSOLE
 extern void prom_con_init(void);
@@ -158,7 +160,6 @@
 static void hide_cursor(int currcons);
 static void unblank_screen_t(unsigned long dummy);
 static void console_callback(void *ignored);
-static void __init con_init_devfs (void);
 
 static int printable;		/* Is console ready for printing? */
 
@@ -2410,7 +2411,7 @@
 		tty->winsize.ws_col = video_num_columns;
 	}
 	if (tty->count == 1)
-		vcs_make_devfs (currcons, 0);
+		vcs_make_devfs(tty);
 	return 0;
 }
 
@@ -2418,10 +2419,10 @@
 {
 	struct vt_struct *vt;
 	
-	if (!tty)
+	if (!tty || tty->count != 1)
 		return;
-	if (tty->count != 1) return;
-	vcs_make_devfs (tty->index, 1);
+
+	vcs_remove_devfs(tty);
 	vt = (struct vt_struct*)tty->driver_data;
 	if (vt)
 		vc_cons[vt->vc_num].d->vc_tty = NULL;
@@ -2525,11 +2526,6 @@
 	console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
 	console_driver.init_termios = tty_std_termios;
 	console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
-	/* Tell tty_register_driver() to skip consoles because they are
-	 * registered before kmalloc() is ready. We'll patch them in later. 
-	 * See comments at console_init(); see also con_init_devfs(). 
-	 */
-	console_driver.flags |= TTY_DRIVER_NO_DEVFS;
 	console_driver.refcount = &console_refcount;
 	console_driver.table = console_table;
 	console_driver.termios = console_termios;
@@ -2562,7 +2558,6 @@
 #ifdef CONFIG_FRAMEBUFFER_CONSOLE
 	fb_console_init();
 #endif	
-	con_init_devfs();
 	vcs_init();
 	return 0;
 }
@@ -2657,18 +2652,6 @@
     vesa_blank_mode = (mode < 4) ? mode : 0;
 }
 
-/* We can't register the console with devfs during con_init(), because it
- * is called before kmalloc() works.  This function is called later to
- * do the registration.
- */
-static void __init con_init_devfs (void)
-{
-	int i;
-
-	for (i = 0; i < console_driver.num; i++)
-		tty_register_device (&console_driver, i);
-}
-
 /*
  * This is called by a timer handler
  */
diff -urN linux-2.5.69-bk2/drivers/i2c/i2c-dev.c linux-2.5.69-bk3/drivers/i2c/i2c-dev.c
--- linux-2.5.69-bk2/drivers/i2c/i2c-dev.c	2003-05-08 04:38:12.000000000 -0700
+++ linux-2.5.69-bk3/drivers/i2c/i2c-dev.c	2003-05-08 04:38:18.000000000 -0700
@@ -372,16 +372,11 @@
 
 int i2cdev_attach_adapter(struct i2c_adapter *adap)
 {
-	char name[12];
 	int i;
 
 	i = i2c_adapter_id(adap);
-	sprintf (name, "i2c/%d", i);
-
-	devfs_register (NULL, name,
-			DEVFS_FL_DEFAULT, I2C_MAJOR, i,
-			S_IFCHR | S_IRUSR | S_IWUSR,
-			&i2cdev_fops, NULL);
+	devfs_mk_cdev(MKDEV(I2C_MAJOR, i),
+			S_IFCHR|S_IRUSR|S_IWUSR, "i2c/%d", i);
 	dev_dbg(&adap->dev, "Registered as minor %d\n", i);
 	return 0;
 }
diff -urN linux-2.5.69-bk2/drivers/ide/ide-tape.c linux-2.5.69-bk3/drivers/ide/ide-tape.c
--- linux-2.5.69-bk2/drivers/ide/ide-tape.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk3/drivers/ide/ide-tape.c	2003-05-08 04:38:18.000000000 -0700
@@ -6292,11 +6292,9 @@
 
 	devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor)
 			S_IFCHR | S_IRUGO | S_IWUGO,
-			&idetape_fops, NULL,
 			"%s/mt", drive->devfs_name);
 	devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor + 128),
 			S_IFCHR | S_IRUGO | S_IWUGO,
-			&idetape_fops, NULL,
 			"%s/mtn", drive->devfs_name);
 
 	drive->disk->number = devfs_register_tape(drive->devfs_name);
diff -urN linux-2.5.69-bk2/drivers/ieee1394/amdtp.c linux-2.5.69-bk3/drivers/ieee1394/amdtp.c
--- linux-2.5.69-bk2/drivers/ieee1394/amdtp.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/drivers/ieee1394/amdtp.c	2003-05-08 04:38:18.000000000 -0700
@@ -1205,7 +1205,6 @@
 {
 	struct amdtp_host *ah;
 	int minor;
-	char name[16];
 
 	if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME) != 0)
 		return;
@@ -1223,13 +1222,11 @@
 
 	minor = IEEE1394_MINOR_BLOCK_AMDTP * 16 + ah->ohci->id;
 
-	sprintf(name, "amdtp/%d", ah->ohci->id);
-
 	INIT_LIST_HEAD(&ah->stream_list);
 	spin_lock_init(&ah->stream_list_lock);
 
-	devfs_register(NULL, name, 0, IEEE1394_MAJOR, minor,
-		       S_IFCHR | S_IRUSR | S_IWUSR, &amdtp_fops, NULL);
+	devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
+			S_IFCHR|S_IRUSR|S_IWUSR, "amdtp/%d", ah->ohci->id);
 }
 
 static void amdtp_remove_host(struct hpsb_host *host)
diff -urN linux-2.5.69-bk2/drivers/ieee1394/dv1394.c linux-2.5.69-bk3/drivers/ieee1394/dv1394.c
--- linux-2.5.69-bk2/drivers/ieee1394/dv1394.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/drivers/ieee1394/dv1394.c	2003-05-08 04:38:18.000000000 -0700
@@ -2420,24 +2420,6 @@
 };
 
 
-#ifdef CONFIG_DEVFS_FS
-static int dv1394_devfs_add_entry(struct video_card *video)
-{
-	char buf[64];
-
-	snprintf(buf, sizeof(buf), "ieee1394/dv/host%d/%s/%s",
-		(video->id>>2),
-		(video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
-		(video->mode == MODE_RECEIVE ? "in" : "out"));
-
-	devfs_register(NULL, buf, 0, IEEE1394_MAJOR,
-			IEEE1394_MINOR_BLOCK_DV1394*16 + video->id,
-			S_IFCHR | S_IRUGO | S_IWUGO, &dv1394_fops, video);
-	return 0;
-}
-#endif /* CONFIG_DEVFS_FS */
-
-
 /*** HOTPLUG STUFF **********************************************************/
 /*
  * Export information about protocols/devices supported by this driver.
@@ -2536,10 +2518,14 @@
 	list_add_tail(&video->list, &dv1394_cards);
 	spin_unlock_irqrestore(&dv1394_cards_lock, flags);
 	
-#ifdef CONFIG_DEVFS_FS
-	if (dv1394_devfs_add_entry(video) < 0)
+	if (devfs_mk_cdev(MKDEV(IEEE1394_MAJOR,
+				IEEE1394_MINOR_BLOCK_DV1394*16 + video->id),
+			S_IFCHR|S_IRUGO|S_IWUGO,
+			 "ieee1394/dv/host%d/%s/%s",
+			 (video->id>>2),
+			 (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
+			 (video->mode == MODE_RECEIVE ? "in" : "out")) < 0)
 			goto err_free;
-#endif
 
 	debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id);
 	
@@ -2562,9 +2548,7 @@
 		(video->mode == MODE_RECEIVE ? "in" : "out")
 		);
 
-#ifdef CONFIG_DEVFS_FS
 	devfs_remove("ieee1394/%s", buf);
-#endif
 #ifdef CONFIG_PROC_FS
 	dv1394_procfs_del(buf);
 #endif
@@ -2602,11 +2586,9 @@
 
 	n = (video->id >> 2);
 
-#ifdef CONFIG_DEVFS_FS
 	devfs_remove("ieee1394/dv/host%d/NTSC", n);
 	devfs_remove("ieee1394/dv/host%d/PAL", n);
 	devfs_remove("ieee1394/dv/host%d", n);
-#endif
 
 #ifdef CONFIG_PROC_FS
 	snprintf(buf, sizeof(buf), "dv/host%d/NTSC", n);
@@ -2642,11 +2624,9 @@
 }
 #endif
 
-#ifdef CONFIG_DEVFS_FS
 	devfs_mk_dir("ieee1394/dv/host%d", ohci->id);
 	devfs_mk_dir("ieee1394/dv/host%d/NTSC", ohci->id);
 	devfs_mk_dir("ieee1394/dv/host%d/PAL", ohci->id);
-#endif
 	
 	dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
 	dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
@@ -2901,9 +2881,7 @@
 
 	hpsb_unregister_highlevel(&dv1394_highlevel);
 	ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
-#ifdef CONFIG_DEVFS_FS
 	devfs_remove("ieee1394/dv");
-#endif
 #ifdef CONFIG_PROC_FS
 	dv1394_procfs_del("dv");
 #endif
@@ -2920,18 +2898,14 @@
 		return -EIO;
 	}
 
-#ifdef CONFIG_DEVFS_FS
 	devfs_mk_dir("ieee1394/dv");
-#endif
 
 #ifdef CONFIG_PROC_FS
 	ret = dv1394_procfs_add_dir("dv",NULL,NULL);
 	if (ret < 0) {
 		printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/dv\n");
 		ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
-#ifdef CONFIG_DEVFS_FS
 		devfs_remove("ieee1394/dv");
-#endif
 		return -ENOMEM;
 	}
 #endif
diff -urN linux-2.5.69-bk2/drivers/ieee1394/raw1394.c linux-2.5.69-bk3/drivers/ieee1394/raw1394.c
--- linux-2.5.69-bk2/drivers/ieee1394/raw1394.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk3/drivers/ieee1394/raw1394.c	2003-05-08 04:38:18.000000000 -0700
@@ -2531,9 +2531,8 @@
 {
 	hpsb_register_highlevel(&raw1394_highlevel);
 
-        devfs_register(NULL, RAW1394_DEVICE_NAME, 0,
-			IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16,
-			S_IFCHR | S_IRUSR | S_IWUSR, &file_ops, NULL);
+        devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
+			S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
 
         if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_RAW1394,
                                       THIS_MODULE, &file_ops)) {
diff -urN linux-2.5.69-bk2/drivers/ieee1394/video1394.c linux-2.5.69-bk3/drivers/ieee1394/video1394.c
--- linux-2.5.69-bk2/drivers/ieee1394/video1394.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk3/drivers/ieee1394/video1394.c	2003-05-08 04:38:18.000000000 -0700
@@ -1257,7 +1257,6 @@
 static void video1394_add_host (struct hpsb_host *host)
 {
 	struct ti_ohci *ohci;
-	char name[16];
 	int minor;
 
 	/* We only work with the OHCI-1394 driver */
@@ -1274,12 +1273,10 @@
 	hpsb_set_hostinfo(&video1394_highlevel, host, ohci);
 	hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->id);
 
-	sprintf(name, "%s/%d", VIDEO1394_DRIVER_NAME, ohci->id);
-	minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->id;
-	devfs_register(NULL, name, 0, IEEE1394_MAJOR, minor,
-		       S_IFCHR | S_IRUSR | S_IWUSR, &video1394_fops, NULL);
-
-	return;
+	minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->id; 
+	devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
+		       S_IFCHR | S_IRUSR | S_IWUSR,
+		       "%s/%d", VIDEO1394_DRIVER_NAME, ohci->id);
 }
 
 
diff -urN linux-2.5.69-bk2/drivers/input/evdev.c linux-2.5.69-bk3/drivers/input/evdev.c
--- linux-2.5.69-bk2/drivers/input/evdev.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/drivers/input/evdev.c	2003-05-08 04:38:18.000000000 -0700
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
+#include <linux/major.h>
 #include <linux/smp_lock.h>
 #include <linux/device.h>
 #include <linux/devfs_fs_kernel.h>
@@ -400,7 +401,9 @@
 	sprintf(evdev->name, "event%d", minor);
 
 	evdev_table[minor] = evdev;
-	input_register_minor("input/event%d", minor, EVDEV_MINOR_BASE);
+
+	devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
+			S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor);
 
 	return &evdev->handle;
 }
diff -urN linux-2.5.69-bk2/drivers/input/input.c linux-2.5.69-bk3/drivers/input/input.c
--- linux-2.5.69-bk2/drivers/input/input.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk3/drivers/input/input.c	2003-05-08 04:38:18.000000000 -0700
@@ -16,6 +16,7 @@
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/random.h>
+#include <linux/major.h>
 #include <linux/pm.h>
 #include <linux/proc_fs.h>
 #include <linux/kmod.h>
@@ -32,7 +33,6 @@
 EXPORT_SYMBOL(input_unregister_device);
 EXPORT_SYMBOL(input_register_handler);
 EXPORT_SYMBOL(input_unregister_handler);
-EXPORT_SYMBOL(input_register_minor);
 EXPORT_SYMBOL(input_open_device);
 EXPORT_SYMBOL(input_close_device);
 EXPORT_SYMBOL(input_accept_process);
@@ -40,7 +40,6 @@
 EXPORT_SYMBOL(input_event);
 EXPORT_SYMBOL(input_class);
 
-#define INPUT_MAJOR	13
 #define INPUT_DEVICES	256
 
 static LIST_HEAD(input_dev_list);
@@ -541,15 +540,6 @@
 	.open = input_open_file,
 };
 
-void input_register_minor(char *name, int minor, int minor_base)
-{
-	char devfs_name[16];
-
-	sprintf(devfs_name, name, minor);
-	devfs_register(NULL, devfs_name, 0, INPUT_MAJOR, minor_base + minor,
-			S_IFCHR|S_IRUGO|S_IWUSR, &input_fops, NULL);
-}
-
 #ifdef CONFIG_PROC_FS
 
 #define SPRINTF_BIT_B(bit, name, max) \
diff -urN linux-2.5.69-bk2/drivers/input/joydev.c linux-2.5.69-bk3/drivers/input/joydev.c
--- linux-2.5.69-bk2/drivers/input/joydev.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk3/drivers/input/joydev.c	2003-05-08 04:38:18.000000000 -0700
@@ -445,7 +445,9 @@
 	}
 
 	joydev_table[minor] = joydev;
-	input_register_minor("js%d", minor, JOYDEV_MINOR_BASE);
+	
+	devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
+			S_IFCHR|S_IRUGO|S_IWUSR, "js%d", minor);
 
 	return &joydev->handle;
 }
diff -urN linux-2.5.69-bk2/drivers/input/mousedev.c linux-2.5.69-bk3/drivers/input/mousedev.c
--- linux-2.5.69-bk2/drivers/input/mousedev.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk3/drivers/input/mousedev.c	2003-05-08 04:38:18.000000000 -0700
@@ -432,7 +432,9 @@
 		input_open_device(&mousedev->handle);
 
 	mousedev_table[minor] = mousedev;
-	input_register_minor("input/mouse%d", minor, MOUSEDEV_MINOR_BASE);
+
+	devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
+			S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor);
 
 	return &mousedev->handle;
 }
@@ -502,7 +504,10 @@
 	mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
 	mousedev_mix.exist = 1;
 	mousedev_mix.minor = MOUSEDEV_MIX;
-	input_register_minor("input/mice", MOUSEDEV_MIX, MOUSEDEV_MINOR_BASE);
+
+	devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
+			S_IFCHR|S_IRUGO|S_IWUSR, "input/mice");
+
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
 	if (!(mousedev_mix.misc = !misc_register(&psaux_mouse)))
diff -urN linux-2.5.69-bk2/drivers/input/serio/i8042.c linux-2.5.69-bk3/drivers/input/serio/i8042.c
--- linux-2.5.69-bk2/drivers/input/serio/i8042.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk3/drivers/input/serio/i8042.c	2003-05-08 04:38:18.000000000 -0700
@@ -62,6 +62,12 @@
 static unsigned char i8042_mux_open;
 struct timer_list i8042_timer;
 
+/*
+ * Shared IRQ's require a device pointer, but this driver doesn't support
+ * multiple devices
+ */
+#define i8042_request_irq_cookie (&i8042_timer)
+
 static unsigned long i8042_unxlate_seen[256 / BITS_PER_LONG];
 static unsigned char i8042_unxlate_table[128] = {
 	  0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
@@ -235,7 +241,8 @@
 		if (i8042_mux_open++)
 			return 0;
 
-	if (request_irq(values->irq, i8042_interrupt, 0, "i8042", NULL)) {
+	if (request_irq(values->irq, i8042_interrupt,
+			SA_SHIRQ, "i8042", i8042_request_irq_cookie)) {
 		printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", values->irq, values->name);
 		values->exists = 0;
 		serio_unregister_port(port);
@@ -275,7 +282,7 @@
 		return;
 	}
 
-	free_irq(values->irq, NULL);
+	free_irq(values->irq, i8042_request_irq_cookie);
 
 	i8042_flush();
 }
@@ -572,9 +579,10 @@
  * Check if AUX irq is available.
  */
 
-	if (request_irq(values->irq, i8042_interrupt, 0, "i8042", NULL))
+	if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ,
+				"i8042", i8042_request_irq_cookie))
                 return -1;
-	free_irq(values->irq, NULL);
+	free_irq(values->irq, i8042_request_irq_cookie);
 
 /*
  * Get rid of bytes in the queue.
@@ -643,9 +651,10 @@
  * in trying to detect AUX presence.
  */
 
-	if (request_irq(values->irq, i8042_interrupt, 0, "i8042", NULL))
+	if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ,
+				"i8042", i8042_request_irq_cookie))
                 return -1;
-	free_irq(values->irq, NULL);
+	free_irq(values->irq, i8042_request_irq_cookie);
 
 /*
  * Get rid of bytes in the queue.
diff -urN linux-2.5.69-bk2/drivers/input/tsdev.c linux-2.5.69-bk3/drivers/input/tsdev.c
--- linux-2.5.69-bk2/drivers/input/tsdev.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk3/drivers/input/tsdev.c	2003-05-08 04:38:18.000000000 -0700
@@ -36,6 +36,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
+#include <linux/major.h>
 #include <linux/config.h>
 #include <linux/smp_lock.h>
 #include <linux/random.h>
@@ -329,8 +330,9 @@
 	tsdev->handle.private = tsdev;
 
 	tsdev_table[minor] = tsdev;
-	input_register_minor("input/ts%d", minor, TSDEV_MINOR_BASE);
-
+	
+	devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
+			S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor);
 
 	return &tsdev->handle;
 }
diff -urN linux-2.5.69-bk2/drivers/isdn/capi/capi.c linux-2.5.69-bk3/drivers/isdn/capi/capi.c
--- linux-2.5.69-bk2/drivers/isdn/capi/capi.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk3/drivers/isdn/capi/capi.c	2003-05-08 04:38:18.000000000 -0700
@@ -200,10 +200,8 @@
 	unsigned int minor = 0;
 	unsigned long flags;
   
-  	MOD_INC_USE_COUNT;
 	mp = kmalloc(sizeof(*mp), GFP_ATOMIC);
   	if (!mp) {
-  		MOD_DEC_USE_COUNT;
   		printk(KERN_ERR "capi: can't alloc capiminor\n");
 		return 0;
 	}
@@ -249,7 +247,6 @@
 	skb_queue_purge(&mp->outqueue);
 	capiminor_del_all_ack(mp);
 	kfree(mp);
-	MOD_DEC_USE_COUNT;
 }
 
 struct capiminor *capiminor_find(unsigned int minor)
@@ -1280,6 +1277,7 @@
 	
 	memset(drv, 0, sizeof(struct tty_driver));
 	drv->magic = TTY_DRIVER_MAGIC;
+	drv->owner = THIS_MODULE;
 	drv->driver_name = "capi_nc";
 	drv->name = "capi/";
 	drv->major = capi_ttymajor;
@@ -1460,7 +1458,6 @@
 	char *p;
 	char *compileinfo;
 
-	MOD_INC_USE_COUNT;
 
 	if ((p = strchr(revision, ':')) != 0 && p[1]) {
 		strncpy(rev, p + 2, sizeof(rev));
@@ -1472,19 +1469,17 @@
 
 	if (register_chrdev(capi_major, "capi20", &capi_fops)) {
 		printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
-		MOD_DEC_USE_COUNT;
 		return -EIO;
 	}
 
-	devfs_register (NULL, "isdn/capi20", DEVFS_FL_DEFAULT,
-			capi_major, 0, S_IFCHR | S_IRUSR | S_IWUSR,
-			&capi_fops, NULL);
+	devfs_mk_cdev(MKDEV(capi_major, 0), S_IFCHR | S_IRUSR | S_IWUSR,
+			"isdn/capi20");
+
 	printk(KERN_NOTICE "capi20: started up with major %d\n", capi_major);
 
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 	if (capinc_tty_init() < 0) {
 		unregister_chrdev(capi_major, "capi20");
-		MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
@@ -1503,7 +1498,6 @@
 	printk(KERN_NOTICE "capi20: Rev %s: started up with major %d%s\n",
 				rev, capi_major, compileinfo);
 
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
diff -urN linux-2.5.69-bk2/drivers/isdn/hardware/eicon/divamnt.c linux-2.5.69-bk3/drivers/isdn/hardware/eicon/divamnt.c
--- linux-2.5.69-bk2/drivers/isdn/hardware/eicon/divamnt.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk3/drivers/isdn/hardware/eicon/divamnt.c	2003-05-08 04:38:18.000000000 -0700
@@ -420,10 +420,8 @@
 		       DRIVERLNAME);
 		return (0);
 	}
-	devfs_register(NULL, "DivasMAINT", DEVFS_FL_DEFAULT, major, 0,
-		       S_IFCHR | S_IRUSR | S_IWUSR, &divas_maint_fops,
-		       NULL);
 
+	devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, DivasMAINT);
 	return (1);
 }
 
diff -urN linux-2.5.69-bk2/drivers/isdn/hardware/eicon/divasi.c linux-2.5.69-bk3/drivers/isdn/hardware/eicon/divasi.c
--- linux-2.5.69-bk2/drivers/isdn/hardware/eicon/divasi.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk3/drivers/isdn/hardware/eicon/divasi.c	2003-05-08 04:38:18.000000000 -0700
@@ -179,10 +179,8 @@
 		       DRIVERLNAME);
 		return (0);
 	}
-	devfs_register(NULL, "DivasIDI", DEVFS_FL_DEFAULT, major, 0,
-		       S_IFCHR | S_IRUSR | S_IWUSR, &divas_idi_fops,
-		       NULL);
 
+	devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, "DivasIDI");
 	return (1);
 }
 
diff -urN linux-2.5.69-bk2/drivers/isdn/hardware/eicon/divasmain.c linux-2.5.69-bk3/drivers/isdn/hardware/eicon/divasmain.c
--- linux-2.5.69-bk2/drivers/isdn/hardware/eicon/divasmain.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk3/drivers/isdn/hardware/eicon/divasmain.c	2003-05-08 04:38:18.000000000 -0700
@@ -788,9 +788,8 @@
 		       DRIVERLNAME);
 		return (0);
 	}
-	devfs_register(NULL, "Divas", DEVFS_FL_DEFAULT, major, 0,
-		       S_IFCHR | S_IRUSR | S_IWUSR, &divas_fops, NULL);
 
+	devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, "Divas");
 	return (1);
 }
 
diff -urN linux-2.5.69-bk2/drivers/isdn/i4l/isdn_common.c linux-2.5.69-bk3/drivers/isdn/i4l/isdn_common.c
--- linux-2.5.69-bk2/drivers/isdn/i4l/isdn_common.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk3/drivers/isdn/i4l/isdn_common.c	2003-05-08 04:38:18.000000000 -0700
@@ -37,9 +37,6 @@
 static void isdn_lock_driver(struct isdn_driver *drv);
 static void isdn_unlock_driver(struct isdn_driver *drv);
 
-static void isdn_register_devfs(int);
-static void isdn_unregister_devfs(int);
-
 /* ====================================================================== */
 
 /* Description of hardware-level-driver */
@@ -2157,86 +2154,38 @@
 	return max;
 }
 
-/*
- *****************************************************************************
- * And now the modules code.
- *****************************************************************************
- */
-
-#ifdef CONFIG_DEVFS_FS
-
-static void isdn_register_devfs(int k)
-{
-	char buf[16];
-
-	sprintf (buf, "isdn/isdnctrl%d", k);
-	devfs_register(NULL, buf, DEVFS_FL_DEFAULT,
-		       ISDN_MAJOR, ISDN_MINOR_CTRL + k, 0600 | S_IFCHR,
-		       &isdn_fops, NULL);
-}
-
-static void isdn_unregister_devfs(int k)
+static void isdn_init_devfs(void)
 {
-	devfs_remove("isdn/isdnctrl%d", k);
-}
+	devfs_mk_dir("isdn");
 
-static void isdn_init_devfs(void)
+#ifdef CONFIG_ISDN_PPP
 {
-#  ifdef CONFIG_ISDN_PPP
 	int i;
-#  endif
 
-	devfs_mk_dir("isdn");
-#  ifdef CONFIG_ISDN_PPP
-	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		char buf[16];
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+		devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_PPP + i),
+				0600 | S_IFCHR, "isdn/ippp%d", i);
+}
+#endif
 
-		sprintf (buf, "isdn/ippp%d", i);
-		devfs_register(NULL, buf, DEVFS_FL_DEFAULT,
-			       ISDN_MAJOR, ISDN_MINOR_PPP + i,
-			       0600 | S_IFCHR, &isdn_fops, NULL);
-	}
-#  endif
-
-	devfs_register(NULL, "isdn/isdninfo", DEVFS_FL_DEFAULT,
-		       ISDN_MAJOR, ISDN_MINOR_STATUS, 0600 | S_IFCHR,
-		       &isdn_fops, NULL);
-	devfs_register(NULL, "isdn/isdnctrl", DEVFS_FL_DEFAULT,
-		       ISDN_MAJOR, ISDN_MINOR_CTRL, 0600 | S_IFCHR, 
-		       &isdn_fops, NULL);
+	devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_STATUS),
+			0600 | S_IFCHR, "isdn/isdninfo");
+	devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_CTRL),
+			0600 | S_IFCHR, "isdn/isdnctrl");
 }
 
 static void isdn_cleanup_devfs(void)
 {
-#  ifdef CONFIG_ISDN_PPP
+#ifdef CONFIG_ISDN_PPP
 	int i;
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) 
 		devfs_remove("isdn/ippp%d", i);
-#  endif
+#endif
 	devfs_remove("isdn/isdninfo");
 	devfs_remove("isdn/isdnctrl");
 	devfs_remove("isdn");
 }
 
-#else   /* CONFIG_DEVFS_FS */
-static void isdn_register_devfs(int dummy)
-{
-}
-
-static void isdn_unregister_devfs(int dummy)
-{
-}
-
-static void isdn_init_devfs(void)
-{
-}
-
-static void isdn_cleanup_devfs(void)
-{
-}
-
-#endif  /* CONFIG_DEVFS_FS */
-
 /*
  * Allocate and initialize all data, register modem-devices
  */
diff -urN linux-2.5.69-bk2/drivers/macintosh/adb.c linux-2.5.69-bk3/drivers/macintosh/adb.c
--- linux-2.5.69-bk2/drivers/macintosh/adb.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk3/drivers/macintosh/adb.c	2003-05-08 04:38:18.000000000 -0700
@@ -896,8 +896,6 @@
 	if (register_chrdev(ADB_MAJOR, "adb", &adb_fops))
 		printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR);
 	else
-		devfs_register (NULL, "adb", DEVFS_FL_DEFAULT,
-				ADB_MAJOR, 0,
-				S_IFCHR | S_IRUSR | S_IWUSR,
-				&adb_fops, NULL);
+		devfs_mk_cdev(MKDEV(ADB_MAJOR, 0),
+				S_IFCHR | S_IRUSR | S_IWUSR, "adb");
 }
diff -urN linux-2.5.69-bk2/drivers/macintosh/macserial.c linux-2.5.69-bk3/drivers/macintosh/macserial.c
--- linux-2.5.69-bk2/drivers/macintosh/macserial.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk3/drivers/macintosh/macserial.c	2003-05-08 04:38:18.000000000 -0700
@@ -1932,7 +1932,6 @@
 	spin_lock_irqsave(&info->lock, flags);
 
 	if (tty_hung_up_p(filp)) {
-		MOD_DEC_USE_COUNT;
 		spin_unlock_irqrestore(&info->lock, flags);
 		return;
 	}
@@ -1956,7 +1955,6 @@
 		info->count = 0;
 	}
 	if (info->count) {
-		MOD_DEC_USE_COUNT;
 		spin_unlock_irqrestore(&info->lock, flags);
 		return;
 	}
@@ -2026,7 +2024,6 @@
 	info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE|
 			 ZILOG_CLOSING);
 	wake_up_interruptible(&info->close_wait);
-	MOD_DEC_USE_COUNT;
 }
 
 /*
@@ -2233,17 +2230,14 @@
 	int 			retval, line;
 	unsigned long		page;
 
-	MOD_INC_USE_COUNT;
 	line = tty->index;
 	if ((line < 0) || (line >= zs_channels_found)) {
-		MOD_DEC_USE_COUNT;
 		return -ENODEV;
 	}
 	info = zs_soft + line;
 
 #ifdef CONFIG_KGDB
 	if (info->kgdb_channel) {
-		MOD_DEC_USE_COUNT;
 		return -ENODEV;
 	}
 #endif
@@ -2610,6 +2604,7 @@
 
 	memset(&serial_driver, 0, sizeof(struct tty_driver));
 	serial_driver.magic = TTY_DRIVER_MAGIC;
+	serial_driver.owner = THIS_MODULE;
 	serial_driver.driver_name = "macserial";
 #ifdef CONFIG_DEVFS_FS
 	serial_driver.name = "tts/";
diff -urN linux-2.5.69-bk2/drivers/md/md.c linux-2.5.69-bk3/drivers/md/md.c
--- linux-2.5.69-bk2/drivers/md/md.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk3/drivers/md/md.c	2003-05-08 04:38:18.000000000 -0700
@@ -1111,8 +1111,10 @@
 
 static void print_desc(mdp_disk_t *desc)
 {
+	char b[BDEVNAME_SIZE];
+
 	printk(" DISK<N:%d,%s(%d,%d),R:%d,S:%d>\n", desc->number,
-		partition_name(MKDEV(desc->major,desc->minor)),
+		__bdevname(MKDEV(desc->major, desc->minor), b),
 		desc->major,desc->minor,desc->raid_disk,desc->state);
 }
 
@@ -1294,6 +1296,7 @@
  */
 static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_minor)
 {
+	char b[BDEVNAME_SIZE];
 	int err;
 	mdk_rdev_t *rdev;
 	sector_t size;
@@ -1301,7 +1304,7 @@
 	rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL);
 	if (!rdev) {
 		printk(KERN_ERR "md: could not alloc mem for %s!\n", 
-			partition_name(newdev));
+			__bdevname(newdev, b));
 		return ERR_PTR(-ENOMEM);
 	}
 	memset(rdev, 0, sizeof(*rdev));
@@ -1312,7 +1315,7 @@
 	err = lock_rdev(rdev, newdev);
 	if (err) {
 		printk(KERN_ERR "md: could not lock %s.\n",
-			partition_name(newdev));
+			__bdevname(newdev, b));
 		goto abort_free;
 	}
 	rdev->desc_nr = -1;
@@ -1840,6 +1843,7 @@
 
 static int autostart_array(dev_t startdev)
 {
+	char b[BDEVNAME_SIZE];
 	int err = -EINVAL, i;
 	mdp_super_t *sb = NULL;
 	mdk_rdev_t *start_rdev = NULL, *rdev;
@@ -1847,7 +1851,7 @@
 	start_rdev = md_import_device(startdev, 0, 0);
 	if (IS_ERR(start_rdev)) {
 		printk(KERN_WARNING "md: could not import %s!\n",
-			partition_name(startdev));
+			__bdevname(startdev, b));
 		return err;
 	}
 
@@ -1884,7 +1888,7 @@
 		if (IS_ERR(rdev)) {
 			printk(KERN_WARNING "md: could not import %s,"
 				" trying to run array nevertheless.\n",
-				partition_name(dev));
+				__bdevname(dev, b));
 			continue;
 		}
 		list_add(&rdev->same_set, &pending_raid_disks);
@@ -2116,6 +2120,7 @@
 
 static int hot_generate_error(mddev_t * mddev, dev_t dev)
 {
+	char b[BDEVNAME_SIZE];
 	struct request_queue *q;
 	mdk_rdev_t *rdev;
 
@@ -2123,7 +2128,7 @@
 		return -ENODEV;
 
 	printk(KERN_INFO "md: trying to generate %s error in md%d ... \n",
-		partition_name(dev), mdidx(mddev));
+		__bdevname(dev, b), mdidx(mddev));
 
 	rdev = find_rdev(mddev, dev);
 	if (!rdev) {
@@ -2151,13 +2156,14 @@
 
 static int hot_remove_disk(mddev_t * mddev, dev_t dev)
 {
+	char b[BDEVNAME_SIZE];
 	mdk_rdev_t *rdev;
 
 	if (!mddev->pers)
 		return -ENODEV;
 
 	printk(KERN_INFO "md: trying to remove %s from md%d ... \n",
-		partition_name(dev), mdidx(mddev));
+		__bdevname(dev, b), mdidx(mddev));
 
 	rdev = find_rdev(mddev, dev);
 	if (!rdev)
@@ -2178,6 +2184,7 @@
 
 static int hot_add_disk(mddev_t * mddev, dev_t dev)
 {
+	char b[BDEVNAME_SIZE];
 	int err;
 	unsigned int size;
 	mdk_rdev_t *rdev;
@@ -2186,7 +2193,7 @@
 		return -ENODEV;
 
 	printk(KERN_INFO "md: trying to hot-add %s to md%d ... \n",
-		partition_name(dev), mdidx(mddev));
+		__bdevname(dev, b), mdidx(mddev));
 
 	if (mddev->major_version != 0) {
 		printk(KERN_WARNING "md%d: HOT_ADD may only be used with"
@@ -2344,6 +2351,7 @@
 static int md_ioctl(struct inode *inode, struct file *file,
 			unsigned int cmd, unsigned long arg)
 {
+	char b[BDEVNAME_SIZE];
 	unsigned int minor;
 	int err = 0;
 	struct hd_geometry *loc = (struct hd_geometry *) arg;
@@ -2403,7 +2411,7 @@
 		err = autostart_array(arg);
 		if (err) {
 			printk(KERN_WARNING "md: autostart %s failed!\n",
-				partition_name(arg));
+				__bdevname(arg, b));
 			goto abort;
 		}
 		goto done;
@@ -3516,6 +3524,7 @@
 
 static void autostart_arrays(void)
 {
+	char b[BDEVNAME_SIZE];
 	mdk_rdev_t *rdev;
 	int i;
 
@@ -3527,7 +3536,7 @@
 		rdev = md_import_device(dev,0, 0);
 		if (IS_ERR(rdev)) {
 			printk(KERN_ALERT "md: could not import %s!\n",
-				partition_name(dev));
+				__bdevname(dev, b));
 			continue;
 		}
 		if (rdev->faulty) {
diff -urN linux-2.5.69-bk2/drivers/media/dvb/dvb-core/dvbdev.c linux-2.5.69-bk3/drivers/media/dvb/dvb-core/dvbdev.c
--- linux-2.5.69-bk2/drivers/media/dvb/dvb-core/dvbdev.c	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk3/drivers/media/dvb/dvb-core/dvbdev.c	2003-05-08 04:38:18.000000000 -0700
@@ -189,7 +189,6 @@
 			const struct dvb_device *template, void *priv, int type)
 {
 	u32 id;
-	char name [20];
 	struct dvb_device *dvbdev;
 
 	if (down_interruptible (&dvbdev_register_lock))
@@ -219,12 +218,12 @@
 
 	list_add_tail (&dvbdev->list_head, &adap->device_list);
 
-	sprintf(name, "dvb/adapter%d%s%d", adap->num, dnames[type], id);
-	devfs_register(NULL, name, 0, DVB_MAJOR, nums2minor(adap->num, type, id),
-			S_IFCHR | S_IRUSR | S_IWUSR, dvbdev->fops, dvbdev);
+	devfs_mk_cdev(MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
+			S_IFCHR | S_IRUSR | S_IWUSR,
+			"dvb/adapter%d/%s%d", adap->num, dnames[type], id);
 
-	dprintk("DVB: register adapter%d/%s @ minor: %i (0x%02x)\n",
-		adap->num, name, nums2minor(adap->num, type, id),
+	dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
+		adap->num, dnames[type], id, nums2minor(adap->num, type, id),
 		nums2minor(adap->num, type, id));
 
 	return 0;
@@ -234,7 +233,7 @@
 void dvb_unregister_device(struct dvb_device *dvbdev)
 {
 	if (dvbdev) {
-		devfs_remove("dvb/adapter%d%s%d", dvbdev->adapter->num,
+		devfs_remove("dvb/adapter%d/%s%d", dvbdev->adapter->num,
 				dnames[dvbdev->type], dvbdev->id);
 		list_del(&dvbdev->list_head);
 		kfree(dvbdev);
@@ -322,12 +321,12 @@
 int __init init_dvbdev(void)
 {
 	devfs_mk_dir("dvb");
-#ifndef CONFIG_DVB_DEVFS_ONLY
+
 	if(register_chrdev(DVB_MAJOR,"DVB", &dvb_device_fops)) {
 		printk("video_dev: unable to get major %d\n", DVB_MAJOR);
 		return -EIO;
 	}
-#endif
+
 	return 0;
 }
 
@@ -335,9 +334,7 @@
 static 
 void __exit exit_dvbdev(void)
 {
-#ifndef CONFIG_DVB_DEVFS_ONLY
 	unregister_chrdev(DVB_MAJOR, "DVB");
-#endif
         devfs_remove("dvb");
 }
 
diff -urN linux-2.5.69-bk2/drivers/media/video/cpia.c linux-2.5.69-bk3/drivers/media/video/cpia.c
--- linux-2.5.69-bk2/drivers/media/video/cpia.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk3/drivers/media/video/cpia.c	2003-05-08 04:38:19.000000000 -0700
@@ -1409,12 +1409,10 @@
 		LOG("Unable to initialise /proc/cpia\n");
 }
 
-#ifdef MODULE
-static void proc_cpia_destroy(void)
+static void __exit proc_cpia_destroy(void)
 {
 	remove_proc_entry("cpia", 0);
 }
-#endif /*MODULE*/
 #endif /* CONFIG_PROC_FS */
 
 /* ----------------------- debug functions ---------------------- */
diff -urN linux-2.5.69-bk2/drivers/media/video/videodev.c linux-2.5.69-bk3/drivers/media/video/videodev.c
--- linux-2.5.69-bk2/drivers/media/video/videodev.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk3/drivers/media/video/videodev.c	2003-05-08 04:38:19.000000000 -0700
@@ -427,8 +427,8 @@
 	up(&videodev_lock);
 
 	sprintf(vfd->devfs_name, "v4l/%s%d", name_base, i - base);
-	devfs_register(NULL, vfd->devfs_name, 0, VIDEO_MAJOR, vfd->minor,
-			S_IFCHR | S_IRUSR | S_IWUSR, &video_fops, NULL);
+	devfs_mk_cdev(MKDEV(VIDEO_MAJOR, vfd->minor),
+			S_IFCHR | S_IRUSR | S_IWUSR, vfd->devfs_name);
 	init_MUTEX(&vfd->lock);
 	
 #ifdef CONFIG_VIDEO_PROC_FS
diff -urN linux-2.5.69-bk2/drivers/mtd/mtdchar.c linux-2.5.69-bk3/drivers/mtd/mtdchar.c
--- linux-2.5.69-bk2/drivers/mtd/mtdchar.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk3/drivers/mtd/mtdchar.c	2003-05-08 04:38:19.000000000 -0700
@@ -461,22 +461,12 @@
 
 static void mtd_notify_add(struct mtd_info* mtd)
 {
-	char name[16];
-
 	if (!mtd)
 		return;
-
-	sprintf(name, "mtd/%d", mtd->index);
-	devfs_register(NULL, name,
-			DEVFS_FL_DEFAULT, MTD_CHAR_MAJOR, mtd->index*2,
-			S_IFCHR | S_IRUGO | S_IWUGO,
-			&mtd_fops, NULL);
-
-	sprintf(name, "mtd/%dro", mtd->index);
-	devfs_register(NULL, name,
-			DEVFS_FL_DEFAULT, MTD_CHAR_MAJOR, mtd->index*2+1,
-			S_IFCHR | S_IRUGO | S_IWUGO,
-			&mtd_fops, NULL);
+	devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
+			S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%d", mtd->index);
+	devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
+			S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%dro", mtd->index);
 }
 
 static void mtd_notify_remove(struct mtd_info* mtd)
diff -urN linux-2.5.69-bk2/drivers/net/pcmcia/3c589_cs.c linux-2.5.69-bk3/drivers/net/pcmcia/3c589_cs.c
--- linux-2.5.69-bk2/drivers/net/pcmcia/3c589_cs.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk3/drivers/net/pcmcia/3c589_cs.c	2003-05-08 04:38:19.000000000 -0700
@@ -159,7 +159,7 @@
 static int el3_config(struct net_device *dev, struct ifmap *map);
 static int el3_open(struct net_device *dev);
 static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void update_stats(struct net_device *dev);
 static struct net_device_stats *el3_get_stats(struct net_device *dev);
 static int el3_rx(struct net_device *dev);
@@ -816,15 +816,16 @@
 }
 
 /* The EL3 interrupt handler. */
-static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
     struct el3_private *lp = dev_id;
     struct net_device *dev = &lp->dev;
     ioaddr_t ioaddr, status;
-    int i = 0;
+    int i = 0, handled = 1;
     
     if (!netif_device_present(dev))
-	return;
+	return IRQ_NONE;
+
     ioaddr = dev->base_addr;
 
     DEBUG(3, "%s: interrupt, status %4.4x.\n",
@@ -833,9 +834,9 @@
     spin_lock(&lp->lock);    
     while ((status = inw(ioaddr + EL3_STATUS)) &
 	(IntLatch | RxComplete | StatsFull)) {
-	if (!netif_device_present(dev) ||
-	    ((status & 0xe000) != 0x2000)) {
+	if ((status & 0xe000) != 0x2000) {
 	    DEBUG(1, "%s: interrupt from dead card\n", dev->name);
+	    handled = 0;
 	    break;
 	}
 	
@@ -897,7 +898,7 @@
     spin_unlock(&lp->lock);    
     DEBUG(3, "%s: exiting interrupt, status %4.4x.\n",
 	  dev->name, inw(ioaddr + EL3_STATUS));
-    return;
+    return IRQ_RETVAL(handled);
 }
 
 static void media_check(unsigned long arg)
diff -urN linux-2.5.69-bk2/drivers/net/pcmcia/fmvj18x_cs.c linux-2.5.69-bk3/drivers/net/pcmcia/fmvj18x_cs.c
--- linux-2.5.69-bk2/drivers/net/pcmcia/fmvj18x_cs.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk3/drivers/net/pcmcia/fmvj18x_cs.c	2003-05-08 04:38:19.000000000 -0700
@@ -107,7 +107,7 @@
 static int fjn_open(struct net_device *dev);
 static int fjn_close(struct net_device *dev);
 static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void fjn_rx(struct net_device *dev);
 static void fjn_reset(struct net_device *dev);
 static struct net_device_stats *fjn_get_stats(struct net_device *dev);
@@ -845,7 +845,7 @@
 
 /*====================================================================*/
 
-static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
     local_info_t *lp = dev_id;
     struct net_device *dev = &lp->dev;
@@ -855,7 +855,7 @@
     if (lp == NULL) {
         printk(KERN_NOTICE "fjn_interrupt(): irq %d for "
 	       "unknown device.\n", irq);
-        return;
+        return IRQ_NONE;
     }
     ioaddr = dev->base_addr;
 
@@ -899,6 +899,7 @@
 
     outb(D_TX_INTR, ioaddr + TX_INTR);
     outb(D_RX_INTR, ioaddr + RX_INTR);
+    return IRQ_HANDLED;
 
 } /* fjn_interrupt */
 
diff -urN linux-2.5.69-bk2/drivers/net/pcmcia/ibmtr_cs.c linux-2.5.69-bk3/drivers/net/pcmcia/ibmtr_cs.c
--- linux-2.5.69-bk2/drivers/net/pcmcia/ibmtr_cs.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk3/drivers/net/pcmcia/ibmtr_cs.c	2003-05-08 04:38:19.000000000 -0700
@@ -127,7 +127,7 @@
 
 extern int ibmtr_probe(struct net_device *dev);
 extern int trdev_init(struct net_device *dev);
-extern void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t tok_interrupt (int irq, void *dev_id, struct pt_regs *regs);
 
 /*====================================================================*/
 
diff -urN linux-2.5.69-bk2/drivers/net/pcmcia/nmclan_cs.c linux-2.5.69-bk3/drivers/net/pcmcia/nmclan_cs.c
--- linux-2.5.69-bk2/drivers/net/pcmcia/nmclan_cs.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk3/drivers/net/pcmcia/nmclan_cs.c	2003-05-08 04:38:19.000000000 -0700
@@ -431,7 +431,7 @@
 static int mace_close(struct net_device *dev);
 static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void mace_tx_timeout(struct net_device *dev);
-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);
 static struct net_device_stats *mace_get_stats(struct net_device *dev);
 static int mace_rx(struct net_device *dev, unsigned char RxCnt);
 static void restore_multicast_list(struct net_device *dev);
@@ -1143,7 +1143,7 @@
 mace_interrupt
 	The interrupt handler.
 ---------------------------------------------------------------------------- */
-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)
 {
   mace_private *lp = (mace_private *)dev_id;
   struct net_device *dev = &lp->dev;
@@ -1154,7 +1154,7 @@
   if (dev == NULL) {
     DEBUG(2, "mace_interrupt(): irq 0x%X for unknown device.\n",
 	  irq);
-    return;
+    return IRQ_NONE;
   }
 
   if (lp->tx_irq_disabled) {
@@ -1169,12 +1169,12 @@
       inb(ioaddr + AM2150_MACE_BASE + MACE_IMR)
     );
     /* WARNING: MACE_IR has been read! */
-    return;
+    return IRQ_NONE;
   }
 
   if (!netif_device_present(dev)) {
     DEBUG(2, "%s: interrupt from dead card\n", dev->name);
-    goto exception;
+    return IRQ_NONE;
   }
 
   do {
@@ -1279,8 +1279,7 @@
 
   } while ((status & ~MACE_IMR_DEFAULT) && (--IntrCnt));
 
-exception:
-  return;
+  return IRQ_HANDLED;
 } /* mace_interrupt */
 
 /* ----------------------------------------------------------------------------
diff -urN linux-2.5.69-bk2/drivers/net/pcmcia/smc91c92_cs.c linux-2.5.69-bk3/drivers/net/pcmcia/smc91c92_cs.c
--- linux-2.5.69-bk2/drivers/net/pcmcia/smc91c92_cs.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk3/drivers/net/pcmcia/smc91c92_cs.c	2003-05-08 04:38:19.000000000 -0700
@@ -293,7 +293,7 @@
 static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void smc_tx_timeout(struct net_device *dev);
 static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void smc_rx(struct net_device *dev);
 static struct net_device_stats *smc_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
@@ -1574,16 +1574,18 @@
 
 /*====================================================================*/
 
-static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
     struct smc_private *smc = dev_id;
     struct net_device *dev = &smc->dev;
     ioaddr_t ioaddr;
     u_short saved_bank, saved_pointer, mask, status;
+    unsigned int handled = 1;
     char bogus_cnt = INTR_WORK;		/* Work we are willing to do. */
 
     if (!netif_device_present(dev))
-	return;
+	return IRQ_NONE;
+
     ioaddr = dev->base_addr;
 
     DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name,
@@ -1596,6 +1598,7 @@
 	   maybe it has been ejected. */
 	DEBUG(1, "%s: SMC91c92 interrupt %d for non-existent"
 	      "/ejected device.\n", dev->name, irq);
+	handled = 0;
 	goto irq_done;
     }
 
@@ -1609,9 +1612,11 @@
 	status = inw(ioaddr + INTERRUPT) & 0xff;
 	DEBUG(3, "%s: Status is %#2.2x (mask %#2.2x).\n", dev->name,
 	      status, mask);
-	if ((status & mask) == 0)
+	if ((status & mask) == 0) {
+	    if (bogus_cnt == INTR_WORK)
+		handled = 0;
 	    break;
-	
+	}
 	if (status & IM_RCV_INT) {
 	    /* Got a packet(s). */
 	    smc_rx(dev);
@@ -1683,6 +1688,7 @@
 	readb(smc->base+MEGAHERTZ_ISR);
     }
 #endif
+    return IRQ_RETVAL(handled);
 }
 
 /*====================================================================*/
diff -urN linux-2.5.69-bk2/drivers/net/pcmcia/xirc2ps_cs.c linux-2.5.69-bk3/drivers/net/pcmcia/xirc2ps_cs.c
--- linux-2.5.69-bk2/drivers/net/pcmcia/xirc2ps_cs.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/drivers/net/pcmcia/xirc2ps_cs.c	2003-05-08 04:38:19.000000000 -0700
@@ -317,7 +317,7 @@
  * less on other parts of the kernel.
  */
 
-static void xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
 /*
  * The dev_info variable is the "key" that is used to match up this
@@ -1296,7 +1296,7 @@
 /****************
  * This is the Interrupt service route.
  */
-static void
+static irqreturn_t
 xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
     struct net_device *dev = (struct net_device *)dev_id;
@@ -1305,14 +1305,14 @@
     u_char saved_page;
     unsigned bytes_rcvd;
     unsigned int_status, eth_status, rx_status, tx_status;
-    unsigned rsr, pktlen;
+    unsigned rsr, pktlen, handled = 1;
     ulong start_ticks = jiffies; /* fixme: jiffies rollover every 497 days
 				  * is this something to worry about?
 				  * -- on a laptop?
 				  */
 
     if (!netif_device_present(dev))
-	return;
+	return IRQ_NONE;
 
     ioaddr = dev->base_addr;
     if (lp->mohawk) { /* must disable the interrupt */
@@ -1330,6 +1330,7 @@
   loop_entry:
     if (int_status == 0xff) { /* card may be ejected */
 	DEBUG(3, "%s: interrupt %d for dead card\n", dev->name, irq);
+	handled = 0;
 	goto leave;
     }
     eth_status = GetByte(XIRCREG_ESR);
@@ -1514,6 +1515,7 @@
      * force an interrupt with this command:
      *	  PutByte(XIRCREG_CR, EnableIntr|ForceIntr);
      */
+    return IRQ_RETVAL(handled);
 } /* xirc2ps_interrupt */
 
 /*====================================================================*/
diff -urN linux-2.5.69-bk2/drivers/net/ppp_generic.c linux-2.5.69-bk3/drivers/net/ppp_generic.c
--- linux-2.5.69-bk2/drivers/net/ppp_generic.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk3/drivers/net/ppp_generic.c	2003-05-08 04:38:19.000000000 -0700
@@ -784,11 +784,14 @@
 
 	printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n");
 	err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
-	if (err)
+	if (!err) {
+		err = devfs_mk_cdev(MKDEV(PPP_MAJOR, 0),
+				S_IFCHR|S_IRUSR|S_IWUSR, "ppp");
+	}
+
+	if (!err)
 		printk(KERN_ERR "failed to register PPP device (%d)\n", err);
-	devfs_register(NULL, "ppp", DEVFS_FL_DEFAULT, PPP_MAJOR, 0,
-		       S_IFCHR | S_IRUSR | S_IWUSR, &ppp_device_fops, NULL);
-	return 0;
+	return err;
 }
 
 /*
diff -urN linux-2.5.69-bk2/drivers/net/wan/cosa.c linux-2.5.69-bk3/drivers/net/wan/cosa.c
--- linux-2.5.69-bk2/drivers/net/wan/cosa.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk3/drivers/net/wan/cosa.c	2003-05-08 04:38:19.000000000 -0700
@@ -392,12 +392,9 @@
 	}
 	devfs_mk_dir("cosa");
 	for (i=0; i<nr_cards; i++) {
-		char name[16];
-		sprintf(name, "cosa/%d", i);
-		devfs_register(NULL, name, DEVFS_FL_DEFAULT,
-			       cosa_major, i,
-			       S_IFCHR | S_IRUSR | S_IWUSR,
-			       &cosa_fops, NULL);
+		devfs_mk_cdev(MKDEV(cosa_major, i),
+				S_IFCHR|S_IRUSR|S_IWUSR,
+				"cosa/%d", i);
 	}
 	return 0;
 }
diff -urN linux-2.5.69-bk2/drivers/s390/char/tuball.c linux-2.5.69-bk3/drivers/s390/char/tuball.c
--- linux-2.5.69-bk2/drivers/s390/char/tuball.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk3/drivers/s390/char/tuball.c	2003-05-08 04:38:19.000000000 -0700
@@ -468,9 +468,8 @@
 	}
 #endif /* CONFIG_TN3270_CONSOLE */
 
-#ifdef CONFIG_DEVFS_FS
-	fs3270_devfs_register(tubp);
-#endif
+	devfs_mk_cdev(MKDEV(IBM_FS3270_MAJOR, tubp->minor),
+			S_IFCHR|S_IRUSR|S_IWUSR, "3270/tub%.4x");
 
 	TUBUNLOCK(tubp->irq, flags);
 	return minor;
@@ -492,9 +491,7 @@
 	for (i = 0; i < TUBMAXMINS; i++) {
 		tubpp = &(*tubminors)[i];
 		if ((tubp = *tubpp)) {
-#ifdef CONFIG_DEVFS_FS
-			fs3270_devfs_unregister(tubp);
-#endif
+			devfs_remove("3270/tub%.4x", tubp->devno);
 			tubdelbyirq(tubp, tubp->irq);
 			tty3270_rcl_fini(tubp);
 			kfree(tubp->tty_bcb.bc_buf);
diff -urN linux-2.5.69-bk2/drivers/s390/char/tubfs.c linux-2.5.69-bk3/drivers/s390/char/tubfs.c
--- linux-2.5.69-bk2/drivers/s390/char/tubfs.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/drivers/s390/char/tubfs.c	2003-05-08 04:38:19.000000000 -0700
@@ -23,9 +23,7 @@
 extern void tty3270_refresh(tub_t *);
 
 static struct file_operations fs3270_fops = {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0))
 	.owner = THIS_MODULE,		/* owner */
-#endif
 	.read 	= fs3270_read,	/* read */
 	.write	= fs3270_write,	/* write */
 	.ioctl	= fs3270_ioctl,	/* ioctl */
@@ -33,27 +31,6 @@
 	.release = fs3270_close,	/* release */
 };
 
-#ifdef CONFIG_DEVFS_FS
-void fs3270_devfs_register(tub_t *tubp)
-{
-	char name[16];
-
-	sprintf(name, "3270/tub%.4x", tubp->devno);
-	devfs_register(NULL, name, DEVFS_FL_DEFAULT,
-		       IBM_FS3270_MAJOR, tubp->minor,
-		       S_IFCHR | S_IRUSR | S_IWUSR, &fs3270_fops, NULL);
-	sprintf(name, "tty%.4x", tubp->devno);
-	tty_register_devfs_name(&tty3270_driver, 0, tubp->minor,
-				NULL, name);
-}
-
-void fs3270_devfs_unregister(tub_t *tubp)
-{
-	devfs_remove("3270/tub%.4x", tubp->devno);
-	devfs_remove("3270/tty%.4x", tubp->devno);
-}
-#endif
-
 /*
  * fs3270_init() -- Initialize fullscreen tubes
  */
@@ -69,10 +46,8 @@
 		return -1;
 	}
 	devfs_mk_dir("3270");
-	devfs_register(NULL, "3270/tub", 0,
-			       IBM_FS3270_MAJOR, 0,
-			       S_IFCHR | S_IRUGO | S_IWUGO, 
-			       &fs3270_fops, NULL);
+	devfs_mk_cdev(MKDEV(IBM_FS3270_MAJOR, 0),
+			S_IFCHR|S_IRUGO|S_IWUGO, "3270/tub");
 	fs3270_major = IBM_FS3270_MAJOR;
 	return 0;
 }
diff -urN linux-2.5.69-bk2/drivers/s390/char/tubio.h linux-2.5.69-bk3/drivers/s390/char/tubio.h
--- linux-2.5.69-bk2/drivers/s390/char/tubio.h	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk3/drivers/s390/char/tubio.h	2003-05-08 04:38:19.000000000 -0700
@@ -337,10 +337,6 @@
 extern int tty3270_proc_misc;
 extern enum tubwhat tty3270_proc_what;
 extern struct tty_driver tty3270_driver;
-#ifdef CONFIG_DEVFS_FS
-extern void fs3270_devfs_register(tub_t *);
-extern void fs3270_devfs_unregister(tub_t *);
-#endif
 
 #ifndef spin_trylock_irqsave
 #define spin_trylock_irqsave(lock, flags) \
diff -urN linux-2.5.69-bk2/drivers/s390/char/tubtty.c linux-2.5.69-bk3/drivers/s390/char/tubtty.c
--- linux-2.5.69-bk2/drivers/s390/char/tubtty.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk3/drivers/s390/char/tubtty.c	2003-05-08 04:38:19.000000000 -0700
@@ -90,9 +90,7 @@
 	td->subtype = SYSTEM_TYPE_TTY;
 	td->init_termios = tty_std_termios;
 	td->flags = TTY_DRIVER_RESET_TERMIOS;
-#ifdef CONFIG_DEVFS_FS
 	td->flags |= TTY_DRIVER_NO_DEVFS;
-#endif
 	td->refcount = &tty3270_refcount;
 	td->table = tty3270_table;
 	td->termios = tty3270_termios;
diff -urN linux-2.5.69-bk2/drivers/sbus/char/bpp.c linux-2.5.69-bk3/drivers/sbus/char/bpp.c
--- linux-2.5.69-bk2/drivers/sbus/char/bpp.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk3/drivers/sbus/char/bpp.c	2003-05-08 04:38:19.000000000 -0700
@@ -1051,11 +1051,8 @@
 	}
 	devfs_mk_dir("bpp");
 	for (idx = 0; idx < BPP_NO; idx++) {
-		char name[16];
-		sprintf(name, "bpp/%d", idx);
-		devfs_register(NULL, name, DEVFS_FL_DEFAULT,
-			       BPP_MAJOR, idx, S_IFCHR | S_IRUSR | S_IWUSR,
-			       &bpp_fops, NULL);
+		devfs_mk_cdev(MKDEV(BPP_MAJOR, idx),
+				S_IFCHR | S_IRUSR | S_IWUSR, "bpp/%d", idx);
 	}
 
 	return 0;
diff -urN linux-2.5.69-bk2/drivers/sbus/char/vfc_dev.c linux-2.5.69-bk3/drivers/sbus/char/vfc_dev.c
--- linux-2.5.69-bk2/drivers/sbus/char/vfc_dev.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/drivers/sbus/char/vfc_dev.c	2003-05-08 04:38:19.000000000 -0700
@@ -143,8 +143,6 @@
 
 int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, int instance)
 {
-	char devname[16];
-
 	if(dev == NULL) {
 		printk(KERN_ERR "VFC: Bogus pointer passed\n");
 		return -ENOMEM;
@@ -167,11 +165,9 @@
 	if (init_vfc_hw(dev))
 		return -EIO;
 
-	sprintf (devname, "vfc/%d", instance);
-	dev->de = devfs_register (NULL, devname, DEVFS_FL_DEFAULT,
-				  VFC_MAJOR, instance,
-				  S_IFCHR | S_IRUSR | S_IWUSR,
-				  &vfc_fops, NULL);
+	devfs_mk_cdev(MKDEV(VFC_MAJOR, instance),
+			S_IFCHR | S_IRUSR | S_IWUSR,
+			"vfc/%d", instance);
 	return 0;
 }
 
diff -urN linux-2.5.69-bk2/drivers/scsi/osst.c linux-2.5.69-bk3/drivers/scsi/osst.c
--- linux-2.5.69-bk2/drivers/scsi/osst.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk3/drivers/scsi/osst.c	2003-05-08 04:38:19.000000000 -0700
@@ -5527,11 +5527,10 @@
 	write_unlock(&os_scsi_tapes_lock);
 
 	for (mode = 0; mode < ST_NBR_MODES; ++mode) {
-		char name[8], devfs_name[64];
+		char name[8];
 
 		/*  Rewind entry  */
 		sprintf(name, "ot%s", osst_formats[mode]);
-		sprintf(devfs_name, "%s/ot%s", SDp->devfs_name, osst_formats[mode]);
 
 		sprintf(tpnt->driverfs_dev_r[mode].bus_id, "%s:%s", 
 				SDp->sdev_driverfs_dev.bus_id, name);
@@ -5545,13 +5544,13 @@
 		device_create_file(&tpnt->driverfs_dev_r[mode], 
 				&dev_attr_type);
 		device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev);
-		devfs_register(NULL, devfs_name, 0,
-					OSST_MAJOR, dev_num + (mode << 5),
-					S_IFCHR | S_IRUGO | S_IWUGO,
-					&osst_fops, NULL);
+
+		devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)),
+				S_IFCHR | S_IRUGO | S_IWUGO,
+				"%s/ot%s", SDp->devfs_name, osst_formats[mode]);
+
 		/*  No-rewind entry  */
 		sprintf (name, "ot%sn", osst_formats[mode]);
-		sprintf(devfs_name, "%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
 
 		sprintf(tpnt->driverfs_dev_n[mode].bus_id, "%s:%s", 
 				SDp->sdev_driverfs_dev.bus_id, name);
@@ -5566,10 +5565,10 @@
 				&dev_attr_type);
 		device_create_file(&tpnt->driverfs_dev_n[mode], 
 				&dev_attr_kdev);
-		devfs_register(NULL, devfs_name, 0,
-					OSST_MAJOR, dev_num + (mode << 5) + 128,
-					S_IFCHR | S_IRUGO | S_IWUGO,
-					&osst_fops, NULL);
+
+		devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5) + 128),
+				S_IFCHR | S_IRUGO | S_IWUGO,
+				"%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
 	}
 	drive->number = devfs_register_tape(SDp->devfs_name);
 
diff -urN linux-2.5.69-bk2/drivers/scsi/sg.c linux-2.5.69-bk3/drivers/scsi/sg.c
--- linux-2.5.69-bk2/drivers/scsi/sg.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk3/drivers/scsi/sg.c	2003-05-08 04:38:19.000000000 -0700
@@ -1350,7 +1350,6 @@
 	struct gendisk *disk;
 	Sg_device *sdp = NULL;
 	unsigned long iflags;
-	char devfs_name[64];
 	int k, error;
 
 	disk = alloc_disk(1);
@@ -1449,11 +1448,9 @@
 	device_create_file(&sdp->sg_driverfs_dev, &dev_attr_type);
 	device_create_file(&sdp->sg_driverfs_dev, &dev_attr_kdev);
 
-	sprintf(devfs_name, "%s/generic", scsidp->devfs_name);
-	devfs_register(NULL, devfs_name, 0,
-			SCSI_GENERIC_MAJOR, k,
+	devfs_mk_cdev(MKDEV(SCSI_GENERIC_MAJOR, k),
 			S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
-			&sg_fops, sdp);
+			"%s/generic", scsidp->devfs_name);
 
 	switch (scsidp->type) {
 	case TYPE_DISK:
diff -urN linux-2.5.69-bk2/drivers/scsi/st.c linux-2.5.69-bk3/drivers/scsi/st.c
--- linux-2.5.69-bk2/drivers/scsi/st.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk3/drivers/scsi/st.c	2003-05-08 04:38:19.000000000 -0700
@@ -3865,11 +3865,10 @@
 	write_unlock(&st_dev_arr_lock);
 
 	for (mode = 0; mode < ST_NBR_MODES; ++mode) {
-	    char name[8], devfs_name[64];
+	    char name[8];
 
 	    /*  Rewind entry  */
 	    sprintf(name, "mt%s", st_formats[mode]);
-	    sprintf(devfs_name, "%s/mt%s", SDp->devfs_name, st_formats[mode]);
 	    
 	    sprintf(tpnt->driverfs_dev_r[mode].bus_id, "%s:%s", 
 		    SDp->sdev_driverfs_dev.bus_id, name);
@@ -3883,13 +3882,12 @@
 	    device_create_file(&tpnt->driverfs_dev_r[mode], 
 			       &dev_attr_type);
 	    device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev);
-	    devfs_register(NULL, devfs_name, 0,
-				SCSI_TAPE_MAJOR, dev_num + (mode << 5),
+	    devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5)),
 				S_IFCHR | S_IRUGO | S_IWUGO,
-				&st_fops, NULL);
+				"%s/mt%s", SDp->devfs_name, st_formats[mode]);
+
 	    /*  No-rewind entry  */
 	    sprintf (name, "mt%sn", st_formats[mode]);
-	    sprintf(devfs_name, "%s/mt%sn", SDp->devfs_name, st_formats[mode]);
 
 	    sprintf(tpnt->driverfs_dev_n[mode].bus_id, "%s:%s", 
 		    SDp->sdev_driverfs_dev.bus_id, name);
@@ -3904,10 +3902,9 @@
 			       &dev_attr_type);
 	    device_create_file(&tpnt->driverfs_dev_n[mode], 
 			       &dev_attr_kdev);
-	    devfs_register(NULL, devfs_name, 0,
-				SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128,
+	    devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128),
 				S_IFCHR | S_IRUGO | S_IWUGO,
-				&st_fops, NULL);
+				"%s/mt%sn", SDp->devfs_name, st_formats[mode]);
 	}
 	disk->number = devfs_register_tape(SDp->devfs_name);
 
diff -urN linux-2.5.69-bk2/drivers/serial/core.c linux-2.5.69-bk3/drivers/serial/core.c
--- linux-2.5.69-bk2/drivers/serial/core.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk3/drivers/serial/core.c	2003-05-08 04:38:19.000000000 -0700
@@ -2242,7 +2242,7 @@
 	 * Register the port whether it's detected or not.  This allows
 	 * setserial to be used to alter this ports parameters.
 	 */
-	tty_register_device(drv->tty_driver, port->line);
+	tty_register_device(drv->tty_driver, port->line, NULL);
 
  out:
 	up(&port_sem);
diff -urN linux-2.5.69-bk2/drivers/sgi/char/sgiserial.c linux-2.5.69-bk3/drivers/sgi/char/sgiserial.c
--- linux-2.5.69-bk2/drivers/sgi/char/sgiserial.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk3/drivers/sgi/char/sgiserial.c	2003-05-08 04:38:19.000000000 -0700
@@ -1867,6 +1867,7 @@
 	
 	memset(&serial_driver, 0, sizeof(struct tty_driver));
 	serial_driver.magic = TTY_DRIVER_MAGIC;
+	serial_driver.owner = THIS_MODULE;
 	serial_driver.name = "ttyS";
 	serial_driver.major = TTY_MAJOR;
 	serial_driver.minor_start = 64;
diff -urN linux-2.5.69-bk2/drivers/sgi/char/shmiq.c linux-2.5.69-bk3/drivers/sgi/char/shmiq.c
--- linux-2.5.69-bk2/drivers/sgi/char/shmiq.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/drivers/sgi/char/shmiq.c	2003-05-08 04:38:19.000000000 -0700
@@ -470,9 +470,8 @@
 	printk ("SHMIQ setup\n");
 	register_chrdev(SHMIQ_MAJOR, "shmiq", &shmiq_fops);
 	for (i = 0; i < 3; i++) {
-		devfs_register (NULL, names[i], DEVFS_FL_DEFAULT,
-			SHMIQ_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR,
-			&shmiq_fops, NULL);
+		devfs_mk_cdev(MKDEV(SHMIQ_MAJOR, i),
+				S_IFCHR | S_IRUSR | S_IWUSR, names[i]);
 	}
 }
 
diff -urN linux-2.5.69-bk2/drivers/tc/zs.c linux-2.5.69-bk3/drivers/tc/zs.c
--- linux-2.5.69-bk2/drivers/tc/zs.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk3/drivers/tc/zs.c	2003-05-08 04:38:19.000000000 -0700
@@ -1872,6 +1872,7 @@
 
 	memset(&serial_driver, 0, sizeof(struct tty_driver));
 	serial_driver.magic = TTY_DRIVER_MAGIC;
+	serial_driver.owner = THIS_MODULE;
 #if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
 	serial_driver.name = "tts/";
 #else
@@ -1970,8 +1971,8 @@
 		printk("ttyS%02d at 0x%08x (irq = %d)", info->line, 
 		       info->port, info->irq);
 		printk(" is a Z85C30 SCC\n");
-		tty_register_device(&serial_driver, info->line);
-		tty_register_device(&callout_driver, info->line);
+		tty_register_device(&serial_driver, info->line, NULL);
+		tty_register_device(&callout_driver, info->line, NULL);
 
 	}
 
diff -urN linux-2.5.69-bk2/drivers/usb/class/bluetty.c linux-2.5.69-bk3/drivers/usb/class/bluetty.c
--- linux-2.5.69-bk2/drivers/usb/class/bluetty.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/class/bluetty.c	2003-05-08 04:38:19.000000000 -0700
@@ -1198,7 +1198,7 @@
 		     bluetooth, endpoint->bInterval);
 
 	/* initialize the devfs nodes for this device and let the user know what bluetooths we are bound to */
-	tty_register_device (&bluetooth_tty_driver, minor);
+	tty_register_device (&bluetooth_tty_driver, minor, &intf->dev);
 	info("Bluetooth converter now attached to ttyUB%d (or usb/ttub/%d for devfs)", minor, minor);
 
 	bluetooth_table[minor] = bluetooth;
diff -urN linux-2.5.69-bk2/drivers/usb/class/cdc-acm.c linux-2.5.69-bk3/drivers/usb/class/cdc-acm.c
--- linux-2.5.69-bk2/drivers/usb/class/cdc-acm.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/class/cdc-acm.c	2003-05-08 04:38:19.000000000 -0700
@@ -653,7 +653,7 @@
 		usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm);
 		usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
 
-		tty_register_device(&acm_tty_driver, minor);
+		tty_register_device(&acm_tty_driver, minor, &intf->dev);
 
 		acm_table[minor] = acm;
 		usb_set_intfdata (intf, acm);
diff -urN linux-2.5.69-bk2/drivers/usb/class/usblp.c linux-2.5.69-bk3/drivers/usb/class/usblp.c
--- linux-2.5.69-bk2/drivers/usb/class/usblp.c	2003-05-04 16:53:03.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/class/usblp.c	2003-05-08 04:38:19.000000000 -0700
@@ -54,7 +54,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/lp.h>
-#include <linux/devfs_fs_kernel.h>
 #undef DEBUG
 #include <linux/usb.h>
 
@@ -109,11 +108,7 @@
 #define USBLP_REQ_RESET				0x02
 #define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST	0x00	/* HP Vendor-specific */
 
-#ifdef CONFIG_USB_DYNAMIC_MINORS
-#define USBLP_MINORS		256
-#else
 #define USBLP_MINORS		16
-#endif
 #define USBLP_MINOR_BASE	0
 
 #define USBLP_WRITE_TIMEOUT	(5*HZ)			/* 5 seconds */
@@ -324,13 +319,13 @@
 	struct usb_interface *intf;
 	int retval;
 
-	if (minor < 0 || minor >= USBLP_MINORS)
+	if (minor < 0)
 		return -ENODEV;
 
 	lock_kernel();
 
 	retval = -ENODEV;
-	intf = usb_find_interface(&usblp_driver, mk_kdev(USB_MAJOR,minor));
+	intf = usb_find_interface(&usblp_driver, minor);
 	if (!intf) {
 		goto out;
 	}
@@ -380,8 +375,6 @@
 
 static void usblp_cleanup (struct usblp *usblp)
 {
-	devfs_remove ("usb/lp%d", usblp->minor);
-	usb_deregister_dev (1, usblp->minor);
 	info("usblp%d: removed", usblp->minor);
 
 	usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
@@ -809,6 +802,13 @@
 	.release =	usblp_release,
 };
 
+static struct usb_class_driver usblp_class = {
+	.name =		"usb/lp%d",
+	.fops =		&usblp_fops,
+	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+	.minor_base =	USBLP_MINOR_BASE,
+};
+
 static int usblp_probe(struct usb_interface *intf,
 		       const struct usb_device_id *id)
 {
@@ -816,7 +816,6 @@
 	struct usblp *usblp = 0;
 	int protocol;
 	int retval;
-	char name[10];
 
 	/* Malloc and start initializing usblp structure so we can use it
 	 * directly. */
@@ -830,11 +829,12 @@
 	init_waitqueue_head(&usblp->wait);
 	usblp->ifnum = intf->altsetting->desc.bInterfaceNumber;
 
-	retval = usb_register_dev(&usblp_fops, USBLP_MINOR_BASE, 1, &usblp->minor);
+	retval = usb_register_dev(intf, &usblp_class);
 	if (retval) {
 		err("Not able to get a minor for this device.");
 		goto abort;
 	}
+	usblp->minor = intf->minor;
 
 	usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!usblp->writeurb) {
@@ -904,13 +904,6 @@
 	usblp_check_status(usblp, 0);
 #endif
 
-	/* If we have devfs, create with perms=660. */
-	sprintf(name, "usb/lp%d", usblp->minor);
-	devfs_register(NULL, name, 0, USB_MAJOR,
-				      usblp->minor,
-				      S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
-				      S_IWGRP, &usblp_fops, NULL);
-
 	info("usblp%d: USB %sdirectional printer dev %d "
 		"if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
 		usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
@@ -921,13 +914,10 @@
 
 	usb_set_intfdata (intf, usblp);
 
-	/* add device id so the device works when advertised */
-	intf->kdev = mk_kdev(USB_MAJOR,usblp->minor);
-
 	return 0;
 
 abort_minor:
-	usb_deregister_dev (1, usblp->minor);
+	usb_deregister_dev(intf, &usblp_class);
 abort:
 	if (usblp) {
 		if (usblp->writebuf)
@@ -1108,8 +1098,7 @@
 {
 	struct usblp *usblp = usb_get_intfdata (intf);
 
-	/* remove device id to disable open() */
-	intf->kdev = NODEV;
+	usb_deregister_dev(intf, &usblp_class);
 
 	if (!usblp || !usblp->dev) {
 		err("bogus disconnect");
diff -urN linux-2.5.69-bk2/drivers/usb/core/file.c linux-2.5.69-bk3/drivers/usb/core/file.c
--- linux-2.5.69-bk2/drivers/usb/core/file.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/core/file.c	2003-05-08 04:38:19.000000000 -0700
@@ -66,6 +66,10 @@
 	.open =		usb_open,
 };
 
+static struct class usb_class = {
+	.name	= "usb",
+};
+
 int usb_major_init(void)
 {
 	if (register_chrdev(USB_MAJOR, "usb", &usb_fops)) {
@@ -74,41 +78,53 @@
 	}
 
 	devfs_mk_dir("usb");
+	class_register(&usb_class);
 	return 0;
 }
 
 void usb_major_cleanup(void)
 {
+	class_unregister(&usb_class);
 	devfs_remove("usb");
 	unregister_chrdev(USB_MAJOR, "usb");
 }
 
+static ssize_t show_dev(struct class_device *class_dev, char *buf)
+{
+	struct usb_interface *intf = class_dev_to_usb_interface(class_dev);
+	dev_t dev = MKDEV(USB_MAJOR, intf->minor);
+	return sprintf(buf, "%04x\n", dev);
+}
+static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
+
 /**
  * usb_register_dev - register a USB device, and ask for a minor number
- * @fops: the file operations for this USB device
- * @minor: the requested starting minor for this device.
- * @num_minors: number of minor numbers requested for this device
- * @start_minor: place to put the new starting minor number
+ * @intf: pointer to the usb_interface that is being registered
+ * @class_driver: pointer to the usb_class_driver for this device
  *
  * This should be called by all USB drivers that use the USB major number.
  * If CONFIG_USB_DYNAMIC_MINORS is enabled, the minor number will be
  * dynamically allocated out of the list of available ones.  If it is not
  * enabled, the minor number will be based on the next available free minor,
- * starting at the requested @minor.
+ * starting at the class_driver->minor_base.
+ *
+ * This function also creates the devfs file for the usb device, if devfs
+ * is enabled, and creates a usb class device in the sysfs tree.
  *
  * usb_deregister_dev() must be called when the driver is done with
  * the minor numbers given out by this function.
  *
  * Returns -EINVAL if something bad happens with trying to register a
- * device, and 0 on success, alone with a value that the driver should
- * use in start_minor.
+ * device, and 0 on success.
  */
-int usb_register_dev (struct file_operations *fops, int minor, int num_minors, int *start_minor)
+int usb_register_dev(struct usb_interface *intf,
+		     struct usb_class_driver *class_driver)
 {
-	int i;
-	int j;
-	int good_spot;
 	int retval = -EINVAL;
+	int minor_base = class_driver->minor_base;
+	int minor = 0;
+	char name[DEVICE_ID_SIZE];
+	char *temp;
 
 #ifdef CONFIG_USB_DYNAMIC_MINORS
 	/* 
@@ -116,65 +132,94 @@
 	 * at zero to pack the devices into the smallest available space with
 	 * no holes in the minor range.
 	 */
-	minor = 0;
+	minor_base = 0;
 #endif
+	intf->minor = -1;
 
-	dbg ("asking for %d minors, starting at %d", num_minors, minor);
+	dbg ("looking for a minor, starting at %d", minor_base);
 
-	if (fops == NULL)
+	if (class_driver->fops == NULL)
 		goto exit;
 
-	*start_minor = 0; 
 	spin_lock (&minor_lock);
-	for (i = minor; i < MAX_USB_MINORS; ++i) {
-		if (usb_minors[i])
+	for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {
+		if (usb_minors[minor])
 			continue;
 
-		good_spot = 1;
-		for (j = 1; j <= num_minors-1; ++j)
-			if (usb_minors[i+j]) {
-				good_spot = 0;
-				break;
-			}
-		if (good_spot == 0)
-			continue;
-
-		*start_minor = i;
-		dbg("found a minor chunk free, starting at %d", i);
-		for (i = *start_minor; i < (*start_minor + num_minors); ++i)
-			usb_minors[i] = fops;
+		usb_minors[minor] = class_driver->fops;
 
 		retval = 0;
-		goto exit;
+		break;
 	}
-exit:
 	spin_unlock (&minor_lock);
+
+	if (retval)
+		goto exit;
+
+	intf->minor = minor;
+
+	/* handle the devfs registration */
+	snprintf(name, DEVICE_ID_SIZE, class_driver->name, minor - minor_base);
+	devfs_register(NULL, name, 0, USB_MAJOR, minor, class_driver->mode,
+		       class_driver->fops, NULL);
+
+	/* create a usb class device for this usb interface */
+	memset(&intf->class_dev, 0x00, sizeof(struct class_device));
+	intf->class_dev.class = &usb_class;
+	intf->class_dev.dev = &intf->dev;
+
+	temp = strrchr(name, '/');
+	if (temp && (temp[1] != 0x00))
+		++temp;
+	else
+		temp = name;
+	snprintf(intf->class_dev.class_id, BUS_ID_SIZE, "%s", temp);
+	class_device_register(&intf->class_dev);
+	class_device_create_file (&intf->class_dev, &class_device_attr_dev);
+exit:
 	return retval;
 }
 EXPORT_SYMBOL(usb_register_dev);
 
 /**
  * usb_deregister_dev - deregister a USB device's dynamic minor.
- * @num_minors: number of minor numbers to put back.
- * @start_minor: the starting minor number
+ * @intf: pointer to the usb_interface that is being deregistered
+ * @class_driver: pointer to the usb_class_driver for this device
  *
  * Used in conjunction with usb_register_dev().  This function is called
  * when the USB driver is finished with the minor numbers gotten from a
  * call to usb_register_dev() (usually when the device is disconnected
  * from the system.)
+ *
+ * This function also cleans up the devfs file for the usb device, if devfs
+ * is enabled, and removes the usb class device from the sysfs tree.
  * 
  * This should be called by all drivers that use the USB major number.
  */
-void usb_deregister_dev (int num_minors, int start_minor)
+void usb_deregister_dev(struct usb_interface *intf,
+			struct usb_class_driver *class_driver)
 {
-	int i;
+	int minor_base = class_driver->minor_base;
+	char name[DEVICE_ID_SIZE];
 
-	dbg ("removing %d minors starting at %d", num_minors, start_minor);
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+	minor_base = 0;
+#endif
+
+	if (intf->minor == -1)
+		return;
+
+	dbg ("removing %d minor", intf->minor);
 
 	spin_lock (&minor_lock);
-	for (i = start_minor; i < (start_minor + num_minors); ++i)
-		usb_minors[i] = NULL;
+	usb_minors[intf->minor] = NULL;
 	spin_unlock (&minor_lock);
+
+	snprintf(name, DEVICE_ID_SIZE, class_driver->name, intf->minor - minor_base);
+	devfs_remove (name);
+
+	class_device_unregister(&intf->class_dev);
+	intf->minor = -1;
 }
 EXPORT_SYMBOL(usb_deregister_dev);
 
diff -urN linux-2.5.69-bk2/drivers/usb/core/usb.c linux-2.5.69-bk3/drivers/usb/core/usb.c
--- linux-2.5.69-bk2/drivers/usb/core/usb.c	2003-05-04 16:53:29.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/core/usb.c	2003-05-08 04:38:19.000000000 -0700
@@ -457,12 +457,13 @@
 /**
  * usb_find_interface - find usb_interface pointer for driver and device
  * @drv: the driver whose current configuration is considered
- * @kdev: the desired device
+ * @minor: the minor number of the desired device
  *
  * This walks the driver device list and returns a pointer to the interface 
- * with the matching kdev_t.
+ * with the matching minor.  Note, this only works for devices that share the
+ * USB major number.
  */
-struct usb_interface *usb_find_interface(struct usb_driver *drv, kdev_t kdev)
+struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
 {
 	struct list_head *entry;
 	struct device *dev;
@@ -476,9 +477,10 @@
 			continue;
 
 		intf = to_usb_interface(dev);
-		if (kdev_same(intf->kdev,kdev)) {
+		if (intf->minor == -1)
+			continue;
+		if (intf->minor == minor)
 			return intf;
-		}
 	}
 
 	/* no device found that matches */
diff -urN linux-2.5.69-bk2/drivers/usb/host/ehci-hcd.c linux-2.5.69-bk3/drivers/usb/host/ehci-hcd.c
--- linux-2.5.69-bk2/drivers/usb/host/ehci-hcd.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/host/ehci-hcd.c	2003-05-08 04:38:19.000000000 -0700
@@ -116,8 +116,10 @@
 #define	EHCI_TUNE_MULT_TT	1
 #define	EHCI_TUNE_FLS		2	/* (small) 256 frame schedule */
 
-#define EHCI_WATCHDOG_JIFFIES	(HZ/100)	/* arbitrary; ~10 msec */
+#define EHCI_IAA_JIFFIES	(HZ/100)	/* arbitrary; ~10 msec */
+#define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
 #define EHCI_ASYNC_JIFFIES	(HZ/20)		/* async idle timeout */
+#define EHCI_SHRINK_JIFFIES	(HZ/200)	/* async qh unlink delay */
 
 /* Initial IRQ latency:  lower than default */
 static int log2_irq_thresh = 0;		// 0 to 6
@@ -266,16 +268,13 @@
 		}
 	}
 
+ 	/* stop async processing after it's idled a bit */
+	if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
+ 		start_unlink_async (ehci, ehci->async);
+
+	/* ehci could run by timer, without IRQs ... */
 	ehci_work (ehci, NULL);
-	if (ehci->reclaim && !timer_pending (&ehci->watchdog))
-		mod_timer (&ehci->watchdog,
-				jiffies + EHCI_WATCHDOG_JIFFIES);
 
- 	/* stop async processing after it's idled a while */
-	else if (ehci->async_idle) {
- 		start_unlink_async (ehci, ehci->async);
- 		ehci->async_idle = 0;
-	}
 	spin_unlock_irqrestore (&ehci->lock, flags);
 }
 
@@ -658,11 +657,18 @@
  */
 static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
 {
+	timer_action_done (ehci, TIMER_IO_WATCHDOG);
 	if (ehci->reclaim_ready)
 		end_unlink_async (ehci, regs);
 	scan_async (ehci, regs);
 	if (ehci->next_uframe != -1)
 		scan_periodic (ehci, regs);
+
+	/* the IO watchdog guards against hardware or driver bugs that
+	 * misplace IRQs, and should let us run completely without IRQs.
+	 */
+	if ((ehci->async->qh_next.ptr != 0) || (ehci->periodic_sched != 0))
+		timer_action (ehci, TIMER_IO_WATCHDOG);
 }
 
 /*-------------------------------------------------------------------------*/
diff -urN linux-2.5.69-bk2/drivers/usb/host/ehci-q.c linux-2.5.69-bk3/drivers/usb/host/ehci-q.c
--- linux-2.5.69-bk2/drivers/usb/host/ehci-q.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/host/ehci-q.c	2003-05-08 04:38:19.000000000 -0700
@@ -706,8 +706,7 @@
 
 	/* (re)start the async schedule? */
 	head = ehci->async;
-	if (ehci->async_idle)
-		del_timer (&ehci->watchdog);
+	timer_action_done (ehci, TIMER_ASYNC_OFF);
 	if (!head->qh_next.qh) {
 		u32	cmd = readl (&ehci->regs->command);
 
@@ -733,8 +732,6 @@
 
 	qh->qh_state = QH_STATE_LINKED;
 	/* qtd completions reported later by interrupt */
-
-	ehci->async_idle = 0;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -915,7 +912,7 @@
 	struct ehci_qh		*qh = ehci->reclaim;
 	struct ehci_qh		*next;
 
-	del_timer (&ehci->watchdog);
+	timer_action_done (ehci, TIMER_IAA_WATCHDOG);
 
 	// qh->hw_next = cpu_to_le32 (qh->qh_dma);
 	qh->qh_state = QH_STATE_IDLE;
@@ -940,12 +937,8 @@
 		 * active but idle for a while once it empties.
 		 */
 		if (HCD_IS_RUNNING (ehci->hcd.state)
-				&& ehci->async->qh_next.qh == 0
-				&& !timer_pending (&ehci->watchdog)) {
-			ehci->async_idle = 1;
-			mod_timer (&ehci->watchdog,
-					jiffies + EHCI_ASYNC_JIFFIES);
-		}
+				&& ehci->async->qh_next.qh == 0)
+			timer_action (ehci, TIMER_ASYNC_OFF);
 	}
 
 	if (next)
@@ -980,6 +973,7 @@
 			wmb ();
 			// handshake later, if we need to
 		}
+		timer_action_done (ehci, TIMER_ASYNC_OFF);
 		return;
 	} 
 
@@ -1005,9 +999,8 @@
 	ehci->reclaim_ready = 0;
 	cmd |= CMD_IAAD;
 	writel (cmd, &ehci->regs->command);
-	/* posted write need not be known to HC yet ... */
-
-	mod_timer (&ehci->watchdog, jiffies + EHCI_WATCHDOG_JIFFIES);
+	(void) readl (&ehci->regs->command);
+	timer_action (ehci, TIMER_IAA_WATCHDOG);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1016,10 +1009,11 @@
 scan_async (struct ehci_hcd *ehci, struct pt_regs *regs)
 {
 	struct ehci_qh		*qh;
-	int			unlink_delay = 0;
+	enum ehci_timer_action	action = TIMER_IO_WATCHDOG;
 
 	if (!++(ehci->stamp))
 		ehci->stamp++;
+	timer_action_done (ehci, TIMER_ASYNC_SHRINK);
 rescan:
 	qh = ehci->async->qh_next.qh;
 	if (likely (qh != 0)) {
@@ -1051,17 +1045,14 @@
 			 */
 			if (list_empty (&qh->qtd_list)) {
 				if (qh->stamp == ehci->stamp)
-					unlink_delay = 1;
-				else if (!ehci->reclaim) {
+					action = TIMER_ASYNC_SHRINK;
+				else if (!ehci->reclaim)
 					start_unlink_async (ehci, qh);
-					unlink_delay = 0;
-				}
 			}
 
 			qh = qh->qh_next.qh;
 		} while (qh);
 	}
-
-	if (unlink_delay && !timer_pending (&ehci->watchdog))
-		mod_timer (&ehci->watchdog, jiffies + EHCI_WATCHDOG_JIFFIES/2);
+	if (action == TIMER_ASYNC_SHRINK)
+		timer_action (ehci, TIMER_ASYNC_SHRINK);
 }
diff -urN linux-2.5.69-bk2/drivers/usb/host/ehci.h linux-2.5.69-bk3/drivers/usb/host/ehci.h
--- linux-2.5.69-bk2/drivers/usb/host/ehci.h	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/host/ehci.h	2003-05-08 04:38:19.000000000 -0700
@@ -52,8 +52,7 @@
 	/* async schedule support */
 	struct ehci_qh		*async;
 	struct ehci_qh		*reclaim;
-	int			reclaim_ready : 1,
-				async_idle : 1;
+	int			reclaim_ready : 1;
 
 	/* periodic schedule support */
 #define	DEFAULT_I_TDPS		1024		/* some HCs can do less */
@@ -83,6 +82,7 @@
 
 	struct timer_list	watchdog;
 	struct notifier_block	reboot_notifier;
+	unsigned long		actions;
 	unsigned		stamp;
 
 	/* irq statistics */
@@ -100,6 +100,53 @@
 /* NOTE:  urb->transfer_flags expected to not use this bit !!! */
 #define EHCI_STATE_UNLINK	0x8000		/* urb being unlinked */
 
+enum ehci_timer_action {
+	TIMER_IO_WATCHDOG,
+	TIMER_IAA_WATCHDOG,
+	TIMER_ASYNC_SHRINK,
+	TIMER_ASYNC_OFF,
+};
+
+static inline void
+timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action)
+{
+	clear_bit (action, &ehci->actions);
+}
+
+static inline void
+timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
+{
+	if (!test_and_set_bit (action, &ehci->actions)) {
+		unsigned long t;
+
+		switch (action) {
+		case TIMER_IAA_WATCHDOG:
+			t = EHCI_IAA_JIFFIES;
+			break;
+		case TIMER_IO_WATCHDOG:
+			t = EHCI_IO_JIFFIES;
+			break;
+		case TIMER_ASYNC_OFF:
+			t = EHCI_ASYNC_JIFFIES;
+			break;
+		// case TIMER_ASYNC_SHRINK:
+		default:
+			t = EHCI_SHRINK_JIFFIES;
+			break;
+		}
+		t += jiffies;
+		// all timings except IAA watchdog can be overridden.
+		// async queue SHRINK often precedes IAA.  while it's ready
+		// to go OFF neither can matter, and afterwards the IO
+		// watchdog stops unless there's still periodic traffic.
+		if (action != TIMER_IAA_WATCHDOG
+				&& t > ehci->watchdog.expires
+				&& timer_pending (&ehci->watchdog))
+			return;
+		mod_timer (&ehci->watchdog, t);
+	}
+}
+
 /*-------------------------------------------------------------------------*/
 
 /* EHCI register interface, corresponds to EHCI Revision 0.95 specification */
diff -urN linux-2.5.69-bk2/drivers/usb/image/mdc800.c linux-2.5.69-bk3/drivers/usb/image/mdc800.c
--- linux-2.5.69-bk2/drivers/usb/image/mdc800.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/image/mdc800.c	2003-05-08 04:38:19.000000000 -0700
@@ -118,12 +118,8 @@
 #define TO_READ_FROM_IRQ 		TO_DEFAULT_COMMAND
 #define TO_GET_READY			TO_DEFAULT_COMMAND
 
-#ifdef CONFIG_USB_DYNAMIC_MINORS
-#define MDC800_DEVICE_MINOR_BASE 0
-#else
 /* Minor Number of the device (create with mknod /dev/mustek c 180 32) */
 #define MDC800_DEVICE_MINOR_BASE 32
-#endif
 
 
 /**************************************************************************
@@ -401,6 +397,13 @@
 
 static struct usb_driver mdc800_usb_driver;
 static struct file_operations mdc800_device_ops;
+static struct usb_class_driver mdc800_class = {
+	.name =		"usb/mdc800%d",
+	.fops =		&mdc800_device_ops,
+	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+	.minor_base =	MDC800_DEVICE_MINOR_BASE,
+};
+
 
 /*
  * Callback to search the Mustek MDC800 on the USB Bus
@@ -477,8 +480,8 @@
 
 	down (&mdc800->io_lock);
 
-	retval = usb_register_dev (&mdc800_device_ops, MDC800_DEVICE_MINOR_BASE, 1, &mdc800->minor);
-	if (retval && (retval != -ENODEV)) {
+	retval = usb_register_dev(intf, &mdc800_class);
+	if (retval) {
 		err ("Not able to get a minor for this device.");
 		return -ENODEV;
 	}
@@ -540,7 +543,7 @@
 		if (mdc800->state == NOT_CONNECTED)
 			return;
 
-		usb_deregister_dev (1, mdc800->minor);
+		usb_deregister_dev(intf, &mdc800_class);
 
 		mdc800->state=NOT_CONNECTED;
 
diff -urN linux-2.5.69-bk2/drivers/usb/image/scanner.c linux-2.5.69-bk3/drivers/usb/image/scanner.c
--- linux-2.5.69-bk2/drivers/usb/image/scanner.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/image/scanner.c	2003-05-08 04:38:19.000000000 -0700
@@ -397,7 +397,6 @@
  */
 
 
-#include <linux/devfs_fs_kernel.h>
 #include <asm/byteorder.h>
 
 /* 
@@ -464,7 +463,7 @@
 
 	dbg("open_scanner: scn_minor:%d", scn_minor);
 
-	intf = usb_find_interface(&scanner_driver, mk_kdev(USB_MAJOR,scn_minor));
+	intf = usb_find_interface(&scanner_driver, scn_minor);
 	if (!intf) {
 		up(&scn_mutex);
 		err("open_scanner(%d): Unable to access minor data", scn_minor);
@@ -843,9 +842,6 @@
 	kfree(scn->ibuf);
 	kfree(scn->obuf);
 
-	dbg("%s: De-allocating minor:%d", __FUNCTION__, scn->scn_minor);
-	devfs_remove("usb/scanner%d", scn->scn_minor - SCN_BASE_MNR);
-	usb_deregister_dev(1, scn->scn_minor);
 	usb_free_urb(scn->scn_irq);
 	usb_put_dev(scn->scn_dev);
 	up (&(scn->sem));
@@ -867,6 +863,13 @@
 	.release =	close_scanner,
 };
 
+static struct usb_class_driver scanner_class = {
+	.name =		"usb/scanner%d",
+	.fops =		&usb_scanner_fops,
+	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
+	.minor_base =	SCN_BASE_MNR,
+};
+
 static int
 probe_scanner(struct usb_interface *intf,
 	      const struct usb_device_id *id)
@@ -878,7 +881,6 @@
 
 	int ep_cnt;
 	int ix;
-	int scn_minor;
 	int retval;
 
 	char valid_device = 0;
@@ -1011,14 +1013,14 @@
 	
 	down(&scn_mutex);
 
-	retval = usb_register_dev(&usb_scanner_fops, SCN_BASE_MNR, 1, &scn_minor);
+	retval = usb_register_dev(intf, &scanner_class);
 	if (retval) {
 		err ("Not able to get a minor for this device.");
 		up(&scn_mutex);
 		return -ENOMEM;
 	}
 
-	dbg("probe_scanner: Allocated minor:%d", scn_minor);
+	dbg("probe_scanner: Allocated minor:%d", intf->minor);
 
 	if (!(scn = kmalloc (sizeof (struct scn_usb_data), GFP_KERNEL))) {
 		err("probe_scanner: Out of memory.");
@@ -1038,11 +1040,11 @@
 
 	init_MUTEX(&(scn->sem)); /* Initializes to unlocked */
 
-	dbg ("probe_scanner(%d): Address of scn:%p", scn_minor, scn);
+	dbg ("probe_scanner(%d): Address of scn:%p", intf->minor, scn);
 
 /* Ok, if we detected an interrupt EP, setup a handler for it */
 	if (have_intr) {
-		dbg("probe_scanner(%d): Configuring IRQ handler for intr EP:%d", scn_minor, have_intr);
+		dbg("probe_scanner(%d): Configuring IRQ handler for intr EP:%d", intf->minor, have_intr);
 		usb_fill_int_urb(scn->scn_irq, dev,
 			     usb_rcvintpipe(dev, have_intr),
 			     &scn->button, 1, irq_scanner, scn,
@@ -1050,7 +1052,7 @@
 			     250);
 
 	        if (usb_submit_urb(scn->scn_irq, GFP_KERNEL)) {
-			err("probe_scanner(%d): Unable to allocate INT URB.", scn_minor);
+			err("probe_scanner(%d): Unable to allocate INT URB.", intf->minor);
                 	kfree(scn);
 			up(&scn_mutex);
                 	return -ENOMEM;
@@ -1060,21 +1062,21 @@
 
 /* Ok, now initialize all the relevant values */
 	if (!(scn->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {
-		err("probe_scanner(%d): Not enough memory for the output buffer.", scn_minor);
+		err("probe_scanner(%d): Not enough memory for the output buffer.", intf->minor);
 		kfree(scn);
 		up(&scn_mutex);
 		return -ENOMEM;
 	}
-	dbg("probe_scanner(%d): obuf address:%p", scn_minor, scn->obuf);
+	dbg("probe_scanner(%d): obuf address:%p", intf->minor, scn->obuf);
 
 	if (!(scn->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {
-		err("probe_scanner(%d): Not enough memory for the input buffer.", scn_minor);
+		err("probe_scanner(%d): Not enough memory for the input buffer.", intf->minor);
 		kfree(scn->obuf);
 		kfree(scn);
 		up(&scn_mutex);
 		return -ENOMEM;
 	}
-	dbg("probe_scanner(%d): ibuf address:%p", scn_minor, scn->ibuf);
+	dbg("probe_scanner(%d): ibuf address:%p", intf->minor, scn->ibuf);
 	
 
 	switch (dev->descriptor.idVendor) { /* Scanner specific read timeout parameters */
@@ -1101,17 +1103,9 @@
 	scn->intr_ep = have_intr;
 	scn->present = 1;
 	scn->scn_dev = dev;
-	scn->scn_minor = scn_minor;
+	scn->scn_minor = intf->minor;
 	scn->isopen = 0;
 
-	sprintf(name, "usb/scanner%d", scn->scn_minor - SCN_BASE_MNR);
-	
-	devfs_register(NULL, name,
-				    DEVFS_FL_DEFAULT, USB_MAJOR,
-				    scn->scn_minor,
-				    S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
-				    S_IWGRP | S_IROTH | S_IWOTH, &usb_scanner_fops, NULL);
-
 	info ("USB scanner device (0x%04x/0x%04x) now attached to %s",
 	      dev->descriptor.idVendor, dev->descriptor.idProduct, name);
 
@@ -1119,9 +1113,6 @@
 
 	usb_set_intfdata(intf, scn);
 
-	/* add device id so the device works when advertised */
-	intf->kdev = mk_kdev(USB_MAJOR,scn->scn_minor);
-
 	return 0;
 }
 
@@ -1130,8 +1121,9 @@
 {
 	struct scn_usb_data *scn = usb_get_intfdata(intf);
 
-	/* remove device id to disable open() */
-	intf->kdev = NODEV;
+	/* disable open() */
+	dbg("%s: De-allocating minor:%d", __FUNCTION__, scn->scn_minor);
+	usb_deregister_dev(intf, &scanner_class);
 
 	usb_set_intfdata(intf, NULL);
 	if(scn->intr_ep) {
diff -urN linux-2.5.69-bk2/drivers/usb/image/scanner.h linux-2.5.69-bk3/drivers/usb/image/scanner.h
--- linux-2.5.69-bk2/drivers/usb/image/scanner.h	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/image/scanner.h	2003-05-08 04:38:19.000000000 -0700
@@ -323,13 +323,7 @@
    USB - Vivid III */
 #define SCN_CLASS_SCANJET 16
 
-#ifdef CONFIG_USB_DYNAMIC_MINORS
-#define SCN_MAX_MNR 256
-#define SCN_BASE_MNR 0
-#else
-#define SCN_MAX_MNR 16		/* We're allocated 16 minors */
 #define SCN_BASE_MNR 48		/* USB Scanners start at minor 48 */
-#endif
 
 static DECLARE_MUTEX (scn_mutex); /* Initializes to unlocked */
 
diff -urN linux-2.5.69-bk2/drivers/usb/input/hiddev.c linux-2.5.69-bk3/drivers/usb/input/hiddev.c
--- linux-2.5.69-bk2/drivers/usb/input/hiddev.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/input/hiddev.c	2003-05-08 04:38:19.000000000 -0700
@@ -53,6 +53,7 @@
 	wait_queue_head_t wait;
 	struct hid_device *hid;
 	struct hiddev_list *list;
+	struct usb_interface intf;
 };
 
 struct hiddev_list {
@@ -226,10 +227,10 @@
 /*
  * De-allocate a hiddev structure
  */
+static struct usb_class_driver hiddev_class;
 static void hiddev_cleanup(struct hiddev *hiddev)
 {
-	devfs_remove("usb/hid/hiddev%d", hiddev->minor);
-	usb_deregister_dev(1, hiddev->minor);
+	usb_deregister_dev(&hiddev->intf, &hiddev_class);
 	hiddev_table[hiddev->minor] = NULL;
 	kfree(hiddev);
 }
@@ -675,15 +676,21 @@
 	.fasync =	hiddev_fasync,
 };
 
+static struct usb_class_driver hiddev_class = {
+	.name =		"usb/hid/hiddev%d",
+	.fops =		&hiddev_fops,
+	.mode =		S_IFCHR | S_IRUGO | S_IWUSR,
+       	.minor_base =	HIDDEV_MINOR_BASE,
+};
+
 /*
  * This is where hid.c calls us to connect a hid device to the hiddev driver
  */
 int hiddev_connect(struct hid_device *hid)
 {
 	struct hiddev *hiddev;
-	int minor, i;
+	int i;
 	int retval;
-	char devfs_name[24];
 
 	for (i = 0; i < hid->maxcollection; i++)
 		if (hid->collection[i].type == 
@@ -694,31 +701,25 @@
 	if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0)
 		return -1;
 
-	retval = usb_register_dev(&hiddev_fops, HIDDEV_MINOR_BASE, 1, &minor);
-	if (retval) {
-		err("Not able to get a minor for this device.");
+ 	if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL)))
 		return -1;
-	}
+	memset(hiddev, 0, sizeof(struct hiddev));
 
-	if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) {
-		usb_deregister_dev (1, minor);
+ 	retval = usb_register_dev(&hiddev->intf, &hiddev_class);
+	if (retval) {
+		err("Not able to get a minor for this device.");
 		return -1;
 	}
-	memset(hiddev, 0, sizeof(struct hiddev));
 
 	init_waitqueue_head(&hiddev->wait);
 
-	hiddev->minor = minor;
-	hiddev_table[minor - HIDDEV_MINOR_BASE] = hiddev;
+ 	hiddev->minor = hiddev->intf.minor;
+ 	hiddev_table[hiddev->intf.minor - HIDDEV_MINOR_BASE] = hiddev;
 
 	hiddev->hid = hid;
 	hiddev->exist = 1;
 
-	sprintf(devfs_name, "usb/hid/hiddev%d", minor);
-	devfs_register(NULL, devfs_name, 0,
-		USB_MAJOR, minor + HIDDEV_MINOR_BASE,
-		S_IFCHR | S_IRUGO | S_IWUSR, &hiddev_fops, NULL);
-	hid->minor = minor;
+ 	hid->minor = hiddev->intf.minor;
 	hid->hiddev = hiddev;
 
 	return 0;
diff -urN linux-2.5.69-bk2/drivers/usb/input/xpad.c linux-2.5.69-bk3/drivers/usb/input/xpad.c
--- linux-2.5.69-bk2/drivers/usb/input/xpad.c	2003-05-04 16:53:28.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/input/xpad.c	2003-05-08 04:38:19.000000000 -0700
@@ -61,7 +61,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/smp_lock.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/usb.h>
 
 #define DRIVER_VERSION "v0.0.5"
diff -urN linux-2.5.69-bk2/drivers/usb/media/dabusb.c linux-2.5.69-bk3/drivers/usb/media/dabusb.c
--- linux-2.5.69-bk2/drivers/usb/media/dabusb.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/media/dabusb.c	2003-05-08 04:38:19.000000000 -0700
@@ -712,12 +712,19 @@
 	.release =	dabusb_release,
 };
 
+static struct usb_class_driver dabusb_class = {
+	.name =		"usb/dabusb%d",
+	.fops =		&dabusb_fops,
+	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+	.minor_base =	DABUSB_MINOR,
+};
+
+
 /* --------------------------------------------------------------------- */
 static int dabusb_probe (struct usb_interface *intf, 
 			 const struct usb_device_id *id)
 {
 	struct usb_device *usbdev = interface_to_usbdev(intf);
-	int devnum;
 	int retval;
 	pdabusb_t s;
 
@@ -731,16 +738,16 @@
 	if (intf->altsetting->desc.bInterfaceNumber != _DABUSB_IF && usbdev->descriptor.idProduct == 0x9999)
 		return -ENODEV;
 
-	retval = usb_register_dev (&dabusb_fops, DABUSB_MINOR, 1, &devnum);
+	retval = usb_register_dev(intf, &dabusb_class);
 	if (retval)
 		return -ENOMEM;
 
-	s = &dabusb[devnum];
+	s = &dabusb[intf->minor];
 
 	down (&s->mutex);
 	s->remove_pending = 0;
 	s->usbdev = usbdev;
-	s->devnum = devnum;
+	s->devnum = intf->minor;
 
 	if (usb_set_configuration (usbdev, usbdev->config[0].desc.bConfigurationValue) < 0) {
 		err("set_configuration failed");
@@ -778,7 +785,7 @@
 
 	usb_set_intfdata (intf, NULL);
 	if (s) {
-		usb_deregister_dev (1, s->devnum);
+		usb_deregister_dev (intf, &dabusb_class);
 		s->remove_pending = 1;
 		wake_up (&s->wait);
 		if (s->state == _started)
diff -urN linux-2.5.69-bk2/drivers/usb/media/dabusb.h linux-2.5.69-bk3/drivers/usb/media/dabusb.h
--- linux-2.5.69-bk2/drivers/usb/media/dabusb.h	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/media/dabusb.h	2003-05-08 04:38:19.000000000 -0700
@@ -6,11 +6,7 @@
 	unsigned int pipe;
 }bulk_transfer_t,*pbulk_transfer_t;
 
-#ifdef CONFIG_USB_DYNAMIC_MINORS
-#define DABUSB_MINOR 0
-#else
 #define DABUSB_MINOR 240		/* some unassigned USB minor */
-#endif
 #define DABUSB_VERSION 0x1000
 #define IOCTL_DAB_BULK              _IOWR('d', 0x30, bulk_transfer_t)
 #define IOCTL_DAB_OVERRUNS	    _IOR('d',  0x15, int)
diff -urN linux-2.5.69-bk2/drivers/usb/media/vicam.c linux-2.5.69-bk3/drivers/usb/media/vicam.c
--- linux-2.5.69-bk2/drivers/usb/media/vicam.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/media/vicam.c	2003-05-08 04:38:19.000000000 -0700
@@ -1101,28 +1101,6 @@
 				((struct vicam_camera *)data)->gain);
 }
 
-static int vicam_write_proc_shutter(struct file *file, const char *buffer,
-				unsigned long count, void *data)
-{
-	struct vicam_camera *cam = (struct vicam_camera *)data;
-	
-	cam->shutter_speed = simple_strtoul(buffer, NULL, 10);
-
-	return count;
-}
-
-static int vicam_write_proc_gain(struct file *file, const char *buffer,
-				unsigned long count, void *data)
-{
-	struct vicam_camera *cam = (struct vicam_camera *)data;
-	
-	cam->gain = simple_strtoul(buffer, NULL, 10);
-
-	return count;
-}
-
-
-
 static void
 vicam_create_proc_root(void)
 {
@@ -1164,21 +1142,17 @@
 	if ( !cam->proc_dir ) return; // We should probably return an error here
 	
 	ent =
-	    create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR,
-			      cam->proc_dir);
+	    create_proc_entry("shutter", S_IFREG | S_IRUGO, cam->proc_dir);
 	if (ent) {
 		ent->data = cam;
 		ent->read_proc = vicam_read_proc_shutter;
-		ent->write_proc = vicam_write_proc_shutter;
 		ent->size = 64;
 	}
 
-	ent = create_proc_entry("gain", S_IFREG | S_IRUGO | S_IWUSR,
-					cam->proc_dir);
+	ent = create_proc_entry("gain", S_IFREG | S_IRUGO , cam->proc_dir);
 	if ( ent ) {
 		ent->data = cam;
 		ent->read_proc = vicam_read_proc_gain;
-		ent->write_proc = vicam_write_proc_gain;
 		ent->size = 64;
 	}
 }
diff -urN linux-2.5.69-bk2/drivers/usb/misc/auerswald.c linux-2.5.69-bk3/drivers/usb/misc/auerswald.c
--- linux-2.5.69-bk2/drivers/usb/misc/auerswald.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/misc/auerswald.c	2003-05-08 04:38:19.000000000 -0700
@@ -29,7 +29,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/devfs_fs_kernel.h>
 #undef DEBUG   		/* include debug macros until it's done	*/
 #include <linux/usb.h>
 
@@ -60,16 +59,10 @@
 /* Auerswald Vendor ID */
 #define ID_AUERSWALD  	0x09BF
 
-#ifdef CONFIG_USB_DYNAMIC_MINORS
-/* we can have up to 256 devices at once */
-#define AUER_MINOR_BASE	0
-#define AUER_MAX_DEVICES 256
-#else
 #define AUER_MINOR_BASE	112	/* auerswald driver minor number */
 
 /* we can have up to this number of device plugged in at once */
 #define AUER_MAX_DEVICES 16
-#endif
 
 
 /* Number of read buffers for each device */
@@ -256,12 +249,6 @@
 	wait_queue_head_t 	bufferwait;         /* wait for a control buffer */
 } auerswald_t,*pauerswald_t;
 
-/* array of pointers to our devices that are currently connected */
-static pauerswald_t dev_table[AUER_MAX_DEVICES];
-
-/* lock to protect the dev_table structure */
-static struct semaphore dev_table_mutex;
-
 /* ................................................................... */
 /* character device context */
 typedef struct
@@ -1384,29 +1371,29 @@
 /* Open a new character device */
 static int auerchar_open (struct inode *inode, struct file *file)
 {
-	int dtindex = minor(inode->i_rdev) - AUER_MINOR_BASE;
+	int dtindex = minor(inode->i_rdev);
 	pauerswald_t cp = NULL;
 	pauerchar_t ccp = NULL;
+	struct usb_interface *intf;
         int ret;
 
         /* minor number in range? */
-	if ((dtindex < 0) || (dtindex >= AUER_MAX_DEVICES)) {
+	if (dtindex < 0) {
 		return -ENODEV;
         }
-	/* usb device available? */
-	if (down_interruptible (&dev_table_mutex)) {
-		return -ERESTARTSYS;
+	intf = usb_find_interface(&auerswald_driver, dtindex);
+	if (!intf) {
+		return -ENODEV;
 	}
-	cp = dev_table[dtindex];
+
+	/* usb device available? */
+	cp = usb_get_intfdata (intf);
 	if (cp == NULL) {
-		up (&dev_table_mutex);
 		return -ENODEV;
 	}
 	if (down_interruptible (&cp->mutex)) {
-		up (&dev_table_mutex);
 		return -ERESTARTSYS;
 	}
-	up (&dev_table_mutex);
 
 	/* we have access to the device. Now lets allocate memory */
 	ccp = (pauerchar_t) kmalloc(sizeof(auerchar_t), GFP_KERNEL);
@@ -1895,6 +1882,13 @@
 	.release =	auerchar_release,
 };
 
+static struct usb_class_driver auerswald_class = {
+	.name =		"usb/auer%d",
+	.fops =		&auerswald_fops,
+	.mode =		S_IFCHR | S_IRUGO | S_IWUGO,
+	.minor_base =	AUER_MINOR_BASE,
+};
+
 
 /* --------------------------------------------------------------------- */
 /* Special USB driver functions                                          */
@@ -1923,7 +1917,6 @@
 	struct usb_device *usbdev = interface_to_usbdev(intf);
 	pauerswald_t cp = NULL;
 	DECLARE_WAIT_QUEUE_HEAD (wqh);
-	unsigned int dtindex;
 	unsigned int u = 0;
 	char *pbuf;
 	int ret;
@@ -1954,27 +1947,17 @@
         auerbuf_init (&cp->bufctl);
 	init_waitqueue_head (&cp->bufferwait);
 
-	down (&dev_table_mutex);
-	ret = usb_register_dev (&auerswald_fops, AUER_MINOR_BASE, 1, &dtindex);
+	ret = usb_register_dev(intf, &auerswald_class);
 	if (ret) {
 		err ("Not able to get a minor for this device.");
-		up (&dev_table_mutex);
 		goto pfail;
 	}
 
 	/* Give the device a name */
-	sprintf (cp->name, "usb/auer%d", dtindex);
+	sprintf (cp->name, "usb/auer%d", intf->minor);
 
 	/* Store the index */
-	cp->dtindex = dtindex;
-	dev_table[dtindex] = cp;
-	up (&dev_table_mutex);
-
-	/* initialize the devfs node for this device and register it */
-	devfs_register(NULL, cp->name, 0, USB_MAJOR,
-				    AUER_MINOR_BASE + dtindex,
-				    S_IFCHR | S_IRUGO | S_IWUGO,
-				    &auerswald_fops, NULL);
+	cp->dtindex = intf->minor;
 
 	/* Get the usb version of the device */
 	cp->version = cp->usbdev->descriptor.bcdDevice;
@@ -2083,18 +2066,8 @@
 	down (&cp->mutex);
 	info ("device /dev/%s now disconnecting", cp->name);
 
-	/* remove from device table */
-	/* Nobody can open() this device any more */
-	down (&dev_table_mutex);
-	dev_table[cp->dtindex] = NULL;
-	up (&dev_table_mutex);
-
-	/* remove our devfs node */
-	/* Nobody can see this device any more */
-	devfs_remove(cp->name);
-
 	/* give back our USB minor number */
-	usb_deregister_dev (1, cp->dtindex);
+	usb_deregister_dev(intf, &auerswald_class);
 
 	/* Stop the interrupt endpoint */
 	auerswald_int_release (cp);
@@ -2163,10 +2136,6 @@
 	int result;
 	dbg ("init");
 
-	/* initialize the device table */
-	memset (&dev_table, 0, sizeof(dev_table));
-	init_MUTEX (&dev_table_mutex);
-
 	/* register driver at the USB subsystem */
 	result = usb_register (&auerswald_driver);
 	if (result < 0) {
diff -urN linux-2.5.69-bk2/drivers/usb/misc/brlvger.c linux-2.5.69-bk3/drivers/usb/misc/brlvger.c
--- linux-2.5.69-bk2/drivers/usb/misc/brlvger.c	2003-05-04 16:53:29.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/misc/brlvger.c	2003-05-08 04:38:19.000000000 -0700
@@ -50,7 +50,6 @@
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
 #include <linux/poll.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/brlvger.h>
 
 MODULE_AUTHOR( DRIVER_AUTHOR );
@@ -180,12 +179,6 @@
 
 /* Globals */
 
-/* Table of connected devices, a different minor for each. */
-static struct brlvger_priv *display_table[ MAX_NR_BRLVGER_DEVS ];
-
-/* Mutex for the operation of removing a device from display_table */
-static DECLARE_MUTEX(disconnect_sem);
-
 /* For blocking open */
 static DECLARE_WAIT_QUEUE_HEAD(open_wait);
 
@@ -237,6 +230,13 @@
 	.poll =		brlvger_poll,
 };
 
+static struct usb_class_driver brlvger_class = {
+	.name =		"usb/brlvger%d",
+	.fops =		&brlvger_fops,
+	.mode =		S_IFCHR | S_IRUSR |S_IWUSR | S_IRGRP | S_IWGRP,
+	.minor_base =	BRLVGER_MINOR,
+};
+
 static struct usb_driver brlvger_driver =
 {
 	.owner =	THIS_MODULE,
@@ -254,8 +254,6 @@
 	if(stall_tries < 1 || write_repeats < 1)
 	  return -EINVAL;
 
-	memset(display_table, 0, sizeof(display_table));
-
 	if (usb_register(&brlvger_driver)) {
 		err("USB registration failed");
 		return -ENOSYS;
@@ -284,14 +282,12 @@
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
 	struct brlvger_priv *priv = NULL;
-	int i;
 	int retval;
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_host_interface *actifsettings;
 	/* protects against reentrance: once we've found a free slot
 	   we reserve it.*/
 	static DECLARE_MUTEX(reserve_sem);
-        char devfs_name[20];
 
 	actifsettings = dev->actconfig->interface->altsetting;
 
@@ -311,7 +307,7 @@
 
 	down(&reserve_sem);
 
-	retval = usb_register_dev(&brlvger_fops, BRLVGER_MINOR, 1, &i);
+	retval = usb_register_dev(intf, &brlvger_class);
 	if (retval) {
 		err("Not able to get a minor for this device.");
 		goto error;
@@ -331,7 +327,7 @@
 	init_MUTEX(&priv->open_sem);
 	init_MUTEX(&priv->dev_sem);
 
-	priv->subminor = i;
+	priv->subminor = intf->minor;
 
 	/* we found a interrupt in endpoint */
 	priv->in_interrupt = endpoint;
@@ -372,17 +368,9 @@
 	};
 	dbg("Display length: %d", priv->plength);
 
-	sprintf(devfs_name, "usb/brlvger%d", priv->subminor);
-	devfs_register(NULL, devfs_name,
-				     DEVFS_FL_DEFAULT, USB_MAJOR,
-				     BRLVGER_MINOR+priv->subminor,
-				     S_IFCHR |S_IRUSR|S_IWUSR |S_IRGRP|S_IWGRP,
-				     &brlvger_fops, NULL);
-
-	display_table[i] = priv;
-
+	usb_set_intfdata (intf, priv);
 	info( "Braille display %d is device major %d minor %d",
-				i, USB_MAJOR, BRLVGER_MINOR + i);
+				intf->minor, USB_MAJOR, BRLVGER_MINOR + intf->minor);
 
 	/* Tell anyone waiting on a blocking open */
 	wake_up_interruptible(&open_wait);
@@ -414,12 +402,7 @@
 	if(priv){
 		info("Display %d disconnecting", priv->subminor);
 
-		devfs_remove("usb/brlvger%d", priv->subminor);
-		usb_deregister_dev(1, priv->subminor);
-
-		down(&disconnect_sem);
-		display_table[priv->subminor] = NULL;
-		up(&disconnect_sem);
+		usb_deregister_dev(intf, &brlvger_class);
 
 		down(&priv->open_sem);
 		down(&priv->dev_sem);
@@ -450,21 +433,18 @@
 brlvger_open(struct inode *inode, struct file *file)
 {
 	int devnum = minor (inode->i_rdev);
-	struct brlvger_priv *priv;
+	struct usb_interface *intf = NULL;
+	struct brlvger_priv *priv = NULL;
 	int n, ret;
 
-	if (devnum < BRLVGER_MINOR
-	    || devnum >= (BRLVGER_MINOR + MAX_NR_BRLVGER_DEVS))
+	if (devnum < 0)
 		return -ENXIO;
 
 	n = devnum - BRLVGER_MINOR;
 
 	do {
-		down(&disconnect_sem);
-		priv = display_table[n];
-		
-		if(!priv) {
-			up(&disconnect_sem);
+		intf = usb_find_interface(&brlvger_driver, devnum);
+		if (!intf) {
 			if (file->f_flags & O_NONBLOCK) {
 				dbg3("Failing non-blocking open: "
 				     "device %d not connected", n);
@@ -475,19 +455,18 @@
 			   minor is connected. */
 			dbg2("Waiting for device %d to be connected", n);
 			ret = wait_event_interruptible(open_wait,
-						       display_table[n]
-						       != NULL);
-			if(ret) {
+						       (intf = usb_find_interface(&brlvger_driver, devnum)));
+			if (ret) {
 				dbg2("Interrupted wait for device %d", n);
 				return ret;
 			}
 		}
-	} while(!priv);
-	/* We grabbed an existing device. */
+	} while(!intf);
+	priv = usb_get_intfdata(intf);
 
+	/* We grabbed an existing device. */
 	if(down_interruptible(&priv->open_sem))
 		return -ERESTARTSYS;
-	up(&disconnect_sem);
 
 	/* Only one process can open each device, no sharing. */
 	ret = -EBUSY;
diff -urN linux-2.5.69-bk2/drivers/usb/misc/rio500.c linux-2.5.69-bk3/drivers/usb/misc/rio500.c
--- linux-2.5.69-bk2/drivers/usb/misc/rio500.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/misc/rio500.c	2003-05-08 04:38:19.000000000 -0700
@@ -38,7 +38,6 @@
 #include <linux/spinlock.h>
 #include <linux/usb.h>
 #include <linux/smp_lock.h>
-#include <linux/devfs_fs_kernel.h>
 
 #include "rio500_usb.h"
 
@@ -49,11 +48,7 @@
 #define DRIVER_AUTHOR "Cesar Miquel <miquel@df.uba.ar>"
 #define DRIVER_DESC "USB Rio 500 driver"
 
-#ifdef CONFIG_USB_DYNAMIC_MINORS
-	#define RIO_MINOR	0
-#else
-	#define RIO_MINOR	64
-#endif
+#define RIO_MINOR	64
 
 /* stall/wait timeout for rio */
 #define NAK_TIMEOUT (HZ)
@@ -68,7 +63,6 @@
         unsigned int ifnum;             /* Interface number of the USB device */
         int isopen;                     /* nz if open */
         int present;                    /* Device is present on the bus */
-	int minor;			/* minor number assigned to us */
         char *obuf, *ibuf;              /* transfer buffers */
         char bulk_in_ep, bulk_out_ep;   /* Endpoint assignments */
         wait_queue_head_t wait_q;       /* for timeouts */
@@ -444,6 +438,13 @@
 	.release =	close_rio,
 };
 
+static struct usb_class_driver usb_rio_class = {
+	.name =		"usb/rio500%d",
+	.fops =		&usb_rio_fops,
+	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+	.minor_base =	RIO_MINOR,
+};
+
 static int probe_rio(struct usb_interface *intf,
 		     const struct usb_device_id *id)
 {
@@ -453,7 +454,7 @@
 
 	info("USB Rio found at address %d", dev->devnum);
 
-	retval = usb_register_dev(&usb_rio_fops, RIO_MINOR, 1, &rio->minor);
+	retval = usb_register_dev(intf, &usb_rio_class);
 	if (retval) {
 		err("Not able to get a minor for this device.");
 		return -ENOMEM;
@@ -464,23 +465,19 @@
 
 	if (!(rio->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
 		err("probe_rio: Not enough memory for the output buffer");
+		usb_deregister_dev(intf, &usb_rio_class);
 		return -ENOMEM;
 	}
 	dbg("probe_rio: obuf address:%p", rio->obuf);
 
 	if (!(rio->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) {
 		err("probe_rio: Not enough memory for the input buffer");
+		usb_deregister_dev(intf, &usb_rio_class);
 		kfree(rio->obuf);
 		return -ENOMEM;
 	}
 	dbg("probe_rio: ibuf address:%p", rio->ibuf);
 
-	devfs_register(NULL, "usb/rio500",
-				    DEVFS_FL_DEFAULT, USB_MAJOR,
-				    RIO_MINOR,
-				    S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
-				    S_IWGRP, &usb_rio_fops, NULL);
-
 	init_MUTEX(&(rio->lock));
 
 	usb_set_intfdata (intf, rio);
@@ -493,8 +490,7 @@
 
 	usb_set_intfdata (intf, NULL);
 	if (rio) {
-		devfs_remove("usb/rio500");
-		usb_deregister_dev(1, rio->minor);
+		usb_deregister_dev(intf, &usb_rio_class);
 
 		down(&(rio->lock));
 		if (rio->isopen) {
diff -urN linux-2.5.69-bk2/drivers/usb/misc/speedtch.c linux-2.5.69-bk3/drivers/usb/misc/speedtch.c
--- linux-2.5.69-bk2/drivers/usb/misc/speedtch.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/misc/speedtch.c	2003-05-08 04:38:19.000000000 -0700
@@ -74,6 +74,7 @@
 #include <linux/atm.h>
 #include <linux/atmdev.h>
 #include <linux/crc32.h>
+#include <linux/init.h>
 
 /*
 #define DEBUG 1
diff -urN linux-2.5.69-bk2/drivers/usb/misc/tiglusb.c linux-2.5.69-bk3/drivers/usb/misc/tiglusb.c
--- linux-2.5.69-bk2/drivers/usb/misc/tiglusb.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/misc/tiglusb.c	2003-05-08 04:38:19.000000000 -0700
@@ -327,7 +327,6 @@
 	int minor = -1;
 	int i;
 	ptiglusb_t s;
-	char name[32];
 
 	dbg ("probing vendor id 0x%x, device id 0x%x",
 	     dev->descriptor.idVendor, dev->descriptor.idProduct);
@@ -371,12 +370,9 @@
 	up (&s->mutex);
 	dbg ("bound to interface");
 
-	sprintf (name, "ticables/usb/%d", s->minor);
-	dbg ("registering to devfs : major = %d, minor = %d, node = %s",
-	     TIUSB_MAJOR, (TIUSB_MINOR + s->minor), name);
-	devfs_register(NULL, name, DEVFS_FL_DEFAULT, TIUSB_MAJOR,
-		       TIUSB_MINOR + s->minor, S_IFCHR | S_IRUGO | S_IWUGO,
-		       &tiglusb_fops, NULL);
+	devfs_mk_cdev(MAJOR(TIUSB_MAJOR, TIUSB_MINOR + s->minor),
+			S_IFCHR | S_IRUGO | S_IWUGO,
+			"ticables/usb/%d", s->minor);
 
 	/* Display firmware version */
 	info ("firmware revision %i.%02x",
@@ -390,8 +386,6 @@
 static void
 tiglusb_disconnect (struct usb_interface *intf)
 {
-	char name[32];
-
 	ptiglusb_t s = usb_get_intfdata (intf);
 
 	usb_set_intfdata (intf, NULL);
@@ -408,7 +402,7 @@
 	s->dev = NULL;
 	s->opened = 0;
 
-	devfs_remove (name, "ticables/usb/%d", s->minor);
+	devfs_remove("ticables/usb/%d", s->minor);
 
 	info ("device %d removed", s->minor);
 
diff -urN linux-2.5.69-bk2/drivers/usb/misc/usblcd.c linux-2.5.69-bk3/drivers/usb/misc/usblcd.c
--- linux-2.5.69-bk2/drivers/usb/misc/usblcd.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/misc/usblcd.c	2003-05-08 04:38:19.000000000 -0700
@@ -34,7 +34,6 @@
 struct lcd_usb_data {
 	struct usb_device *lcd_dev;	/* init: probe_lcd */
 	unsigned int ifnum;		/* Interface number of the USB device */
-	int minor;			/* minor number for this device */
 	int isopen;			/* nz if open */
 	int present;			/* Device is present on the bus */
 	char *obuf, *ibuf;		/* transfer buffers */
@@ -245,6 +244,13 @@
 	.release =	close_lcd,
 };
 
+static struct usb_class_driver usb_lcd_class = {
+	.name =		"usb/lcd%d",
+	.fops =		&usb_lcd_fops,
+	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+	.minor_base =	USBLCD_MINOR,
+};
+
 static int probe_lcd(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
@@ -268,23 +274,25 @@
 		(i & 0xF000)>>12,(i & 0xF00)>>8,(i & 0xF0)>>4,(i & 0xF),
 		dev->devnum);
 
-	retval = usb_register_dev(&usb_lcd_fops, USBLCD_MINOR, 1, &lcd->minor);
+	retval = usb_register_dev(intf, &usb_lcd_class);
 	if (retval) {
 		err("Not able to get a minor for this device.");
 		return -ENOMEM;
 	}
-	
+
 	lcd->present = 1;
 	lcd->lcd_dev = dev;
 
 	if (!(lcd->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
 		err("probe_lcd: Not enough memory for the output buffer");
+		usb_deregister_dev(intf, &usb_lcd_class);
 		return -ENOMEM;
 	}
 	dbg("probe_lcd: obuf address:%p", lcd->obuf);
 
 	if (!(lcd->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) {
 		err("probe_lcd: Not enough memory for the input buffer");
+		usb_deregister_dev(intf, &usb_lcd_class);
 		kfree(lcd->obuf);
 		return -ENOMEM;
 	}
@@ -300,7 +308,7 @@
 
 	usb_set_intfdata (intf, NULL);
 	if (lcd) {
-		usb_deregister_dev(1, lcd->minor);
+		usb_deregister_dev(intf, &usb_lcd_class);
 
 		if (lcd->isopen) {
 			lcd->isopen = 0;
diff -urN linux-2.5.69-bk2/drivers/usb/net/rtl8150.c linux-2.5.69-bk3/drivers/usb/net/rtl8150.c
--- linux-2.5.69-bk2/drivers/usb/net/rtl8150.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/net/rtl8150.c	2003-05-08 04:38:19.000000000 -0700
@@ -16,7 +16,6 @@
 #include <linux/etherdevice.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/usb.h>
 #include <asm/uaccess.h>
 
@@ -106,7 +105,6 @@
 
 typedef struct rtl8150 rtl8150_t;
 
-/* the global usb devfs handle */
 unsigned long multicast_filter_limit = 32;
 
 static void fill_skb_pool(rtl8150_t *);
@@ -160,7 +158,7 @@
 	clear_bit(RX_REG_SET, &dev->flags);
 }
 
-static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
+static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size)
 {
 	int ret;
 
@@ -537,7 +535,8 @@
 		warn("%s - device reset failed", __FUNCTION__);
 	}
 	/* RCR bit7=1 attach Rx info at the end;  =0 HW CRC (which is broken) */
-	dev->rx_creg = rcr = 0x9e;
+	rcr = 0x9e;	/* bit7=1 attach Rx info at the end */
+	dev->rx_creg = cpu_to_le16(rcr);
 	tcr = 0xd8;
 	cr = 0x0c;
 	if (!(rcr & 0x80))
@@ -584,18 +583,18 @@
 	dev = netdev->priv;
 	netif_stop_queue(netdev);
 	if (netdev->flags & IFF_PROMISC) {
-		dev->rx_creg |= 0x0001;
+		dev->rx_creg |= cpu_to_le16(0x0001);
 		info("%s: promiscuous mode", netdev->name);
 	} else if ((netdev->mc_count > multicast_filter_limit) ||
 		   (netdev->flags & IFF_ALLMULTI)) {
-		dev->rx_creg &= 0xfffe;
-		dev->rx_creg |= 0x0002;
+		dev->rx_creg &= cpu_to_le16(0xfffe);
+		dev->rx_creg |= cpu_to_le16(0x0002);
 		info("%s: allmulti set", netdev->name);
 	} else {
 		/* ~RX_MULTICAST, ~RX_PROMISCUOUS */
-		dev->rx_creg &= 0x00fc;
+		dev->rx_creg &= cpu_to_le16(0x00fc);
 	}
-	async_set_registers(dev, RCR, 2, &dev->rx_creg);
+	async_set_registers(dev, RCR, 2);
 	netif_wake_queue(netdev);
 }
 
diff -urN linux-2.5.69-bk2/drivers/usb/serial/bus.c linux-2.5.69-bk3/drivers/usb/serial/bus.c
--- linux-2.5.69-bk2/drivers/usb/serial/bus.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/serial/bus.c	2003-05-08 04:38:19.000000000 -0700
@@ -23,18 +23,6 @@
 
 #include "usb-serial.h"
 
-static ssize_t show_dev (struct device *dev, char *buf)
-{
-	struct usb_serial_port *port= to_usb_serial_port(dev);
-	dev_t base;
-
-	port = to_usb_serial_port(dev);
-
-	base = MKDEV(SERIAL_TTY_MAJOR, port->number);
-	return sprintf(buf, "%04x\n", base);
-}
-static DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-
 static int usb_serial_device_match (struct device *dev, struct device_driver *drv)
 {
 	struct usb_serial_device_type *driver;
@@ -88,10 +76,7 @@
 	}
 
 	minor = port->number;
-
-	tty_register_device (&usb_serial_tty_driver, minor);
-	device_create_file (dev, &dev_attr_dev);
-
+	tty_register_device (&usb_serial_tty_driver, minor, dev);
 	dev_info(&port->serial->dev->dev, 
 		 "%s converter now attached to ttyUSB%d (or usb/tts/%d for devfs)\n",
 		 driver->name, minor, minor);
diff -urN linux-2.5.69-bk2/drivers/usb/serial/console.c linux-2.5.69-bk3/drivers/usb/serial/console.c
--- linux-2.5.69-bk2/drivers/usb/serial/console.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/serial/console.c	2003-05-08 04:38:19.000000000 -0700
@@ -133,7 +133,7 @@
 	co->cflag = cflag;
 
 	/* grab the first serial port that happens to be connected */
-	serial = usb_serial_get_by_minor (0);
+	serial = usb_serial_get_by_index(0);
 	if (serial_paranoia_check (serial, __FUNCTION__)) {
 		/* no device is connected yet, sorry :( */
 		err ("No USB device connected to ttyUSB0");
diff -urN linux-2.5.69-bk2/drivers/usb/serial/usb-serial.h linux-2.5.69-bk3/drivers/usb/serial/usb-serial.h
--- linux-2.5.69-bk2/drivers/usb/serial/usb-serial.h	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/serial/usb-serial.h	2003-05-08 04:38:19.000000000 -0700
@@ -280,7 +280,7 @@
 #endif
 
 /* Functions needed by other parts of the usbserial core */
-extern struct usb_serial *usb_serial_get_by_minor (unsigned int minor);
+extern struct usb_serial *usb_serial_get_by_index (unsigned int minor);
 extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp);
 extern int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
 extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp);
diff -urN linux-2.5.69-bk2/drivers/usb/storage/unusual_devs.h linux-2.5.69-bk3/drivers/usb/storage/unusual_devs.h
--- linux-2.5.69-bk2/drivers/usb/storage/unusual_devs.h	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/storage/unusual_devs.h	2003-05-08 04:38:19.000000000 -0700
@@ -98,6 +98,18 @@
 		"Nex II Digital",
 		US_SC_SCSI, US_PR_BULK, NULL, US_FL_START_STOP),
 
+/* Patch submitted by Philipp Friedrich <philipp@void.at> */
+UNUSUAL_DEV(  0x0482, 0x0100, 0x0100, 0x0100,
+		"Kyocera",
+		"Finecam S3x",
+		US_SC_8070, US_PR_CB, NULL, US_FL_FIX_INQUIRY),
+
+/* Patch submitted by Philipp Friedrich <philipp@void.at> */
+UNUSUAL_DEV(  0x0482, 0x0101, 0x0100, 0x0100,
+		"Kyocera",
+		"Finecam S4",
+		US_SC_8070, US_PR_CB, NULL, US_FL_FIX_INQUIRY),
+
 /* Reported by Paul Stewart <stewart@wetlogic.net>
  * This entry is needed because the device reports Sub=ff */
 UNUSUAL_DEV(  0x04a4, 0x0004, 0x0001, 0x0001,
@@ -237,14 +249,6 @@
 		US_SC_8070, US_PR_BULK, NULL,
 		US_FL_FIX_INQUIRY | US_FL_START_STOP ),
 
-/* Submitted by Lars Gemeinhardt <linux-usb@gemeinhardt.info>
- * Needed for START_STOP flag */
-UNUSUAL_DEV(  0x0547, 0x2810, 0x0001, 0x0001,
-                "Mello",
-                "MP3 Player",
-		US_SC_SCSI, US_PR_BULK, NULL,
-		US_FL_START_STOP),
-
 /* This entry is needed because the device reports Sub=ff */
 UNUSUAL_DEV(  0x054c, 0x0010, 0x0106, 0x0450, 
 		"Sony",
@@ -626,6 +630,26 @@
 		US_SC_SCSI, US_PR_BULK, NULL,
 		US_FL_MODE_XLATE | US_FL_START_STOP | US_FL_FIX_INQUIRY ),
 
+/* This Pentax still camera is not conformant
+ * to the USB storage specification: -
+ * - It does not like the INQUIRY command. So we must handle this command
+ *   of the SCSI layer ourselves.
+ * Tested on Rev. 10.00 (0x1000)
+ * Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
+ */
+UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
+                "Pentax",
+                "Optio 2/3/400",
+                US_SC_8070, US_PR_CBI, NULL,
+                US_FL_FIX_INQUIRY ),
+
+/* Submitted by Per Winkvist <per.winkvist@uk.com> */
+UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009,
+                "Pentax",
+                "Optio S",
+                US_SC_8070, US_PR_CBI, NULL,
+                US_FL_FIX_INQUIRY ),
+
 /* Submitted by Brian Hall <brihall@pcisys.net>
  * Needed for START_STOP flag */
 UNUSUAL_DEV(  0x0c76, 0x0003, 0x0100, 0x0100,
@@ -657,3 +681,13 @@
 		US_SC_SCSI, US_PR_SDDR55, NULL,
 		US_FL_SINGLE_LUN),
 #endif
+
+/* Aiptek PocketCAM 3Mega
+ * Nicolas DUPEUX <nicolas@dupeux.net> 
+ */
+UNUSUAL_DEV(  0x08ca, 0x2011, 0x0000, 0x9999,
+	"AIPTEK",
+	"PocketCAM 3Mega",
+	US_SC_SCSI, US_PR_BULK, NULL,
+	US_FL_MODE_XLATE | US_FL_START_STOP),
+
diff -urN linux-2.5.69-bk2/drivers/usb/usb-skeleton.c linux-2.5.69-bk3/drivers/usb/usb-skeleton.c
--- linux-2.5.69-bk2/drivers/usb/usb-skeleton.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk3/drivers/usb/usb-skeleton.c	2003-05-08 04:38:19.000000000 -0700
@@ -1,5 +1,5 @@
 /*
- * USB Skeleton driver - 1.0
+ * USB Skeleton driver - 1.1
  *
  * Copyright (c) 2001-2002 Greg Kroah-Hartman (greg@kroah.com)
  *
@@ -18,6 +18,7 @@
  *
  * History:
  *
+ * 2003-05-06 - 1.1 - changes due to usb core changes with usb_register_dev()
  * 2003-02-25 - 1.0 - fix races involving urb->status, unlink_urb(), and
  *			disconnect.  Fix transfer amount in read().  Use
  *			macros instead of magic numbers in probe().  Change
@@ -47,7 +48,6 @@
 #include <linux/module.h>
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
-#include <linux/devfs_fs_kernel.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 
@@ -87,12 +87,8 @@
 MODULE_DEVICE_TABLE (usb, skel_table);
 
 
-#ifdef CONFIG_USB_DYNAMIC_MINORS
-#define USB_SKEL_MINOR_BASE	0
-#else
 /* Get a minor range for your devices from the usb maintainer */
 #define USB_SKEL_MINOR_BASE	192
-#endif
 
 /* Structure to hold all of our device specific stuff */
 struct usb_skel {
@@ -153,16 +149,6 @@
 	 * This also means that the kernel can decrement
 	 * the use-counter again before calling release()
 	 * or should the open() function fail.
-	 *
-	 * Not all device structures have an "owner" field
-	 * yet. "struct file_operations" and "struct net_device"
-	 * do, while "struct tty_driver" does not. If the struct
-	 * has an "owner" field, then initialize it to the value
-	 * THIS_MODULE and the kernel will handle all module
-	 * locking for you automatically. Otherwise, you must
-	 * increment the use-counter in the open() function
-	 * and decrement it again in the release() function
-	 * yourself.
 	 */
 	.owner =	THIS_MODULE,
 
@@ -173,6 +159,16 @@
 	.release =	skel_release,
 };
 
+/* 
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with devfs and the driver core
+ */
+static struct usb_class_driver skell_class = {
+	.name =		"usb/skel%d",
+	.fops =		&skel_fops,
+	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
+	.minor_base =	USB_SKEL_MINOR_BASE,
+};
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver skel_driver = {
@@ -236,8 +232,7 @@
 	/* prevent disconnects */
 	down (&disconnect_sem);
 
-	interface = usb_find_interface (&skel_driver,
-					mk_kdev(USB_MAJOR, subminor));
+	interface = usb_find_interface (&skel_driver, subminor);
 	if (!interface) {
 		err ("%s - error, can't find device for minor %d",
 		     __FUNCTION__, subminor);
@@ -508,7 +503,6 @@
 	struct usb_skel *dev = NULL;
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
-	int minor;
 	size_t buffer_size;
 	int i;
 	int retval;
@@ -521,7 +515,7 @@
 		return -ENODEV;
 	}
 
-	retval = usb_register_dev (&skel_fops, USB_SKEL_MINOR_BASE, 1, &minor);
+	retval = usb_register_dev (intf, &skel_class);
 	if (retval) {
 		/* something prevented us from registering this driver */
 		err ("Not able to get a minor for this device.");
@@ -539,7 +533,7 @@
 	init_MUTEX (&dev->sem);
 	dev->udev = udev;
 	dev->interface = interface;
-	dev->minor = minor;
+	dev->minor = intf->minor;
 
 	/* set up the endpoint information */
 	/* check out the endpoints */
@@ -606,22 +600,9 @@
 		goto error;
 	}
 
-	/* initialize the devfs node for this device and register it */
-	sprintf(name, "usb/skel%d", dev->minor);
-
-	devfs = devfs_register(NULL, name,
-				     DEVFS_FL_DEFAULT, USB_MAJOR,
-				     dev->minor,
-				     S_IFCHR | S_IRUSR | S_IWUSR |
-				     S_IRGRP | S_IWGRP | S_IROTH,
-				     &skel_fops, NULL);
-
 	/* let the user know what node this device is now attached to */
 	info ("USB Skeleton device now attached to USBSkel-%d", dev->minor);
 
-	/* add device id so the device works when advertised */
-	interface->kdev = mk_kdev(USB_MAJOR, dev->minor);
-
 	goto exit;
 
 error:
@@ -629,7 +610,7 @@
 	dev = NULL;
 
 exit_minor:
-	usb_deregister_dev (1, minor);
+	usb_deregister_dev (intf, &skel_class);
 
 exit:
 	if (dev) {
@@ -667,16 +648,13 @@
 
 	down (&dev->sem);
 
-	/* remove device id to disable open() */
-	interface->kdev = NODEV;
+	/* disable open() */
+	interface->minor = -1;
 
 	minor = dev->minor;
 
-	/* remove our devfs node */
-	devfs_remove("usb/skel%d", dev->minor);
-
-	/* give back our dynamic minor */
-	usb_deregister_dev (1, minor);
+	/* give back our minor */
+	usb_deregister_dev (intf, &skel_class);
 
 	/* terminate an ongoing write */
 	if (atomic_read (&dev->write_busy)) {
diff -urN linux-2.5.69-bk2/drivers/video/fbmem.c linux-2.5.69-bk3/drivers/video/fbmem.c
--- linux-2.5.69-bk2/drivers/video/fbmem.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk3/drivers/video/fbmem.c	2003-05-08 04:38:19.000000000 -0700
@@ -1214,7 +1214,6 @@
 int
 register_framebuffer(struct fb_info *fb_info)
 {
-	char name_buf[12];
 	int i;
 
 	if (num_registered_fb == FB_MAX)
@@ -1242,10 +1241,9 @@
 	spin_lock_init(&fb_info->pixmap.lock);
 
 	registered_fb[i] = fb_info;
-	sprintf(name_buf, "fb/%d", i);
-	devfs_register(NULL, name_buf, DEVFS_FL_DEFAULT,
-			FB_MAJOR, i, S_IFCHR | S_IRUGO | S_IWUGO,
-			&fb_fops, NULL);
+
+	devfs_mk_cdev(MKDEV(FB_MAJOR, i),
+			S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i);
 	return 0;
 }
 
diff -urN linux-2.5.69-bk2/fs/Kconfig linux-2.5.69-bk3/fs/Kconfig
--- linux-2.5.69-bk2/fs/Kconfig	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/fs/Kconfig	2003-05-08 04:38:19.000000000 -0700
@@ -73,6 +73,18 @@
 
 	  If you don't know what Access Control Lists are, say N
 
+config EXT2_FS_SECURITY
+	bool "Ext2 Security Labels"
+	depends on EXT2_FS_XATTR
+	help
+	  Security labels support alternative access control models
+	  implemented by security modules like SELinux.  This option
+	  enables an extended attribute handler for file security
+	  labels in the ext2 filesystem.
+
+	  If you are not using a security module that requires using
+	  extended attributes for file security labels, say N.
+
 config EXT3_FS
 	tristate "Ext3 journalling file system support"
 	help
@@ -131,6 +143,18 @@
 
 	  If you don't know what Access Control Lists are, say N
 
+config EXT3_FS_SECURITY
+	bool "Ext3 Security Labels"
+	depends on EXT3_FS_XATTR
+	help
+	  Security labels support alternative access control models
+	  implemented by security modules like SELinux.  This option
+	  enables an extended attribute handler for file security
+	  labels in the ext3 filesystem.
+
+	  If you are not using a security module that requires using
+	  extended attributes for file security labels, say N.
+
 config JBD
 # CONFIG_JBD could be its own option (even modular), but until there are
 # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
diff -urN linux-2.5.69-bk2/fs/bfs/dir.c linux-2.5.69-bk3/fs/bfs/dir.c
--- linux-2.5.69-bk2/fs/bfs/dir.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk3/fs/bfs/dir.c	2003-05-08 04:38:19.000000000 -0700
@@ -65,7 +65,7 @@
 		brelse(bh);
 	}
 
-	UPDATE_ATIME(dir);
+	update_atime(dir);
 	unlock_kernel();
 	return 0;	
 }
diff -urN linux-2.5.69-bk2/fs/buffer.c linux-2.5.69-bk3/fs/buffer.c
--- linux-2.5.69-bk2/fs/buffer.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/fs/buffer.c	2003-05-08 04:38:19.000000000 -0700
@@ -244,18 +244,28 @@
  * sync everything.  Start out by waking pdflush, because that writes back
  * all queues in parallel.
  */
-asmlinkage long sys_sync(void)
+static void do_sync(unsigned long wait)
 {
 	wakeup_bdflush(0);
 	sync_inodes(0);		/* All mappings, inodes and their blockdevs */
 	DQUOT_SYNC(NULL);
 	sync_supers();		/* Write the superblocks */
 	sync_filesystems(0);	/* Start syncing the filesystems */
-	sync_filesystems(1);	/* Waitingly sync the filesystems */
-	sync_inodes(1);		/* Mappings, inodes and blockdevs, again. */
+	sync_filesystems(wait);	/* Waitingly sync the filesystems */
+	sync_inodes(wait);	/* Mappings, inodes and blockdevs, again. */
+}
+
+asmlinkage long sys_sync(void)
+{
+	do_sync(1);
 	return 0;
 }
 
+void emergency_sync(void)
+{
+	pdflush_operation(do_sync, 0);
+}
+
 /*
  * Generic function to fsync a file.
  *
diff -urN linux-2.5.69-bk2/fs/coda/psdev.c linux-2.5.69-bk3/fs/coda/psdev.c
--- linux-2.5.69-bk2/fs/coda/psdev.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/fs/coda/psdev.c	2003-05-08 04:38:19.000000000 -0700
@@ -373,16 +373,10 @@
 	}
 	devfs_mk_dir ("coda");
 	for (i = 0; i < MAX_CODADEVS; i++) {
-		char name[16];
-		sprintf(name, "coda/%d", i);
-		devfs_register(NULL, name, DEVFS_FL_NONE,
-			       CODA_PSDEV_MAJOR, i,
-			       S_IFCHR | S_IRUSR | S_IWUSR,
-			       &coda_psdev_fops, NULL);
+		devfs_mk_cdev(MKDEV(CODA_PSDEV_MAJOR, i),
+				S_IFCHR|S_IRUSR|S_IWUSR, "coda/%d", i);
 	}
-
 	coda_sysctl_init();
-
 	return 0;
 }
 
diff -urN linux-2.5.69-bk2/fs/dcache.c linux-2.5.69-bk3/fs/dcache.c
--- linux-2.5.69-bk2/fs/dcache.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk3/fs/dcache.c	2003-05-08 04:38:19.000000000 -0700
@@ -770,12 +770,12 @@
 void d_instantiate(struct dentry *entry, struct inode * inode)
 {
 	if (!list_empty(&entry->d_alias)) BUG();
-	security_d_instantiate(entry, inode);
 	spin_lock(&dcache_lock);
 	if (inode)
 		list_add(&entry->d_alias, &inode->i_dentry);
 	entry->d_inode = inode;
 	spin_unlock(&dcache_lock);
+	security_d_instantiate(entry, inode);
 }
 
 /**
@@ -903,12 +903,12 @@
 	struct dentry *new = NULL;
 
 	if (inode && S_ISDIR(inode->i_mode)) {
-		security_d_instantiate(dentry, inode);
 		spin_lock(&dcache_lock);
 		if (!list_empty(&inode->i_dentry)) {
 			new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
 			__dget_locked(new);
 			spin_unlock(&dcache_lock);
+			security_d_instantiate(dentry, inode);
 			d_rehash(dentry);
 			d_move(new, dentry);
 			iput(inode);
@@ -917,6 +917,7 @@
 			list_add(&dentry->d_alias, &inode->i_dentry);
 			dentry->d_inode = inode;
 			spin_unlock(&dcache_lock);
+			security_d_instantiate(dentry, inode);
 			d_rehash(dentry);
 		}
 	} else
diff -urN linux-2.5.69-bk2/fs/devfs/base.c linux-2.5.69-bk3/fs/devfs/base.c
--- linux-2.5.69-bk2/fs/devfs/base.c	2003-05-04 16:53:03.000000000 -0700
+++ linux-2.5.69-bk3/fs/devfs/base.c	2003-05-08 04:38:19.000000000 -0700
@@ -1562,6 +1562,52 @@
 EXPORT_SYMBOL(devfs_mk_bdev);
 
 
+int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
+{
+	struct devfs_entry *dir = NULL, *de;
+	char buf[64];
+	va_list args;
+	int error, n;
+
+	if (!S_ISCHR(mode)) {
+		printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
+				__FUNCTION__, mode, buf);
+		return -EINVAL;
+	}
+
+	va_start(args, fmt);
+	n = vsnprintf(buf, 64, fmt, args);
+	if (n >= 64 || !buf[0]) {
+		printk(KERN_WARNING "%s: invalid format string\n",
+				__FUNCTION__);
+		return -EINVAL;
+	}
+
+	de = _devfs_prepare_leaf(&dir, buf, mode);
+	if (!de) {
+		printk(KERN_WARNING "%s: could not prepare leaf for %s\n",
+				__FUNCTION__, buf);
+		return -ENOMEM;		/* could be more accurate... */
+	}
+
+	de->u.cdev.dev = dev;
+
+	error = _devfs_append_entry(dir, de, NULL);
+	if (error) {
+		printk(KERN_WARNING "%s: could not append to parent for %s\n",
+				__FUNCTION__, buf);
+		goto out;
+	}
+
+	devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED);
+ out:
+	devfs_put(dir);
+	return error;
+}
+
+EXPORT_SYMBOL(devfs_mk_cdev);
+
+
 /**
  *	_devfs_unhook - Unhook a device entry from its parents list
  *	@de: The entry to unhook.
diff -urN linux-2.5.69-bk2/fs/ext2/Makefile linux-2.5.69-bk3/fs/ext2/Makefile
--- linux-2.5.69-bk2/fs/ext2/Makefile	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/fs/ext2/Makefile	2003-05-08 04:38:19.000000000 -0700
@@ -14,3 +14,7 @@
 ifeq ($(CONFIG_EXT2_FS_POSIX_ACL),y)
 ext2-objs += acl.o
 endif
+
+ifeq ($(CONFIG_EXT2_FS_SECURITY),y)
+ext2-objs += xattr_security.o
+endif
diff -urN linux-2.5.69-bk2/fs/ext2/dir.c linux-2.5.69-bk3/fs/ext2/dir.c
--- linux-2.5.69-bk2/fs/ext2/dir.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk3/fs/ext2/dir.c	2003-05-08 04:38:19.000000000 -0700
@@ -310,7 +310,7 @@
 done:
 	filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
 	filp->f_version = inode->i_version;
-	UPDATE_ATIME(inode);
+	update_atime(inode);
 	return 0;
 }
 
diff -urN linux-2.5.69-bk2/fs/ext2/xattr.c linux-2.5.69-bk3/fs/ext2/xattr.c
--- linux-2.5.69-bk2/fs/ext2/xattr.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/fs/ext2/xattr.c	2003-05-08 04:38:19.000000000 -0700
@@ -1102,22 +1102,33 @@
 				  &ext2_xattr_trusted_handler);
 	if (err)
 		goto out;
+#ifdef CONFIG_EXT2_FS_SECURITY
+	err = ext2_xattr_register(EXT2_XATTR_INDEX_SECURITY,
+				  &ext2_xattr_security_handler);
+	if (err)
+		goto out1;
+#endif
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
 	err = init_ext2_acl();
 	if (err)
-		goto out1;
+		goto out2;
 #endif
 	ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
 		sizeof(struct mb_cache_entry) +
 		sizeof(struct mb_cache_entry_index), 1, 6);
 	if (!ext2_xattr_cache) {
 		err = -ENOMEM;
-		goto out2;
+		goto out3;
 	}
 	return 0;
-out2:
+out3:
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
 	exit_ext2_acl();
+out2:
+#endif
+#ifdef CONFIG_EXT2_FS_SECURITY
+	ext2_xattr_unregister(EXT2_XATTR_INDEX_SECURITY,
+			      &ext2_xattr_security_handler);
 out1:
 #endif
 	ext2_xattr_unregister(EXT2_XATTR_INDEX_TRUSTED,
@@ -1135,6 +1146,10 @@
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
 	exit_ext2_acl();
 #endif
+#ifdef CONFIG_EXT2_FS_SECURITY
+	ext2_xattr_unregister(EXT2_XATTR_INDEX_SECURITY,
+			      &ext2_xattr_security_handler);
+#endif
 	ext2_xattr_unregister(EXT2_XATTR_INDEX_TRUSTED,
 			      &ext2_xattr_trusted_handler);
 	ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
diff -urN linux-2.5.69-bk2/fs/ext2/xattr.h linux-2.5.69-bk3/fs/ext2/xattr.h
--- linux-2.5.69-bk2/fs/ext2/xattr.h	2003-05-04 16:53:34.000000000 -0700
+++ linux-2.5.69-bk3/fs/ext2/xattr.h	2003-05-08 04:38:19.000000000 -0700
@@ -22,6 +22,7 @@
 #define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS	2
 #define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT	3
 #define EXT2_XATTR_INDEX_TRUSTED		4
+#define EXT2_XATTR_INDEX_SECURITY	        6
 
 struct ext2_xattr_header {
 	__u32	h_magic;	/* magic number for identification */
@@ -134,4 +135,5 @@
 
 extern struct ext2_xattr_handler ext2_xattr_user_handler;
 extern struct ext2_xattr_handler ext2_xattr_trusted_handler;
+extern struct ext2_xattr_handler ext2_xattr_security_handler;
 
diff -urN linux-2.5.69-bk2/fs/ext2/xattr_security.c linux-2.5.69-bk3/fs/ext2/xattr_security.c
--- linux-2.5.69-bk2/fs/ext2/xattr_security.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/fs/ext2/xattr_security.c	2003-05-08 04:38:19.000000000 -0700
@@ -0,0 +1,54 @@
+/*
+ * linux/fs/ext2/xattr_security.c
+ * Handler for storing security labels as extended attributes.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/ext2_fs.h>
+#include "xattr.h"
+
+#define XATTR_SECURITY_PREFIX "security."
+
+static size_t
+ext2_xattr_security_list(char *list, struct inode *inode,
+			const char *name, int name_len)
+{
+	const int prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
+
+	if (list) {
+		memcpy(list, XATTR_SECURITY_PREFIX, prefix_len);
+		memcpy(list+prefix_len, name, name_len);
+		list[prefix_len + name_len] = '\0';
+	}
+	return prefix_len + name_len + 1;
+}
+
+static int
+ext2_xattr_security_get(struct inode *inode, const char *name,
+		       void *buffer, size_t size)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_SECURITY, name,
+			      buffer, size);
+}
+
+static int
+ext2_xattr_security_set(struct inode *inode, const char *name,
+		       const void *value, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY, name,
+			      value, size, flags);
+}
+
+struct ext2_xattr_handler ext2_xattr_security_handler = {
+	.prefix	= XATTR_SECURITY_PREFIX,
+	.list	= ext2_xattr_security_list,
+	.get	= ext2_xattr_security_get,
+	.set	= ext2_xattr_security_set,
+};
diff -urN linux-2.5.69-bk2/fs/ext3/Makefile linux-2.5.69-bk3/fs/ext3/Makefile
--- linux-2.5.69-bk2/fs/ext3/Makefile	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk3/fs/ext3/Makefile	2003-05-08 04:38:19.000000000 -0700
@@ -14,3 +14,7 @@
 ifeq ($(CONFIG_EXT3_FS_POSIX_ACL),y)
 ext3-objs += acl.o
 endif
+
+ifeq ($(CONFIG_EXT3_FS_SECURITY),y)
+ext3-objs += xattr_security.o
+endif
diff -urN linux-2.5.69-bk2/fs/ext3/dir.c linux-2.5.69-bk3/fs/ext3/dir.c
--- linux-2.5.69-bk2/fs/ext3/dir.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk3/fs/ext3/dir.c	2003-05-08 04:38:19.000000000 -0700
@@ -216,7 +216,7 @@
 		offset = 0;
 		brelse (bh);
 	}
-	UPDATE_ATIME(inode);
+       update_atime(inode);
 out:
 	return ret;
 }
@@ -489,7 +489,7 @@
 	}
 finished:
 	info->last_pos = filp->f_pos;
-	UPDATE_ATIME(inode);
+	update_atime(inode);
 	return 0;
 }
 
diff -urN linux-2.5.69-bk2/fs/ext3/fsync.c linux-2.5.69-bk3/fs/ext3/fsync.c
--- linux-2.5.69-bk2/fs/ext3/fsync.c	2003-05-04 16:53:55.000000000 -0700
+++ linux-2.5.69-bk3/fs/ext3/fsync.c	2003-05-08 04:38:19.000000000 -0700
@@ -27,8 +27,6 @@
 #include <linux/jbd.h>
 #include <linux/ext3_fs.h>
 #include <linux/ext3_jbd.h>
-#include <linux/jbd.h>
-#include <linux/smp_lock.h>
 
 /*
  * akpm: A new design for ext3_sync_file().
diff -urN linux-2.5.69-bk2/fs/ext3/xattr.c linux-2.5.69-bk3/fs/ext3/xattr.c
--- linux-2.5.69-bk2/fs/ext3/xattr.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/fs/ext3/xattr.c	2003-05-08 04:38:19.000000000 -0700
@@ -1142,22 +1142,33 @@
 				  &ext3_xattr_trusted_handler);
 	if (err)
 		goto out;
+#ifdef CONFIG_EXT3_FS_SECURITY
+	err = ext3_xattr_register(EXT3_XATTR_INDEX_SECURITY,
+				  &ext3_xattr_security_handler);
+	if (err)
+		goto out1;
+#endif
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
 	err = init_ext3_acl();
 	if (err)
-		goto out1;
+		goto out2;
 #endif
 	ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
 		sizeof(struct mb_cache_entry) +
 		sizeof(struct mb_cache_entry_index), 1, 6);
 	if (!ext3_xattr_cache) {
 		err = -ENOMEM;
-		goto out2;
+		goto out3;
 	}
 	return 0;
-out2:
+out3:
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
 	exit_ext3_acl();
+out2:
+#endif
+#ifdef CONFIG_EXT3_FS_SECURITY
+	ext3_xattr_unregister(EXT3_XATTR_INDEX_SECURITY,
+			      &ext3_xattr_security_handler);
 out1:
 #endif
 	ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED,
@@ -1177,6 +1188,10 @@
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
 	exit_ext3_acl();
 #endif
+#ifdef CONFIG_EXT3_FS_SECURITY
+	ext3_xattr_unregister(EXT3_XATTR_INDEX_SECURITY,
+			      &ext3_xattr_security_handler);
+#endif
 	ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED,
 			      &ext3_xattr_trusted_handler);
 	ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
diff -urN linux-2.5.69-bk2/fs/ext3/xattr.h linux-2.5.69-bk3/fs/ext3/xattr.h
--- linux-2.5.69-bk2/fs/ext3/xattr.h	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk3/fs/ext3/xattr.h	2003-05-08 04:38:19.000000000 -0700
@@ -21,6 +21,7 @@
 #define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS	2
 #define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT	3
 #define EXT3_XATTR_INDEX_TRUSTED		4
+#define EXT3_XATTR_INDEX_SECURITY	        6
 
 struct ext3_xattr_header {
 	__u32	h_magic;	/* magic number for identification */
@@ -141,3 +142,4 @@
 
 extern struct ext3_xattr_handler ext3_xattr_user_handler;
 extern struct ext3_xattr_handler ext3_xattr_trusted_handler;
+extern struct ext3_xattr_handler ext3_xattr_security_handler;
diff -urN linux-2.5.69-bk2/fs/ext3/xattr_security.c linux-2.5.69-bk3/fs/ext3/xattr_security.c
--- linux-2.5.69-bk2/fs/ext3/xattr_security.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/fs/ext3/xattr_security.c	2003-05-08 04:38:19.000000000 -0700
@@ -0,0 +1,55 @@
+/*
+ * linux/fs/ext3/xattr_security.c
+ * Handler for storing security labels as extended attributes.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/ext3_jbd.h>
+#include <linux/ext3_fs.h>
+#include "xattr.h"
+
+#define XATTR_SECURITY_PREFIX "security."
+
+static size_t
+ext3_xattr_security_list(char *list, struct inode *inode,
+		    const char *name, int name_len)
+{
+	const int prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
+
+	if (list) {
+		memcpy(list, XATTR_SECURITY_PREFIX, prefix_len);
+		memcpy(list+prefix_len, name, name_len);
+		list[prefix_len + name_len] = '\0';
+	}
+	return prefix_len + name_len + 1;
+}
+
+static int
+ext3_xattr_security_get(struct inode *inode, const char *name,
+		       void *buffer, size_t size)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_SECURITY, name,
+			      buffer, size);
+}
+
+static int
+ext3_xattr_security_set(struct inode *inode, const char *name,
+		       const void *value, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_SECURITY, name,
+			      value, size, flags);
+}
+
+struct ext3_xattr_handler ext3_xattr_security_handler = {
+	.prefix	= XATTR_SECURITY_PREFIX,
+	.list	= ext3_xattr_security_list,
+	.get	= ext3_xattr_security_get,
+	.set	= ext3_xattr_security_set,
+};
diff -urN linux-2.5.69-bk2/fs/file_table.c linux-2.5.69-bk3/fs/file_table.c
--- linux-2.5.69-bk2/fs/file_table.c	2003-05-04 16:53:00.000000000 -0700
+++ linux-2.5.69-bk3/fs/file_table.c	2003-05-08 04:38:19.000000000 -0700
@@ -141,7 +141,7 @@
 	security_file_free(file);
 }
 
-void fput(struct file * file)
+void fput(struct file *file)
 {
 	if (atomic_dec_and_test(&file->f_count))
 		__fput(file);
@@ -190,6 +190,34 @@
 	return file;
 }
 
+/*
+ * Lightweight file lookup - no refcnt increment if fd table isn't shared. 
+ * You can use this only if it is guranteed that the current task already 
+ * holds a refcnt to that file. That check has to be done at fget() only
+ * and a flag is returned to be passed to the corresponding fput_light().
+ * There must not be a cloning between an fget_light/fput_light pair.
+ */
+struct file *fget_light(unsigned int fd, int *fput_needed)
+{
+	struct file *file;
+	struct files_struct *files = current->files;
+
+	*fput_needed = 0;
+	if (likely((atomic_read(&files->count) == 1))) {
+		file = fcheck(fd);
+	} else {
+		spin_lock(&files->file_lock);
+		file = fcheck(fd);
+		if (file) {
+			get_file(file);
+			*fput_needed = 1;
+		}
+		spin_unlock(&files->file_lock);
+	}
+	return file;
+}
+
+
 void put_filp(struct file *file)
 {
 	if (atomic_dec_and_test(&file->f_count)) {
diff -urN linux-2.5.69-bk2/fs/hugetlbfs/inode.c linux-2.5.69-bk3/fs/hugetlbfs/inode.c
--- linux-2.5.69-bk2/fs/hugetlbfs/inode.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk3/fs/hugetlbfs/inode.c	2003-05-08 04:38:19.000000000 -0700
@@ -62,7 +62,7 @@
 
 	down(&inode->i_sem);
 
-	UPDATE_ATIME(inode);
+	update_atime(inode);
 	vma->vm_flags |= VM_HUGETLB | VM_RESERVED;
 	vma->vm_ops = &hugetlb_vm_ops;
 	ret = hugetlb_prefault(mapping, vma);
diff -urN linux-2.5.69-bk2/fs/minix/dir.c linux-2.5.69-bk3/fs/minix/dir.c
--- linux-2.5.69-bk2/fs/minix/dir.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/fs/minix/dir.c	2003-05-08 04:38:19.000000000 -0700
@@ -127,7 +127,7 @@
 
 done:
 	filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
-	UPDATE_ATIME(inode);
+	update_atime(inode);
 	unlock_kernel();
 	return 0;
 }
diff -urN linux-2.5.69-bk2/fs/namei.c linux-2.5.69-bk3/fs/namei.c
--- linux-2.5.69-bk2/fs/namei.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk3/fs/namei.c	2003-05-08 04:38:19.000000000 -0700
@@ -405,7 +405,7 @@
 		goto loop;
 	current->link_count++;
 	current->total_link_count++;
-	UPDATE_ATIME(dentry->d_inode);
+	update_atime(dentry->d_inode);
 	err = dentry->d_inode->i_op->follow_link(dentry, nd);
 	current->link_count--;
 	return err;
@@ -1327,7 +1327,7 @@
 	error = security_inode_follow_link(dentry, nd);
 	if (error)
 		goto exit_dput;
-	UPDATE_ATIME(dentry->d_inode);
+	update_atime(dentry->d_inode);
 	error = dentry->d_inode->i_op->follow_link(dentry, nd);
 	dput(dentry);
 	if (error)
diff -urN linux-2.5.69-bk2/fs/namespace.c linux-2.5.69-bk3/fs/namespace.c
--- linux-2.5.69-bk2/fs/namespace.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk3/fs/namespace.c	2003-05-08 04:38:19.000000000 -0700
@@ -24,7 +24,6 @@
 #include <asm/uaccess.h>
 
 extern struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
-extern int do_remount_sb(struct super_block *sb, int flags, void * data);
 extern int __init init_rootfs(void);
 extern int __init fs_subsys_init(void);
 
@@ -326,7 +325,7 @@
 		down_write(&sb->s_umount);
 		if (!(sb->s_flags & MS_RDONLY)) {
 			lock_kernel();
-			retval = do_remount_sb(sb, MS_RDONLY, 0);
+			retval = do_remount_sb(sb, MS_RDONLY, 0, 0);
 			unlock_kernel();
 		}
 		up_write(&sb->s_umount);
@@ -555,7 +554,7 @@
 		return -EINVAL;
 
 	down_write(&sb->s_umount);
-	err = do_remount_sb(sb, flags, data);
+	err = do_remount_sb(sb, flags, data, 0);
 	if (!err)
 		nd->mnt->mnt_flags=mnt_flags;
 	up_write(&sb->s_umount);
diff -urN linux-2.5.69-bk2/fs/nfs/inode.c linux-2.5.69-bk3/fs/nfs/inode.c
--- linux-2.5.69-bk2/fs/nfs/inode.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/fs/nfs/inode.c	2003-05-08 04:38:19.000000000 -0700
@@ -682,7 +682,7 @@
 		 * such as stat(2) */
 		inode->i_ino = hash;
 
-		/* We can't support UPDATE_ATIME(), since the server will reset it */
+		/* We can't support update_atime(), since the server will reset it */
 		inode->i_flags |= S_NOATIME;
 		inode->i_mode = fattr->mode;
 		/* Why so? Because we want revalidate for devices/FIFOs, and
diff -urN linux-2.5.69-bk2/fs/nfsd/vfs.c linux-2.5.69-bk3/fs/nfsd/vfs.c
--- linux-2.5.69-bk2/fs/nfsd/vfs.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/fs/nfsd/vfs.c	2003-05-08 04:38:19.000000000 -0700
@@ -1124,7 +1124,7 @@
 	if (!inode->i_op || !inode->i_op->readlink)
 		goto out;
 
-	UPDATE_ATIME(inode);
+	update_atime(inode);
 	/* N.B. Why does this call need a get_fs()??
 	 * Remove the set_fs and watch the fireworks:-) --okir
 	 */
diff -urN linux-2.5.69-bk2/fs/ntfs/inode.c linux-2.5.69-bk3/fs/ntfs/inode.c
--- linux-2.5.69-bk2/fs/ntfs/inode.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk3/fs/ntfs/inode.c	2003-05-08 04:38:19.000000000 -0700
@@ -1736,7 +1736,7 @@
  * @vi:		inode to mark dirty
  *
  * This is called from fs/inode.c::__mark_inode_dirty(), when the inode itself
- * is being marked dirty. An example is when UPDATE_ATIME() is invoked.
+ * is being marked dirty. An example is when update_atime() is invoked.
  *
  * We mark the inode dirty by setting both the page in which the mft record
  * resides and the buffer heads in that page which correspond to the mft record
diff -urN linux-2.5.69-bk2/fs/partitions/check.c linux-2.5.69-bk3/fs/partitions/check.c
--- linux-2.5.69-bk2/fs/partitions/check.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk3/fs/partitions/check.c	2003-05-08 04:38:19.000000000 -0700
@@ -96,19 +96,6 @@
 
 char *disk_name(struct gendisk *hd, int part, char *buf)
 {
-#ifdef CONFIG_DEVFS_FS
-	if (hd->devfs_name[0] != '\0') {
-		if (part)
-			snprintf(buf, BDEVNAME_SIZE, "%s/part%d",
-					hd->devfs_name, part);
-		else if (hd->minors != 1)
-			snprintf(buf, BDEVNAME_SIZE, "%s/disc", hd->devfs_name);
-		else
-			snprintf(buf, BDEVNAME_SIZE, "%s", hd->devfs_name);
-		return buf;
-	}
-#endif
-
 	if (!part)
 		snprintf(buf, BDEVNAME_SIZE, "%s", hd->disk_name);
 	else if (isdigit(hd->disk_name[strlen(hd->disk_name)-1]))
@@ -443,53 +430,3 @@
 	}
 	kobject_del(&disk->kobj);
 }
-
-struct dev_name {
-	struct list_head list;
-	dev_t dev;
-	char namebuf[BDEVNAME_SIZE];
-	char *name;
-};
-
-static LIST_HEAD(device_names);
-
-char *partition_name(dev_t dev)
-{
-	struct gendisk *hd;
-	static char nomem [] = "<nomem>";
-	char b[BDEVNAME_SIZE];
-	struct dev_name *dname;
-	struct list_head *tmp;
-	int part;
-
-	list_for_each(tmp, &device_names) {
-		dname = list_entry(tmp, struct dev_name, list);
-		if (dname->dev == dev)
-			return dname->name;
-	}
-
-	dname = kmalloc(sizeof(*dname), GFP_KERNEL);
-
-	if (!dname)
-		return nomem;
-	/*
-	 * ok, add this new device name to the list
-	 */
-	hd = get_gendisk(dev, &part);
-	dname->name = NULL;
-	if (hd) {
-		dname->name = disk_name(hd, part, dname->namebuf);
-		module_put(hd->fops->owner);
-		put_disk(hd);
-	}
-	if (!dname->name) {
-		sprintf(dname->namebuf, "[dev %s]", __bdevname(dev, b));
-		dname->name = dname->namebuf;
-	}
-
-	dname->dev = dev;
-	list_add(&dname->list, &device_names);
-
-	return dname->name;
-}
-
diff -urN linux-2.5.69-bk2/fs/pipe.c linux-2.5.69-bk3/fs/pipe.c
--- linux-2.5.69-bk2/fs/pipe.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk3/fs/pipe.c	2003-05-08 04:38:19.000000000 -0700
@@ -121,7 +121,7 @@
 		kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
 	}
 	if (ret > 0)
-		UPDATE_ATIME(inode);
+		update_atime(inode);
 	return ret;
 }
 
diff -urN linux-2.5.69-bk2/fs/qnx4/dir.c linux-2.5.69-bk3/fs/qnx4/dir.c
--- linux-2.5.69-bk2/fs/qnx4/dir.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk3/fs/qnx4/dir.c	2003-05-08 04:38:19.000000000 -0700
@@ -76,7 +76,7 @@
 		}
 		brelse(bh);
 	}
-	UPDATE_ATIME(inode);
+	update_atime(inode);
 
 out:
 	unlock_kernel();
diff -urN linux-2.5.69-bk2/fs/read_write.c linux-2.5.69-bk3/fs/read_write.c
--- linux-2.5.69-bk2/fs/read_write.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/fs/read_write.c	2003-05-08 04:38:19.000000000 -0700
@@ -115,9 +115,10 @@
 {
 	off_t retval;
 	struct file * file;
+	int fput_needed;
 
 	retval = -EBADF;
-	file = fget(fd);
+	file = fget_light(fd, &fput_needed);
 	if (!file)
 		goto bad;
 
@@ -128,7 +129,7 @@
 		if (res != (loff_t)retval)
 			retval = -EOVERFLOW;	/* LFS: should only happen on 32 bit platforms */
 	}
-	fput(file);
+	fput_light(file, fput_needed);
 bad:
 	return retval;
 }
@@ -141,9 +142,10 @@
 	int retval;
 	struct file * file;
 	loff_t offset;
+	int fput_needed;
 
 	retval = -EBADF;
-	file = fget(fd);
+	file = fget_light(fd, &fput_needed);
 	if (!file)
 		goto bad;
 
@@ -161,7 +163,7 @@
 			retval = 0;
 	}
 out_putf:
-	fput(file);
+	fput_light(file, fput_needed);
 bad:
 	return retval;
 }
@@ -251,11 +253,12 @@
 {
 	struct file *file;
 	ssize_t ret = -EBADF;
+	int fput_needed;
 
-	file = fget(fd);
+	file = fget_light(fd, &fput_needed);
 	if (file) {
 		ret = vfs_read(file, buf, count, &file->f_pos);
-		fput(file);
+		fput_light(file, fput_needed);
 	}
 
 	return ret;
@@ -265,11 +268,12 @@
 {
 	struct file *file;
 	ssize_t ret = -EBADF;
+	int fput_needed;
 
-	file = fget(fd);
+	file = fget_light(fd, &fput_needed);
 	if (file) {
 		ret = vfs_write(file, buf, count, &file->f_pos);
-		fput(file);
+		fput_light(file, fput_needed);
 	}
 
 	return ret;
@@ -280,14 +284,15 @@
 {
 	struct file *file;
 	ssize_t ret = -EBADF;
+	int fput_needed;
 
 	if (pos < 0)
 		return -EINVAL;
 
-	file = fget(fd);
+	file = fget_light(fd, &fput_needed);
 	if (file) {
 		ret = vfs_read(file, buf, count, &pos);
-		fput(file);
+		fput_light(file, fput_needed);
 	}
 
 	return ret;
@@ -298,14 +303,15 @@
 {
 	struct file *file;
 	ssize_t ret = -EBADF;
+	int fput_needed;
 
 	if (pos < 0)
 		return -EINVAL;
 
-	file = fget(fd);
+	file = fget_light(fd, &fput_needed);
 	if (file) {
 		ret = vfs_write(file, buf, count, &pos);
-		fput(file);
+		fput_light(file, fput_needed);
 	}
 
 	return ret;
@@ -479,11 +485,12 @@
 {
 	struct file *file;
 	ssize_t ret = -EBADF;
+	int fput_needed;
 
-	file = fget(fd);
+	file = fget_light(fd, &fput_needed);
 	if (file) {
 		ret = vfs_readv(file, vec, vlen, &file->f_pos);
-		fput(file);
+		fput_light(file, fput_needed);
 	}
 
 	return ret;
@@ -494,11 +501,12 @@
 {
 	struct file *file;
 	ssize_t ret = -EBADF;
+	int fput_needed;
 
-	file = fget(fd);
+	file = fget_light(fd, &fput_needed);
 	if (file) {
 		ret = vfs_writev(file, vec, vlen, &file->f_pos);
-		fput(file);
+		fput_light(file, fput_needed);
 	}
 
 	return ret;
@@ -511,12 +519,13 @@
 	struct inode * in_inode, * out_inode;
 	loff_t pos;
 	ssize_t retval;
+	int fput_needed_in, fput_needed_out;
 
 	/*
 	 * Get input file, and verify that it is ok..
 	 */
 	retval = -EBADF;
-	in_file = fget(in_fd);
+	in_file = fget_light(in_fd, &fput_needed_in);
 	if (!in_file)
 		goto out;
 	if (!(in_file->f_mode & FMODE_READ))
@@ -539,7 +548,7 @@
 	 * Get output file, and verify that it is ok..
 	 */
 	retval = -EBADF;
-	out_file = fget(out_fd);
+	out_file = fget_light(out_fd, &fput_needed_out);
 	if (!out_file)
 		goto fput_in;
 	if (!(out_file->f_mode & FMODE_WRITE))
@@ -579,9 +588,9 @@
 		retval = -EOVERFLOW;
 
 fput_out:
-	fput(out_file);
+	fput_light(out_file, fput_needed_out);
 fput_in:
-	fput(in_file);
+	fput_light(in_file, fput_needed_in);
 out:
 	return retval;
 }
diff -urN linux-2.5.69-bk2/fs/reiserfs/dir.c linux-2.5.69-bk3/fs/reiserfs/dir.c
--- linux-2.5.69-bk2/fs/reiserfs/dir.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk3/fs/reiserfs/dir.c	2003-05-08 04:38:19.000000000 -0700
@@ -185,7 +185,7 @@
     filp->f_pos = next_pos;
     pathrelse (&path_to_entry);
     reiserfs_check_path(&path_to_entry) ;
-    UPDATE_ATIME(inode) ;
+    update_atime(inode) ;
  out:
     reiserfs_write_unlock(inode->i_sb);
     return ret;
diff -urN linux-2.5.69-bk2/fs/select.c linux-2.5.69-bk3/fs/select.c
--- linux-2.5.69-bk2/fs/select.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk3/fs/select.c	2003-05-08 04:38:19.000000000 -0700
@@ -176,7 +176,7 @@
 {
 	struct poll_wqueues table;
 	poll_table *wait;
-	int retval, i, off;
+	int retval, i;
 	long __timeout = *timeout;
 
  	spin_lock(&current->files->file_lock);
@@ -193,38 +193,58 @@
 		wait = NULL;
 	retval = 0;
 	for (;;) {
+		unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;
+
 		set_current_state(TASK_INTERRUPTIBLE);
-		for (i = 0 ; i < n; i++) {
-			unsigned long bit = BIT(i);
-			unsigned long mask;
-			struct file *file;
 
-			off = i / __NFDBITS;
-			if (!(bit & BITS(fds, off)))
+		inp = fds->in; outp = fds->out; exp = fds->ex;
+		rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex;
+
+		for (i = 0; i < n; ++rinp, ++routp, ++rexp) {
+			unsigned long in, out, ex, all_bits, bit = 1, mask, j;
+			unsigned long res_in = 0, res_out = 0, res_ex = 0;
+			struct file_operations *f_op = NULL;
+			struct file *file = NULL;
+
+			in = *inp++; out = *outp++; ex = *exp++;
+			all_bits = in | out | ex;
+			if (all_bits == 0) {
+				i += __NFDBITS;
 				continue;
-			file = fget(i);
-			mask = POLLNVAL;
-			if (file) {
-				mask = DEFAULT_POLLMASK;
-				if (file->f_op && file->f_op->poll)
-					mask = file->f_op->poll(file, wait);
-				fput(file);
-			}
-			if ((mask & POLLIN_SET) && ISSET(bit, __IN(fds,off))) {
-				SET(bit, __RES_IN(fds,off));
-				retval++;
-				wait = NULL;
 			}
-			if ((mask & POLLOUT_SET) && ISSET(bit, __OUT(fds,off))) {
-				SET(bit, __RES_OUT(fds,off));
-				retval++;
-				wait = NULL;
-			}
-			if ((mask & POLLEX_SET) && ISSET(bit, __EX(fds,off))) {
-				SET(bit, __RES_EX(fds,off));
-				retval++;
-				wait = NULL;
+
+			for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) {
+				if (i >= n)
+					break;
+				if (!(bit & all_bits))
+					continue;
+				file = fget(i);
+				if (file) {
+					f_op = file->f_op;
+					mask = DEFAULT_POLLMASK;
+					if (f_op && f_op->poll)
+						mask = (*f_op->poll)(file, retval ? NULL : wait);
+					fput(file);
+					if ((mask & POLLIN_SET) && (in & bit)) {
+						res_in |= bit;
+						retval++;
+					}
+					if ((mask & POLLOUT_SET) && (out & bit)) {
+						res_out |= bit;
+						retval++;
+					}
+					if ((mask & POLLEX_SET) && (ex & bit)) {
+						res_ex |= bit;
+						retval++;
+					}
+				}
 			}
+			if (res_in)
+				*rinp = res_in;
+			if (res_out)
+				*routp = res_out;
+			if (res_ex)
+				*rexp = res_ex;
 		}
 		wait = NULL;
 		if (retval || !__timeout || signal_pending(current))
diff -urN linux-2.5.69-bk2/fs/stat.c linux-2.5.69-bk3/fs/stat.c
--- linux-2.5.69-bk2/fs/stat.c	2003-05-04 16:53:03.000000000 -0700
+++ linux-2.5.69-bk3/fs/stat.c	2003-05-08 04:38:19.000000000 -0700
@@ -244,7 +244,7 @@
 		if (inode->i_op && inode->i_op->readlink) {
 			error = security_inode_readlink(nd.dentry);
 			if (!error) {
-				UPDATE_ATIME(inode);
+				update_atime(inode);
 				error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
 			}
 		}
diff -urN linux-2.5.69-bk2/fs/super.c linux-2.5.69-bk3/fs/super.c
--- linux-2.5.69-bk2/fs/super.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk3/fs/super.c	2003-05-08 04:38:19.000000000 -0700
@@ -31,6 +31,7 @@
 #include <linux/mount.h>
 #include <linux/security.h>
 #include <linux/vfs.h>
+#include <linux/writeback.h>		/* for the emergency remount stuff */
 #include <asm/uaccess.h>
 
 
@@ -431,6 +432,18 @@
 	return err;
 }
 
+static void mark_files_ro(struct super_block *sb)
+{
+	struct file *f;
+
+	file_list_lock();
+	list_for_each_entry(f, &sb->s_files, f_list) {
+		if (S_ISREG(f->f_dentry->d_inode->i_mode) && file_count(f))
+			f->f_mode &= ~FMODE_WRITE;
+	}
+	file_list_unlock();
+}
+
 /**
  *	do_remount_sb	-	asks filesystem to change mount options.
  *	@sb:	superblock in question
@@ -439,21 +452,25 @@
  *
  *	Alters the mount options of a mounted file system.
  */
-int do_remount_sb(struct super_block *sb, int flags, void *data)
+int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
 {
 	int retval;
 	
 	if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev))
 		return -EACCES;
-		/*flags |= MS_RDONLY;*/
 	if (flags & MS_RDONLY)
 		acct_auto_close(sb);
 	shrink_dcache_sb(sb);
 	fsync_super(sb);
+
 	/* If we are remounting RDONLY, make sure there are no rw files open */
-	if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
-		if (!fs_may_remount_ro(sb))
+	if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) {
+		if (force)
+			mark_files_ro(sb);
+		else if (!fs_may_remount_ro(sb))
 			return -EBUSY;
+	}
+
 	if (sb->s_op->remount_fs) {
 		lock_super(sb);
 		retval = sb->s_op->remount_fs(sb, &flags, data);
@@ -465,6 +482,28 @@
 	return 0;
 }
 
+static void do_emergency_remount(unsigned long foo)
+{
+	struct super_block *sb;
+
+	spin_lock(&sb_lock);
+	list_for_each_entry(sb, &super_blocks, s_list) {
+		sb->s_count++;
+		spin_unlock(&sb_lock);
+		down_read(&sb->s_umount);
+		if (sb->s_root && sb->s_bdev && !(sb->s_flags & MS_RDONLY))
+			do_remount_sb(sb, MS_RDONLY, NULL, 1);
+		drop_super(sb);
+		spin_lock(&sb_lock);
+	}
+	spin_unlock(&sb_lock);
+}
+
+void emergency_remount(void)
+{
+	pdflush_operation(do_emergency_remount, 0);
+}
+
 /*
  * Unnamed block devices are dummy devices used by virtual
  * filesystems which don't use real block-devices.  -- jrs
@@ -618,7 +657,7 @@
 		}
 		s->s_flags |= MS_ACTIVE;
 	}
-	do_remount_sb(s, flags, data);
+	do_remount_sb(s, flags, data, 0);
 	return s;
 }
 
diff -urN linux-2.5.69-bk2/fs/sysv/dir.c linux-2.5.69-bk3/fs/sysv/dir.c
--- linux-2.5.69-bk2/fs/sysv/dir.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk3/fs/sysv/dir.c	2003-05-08 04:38:19.000000000 -0700
@@ -116,7 +116,7 @@
 
 done:
 	filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
-	UPDATE_ATIME(inode);
+	update_atime(inode);
 	unlock_kernel();
 	return 0;
 }
diff -urN linux-2.5.69-bk2/fs/udf/dir.c linux-2.5.69-bk3/fs/udf/dir.c
--- linux-2.5.69-bk2/fs/udf/dir.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk3/fs/udf/dir.c	2003-05-08 04:38:19.000000000 -0700
@@ -98,7 +98,7 @@
 	}
 
 	result = do_udf_readdir(dir, filp, filldir, dirent);
-	UPDATE_ATIME(dir);
+	update_atime(dir);
 	unlock_kernel();
  	return result;
 }
diff -urN linux-2.5.69-bk2/fs/ufs/dir.c linux-2.5.69-bk3/fs/ufs/dir.c
--- linux-2.5.69-bk2/fs/ufs/dir.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk3/fs/ufs/dir.c	2003-05-08 04:38:19.000000000 -0700
@@ -166,7 +166,7 @@
 		offset = 0;
 		brelse (bh);
 	}
-	UPDATE_ATIME(inode);
+	update_atime(inode);
 	unlock_kernel();
 	return 0;
 }
diff -urN linux-2.5.69-bk2/fs/xattr.c linux-2.5.69-bk3/fs/xattr.c
--- linux-2.5.69-bk2/fs/xattr.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/fs/xattr.c	2003-05-08 04:38:19.000000000 -0700
@@ -79,15 +79,16 @@
 
 	error = -EOPNOTSUPP;
 	if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
+		down(&d->d_inode->i_sem);
 		error = security_inode_setxattr(d, kname, kvalue, size, flags);
 		if (error)
 			goto out;
-		down(&d->d_inode->i_sem);
 		error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
+		if (!error)
+			security_inode_post_setxattr(d, kname, kvalue, size, flags);
+out:
 		up(&d->d_inode->i_sem);
 	}
-
-out:
 	xattr_free(kvalue, size);
 	return error;
 }
diff -urN linux-2.5.69-bk2/include/asm-i386/apicdef.h linux-2.5.69-bk3/include/asm-i386/apicdef.h
--- linux-2.5.69-bk2/include/asm-i386/apicdef.h	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/apicdef.h	2003-05-08 04:38:20.000000000 -0700
@@ -11,13 +11,6 @@
 #define		APIC_DEFAULT_PHYS_BASE	0xfee00000
  
 #define		APIC_ID		0x20
-#ifdef CONFIG_X86_SUMMIT
- #define		APIC_ID_MASK		(0xFF<<24)
- #define		GET_APIC_ID(x)		(((x)>>24)&0xFF)
-#else
- #define		APIC_ID_MASK		(0x0F<<24)
- #define		GET_APIC_ID(x)		(((x)>>24)&0x0F)
-#endif
 #define		APIC_LVR	0x30
 #define			APIC_LVR_MASK		0xFF00FF
 #define			GET_APIC_VERSION(x)	((x)&0xFF)
diff -urN linux-2.5.69-bk2/include/asm-i386/edd.h linux-2.5.69-bk3/include/asm-i386/edd.h
--- linux-2.5.69-bk2/include/asm-i386/edd.h	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/edd.h	2003-05-08 04:38:20.000000000 -0700
@@ -141,7 +141,7 @@
 			u32 array_number;
 			u32 reserved1;
 			u64 reserved2;
-		} __attribute((packed)) raid;
+		} __attribute__ ((packed)) raid;
 		struct {
 			u8 device;
 			u8 reserved1;
diff -urN linux-2.5.69-bk2/include/asm-i386/fixmap.h linux-2.5.69-bk3/include/asm-i386/fixmap.h
--- linux-2.5.69-bk2/include/asm-i386/fixmap.h	2003-05-04 16:53:00.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/fixmap.h	2003-05-08 04:38:20.000000000 -0700
@@ -60,7 +60,7 @@
 #ifdef CONFIG_X86_F00F_BUG
 	FIX_F00F_IDT,	/* Virtual mapping for IDT */
 #endif
-#ifdef CONFIG_X86_SUMMIT
+#ifdef CONFIG_X86_CYCLONE_TIMER
 	FIX_CYCLONE_TIMER, /*cyclone timer register*/
 #endif 
 #ifdef CONFIG_HIGHMEM
diff -urN linux-2.5.69-bk2/include/asm-i386/genapic.h linux-2.5.69-bk3/include/asm-i386/genapic.h
--- linux-2.5.69-bk2/include/asm-i386/genapic.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/include/asm-i386/genapic.h	2003-05-08 04:38:20.000000000 -0700
@@ -0,0 +1,106 @@
+#ifndef _ASM_GENAPIC_H
+#define _ASM_GENAPIC_H 1
+
+/* 
+ * Generic APIC driver interface.
+ *  
+ * An straight forward mapping of the APIC related parts of the 
+ * x86 subarchitecture interface to a dynamic object.
+ *	
+ * This is used by the "generic" x86 subarchitecture. 
+ *
+ * Copyright 2003 Andi Kleen, SuSE Labs.
+ */
+
+struct mpc_config_translation;
+struct mpc_config_bus;
+struct mp_config_table;
+struct mpc_config_processor;
+
+struct genapic { 
+	char *name; 
+	int (*probe)(void); 
+
+	int (*apic_id_registered)(void);
+	unsigned long (*target_cpus)(void); 
+	int int_delivery_mode;
+	int int_dest_mode; 
+	int apic_broadcast_id; 
+	int esr_disable;
+	unsigned long (*check_apicid_used)(unsigned long bitmap, int apicid); 
+	unsigned long (*check_apicid_present)(int apicid); 
+	int no_balance_irq;
+	void (*init_apic_ldr)(void);
+	unsigned long (*ioapic_phys_id_map)(unsigned long map); 
+
+	void (*clustered_apic_check)(void);
+	int (*multi_timer_check)(int apic, int irq);
+	int (*apicid_to_node)(int logical_apicid); 
+	int (*cpu_to_logical_apicid)(int cpu);
+	int (*cpu_present_to_apicid)(int mps_cpu);
+	unsigned long (*apicid_to_cpu_present)(int phys_apicid); 
+	int (*mpc_apic_id)(struct mpc_config_processor *m, 
+			   struct mpc_config_translation *t); 
+	void (*setup_portio_remap)(void); 
+	int (*check_phys_apicid_present)(int boot_cpu_physical_apicid);
+
+	/* mpparse */
+	void (*mpc_oem_bus_info)(struct mpc_config_bus *, char *, 
+				 struct mpc_config_translation *);
+	void (*mpc_oem_pci_bus)(struct mpc_config_bus *, 
+				struct mpc_config_translation *); 
+
+	/* When one of the next two hooks returns 1 the genapic
+	   is switched to this. Essentially they are additional probe 
+	   functions. */
+	int (*mps_oem_check)(struct mp_config_table *mpc, char *oem, 
+			      char *productid);
+	int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id);
+
+	unsigned (*get_apic_id)(unsigned long x);
+	unsigned long apic_id_mask; 
+	
+	/* ipi */
+	void (*send_IPI_mask)(int mask, int vector);
+	void (*send_IPI_allbutself)(int vector);
+	void (*send_IPI_all)(int vector);
+}; 
+
+#define APICFUNC(x) .x = x
+
+#define APIC_INIT(aname, aprobe) { \
+	.name = aname, \
+	.probe = aprobe, \
+	.int_delivery_mode = INT_DELIVERY_MODE, \
+	.int_dest_mode = INT_DEST_MODE, \
+	.apic_broadcast_id = APIC_BROADCAST_ID, \
+	.no_balance_irq = NO_BALANCE_IRQ, \
+	APICFUNC(apic_id_registered), \
+	APICFUNC(target_cpus), \
+	APICFUNC(check_apicid_used), \
+	APICFUNC(check_apicid_present), \
+	APICFUNC(init_apic_ldr), \
+	APICFUNC(ioapic_phys_id_map), \
+	APICFUNC(clustered_apic_check), \
+	APICFUNC(multi_timer_check), \
+	APICFUNC(apicid_to_node), \
+	APICFUNC(cpu_to_logical_apicid), \
+	APICFUNC(cpu_present_to_apicid), \
+	APICFUNC(apicid_to_cpu_present), \
+	APICFUNC(mpc_apic_id), \
+	APICFUNC(setup_portio_remap), \
+	APICFUNC(check_phys_apicid_present), \
+	APICFUNC(mpc_oem_bus_info), \
+	APICFUNC(mpc_oem_pci_bus), \
+	APICFUNC(mps_oem_check), \
+	APICFUNC(get_apic_id), \
+	.apic_id_mask = APIC_ID_MASK, \
+	APICFUNC(acpi_madt_oem_check), \
+	APICFUNC(send_IPI_mask), \
+	APICFUNC(send_IPI_allbutself), \
+	APICFUNC(send_IPI_all), \
+	}
+
+extern struct genapic *genapic;
+
+#endif
diff -urN linux-2.5.69-bk2/include/asm-i386/kmap_types.h linux-2.5.69-bk3/include/asm-i386/kmap_types.h
--- linux-2.5.69-bk2/include/asm-i386/kmap_types.h	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/kmap_types.h	2003-05-08 04:38:20.000000000 -0700
@@ -3,7 +3,7 @@
 
 #include <linux/config.h>
 
-#if CONFIG_DEBUG_HIGHMEM
+#ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
 #else
 # define D(n)
diff -urN linux-2.5.69-bk2/include/asm-i386/mach-bigsmp/mach_apic.h linux-2.5.69-bk3/include/asm-i386/mach-bigsmp/mach_apic.h
--- linux-2.5.69-bk2/include/asm-i386/mach-bigsmp/mach_apic.h	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/mach-bigsmp/mach_apic.h	2003-05-08 04:38:20.000000000 -0700
@@ -15,18 +15,28 @@
 
 static inline int apic_id_registered(void)
 {
-	        return (1);
+	return (1);
 }
 
 #define APIC_DFR_VALUE	(APIC_DFR_CLUSTER)
-#define TARGET_CPUS	((cpu_online_map < 0xf)?cpu_online_map:0xf)
+static inline unsigned long target_cpus(void)
+{ 
+	return ((cpu_online_map < 0xf)?cpu_online_map:0xf);
+}
+#define TARGET_CPUS	(target_cpus())
 
 #define INT_DELIVERY_MODE dest_LowestPrio
 #define INT_DEST_MODE 1     /* logical delivery broadcast to all procs */
 
 #define APIC_BROADCAST_ID     (0x0f)
-#define check_apicid_used(bitmap, apicid) (0)
-#define check_apicid_present(bit) (phys_cpu_present_map & (1 << bit))
+static inline unsigned long check_apicid_used(unsigned long bitmap, int apicid) 
+{ 
+	return 0;
+} 
+static inline unsigned long check_apicid_present(int bit) 
+{ 
+	return (phys_cpu_present_map & (1 << bit));
+}
 
 static inline unsigned long calculate_ldr(unsigned long old)
 {
@@ -115,4 +125,13 @@
 	return (1);
 }
 
+#define		APIC_ID_MASK		(0x0F<<24)
+
+static inline unsigned get_apic_id(unsigned long x) 
+{ 
+	return (((x)>>24)&0x0F);
+} 
+
+#define		GET_APIC_ID(x)	get_apic_id(x)
+
 #endif /* __ASM_MACH_APIC_H */
diff -urN linux-2.5.69-bk2/include/asm-i386/mach-bigsmp/mach_ipi.h linux-2.5.69-bk3/include/asm-i386/mach-bigsmp/mach_ipi.h
--- linux-2.5.69-bk2/include/asm-i386/mach-bigsmp/mach_ipi.h	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/mach-bigsmp/mach_ipi.h	2003-05-08 04:38:20.000000000 -0700
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-static inline void send_IPI_mask_sequence(int mask, int vector);
+inline void send_IPI_mask_sequence(int mask, int vector);
 
 static inline void send_IPI_mask(int mask, int vector)
 {
diff -urN linux-2.5.69-bk2/include/asm-i386/mach-default/mach_apic.h linux-2.5.69-bk3/include/asm-i386/mach-default/mach_apic.h
--- linux-2.5.69-bk2/include/asm-i386/mach-default/mach_apic.h	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/mach-default/mach_apic.h	2003-05-08 04:38:20.000000000 -0700
@@ -3,11 +3,15 @@
 
 #define APIC_DFR_VALUE	(APIC_DFR_FLAT)
 
+static inline unsigned long target_cpus(void)
+{ 
 #ifdef CONFIG_SMP
- #define TARGET_CPUS (cpu_online_map)
+	return cpu_online_map;
 #else
- #define TARGET_CPUS 0x01
+	return 1; 
 #endif
+} 
+#define TARGET_CPUS (target_cpus())
 
 #define NO_BALANCE_IRQ (0)
 #define esr_disable (0)
@@ -16,13 +20,15 @@
 #define INT_DEST_MODE 1     /* logical delivery broadcast to all procs */
 
 #define APIC_BROADCAST_ID      0x0F
-#define check_apicid_used(bitmap, apicid) (bitmap & (1 << apicid))
-#define check_apicid_present(bit) (phys_cpu_present_map & (1 << bit))
 
-static inline int apic_id_registered(void)
+static inline unsigned long check_apicid_used(unsigned long bitmap, int apicid) 
+{ 
+	return (bitmap & (1UL << apicid)); 
+} 
+
+static inline unsigned long check_apicid_present(int bit) 
 {
-	return (test_bit(GET_APIC_ID(apic_read(APIC_ID)), 
-						&phys_cpu_present_map));
+	return (phys_cpu_present_map & (1UL << bit));
 }
 
 /*
@@ -42,7 +48,7 @@
 	apic_write_around(APIC_LDR, val);
 }
 
-static inline ulong ioapic_phys_id_map(ulong phys_map)
+static inline unsigned long ioapic_phys_id_map(unsigned long phys_map)
 {
 	return phys_map;
 }
@@ -99,4 +105,19 @@
 	return test_bit(boot_cpu_physical_apicid, &phys_cpu_present_map);
 }
 
+#define		APIC_ID_MASK		(0xF<<24)
+
+static inline unsigned get_apic_id(unsigned long x) 
+{ 
+	return (((x)>>24)&0xF);
+} 
+
+#define		GET_APIC_ID(x)	get_apic_id(x)
+
+static inline int apic_id_registered(void)
+{
+	return (test_bit(GET_APIC_ID(apic_read(APIC_ID)), 
+						&phys_cpu_present_map));
+}
+
 #endif /* __ASM_MACH_APIC_H */
diff -urN linux-2.5.69-bk2/include/asm-i386/mach-default/mach_ipi.h linux-2.5.69-bk3/include/asm-i386/mach-default/mach_ipi.h
--- linux-2.5.69-bk2/include/asm-i386/mach-default/mach_ipi.h	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/mach-default/mach_ipi.h	2003-05-08 04:38:20.000000000 -0700
@@ -1,8 +1,8 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-static inline void send_IPI_mask_bitmask(int mask, int vector);
-static inline void __send_IPI_shortcut(unsigned int shortcut, int vector);
+inline void send_IPI_mask_bitmask(int mask, int vector);
+inline void __send_IPI_shortcut(unsigned int shortcut, int vector);
 
 static inline void send_IPI_mask(int mask, int vector)
 {
diff -urN linux-2.5.69-bk2/include/asm-i386/mach-default/mach_mpparse.h linux-2.5.69-bk3/include/asm-i386/mach-default/mach_mpparse.h
--- linux-2.5.69-bk2/include/asm-i386/mach-default/mach_mpparse.h	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/mach-default/mach_mpparse.h	2003-05-08 04:38:20.000000000 -0700
@@ -12,14 +12,16 @@
 {
 }
 
-static inline void mps_oem_check(struct mp_config_table *mpc, char *oem, 
+static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, 
 		char *productid)
 {
+	return 0;
 }
 
 /* Hook from generic ACPI tables.c */
-static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 {
+	return 0;
 }
 
 
diff -urN linux-2.5.69-bk2/include/asm-i386/mach-generic/mach_apic.h linux-2.5.69-bk3/include/asm-i386/mach-generic/mach_apic.h
--- linux-2.5.69-bk2/include/asm-i386/mach-generic/mach_apic.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/include/asm-i386/mach-generic/mach_apic.h	2003-05-08 04:38:20.000000000 -0700
@@ -0,0 +1,30 @@
+#ifndef __ASM_MACH_APIC_H
+#define __ASM_MACH_APIC_H
+
+#include <asm/genapic.h>
+
+#define esr_disable (genapic->esr_disable)
+#define NO_BALANCE_IRQ (genapic->no_balance_irq)
+#define APIC_BROADCAST_ID (genapic->apic_broadcast_id)
+#define INT_DELIVERY_MODE (genapic->int_delivery_mode)
+#define INT_DEST_MODE (genapic->int_dest_mode)
+#define TARGET_CPUS	  (genapic->target_cpus())
+#define apic_id_registered (genapic->apic_id_registered)
+#define apic_id_registered (genapic->apic_id_registered)
+#define init_apic_ldr (genapic->init_apic_ldr)
+#define ioapic_phys_id_map (genapic->ioapic_phys_id_map)
+#define clustered_apic_check (genapic->clustered_apic_check) 
+#define multi_timer_check (genapic->multi_timer_check)
+#define apicid_to_node (genapic->apicid_to_node)
+#define cpu_to_logical_apicid (genapic->cpu_to_logical_apicid) 
+#define cpu_present_to_apicid (genapic->cpu_present_to_apicid)
+#define apicid_to_cpu_present (genapic->apicid_to_cpu_present)
+#define mpc_apic_id (genapic->mpc_apic_id) 
+#define setup_portio_remap (genapic->setup_portio_remap)
+#define check_apicid_present (genapic->check_apicid_present)
+#define check_phys_apicid_present (genapic->check_phys_apicid_present)
+#define check_apicid_used (genapic->check_apicid_used)
+#define GET_APIC_ID (genapic->get_apic_id)
+#define APIC_ID_MASK (genapic->apic_id_mask)
+
+#endif /* __ASM_MACH_APIC_H */
diff -urN linux-2.5.69-bk2/include/asm-i386/mach-generic/mach_ipi.h linux-2.5.69-bk3/include/asm-i386/mach-generic/mach_ipi.h
--- linux-2.5.69-bk2/include/asm-i386/mach-generic/mach_ipi.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/include/asm-i386/mach-generic/mach_ipi.h	2003-05-08 04:38:20.000000000 -0700
@@ -0,0 +1,10 @@
+#ifndef _MACH_IPI_H
+#define _MACH_IPI_H 1
+
+#include <asm/genapic.h>
+
+#define send_IPI_mask (genapic->send_IPI_mask)
+#define send_IPI_allbutself (genapic->send_IPI_allbutself)
+#define send_IPI_all (genapic->send_IPI_all)
+
+#endif
diff -urN linux-2.5.69-bk2/include/asm-i386/mach-generic/mach_mpparse.h linux-2.5.69-bk3/include/asm-i386/mach-generic/mach_mpparse.h
--- linux-2.5.69-bk2/include/asm-i386/mach-generic/mach_mpparse.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/include/asm-i386/mach-generic/mach_mpparse.h	2003-05-08 04:38:20.000000000 -0700
@@ -0,0 +1,12 @@
+#ifndef _MACH_MPPARSE_H
+#define _MACH_MPPARSE_H 1
+
+#include <asm/genapic.h>
+
+#define mpc_oem_bus_info (genapic->mpc_oem_bus_info)
+#define mpc_oem_pci_bus (genapic->mpc_oem_pci_bus)
+
+int mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid); 
+int acpi_madt_oem_check(char *oem_id, char *oem_table_id); 
+
+#endif
diff -urN linux-2.5.69-bk2/include/asm-i386/mach-numaq/mach_apic.h linux-2.5.69-bk3/include/asm-i386/mach-numaq/mach_apic.h
--- linux-2.5.69-bk2/include/asm-i386/mach-numaq/mach_apic.h	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/mach-numaq/mach_apic.h	2003-05-08 04:38:20.000000000 -0700
@@ -1,6 +1,9 @@
 #ifndef __ASM_MACH_APIC_H
 #define __ASM_MACH_APIC_H
 
+#include <asm/io.h>
+#include <linux/mmzone.h>
+
 #define APIC_DFR_VALUE	(APIC_DFR_CLUSTER)
 
 #define TARGET_CPUS (0xf)
@@ -103,4 +106,13 @@
 	return (1);
 }
 
+#define APIC_ID_MASK (0xF<<24)
+
+static inline unsigned get_apic_id(unsigned long x)
+{
+	        return (((x)>>24)&0x0F);
+}
+
+#define         GET_APIC_ID(x)  get_apic_id(x)
+
 #endif /* __ASM_MACH_APIC_H */
diff -urN linux-2.5.69-bk2/include/asm-i386/mach-summit/mach_apic.h linux-2.5.69-bk3/include/asm-i386/mach-summit/mach_apic.h
--- linux-2.5.69-bk2/include/asm-i386/mach-summit/mach_apic.h	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/mach-summit/mach_apic.h	2003-05-08 04:38:20.000000000 -0700
@@ -1,7 +1,13 @@
 #ifndef __ASM_MACH_APIC_H
 #define __ASM_MACH_APIC_H
 
+#include <linux/config.h>
+
+#ifdef CONFIG_X86_GENERICARCH
+#define x86_summit 1	/* must be an constant expressiona for generic arch */
+#else
 extern int x86_summit;
+#endif
 
 #define esr_disable (x86_summit ? 1 : 0)
 #define NO_BALANCE_IRQ (0)
@@ -9,20 +15,34 @@
 #define XAPIC_DEST_CPUS_MASK    0x0Fu
 #define XAPIC_DEST_CLUSTER_MASK 0xF0u
 
-#define xapic_phys_to_log_apicid(phys_apic) ( (1ul << ((phys_apic) & 0x3)) |\
-		((phys_apic) & XAPIC_DEST_CLUSTER_MASK) )
+static inline unsigned long xapic_phys_to_log_apicid(int phys_apic) 
+{
+	return ( (1ul << ((phys_apic) & 0x3)) |
+		 ((phys_apic) & XAPIC_DEST_CLUSTER_MASK) );
+}
 
 #define APIC_DFR_VALUE	(x86_summit ? APIC_DFR_CLUSTER : APIC_DFR_FLAT)
-#define TARGET_CPUS	(x86_summit ? XAPIC_DEST_CPUS_MASK : cpu_online_map)
+
+static inline unsigned long target_cpus(void)
+{
+	return (x86_summit ? XAPIC_DEST_CPUS_MASK : cpu_online_map);
+} 
+#define TARGET_CPUS	(target_cpus())
 
 #define INT_DELIVERY_MODE (x86_summit ? dest_Fixed : dest_LowestPrio)
 #define INT_DEST_MODE 1     /* logical delivery broadcast to all procs */
 
-#define APIC_BROADCAST_ID     (x86_summit ? 0xFF : 0x0F)
-#define check_apicid_used(bitmap, apicid) (x86_summit ? 0 : (bitmap & (1 << apicid)))
+#define APIC_BROADCAST_ID     (0x0F)
+static inline unsigned long check_apicid_used(unsigned long bitmap, int apicid) 
+{ 
+	return (x86_summit ? 0 : (bitmap & (1 << apicid)));
+} 
 
 /* we don't use the phys_cpu_present_map to indicate apicid presence */
-#define check_apicid_present(bit) (x86_summit ? 1 : (phys_cpu_present_map & (1 << bit))) 
+static inline unsigned long check_apicid_present(int bit) 
+{
+	return (x86_summit ? 1 : (phys_cpu_present_map & (1 << bit)));
+}
 
 extern u8 bios_cpu_apicid[];
 
@@ -113,4 +133,13 @@
 		return test_bit(boot_cpu_physical_apicid, &phys_cpu_present_map);
 }
 
+#define		APIC_ID_MASK		(0xFF<<24)
+
+static inline unsigned get_apic_id(unsigned long x) 
+{ 
+	return (((x)>>24)&0xFF);
+} 
+
+#define		GET_APIC_ID(x)	get_apic_id(x)
+
 #endif /* __ASM_MACH_APIC_H */
diff -urN linux-2.5.69-bk2/include/asm-i386/mach-summit/mach_ipi.h linux-2.5.69-bk3/include/asm-i386/mach-summit/mach_ipi.h
--- linux-2.5.69-bk2/include/asm-i386/mach-summit/mach_ipi.h	2003-05-04 16:53:05.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/mach-summit/mach_ipi.h	2003-05-08 04:38:20.000000000 -0700
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-static inline void send_IPI_mask_sequence(int mask, int vector);
+inline void send_IPI_mask_sequence(int mask, int vector);
 
 static inline void send_IPI_mask(int mask, int vector)
 {
diff -urN linux-2.5.69-bk2/include/asm-i386/mach-summit/mach_mpparse.h linux-2.5.69-bk3/include/asm-i386/mach-summit/mach_mpparse.h
--- linux-2.5.69-bk2/include/asm-i386/mach-summit/mach_mpparse.h	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/mach-summit/mach_mpparse.h	2003-05-08 04:38:20.000000000 -0700
@@ -14,26 +14,34 @@
 {
 }
 
-static inline void mps_oem_check(struct mp_config_table *mpc, char *oem, 
+static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, 
 		char *productid)
 {
 	if (!strncmp(oem, "IBM ENSW", 8) && 
 			(!strncmp(productid, "VIGIL SMP", 9) 
 			 || !strncmp(productid, "EXA", 3)
 			 || !strncmp(productid, "RUTHLESS SMP", 12))){
+#ifndef CONFIG_X86_GENERICARCH
 		x86_summit = 1;
+#endif
 		use_cyclone = 1; /*enable cyclone-timer*/
+		return 1;
 	}
+	return 0;
 }
 
 /* Hook from generic ACPI tables.c */
-static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 {
 	if (!strncmp(oem_id, "IBM", 3) &&
 	    (!strncmp(oem_table_id, "SERVIGIL", 8)
 	     || !strncmp(oem_table_id, "EXA", 3))){
+#ifndef CONFIG_X86_GENERICARCH
 		x86_summit = 1;
+#endif
 		use_cyclone = 1; /*enable cyclone-timer*/
+		return 1;
 	}
+	return 0;
 }
 #endif /* __ASM_MACH_MPPARSE_H */
diff -urN linux-2.5.69-bk2/include/asm-i386/mmzone.h linux-2.5.69-bk3/include/asm-i386/mmzone.h
--- linux-2.5.69-bk2/include/asm-i386/mmzone.h	2003-05-04 16:53:28.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/mmzone.h	2003-05-08 04:38:20.000000000 -0700
@@ -120,7 +120,7 @@
 
 #ifdef CONFIG_X86_NUMAQ
 #include <asm/numaq.h>
-#elif CONFIG_X86_SUMMIT
+#elif CONFIG_NUMA	/* summit or generic arch */
 #include <asm/srat.h>
 #elif CONFIG_X86_PC
 #define get_memcfg_numa get_memcfg_numa_flat
diff -urN linux-2.5.69-bk2/include/asm-i386/mpspec.h linux-2.5.69-bk3/include/asm-i386/mpspec.h
--- linux-2.5.69-bk2/include/asm-i386/mpspec.h	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/mpspec.h	2003-05-08 04:38:20.000000000 -0700
@@ -16,7 +16,7 @@
 /*
  * a maximum of 16 APICs with the current APIC ID architecture.
  */
-#if defined(CONFIG_X86_NUMAQ) || defined (CONFIG_X86_SUMMIT)
+#if defined(CONFIG_X86_NUMAQ) || defined (CONFIG_X86_SUMMIT) || defined(CONFIG_X86_GENERICARCH)
 #define MAX_APICS 256
 #else
 #define MAX_APICS 16
diff -urN linux-2.5.69-bk2/include/asm-i386/numnodes.h linux-2.5.69-bk3/include/asm-i386/numnodes.h
--- linux-2.5.69-bk2/include/asm-i386/numnodes.h	2003-05-04 16:53:03.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/numnodes.h	2003-05-08 04:38:20.000000000 -0700
@@ -5,7 +5,7 @@
 
 #ifdef CONFIG_X86_NUMAQ
 #include <asm/numaq.h>
-#elif CONFIG_X86_SUMMIT
+#elif CONFIG_NUMA
 #include <asm/srat.h>
 #else
 #define MAX_NUMNODES	1
diff -urN linux-2.5.69-bk2/include/asm-i386/processor.h linux-2.5.69-bk3/include/asm-i386/processor.h
--- linux-2.5.69-bk2/include/asm-i386/processor.h	2003-05-04 16:53:00.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/processor.h	2003-05-08 04:38:20.000000000 -0700
@@ -536,7 +536,7 @@
 #define ASM_NOP6 K8_NOP6
 #define ASM_NOP7 K8_NOP7
 #define ASM_NOP8 K8_NOP8
-#elif CONFIG_MK7
+#elif defined(CONFIG_MK7)
 #define ASM_NOP1 K7_NOP1
 #define ASM_NOP2 K7_NOP2
 #define ASM_NOP3 K7_NOP3
diff -urN linux-2.5.69-bk2/include/asm-i386/smp.h linux-2.5.69-bk3/include/asm-i386/smp.h
--- linux-2.5.69-bk2/include/asm-i386/smp.h	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/smp.h	2003-05-08 04:38:20.000000000 -0700
@@ -87,11 +87,17 @@
 	return -1;
 }
 #ifdef CONFIG_X86_LOCAL_APIC
-static __inline int hard_smp_processor_id(void)
+
+#ifdef APIC_DEFINITION
+extern int hard_smp_processor_id(void);
+#else
+#include <mach_apic.h>
+static inline int hard_smp_processor_id(void)
 {
 	/* we don't want to mark this access volatile - bad code generation */
 	return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID));
 }
+#endif
 
 static __inline int logical_smp_processor_id(void)
 {
diff -urN linux-2.5.69-bk2/include/asm-i386/uaccess.h linux-2.5.69-bk3/include/asm-i386/uaccess.h
--- linux-2.5.69-bk2/include/asm-i386/uaccess.h	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/uaccess.h	2003-05-08 04:38:20.000000000 -0700
@@ -62,8 +62,6 @@
 		:"1" (addr),"g" ((int)(size)),"g" (current_thread_info()->addr_limit.seg)); \
 	flag; })
 
-#ifdef CONFIG_X86_WP_WORKS_OK
-
 /**
  * access_ok: - Checks if a user space pointer is valid
  * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE.  Note that
@@ -85,14 +83,6 @@
  */
 #define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
 
-#else
-
-#define access_ok(type,addr,size) ( (__range_ok(addr,size) == 0) && \
-			 ((type) == VERIFY_READ || boot_cpu_data.wp_works_ok || \
-			  __verify_write((void *)(addr),(size))))
-
-#endif
-
 /**
  * verify_area: - Obsolete, use access_ok()
  * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
@@ -191,14 +181,8 @@
 	__ret_gu;							\
 })
 
-extern void __put_user_1(void);
-extern void __put_user_2(void);
-extern void __put_user_4(void);
-extern void __put_user_8(void);
-
 extern void __put_user_bad(void);
 
-
 /**
  * put_user: - Write a simple value into user space.
  * @x:   Value to copy to user space.
@@ -299,6 +283,8 @@
 		: "=r"(err)					\
 		: "A" (x), "r" (addr), "i"(-EFAULT), "0"(err))
 
+#ifdef CONFIG_X86_WP_WORKS_OK
+
 #define __put_user_size(x,ptr,size,retval,errret)			\
 do {									\
 	retval = 0;							\
@@ -311,6 +297,18 @@
 	}								\
 } while (0)
 
+#else
+
+#define __put_user_size(x,ptr,size,retval,errret)			\
+do {									\
+	__typeof__(*(ptr)) __pus_tmp = x;				\
+	retval = 0;							\
+									\
+	if(unlikely(__copy_to_user_ll(ptr, &__pus_tmp, size) != 0))	\
+		retval = errret;					\
+} while (0)
+
+#endif
 struct __large_struct { unsigned long buf[100]; };
 #define __m(x) (*(struct __large_struct *)(x))
 
diff -urN linux-2.5.69-bk2/include/asm-i386/unistd.h linux-2.5.69-bk3/include/asm-i386/unistd.h
--- linux-2.5.69-bk2/include/asm-i386/unistd.h	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk3/include/asm-i386/unistd.h	2003-05-08 04:38:20.000000000 -0700
@@ -399,6 +399,8 @@
  * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
  * but it doesn't work on all toolchains, so we just do it by hand
  */
+#ifndef cond_syscall
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#endif
 
 #endif /* _ASM_I386_UNISTD_H_ */
diff -urN linux-2.5.69-bk2/include/linux/atm_he.h linux-2.5.69-bk3/include/linux/atm_he.h
--- linux-2.5.69-bk2/include/linux/atm_he.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/include/linux/atm_he.h	2003-05-08 04:38:20.000000000 -0700
@@ -0,0 +1,20 @@
+/* atm_he.h */
+
+#ifndef LINUX_ATM_HE_H
+#define LINUX_ATM_HE_H
+
+#include <linux/atmioc.h>
+
+#define HE_GET_REG	_IOW('a', ATMIOC_SARPRV, struct atmif_sioc)
+
+#define HE_REGTYPE_PCI	1
+#define HE_REGTYPE_RCM	2
+#define HE_REGTYPE_TCM	3
+#define HE_REGTYPE_MBOX	4
+
+struct he_ioctl_reg {
+	unsigned addr, val;
+	char type;
+};
+
+#endif /* LINUX_ATM_HE_H */
diff -urN linux-2.5.69-bk2/include/linux/atmbr2684.h linux-2.5.69-bk3/include/linux/atmbr2684.h
--- linux-2.5.69-bk2/include/linux/atmbr2684.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/include/linux/atmbr2684.h	2003-05-08 04:38:20.000000000 -0700
@@ -0,0 +1,101 @@
+#ifndef _LINUX_ATMBR2684_H
+#define _LINUX_ATMBR2684_H
+
+#include <linux/atm.h>
+#include <linux/if.h>		/* For IFNAMSIZ */
+
+/*
+ * Type of media we're bridging (ethernet, token ring, etc)  Currently only
+ * ethernet is supported
+ */
+#define BR2684_MEDIA_ETHERNET	(0)	/* 802.3 */
+#define BR2684_MEDIA_802_4	(1)	/* 802.4 */
+#define BR2684_MEDIA_TR		(2)	/* 802.5 - token ring */
+#define BR2684_MEDIA_FDDI	(3)
+#define BR2684_MEDIA_802_6	(4)	/* 802.6 */
+
+/*
+ * Is there FCS inbound on this VC?  This currently isn't supported.
+ */
+#define BR2684_FCSIN_NO		(0)
+#define BR2684_FCSIN_IGNORE	(1)
+#define BR2684_FCSIN_VERIFY	(2)
+
+/*
+ * Is there FCS outbound on this VC?  This currently isn't supported.
+ */
+#define BR2684_FCSOUT_NO	(0)
+#define BR2684_FCSOUT_SENDZERO	(1)
+#define BR2684_FCSOUT_GENERATE	(2)
+
+/*
+ * Does this VC include LLC encapsulation?
+ */
+#define BR2684_ENCAPS_VC	(0)	/* VC-mux */
+#define BR2684_ENCAPS_LLC	(1)
+#define BR2684_ENCAPS_AUTODETECT (2)	/* Unsuported */
+
+/*
+ * This is for the ATM_NEWBACKENDIF call - these are like socket families:
+ * the first element of the structure is the backend number and the rest
+ * is per-backend specific
+ */
+struct atm_newif_br2684 {
+	atm_backend_t	backend_num;	/* ATM_BACKEND_BR2684 */
+	int		media;		/* BR2684_MEDIA_* */
+	char		ifname[IFNAMSIZ];
+	int		mtu;
+};
+
+/*
+ * This structure is used to specify a br2684 interface - either by a
+ * positive integer (returned by ATM_NEWBACKENDIF) or the interfaces name
+ */
+#define BR2684_FIND_BYNOTHING	(0)
+#define BR2684_FIND_BYNUM	(1)
+#define BR2684_FIND_BYIFNAME	(2)
+struct br2684_if_spec {
+	int method;			/* BR2684_FIND_* */
+	union {
+		char		ifname[IFNAMSIZ];
+		int		devnum;
+	} spec;
+};
+
+/*
+ * This is for the ATM_SETBACKEND call - these are like socket families:
+ * the first element of the structure is the backend number and the rest
+ * is per-backend specific
+ */
+struct atm_backend_br2684 {
+	atm_backend_t	backend_num;	/* ATM_BACKEND_BR2684 */
+	struct br2684_if_spec ifspec;
+	int	fcs_in;		/* BR2684_FCSIN_* */
+	int	fcs_out;	/* BR2684_FCSOUT_* */
+	int	fcs_auto;	/* 1: fcs_{in,out} disabled if no FCS rx'ed */
+	int	encaps;		/* BR2684_ENCAPS_* */
+	int	has_vpiid;	/* 1: use vpn_id - Unsupported */
+	__u8	vpn_id[7];
+	int	send_padding;	/* unsupported */
+	int	min_size;	/* we will pad smaller packets than this */
+};
+
+/*
+ * The BR2684_SETFILT ioctl is an experimental mechanism for folks
+ * terminating a large number of IP-only vcc's.  When netfilter allows
+ * efficient per-if in/out filters, this support will be removed
+ */
+struct br2684_filter {
+	__u32	prefix;		/* network byte order */
+	__u32	netmask;	/* 0 = disable filter */
+};
+
+struct br2684_filter_set {
+	struct br2684_if_spec ifspec;
+	struct br2684_filter filter;
+};
+
+#define BR2684_SETFILT	_IOW( 'a', ATMIOC_BACKEND + 0, \
+				struct br2684_filter_set)
+
+#endif /* _LINUX_ATMBR2684_H */
diff -urN linux-2.5.69-bk2/include/linux/atmdev.h linux-2.5.69-bk3/include/linux/atmdev.h
--- linux-2.5.69-bk2/include/linux/atmdev.h	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/atmdev.h	2003-05-08 04:38:20.000000000 -0700
@@ -96,6 +96,8 @@
 					/* enable or disable single-copy */
 #define ATM_SETBACKEND	_IOW('a',ATMIOC_SPECIAL+2,atm_backend_t)
 					/* set backend handler */
+#define ATM_NEWBACKENDIF _IOW('a',ATMIOC_SPECIAL+3,atm_backend_t)
+					/* use backend to make new if */
 
 /*
  * These are backend handkers that can be set via the ATM_SETBACKEND call
@@ -104,7 +106,7 @@
  */
 #define ATM_BACKEND_RAW		0	
 #define ATM_BACKEND_PPP		1	/* PPPoATM - RFC2364 */
-#define ATM_BACKEND_BR_2684	2	/* Bridged RFC1483/2684 */
+#define ATM_BACKEND_BR2684	2	/* Bridged RFC1483/2684 */
 
 /* for ATM_GETTYPE */
 #define ATM_ITFTYP_LEN	8	/* maximum length of interface type name */
@@ -304,9 +306,6 @@
 	struct sockaddr_atmsvc local;
 	struct sockaddr_atmsvc remote;
 	void (*callback)(struct atm_vcc *vcc);
-	struct sk_buff_head listenq;
-	int		backlog_quota;	/* number of connection requests we */
-					/* can still accept */
 	int		reply;		/* also used by ATMTCP */
 	/* Multipoint part ------------------------------------------------- */
 	struct atm_vcc	*session;	/* session VCC descriptor */
diff -urN linux-2.5.69-bk2/include/linux/blkpg.h linux-2.5.69-bk3/include/linux/blkpg.h
--- linux-2.5.69-bk2/include/linux/blkpg.h	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/blkpg.h	2003-05-08 04:38:20.000000000 -0700
@@ -54,10 +54,4 @@
 	char volname[BLKPG_VOLNAMELTH];	/* volume label */
 };
 
-#ifdef __KERNEL__
-
-extern char * partition_name(dev_t dev);
-
-#endif /* __KERNEL__ */
-
 #endif /* _LINUX_BLKPG_H */
diff -urN linux-2.5.69-bk2/include/linux/brlvger.h linux-2.5.69-bk3/include/linux/brlvger.h
--- linux-2.5.69-bk2/include/linux/brlvger.h	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/brlvger.h	2003-05-08 04:38:20.000000000 -0700
@@ -30,16 +30,8 @@
 #define BRLVGER_DISPLAY_OFF	3
 #define BRLVGER_BUZZ		4
 
-#ifdef CONFIG_USB_DYNAMIC_MINORS
-#define MAX_NR_BRLVGER_DEVS	256
-#define BRLVGER_MINOR		0
-#else
-/* Number of supported devices, and range of covered minors */
-#define MAX_NR_BRLVGER_DEVS	4
-
 /* Base minor for the char devices */
 #define BRLVGER_MINOR		128
-#endif
 
 /* Size of some fields */
 #define BRLVGER_HWVER_SIZE	2
diff -urN linux-2.5.69-bk2/include/linux/devfs_fs_kernel.h linux-2.5.69-bk3/include/linux/devfs_fs_kernel.h
--- linux-2.5.69-bk2/include/linux/devfs_fs_kernel.h	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/devfs_fs_kernel.h	2003-05-08 04:38:20.000000000 -0700
@@ -27,6 +27,8 @@
 				      umode_t mode, void *ops, void *info);
 extern int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...)
 	__attribute__((format (printf, 3, 4)));
+extern int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
+	__attribute__((format (printf, 3, 4)));
 extern int devfs_mk_symlink(const char *name, const char *link);
 extern int devfs_mk_dir(const char *fmt, ...)
 	__attribute__((format (printf, 1, 2)));
@@ -51,6 +53,10 @@
 {
 	return 0;
 }
+static inline int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
+{
+	return 0;
+}
 static inline int devfs_mk_symlink (const char *name, const char *link)
 {
     return 0;
diff -urN linux-2.5.69-bk2/include/linux/file.h linux-2.5.69-bk3/include/linux/file.h
--- linux-2.5.69-bk2/include/linux/file.h	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/file.h	2003-05-08 04:38:20.000000000 -0700
@@ -35,7 +35,15 @@
 
 extern void FASTCALL(__fput(struct file *));
 extern void FASTCALL(fput(struct file *));
+
+static inline void fput_light(struct file *file, int fput_needed)
+{
+	if (unlikely(fput_needed))
+		fput(file);
+}
+
 extern struct file * FASTCALL(fget(unsigned int fd));
+extern struct file * FASTCALL(fget_light(unsigned int fd, int *fput_needed));
 extern void FASTCALL(set_close_on_exec(unsigned int fd, int flag));
 extern void put_filp(struct file *);
 extern int get_unused_fd(void);
diff -urN linux-2.5.69-bk2/include/linux/fs.h linux-2.5.69-bk3/include/linux/fs.h
--- linux-2.5.69-bk2/include/linux/fs.h	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/fs.h	2003-05-08 04:38:20.000000000 -0700
@@ -206,8 +206,8 @@
 #include <asm/semaphore.h>
 #include <asm/byteorder.h>
 
+/* Used to be a macro which just called the function, now just a function */
 extern void update_atime (struct inode *);
-#define UPDATE_ATIME(inode) update_atime (inode)
 
 extern void inode_init(unsigned long);
 extern void mnt_init(unsigned long);
@@ -1113,6 +1113,10 @@
 extern int filemap_fdatawait(struct address_space *);
 extern void sync_supers(void);
 extern void sync_filesystems(int wait);
+extern void emergency_sync(void);
+extern void emergency_remount(void);
+extern int do_remount_sb(struct super_block *sb, int flags,
+			void *data, int force);
 extern sector_t bmap(struct inode *, sector_t);
 extern int setattr_mask(unsigned int);
 extern int notify_change(struct dentry *, struct iattr *);
diff -urN linux-2.5.69-bk2/include/linux/input.h linux-2.5.69-bk3/include/linux/input.h
--- linux-2.5.69-bk2/include/linux/input.h	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/input.h	2003-05-08 04:38:20.000000000 -0700
@@ -894,9 +894,6 @@
 int input_accept_process(struct input_handle *handle, struct file *file);
 int input_flush_device(struct input_handle* handle, struct file* file);
 
-/* will go away once devfs_register gets sanitized */
-void input_register_minor(char *name, int minor, int minor_base);
-
 void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
 
 #define input_report_key(a,b,c) input_event(a, EV_KEY, b, !!(c))
diff -urN linux-2.5.69-bk2/include/linux/major.h linux-2.5.69-bk3/include/linux/major.h
--- linux-2.5.69-bk2/include/linux/major.h	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/major.h	2003-05-08 04:38:20.000000000 -0700
@@ -27,6 +27,7 @@
 #define MUX_MAJOR		11	/* PA-RISC only */
 #define QIC02_TAPE_MAJOR	12
 #define XT_DISK_MAJOR		13
+#define INPUT_MAJOR		13
 #define SOUND_MAJOR		14
 #define CDU31A_CDROM_MAJOR	15
 #define JOYSTICK_MAJOR		15
diff -urN linux-2.5.69-bk2/include/linux/raid/md.h linux-2.5.69-bk3/include/linux/raid/md.h
--- linux-2.5.69-bk2/include/linux/raid/md.h	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/raid/md.h	2003-05-08 04:38:20.000000000 -0700
@@ -61,9 +61,20 @@
 #define MD_MINOR_VERSION                90
 #define MD_PATCHLEVEL_VERSION           0
 
-extern inline char * bdev_partition_name (struct block_device *bdev)
+/*
+ * XXX(hch): This function is broken.  Someone who understands the md
+ * code needs to go through all callers, check whether bdev could
+ * be NULL and replace it with direct calls to bdevmame.
+ *
+ * This would also fix the returns buffer on stack issue nicely :)
+ */
+static inline const char *bdev_partition_name (struct block_device *bdev)
 {
-	return partition_name(bdev ? bdev->bd_dev : 0);
+	char b[BDEVNAME_SIZE];
+
+	if (!bdev)
+		return __bdevname(0, b);
+	return bdevname(bdev, b);
 }
 extern int register_md_personality (int p_num, mdk_personality_t *p);
 extern int unregister_md_personality (int p_num);
diff -urN linux-2.5.69-bk2/include/linux/rtnetlink.h linux-2.5.69-bk3/include/linux/rtnetlink.h
--- linux-2.5.69-bk2/include/linux/rtnetlink.h	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/rtnetlink.h	2003-05-08 04:38:21.000000000 -0700
@@ -78,7 +78,7 @@
 
 
 /******************************************************************************
- *		Definitions used in routing table administation.
+ *		Definitions used in routing table administration.
  ****/
 
 struct rtmsg
@@ -129,14 +129,14 @@
 #define RTPROT_STATIC	4	/* Route installed by administrator	*/
 
 /* Values of protocol >= RTPROT_STATIC are not interpreted by kernel;
-   they just passed from user and back as is.
+   they are just passed from user and back as is.
    It will be used by hypothetical multiple routing daemons.
    Note that protocol values should be standardized in order to
    avoid conflicts.
  */
 
 #define RTPROT_GATED	8	/* Apparently, GateD */
-#define RTPROT_RA	9	/* RDISC/ND router advertisments */
+#define RTPROT_RA	9	/* RDISC/ND router advertisements */
 #define RTPROT_MRT	10	/* Merit MRT */
 #define RTPROT_ZEBRA	11	/* Zebra */
 #define RTPROT_BIRD	12	/* BIRD */
@@ -210,8 +210,8 @@
 
 /* RTM_MULTIPATH --- array of struct rtnexthop.
  *
- * "struct rtnexthop" describres all necessary nexthop information,
- * i.e. parameters of path to a destination via this nextop.
+ * "struct rtnexthop" describes all necessary nexthop information,
+ * i.e. parameters of path to a destination via this nexthop.
  *
  * At the moment it is impossible to set different prefsrc, mtu, window
  * and rtt for different paths from multipath.
@@ -485,7 +485,7 @@
 
    Comments:
    - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid
-   - If neiher of these three flags are set;
+   - If neither of these three flags are set;
      the interface is NBMA.
 
    - IFF_MULTICAST does not mean anything special:
diff -urN linux-2.5.69-bk2/include/linux/sched.h linux-2.5.69-bk3/include/linux/sched.h
--- linux-2.5.69-bk2/include/linux/sched.h	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/sched.h	2003-05-08 04:38:21.000000000 -0700
@@ -294,6 +294,7 @@
 
 typedef struct prio_array prio_array_t;
 struct backing_dev_info;
+struct reclaim_state;
 
 /* POSIX.1b interval timer structure. */
 struct k_itimer {
@@ -433,6 +434,10 @@
 
 /* journalling filesystem info */
 	void *journal_info;
+
+/* VM state */
+	struct reclaim_state *reclaim_state;
+
 	struct dentry *proc_dentry;
 	struct backing_dev_info *backing_dev_info;
 
diff -urN linux-2.5.69-bk2/include/linux/security.h linux-2.5.69-bk3/include/linux/security.h
--- linux-2.5.69-bk2/include/linux/security.h	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/security.h	2003-05-08 04:38:21.000000000 -0700
@@ -361,6 +361,9 @@
  * 	Check permission before setting the extended attributes
  * 	@value identified by @name for @dentry.
  * 	Return 0 if permission is granted.
+ * @inode_post_setxattr:
+ * 	Update inode security field after successful setxattr operation.
+ * 	@value identified by @name for @dentry.
  * @inode_getxattr:
  * 	Check permission before obtaining the extended attributes
  * 	identified by @name for @dentry.
@@ -1036,6 +1039,8 @@
         void (*inode_delete) (struct inode *inode);
 	int (*inode_setxattr) (struct dentry *dentry, char *name, void *value,
 			       size_t size, int flags);
+	void (*inode_post_setxattr) (struct dentry *dentry, char *name, void *value,
+				     size_t size, int flags);
 	int (*inode_getxattr) (struct dentry *dentry, char *name);
 	int (*inode_listxattr) (struct dentry *dentry);
 	int (*inode_removexattr) (struct dentry *dentry, char *name);
@@ -1464,6 +1469,12 @@
 	return security_ops->inode_setxattr (dentry, name, value, size, flags);
 }
 
+static inline void security_inode_post_setxattr (struct dentry *dentry, char *name,
+						void *value, size_t size, int flags)
+{
+	security_ops->inode_post_setxattr (dentry, name, value, size, flags);
+}
+
 static inline int security_inode_getxattr (struct dentry *dentry, char *name)
 {
 	return security_ops->inode_getxattr (dentry, name);
@@ -2063,6 +2074,10 @@
 	return 0;
 }
 
+static inline void security_inode_post_setxattr (struct dentry *dentry, char *name,
+						 void *value, size_t size, int flags)
+{ }
+
 static inline int security_inode_getxattr (struct dentry *dentry, char *name)
 {
 	return 0;
diff -urN linux-2.5.69-bk2/include/linux/slab.h linux-2.5.69-bk3/include/linux/slab.h
--- linux-2.5.69-bk2/include/linux/slab.h	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/slab.h	2003-05-08 04:38:21.000000000 -0700
@@ -49,7 +49,6 @@
 
 /* prototypes */
 extern void kmem_cache_init(void);
-extern void kmem_cache_sizes_init(void);
 
 extern kmem_cache_t *kmem_find_general_cachep(size_t, int gfpflags);
 extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned long,
diff -urN linux-2.5.69-bk2/include/linux/sunrpc/svc.h linux-2.5.69-bk3/include/linux/sunrpc/svc.h
--- linux-2.5.69-bk2/include/linux/sunrpc/svc.h	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/sunrpc/svc.h	2003-05-08 04:38:21.000000000 -0700
@@ -176,8 +176,10 @@
 {
 	if (rqstp->rq_arghi <= rqstp->rq_argused)
 		return -ENOMEM;
-	rqstp->rq_respages[rqstp->rq_resused++] =
-		rqstp->rq_argpages[--rqstp->rq_arghi];
+	rqstp->rq_arghi--;
+	rqstp->rq_respages[rqstp->rq_resused] =
+		rqstp->rq_argpages[rqstp->rq_arghi];
+	rqstp->rq_resused++;
 	return 0;
 }
 
diff -urN linux-2.5.69-bk2/include/linux/swap.h linux-2.5.69-bk3/include/linux/swap.h
--- linux-2.5.69-bk2/include/linux/swap.h	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/swap.h	2003-05-08 04:38:21.000000000 -0700
@@ -66,6 +66,14 @@
 	unsigned long val;
 } swp_entry_t;
 
+/*
+ * current->reclaim_state points to one of these when a task is running
+ * memory reclaim
+ */
+struct reclaim_state {
+	unsigned long reclaimed_slab;
+};
+
 #ifdef __KERNEL__
 
 struct address_space;
diff -urN linux-2.5.69-bk2/include/linux/sysrq.h linux-2.5.69-bk3/include/linux/sysrq.h
--- linux-2.5.69-bk2/include/linux/sysrq.h	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/sysrq.h	2003-05-08 04:38:21.000000000 -0700
@@ -92,21 +92,3 @@
 #define unregister_sysrq_key(ig,nore) __reterr()
 
 #endif
-
-
-/* Deferred actions */
-
-extern int emergency_sync_scheduled;
-
-#define EMERG_SYNC 1
-#define EMERG_REMOUNT 2
-
-void do_emergency_sync(void);
-
-#ifdef CONFIG_MAGIC_SYSRQ
-#define CHECK_EMERGENCY_SYNC			\
-	if (emergency_sync_scheduled)		\
-		do_emergency_sync();
-#else
-#define CHECK_EMERGENCY_SYNC
-#endif
diff -urN linux-2.5.69-bk2/include/linux/tty.h linux-2.5.69-bk3/include/linux/tty.h
--- linux-2.5.69-bk2/include/linux/tty.h	2003-05-04 16:53:28.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/tty.h	2003-05-08 04:38:21.000000000 -0700
@@ -243,6 +243,7 @@
 #define L_PENDIN(tty)	_L_FLAG((tty),PENDIN)
 #define L_IEXTEN(tty)	_L_FLAG((tty),IEXTEN)
 
+struct device;
 /*
  * Where all of the state associated with a tty is kept while the tty
  * is open.  Since the termios state should be kept even if the tty
@@ -380,7 +381,7 @@
 extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc);
 extern int tty_register_driver(struct tty_driver *driver);
 extern int tty_unregister_driver(struct tty_driver *driver);
-extern void tty_register_device(struct tty_driver *driver, unsigned index);
+extern void tty_register_device(struct tty_driver *driver, unsigned index, struct device *dev);
 extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
 extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
 			     int buflen);
diff -urN linux-2.5.69-bk2/include/linux/usb.h linux-2.5.69-bk3/include/linux/usb.h
--- linux-2.5.69-bk2/include/linux/usb.h	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/include/linux/usb.h	2003-05-08 04:38:21.000000000 -0700
@@ -73,13 +73,22 @@
 /**
  * struct usb_interface - what usb device drivers talk to
  * @altsetting: array of interface descriptors, one for each alternate
- * 	setting that may be selected.  each one includes a set of
- * 	endpoint configurations.
+ * 	setting that may be selected.  Each one includes a set of
+ * 	endpoint configurations and will be in numberic order,
+ * 	0..num_altsetting.
  * @num_altsetting: number of altsettings defined.
  * @act_altsetting: index of current altsetting.  this number is always
  *	less than num_altsetting.  after the device is configured, each
  *	interface uses its default setting of zero.
+ * @max_altsetting:
+ * @minor: the minor number assigned to this interface, if this
+ *	interface is bound to a driver that uses the USB major number.
+ *	If this interface does not use the USB major, this field should
+ *	be unused.  The driver should set this value in the probe()
+ *	function of the driver, after it has been assigned a minor
+ *	number from the USB core by calling usb_register_dev().
  * @dev: driver model's view of this device
+ * @class_dev: driver model's class view of this device.
  *
  * USB device drivers attach to interfaces on a physical device.  Each
  * interface encapsulates a single high level function, such as feeding
@@ -111,10 +120,12 @@
 	unsigned max_altsetting;	/* total memory allocated */
 
 	struct usb_driver *driver;	/* driver */
-	kdev_t kdev;			/* node this interface is bound to */
+	int minor;			/* minor number this interface is bound to */
 	struct device dev;		/* interface specific device info */
+	struct class_device class_dev;
 };
 #define	to_usb_interface(d) container_of(d, struct usb_interface, dev)
+#define class_dev_to_usb_interface(d) container_of(d, struct usb_interface, class_dev)
 #define	interface_to_usbdev(intf) \
 	container_of(intf->dev.parent, struct usb_device, dev)
 
@@ -279,7 +290,7 @@
 const struct usb_device_id *usb_match_id(struct usb_interface *interface,
 					 const struct usb_device_id *id);
 
-extern struct usb_interface *usb_find_interface(struct usb_driver *drv, kdev_t kdev);
+extern struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor);
 extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum);
 
 
@@ -433,6 +444,25 @@
 
 extern struct bus_type usb_bus_type;
 
+/**
+ * struct usb_class_driver - identifies a USB driver that wants to use the USB major number
+ * @name: devfs name for this driver.  Will also be used by the driver
+ *	class code to create a usb class device.
+ * @fops: pointer to the struct file_operations of this driver.
+ * @mode: the mode for the devfs file to be created for this driver.
+ * @minor_base: the start of the minor range for this driver.
+ *
+ * This structure is used for the usb_register_dev() and
+ * usb_unregister_dev() functions, to consolodate a number of the
+ * paramaters used for them.
+ */
+struct usb_class_driver {
+	char *name;
+	struct file_operations *fops;
+	mode_t mode;
+	int minor_base;	
+};
+
 /*
  * use these in module_init()/module_exit()
  * and don't forget MODULE_DEVICE_TABLE(usb, ...)
@@ -440,8 +470,10 @@
 extern int usb_register(struct usb_driver *);
 extern void usb_deregister(struct usb_driver *);
 
-extern int usb_register_dev(struct file_operations *fops, int minor, int num_minors, int *start_minor);
-extern void usb_deregister_dev(int num_minors, int start_minor);
+extern int usb_register_dev(struct usb_interface *intf,
+			    struct usb_class_driver *class_driver);
+extern void usb_deregister_dev(struct usb_interface *intf,
+			       struct usb_class_driver *class_driver);
 
 extern int usb_device_probe(struct device *dev);
 extern int usb_device_remove(struct device *dev);
diff -urN linux-2.5.69-bk2/init/main.c linux-2.5.69-bk3/init/main.c
--- linux-2.5.69-bk2/init/main.c	2003-05-04 16:53:03.000000000 -0700
+++ linux-2.5.69-bk3/init/main.c	2003-05-08 04:38:21.000000000 -0700
@@ -417,7 +417,6 @@
 	 */
 	console_init();
 	profile_init();
-	kmem_cache_init();
 	local_irq_enable();
 	calibrate_delay();
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -430,7 +429,7 @@
 #endif
 	page_address_init();
 	mem_init();
-	kmem_cache_sizes_init();
+	kmem_cache_init();
 	pidmap_init();
 	pgtable_cache_init();
 	pte_chain_init();
diff -urN linux-2.5.69-bk2/ipc/shm.c linux-2.5.69-bk3/ipc/shm.c
--- linux-2.5.69-bk2/ipc/shm.c	2003-05-04 16:53:28.000000000 -0700
+++ linux-2.5.69-bk3/ipc/shm.c	2003-05-08 04:38:21.000000000 -0700
@@ -149,7 +149,7 @@
 
 static int shm_mmap(struct file * file, struct vm_area_struct * vma)
 {
-	UPDATE_ATIME(file->f_dentry->d_inode);
+	update_atime(file->f_dentry->d_inode);
 	vma->vm_ops = &shm_vm_ops;
 	shm_inc(file->f_dentry->d_inode->i_ino);
 	return 0;
diff -urN linux-2.5.69-bk2/kernel/ksyms.c linux-2.5.69-bk3/kernel/ksyms.c
--- linux-2.5.69-bk2/kernel/ksyms.c	2003-05-08 04:38:12.000000000 -0700
+++ linux-2.5.69-bk3/kernel/ksyms.c	2003-05-08 04:38:21.000000000 -0700
@@ -580,8 +580,6 @@
 EXPORT_SYMBOL(fasync_helper);
 EXPORT_SYMBOL(kill_fasync);
 
-EXPORT_SYMBOL(partition_name);
-
 /* binfmt_aout */
 EXPORT_SYMBOL(get_write_access);
 
diff -urN linux-2.5.69-bk2/kernel/panic.c linux-2.5.69-bk3/kernel/panic.c
--- linux-2.5.69-bk2/kernel/panic.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk3/kernel/panic.c	2003-05-08 04:38:21.000000000 -0700
@@ -96,9 +96,8 @@
         disabled_wait(caller);
 #endif
 	local_irq_enable();
-	for(;;) {
-		CHECK_EMERGENCY_SYNC
-	}
+	for (;;)
+		;
 }
 
 /**
diff -urN linux-2.5.69-bk2/lib/inflate.c linux-2.5.69-bk3/lib/inflate.c
--- linux-2.5.69-bk2/lib/inflate.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk3/lib/inflate.c	2003-05-08 04:38:21.000000000 -0700
@@ -271,14 +271,15 @@
 STATIC unsigned hufts;         /* track memory usage */
 
 
-STATIC int huft_build(b, n, s, d, e, t, m)
-unsigned *b;            /* code lengths in bits (all assumed <= BMAX) */
-unsigned n;             /* number of codes (assumed <= N_MAX) */
-unsigned s;             /* number of simple-valued codes (0..s-1) */
-const ush *d;                 /* list of base values for non-simple codes */
-const ush *e;                 /* list of extra bits for non-simple codes */
-struct huft **t;        /* result: starting table */
-int *m;                 /* maximum lookup bits, returns actual */
+STATIC int huft_build(
+	unsigned *b,            /* code lengths in bits (all assumed <= BMAX) */
+	unsigned n,             /* number of codes (assumed <= N_MAX) */
+	unsigned s,             /* number of simple-valued codes (0..s-1) */
+	const ush *d,           /* list of base values for non-simple codes */
+	const ush *e,           /* list of extra bits for non-simple codes */
+	struct huft **t,        /* result: starting table */
+	int *m                  /* maximum lookup bits, returns actual */
+	)
 /* Given a list of code lengths and a maximum table size, make a set of
    tables to decode that set of codes.  Return zero on success, one if
    the given code set is incomplete (the tables are still built in this
@@ -489,8 +490,9 @@
 
 
 
-STATIC int huft_free(t)
-struct huft *t;         /* table to free */
+STATIC int huft_free(
+	struct huft *t         /* table to free */
+	)
 /* Free the malloc'ed tables built by huft_build(), which makes a linked
    list of the tables it made, with the links in a dummy first entry of
    each table. */
@@ -510,9 +512,12 @@
 }
 
 
-STATIC int inflate_codes(tl, td, bl, bd)
-struct huft *tl, *td;   /* literal/length and distance decoder tables */
-int bl, bd;             /* number of bits decoded by tl[] and td[] */
+STATIC int inflate_codes(
+	struct huft *tl,    /* literal/length decoder tables */
+	struct huft *td,    /* distance decoder tables */
+	int bl,             /* number of bits decoded by tl[] */
+	int bd              /* number of bits decoded by td[] */
+	)
 /* inflate (decompress) the codes in a deflated (compressed) block.
    Return an error code or zero if it all goes ok. */
 {
@@ -619,7 +624,7 @@
 
 
 
-STATIC int inflate_stored()
+STATIC int inflate_stored(void)
 /* "decompress" an inflated type 0 (stored) block. */
 {
   unsigned n;           /* number of bytes in block */
@@ -675,7 +680,7 @@
 
 
 
-STATIC int inflate_fixed()
+STATIC int inflate_fixed(void)
 /* decompress an inflated type 1 (fixed Huffman codes) block.  We should
    either replace this with a custom decoder, or at least precompute the
    Huffman tables. */
@@ -729,7 +734,7 @@
 
 
 
-STATIC int inflate_dynamic()
+STATIC int inflate_dynamic(void)
 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
 {
   int i;                /* temporary variables */
@@ -907,8 +912,9 @@
 
 
 
-STATIC int inflate_block(e)
-int *e;                 /* last block flag */
+STATIC int inflate_block(
+	int *e                  /* last block flag */
+	)
 /* decompress an inflated block */
 {
   unsigned t;           /* block type */
@@ -954,7 +960,7 @@
 
 
 
-STATIC int inflate()
+STATIC int inflate(void)
 /* decompress an inflated entry */
 {
   int e;                /* last block flag */
diff -urN linux-2.5.69-bk2/mm/filemap.c linux-2.5.69-bk3/mm/filemap.c
--- linux-2.5.69-bk2/mm/filemap.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk3/mm/filemap.c	2003-05-08 04:38:21.000000000 -0700
@@ -681,7 +681,7 @@
 	*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
 	if (cached_page)
 		page_cache_release(cached_page);
-	UPDATE_ATIME(inode);
+	update_atime(inode);
 }
 
 int file_read_actor(read_descriptor_t *desc, struct page *page,
@@ -774,7 +774,7 @@
 			if (retval > 0)
 				*ppos = pos + retval;
 		}
-		UPDATE_ATIME(filp->f_dentry->d_inode);
+		update_atime(filp->f_dentry->d_inode);
 		goto out;
 	}
 
@@ -1259,7 +1259,7 @@
 
 	if (!mapping->a_ops->readpage)
 		return -ENOEXEC;
-	UPDATE_ATIME(inode);
+	update_atime(inode);
 	vma->vm_ops = &generic_file_vm_ops;
 	return 0;
 }
diff -urN linux-2.5.69-bk2/mm/page-writeback.c linux-2.5.69-bk3/mm/page-writeback.c
--- linux-2.5.69-bk2/mm/page-writeback.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk3/mm/page-writeback.c	2003-05-08 04:38:21.000000000 -0700
@@ -20,7 +20,6 @@
 #include <linux/pagemap.h>
 #include <linux/writeback.h>
 #include <linux/init.h>
-#include <linux/sysrq.h>
 #include <linux/backing-dev.h>
 #include <linux/blkdev.h>
 #include <linux/mpage.h>
@@ -237,7 +236,6 @@
 		.nonblocking	= 1,
 	};
 
-	CHECK_EMERGENCY_SYNC
 	for ( ; ; ) {
 		struct page_state ps;
 		long background_thresh;
diff -urN linux-2.5.69-bk2/mm/page_alloc.c linux-2.5.69-bk3/mm/page_alloc.c
--- linux-2.5.69-bk2/mm/page_alloc.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk3/mm/page_alloc.c	2003-05-08 04:38:21.000000000 -0700
@@ -537,6 +537,7 @@
 	int i;
 	int cold;
 	int do_retry;
+	struct reclaim_state reclaim_state;
 
 	if (wait)
 		might_sleep();
@@ -608,7 +609,12 @@
 		goto nopage;
 
 	current->flags |= PF_MEMALLOC;
+	reclaim_state.reclaimed_slab = 0;
+	current->reclaim_state = &reclaim_state;
+
 	try_to_free_pages(classzone, gfp_mask, order);
+
+	current->reclaim_state = NULL;
 	current->flags &= ~PF_MEMALLOC;
 
 	/* go through the zonelist yet one more time */
diff -urN linux-2.5.69-bk2/mm/shmem.c linux-2.5.69-bk3/mm/shmem.c
--- linux-2.5.69-bk2/mm/shmem.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/mm/shmem.c	2003-05-08 04:38:21.000000000 -0700
@@ -1013,7 +1013,7 @@
 	ops = &shmem_vm_ops;
 	if (!inode->i_sb || !S_ISREG(inode->i_mode))
 		return -EACCES;
-	UPDATE_ATIME(inode);
+	update_atime(inode);
 	vma->vm_ops = ops;
 	return 0;
 }
@@ -1307,7 +1307,7 @@
 	}
 
 	*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
-	UPDATE_ATIME(inode);
+	update_atime(inode);
 }
 
 static ssize_t shmem_file_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
diff -urN linux-2.5.69-bk2/mm/slab.c linux-2.5.69-bk3/mm/slab.c
--- linux-2.5.69-bk2/mm/slab.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/mm/slab.c	2003-05-08 04:38:21.000000000 -0700
@@ -76,6 +76,7 @@
 #include	<linux/config.h>
 #include	<linux/slab.h>
 #include	<linux/mm.h>
+#include	<linux/swap.h>
 #include	<linux/cache.h>
 #include	<linux/interrupt.h>
 #include	<linux/init.h>
@@ -567,11 +568,40 @@
 	return cachep->array[smp_processor_id()];
 }
 
-/* Initialisation - setup the `cache' cache. */
+/* Initialisation.
+ * Called after the gfp() functions have been enabled, and before smp_init().
+ */
 void __init kmem_cache_init(void)
 {
 	size_t left_over;
+	struct cache_sizes *sizes;
+	struct cache_names *names;
 
+	/*
+	 * Fragmentation resistance on low memory - only use bigger
+	 * page orders on machines with more than 32MB of memory.
+	 */
+	if (num_physpages > (32 << 20) >> PAGE_SHIFT)
+		slab_break_gfp_order = BREAK_GFP_ORDER_HI;
+
+	
+	/* Bootstrap is tricky, because several objects are allocated
+	 * from caches that do not exist yet:
+	 * 1) initialize the cache_cache cache: it contains the kmem_cache_t
+	 *    structures of all caches, except cache_cache itself: cache_cache
+	 *    is statically allocated.
+	 *    Initially an __init data area is used for the head array, it's
+	 *    replaced with a kmalloc allocated array at the end of the bootstrap.
+	 * 2) Create the first kmalloc cache.
+	 *    The kmem_cache_t for the new cache is allocated normally. An __init
+	 *    data area is used for the head array.
+	 * 3) Create the remaining kmalloc caches, with minimally sized head arrays.
+	 * 4) Replace the __init data head arrays for cache_cache and the first
+	 *    kmalloc cache with kmalloc allocated arrays.
+	 * 5) Resize the head arrays of the kmalloc caches to their final sizes.
+	 */
+
+	/* 1) create the cache_cache */
 	init_MUTEX(&cache_chain_sem);
 	INIT_LIST_HEAD(&cache_chain);
 	list_add(&cache_cache.next, &cache_chain);
@@ -585,27 +615,10 @@
 	cache_cache.colour = left_over/cache_cache.colour_off;
 	cache_cache.colour_next = 0;
 
-	/* Register a cpu startup notifier callback
-	 * that initializes ac_data for all new cpus
-	 */
-	register_cpu_notifier(&cpucache_notifier);
-}
-
 
-/* Initialisation - setup remaining internal and general caches.
- * Called after the gfp() functions have been enabled, and before smp_init().
- */
-void __init kmem_cache_sizes_init(void)
-{
-	struct cache_sizes *sizes = malloc_sizes;
-	struct cache_names *names = cache_names;
-
-	/*
-	 * Fragmentation resistance on low memory - only use bigger
-	 * page orders on machines with more than 32MB of memory.
-	 */
-	if (num_physpages > (32 << 20) >> PAGE_SHIFT)
-		slab_break_gfp_order = BREAK_GFP_ORDER_HI;
+	/* 2+3) create the kmalloc caches */
+	sizes = malloc_sizes;
+	names = cache_names;
 
 	while (sizes->cs_size) {
 		/* For performance, all the general caches are L1 aligned.
@@ -634,10 +647,7 @@
 		sizes++;
 		names++;
 	}
-	/*
-	 * The generic caches are running - time to kick out the
-	 * bootstrap cpucaches.
-	 */
+	/* 4) Replace the bootstrap head arrays */
 	{
 		void * ptr;
 		
@@ -656,29 +666,42 @@
 		malloc_sizes[0].cs_cachep->array[smp_processor_id()] = ptr;
 		local_irq_enable();
 	}
+
+	/* 5) resize the head arrays to their final sizes */
+	{
+		kmem_cache_t *cachep;
+		down(&cache_chain_sem);
+		list_for_each_entry(cachep, &cache_chain, next)
+			enable_cpucache(cachep);
+		up(&cache_chain_sem);
+	}
+
+	/* Done! */
+	g_cpucache_up = FULL;
+
+	/* Register a cpu startup notifier callback
+	 * that initializes ac_data for all new cpus
+	 */
+	register_cpu_notifier(&cpucache_notifier);
+	
+
+	/* The reap timers are started later, with a module init call:
+	 * That part of the kernel is not yet operational.
+	 */
 }
 
 int __init cpucache_init(void)
 {
-	kmem_cache_t *cachep;
 	int cpu;
 
-	down(&cache_chain_sem);
-	g_cpucache_up = FULL;
-
-	list_for_each_entry(cachep, &cache_chain, next)
-		enable_cpucache(cachep);
-	
 	/* 
 	 * Register the timers that return unneeded
 	 * pages to gfp.
 	 */
-
 	for (cpu = 0; cpu < NR_CPUS; cpu++) {
 		if (cpu_online(cpu))
 			start_cpu_timer(cpu);
 	}
-	up(&cache_chain_sem);
 
 	return 0;
 }
@@ -712,6 +735,7 @@
 {
 	unsigned long i = (1<<cachep->gfporder);
 	struct page *page = virt_to_page(addr);
+	const unsigned long nr_freed = i;
 
 	/* free_pages() does not clear the type bit - we do that.
 	 * The pages have been unlinked from their cache-slab,
@@ -720,9 +744,11 @@
 	 */
 	while (i--) {
 		ClearPageSlab(page);
-		dec_page_state(nr_slab);
 		page++;
 	}
+	sub_page_state(nr_slab, nr_freed);
+	if (current->reclaim_state)
+		current->reclaim_state->reclaimed_slab += nr_freed;
 	free_pages((unsigned long)addr, cachep->gfporder);
 }
 
@@ -914,12 +940,19 @@
 	}
 
 #if FORCED_DEBUG
-	if ((size < (PAGE_SIZE>>3)) && !(flags & SLAB_MUST_HWCACHE_ALIGN))
-		/*
-		 * do not red zone large object, causes severe
-		 * fragmentation.
-		 */
+	/*
+	 * Enable redzoning and last user accounting, except
+	 * - for caches with forced alignment: redzoning would violate the
+	 *   alignment
+	 * - for caches with large objects, if the increased size would
+	 *   increase the object size above the next power of two: caches
+	 *   with object sizes just above a power of two have a significant
+	 *   amount of internal fragmentation
+	 */
+	if ((size < (PAGE_SIZE>>3) || fls(size-1) == fls(size-1+3*BYTES_PER_WORD))
+			&& !(flags & SLAB_MUST_HWCACHE_ALIGN)) {
 		flags |= SLAB_RED_ZONE|SLAB_STORE_USER;
+	}
 	flags |= SLAB_POISON;
 #endif
 #endif
@@ -1756,10 +1789,12 @@
 		slabp = GET_PAGE_SLAB(virt_to_page(objp));
 		list_del(&slabp->list);
 		objnr = (objp - slabp->s_mem) / cachep->objsize;
+		check_slabp(cachep, slabp);
 		slab_bufctl(slabp)[objnr] = slabp->free;
 		slabp->free = objnr;
 		STATS_DEC_ACTIVE(cachep);
 		slabp->inuse--;
+		check_slabp(cachep, slabp);
 
 		/* fixup slab chains */
 		if (slabp->inuse == 0) {
diff -urN linux-2.5.69-bk2/mm/swapfile.c linux-2.5.69-bk3/mm/swapfile.c
--- linux-2.5.69-bk2/mm/swapfile.c	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk3/mm/swapfile.c	2003-05-08 04:38:21.000000000 -0700
@@ -886,6 +886,10 @@
  * requirements, they are simply tossed out - we will never use those blocks
  * for swapping.
  *
+ * For S_ISREG swapfiles we hold i_sem across the life of the swapon.  This
+ * prevents root from shooting her foot off by ftruncating an in-use swapfile,
+ * which will scribble on the fs.
+ *
  * The amount of disk space which a single swap extent represents varies.
  * Typically it is in the 1-4 megabyte range.  So we can have hundreds of
  * extents in the list.  To avoid much list walking, we cache the previous
@@ -1095,6 +1099,8 @@
 		bdev = swap_file->f_dentry->d_inode->i_bdev;
 		set_blocksize(bdev, p->old_block_size);
 		bd_release(bdev);
+	} else {
+		up(&swap_file->f_dentry->d_inode->i_mapping->host->i_sem);
 	}
 	filp_close(swap_file, NULL);
 	err = 0;
@@ -1228,6 +1234,8 @@
 	int swapfilesize;
 	unsigned short *swap_map;
 	struct page *page = NULL;
+	struct inode *inode;
+	struct inode *downed_inode = NULL;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
@@ -1274,39 +1282,42 @@
 	}
 
 	p->swap_file = swap_file;
+	inode = swap_file->f_dentry->d_inode;
+	mapping = swap_file->f_dentry->d_inode->i_mapping;
+
+	error = -EBUSY;
+	for (i = 0; i < nr_swapfiles; i++) {
+		struct swap_info_struct *q = &swap_info[i];
+
+		if (i == type || !q->swap_file)
+			continue;
+		if (mapping == q->swap_file->f_dentry->d_inode->i_mapping)
+			goto bad_swap;
+	}
 
 	error = -EINVAL;
-	if (S_ISBLK(swap_file->f_dentry->d_inode->i_mode)) {
-		bdev = swap_file->f_dentry->d_inode->i_bdev;
+	if (S_ISBLK(inode->i_mode)) {
+		bdev = inode->i_bdev;
 		error = bd_claim(bdev, sys_swapon);
 		if (error < 0) {
 			bdev = NULL;
 			goto bad_swap;
 		}
 		p->old_block_size = block_size(bdev);
-		error = set_blocksize(swap_file->f_dentry->d_inode->i_bdev,
-				      PAGE_SIZE);
+		error = set_blocksize(inode->i_bdev, PAGE_SIZE);
 		if (error < 0)
 			goto bad_swap;
 		p->bdev = bdev;
-	} else if (S_ISREG(swap_file->f_dentry->d_inode->i_mode)) {
-		p->bdev = swap_file->f_dentry->d_inode->i_sb->s_bdev;
+	} else if (S_ISREG(inode->i_mode)) {
+		p->bdev = inode->i_sb->s_bdev;
+		downed_inode = mapping->host;
+		down(&downed_inode->i_sem);
 	} else {
 		goto bad_swap;
 	}
 
-	mapping = swap_file->f_dentry->d_inode->i_mapping;
 	swapfilesize = mapping->host->i_size >> PAGE_SHIFT;
 
-	error = -EBUSY;
-	for (i = 0 ; i < nr_swapfiles ; i++) {
-		struct swap_info_struct *q = &swap_info[i];
-		if (i == type || !q->swap_file)
-			continue;
-		if (mapping == q->swap_file->f_dentry->d_inode->i_mapping)
-			goto bad_swap;
-	}
-
 	/*
 	 * Read the swap header.
 	 */
@@ -1452,6 +1463,8 @@
 	}
 	if (name)
 		putname(name);
+	if (error && downed_inode)
+		up(&downed_inode->i_sem);
 	return error;
 }
 
diff -urN linux-2.5.69-bk2/mm/vmalloc.c linux-2.5.69-bk3/mm/vmalloc.c
--- linux-2.5.69-bk2/mm/vmalloc.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/mm/vmalloc.c	2003-05-08 04:38:21.000000000 -0700
@@ -97,8 +97,7 @@
 	do {
 		struct page *page = **pages;
 
-		if (!pte_none(*pte))
-			printk(KERN_ERR "alloc_area_pte: page already exists\n");
+		WARN_ON(!pte_none(*pte));
 		if (!page)
 			return -ENOMEM;
 
diff -urN linux-2.5.69-bk2/mm/vmscan.c linux-2.5.69-bk3/mm/vmscan.c
--- linux-2.5.69-bk2/mm/vmscan.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk3/mm/vmscan.c	2003-05-08 04:38:21.000000000 -0700
@@ -817,12 +817,14 @@
  * excessive rotation of the inactive list, which is _supposed_ to be an LRU,
  * yes?
  */
-int try_to_free_pages(struct zone *classzone,
+int try_to_free_pages(struct zone *cz,
 		unsigned int gfp_mask, unsigned int order)
 {
 	int priority;
+	int ret = 0;
 	const int nr_pages = SWAP_CLUSTER_MAX;
 	int nr_reclaimed = 0;
+	struct reclaim_state *reclaim_state = current->reclaim_state;
 
 	inc_page_state(allocstall);
 
@@ -831,11 +833,12 @@
 		struct page_state ps;
 
 		get_page_state(&ps);
-		nr_reclaimed += shrink_caches(classzone, priority,
-					&total_scanned, gfp_mask,
-					nr_pages, &ps);
-		if (nr_reclaimed >= nr_pages)
-			return 1;
+		nr_reclaimed += shrink_caches(cz, priority, &total_scanned,
+						gfp_mask, nr_pages, &ps);
+		if (nr_reclaimed >= nr_pages) {
+			ret = 1;
+			goto out;
+		}
 		if (!(gfp_mask & __GFP_FS))
 			break;		/* Let the caller handle it */
 		/*
@@ -847,12 +850,18 @@
 
 		/* Take a nap, wait for some writeback to complete */
 		blk_congestion_wait(WRITE, HZ/10);
-		if (classzone - classzone->zone_pgdat->node_zones < ZONE_HIGHMEM)
+		if (cz - cz->zone_pgdat->node_zones < ZONE_HIGHMEM) {
 			shrink_slab(total_scanned, gfp_mask);
+			if (reclaim_state) {
+				nr_reclaimed += reclaim_state->reclaimed_slab;
+				reclaim_state->reclaimed_slab = 0;
+			}
+		}
 	}
 	if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY))
 		out_of_memory();
-	return 0;
+out:
+	return ret;
 }
 
 /*
@@ -878,6 +887,7 @@
 	int to_free = nr_pages;
 	int priority;
 	int i;
+	struct reclaim_state *reclaim_state = current->reclaim_state;
 
 	inc_page_state(pageoutrun);
 
@@ -908,8 +918,11 @@
 				max_scan = SWAP_CLUSTER_MAX;
 			to_free -= shrink_zone(zone, max_scan, GFP_KERNEL,
 					to_reclaim, &nr_mapped, ps, priority);
-			if (i < ZONE_HIGHMEM)
+			if (i < ZONE_HIGHMEM) {
+				reclaim_state->reclaimed_slab = 0;
 				shrink_slab(max_scan + nr_mapped, GFP_KERNEL);
+				to_free += reclaim_state->reclaimed_slab;
+			}
 			if (zone->all_unreclaimable)
 				continue;
 			if (zone->pages_scanned > zone->present_pages * 2)
@@ -940,10 +953,14 @@
 	pg_data_t *pgdat = (pg_data_t*)p;
 	struct task_struct *tsk = current;
 	DEFINE_WAIT(wait);
+	struct reclaim_state reclaim_state = {
+		.reclaimed_slab = 0,
+	};
 
 	daemonize("kswapd%d", pgdat->node_id);
 	set_cpus_allowed(tsk, node_to_cpumask(pgdat->node_id));
-	
+	current->reclaim_state = &reclaim_state;
+
 	/*
 	 * Tell the memory management that we're a "memory allocator",
 	 * and that if we need more memory we should get access to it
diff -urN linux-2.5.69-bk2/net/Kconfig linux-2.5.69-bk3/net/Kconfig
--- linux-2.5.69-bk2/net/Kconfig	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk3/net/Kconfig	2003-05-08 04:38:21.000000000 -0700
@@ -266,6 +266,23 @@
 	  subnetwork boundaries. These shortcut connections bypass routers
 	  enhancing overall network performance.
 
+config ATM_BR2684
+	tristate "RFC1483/2684 Bridged protocols"
+	depends on ATM && INET
+	help
+	  ATM PVCs can carry ethernet PDUs according to rfc2684 (formerly 1483)
+	  This device will act like an ethernet from the kernels point of view,
+	  with the traffic being carried by ATM PVCs (currently 1 PVC/device).
+	  This is sometimes used over DSL lines.  If in doubt, say N.
+
+config ATM_BR2684_IPFILTER
+	bool "Per-VC IP filter kludge"
+	depends on ATM_BR2684
+	help
+	  This is an experimental mechanism for users who need to terminating a
+	  large number of IP-only vcc's.  Do not enable this unless you are sure
+	  you know what you are doing.
+
 config VLAN_8021Q
 	tristate "802.1Q VLAN Support"
 
diff -urN linux-2.5.69-bk2/net/atm/Makefile linux-2.5.69-bk3/net/atm/Makefile
--- linux-2.5.69-bk2/net/atm/Makefile	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk3/net/atm/Makefile	2003-05-08 04:38:21.000000000 -0700
@@ -7,6 +7,7 @@
 obj-$(CONFIG_ATM) := addr.o pvc.o signaling.o svc.o common.o atm_misc.o raw.o resources.o
 
 obj-$(CONFIG_ATM_CLIP) += clip.o ipcommon.o
+obj-$(CONFIG_ATM_BR2684) += br2684.o ipcommon.o
 obj-$(CONFIG_NET_SCH_ATM) += ipcommon.o
 obj-$(CONFIG_PROC_FS) += proc.o
 
diff -urN linux-2.5.69-bk2/net/atm/br2684.c linux-2.5.69-bk3/net/atm/br2684.c
--- linux-2.5.69-bk2/net/atm/br2684.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk3/net/atm/br2684.c	2003-05-08 04:38:21.000000000 -0700
@@ -0,0 +1,803 @@
+/*
+Experimental ethernet netdevice using ATM AAL5 as underlying carrier
+(RFC1483 obsoleted by RFC2684) for Linux 2.4
+Author: Marcell GAL, 2000, XDSL Ltd, Hungary
+*/
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/ip.h>
+#include <asm/uaccess.h>
+#include <net/arp.h>
+
+#include <linux/atmbr2684.h>
+
+#include "ipcommon.h"
+
+/*
+ * Define this to use a version of the code which interacts with the higher
+ * layers in a more intellegent way, by always reserving enough space for
+ * our header at the begining of the packet.  However, there may still be
+ * some problems with programs like tcpdump.  In 2.5 we'll sort out what
+ * we need to do to get this perfect.  For now we just will copy the packet
+ * if we need space for the header
+ */
+/* #define FASTER_VERSION */
+
+#ifdef DEBUG
+#define DPRINTK(format, args...) printk(KERN_DEBUG "br2684: " format, ##args)
+#else
+#define DPRINTK(format, args...)
+#endif
+
+#ifdef SKB_DEBUG
+static void skb_debug(const struct sk_buff *skb)
+{
+#define NUM2PRINT 50
+	char buf[NUM2PRINT * 3 + 1];	/* 3 chars per byte */
+	int i = 0;
+	for (i = 0; i < skb->len && i < NUM2PRINT; i++) {
+		sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
+	}
+	printk(KERN_DEBUG "br2684: skb: %s\n", buf);
+}
+#else
+#define skb_debug(skb)	do {} while (0)
+#endif
+
+static unsigned char llc_oui_pid_pad[] =
+    { 0xAA, 0xAA, 0x03, 0x00, 0x80, 0xC2, 0x00, 0x07, 0x00, 0x00 };
+#define PADLEN	(2)
+
+enum br2684_encaps {
+	e_vc  = BR2684_ENCAPS_VC,
+	e_llc = BR2684_ENCAPS_LLC,
+};
+
+struct br2684_vcc {
+	struct atm_vcc  *atmvcc;
+	struct br2684_dev *brdev;
+	/* keep old push,pop functions for chaining */
+	void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb);
+	/* void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); */
+	enum br2684_encaps encaps;
+	struct list_head brvccs;
+#ifdef CONFIG_ATM_BR2684_IPFILTER
+	struct br2684_filter filter;
+#endif /* CONFIG_ATM_BR2684_IPFILTER */
+#ifndef FASTER_VERSION
+	unsigned copies_needed, copies_failed;
+#endif /* FASTER_VERSION */
+};
+
+struct br2684_dev {
+	struct net_device net_dev;
+	struct list_head br2684_devs;
+	int number;
+	struct list_head brvccs; /* one device <=> one vcc (before xmas) */
+	struct net_device_stats stats;
+	int mac_was_set;
+};
+
+/*
+ * This lock should be held for writing any time the list of devices or
+ * their attached vcc's could be altered.  It should be held for reading
+ * any time these are being queried.  Note that we sometimes need to
+ * do read-locking under interrupt context, so write locking must block
+ * the current CPU's interrupts
+ */
+static rwlock_t devs_lock = RW_LOCK_UNLOCKED;
+
+static LIST_HEAD(br2684_devs);
+
+static inline struct br2684_dev *BRPRIV(const struct net_device *net_dev)
+{
+	return (struct br2684_dev *) ((char *) (net_dev) -
+	    (unsigned long) (&((struct br2684_dev *) 0)->net_dev));
+}
+
+static inline struct br2684_dev *list_entry_brdev(const struct list_head *le)
+{
+	return list_entry(le, struct br2684_dev, br2684_devs);
+}
+
+static inline struct br2684_vcc *BR2684_VCC(const struct atm_vcc *atmvcc)
+{
+	return (struct br2684_vcc *) (atmvcc->user_back);
+}
+
+static inline struct br2684_vcc *list_entry_brvcc(const struct list_head *le)
+{
+	return list_entry(le, struct br2684_vcc, brvccs);
+}
+
+/* Caller should hold read_lock(&devs_lock) */
+static struct br2684_dev *br2684_find_dev(const struct br2684_if_spec *s)
+{
+	struct list_head *lh;
+	struct br2684_dev *brdev;
+	switch (s->method) {
+	case BR2684_FIND_BYNUM:
+		list_for_each(lh, &br2684_devs) {
+			brdev = list_entry_brdev(lh);
+			if (brdev->number == s->spec.devnum)
+				return brdev;
+		}
+		break;
+	case BR2684_FIND_BYIFNAME:
+		list_for_each(lh, &br2684_devs) {
+			brdev = list_entry_brdev(lh);
+			if (!strncmp(brdev->net_dev.name, s->spec.ifname,
+			    sizeof brdev->net_dev.name))
+				return brdev;
+		}
+		break;
+	}
+	return NULL;
+}
+
+/*
+ * Send a packet out a particular vcc.  Not to useful right now, but paves
+ * the way for multiple vcc's per itf.  Returns true if we can send,
+ * otherwise false
+ */
+static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
+	struct br2684_vcc *brvcc)
+{
+	struct atm_vcc *atmvcc;
+#ifdef FASTER_VERSION
+	if (brvcc->encaps == e_llc)
+		memcpy(skb_push(skb, 8), llc_oui_pid_pad, 8);
+	/* last 2 bytes of llc_oui_pid_pad are managed by header routines;
+	   yes, you got it: 8 + 2 = sizeof(llc_oui_pid_pad)
+	 */
+#else
+	int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2;
+	if (skb_headroom(skb) < minheadroom) {
+		struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom);
+		brvcc->copies_needed++;
+		dev_kfree_skb(skb);
+		if (skb2 == NULL) {
+			brvcc->copies_failed++;
+			return 0;
+		}
+		skb = skb2;
+	}
+	skb_push(skb, minheadroom);
+	if (brvcc->encaps == e_llc)
+		memcpy(skb->data, llc_oui_pid_pad, 10);
+	else
+		memset(skb->data, 0, 2);
+#endif /* FASTER_VERSION */
+	skb_debug(skb);
+
+	ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
+	DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev);
+	if (!atm_may_send(atmvcc, skb->truesize)) {
+		/* we free this here for now, because we cannot know in a higher 
+			layer whether the skb point it supplied wasn't freed yet.
+			now, it always is.
+		*/
+		dev_kfree_skb(skb);
+		return 0;
+		}
+	atomic_add(skb->truesize, &atmvcc->sk->wmem_alloc);
+	ATM_SKB(skb)->atm_options = atmvcc->atm_options;
+	brdev->stats.tx_packets++;
+	brdev->stats.tx_bytes += skb->len;
+	atmvcc->send(atmvcc, skb);
+	return 1;
+}
+
+static inline struct br2684_vcc *pick_outgoing_vcc(struct sk_buff *skb,
+	struct br2684_dev *brdev)
+{
+	return list_empty(&brdev->brvccs) ? NULL :
+	    list_entry_brvcc(brdev->brvccs.next); /* 1 vcc/dev right now */
+}
+
+static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct br2684_dev *brdev = BRPRIV(dev);
+	struct br2684_vcc *brvcc;
+
+	DPRINTK("br2684_start_xmit, skb->dst=%p\n", skb->dst);
+	read_lock(&devs_lock);
+	brvcc = pick_outgoing_vcc(skb, brdev);
+	if (brvcc == NULL) {
+		DPRINTK("no vcc attached to dev %s\n", dev->name);
+		brdev->stats.tx_errors++;
+		brdev->stats.tx_carrier_errors++;
+		/* netif_stop_queue(dev); */
+		dev_kfree_skb(skb);
+		read_unlock(&devs_lock);
+		return -EUNATCH;
+	}
+	if (!br2684_xmit_vcc(skb, brdev, brvcc)) {
+		/*
+		 * We should probably use netif_*_queue() here, but that
+		 * involves added complication.  We need to walk before
+		 * we can run
+		 */
+		/* don't free here! this pointer might be no longer valid!
+		dev_kfree_skb(skb);
+		*/
+		brdev->stats.tx_errors++;
+		brdev->stats.tx_fifo_errors++;
+	}
+	read_unlock(&devs_lock);
+	return 0;
+}
+
+static struct net_device_stats *br2684_get_stats(struct net_device *dev)
+{
+	DPRINTK("br2684_get_stats\n");
+	return &BRPRIV(dev)->stats;
+}
+
+#ifdef FASTER_VERSION
+/*
+ * These mirror eth_header and eth_header_cache.  They are not usually
+ * exported for use in modules, so we grab them from net_device
+ * after ether_setup() is done with it.  Bit of a hack.
+ */
+static int (*my_eth_header)(struct sk_buff *, struct net_device *,
+	unsigned short, void *, void *, unsigned);
+static int (*my_eth_header_cache)(struct neighbour *, struct hh_cache *);
+
+static int
+br2684_header(struct sk_buff *skb, struct net_device *dev,
+	      unsigned short type, void *daddr, void *saddr, unsigned len)
+{
+	u16 *pad_before_eth;
+	int t = my_eth_header(skb, dev, type, daddr, saddr, len);
+	if (t > 0) {
+		pad_before_eth = (u16 *) skb_push(skb, 2);
+		*pad_before_eth = 0;
+		return dev->hard_header_len;	/* or return 16; ? */
+	} else
+		return t;
+}
+
+static int
+br2684_header_cache(struct neighbour *neigh, struct hh_cache *hh)
+{
+/* hh_data is 16 bytes long. if encaps is ether-llc we need 24, so
+xmit will add the additional header part in that case */
+	u16 *pad_before_eth = (u16 *)(hh->hh_data);
+	int t = my_eth_header_cache(neigh, hh);
+	DPRINTK("br2684_header_cache, neigh=%p, hh_cache=%p\n", neigh, hh);
+	if (t < 0)
+		return t;
+	else {
+		*pad_before_eth = 0;
+		hh->hh_len = PADLEN + ETH_HLEN;
+	}
+	return 0;
+}
+
+/*
+ * This is similar to eth_type_trans, which cannot be used because of
+ * our dev->hard_header_len
+ */
+static inline unsigned short br_type_trans(struct sk_buff *skb,
+					       struct net_device *dev)
+{
+	struct ethhdr *eth;
+	unsigned char *rawp;
+	eth = skb->mac.ethernet;
+
+	if (*eth->h_dest & 1) {
+		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
+			skb->pkt_type = PACKET_BROADCAST;
+		else
+			skb->pkt_type = PACKET_MULTICAST;
+	}
+
+	else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
+		skb->pkt_type = PACKET_OTHERHOST;
+
+	if (ntohs(eth->h_proto) >= 1536)
+		return eth->h_proto;
+
+	rawp = skb->data;
+
+	/*
+	 * This is a magic hack to spot IPX packets. Older Novell breaks
+	 * the protocol design and runs IPX over 802.3 without an 802.2 LLC
+	 * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
+	 * won't work for fault tolerant netware but does for the rest.
+	 */
+	if (*(unsigned short *) rawp == 0xFFFF)
+		return htons(ETH_P_802_3);
+
+	/*
+	 * Real 802.2 LLC
+	 */
+	return htons(ETH_P_802_2);
+}
+#endif /* FASTER_VERSION */
+
+/*
+ * We remember when the MAC gets set, so we don't override it later with
+ * the ESI of the ATM card of the first VC
+ */
+static int (*my_eth_mac_addr)(struct net_device *, void *);
+static int br2684_mac_addr(struct net_device *dev, void *p)
+{
+	int err = my_eth_mac_addr(dev, p);
+	if (!err)
+		BRPRIV(dev)->mac_was_set = 1;
+	return err;
+}
+
+#ifdef CONFIG_ATM_BR2684_IPFILTER
+/* this IOCTL is experimental. */
+static int br2684_setfilt(struct atm_vcc *atmvcc, unsigned long arg)
+{
+	struct br2684_vcc *brvcc;
+	struct br2684_filter_set fs;
+
+	if (copy_from_user(&fs, (void *) arg, sizeof fs))
+		return -EFAULT;
+	if (fs.ifspec.method != BR2684_FIND_BYNOTHING) {
+		/*
+		 * This is really a per-vcc thing, but we can also search
+		 * by device
+		 */
+		struct br2684_dev *brdev;
+		read_lock(&devs_lock);
+		brdev = br2684_find_dev(&fs.ifspec);
+		if (brdev == NULL || list_empty(&brdev->brvccs) ||
+		    brdev->brvccs.next != brdev->brvccs.prev)  /* >1 VCC */
+			brvcc = NULL;
+		else
+			brvcc = list_entry_brvcc(brdev->brvccs.next);
+		read_unlock(&devs_lock);
+		if (brvcc == NULL)
+			return -ESRCH;
+	} else
+		brvcc = BR2684_VCC(atmvcc);
+	memcpy(&brvcc->filter, &fs.filter, sizeof(brvcc->filter));
+	return 0;
+}
+
+/* Returns 1 if packet should be dropped */
+static inline int
+packet_fails_filter(u16 type, struct br2684_vcc *brvcc, struct sk_buff *skb)
+{
+	if (brvcc->filter.netmask == 0)
+		return 0;			/* no filter in place */
+	if (type == __constant_htons(ETH_P_IP) &&
+	    (((struct iphdr *) (skb->data))->daddr & brvcc->filter.
+	     netmask) == brvcc->filter.prefix)
+		return 0;
+	if (type == __constant_htons(ETH_P_ARP))
+		return 0;
+	/* TODO: we should probably filter ARPs too.. don't want to have
+	 *   them returning values that don't make sense, or is that ok?
+	 */
+	return 1;		/* drop */
+}
+#endif /* CONFIG_ATM_BR2684_IPFILTER */
+
+static void br2684_close_vcc(struct br2684_vcc *brvcc)
+{
+	DPRINTK("removing VCC %p from dev %p\n", brvcc, brvcc->brdev);
+	write_lock_irq(&devs_lock);
+	list_del(&brvcc->brvccs);
+	write_unlock_irq(&devs_lock);
+	brvcc->atmvcc->user_back = NULL;	/* what about vcc->recvq ??? */
+	brvcc->old_push(brvcc->atmvcc, NULL);	/* pass on the bad news */
+	kfree(brvcc);
+	MOD_DEC_USE_COUNT;
+}
+
+/* when AAL5 PDU comes in: */
+static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
+{
+	struct br2684_vcc *brvcc = BR2684_VCC(atmvcc);
+	struct br2684_dev *brdev = brvcc->brdev;
+	int plen = sizeof(llc_oui_pid_pad) + ETH_HLEN;
+
+	DPRINTK("br2684_push\n");
+
+	if (skb == NULL) {	/* skb==NULL means VCC is being destroyed */
+		br2684_close_vcc(brvcc);
+		if (list_empty(&brdev->brvccs)) {
+			read_lock(&devs_lock);
+			list_del(&brdev->br2684_devs);
+			read_unlock(&devs_lock);
+			unregister_netdev(&brdev->net_dev);
+			kfree(brdev);
+		}
+		return;
+	}
+
+	skb_debug(skb);
+	atm_return(atmvcc, skb->truesize);
+	DPRINTK("skb from brdev %p\n", brdev);
+	if (brvcc->encaps == e_llc) {
+		/* let us waste some time for checking the encapsulation.
+		   Note, that only 7 char is checked so frames with a valid FCS
+		   are also accepted (but FCS is not checked of course) */
+		if (memcmp(skb->data, llc_oui_pid_pad, 7)) {
+			brdev->stats.rx_errors++;
+			dev_kfree_skb(skb);
+			return;
+		}
+	} else {
+		plen = PADLEN + ETH_HLEN;	/* pad, dstmac,srcmac, ethtype */
+		/* first 2 chars should be 0 */
+		if (*((u16 *) (skb->data)) != 0) {
+			brdev->stats.rx_errors++;
+			dev_kfree_skb(skb);
+			return;
+		}
+	}
+	if (skb->len < plen) {
+		brdev->stats.rx_errors++;
+		dev_kfree_skb(skb);	/* dev_ not needed? */
+		return;
+	}
+
+#ifdef FASTER_VERSION
+	/* FIXME: tcpdump shows that pointer to mac header is 2 bytes earlier,
+	   than should be. What else should I set? */
+	skb_pull(skb, plen);
+	skb->mac.raw = ((char *) (skb->data)) - ETH_HLEN;
+	skb->pkt_type = PACKET_HOST;
+#ifdef CONFIG_BR2684_FAST_TRANS
+	skb->protocol = ((u16 *) skb->data)[-1];
+#else				/* some protocols might require this: */
+	skb->protocol = br_type_trans(skb, &brdev->net_dev);
+#endif /* CONFIG_BR2684_FAST_TRANS */
+#else
+	skb_pull(skb, plen - ETH_HLEN);
+	skb->protocol = eth_type_trans(skb, &brdev->net_dev);
+#endif /* FASTER_VERSION */
+#ifdef CONFIG_ATM_BR2684_IPFILTER
+	if (packet_fails_filter(skb->protocol, brvcc, skb)) {
+		brdev->stats.rx_dropped++;
+		dev_kfree_skb(skb);
+		return;
+	}
+#endif /* CONFIG_ATM_BR2684_IPFILTER */
+	skb->dev = &brdev->net_dev;
+	ATM_SKB(skb)->vcc = atmvcc;	/* needed ? */
+	DPRINTK("received packet's protocol: %x\n", ntohs(skb->protocol));
+	skb_debug(skb);
+	if (!(brdev->net_dev.flags & IFF_UP)) { /* sigh, interface is down */
+		brdev->stats.rx_dropped++;
+		dev_kfree_skb(skb);
+		return;
+	}
+	brdev->stats.rx_packets++;
+	brdev->stats.rx_bytes += skb->len;
+	netif_rx(skb);
+}
+
+static int br2684_regvcc(struct atm_vcc *atmvcc, unsigned long arg)
+{
+/* assign a vcc to a dev
+Note: we do not have explicit unassign, but look at _push()
+*/
+	int err;
+	struct br2684_vcc *brvcc;
+	struct sk_buff_head copy;
+	struct sk_buff *skb;
+	struct br2684_dev *brdev;
+	struct atm_backend_br2684 be;
+
+	MOD_INC_USE_COUNT;
+	if (copy_from_user(&be, (void *) arg, sizeof be)) {
+		MOD_DEC_USE_COUNT;
+		return -EFAULT;
+	}
+	write_lock_irq(&devs_lock);
+	brdev = br2684_find_dev(&be.ifspec);
+	if (brdev == NULL) {
+		printk(KERN_ERR
+		    "br2684: tried to attach to non-existant device\n");
+		err = -ENXIO;
+		goto error;
+	}
+	if (atmvcc->push == NULL) {
+		err = -EBADFD;
+		goto error;
+	}
+	if (!list_empty(&brdev->brvccs)) {	/* Only 1 VCC/dev right now */
+		err = -EEXIST;
+		goto error;
+	}
+	if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO ||
+	    be.fcs_auto || be.has_vpiid || be.send_padding || (be.encaps !=
+	    BR2684_ENCAPS_VC && be.encaps != BR2684_ENCAPS_LLC) ||
+	    be.min_size != 0) {
+		err = -EINVAL;
+		goto error;
+	}
+	brvcc = kmalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
+	if (!brvcc) {
+		err = -ENOMEM;
+		goto error;
+	}
+	memset(brvcc, 0, sizeof(struct br2684_vcc));
+	DPRINTK("br2684_regvcc vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps,
+		brvcc);
+	if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) {
+		unsigned char *esi = atmvcc->dev->esi;
+		if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5])
+			memcpy(brdev->net_dev.dev_addr, esi,
+			    brdev->net_dev.addr_len);
+		else
+			brdev->net_dev.dev_addr[2] = 1;
+	}
+	list_add(&brvcc->brvccs, &brdev->brvccs);
+	write_unlock_irq(&devs_lock);
+	brvcc->brdev = brdev;
+	brvcc->atmvcc = atmvcc;
+	atmvcc->user_back = brvcc;
+	brvcc->encaps = (enum br2684_encaps) be.encaps;
+	brvcc->old_push = atmvcc->push;
+	barrier();
+	atmvcc->push = br2684_push;
+	skb_queue_head_init(&copy);
+	skb_migrate(&atmvcc->sk->receive_queue, &copy);
+	while ((skb = skb_dequeue(&copy))) {
+		BRPRIV(skb->dev)->stats.rx_bytes -= skb->len;
+		BRPRIV(skb->dev)->stats.rx_packets--;
+		br2684_push(atmvcc, skb);
+	}
+	return 0;
+    error:
+	write_unlock_irq(&devs_lock);
+	MOD_DEC_USE_COUNT;
+	return err;
+}
+
+static int br2684_create(unsigned long arg)
+{
+	int err;
+	struct br2684_dev *brdev;
+	struct atm_newif_br2684 ni;
+
+	DPRINTK("br2684_create\n");
+	/*
+	 * We track module use by vcc's NOT the devices they're on.  We're
+	 * protected here against module death by the kernel_lock, but if
+	 * we need to sleep we should make sure that the module doesn't
+	 * disappear under us.
+	 */
+	MOD_INC_USE_COUNT;
+	if (copy_from_user(&ni, (void *) arg, sizeof ni)) {
+		MOD_DEC_USE_COUNT;
+		return -EFAULT;
+	}
+	if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) {
+		MOD_DEC_USE_COUNT;
+		return -EINVAL;
+	}
+	if ((brdev = kmalloc(sizeof(struct br2684_dev), GFP_KERNEL)) == NULL) {
+		MOD_DEC_USE_COUNT;
+		return -ENOMEM;
+	}
+	memset(brdev, 0, sizeof(struct br2684_dev));
+	INIT_LIST_HEAD(&brdev->brvccs);
+
+	write_lock_irq(&devs_lock);
+	brdev->number = list_empty(&br2684_devs) ? 1 :
+	    list_entry_brdev(br2684_devs.prev)->number + 1;
+	list_add_tail(&brdev->br2684_devs, &br2684_devs);
+	write_unlock_irq(&devs_lock);
+
+	if (ni.ifname[0] != '\0') {
+		memcpy(brdev->net_dev.name, ni.ifname,
+		    sizeof(brdev->net_dev.name));
+		brdev->net_dev.name[sizeof(brdev->net_dev.name) - 1] = '\0';
+	} else
+		sprintf(brdev->net_dev.name, "nas%d", brdev->number);
+	DPRINTK("registered netdev %s\n", brdev->net_dev.name);
+	ether_setup(&brdev->net_dev);
+	brdev->mac_was_set = 0;
+#ifdef FASTER_VERSION
+	my_eth_header = brdev->net_dev.hard_header;
+	brdev->net_dev.hard_header = br2684_header;
+	my_eth_header_cache = brdev->net_dev.hard_header_cache;
+	brdev->net_dev.hard_header_cache = br2684_header_cache;
+	brdev->net_dev.hard_header_len = sizeof(llc_oui_pid_pad) + ETH_HLEN;	/* 10 + 14 */
+#endif
+	my_eth_mac_addr = brdev->net_dev.set_mac_address;
+	brdev->net_dev.set_mac_address = br2684_mac_addr;
+	brdev->net_dev.hard_start_xmit = br2684_start_xmit;
+	brdev->net_dev.get_stats = br2684_get_stats;
+
+	/* open, stop, do_ioctl ? */
+	err = register_netdev(&brdev->net_dev);
+	MOD_DEC_USE_COUNT;
+	if (err < 0) {
+		printk(KERN_ERR "br2684_create: register_netdev failed\n");
+		write_lock_irq(&devs_lock);
+		list_del(&brdev->br2684_devs);
+		write_unlock_irq(&devs_lock);
+		kfree(brdev);
+		return err;
+	}
+	return 0;
+}
+
+/*
+ * This handles ioctls actually performed on our vcc - we must return
+ * -ENOIOCTLCMD for any unrecognized ioctl
+ */
+static int br2684_ioctl(struct atm_vcc *atmvcc, unsigned int cmd,
+	unsigned long arg)
+{
+	int err;
+	switch(cmd) {
+	case ATM_SETBACKEND:
+	case ATM_NEWBACKENDIF: {
+		atm_backend_t b;
+		MOD_INC_USE_COUNT;
+		err = get_user(b, (atm_backend_t *) arg);
+		MOD_DEC_USE_COUNT;
+		if (err)
+			return -EFAULT;
+		if (b != ATM_BACKEND_BR2684)
+			return -ENOIOCTLCMD;
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (cmd == ATM_SETBACKEND)
+			return br2684_regvcc(atmvcc, arg);
+		else
+			return br2684_create(arg);
+		}
+#ifdef CONFIG_ATM_BR2684_IPFILTER
+	case BR2684_SETFILT:
+		if (atmvcc->push != br2684_push)
+			return -ENOIOCTLCMD;
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		MOD_INC_USE_COUNT;
+		err = br2684_setfilt(atmvcc, arg);
+		MOD_DEC_USE_COUNT;
+		return err;
+#endif /* CONFIG_ATM_BR2684_IPFILTER */
+	}
+	return -ENOIOCTLCMD;
+}
+
+/* Never put more than 256 bytes in at once */
+static int br2684_proc_engine(loff_t pos, char *buf)
+{
+	struct list_head *lhd, *lhc;
+	struct br2684_dev *brdev;
+	struct br2684_vcc *brvcc;
+	list_for_each(lhd, &br2684_devs) {
+		brdev = list_entry_brdev(lhd);
+		if (pos-- == 0)
+			return sprintf(buf, "dev %.16s: num=%d, mac=%02X:%02X:"
+			    "%02X:%02X:%02X:%02X (%s)\n", brdev->net_dev.name,
+			    brdev->number,
+			    brdev->net_dev.dev_addr[0],
+			    brdev->net_dev.dev_addr[1],
+			    brdev->net_dev.dev_addr[2],
+			    brdev->net_dev.dev_addr[3],
+			    brdev->net_dev.dev_addr[4],
+			    brdev->net_dev.dev_addr[5],
+			    brdev->mac_was_set ? "set" : "auto");
+		list_for_each(lhc, &brdev->brvccs) {
+			brvcc = list_entry_brvcc(lhc);
+			if (pos-- == 0)
+				return sprintf(buf, "  vcc %d.%d.%d: encaps=%s"
+#ifndef FASTER_VERSION
+				    ", failed copies %u/%u"
+#endif /* FASTER_VERSION */
+				    "\n", brvcc->atmvcc->dev->number,
+				    brvcc->atmvcc->vpi, brvcc->atmvcc->vci,
+				    (brvcc->encaps == e_llc) ? "LLC" : "VC"
+#ifndef FASTER_VERSION
+				    , brvcc->copies_failed
+				    , brvcc->copies_needed
+#endif /* FASTER_VERSION */
+				    );
+#ifdef CONFIG_ATM_BR2684_IPFILTER
+#define b1(var, byte)	((u8 *) &brvcc->filter.var)[byte]
+#define bs(var)		b1(var, 0), b1(var, 1), b1(var, 2), b1(var, 3)
+			if (brvcc->filter.netmask != 0 && pos-- == 0)
+				return sprintf(buf, "    filter=%d.%d.%d.%d/"
+				    "%d.%d.%d.%d\n", bs(prefix), bs(netmask));
+#undef bs
+#undef b1
+#endif /* CONFIG_ATM_BR2684_IPFILTER */
+		}
+	}
+	return 0;
+}
+
+static ssize_t br2684_proc_read(struct file *file, char *buf, size_t count,
+	loff_t *pos)
+{
+	unsigned long page;
+	int len = 0, x, left;
+	page = get_zeroed_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+	left = PAGE_SIZE - 256;
+	if (count < left)
+		left = count;
+	read_lock(&devs_lock);
+	for (;;) {
+		x = br2684_proc_engine(*pos, &((char *) page)[len]);
+		if (x == 0)
+			break;
+		if (x > left)
+			/*
+			 * This should only happen if the user passed in
+			 * a "count" too small for even one line
+			 */
+			x = -EINVAL;
+		if (x < 0) {
+			len = x;
+			break;
+		}
+		len += x;
+		left -= x;
+		(*pos)++;
+		if (left < 256)
+			break;
+	}
+	read_unlock(&devs_lock);
+	if (len > 0 && copy_to_user(buf, (char *) page, len))
+		len = -EFAULT;
+	free_page(page);
+	return len;
+}
+
+static struct file_operations br2684_proc_operations = {
+	read: br2684_proc_read,
+};
+
+extern struct proc_dir_entry *atm_proc_root;	/* from proc.c */
+
+extern int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
+
+/* the following avoids some spurious warnings from the compiler */
+#define UNUSED __attribute__((unused))
+
+static int __init UNUSED br2684_init(void)
+{
+	struct proc_dir_entry *p;
+	if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL)
+		return -ENOMEM;
+	p->proc_fops = &br2684_proc_operations;
+	br2684_ioctl_hook = br2684_ioctl;
+	return 0;
+}
+
+static void __exit UNUSED br2684_exit(void)
+{
+	struct br2684_dev *brdev;
+	br2684_ioctl_hook = NULL;
+	remove_proc_entry("br2684", atm_proc_root);
+	while (!list_empty(&br2684_devs)) {
+		brdev = list_entry_brdev(br2684_devs.next);
+		unregister_netdev(&brdev->net_dev);
+		list_del(&brdev->br2684_devs);
+		kfree(brdev);
+	}
+}
+
+module_init(br2684_init);
+module_exit(br2684_exit);
+
+MODULE_AUTHOR("Marcell GAL");
+MODULE_DESCRIPTION("RFC2684 bridged protocols over ATM/AAL5");
+MODULE_LICENSE("GPL");
diff -urN linux-2.5.69-bk2/net/atm/clip.c linux-2.5.69-bk3/net/atm/clip.c
--- linux-2.5.69-bk2/net/atm/clip.c	2003-05-04 16:53:55.000000000 -0700
+++ linux-2.5.69-bk3/net/atm/clip.c	2003-05-08 04:38:21.000000000 -0700
@@ -127,6 +127,8 @@
 			struct atmarp_entry *entry = NEIGH2ENTRY(n);
 			struct clip_vcc *clip_vcc;
 
+			write_lock(&n->lock);
+
 			for (clip_vcc = entry->vccs; clip_vcc;
 			    clip_vcc = clip_vcc->next)
 				if (clip_vcc->idle_timeout &&
@@ -141,6 +143,7 @@
 			if (entry->vccs ||
 			    time_before(jiffies, entry->expires)) {
 				np = &n->next;
+				write_unlock(&n->lock);
 				continue;
 			}
 			if (atomic_read(&n->refcnt) > 1) {
@@ -152,11 +155,13 @@
 				     NULL) 
 					dev_kfree_skb(skb);
 				np = &n->next;
+				write_unlock(&n->lock);
 				continue;
 			}
 			*np = n->next;
 			DPRINTK("expired neigh %p\n",n);
 			n->dead = 1;
+			write_unlock(&n->lock);
 			neigh_release(n);
 		}
 	}
diff -urN linux-2.5.69-bk2/net/atm/common.c linux-2.5.69-bk3/net/atm/common.c
--- linux-2.5.69-bk2/net/atm/common.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk3/net/atm/common.c	2003-05-08 04:38:21.000000000 -0700
@@ -62,6 +62,13 @@
 EXPORT_SYMBOL(pppoatm_ioctl_hook);
 #endif
 
+#if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE)
+int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
+#ifdef CONFIG_ATM_BR2684_MODULE
+EXPORT_SYMBOL(br2684_ioctl_hook);
+#endif
+#endif
+
 #include "resources.h"		/* atm_find_dev */
 #include "common.h"		/* prototypes */
 #include "protocols.h"		/* atm_init_<transport> */
@@ -120,7 +127,6 @@
 	vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
 	vcc->atm_options = vcc->aal_options = 0;
 	init_waitqueue_head(&vcc->sleep);
-	skb_queue_head_init(&vcc->listenq);
 	sk->sleep = &vcc->sleep;
 	sock->sk = sk;
 	return 0;
@@ -489,7 +495,7 @@
 	vcc = ATM_SD(sock);
 	poll_wait(file,&vcc->sleep,wait);
 	mask = 0;
-	if (skb_peek(&vcc->sk->receive_queue) || skb_peek(&vcc->listenq))
+	if (skb_peek(&vcc->sk->receive_queue))
 		mask |= POLLIN | POLLRDNORM;
 	if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
 	    test_bit(ATM_VF_CLOSE,&vcc->flags))
@@ -785,6 +791,13 @@
 			goto done;
 	}
 #endif
+#if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE)
+	if (br2684_ioctl_hook) {
+		ret_val = br2684_ioctl_hook(vcc, cmd, arg);
+		if (ret_val != -ENOIOCTLCMD)
+			goto done;
+	}
+#endif
 	if (get_user(buf,&((struct atmif_sioc *) arg)->arg)) {
 		ret_val = -EFAULT;
 		goto done;
diff -urN linux-2.5.69-bk2/net/atm/lec.c linux-2.5.69-bk3/net/atm/lec.c
--- linux-2.5.69-bk2/net/atm/lec.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/net/atm/lec.c	2003-05-08 04:38:21.000000000 -0700
@@ -302,7 +302,7 @@
 #endif
         min_frame_size = LEC_MINIMUM_8023_SIZE;
         if (skb->len < min_frame_size) {
-                if (skb->truesize < min_frame_size) {
+                if ((skb->len + skb_tailroom(skb)) < min_frame_size) {
                         skb2 = skb_copy_expand(skb, 0,
                             min_frame_size - skb->truesize, GFP_ATOMIC);
                                 dev_kfree_skb(skb);
diff -urN linux-2.5.69-bk2/net/atm/signaling.c linux-2.5.69-bk3/net/atm/signaling.c
--- linux-2.5.69-bk2/net/atm/signaling.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/net/atm/signaling.c	2003-05-08 04:38:21.000000000 -0700
@@ -129,12 +129,12 @@
 		case as_indicate:
 			vcc = *(struct atm_vcc **) &msg->listen_vcc;
 			DPRINTK("as_indicate!!!\n");
-			if (!vcc->backlog_quota) {
+			if (vcc->sk->ack_backlog == vcc->sk->max_ack_backlog) {
 				sigd_enq(0,as_reject,vcc,NULL,NULL);
 				return 0;
 			}
-			vcc->backlog_quota--;
-			skb_queue_tail(&vcc->listenq,skb);
+			vcc->sk->ack_backlog++;
+			skb_queue_tail(&vcc->sk->receive_queue,skb);
 			if (vcc->callback) {
 				DPRINTK("waking vcc->sleep 0x%p\n",
 				    &vcc->sleep);
diff -urN linux-2.5.69-bk2/net/atm/svc.c linux-2.5.69-bk3/net/atm/svc.c
--- linux-2.5.69-bk2/net/atm/svc.c	2003-05-08 04:38:12.000000000 -0700
+++ linux-2.5.69-bk3/net/atm/svc.c	2003-05-08 04:38:21.000000000 -0700
@@ -74,7 +74,7 @@
 	}
 	/* beware - socket is still in use by atmsigd until the last
 	   as_indicate has been answered */
-	while ((skb = skb_dequeue(&vcc->listenq))) {
+	while ((skb = skb_dequeue(&vcc->sk->receive_queue))) {
 		DPRINTK("LISTEN REL\n");
 		sigd_enq2(NULL,as_reject,vcc,NULL,NULL,&vcc->qos,0);
 		dev_kfree_skb(skb);
@@ -253,7 +253,7 @@
 	remove_wait_queue(&vcc->sleep,&wait);
 	if (!sigd) return -EUNATCH;
 	set_bit(ATM_VF_LISTEN,&vcc->flags);
-	vcc->backlog_quota = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
+	vcc->sk->max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
 	return vcc->reply;
 }
 
@@ -277,7 +277,7 @@
 		DECLARE_WAITQUEUE(wait,current);
 
 		add_wait_queue(&old_vcc->sleep,&wait);
-		while (!(skb = skb_dequeue(&old_vcc->listenq)) && sigd) {
+		while (!(skb = skb_dequeue(&old_vcc->sk->receive_queue)) && sigd) {
 			if (test_bit(ATM_VF_RELEASED,&old_vcc->flags)) break;
 			if (test_bit(ATM_VF_CLOSE,&old_vcc->flags)) {
 				error = old_vcc->reply;
@@ -306,7 +306,7 @@
 		error = atm_connect(newsock,msg->pvc.sap_addr.itf,
 		    msg->pvc.sap_addr.vpi,msg->pvc.sap_addr.vci);
 		dev_kfree_skb(skb);
-		old_vcc->backlog_quota++;
+		old_vcc->sk->ack_backlog--;
 		if (error) {
 			sigd_enq2(NULL,as_reject,old_vcc,NULL,NULL,
 			    &old_vcc->qos,error);
diff -urN linux-2.5.69-bk2/net/bridge/br_input.c linux-2.5.69-bk3/net/bridge/br_input.c
--- linux-2.5.69-bk2/net/bridge/br_input.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk3/net/bridge/br_input.c	2003-05-08 04:38:21.000000000 -0700
@@ -143,6 +143,9 @@
 			return -1;
 		}
 
+		if (!memcmp(p->br->dev.dev_addr, dest, ETH_ALEN))
+			skb->pkt_type = PACKET_HOST;
+
 		NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
 			br_handle_frame_finish);
 		rcu_read_unlock();
diff -urN linux-2.5.69-bk2/net/core/skbuff.c linux-2.5.69-bk3/net/core/skbuff.c
--- linux-2.5.69-bk2/net/core/skbuff.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/net/core/skbuff.c	2003-05-08 04:38:21.000000000 -0700
@@ -126,9 +126,6 @@
 	struct sk_buff *skb;
 	u8 *data;
 
-	if (gfp_mask & __GFP_WAIT)
-		might_sleep();
-
 	/* Get the HEAD */
 	skb = kmem_cache_alloc(skbuff_head_cache,
 			       gfp_mask & ~__GFP_DMA);
diff -urN linux-2.5.69-bk2/net/ipv4/af_inet.c linux-2.5.69-bk3/net/ipv4/af_inet.c
--- linux-2.5.69-bk2/net/ipv4/af_inet.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk3/net/ipv4/af_inet.c	2003-05-08 04:38:21.000000000 -0700
@@ -926,6 +926,7 @@
 struct net_proto_family inet_family_ops = {
 	.family = PF_INET,
 	.create = inet_create,
+	.owner	= THIS_MODULE,
 };
 
 
diff -urN linux-2.5.69-bk2/net/ipv4/fib_frontend.c linux-2.5.69-bk3/net/ipv4/fib_frontend.c
--- linux-2.5.69-bk2/net/ipv4/fib_frontend.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk3/net/ipv4/fib_frontend.c	2003-05-08 04:38:21.000000000 -0700
@@ -115,9 +115,9 @@
 	if (res.type != RTN_LOCAL)
 		goto out;
 	dev = FIB_RES_DEV(res);
-	if (dev)
-		atomic_inc(&dev->refcnt);
 
+	if (dev)
+		dev_hold(dev);
 out:
 	fib_res_put(&res);
 	return dev;
diff -urN linux-2.5.69-bk2/net/ipv4/fib_semantics.c linux-2.5.69-bk3/net/ipv4/fib_semantics.c
--- linux-2.5.69-bk2/net/ipv4/fib_semantics.c	2003-05-04 16:53:03.000000000 -0700
+++ linux-2.5.69-bk3/net/ipv4/fib_semantics.c	2003-05-08 04:38:21.000000000 -0700
@@ -406,7 +406,7 @@
 			if (!(dev->flags&IFF_UP))
 				return -ENETDOWN;
 			nh->nh_dev = dev;
-			atomic_inc(&dev->refcnt);
+			dev_hold(dev);
 			nh->nh_scope = RT_SCOPE_LINK;
 			return 0;
 		}
@@ -429,7 +429,7 @@
 		nh->nh_oif = FIB_RES_OIF(res);
 		if ((nh->nh_dev = FIB_RES_DEV(res)) == NULL)
 			goto out;
-		atomic_inc(&nh->nh_dev->refcnt);
+		dev_hold(nh->nh_dev);
 		err = -ENETDOWN;
 		if (!(nh->nh_dev->flags & IFF_UP))
 			goto out;
@@ -451,7 +451,7 @@
 			return -ENETDOWN;
 		}
 		nh->nh_dev = in_dev->dev;
-		atomic_inc(&nh->nh_dev->refcnt);
+		dev_hold(nh->nh_dev);
 		nh->nh_scope = RT_SCOPE_HOST;
 		in_dev_put(in_dev);
 	}
diff -urN linux-2.5.69-bk2/net/ipv4/tcp_minisocks.c linux-2.5.69-bk3/net/ipv4/tcp_minisocks.c
--- linux-2.5.69-bk2/net/ipv4/tcp_minisocks.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk3/net/ipv4/tcp_minisocks.c	2003-05-08 04:38:22.000000000 -0700
@@ -444,6 +444,8 @@
 
 	while((tw = tcp_tw_death_row[tcp_tw_death_row_slot]) != NULL) {
 		tcp_tw_death_row[tcp_tw_death_row_slot] = tw->next_death;
+		if (tw->next_death)
+			tw->next_death->pprev_death = tw->pprev_death;
 		tw->pprev_death = NULL;
 		spin_unlock(&tw_death_lock);
 
diff -urN linux-2.5.69-bk2/net/ipv6/af_inet6.c linux-2.5.69-bk3/net/ipv6/af_inet6.c
--- linux-2.5.69-bk2/net/ipv6/af_inet6.c	2003-05-08 04:38:13.000000000 -0700
+++ linux-2.5.69-bk3/net/ipv6/af_inet6.c	2003-05-08 04:38:22.000000000 -0700
@@ -535,6 +535,7 @@
 struct net_proto_family inet6_family_ops = {
 	.family = PF_INET6,
 	.create = inet6_create,
+	.owner	= THIS_MODULE,
 };
 
 #ifdef MODULE
diff -urN linux-2.5.69-bk2/net/ipv6/ip6_fib.c linux-2.5.69-bk3/net/ipv6/ip6_fib.c
--- linux-2.5.69-bk2/net/ipv6/ip6_fib.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk3/net/ipv6/ip6_fib.c	2003-05-08 04:38:22.000000000 -0700
@@ -593,7 +593,7 @@
 
 #ifdef CONFIG_IPV6_SUBTREES
 	/* Subtree creation failed, probably main tree node
-	   is orphan. If it is, shot it.
+	   is orphan. If it is, shoot it.
 	 */
 st_failure:
 	if (fn && !(fn->fn_flags&RTN_RTINFO|RTN_ROOT))
@@ -953,7 +953,7 @@
 
 #if RT6_DEBUG >= 2
 	if (rt->u.dst.obsolete>0) {
-		BUG_TRAP(fn==NULL || rt->u.dst.obsolete<=0);
+		BUG_TRAP(fn==NULL);
 		return -ENOENT;
 	}
 #endif
@@ -979,7 +979,7 @@
 }
 
 /*
- *	Tree transversal function.
+ *	Tree traversal function.
  *
  *	Certainly, it is not interrupt safe.
  *	However, it is internally reenterable wrt itself and fib6_add/fib6_del.
@@ -1179,14 +1179,14 @@
 	 */
 
 	if (rt->rt6i_flags&RTF_EXPIRES && rt->rt6i_expires) {
-		if ((long)(now - rt->rt6i_expires) > 0) {
+		if (time_after(now, rt->rt6i_expires)) {
 			RT6_TRACE("expiring %p\n", rt);
 			return -1;
 		}
 		gc_args.more++;
 	} else if (rt->rt6i_flags & RTF_CACHE) {
 		if (atomic_read(&rt->u.dst.__refcnt) == 0 &&
-		    (long)(now - rt->u.dst.lastuse) >= gc_args.timeout) {
+		    time_after_eq(now, rt->u.dst.lastuse + gc_args.timeout)) {
 			RT6_TRACE("aging clone %p\n", rt);
 			return -1;
 		}
diff -urN linux-2.5.69-bk2/net/ipv6/route.c linux-2.5.69-bk3/net/ipv6/route.c
--- linux-2.5.69-bk2/net/ipv6/route.c	2003-05-08 04:38:13.000000000 -0700
+++ linux-2.5.69-bk3/net/ipv6/route.c	2003-05-08 04:38:22.000000000 -0700
@@ -39,6 +39,7 @@
 
 #ifdef 	CONFIG_PROC_FS
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #endif
 
 #include <net/snmp.h>
@@ -564,7 +565,7 @@
 	static unsigned long last_gc;
 	unsigned long now = jiffies;
 
-	if ((long)(now - last_gc) < ip6_rt_gc_min_interval &&
+	if (time_after(last_gc + ip6_rt_gc_min_interval, now) &&
 	    atomic_read(&ip6_dst_ops.entries) <= ip6_rt_max_size)
 		goto out;
 
@@ -1751,27 +1752,28 @@
 
 extern struct rt6_statistics rt6_stats;
 
-static int rt6_proc_stats(char *buffer, char **start, off_t offset, int length)
+static int rt6_stats_seq_show(struct seq_file *seq, void *v)
 {
-	int len;
-
-	len = sprintf(buffer, "%04x %04x %04x %04x %04x %04x\n",
+	seq_printf(seq, "%04x %04x %04x %04x %04x %04x\n",
 		      rt6_stats.fib_nodes, rt6_stats.fib_route_nodes,
 		      rt6_stats.fib_rt_alloc, rt6_stats.fib_rt_entries,
 		      rt6_stats.fib_rt_cache,
 		      atomic_read(&ip6_dst_ops.entries));
 
-	len -= offset;
-
-	if (len > length)
-		len = length;
-	if(len < 0)
-		len = 0;
-
-	*start = buffer + offset;
+	return 0;
+}
 
-	return len;
+static int rt6_stats_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, rt6_stats_seq_show, NULL);
 }
+
+static struct file_operations rt6_stats_seq_fops = {
+	.open	 = rt6_stats_seq_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = single_release,
+};
 #endif	/* CONFIG_PROC_FS */
 
 #ifdef CONFIG_SYSCTL
@@ -1877,6 +1879,8 @@
 
 void __init ip6_route_init(void)
 {
+	struct proc_dir_entry *p;
+
 	ip6_dst_ops.kmem_cachep = kmem_cache_create("ip6_dst_cache",
 						     sizeof(struct rt6_info),
 						     0, SLAB_HWCACHE_ALIGN,
@@ -1884,7 +1888,9 @@
 	fib6_init();
 #ifdef 	CONFIG_PROC_FS
 	proc_net_create("ipv6_route", 0, rt6_proc_info);
-	proc_net_create("rt6_stats", 0, rt6_proc_stats);
+	p = create_proc_entry("rt6_stats", S_IRUGO, proc_net);
+	if (p)
+		p->proc_fops = &rt6_stats_seq_fops;
 #endif
 	xfrm6_init();
 }
@@ -1894,7 +1900,7 @@
 {
 #ifdef CONFIG_PROC_FS
 	proc_net_remove("ipv6_route");
-	proc_net_remove("rt6_stats");
+	remove_proc_entry("rt6_stats", proc_net);
 #endif
 	xfrm6_fini();
 	rt6_ifdown(NULL);
diff -urN linux-2.5.69-bk2/net/netlink/netlink_dev.c linux-2.5.69-bk3/net/netlink/netlink_dev.c
--- linux-2.5.69-bk2/net/netlink/netlink_dev.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk3/net/netlink/netlink_dev.c	2003-05-08 04:38:22.000000000 -0700
@@ -220,14 +220,6 @@
 	},
 };
 
-static void __init make_devfs_entries (const char *name, int minor)
-{
-	devfs_register (NULL, name, DEVFS_FL_DEFAULT,
-			NETLINK_MAJOR, minor,
-			S_IFCHR | S_IRUSR | S_IWUSR,
-			&netlink_fops, NULL);
-}
-
 int __init init_netlink(void)
 {
 	int i;
@@ -236,18 +228,20 @@
 		printk(KERN_ERR "netlink: unable to get major %d\n", NETLINK_MAJOR);
 		return -EIO;
 	}
+
 	devfs_mk_dir("netlink");
+
 	/*  Someone tell me the official names for the uppercase ones  */
 	for (i = 0; i < sizeof(entries)/sizeof(entries[0]); i++) {
-		char name[20];
-		sprintf(name, "netlink/%s", entries[i].name);
-		make_devfs_entries(name, entries[i].minor);
+		devfs_mk_cdev(MKDEV(NETLINK_MAJOR, entries[i].minor),
+			S_IFCHR|S_IRUSR|S_IWUSR, "netlink/%s", entries[i].name);
 	}
+
 	for (i = 0; i < 16; i++) {
-		char name[20];
-		sprintf(name, "netlink/tap%d", i);
-		make_devfs_entries(name, i + 16);
+		devfs_mk_cdev(MKDEV(NETLINK_MAJOR, i + 16),
+			S_IFCHR|S_IRUSR|S_IWUSR, "netlink/tap%d", i);
 	}
+
 	return 0;
 }
 
diff -urN linux-2.5.69-bk2/net/socket.c linux-2.5.69-bk3/net/socket.c
--- linux-2.5.69-bk2/net/socket.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk3/net/socket.c	2003-05-08 04:38:22.000000000 -0700
@@ -1280,26 +1280,26 @@
 	 * We don't need try_module_get here, as the listening socket (sock)
 	 * has the protocol module (sock->ops->owner) held.
 	 */
-	__module_get(sock->ops->owner);
+	__module_get(newsock->ops->owner);
 
 	err = sock->ops->accept(sock, newsock, sock->file->f_flags);
 	if (err < 0)
-		goto out_module_put;
+		goto out_release;
 
 	if (upeer_sockaddr) {
 		if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) {
 			err = -ECONNABORTED;
-			goto out_module_put;
+			goto out_release;
 		}
 		err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen);
 		if (err < 0)
-			goto out_module_put;
+			goto out_release;
 	}
 
 	/* File flags are not inherited via accept() unlike another OSes. */
 
 	if ((err = sock_map_fd(newsock)) < 0)
-		goto out_module_put;
+		goto out_release;
 
 	security_socket_post_accept(sock, newsock);
 
@@ -1307,8 +1307,6 @@
 	sockfd_put(sock);
 out:
 	return err;
-out_module_put:
-	module_put(sock->ops->owner);
 out_release:
 	sock_release(newsock);
 	goto out_put;
diff -urN linux-2.5.69-bk2/net/unix/af_unix.c linux-2.5.69-bk3/net/unix/af_unix.c
--- linux-2.5.69-bk2/net/unix/af_unix.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk3/net/unix/af_unix.c	2003-05-08 04:38:22.000000000 -0700
@@ -625,7 +625,7 @@
 			goto put_fail;
 
 		if (u->type == type)
-			UPDATE_ATIME(nd.dentry->d_inode);
+			update_atime(nd.dentry->d_inode);
 
 		path_release(&nd);
 
@@ -641,7 +641,7 @@
 			struct dentry *dentry;
 			dentry = unix_sk(u)->dentry;
 			if (dentry)
-				UPDATE_ATIME(dentry->d_inode);
+				update_atime(dentry->d_inode);
 		} else
 			goto fail;
 	}
diff -urN linux-2.5.69-bk2/scripts/Makefile.build linux-2.5.69-bk3/scripts/Makefile.build
--- linux-2.5.69-bk2/scripts/Makefile.build	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk3/scripts/Makefile.build	2003-05-08 04:38:22.000000000 -0700
@@ -66,6 +66,12 @@
 	 $(subdir-ym) $(always)
 	@:
 
+# Linus's kernel sanity checking tool
+ifneq ($(KBUILD_CHECKSRC),0)
+quiet_cmd_checksrc = CHECK   $<
+      cmd_checksrc = $(CHECK) $(CFLAGS) $< ;
+endif
+ 
 # Module versioning
 # ---------------------------------------------------------------------------
 
@@ -91,6 +97,8 @@
 cmd_vcc_o_c       = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
 
 define rule_vcc_o_c
+	$(if $($(quiet)cmd_checksrc),echo '  $($(quiet)cmd_checksrc)';)	      \
+	$(cmd_checksrc)							      \
 	$(if $($(quiet)cmd_vcc_o_c),echo '  $($(quiet)cmd_vcc_o_c)';)	      \
 	$(cmd_vcc_o_c);							      \
 									      \
@@ -158,6 +166,15 @@
 
 quiet_cmd_cc_o_c = CC $(quiet_modtag)  $@
 cmd_cc_o_c       = $(CC) $(c_flags) -c -o $@ $<
+define rule_cc_o_c
+	$(if $($(quiet)cmd_checksrc),echo '  $($(quiet)cmd_checksrc)';)	      \
+	$(cmd_checksrc)							      \
+	$(if $($(quiet)cmd_cc_o_c),echo '  $($(quiet)cmd_cc_o_c)';)	      \
+	$(cmd_cc_o_c);							      \
+	scripts/fixdep $(depfile) $@ '$(cmd_cc_o_c)' > $(@D)/.$(@F).tmp;      \
+	rm -f $(depfile);						      \
+	mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd
+endef
 
 # Built-in and composite module parts
 
@@ -165,7 +182,7 @@
 ifdef CONFIG_MODVERSIONS
 	$(call if_changed_rule,vcc_o_c)
 else
-	$(call if_changed_dep,cc_o_c)
+	$(call if_changed_rule,cc_o_c)
 endif
 
 # Single-part modules are special since we need to mark them in $(MODVERDIR)
@@ -174,7 +191,7 @@
 ifdef CONFIG_MODVERSIONS
 	$(call if_changed_rule,vcc_o_c)
 else
-	$(call if_changed_dep,cc_o_c)
+	$(call if_changed_rule,cc_o_c)
 endif
 	$(touch-module)
 
diff -urN linux-2.5.69-bk2/security/dummy.c linux-2.5.69-bk3/security/dummy.c
--- linux-2.5.69-bk2/security/dummy.c	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk3/security/dummy.c	2003-05-08 04:38:22.000000000 -0700
@@ -334,6 +334,11 @@
 	return 0;
 }
 
+static void dummy_inode_post_setxattr (struct dentry *dentry, char *name, void *value,
+				       size_t size, int flags)
+{
+}
+
 static int dummy_inode_getxattr (struct dentry *dentry, char *name)
 {
 	return 0;
@@ -803,6 +808,7 @@
 	set_to_dummy_if_null(ops, inode_getattr);
 	set_to_dummy_if_null(ops, inode_delete);
 	set_to_dummy_if_null(ops, inode_setxattr);
+	set_to_dummy_if_null(ops, inode_post_setxattr);
 	set_to_dummy_if_null(ops, inode_getxattr);
 	set_to_dummy_if_null(ops, inode_listxattr);
 	set_to_dummy_if_null(ops, inode_removexattr);
diff -urN linux-2.5.69-bk2/sound/core/info.c linux-2.5.69-bk3/sound/core/info.c
--- linux-2.5.69-bk2/sound/core/info.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk3/sound/core/info.c	2003-05-08 04:38:22.000000000 -0700
@@ -1079,15 +1079,9 @@
 	p->data = (void *) entry;
 	entry->p = p;
 	up(&info_mutex);
-#ifdef CONFIG_DEVFS_FS
-	if (strncmp(name, "controlC", 8)) {	/* created in sound.c */
-		char dname[32];
-		sprintf(dname, "snd/%s", name);
-		devfs_register(NULL, dname, DEVFS_FL_DEFAULT,
-				_major, minor, mode,
-				&snd_fops, NULL);
-	}
-#endif
+
+	if (strncmp(name, "controlC", 8) == 0)	/* created in sound.c */
+		devfs_mk_cdev(MKDEV(_major, minor), mode, "snd/%s", name);
 	return entry;
 }
 
diff -urN linux-2.5.69-bk2/sound/core/sound.c linux-2.5.69-bk3/sound/core/sound.c
--- linux-2.5.69-bk2/sound/core/sound.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk3/sound/core/sound.c	2003-05-08 04:38:22.000000000 -0700
@@ -323,13 +323,8 @@
 
 static int __init alsa_sound_init(void)
 {
-#ifdef CONFIG_DEVFS_FS
 	short controlnum;
-	char controlname[24];
-#endif
-#ifdef CONFIG_SND_OSSEMUL
-	int err;
-#endif
+	int err = 0;
 	int card;
 
 	snd_ecards_limit = cards_limit;
@@ -356,21 +351,19 @@
 #ifdef CONFIG_SND_OSSEMUL
 	snd_info_minor_register();
 #endif
-#ifdef CONFIG_DEVFS_FS
+
 	for (controlnum = 0; controlnum < cards_limit; controlnum++) {
-		sprintf(controlname, "snd/controlC%d", controlnum);
-		devfs_register(NULL, controlname, DEVFS_FL_DEFAULT,
-				major, controlnum<<5, device_mode | S_IFCHR,
-				&snd_fops, NULL);
+		devfs_mk_cdev(MKDEV(major, controlnum<<5),
+			device_mode | S_IFCHR, "snd/controlC%d", controlnum);
 	}
-#endif
+
 #ifndef MODULE
 	printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n");
 #endif
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) && defined(CONFIG_APM)
 	pm_init();
 #endif
-	return 0;
+	return err;
 }
 
 static void __exit alsa_sound_exit(void)
diff -urN linux-2.5.69-bk2/sound/oss/opl3sa2.c linux-2.5.69-bk3/sound/oss/opl3sa2.c
--- linux-2.5.69-bk2/sound/oss/opl3sa2.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk3/sound/oss/opl3sa2.c	2003-05-08 04:38:22.000000000 -0700
@@ -353,7 +353,8 @@
 	}
 }
 
-
+/* Currently only used for power management */
+#ifdef CONFIG_PM
 static void opl3sa2_mixer_restore(opl3sa2_state_t* devc)
 {
 	if (devc) {
@@ -366,7 +367,7 @@
 		}
 	}
 }
-
+#endif
 
 static inline void arg_to_vol_mono(unsigned int vol, int* value)
 {
@@ -961,7 +962,6 @@
 	spin_unlock_irqrestore(&opl3sa2_lock,flags);
 	return 0;
 }
-#endif /* CONFIG_PM */
 
 static int opl3sa2_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data)
 {
@@ -976,6 +976,7 @@
 	}
 	return 0;
 }
+#endif /* CONFIG_PM */
 
 /*
  * Install OPL3-SA2 based card(s).
@@ -1127,10 +1128,11 @@
 	int card;
 
 	for(card = 0; card < opl3sa2_cards_num; card++) {
+#ifdef CONFIG_PM
 		if (opl3sa2_state[card].pmdev)
 			pm_unregister(opl3sa2_state[card].pmdev);
-
-	        if(opl3sa2_state[card].cfg_mpu.slots[1] != -1) {
+#endif
+	        if (opl3sa2_state[card].cfg_mpu.slots[1] != -1) {
 			unload_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu);
  		}
 		unload_opl3sa2_mss(&opl3sa2_state[card].cfg_mss);
diff -urN linux-2.5.69-bk2/sound/oss/soundcard.c linux-2.5.69-bk3/sound/oss/soundcard.c
--- linux-2.5.69-bk2/sound/oss/soundcard.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk3/sound/oss/soundcard.c	2003-05-08 04:38:22.000000000 -0700
@@ -549,7 +549,6 @@
 static int __init oss_init(void)
 {
 	int             err;
-	char name_buf[32];
 	int i, j;
 	
 	/* drag in sound_syms.o */
@@ -573,19 +572,18 @@
 	sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
 
 	for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
-		sprintf(name_buf, "sound/%s", dev_list[i].name);
-		devfs_register (NULL, name_buf, DEVFS_FL_NONE,
-			SOUND_MAJOR, dev_list[i].minor,
-			S_IFCHR | dev_list[i].mode,
-			&oss_sound_fops, NULL);
+		devfs_mk_cdev(MKDEV(SOUND_MAJOR, dev_list[i].minor),
+				S_IFCHR | dev_list[i].mode,
+				"sound/%s", dev_list[i].name);
+
 		if (!dev_list[i].num)
 			continue;
+
 		for (j = 1; j < *dev_list[i].num; j++) {
-			sprintf(name_buf, "sound/%s%d", dev_list[i].name, j);
-			devfs_register (NULL, name_buf, DEVFS_FL_NONE,
-				SOUND_MAJOR, dev_list[i].minor + (j * 0x10),
-				S_IFCHR | dev_list[i].mode,
-				&oss_sound_fops, NULL);
+			devfs_mk_cdev(MKDEV(SOUND_MAJOR,
+						dev_list[i].minor + (j*0x10)),
+					S_IFCHR | dev_list[i].mode,
+					"sound/%s%d", dev_list[i].name, j);
 		}
 	}
 
diff -urN linux-2.5.69-bk2/sound/sound_core.c linux-2.5.69-bk3/sound/sound_core.c
--- linux-2.5.69-bk2/sound/sound_core.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk3/sound/sound_core.c	2003-05-08 04:38:22.000000000 -0700
@@ -168,8 +168,8 @@
 	else
 		sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
 
-	devfs_register(NULL, s->name, 0, SOUND_MAJOR, s->unit_minor,
-			S_IFCHR | mode, fops, NULL);
+	devfs_mk_cdev(MKDEV(SOUND_MAJOR, s->unit_minor),
+			S_IFCHR | mode, s->name);
 	return r;
 
  fail:
