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

diff -urN linux-2.5.69-bk18/CREDITS linux-2.5.69-bk19/CREDITS
--- linux-2.5.69-bk18/CREDITS	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/CREDITS	2003-05-26 04:41:41.000000000 -0700
@@ -2966,12 +2966,11 @@
 S: USA
 
 N: Manfred Spraul
-E: manfreds@colorfullife.com
-W: http://colorfullife.com/~manfreds
-D: major SysV IPC changes
-D: various bug fixes (mostly SMP code)
-S: Warburgring 67
-S: 66424 Homburg 
+E: manfred@colorfullife.com
+W: http://www.colorfullife.com/~manfred
+D: Lots of tiny hacks. Larger improvments to SysV IPC msg,
+D: slab, pipe, select.
+S: 71701 Schwieberdingen
 S: Germany
 
 N: Andrew Stanley-Jones
diff -urN linux-2.5.69-bk18/Documentation/Changes linux-2.5.69-bk19/Documentation/Changes
--- linux-2.5.69-bk18/Documentation/Changes	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/Documentation/Changes	2003-05-26 04:41:41.000000000 -0700
@@ -83,8 +83,6 @@
 will need to be fixed in order to use these compilers. In any case, using
 pgcc instead of plain gcc is just asking for trouble.
 
-gcc 2.91.66 (egcs-1.1.2) continues to be supported for SPARC64 requirements.
-
 The Red Hat gcc 2.96 compiler subtree can also be used to build this tree.
 You should ensure you use gcc-2.96-74 or later. gcc-2.96-54 will not build
 the kernel correctly.
diff -urN linux-2.5.69-bk18/Documentation/filesystems/Locking linux-2.5.69-bk19/Documentation/filesystems/Locking
--- linux-2.5.69-bk18/Documentation/filesystems/Locking	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/Documentation/filesystems/Locking	2003-05-26 04:41:41.000000000 -0700
@@ -120,7 +120,7 @@
 
 --------------------------- file_system_type ---------------------------
 prototypes:
-	struct super_block *(*get_sb) (struct file_system_type *, int, char *, void *);
+	struct super_block *(*get_sb) (struct file_system_type *, int, const char *, void *);
 	void (*kill_sb) (struct super_block *);
 locking rules:
 		may block	BKL
diff -urN linux-2.5.69-bk18/Documentation/filesystems/porting linux-2.5.69-bk19/Documentation/filesystems/porting
--- linux-2.5.69-bk18/Documentation/filesystems/porting	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/Documentation/filesystems/porting	2003-05-26 04:41:41.000000000 -0700
@@ -51,7 +51,7 @@
 informative error value to report).  Call it foo_fill_super().  Now declare
 
 struct super_block foo_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super);
 }
diff -urN linux-2.5.69-bk18/Documentation/iostats.txt linux-2.5.69-bk19/Documentation/iostats.txt
--- linux-2.5.69-bk18/Documentation/iostats.txt	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/Documentation/iostats.txt	2003-05-26 04:41:41.000000000 -0700
@@ -0,0 +1,148 @@
+I/O statistics fields
+---------------
+
+Last modified 5/15/03
+
+In 2.4.20 (and some versions before, with patches), and 2.5.45,
+more extensive disk statistics were introduced to help measure disk
+activity. Tools such as sar and iostat typically interpret these and do
+the work for you, but in case you are interested in creating your own
+tools, the fields are explained here.
+
+In most versions of the 2.4 patch, the information is found as additional
+fields in /proc/partitions.  In 2.5, the same information is found in
+two places: one is in the file /proc/diskstats (appears in 2.5.69 and
+beyond), and the other is within the sysfs file system, which must be
+mounted in order to obtain the information. Throughout this document
+we'll assume that sysfs is mounted on /sys, although of course it may
+be mounted anywhere.  In 2.5, both /proc/diskstats and sysfs use the
+same source for the information and so should not differ.
+
+Here are examples of these different formats:
+
+2.4:
+   3     0   39082680 hda 446216 784926 9550688 4382310 424847 312726 5922052 19310380 0 3376340 23705160
+   3     1    9221278 hda1 35486 0 35496 38030 0 0 0 0 0 38030 38030
+
+
+2.5 sysfs:
+   446216 784926 9550688 4382310 424847 312726 5922052 19310380 0 3376340 23705160
+   35486    38030    38030    38030
+
+2.5 diskstats:
+   3    0   hda 446216 784926 9550688 4382310 424847 312726 5922052 19310380 0 3376340 23705160
+   3    1   hda1 35486 38030 38030 38030
+
+On 2.4 you might execute "grep 'hda ' /proc/partitions". On 2.5, you have
+a choice of "cat /sys/block/hda/stat" or "grep 'hda ' /proc/diskstats".
+The advantage of one over the other is that the sysfs choice works well
+if you are watching a known, small set of disks.  /proc/diskstats may
+be a better choice if you are watching a large number of disks because
+you'll avoid the overhead of 50, 100, or 500 or more opens/closes with
+each snapshot of your disk statistics.
+
+In 2.4, the statistics fields are those after the device name. In
+the above example, the first field of statistics would be 446216.
+By contrast, in 2.5 if you look at /sys/block/hda/stat, you'll
+find just the eleven fields, beginning with 446216.  If you look at
+/proc/diskstats, the eleven fields will be preceded by the major and
+minor device numbers, and device name.  Each of these formats provide
+eleven fields of statistics, each meaning exactly the same things.
+All fields except field 9 are cumulative since boot.  Field 9 should
+go to zero as I/Os complete; all others only increase.  Yes, these are
+32 bit unsigned numbers, and on a very busy or long-lived system they
+may wrap. Applications should be prepared to deal with that; unless
+your observations are measured in large numbers of minutes or hours,
+they should not wrap twice before you notice them.
+
+Each set of stats only applies to the indicated device; if you want
+system-wide stats you'll have to find all the devices and sum them all up.
+
+Field  1 -- # of reads issued
+    This is the total number of reads completed successfully.
+Field  2 -- # of reads merged, field 6 -- # of writes merged
+    Reads and writes which are adjacent to each other may be merged for
+    efficiency.  Thus two 4K reads may become one 8K read before it is
+    ultimately handed to the disk, and so it will be counted (and queued)
+    as only one I/O.  This field lets you know how often this was done.
+Field  3 -- # of sectors read
+    This is the total number of sectors read successfully.
+Field  4 -- # of milliseconds spent reading
+    This is the total number of milliseconds spent by all reads (as
+    measured from __make_request() to end_that_request_last()).
+Field  5 -- # of writes completed
+    This is the total number of writes completed successfully.
+Field  7 -- # of sectors written
+    This is the total number of sectors written successfully.
+Field  8 -- # of milliseconds spent writing
+    This is the total number of milliseconds spent by all writes (as
+    measured from __make_request() to end_that_request_last()).
+Field  9 -- # of I/Os currently in progress
+    The only field that should go to zero. Incremented as requests are
+    given to appropriate request_queue_t and decremented as they finish.
+Field 10 -- # of milliseconds spent doing I/Os
+    This field is increases so long as field 9 is nonzero.
+Field 11 -- weighted # of milliseconds spent doing I/Os
+    This field is incremented at each I/O start, I/O completion, I/O
+    merge, or read of these stats by the number of I/Os in progress
+    (field 9) times the number of milliseconds spent doing I/O since the
+    last update of this field.  This can provide an easy measure of both
+    I/O completion time and the backlog that may be accumulating.
+
+
+To avoid introducing performance bottlenecks, no locks are held while
+modifying these counters.  This implies that minor inaccuracies may be
+introduced when changes collide, so (for instance) adding up all the
+read I/Os issued per partition should equal those made to the disks
+... but due to the lack of locking it may only be very close.
+
+In release 2.5.65 the 2.5 counters were made per-cpu, which made the lack
+of locking almost a non-issue.  When the statistics are read, the per-cpu
+counters are summed (possibly overflowing the unsigned 32-bit variable
+they are summed to) and the result given to the user.  There is no
+convenient user interface for accessing the per-cpu counters themselves.
+
+Disks vs Partitions
+-------------------
+
+There were significant changes between 2.4 and 2.5 in the I/O subsystem.
+As a result, some statistic information disappeared. The translation from
+a disk address relative to a partition to the disk address relative to
+the host disk happens much earlier.  All merges and timings now happen
+at the disk level rather than at both the disk and partition level as
+in 2.4.  Consequently, you'll see a different statistics output on 2.5 for
+partitions from that for disks.  There are only *four* fields available
+for partitions on 2.5 machines.  This is reflected in the examples above.
+
+Field  1 -- # of reads issued
+    This is the total number of reads issued to this partition.
+Field  2 -- # of sectors read
+    This is the total number of sectors requested to be read from this
+    partition.
+Field  3 -- # of reads issued
+    This is the total number of writes issued to this partition.
+Field  4 -- # of sectors read
+    This is the total number of sectors requested to be written to
+    this partition.
+
+Note that since the address is translated to a disk-relative one, and no
+record of the partition-relative address is kept, the subsequent success
+or failure of the read cannot be attributed to the partition.  In other
+words, the number of reads for partitions is counted slightly before time
+of queuing for partitions, and at completion for whole disks.  This is
+a subtle distinction that is probably uninteresting for most cases.
+
+Additional notes
+----------------
+
+In 2.5, sysfs is not mounted by default.  Here's the line you'll want
+to add to your /etc/fstab:
+
+none /sys sysfs defaults 0 0
+
+
+In 2.5, at the same time that disk statistics appeared in sysfs, they were
+removed from /proc/stat.  In 2.4, they appear in both /proc/partitions
+and /proc/stat.
+
+-- ricklind@us.ibm.com
diff -urN linux-2.5.69-bk18/Documentation/kernel-parameters.txt linux-2.5.69-bk19/Documentation/kernel-parameters.txt
--- linux-2.5.69-bk18/Documentation/kernel-parameters.txt	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/Documentation/kernel-parameters.txt	2003-05-26 04:41:41.000000000 -0700
@@ -652,6 +652,9 @@
 	opl3sa2=	[HW,OSS]
 			Format: <io>,<irq>,<dma>,<dma2>,<mss_io>,<mpu_io>,<ymode>,<loopback>[,<isapnp>,<multiple]
  
+	oprofile.timer=	[HW]
+			Use timer interrupt instead of performance counters
+
 	optcd=		[HW,CD]
 			Format: <io>
 
diff -urN linux-2.5.69-bk18/Documentation/networking/generic-hdlc.txt linux-2.5.69-bk19/Documentation/networking/generic-hdlc.txt
--- linux-2.5.69-bk18/Documentation/networking/generic-hdlc.txt	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk19/Documentation/networking/generic-hdlc.txt	2003-05-26 04:41:41.000000000 -0700
@@ -38,8 +38,10 @@
 	sethdlc hdlc0 cisco interval 10 timeout 25
 or
 	sethdlc hdlc0 rs232 clock ext
-	sethdlc fr lmi ansi
-	sethdlc create 99
+	sethdlc hdlc0 fr lmi ansi
+	sethdlc hdlc0 create 99
+	ifconfig hdlc0 up
+	ifconfig pvc0 localIP pointopoint remoteIP
 
 In Frame Relay mode, ifconfig master hdlc device up (without assigning
 any IP address to it) before using pvc devices.
diff -urN linux-2.5.69-bk18/Documentation/sysctl/vm.txt linux-2.5.69-bk19/Documentation/sysctl/vm.txt
--- linux-2.5.69-bk18/Documentation/sysctl/vm.txt	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/Documentation/sysctl/vm.txt	2003-05-26 04:41:41.000000000 -0700
@@ -35,17 +35,20 @@
 overcommit_memory:
 
 This value contains a flag that enables memory overcommitment.
-When this flag is 0, the kernel checks before each malloc()
-to see if there's enough memory left. If the flag is nonzero,
-the system pretends there's always enough memory.
+
+When this flag is 0, the kernel attempts to estimate the amount
+of free memory left when userspace requests more memory.
+
+When this flag is 1, the kernel pretends there is always enough
+memory until it actually runs out.
+
+When this flag is 2, the kernel uses a "strict overcommit" 
+policy that attempts to prevent any overcommit of memory.  
 
 This feature can be very useful because there are a lot of
 programs that malloc() huge amounts of memory "just-in-case"
 and don't use much of it.
 
-A value  of 2 introduces a new "strict overcommit" policy
-that attempts to prevent any overcommit of memory.
-
 The default value is 0.
 
 See Documentation/vm/overcommit-accounting and
diff -urN linux-2.5.69-bk18/Documentation/vm/overcommit-accounting linux-2.5.69-bk19/Documentation/vm/overcommit-accounting
--- linux-2.5.69-bk18/Documentation/vm/overcommit-accounting	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/Documentation/vm/overcommit-accounting	2003-05-26 04:41:41.000000000 -0700
@@ -3,7 +3,9 @@
 0	-	Heuristic overcommit handling. Obvious overcommits of
 		address space are refused. Used for a typical system. It
 		ensures a seriously wild allocation fails while allowing
-		overcommit to reduce swap usage.  This is the default.
+		overcommit to reduce swap usage.  root is allowed to 
+		allocate slighly more memory in this mode. This is the 
+		default.
 
 1	-	No overcommit handling. Appropriate for some scientific
 		applications.
diff -urN linux-2.5.69-bk18/Makefile linux-2.5.69-bk19/Makefile
--- linux-2.5.69-bk18/Makefile	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/Makefile	2003-05-26 04:41:41.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 69
-EXTRAVERSION = -bk18
+EXTRAVERSION = -bk19
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -107,7 +107,7 @@
 # If it is set to "silent_", nothing wil be printed at all, since
 # the variable $(silent_cmd_cc_o_c) doesn't exist.
 
-#	For now, leave verbose as default
+# To put more focus on warnings, less verbose as default
 
 ifdef V
   ifeq ("$(origin V)", "command line")
@@ -115,7 +115,7 @@
   endif
 endif
 ifndef KBUILD_VERBOSE
-  KBUILD_VERBOSE = 1
+  KBUILD_VERBOSE = 0 
 endif
 
 ifdef C
diff -urN linux-2.5.69-bk18/arch/alpha/kernel/setup.c linux-2.5.69-bk19/arch/alpha/kernel/setup.c
--- linux-2.5.69-bk18/arch/alpha/kernel/setup.c	2003-05-04 16:53:03.000000000 -0700
+++ linux-2.5.69-bk19/arch/alpha/kernel/setup.c	2003-05-26 04:41:41.000000000 -0700
@@ -501,10 +501,9 @@
 	   boot flags depending on the boot mode, we need some shorthand.
 	   This should do for installation.  */
 	if (strcmp(COMMAND_LINE, "INSTALL") == 0) {
-		strcpy(command_line, "root=/dev/fd0 load_ramdisk=1");
+		strlcpy(command_line, "root=/dev/fd0 load_ramdisk=1", sizeof command_line);
 	} else {
-		strncpy(command_line, COMMAND_LINE, sizeof command_line);
-		command_line[sizeof(command_line)-1] = 0;
+		strlcpy(command_line, COMMAND_LINE, sizeof command_line);
 	}
 	strcpy(saved_command_line, command_line);
 	*cmdline_p = command_line;
diff -urN linux-2.5.69-bk18/arch/alpha/mm/init.c linux-2.5.69-bk19/arch/alpha/mm/init.c
--- linux-2.5.69-bk18/arch/alpha/mm/init.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/arch/alpha/mm/init.c	2003-05-26 04:41:41.000000000 -0700
@@ -34,7 +34,7 @@
 #include <asm/console.h>
 #include <asm/tlb.h>
 
-struct mmu_gather mmu_gathers[NR_CPUS];
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 extern void die_if_kernel(char *,struct pt_regs *,long);
 
diff -urN linux-2.5.69-bk18/arch/arm/common/sa1111-pcipool.c linux-2.5.69-bk19/arch/arm/common/sa1111-pcipool.c
--- linux-2.5.69-bk18/arch/arm/common/sa1111-pcipool.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/arm/common/sa1111-pcipool.c	2003-05-26 04:41:41.000000000 -0700
@@ -113,8 +113,7 @@
 	if (!(retval = kmalloc (sizeof *retval, SLAB_KERNEL)))
 		return retval;
 
-	strncpy (retval->name, name, sizeof retval->name);
-	retval->name [sizeof retval->name - 1] = 0;
+	strlcpy (retval->name, name, sizeof retval->name);
 
 	retval->dev = pdev;
 	INIT_LIST_HEAD (&retval->page_list);
diff -urN linux-2.5.69-bk18/arch/arm/kernel/setup.c linux-2.5.69-bk19/arch/arm/kernel/setup.c
--- linux-2.5.69-bk18/arch/arm/kernel/setup.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk19/arch/arm/kernel/setup.c	2003-05-26 04:41:41.000000000 -0700
@@ -598,8 +598,7 @@
 
 static int __init parse_tag_cmdline(const struct tag *tag)
 {
-	strncpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
-	default_command_line[COMMAND_LINE_SIZE - 1] = '\0';
+	strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
 	return 0;
 }
 
diff -urN linux-2.5.69-bk18/arch/cris/kernel/setup.c linux-2.5.69-bk19/arch/cris/kernel/setup.c
--- linux-2.5.69-bk18/arch/cris/kernel/setup.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/arch/cris/kernel/setup.c	2003-05-26 04:41:41.000000000 -0700
@@ -170,14 +170,12 @@
 	*cmdline_p = command_line;
 
 	if (romfs_in_flash) {
-		strncpy(command_line, "root=", COMMAND_LINE_SIZE);
-		strncpy(command_line+5, CONFIG_ETRAX_ROOT_DEVICE,
-			COMMAND_LINE_SIZE-5);
+		strlcpy(command_line, "root=", sizeof(command_line));
+		strlcat(command_line, CONFIG_ETRAX_ROOT_DEVICE,
+			sizeof(command_line));
 
 		/* Save command line copy for /proc/cmdline */
-
-		memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
-		saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+		strlcpy(saved_command_line, command_line, sizeof(saved_command_line));
 	}
 
 	/* give credit for the CRIS port */
diff -urN linux-2.5.69-bk18/arch/i386/kernel/apic.c linux-2.5.69-bk19/arch/i386/kernel/apic.c
--- linux-2.5.69-bk18/arch/i386/kernel/apic.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/arch/i386/kernel/apic.c	2003-05-26 04:41:41.000000000 -0700
@@ -291,6 +291,8 @@
 	value = apic_read(APIC_SPIV);
 	value &= ~APIC_VECTOR_MASK;
 	value |= APIC_SPIV_APIC_ENABLED;
+	
+	/* This bit is reserved on P4/Xeon and should be cleared */
 	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 15))
 		value &= ~APIC_SPIV_FOCUS_DISABLED;
 	else
diff -urN linux-2.5.69-bk18/arch/i386/kernel/apm.c linux-2.5.69-bk19/arch/i386/kernel/apm.c
--- linux-2.5.69-bk18/arch/i386/kernel/apm.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/i386/kernel/apm.c	2003-05-26 04:41:41.000000000 -0700
@@ -512,9 +512,8 @@
 {
 	unsigned long x = current->cpus_allowed;
 	/* Some bioses don't like being called from CPU != 0 */
-	set_cpus_allowed(current, 1 << 0);
-	if (unlikely(smp_processor_id() != 0))
-		BUG();
+	set_cpus_allowed(current, 1UL << 0);
+	BUG_ON(smp_processor_id() != 0);
 	return x;
 }
 
@@ -914,11 +913,8 @@
 	 */
 #ifdef CONFIG_SMP
 	/* Some bioses don't like being called from CPU != 0 */
-	if (smp_processor_id() != 0) {
-		set_cpus_allowed(current, 1 << 0);
-		if (unlikely(smp_processor_id() != 0))
-			BUG();
-	}
+	set_cpus_allowed(current, 1UL << 0);
+	BUG_ON(smp_processor_id() != 0);
 #endif
 	if (apm_info.realmode_power_off)
 	{
@@ -1708,11 +1704,8 @@
 	 * Some bioses don't like being called from CPU != 0.
 	 * Method suggested by Ingo Molnar.
 	 */
-	if (smp_processor_id() != 0) {
-		set_cpus_allowed(current, 1 << 0);
-		if (unlikely(smp_processor_id() != 0))
-			BUG();
-	}
+	set_cpus_allowed(current, 1UL << 0);
+	BUG_ON(smp_processor_id() != 0);
 #endif
 
 	if (apm_info.connection_version == 0) {
diff -urN linux-2.5.69-bk18/arch/i386/kernel/mpparse.c linux-2.5.69-bk19/arch/i386/kernel/mpparse.c
--- linux-2.5.69-bk18/arch/i386/kernel/mpparse.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/i386/kernel/mpparse.c	2003-05-26 04:41:41.000000000 -0700
@@ -171,7 +171,7 @@
 
 	num_processors++;
 
-	if (m->mpc_apicid > MAX_APICS) {
+	if (MAX_APICS - m->mpc_apicid <= 0) {
 		printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
 			m->mpc_apicid, MAX_APICS);
 		--num_processors;
@@ -803,7 +803,7 @@
 	struct mpc_config_processor processor;
 	int			boot_cpu = 0;
 	
-	if (id >= MAX_APICS) {
+	if (MAX_APICS - id <= 0) {
 		printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
 			id, MAX_APICS);
 		return;
diff -urN linux-2.5.69-bk18/arch/i386/kernel/srat.c linux-2.5.69-bk19/arch/i386/kernel/srat.c
--- linux-2.5.69-bk18/arch/i386/kernel/srat.c	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk19/arch/i386/kernel/srat.c	2003-05-26 04:41:41.000000000 -0700
@@ -312,7 +312,8 @@
 
 	if (rsdp_address->pointer_type == ACPI_PHYSICAL_POINTER) {
 		printk("%s: assigning address to rsdp\n", __FUNCTION__);
-		rsdp = (struct acpi_table_rsdp *)rsdp_address->pointer.physical;
+		rsdp = (struct acpi_table_rsdp *)
+				(u32)rsdp_address->pointer.physical;
 	} else {
 		printk("%s: rsdp_address is not a physical pointer\n", __FUNCTION__);
 		return;
diff -urN linux-2.5.69-bk18/arch/i386/kernel/timers/timer.c linux-2.5.69-bk19/arch/i386/kernel/timers/timer.c
--- linux-2.5.69-bk18/arch/i386/kernel/timers/timer.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/i386/kernel/timers/timer.c	2003-05-26 04:41:41.000000000 -0700
@@ -23,10 +23,8 @@
 
 static int __init clock_setup(char* str)
 {
-	if (str) {
-		strncpy(clock_override, str,10);
-		clock_override[9] = '\0';
-	}
+	if (str)
+		strlcpy(clock_override, str, sizeof(clock_override));
 	return 1;
 }
 __setup("clock=", clock_setup);
diff -urN linux-2.5.69-bk18/arch/i386/mach-generic/bigsmp.c linux-2.5.69-bk19/arch/i386/mach-generic/bigsmp.c
--- linux-2.5.69-bk18/arch/i386/mach-generic/bigsmp.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/i386/mach-generic/bigsmp.c	2003-05-26 04:41:41.000000000 -0700
@@ -10,6 +10,7 @@
 #include <linux/smp.h>
 #include <linux/init.h>
 #include <asm/mach-bigsmp/mach_apic.h>
+#include <asm/mach-bigsmp/mach_apicdef.h>
 #include <asm/mach-bigsmp/mach_ipi.h>
 #include <asm/mach-default/mach_mpparse.h>
 
diff -urN linux-2.5.69-bk18/arch/i386/mach-generic/default.c linux-2.5.69-bk19/arch/i386/mach-generic/default.c
--- linux-2.5.69-bk18/arch/i386/mach-generic/default.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/i386/mach-generic/default.c	2003-05-26 04:41:41.000000000 -0700
@@ -10,6 +10,7 @@
 #include <linux/smp.h>
 #include <linux/init.h>
 #include <asm/mach-default/mach_apic.h>
+#include <asm/mach-default/mach_apicdef.h>
 #include <asm/mach-default/mach_ipi.h>
 #include <asm/mach-default/mach_mpparse.h>
 
diff -urN linux-2.5.69-bk18/arch/i386/mach-generic/summit.c linux-2.5.69-bk19/arch/i386/mach-generic/summit.c
--- linux-2.5.69-bk18/arch/i386/mach-generic/summit.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/i386/mach-generic/summit.c	2003-05-26 04:41:41.000000000 -0700
@@ -10,6 +10,7 @@
 #include <linux/smp.h>
 #include <linux/init.h>
 #include <asm/mach-summit/mach_apic.h>
+#include <asm/mach-summit/mach_apicdef.h>
 #include <asm/mach-summit/mach_ipi.h>
 #include <asm/mach-summit/mach_mpparse.h>
 
diff -urN linux-2.5.69-bk18/arch/i386/mm/init.c linux-2.5.69-bk19/arch/i386/mm/init.c
--- linux-2.5.69-bk18/arch/i386/mm/init.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/i386/mm/init.c	2003-05-26 04:41:41.000000000 -0700
@@ -41,7 +41,7 @@
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
 
-struct mmu_gather mmu_gathers[NR_CPUS];
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 unsigned long highstart_pfn, highend_pfn;
 
 static int do_test_wp_bit(void);
diff -urN linux-2.5.69-bk18/arch/ia64/kernel/setup.c linux-2.5.69-bk19/arch/ia64/kernel/setup.c
--- linux-2.5.69-bk18/arch/ia64/kernel/setup.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/ia64/kernel/setup.c	2003-05-26 04:41:41.000000000 -0700
@@ -356,8 +356,7 @@
 	unw_init();
 
 	*cmdline_p = __va(ia64_boot_param->command_line);
-	strncpy(saved_command_line, *cmdline_p, sizeof(saved_command_line));
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';		/* for safety */
+	strlcpy(saved_command_line, *cmdline_p, sizeof(saved_command_line));
 
 	efi_init();
 
diff -urN linux-2.5.69-bk18/arch/ia64/sn/io/klconflib.c linux-2.5.69-bk19/arch/ia64/sn/io/klconflib.c
--- linux-2.5.69-bk18/arch/ia64/sn/io/klconflib.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/arch/ia64/sn/io/klconflib.c	2003-05-26 04:41:41.000000000 -0700
@@ -851,14 +851,12 @@
 		return ;
 
         if  ( (tmp1 = strchr(tmp, ';')) ){
-                strncpy(name, tmp, tmp1-tmp) ;
-                name[tmp1-tmp] = 0 ;
+                strlcpy(name, tmp, tmp1-tmp) ;
         } else {
-                strncpy(name, tmp, (sizeof(name) -1)) ;
-                name[sizeof(name)-1] = 0 ;
+                strlcpy(name, tmp, (sizeof(name))) ;
         }
 
-	strcpy(lb->brd_name, name) ;
+	strlcpy(lb->brd_name, name, sizeof(lb->brd_name)) ;
 }
 
 
diff -urN linux-2.5.69-bk18/arch/ia64/sn/io/l1_command.c linux-2.5.69-bk19/arch/ia64/sn/io/l1_command.c
--- linux-2.5.69-bk18/arch/ia64/sn/io/l1_command.c	2003-05-04 16:53:28.000000000 -0700
+++ linux-2.5.69-bk19/arch/ia64/sn/io/l1_command.c	2003-05-26 04:41:41.000000000 -0700
@@ -718,8 +718,7 @@
 
     for( i = 0; i < numlines; i++ )
     {
-	strncpy( line, chr, L1_DISPLAY_LINE_LENGTH );
-	line[L1_DISPLAY_LINE_LENGTH] = '\0';
+	strlcpy( line, chr, sizeof(line) );
 
 	/* generally we want to leave the first line of the L1 display
 	 * alone (so the L1 can manipulate it).  If you need to be able
diff -urN linux-2.5.69-bk18/arch/ia64/sn/io/sn1/ml_SN_intr.c linux-2.5.69-bk19/arch/ia64/sn/io/sn1/ml_SN_intr.c
--- linux-2.5.69-bk18/arch/ia64/sn/io/sn1/ml_SN_intr.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/arch/ia64/sn/io/sn1/ml_SN_intr.c	2003-05-26 04:41:41.000000000 -0700
@@ -311,14 +311,14 @@
     /* Reserve the level and bump the count. */
     if (rv != -1) {
 	if (reserve) {
-	    int maxlen = sizeof(vecblk->info[bit].ii_name) - 1;
-	    int namelen;
 	    vecblk->info[bit].ii_flags |= (II_RESERVE | resflags);
 	    vecblk->info[bit].ii_owner_dev = owner_dev;
 	    /* Copy in the name. */
-	    namelen = name ? strlen(name) : 0;
-	    strncpy(vecblk->info[bit].ii_name, name, min(namelen, maxlen)); 
-	    vecblk->info[bit].ii_name[maxlen] = '\0';
+	    if (name)
+		strlcpy(vecblk->info[bit].ii_name, name,
+			sizeof(vecblk->info[bit].ii_name));
+	    else
+		vecblk->info[bit].ii_name[0] = '\0';
 	    vecblk->vector_count++;
 	} else {
 	    vecblk->info[bit].ii_flags = 0;	/* Clear all the flags */
@@ -333,7 +333,6 @@
 
 #if defined(DEBUG)
     if (rv >= 0) {
-	    int namelen = name ? strlen(name) : 0;
 	    /* Gather this device - target cpu mapping information
 	     * in a table which can be used later by the idbg "intrmap"
 	     * command
@@ -347,9 +346,10 @@
 		    p->cpuid 	= cpu; 
 		    p->cnodeid 	= cpuid_to_cnodeid(cpu); 
 		    p->bit 	= ip * N_INTPEND_BITS + rv;
-		    strncpy(p->intr_name,
-			    name,
-			    min(MAX_NAME,namelen));
+		    if (name)
+			strlcpy(p->intr_name, name, sizeof(p->intr_name));
+		    else
+			p->intr_name[0] = '\0';
 		    intr_dev_targ_map_size++;
 	    }
 	    mutex_spinunlock(&intr_dev_targ_map_lock,s);
diff -urN linux-2.5.69-bk18/arch/ia64/sn/io/sn2/klconflib.c linux-2.5.69-bk19/arch/ia64/sn/io/sn2/klconflib.c
--- linux-2.5.69-bk18/arch/ia64/sn/io/sn2/klconflib.c	2003-05-04 16:52:50.000000000 -0700
+++ linux-2.5.69-bk19/arch/ia64/sn/io/sn2/klconflib.c	2003-05-26 04:41:41.000000000 -0700
@@ -787,15 +787,12 @@
         if (tmp == NULL)
 		return ;
 
-        if  ( (tmp1 = strchr(tmp, ';')) ){
-                strncpy(name, tmp, tmp1-tmp) ;
-                name[tmp1-tmp] = 0 ;
-        } else {
-                strncpy(name, tmp, (sizeof(name) -1)) ;
-                name[sizeof(name)-1] = 0 ;
-        }
+        if  ( (tmp1 = strchr(tmp, ';')) )
+                strlcpy(name, tmp, tmp1-tmp);
+        else
+                strlcpy(name, tmp, (sizeof(name)));
 
-	strcpy(lb->brd_name, name) ;
+	strlcpy(lb->brd_name, name, sizeof(lb->brd_name)) ;
 }
 
 
diff -urN linux-2.5.69-bk18/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c linux-2.5.69-bk19/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c
--- linux-2.5.69-bk18/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c	2003-05-26 04:41:41.000000000 -0700
@@ -149,7 +149,7 @@
     error = pcibr_slot_attach(pcibr_vhdl, slot, D_PCI_HOT_PLUG_ATTACH,
                               l1_msg, &tmp_up_resp.resp_sub_errno);
 
-    strncpy(tmp_up_resp.resp_l1_msg, l1_msg, L1_QSIZE);
+    strlcpy(tmp_up_resp.resp_l1_msg, l1_msg, L1_QSIZE);
     tmp_up_resp.resp_l1_msg[L1_QSIZE] = '\0';
 
     if (COPYOUT(&tmp_up_resp, reqp->req_respp.up, reqp->req_size)) {
@@ -240,8 +240,8 @@
     error = pcibr_slot_detach(pcibr_vhdl, slot, D_PCI_HOT_PLUG_DETACH,
                               l1_msg, &tmp_down_resp.resp_sub_errno);
 
-    strncpy(tmp_down_resp.resp_l1_msg, l1_msg, L1_QSIZE);
-    tmp_down_resp.resp_l1_msg[L1_QSIZE] = '\0';
+    strlcpy(tmp_down_resp.resp_l1_msg, l1_msg,
+	    sizeof(tmp_down_resp.resp_l1_msg));
 
     shutdown_copyout:
 
diff -urN linux-2.5.69-bk18/arch/m68k/amiga/amiints.c linux-2.5.69-bk19/arch/m68k/amiga/amiints.c
--- linux-2.5.69-bk18/arch/m68k/amiga/amiints.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/amiga/amiints.c	2003-05-26 04:41:41.000000000 -0700
@@ -51,7 +51,7 @@
 #include <asm/amipcmcia.h>
 
 extern int cia_request_irq(struct ciabase *base,int irq,
-                           void (*handler)(int, void *, struct pt_regs *),
+                           irqreturn_t (*handler)(int, void *, struct pt_regs *),
                            unsigned long flags, const char *devname, void *dev_id);
 extern void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id);
 extern void cia_init_IRQ(struct ciabase *base);
@@ -70,9 +70,10 @@
 
 static short ami_ablecount[AMI_IRQS];
 
-static void ami_badint(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t ami_badint(int irq, void *dev_id, struct pt_regs *fp)
 {
 	num_spurious += 1;
+	return IRQ_NONE;
 }
 
 /*
@@ -183,7 +184,7 @@
  */
 
 int amiga_request_irq(unsigned int irq,
-		      void (*handler)(int, void *, struct pt_regs *),
+		      irqreturn_t (*handler)(int, void *, struct pt_regs *),
                       unsigned long flags, const char *devname, void *dev_id)
 {
 	irq_node_t *node;
@@ -368,7 +369,7 @@
  * The builtin Amiga hardware interrupt handlers.
  */
 
-static void ami_int1(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp)
 {
 	unsigned short ints = custom.intreqr & custom.intenar;
 
@@ -389,9 +390,10 @@
 		custom.intreq = IF_SOFT;
 		amiga_do_irq(IRQ_AMIGA_SOFT, fp);
 	}
+	return IRQ_HANDLED;
 }
 
-static void ami_int3(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp)
 {
 	unsigned short ints = custom.intreqr & custom.intenar;
 
@@ -410,9 +412,10 @@
 	/* if a vertical blank interrupt */
 	if (ints & IF_VERTB)
 		amiga_do_irq_list(IRQ_AMIGA_VERTB, fp);
+	return IRQ_HANDLED;
 }
 
-static void ami_int4(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp)
 {
 	unsigned short ints = custom.intreqr & custom.intenar;
 
@@ -439,9 +442,10 @@
 		custom.intreq = IF_AUD3;
 		amiga_do_irq(IRQ_AMIGA_AUD3, fp);
 	}
+	return IRQ_HANDLED;
 }
 
-static void ami_int5(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp)
 {
 	unsigned short ints = custom.intreqr & custom.intenar;
 
@@ -456,14 +460,15 @@
 		custom.intreq = IF_DSKSYN;
 		amiga_do_irq(IRQ_AMIGA_DSKSYN, fp);
 	}
+	return IRQ_HANDLED;
 }
 
-static void ami_int7(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t ami_int7(int irq, void *dev_id, struct pt_regs *fp)
 {
 	panic ("level 7 interrupt received\n");
 }
 
-void (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
+irqreturn_t (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
 	ami_badint, ami_int1, ami_badint, ami_int3,
 	ami_int4, ami_int5, ami_badint, ami_int7
 };
diff -urN linux-2.5.69-bk18/arch/m68k/amiga/cia.c linux-2.5.69-bk19/arch/m68k/amiga/cia.c
--- linux-2.5.69-bk18/arch/m68k/amiga/cia.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/amiga/cia.c	2003-05-26 04:41:41.000000000 -0700
@@ -90,7 +90,7 @@
 }
 
 int cia_request_irq(struct ciabase *base, unsigned int irq,
-                    void (*handler)(int, void *, struct pt_regs *),
+                    irqreturn_t (*handler)(int, void *, struct pt_regs *),
                     unsigned long flags, const char *devname, void *dev_id)
 {
 	unsigned char mask;
@@ -120,7 +120,7 @@
 	cia_able_irq(base, 1 << irq);
 }
 
-static void cia_handler(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t cia_handler(int irq, void *dev_id, struct pt_regs *fp)
 {
 	struct ciabase *base = (struct ciabase *)dev_id;
 	int mach_irq, i;
@@ -138,6 +138,7 @@
 		ints >>= 1;
 	}
 	amiga_do_irq_list(base->server_irq, fp);
+	return IRQ_HANDLED;
 }
 
 void __init cia_init_IRQ(struct ciabase *base)
diff -urN linux-2.5.69-bk18/arch/m68k/amiga/config.c linux-2.5.69-bk19/arch/m68k/amiga/config.c
--- linux-2.5.69-bk18/arch/m68k/amiga/config.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/amiga/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -71,12 +71,12 @@
 
 extern char m68k_debug_device[];
 
-static void amiga_sched_init(void (*handler)(int, void *, struct pt_regs *));
+static void amiga_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
 /* amiga specific irq functions */
 extern void amiga_init_IRQ (void);
-extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *);
+extern irqreturn_t (*amiga_default_handler[]) (int, void *, struct pt_regs *);
 extern int amiga_request_irq (unsigned int irq,
-			      void (*handler)(int, void *, struct pt_regs *),
+			      irqreturn_t (*handler)(int, void *, struct pt_regs *),
                               unsigned long flags, const char *devname,
 			      void *dev_id);
 extern void amiga_free_irq (unsigned int irq, void *dev_id);
@@ -491,7 +491,7 @@
 
 static unsigned short jiffy_ticks;
 
-static void __init amiga_sched_init(void (*timer_routine)(int, void *,
+static void __init amiga_sched_init(irqreturn_t (*timer_routine)(int, void *,
 							  struct pt_regs *))
 {
 	static struct resource sched_res = {
diff -urN linux-2.5.69-bk18/arch/m68k/apollo/config.c linux-2.5.69-bk19/arch/m68k/apollo/config.c
--- linux-2.5.69-bk18/arch/m68k/apollo/config.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/apollo/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -26,9 +26,9 @@
 u_long timer_physaddr;
 u_long apollo_model;
 
-extern void dn_sched_init(void (*handler)(int,void *,struct pt_regs *));
+extern void dn_sched_init(irqreturn_t (*handler)(int,void *,struct pt_regs *));
 extern void dn_init_IRQ(void);
-extern int dn_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+extern int dn_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
 extern void dn_free_irq(unsigned int irq, void *dev_id);
 extern void dn_enable_irq(unsigned int);
 extern void dn_disable_irq(unsigned int);
@@ -41,12 +41,12 @@
 extern struct fb_info *dn_fb_init(long *);
 extern void dn_dummy_debug_init(void);
 extern void dn_dummy_video_setup(char *,int *);
-extern void dn_process_int(int irq, struct pt_regs *fp);
+extern irqreturn_t dn_process_int(int irq, struct pt_regs *fp);
 #ifdef CONFIG_HEARTBEAT
 static void dn_heartbeat(int on);
 #endif
-static void dn_timer_int(int irq,void *, struct pt_regs *);
-static void (*sched_timer_handler)(int, void *, struct pt_regs *)=NULL;
+static irqreturn_t dn_timer_int(int irq,void *, struct pt_regs *);
+static irqreturn_t (*sched_timer_handler)(int, void *, struct pt_regs *)=NULL;
 static void dn_get_model(char *model);
 static const char *apollo_models[] = {
 	"DN3000 (Otter)",
@@ -195,7 +195,7 @@
 
 }		
 
-void dn_timer_int(int irq, void *dev_id, struct pt_regs *fp) {
+irqreturn_t dn_timer_int(int irq, void *dev_id, struct pt_regs *fp) {
 
 	volatile unsigned char x;
 
@@ -204,9 +204,10 @@
 	x=*(volatile unsigned char *)(timer+3);
 	x=*(volatile unsigned char *)(timer+5);
 
+	return IRQ_HANDLED;
 }
 
-void dn_sched_init(void (*timer_routine)(int, void *, struct pt_regs *)) {
+void dn_sched_init(irqreturn_t (*timer_routine)(int, void *, struct pt_regs *)) {
 
 	/* program timer 1 */       	
 	*(volatile unsigned char *)(timer+3)=0x01;
diff -urN linux-2.5.69-bk18/arch/m68k/apollo/dn_ints.c linux-2.5.69-bk19/arch/m68k/apollo/dn_ints.c
--- linux-2.5.69-bk18/arch/m68k/apollo/dn_ints.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/apollo/dn_ints.c	2003-05-26 04:41:41.000000000 -0700
@@ -14,19 +14,20 @@
 
 static irq_handler_t dn_irqs[16];
 
-void dn_process_int(int irq, struct pt_regs *fp) {
-
+irqreturn_t dn_process_int(int irq, struct pt_regs *fp)
+{
+  irqreturn_t res = IRQ_NONE;
 
   if(dn_irqs[irq-160].handler) {
-    dn_irqs[irq-160].handler(irq,dn_irqs[irq-160].dev_id,fp);
-  }
-  else {
+    res = dn_irqs[irq-160].handler(irq,dn_irqs[irq-160].dev_id,fp);
+  } else {
     printk("spurious irq %d occurred\n",irq);
   }
 
   *(volatile unsigned char *)(pica)=0x20;
   *(volatile unsigned char *)(picb)=0x20;
 
+  return res;
 }
 
 void dn_init_IRQ(void) {
@@ -42,7 +43,7 @@
   
 }
 
-int dn_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) {
+int dn_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) {
 
   if((irq<0) || (irq>15)) {
     printk("Trying to request illegal IRQ\n");
diff -urN linux-2.5.69-bk18/arch/m68k/atari/ataints.c linux-2.5.69-bk19/arch/m68k/atari/ataints.c
--- linux-2.5.69-bk18/arch/m68k/atari/ataints.c	2003-05-04 16:53:03.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/atari/ataints.c	2003-05-26 04:41:41.000000000 -0700
@@ -110,7 +110,7 @@
 typedef void (*asm_irq_handler)(void);
 
 struct irqhandler {
-	void	(*handler)(int, void *, struct pt_regs *);
+	irqreturn_t (*handler)(int, void *, struct pt_regs *);
 	void	*dev_id;
 };
 
@@ -404,12 +404,13 @@
 }
 
 
-static void atari_call_irq_list( int irq, void *dev_id, struct pt_regs *fp )
+static irqreturn_t atari_call_irq_list( int irq, void *dev_id, struct pt_regs *fp )
 {
 	irq_node_t *node;
 
 	for (node = (irq_node_t *)dev_id; node; node = node->next)
 		node->handler(irq, node->dev_id, fp);
+	return IRQ_HANDLED;
 }
 
 
@@ -419,7 +420,7 @@
  *                     If the addition was successful, it returns 0.
  */
 
-int atari_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+int atari_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
                       unsigned long flags, const char *devname, void *dev_id)
 {
 	int vector;
diff -urN linux-2.5.69-bk18/arch/m68k/atari/config.c linux-2.5.69-bk19/arch/m68k/atari/config.c
--- linux-2.5.69-bk18/arch/m68k/atari/config.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/atari/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -60,7 +60,7 @@
 
 /* atari specific irq functions */
 extern void atari_init_IRQ (void);
-extern int atari_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+extern int atari_request_irq (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
                               unsigned long flags, const char *devname, void *dev_id);
 extern void atari_free_irq (unsigned int irq, void *dev_id);
 extern void atari_enable_irq (unsigned int);
@@ -72,7 +72,7 @@
 #endif
 
 /* atari specific timer functions (in time.c) */
-extern void atari_sched_init(void (*)(int, void *, struct pt_regs *));
+extern void atari_sched_init(irqreturn_t (*)(int, void *, struct pt_regs *));
 extern unsigned long atari_gettimeoffset (void);
 extern int atari_mste_hwclk (int, struct rtc_time *);
 extern int atari_tt_hwclk (int, struct rtc_time *);
@@ -188,8 +188,7 @@
     char *args = switches;
 
     /* copy string to local array, strsep works destructively... */
-    strncpy( switches, str, len );
-    switches[len] = 0;
+    strlcpy( switches, str, sizeof(switches) );
     atari_switches = 0;
 
     /* parse the options */
diff -urN linux-2.5.69-bk18/arch/m68k/atari/stdma.c linux-2.5.69-bk19/arch/m68k/atari/stdma.c
--- linux-2.5.69-bk18/arch/m68k/atari/stdma.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/atari/stdma.c	2003-05-26 04:41:41.000000000 -0700
@@ -43,8 +43,8 @@
 
 static int stdma_locked = 0;			/* the semaphore */
 						/* int func to be called */
-static void (*stdma_isr)(int, void *, struct pt_regs *) = NULL;
-static void	*stdma_isr_data = NULL;		/* data passed to isr */
+static irqreturn_t (*stdma_isr)(int, void *, struct pt_regs *) = NULL;
+static void *stdma_isr_data = NULL;		/* data passed to isr */
 static DECLARE_WAIT_QUEUE_HEAD(stdma_wait);	/* wait queue for ST-DMA */
 
 
@@ -52,7 +52,7 @@
 
 /***************************** Prototypes *****************************/
 
-static void stdma_int (int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t stdma_int (int irq, void *dummy, struct pt_regs *fp);
 
 /************************* End of Prototypes **************************/
 
@@ -74,7 +74,8 @@
  *
  */
 
-void stdma_lock(void (*handler)(int, void *, struct pt_regs *), void *data)
+void stdma_lock(irqreturn_t (*handler)(int, void *, struct pt_regs *),
+		void *data)
 {
 	unsigned long flags;
 
@@ -187,8 +188,9 @@
  *
  */
 
-static void stdma_int(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t stdma_int(int irq, void *dummy, struct pt_regs *fp)
 {
   if (stdma_isr)
       (*stdma_isr)(irq, stdma_isr_data, fp);
+  return IRQ_HANDLED;
 }
diff -urN linux-2.5.69-bk18/arch/m68k/atari/time.c linux-2.5.69-bk19/arch/m68k/atari/time.c
--- linux-2.5.69-bk18/arch/m68k/atari/time.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/atari/time.c	2003-05-26 04:41:41.000000000 -0700
@@ -20,7 +20,7 @@
 #include <asm/rtc.h>
 
 void __init
-atari_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))
+atari_sched_init(irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
 {
     /* set Timer C data Register */
     mfp.tim_dt_c = INT_TICKS;
diff -urN linux-2.5.69-bk18/arch/m68k/bvme6000/bvmeints.c linux-2.5.69-bk19/arch/m68k/bvme6000/bvmeints.c
--- linux-2.5.69-bk18/arch/m68k/bvme6000/bvmeints.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/bvme6000/bvmeints.c	2003-05-26 04:41:41.000000000 -0700
@@ -21,14 +21,14 @@
 #include <asm/irq.h>
 #include <asm/traps.h>
 
-static void bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp);
+static irqreturn_t bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp);
 
 /*
  * This should ideally be 4 elements only, for speed.
  */
 
 static struct {
-	void		(*handler)(int, void *, struct pt_regs *);
+	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
 	unsigned long	flags;
 	void		*dev_id;
 	const char	*devname;
@@ -60,7 +60,7 @@
 }
 
 int bvme6000_request_irq(unsigned int irq,
-		void (*handler)(int, void *, struct pt_regs *),
+		irqreturn_t (*handler)(int, void *, struct pt_regs *),
                 unsigned long flags, const char *devname, void *dev_id)
 {
 	if (irq > 255) {
@@ -117,14 +117,15 @@
 	irq_tab[irq].devname = NULL;
 }
 
-void bvme6000_process_int (unsigned long vec, struct pt_regs *fp)
+irqreturn_t bvme6000_process_int (unsigned long vec, struct pt_regs *fp)
 {
-	if (vec > 255)
+	if (vec > 255) {
 		printk ("bvme6000_process_int: Illegal vector %ld", vec);
-	else
-	{
+		return IRQ_NONE;
+	} else {
 		irq_tab[vec].count++;
 		irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp);
+		return IRQ_HANDLED;
 	}
 }
 
@@ -142,9 +143,10 @@
 }
 
 
-static void bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp)
 {
 	printk ("Unknown interrupt 0x%02x\n", irq);
+	return IRQ_NONE;
 }
 
 void bvme6000_enable_irq (unsigned int irq)
diff -urN linux-2.5.69-bk18/arch/m68k/bvme6000/config.c linux-2.5.69-bk19/arch/m68k/bvme6000/config.c
--- linux-2.5.69-bk18/arch/m68k/bvme6000/config.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/bvme6000/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -36,7 +36,7 @@
 #include <asm/machdep.h>
 #include <asm/bvme6000hw.h>
 
-extern void bvme6000_process_int (int level, struct pt_regs *regs);
+extern irqreturn_t bvme6000_process_int (int level, struct pt_regs *regs);
 extern void bvme6000_init_IRQ (void);
 extern void bvme6000_free_irq (unsigned int, void *);
 extern int  show_bvme6000_interrupts(struct seq_file *, void *);
@@ -44,8 +44,8 @@
 extern void bvme6000_disable_irq (unsigned int);
 static void bvme6000_get_model(char *model);
 static int  bvme6000_get_hardware_list(char *buffer);
-extern int  bvme6000_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
-extern void bvme6000_sched_init(void (*handler)(int, void *, struct pt_regs *));
+extern int  bvme6000_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+extern void bvme6000_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
 extern unsigned long bvme6000_gettimeoffset (void);
 extern int bvme6000_hwclk (int, struct rtc_time *);
 extern int bvme6000_set_clock_mmss (unsigned long);
@@ -59,7 +59,7 @@
 /* Save tick handler routine pointer, will point to do_timer() in
  * kernel/sched.c, called via bvme6000_process_int() */
 
-static void (*tick_handler)(int, void *, struct pt_regs *);
+static irqreturn_t (*tick_handler)(int, void *, struct pt_regs *);
 
 
 int bvme6000_parse_bootinfo(const struct bi_record *bi)
@@ -159,7 +159,7 @@
 }
 
 
-void bvme6000_abort_int (int irq, void *dev_id, struct pt_regs *fp)
+irqreturn_t bvme6000_abort_int (int irq, void *dev_id, struct pt_regs *fp)
 {
         unsigned long *new = (unsigned long *)vectors;
         unsigned long *old = (unsigned long *)0xf8000000;
@@ -172,17 +172,18 @@
         *(new+9) = *(old+9);            /* Trace */
         *(new+47) = *(old+47);          /* Trap #15 */
         *(new+0x1f) = *(old+0x1f);      /* ABORT switch */
+	return IRQ_HANDLED;
 }
 
 
-static void bvme6000_timer_int (int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t bvme6000_timer_int (int irq, void *dev_id, struct pt_regs *fp)
 {
     volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
     unsigned char msr = rtc->msr & 0xc0;
 
     rtc->msr = msr | 0x20;		/* Ack the interrupt */
 
-    tick_handler(irq, dev_id, fp);
+    return tick_handler(irq, dev_id, fp);
 }
 
 /*
@@ -194,7 +195,7 @@
  * so divide by 8 to get the microsecond result.
  */
 
-void bvme6000_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
+void bvme6000_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
 {
     volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
     unsigned char msr = rtc->msr & 0xc0;
diff -urN linux-2.5.69-bk18/arch/m68k/hp300/config.c linux-2.5.69-bk19/arch/m68k/hp300/config.c
--- linux-2.5.69-bk18/arch/m68k/hp300/config.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/hp300/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -23,7 +23,7 @@
 #include "time.h"
 
 extern void hp300_reset(void);
-extern void (*hp300_default_handler[])(int, void *, struct pt_regs *);
+extern irqreturn_t (*hp300_default_handler[])(int, void *, struct pt_regs *);
 extern int show_hp300_interrupts(struct seq_file *, void *);
 
 #ifdef CONFIG_HEARTBEAT
diff -urN linux-2.5.69-bk18/arch/m68k/hp300/ints.c linux-2.5.69-bk19/arch/m68k/hp300/ints.c
--- linux-2.5.69-bk18/arch/m68k/hp300/ints.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/hp300/ints.c	2003-05-26 04:41:41.000000000 -0700
@@ -42,7 +42,7 @@
 static spinlock_t irqlist_lock;
 
 /* This handler receives all interrupts, dispatching them to the registered handlers */
-static void hp300_int_handler(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t hp300_int_handler(int irq, void *dev_id, struct pt_regs *fp)
 {
         irq_node_t *t;
         /* We just give every handler on the chain an opportunity to handle
@@ -54,9 +54,10 @@
          * etc, in here. Note that currently we can't tell whether or not
          * a handler handles the interrupt, though. 
          */
+	return IRQ_HANDLED;
 }
 
-void (*hp300_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
+irqreturn_t (*hp300_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
 	hp300_int_handler, hp300_int_handler, hp300_int_handler, hp300_int_handler,
 	hp300_int_handler, hp300_int_handler, hp300_int_handler, NULL
 };
@@ -70,7 +71,7 @@
  * matters (eg the dreaded FIFOless UART...)
  */
 int hp300_request_irq(unsigned int irq,
-                      void (*handler) (int, void *, struct pt_regs *),
+                      irqreturn_t (*handler) (int, void *, struct pt_regs *),
                       unsigned long flags, const char *devname, void *dev_id)
 {
         irq_node_t *t, *n = new_irq_node();
diff -urN linux-2.5.69-bk18/arch/m68k/hp300/ints.h linux-2.5.69-bk19/arch/m68k/hp300/ints.h
--- linux-2.5.69-bk18/arch/m68k/hp300/ints.h	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/hp300/ints.h	2003-05-26 04:41:41.000000000 -0700
@@ -2,7 +2,7 @@
 extern void (*hp300_handlers[8])(int, void *, struct pt_regs *);
 extern void hp300_free_irq(unsigned int irq, void *dev_id);
 extern int hp300_request_irq(unsigned int irq,
-		void (*handler) (int, void *, struct pt_regs *),
+		irqreturn_t (*handler) (int, void *, struct pt_regs *),
 		unsigned long flags, const char *devname, void *dev_id);
 
 /* number of interrupts, includes 0 (what's that?) */
diff -urN linux-2.5.69-bk18/arch/m68k/hp300/time.c linux-2.5.69-bk19/arch/m68k/hp300/time.c
--- linux-2.5.69-bk18/arch/m68k/hp300/time.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/hp300/time.c	2003-05-26 04:41:41.000000000 -0700
@@ -36,13 +36,13 @@
 
 #define INTVAL ((10000 / 4) - 1)
 
-static void hp300_tick(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t hp300_tick(int irq, void *dev_id, struct pt_regs *regs)
 {
   unsigned long tmp;
-  void (*vector)(int, void *, struct pt_regs *) = dev_id;
+  irqreturn_t (*vector)(int, void *, struct pt_regs *) = dev_id;
   in_8(CLOCKBASE + CLKSR);
   asm volatile ("movpw %1@(5),%0" : "=d" (tmp) : "a" (CLOCKBASE));
-  vector(irq, NULL, regs);
+  return vector(irq, NULL, regs);
 }
 
 unsigned long hp300_gettimeoffset(void)
@@ -61,7 +61,7 @@
   return (USECS_PER_JIFFY * ticks) / INTVAL;
 }
 
-void __init hp300_sched_init(void (*vector)(int, void *, struct pt_regs *))
+void __init hp300_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *))
 {
   out_8(CLOCKBASE + CLKCR2, 0x1);		/* select CR1 */
   out_8(CLOCKBASE + CLKCR1, 0x1);		/* reset */
diff -urN linux-2.5.69-bk18/arch/m68k/hp300/time.h linux-2.5.69-bk19/arch/m68k/hp300/time.h
--- linux-2.5.69-bk18/arch/m68k/hp300/time.h	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/hp300/time.h	2003-05-26 04:41:41.000000000 -0700
@@ -1,4 +1,4 @@
-extern void hp300_sched_init(void (*vector)(int, void *, struct pt_regs *));
+extern void hp300_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *));
 extern unsigned long hp300_gettimeoffset (void);
 
 
diff -urN linux-2.5.69-bk18/arch/m68k/kernel/ints.c linux-2.5.69-bk19/arch/m68k/kernel/ints.c
--- linux-2.5.69-bk18/arch/m68k/kernel/ints.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/kernel/ints.c	2003-05-26 04:41:41.000000000 -0700
@@ -60,14 +60,14 @@
 static void dummy_enable_irq(unsigned int irq);
 static void dummy_disable_irq(unsigned int irq);
 static int dummy_request_irq(unsigned int irq,
-		void (*handler) (int, void *, struct pt_regs *),
+		irqreturn_t (*handler) (int, void *, struct pt_regs *),
 		unsigned long flags, const char *devname, void *dev_id);
 static void dummy_free_irq(unsigned int irq, void *dev_id);
 
 void (*enable_irq) (unsigned int) = dummy_enable_irq;
 void (*disable_irq) (unsigned int) = dummy_disable_irq;
 
-int (*mach_request_irq) (unsigned int, void (*)(int, void *, struct pt_regs *),
+int (*mach_request_irq) (unsigned int, irqreturn_t (*)(int, void *, struct pt_regs *),
                       unsigned long, const char *, void *) = dummy_request_irq;
 void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
 
@@ -121,7 +121,7 @@
  * include/asm/irq.h.
  */
 int request_irq(unsigned int irq,
-		void (*handler) (int, void *, struct pt_regs *),
+		irqreturn_t (*handler) (int, void *, struct pt_regs *),
 		unsigned long flags, const char *devname, void *dev_id)
 {
 	return mach_request_irq(irq, handler, flags, devname, dev_id);
@@ -133,7 +133,7 @@
 }
 
 int sys_request_irq(unsigned int irq, 
-                    void (*handler)(int, void *, struct pt_regs *), 
+                    irqreturn_t (*handler)(int, void *, struct pt_regs *), 
                     unsigned long flags, const char *devname, void *dev_id)
 {
 	if (irq < IRQ1 || irq > IRQ7) {
@@ -215,7 +215,7 @@
 }
 
 static int dummy_request_irq(unsigned int irq,
-		void (*handler) (int, void *, struct pt_regs *),
+		irqreturn_t (*handler) (int, void *, struct pt_regs *),
 		unsigned long flags, const char *devname, void *dev_id)
 {
 	printk("calling uninitialized request_irq()\n");
diff -urN linux-2.5.69-bk18/arch/m68k/kernel/ptrace.c linux-2.5.69-bk19/arch/m68k/kernel/ptrace.c
--- linux-2.5.69-bk18/arch/m68k/kernel/ptrace.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/kernel/ptrace.c	2003-05-26 04:41:41.000000000 -0700
@@ -135,14 +135,9 @@
 		ret = ptrace_attach(child);
 		goto out_tsk;
 	}
-	ret = -ESRCH;
-	if (!(child->ptrace & PT_PTRACED))
-		goto out_tsk;
-	if (child->state != TASK_STOPPED) {
-		if (request != PTRACE_KILL)
-			goto out_tsk;
-	}
-	if (child->parent != current)
+
+	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	if (ret < 0)
 		goto out_tsk;
 
 	switch (request) {
diff -urN linux-2.5.69-bk18/arch/m68k/kernel/setup.c linux-2.5.69-bk19/arch/m68k/kernel/setup.c
--- linux-2.5.69-bk18/arch/m68k/kernel/setup.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/kernel/setup.c	2003-05-26 04:41:41.000000000 -0700
@@ -67,14 +67,14 @@
 
 char m68k_debug_device[6] = "";
 
-void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
+void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
 /* machine dependent irq functions */
 void (*mach_init_IRQ) (void) __initdata = NULL;
-void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
+irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
 void (*mach_get_model) (char *model) = NULL;
 int (*mach_get_hardware_list) (char *buffer) = NULL;
 int (*mach_get_irq_list) (struct seq_file *, void *) = NULL;
-void (*mach_process_int) (int, struct pt_regs *) = NULL;
+irqreturn_t (*mach_process_int) (int, struct pt_regs *) = NULL;
 /* machine dependent timer functions */
 unsigned long (*mach_gettimeoffset) (void);
 int (*mach_hwclk) (int, struct rtc_time*) = NULL;
@@ -159,8 +159,7 @@
 		break;
 
 	    case BI_COMMAND_LINE:
-		strncpy(m68k_command_line, (const char *)data, CL_SIZE);
-		m68k_command_line[CL_SIZE-1] = '\0';
+		strlcpy(m68k_command_line, (const char *)data, sizeof(m68k_command_line));
 		break;
 
 	    default:
@@ -255,8 +254,7 @@
 	for( p = *cmdline_p; p && *p; ) {
 	    i = 0;
 	    if (!strncmp( p, "debug=", 6 )) {
-		strncpy( m68k_debug_device, p+6, sizeof(m68k_debug_device)-1 );
-		m68k_debug_device[sizeof(m68k_debug_device)-1] = 0;
+		strlcpy( m68k_debug_device, p+6, sizeof(m68k_debug_device) );
 		if ((q = strchr( m68k_debug_device, ' ' ))) *q = 0;
 		i = 1;
 	    }
diff -urN linux-2.5.69-bk18/arch/m68k/kernel/sys_m68k.c linux-2.5.69-bk19/arch/m68k/kernel/sys_m68k.c
--- linux-2.5.69-bk18/arch/m68k/kernel/sys_m68k.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/kernel/sys_m68k.c	2003-05-26 04:41:41.000000000 -0700
@@ -202,7 +202,7 @@
 			return sys_semctl (first, second, third, fourth);
 			}
 		default:
-			return -EINVAL;
+			return -ENOSYS;
 		}
 	if (call <= MSGCTL) 
 		switch (call) {
@@ -233,7 +233,7 @@
 			return sys_msgctl (first, second,
 					   (struct msqid_ds *) ptr);
 		default:
-			return -EINVAL;
+			return -ENOSYS;
 		}
 	if (call <= SHMCTL) 
 		switch (call) {
@@ -256,7 +256,7 @@
 			return sys_shmctl (first, second,
 					   (struct shmid_ds *) ptr);
 		default:
-			return -EINVAL;
+			return -ENOSYS;
 		}
 
 	return -EINVAL;
diff -urN linux-2.5.69-bk18/arch/m68k/kernel/time.c linux-2.5.69-bk19/arch/m68k/kernel/time.c
--- linux-2.5.69-bk18/arch/m68k/kernel/time.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/kernel/time.c	2003-05-26 04:41:41.000000000 -0700
@@ -57,7 +57,7 @@
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-static void timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
+static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
 {
 	do_timer(regs);
 
@@ -87,6 +87,7 @@
 	    }
 	}
 #endif /* CONFIG_HEARTBEAT */
+	return IRQ_HANDLED;
 }
 
 void time_init(void)
diff -urN linux-2.5.69-bk18/arch/m68k/mac/baboon.c linux-2.5.69-bk19/arch/m68k/mac/baboon.c
--- linux-2.5.69-bk18/arch/m68k/mac/baboon.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/mac/baboon.c	2003-05-26 04:41:41.000000000 -0700
@@ -25,7 +25,7 @@
 int baboon_present,baboon_active;
 volatile struct baboon *baboon;
 
-void baboon_irq(int, void *, struct pt_regs *);
+irqreturn_t baboon_irq(int, void *, struct pt_regs *);
 
 #if 0
 extern int macide_ack_intr(struct ata_channel *);
@@ -64,7 +64,7 @@
  * Baboon interrupt handler. This works a lot like a VIA.
  */
 
-void baboon_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t baboon_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int irq_bit,i;
 	unsigned char events;
@@ -75,7 +75,8 @@
 		(uint) baboon->mb_status,  baboon_active);
 #endif
 
-	if (!(events = baboon->mb_ifr & 0x07)) return;
+	if (!(events = baboon->mb_ifr & 0x07))
+		return IRQ_NONE;
 
 	for (i = 0, irq_bit = 1 ; i < 3 ; i++, irq_bit <<= 1) {
 	        if (events & irq_bit/* & baboon_active*/) {
@@ -90,6 +91,7 @@
 	/* for now we need to smash all interrupts */
 	baboon->mb_ifr &= ~events;
 #endif
+	return IRQ_HANDLED;
 }
 
 void baboon_irq_enable(int irq) {
diff -urN linux-2.5.69-bk18/arch/m68k/mac/config.c linux-2.5.69-bk19/arch/m68k/mac/config.c
--- linux-2.5.69-bk18/arch/m68k/mac/config.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/mac/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -72,7 +72,7 @@
 extern void iop_preinit(void);
 extern void iop_init(void);
 extern void via_init(void);
-extern void via_init_clock(void (*func)(int, void *, struct pt_regs *));
+extern void via_init_clock(irqreturn_t (*func)(int, void *, struct pt_regs *));
 extern void via_flush_cache(void);
 extern void oss_init(void);
 extern void psc_init(void);
@@ -94,7 +94,7 @@
 	mac_reset();
 }
 
-static void mac_sched_init(void (*vector)(int, void *, struct pt_regs *))
+static void mac_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *))
 {
 	via_init_clock(vector);
 }
@@ -106,9 +106,9 @@
 }
 #endif
 
-extern void mac_default_handler(int, void *, struct pt_regs *);
+extern irqreturn_t mac_default_handler(int, void *, struct pt_regs *);
 
-void (*mac_handlers[8])(int, void *, struct pt_regs *)=
+irqreturn_t (*mac_handlers[8])(int, void *, struct pt_regs *)=
 {
 	mac_default_handler,
 	mac_default_handler,
diff -urN linux-2.5.69-bk18/arch/m68k/mac/iop.c linux-2.5.69-bk19/arch/m68k/mac/iop.c
--- linux-2.5.69-bk18/arch/m68k/mac/iop.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/mac/iop.c	2003-05-26 04:41:41.000000000 -0700
@@ -153,7 +153,7 @@
 static struct iop_msg *iop_send_queue[NUM_IOPS][NUM_IOP_CHAN];
 static struct listener iop_listeners[NUM_IOPS][NUM_IOP_CHAN];
 
-void iop_ism_irq(int, void *, struct pt_regs *);
+irqreturn_t iop_ism_irq(int, void *, struct pt_regs *);
 
 extern void oss_irq_enable(int);
 
@@ -585,7 +585,7 @@
  * Handle an ISM IOP interrupt
  */
 
-void iop_ism_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t iop_ism_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
 	uint iop_num = (uint) dev_id;
 	volatile struct mac_iop *iop = iop_base[iop_num];
@@ -636,7 +636,7 @@
 		printk("\n");
 #endif
 	}
-
+	return IRQ_HANDLED;
 }
 
 #ifdef CONFIG_PROC_FS
diff -urN linux-2.5.69-bk18/arch/m68k/mac/macints.c linux-2.5.69-bk19/arch/m68k/mac/macints.c
--- linux-2.5.69-bk18/arch/m68k/mac/macints.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/mac/macints.c	2003-05-26 04:41:41.000000000 -0700
@@ -217,10 +217,9 @@
  * console_loglevel determines NMI handler function
  */
 
-extern void mac_bang(int, void *, struct pt_regs *);
-
-void mac_nmi_handler(int, void *, struct pt_regs *);
-void mac_debug_handler(int, void *, struct pt_regs *);
+extern irqreturn_t mac_bang(int, void *, struct pt_regs *);
+irqreturn_t mac_nmi_handler(int, void *, struct pt_regs *);
+irqreturn_t mac_debug_handler(int, void *, struct pt_regs *);
 
 /* #define DEBUG_MACINTS */
 
@@ -499,7 +498,7 @@
  */
  
 int mac_request_irq(unsigned int irq,
-		    void (*handler)(int, void *, struct pt_regs *),
+		    irqreturn_t (*handler)(int, void *, struct pt_regs *),
 		    unsigned long flags, const char *devname, void *dev_id)
 {
 	irq_node_t *node;
@@ -647,18 +646,19 @@
 
 static int num_debug[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 
-void mac_debug_handler(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t mac_debug_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 	if (num_debug[irq] < 10) {
 		printk("DEBUG: Unexpected IRQ %d\n", irq);
 		num_debug[irq]++;
 	}
+	return IRQ_HANDLED;
 }
 
 static int in_nmi = 0;
 static volatile int nmi_hold = 0;
 
-void mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp)
+irqreturn_t mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp)
 {
 	int i;
 	/* 
@@ -703,6 +703,7 @@
 #endif
 	}
 	in_nmi--;
+	return IRQ_HANDLED;
 }
 
 /*
diff -urN linux-2.5.69-bk18/arch/m68k/mac/oss.c linux-2.5.69-bk19/arch/m68k/mac/oss.c
--- linux-2.5.69-bk18/arch/m68k/mac/oss.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/mac/oss.c	2003-05-26 04:41:41.000000000 -0700
@@ -30,11 +30,11 @@
 int oss_present;
 volatile struct mac_oss *oss;
 
-void oss_irq(int, void *, struct pt_regs *);
-void oss_nubus_irq(int, void *, struct pt_regs *);
+irqreturn_t oss_irq(int, void *, struct pt_regs *);
+irqreturn_t oss_nubus_irq(int, void *, struct pt_regs *);
 
-extern void via1_irq(int, void *, struct pt_regs *);
-extern void mac_scc_dispatch(int, void *, struct pt_regs *);
+extern irqreturn_t via1_irq(int, void *, struct pt_regs *);
+extern irqreturn_t mac_scc_dispatch(int, void *, struct pt_regs *);
 
 /*
  * Initialize the OSS
@@ -92,12 +92,13 @@
  * and SCSI; everything else is routed to its own autovector IRQ.
  */
  
-void oss_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t oss_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int events;
 
 	events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI);
-	if (!events) return;
+	if (!events)
+		return IRQ_NONE;
 
 #ifdef DEBUG_IRQS	
 	if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) {
@@ -118,6 +119,7 @@
 	} else {
 		/* FIXME: error check here? */
 	}
+	return IRQ_HANDLED;
 }
 
 /*
@@ -126,12 +128,13 @@
  * Unlike the VIA/RBV this is on its own autovector interrupt level.
  */
 
-void oss_nubus_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t oss_nubus_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int events, irq_bit, i;
 
 	events = oss->irq_pending & OSS_IP_NUBUS;
-	if (!events) return;
+	if (!events)
+		return IRQ_NONE;
 
 #ifdef DEBUG_NUBUS_INT
 	if (console_loglevel > 7) {
@@ -148,6 +151,7 @@
 			oss->irq_level[i] = OSS_IRQLEV_NUBUS;
 		}
 	}
+	return IRQ_HANDLED;
 }
 
 /*
diff -urN linux-2.5.69-bk18/arch/m68k/mac/psc.c linux-2.5.69-bk19/arch/m68k/mac/psc.c
--- linux-2.5.69-bk18/arch/m68k/mac/psc.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/mac/psc.c	2003-05-26 04:41:41.000000000 -0700
@@ -30,7 +30,7 @@
 int psc_present;
 volatile __u8 *psc;
 
-void psc_irq(int, void *, struct pt_regs *);
+irqreturn_t psc_irq(int, void *, struct pt_regs *);
 
 /*
  * Debugging dump, used in various places to see what's going on.
@@ -131,7 +131,7 @@
  * PSC interrupt handler. It's a lot like the VIA interrupt handler.
  */
 
-void psc_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t psc_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int pIFR	= pIFRbase + ((int) dev_id);
 	int pIER	= pIERbase + ((int) dev_id);
@@ -147,7 +147,8 @@
 #endif
 
 	events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF;
-	if (!events) return;
+	if (!events)
+		return IRQ_NONE;
 
 	for (i = 0, irq_bit = 1 ; i < 4 ; i++, irq_bit <<= 1) {
 	        if (events & irq_bit) {
@@ -157,6 +158,7 @@
 			psc_write_byte(pIER, irq_bit | 0x80);
 		}
 	}
+	return IRQ_HANDLED;
 }
 
 void psc_irq_enable(int irq) {
diff -urN linux-2.5.69-bk18/arch/m68k/mac/via.c linux-2.5.69-bk19/arch/m68k/mac/via.c
--- linux-2.5.69-bk18/arch/m68k/mac/via.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/mac/via.c	2003-05-26 04:41:41.000000000 -0700
@@ -65,15 +65,15 @@
 static int  nubus_active = 0;
 
 void via_debug_dump(void);
-void via1_irq(int, void *, struct pt_regs *);
-void via2_irq(int, void *, struct pt_regs *);
-void via_nubus_irq(int, void *, struct pt_regs *);
+irqreturn_t via1_irq(int, void *, struct pt_regs *);
+irqreturn_t via2_irq(int, void *, struct pt_regs *);
+irqreturn_t via_nubus_irq(int, void *, struct pt_regs *);
 void via_irq_enable(int irq);
 void via_irq_disable(int irq);
 void via_irq_clear(int irq);
 
-extern void mac_bang(int, void *, struct pt_regs *);
-extern void mac_scc_dispatch(int, void *, struct pt_regs *);
+extern irqreturn_t mac_bang(int, void *, struct pt_regs *);
+extern irqreturn_t mac_scc_dispatch(int, void *, struct pt_regs *);
 extern int oss_present;
 
 /*
@@ -243,7 +243,7 @@
  * Start the 100 Hz clock
  */
 
-void __init via_init_clock(void (*func)(int, void *, struct pt_regs *))
+void __init via_init_clock(irqreturn_t (*func)(int, void *, struct pt_regs *))
 {	
 	via1[vACR] |= 0x40;
 	via1[vT1LL] = MAC_CLOCK_LOW;
@@ -423,13 +423,14 @@
  * the machspec interrupt number after clearing the interrupt.
  */
 
-void via1_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t via1_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int irq_bit, i;
 	unsigned char events, mask;
 
 	mask = via1[vIER] & 0x7F;
-	if (!(events = via1[vIFR] & mask)) return;
+	if (!(events = via1[vIFR] & mask))
+		return IRQ_NONE;
 
 	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
 		if (events & irq_bit) {
@@ -453,15 +454,17 @@
 		via_irq_enable(IRQ_MAC_NUBUS);
 	}
 #endif
+	return IRQ_HANDLED;
 }
 
-void via2_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t via2_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int irq_bit, i;
 	unsigned char events, mask;
 
 	mask = via2[gIER] & 0x7F;
-	if (!(events = via2[gIFR] & mask)) return;
+	if (!(events = via2[gIFR] & mask))
+		return IRQ_NONE;
 
 	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
 		if (events & irq_bit) {
@@ -470,6 +473,7 @@
 			via2[gIFR] = irq_bit | rbv_clear;
 			via2[gIER] = irq_bit | 0x80;
 		}
+	return IRQ_HANDLED;
 }
 
 /*
@@ -477,12 +481,13 @@
  * VIA2 dispatcher as a fast interrupt handler.
  */
 
-void via_nubus_irq(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t via_nubus_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int irq_bit, i;
 	unsigned char events;
 
-	if (!(events = ~via2[gBufA] & nubus_active)) return;
+	if (!(events = ~via2[gBufA] & nubus_active))
+		return IRQ_NONE;
 
 	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) {
 		if (events & irq_bit) {
@@ -491,6 +496,7 @@
 			via_irq_enable(NUBUS_SOURCE_BASE + i);
 		}
 	}
+	return IRQ_HANDLED;
 }
 
 void via_irq_enable(int irq) {
diff -urN linux-2.5.69-bk18/arch/m68k/mm/init.c linux-2.5.69-bk19/arch/m68k/mm/init.c
--- linux-2.5.69-bk18/arch/m68k/mm/init.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/mm/init.c	2003-05-26 04:41:41.000000000 -0700
@@ -33,7 +33,7 @@
 #endif
 #include <asm/tlb.h>
 
-struct mmu_gather mmu_gathers[NR_CPUS];
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 /*
  * ZERO_PAGE is a special page that is used for zero-initialized
diff -urN linux-2.5.69-bk18/arch/m68k/mvme147/147ints.c linux-2.5.69-bk19/arch/m68k/mvme147/147ints.c
--- linux-2.5.69-bk18/arch/m68k/mvme147/147ints.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/mvme147/147ints.c	2003-05-26 04:41:41.000000000 -0700
@@ -21,14 +21,14 @@
 #include <asm/irq.h>
 #include <asm/traps.h>
 
-static void mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp);
+static irqreturn_t mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp);
 
 /*
  * This should ideally be 4 elements only, for speed.
  */
 
 static struct {
-	void		(*handler)(int, void *, struct pt_regs *);
+	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
 	unsigned long	flags;
 	void		*dev_id;
 	const char	*devname;
@@ -60,7 +60,7 @@
 }
 
 int mvme147_request_irq(unsigned int irq,
-		void (*handler)(int, void *, struct pt_regs *),
+		irqreturn_t (*handler)(int, void *, struct pt_regs *),
                 unsigned long flags, const char *devname, void *dev_id)
 {
 	if (irq > 255) {
@@ -102,14 +102,15 @@
 	irq_tab[irq].devname = NULL;
 }
 
-void mvme147_process_int (unsigned long vec, struct pt_regs *fp)
+irqreturn_t mvme147_process_int (unsigned long vec, struct pt_regs *fp)
 {
-	if (vec > 255)
+	if (vec > 255) {
 		printk ("mvme147_process_int: Illegal vector %ld\n", vec);
-	else
-	{
+		return IRQ_NONE;
+	} else {
 		irq_tab[vec].count++;
 		irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp);
+		return IRQ_HANDLED;
 	}
 }
 
@@ -127,9 +128,10 @@
 }
 
 
-static void mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp)
 {
 	printk ("Unknown interrupt 0x%02x\n", irq);
+	return IRQ_NONE;
 }
 
 void mvme147_enable_irq (unsigned int irq)
diff -urN linux-2.5.69-bk18/arch/m68k/mvme147/config.c linux-2.5.69-bk19/arch/m68k/mvme147/config.c
--- linux-2.5.69-bk18/arch/m68k/mvme147/config.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/mvme147/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -36,7 +36,7 @@
 #include <asm/mvme147hw.h>
 
 
-extern void mvme147_process_int (int level, struct pt_regs *regs);
+extern irqreturn_t mvme147_process_int (int level, struct pt_regs *regs);
 extern void mvme147_init_IRQ (void);
 extern void mvme147_free_irq (unsigned int, void *);
 extern int  show_mvme147_interrupts (struct seq_file *, void *);
@@ -44,8 +44,8 @@
 extern void mvme147_disable_irq (unsigned int);
 static void mvme147_get_model(char *model);
 static int  mvme147_get_hardware_list(char *buffer);
-extern int mvme147_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
-extern void mvme147_sched_init(void (*handler)(int, void *, struct pt_regs *));
+extern int mvme147_request_irq (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+extern void mvme147_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
 extern unsigned long mvme147_gettimeoffset (void);
 extern int mvme147_hwclk (int, struct rtc_time *);
 extern int mvme147_set_clock_mmss (unsigned long);
@@ -58,7 +58,7 @@
 /* Save tick handler routine pointer, will point to do_timer() in
  * kernel/sched.c, called via mvme147_process_int() */
 
-void (*tick_handler)(int, void *, struct pt_regs *);
+irqreturn_t (*tick_handler)(int, void *, struct pt_regs *);
 
 
 int mvme147_parse_bootinfo(const struct bi_record *bi)
@@ -118,15 +118,15 @@
 
 /* Using pcc tick timer 1 */
 
-static void mvme147_timer_int (int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t mvme147_timer_int (int irq, void *dev_id, struct pt_regs *fp)
 {
 	m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;  
 	m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;   
-	tick_handler(irq, dev_id, fp);
+	return tick_handler(irq, dev_id, fp);
 }
 
 
-void mvme147_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
+void mvme147_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
 {
 	tick_handler = timer_routine;
 	request_irq (PCC_IRQ_TIMER1, mvme147_timer_int, 
diff -urN linux-2.5.69-bk18/arch/m68k/mvme16x/16xints.c linux-2.5.69-bk19/arch/m68k/mvme16x/16xints.c
--- linux-2.5.69-bk18/arch/m68k/mvme16x/16xints.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/mvme16x/16xints.c	2003-05-26 04:41:41.000000000 -0700
@@ -20,14 +20,14 @@
 #include <asm/ptrace.h>
 #include <asm/irq.h>
 
-static void mvme16x_defhand (int irq, void *dev_id, struct pt_regs *fp);
+static irqreturn_t mvme16x_defhand (int irq, void *dev_id, struct pt_regs *fp);
 
 /*
  * This should ideally be 4 elements only, for speed.
  */
 
 static struct {
-	void		(*handler)(int, void *, struct pt_regs *);
+	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
 	unsigned long	flags;
 	void		*dev_id;
 	const char	*devname;
@@ -60,7 +60,7 @@
 }
 
 int mvme16x_request_irq(unsigned int irq,
-		void (*handler)(int, void *, struct pt_regs *),
+		irqreturn_t (*handler)(int, void *, struct pt_regs *),
                 unsigned long flags, const char *devname, void *dev_id)
 {
 	if (irq < 64 || irq > 255) {
@@ -104,14 +104,15 @@
 	irq_tab[irq-64].devname = NULL;
 }
 
-void mvme16x_process_int (unsigned long vec, struct pt_regs *fp)
+irqreturn_t mvme16x_process_int (unsigned long vec, struct pt_regs *fp)
 {
-	if (vec < 64 || vec > 255)
+	if (vec < 64 || vec > 255) {
 		printk ("mvme16x_process_int: Illegal vector %ld", vec);
-	else
-	{
+		return IRQ_NONE;
+	} else {
 		irq_tab[vec-64].count++;
 		irq_tab[vec-64].handler(vec, irq_tab[vec-64].dev_id, fp);
+		return IRQ_HANDLED;
 	}
 }
 
@@ -129,9 +130,10 @@
 }
 
 
-static void mvme16x_defhand (int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t mvme16x_defhand (int irq, void *dev_id, struct pt_regs *fp)
 {
 	printk ("Unknown interrupt 0x%02x\n", irq);
+	return IRQ_NONE;
 }
 
 
diff -urN linux-2.5.69-bk18/arch/m68k/mvme16x/config.c linux-2.5.69-bk19/arch/m68k/mvme16x/config.c
--- linux-2.5.69-bk18/arch/m68k/mvme16x/config.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/mvme16x/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -40,7 +40,7 @@
 
 static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE;
 
-extern void mvme16x_process_int (int level, struct pt_regs *regs);
+extern irqreturn_t mvme16x_process_int (int level, struct pt_regs *regs);
 extern void mvme16x_init_IRQ (void);
 extern void mvme16x_free_irq (unsigned int, void *);
 extern int show_mvme16x_interrupts (struct seq_file *, void *);
@@ -48,8 +48,8 @@
 extern void mvme16x_disable_irq (unsigned int);
 static void mvme16x_get_model(char *model);
 static int  mvme16x_get_hardware_list(char *buffer);
-extern int  mvme16x_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
-extern void mvme16x_sched_init(void (*handler)(int, void *, struct pt_regs *));
+extern int  mvme16x_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+extern void mvme16x_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
 extern unsigned long mvme16x_gettimeoffset (void);
 extern int mvme16x_hwclk (int, struct rtc_time *);
 extern int mvme16x_set_clock_mmss (unsigned long);
@@ -61,7 +61,7 @@
 /* Save tick handler routine pointer, will point to do_timer() in
  * kernel/sched.c, called via mvme16x_process_int() */
 
-static void (*tick_handler)(int, void *, struct pt_regs *);
+static irqreturn_t (*tick_handler)(int, void *, struct pt_regs *);
 
 
 unsigned short mvme16x_config;
@@ -193,7 +193,7 @@
     }
 }
 
-static void mvme16x_abort_int (int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t mvme16x_abort_int (int irq, void *dev_id, struct pt_regs *fp)
 {
 	p_bdid p = &mvme_bdid;
 	unsigned long *new = (unsigned long *)vectors;
@@ -218,15 +218,16 @@
 		*(new+0x5e) = *(old+0x5e);	/* ABORT switch */
 	else
 		*(new+0x6e) = *(old+0x6e);	/* ABORT switch */
+	return IRQ_HANDLED;
 }
 
-static void mvme16x_timer_int (int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t mvme16x_timer_int (int irq, void *dev_id, struct pt_regs *fp)
 {
     *(volatile unsigned char *)0xfff4201b |= 8;
-    tick_handler(irq, dev_id, fp);
+    return tick_handler(irq, dev_id, fp);
 }
 
-void mvme16x_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
+void mvme16x_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
 {
     p_bdid p = &mvme_bdid;
     int irq;
diff -urN linux-2.5.69-bk18/arch/m68k/q40/config.c linux-2.5.69-bk19/arch/m68k/q40/config.c
--- linux-2.5.69-bk18/arch/m68k/q40/config.c	2003-05-04 16:53:28.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/q40/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -39,8 +39,8 @@
 
 extern void floppy_setup(char *str, int *ints);
 
-extern void q40_process_int (int level, struct pt_regs *regs);
-extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *);  /* added just for debugging */
+extern irqreturn_t q40_process_int (int level, struct pt_regs *regs);
+extern irqreturn_t (*q40_sys_default_handler[]) (int, void *, struct pt_regs *);  /* added just for debugging */
 extern void q40_init_IRQ (void);
 extern void q40_free_irq (unsigned int, void *);
 extern int  show_q40_interrupts (struct seq_file *, void *);
@@ -48,8 +48,8 @@
 extern void q40_disable_irq (unsigned int);
 static void q40_get_model(char *model);
 static int  q40_get_hardware_list(char *buffer);
-extern int  q40_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
-extern void q40_sched_init(void (*handler)(int, void *, struct pt_regs *));
+extern int  q40_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+extern void q40_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
 
 extern unsigned long q40_gettimeoffset (void);
 extern int q40_hwclk (int, struct rtc_time *);
diff -urN linux-2.5.69-bk18/arch/m68k/q40/q40ints.c linux-2.5.69-bk19/arch/m68k/q40/q40ints.c
--- linux-2.5.69-bk18/arch/m68k/q40/q40ints.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/q40/q40ints.c	2003-05-26 04:41:41.000000000 -0700
@@ -43,19 +43,19 @@
 extern int ints_inited;
 
 
-void q40_irq2_handler (int, void *, struct pt_regs *fp);
+irqreturn_t q40_irq2_handler (int, void *, struct pt_regs *fp);
 
 
-extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *);
+extern irqreturn_t (*q40_sys_default_handler[]) (int, void *, struct pt_regs *);
 
-static void q40_defhand (int irq, void *dev_id, struct pt_regs *fp);
-static void sys_default_handler(int lev, void *dev_id, struct pt_regs *regs);
+static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp);
+static irqreturn_t sys_default_handler(int lev, void *dev_id, struct pt_regs *regs);
 
 
 #define DEVNAME_SIZE 24
 
 static struct q40_irq_node {
-	void		(*handler)(int, void *, struct pt_regs *);
+	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
 	unsigned long	flags;
 	void		*dev_id;
   /*        struct q40_irq_node *next;*/
@@ -106,7 +106,7 @@
 }
 
 int q40_request_irq(unsigned int irq,
-		void (*handler)(int, void *, struct pt_regs *),
+		irqreturn_t (*handler)(int, void *, struct pt_regs *),
                 unsigned long flags, const char *devname, void *dev_id)
 {
   /*printk("q40_request_irq %d, %s\n",irq,devname);*/
@@ -147,7 +147,7 @@
 	    irq_tab[irq].handler = handler;
 	    irq_tab[irq].flags   = flags;
 	    irq_tab[irq].dev_id  = dev_id;
-	    strncpy(irq_tab[irq].devname,devname,DEVNAME_SIZE);
+	    strlcpy(irq_tab[irq].devname,devname,sizeof(irq_tab[irq].devname));
 	    irq_tab[irq].state = 0;
 	    return 0;
 	  }
@@ -198,9 +198,10 @@
 }
 
 
-void q40_process_int (int level, struct pt_regs *fp)
+irqreturn_t q40_process_int (int level, struct pt_regs *fp)
 {
   printk("unexpected interrupt %x\n",level);
+  return IRQ_HANDLED;
 }
 
 /* 
@@ -231,9 +232,9 @@
   sound_ticks=ticks<<1;
 }
 
-static void (*q40_timer_routine)(int, void *, struct pt_regs *);
+static irqreturn_t (*q40_timer_routine)(int, void *, struct pt_regs *);
 
-static void q40_timer_int (int irq, void * dev, struct pt_regs * regs)
+static irqreturn_t q40_timer_int (int irq, void * dev, struct pt_regs * regs)
 {
     ql_ticks = ql_ticks ? 0 : 1;
     if (sound_ticks)
@@ -244,12 +245,12 @@
 	*DAC_RIGHT=sval;
       }
 
-    if (ql_ticks) return;
-
-    q40_timer_routine(irq, dev, regs);
+    if (!ql_ticks)
+	q40_timer_routine(irq, dev, regs);
+    return IRQ_HANDLED;
 }
 
-void q40_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
+void q40_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
 {
     int timer_irq;
 
@@ -312,7 +313,7 @@
 
 
 /* got level 2 interrupt, dispatch to ISA or keyboard/timer IRQs */
-void q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)
+irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)
 {
   unsigned mir, mer;
   int irq,i;
@@ -378,7 +379,7 @@
 #endif
 			  }
 // used to do 'goto repeat;' her, this delayed bh processing too long
-			  return;
+			  return IRQ_HANDLED;
 		  }
 	  }
 	  if (mer && ccleirq>0 && !aliased_irq) 
@@ -390,6 +391,7 @@
 	  irq_tab[Q40_IRQ_KEYBOARD].count++;
 	  irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp);
   }
+  return IRQ_HANDLED;
 }
 
 int show_q40_interrupts (struct seq_file *p, void *v)
@@ -409,16 +411,18 @@
 }
 
 
-static void q40_defhand (int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp)
 {
 	printk ("Unknown q40 interrupt 0x%02x\n", irq);
+	return IRQ_NONE;
 }
-static void sys_default_handler(int lev, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sys_default_handler(int lev, void *dev_id, struct pt_regs *regs)
 {
 	printk ("Uninitialised interrupt level %d\n", lev);
+	return IRQ_NONE;
 }
 
- void (*q40_sys_default_handler[SYS_IRQS]) (int, void *, struct pt_regs *) = {
+ irqreturn_t (*q40_sys_default_handler[SYS_IRQS]) (int, void *, struct pt_regs *) = {
 	 sys_default_handler,sys_default_handler,sys_default_handler,sys_default_handler,
 	 sys_default_handler,sys_default_handler,sys_default_handler,sys_default_handler
  };
diff -urN linux-2.5.69-bk18/arch/m68k/sun3/config.c linux-2.5.69-bk19/arch/m68k/sun3/config.c
--- linux-2.5.69-bk18/arch/m68k/sun3/config.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/sun3/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -37,7 +37,7 @@
 
 extern unsigned long sun3_gettimeoffset(void);
 extern int show_sun3_interrupts (struct seq_file *, void *);
-extern void sun3_sched_init(void (*handler)(int, void *, struct pt_regs *));
+extern void sun3_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
 extern void sun3_get_model (char* model);
 extern void idprom_init (void);
 extern int sun3_hwclk(int set, struct rtc_time *t);
@@ -174,7 +174,7 @@
 	sun3_bootmem_alloc(memory_start, memory_end);
 }
 
-void __init sun3_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))
+void __init sun3_sched_init(irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
 {
 	sun3_disable_interrupts();
         intersil_clock->cmd_reg=(INTERSIL_RUN|INTERSIL_INT_DISABLE|INTERSIL_24H_MODE);
diff -urN linux-2.5.69-bk18/arch/m68k/sun3/sun3ints.c linux-2.5.69-bk19/arch/m68k/sun3/sun3ints.c
--- linux-2.5.69-bk18/arch/m68k/sun3/sun3ints.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/sun3/sun3ints.c	2003-05-26 04:41:41.000000000 -0700
@@ -18,7 +18,7 @@
 #include <linux/seq_file.h>
 
 extern void sun3_leds (unsigned char);
-static void sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp);
+static irqreturn_t sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp);
 
 void sun3_disable_interrupts(void)
 {
@@ -64,15 +64,16 @@
 	*sun3_intreg |=  (1<<irq);
 }
 
-static void sun3_int7(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t sun3_int7(int irq, void *dev_id, struct pt_regs *fp)
 {
 	sun3_do_irq(irq,fp);
 	if(!(kstat_cpu(0).irqs[SYS_IRQS + irq] % 2000)) 
 		sun3_leds(led_pattern[(kstat_cpu(0).irqs[SYS_IRQS+irq]%16000)
 			  /2000]);
+	return IRQ_HANDLED;
 }
 
-static void sun3_int5(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t sun3_int5(int irq, void *dev_id, struct pt_regs *fp)
 {
         kstat_cpu(0).irqs[SYS_IRQS + irq]++;
 #ifdef CONFIG_SUN3
@@ -87,11 +88,12 @@
         if(!(kstat_cpu(0).irqs[SYS_IRQS + irq] % 20))
                 sun3_leds(led_pattern[(kstat_cpu(0).irqs[SYS_IRQS+irq]%160)
                 /20]);
+	return IRQ_HANDLED;
 }
 
 /* handle requested ints, excepting 5 and 7, which always do the same
    thing */
-void (*sun3_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
+irqreturn_t (*sun3_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
 	sun3_inthandle, sun3_inthandle, sun3_inthandle, sun3_inthandle,
 	sun3_inthandle, sun3_int5, sun3_inthandle, sun3_int7
 };
@@ -99,10 +101,10 @@
 static const char *dev_names[SYS_IRQS] = { NULL, NULL, NULL, NULL, 
 				     NULL, "timer", NULL, "int7 handler" };
 static void *dev_ids[SYS_IRQS];
-static void (*sun3_inthandler[SYS_IRQS])(int, void *, struct pt_regs *) = {
+static irqreturn_t (*sun3_inthandler[SYS_IRQS])(int, void *, struct pt_regs *) = {
 	NULL, NULL, NULL, NULL, NULL, sun3_int5, NULL, sun3_int7
 };
-static void (*sun3_vechandler[SUN3_INT_VECS])(int, void *, struct pt_regs *);
+static irqreturn_t (*sun3_vechandler[SUN3_INT_VECS])(int, void *, struct pt_regs *);
 static void *vec_ids[SUN3_INT_VECS];
 static const char *vec_names[SUN3_INT_VECS];
 static int vec_ints[SUN3_INT_VECS];
@@ -124,7 +126,7 @@
 	return 0;
 }
 
-static void sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp)
 {
 	if(sun3_inthandler[irq] == NULL)
 		panic ("bad interrupt %d received (id %p)\n",irq, dev_id);
@@ -133,11 +135,13 @@
         *sun3_intreg &= ~(1<<irq);
 
 	sun3_inthandler[irq](irq, dev_ids[irq], fp);
+	return IRQ_HANDLED;
 }
 
-static void sun3_vec255(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t sun3_vec255(int irq, void *dev_id, struct pt_regs *fp)
 {
 //	intersil_clear();
+	return IRQ_HANDLED;
 }
 
 void sun3_init_IRQ(void)
@@ -159,7 +163,7 @@
 	sun3_vechandler[191] = sun3_vec255;
 }
                                 
-int sun3_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+int sun3_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
                       unsigned long flags, const char *devname, void *dev_id)
 {
 
@@ -228,7 +232,7 @@
 	}		
 }
 
-void sun3_process_int(int irq, struct pt_regs *regs)
+irqreturn_t sun3_process_int(int irq, struct pt_regs *regs)
 {
 
 	if((irq >= 64) && (irq <= 255)) {
@@ -239,8 +243,7 @@
 			panic ("bad interrupt vector %d received\n",irq);
 
 		vec_ints[vec]++;
-		sun3_vechandler[vec](irq, vec_ids[vec], regs);
-		return;
+		return sun3_vechandler[vec](irq, vec_ids[vec], regs);
 	} else {
 		panic("sun3_process_int: unable to handle interrupt vector %d\n",
 		      irq);
diff -urN linux-2.5.69-bk18/arch/m68k/sun3x/time.c linux-2.5.69-bk19/arch/m68k/sun3x/time.c
--- linux-2.5.69-bk18/arch/m68k/sun3x/time.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/sun3x/time.c	2003-05-26 04:41:41.000000000 -0700
@@ -90,7 +90,7 @@
 }
 #endif
 
-void __init sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *))
+void __init sun3x_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *))
 {
 	
 	sun3_disable_interrupts();
diff -urN linux-2.5.69-bk18/arch/m68k/sun3x/time.h linux-2.5.69-bk19/arch/m68k/sun3x/time.h
--- linux-2.5.69-bk18/arch/m68k/sun3x/time.h	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68k/sun3x/time.h	2003-05-26 04:41:41.000000000 -0700
@@ -3,7 +3,7 @@
 
 extern int sun3x_hwclk(int set, struct rtc_time *t);
 unsigned long sun3x_gettimeoffset (void);
-void sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *));
+void sun3x_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *));
 
 struct mostek_dt {
 	volatile unsigned char csr;
diff -urN linux-2.5.69-bk18/arch/m68knommu/Kconfig linux-2.5.69-bk19/arch/m68knommu/Kconfig
--- linux-2.5.69-bk18/arch/m68knommu/Kconfig	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/Kconfig	2003-05-26 04:41:41.000000000 -0700
@@ -74,6 +74,11 @@
 	help
 	  Motorola ColdFire 5272 processor support.
 
+config M5282
+	bool "MCF5282"
+	help
+	  Motorola ColdFire 5282 processor support.
+
 config M5307
 	bool "MCF5307"
 	help
@@ -88,7 +93,7 @@
 
 config COLDFIRE
 	bool
-	depends on (M5206 || M5206e || M5249 || M5272 || M5307 || M5407)
+	depends on (M5206 || M5206e || M5249 || M5272 || M5282 || M5307 || M5407)
 	default y
 
 choice
@@ -281,6 +286,12 @@
 	help
 	  Support for the Motorola M5272C3 board.
 
+config M5282C3
+	bool "Motorola M5282C3 board support"
+	depends on M5282
+	help
+	  Support for the Motorola M5282C3 board.
+
 config ARN5307
 	bool "Arnewsh 5307 board support"
 	depends on M5307
@@ -349,7 +360,7 @@
 config MOTOROLA
 	bool
 	default y
-	depends on (M5206eC3 || M5249C3 || M5272C3 || M5307C3 || M5407C3)
+	depends on (M5206eC3 || M5249C3 || M5272C3 || M5282C3 || M5307C3 || M5407C3)
 
 config LARGE_ALLOCS
 	bool "Allow allocating large blocks (> 1MB) of memory"
diff -urN linux-2.5.69-bk18/arch/m68knommu/Makefile linux-2.5.69-bk19/arch/m68knommu/Makefile
--- linux-2.5.69-bk18/arch/m68knommu/Makefile	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/Makefile	2003-05-26 04:41:41.000000000 -0700
@@ -16,6 +16,7 @@
 platform-$(CONFIG_M5206e)	:= 5206e
 platform-$(CONFIG_M5249)	:= 5249
 platform-$(CONFIG_M5272)	:= 5272
+platform-$(CONFIG_M5282)	:= 5282
 platform-$(CONFIG_M5307)	:= 5307
 platform-$(CONFIG_M5407)	:= 5407
 PLATFORM := $(platform-y)
@@ -49,6 +50,7 @@
 cpuclass-$(CONFIG_M5206e)	:= 5307
 cpuclass-$(CONFIG_M5249)	:= 5307
 cpuclass-$(CONFIG_M5272)	:= 5307
+cpuclass-$(CONFIG_M5282)	:= 5307
 cpuclass-$(CONFIG_M5407)	:= 5307
 cpuclass-$(CONFIG_M68EZ328)	:= 68328
 cpuclass-$(CONFIG_M68VZ328)	:= 68328
@@ -67,6 +69,7 @@
 cflags-$(CONFIG_M5206e)		:= -m5200 -Wa,-S -Wa,-m5200
 cflags-$(CONFIG_M5249)		:= -m5200 -Wa,-S -Wa,-m5200
 cflags-$(CONFIG_M5272)		:= -m5307 -Wa,-S -Wa,-m5307
+cflags-$(CONFIG_M5282)		:= -m5307 -Wa,-S -Wa,-m5307
 cflags-$(CONFIG_M5307)		:= -m5307 -Wa,-S -Wa,-m5307
 cflags-$(CONFIG_M5407)		:= -m5200 -Wa,-S -Wa,-m5200
 cflags-$(CONFIG_M68328)		:= -m68000
diff -urN linux-2.5.69-bk18/arch/m68knommu/defconfig linux-2.5.69-bk19/arch/m68knommu/defconfig
--- linux-2.5.69-bk18/arch/m68knommu/defconfig	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/defconfig	2003-05-26 04:41:41.000000000 -0700
@@ -1,8 +1,8 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
 #
 # CONFIG_MMU is not set
-# CONFIG_SWAP is not set
+# CONFIG_FPU is not set
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
@@ -13,6 +13,14 @@
 CONFIG_EXPERIMENTAL=y
 
 #
+# General setup
+#
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+CONFIG_LOG_BUF_SHIFT=14
+
+#
 # Loadable module support
 #
 # CONFIG_MODULES is not set
@@ -20,18 +28,15 @@
 #
 # Processor type and features
 #
-# CONFIG_M68000 is not set
-# CONFIG_M68EN302 is not set
 # CONFIG_M68328 is not set
 # CONFIG_M68EZ328 is not set
 # CONFIG_M68VZ328 is not set
-# CONFIG_M68332 is not set
 # CONFIG_M68360 is not set
-# CONFIG_M5204 is not set
 # CONFIG_M5206 is not set
 # CONFIG_M5206e is not set
 # CONFIG_M5249 is not set
 CONFIG_M5272=y
+# CONFIG_M5282 is not set
 # CONFIG_M5307 is not set
 # CONFIG_M5407 is not set
 CONFIG_COLDFIRE=y
@@ -51,11 +56,12 @@
 CONFIG_CLOCK_66MHz=y
 # CONFIG_CLOCK_70MHz is not set
 # CONFIG_CLOCK_140MHz is not set
+
+#
+# Platform
+#
 CONFIG_M5272C3=y
-# CONFIG_GILBARCONAP is not set
 # CONFIG_NETtel is not set
-# CONFIG_SNAPGEAR is not set
-# CONFIG_ROMFS_FROM_ROM is not set
 CONFIG_MOTOROLA=y
 # CONFIG_LARGE_ALLOCS is not set
 # CONFIG_RAMAUTO is not set
@@ -63,31 +69,30 @@
 # CONFIG_RAM8MB is not set
 CONFIG_RAM16MB=y
 # CONFIG_RAM32MB is not set
-CONFIG_AUTOBIT=y
+CONFIG_RAMAUTOBIT=y
 # CONFIG_RAM8BIT is not set
 # CONFIG_RAM16BIT is not set
-# CONFIG_RAM32bit is not set
+# CONFIG_RAM32BIT is not set
 CONFIG_RAMKERNEL=y
 # CONFIG_ROMKERNEL is not set
 # CONFIG_HIMEMKERNEL is not set
 
 #
-# General setup
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-CONFIG_NET=y
 # CONFIG_PCI is not set
 # CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-# CONFIG_SYSVIPC is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-# CONFIG_KCORE_ELF is not set
+
+#
+# Executable file formats
+#
 CONFIG_KCORE_AOUT=y
 CONFIG_BINFMT_FLAT=y
 # CONFIG_BINFMT_ZFLAT is not set
-# CONFIG_BINFMT_AOUT is not set
-# CONFIG_BINFMT_ELF is not set
-# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
 # CONFIG_PM is not set
 
 #
@@ -99,6 +104,10 @@
 # CONFIG_MTD_CONCAT is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 # CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
@@ -109,37 +118,29 @@
 #
 # CONFIG_MTD_CFI is not set
 # CONFIG_MTD_JEDECPROBE is not set
-# CONFIG_MTD_GEN_PROBE is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-# CONFIG_MTD_CFI_AMDSTD is not set
 CONFIG_MTD_RAM=y
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
 # CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_AMDSTD is not set
-# CONFIG_MTD_SHARP is not set
-# CONFIG_MTD_JEDEC is not set
 
 #
 # Mapping drivers for chip access
 #
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_PCI is not set
-# CONFIG_MTD_PCMCIA is not set
 CONFIG_MTD_UCLINUX=y
-# CONFIG_MTD_SNAPGEARuC is not set
 
 #
 # Self-contained MTD device drivers
 #
-# CONFIG_MTD_PMC551 is not set
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_MTDRAM is not set
 # CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
 # CONFIG_MTD_DOC1000 is not set
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOCPROBE is not set
 
 #
 # NAND Flash Device Drivers
@@ -152,25 +153,14 @@
 # CONFIG_PARPORT is not set
 
 #
-# Plug and Play configuration
+# Plug and Play support
 #
 # CONFIG_PNP is not set
-# CONFIG_PNP_NAMES is not set
-# CONFIG_PNP_DEBUG is not set
-# CONFIG_ISAPNP is not set
-# CONFIG_PNPBIOS is not set
 
 #
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
@@ -179,6 +169,34 @@
 # CONFIG_BLK_DEV_BLKMEM is not set
 
 #
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
 # Networking options
 #
 CONFIG_PACKET=y
@@ -187,6 +205,7 @@
 # CONFIG_NETFILTER is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -196,19 +215,19 @@
 # CONFIG_ARPD is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_XFRM_USER is not set
 # CONFIG_IPV6 is not set
 
 #
-#    SCTP Configuration (EXPERIMENTAL)
+# SCTP Configuration (EXPERIMENTAL)
 #
 CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_LLC is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_DEV_APPLETALK is not set
 # CONFIG_DECNET is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
@@ -225,42 +244,10 @@
 # CONFIG_NET_SCHED is not set
 
 #
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-# CONFIG_PHONE_IXJ is not set
-# CONFIG_PHONE_IXJ_PCMCIA is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-# CONFIG_IDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
-
-#
-# Network device support
+# Network testing
 #
+# CONFIG_NET_PKTGEN is not set
 CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -271,43 +258,14 @@
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-# CONFIG_SUNLANCE is not set
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_NET_ISA is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_NET_POCKET is not set
+# CONFIG_MII is not set
 CONFIG_FEC=y
 
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_E1000_NAPI is not set
-# CONFIG_MYRI_SBUS is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
 CONFIG_PPP=y
 # CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
 # CONFIG_PPP_ASYNC is not set
 # CONFIG_PPP_SYNC_TTY is not set
 # CONFIG_PPP_DEFLATE is not set
@@ -321,11 +279,8 @@
 # CONFIG_NET_RADIO is not set
 
 #
-# Token Ring devices
+# Token Ring devices (depends on LLC=y)
 #
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
 # CONFIG_SHAPER is not set
 
 #
@@ -349,30 +304,68 @@
 # CONFIG_ISDN_BOOL is not set
 
 #
-# Old CD-ROM drivers (not SCSI, not IDE)
+# Telephony Support
 #
-# CONFIG_CD_NO_IDESCSI is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
 
 #
 # Character devices
 #
 # CONFIG_VT is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_RESETSWITCH is not set
 # CONFIG_LEDMAN is not set
+# CONFIG_RESETSWITCH is not set
 
 #
 # Serial drivers
 #
 # CONFIG_SERIAL_8250 is not set
-# CONFIG_SERIAL_8250_CONSOLE is not set
-# CONFIG_SERIAL_8250_CS is not set
-# CONFIG_SERIAL_8250_EXTENDED is not set
-# CONFIG_SERIAL_8250_MANY_PORTS is not set
-# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
-# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
 CONFIG_SERIAL_COLDFIRE=y
 # CONFIG_UNIX98_PTYS is not set
 
@@ -382,12 +375,25 @@
 # CONFIG_I2C is not set
 
 #
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+
+#
 # Mice
 #
 # CONFIG_BUSMOUSE is not set
 # CONFIG_QIC02_TAPE is not set
 
 #
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
@@ -404,105 +410,91 @@
 # CONFIG_FTAPE is not set
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
-# CONFIG_SCx200_GPIO is not set
 # CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
 #
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
 # CONFIG_QUOTA is not set
-# CONFIG_QFMT_V1 is not set
-# CONFIG_QFMT_V2 is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
 # CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_JBD_DEBUG is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-# CONFIG_MINIX_FS is not set
 # CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS is not set
 # CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-CONFIG_ROMFS_FS=y
-CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_QUOTA is not set
 
 #
 # Network File Systems
 #
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_NFS_FS is not set
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_ROOT_NFS is not set
 # CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-# CONFIG_SUNRPC is not set
-# CONFIG_LOCKD is not set
 # CONFIG_EXPORTFS is not set
-# CONFIG_CIFS is not set
 # CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_AFS_FS is not set
-# CONFIG_ZISOFS_FS is not set
 
 #
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_SMB_NLS is not set
-# CONFIG_NLS is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
 
 #
 # Sound
@@ -512,27 +504,33 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
 
 #
 # Kernel hacking
 #
 # CONFIG_FULLDEBUG is not set
 # CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_PROFILE is not set
+# CONFIG_HIGHPROFILE is not set
 # CONFIG_DUMPTOFLASH is not set
 # CONFIG_NO_KERNEL_MSG is not set
-# CONFIG_SMALL_TASKS is not set
 # CONFIG_BDM_DISABLE is not set
 
 #
 # Security options
 #
-CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
 
 #
 # Library routines
 #
 # CONFIG_CRC32 is not set
-# CONFIG_ZLIB_INFLATE is not set
-# CONFIG_ZLIB_DEFLATE is not set
diff -urN linux-2.5.69-bk18/arch/m68knommu/kernel/setup.c linux-2.5.69-bk19/arch/m68knommu/kernel/setup.c
--- linux-2.5.69-bk18/arch/m68knommu/kernel/setup.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/kernel/setup.c	2003-05-26 04:41:41.000000000 -0700
@@ -120,6 +120,9 @@
 #if defined(CONFIG_M5272)
 	#define CPU "COLDFIRE(m5272)"
 #endif
+#if defined(CONFIG_M5282)
+	#define CPU "COLDFIRE(m5282)"
+#endif
 #if defined(CONFIG_M5307)
 	#define	CPU "COLDFIRE(m5307)"
 #endif
diff -urN linux-2.5.69-bk18/arch/m68knommu/kernel/time.c linux-2.5.69-bk19/arch/m68knommu/kernel/time.c
--- linux-2.5.69-bk18/arch/m68knommu/kernel/time.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/kernel/time.c	2003-05-26 04:41:41.000000000 -0700
@@ -28,6 +28,9 @@
 
 u64 jiffies_64 = INITIAL_JIFFIES;
 
+extern unsigned long wall_jiffies;
+
+
 static inline int set_rtc_mmss(unsigned long nowtime)
 {
 	if (mach_set_clock_mmss)
@@ -66,6 +69,8 @@
 	if (mach_tick)
 	  mach_tick();
 
+	write_seqlock(&xtime_lock);
+
 	do_timer(regs);
 
 	if (!user_mode(regs))
@@ -108,6 +113,8 @@
 	    }
 	}
 #endif /* CONFIG_HEARTBEAT */
+
+	write_sequnlock(&xtime_lock);
 }
 
 void time_init(void)
@@ -133,18 +140,19 @@
 void do_gettimeofday(struct timeval *tv)
 {
 	unsigned long flags;
-	unsigned long seq;
+	unsigned long lost, seq;
 	unsigned long usec, sec;
 
 	do {
 		seq = read_seqbegin_irqsave(&xtime_lock, flags);
-
 		usec = mach_gettimeoffset ? mach_gettimeoffset() : 0;
+		lost = jiffies - wall_jiffies;
+		if (lost)
+			usec += lost * (1000000 / HZ);
 		sec = xtime.tv_sec;
 		usec += (xtime.tv_nsec / 1000);
 	} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
 
-
 	while (usec >= 1000000) {
 		usec -= 1000000;
 		sec++;
diff -urN linux-2.5.69-bk18/arch/m68knommu/platform/5206/config.c linux-2.5.69-bk19/arch/m68knommu/platform/5206/config.c
--- linux-2.5.69-bk18/arch/m68knommu/platform/5206/config.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/platform/5206/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -79,6 +79,20 @@
 
 /***************************************************************************/
 
+int mcf_timerirqpending(int timer)
+{
+	unsigned int imr = 0;
+
+	switch (timer) {
+	case 1:  imr = MCFSIM_IMR_TIMER1; break;
+	case 2:  imr = MCFSIM_IMR_TIMER2; break;
+	default: break;
+	}
+	return (mcf_getipr() & imr);
+}
+
+/***************************************************************************/
+
 void config_BSP(char *commandp, int size)
 {
 	mcf_setimr(MCFSIM_IMR_MASKALL);
diff -urN linux-2.5.69-bk18/arch/m68knommu/platform/5206e/config.c linux-2.5.69-bk19/arch/m68knommu/platform/5206e/config.c
--- linux-2.5.69-bk18/arch/m68knommu/platform/5206e/config.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/platform/5206e/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -79,6 +79,20 @@
 
 /***************************************************************************/
 
+int mcf_timerirqpending(int timer)
+{
+	unsigned int imr = 0;
+
+	switch (timer) {
+	case 1:  imr = MCFSIM_IMR_TIMER1; break;
+	case 2:  imr = MCFSIM_IMR_TIMER2; break;
+	default: break;
+	}
+	return (mcf_getipr() & imr);
+}
+
+/***************************************************************************/
+
 void config_BSP(char *commandp, int size)
 {
 	mcf_setimr(MCFSIM_IMR_MASKALL);
diff -urN linux-2.5.69-bk18/arch/m68knommu/platform/5249/config.c linux-2.5.69-bk19/arch/m68knommu/platform/5249/config.c
--- linux-2.5.69-bk18/arch/m68knommu/platform/5249/config.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/platform/5249/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -78,6 +78,20 @@
 
 /***************************************************************************/
 
+int mcf_timerirqpending(int timer)
+{
+	unsigned int imr = 0;
+
+	switch (timer) {
+	case 1:  imr = MCFSIM_IMR_TIMER1; break;
+	case 2:  imr = MCFSIM_IMR_TIMER2; break;
+	default: break;
+	}
+	return (mcf_getipr() & imr);
+}
+
+/***************************************************************************/
+
 void config_BSP(char *commandp, int size)
 {
 	mcf_setimr(MCFSIM_IMR_MASKALL);
diff -urN linux-2.5.69-bk18/arch/m68knommu/platform/5272/config.c linux-2.5.69-bk19/arch/m68knommu/platform/5272/config.c
--- linux-2.5.69-bk18/arch/m68knommu/platform/5272/config.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/platform/5272/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -70,17 +70,24 @@
 void mcf_settimericr(int timer, int level)
 {
 	volatile unsigned long *icrp;
-	unsigned int icr;
 
-	switch (timer) {
-	case 2:  icr = MCFSIM_ICR2; break;
-	case 3:  icr = MCFSIM_ICR3; break;
-	case 4:  icr = MCFSIM_ICR4; break;
-	default: icr = MCFSIM_ICR1; break;
+	if ((timer >= 1 ) && (timer <= 4)) {
+		icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
+		*icrp = (0x8 | level) << ((4 - timer) * 4);
 	}
+}
+
+/***************************************************************************/
 
-	icrp = (volatile unsigned long *) (MCF_MBAR + icr);
-	*icrp = (0x8 | level) << ((4 - timer) * 4);
+int mcf_timerirqpending(int timer)
+{
+	volatile unsigned long *icrp;
+
+	if ((timer >= 1 ) && (timer <= 4)) {
+		icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
+		return (*icrp & (0x8 << ((4 - timer) * 4)));
+	}
+	return 0;
 }
 
 /***************************************************************************/
diff -urN linux-2.5.69-bk18/arch/m68knommu/platform/5282/MOTOROLA/crt0_ram.S linux-2.5.69-bk19/arch/m68knommu/platform/5282/MOTOROLA/crt0_ram.S
--- linux-2.5.69-bk18/arch/m68knommu/platform/5282/MOTOROLA/crt0_ram.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/arch/m68knommu/platform/5282/MOTOROLA/crt0_ram.S	2003-05-26 04:41:41.000000000 -0700
@@ -0,0 +1,164 @@
+/*****************************************************************************/
+
+/*
+ *	crt0_ram.S -- startup code for MCF5282 ColdFire based MOTOROLA boards.
+ *
+ *	(C) Copyright 2003, Greg Ungerer (gerg@snapgear.com).
+ */
+
+/*****************************************************************************/
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+
+/*****************************************************************************/
+
+/*
+ *	Motorola M5282C3 ColdFire eval board, chip select and memory setup.
+ */
+
+#define	MEM_BASE	0x00000000	/* Memory base at address 0 */
+#define	VBR_BASE	MEM_BASE	/* Vector address */
+
+#if defined(CONFIG_RAM16MB)
+#define	MEM_SIZE	0x01000000	/* Memory size 16Mb */
+#elif defined(CONFIG_RAM8MB)
+#define	MEM_SIZE	0x00800000	/* Memory size 8Mb */
+#else
+#define	MEM_SIZE	0x00400000	/* Memory size 4Mb */
+#endif
+
+/*****************************************************************************/
+
+.global	_start
+.global _rambase
+.global _ramvec
+.global	_ramstart
+.global	_ramend
+
+/*****************************************************************************/
+
+.data
+
+/*
+ *	Set up the usable of RAM stuff. Size of RAM is determined then
+ *	an initial stack set up at the end.
+ */
+_rambase:
+.long	0
+_ramvec:
+.long	0
+_ramstart:
+.long	0
+_ramend:
+.long	0
+
+/*****************************************************************************/
+
+.text
+
+/*
+ *	This is the codes first entry point. This is where it all
+ *	begins...
+ */
+
+_start:
+	nop					/* Filler */
+	move.w	#0x2700, %sr			/* No interrupts */
+
+	/*
+	 * Setup VBR here, otherwise buserror remap will not work.
+	 * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
+	 *
+	 * bkr@cut.de 19990306
+	 *
+	 * Note: this is because dBUG points VBR to ROM, making vectors read
+	 * only, so the bus trap can't be changed. (RS)
+	 */
+	move.l	#VBR_BASE, %a7			/* Note VBR can't be read */
+	movec   %a7, %VBR
+	move.l	%a7, _ramvec			/* Set up vector addr */
+	move.l	%a7, _rambase			/* Set up base RAM addr */
+
+
+	/*
+	 *	Set memory size.
+	 */
+	move.l	#MEM_SIZE, %a0
+
+	move.l	%a0, %d0			/* Mem end addr is in a0 */
+	move.l	%d0, %sp			/* Set up initial stack ptr */
+	move.l	%d0, _ramend			/* Set end ram addr */
+
+	/*
+	 *	Enable CPU internal cache.
+	 *
+	 *	Cache is totally broken in first 5282 silicon.
+	 *	No point enabling it for now.
+	 */
+#if 0
+	move.l	#0x01000000, %d0
+	movec	%d0, %CACR			/* Invalidate cache */
+	nop
+
+	move.l	#0x0000c000, %d0		/* Set SDRAM cached only */
+	movec	%d0, %ACR0
+	move.l	#0x00000000, %d0		/* No other regions cached */
+	movec	%d0, %ACR1
+
+	move.l	#0x00000000, %d0		/* Setup cache mask */
+	movec	%d0, %CACR			/* Enable cache */
+	nop
+#endif
+
+	/*
+	 *	Move ROM filesystem above bss :-)
+	 */
+	lea.l	_sbss, %a0			/* Get start of bss */
+	lea.l	_ebss, %a1			/* Set up destination  */
+	move.l	%a0, %a2			/* Copy of bss start */
+
+	move.l	8(%a0), %d0			/* Get size of ROMFS */
+	addq.l	#8, %d0				/* Allow for rounding */
+	and.l	#0xfffffffc, %d0		/* Whole words */
+
+	add.l	%d0, %a0			/* Copy from end */
+	add.l	%d0, %a1			/* Copy from end */
+	move.l	%a1, _ramstart			/* Set start of ram */
+
+_copy_romfs:
+	move.l	-(%a0), %d0			/* Copy dword */
+	move.l	%d0, -(%a1)
+	cmp.l	%a0, %a2			/* Check if at end */
+	bne	_copy_romfs
+
+	/*
+	 *	Zero out the bss region.
+	 */
+	lea.l	_sbss, %a0			/* Get start of bss */
+	lea.l	_ebss, %a1			/* Get end of bss */
+	clr.l	%d0				/* Set value */
+_clear_bss:
+	move.l	%d0, (%a0)+			/* Clear each word */
+	cmp.l	%a0, %a1			/* Check if at end */
+	bne	_clear_bss
+
+	/*
+	 *	Load the current thread pointer and stack.
+	 */
+	lea	init_thread_union, %a0
+	lea	0x2000(%a0), %sp
+
+	/*
+	 *	Assember start up done, start code proper.
+	 */
+	jsr	start_kernel			/* Start Linux kernel */
+
+_exit:
+	jmp	_exit				/* Should never get here */
+
+/*****************************************************************************/
diff -urN linux-2.5.69-bk18/arch/m68knommu/platform/5282/Makefile linux-2.5.69-bk19/arch/m68knommu/platform/5282/Makefile
--- linux-2.5.69-bk18/arch/m68knommu/platform/5282/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/arch/m68knommu/platform/5282/Makefile	2003-05-26 04:41:41.000000000 -0700
@@ -0,0 +1,21 @@
+#
+# Makefile for the linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs.  You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
+# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+#
+
+ifdef CONFIG_FULLDEBUG
+AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+endif
+
+obj-y := config.o pit.o
+
+extra-y := $(BOARD)/crt0_$(MODEL).o
diff -urN linux-2.5.69-bk18/arch/m68knommu/platform/5282/config.c linux-2.5.69-bk19/arch/m68knommu/platform/5282/config.c
--- linux-2.5.69-bk18/arch/m68knommu/platform/5282/config.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/arch/m68knommu/platform/5282/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -0,0 +1,79 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/5282/config.c
+ *
+ *	Sub-architcture dependant initialization code for the Motorola
+ *	5282 CPU.
+ *
+ *	Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com)
+ *	Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <asm/dma.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfdma.h>
+
+/***************************************************************************/
+
+void coldfire_pit_tick(void);
+void coldfire_pit_init(void (*handler)(int, void *, struct pt_regs *));
+unsigned long coldfire_pit_offset(void);
+void coldfire_trap_init(void);
+void coldfire_reset(void);
+
+/***************************************************************************/
+
+/*
+ *	DMA channel base address table.
+ */
+unsigned int   dma_base_addr[MAX_M68K_DMA_CHANNELS] = {
+        MCF_MBAR + MCFDMA_BASE0,
+};
+
+/***************************************************************************/
+
+void mcf_disableall(void)
+{
+	*((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH)) = 0xffffffff;
+	*((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL)) = 0xffffffff;
+}
+
+/***************************************************************************/
+
+void mcf_autovector(unsigned int vec)
+{
+	/* Everything is auto-vectored on the 5272 */
+}
+
+/***************************************************************************/
+
+void config_BSP(char *commandp, int size)
+{
+	mcf_disableall();
+
+#if defined(CONFIG_BOOTPARAM)
+	strncpy(commandp, CONFIG_BOOTPARAM_STRING, size);
+	commandp[size-1] = 0;
+#else
+	memset(commandp, 0, size);
+#endif
+
+	mach_sched_init = coldfire_pit_init;
+	mach_tick = coldfire_pit_tick;
+	mach_gettimeoffset = coldfire_pit_offset;
+	mach_trap_init = coldfire_trap_init;
+	mach_reset = coldfire_reset;
+}
+
+/***************************************************************************/
diff -urN linux-2.5.69-bk18/arch/m68knommu/platform/5282/pit.c linux-2.5.69-bk19/arch/m68knommu/platform/5282/pit.c
--- linux-2.5.69-bk18/arch/m68knommu/platform/5282/pit.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/arch/m68knommu/platform/5282/pit.c	2003-05-26 04:41:41.000000000 -0700
@@ -0,0 +1,86 @@
+/***************************************************************************/
+
+/*
+ *	pit.c -- Motorola ColdFire PIT timer. Currently this type of
+ *	         hardware timer only exists in the Motorola ColdFire
+ *		 5282 CPU.
+ *
+ *	Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com)
+ *	Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
+ *
+ */
+
+/***************************************************************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <asm/irq.h>
+#include <asm/coldfire.h>
+#include <asm/mcfpit.h>
+#include <asm/mcfsim.h>
+
+/***************************************************************************/
+
+void coldfire_pit_tick(void)
+{
+	volatile struct mcfpit *tp;
+
+	/* Reset the ColdFire timer */
+	tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
+	tp->pcsr |= MCFPIT_PCSR_PIF;
+}
+
+/***************************************************************************/
+
+void coldfire_pit_init(void (*handler)(int, void *, struct pt_regs *))
+{
+	volatile unsigned char *icrp;
+	volatile unsigned long *imrp;
+	volatile struct mcfpit *tp;
+
+	request_irq(64+55, handler, SA_INTERRUPT, "ColdFire Timer", NULL);
+
+	icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 +
+		MCFINTC_ICR0 + MCFINT_PIT1);
+	*icrp = 0x2b; /* PIT1 with level 5, priority 3 */
+
+	imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
+	*imrp &= ~(1 << (55 - 32));
+
+	/* Set up PIT timer 1 as poll clock */
+	tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
+	tp->pcsr = MCFPIT_PCSR_DISABLE;
+
+	tp->pmr = ((MCF_CLK / 2) / 64) / HZ;
+	tp->pcsr = MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW |
+		MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64;
+}
+
+/***************************************************************************/
+
+unsigned long coldfire_pit_offset(void)
+{
+	volatile struct mcfpit *tp;
+	volatile unsigned long *ipr;
+	unsigned long pmr, pcntr, offset;
+
+	tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
+	ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IPRH);
+
+	pmr = tp->pmr;
+	pcntr = tp->pcntr;
+
+	/*
+	 * If we are still in the first half of the upcount and a
+	 * timer interupt is pending, then add on a ticks worth of time.
+	 */
+	offset = ((pcntr * (1000000 / HZ)) / pmr);
+	if ((offset < (1000000 / HZ / 2)) && (*ipr & (1 << (55 - 32))))
+		offset += 1000000 / HZ;
+	return offset;	
+}
+
+/***************************************************************************/
diff -urN linux-2.5.69-bk18/arch/m68knommu/platform/5307/Makefile linux-2.5.69-bk19/arch/m68knommu/platform/5307/Makefile
--- linux-2.5.69-bk18/arch/m68knommu/platform/5307/Makefile	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/platform/5307/Makefile	2003-05-26 04:41:41.000000000 -0700
@@ -16,8 +16,13 @@
 AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
 endif
 
-obj-$(CONFIG_COLDFIRE)	+= entry.o timers.o vectors.o
-obj-$(CONFIG_M5307)	+= config.o
+obj-$(CONFIG_COLDFIRE)	+= entry.o vectors.o
+obj-$(CONFIG_M5206)	+= timers.o
+obj-$(CONFIG_M5206e)	+= timers.o
+obj-$(CONFIG_M5249)	+= timers.o
+obj-$(CONFIG_M5272)	+= timers.o
+obj-$(CONFIG_M5307)	+= config.o timers.o
+obj-$(CONFIG_M5407)	+= timers.o
 
 ifeq ($(CONFIG_M5307),y)
 extra-y := $(BOARD)/crt0_$(MODEL).o
diff -urN linux-2.5.69-bk18/arch/m68knommu/platform/5307/config.c linux-2.5.69-bk19/arch/m68knommu/platform/5307/config.c
--- linux-2.5.69-bk18/arch/m68knommu/platform/5307/config.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/platform/5307/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -84,6 +84,20 @@
 
 /***************************************************************************/
 
+int mcf_timerirqpending(int timer)
+{
+	unsigned int imr = 0;
+
+	switch (timer) {
+	case 1:  imr = MCFSIM_IMR_TIMER1; break;
+	case 2:  imr = MCFSIM_IMR_TIMER2; break;
+	default: break;
+	}
+	return (mcf_getipr() & imr);
+}
+
+/***************************************************************************/
+
 void config_BSP(char *commandp, int size)
 {
 	mcf_setimr(MCFSIM_IMR_MASKALL);
diff -urN linux-2.5.69-bk18/arch/m68knommu/platform/5307/timers.c linux-2.5.69-bk19/arch/m68knommu/platform/5307/timers.c
--- linux-2.5.69-bk18/arch/m68knommu/platform/5307/timers.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/platform/5307/timers.c	2003-05-26 04:41:41.000000000 -0700
@@ -1,7 +1,7 @@
 /***************************************************************************/
 
 /*
- *	linux/arch/m68knommu/platform/5307/timers.c
+ *	timers.c -- generic ColdFire hardware timer support.
  *
  *	Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com)
  */
@@ -34,6 +34,13 @@
 
 static volatile struct mcftimer *mcf_timerp;
 
+/*
+ *	These provide the underlying interrupt vector support.
+ *	Unfortunately it is a little different on each ColdFire.
+ */
+extern void mcf_settimericr(int timer, int level);
+extern int mcf_timerirqpending(int timer);
+
 /***************************************************************************/
 
 void coldfire_tick(void)
@@ -42,7 +49,9 @@
 	mcf_timerp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
 }
 
-void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *))
+/***************************************************************************/
+
+void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
 {
 	/* Set up an internal TIMER as poll clock */
 	mcf_timerp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE1);
@@ -64,12 +73,21 @@
 
 unsigned long coldfire_timer_offset(void)
 {
-	unsigned long trr, tcn;
+	unsigned long trr, tcn, offset;
 
-	/* Get the values as longs for accurate calculation. */
-	tcn = mcf_timerp->tcn;
-	trr = mcf_timerp->trr;
-	return((tcn * (1000000 / HZ)) / trr);
+	/*
+	 * The change to pointer and de-reference is to force the compiler
+	 * to read the registers with a single 16bit access. Otherwise it
+	 * does some crazy 8bit read combining.
+	 */
+	tcn = *(&mcf_timerp->tcn);
+	trr = *(&mcf_timerp->trr);
+	offset = (tcn * (1000000 / HZ)) / trr;
+
+	/* Check if we just wrapped the counters and maybe missed a tick */
+	if ((offset < (1000000 / HZ / 2)) && mcf_timerirqpending(1))
+		offset += 1000000 / HZ;
+	return offset;
 }
 
 /***************************************************************************/
@@ -105,6 +123,8 @@
         }
 }
 
+/***************************************************************************/
+
 void coldfire_profile_init(void)
 {
 	printk("PROFILE: lodging TIMER2 @ %dHz as profile timer\n", PROFILEHZ);
diff -urN linux-2.5.69-bk18/arch/m68knommu/platform/5407/CLEOPATRA/crt0_ram.S linux-2.5.69-bk19/arch/m68knommu/platform/5407/CLEOPATRA/crt0_ram.S
--- linux-2.5.69-bk18/arch/m68knommu/platform/5407/CLEOPATRA/crt0_ram.S	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/platform/5407/CLEOPATRA/crt0_ram.S	2003-05-26 04:41:41.000000000 -0700
@@ -118,8 +118,8 @@
 	move.l #(0x00<<ACR_BASE_POS)+(0<<ACR_MASK_POS)+ACR_ENABLE+ACR_ANY+ACR_CM_CP,%d0
    movec  %d0,%ACR3
  
-   /* Enable cache */
-	move.l	#0x86088400, %d0
+	/* Enable cache */
+	move.l	#0xa4098400, %d0		/* Write buffer, dflt precise */
 	movec	%d0,%CACR
 	nop
 
diff -urN linux-2.5.69-bk18/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S linux-2.5.69-bk19/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S
--- linux-2.5.69-bk18/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S	2003-05-26 04:41:41.000000000 -0700
@@ -99,7 +99,7 @@
 	movec	%d0, %ACR3
 
 	/* Enable cache */
-	move.l	#0x86088400, %d0
+	move.l	#0xa4098400, %d0		/* Write buffer, dflt precise */
 	movec	%d0,%CACR
 	nop
 
diff -urN linux-2.5.69-bk18/arch/m68knommu/platform/5407/config.c linux-2.5.69-bk19/arch/m68knommu/platform/5407/config.c
--- linux-2.5.69-bk18/arch/m68knommu/platform/5407/config.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/platform/5407/config.c	2003-05-26 04:41:41.000000000 -0700
@@ -83,6 +83,20 @@
 
 /***************************************************************************/
 
+int mcf_timerirqpending(int timer)
+{
+	unsigned int imr = 0;
+
+	switch (timer) {
+	case 1:  imr = MCFSIM_IMR_TIMER1; break;
+	case 2:  imr = MCFSIM_IMR_TIMER2; break;
+	default: break;
+	}
+	return (mcf_getipr() & imr);
+}
+
+/***************************************************************************/
+
 void config_BSP(char *commandp, int size)
 {
 	mcf_setimr(MCFSIM_IMR_MASKALL);
diff -urN linux-2.5.69-bk18/arch/m68knommu/vmlinux.lds.S linux-2.5.69-bk19/arch/m68knommu/vmlinux.lds.S
--- linux-2.5.69-bk18/arch/m68knommu/vmlinux.lds.S	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/arch/m68knommu/vmlinux.lds.S	2003-05-26 04:41:41.000000000 -0700
@@ -73,42 +73,8 @@
 #endif
 
 #ifdef CONFIG_DRAGEN2
-#ifdef CONFIG_RAMKERNEL
-#define	ROMVEC_START	0x04030000
-#define	ROMVEC_LENGTH	0x400
-#define	ROM_START	0x04030400
-#define	ROM_LENGTH	0x1cec00
-#define	ROM_END		0x04200000
-#define	RAMVEC_START	0x00000000
-#define	RAMVEC_LENGTH	0x400
-#define	RAM_START	0x00010400
-#define	RAM_LENGTH	0x1ff0000
-#define	RAM_END		0x02000000
-#endif
-#ifdef CONFIG_ROMKERNEL
-#define	ROMVEC_START	0x04030000
-#define	ROMVEC_LENGTH	0x400
-#define	ROM_START	0x04030400
-#define	ROM_LENGTH	0x1cec00
-#define	ROM_END		0x04200000
-#define	RAMVEC_START	0x00000000
-#define	RAMVEC_LENGTH	0x400
-#define	RAM_START	0x00010000
-#define	RAM_LENGTH	0x1ff0000
-#define	RAM_END		0x02000000
-#endif
-#ifdef CONFIG_HIMEMKERNEL
-#define	ROMVEC_START	0x01e00000
-#define	ROMVEC_LENGTH	0x400
-#define	ROM_START	0x01e00400
-#define	ROM_LENGTH	0x1ffc00
-#define	ROM_END		0x02000000
-#define	RAMVEC_START	0x00000000
-#define	RAMVEC_LENGTH	0x400
-#define	RAM_START	0x00010000
-#define	RAM_LENGTH	0x1df0000
-#define	RAM_END		0x01e00000
-#endif
+#define	RAM_START	0x10000
+#define	RAM_LENGTH	0x7f0000
 #endif
 
 #ifdef CONFIG_UCQUICC
@@ -149,12 +115,17 @@
  *	but this isn't important here, we assume at least 4MiB.
  */
 #if defined(CONFIG_M5206eC3) || defined(CONFIG_M5249C3) || \
-    defined(CONFIG_M5272C3) || defined(CONFIG_M5306C3) || \
+    defined(CONFIG_M5272C3) || defined(CONFIG_M5307C3) || \
     defined(CONFIG_ARN5307) || defined(CONFIG_M5407C3)
 #define	RAM_START	0x20000
 #define	RAM_LENGTH	0x3e0000
 #endif
 
+#if defined(CONFIG_M5282C3)
+#define	RAM_START	0x10000
+#define	RAM_LENGTH	0x3f0000
+#endif
+
 /*
  *	These flash boot boards use all of ram for operation. Again the
  *	actual memory size is not important here, assume at least 4MiB.
@@ -167,13 +138,13 @@
 #define	RAM_LENGTH	0x3ffc00
 #endif
 
-#ifdef CONFIG_RAMKERNEL
+#if defined(CONFIG_RAMKERNEL)
 #define	TEXT		ram
 #define	DATA		ram
 #define	INIT		ram
 #define	BSS		ram
 #endif
-#ifdef CONFIG_ROMKERNEL
+#if defined(CONFIG_ROMKERNEL) || defined(CONFIG_HIMEMKERNEL)
 #define	TEXT		rom
 #define	DATA		ram
 #define	INIT		ram
diff -urN linux-2.5.69-bk18/arch/mips/kernel/irixelf.c linux-2.5.69-bk19/arch/mips/kernel/irixelf.c
--- linux-2.5.69-bk18/arch/mips/kernel/irixelf.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/arch/mips/kernel/irixelf.c	2003-05-26 04:41:41.000000000 -0700
@@ -1175,7 +1175,7 @@
 
 		set_fs(KERNEL_DS);
 	}
-	strncpy(psinfo.pr_fname, current->comm, sizeof(psinfo.pr_fname));
+	strlcpy(psinfo.pr_fname, current->comm, sizeof(psinfo.pr_fname));
 
 	notes[2].name = "CORE";
 	notes[2].type = NT_TASKSTRUCT;
diff -urN linux-2.5.69-bk18/arch/mips/kernel/setup.c linux-2.5.69-bk19/arch/mips/kernel/setup.c
--- linux-2.5.69-bk18/arch/mips/kernel/setup.c	2003-05-04 16:53:03.000000000 -0700
+++ linux-2.5.69-bk19/arch/mips/kernel/setup.c	2003-05-26 04:41:41.000000000 -0700
@@ -633,9 +633,8 @@
 		panic("Unsupported architecture");
 	}
 
-	strncpy(command_line, arcs_cmdline, sizeof command_line);
-	command_line[sizeof command_line - 1] = 0;
-	strcpy(saved_command_line, command_line);
+	strlcpy(command_line, arcs_cmdline, sizeof command_line);
+	strlcpy(saved_command_line, command_line, sizeof saved_command_line);
 	*cmdline_p = command_line;
 
 	parse_mem_cmdline();
diff -urN linux-2.5.69-bk18/arch/mips/kernel/sysmips.c linux-2.5.69-bk19/arch/mips/kernel/sysmips.c
--- linux-2.5.69-bk18/arch/mips/kernel/sysmips.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/arch/mips/kernel/sysmips.c	2003-05-26 04:41:41.000000000 -0700
@@ -64,14 +64,15 @@
 
 		name = (char *) arg1;
 
-		len = strncpy_from_user(nodename, name, sizeof(nodename));
+		len = strncpy_from_user(nodename, name, __NEW_UTS_LEN);
 		if (len < 0) 
 			return -EFAULT;
+		nodename[__NEW_UTS_LEN] = '\0';
 
 		down_write(&uts_sem);
-		strncpy(system_utsname.nodename, name, len);
+		strlcpy(system_utsname.nodename, nodename,
+			sizeof(system_utsname.nodename));
 		up_write(&uts_sem);
-		system_utsname.nodename[len] = '\0'; 
 		return 0;
 	}
 
diff -urN linux-2.5.69-bk18/arch/mips/mm/init.c linux-2.5.69-bk19/arch/mips/mm/init.c
--- linux-2.5.69-bk18/arch/mips/mm/init.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/arch/mips/mm/init.c	2003-05-26 04:41:41.000000000 -0700
@@ -42,7 +42,7 @@
 #include <asm/mmu_context.h>
 #include <asm/tlb.h>
 
-struct mmu_gather mmu_gathers[NR_CPUS];
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 extern void prom_free_prom_memory(void);
 
diff -urN linux-2.5.69-bk18/arch/mips64/kernel/setup.c linux-2.5.69-bk19/arch/mips64/kernel/setup.c
--- linux-2.5.69-bk18/arch/mips64/kernel/setup.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/arch/mips64/kernel/setup.c	2003-05-26 04:41:41.000000000 -0700
@@ -149,9 +149,8 @@
 	bootmem_init ();
 #endif
 
-	strncpy(command_line, arcs_cmdline, CL_SIZE);
-	memcpy(saved_command_line, command_line, CL_SIZE);
-	saved_command_line[CL_SIZE-1] = '\0';
+	strlcpy(command_line, arcs_cmdline, sizeof(command_line));
+	strlcpy(saved_command_line, command_line, sizeof(saved_command_line));
 
 	*cmdline_p = command_line;
 
diff -urN linux-2.5.69-bk18/arch/mips64/kernel/syscall.c linux-2.5.69-bk19/arch/mips64/kernel/syscall.c
--- linux-2.5.69-bk18/arch/mips64/kernel/syscall.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/mips64/kernel/syscall.c	2003-05-26 04:41:41.000000000 -0700
@@ -147,14 +147,15 @@
 
 		name = (char *) arg1;
 
-		len = strncpy_from_user(nodename, name, sizeof(nodename));
+		len = strncpy_from_user(nodename, name, __NEW_UTS_LEN);
 		if (len < 0)
 			return -EFAULT;
+		nodename[__NEW_UTS_LEN] = '\0';
 
 		down_write(&uts_sem);
-		strncpy(system_utsname.nodename, name, len);
+		strlcpy(system_utsname.nodename, nodename,
+			sizeof(system_utsname.nodename));
 		up_write(&uts_sem);
-		system_utsname.nodename[len] = '\0';
 		return 0;
 	}
 
diff -urN linux-2.5.69-bk18/arch/mips64/mm/init.c linux-2.5.69-bk19/arch/mips64/mm/init.c
--- linux-2.5.69-bk18/arch/mips64/mm/init.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/mips64/mm/init.c	2003-05-26 04:41:41.000000000 -0700
@@ -35,7 +35,7 @@
 #include <asm/mmu_context.h>
 #include <asm/tlb.h>
 
-struct mmu_gather mmu_gathers[NR_CPUS];
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 void pgd_init(unsigned long page)
 {
diff -urN linux-2.5.69-bk18/arch/parisc/kernel/drivers.c linux-2.5.69-bk19/arch/parisc/kernel/drivers.c
--- linux-2.5.69-bk18/arch/parisc/kernel/drivers.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/arch/parisc/kernel/drivers.c	2003-05-26 04:41:41.000000000 -0700
@@ -398,7 +398,7 @@
 	dev->hpa = hpa;
 	name = parisc_hardware_description(&dev->id);
 	if (name) {
-		strncpy(dev->name, name, sizeof(dev->name)-1);
+		strlcpy(dev->name, name, sizeof(dev->name));
 	}
 
 	return dev;
@@ -601,7 +601,7 @@
 		    ndev = ndev->parent) {
 			snprintf(tmp2, sizeof(tmp2), "%d:%s",
 				 ndev->hw_path, tmp1);
-			strncpy(tmp1, tmp2, sizeof(tmp1));
+			strlcpy(tmp1, tmp2, sizeof(tmp1));
 		}
 	}
 
diff -urN linux-2.5.69-bk18/arch/parisc/kernel/ioctl32.c linux-2.5.69-bk19/arch/parisc/kernel/ioctl32.c
--- linux-2.5.69-bk18/arch/parisc/kernel/ioctl32.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk19/arch/parisc/kernel/ioctl32.c	2003-05-26 04:41:41.000000000 -0700
@@ -53,6 +53,7 @@
 #include <linux/pci.h>
 #include <linux/serial.h>
 #include <linux/watchdog.h>
+#include <net/sock.h>		/* siocdevprivate_ioctl */
 
 #include <scsi/scsi.h>
 /* Ugly hack. */
diff -urN linux-2.5.69-bk18/arch/parisc/mm/init.c linux-2.5.69-bk19/arch/parisc/mm/init.c
--- linux-2.5.69-bk18/arch/parisc/mm/init.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/arch/parisc/mm/init.c	2003-05-26 04:41:41.000000000 -0700
@@ -23,7 +23,7 @@
 #include <asm/tlb.h>
 #include <asm/pdc_chassis.h>
 
-struct mmu_gather mmu_gathers[NR_CPUS];
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 extern char _text;	/* start of kernel code, defined by linker */
 extern int  data_start;
diff -urN linux-2.5.69-bk18/arch/ppc/8xx_io/cs4218_tdm.c linux-2.5.69-bk19/arch/ppc/8xx_io/cs4218_tdm.c
--- linux-2.5.69-bk18/arch/ppc/8xx_io/cs4218_tdm.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc/8xx_io/cs4218_tdm.c	2003-05-26 04:41:41.000000000 -0700
@@ -1654,8 +1654,8 @@
 	switch (cmd) {
 		case SOUND_MIXER_INFO: {
 		    mixer_info info;
-		    strncpy(info.id, "CS4218_TDM", sizeof(info.id));
-		    strncpy(info.name, "CS4218_TDM", sizeof(info.name));
+		    strlcpy(info.id, "CS4218_TDM", sizeof(info.id));
+		    strlcpy(info.name, "CS4218_TDM", sizeof(info.name));
 		    info.name[sizeof(info.name)-1] = 0;
 		    info.modify_counter = mixer.modify_counter;
 		    if (copy_to_user((int *)arg, &info, sizeof(info)))
diff -urN linux-2.5.69-bk18/arch/ppc/amiga/bootinfo.c linux-2.5.69-bk19/arch/ppc/amiga/bootinfo.c
--- linux-2.5.69-bk18/arch/ppc/amiga/bootinfo.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc/amiga/bootinfo.c	2003-05-26 04:41:41.000000000 -0700
@@ -59,8 +59,7 @@
 		break;
 
 	    case BI_COMMAND_LINE:
-		strncpy(cmd_line, (const char *)data, CL_SIZE);
-		cmd_line[CL_SIZE-1] = '\0';
+		strlcpy(cmd_line, (const char *)data, sizeof(cmd_line));
 		break;
 
 	    default:
diff -urN linux-2.5.69-bk18/arch/ppc/kernel/setup.c linux-2.5.69-bk19/arch/ppc/kernel/setup.c
--- linux-2.5.69-bk18/arch/ppc/kernel/setup.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc/kernel/setup.c	2003-05-26 04:41:41.000000000 -0700
@@ -403,14 +403,14 @@
 	 * are used for initrd_start and initrd_size,
 	 * otherwise they contain 0xdeadbeef.  
 	 */
+	cmd_line[0] = 0;
 	if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) {
-		cmd_line[0] = 0;
-		strncpy(cmd_line, (char *)r3 + KERNELBASE,
+		strlcpy(cmd_line, (char *)r3 + KERNELBASE,
 			sizeof(cmd_line));
 	} else if (boot_infos != 0) {
 		/* booted by BootX - check for ramdisk */
 		if (boot_infos->kernelParamsOffset != 0)
-			strncpy(cmd_line, (char *) boot_infos
+			strlcpy(cmd_line, (char *) boot_infos
 				+ boot_infos->kernelParamsOffset,
 				sizeof(cmd_line));
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -439,12 +439,10 @@
 		if (chosen != NULL) {
 			p = get_property(chosen, "bootargs", NULL);
 			if (p && *p) {
-				cmd_line[0] = 0;
-				strncpy(cmd_line, p, sizeof(cmd_line));
+				strlcpy(cmd_line, p, sizeof(cmd_line));
 			}
 		}
 	}
-	cmd_line[sizeof(cmd_line) - 1] = 0;
 #ifdef CONFIG_ADB
 	if (strstr(cmd_line, "adb_sync")) {
 		extern int __adb_probe_sync;
diff -urN linux-2.5.69-bk18/arch/ppc/mm/init.c linux-2.5.69-bk19/arch/ppc/mm/init.c
--- linux-2.5.69-bk18/arch/ppc/mm/init.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc/mm/init.c	2003-05-26 04:41:41.000000000 -0700
@@ -53,7 +53,7 @@
 #endif
 #define MAX_LOW_MEM	CONFIG_LOWMEM_SIZE
 
-struct mmu_gather mmu_gathers[NR_CPUS];
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 unsigned long total_memory;
 unsigned long total_lowmem;
diff -urN linux-2.5.69-bk18/arch/ppc/platforms/apus_setup.c linux-2.5.69-bk19/arch/ppc/platforms/apus_setup.c
--- linux-2.5.69-bk18/arch/ppc/platforms/apus_setup.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc/platforms/apus_setup.c	2003-05-26 04:41:41.000000000 -0700
@@ -130,8 +130,7 @@
 	for( p = cmd_line; p && *p; ) {
 	    i = 0;
 	    if (!strncmp( p, "debug=", 6 )) {
-		    strncpy( debug_device, p+6, sizeof(debug_device)-1 );
-		    debug_device[sizeof(debug_device)-1] = 0;
+		    strlcpy( debug_device, p+6, sizeof(debug_device) );
 		    if ((q = strchr( debug_device, ' ' ))) *q = 0;
 		    i = 1;
 	    } else if (!strncmp( p, "60nsram", 7 )) {
diff -urN linux-2.5.69-bk18/arch/ppc/platforms/pmac_cpufreq.c linux-2.5.69-bk19/arch/ppc/platforms/pmac_cpufreq.c
--- linux-2.5.69-bk18/arch/ppc/platforms/pmac_cpufreq.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc/platforms/pmac_cpufreq.c	2003-05-26 04:41:41.000000000 -0700
@@ -330,7 +330,7 @@
 	driver->setpolicy	= &pmac_cpufreq_setpolicy;
 	driver->init		= NULL;
 	driver->exit		= NULL;
-	strncpy(driver->name, "powermac", CPUFREQ_NAME_LEN);
+	strlcpy(driver->name, "powermac", sizeof(driver->name));
 
 	driver->policy[0].cpu				= 0;
 	driver->policy[0].cpuinfo.transition_latency	= CPUFREQ_ETERNAL;
diff -urN linux-2.5.69-bk18/arch/ppc/platforms/zx4500_setup.c linux-2.5.69-bk19/arch/ppc/platforms/zx4500_setup.c
--- linux-2.5.69-bk18/arch/ppc/platforms/zx4500_setup.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc/platforms/zx4500_setup.c	2003-05-26 04:41:41.000000000 -0700
@@ -104,9 +104,9 @@
 #endif
 
 	/* Get boot string from flash */
-	strncpy(boot_string,
+	strlcpy(boot_string,
 		(char *)ZX4500_BOOT_STRING_ADDR,
-		ZX4500_BOOT_STRING_LEN);
+		sizeof(boot_string));
 	boot_string[ZX4500_BOOT_STRING_LEN] = '\0';
 
 	/* Can be delimited by 0xff */
diff -urN linux-2.5.69-bk18/arch/ppc64/boot/addnote.c linux-2.5.69-bk19/arch/ppc64/boot/addnote.c
--- linux-2.5.69-bk18/arch/ppc64/boot/addnote.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc64/boot/addnote.c	2003-05-26 04:41:41.000000000 -0700
@@ -14,6 +14,7 @@
  * Usage: addnote zImage
  */
 #include <stdio.h>
+#include <stdlib.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <string.h>
diff -urN linux-2.5.69-bk18/arch/ppc64/kernel/align.c linux-2.5.69-bk19/arch/ppc64/kernel/align.c
--- linux-2.5.69-bk18/arch/ppc64/kernel/align.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc64/kernel/align.c	2003-05-26 04:41:41.000000000 -0700
@@ -21,6 +21,8 @@
 #include <asm/system.h>
 #include <asm/cache.h>
 
+void disable_kernel_fp(void); /* asm function from head.S */
+
 struct aligninfo {
 	unsigned char len;
 	unsigned char flags;
diff -urN linux-2.5.69-bk18/arch/ppc64/kernel/ioctl32.c linux-2.5.69-bk19/arch/ppc64/kernel/ioctl32.c
--- linux-2.5.69-bk18/arch/ppc64/kernel/ioctl32.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc64/kernel/ioctl32.c	2003-05-26 04:41:41.000000000 -0700
@@ -685,7 +685,7 @@
 		return -EFAULT;
 	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
 		return -EFAULT;
-	data64 = A(data32);
+	data64 = (void __user *)A(data32);
 
 	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
 
diff -urN linux-2.5.69-bk18/arch/ppc64/kernel/misc.S linux-2.5.69-bk19/arch/ppc64/kernel/misc.S
--- linux-2.5.69-bk18/arch/ppc64/kernel/misc.S	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc64/kernel/misc.S	2003-05-26 04:41:41.000000000 -0700
@@ -735,11 +735,11 @@
 	.llong .sys_ni_syscall
 	.llong .sys_ni_syscall		/* 225 - reserved for tux */
 	.llong .sys32_sendfile64
-	.llong .sys_ni_syscall		/* reserved for sys_io_setup */
-	.llong .sys_ni_syscall		/* reserved for sys_io_destroy */
-	.llong .sys_ni_syscall		/* reserved for sys_io_getevents */
-	.llong .sys_ni_syscall		/* 230 - reserved for sys_io_submit */
-	.llong .sys_ni_syscall		/* reserved for sys_io_cancel */
+	.llong .sys32_io_setup
+	.llong .sys_io_destroy
+	.llong .sys32_io_getevents
+	.llong .sys32_io_submit
+	.llong .sys_io_cancel
 	.llong .sys_set_tid_address
 	.llong .ppc32_fadvise64
 	.llong .sys_exit_group
diff -urN linux-2.5.69-bk18/arch/ppc64/kernel/prom.c linux-2.5.69-bk19/arch/ppc64/kernel/prom.c
--- linux-2.5.69-bk18/arch/ppc64/kernel/prom.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc64/kernel/prom.c	2003-05-26 04:41:41.000000000 -0700
@@ -1060,12 +1060,11 @@
 prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
 	  unsigned long r6, unsigned long r7)
 {
-	int chrp = 0;
 	unsigned long mem;
-	ihandle prom_mmu, prom_op, prom_root, prom_cpu;
+	ihandle prom_root, prom_cpu;
 	phandle cpu_pkg;
 	unsigned long offset = reloc_offset();
-	long l, sz;
+	long l;
 	char *p, *d;
  	unsigned long phys;
         u32 getprop_rval;
diff -urN linux-2.5.69-bk18/arch/ppc64/kernel/setup.c linux-2.5.69-bk19/arch/ppc64/kernel/setup.c
--- linux-2.5.69-bk18/arch/ppc64/kernel/setup.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc64/kernel/setup.c	2003-05-26 04:41:41.000000000 -0700
@@ -193,9 +193,9 @@
 	printk("naca                          = 0x%p\n", naca);
 	printk("naca->pftSize                 = 0x%lx\n", naca->pftSize);
 	printk("naca->debug_switch            = 0x%lx\n", naca->debug_switch);
-	printk("naca->interrupt_controller    = 0x%d\n", naca->interrupt_controller);
+	printk("naca->interrupt_controller    = 0x%ld\n", naca->interrupt_controller);
 	printk("systemcf                      = 0x%p\n", systemcfg);
-	printk("systemcfg->processorCount     = 0x%x\n", systemcfg->processorCount);
+	printk("systemcfg->processorCount     = 0x%lx\n", systemcfg->processorCount);
 	printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize);
 	printk("systemcfg->dCacheL1LineSize   = 0x%x\n", systemcfg->dCacheL1LineSize);
 	printk("systemcfg->iCacheL1LineSize   = 0x%x\n", systemcfg->iCacheL1LineSize);
@@ -365,16 +365,15 @@
 	cmd_line[0] = 0;
 
 #ifdef CONFIG_CMDLINE
-	strcpy(cmd_line, CONFIG_CMDLINE);
+	strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
 #endif /* CONFIG_CMDLINE */
 
 	chosen = find_devices("chosen");
 	if (chosen != NULL) {
 		p = get_property(chosen, "bootargs", NULL);
 		if (p != NULL && p[0] != 0)
-			strncpy(cmd_line, p, sizeof(cmd_line));
+			strlcpy(cmd_line, p, sizeof(cmd_line));
 	}
-	cmd_line[sizeof(cmd_line) - 1] = 0;
 
 	/* Look for mem= option on command line */
 	if (strstr(cmd_line, "mem=")) {
diff -urN linux-2.5.69-bk18/arch/ppc64/kernel/sys_ppc32.c linux-2.5.69-bk19/arch/ppc64/kernel/sys_ppc32.c
--- linux-2.5.69-bk18/arch/ppc64/kernel/sys_ppc32.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc64/kernel/sys_ppc32.c	2003-05-26 04:41:41.000000000 -0700
@@ -32,6 +32,7 @@
 #include <linux/shm.h>
 #include <linux/slab.h>
 #include <linux/uio.h>
+#include <linux/aio.h>
 #include <linux/nfs_fs.h>
 #include <linux/smb_fs.h>
 #include <linux/smb_mount.h>
@@ -58,6 +59,7 @@
 #include <linux/security.h>
 #include <linux/compat.h>
 #include <linux/ptrace.h>
+#include <linux/aio_abi.h>
 
 #include <asm/types.h>
 #include <asm/ipc.h>
@@ -2643,6 +2645,98 @@
 	return sys_mmap(addr, len, prot, flags, fd, pgoff << 12);
 }
 
+extern long sys_io_setup(unsigned nr_reqs, aio_context_t *ctx);
+
+long sys32_io_setup(unsigned nr_reqs, u32 *ctx32p)
+{
+	long ret;
+	aio_context_t ctx64;
+	mm_segment_t oldfs = get_fs();
+
+	if (get_user((u32)ctx64, ctx32p))
+		return -EFAULT;
+
+	set_fs(KERNEL_DS);
+	ret = sys_io_setup(nr_reqs, &ctx64);
+	set_fs(oldfs);
+
+	/* truncating is ok because it's a user address */
+	if (!ret)
+		ret = put_user((u32)ctx64, ctx32p);
+
+	return ret;
+}
+
+long sys_io_getevents(aio_context_t ctx_id, long min_nr, long nr,
+		      struct io_event *events, struct timespec *timeout);
+
+long sys32_io_getevents(aio_context_t ctx_id, u32 min_nr, u32 nr,
+			struct io_event *events, struct compat_timespec *t32)
+{
+	struct timespec t;
+	long ret;
+	mm_segment_t oldfs = get_fs();
+
+	if (t32) {
+		if (get_user(t.tv_sec, &t32->tv_sec) ||
+		    __get_user(t.tv_nsec, &t32->tv_nsec))
+			return -EFAULT;
+	}
+
+	if (verify_area(VERIFY_WRITE, events, nr * sizeof(*events)))
+		return -EFAULT;
+
+	set_fs(KERNEL_DS);
+	/* sign extend min_nr and nr */
+	ret = sys_io_getevents(ctx_id, (int)min_nr, (int)nr, events,
+			       t32 ? &t : NULL);
+	set_fs(oldfs);
+
+	return ret;
+}
+
+long sys32_io_submit(aio_context_t ctx_id, u32 number, u32 *iocbpp)
+{
+	struct kioctx *ctx;
+	long ret = 0;
+	int i;
+	int nr = (int)number;	/* sign extend */
+
+	if (unlikely(nr < 0))
+		return -EINVAL;
+
+	if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(u32)))))
+		return -EFAULT;
+
+	ctx = lookup_ioctx(ctx_id);
+	if (unlikely(!ctx)) {
+		pr_debug("EINVAL: io_submit: invalid context id\n");
+		return -EINVAL;
+	}
+
+	for (i=0; i<nr; i++) {
+		struct iocb tmp;
+		u32 *user_iocb;
+
+		if (unlikely(__get_user((u32)(long)user_iocb, iocbpp + i))) {
+			ret = -EFAULT;
+			break;
+		}
+
+		if (unlikely(copy_from_user(&tmp, user_iocb, sizeof(tmp)))) {
+			ret = -EFAULT;
+			break;
+		}
+
+		ret = io_submit_one(ctx, (struct iocb *)user_iocb, &tmp);
+		if (ret)
+			break;
+	}
+
+	put_ioctx(ctx);
+	return i ? i : ret;
+}
+
 /* 
  * long long munging:
  * The 32 bit ABI passes long longs in an odd even register pair.
diff -urN linux-2.5.69-bk18/arch/ppc64/kernel/traps.c linux-2.5.69-bk19/arch/ppc64/kernel/traps.c
--- linux-2.5.69-bk18/arch/ppc64/kernel/traps.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc64/kernel/traps.c	2003-05-26 04:41:41.000000000 -0700
@@ -346,10 +346,11 @@
 	}
 }
 
- void
+void
 KernelFPUnavailableException(struct pt_regs *regs)
 {
-	printk("Illegal floating point used in kernel (task=0x%016lx, pc=0x%016lx, trap=0x%08x)\n",
+	printk("Illegal floating point used in kernel "
+			"(task=0x%p, pc=0x%016lx, trap=0x%08lx)\n",
 		current, regs->nip, regs->trap);
 	panic("Unrecoverable FP Unavailable Exception in Kernel");
 }
diff -urN linux-2.5.69-bk18/arch/ppc64/kernel/xics.c linux-2.5.69-bk19/arch/ppc64/kernel/xics.c
--- linux-2.5.69-bk18/arch/ppc64/kernel/xics.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc64/kernel/xics.c	2003-05-26 04:41:41.000000000 -0700
@@ -25,6 +25,7 @@
 #include <asm/xics.h>
 #include <asm/ppcdebug.h>
 #include <asm/hvcall.h>
+#include <asm/machdep.h>
 
 #include "i8259.h"
 
@@ -322,11 +323,9 @@
 irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int cpu = smp_processor_id();
-	int handled = 0;
 
 	ops->qirr_info(cpu, 0xff);
 	while (xics_ipi_message[cpu].value) {
-		handled = 1;
 		if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION,
 				       &xics_ipi_message[cpu].value)) {
 			mb();
@@ -352,7 +351,7 @@
 		}
 #endif
 	}
-	return IRQ_RETVAL(handled);
+	return IRQ_HANDLED;
 }
 
 void xics_cause_IPI(int cpu)
diff -urN linux-2.5.69-bk18/arch/ppc64/mm/init.c linux-2.5.69-bk19/arch/ppc64/mm/init.c
--- linux-2.5.69-bk18/arch/ppc64/mm/init.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/ppc64/mm/init.c	2003-05-26 04:41:41.000000000 -0700
@@ -93,7 +93,7 @@
 /* This is declared as we are using the more or less generic 
  * include/asm-ppc64/tlb.h file -- tgall
  */
-struct mmu_gather     mmu_gathers[NR_CPUS];
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 void show_mem(void)
 {
diff -urN linux-2.5.69-bk18/arch/s390/kernel/debug.c linux-2.5.69-bk19/arch/s390/kernel/debug.c
--- linux-2.5.69-bk18/arch/s390/kernel/debug.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/arch/s390/kernel/debug.c	2003-05-26 04:41:41.000000000 -0700
@@ -208,8 +208,7 @@
 	rc->level       = DEBUG_DEFAULT_LEVEL;
 	rc->buf_size    = buf_size;
 	rc->entry_size  = sizeof(debug_entry_t) + buf_size;
-	strncpy(rc->name, name, MIN(strlen(name), (DEBUG_MAX_PROCF_LEN - 1)));
-	rc->name[MIN(strlen(name), (DEBUG_MAX_PROCF_LEN - 1))] = 0;
+	strlcpy(rc->name, name, sizeof(rc->name));
 	memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
 #ifdef CONFIG_PROC_FS
 	memset(rc->proc_entries, 0 ,DEBUG_MAX_VIEWS *
diff -urN linux-2.5.69-bk18/arch/s390/mm/init.c linux-2.5.69-bk19/arch/s390/mm/init.c
--- linux-2.5.69-bk18/arch/s390/mm/init.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/arch/s390/mm/init.c	2003-05-26 04:41:41.000000000 -0700
@@ -38,7 +38,7 @@
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 
-struct mmu_gather mmu_gathers[NR_CPUS];
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
 char  empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
diff -urN linux-2.5.69-bk18/arch/sh/mm/init.c linux-2.5.69-bk19/arch/sh/mm/init.c
--- linux-2.5.69-bk18/arch/sh/mm/init.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk19/arch/sh/mm/init.c	2003-05-26 04:41:41.000000000 -0700
@@ -36,7 +36,7 @@
 #include <asm/io.h>
 #include <asm/tlb.h>
 
-struct mmu_gather mmu_gathers[NR_CPUS];
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 /*
  * Cache of MMU context last used.
diff -urN linux-2.5.69-bk18/arch/sparc/kernel/ioport.c linux-2.5.69-bk19/arch/sparc/kernel/ioport.c
--- linux-2.5.69-bk18/arch/sparc/kernel/ioport.c	2003-05-04 16:53:56.000000000 -0700
+++ linux-2.5.69-bk19/arch/sparc/kernel/ioport.c	2003-05-26 04:41:41.000000000 -0700
@@ -179,8 +179,7 @@
 		tack += sizeof (struct resource);
 	}
 
-	strncpy(tack, name, XNMLN);
-	tack[XNMLN] = 0;
+	strlcpy(tack, name, XNMLN+1);
 	res->name = tack;
 
 	va = _sparc_ioremap(res, busno, phys, size);
diff -urN linux-2.5.69-bk18/arch/sparc/kernel/sys_sunos.c linux-2.5.69-bk19/arch/sparc/kernel/sys_sunos.c
--- linux-2.5.69-bk18/arch/sparc/kernel/sys_sunos.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/arch/sparc/kernel/sys_sunos.c	2003-05-26 04:41:41.000000000 -0700
@@ -738,8 +738,8 @@
 	if(IS_ERR(the_name))
 		return PTR_ERR(the_name);
 
-	strncpy (linux_nfs_mount.hostname, the_name, 254);
-	linux_nfs_mount.hostname [255] = 0;
+	strlcpy(linux_nfs_mount.hostname, the_name,
+		sizeof(linux_nfs_mount.hostname));
 	putname (the_name);
 	
 	return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount);
diff -urN linux-2.5.69-bk18/arch/sparc/mm/init.c linux-2.5.69-bk19/arch/sparc/mm/init.c
--- linux-2.5.69-bk18/arch/sparc/mm/init.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/sparc/mm/init.c	2003-05-26 04:41:41.000000000 -0700
@@ -32,7 +32,7 @@
 #include <asm/pgalloc.h>	/* bug in asm-generic/tlb.h: check_pgt_cache */
 #include <asm/tlb.h>
 
-struct mmu_gather mmu_gathers[NR_CPUS];
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 unsigned long *sparc_valid_addr_bitmap;
 
diff -urN linux-2.5.69-bk18/arch/sparc/prom/bootstr.c linux-2.5.69-bk19/arch/sparc/prom/bootstr.c
--- linux-2.5.69-bk18/arch/sparc/prom/bootstr.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/sparc/prom/bootstr.c	2003-05-26 04:41:41.000000000 -0700
@@ -52,7 +52,7 @@
 		 * V3 PROM cannot supply as with more than 128 bytes
 		 * of an argument. But a smart bootstrap loader can.
 		 */
-		strncpy(barg_buf, *romvec->pv_v2bootargs.bootargs, BARG_LEN-1);
+		strlcpy(barg_buf, *romvec->pv_v2bootargs.bootargs, sizeof(barg_buf));
 		break;
 	default:
 		break;
diff -urN linux-2.5.69-bk18/arch/sparc64/Kconfig linux-2.5.69-bk19/arch/sparc64/Kconfig
--- linux-2.5.69-bk18/arch/sparc64/Kconfig	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/arch/sparc64/Kconfig	2003-05-26 04:41:41.000000000 -0700
@@ -1445,6 +1445,12 @@
 
 source "net/ax25/Kconfig"
 
+source "net/irda/Kconfig"
+
+source "drivers/isdn/Kconfig"
+
+source "drivers/telephony/Kconfig"
+
 # This one must be before the filesystem configs. -DaveM
 
 menu "Unix 98 PTY support"
diff -urN linux-2.5.69-bk18/arch/sparc64/defconfig linux-2.5.69-bk19/arch/sparc64/defconfig
--- linux-2.5.69-bk18/arch/sparc64/defconfig	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/sparc64/defconfig	2003-05-26 04:41:41.000000000 -0700
@@ -444,6 +444,7 @@
 CONFIG_IPV6_PRIVACY=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
 
 #
 # IPv6: Netfilter Configuration
@@ -742,6 +743,104 @@
 # CONFIG_YAM is not set
 
 #
+# IrDA (infrared) support
+#
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRTTY_OLD is not set
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+# CONFIG_DONGLE_OLD is not set
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_NSC_FIR is not set
+# CONFIG_WINBOND_FIR is not set
+# CONFIG_TOSHIBA_OLD is not set
+# CONFIG_TOSHIBA_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+# CONFIG_ALI_FIR is not set
+# CONFIG_VLSI_FIR is not set
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN_BOOL=y
+
+#
+# Old ISDN4Linux
+#
+# CONFIG_ISDN is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+# CONFIG_CAPI_AVM is not set
+
+#
+# Active Eicon DIVA Server cards
+#
+# CONFIG_CAPI_EICON is not set
+
+#
+# Telephony Support
+#
+CONFIG_PHONE=m
+CONFIG_PHONE_IXJ=m
+# CONFIG_PHONE_IXJ_PCMCIA is not set
+
+#
 # Unix 98 PTY support
 #
 CONFIG_UNIX98_PTYS=y
diff -urN linux-2.5.69-bk18/arch/sparc64/kernel/ioctl32.c linux-2.5.69-bk19/arch/sparc64/kernel/ioctl32.c
--- linux-2.5.69-bk18/arch/sparc64/kernel/ioctl32.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/sparc64/kernel/ioctl32.c	2003-05-26 04:41:41.000000000 -0700
@@ -56,6 +56,7 @@
 #include <linux/rtc.h>
 #include <linux/pci.h>
 #include <linux/dm-ioctl.h>
+#include <net/sock.h>		/* siocdevprivate_ioctl */
 
 #include <scsi/scsi.h>
 /* Ugly hack. */
diff -urN linux-2.5.69-bk18/arch/sparc64/kernel/sys_sunos32.c linux-2.5.69-bk19/arch/sparc64/kernel/sys_sunos32.c
--- linux-2.5.69-bk18/arch/sparc64/kernel/sys_sunos32.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/arch/sparc64/kernel/sys_sunos32.c	2003-05-26 04:41:41.000000000 -0700
@@ -704,8 +704,8 @@
 	if(IS_ERR(the_name))
 		return PTR_ERR(the_name);
 
-	strncpy (linux_nfs_mount.hostname, the_name, 254);
-	linux_nfs_mount.hostname [255] = 0;
+	strlcpy(linux_nfs_mount.hostname, the_name,
+		sizeof(linux_nfs_mount.hostname));
 	putname (the_name);
 	
 	return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount);
diff -urN linux-2.5.69-bk18/arch/sparc64/mm/init.c linux-2.5.69-bk19/arch/sparc64/mm/init.c
--- linux-2.5.69-bk18/arch/sparc64/mm/init.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk19/arch/sparc64/mm/init.c	2003-05-26 04:41:41.000000000 -0700
@@ -36,7 +36,7 @@
 #include <asm/tlb.h>
 #include <asm/spitfire.h>
 
-struct mmu_gather mmu_gathers[NR_CPUS];
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 extern void device_scan(void);
 
diff -urN linux-2.5.69-bk18/arch/um/drivers/line.c linux-2.5.69-bk19/arch/um/drivers/line.c
--- linux-2.5.69-bk18/arch/um/drivers/line.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/arch/um/drivers/line.c	2003-05-26 04:41:41.000000000 -0700
@@ -563,9 +563,7 @@
 		return(base);
 	}
 
-	strncpy(title, base, len);
-	len -= strlen(title);
-	snprintf(&title[strlen(title)], len, " (%s)", umid);
+	snprintf(title, len, "%s (%s)", base, umid);
 	return(title);
 }
 
diff -urN linux-2.5.69-bk18/arch/um/kernel/mem.c linux-2.5.69-bk19/arch/um/kernel/mem.c
--- linux-2.5.69-bk18/arch/um/kernel/mem.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/um/kernel/mem.c	2003-05-26 04:41:41.000000000 -0700
@@ -45,7 +45,7 @@
 extern long physmem_size;
 
 /* Not changed by UML */
-struct mmu_gather mmu_gathers[NR_CPUS];
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 /* Changed during early boot */
 int kmalloc_ok = 0;
diff -urN linux-2.5.69-bk18/arch/um/kernel/umid.c linux-2.5.69-bk19/arch/um/kernel/umid.c
--- linux-2.5.69-bk18/arch/um/kernel/umid.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/arch/um/kernel/umid.c	2003-05-26 04:41:41.000000000 -0700
@@ -45,8 +45,7 @@
 	if(strlen(name) > UMID_LEN - 1)
 		printk("Unique machine name is being truncated to %s "
 		       "characters\n", UMID_LEN);
-	strncpy(umid, name, UMID_LEN - 1);
-	umid[UMID_LEN - 1] = '\0';
+	strlcpy(umid, name, sizeof(umid));
 
 	umid_is_random = is_random;
 	umid_inited = 1;
@@ -222,7 +221,7 @@
 			       "$HOME\n");
 			exit(1);
 		}
-		strncpy(dir, home, sizeof(dir));
+		strlcpy(dir, home, sizeof(dir));
 		uml_dir++;
 	}
 	len = strlen(dir);
@@ -251,8 +250,7 @@
 	int fd, err;
 	char tmp[strlen(uml_dir) + UMID_LEN + 1];
 
-	strncpy(tmp, uml_dir, sizeof(tmp) - 1);
-	tmp[sizeof(tmp) - 1] = '\0';
+	strlcpy(tmp, uml_dir, sizeof(tmp));
 
 	if(*umid == 0){
 		strcat(tmp, "XXXXXX");
diff -urN linux-2.5.69-bk18/arch/um/os-Linux/drivers/tuntap_user.c linux-2.5.69-bk19/arch/um/os-Linux/drivers/tuntap_user.c
--- linux-2.5.69-bk18/arch/um/os-Linux/drivers/tuntap_user.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/arch/um/os-Linux/drivers/tuntap_user.c	2003-05-26 04:41:41.000000000 -0700
@@ -143,7 +143,7 @@
 		}
 		memset(&ifr, 0, sizeof(ifr));
 		ifr.ifr_flags = IFF_TAP;
-		strncpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name) - 1);
+		strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
 		if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){
 			printk("TUNSETIFF failed, errno = %d", errno);
 			close(pri->fd);
diff -urN linux-2.5.69-bk18/arch/x86_64/ia32/ia32_ioctl.c linux-2.5.69-bk19/arch/x86_64/ia32/ia32_ioctl.c
--- linux-2.5.69-bk18/arch/x86_64/ia32/ia32_ioctl.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/x86_64/ia32/ia32_ioctl.c	2003-05-26 04:41:41.000000000 -0700
@@ -61,6 +61,7 @@
 #include <linux/if_tun.h>
 #include <linux/dirent.h>
 #include <linux/ctype.h>
+#include <net/sock.h>		/* siocdevprivate_ioctl */
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/rfcomm.h>
 
@@ -467,8 +468,7 @@
 	if (!dev)
 		return -ENODEV;
 
-	strncpy(ifr32.ifr_name, dev->name, sizeof(ifr32.ifr_name)-1);
-	ifr32.ifr_name[sizeof(ifr32.ifr_name)-1] = 0; 
+	strlcpy(ifr32.ifr_name, dev->name, sizeof(ifr32.ifr_name));
 	dev_put(dev);
 	
 	err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32));
diff -urN linux-2.5.69-bk18/arch/x86_64/kernel/early_printk.c linux-2.5.69-bk19/arch/x86_64/kernel/early_printk.c
--- linux-2.5.69-bk18/arch/x86_64/kernel/early_printk.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/x86_64/kernel/early_printk.c	2003-05-26 04:41:41.000000000 -0700
@@ -170,8 +170,7 @@
 	if (early_console_initialized)
 		return -1;
 
-	strncpy(buf,opt,256); 
-	buf[255] = 0; 
+	strlcpy(buf,opt,sizeof(buf)); 
 	space = strchr(buf, ' '); 
 	if (space)
 		*space = 0; 
diff -urN linux-2.5.69-bk18/arch/x86_64/mm/init.c linux-2.5.69-bk19/arch/x86_64/mm/init.c
--- linux-2.5.69-bk18/arch/x86_64/mm/init.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/arch/x86_64/mm/init.c	2003-05-26 04:41:41.000000000 -0700
@@ -41,7 +41,7 @@
 
 #define Dprintk(x...)
 
-struct mmu_gather mmu_gathers[NR_CPUS];
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 /*
  * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the
diff -urN linux-2.5.69-bk18/drivers/acorn/block/fd1772.c linux-2.5.69-bk19/drivers/acorn/block/fd1772.c
--- linux-2.5.69-bk18/drivers/acorn/block/fd1772.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/drivers/acorn/block/fd1772.c	2003-05-26 04:41:41.000000000 -0700
@@ -1513,7 +1513,7 @@
 	.revalidate_disk= floppy_revalidate,
 };
 
-static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
+static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 {
 	int drive = *part & 3;
 	if ((*part >> 2) > NUM_DISK_TYPES || drive >= FD_MAX_UNITS)
diff -urN linux-2.5.69-bk18/drivers/base/Makefile linux-2.5.69-bk19/drivers/base/Makefile
--- linux-2.5.69-bk18/drivers/base/Makefile	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk19/drivers/base/Makefile	2003-05-26 04:41:41.000000000 -0700
@@ -2,5 +2,5 @@
 
 obj-y			:= core.o sys.o interface.o power.o bus.o \
 			   driver.o class.o platform.o \
-			   cpu.o firmware.o init.o
+			   cpu.o firmware.o init.o map.o
 obj-$(CONFIG_NUMA)	+= node.o  memblk.o
diff -urN linux-2.5.69-bk18/drivers/base/bus.c linux-2.5.69-bk19/drivers/base/bus.c
--- linux-2.5.69-bk18/drivers/base/bus.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/drivers/base/bus.c	2003-05-26 04:41:41.000000000 -0700
@@ -431,7 +431,7 @@
 	if (bus) {
 		pr_debug("bus %s: add driver %s\n",bus->name,drv->name);
 
-		strncpy(drv->kobj.name,drv->name,KOBJ_NAME_LEN);
+		strlcpy(drv->kobj.name,drv->name,KOBJ_NAME_LEN);
 		drv->kobj.kset = &bus->drivers;
 
 		if ((error = kobject_register(&drv->kobj))) {
@@ -540,15 +540,15 @@
  */
 int bus_register(struct bus_type * bus)
 {
-	strncpy(bus->subsys.kset.kobj.name,bus->name,KOBJ_NAME_LEN);
+	strlcpy(bus->subsys.kset.kobj.name,bus->name,KOBJ_NAME_LEN);
 	subsys_set_kset(bus,bus_subsys);
 	subsystem_register(&bus->subsys);
 
-	snprintf(bus->devices.kobj.name,KOBJ_NAME_LEN,"devices");
+	strlcpy(bus->devices.kobj.name, "devices", KOBJ_NAME_LEN);
 	bus->devices.subsys = &bus->subsys;
 	kset_register(&bus->devices);
 
-	snprintf(bus->drivers.kobj.name,KOBJ_NAME_LEN,"drivers");
+	strlcpy(bus->drivers.kobj.name, "drivers", KOBJ_NAME_LEN);
 	bus->drivers.subsys = &bus->subsys;
 	bus->drivers.ktype = &ktype_driver;
 	kset_register(&bus->drivers);
diff -urN linux-2.5.69-bk18/drivers/base/class.c linux-2.5.69-bk19/drivers/base/class.c
--- linux-2.5.69-bk18/drivers/base/class.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/drivers/base/class.c	2003-05-26 04:41:41.000000000 -0700
@@ -88,7 +88,7 @@
 	INIT_LIST_HEAD(&cls->children);
 	INIT_LIST_HEAD(&cls->interfaces);
 	
-	strncpy(cls->subsys.kset.kobj.name,cls->name,KOBJ_NAME_LEN);
+	strlcpy(cls->subsys.kset.kobj.name,cls->name,KOBJ_NAME_LEN);
 	subsys_set_kset(cls,class_subsys);
 	subsystem_register(&cls->subsys);
 
@@ -258,7 +258,7 @@
 		 class_dev->class_id);
 
 	/* first, register with generic layer. */
-	strncpy(class_dev->kobj.name, class_dev->class_id, KOBJ_NAME_LEN);
+	strlcpy(class_dev->kobj.name, class_dev->class_id, KOBJ_NAME_LEN);
 	kobj_set_kset_s(class_dev, class_obj_subsys);
 	if (parent)
 		class_dev->kobj.parent = &parent->subsys.kset.kobj;
diff -urN linux-2.5.69-bk18/drivers/base/core.c linux-2.5.69-bk19/drivers/base/core.c
--- linux-2.5.69-bk18/drivers/base/core.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/drivers/base/core.c	2003-05-26 04:41:41.000000000 -0700
@@ -211,7 +211,7 @@
 		 dev->bus_id, dev->name);
 
 	/* first, register with generic layer. */
-	strncpy(dev->kobj.name,dev->bus_id,KOBJ_NAME_LEN);
+	strlcpy(dev->kobj.name,dev->bus_id,KOBJ_NAME_LEN);
 	if (parent)
 		dev->kobj.parent = &parent->kobj;
 
diff -urN linux-2.5.69-bk18/drivers/base/map.c linux-2.5.69-bk19/drivers/base/map.c
--- linux-2.5.69-bk18/drivers/base/map.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/drivers/base/map.c	2003-05-26 04:41:41.000000000 -0700
@@ -0,0 +1,154 @@
+/*
+ *  linux/drivers/base/map.c
+ *
+ * (C) Copyright Al Viro 2002,2003
+ *	Released under GPL v2.
+ *
+ * NOTE: data structure needs to be changed.  It works, but for large dev_t
+ * it will be too slow.  It is isolated, though, so these changes will be
+ * local to that file.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kdev_t.h>
+#include <linux/kobject.h>
+#include <linux/kobj_map.h>
+
+struct kobj_map {
+	struct probe {
+		struct probe *next;
+		dev_t dev;
+		unsigned long range;
+		struct module *owner;
+		kobj_probe_t *get;
+		int (*lock)(dev_t, void *);
+		void *data;
+	} *probes[255];
+	struct rw_semaphore *sem;
+};
+
+static inline int dev_to_index(dev_t dev)
+{
+	return MAJOR(dev) % 255;
+}
+
+int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
+	     struct module *module, kobj_probe_t *probe,
+	     int (*lock)(dev_t, void *), void *data)
+{
+	unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
+	unsigned index = MAJOR(dev);
+	unsigned i;
+	struct probe *p;
+
+	if (n > 255)
+		n = 255;
+
+	p = kmalloc(sizeof(struct probe) * n, GFP_KERNEL);
+
+	if (p == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < n; i++, p++) {
+		p->owner = module;
+		p->get = probe;
+		p->lock = lock;
+		p->dev = dev;
+		p->range = range;
+		p->data = data;
+	}
+	down_write(domain->sem);
+	for (i = 0, p -= n; i < n; i++, p++, index++) {
+		struct probe **s = &domain->probes[index % 255];
+		while (*s && (*s)->range < range)
+			s = &(*s)->next;
+		p->next = *s;
+		*s = p;
+	}
+	up_write(domain->sem);
+	return 0;
+}
+
+void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
+{
+	unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
+	unsigned index = MAJOR(dev);
+	unsigned i;
+	struct probe *found = NULL;
+
+	if (n > 255)
+		n = 255;
+
+	down_write(domain->sem);
+	for (i = 0; i < n; i++, index++) {
+		struct probe **s;
+		for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) {
+			struct probe *p = *s;
+			if (p->dev == dev && p->range == range) {
+				*s = p->next;
+				if (!found)
+					found = p;
+				break;
+			}
+		}
+	}
+	up_write(domain->sem);
+	kfree(found);
+}
+
+struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
+{
+	struct kobject *kobj;
+	struct probe *p;
+	unsigned best = ~0U;
+
+retry:
+	down_read(domain->sem);
+	for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) {
+		struct kobject *(*probe)(dev_t, int *, void *);
+		struct module *owner;
+		void *data;
+
+		if (p->dev > dev || p->dev + p->range - 1 < dev)
+			continue;
+		if (p->range - 1 >= best)
+			break;
+		if (!try_module_get(p->owner))
+			continue;
+		owner = p->owner;
+		data = p->data;
+		probe = p->get;
+		best = p->range - 1;
+		*index = dev - p->dev;
+		if (p->lock && p->lock(dev, data) < 0) {
+			module_put(owner);
+			continue;
+		}
+		up_read(domain->sem);
+		kobj = probe(dev, index, data);
+		/* Currently ->owner protects _only_ ->probe() itself. */
+		module_put(owner);
+		if (kobj)
+			return kobj;
+		goto retry;
+	}
+	up_read(domain->sem);
+	return NULL;
+}
+
+struct kobj_map *kobj_map_init(kobj_probe_t *base_probe,
+		struct subsystem *s)
+{
+	struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
+	struct probe *base = kmalloc(sizeof(struct probe), GFP_KERNEL);
+	int i;
+	memset(base, 0, sizeof(struct probe));
+	base->dev = 1;
+	base->range = ~0;
+	base->get = base_probe;
+	for (i = 0; i < 255; i++)
+		p->probes[i] = base;
+	p->sem = &s->rwsem;
+	return p;
+}
diff -urN linux-2.5.69-bk18/drivers/base/sys.c linux-2.5.69-bk19/drivers/base/sys.c
--- linux-2.5.69-bk18/drivers/base/sys.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/drivers/base/sys.c	2003-05-26 04:41:41.000000000 -0700
@@ -63,8 +63,8 @@
 
 	error = device_register(&root->dev);
 	if (!error) {
-		strncpy(root->sysdev.bus_id,"sys",BUS_ID_SIZE);
-		strncpy(root->sysdev.name,"System Bus",DEVICE_NAME_SIZE);
+		strlcpy(root->sysdev.bus_id,"sys",BUS_ID_SIZE);
+		strlcpy(root->sysdev.name,"System Bus",DEVICE_NAME_SIZE);
 		root->sysdev.parent = &root->dev;
 		error = device_register(&root->sysdev);
 	};
diff -urN linux-2.5.69-bk18/drivers/block/acsi.c linux-2.5.69-bk19/drivers/block/acsi.c
--- linux-2.5.69-bk18/drivers/block/acsi.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/drivers/block/acsi.c	2003-05-26 04:41:41.000000000 -0700
@@ -348,7 +348,7 @@
                         rwflag, int enable);
 static int acsi_reqsense( char *buffer, int targ, int lun);
 static void acsi_print_error(const unsigned char *errblk, int struct acsi_info_struct *aip);
-static void acsi_interrupt (int irq, void *data, struct pt_regs *fp);
+static irqreturn_t acsi_interrupt (int irq, void *data, struct pt_regs *fp);
 static void unexpected_acsi_interrupt( void );
 static void bad_rw_intr( void );
 static void read_intr( void );
@@ -728,7 +728,7 @@
  *
  *******************************************************************/
 
-static void acsi_interrupt(int irq, void *data, struct pt_regs *fp )
+static irqreturn_t acsi_interrupt(int irq, void *data, struct pt_regs *fp )
 
 {	void (*acsi_irq_handler)(void) = do_acsi;
 
@@ -738,6 +738,7 @@
 	if (!acsi_irq_handler)
 		acsi_irq_handler = unexpected_acsi_interrupt;
 	acsi_irq_handler();
+	return IRQ_HANDLED;
 }
 
 
diff -urN linux-2.5.69-bk18/drivers/block/acsi_slm.c linux-2.5.69-bk19/drivers/block/acsi_slm.c
--- linux-2.5.69-bk18/drivers/block/acsi_slm.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/drivers/block/acsi_slm.c	2003-05-26 04:41:41.000000000 -0700
@@ -247,7 +247,7 @@
 static ssize_t slm_read( struct file* file, char *buf, size_t count, loff_t
                          *ppos );
 static void start_print( int device );
-static void slm_interrupt(int irc, void *data, struct pt_regs *fp);
+static irqreturn_t slm_interrupt(int irc, void *data, struct pt_regs *fp);
 static void slm_test_ready( unsigned long dummy );
 static void set_dma_addr( unsigned long paddr );
 static unsigned long get_dma_addr( void );
@@ -455,7 +455,7 @@
 
 /* Only called when an error happened or at the end of a page */
 
-static void slm_interrupt(int irc, void *data, struct pt_regs *fp)
+static irqreturn_t slm_interrupt(int irc, void *data, struct pt_regs *fp)
 
 {	unsigned long	addr;
 	int				stat;
@@ -476,6 +476,7 @@
 	wake_up( &print_wait );
 	stdma_release();
 	ENABLE_IRQ();
+	return IRQ_HANDLED;
 }
 
 
diff -urN linux-2.5.69-bk18/drivers/block/amiflop.c linux-2.5.69-bk19/drivers/block/amiflop.c
--- linux-2.5.69-bk18/drivers/block/amiflop.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/drivers/block/amiflop.c	2003-05-26 04:41:41.000000000 -0700
@@ -216,10 +216,11 @@
 
 /* Milliseconds timer */
 
-static void ms_isr(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t ms_isr(int irq, void *dummy, struct pt_regs *fp)
 {
 	ms_busy = -1;
 	wake_up(&ms_wait);
+	return IRQ_HANDLED;
 }
 
 /* all waits are queued up 
@@ -576,7 +577,7 @@
 	return (id);
 }
 
-static void fd_block_done(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t fd_block_done(int irq, void *dummy, struct pt_regs *fp)
 {
 	if (block_flag)
 		custom.dsklen = 0x4000;
@@ -591,6 +592,7 @@
 		block_flag = 0;
 		wake_up (&wait_fd_block);
 	}
+	return IRQ_HANDLED;
 }
 
 static void raw_read(int drive)
@@ -1728,7 +1730,7 @@
 	return -ENOMEM;
 }
  
-static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
+static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 {
 	int drive = *part & 3;
 	if (unit[drive].type->code == FD_NODRIVE)
diff -urN linux-2.5.69-bk18/drivers/block/ataflop.c linux-2.5.69-bk19/drivers/block/ataflop.c
--- linux-2.5.69-bk18/drivers/block/ataflop.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/drivers/block/ataflop.c	2003-05-26 04:41:41.000000000 -0700
@@ -364,7 +364,7 @@
 static void check_change( unsigned long dummy );
 static __inline__ void set_head_settle_flag( void );
 static __inline__ int get_head_settle_flag( void );
-static void floppy_irq (int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t floppy_irq (int irq, void *dummy, struct pt_regs *fp);
 static void fd_error( void );
 static int do_format(int drive, int type, struct atari_format_descr *desc);
 static void do_fd_action( int drive );
@@ -597,7 +597,7 @@
 
 static void (*FloppyIRQHandler)( int status ) = NULL;
 
-static void floppy_irq (int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t floppy_irq (int irq, void *dummy, struct pt_regs *fp)
 {
 	unsigned char status;
 	void (*handler)( int );
@@ -613,6 +613,7 @@
 	else {
 		DPRINT(("FDC irq, no handler\n"));
 	}
+	return IRQ_HANDLED;
 }
 
 
@@ -1570,7 +1571,7 @@
 		 */
 
 		/* get the parameters from user space */
-		if (p->ref != 1 && p->ref != -1)
+		if (floppy->ref != 1 && floppy->ref != -1)
 			return -EBUSY;
 		if (copy_from_user(&setprm, (void *) param, sizeof(setprm)))
 			return -EFAULT;
@@ -1617,7 +1618,7 @@
 				    printk (KERN_INFO "floppy%d: setting %s %p!\n",
 				        drive, dtp->name, dtp);
 				UDT = dtp;
-				set_capacity(p->disk, UDT->blocks);
+				set_capacity(floppy->disk, UDT->blocks);
 
 				if (cmd == FDDEFPRM) {
 				  /* save settings as permanent default type */
@@ -1663,7 +1664,7 @@
 		}
 
 		UDT = dtp;
-		set_capacity(p->disk, UDT->blocks);
+		set_capacity(floppy->disk, UDT->blocks);
 
 		return 0;
 	case FDMSGON:
@@ -1677,7 +1678,7 @@
 	case FDFMTBEG:
 		return 0;
 	case FDFMTTRK:
-		if (p->ref != 1 && p->ref != -1)
+		if (floppy->ref != 1 && floppy->ref != -1)
 			return -EBUSY;
 		if (copy_from_user(&fmt_desc, (void *) param, sizeof(fmt_desc)))
 			return -EFAULT;
@@ -1686,7 +1687,7 @@
 		UDT = NULL;
 		/* MSch: invalidate default_params */
 		default_params[drive].blocks  = 0;
-		set_capacity(p->disk, MAX_DISK_SIZE * 2);
+		set_capacity(floppy->disk, MAX_DISK_SIZE * 2);
 	case FDFMTEND:
 	case FDFLUSH:
 		/* invalidate the buffer track to force a reread */
@@ -1895,7 +1896,7 @@
 	.revalidate_disk= floppy_revalidate,
 };
 
-static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
+static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 {
 	int drive = *part & 3;
 	int type  = *part >> 2;
diff -urN linux-2.5.69-bk18/drivers/block/cpqarray.c linux-2.5.69-bk19/drivers/block/cpqarray.c
--- linux-2.5.69-bk18/drivers/block/cpqarray.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/drivers/block/cpqarray.c	2003-05-26 04:41:41.000000000 -0700
@@ -134,7 +134,7 @@
 static int ida_open(struct inode *inode, struct file *filep);
 static int ida_release(struct inode *inode, struct file *filep);
 static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
-static int ida_ctlr_ioctl(int ctlr, int dsk, ida_ioctl_t *io);
+static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io);
 
 static void do_ida_request(request_queue_t *q);
 static void start_io(ctlr_info_t *h);
@@ -147,7 +147,7 @@
 static irqreturn_t do_ida_intr(int irq, void *dev_id, struct pt_regs * regs);
 static void ida_timer(unsigned long tdata);
 static int ida_revalidate(struct gendisk *disk);
-static int revalidate_allvol(kdev_t dev);
+static int revalidate_allvol(ctlr_info_t *host);
 
 #ifdef CONFIG_PROC_FS
 static void ida_procinit(int i);
@@ -158,6 +158,17 @@
 			     int length, int *eof, void *data) { return 0;}
 #endif
 
+static inline drv_info_t *get_drv(struct gendisk *disk)
+{
+	return disk->private_data;
+}
+
+static inline ctlr_info_t *get_host(struct gendisk *disk)
+{
+	return disk->queue->queuedata;
+}
+
+
 static struct block_device_operations ida_fops  = {
 	.owner		= THIS_MODULE,
 	.open		= ida_open,
@@ -401,7 +412,7 @@
 			disk->major = COMPAQ_SMART2_MAJOR + i;
 			disk->first_minor = j<<NWD_SHIFT;
 			disk->fops = &ida_fops; 
-			if (!drv->nr_blks)
+			if (j && !drv->nr_blks)
 				continue;
 			hba[i]->queue.hardsect_size = drv->blk_size;
 			set_capacity(disk, drv->nr_blks);
@@ -704,27 +715,23 @@
  */
 static int ida_open(struct inode *inode, struct file *filep)
 {
-	int ctlr = major(inode->i_rdev) - COMPAQ_SMART2_MAJOR;
-	int dsk  = minor(inode->i_rdev) >> NWD_SHIFT;
-
-	DBGINFO(printk("ida_open %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) );
-	if (ctlr > MAX_CTLR || hba[ctlr] == NULL)
-		return -ENXIO;
+	drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
+	ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
 
+	DBGINFO(printk("ida_open %s\n", inode->i_bdev->bd_disk->disk_name));
 	/*
 	 * Root is allowed to open raw volume zero even if it's not configured
 	 * so array config can still work.  I don't think I really like this,
 	 * but I'm already using way to many device nodes to claim another one
 	 * for "raw controller".
 	 */
-	if (!hba[ctlr]->drv[dsk].nr_blks) {
+	if (!drv->nr_blks) {
 		if (!capable(CAP_SYS_RAWIO))
 			return -ENXIO;
-		/* Huh??? */
-		if (capable(CAP_SYS_ADMIN) && minor(inode->i_rdev) != 0)
+		if (!capable(CAP_SYS_ADMIN) && drv != host->drv)
 			return -ENXIO;
 	}
-	hba[ctlr]->usage_count++;
+	host->usage_count++;
 	return 0;
 }
 
@@ -733,8 +740,8 @@
  */
 static int ida_release(struct inode *inode, struct file *filep)
 {
-	int ctlr = major(inode->i_rdev) - COMPAQ_SMART2_MAJOR;
-	hba[ctlr]->usage_count--;
+	ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
+	host->usage_count--;
 	return 0;
 }
 
@@ -1015,8 +1022,8 @@
  */
 static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
 {
-	int ctlr = major(inode->i_rdev) - COMPAQ_SMART2_MAJOR;
-	int dsk  = minor(inode->i_rdev) >> NWD_SHIFT;
+	drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
+	ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
 	int error;
 	int diskinfo[4];
 	struct hd_geometry *geo = (struct hd_geometry *)arg;
@@ -1025,14 +1032,14 @@
 
 	switch(cmd) {
 	case HDIO_GETGEO:
-		if (hba[ctlr]->drv[dsk].cylinders) {
-			diskinfo[0] = hba[ctlr]->drv[dsk].heads;
-			diskinfo[1] = hba[ctlr]->drv[dsk].sectors;
-			diskinfo[2] = hba[ctlr]->drv[dsk].cylinders;
+		if (drv->cylinders) {
+			diskinfo[0] = drv->heads;
+			diskinfo[1] = drv->sectors;
+			diskinfo[2] = drv->cylinders;
 		} else {
 			diskinfo[0] = 0xff;
 			diskinfo[1] = 0x3f;
-			diskinfo[2] = hba[ctlr]->drv[dsk].nr_blks / (0xff*0x3f);
+			diskinfo[2] = drv->nr_blks / (0xff*0x3f);
 		}
 		put_user(diskinfo[0], &geo->heads);
 		put_user(diskinfo[1], &geo->sectors);
@@ -1040,23 +1047,24 @@
 		put_user(get_start_sect(inode->i_bdev), &geo->start);
 		return 0;
 	case IDAGETDRVINFO:
-		if (copy_to_user(&io->c.drv, &hba[ctlr]->drv[dsk],
-				 sizeof(drv_info_t)))
+		if (copy_to_user(&io->c.drv, drv, sizeof(drv_info_t)))
 			return -EFAULT;
 		return 0;
 	case IDAPASSTHRU:
 		if (!capable(CAP_SYS_RAWIO)) return -EPERM;
 		if (copy_from_user(&my_io, io, sizeof(my_io)))
 			return -EFAULT;
-		error = ida_ctlr_ioctl(ctlr, dsk, &my_io);
+		error = ida_ctlr_ioctl(host, drv - host->drv, &my_io);
 		if (error) return error;
 		return copy_to_user(io, &my_io, sizeof(my_io)) ? -EFAULT : 0;
 	case IDAGETCTLRSIG:
 		if (!arg) return -EINVAL;
-		put_user(hba[ctlr]->ctlr_sig, (int*)arg);
+		put_user(host->ctlr_sig, (int*)arg);
 		return 0;
 	case IDAREVALIDATEVOLS:
-		return revalidate_allvol(inode->i_rdev);
+		if (minor(inode->i_rdev) != 0)
+			return -ENXIO;
+		return revalidate_allvol(host);
 	case IDADRIVERVERSION:
 		if (!arg) return -EINVAL;
 		put_user(DRIVER_VERSION, (unsigned long*)arg);
@@ -1067,9 +1075,9 @@
 		ida_pci_info_struct pciinfo;
 
 		if (!arg) return -EINVAL;
-		pciinfo.bus = hba[ctlr]->pci_dev->bus->number;
-		pciinfo.dev_fn = hba[ctlr]->pci_dev->devfn;
-		pciinfo.board_id = hba[ctlr]->board_id;
+		pciinfo.bus = host->pci_dev->bus->number;
+		pciinfo.dev_fn = host->pci_dev->devfn;
+		pciinfo.board_id = host->board_id;
 		if(copy_to_user((void *) arg, &pciinfo,  
 			sizeof( ida_pci_info_struct)))
 				return -EFAULT;
@@ -1091,9 +1099,9 @@
  * any serious sanity checking on the arguments.  Doing an IDA_WRITE_MEDIA and
  * putting a 64M buffer in the sglist is probably a *bad* idea.
  */
-static int ida_ctlr_ioctl(int ctlr, int dsk, ida_ioctl_t *io)
+static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io)
 {
-	ctlr_info_t *h = hba[ctlr];
+	int ctlr = h->ctlr;
 	cmdlist_t *c;
 	void *p = NULL;
 	unsigned long flags;
@@ -1387,59 +1395,57 @@
  * particualar logical volume (instead of all of them on a particular
  * controller).
  */
-static int revalidate_allvol(kdev_t dev)
+static int revalidate_allvol(ctlr_info_t *host)
 {
-	int ctlr, i;
+	int ctlr = host->ctlr;
+	int i;
 	unsigned long flags;
 
-	if (minor(dev) != 0)
-		return -ENXIO;
-
-	ctlr = major(dev) - COMPAQ_SMART2_MAJOR;
-
 	spin_lock_irqsave(IDA_LOCK(ctlr), flags);
-	if (hba[ctlr]->usage_count > 1) {
+	if (host->usage_count > 1) {
 		spin_unlock_irqrestore(IDA_LOCK(ctlr), flags);
 		printk(KERN_WARNING "cpqarray: Device busy for volume"
-			" revalidation (usage=%d)\n", hba[ctlr]->usage_count);
+			" revalidation (usage=%d)\n", host->usage_count);
 		return -EBUSY;
 	}
-	hba[ctlr]->usage_count++;
+	host->usage_count++;
 	spin_unlock_irqrestore(IDA_LOCK(ctlr), flags);
 
 	/*
 	 * Set the partition and block size structures for all volumes
 	 * on this controller to zero.  We will reread all of this data
 	 */
-	for (i = 0; i < NWD; i++) {
+	set_capacity(ida_gendisk[ctlr][0], 0);
+	for (i = 1; i < NWD; i++) {
 		struct gendisk *disk = ida_gendisk[ctlr][i];
 		if (disk->flags & GENHD_FL_UP)
 			del_gendisk(disk);
 	}
-	memset(hba[ctlr]->drv,            0, sizeof(drv_info_t)*NWD);
+	memset(host->drv, 0, sizeof(drv_info_t)*NWD);
 
 	/*
 	 * Tell the array controller not to give us any interrupts while
 	 * we check the new geometry.  Then turn interrupts back on when
 	 * we're done.
 	 */
-	hba[ctlr]->access.set_intr_mask(hba[ctlr], 0);
+	host->access.set_intr_mask(host, 0);
 	getgeometry(ctlr);
-	hba[ctlr]->access.set_intr_mask(hba[ctlr], FIFO_NOT_EMPTY);
+	host->access.set_intr_mask(host, FIFO_NOT_EMPTY);
 
 	for(i=0; i<NWD; i++) {
 		struct gendisk *disk = ida_gendisk[ctlr][i];
-		drv_info_t *drv = &hba[ctlr]->drv[i];
-		if (!drv->nr_blks)
+		drv_info_t *drv = &host->drv[i];
+		if (i && !drv->nr_blks)
 			continue;
-		hba[ctlr]->queue.hardsect_size = drv->blk_size;
+		host->queue.hardsect_size = drv->blk_size;
 		set_capacity(disk, drv->nr_blks);
-		disk->queue = &hba[ctlr]->queue;
+		disk->queue = &host->queue;
 		disk->private_data = drv;
-		add_disk(disk);
+		if (i)
+			add_disk(disk);
 	}
 
-	hba[ctlr]->usage_count--;
+	host->usage_count--;
 	return 0;
 }
 
diff -urN linux-2.5.69-bk18/drivers/block/floppy.c linux-2.5.69-bk19/drivers/block/floppy.c
--- linux-2.5.69-bk18/drivers/block/floppy.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/drivers/block/floppy.c	2003-05-26 04:41:41.000000000 -0700
@@ -4212,7 +4212,7 @@
 	},
 };
 
-static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
+static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 {
 	int drive = (*part&3) | ((*part&0x80) >> 5);
 	if (drive >= N_DRIVE ||
diff -urN linux-2.5.69-bk18/drivers/block/floppy98.c linux-2.5.69-bk19/drivers/block/floppy98.c
--- linux-2.5.69-bk18/drivers/block/floppy98.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk19/drivers/block/floppy98.c	2003-05-26 04:41:41.000000000 -0700
@@ -4246,7 +4246,7 @@
 	},
 };
 
-static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
+static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 {
 	int drive = (*part&3) | ((*part&0x80) >> 5);
 	if (drive >= N_DRIVE ||
diff -urN linux-2.5.69-bk18/drivers/block/genhd.c linux-2.5.69-bk19/drivers/block/genhd.c
--- linux-2.5.69-bk18/drivers/block/genhd.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/drivers/block/genhd.c	2003-05-26 04:41:41.000000000 -0700
@@ -13,13 +13,14 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/kmod.h>
+#include <linux/kobj_map.h>
 
 #define MAX_PROBE_HASH 255	/* random */
 
 static struct subsystem block_subsys;
 
 /*
- * Can be merged with blk_probe or deleted altogether. Later.
+ * Can be deleted altogether. Later.
  *
  * Modified under both block_subsys.rwsem and major_names_lock.
  */
@@ -31,27 +32,12 @@
 
 static spinlock_t major_names_lock = SPIN_LOCK_UNLOCKED;
 
-static struct blk_probe {
-	struct blk_probe *next;
-	dev_t dev;
-	unsigned long range;
-	struct module *owner;
-	struct gendisk *(*get)(dev_t dev, int *part, void *data);
-	int (*lock)(dev_t, void *);
-	void *data;
-} *probes[MAX_PROBE_HASH];
-
 /* index in the above - for now: assume no multimajor ranges */
 static inline int major_to_index(int major)
 {
 	return major % MAX_PROBE_HASH;
 }
 
-static inline int dev_to_index(dev_t dev)
-{
-	return major_to_index(MAJOR(dev));
-}
-
 /* get block device names in somewhat random order */
 int get_blkdev_list(char *p)
 {
@@ -156,59 +142,32 @@
 	return ret;
 }
 
+static struct kobj_map *bdev_map;
+
 /*
  * Register device numbers dev..(dev+range-1)
  * range must be nonzero
  * The hash chain is sorted on range, so that subranges can override.
  */
 void blk_register_region(dev_t dev, unsigned long range, struct module *module,
-			 struct gendisk *(*probe)(dev_t, int *, void *),
+			 struct kobject *(*probe)(dev_t, int *, void *),
 			 int (*lock)(dev_t, void *), void *data)
 {
-	int index = dev_to_index(dev);
-	struct blk_probe *p = kmalloc(sizeof(struct blk_probe), GFP_KERNEL);
-	struct blk_probe **s;
-
-	if (p == NULL)
-		return;
-
-	p->owner = module;
-	p->get = probe;
-	p->lock = lock;
-	p->dev = dev;
-	p->range = range;
-	p->data = data;
-	down_write(&block_subsys.rwsem);
-	for (s = &probes[index]; *s && (*s)->range < range; s = &(*s)->next)
-		;
-	p->next = *s;
-	*s = p;
-	up_write(&block_subsys.rwsem);
+	kobj_map(bdev_map, dev, range, module, probe, lock, data);
 }
 
 void blk_unregister_region(dev_t dev, unsigned long range)
 {
-	int index = dev_to_index(dev);
-	struct blk_probe **s;
-
-	down_write(&block_subsys.rwsem);
-	for (s = &probes[index]; *s; s = &(*s)->next) {
-		struct blk_probe *p = *s;
-		if (p->dev == dev && p->range == range) {
-			*s = p->next;
-			kfree(p);
-			break;
-		}
-	}
-	up_write(&block_subsys.rwsem);
+	kobj_unmap(bdev_map, dev, range);
 }
 
 EXPORT_SYMBOL(blk_register_region);
 EXPORT_SYMBOL(blk_unregister_region);
 
-static struct gendisk *exact_match(dev_t dev, int *part, void *data)
+static struct kobject *exact_match(dev_t dev, int *part, void *data)
 {
-	return data;
+	struct gendisk *p = data;
+	return &p->kobj;
 }
 
 static int exact_lock(dev_t dev, void *data)
@@ -246,6 +205,8 @@
 			      disk->minors);
 }
 
+#define to_disk(obj) container_of(obj,struct gendisk,kobj)
+
 /**
  * get_gendisk - get partitioning information for a given device
  * @dev: device to get partitioning information for
@@ -253,46 +214,10 @@
  * This function gets the structure containing partitioning
  * information for the given device @dev.
  */
-struct gendisk *
-get_gendisk(dev_t dev, int *part)
+struct gendisk *get_gendisk(dev_t dev, int *part)
 {
-	int index = dev_to_index(dev);
-	struct gendisk *disk;
-	struct blk_probe *p;
-	unsigned best = ~0U;
-
-retry:
-	down_read(&block_subsys.rwsem);
-	for (p = probes[index]; p; p = p->next) {
-		struct gendisk *(*probe)(dev_t, int *, void *);
-		struct module *owner;
-		void *data;
-
-		if (p->dev > dev || p->dev + p->range - 1 < dev)
-			continue;
-		if (p->range - 1 >= best)
-			break;
-		if (!try_module_get(p->owner))
-			continue;
-		owner = p->owner;
-		data = p->data;
-		probe = p->get;
-		best = p->range - 1;
-		*part = dev - p->dev;
-		if (p->lock && p->lock(dev, data) < 0) {
-			module_put(owner);
-			continue;
-		}
-		up_read(&block_subsys.rwsem);
-		disk = probe(dev, part, data);
-		/* Currently ->owner protects _only_ ->probe() itself. */
-		module_put(owner);
-		if (disk)
-			return disk;
-		goto retry;		/* this terminates: best decreases */
-	}
-	up_read(&block_subsys.rwsem);
-	return NULL;
+	struct kobject *kobj = kobj_lookup(bdev_map, dev, part);
+	return  kobj ? to_disk(kobj) : NULL;
 }
 
 #ifdef CONFIG_PROC_FS
@@ -365,7 +290,7 @@
 
 extern int blk_dev_init(void);
 
-static struct gendisk *base_probe(dev_t dev, int *part, void *data)
+static struct kobject *base_probe(dev_t dev, int *part, void *data)
 {
 	request_module("block-major-%d", MAJOR(dev));
 	return NULL;
@@ -373,14 +298,7 @@
 
 int __init device_init(void)
 {
-	struct blk_probe *base = kmalloc(sizeof(struct blk_probe), GFP_KERNEL);
-	int i;
-	memset(base, 0, sizeof(struct blk_probe));
-	base->dev = 1;
-	base->range = ~0;		/* range 1 .. ~0 */
-	base->get = base_probe;
-	for (i = 0; i < MAX_PROBE_HASH; i++)
-		probes[i] = base;	/* must remain last in chain */
+	bdev_map = kobj_map_init(base_probe, &block_subsys);
 	blk_dev_init();
 	subsystem_register(&block_subsys);
 	return 0;
@@ -394,8 +312,6 @@
  * kobject & sysfs bindings for block devices
  */
 
-#define to_disk(obj) container_of(obj,struct gendisk,kobj)
-
 struct disk_attribute {
 	struct attribute attr;
 	ssize_t (*show)(struct gendisk *, char *);
@@ -632,7 +548,7 @@
 	return disk;
 }
 
-struct gendisk *get_disk(struct gendisk *disk)
+struct kobject *get_disk(struct gendisk *disk)
 {
 	struct module *owner;
 	struct kobject *kobj;
@@ -647,7 +563,7 @@
 		module_put(owner);
 		return NULL;
 	}
-	return to_disk(kobj);
+	return kobj;
 
 }
 
diff -urN linux-2.5.69-bk18/drivers/block/paride/pg.c linux-2.5.69-bk19/drivers/block/paride/pg.c
--- linux-2.5.69-bk18/drivers/block/paride/pg.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/drivers/block/paride/pg.c	2003-05-26 04:41:41.000000000 -0700
@@ -136,31 +136,23 @@
 
 */
 
-static int	verbose = 0;
-static int	major = PG_MAJOR;
-static char	*name = PG_NAME;
-static int      disable = 0;
-
-static int drive0[6] = {0,0,0,-1,-1,-1};
-static int drive1[6] = {0,0,0,-1,-1,-1};
-static int drive2[6] = {0,0,0,-1,-1,-1};
-static int drive3[6] = {0,0,0,-1,-1,-1};
+static int verbose = 0;
+static int major = PG_MAJOR;
+static char *name = PG_NAME;
+static int disable = 0;
+
+static int drive0[6] = { 0, 0, 0, -1, -1, -1 };
+static int drive1[6] = { 0, 0, 0, -1, -1, -1 };
+static int drive2[6] = { 0, 0, 0, -1, -1, -1 };
+static int drive3[6] = { 0, 0, 0, -1, -1, -1 };
 
-static int (*drives[4])[6] = {&drive0,&drive1,&drive2,&drive3};
+static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
 static int pg_drive_count;
 
-#define D_PRT   0
-#define D_PRO   1
-#define D_UNI   2
-#define D_MOD   3
-#define D_SLV   4
-#define D_DLY   5
-
-#define DU              (*drives[unit])
+enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY};
 
 /* end of parameters */
 
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/fs.h>
@@ -176,30 +168,32 @@
 
 #include "setup.h"
 
-static STT pg_stt[5] = {{"drive0",6,drive0},
-			{"drive1",6,drive1},
-			{"drive2",6,drive2},
-			{"drive3",6,drive3},
-			{"disable",1,&disable}};
-
-void pg_setup( char *str, int *ints)
+static STT pg_stt[5] = {
+	{"drive0", 6, drive0},
+	{"drive1", 6, drive1},
+	{"drive2", 6, drive2},
+	{"drive3", 6, drive3},
+	{"disable", 1, &disable}
+};
 
-{       generic_setup(pg_stt,5,str);
+void pg_setup(char *str, int *ints)
+{
+	generic_setup(pg_stt, 5, str);
 }
 
 #endif
 
-MODULE_PARM(verbose,"i");
-MODULE_PARM(major,"i");
-MODULE_PARM(name,"s");
-MODULE_PARM(drive0,"1-6i");
-MODULE_PARM(drive1,"1-6i");
-MODULE_PARM(drive2,"1-6i");
-MODULE_PARM(drive3,"1-6i");
+MODULE_PARM(verbose, "i");
+MODULE_PARM(major, "i");
+MODULE_PARM(name, "s");
+MODULE_PARM(drive0, "1-6i");
+MODULE_PARM(drive1, "1-6i");
+MODULE_PARM(drive2, "1-6i");
+MODULE_PARM(drive3, "1-6i");
 
 #include "paride.h"
 
-#define PG_SPIN_DEL     50              /* spin delay in micro-seconds  */
+#define PG_SPIN_DEL     50	/* spin delay in micro-seconds  */
 #define PG_SPIN         200
 #define PG_TMO		HZ
 #define PG_RESET_TMO	10*HZ
@@ -216,91 +210,101 @@
 #define ATAPI_IDENTIFY		0x12
 
 static int pg_open(struct inode *inode, struct file *file);
-static int pg_release (struct inode *inode, struct file *file);
-static ssize_t pg_read(struct file * filp, char * buf, 
-		       size_t count, loff_t *ppos);
-static ssize_t pg_write(struct file * filp, const char * buf, 
-			size_t count, loff_t *ppos);
+static int pg_release(struct inode *inode, struct file *file);
+static ssize_t pg_read(struct file *filp, char *buf,
+		       size_t count, loff_t * ppos);
+static ssize_t pg_write(struct file *filp, const char *buf,
+			size_t count, loff_t * ppos);
 static int pg_detect(void);
 
-static int pg_identify (int unit, int log);
-
 #define PG_NAMELEN      8
 
-struct pg_unit {
-	struct pi_adapter pia;    /* interface to paride layer */
+struct pg {
+	struct pi_adapter pia;	/* interface to paride layer */
 	struct pi_adapter *pi;
-	int busy;        	  /* write done, read expected */
-	int start;		  /* jiffies at command start */
-	int dlen;		  /* transfer size requested */
-	unsigned long timeout;	  /* timeout requested */
-	int status;		  /* last sense key */
-	int drive;		  /* drive */
-	unsigned long access;     /* count of active opens ... */
-	int present;		  /* device present ? */
+	int busy;		/* write done, read expected */
+	int start;		/* jiffies at command start */
+	int dlen;		/* transfer size requested */
+	unsigned long timeout;	/* timeout requested */
+	int status;		/* last sense key */
+	int drive;		/* drive */
+	unsigned long access;	/* count of active opens ... */
+	int present;		/* device present ? */
 	char *bufptr;
-	char name[PG_NAMELEN];	  /* pg0, pg1, ... */
+	char name[PG_NAMELEN];	/* pg0, pg1, ... */
 };
 
-struct pg_unit pg[PG_UNITS];
-
-/*  'unit' must be defined in all functions - either as a local or a param */
+struct pg devices[PG_UNITS];
 
-#define PG pg[unit]
-#define PI PG.pi
+static int pg_identify(struct pg *dev, int log);
 
-static char pg_scratch[512];            /* scratch block buffer */
+static char pg_scratch[512];	/* scratch block buffer */
 
 /* kernel glue structures */
 
 static struct file_operations pg_fops = {
-	.owner =	THIS_MODULE,
-	.read =		pg_read,
-	.write =	pg_write,
-	.open =		pg_open,
-	.release =	pg_release,
+	.owner = THIS_MODULE,
+	.read = pg_read,
+	.write = pg_write,
+	.open = pg_open,
+	.release = pg_release,
 };
 
-void pg_init_units( void )
-
-{       int     unit, j;
+static void pg_init_units(void)
+{
+	int unit;
 
 	pg_drive_count = 0;
-	for (unit=0;unit<PG_UNITS;unit++) {
-		PG.pi = & PG.pia;
-		set_bit( 0, &PG.access );
-		PG.busy = 0;
-		PG.present = 0;
-		PG.bufptr = NULL;
-		PG.drive = DU[D_SLV];
-		j = 0;
-		while ((j < PG_NAMELEN-2) && (PG.name[j]=name[j])) j++;
-		PG.name[j++] = '0' + unit;
-		PG.name[j] = 0;
-		if (DU[D_PRT]) pg_drive_count++;
-	}
-} 
+	for (unit = 0; unit < PG_UNITS; unit++) {
+		int *parm = *drives[unit];
+		struct pg *dev = &devices[unit];
+		dev->pi = &dev->pia;
+		set_bit(0, &dev->access);
+		dev->busy = 0;
+		dev->present = 0;
+		dev->bufptr = NULL;
+		dev->drive = parm[D_SLV];
+		snprintf(dev->name, PG_NAMELEN, "%s%c", name, 'a'+unit);
+		if (parm[D_PRT])
+			pg_drive_count++;
+	}
+}
 
-#define	WR(c,r,v)	pi_write_regr(PI,c,r,v)
-#define	RR(c,r)		(pi_read_regr(PI,c,r))
+static inline int status_reg(struct pg *dev)
+{
+	return pi_read_regr(dev->pi, 1, 6);
+}
 
-#define DRIVE           (0xa0+0x10*PG.drive)
+static inline int read_reg(struct pg *dev, int reg)
+{
+	return pi_read_regr(dev->pi, 0, reg);
+}
+
+static inline void write_reg(struct pg *dev, int reg, int val)
+{
+	pi_write_regr(dev->pi, 0, reg, val);
+}
 
-static void pg_sleep( int cs )
+static inline u8 DRIVE(struct pg *dev)
+{
+	return 0xa0+0x10*dev->drive;
+}
 
-{       current->state = TASK_INTERRUPTIBLE;
+static void pg_sleep(int cs)
+{
+	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(cs);
 }
 
-static int pg_wait(int unit, int go, int stop, unsigned long tmo, char *msg)
+static int pg_wait(struct pg *dev, int go, int stop, unsigned long tmo, char *msg)
 {
 	int j, r, e, s, p, to;
 
-	PG.status = 0;
+	dev->status = 0;
 
 	j = 0;
-	while ((((r=RR(1,6))&go) || (stop&&(!(r&stop))))
-	       && time_before(jiffies,tmo)) {
+	while ((((r = status_reg(dev)) & go) || (stop && (!(r & stop))))
+	       && time_before(jiffies, tmo)) {
 		if (j++ < PG_SPIN)
 			udelay(PG_SPIN_DEL);
 		else
@@ -309,325 +313,349 @@
 
 	to = time_after_eq(jiffies, tmo);
 
-	if ((r&(STAT_ERR&stop)) || to) {
-		s = RR(0,7);
-		e = RR(0,1);
-		p = RR(0,2);
+	if ((r & (STAT_ERR & stop)) || to) {
+		s = read_reg(dev, 7);
+		e = read_reg(dev, 1);
+		p = read_reg(dev, 2);
 		if (verbose > 1)
 			printk("%s: %s: stat=0x%x err=0x%x phase=%d%s\n",
-			       PG.name, msg, s, e, p, to ? " timeout" : "");
+			       dev->name, msg, s, e, p, to ? " timeout" : "");
 		if (to)
 			e |= 0x100;
-		PG.status = (e >> 4) & 0xff;
+		dev->status = (e >> 4) & 0xff;
 		return -1;
 	}
 	return 0;
 }
 
-static int pg_command(int unit, char *cmd, int dlen, unsigned long tmo)
+static int pg_command(struct pg *dev, char *cmd, int dlen, unsigned long tmo)
 {
 	int k;
 
-	pi_connect(PI);
+	pi_connect(dev->pi);
 
-	WR(0,6,DRIVE);
+	write_reg(dev, 6, DRIVE(dev));
 
-	if (pg_wait(unit, STAT_BUSY|STAT_DRQ, 0, tmo, "before command")) {
-		pi_disconnect(PI);
-		return -1;
-	}
+	if (pg_wait(dev, STAT_BUSY | STAT_DRQ, 0, tmo, "before command"))
+		goto fail;
 
-	WR(0,4,dlen % 256);
-	WR(0,5,dlen / 256);
-	WR(0,7,0xa0);          /* ATAPI packet command */
+	write_reg(dev, 4, dlen % 256);
+	write_reg(dev, 5, dlen / 256);
+	write_reg(dev, 7, 0xa0);	/* ATAPI packet command */
 
-	if (pg_wait(unit, STAT_BUSY, STAT_DRQ, tmo, "command DRQ")) {
-		pi_disconnect(PI);
-		return -1;
-	}
+	if (pg_wait(dev, STAT_BUSY, STAT_DRQ, tmo, "command DRQ"))
+		goto fail;
 
-	if (RR(0,2) != 1) {
-		printk("%s: command phase error\n",PG.name);
-		pi_disconnect(PI);
-		return -1;
+	if (read_reg(dev, 2) != 1) {
+		printk("%s: command phase error\n", dev->name);
+		goto fail;
 	}
 
-	pi_write_block(PI,cmd,12);
+	pi_write_block(dev->pi, cmd, 12);
 
 	if (verbose > 1) {
-		printk("%s: Command sent, dlen=%d packet= ", PG.name,dlen);
-		for (k=0;k<12;k++) printk("%02x ",cmd[k]&0xff);
+		printk("%s: Command sent, dlen=%d packet= ", dev->name, dlen);
+		for (k = 0; k < 12; k++)
+			printk("%02x ", cmd[k] & 0xff);
 		printk("\n");
 	}
 	return 0;
+fail:
+	pi_disconnect(dev->pi);
+	return -1;
 }
 
-static int pg_completion(int unit, char *buf, unsigned long tmo)
+static int pg_completion(struct pg *dev, char *buf, unsigned long tmo)
 {
 	int r, d, n, p;
 
-	r = pg_wait(unit, STAT_BUSY, STAT_DRQ|STAT_READY|STAT_ERR,
+	r = pg_wait(dev, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR,
 		    tmo, "completion");
 
-	PG.dlen = 0;
+	dev->dlen = 0;
 
-	while (RR(0,7)&STAT_DRQ) {
-		d = (RR(0,4)+256*RR(0,5));
-		n = ((d+3)&0xfffc);
-		p = RR(0,2)&3;
+	while (read_reg(dev, 7) & STAT_DRQ) {
+		d = (read_reg(dev, 4) + 256 * read_reg(dev, 5));
+		n = ((d + 3) & 0xfffc);
+		p = read_reg(dev, 2) & 3;
 		if (p == 0)
-			pi_write_block(PI,buf,n);
+			pi_write_block(dev->pi, buf, n);
 		if (p == 2)
-			pi_read_block(PI,buf,n);
+			pi_read_block(dev->pi, buf, n);
 		if (verbose > 1)
-			printk("%s: %s %d bytes\n", PG.name,
-			       p?"Read":"Write", n);
-		PG.dlen += (1-p)*d;
+			printk("%s: %s %d bytes\n", dev->name,
+			       p ? "Read" : "Write", n);
+		dev->dlen += (1 - p) * d;
 		buf += d;
-		r = pg_wait(unit, STAT_BUSY, STAT_DRQ|STAT_READY|STAT_ERR,
+		r = pg_wait(dev, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR,
 			    tmo, "completion");
 	}
 
-	pi_disconnect(PI); 
+	pi_disconnect(dev->pi);
 
 	return r;
 }
 
-static int pg_reset( int unit )
-
-{	int	i, k, flg;
-	int	expect[5] = {1,1,1,0x14,0xeb};
-
-	pi_connect(PI);
-	WR(0,6,DRIVE);
-	WR(0,7,8);
+static int pg_reset(struct pg *dev)
+{
+	int i, k, err;
+	int expect[5] = { 1, 1, 1, 0x14, 0xeb };
+	int got[5];
+
+	pi_connect(dev->pi);
+	write_reg(dev, 6, DRIVE(dev));
+	write_reg(dev, 7, 8);
 
-	pg_sleep(20*HZ/1000);
+	pg_sleep(20 * HZ / 1000);
 
 	k = 0;
-	while ((k++ < PG_RESET_TMO) && (RR(1,6)&STAT_BUSY))
+	while ((k++ < PG_RESET_TMO) && (status_reg(dev) & STAT_BUSY))
 		pg_sleep(1);
 
-	flg = 1;
-	for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
+	for (i = 0; i < 5; i++)
+		got[i] = read_reg(dev, i + 1);
+
+	err = memcmp(expect, got, sizeof(got)) ? -1 : 0;
 
 	if (verbose) {
-		printk("%s: Reset (%d) signature = ",PG.name,k);
-		for (i=0;i<5;i++) printk("%3x",RR(0,i+1));
-		if (!flg) printk(" (incorrect)");
+		printk("%s: Reset (%d) signature = ", dev->name, k);
+		for (i = 0; i < 5; i++)
+			printk("%3x", got[i]);
+		if (err)
+			printk(" (incorrect)");
 		printk("\n");
 	}
-	
-	pi_disconnect(PI);
-	return flg-1;	
-}
 
-static void xs( char *buf, char *targ, int offs, int len )
+	pi_disconnect(dev->pi);
+	return err;
+}
 
-{	int	j,k,l;
+static void xs(char *buf, char *targ, int len)
+{
+	char l = '\0';
+	int k;
 
-	j=0; l=0;
-	for (k=0;k<len;k++) 
-	   if((buf[k+offs]!=0x20)||(buf[k+offs]!=l))
-		l=targ[j++]=buf[k+offs];
-	if (l==0x20) j--;
-	targ[j]=0;
+	for (k = 0; k < len; k++) {
+		char c = *buf++;
+		if (c != ' ' || c != l)
+			l = *targ++ = c;
+	}
+	if (l == ' ')
+		targ--;
+	*targ = '\0';
 }
 
-static int pg_identify( int unit, int log )
-
-{	int 	s;
-	char	*ms[2] = {"master","slave"};
-	char	mf[10], id[18];
-	char    id_cmd[12] = { ATAPI_IDENTIFY,0,0,0,36,0,0,0,0,0,0,0};
-	char	buf[36];
+static int pg_identify(struct pg *dev, int log)
+{
+	int s;
+	char *ms[2] = { "master", "slave" };
+	char mf[10], id[18];
+	char id_cmd[12] = { ATAPI_IDENTIFY, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
+	char buf[36];
 
-	s = pg_command(unit,id_cmd,36,jiffies+PG_TMO);
-	if (s) return -1;
-	s = pg_completion(unit,buf,jiffies+PG_TMO);
-	if (s) return -1;
+	s = pg_command(dev, id_cmd, 36, jiffies + PG_TMO);
+	if (s)
+		return -1;
+	s = pg_completion(dev, buf, jiffies + PG_TMO);
+	if (s)
+		return -1;
 
 	if (log) {
-		xs(buf,mf,8,8);
-		xs(buf,id,16,16);
-		printk("%s: %s %s, %s\n",PG.name,mf,id,ms[PG.drive]);
+		xs(buf + 8, mf, 8);
+		xs(buf + 16, id, 16);
+		printk("%s: %s %s, %s\n", dev->name, mf, id, ms[dev->drive]);
 	}
 
 	return 0;
 }
 
-static int pg_probe( int unit )
-
-/*	returns  0, with id set if drive is detected
-		-1, if drive detection failed
-*/
-
-{	if (PG.drive == -1) {
-	   for (PG.drive=0;PG.drive<=1;PG.drive++)
-		if (!pg_reset(unit)) return pg_identify(unit,1);
+/*
+ * returns  0, with id set if drive is detected
+ *	   -1, if drive detection failed
+ */
+static int pg_probe(struct pg *dev)
+{
+	if (dev->drive == -1) {
+		for (dev->drive = 0; dev->drive <= 1; dev->drive++)
+			if (!pg_reset(dev))
+				return pg_identify(dev, 1);
 	} else {
-	   if (!pg_reset(unit)) return pg_identify(unit,1);
+		if (!pg_reset(dev))
+			return pg_identify(dev, 1);
 	}
-	return -1; 
+	return -1;
 }
 
-static int pg_detect( void )
-
-{	int	k, unit;
+static int pg_detect(void)
+{
+	struct pg *dev = &devices[0];
+	int k, unit;
 
-	printk("%s: %s version %s, major %d\n",
-		name,name,PG_VERSION,major);
+	printk("%s: %s version %s, major %d\n", name, name, PG_VERSION, major);
 
 	k = 0;
 	if (pg_drive_count == 0) {
-	    unit = 0;
-	    if (pi_init(PI,1,-1,-1,-1,-1,-1,pg_scratch,
-			PI_PG,verbose,PG.name)) {
-		if (!pg_probe(unit)) {
-			PG.present = 1;
-			k++;
-		} else pi_release(PI);
-	    }
-
-	} else for (unit=0;unit<PG_UNITS;unit++) if (DU[D_PRT])
-	    if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
-			DU[D_PRO],DU[D_DLY],pg_scratch,PI_PG,verbose,
-			PG.name)) { 
-		if (!pg_probe(unit)) {
-			PG.present = 1;
-			k++;
-		} else pi_release(PI);
-	    }
+		if (pi_init(dev->pi, 1, -1, -1, -1, -1, -1, pg_scratch,
+			    PI_PG, verbose, dev->name)) {
+			if (!pg_probe(dev)) {
+				dev->present = 1;
+				k++;
+			} else
+				pi_release(dev->pi);
+		}
+
+	} else
+		for (unit = 0; unit < PG_UNITS; unit++, dev++) {
+			int *parm = *drives[unit];
+			if (!parm[D_PRT])
+				continue;
+			if (pi_init(dev->pi, 0, parm[D_PRT], parm[D_MOD],
+				    parm[D_UNI], parm[D_PRO], parm[D_DLY],
+				    pg_scratch, PI_PG, verbose, dev->name)) {
+				if (!pg_probe(dev)) {
+					dev->present = 1;
+					k++;
+				} else
+					pi_release(dev->pi);
+			}
+		}
 
-	if (k) return 0;
+	if (k)
+		return 0;
 
-	printk("%s: No ATAPI device detected\n",name);
+	printk("%s: No ATAPI device detected\n", name);
 	return -1;
 }
 
 #define DEVICE_NR(dev)	(minor(dev) & 0x7F)
 
-static int pg_open (struct inode *inode, struct file *file)
-
-{       int	unit = DEVICE_NR(inode->i_rdev);
+static int pg_open(struct inode *inode, struct file *file)
+{
+	int unit = DEVICE_NR(inode->i_rdev);
+	struct pg *dev = &devices[unit];
 
-	if ((unit >= PG_UNITS) || (!PG.present)) return -ENODEV;
+	if ((unit >= PG_UNITS) || (!dev->present))
+		return -ENODEV;
 
-	if ( test_and_set_bit(0, &PG.access) ) {
+	if (test_and_set_bit(0, &dev->access))
 		return -EBUSY;
-	}
 
-	if (PG.busy) {
-		pg_reset(unit);
-		PG.busy = 0;
+	if (dev->busy) {
+		pg_reset(dev);
+		dev->busy = 0;
 	}
 
-	pg_identify(unit,(verbose>1));
-
+	pg_identify(dev, (verbose > 1));
 
-	PG.bufptr = kmalloc(PG_MAX_DATA,GFP_KERNEL);
-	if (PG.bufptr == NULL) {
-		clear_bit( 0, &PG.access ) ;
-		printk("%s: buffer allocation failed\n",PG.name);
+	dev->bufptr = kmalloc(PG_MAX_DATA, GFP_KERNEL);
+	if (dev->bufptr == NULL) {
+		clear_bit(0, &dev->access);
+		printk("%s: buffer allocation failed\n", dev->name);
 		return -ENOMEM;
 	}
 
+	file->private_data = dev;
+
 	return 0;
 }
 
-static int pg_release (struct inode *inode, struct file *file)
+static int pg_release(struct inode *inode, struct file *file)
 {
-	int	unit = DEVICE_NR(inode->i_rdev);
-
-	if ( unit >= PG_UNITS || !test_bit(0,&PG.access) )
-		return -EINVAL;
-
-	clear_bit( 0, &PG.access);
+	struct pg *dev = file->private_data;
 
-	kfree(PG.bufptr);
-	PG.bufptr = NULL;
+	kfree(dev->bufptr);
+	dev->bufptr = NULL;
+	clear_bit(0, &dev->access);
 
 	return 0;
-
 }
 
-static ssize_t pg_write(struct file * filp, const char * buf, 
-			size_t count, loff_t *ppos)
+static ssize_t pg_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
+{
+	struct pg *dev = filp->private_data;
+	struct pg_write_hdr hdr;
+	int hs = sizeof (hdr);
+
+	if (dev->busy)
+		return -EBUSY;
+	if (count < hs)
+		return -EINVAL;
 
-{       struct inode            *ino = filp->f_dentry->d_inode;
-	int                     unit = DEVICE_NR(ino->i_rdev);
-	struct pg_write_hdr     hdr;
-	int                     hs = sizeof(hdr);
-
-	if (PG.busy) return -EBUSY;
-	if (count < hs) return -EINVAL;
-	
-	if (copy_from_user((char *)&hdr, buf, hs))
+	if (copy_from_user((char *) &hdr, buf, hs))
 		return -EFAULT;
 
-	if (hdr.magic != PG_MAGIC) return -EINVAL;
-	if (hdr.dlen > PG_MAX_DATA) return -EINVAL;
-	if ((count - hs) > PG_MAX_DATA) return -EINVAL;
+	if (hdr.magic != PG_MAGIC)
+		return -EINVAL;
+	if (hdr.dlen > PG_MAX_DATA)
+		return -EINVAL;
+	if ((count - hs) > PG_MAX_DATA)
+		return -EINVAL;
 
 	if (hdr.func == PG_RESET) {
-		if (count != hs) return -EINVAL;
-		if (pg_reset(unit)) return -EIO;
+		if (count != hs)
+			return -EINVAL;
+		if (pg_reset(dev))
+			return -EIO;
 		return count;
 	}
 
-	if (hdr.func != PG_COMMAND) return -EINVAL;
+	if (hdr.func != PG_COMMAND)
+		return -EINVAL;
 
-	PG.start = jiffies;
-	PG.timeout = hdr.timeout*HZ + HZ/2 + jiffies;
+	dev->start = jiffies;
+	dev->timeout = hdr.timeout * HZ + HZ / 2 + jiffies;
 
-	if (pg_command(unit,hdr.packet,hdr.dlen,jiffies+PG_TMO)) {
-		if (PG.status & 0x10) return -ETIME;
+	if (pg_command(dev, hdr.packet, hdr.dlen, jiffies + PG_TMO)) {
+		if (dev->status & 0x10)
+			return -ETIME;
 		return -EIO;
 	}
 
-	PG.busy = 1;
+	dev->busy = 1;
 
-	if (copy_from_user(PG.bufptr, buf + hs, count - hs))
+	if (copy_from_user(dev->bufptr, buf + hs, count - hs))
 		return -EFAULT;
 	return count;
 }
 
-static ssize_t pg_read(struct file * filp, char * buf, 
-		       size_t count, loff_t *ppos)
-
-{  	struct inode 		*ino = filp->f_dentry->d_inode;
-	int			unit = DEVICE_NR(ino->i_rdev);
-	struct pg_read_hdr 	hdr;
-	int			hs = sizeof(hdr);
-	int			copy;
+static ssize_t pg_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
+{
+	struct pg *dev = filp->private_data;
+	struct pg_read_hdr hdr;
+	int hs = sizeof (hdr);
+	int copy;
 
-	if (!PG.busy) return -EINVAL;
-	if (count < hs) return -EINVAL;
+	if (!dev->busy)
+		return -EINVAL;
+	if (count < hs)
+		return -EINVAL;
 
-	PG.busy = 0;
+	dev->busy = 0;
 
-	if (pg_completion(unit,PG.bufptr,PG.timeout))
-	  if (PG.status & 0x10) return -ETIME;
+	if (pg_completion(dev, dev->bufptr, dev->timeout))
+		if (dev->status & 0x10)
+			return -ETIME;
 
 	hdr.magic = PG_MAGIC;
-	hdr.dlen = PG.dlen;
+	hdr.dlen = dev->dlen;
 	copy = 0;
 
 	if (hdr.dlen < 0) {
 		hdr.dlen = -1 * hdr.dlen;
 		copy = hdr.dlen;
-		if (copy > (count - hs)) copy = count - hs;
+		if (copy > (count - hs))
+			copy = count - hs;
 	}
 
-	hdr.duration = (jiffies - PG.start + HZ/2) / HZ;
-	hdr.scsi = PG.status & 0x0f;
+	hdr.duration = (jiffies - dev->start + HZ / 2) / HZ;
+	hdr.scsi = dev->status & 0x0f;
 
-	if (copy_to_user(buf, (char *)&hdr, hs))
+	if (copy_to_user(buf, (char *) &hdr, hs))
 		return -EFAULT;
 	if (copy > 0)
-		if (copy_to_user(buf+hs,PG.bufptr,copy))
+		if (copy_to_user(buf + hs, dev->bufptr, copy))
 			return -EFAULT;
-	return copy+hs;
+	return copy + hs;
 }
 
 static int __init pg_init(void)
@@ -642,19 +670,24 @@
 	if (pg_detect())
 		return -1;
 
-	if (register_chrdev(major,name,&pg_fops)) {
-		printk("pg_init: unable to get major number %d\n",
-			major);
-		for (unit=0;unit<PG_UNITS;unit++)
-		  if (PG.present) pi_release(PI);
+	if (register_chrdev(major, name, &pg_fops)) {
+		printk("pg_init: unable to get major number %d\n", major);
+		for (unit = 0; unit < PG_UNITS; unit++) {
+			struct pg *dev = &devices[unit];
+			if (dev->present)
+				pi_release(dev->pi);
+		}
 		return -1;
 	}
-	devfs_mk_dir ("pg");
-	for (unit=0; unit<PG_UNITS; unit++)
-		if (PG.present) {
+	devfs_mk_dir("pg");
+	for (unit = 0; unit < PG_UNITS; unit++) {
+		struct pg *dev = &devices[unit];
+		if (dev->present) {
 			devfs_mk_cdev(MKDEV(major, unit),
-				S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u", unit);
+				      S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u",
+				      unit);
 		}
+	}
 	return 0;
 }
 
@@ -662,15 +695,20 @@
 {
 	int unit;
 
-	for (unit=0; unit<PG_UNITS; unit++)
-		if (PG.present)
+	for (unit = 0; unit < PG_UNITS; unit++) {
+		struct pg *dev = &devices[unit];
+		if (dev->present)
 			devfs_remove("pg/%u", unit);
+	}
 
-	devfs_remove ("pg");
-	unregister_chrdev(major,name);
+	devfs_remove("pg");
+	unregister_chrdev(major, name);
 
-	for (unit=0;unit<PG_UNITS;unit++)
-		if (PG.present) pi_release(PI);
+	for (unit = 0; unit < PG_UNITS; unit++) {
+		struct pg *dev = &devices[unit];
+		if (dev->present)
+			pi_release(dev->pi);
+	}
 }
 
 MODULE_LICENSE("GPL");
diff -urN linux-2.5.69-bk18/drivers/block/paride/pt.c linux-2.5.69-bk19/drivers/block/paride/pt.c
--- linux-2.5.69-bk18/drivers/block/paride/pt.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/drivers/block/paride/pt.c	2003-05-26 04:41:41.000000000 -0700
@@ -115,17 +115,17 @@
 
 */
 
-static int	verbose = 0;
-static int	major = PT_MAJOR;
-static char	*name = PT_NAME;
-static int      disable = 0;
-
-static int drive0[6] = {0,0,0,-1,-1,-1};
-static int drive1[6] = {0,0,0,-1,-1,-1};
-static int drive2[6] = {0,0,0,-1,-1,-1};
-static int drive3[6] = {0,0,0,-1,-1,-1};
+static int verbose = 0;
+static int major = PT_MAJOR;
+static char *name = PT_NAME;
+static int disable = 0;
+
+static int drive0[6] = { 0, 0, 0, -1, -1, -1 };
+static int drive1[6] = { 0, 0, 0, -1, -1, -1 };
+static int drive2[6] = { 0, 0, 0, -1, -1, -1 };
+static int drive3[6] = { 0, 0, 0, -1, -1, -1 };
 
-static int (*drives[4])[6] = {&drive0,&drive1,&drive2,&drive3};
+static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
 static int pt_drive_count;
 
 #define D_PRT   0
@@ -139,7 +139,6 @@
 
 /* end of parameters */
 
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/fs.h>
@@ -154,37 +153,40 @@
 
 #include "setup.h"
 
-static STT pt_stt[5] = {{"drive0",6,drive0},
-                        {"drive1",6,drive1},
-                        {"drive2",6,drive2},
-                        {"drive3",6,drive3},
-			{"disable",1,&disable}};
-
-void pt_setup( char *str, int *ints)
+static STT pt_stt[5] = {
+	{"drive0", 6, drive0},
+	{"drive1", 6, drive1},
+	{"drive2", 6, drive2},
+	{"drive3", 6, drive3},
+	{"disable", 1, &disable}
+};
 
-{       generic_setup(pt_stt,5,str);
+void
+pt_setup(char *str, int *ints)
+{
+	generic_setup(pt_stt, 5, str);
 }
 
 #endif
 
-MODULE_PARM(verbose,"i");
-MODULE_PARM(major,"i");
-MODULE_PARM(name,"s");
-MODULE_PARM(drive0,"1-6i");
-MODULE_PARM(drive1,"1-6i");
-MODULE_PARM(drive2,"1-6i");
-MODULE_PARM(drive3,"1-6i");
+MODULE_PARM(verbose, "i");
+MODULE_PARM(major, "i");
+MODULE_PARM(name, "s");
+MODULE_PARM(drive0, "1-6i");
+MODULE_PARM(drive1, "1-6i");
+MODULE_PARM(drive2, "1-6i");
+MODULE_PARM(drive3, "1-6i");
 
 #include "paride.h"
 
 #define PT_MAX_RETRIES  5
-#define PT_TMO          3000            /* interrupt timeout in jiffies */
-#define PT_SPIN_DEL     50              /* spin delay in micro-seconds  */
-#define PT_RESET_TMO    30		/* 30 seconds */
-#define PT_READY_TMO	60		/* 60 seconds */
-#define PT_REWIND_TMO	1200		/* 20 minutes */
+#define PT_TMO          3000	/* interrupt timeout in jiffies */
+#define PT_SPIN_DEL     50	/* spin delay in micro-seconds  */
+#define PT_RESET_TMO    30	/* 30 seconds */
+#define PT_READY_TMO	60	/* 60 seconds */
+#define PT_REWIND_TMO	1200	/* 20 minutes */
 
-#define PT_SPIN         ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO)  
+#define PT_SPIN         ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO)
 
 #define STAT_ERR        0x00001
 #define STAT_INDEX      0x00002
@@ -207,16 +209,16 @@
 #define ATAPI_LOG_SENSE		0x4d
 
 static int pt_open(struct inode *inode, struct file *file);
-static int pt_ioctl(struct inode *inode,struct file *file,
-                    unsigned int cmd, unsigned long arg);
-static int pt_release (struct inode *inode, struct file *file);
-static ssize_t pt_read(struct file * filp, char * buf, 
-                       size_t count, loff_t *ppos);
-static ssize_t pt_write(struct file * filp, const char * buf, 
-                        size_t count, loff_t *ppos);
+static int pt_ioctl(struct inode *inode, struct file *file,
+		    unsigned int cmd, unsigned long arg);
+static int pt_release(struct inode *inode, struct file *file);
+static ssize_t pt_read(struct file *filp, char *buf,
+		       size_t count, loff_t * ppos);
+static ssize_t pt_write(struct file *filp, const char *buf,
+			size_t count, loff_t * ppos);
 static int pt_detect(void);
 
-static int pt_identify (int unit);
+static int pt_identify(int unit);
 
 /* bits in PT.flags */
 
@@ -231,18 +233,18 @@
 #define PT_BUFSIZE  16384
 
 struct pt_unit {
-	struct pi_adapter pia;    /* interface to paride layer */
+	struct pi_adapter pia;	/* interface to paride layer */
 	struct pi_adapter *pi;
-	int flags;        	  /* various state flags */
-	int last_sense;		  /* result of last request sense */
-	int drive;		  /* drive */
-	atomic_t available;       /* 1 if access is available 0 otherwise */
-	int bs;			  /* block size */
-	int capacity;             /* Size of tape in KB */
-	int present;		  /* device present ? */
+	int flags;		/* various state flags */
+	int last_sense;		/* result of last request sense */
+	int drive;		/* drive */
+	atomic_t available;	/* 1 if access is available 0 otherwise */
+	int bs;			/* block size */
+	int capacity;		/* Size of tape in KB */
+	int present;		/* device present ? */
 	char *bufptr;
-	char name[PT_NAMELEN];	  /* pf0, pf1, ... */
-	};
+	char name[PT_NAMELEN];	/* pf0, pf1, ... */
+};
 
 struct pt_unit pt[PT_UNITS];
 
@@ -251,641 +253,718 @@
 #define PT pt[unit]
 #define PI PT.pi
 
-static char pt_scratch[512];            /* scratch block buffer */
+static char pt_scratch[512];	/* scratch block buffer */
 
 /* kernel glue structures */
 
 static struct file_operations pt_fops = {
-	.owner =	THIS_MODULE,
-	.read =		pt_read,
-	.write =	pt_write,
-	.ioctl =	pt_ioctl,
-	.open =		pt_open,
-	.release =	pt_release,
+	.owner = THIS_MODULE,
+	.read = pt_read,
+	.write = pt_write,
+	.ioctl = pt_ioctl,
+	.open = pt_open,
+	.release = pt_release,
 };
 
-void pt_init_units( void )
-
-{       int     unit, j;
+static void pt_init_units(void)
+{
+	int unit, j;
 
-        pt_drive_count = 0;
-        for (unit=0;unit<PT_UNITS;unit++) {
-                PT.pi = & PT.pia;
-                atomic_set( &PT.available, 1 );
-                PT.flags = 0;
+	pt_drive_count = 0;
+	for (unit = 0; unit < PT_UNITS; unit++) {
+		PT.pi = &PT.pia;
+		atomic_set(&PT.available, 1);
+		PT.flags = 0;
 		PT.last_sense = 0;
-                PT.present = 0;
+		PT.present = 0;
 		PT.bufptr = NULL;
 		PT.drive = DU[D_SLV];
-                j = 0;
-                while ((j < PT_NAMELEN-2) && (PT.name[j]=name[j])) j++;
-                PT.name[j++] = '0' + unit;
-                PT.name[j] = 0;
-                if (DU[D_PRT]) pt_drive_count++;
-        }
+		j = 0;
+		while ((j < PT_NAMELEN - 2) && (PT.name[j] = name[j]))
+			j++;
+		PT.name[j++] = '0' + unit;
+		PT.name[j] = 0;
+		if (DU[D_PRT])
+			pt_drive_count++;
+	}
 }
 
-#define	WR(c,r,v)	pi_write_regr(PI,c,r,v)
-#define	RR(c,r)		(pi_read_regr(PI,c,r))
+static inline int status_reg(int unit)
+{
+	return pi_read_regr(PI, 1, 6);
+}
 
-#define DRIVE           (0xa0+0x10*PT.drive)
+static inline int read_reg(int unit, int reg)
+{
+	return pi_read_regr(PI, 0, reg);
+}
 
-static int pt_wait( int unit, int go, int stop, char * fun, char * msg )
+static inline void write_reg(int unit, int reg, int val)
+{
+	pi_write_regr(PI, 0, reg, val);
+}
 
-{       int j, r, e, s, p;
+#define DRIVE           (0xa0+0x10*PT.drive)
 
-        j = 0;
-        while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(j++<PT_SPIN))
-                udelay(PT_SPIN_DEL);
+static int pt_wait(int unit, int go, int stop, char *fun, char *msg)
+{
+	int j, r, e, s, p;
 
-        if ((r&(STAT_ERR&stop))||(j>=PT_SPIN)) {
-           s = RR(0,7);
-           e = RR(0,1);
-           p = RR(0,2);
-           if (j >= PT_SPIN) e |= 0x100;
-           if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
-                           " loop=%d phase=%d\n",
-                            PT.name,fun,msg,r,s,e,j,p);
-           return (e<<8)+s;
-        }
-        return 0;
+	j = 0;
+	while ((((r = status_reg(unit)) & go) || (stop && (!(r & stop))))
+	       && (j++ < PT_SPIN))
+		udelay(PT_SPIN_DEL);
+
+	if ((r & (STAT_ERR & stop)) || (j >= PT_SPIN)) {
+		s = read_reg(unit, 7);
+		e = read_reg(unit, 1);
+		p = read_reg(unit, 2);
+		if (j >= PT_SPIN)
+			e |= 0x100;
+		if (fun)
+			printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
+			       " loop=%d phase=%d\n",
+			       PT.name, fun, msg, r, s, e, j, p);
+		return (e << 8) + s;
+	}
+	return 0;
 }
 
-static int pt_command( int unit, char * cmd, int dlen, char * fun )
-
-{       pi_connect(PI);
+static int pt_command(int unit, char *cmd, int dlen, char *fun)
+{
+	pi_connect(PI);
 
-        WR(0,6,DRIVE);
+	write_reg(unit, 6, DRIVE);
 
-        if (pt_wait(unit,STAT_BUSY|STAT_DRQ,0,fun,"before command")) {
-                pi_disconnect(PI);
-                return -1;
-        }
+	if (pt_wait(unit, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) {
+		pi_disconnect(PI);
+		return -1;
+	}
 
-        WR(0,4,dlen % 256);
-        WR(0,5,dlen / 256);
-        WR(0,7,0xa0);          /* ATAPI packet command */
+	write_reg(unit, 4, dlen % 256);
+	write_reg(unit, 5, dlen / 256);
+	write_reg(unit, 7, 0xa0);	/* ATAPI packet command */
 
-        if (pt_wait(unit,STAT_BUSY,STAT_DRQ,fun,"command DRQ")) {
-                pi_disconnect(PI);
-                return -1;
-        }
+	if (pt_wait(unit, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) {
+		pi_disconnect(PI);
+		return -1;
+	}
 
-        if (RR(0,2) != 1) {
-           printk("%s: %s: command phase error\n",PT.name,fun);
-           pi_disconnect(PI);
-           return -1;
-        }
+	if (read_reg(unit, 2) != 1) {
+		printk("%s: %s: command phase error\n", PT.name, fun);
+		pi_disconnect(PI);
+		return -1;
+	}
 
-        pi_write_block(PI,cmd,12);
+	pi_write_block(PI, cmd, 12);
 
-        return 0;
+	return 0;
 }
 
-static int pt_completion( int unit, char * buf, char * fun )
-
-{       int r, s, n, p;
+static int pt_completion(int unit, char *buf, char *fun)
+{
+	int r, s, n, p;
 
-        r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
-			fun,"completion");
+	r = pt_wait(unit, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR,
+		    fun, "completion");
 
-        if (RR(0,7)&STAT_DRQ) { 
-           n = (((RR(0,4)+256*RR(0,5))+3)&0xfffc);
-	   p = RR(0,2)&3;
-	   if (p == 0) pi_write_block(PI,buf,n);
-	   if (p == 2) pi_read_block(PI,buf,n);
-        }
+	if (read_reg(unit, 7) & STAT_DRQ) {
+		n = (((read_reg(unit, 4) + 256 * read_reg(unit, 5)) +
+		      3) & 0xfffc);
+		p = read_reg(unit, 2) & 3;
+		if (p == 0)
+			pi_write_block(PI, buf, n);
+		if (p == 2)
+			pi_read_block(PI, buf, n);
+	}
 
-        s = pt_wait(unit,STAT_BUSY,STAT_READY|STAT_ERR,fun,"data done");
+	s = pt_wait(unit, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done");
 
-        pi_disconnect(PI); 
+	pi_disconnect(PI);
 
-        return (r?r:s);
+	return (r ? r : s);
 }
 
-static void pt_req_sense( int unit, int quiet )
-
-{       char    rs_cmd[12] = { ATAPI_REQ_SENSE,0,0,0,16,0,0,0,0,0,0,0 };
-        char    buf[16];
-        int     r;
-
-        r = pt_command(unit,rs_cmd,16,"Request sense");
-        mdelay(1);
-        if (!r) pt_completion(unit,buf,"Request sense");
+static void pt_req_sense(int unit, int quiet)
+{
+	char rs_cmd[12] = { ATAPI_REQ_SENSE, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
+	char buf[16];
+	int r;
+
+	r = pt_command(unit, rs_cmd, 16, "Request sense");
+	mdelay(1);
+	if (!r)
+		pt_completion(unit, buf, "Request sense");
 
 	PT.last_sense = -1;
-        if (!r) {
-	    if (!quiet) printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
-                                    PT.name,buf[2]&0xf,buf[12],buf[13]);
-	    PT.last_sense = (buf[2]&0xf) | ((buf[12]&0xff)<<8)
-					 | ((buf[13]&0xff)<<16) ;
-	} 
+	if (!r) {
+		if (!quiet)
+			printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
+			       PT.name, buf[2] & 0xf, buf[12], buf[13]);
+		PT.last_sense = (buf[2] & 0xf) | ((buf[12] & 0xff) << 8)
+		    | ((buf[13] & 0xff) << 16);
+	}
 }
 
-static int pt_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
+static int pt_atapi(int unit, char *cmd, int dlen, char *buf, char *fun)
+{
+	int r;
 
-{       int r;
+	r = pt_command(unit, cmd, dlen, fun);
+	mdelay(1);
+	if (!r)
+		r = pt_completion(unit, buf, fun);
+	if (r)
+		pt_req_sense(unit, !fun);
 
-        r = pt_command(unit,cmd,dlen,fun);
-        mdelay(1);
-        if (!r) r = pt_completion(unit,buf,fun);
-        if (r) pt_req_sense(unit,!fun);
-        
-        return r;
+	return r;
 }
 
-static void pt_sleep( int cs )
-
-{       current->state = TASK_INTERRUPTIBLE;
-        schedule_timeout(cs);
+static void pt_sleep(int cs)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(cs);
 }
 
-static int pt_poll_dsc( int unit, int pause, int tmo, char *msg )
-
-{	int	k, e, s;
+static int pt_poll_dsc(int unit, int pause, int tmo, char *msg)
+{
+	int k, e, s;
 
-	k = 0; e = 0; s = 0;
+	k = 0;
+	e = 0;
+	s = 0;
 	while (k < tmo) {
 		pt_sleep(pause);
 		k++;
 		pi_connect(PI);
-		WR(0,6,DRIVE);
-		s = RR(0,7);
-		e = RR(0,1);
+		write_reg(unit, 6, DRIVE);
+		s = read_reg(unit, 7);
+		e = read_reg(unit, 1);
 		pi_disconnect(PI);
-		if (s & (STAT_ERR|STAT_SEEK)) break;
+		if (s & (STAT_ERR | STAT_SEEK))
+			break;
 	}
 	if ((k >= tmo) || (s & STAT_ERR)) {
-	   if (k >= tmo) printk("%s: %s DSC timeout\n",PT.name,msg);
-	     else printk("%s: %s stat=0x%x err=0x%x\n",PT.name,msg,s,e);
-	   pt_req_sense(unit,0);
-	   return 0;
+		if (k >= tmo)
+			printk("%s: %s DSC timeout\n", PT.name, msg);
+		else
+			printk("%s: %s stat=0x%x err=0x%x\n", PT.name, msg, s,
+			       e);
+		pt_req_sense(unit, 0);
+		return 0;
 	}
 	return 1;
 }
 
-static void pt_media_access_cmd( int unit, int tmo, char *cmd, char *fun)
-
-{	if (pt_command(unit,cmd,0,fun)) {
-		pt_req_sense(unit,0);
+static void pt_media_access_cmd(int unit, int tmo, char *cmd, char *fun)
+{
+	if (pt_command(unit, cmd, 0, fun)) {
+		pt_req_sense(unit, 0);
 		return;
 	}
 	pi_disconnect(PI);
-	pt_poll_dsc(unit,HZ,tmo,fun);
+	pt_poll_dsc(unit, HZ, tmo, fun);
 }
 
-static void pt_rewind( int unit )
-
-{	char	rw_cmd[12] = {ATAPI_REWIND,0,0,0,0,0,0,0,0,0,0,0};
+static void pt_rewind(int unit)
+{
+	char rw_cmd[12] = { ATAPI_REWIND, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
-	pt_media_access_cmd(unit,PT_REWIND_TMO,rw_cmd,"rewind");
+	pt_media_access_cmd(unit, PT_REWIND_TMO, rw_cmd, "rewind");
 }
 
-static void pt_write_fm( int unit )
-
-{	char	wm_cmd[12] = {ATAPI_WFM,0,0,0,1,0,0,0,0,0,0,0};
+static void pt_write_fm(int unit)
+{
+	char wm_cmd[12] = { ATAPI_WFM, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
 
-        pt_media_access_cmd(unit,PT_TMO,wm_cmd,"write filemark");
+	pt_media_access_cmd(unit, PT_TMO, wm_cmd, "write filemark");
 }
 
 #define DBMSG(msg)      ((verbose>1)?(msg):NULL)
 
-static int pt_reset( int unit )
-
-{	int	i, k, flg;
-	int	expect[5] = {1,1,1,0x14,0xeb};
+static int pt_reset(int unit)
+{
+	int i, k, flg;
+	int expect[5] = { 1, 1, 1, 0x14, 0xeb };
 
 	pi_connect(PI);
-	WR(0,6,DRIVE);
-	WR(0,7,8);
+	write_reg(unit, 6, DRIVE);
+	write_reg(unit, 7, 8);
 
-	pt_sleep(20*HZ/1000);
+	pt_sleep(20 * HZ / 1000);
 
-        k = 0;
-        while ((k++ < PT_RESET_TMO) && (RR(1,6)&STAT_BUSY))
-                pt_sleep(HZ/10);
+	k = 0;
+	while ((k++ < PT_RESET_TMO) && (status_reg(unit) & STAT_BUSY))
+		pt_sleep(HZ / 10);
 
 	flg = 1;
-	for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
+	for (i = 0; i < 5; i++)
+		flg &= (read_reg(unit, i + 1) == expect[i]);
 
 	if (verbose) {
-		printk("%s: Reset (%d) signature = ",PT.name,k);
-		for (i=0;i<5;i++) printk("%3x",RR(0,i+1));
-		if (!flg) printk(" (incorrect)");
+		printk("%s: Reset (%d) signature = ", PT.name, k);
+		for (i = 0; i < 5; i++)
+			printk("%3x", read_reg(unit, i + 1));
+		if (!flg)
+			printk(" (incorrect)");
 		printk("\n");
 	}
-	
+
 	pi_disconnect(PI);
-	return flg-1;	
+	return flg - 1;
 }
 
-static int pt_ready_wait( int unit, int tmo )
-
-{	char	tr_cmd[12] = {ATAPI_TEST_READY,0,0,0,0,0,0,0,0,0,0,0};
-	int	k, p;
+static int pt_ready_wait(int unit, int tmo)
+{
+	char tr_cmd[12] = { ATAPI_TEST_READY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	int k, p;
 
 	k = 0;
 	while (k < tmo) {
-	  PT.last_sense = 0;
-	  pt_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready"));
-	  p = PT.last_sense;
-	  if (!p) return 0;
-	  if (!(((p & 0xffff) == 0x0402)||((p & 0xff) == 6))) return p;
-	  k++;
-          pt_sleep(HZ);
+		PT.last_sense = 0;
+		pt_atapi(unit, tr_cmd, 0, NULL, DBMSG("test unit ready"));
+		p = PT.last_sense;
+		if (!p)
+			return 0;
+		if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6)))
+			return p;
+		k++;
+		pt_sleep(HZ);
 	}
 	return 0x000020;	/* timeout */
 }
 
-static void xs( char *buf, char *targ, int offs, int len )
-
-{	int	j,k,l;
+static void xs(char *buf, char *targ, int offs, int len)
+{
+	int j, k, l;
 
-	j=0; l=0;
-	for (k=0;k<len;k++) 
-	   if((buf[k+offs]!=0x20)||(buf[k+offs]!=l))
-		l=targ[j++]=buf[k+offs];
-	if (l==0x20) j--;
-	targ[j]=0;
+	j = 0;
+	l = 0;
+	for (k = 0; k < len; k++)
+		if ((buf[k + offs] != 0x20) || (buf[k + offs] != l))
+			l = targ[j++] = buf[k + offs];
+	if (l == 0x20)
+		j--;
+	targ[j] = 0;
 }
 
-static int xn( char *buf, int offs, int size )
-
-{	int	v,k;
+static int xn(char *buf, int offs, int size)
+{
+	int v, k;
 
-	v=0; 
-	for(k=0;k<size;k++) v=v*256+(buf[k+offs]&0xff);
+	v = 0;
+	for (k = 0; k < size; k++)
+		v = v * 256 + (buf[k + offs] & 0xff);
 	return v;
 }
 
-static int pt_identify( int unit )
-
-{	int 	dt, s;
-	char	*ms[2] = {"master","slave"};
-	char	mf[10], id[18];
-	char    id_cmd[12] = { ATAPI_IDENTIFY,0,0,0,36,0,0,0,0,0,0,0};
-        char    ms_cmd[12] = { ATAPI_MODE_SENSE,0,0x2a,0,36,0,0,0,0,0,0,0};
-	char    ls_cmd[12] = { ATAPI_LOG_SENSE,0,0x71,0,0,0,0,0,36,0,0,0};
-	char	buf[36];
+static int pt_identify(int unit)
+{
+	int dt, s;
+	char *ms[2] = { "master", "slave" };
+	char mf[10], id[18];
+	char id_cmd[12] = { ATAPI_IDENTIFY, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
+	char ms_cmd[12] =
+	    { ATAPI_MODE_SENSE, 0, 0x2a, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
+	char ls_cmd[12] =
+	    { ATAPI_LOG_SENSE, 0, 0x71, 0, 0, 0, 0, 0, 36, 0, 0, 0 };
+	char buf[36];
 
-        s = pt_atapi(unit,id_cmd,36,buf,"identify");
-	if (s) return -1;
+	s = pt_atapi(unit, id_cmd, 36, buf, "identify");
+	if (s)
+		return -1;
 
 	dt = buf[0] & 0x1f;
 	if (dt != 1) {
-	  	if (verbose) 
-		   printk("%s: Drive %d, unsupported type %d\n",
-				PT.name,PT.drive,dt);
-	  	return -1;
-       	}
+		if (verbose)
+			printk("%s: Drive %d, unsupported type %d\n",
+			       PT.name, PT.drive, dt);
+		return -1;
+	}
 
-	xs(buf,mf,8,8);
-	xs(buf,id,16,16);
+	xs(buf, mf, 8, 8);
+	xs(buf, id, 16, 16);
 
 	PT.flags = 0;
 	PT.capacity = 0;
 	PT.bs = 0;
 
-	if (!pt_ready_wait(unit,PT_READY_TMO)) PT.flags |= PT_MEDIA;
+	if (!pt_ready_wait(unit, PT_READY_TMO))
+		PT.flags |= PT_MEDIA;
 
-        if (!pt_atapi(unit,ms_cmd,36,buf,"mode sense")) {
-          if (!(buf[2] & 0x80)) PT.flags |= PT_WRITE_OK;
-	  PT.bs = xn(buf,10,2);
-	}
-
-        if (!pt_atapi(unit,ls_cmd,36,buf,"log sense")) 
-		PT.capacity = xn(buf,24,4);
-
-        printk("%s: %s %s, %s",
-		PT.name,mf,id,ms[PT.drive]);
-        if (!(PT.flags & PT_MEDIA)) 
-                printk(", no media\n");
-        else {  if (!(PT.flags & PT_WRITE_OK)) printk(", RO");
-                printk(", blocksize %d, %d MB\n",
-		       PT.bs,PT.capacity/1024);
-        }
+	if (!pt_atapi(unit, ms_cmd, 36, buf, "mode sense")) {
+		if (!(buf[2] & 0x80))
+			PT.flags |= PT_WRITE_OK;
+		PT.bs = xn(buf, 10, 2);
+	}
+
+	if (!pt_atapi(unit, ls_cmd, 36, buf, "log sense"))
+		PT.capacity = xn(buf, 24, 4);
+
+	printk("%s: %s %s, %s", PT.name, mf, id, ms[PT.drive]);
+	if (!(PT.flags & PT_MEDIA))
+		printk(", no media\n");
+	else {
+		if (!(PT.flags & PT_WRITE_OK))
+			printk(", RO");
+		printk(", blocksize %d, %d MB\n", PT.bs, PT.capacity / 1024);
+	}
 
 	return 0;
 }
 
-static int pt_probe( int unit )
-
-/*	returns  0, with id set if drive is detected
-	        -1, if drive detection failed
-*/
 
-{	if (PT.drive == -1) {
-	   for (PT.drive=0;PT.drive<=1;PT.drive++)
-		if (!pt_reset(unit)) return pt_identify(unit);
+/*
+ * returns  0, with id set if drive is detected
+ *	   -1, if drive detection failed
+ */
+static int pt_probe(int unit)
+{
+	if (PT.drive == -1) {
+		for (PT.drive = 0; PT.drive <= 1; PT.drive++)
+			if (!pt_reset(unit))
+				return pt_identify(unit);
 	} else {
-	   if (!pt_reset(unit)) return pt_identify(unit);
+		if (!pt_reset(unit))
+			return pt_identify(unit);
 	}
-        return -1; 
+	return -1;
 }
 
-static int pt_detect( void )
-
-{	int	k, unit;
+static int pt_detect(void)
+{
+	int k, unit;
 
-	printk("%s: %s version %s, major %d\n",
-		name,name,PT_VERSION,major);
+	printk("%s: %s version %s, major %d\n", name, name, PT_VERSION, major);
 
 	k = 0;
 	if (pt_drive_count == 0) {
-	    unit = 0;
-	    if (pi_init(PI,1,-1,-1,-1,-1,-1,pt_scratch,
-                        PI_PT,verbose,PT.name)) {
-	        if (!pt_probe(unit)) {
-			PT.present = 1;
-			k++;
-	        } else pi_release(PI);
-	    }
-
-	} else for (unit=0;unit<PT_UNITS;unit++) if (DU[D_PRT])
-	    if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
-			DU[D_PRO],DU[D_DLY],pt_scratch,PI_PT,verbose,
-			PT.name)) { 
-                if (!pt_probe(unit)) {
-                        PT.present = 1;
-                        k++;
-                } else pi_release(PI);
-            }
+		unit = 0;
+		if (pi_init(PI, 1, -1, -1, -1, -1, -1, pt_scratch,
+			    PI_PT, verbose, PT.name)) {
+			if (!pt_probe(unit)) {
+				PT.present = 1;
+				k++;
+			} else
+				pi_release(PI);
+		}
 
-	if (k) return 0;
+	} else
+		for (unit = 0; unit < PT_UNITS; unit++)
+			if (DU[D_PRT])
+				if (pi_init
+				    (PI, 0, DU[D_PRT], DU[D_MOD], DU[D_UNI],
+				     DU[D_PRO], DU[D_DLY], pt_scratch, PI_PT,
+				     verbose, PT.name)) {
+					if (!pt_probe(unit)) {
+						PT.present = 1;
+						k++;
+					} else
+						pi_release(PI);
+				}
 
-	printk("%s: No ATAPI tape drive detected\n",name);
+	if (k)
+		return 0;
+
+	printk("%s: No ATAPI tape drive detected\n", name);
 	return -1;
 }
 
 #define DEVICE_NR(dev)	(minor(dev) & 0x7F)
 
-static int pt_open (struct inode *inode, struct file *file)
-
-{       int	unit = DEVICE_NR(inode->i_rdev);
+static int pt_open(struct inode *inode, struct file *file)
+{
+	int unit = DEVICE_NR(inode->i_rdev);
 
-        if ((unit >= PT_UNITS) || (!PT.present)) return -ENODEV;
+	if ((unit >= PT_UNITS) || (!PT.present))
+		return -ENODEV;
 
-	if ( !atomic_dec_and_test(&PT.available) ) {
-		atomic_inc( &PT.available );
+	if (!atomic_dec_and_test(&PT.available)) {
+		atomic_inc(&PT.available);
 		return -EBUSY;
 	}
 
 	pt_identify(unit);
 
 	if (!PT.flags & PT_MEDIA) {
-		atomic_inc( &PT.available );
+		atomic_inc(&PT.available);
 		return -ENODEV;
-		}
+	}
 
-	if ((!PT.flags & PT_WRITE_OK) && (file ->f_mode & 2)) {
-		atomic_inc( &PT.available );
+	if ((!PT.flags & PT_WRITE_OK) && (file->f_mode & 2)) {
+		atomic_inc(&PT.available);
 		return -EROFS;
-		}
+	}
 
 	if (!(minor(inode->i_rdev) & 128))
 		PT.flags |= PT_REWIND;
 
-	PT.bufptr = kmalloc(PT_BUFSIZE,GFP_KERNEL);
+	PT.bufptr = kmalloc(PT_BUFSIZE, GFP_KERNEL);
 	if (PT.bufptr == NULL) {
-		atomic_inc( &PT.available );
-		printk("%s: buffer allocation failed\n",PT.name);
+		atomic_inc(&PT.available);
+		printk("%s: buffer allocation failed\n", PT.name);
 		return -ENOMEM;
 	}
 
-        return 0;
+	return 0;
 }
 
-static int pt_ioctl(struct inode *inode,struct file *file,
-                    unsigned int cmd, unsigned long arg)
+static int pt_ioctl(struct inode *inode, struct file *file,
+	 unsigned int cmd, unsigned long arg)
 {
 	int unit;
 	struct mtop mtop;
 
-        unit = DEVICE_NR(inode->i_rdev);
-        if (unit >= PT_UNITS)
+	unit = DEVICE_NR(inode->i_rdev);
+	if (unit >= PT_UNITS)
 		return -EINVAL;
-        if (!PT.present)
+	if (!PT.present)
 		return -ENODEV;
 
-        switch (cmd) {
-	    case MTIOCTOP:	
-		if (copy_from_user((char *)&mtop, (char *)arg, 
-			           sizeof(struct mtop))) return -EFAULT;
+	switch (cmd) {
+	case MTIOCTOP:
+		if (copy_from_user((char *) &mtop, (char *) arg,
+				   sizeof (struct mtop)))
+			return -EFAULT;
 
 		switch (mtop.mt_op) {
 
-		    case MTREW: 
+		case MTREW:
 			pt_rewind(unit);
 			return 0;
 
-		    case MTWEOF:
+		case MTWEOF:
 			pt_write_fm(unit);
 			return 0;
 
-		    default:	
-			printk("%s: Unimplemented mt_op %d\n",PT.name,
-					mtop.mt_op);
+		default:
+			printk("%s: Unimplemented mt_op %d\n", PT.name,
+			       mtop.mt_op);
 			return -EINVAL;
 		}
 
-            default:
-		printk("%s: Unimplemented ioctl 0x%x\n",PT.name,cmd);
-                return -EINVAL;
+	default:
+		printk("%s: Unimplemented ioctl 0x%x\n", PT.name, cmd);
+		return -EINVAL;
 
-        }
+	}
 }
 
-
-static int pt_release (struct inode *inode, struct file *file)
+static int
+pt_release(struct inode *inode, struct file *file)
 {
-        int	unit = DEVICE_NR(inode->i_rdev);
+	int unit = DEVICE_NR(inode->i_rdev);
 
-        if ((unit >= PT_UNITS) || (atomic_read(&PT.available) > 1)) 
-                return -EINVAL;
+	if ((unit >= PT_UNITS) || (atomic_read(&PT.available) > 1))
+		return -EINVAL;
 
-	if (PT.flags & PT_WRITING) pt_write_fm(unit);
+	if (PT.flags & PT_WRITING)
+		pt_write_fm(unit);
 
-	if (PT.flags & PT_REWIND) pt_rewind(unit);	
+	if (PT.flags & PT_REWIND)
+		pt_rewind(unit);
 
 	kfree(PT.bufptr);
 	PT.bufptr = NULL;
 
-	atomic_inc( &PT.available );
-	
+	atomic_inc(&PT.available);
+
 	return 0;
 
 }
 
-static ssize_t pt_read(struct file * filp, char * buf, 
-                       size_t count, loff_t *ppos)
+static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos)
 {
-  	struct 	inode *ino = filp->f_dentry->d_inode;
-	int	unit = DEVICE_NR(ino->i_rdev);
-	char	rd_cmd[12] = {ATAPI_READ_6,1,0,0,0,0,0,0,0,0,0,0};
-	int	k, n, r, p, s, t, b;
-
-	if (!(PT.flags & (PT_READING|PT_WRITING))) {
-	    PT.flags |= PT_READING;
-	    if (pt_atapi(unit,rd_cmd,0,NULL,"start read-ahead"))
+	struct inode *ino = filp->f_dentry->d_inode;
+	int unit = DEVICE_NR(ino->i_rdev);
+	char rd_cmd[12] = { ATAPI_READ_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	int k, n, r, p, s, t, b;
+
+	if (!(PT.flags & (PT_READING | PT_WRITING))) {
+		PT.flags |= PT_READING;
+		if (pt_atapi(unit, rd_cmd, 0, NULL, "start read-ahead"))
 			return -EIO;
-	} else if (PT.flags & PT_WRITING) return -EIO;
+	} else if (PT.flags & PT_WRITING)
+		return -EIO;
 
-	if (PT.flags & PT_EOF) return 0;
+	if (PT.flags & PT_EOF)
+		return 0;
 
 	t = 0;
 
 	while (count > 0) {
 
-	    if (!pt_poll_dsc(unit,HZ/100,PT_TMO,"read")) return -EIO;
+		if (!pt_poll_dsc(unit, HZ / 100, PT_TMO, "read"))
+			return -EIO;
 
-	    n = count;
-	    if (n > 32768) n = 32768;   /* max per command */
-	    b = (n-1+PT.bs)/PT.bs;
-	    n = b*PT.bs;		/* rounded up to even block */
-
-	    rd_cmd[4] = b;
-
-	    r = pt_command(unit,rd_cmd,n,"read");
-
-	    mdelay(1);
-
-	    if (r) {
-	        pt_req_sense(unit,0);
-	        return -EIO;
-	    }
-
-	    while (1) {
-
-	        r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR|STAT_READY,
-                                           DBMSG("read DRQ"),"");
-
-	        if (r & STAT_SENSE) {
-	            pi_disconnect(PI);
-		    pt_req_sense(unit,0);
-		    return -EIO;
-	        }
-
-	        if (r) PT.flags |= PT_EOF; 
-
-	        s = RR(0,7);
-
-	        if (!(s & STAT_DRQ)) break;
-
-	    	n = (RR(0,4)+256*RR(0,5));
-	    	p = (RR(0,2)&3);
-	    	if (p != 2) {
-		    pi_disconnect(PI);
-		    printk("%s: Phase error on read: %d\n",PT.name,p);
-		    return -EIO;
-	    	}
-
-	        while (n > 0) {
-		    k = n;
-		    if (k > PT_BUFSIZE) k = PT_BUFSIZE; 
-		    pi_read_block(PI,PT.bufptr,k);
-		    n -= k;
-		    b = k;
-		    if (b > count) b = count;
-		    if (copy_to_user(buf + t, PT.bufptr, b)) {
-	    		pi_disconnect(PI);
-			return -EFAULT;
-		    }
-		    t += b;
-		    count -= b;
-	        }
-
-	    }
-	    pi_disconnect(PI);
-	    if (PT.flags & PT_EOF) break;
+		n = count;
+		if (n > 32768)
+			n = 32768;	/* max per command */
+		b = (n - 1 + PT.bs) / PT.bs;
+		n = b * PT.bs;	/* rounded up to even block */
+
+		rd_cmd[4] = b;
+
+		r = pt_command(unit, rd_cmd, n, "read");
+
+		mdelay(1);
+
+		if (r) {
+			pt_req_sense(unit, 0);
+			return -EIO;
+		}
+
+		while (1) {
+
+			r = pt_wait(unit, STAT_BUSY,
+				    STAT_DRQ | STAT_ERR | STAT_READY,
+				    DBMSG("read DRQ"), "");
+
+			if (r & STAT_SENSE) {
+				pi_disconnect(PI);
+				pt_req_sense(unit, 0);
+				return -EIO;
+			}
+
+			if (r)
+				PT.flags |= PT_EOF;
+
+			s = read_reg(unit, 7);
+
+			if (!(s & STAT_DRQ))
+				break;
+
+			n = (read_reg(unit, 4) + 256 * read_reg(unit, 5));
+			p = (read_reg(unit, 2) & 3);
+			if (p != 2) {
+				pi_disconnect(PI);
+				printk("%s: Phase error on read: %d\n", PT.name,
+				       p);
+				return -EIO;
+			}
+
+			while (n > 0) {
+				k = n;
+				if (k > PT_BUFSIZE)
+					k = PT_BUFSIZE;
+				pi_read_block(PI, PT.bufptr, k);
+				n -= k;
+				b = k;
+				if (b > count)
+					b = count;
+				if (copy_to_user(buf + t, PT.bufptr, b)) {
+					pi_disconnect(PI);
+					return -EFAULT;
+				}
+				t += b;
+				count -= b;
+			}
+
+		}
+		pi_disconnect(PI);
+		if (PT.flags & PT_EOF)
+			break;
 	}
 
 	return t;
 
 }
 
-static ssize_t pt_write(struct file * filp, const char * buf, 
-                        size_t count, loff_t *ppos)
+static ssize_t pt_write(struct file *filp, const char *buf, size_t count, loff_t * ppos)
 {
-        struct inode *ino = filp->f_dentry->d_inode;
-        int unit = DEVICE_NR(ino->i_rdev);
-        char    wr_cmd[12] = {ATAPI_WRITE_6,1,0,0,0,0,0,0,0,0,0,0};
-        int     k, n, r, p, s, t, b;
-
-	if (!(PT.flags & PT_WRITE_OK)) return -EROFS;
-
-        if (!(PT.flags & (PT_READING|PT_WRITING))) {
-            PT.flags |= PT_WRITING;
-            if (pt_atapi(unit,wr_cmd,0,NULL,"start buffer-available mode"))
-                        return -EIO;
-        } else if (PT.flags&PT_READING) return -EIO;
+	struct inode *ino = filp->f_dentry->d_inode;
+	int unit = DEVICE_NR(ino->i_rdev);
+	char wr_cmd[12] = { ATAPI_WRITE_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	int k, n, r, p, s, t, b;
 
-	if (PT.flags & PT_EOF) return -ENOSPC;
-
-	t = 0;
-
-	while (count > 0) {
-
-	    if (!pt_poll_dsc(unit,HZ/100,PT_TMO,"write")) return -EIO;
+	if (!(PT.flags & PT_WRITE_OK))
+		return -EROFS;
 
-            n = count;
-            if (n > 32768) n = 32768;	/* max per command */
-            b = (n-1+PT.bs)/PT.bs;
-            n = b*PT.bs;                /* rounded up to even block */
+	if (!(PT.flags & (PT_READING | PT_WRITING))) {
+		PT.flags |= PT_WRITING;
+		if (pt_atapi
+		    (unit, wr_cmd, 0, NULL, "start buffer-available mode"))
+			return -EIO;
+	} else if (PT.flags & PT_READING)
+		return -EIO;
 
-            wr_cmd[4] = b;
+	if (PT.flags & PT_EOF)
+		return -ENOSPC;
 
-            r = pt_command(unit,wr_cmd,n,"write");
+	t = 0;
 
-            mdelay(1);
+	while (count > 0) {
 
-            if (r) {			/* error delivering command only */
-                pt_req_sense(unit,0);
-                return -EIO;
-            }
+		if (!pt_poll_dsc(unit, HZ / 100, PT_TMO, "write"))
+			return -EIO;
 
-	    while (1) {
+		n = count;
+		if (n > 32768)
+			n = 32768;	/* max per command */
+		b = (n - 1 + PT.bs) / PT.bs;
+		n = b * PT.bs;	/* rounded up to even block */
 
-                r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR|STAT_READY,
-			                        DBMSG("write DRQ"),NULL);
+		wr_cmd[4] = b;
 
-                if (r & STAT_SENSE) {
-                    pi_disconnect(PI);
-                    pt_req_sense(unit,0);
-                    return -EIO;
-                }
+		r = pt_command(unit, wr_cmd, n, "write");
 
-                if (r) PT.flags |= PT_EOF;
+		mdelay(1);
 
-	        s = RR(0,7);
+		if (r) {	/* error delivering command only */
+			pt_req_sense(unit, 0);
+			return -EIO;
+		}
 
-	        if (!(s & STAT_DRQ)) break;
+		while (1) {
 
-                n = (RR(0,4)+256*RR(0,5));
-                p = (RR(0,2)&3);
-                if (p != 0) {
-                    pi_disconnect(PI);
-                    printk("%s: Phase error on write: %d \n",PT.name,p);
-                    return -EIO;
-                }
+			r = pt_wait(unit, STAT_BUSY,
+				    STAT_DRQ | STAT_ERR | STAT_READY,
+				    DBMSG("write DRQ"), NULL);
+
+			if (r & STAT_SENSE) {
+				pi_disconnect(PI);
+				pt_req_sense(unit, 0);
+				return -EIO;
+			}
+
+			if (r)
+				PT.flags |= PT_EOF;
+
+			s = read_reg(unit, 7);
+
+			if (!(s & STAT_DRQ))
+				break;
+
+			n = (read_reg(unit, 4) + 256 * read_reg(unit, 5));
+			p = (read_reg(unit, 2) & 3);
+			if (p != 0) {
+				pi_disconnect(PI);
+				printk("%s: Phase error on write: %d \n",
+				       PT.name, p);
+				return -EIO;
+			}
+
+			while (n > 0) {
+				k = n;
+				if (k > PT_BUFSIZE)
+					k = PT_BUFSIZE;
+				b = k;
+				if (b > count)
+					b = count;
+				if (copy_from_user(PT.bufptr, buf + t, b)) {
+					pi_disconnect(PI);
+					return -EFAULT;
+				}
+				pi_write_block(PI, PT.bufptr, k);
+				t += b;
+				count -= b;
+				n -= k;
+			}
 
-                while (n > 0) {
-		    k = n;
-		    if (k > PT_BUFSIZE) k = PT_BUFSIZE;
-		    b = k;
-		    if (b > count) b = count;
-		    if (copy_from_user(PT.bufptr, buf + t, b)) {
-			pi_disconnect(PI);
-			return -EFAULT;
-		    }
-                    pi_write_block(PI,PT.bufptr,k);
-		    t += b;
-		    count -= b;
-		    n -= k;
-                }
-
-	    }
-	    pi_disconnect(PI);
-	    if (PT.flags & PT_EOF) break;
+		}
+		pi_disconnect(PI);
+		if (PT.flags & PT_EOF)
+			break;
 	}
 
 	return t;
@@ -903,23 +982,23 @@
 	if (pt_detect())
 		return -1;
 
-	if (register_chrdev(major,name,&pt_fops)) {
-		printk("pt_init: unable to get major number %d\n",
-			major);
-		for (unit=0;unit<PT_UNITS;unit++)
-			if (PT.present) pi_release(PI);
+	if (register_chrdev(major, name, &pt_fops)) {
+		printk("pt_init: unable to get major number %d\n", major);
+		for (unit = 0; unit < PT_UNITS; unit++)
+			if (PT.present)
+				pi_release(PI);
 		return -1;
 	}
 
-	devfs_mk_dir ("pt");
-	for (unit=0;unit<PT_UNITS;unit++)
+	devfs_mk_dir("pt");
+	for (unit = 0; unit < PT_UNITS; unit++)
 		if (PT.present) {
 			devfs_mk_cdev(MKDEV(major, unit),
-					S_IFCHR | S_IRUSR | S_IWUSR,
-					"pt/%d", 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);
+				      S_IFCHR | S_IRUSR | S_IWUSR,
+				      "pt/%dn", unit);
 		}
 	return 0;
 }
@@ -927,14 +1006,14 @@
 static void __exit pt_exit(void)
 {
 	int unit;
-	for (unit=0;unit<PT_UNITS;unit++)
+	for (unit = 0; unit < PT_UNITS; unit++)
 		if (PT.present) {
 			devfs_remove("pt/%d", unit);
 			devfs_remove("pt/%dn", unit);
 		}
 	devfs_remove("pt");
-	unregister_chrdev(major,name);
-	for (unit=0;unit<PT_UNITS;unit++)
+	unregister_chrdev(major, name);
+	for (unit = 0; unit < PT_UNITS; unit++)
 		if (PT.present)
 			pi_release(PI);
 }
diff -urN linux-2.5.69-bk18/drivers/block/rd.c linux-2.5.69-bk19/drivers/block/rd.c
--- linux-2.5.69-bk18/drivers/block/rd.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/drivers/block/rd.c	2003-05-26 04:41:41.000000000 -0700
@@ -67,6 +67,7 @@
 
 static struct gendisk *rd_disks[NUM_RAMDISKS];
 static struct block_device *rd_bdev[NUM_RAMDISKS];/* Protected device data */
+static struct request_queue *rd_queue;
 
 /*
  * Parameters for the boot-loading of the RAM disk.  These are set by
@@ -308,12 +309,11 @@
 		del_gendisk(rd_disks[i]);
 		put_disk(rd_disks[i]);
 	}
-
+	kfree(rd_queue);
 	devfs_remove("rd");
 	unregister_blkdev(RAMDISK_MAJOR, "ramdisk" );
 }
 
-static struct request_queue rd_queue;
 /* This is the registration and initialization section of the RAM disk driver */
 static int __init rd_init (void)
 {
@@ -333,23 +333,28 @@
 			goto out;
 	}
 
+	rd_queue = kmalloc(NUM_RAMDISKS * sizeof(struct request_queue),
+			     GFP_KERNEL);
+	if (!rd_queue)
+		goto out;
+	memset(rd_queue, 0, NUM_RAMDISKS * sizeof(struct request_queue));
 	if (register_blkdev(RAMDISK_MAJOR, "ramdisk")) {
 		err = -EIO;
-		goto out;
+		goto out_queue;
 	}
 
-	blk_queue_make_request(&rd_queue, &rd_make_request);
-
 	devfs_mk_dir("rd");
 
 	for (i = 0; i < NUM_RAMDISKS; i++) {
 		struct gendisk *disk = rd_disks[i];
 
+		blk_queue_make_request(&rd_queue[i], &rd_make_request);
+
 		/* rd_size is given in kB */
 		disk->major = RAMDISK_MAJOR;
 		disk->first_minor = i;
 		disk->fops = &rd_bd_op;
-		disk->queue = &rd_queue;
+		disk->queue = &rd_queue[i];
 		sprintf(disk->disk_name, "ram%d", i);
 		sprintf(disk->devfs_name, "rd/%d", i);
 		set_capacity(disk, rd_size * 2);
@@ -362,6 +367,8 @@
 	       NUM_RAMDISKS, rd_size, rd_blocksize);
 
 	return 0;
+out_queue:
+	kfree(rd_queue);
 out:
 	while (i--)
 		put_disk(rd_disks[i]);
diff -urN linux-2.5.69-bk18/drivers/block/z2ram.c linux-2.5.69-bk19/drivers/block/z2ram.c
--- linux-2.5.69-bk18/drivers/block/z2ram.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/drivers/block/z2ram.c	2003-05-26 04:41:41.000000000 -0700
@@ -322,7 +322,7 @@
 	.release	= z2_release,
 };
 
-static struct gendisk *z2_find(dev_t dev, int *part, void *data)
+static struct kobject *z2_find(dev_t dev, int *part, void *data)
 {
 	*part = 0;
 	return get_disk(z2ram_gendisk);
diff -urN linux-2.5.69-bk18/drivers/char/amiserial.c linux-2.5.69-bk19/drivers/char/amiserial.c
--- linux-2.5.69-bk18/drivers/char/amiserial.c	2003-05-26 04:41:35.000000000 -0700
+++ linux-2.5.69-bk19/drivers/char/amiserial.c	2003-05-26 04:41:41.000000000 -0700
@@ -490,7 +490,7 @@
 	}
 }
 
-static void ser_vbl_int( int irq, void *data, struct pt_regs *regs)
+static irqreturn_t ser_vbl_int( int irq, void *data, struct pt_regs *regs)
 {
         /* vbl is just a periodic interrupt we tie into to update modem status */
 	struct async_struct * info = IRQ_ports;
@@ -500,9 +500,10 @@
 	 */
 	if(info->IER & UART_IER_MSI)
 	  check_modem_status(info);
+	return IRQ_HANDLED;
 }
 
-static void ser_rx_int(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t ser_rx_int(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct async_struct * info;
 
@@ -512,16 +513,17 @@
 
 	info = IRQ_ports;
 	if (!info || !info->tty)
-		return;
+		return IRQ_NONE;
 
 	receive_chars(info);
 	info->last_active = jiffies;
 #ifdef SERIAL_DEBUG_INTR
 	printk("end.\n");
 #endif
+	return IRQ_HANDLED;
 }
 
-static void ser_tx_int(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t ser_tx_int(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct async_struct * info;
 
@@ -532,7 +534,7 @@
 
 	  info = IRQ_ports;
 	  if (!info || !info->tty)
-	    return;
+		return IRQ_NONE;
 
 	  transmit_chars(info);
 	  info->last_active = jiffies;
@@ -540,6 +542,7 @@
 	  printk("end.\n");
 #endif
 	}
+	return IRQ_HANDLED;
 }
 
 /*
diff -urN linux-2.5.69-bk18/drivers/char/ser_a2232.c linux-2.5.69-bk19/drivers/char/ser_a2232.c
--- linux-2.5.69-bk18/drivers/char/ser_a2232.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/char/ser_a2232.c	2003-05-26 04:41:41.000000000 -0700
@@ -116,7 +116,7 @@
 static __inline__ void a2232_receive_char(	struct a2232_port *port,
 						int ch, int err );
 /* The interrupt service routine */
-static void a2232_vbl_inter(int irq, void *data, struct pt_regs *fp);
+static irqreturn_t a2232_vbl_inter(int irq, void *data, struct pt_regs *fp);
 /* Initialize the port structures */
 static void a2232_init_portstructs(void);
 /* Initialize and register TTY drivers. */
@@ -533,7 +533,7 @@
 	tty_flip_buffer_push(tty);
 }
 
-static void a2232_vbl_inter(int irq, void *data, struct pt_regs *fp)
+static irqreturn_t a2232_vbl_inter(int irq, void *data, struct pt_regs *fp)
 {
 #if A2232_IOBUFLEN != 256
 #error "Re-Implement a2232_vbl_inter()!"
@@ -673,6 +673,7 @@
 		} // if events in CD queue
 		
 	} // for every completely initialized A2232 board
+	return IRQ_HANDLED;
 }
 
 static void a2232_init_portstructs(void)
diff -urN linux-2.5.69-bk18/drivers/char/serial167.c linux-2.5.69-bk19/drivers/char/serial167.c
--- linux-2.5.69-bk18/drivers/char/serial167.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/char/serial167.c	2003-05-26 04:41:41.000000000 -0700
@@ -400,7 +400,7 @@
    whenever the card wants its hand held--chars
    received, out buffer empty, modem change, etc.
  */
-static void
+static irqreturn_t
 cd2401_rxerr_interrupt(int irq, void *dev_id, struct pt_regs *fp)
 {
     struct tty_struct *tty;
@@ -418,7 +418,7 @@
     if ((err = base_addr[CyRISR]) & CyTIMEOUT) {
 	/* This is a receive timeout interrupt, ignore it */
 	base_addr[CyREOIR] = CyNOTRANS;
-	return;
+	return IRQ_HANDLED;
     }
 
     /* Read a byte of data if there is any - assume the error
@@ -432,13 +432,13 @@
     /* if there is nowhere to put the data, discard it */
     if(info->tty == 0) {
 	base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
-	return;
+	return IRQ_HANDLED;
     }
     else { /* there is an open port for this data */
 	tty = info->tty;
 	if(err & info->ignore_status_mask){
 	    base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
-	    return;
+	    return IRQ_HANDLED;
 	}
 	if (tty->flip.count < TTY_FLIPBUF_SIZE){
 	    tty->flip.count++;
@@ -488,9 +488,10 @@
     queue_task(&tty->flip.tqueue, &tq_timer);
     /* end of service */
     base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
+    return IRQ_HANDLED;
 } /* cy_rxerr_interrupt */
 
-static void
+static irqreturn_t
 cd2401_modem_interrupt(int irq, void *dev_id, struct pt_regs *fp)
 {
     struct cyclades_port *info;
@@ -543,9 +544,10 @@
 	}
     }
     base_addr[CyMEOIR] = 0;
+    return IRQ_HANDLED;
 } /* cy_modem_interrupt */
 
-static void
+static irqreturn_t
 cd2401_tx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
 {
     struct cyclades_port *info;
@@ -569,7 +571,7 @@
     if( (channel < 0) || (NR_PORTS <= channel) ){
 	base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
 	base_addr[CyTEOIR] = CyNOTRANS;
-	return;
+	return IRQ_HANDLED;
     }
     info->last_active = jiffies;
     if(info->tty == 0){
@@ -578,7 +580,7 @@
 	    cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
         }
 	base_addr[CyTEOIR] = CyNOTRANS;
-	return;
+	return IRQ_HANDLED;
     }
 
     /* load the on-chip space available for outbound data */
@@ -662,9 +664,10 @@
 	cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
     }
     base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS;
+    return IRQ_HANDLED;
 } /* cy_tx_interrupt */
 
-static void
+static irqreturn_t
 cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
 {
     struct tty_struct *tty;
@@ -722,6 +725,7 @@
     }
     /* end of service */
     base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS;
+    return IRQ_HANDLED;
 } /* cy_rx_interrupt */
 
 /*
diff -urN linux-2.5.69-bk18/drivers/char/tty_io.c linux-2.5.69-bk19/drivers/char/tty_io.c
--- linux-2.5.69-bk18/drivers/char/tty_io.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/char/tty_io.c	2003-05-26 04:41:41.000000000 -0700
@@ -132,12 +132,6 @@
 
 extern void disable_early_printk(void);
 
-/*
- * redirect is the pseudo-tty that console output
- * is redirected to if asked by TIOCCONS.
- */
-static struct tty_struct *redirect;
-
 static void initialize_tty_struct(struct tty_struct *tty);
 
 static ssize_t tty_read(struct file *, char *, size_t, loff_t *);
@@ -400,6 +394,8 @@
 	.release	= tty_release,
 };
 
+static spinlock_t redirect_lock = SPIN_LOCK_UNLOCKED;
+static struct file *redirect;
 /*
  * This can be called by the "eventd" kernel thread.  That is process synchronous,
  * but doesn't hold any locks, so we need to make sure we have the appropriate
@@ -409,7 +405,7 @@
 {
 	struct tty_struct *tty = (struct tty_struct *) data;
 	struct file * cons_filp = NULL;
-	struct file *filp;
+	struct file *filp, *f = NULL;
 	struct task_struct *p;
 	struct pid *pid;
 	int    closecount = 0, n;
@@ -419,6 +415,15 @@
 
 	/* inuse_filps is protected by the single kernel lock */
 	lock_kernel();
+
+	spin_lock(&redirect_lock);
+	if (redirect && redirect->private_data == tty) {
+		f = redirect;
+		redirect = NULL;
+	}
+	spin_unlock(&redirect_lock);
+	if (f)
+		fput(f);
 	
 	check_tty_count(tty, "do_tty_hangup");
 	file_list_lock();
@@ -726,39 +731,40 @@
 {
 	int is_console;
 	struct tty_struct * tty;
-	struct inode *inode;
-
-	/* Can't seek (pwrite) on ttys.  */
-	if (ppos != &file->f_pos)
-		return -ESPIPE;
-
+	struct inode *inode = file->f_dentry->d_inode;
 	/*
 	 *      For now, we redirect writes from /dev/console as
 	 *      well as /dev/tty0.
 	 */
-	inode = file->f_dentry->d_inode;
 	is_console = IS_SYSCONS_DEV(inode->i_rdev) ||
 		     IS_CONSOLE_DEV(inode->i_rdev);
 
-	if (is_console && redirect)
-		tty = redirect;
-	else
-		tty = (struct tty_struct *)file->private_data;
+	/* Can't seek (pwrite) on ttys.  */
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+
+	if (is_console) {
+		struct file *p = NULL;
+
+		spin_lock(&redirect_lock);
+		if (redirect) {
+			get_file(redirect);
+			p = redirect;
+		}
+		spin_unlock(&redirect_lock);
+
+		if (p) {
+			ssize_t res = vfs_write(p, buf, count, &p->f_pos);
+			fput(p);
+			return res;
+		}
+	}
+
+	tty = (struct tty_struct *)file->private_data;
 	if (tty_paranoia_check(tty, inode->i_rdev, "tty_write"))
 		return -EIO;
 	if (!tty || !tty->driver->write || (test_bit(TTY_IO_ERROR, &tty->flags)))
 		return -EIO;
-#if 0
-	if (!is_console && L_TOSTOP(tty) && (tty->pgrp > 0) &&
-	    (current->tty == tty) && (tty->pgrp != current->pgrp)) {
-		if (is_orphaned_pgrp(current->pgrp))
-			return -EIO;
-		if (!is_ignored(SIGTTOU)) {
-			(void) kill_pg(current->pgrp, SIGTTOU, 1);
-			return -ERESTARTSYS;
-		}
-	}
-#endif
 	if (!tty->ldisc.write)
 		return -EIO;
 	return do_tty_write(tty->ldisc.write, tty, file,
@@ -1221,7 +1227,7 @@
 	/*
 	 * If _either_ side is closing, make sure there aren't any
 	 * processes that still think tty or o_tty is their controlling
-	 * tty.  Also, clear redirect if it points to either tty.
+	 * tty.
 	 */
 	if (tty_closing || o_tty_closing) {
 		struct task_struct *p;
@@ -1235,9 +1241,6 @@
 			for_each_task_pid(o_tty->session, PIDTYPE_SID, p,l, pid)
 				p->tty = NULL;
 		read_unlock(&tasklist_lock);
-
-		if (redirect == tty || (o_tty && redirect == o_tty))
-			redirect = NULL;
 	}
 
 	/* check whether both sides are closing ... */
@@ -1526,19 +1529,29 @@
 	return 0;
 }
 
-static int tioccons(struct inode *inode,
-	struct tty_struct *tty, struct tty_struct *real_tty)
+static int tioccons(struct inode *inode, struct file *file)
 {
 	if (IS_SYSCONS_DEV(inode->i_rdev) ||
 	    IS_CONSOLE_DEV(inode->i_rdev)) {
+		struct file *f;
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
+		spin_lock(&redirect_lock);
+		f = redirect;
 		redirect = NULL;
+		spin_unlock(&redirect_lock);
+		if (f)
+			fput(f);
 		return 0;
 	}
-	if (redirect)
+	spin_lock(&redirect_lock);
+	if (redirect) {
+		spin_unlock(&redirect_lock);
 		return -EBUSY;
-	redirect = real_tty;
+	}
+	get_file(file);
+	redirect = file;
+	spin_unlock(&redirect_lock);
 	return 0;
 }
 
@@ -1786,7 +1799,7 @@
 		case TIOCSWINSZ:
 			return tiocswinsz(tty, real_tty, (struct winsize *) arg);
 		case TIOCCONS:
-			return tioccons(inode, tty, real_tty);
+			return real_tty!=tty ? -EINVAL : tioccons(inode, file);
 		case FIONBIO:
 			return fionbio(file, (int *) arg);
 		case TIOCEXCL:
@@ -2113,7 +2126,7 @@
 static ssize_t show_dev(struct class_device *class_dev, char *buf)
 {
 	struct tty_dev *tty_dev = to_tty_dev(class_dev);
-	return sprintf(buf, "%04x\n", tty_dev->dev);
+	return sprintf(buf, "%04lx\n", (unsigned long)tty_dev->dev);
 }
 static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
 
@@ -2229,53 +2242,7 @@
 EXPORT_SYMBOL(tty_register_device);
 EXPORT_SYMBOL(tty_unregister_device);
 
-/* that should be handled by register_chrdev_region() */
-static int get_range(struct tty_driver *driver)
-{
-	dev_t from = MKDEV(driver->major, driver->minor_start);
-	dev_t to = from + driver->num;
-	dev_t n, next;
-	int error = 0;
-
-	for (n = from; MAJOR(n) < MAJOR(to); n = next) {
-		next = MKDEV(MAJOR(n)+1, 0);
-		error = register_chrdev_region(MAJOR(n), MINOR(n),
-			       next - n, driver->name, &tty_fops);
-		if (error)
-			goto fail;
-	}
-	if (n != to)
-		error = register_chrdev_region(MAJOR(n), MINOR(n),
-			       to - n, driver->name, &tty_fops);
-	if (!error)
-		return 0;
-fail:
-	to = n;
-	for (n = from; MAJOR(n) < MAJOR(to); n = next) {
-		next = MKDEV(MAJOR(n)+1, 0);
-		unregister_chrdev_region(MAJOR(n), MINOR(n),
-			       next - n, driver->name);
-	}
-	return error;
-}
-
-/* that should be handled by unregister_chrdev_region() */
-static void put_range(struct tty_driver *driver)
-{
-	dev_t from = MKDEV(driver->major, driver->minor_start);
-	dev_t to = from + driver->num;
-	dev_t n, next;
-
-	for (n = from; MAJOR(n) < MAJOR(to); n = next) {
-		next = MKDEV(MAJOR(n)+1, 0);
-		unregister_chrdev_region(MAJOR(n), MINOR(n),
-			       next - n, driver->name);
-	}
-	if (n != to)
-		unregister_chrdev_region(MAJOR(n), MINOR(n),
-			       to - n, driver->name);
-}
-
+static struct kobject tty_kobj = {.name = "tty"};
 /*
  * Called by a tty driver to register itself.
  */
@@ -2283,21 +2250,40 @@
 {
 	int error;
         int i;
+	dev_t dev;
+	char *s;
 
 	if (driver->flags & TTY_DRIVER_INSTALLED)
 		return 0;
 
 	if (!driver->major) {
-		error = register_chrdev_region(0, driver->minor_start,
-				       driver->num, driver->name, &tty_fops);
-		if (error > 0)
-			driver->major = error;
+		error = alloc_chrdev_region(&dev, driver->num,
+						(char*)driver->name);
+		if (!error) {
+			driver->major = MAJOR(dev);
+			driver->minor_start = MINOR(dev);
+		}
 	} else {
-		error = get_range(driver);
+		dev = MKDEV(driver->major, driver->minor_start);
+		error = register_chrdev_region(dev, driver->num,
+						(char*)driver->name);
 	}
 	if (error < 0)
 		return error;
 
+	driver->cdev.kobj.parent = &tty_kobj;
+	strcpy(driver->cdev.kobj.name, driver->name);
+	for (s = strchr(driver->cdev.kobj.name, '/'); s; s = strchr(s, '/'))
+		*s = '!';
+	cdev_init(&driver->cdev, &tty_fops);
+	driver->cdev.owner = driver->owner;
+	error = cdev_add(&driver->cdev, dev, driver->num);
+	if (error) {
+		kobject_del(&driver->cdev.kobj);
+		unregister_chrdev_region(dev, driver->num);
+		return error;
+	}
+
 	if (!driver->put_char)
 		driver->put_char = tty_default_put_char;
 	
@@ -2308,7 +2294,7 @@
 		    tty_register_device(driver, i, NULL);
 	}
 	proc_tty_register_driver(driver);
-	return error;
+	return 0;
 }
 
 /*
@@ -2322,7 +2308,9 @@
 	if (*driver->refcount)
 		return -EBUSY;
 
-	put_range(driver);
+	cdev_unmap(MKDEV(driver->major, driver->minor_start), driver->num);
+	unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
+				driver->num);
 
 	list_del(&driver->tty_drivers);
 
@@ -2346,6 +2334,7 @@
 			tty_unregister_device(driver, i);
 	}
 	proc_tty_unregister_driver(driver);
+	cdev_del(&driver->cdev);
 	return 0;
 }
 
@@ -2392,6 +2381,14 @@
 }
 
 postcore_initcall(tty_class_init);
+ 
+static struct cdev tty_cdev, console_cdev;
+#ifdef CONFIG_UNIX98_PTYS
+static struct cdev ptmx_cdev;
+#endif
+#ifdef CONFIG_VT
+static struct cdev vc0_cdev;
+#endif
 
 /*
  * Ok, now we can initialize the rest of the tty devices and can count
@@ -2399,29 +2396,40 @@
  */
 void __init tty_init(void)
 {
-	if (register_chrdev_region(TTYAUX_MAJOR, 0, 1,
-				   "/dev/tty", &tty_fops) < 0)
+	strcpy(tty_cdev.kobj.name, "dev.tty");
+	cdev_init(&tty_cdev, &tty_fops);
+	if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
+	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
 		panic("Couldn't register /dev/tty driver\n");
 	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)
+	strcpy(console_cdev.kobj.name, "dev.console");
+	cdev_init(&console_cdev, &tty_fops);
+	if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
+	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
 		panic("Couldn't register /dev/console driver\n");
 	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
 	tty_add_class_device ("console", MKDEV(TTYAUX_MAJOR, 1), NULL);
 
+	tty_kobj.kset = tty_cdev.kobj.kset;
+	kobject_register(&tty_kobj);
+
 #ifdef CONFIG_UNIX98_PTYS
-	if (register_chrdev_region(TTYAUX_MAJOR, 2, 1,
-				   "/dev/ptmx", &tty_fops) < 0)
+	strcpy(ptmx_cdev.kobj.name, "dev.ptmx");
+	cdev_init(&ptmx_cdev, &tty_fops);
+	if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
+	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
 		panic("Couldn't register /dev/ptmx driver\n");
 	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)
+	strcpy(vc0_cdev.kobj.name, "dev.vc0");
+	cdev_init(&vc0_cdev, &tty_fops);
+	if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
+	    register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
 		panic("Couldn't register /dev/tty0 driver\n");
 	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);
diff -urN linux-2.5.69-bk18/drivers/char/vme_scc.c linux-2.5.69-bk19/drivers/char/vme_scc.c
--- linux-2.5.69-bk18/drivers/char/vme_scc.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/char/vme_scc.c	2003-05-26 04:41:41.000000000 -0700
@@ -83,10 +83,10 @@
                      unsigned int cmd, unsigned long arg);
 static void scc_throttle(struct tty_struct *tty);
 static void scc_unthrottle(struct tty_struct *tty);
-static void scc_tx_int(int irq, void *data, struct pt_regs *fp);
-static void scc_rx_int(int irq, void *data, struct pt_regs *fp);
-static void scc_stat_int(int irq, void *data, struct pt_regs *fp);
-static void scc_spcond_int(int irq, void *data, struct pt_regs *fp);
+static irqreturn_t scc_tx_int(int irq, void *data, struct pt_regs *fp);
+static irqreturn_t scc_rx_int(int irq, void *data, struct pt_regs *fp);
+static irqreturn_t scc_stat_int(int irq, void *data, struct pt_regs *fp);
+static irqreturn_t scc_spcond_int(int irq, void *data, struct pt_regs *fp);
 static void scc_setsignals(struct scc_port *port, int dtr, int rts);
 static void scc_break_ctl(struct tty_struct *tty, int break_state);
 
@@ -448,7 +448,7 @@
  * Interrupt handlers
  *--------------------------------------------------------------------------*/
 
-static void scc_rx_int(int irq, void *data, struct pt_regs *fp)
+static irqreturn_t scc_rx_int(int irq, void *data, struct pt_regs *fp)
 {
 	unsigned char	ch;
 	struct scc_port *port = data;
@@ -459,7 +459,7 @@
 	if (!tty) {
 		printk(KERN_WARNING "scc_rx_int with NULL tty!\n");
 		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-		return;
+		return IRQ_HANDLED;
 	}
 	if (tty->flip.count < TTY_FLIPBUF_SIZE) {
 		*tty->flip.char_buf_ptr = ch;
@@ -476,16 +476,17 @@
 	if (SCCread(INT_PENDING_REG) &
 	    (port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX)) {
 		scc_spcond_int (irq, data, fp);
-		return;
+		return IRQ_HANDLED;
 	}
 
 	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 
 	tty_flip_buffer_push(tty);
+	return IRQ_HANDLED;
 }
 
 
-static void scc_spcond_int(int irq, void *data, struct pt_regs *fp)
+static irqreturn_t scc_spcond_int(int irq, void *data, struct pt_regs *fp)
 {
 	struct scc_port *port = data;
 	struct tty_struct *tty = port->gs.tty;
@@ -498,7 +499,7 @@
 		printk(KERN_WARNING "scc_spcond_int with NULL tty!\n");
 		SCCwrite(COMMAND_REG, CR_ERROR_RESET);
 		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-		return;
+		return IRQ_HANDLED;
 	}
 	do {
 		stat = SCCread(SPCOND_STATUS_REG);
@@ -532,10 +533,11 @@
 	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 
 	tty_flip_buffer_push(tty);
+	return IRQ_HANDLED;
 }
 
 
-static void scc_tx_int(int irq, void *data, struct pt_regs *fp)
+static irqreturn_t scc_tx_int(int irq, void *data, struct pt_regs *fp)
 {
 	struct scc_port *port = data;
 	SCC_ACCESS_INIT(port);
@@ -545,7 +547,7 @@
 		SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
 		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
 		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-		return;
+		return IRQ_HANDLED;
 	}
 	while ((SCCread_NB(STATUS_REG) & SR_TX_BUF_EMPTY)) {
 		if (port->x_char) {
@@ -577,10 +579,11 @@
 	}
 
 	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+	return IRQ_HANDLED;
 }
 
 
-static void scc_stat_int(int irq, void *data, struct pt_regs *fp)
+static irqreturn_t scc_stat_int(int irq, void *data, struct pt_regs *fp)
 {
 	struct scc_port *port = data;
 	unsigned channel = port->channel;
@@ -612,6 +615,7 @@
 	}
 	SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET);
 	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+	return IRQ_HANDLED;
 }
 
 
diff -urN linux-2.5.69-bk18/drivers/ide/ide-iops.c linux-2.5.69-bk19/drivers/ide/ide-iops.c
--- linux-2.5.69-bk18/drivers/ide/ide-iops.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/drivers/ide/ide-iops.c	2003-05-26 04:41:41.000000000 -0700
@@ -155,7 +155,7 @@
 
 static void ide_outsl (unsigned long port, void *addr, u32 count)
 {
-	return outsl(port, addr, count);
+	outsl(port, addr, count);
 }
 
 void default_hwif_iops (ide_hwif_t *hwif)
@@ -391,7 +391,7 @@
 		insw_swapw(IDE_DATA_REG, buffer, bytecount / 2);
 		return;
 	}
-#endif /* CONFIG_ATARI */
+#endif /* CONFIG_ATARI || CONFIG_Q40 */
 	hwif->ata_input_data(drive, buffer, bytecount / 4);
 	if ((bytecount & 0x03) >= 2)
 		hwif->INSW(IDE_DATA_REG, ((u8 *)buffer)+(bytecount & ~0x03), 1);
@@ -410,7 +410,7 @@
 		outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2);
 		return;
 	}
-#endif /* CONFIG_ATARI */
+#endif /* CONFIG_ATARI || CONFIG_Q40 */
 	hwif->ata_output_data(drive, buffer, bytecount / 4);
 	if ((bytecount & 0x03) >= 2)
 		hwif->OUTSW(IDE_DATA_REG, ((u8*)buffer)+(bytecount & ~0x03), 1);
diff -urN linux-2.5.69-bk18/drivers/ide/ide-probe.c linux-2.5.69-bk19/drivers/ide/ide-probe.c
--- linux-2.5.69-bk18/drivers/ide/ide-probe.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/ide/ide-probe.c	2003-05-26 04:41:41.000000000 -0700
@@ -1226,7 +1226,7 @@
 	return 0;
 }
 
-struct gendisk *ata_probe(dev_t dev, int *part, void *data)
+struct kobject *ata_probe(dev_t dev, int *part, void *data)
 {
 	ide_hwif_t *hwif = data;
 	int unit = *part >> PARTN_BITS;
diff -urN linux-2.5.69-bk18/drivers/ide/legacy/q40ide.c linux-2.5.69-bk19/drivers/ide/legacy/q40ide.c
--- linux-2.5.69-bk18/drivers/ide/legacy/q40ide.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/drivers/ide/legacy/q40ide.c	2003-05-26 04:41:41.000000000 -0700
@@ -31,7 +31,7 @@
 #define PCIDE_BASE5	0x1e0
 #define PCIDE_BASE6	0x160
 
-static const q40ide_ioreg_t pcide_bases[Q40IDE_NUM_HWIFS] = {
+static const unsigned long pcide_bases[Q40IDE_NUM_HWIFS] = {
     PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4  , PCIDE_BASE5,
     PCIDE_BASE6 */
 };
@@ -41,23 +41,21 @@
      *  Offsets from one of the above bases
      */
 
+/* used to do addr translation here but it is easier to do in setup ports */
+/*#define IDE_OFF_B(x)	((unsigned long)Q40_ISA_IO_B((IDE_##x##_OFFSET)))*/
 
-/* HD_DATA was redefined in asm-m68k/ide.h */
-#undef HD_DATA
-#define HD_DATA  0x1f0
-
-
-#define PCIDE_REG(x)	((q40ide_ioreg_t)(HD_##x-PCIDE_BASE1))
+#define IDE_OFF_B(x)	((unsigned long)((IDE_##x##_OFFSET)))
+#define IDE_OFF_W(x)	((unsigned long)((IDE_##x##_OFFSET)))
 
 static const int pcide_offsets[IDE_NR_PORTS] = {
-    PCIDE_REG(DATA), PCIDE_REG(ERROR), PCIDE_REG(NSECTOR), PCIDE_REG(SECTOR),
-    PCIDE_REG(LCYL), PCIDE_REG(HCYL), PCIDE_REG(CURRENT), PCIDE_REG(STATUS),
-    PCIDE_REG(CMD)
+    IDE_OFF_W(DATA), IDE_OFF_B(ERROR), IDE_OFF_B(NSECTOR), IDE_OFF_B(SECTOR),
+    IDE_OFF_B(LCYL), IDE_OFF_B(HCYL), 6 /*IDE_OFF_B(CURRENT)*/, IDE_OFF_B(STATUS),
+    518/*IDE_OFF(CMD)*/
 };
 
-static int q40ide_default_irq(q40ide_ioreg_t base)
+static int q40ide_default_irq(unsigned long base)
 {
-           switch (base) { 
+           switch (base) {
 	            case 0x1f0: return 14;
 		    case 0x170: return 15;
 		    case 0x1e8: return 11;
@@ -67,14 +65,58 @@
 }
 
 
+/*
+ * This is very similar to ide_setup_ports except that addresses
+ * are pretranslated for q40 ISA access
+ */
+void q40_ide_setup_ports ( hw_regs_t *hw,
+			unsigned long base, int *offsets,
+			unsigned long ctrl, unsigned long intr,
+			ide_ack_intr_t *ack_intr,
+/*
+ *			ide_io_ops_t *iops,
+ */
+			int irq)
+{
+	int i;
 
-    /*
-     *  Probe for Q40 IDE interfaces
-     */
+	for (i = 0; i < IDE_NR_PORTS; i++) {
+		/* BIG FAT WARNING: 
+		   assumption: only DATA port is ever used in 16 bit mode */
+		if ( i==0 )
+			hw->io_ports[i] = Q40_ISA_IO_W(base + offsets[i]);
+		else
+			hw->io_ports[i] = Q40_ISA_IO_B(base + offsets[i]);
+	}
+	
+	hw->irq = irq;
+	hw->dma = NO_DMA;
+	hw->ack_intr = ack_intr;
+/*
+ *	hw->iops = iops;
+ */
+}
+
+
+
+/* 
+ * the static array is needed to have the name reported in /proc/ioports,
+ * hwif->name unfortunately isn´t available yet
+ */
+static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
+	"ide0", "ide1"
+};
+
+/*
+ *  Probe for Q40 IDE interfaces
+ */
 
 void q40ide_init(void)
 {
     int i;
+    ide_hwif_t *hwif;
+    int index;
+    const char *name;
 
     if (!MACH_IS_Q40)
       return ;
@@ -82,12 +124,27 @@
     for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
 	hw_regs_t hw;
 
-	ide_setup_ports(&hw,(unsigned long) pcide_bases[i], (int *)pcide_offsets, 
+	name = q40_ide_names[i];
+	if (!request_region(pcide_bases[i], 8, name)) {
+		printk("could not reserve ports %lx-%lx for %s\n",
+		       pcide_bases[i],pcide_bases[i]+8,name);
+		continue;
+	}
+	if (!request_region(pcide_bases[i]+0x206, 1, name)) {
+		printk("could not reserve port %lx for %s\n",
+		       pcide_bases[i]+0x206,name);
+		release_region(pcide_bases[i], 8);
+		continue;
+	}
+	q40_ide_setup_ports(&hw,(unsigned long) pcide_bases[i], (int *)pcide_offsets, 
 			pcide_bases[i]+0x206, 
 			0, NULL,
-//			pcide_iops,
+//			m68kide_iops,
 			q40ide_default_irq(pcide_bases[i]));
-	ide_register_hw(&hw, NULL);
+	index = ide_register_hw(&hw, &hwif);
+	// **FIXME**
+	if (index != -1)
+		hwif->mmio = 2;
     }
 }
 
diff -urN linux-2.5.69-bk18/drivers/ide/pci/hpt366.c linux-2.5.69-bk19/drivers/ide/pci/hpt366.c
--- linux-2.5.69-bk18/drivers/ide/pci/hpt366.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/drivers/ide/pci/hpt366.c	2003-05-26 04:41:41.000000000 -0700
@@ -1105,7 +1105,6 @@
 		    (findev->device == dev->device) &&
 		    ((findev->devfn - dev->devfn) == 1) &&
 		    (PCI_FUNC(findev->devfn) & 1)) {
-			u8 irq = 0, irq2 = 0;
 			if (findev->irq != dev->irq) {
 				/* FIXME: we need a core pci_set_interrupt() */
 				findev->irq = dev->irq;
diff -urN linux-2.5.69-bk18/drivers/ide/ppc/pmac.c linux-2.5.69-bk19/drivers/ide/ppc/pmac.c
--- linux-2.5.69-bk18/drivers/ide/ppc/pmac.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/drivers/ide/ppc/pmac.c	2003-05-26 04:41:41.000000000 -0700
@@ -721,7 +721,7 @@
 		}
 	}
 
-	return NODEV;
+	return 0;
 }
 
 void __init
diff -urN linux-2.5.69-bk18/drivers/input/joystick/amijoy.c linux-2.5.69-bk19/drivers/input/joystick/amijoy.c
--- linux-2.5.69-bk18/drivers/input/joystick/amijoy.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/drivers/input/joystick/amijoy.c	2003-05-26 04:41:41.000000000 -0700
@@ -52,7 +52,7 @@
 
 static char *amijoy_name = "Amiga joystick";
 
-static void amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
 {
 	int i, data = 0, button = 0;
 
@@ -74,6 +74,7 @@
 
 			input_sync(amijoy_dev + i);
 		}
+	return IRQ_HANDLED;
 }
 
 static int amijoy_open(struct input_dev *dev)
diff -urN linux-2.5.69-bk18/drivers/input/keyboard/amikbd.c linux-2.5.69-bk19/drivers/input/keyboard/amikbd.c
--- linux-2.5.69-bk18/drivers/input/keyboard/amikbd.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/drivers/input/keyboard/amikbd.c	2003-05-26 04:41:41.000000000 -0700
@@ -71,7 +71,7 @@
 static char *amikbd_name = "Amiga keyboard";
 static char *amikbd_phys = "amikbd/input0";
 
-static void amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t amikbd_interrupt(int irq, void *dummy, struct pt_regs *fp)
 {
 	unsigned char scancode, down;
 
@@ -93,16 +93,14 @@
 			input_report_key(&amikbd_dev, scancode, 1);
 			input_report_key(&amikbd_dev, scancode, 0);
 			input_sync(&amikbd_dev);
-			return;
+		} else {
+			input_report_key(&amikbd_dev, scancode, down);
+			input_sync(&amikbd_dev);
 		}
+	} else				/* scancodes >= 0x78 are error codes */
+		printk(amikbd_messages[scancode - 0x78]);
 
-		input_report_key(&amikbd_dev, scancode, down);
-		input_sync(&amikbd_dev);
-
-		return;
-	}
-
-	printk(amikbd_messages[scancode - 0x78]);	/* scancodes >= 0x78 are error codes */
+	return IRQ_HANDLED;
 }
 
 static int __init amikbd_init(void)
diff -urN linux-2.5.69-bk18/drivers/input/mouse/amimouse.c linux-2.5.69-bk19/drivers/input/mouse/amimouse.c
--- linux-2.5.69-bk18/drivers/input/mouse/amimouse.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/drivers/input/mouse/amimouse.c	2003-05-26 04:41:41.000000000 -0700
@@ -40,7 +40,7 @@
 static char *amimouse_name = "Amiga mouse";
 static char *amimouse_phys = "amimouse/input0";
 
-static void amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
 {
 	unsigned short joy0dat, potgor;
 	int nx, ny, dx, dy;
@@ -73,6 +73,8 @@
 	input_report_key(&amimouse_dev, BTN_RIGHT,  potgor & 0x0400);
 
 	input_sync(&amimouse_dev);
+
+	return IRQ_HANDLED;
 }
 
 static int amimouse_open(struct input_dev *dev)
diff -urN linux-2.5.69-bk18/drivers/isdn/capi/capifs.c linux-2.5.69-bk19/drivers/isdn/capi/capifs.c
--- linux-2.5.69-bk18/drivers/isdn/capi/capifs.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/drivers/isdn/capi/capifs.c	2003-05-26 04:41:41.000000000 -0700
@@ -141,7 +141,7 @@
 }
 
 static struct super_block *capifs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_single(fs_type, flags, data, capifs_fill_super);
 }
diff -urN linux-2.5.69-bk18/drivers/macintosh/adbhid.c linux-2.5.69-bk19/drivers/macintosh/adbhid.c
--- linux-2.5.69-bk18/drivers/macintosh/adbhid.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/drivers/macintosh/adbhid.c	2003-05-26 04:41:41.000000000 -0700
@@ -42,6 +42,10 @@
 #include <linux/adb.h>
 #include <linux/cuda.h>
 #include <linux/pmu.h>
+
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+
 #ifdef CONFIG_PMAC_BACKLIGHT
 #include <asm/backlight.h>
 #endif
@@ -65,7 +69,7 @@
 	  0, 83,  0, 55,  0, 78,  0, 69,  0,  0,  0, 98, 96,  0, 74,  0,
 	  0,117, 82, 79, 80, 81, 75, 76, 77, 71,  0, 72, 73,183,181,124,
 	 63, 64, 65, 61, 66, 67,191, 87,190, 99,  0, 70,  0, 68,101, 88,
-	  0,119,110,102,104,111, 62,107, 60,109, 59, 54,100, 97,116,116
+	  0,119,110,102,104,111, 62,107, 60,109, 59, 54,100, 97,126,116
 };
 
 struct adbhid {
@@ -84,7 +88,7 @@
 
 static void adbhid_probe(void);
 
-static void adbhid_input_keycode(int, int, int);
+static void adbhid_input_keycode(int, int, int, struct pt_regs *);
 static void leds_done(struct adb_request *);
 
 static void init_trackpad(int id);
@@ -140,7 +144,7 @@
 }
 
 static void
-adbhid_input_keycode(int id, int keycode, int repeat, pt_regs *regs)
+adbhid_input_keycode(int id, int keycode, int repeat, struct pt_regs *regs)
 {
 	int up_flag;
 
@@ -156,6 +160,15 @@
 		return;
 	case 0x3f: /* ignore Powerbook Fn key */
 		return;
+	case 0x7e: /* Power key on PBook 3400 needs remapping */
+		switch(pmac_call_feature(PMAC_FTR_GET_MB_INFO,
+			NULL, PMAC_MB_INFO_MODEL, 0)) {
+		case PMAC_TYPE_COMET:
+		case PMAC_TYPE_HOOPER:
+		case PMAC_TYPE_KANGA:
+			keycode = 0x7f;
+		}
+		break;
 	}
 
 	if (adbhid[id]->keycode[keycode]) {
@@ -343,13 +356,12 @@
 		case 0xa:	/* brightness decrease */
 #ifdef CONFIG_PMAC_BACKLIGHT
 			if (!disable_kernel_backlight) {
-				if (!down || backlight < 0)
-					break;
-				if (backlight > BACKLIGHT_OFF)
-					set_backlight_level(backlight-1);
-				else
-					set_backlight_level(BACKLIGHT_OFF);
-				break;
+				if (down && backlight >= 0) {
+					if (backlight > BACKLIGHT_OFF)
+						set_backlight_level(backlight-1);
+					else
+						set_backlight_level(BACKLIGHT_OFF);
+				}
 			}
 #endif /* CONFIG_PMAC_BACKLIGHT */
 			input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);
@@ -358,13 +370,12 @@
 		case 0x9:	/* brightness increase */
 #ifdef CONFIG_PMAC_BACKLIGHT
 			if (!disable_kernel_backlight) {
-				if (!down || backlight < 0)
-					break;
-				if (backlight < BACKLIGHT_MAX)
-					set_backlight_level(backlight+1);
-				else 
-					set_backlight_level(BACKLIGHT_MAX);
-				break;
+				if (down && backlight >= 0) {
+					if (backlight < BACKLIGHT_MAX)
+						set_backlight_level(backlight+1);
+					else 
+						set_backlight_level(BACKLIGHT_MAX);
+				}
 			}
 #endif /* CONFIG_PMAC_BACKLIGHT */
 			input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSUP, down);
diff -urN linux-2.5.69-bk18/drivers/macintosh/via-macii.c linux-2.5.69-bk19/drivers/macintosh/via-macii.c
--- linux-2.5.69-bk18/drivers/macintosh/via-macii.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/drivers/macintosh/via-macii.c	2003-05-26 04:41:41.000000000 -0700
@@ -77,7 +77,7 @@
 
 static int  macii_init_via(void);
 static void macii_start(void);
-static void macii_interrupt(int irq, void *arg, struct pt_regs *regs);
+static irqreturn_t macii_interrupt(int irq, void *arg, struct pt_regs *regs);
 static void macii_retransmit(int);
 static void macii_queue_poll(void);
 
@@ -151,7 +151,7 @@
 	if (err) return err;
 
 	err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB",
-		    macii_interrupt);
+			  macii_interrupt);
 	if (err) return err;
 
 	macii_state = idle;
@@ -410,7 +410,7 @@
  * Note: As of 21/10/97, the MacII ADB part works including timeout detection
  * and retransmit (Talk to the last active device).
  */
-void macii_interrupt(int irq, void *arg, struct pt_regs *regs)
+static irqreturn_t macii_interrupt(int irq, void *arg, struct pt_regs *regs)
 {
 	int x, adbdir;
 	unsigned long flags;
@@ -423,7 +423,7 @@
 
 	if (driver_running) {
 		local_irq_restore(flags);
-		return;
+		return IRQ_NONE;
 	}
 
 	driver_running = 1;
@@ -649,4 +649,5 @@
 	/* reset mutex and interrupts */
 	driver_running = 0;
 	local_irq_restore(flags);
+	return IRQ_HANDLED;
 }
diff -urN linux-2.5.69-bk18/drivers/macintosh/via-maciisi.c linux-2.5.69-bk19/drivers/macintosh/via-maciisi.c
--- linux-2.5.69-bk18/drivers/macintosh/via-maciisi.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/drivers/macintosh/via-maciisi.c	2003-05-26 04:41:41.000000000 -0700
@@ -84,7 +84,7 @@
 static int maciisi_send_request(struct adb_request* req, int sync);
 static void maciisi_sync(struct adb_request *req);
 static int maciisi_write(struct adb_request* req);
-static void maciisi_interrupt(int irq, void* arg, struct pt_regs* regs);
+static irqreturn_t maciisi_interrupt(int irq, void* arg, struct pt_regs* regs);
 static void maciisi_input(unsigned char *buf, int nb, struct pt_regs *regs);
 static int maciisi_init_via(void);
 static void maciisi_poll(void);
@@ -414,7 +414,7 @@
 /* Shift register interrupt - this is *supposed* to mean that the
    register is either full or empty. In practice, I have no idea what
    it means :( */
-static void
+static irqreturn_t
 maciisi_interrupt(int irq, void* arg, struct pt_regs* regs)
 {
 	int status;
@@ -436,7 +436,7 @@
 		/* Shouldn't happen, we hope */
 		printk(KERN_ERR "maciisi_interrupt: called without interrupt flag set\n");
 		local_irq_restore(flags);
-		return;
+		return IRQ_NONE;
 	}
 
 	/* Clear the interrupt */
@@ -635,6 +635,7 @@
 		printk("maciisi_interrupt: unknown maciisi_state %d?\n", maciisi_state);
 	}
 	local_irq_restore(flags);
+	return IRQ_HANDLED;
 }
 
 static void
diff -urN linux-2.5.69-bk18/drivers/macintosh/via-pmu68k.c linux-2.5.69-bk19/drivers/macintosh/via-pmu68k.c
--- linux-2.5.69-bk18/drivers/macintosh/via-pmu68k.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/drivers/macintosh/via-pmu68k.c	2003-05-26 04:41:41.000000000 -0700
@@ -107,7 +107,7 @@
 static int pmu_probe(void);
 static int pmu_init(void);
 static void pmu_start(void);
-static void pmu_interrupt(int irq, void *arg, struct pt_regs *regs);
+static irqreturn_t pmu_interrupt(int irq, void *arg, struct pt_regs *regs);
 static int pmu_send_request(struct adb_request *req, int sync);
 static int pmu_autopoll(int devs);
 void pmu_poll(void);
@@ -572,7 +572,7 @@
 	local_irq_restore(flags);
 }
 
-static void 
+static irqreturn_t
 pmu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct adb_request *req;
@@ -688,6 +688,7 @@
 	printk("pmu_interrupt: exit state %d acr %02X, b %02X data_index %d/%d adb_int_pending %d\n",
 		pmu_state, (uint) via1[ACR], (uint) via2[B], data_index, data_len, adb_int_pending);
 #endif
+	return IRQ_HANDLED;
 }
 
 static void 
diff -urN linux-2.5.69-bk18/drivers/md/md.c linux-2.5.69-bk19/drivers/md/md.c
--- linux-2.5.69-bk18/drivers/md/md.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/md/md.c	2003-05-26 04:41:41.000000000 -0700
@@ -1438,7 +1438,7 @@
 }
 
 
-static struct gendisk *md_probe(dev_t dev, int *part, void *data)
+static struct kobject *md_probe(dev_t dev, int *part, void *data)
 {
 	static DECLARE_MUTEX(disks_sem);
 	int unit = MINOR(dev);
diff -urN linux-2.5.69-bk18/drivers/media/video/bttv-cards.c linux-2.5.69-bk19/drivers/media/video/bttv-cards.c
--- linux-2.5.69-bk18/drivers/media/video/bttv-cards.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/drivers/media/video/bttv-cards.c	2003-05-26 04:41:41.000000000 -0700
@@ -2671,7 +2671,7 @@
 static int tea5757_read(struct bttv *btv)
 {
 	int value = 0;
-	long timeout;
+	unsigned long timeout;
 	int i;
 	
 	/* better safe than sorry */
diff -urN linux-2.5.69-bk18/drivers/media/video/cpia.c linux-2.5.69-bk19/drivers/media/video/cpia.c
--- linux-2.5.69-bk18/drivers/media/video/cpia.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/media/video/cpia.c	2003-05-26 04:41:41.000000000 -0700
@@ -2427,10 +2427,20 @@
 #define FIRMWARE_VERSION(x,y) (params->version.firmwareVersion == (x) && \
                                params->version.firmwareRevision == (y))
 /* define for compgain calculation */
+#if 0
 #define COMPGAIN(base, curexp, newexp) \
     (u8) ((((float) base - 128.0) * ((float) curexp / (float) newexp)) + 128.5)
 #define EXP_FROM_COMP(basecomp, curcomp, curexp) \
     (u16)((float)curexp * (float)(u8)(curcomp + 128) / (float)(u8)(basecomp - 128))
+#else
+  /* equivalent functions without floating point math */
+#define COMPGAIN(base, curexp, newexp) \
+    (u8)(128 + (((u32)(2*(base-128)*curexp + newexp)) / (2* newexp)) )
+#define EXP_FROM_COMP(basecomp, curcomp, curexp) \
+     (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128)))
+#endif
+
+ 
 	int currentexp = params->exposure.coarseExpLo +
 			 params->exposure.coarseExpHi*256;
 	int startexp;
diff -urN linux-2.5.69-bk18/drivers/media/video/saa7134/saa7134-cards.c linux-2.5.69-bk19/drivers/media/video/saa7134/saa7134-cards.c
--- linux-2.5.69-bk18/drivers/media/video/saa7134/saa7134-cards.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/media/video/saa7134/saa7134-cards.c	2003-05-26 04:41:41.000000000 -0700
@@ -596,16 +596,18 @@
 static void board_flyvideo(struct saa7134_dev *dev)
 {
 	u32 value;
-	int index;
 
 	saa_writel(SAA7134_GPIO_GPMODE0 >> 2,   0);
 	value = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
 #if 0
-	index = (value & 0x1f00) >> 8;
-	printk(KERN_INFO "%s: flyvideo: gpio is 0x%x [model=%s,tuner=%d]\n",
-	       dev->name, value, fly_list[index].model,
-	       fly_list[index].tuner_type);
-	dev->tuner_type = fly_list[index].tuner_type;
+	{
+		int index = (value & 0x1f00) >> 8;
+		printk(KERN_INFO "%s: flyvideo: gpio is 0x%x "
+				"[model=%s,tuner=%d]\n",
+		       dev->name, value, fly_list[index].model,
+		       fly_list[index].tuner_type);
+		dev->tuner_type = fly_list[index].tuner_type;
+	}
 #else
 	printk(KERN_INFO "%s: flyvideo: gpio is 0x%x\n",
 	       dev->name, value);
diff -urN linux-2.5.69-bk18/drivers/mtd/nftlcore.c linux-2.5.69-bk19/drivers/mtd/nftlcore.c
--- linux-2.5.69-bk18/drivers/mtd/nftlcore.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk19/drivers/mtd/nftlcore.c	2003-05-26 04:41:41.000000000 -0700
@@ -862,7 +862,7 @@
 	}
 }
 
-static struct gendisk *nftl_probe(dev_t dev, int *part, void *data)
+static struct kobject *nftl_probe(dev_t dev, int *part, void *data)
 {
 	request_module("docprobe");
 	return NULL;
diff -urN linux-2.5.69-bk18/drivers/net/3c505.c linux-2.5.69-bk19/drivers/net/3c505.c
--- linux-2.5.69-bk18/drivers/net/3c505.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/3c505.c	2003-05-26 04:41:41.000000000 -0700
@@ -312,7 +312,7 @@
 
 	outb_control(orig_hcr, dev);
 	if (!start_receive(dev, &adapter->tx_pcb))
-		printk("%s: start receive command failed \n", dev->name);
+		printk(KERN_ERR "%s: start receive command failed \n", dev->name);
 }
 
 /* Check to make sure that a DMA transfer hasn't timed out.  This should
@@ -324,7 +324,7 @@
 	elp_device *adapter = dev->priv;
 	if (adapter->dmaing && time_after(jiffies, adapter->current_dma.start_time + 10)) {
 		unsigned long flags, f;
-		printk("%s: DMA %s timed out, %d bytes left\n", dev->name, adapter->current_dma.direction ? "download" : "upload", get_dma_residue(dev->dma));
+		printk(KERN_ERR "%s: DMA %s timed out, %d bytes left\n", dev->name, adapter->current_dma.direction ? "download" : "upload", get_dma_residue(dev->dma));
 		spin_lock_irqsave(&adapter->lock, flags);
 		adapter->dmaing = 0;
 		adapter->busy = 0;
@@ -460,7 +460,7 @@
 	}
 
 	if (elp_debug >= 1)
-		printk("%s: timeout waiting for PCB acknowledge (status %02x)\n", dev->name, inb_status(dev->base_addr));
+		printk(KERN_DEBUG "%s: timeout waiting for PCB acknowledge (status %02x)\n", dev->name, inb_status(dev->base_addr));
 
       sti_abort:
 	spin_unlock_irqrestore(&adapter->lock, flags);
@@ -509,7 +509,7 @@
 	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));
 	if (time_after_eq(jiffies, timeout)) {
 		TIMEOUT_MSG(__LINE__);
-		printk("%s: status %02x\n", dev->name, stat);
+		printk(KERN_INFO "%s: status %02x\n", dev->name, stat);
 		return FALSE;
 	}
 	pcb->length = inb_command(dev->base_addr);
@@ -540,7 +540,7 @@
 	/* safety check total length vs data length */
 	if (total_length != (pcb->length + 2)) {
 		if (elp_debug >= 2)
-			printk("%s: mangled PCB received\n", dev->name);
+			printk(KERN_WARNING "%s: mangled PCB received\n", dev->name);
 		set_hsf(dev, HSF_PCB_NAK);
 		return FALSE;
 	}
@@ -549,7 +549,7 @@
 		if (test_and_set_bit(0, (void *) &adapter->busy)) {
 			if (backlog_next(adapter->rx_backlog.in) == adapter->rx_backlog.out) {
 				set_hsf(dev, HSF_PCB_NAK);
-				printk("%s: PCB rejected, transfer in progress and backlog full\n", dev->name);
+				printk(KERN_WARNING "%s: PCB rejected, transfer in progress and backlog full\n", dev->name);
 				pcb->command = 0;
 				return TRUE;
 			} else {
@@ -574,7 +574,7 @@
 	elp_device *adapter = dev->priv;
 
 	if (elp_debug >= 3)
-		printk("%s: restarting receiver\n", dev->name);
+		printk(KERN_DEBUG "%s: restarting receiver\n", dev->name);
 	tx_pcb->command = CMD_RECEIVE_PACKET;
 	tx_pcb->length = sizeof(struct Rcv_pkt);
 	tx_pcb->data.rcv_pkt.buf_seg
@@ -626,7 +626,7 @@
 
 	/* if this happens, we die */
 	if (test_and_set_bit(0, (void *) &adapter->dmaing))
-		printk("%s: rx blocked, DMA in progress, dir %d\n", dev->name, adapter->current_dma.direction);
+		printk(KERN_ERR "%s: rx blocked, DMA in progress, dir %d\n", dev->name, adapter->current_dma.direction);
 
 	skb->dev = dev;
 	adapter->current_dma.direction = 0;
@@ -646,7 +646,7 @@
 	release_dma_lock(flags);
 
 	if (elp_debug >= 3) {
-		printk("%s: rx DMA transfer started\n", dev->name);
+		printk(KERN_DEBUG "%s: rx DMA transfer started\n", dev->name);
 	}
 
 	if (adapter->rx_active)
@@ -682,10 +682,10 @@
 		 */
 		if (inb_status(dev->base_addr) & DONE) {
 			if (!adapter->dmaing) {
-				printk("%s: phantom DMA completed\n", dev->name);
+				printk(KERN_WARNING "%s: phantom DMA completed\n", dev->name);
 			}
 			if (elp_debug >= 3) {
-				printk("%s: %s DMA complete, status %02x\n", dev->name, adapter->current_dma.direction ? "tx" : "rx", inb_status(dev->base_addr));
+				printk(KERN_DEBUG "%s: %s DMA complete, status %02x\n", dev->name, adapter->current_dma.direction ? "tx" : "rx", inb_status(dev->base_addr));
 			}
 
 			outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR), dev);
@@ -709,7 +709,7 @@
 				int t = adapter->rx_backlog.length[adapter->rx_backlog.out];
 				adapter->rx_backlog.out = backlog_next(adapter->rx_backlog.out);
 				if (elp_debug >= 2)
-					printk("%s: receiving backlogged packet (%d)\n", dev->name, t);
+					printk(KERN_DEBUG "%s: receiving backlogged packet (%d)\n", dev->name, t);
 				receive_packet(dev, t);
 			} else {
 				adapter->busy = 0;
@@ -743,18 +743,18 @@
 						printk(KERN_ERR "%s: interrupt - packet not received correctly\n", dev->name);
 					} else {
 						if (elp_debug >= 3) {
-							printk("%s: interrupt - packet received of length %i (%i)\n", dev->name, len, dlen);
+							printk(KERN_DEBUG "%s: interrupt - packet received of length %i (%i)\n", dev->name, len, dlen);
 						}
 						if (adapter->irx_pcb.command == 0xff) {
 							if (elp_debug >= 2)
-								printk("%s: adding packet to backlog (len = %d)\n", dev->name, dlen);
+								printk(KERN_DEBUG "%s: adding packet to backlog (len = %d)\n", dev->name, dlen);
 							adapter->rx_backlog.length[adapter->rx_backlog.in] = dlen;
 							adapter->rx_backlog.in = backlog_next(adapter->rx_backlog.in);
 						} else {
 							receive_packet(dev, dlen);
 						}
 						if (elp_debug >= 3)
-							printk("%s: packet received\n", dev->name);
+							printk(KERN_DEBUG "%s: packet received\n", dev->name);
 					}
 					break;
 
@@ -764,7 +764,7 @@
 				case CMD_CONFIGURE_82586_RESPONSE:
 					adapter->got[CMD_CONFIGURE_82586] = 1;
 					if (elp_debug >= 3)
-						printk("%s: interrupt - configure response received\n", dev->name);
+						printk(KERN_DEBUG "%s: interrupt - configure response received\n", dev->name);
 					break;
 
 					/*
@@ -773,7 +773,7 @@
 				case CMD_CONFIGURE_ADAPTER_RESPONSE:
 					adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 1;
 					if (elp_debug >= 3)
-						printk("%s: Adapter memory configuration %s.\n", dev->name,
+						printk(KERN_DEBUG "%s: Adapter memory configuration %s.\n", dev->name,
 						       adapter->irx_pcb.data.failed ? "failed" : "succeeded");
 					break;
 
@@ -783,7 +783,7 @@
 				case CMD_LOAD_MULTICAST_RESPONSE:
 					adapter->got[CMD_LOAD_MULTICAST_LIST] = 1;
 					if (elp_debug >= 3)
-						printk("%s: Multicast address list loading %s.\n", dev->name,
+						printk(KERN_DEBUG "%s: Multicast address list loading %s.\n", dev->name,
 						       adapter->irx_pcb.data.failed ? "failed" : "succeeded");
 					break;
 
@@ -793,7 +793,7 @@
 				case CMD_SET_ADDRESS_RESPONSE:
 					adapter->got[CMD_SET_STATION_ADDRESS] = 1;
 					if (elp_debug >= 3)
-						printk("%s: Ethernet address setting %s.\n", dev->name,
+						printk(KERN_DEBUG "%s: Ethernet address setting %s.\n", dev->name,
 						       adapter->irx_pcb.data.failed ? "failed" : "succeeded");
 					break;
 
@@ -810,7 +810,7 @@
 					adapter->stats.rx_over_errors += adapter->irx_pcb.data.netstat.err_res;
 					adapter->got[CMD_NETWORK_STATISTICS] = 1;
 					if (elp_debug >= 3)
-						printk("%s: interrupt - statistics response received\n", dev->name);
+						printk(KERN_DEBUG "%s: interrupt - statistics response received\n", dev->name);
 					break;
 
 					/*
@@ -818,7 +818,7 @@
 					 */
 				case CMD_TRANSMIT_PACKET_COMPLETE:
 					if (elp_debug >= 3)
-						printk("%s: interrupt - packet sent\n", dev->name);
+						printk(KERN_DEBUG "%s: interrupt - packet sent\n", dev->name);
 					if (!netif_running(dev))
 						break;
 					switch (adapter->irx_pcb.data.xmit_resp.c_stat) {
@@ -842,7 +842,7 @@
 					break;
 				}
 			} else {
-				printk("%s: failed to read PCB on interrupt\n", dev->name);
+				printk(KERN_WARNING "%s: failed to read PCB on interrupt\n", dev->name);
 				adapter_reset(dev);
 			}
 		}
@@ -873,7 +873,7 @@
 	adapter = dev->priv;
 
 	if (elp_debug >= 3)
-		printk("%s: request to open device\n", dev->name);
+		printk(KERN_DEBUG "%s: request to open device\n", dev->name);
 
 	/*
 	 * make sure we actually found the device
@@ -946,7 +946,7 @@
 	adapter->tx_pcb.length = sizeof(struct Memconf);
 	adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 0;
 	if (!send_pcb(dev, &adapter->tx_pcb))
-		printk("%s: couldn't send memory configuration command\n", dev->name);
+		printk(KERN_ERR "%s: couldn't send memory configuration command\n", dev->name);
 	else {
 		unsigned long timeout = jiffies + TIMEOUT;
 		while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && time_before(jiffies, timeout));
@@ -959,13 +959,13 @@
 	 * configure adapter to receive broadcast messages and wait for response
 	 */
 	if (elp_debug >= 3)
-		printk("%s: sending 82586 configure command\n", dev->name);
+		printk(KERN_DEBUG "%s: sending 82586 configure command\n", dev->name);
 	adapter->tx_pcb.command = CMD_CONFIGURE_82586;
 	adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD;
 	adapter->tx_pcb.length = 2;
 	adapter->got[CMD_CONFIGURE_82586] = 0;
 	if (!send_pcb(dev, &adapter->tx_pcb))
-		printk("%s: couldn't send 82586 configure command\n", dev->name);
+		printk(KERN_ERR "%s: couldn't send 82586 configure command\n", dev->name);
 	else {
 		unsigned long timeout = jiffies + TIMEOUT;
 		while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));
@@ -981,7 +981,7 @@
 	 */
 	prime_rx(dev);
 	if (elp_debug >= 3)
-		printk("%s: %d receive PCBs active\n", dev->name, adapter->rx_active);
+		printk(KERN_DEBUG "%s: %d receive PCBs active\n", dev->name, adapter->rx_active);
 
 	/*
 	 * device is now officially open!
@@ -1011,7 +1011,7 @@
 
 	if (test_and_set_bit(0, (void *) &adapter->busy)) {
 		if (elp_debug >= 2)
-			printk("%s: transmit blocked\n", dev->name);
+			printk(KERN_DEBUG "%s: transmit blocked\n", dev->name);
 		return FALSE;
 	}
 
@@ -1033,7 +1033,7 @@
 	}
 	/* if this happens, we die */
 	if (test_and_set_bit(0, (void *) &adapter->dmaing))
-		printk("%s: tx: DMA %d in progress\n", dev->name, adapter->current_dma.direction);
+		printk(KERN_DEBUG "%s: tx: DMA %d in progress\n", dev->name, adapter->current_dma.direction);
 
 	adapter->current_dma.direction = 1;
 	adapter->current_dma.start_time = jiffies;
@@ -1059,7 +1059,7 @@
 	release_dma_lock(flags);
 	
 	if (elp_debug >= 3)
-		printk("%s: DMA transfer started\n", dev->name);
+		printk(KERN_DEBUG "%s: DMA transfer started\n", dev->name);
 
 	return TRUE;
 }
@@ -1076,7 +1076,7 @@
 	stat = inb_status(dev->base_addr);
 	printk(KERN_WARNING "%s: transmit timed out, lost %s?\n", dev->name, (stat & ACRF) ? "interrupt" : "command");
 	if (elp_debug >= 1)
-		printk("%s: status %#02x\n", dev->name, stat);
+		printk(KERN_DEBUG "%s: status %#02x\n", dev->name, stat);
 	dev->trans_start = jiffies;
 	adapter->stats.tx_dropped++;
 	netif_wake_queue(dev);
@@ -1098,7 +1098,7 @@
 	check_3c505_dma(dev);
 
 	if (elp_debug >= 3)
-		printk("%s: request to send packet of length %d\n", dev->name, (int) skb->len);
+		printk(KERN_DEBUG "%s: request to send packet of length %d\n", dev->name, (int) skb->len);
 
 	netif_stop_queue(dev);
 	
@@ -1107,13 +1107,13 @@
 	 */
 	if (!send_packet(dev, skb)) {
 		if (elp_debug >= 2) {
-			printk("%s: failed to transmit packet\n", dev->name);
+			printk(KERN_DEBUG "%s: failed to transmit packet\n", dev->name);
 		}
 		spin_unlock_irqrestore(&adapter->lock, flags);
 		return 1;
 	}
 	if (elp_debug >= 3)
-		printk("%s: packet of length %d sent\n", dev->name, (int) skb->len);
+		printk(KERN_DEBUG "%s: packet of length %d sent\n", dev->name, (int) skb->len);
 
 	/*
 	 * start the transmit timeout
@@ -1137,7 +1137,7 @@
 	elp_device *adapter = (elp_device *) dev->priv;
 
 	if (elp_debug >= 3)
-		printk("%s: request for stats\n", dev->name);
+		printk(KERN_DEBUG "%s: request for stats\n", dev->name);
 
 	/* If the device is closed, just return the latest stats we have,
 	   - we cannot ask from the adapter without interrupts */
@@ -1149,7 +1149,7 @@
 	adapter->tx_pcb.length = 0;
 	adapter->got[CMD_NETWORK_STATISTICS] = 0;
 	if (!send_pcb(dev, &adapter->tx_pcb))
-		printk("%s: couldn't send get statistics command\n", dev->name);
+		printk(KERN_ERR "%s: couldn't send get statistics command\n", dev->name);
 	else {
 		unsigned long timeout = jiffies + TIMEOUT;
 		while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && time_before(jiffies, timeout));
@@ -1257,7 +1257,7 @@
 	adapter = dev->priv;
 
 	if (elp_debug >= 3)
-		printk("%s: request to close device\n", dev->name);
+		printk(KERN_DEBUG "%s: request to close device\n", dev->name);
 
 	netif_stop_queue(dev);
 
@@ -1301,7 +1301,7 @@
 	unsigned long flags;
 
 	if (elp_debug >= 3)
-		printk("%s: request to set multicast list\n", dev->name);
+		printk(KERN_DEBUG "%s: request to set multicast list\n", dev->name);
 
 	spin_lock_irqsave(&adapter->lock, flags);
 	
@@ -1316,7 +1316,7 @@
 		}
 		adapter->got[CMD_LOAD_MULTICAST_LIST] = 0;
 		if (!send_pcb(dev, &adapter->tx_pcb))
-			printk("%s: couldn't send set_multicast command\n", dev->name);
+			printk(KERN_ERR "%s: couldn't send set_multicast command\n", dev->name);
 		else {
 			unsigned long timeout = jiffies + TIMEOUT;
 			while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && time_before(jiffies, timeout));
@@ -1335,14 +1335,14 @@
 	 * and wait for response
 	 */
 	if (elp_debug >= 3)
-		printk("%s: sending 82586 configure command\n", dev->name);
+		printk(KERN_DEBUG "%s: sending 82586 configure command\n", dev->name);
 	adapter->tx_pcb.command = CMD_CONFIGURE_82586;
 	adapter->tx_pcb.length = 2;
 	adapter->got[CMD_CONFIGURE_82586] = 0;
 	if (!send_pcb(dev, &adapter->tx_pcb))
 	{
 		spin_unlock_irqrestore(&adapter->lock, flags);
-		printk("%s: couldn't send 82586 configure command\n", dev->name);
+		printk(KERN_ERR "%s: couldn't send 82586 configure command\n", dev->name);
 	}
 	else {
 		unsigned long timeout = jiffies + TIMEOUT;
@@ -1524,9 +1524,9 @@
 	 */
 	adapter = (elp_device *) (dev->priv = kmalloc(sizeof(elp_device), GFP_KERNEL));
 	if (adapter == NULL) {
-		printk("%s: out of memory\n", dev->name);
+		printk(KERN_ERR "%s: out of memory\n", dev->name);
 		return -ENODEV;
-        }
+	}
 
 	adapter->send_pcb_semaphore = 0;
 
@@ -1549,7 +1549,7 @@
 			/* Nope, it's ignoring the command register.  This means that
 			 * either it's still booting up, or it's died.
 			 */
-			printk("%s: command register wouldn't drain, ", dev->name);
+			printk(KERN_ERR "%s: command register wouldn't drain, ", dev->name);
 			if ((inb_status(dev->base_addr) & 7) == 3) {
 				/* If the adapter status is 3, it *could* still be booting.
 				 * Give it the benefit of the doubt for 10 seconds.
@@ -1558,7 +1558,7 @@
 				timeout = jiffies + 10*HZ;
 				while (time_before(jiffies, timeout) && (inb_status(dev->base_addr) & 7));
 				if (inb_status(dev->base_addr) & 7) {
-					printk("%s: 3c505 failed to start\n", dev->name);
+					printk(KERN_ERR "%s: 3c505 failed to start\n", dev->name);
 				} else {
 					okay = 1;  /* It started */
 				}
@@ -1579,18 +1579,18 @@
 			adapter->tx_pcb.length = 0;
 			cookie = probe_irq_on();
 			if (!send_pcb(dev, &adapter->tx_pcb)) {
-				printk("%s: could not send first PCB\n", dev->name);
+				printk(KERN_ERR "%s: could not send first PCB\n", dev->name);
 				probe_irq_off(cookie);
 				continue;
 			}
 			if (!receive_pcb(dev, &adapter->rx_pcb)) {
-				printk("%s: could not read first PCB\n", dev->name);
+				printk(KERN_ERR "%s: could not read first PCB\n", dev->name);
 				probe_irq_off(cookie);
 				continue;
 			}
 			if ((adapter->rx_pcb.command != CMD_ADDRESS_RESPONSE) ||
 			    (adapter->rx_pcb.length != 6)) {
-				printk("%s: first PCB wrong (%d, %d)\n", dev->name, adapter->rx_pcb.command, adapter->rx_pcb.length);
+				printk(KERN_ERR "%s: first PCB wrong (%d, %d)\n", dev->name, adapter->rx_pcb.command, adapter->rx_pcb.length);
 				probe_irq_off(cookie);
 				continue;
 			}
@@ -1603,7 +1603,7 @@
 		outb_control(adapter->hcr_val | FLSH | ATTN, dev);
 		outb_control(adapter->hcr_val & ~(FLSH | ATTN), dev);
 	}
-	printk("%s: failed to initialise 3c505\n", dev->name);
+	printk(KERN_ERR "%s: failed to initialise 3c505\n", dev->name);
 	release_region(dev->base_addr, ELP_IO_EXTENT);
 	return -ENODEV;
 
@@ -1611,21 +1611,21 @@
 	if (dev->irq) {		/* Is there a preset IRQ? */
 		int rpt = probe_irq_off(cookie);
 		if (dev->irq != rpt) {
-			printk("%s: warning, irq %d configured but %d detected\n", dev->name, dev->irq, rpt);
+			printk(KERN_WARNING "%s: warning, irq %d configured but %d detected\n", dev->name, dev->irq, rpt);
 		}
 		/* if dev->irq == probe_irq_off(cookie), all is well */
 	} else		       /* No preset IRQ; just use what we can detect */
 		dev->irq = probe_irq_off(cookie);
 	switch (dev->irq) {    /* Legal, sane? */
 	case 0:
-		printk("%s: IRQ probe failed: check 3c505 jumpers.\n",
+		printk(KERN_ERR "%s: IRQ probe failed: check 3c505 jumpers.\n",
 		       dev->name);
 		return -ENODEV;
 	case 1:
 	case 6:
 	case 8:
 	case 13:
-		printk("%s: Impossible IRQ %d reported by probe_irq_off().\n",
+		printk(KERN_ERR "%s: Impossible IRQ %d reported by probe_irq_off().\n",
 		       dev->name, dev->irq);
 		return -ENODEV;
 	}
@@ -1655,7 +1655,7 @@
 	/*
 	 * print remainder of startup message
 	 */
-	printk("%s: 3c505 at %#lx, irq %d, dma %d, ",
+	printk(KERN_INFO "%s: 3c505 at %#lx, irq %d, dma %d, ",
 	       dev->name, dev->base_addr, dev->irq, dev->dma);
 	printk("addr %02x:%02x:%02x:%02x:%02x:%02x, ",
 	       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
@@ -1690,10 +1690,10 @@
 	    !receive_pcb(dev, &adapter->rx_pcb) ||
 	    (adapter->rx_pcb.command != CMD_CONFIGURE_ADAPTER_RESPONSE) ||
 	    (adapter->rx_pcb.length != 2)) {
-		printk("%s: could not configure adapter memory\n", dev->name);
+		printk(KERN_ERR "%s: could not configure adapter memory\n", dev->name);
 	}
 	if (adapter->rx_pcb.data.configure) {
-		printk("%s: adapter configuration failed\n", dev->name);
+		printk(KERN_ERR "%s: adapter configuration failed\n", dev->name);
 	}
 
 	/*
diff -urN linux-2.5.69-bk18/drivers/net/82596.c linux-2.5.69-bk19/drivers/net/82596.c
--- linux-2.5.69-bk18/drivers/net/82596.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/82596.c	2003-05-26 04:41:42.000000000 -0700
@@ -501,7 +501,7 @@
 
 
 #if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
-static void i596_error(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t i596_error(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
 #ifdef ENABLE_MVME16x_NET
@@ -522,6 +522,7 @@
 #endif
 	printk(KERN_ERR "%s: Error interrupt\n", dev->name);
 	i596_display_data(dev);
+	return IRQ_HANDLED;
 }
 #endif
 
@@ -1004,13 +1005,13 @@
 
 	DEB(DEB_OPEN,printk(KERN_DEBUG "%s: i596_open() irq %d.\n", dev->name, dev->irq));
 
-	if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) {
+	if (request_irq(dev->irq, i596_interrupt, 0, "i82596", dev)) {
 		printk(KERN_ERR "%s: IRQ %d not free\n", dev->name, dev->irq);
 		return -EAGAIN;
 	}
 #ifdef ENABLE_MVME16x_NET
 	if (MACH_IS_MVME16x) {
-		if (request_irq(0x56, &i596_error, 0, "i82596_error", dev))
+		if (request_irq(0x56, i596_error, 0, "i82596_error", dev))
 			return -EAGAIN;
 	}
 #endif
diff -urN linux-2.5.69-bk18/drivers/net/Kconfig linux-2.5.69-bk19/drivers/net/Kconfig
--- linux-2.5.69-bk18/drivers/net/Kconfig	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/Kconfig	2003-05-26 04:41:42.000000000 -0700
@@ -1870,7 +1870,7 @@
 
 config FEC
 	bool "FEC ethernet controller (of ColdFire 5272)"
-	depends on M5272
+	depends on M5272 || M5282
 	help
 	  Say Y here if you want to use the built-in 10/100 Fast ethernet
 	  controller on the Motorola ColdFire 5272 processor.
diff -urN linux-2.5.69-bk18/drivers/net/Makefile linux-2.5.69-bk19/drivers/net/Makefile
--- linux-2.5.69-bk18/drivers/net/Makefile	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/Makefile	2003-05-26 04:41:42.000000000 -0700
@@ -11,6 +11,7 @@
 obj-$(CONFIG_E100) += e100/
 obj-$(CONFIG_E1000) += e1000/
 obj-$(CONFIG_IXGB) += ixgb/
+obj-$(CONFIG_BONDING) += bonding/
 
 #
 # link order important here
@@ -108,7 +109,6 @@
 endif
 
 obj-$(CONFIG_DUMMY) += dummy.o
-obj-$(CONFIG_BONDING) += bonding.o
 obj-$(CONFIG_DE600) += de600.o
 obj-$(CONFIG_DE620) += de620.o
 obj-$(CONFIG_AT1500) += lance.o
diff -urN linux-2.5.69-bk18/drivers/net/apne.c linux-2.5.69-bk19/drivers/net/apne.c
--- linux-2.5.69-bk18/drivers/net/apne.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/apne.c	2003-05-26 04:41:42.000000000 -0700
@@ -85,7 +85,7 @@
 								struct sk_buff *skb, int ring_offset);
 static void apne_block_output(struct net_device *dev, const int count,
 							const unsigned char *buf, const int start_page);
-static void apne_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t apne_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
 static int init_pcmcia(void);
 
@@ -511,18 +511,18 @@
     return;
 }
 
-static void apne_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t apne_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
     unsigned char pcmcia_intreq;
 
     if (!(gayle.inten & GAYLE_IRQ_IRQ))
-        return;
+        return IRQ_NONE;
 
     pcmcia_intreq = pcmcia_get_intreq();
 
     if (!(pcmcia_intreq & GAYLE_IRQ_IRQ)) {
         pcmcia_ack_int(pcmcia_intreq);
-        return;
+        return IRQ_NONE;
     }
     if (ei_debug > 3)
         printk("pcmcia intreq = %x\n", pcmcia_intreq);
@@ -530,6 +530,7 @@
     ei_interrupt(irq, dev_id, regs);
     pcmcia_ack_int(pcmcia_get_intreq());
     pcmcia_enable_irq();
+    return IRQ_HANDLED;
 }
 
 #ifdef MODULE
diff -urN linux-2.5.69-bk18/drivers/net/arcnet/arcnet.c linux-2.5.69-bk19/drivers/net/arcnet/arcnet.c
--- linux-2.5.69-bk18/drivers/net/arcnet/arcnet.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/arcnet/arcnet.c	2003-05-26 04:41:42.000000000 -0700
@@ -671,7 +671,7 @@
  * interrupts. Establish which device needs attention, and call the correct
  * chipset interrupt handler.
  */
-void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
 	struct arcnet_local *lp;
@@ -696,7 +696,7 @@
 			ACOMMAND(CFLAGScmd | RESETclear);
 		AINTMASK(0);
 		spin_unlock(&arcnet_lock);
-		return;
+		return IRQ_HANDLED;
 	}
 
 	BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",
@@ -864,6 +864,7 @@
 	AINTMASK(lp->intmask);
 	
 	spin_unlock(&arcnet_lock);
+	return IRQ_RETVAL(didsomething);
 }
 
 
diff -urN linux-2.5.69-bk18/drivers/net/atari_bionet.c linux-2.5.69-bk19/drivers/net/atari_bionet.c
--- linux-2.5.69-bk18/drivers/net/atari_bionet.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/atari_bionet.c	2003-05-26 04:41:42.000000000 -0700
@@ -221,9 +221,9 @@
 	return c;
 }
 
-static void
+static irqreturn_t
 bionet_intr(int irq, void *data, struct pt_regs *fp) {
-	return;
+	return IRQ_HANDLED;
 }
 
 
diff -urN linux-2.5.69-bk18/drivers/net/atari_pamsnet.c linux-2.5.69-bk19/drivers/net/atari_pamsnet.c
--- linux-2.5.69-bk18/drivers/net/atari_pamsnet.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/atari_pamsnet.c	2003-05-26 04:41:42.000000000 -0700
@@ -167,7 +167,7 @@
 static struct net_device_stats *net_get_stats(struct net_device *dev);
 static void pamsnet_tick(unsigned long);
 
-static void pamsnet_intr(int irq, void *data, struct pt_regs *fp);
+static irqreturn_t pamsnet_intr(int irq, void *data, struct pt_regs *fp);
 
 static struct timer_list pamsnet_timer = TIMER_INITIALIZER(amsnet_tick, 0, 0);
 
@@ -494,13 +494,13 @@
 	return (ret);
 }
 
-static void
+static irqreturn_t
 pamsnet_intr(irq, data, fp)
 	int irq;
 	void *data;
 	struct pt_regs *fp;
 {
-	return;
+	return IRQ_HANDLED;
 }
 
 /* receivepkt() loads a packet to a given buffer and returns its length */
diff -urN linux-2.5.69-bk18/drivers/net/au1000_eth.c linux-2.5.69-bk19/drivers/net/au1000_eth.c
--- linux-2.5.69-bk18/drivers/net/au1000_eth.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/au1000_eth.c	2003-05-26 04:41:42.000000000 -0700
@@ -675,37 +675,24 @@
 	char *pmac, *argptr;
 	char ethaddr[6];
 
-	if (!request_region(ioaddr, MAC_IOSIZE, "Au1000 ENET")) {
+	if (!request_region(ioaddr, MAC_IOSIZE, "Au1000 ENET"))
 		 return -ENODEV;
-	}
 
 	if (version_printed++ == 0) printk(version);
 
+	if (!dev)
+		dev = init_etherdev(NULL, sizeof(struct au1000_private));
+
 	if (!dev) {
-		dev = init_etherdev(0, sizeof(struct au1000_private));
-	}
-	if (!dev) {
-		 printk (KERN_ERR "au1000 eth: init_etherdev failed\n");  
-		 return -ENODEV;
+		printk (KERN_ERR "au1000 eth: init_etherdev failed\n");  
+		release_region(ioaddr, MAC_IOSIZE);
+		return -ENODEV;
 	}
 
 	printk("%s: Au1xxx ethernet found at 0x%lx, irq %d\n", 
 			dev->name, ioaddr, irq);
 
-	/* Initialize our private structure */
-	if (dev->priv == NULL) {
-		aup = (struct au1000_private *) 
-			kmalloc(sizeof(*aup), GFP_KERNEL);
-		if (aup == NULL) {
-			retval = -ENOMEM;
-			goto free_region;
-		}
-		dev->priv = aup;
-	}
-
 	aup = dev->priv;
-	memset(aup, 0, sizeof(*aup));
-
 
 	/* Allocate the data buffers */
 	aup->vaddr = (u32)dma_alloc(MAX_BUF_SIZE * 
@@ -834,8 +821,6 @@
 	if (aup->vaddr) 
 		dma_free((void *)aup->vaddr, 
 				MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS));
-	if (dev->priv != NULL)
-		kfree(dev->priv);
 	printk(KERN_ERR "%s: au1000_probe1 failed.  Returns %d\n",
 	       dev->name, retval);
 	kfree(dev);
@@ -1003,15 +988,15 @@
 	spin_lock_irqsave(&aup->lock, flags);
 	
 	/* stop the device */
-	if (netif_device_present(dev)) {
+	if (netif_device_present(dev))
 		netif_stop_queue(dev);
-	}
 
 	/* disable the interrupt */
 	free_irq(dev->irq, dev);
 	spin_unlock_irqrestore(&aup->lock, flags);
 
 	reset_mac(dev);
+	kfree(dev);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
diff -urN linux-2.5.69-bk18/drivers/net/bmac.c linux-2.5.69-bk19/drivers/net/bmac.c
--- linux-2.5.69-bk18/drivers/net/bmac.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/bmac.c	2003-05-26 04:41:42.000000000 -0700
@@ -1407,7 +1407,6 @@
 	skb_queue_head_init(bp->queue);
 
 	init_timer(&bp->tx_timeout);
-	/*     bp->timeout_active = 0; */
 
 	ret = request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev);
 	if (ret) {
diff -urN linux-2.5.69-bk18/drivers/net/bonding/Makefile linux-2.5.69-bk19/drivers/net/bonding/Makefile
--- linux-2.5.69-bk18/drivers/net/bonding/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/drivers/net/bonding/Makefile	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,8 @@
+#
+# Makefile for the Ethernet Bonding driver
+#
+
+obj-$(CONFIG_BONDING) += bonding.o
+
+bonding-objs := bond_main.o bond_3ad.o bond_alb.o
+
diff -urN linux-2.5.69-bk18/drivers/net/bonding/bond_3ad.c linux-2.5.69-bk19/drivers/net/bonding/bond_3ad.c
--- linux-2.5.69-bk18/drivers/net/bonding/bond_3ad.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/drivers/net/bonding/bond_3ad.c	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,2476 @@
+/*
+ * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ *
+ * Changes:
+ *
+ * 2003/05/01 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
+ *		Amir Noam <amir.noam at intel dot com>
+ *	- Added support for lacp_rate module param.
+ *
+ * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Based on discussion on mailing list, changed locking scheme
+ *	  to use lock/unlock or lock_bh/unlock_bh appropriately instead
+ *	  of lock_irqsave/unlock_irqrestore. The new scheme helps exposing
+ *	  hidden bugs and solves system hangs that occurred due to the fact
+ *	  that holding lock_irqsave doesn't prevent softirqs from running.
+ *	  This also increases total throughput since interrupts are not
+ *	  blocked on each transmitted packets or monitor timeout.
+ *
+ * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Renamed bond_3ad_link_status_changed() to
+ *	  bond_3ad_handle_link_change() for compatibility with TLB.
+ */
+
+#include <linux/skbuff.h>
+#include <linux/if_ether.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+#include <linux/ethtool.h>
+#include <linux/if_bonding.h>
+#include "bonding.h"
+#include "bond_3ad.h"
+
+// General definitions
+#define AD_SHORT_TIMEOUT           1
+#define AD_LONG_TIMEOUT            0
+#define AD_STANDBY                 0x2
+#define AD_MAX_TX_IN_SECOND        3
+#define AD_COLLECTOR_MAX_DELAY     0
+
+// Timer definitions(43.4.4 in the 802.3ad standard)
+#define AD_FAST_PERIODIC_TIME      1
+#define AD_SLOW_PERIODIC_TIME      30
+#define AD_SHORT_TIMEOUT_TIME      (3*AD_FAST_PERIODIC_TIME)
+#define AD_LONG_TIMEOUT_TIME       (3*AD_SLOW_PERIODIC_TIME)
+#define AD_CHURN_DETECTION_TIME    60
+#define AD_AGGREGATE_WAIT_TIME     2
+
+// Port state definitions(43.4.2.2 in the 802.3ad standard)
+#define AD_STATE_LACP_ACTIVITY   0x1
+#define AD_STATE_LACP_TIMEOUT    0x2
+#define AD_STATE_AGGREGATION     0x4
+#define AD_STATE_SYNCHRONIZATION 0x8
+#define AD_STATE_COLLECTING      0x10
+#define AD_STATE_DISTRIBUTING    0x20
+#define AD_STATE_DEFAULTED       0x40
+#define AD_STATE_EXPIRED         0x80
+
+// Port Variables definitions used by the State Machines(43.4.7 in the 802.3ad standard)
+#define AD_PORT_BEGIN           0x1
+#define AD_PORT_LACP_ENABLED    0x2
+#define AD_PORT_ACTOR_CHURN     0x4
+#define AD_PORT_PARTNER_CHURN   0x8
+#define AD_PORT_READY           0x10
+#define AD_PORT_READY_N         0x20
+#define AD_PORT_MATCHED         0x40
+#define AD_PORT_STANDBY         0x80
+#define AD_PORT_SELECTED        0x100
+#define AD_PORT_MOVED           0x200
+
+// Port Key definitions
+// key is determined according to the link speed, duplex and
+// user key(which is yet not supported)
+//              ------------------------------------------------------------
+// Port key :   | User key                       |      Speed       |Duplex|
+//              ------------------------------------------------------------
+//              16                               6               1 0
+#define  AD_DUPLEX_KEY_BITS    0x1
+#define  AD_SPEED_KEY_BITS     0x3E
+#define  AD_USER_KEY_BITS      0xFFC0
+
+//dalloun
+#define     AD_LINK_SPEED_BITMASK_1MBPS       0x1
+#define     AD_LINK_SPEED_BITMASK_10MBPS      0x2
+#define     AD_LINK_SPEED_BITMASK_100MBPS     0x4
+#define     AD_LINK_SPEED_BITMASK_1000MBPS    0x8
+//endalloun
+
+// compare MAC addresses
+#define MAC_ADDRESS_COMPARE(A, B) memcmp(A, B, ETH_ALEN)
+
+static struct mac_addr null_mac_addr = {{0, 0, 0, 0, 0, 0}};
+static u16 ad_ticks_per_sec;
+
+// ================= 3AD api to bonding and kernel code ==================
+static u16 __get_link_speed(struct port *port);
+static u8 __get_duplex(struct port *port);
+static inline void __initialize_port_locks(struct port *port);
+static inline void __deinitialize_port_locks(struct port *port);
+//conversions
+static void __ntohs_lacpdu(struct lacpdu *lacpdu);
+static u16 __ad_timer_to_ticks(u16 timer_type, u16 Par);
+
+
+// ================= ad code helper functions ==================
+//needed by ad_rx_machine(...)
+static void __record_pdu(struct lacpdu *lacpdu, struct port *port);
+static void __record_default(struct port *port);
+static void __update_selected(struct lacpdu *lacpdu, struct port *port);
+static void __update_default_selected(struct port *port);
+static void __choose_matched(struct lacpdu *lacpdu, struct port *port);
+static void __update_ntt(struct lacpdu *lacpdu, struct port *port);
+
+//needed for ad_mux_machine(..)
+static void __attach_bond_to_agg(struct port *port);
+static void __detach_bond_from_agg(struct port *port);
+static int __agg_ports_are_ready(struct aggregator *aggregator);
+static void __set_agg_ports_ready(struct aggregator *aggregator, int val);
+
+//needed for ad_agg_selection_logic(...)
+static u32 __get_agg_bandwidth(struct aggregator *aggregator);
+static struct aggregator *__get_active_agg(struct aggregator *aggregator);
+
+
+// ================= main 802.3ad protocol functions ==================
+static int ad_lacpdu_send(struct port *port);
+static int ad_marker_send(struct port *port, struct marker *marker);
+static void ad_mux_machine(struct port *port);
+static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port);
+static void ad_tx_machine(struct port *port);
+static void ad_periodic_machine(struct port *port);
+static void ad_port_selection_logic(struct port *port);
+static void ad_agg_selection_logic(struct aggregator *aggregator);
+static void ad_clear_agg(struct aggregator *aggregator);
+static void ad_initialize_agg(struct aggregator *aggregator);
+static void ad_initialize_port(struct port *port, int lacp_fast);
+static void ad_initialize_lacpdu(struct lacpdu *Lacpdu);
+static void ad_enable_collecting_distributing(struct port *port);
+static void ad_disable_collecting_distributing(struct port *port);
+static void ad_marker_info_received(struct marker *marker_info, struct port *port);
+static void ad_marker_response_received(struct marker *marker, struct port *port);
+
+
+/////////////////////////////////////////////////////////////////////////////////
+// ================= api to bonding and kernel code ==================
+/////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * __get_bond_by_port - get the port's bonding struct
+ * @port: the port we're looking at
+ *
+ * Return @port's bonding struct, or %NULL if it can't be found.
+ */
+static inline struct bonding *__get_bond_by_port(struct port *port)
+{
+	if (port->slave == NULL) {
+		return NULL;
+	}
+
+	return bond_get_bond_by_slave(port->slave);
+}
+
+/**
+ * __get_first_port - get the first port in the bond
+ * @bond: the bond we're looking at
+ *
+ * Return the port of the first slave in @bond, or %NULL if it can't be found.
+ */
+static inline struct port *__get_first_port(struct bonding *bond)
+{
+	struct slave *slave = bond->next;
+
+	if (slave == (struct slave *)bond) {
+		return NULL;
+	}
+
+	return &(SLAVE_AD_INFO(slave).port);
+}
+
+/**
+ * __get_next_port - get the next port in the bond
+ * @port: the port we're looking at
+ *
+ * Return the port of the slave that is next in line of @port's slave in the
+ * bond, or %NULL if it can't be found.
+ */
+static inline struct port *__get_next_port(struct port *port)
+{
+	struct bonding *bond = __get_bond_by_port(port);
+	struct slave *slave = port->slave;
+
+	// If there's no bond for this port, or this is the last slave
+	if ((bond == NULL) || (slave->next == bond->next)) {
+		return NULL;
+	}
+
+	return &(SLAVE_AD_INFO(slave->next).port);
+}
+
+/**
+ * __get_first_agg - get the first aggregator in the bond
+ * @bond: the bond we're looking at
+ *
+ * Return the aggregator of the first slave in @bond, or %NULL if it can't be
+ * found.
+ */
+static inline struct aggregator *__get_first_agg(struct port *port)
+{
+	struct bonding *bond = __get_bond_by_port(port);
+
+	// If there's no bond for this port, or this is the last slave
+	if ((bond == NULL) || (bond->next == (struct slave *)bond)) {
+		return NULL;
+	}
+
+	return &(SLAVE_AD_INFO(bond->next).aggregator);
+}
+
+/**
+ * __get_next_agg - get the next aggregator in the bond
+ * @aggregator: the aggregator we're looking at
+ *
+ * Return the aggregator of the slave that is next in line of @aggregator's
+ * slave in the bond, or %NULL if it can't be found.
+ */
+static inline struct aggregator *__get_next_agg(struct aggregator *aggregator)
+{
+	struct slave *slave = aggregator->slave;
+	struct bonding *bond = bond_get_bond_by_slave(slave);
+
+	// If there's no bond for this aggregator, or this is the last slave
+	if ((bond == NULL) || (slave->next == bond->next)) {
+		return NULL;
+	}
+
+	return &(SLAVE_AD_INFO(slave->next).aggregator);
+}
+
+/**
+ * __disable_port - disable the port's slave
+ * @port: the port we're looking at
+ *
+ */
+static inline void __disable_port(struct port *port)
+{
+	bond_set_slave_inactive_flags(port->slave);
+}
+
+/**
+ * __enable_port - enable the port's slave, if it's up
+ * @port: the port we're looking at
+ *
+ */
+static inline void __enable_port(struct port *port)
+{
+	struct slave *slave = port->slave;
+
+	if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev)) {
+		bond_set_slave_active_flags(slave);
+	}
+}
+
+/**
+ * __port_is_enabled - check if the port's slave is in active state
+ * @port: the port we're looking at
+ *
+ */
+static inline int __port_is_enabled(struct port *port)
+{
+	return(port->slave->state == BOND_STATE_ACTIVE);
+}
+
+/**
+ * __get_agg_selection_mode - get the aggregator selection mode
+ * @port: the port we're looking at
+ *
+ * Get the aggregator selection mode. Can be %BANDWIDTH or %COUNT.
+ */
+static inline u32 __get_agg_selection_mode(struct port *port)
+{
+	struct bonding *bond = __get_bond_by_port(port);
+
+	if (bond == NULL) {
+		return AD_BANDWIDTH;
+	}
+
+	return BOND_AD_INFO(bond).agg_select_mode;
+}
+
+/**
+ * __check_agg_selection_timer - check if the selection timer has expired
+ * @port: the port we're looking at
+ *
+ */
+static inline int __check_agg_selection_timer(struct port *port)
+{
+	struct bonding *bond = __get_bond_by_port(port);
+
+	if (bond == NULL) {
+		return 0;
+	}
+
+	return BOND_AD_INFO(bond).agg_select_timer ? 1 : 0;
+}
+
+/**
+ * __get_rx_machine_lock - lock the port's RX machine
+ * @port: the port we're looking at
+ *
+ */
+static inline void __get_rx_machine_lock(struct port *port)
+{
+	spin_lock(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
+}
+
+/**
+ * __release_rx_machine_lock - unlock the port's RX machine
+ * @port: the port we're looking at
+ *
+ */
+static inline void __release_rx_machine_lock(struct port *port)
+{
+	spin_unlock(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
+}
+
+/**
+ * __get_link_speed - get a port's speed
+ * @port: the port we're looking at
+ *
+ * Return @port's speed in 802.3ad bitmask format. i.e. one of:
+ *     0,
+ *     %AD_LINK_SPEED_BITMASK_10MBPS,
+ *     %AD_LINK_SPEED_BITMASK_100MBPS,
+ *     %AD_LINK_SPEED_BITMASK_1000MBPS
+ */
+static u16 __get_link_speed(struct port *port)
+{
+	struct slave *slave = port->slave;
+	u16 speed;
+
+	/* this if covers only a special case: when the configuration starts with
+	 * link down, it sets the speed to 0.
+	 * This is done in spite of the fact that the e100 driver reports 0 to be
+	 * compatible with MVT in the future.*/
+	if (slave->link != BOND_LINK_UP) {
+		speed=0;
+	} else {
+		switch (slave->speed) {
+		case SPEED_10:
+			speed = AD_LINK_SPEED_BITMASK_10MBPS;
+			break;
+
+		case SPEED_100:
+			speed = AD_LINK_SPEED_BITMASK_100MBPS;
+			break;
+
+		case SPEED_1000:
+			speed = AD_LINK_SPEED_BITMASK_1000MBPS;
+			break;
+
+		default:
+			speed = 0; // unknown speed value from ethtool. shouldn't happen
+			break;
+		}
+	}
+
+	BOND_PRINT_DBG(("Port %d Received link speed %d update from adapter", port->actor_port_number, speed));
+	return speed;
+}
+
+/**
+ * __get_duplex - get a port's duplex
+ * @port: the port we're looking at
+ *
+ * Return @port's duplex in 802.3ad bitmask format. i.e.:
+ *     0x01 if in full duplex
+ *     0x00 otherwise
+ */
+static u8 __get_duplex(struct port *port)
+{
+	struct slave *slave = port->slave;
+
+	u8 retval;
+
+	//  handling a special case: when the configuration starts with
+	// link down, it sets the duplex to 0.
+	if (slave->link != BOND_LINK_UP) {
+		retval=0x0;
+	} else {
+		switch (slave->duplex) {
+		case DUPLEX_FULL:
+			retval=0x1;
+			BOND_PRINT_DBG(("Port %d Received status full duplex update from adapter", port->actor_port_number));
+			break;
+		case DUPLEX_HALF:
+		default:
+			retval=0x0;
+			BOND_PRINT_DBG(("Port %d Received status NOT full duplex update from adapter", port->actor_port_number));
+			break;
+		}
+	}
+	return retval;
+}
+
+/**
+ * __initialize_port_locks - initialize a port's RX machine spinlock
+ * @port: the port we're looking at
+ *
+ */
+static inline void __initialize_port_locks(struct port *port)
+{
+	// make sure it isn't called twice
+	spin_lock_init(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
+}
+
+/**
+ * __deinitialize_port_locks - deinitialize a port's RX machine spinlock
+ * @port: the port we're looking at
+ *
+ */
+static inline void __deinitialize_port_locks(struct port *port)
+{
+}
+
+//conversions
+/**
+ * __ntohs_lacpdu - convert the contents of a LACPDU to host byte order
+ * @lacpdu: the speicifed lacpdu
+ *
+ * For each multi-byte field in the lacpdu, convert its content
+ */
+static void __ntohs_lacpdu(struct lacpdu *lacpdu)
+{
+	if (lacpdu) {
+		lacpdu->actor_system_priority =   ntohs(lacpdu->actor_system_priority);
+		lacpdu->actor_key =               ntohs(lacpdu->actor_key);
+		lacpdu->actor_port_priority =     ntohs(lacpdu->actor_port_priority);
+		lacpdu->actor_port =              ntohs(lacpdu->actor_port);
+		lacpdu->partner_system_priority = ntohs(lacpdu->partner_system_priority);
+		lacpdu->partner_key =             ntohs(lacpdu->partner_key);
+		lacpdu->partner_port_priority =   ntohs(lacpdu->partner_port_priority);
+		lacpdu->partner_port =            ntohs(lacpdu->partner_port);
+		lacpdu->collector_max_delay =     ntohs(lacpdu->collector_max_delay);
+	}
+}
+
+/**
+ * __ad_timer_to_ticks - convert a given timer type to AD module ticks
+ * @timer_type:	which timer to operate
+ * @par: timer parameter. see below
+ *
+ * If @timer_type is %current_while_timer, @par indicates long/short timer.
+ * If @timer_type is %periodic_timer, @par is one of %FAST_PERIODIC_TIME,
+ *						    %SLOW_PERIODIC_TIME.
+ */
+static u16 __ad_timer_to_ticks(u16 timer_type, u16 par)
+{
+	u16 retval=0;	 //to silence the compiler
+
+	switch (timer_type) {
+	case AD_CURRENT_WHILE_TIMER:   // for rx machine usage
+		if (par) {	      // for short or long timeout
+			retval = (AD_SHORT_TIMEOUT_TIME*ad_ticks_per_sec); // short timeout
+		} else {
+			retval = (AD_LONG_TIMEOUT_TIME*ad_ticks_per_sec); // long timeout
+		}
+		break;
+	case AD_ACTOR_CHURN_TIMER:	    // for local churn machine
+		retval = (AD_CHURN_DETECTION_TIME*ad_ticks_per_sec);
+		break;
+	case AD_PERIODIC_TIMER:	    // for periodic machine
+		retval = (par*ad_ticks_per_sec); // long timeout
+		break;
+	case AD_PARTNER_CHURN_TIMER:   // for remote churn machine
+		retval = (AD_CHURN_DETECTION_TIME*ad_ticks_per_sec);
+		break;
+	case AD_WAIT_WHILE_TIMER:	    // for selection machine
+		retval = (AD_AGGREGATE_WAIT_TIME*ad_ticks_per_sec);
+		break;
+	}
+	return retval;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////
+// ================= ad_rx_machine helper functions ==================
+/////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * __record_pdu - record parameters from a received lacpdu
+ * @lacpdu: the lacpdu we've received
+ * @port: the port we're looking at
+ *
+ * Record the parameter values for the Actor carried in a received lacpdu as
+ * the current partner operational parameter values and sets
+ * actor_oper_port_state.defaulted to FALSE.
+ */
+static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
+{
+	// validate lacpdu and port
+	if (lacpdu && port) {
+		// record the new parameter values for the partner operational
+		port->partner_oper_port_number = lacpdu->actor_port;
+		port->partner_oper_port_priority = lacpdu->actor_port_priority;
+		port->partner_oper_system = lacpdu->actor_system;
+		port->partner_oper_system_priority = lacpdu->actor_system_priority;
+		port->partner_oper_key = lacpdu->actor_key;
+		// zero partener's lase states
+		port->partner_oper_port_state = 0;
+		port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_LACP_ACTIVITY);
+		port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_LACP_TIMEOUT);
+		port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_AGGREGATION);
+		port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION);
+		port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_COLLECTING);
+		port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_DISTRIBUTING);
+		port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_DEFAULTED);
+		port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_EXPIRED);
+
+		// set actor_oper_port_state.defaulted to FALSE
+		port->actor_oper_port_state &= ~AD_STATE_DEFAULTED;
+
+		// set the partner sync. to on if the partner is sync. and the port is matched
+		if ((port->sm_vars & AD_PORT_MATCHED) && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION)) {
+			port->partner_oper_port_state |= AD_STATE_SYNCHRONIZATION;
+		} else {
+			port->partner_oper_port_state &= ~AD_STATE_SYNCHRONIZATION;
+		}
+	}
+}
+
+/**
+ * __record_default - record default parameters
+ * @port: the port we're looking at
+ *
+ * This function records the default parameter values for the partner carried
+ * in the Partner Admin parameters as the current partner operational parameter
+ * values and sets actor_oper_port_state.defaulted to TRUE.
+ */
+static void __record_default(struct port *port)
+{
+	// validate the port
+	if (port) {
+		// record the partner admin parameters
+		port->partner_oper_port_number = port->partner_admin_port_number;
+		port->partner_oper_port_priority = port->partner_admin_port_priority;
+		port->partner_oper_system = port->partner_admin_system;
+		port->partner_oper_system_priority = port->partner_admin_system_priority;
+		port->partner_oper_key = port->partner_admin_key;
+		port->partner_oper_port_state = port->partner_admin_port_state;
+
+		// set actor_oper_port_state.defaulted to true
+		port->actor_oper_port_state |= AD_STATE_DEFAULTED;
+	}
+}
+
+/**
+ * __update_selected - update a port's Selected variable from a received lacpdu
+ * @lacpdu: the lacpdu we've received
+ * @port: the port we're looking at
+ *
+ * Update the value of the selected variable, using parameter values from a
+ * newly received lacpdu. The parameter values for the Actor carried in the
+ * received PDU are compared with the corresponding operational parameter
+ * values for the ports partner. If one or more of the comparisons shows that
+ * the value(s) received in the PDU differ from the current operational values,
+ * then selected is set to FALSE and actor_oper_port_state.synchronization is
+ * set to out_of_sync. Otherwise, selected remains unchanged.
+ */
+static void __update_selected(struct lacpdu *lacpdu, struct port *port)
+{
+	// validate lacpdu and port
+	if (lacpdu && port) {
+		// check if any parameter is different
+		if ((lacpdu->actor_port != port->partner_oper_port_number) ||
+		    (lacpdu->actor_port_priority != port->partner_oper_port_priority) ||
+		    MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->partner_oper_system)) ||
+		    (lacpdu->actor_system_priority != port->partner_oper_system_priority) ||
+		    (lacpdu->actor_key != port->partner_oper_key) ||
+		    ((lacpdu->actor_state & AD_STATE_AGGREGATION) != (port->partner_oper_port_state & AD_STATE_AGGREGATION))
+		   ) {
+			// update the state machine Selected variable
+			port->sm_vars &= ~AD_PORT_SELECTED;
+		}
+	}
+}
+
+/**
+ * __update_default_selected - update a port's Selected variable from Partner
+ * @port: the port we're looking at
+ *
+ * This function updates the value of the selected variable, using the partner
+ * administrative parameter values. The administrative values are compared with
+ * the corresponding operational parameter values for the partner. If one or
+ * more of the comparisons shows that the administrative value(s) differ from
+ * the current operational values, then Selected is set to FALSE and
+ * actor_oper_port_state.synchronization is set to OUT_OF_SYNC. Otherwise,
+ * Selected remains unchanged.
+ */
+static void __update_default_selected(struct port *port)
+{
+	// validate the port
+	if (port) {
+		// check if any parameter is different
+		if ((port->partner_admin_port_number != port->partner_oper_port_number) ||
+		    (port->partner_admin_port_priority != port->partner_oper_port_priority) ||
+		    MAC_ADDRESS_COMPARE(&(port->partner_admin_system), &(port->partner_oper_system)) ||
+		    (port->partner_admin_system_priority != port->partner_oper_system_priority) ||
+		    (port->partner_admin_key != port->partner_oper_key) ||
+		    ((port->partner_admin_port_state & AD_STATE_AGGREGATION) != (port->partner_oper_port_state & AD_STATE_AGGREGATION))
+		   ) {
+			// update the state machine Selected variable
+			port->sm_vars &= ~AD_PORT_SELECTED;
+		}
+	}
+}
+
+/**
+ * __choose_matched - update a port's matched variable from a received lacpdu
+ * @lacpdu: the lacpdu we've received
+ * @port: the port we're looking at
+ *
+ * Update the value of the matched variable, using parameter values from a
+ * newly received lacpdu. Parameter values for the partner carried in the
+ * received PDU are compared with the corresponding operational parameter
+ * values for the actor. Matched is set to TRUE if all of these parameters
+ * match and the PDU parameter partner_state.aggregation has the same value as
+ * actor_oper_port_state.aggregation and lacp will actively maintain the link
+ * in the aggregation. Matched is also set to TRUE if the value of
+ * actor_state.aggregation in the received PDU is set to FALSE, i.e., indicates
+ * an individual link and lacp will actively maintain the link. Otherwise,
+ * matched is set to FALSE. LACP is considered to be actively maintaining the
+ * link if either the PDU's actor_state.lacp_activity variable is TRUE or both
+ * the actor's actor_oper_port_state.lacp_activity and the PDU's
+ * partner_state.lacp_activity variables are TRUE.
+ */
+static void __choose_matched(struct lacpdu *lacpdu, struct port *port)
+{
+	// validate lacpdu and port
+	if (lacpdu && port) {
+		// check if all parameters are alike
+		if (((lacpdu->partner_port == port->actor_port_number) &&
+		     (lacpdu->partner_port_priority == port->actor_port_priority) &&
+		     !MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) &&
+		     (lacpdu->partner_system_priority == port->actor_system_priority) &&
+		     (lacpdu->partner_key == port->actor_oper_port_key) &&
+		     ((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
+		    // or this is individual link(aggregation == FALSE)
+		    ((lacpdu->actor_state & AD_STATE_AGGREGATION) == 0)
+		   ) {
+			// update the state machine Matched variable
+			port->sm_vars |= AD_PORT_MATCHED;
+		} else {
+			port->sm_vars &= ~AD_PORT_MATCHED;
+		}
+	}
+}
+
+/**
+ * __update_ntt - update a port's ntt variable from a received lacpdu
+ * @lacpdu: the lacpdu we've received
+ * @port: the port we're looking at
+ *
+ * Updates the value of the ntt variable, using parameter values from a newly
+ * received lacpdu. The parameter values for the partner carried in the
+ * received PDU are compared with the corresponding operational parameter
+ * values for the Actor. If one or more of the comparisons shows that the
+ * value(s) received in the PDU differ from the current operational values,
+ * then ntt is set to TRUE. Otherwise, ntt remains unchanged.
+ */
+static void __update_ntt(struct lacpdu *lacpdu, struct port *port)
+{
+	// validate lacpdu and port
+	if (lacpdu && port) {
+		// check if any parameter is different
+		if ((lacpdu->partner_port != port->actor_port_number) ||
+		    (lacpdu->partner_port_priority != port->actor_port_priority) ||
+		    MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) ||
+		    (lacpdu->partner_system_priority != port->actor_system_priority) ||
+		    (lacpdu->partner_key != port->actor_oper_port_key) ||
+		    ((lacpdu->partner_state & AD_STATE_LACP_ACTIVITY) != (port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY)) ||
+		    ((lacpdu->partner_state & AD_STATE_LACP_TIMEOUT) != (port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT)) ||
+		    ((lacpdu->partner_state & AD_STATE_SYNCHRONIZATION) != (port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION)) ||
+		    ((lacpdu->partner_state & AD_STATE_AGGREGATION) != (port->actor_oper_port_state & AD_STATE_AGGREGATION))
+		   ) {
+			// set ntt to be TRUE
+			port->ntt = 1;
+		}
+	}
+}
+
+/**
+ * __attach_bond_to_agg
+ * @port: the port we're looking at
+ *
+ * Handle the attaching of the port's control parser/multiplexer and the
+ * aggregator. This function does nothing since the parser/multiplexer of the
+ * receive and the parser/multiplexer of the aggregator are already combined.
+ */
+static void __attach_bond_to_agg(struct port *port)
+{
+	port=NULL; // just to satisfy the compiler
+	// This function does nothing since the parser/multiplexer of the receive
+	// and the parser/multiplexer of the aggregator are already combined
+}
+
+/**
+ * __detach_bond_to_agg
+ * @port: the port we're looking at
+ *
+ * Handle the detaching of the port's control parser/multiplexer from the
+ * aggregator. This function does nothing since the parser/multiplexer of the
+ * receive and the parser/multiplexer of the aggregator are already combined.
+ */
+static void __detach_bond_from_agg(struct port *port)
+{
+	port=NULL; // just to satisfy the compiler
+	// This function does nothing sience the parser/multiplexer of the receive
+	// and the parser/multiplexer of the aggregator are already combined
+}
+
+/**
+ * __agg_ports_are_ready - check if all ports in an aggregator are ready
+ * @aggregator: the aggregator we're looking at
+ *
+ */
+static int __agg_ports_are_ready(struct aggregator *aggregator)
+{
+	struct port *port;
+	int retval = 1;
+
+	if (aggregator) {
+		// scan all ports in this aggregator to verfy if they are all ready
+		for (port=aggregator->lag_ports; port; port=port->next_port_in_aggregator) {
+			if (!(port->sm_vars & AD_PORT_READY_N)) {
+				retval = 0;
+				break;
+			}
+		}
+	}
+
+	return retval;
+}
+
+/**
+ * __set_agg_ports_ready - set value of Ready bit in all ports of an aggregator
+ * @aggregator: the aggregator we're looking at
+ * @val: Should the ports' ready bit be set on or off
+ *
+ */
+static void __set_agg_ports_ready(struct aggregator *aggregator, int val)
+{
+	struct port *port;
+
+	for (port=aggregator->lag_ports; port; port=port->next_port_in_aggregator) {
+		if (val) {
+			port->sm_vars |= AD_PORT_READY;
+		} else {
+			port->sm_vars &= ~AD_PORT_READY;
+		}
+	}
+}
+
+/**
+ * __get_agg_bandwidth - get the total bandwidth of an aggregator
+ * @aggregator: the aggregator we're looking at
+ *
+ */
+static u32 __get_agg_bandwidth(struct aggregator *aggregator)
+{
+	u32 bandwidth=0;
+	u32 basic_speed;
+
+	if (aggregator->num_of_ports) {
+		basic_speed = __get_link_speed(aggregator->lag_ports);
+		switch (basic_speed) {
+		case AD_LINK_SPEED_BITMASK_1MBPS:
+			bandwidth = aggregator->num_of_ports;
+			break;
+		case AD_LINK_SPEED_BITMASK_10MBPS:
+			bandwidth = aggregator->num_of_ports * 10;
+			break;
+		case AD_LINK_SPEED_BITMASK_100MBPS:
+			bandwidth = aggregator->num_of_ports * 100;
+			break;
+		case AD_LINK_SPEED_BITMASK_1000MBPS:
+			bandwidth = aggregator->num_of_ports * 1000;
+			break;
+		default:
+			bandwidth=0; // to silent the compilor ....
+		}
+	}
+	return bandwidth;
+}
+
+/**
+ * __get_active_agg - get the current active aggregator
+ * @aggregator: the aggregator we're looking at
+ *
+ */
+static struct aggregator *__get_active_agg(struct aggregator *aggregator)
+{
+	struct aggregator *retval = NULL;
+
+	for (; aggregator; aggregator = __get_next_agg(aggregator)) {
+		if (aggregator->is_active) {
+			retval = aggregator;
+			break;
+		}
+	}
+
+	return retval;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+// ================= main 802.3ad protocol code ======================================
+//////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * ad_lacpdu_send - send out a lacpdu packet on a given port
+ * @port: the port we're looking at
+ *
+ * Returns:   0 on success
+ *          < 0 on error
+ */
+static int ad_lacpdu_send(struct port *port)
+{
+	struct slave *slave = port->slave;
+	struct sk_buff *skb;
+	struct lacpdu_header *lacpdu_header;
+	int length = sizeof(struct lacpdu_header);
+	struct mac_addr lacpdu_multicast_address = AD_MULTICAST_LACPDU_ADDR;
+
+	skb = dev_alloc_skb(length);
+	if (!skb) {
+		return -ENOMEM;
+	}
+
+	skb->dev = slave->dev;
+	skb->mac.raw = skb->data;
+	skb->nh.raw = skb->data + ETH_HLEN;
+	skb->protocol = PKT_TYPE_LACPDU;
+
+	lacpdu_header = (struct lacpdu_header *)skb_put(skb, length);
+
+	lacpdu_header->ad_header.destination_address = lacpdu_multicast_address;
+	/* Note: source addres is set to be the member's PERMANENT address, because we use it
+	   to identify loopback lacpdus in receive. */
+	lacpdu_header->ad_header.source_address = *((struct mac_addr *)(slave->perm_hwaddr));
+	lacpdu_header->ad_header.length_type = PKT_TYPE_LACPDU;
+
+	lacpdu_header->lacpdu = port->lacpdu; // struct copy
+
+	dev_queue_xmit(skb);
+
+	return 0;
+}
+
+/**
+ * ad_marker_send - send marker information/response on a given port
+ * @port: the port we're looking at
+ * @marker: marker data to send
+ *
+ * Returns:   0 on success
+ *          < 0 on error
+ */
+static int ad_marker_send(struct port *port, struct marker *marker)
+{
+	struct slave *slave = port->slave;
+	struct sk_buff *skb;
+	struct marker_header *marker_header;
+	int length = sizeof(struct marker_header);
+	struct mac_addr lacpdu_multicast_address = AD_MULTICAST_LACPDU_ADDR;
+
+	skb = dev_alloc_skb(length + 16);
+	if (!skb) {
+		return -ENOMEM;
+	}
+
+	skb_reserve(skb, 16);
+
+	skb->dev = slave->dev;
+	skb->mac.raw = skb->data;
+	skb->nh.raw = skb->data + ETH_HLEN;
+	skb->protocol = PKT_TYPE_LACPDU;
+
+	marker_header = (struct marker_header *)skb_put(skb, length);
+
+	marker_header->ad_header.destination_address = lacpdu_multicast_address;
+	/* Note: source addres is set to be the member's PERMANENT address, because we use it
+	   to identify loopback MARKERs in receive. */
+	marker_header->ad_header.source_address = *((struct mac_addr *)(slave->perm_hwaddr));
+	marker_header->ad_header.length_type = PKT_TYPE_LACPDU;
+
+	marker_header->marker = *marker; // struct copy
+
+	dev_queue_xmit(skb);
+
+	return 0;
+}
+
+/**
+ * ad_mux_machine - handle a port's mux state machine
+ * @port: the port we're looking at
+ *
+ */
+static void ad_mux_machine(struct port *port)
+{
+	mux_states_t last_state;
+
+	// keep current State Machine state to compare later if it was changed
+	last_state = port->sm_mux_state;
+
+	if (port->sm_vars & AD_PORT_BEGIN) {
+		port->sm_mux_state = AD_MUX_DETACHED;		 // next state
+	} else {
+		switch (port->sm_mux_state) {
+		case AD_MUX_DETACHED:
+			if ((port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY)) { // if SELECTED or STANDBY
+				port->sm_mux_state = AD_MUX_WAITING; // next state
+			}
+			break;
+		case AD_MUX_WAITING:
+			// if SELECTED == FALSE return to DETACH state
+			if (!(port->sm_vars & AD_PORT_SELECTED)) { // if UNSELECTED
+				port->sm_vars &= ~AD_PORT_READY_N;
+				// in order to withhold the Selection Logic to check all ports READY_N value
+				// every callback cycle to update ready variable, we check READY_N and update READY here
+				__set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
+				port->sm_mux_state = AD_MUX_DETACHED;	 // next state
+				break;
+			}
+
+			// check if the wait_while_timer expired
+			if (port->sm_mux_timer_counter && !(--port->sm_mux_timer_counter)) {
+				port->sm_vars |= AD_PORT_READY_N;
+			}
+
+			// in order to withhold the selection logic to check all ports READY_N value
+			// every callback cycle to update ready variable, we check READY_N and update READY here
+			__set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
+
+			// if the wait_while_timer expired, and the port is in READY state, move to ATTACHED state
+			if ((port->sm_vars & AD_PORT_READY) && !port->sm_mux_timer_counter) {
+				port->sm_mux_state = AD_MUX_ATTACHED;	 // next state
+			}
+			break;
+		case AD_MUX_ATTACHED:
+			// check also if agg_select_timer expired(so the edable port will take place only after this timer)
+			if ((port->sm_vars & AD_PORT_SELECTED) && (port->partner_oper_port_state & AD_STATE_SYNCHRONIZATION) && !__check_agg_selection_timer(port)) {
+				port->sm_mux_state = AD_MUX_COLLECTING_DISTRIBUTING;// next state
+			} else if (!(port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY)) {	  // if UNSELECTED or STANDBY
+				port->sm_vars &= ~AD_PORT_READY_N;
+				// in order to withhold the selection logic to check all ports READY_N value
+				// every callback cycle to update ready variable, we check READY_N and update READY here
+				__set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
+				port->sm_mux_state = AD_MUX_DETACHED;// next state
+			}
+			break;
+		case AD_MUX_COLLECTING_DISTRIBUTING:
+			if (!(port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY) ||
+			    !(port->partner_oper_port_state & AD_STATE_SYNCHRONIZATION)
+			   ) {
+				port->sm_mux_state = AD_MUX_ATTACHED;// next state
+
+			} else {
+				// if port state hasn't changed make
+				// sure that a collecting distributing
+				// port in an active aggregator is enabled
+				if (port->aggregator &&
+				    port->aggregator->is_active &&
+				    !__port_is_enabled(port)) {
+
+					__enable_port(port);
+				}
+			}
+			break;
+		default:    //to silence the compiler
+			break;
+		}
+	}
+
+	// check if the state machine was changed
+	if (port->sm_mux_state != last_state) {
+		BOND_PRINT_DBG(("Mux Machine: Port=%d, Last State=%d, Curr State=%d", port->actor_port_number, last_state, port->sm_mux_state));
+		switch (port->sm_mux_state) {
+		case AD_MUX_DETACHED:
+			__detach_bond_from_agg(port);
+			port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION;
+			ad_disable_collecting_distributing(port);
+			port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
+			port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
+			port->ntt = 1;
+			break;
+		case AD_MUX_WAITING:
+			port->sm_mux_timer_counter = __ad_timer_to_ticks(AD_WAIT_WHILE_TIMER, 0);
+			break;
+		case AD_MUX_ATTACHED:
+			__attach_bond_to_agg(port);
+			port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION;
+			port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
+			port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
+			ad_disable_collecting_distributing(port);
+			port->ntt = 1;
+			break;
+		case AD_MUX_COLLECTING_DISTRIBUTING:
+			port->actor_oper_port_state |= AD_STATE_COLLECTING;
+			port->actor_oper_port_state |= AD_STATE_DISTRIBUTING;
+			ad_enable_collecting_distributing(port);
+			port->ntt = 1;
+			break;
+		default:    //to silence the compiler
+			break;
+		}
+	}
+}
+
+/**
+ * ad_rx_machine - handle a port's rx State Machine
+ * @lacpdu: the lacpdu we've received
+ * @port: the port we're looking at
+ *
+ * If lacpdu arrived, stop previous timer (if exists) and set the next state as
+ * CURRENT. If timer expired set the state machine in the proper state.
+ * In other cases, this function checks if we need to switch to other state.
+ */
+static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
+{
+	rx_states_t last_state;
+
+	// Lock to prevent 2 instances of this function to run simultaneously(rx interrupt and periodic machine callback)
+	__get_rx_machine_lock(port);
+
+	// keep current State Machine state to compare later if it was changed
+	last_state = port->sm_rx_state;
+
+	// check if state machine should change state
+	// first, check if port was reinitialized
+	if (port->sm_vars & AD_PORT_BEGIN) {
+		port->sm_rx_state = AD_RX_INITIALIZE;		    // next state
+	}
+	// check if port is not enabled
+	else if (!(port->sm_vars & AD_PORT_BEGIN) && !port->is_enabled && !(port->sm_vars & AD_PORT_MOVED)) {
+		port->sm_rx_state = AD_RX_PORT_DISABLED;	    // next state
+	}
+	// check if new lacpdu arrived
+	else if (lacpdu && ((port->sm_rx_state == AD_RX_EXPIRED) || (port->sm_rx_state == AD_RX_DEFAULTED) || (port->sm_rx_state == AD_RX_CURRENT))) {
+		port->sm_rx_timer_counter = 0; // zero timer
+		port->sm_rx_state = AD_RX_CURRENT;
+	} else {
+		// if timer is on, and if it is expired
+		if (port->sm_rx_timer_counter && !(--port->sm_rx_timer_counter)) {
+			switch (port->sm_rx_state) {
+			case AD_RX_EXPIRED:
+				port->sm_rx_state = AD_RX_DEFAULTED;		// next state
+				break;
+			case AD_RX_CURRENT:
+				port->sm_rx_state = AD_RX_EXPIRED;	    // next state
+				break;
+			default:    //to silence the compiler
+				break;
+			}
+		} else {
+			// if no lacpdu arrived and no timer is on
+			switch (port->sm_rx_state) {
+			case AD_RX_PORT_DISABLED:
+				if (port->sm_vars & AD_PORT_MOVED) {
+					port->sm_rx_state = AD_RX_INITIALIZE;	    // next state
+				} else if (port->is_enabled && (port->sm_vars & AD_PORT_LACP_ENABLED)) {
+					port->sm_rx_state = AD_RX_EXPIRED;	// next state
+				} else if (port->is_enabled && ((port->sm_vars & AD_PORT_LACP_ENABLED) == 0)) {
+					port->sm_rx_state = AD_RX_LACP_DISABLED;    // next state
+				}
+				break;
+			default:    //to silence the compiler
+				break;
+
+			}
+		}
+	}
+
+	// check if the State machine was changed or new lacpdu arrived
+	if ((port->sm_rx_state != last_state) || (lacpdu)) {
+		BOND_PRINT_DBG(("Rx Machine: Port=%d, Last State=%d, Curr State=%d", port->actor_port_number, last_state, port->sm_rx_state));
+		switch (port->sm_rx_state) {
+		case AD_RX_INITIALIZE:
+			if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) {
+				port->sm_vars &= ~AD_PORT_LACP_ENABLED;
+			} else {
+				port->sm_vars |= AD_PORT_LACP_ENABLED;
+			}
+			port->sm_vars &= ~AD_PORT_SELECTED;
+			__record_default(port);
+			port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
+			port->sm_vars &= ~AD_PORT_MOVED;
+			port->sm_rx_state = AD_RX_PORT_DISABLED;	// next state
+
+			/*- Fall Through -*/
+
+		case AD_RX_PORT_DISABLED:
+			port->sm_vars &= ~AD_PORT_MATCHED;
+			break;
+		case AD_RX_LACP_DISABLED:
+			port->sm_vars &= ~AD_PORT_SELECTED;
+			__record_default(port);
+			port->partner_oper_port_state &= ~AD_STATE_AGGREGATION;
+			port->sm_vars |= AD_PORT_MATCHED;
+			port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
+			break;
+		case AD_RX_EXPIRED:
+			//Reset of the Synchronization flag. (Standard 43.4.12)
+			//This reset cause to disable this port in the COLLECTING_DISTRIBUTING state of the
+			//mux machine in case of EXPIRED even if LINK_DOWN didn't arrive for the port.
+			port->partner_oper_port_state &= ~AD_STATE_SYNCHRONIZATION;
+			port->sm_vars &= ~AD_PORT_MATCHED;
+			port->partner_oper_port_state |= AD_SHORT_TIMEOUT;
+			port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT));
+			port->actor_oper_port_state |= AD_STATE_EXPIRED;
+			break;
+		case AD_RX_DEFAULTED:
+			__update_default_selected(port);
+			__record_default(port);
+			port->sm_vars |= AD_PORT_MATCHED;
+			port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
+			break;
+		case AD_RX_CURRENT:
+			// detect loopback situation
+			if (!MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->actor_system))) {
+				// INFO_RECEIVED_LOOPBACK_FRAMES
+				printk(KERN_ERR "bonding: An illegal loopback occurred on adapter (%s)\n",
+						port->slave->dev->name);
+				printk(KERN_ERR "Check the configuration to verify that all Adapters "
+						"are connected to 802.3ad compliant switch ports\n");
+				__release_rx_machine_lock(port);
+				return;
+			}
+			__update_selected(lacpdu, port);
+			__update_ntt(lacpdu, port);
+			__record_pdu(lacpdu, port);
+			__choose_matched(lacpdu, port);
+			port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT));
+			port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
+			// verify that if the aggregator is enabled, the port is enabled too.
+			//(because if the link goes down for a short time, the 802.3ad will not
+			// catch it, and the port will continue to be disabled)
+			if (port->aggregator && port->aggregator->is_active && !__port_is_enabled(port)) {
+				__enable_port(port);
+			}
+			break;
+		default:    //to silence the compiler
+			break;
+		}
+	}
+	__release_rx_machine_lock(port);
+}
+
+/**
+ * ad_tx_machine - handle a port's tx state machine
+ * @port: the port we're looking at
+ *
+ */
+static void ad_tx_machine(struct port *port)
+{
+	struct lacpdu *lacpdu = &port->lacpdu;
+
+	// check if tx timer expired, to verify that we do not send more than 3 packets per second
+	if (port->sm_tx_timer_counter && !(--port->sm_tx_timer_counter)) {
+		// check if there is something to send
+		if (port->ntt && (port->sm_vars & AD_PORT_LACP_ENABLED)) {
+			//update current actual Actor parameters
+			//lacpdu->subtype                   initialized
+			//lacpdu->version_number            initialized
+			//lacpdu->tlv_type_actor_info       initialized
+			//lacpdu->actor_information_length  initialized
+			lacpdu->actor_system_priority = port->actor_system_priority;
+			lacpdu->actor_system = port->actor_system;
+			lacpdu->actor_key = port->actor_oper_port_key;
+			lacpdu->actor_port_priority = port->actor_port_priority;
+			lacpdu->actor_port = port->actor_port_number;
+			lacpdu->actor_state = port->actor_oper_port_state;
+			//lacpdu->reserved_3_1              initialized
+			//lacpdu->tlv_type_partner_info     initialized
+			//lacpdu->partner_information_length initialized
+			lacpdu->partner_system_priority = port->partner_oper_system_priority;
+			lacpdu->partner_system = port->partner_oper_system;
+			lacpdu->partner_key = port->partner_oper_key;
+			lacpdu->partner_port_priority = port->partner_oper_port_priority;
+			lacpdu->partner_port = port->partner_oper_port_number;
+			lacpdu->partner_state = port->partner_oper_port_state;
+			//lacpdu->reserved_3_2              initialized
+			//lacpdu->tlv_type_collector_info   initialized
+			//lacpdu->collector_information_length initialized
+			//collector_max_delay                initialized
+			//reserved_12[12]                   initialized
+			//tlv_type_terminator               initialized
+			//terminator_length                 initialized
+			//reserved_50[50]                   initialized
+
+			// We need to convert all non u8 parameters to Big Endian for transmit
+			__ntohs_lacpdu(lacpdu);
+			// send the lacpdu
+			if (ad_lacpdu_send(port) >= 0) {
+				BOND_PRINT_DBG(("Sent LACPDU on port %d", port->actor_port_number));
+				// mark ntt as false, so it will not be sent again until demanded
+				port->ntt = 0;
+			}
+		}
+		// restart tx timer(to verify that we will not exceed AD_MAX_TX_IN_SECOND
+		port->sm_tx_timer_counter=ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
+	}
+}
+
+/**
+ * ad_periodic_machine - handle a port's periodic state machine
+ * @port: the port we're looking at
+ *
+ * Turn ntt flag on priodically to perform periodic transmission of lacpdu's.
+ */
+static void ad_periodic_machine(struct port *port)
+{
+	periodic_states_t last_state;
+
+	// keep current state machine state to compare later if it was changed
+	last_state = port->sm_periodic_state;
+
+	// check if port was reinitialized
+	if (((port->sm_vars & AD_PORT_BEGIN) || !(port->sm_vars & AD_PORT_LACP_ENABLED) || !port->is_enabled) ||
+	    (!(port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY) && !(port->partner_oper_port_state & AD_STATE_LACP_ACTIVITY))
+	   ) {
+		port->sm_periodic_state = AD_NO_PERIODIC;	     // next state
+	}
+	// check if state machine should change state
+	else if (port->sm_periodic_timer_counter) {
+		// check if periodic state machine expired
+		if (!(--port->sm_periodic_timer_counter)) {
+			// if expired then do tx
+			port->sm_periodic_state = AD_PERIODIC_TX;    // next state
+		} else {
+			// If not expired, check if there is some new timeout parameter from the partner state
+			switch (port->sm_periodic_state) {
+			case AD_FAST_PERIODIC:
+				if (!(port->partner_oper_port_state & AD_STATE_LACP_TIMEOUT)) {
+					port->sm_periodic_state = AD_SLOW_PERIODIC;  // next state
+				}
+				break;
+			case AD_SLOW_PERIODIC:
+				if ((port->partner_oper_port_state & AD_STATE_LACP_TIMEOUT)) {
+					// stop current timer
+					port->sm_periodic_timer_counter = 0;
+					port->sm_periodic_state = AD_PERIODIC_TX;	 // next state
+				}
+				break;
+			default:    //to silence the compiler
+				break;
+			}
+		}
+	} else {
+		switch (port->sm_periodic_state) {
+		case AD_NO_PERIODIC:
+			port->sm_periodic_state = AD_FAST_PERIODIC;	 // next state
+			break;
+		case AD_PERIODIC_TX:
+			if (!(port->partner_oper_port_state & AD_STATE_LACP_TIMEOUT)) {
+				port->sm_periodic_state = AD_SLOW_PERIODIC;  // next state
+			} else {
+				port->sm_periodic_state = AD_FAST_PERIODIC;  // next state
+			}
+			break;
+		default:    //to silence the compiler
+			break;
+		}
+	}
+
+	// check if the state machine was changed
+	if (port->sm_periodic_state != last_state) {
+		BOND_PRINT_DBG(("Periodic Machine: Port=%d, Last State=%d, Curr State=%d", port->actor_port_number, last_state, port->sm_periodic_state));
+		switch (port->sm_periodic_state) {
+		case AD_NO_PERIODIC:
+			port->sm_periodic_timer_counter = 0;	   // zero timer
+			break;
+		case AD_FAST_PERIODIC:
+			port->sm_periodic_timer_counter = __ad_timer_to_ticks(AD_PERIODIC_TIMER, (u16)(AD_FAST_PERIODIC_TIME))-1; // decrement 1 tick we lost in the PERIODIC_TX cycle
+			break;
+		case AD_SLOW_PERIODIC:
+			port->sm_periodic_timer_counter = __ad_timer_to_ticks(AD_PERIODIC_TIMER, (u16)(AD_SLOW_PERIODIC_TIME))-1; // decrement 1 tick we lost in the PERIODIC_TX cycle
+			break;
+		case AD_PERIODIC_TX:
+			port->ntt = 1;
+			break;
+		default:    //to silence the compiler
+			break;
+		}
+	}
+}
+
+/**
+ * ad_port_selection_logic - select aggregation groups
+ * @port: the port we're looking at
+ *
+ * Select aggregation groups, and assign each port for it's aggregetor. The
+ * selection logic is called in the inititalization (after all the handshkes),
+ * and after every lacpdu receive (if selected is off).
+ */
+static void ad_port_selection_logic(struct port *port)
+{
+	struct aggregator *aggregator, *free_aggregator = NULL, *temp_aggregator;
+	struct port *last_port = NULL, *curr_port;
+	int found = 0;
+
+	// if the port is already Selected, do nothing
+	if (port->sm_vars & AD_PORT_SELECTED) {
+		return;
+	}
+
+	// if the port is connected to other aggregator, detach it
+	if (port->aggregator) {
+		// detach the port from its former aggregator
+		temp_aggregator=port->aggregator;
+		for (curr_port=temp_aggregator->lag_ports; curr_port; last_port=curr_port, curr_port=curr_port->next_port_in_aggregator) {
+			if (curr_port == port) {
+				temp_aggregator->num_of_ports--;
+				if (!last_port) {// if it is the first port attached to the aggregator
+					temp_aggregator->lag_ports=port->next_port_in_aggregator;
+				} else {// not the first port attached to the aggregator
+					last_port->next_port_in_aggregator=port->next_port_in_aggregator;
+				}
+
+				// clear the port's relations to this aggregator
+				port->aggregator = NULL;
+				port->next_port_in_aggregator=NULL;
+				port->actor_port_aggregator_identifier=0;
+
+				BOND_PRINT_DBG(("Port %d left LAG %d", port->actor_port_number, temp_aggregator->aggregator_identifier));
+				// if the aggregator is empty, clear its parameters, and set it ready to be attached
+				if (!temp_aggregator->lag_ports) {
+					ad_clear_agg(temp_aggregator);
+				}
+				break;
+			}
+		}
+		if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list
+			printk(KERN_WARNING "bonding: Warning: Port %d (on %s) was "
+			       "related to aggregator %d but was not on its port list\n",
+			       port->actor_port_number, port->slave->dev->name,
+			       port->aggregator->aggregator_identifier);
+		}
+	}
+	// search on all aggregators for a suitable aggregator for this port
+	for (aggregator = __get_first_agg(port); aggregator;
+	     aggregator = __get_next_agg(aggregator)) {
+
+		// keep a free aggregator for later use(if needed)
+		if (!aggregator->lag_ports) {
+			if (!free_aggregator) {
+				free_aggregator=aggregator;
+			}
+			continue;
+		}
+		// check if current aggregator suits us
+		if (((aggregator->actor_oper_aggregator_key == port->actor_oper_port_key) && // if all parameters match AND
+		     !MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(port->partner_oper_system)) &&
+		     (aggregator->partner_system_priority == port->partner_oper_system_priority) &&
+		     (aggregator->partner_oper_aggregator_key == port->partner_oper_key)
+		    ) &&
+		    ((MAC_ADDRESS_COMPARE(&(port->partner_oper_system), &(null_mac_addr)) && // partner answers
+		      !aggregator->is_individual)  // but is not individual OR
+		    )
+		   ) {
+			// attach to the founded aggregator
+			port->aggregator = aggregator;
+			port->actor_port_aggregator_identifier=port->aggregator->aggregator_identifier;
+			port->next_port_in_aggregator=aggregator->lag_ports;
+			port->aggregator->num_of_ports++;
+			aggregator->lag_ports=port;
+			BOND_PRINT_DBG(("Port %d joined LAG %d(existing LAG)", port->actor_port_number, port->aggregator->aggregator_identifier));
+
+			// mark this port as selected
+			port->sm_vars |= AD_PORT_SELECTED;
+			found = 1;
+			break;
+		}
+	}
+
+	// the port couldn't find an aggregator - attach it to a new aggregator
+	if (!found) {
+		if (free_aggregator) {
+			// assign port a new aggregator
+			port->aggregator = free_aggregator;
+			port->actor_port_aggregator_identifier=port->aggregator->aggregator_identifier;
+
+			// update the new aggregator's parameters
+			// if port was responsed from the end-user
+			if (port->actor_oper_port_key & AD_DUPLEX_KEY_BITS) {// if port is full duplex
+				port->aggregator->is_individual = 0;
+			} else {
+				port->aggregator->is_individual = 1;
+			}
+
+			port->aggregator->actor_admin_aggregator_key = port->actor_admin_port_key;
+			port->aggregator->actor_oper_aggregator_key = port->actor_oper_port_key;
+			port->aggregator->partner_system=port->partner_oper_system;
+			port->aggregator->partner_system_priority = port->partner_oper_system_priority;
+			port->aggregator->partner_oper_aggregator_key = port->partner_oper_key;
+			port->aggregator->receive_state = 1;
+			port->aggregator->transmit_state = 1;
+			port->aggregator->lag_ports = port;
+			port->aggregator->num_of_ports++;
+
+			// mark this port as selected
+			port->sm_vars |= AD_PORT_SELECTED;
+
+			BOND_PRINT_DBG(("Port %d joined LAG %d(new LAG)", port->actor_port_number, port->aggregator->aggregator_identifier));
+		} else {
+			printk(KERN_ERR "bonding: Port %d (on %s) did not find a suitable aggregator\n",
+			       port->actor_port_number, port->slave->dev->name);
+		}
+	}
+	// if all aggregator's ports are READY_N == TRUE, set ready=TRUE in all aggregator's ports
+	// else set ready=FALSE in all aggregator's ports
+	__set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
+
+	if (!__check_agg_selection_timer(port) && (aggregator = __get_first_agg(port))) {
+		ad_agg_selection_logic(aggregator);
+	}
+}
+
+/**
+ * ad_agg_selection_logic - select an aggregation group for a team
+ * @aggregator: the aggregator we're looking at
+ *
+ * It is assumed that only one aggregator may be selected for a team.
+ * The logic of this function is to select (at first time) the aggregator with
+ * the most ports attached to it, and to reselect the active aggregator only if
+ * the previous aggregator has no more ports related to it.
+ *
+ * FIXME: this function MUST be called with the first agg in the bond, or
+ * __get_active_agg() won't work correctly. This function should be better
+ * called with the bond itself, and retrieve the first agg from it.
+ */
+static void ad_agg_selection_logic(struct aggregator *aggregator)
+{
+	struct aggregator *best_aggregator = NULL, *active_aggregator = NULL;
+	struct aggregator *last_active_aggregator = NULL, *origin_aggregator;
+	struct port *port;
+	u16 num_of_aggs=0;
+
+	origin_aggregator = aggregator;
+
+	//get current active aggregator
+	last_active_aggregator = __get_active_agg(aggregator);
+
+	// search for the aggregator with the most ports attached to it.
+	do {
+		// count how many candidate lag's we have
+		if (aggregator->lag_ports) {
+			num_of_aggs++;
+		}
+		if (aggregator->is_active && !aggregator->is_individual &&   // if current aggregator is the active aggregator
+		    MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr))) {   // and partner answers to 802.3ad PDUs
+			if (aggregator->num_of_ports) {	// if any ports attached to the current aggregator
+				best_aggregator=NULL;	 // disregard the best aggregator that was chosen by now
+				break;		 // stop the selection of other aggregator if there are any ports attached to this active aggregator
+			} else { // no ports attached to this active aggregator
+				aggregator->is_active = 0; // mark this aggregator as not active anymore
+			}
+		}
+		if (aggregator->num_of_ports) {	// if any ports attached
+			if (best_aggregator) {	// if there is a candidte aggregator
+				//The reasons for choosing new best aggregator:
+				// 1. if current agg is NOT individual and the best agg chosen so far is individual OR
+				// current and best aggs are both individual or both not individual, AND
+				// 2a.  current agg partner reply but best agg partner do not reply OR
+				// 2b.  current agg partner reply OR current agg partner do not reply AND best agg partner also do not reply AND
+				//      current has more ports/bandwidth, or same amount of ports but current has faster ports, THEN
+				//      current agg become best agg so far
+
+				//if current agg is NOT individual and the best agg chosen so far is individual change best_aggregator
+				if (!aggregator->is_individual && best_aggregator->is_individual) {
+					best_aggregator=aggregator;
+				}
+				// current and best aggs are both individual or both not individual
+				else if ((aggregator->is_individual && best_aggregator->is_individual) ||
+					 (!aggregator->is_individual && !best_aggregator->is_individual)) {
+					//  current and best aggs are both individual or both not individual AND
+					//  current agg partner reply but best agg partner do not reply
+					if ((MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr)) &&
+					     !MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr)))) {
+						best_aggregator=aggregator;
+					}
+					//  current agg partner reply OR current agg partner do not reply AND best agg partner also do not reply
+					else if (! (!MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr)) &&
+						    MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr)))) {
+						if ((__get_agg_selection_mode(aggregator->lag_ports) == AD_BANDWIDTH)&&
+						    (__get_agg_bandwidth(aggregator) > __get_agg_bandwidth(best_aggregator))) {
+							best_aggregator=aggregator;
+						} else if (__get_agg_selection_mode(aggregator->lag_ports) == AD_COUNT) {
+							if (((aggregator->num_of_ports > best_aggregator->num_of_ports) &&
+							     (aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS))||
+							    ((aggregator->num_of_ports == best_aggregator->num_of_ports) &&
+							     ((u16)(aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS) >
+							      (u16)(best_aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS)))) {
+								best_aggregator=aggregator;
+							}
+						}
+					}
+				}
+			} else {
+				best_aggregator=aggregator;
+			}
+		}
+		aggregator->is_active = 0; // mark all aggregators as not active anymore
+	} while ((aggregator = __get_next_agg(aggregator)));
+
+	// if we have new aggregator selected, don't replace the old aggregator if it has an answering partner,
+	// or if both old aggregator and new aggregator don't have answering partner
+	if (best_aggregator) {
+		if (last_active_aggregator && last_active_aggregator->lag_ports && last_active_aggregator->lag_ports->is_enabled &&
+		    (MAC_ADDRESS_COMPARE(&(last_active_aggregator->partner_system), &(null_mac_addr)) ||   // partner answers OR
+		     (!MAC_ADDRESS_COMPARE(&(last_active_aggregator->partner_system), &(null_mac_addr)) &&	// both old and new
+		      !MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr))))     // partner do not answer
+		   ) {
+			// if new aggregator has link, and old aggregator does not, replace old aggregator.(do nothing)
+			// -> don't replace otherwise.
+			if (!(!last_active_aggregator->actor_oper_aggregator_key && best_aggregator->actor_oper_aggregator_key)) {
+				best_aggregator=NULL;
+				last_active_aggregator->is_active = 1; // don't replace good old aggregator
+
+			}
+		}
+	}
+
+	// if there is new best aggregator, activate it
+	if (best_aggregator) {
+		for (aggregator = __get_first_agg(best_aggregator->lag_ports);
+		    aggregator;
+		    aggregator = __get_next_agg(aggregator)) {
+
+			BOND_PRINT_DBG(("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d",
+					aggregator->aggregator_identifier, aggregator->num_of_ports,
+					aggregator->actor_oper_aggregator_key, aggregator->partner_oper_aggregator_key,
+					aggregator->is_individual, aggregator->is_active));
+		}
+
+		// check if any partner replys
+		if (best_aggregator->is_individual) {
+			printk(KERN_WARNING "bonding: Warning: No 802.3ad response from the link partner "
+					"for any adapters in the bond\n");
+		}
+
+		// check if there are more than one aggregator
+		if (num_of_aggs > 1) {
+			BOND_PRINT_DBG(("Warning: More than one Link Aggregation Group was "
+					"found in the bond. Only one group will function in the bond"));
+		}
+
+		best_aggregator->is_active = 1;
+		BOND_PRINT_DBG(("LAG %d choosed as the active LAG", best_aggregator->aggregator_identifier));
+		BOND_PRINT_DBG(("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d",
+				best_aggregator->aggregator_identifier, best_aggregator->num_of_ports,
+				best_aggregator->actor_oper_aggregator_key, best_aggregator->partner_oper_aggregator_key,
+				best_aggregator->is_individual, best_aggregator->is_active));
+
+		// disable the ports that were related to the former active_aggregator
+		if (last_active_aggregator) {
+			for (port=last_active_aggregator->lag_ports; port; port=port->next_port_in_aggregator) {
+				__disable_port(port);
+			}
+		}
+	}
+
+	// if the selected aggregator is of join individuals(partner_system is NULL), enable their ports
+	active_aggregator = __get_active_agg(origin_aggregator);
+
+	if (active_aggregator) {
+		if (!MAC_ADDRESS_COMPARE(&(active_aggregator->partner_system), &(null_mac_addr))) {
+			for (port=active_aggregator->lag_ports; port; port=port->next_port_in_aggregator) {
+				__enable_port(port);
+			}
+		}
+	}
+}
+
+/**
+ * ad_clear_agg - clear a given aggregator's parameters
+ * @aggregator: the aggregator we're looking at
+ *
+ */
+static void ad_clear_agg(struct aggregator *aggregator)
+{
+	if (aggregator) {
+		aggregator->is_individual = 0;
+		aggregator->actor_admin_aggregator_key = 0;
+		aggregator->actor_oper_aggregator_key = 0;
+		aggregator->partner_system = null_mac_addr;
+		aggregator->partner_system_priority = 0;
+		aggregator->partner_oper_aggregator_key = 0;
+		aggregator->receive_state = 0;
+		aggregator->transmit_state = 0;
+		aggregator->lag_ports = NULL;
+		aggregator->is_active = 0;
+		aggregator->num_of_ports = 0;
+		BOND_PRINT_DBG(("LAG %d was cleared", aggregator->aggregator_identifier));
+	}
+}
+
+/**
+ * ad_initialize_agg - initialize a given aggregator's parameters
+ * @aggregator: the aggregator we're looking at
+ *
+ */
+static void ad_initialize_agg(struct aggregator *aggregator)
+{
+	if (aggregator) {
+		ad_clear_agg(aggregator);
+
+		aggregator->aggregator_mac_address = null_mac_addr;
+		aggregator->aggregator_identifier = 0;
+		aggregator->slave = NULL;
+	}
+}
+
+/**
+ * ad_initialize_port - initialize a given port's parameters
+ * @aggregator: the aggregator we're looking at
+ * @lacp_fast: boolean. whether fast periodic should be used
+ *
+ */
+static void ad_initialize_port(struct port *port, int lacp_fast)
+{
+	if (port) {
+		port->actor_port_number = 1;
+		port->actor_port_priority = 0xff;
+		port->actor_system = null_mac_addr;
+		port->actor_system_priority = 0xffff;
+		port->actor_port_aggregator_identifier = 0;
+		port->ntt = 0;
+		port->actor_admin_port_key = 1;
+		port->actor_oper_port_key  = 1;
+		port->actor_admin_port_state = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;
+		port->actor_oper_port_state  = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;
+
+		if (lacp_fast) {
+			port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
+		}
+
+		port->partner_admin_system = null_mac_addr;
+		port->partner_oper_system  = null_mac_addr;
+		port->partner_admin_system_priority = 0xffff;
+		port->partner_oper_system_priority  = 0xffff;
+		port->partner_admin_key = 1;
+		port->partner_oper_key  = 1;
+		port->partner_admin_port_number = 1;
+		port->partner_oper_port_number  = 1;
+		port->partner_admin_port_priority = 0xff;
+		port->partner_oper_port_priority  = 0xff;
+		port->partner_admin_port_state = 1;
+		port->partner_oper_port_state  = 1;
+		port->is_enabled = 1;
+		// ****** private parameters ******
+		port->sm_vars = 0x3;
+		port->sm_rx_state = 0;
+		port->sm_rx_timer_counter = 0;
+		port->sm_periodic_state = 0;
+		port->sm_periodic_timer_counter = 0;
+		port->sm_mux_state = 0;
+		port->sm_mux_timer_counter = 0;
+		port->sm_tx_state = 0;
+		port->sm_tx_timer_counter = 0;
+		port->slave = NULL;
+		port->aggregator = NULL;
+		port->next_port_in_aggregator = NULL;
+		port->transaction_id = 0;
+
+		ad_initialize_lacpdu(&(port->lacpdu));
+	}
+}
+
+/**
+ * ad_enable_collecting_distributing - enable a port's transmit/receive
+ * @port: the port we're looking at
+ *
+ * Enable @port if it's in an active aggregator
+ */
+static void ad_enable_collecting_distributing(struct port *port)
+{
+	if (port->aggregator->is_active) {
+		BOND_PRINT_DBG(("Enabling port %d(LAG %d)", port->actor_port_number, port->aggregator->aggregator_identifier));
+		__enable_port(port);
+	}
+}
+
+/**
+ * ad_disable_collecting_distributing - disable a port's transmit/receive
+ * @port: the port we're looking at
+ *
+ */
+static void ad_disable_collecting_distributing(struct port *port)
+{
+	if (port->aggregator && MAC_ADDRESS_COMPARE(&(port->aggregator->partner_system), &(null_mac_addr))) {
+		BOND_PRINT_DBG(("Disabling port %d(LAG %d)", port->actor_port_number, port->aggregator->aggregator_identifier));
+		__disable_port(port);
+	}
+}
+
+#if 0
+/**
+ * ad_marker_info_send - send a marker information frame
+ * @port: the port we're looking at
+ *
+ * This function does nothing since we decided not to implement send and handle
+ * response for marker PDU's, in this stage, but only to respond to marker
+ * information.
+ */
+static void ad_marker_info_send(struct port *port)
+{
+	struct marker marker;
+	u16 index;
+
+	// fill the marker PDU with the appropriate values
+	marker.subtype = 0x02;
+	marker.version_number = 0x01;
+	marker.tlv_type = AD_MARKER_INFORMATION_SUBTYPE;
+	marker.marker_length = 0x16;
+	// convert requester_port to Big Endian
+	marker.requester_port = (((port->actor_port_number & 0xFF) << 8) |((u16)(port->actor_port_number & 0xFF00) >> 8));
+	marker.requester_system = port->actor_system;
+	// convert requester_port(u32) to Big Endian
+	marker.requester_transaction_id = (((++port->transaction_id & 0xFF) << 24) |((port->transaction_id & 0xFF00) << 8) |((port->transaction_id & 0xFF0000) >> 8) |((port->transaction_id & 0xFF000000) >> 24));
+	marker.pad = 0;
+	marker.tlv_type_terminator = 0x00;
+	marker.terminator_length = 0x00;
+	for (index=0; index<90; index++) {
+		marker.reserved_90[index]=0;
+	}
+
+	// send the marker information
+	if (ad_marker_send(port, &marker) >= 0) {
+		BOND_PRINT_DBG(("Sent Marker Information on port %d", port->actor_port_number));
+	}
+}
+#endif
+
+/**
+ * ad_marker_info_received - handle receive of a Marker information frame
+ * @marker_info: Marker info received
+ * @port: the port we're looking at
+ *
+ */
+static void ad_marker_info_received(struct marker *marker_info,struct port *port)
+{
+	struct marker marker;
+
+	// copy the received marker data to the response marker
+	//marker = *marker_info;
+	memcpy(&marker, marker_info, sizeof(struct marker));
+	// change the marker subtype to marker response
+	marker.tlv_type=AD_MARKER_RESPONSE_SUBTYPE;
+	// send the marker response
+
+	if (ad_marker_send(port, &marker) >= 0) {
+		BOND_PRINT_DBG(("Sent Marker Response on port %d", port->actor_port_number));
+	}
+}
+
+/**
+ * ad_marker_response_received - handle receive of a marker response frame
+ * @marker: marker PDU received
+ * @port: the port we're looking at
+ *
+ * This function does nothing since we decided not to implement send and handle
+ * response for marker PDU's, in this stage, but only to respond to marker
+ * information.
+ */
+static void ad_marker_response_received(struct marker *marker, struct port *port)
+{
+	marker=NULL; // just to satisfy the compiler
+	port=NULL;  // just to satisfy the compiler
+	// DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW
+}
+
+/**
+ * ad_initialize_lacpdu - initialize a given lacpdu structure
+ * @lacpdu: lacpdu structure to initialize
+ *
+ */
+static void ad_initialize_lacpdu(struct lacpdu *lacpdu)
+{
+	u16 index;
+
+	// initialize lacpdu data
+	lacpdu->subtype = 0x01;
+	lacpdu->version_number = 0x01;
+	lacpdu->tlv_type_actor_info = 0x01;
+	lacpdu->actor_information_length = 0x14;
+	// lacpdu->actor_system_priority    updated on send
+	// lacpdu->actor_system             updated on send
+	// lacpdu->actor_key                updated on send
+	// lacpdu->actor_port_priority      updated on send
+	// lacpdu->actor_port               updated on send
+	// lacpdu->actor_state              updated on send
+	lacpdu->tlv_type_partner_info = 0x02;
+	lacpdu->partner_information_length = 0x14;
+	for (index=0; index<=2; index++) {
+		lacpdu->reserved_3_1[index]=0;
+	}
+	// lacpdu->partner_system_priority  updated on send
+	// lacpdu->partner_system           updated on send
+	// lacpdu->partner_key              updated on send
+	// lacpdu->partner_port_priority    updated on send
+	// lacpdu->partner_port             updated on send
+	// lacpdu->partner_state            updated on send
+	for (index=0; index<=2; index++) {
+		lacpdu->reserved_3_2[index]=0;
+	}
+	lacpdu->tlv_type_collector_info = 0x03;
+	lacpdu->collector_information_length= 0x10;
+	lacpdu->collector_max_delay = AD_COLLECTOR_MAX_DELAY;
+	for (index=0; index<=11; index++) {
+		lacpdu->reserved_12[index]=0;
+	}
+	lacpdu->tlv_type_terminator = 0x00;
+	lacpdu->terminator_length = 0;
+	for (index=0; index<=49; index++) {
+		lacpdu->reserved_50[index]=0;
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+// ================= AD exported functions to the main bonding code ==================
+//////////////////////////////////////////////////////////////////////////////////////
+
+// Check aggregators status in team every T seconds
+#define AD_AGGREGATOR_SELECTION_TIMER  8
+
+static u16 aggregator_identifier;
+
+/**
+ * bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures
+ * @bond: bonding struct to work on
+ * @tick_resolution: tick duration (millisecond resolution)
+ * @lacp_fast: boolean. whether fast periodic should be used
+ *
+ * Can be called only after the mac address of the bond is set.
+ */
+void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast)
+{                         
+	// check that the bond is not initialized yet
+	if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr), &(bond->device->dev_addr))) {
+
+		aggregator_identifier = 0;
+
+		BOND_AD_INFO(bond).lacp_fast = lacp_fast;
+		BOND_AD_INFO(bond).system.sys_priority = 0xFFFF;
+		BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->device->dev_addr);
+
+		// initialize how many times this module is called in one second(should be about every 100ms)
+		ad_ticks_per_sec = tick_resolution;
+
+		// initialize the aggregator selection timer(to activate an aggregation selection after initialize)
+		BOND_AD_INFO(bond).agg_select_timer = (AD_AGGREGATOR_SELECTION_TIMER * ad_ticks_per_sec);
+		BOND_AD_INFO(bond).agg_select_mode = AD_BANDWIDTH;
+	}
+}
+
+/**
+ * bond_3ad_bind_slave - initialize a slave's port
+ * @slave: slave struct to work on
+ *
+ * Returns:   0 on success
+ *          < 0 on error
+ */
+int bond_3ad_bind_slave(struct slave *slave)
+{
+	struct bonding *bond = bond_get_bond_by_slave(slave);
+	struct port *port;
+	struct aggregator *aggregator;
+
+	if (bond == NULL) {
+		printk(KERN_CRIT "The slave %s is not attached to its bond\n", slave->dev->name);
+		return -1;
+	}
+
+	//check that the slave has not been intialized yet.
+	if (SLAVE_AD_INFO(slave).port.slave != slave) {
+
+		// port initialization
+		port = &(SLAVE_AD_INFO(slave).port);
+
+		ad_initialize_port(port, BOND_AD_INFO(bond).lacp_fast);
+
+		port->slave = slave;
+		port->actor_port_number = SLAVE_AD_INFO(slave).id;
+		// key is determined according to the link speed, duplex and user key(which is yet not supported)
+		//              ------------------------------------------------------------
+		// Port key :   | User key                       |      Speed       |Duplex|
+		//              ------------------------------------------------------------
+		//              16                               6               1 0
+		port->actor_admin_port_key = 0;	// initialize this parameter
+		port->actor_admin_port_key |= __get_duplex(port);
+		port->actor_admin_port_key |= (__get_link_speed(port) << 1);
+		port->actor_oper_port_key = port->actor_admin_port_key;
+		// if the port is not full duplex, then the port should be not lacp Enabled
+		if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) {
+			port->sm_vars &= ~AD_PORT_LACP_ENABLED;
+		}
+		// actor system is the bond's system
+		port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr;
+		// tx timer(to verify that no more than MAX_TX_IN_SECOND lacpdu's are sent in one second)
+		port->sm_tx_timer_counter = ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
+		port->aggregator = NULL;
+		port->next_port_in_aggregator = NULL;
+
+		__disable_port(port);
+		__initialize_port_locks(port);
+
+
+		// aggregator initialization
+		aggregator = &(SLAVE_AD_INFO(slave).aggregator);
+
+		ad_initialize_agg(aggregator);
+
+		aggregator->aggregator_mac_address = *((struct mac_addr *)bond->device->dev_addr);
+		aggregator->aggregator_identifier = (++aggregator_identifier);
+		aggregator->slave = slave;
+		aggregator->is_active = 0;
+		aggregator->num_of_ports = 0;
+	}
+
+	return 0;
+}
+
+/**
+ * bond_3ad_unbind_slave - deinitialize a slave's port
+ * @slave: slave struct to work on
+ *
+ * Search for the aggregator that is related to this port, remove the
+ * aggregator and assign another aggregator for other port related to it
+ * (if any), and remove the port.
+ */
+void bond_3ad_unbind_slave(struct slave *slave)
+{
+	struct port *port, *prev_port, *temp_port;
+	struct aggregator *aggregator, *new_aggregator, *temp_aggregator;
+	int select_new_active_agg = 0;
+	
+	// find the aggregator related to this slave
+	aggregator = &(SLAVE_AD_INFO(slave).aggregator);
+
+	// find the port related to this slave
+	port = &(SLAVE_AD_INFO(slave).port);
+
+	// if slave is null, the whole port is not initialized
+	if (!port->slave) {
+		printk(KERN_WARNING "bonding: Trying to unbind an uninitialized port on %s\n", slave->dev->name);
+		return;
+	}
+
+	// disable the port
+	ad_disable_collecting_distributing(port);
+
+	// deinitialize port's locks if necessary(os-specific)
+	__deinitialize_port_locks(port);
+
+	BOND_PRINT_DBG(("Unbinding Link Aggregation Group %d", aggregator->aggregator_identifier));
+	// check if this aggregator is occupied
+	if (aggregator->lag_ports) {
+		// check if there are other ports related to this aggregator except
+		// the port related to this slave(thats ensure us that there is a
+		// reason to search for new aggregator, and that we will find one
+		if ((aggregator->lag_ports != port) || (aggregator->lag_ports->next_port_in_aggregator)) {
+			// find new aggregator for the related port(s)
+			new_aggregator = __get_first_agg(port);
+			for (; new_aggregator; new_aggregator = __get_next_agg(new_aggregator)) {
+				// if the new aggregator is empty, or it connected to to our port only
+				if (!new_aggregator->lag_ports || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator)) {
+					break;
+				}
+			}
+			// if new aggregator found, copy the aggregator's parameters
+			// and connect the related lag_ports to the new aggregator
+			if ((new_aggregator) && ((!new_aggregator->lag_ports) || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator))) {
+				BOND_PRINT_DBG(("Some port(s) related to LAG %d - replaceing with LAG %d", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier));
+
+				if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) {
+					printk(KERN_INFO "bonding: Removing an active aggregator\n");
+					// select new active aggregator
+					 select_new_active_agg = 1;
+				}
+
+				new_aggregator->is_individual = aggregator->is_individual;
+				new_aggregator->actor_admin_aggregator_key = aggregator->actor_admin_aggregator_key;
+				new_aggregator->actor_oper_aggregator_key = aggregator->actor_oper_aggregator_key;
+				new_aggregator->partner_system = aggregator->partner_system;
+				new_aggregator->partner_system_priority = aggregator->partner_system_priority;
+				new_aggregator->partner_oper_aggregator_key = aggregator->partner_oper_aggregator_key;
+				new_aggregator->receive_state = aggregator->receive_state;
+				new_aggregator->transmit_state = aggregator->transmit_state;
+				new_aggregator->lag_ports = aggregator->lag_ports;
+				new_aggregator->is_active = aggregator->is_active;
+				new_aggregator->num_of_ports = aggregator->num_of_ports;
+
+				// update the information that is written on the ports about the aggregator
+				for (temp_port=aggregator->lag_ports; temp_port; temp_port=temp_port->next_port_in_aggregator) {
+					temp_port->aggregator=new_aggregator;
+					temp_port->actor_port_aggregator_identifier = new_aggregator->aggregator_identifier;
+				}
+
+				// clear the aggregator
+				ad_clear_agg(aggregator);
+				
+				if (select_new_active_agg) {
+					ad_agg_selection_logic(__get_first_agg(port));
+				}
+			} else {
+				printk(KERN_WARNING "bonding: Warning: unbinding aggregator, "
+				       "and could not find a new aggregator for its ports\n");
+			}
+		} else { // in case that the only port related to this aggregator is the one we want to remove
+			select_new_active_agg = aggregator->is_active;
+			// clear the aggregator
+			ad_clear_agg(aggregator);
+			if (select_new_active_agg) {
+				printk(KERN_INFO "Removing an active aggregator\n");
+				// select new active aggregator
+				ad_agg_selection_logic(__get_first_agg(port));
+			}
+		}
+	}
+
+	BOND_PRINT_DBG(("Unbinding port %d", port->actor_port_number));
+	// find the aggregator that this port is connected to
+	temp_aggregator = __get_first_agg(port);
+	for (; temp_aggregator; temp_aggregator = __get_next_agg(temp_aggregator)) {
+		prev_port = NULL;
+		// search the port in the aggregator's related ports
+		for (temp_port=temp_aggregator->lag_ports; temp_port; prev_port=temp_port, temp_port=temp_port->next_port_in_aggregator) {
+			if (temp_port == port) { // the aggregator found - detach the port from this aggregator
+				if (prev_port) {
+					prev_port->next_port_in_aggregator = temp_port->next_port_in_aggregator;
+				} else {
+					temp_aggregator->lag_ports = temp_port->next_port_in_aggregator;
+				}
+				temp_aggregator->num_of_ports--;
+				if (temp_aggregator->num_of_ports==0) {
+					select_new_active_agg = temp_aggregator->is_active;
+					// clear the aggregator
+					ad_clear_agg(temp_aggregator);
+					if (select_new_active_agg) {
+						printk(KERN_INFO "Removing an active aggregator\n");
+						// select new active aggregator
+						ad_agg_selection_logic(__get_first_agg(port));
+					}
+				}
+				break;
+			}
+		}
+	}
+	port->slave=NULL;	
+}
+
+/**
+ * bond_3ad_state_machine_handler - handle state machines timeout
+ * @bond: bonding struct to work on
+ *
+ * The state machine handling concept in this module is to check every tick
+ * which state machine should operate any function. The execution order is
+ * round robin, so when we have an interaction between state machines, the
+ * reply of one to each other might be delayed until next tick.
+ *
+ * This function also complete the initialization when the agg_select_timer
+ * times out, and it selects an aggregator for the ports that are yet not
+ * related to any aggregator, and selects the active aggregator for a bond.
+ */
+void bond_3ad_state_machine_handler(struct bonding *bond)
+{
+	struct port *port;
+	struct aggregator *aggregator;
+
+	read_lock(&bond->lock);
+
+	//check if there are any slaves
+	if (bond->next == (struct slave *)bond) {
+		goto end;
+	}
+
+	if ((bond->device->flags & IFF_UP) != IFF_UP) {
+		goto end;
+	}
+
+	// check if agg_select_timer timer after initialize is timed out
+	if (BOND_AD_INFO(bond).agg_select_timer && !(--BOND_AD_INFO(bond).agg_select_timer)) {
+		// select the active aggregator for the bond
+		if ((port = __get_first_port(bond))) {
+			if (!port->slave) {
+				printk(KERN_WARNING "bonding: Warning: bond's first port is uninitialized\n");
+				goto end;
+			}
+
+			aggregator = __get_first_agg(port);
+			ad_agg_selection_logic(aggregator);
+		}
+	}
+
+	// for each port run the state machines
+	for (port = __get_first_port(bond); port; port = __get_next_port(port)) {
+		if (!port->slave) {
+			printk(KERN_WARNING "bonding: Warning: Found an uninitialized port\n");
+			goto end;
+		}
+
+		ad_rx_machine(NULL, port);
+		ad_periodic_machine(port);
+		ad_port_selection_logic(port);
+		ad_mux_machine(port);
+		ad_tx_machine(port);
+
+		// turn off the BEGIN bit, since we already handled it
+		if (port->sm_vars & AD_PORT_BEGIN) {
+			port->sm_vars &= ~AD_PORT_BEGIN;
+		}
+	}
+
+end:
+	read_unlock(&bond->lock);
+
+
+	if ((bond->device->flags & IFF_UP) == IFF_UP) {
+		/* re-arm the timer */
+		mod_timer(&(BOND_AD_INFO(bond).ad_timer), jiffies + (AD_TIMER_INTERVAL * HZ / 1000));
+	}
+}
+
+/**
+ * bond_3ad_rx_indication - handle a received frame
+ * @lacpdu: received lacpdu
+ * @slave: slave struct to work on
+ * @length: length of the data received
+ *
+ * It is assumed that frames that were sent on this NIC don't returned as new
+ * received frames (loopback). Since only the payload is given to this
+ * function, it check for loopback.
+ */
+void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length)
+{
+	struct port *port;
+
+	if (length >= sizeof(struct lacpdu)) {
+
+		port = &(SLAVE_AD_INFO(slave).port);
+
+		if (!port->slave) {
+			printk(KERN_WARNING "bonding: Warning: port of slave %s is uninitialized\n", slave->dev->name);
+			return;
+		}
+
+		switch (lacpdu->subtype) {
+		case AD_TYPE_LACPDU:
+			__ntohs_lacpdu(lacpdu);
+			BOND_PRINT_DBG(("Received LACPDU on port %d", port->actor_port_number));
+			ad_rx_machine(lacpdu, port);
+			break;
+
+		case AD_TYPE_MARKER:
+			// No need to convert fields to Little Endian since we don't use the marker's fields.
+
+			switch (((struct marker *)lacpdu)->tlv_type) {
+			case AD_MARKER_INFORMATION_SUBTYPE:
+				BOND_PRINT_DBG(("Received Marker Information on port %d", port->actor_port_number));
+				ad_marker_info_received((struct marker *)lacpdu, port);
+				break;
+
+			case AD_MARKER_RESPONSE_SUBTYPE:
+				BOND_PRINT_DBG(("Received Marker Response on port %d", port->actor_port_number));
+				ad_marker_response_received((struct marker *)lacpdu, port);
+				break;
+
+			default:
+				BOND_PRINT_DBG(("Received an unknown Marker subtype on slot %d", port->actor_port_number));
+			}
+		}
+	}
+}
+
+/**
+ * bond_3ad_adapter_speed_changed - handle a slave's speed change indication
+ * @slave: slave struct to work on
+ *
+ * Handle reselection of aggregator (if needed) for this port.
+ */
+void bond_3ad_adapter_speed_changed(struct slave *slave)
+{
+	struct port *port;
+
+	port = &(SLAVE_AD_INFO(slave).port);
+
+	// if slave is null, the whole port is not initialized
+	if (!port->slave) {
+		printk(KERN_WARNING "bonding: Warning: speed changed for uninitialized port on %s\n",
+		       slave->dev->name);
+		return;
+	}
+
+	port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
+	port->actor_oper_port_key=port->actor_admin_port_key |= (__get_link_speed(port) << 1);
+	BOND_PRINT_DBG(("Port %d changed speed", port->actor_port_number));
+	// there is no need to reselect a new aggregator, just signal the
+	// state machines to reinitialize
+	port->sm_vars |= AD_PORT_BEGIN;
+}
+
+/**
+ * bond_3ad_adapter_duplex_changed - handle a slave's duplex change indication
+ * @slave: slave struct to work on
+ *
+ * Handle reselection of aggregator (if needed) for this port.
+ */
+void bond_3ad_adapter_duplex_changed(struct slave *slave)
+{
+	struct port *port;
+
+	port=&(SLAVE_AD_INFO(slave).port);
+
+	// if slave is null, the whole port is not initialized
+	if (!port->slave) {
+		printk(KERN_WARNING "bonding: Warning: duplex changed for uninitialized port on %s\n",
+		       slave->dev->name);
+		return;
+	}
+
+	port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
+	port->actor_oper_port_key=port->actor_admin_port_key |= __get_duplex(port);
+	BOND_PRINT_DBG(("Port %d changed duplex", port->actor_port_number));
+	// there is no need to reselect a new aggregator, just signal the
+	// state machines to reinitialize
+	port->sm_vars |= AD_PORT_BEGIN;
+}
+
+/**
+ * bond_3ad_handle_link_change - handle a slave's link status change indication
+ * @slave: slave struct to work on
+ * @status: whether the link is now up or down
+ *
+ * Handle reselection of aggregator (if needed) for this port.
+ */
+void bond_3ad_handle_link_change(struct slave *slave, char link)
+{
+	struct port *port;
+
+	port = &(SLAVE_AD_INFO(slave).port);
+
+	// if slave is null, the whole port is not initialized
+	if (!port->slave) {
+#ifdef BONDING_DEBUG
+		printk(KERN_WARNING "bonding: Warning: link status changed for uninitialized port on %s\n",
+		       slave->dev->name);
+#endif
+		return;
+	}
+
+	// on link down we are zeroing duplex and speed since some of the adaptors(ce1000.lan) report full duplex/speed instead of N/A(duplex) / 0(speed)
+	// on link up we are forcing recheck on the duplex and speed since some of he adaptors(ce1000.lan) report
+	if (link == BOND_LINK_UP) {
+		port->is_enabled = 1;
+		port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
+		port->actor_oper_port_key=port->actor_admin_port_key |= __get_duplex(port);
+		port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
+		port->actor_oper_port_key=port->actor_admin_port_key |= (__get_link_speed(port) << 1);
+	} else {
+		/* link has failed */
+		port->is_enabled = 0;
+		port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
+		port->actor_oper_port_key= (port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS);
+	}
+	//BOND_PRINT_DBG(("Port %d changed link status to %s", port->actor_port_number, ((link == BOND_LINK_UP)?"UP":"DOWN")));
+	// there is no need to reselect a new aggregator, just signal the
+	// state machines to reinitialize
+	port->sm_vars |= AD_PORT_BEGIN;
+}
+
+/**
+ * bond_3ad_get_active_agg_info - get information of the active aggregator
+ * @bond: bonding struct to work on
+ * @ad_info: ad_info struct to fill with the bond's info
+ *
+ * Returns:   0 on success
+ *          < 0 on error
+ */
+int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
+{
+	struct aggregator *aggregator = NULL;
+	struct port *port;
+
+	for (port = __get_first_port(bond); port; port = __get_next_port(port)) {
+		if (port->aggregator && port->aggregator->is_active) {
+			aggregator = port->aggregator;
+			break;
+		}
+	}
+
+	if (aggregator) {
+		ad_info->aggregator_id = aggregator->aggregator_identifier;
+		ad_info->ports = aggregator->num_of_ports;
+		ad_info->actor_key = aggregator->actor_oper_aggregator_key;
+		ad_info->partner_key = aggregator->partner_oper_aggregator_key;
+		memcpy(ad_info->partner_system, aggregator->partner_system.mac_addr_value, ETH_ALEN);
+		return 0;
+	}
+
+	return -1;
+}
+
+int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
+{
+	slave_t *slave, *start_at;
+	struct bonding *bond = (struct bonding *) dev->priv;
+	struct ethhdr *data = (struct ethhdr *)skb->data;
+	int slave_agg_no;
+	int slaves_in_agg;
+	int agg_id;
+	struct ad_info ad_info;
+
+	if (!IS_UP(dev)) { /* bond down */
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	if (bond == NULL) {
+		printk(KERN_CRIT "bonding: Error: bond is NULL on device %s\n", dev->name);
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	read_lock(&bond->lock);
+	slave = bond->prev;
+
+	/* check if bond is empty */
+	if ((slave == (struct slave *) bond) || (bond->slave_cnt == 0)) {
+		printk(KERN_DEBUG "ERROR: bond is empty\n");
+		dev_kfree_skb(skb);
+		read_unlock(&bond->lock);
+		return 0;
+	}
+
+	if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
+		printk(KERN_DEBUG "ERROR: bond_3ad_get_active_agg_info failed\n");
+		dev_kfree_skb(skb);
+		read_unlock(&bond->lock);
+		return 0;
+	}
+
+	slaves_in_agg = ad_info.ports;
+	agg_id = ad_info.aggregator_id;
+
+	if (slaves_in_agg == 0) {
+		/*the aggregator is empty*/
+		printk(KERN_DEBUG "ERROR: active aggregator is empty\n");
+		dev_kfree_skb(skb);
+		read_unlock(&bond->lock);
+		return 0;
+	}
+
+	/* we're at the root, get the first slave */
+	if ((slave == NULL) || (slave->dev == NULL)) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+		read_unlock(&bond->lock);
+		return 0;
+	}
+
+	slave_agg_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % slaves_in_agg;
+	while (slave != (slave_t *)bond) {
+		struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
+
+		if (agg && (agg->aggregator_identifier == agg_id)) {
+			slave_agg_no--;
+			if (slave_agg_no < 0) {
+				break;
+			}
+		}
+
+		slave = slave->prev;
+		if (slave == NULL) {
+			printk(KERN_ERR "bonding: Error: slave is NULL\n");
+			dev_kfree_skb(skb);
+			read_unlock(&bond->lock);
+			return 0;
+		}
+	}
+
+	if (slave == (slave_t *)bond) {
+		printk(KERN_ERR "bonding: Error: Couldn't find a slave to tx on for aggregator ID %d\n", agg_id);
+		dev_kfree_skb(skb);
+		read_unlock(&bond->lock);
+		return 0;
+	}
+
+	start_at = slave;
+
+	do {
+		int slave_agg_id = 0;
+		struct aggregator *agg;
+
+		if (slave == NULL) {
+			printk(KERN_ERR "bonding: Error: slave is NULL\n");
+			dev_kfree_skb(skb);
+			read_unlock(&bond->lock);
+			return 0;
+		}
+
+		agg = SLAVE_AD_INFO(slave).port.aggregator;
+
+		if (agg) {
+			slave_agg_id = agg->aggregator_identifier;
+		}
+
+		if (SLAVE_IS_OK(slave) && 
+		    agg && (slave_agg_id == agg_id)) {
+			skb->dev = slave->dev;			
+			skb->priority = 1;
+			dev_queue_xmit(skb);
+			read_unlock(&bond->lock);
+			return 0;
+		}
+	} while ((slave = slave->next) != start_at);
+
+	/* no suitable interface, frame not sent */
+	dev_kfree_skb(skb);
+	read_unlock(&bond->lock);
+	return 0;
+}
+
+int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype)
+{
+	struct bonding *bond = (struct bonding *)dev->priv;
+	struct slave *slave = NULL;
+	int ret = NET_RX_DROP;
+
+	if (!(dev->flags & IFF_MASTER)) {
+		goto out;
+	}
+
+	read_lock(&bond->lock);
+	slave = bond_get_slave_by_dev((struct bonding *)dev->priv,
+				      skb->real_dev);
+	if (slave == NULL) {
+		goto out_unlock;
+	}
+
+	bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len);
+
+	ret = NET_RX_SUCCESS;
+
+out_unlock:
+	read_unlock(&bond->lock);
+out:
+	dev_kfree_skb(skb);
+
+	return ret;
+}
+
diff -urN linux-2.5.69-bk18/drivers/net/bonding/bond_3ad.h linux-2.5.69-bk19/drivers/net/bonding/bond_3ad.h
--- linux-2.5.69-bk18/drivers/net/bonding/bond_3ad.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/drivers/net/bonding/bond_3ad.h	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,298 @@
+/*
+ * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ *
+ * Changes:
+ *
+ * 2003/05/01 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
+ *		Amir Noam <amir.noam at intel dot com>
+ *	- Added support for lacp_rate module param.
+ *
+ * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Renamed bond_3ad_link_status_changed() to
+ *	  bond_3ad_handle_link_change() for compatibility with TLB.
+ */
+
+#ifndef __BOND_3AD_H__
+#define __BOND_3AD_H__
+
+#include <asm/byteorder.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+// General definitions
+#define BOND_ETH_P_LACPDU       0x8809
+#define PKT_TYPE_LACPDU         __constant_htons(BOND_ETH_P_LACPDU)
+#define AD_TIMER_INTERVAL       100 /*msec*/
+
+#define MULTICAST_LACPDU_ADDR    {0x01, 0x80, 0xC2, 0x00, 0x00, 0x02}
+#define AD_MULTICAST_LACPDU_ADDR    {MULTICAST_LACPDU_ADDR}
+
+#define AD_LACP_SLOW 0
+#define AD_LACP_FAST 1
+
+typedef struct mac_addr {
+	u8 mac_addr_value[ETH_ALEN];
+} mac_addr_t;
+
+typedef enum {
+	AD_BANDWIDTH = 0,
+	AD_COUNT
+} agg_selection_t;
+
+// rx machine states(43.4.11 in the 802.3ad standard)
+typedef enum {
+	AD_RX_DUMMY,
+	AD_RX_INITIALIZE,     // rx Machine
+	AD_RX_PORT_DISABLED,  // rx Machine
+	AD_RX_LACP_DISABLED,  // rx Machine
+	AD_RX_EXPIRED,	      // rx Machine
+	AD_RX_DEFAULTED,      // rx Machine
+	AD_RX_CURRENT	      // rx Machine
+} rx_states_t;
+
+// periodic machine states(43.4.12 in the 802.3ad standard)
+typedef enum {
+	AD_PERIODIC_DUMMY,
+	AD_NO_PERIODIC,	       // periodic machine
+	AD_FAST_PERIODIC,      // periodic machine
+	AD_SLOW_PERIODIC,      // periodic machine
+	AD_PERIODIC_TX	   // periodic machine
+} periodic_states_t;
+
+// mux machine states(43.4.13 in the 802.3ad standard)
+typedef enum {
+	AD_MUX_DUMMY,
+	AD_MUX_DETACHED,       // mux machine
+	AD_MUX_WAITING,	       // mux machine
+	AD_MUX_ATTACHED,       // mux machine
+	AD_MUX_COLLECTING_DISTRIBUTING // mux machine
+} mux_states_t;
+
+// tx machine states(43.4.15 in the 802.3ad standard)
+typedef enum {
+	AD_TX_DUMMY,
+	AD_TRANSMIT	   // tx Machine
+} tx_states_t;
+
+// rx indication types
+typedef enum {
+	AD_TYPE_LACPDU = 1,    // type lacpdu
+	AD_TYPE_MARKER	   // type marker
+} pdu_type_t;
+
+// rx marker indication types
+typedef enum {
+	AD_MARKER_INFORMATION_SUBTYPE = 1, // marker imformation subtype
+	AD_MARKER_RESPONSE_SUBTYPE     // marker response subtype
+} marker_subtype_t;
+
+// timers types(43.4.9 in the 802.3ad standard)
+typedef enum {
+	AD_CURRENT_WHILE_TIMER,
+	AD_ACTOR_CHURN_TIMER,
+	AD_PERIODIC_TIMER,
+	AD_PARTNER_CHURN_TIMER,
+	AD_WAIT_WHILE_TIMER
+} ad_timers_t;
+
+#pragma pack(1)
+
+typedef struct ad_header {
+	struct mac_addr destination_address;
+	struct mac_addr source_address;
+	u16 length_type;
+} ad_header_t;
+
+// Link Aggregation Control Protocol(LACP) data unit structure(43.4.2.2 in the 802.3ad standard)
+typedef struct lacpdu {
+	u8 subtype;		     // = LACP(= 0x01)
+	u8 version_number;
+	u8 tlv_type_actor_info;	      // = actor information(type/length/value)
+	u8 actor_information_length; // = 20
+	u16 actor_system_priority;
+	struct mac_addr actor_system;
+	u16 actor_key;
+	u16 actor_port_priority;
+	u16 actor_port;
+	u8 actor_state;
+	u8 reserved_3_1[3];	     // = 0
+	u8 tlv_type_partner_info;     // = partner information
+	u8 partner_information_length;	 // = 20
+	u16 partner_system_priority;
+	struct mac_addr partner_system;
+	u16 partner_key;
+	u16 partner_port_priority;
+	u16 partner_port;
+	u8 partner_state;
+	u8 reserved_3_2[3];	     // = 0
+	u8 tlv_type_collector_info;	  // = collector information
+	u8 collector_information_length; // = 16
+	u16 collector_max_delay;
+	u8 reserved_12[12];
+	u8 tlv_type_terminator;	     // = terminator
+	u8 terminator_length;	     // = 0
+	u8 reserved_50[50];	     // = 0
+} lacpdu_t;
+
+typedef struct lacpdu_header {
+	struct ad_header ad_header;
+	struct lacpdu lacpdu;
+} lacpdu_header_t;
+
+// Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard)
+typedef struct marker {
+	u8 subtype;		 //  = 0x02  (marker PDU)
+	u8 version_number;	 //  = 0x01
+	u8 tlv_type;		 //  = 0x01  (marker information)
+	//  = 0x02  (marker response information)
+	u8 marker_length;	 //  = 0x16
+	u16 requester_port;	 //   The number assigned to the port by the requester
+	struct mac_addr requester_system;      //   The requester’s system id
+	u32 requester_transaction_id;	//   The transaction id allocated by the requester,
+	u16 pad;		 //  = 0
+	u8 tlv_type_terminator;	     //  = 0x00
+	u8 terminator_length;	     //  = 0x00
+	u8 reserved_90[90];	     //  = 0
+} marker_t;
+
+typedef struct marker_header {
+	struct ad_header ad_header;
+	struct marker marker;
+} marker_header_t;
+
+#pragma pack()
+
+struct slave;
+struct bonding;
+struct ad_info;
+struct port;
+
+#ifdef __ia64__
+#pragma pack(8)
+#endif
+
+// aggregator structure(43.4.5 in the 802.3ad standard)
+typedef struct aggregator {
+	struct mac_addr aggregator_mac_address;
+	u16 aggregator_identifier;
+	u16 is_individual;		 // BOOLEAN
+	u16 actor_admin_aggregator_key;
+	u16 actor_oper_aggregator_key;
+	struct mac_addr partner_system;
+	u16 partner_system_priority;
+	u16 partner_oper_aggregator_key;
+	u16 receive_state;		// BOOLEAN
+	u16 transmit_state;		// BOOLEAN
+	struct port *lag_ports;
+	// ****** PRIVATE PARAMETERS ******
+	struct slave *slave;	    // pointer to the bond slave that this aggregator belongs to
+	u16 is_active;	    // BOOLEAN. Indicates if this aggregator is active
+	u16 num_of_ports;
+} aggregator_t;
+
+// port structure(43.4.6 in the 802.3ad standard)
+typedef struct port {
+	u16 actor_port_number;
+	u16 actor_port_priority;
+	struct mac_addr actor_system;	       // This parameter is added here although it is not specified in the standard, just for simplification
+	u16 actor_system_priority;	 // This parameter is added here although it is not specified in the standard, just for simplification
+	u16 actor_port_aggregator_identifier;
+	u16 ntt;			 // BOOLEAN
+	u16 actor_admin_port_key;
+	u16 actor_oper_port_key;
+	u8 actor_admin_port_state;
+	u8 actor_oper_port_state;
+	struct mac_addr partner_admin_system;
+	struct mac_addr partner_oper_system;
+	u16 partner_admin_system_priority;
+	u16 partner_oper_system_priority;
+	u16 partner_admin_key;
+	u16 partner_oper_key;
+	u16 partner_admin_port_number;
+	u16 partner_oper_port_number;
+	u16 partner_admin_port_priority;
+	u16 partner_oper_port_priority;
+	u8 partner_admin_port_state;
+	u8 partner_oper_port_state;
+	u16 is_enabled;	      // BOOLEAN
+	// ****** PRIVATE PARAMETERS ******
+	u16 sm_vars;	      // all state machines variables for this port
+	rx_states_t sm_rx_state;	// state machine rx state
+	u16 sm_rx_timer_counter;    // state machine rx timer counter
+	periodic_states_t sm_periodic_state;// state machine periodic state
+	u16 sm_periodic_timer_counter;	// state machine periodic timer counter
+	mux_states_t sm_mux_state;	// state machine mux state
+	u16 sm_mux_timer_counter;   // state machine mux timer counter
+	tx_states_t sm_tx_state;	// state machine tx state
+	u16 sm_tx_timer_counter;    // state machine tx timer counter(allways on - enter to transmit state 3 time per second)
+	struct slave *slave;	    // pointer to the bond slave that this port belongs to
+	struct aggregator *aggregator;	   // pointer to an aggregator that this port related to
+	struct port *next_port_in_aggregator; // Next port on the linked list of the parent aggregator
+	u32 transaction_id;	    // continuous number for identification of Marker PDU's;
+	struct lacpdu lacpdu;	       // the lacpdu that will be sent for this port
+} port_t;
+
+// system structure
+typedef struct ad_system {
+	u16 sys_priority;
+	struct mac_addr sys_mac_addr;
+} ad_system_t;
+
+#ifdef __ia64__
+#pragma pack()
+#endif
+
+// ================= AD Exported structures to the main bonding code ==================
+#define BOND_AD_INFO(bond)   ((bond)->ad_info)
+#define SLAVE_AD_INFO(slave) ((slave)->ad_info)
+
+struct ad_bond_info {
+	ad_system_t system;	    // 802.3ad system structure
+	u32 agg_select_timer;	    // Timer to select aggregator after all adapter's hand shakes
+	u32 agg_select_mode;	    // Mode of selection of active aggregator(bandwidth/count)
+	int lacp_fast;		/* whether fast periodic tx should be
+				 * requested
+				 */
+	struct timer_list ad_timer;
+	struct packet_type ad_pkt_type;
+};
+
+struct ad_slave_info {
+	struct aggregator aggregator;	    // 802.3ad aggregator structure
+	struct port port;		    // 802.3ad port structure
+	spinlock_t rx_machine_lock; // To avoid race condition between callback and receive interrupt
+	u16 id;
+};
+
+// ================= AD Exported functions to the main bonding code ==================
+void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast);
+int  bond_3ad_bind_slave(struct slave *slave);
+void bond_3ad_unbind_slave(struct slave *slave);
+void bond_3ad_state_machine_handler(struct bonding *bond);
+void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length);
+void bond_3ad_adapter_speed_changed(struct slave *slave);
+void bond_3ad_adapter_duplex_changed(struct slave *slave);
+void bond_3ad_handle_link_change(struct slave *slave, char link);
+int  bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info);
+int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev);
+int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype);
+#endif //__BOND_3AD_H__
+
diff -urN linux-2.5.69-bk18/drivers/net/bonding/bond_alb.c linux-2.5.69-bk19/drivers/net/bonding/bond_alb.c
--- linux-2.5.69-bk18/drivers/net/bonding/bond_alb.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/drivers/net/bonding/bond_alb.c	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,1571 @@
+/*
+ * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ */
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/pkt_sched.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/if_bonding.h>
+#include <net/ipx.h>
+#include <net/arp.h>
+#include <asm/byteorder.h>
+#include "bonding.h"
+#include "bond_alb.h"
+
+
+#define ALB_TIMER_TICKS_PER_SEC	    10	/* should be a divisor of HZ */
+#define BOND_TLB_REBALANCE_INTERVAL 10	/* in seconds, periodic re-balancing
+					 * used for division - never set
+					 * to zero !!!
+					 */
+#define BOND_ALB_LP_INTERVAL	    1	/* in seconds periodic send of
+					 * learning packets to the switch
+					 */
+
+#define BOND_TLB_REBALANCE_TICKS (BOND_TLB_REBALANCE_INTERVAL \
+				  * ALB_TIMER_TICKS_PER_SEC)
+
+#define BOND_ALB_LP_TICKS (BOND_ALB_LP_INTERVAL \
+			   * ALB_TIMER_TICKS_PER_SEC)
+
+#define TLB_HASH_TABLE_SIZE 256	/* The size of the clients hash table.
+				 * Note that this value MUST NOT be smaller
+				 * because the key hash table BYTE wide !
+				 */
+
+
+#define TLB_NULL_INDEX		0xffffffff
+#define MAX_LP_RETRY		3
+
+/* rlb defs */
+#define RLB_HASH_TABLE_SIZE	256
+#define RLB_NULL_INDEX		0xffffffff
+#define RLB_UPDATE_DELAY	2*ALB_TIMER_TICKS_PER_SEC /* 2 seconds */
+#define RLB_ARP_BURST_SIZE	2
+#define RLB_UPDATE_RETRY	3	/* 3-ticks - must be smaller than the rlb
+					 * rebalance interval (5 min).
+					 */
+/* RLB_PROMISC_TIMEOUT = 10 sec equals the time that the current slave is
+ * promiscuous after failover
+ */
+#define RLB_PROMISC_TIMEOUT	10*ALB_TIMER_TICKS_PER_SEC
+
+#pragma pack(1)
+struct learning_pkt {
+	u8 mac_dst[ETH_ALEN];
+	u8 mac_src[ETH_ALEN];
+	u16 type;
+	u8 padding[ETH_ZLEN - (2*ETH_ALEN + 2)];
+};
+
+struct arp_pkt {
+	u16     hw_addr_space;
+	u16     prot_addr_space;
+	u8      hw_addr_len;
+	u8      prot_addr_len;
+	u16     op_code;
+	u8      mac_src[ETH_ALEN];	/* sender hardware address */
+	u32     ip_src;			/* sender IP address */
+	u8      mac_dst[ETH_ALEN];	/* target hardware address */
+	u32     ip_dst;			/* target IP address */
+};
+#pragma pack()
+
+/* Forward declaration */
+static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]);
+
+static inline u8
+_simple_hash(u8 *hash_start, int hash_size)
+{
+	int i;
+	u8 hash = 0;
+
+	for (i=0; i<hash_size; i++) {
+		hash ^= hash_start[i];
+	}
+
+	return hash;
+}
+
+/*********************** tlb specific functions ***************************/
+
+static inline void
+_lock_tx_hashtbl(struct bonding *bond)
+{
+	spin_lock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
+}
+
+static inline void
+_unlock_tx_hashtbl(struct bonding *bond)
+{
+	spin_unlock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
+}
+
+/* Caller must hold tx_hashtbl lock */
+static inline void
+tlb_init_table_entry(struct bonding *bond, u8 index, u8 save_load)
+{
+	struct tlb_client_info *entry;
+
+	if (BOND_ALB_INFO(bond).tx_hashtbl == NULL) {
+		return;
+	}
+
+	entry = &(BOND_ALB_INFO(bond).tx_hashtbl[index]);
+	/* at end of cycle, save the load that was transmitted to the client
+	 * during the cycle, and set the tx_bytes counter to 0 for counting
+	 * the load during the next cycle
+	 */
+	if (save_load) {
+		entry->load_history = 1 + entry->tx_bytes /
+			BOND_TLB_REBALANCE_INTERVAL;
+		entry->tx_bytes = 0;
+	}
+	entry->tx_slave = NULL;
+	entry->next = TLB_NULL_INDEX;
+	entry->prev = TLB_NULL_INDEX;
+}
+
+static inline void
+tlb_init_slave(struct slave *slave)
+{
+	struct tlb_slave_info *slave_info = &(SLAVE_TLB_INFO(slave));
+
+	slave_info->load = 0;
+	slave_info->head = TLB_NULL_INDEX;
+}
+
+/* Caller must hold bond lock for read */
+static inline void
+tlb_clear_slave(struct bonding *bond, struct slave *slave, u8 save_load)
+{
+	struct tlb_client_info *tx_hash_table = NULL;
+	u32 index, next_index;
+
+	/* clear slave from tx_hashtbl */
+	_lock_tx_hashtbl(bond);
+	tx_hash_table = BOND_ALB_INFO(bond).tx_hashtbl;
+
+	if (tx_hash_table) {
+		index = SLAVE_TLB_INFO(slave).head;
+		while (index != TLB_NULL_INDEX) {
+			next_index = tx_hash_table[index].next;
+			tlb_init_table_entry(bond, index, save_load);
+			index = next_index;
+		}
+	}
+	_unlock_tx_hashtbl(bond);
+
+	tlb_init_slave(slave);
+}
+
+/* Must be called before starting the monitor timer */
+static int
+tlb_initialize(struct bonding *bond)
+{
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	int i;
+	size_t size;
+
+#if(TLB_HASH_TABLE_SIZE != 256)
+	/* Key to the hash table is byte wide. Check the size! */
+	#error Hash Table size is wrong.
+#endif
+
+	spin_lock_init(&(bond_info->tx_hashtbl_lock));
+
+	_lock_tx_hashtbl(bond);
+	if (bond_info->tx_hashtbl != NULL) {
+		printk (KERN_ERR "%s: TLB hash table is not NULL\n",
+			bond->device->name);
+		_unlock_tx_hashtbl(bond);
+		return -1;
+	}
+
+	size = TLB_HASH_TABLE_SIZE * sizeof(struct tlb_client_info);
+	bond_info->tx_hashtbl = kmalloc(size, GFP_KERNEL);
+	if (bond_info->tx_hashtbl == NULL) {
+		printk (KERN_ERR "%s: Failed to allocate TLB hash table\n",
+			bond->device->name);
+		_unlock_tx_hashtbl(bond);
+		return -1;
+	}
+
+	memset(bond_info->tx_hashtbl, 0, size);
+	for (i=0; i<TLB_HASH_TABLE_SIZE; i++) {
+		tlb_init_table_entry(bond, i, 1);
+	}
+	_unlock_tx_hashtbl(bond);
+
+	return 0;
+}
+
+/* Must be called only after all slaves have been released */
+static void
+tlb_deinitialize(struct bonding *bond)
+{
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+
+	_lock_tx_hashtbl(bond);
+	if (bond_info->tx_hashtbl == NULL) {
+		_unlock_tx_hashtbl(bond);
+		return;
+	}
+	kfree(bond_info->tx_hashtbl);
+	bond_info->tx_hashtbl = NULL;
+	_unlock_tx_hashtbl(bond);
+}
+
+/* Caller must hold bond lock for read */
+static struct slave*
+tlb_get_least_loaded_slave(struct bonding *bond)
+{
+	struct slave *slave;
+	struct slave *least_loaded;
+	u32 curr_gap, max_gap;
+
+	/* Find the first enabled slave */
+	slave = bond_get_first_slave(bond);
+	while (slave) {
+		if (SLAVE_IS_OK(slave)) {
+			break;
+		}
+		slave = bond_get_next_slave(bond, slave);
+	}
+
+	if (!slave) {
+		return NULL;
+	}
+
+	least_loaded = slave;
+	max_gap = (slave->speed * 1000000) -
+		  (SLAVE_TLB_INFO(slave).load * 8);
+
+	/* Find the slave with the largest gap */
+	slave = bond_get_next_slave(bond, slave);
+	while (slave) {
+		if (SLAVE_IS_OK(slave)) {
+			curr_gap = (slave->speed * 1000000) -
+				   (SLAVE_TLB_INFO(slave).load * 8);
+			if (max_gap < curr_gap) {
+				least_loaded = slave;
+				max_gap = curr_gap;
+			}
+		}
+		slave = bond_get_next_slave(bond, slave);
+	}
+
+	return least_loaded;
+}
+
+/* Caller must hold bond lock for read */
+struct slave*
+tlb_choose_channel(struct bonding *bond, u32 hash_index, u32 skb_len)
+{
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct tlb_client_info *hash_table = NULL;
+	struct slave *assigned_slave = NULL;
+
+	_lock_tx_hashtbl(bond);
+
+	hash_table = bond_info->tx_hashtbl;
+	if (hash_table == NULL) {
+		printk (KERN_ERR "%s: TLB hash table is NULL\n",
+			bond->device->name);
+		_unlock_tx_hashtbl(bond);
+		return NULL;
+	}
+
+	assigned_slave = hash_table[hash_index].tx_slave;
+	if (!assigned_slave) {
+		assigned_slave = tlb_get_least_loaded_slave(bond);
+
+		if (assigned_slave) {
+			struct tlb_slave_info *slave_info =
+				&(SLAVE_TLB_INFO(assigned_slave));
+			u32 next_index = slave_info->head;
+
+			hash_table[hash_index].tx_slave = assigned_slave;
+			hash_table[hash_index].next = next_index;
+			hash_table[hash_index].prev = TLB_NULL_INDEX;
+
+			if (next_index != TLB_NULL_INDEX) {
+				hash_table[next_index].prev = hash_index;
+			}
+
+			slave_info->head = hash_index;
+			slave_info->load +=
+				hash_table[hash_index].load_history;
+		}
+	}
+
+	if (assigned_slave) {
+		hash_table[hash_index].tx_bytes += skb_len;
+	}
+
+	_unlock_tx_hashtbl(bond);
+
+	return assigned_slave;
+}
+
+/*********************** rlb specific functions ***************************/
+static inline void
+_lock_rx_hashtbl(struct bonding *bond)
+{
+	spin_lock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
+}
+
+static inline void
+_unlock_rx_hashtbl(struct bonding *bond)
+{
+	spin_unlock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
+}
+
+/* when an ARP REPLY is received from a client update its info
+ * in the rx_hashtbl
+ */
+static void
+rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
+{
+	u32 hash_index;
+	struct rlb_client_info *client_info = NULL;
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+
+	_lock_rx_hashtbl(bond);
+
+	if (bond_info->rx_hashtbl == NULL) {
+		_unlock_rx_hashtbl(bond);
+		return;
+	}
+	hash_index = _simple_hash((u8*)&(arp->ip_src), 4);
+	client_info = &(bond_info->rx_hashtbl[hash_index]);
+
+	if ((client_info->assigned) &&
+	    (client_info->ip_src == arp->ip_dst) &&
+	    (client_info->ip_dst == arp->ip_src)) {
+
+		/* update the clients MAC address */
+		memcpy(client_info->mac_dst, arp->mac_src, ETH_ALEN);
+		client_info->ntt = 1;
+		bond_info->rx_ntt = 1;
+	}
+
+	_unlock_rx_hashtbl(bond);
+}
+
+static int
+rlb_arp_recv(struct sk_buff *skb,
+	     struct net_device *dev,
+	     struct packet_type* ptype)
+{
+	struct bonding *bond = (struct bonding *)dev->priv;
+	int ret = NET_RX_DROP;
+	struct arp_pkt *arp = (struct arp_pkt *)skb->data;
+
+	if (!(dev->flags & IFF_MASTER)) {
+		goto out;
+	}
+
+	if (!arp) {
+		printk(KERN_ERR "Packet has no ARP data\n");
+		goto out;
+	}
+
+	if (skb->len < sizeof(struct arp_pkt)) {
+		printk(KERN_ERR "Packet is too small to be an ARP\n");
+		goto out;
+	}
+
+	if (arp->op_code == htons(ARPOP_REPLY)) {
+		/* update rx hash table for this ARP */
+		rlb_update_entry_from_arp(bond, arp);
+		BOND_PRINT_DBG(("Server received an ARP Reply from client"));
+	}
+
+	ret = NET_RX_SUCCESS;
+
+out:
+	dev_kfree_skb(skb);
+
+	return ret;
+}
+
+/* Caller must hold bond lock for read */
+static struct slave*
+rlb_next_rx_slave(struct bonding *bond)
+{
+	struct slave *rx_slave = NULL, *slave = NULL;
+	unsigned int i = 0;
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+
+	slave = bond_info->next_rx_slave;
+	if (slave == NULL) {
+		slave = bond->next;
+	}
+
+	/* this loop uses the circular linked list property of the
+	 * slave's list to go through all slaves
+	 */
+	for (i = 0; i < bond->slave_cnt; i++, slave = slave->next) {
+
+		if (SLAVE_IS_OK(slave)) {
+			if (!rx_slave) {
+				rx_slave = slave;
+			}
+			else if (slave->speed > rx_slave->speed) {
+				rx_slave = slave;
+			}
+		}
+	}
+
+	if (rx_slave) {
+		bond_info->next_rx_slave = rx_slave->next;
+	}
+
+	return rx_slave;
+}
+
+/* teach the switch the mac of a disabled slave
+ * on the primary for fault tolerance
+ *
+ * Caller must hold bond->ptrlock for write or bond lock for write
+ */
+static void
+rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
+{
+	if (!bond->current_slave) {
+		return;
+	}
+	if (!bond->alb_info.primary_is_promisc) {
+		bond->alb_info.primary_is_promisc = 1;
+		dev_set_promiscuity(bond->current_slave->dev, 1);
+	}
+	bond->alb_info.rlb_promisc_timeout_counter = 0;
+
+	alb_send_learning_packets(bond->current_slave, addr);
+}
+
+/* slave being removed should not be active at this point
+ *
+ * Caller must hold bond lock for read
+ */
+static void
+rlb_clear_slave(struct bonding *bond, struct slave *slave)
+{
+	struct rlb_client_info *rx_hash_table = NULL;
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	u32 index, next_index;
+
+	/* clear slave from rx_hashtbl */
+	_lock_rx_hashtbl(bond);
+	rx_hash_table = bond_info->rx_hashtbl;
+
+	if (rx_hash_table == NULL) {
+		_unlock_rx_hashtbl(bond);
+		return;
+	}
+
+	index = bond_info->rx_hashtbl_head;
+	for (; index != RLB_NULL_INDEX; index = next_index) {
+		next_index = rx_hash_table[index].next;
+
+		if (rx_hash_table[index].slave == slave) {
+			struct slave *assigned_slave = rlb_next_rx_slave(bond);
+
+			if (assigned_slave) {
+				rx_hash_table[index].slave = assigned_slave;
+				if (memcmp(rx_hash_table[index].mac_dst,
+					   mac_bcast, ETH_ALEN)) {
+					bond_info->rx_hashtbl[index].ntt = 1;
+					bond_info->rx_ntt = 1;
+					/* A slave has been removed from the
+					 * table because it is either disabled
+					 * or being released. We must retry the
+					 * update to avoid clients from not
+					 * being updated & disconnecting when
+					 * there is stress
+					 */
+					bond_info->rlb_update_retry_counter =
+						RLB_UPDATE_RETRY;
+				}
+			} else {  /* there is no active slave */
+				rx_hash_table[index].slave = NULL;
+			}
+		}
+	}
+
+	_unlock_rx_hashtbl(bond);
+
+	write_lock(&bond->ptrlock);
+	if (slave != bond->current_slave) {
+		rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr);
+	}
+	write_unlock(&bond->ptrlock);
+}
+
+static void
+rlb_update_client(struct rlb_client_info *client_info)
+{
+	int i = 0;
+
+	if (client_info->slave == NULL) {
+		return;
+	}
+
+	for (i=0; i<RLB_ARP_BURST_SIZE; i++) {
+		arp_send(ARPOP_REPLY, ETH_P_ARP,
+			 client_info->ip_dst,
+			 client_info->slave->dev,
+			 client_info->ip_src,
+			 client_info->mac_dst,
+			 client_info->slave->dev->dev_addr,
+			 client_info->mac_dst);
+	}
+}
+
+/* sends ARP REPLIES that update the clients that need updating */
+static void
+rlb_update_rx_clients(struct bonding *bond)
+{
+	u32 hash_index;
+	struct rlb_client_info *client_info = NULL;
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+
+	_lock_rx_hashtbl(bond);
+
+	if (bond_info->rx_hashtbl == NULL) {
+		_unlock_rx_hashtbl(bond);
+		return;
+	}
+
+	hash_index = bond_info->rx_hashtbl_head;
+	for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+		client_info = &(bond_info->rx_hashtbl[hash_index]);
+		if (client_info->ntt) {
+			rlb_update_client(client_info);
+			if (bond_info->rlb_update_retry_counter == 0) {
+				client_info->ntt = 0;
+			}
+		}
+	}
+
+	/* do not update the entries again untill this counter is zero so that
+	 * not to confuse the clients.
+	 */
+	bond_info->rlb_update_delay_counter = RLB_UPDATE_DELAY;
+
+	_unlock_rx_hashtbl(bond);
+}
+
+/* The slave was assigned a new mac address - update the clients */
+static void
+rlb_req_update_slave_clients(struct bonding *bond, struct slave *slave)
+{
+	u32 hash_index;
+	u8 ntt = 0;
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	struct rlb_client_info* client_info = NULL;
+
+	_lock_rx_hashtbl(bond);
+
+	if (bond_info->rx_hashtbl == NULL) {
+		_unlock_rx_hashtbl(bond);
+		return;
+	}
+
+	hash_index = bond_info->rx_hashtbl_head;
+	for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+		client_info = &(bond_info->rx_hashtbl[hash_index]);
+
+		if ((client_info->slave == slave) &&
+		    memcmp(client_info->mac_dst, mac_bcast, ETH_ALEN)) {
+			client_info->ntt = 1;
+			ntt = 1;
+		}
+	}
+
+	// update the team's flag only after the whole iteration
+	if (ntt) {
+		bond_info->rx_ntt = 1;
+		//fasten the change
+		bond_info->rlb_update_retry_counter = RLB_UPDATE_RETRY;
+	}
+
+	_unlock_rx_hashtbl(bond);
+}
+
+/* mark all clients using src_ip to be updated */
+static void
+rlb_req_update_subnet_clients(struct bonding *bond, u32 src_ip)
+{
+	u32 hash_index;
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	struct rlb_client_info *client_info = NULL;
+
+	_lock_rx_hashtbl(bond);
+
+	if (bond_info->rx_hashtbl == NULL) {
+		_unlock_rx_hashtbl(bond);
+		return;
+	}
+
+	hash_index = bond_info->rx_hashtbl_head;
+	for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+		client_info = &(bond_info->rx_hashtbl[hash_index]);
+
+		if (!client_info->slave) {
+			printk(KERN_ERR "Bonding: Error: found a client with no"
+			       " channel in the client's hash table\n");
+			continue;
+		}
+		/*update all clients using this src_ip, that are not assigned
+		 * to the team's address (current_slave) and have a known
+		 * unicast mac address.
+		 */
+		if ((client_info->ip_src == src_ip) &&
+		    memcmp(client_info->slave->dev->dev_addr,
+			   bond->device->dev_addr, ETH_ALEN) &&
+		    memcmp(client_info->mac_dst, mac_bcast, ETH_ALEN)) {
+			client_info->ntt = 1;
+			bond_info->rx_ntt = 1;
+		}
+	}
+
+	_unlock_rx_hashtbl(bond);
+}
+
+/* Caller must hold both bond and ptr locks for read */
+struct slave*
+rlb_choose_channel(struct bonding *bond, struct arp_pkt *arp)
+{
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct rlb_client_info *client_info = NULL;
+	u32 hash_index = 0;
+	struct slave *assigned_slave = NULL;
+	u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+
+	_lock_rx_hashtbl(bond);
+
+	if (bond_info->rx_hashtbl == NULL) {
+		_unlock_rx_hashtbl(bond);
+		return NULL;
+	}
+
+	hash_index = _simple_hash((u8 *)&arp->ip_dst, 4);
+	client_info = &(bond_info->rx_hashtbl[hash_index]);
+
+	if (client_info->assigned == 1) {
+		if ((client_info->ip_src == arp->ip_src) &&
+		    (client_info->ip_dst == arp->ip_dst)) {
+			/* the entry is already assigned to this client */
+
+			if (memcmp(arp->mac_dst, mac_bcast, ETH_ALEN)) {
+				/* update mac address from arp */
+				memcpy(client_info->mac_dst, arp->mac_dst, ETH_ALEN);
+			}
+
+			assigned_slave = client_info->slave;
+			if (assigned_slave) {
+				_unlock_rx_hashtbl(bond);
+				return assigned_slave;
+			}
+		} else {
+			/* the entry is already assigned to some other client,
+			 * move the old client to primary (current_slave) so
+			 * that the new client can be assigned to this entry.
+			 */
+			if (bond->current_slave &&
+			    client_info->slave != bond->current_slave) {
+				client_info->slave = bond->current_slave;
+				rlb_update_client(client_info);
+			}
+		}
+	}
+	/* assign a new slave */
+	assigned_slave = rlb_next_rx_slave(bond);
+
+	if (assigned_slave) {
+		client_info->ip_src = arp->ip_src;
+		client_info->ip_dst = arp->ip_dst;
+		/* arp->mac_dst is broadcast for arp reqeusts.
+		 * will be updated with clients actual unicast mac address
+		 * upon receiving an arp reply.
+		 */
+		memcpy(client_info->mac_dst, arp->mac_dst, ETH_ALEN);
+		client_info->slave = assigned_slave;
+
+		if (memcmp(client_info->mac_dst, mac_bcast, ETH_ALEN)) {
+			client_info->ntt = 1;
+			bond->alb_info.rx_ntt = 1;
+		}
+		else {
+			client_info->ntt = 0;
+		}
+
+		if (!client_info->assigned) {
+			u32 prev_tbl_head = bond_info->rx_hashtbl_head;
+			bond_info->rx_hashtbl_head = hash_index;
+			client_info->next = prev_tbl_head;
+			if (prev_tbl_head != RLB_NULL_INDEX) {
+				bond_info->rx_hashtbl[prev_tbl_head].prev =
+					hash_index;
+			}
+			client_info->assigned = 1;
+		}
+	}
+
+	_unlock_rx_hashtbl(bond);
+
+	return assigned_slave;
+}
+
+/* chooses (and returns) transmit channel for arp reply
+ * does not choose channel for other arp types since they are
+ * sent on the current_slave
+ */
+static struct slave*
+rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
+{
+	struct arp_pkt *arp = (struct arp_pkt *)skb->nh.raw;
+	struct slave *tx_slave = NULL;
+
+	if (arp->op_code == __constant_htons(ARPOP_REPLY)) {
+		/* the arp must be sent on the selected
+		* rx channel
+		*/
+		tx_slave = rlb_choose_channel(bond, arp);
+		if (tx_slave) {
+			memcpy(arp->mac_src,tx_slave->dev->dev_addr, ETH_ALEN);
+		}
+		BOND_PRINT_DBG(("Server sent ARP Reply packet"));
+	} else if (arp->op_code == __constant_htons(ARPOP_REQUEST)) {
+
+		/* Create an entry in the rx_hashtbl for this client as a
+		 * place holder.
+		 * When the arp reply is received the entry will be updated
+		 * with the correct unicast address of the client.
+		 */
+		rlb_choose_channel(bond, arp);
+
+		/* The ARP relpy packets must be delayed so that
+		 * they can cancel out the influence of the ARP request.
+		 */
+		bond->alb_info.rlb_update_delay_counter = RLB_UPDATE_DELAY;
+
+		/* arp requests are broadcast and are sent on the primary
+		 * the arp request will collapse all clients on the subnet to
+		 * the primary slave. We must register these clients to be
+		 * updated with their assigned mac.
+		 */
+		rlb_req_update_subnet_clients(bond, arp->ip_src);
+		BOND_PRINT_DBG(("Server sent ARP Request packet"));
+	}
+
+	return tx_slave;
+}
+
+/* Caller must hold bond lock for read */
+static void
+rlb_rebalance(struct bonding *bond)
+{
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct slave *assigned_slave = NULL;
+	u32 hash_index;
+	struct rlb_client_info *client_info = NULL;
+	u8 ntt = 0;
+
+	_lock_rx_hashtbl(bond);
+
+	if (bond_info->rx_hashtbl == NULL) {
+		_unlock_rx_hashtbl(bond);
+		return;
+	}
+
+	hash_index = bond_info->rx_hashtbl_head;
+	for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+		client_info = &(bond_info->rx_hashtbl[hash_index]);
+		assigned_slave = rlb_next_rx_slave(bond);
+		if (assigned_slave && (client_info->slave != assigned_slave)){
+			client_info->slave = assigned_slave;
+			client_info->ntt = 1;
+			ntt = 1;
+		}
+	}
+
+	/* update the team's flag only after the whole iteration */
+	if (ntt) {
+		bond_info->rx_ntt = 1;
+	}
+	_unlock_rx_hashtbl(bond);
+}
+
+/* Caller must hold rx_hashtbl lock */
+static inline void
+rlb_init_table_entry(struct rlb_client_info *entry)
+{
+	entry->next = RLB_NULL_INDEX;
+	entry->prev = RLB_NULL_INDEX;
+	entry->assigned = 0;
+	entry->ntt = 0;
+}
+
+static int
+rlb_initialize(struct bonding *bond)
+{
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct packet_type *pk_type = &(BOND_ALB_INFO(bond).rlb_pkt_type);
+	int i;
+	size_t size;
+
+	spin_lock_init(&(bond_info->rx_hashtbl_lock));
+
+	_lock_rx_hashtbl(bond);
+	if (bond_info->rx_hashtbl != NULL) {
+		printk (KERN_ERR "%s: RLB hash table is not NULL\n",
+			bond->device->name);
+		_unlock_rx_hashtbl(bond);
+		return -1;
+	}
+
+	size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info);
+	bond_info->rx_hashtbl = kmalloc(size, GFP_KERNEL);
+	if (bond_info->rx_hashtbl == NULL) {
+		printk (KERN_ERR "%s: Failed to allocate"
+			" RLB hash table\n", bond->device->name);
+		_unlock_rx_hashtbl(bond);
+		return -1;
+	}
+
+	bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
+
+	for (i=0; i<RLB_HASH_TABLE_SIZE; i++) {
+		rlb_init_table_entry(bond_info->rx_hashtbl + i);
+	}
+	_unlock_rx_hashtbl(bond);
+
+	/* register to receive ARPs */
+
+	/*initialize packet type*/
+	pk_type->type = __constant_htons(ETH_P_ARP);
+	pk_type->dev = bond->device;
+	pk_type->func = rlb_arp_recv;
+	pk_type->data = (void*)1;  /* understand shared skbs */
+
+	dev_add_pack(pk_type);
+
+	return 0;
+}
+
+static void
+rlb_deinitialize(struct bonding *bond)
+{
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+
+	dev_remove_pack(&(bond_info->rlb_pkt_type));
+
+	_lock_rx_hashtbl(bond);
+	if (bond_info->rx_hashtbl == NULL) {
+		_unlock_rx_hashtbl(bond);
+		return;
+	}
+	kfree(bond_info->rx_hashtbl);
+	bond_info->rx_hashtbl = NULL;
+	_unlock_rx_hashtbl(bond);
+}
+
+/*********************** tlb/rlb shared functions *********************/
+
+static void
+alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
+{
+	struct sk_buff *skb = NULL;
+	struct learning_pkt pkt;
+	char *data = NULL;
+	int i;
+	unsigned int size = sizeof(struct learning_pkt);
+
+	memset(&pkt, 0, size);
+	memcpy(pkt.mac_dst, mac_addr, ETH_ALEN);
+	memcpy(pkt.mac_src, mac_addr, ETH_ALEN);
+	pkt.type = __constant_htons(ETH_P_LOOP);
+
+	for (i=0; i < MAX_LP_RETRY; i++) {
+		skb = NULL;
+		skb = dev_alloc_skb(size);
+		if (!skb) {
+			return;
+		}
+
+		data = skb_put(skb, size);
+		memcpy(data, &pkt, size);
+		skb->mac.raw = data;
+		skb->nh.raw = data + ETH_HLEN;
+		skb->protocol = pkt.type;
+		skb->priority = TC_PRIO_CONTROL;
+		skb->dev = slave->dev;
+		dev_queue_xmit(skb);
+	}
+
+}
+
+/* hw is a boolean parameter that determines whether we should try and
+ * set the hw address of the hw as well as the hw address of the net_device
+ */
+static int
+alb_set_mac_addr(struct slave *slave, u8 addr[], int hw)
+{
+	struct net_device *dev = NULL;
+	struct sockaddr s_addr;
+
+	dev = slave->dev;
+
+	if (!hw) {
+		memcpy(dev->dev_addr, addr, ETH_ALEN);
+		return 0;
+	}
+
+	/* for rlb each slave must have a unique hw mac addresses so that */
+	/* each slave will receive packets destined to a different mac */
+	memcpy(s_addr.sa_data, addr, ETH_ALEN);
+	s_addr.sa_family = dev->type;
+	if (dev->set_mac_address(dev, &s_addr)) {
+		printk(KERN_DEBUG "bonding: Error: alb_set_mac_addr:"
+				  " dev->set_mac_address of dev %s failed!"
+				  " ALB mode requires that the base driver"
+				  " support setting the hw address also when"
+				  " the network device's interface is open\n",
+				  dev->name);
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
+/* Caller must hold bond lock for write or ptrlock for write*/
+static void
+alb_swap_mac_addr(struct bonding *bond,
+		  struct slave *slave1,
+		  struct slave *slave2)
+{
+	u8 tmp_mac_addr[ETH_ALEN];
+	struct slave *disabled_slave = NULL;
+	u8 slaves_state_differ;
+
+	slaves_state_differ = (SLAVE_IS_OK(slave1) != SLAVE_IS_OK(slave2));
+
+	memcpy(tmp_mac_addr, slave1->dev->dev_addr, ETH_ALEN);
+	alb_set_mac_addr(slave1, slave2->dev->dev_addr, bond->alb_info.rlb_enabled);
+	alb_set_mac_addr(slave2, tmp_mac_addr, bond->alb_info.rlb_enabled);
+
+	/* fasten the change in the switch */
+	if (SLAVE_IS_OK(slave1)) {
+		alb_send_learning_packets(slave1, slave1->dev->dev_addr);
+		if (bond->alb_info.rlb_enabled) {
+			/* inform the clients that the mac address
+			 * has changed
+			 */
+			rlb_req_update_slave_clients(bond, slave1);
+		}
+	}
+	else {
+		disabled_slave = slave1;
+	}
+
+	if (SLAVE_IS_OK(slave2)) {
+		alb_send_learning_packets(slave2, slave2->dev->dev_addr);
+		if (bond->alb_info.rlb_enabled) {
+			/* inform the clients that the mac address
+			 * has changed
+			 */
+			rlb_req_update_slave_clients(bond, slave2);
+		}
+	}
+	else {
+		disabled_slave = slave2;
+	}
+
+	if (bond->alb_info.rlb_enabled && slaves_state_differ) {
+			/* A disabled slave was assigned an active mac addr */
+			rlb_teach_disabled_mac_on_primary(bond,
+				disabled_slave->dev->dev_addr);
+	}
+}
+
+/**
+ * alb_change_hw_addr_on_detach
+ * @bond: bonding we're working on
+ * @slave: the slave that was just detached
+ *
+ * We assume that @slave was already detached from the slave list.
+ *
+ * If @slave's permanent hw address is different both from its current
+ * address and from @bond's address, then somewhere in the bond there's
+ * a slave that has @slave's permanet address as its current address.
+ * We'll make sure that that slave no longer uses @slave's permanent address.
+ *
+ * Caller must hold bond lock
+ */
+static void
+alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *slave)
+{
+	struct slave *tmp_slave;
+	int perm_curr_diff;
+	int perm_bond_diff;
+
+	perm_curr_diff = memcmp(slave->perm_hwaddr,
+				slave->dev->dev_addr,
+				ETH_ALEN);
+	perm_bond_diff = memcmp(slave->perm_hwaddr,
+				bond->device->dev_addr,
+				ETH_ALEN);
+	if (perm_curr_diff && perm_bond_diff) {
+		tmp_slave = bond_get_first_slave(bond);
+		while (tmp_slave) {
+			if (!memcmp(slave->perm_hwaddr,
+				   tmp_slave->dev->dev_addr,
+				   ETH_ALEN)) {
+				break;
+			}
+			tmp_slave = bond_get_next_slave(bond, tmp_slave);
+		}
+
+		if (tmp_slave) {
+			alb_swap_mac_addr(bond, slave, tmp_slave);
+		}
+	}
+}
+
+/**
+ * alb_handle_addr_collision_on_attach
+ * @bond: bonding we're working on
+ * @slave: the slave that was just attached
+ *
+ * checks uniqueness of slave's mac address and handles the case the
+ * new slave uses the bonds mac address.
+ *
+ * If the permanent hw address of @slave is @bond's hw address, we need to
+ * find a different hw address to give @slave, that isn't in use by any other
+ * slave in the bond. This address must be, of course, one of the premanent
+ * addresses of the other slaves.
+ *
+ * We go over the slave list, and for each slave there we compare its
+ * permanent hw address with the current address of all the other slaves.
+ * If no match was found, then we've found a slave with a permanent address
+ * that isn't used by any other slave in the bond, so we can assign it to
+ * @slave.
+ *
+ * assumption: this function is called before @slave is attached to the
+ * 	       bond slave list.
+ *
+ * caller must hold the bond lock for write since the mac addresses are compared
+ * and may be swapped.
+ */
+static int
+alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
+{
+	struct slave *tmp_slave1, *tmp_slave2;
+
+	if (bond->slave_cnt == 0) {
+		/* this is the first slave */
+		return 0;
+	}
+
+	/* if slave's mac address differs from bond's mac address
+	 * check uniqueness of slave's mac address against the other
+	 * slaves in the bond.
+	 */
+	if (memcmp(slave->perm_hwaddr, bond->device->dev_addr, ETH_ALEN)) {
+		tmp_slave1 = bond_get_first_slave(bond);
+		for (; tmp_slave1; tmp_slave1 = bond_get_next_slave(bond, tmp_slave1)) {
+			if (!memcmp(tmp_slave1->dev->dev_addr, slave->dev->dev_addr,
+				    ETH_ALEN)) {
+				break;
+			}
+		}
+		if (tmp_slave1) {
+			/* a slave was found that is using the mac address
+			 * of the new slave
+			 */
+			printk(KERN_ERR "bonding: Warning: the hw address "
+			       "of slave %s is not unique - cannot enslave it!"
+			       , slave->dev->name);
+			return -EINVAL;
+		}
+		return 0;
+	}
+
+	/* the slave's address is equal to the address of the bond
+	 * search for a spare address in the bond for this slave.
+	 */
+	tmp_slave1 = bond_get_first_slave(bond);
+	for (; tmp_slave1; tmp_slave1 = bond_get_next_slave(bond, tmp_slave1)) {
+
+		tmp_slave2 = bond_get_first_slave(bond);
+		for (; tmp_slave2; tmp_slave2 = bond_get_next_slave(bond, tmp_slave2)) {
+
+			if (!memcmp(tmp_slave1->perm_hwaddr,
+				    tmp_slave2->dev->dev_addr,
+				    ETH_ALEN)) {
+
+				break;
+			}
+		}
+
+		if (!tmp_slave2) {
+			/* no slave has tmp_slave1's perm addr
+			 * as its curr addr
+			 */
+			break;
+		}
+	}
+
+	if (tmp_slave1) {
+		alb_set_mac_addr(slave, tmp_slave1->perm_hwaddr,
+				 bond->alb_info.rlb_enabled);
+
+		printk(KERN_WARNING "bonding: Warning: the hw address "
+		       "of slave %s is in use by the bond; "
+		       "giving it the hw address of %s\n",
+		       slave->dev->name, tmp_slave1->dev->name);
+	} else {
+		printk(KERN_CRIT "bonding: Error: the hw address "
+		       "of slave %s is in use by the bond; "
+		       "couldn't find a slave with a free hw "
+		       "address to give it (this should not have "
+		       "happened)\n", slave->dev->name);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+/************************ exported alb funcions ************************/
+
+int
+bond_alb_initialize(struct bonding *bond, int rlb_enabled)
+{
+	int res;
+
+	res = tlb_initialize(bond);
+	if (res) {
+		return res;
+	}
+
+	if (rlb_enabled) {
+		bond->alb_info.rlb_enabled = 1;
+		/* initialize rlb */
+		res = rlb_initialize(bond);
+		if (res) {
+			tlb_deinitialize(bond);
+			return res;
+		}
+	}
+
+	return 0;
+}
+
+void
+bond_alb_deinitialize(struct bonding *bond)
+{
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+
+	tlb_deinitialize(bond);
+
+	if (bond_info->rlb_enabled) {
+		rlb_deinitialize(bond);
+	}
+}
+
+int
+bond_alb_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct bonding *bond = (struct bonding *) dev->priv;
+	struct ethhdr *eth_data = (struct ethhdr *)skb->data;
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct slave *tx_slave = NULL;
+	char do_tx_balance = 1;
+	int hash_size = 0;
+	u32 hash_index = 0;
+	u8 *hash_start = NULL;
+	u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+
+	if (!IS_UP(dev)) { /* bond down */
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	/* make sure that the current_slave and the slaves list do
+	 * not change during tx
+	 */
+	read_lock(&bond->lock);
+
+	if (bond->slave_cnt == 0) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+		read_unlock(&bond->lock);
+		return 0;
+	}
+
+	read_lock(&bond->ptrlock);
+
+	switch (ntohs(skb->protocol)) {
+	case ETH_P_IP:
+		if ((memcmp(eth_data->h_dest, mac_bcast, ETH_ALEN) == 0) ||
+		    (skb->nh.iph->daddr == 0xffffffff)) {
+			do_tx_balance = 0;
+			break;
+		}
+		hash_start = (char*)&(skb->nh.iph->daddr);
+		hash_size = 4;
+		break;
+
+	case ETH_P_IPV6:
+		if (memcmp(eth_data->h_dest, mac_bcast, ETH_ALEN) == 0) {
+			do_tx_balance = 0;
+			break;
+		}
+
+		hash_start = (char*)&(skb->nh.ipv6h->daddr);
+		hash_size = 16;
+		break;
+
+#ifdef FIXME
+	case ETH_P_IPX:
+		if (skb->nh.ipxh->ipx_checksum !=
+		    __constant_htons(IPX_NO_CHECKSUM)) {
+			/* something is wrong with this packet */
+			do_tx_balance = 0;
+			break;
+		}
+
+		if (skb->nh.ipxh->ipx_type !=
+		    __constant_htons(IPX_TYPE_NCP)) {
+			/* The only protocol worth balancing in
+			 * this family since it has an "ARP" like
+			 * mechanism
+			 */
+			do_tx_balance = 0;
+			break;
+		}
+
+		hash_start = (char*)eth_data->h_dest;
+		hash_size = ETH_ALEN;
+		break;
+#endif
+
+	case ETH_P_ARP:
+		do_tx_balance = 0;
+		if (bond_info->rlb_enabled) {
+			tx_slave = rlb_arp_xmit(skb, bond);
+		}
+		break;
+
+	default:
+		do_tx_balance = 0;
+		break;
+	}
+
+	if (do_tx_balance) {
+		hash_index = _simple_hash(hash_start, hash_size);
+		tx_slave = tlb_choose_channel(bond, hash_index, skb->len);
+	}
+
+	if (!tx_slave) {
+		/* unbalanced or unassigned, send through primary */
+		tx_slave = bond->current_slave;
+		bond_info->unbalanced_load += skb->len;
+	}
+
+	if (tx_slave && SLAVE_IS_OK(tx_slave)) {
+		skb->dev = tx_slave->dev;
+		if (tx_slave != bond->current_slave) {
+			memcpy(eth_data->h_source,
+				tx_slave->dev->dev_addr,
+				ETH_ALEN);
+		}
+		dev_queue_xmit(skb);
+	} else {
+		/* no suitable interface, frame not sent */
+		if (tx_slave) {
+			tlb_clear_slave(bond, tx_slave, 0);
+		}
+		dev_kfree_skb(skb);
+	}
+
+	read_unlock(&bond->ptrlock);
+	read_unlock(&bond->lock);
+	return 0;
+}
+
+void
+bond_alb_monitor(struct bonding *bond)
+{
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct slave *slave = NULL;
+
+	read_lock(&bond->lock);
+
+	if ((bond->slave_cnt == 0) || !(bond->device->flags & IFF_UP)) {
+		bond_info->tx_rebalance_counter = 0;
+		bond_info->lp_counter = 0;
+		goto out;
+	}
+
+	bond_info->tx_rebalance_counter++;
+	bond_info->lp_counter++;
+
+	/* send learning packets */
+	if (bond_info->lp_counter >= BOND_ALB_LP_TICKS) {
+		/* change of current_slave involves swapping of mac addresses.
+		 * in order to avoid this swapping from happening while
+		 * sending the learning packets, the ptrlock must be held for
+		 * read.
+		 */
+		read_lock(&bond->ptrlock);
+		slave = bond_get_first_slave(bond);
+		while (slave) {
+			alb_send_learning_packets(slave,slave->dev->dev_addr);
+			slave = bond_get_next_slave(bond, slave);
+		}
+		read_unlock(&bond->ptrlock);
+
+		bond_info->lp_counter = 0;
+	}
+
+	/* rebalance tx traffic */
+	if (bond_info->tx_rebalance_counter >= BOND_TLB_REBALANCE_TICKS) {
+		read_lock(&bond->ptrlock);
+		slave = bond_get_first_slave(bond);
+		while (slave) {
+			tlb_clear_slave(bond, slave, 1);
+			if (slave == bond->current_slave) {
+				SLAVE_TLB_INFO(slave).load =
+					bond_info->unbalanced_load /
+						BOND_TLB_REBALANCE_INTERVAL;
+				bond_info->unbalanced_load = 0;
+			}
+			slave = bond_get_next_slave(bond, slave);
+		}
+		read_unlock(&bond->ptrlock);
+		bond_info->tx_rebalance_counter = 0;
+	}
+
+	/* handle rlb stuff */
+	if (bond_info->rlb_enabled) {
+		/* the following code changes the promiscuity of the
+		 * the current_slave. It needs to be locked with a
+		 * write lock to protect from other code that also
+		 * sets the promiscuity.
+		 */
+		write_lock(&bond->ptrlock);
+		if (bond_info->primary_is_promisc &&
+		    (++bond_info->rlb_promisc_timeout_counter >=
+			RLB_PROMISC_TIMEOUT)) {
+
+			bond_info->rlb_promisc_timeout_counter = 0;
+
+			/* If the primary was set to promiscuous mode
+			 * because a slave was disabled then
+			 * it can now leave promiscuous mode.
+			 */
+			dev_set_promiscuity(bond->current_slave->dev, -1);
+			bond_info->primary_is_promisc = 0;
+		}
+		write_unlock(&bond->ptrlock);
+
+		if (bond_info->rlb_rebalance == 1) {
+			bond_info->rlb_rebalance = 0;
+			rlb_rebalance(bond);
+		}
+
+		/* check if clients need updating */
+		if (bond_info->rx_ntt) {
+			if (bond_info->rlb_update_delay_counter) {
+				--bond_info->rlb_update_delay_counter;
+			} else {
+				rlb_update_rx_clients(bond);
+				if (bond_info->rlb_update_retry_counter) {
+					--bond_info->rlb_update_retry_counter;
+				} else {
+					bond_info->rx_ntt = 0;
+				}
+			}
+		}
+	}
+
+out:
+	read_unlock(&bond->lock);
+
+	if (bond->device->flags & IFF_UP) {
+		/* re-arm the timer */
+		mod_timer(&(bond_info->alb_timer),
+			jiffies + (HZ/ALB_TIMER_TICKS_PER_SEC));
+	}
+}
+
+/* assumption: called before the slave is attched to the bond
+ * and not locked by the bond lock
+ */
+int
+bond_alb_init_slave(struct bonding *bond, struct slave *slave)
+{
+	int err = 0;
+
+	err = alb_set_mac_addr(slave, slave->perm_hwaddr,
+				bond->alb_info.rlb_enabled);
+	if (err) {
+		return err;
+	}
+
+	/* caller must hold the bond lock for write since the mac addresses
+	 * are compared and may be swapped.
+	 */
+	write_lock_bh(&bond->lock);
+
+	err = alb_handle_addr_collision_on_attach(bond, slave);
+
+	write_unlock_bh(&bond->lock);
+
+	if (err) {
+		return err;
+	}
+
+	tlb_init_slave(slave);
+
+	/* order a rebalance ASAP */
+	bond->alb_info.tx_rebalance_counter = BOND_TLB_REBALANCE_TICKS;
+
+	if (bond->alb_info.rlb_enabled) {
+		bond->alb_info.rlb_rebalance = 1;
+	}
+
+	return 0;
+}
+
+/* Caller must hold bond lock for write */
+void
+bond_alb_deinit_slave(struct bonding *bond, struct slave *slave)
+{
+	if (bond->slave_cnt > 1) {
+		alb_change_hw_addr_on_detach(bond, slave);
+	}
+
+	tlb_clear_slave(bond, slave, 0);
+
+	if (bond->alb_info.rlb_enabled) {
+		bond->alb_info.next_rx_slave = NULL;
+		rlb_clear_slave(bond, slave);
+	}
+}
+
+/* Caller must hold bond lock for read */
+void
+bond_alb_handle_link_change(struct bonding *bond, struct slave *slave,
+			    char link)
+{
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+
+	if (link == BOND_LINK_DOWN) {
+		tlb_clear_slave(bond, slave, 0);
+		if (bond->alb_info.rlb_enabled) {
+			rlb_clear_slave(bond, slave);
+		}
+	} else if (link == BOND_LINK_UP) {
+		/* order a rebalance ASAP */
+		bond_info->tx_rebalance_counter = BOND_TLB_REBALANCE_TICKS;
+		if (bond->alb_info.rlb_enabled) {
+			bond->alb_info.rlb_rebalance = 1;
+			/* If the updelay module parameter is smaller than the
+			 * forwarding delay of the switch the rebalance will
+			 * not work because the rebalance arp replies will
+			 * not be forwarded to the clients..
+			 */
+		}
+	}
+}
+
+/**
+ * bond_alb_assign_current_slave - assign new current_slave
+ * @bond: our bonding struct
+ * @new_slave: new slave to assign
+ *
+ * Set the bond->current_slave to @new_slave and handle
+ * mac address swapping and promiscuity changes as needed.
+ *
+ * Caller must hold bond ptrlock for write (or bond lock for write)
+ */
+void
+bond_alb_assign_current_slave(struct bonding *bond, struct slave *new_slave)
+{
+	struct slave *swap_slave = bond->current_slave;
+
+	if (bond->current_slave == new_slave) {
+		return;
+	}
+
+	if (bond->current_slave && bond->alb_info.primary_is_promisc) {
+		dev_set_promiscuity(bond->current_slave->dev, -1);
+		bond->alb_info.primary_is_promisc = 0;
+		bond->alb_info.rlb_promisc_timeout_counter = 0;
+	}
+
+	bond->current_slave = new_slave;
+
+	if (!new_slave || (bond->slave_cnt == 0)) {
+		return;
+	}
+
+	/* set the new current_slave to the bonds mac address
+	 * i.e. swap mac addresses of old current_slave and new current_slave
+	 */
+	if (!swap_slave) {
+		/* find slave that is holding the bond's mac address */
+		swap_slave = bond_get_first_slave(bond);
+		while (swap_slave) {
+			if (!memcmp(swap_slave->dev->dev_addr,
+				bond->device->dev_addr, ETH_ALEN)) {
+				break;
+			}
+			swap_slave = bond_get_next_slave(bond, swap_slave);
+		}
+	}
+
+	/* current_slave must be set before calling alb_swap_mac_addr */
+	if (swap_slave) {
+		/* swap mac address */
+		alb_swap_mac_addr(bond, swap_slave, new_slave);
+	} else {
+		/* set the new_slave to the bond mac address */
+		alb_set_mac_addr(new_slave, bond->device->dev_addr,
+				 bond->alb_info.rlb_enabled);
+		/* fasten bond mac on new current slave */
+		alb_send_learning_packets(new_slave, bond->device->dev_addr);
+	}
+}
+
diff -urN linux-2.5.69-bk18/drivers/net/bonding/bond_alb.h linux-2.5.69-bk19/drivers/net/bonding/bond_alb.h
--- linux-2.5.69-bk18/drivers/net/bonding/bond_alb.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/drivers/net/bonding/bond_alb.h	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,127 @@
+/*
+ * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ */
+
+#ifndef __BOND_ALB_H__
+#define __BOND_ALB_H__
+
+#include <linux/if_ether.h>
+
+struct bonding;
+struct slave;
+
+#define BOND_ALB_INFO(bond)   ((bond)->alb_info)
+#define SLAVE_TLB_INFO(slave) ((slave)->tlb_info)
+
+struct tlb_client_info {
+	struct slave *tx_slave;	/* A pointer to slave used for transmiting
+				 * packets to a Client that the Hash function
+				 * gave this entry index.
+				 */
+	u32 tx_bytes;		/* Each Client acumulates the BytesTx that
+				 * were tranmitted to it, and after each
+				 * CallBack the LoadHistory is devided
+				 * by the balance interval
+				 */
+	u32 load_history;	/* This field contains the amount of Bytes
+				 * that were transmitted to this client by
+				 * the server on the previous balance
+				 * interval in Bps.
+				 */
+	u32 next;		/* The next Hash table entry index, assigned
+				 * to use the same adapter for transmit.
+				 */
+	u32 prev;		/* The previous Hash table entry index,
+				 * assigned to use the same
+				 */
+};
+
+/* -------------------------------------------------------------------------
+ * struct rlb_client_info contains all info related to a specific rx client
+ * connection. This is the Clients Hash Table entry struct
+ * -------------------------------------------------------------------------
+ */
+struct rlb_client_info {
+	u32 ip_src;		/* the server IP address */
+	u32 ip_dst;		/* the client IP address */
+	u8  mac_dst[ETH_ALEN];	/* the client MAC address */
+	u32 next;		/* The next Hash table entry index */
+	u32 prev;		/* The previous Hash table entry index */
+	u8  assigned;		/* checking whether this entry is assigned */
+	u8  ntt;		/* flag - need to transmit client info */
+	struct slave *slave;	/* the slave assigned to this client */
+};
+
+struct tlb_slave_info {
+	u32 head;	/* Index to the head of the bi-directional clients
+			 * hash table entries list. The entries in the list
+			 * are the entries that were assigned to use this
+			 * slave for transmit.
+			 */
+	u32 load;	/* Each slave sums the loadHistory of all clients
+			 * assigned to it
+			 */
+};
+
+struct alb_bond_info {
+	struct timer_list	alb_timer;
+	struct tlb_client_info	*tx_hashtbl; /* Dynamically allocated */
+	spinlock_t		tx_hashtbl_lock;
+	u32			unbalanced_load;
+	int			tx_rebalance_counter;
+	int			lp_counter;
+	/* -------- rlb parameters -------- */
+	int rlb_enabled;
+	struct packet_type	rlb_pkt_type;
+	struct rlb_client_info	*rx_hashtbl;	/* Receive hash table */
+	spinlock_t		rx_hashtbl_lock;
+	u32			rx_hashtbl_head;
+	u8			rx_ntt;	/* flag - need to transmit
+					 * to all rx clients
+					 */
+	struct slave		*next_rx_slave;/* next slave to be assigned
+						* to a new rx client for
+						*/
+	u32			rlb_interval_counter;
+	u8			primary_is_promisc;	   /* boolean */
+	u32			rlb_promisc_timeout_counter;/* counts primary
+							     * promiscuity time
+							     */
+	u32			rlb_update_delay_counter;
+	u32			rlb_update_retry_counter;/* counter of retries
+							  * of client update
+							  */
+	u8			rlb_rebalance;	/* flag - indicates that the
+						 * rx traffic should be
+						 * rebalanced
+						 */
+};
+
+int bond_alb_initialize(struct bonding *bond, int rlb_enabled);
+void bond_alb_deinitialize(struct bonding *bond);
+int bond_alb_init_slave(struct bonding *bond, struct slave *slave);
+void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave);
+void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char link);
+void bond_alb_assign_current_slave(struct bonding *bond, struct slave *new_slave);
+int bond_alb_xmit(struct sk_buff *skb, struct net_device *dev);
+void bond_alb_monitor(struct bonding *bond);
+
+#endif /* __BOND_ALB_H__ */
+
diff -urN linux-2.5.69-bk18/drivers/net/bonding/bond_main.c linux-2.5.69-bk19/drivers/net/bonding/bond_main.c
--- linux-2.5.69-bk18/drivers/net/bonding/bond_main.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/drivers/net/bonding/bond_main.c	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,4053 @@
+/*
+ * originally based on the dummy device.
+ *
+ * Copyright 1999, Thomas Davis, tadavis@lbl.gov.  
+ * Licensed under the GPL. Based on dummy.c, and eql.c devices.
+ *
+ * bonding.c: an Ethernet Bonding driver
+ *
+ * This is useful to talk to a Cisco EtherChannel compatible equipment:
+ *	Cisco 5500
+ *	Sun Trunking (Solaris)
+ *	Alteon AceDirector Trunks
+ *	Linux Bonding
+ *	and probably many L2 switches ...
+ *
+ * How it works:
+ *    ifconfig bond0 ipaddress netmask up
+ *      will setup a network device, with an ip address.  No mac address 
+ *	will be assigned at this time.  The hw mac address will come from 
+ *	the first slave bonded to the channel.  All slaves will then use 
+ *	this hw mac address.
+ *
+ *    ifconfig bond0 down
+ *         will release all slaves, marking them as down.
+ *
+ *    ifenslave bond0 eth0
+ *	will attach eth0 to bond0 as a slave.  eth0 hw mac address will either
+ *	a: be used as initial mac address
+ *	b: if a hw mac address already is there, eth0's hw mac address 
+ *	   will then be set from bond0.
+ *
+ * v0.1 - first working version.
+ * v0.2 - changed stats to be calculated by summing slaves stats.
+ *
+ * Changes:
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ * - fix leaks on failure at bond_init
+ *
+ * 2000/09/30 - Willy Tarreau <willy at meta-x.org>
+ *     - added trivial code to release a slave device.
+ *     - fixed security bug (CAP_NET_ADMIN not checked)
+ *     - implemented MII link monitoring to disable dead links :
+ *       All MII capable slaves are checked every <miimon> milliseconds
+ *       (100 ms seems good). This value can be changed by passing it to
+ *       insmod. A value of zero disables the monitoring (default).
+ *     - fixed an infinite loop in bond_xmit_roundrobin() when there's no
+ *       good slave.
+ *     - made the code hopefully SMP safe
+ *
+ * 2000/10/03 - Willy Tarreau <willy at meta-x.org>
+ *     - optimized slave lists based on relevant suggestions from Thomas Davis
+ *     - implemented active-backup method to obtain HA with two switches:
+ *       stay as long as possible on the same active interface, while we
+ *       also monitor the backup one (MII link status) because we want to know
+ *       if we are able to switch at any time. ( pass "mode=1" to insmod )
+ *     - lots of stress testings because we need it to be more robust than the
+ *       wires ! :->
+ *
+ * 2000/10/09 - Willy Tarreau <willy at meta-x.org>
+ *     - added up and down delays after link state change.
+ *     - optimized the slaves chaining so that when we run forward, we never
+ *       repass through the bond itself, but we can find it by searching
+ *       backwards. Renders the deletion more difficult, but accelerates the
+ *       scan.
+ *     - smarter enslaving and releasing.
+ *     - finer and more robust SMP locking
+ *
+ * 2000/10/17 - Willy Tarreau <willy at meta-x.org>
+ *     - fixed two potential SMP race conditions
+ *
+ * 2000/10/18 - Willy Tarreau <willy at meta-x.org>
+ *     - small fixes to the monitoring FSM in case of zero delays
+ * 2000/11/01 - Willy Tarreau <willy at meta-x.org>
+ *     - fixed first slave not automatically used in trunk mode.
+ * 2000/11/10 : spelling of "EtherChannel" corrected.
+ * 2000/11/13 : fixed a race condition in case of concurrent accesses to ioctl().
+ * 2000/12/16 : fixed improper usage of rtnl_exlock_nowait().
+ *
+ * 2001/1/3 - Chad N. Tindel <ctindel at ieee dot org>
+ *     - The bonding driver now simulates MII status monitoring, just like
+ *       a normal network device.  It will show that the link is down iff
+ *       every slave in the bond shows that their links are down.  If at least
+ *       one slave is up, the bond's MII status will appear as up.
+ *
+ * 2001/2/7 - Chad N. Tindel <ctindel at ieee dot org>
+ *     - Applications can now query the bond from user space to get
+ *       information which may be useful.  They do this by calling
+ *       the BOND_INFO_QUERY ioctl.  Once the app knows how many slaves
+ *       are in the bond, it can call the BOND_SLAVE_INFO_QUERY ioctl to
+ *       get slave specific information (# link failures, etc).  See
+ *       <linux/if_bonding.h> for more details.  The structs of interest
+ *       are ifbond and ifslave.
+ *
+ * 2001/4/5 - Chad N. Tindel <ctindel at ieee dot org>
+ *     - Ported to 2.4 Kernel
+ * 
+ * 2001/5/2 - Jeffrey E. Mast <jeff at mastfamily dot com>
+ *     - When a device is detached from a bond, the slave device is no longer
+ *       left thinking that is has a master.
+ *
+ * 2001/5/16 - Jeffrey E. Mast <jeff at mastfamily dot com>
+ *     - memset did not appropriately initialized the bond rw_locks. Used 
+ *       rwlock_init to initialize to unlocked state to prevent deadlock when 
+ *       first attempting a lock
+ *     - Called SET_MODULE_OWNER for bond device
+ *
+ * 2001/5/17 - Tim Anderson <tsa at mvista.com>
+ *     - 2 paths for releasing for slave release; 1 through ioctl
+ *       and 2) through close. Both paths need to release the same way.
+ *     - the free slave in bond release is changing slave status before
+ *       the free. The netdev_set_master() is intended to change slave state
+ *       so it should not be done as part of the release process.
+ *     - Simple rule for slave state at release: only the active in A/B and
+ *       only one in the trunked case.
+ *
+ * 2001/6/01 - Tim Anderson <tsa at mvista.com>
+ *     - Now call dev_close when releasing a slave so it doesn't screw up
+ *       out routing table.
+ *
+ * 2001/6/01 - Chad N. Tindel <ctindel at ieee dot org>
+ *     - Added /proc support for getting bond and slave information.
+ *       Information is in /proc/net/<bond device>/info. 
+ *     - Changed the locking when calling bond_close to prevent deadlock.
+ *
+ * 2001/8/05 - Janice Girouard <girouard at us.ibm.com>
+ *     - correct problem where refcnt of slave is not incremented in bond_ioctl
+ *       so the system hangs when halting.
+ *     - correct locking problem when unable to malloc in bond_enslave.
+ *     - adding bond_xmit_xor logic.
+ *     - adding multiple bond device support.
+ *
+ * 2001/8/13 - Erik Habbinga <erik_habbinga at hp dot com>
+ *     - correct locking problem with rtnl_exlock_nowait
+ *
+ * 2001/8/23 - Janice Girouard <girouard at us.ibm.com>
+ *     - bzero initial dev_bonds, to correct oops
+ *     - convert SIOCDEVPRIVATE to new MII ioctl calls
+ *
+ * 2001/9/13 - Takao Indoh <indou dot takao at jp dot fujitsu dot com>
+ *     - Add the BOND_CHANGE_ACTIVE ioctl implementation
+ *
+ * 2001/9/14 - Mark Huth <mhuth at mvista dot com>
+ *     - Change MII_LINK_READY to not check for end of auto-negotiation,
+ *       but only for an up link.
+ *
+ * 2001/9/20 - Chad N. Tindel <ctindel at ieee dot org>
+ *     - Add the device field to bonding_t.  Previously the net_device 
+ *       corresponding to a bond wasn't available from the bonding_t 
+ *       structure.
+ *
+ * 2001/9/25 - Janice Girouard <girouard at us.ibm.com>
+ *     - add arp_monitor for active backup mode
+ *
+ * 2001/10/23 - Takao Indoh <indou dot takao at jp dot fujitsu dot com>
+ *     - Various memory leak fixes
+ *
+ * 2001/11/5 - Mark Huth <mark dot huth at mvista dot com>
+ *     - Don't take rtnl lock in bond_mii_monitor as it deadlocks under 
+ *       certain hotswap conditions.  
+ *       Note:  this same change may be required in bond_arp_monitor ???
+ *     - Remove possibility of calling bond_sethwaddr with NULL slave_dev ptr 
+ *     - Handle hot swap ethernet interface deregistration events to remove
+ *       kernel oops following hot swap of enslaved interface
+ *
+ * 2002/1/2 - Chad N. Tindel <ctindel at ieee dot org>
+ *     - Restore original slave flags at release time.
+ *
+ * 2002/02/18 - Erik Habbinga <erik_habbinga at hp dot com>
+ *     - bond_release(): calling kfree on our_slave after call to
+ *       bond_restore_slave_flags, not before
+ *     - bond_enslave(): saving slave flags into original_flags before
+ *       call to netdev_set_master, so the IFF_SLAVE flag doesn't end
+ *       up in original_flags
+ *
+ * 2002/04/05 - Mark Smith <mark.smith at comdev dot cc> and
+ *              Steve Mead <steve.mead at comdev dot cc>
+ *     - Port Gleb Natapov's multicast support patchs from 2.4.12
+ *       to 2.4.18 adding support for multicast.
+ *
+ * 2002/06/10 - Tony Cureington <tony.cureington * hp_com>
+ *     - corrected uninitialized pointer (ifr.ifr_data) in bond_check_dev_link;
+ *       actually changed function to use MIIPHY, then MIIREG, and finally
+ *       ETHTOOL to determine the link status
+ *     - fixed bad ifr_data pointer assignments in bond_ioctl
+ *     - corrected mode 1 being reported as active-backup in bond_get_info;
+ *       also added text to distinguish type of load balancing (rr or xor)
+ *     - change arp_ip_target module param from "1-12s" (array of 12 ptrs)
+ *       to "s" (a single ptr)
+ *
+ * 2002/08/30 - Jay Vosburgh <fubar at us dot ibm dot com>
+ *     - Removed acquisition of xmit_lock in set_multicast_list; caused
+ *       deadlock on SMP (lock is held by caller).
+ *     - Revamped SIOCGMIIPHY, SIOCGMIIREG portion of bond_check_dev_link().
+ *
+ * 2002/09/18 - Jay Vosburgh <fubar at us dot ibm dot com>
+ *     - Fixed up bond_check_dev_link() (and callers): removed some magic
+ *	 numbers, banished local MII_ defines, wrapped ioctl calls to
+ *	 prevent EFAULT errors
+ *
+ * 2002/9/30 - Jay Vosburgh <fubar at us dot ibm dot com>
+ *     - make sure the ip target matches the arp_target before saving the
+ *	 hw address.
+ *
+ * 2002/9/30 - Dan Eisner <eisner at 2robots dot com>
+ *     - make sure my_ip is set before taking down the link, since
+ *	 not all switches respond if the source ip is not set.
+ *
+ * 2002/10/8 - Janice Girouard <girouard at us dot ibm dot com>
+ *     - read in the local ip address when enslaving a device
+ *     - add primary support
+ *     - make sure 2*arp_interval has passed when a new device
+ *       is brought on-line before taking it down.
+ *
+ * 2002/09/11 - Philippe De Muyter <phdm at macqel dot be>
+ *     - Added bond_xmit_broadcast logic.
+ *     - Added bond_mode() support function.
+ *
+ * 2002/10/26 - Laurent Deniel <laurent.deniel at free.fr>
+ *     - allow to register multicast addresses only on active slave
+ *       (useful in active-backup mode)
+ *     - add multicast module parameter
+ *     - fix deletion of multicast groups after unloading module
+ *
+ * 2002/11/06 - Kameshwara Rayaprolu <kameshwara.rao * wipro_com>
+ *     - Changes to prevent panic from closing the device twice; if we close 
+ *       the device in bond_release, we must set the original_flags to down 
+ *       so it won't be closed again by the network layer.
+ *
+ * 2002/11/07 - Tony Cureington <tony.cureington * hp_com>
+ *     - Fix arp_target_hw_addr memory leak
+ *     - Created activebackup_arp_monitor function to handle arp monitoring 
+ *       in active backup mode - the bond_arp_monitor had several problems... 
+ *       such as allowing slaves to tx arps sequentially without any delay 
+ *       for a response
+ *     - Renamed bond_arp_monitor to loadbalance_arp_monitor and re-wrote
+ *       this function to just handle arp monitoring in load-balancing mode;
+ *       it is a lot more compact now
+ *     - Changes to ensure one and only one slave transmits in active-backup 
+ *       mode
+ *     - Robustesize parameters; warn users about bad combinations of 
+ *       parameters; also if miimon is specified and a network driver does 
+ *       not support MII or ETHTOOL, inform the user of this
+ *     - Changes to support link_failure_count when in arp monitoring mode
+ *     - Fix up/down delay reported in /proc
+ *     - Added version; log version; make version available from "modinfo -d"
+ *     - Fixed problem in bond_check_dev_link - if the first IOCTL (SIOCGMIIPH)
+ *	 failed, the ETHTOOL ioctl never got a chance
+ *
+ * 2002/11/16 - Laurent Deniel <laurent.deniel at free.fr>
+ *     - fix multicast handling in activebackup_arp_monitor
+ *     - remove one unnecessary and confusing current_slave == slave test 
+ *	 in activebackup_arp_monitor
+ *
+ *  2002/11/17 - Laurent Deniel <laurent.deniel at free.fr>
+ *     - fix bond_slave_info_query when slave_id = num_slaves
+ *
+ *  2002/11/19 - Janice Girouard <girouard at us dot ibm dot com>
+ *     - correct ifr_data reference.  Update ifr_data reference
+ *       to mii_ioctl_data struct values to avoid confusion.
+ *
+ *  2002/11/22 - Bert Barbe <bert.barbe at oracle dot com>
+ *      - Add support for multiple arp_ip_target
+ *
+ *  2002/12/13 - Jay Vosburgh <fubar at us dot ibm dot com>
+ *	- Changed to allow text strings for mode and multicast, e.g.,
+ *	  insmod bonding mode=active-backup.  The numbers still work.
+ *	  One change: an invalid choice will cause module load failure,
+ *	  rather than the previous behavior of just picking one.
+ *	- Minor cleanups; got rid of dup ctype stuff, atoi function
+ * 
+ * 2003/02/07 - Jay Vosburgh <fubar at us dot ibm dot com>
+ *	- Added use_carrier module parameter that causes miimon to
+ *	  use netif_carrier_ok() test instead of MII/ETHTOOL ioctls.
+ *	- Minor cleanups; consolidated ioctl calls to one function.
+ *
+ * 2003/02/07 - Tony Cureington <tony.cureington * hp_com>
+ *	- Fix bond_mii_monitor() logic error that could result in
+ *	  bonding round-robin mode ignoring links after failover/recovery
+ *
+ * 2003/03/17 - Jay Vosburgh <fubar at us dot ibm dot com>
+ *	- kmalloc fix (GPF_KERNEL to GPF_ATOMIC) reported by
+ *	  Shmulik dot Hen at intel.com.
+ *	- Based on discussion on mailing list, changed use of
+ *	  update_slave_cnt(), created wrapper functions for adding/removing
+ *	  slaves, changed bond_xmit_xor() to check slave_cnt instead of
+ *	  checking slave and slave->dev (which only worked by accident).
+ *	- Misc code cleanup: get arp_send() prototype from header file,
+ *	  add max_bonds to bonding.txt.
+ *
+ * 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
+ *		Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Make sure only bond_attach_slave() and bond_detach_slave() can
+ *	  manipulate the slave list, including slave_cnt, even when in
+ *	  bond_release_all().
+ *	- Fixed hang in bond_release() with traffic running:
+ *	  netdev_set_master() must not be called from within the bond lock.
+ *
+ * 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
+ *		Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Fixed hang in bond_enslave() with traffic running:
+ *	  netdev_set_master() must not be called from within the bond lock.
+ *
+ * 2003/03/18 - Amir Noam <amir.noam at intel dot com>
+ *	- Added support for getting slave's speed and duplex via ethtool.
+ *	  Needed for 802.3ad and other future modes.
+ *
+ * 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
+ *		Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Enable support of modes that need to use the unique mac address of
+ *	  each slave.
+ *	  * bond_enslave(): Moved setting the slave's mac address, and
+ *	    openning it, from the application to the driver. This breaks
+ *	    backward comaptibility with old versions of ifenslave that open
+ *	     the slave before enalsving it !!!.
+ *	  * bond_release(): The driver also takes care of closing the slave
+ *	    and restoring its original mac address.
+ *	- Removed the code that restores all base driver's flags.
+ *	  Flags are automatically restored once all undo stages are done
+ *	  properly.
+ *	- Block possibility of enslaving before the master is up. This
+ *	  prevents putting the system in an unstable state.
+ *
+ * 2003/03/18 - Amir Noam <amir.noam at intel dot com>,
+ *		Tsippy Mendelson <tsippy.mendelson at intel dot com> and
+ *		Shmulik Hen <shmulik.hen at intel dot com>
+ *    - Added support for IEEE 802.3ad Dynamic link aggregation mode.
+ *
+ * 2003/05/01 - Amir Noam <amir.noam at intel dot com>
+ *    - Added ABI version control to restore compatibility between
+ *      new/old ifenslave and new/old bonding.
+ *
+ * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *    - Fixed bug in bond_release_all(): save old value of current_slave
+ *      before setting it to NULL.
+ *    - Changed driver versioning scheme to include version number instead
+ *      of release date (that is already in another field). There are 3
+ *      fields X.Y.Z where:
+ *            X - Major version - big behavior changes
+ *            Y - Minor version - addition of features
+ *            Z - Extra version - minor changes and bug fixes
+ *      The current version is 1.0.0 as a base line.
+ *
+ * 2003/05/01 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
+ *		Amir Noam <amir.noam at intel dot com>
+ *	- Added support for lacp_rate module param.
+ *	- Code beautification and style changes (mainly in comments).
+ *	  new version - 1.0.1
+ *
+ * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Based on discussion on mailing list, changed locking scheme
+ *	  to use lock/unlock or lock_bh/unlock_bh appropriately instead
+ *	  of lock_irqsave/unlock_irqrestore. The new scheme helps exposing
+ *	  hidden bugs and solves system hangs that occurred due to the fact
+ *	  that holding lock_irqsave doesn't prevent softirqs from running.
+ *	  This also increases total throughput since interrupts are not
+ *	  blocked on each transmitted packets or monitor timeout.
+ *	  new version - 2.0.0
+ *
+ * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Added support for Transmit load balancing mode.
+ *	- Concentrate all assignments of current_slave to a single point
+ *	  so specific modes can take actions when the primary adapter is
+ *	  changed.
+ *	- Take the updelay parameter into consideration during bond_enslave
+ *	  since some adapters loose their link during setting the device.
+ *	- Renamed bond_3ad_link_status_changed() to
+ *	  bond_3ad_handle_link_change() for compatibility with TLB.
+ *	  new version - 2.1.0
+ *
+ * 2003/05/01 - Tsippy Mendelson <tsippy.mendelson at intel dot com>
+ *	- Added support for Adaptive load balancing mode which is
+ *	  equivalent to Transmit load balancing + Receive load balancing.
+ *	  new version - 2.2.0
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/socket.h>
+#include <linux/ctype.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <linux/rtnetlink.h>
+
+#include <linux/if_bonding.h>
+#include <linux/smp.h>
+#include <linux/if_ether.h>
+#include <net/arp.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include "bonding.h"
+#include "bond_3ad.h"
+#include "bond_alb.h"
+
+#define DRV_VERSION		"2.2.0"
+#define DRV_RELDATE		"April 15, 2003"
+#define DRV_NAME		"bonding"
+#define DRV_DESCRIPTION		"Ethernet Channel Bonding Driver"
+
+static const char *version =
+DRV_NAME ".c:v" DRV_VERSION " (" DRV_RELDATE ")\n";
+
+/* monitor all links that often (in milliseconds). <=0 disables monitoring */
+#ifndef BOND_LINK_MON_INTERV
+#define BOND_LINK_MON_INTERV	0
+#endif
+
+#ifndef BOND_LINK_ARP_INTERV
+#define BOND_LINK_ARP_INTERV	0
+#endif
+
+#ifndef MAX_ARP_IP_TARGETS
+#define MAX_ARP_IP_TARGETS 16
+#endif
+
+struct bond_parm_tbl {
+	char *modename;
+	int mode;
+};
+
+static int arp_interval = BOND_LINK_ARP_INTERV;
+static char *arp_ip_target[MAX_ARP_IP_TARGETS] = { NULL, };
+static unsigned long arp_target[MAX_ARP_IP_TARGETS] = { 0, } ;
+static int arp_ip_count = 0;
+static u32 my_ip = 0;
+char *arp_target_hw_addr = NULL;
+
+static char *primary= NULL;
+
+static int app_abi_ver = 0;
+static int orig_app_abi_ver = -1; /* This is used to save the first ABI version
+				   * we receive from the application. Once set,
+				   * it won't be changed, and the module will
+				   * refuse to enslave/release interfaces if the
+				   * command comes from an application using
+				   * another ABI version.
+				   */
+
+static int max_bonds	= BOND_DEFAULT_MAX_BONDS;
+static int miimon	= BOND_LINK_MON_INTERV;
+static int use_carrier	= 1;
+static int bond_mode	= BOND_MODE_ROUNDROBIN;
+static int updelay	= 0;
+static int downdelay	= 0;
+
+static char *mode	= NULL;
+
+static struct bond_parm_tbl bond_mode_tbl[] = {
+{	"balance-rr",		BOND_MODE_ROUNDROBIN},
+{	"active-backup",	BOND_MODE_ACTIVEBACKUP},
+{	"balance-xor",		BOND_MODE_XOR},
+{	"broadcast",		BOND_MODE_BROADCAST},
+{	"802.3ad",		BOND_MODE_8023AD},
+{	"tlb",			BOND_MODE_TLB},
+{	"alb",			BOND_MODE_ALB},
+{	NULL,			-1},
+};
+
+static int multicast_mode	= BOND_MULTICAST_ALL;
+static char *multicast		= NULL;
+
+static struct bond_parm_tbl bond_mc_tbl[] = {
+{	"disabled",		BOND_MULTICAST_DISABLED},
+{	"active",		BOND_MULTICAST_ACTIVE},
+{	"all",			BOND_MULTICAST_ALL},
+{	NULL,			-1},
+};
+
+static int lacp_fast		= 0;
+static char *lacp_rate		= NULL;
+
+static struct bond_parm_tbl bond_lacp_tbl[] = {
+{	"slow",		AD_LACP_SLOW},
+{	"fast",		AD_LACP_FAST},
+{	NULL,		-1},
+};
+
+static int first_pass	= 1;
+static struct bonding *these_bonds =  NULL;
+static struct net_device *dev_bonds = NULL;
+
+MODULE_PARM(max_bonds, "i");
+MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
+MODULE_PARM(miimon, "i");
+MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
+MODULE_PARM(use_carrier, "i");
+MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 09 for off, 1 for on (default)");
+MODULE_PARM(mode, "s");
+MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor");
+MODULE_PARM(arp_interval, "i");
+MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
+MODULE_PARM(arp_ip_target, "1-" __MODULE_STRING(MAX_ARP_IP_TARGETS) "s");
+MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
+MODULE_PARM(updelay, "i");
+MODULE_PARM_DESC(updelay, "Delay before considering link up, in milliseconds");
+MODULE_PARM(downdelay, "i");
+MODULE_PARM_DESC(downdelay, "Delay before considering link down, in milliseconds");
+MODULE_PARM(primary, "s");
+MODULE_PARM_DESC(primary, "Primary network device to use");
+MODULE_PARM(multicast, "s");
+MODULE_PARM_DESC(multicast, "Mode for multicast support : 0 for none, 1 for active slave, 2 for all slaves (default)");
+MODULE_PARM(lacp_rate, "s");
+MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)");
+
+static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *dev);
+static int bond_xmit_xor(struct sk_buff *skb, struct net_device *dev);
+static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *dev);
+static struct net_device_stats *bond_get_stats(struct net_device *dev);
+static void bond_mii_monitor(struct net_device *dev);
+static void loadbalance_arp_monitor(struct net_device *dev);
+static void activebackup_arp_monitor(struct net_device *dev);
+static int bond_event(struct notifier_block *this, unsigned long event, void *ptr);
+static void bond_mc_list_destroy(struct bonding *bond);
+static void bond_mc_add(bonding_t *bond, void *addr, int alen);
+static void bond_mc_delete(bonding_t *bond, void *addr, int alen);
+static int bond_mc_list_copy (struct dev_mc_list *src, struct bonding *dst, int gpf_flag);
+static inline int dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list *dmi2);
+static void bond_set_promiscuity(bonding_t *bond, int inc);
+static void bond_set_allmulti(bonding_t *bond, int inc);
+static struct dev_mc_list* bond_mc_list_find_dmi(struct dev_mc_list *dmi, struct dev_mc_list *mc_list);
+static void bond_mc_update(bonding_t *bond, slave_t *new, slave_t *old);
+static int bond_enslave(struct net_device *master, struct net_device *slave);
+static int bond_release(struct net_device *master, struct net_device *slave);
+static int bond_release_all(struct net_device *master);
+static int bond_sethwaddr(struct net_device *master, struct net_device *slave);
+
+/*
+ * bond_get_info is the interface into the /proc filesystem.  This is
+ * a different interface than the BOND_INFO_QUERY ioctl.  That is done
+ * through the generic networking ioctl interface, and bond_info_query
+ * is the internal function which provides that information.
+ */
+static int bond_get_info(char *buf, char **start, off_t offset, int length);
+
+/* Caller must hold bond->ptrlock for write */
+static inline struct slave*
+bond_assign_current_slave(struct bonding *bond,struct slave *newslave)
+{
+	if ((bond_mode == BOND_MODE_TLB) ||
+	    (bond_mode == BOND_MODE_ALB)) {
+		bond_alb_assign_current_slave(bond, newslave);
+	} else {
+		bond->current_slave = newslave;
+	}
+
+	return bond->current_slave;
+}
+
+/* #define BONDING_DEBUG 1 */
+
+/* several macros */
+
+static void arp_send_all(slave_t *slave)
+{	
+	int i; 
+
+	for (i = 0; (i<MAX_ARP_IP_TARGETS) && arp_target[i]; i++) { 
+		arp_send(ARPOP_REQUEST, ETH_P_ARP, arp_target[i], slave->dev, 
+			 my_ip, arp_target_hw_addr, slave->dev->dev_addr,
+			 arp_target_hw_addr); 
+	} 
+}
+ 
+
+static const char *
+bond_mode_name(void)
+{
+	switch (bond_mode) {
+	case BOND_MODE_ROUNDROBIN :
+		return "load balancing (round-robin)";
+	case BOND_MODE_ACTIVEBACKUP :
+		return "fault-tolerance (active-backup)";
+	case BOND_MODE_XOR :
+		return "load balancing (xor)";
+	case BOND_MODE_BROADCAST :
+		return "fault-tolerance (broadcast)";
+	case BOND_MODE_8023AD:
+		return "IEEE 802.3ad Dynamic link aggregation";
+	case BOND_MODE_TLB:
+		return "transmit load balancing";
+	case BOND_MODE_ALB:
+		return "adaptive load balancing";
+	default:
+		return "unknown";
+	}
+}
+
+static const char *
+multicast_mode_name(void)
+{
+	switch(multicast_mode) {
+	case BOND_MULTICAST_DISABLED :
+		return "disabled";
+	case BOND_MULTICAST_ACTIVE :
+		return "active slave only";
+	case BOND_MULTICAST_ALL :
+		return "all slaves";
+	default :
+		return "unknown";
+	}
+}
+
+void bond_set_slave_inactive_flags(slave_t *slave)
+{
+	slave->state = BOND_STATE_BACKUP;
+	slave->dev->flags |= IFF_NOARP;
+}
+
+void bond_set_slave_active_flags(slave_t *slave)
+{
+	slave->state = BOND_STATE_ACTIVE;
+	slave->dev->flags &= ~IFF_NOARP;
+}
+
+/*
+ * This function counts and verifies the the number of attached
+ * slaves, checking the count against the expected value (given that incr
+ * is either 1 or -1, for add or removal of a slave).  Only
+ * bond_xmit_xor() uses the slave_cnt value, but this is still a good
+ * consistency check.
+ */
+static inline void
+update_slave_cnt(bonding_t *bond, int incr)
+{
+	slave_t *slave = NULL;
+	int expect = bond->slave_cnt + incr;
+
+	bond->slave_cnt = 0;
+	for (slave = bond->prev; slave != (slave_t*)bond;
+	     slave = slave->prev) {
+		bond->slave_cnt++;
+	}
+
+	if (expect != bond->slave_cnt)
+		BUG();
+}
+
+/* 
+ * This function detaches the slave <slave> from the list <bond>.
+ * WARNING: no check is made to verify if the slave effectively
+ * belongs to <bond>. It returns <slave> in case it's needed.
+ * Nothing is freed on return, structures are just unchained.
+ * If the bond->current_slave pointer was pointing to <slave>,
+ * it's replaced with bond->next, or NULL if not applicable.
+ *
+ * bond->lock held for writing by caller.
+ */
+static slave_t *
+bond_detach_slave(bonding_t *bond, slave_t *slave)
+{
+	if ((bond == NULL) || (slave == NULL) ||
+	   ((void *)bond == (void *)slave)) {
+		printk(KERN_ERR
+			"bond_detach_slave(): trying to detach "
+			"slave %p from bond %p\n", bond, slave);
+		return slave;
+	}
+
+	if (bond->next == slave) {  /* is the slave at the head ? */
+		if (bond->prev == slave) {  /* is the slave alone ? */
+			bond->prev = bond->next = (slave_t *)bond;
+		} else { /* not alone */
+			bond->next        = slave->next;
+			slave->next->prev = (slave_t *)bond;
+			bond->prev->next  = slave->next;
+		}
+	} else {
+		slave->prev->next = slave->next;
+		if (bond->prev == slave) {  /* is this slave the last one ? */
+			bond->prev = slave->prev;
+		} else {
+			slave->next->prev = slave->prev;
+		}
+	}
+
+	update_slave_cnt(bond, -1);
+
+	/* no need to hold ptrlock since bond lock is
+	 * already held for writing
+	 */
+	if (slave == bond->current_slave) {
+		if ( bond->next != (slave_t *)bond) {  /* found one slave */
+			bond_assign_current_slave(bond, bond->next);
+		} else {
+			bond_assign_current_slave(bond, NULL);
+		}
+	}
+
+	return slave;
+}
+
+/*
+ * This function attaches the slave <slave> to the list <bond>.
+ *
+ * bond->lock held for writing by caller.
+ */
+static void
+bond_attach_slave(struct bonding *bond, struct slave *new_slave)
+{
+	/* 
+	 * queue to the end of the slaves list, make the first element its
+	 * successor, the last one its predecessor, and make it the bond's
+	 * predecessor. 
+	 *
+	 * Just to clarify, so future bonding driver hackers don't go through
+	 * the same confusion stage I did trying to figure this out, the
+	 * slaves are stored in a double linked circular list, sortof.
+	 * In the ->next direction, the last slave points to the first slave,
+	 * bypassing bond; only the slaves are in the ->next direction.
+	 * In the ->prev direction, however, the first slave points to bond
+	 * and bond points to the last slave.
+	 *
+	 * It looks like a circle with a little bubble hanging off one side
+	 * in the ->prev direction only.
+	 *
+	 * When going through the list once, its best to start at bond->prev
+	 * and go in the ->prev direction, testing for bond.  Doing this
+	 * in the ->next direction doesn't work.  Trust me, I know this now.
+	 * :)  -mts 2002.03.14
+	 */
+	new_slave->prev       = bond->prev;
+	new_slave->prev->next = new_slave;
+	bond->prev            = new_slave;
+	new_slave->next       = bond->next;
+
+	update_slave_cnt(bond, 1);
+}
+
+
+/*
+ * Less bad way to call ioctl from within the kernel; this needs to be
+ * done some other way to get the call out of interrupt context.
+ * Needs "ioctl" variable to be supplied by calling context.
+ */
+#define IOCTL(dev, arg, cmd) ({		\
+	int ret;			\
+	mm_segment_t fs = get_fs();	\
+	set_fs(get_ds());		\
+	ret = ioctl(dev, arg, cmd);	\
+	set_fs(fs);			\
+	ret; })
+
+/*
+ * Get link speed and duplex from the slave's base driver
+ * using ethtool. If for some reason the call fails or the
+ * values are invalid, fake speed and duplex to 100/Full
+ * and return error.
+ */
+static int bond_update_speed_duplex(struct slave *slave)
+{
+	struct net_device *dev = slave->dev;
+	static int (* ioctl)(struct net_device *, struct ifreq *, int);
+	struct ifreq ifr;
+	struct ethtool_cmd etool;
+
+	ioctl = dev->do_ioctl;
+	if (ioctl) {
+		etool.cmd = ETHTOOL_GSET;
+		ifr.ifr_data = (char*)&etool;
+		if (IOCTL(dev, &ifr, SIOCETHTOOL) == 0) {
+			slave->speed = etool.speed;
+			slave->duplex = etool.duplex;
+		} else {
+			goto err_out;
+		}
+	} else {
+		goto err_out;
+	}
+
+	switch (slave->speed) {
+		case SPEED_10:
+		case SPEED_100:
+		case SPEED_1000:
+			break;
+		default:
+			goto err_out;
+	}
+
+	switch (slave->duplex) {
+		case DUPLEX_FULL:
+		case DUPLEX_HALF:
+			break;
+		default:
+			goto err_out;
+	}
+
+	return 0;
+
+err_out:
+	/* Fake speed and duplex */
+	slave->speed = SPEED_100;
+	slave->duplex = DUPLEX_FULL;
+	return -1;
+}
+
+/* 
+ * if <dev> supports MII link status reporting, check its link status.
+ *
+ * We either do MII/ETHTOOL ioctls, or check netif_carrier_ok(),
+ * depening upon the setting of the use_carrier parameter.
+ *
+ * Return either BMSR_LSTATUS, meaning that the link is up (or we
+ * can't tell and just pretend it is), or 0, meaning that the link is
+ * down.
+ *
+ * If reporting is non-zero, instead of faking link up, return -1 if
+ * both ETHTOOL and MII ioctls fail (meaning the device does not
+ * support them).  If use_carrier is set, return whatever it says.
+ * It'd be nice if there was a good way to tell if a driver supports
+ * netif_carrier, but there really isn't.
+ */
+static int
+bond_check_dev_link(struct net_device *dev, int reporting)
+{
+	static int (* ioctl)(struct net_device *, struct ifreq *, int);
+	struct ifreq ifr;
+	struct mii_ioctl_data *mii;
+	struct ethtool_value etool;
+
+	if (use_carrier) {
+		return netif_carrier_ok(dev) ? BMSR_LSTATUS : 0;
+	}
+
+	ioctl = dev->do_ioctl;
+	if (ioctl) {
+		/* TODO: set pointer to correct ioctl on a per team member */
+		/*       bases to make this more efficient. that is, once  */
+		/*       we determine the correct ioctl, we will always    */
+		/*       call it and not the others for that team          */
+		/*       member.                                           */
+
+		/*
+		 * We cannot assume that SIOCGMIIPHY will also read a
+		 * register; not all network drivers (e.g., e100)
+		 * support that.
+		 */
+
+		/* Yes, the mii is overlaid on the ifreq.ifr_ifru */
+		mii = (struct mii_ioctl_data *)&ifr.ifr_data;
+		if (IOCTL(dev, &ifr, SIOCGMIIPHY) == 0) {
+			mii->reg_num = MII_BMSR;
+			if (IOCTL(dev, &ifr, SIOCGMIIREG) == 0) {
+				return mii->val_out & BMSR_LSTATUS;
+			}
+		}
+
+		/* try SIOCETHTOOL ioctl, some drivers cache ETHTOOL_GLINK */
+		/* for a period of time so we attempt to get link status   */
+		/* from it last if the above MII ioctls fail...            */
+	        etool.cmd = ETHTOOL_GLINK;
+	        ifr.ifr_data = (char*)&etool;
+		if (IOCTL(dev, &ifr, SIOCETHTOOL) == 0) {
+			if (etool.data == 1) {
+				return BMSR_LSTATUS;
+			} else { 
+#ifdef BONDING_DEBUG
+				printk(KERN_INFO 
+					":: SIOCETHTOOL shows link down \n");
+#endif
+				return 0;
+			} 
+		}
+
+	}
+ 
+	/*
+	 * If reporting, report that either there's no dev->do_ioctl,
+	 * or both SIOCGMIIREG and SIOCETHTOOL failed (meaning that we
+	 * cannot report link status).  If not reporting, pretend
+	 * we're ok.
+	 */
+	return reporting ? -1 : BMSR_LSTATUS;
+}
+
+static u16 bond_check_mii_link(bonding_t *bond)
+{
+	int has_active_interface = 0;
+
+	read_lock_bh(&bond->lock);
+	read_lock(&bond->ptrlock);
+	has_active_interface = (bond->current_slave != NULL);
+	read_unlock(&bond->ptrlock);
+	read_unlock_bh(&bond->lock);
+
+	return (has_active_interface ? BMSR_LSTATUS : 0);
+}
+
+/* register to receive lacpdus on a bond */
+static void bond_register_lacpdu(struct bonding *bond)
+{
+	struct packet_type* pk_type = &(BOND_AD_INFO(bond).ad_pkt_type);
+
+	/* initialize packet type */
+	pk_type->type = PKT_TYPE_LACPDU;
+	pk_type->dev = bond->device;
+	pk_type->func = bond_3ad_lacpdu_recv;
+	pk_type->data = (void*)1;  /* understand shared skbs */
+
+	dev_add_pack(pk_type);
+}
+
+/* unregister to receive lacpdus on a bond */
+static void bond_unregister_lacpdu(struct bonding *bond)
+{
+	dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type));
+}
+
+static int bond_open(struct net_device *dev)
+{
+	struct bonding *bond = (struct bonding *)(dev->priv);
+	struct timer_list *timer = &((struct bonding *)(dev->priv))->mii_timer;
+	struct timer_list *arp_timer = &((struct bonding *)(dev->priv))->arp_timer;
+
+	if ((bond_mode == BOND_MODE_TLB) ||
+	    (bond_mode == BOND_MODE_ALB)) {
+		struct timer_list *alb_timer = &(BOND_ALB_INFO(bond).alb_timer);
+
+		/* bond_alb_initialize must be called before the timer
+		 * is started.
+		 */
+		if (bond_alb_initialize(bond, (bond_mode == BOND_MODE_ALB))) {
+			/* something went wrong - fail the open operation */
+			return -1;
+		}
+
+		init_timer(alb_timer);
+		alb_timer->expires  = jiffies + 1;
+		alb_timer->data     = (unsigned long)bond;
+		alb_timer->function = (void *)&bond_alb_monitor;
+		add_timer(alb_timer);
+	}
+
+	MOD_INC_USE_COUNT;
+
+	if (miimon > 0) {  /* link check interval, in milliseconds. */
+		init_timer(timer);
+		timer->expires  = jiffies + (miimon * HZ / 1000);
+		timer->data     = (unsigned long)dev;
+		timer->function = (void *)&bond_mii_monitor;
+		add_timer(timer);
+	}
+
+	if (arp_interval> 0) {  /* arp interval, in milliseconds. */
+		init_timer(arp_timer);
+		arp_timer->expires  = jiffies + (arp_interval * HZ / 1000);
+		arp_timer->data     = (unsigned long)dev;
+		if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
+			arp_timer->function = (void *)&activebackup_arp_monitor;
+		} else {
+			arp_timer->function = (void *)&loadbalance_arp_monitor;
+		}
+		add_timer(arp_timer);
+	}
+
+	if (bond_mode == BOND_MODE_8023AD) {
+		struct timer_list *ad_timer = &(BOND_AD_INFO(bond).ad_timer);
+		init_timer(ad_timer);
+		ad_timer->expires  = jiffies + (AD_TIMER_INTERVAL * HZ / 1000);
+		ad_timer->data     = (unsigned long)bond;
+		ad_timer->function = (void *)&bond_3ad_state_machine_handler;
+		add_timer(ad_timer);
+
+		/* register to receive LACPDUs */
+		bond_register_lacpdu(bond);
+	}
+
+	return 0;
+}
+
+static int bond_close(struct net_device *master)
+{
+	bonding_t *bond = (struct bonding *) master->priv;
+
+	write_lock_bh(&bond->lock);
+
+	if (miimon > 0) {  /* link check interval, in milliseconds. */
+		del_timer(&bond->mii_timer);
+	}
+	if (arp_interval> 0) {  /* arp interval, in milliseconds. */
+		del_timer(&bond->arp_timer);
+                if (arp_target_hw_addr != NULL) {
+			kfree(arp_target_hw_addr); 
+			arp_target_hw_addr = NULL;
+		}
+	}
+
+	if (bond_mode == BOND_MODE_8023AD) {
+		del_timer_sync(&(BOND_AD_INFO(bond).ad_timer));
+
+		/* Unregister the receive of LACPDUs */
+		bond_unregister_lacpdu(bond);
+	}
+
+	bond_mc_list_destroy (bond);
+
+	write_unlock_bh(&bond->lock);
+
+	/* Release the bonded slaves */
+	bond_release_all(master);
+
+	if ((bond_mode == BOND_MODE_TLB) ||
+	    (bond_mode == BOND_MODE_ALB)) {
+		del_timer_sync(&(BOND_ALB_INFO(bond).alb_timer));
+
+		bond_alb_deinitialize(bond);
+	}
+
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+/* 
+ * flush all members of flush->mc_list from device dev->mc_list
+ */
+static void bond_mc_list_flush(struct net_device *dev, struct net_device *flush)
+{ 
+	struct dev_mc_list *dmi; 
+ 
+	for (dmi = flush->mc_list; dmi != NULL; dmi = dmi->next) 
+		dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
+
+	if (bond_mode == BOND_MODE_8023AD) {
+		/* del lacpdu mc addr from mc list */
+		u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
+
+		dev_mc_delete(dev, lacpdu_multicast, ETH_ALEN, 0);
+	}
+}
+
+/*
+ * Totally destroys the mc_list in bond
+ */
+static void bond_mc_list_destroy(struct bonding *bond)
+{
+	struct dev_mc_list *dmi;
+
+	dmi = bond->mc_list; 
+	while (dmi) { 
+		bond->mc_list = dmi->next; 
+		kfree(dmi); 
+		dmi = bond->mc_list; 
+	}
+}
+
+/*
+ * Add a Multicast address to every slave in the bonding group
+ */
+static void bond_mc_add(bonding_t *bond, void *addr, int alen)
+{ 
+	slave_t *slave;
+	switch (multicast_mode) {
+	case BOND_MULTICAST_ACTIVE :
+		/* write lock already acquired */
+		if (bond->current_slave != NULL)
+			dev_mc_add(bond->current_slave->dev, addr, alen, 0);
+		break;
+	case BOND_MULTICAST_ALL :
+		for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev)
+			dev_mc_add(slave->dev, addr, alen, 0);
+		break;
+	case BOND_MULTICAST_DISABLED :
+		break;
+	}
+} 
+
+/*
+ * Remove a multicast address from every slave in the bonding group
+ */
+static void bond_mc_delete(bonding_t *bond, void *addr, int alen)
+{ 
+	slave_t *slave; 
+	switch (multicast_mode) {
+	case BOND_MULTICAST_ACTIVE :
+		/* write lock already acquired */
+		if (bond->current_slave != NULL)
+			dev_mc_delete(bond->current_slave->dev, addr, alen, 0);
+		break;
+	case BOND_MULTICAST_ALL :
+		for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev)
+			dev_mc_delete(slave->dev, addr, alen, 0);
+		break;
+	case BOND_MULTICAST_DISABLED :
+		break;
+	}
+} 
+
+/*
+ * Copy all the Multicast addresses from src to the bonding device dst
+ */
+static int bond_mc_list_copy (struct dev_mc_list *src, struct bonding *dst,
+ int gpf_flag)
+{
+	struct dev_mc_list *dmi, *new_dmi;
+
+   	for (dmi = src; dmi != NULL; dmi = dmi->next) { 
+		new_dmi = kmalloc(sizeof(struct dev_mc_list), gpf_flag);
+
+		if (new_dmi == NULL) {
+			return -ENOMEM; 
+		}
+
+		new_dmi->next = dst->mc_list; 
+		dst->mc_list = new_dmi;
+
+		new_dmi->dmi_addrlen = dmi->dmi_addrlen; 
+		memcpy(new_dmi->dmi_addr, dmi->dmi_addr, dmi->dmi_addrlen); 
+		new_dmi->dmi_users = dmi->dmi_users;
+		new_dmi->dmi_gusers = dmi->dmi_gusers; 
+	} 
+	return 0;
+}
+
+/*
+ * Returns 0 if dmi1 and dmi2 are the same, non-0 otherwise
+ */
+static inline int dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list *dmi2)
+{ 
+	return memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0 &&
+	 dmi1->dmi_addrlen == dmi2->dmi_addrlen;
+} 
+
+/*
+ * Push the promiscuity flag down to all slaves
+ */
+static void bond_set_promiscuity(bonding_t *bond, int inc)
+{ 
+	slave_t *slave; 
+	switch (multicast_mode) {
+	case BOND_MULTICAST_ACTIVE :
+		/* write lock already acquired */
+		if (bond->current_slave != NULL)
+			dev_set_promiscuity(bond->current_slave->dev, inc);
+		break;
+	case BOND_MULTICAST_ALL :
+		for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev)
+			dev_set_promiscuity(slave->dev, inc);
+		break;
+	case BOND_MULTICAST_DISABLED :
+		break;
+	}
+} 
+
+/*
+ * Push the allmulti flag down to all slaves
+ */
+static void bond_set_allmulti(bonding_t *bond, int inc)
+{ 
+	slave_t *slave; 
+	switch (multicast_mode) {
+	case BOND_MULTICAST_ACTIVE : 
+		/* write lock already acquired */
+		if (bond->current_slave != NULL)
+			dev_set_allmulti(bond->current_slave->dev, inc);
+		break;
+	case BOND_MULTICAST_ALL :
+		for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev)
+			dev_set_allmulti(slave->dev, inc);
+		break;
+	case BOND_MULTICAST_DISABLED :
+		break;
+	}
+} 
+
+/* 
+ * returns dmi entry if found, NULL otherwise 
+ */
+static struct dev_mc_list* bond_mc_list_find_dmi(struct dev_mc_list *dmi,
+ struct dev_mc_list *mc_list)
+{ 
+	struct dev_mc_list *idmi;
+
+	for (idmi = mc_list; idmi != NULL; idmi = idmi->next) {
+		if (dmi_same(dmi, idmi)) {
+			return idmi; 
+		}
+	}
+	return NULL;
+} 
+
+static void set_multicast_list(struct net_device *master)
+{
+	bonding_t *bond = master->priv;
+	struct dev_mc_list *dmi;
+
+	if (multicast_mode == BOND_MULTICAST_DISABLED)
+		return;
+	/*
+	 * Lock the private data for the master
+	 */
+	write_lock_bh(&bond->lock);
+
+	/* set promiscuity flag to slaves */
+	if ( (master->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC) )
+		bond_set_promiscuity(bond, 1); 
+
+	if ( !(master->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC) ) 
+		bond_set_promiscuity(bond, -1); 
+
+	/* set allmulti flag to slaves */ 
+	if ( (master->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI) ) 
+		bond_set_allmulti(bond, 1); 
+
+	if ( !(master->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI) )
+		bond_set_allmulti(bond, -1); 
+
+	bond->flags = master->flags; 
+
+	/* looking for addresses to add to slaves' mc list */ 
+	for (dmi = master->mc_list; dmi != NULL; dmi = dmi->next) { 
+		if (bond_mc_list_find_dmi(dmi, bond->mc_list) == NULL) 
+		 bond_mc_add(bond, dmi->dmi_addr, dmi->dmi_addrlen); 
+	} 
+
+	/* looking for addresses to delete from slaves' list */ 
+	for (dmi = bond->mc_list; dmi != NULL; dmi = dmi->next) { 
+		if (bond_mc_list_find_dmi(dmi, master->mc_list) == NULL) 
+		 bond_mc_delete(bond, dmi->dmi_addr, dmi->dmi_addrlen); 
+	}
+
+
+	/* save master's multicast list */ 
+	bond_mc_list_destroy (bond);
+	bond_mc_list_copy (master->mc_list, bond, GFP_ATOMIC);
+
+	write_unlock_bh(&bond->lock);
+}
+
+/*
+ * Update the mc list and multicast-related flags for the new and 
+ * old active slaves (if any) according to the multicast mode
+ */
+static void bond_mc_update(bonding_t *bond, slave_t *new, slave_t *old)
+{
+	struct dev_mc_list *dmi;
+
+	switch(multicast_mode) {
+	case BOND_MULTICAST_ACTIVE :		
+		if (bond->device->flags & IFF_PROMISC) {
+			if (old != NULL && new != old)
+				dev_set_promiscuity(old->dev, -1);
+			dev_set_promiscuity(new->dev, 1);
+		}
+		if (bond->device->flags & IFF_ALLMULTI) {
+			if (old != NULL && new != old)
+				dev_set_allmulti(old->dev, -1);
+			dev_set_allmulti(new->dev, 1);
+		}
+		/* first remove all mc addresses from old slave if any,
+		   and _then_ add them to new active slave */
+		if (old != NULL && new != old) {
+			for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next)
+				dev_mc_delete(old->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
+		}
+		for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next)
+			dev_mc_add(new->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
+		break;
+	case BOND_MULTICAST_ALL :
+		/* nothing to do: mc list is already up-to-date on all slaves */
+		break;
+	case BOND_MULTICAST_DISABLED :
+		break;
+	}
+}
+
+/* enslave device <slave> to bond device <master> */
+static int bond_enslave(struct net_device *master_dev, 
+                        struct net_device *slave_dev)
+{
+	bonding_t *bond = NULL;
+	slave_t *new_slave = NULL;
+	unsigned long rflags = 0;
+	int err = 0;
+	struct dev_mc_list *dmi;
+	struct in_ifaddr **ifap;
+	struct in_ifaddr *ifa;
+	int link_reporting;
+	struct sockaddr addr;
+
+	if (master_dev == NULL || slave_dev == NULL) {
+		return -ENODEV;
+	}
+	bond = (struct bonding *) master_dev->priv;
+
+	if (slave_dev->do_ioctl == NULL) {
+		printk(KERN_DEBUG
+			"Warning : no link monitoring support for %s\n",
+			slave_dev->name);
+	}
+
+
+	/* bond must be initialized by bond_open() before enslaving */
+	if (!(master_dev->flags & IFF_UP)) {
+#ifdef BONDING_DEBUG
+		printk(KERN_CRIT "Error, master_dev is not up\n");
+#endif
+		return -EPERM;
+	}
+
+	/* already enslaved */
+	if (master_dev->flags & IFF_SLAVE || slave_dev->flags & IFF_SLAVE) {
+#ifdef BONDING_DEBUG
+		printk(KERN_CRIT "Error, Device was already enslaved\n");
+#endif
+		return -EBUSY;
+	}
+
+	if (app_abi_ver >= 1) {
+		/* The application is using an ABI, which requires the
+		 * slave interface to be closed.
+		 */
+		if ((slave_dev->flags & IFF_UP)) {
+#ifdef BONDING_DEBUG
+			printk(KERN_CRIT "Error, slave_dev is up\n");
+#endif
+			return -EPERM;
+		}
+
+		if (slave_dev->set_mac_address == NULL) {
+			printk(KERN_CRIT
+			       "The slave device you specified does not support"
+			       " setting the MAC address.\n");
+			printk(KERN_CRIT
+			       "Your kernel likely does not support slave"
+			       " devices.\n");
+
+			return -EOPNOTSUPP;
+		}
+	} else {
+		/* The application is not using an ABI, which requires the
+		 * slave interface to be open.
+		 */
+		if (!(slave_dev->flags & IFF_UP)) {
+#ifdef BONDING_DEBUG
+			printk(KERN_CRIT "Error, slave_dev is not running\n");
+#endif
+			return -EINVAL;
+		}
+
+		if ((bond_mode == BOND_MODE_8023AD) ||
+		    (bond_mode == BOND_MODE_TLB) ||
+		    (bond_mode == BOND_MODE_ALB)) {
+			printk(KERN_ERR
+			       "bonding: Error: to use %s mode, you must "
+			       "upgrade ifenslave.\n", bond_mode_name());
+			return -EOPNOTSUPP;
+		}
+	}
+
+	if ((new_slave = kmalloc(sizeof(slave_t), GFP_KERNEL)) == NULL) {
+		return -ENOMEM;
+	}
+	memset(new_slave, 0, sizeof(slave_t));
+
+	/* save slave's original flags before calling
+	 * netdev_set_master and dev_open
+	 */
+	new_slave->original_flags = slave_dev->flags;
+
+	if (app_abi_ver >= 1) {
+		/* save slave's original ("permanent") mac address for
+		 * modes that needs it, and for restoring it upon release,
+		 * and then set it to the master's address
+		 */
+		memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN);
+
+		if (bond->slave_cnt > 0) {
+			/* set slave to master's mac address
+			 * The application already set the master's
+			 * mac address to that of the first slave
+			 */
+			memcpy(addr.sa_data, master_dev->dev_addr, ETH_ALEN);
+			addr.sa_family = slave_dev->type;
+			err = slave_dev->set_mac_address(slave_dev, &addr);
+			if (err) {
+#ifdef BONDING_DEBUG
+				printk(KERN_CRIT "Error %d calling set_mac_address\n", err);
+#endif
+				goto err_free;
+			}
+		}
+
+		/* open the slave since the application closed it */
+		err = dev_open(slave_dev);
+		if (err) {
+#ifdef BONDING_DEBUG
+			printk(KERN_CRIT "Openning slave %s failed\n", slave_dev->name);
+#endif
+			goto err_restore_mac;
+		}
+	}
+
+	err = netdev_set_master(slave_dev, master_dev);
+	if (err) {
+#ifdef BONDING_DEBUG
+		printk(KERN_CRIT "Error %d calling netdev_set_master\n", err);
+#endif
+		if (app_abi_ver < 1) {
+			goto err_free;
+		} else {
+			goto err_close;
+		}
+	}
+
+	new_slave->dev = slave_dev;
+
+	if ((bond_mode == BOND_MODE_TLB) ||
+	    (bond_mode == BOND_MODE_ALB)) {
+		/* bond_alb_init_slave() must be called before all other stages since
+		 * it might fail and we do not want to have to undo everything
+		 */
+		err = bond_alb_init_slave(bond, new_slave);
+		if (err) {
+			goto err_unset_master;
+		}
+	}
+
+	if (multicast_mode == BOND_MULTICAST_ALL) {
+		/* set promiscuity level to new slave */ 
+		if (master_dev->flags & IFF_PROMISC)
+			dev_set_promiscuity(slave_dev, 1); 
+ 
+		/* set allmulti level to new slave */
+		if (master_dev->flags & IFF_ALLMULTI) 
+			dev_set_allmulti(slave_dev, 1); 
+		
+		/* upload master's mc_list to new slave */ 
+		for (dmi = master_dev->mc_list; dmi != NULL; dmi = dmi->next) 
+			dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
+	}
+
+	if (bond_mode == BOND_MODE_8023AD) {
+		/* add lacpdu mc addr to mc list */
+		u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
+
+		dev_mc_add(slave_dev, lacpdu_multicast, ETH_ALEN, 0);
+	}
+
+	write_lock_bh(&bond->lock);
+	
+	bond_attach_slave(bond, new_slave);
+	new_slave->delay = 0;
+	new_slave->link_failure_count = 0;
+
+	if (miimon > 0 && !use_carrier) {
+		link_reporting = bond_check_dev_link(slave_dev, 1);
+
+		if ((link_reporting == -1) && (arp_interval == 0)) {
+			/*
+			 * miimon is set but a bonded network driver
+			 * does not support ETHTOOL/MII and
+			 * arp_interval is not set.  Note: if
+			 * use_carrier is enabled, we will never go
+			 * here (because netif_carrier is always
+			 * supported); thus, we don't need to change
+			 * the messages for netif_carrier.
+			 */ 
+			printk(KERN_ERR
+				"bond_enslave(): MII and ETHTOOL support not "
+				"available for interface %s, and "
+				"arp_interval/arp_ip_target module parameters "
+		       		"not specified, thus bonding will not detect "
+				"link failures! see bonding.txt for details.\n",
+		       		slave_dev->name);
+		} else if (link_reporting == -1) {
+			/* unable  get link status using mii/ethtool */
+			printk(KERN_WARNING 
+			       "bond_enslave: can't get link status from "
+			       "interface %s; the network driver associated "
+			       "with this interface does not support "
+			       "MII or ETHTOOL link status reporting, thus "
+			       "miimon has no effect on this interface.\n", 
+			       slave_dev->name);
+		}
+	}
+
+	/* check for initial state */
+	if ((miimon <= 0) ||
+	    (bond_check_dev_link(slave_dev, 0) == BMSR_LSTATUS)) {
+		if (updelay) {
+#ifdef BONDING_DEBUG
+			printk(KERN_CRIT "Initial state of slave_dev is "
+			       "BOND_LINK_BACK\n");
+#endif
+			new_slave->link  = BOND_LINK_BACK;
+			new_slave->delay = updelay;
+		}
+		else {
+#ifdef BONDING_DEBUG
+			printk(KERN_DEBUG "Initial state of slave_dev is "
+				"BOND_LINK_UP\n");
+#endif
+			new_slave->link  = BOND_LINK_UP;
+		}
+		new_slave->jiffies = jiffies;
+	}
+	else {
+#ifdef BONDING_DEBUG
+		printk(KERN_CRIT "Initial state of slave_dev is "
+			"BOND_LINK_DOWN\n");
+#endif
+		new_slave->link  = BOND_LINK_DOWN;
+	}
+
+	if (bond_update_speed_duplex(new_slave) &&
+	    (new_slave->link != BOND_LINK_DOWN)) {
+
+		printk(KERN_WARNING
+		       "bond_enslave(): failed to get speed/duplex from %s, "
+		       "speed forced to 100Mbps, duplex forced to Full.\n",
+		       new_slave->dev->name);
+		if (bond_mode == BOND_MODE_8023AD) {
+			printk(KERN_WARNING
+			       "Operation of 802.3ad mode requires ETHTOOL support "
+			       "in base driver for proper aggregator selection.\n");
+		}
+	}
+
+	/* if we're in active-backup mode, we need one and only one active
+	 * interface. The backup interfaces will have their NOARP flag set
+	 * because we need them to be completely deaf and not to respond to
+	 * any ARP request on the network to avoid fooling a switch. Thus,
+	 * since we guarantee that current_slave always point to the last
+	 * usable interface, we just have to verify this interface's flag.
+	 */
+	if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
+		if (((bond->current_slave == NULL)
+			|| (bond->current_slave->dev->flags & IFF_NOARP))
+			&& (new_slave->link != BOND_LINK_DOWN)) {
+#ifdef BONDING_DEBUG
+			printk(KERN_CRIT "This is the first active slave\n");
+#endif
+			/* first slave or no active slave yet, and this link
+			   is OK, so make this interface the active one */
+			bond_assign_current_slave(bond, new_slave);
+			bond_set_slave_active_flags(new_slave);
+			bond_mc_update(bond, new_slave, NULL);
+		}
+		else {
+#ifdef BONDING_DEBUG
+			printk(KERN_CRIT "This is just a backup slave\n");
+#endif
+			bond_set_slave_inactive_flags(new_slave);
+		}
+		read_lock_irqsave(&(((struct in_device *)slave_dev->ip_ptr)->lock), rflags);
+		ifap= &(((struct in_device *)slave_dev->ip_ptr)->ifa_list);
+		ifa = *ifap;
+		my_ip = ifa->ifa_address;
+		read_unlock_irqrestore(&(((struct in_device *)slave_dev->ip_ptr)->lock), rflags);
+
+		/* if there is a primary slave, remember it */
+		if (primary != NULL) {
+			if (strcmp(primary, new_slave->dev->name) == 0) {
+				bond->primary_slave = new_slave;
+			}
+		}
+	} else if (bond_mode == BOND_MODE_8023AD) {
+		/* in 802.3ad mode, the internal mechanism
+		 * will activate the slaves in the selected
+		 * aggregator
+		 */
+		bond_set_slave_inactive_flags(new_slave);
+		/* if this is the first slave */
+		if (new_slave == bond->next) {
+			SLAVE_AD_INFO(new_slave).id = 1;
+			/* Initialize AD with the number of times that the AD timer is called in 1 second
+			 * can be called only after the mac address of the bond is set
+			 */
+			bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL,
+					    lacp_fast);
+		} else {
+			SLAVE_AD_INFO(new_slave).id =
+			SLAVE_AD_INFO(new_slave->prev).id + 1;
+		}
+
+		bond_3ad_bind_slave(new_slave);
+	} else if ((bond_mode == BOND_MODE_TLB) ||
+		   (bond_mode == BOND_MODE_ALB)) {
+		new_slave->state = BOND_STATE_ACTIVE;
+		if ((bond->current_slave == NULL) && (new_slave->link != BOND_LINK_DOWN)) {
+			/* first slave or no active slave yet, and this link
+			 * is OK, so make this interface the active one
+			 */
+			bond_assign_current_slave(bond, new_slave);
+		}
+
+		/* if there is a primary slave, remember it */
+		if (primary != NULL) {
+			if (strcmp(primary, new_slave->dev->name) == 0) {
+				bond->primary_slave = new_slave;
+			}
+		}
+	} else {
+#ifdef BONDING_DEBUG
+		printk(KERN_CRIT "This slave is always active in trunk mode\n");
+#endif
+		/* always active in trunk mode */
+		new_slave->state = BOND_STATE_ACTIVE;
+		if (bond->current_slave == NULL) 
+			bond_assign_current_slave(bond, new_slave);
+	}
+
+	write_unlock_bh(&bond->lock);
+
+	if (app_abi_ver < 1) {
+		/*
+		 * !!! This is to support old versions of ifenslave.
+		 * We can remove this in 2.5 because our ifenslave takes
+		 * care of this for us.
+		 * We check to see if the master has a mac address yet.
+		 * If not, we'll give it the mac address of our slave device.
+		 */
+		int ndx = 0;
+
+		for (ndx = 0; ndx < slave_dev->addr_len; ndx++) {
+#ifdef BONDING_DEBUG
+			printk(KERN_DEBUG
+			       "Checking ndx=%d of master_dev->dev_addr\n", ndx);
+#endif
+			if (master_dev->dev_addr[ndx] != 0) {
+#ifdef BONDING_DEBUG
+				printk(KERN_DEBUG
+				       "Found non-zero byte at ndx=%d\n", ndx);
+#endif
+				break;
+			}
+		}
+		if (ndx == slave_dev->addr_len) {
+			/*
+			 * We got all the way through the address and it was
+			 * all 0's.
+			 */
+#ifdef BONDING_DEBUG
+			printk(KERN_DEBUG "%s doesn't have a MAC address yet.  ",
+			       master_dev->name);
+			printk(KERN_DEBUG "Going to give assign it from %s.\n",
+			       slave_dev->name);
+#endif
+			bond_sethwaddr(master_dev, slave_dev);
+		}
+	}
+
+	printk (KERN_INFO "%s: enslaving %s as a%s interface with a%s link.\n",
+		master_dev->name, slave_dev->name,
+		new_slave->state == BOND_STATE_ACTIVE ? "n active" : " backup",
+		new_slave->link != BOND_LINK_DOWN ? "n up" : " down");
+
+	/* enslave is successful */
+	return 0;
+
+/* Undo stages on error */
+err_unset_master:
+	netdev_set_master(slave_dev, NULL);
+
+err_close:
+	dev_close(slave_dev);
+
+err_restore_mac:
+	memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN);
+	addr.sa_family = slave_dev->type;
+	slave_dev->set_mac_address(slave_dev, &addr);
+
+err_free:
+	kfree(new_slave);
+	return err;
+}
+
+/* 
+ * This function changes the active slave to slave <slave_dev>.
+ * It returns -EINVAL in the following cases.
+ *  - <slave_dev> is not found in the list.
+ *  - There is not active slave now.
+ *  - <slave_dev> is already active.
+ *  - The link state of <slave_dev> is not BOND_LINK_UP.
+ *  - <slave_dev> is not running.
+ * In these cases, this fuction does nothing.
+ * In the other cases, currnt_slave pointer is changed and 0 is returned.
+ */
+static int bond_change_active(struct net_device *master_dev, struct net_device *slave_dev)
+{
+	bonding_t *bond;
+	slave_t *slave;
+	slave_t *oldactive = NULL;
+	slave_t *newactive = NULL;
+	int ret = 0;
+
+	if (master_dev == NULL || slave_dev == NULL) {
+		return -ENODEV;
+	}
+
+	bond = (struct bonding *) master_dev->priv;
+	write_lock_bh(&bond->lock);
+	slave = (slave_t *)bond;
+	oldactive = bond->current_slave;
+
+	while ((slave = slave->prev) != (slave_t *)bond) {
+		if(slave_dev == slave->dev) {
+			newactive = slave;
+			break;
+		}
+	}
+
+	if ((newactive != NULL)&&
+	    (oldactive != NULL)&&
+	    (newactive != oldactive)&&
+	    (newactive->link == BOND_LINK_UP)&&
+	    IS_UP(newactive->dev)) {
+		bond_set_slave_inactive_flags(oldactive);
+		bond_set_slave_active_flags(newactive);
+		bond_mc_update(bond, newactive, oldactive);
+		bond_assign_current_slave(bond, newactive);
+		printk("%s : activate %s(old : %s)\n",
+			master_dev->name, newactive->dev->name, 
+			oldactive->dev->name);
+	}
+	else {
+		ret = -EINVAL;
+	}
+	write_unlock_bh(&bond->lock);
+	return ret;
+}
+
+/* Choose a new valid interface from the pool, set it active
+ * and make it the current slave. If no valid interface is
+ * found, the oldest slave in BACK state is choosen and
+ * activated. If none is found, it's considered as no
+ * interfaces left so the current slave is set to NULL.
+ * The result is a pointer to the current slave.
+ *
+ * Since this function sends messages tails through printk, the caller
+ * must have started something like `printk(KERN_INFO "xxxx ");'.
+ *
+ * Warning: Caller must hold ptrlock for writing.
+ */
+slave_t *change_active_interface(bonding_t *bond)
+{
+	slave_t *newslave, *oldslave;
+	slave_t *bestslave = NULL;
+	int mintime;
+
+	newslave = oldslave = bond->current_slave;
+
+	if (newslave == NULL) { /* there were no active slaves left */
+		if (bond->next != (slave_t *)bond) {  /* found one slave */
+			newslave = bond_assign_current_slave(bond, bond->next);
+		} else {
+
+			printk (" but could not find any %s interface.\n",
+				(bond_mode == BOND_MODE_ACTIVEBACKUP) ? "backup":"other");
+			bond_assign_current_slave(bond, NULL);
+			return NULL; /* still no slave, return NULL */
+		}
+	} else if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
+		/* make sure oldslave doesn't send arps - this could
+		 * cause a ping-pong effect between interfaces since they
+		 * would be able to tx arps - in active backup only one
+		 * slave should be able to tx arps, and that should be
+		 * the current_slave; the only exception is when all
+		 * slaves have gone down, then only one non-current slave can
+		 * send arps at a time; clearing oldslaves' mc list is handled
+		 * later in this function.
+		 */
+		bond_set_slave_inactive_flags(oldslave);
+	}
+
+	mintime = updelay;
+
+	/* first try the primary link; if arping, a link must tx/rx traffic 
+	 * before it can be considered the current_slave - also, we would skip 
+	 * slaves between the current_slave and primary_slave that may be up 
+	 * and able to arp
+	 */
+	if ((bond->primary_slave != NULL) && (arp_interval == 0)) {
+		if (IS_UP(bond->primary_slave->dev)) 
+			newslave = bond->primary_slave;
+	}
+
+	do {
+		if (IS_UP(newslave->dev)) {
+			if (newslave->link == BOND_LINK_UP) {
+				/* this one is immediately usable */
+				if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
+					bond_set_slave_active_flags(newslave);
+					bond_mc_update(bond, newslave, oldslave);
+					printk (" and making interface %s the active one.\n",
+						newslave->dev->name);
+				}
+				else {
+					printk (" and setting pointer to interface %s.\n",
+						newslave->dev->name);
+				}
+
+				bond_assign_current_slave(bond, newslave);
+				return newslave;
+			}
+			else if (newslave->link == BOND_LINK_BACK) {
+				/* link up, but waiting for stabilization */
+				if (newslave->delay < mintime) {
+					mintime = newslave->delay;
+					bestslave = newslave;
+				}
+			}
+		}
+	} while ((newslave = newslave->next) != oldslave);
+
+	/* no usable backup found, we'll see if we at least got a link that was
+	   coming back for a long time, and could possibly already be usable.
+	*/
+
+	if (bestslave != NULL) {
+		/* early take-over. */
+		printk (" and making interface %s the active one %d ms earlier.\n",
+			bestslave->dev->name,
+			(updelay - bestslave->delay)*miimon);
+
+		bestslave->delay = 0;
+		bestslave->link = BOND_LINK_UP;
+		bestslave->jiffies = jiffies;
+		bond_set_slave_active_flags(bestslave);
+		bond_mc_update(bond, bestslave, oldslave);
+		bond_assign_current_slave(bond, bestslave);
+		return bestslave;
+	}
+
+	if ((bond_mode == BOND_MODE_ACTIVEBACKUP) &&
+	    (multicast_mode == BOND_MULTICAST_ACTIVE) &&
+	    (oldslave != NULL)) {
+		/* flush bonds (master's) mc_list from oldslave since it wasn't
+		 * updated (and deleted) above
+		 */ 
+		bond_mc_list_flush(oldslave->dev, bond->device); 
+		if (bond->device->flags & IFF_PROMISC) {
+			dev_set_promiscuity(oldslave->dev, -1);
+		}
+		if (bond->device->flags & IFF_ALLMULTI) {
+			dev_set_allmulti(oldslave->dev, -1);
+		}
+	}
+
+	printk (" but could not find any %s interface.\n",
+		(bond_mode == BOND_MODE_ACTIVEBACKUP) ? "backup":"other");
+	
+	/* absolutely nothing found. let's return NULL */
+	bond_assign_current_slave(bond, NULL);
+	return NULL;
+}
+
+/*
+ * Try to release the slave device <slave> from the bond device <master>
+ * It is legal to access current_slave without a lock because all the function
+ * is write-locked.
+ *
+ * The rules for slave state should be:
+ *   for Active/Backup:
+ *     Active stays on all backups go down
+ *   for Bonded connections:
+ *     The first up interface should be left on and all others downed.
+ */
+static int bond_release(struct net_device *master, struct net_device *slave)
+{
+	bonding_t *bond;
+	slave_t *our_slave, *old_current;
+	struct sockaddr addr;
+	
+	if (master == NULL || slave == NULL)  {
+		return -ENODEV;
+	}
+
+	bond = (struct bonding *) master->priv;
+
+	/* master already enslaved, or slave not enslaved,
+	   or no slave for this master */
+	if ((master->flags & IFF_SLAVE) || !(slave->flags & IFF_SLAVE)) {
+		printk (KERN_DEBUG "%s: cannot release %s.\n", master->name, slave->name);
+		return -EINVAL;
+	}
+
+	write_lock_bh(&bond->lock);
+	bond->current_arp_slave = NULL;
+	our_slave = (slave_t *)bond;
+	old_current = bond->current_slave;
+	while ((our_slave = our_slave->prev) != (slave_t *)bond) {
+		if (our_slave->dev == slave) {
+			int mac_addr_differ = memcmp(bond->device->dev_addr,
+						 our_slave->perm_hwaddr,
+						 ETH_ALEN);
+			if (!mac_addr_differ && (bond->slave_cnt > 1)) {
+				printk(KERN_WARNING "WARNING: the permanent HWaddr of %s "
+				"- %02X:%02X:%02X:%02X:%02X:%02X - "
+				"is still in use by %s. Set the HWaddr "
+				"of %s to a different address "
+				"to avoid conflicts.\n",
+				       slave->name,
+				       slave->dev_addr[0],
+				       slave->dev_addr[1],
+				       slave->dev_addr[2],
+				       slave->dev_addr[3],
+				       slave->dev_addr[4],
+				       slave->dev_addr[5],
+				       bond->device->name,
+				       slave->name);
+			}
+
+			/* Inform AD package of unbinding of slave. */
+			if (bond_mode == BOND_MODE_8023AD) {
+				/* must be called before the slave is
+				 * detached from the list
+				 */
+				bond_3ad_unbind_slave(our_slave);
+			}
+
+			/* release the slave from its bond */
+			bond_detach_slave(bond, our_slave);
+
+			printk (KERN_INFO "%s: releasing %s interface %s",
+				master->name,
+				(our_slave->state == BOND_STATE_ACTIVE) ? "active" : "backup",
+				slave->name);
+
+			if (our_slave == old_current) {
+				/* find a new interface and be verbose */
+				change_active_interface(bond); 
+			} else {
+				printk(".\n");
+			}
+			
+			if (bond->current_slave == NULL) {
+				printk(KERN_INFO
+					"%s: now running without any active interface !\n",
+					master->name);
+			}
+
+			if (bond->primary_slave == our_slave) {
+				bond->primary_slave = NULL;
+			}
+
+			if ((bond_mode == BOND_MODE_TLB) ||
+			    (bond_mode == BOND_MODE_ALB)) {
+				/* must be called only after the slave has been
+				 * detached from the list and the current_slave
+				 * has been replaced (if our_slave == old_current)
+				 */
+				bond_alb_deinit_slave(bond, our_slave);
+			}
+
+			break;
+		}
+
+	}
+	write_unlock_bh(&bond->lock);
+	
+	if (our_slave == (slave_t *)bond) {
+		/* if we get here, it's because the device was not found */
+		printk (KERN_INFO "%s: %s not enslaved\n", master->name, slave->name);
+		return -EINVAL;
+	}
+
+	/* undo settings and restore original values */
+	
+	if (multicast_mode == BOND_MULTICAST_ALL) {
+		/* flush master's mc_list from slave */ 
+		bond_mc_list_flush (slave, master); 
+
+		/* unset promiscuity level from slave */
+		if (master->flags & IFF_PROMISC) 
+			dev_set_promiscuity(slave, -1); 
+
+		/* unset allmulti level from slave */ 
+		if (master->flags & IFF_ALLMULTI)
+			dev_set_allmulti(slave, -1); 
+	}
+
+	netdev_set_master(slave, NULL);
+
+	/* close slave before restoring its mac address */
+	dev_close(slave);
+
+	if (app_abi_ver >= 1) {
+		/* restore original ("permanent") mac address */
+		memcpy(addr.sa_data, our_slave->perm_hwaddr, ETH_ALEN);
+		addr.sa_family = slave->type;
+		slave->set_mac_address(slave, &addr);
+	}
+
+	/* restore the original state of the
+	 * IFF_NOARP flag that might have been
+	 * set by bond_set_slave_inactive_flags()
+	 */
+	if ((our_slave->original_flags & IFF_NOARP) == 0) {
+		slave->flags &= ~IFF_NOARP;
+	}
+
+	kfree(our_slave);
+
+	/* if the last slave was removed, zero the mac address
+	 * of the master so it will be set by the application
+	 * to the mac address of the first slave
+	 */
+	if (bond->next == (slave_t*)bond) {
+		memset(master->dev_addr, 0, master->addr_len);
+	}
+
+	return 0;  /* deletion OK */
+}
+
+/* 
+ * This function releases all slaves.
+ */
+static int bond_release_all(struct net_device *master)
+{
+	bonding_t *bond;
+	slave_t *our_slave, *old_current;
+	struct net_device *slave_dev;
+	struct sockaddr addr;
+	int err = 0;
+
+	if (master == NULL)  {
+		return -ENODEV;
+	}
+
+	if (master->flags & IFF_SLAVE) {
+		return -EINVAL;
+	}
+
+	bond = (struct bonding *) master->priv;
+
+	write_lock_bh(&bond->lock);
+	if (bond->next == (struct slave *) bond) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	old_current = bond->current_slave;
+	bond_assign_current_slave(bond, NULL);
+	bond->current_arp_slave = NULL;
+	bond->primary_slave = NULL;
+
+	while ((our_slave = bond->prev) != (slave_t *)bond) {
+		/* Inform AD package of unbinding of slave
+		 * before slave is detached from the list.
+		 */
+		if (bond_mode == BOND_MODE_8023AD) {
+			bond_3ad_unbind_slave(our_slave);
+		}
+
+		slave_dev = our_slave->dev;
+		bond_detach_slave(bond, our_slave);
+
+		if ((bond_mode == BOND_MODE_TLB) ||
+		    (bond_mode == BOND_MODE_ALB)) {
+			/* must be called only after the slave
+			 * has been detached from the list
+			 */
+			bond_alb_deinit_slave(bond, our_slave);
+		}
+
+		/* now that the slave is detached, unlock and perform
+		 * all the undo steps that should not be called from
+		 * within a lock.
+		 */
+		write_unlock_bh(&bond->lock);
+
+		if (multicast_mode == BOND_MULTICAST_ALL 
+		    || (multicast_mode == BOND_MULTICAST_ACTIVE 
+			&& old_current == our_slave)) {
+
+			/* flush master's mc_list from slave */ 
+			bond_mc_list_flush (slave_dev, master); 
+
+			/* unset promiscuity level from slave */
+			if (master->flags & IFF_PROMISC) 
+				dev_set_promiscuity(slave_dev, -1); 
+
+			/* unset allmulti level from slave */ 
+			if (master->flags & IFF_ALLMULTI)
+				dev_set_allmulti(slave_dev, -1); 
+		}
+
+		netdev_set_master(slave_dev, NULL);
+
+		/* close slave before restoring its mac address */
+		dev_close(slave_dev);
+
+		if (app_abi_ver >= 1) {
+			/* restore original ("permanent") mac address*/
+			memcpy(addr.sa_data, our_slave->perm_hwaddr, ETH_ALEN);
+			addr.sa_family = slave_dev->type;
+			slave_dev->set_mac_address(slave_dev, &addr);
+		}
+
+		/* restore the original state of the IFF_NOARP flag that might have
+		 * been set by bond_set_slave_inactive_flags()
+		 */
+		if ((our_slave->original_flags & IFF_NOARP) == 0) {
+			slave_dev->flags &= ~IFF_NOARP;
+		}
+
+		kfree(our_slave);
+
+		/* re-acquire the lock before getting the next slave */
+		write_lock_bh(&bond->lock);
+	}
+
+	/* zero the mac address of the master so it will be
+	 * set by the application to the mac address of the
+	 * first slave
+	 */
+	memset(master->dev_addr, 0, master->addr_len);
+
+	printk (KERN_INFO "%s: released all slaves\n", master->name);
+
+out:
+	write_unlock_bh(&bond->lock);
+
+	return err;
+}
+
+/* this function is called regularly to monitor each slave's link. */
+static void bond_mii_monitor(struct net_device *master)
+{
+	bonding_t *bond = (struct bonding *) master->priv;
+	slave_t *slave, *bestslave, *oldcurrent;
+	int slave_died = 0;
+
+	read_lock(&bond->lock);
+
+	/* we will try to read the link status of each of our slaves, and
+	 * set their IFF_RUNNING flag appropriately. For each slave not
+	 * supporting MII status, we won't do anything so that a user-space
+	 * program could monitor the link itself if needed.
+	 */
+
+	bestslave = NULL;
+	slave = (slave_t *)bond;
+
+	read_lock(&bond->ptrlock);
+	oldcurrent = bond->current_slave;
+	read_unlock(&bond->ptrlock);
+
+	while ((slave = slave->prev) != (slave_t *)bond) {
+		/* use updelay+1 to match an UP slave even when updelay is 0 */
+		int mindelay = updelay + 1;
+		struct net_device *dev = slave->dev;
+		int link_state;
+		u16 old_speed = slave->speed;
+		u8 old_duplex = slave->duplex;
+		
+		link_state = bond_check_dev_link(dev, 0);
+
+		switch (slave->link) {
+		case BOND_LINK_UP:	/* the link was up */
+			if (link_state == BMSR_LSTATUS) {
+				/* link stays up, tell that this one
+				   is immediately available */
+				if (IS_UP(dev) && (mindelay > -2)) {
+					/* -2 is the best case :
+					   this slave was already up */
+					mindelay = -2;
+					bestslave = slave;
+				}
+				break;
+			}
+			else { /* link going down */
+				slave->link  = BOND_LINK_FAIL;
+				slave->delay = downdelay;
+				if (slave->link_failure_count < UINT_MAX) {
+					slave->link_failure_count++;
+				}
+				if (downdelay > 0) {
+					printk (KERN_INFO
+						"%s: link status down for %sinterface "
+						"%s, disabling it in %d ms.\n",
+						master->name,
+						IS_UP(dev)
+						? ((bond_mode == BOND_MODE_ACTIVEBACKUP)
+						   ? ((slave == oldcurrent)
+						      ? "active " : "backup ")
+						   : "")
+						: "idle ",
+						dev->name,
+						downdelay * miimon);
+					}
+			}
+			/* no break ! fall through the BOND_LINK_FAIL test to
+			   ensure proper action to be taken
+			*/
+		case BOND_LINK_FAIL:	/* the link has just gone down */
+			if (link_state != BMSR_LSTATUS) {
+				/* link stays down */
+				if (slave->delay <= 0) {
+					/* link down for too long time */
+					slave->link = BOND_LINK_DOWN;
+					/* in active/backup mode, we must
+					 * completely disable this interface
+					 */
+					if ((bond_mode == BOND_MODE_ACTIVEBACKUP) ||
+					    (bond_mode == BOND_MODE_8023AD)) {
+						bond_set_slave_inactive_flags(slave);
+					}
+					printk(KERN_INFO
+						"%s: link status definitely down "
+						"for interface %s, disabling it\n",
+						master->name,
+						dev->name);
+
+					/* notify ad that the link status has changed */
+					if (bond_mode == BOND_MODE_8023AD) {
+						bond_3ad_handle_link_change(slave, BOND_LINK_DOWN);
+					}
+
+					if ((bond_mode == BOND_MODE_TLB) ||
+					    (bond_mode == BOND_MODE_ALB)) {
+						bond_alb_handle_link_change(bond, slave, BOND_LINK_DOWN);
+					}
+
+					write_lock(&bond->ptrlock);
+					if (slave == bond->current_slave) {
+						/* find a new interface and be verbose */
+						change_active_interface(bond);
+					} else {
+						printk(".\n");
+					}
+					write_unlock(&bond->ptrlock);
+					slave_died = 1;
+				} else {
+					slave->delay--;
+				}
+			} else {
+				/* link up again */
+				slave->link  = BOND_LINK_UP;
+				slave->jiffies = jiffies;
+				printk(KERN_INFO
+					"%s: link status up again after %d ms "
+					"for interface %s.\n",
+					master->name,
+					(downdelay - slave->delay) * miimon,
+					dev->name);
+
+				if (IS_UP(dev) && (mindelay > -1)) {
+					/* -1 is a good case : this slave went
+					   down only for a short time */
+					mindelay = -1;
+					bestslave = slave;
+				}
+			}
+			break;
+		case BOND_LINK_DOWN:	/* the link was down */
+			if (link_state != BMSR_LSTATUS) {
+				/* the link stays down, nothing more to do */
+				break;
+			} else {	/* link going up */
+				slave->link  = BOND_LINK_BACK;
+				slave->delay = updelay;
+				
+				if (updelay > 0) {
+					/* if updelay == 0, no need to
+					   advertise about a 0 ms delay */
+					printk (KERN_INFO
+						"%s: link status up for interface"
+						" %s, enabling it in %d ms.\n",
+						master->name,
+						dev->name,
+						updelay * miimon);
+				}
+			}
+			/* no break ! fall through the BOND_LINK_BACK state in
+			   case there's something to do.
+			*/
+		case BOND_LINK_BACK:	/* the link has just come back */
+			if (link_state != BMSR_LSTATUS) {
+				/* link down again */
+				slave->link  = BOND_LINK_DOWN;
+				printk(KERN_INFO
+					"%s: link status down again after %d ms "
+					"for interface %s.\n",
+					master->name,
+					(updelay - slave->delay) * miimon,
+					dev->name);
+			} else {
+				/* link stays up */
+				if (slave->delay == 0) {
+					/* now the link has been up for long time enough */
+					slave->link = BOND_LINK_UP;
+					slave->jiffies = jiffies;
+
+					if (bond_mode == BOND_MODE_8023AD) {
+						/* prevent it from being the active one */
+						slave->state = BOND_STATE_BACKUP;
+					}
+					else if (bond_mode != BOND_MODE_ACTIVEBACKUP) {
+						/* make it immediately active */
+						slave->state = BOND_STATE_ACTIVE;
+					} else if (slave != bond->primary_slave) {
+						/* prevent it from being the active one */
+						slave->state = BOND_STATE_BACKUP;
+					}
+
+					printk(KERN_INFO
+						"%s: link status definitely up "
+						"for interface %s.\n",
+						master->name,
+						dev->name);
+	
+					/* notify ad that the link status has changed */
+					if (bond_mode == BOND_MODE_8023AD) {
+						bond_3ad_handle_link_change(slave, BOND_LINK_UP);
+					}
+
+					if ((bond_mode == BOND_MODE_TLB) ||
+					    (bond_mode == BOND_MODE_ALB)) {
+						bond_alb_handle_link_change(bond, slave, BOND_LINK_UP);
+					}
+
+					write_lock(&bond->ptrlock);
+					if ( (bond->primary_slave != NULL)
+					  && (slave == bond->primary_slave) )
+						change_active_interface(bond); 
+					write_unlock(&bond->ptrlock);
+				}
+				else
+					slave->delay--;
+
+				/* we'll also look for the mostly eligible slave */
+				if (bond->primary_slave == NULL)  {
+				    if (IS_UP(dev) && (slave->delay < mindelay)) {
+					mindelay = slave->delay;
+					bestslave = slave;
+				    } 
+				} else if ( (IS_UP(bond->primary_slave->dev))  || 
+				          ( (!IS_UP(bond->primary_slave->dev))  && 
+				          (IS_UP(dev) && (slave->delay < mindelay)) ) ) {
+					mindelay = slave->delay;
+					bestslave = slave;
+				}
+			}
+			break;
+		} /* end of switch */
+
+		bond_update_speed_duplex(slave);
+
+		if (bond_mode == BOND_MODE_8023AD) {
+			if (old_speed != slave->speed) {
+				bond_3ad_adapter_speed_changed(slave);
+			}
+			if (old_duplex != slave->duplex) {
+				bond_3ad_adapter_duplex_changed(slave);
+			}
+		}
+
+	} /* end of while */
+
+	/* 
+	 * if there's no active interface and we discovered that one
+	 * of the slaves could be activated earlier, so we do it.
+	 */
+	read_lock(&bond->ptrlock);
+	oldcurrent = bond->current_slave;
+	read_unlock(&bond->ptrlock);
+
+	/* no active interface at the moment or need to bring up the primary */
+	if (oldcurrent == NULL)  { /* no active interface at the moment */
+		if (bestslave != NULL) { /* last chance to find one ? */
+			if (bestslave->link == BOND_LINK_UP) {
+				printk (KERN_INFO
+					"%s: making interface %s the new active one.\n",
+					master->name, bestslave->dev->name);
+			} else {
+				printk (KERN_INFO
+					"%s: making interface %s the new "
+					"active one %d ms earlier.\n",
+					master->name, bestslave->dev->name,
+					(updelay - bestslave->delay) * miimon);
+
+				bestslave->delay = 0;
+				bestslave->link  = BOND_LINK_UP;
+				bestslave->jiffies = jiffies;
+
+				/* notify ad that the link status has changed */
+				if (bond_mode == BOND_MODE_8023AD) {
+					bond_3ad_handle_link_change(bestslave, BOND_LINK_UP);
+				}
+
+				if ((bond_mode == BOND_MODE_TLB) ||
+				    (bond_mode == BOND_MODE_ALB)) {
+					bond_alb_handle_link_change(bond, bestslave, BOND_LINK_UP);
+				}
+			}
+
+			if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
+				bond_set_slave_active_flags(bestslave);
+				bond_mc_update(bond, bestslave, NULL);
+			} else if (bond_mode != BOND_MODE_8023AD) {
+				bestslave->state = BOND_STATE_ACTIVE;
+			}
+			write_lock(&bond->ptrlock);
+			bond_assign_current_slave(bond, bestslave);
+			write_unlock(&bond->ptrlock);
+		} else if (slave_died) {
+			/* print this message only once a slave has just died */
+			printk(KERN_INFO
+				"%s: now running without any active interface !\n",
+				master->name);
+		}
+	}
+
+	read_unlock(&bond->lock);
+	/* re-arm the timer */
+	mod_timer(&bond->mii_timer, jiffies + (miimon * HZ / 1000));
+}
+
+/* 
+ * this function is called regularly to monitor each slave's link 
+ * ensuring that traffic is being sent and received when arp monitoring
+ * is used in load-balancing mode. if the adapter has been dormant, then an 
+ * arp is transmitted to generate traffic. see activebackup_arp_monitor for 
+ * arp monitoring in active backup mode. 
+ */
+static void loadbalance_arp_monitor(struct net_device *master)
+{
+	bonding_t *bond;
+	slave_t *slave;
+	int the_delta_in_ticks =  arp_interval * HZ / 1000;
+	int next_timer = jiffies + (arp_interval * HZ / 1000);
+
+	bond = (struct bonding *) master->priv; 
+	if (master->priv == NULL) {
+		mod_timer(&bond->arp_timer, next_timer);
+		return;
+	}
+
+	/* TODO: investigate why rtnl_shlock_nowait and rtnl_exlock_nowait
+	 * are called below and add comment why they are required... 
+	 */
+	if ((!IS_UP(master)) || rtnl_shlock_nowait()) {
+		mod_timer(&bond->arp_timer, next_timer);
+		return;
+	}
+
+	if (rtnl_exlock_nowait()) {
+		rtnl_shunlock();
+		mod_timer(&bond->arp_timer, next_timer);
+		return;
+	}
+
+	read_lock(&bond->lock);
+
+	/* see if any of the previous devices are up now (i.e. they have
+	 * xmt and rcv traffic). the current_slave does not come into
+	 * the picture unless it is null. also, slave->jiffies is not needed
+	 * here because we send an arp on each slave and give a slave as
+	 * long as it needs to get the tx/rx within the delta.
+	 * TODO: what about up/down delay in arp mode? it wasn't here before
+	 *       so it can wait 
+	 */
+	slave = (slave_t *)bond;
+	while ((slave = slave->prev) != (slave_t *)bond)  {
+
+	  	if (slave->link != BOND_LINK_UP) {
+
+	  		if (((jiffies - slave->dev->trans_start) <= 
+						the_delta_in_ticks) &&  
+			     ((jiffies - slave->dev->last_rx) <= 
+						the_delta_in_ticks)) {
+
+				slave->link  = BOND_LINK_UP;
+				slave->state = BOND_STATE_ACTIVE;
+
+				/* primary_slave has no meaning in round-robin
+				 * mode. the window of a slave being up and 
+				 * current_slave being null after enslaving
+				 * is closed.
+				 */
+				write_lock(&bond->ptrlock);
+				if (bond->current_slave == NULL) {
+					printk(KERN_INFO
+						"%s: link status definitely up "
+						"for interface %s, ",
+						master->name,
+						slave->dev->name);
+					change_active_interface(bond); 
+				} else {
+					printk(KERN_INFO
+						"%s: interface %s is now up\n",
+						master->name,
+						slave->dev->name);
+				}
+				write_unlock(&bond->ptrlock);
+			} 
+		} else {
+			/* slave->link == BOND_LINK_UP */
+
+			/* not all switches will respond to an arp request
+			 * when the source ip is 0, so don't take the link down
+			 * if we don't know our ip yet
+			 */
+			if (((jiffies - slave->dev->trans_start) >= 
+		              (2*the_delta_in_ticks)) ||
+		             (((jiffies - slave->dev->last_rx) >= 
+		               (2*the_delta_in_ticks)) && my_ip !=0)) {
+				slave->link  = BOND_LINK_DOWN;
+				slave->state = BOND_STATE_BACKUP;
+				if (slave->link_failure_count < UINT_MAX) {
+					slave->link_failure_count++;
+				}
+				printk(KERN_INFO
+				       "%s: interface %s is now down.\n",
+				       master->name,
+				       slave->dev->name);
+
+				write_lock(&bond->ptrlock);
+				if (slave == bond->current_slave) {
+					change_active_interface(bond);
+				}
+				write_unlock(&bond->ptrlock);
+			}
+		} 
+
+		/* note: if switch is in round-robin mode, all links 
+		 * must tx arp to ensure all links rx an arp - otherwise
+		 * links may oscillate or not come up at all; if switch is 
+		 * in something like xor mode, there is nothing we can 
+		 * do - all replies will be rx'ed on same link causing slaves 
+		 * to be unstable during low/no traffic periods
+		 */
+		if (IS_UP(slave->dev)) {
+			arp_send_all(slave);
+		}
+	}
+
+	read_unlock(&bond->lock);
+	rtnl_exunlock();
+	rtnl_shunlock();
+
+	/* re-arm the timer */
+	mod_timer(&bond->arp_timer, next_timer);
+}
+
+/* 
+ * When using arp monitoring in active-backup mode, this function is
+ * called to determine if any backup slaves have went down or a new
+ * current slave needs to be found.
+ * The backup slaves never generate traffic, they are considered up by merely 
+ * receiving traffic. If the current slave goes down, each backup slave will 
+ * be given the opportunity to tx/rx an arp before being taken down - this 
+ * prevents all slaves from being taken down due to the current slave not 
+ * sending any traffic for the backups to receive. The arps are not necessarily
+ * necessary, any tx and rx traffic will keep the current slave up. While any 
+ * rx traffic will keep the backup slaves up, the current slave is responsible 
+ * for generating traffic to keep them up regardless of any other traffic they 
+ * may have received.
+ * see loadbalance_arp_monitor for arp monitoring in load balancing mode
+ */
+static void activebackup_arp_monitor(struct net_device *master)
+{
+	bonding_t *bond;
+	slave_t *slave;
+	int the_delta_in_ticks =  arp_interval * HZ / 1000;
+	int next_timer = jiffies + (arp_interval * HZ / 1000);
+
+	bond = (struct bonding *) master->priv; 
+	if (master->priv == NULL) {
+		mod_timer(&bond->arp_timer, next_timer);
+		return;
+	}
+
+	if (!IS_UP(master)) {
+		mod_timer(&bond->arp_timer, next_timer);
+		return;
+	}
+
+	read_lock(&bond->lock);
+
+	/* determine if any slave has come up or any backup slave has 
+	 * gone down 
+	 * TODO: what about up/down delay in arp mode? it wasn't here before
+	 *       so it can wait 
+	 */
+	slave = (slave_t *)bond;
+	while ((slave = slave->prev) != (slave_t *)bond)  {
+
+	  	if (slave->link != BOND_LINK_UP) {
+			if ((jiffies - slave->dev->last_rx) <=
+			    the_delta_in_ticks) {
+
+				slave->link = BOND_LINK_UP;
+				write_lock(&bond->ptrlock);
+				if ((bond->current_slave == NULL) &&
+				    ((jiffies - slave->dev->trans_start) <=
+				     the_delta_in_ticks)) {
+					bond_assign_current_slave(bond, slave);
+					bond_set_slave_active_flags(slave);
+			                bond_mc_update(bond, slave, NULL);
+					bond->current_arp_slave = NULL;
+				} else if (bond->current_slave != slave) {
+					/* this slave has just come up but we 
+					 * already have a current slave; this
+					 * can also happen if bond_enslave adds
+					 * a new slave that is up while we are 
+					 * searching for a new slave
+					 */
+					bond_set_slave_inactive_flags(slave);
+					bond->current_arp_slave = NULL;
+				}
+
+				if (slave == bond->current_slave) {
+					printk(KERN_INFO
+						"%s: %s is up and now the "
+						"active interface\n",
+						master->name,
+						slave->dev->name);
+				} else {
+					printk(KERN_INFO
+						"%s: backup interface %s is "
+						"now up\n",
+						master->name,
+						slave->dev->name);
+				}
+
+				write_unlock(&bond->ptrlock);
+			}
+		} else {
+			read_lock(&bond->ptrlock);
+			if ((slave != bond->current_slave) &&
+			    (bond->current_arp_slave == NULL) &&
+			    (((jiffies - slave->dev->last_rx) >=
+			     3*the_delta_in_ticks) && (my_ip != 0))) {
+				/* a backup slave has gone down; three times 
+				 * the delta allows the current slave to be 
+				 * taken out before the backup slave.
+				 * note: a non-null current_arp_slave indicates
+				 * the current_slave went down and we are 
+				 * searching for a new one; under this 
+				 * condition we only take the current_slave 
+				 * down - this gives each slave a chance to 
+				 * tx/rx traffic before being taken out
+				 */
+				read_unlock(&bond->ptrlock);
+				slave->link  = BOND_LINK_DOWN;
+				if (slave->link_failure_count < UINT_MAX) {
+					slave->link_failure_count++;
+				}
+				bond_set_slave_inactive_flags(slave);
+				printk(KERN_INFO
+					"%s: backup interface %s is now down\n",
+					master->name,
+					slave->dev->name);
+			} else {
+				read_unlock(&bond->ptrlock);
+			}
+		}
+	}
+
+	read_lock(&bond->ptrlock);
+	slave = bond->current_slave;
+	read_unlock(&bond->ptrlock);
+
+	if (slave != NULL) {
+
+		/* if we have sent traffic in the past 2*arp_intervals but
+		 * haven't xmit and rx traffic in that time interval, select 
+		 * a different slave. slave->jiffies is only updated when
+		 * a slave first becomes the current_slave - not necessarily
+		 * after every arp; this ensures the slave has a full 2*delta 
+		 * before being taken out. if a primary is being used, check 
+		 * if it is up and needs to take over as the current_slave
+		 */
+		if ((((jiffies - slave->dev->trans_start) >= 
+		       (2*the_delta_in_ticks)) ||
+		     (((jiffies - slave->dev->last_rx) >= 
+		       (2*the_delta_in_ticks)) && (my_ip != 0))) &&
+		    ((jiffies - slave->jiffies) >= 2*the_delta_in_ticks)) {
+
+			slave->link  = BOND_LINK_DOWN;
+			if (slave->link_failure_count < UINT_MAX) {
+				slave->link_failure_count++;
+			}
+			printk(KERN_INFO "%s: link status down for "
+					 "active interface %s, disabling it",
+			       master->name,
+			       slave->dev->name);
+			write_lock(&bond->ptrlock);
+			slave = change_active_interface(bond);
+			write_unlock(&bond->ptrlock);
+			bond->current_arp_slave = slave;
+			if (slave != NULL) {
+				slave->jiffies = jiffies;
+			}
+
+		} else if ((bond->primary_slave != NULL) && 
+			   (bond->primary_slave != slave) && 
+			   (bond->primary_slave->link == BOND_LINK_UP)) {
+			/* at this point, slave is the current_slave */
+			printk(KERN_INFO 
+			       "%s: changing from interface %s to primary "
+			       "interface %s\n",
+			       master->name, 
+			       slave->dev->name, 
+			       bond->primary_slave->dev->name);
+			       
+			/* primary is up so switch to it */
+			bond_set_slave_inactive_flags(slave);
+			bond_mc_update(bond, bond->primary_slave, slave);
+			write_lock(&bond->ptrlock);
+			bond_assign_current_slave(bond, bond->primary_slave);
+			write_unlock(&bond->ptrlock);
+			slave = bond->primary_slave;
+			bond_set_slave_active_flags(slave);
+			slave->jiffies = jiffies;
+		} else {
+			bond->current_arp_slave = NULL;
+		}
+
+		/* the current slave must tx an arp to ensure backup slaves
+		 * rx traffic
+		 */
+		if ((slave != NULL) &&
+		    (((jiffies - slave->dev->last_rx) >= the_delta_in_ticks) &&
+		     (my_ip != 0))) {
+		  arp_send_all(slave);
+		}
+	}
+
+	/* if we don't have a current_slave, search for the next available 
+	 * backup slave from the current_arp_slave and make it the candidate 
+	 * for becoming the current_slave
+	 */
+	if (slave == NULL) { 
+
+		if ((bond->current_arp_slave == NULL) ||
+		    (bond->current_arp_slave == (slave_t *)bond)) {
+			bond->current_arp_slave = bond->prev;
+		} 
+
+		if (bond->current_arp_slave != (slave_t *)bond) {
+			bond_set_slave_inactive_flags(bond->current_arp_slave);
+			slave = bond->current_arp_slave->next;
+
+			/* search for next candidate */
+			do {
+				if (IS_UP(slave->dev)) {
+					slave->link = BOND_LINK_BACK;
+					bond_set_slave_active_flags(slave);
+					arp_send_all(slave);
+					slave->jiffies = jiffies;
+					bond->current_arp_slave = slave;
+					break;
+				}
+
+				/* if the link state is up at this point, we 
+				 * mark it down - this can happen if we have 
+				 * simultaneous link failures and 
+				 * change_active_interface doesn't make this 
+				 * one the current slave so it is still marked 
+				 * up when it is actually down
+				 */
+				if (slave->link == BOND_LINK_UP) {
+					slave->link  = BOND_LINK_DOWN;
+					if (slave->link_failure_count < 
+							UINT_MAX) {
+						slave->link_failure_count++;
+					}
+
+					bond_set_slave_inactive_flags(slave);
+					printk(KERN_INFO
+						"%s: backup interface "
+						"%s is now down.\n",
+						master->name,
+						slave->dev->name);
+				}
+			} while ((slave = slave->next) != 
+					bond->current_arp_slave->next);
+		}
+	}
+
+	read_unlock(&bond->lock);
+	mod_timer(&bond->arp_timer, next_timer);
+}
+
+typedef uint32_t in_addr_t;
+
+int
+my_inet_aton(char *cp, unsigned long *the_addr) {
+	static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
+	in_addr_t val;
+	char c;
+	union iaddr {
+	  uint8_t bytes[4];
+	  uint32_t word;
+	} res;
+	uint8_t *pp = res.bytes;
+	int digit,base;
+
+	res.word = 0;
+
+	c = *cp;
+	for (;;) {
+		/*
+		 * Collect number up to ``.''.
+		 * Values are specified as for C:
+		 * 0x=hex, 0=octal, isdigit=decimal.
+		 */
+		if (!isdigit(c)) goto ret_0;
+		val = 0; base = 10; digit = 0;
+		for (;;) {
+			if (isdigit(c)) {
+				val = (val * base) + (c - '0');
+				c = *++cp;
+				digit = 1;
+			} else {
+				break;
+			}
+		}
+		if (c == '.') {
+			/*
+			 * Internet format:
+			 *	a.b.c.d
+			 *	a.b.c	(with c treated as 16 bits)
+			 *	a.b	(with b treated as 24 bits)
+			 */
+			if (pp > res.bytes + 2 || val > 0xff) {
+				goto ret_0;
+			}
+			*pp++ = val;
+			c = *++cp;
+		} else
+			break;
+	}
+	/*
+	 * Check for trailing characters.
+	 */
+	if (c != '\0' && (!isascii(c) || !isspace(c))) {
+		goto ret_0;
+	}
+	/*
+	 * Did we get a valid digit?
+	 */
+	if (!digit) {
+		goto ret_0;
+	}
+
+	/* Check whether the last part is in its limits depending on
+	   the number of parts in total.  */
+	if (val > max[pp - res.bytes]) {
+		goto ret_0;
+	}
+
+	if (the_addr != NULL) {
+		*the_addr = res.word | htonl (val);
+	}
+
+	return (1);
+
+ret_0:
+	return (0);
+}
+
+static int bond_sethwaddr(struct net_device *master, struct net_device *slave)
+{
+#ifdef BONDING_DEBUG
+	printk(KERN_CRIT "bond_sethwaddr: master=%x\n", (unsigned int)master);
+	printk(KERN_CRIT "bond_sethwaddr: slave=%x\n", (unsigned int)slave);
+	printk(KERN_CRIT "bond_sethwaddr: slave->addr_len=%d\n", slave->addr_len);
+#endif
+	memcpy(master->dev_addr, slave->dev_addr, slave->addr_len);
+	return 0;
+}
+
+static int bond_info_query(struct net_device *master, struct ifbond *info)
+{
+	bonding_t *bond = (struct bonding *) master->priv;
+	slave_t *slave;
+
+	info->bond_mode = bond_mode;
+	info->num_slaves = 0;
+	info->miimon = miimon;
+
+	read_lock_bh(&bond->lock);
+	for (slave = bond->prev; slave != (slave_t *)bond; slave = slave->prev) {
+		info->num_slaves++;
+	}
+	read_unlock_bh(&bond->lock);
+
+	return 0;
+}
+
+static int bond_slave_info_query(struct net_device *master, 
+					struct ifslave *info)
+{
+	bonding_t *bond = (struct bonding *) master->priv;
+	slave_t *slave;
+	int cur_ndx = 0;
+
+	if (info->slave_id < 0) {
+		return -ENODEV;
+	}
+
+	read_lock_bh(&bond->lock);
+	for (slave = bond->prev; 
+		 slave != (slave_t *)bond && cur_ndx < info->slave_id; 
+		 slave = slave->prev) {
+		cur_ndx++;
+	}
+	read_unlock_bh(&bond->lock);
+
+	if (slave != (slave_t *)bond) {
+		strcpy(info->slave_name, slave->dev->name);
+		info->link = slave->link;
+		info->state = slave->state;
+		info->link_failure_count = slave->link_failure_count;
+	} else {
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int bond_ethtool_ioctl(struct net_device *master_dev, struct ifreq *ifr)
+{
+	void *addr = ifr->ifr_data;
+	uint32_t cmd;
+
+	if (get_user(cmd, (uint32_t *) addr))
+		return -EFAULT;
+
+	switch (cmd) {
+
+	case ETHTOOL_GDRVINFO:
+		{
+			struct ethtool_drvinfo info;
+			char *endptr;
+
+			if (copy_from_user(&info, addr, sizeof(info)))
+				return -EFAULT;
+
+			if (strcmp(info.driver, "ifenslave") == 0) {
+				int new_abi_ver;
+
+				new_abi_ver = simple_strtoul(info.fw_version,
+						             &endptr, 0);
+				if (*endptr) {
+					printk(KERN_ERR
+					       "bonding: Error: got invalid ABI"
+					       " version from application\n");
+
+					return -EINVAL;
+				}
+
+				if (orig_app_abi_ver == -1) {
+					orig_app_abi_ver  = new_abi_ver;
+				}
+
+				app_abi_ver = new_abi_ver;
+			}
+
+			strncpy(info.driver,  DRV_NAME, 32);
+			strncpy(info.version, DRV_VERSION, 32);
+			snprintf(info.fw_version, 32, "%d", BOND_ABI_VERSION);
+
+			if (copy_to_user(addr, &info, sizeof(info)))
+				return -EFAULT;
+
+			return 0;
+		}
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int bond_ioctl(struct net_device *master_dev, struct ifreq *ifr, int cmd)
+{
+	struct net_device *slave_dev = NULL;
+	struct ifbond *u_binfo = NULL, k_binfo;
+	struct ifslave *u_sinfo = NULL, k_sinfo;
+	struct mii_ioctl_data *mii = NULL;
+	int ret = 0;
+
+#ifdef BONDING_DEBUG
+	printk(KERN_INFO "bond_ioctl: master=%s, cmd=%d\n", 
+		master_dev->name, cmd);
+#endif
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		return bond_ethtool_ioctl(master_dev, ifr);
+
+	case SIOCGMIIPHY:
+		mii = (struct mii_ioctl_data *)&ifr->ifr_data;
+		if (mii == NULL) {
+			return -EINVAL;
+		}
+		mii->phy_id = 0;
+		/* Fall Through */
+	case SIOCGMIIREG:
+		/* 
+		 * We do this again just in case we were called by SIOCGMIIREG
+		 * instead of SIOCGMIIPHY.
+		 */
+		mii = (struct mii_ioctl_data *)&ifr->ifr_data;
+		if (mii == NULL) {
+			return -EINVAL;
+		}
+		if (mii->reg_num == 1) {
+			mii->val_out = bond_check_mii_link(
+				(struct bonding *)master_dev->priv);
+		}
+		return 0;
+	case BOND_INFO_QUERY_OLD:
+	case SIOCBONDINFOQUERY:
+		u_binfo = (struct ifbond *)ifr->ifr_data;
+		if (copy_from_user(&k_binfo, u_binfo, sizeof(ifbond))) {
+			return -EFAULT;
+		}
+		ret = bond_info_query(master_dev, &k_binfo);
+		if (ret == 0) {
+			if (copy_to_user(u_binfo, &k_binfo, sizeof(ifbond))) {
+				return -EFAULT;
+			}
+		}
+		return ret;
+	case BOND_SLAVE_INFO_QUERY_OLD:
+	case SIOCBONDSLAVEINFOQUERY:
+		u_sinfo = (struct ifslave *)ifr->ifr_data;
+		if (copy_from_user(&k_sinfo, u_sinfo, sizeof(ifslave))) {
+			return -EFAULT;
+		}
+		ret = bond_slave_info_query(master_dev, &k_sinfo);
+		if (ret == 0) {
+			if (copy_to_user(u_sinfo, &k_sinfo, sizeof(ifslave))) {
+				return -EFAULT;
+			}
+		}
+		return ret;
+	}
+
+	if (!capable(CAP_NET_ADMIN)) {
+		return -EPERM;
+	}
+
+	if (orig_app_abi_ver == -1) {
+		/* no orig_app_abi_ver was provided yet, so we'll use the
+		 * current one from now on, even if it's 0
+		 */
+		orig_app_abi_ver = app_abi_ver;
+
+	} else if (orig_app_abi_ver != app_abi_ver) {
+		printk(KERN_ERR
+		       "bonding: Error: already using ifenslave ABI "
+		       "version %d; to upgrade ifenslave to version %d,"
+		       "you must first reload bonding.\n",
+		       orig_app_abi_ver, app_abi_ver);
+		return -EINVAL;
+	}
+
+	slave_dev = dev_get_by_name(ifr->ifr_slave);
+
+#ifdef BONDING_DEBUG
+	printk(KERN_INFO "slave_dev=%x: \n", (unsigned int)slave_dev);
+	printk(KERN_INFO "slave_dev->name=%s: \n", slave_dev->name);
+#endif
+
+	if (slave_dev == NULL) {
+		ret = -ENODEV;
+	} else {
+		switch (cmd) {
+		case BOND_ENSLAVE_OLD:
+		case SIOCBONDENSLAVE:		
+			ret = bond_enslave(master_dev, slave_dev);
+			break;
+		case BOND_RELEASE_OLD:			
+		case SIOCBONDRELEASE:	
+			ret = bond_release(master_dev, slave_dev); 
+			break;
+		case BOND_SETHWADDR_OLD:
+		case SIOCBONDSETHWADDR:	
+			ret = bond_sethwaddr(master_dev, slave_dev);
+			break;
+		case BOND_CHANGE_ACTIVE_OLD:
+		case SIOCBONDCHANGEACTIVE:
+			if ((bond_mode == BOND_MODE_ACTIVEBACKUP) ||
+			    (bond_mode == BOND_MODE_TLB) ||
+			    (bond_mode == BOND_MODE_ALB)) {
+				ret = bond_change_active(master_dev, slave_dev);
+			}
+			else {
+				ret = -EINVAL;
+			}
+			break;
+		default:
+			ret = -EOPNOTSUPP;
+		}
+		dev_put(slave_dev);
+	}
+	return ret;
+}
+
+#ifdef CONFIG_NET_FASTROUTE
+static int bond_accept_fastpath(struct net_device *dev, struct dst_entry *dst)
+{
+	return -1;
+}
+#endif
+
+/* 
+ * in broadcast mode, we send everything to all usable interfaces.
+ */
+static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *dev)
+{
+	slave_t *slave, *start_at;
+	struct bonding *bond = (struct bonding *) dev->priv;
+	struct net_device *device_we_should_send_to = 0;
+
+	if (!IS_UP(dev)) { /* bond down */
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	read_lock(&bond->lock);
+
+	read_lock(&bond->ptrlock);
+	slave = start_at = bond->current_slave;
+	read_unlock(&bond->ptrlock);
+
+	if (slave == NULL) { /* we're at the root, get the first slave */
+		/* no suitable interface, frame not sent */
+		read_unlock(&bond->lock);
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	do {
+		if (IS_UP(slave->dev)
+		    && (slave->link == BOND_LINK_UP)
+		    && (slave->state == BOND_STATE_ACTIVE)) {
+			if (device_we_should_send_to) {
+				struct sk_buff *skb2;
+				if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
+					printk(KERN_ERR "bond_xmit_broadcast: skb_clone() failed\n");
+					continue;
+				}
+
+				skb2->dev = device_we_should_send_to;
+				skb2->priority = 1;
+				dev_queue_xmit(skb2);
+			}
+			device_we_should_send_to = slave->dev;
+		}
+	} while ((slave = slave->next) != start_at);
+
+	if (device_we_should_send_to) {
+		skb->dev = device_we_should_send_to;
+		skb->priority = 1;
+		dev_queue_xmit(skb);
+	} else
+		dev_kfree_skb(skb);
+
+	/* frame sent to all suitable interfaces */
+	read_unlock(&bond->lock);
+	return 0;
+}
+
+static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *dev)
+{
+	slave_t *slave, *start_at;
+	struct bonding *bond = (struct bonding *) dev->priv;
+
+	if (!IS_UP(dev)) { /* bond down */
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	read_lock(&bond->lock);
+
+	read_lock(&bond->ptrlock);
+	slave = start_at = bond->current_slave;
+	read_unlock(&bond->ptrlock);
+
+	if (slave == NULL) { /* we're at the root, get the first slave */
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+		read_unlock(&bond->lock);
+		return 0;
+	}
+
+	do {
+		if (IS_UP(slave->dev)
+		    && (slave->link == BOND_LINK_UP)
+		    && (slave->state == BOND_STATE_ACTIVE)) {
+
+			skb->dev = slave->dev;
+			skb->priority = 1;
+			dev_queue_xmit(skb);
+
+			write_lock(&bond->ptrlock);
+			bond_assign_current_slave(bond, slave->next);
+			write_unlock(&bond->ptrlock);
+
+			read_unlock(&bond->lock);
+			return 0;
+		}
+	} while ((slave = slave->next) != start_at);
+
+	/* no suitable interface, frame not sent */
+	dev_kfree_skb(skb);
+	read_unlock(&bond->lock);
+	return 0;
+}
+
+/* 
+ * in XOR mode, we determine the output device by performing xor on
+ * the source and destination hw adresses.  If this device is not 
+ * enabled, find the next slave following this xor slave. 
+ */
+static int bond_xmit_xor(struct sk_buff *skb, struct net_device *dev)
+{
+	slave_t *slave, *start_at;
+	struct bonding *bond = (struct bonding *) dev->priv;
+	struct ethhdr *data = (struct ethhdr *)skb->data;
+	int slave_no;
+
+	if (!IS_UP(dev)) { /* bond down */
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	read_lock(&bond->lock);
+	slave = bond->prev;
+
+	/* we're at the root, get the first slave */
+	if (bond->slave_cnt == 0) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+		read_unlock(&bond->lock);
+		return 0;
+	}
+
+	slave_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % bond->slave_cnt;
+
+	while ( (slave_no > 0) && (slave != (slave_t *)bond) ) {
+		slave = slave->prev;
+		slave_no--;
+	} 
+	start_at = slave;
+
+	do {
+		if (IS_UP(slave->dev)
+		    && (slave->link == BOND_LINK_UP)
+		    && (slave->state == BOND_STATE_ACTIVE)) {
+
+			skb->dev = slave->dev;
+			skb->priority = 1;
+			dev_queue_xmit(skb);
+
+			read_unlock(&bond->lock);
+			return 0;
+		}
+	} while ((slave = slave->next) != start_at);
+
+	/* no suitable interface, frame not sent */
+	dev_kfree_skb(skb);
+	read_unlock(&bond->lock);
+	return 0;
+}
+
+/* 
+ * in active-backup mode, we know that bond->current_slave is always valid if
+ * the bond has a usable interface.
+ */
+static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *dev)
+{
+	struct bonding *bond = (struct bonding *) dev->priv;
+	int ret;
+
+	if (!IS_UP(dev)) { /* bond down */
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	/* if we are sending arp packets, try to at least 
+	   identify our own ip address */
+	if ( (arp_interval > 0) && (my_ip == 0) &&
+		(skb->protocol == __constant_htons(ETH_P_ARP) ) ) {
+		char *the_ip = (((char *)skb->data)) 
+				+ sizeof(struct ethhdr)  
+				+ sizeof(struct arphdr) + 
+				ETH_ALEN;
+		memcpy(&my_ip, the_ip, 4);
+	}
+
+	/* if we are sending arp packets and don't know 
+	 * the target hw address, save it so we don't need 
+	 * to use a broadcast address.
+	 * don't do this if in active backup mode because the slaves must 
+	 * receive packets to stay up, and the only ones they receive are 
+	 * broadcasts. 
+	 */
+	if ( (bond_mode != BOND_MODE_ACTIVEBACKUP) && 
+             (arp_ip_count == 1) &&
+	     (arp_interval > 0) && (arp_target_hw_addr == NULL) &&
+	     (skb->protocol == __constant_htons(ETH_P_IP) ) ) {
+		struct ethhdr *eth_hdr = 
+			(struct ethhdr *) (((char *)skb->data));
+		struct iphdr *ip_hdr = (struct iphdr *)(eth_hdr + 1);
+
+		if (arp_target[0] == ip_hdr->daddr) {
+			arp_target_hw_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
+			if (arp_target_hw_addr != NULL)
+				memcpy(arp_target_hw_addr, eth_hdr->h_dest, ETH_ALEN);
+		}
+	}
+
+	read_lock(&bond->lock);
+
+	read_lock(&bond->ptrlock);
+	if (bond->current_slave != NULL) { /* one usable interface */
+		skb->dev = bond->current_slave->dev;
+		read_unlock(&bond->ptrlock);
+		skb->priority = 1;
+		ret = dev_queue_xmit(skb);
+		read_unlock(&bond->lock);
+		return 0;
+	}
+	else {
+		read_unlock(&bond->ptrlock);
+	}
+
+	/* no suitable interface, frame not sent */
+#ifdef BONDING_DEBUG
+	printk(KERN_INFO "There was no suitable interface, so we don't transmit\n");
+#endif
+	dev_kfree_skb(skb);
+	read_unlock(&bond->lock);
+	return 0;
+}
+
+static struct net_device_stats *bond_get_stats(struct net_device *dev)
+{
+	bonding_t *bond = dev->priv;
+	struct net_device_stats *stats = bond->stats, *sstats;
+	slave_t *slave;
+
+	memset(bond->stats, 0, sizeof(struct net_device_stats));
+
+	read_lock_bh(&bond->lock);
+
+	for (slave = bond->prev; slave != (slave_t *)bond; slave = slave->prev) {
+		sstats = slave->dev->get_stats(slave->dev);
+ 
+		stats->rx_packets += sstats->rx_packets;
+		stats->rx_bytes += sstats->rx_bytes;
+		stats->rx_errors += sstats->rx_errors;
+		stats->rx_dropped += sstats->rx_dropped;
+
+		stats->tx_packets += sstats->tx_packets;
+		stats->tx_bytes += sstats->tx_bytes;
+		stats->tx_errors += sstats->tx_errors;
+		stats->tx_dropped += sstats->tx_dropped;
+
+		stats->multicast += sstats->multicast;
+		stats->collisions += sstats->collisions;
+
+		stats->rx_length_errors += sstats->rx_length_errors;
+		stats->rx_over_errors += sstats->rx_over_errors;
+		stats->rx_crc_errors += sstats->rx_crc_errors;
+		stats->rx_frame_errors += sstats->rx_frame_errors;
+		stats->rx_fifo_errors += sstats->rx_fifo_errors;	
+		stats->rx_missed_errors += sstats->rx_missed_errors;
+	
+		stats->tx_aborted_errors += sstats->tx_aborted_errors;
+		stats->tx_carrier_errors += sstats->tx_carrier_errors;
+		stats->tx_fifo_errors += sstats->tx_fifo_errors;
+		stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors;
+		stats->tx_window_errors += sstats->tx_window_errors;
+
+	}
+
+	read_unlock_bh(&bond->lock);
+	return stats;
+}
+
+static int bond_get_info(char *buf, char **start, off_t offset, int length)
+{
+	bonding_t *bond = these_bonds;
+	int len = 0;
+	off_t begin = 0;
+	u16 link;
+	slave_t *slave = NULL;
+
+	len += sprintf(buf + len, "%s\n", version);
+
+	while (bond != NULL) {
+		/*
+		 * This function locks the mutex, so we can't lock it until 
+		 * afterwards
+		 */
+		link = bond_check_mii_link(bond);
+
+		len += sprintf(buf + len, "Bonding Mode: %s\n",
+			       bond_mode_name());
+
+		if ((bond_mode == BOND_MODE_ACTIVEBACKUP) ||
+		    (bond_mode == BOND_MODE_TLB) ||
+		    (bond_mode == BOND_MODE_ALB)) {
+			read_lock_bh(&bond->lock);
+			read_lock(&bond->ptrlock);
+			if (bond->current_slave != NULL) {
+				len += sprintf(buf + len, 
+					"Currently Active Slave: %s\n", 
+					bond->current_slave->dev->name);
+			}
+			read_unlock(&bond->ptrlock);
+			read_unlock_bh(&bond->lock);
+		}
+
+		len += sprintf(buf + len, "MII Status: ");
+		len += sprintf(buf + len, 
+				link == BMSR_LSTATUS ? "up\n" : "down\n");
+		len += sprintf(buf + len, "MII Polling Interval (ms): %d\n", 
+				miimon);
+		len += sprintf(buf + len, "Up Delay (ms): %d\n", 
+				updelay * miimon);
+		len += sprintf(buf + len, "Down Delay (ms): %d\n", 
+				downdelay * miimon);
+		len += sprintf(buf + len, "Multicast Mode: %s\n",
+			       multicast_mode_name());
+
+		read_lock_bh(&bond->lock);
+
+		if (bond_mode == BOND_MODE_8023AD) {
+			struct ad_info ad_info;
+
+			len += sprintf(buf + len, "\n802.3ad info\n");
+
+			if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
+				len += sprintf(buf + len, "bond %s has no active aggregator\n", bond->device->name);
+			} else {
+				len += sprintf(buf + len, "Active Aggregator Info:\n");
+
+				len += sprintf(buf + len, "\tAggregator ID: %d\n", ad_info.aggregator_id);
+				len += sprintf(buf + len, "\tNumber of ports: %d\n", ad_info.ports);
+				len += sprintf(buf + len, "\tActor Key: %d\n", ad_info.actor_key);
+				len += sprintf(buf + len, "\tPartner Key: %d\n", ad_info.partner_key);
+				len += sprintf(buf + len, "\tPartner Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+					       ad_info.partner_system[0],
+					       ad_info.partner_system[1],
+					       ad_info.partner_system[2],
+					       ad_info.partner_system[3],
+					       ad_info.partner_system[4],
+					       ad_info.partner_system[5]);
+			}
+		}
+
+		for (slave = bond->prev; slave != (slave_t *)bond; 
+		     slave = slave->prev) {
+			len += sprintf(buf + len, "\nSlave Interface: %s\n", slave->dev->name);
+
+			len += sprintf(buf + len, "MII Status: ");
+
+			len += sprintf(buf + len, 
+				slave->link == BOND_LINK_UP ? 
+				"up\n" : "down\n");
+			len += sprintf(buf + len, "Link Failure Count: %d\n", 
+				slave->link_failure_count);
+
+			if (app_abi_ver >= 1) {
+				len += sprintf(buf + len,
+					       "Permanent HW addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
+					       slave->perm_hwaddr[0],
+					       slave->perm_hwaddr[1],
+					       slave->perm_hwaddr[2],
+					       slave->perm_hwaddr[3],
+					       slave->perm_hwaddr[4],
+					       slave->perm_hwaddr[5]);
+			}
+
+			if (bond_mode == BOND_MODE_8023AD) {
+				struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
+
+				if (agg) {
+					len += sprintf(buf + len, "Aggregator ID: %d\n",
+						       agg->aggregator_identifier);
+				} else {
+					len += sprintf(buf + len, "Aggregator ID: N/A\n");
+				}
+			}
+		}
+		read_unlock_bh(&bond->lock);
+
+		/*
+		 * Figure out the calcs for the /proc/net interface
+		 */
+		*start = buf + (offset - begin);
+		len -= (offset - begin);
+		if (len > length) {
+			len = length;
+		}
+		if (len < 0) {
+			len = 0;
+		}
+
+
+		bond = bond->next_bond;
+	}
+	return len;
+}
+
+static int bond_event(struct notifier_block *this, unsigned long event, 
+			void *ptr)
+{
+	struct bonding *this_bond = (struct bonding *)these_bonds;
+	struct bonding *last_bond;
+	struct net_device *event_dev = (struct net_device *)ptr;
+
+	/* while there are bonds configured */
+	while (this_bond != NULL) {
+		if (this_bond == event_dev->priv ) {
+			switch (event) {
+			case NETDEV_UNREGISTER:
+				/* 
+				 * remove this bond from a linked list of 
+				 * bonds 
+				 */
+				if (this_bond == these_bonds) {
+					these_bonds = this_bond->next_bond;
+				} else {
+					for (last_bond = these_bonds; 
+					     last_bond != NULL; 
+					     last_bond = last_bond->next_bond) {
+						if (last_bond->next_bond == 
+						    this_bond) {
+							last_bond->next_bond = 
+							this_bond->next_bond;
+						}
+					}
+				}
+				return NOTIFY_DONE;
+
+			default:
+				return NOTIFY_DONE;
+			}
+		} else if (this_bond->device == event_dev->master) {
+			switch (event) {
+			case NETDEV_UNREGISTER:
+				bond_release(this_bond->device, event_dev);
+				break;
+			}
+			return NOTIFY_DONE;
+		}
+		this_bond = this_bond->next_bond;
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block bond_netdev_notifier = {
+	notifier_call: bond_event,
+};
+
+static int __init bond_init(struct net_device *dev)
+{
+	bonding_t *bond, *this_bond, *last_bond;
+	int count;
+
+#ifdef BONDING_DEBUG
+	printk (KERN_INFO "Begin bond_init for %s\n", dev->name);
+#endif
+	bond = kmalloc(sizeof(struct bonding), GFP_KERNEL);
+	if (bond == NULL) {
+		return -ENOMEM;
+	}
+	memset(bond, 0, sizeof(struct bonding));
+
+	/* initialize rwlocks */
+	rwlock_init(&bond->lock);
+	rwlock_init(&bond->ptrlock);
+	
+	bond->stats = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
+	if (bond->stats == NULL) {
+		kfree(bond);
+		return -ENOMEM;
+	}
+	memset(bond->stats, 0, sizeof(struct net_device_stats));
+
+	bond->next = bond->prev = (slave_t *)bond;
+	bond->current_slave = NULL;
+	bond->current_arp_slave = NULL;
+	bond->device = dev;
+	dev->priv = bond;
+
+	/* Initialize the device structure. */
+	switch (bond_mode) {
+	case BOND_MODE_ACTIVEBACKUP:
+		dev->hard_start_xmit = bond_xmit_activebackup;
+		break;
+	case BOND_MODE_ROUNDROBIN:
+		dev->hard_start_xmit = bond_xmit_roundrobin;
+		break;
+	case BOND_MODE_XOR:
+		dev->hard_start_xmit = bond_xmit_xor;
+		break;
+	case BOND_MODE_BROADCAST:
+		dev->hard_start_xmit = bond_xmit_broadcast;
+		break;
+	case BOND_MODE_8023AD:
+		dev->hard_start_xmit = bond_3ad_xmit_xor;
+		break;
+	case BOND_MODE_TLB:
+	case BOND_MODE_ALB:
+		dev->hard_start_xmit = bond_alb_xmit;
+		break;
+	default:
+		printk(KERN_ERR "Unknown bonding mode %d\n", bond_mode);
+		kfree(bond->stats);
+		kfree(bond);
+		return -EINVAL;
+	}
+
+	dev->get_stats = bond_get_stats;
+	dev->open = bond_open;
+	dev->stop = bond_close;
+	dev->set_multicast_list = set_multicast_list;
+	dev->do_ioctl = bond_ioctl;
+
+	/* 
+	 * Fill in the fields of the device structure with ethernet-generic 
+	 * values. 
+	 */
+
+	ether_setup(dev);
+
+	dev->tx_queue_len = 0;
+	dev->flags |= IFF_MASTER|IFF_MULTICAST;
+#ifdef CONFIG_NET_FASTROUTE
+	dev->accept_fastpath = bond_accept_fastpath;
+#endif
+
+	printk(KERN_INFO "%s registered with", dev->name);
+	if (miimon > 0) {
+		printk(" MII link monitoring set to %d ms", miimon);
+		updelay /= miimon;
+		downdelay /= miimon;
+	} else {
+		printk("out MII link monitoring");
+	}
+	printk(", in %s mode.\n", bond_mode_name());
+
+	printk(KERN_INFO "%s registered with", dev->name);
+	if (arp_interval > 0) {
+		printk(" ARP monitoring set to %d ms with %d target(s):", 
+			arp_interval, arp_ip_count);
+		for (count=0 ; count<arp_ip_count ; count++)
+                        printk (" %s", arp_ip_target[count]);
+		printk("\n");
+	} else {
+		printk("out ARP monitoring\n");
+	}
+
+#ifdef CONFIG_PROC_FS
+	bond->bond_proc_dir = proc_mkdir(dev->name, proc_net);
+	if (bond->bond_proc_dir == NULL) {
+		printk(KERN_ERR "%s: Cannot init /proc/net/%s/\n", 
+			dev->name, dev->name);
+		kfree(bond->stats);
+		kfree(bond);
+		return -ENOMEM;
+	}
+	bond->bond_proc_info_file = 
+		create_proc_info_entry("info", 0, bond->bond_proc_dir, 
+					bond_get_info);
+	if (bond->bond_proc_info_file == NULL) {
+		printk(KERN_ERR "%s: Cannot init /proc/net/%s/info\n", 
+			dev->name, dev->name);
+		remove_proc_entry(dev->name, proc_net);
+		kfree(bond->stats);
+		kfree(bond);
+		return -ENOMEM;
+	}
+#endif /* CONFIG_PROC_FS */
+
+	if (first_pass == 1) {
+		these_bonds = bond;
+		register_netdevice_notifier(&bond_netdev_notifier);
+		first_pass = 0;
+	} else {
+		last_bond = these_bonds;
+		this_bond = these_bonds->next_bond;
+		while (this_bond != NULL) {
+			last_bond = this_bond;
+			this_bond = this_bond->next_bond;
+		}
+		last_bond->next_bond = bond;
+	} 
+
+	return 0;
+}
+
+/*
+static int __init bond_probe(struct net_device *dev)
+{
+	bond_init(dev);
+	return 0;
+}
+ */
+
+/*
+ * Convert string input module parms.  Accept either the
+ * number of the mode or its string name.
+ */
+static inline int
+bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
+{
+	int i;
+
+	for (i = 0; tbl[i].modename != NULL; i++) {
+		if ((isdigit(*mode_arg) &&
+		    tbl[i].mode == simple_strtol(mode_arg, NULL, 0)) ||
+		    (0 == strncmp(mode_arg, tbl[i].modename,
+				  strlen(tbl[i].modename)))) {
+			return tbl[i].mode;
+		}
+	}
+
+	return -1;
+}
+
+
+static int __init bonding_init(void)
+{
+	int no;
+	int err;
+
+	/* Find a name for this unit */
+	static struct net_device *dev_bond = NULL;
+
+	printk(KERN_INFO "%s", version);
+
+	/*
+	 * Convert string parameters.
+	 */
+	if (mode) {
+		bond_mode = bond_parse_parm(mode, bond_mode_tbl);
+		if (bond_mode == -1) {
+			printk(KERN_WARNING
+			       "bonding_init(): Invalid bonding mode \"%s\"\n",
+			       mode == NULL ? "NULL" : mode);
+			return -EINVAL;
+		}
+	}
+
+	if (multicast) {
+		multicast_mode = bond_parse_parm(multicast, bond_mc_tbl);
+		if (multicast_mode == -1) {
+			printk(KERN_WARNING 
+		       "bonding_init(): Invalid multicast mode \"%s\"\n",
+			       multicast == NULL ? "NULL" : multicast);
+			return -EINVAL;
+		}
+	}
+
+	if (lacp_rate) {
+		if (bond_mode != BOND_MODE_8023AD) {
+			printk(KERN_WARNING
+			       "lacp_rate param is irrelevant in mode %s\n",
+			       bond_mode_name());
+		} else {
+			lacp_fast = bond_parse_parm(lacp_rate, bond_lacp_tbl);
+			if (lacp_fast == -1) {
+				printk(KERN_WARNING
+			       	       "bonding_init(): Invalid lacp rate "
+				       "\"%s\"\n",
+				       lacp_rate == NULL ? "NULL" : lacp_rate);
+
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (max_bonds < 1 || max_bonds > INT_MAX) {
+		printk(KERN_WARNING 
+		       "bonding_init(): max_bonds (%d) not in range %d-%d, "
+		       "so it was reset to BOND_DEFAULT_MAX_BONDS (%d)",
+		       max_bonds, 1, INT_MAX, BOND_DEFAULT_MAX_BONDS);
+		max_bonds = BOND_DEFAULT_MAX_BONDS;
+	}
+	dev_bond = dev_bonds = kmalloc(max_bonds*sizeof(struct net_device), 
+					GFP_KERNEL);
+	if (dev_bond == NULL) {
+		return -ENOMEM;
+	}
+	memset(dev_bonds, 0, max_bonds*sizeof(struct net_device));
+
+	if (miimon < 0) {
+		printk(KERN_WARNING 
+		       "bonding_init(): miimon module parameter (%d), "
+		       "not in range 0-%d, so it was reset to %d\n",
+		       miimon, INT_MAX, BOND_LINK_MON_INTERV);
+		miimon = BOND_LINK_MON_INTERV;
+	}
+
+	if (updelay < 0) {
+		printk(KERN_WARNING 
+		       "bonding_init(): updelay module parameter (%d), "
+		       "not in range 0-%d, so it was reset to 0\n",
+		       updelay, INT_MAX);
+		updelay = 0;
+	}
+
+	if (downdelay < 0) {
+		printk(KERN_WARNING 
+		       "bonding_init(): downdelay module parameter (%d), "
+		       "not in range 0-%d, so it was reset to 0\n",
+		       downdelay, INT_MAX);
+		downdelay = 0;
+	}
+
+	/* reset values for 802.3ad */
+	if (bond_mode == BOND_MODE_8023AD) {
+		if (arp_interval != 0) {
+			printk(KERN_WARNING "bonding_init(): ARP monitoring"
+			       "can't be used simultaneously with 802.3ad, "
+			       "disabling ARP monitoring\n");
+			arp_interval = 0;
+		}
+
+		if (miimon == 0) {
+			printk(KERN_ERR
+			       "bonding_init(): miimon must be specified, "
+			       "otherwise bonding will not detect link failure, "
+			       "speed and duplex which are essential "
+			       "for 802.3ad operation\n");
+			printk(KERN_ERR "Forcing miimon to 100msec\n");
+			miimon = 100;
+		}
+
+		if (multicast_mode != BOND_MULTICAST_ALL) {
+			printk(KERN_ERR
+			       "bonding_init(): Multicast mode must "
+			       "be set to ALL for 802.3ad\n");
+			printk(KERN_ERR "Forcing Multicast mode to ALL\n");
+			multicast_mode = BOND_MULTICAST_ALL;
+		}
+	}
+
+	/* reset values for TLB/ALB */
+	if ((bond_mode == BOND_MODE_TLB) ||
+	    (bond_mode == BOND_MODE_ALB)) {
+		if (miimon == 0) {
+			printk(KERN_ERR
+			       "bonding_init(): miimon must be specified, "
+			       "otherwise bonding will not detect link failure "
+			       "and link speed which are essential "
+			       "for TLB/ALB load balancing\n");
+			printk(KERN_ERR "Forcing miimon to 100msec\n");
+			miimon = 100;
+		}
+
+		if (multicast_mode != BOND_MULTICAST_ACTIVE) {
+			printk(KERN_ERR
+			       "bonding_init(): Multicast mode must "
+			       "be set to ACTIVE for TLB/ALB\n");
+			printk(KERN_ERR "Forcing Multicast mode to ACTIVE\n");
+			multicast_mode = BOND_MULTICAST_ACTIVE;
+		}
+	}
+
+	if (bond_mode == BOND_MODE_ALB) {
+		printk(KERN_INFO
+		       "In ALB mode you might experience client disconnections"
+		       " upon reconnection of a link if the bonding module"
+		       " updelay parameter (%d msec) is incompatible with the"
+		       " forwarding delay time of the switch\n", updelay);
+	}
+
+	if (miimon == 0) {
+		if ((updelay != 0) || (downdelay != 0)) {
+			/* just warn the user the up/down delay will have
+			 * no effect since miimon is zero...
+			 */
+			printk(KERN_WARNING 
+		               "bonding_init(): miimon module parameter not "
+			       "set and updelay (%d) or downdelay (%d) module "
+			       "parameter is set; updelay and downdelay have "
+			       "no effect unless miimon is set\n",
+		               updelay, downdelay);
+		}
+	} else {
+		/* don't allow arp monitoring */
+		if (arp_interval != 0) {
+			printk(KERN_WARNING 
+		               "bonding_init(): miimon (%d) and arp_interval "
+			       "(%d) can't be used simultaneously, "
+			       "disabling ARP monitoring\n",
+		               miimon, arp_interval);
+			arp_interval = 0;
+		}
+
+		if ((updelay % miimon) != 0) {
+			/* updelay will be rounded in bond_init() when it
+			 * is divided by miimon, we just inform user here
+			 */
+			printk(KERN_WARNING 
+		               "bonding_init(): updelay (%d) is not a multiple "
+			       "of miimon (%d), updelay rounded to %d ms\n",
+		               updelay, miimon, (updelay / miimon) * miimon);
+		}
+
+		if ((downdelay % miimon) != 0) {
+			/* downdelay will be rounded in bond_init() when it
+			 * is divided by miimon, we just inform user here
+			 */
+			printk(KERN_WARNING 
+		               "bonding_init(): downdelay (%d) is not a "
+			       "multiple of miimon (%d), downdelay rounded "
+			       "to %d ms\n",
+		               downdelay, miimon, 
+			       (downdelay / miimon) * miimon);
+		}
+	}
+
+	if (arp_interval < 0) {
+		printk(KERN_WARNING 
+		       "bonding_init(): arp_interval module parameter (%d), "
+		       "not in range 0-%d, so it was reset to %d\n",
+		       arp_interval, INT_MAX, BOND_LINK_ARP_INTERV);
+		arp_interval = BOND_LINK_ARP_INTERV;
+	}
+
+        for (arp_ip_count=0 ;
+             (arp_ip_count < MAX_ARP_IP_TARGETS) && arp_ip_target[arp_ip_count];
+              arp_ip_count++ ) {
+                /* TODO: check and log bad ip address */
+                if (my_inet_aton(arp_ip_target[arp_ip_count],
+                                 &arp_target[arp_ip_count]) == 0) {
+                        printk(KERN_WARNING
+                               "bonding_init(): bad arp_ip_target module "
+                               "parameter (%s), ARP monitoring will not be "
+                               "performed\n",
+                               arp_ip_target[arp_ip_count]);
+                        arp_interval = 0;
+		}
+        }
+
+
+	if ( (arp_interval > 0) && (arp_ip_count==0)) {
+		/* don't allow arping if no arp_ip_target given... */
+		printk(KERN_WARNING 
+		       "bonding_init(): arp_interval module parameter "
+		       "(%d) specified without providing an arp_ip_target "
+		       "parameter, arp_interval was reset to 0\n",
+		       arp_interval);
+		arp_interval = 0;
+	}
+
+	if ((miimon == 0) && (arp_interval == 0)) {
+		/* miimon and arp_interval not set, we need one so things
+		 * work as expected, see bonding.txt for details
+		 */
+		printk(KERN_ERR 
+		       "bonding_init(): either miimon or "
+		       "arp_interval and arp_ip_target module parameters "
+		       "must be specified, otherwise bonding will not detect "
+		       "link failures! see bonding.txt for details.\n");
+	}
+
+	if ((primary != NULL) && (bond_mode != BOND_MODE_ACTIVEBACKUP) &&
+	    (bond_mode != BOND_MODE_TLB) &&
+	    (bond_mode != BOND_MODE_ALB)){
+		/* currently, using a primary only makes sense
+		 * in active backup, TLB or ALB modes
+		 */
+		printk(KERN_WARNING 
+		       "bonding_init(): %s primary device specified but has "
+		       "no effect in %s mode\n",
+		       primary, bond_mode_name());
+		primary = NULL;
+	}
+
+
+	for (no = 0; no < max_bonds; no++) {
+		dev_bond->init = bond_init;
+	
+		err = dev_alloc_name(dev_bond,"bond%d");
+		if (err < 0) {
+			kfree(dev_bonds);
+			return err;
+		}
+		SET_MODULE_OWNER(dev_bond);
+		if (register_netdev(dev_bond) != 0) {
+			kfree(dev_bonds);
+			return -EIO;
+		}	
+		dev_bond++;
+	}
+	return 0;
+}
+
+static void __exit bonding_exit(void)
+{
+	struct net_device *dev_bond = dev_bonds;
+	struct bonding *bond;
+	int no;
+
+	unregister_netdevice_notifier(&bond_netdev_notifier);
+		 
+	for (no = 0; no < max_bonds; no++) {
+
+#ifdef CONFIG_PROC_FS
+		bond = (struct bonding *) dev_bond->priv;
+		remove_proc_entry("info", bond->bond_proc_dir);
+		remove_proc_entry(dev_bond->name, proc_net);
+#endif
+		unregister_netdev(dev_bond);
+		kfree(bond->stats);
+		kfree(dev_bond->priv);
+		
+		dev_bond->priv = NULL;
+		dev_bond++;
+	}
+	kfree(dev_bonds);
+}
+
+module_init(bonding_init);
+module_exit(bonding_exit);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRV_DESCRIPTION ", v" DRV_VERSION);
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -urN linux-2.5.69-bk18/drivers/net/bonding/bonding.h linux-2.5.69-bk19/drivers/net/bonding/bonding.h
--- linux-2.5.69-bk18/drivers/net/bonding/bonding.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/drivers/net/bonding/bonding.h	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,181 @@
+/*
+ * Bond several ethernet interfaces into a Cisco, running 'Etherchannel'.
+ *
+ * Portions are (c) Copyright 1995 Simon "Guru Aleph-Null" Janes
+ * NCM: Network and Communications Management, Inc.
+ *
+ * BUT, I'm the one who modified it for ethernet, so:
+ * (c) Copyright 1999, Thomas Davis, tadavis@lbl.gov
+ *
+ *	This software may be used and distributed according to the terms
+ *	of the GNU Public License, incorporated herein by reference.
+ * 
+ *
+ * 2003/03/18 - Amir Noam <amir.noam at intel dot com>,
+ *		Tsippy Mendelson <tsippy.mendelson at intel dot com> and
+ *		Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Added support for IEEE 802.3ad Dynamic link aggregation mode.
+ *
+ * 2003/05/01 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
+ *		Amir Noam <amir.noam at intel dot com>
+ *	- Code beautification and style changes (mainly in comments).
+ *
+ * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Added support for Transmit load balancing mode.
+ */
+ 
+#ifndef _LINUX_BONDING_H
+#define _LINUX_BONDING_H
+
+#include <linux/timer.h>
+#include <linux/proc_fs.h>
+#include "bond_3ad.h"
+#include "bond_alb.h"
+
+#ifdef BONDING_DEBUG
+
+// use this like so: BOND_PRINT_DBG(("foo = %d, bar = %d", foo, bar));
+#define BOND_PRINT_DBG(X)                                     \
+do {                                                          \
+	printk(KERN_DEBUG "%s (%d)", __FUNCTION__, __LINE__); \
+	printk X;                                             \
+	printk("\n");                                         \
+} while(0)
+
+#else
+#define BOND_PRINT_DBG(X)
+#endif /* BONDING_DEBUG */
+
+#define IS_UP(dev)  ((((dev)->flags & (IFF_UP)) == (IFF_UP)) && \
+		     (netif_running(dev) && netif_carrier_ok(dev)))
+
+/* Checks whether the dev is ready for transmit. We do not check netif_running
+ * since a device can be stopped by the driver for short periods of time for
+ * maintainance. dev_queue_xmit() handles this by queing the packet until the
+ * the dev is running again. Keeping packets ordering requires sticking the
+ * same dev as much as possible
+ */
+#define SLAVE_IS_OK(slave) \
+		     ((((slave)->dev->flags & (IFF_UP)) == (IFF_UP)) && \
+		     netif_carrier_ok((slave)->dev) && \
+		     ((slave)->link == BOND_LINK_UP) && \
+		     ((slave)->state == BOND_STATE_ACTIVE))
+
+
+typedef struct slave {
+	struct slave *next;
+	struct slave *prev;
+	struct net_device *dev;
+	short  delay;
+	unsigned long jiffies;
+	char   link;    /* one of BOND_LINK_XXXX */
+	char   state;   /* one of BOND_STATE_XXXX */
+	unsigned short original_flags;
+	u32 link_failure_count;
+	u16    speed;
+	u8     duplex;
+	u8     perm_hwaddr[ETH_ALEN];
+	struct ad_slave_info ad_info; /* HUGE - better to dynamically alloc */
+	struct tlb_slave_info tlb_info;
+} slave_t;
+
+/*
+ * Here are the locking policies for the two bonding locks:
+ *
+ * 1) Get bond->lock when reading/writing slave list.
+ * 2) Get bond->ptrlock when reading/writing bond->current_slave.
+ *    (It is unnecessary when the write-lock is put with bond->lock.)
+ * 3) When we lock with bond->ptrlock, we must lock with bond->lock
+ *    beforehand.
+ */
+typedef struct bonding {
+	slave_t *next;
+	slave_t *prev;
+	slave_t *current_slave;
+	slave_t *primary_slave;
+	slave_t *current_arp_slave;
+	__s32 slave_cnt;
+	rwlock_t lock;
+	rwlock_t ptrlock;
+	struct timer_list mii_timer;
+	struct timer_list arp_timer;
+	struct net_device_stats *stats;
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry *bond_proc_dir;
+	struct proc_dir_entry *bond_proc_info_file;
+#endif /* CONFIG_PROC_FS */
+	struct bonding *next_bond;
+	struct net_device *device;
+	struct dev_mc_list *mc_list;
+	unsigned short flags;
+	struct ad_bond_info ad_info;
+	struct alb_bond_info alb_info;
+} bonding_t;
+
+/* Forward declarations */
+void bond_set_slave_active_flags(slave_t *slave);
+void bond_set_slave_inactive_flags(slave_t *slave);
+
+/**
+ * These functions can be used for iterating the slave list
+ * (which is circular)
+ * Caller must hold bond lock for read
+ */
+extern inline struct slave*
+bond_get_first_slave(struct bonding *bond)
+{
+	/* if there are no slaves return NULL */
+	if (bond->next == (slave_t *)bond) {
+		return NULL;
+	}
+	return bond->next;
+}
+
+/**
+ * Caller must hold bond lock for read
+ */
+extern inline struct slave*
+bond_get_next_slave(struct bonding *bond, struct slave *slave)
+{
+	/* If we have reached the last slave return NULL */
+	if (slave->next == bond->next) {
+		return NULL;
+	}
+	return slave->next;
+}
+
+/**
+ * Returns NULL if the net_device does not belong to any of the bond's slaves
+ *
+ * Caller must hold bond lock for read
+ */
+extern inline struct slave*
+bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev)
+{
+	struct slave *our_slave = bond->next;
+
+	/* check if the list of slaves is empty */
+	if (our_slave == (slave_t *)bond) {
+		return NULL;
+	}
+
+	for (; our_slave; our_slave = bond_get_next_slave(bond, our_slave)) {
+		if (our_slave->dev == slave_dev) {
+			break;
+		}
+	}
+	return our_slave;
+}
+
+extern inline struct bonding*
+bond_get_bond_by_slave(struct slave *slave)
+{
+	if (!slave || !slave->dev->master) {
+		return NULL;
+	}
+
+	return (struct bonding *)(slave->dev->master->priv);
+}
+
+#endif /* _LINUX_BONDING_H */
+
diff -urN linux-2.5.69-bk18/drivers/net/bonding.c linux-2.5.69-bk19/drivers/net/bonding.c
--- linux-2.5.69-bk18/drivers/net/bonding.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/bonding.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,3299 +0,0 @@
-/*
- * originally based on the dummy device.
- *
- * Copyright 1999, Thomas Davis, tadavis@lbl.gov.  
- * Licensed under the GPL. Based on dummy.c, and eql.c devices.
- *
- * bonding.c: an Ethernet Bonding driver
- *
- * This is useful to talk to a Cisco EtherChannel compatible equipment:
- *	Cisco 5500
- *	Sun Trunking (Solaris)
- *	Alteon AceDirector Trunks
- *	Linux Bonding
- *	and probably many L2 switches ...
- *
- * How it works:
- *    ifconfig bond0 ipaddress netmask up
- *      will setup a network device, with an ip address.  No mac address 
- *	will be assigned at this time.  The hw mac address will come from 
- *	the first slave bonded to the channel.  All slaves will then use 
- *	this hw mac address.
- *
- *    ifconfig bond0 down
- *         will release all slaves, marking them as down.
- *
- *    ifenslave bond0 eth0
- *	will attach eth0 to bond0 as a slave.  eth0 hw mac address will either
- *	a: be used as initial mac address
- *	b: if a hw mac address already is there, eth0's hw mac address 
- *	   will then be set from bond0.
- *
- * v0.1 - first working version.
- * v0.2 - changed stats to be calculated by summing slaves stats.
- *
- * Changes:
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- * - fix leaks on failure at bond_init
- *
- * 2000/09/30 - Willy Tarreau <willy at meta-x.org>
- *     - added trivial code to release a slave device.
- *     - fixed security bug (CAP_NET_ADMIN not checked)
- *     - implemented MII link monitoring to disable dead links :
- *       All MII capable slaves are checked every <miimon> milliseconds
- *       (100 ms seems good). This value can be changed by passing it to
- *       insmod. A value of zero disables the monitoring (default).
- *     - fixed an infinite loop in bond_xmit_roundrobin() when there's no
- *       good slave.
- *     - made the code hopefully SMP safe
- *
- * 2000/10/03 - Willy Tarreau <willy at meta-x.org>
- *     - optimized slave lists based on relevant suggestions from Thomas Davis
- *     - implemented active-backup method to obtain HA with two switches:
- *       stay as long as possible on the same active interface, while we
- *       also monitor the backup one (MII link status) because we want to know
- *       if we are able to switch at any time. ( pass "mode=1" to insmod )
- *     - lots of stress testings because we need it to be more robust than the
- *       wires ! :->
- *
- * 2000/10/09 - Willy Tarreau <willy at meta-x.org>
- *     - added up and down delays after link state change.
- *     - optimized the slaves chaining so that when we run forward, we never
- *       repass through the bond itself, but we can find it by searching
- *       backwards. Renders the deletion more difficult, but accelerates the
- *       scan.
- *     - smarter enslaving and releasing.
- *     - finer and more robust SMP locking
- *
- * 2000/10/17 - Willy Tarreau <willy at meta-x.org>
- *     - fixed two potential SMP race conditions
- *
- * 2000/10/18 - Willy Tarreau <willy at meta-x.org>
- *     - small fixes to the monitoring FSM in case of zero delays
- * 2000/11/01 - Willy Tarreau <willy at meta-x.org>
- *     - fixed first slave not automatically used in trunk mode.
- * 2000/11/10 : spelling of "EtherChannel" corrected.
- * 2000/11/13 : fixed a race condition in case of concurrent accesses to ioctl().
- * 2000/12/16 : fixed improper usage of rtnl_exlock_nowait().
- *
- * 2001/1/3 - Chad N. Tindel <ctindel at ieee dot org>
- *     - The bonding driver now simulates MII status monitoring, just like
- *       a normal network device.  It will show that the link is down iff
- *       every slave in the bond shows that their links are down.  If at least
- *       one slave is up, the bond's MII status will appear as up.
- *
- * 2001/2/7 - Chad N. Tindel <ctindel at ieee dot org>
- *     - Applications can now query the bond from user space to get
- *       information which may be useful.  They do this by calling
- *       the BOND_INFO_QUERY ioctl.  Once the app knows how many slaves
- *       are in the bond, it can call the BOND_SLAVE_INFO_QUERY ioctl to
- *       get slave specific information (# link failures, etc).  See
- *       <linux/if_bonding.h> for more details.  The structs of interest
- *       are ifbond and ifslave.
- *
- * 2001/4/5 - Chad N. Tindel <ctindel at ieee dot org>
- *     - Ported to 2.4 Kernel
- * 
- * 2001/5/2 - Jeffrey E. Mast <jeff at mastfamily dot com>
- *     - When a device is detached from a bond, the slave device is no longer
- *       left thinking that is has a master.
- *
- * 2001/5/16 - Jeffrey E. Mast <jeff at mastfamily dot com>
- *     - memset did not appropriately initialized the bond rw_locks. Used 
- *       rwlock_init to initialize to unlocked state to prevent deadlock when 
- *       first attempting a lock
- *     - Called SET_MODULE_OWNER for bond device
- *
- * 2001/5/17 - Tim Anderson <tsa at mvista.com>
- *     - 2 paths for releasing for slave release; 1 through ioctl
- *       and 2) through close. Both paths need to release the same way.
- *     - the free slave in bond release is changing slave status before
- *       the free. The netdev_set_master() is intended to change slave state
- *       so it should not be done as part of the release process.
- *     - Simple rule for slave state at release: only the active in A/B and
- *       only one in the trunked case.
- *
- * 2001/6/01 - Tim Anderson <tsa at mvista.com>
- *     - Now call dev_close when releasing a slave so it doesn't screw up
- *       out routing table.
- *
- * 2001/6/01 - Chad N. Tindel <ctindel at ieee dot org>
- *     - Added /proc support for getting bond and slave information.
- *       Information is in /proc/net/<bond device>/info. 
- *     - Changed the locking when calling bond_close to prevent deadlock.
- *
- * 2001/8/05 - Janice Girouard <girouard at us.ibm.com>
- *     - correct problem where refcnt of slave is not incremented in bond_ioctl
- *       so the system hangs when halting.
- *     - correct locking problem when unable to malloc in bond_enslave.
- *     - adding bond_xmit_xor logic.
- *     - adding multiple bond device support.
- *
- * 2001/8/13 - Erik Habbinga <erik_habbinga at hp dot com>
- *     - correct locking problem with rtnl_exlock_nowait
- *
- * 2001/8/23 - Janice Girouard <girouard at us.ibm.com>
- *     - bzero initial dev_bonds, to correct oops
- *     - convert SIOCDEVPRIVATE to new MII ioctl calls
- *
- * 2001/9/13 - Takao Indoh <indou dot takao at jp dot fujitsu dot com>
- *     - Add the BOND_CHANGE_ACTIVE ioctl implementation
- *
- * 2001/9/14 - Mark Huth <mhuth at mvista dot com>
- *     - Change MII_LINK_READY to not check for end of auto-negotiation,
- *       but only for an up link.
- *
- * 2001/9/20 - Chad N. Tindel <ctindel at ieee dot org>
- *     - Add the device field to bonding_t.  Previously the net_device 
- *       corresponding to a bond wasn't available from the bonding_t 
- *       structure.
- *
- * 2001/9/25 - Janice Girouard <girouard at us.ibm.com>
- *     - add arp_monitor for active backup mode
- *
- * 2001/10/23 - Takao Indoh <indou dot takao at jp dot fujitsu dot com>
- *     - Various memory leak fixes
- *
- * 2001/11/5 - Mark Huth <mark dot huth at mvista dot com>
- *     - Don't take rtnl lock in bond_mii_monitor as it deadlocks under 
- *       certain hotswap conditions.  
- *       Note:  this same change may be required in bond_arp_monitor ???
- *     - Remove possibility of calling bond_sethwaddr with NULL slave_dev ptr 
- *     - Handle hot swap ethernet interface deregistration events to remove
- *       kernel oops following hot swap of enslaved interface
- *
- * 2002/1/2 - Chad N. Tindel <ctindel at ieee dot org>
- *     - Restore original slave flags at release time.
- *
- * 2002/02/18 - Erik Habbinga <erik_habbinga at hp dot com>
- *     - bond_release(): calling kfree on our_slave after call to
- *       bond_restore_slave_flags, not before
- *     - bond_enslave(): saving slave flags into original_flags before
- *       call to netdev_set_master, so the IFF_SLAVE flag doesn't end
- *       up in original_flags
- *
- * 2002/04/05 - Mark Smith <mark.smith at comdev dot cc> and
- *              Steve Mead <steve.mead at comdev dot cc>
- *     - Port Gleb Natapov's multicast support patchs from 2.4.12
- *       to 2.4.18 adding support for multicast.
- *
- * 2002/06/10 - Tony Cureington <tony.cureington * hp_com>
- *     - corrected uninitialized pointer (ifr.ifr_data) in bond_check_dev_link;
- *       actually changed function to use MIIPHY, then MIIREG, and finally
- *       ETHTOOL to determine the link status
- *     - fixed bad ifr_data pointer assignments in bond_ioctl
- *     - corrected mode 1 being reported as active-backup in bond_get_info;
- *       also added text to distinguish type of load balancing (rr or xor)
- *     - change arp_ip_target module param from "1-12s" (array of 12 ptrs)
- *       to "s" (a single ptr)
- *
- * 2002/08/30 - Jay Vosburgh <fubar at us dot ibm dot com>
- *     - Removed acquisition of xmit_lock in set_multicast_list; caused
- *       deadlock on SMP (lock is held by caller).
- *     - Revamped SIOCGMIIPHY, SIOCGMIIREG portion of bond_check_dev_link().
- *
- * 2002/09/18 - Jay Vosburgh <fubar at us dot ibm dot com>
- *     - Fixed up bond_check_dev_link() (and callers): removed some magic
- *	 numbers, banished local MII_ defines, wrapped ioctl calls to
- *	 prevent EFAULT errors
- *
- * 2002/9/30 - Jay Vosburgh <fubar at us dot ibm dot com>
- *     - make sure the ip target matches the arp_target before saving the
- *	 hw address.
- *
- * 2002/9/30 - Dan Eisner <eisner at 2robots dot com>
- *     - make sure my_ip is set before taking down the link, since
- *	 not all switches respond if the source ip is not set.
- *
- * 2002/10/8 - Janice Girouard <girouard at us dot ibm dot com>
- *     - read in the local ip address when enslaving a device
- *     - add primary support
- *     - make sure 2*arp_interval has passed when a new device
- *       is brought on-line before taking it down.
- *
- * 2002/09/11 - Philippe De Muyter <phdm at macqel dot be>
- *     - Added bond_xmit_broadcast logic.
- *     - Added bond_mode() support function.
- *
- * 2002/10/26 - Laurent Deniel <laurent.deniel at free.fr>
- *     - allow to register multicast addresses only on active slave
- *       (useful in active-backup mode)
- *     - add multicast module parameter
- *     - fix deletion of multicast groups after unloading module
- *
- * 2002/11/06 - Kameshwara Rayaprolu <kameshwara.rao * wipro_com>
- *     - Changes to prevent panic from closing the device twice; if we close 
- *       the device in bond_release, we must set the original_flags to down 
- *       so it won't be closed again by the network layer.
- *
- * 2002/11/07 - Tony Cureington <tony.cureington * hp_com>
- *     - Fix arp_target_hw_addr memory leak
- *     - Created activebackup_arp_monitor function to handle arp monitoring 
- *       in active backup mode - the bond_arp_monitor had several problems... 
- *       such as allowing slaves to tx arps sequentially without any delay 
- *       for a response
- *     - Renamed bond_arp_monitor to loadbalance_arp_monitor and re-wrote
- *       this function to just handle arp monitoring in load-balancing mode;
- *       it is a lot more compact now
- *     - Changes to ensure one and only one slave transmits in active-backup 
- *       mode
- *     - Robustesize parameters; warn users about bad combinations of 
- *       parameters; also if miimon is specified and a network driver does 
- *       not support MII or ETHTOOL, inform the user of this
- *     - Changes to support link_failure_count when in arp monitoring mode
- *     - Fix up/down delay reported in /proc
- *     - Added version; log version; make version available from "modinfo -d"
- *     - Fixed problem in bond_check_dev_link - if the first IOCTL (SIOCGMIIPH)
- *	 failed, the ETHTOOL ioctl never got a chance
- *
- * 2002/11/16 - Laurent Deniel <laurent.deniel at free.fr>
- *     - fix multicast handling in activebackup_arp_monitor
- *     - remove one unnecessary and confusing current_slave == slave test 
- *	 in activebackup_arp_monitor
- *
- *  2002/11/17 - Laurent Deniel <laurent.deniel at free.fr>
- *     - fix bond_slave_info_query when slave_id = num_slaves
- *
- *  2002/11/19 - Janice Girouard <girouard at us dot ibm dot com>
- *     - correct ifr_data reference.  Update ifr_data reference
- *       to mii_ioctl_data struct values to avoid confusion.
- *
- *  2002/11/22 - Bert Barbe <bert.barbe at oracle dot com>
- *      - Add support for multiple arp_ip_target
- *
- *  2002/12/13 - Jay Vosburgh <fubar at us dot ibm dot com>
- *	- Changed to allow text strings for mode and multicast, e.g.,
- *	  insmod bonding mode=active-backup.  The numbers still work.
- *	  One change: an invalid choice will cause module load failure,
- *	  rather than the previous behavior of just picking one.
- *	- Minor cleanups; got rid of dup ctype stuff, atoi function
- * 
- * 2003/02/07 - Jay Vosburgh <fubar at us dot ibm dot com>
- *	- Added use_carrier module parameter that causes miimon to
- *	  use netif_carrier_ok() test instead of MII/ETHTOOL ioctls.
- *	- Minor cleanups; consolidated ioctl calls to one function.
- *
- * 2003/02/07 - Tony Cureington <tony.cureington * hp_com>
- *	- Fix bond_mii_monitor() logic error that could result in
- *	  bonding round-robin mode ignoring links after failover/recovery
- *
- * 2003/03/17 - Jay Vosburgh <fubar at us dot ibm dot com>
- *	- kmalloc fix (GFP_KERNEL to GFP_ATOMIC) reported by
- *	  Shmulik dot Hen at intel.com.
- *	- Based on discussion on mailing list, changed use of
- *	  update_slave_cnt(), created wrapper functions for adding/removing
- *	  slaves, changed bond_xmit_xor() to check slave_cnt instead of
- *	  checking slave and slave->dev (which only worked by accident).
- *	- Misc code cleanup: get arp_send() prototype from header file,
- *	  add max_bonds to bonding.txt.
- *
- * 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- *		Shmulik Hen <shmulik.hen at intel dot com>
- *	- Make sure only bond_attach_slave() and bond_detach_slave() can
- *	  manipulate the slave list, including slave_cnt, even when in
- *	  bond_release_all().
- *	- Fixed hang in bond_release() while traffic is running.
- *	  netdev_set_master() must not be called from within the bond lock.
- *
- * 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- *		Shmulik Hen <shmulik.hen at intel dot com>
- *	- Fixed hang in bond_enslave(): netdev_set_master() must not be
- *	  called from within the bond lock while traffic is running.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/socket.h>
-#include <linux/ctype.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <linux/rtnetlink.h>
-#include <linux/if_bonding.h>
-#include <linux/smp.h>
-#include <linux/if_ether.h>
-#include <net/arp.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/uaccess.h>
-
-#define DRV_VERSION		"2.5.65-20030320"
-#define DRV_RELDATE		"March 20, 2003"
-#define DRV_NAME		"bonding"
-#define DRV_DESCRIPTION		"Ethernet Channel Bonding Driver"
-
-static const char *version =
-DRV_NAME ".c:v" DRV_VERSION " (" DRV_RELDATE ")\n";
-
-/* monitor all links that often (in milliseconds). <=0 disables monitoring */
-#ifndef BOND_LINK_MON_INTERV
-#define BOND_LINK_MON_INTERV	0
-#endif
-
-#ifndef BOND_LINK_ARP_INTERV
-#define BOND_LINK_ARP_INTERV	0
-#endif
-
-#ifndef MAX_ARP_IP_TARGETS
-#define MAX_ARP_IP_TARGETS 16
-#endif
-
-static int arp_interval = BOND_LINK_ARP_INTERV;
-static char *arp_ip_target[MAX_ARP_IP_TARGETS] = { NULL, };
-static unsigned long arp_target[MAX_ARP_IP_TARGETS] = { 0, } ;
-static int arp_ip_count = 0;
-static u32 my_ip = 0;
-char *arp_target_hw_addr = NULL;
-
-static char *primary= NULL;
-
-static int max_bonds	= BOND_DEFAULT_MAX_BONDS;
-static int miimon	= BOND_LINK_MON_INTERV;
-static int use_carrier	= 1;
-static int bond_mode	= BOND_MODE_ROUNDROBIN;
-static int updelay	= 0;
-static int downdelay	= 0;
-
-static char *mode	= NULL;
-
-static struct bond_parm_tbl bond_mode_tbl[] = {
-{	"balance-rr",		BOND_MODE_ROUNDROBIN},
-{	"active-backup",	BOND_MODE_ACTIVEBACKUP},
-{	"balance-xor",		BOND_MODE_XOR},
-{	"broadcast",		BOND_MODE_BROADCAST},
-{	NULL,			-1},
-};
-
-static int multicast_mode	= BOND_MULTICAST_ALL;
-static char *multicast		= NULL;
-
-static struct bond_parm_tbl bond_mc_tbl[] = {
-{	"disabled",		BOND_MULTICAST_DISABLED},
-{	"active",		BOND_MULTICAST_ACTIVE},
-{	"all",			BOND_MULTICAST_ALL},
-{	NULL,			-1},
-};
-
-static int first_pass	= 1;
-static struct bonding *these_bonds =  NULL;
-static struct net_device *dev_bonds = NULL;
-
-MODULE_PARM(max_bonds, "i");
-MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
-MODULE_PARM(miimon, "i");
-MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
-MODULE_PARM(use_carrier, "i");
-MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 09 for off, 1 for on (default)");
-MODULE_PARM(mode, "s");
-MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor");
-MODULE_PARM(arp_interval, "i");
-MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
-MODULE_PARM(arp_ip_target, "1-" __MODULE_STRING(MAX_ARP_IP_TARGETS) "s");
-MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
-MODULE_PARM(updelay, "i");
-MODULE_PARM_DESC(updelay, "Delay before considering link up, in milliseconds");
-MODULE_PARM(downdelay, "i");
-MODULE_PARM_DESC(downdelay, "Delay before considering link down, in milliseconds");
-MODULE_PARM(primary, "s");
-MODULE_PARM_DESC(primary, "Primary network device to use");
-MODULE_PARM(multicast, "s");
-MODULE_PARM_DESC(multicast, "Mode for multicast support : 0 for none, 1 for active slave, 2 for all slaves (default)");
-
-static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *dev);
-static int bond_xmit_xor(struct sk_buff *skb, struct net_device *dev);
-static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *dev);
-static struct net_device_stats *bond_get_stats(struct net_device *dev);
-static void bond_mii_monitor(struct net_device *dev);
-static void loadbalance_arp_monitor(struct net_device *dev);
-static void activebackup_arp_monitor(struct net_device *dev);
-static int bond_event(struct notifier_block *this, unsigned long event, void *ptr);
-static void bond_restore_slave_flags(slave_t *slave);
-static void bond_mc_list_destroy(struct bonding *bond);
-static void bond_mc_add(bonding_t *bond, void *addr, int alen);
-static void bond_mc_delete(bonding_t *bond, void *addr, int alen);
-static int bond_mc_list_copy (struct dev_mc_list *src, struct bonding *dst, int gpf_flag);
-static inline int dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list *dmi2);
-static void bond_set_promiscuity(bonding_t *bond, int inc);
-static void bond_set_allmulti(bonding_t *bond, int inc);
-static struct dev_mc_list* bond_mc_list_find_dmi(struct dev_mc_list *dmi, struct dev_mc_list *mc_list);
-static void bond_mc_update(bonding_t *bond, slave_t *new, slave_t *old);
-static void bond_set_slave_inactive_flags(slave_t *slave);
-static void bond_set_slave_active_flags(slave_t *slave);
-static int bond_enslave(struct net_device *master, struct net_device *slave);
-static int bond_release(struct net_device *master, struct net_device *slave);
-static int bond_release_all(struct net_device *master);
-static int bond_sethwaddr(struct net_device *master, struct net_device *slave);
-
-/*
- * bond_get_info is the interface into the /proc filesystem.  This is
- * a different interface than the BOND_INFO_QUERY ioctl.  That is done
- * through the generic networking ioctl interface, and bond_info_query
- * is the internal function which provides that information.
- */
-static int bond_get_info(char *buf, char **start, off_t offset, int length);
-
-/* #define BONDING_DEBUG 1 */
-
-/* several macros */
-
-#define IS_UP(dev)	((((dev)->flags & (IFF_UP)) == (IFF_UP)) && \
-			(netif_running(dev) && netif_carrier_ok(dev)))
-  
-static void arp_send_all(slave_t *slave)
-{	
-	int i; 
-
-	for (i = 0; (i<MAX_ARP_IP_TARGETS) && arp_target[i]; i++) { 
-		arp_send(ARPOP_REQUEST, ETH_P_ARP, arp_target[i], slave->dev, 
-			 my_ip, arp_target_hw_addr, slave->dev->dev_addr,
-			 arp_target_hw_addr); 
-	} 
-}
- 
-
-static const char *
-bond_mode_name(void)
-{
-	switch (bond_mode) {
-	case BOND_MODE_ROUNDROBIN :
-		return "load balancing (round-robin)";
-	case BOND_MODE_ACTIVEBACKUP :
-		return "fault-tolerance (active-backup)";
-	case BOND_MODE_XOR :
-		return "load balancing (xor)";
-	case BOND_MODE_BROADCAST :
-		return "fault-tolerance (broadcast)";
-	default :
-		return "unknown";
-	}
-}
-
-static const char *
-multicast_mode_name(void)
-{
-	switch(multicast_mode) {
-	case BOND_MULTICAST_DISABLED :
-		return "disabled";
-	case BOND_MULTICAST_ACTIVE :
-		return "active slave only";
-	case BOND_MULTICAST_ALL :
-		return "all slaves";
-	default :
-		return "unknown";
-	}
-}
-
-static void bond_restore_slave_flags(slave_t *slave)
-{
-	slave->dev->flags = slave->original_flags;
-}
-
-static void bond_set_slave_inactive_flags(slave_t *slave)
-{
-	slave->state = BOND_STATE_BACKUP;
-	slave->dev->flags |= IFF_NOARP;
-}
-
-static void bond_set_slave_active_flags(slave_t *slave)
-{
-	slave->state = BOND_STATE_ACTIVE;
-	slave->dev->flags &= ~IFF_NOARP;
-}
-
-/*
- * This function counts and verifies the the number of attached
- * slaves, checking the count against the expected value (given that incr
- * is either 1 or -1, for add or removal of a slave).  Only
- * bond_xmit_xor() uses the slave_cnt value, but this is still a good
- * consistency check.
- */
-static inline void
-update_slave_cnt(bonding_t *bond, int incr)
-{
-	slave_t *slave = NULL;
-	int expect = bond->slave_cnt + incr;
-
-	bond->slave_cnt = 0;
-	for (slave = bond->prev; slave != (slave_t*)bond;
-	     slave = slave->prev) {
-		bond->slave_cnt++;
-	}
-
-	if (expect != bond->slave_cnt)
-		BUG();
-}
-
-/* 
- * This function detaches the slave <slave> from the list <bond>.
- * WARNING: no check is made to verify if the slave effectively
- * belongs to <bond>. It returns <slave> in case it's needed.
- * Nothing is freed on return, structures are just unchained.
- * If the bond->current_slave pointer was pointing to <slave>,
- * it's replaced with slave->next, or <bond> if not applicable.
- *
- * bond->lock held by caller.
- */
-static slave_t *
-bond_detach_slave(bonding_t *bond, slave_t *slave)
-{
-	if ((bond == NULL) || (slave == NULL) ||
-	   ((void *)bond == (void *)slave)) {
-		printk(KERN_ERR
-			"bond_detach_slave(): trying to detach "
-			"slave %p from bond %p\n", bond, slave);
-		return slave;
-	}
-
-	if (bond->next == slave) {  /* is the slave at the head ? */
-		if (bond->prev == slave) {  /* is the slave alone ? */
-			write_lock(&bond->ptrlock);
-			bond->current_slave = NULL; /* no slave anymore */
-			write_unlock(&bond->ptrlock);
-			bond->prev = bond->next = (slave_t *)bond;
-		} else { /* not alone */
-			bond->next        = slave->next;
-			slave->next->prev = (slave_t *)bond;
-			bond->prev->next  = slave->next;
-
-			write_lock(&bond->ptrlock);
-			if (bond->current_slave == slave) {
-				bond->current_slave = slave->next;
-			}
-			write_unlock(&bond->ptrlock);
-		}
-	} else {
-		slave->prev->next = slave->next;
-		if (bond->prev == slave) {  /* is this slave the last one ? */
-			bond->prev = slave->prev;
-		} else {
-			slave->next->prev = slave->prev;
-		}
-
-		write_lock(&bond->ptrlock);
-		if (bond->current_slave == slave) {
-			bond->current_slave = slave->next;
-		}
-		write_unlock(&bond->ptrlock);
-	}
-
-	update_slave_cnt(bond, -1);
-
-	return slave;
-}
-
-static void
-bond_attach_slave(struct bonding *bond, struct slave *new_slave)
-{
-	/* 
-	 * queue to the end of the slaves list, make the first element its
-	 * successor, the last one its predecessor, and make it the bond's
-	 * predecessor. 
-	 *
-	 * Just to clarify, so future bonding driver hackers don't go through
-	 * the same confusion stage I did trying to figure this out, the
-	 * slaves are stored in a double linked circular list, sortof.
-	 * In the ->next direction, the last slave points to the first slave,
-	 * bypassing bond; only the slaves are in the ->next direction.
-	 * In the ->prev direction, however, the first slave points to bond
-	 * and bond points to the last slave.
-	 *
-	 * It looks like a circle with a little bubble hanging off one side
-	 * in the ->prev direction only.
-	 *
-	 * When going through the list once, its best to start at bond->prev
-	 * and go in the ->prev direction, testing for bond.  Doing this
-	 * in the ->next direction doesn't work.  Trust me, I know this now.
-	 * :)  -mts 2002.03.14
-	 */
-	new_slave->prev       = bond->prev;
-	new_slave->prev->next = new_slave;
-	bond->prev            = new_slave;
-	new_slave->next       = bond->next;
-
-	update_slave_cnt(bond, 1);
-}
-
-
-/*
- * Less bad way to call ioctl from within the kernel; this needs to be
- * done some other way to get the call out of interrupt context.
- * Needs "ioctl" variable to be supplied by calling context.
- */
-#define IOCTL(dev, arg, cmd) ({		\
-	int ret;			\
-	mm_segment_t fs = get_fs();	\
-	set_fs(get_ds());		\
-	ret = ioctl(dev, arg, cmd);	\
-	set_fs(fs);			\
-	ret; })
-
-/* 
- * if <dev> supports MII link status reporting, check its link status.
- *
- * We either do MII/ETHTOOL ioctls, or check netif_carrier_ok(),
- * depening upon the setting of the use_carrier parameter.
- *
- * Return either BMSR_LSTATUS, meaning that the link is up (or we
- * can't tell and just pretend it is), or 0, meaning that the link is
- * down.
- *
- * If reporting is non-zero, instead of faking link up, return -1 if
- * both ETHTOOL and MII ioctls fail (meaning the device does not
- * support them).  If use_carrier is set, return whatever it says.
- * It'd be nice if there was a good way to tell if a driver supports
- * netif_carrier, but there really isn't.
- */
-static int
-bond_check_dev_link(struct net_device *dev, int reporting)
-{
-	static int (* ioctl)(struct net_device *, struct ifreq *, int);
-	struct ifreq ifr;
-	struct mii_ioctl_data *mii;
-	struct ethtool_value etool;
-
-	if (use_carrier) {
-		return netif_carrier_ok(dev) ? BMSR_LSTATUS : 0;
-	}
-
-	ioctl = dev->do_ioctl;
-	if (ioctl) {
-		/* TODO: set pointer to correct ioctl on a per team member */
-		/*       bases to make this more efficient. that is, once  */
-		/*       we determine the correct ioctl, we will always    */
-		/*       call it and not the others for that team          */
-		/*       member.                                           */
-
-		/*
-		 * We cannot assume that SIOCGMIIPHY will also read a
-		 * register; not all network drivers (e.g., e100)
-		 * support that.
-		 */
-
-		/* Yes, the mii is overlaid on the ifreq.ifr_ifru */
-		mii = (struct mii_ioctl_data *)&ifr.ifr_data;
-		if (IOCTL(dev, &ifr, SIOCGMIIPHY) == 0) {
-			mii->reg_num = MII_BMSR;
-			if (IOCTL(dev, &ifr, SIOCGMIIREG) == 0) {
-				return mii->val_out & BMSR_LSTATUS;
-			}
-		}
-
-		/* try SIOCETHTOOL ioctl, some drivers cache ETHTOOL_GLINK */
-		/* for a period of time so we attempt to get link status   */
-		/* from it last if the above MII ioctls fail...            */
-	        etool.cmd = ETHTOOL_GLINK;
-	        ifr.ifr_data = (char*)&etool;
-		if (IOCTL(dev, &ifr, SIOCETHTOOL) == 0) {
-			if (etool.data == 1) {
-				return BMSR_LSTATUS;
-			} else { 
-#ifdef BONDING_DEBUG
-				printk(KERN_INFO 
-					":: SIOCETHTOOL shows link down \n");
-#endif
-				return 0;
-			} 
-		}
-
-	}
- 
-	/*
-	 * If reporting, report that either there's no dev->do_ioctl,
-	 * or both SIOCGMIIREG and SIOCETHTOOL failed (meaning that we
-	 * cannot report link status).  If not reporting, pretend
-	 * we're ok.
-	 */
-	return reporting ? -1 : BMSR_LSTATUS;
-}
-
-static u16 bond_check_mii_link(bonding_t *bond)
-{
-	int has_active_interface = 0;
-	unsigned long flags;
-
-	read_lock_irqsave(&bond->lock, flags);
-	read_lock(&bond->ptrlock);
-	has_active_interface = (bond->current_slave != NULL);
-	read_unlock(&bond->ptrlock);
-	read_unlock_irqrestore(&bond->lock, flags);
-
-	return (has_active_interface ? BMSR_LSTATUS : 0);
-}
-
-static int bond_open(struct net_device *dev)
-{
-	struct timer_list *timer = &((struct bonding *)(dev->priv))->mii_timer;
-	struct timer_list *arp_timer = &((struct bonding *)(dev->priv))->arp_timer;
-	MOD_INC_USE_COUNT;
-
-	if (miimon > 0) {  /* link check interval, in milliseconds. */
-		init_timer(timer);
-		timer->expires  = jiffies + (miimon * HZ / 1000);
-		timer->data     = (unsigned long)dev;
-		timer->function = (void *)&bond_mii_monitor;
-		add_timer(timer);
-	}
-
-	if (arp_interval> 0) {  /* arp interval, in milliseconds. */
-		init_timer(arp_timer);
-		arp_timer->expires  = jiffies + (arp_interval * HZ / 1000);
-		arp_timer->data     = (unsigned long)dev;
-		if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
-			arp_timer->function = (void *)&activebackup_arp_monitor;
-		} else {
-			arp_timer->function = (void *)&loadbalance_arp_monitor;
-		}
-		add_timer(arp_timer);
-	}
-	return 0;
-}
-
-static int bond_close(struct net_device *master)
-{
-	bonding_t *bond = (struct bonding *) master->priv;
-	unsigned long flags;
-
-	write_lock_irqsave(&bond->lock, flags);
-
-	if (miimon > 0) {  /* link check interval, in milliseconds. */
-		del_timer(&bond->mii_timer);
-	}
-	if (arp_interval> 0) {  /* arp interval, in milliseconds. */
-		del_timer(&bond->arp_timer);
-                if (arp_target_hw_addr != NULL) {
-			kfree(arp_target_hw_addr); 
-			arp_target_hw_addr = NULL;
-		}
-	}
-
-	/* Release the bonded slaves */
-	bond_release_all(master);
-	bond_mc_list_destroy (bond);
-
-	write_unlock_irqrestore(&bond->lock, flags);
-
-	MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-/* 
- * flush all members of flush->mc_list from device dev->mc_list
- */
-static void bond_mc_list_flush(struct net_device *dev, struct net_device *flush)
-{ 
-	struct dev_mc_list *dmi; 
- 
-	for (dmi = flush->mc_list; dmi != NULL; dmi = dmi->next) 
-		dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-}
-
-/*
- * Totally destroys the mc_list in bond
- */
-static void bond_mc_list_destroy(struct bonding *bond)
-{
-	struct dev_mc_list *dmi;
-
-	dmi = bond->mc_list; 
-	while (dmi) { 
-		bond->mc_list = dmi->next; 
-		kfree(dmi); 
-		dmi = bond->mc_list; 
-	}
-}
-
-/*
- * Add a Multicast address to every slave in the bonding group
- */
-static void bond_mc_add(bonding_t *bond, void *addr, int alen)
-{ 
-	slave_t *slave;
-	switch (multicast_mode) {
-	case BOND_MULTICAST_ACTIVE :
-		/* write lock already acquired */
-		if (bond->current_slave != NULL)
-			dev_mc_add(bond->current_slave->dev, addr, alen, 0);
-		break;
-	case BOND_MULTICAST_ALL :
-		for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev)
-			dev_mc_add(slave->dev, addr, alen, 0);
-		break;
-	case BOND_MULTICAST_DISABLED :
-		break;
-	}
-} 
-
-/*
- * Remove a multicast address from every slave in the bonding group
- */
-static void bond_mc_delete(bonding_t *bond, void *addr, int alen)
-{ 
-	slave_t *slave; 
-	switch (multicast_mode) {
-	case BOND_MULTICAST_ACTIVE :
-		/* write lock already acquired */
-		if (bond->current_slave != NULL)
-			dev_mc_delete(bond->current_slave->dev, addr, alen, 0);
-		break;
-	case BOND_MULTICAST_ALL :
-		for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev)
-			dev_mc_delete(slave->dev, addr, alen, 0);
-		break;
-	case BOND_MULTICAST_DISABLED :
-		break;
-	}
-} 
-
-/*
- * Copy all the Multicast addresses from src to the bonding device dst
- */
-static int bond_mc_list_copy (struct dev_mc_list *src, struct bonding *dst,
- int gpf_flag)
-{
-	struct dev_mc_list *dmi, *new_dmi;
-
-   	for (dmi = src; dmi != NULL; dmi = dmi->next) { 
-		new_dmi = kmalloc(sizeof(struct dev_mc_list), gpf_flag);
-
-		if (new_dmi == NULL) {
-			return -ENOMEM; 
-		}
-
-		new_dmi->next = dst->mc_list; 
-		dst->mc_list = new_dmi;
-
-		new_dmi->dmi_addrlen = dmi->dmi_addrlen; 
-		memcpy(new_dmi->dmi_addr, dmi->dmi_addr, dmi->dmi_addrlen); 
-		new_dmi->dmi_users = dmi->dmi_users;
-		new_dmi->dmi_gusers = dmi->dmi_gusers; 
-	} 
-	return 0;
-}
-
-/*
- * Returns 0 if dmi1 and dmi2 are the same, non-0 otherwise
- */
-static inline int dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list *dmi2)
-{ 
-	return memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0 &&
-	 dmi1->dmi_addrlen == dmi2->dmi_addrlen;
-} 
-
-/*
- * Push the promiscuity flag down to all slaves
- */
-static void bond_set_promiscuity(bonding_t *bond, int inc)
-{ 
-	slave_t *slave; 
-	switch (multicast_mode) {
-	case BOND_MULTICAST_ACTIVE :
-		/* write lock already acquired */
-		if (bond->current_slave != NULL)
-			dev_set_promiscuity(bond->current_slave->dev, inc);
-		break;
-	case BOND_MULTICAST_ALL :
-		for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev)
-			dev_set_promiscuity(slave->dev, inc);
-		break;
-	case BOND_MULTICAST_DISABLED :
-		break;
-	}
-} 
-
-/*
- * Push the allmulti flag down to all slaves
- */
-static void bond_set_allmulti(bonding_t *bond, int inc)
-{ 
-	slave_t *slave; 
-	switch (multicast_mode) {
-	case BOND_MULTICAST_ACTIVE : 
-		/* write lock already acquired */
-		if (bond->current_slave != NULL)
-			dev_set_allmulti(bond->current_slave->dev, inc);
-		break;
-	case BOND_MULTICAST_ALL :
-		for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev)
-			dev_set_allmulti(slave->dev, inc);
-		break;
-	case BOND_MULTICAST_DISABLED :
-		break;
-	}
-} 
-
-/* 
- * returns dmi entry if found, NULL otherwise 
- */
-static struct dev_mc_list* bond_mc_list_find_dmi(struct dev_mc_list *dmi,
- struct dev_mc_list *mc_list)
-{ 
-	struct dev_mc_list *idmi;
-
-	for (idmi = mc_list; idmi != NULL; idmi = idmi->next) {
-		if (dmi_same(dmi, idmi)) {
-			return idmi; 
-		}
-	}
-	return NULL;
-} 
-
-static void set_multicast_list(struct net_device *master)
-{
-	bonding_t *bond = master->priv;
-	struct dev_mc_list *dmi;
-	unsigned long flags = 0;
-
-	if (multicast_mode == BOND_MULTICAST_DISABLED)
-		return;
-	/*
-	 * Lock the private data for the master
-	 */
-	write_lock_irqsave(&bond->lock, flags);
-
-	/* set promiscuity flag to slaves */
-	if ( (master->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC) )
-		bond_set_promiscuity(bond, 1); 
-
-	if ( !(master->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC) ) 
-		bond_set_promiscuity(bond, -1); 
-
-	/* set allmulti flag to slaves */ 
-	if ( (master->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI) ) 
-		bond_set_allmulti(bond, 1); 
-
-	if ( !(master->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI) )
-		bond_set_allmulti(bond, -1); 
-
-	bond->flags = master->flags; 
-
-	/* looking for addresses to add to slaves' mc list */ 
-	for (dmi = master->mc_list; dmi != NULL; dmi = dmi->next) { 
-		if (bond_mc_list_find_dmi(dmi, bond->mc_list) == NULL) 
-		 bond_mc_add(bond, dmi->dmi_addr, dmi->dmi_addrlen); 
-	} 
-
-	/* looking for addresses to delete from slaves' list */ 
-	for (dmi = bond->mc_list; dmi != NULL; dmi = dmi->next) { 
-		if (bond_mc_list_find_dmi(dmi, master->mc_list) == NULL) 
-		 bond_mc_delete(bond, dmi->dmi_addr, dmi->dmi_addrlen); 
-	}
-
-
-	/* save master's multicast list */ 
-	bond_mc_list_destroy (bond);
-	bond_mc_list_copy (master->mc_list, bond, GFP_ATOMIC);
-
-	write_unlock_irqrestore(&bond->lock, flags);
-}
-
-/*
- * Update the mc list and multicast-related flags for the new and 
- * old active slaves (if any) according to the multicast mode
- */
-static void bond_mc_update(bonding_t *bond, slave_t *new, slave_t *old)
-{
-	struct dev_mc_list *dmi;
-
-	switch(multicast_mode) {
-	case BOND_MULTICAST_ACTIVE :		
-		if (bond->device->flags & IFF_PROMISC) {
-			if (old != NULL && new != old)
-				dev_set_promiscuity(old->dev, -1);
-			dev_set_promiscuity(new->dev, 1);
-		}
-		if (bond->device->flags & IFF_ALLMULTI) {
-			if (old != NULL && new != old)
-				dev_set_allmulti(old->dev, -1);
-			dev_set_allmulti(new->dev, 1);
-		}
-		/* first remove all mc addresses from old slave if any,
-		   and _then_ add them to new active slave */
-		if (old != NULL && new != old) {
-			for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next)
-				dev_mc_delete(old->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-		}
-		for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next)
-			dev_mc_add(new->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-		break;
-	case BOND_MULTICAST_ALL :
-		/* nothing to do: mc list is already up-to-date on all slaves */
-		break;
-	case BOND_MULTICAST_DISABLED :
-		break;
-	}
-}
-
-/* enslave device <slave> to bond device <master> */
-static int bond_enslave(struct net_device *master_dev, 
-                        struct net_device *slave_dev)
-{
-	bonding_t *bond = NULL;
-	slave_t *new_slave = NULL;
-	unsigned long flags = 0;
-	unsigned long rflags = 0;
-	int ndx = 0;
-	int err = 0;
-	struct dev_mc_list *dmi;
-	struct in_ifaddr **ifap;
-	struct in_ifaddr *ifa;
-	int link_reporting;
-
-	if (master_dev == NULL || slave_dev == NULL) {
-		return -ENODEV;
-	}
-	bond = (struct bonding *) master_dev->priv;
-
-	if (slave_dev->do_ioctl == NULL) {
-		printk(KERN_DEBUG
-			"Warning : no link monitoring support for %s\n",
-			slave_dev->name);
-	}
-
-	/* not running. */
-	if ((slave_dev->flags & IFF_UP) != IFF_UP) {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "Error, slave_dev is not running\n");
-#endif
-		return -EINVAL;
-	}
-
-	/* already enslaved */
-	if (master_dev->flags & IFF_SLAVE || slave_dev->flags & IFF_SLAVE) {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "Error, Device was already enslaved\n");
-#endif
-		return -EBUSY;
-	}
-		   
-	if ((new_slave = kmalloc(sizeof(slave_t), GFP_ATOMIC)) == NULL) {
-		return -ENOMEM;
-	}
-	memset(new_slave, 0, sizeof(slave_t));
-
-	/* save flags before call to netdev_set_master */
-	new_slave->original_flags = slave_dev->flags;
-	err = netdev_set_master(slave_dev, master_dev);
-
-	if (err) {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "Error %d calling netdev_set_master\n", err);
-#endif
-		goto err_free;
-	}
-
-	new_slave->dev = slave_dev;
-
-	if (multicast_mode == BOND_MULTICAST_ALL) {
-		/* set promiscuity level to new slave */ 
-		if (master_dev->flags & IFF_PROMISC)
-			dev_set_promiscuity(slave_dev, 1); 
- 
-		/* set allmulti level to new slave */
-		if (master_dev->flags & IFF_ALLMULTI) 
-			dev_set_allmulti(slave_dev, 1); 
-		
-		/* upload master's mc_list to new slave */ 
-		for (dmi = master_dev->mc_list; dmi != NULL; dmi = dmi->next) 
-			dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-	}
-
-	write_lock_irqsave(&bond->lock, flags);
-	
-	bond_attach_slave(bond, new_slave);
-	new_slave->delay = 0;
-	new_slave->link_failure_count = 0;
-
-	if (miimon > 0 && !use_carrier) {
-		link_reporting = bond_check_dev_link(slave_dev, 1);
-
-		if ((link_reporting == -1) && (arp_interval == 0)) {
-			/*
-			 * miimon is set but a bonded network driver
-			 * does not support ETHTOOL/MII and
-			 * arp_interval is not set.  Note: if
-			 * use_carrier is enabled, we will never go
-			 * here (because netif_carrier is always
-			 * supported); thus, we don't need to change
-			 * the messages for netif_carrier.
-			 */ 
-			printk(KERN_ERR
-				"bond_enslave(): MII and ETHTOOL support not "
-				"available for interface %s, and "
-				"arp_interval/arp_ip_target module parameters "
-		       		"not specified, thus bonding will not detect "
-				"link failures! see bonding.txt for details.\n",
-		       		slave_dev->name);
-		} else if (link_reporting == -1) {
-			/* unable  get link status using mii/ethtool */
-			printk(KERN_WARNING 
-			       "bond_enslave: can't get link status from "
-			       "interface %s; the network driver associated "
-			       "with this interface does not support "
-			       "MII or ETHTOOL link status reporting, thus "
-			       "miimon has no effect on this interface.\n", 
-			       slave_dev->name);
-		}
-	}
-
-	/* check for initial state */
-	if ((miimon <= 0) ||
-	    (bond_check_dev_link(slave_dev, 0) == BMSR_LSTATUS)) {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "Initial state of slave_dev is BOND_LINK_UP\n");
-#endif
-		new_slave->link  = BOND_LINK_UP;
-		new_slave->jiffies = jiffies;
-	}
-	else {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "Initial state of slave_dev is BOND_LINK_DOWN\n");
-#endif
-		new_slave->link  = BOND_LINK_DOWN;
-	}
-
-	/* if we're in active-backup mode, we need one and only one active
-	 * interface. The backup interfaces will have their NOARP flag set
-	 * because we need them to be completely deaf and not to respond to
-	 * any ARP request on the network to avoid fooling a switch. Thus,
-	 * since we guarantee that current_slave always point to the last
-	 * usable interface, we just have to verify this interface's flag.
-	 */
-	if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
-		if (((bond->current_slave == NULL)
-			|| (bond->current_slave->dev->flags & IFF_NOARP))
-			&& (new_slave->link == BOND_LINK_UP)) {
-#ifdef BONDING_DEBUG
-			printk(KERN_CRIT "This is the first active slave\n");
-#endif
-			/* first slave or no active slave yet, and this link
-			   is OK, so make this interface the active one */
-			bond->current_slave = new_slave;
-			bond_set_slave_active_flags(new_slave);
-			bond_mc_update(bond, new_slave, NULL);
-		}
-		else {
-#ifdef BONDING_DEBUG
-			printk(KERN_CRIT "This is just a backup slave\n");
-#endif
-			bond_set_slave_inactive_flags(new_slave);
-		}
-		read_lock_irqsave(&(((struct in_device *)slave_dev->ip_ptr)->lock), rflags);
-		ifap= &(((struct in_device *)slave_dev->ip_ptr)->ifa_list);
-		ifa = *ifap;
-		my_ip = ifa->ifa_address;
-		read_unlock_irqrestore(&(((struct in_device *)slave_dev->ip_ptr)->lock), rflags);
-
-		/* if there is a primary slave, remember it */
-		if (primary != NULL)
-		  if( strcmp(primary, new_slave->dev->name) == 0) 
-			bond->primary_slave = new_slave;
-	} else {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "This slave is always active in trunk mode\n");
-#endif
-		/* always active in trunk mode */
-		new_slave->state = BOND_STATE_ACTIVE;
-		if (bond->current_slave == NULL) 
-			bond->current_slave = new_slave;
-	}
-
-	write_unlock_irqrestore(&bond->lock, flags);
-
-	/*
-	 * !!! This is to support old versions of ifenslave.  We can remove
-	 * this in 2.5 because our ifenslave takes care of this for us.
-	 * We check to see if the master has a mac address yet.  If not,
-	 * we'll give it the mac address of our slave device.
-	 */
-	for (ndx = 0; ndx < slave_dev->addr_len; ndx++) {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "Checking ndx=%d of master_dev->dev_addr\n",
-		       ndx);
-#endif
-		if (master_dev->dev_addr[ndx] != 0) {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "Found non-zero byte at ndx=%d\n",
-		       ndx);
-#endif
-			break;
-		}
-	}
-	if (ndx == slave_dev->addr_len) {
-		/*
-		 * We got all the way through the address and it was
-		 * all 0's.
-		 */
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "%s doesn't have a MAC address yet.  ",
-		       master_dev->name);
-		printk(KERN_CRIT "Going to give assign it from %s.\n",
-		       slave_dev->name);
-#endif
-		bond_sethwaddr(master_dev, slave_dev);
-	}
-
-	printk (KERN_INFO "%s: enslaving %s as a%s interface with a%s link.\n",
-		master_dev->name, slave_dev->name,
-		new_slave->state == BOND_STATE_ACTIVE ? "n active" : " backup",
-		new_slave->link == BOND_LINK_UP ? "n up" : " down");
-
-	/* enslave is successful */
-	return 0;
-err_free:
-	kfree(new_slave);
-	return err;
-}
-
-/* 
- * This function changes the active slave to slave <slave_dev>.
- * It returns -EINVAL in the following cases.
- *  - <slave_dev> is not found in the list.
- *  - There is not active slave now.
- *  - <slave_dev> is already active.
- *  - The link state of <slave_dev> is not BOND_LINK_UP.
- *  - <slave_dev> is not running.
- * In these cases, this fuction does nothing.
- * In the other cases, currnt_slave pointer is changed and 0 is returned.
- */
-static int bond_change_active(struct net_device *master_dev, struct net_device *slave_dev)
-{
-	bonding_t *bond;
-	slave_t *slave;
-	slave_t *oldactive = NULL;
-	slave_t *newactive = NULL;
-	unsigned long flags;
-	int ret = 0;
-
-	if (master_dev == NULL || slave_dev == NULL) {
-		return -ENODEV;
-	}
-
-	bond = (struct bonding *) master_dev->priv;
-	write_lock_irqsave(&bond->lock, flags);
-	slave = (slave_t *)bond;
-	oldactive = bond->current_slave;
-
-	while ((slave = slave->prev) != (slave_t *)bond) {
-		if(slave_dev == slave->dev) {
-			newactive = slave;
-			break;
-		}
-	}
-
-	if ((newactive != NULL)&&
-	    (oldactive != NULL)&&
-	    (newactive != oldactive)&&
-	    (newactive->link == BOND_LINK_UP)&&
-	    IS_UP(newactive->dev)) {
-		bond_set_slave_inactive_flags(oldactive);
-		bond_set_slave_active_flags(newactive);
-		bond_mc_update(bond, newactive, oldactive);
-		bond->current_slave = newactive;
-		printk("%s : activate %s(old : %s)\n",
-			master_dev->name, newactive->dev->name, 
-			oldactive->dev->name);
-	}
-	else {
-		ret = -EINVAL;
-	}
-	write_unlock_irqrestore(&bond->lock, flags);
-	return ret;
-}
-
-/* Choose a new valid interface from the pool, set it active
- * and make it the current slave. If no valid interface is
- * found, the oldest slave in BACK state is choosen and
- * activated. If none is found, it's considered as no
- * interfaces left so the current slave is set to NULL.
- * The result is a pointer to the current slave.
- *
- * Since this function sends messages tails through printk, the caller
- * must have started something like `printk(KERN_INFO "xxxx ");'.
- *
- * Warning: must put locks around the call to this function if needed.
- */
-slave_t *change_active_interface(bonding_t *bond)
-{
-	slave_t *newslave, *oldslave;
-	slave_t *bestslave = NULL;
-	int mintime;
-
-	read_lock(&bond->ptrlock);
-	newslave = oldslave = bond->current_slave;
-	read_unlock(&bond->ptrlock);
-
-	if (newslave == NULL) { /* there were no active slaves left */
-		if (bond->next != (slave_t *)bond) {  /* found one slave */
-			write_lock(&bond->ptrlock);
-			newslave = bond->current_slave = bond->next;
-			write_unlock(&bond->ptrlock);
-		} else {
-
-			printk (" but could not find any %s interface.\n",
-				(bond_mode == BOND_MODE_ACTIVEBACKUP) ? "backup":"other");
-			write_lock(&bond->ptrlock);
-			bond->current_slave = (slave_t *)NULL;
-			write_unlock(&bond->ptrlock);
-			return NULL; /* still no slave, return NULL */
-		}
-	} else if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
-		/* make sure oldslave doesn't send arps - this could
-		 * cause a ping-pong effect between interfaces since they
-		 * would be able to tx arps - in active backup only one
-		 * slave should be able to tx arps, and that should be
-		 * the current_slave; the only exception is when all
-		 * slaves have gone down, then only one non-current slave can
-		 * send arps at a time; clearing oldslaves' mc list is handled
-		 * later in this function.
-		 */
-		bond_set_slave_inactive_flags(oldslave);
-	}
-
-	mintime = updelay;
-
-	/* first try the primary link; if arping, a link must tx/rx traffic 
-	 * before it can be considered the current_slave - also, we would skip 
-	 * slaves between the current_slave and primary_slave that may be up 
-	 * and able to arp
-	 */
-	if ((bond->primary_slave != NULL) && (arp_interval == 0)) {
-		if (IS_UP(bond->primary_slave->dev)) 
-			newslave = bond->primary_slave;
-	}
-
-	do {
-		if (IS_UP(newslave->dev)) {
-			if (newslave->link == BOND_LINK_UP) {
-				/* this one is immediately usable */
-				if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
-					bond_set_slave_active_flags(newslave);
-					bond_mc_update(bond, newslave, oldslave);
-					printk (" and making interface %s the active one.\n",
-						newslave->dev->name);
-				}
-				else {
-					printk (" and setting pointer to interface %s.\n",
-						newslave->dev->name);
-				}
-
-				write_lock(&bond->ptrlock);
-				bond->current_slave = newslave;
-				write_unlock(&bond->ptrlock);
-				return newslave;
-			}
-			else if (newslave->link == BOND_LINK_BACK) {
-				/* link up, but waiting for stabilization */
-				if (newslave->delay < mintime) {
-					mintime = newslave->delay;
-					bestslave = newslave;
-				}
-			}
-		}
-	} while ((newslave = newslave->next) != oldslave);
-
-	/* no usable backup found, we'll see if we at least got a link that was
-	   coming back for a long time, and could possibly already be usable.
-	*/
-
-	if (bestslave != NULL) {
-		/* early take-over. */
-		printk (" and making interface %s the active one %d ms earlier.\n",
-			bestslave->dev->name,
-			(updelay - bestslave->delay)*miimon);
-
-		bestslave->delay = 0;
-		bestslave->link = BOND_LINK_UP;
-		bestslave->jiffies = jiffies;
-		bond_set_slave_active_flags(bestslave);
-		bond_mc_update(bond, bestslave, oldslave);
-		write_lock(&bond->ptrlock);
-		bond->current_slave = bestslave;
-		write_unlock(&bond->ptrlock);
-		return bestslave;
-	}
-
-	if ((bond_mode == BOND_MODE_ACTIVEBACKUP) &&
-	    (multicast_mode == BOND_MULTICAST_ACTIVE) &&
-	    (oldslave != NULL)) {
-		/* flush bonds (master's) mc_list from oldslave since it wasn't
-		 * updated (and deleted) above
-		 */ 
-		bond_mc_list_flush(oldslave->dev, bond->device); 
-		if (bond->device->flags & IFF_PROMISC) {
-			dev_set_promiscuity(oldslave->dev, -1);
-		}
-		if (bond->device->flags & IFF_ALLMULTI) {
-			dev_set_allmulti(oldslave->dev, -1);
-		}
-	}
-
-	printk (" but could not find any %s interface.\n",
-		(bond_mode == BOND_MODE_ACTIVEBACKUP) ? "backup":"other");
-	
-	/* absolutely nothing found. let's return NULL */
-	write_lock(&bond->ptrlock);
-	bond->current_slave = (slave_t *)NULL;
-	write_unlock(&bond->ptrlock);
-	return NULL;
-}
-
-/*
- * Try to release the slave device <slave> from the bond device <master>
- * It is legal to access current_slave without a lock because all the function
- * is write-locked.
- *
- * The rules for slave state should be:
- *   for Active/Backup:
- *     Active stays on all backups go down
- *   for Bonded connections:
- *     The first up interface should be left on and all others downed.
- */
-static int bond_release(struct net_device *master, struct net_device *slave)
-{
-	bonding_t *bond;
-	slave_t *our_slave, *old_current;
-	unsigned long flags;
-	
-	if (master == NULL || slave == NULL)  {
-		return -ENODEV;
-	}
-
-	bond = (struct bonding *) master->priv;
-
-	/* master already enslaved, or slave not enslaved,
-	   or no slave for this master */
-	if ((master->flags & IFF_SLAVE) || !(slave->flags & IFF_SLAVE)) {
-		printk (KERN_DEBUG "%s: cannot release %s.\n", master->name, slave->name);
-		return -EINVAL;
-	}
-
-	write_lock_irqsave(&bond->lock, flags);
-	bond->current_arp_slave = NULL;
-	our_slave = (slave_t *)bond;
-	old_current = bond->current_slave;
-	while ((our_slave = our_slave->prev) != (slave_t *)bond) {
-		if (our_slave->dev == slave) {
-			bond_detach_slave(bond, our_slave);
-
-			printk (KERN_INFO "%s: releasing %s interface %s",
-				master->name,
-				(our_slave->state == BOND_STATE_ACTIVE) ? "active" : "backup",
-				slave->name);
-
-			if (our_slave == old_current) {
-				/* find a new interface and be verbose */
-				change_active_interface(bond); 
-			} else {
-				printk(".\n");
-			}
-			
-			if (bond->current_slave == NULL) {
-				printk(KERN_INFO
-					"%s: now running without any active interface !\n",
-					master->name);
-			}
-
-			if (bond->primary_slave == our_slave) {
-				bond->primary_slave = NULL;
-			}
-
-			break;
-		}
-
-	}
-	write_unlock_irqrestore(&bond->lock, flags);
-	
-	if (our_slave == (slave_t *)bond) {
-		/* if we get here, it's because the device was not found */
-		printk (KERN_INFO "%s: %s not enslaved\n", master->name, slave->name);
-		return -EINVAL;
-	}
-
-	/* undo settings and restore original values */
-	
-	if (multicast_mode == BOND_MULTICAST_ALL) {
-		/* flush master's mc_list from slave */ 
-		bond_mc_list_flush (slave, master); 
-
-		/* unset promiscuity level from slave */
-		if (master->flags & IFF_PROMISC) 
-			dev_set_promiscuity(slave, -1); 
-
-		/* unset allmulti level from slave */ 
-		if (master->flags & IFF_ALLMULTI)
-			dev_set_allmulti(slave, -1); 
-	}
-
-	netdev_set_master(slave, NULL);
-
-	/* only restore its RUNNING flag if monitoring set it down */
-	if (slave->flags & IFF_UP) {
-		slave->flags |= IFF_RUNNING;
-	}
-
-	if (slave->flags & IFF_NOARP || 
-		bond->current_slave != NULL) {
-			dev_close(slave);
-			our_slave->original_flags &= ~IFF_UP;
-	}
-
-	bond_restore_slave_flags(our_slave);
-	
-	kfree(our_slave);
-
-	return 0;  /* deletion OK */
-}
-
-/* 
- * This function releases all slaves.
- * Warning: must put write-locks around the call to this function.
- */
-static int bond_release_all(struct net_device *master)
-{
-	bonding_t *bond;
-	slave_t *our_slave;
-	struct net_device *slave_dev;
-
-	if (master == NULL)  {
-		return -ENODEV;
-	}
-
-	if (master->flags & IFF_SLAVE) {
-		return -EINVAL;
-	}
-
-	bond = (struct bonding *) master->priv;
-	bond->current_arp_slave = NULL;
-	bond->current_slave = NULL;
-	bond->primary_slave = NULL;
-
-	while ((our_slave = bond->prev) != (slave_t *)bond) {
-		slave_dev = our_slave->dev;
-		bond_detach_slave(bond, our_slave);
-
-		if (multicast_mode == BOND_MULTICAST_ALL 
-		    || (multicast_mode == BOND_MULTICAST_ACTIVE 
-			&& bond->current_slave == our_slave)) {
-
-			/* flush master's mc_list from slave */ 
-			bond_mc_list_flush (slave_dev, master); 
-			
-			/* unset promiscuity level from slave */
-			if (master->flags & IFF_PROMISC) 
-				dev_set_promiscuity(slave_dev, -1); 
-			
-			/* unset allmulti level from slave */ 
-			if (master->flags & IFF_ALLMULTI)
-				dev_set_allmulti(slave_dev, -1); 
-		}
-
-		kfree(our_slave);
-
-		/*
-		 * Can be safely called from inside the bond lock
-		 * since traffic and timers have already stopped
-		 */
-		netdev_set_master(slave_dev, NULL);
-
-		/* only restore its RUNNING flag if monitoring set it down */
-		if (slave_dev->flags & IFF_UP)
-			slave_dev->flags |= IFF_RUNNING;
-
-		if (slave_dev->flags & IFF_NOARP)
-			dev_close(slave_dev);
-	}
-
-	printk (KERN_INFO "%s: released all slaves\n", master->name);
-
-	return 0;
-}
-
-/* this function is called regularly to monitor each slave's link. */
-static void bond_mii_monitor(struct net_device *master)
-{
-	bonding_t *bond = (struct bonding *) master->priv;
-	slave_t *slave, *bestslave, *oldcurrent;
-	unsigned long flags;
-	int slave_died = 0;
-
-	read_lock_irqsave(&bond->lock, flags);
-
-	/* we will try to read the link status of each of our slaves, and
-	 * set their IFF_RUNNING flag appropriately. For each slave not
-	 * supporting MII status, we won't do anything so that a user-space
-	 * program could monitor the link itself if needed.
-	 */
-
-	bestslave = NULL;
-	slave = (slave_t *)bond;
-
-	read_lock(&bond->ptrlock);
-	oldcurrent = bond->current_slave;
-	read_unlock(&bond->ptrlock);
-
-	while ((slave = slave->prev) != (slave_t *)bond) {
-		/* use updelay+1 to match an UP slave even when updelay is 0 */
-		int mindelay = updelay + 1;
-		struct net_device *dev = slave->dev;
-		int link_state;
-		
-		link_state = bond_check_dev_link(dev, 0);
-
-		switch (slave->link) {
-		case BOND_LINK_UP:	/* the link was up */
-			if (link_state == BMSR_LSTATUS) {
-				/* link stays up, tell that this one
-				   is immediately available */
-				if (IS_UP(dev) && (mindelay > -2)) {
-					/* -2 is the best case :
-					   this slave was already up */
-					mindelay = -2;
-					bestslave = slave;
-				}
-				break;
-			}
-			else { /* link going down */
-				slave->link  = BOND_LINK_FAIL;
-				slave->delay = downdelay;
-				if (slave->link_failure_count < UINT_MAX) {
-					slave->link_failure_count++;
-				}
-				if (downdelay > 0) {
-					printk (KERN_INFO
-						"%s: link status down for %sinterface "
-						"%s, disabling it in %d ms.\n",
-						master->name,
-						IS_UP(dev)
-						? ((bond_mode == BOND_MODE_ACTIVEBACKUP)
-						   ? ((slave == oldcurrent)
-						      ? "active " : "backup ")
-						   : "")
-						: "idle ",
-						dev->name,
-						downdelay * miimon);
-					}
-			}
-			/* no break ! fall through the BOND_LINK_FAIL test to
-			   ensure proper action to be taken
-			*/
-		case BOND_LINK_FAIL:	/* the link has just gone down */
-			if (link_state != BMSR_LSTATUS) {
-				/* link stays down */
-				if (slave->delay <= 0) {
-					/* link down for too long time */
-					slave->link = BOND_LINK_DOWN;
-					/* in active/backup mode, we must
-					   completely disable this interface */
-					if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
-						bond_set_slave_inactive_flags(slave);
-					}
-					printk(KERN_INFO
-						"%s: link status definitely down "
-						"for interface %s, disabling it",
-						master->name,
-						dev->name);
-
-					read_lock(&bond->ptrlock);
-					if (slave == bond->current_slave) {
-						read_unlock(&bond->ptrlock);
-						/* find a new interface and be verbose */
-						change_active_interface(bond);
-					} else {
-						read_unlock(&bond->ptrlock);
-						printk(".\n");
-					}
-					slave_died = 1;
-				} else {
-					slave->delay--;
-				}
-			} else {
-				/* link up again */
-				slave->link  = BOND_LINK_UP;
-				slave->jiffies = jiffies;
-				printk(KERN_INFO
-					"%s: link status up again after %d ms "
-					"for interface %s.\n",
-					master->name,
-					(downdelay - slave->delay) * miimon,
-					dev->name);
-
-				if (IS_UP(dev) && (mindelay > -1)) {
-					/* -1 is a good case : this slave went
-					   down only for a short time */
-					mindelay = -1;
-					bestslave = slave;
-				}
-			}
-			break;
-		case BOND_LINK_DOWN:	/* the link was down */
-			if (link_state != BMSR_LSTATUS) {
-				/* the link stays down, nothing more to do */
-				break;
-			} else {	/* link going up */
-				slave->link  = BOND_LINK_BACK;
-				slave->delay = updelay;
-				
-				if (updelay > 0) {
-					/* if updelay == 0, no need to
-					   advertise about a 0 ms delay */
-					printk (KERN_INFO
-						"%s: link status up for interface"
-						" %s, enabling it in %d ms.\n",
-						master->name,
-						dev->name,
-						updelay * miimon);
-				}
-			}
-			/* no break ! fall through the BOND_LINK_BACK state in
-			   case there's something to do.
-			*/
-		case BOND_LINK_BACK:	/* the link has just come back */
-			if (link_state != BMSR_LSTATUS) {
-				/* link down again */
-				slave->link  = BOND_LINK_DOWN;
-				printk(KERN_INFO
-					"%s: link status down again after %d ms "
-					"for interface %s.\n",
-					master->name,
-					(updelay - slave->delay) * miimon,
-					dev->name);
-			} else {
-				/* link stays up */
-				if (slave->delay == 0) {
-					/* now the link has been up for long time enough */
-					slave->link = BOND_LINK_UP;
-					slave->jiffies = jiffies;
-
-					if (bond_mode != BOND_MODE_ACTIVEBACKUP) {
-						/* make it immediately active */
-						slave->state = BOND_STATE_ACTIVE;
-					} else if (slave != bond->primary_slave) {
-						/* prevent it from being the active one */
-						slave->state = BOND_STATE_BACKUP;
-					}
-
-					printk(KERN_INFO
-						"%s: link status definitely up "
-						"for interface %s.\n",
-						master->name,
-						dev->name);
-	
-					if ( (bond->primary_slave != NULL)	 
-					  && (slave == bond->primary_slave) )
-						change_active_interface(bond); 
-				}
-				else
-					slave->delay--;
-				
-				/* we'll also look for the mostly eligible slave */
-				if (bond->primary_slave == NULL)  {
-				    if (IS_UP(dev) && (slave->delay < mindelay)) {
-					mindelay = slave->delay;
-					bestslave = slave;
-				    } 
-				} else if ( (IS_UP(bond->primary_slave->dev))  || 
-				          ( (!IS_UP(bond->primary_slave->dev))  && 
-				          (IS_UP(dev) && (slave->delay < mindelay)) ) ) {
-					mindelay = slave->delay;
-					bestslave = slave;
-				}
-			}
-			break;
-		} /* end of switch */
-	} /* end of while */
-
-	/* 
-	 * if there's no active interface and we discovered that one
-	 * of the slaves could be activated earlier, so we do it.
-	 */
-	read_lock(&bond->ptrlock);
-	oldcurrent = bond->current_slave;
-	read_unlock(&bond->ptrlock);
-
-	/* no active interface at the moment or need to bring up the primary */
-	if (oldcurrent == NULL)  { /* no active interface at the moment */
-		if (bestslave != NULL) { /* last chance to find one ? */
-			if (bestslave->link == BOND_LINK_UP) {
-				printk (KERN_INFO
-					"%s: making interface %s the new active one.\n",
-					master->name, bestslave->dev->name);
-			} else {
-				printk (KERN_INFO
-					"%s: making interface %s the new "
-					"active one %d ms earlier.\n",
-					master->name, bestslave->dev->name,
-					(updelay - bestslave->delay) * miimon);
-
-				bestslave->delay = 0;
-				bestslave->link  = BOND_LINK_UP;
-				bestslave->jiffies = jiffies;
-			}
-
-			if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
-				bond_set_slave_active_flags(bestslave);
-				bond_mc_update(bond, bestslave, NULL);
-			} else {
-				bestslave->state = BOND_STATE_ACTIVE;
-			}
-			write_lock(&bond->ptrlock);
-			bond->current_slave = bestslave;
-			write_unlock(&bond->ptrlock);
-		} else if (slave_died) {
-			/* print this message only once a slave has just died */
-			printk(KERN_INFO
-				"%s: now running without any active interface !\n",
-				master->name);
-		}
-	}
-
-	read_unlock_irqrestore(&bond->lock, flags);
-	/* re-arm the timer */
-	mod_timer(&bond->mii_timer, jiffies + (miimon * HZ / 1000));
-}
-
-/* 
- * this function is called regularly to monitor each slave's link 
- * ensuring that traffic is being sent and received when arp monitoring
- * is used in load-balancing mode. if the adapter has been dormant, then an 
- * arp is transmitted to generate traffic. see activebackup_arp_monitor for 
- * arp monitoring in active backup mode. 
- */
-static void loadbalance_arp_monitor(struct net_device *master)
-{
-	bonding_t *bond;
-	unsigned long flags;
-	slave_t *slave;
-	int the_delta_in_ticks =  arp_interval * HZ / 1000;
-	int next_timer = jiffies + (arp_interval * HZ / 1000);
-
-	bond = (struct bonding *) master->priv; 
-	if (master->priv == NULL) {
-		mod_timer(&bond->arp_timer, next_timer);
-		return;
-	}
-
-	read_lock_irqsave(&bond->lock, flags);
-
-	/* TODO: investigate why rtnl_shlock_nowait and rtnl_exlock_nowait
-	 * are called below and add comment why they are required... 
-	 */
-	if ((!IS_UP(master)) || rtnl_shlock_nowait()) {
-		mod_timer(&bond->arp_timer, next_timer);
-		read_unlock_irqrestore(&bond->lock, flags);
-		return;
-	}
-
-	if (rtnl_exlock_nowait()) {
-		rtnl_shunlock();
-		mod_timer(&bond->arp_timer, next_timer);
-		read_unlock_irqrestore(&bond->lock, flags);
-		return;
-	}
-
-	/* see if any of the previous devices are up now (i.e. they have
-	 * xmt and rcv traffic). the current_slave does not come into
-	 * the picture unless it is null. also, slave->jiffies is not needed
-	 * here because we send an arp on each slave and give a slave as
-	 * long as it needs to get the tx/rx within the delta.
-	 * TODO: what about up/down delay in arp mode? it wasn't here before
-	 *       so it can wait 
-	 */
-	slave = (slave_t *)bond;
-	while ((slave = slave->prev) != (slave_t *)bond)  {
-
-	  	if (slave->link != BOND_LINK_UP) {
-
-	  		if (((jiffies - slave->dev->trans_start) <= 
-						the_delta_in_ticks) &&  
-			     ((jiffies - slave->dev->last_rx) <= 
-						the_delta_in_ticks)) {
-
-				slave->link  = BOND_LINK_UP;
-				slave->state = BOND_STATE_ACTIVE;
-
-				/* primary_slave has no meaning in round-robin
-				 * mode. the window of a slave being up and 
-				 * current_slave being null after enslaving
-				 * is closed.
-				 */
-				read_lock(&bond->ptrlock);
-				if (bond->current_slave == NULL) {
-					read_unlock(&bond->ptrlock);
-					printk(KERN_INFO
-						"%s: link status definitely up "
-						"for interface %s, ",
-						master->name,
-						slave->dev->name);
-					change_active_interface(bond); 
-				} else {
-					read_unlock(&bond->ptrlock);
-					printk(KERN_INFO
-						"%s: interface %s is now up\n",
-						master->name,
-						slave->dev->name);
-				}
-			} 
-		} else {
-			/* slave->link == BOND_LINK_UP */
-
-			/* not all switches will respond to an arp request
-			 * when the source ip is 0, so don't take the link down
-			 * if we don't know our ip yet
-			 */
-			if (((jiffies - slave->dev->trans_start) >= 
-		              (2*the_delta_in_ticks)) ||
-		             (((jiffies - slave->dev->last_rx) >= 
-		               (2*the_delta_in_ticks)) && my_ip !=0)) {
-				slave->link  = BOND_LINK_DOWN;
-				slave->state = BOND_STATE_BACKUP;
-				if (slave->link_failure_count < UINT_MAX) {
-					slave->link_failure_count++;
-				}
-				printk(KERN_INFO
-				       "%s: interface %s is now down.\n",
-				       master->name,
-				       slave->dev->name);
-
-				read_lock(&bond->ptrlock);
-				if (slave == bond->current_slave) {
-					read_unlock(&bond->ptrlock);
-					change_active_interface(bond);
-				} else {
-					read_unlock(&bond->ptrlock);
-				}
-			}
-		} 
-
-		/* note: if switch is in round-robin mode, all links 
-		 * must tx arp to ensure all links rx an arp - otherwise
-		 * links may oscillate or not come up at all; if switch is 
-		 * in something like xor mode, there is nothing we can 
-		 * do - all replies will be rx'ed on same link causing slaves 
-		 * to be unstable during low/no traffic periods
-		 */
-		if (IS_UP(slave->dev)) {
-			arp_send_all(slave);
-		}
-	}
-
-	rtnl_exunlock();
-	rtnl_shunlock();
-	read_unlock_irqrestore(&bond->lock, flags);
-
-	/* re-arm the timer */
-	mod_timer(&bond->arp_timer, next_timer);
-}
-
-/* 
- * When using arp monitoring in active-backup mode, this function is
- * called to determine if any backup slaves have went down or a new
- * current slave needs to be found.
- * The backup slaves never generate traffic, they are considered up by merely 
- * receiving traffic. If the current slave goes down, each backup slave will 
- * be given the opportunity to tx/rx an arp before being taken down - this 
- * prevents all slaves from being taken down due to the current slave not 
- * sending any traffic for the backups to receive. The arps are not necessarily
- * necessary, any tx and rx traffic will keep the current slave up. While any 
- * rx traffic will keep the backup slaves up, the current slave is responsible 
- * for generating traffic to keep them up regardless of any other traffic they 
- * may have received.
- * see loadbalance_arp_monitor for arp monitoring in load balancing mode
- */
-static void activebackup_arp_monitor(struct net_device *master)
-{
-	bonding_t *bond;
-	unsigned long flags;
-	slave_t *slave;
-	int the_delta_in_ticks =  arp_interval * HZ / 1000;
-	int next_timer = jiffies + (arp_interval * HZ / 1000);
-
-	bond = (struct bonding *) master->priv; 
-	if (master->priv == NULL) {
-		mod_timer(&bond->arp_timer, next_timer);
-		return;
-	}
-
-	read_lock_irqsave(&bond->lock, flags);
-
-	if (!IS_UP(master)) {
-		mod_timer(&bond->arp_timer, next_timer);
-	        read_unlock_irqrestore(&bond->lock, flags);
-		return;
-	}
-
-	/* determine if any slave has come up or any backup slave has 
-	 * gone down 
-	 * TODO: what about up/down delay in arp mode? it wasn't here before
-	 *       so it can wait 
-	 */
-	slave = (slave_t *)bond;
-	while ((slave = slave->prev) != (slave_t *)bond)  {
-
-	  	if (slave->link != BOND_LINK_UP) {
-			if ((jiffies - slave->dev->last_rx) <=
-			    the_delta_in_ticks) {
-
-				slave->link = BOND_LINK_UP;
-				write_lock(&bond->ptrlock);
-				if ((bond->current_slave == NULL) &&
-				    ((jiffies - slave->dev->trans_start) <=
-				     the_delta_in_ticks)) {
-					bond->current_slave = slave;
-					bond_set_slave_active_flags(slave);
-			                bond_mc_update(bond, slave, NULL);
-					bond->current_arp_slave = NULL;
-				} else if (bond->current_slave != slave) {
-					/* this slave has just come up but we 
-					 * already have a current slave; this
-					 * can also happen if bond_enslave adds
-					 * a new slave that is up while we are 
-					 * searching for a new slave
-					 */
-					bond_set_slave_inactive_flags(slave);
-					bond->current_arp_slave = NULL;
-				}
-
-				if (slave == bond->current_slave) {
-					printk(KERN_INFO
-						"%s: %s is up and now the "
-						"active interface\n",
-						master->name,
-						slave->dev->name);
-				} else {
-					printk(KERN_INFO
-						"%s: backup interface %s is "
-						"now up\n",
-						master->name,
-						slave->dev->name);
-				}
-
-				write_unlock(&bond->ptrlock);
-			}
-		} else {
-			read_lock(&bond->ptrlock);
-			if ((slave != bond->current_slave) &&
-			    (bond->current_arp_slave == NULL) &&
-			    (((jiffies - slave->dev->last_rx) >=
-			     3*the_delta_in_ticks) && (my_ip != 0))) {
-				/* a backup slave has gone down; three times 
-				 * the delta allows the current slave to be 
-				 * taken out before the backup slave.
-				 * note: a non-null current_arp_slave indicates
-				 * the current_slave went down and we are 
-				 * searching for a new one; under this 
-				 * condition we only take the current_slave 
-				 * down - this gives each slave a chance to 
-				 * tx/rx traffic before being taken out
-				 */
-				read_unlock(&bond->ptrlock);
-				slave->link  = BOND_LINK_DOWN;
-				if (slave->link_failure_count < UINT_MAX) {
-					slave->link_failure_count++;
-				}
-				bond_set_slave_inactive_flags(slave);
-				printk(KERN_INFO
-					"%s: backup interface %s is now down\n",
-					master->name,
-					slave->dev->name);
-			} else {
-				read_unlock(&bond->ptrlock);
-			}
-		}
-	}
-
-	read_lock(&bond->ptrlock);
-	slave = bond->current_slave;
-	read_unlock(&bond->ptrlock);
-
-	if (slave != NULL) {
-
-		/* if we have sent traffic in the past 2*arp_intervals but
-		 * haven't xmit and rx traffic in that time interval, select 
-		 * a different slave. slave->jiffies is only updated when
-		 * a slave first becomes the current_slave - not necessarily
-		 * after every arp; this ensures the slave has a full 2*delta 
-		 * before being taken out. if a primary is being used, check 
-		 * if it is up and needs to take over as the current_slave
-		 */
-		if ((((jiffies - slave->dev->trans_start) >= 
-		       (2*the_delta_in_ticks)) ||
-		     (((jiffies - slave->dev->last_rx) >= 
-		       (2*the_delta_in_ticks)) && (my_ip != 0))) &&
-		    ((jiffies - slave->jiffies) >= 2*the_delta_in_ticks)) {
-
-			slave->link  = BOND_LINK_DOWN;
-			if (slave->link_failure_count < UINT_MAX) {
-				slave->link_failure_count++;
-			}
-			printk(KERN_INFO "%s: link status down for "
-					 "active interface %s, disabling it",
-			       master->name,
-			       slave->dev->name);
-			slave = change_active_interface(bond);
-			bond->current_arp_slave = slave;
-			if (slave != NULL) {
-				slave->jiffies = jiffies;
-			}
-
-		} else if ((bond->primary_slave != NULL) && 
-			   (bond->primary_slave != slave) && 
-			   (bond->primary_slave->link == BOND_LINK_UP)) {
-			/* at this point, slave is the current_slave */
-			printk(KERN_INFO 
-			       "%s: changing from interface %s to primary "
-			       "interface %s\n",
-			       master->name, 
-			       slave->dev->name, 
-			       bond->primary_slave->dev->name);
-			       
-			/* primary is up so switch to it */
-			bond_set_slave_inactive_flags(slave);
-			bond_mc_update(bond, bond->primary_slave, slave);
-			write_lock(&bond->ptrlock);
-			bond->current_slave = bond->primary_slave;
-			write_unlock(&bond->ptrlock);
-			slave = bond->primary_slave;
-			bond_set_slave_active_flags(slave);
-			slave->jiffies = jiffies;
-		} else {
-			bond->current_arp_slave = NULL;
-		}
-
-		/* the current slave must tx an arp to ensure backup slaves
-		 * rx traffic
-		 */
-		if ((slave != NULL) &&
-		    (((jiffies - slave->dev->last_rx) >= the_delta_in_ticks) &&
-		     (my_ip != 0))) {
-		  arp_send_all(slave);
-		}
-	}
-
-	/* if we don't have a current_slave, search for the next available 
-	 * backup slave from the current_arp_slave and make it the candidate 
-	 * for becoming the current_slave
-	 */
-	if (slave == NULL) { 
-
-		if ((bond->current_arp_slave == NULL) ||
-		    (bond->current_arp_slave == (slave_t *)bond)) {
-			bond->current_arp_slave = bond->prev;
-		} 
-
-		if (bond->current_arp_slave != (slave_t *)bond) {
-			bond_set_slave_inactive_flags(bond->current_arp_slave);
-			slave = bond->current_arp_slave->next;
-
-			/* search for next candidate */
-			do {
-				if (IS_UP(slave->dev)) {
-					slave->link = BOND_LINK_BACK;
-					bond_set_slave_active_flags(slave);
-					arp_send_all(slave);
-					slave->jiffies = jiffies;
-					bond->current_arp_slave = slave;
-					break;
-				}
-
-				/* if the link state is up at this point, we 
-				 * mark it down - this can happen if we have 
-				 * simultaneous link failures and 
-				 * change_active_interface doesn't make this 
-				 * one the current slave so it is still marked 
-				 * up when it is actually down
-				 */
-				if (slave->link == BOND_LINK_UP) {
-					slave->link  = BOND_LINK_DOWN;
-					if (slave->link_failure_count < 
-							UINT_MAX) {
-						slave->link_failure_count++;
-					}
-
-					bond_set_slave_inactive_flags(slave);
-					printk(KERN_INFO
-						"%s: backup interface "
-						"%s is now down.\n",
-						master->name,
-						slave->dev->name);
-				}
-			} while ((slave = slave->next) != 
-					bond->current_arp_slave->next);
-		}
-	}
-
-	mod_timer(&bond->arp_timer, next_timer);
-	read_unlock_irqrestore(&bond->lock, flags);
-}
-
-typedef uint32_t in_addr_t;
-
-int
-my_inet_aton(char *cp, unsigned long *the_addr) {
-	static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
-	in_addr_t val;
-	char c;
-	union iaddr {
-	  uint8_t bytes[4];
-	  uint32_t word;
-	} res;
-	uint8_t *pp = res.bytes;
-	int digit,base;
-
-	res.word = 0;
-
-	c = *cp;
-	for (;;) {
-		/*
-		 * Collect number up to ``.''.
-		 * Values are specified as for C:
-		 * 0x=hex, 0=octal, isdigit=decimal.
-		 */
-		if (!isdigit(c)) goto ret_0;
-		val = 0; base = 10; digit = 0;
-		for (;;) {
-			if (isdigit(c)) {
-				val = (val * base) + (c - '0');
-				c = *++cp;
-				digit = 1;
-			} else {
-				break;
-			}
-		}
-		if (c == '.') {
-			/*
-			 * Internet format:
-			 *	a.b.c.d
-			 *	a.b.c	(with c treated as 16 bits)
-			 *	a.b	(with b treated as 24 bits)
-			 */
-			if (pp > res.bytes + 2 || val > 0xff) {
-				goto ret_0;
-			}
-			*pp++ = val;
-			c = *++cp;
-		} else
-			break;
-	}
-	/*
-	 * Check for trailing characters.
-	 */
-	if (c != '\0' && (!isascii(c) || !isspace(c))) {
-		goto ret_0;
-	}
-	/*
-	 * Did we get a valid digit?
-	 */
-	if (!digit) {
-		goto ret_0;
-	}
-
-	/* Check whether the last part is in its limits depending on
-	   the number of parts in total.  */
-	if (val > max[pp - res.bytes]) {
-		goto ret_0;
-	}
-
-	if (the_addr != NULL) {
-		*the_addr = res.word | htonl (val);
-	}
-
-	return (1);
-
-ret_0:
-	return (0);
-}
-
-static int bond_sethwaddr(struct net_device *master, struct net_device *slave)
-{
-#ifdef BONDING_DEBUG
-	printk(KERN_CRIT "bond_sethwaddr: master=%x\n", (unsigned int)master);
-	printk(KERN_CRIT "bond_sethwaddr: slave=%x\n", (unsigned int)slave);
-	printk(KERN_CRIT "bond_sethwaddr: slave->addr_len=%d\n", slave->addr_len);
-#endif
-	memcpy(master->dev_addr, slave->dev_addr, slave->addr_len);
-	return 0;
-}
-
-static int bond_info_query(struct net_device *master, struct ifbond *info)
-{
-	bonding_t *bond = (struct bonding *) master->priv;
-	slave_t *slave;
-	unsigned long flags;
-
-	info->bond_mode = bond_mode;
-	info->num_slaves = 0;
-	info->miimon = miimon;
-
-	read_lock_irqsave(&bond->lock, flags);
-	for (slave = bond->prev; slave != (slave_t *)bond; slave = slave->prev) {
-		info->num_slaves++;
-	}
-	read_unlock_irqrestore(&bond->lock, flags);
-
-	return 0;
-}
-
-static int bond_slave_info_query(struct net_device *master, 
-					struct ifslave *info)
-{
-	bonding_t *bond = (struct bonding *) master->priv;
-	slave_t *slave;
-	int cur_ndx = 0;
-	unsigned long flags;
-
-	if (info->slave_id < 0) {
-		return -ENODEV;
-	}
-
-	read_lock_irqsave(&bond->lock, flags);
-	for (slave = bond->prev; 
-		 slave != (slave_t *)bond && cur_ndx < info->slave_id; 
-		 slave = slave->prev) {
-		cur_ndx++;
-	}
-	read_unlock_irqrestore(&bond->lock, flags);
-
-	if (slave != (slave_t *)bond) {
-		strcpy(info->slave_name, slave->dev->name);
-		info->link = slave->link;
-		info->state = slave->state;
-		info->link_failure_count = slave->link_failure_count;
-	} else {
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static int bond_ioctl(struct net_device *master_dev, struct ifreq *ifr, int cmd)
-{
-	struct net_device *slave_dev = NULL;
-	struct ifbond *u_binfo = NULL, k_binfo;
-	struct ifslave *u_sinfo = NULL, k_sinfo;
-	struct mii_ioctl_data *mii = NULL;
-	int ret = 0;
-
-#ifdef BONDING_DEBUG
-	printk(KERN_INFO "bond_ioctl: master=%s, cmd=%d\n", 
-		master_dev->name, cmd);
-#endif
-
-	switch (cmd) {
-	case SIOCGMIIPHY:
-		mii = (struct mii_ioctl_data *)&ifr->ifr_data;
-		if (mii == NULL) {
-			return -EINVAL;
-		}
-		mii->phy_id = 0;
-		/* Fall Through */
-	case SIOCGMIIREG:
-		/* 
-		 * We do this again just in case we were called by SIOCGMIIREG
-		 * instead of SIOCGMIIPHY.
-		 */
-		mii = (struct mii_ioctl_data *)&ifr->ifr_data;
-		if (mii == NULL) {
-			return -EINVAL;
-		}
-		if (mii->reg_num == 1) {
-			mii->val_out = bond_check_mii_link(
-				(struct bonding *)master_dev->priv);
-		}
-		return 0;
-	case BOND_INFO_QUERY_OLD:
-	case SIOCBONDINFOQUERY:
-		u_binfo = (struct ifbond *)ifr->ifr_data;
-		if (copy_from_user(&k_binfo, u_binfo, sizeof(ifbond))) {
-			return -EFAULT;
-		}
-		ret = bond_info_query(master_dev, &k_binfo);
-		if (ret == 0) {
-			if (copy_to_user(u_binfo, &k_binfo, sizeof(ifbond))) {
-				return -EFAULT;
-			}
-		}
-		return ret;
-	case BOND_SLAVE_INFO_QUERY_OLD:
-	case SIOCBONDSLAVEINFOQUERY:
-		u_sinfo = (struct ifslave *)ifr->ifr_data;
-		if (copy_from_user(&k_sinfo, u_sinfo, sizeof(ifslave))) {
-			return -EFAULT;
-		}
-		ret = bond_slave_info_query(master_dev, &k_sinfo);
-		if (ret == 0) {
-			if (copy_to_user(u_sinfo, &k_sinfo, sizeof(ifslave))) {
-				return -EFAULT;
-			}
-		}
-		return ret;
-	}
-
-	if (!capable(CAP_NET_ADMIN)) {
-		return -EPERM;
-	}
-
-	slave_dev = dev_get_by_name(ifr->ifr_slave);
-
-#ifdef BONDING_DEBUG
-	printk(KERN_INFO "slave_dev=%x: \n", (unsigned int)slave_dev);
-	printk(KERN_INFO "slave_dev->name=%s: \n", slave_dev->name);
-#endif
-
-	if (slave_dev == NULL) {
-		ret = -ENODEV;
-	} else {
-		switch (cmd) {
-		case BOND_ENSLAVE_OLD:
-		case SIOCBONDENSLAVE:		
-			ret = bond_enslave(master_dev, slave_dev);
-			break;
-		case BOND_RELEASE_OLD:			
-		case SIOCBONDRELEASE:	
-			ret = bond_release(master_dev, slave_dev); 
-			break;
-		case BOND_SETHWADDR_OLD:
-		case SIOCBONDSETHWADDR:	
-			ret = bond_sethwaddr(master_dev, slave_dev);
-			break;
-		case BOND_CHANGE_ACTIVE_OLD:
-		case SIOCBONDCHANGEACTIVE:
-			if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
-				ret = bond_change_active(master_dev, slave_dev);
-			}
-			else {
-				ret = -EINVAL;
-			}
-			break;
-		default:
-			ret = -EOPNOTSUPP;
-		}
-		dev_put(slave_dev);
-	}
-	return ret;
-}
-
-#ifdef CONFIG_NET_FASTROUTE
-static int bond_accept_fastpath(struct net_device *dev, struct dst_entry *dst)
-{
-	return -1;
-}
-#endif
-
-/* 
- * in broadcast mode, we send everything to all usable interfaces.
- */
-static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *dev)
-{
-	slave_t *slave, *start_at;
-	struct bonding *bond = (struct bonding *) dev->priv;
-	unsigned long flags;
-	struct net_device *device_we_should_send_to = 0;
-
-	if (!IS_UP(dev)) { /* bond down */
-		dev_kfree_skb(skb);
-		return 0;
-	}
-
-	read_lock_irqsave(&bond->lock, flags);
-
-	read_lock(&bond->ptrlock);
-	slave = start_at = bond->current_slave;
-	read_unlock(&bond->ptrlock);
-
-	if (slave == NULL) { /* we're at the root, get the first slave */
-		/* no suitable interface, frame not sent */
-		read_unlock_irqrestore(&bond->lock, flags);
-		dev_kfree_skb(skb);
-		return 0;
-	}
-
-	do {
-		if (IS_UP(slave->dev)
-		    && (slave->link == BOND_LINK_UP)
-		    && (slave->state == BOND_STATE_ACTIVE)) {
-			if (device_we_should_send_to) {
-				struct sk_buff *skb2;
-				if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
-					printk(KERN_ERR "bond_xmit_broadcast: skb_clone() failed\n");
-					continue;
-				}
-
-				skb2->dev = device_we_should_send_to;
-				skb2->priority = 1;
-				dev_queue_xmit(skb2);
-			}
-			device_we_should_send_to = slave->dev;
-		}
-	} while ((slave = slave->next) != start_at);
-
-	if (device_we_should_send_to) {
-		skb->dev = device_we_should_send_to;
-		skb->priority = 1;
-		dev_queue_xmit(skb);
-	} else
-		dev_kfree_skb(skb);
-
-	/* frame sent to all suitable interfaces */
-	read_unlock_irqrestore(&bond->lock, flags);
-	return 0;
-}
-
-static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *dev)
-{
-	slave_t *slave, *start_at;
-	struct bonding *bond = (struct bonding *) dev->priv;
-	unsigned long flags;
-
-	if (!IS_UP(dev)) { /* bond down */
-		dev_kfree_skb(skb);
-		return 0;
-	}
-
-	read_lock_irqsave(&bond->lock, flags);
-
-	read_lock(&bond->ptrlock);
-	slave = start_at = bond->current_slave;
-	read_unlock(&bond->ptrlock);
-
-	if (slave == NULL) { /* we're at the root, get the first slave */
-		/* no suitable interface, frame not sent */
-		dev_kfree_skb(skb);
-		read_unlock_irqrestore(&bond->lock, flags);
-		return 0;
-	}
-
-	do {
-		if (IS_UP(slave->dev)
-		    && (slave->link == BOND_LINK_UP)
-		    && (slave->state == BOND_STATE_ACTIVE)) {
-
-			skb->dev = slave->dev;
-			skb->priority = 1;
-			dev_queue_xmit(skb);
-
-			write_lock(&bond->ptrlock);
-			bond->current_slave = slave->next;
-			write_unlock(&bond->ptrlock);
-
-			read_unlock_irqrestore(&bond->lock, flags);
-			return 0;
-		}
-	} while ((slave = slave->next) != start_at);
-
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
-	read_unlock_irqrestore(&bond->lock, flags);
-	return 0;
-}
-
-/* 
- * in XOR mode, we determine the output device by performing xor on
- * the source and destination hw addresses.  If this device is not 
- * enabled, find the next slave following this xor slave. 
- */
-static int bond_xmit_xor(struct sk_buff *skb, struct net_device *dev)
-{
-	slave_t *slave, *start_at;
-	struct bonding *bond = (struct bonding *) dev->priv;
-	unsigned long flags;
-	struct ethhdr *data = (struct ethhdr *)skb->data;
-	int slave_no;
-
-	if (!IS_UP(dev)) { /* bond down */
-		dev_kfree_skb(skb);
-		return 0;
-	}
-
-	read_lock_irqsave(&bond->lock, flags);
-	slave = bond->prev;
-
-	/* we're at the root, get the first slave */
-	if (bond->slave_cnt == 0) {
-		/* no suitable interface, frame not sent */
-		dev_kfree_skb(skb);
-		read_unlock_irqrestore(&bond->lock, flags);
-		return 0;
-	}
-
-	slave_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % bond->slave_cnt;
-
-	while ( (slave_no > 0) && (slave != (slave_t *)bond) ) {
-		slave = slave->prev;
-		slave_no--;
-	} 
-	start_at = slave;
-
-	do {
-		if (IS_UP(slave->dev)
-		    && (slave->link == BOND_LINK_UP)
-		    && (slave->state == BOND_STATE_ACTIVE)) {
-
-			skb->dev = slave->dev;
-			skb->priority = 1;
-			dev_queue_xmit(skb);
-
-			read_unlock_irqrestore(&bond->lock, flags);
-			return 0;
-		}
-	} while ((slave = slave->next) != start_at);
-
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
-	read_unlock_irqrestore(&bond->lock, flags);
-	return 0;
-}
-
-/* 
- * in active-backup mode, we know that bond->current_slave is always valid if
- * the bond has a usable interface.
- */
-static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *dev)
-{
-	struct bonding *bond = (struct bonding *) dev->priv;
-	unsigned long flags;
-	int ret;
-
-	if (!IS_UP(dev)) { /* bond down */
-		dev_kfree_skb(skb);
-		return 0;
-	}
-
-	/* if we are sending arp packets, try to at least 
-	   identify our own ip address */
-	if ( (arp_interval > 0) && (my_ip == 0) &&
-		(skb->protocol == __constant_htons(ETH_P_ARP) ) ) {
-		char *the_ip = (((char *)skb->data)) 
-				+ sizeof(struct ethhdr)  
-				+ sizeof(struct arphdr) + 
-				ETH_ALEN;
-		memcpy(&my_ip, the_ip, 4);
-	}
-
-	/* if we are sending arp packets and don't know 
-	 * the target hw address, save it so we don't need 
-	 * to use a broadcast address.
-	 * don't do this if in active backup mode because the slaves must 
-	 * receive packets to stay up, and the only ones they receive are 
-	 * broadcasts. 
-	 */
-	if ( (bond_mode != BOND_MODE_ACTIVEBACKUP) && 
-             (arp_ip_count == 1) &&
-	     (arp_interval > 0) && (arp_target_hw_addr == NULL) &&
-	     (skb->protocol == __constant_htons(ETH_P_IP) ) ) {
-		struct ethhdr *eth_hdr = 
-			(struct ethhdr *) (((char *)skb->data));
-		struct iphdr *ip_hdr = (struct iphdr *)(eth_hdr + 1);
-
-		if (arp_target[0] == ip_hdr->daddr) {
-			arp_target_hw_addr = kmalloc(ETH_ALEN, GFP_KERNEL);
-			if (arp_target_hw_addr != NULL)
-				memcpy(arp_target_hw_addr, eth_hdr->h_dest, ETH_ALEN);
-		}
-	}
-
-	read_lock_irqsave(&bond->lock, flags);
-
-	read_lock(&bond->ptrlock);
-	if (bond->current_slave != NULL) { /* one usable interface */
-		skb->dev = bond->current_slave->dev;
-		read_unlock(&bond->ptrlock);
-		skb->priority = 1;
-		ret = dev_queue_xmit(skb);
-		read_unlock_irqrestore(&bond->lock, flags);
-		return 0;
-	}
-	else {
-		read_unlock(&bond->ptrlock);
-	}
-
-	/* no suitable interface, frame not sent */
-#ifdef BONDING_DEBUG
-	printk(KERN_INFO "There was no suitable interface, so we don't transmit\n");
-#endif
-	dev_kfree_skb(skb);
-	read_unlock_irqrestore(&bond->lock, flags);
-	return 0;
-}
-
-static struct net_device_stats *bond_get_stats(struct net_device *dev)
-{
-	bonding_t *bond = dev->priv;
-	struct net_device_stats *stats = bond->stats, *sstats;
-	slave_t *slave;
-	unsigned long flags;
-
-	memset(bond->stats, 0, sizeof(struct net_device_stats));
-
-	read_lock_irqsave(&bond->lock, flags);
-
-	for (slave = bond->prev; slave != (slave_t *)bond; slave = slave->prev) {
-		sstats = slave->dev->get_stats(slave->dev);
- 
-		stats->rx_packets += sstats->rx_packets;
-		stats->rx_bytes += sstats->rx_bytes;
-		stats->rx_errors += sstats->rx_errors;
-		stats->rx_dropped += sstats->rx_dropped;
-
-		stats->tx_packets += sstats->tx_packets;
-		stats->tx_bytes += sstats->tx_bytes;
-		stats->tx_errors += sstats->tx_errors;
-		stats->tx_dropped += sstats->tx_dropped;
-
-		stats->multicast += sstats->multicast;
-		stats->collisions += sstats->collisions;
-
-		stats->rx_length_errors += sstats->rx_length_errors;
-		stats->rx_over_errors += sstats->rx_over_errors;
-		stats->rx_crc_errors += sstats->rx_crc_errors;
-		stats->rx_frame_errors += sstats->rx_frame_errors;
-		stats->rx_fifo_errors += sstats->rx_fifo_errors;	
-		stats->rx_missed_errors += sstats->rx_missed_errors;
-	
-		stats->tx_aborted_errors += sstats->tx_aborted_errors;
-		stats->tx_carrier_errors += sstats->tx_carrier_errors;
-		stats->tx_fifo_errors += sstats->tx_fifo_errors;
-		stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors;
-		stats->tx_window_errors += sstats->tx_window_errors;
-
-	}
-
-	read_unlock_irqrestore(&bond->lock, flags);
-	return stats;
-}
-
-static int bond_get_info(char *buf, char **start, off_t offset, int length)
-{
-	bonding_t *bond = these_bonds;
-	int len = 0;
-	off_t begin = 0;
-	u16 link;
-	slave_t *slave = NULL;
-	unsigned long flags;
-
-	while (bond != NULL) {
-		/*
-		 * This function locks the mutex, so we can't lock it until 
-		 * afterwards
-		 */
-		link = bond_check_mii_link(bond);
-
-		len += sprintf(buf + len, "Bonding Mode: %s\n",
-			       bond_mode_name());
-
-		if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
-			read_lock_irqsave(&bond->lock, flags);
-			read_lock(&bond->ptrlock);
-			if (bond->current_slave != NULL) {
-				len += sprintf(buf + len, 
-					"Currently Active Slave: %s\n", 
-					bond->current_slave->dev->name);
-			}
-			read_unlock(&bond->ptrlock);
-			read_unlock_irqrestore(&bond->lock, flags);
-		}
-
-		len += sprintf(buf + len, "MII Status: ");
-		len += sprintf(buf + len, 
-				link == BMSR_LSTATUS ? "up\n" : "down\n");
-		len += sprintf(buf + len, "MII Polling Interval (ms): %d\n", 
-				miimon);
-		len += sprintf(buf + len, "Up Delay (ms): %d\n", 
-				updelay * miimon);
-		len += sprintf(buf + len, "Down Delay (ms): %d\n", 
-				downdelay * miimon);
-		len += sprintf(buf + len, "Multicast Mode: %s\n",
-			       multicast_mode_name());
-
-		read_lock_irqsave(&bond->lock, flags);
-		for (slave = bond->prev; slave != (slave_t *)bond; 
-		     slave = slave->prev) {
-			len += sprintf(buf + len, "\nSlave Interface: %s\n", slave->dev->name);
-
-			len += sprintf(buf + len, "MII Status: ");
-
-			len += sprintf(buf + len, 
-				slave->link == BOND_LINK_UP ? 
-				"up\n" : "down\n");
-			len += sprintf(buf + len, "Link Failure Count: %d\n", 
-				slave->link_failure_count);
-		}
-		read_unlock_irqrestore(&bond->lock, flags);
-
-		/*
-		 * Figure out the calcs for the /proc/net interface
-		 */
-		*start = buf + (offset - begin);
-		len -= (offset - begin);
-		if (len > length) {
-			len = length;
-		}
-		if (len < 0) {
-			len = 0;
-		}
-
-
-		bond = bond->next_bond;
-	}
-	return len;
-}
-
-static int bond_event(struct notifier_block *this, unsigned long event, 
-			void *ptr)
-{
-	struct bonding *this_bond = (struct bonding *)these_bonds;
-	struct bonding *last_bond;
-	struct net_device *event_dev = (struct net_device *)ptr;
-
-	/* while there are bonds configured */
-	while (this_bond != NULL) {
-		if (this_bond == event_dev->priv ) {
-			switch (event) {
-			case NETDEV_UNREGISTER:
-				/* 
-				 * remove this bond from a linked list of 
-				 * bonds 
-				 */
-				if (this_bond == these_bonds) {
-					these_bonds = this_bond->next_bond;
-				} else {
-					for (last_bond = these_bonds; 
-					     last_bond != NULL; 
-					     last_bond = last_bond->next_bond) {
-						if (last_bond->next_bond == 
-						    this_bond) {
-							last_bond->next_bond = 
-							this_bond->next_bond;
-						}
-					}
-				}
-				return NOTIFY_DONE;
-
-			default:
-				return NOTIFY_DONE;
-			}
-		} else if (this_bond->device == event_dev->master) {
-			switch (event) {
-			case NETDEV_UNREGISTER:
-				bond_release(this_bond->device, event_dev);
-				break;
-			}
-			return NOTIFY_DONE;
-		}
-		this_bond = this_bond->next_bond;
-	}
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block bond_netdev_notifier = {
-	.notifier_call = bond_event,
-};
-
-static int __init bond_init(struct net_device *dev)
-{
-	bonding_t *bond, *this_bond, *last_bond;
-	int count;
-
-#ifdef BONDING_DEBUG
-	printk (KERN_INFO "Begin bond_init for %s\n", dev->name);
-#endif
-	bond = kmalloc(sizeof(struct bonding), GFP_KERNEL);
-	if (bond == NULL) {
-		return -ENOMEM;
-	}
-	memset(bond, 0, sizeof(struct bonding));
-
-	/* initialize rwlocks */
-	rwlock_init(&bond->lock);
-	rwlock_init(&bond->ptrlock);
-	
-	bond->stats = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
-	if (bond->stats == NULL) {
-		kfree(bond);
-		return -ENOMEM;
-	}
-	memset(bond->stats, 0, sizeof(struct net_device_stats));
-
-	bond->next = bond->prev = (slave_t *)bond;
-	bond->current_slave = NULL;
-	bond->current_arp_slave = NULL;
-	bond->device = dev;
-	dev->priv = bond;
-
-	/* Initialize the device structure. */
-	switch (bond_mode) {
-	case BOND_MODE_ACTIVEBACKUP:
-		dev->hard_start_xmit = bond_xmit_activebackup;
-		break;
-	case BOND_MODE_ROUNDROBIN:
-		dev->hard_start_xmit = bond_xmit_roundrobin;
-		break;
-	case BOND_MODE_XOR:
-		dev->hard_start_xmit = bond_xmit_xor;
-		break;
-	case BOND_MODE_BROADCAST:
-		dev->hard_start_xmit = bond_xmit_broadcast;
-		break;
-	default:
-		printk(KERN_ERR "Unknown bonding mode %d\n", bond_mode);
-		kfree(bond->stats);
-		kfree(bond);
-		return -EINVAL;
-	}
-
-	dev->get_stats = bond_get_stats;
-	dev->open = bond_open;
-	dev->stop = bond_close;
-	dev->set_multicast_list = set_multicast_list;
-	dev->do_ioctl = bond_ioctl;
-
-	/* 
-	 * Fill in the fields of the device structure with ethernet-generic 
-	 * values. 
-	 */
-
-	ether_setup(dev);
-
-	dev->tx_queue_len = 0;
-	dev->flags |= IFF_MASTER|IFF_MULTICAST;
-#ifdef CONFIG_NET_FASTROUTE
-	dev->accept_fastpath = bond_accept_fastpath;
-#endif
-
-	printk(KERN_INFO "%s registered with", dev->name);
-	if (miimon > 0) {
-		printk(" MII link monitoring set to %d ms", miimon);
-		updelay /= miimon;
-		downdelay /= miimon;
-	} else {
-		printk("out MII link monitoring");
-	}
-	printk(", in %s mode.\n", bond_mode_name());
-
-	printk(KERN_INFO "%s registered with", dev->name);
-	if (arp_interval > 0) {
-		printk(" ARP monitoring set to %d ms with %d target(s):", 
-			arp_interval, arp_ip_count);
-		for (count=0 ; count<arp_ip_count ; count++)
-                        printk (" %s", arp_ip_target[count]);
-		printk("\n");
-	} else {
-		printk("out ARP monitoring\n");
-	}
-
-#ifdef CONFIG_PROC_FS
-	bond->bond_proc_dir = proc_mkdir(dev->name, proc_net);
-	if (bond->bond_proc_dir == NULL) {
-		printk(KERN_ERR "%s: Cannot init /proc/net/%s/\n", 
-			dev->name, dev->name);
-		kfree(bond->stats);
-		kfree(bond);
-		return -ENOMEM;
-	}
-	bond->bond_proc_info_file = 
-		create_proc_info_entry("info", 0, bond->bond_proc_dir, 
-					bond_get_info);
-	if (bond->bond_proc_info_file == NULL) {
-		printk(KERN_ERR "%s: Cannot init /proc/net/%s/info\n", 
-			dev->name, dev->name);
-		remove_proc_entry(dev->name, proc_net);
-		kfree(bond->stats);
-		kfree(bond);
-		return -ENOMEM;
-	}
-#endif /* CONFIG_PROC_FS */
-
-	if (first_pass == 1) {
-		these_bonds = bond;
-		register_netdevice_notifier(&bond_netdev_notifier);
-		first_pass = 0;
-	} else {
-		last_bond = these_bonds;
-		this_bond = these_bonds->next_bond;
-		while (this_bond != NULL) {
-			last_bond = this_bond;
-			this_bond = this_bond->next_bond;
-		}
-		last_bond->next_bond = bond;
-	} 
-
-	return 0;
-}
-
-/*
-static int __init bond_probe(struct net_device *dev)
-{
-	bond_init(dev);
-	return 0;
-}
- */
-
-/*
- * Convert string input module parms.  Accept either the
- * number of the mode or its string name.
- */
-static inline int
-bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
-{
-	int i;
-
-	for (i = 0; tbl[i].modename != NULL; i++) {
-		if ((isdigit(*mode_arg) &&
-		    tbl[i].mode == simple_strtol(mode_arg, NULL, 0)) ||
-		    (0 == strncmp(mode_arg, tbl[i].modename,
-				  strlen(tbl[i].modename)))) {
-			return tbl[i].mode;
-		}
-	}
-
-	return -1;
-}
-
-
-static int __init bonding_init(void)
-{
-	int no;
-	int err;
-
-	/* Find a name for this unit */
-	static struct net_device *dev_bond = NULL;
-
-	printk(KERN_INFO "%s", version);
-
-	/*
-	 * Convert string parameters.
-	 */
-	if (mode) {
-		bond_mode = bond_parse_parm(mode, bond_mode_tbl);
-		if (bond_mode == -1) {
-			printk(KERN_WARNING
-			       "bonding_init(): Invalid bonding mode \"%s\"\n",
-			       mode == NULL ? "NULL" : mode);
-			return -EINVAL;
-		}
-	}
-
-	if (multicast) {
-		multicast_mode = bond_parse_parm(multicast, bond_mc_tbl);
-		if (multicast_mode == -1) {
-			printk(KERN_WARNING 
-		       "bonding_init(): Invalid multicast mode \"%s\"\n",
-			       multicast == NULL ? "NULL" : multicast);
-			return -EINVAL;
-		}
-	}
-
-	if (max_bonds < 1 || max_bonds > INT_MAX) {
-		printk(KERN_WARNING 
-		       "bonding_init(): max_bonds (%d) not in range %d-%d, "
-		       "so it was reset to BOND_DEFAULT_MAX_BONDS (%d)",
-		       max_bonds, 1, INT_MAX, BOND_DEFAULT_MAX_BONDS);
-		max_bonds = BOND_DEFAULT_MAX_BONDS;
-	}
-	dev_bond = dev_bonds = kmalloc(max_bonds*sizeof(struct net_device), 
-					GFP_KERNEL);
-	if (dev_bond == NULL) {
-		return -ENOMEM;
-	}
-	memset(dev_bonds, 0, max_bonds*sizeof(struct net_device));
-
-	if (miimon < 0) {
-		printk(KERN_WARNING 
-		       "bonding_init(): miimon module parameter (%d), "
-		       "not in range 0-%d, so it was reset to %d\n",
-		       miimon, INT_MAX, BOND_LINK_MON_INTERV);
-		miimon = BOND_LINK_MON_INTERV;
-	}
-
-	if (updelay < 0) {
-		printk(KERN_WARNING 
-		       "bonding_init(): updelay module parameter (%d), "
-		       "not in range 0-%d, so it was reset to 0\n",
-		       updelay, INT_MAX);
-		updelay = 0;
-	}
-
-	if (downdelay < 0) {
-		printk(KERN_WARNING 
-		       "bonding_init(): downdelay module parameter (%d), "
-		       "not in range 0-%d, so it was reset to 0\n",
-		       downdelay, INT_MAX);
-		downdelay = 0;
-	}
-
-	if (miimon == 0) {
-		if ((updelay != 0) || (downdelay != 0)) {
-			/* just warn the user the up/down delay will have
-			 * no effect since miimon is zero...
-			 */
-			printk(KERN_WARNING 
-		               "bonding_init(): miimon module parameter not "
-			       "set and updelay (%d) or downdelay (%d) module "
-			       "parameter is set; updelay and downdelay have "
-			       "no effect unless miimon is set\n",
-		               updelay, downdelay);
-		}
-	} else {
-		/* don't allow arp monitoring */
-		if (arp_interval != 0) {
-			printk(KERN_WARNING 
-		               "bonding_init(): miimon (%d) and arp_interval "
-			       "(%d) can't be used simultaneously, "
-			       "disabling ARP monitoring\n",
-		               miimon, arp_interval);
-			arp_interval = 0;
-		}
-
-		if ((updelay % miimon) != 0) {
-			/* updelay will be rounded in bond_init() when it
-			 * is divided by miimon, we just inform user here
-			 */
-			printk(KERN_WARNING 
-		               "bonding_init(): updelay (%d) is not a multiple "
-			       "of miimon (%d), updelay rounded to %d ms\n",
-		               updelay, miimon, (updelay / miimon) * miimon);
-		}
-
-		if ((downdelay % miimon) != 0) {
-			/* downdelay will be rounded in bond_init() when it
-			 * is divided by miimon, we just inform user here
-			 */
-			printk(KERN_WARNING 
-		               "bonding_init(): downdelay (%d) is not a "
-			       "multiple of miimon (%d), downdelay rounded "
-			       "to %d ms\n",
-		               downdelay, miimon, 
-			       (downdelay / miimon) * miimon);
-		}
-	}
-
-	if (arp_interval < 0) {
-		printk(KERN_WARNING 
-		       "bonding_init(): arp_interval module parameter (%d), "
-		       "not in range 0-%d, so it was reset to %d\n",
-		       arp_interval, INT_MAX, BOND_LINK_ARP_INTERV);
-		arp_interval = BOND_LINK_ARP_INTERV;
-	}
-
-        for (arp_ip_count=0 ;
-             (arp_ip_count < MAX_ARP_IP_TARGETS) && arp_ip_target[arp_ip_count];
-              arp_ip_count++ ) {
-                /* TODO: check and log bad ip address */
-                if (my_inet_aton(arp_ip_target[arp_ip_count],
-                                 &arp_target[arp_ip_count]) == 0) {
-                        printk(KERN_WARNING
-                               "bonding_init(): bad arp_ip_target module "
-                               "parameter (%s), ARP monitoring will not be "
-                               "performed\n",
-                               arp_ip_target[arp_ip_count]);
-                        arp_interval = 0;
-		}
-        }
-
-
-	if ( (arp_interval > 0) && (arp_ip_count==0)) {
-		/* don't allow arping if no arp_ip_target given... */
-		printk(KERN_WARNING 
-		       "bonding_init(): arp_interval module parameter "
-		       "(%d) specified without providing an arp_ip_target "
-		       "parameter, arp_interval was reset to 0\n",
-		       arp_interval);
-		arp_interval = 0;
-	}
-
-	if ((miimon == 0) && (arp_interval == 0)) {
-		/* miimon and arp_interval not set, we need one so things
-		 * work as expected, see bonding.txt for details
-		 */
-		printk(KERN_ERR 
-		       "bonding_init(): either miimon or "
-		       "arp_interval and arp_ip_target module parameters "
-		       "must be specified, otherwise bonding will not detect "
-		       "link failures! see bonding.txt for details.\n");
-	}
-
-	if ((primary != NULL) && (bond_mode != BOND_MODE_ACTIVEBACKUP)){
-		/* currently, using a primary only makes sence 
-		 * in active backup mode 
-		 */
-		printk(KERN_WARNING 
-		       "bonding_init(): %s primary device specified but has "
-		       " no effect in %s mode\n",
-		       primary, bond_mode_name());
-		primary = NULL;
-	}
-
-
-	for (no = 0; no < max_bonds; no++) {
-		dev_bond->init = bond_init;
-	
-		err = dev_alloc_name(dev_bond,"bond%d");
-		if (err < 0) {
-			kfree(dev_bonds);
-			return err;
-		}
-		SET_MODULE_OWNER(dev_bond);
-		if (register_netdev(dev_bond) != 0) {
-			kfree(dev_bonds);
-			return -EIO;
-		}	
-		dev_bond++;
-	}
-	return 0;
-}
-
-static void __exit bonding_exit(void)
-{
-	struct net_device *dev_bond = dev_bonds;
-	struct bonding *bond;
-	int no;
-
-	unregister_netdevice_notifier(&bond_netdev_notifier);
-		 
-	for (no = 0; no < max_bonds; no++) {
-
-#ifdef CONFIG_PROC_FS
-		bond = (struct bonding *) dev_bond->priv;
-		remove_proc_entry("info", bond->bond_proc_dir);
-		remove_proc_entry(dev_bond->name, proc_net);
-#endif
-		unregister_netdev(dev_bond);
-		kfree(bond->stats);
-		kfree(dev_bond->priv);
-		
-		dev_bond->priv = NULL;
-		dev_bond++;
-	}
-	kfree(dev_bonds);
-}
-
-module_init(bonding_init);
-module_exit(bonding_exit);
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(DRV_DESCRIPTION ", v" DRV_VERSION);
-
-/*
- * Local variables:
- *  c-indent-level: 8
- *  c-basic-offset: 8
- *  tab-width: 8
- * End:
- */
diff -urN linux-2.5.69-bk18/drivers/net/cs89x0.h linux-2.5.69-bk19/drivers/net/cs89x0.h
--- linux-2.5.69-bk18/drivers/net/cs89x0.h	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/cs89x0.h	2003-05-26 04:41:42.000000000 -0700
@@ -385,11 +385,11 @@
 #define A_CNF_10B_T 0x0001
 #define A_CNF_AUI 0x0002
 #define A_CNF_10B_2 0x0004
-#define A_CNF_MEDIA_TYPE 0x0060
-#define A_CNF_MEDIA_AUTO 0x0000
+#define A_CNF_MEDIA_TYPE 0x0070
+#define A_CNF_MEDIA_AUTO 0x0070
 #define A_CNF_MEDIA_10B_T 0x0020
 #define A_CNF_MEDIA_AUI 0x0040
-#define A_CNF_MEDIA_10B_2 0x0060
+#define A_CNF_MEDIA_10B_2 0x0010
 #define A_CNF_DC_DC_POLARITY 0x0080
 #define A_CNF_NO_AUTO_POLARITY 0x2000
 #define A_CNF_LOW_RX_SQUELCH 0x4000
diff -urN linux-2.5.69-bk18/drivers/net/e100/e100.h linux-2.5.69-bk19/drivers/net/e100/e100.h
--- linux-2.5.69-bk18/drivers/net/e100/e100.h	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/e100/e100.h	2003-05-26 04:41:42.000000000 -0700
@@ -60,7 +60,14 @@
 #include <linux/if_vlan.h>
 #include <linux/mii.h>
 
-#define E100_REGS_LEN 1
+#define E100_CABLE_UNKNOWN	0
+#define E100_CABLE_OK		1		
+#define E100_CABLE_OPEN_NEAR	2	/* Open Circuit Near End  */
+#define E100_CABLE_OPEN_FAR	3	/* Open Circuit Far End   */
+#define E100_CABLE_SHORT_NEAR	4	/* Short Circuit Near End */
+#define E100_CABLE_SHORT_FAR	5	/* Short Circuit Far End  */
+
+#define E100_REGS_LEN 2
 /*
  *  Configure parameters for buffers per controller.
  *  If the machine this is being used on is a faster machine (i.e. > 150MHz)
@@ -105,8 +112,6 @@
 #define E100_MAX_CU_IDLE_WAIT	50	/* Max udelays in wait_cus_idle */
 
 /* HWI feature related constant */
-#define HWI_MAX_LOOP                    100
-#define MAX_SAME_RESULTS		3
 #define HWI_REGISTER_GRANULARITY        80	/* register granularity = 80 Cm */
 #define HWI_NEAR_END_BOUNDARY           1000	/* Near end is defined as < 10 meters */
 
@@ -942,7 +947,6 @@
 #ifdef CONFIG_PM
 	u32 pci_state[16];
 #endif
-	char ifname[IFNAMSIZ];
 #ifdef E100_CU_DEBUG	
 	u8 last_cmd;
 	u8 last_sub_cmd;
@@ -956,7 +960,10 @@
 #define E100_SPEED_100_FULL 4
 
 /********* function prototypes *************/
+extern int e100_open(struct net_device *);
+extern int e100_close(struct net_device *);
 extern void e100_isolate_driver(struct e100_private *bdp);
+extern unsigned char e100_hw_init(struct e100_private *);
 extern void e100_sw_reset(struct e100_private *bdp, u32 reset_cmd);
 extern u8 e100_start_cu(struct e100_private *bdp, tcb_t *tcb);
 extern void e100_free_non_tx_cmd(struct e100_private *bdp,
@@ -981,14 +988,13 @@
 #define TEST_TIMEOUT		0x08
 
 enum test_offsets {
-	E100_EEPROM_TEST_FAIL = 0,
-	E100_CHIP_TIMEOUT,
-	E100_ROM_TEST_FAIL,
-	E100_REG_TEST_FAIL,
-	E100_MAC_TEST_FAIL,
-	E100_LPBK_MAC_FAIL,
-	E100_LPBK_PHY_FAIL,
-	E100_MAX_TEST_RES
+	test_link,
+	test_eeprom,
+	test_self_test,
+	test_loopback_mac,
+	test_loopback_phy,
+	cable_diag,
+	max_test_res,  /* must be last */
 };
 
 #endif
diff -urN linux-2.5.69-bk18/drivers/net/e100/e100_main.c linux-2.5.69-bk19/drivers/net/e100/e100_main.c
--- linux-2.5.69-bk18/drivers/net/e100/e100_main.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/e100/e100_main.c	2003-05-26 04:41:42.000000000 -0700
@@ -46,6 +46,24 @@
 
 /* Change Log
  * 
+ * 2.3.13       05/08/03
+ * o Feature remove: /proc/net/PRO_LAN_Adapters support gone completely
+ * o Feature remove: IDIAG support (use ethtool -t instead)
+ * o Cleanup: fixed spelling mistakes found by community
+ * o Feature add: ethtool cable diag test
+ * o Feature add: ethtool parameter support (ring size, xsum, flow ctrl)
+ * o Cleanup: move e100_asf_enable under CONFIG_PM to avoid warning
+ *   [Stephen Rothwell (sfr@canb.auug.org.au)]
+ * o Bug fix: don't call any netif_carrier_* until netdev registered.
+ *   [Andrew Morton (akpm@digeo.com)]
+ * o Cleanup: replace (skb->len - skb->data_len) with skb_headlen(skb)
+ *   [jmorris@intercode.com.au]
+ * o Bug fix: cleanup of Tx skbs after running ethtool diags
+ * o Bug fix: incorrect reporting of ethtool diag overall results
+ * o Bug fix: must hold xmit_lock before stopping queue in ethtool
+ *   operations that require reset h/w and driver structures.
+ * o Bug fix: statistic command failure would stop statistic collection.
+ * 
  * 2.2.21	02/11/03
  * o Removed marketing brand strings. Instead, Using generic string 
  *   "Intel(R) PRO/100 Network Connection" for all adapters.
@@ -61,21 +79,6 @@
  * o New feature: added ICH5 support
  * 
  * 2.1.27	11/20/02
- *   o Bug fix: Device command timeout due to SMBus processing during init
- *   o Bug fix: Not setting/clearing I (Interrupt) bit in tcb correctly
- *   o Bug fix: Not using EEPROM WoL setting as default in ethtool
- *   o Bug fix: Not able to set autoneg on using ethtool when interface down
- *   o Bug fix: Not able to change speed/duplex using ethtool/mii
- *     when interface up
- *   o Bug fix: Ethtool shows autoneg on when forced to 100/Full
- *   o Bug fix: Compiler error when CONFIG_PROC_FS not defined
- *   o Bug fix: 2.5.44 e100 doesn't load with preemptive kernel enabled
- *     (sleep while holding spinlock)
- *   o Bug fix: 2.1.24-k1 doesn't display complete statistics
- *   o Bug fix: System panic due to NULL watchdog timer dereference during
- *     ifconfig down, rmmod and insmod
- *
- * 2.1.24       10/7/02
  */
  
 #include <linux/config.h>
@@ -121,14 +124,13 @@
 extern u32 e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags);
 static int e100_ethtool_test(struct net_device *, struct ifreq *);
 static int e100_ethtool_gstrings(struct net_device *, struct ifreq *);
-static char *test_strings[] = {
-	"E100_EEPROM_TEST_FAIL",
-	"E100_CHIP_TIMEOUT",
-	"E100_ROM_TEST_FAIL",
-	"E100_REG_TEST_FAIL",
-	"E100_MAC_TEST_FAIL",
-	"E100_LPBK_MAC_FAIL",
-	"E100_LPBK_PHY_FAIL"
+static char test_strings[][ETH_GSTRING_LEN] = {
+	"Link test     (on/offline)",
+	"Eeprom test   (on/offline)",
+	"Self test        (offline)",
+	"Mac loopback     (offline)",
+	"Phy loopback     (offline)",
+	"Cable diagnostic (offline)"
 };
 
 static int e100_ethtool_led_blink(struct net_device *, struct ifreq *);
@@ -139,10 +141,10 @@
 						  nxmit_cb_entry_t *);
 static void e100_free_nontx_list(struct e100_private *);
 static void e100_non_tx_background(unsigned long);
-
+static inline void e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb);
 /* Global Data structures and variables */
 char e100_copyright[] __devinitdata = "Copyright (c) 2003 Intel Corporation";
-char e100_driver_version[]="2.2.21-k1";
+char e100_driver_version[]="2.3.13-k1";
 const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver";
 char e100_short_driver_name[] = "e100";
 static int e100nics = 0;
@@ -155,6 +157,7 @@
 static int e100_notify_reboot(struct notifier_block *, unsigned long event, void *ptr);
 static int e100_suspend(struct pci_dev *pcid, u32 state);
 static int e100_resume(struct pci_dev *pcid);
+static unsigned char e100_asf_enabled(struct e100_private *bdp);
 struct notifier_block e100_notifier_reboot = {
         .notifier_call  = e100_notify_reboot,
         .next           = NULL,
@@ -182,8 +185,6 @@
 static u8 e100_D101M_checksum(struct e100_private *, struct sk_buff *);
 static u8 e100_D102_check_checksum(rfd_t *);
 static int e100_ioctl(struct net_device *, struct ifreq *, int);
-static int e100_open(struct net_device *);
-static int e100_close(struct net_device *);
 static int e100_change_mtu(struct net_device *, int);
 static int e100_xmit_frame(struct sk_buff *, struct net_device *);
 static unsigned char e100_init(struct e100_private *);
@@ -193,7 +194,6 @@
 static irqreturn_t e100intr(int, void *, struct pt_regs *);
 static void e100_print_brd_conf(struct e100_private *);
 static void e100_set_multi(struct net_device *);
-void e100_set_speed_duplex(struct e100_private *);
 
 static u8 e100_pci_setup(struct pci_dev *, struct e100_private *);
 static u8 e100_sw_init(struct e100_private *);
@@ -215,7 +215,6 @@
 
 static unsigned char e100_clr_cntrs(struct e100_private *);
 static unsigned char e100_load_microcode(struct e100_private *);
-static unsigned char e100_hw_init(struct e100_private *);
 static unsigned char e100_setup_iaaddr(struct e100_private *, u8 *);
 static unsigned char e100_update_stats(struct e100_private *bdp);
 
@@ -228,7 +227,6 @@
 				 char *);
 unsigned char e100_wait_exec_cmplx(struct e100_private *, u32, u8, u8);
 void e100_exec_cmplx(struct e100_private *, u32, u8);
-static unsigned char e100_asf_enabled(struct e100_private *bdp);
 
 /**
  * e100_get_rx_struct - retrieve cell to hold skb buff from the pool
@@ -616,6 +614,10 @@
 		goto err_dealloc;
 	}
 
+	if ((rc = register_netdev(dev)) != 0) {
+		goto err_pci;
+	}
+
 	if (((bdp->pdev->device > 0x1030)
 	       && (bdp->pdev->device < 0x103F))
 	    || ((bdp->pdev->device >= 0x1050)
@@ -645,7 +647,7 @@
 		printk(KERN_ERR "e100: Failed to initialize, instance #%d\n",
 		       e100nics);
 		rc = -ENODEV;
-		goto err_pci;
+		goto err_unregister_netdev;
 	}
 
 	/* Check if checksum is valid */
@@ -655,7 +657,7 @@
                 printk(KERN_ERR "e100: Corrupted EEPROM on instance #%d\n",
 		       e100nics);
                 rc = -ENODEV;
-                goto err_pci;
+                goto err_unregister_netdev;
 	}
 	
 	dev->vlan_rx_register = e100_vlan_rx_register;
@@ -679,12 +681,6 @@
 
 	e100_get_speed_duplex_caps(bdp);
 
-	if ((rc = register_netdev(dev)) != 0) {
-		goto err_pci;
-	}
-        memcpy(bdp->ifname, dev->name, IFNAMSIZ);
-        bdp->ifname[IFNAMSIZ-1] = 0;	
-
 	printk(KERN_NOTICE
 	       "e100: %s: %s\n", 
 	       bdp->device->name, "Intel(R) PRO/100 Network Connection");
@@ -709,6 +705,8 @@
 
 	goto out;
 
+err_unregister_netdev:
+	unregister_netdev(dev);
 err_pci:
 	iounmap(bdp->scb);
 	pci_release_regions(pcid);
@@ -974,7 +972,7 @@
 	}
 }
 
-static int
+int
 e100_open(struct net_device *dev)
 {
 	struct e100_private *bdp;
@@ -1012,7 +1010,11 @@
 
 	mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ));
 
-	netif_start_queue(dev);
+	if (dev->flags & IFF_UP)
+		/* Otherwise process may sleep forever */
+		netif_wake_queue(dev);
+	else
+		netif_start_queue(dev);
 
 	e100_start_ru(bdp);
 	if ((rc = request_irq(dev->irq, &e100intr, SA_SHIRQ,
@@ -1033,7 +1035,7 @@
 	return rc;
 }
 
-static int
+int
 e100_close(struct net_device *dev)
 {
 	struct e100_private *bdp = dev->priv;
@@ -1074,7 +1076,8 @@
 		goto exit2;
 	}
 
-	if (!TCBS_AVAIL(bdp->tcb_pool) ||
+	/* tcb list may be empty temporarily during releasing resources */
+	if (!TCBS_AVAIL(bdp->tcb_pool) || (bdp->tcb_phys == 0) ||
 	    (bdp->non_tx_command_state != E100_NON_TX_IDLE)) {
 		notify_stop = true;
 		rc = 1;
@@ -1285,10 +1288,8 @@
 	/* read NIC's part number */
 	e100_rd_pwa_no(bdp);
 
-	if (!e100_hw_init(bdp)) {
-		printk(KERN_ERR "e100: hw init failed\n");
+	if (!e100_hw_init(bdp))
 		return false;
-	}
 	/* Interrupts are enabled after device reset */
 	e100_disable_clear_intr(bdp);
 
@@ -1330,6 +1331,8 @@
 	spin_lock_init(&(bdp->bd_non_tx_lock));
 	spin_lock_init(&(bdp->config_lock));
 	spin_lock_init(&(bdp->mdi_access_lock));
+	/* Initialize configuration data */
+	e100_config_init(bdp);
 
 	return 1;
 }
@@ -1384,11 +1387,11 @@
  *      true - If the adapter was initialized
  *      false - If the adapter failed initialization
  */
-unsigned char __devinit
+unsigned char
 e100_hw_init(struct e100_private *bdp)
 {
 	if (!e100_phy_init(bdp))
-		return false;
+		goto err;
 
 	e100_sw_reset(bdp, PORT_SELECTIVE_RESET);
 
@@ -1398,27 +1401,25 @@
 
 	/* Load the CU BASE (set to 0, because we use linear mode) */
 	if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0))
-		return false;
+		goto err;
 
 	if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0))
-		return false;
+		goto err;
 
 	/* Load interrupt microcode  */
 	if (e100_load_microcode(bdp)) {
 		bdp->flags |= DF_UCODE_LOADED;
 	}
 
-	e100_config_init(bdp);
-	if (!e100_config(bdp)) {
-		return false;
-	}
+	if (!e100_config(bdp))
+		goto err;
 
 	if (!e100_setup_iaaddr(bdp, bdp->device->dev_addr))
-		return false;
+		goto err;
 
 	/* Clear the internal counters */
 	if (!e100_clr_cntrs(bdp))
-		return false;
+		goto err;
 
 	/* Change for 82558 enhancement */
 	/* If 82558/9 and if the user has enabled flow control, set up the
@@ -1431,6 +1432,9 @@
 	}
 
 	return true;
+err:
+	printk(KERN_ERR "e100: hw init failed\n");
+	return false;
 }
 
 /**
@@ -1591,9 +1595,22 @@
 void
 e100_free_tcb_pool(struct e100_private *bdp)
 {
+	tcb_t *tcb;
+	int i;
+	/* Return tx skbs */ 
+	for (i = 0; i < bdp->params.TxDescriptors; i++) {
+	  	tcb = bdp->tcb_pool.data;
+		tcb += bdp->tcb_pool.head;
+  		e100_tx_skb_free(bdp, tcb);
+		if (NEXT_TCB_TOUSE(bdp->tcb_pool.head) == bdp->tcb_pool.tail)
+		  	break;
+		bdp->tcb_pool.head = NEXT_TCB_TOUSE(bdp->tcb_pool.head);
+	}
 	pci_free_consistent(bdp->pdev,
 			    sizeof (tcb_t) * bdp->params.TxDescriptors,
 			    bdp->tcb_pool.data, bdp->tcb_phys);
+	bdp->tcb_pool.head = 0;
+	bdp->tcb_pool.tail = 1;	
 	bdp->tcb_phys = 0;
 }
 
@@ -1747,12 +1764,10 @@
 				e100_set_multi(dev);
 			}
 		}
-
-		/* Update the statistics needed by the upper interface */
-		/* This should be the last statistic related command
-		 * as it's async. now */
-		e100_dump_stats_cntrs(bdp);
 	}
+	/* Issue command to dump statistics from device.        */
+	/* Check for command completion on next watchdog timer. */
+	e100_dump_stats_cntrs(bdp);
 
 	wmb();
 
@@ -2544,6 +2559,7 @@
 	pcmd_complete = e100_cmd_complete_location(bdp);
 	if (*pcmd_complete != le32_to_cpu(DUMP_RST_STAT_COMPLETED) &&
 	    *pcmd_complete != le32_to_cpu(DUMP_STAT_COMPLETED)) {
+		*pcmd_complete = 0;
 		return false;
 	}
 
@@ -3041,23 +3057,6 @@
 	e100_sw_reset(bdp, PORT_SELECTIVE_RESET);
 }
 
-void
-e100_set_speed_duplex(struct e100_private *bdp)
-{
-	int carrier_ok;
-	/* Device may lose link with some siwtches when */
-	/* changing speed/duplex to non-autoneg. e100   */
-	/* needs to remember carrier state in order to  */
-	/* start watchdog timer for recovering link     */
-	if ((carrier_ok = netif_carrier_ok(bdp->device)))
-		e100_isolate_driver(bdp);
-	e100_phy_set_speed_duplex(bdp, true);
-	e100_config_fc(bdp);	/* re-config flow-control if necessary */
-	e100_config(bdp);	
-	if (carrier_ok)
-		e100_deisolate_driver(bdp, false);
-}
-
 static void
 e100_tcb_add_C_bit(struct e100_private *bdp)
 {
@@ -3213,6 +3212,144 @@
 	case ETHTOOL_PHYS_ID:
 		rc = e100_ethtool_led_blink(dev,ifr);
 		break;
+#ifdef	ETHTOOL_GRINGPARAM
+	case ETHTOOL_GRINGPARAM: {
+		struct ethtool_ringparam ering;
+		struct e100_private *bdp = dev->priv;
+		memset((void *) &ering, 0, sizeof(ering));
+		ering.rx_max_pending = E100_MAX_RFD;
+		ering.tx_max_pending = E100_MAX_TCB;
+		ering.rx_pending = bdp->params.RxDescriptors;
+		ering.tx_pending = bdp->params.TxDescriptors;
+		rc = copy_to_user(ifr->ifr_data, &ering, sizeof(ering))
+			? -EFAULT : 0;
+		return rc;
+	}
+#endif
+#ifdef	ETHTOOL_SRINGPARAM
+	case ETHTOOL_SRINGPARAM: {
+		struct ethtool_ringparam ering;
+		struct e100_private *bdp = dev->priv;
+		if (copy_from_user(&ering, ifr->ifr_data, sizeof(ering)))
+			return -EFAULT;
+		if (ering.rx_pending > E100_MAX_RFD 
+		    || ering.rx_pending < E100_MIN_RFD)
+			return -EINVAL;
+		if (ering.tx_pending > E100_MAX_TCB 
+		    || ering.tx_pending < E100_MIN_TCB)
+			return -EINVAL;
+		if (netif_running(dev)) {
+			spin_lock_bh(&dev->xmit_lock);
+			e100_close(dev);
+			spin_unlock_bh(&dev->xmit_lock);
+			/* Use new values to open interface */
+			bdp->params.RxDescriptors = ering.rx_pending;
+			bdp->params.TxDescriptors = ering.tx_pending;
+			e100_hw_init(bdp);
+			e100_open(dev);
+		}
+		else {
+			bdp->params.RxDescriptors = ering.rx_pending;
+			bdp->params.TxDescriptors = ering.tx_pending;
+		}
+		return 0;
+	}
+#endif
+#ifdef	ETHTOOL_GPAUSEPARAM
+	case ETHTOOL_GPAUSEPARAM: {
+		struct ethtool_pauseparam epause;
+		struct e100_private *bdp = dev->priv;
+		memset((void *) &epause, 0, sizeof(epause));
+		if ((bdp->flags & IS_BACHELOR)
+		    && (bdp->params.b_params & PRM_FC)) {
+			epause.autoneg = 1;
+			if (bdp->flags && DF_LINK_FC_CAP) {
+				epause.rx_pause = 1;
+				epause.tx_pause = 1;
+			}
+			if (bdp->flags && DF_LINK_FC_TX_ONLY)
+				epause.tx_pause = 1;
+		}
+		rc = copy_to_user(ifr->ifr_data, &epause, sizeof(epause))
+			? -EFAULT : 0;
+		return rc;
+	}
+#endif
+#ifdef	ETHTOOL_SPAUSEPARAM
+	case ETHTOOL_SPAUSEPARAM: {
+		struct ethtool_pauseparam epause;
+		struct e100_private *bdp = dev->priv;
+		if (!(bdp->flags & IS_BACHELOR))
+			return -EINVAL;
+		if (copy_from_user(&epause, ifr->ifr_data, sizeof(epause)))
+			return -EFAULT;
+		if (epause.autoneg == 1)
+			bdp->params.b_params |= PRM_FC;
+		else
+			bdp->params.b_params &= ~PRM_FC;
+		if (netif_running(dev)) {
+			spin_lock_bh(&dev->xmit_lock);
+			e100_close(dev);
+			spin_unlock_bh(&dev->xmit_lock);
+			e100_hw_init(bdp);
+			e100_open(dev);
+		}
+		return 0;
+	}
+#endif
+#ifdef	ETHTOOL_GRXCSUM
+	case ETHTOOL_GRXCSUM:
+	case ETHTOOL_GTXCSUM:
+	case ETHTOOL_GSG:
+	{	struct ethtool_value eval;
+		struct e100_private *bdp = dev->priv;
+		memset((void *) &eval, 0, sizeof(eval));
+		if ((ecmd.cmd == ETHTOOL_GRXCSUM) 
+		    && (bdp->params.b_params & PRM_XSUMRX))
+			eval.data = 1;
+		else
+			eval.data = 0;
+		rc = copy_to_user(ifr->ifr_data, &eval, sizeof(eval))
+			? -EFAULT : 0;
+		return rc;
+	}
+#endif
+#ifdef	ETHTOOL_SRXCSUM
+	case ETHTOOL_SRXCSUM:
+	case ETHTOOL_STXCSUM:
+	case ETHTOOL_SSG:
+	{	struct ethtool_value eval;
+		struct e100_private *bdp = dev->priv;
+		if (copy_from_user(&eval, ifr->ifr_data, sizeof(eval)))
+			return -EFAULT;
+		if (ecmd.cmd == ETHTOOL_SRXCSUM) {
+			if (eval.data == 1) { 
+				if (bdp->rev_id >= D101MA_REV_ID)
+					bdp->params.b_params |= PRM_XSUMRX;
+				else
+					return -EINVAL;
+			} else {
+				if (bdp->rev_id >= D101MA_REV_ID)
+					bdp->params.b_params &= ~PRM_XSUMRX;
+				else
+					return 0;
+			}
+		} else {
+			if (eval.data == 1)
+				return -EINVAL;
+			else
+				return 0;
+		}
+		if (netif_running(dev)) {
+			spin_lock_bh(&dev->xmit_lock);
+			e100_close(dev);
+			spin_unlock_bh(&dev->xmit_lock);
+			e100_hw_init(bdp);
+			e100_open(dev);
+		}
+		return 0;
+	}
+#endif
 	default:
 		break;
 	}			//switch
@@ -3298,7 +3435,13 @@
 	if ((ecmd.autoneg == AUTONEG_ENABLE)
 	    && (bdp->speed_duplex_caps & SUPPORTED_Autoneg)) {
 		bdp->params.e100_speed_duplex = E100_AUTONEG;
-		e100_set_speed_duplex(bdp);
+		if (netif_running(dev)) {
+			spin_lock_bh(&dev->xmit_lock);
+			e100_close(dev);
+			spin_unlock_bh(&dev->xmit_lock);
+			e100_hw_init(bdp);
+			e100_open(dev);
+		}
 	} else {
 		if (ecmd.speed == SPEED_10) {
 			if (ecmd.duplex == DUPLEX_HALF) {
@@ -3329,7 +3472,13 @@
 		if (bdp->speed_duplex_caps & ethtool_new_speed_duplex) {
 			bdp->params.e100_speed_duplex =
 				e100_new_speed_duplex;
-			e100_set_speed_duplex(bdp);
+			if (netif_running(dev)) {
+				spin_lock_bh(&dev->xmit_lock);
+				e100_close(dev);
+				spin_unlock_bh(&dev->xmit_lock);
+				e100_hw_init(bdp);
+				e100_open(dev);
+			}
 		} else {
 			return -EOPNOTSUPP;
 		} 
@@ -3364,14 +3513,14 @@
 	struct ethtool_test *info;
 	int rc = -EFAULT;
 
-	info = kmalloc(sizeof(*info) + E100_MAX_TEST_RES * sizeof(u64),
+	info = kmalloc(sizeof(*info) + max_test_res * sizeof(u64),
 		       GFP_ATOMIC);
 
 	if (!info)
 		return -ENOMEM;
 
 	memset((void *) info, 0, sizeof(*info) +
-				 E100_MAX_TEST_RES * sizeof(u64));
+				 max_test_res * sizeof(u64));
 
 	if (copy_from_user(info, ifr->ifr_data, sizeof(*info)))
 		goto exit;
@@ -3379,7 +3528,7 @@
 	info->flags = e100_run_diag(dev, info->data, info->flags);
 
 	if (!copy_to_user(ifr->ifr_data, info,
-			 sizeof(*info) + E100_MAX_TEST_RES * sizeof(u64)))
+			 sizeof(*info) + max_test_res * sizeof(u64)))
 		rc = 0;
 exit:
 	kfree(info);
@@ -3393,6 +3542,7 @@
 	u32 regs_buff[E100_REGS_LEN];
 	struct ethtool_regs regs = {ETHTOOL_GREGS};
 	void *addr = ifr->ifr_data;
+	u16 mdi_reg;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
@@ -3405,6 +3555,8 @@
 	regs_buff[0] = readb(&(bdp->scb->scb_cmd_hi)) << 24 |
 		readb(&(bdp->scb->scb_cmd_low)) << 16 |
 		readw(&(bdp->scb->scb_status));
+	e100_mdi_read(bdp, MII_NCONFIG, bdp->phy_addr, &mdi_reg);
+	regs_buff[1] = mdi_reg;
 
 	if(copy_to_user(addr, &regs, sizeof(regs)))
 		return -EFAULT;
@@ -3428,7 +3580,13 @@
 
 	if ((bdp->speed_duplex_caps & SUPPORTED_Autoneg) &&
 	    (bdp->params.e100_speed_duplex == E100_AUTONEG)) {
-		e100_set_speed_duplex(bdp);
+		if (netif_running(dev)) {
+			spin_lock_bh(&dev->xmit_lock);
+			e100_close(dev);
+			spin_unlock_bh(&dev->xmit_lock);
+			e100_hw_init(bdp);
+			e100_open(dev);
+		}
 	} else {
 		return -EFAULT;
 	}
@@ -3454,7 +3612,7 @@
 	info.n_stats = E100_STATS_LEN;
 	info.regdump_len  = E100_REGS_LEN * sizeof(u32);
 	info.eedump_len = (bdp->eeprom_size << 1);	
-	info.testinfo_len = E100_MAX_TEST_RES;
+	info.testinfo_len = max_test_res;
 	if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
 		return -EFAULT;
 
@@ -3804,15 +3962,15 @@
 	switch (info.string_set) {
 	case ETH_SS_TEST: {
 		int ret = 0;
-		if (info.len > E100_MAX_TEST_RES)
-			info.len = E100_MAX_TEST_RES;
+		if (info.len > max_test_res)
+			info.len = max_test_res;
 		strings = kmalloc(info.len * ETH_GSTRING_LEN, GFP_ATOMIC);
 		if (!strings)
 			return -ENOMEM;
 		memset(strings, 0, info.len * ETH_GSTRING_LEN);
 
 		for (i = 0; i < info.len; i++) {
-			sprintf(strings + i * ETH_GSTRING_LEN, "%-31s",
+			sprintf(strings + i * ETH_GSTRING_LEN, "%s",
 				test_strings[i]);
 		}
 		if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
@@ -3881,7 +4039,13 @@
 					bdp->params.e100_speed_duplex = E100_SPEED_10_FULL;
 				else
 					bdp->params.e100_speed_duplex = E100_SPEED_10_HALF;
-				e100_set_speed_duplex(bdp);
+				if (netif_running(dev)) {
+					spin_lock_bh(&dev->xmit_lock);
+					e100_close(dev);
+					spin_unlock_bh(&dev->xmit_lock);
+					e100_hw_init(bdp);
+					e100_open(dev);
+				}
 		}
 		else 
 			/* Only allows changing speed/duplex */
@@ -4164,7 +4328,6 @@
 
 	return 0;
 }
-#endif /* CONFIG_PM */
 
 /**
  * e100_asf_enabled - checks if ASF is configured on the current adaper
@@ -4190,6 +4353,7 @@
 	}
 	return false;
 }
+#endif /* CONFIG_PM */
 
 #ifdef E100_CU_DEBUG
 unsigned char
diff -urN linux-2.5.69-bk18/drivers/net/e100/e100_phy.c linux-2.5.69-bk19/drivers/net/e100/e100_phy.c
--- linux-2.5.69-bk18/drivers/net/e100/e100_phy.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/e100/e100_phy.c	2003-05-26 04:41:42.000000000 -0700
@@ -628,8 +628,6 @@
 	u16 control;
 	unsigned long expires;
 
-	e100_phy_reset(bdp);
-
 	bdp->flags |= DF_SPEED_FORCED;
 
 	e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control);
@@ -912,6 +910,10 @@
 	u16 ctrl_reg;
 	ctrl_reg = BMCR_RESET;
 	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg);
+	/* ieee 802.3 : The reset process shall be completed       */
+	/* within 0.5 seconds from the settting of PHY reset bit.  */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ / 2);
 }
 
 unsigned char __devinit
@@ -928,6 +930,7 @@
 	bdp->PhyDelay = 0;
 	bdp->zlock_state = ZLOCK_INITIAL;
 
+	e100_phy_reset(bdp);
 	e100_phy_set_speed_duplex(bdp, false);
 	e100_fix_polarity(bdp);
 
diff -urN linux-2.5.69-bk18/drivers/net/e100/e100_test.c linux-2.5.69-bk19/drivers/net/e100/e100_test.c
--- linux-2.5.69-bk18/drivers/net/e100/e100_test.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/e100/e100_test.c	2003-05-26 04:41:42.000000000 -0700
@@ -25,7 +25,7 @@
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *******************************************************************************/
 
-#include "e100.h"
+#include "e100_phy.h"
 #include "e100_config.h"
 
 extern u16 e100_eeprom_read(struct e100_private *, u16);
@@ -46,6 +46,7 @@
 static void e100_diag_loopback_cu_ru_exec(struct e100_private *);
 static u8 e100_diag_check_pkt(u8 *);
 static void e100_diag_loopback_free(struct e100_private *);
+static int e100_cable_diag(struct e100_private *bdp);
 
 #define LB_PACKET_SIZE 1500
 
@@ -60,46 +61,52 @@
 e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags)
 {
 	struct e100_private* bdp = dev->priv;
-	u8 test_result = true;
-
-	e100_isolate_driver(bdp);
+	u8 test_result = 0;
 
+	if (!e100_get_link_state(bdp)) {
+		test_result = ETH_TEST_FL_FAILED;
+		test_info[test_link] = true;
+	}
+	if (!e100_diag_eeprom(dev)) {
+		test_result = ETH_TEST_FL_FAILED;
+		test_info[test_eeprom] = true;
+	}
 	if (flags & ETH_TEST_FL_OFFLINE) {
 		u8 fail_mask;
-		
-		fail_mask = e100_diag_selftest(dev);
-		if (fail_mask) {
-			test_result = false;
-			if (fail_mask & REGISTER_TEST_FAIL)
-				test_info [E100_REG_TEST_FAIL] = true;
-			if (fail_mask & ROM_TEST_FAIL)
-				test_info [E100_ROM_TEST_FAIL] = true;
-			if (fail_mask & SELF_TEST_FAIL)
-				test_info [E100_MAC_TEST_FAIL] = true;
-			if (fail_mask & TEST_TIMEOUT)
-				test_info [E100_CHIP_TIMEOUT] = true;
+		if (netif_running(dev)) {
+			spin_lock_bh(&dev->xmit_lock);
+			e100_close(dev);
+			spin_unlock_bh(&dev->xmit_lock);
+		}
+		if (e100_diag_selftest(dev)) {
+			test_result = ETH_TEST_FL_FAILED;
+			test_info[test_self_test] = true;
 		}
 
 		fail_mask = e100_diag_loopback(dev);
 		if (fail_mask) {
-			test_result = false;
+			test_result = ETH_TEST_FL_FAILED;
 			if (fail_mask & PHY_LOOPBACK)
-				test_info [E100_LPBK_PHY_FAIL] = true;
+				test_info[test_loopback_phy] = true;
 			if (fail_mask & MAC_LOOPBACK)
-				test_info [E100_LPBK_MAC_FAIL] = true;
+				test_info[test_loopback_mac] = true;
 		}
-	}
 
-	if (!e100_diag_eeprom(dev)) {
-		test_result = false;
-		test_info [E100_EEPROM_TEST_FAIL] = true;
+		test_info[cable_diag] = e100_cable_diag(bdp);
+		/* Need hw init regardless of netif_running */
+		e100_hw_init(bdp);
+		if (netif_running(dev)) {
+			e100_open(dev);
+		}
+	}
+	else {
+		test_info[test_self_test] = false;
+		test_info[test_loopback_phy] = false;
+		test_info[test_loopback_mac] = false;
+		test_info[cable_diag] = false;
 	}
 
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ * 2);
-    	e100_deisolate_driver(bdp, false);
-
-	return flags | (test_result ? 0 : ETH_TEST_FL_FAILED);
+	return flags | test_result;
 }
 
 /**
@@ -126,8 +133,6 @@
 		}
 	}
 
-	e100_configure_device(bdp);
-
 	return retval;
 }
 
@@ -165,14 +170,14 @@
 	u8 rc = 0;
 
 	printk(KERN_DEBUG "%s: PHY loopback test starts\n", dev->name);
-	e100_sw_reset(dev->priv, PORT_SELECTIVE_RESET);
+	e100_hw_init(dev->priv);
 	if (!e100_diag_one_loopback(dev, PHY_LOOPBACK)) {
 		rc |= PHY_LOOPBACK;
 	}
 	printk(KERN_DEBUG "%s: PHY loopback test ends\n", dev->name);
 
 	printk(KERN_DEBUG "%s: MAC loopback test starts\n", dev->name);
-	e100_sw_reset(dev->priv, PORT_SELECTIVE_RESET);
+	e100_hw_init(dev->priv);
 	if (!e100_diag_one_loopback(dev, MAC_LOOPBACK)) {
 		rc |= MAC_LOOPBACK;
 	}
@@ -257,15 +262,10 @@
 		if (set_loopback)
                         /* Set PHY loopback mode */
                         e100_phy_set_loopback(bdp);
-                else {	/* Back to normal speed and duplex */
-                	if (bdp->params.e100_speed_duplex == E100_AUTONEG)
-				/* Reset PHY and do autoneg */
-                        	e100_phy_autoneg(bdp);
-			else    
-				/* Reset PHY and force speed and duplex */
-				e100_force_speed_duplex(bdp);
-		}
-                /* Wait for PHY state change */
+		else
+			/* Reset PHY loopback mode */
+			e100_phy_reset(bdp);	
+		/* Wait for PHY state change */
 		set_current_state(TASK_UNINTERRUPTIBLE);
                 schedule_timeout(HZ);
 	} else { /* For MAC loopback wait 500 msec to take effect */
@@ -348,10 +348,6 @@
 e100_diag_loopback_cu_ru_exec(struct e100_private *bdp)
 {
 	/*load CU & RU base */ 
-	if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0))
-		printk(KERN_ERR "e100: SCB_CUC_LOAD_BASE failed\n");
-	if(!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0))
-		printk(KERN_ERR "e100: SCB_RUC_LOAD_BASE failed!\n");
 	if(!e100_wait_exec_cmplx(bdp, bdp->loopback.dma_handle, SCB_RUC_START, 0))
 		printk(KERN_ERR "e100: SCB_RUC_START failed!\n");
 
@@ -433,3 +429,72 @@
 			    bdp->loopback.dma_handle);
 }
 
+static int
+e100_cable_diag(struct e100_private *bdp)
+{	
+	int saved_open_circut = 0xffff;
+	int saved_short_circut = 0xffff;
+	int saved_distance = 0xffff;
+	int saved_same = 0;
+	int cable_status = E100_CABLE_UNKNOWN;
+	int i;
+	
+	/* If we have link, */	
+	if (e100_get_link_state(bdp))
+		return E100_CABLE_OK;
+	
+	if (bdp->rev_id < D102_REV_ID)
+		return E100_CABLE_UNKNOWN;
+
+	/* Disable MDI/MDI-X auto switching */
+        e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr,
+		MDI_MDIX_RESET_ALL_MASK);
+	/* Set to 100 Full as required by cable test */
+	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr,
+		BMCR_SPEED100 | BMCR_FULLDPLX);
+
+	/* Test up to 100 times */
+	for (i = 0; i < 100; i++) {
+		u16 ctrl_reg;
+		int distance, open_circut, short_circut, near_end;
+
+		/* Enable and execute cable test */
+		e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr,
+			(HWI_TEST_ENABLE | HWI_TEST_EXECUTE));
+		/* Wait for cable test finished */
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ/100 + 1);
+		/* Read results */
+		e100_mdi_read(bdp, HWI_CONTROL_REG, bdp->phy_addr, &ctrl_reg);
+		distance = ctrl_reg & HWI_TEST_DISTANCE;
+		open_circut = ctrl_reg & HWI_TEST_HIGHZ_PROBLEM;
+		short_circut = ctrl_reg & HWI_TEST_LOWZ_PROBLEM;
+
+		if ((distance == saved_distance) &&
+	    	    (open_circut == saved_open_circut) &&
+	    	    (short_circut == saved_short_circut)) 
+			saved_same++;
+		else {
+			saved_same = 0;
+			saved_distance = distance;
+			saved_open_circut = open_circut;
+			saved_short_circut = short_circut;
+		}
+		/* If results are the same 3 times */
+		if (saved_same == 3) {
+			near_end = ((distance * HWI_REGISTER_GRANULARITY) <
+			       HWI_NEAR_END_BOUNDARY);
+			if (open_circut)
+				cable_status = (near_end) ? 
+					E100_CABLE_OPEN_NEAR : E100_CABLE_OPEN_FAR;
+			if (short_circut)
+				cable_status = (near_end) ?
+					E100_CABLE_SHORT_NEAR : E100_CABLE_SHORT_FAR;
+			break;
+		}
+	}
+	/* Reset cable test */
+        e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr,					       HWI_RESET_ALL_MASK);
+	return cable_status;
+}
+
diff -urN linux-2.5.69-bk18/drivers/net/e1000/Makefile linux-2.5.69-bk19/drivers/net/e1000/Makefile
--- linux-2.5.69-bk18/drivers/net/e1000/Makefile	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/e1000/Makefile	2003-05-26 04:41:42.000000000 -0700
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # 
-# Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved.
+# Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
 # 
 # This program is free software; you can redistribute it and/or modify it 
 # under the terms of the GNU General Public License as published by the Free 
diff -urN linux-2.5.69-bk18/drivers/net/e1000/e1000.h linux-2.5.69-bk19/drivers/net/e1000/e1000.h
--- linux-2.5.69-bk18/drivers/net/e1000/e1000.h	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/e1000/e1000.h	2003-05-26 04:41:42.000000000 -0700
@@ -134,6 +134,7 @@
 	uint64_t dma;
 	unsigned long length;
 	unsigned long time_stamp;
+	unsigned int next_to_watch;
 };
 
 struct e1000_desc_ring {
@@ -169,7 +170,6 @@
 	struct timer_list watchdog_timer;
 	struct timer_list phy_info_timer;
 	struct vlan_group *vlgrp;
-	char *id_string;
 	uint32_t bd_number;
 	uint32_t rx_buffer_len;
 	uint32_t part_num;
@@ -218,6 +218,9 @@
 	struct e1000_phy_info phy_info;
 	struct e1000_phy_stats phy_stats;
 
+	uint32_t test_icr;
+	struct e1000_desc_ring test_tx_ring;
+	struct e1000_desc_ring test_rx_ring;
 
 
 	uint32_t pci_state[16];
diff -urN linux-2.5.69-bk18/drivers/net/e1000/e1000_ethtool.c linux-2.5.69-bk19/drivers/net/e1000/e1000_ethtool.c
--- linux-2.5.69-bk18/drivers/net/e1000/e1000_ethtool.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/e1000/e1000_ethtool.c	2003-05-26 04:41:42.000000000 -0700
@@ -40,15 +40,60 @@
 extern void e1000_reset(struct e1000_adapter *adapter);
 extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
 
-static char e1000_gstrings_stats[][ETH_GSTRING_LEN] = {
-	"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
-	"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
-	"rx_length_errors", "rx_over_errors", "rx_crc_errors",
-	"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
-	"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
-	"tx_heartbeat_errors", "tx_window_errors",
+struct e1000_stats {
+	char stat_string[ETH_GSTRING_LEN];
+	int sizeof_stat;
+	int stat_offset;
 };
-#define E1000_STATS_LEN	sizeof(e1000_gstrings_stats) / ETH_GSTRING_LEN
+
+#define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \
+		      offsetof(struct e1000_adapter, m)
+static struct e1000_stats e1000_gstrings_stats[] = {
+	{ "rx_packets", E1000_STAT(net_stats.rx_packets) },
+	{ "tx_packets", E1000_STAT(net_stats.tx_packets) },
+	{ "rx_bytes", E1000_STAT(net_stats.rx_bytes) },
+	{ "tx_bytes", E1000_STAT(net_stats.tx_bytes) },
+	{ "rx_errors", E1000_STAT(net_stats.rx_errors) },
+	{ "tx_errors", E1000_STAT(net_stats.tx_errors) },
+	{ "rx_dropped", E1000_STAT(net_stats.rx_dropped) },
+	{ "tx_dropped", E1000_STAT(net_stats.tx_dropped) },
+	{ "multicast", E1000_STAT(net_stats.multicast) },
+	{ "collisions", E1000_STAT(net_stats.collisions) },
+	{ "rx_length_errors", E1000_STAT(net_stats.rx_length_errors) },
+	{ "rx_over_errors", E1000_STAT(net_stats.rx_over_errors) },
+	{ "rx_crc_errors", E1000_STAT(net_stats.rx_crc_errors) },
+	{ "rx_frame_errors", E1000_STAT(net_stats.rx_frame_errors) },
+	{ "rx_fifo_errors", E1000_STAT(net_stats.rx_fifo_errors) },
+	{ "rx_missed_errors", E1000_STAT(net_stats.rx_missed_errors) },
+	{ "tx_aborted_errors", E1000_STAT(net_stats.tx_aborted_errors) },
+	{ "tx_carrier_errors", E1000_STAT(net_stats.tx_carrier_errors) },
+	{ "tx_fifo_errors", E1000_STAT(net_stats.tx_fifo_errors) },
+	{ "tx_heartbeat_errors", E1000_STAT(net_stats.tx_heartbeat_errors) },
+	{ "tx_window_errors", E1000_STAT(net_stats.tx_window_errors) },
+	{ "tx_abort_late_coll", E1000_STAT(stats.latecol) },
+	{ "tx_deferred_ok", E1000_STAT(stats.dc) },
+	{ "tx_single_coll_ok", E1000_STAT(stats.scc) },
+	{ "tx_multi_coll_ok", E1000_STAT(stats.mcc) },
+	{ "rx_long_length_errors", E1000_STAT(stats.roc) },
+	{ "rx_short_length_errors", E1000_STAT(stats.ruc) },
+	{ "rx_align_errors", E1000_STAT(stats.algnerrc) },
+	{ "tx_tcp_seg_good", E1000_STAT(stats.tsctc) },
+	{ "tx_tcp_seg_failed", E1000_STAT(stats.tsctfc) },
+	{ "rx_flow_control_xon", E1000_STAT(stats.xonrxc) },
+	{ "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) },
+	{ "tx_flow_control_xon", E1000_STAT(stats.xontxc) },
+	{ "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
+	{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
+	{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }
+};
+#define E1000_STATS_LEN	\
+	sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
+static char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
+	"Register test  (offline)", "Eeprom test    (offline)",
+	"Interrupt test (offline)", "Loopback test  (offline)",
+	"Link test   (on/offline)"
+};
+#define E1000_TEST_LEN sizeof(e1000_gstrings_test) / ETH_GSTRING_LEN
 
 static void
 e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
@@ -154,6 +199,7 @@
 	strncpy(drvinfo->fw_version, "N/A", 32);
 	strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32);
 	drvinfo->n_stats = E1000_STATS_LEN;
+	drvinfo->testinfo_len = E1000_TEST_LEN;
 #define E1000_REGS_LEN 32
 	drvinfo->regdump_len  = E1000_REGS_LEN * sizeof(uint32_t);
 	drvinfo->eedump_len = adapter->hw.eeprom.word_size * 2;
@@ -164,6 +210,7 @@
                     struct ethtool_regs *regs, uint32_t *regs_buff)
 {
 	struct e1000_hw *hw = &adapter->hw;
+	uint16_t phy_data;
 
 	regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
 
@@ -182,6 +229,62 @@
 	regs_buff[10] = E1000_READ_REG(hw, TDT);
 	regs_buff[11] = E1000_READ_REG(hw, TIDV);
 
+	regs_buff[12] = adapter->hw.phy_type;  /* PHY type (IGP=1, M88=0) */
+	if(hw->phy_type == e1000_phy_igp) {
+		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+				    IGP01E1000_PHY_AGC_A);
+		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A &
+				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+		regs_buff[13] = (uint32_t)phy_data; /* cable length */
+		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+				    IGP01E1000_PHY_AGC_B);
+		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_B &
+				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+		regs_buff[14] = (uint32_t)phy_data; /* cable length */
+		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+				    IGP01E1000_PHY_AGC_C);
+		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_C &
+				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+		regs_buff[15] = (uint32_t)phy_data; /* cable length */
+		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+				    IGP01E1000_PHY_AGC_D);
+		e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_D &
+				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+		regs_buff[16] = (uint32_t)phy_data; /* cable length */
+		regs_buff[17] = 0; /* extended 10bt distance (not needed) */
+		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
+		e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS &
+				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+		regs_buff[18] = (uint32_t)phy_data; /* cable polarity */
+		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+				    IGP01E1000_PHY_PCS_INIT_REG);
+		e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG &
+				   IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+		regs_buff[19] = (uint32_t)phy_data; /* cable polarity */
+		regs_buff[20] = 0; /* polarity correction enabled (always) */
+		regs_buff[22] = 0; /* phy receive errors (unavailable) */
+		regs_buff[23] = regs_buff[18]; /* mdix mode */
+		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
+	} else {
+        	e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+		regs_buff[13] = (uint32_t)phy_data; /* cable length */
+		regs_buff[14] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
+		regs_buff[15] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
+		regs_buff[16] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
+        	e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+		regs_buff[17] = (uint32_t)phy_data; /* extended 10bt distance */
+		regs_buff[18] = regs_buff[13]; /* cable polarity */
+		regs_buff[19] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
+		regs_buff[20] = regs_buff[17]; /* polarity correction */
+		/* phy receive errors */
+		regs_buff[22] = adapter->phy_stats.receive_errors;
+		regs_buff[23] = regs_buff[13]; /* mdix mode */
+	}
+	regs_buff[21] = adapter->phy_stats.idle_errors;  /* phy idle errors */
+	e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
+	regs_buff[24] = (uint32_t)phy_data;  /* phy local receiver status */
+	regs_buff[25] = regs_buff[24];  /* phy remote receiver status */
+
 	return;
 }
 
@@ -219,7 +322,7 @@
 		uint16_t i;
 		for (i = 0; i < last_word - first_word + 1; i++)
 			if((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
-						       &eeprom_buff[i])))
+							&eeprom_buff[i])))
 				break;
 	}
 geeprom_error:
@@ -249,7 +352,7 @@
 	first_word = eeprom->offset >> 1;
 	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
 	eeprom_buff = kmalloc(max_len, GFP_KERNEL);
-	if(eeprom_buff == NULL)
+	if(!eeprom_buff)
 		return -ENOMEM;
 
 	ptr = (void *)eeprom_buff;
@@ -284,6 +387,765 @@
 	return ret_val;
 }
 
+#define REG_PATTERN_TEST(R, M, W)                                              \
+{                                                                              \
+	uint32_t pat, value;                                                   \
+	uint32_t test[] =                                                      \
+		{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};              \
+	for(pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) {              \
+		E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W));             \
+		value = E1000_READ_REG(&adapter->hw, R);                       \
+		if(value != (test[pat] & W & M)) {                             \
+			*data = (adapter->hw.mac_type < e1000_82543) ?         \
+				E1000_82542_##R : E1000_##R;                   \
+			return 1;                                              \
+		}                                                              \
+	}                                                                      \
+}
+
+#define REG_SET_AND_CHECK(R, M, W)                                             \
+{                                                                              \
+	uint32_t value;                                                        \
+	E1000_WRITE_REG(&adapter->hw, R, W & M);                               \
+	value = E1000_READ_REG(&adapter->hw, R);                               \
+	if ((W & M) != (value & M)) {                                          \
+		*data = (adapter->hw.mac_type < e1000_82543) ?                 \
+			E1000_82542_##R : E1000_##R;                           \
+		return 1;                                                      \
+	}                                                                      \
+}
+
+static int
+e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
+{
+	uint32_t value;
+	uint32_t i;
+
+	/* The status register is Read Only, so a write should fail.
+	 * Some bits that get toggled are ignored.
+	 */
+	value = (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833));
+	E1000_WRITE_REG(&adapter->hw, STATUS, (0xFFFFFFFF));
+	if(value != (E1000_READ_REG(&adapter->hw, STATUS) & (0xFFFFF833))) {
+		*data = 1;
+		return 1;
+	}
+
+	REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
+	REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
+	REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
+	REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF);
+	REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF);
+	REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
+	REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF);
+	REG_PATTERN_TEST(RDH, 0x0000FFFF, 0x0000FFFF);
+	REG_PATTERN_TEST(RDT, 0x0000FFFF, 0x0000FFFF);
+	REG_PATTERN_TEST(FCRTH, 0x0000FFF8, 0x0000FFF8);
+	REG_PATTERN_TEST(FCTTV, 0x0000FFFF, 0x0000FFFF);
+	REG_PATTERN_TEST(TIPG, 0x3FFFFFFF, 0x3FFFFFFF);
+	REG_PATTERN_TEST(TDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
+	REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF);
+
+	REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000);
+	REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0x003FFFFB);
+	REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
+
+	if(adapter->hw.mac_type >= e1000_82543) {
+
+		REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0xFFFFFFFF);
+		REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
+		REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);
+		REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
+		REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
+
+		for(i = 0; i < E1000_RAR_ENTRIES; i++) {
+			REG_PATTERN_TEST(RA + ((i << 1) << 2), 0xFFFFFFFF,
+					 0xFFFFFFFF);
+			REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
+					 0xFFFFFFFF);
+		}
+
+	} else {
+
+		REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x01FFFFFF);
+		REG_PATTERN_TEST(RDBAL, 0xFFFFF000, 0xFFFFFFFF);
+		REG_PATTERN_TEST(TXCW, 0x0000FFFF, 0x0000FFFF);
+		REG_PATTERN_TEST(TDBAL, 0xFFFFF000, 0xFFFFFFFF);
+
+	}
+
+	for(i = 0; i < E1000_MC_TBL_SIZE; i++)
+		REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
+
+	return 0;
+}
+
+static int
+e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
+{
+	uint16_t temp;
+	uint16_t checksum = 0;
+	uint16_t i;
+
+	*data = 0;
+	/* Read and add up the contents of the EEPROM */
+	for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
+		if((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {
+			*data = 1;
+			break;
+		}
+		checksum += temp;
+	}
+
+	/* If Checksum is not Correct return error else test passed */
+	if((checksum != (uint16_t) EEPROM_SUM) && !(*data))
+		*data = 2;
+
+	return *data;
+}
+
+static irqreturn_t
+e1000_test_intr(int irq,
+		void *data,
+		struct pt_regs *regs)
+{
+	struct net_device *netdev = (struct net_device *) data;
+	struct e1000_adapter *adapter = netdev->priv;
+
+	adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR);
+
+	return IRQ_HANDLED;
+}
+
+static int
+e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
+{
+	struct net_device *netdev = adapter->netdev;
+	uint32_t icr, mask, i=0;
+
+	*data = 0;
+
+	/* Hook up test interrupt handler just for this test */
+	if(request_irq
+	   (netdev->irq, &e1000_test_intr, SA_SHIRQ, netdev->name, netdev)) {
+		*data = 1;
+		return -1;
+	}
+
+	/* Disable all the interrupts */
+	E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
+	msec_delay(10);
+
+	/* Interrupts are disabled, so read interrupt cause
+	 * register (icr) twice to verify that there are no interrupts
+	 * pending.  icr is clear on read.
+	 */
+	icr = E1000_READ_REG(&adapter->hw, ICR);
+	icr = E1000_READ_REG(&adapter->hw, ICR);
+
+	if(icr != 0) {
+		/* if icr is non-zero, there is no point
+		 * running other interrupt tests.
+		 */
+		*data = 2;
+		i = 10;
+	}
+
+	/* Test each interrupt */
+	for(; i < 10; i++) {
+
+		/* Interrupt to test */
+		mask = 1 << i;
+
+		/* Disable the interrupt to be reported in
+		 * the cause register and then force the same
+		 * interrupt and see if one gets posted.  If
+		 * an interrupt was posted to the bus, the
+		 * test failed.
+		 */
+		adapter->test_icr = 0;
+		E1000_WRITE_REG(&adapter->hw, IMC, mask);
+		E1000_WRITE_REG(&adapter->hw, ICS, mask);
+		msec_delay(10);
+
+		if(adapter->test_icr & mask) {
+			*data = 3;
+			break;
+		}
+
+		/* Enable the interrupt to be reported in
+		 * the cause register and then force the same
+		 * interrupt and see if one gets posted.  If
+		 * an interrupt was not posted to the bus, the
+		 * test failed.
+		 */
+		adapter->test_icr = 0;
+		E1000_WRITE_REG(&adapter->hw, IMS, mask);
+		E1000_WRITE_REG(&adapter->hw, ICS, mask);
+		msec_delay(10);
+
+		if(!(adapter->test_icr & mask)) {
+			*data = 4;
+			break;
+		}
+
+		/* Disable the other interrupts to be reported in
+		 * the cause register and then force the other
+		 * interrupts and see if any get posted.  If
+		 * an interrupt was posted to the bus, the
+		 * test failed.
+		 */
+		adapter->test_icr = 0;
+		E1000_WRITE_REG(&adapter->hw, IMC, ~mask);
+		E1000_WRITE_REG(&adapter->hw, ICS, ~mask);
+		msec_delay(10);
+
+		if(adapter->test_icr) {
+			*data = 5;
+			break;
+		}
+	}
+
+	/* Disable all the interrupts */
+	E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
+	msec_delay(10);
+
+	/* Unhook test interrupt handler */
+	free_irq(netdev->irq, netdev);
+
+	return *data;
+}
+
+static void
+e1000_free_desc_rings(struct e1000_adapter *adapter)
+{
+	struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
+	struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+	struct pci_dev *pdev = adapter->pdev;
+	int i;
+
+	if(txdr->desc && txdr->buffer_info) {
+		for(i = 0; i < txdr->count; i++) {
+			if(txdr->buffer_info[i].dma)
+				pci_unmap_single(pdev, txdr->buffer_info[i].dma,
+						 txdr->buffer_info[i].length,
+						 PCI_DMA_TODEVICE);
+			if(txdr->buffer_info[i].skb)
+				dev_kfree_skb(txdr->buffer_info[i].skb);
+		}
+	}
+
+	if(rxdr->desc && rxdr->buffer_info) {
+		for(i = 0; i < rxdr->count; i++) {
+			if(rxdr->buffer_info[i].dma)
+				pci_unmap_single(pdev, rxdr->buffer_info[i].dma,
+						 rxdr->buffer_info[i].length,
+						 PCI_DMA_FROMDEVICE);
+			if(rxdr->buffer_info[i].skb)
+				dev_kfree_skb(rxdr->buffer_info[i].skb);
+		}
+	}
+
+	if(txdr->desc)
+		pci_free_consistent(pdev, txdr->size, txdr->desc, txdr->dma);
+	if(rxdr->desc)
+		pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma);
+
+	if(txdr->buffer_info)
+		kfree(txdr->buffer_info);
+	if(rxdr->buffer_info)
+		kfree(rxdr->buffer_info);
+
+	return;
+}
+
+static int
+e1000_setup_desc_rings(struct e1000_adapter *adapter)
+{
+	struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
+	struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+	struct pci_dev *pdev = adapter->pdev;
+	uint32_t rctl;
+	int size, i, ret_val;
+
+	/* Setup Tx descriptor ring and Tx buffers */
+
+	txdr->count = 80;
+
+	size = txdr->count * sizeof(struct e1000_buffer);
+	if(!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
+		ret_val = 1;
+		goto err_nomem;
+	}
+	memset(txdr->buffer_info, 0, size);
+
+	txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
+	E1000_ROUNDUP(txdr->size, 4096);
+	if(!(txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma))) {
+		ret_val = 2;
+		goto err_nomem;
+	}
+	memset(txdr->desc, 0, txdr->size);
+	txdr->next_to_use = txdr->next_to_clean = 0;
+
+	E1000_WRITE_REG(&adapter->hw, TDBAL,
+			((uint64_t) txdr->dma & 0x00000000FFFFFFFF));
+	E1000_WRITE_REG(&adapter->hw, TDBAH, ((uint64_t) txdr->dma >> 32));
+	E1000_WRITE_REG(&adapter->hw, TDLEN,
+			txdr->count * sizeof(struct e1000_tx_desc));
+	E1000_WRITE_REG(&adapter->hw, TDH, 0);
+	E1000_WRITE_REG(&adapter->hw, TDT, 0);
+	E1000_WRITE_REG(&adapter->hw, TCTL,
+			E1000_TCTL_PSP | E1000_TCTL_EN |
+			E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
+			E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
+
+	for(i = 0; i < txdr->count; i++) {
+		struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i);
+		struct sk_buff *skb;
+		unsigned int size = 1024;
+
+		if(!(skb = alloc_skb(size, GFP_KERNEL))) {
+			ret_val = 3;
+			goto err_nomem;
+		}
+		skb_put(skb, size);
+		txdr->buffer_info[i].skb = skb;
+		txdr->buffer_info[i].length = skb->len;
+		txdr->buffer_info[i].dma =
+			pci_map_single(pdev, skb->data, skb->len,
+				       PCI_DMA_TODEVICE);
+		tx_desc->buffer_addr = cpu_to_le64(txdr->buffer_info[i].dma);
+		tx_desc->lower.data = cpu_to_le32(skb->len);
+		tx_desc->lower.data |= E1000_TXD_CMD_EOP;
+		tx_desc->lower.data |= E1000_TXD_CMD_IFCS;
+		tx_desc->lower.data |= E1000_TXD_CMD_RPS;
+		tx_desc->upper.data = 0;
+	}
+
+	/* Setup Rx descriptor ring and Rx buffers */
+
+	rxdr->count = 80;
+
+	size = rxdr->count * sizeof(struct e1000_buffer);
+	if(!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
+		ret_val = 4;
+		goto err_nomem;
+	}
+	memset(rxdr->buffer_info, 0, size);
+
+	rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
+	if(!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) {
+		ret_val = 5;
+		goto err_nomem;
+	}
+	memset(rxdr->desc, 0, rxdr->size);
+	rxdr->next_to_use = rxdr->next_to_clean = 0;
+
+	rctl = E1000_READ_REG(&adapter->hw, RCTL);
+	E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
+	E1000_WRITE_REG(&adapter->hw, RDBAL,
+			((uint64_t) rxdr->dma & 0xFFFFFFFF));
+	E1000_WRITE_REG(&adapter->hw, RDBAH, ((uint64_t) rxdr->dma >> 32));
+	E1000_WRITE_REG(&adapter->hw, RDLEN, rxdr->size);
+	E1000_WRITE_REG(&adapter->hw, RDH, 0);
+	E1000_WRITE_REG(&adapter->hw, RDT, 0);
+	rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
+		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
+		(adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
+	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+
+	for(i = 0; i < rxdr->count; i++) {
+		struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i);
+		struct sk_buff *skb;
+
+		if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + 2, GFP_KERNEL))) {
+			ret_val = 6;
+			goto err_nomem;
+		}
+		skb_reserve(skb, 2);
+		rxdr->buffer_info[i].skb = skb;
+		rxdr->buffer_info[i].length = E1000_RXBUFFER_2048;
+		rxdr->buffer_info[i].dma =
+			pci_map_single(pdev, skb->data, E1000_RXBUFFER_2048,
+				       PCI_DMA_FROMDEVICE);
+		rx_desc->buffer_addr = cpu_to_le64(rxdr->buffer_info[i].dma);
+		memset(skb->data, 0x00, skb->len);
+	}
+
+	return 0;
+
+      err_nomem:
+	e1000_free_desc_rings(adapter);
+	return ret_val;
+}
+
+static void
+e1000_phy_disable_receiver(struct e1000_adapter *adapter)
+{
+	/* Write out to PHY registers 29 and 30 to disable the Receiver. */
+	e1000_write_phy_reg(&adapter->hw, 29, 0x001F);
+	e1000_write_phy_reg(&adapter->hw, 30, 0x8FFC);
+	e1000_write_phy_reg(&adapter->hw, 29, 0x001A);
+	e1000_write_phy_reg(&adapter->hw, 30, 0x8FF0);
+
+	return;
+}
+
+static void
+e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
+{
+	uint16_t phy_reg;
+
+	/* Because we reset the PHY above, we need to re-force TX_CLK in the
+	 * Extended PHY Specific Control Register to 25MHz clock.  This
+	 * value defaults back to a 2.5MHz clock when the PHY is reset.
+	 */
+	e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
+	phy_reg |= M88E1000_EPSCR_TX_CLK_25;
+	e1000_write_phy_reg(&adapter->hw,
+		M88E1000_EXT_PHY_SPEC_CTRL, phy_reg);
+
+	/* In addition, because of the s/w reset above, we need to enable
+	 * CRS on TX.  This must be set for both full and half duplex
+	 * operation.
+	 */
+	e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
+	phy_reg |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+	e1000_write_phy_reg(&adapter->hw,
+		M88E1000_PHY_SPEC_CTRL, phy_reg);
+}
+
+static int
+e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
+{
+	uint32_t ctrl_reg;
+	uint16_t phy_reg;
+
+	/* Setup the Device Control Register for PHY loopback test. */
+
+	ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
+	ctrl_reg |= (E1000_CTRL_ILOS |		/* Invert Loss-Of-Signal */
+		     E1000_CTRL_FRCSPD |	/* Set the Force Speed Bit */
+		     E1000_CTRL_FRCDPX |	/* Set the Force Duplex Bit */
+		     E1000_CTRL_SPD_1000 |	/* Force Speed to 1000 */
+		     E1000_CTRL_FD);		/* Force Duplex to FULL */
+
+	E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);
+
+	/* Read the PHY Specific Control Register (0x10) */
+	e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
+
+	/* Clear Auto-Crossover bits in PHY Specific Control Register
+	 * (bits 6:5).
+	 */
+	phy_reg &= ~M88E1000_PSCR_AUTO_X_MODE;
+	e1000_write_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, phy_reg);
+
+	/* Perform software reset on the PHY */
+	e1000_phy_reset(&adapter->hw);
+
+	/* Have to setup TX_CLK and TX_CRS after software reset */
+	e1000_phy_reset_clk_and_crs(adapter);
+
+	e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8100);
+
+	/* Wait for reset to complete. */
+	udelay(500);
+
+	/* Have to setup TX_CLK and TX_CRS after software reset */
+	e1000_phy_reset_clk_and_crs(adapter);
+
+	/* Write out to PHY registers 29 and 30 to disable the Receiver. */
+	e1000_phy_disable_receiver(adapter);
+
+	/* Set the loopback bit in the PHY control register. */
+	e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+	phy_reg |= MII_CR_LOOPBACK;
+	e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
+
+	/* Setup TX_CLK and TX_CRS one more time. */
+	e1000_phy_reset_clk_and_crs(adapter);
+
+	/* Check Phy Configuration */
+	e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+	if(phy_reg != 0x4100)
+		 return 9;
+
+	e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
+	if(phy_reg != 0x0070)
+		return 10;
+
+	e1000_read_phy_reg(&adapter->hw, 29, &phy_reg);
+	if(phy_reg != 0x001A)
+		return 11;
+
+	return 0;
+}
+
+static int
+e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+{
+	uint32_t ctrl_reg = 0;
+	uint32_t stat_reg = 0;
+
+	adapter->hw.autoneg = FALSE;
+
+	if(adapter->hw.phy_type == e1000_phy_m88) {
+		/* Auto-MDI/MDIX Off */
+		e1000_write_phy_reg(&adapter->hw,
+				    M88E1000_PHY_SPEC_CTRL, 0x0808);
+		/* reset to update Auto-MDI/MDIX */
+		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x9140);
+		/* autoneg off */
+		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8140);
+	}
+	/* force 1000, set loopback */
+	e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4140);
+
+	/* Now set up the MAC to the same speed/duplex as the PHY. */
+	ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
+	ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
+	ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
+		     E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
+		     E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
+		     E1000_CTRL_FD);	 /* Force Duplex to FULL */
+
+	if(adapter->hw.media_type == e1000_media_type_copper &&
+	   adapter->hw.phy_type == e1000_phy_m88) {
+		ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
+	} else {
+		/* Set the ILOS bit on the fiber Nic is half
+		 * duplex link is detected. */
+		stat_reg = E1000_READ_REG(&adapter->hw, STATUS);
+		if((stat_reg & E1000_STATUS_FD) == 0)
+			ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
+	}
+
+	E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);
+
+	/* Disable the receiver on the PHY so when a cable is plugged in, the
+	 * PHY does not begin to autoneg when a cable is reconnected to the NIC.
+	 */
+	if(adapter->hw.phy_type == e1000_phy_m88)
+		e1000_phy_disable_receiver(adapter);
+
+	udelay(500);
+
+	return 0;
+}
+
+static int
+e1000_set_phy_loopback(struct e1000_adapter *adapter)
+{
+	uint16_t phy_reg = 0;
+	uint16_t count = 0;
+
+	switch (adapter->hw.mac_type) {
+	case e1000_82543:
+		if(adapter->hw.media_type == e1000_media_type_copper) {
+			/* Attempt to setup Loopback mode on Non-integrated PHY.
+			 * Some PHY registers get corrupted at random, so
+			 * attempt this 10 times.
+			 */
+			while(e1000_nonintegrated_phy_loopback(adapter) &&
+			      count++ < 10);
+			if(count < 11)
+				return 0;
+		}
+		break;
+
+	case e1000_82544:
+	case e1000_82540:
+	case e1000_82545:
+	case e1000_82546:
+	case e1000_82541:
+	case e1000_82547:
+		return e1000_integrated_phy_loopback(adapter);
+		break;
+
+	default:
+		/* Default PHY loopback work is to read the MII
+		 * control register and assert bit 14 (loopback mode).
+		 */
+		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+		phy_reg |= MII_CR_LOOPBACK;
+		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
+		return 0;
+		break;
+	}
+
+	return 8;
+}
+
+static int
+e1000_setup_loopback_test(struct e1000_adapter *adapter)
+{
+	uint32_t rctl;
+
+	if(adapter->hw.media_type == e1000_media_type_fiber) {
+		if(adapter->hw.mac_type == e1000_82545 ||
+		   adapter->hw.mac_type == e1000_82546)
+			return e1000_set_phy_loopback(adapter);
+		else {
+			rctl = E1000_READ_REG(&adapter->hw, RCTL);
+			rctl |= E1000_RCTL_LBM_TCVR;
+			E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+			return 0;
+		}
+	} else if(adapter->hw.media_type == e1000_media_type_copper)
+		return e1000_set_phy_loopback(adapter);
+
+	return 7;
+}
+
+static void
+e1000_loopback_cleanup(struct e1000_adapter *adapter)
+{
+	uint32_t rctl;
+	uint16_t phy_reg;
+
+	rctl = E1000_READ_REG(&adapter->hw, RCTL);
+	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
+	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+
+	if(adapter->hw.media_type == e1000_media_type_copper ||
+	   (adapter->hw.media_type == e1000_media_type_fiber &&
+	    (adapter->hw.mac_type == e1000_82545 ||
+	     adapter->hw.mac_type == e1000_82546))) {
+		adapter->hw.autoneg = TRUE;
+		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+		if(phy_reg & MII_CR_LOOPBACK) {
+			phy_reg &= ~MII_CR_LOOPBACK;
+			e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
+			e1000_phy_reset(&adapter->hw);
+		}
+	}
+}
+
+static void
+e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
+{
+	memset(skb->data, 0xFF, frame_size);
+	frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;
+	memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
+	memset(&skb->data[frame_size / 2 + 10], 0xBE, 1);
+	memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
+}
+
+static int
+e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
+{
+	frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;
+	if(*(skb->data + 3) == 0xFF) {
+		if((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
+		   (*(skb->data + frame_size / 2 + 12) == 0xAF)) {
+			return 0;
+		}
+	}
+	return 13;
+}
+
+static int
+e1000_run_loopback_test(struct e1000_adapter *adapter)
+{
+	struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
+	struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
+	struct pci_dev *pdev = adapter->pdev;
+	int i;
+
+	E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);
+
+	for(i = 0; i < 64; i++) {
+		e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 1024);
+		pci_dma_sync_single(pdev, txdr->buffer_info[i].dma,
+				    txdr->buffer_info[i].length,
+				    PCI_DMA_TODEVICE);
+	}
+	E1000_WRITE_REG(&adapter->hw, TDT, i);
+
+	msec_delay(200);
+
+	pci_dma_sync_single(pdev, rxdr->buffer_info[0].dma,
+			    rxdr->buffer_info[0].length, PCI_DMA_FROMDEVICE);
+
+	return e1000_check_lbtest_frame(rxdr->buffer_info[0].skb, 1024);
+}
+
+static int
+e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data)
+{
+	if((*data = e1000_setup_desc_rings(adapter))) goto err_loopback;
+	if((*data = e1000_setup_loopback_test(adapter))) goto err_loopback;
+	*data = e1000_run_loopback_test(adapter);
+	e1000_loopback_cleanup(adapter);
+	e1000_free_desc_rings(adapter);
+err_loopback:
+	return *data;
+}
+
+static int
+e1000_link_test(struct e1000_adapter *adapter, uint64_t *data)
+{
+	*data = 0;
+	e1000_check_for_link(&adapter->hw);
+
+	if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
+		*data = 1;
+	}
+	return *data;
+}
+
+static int
+e1000_ethtool_test(struct e1000_adapter *adapter,
+		   struct ethtool_test *eth_test, uint64_t *data)
+{
+	boolean_t if_running = netif_running(adapter->netdev);
+
+	if(eth_test->flags == ETH_TEST_FL_OFFLINE) {
+		/* Offline tests */
+
+		/* Link test performed before hardware reset so autoneg doesn't
+		 * interfere with test result */
+		if(e1000_link_test(adapter, &data[4]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		if(if_running)
+			e1000_down(adapter);
+
+		e1000_reset(adapter);
+		if(e1000_reg_test(adapter, &data[0]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		e1000_reset(adapter);
+		if(e1000_eeprom_test(adapter, &data[1]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		e1000_reset(adapter);
+		if(e1000_intr_test(adapter, &data[2]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		e1000_reset(adapter);
+		if(e1000_loopback_test(adapter, &data[3]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		e1000_reset(adapter);
+		if(if_running)
+			e1000_up(adapter);
+	} else {
+		/* Online tests */
+		if(e1000_link_test(adapter, &data[4]))
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		/* Offline tests aren't run; pass by default */
+		data[0] = 0;
+		data[1] = 0;
+		data[2] = 0;
+		data[3] = 0;
+	}
+	return 0;
+}
+
 static void
 e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
 {
@@ -443,24 +1305,46 @@
 	case ETHTOOL_GSTRINGS: {
 		struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS };
 		char *strings = NULL;
+		int err = 0;
 
 		if(copy_from_user(&gstrings, addr, sizeof(gstrings)))
 			return -EFAULT;
 		switch(gstrings.string_set) {
-		case ETH_SS_STATS:
+		case ETH_SS_TEST:
+			gstrings.len = E1000_TEST_LEN;
+			strings = kmalloc(E1000_TEST_LEN * ETH_GSTRING_LEN,
+					  GFP_KERNEL);
+			if(!strings)
+				return -ENOMEM;
+			memcpy(strings, e1000_gstrings_test, E1000_TEST_LEN *
+			       ETH_GSTRING_LEN);
+			break;
+		case ETH_SS_STATS: {
+			int i;
 			gstrings.len = E1000_STATS_LEN;
-			strings = *e1000_gstrings_stats;
+			strings = kmalloc(E1000_STATS_LEN * ETH_GSTRING_LEN,
+					  GFP_KERNEL);
+			if(!strings)
+				return -ENOMEM;
+			for(i=0; i < E1000_STATS_LEN; i++) {
+				memcpy(&strings[i * ETH_GSTRING_LEN],
+				       e1000_gstrings_stats[i].stat_string,
+				       ETH_GSTRING_LEN);
+			}
 			break;
+		}
 		default:
 			return -EOPNOTSUPP;
 		}
 		if(copy_to_user(addr, &gstrings, sizeof(gstrings)))
-			return -EFAULT;
+			err = -EFAULT;
 		addr += offsetof(struct ethtool_gstrings, data);
-		if(copy_to_user(addr, strings,
+		if(!err && copy_to_user(addr, strings,
 		   gstrings.len * ETH_GSTRING_LEN))
-			return -EFAULT;
-		return 0;
+			err = -EFAULT;
+
+		kfree(strings);
+		return err;
 	}
 	case ETHTOOL_GREGS: {
 		struct ethtool_regs regs = {ETHTOOL_GREGS};
@@ -522,16 +1406,14 @@
 		void *ptr;
 		int err = 0;
 
+		if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
+			return -EFAULT;
+
 		eeprom_buff = kmalloc(hw->eeprom.word_size * 2, GFP_KERNEL);
 
-		if(eeprom_buff == NULL)
+		if(!eeprom_buff)
 			return -ENOMEM;
 
-		if(copy_from_user(&eeprom, addr, sizeof(eeprom))) {
-			err = -EFAULT;
-			goto err_geeprom_ioctl;
-		}
-
 		if((err = e1000_ethtool_geeprom(adapter, &eeprom,
 						eeprom_buff)))
 			goto err_geeprom_ioctl;
@@ -565,18 +1447,45 @@
 	}
 	case ETHTOOL_GSTATS: {
 		struct {
-			struct ethtool_stats cmd;
+			struct ethtool_stats eth_stats;
 			uint64_t data[E1000_STATS_LEN];
 		} stats = { {ETHTOOL_GSTATS, E1000_STATS_LEN} };
 		int i;
 
 		for(i = 0; i < E1000_STATS_LEN; i++)
-			stats.data[i] =
-				((unsigned long *)&adapter->net_stats)[i];
+			stats.data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
+					sizeof(uint64_t)) ?
+				*(uint64_t *)((char *)adapter +
+					e1000_gstrings_stats[i].stat_offset) :
+				*(uint32_t *)((char *)adapter +
+					e1000_gstrings_stats[i].stat_offset);
 		if(copy_to_user(addr, &stats, sizeof(stats)))
 			return -EFAULT;
 		return 0;
 	}
+	case ETHTOOL_TEST: {
+		struct {
+			struct ethtool_test eth_test;
+			uint64_t data[E1000_TEST_LEN];
+		} test = { {ETHTOOL_TEST} };
+		int err;
+
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+
+		if(copy_from_user(&test.eth_test, addr, sizeof(test.eth_test)))
+			return -EFAULT;
+
+		test.eth_test.len = E1000_TEST_LEN;
+
+		if((err = e1000_ethtool_test(adapter, &test.eth_test,
+					     test.data)))
+			return err;
+
+		if(copy_to_user(addr, &test, sizeof(test)) != 0)
+			return -EFAULT;
+		return 0;
+	}
 	default:
 		return -EOPNOTSUPP;
 	}
diff -urN linux-2.5.69-bk18/drivers/net/e1000/e1000_hw.c linux-2.5.69-bk19/drivers/net/e1000/e1000_hw.c
--- linux-2.5.69-bk18/drivers/net/e1000/e1000_hw.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/e1000/e1000_hw.c	2003-05-26 04:41:42.000000000 -0700
@@ -185,6 +185,7 @@
         break;
     case E1000_DEV_ID_82546EB_COPPER:
     case E1000_DEV_ID_82546EB_FIBER:
+    case E1000_DEV_ID_82546EB_QUAD_COPPER:
         hw->mac_type = e1000_82546;
         break;
     case E1000_DEV_ID_82541EI:
@@ -288,9 +289,7 @@
         /* Configure activity LED after PHY reset */
         led_ctrl = E1000_READ_REG(hw, LEDCTL);
         led_ctrl &= IGP_ACTIVITY_LED_MASK;
-        led_ctrl |= IGP_ACTIVITY_LED_ENABLE;
-        if(hw->mac_type == e1000_82547)
-            led_ctrl |= IGP_LED3_MODE;
+        led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
         E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
     }
 
@@ -737,9 +736,7 @@
         /* Configure activity LED after PHY reset */
         led_ctrl = E1000_READ_REG(hw, LEDCTL);
         led_ctrl &= IGP_ACTIVITY_LED_MASK;
-        led_ctrl |= IGP_ACTIVITY_LED_ENABLE;
-        if(hw->mac_type == e1000_82547)
-            led_ctrl |= IGP_LED3_MODE;
+        led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
         E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
 
         if(hw->autoneg_advertised == ADVERTISE_1000_FULL) {
@@ -2293,9 +2290,7 @@
         /* Configure activity LED after PHY reset */
         led_ctrl = E1000_READ_REG(hw, LEDCTL);
         led_ctrl &= IGP_ACTIVITY_LED_MASK;
-        led_ctrl |= IGP_ACTIVITY_LED_ENABLE;
-        if(hw->mac_type == e1000_82547)
-            led_ctrl |= IGP_LED3_MODE;
+        led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
         E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
     }
 }
@@ -3801,6 +3796,7 @@
     case E1000_DEV_ID_82540EM_LOM:
     case E1000_DEV_ID_82545EM_COPPER:
     case E1000_DEV_ID_82546EB_COPPER:
+    case E1000_DEV_ID_82546EB_QUAD_COPPER:
     case E1000_DEV_ID_82541EI:
     case E1000_DEV_ID_82541EP:
     case E1000_DEV_ID_82547EI:
@@ -3842,6 +3838,7 @@
     case E1000_DEV_ID_82545EM_FIBER:
     case E1000_DEV_ID_82546EB_COPPER:
     case E1000_DEV_ID_82546EB_FIBER:
+    case E1000_DEV_ID_82546EB_QUAD_COPPER:
     case E1000_DEV_ID_82541EI:
     case E1000_DEV_ID_82541EP:
     case E1000_DEV_ID_82547EI:
@@ -3896,6 +3893,7 @@
     case E1000_DEV_ID_82540EM_LOM:
     case E1000_DEV_ID_82545EM_COPPER:
     case E1000_DEV_ID_82546EB_COPPER:
+    case E1000_DEV_ID_82546EB_QUAD_COPPER:
     case E1000_DEV_ID_82541EI:
     case E1000_DEV_ID_82541EP:
     case E1000_DEV_ID_82547EI:
@@ -3949,6 +3947,7 @@
     case E1000_DEV_ID_82540EM_LOM:
     case E1000_DEV_ID_82545EM_COPPER:
     case E1000_DEV_ID_82546EB_COPPER:
+    case E1000_DEV_ID_82546EB_QUAD_COPPER:
     case E1000_DEV_ID_82541EI:
     case E1000_DEV_ID_82541EP:
     case E1000_DEV_ID_82547EI:
@@ -4206,7 +4205,11 @@
     status = E1000_READ_REG(hw, STATUS);
     hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
                    e1000_bus_type_pcix : e1000_bus_type_pci;
-    if(hw->bus_type == e1000_bus_type_pci) {
+
+    if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
+        hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ?
+                        e1000_bus_speed_66 : e1000_bus_speed_120;
+    } else if(hw->bus_type == e1000_bus_type_pci) {
         hw->bus_speed = (status & E1000_STATUS_PCI66) ?
                         e1000_bus_speed_66 : e1000_bus_speed_33;
     } else {
diff -urN linux-2.5.69-bk18/drivers/net/e1000/e1000_hw.h linux-2.5.69-bk19/drivers/net/e1000/e1000_hw.h
--- linux-2.5.69-bk18/drivers/net/e1000/e1000_hw.h	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/e1000/e1000_hw.h	2003-05-26 04:41:42.000000000 -0700
@@ -99,6 +99,7 @@
     e1000_bus_speed_33,
     e1000_bus_speed_66,
     e1000_bus_speed_100,
+    e1000_bus_speed_120,
     e1000_bus_speed_133,
     e1000_bus_speed_reserved
 } e1000_bus_speed;
@@ -314,10 +315,11 @@
 #define E1000_DEV_ID_82545EM_FIBER       0x1011
 #define E1000_DEV_ID_82546EB_COPPER      0x1010
 #define E1000_DEV_ID_82546EB_FIBER       0x1012
+#define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D
 #define E1000_DEV_ID_82541EI             0x1013
 #define E1000_DEV_ID_82541EP             0x1018
 #define E1000_DEV_ID_82547EI             0x1019
-#define NUM_DEV_IDS 19
+#define NUM_DEV_IDS 20
 
 #define NODE_ADDRESS_SIZE 6
 #define ETH_LENGTH_OF_ADDRESS 6
@@ -601,7 +603,7 @@
 #define E1000_EECD     0x00010  /* EEPROM/Flash Control - RW */
 #define E1000_EERD     0x00014  /* EEPROM Read - RW */
 #define E1000_CTRL_EXT 0x00018  /* Extended Device Control - RW */
-#define E1000_FLA      0x0001C  /* Flash Access Register - RW */
+#define E1000_FLA      0x0001C  /* Flash Access - RW */
 #define E1000_MDIC     0x00020  /* MDI Control - RW */
 #define E1000_FCAL     0x00028  /* Flow Control Address Low - RW */
 #define E1000_FCAH     0x0002C  /* Flow Control Address High -RW */
@@ -730,6 +732,7 @@
  * the registers function in the same manner.
  */
 #define E1000_82542_CTRL     E1000_CTRL
+#define E1000_82542_CTRL_DUP E1000_CTRL_DUP
 #define E1000_82542_STATUS   E1000_STATUS
 #define E1000_82542_EECD     E1000_EECD
 #define E1000_82542_EERD     E1000_EERD
@@ -1485,7 +1488,6 @@
 #define E1000_COLLISION_DISTANCE        64
 #define E1000_FDX_COLLISION_DISTANCE    E1000_COLLISION_DISTANCE
 #define E1000_HDX_COLLISION_DISTANCE    E1000_COLLISION_DISTANCE
-#define E1000_GB_HDX_COLLISION_DISTANCE 512
 #define E1000_COLD_SHIFT                12
 
 /* The number of Transmit and Receive Descriptors must be a multiple of 8 */
diff -urN linux-2.5.69-bk18/drivers/net/e1000/e1000_main.c linux-2.5.69-bk19/drivers/net/e1000/e1000_main.c
--- linux-2.5.69-bk18/drivers/net/e1000/e1000_main.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/e1000/e1000_main.c	2003-05-26 04:41:42.000000000 -0700
@@ -30,7 +30,14 @@
 
 /* Change Log
  *
- * 5.0.43	3/5/03
+ * 5.1.11	5/6/03
+ *   o Feature: Added support for 82546EB (Quad-port) hardware.
+ *   o Feature: Added support for Diagnostics through Ethtool.
+ *   o Cleanup: Removed /proc support.
+ *   o Cleanup: Removed proprietary IDIAG interface.
+ *   o Bug fix: TSO bug fixes.
+ *
+ * 5.0.42	3/5/03
  *   o Feature: Added support for 82541 and 82547 hardware.
  *   o Feature: Added support for Intel Gigabit PHY (IGP) and a variety of
  *   eeproms.
@@ -46,51 +53,22 @@
  *   shared interrupt instances.
  *
  * 4.4.18       11/27/02
- *   o Feature: Added user-settable knob for interrupt throttle rate (ITR).
- *   o Cleanup: removed large static array allocations.
- *   o Cleanup: C99 struct initializer format.
- *   o Bug fix: restore VLAN settings when interface is brought up.
- *   o Bug fix: return cleanly in probe if error in detecting MAC type.
- *   o Bug fix: Wake up on magic packet by default only if enabled in eeprom.
- *   o Bug fix: Validate MAC address in set_mac.
- *   o Bug fix: Throw away zero-length Tx skbs.
- *   o Bug fix: Make ethtool EEPROM acceses work on older versions of ethtool.
- * 
- * 4.4.12       10/15/02
  */
 
 char e1000_driver_name[] = "e1000";
 char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-char e1000_driver_version[] = "5.0.43-k3";
+char e1000_driver_version[] = "5.1.11-k1";
 char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation.";
 
 /* e1000_pci_tbl - PCI Device ID Table
  *
- * Private driver_data field (last one) stores an index into e1000_strings
  * Wildcard entries (PCI_ANY_ID) should come last
  * Last entry must be all 0s
  *
  * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
- *   Class, Class Mask, String Index }
+ *   Class, Class Mask, private data (not used) }
  */
 static struct pci_device_id e1000_pci_tbl[] __devinitdata = {
-	/* Intel(R) PRO/1000 Network Connection */
-	{0x8086, 0x1000, 0x8086, 0x1000, 0, 0, 0},
-	{0x8086, 0x1001, 0x8086, 0x1003, 0, 0, 0},
-	{0x8086, 0x1004, 0x8086, 0x1004, 0, 0, 0},
-	{0x8086, 0x1008, 0x8086, 0x1107, 0, 0, 0},
-	{0x8086, 0x1009, 0x8086, 0x1109, 0, 0, 0},
-	{0x8086, 0x100C, 0x8086, 0x1112, 0, 0, 0},
-	{0x8086, 0x100E, 0x8086, 0x001E, 0, 0, 0},
-	/* Compaq Gigabit Ethernet Server Adapter */
-	{0x8086, 0x1000, 0x0E11, PCI_ANY_ID, 0, 0, 1},
-	{0x8086, 0x1001, 0x0E11, PCI_ANY_ID, 0, 0, 1},
-	{0x8086, 0x1004, 0x0E11, PCI_ANY_ID, 0, 0, 1},
-	/* IBM Mobile, Desktop & Server Adapters */
-	{0x8086, 0x1000, 0x1014, PCI_ANY_ID, 0, 0, 2},
-	{0x8086, 0x1001, 0x1014, PCI_ANY_ID, 0, 0, 2},
-	{0x8086, 0x1004, 0x1014, PCI_ANY_ID, 0, 0, 2},
-	/* Generic */
 	{0x8086, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x8086, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x8086, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -106,6 +84,7 @@
 	{0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	/* required last entry */
@@ -114,12 +93,6 @@
 
 MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
 
-static char *e1000_strings[] = {
-	"Intel(R) PRO/1000 Network Connection",
-	"HP Gigabit Ethernet Server Adapter",
-	"IBM Mobile, Desktop & Server Adapters"
-};
-
 /* Local Function Prototypes */
 
 int e1000_up(struct e1000_adapter *adapter);
@@ -130,7 +103,7 @@
 static int e1000_init_module(void);
 static void e1000_exit_module(void);
 static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-static void e1000_remove(struct pci_dev *pdev);
+static void __devexit e1000_remove(struct pci_dev *pdev);
 static int e1000_sw_init(struct e1000_adapter *adapter);
 static int e1000_open(struct net_device *netdev);
 static int e1000_close(struct net_device *netdev);
@@ -195,7 +168,6 @@
 	.priority	= 0
 };
 
-
 /* Exported from other modules */
 
 extern void e1000_check_options(struct e1000_adapter *adapter);
@@ -234,8 +206,9 @@
 	printk(KERN_INFO "%s\n", e1000_copyright);
 
 	ret = pci_module_init(&e1000_driver);
-	if(ret >= 0)
+	if(ret >= 0) {
 		register_reboot_notifier(&e1000_notifier_reboot);
+	}
 	return ret;
 }
 
@@ -439,7 +412,6 @@
 	netdev->base_addr = adapter->hw.io_base;
 
 	adapter->bd_number = cards_found;
-	adapter->id_string = e1000_strings[ent->driver_data];
 
 	/* setup the private structure */
 
@@ -500,15 +472,14 @@
 		(void (*)(void *))e1000_tx_timeout_task, netdev);
 
 	register_netdev(netdev);
-	memcpy(adapter->ifname, netdev->name, IFNAMSIZ);
-	adapter->ifname[IFNAMSIZ-1] = 0;
 
 	/* we're going to reset, so assume we have no link for now */
 
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
 
-	printk(KERN_INFO "%s: %s\n", netdev->name, adapter->id_string);
+	printk(KERN_INFO "%s: Intel(R) PRO/1000 Network Connection\n",
+	       netdev->name);
 	e1000_check_options(adapter);
 
 	/* Initial Wake on LAN setting
@@ -568,7 +539,6 @@
 
 	e1000_phy_hw_reset(&adapter->hw);
 
-
 	iounmap(adapter->hw.hw_addr);
 	pci_release_regions(pdev);
 
@@ -831,8 +801,9 @@
 
 	e1000_config_collision_dist(&adapter->hw);
 
-	/* Setup Transmit Descriptor Settings for this adapter */
-	adapter->txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_IDE;
+	/* Setup Transmit Descriptor Settings for eop descriptor */
+	adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP |
+		E1000_TXD_CMD_IFCS;
 
 	if(adapter->hw.report_tx_early == 1)
 		adapter->txd_cmd |= E1000_TXD_CMD_RS;
@@ -1435,7 +1406,7 @@
 #define E1000_TX_FLAGS_VLAN_SHIFT	16
 
 static inline boolean_t
-e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb, int tx_flags)
+e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
 {
 #ifdef NETIF_F_TSO
 	struct e1000_context_desc *context_desc;
@@ -1471,7 +1442,7 @@
 		context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse);
 		context_desc->tcp_seg_setup.fields.mss     = cpu_to_le16(mss);
 		context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
-		context_desc->cmd_and_length = cpu_to_le32(adapter->txd_cmd |
+		context_desc->cmd_and_length = cpu_to_le32(
 			E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
 			E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP |
 			(skb->len - (hdr_len)));
@@ -1504,8 +1475,7 @@
 		context_desc->upper_setup.tcp_fields.tucso = cso;
 		context_desc->upper_setup.tcp_fields.tucse = 0;
 		context_desc->tcp_seg_setup.data = 0;
-		context_desc->cmd_and_length =
-			cpu_to_le32(adapter->txd_cmd | E1000_TXD_CMD_DEXT);
+		context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
 
 		if(++i == adapter->tx_ring.count) i = 0;
 		adapter->tx_ring.next_to_use = i;
@@ -1520,7 +1490,8 @@
 #define E1000_MAX_DATA_PER_TXD	(1<<E1000_MAX_TXD_PWR)
 
 static inline int
-e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb)
+e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
+	unsigned int first)
 {
 	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
 	int len = skb->len, offset = 0, size, count = 0, i;
@@ -1588,6 +1559,7 @@
 	}
 	if(--i < 0) i = tx_ring->count - 1;
 	tx_ring->buffer_info[i].skb = skb;
+	tx_ring->buffer_info[first].next_to_watch = i;
 
 	return count;
 }
@@ -1597,12 +1569,9 @@
 {
 	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
 	struct e1000_tx_desc *tx_desc = NULL;
-	uint32_t txd_upper, txd_lower;
+	uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
 	int i;
 
-	txd_upper = 0;
-	txd_lower = adapter->txd_cmd;
-
 	if(tx_flags & E1000_TX_FLAGS_TSO) {
 		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
 		             E1000_TXD_CMD_TSE;
@@ -1630,7 +1599,7 @@
 		if(++i == tx_ring->count) i = 0;
 	}
 
-	tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP);
+	tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
 
 	/* Force memory writes to complete before letting h/w
 	 * know there are new descriptors to fetch.  (Only
@@ -1690,6 +1659,7 @@
 e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev->priv;
+	unsigned int first;
 	int tx_flags = 0;
 
 	if(skb->len <= 0) {
@@ -1715,12 +1685,14 @@
 		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
 	}
 
-	if(e1000_tso(adapter, skb, tx_flags))
+	first = adapter->tx_ring.next_to_use;
+	
+	if(e1000_tso(adapter, skb))
 		tx_flags |= E1000_TX_FLAGS_TSO;
 	else if(e1000_tx_csum(adapter, skb))
 		tx_flags |= E1000_TX_FLAGS_CSUM;
 
-	e1000_tx_queue(adapter, e1000_tx_map(adapter, skb), tx_flags);
+	e1000_tx_queue(adapter, e1000_tx_map(adapter, skb, first), tx_flags);
 
 	netdev->trans_start = jiffies;
 
@@ -1952,6 +1924,7 @@
 		}
 
 		if((hw->mac_type <= e1000_82546) &&
+		   (hw->phy_type == e1000_phy_m88) &&
 		   !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
 			adapter->phy_stats.receive_errors += phy_tmp;
 	}
@@ -2069,39 +2042,47 @@
 	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_tx_desc *tx_desc;
-	int i, cleaned = FALSE;
+	struct e1000_tx_desc *tx_desc, *eop_desc;
+	struct e1000_buffer *buffer_info;
+	int i, eop, cleaned = FALSE;
 
 	i = tx_ring->next_to_clean;
-	tx_desc = E1000_TX_DESC(*tx_ring, i);
+	eop = tx_ring->buffer_info[i].next_to_watch;
+	eop_desc = E1000_TX_DESC(*tx_ring, eop);
 
-	while(tx_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
+	while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
 
-		cleaned = TRUE;
+		for(cleaned = FALSE; !cleaned; ) {
+			tx_desc = E1000_TX_DESC(*tx_ring, i);
+			buffer_info = &tx_ring->buffer_info[i];
 
-		if(tx_ring->buffer_info[i].dma) {
+			if(buffer_info->dma) {
 
-			pci_unmap_page(pdev,
-			               tx_ring->buffer_info[i].dma,
-			               tx_ring->buffer_info[i].length,
-			               PCI_DMA_TODEVICE);
+				pci_unmap_page(pdev,
+					       buffer_info->dma,
+					       buffer_info->length,
+					       PCI_DMA_TODEVICE);
 
-			tx_ring->buffer_info[i].dma = 0;
-		}
+				buffer_info->dma = 0;
+			}
 
-		if(tx_ring->buffer_info[i].skb) {
+			if(buffer_info->skb) {
 
-			dev_kfree_skb_any(tx_ring->buffer_info[i].skb);
+				dev_kfree_skb_any(buffer_info->skb);
 
-			tx_ring->buffer_info[i].skb = NULL;
-		}
+				buffer_info->skb = NULL;
+			}
 
-		tx_desc->buffer_addr = 0;
-		tx_desc->lower.data = 0;
-		tx_desc->upper.data = 0;
+			tx_desc->buffer_addr = 0;
+			tx_desc->lower.data = 0;
+			tx_desc->upper.data = 0;
 
-		if(++i == tx_ring->count) i = 0;
-		tx_desc = E1000_TX_DESC(*tx_ring, i);
+			cleaned = (i == eop);
+			if(++i == tx_ring->count) i = 0;
+		}
+		
+		eop = tx_ring->buffer_info[i].next_to_watch;
+		eop_desc = E1000_TX_DESC(*tx_ring, eop);
 	}
 
 	tx_ring->next_to_clean = i;
@@ -2224,7 +2205,6 @@
 			netif_rx(skb);
 		}
 #endif /* CONFIG_E1000_NAPI */
-
 		netdev->last_rx = jiffies;
 
 		rx_desc->status = 0;
@@ -2677,7 +2657,6 @@
 	return NOTIFY_DONE;
 }
 
-
 static int
 e1000_suspend(struct pci_dev *pdev, uint32_t state)
 {
diff -urN linux-2.5.69-bk18/drivers/net/ewrk3.c linux-2.5.69-bk19/drivers/net/ewrk3.c
--- linux-2.5.69-bk18/drivers/net/ewrk3.c	2003-05-04 16:53:55.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/ewrk3.c	2003-05-26 04:41:42.000000000 -0700
@@ -1968,7 +1968,10 @@
 	case EWRK3_GET_STATS: { /* Get the driver statistics */
 		struct ewrk3_stats *tmp_stats =
         		kmalloc(sizeof(lp->pktStats), GFP_KERNEL);
-		if (!tmp_stats) return -ENOMEM;
+		if (!tmp_stats) {
+			status = -ENOMEM;
+			break;
+		}
 
 		spin_lock_irqsave(&lp->hw_lock, flags);
 		memcpy(tmp_stats, &lp->pktStats, sizeof(lp->pktStats));
diff -urN linux-2.5.69-bk18/drivers/net/fc/iph5526.c linux-2.5.69-bk19/drivers/net/fc/iph5526.c
--- linux-2.5.69-bk18/drivers/net/fc/iph5526.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/fc/iph5526.c	2003-05-26 04:41:42.000000000 -0700
@@ -134,7 +134,7 @@
 	{0,}
 };
 
-static void tachyon_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t tachyon_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void tachyon_interrupt_handler(int irq, void* dev_id, struct pt_regs* regs);
 
 static int initialize_register_pointers(struct fc_info *fi);
@@ -623,7 +623,7 @@
 }
 
 
-static void tachyon_interrupt(int irq, void* dev_id, struct pt_regs* regs)
+static irqreturn_t tachyon_interrupt(int irq, void* dev_id, struct pt_regs* regs)
 {
 struct Scsi_Host *host = dev_id;
 struct iph5526_hostdata *hostdata = (struct iph5526_hostdata *)host->hostdata;
@@ -632,6 +632,7 @@
 	spin_lock_irqsave(&fi->fc_lock, flags);
 	tachyon_interrupt_handler(irq, dev_id, regs);
 	spin_unlock_irqrestore(&fi->fc_lock, flags);
+	return IRQ_HANDLED;
 }
 
 static void tachyon_interrupt_handler(int irq, void* dev_id, struct pt_regs* regs)
@@ -3720,12 +3721,13 @@
 
 int iph5526_detect(Scsi_Host_Template *tmpt)
 {
-struct Scsi_Host *host = NULL;
-struct iph5526_hostdata *hostdata;
-struct fc_info *fi = NULL;
-int no_of_hosts = 0, timeout, i, j, count = 0;
-u_int pci_maddr = 0;
-struct pci_dev *pdev = NULL;
+	struct Scsi_Host *host = NULL;
+	struct iph5526_hostdata *hostdata;
+	struct fc_info *fi = NULL;
+	int no_of_hosts = 0, i, j, count = 0;
+	u_int pci_maddr = 0;
+	struct pci_dev *pdev = NULL;
+	unsigned long timeout;
 
 	tmpt->proc_name = "iph5526";
 	if (pci_present() == 0) {
diff -urN linux-2.5.69-bk18/drivers/net/fec.c linux-2.5.69-bk19/drivers/net/fec.c
--- linux-2.5.69-bk18/drivers/net/fec.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/fec.c	2003-05-26 04:41:42.000000000 -0700
@@ -188,7 +188,7 @@
 static int fec_enet_open(struct net_device *dev);
 static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void fec_enet_mii(struct net_device *dev);
-static void fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static irqreturn_t fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
 static void fec_enet_tx(struct net_device *dev);
 static void fec_enet_rx(struct net_device *dev);
 static int fec_enet_close(struct net_device *dev);
@@ -393,12 +393,13 @@
 /* The interrupt handler.
  * This is called from the MPC core interrupt.
  */
-static	void
+static irqreturn_t
 fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
 {
 	struct	net_device *dev = dev_id;
 	volatile fec_t	*fecp;
 	uint	int_events;
+	int handled = 0;
 
 	fecp = (volatile fec_t*)dev->base_addr;
 
@@ -413,20 +414,27 @@
 
 		/* Handle receive event in its own function.
 		 */
-		if (int_events & FEC_ENET_RXF)
+		if (int_events & FEC_ENET_RXF) {
+			handled = 1;
 			fec_enet_rx(dev);
+		}
 
 		/* Transmit OK, or non-fatal error. Update the buffer
 		   descriptors. FEC handles all errors, we just discover
 		   them as part of the transmit process.
 		*/
-		if (int_events & FEC_ENET_TXF)
+		if (int_events & FEC_ENET_TXF) {
+			handled = 1;
 			fec_enet_tx(dev);
+		}
 
-		if (int_events & FEC_ENET_MII)
+		if (int_events & FEC_ENET_MII) {
+			handled = 1;
 			fec_enet_mii(dev);
+		}
 	
 	}
+	return IRQ_RETVAL(handled);
 }
 
 
diff -urN linux-2.5.69-bk18/drivers/net/fec.h linux-2.5.69-bk19/drivers/net/fec.h
--- linux-2.5.69-bk18/drivers/net/fec.h	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/fec.h	2003-05-26 04:41:42.000000000 -0700
@@ -1,9 +1,10 @@
 /****************************************************************************/
 
 /*
- *	fec.h  --  Fast Ethernet Controller for Motorola ColdFire 5272.
+ *	fec.h  --  Fast Ethernet Controller for Motorola ColdFire 5272
+ *		   and 5282..
  *
- *	(C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com)
+ *	(C) Copyright 2000-2003, Greg Ungerer (gerg@snapgear.com)
  *	(C) Copyright 2000-2001, Lineo (www.lineo.com)
  */
 
@@ -12,6 +13,52 @@
 #define	FEC_H
 /****************************************************************************/
 
+#ifdef CONFIG_M5282
+/*
+ *	Just figures, Motorola would have to change the offsets for
+ *	registers in the same peripheral device on different models
+ *	of the ColdFire!
+ */
+typedef struct fec {
+	unsigned long	fec_reserved0;
+	unsigned long	fec_ievent;		/* Interrupt event reg */
+	unsigned long	fec_imask;		/* Interrupt mask reg */
+	unsigned long	fec_reserved1;
+	unsigned long	fec_r_des_active;	/* Receive descriptor reg */
+	unsigned long	fec_x_des_active;	/* Transmit descriptor reg */
+	unsigned long	fec_reserved2[3];
+	unsigned long	fec_ecntrl;		/* Ethernet control reg */
+	unsigned long	fec_reserved3[6];
+	unsigned long	fec_mii_data;		/* MII manage frame reg */
+	unsigned long	fec_mii_speed;		/* MII speed control reg */
+	unsigned long	fec_reserved4[7];
+	unsigned long	fec_mib_ctrlstat;	/* MIB control/status reg */
+	unsigned long	fec_reserved5[7];
+	unsigned long	fec_r_cntrl;		/* Receive control reg */
+	unsigned long	fec_reserved6[15];
+	unsigned long	fec_x_cntrl;		/* Transmit Control reg */
+	unsigned long	fec_reserved7[7];
+	unsigned long	fec_addr_low;		/* Low 32bits MAC address */
+	unsigned long	fec_addr_high;		/* High 16bits MAC address */
+	unsigned long	fec_opd;		/* Opcode + Pause duration */
+	unsigned long	fec_reserved8[10];
+	unsigned long	fec_hash_table_high;	/* High 32bits hash table */
+	unsigned long	fec_hash_table_low;	/* Low 32bits hash table */
+	unsigned long	fec_grp_hash_table_high;/* High 32bits hash table */
+	unsigned long	fec_grp_hash_table_low;	/* Low 32bits hash table */
+	unsigned long	fec_reserved9[7];
+	unsigned long	fec_x_wmrk;		/* FIFO transmit water mark */
+	unsigned long	fec_reserved10;
+	unsigned long	fec_r_bound;		/* FIFO receive bound reg */
+	unsigned long	fec_r_fstart;		/* FIFO receive start reg */
+	unsigned long	fec_reserved11[11];
+	unsigned long	fec_r_des_start;	/* Receive descriptor ring */
+	unsigned long	fec_x_des_start;	/* Transmit descriptor ring */
+	unsigned long	fec_r_buff_size;	/* Maximum receive buff size */
+} fec_t;
+
+#else
+
 /*
  *	Define device register set address map.
  */
@@ -49,6 +96,8 @@
 	unsigned long	fec_fifo_ram[112];	/* FIFO RAM buffer */
 } fec_t;
 
+#endif /* CONFIG_M5272 */
+
 
 /*
  *	Define the buffer descriptor structure.
diff -urN linux-2.5.69-bk18/drivers/net/fmv18x.c linux-2.5.69-bk19/drivers/net/fmv18x.c
--- linux-2.5.69-bk18/drivers/net/fmv18x.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/fmv18x.c	2003-05-26 04:41:42.000000000 -0700
@@ -114,7 +114,7 @@
 static int fmv18x_probe1(struct net_device *dev, short ioaddr);
 static int net_open(struct net_device *dev);
 static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void net_rx(struct net_device *dev);
 static void net_timeout(struct net_device *dev);
 static int net_close(struct net_device *dev);
@@ -423,7 +423,7 @@
 
 /* The typical workload of the driver:
    Handle the network interface interrupts. */
-static void
+static irqreturn_t
 net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
@@ -476,7 +476,7 @@
 			spin_unlock(&lp->lock);
 		}
 	}
-	return;
+	return IRQ_RETVAL(status);
 }
 
 /* We have a good packet(s), get it/them out of the buffers. */
diff -urN linux-2.5.69-bk18/drivers/net/hamachi.c linux-2.5.69-bk19/drivers/net/hamachi.c
--- linux-2.5.69-bk18/drivers/net/hamachi.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/hamachi.c	2003-05-26 04:41:42.000000000 -0700
@@ -207,8 +207,10 @@
 /* Condensed bus+endian portability operations. */
 #if ADDRLEN == 64
 #define cpu_to_leXX(addr)	cpu_to_le64(addr)
+#define desc_to_virt(addr) bus_to_virt(le64_to_cpu(addr))
 #else 
 #define cpu_to_leXX(addr)	cpu_to_le32(addr)
+#define desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
 #endif   
 
 
@@ -1498,7 +1500,7 @@
 			break;
 		pci_dma_sync_single(hmp->pci_dev, desc->addr, hmp->rx_buf_sz, 
 			PCI_DMA_FROMDEVICE);
-		buf_addr = (u8 *)hmp->rx_ring + entry*sizeof(*desc);
+		buf_addr = desc_to_virt(desc->addr);
 		frame_status = le32_to_cpu(get_unaligned((s32*)&(buf_addr[data_size - 12])));
 		if (hamachi_debug > 4)
 			printk(KERN_DEBUG "  hamachi_rx() status was %8.8x.\n",
diff -urN linux-2.5.69-bk18/drivers/net/hamradio/scc.c linux-2.5.69-bk19/drivers/net/hamradio/scc.c
--- linux-2.5.69-bk18/drivers/net/hamradio/scc.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/hamradio/scc.c	2003-05-26 04:41:42.000000000 -0700
@@ -199,7 +199,7 @@
 
 static void init_channel(struct scc_channel *scc);
 static void scc_key_trx (struct scc_channel *scc, char tx);
-static void scc_isr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs);
 static void scc_init_timer(struct scc_channel *scc);
 
 static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int addev);
@@ -625,7 +625,7 @@
 
 #define SCC_IRQTIMEOUT 30000
 
-static void scc_isr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned char vector;	
 	struct scc_channel *scc;
@@ -653,7 +653,7 @@
 		if (k == SCC_IRQTIMEOUT)
 			printk(KERN_WARNING "z8530drv: endless loop in scc_isr()?\n");
 
-		return;
+		return IRQ_HANDLED;
 	}
 
 	/* Find the SCC generating the interrupt by polling all attached SCCs
@@ -701,6 +701,7 @@
 		} else
 			ctrl++;
 	}
+	return IRQ_HANDLED;
 }
 
 
diff -urN linux-2.5.69-bk18/drivers/net/irda/Kconfig linux-2.5.69-bk19/drivers/net/irda/Kconfig
--- linux-2.5.69-bk18/drivers/net/irda/Kconfig	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/irda/Kconfig	2003-05-26 04:41:42.000000000 -0700
@@ -289,16 +289,29 @@
 	  <file:Documentation/modules.txt>.
 	  The module will be called donauboe.
 
-config SMC_IRCC_FIR
-	tristate "SMC IrCC (EXPERIMENTAL)"
+config SMC_IRCC_OLD
+	tristate "SMC IrCC (old driver) (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && IRDA
 	help
 	  Say Y here if you want to build support for the SMC Infrared
 	  Communications Controller.  It is used in the Fujitsu Lifebook 635t
-	  and Sony PCG-505TX.  If you want to compile it as a module, say M
-	  here and read <file:Documentation/modules.txt>.  The module will be
+	  and Sony PCG-505TX.  This driver is obsolete, will no more be
+	  maintained and will be removed in favor of the new driver.
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.  The module will be
 	  called smc-ircc.
 
+config SMC_IRCC_FIR
+	tristate "SMSC IrCC (EXPERIMENTAL)"
+	depends on EXPERIMENTAL && IRDA
+	help
+	  Say Y here if you want to build support for the SMC Infrared
+	  Communications Controller.  It is used in a wide variety of
+	  laptops (Fujitsu, Sony, Compaq and some Toshiba).
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.  The module will be
+	  called smsc-ircc2.o.
+
 config ALI_FIR
 	tristate "ALi M5123 FIR (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && IRDA
diff -urN linux-2.5.69-bk18/drivers/net/irda/Makefile linux-2.5.69-bk19/drivers/net/irda/Makefile
--- linux-2.5.69-bk18/drivers/net/irda/Makefile	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/irda/Makefile	2003-05-26 04:41:42.000000000 -0700
@@ -15,13 +15,14 @@
 obj-$(CONFIG_SA1100_FIR)	+= sa1100_ir.o
 obj-$(CONFIG_TOSHIBA_OLD)	+= toshoboe.o
 obj-$(CONFIG_TOSHIBA_FIR)	+= donauboe.o
-obj-$(CONFIG_SMC_IRCC_FIR)	+= smc-ircc.o	irport.o
+obj-$(CONFIG_SMC_IRCC_OLD)	+= smc-ircc.o	irport.o
+obj-$(CONFIG_SMC_IRCC_FIR)	+= smsc-ircc2.o
 obj-$(CONFIG_ALI_FIR)		+= ali-ircc.o
 obj-$(CONFIG_VLSI_FIR)		+= vlsi_ir.o
 # Old dongle drivers for old SIR drivers
-obj-$(CONFIG_ESI_OLD)		+= esi.o
-obj-$(CONFIG_TEKRAM_OLD)	+= tekram.o
-obj-$(CONFIG_ACTISYS_OLD)	+= actisys.o
+obj-$(CONFIG_ESI_DONGLE_OLD)		+= esi.o
+obj-$(CONFIG_TEKRAM_DONGLE_OLD)	+= tekram.o
+obj-$(CONFIG_ACTISYS_DONGLE_OLD)	+= actisys.o
 obj-$(CONFIG_GIRBIL_DONGLE)	+= girbil.o
 obj-$(CONFIG_LITELINK_DONGLE)	+= litelink.o
 obj-$(CONFIG_OLD_BELKIN_DONGLE)	+= old_belkin.o
diff -urN linux-2.5.69-bk18/drivers/net/irda/ali-ircc.c linux-2.5.69-bk19/drivers/net/irda/ali-ircc.c
--- linux-2.5.69-bk18/drivers/net/irda/ali-ircc.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/irda/ali-ircc.c	2003-05-26 04:41:42.000000000 -0700
@@ -1451,6 +1451,7 @@
 		/* Check for empty frame */
 		if (!skb->len) {
 			ali_ircc_change_speed(self, speed); 
+			dev->trans_start = jiffies;
 			spin_unlock_irqrestore(&self->lock, flags);
 			dev_kfree_skb(skb);
 			return 0;
@@ -1560,6 +1561,7 @@
 	/* Restore bank register */
 	switch_bank(iobase, BANK0);
 
+	dev->trans_start = jiffies;
 	spin_unlock_irqrestore(&self->lock, flags);
 	dev_kfree_skb(skb);
 
@@ -1974,6 +1976,7 @@
 		/* Check for empty frame */
 		if (!skb->len) {
 			ali_ircc_change_speed(self, speed); 
+			dev->trans_start = jiffies;
 			spin_unlock_irqrestore(&self->lock, flags);
 			dev_kfree_skb(skb);
 			return 0;
@@ -1993,6 +1996,7 @@
 	/* Turn on transmit finished interrupt. Will fire immediately!  */
 	outb(UART_IER_THRI, iobase+UART_IER); 
 
+	dev->trans_start = jiffies;
 	spin_unlock_irqrestore(&self->lock, flags);
 
 	dev_kfree_skb(skb);
diff -urN linux-2.5.69-bk18/drivers/net/irda/donauboe.c linux-2.5.69-bk19/drivers/net/irda/donauboe.c
--- linux-2.5.69-bk18/drivers/net/irda/donauboe.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/irda/donauboe.c	2003-05-26 04:41:42.000000000 -0700
@@ -1051,7 +1051,9 @@
 
   toshoboe_checkstuck (self);
 
-  /* Check if we need to change the speed */
+  dev->trans_start = jiffies;
+
+ /* Check if we need to change the speed */
   /* But not now. Wait after transmission if mtt not required */
   speed=irda_get_next_speed(skb);
   if ((speed != self->io.speed) && (speed != -1))
diff -urN linux-2.5.69-bk18/drivers/net/irda/irport.c linux-2.5.69-bk19/drivers/net/irda/irport.c
--- linux-2.5.69-bk18/drivers/net/irda/irport.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/irda/irport.c	2003-05-26 04:41:42.000000000 -0700
@@ -11,6 +11,7 @@
  * Sources:	  serial.c by Linus Torvalds 
  * 
  *     Copyright (c) 1997, 1998, 1999-2000 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 2000-2003 Jean Tourrilhes, All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -48,6 +49,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
+#include <linux/delay.h>
 #include <linux/rtnetlink.h>
 
 #include <asm/system.h>
@@ -72,14 +74,14 @@
 static struct irport_cb *dev_self[] = { NULL, NULL, NULL, NULL};
 static char *driver_name = "irport";
 
-static void irport_write_wakeup(struct irport_cb *self);
-static int  irport_write(int iobase, int fifo_size, __u8 *buf, int len);
-static void irport_receive(struct irport_cb *self);
+static inline void irport_write_wakeup(struct irport_cb *self);
+static inline int  irport_write(int iobase, int fifo_size, __u8 *buf, int len);
+static inline void irport_receive(struct irport_cb *self);
 
 static int  irport_net_init(struct net_device *dev);
 static int  irport_net_ioctl(struct net_device *dev, struct ifreq *rq, 
 			     int cmd);
-static int  irport_is_receiving(struct irport_cb *self);
+static inline int  irport_is_receiving(struct irport_cb *self);
 static int  irport_set_dtr_rts(struct net_device *dev, int dtr, int rts);
 static int  irport_raw_write(struct net_device *dev, __u8 *buf, int len);
 static struct net_device_stats *irport_net_get_stats(struct net_device *dev);
@@ -169,7 +171,7 @@
 	self->io.sir_base  = iobase;
         self->io.sir_ext   = IO_EXTENT;
         self->io.irq       = irq;
-        self->io.fifo_size = 16;
+        self->io.fifo_size = 16;		/* 16550A and compatible */
 
 	/* Initialize QoS for this device */
 	irda_init_max_qos_capabilies(&self->qos);
@@ -181,39 +183,47 @@
 	irda_qos_bits_to_value(&self->qos);
 	
 	self->flags = IFF_SIR|IFF_PIO;
+	self->mode = IRDA_IRLAP;
+
+	/* Bootstrap ZeroCopy Rx */
+	self->rx_buff.truesize = IRDA_SKB_MAX_MTU;
+	self->rx_buff.skb = __dev_alloc_skb(self->rx_buff.truesize,
+					    GFP_KERNEL);
+	if (self->rx_buff.skb == NULL)
+		return NULL;
+	skb_reserve(self->rx_buff.skb, 1);
+	self->rx_buff.head = self->rx_buff.skb->data;
+	/* No need to memset the buffer, unless you are really pedantic */
+
+	/* Finish setup the Rx buffer descriptor */
+	self->rx_buff.in_frame = FALSE;
+	self->rx_buff.state = OUTSIDE_FRAME;
+	self->rx_buff.data = self->rx_buff.head;
 
 	/* Specify how much memory we want */
-	self->rx_buff.truesize = 4000; 
 	self->tx_buff.truesize = 4000;
 	
 	/* Allocate memory if needed */
-	if (self->rx_buff.truesize > 0) {
-		self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
-						      GFP_KERNEL);
-		if (self->rx_buff.head == NULL)
-			return NULL;
-		memset(self->rx_buff.head, 0, self->rx_buff.truesize);
-	}
 	if (self->tx_buff.truesize > 0) {
 		self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
 						      GFP_KERNEL);
 		if (self->tx_buff.head == NULL) {
-			kfree(self->rx_buff.head);
+			kfree_skb(self->rx_buff.skb);
+			self->rx_buff.skb = NULL;
+			self->rx_buff.head = NULL;
 			return NULL;
 		}
 		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 	}	
-	self->rx_buff.in_frame = FALSE;
-	self->rx_buff.state = OUTSIDE_FRAME;
 	self->tx_buff.data = self->tx_buff.head;
-	self->rx_buff.data = self->rx_buff.head;
-	self->mode = IRDA_IRLAP;
 
 	if (!(dev = dev_alloc("irda%d", &err))) {
 		ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
 		return NULL;
 	}
 	self->netdev = dev;
+	/* Keep track of module usage */
+	SET_MODULE_OWNER(dev);
 
 	/* May be overridden by piggyback drivers */
  	dev->priv = (void *) self;
@@ -241,7 +251,8 @@
 		ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
 		return NULL;
 	}
-	MESSAGE("IrDA: Registered device %s\n", dev->name);
+	MESSAGE("IrDA: Registered device %s (irport io=0x%X irq=%d)\n",
+		dev->name, iobase, irq);
 
 	return self;
 }
@@ -270,8 +281,9 @@
 	if (self->tx_buff.head)
 		kfree(self->tx_buff.head);
 	
-	if (self->rx_buff.head)
-		kfree(self->rx_buff.head);
+	if (self->rx_buff.skb)
+		kfree_skb(self->rx_buff.skb);
+	self->rx_buff.skb = NULL;
 	
 	/* Remove ourselves */
 	dev_self[self->index] = NULL;
@@ -306,6 +318,9 @@
 
 	/* We can't lock, we may be called from a FIR driver - Jean II */
 
+	/* We are not transmitting any more */
+	self->transmitting = 0;
+
 	/* Reset UART */
 	outb(0, iobase+UART_MCR);
 	
@@ -327,6 +342,33 @@
 }
 
 /*
+ * Function irport_get_fcr (speed)
+ *
+ *    Compute value of fcr
+ *
+ */
+static inline unsigned int irport_get_fcr(__u32 speed)
+{
+	unsigned int fcr;    /* FIFO control reg */
+
+	/* Enable fifos */
+	fcr = UART_FCR_ENABLE_FIFO;
+
+	/* 
+	 * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
+	 * almost 1,7 ms at 19200 bps. At speeds above that we can just forget
+	 * about this timeout since it will always be fast enough. 
+	 */
+	if (speed < 38400)
+		fcr |= UART_FCR_TRIGGER_1;
+	else 
+		//fcr |= UART_FCR_TRIGGER_14;
+		fcr |= UART_FCR_TRIGGER_8;
+
+	return(fcr);
+}
+ 
+/*
  * Function irport_change_speed (self, speed)
  *
  *    Set speed of IrDA port to specified baudrate
@@ -337,11 +379,12 @@
 {
 	struct irport_cb *self = (struct irport_cb *) priv;
 	int iobase; 
-	int fcr;    /* FIFO control reg */
-	int lcr;    /* Line control reg */
+	unsigned int fcr;    /* FIFO control reg */
+	unsigned int lcr;    /* Line control reg */
 	int divisor;
 
 	ASSERT(self != NULL, return;);
+	ASSERT(speed != 0, return;);
 
 	IRDA_DEBUG(1, "%s(), Setting speed to: %d - iobase=%#x\n",
 		    __FUNCTION__, speed, self->io.sir_base);
@@ -358,18 +401,9 @@
 
 	divisor = SPEED_MAX/speed;
 	
-	fcr = UART_FCR_ENABLE_FIFO;
+	/* Get proper fifo configuration */
+	fcr = irport_get_fcr(speed);
 
-	/* 
-	 * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
-	 * almost 1,7 ms at 19200 bps. At speeds above that we can just forget
-	 * about this timeout since it will always be fast enough. 
-	 */
-	if (self->io.speed < 38400)
-		fcr |= UART_FCR_TRIGGER_1;
-	else 
-		fcr |= UART_FCR_TRIGGER_14;
-        
 	/* IrDA ports use 8N1 */
 	lcr = UART_LCR_WLEN8;
 	
@@ -380,7 +414,7 @@
 	outb(fcr,		  iobase+UART_FCR); /* Enable FIFO's */
 
 	/* Turn on interrups */
-	/* This will generate a fata interrupt storm.
+	/* This will generate a fatal interrupt storm.
 	 * People calling us will do that properly - Jean II */
 	//outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER);
 }
@@ -467,8 +501,8 @@
 		irda_task_next_state(task, IRDA_TASK_DONE);
 		ret = -1;
 		break;
-	}	
-	/* Put stuff in the sate we found them - Jean II */
+	}
+	/* Put stuff in the state we found them - Jean II */
 	if(wasunlocked) {
 		spin_unlock_irqrestore(&self->lock, flags);
 	}
@@ -477,98 +511,6 @@
 }
 
 /*
- * Function irport_write_wakeup (tty)
- *
- *    Called by the driver when there's room for more data.  If we have
- *    more packets to send, we send them here.
- *
- */
-static void irport_write_wakeup(struct irport_cb *self)
-{
-	int actual = 0;
-	int iobase;
-	int fcr;
-
-	ASSERT(self != NULL, return;);
-
-	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
-
-	iobase = self->io.sir_base;
-
-	/* Finished with frame?  */
-	if (self->tx_buff.len > 0)  {
-		/* Write data left in transmit buffer */
-		actual = irport_write(iobase, self->io.fifo_size, 
-				      self->tx_buff.data, self->tx_buff.len);
-		self->tx_buff.data += actual;
-		self->tx_buff.len  -= actual;
-
-		/* Turn on transmit finished interrupt. */
-		outb(UART_IER_THRI, iobase+UART_IER); 
-	} else {
-		/* 
-		 *  Now serial buffer is almost free & we can start 
-		 *  transmission of another packet. But first we must check
-		 *  if we need to change the speed of the hardware
-		 */
-		if (self->new_speed) {
-			IRDA_DEBUG(5, "%s(), Changing speed!\n", __FUNCTION__);
-			irda_task_execute(self, __irport_change_speed, 
-					  irport_change_speed_complete, 
-					  NULL, (void *) self->new_speed);
-			self->new_speed = 0;
-			IRDA_DEBUG(5, "%s(), Speed changed!\n", __FUNCTION__ );
-		} else {
-			/* Tell network layer that we want more frames */
-			netif_wake_queue(self->netdev);
-		}
-		self->stats.tx_packets++;
-
-		/* 
-		 * Reset Rx FIFO to make sure that all reflected transmit data
-		 * is discarded. This is needed for half duplex operation
-		 */
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR;
-		if (self->io.speed < 38400)
-			fcr |= UART_FCR_TRIGGER_1;
-		else 
-			fcr |= UART_FCR_TRIGGER_14;
-
-		outb(fcr, iobase+UART_FCR);
-
-		/* Turn on receive interrupts */
-		outb(UART_IER_RDI, iobase+UART_IER);
-	}
-}
-
-/*
- * Function irport_write (driver)
- *
- *    Fill Tx FIFO with transmit data
- *
- */
-static int irport_write(int iobase, int fifo_size, __u8 *buf, int len)
-{
-	int actual = 0;
-
-	/* Tx FIFO should be empty! */
-	if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
-		IRDA_DEBUG(0, "%s(), failed, fifo not empty!\n", __FUNCTION__);
-		return 0;
-	}
-        
-	/* Fill FIFO with current frame */
-	while ((fifo_size-- > 0) && (actual < len)) {
-		/* Transmit next byte */
-		outb(buf[actual], iobase+UART_TX);
-
-		actual++;
-	}
-        
-	return actual;
-}
-
-/*
  * Function irport_change_speed_complete (task)
  *
  *    Called when the change speed operation completes
@@ -604,24 +546,80 @@
 {
 	struct irport_cb *self;
 	int iobase;
+	int iir, lsr;
 	unsigned long flags;
 
 	self = (struct irport_cb *) dev->priv;
+	ASSERT(self != NULL, return;);
 	iobase = self->io.sir_base;
 	
-	WARNING("%s: transmit timed out\n", dev->name);
+	WARNING("%s: transmit timed out, jiffies = %ld, trans_start = %ld\n",
+		dev->name, jiffies, dev->trans_start);
 	spin_lock_irqsave(&self->lock, flags);
+
+	/* Debug what's happening... */
+
+	/* Get interrupt status */
+	lsr = inb(iobase+UART_LSR);
+	/* Read interrupt register */
+	iir = inb(iobase+UART_IIR);
+	IRDA_DEBUG(0, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", 
+		   __FUNCTION__, iir, lsr, iobase);
+
+	IRDA_DEBUG(0, "%s(), transmitting=%d, remain=%d, done=%d\n", 
+		   __FUNCTION__, self->transmitting, self->tx_buff.len,
+		   self->tx_buff.data - self->tx_buff.head);
+
+	/* Now, restart the port */
 	irport_start(self);
 	self->change_speed(self->priv, self->io.speed);
 	/* This will re-enable irqs */
 	outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER);
+	dev->trans_start = jiffies;
 	spin_unlock_irqrestore(&self->lock, flags);
 
-	dev->trans_start = jiffies;
 	netif_wake_queue(dev);
 }
  
 /*
+ * Function irport_wait_hw_transmitter_finish ()
+ *
+ *    Wait for the real end of HW transmission
+ *
+ * The UART is a strict FIFO, and we get called only when we have finished
+ * pushing data to the FIFO, so the maximum amount of time we must wait
+ * is only for the FIFO to drain out.
+ *
+ * We use a simple calibrated loop. We may need to adjust the loop
+ * delay (udelay) to balance I/O traffic and latency. And we also need to
+ * adjust the maximum timeout.
+ * It would probably be better to wait for the proper interrupt,
+ * but it doesn't seem to be available.
+ *
+ * We can't use jiffies or kernel timers because :
+ * 1) We are called from the interrupt handler, which disable softirqs,
+ * so jiffies won't be increased
+ * 2) Jiffies granularity is usually very coarse (10ms), and we don't
+ * want to wait that long to detect stuck hardware.
+ * Jean II
+ */
+
+static void irport_wait_hw_transmitter_finish(struct irport_cb *self)
+{
+	int iobase;
+	int count = 1000;	/* 1 ms */
+	
+	iobase = self->io.sir_base;
+
+	/* Calibrated busy loop */
+	while((count-- > 0) && !(inb(iobase+UART_LSR) & UART_LSR_TEMT))
+		udelay(1);
+
+	if(count == 0)
+		IRDA_DEBUG(0, "%s(): stuck transmitter\n", __FUNCTION__);
+}
+
+/*
  * Function irport_hard_start_xmit (struct sk_buff *skb, struct net_device *dev)
  *
  *    Transmits the current frame until FIFO is full, then
@@ -645,8 +643,8 @@
 	iobase = self->io.sir_base;
 
 	netif_stop_queue(dev);
-	
-	/* Make sure tests *& speed change are atomic */
+
+	/* Make sure tests & speed change are atomic */
 	spin_lock_irqsave(&self->lock, flags);
 
 	/* Check if we need to change the speed */
@@ -654,10 +652,21 @@
 	if ((speed != self->io.speed) && (speed != -1)) {
 		/* Check for empty frame */
 		if (!skb->len) {
+			/*
+			 * We send frames one by one in SIR mode (no
+			 * pipelining), so at this point, if we were sending
+			 * a previous frame, we just received the interrupt
+			 * telling us it is finished (UART_IIR_THRI).
+			 * Therefore, waiting for the transmitter to really
+			 * finish draining the fifo won't take too long.
+			 * And the interrupt handler is not expected to run.
+			 * - Jean II */
+			irport_wait_hw_transmitter_finish(self);
 			/* Better go there already locked - Jean II */
 			irda_task_execute(self, __irport_change_speed, 
 					  irport_change_speed_complete, 
 					  NULL, (void *) speed);
+			dev->trans_start = jiffies;
 			spin_unlock_irqrestore(&self->lock, flags);
 			dev_kfree_skb(skb);
 			return 0;
@@ -674,9 +683,13 @@
 	
 	self->stats.tx_bytes += self->tx_buff.len;
 
+	/* We are transmitting */
+	self->transmitting = 1;
+
 	/* Turn on transmit finished interrupt. Will fire immediately!  */
 	outb(UART_IER_THRI, iobase+UART_IER); 
 
+	dev->trans_start = jiffies;
 	spin_unlock_irqrestore(&self->lock, flags);
 
 	dev_kfree_skb(skb);
@@ -685,12 +698,100 @@
 }
         
 /*
+ * Function irport_write (driver)
+ *
+ *    Fill Tx FIFO with transmit data
+ *
+ * Called only from irport_write_wakeup()
+ */
+static inline int irport_write(int iobase, int fifo_size, __u8 *buf, int len)
+{
+	int actual = 0;
+
+	/* Fill FIFO with current frame */
+	while ((actual < fifo_size) && (actual < len)) {
+		/* Transmit next byte */
+		outb(buf[actual], iobase+UART_TX);
+
+		actual++;
+	}
+        
+	return actual;
+}
+
+/*
+ * Function irport_write_wakeup (tty)
+ *
+ *    Called by the driver when there's room for more data.  If we have
+ *    more packets to send, we send them here.
+ *
+ * Called only from irport_interrupt()
+ * Make sure this function is *not* called while we are receiving,
+ * otherwise we will reset fifo and loose data :-(
+ */
+static inline void irport_write_wakeup(struct irport_cb *self)
+{
+	int actual = 0;
+	int iobase;
+	unsigned int fcr;
+
+	ASSERT(self != NULL, return;);
+
+	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
+
+	iobase = self->io.sir_base;
+
+	/* Finished with frame?  */
+	if (self->tx_buff.len > 0)  {
+		/* Write data left in transmit buffer */
+		actual = irport_write(iobase, self->io.fifo_size, 
+				      self->tx_buff.data, self->tx_buff.len);
+		self->tx_buff.data += actual;
+		self->tx_buff.len  -= actual;
+	} else {
+		/* 
+		 *  Now serial buffer is almost free & we can start 
+		 *  transmission of another packet. But first we must check
+		 *  if we need to change the speed of the hardware
+		 */
+		if (self->new_speed) {
+			irport_wait_hw_transmitter_finish(self);
+			irda_task_execute(self, __irport_change_speed, 
+					  irport_change_speed_complete, 
+					  NULL, (void *) self->new_speed);
+			self->new_speed = 0;
+		} else {
+			/* Tell network layer that we want more frames */
+			netif_wake_queue(self->netdev);
+		}
+		self->stats.tx_packets++;
+
+		/* 
+		 * Reset Rx FIFO to make sure that all reflected transmit data
+		 * is discarded. This is needed for half duplex operation
+		 */
+		fcr = irport_get_fcr(self->io.speed);
+		fcr |= UART_FCR_CLEAR_RCVR;
+		outb(fcr, iobase+UART_FCR);
+
+		/* Finished transmitting */
+		self->transmitting = 0;
+
+		/* Turn on receive interrupts */
+		outb(UART_IER_RDI, iobase+UART_IER);
+
+		IRDA_DEBUG(1, "%s() : finished Tx\n", __FUNCTION__);
+	}
+}
+
+/*
  * Function irport_receive (self)
  *
  *    Receive one frame from the infrared port
  *
+ * Called only from irport_interrupt()
  */
-static void irport_receive(struct irport_cb *self) 
+static inline void irport_receive(struct irport_cb *self) 
 {
 	int boguscount = 0;
 	int iobase;
@@ -739,40 +840,51 @@
 
 	iobase = self->io.sir_base;
 
-	iir = inb(iobase+UART_IIR) & UART_IIR_ID;
-	while (iir) {
-		handled = 1;
+	/* Cut'n'paste interrupt routine from serial.c
+	 * This version try to minimise latency and I/O operations.
+	 * Simplified and modified to enforce half duplex operation.
+	 * - Jean II */
 
-		/* Clear interrupt */
+	/* Check status even is iir reg is cleared, more robust and
+	 * eliminate a read on the I/O bus - Jean II */
+	do {
+		/* Get interrupt status ; Clear interrupt */
 		lsr = inb(iobase+UART_LSR);
-
-		IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", 
-			   __FUNCTION__, iir, lsr, iobase);
-
-		switch (iir) {
-		case UART_IIR_RLSI:
-			IRDA_DEBUG(2, "%s(), RLSI\n", __FUNCTION__);
-			break;
-		case UART_IIR_RDI:
-			/* Receive interrupt */
-			irport_receive(self);
-			break;
-		case UART_IIR_THRI:
-			if (lsr & UART_LSR_THRE)
-				/* Transmitter ready for data */
-				irport_write_wakeup(self);
-			break;
-		default:
-			IRDA_DEBUG(0, "%s(), unhandled IIR=%#x\n", __FUNCTION__, iir);
-			break;
-		} 
 		
-		/* Make sure we don't stay here too long */
-		if (boguscount++ > 100)
+		/* Are we receiving or transmitting ? */
+		if(!self->transmitting) {
+			/* Received something ? */
+			if (lsr & UART_LSR_DR)
+				irport_receive(self);
+		} else {
+			/* Room in Tx fifo ? */
+			if (lsr & (UART_LSR_THRE | UART_LSR_TEMT))
+				irport_write_wakeup(self);
+		}
+
+		/* A bit hackish, but working as expected... Jean II */
+		if(lsr & (UART_LSR_THRE | UART_LSR_TEMT | UART_LSR_DR))
+			handled = 1;
+
+		/* Make sure we don't stay here to long */
+		if (boguscount++ > 10) {
+			WARNING("%s() irq handler looping : lsr=%02x\n",
+				__FUNCTION__, lsr);
 			break;
+		}
+
+		/* Read interrupt register */
+ 	        iir = inb(iobase+UART_IIR);
+
+		/* Enable this debug only when no other options and at low
+		 * bit rates, otherwise it may cause Rx overruns (lsr=63).
+		 * - Jean II */
+		IRDA_DEBUG(6, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", 
+			    __FUNCTION__, iir, lsr, iobase);
+
+		/* As long as interrupt pending... */
+	} while ((iir & UART_IIR_NO_INT) == 0);
 
- 	        iir = inb(iobase + UART_IIR) & UART_IIR_ID;
-	}
 	spin_unlock(&self->lock);
 	return IRQ_RETVAL(handled);
 }
@@ -800,8 +912,8 @@
 	char hwname[16];
 	unsigned long flags;
 
-	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
-	
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
+
 	ASSERT(dev != NULL, return -1;);
 	self = (struct irport_cb *) dev->priv;
 
@@ -815,7 +927,12 @@
 	}
 
 	spin_lock_irqsave(&self->lock, flags);
+	/* Init uart */
 	irport_start(self);
+	/* Set 9600 bauds per default, including at the dongle */
+	irda_task_execute(self, __irport_change_speed, 
+			  irport_change_speed_complete, 
+			  NULL, (void *) 9600);
 	spin_unlock_irqrestore(&self->lock, flags);
 
 
@@ -828,12 +945,9 @@
 	 */
 	self->irlap = irlap_open(dev, &self->qos, hwname);
 
-	/* FIXME: change speed of dongle */
 	/* Ready to play! */
 
 	netif_start_queue(dev);
-	
-	MOD_INC_USE_COUNT;
 
 	return 0;
 }
@@ -873,40 +987,16 @@
 
 	free_irq(self->io.irq, dev);
 
-	MOD_DEC_USE_COUNT;
-
 	return 0;
 }
 
 /*
- * Function irport_wait_until_sent (self)
- *
- *    Delay exectution until finished transmitting
- *
- */
-#if 0
-void irport_wait_until_sent(struct irport_cb *self)
-{
-	int iobase;
-
-	iobase = self->io.sir_base;
-
-	/* Wait until Tx FIFO is empty */
-	while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
-		IRDA_DEBUG(2, "%s(), waiting!\n", __FUNCTION__);
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(MSECS_TO_JIFFIES(60));
-	}
-}
-#endif
-
-/*
  * Function irport_is_receiving (self)
  *
  *    Returns true is we are currently receiving data
  *
  */
-static int irport_is_receiving(struct irport_cb *self)
+static inline int irport_is_receiving(struct irport_cb *self)
 {
 	return (self->rx_buff.state != OUTSIDE_FRAME);
 }
@@ -998,6 +1088,12 @@
 			break;
 		}
 
+		/* Locking :
+		 * irda_device_dongle_init() can't be locked.
+		 * irda_task_execute() doesn't need to be locked.
+		 * Jean II
+		 */
+
 		/* Initialize dongle */
 		dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
 		if (!dongle)
diff -urN linux-2.5.69-bk18/drivers/net/irda/irtty-sir.c linux-2.5.69-bk19/drivers/net/irda/irtty-sir.c
--- linux-2.5.69-bk18/drivers/net/irda/irtty-sir.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/irda/irtty-sir.c	2003-05-26 04:41:42.000000000 -0700
@@ -504,10 +504,7 @@
 	struct sirtty_cb *priv;
 	int ret = 0;
 
-	/* unfortunately, there's no tty_ldisc->owner field
-	 * so there is some window for SMP race with rmmod
-	 */
-	MOD_INC_USE_COUNT;
+	/* Module stuff handled via irda_ldisc.owner - Jean II */
 
 	/* First make sure we're not already connected. */
 	if (tty->disc_data != NULL) {
@@ -569,7 +566,6 @@
 out_put:
 	sirdev_put_instance(dev);
 out:
-	MOD_DEC_USE_COUNT;
 	return ret;
 }
 
@@ -614,8 +610,6 @@
 		tty->driver->stop(tty);
 
 	kfree(priv);
-
-	MOD_DEC_USE_COUNT;
 }
 
 /* ------------------------------------------------------- */
@@ -633,6 +627,7 @@
 	.receive_buf	= irtty_receive_buf,
 	.receive_room	= irtty_receive_room,
 	.write_wakeup	= irtty_write_wakeup,
+	.owner		= THIS_MODULE,
 };
 
 /* ------------------------------------------------------- */
diff -urN linux-2.5.69-bk18/drivers/net/irda/nsc-ircc.c linux-2.5.69-bk19/drivers/net/irda/nsc-ircc.c
--- linux-2.5.69-bk18/drivers/net/irda/nsc-ircc.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/irda/nsc-ircc.c	2003-05-26 04:41:42.000000000 -0700
@@ -1096,6 +1096,7 @@
 				 * to make sure packets gets through the
 				 * proper xmit handler - Jean II */
 			}
+			dev->trans_start = jiffies;
 			spin_unlock_irqrestore(&self->lock, flags);
 			dev_kfree_skb(skb);
 			return 0;
@@ -1120,6 +1121,7 @@
 	/* Restore bank register */
 	outb(bank, iobase+BSR);
 
+	dev->trans_start = jiffies;
 	spin_unlock_irqrestore(&self->lock, flags);
 
 	dev_kfree_skb(skb);
@@ -1164,6 +1166,7 @@
 				 * the speed change has been done.
 				 * Jean II */
 			}
+			dev->trans_start = jiffies;
 			spin_unlock_irqrestore(&self->lock, flags);
 			dev_kfree_skb(skb);
 			return 0;
@@ -1250,6 +1253,7 @@
 	/* Restore bank register */
 	outb(bank, iobase+BSR);
 
+	dev->trans_start = jiffies;
 	spin_unlock_irqrestore(&self->lock, flags);
 	dev_kfree_skb(skb);
 
diff -urN linux-2.5.69-bk18/drivers/net/irda/sir_kthread.c linux-2.5.69-bk19/drivers/net/irda/sir_kthread.c
--- linux-2.5.69-bk18/drivers/net/irda/sir_kthread.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/irda/sir_kthread.c	2003-05-26 04:41:42.000000000 -0700
@@ -151,6 +151,13 @@
 
 	while (irda_rq_queue.thread != NULL) {
 
+		/* We use TASK_INTERRUPTIBLE, rather than
+		 * TASK_UNINTERRUPTIBLE.  Andrew Morton made this
+		 * change ; he told me that it is safe, because "signal
+		 * blocking is now handled in daemonize()", he added
+		 * that the problem is that "uninterruptible sleep
+		 * contributes to load average", making user worry.
+		 * Jean II */
 		set_task_state(current, TASK_INTERRUPTIBLE);
 		add_wait_queue(&irda_rq_queue.kick, &wait);
 		if (list_empty(&irda_rq_queue.request_list))
diff -urN linux-2.5.69-bk18/drivers/net/irda/smc-ircc.c linux-2.5.69-bk19/drivers/net/irda/smc-ircc.c
--- linux-2.5.69-bk18/drivers/net/irda/smc-ircc.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/irda/smc-ircc.c	2003-05-26 04:41:42.000000000 -0700
@@ -529,6 +529,9 @@
 
 	irport->priv = self;
 
+	/* Keep track of module usage */
+	SET_MODULE_OWNER(self->netdev);
+
 	/* Initialize IO */
 	self->io           = &irport->io;
 	self->io->fir_base  = fir_base;
@@ -747,6 +750,7 @@
 		/* Check for empty frame */
 		if (!skb->len) {
 			ircc_change_speed(self, speed); 
+			dev->trans_start = jiffies;
 			spin_unlock_irqrestore(&self->irport->lock, flags);
 			dev_kfree_skb(skb);
 			return 0;
@@ -776,6 +780,7 @@
 		/* Transmit frame */
 		ircc_dma_xmit(self, iobase, 0);
 	}
+	dev->trans_start = jiffies;
 	spin_unlock_irqrestore(&self->irport->lock, flags);
 	dev_kfree_skb(skb);
 
@@ -1090,8 +1095,6 @@
 		WARNING("%s(), unable to allocate DMA=%d\n", __FUNCTION__, self->io->dma);
 		return -EAGAIN;
 	}
-	
-	MOD_INC_USE_COUNT;
 
 	return 0;
 }
@@ -1124,8 +1127,6 @@
 
 	free_dma(self->io->dma);
 
-	MOD_DEC_USE_COUNT;
-
 	return 0;
 }
 
@@ -1187,6 +1188,9 @@
 
         iobase = self->irport->io.fir_base;
 
+        if (self->pmdev)
+		pm_unregister(self->pmdev);
+
 	/* This will destroy irport */
 	irport_close(self->irport);
 
diff -urN linux-2.5.69-bk18/drivers/net/irda/smsc-ircc2.c linux-2.5.69-bk19/drivers/net/irda/smsc-ircc2.c
--- linux-2.5.69-bk18/drivers/net/irda/smsc-ircc2.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/drivers/net/irda/smsc-ircc2.c	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,2441 @@
+/*********************************************************************
+ * $Id: smsc-ircc2.c,v 1.19.2.5 2002/10/27 11:34:26 dip Exp $
+ *
+ * Description:   Driver for the SMC Infrared Communications Controller
+ * Status:        Experimental.
+ * Author:        Daniele Peri (peri@csai.unipa.it)
+ * Created at:    
+ * Modified at:   
+ * Modified by:   
+ * 
+ *     Copyright (c) 2002      Daniele Peri
+ *     All Rights Reserved.
+ *     Copyright (c) 2002      Jean Tourrilhes
+ *
+ *
+ * Based on smc-ircc.c:
+ *
+ *     Copyright (c) 2001      Stefani Seibold
+ *     Copyright (c) 1999-2001 Dag Brattli
+ *     Copyright (c) 1998-1999 Thomas Davis, 
+ *
+ *	and irport.c:
+ *
+ *     Copyright (c) 1997, 1998, 1999-2000 Dag Brattli, All Rights Reserved.
+ *
+ * 
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/rtnetlink.h>
+#include <linux/serial_reg.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+
+#include <linux/spinlock.h>
+#include <linux/pm.h>
+
+#include <net/irda/wrapper.h>
+#include <net/irda/irda.h>
+#include <net/irda/irda_device.h>
+
+#include "smsc-ircc2.h"
+#include "smsc-sio.h"
+
+/* Types */
+
+struct smsc_transceiver {
+	char *name;
+	void (*set_for_speed)(int fir_base, u32 speed);	
+	int  (*probe)(int fir_base);
+};
+typedef struct smsc_transceiver smsc_transceiver_t;
+
+#if 0
+struct smc_chip {
+	char *name;
+	u16 flags;
+	u8 devid;
+	u8 rev;
+};
+typedef struct smc_chip smc_chip_t;
+#endif
+
+struct smsc_chip {
+	char *name;
+	#if 0
+	u8	type;
+	#endif
+	u16 flags;
+	u8 devid;
+	u8 rev;
+};
+typedef struct smsc_chip smsc_chip_t;
+
+struct smsc_chip_address {
+	unsigned int cfg_base;
+	unsigned int type;
+};
+typedef struct smsc_chip_address smsc_chip_address_t;
+
+/* Private data for each instance */
+struct smsc_ircc_cb {
+	struct net_device *netdev;     /* Yes! we are some kind of netdevice */
+	struct net_device_stats stats;
+	struct irlap_cb    *irlap; /* The link layer we are binded to */
+	
+	chipio_t io;               /* IrDA controller information */
+	iobuff_t tx_buff;          /* Transmit buffer */
+	iobuff_t rx_buff;          /* Receive buffer */
+
+	struct qos_info qos;       /* QoS capabilities for this device */
+
+	spinlock_t lock;           /* For serializing operations */
+	
+	__u32 new_speed;
+	__u32 flags;               /* Interface flags */
+
+	int tx_buff_offsets[10];   /* Offsets between frames in tx_buff */
+	int tx_len;                /* Number of frames in tx_buff */
+
+	int transceiver;
+	struct pm_dev *pmdev;
+};
+
+/* Constants */
+
+static const char *driver_name = "smsc-ircc2";
+#define	DIM(x)	(sizeof(x)/(sizeof(*(x))))
+#define SMSC_IRCC2_C_IRDA_FALLBACK_SPEED	9600
+#define SMSC_IRCC2_C_DEFAULT_TRANSCEIVER	1
+#define SMSC_IRCC2_C_NET_TIMEOUT			0
+#define SMSC_IRCC2_C_SIR_STOP			0
+
+/* Prototypes */
+
+static int smsc_ircc_open(unsigned int firbase, unsigned int sirbase, u8 dma, u8 irq);
+static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base);
+static int smsc_ircc_setup_io(struct smsc_ircc_cb *self, unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq);
+static int smsc_ircc_setup_buffers(struct smsc_ircc_cb *self);
+static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self);
+static int smsc_ircc_setup_netdev(struct smsc_ircc_cb *self);
+static void smsc_ircc_init_chip(struct smsc_ircc_cb *self);
+static int __exit smsc_ircc_close(struct smsc_ircc_cb *self);
+static int  smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase); 
+static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self, int iobase);
+static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self);
+static int  smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev);
+static int  smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev);
+static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int iobase, int bofs);
+static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self, int iobase);
+static void smsc_ircc_change_speed(void *priv, u32 speed);
+static void smsc_ircc_set_sir_speed(void *priv, u32 speed);
+static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void smsc_ircc_interrupt_sir(int irq, void *dev_id, struct pt_regs *regs);
+static void smsc_ircc_sir_start(struct smsc_ircc_cb *self);
+#if SMSC_IRCC2_C_SIR_STOP
+static void smsc_ircc_sir_stop(struct smsc_ircc_cb *self);
+#endif
+static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self);
+static int  smsc_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len);
+static int  smsc_ircc_net_init(struct net_device *dev);
+static int  smsc_ircc_net_open(struct net_device *dev);
+static int  smsc_ircc_net_close(struct net_device *dev);
+static int  smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+#if SMSC_IRCC2_C_NET_TIMEOUT
+static void smsc_ircc_timeout(struct net_device *dev);
+#endif
+static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev);
+static int  smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
+static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self);
+static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self);
+static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed);
+static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self);
+
+/* Probing */
+static int __init smsc_ircc_look_for_chips(void);
+static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg,const smsc_chip_t *chip,char *type);
+static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfg_base, char *type);
+static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cfg_base, char *type);
+static int __init smsc_superio_fdc(unsigned short cfg_base);
+static int __init smsc_superio_lpc(unsigned short cfg_base);
+
+/* Transceivers specific functions */
+
+static void smsc_ircc_set_transceiver_toshiba_sat1800(int fir_base, u32 speed);
+static int  smsc_ircc_probe_transceiver_toshiba_sat1800(int fir_base);
+static void smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(int fir_base, u32 speed);
+static int  smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(int fir_base);
+static void smsc_ircc_set_transceiver_smsc_ircc_atc(int fir_base, u32 speed);
+static int  smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base);
+
+/* Power Management */
+
+static void smsc_ircc_suspend(struct smsc_ircc_cb *self);
+static void smsc_ircc_wakeup(struct smsc_ircc_cb *self);
+static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
+
+
+/* Transceivers for SMSC-ircc */
+
+smsc_transceiver_t smsc_transceivers[]=
+{
+	{ "Toshiba Satellite 1800 (GP data pin select)", smsc_ircc_set_transceiver_toshiba_sat1800, smsc_ircc_probe_transceiver_toshiba_sat1800},
+	{ "Fast pin select", smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select, smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select},
+	{ "ATC IRMode", smsc_ircc_set_transceiver_smsc_ircc_atc, smsc_ircc_probe_transceiver_smsc_ircc_atc},
+	{ NULL, NULL}
+};
+#define SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS (DIM(smsc_transceivers)-1)
+
+/*  SMC SuperIO chipsets definitions */
+
+#define	KEY55_1	0	/* SuperIO Configuration mode with Key <0x55> */
+#define	KEY55_2	1	/* SuperIO Configuration mode with Key <0x55,0x55> */
+#define	NoIRDA	2	/* SuperIO Chip has no IRDA Port */
+#define	SIR	0	/* SuperIO Chip has only slow IRDA */
+#define	FIR	4	/* SuperIO Chip has fast IRDA */
+#define	SERx4	8	/* SuperIO Chip supports 115,2 KBaud * 4=460,8 KBaud */
+
+static smsc_chip_t __initdata fdc_chips_flat[]=
+{
+	/* Base address 0x3f0 or 0x370 */
+	{ "37C44",	KEY55_1|NoIRDA,		0x00, 0x00 }, /* This chip cannot be detected */
+	{ "37C665GT",	KEY55_2|NoIRDA,		0x65, 0x01 },
+	{ "37C665GT",	KEY55_2|NoIRDA,		0x66, 0x01 },
+	{ "37C669",	KEY55_2|SIR|SERx4,	0x03, 0x02 },
+	{ "37C669",	KEY55_2|SIR|SERx4,	0x04, 0x02 }, /* ID? */
+	{ "37C78",	KEY55_2|NoIRDA,		0x78, 0x00 },
+	{ "37N769",	KEY55_1|FIR|SERx4,	0x28, 0x00 },
+	{ "37N869",	KEY55_1|FIR|SERx4,	0x29, 0x00 },
+	{ NULL }
+};
+
+static smsc_chip_t __initdata fdc_chips_paged[]=
+{
+	/* Base address 0x3f0 or 0x370 */
+	{ "37B72X",	KEY55_1|SIR|SERx4,	0x4c, 0x00 },
+	{ "37B77X",	KEY55_1|SIR|SERx4,	0x43, 0x00 },
+	{ "37B78X",	KEY55_1|SIR|SERx4,	0x44, 0x00 },
+	{ "37B80X",	KEY55_1|SIR|SERx4,	0x42, 0x00 },
+	{ "37C67X",	KEY55_1|FIR|SERx4,	0x40, 0x00 },
+	{ "37C93X",	KEY55_2|SIR|SERx4,	0x02, 0x01 },
+	{ "37C93XAPM",	KEY55_1|SIR|SERx4,	0x30, 0x01 },
+	{ "37C93XFR",	KEY55_2|FIR|SERx4,	0x03, 0x01 },
+	{ "37M707",	KEY55_1|SIR|SERx4,	0x42, 0x00 },
+	{ "37M81X",	KEY55_1|SIR|SERx4,	0x4d, 0x00 },
+	{ "37N958FR",	KEY55_1|FIR|SERx4,	0x09, 0x04 },
+	{ "37N971",	KEY55_1|FIR|SERx4,	0x0a, 0x00 },
+	{ "37N972",	KEY55_1|FIR|SERx4,	0x0b, 0x00 },
+	{ NULL }
+};
+
+static smsc_chip_t __initdata lpc_chips_flat[]=
+{
+	/* Base address 0x2E or 0x4E */
+	{ "47N227",	KEY55_1|FIR|SERx4,	0x5a, 0x00 },
+	{ "47N267",	KEY55_1|FIR|SERx4,	0x5e, 0x00 },
+	{ NULL }
+};
+
+static smsc_chip_t __initdata lpc_chips_paged[]=
+{
+	/* Base address 0x2E or 0x4E */
+	{ "47B27X",	KEY55_1|SIR|SERx4,	0x51, 0x00 },
+	{ "47B37X",	KEY55_1|SIR|SERx4,	0x52, 0x00 },
+	{ "47M10X",	KEY55_1|SIR|SERx4,	0x59, 0x00 },
+	{ "47M120",	KEY55_1|NoIRDA|SERx4,	0x5c, 0x00 },
+	{ "47M13X",	KEY55_1|SIR|SERx4,	0x59, 0x00 },
+	{ "47M14X",	KEY55_1|SIR|SERx4,	0x5f, 0x00 },
+	{ "47N252",	KEY55_1|FIR|SERx4,	0x0e, 0x00 },
+	{ "47S42X",	KEY55_1|SIR|SERx4,	0x57, 0x00 },
+	{ NULL }
+};
+
+#define SMSCSIO_TYPE_FDC	1
+#define SMSCSIO_TYPE_LPC	2
+#define SMSCSIO_TYPE_FLAT	4
+#define SMSCSIO_TYPE_PAGED	8
+
+static smsc_chip_address_t __initdata possible_addresses[]=
+{
+	{0x3f0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
+	{0x370, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
+	{0xe0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
+	{0x2e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
+	{0x4e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED},
+	{0,0}
+};
+
+/* Globals */
+
+static struct smsc_ircc_cb *dev_self[] = { NULL, NULL};
+
+static int ircc_irq=255;
+static int ircc_dma=255;
+static int ircc_fir=0;
+static int ircc_sir=0;
+static int ircc_cfg=0;
+static int ircc_transceiver=0;
+
+static unsigned short	dev_count=0;
+
+static inline void register_bank(int iobase, int bank)
+{
+        outb(((inb(iobase+IRCC_MASTER) & 0xf0) | (bank & 0x07)),
+               iobase+IRCC_MASTER);
+}
+
+
+/*******************************************************************************
+ *
+ *
+ * SMSC-ircc stuff
+ *
+ *
+ *******************************************************************************/
+
+/*
+ * Function smsc_ircc_init ()
+ *
+ *    Initialize chip. Just try to find out how many chips we are dealing with
+ *    and where they are
+ */
+int __init smsc_ircc_init(void)
+{
+	int ret=-ENODEV;
+
+	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+
+	dev_count=0;
+ 
+	if ((ircc_fir>0)&&(ircc_sir>0)) {
+		MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
+		MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
+
+		if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq) == 0)
+			return 0;
+
+		return -ENODEV;
+	}
+
+	/* try user provided configuration register base address */
+	if (ircc_cfg>0) {
+	        MESSAGE(" Overriding configuration address 0x%04x\n", ircc_cfg);
+		if (!smsc_superio_fdc(ircc_cfg))
+			ret = 0;
+		if (!smsc_superio_lpc(ircc_cfg))
+			ret = 0;
+	}
+	
+	if(smsc_ircc_look_for_chips()>0) ret = 0;
+	
+	return ret;
+}
+
+/*
+ * Function smsc_ircc_open (firbase, sirbase, dma, irq)
+ *
+ *    Try to open driver instance
+ *
+ */
+static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
+{
+	struct smsc_ircc_cb *self;
+	int err;
+	
+	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+
+	err= smsc_ircc_present(fir_base, sir_base);
+	if(err) return -ENODEV;
+		
+	if (dev_count>DIM(dev_self)) {
+	        WARNING("%s(), too many devices!\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+
+	/*
+	 *  Allocate new instance of the driver
+	 */
+	self = kmalloc(sizeof(struct smsc_ircc_cb), GFP_KERNEL);
+	if (self == NULL) {
+		ERROR("%s, Can't allocate memory for control block!\n",
+                      driver_name);
+		return -ENOMEM;
+	}
+	memset(self, 0, sizeof(struct smsc_ircc_cb));
+
+	/* Need to store self somewhere */
+	dev_self[dev_count++] = self;
+	spin_lock_init(&self->lock);
+
+	err = smsc_ircc_setup_buffers(self);
+	if(err) return err;
+	   
+	err= smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq);
+	if(err) return err;
+
+	smsc_ircc_setup_qos(self);
+
+	self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
+		
+	smsc_ircc_init_chip(self);
+	
+	if(ircc_transceiver > 0 && ircc_transceiver < SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS) self->transceiver = ircc_transceiver;
+	else smsc_ircc_probe_transceiver(self);
+
+	err = smsc_ircc_setup_netdev(self);
+	if(err) return err;
+
+	self->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, smsc_ircc_pmproc);
+	if (self->pmdev)
+		self->pmdev->data = self;
+
+	return 0;
+}
+
+/*
+ * Function smsc_ircc_present(fir_base, sir_base)
+ *
+ *    Check the smsc-ircc chip presence
+ *
+ */
+static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base)
+{
+	unsigned char low, high, chip, config, dma, irq, version;
+
+	if (check_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT) < 0) {
+		WARNING("%s: can't get fir_base of 0x%03x\n",
+			__FUNCTION__, fir_base);
+		return -ENODEV;
+	}
+#if POSSIBLE_USED_BY_SERIAL_DRIVER
+	if (check_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT) < 0) {
+		WARNING("%s: can't get sir_base of 0x%03x\n",
+			__FUNCTION__, sir_base);
+		return -ENODEV;
+	}
+#endif
+
+	register_bank(fir_base, 3);
+
+	high    = inb(fir_base+IRCC_ID_HIGH);
+	low     = inb(fir_base+IRCC_ID_LOW);
+	chip    = inb(fir_base+IRCC_CHIP_ID);
+	version = inb(fir_base+IRCC_VERSION);
+	config  = inb(fir_base+IRCC_INTERFACE);
+	dma     = config & IRCC_INTERFACE_DMA_MASK;
+	irq     = (config & IRCC_INTERFACE_IRQ_MASK) >> 4;
+
+	if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) { 
+	        WARNING("%s(), addr 0x%04x - no device found!\n",
+			__FUNCTION__, fir_base);
+		return -ENODEV;
+	}
+	MESSAGE("SMsC IrDA Controller found\n IrCC version %d.%d, "
+		"firport 0x%03x, sirport 0x%03x dma=%d, irq=%d\n",
+		chip & 0x0f, version, fir_base, sir_base, dma, irq);
+
+	return 0;
+}
+
+/*
+ * Function smsc_ircc_setup_buffers(self)
+ *
+ *    Setup RX/TX buffers
+ *
+ */
+static int smsc_ircc_setup_buffers(struct smsc_ircc_cb *self)
+{
+	self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE; 
+	self->tx_buff.truesize = SMSC_IRCC2_TX_BUFF_TRUESIZE;
+
+	self->rx_buff.head = (u8 *) kmalloc(self->rx_buff.truesize,
+					      GFP_KERNEL|GFP_DMA);
+	if (self->rx_buff.head == NULL) {
+		ERROR("%s, Can't allocate memory for receive buffer!\n",
+                      driver_name);
+		kfree(self);
+		return -ENOMEM;
+	}
+
+	self->tx_buff.head = (u8 *) kmalloc(self->tx_buff.truesize, 
+					      GFP_KERNEL|GFP_DMA);
+	if (self->tx_buff.head == NULL) {
+		ERROR("%s, Can't allocate memory for transmit buffer!\n",
+                      driver_name);
+		kfree(self->rx_buff.head);
+		kfree(self);
+		return -ENOMEM;
+	}
+
+	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+
+	self->rx_buff.in_frame = FALSE;
+	self->rx_buff.state = OUTSIDE_FRAME;
+	self->tx_buff.data = self->tx_buff.head;
+	self->rx_buff.data = self->rx_buff.head;
+
+	return 0;
+}
+
+/*
+ * Function smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq)
+ *
+ *    Setup I/O
+ *
+ */
+static int smsc_ircc_setup_io(struct smsc_ircc_cb *self, unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
+{
+	unsigned char config, chip_dma, chip_irq;
+	void *ret;
+
+	register_bank(fir_base, 3);
+	config  = inb(fir_base+IRCC_INTERFACE);
+	chip_dma     = config & IRCC_INTERFACE_DMA_MASK;
+	chip_irq     = (config & IRCC_INTERFACE_IRQ_MASK) >> 4;
+
+	self->io.fir_base  = fir_base;
+	self->io.sir_base  = sir_base;
+	self->io.fir_ext   = SMSC_IRCC2_FIR_CHIP_IO_EXTENT;
+	self->io.sir_ext   = SMSC_IRCC2_SIR_CHIP_IO_EXTENT;
+	self->io.fifo_size = SMSC_IRCC2_FIFO_SIZE;
+	self->io.speed = SMSC_IRCC2_C_IRDA_FALLBACK_SPEED;
+
+	if (irq < 255) {
+		if (irq != chip_irq)
+			MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
+				driver_name, chip_irq, irq);
+		self->io.irq = irq;
+	}
+	else
+		self->io.irq = chip_irq;
+	
+	if (dma < 255) {
+		if (dma != chip_dma)
+			MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
+				driver_name, chip_dma, dma);
+		self->io.dma = dma;
+	}
+	else
+		self->io.dma = chip_dma;
+
+	ret = request_region(self->io.fir_base, self->io.fir_ext, driver_name);
+	if (!ret) { 
+		WARNING("%s(), can't get iobase of 0x%03x\n",
+			__FUNCTION__, self->io.fir_base);
+		kfree(self->tx_buff.head);
+		kfree(self->rx_buff.head);
+		kfree(self);
+		return -ENODEV;
+	}
+	ret = request_region(self->io.sir_base, self->io.sir_ext, driver_name);
+	if (!ret) { 
+		WARNING("%s(), can't get iobase of 0x%03x\n",
+			__FUNCTION__, self->io.sir_base);
+		release_region(self->io.fir_base, self->io.fir_ext);
+		kfree(self->tx_buff.head);
+		kfree(self->rx_buff.head);
+		kfree(self);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/*
+ * Function smsc_ircc_setup_qos(self)
+ *
+ *    Setup qos
+ *
+ */
+static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self)
+{
+	/* Initialize QoS for this device */
+	irda_init_max_qos_capabilies(&self->qos);
+	
+	self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
+
+	self->qos.min_turn_time.bits = SMSC_IRCC2_MIN_TURN_TIME;
+	self->qos.window_size.bits = SMSC_IRCC2_WINDOW_SIZE;
+	irda_qos_bits_to_value(&self->qos);
+}
+
+/*
+ * Function smsc_ircc_init_chip(self)
+ *
+ *    Init chip
+ *
+ */
+static void smsc_ircc_init_chip(struct smsc_ircc_cb *self)
+{
+	int iobase, ir_mode, ctrl, fast; 
+	
+	ASSERT( self != NULL, return; );
+	iobase = self->io.fir_base;
+
+	ir_mode = IRCC_CFGA_IRDA_SIR_A;
+	ctrl = 0;
+	fast = 0;
+
+	register_bank(iobase, 0);
+	outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
+	outb(0x00, iobase+IRCC_MASTER);
+
+	register_bank(iobase, 1);
+	outb(((inb(iobase+IRCC_SCE_CFGA) & 0x87) | ir_mode), 
+	     iobase+IRCC_SCE_CFGA);
+
+#ifdef smsc_669 /* Uses pin 88/89 for Rx/Tx */
+	outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM), 
+	     iobase+IRCC_SCE_CFGB);
+#else	
+	outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
+	     iobase+IRCC_SCE_CFGB);
+#endif	
+	(void) inb(iobase+IRCC_FIFO_THRESHOLD);
+	outb(SMSC_IRCC2_FIFO_THRESHOLD, iobase+IRCC_FIFO_THRESHOLD);
+	
+	register_bank(iobase, 4);
+	outb((inb(iobase+IRCC_CONTROL) & 0x30) | ctrl, iobase+IRCC_CONTROL);
+	
+	register_bank(iobase, 0);
+	outb(fast, iobase+IRCC_LCR_A);
+
+	smsc_ircc_set_sir_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED);
+	
+	/* Power on device */
+	outb(0x00, iobase+IRCC_MASTER);
+}
+
+/*
+ * Function smsc_ircc_setup_netdev(self)
+ *
+ *    Alloc and setup network device
+ *
+ */
+static int smsc_ircc_setup_netdev(struct smsc_ircc_cb *self)
+{
+	struct net_device *dev;
+	int err;
+	/* Alloc netdev */
+
+	if (!(dev = dev_alloc("irda%d", &err))) {
+		ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
+		kfree(self->tx_buff.head);
+		kfree(self->rx_buff.head);
+		kfree(self);
+		return -ENOMEM;
+	}
+
+	dev->priv = (void *) self;
+	self->netdev = dev;
+
+	dev->init            = smsc_ircc_net_init;
+	dev->hard_start_xmit = smsc_ircc_hard_xmit_sir;
+	#if SMSC_IRCC2_C_NET_TIMEOUT
+	dev->tx_timeout	     = smsc_ircc_timeout;
+	dev->watchdog_timeo  = HZ*2;  /* Allow enough time for speed change */
+	#endif
+	dev->open            = smsc_ircc_net_open;
+	dev->stop            = smsc_ircc_net_close;
+	dev->do_ioctl        = smsc_ircc_net_ioctl;
+	dev->get_stats	     = smsc_ircc_net_get_stats;
+	
+	/* Make ifconfig display some details */
+	dev->base_addr = self->io.fir_base;
+	dev->irq = self->io.irq;
+
+	rtnl_lock();
+	err = register_netdevice(dev);
+	rtnl_unlock();
+	if (err) {
+		ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
+		kfree(self->tx_buff.head);
+		kfree(self->rx_buff.head);
+		kfree(self);
+		return -ENODEV;
+	}
+	MESSAGE("IrDA: Registered device %s\n", dev->name);
+
+	return 0;
+}
+
+/*
+ * Function smsc_ircc_net_ioctl (dev, rq, cmd)
+ *
+ *    Process IOCTL commands for this device
+ *
+ */
+static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct if_irda_req *irq = (struct if_irda_req *) rq;
+	struct smsc_ircc_cb *self;
+	unsigned long flags;
+	int ret = 0;
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+
+	IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
+	
+	switch (cmd) {
+	case SIOCSBANDWIDTH: /* Set bandwidth */
+		if (!capable(CAP_NET_ADMIN))
+			ret = -EPERM;
+                else {
+			/* Make sure we are the only one touching
+			 * self->io.speed and the hardware - Jean II */
+			spin_lock_irqsave(&self->lock, flags);
+			smsc_ircc_change_speed(self, irq->ifr_baudrate);
+			spin_unlock_irqrestore(&self->lock, flags);
+		}
+		break;
+	case SIOCSMEDIABUSY: /* Set media busy */
+		if (!capable(CAP_NET_ADMIN)) {
+			ret = -EPERM;
+			break;
+		}
+
+		irda_device_set_media_busy(self->netdev, TRUE);
+		break;
+	case SIOCGRECEIVING: /* Check if we are receiving right now */
+		irq->ifr_receiving = smsc_ircc_is_receiving(self);
+		break;
+	#if 0
+	case SIOCSDTRRTS:
+		if (!capable(CAP_NET_ADMIN)) {
+			ret = -EPERM;
+			break;
+		}
+		smsc_ircc_sir_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
+		break;
+	#endif
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	
+	return ret;
+}
+
+static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev)
+{
+	struct smsc_ircc_cb *self = (struct smsc_ircc_cb *) dev->priv;
+	
+	return &self->stats;
+}
+
+#if SMSC_IRCC2_C_NET_TIMEOUT
+/*
+ * Function smsc_ircc_timeout (struct net_device *dev)
+ *
+ *    The networking timeout management.
+ *
+ */
+
+static void smsc_ircc_timeout(struct net_device *dev)
+{
+	struct smsc_ircc_cb *self;
+	unsigned long flags;
+
+	self = (struct smsc_ircc_cb *) dev->priv;
+	
+	WARNING("%s: transmit timed out, changing speed to: %d\n", dev->name, self->io.speed);
+	spin_lock_irqsave(&self->lock, flags);
+	smsc_ircc_sir_start(self);
+	smsc_ircc_change_speed(self, self->io.speed);
+	dev->trans_start = jiffies;
+	netif_wake_queue(dev);
+	spin_unlock_irqrestore(&self->lock, flags);
+}
+#endif
+
+/*
+ * Function smsc_ircc_hard_xmit_sir (struct sk_buff *skb, struct net_device *dev)
+ *
+ *    Transmits the current frame until FIFO is full, then
+ *    waits until the next transmit interrupt, and continues until the
+ *    frame is transmitted.
+ */
+int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
+{
+	struct smsc_ircc_cb *self;
+	unsigned long flags;
+	int iobase;
+	s32 speed;
+
+	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+
+	ASSERT(dev != NULL, return 0;);
+	
+	self = (struct smsc_ircc_cb *) dev->priv;
+	ASSERT(self != NULL, return 0;);
+
+	iobase = self->io.sir_base;
+
+	netif_stop_queue(dev);
+	
+	/* Make sure test of self->io.speed & speed change are atomic */
+	spin_lock_irqsave(&self->lock, flags);
+
+	/* Check if we need to change the speed */
+	speed = irda_get_next_speed(skb);
+	if ((speed != self->io.speed) && (speed != -1)) {
+		/* Check for empty frame */
+		if (!skb->len) {
+			/*
+			 * We send frames one by one in SIR mode (no
+			 * pipelining), so at this point, if we were sending
+			 * a previous frame, we just received the interrupt
+			 * telling us it is finished (UART_IIR_THRI).
+			 * Therefore, waiting for the transmitter to really
+			 * finish draining the fifo won't take too long.
+			 * And the interrupt handler is not expected to run.
+			 * - Jean II */
+			smsc_ircc_sir_wait_hw_transmitter_finish(self);
+			smsc_ircc_change_speed(self, speed);
+			spin_unlock_irqrestore(&self->lock, flags);
+			dev_kfree_skb(skb);
+			return 0;
+		} else {
+			self->new_speed = speed;
+		}
+	}
+
+	/* Init tx buffer */
+	self->tx_buff.data = self->tx_buff.head;
+
+	/* Copy skb to tx_buff while wrapping, stuffing and making CRC */
+	self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
+					   self->tx_buff.truesize);
+	
+	self->stats.tx_bytes += self->tx_buff.len;
+
+	/* Turn on transmit finished interrupt. Will fire immediately!  */
+	outb(UART_IER_THRI, iobase+UART_IER); 
+
+	spin_unlock_irqrestore(&self->lock, flags);
+
+	dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+/*
+ * Function smsc_ircc_set_fir_speed (self, baud)
+ *
+ *    Change the speed of the device
+ *
+ */
+static void smsc_ircc_set_fir_speed(struct smsc_ircc_cb *self, u32 speed)
+{
+	int fir_base, ir_mode, ctrl, fast;
+
+	ASSERT(self != NULL, return;);
+	fir_base = self->io.fir_base;
+
+	self->io.speed = speed;
+
+	switch(speed) {
+	default:
+	case 576000:		
+		ir_mode = IRCC_CFGA_IRDA_HDLC;
+		ctrl = IRCC_CRC;
+		fast = 0;
+		IRDA_DEBUG(0, "%s(), handling baud of 576000\n", __FUNCTION__);
+		break;
+	case 1152000:
+		ir_mode = IRCC_CFGA_IRDA_HDLC;
+		ctrl = IRCC_1152 | IRCC_CRC;
+		fast = IRCC_LCR_A_FAST | IRCC_LCR_A_GP_DATA;
+		IRDA_DEBUG(0, "%s(), handling baud of 1152000\n",
+			   __FUNCTION__);
+		break;
+	case 4000000:
+		ir_mode = IRCC_CFGA_IRDA_4PPM;
+		ctrl = IRCC_CRC;
+		fast = IRCC_LCR_A_FAST;
+		IRDA_DEBUG(0, "%s(), handling baud of 4000000\n",
+			   __FUNCTION__);
+		break;
+	}
+	#if 0
+	Now in tranceiver!
+	/* This causes an interrupt */
+	register_bank(fir_base, 0);
+	outb((inb(fir_base+IRCC_LCR_A) &  0xbf) | fast, fir_base+IRCC_LCR_A);
+	#endif
+	
+	register_bank(fir_base, 1);
+	outb(((inb(fir_base+IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | ir_mode), fir_base+IRCC_SCE_CFGA);
+	
+	register_bank(fir_base, 4);
+	outb((inb(fir_base+IRCC_CONTROL) & 0x30) | ctrl, fir_base+IRCC_CONTROL);
+}
+
+/*
+ * Function smsc_ircc_fir_start(self)
+ *
+ *    Change the speed of the device
+ *
+ */
+static void smsc_ircc_fir_start(struct smsc_ircc_cb *self)
+{
+	struct net_device *dev;
+	int fir_base;
+
+	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+
+	ASSERT(self != NULL, return;);
+	dev = self->netdev;
+	ASSERT(dev != NULL, return;);
+
+	fir_base = self->io.fir_base;
+
+	/* Reset everything */
+
+	/* Install FIR transmit handler */
+	dev->hard_start_xmit = smsc_ircc_hard_xmit_fir;	
+
+	/* Clear FIFO */
+	outb(inb(fir_base+IRCC_LCR_A)|IRCC_LCR_A_FIFO_RESET, fir_base+IRCC_LCR_A);
+
+	/* Enable interrupt */
+	/*outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base+IRCC_IER);*/
+
+	register_bank(fir_base, 1);
+
+	/* Select the TX/RX interface */	
+#ifdef SMSC_669 /* Uses pin 88/89 for Rx/Tx */
+	outb(((inb(fir_base+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM), 
+	     fir_base+IRCC_SCE_CFGB);
+#else	
+	outb(((inb(fir_base+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
+	     fir_base+IRCC_SCE_CFGB);
+#endif	
+	(void) inb(fir_base+IRCC_FIFO_THRESHOLD);
+
+	/* Enable SCE interrupts */
+	outb(0, fir_base+IRCC_MASTER);
+	register_bank(fir_base, 0);
+	outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base+IRCC_IER);
+	outb(IRCC_MASTER_INT_EN, fir_base+IRCC_MASTER);
+}
+
+/*
+ * Function smsc_ircc_fir_stop(self, baud)
+ *
+ *    Change the speed of the device
+ *
+ */
+static void smsc_ircc_fir_stop(struct smsc_ircc_cb *self)
+{
+	int fir_base;
+
+	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+	
+	ASSERT(self != NULL, return;);
+
+	fir_base = self->io.fir_base;
+	register_bank(fir_base, 0);
+	/*outb(IRCC_MASTER_RESET, fir_base+IRCC_MASTER);*/	
+	outb(inb(fir_base+IRCC_LCR_B) & IRCC_LCR_B_SIP_ENABLE, fir_base+IRCC_LCR_B);
+}
+
+
+/*
+ * Function smsc_ircc_change_speed(self, baud)
+ *
+ *    Change the speed of the device
+ *
+ * This function *must* be called with spinlock held, because it may
+ * be called from the irq handler. - Jean II
+ */
+static void smsc_ircc_change_speed(void *priv, u32 speed)
+{
+	struct smsc_ircc_cb *self = (struct smsc_ircc_cb *) priv;
+	struct net_device *dev;
+	int iobase;
+	int last_speed_was_sir;
+	
+	IRDA_DEBUG(0, "%s() changing speed to: %d\n", __FUNCTION__, speed);
+
+	ASSERT(self != NULL, return;);
+	dev = self->netdev;
+	iobase = self->io.fir_base;
+
+	last_speed_was_sir = self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED;
+
+	#if 0
+	/* Temp Hack */
+	speed= 1152000;
+	self->io.speed = speed;
+	last_speed_was_sir = 0;
+	smsc_ircc_fir_start(self);	
+	#endif
+	
+	if(self->io.speed == 0)
+		smsc_ircc_sir_start(self);
+
+	#if 0
+	if(!last_speed_was_sir) speed = self->io.speed;
+	#endif
+
+	if(self->io.speed != speed) smsc_ircc_set_transceiver_for_speed(self, speed);
+
+	self->io.speed = speed;
+	
+	if(speed <= SMSC_IRCC2_MAX_SIR_SPEED) {
+		if(!last_speed_was_sir) {
+			smsc_ircc_fir_stop(self);
+			smsc_ircc_sir_start(self);
+		}
+		smsc_ircc_set_sir_speed(self, speed); 
+	}
+	else {
+		if(last_speed_was_sir) {
+			#if SMSC_IRCC2_C_SIR_STOP		
+			smsc_ircc_sir_stop(self);
+			#endif
+			smsc_ircc_fir_start(self);
+		}
+		smsc_ircc_set_fir_speed(self, speed);
+
+		#if 0
+		self->tx_buff.len = 10;
+		self->tx_buff.data = self->tx_buff.head;
+		
+		smsc_ircc_dma_xmit(self, iobase, 4000);
+		#endif
+		/* Be ready for incoming frames */
+		smsc_ircc_dma_receive(self, iobase);
+	}
+	
+	netif_wake_queue(dev);
+}
+
+/*
+ * Function smsc_ircc_set_sir_speed (self, speed)
+ *
+ *    Set speed of IrDA port to specified baudrate
+ *
+ */
+void smsc_ircc_set_sir_speed(void *priv, __u32 speed)
+{
+	struct smsc_ircc_cb *self = (struct smsc_ircc_cb *) priv;
+	int iobase; 
+	int fcr;    /* FIFO control reg */
+	int lcr;    /* Line control reg */
+	int divisor;
+
+	IRDA_DEBUG(0, "%s(), Setting speed to: %d\n", __FUNCTION__, speed);
+
+	ASSERT(self != NULL, return;);
+	iobase = self->io.sir_base;
+	
+	/* Update accounting for new speed */
+	self->io.speed = speed;
+
+	/* Turn off interrupts */
+	outb(0, iobase+UART_IER); 
+
+	divisor = SMSC_IRCC2_MAX_SIR_SPEED/speed;
+	
+	fcr = UART_FCR_ENABLE_FIFO;
+
+	/* 
+	 * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
+	 * almost 1,7 ms at 19200 bps. At speeds above that we can just forget
+	 * about this timeout since it will always be fast enough. 
+	 */
+	if (self->io.speed < 38400)
+		fcr |= UART_FCR_TRIGGER_1;
+	else 
+		fcr |= UART_FCR_TRIGGER_14;
+        
+	/* IrDA ports use 8N1 */
+	lcr = UART_LCR_WLEN8;
+	
+	outb(UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */
+	outb(divisor & 0xff,      iobase+UART_DLL); /* Set speed */
+	outb(divisor >> 8,	  iobase+UART_DLM);
+	outb(lcr,		  iobase+UART_LCR); /* Set 8N1	*/
+	outb(fcr,		  iobase+UART_FCR); /* Enable FIFO's */
+
+	/* Turn on interrups */
+	outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, iobase+UART_IER);
+
+	IRDA_DEBUG(2, "%s() speed changed to: %d\n", __FUNCTION__, speed);
+}
+
+
+/*
+ * Function smsc_ircc_hard_xmit_fir (skb, dev)
+ *
+ *    Transmit the frame!
+ *
+ */
+static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
+{
+	struct smsc_ircc_cb *self;
+	unsigned long flags;
+	s32 speed;
+	int iobase;
+	int mtt;
+
+	ASSERT(dev != NULL, return 0;);
+	self = (struct smsc_ircc_cb *) dev->priv;
+	ASSERT(self != NULL, return 0;);
+
+	iobase = self->io.fir_base;
+
+	netif_stop_queue(dev);
+
+	/* Make sure test of self->io.speed & speed change are atomic */
+	spin_lock_irqsave(&self->lock, flags);
+
+	/* Check if we need to change the speed after this frame */
+	speed = irda_get_next_speed(skb);
+	if ((speed != self->io.speed) && (speed != -1)) {
+		/* Check for empty frame */
+		if (!skb->len) {
+			/* Note : you should make sure that speed changes
+			 * are not going to corrupt any outgoing frame.
+			 * Look at nsc-ircc for the gory details - Jean II */
+			smsc_ircc_change_speed(self, speed); 
+			spin_unlock_irqrestore(&self->lock, flags);
+			dev_kfree_skb(skb);
+			return 0;
+		} else
+			self->new_speed = speed;
+	}
+	
+	memcpy(self->tx_buff.head, skb->data, skb->len);
+
+	self->tx_buff.len = skb->len;
+	self->tx_buff.data = self->tx_buff.head;
+	
+	mtt = irda_get_mtt(skb);	
+	if (mtt) {
+		int bofs;
+
+		/* 
+		 * Compute how many BOFs (STA or PA's) we need to waste the
+		 * min turn time given the speed of the link.
+		 */
+		bofs = mtt * (self->io.speed / 1000) / 8000;
+		if (bofs > 4095)
+			bofs = 4095;
+
+		smsc_ircc_dma_xmit(self, iobase, bofs);
+	} else {
+		/* Transmit frame */
+		smsc_ircc_dma_xmit(self, iobase, 0);
+	}
+	spin_unlock_irqrestore(&self->lock, flags);
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function smsc_ircc_dma_xmit (self, iobase)
+ *
+ *    Transmit data using DMA
+ *
+ */
+static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int iobase, int bofs)
+{
+	u8 ctrl;
+
+	IRDA_DEBUG(3, "%s\n", __FUNCTION__);
+#if 1
+	/* Disable Rx */
+	register_bank(iobase, 0);
+	outb(0x00, iobase+IRCC_LCR_B);
+#endif
+	register_bank(iobase, 1);
+	outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, 
+	     iobase+IRCC_SCE_CFGB);
+
+	self->io.direction = IO_XMIT;
+
+	/* Set BOF additional count for generating the min turn time */
+	register_bank(iobase, 4);
+	outb(bofs & 0xff, iobase+IRCC_BOF_COUNT_LO);
+	ctrl = inb(iobase+IRCC_CONTROL) & 0xf0;
+	outb(ctrl | ((bofs >> 8) & 0x0f), iobase+IRCC_BOF_COUNT_HI);
+
+	/* Set max Tx frame size */
+	outb(self->tx_buff.len >> 8, iobase+IRCC_TX_SIZE_HI);
+	outb(self->tx_buff.len & 0xff, iobase+IRCC_TX_SIZE_LO);
+
+	/*outb(UART_MCR_OUT2, self->io.sir_base + UART_MCR);*/
+	
+	/* Enable burst mode chip Tx DMA */
+	register_bank(iobase, 1);
+	outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
+	     IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
+
+	/* Setup DMA controller (must be done after enabling chip DMA) */
+	setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, 
+		  DMA_TX_MODE);
+
+	/* Enable interrupt */
+
+	register_bank(iobase, 0);
+	outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase+IRCC_IER);
+	outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
+	
+	/* Enable transmit */
+	outb(IRCC_LCR_B_SCE_TRANSMIT | IRCC_LCR_B_SIP_ENABLE, iobase+IRCC_LCR_B);
+}
+
+/*
+ * Function smsc_ircc_dma_xmit_complete (self)
+ *
+ *    The transfer of a frame in finished. This function will only be called 
+ *    by the interrupt handler
+ *
+ */
+static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self, int iobase)
+{
+	IRDA_DEBUG(3, "%s\n", __FUNCTION__);
+#if 0
+	/* Disable Tx */
+	register_bank(iobase, 0);
+	outb(0x00, iobase+IRCC_LCR_B);
+#endif
+	register_bank(self->io.fir_base, 1);
+	outb(inb(self->io.fir_base+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+	     self->io.fir_base+IRCC_SCE_CFGB);
+
+	/* Check for underrun! */
+	register_bank(iobase, 0);
+	if (inb(iobase+IRCC_LSR) & IRCC_LSR_UNDERRUN) {
+		self->stats.tx_errors++;
+		self->stats.tx_fifo_errors++;
+
+		/* Reset error condition */
+		register_bank(iobase, 0);
+		outb(IRCC_MASTER_ERROR_RESET, iobase+IRCC_MASTER);
+		outb(0x00, iobase+IRCC_MASTER);
+	} else {
+		self->stats.tx_packets++;
+		self->stats.tx_bytes +=  self->tx_buff.len;
+	}
+
+	/* Check if it's time to change the speed */
+	if (self->new_speed) {
+		smsc_ircc_change_speed(self, self->new_speed);		
+		self->new_speed = 0;
+	}
+
+	netif_wake_queue(self->netdev);
+}
+
+/*
+ * Function smsc_ircc_dma_receive(self)
+ *
+ *    Get ready for receiving a frame. The device will initiate a DMA
+ *    if it starts to receive a frame.
+ *
+ */
+static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase) 
+{
+#if 0
+	/* Turn off chip DMA */
+	register_bank(iobase, 1);
+	outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, 
+	     iobase+IRCC_SCE_CFGB);
+#endif
+	
+	/* Disable Tx */
+	register_bank(iobase, 0);
+	outb(0x00, iobase+IRCC_LCR_B);
+
+	/* Turn off chip DMA */
+	register_bank(iobase, 1);
+	outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, 
+	     iobase+IRCC_SCE_CFGB);
+
+	self->io.direction = IO_RECV;
+	self->rx_buff.data = self->rx_buff.head;
+
+	/* Set max Rx frame size */
+	register_bank(iobase, 4);
+	outb((2050 >> 8) & 0x0f, iobase+IRCC_RX_SIZE_HI);
+	outb(2050 & 0xff, iobase+IRCC_RX_SIZE_LO);
+
+	/* Setup DMA controller */
+	setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, 
+		  DMA_RX_MODE);
+
+	/* Enable burst mode chip Rx DMA */
+	register_bank(iobase, 1);
+	outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE | 
+	     IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
+
+	/* Enable interrupt */
+	register_bank(iobase, 0);
+	outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase+IRCC_IER);
+	outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
+
+
+	/* Enable receiver */
+	register_bank(iobase, 0);
+	outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE, 
+	     iobase+IRCC_LCR_B);
+	
+	return 0;
+}
+
+/*
+ * Function smsc_ircc_dma_receive_complete(self, iobase)
+ *
+ *    Finished with receiving frames
+ *
+ */
+static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self, int iobase)
+{
+	struct sk_buff *skb;
+	int len, msgcnt, lsr;
+	
+	register_bank(iobase, 0);
+	
+	IRDA_DEBUG(3, "%s\n", __FUNCTION__);
+#if 0
+	/* Disable Rx */
+	register_bank(iobase, 0);
+	outb(0x00, iobase+IRCC_LCR_B);
+#endif
+	register_bank(iobase, 0);
+	outb(inb(iobase+IRCC_LSAR) & ~IRCC_LSAR_ADDRESS_MASK, iobase+IRCC_LSAR);
+	lsr= inb(iobase+IRCC_LSR);
+	msgcnt = inb(iobase+IRCC_LCR_B) & 0x08;
+
+	IRDA_DEBUG(2, "%s: dma count = %d\n", __FUNCTION__,
+		   get_dma_residue(self->io.dma));
+
+	len = self->rx_buff.truesize - get_dma_residue(self->io.dma);
+
+	/* Look for errors 
+	 */	
+
+	if(lsr & (IRCC_LSR_FRAME_ERROR | IRCC_LSR_CRC_ERROR | IRCC_LSR_SIZE_ERROR)) {
+		self->stats.rx_errors++;
+		if(lsr & IRCC_LSR_FRAME_ERROR) self->stats.rx_frame_errors++;
+		if(lsr & IRCC_LSR_CRC_ERROR) self->stats.rx_crc_errors++;
+		if(lsr & IRCC_LSR_SIZE_ERROR) self->stats.rx_length_errors++;
+		if(lsr & (IRCC_LSR_UNDERRUN | IRCC_LSR_OVERRUN)) self->stats.rx_length_errors++;
+		return;
+	}
+	/* Remove CRC */
+	if (self->io.speed < 4000000)
+		len -= 2;
+	else
+		len -= 4;
+
+	if ((len < 2) || (len > 2050)) {
+		WARNING("%s(), bogus len=%d\n", __FUNCTION__, len);
+		return;
+	}
+	IRDA_DEBUG(2, "%s: msgcnt = %d, len=%d\n", __FUNCTION__, msgcnt, len);
+
+	skb = dev_alloc_skb(len+1);
+	if (!skb)  {
+		WARNING("%s(), memory squeeze, dropping frame.\n",
+			__FUNCTION__);
+		return;
+	}			
+	/* Make sure IP header gets aligned */
+	skb_reserve(skb, 1); 
+
+	memcpy(skb_put(skb, len), self->rx_buff.data, len);
+	self->stats.rx_packets++;
+	self->stats.rx_bytes += len;
+
+	skb->dev = self->netdev;
+	skb->mac.raw  = skb->data;
+	skb->protocol = htons(ETH_P_IRDA);
+	netif_rx(skb);
+}
+
+/*
+ * Function smsc_ircc_sir_receive (self)
+ *
+ *    Receive one frame from the infrared port
+ *
+ */
+static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self) 
+{
+	int boguscount = 0;
+	int iobase;
+
+	ASSERT(self != NULL, return;);
+
+	iobase = self->io.sir_base;
+
+	/*  
+	 * Receive all characters in Rx FIFO, unwrap and unstuff them. 
+         * async_unwrap_char will deliver all found frames  
+	 */
+	do {
+		async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, 
+				  inb(iobase+UART_RX));
+
+		/* Make sure we don't stay here to long */
+		if (boguscount++ > 32) {
+			IRDA_DEBUG(2, "%s(), breaking!\n", __FUNCTION__);
+			break;
+		}
+	} while (inb(iobase+UART_LSR) & UART_LSR_DR);	
+}
+
+
+/*
+ * Function smsc_ircc_interrupt (irq, dev_id, regs)
+ *
+ *    An interrupt from the chip has arrived. Time to do some work
+ *
+ */
+static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct smsc_ircc_cb *self;
+	int iobase, iir, lcra, lsr;
+
+	if (dev == NULL) {
+		printk(KERN_WARNING "%s: irq %d for unknown device.\n", 
+		       driver_name, irq);
+		return IRQ_NONE;
+	}
+	self = (struct smsc_ircc_cb *) dev->priv;
+	ASSERT(self != NULL, return IRQ_NONE;);
+
+	/* Serialise the interrupt handler in various CPUs, stop Tx path */
+	spin_lock(&self->lock);	
+
+	/* Check if we should use the SIR interrupt handler */
+	if (self->io.speed <=  SMSC_IRCC2_MAX_SIR_SPEED) {
+		smsc_ircc_interrupt_sir(irq, dev_id, regs);
+		spin_unlock(&self->lock);	
+		return IRQ_HANDLED;
+	}
+	iobase = self->io.fir_base;
+
+	register_bank(iobase, 0);
+	iir = inb(iobase+IRCC_IIR);
+	/* Disable interrupts */
+	outb(0, iobase+IRCC_IER);
+	lcra = inb(iobase+IRCC_LCR_A);
+	lsr = inb(iobase+IRCC_LSR);
+	
+	IRDA_DEBUG(2, "%s(), iir = 0x%02x\n", __FUNCTION__, iir);
+
+	if (iir & IRCC_IIR_EOM) {
+		if (self->io.direction == IO_RECV)
+			smsc_ircc_dma_receive_complete(self, iobase);
+		else
+			smsc_ircc_dma_xmit_complete(self, iobase);
+		
+		smsc_ircc_dma_receive(self, iobase);
+	}
+
+	if (iir & IRCC_IIR_ACTIVE_FRAME) {
+		/*printk(KERN_WARNING __FUNCTION__ "(): Active Frame\n");*/
+	}
+
+	/* Enable interrupts again */
+
+	register_bank(iobase, 0);
+	outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, iobase+IRCC_IER);
+
+	spin_unlock(&self->lock);
+	return IRQ_HANDLED;
+}
+
+/*
+ * Function irport_interrupt_sir (irq, dev_id, regs)
+ *
+ *    Interrupt handler for SIR modes
+ */
+void smsc_ircc_interrupt_sir(int irq, void *dev_id, struct pt_regs *regs) 
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct smsc_ircc_cb *self;
+	int boguscount = 0;
+	int iobase;
+	int iir, lsr;
+
+	if (!dev) {
+		WARNING("%s() irq %d for unknown device.\n",
+			__FUNCTION__, irq);
+		return;
+	}
+	self = (struct smsc_ircc_cb *) dev->priv;
+
+	/* Already locked comming here in smsc_ircc_interrupt() */
+	/*spin_lock(&self->lock);*/
+
+	iobase = self->io.sir_base;
+
+	iir = inb(iobase+UART_IIR) & UART_IIR_ID;
+	while (iir) {
+		/* Clear interrupt */
+		lsr = inb(iobase+UART_LSR);
+
+		IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", 
+			    __FUNCTION__, iir, lsr, iobase);
+
+		switch (iir) {
+		case UART_IIR_RLSI:
+			IRDA_DEBUG(2, "%s(), RLSI\n", __FUNCTION__);
+			break;
+		case UART_IIR_RDI:
+			/* Receive interrupt */
+			smsc_ircc_sir_receive(self);
+			break;
+		case UART_IIR_THRI:
+			if (lsr & UART_LSR_THRE)
+				/* Transmitter ready for data */
+				smsc_ircc_sir_write_wakeup(self);
+			break;
+		default:
+			IRDA_DEBUG(0, "%s(), unhandled IIR=%#x\n",
+				   __FUNCTION__, iir);
+			break;
+		} 
+		
+		/* Make sure we don't stay here to long */
+		if (boguscount++ > 100)
+			break;
+
+ 	        iir = inb(iobase + UART_IIR) & UART_IIR_ID;
+	}
+	/*spin_unlock(&self->lock);*/
+}
+
+
+#if 0 /* unused */
+/*
+ * Function ircc_is_receiving (self)
+ *
+ *    Return TRUE is we are currently receiving a frame
+ *
+ */
+static int ircc_is_receiving(struct smsc_ircc_cb *self)
+{
+	int status = FALSE;
+	/* int iobase; */
+
+	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+
+	ASSERT(self != NULL, return FALSE;);
+
+	IRDA_DEBUG(0, "%s: dma count = %d\n", __FUNCTION__,
+		   get_dma_residue(self->io.dma));
+
+	status = (self->rx_buff.state != OUTSIDE_FRAME);
+	
+	return status;
+}
+#endif /* unused */
+
+static int smsc_ircc_net_init(struct net_device *dev)
+{
+	/* Keep track of module usage */
+	SET_MODULE_OWNER(dev);
+
+	/* Set up to be a normal IrDA network device driver */
+	irda_device_setup(dev);
+
+	/* Insert overrides below this line! */
+
+	return 0;
+}
+
+/*
+ * Function smsc_ircc_net_open (dev)
+ *
+ *    Start the device
+ *
+ */
+static int smsc_ircc_net_open(struct net_device *dev)
+{
+	struct smsc_ircc_cb *self;
+	int iobase;
+	char hwname[16];
+	unsigned long flags;
+
+	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+	
+	ASSERT(dev != NULL, return -1;);
+	self = (struct smsc_ircc_cb *) dev->priv;
+	ASSERT(self != NULL, return 0;);
+	
+	iobase = self->io.fir_base;
+
+	if (request_irq(self->io.irq, smsc_ircc_interrupt, 0, dev->name, 
+			(void *) dev)) {
+		IRDA_DEBUG(0, "%s(), unable to allocate irq=%d\n",
+			   __FUNCTION__, self->io.irq);
+		return -EAGAIN;
+	}
+
+	spin_lock_irqsave(&self->lock, flags);
+	/*smsc_ircc_sir_start(self);*/
+	self->io.speed = 0;
+	smsc_ircc_change_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED);
+	spin_unlock_irqrestore(&self->lock, flags);
+	
+	/* Give self a hardware name */
+	/* It would be cool to offer the chip revision here - Jean II */
+	sprintf(hwname, "SMSC @ 0x%03x", self->io.fir_base);
+
+	/* 
+	 * Open new IrLAP layer instance, now that everything should be
+	 * initialized properly 
+	 */
+	self->irlap = irlap_open(dev, &self->qos, hwname);
+
+	/*
+	 * Always allocate the DMA channel after the IRQ,
+	 * and clean up on failure.
+	 */
+	if (request_dma(self->io.dma, dev->name)) {
+		smsc_ircc_net_close(dev);
+
+		WARNING("%s(), unable to allocate DMA=%d\n",
+			__FUNCTION__, self->io.dma);
+		return -EAGAIN;
+	}
+	
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+/*
+ * Function smsc_ircc_net_close (dev)
+ *
+ *    Stop the device
+ *
+ */
+static int smsc_ircc_net_close(struct net_device *dev)
+{
+	struct smsc_ircc_cb *self;
+	int iobase;
+
+	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+	
+	ASSERT(dev != NULL, return -1;);
+	self = (struct smsc_ircc_cb *) dev->priv;	
+	ASSERT(self != NULL, return 0;);
+	
+	iobase = self->io.fir_base;
+
+	/* Stop device */
+	netif_stop_queue(dev);
+	
+	/* Stop and remove instance of IrLAP */
+	if (self->irlap)
+		irlap_close(self->irlap);
+	self->irlap = NULL;
+
+	free_irq(self->io.irq, dev);
+
+	disable_dma(self->io.dma);
+
+	free_dma(self->io.dma);
+
+	return 0;
+}
+
+
+static void smsc_ircc_suspend(struct smsc_ircc_cb *self)
+{
+	MESSAGE("%s, Suspending\n", driver_name);
+
+	if (self->io.suspended)
+		return;
+
+	smsc_ircc_net_close(self->netdev);
+
+	self->io.suspended = 1;
+}
+
+static void smsc_ircc_wakeup(struct smsc_ircc_cb *self)
+{
+	if (!self->io.suspended)
+		return;
+
+	/* The code was doing a "cli()" here, but this can't be right.
+	 * If you need protection, do it in net_open with a spinlock
+	 * or give a good reason. - Jean II */
+
+	smsc_ircc_net_open(self->netdev);
+	
+	MESSAGE("%s, Waking up\n", driver_name);
+}
+
+static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+        struct smsc_ircc_cb *self = (struct smsc_ircc_cb*) dev->data;
+        if (self) {
+                switch (rqst) {
+                case PM_SUSPEND:
+                        smsc_ircc_suspend(self);
+                        break;
+                case PM_RESUME:
+                        smsc_ircc_wakeup(self);
+                        break;
+                }
+        }
+	return 0;
+}
+
+/*
+ * Function smsc_ircc_close (self)
+ *
+ *    Close driver instance
+ *
+ */
+static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
+{
+	int iobase;
+	unsigned long flags;
+
+	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+
+	ASSERT(self != NULL, return -1;);
+
+	iobase = self->io.fir_base;
+
+	if (self->pmdev)
+		pm_unregister(self->pmdev);
+
+	/* Remove netdevice */
+	if (self->netdev) {
+		rtnl_lock();
+		unregister_netdevice(self->netdev);
+		rtnl_unlock();
+	}
+
+	/* Make sure the irq handler is not exectuting */
+	spin_lock_irqsave(&self->lock, flags);
+
+	/* Stop interrupts */
+	register_bank(iobase, 0);
+	outb(0, iobase+IRCC_IER);
+	outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
+	outb(0x00, iobase+IRCC_MASTER);
+#if 0
+	/* Reset to SIR mode */
+	register_bank(iobase, 1);
+        outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase+IRCC_SCE_CFGA);
+        outb(IRCC_CFGB_IR, iobase+IRCC_SCE_CFGB);
+#endif
+	spin_unlock_irqrestore(&self->lock, flags);
+
+	/* Release the PORTS that this driver is using */
+	IRDA_DEBUG(0, "%s(), releasing 0x%03x\n",  __FUNCTION__,
+		   self->io.fir_base);
+
+	release_region(self->io.fir_base, self->io.fir_ext);
+
+	IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __FUNCTION__, 
+		   self->io.sir_base);
+
+	release_region(self->io.sir_base, self->io.sir_ext);
+
+	if (self->tx_buff.head)
+		kfree(self->tx_buff.head);
+	
+	if (self->rx_buff.head)
+		kfree(self->rx_buff.head);
+
+	kfree(self);
+
+	return 0;
+}
+
+void __exit smsc_ircc_cleanup(void)
+{
+	int i;
+
+	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+
+	for (i=0; i < 2; i++) {
+		if (dev_self[i])
+			smsc_ircc_close(dev_self[i]);
+	}
+}
+
+/*
+ *	Start SIR operations
+ *
+ * This function *must* be called with spinlock held, because it may
+ * be called from the irq handler (via smsc_ircc_change_speed()). - Jean II
+ */
+void smsc_ircc_sir_start(struct smsc_ircc_cb *self)
+{
+	struct net_device *dev;
+	int fir_base, sir_base;
+
+	IRDA_DEBUG(3, "%s\n", __FUNCTION__);
+
+	ASSERT(self != NULL, return;);	
+	dev= self->netdev;
+	ASSERT(dev != NULL, return;);		
+	dev->hard_start_xmit = &smsc_ircc_hard_xmit_sir;
+
+	fir_base = self->io.fir_base;
+	sir_base = self->io.sir_base;
+
+	/* Reset everything */
+	outb(IRCC_MASTER_RESET, fir_base+IRCC_MASTER);
+
+	#if SMSC_IRCC2_C_SIR_STOP
+	/*smsc_ircc_sir_stop(self);*/
+	#endif
+
+	register_bank(fir_base, 1);
+	outb(((inb(fir_base+IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | IRCC_CFGA_IRDA_SIR_A), fir_base+IRCC_SCE_CFGA);
+
+	/* Initialize UART */
+	outb(UART_LCR_WLEN8, sir_base+UART_LCR);  /* Reset DLAB */
+	outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), sir_base+UART_MCR);
+	
+	/* Turn on interrups */
+	outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, sir_base+UART_IER);
+
+	IRDA_DEBUG(3, "%s() - exit\n", __FUNCTION__);
+
+	outb(0x00, fir_base+IRCC_MASTER);
+}
+
+#if SMSC_IRCC2_C_SIR_STOP
+void smsc_ircc_sir_stop(struct smsc_ircc_cb *self)
+{
+	int iobase;
+
+	IRDA_DEBUG(3, "%s\n", __FUNCTION__);
+	iobase = self->io.sir_base;
+
+	/* Reset UART */
+	outb(0, iobase+UART_MCR);
+	
+	/* Turn off interrupts */
+	outb(0, iobase+UART_IER);
+}
+#endif
+
+/*
+ * Function smsc_sir_write_wakeup (self)
+ *
+ *    Called by the SIR interrupt handler when there's room for more data.
+ *    If we have more packets to send, we send them here.
+ *
+ */
+static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self)
+{
+	int actual = 0;
+	int iobase;
+	int fcr;
+
+	ASSERT(self != NULL, return;);
+
+	IRDA_DEBUG(4, "%s\n", __FUNCTION__);
+
+	iobase = self->io.sir_base;
+
+	/* Finished with frame?  */
+	if (self->tx_buff.len > 0)  {
+		/* Write data left in transmit buffer */
+		actual = smsc_ircc_sir_write(iobase, self->io.fifo_size, 
+				      self->tx_buff.data, self->tx_buff.len);
+		self->tx_buff.data += actual;
+		self->tx_buff.len  -= actual;
+	} else {
+	
+	/*if (self->tx_buff.len ==0)  {*/
+		
+		/* 
+		 *  Now serial buffer is almost free & we can start 
+		 *  transmission of another packet. But first we must check
+		 *  if we need to change the speed of the hardware
+		 */
+		if (self->new_speed) {
+			IRDA_DEBUG(5, "%s(), Changing speed to %d.\n",
+				   __FUNCTION__, self->new_speed);
+			smsc_ircc_sir_wait_hw_transmitter_finish(self);
+			smsc_ircc_change_speed(self, self->new_speed);
+			self->new_speed = 0;
+		} else {
+			/* Tell network layer that we want more frames */
+			netif_wake_queue(self->netdev);
+		}
+		self->stats.tx_packets++;
+
+		if(self->io.speed <= 115200) {
+		/* 
+		 * Reset Rx FIFO to make sure that all reflected transmit data
+		 * is discarded. This is needed for half duplex operation
+		 */
+		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR;
+		if (self->io.speed < 38400)
+			fcr |= UART_FCR_TRIGGER_1;
+		else 
+			fcr |= UART_FCR_TRIGGER_14;
+
+		outb(fcr, iobase+UART_FCR);
+
+		/* Turn on receive interrupts */
+		outb(UART_IER_RDI, iobase+UART_IER);
+		}
+	}
+}
+
+/*
+ * Function smsc_ircc_sir_write (iobase, fifo_size, buf, len)
+ *
+ *    Fill Tx FIFO with transmit data
+ *
+ */
+static int smsc_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len)
+{
+	int actual = 0;
+	
+	/* Tx FIFO should be empty! */
+	if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
+		WARNING("%s(), failed, fifo not empty!\n", __FUNCTION__);
+		return 0;
+	}
+        
+	/* Fill FIFO with current frame */
+	while ((fifo_size-- > 0) && (actual < len)) {
+		/* Transmit next byte */
+		outb(buf[actual], iobase+UART_TX);
+		actual++;
+	}
+	return actual;
+}
+
+/*
+ * Function smsc_ircc_is_receiving (self)
+ *
+ *    Returns true is we are currently receiving data
+ *
+ */
+static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self)
+{
+	return (self->rx_buff.state != OUTSIDE_FRAME);
+}
+
+
+/*
+ * Function smsc_ircc_probe_transceiver(self)
+ *
+ *    Tries to find the used Transceiver
+ *
+ */
+static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self)
+{
+	unsigned int	i;
+	
+	ASSERT(self != NULL, return;);
+	
+	for(i=0; smsc_transceivers[i].name!=NULL; i++) 
+		if((*smsc_transceivers[i].probe)(self->io.fir_base)) {
+			MESSAGE(" %s transceiver found\n", smsc_transceivers[i].name);
+			self->transceiver= i+1;
+			return;
+		}
+	MESSAGE("No transceiver found. Defaulting to %s\n", smsc_transceivers[SMSC_IRCC2_C_DEFAULT_TRANSCEIVER].name);
+			
+	self->transceiver= SMSC_IRCC2_C_DEFAULT_TRANSCEIVER;
+}
+
+
+/*
+ * Function smsc_ircc_set_transceiver_for_speed(self, speed)
+ *
+ *    Set the transceiver according to the speed
+ *
+ */
+static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed)
+{
+	unsigned int trx;
+	
+	trx = self->transceiver;
+	if(trx>0) (*smsc_transceivers[trx-1].set_for_speed)(self->io.fir_base, speed);
+}
+
+/*
+ * Function smsc_ircc_wait_hw_transmitter_finish ()
+ *
+ *    Wait for the real end of HW transmission
+ *
+ * The UART is a strict FIFO, and we get called only when we have finished
+ * pushing data to the FIFO, so the maximum amount of time we must wait
+ * is only for the FIFO to drain out.
+ *
+ * We use a simple calibrated loop. We may need to adjust the loop
+ * delay (udelay) to balance I/O traffic and latency. And we also need to
+ * adjust the maximum timeout.
+ * It would probably be better to wait for the proper interrupt,
+ * but it doesn't seem to be available.
+ *
+ * We can't use jiffies or kernel timers because :
+ * 1) We are called from the interrupt handler, which disable softirqs,
+ * so jiffies won't be increased
+ * 2) Jiffies granularity is usually very coarse (10ms), and we don't
+ * want to wait that long to detect stuck hardware.
+ * Jean II
+ */
+
+static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self)
+{
+	int iobase;
+	int count = SMSC_IRCC2_HW_TRANSMITTER_TIMEOUT_US;
+	
+	iobase = self->io.sir_base;
+	
+	/* Calibrated busy loop */
+	while((count-- > 0) && !(inb(iobase+UART_LSR) & UART_LSR_TEMT))
+		udelay(1);
+
+	if(count == 0)
+		IRDA_DEBUG(0, "%s(): stuck transmitter\n", __FUNCTION__);
+}
+
+
+/* PROBING
+ *
+ *
+ */
+
+static int __init smsc_ircc_look_for_chips(void)
+{
+	smsc_chip_address_t *address;
+	char	*type;
+	unsigned int cfg_base, found;
+	
+	found = 0;
+	address = possible_addresses;
+	
+	while(address->cfg_base){
+		cfg_base = address->cfg_base;
+		
+		/*printk(KERN_WARNING __FUNCTION__ "(): probing: 0x%02x for: 0x%02x\n", cfg_base, address->type);*/
+		
+		if( address->type & SMSCSIO_TYPE_FDC){
+			type = "FDC";
+			if((address->type) & SMSCSIO_TYPE_FLAT) {
+				if(!smsc_superio_flat(fdc_chips_flat,cfg_base, type)) found++;
+			}
+			if((address->type) & SMSCSIO_TYPE_PAGED) {
+				if(!smsc_superio_paged(fdc_chips_paged,cfg_base, type)) found++;		
+			}			
+		}
+		if( address->type & SMSCSIO_TYPE_LPC){
+			type = "LPC";
+			if((address->type) & SMSCSIO_TYPE_FLAT) {
+				if(!smsc_superio_flat(lpc_chips_flat,cfg_base,type)) found++;
+			}
+			if((address->type) & SMSCSIO_TYPE_PAGED) {
+				if(!smsc_superio_paged(lpc_chips_paged,cfg_base,"LPC")) found++;		
+			}			
+		}
+		address++;
+	}
+	return found;
+} 
+
+/*
+ * Function smsc_superio_flat (chip, base, type)
+ *
+ *    Try to get configuration of a smc SuperIO chip with flat register model
+ *
+ */
+static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfgbase, char *type)
+{
+	unsigned short firbase, sirbase;
+	u8 mode, dma, irq;
+	int ret = -ENODEV;
+
+	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+
+	if (smsc_ircc_probe(cfgbase, SMSCSIOFLAT_DEVICEID_REG, chips, type)==NULL)
+		return ret;
+
+	outb(SMSCSIOFLAT_UARTMODE0C_REG, cfgbase);
+	mode = inb(cfgbase+1);
+	
+	/*printk(KERN_WARNING __FUNCTION__ "(): mode: 0x%02x\n", mode);*/
+	
+	if(!(mode & SMSCSIOFLAT_UART2MODE_VAL_IRDA))
+		WARNING("%s(): IrDA not enabled\n", __FUNCTION__);
+
+	outb(SMSCSIOFLAT_UART2BASEADDR_REG, cfgbase);
+	sirbase = inb(cfgbase+1) << 2;
+
+   	/* FIR iobase */
+	outb(SMSCSIOFLAT_FIRBASEADDR_REG, cfgbase);
+	firbase = inb(cfgbase+1) << 3;
+
+	/* DMA */
+	outb(SMSCSIOFLAT_FIRDMASELECT_REG, cfgbase);
+	dma = inb(cfgbase+1) & SMSCSIOFLAT_FIRDMASELECT_MASK;
+	
+	/* IRQ */
+	outb(SMSCSIOFLAT_UARTIRQSELECT_REG, cfgbase);
+	irq = inb(cfgbase+1) & SMSCSIOFLAT_UART2IRQSELECT_MASK;
+
+	MESSAGE("%s(): fir: 0x%02x, sir: 0x%02x, dma: %02d, irq: %d, mode: 0x%02x\n", __FUNCTION__, firbase, sirbase, dma, irq, mode);
+
+	if (firbase) {
+		if (smsc_ircc_open(firbase, sirbase, dma, irq) == 0)
+			ret=0; 
+	}
+	
+	/* Exit configuration */
+	outb(SMSCSIO_CFGEXITKEY, cfgbase);
+
+	return ret;
+}
+
+/*
+ * Function smsc_superio_paged (chip, base, type)
+ *
+ *    Try  to get configuration of a smc SuperIO chip with paged register model
+ *
+ */
+static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cfg_base, char *type)
+{
+	unsigned short fir_io, sir_io;
+	int ret = -ENODEV;
+	
+	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+
+	if (smsc_ircc_probe(cfg_base,0x20,chips,type)==NULL)
+		return ret;
+	
+	/* Select logical device (UART2) */
+	outb(0x07, cfg_base);
+	outb(0x05, cfg_base + 1);
+		
+	/* SIR iobase */
+	outb(0x60, cfg_base);
+	sir_io  = inb(cfg_base + 1) << 8;
+	outb(0x61, cfg_base);
+	sir_io |= inb(cfg_base + 1);
+		
+	/* Read FIR base */
+	outb(0x62, cfg_base);
+	fir_io = inb(cfg_base + 1) << 8;
+	outb(0x63, cfg_base);
+	fir_io |= inb(cfg_base + 1);
+	outb(0x2b, cfg_base); /* ??? */
+
+	if (fir_io) {
+		if (smsc_ircc_open(fir_io, sir_io, ircc_dma, ircc_irq) == 0)
+			ret=0; 
+	}
+	
+	/* Exit configuration */
+	outb(SMSCSIO_CFGEXITKEY, cfg_base);
+
+	return ret;
+}
+
+
+static int __init smsc_access(unsigned short cfg_base,unsigned char reg)
+{
+	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+
+	outb(reg, cfg_base);
+
+	if (inb(cfg_base)!=reg)
+		return -1;
+
+	return 0;
+}
+
+static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg,const smsc_chip_t *chip,char *type)
+{
+	u8 devid,xdevid,rev; 
+
+	IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+
+	/* Leave configuration */
+
+	outb(SMSCSIO_CFGEXITKEY, cfg_base);
+
+	if (inb(cfg_base) == SMSCSIO_CFGEXITKEY)	/* not a smc superio chip */
+		return NULL;
+
+	outb(reg, cfg_base);
+
+	xdevid=inb(cfg_base+1);
+
+	/* Enter configuration */
+
+	outb(SMSCSIO_CFGACCESSKEY, cfg_base);
+
+	#if 0
+	if (smsc_access(cfg_base,0x55))	/* send second key and check */
+		return NULL;
+	#endif
+	
+	/* probe device ID */
+
+	if (smsc_access(cfg_base,reg))
+		return NULL;
+
+	devid=inb(cfg_base+1);
+	
+	if (devid==0)			/* typical value for unused port */
+		return NULL;
+
+	if (devid==0xff)		/* typical value for unused port */
+		return NULL;
+
+	/* probe revision ID */
+
+	if (smsc_access(cfg_base,reg+1))
+		return NULL;
+
+	rev=inb(cfg_base+1);
+
+	if (rev>=128)			/* i think this will make no sense */
+		return NULL;
+
+	if (devid==xdevid)		/* protection against false positives */        
+		return NULL;
+
+	/* Check for expected device ID; are there others? */
+
+	while(chip->devid!=devid) {
+
+		chip++;
+
+		if (chip->name==NULL)
+			return NULL;
+	}
+
+	MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",devid,rev,cfg_base,type,chip->name);
+
+	if (chip->rev>rev){
+		MESSAGE("Revision higher than expected\n");	
+		return NULL;
+	}
+	
+	if (chip->flags&NoIRDA)
+		MESSAGE("chipset does not support IRDA\n");
+
+	return chip;
+}
+
+static int __init smsc_superio_fdc(unsigned short cfg_base)
+{
+	if (check_region(cfg_base, 2) < 0) {
+		WARNING("%s: can't get cfg_base of 0x%03x\n",
+			__FUNCTION__, cfg_base);
+		return -1;
+	}
+
+	if (!smsc_superio_flat(fdc_chips_flat,cfg_base,"FDC")||!smsc_superio_paged(fdc_chips_paged,cfg_base,"FDC"))
+		return 0;
+
+	return -1;
+}
+
+static int __init smsc_superio_lpc(unsigned short cfg_base)
+{
+#if 0
+	if (check_region(cfg_base, 2) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get cfg_base of 0x%03x\n",
+			   cfg_base);
+		return -1;
+	}
+#endif
+
+	if (!smsc_superio_flat(lpc_chips_flat,cfg_base,"LPC")||!smsc_superio_paged(lpc_chips_paged,cfg_base,"LPC"))
+		return 0;
+
+	return -1;
+}
+
+/************************************************
+ *
+ * Transceivers specific functions
+ *
+ ************************************************/
+
+
+/*
+ * Function smsc_ircc_set_transceiver_smsc_ircc_atc(fir_base, speed)
+ *
+ *    Program transceiver through smsc-ircc ATC circuitry
+ *
+ */
+
+static void smsc_ircc_set_transceiver_smsc_ircc_atc(int fir_base, u32 speed)
+{
+	unsigned long jiffies_now, jiffies_timeout;
+	u8	val;
+	
+	jiffies_now= jiffies;
+	jiffies_timeout= jiffies+SMSC_IRCC2_ATC_PROGRAMMING_TIMEOUT_JIFFIES;
+	
+	/* ATC */
+	register_bank(fir_base, 4);
+	outb((inb(fir_base+IRCC_ATC) & IRCC_ATC_MASK) |IRCC_ATC_nPROGREADY|IRCC_ATC_ENABLE, fir_base+IRCC_ATC);
+	while((val=(inb(fir_base+IRCC_ATC) & IRCC_ATC_nPROGREADY)) && !time_after(jiffies, jiffies_timeout));
+	if(val)
+		WARNING("%s(): ATC: 0x%02x\n", __FUNCTION__,
+			inb(fir_base+IRCC_ATC));
+}
+
+/*
+ * Function smsc_ircc_probe_transceiver_smsc_ircc_atc(fir_base)
+ *
+ *    Probe transceiver smsc-ircc ATC circuitry
+ *
+ */
+
+static int smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base)
+{
+	return 0;
+}
+
+/*
+ * Function smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(self, speed)
+ *
+ *    Set transceiver 
+ *
+ */
+
+static void smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(int fir_base, u32 speed)
+{
+	u8	fast_mode;
+	
+	switch(speed)
+	{
+		default:
+		case 576000 :
+		fast_mode = 0; 
+		break;
+		case 1152000 :
+		case 4000000 :
+		fast_mode = IRCC_LCR_A_FAST;
+		break;
+		
+	}
+	register_bank(fir_base, 0);
+	outb((inb(fir_base+IRCC_LCR_A) &  0xbf) | fast_mode, fir_base+IRCC_LCR_A);
+}
+
+/*
+ * Function smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(fir_base)
+ *
+ *    Probe transceiver 
+ *
+ */
+
+static int smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(int fir_base)
+{
+	return 0;
+}
+
+/*
+ * Function smsc_ircc_set_transceiver_toshiba_sat1800(fir_base, speed)
+ *
+ *    Set transceiver 
+ *
+ */
+
+static void smsc_ircc_set_transceiver_toshiba_sat1800(int fir_base, u32 speed)
+{
+	u8	fast_mode;
+	
+	switch(speed)
+	{
+		default:
+		case 576000 :
+		fast_mode = 0; 
+		break;
+		case 1152000 :
+		case 4000000 :
+		fast_mode = /*IRCC_LCR_A_FAST |*/ IRCC_LCR_A_GP_DATA;
+		break;
+		
+	}
+	/* This causes an interrupt */
+	register_bank(fir_base, 0);
+	outb((inb(fir_base+IRCC_LCR_A) &  0xbf) | fast_mode, fir_base+IRCC_LCR_A);
+}
+
+/*
+ * Function smsc_ircc_probe_transceiver_toshiba_sat1800(fir_base)
+ *
+ *    Probe transceiver 
+ *
+ */
+
+static int smsc_ircc_probe_transceiver_toshiba_sat1800(int fir_base)
+{
+	return 0;
+}
+
+
+module_init(smsc_ircc_init);
+module_exit(smsc_ircc_cleanup);
+
+MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>");
+MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(ircc_dma, "1i");
+MODULE_PARM_DESC(ircc_dma, "DMA channel");
+MODULE_PARM(ircc_irq, "1i");
+MODULE_PARM_DESC(ircc_irq, "IRQ line");
+MODULE_PARM(ircc_fir, "1-4i");
+MODULE_PARM_DESC(ircc_fir, "FIR Base Address");
+MODULE_PARM(ircc_sir, "1-4i");
+MODULE_PARM_DESC(ircc_sir, "SIR Base Address");
+MODULE_PARM(ircc_cfg, "1-4i");
+MODULE_PARM_DESC(ircc_cfg, "Configuration register base address");
+MODULE_PARM(ircc_transceiver, "1i");
+MODULE_PARM_DESC(ircc_transceiver, "Transceiver type");
diff -urN linux-2.5.69-bk18/drivers/net/irda/smsc-ircc2.h linux-2.5.69-bk19/drivers/net/irda/smsc-ircc2.h
--- linux-2.5.69-bk18/drivers/net/irda/smsc-ircc2.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/drivers/net/irda/smsc-ircc2.h	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,194 @@
+/*********************************************************************
+ * $Id: smsc-ircc2.h,v 1.12.2.1 2002/10/27 10:52:37 dip Exp $               
+ *
+ * Description:   Definitions for the SMC IrCC chipset
+ * Status:        Experimental.
+ * Author:        Daniele Peri (peri@csai.unipa.it)
+ *
+ *     Copyright (c) 2002      Daniele Peri
+ *     All Rights Reserved.
+ *
+ * Based on smc-ircc.h:
+ * 
+ *     Copyright (c) 1999-2000, Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998-1999, Thomas Davis (tadavis@jps.net>
+ *     All Rights Reserved
+ *
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *
+ ********************************************************************/
+
+#ifndef SMSC_IRCC2_H
+#define SMSC_IRCC2_H
+
+/* DMA modes needed */
+#define DMA_TX_MODE                0x08    /* Mem to I/O, ++, demand. */
+#define DMA_RX_MODE                0x04    /* I/O to mem, ++, demand. */
+
+/* Master Control Register */
+#define IRCC_MASTER                0x07
+#define   IRCC_MASTER_POWERDOWN	   0x80
+#define   IRCC_MASTER_RESET        0x40
+#define   IRCC_MASTER_INT_EN       0x20
+#define   IRCC_MASTER_ERROR_RESET  0x10
+
+/* Register block 0 */
+
+/* Interrupt Identification */
+#define IRCC_IIR					0x01
+#define   IRCC_IIR_ACTIVE_FRAME		0x80
+#define   IRCC_IIR_EOM				0x40
+#define   IRCC_IIR_RAW_MODE			0x20
+#define   IRCC_IIR_FIFO				0x10
+
+/* Interrupt Enable */
+#define IRCC_IER					0x02
+#define   IRCC_IER_ACTIVE_FRAME		0x80
+#define   IRCC_IER_EOM				0x40
+#define   IRCC_IER_RAW_MODE			0x20
+#define   IRCC_IER_FIFO				0x10
+
+/* Line Status Register */
+#define IRCC_LSR					0x03
+#define   IRCC_LSR_UNDERRUN			0x80
+#define   IRCC_LSR_OVERRUN			0x40
+#define   IRCC_LSR_FRAME_ERROR		0x20
+#define   IRCC_LSR_SIZE_ERROR		0x10
+#define   IRCC_LSR_CRC_ERROR		0x80
+#define   IRCC_LSR_FRAME_ABORT		0x40
+
+/* Line Status Address Register */
+#define IRCC_LSAR					0x03
+#define IRCC_LSAR_ADDRESS_MASK		0x07
+
+/* Line Control Register A */
+#define IRCC_LCR_A                 0x04
+#define   IRCC_LCR_A_FIFO_RESET    0x80
+#define   IRCC_LCR_A_FAST          0x40
+#define   IRCC_LCR_A_GP_DATA       0x20
+#define   IRCC_LCR_A_RAW_TX        0x10
+#define   IRCC_LCR_A_RAW_RX        0x08
+#define   IRCC_LCR_A_ABORT         0x04
+#define   IRCC_LCR_A_DATA_DONE     0x02
+
+/* Line Control Register B */
+#define IRCC_LCR_B                 0x05
+#define   IRCC_LCR_B_SCE_DISABLED  0x00
+#define   IRCC_LCR_B_SCE_TRANSMIT  0x40
+#define   IRCC_LCR_B_SCE_RECEIVE   0x80
+#define   IRCC_LCR_B_SCE_UNDEFINED 0xc0
+#define   IRCC_LCR_B_SIP_ENABLE	   0x20
+#define   IRCC_LCR_B_BRICK_WALL    0x10
+
+/* Bus Status Register */
+#define IRCC_BSR                   0x06
+#define   IRCC_BSR_NOT_EMPTY	   0x80
+#define   IRCC_BSR_FIFO_FULL	   0x40
+#define   IRCC_BSR_TIMEOUT	   0x20
+
+/* Register block 1 */
+
+#define IRCC_FIFO_THRESHOLD			0x02
+
+#define IRCC_SCE_CFGA				0x00
+#define   IRCC_CFGA_AUX_IR			0x80
+#define   IRCC_CFGA_HALF_DUPLEX		0x04
+#define   IRCC_CFGA_TX_POLARITY		0x02
+#define   IRCC_CFGA_RX_POLARITY		0x01
+
+#define   IRCC_CFGA_COM				0x00
+#define		IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK	0x87
+#define   	IRCC_CFGA_IRDA_SIR_A	0x08
+#define   	IRCC_CFGA_ASK_SIR		0x10
+#define   	IRCC_CFGA_IRDA_SIR_B	0x18
+#define   	IRCC_CFGA_IRDA_HDLC		0x20
+#define		IRCC_CFGA_IRDA_4PPM		0x28
+#define		IRCC_CFGA_CONSUMER		0x30
+#define		IRCC_CFGA_RAW_IR		0x38
+#define     IRCC_CFGA_OTHER			0x40
+
+#define IRCC_IR_HDLC               0x04
+#define IRCC_IR_4PPM               0x01
+#define IRCC_IR_CONSUMER           0x02
+
+#define IRCC_SCE_CFGB	           0x01
+#define IRCC_CFGB_LOOPBACK         0x20
+#define IRCC_CFGB_LPBCK_TX_CRC	   0x10
+#define IRCC_CFGB_NOWAIT	   0x08
+#define IRCC_CFGB_STRING_MOVE	   0x04
+#define IRCC_CFGB_DMA_BURST 	   0x02
+#define IRCC_CFGB_DMA_ENABLE	   0x01
+
+#define IRCC_CFGB_MUX_COM          0x00
+#define IRCC_CFGB_MUX_IR           0x40
+#define IRCC_CFGB_MUX_AUX          0x80
+#define IRCC_CFGB_MUX_INACTIVE	   0xc0
+
+/* Register block 3 - Identification Registers! */
+#define IRCC_ID_HIGH	           0x00   /* 0x10 */
+#define IRCC_ID_LOW	           0x01   /* 0xB8 */
+#define IRCC_CHIP_ID 	           0x02   /* 0xF1 */
+#define IRCC_VERSION	           0x03   /* 0x01 */
+#define IRCC_INTERFACE	           0x04   /* low 4 = DMA, high 4 = IRQ */
+#define 	IRCC_INTERFACE_DMA_MASK	0x0F   /* low 4 = DMA, high 4 = IRQ */
+#define 	IRCC_INTERFACE_IRQ_MASK	0xF0   /* low 4 = DMA, high 4 = IRQ */
+
+/* Register block 4 - IrDA */
+#define IRCC_CONTROL               0x00
+#define IRCC_BOF_COUNT_LO          0x01 /* Low byte */
+#define IRCC_BOF_COUNT_HI          0x00 /* High nibble (bit 0-3) */
+#define IRCC_BRICKWALL_CNT_LO      0x02 /* Low byte */
+#define IRCC_BRICKWALL_CNT_HI      0x03 /* High nibble (bit 4-7) */
+#define IRCC_TX_SIZE_LO            0x04 /* Low byte */
+#define IRCC_TX_SIZE_HI            0x03 /* High nibble (bit 0-3) */
+#define IRCC_RX_SIZE_HI            0x05 /* High nibble (bit 0-3) */
+#define IRCC_RX_SIZE_LO            0x06 /* Low byte */
+
+#define IRCC_1152                  0x80
+#define IRCC_CRC                   0x40
+
+/* Register block 5 - IrDA */
+#define IRCC_ATC					0x00
+#define 	IRCC_ATC_nPROGREADY		0x80
+#define 	IRCC_ATC_SPEED			0x40
+#define 	IRCC_ATC_ENABLE			0x20
+#define 	IRCC_ATC_MASK			0xE0
+
+
+#define IRCC_IRHALFDUPLEX_TIMEOUT	0x01
+
+#define IRCC_SCE_TX_DELAY_TIMER		0x02
+
+/*
+ * Other definitions
+ */
+
+#define SMSC_IRCC2_MAX_SIR_SPEED		115200
+#define SMSC_IRCC2_FIR_CHIP_IO_EXTENT 	8
+#define SMSC_IRCC2_SIR_CHIP_IO_EXTENT 	8
+#define SMSC_IRCC2_FIFO_SIZE			16
+#define SMSC_IRCC2_FIFO_THRESHOLD		64
+/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+#define SMSC_IRCC2_RX_BUFF_TRUESIZE		14384
+#define SMSC_IRCC2_TX_BUFF_TRUESIZE		14384
+#define SMSC_IRCC2_MIN_TURN_TIME		0x07
+#define SMSC_IRCC2_WINDOW_SIZE			0x07
+/* Maximum wait for hw transmitter to finish */
+#define SMSC_IRCC2_HW_TRANSMITTER_TIMEOUT_US	1000	/* 1 ms */
+/* Maximum wait for ATC transceiver programming to finish */
+#define SMSC_IRCC2_ATC_PROGRAMMING_TIMEOUT_JIFFIES 1
+#endif /* SMSC_IRCC2_H */
diff -urN linux-2.5.69-bk18/drivers/net/irda/smsc-sio.h linux-2.5.69-bk19/drivers/net/irda/smsc-sio.h
--- linux-2.5.69-bk18/drivers/net/irda/smsc-sio.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/drivers/net/irda/smsc-sio.h	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,100 @@
+#ifndef SMSC_SIO_H
+#define SMSC_SIO_H
+
+/******************************************
+ Keys. They should work with every SMsC SIO
+ ******************************************/
+
+#define SMSCSIO_CFGACCESSKEY		0x55
+#define SMSCSIO_CFGEXITKEY			0xaa
+
+/*****************************
+ * Generic SIO Flat (!?)     *
+ *****************************/
+ 
+/* Register 0x0d */
+#define SMSCSIOFLAT_DEVICEID_REG				0x0d
+
+/* Register 0x0c */
+#define SMSCSIOFLAT_UARTMODE0C_REG				0x0c
+#define 	SMSCSIOFLAT_UART2MODE_MASK			0x38
+#define 	SMSCSIOFLAT_UART2MODE_VAL_COM		0x00
+#define 	SMSCSIOFLAT_UART2MODE_VAL_IRDA		0x08
+#define 	SMSCSIOFLAT_UART2MODE_VAL_ASKIR		0x10
+
+/* Register 0x25 */
+#define SMSCSIOFLAT_UART2BASEADDR_REG			0x25
+
+/* Register 0x2b */
+#define SMSCSIOFLAT_FIRBASEADDR_REG				0x2b
+
+/* Register 0x2c */
+#define SMSCSIOFLAT_FIRDMASELECT_REG			0x2c
+#define 	SMSCSIOFLAT_FIRDMASELECT_MASK		0x0f
+
+/* Register 0x28 */
+#define SMSCSIOFLAT_UARTIRQSELECT_REG			0x28
+#define 	SMSCSIOFLAT_UART2IRQSELECT_MASK		0x0f
+#define 	SMSCSIOFLAT_UART1IRQSELECT_MASK		0xf0
+#define 	SMSCSIOFLAT_UARTIRQSELECT_VAL_NONE	0x00
+
+
+/*********************
+ * LPC47N227         *
+ *********************/
+
+#define LPC47N227_CFGACCESSKEY		0x55
+#define LPC47N227_CFGEXITKEY		0xaa
+
+/* Register 0x00 */
+#define LPC47N227_FDCPOWERVALIDCONF_REG		0x00
+#define 	LPC47N227_FDCPOWER_MASK			0x08
+#define 	LPC47N227_VALID_MASK				0x80
+
+/* Register 0x02 */
+#define LPC47N227_UART12POWER_REG				0x02
+#define 	LPC47N227_UART1POWERDOWN_MASK		0x08
+#define 	LPC47N227_UART2POWERDOWN_MASK		0x80
+
+/* Register 0x07 */
+#define LPC47N227_APMBOOTDRIVE_REG				0x07
+#define 	LPC47N227_PARPORT2AUTOPWRDOWN_MASK	0x10 /* auto power down on if set */
+#define 	LPC47N227_UART2AUTOPWRDOWN_MASK	0x20 /* auto power down on if set */
+#define 	LPC47N227_UART1AUTOPWRDOWN_MASK	0x40 /* auto power down on if set */
+
+/* Register 0x0c */
+#define LPC47N227_UARTMODE0C_REG				0x0c
+#define 	LPC47N227_UART2MODE_MASK			0x38
+#define 	LPC47N227_UART2MODE_VAL_COM		0x00
+#define 	LPC47N227_UART2MODE_VAL_IRDA		0x08
+#define 	LPC47N227_UART2MODE_VAL_ASKIR		0x10
+
+/* Register 0x0d */
+#define LPC47N227_DEVICEID_REG					0x0d
+#define 	LPC47N227_DEVICEID_DEFVAL			0x5a
+
+/* Register 0x0e */
+#define LPC47N227_REVISIONID_REG				0x0e
+
+/* Register 0x25 */
+#define LPC47N227_UART2BASEADDR_REG			0x25
+
+/* Register 0x28 */
+#define LPC47N227_UARTIRQSELECT_REG			0x28
+#define 	LPC47N227_UART2IRQSELECT_MASK		0x0f
+#define 	LPC47N227_UART1IRQSELECT_MASK		0xf0
+#define 	LPC47N227_UARTIRQSELECT_VAL_NONE	0x00
+
+/* Register 0x2b */
+#define LPC47N227_FIRBASEADDR_REG				0x2b
+
+/* Register 0x2c */
+#define LPC47N227_FIRDMASELECT_REG				0x2c
+#define 	LPC47N227_FIRDMASELECT_MASK		0x0f
+#define 	LPC47N227_FIRDMASELECT_VAL_DMA1	0x01 /* 47n227 has three dma channels */
+#define 	LPC47N227_FIRDMASELECT_VAL_DMA2	0x02
+#define 	LPC47N227_FIRDMASELECT_VAL_DMA3	0x03
+#define 	LPC47N227_FIRDMASELECT_VAL_NONE	0x0f
+
+
+#endif
diff -urN linux-2.5.69-bk18/drivers/net/irda/w83977af_ir.c linux-2.5.69-bk19/drivers/net/irda/w83977af_ir.c
--- linux-2.5.69-bk18/drivers/net/irda/w83977af_ir.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/irda/w83977af_ir.c	2003-05-26 04:41:42.000000000 -0700
@@ -524,6 +524,7 @@
 		/* Check for empty frame */
 		if (!skb->len) {
 			w83977af_change_speed(self, speed); 
+			dev->trans_start = jiffies;
 			dev_kfree_skb(skb);
 			return 0;
 		} else
@@ -579,6 +580,7 @@
 		switch_bank(iobase, SET0);
 		outb(ICR_ETXTHI, iobase+ICR);
 	}
+	dev->trans_start = jiffies;
 	dev_kfree_skb(skb);
 
 	/* Restore set register */
diff -urN linux-2.5.69-bk18/drivers/net/macmace.c linux-2.5.69-bk19/drivers/net/macmace.c
--- linux-2.5.69-bk18/drivers/net/macmace.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/macmace.c	2003-05-26 04:41:42.000000000 -0700
@@ -77,8 +77,8 @@
 static struct net_device_stats *mace_stats(struct net_device *dev);
 static void mace_set_multicast(struct net_device *dev);
 static int mace_set_address(struct net_device *dev, void *addr);
-static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void mace_dma_intr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t mace_dma_intr(int irq, void *dev_id, struct pt_regs *regs);
 static void mace_tx_timeout(struct net_device *dev);
 
 /* Bit-reverse one byte of an ethernet hardware address. */
@@ -561,7 +561,7 @@
  * Process the chip interrupt
  */
  
-static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct mace_data *mp = (struct mace_data *) dev->priv;
@@ -577,6 +577,7 @@
 	if (ir & RCVINT) {
 		mace_recv_interrupt(dev);
 	}
+	return IRQ_HANDLED;
 }
 
 static void mace_tx_timeout(struct net_device *dev)
@@ -632,7 +633,7 @@
  * The PSC has passed us a DMA interrupt event.
  */
  
-static void mace_dma_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mace_dma_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct mace_data *mp = (struct mace_data *) dev->priv;
@@ -643,7 +644,7 @@
 	/* Not sure what this does */
 
 	while ((baka = psc_read_long(PSC_MYSTERY)) != psc_read_long(PSC_MYSTERY));
-	if (!(baka & 0x60000000)) return;
+	if (!(baka & 0x60000000)) return IRQ_NONE;
 
 	/*
 	 * Process the read queue
@@ -691,6 +692,7 @@
 		mp->tx_count++;
 		netif_wake_queue(dev);
 	}
+	return IRQ_HANDLED;
 }
 
 MODULE_LICENSE("GPL");
diff -urN linux-2.5.69-bk18/drivers/net/myri_sbus.c linux-2.5.69-bk19/drivers/net/myri_sbus.c
--- linux-2.5.69-bk18/drivers/net/myri_sbus.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/myri_sbus.c	2003-05-26 04:41:42.000000000 -0700
@@ -541,6 +541,7 @@
 	struct myri_channel *chan	= &mp->shmem->channel;
 	unsigned long flags;
 	u32 status;
+	int handled = 0;
 
 	spin_lock_irqsave(&mp->irq_lock, flags);
 
@@ -549,6 +550,7 @@
 	if (status & ISTAT_HOST) {
 		u32 softstate;
 
+		handled = 1;
 		DIRQ(("IRQ_DISAB "));
 		myri_disable_irq(lregs, mp->cregs);
 		softstate = sbus_readl(&chan->state);
@@ -568,7 +570,7 @@
 
 	spin_unlock_irqrestore(&mp->irq_lock, flags);
 
-	return IRQ_HANDLED;
+	return IRQ_RETVAL(handled);
 }
 
 static int myri_open(struct net_device *dev)
diff -urN linux-2.5.69-bk18/drivers/net/pcmcia/xirc2ps_cs.c linux-2.5.69-bk19/drivers/net/pcmcia/xirc2ps_cs.c
--- linux-2.5.69-bk18/drivers/net/pcmcia/xirc2ps_cs.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/pcmcia/xirc2ps_cs.c	2003-05-26 04:41:42.000000000 -0700
@@ -1305,14 +1305,14 @@
     u_char saved_page;
     unsigned bytes_rcvd;
     unsigned int_status, eth_status, rx_status, tx_status;
-    unsigned rsr, pktlen, handled = 1;
+    unsigned rsr, pktlen;
     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 IRQ_NONE;
+	return IRQ_HANDLED;
 
     ioaddr = dev->base_addr;
     if (lp->mohawk) { /* must disable the interrupt */
@@ -1330,7 +1330,6 @@
   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);
@@ -1515,7 +1514,7 @@
      * force an interrupt with this command:
      *	  PutByte(XIRCREG_CR, EnableIntr|ForceIntr);
      */
-    return IRQ_RETVAL(handled);
+    return IRQ_HANDLED;
 } /* xirc2ps_interrupt */
 
 /*====================================================================*/
diff -urN linux-2.5.69-bk18/drivers/net/ppp_synctty.c linux-2.5.69-bk19/drivers/net/ppp_synctty.c
--- linux-2.5.69-bk18/drivers/net/ppp_synctty.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/ppp_synctty.c	2003-05-26 04:41:42.000000000 -0700
@@ -202,7 +202,6 @@
 	struct syncppp *ap;
 	int err;
 
-	MOD_INC_USE_COUNT;
 	ap = kmalloc(sizeof(*ap), GFP_KERNEL);
 	err = -ENOMEM;
 	if (ap == 0)
@@ -236,7 +235,6 @@
  out_free:
 	kfree(ap);
  out:
-	MOD_DEC_USE_COUNT;
 	return err;
 }
 
@@ -276,7 +274,6 @@
 	if (ap->tpkt != 0)
 		kfree_skb(ap->tpkt);
 	kfree(ap);
-	MOD_DEC_USE_COUNT;
 }
 
 /*
@@ -404,6 +401,7 @@
 
 
 static struct tty_ldisc ppp_sync_ldisc = {
+	.owner	= THIS_MODULE,
 	.magic	= TTY_LDISC_MAGIC,
 	.name	= "pppsync",
 	.open	= ppp_sync_open,
diff -urN linux-2.5.69-bk18/drivers/net/seeq8005.c linux-2.5.69-bk19/drivers/net/seeq8005.c
--- linux-2.5.69-bk18/drivers/net/seeq8005.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/seeq8005.c	2003-05-26 04:41:42.000000000 -0700
@@ -84,7 +84,7 @@
 static int seeq8005_open(struct net_device *dev);
 static void seeq8005_timeout(struct net_device *dev);
 static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t seeq8005_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void seeq8005_rx(struct net_device *dev);
 static int seeq8005_close(struct net_device *dev);
 static struct net_device_stats *seeq8005_get_stats(struct net_device *dev);
@@ -400,11 +400,12 @@
 
 /* The typical workload of the driver:
    Handle the network interface interrupts. */
-static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct net_device *dev = dev_id;
 	struct net_local *lp;
 	int ioaddr, status, boguscount = 0;
+	int handled = 0;
 
 	ioaddr = dev->base_addr;
 	lp = (struct net_local *)dev->priv;
@@ -416,17 +417,20 @@
 		}
 		
 		if (status & SEEQSTAT_WINDOW_INT) {
+			handled = 1;
 			outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
 			if (net_debug) {
 				printk("%s: window int!\n",dev->name);
 			}
 		}
 		if (status & SEEQSTAT_TX_INT) {
+			handled = 1;
 			outw( SEEQCMD_TX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
 			lp->stats.tx_packets++;
 			netif_wake_queue(dev);	/* Inform upper layers. */
 		}
 		if (status & SEEQSTAT_RX_INT) {
+			handled = 1;
 			/* Got a packet(s). */
 			seeq8005_rx(dev);
 		}
@@ -436,6 +440,7 @@
 	if(net_debug>2) {
 		printk("%s: eoi\n",dev->name);
 	}
+	return IRQ_RETVAL(handled);
 }
 
 /* We have a good packet(s), get it/them out of the buffers. */
diff -urN linux-2.5.69-bk18/drivers/net/setup.c linux-2.5.69-bk19/drivers/net/setup.c
--- linux-2.5.69-bk18/drivers/net/setup.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/setup.c	2003-05-26 04:41:42.000000000 -0700
@@ -17,8 +17,6 @@
 extern int sdla_c_setup(void); 
 extern int lmc_setup(void);
 
-extern int madgemc_probe(void);
-
 /*
  *	Devices in this list must do new style probing. That is they must
  *	allocate their own device objects and do their own bus scans.
@@ -50,14 +48,6 @@
 #if defined(CONFIG_LANMEDIA)
 	{lmc_setup, 0},
 #endif
-	 
-/*
- *	Token Ring Drivers
- */  
-#ifdef CONFIG_MADGEMC
-	{madgemc_probe, 0},
-#endif
- 
 	{NULL, 0},
 };
 
diff -urN linux-2.5.69-bk18/drivers/net/sun3lance.c linux-2.5.69-bk19/drivers/net/sun3lance.c
--- linux-2.5.69-bk18/drivers/net/sun3lance.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/sun3lance.c	2003-05-26 04:41:42.000000000 -0700
@@ -238,7 +238,7 @@
 static int lance_open( struct net_device *dev );
 static void lance_init_ring( struct net_device *dev );
 static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev );
-static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp );
+static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp );
 static int lance_rx( struct net_device *dev );
 static int lance_close( struct net_device *dev );
 static struct net_device_stats *lance_get_stats( struct net_device *dev );
@@ -620,7 +620,7 @@
 
 /* The LANCE interrupt handler. */
 
-static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp)
 {
 	struct net_device *dev = dev_id;
 	struct lance_private *lp = dev->priv;
@@ -629,7 +629,7 @@
 
 	if (dev == NULL) {
 		DPRINTK( 1, ( "lance_interrupt(): invalid dev_id\n" ));
-		return;
+		return IRQ_NONE;
 	}
 
 	if (in_interrupt)
@@ -688,7 +688,7 @@
 					REGA(CSR3) = CSR3_BSWP;
 					lance_init_ring(dev);
 					REGA(CSR0) = CSR0_STRT | CSR0_INEA;
-					return;
+					return IRQ_HANDLED;
 				}
 			} else if(head->flag & (TMD1_ENP | TMD1_STP)) {
 				
@@ -743,7 +743,7 @@
 	DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n",
 				  dev->name, DREG ));
 	in_interrupt = 0;
-	return;
+	return IRQ_HANDLED;
 }
 
 /* get packet, toss into skbuff */
diff -urN linux-2.5.69-bk18/drivers/net/sunqe.c linux-2.5.69-bk19/drivers/net/sunqe.c
--- linux-2.5.69-bk18/drivers/net/sunqe.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/sunqe.c	2003-05-26 04:41:42.000000000 -0700
@@ -124,6 +124,7 @@
 		qb->qe_rxd[i].rx_flags =
 			(RXD_OWN | ((RXD_PKT_SZ) & RXD_LENGTH));
 	}
+	return IRQ_HANDLED;
 }
 
 static int qe_init(struct sunqe *qep, int from_irq)
diff -urN linux-2.5.69-bk18/drivers/net/tlan.c linux-2.5.69-bk19/drivers/net/tlan.c
--- linux-2.5.69-bk18/drivers/net/tlan.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/tlan.c	2003-05-26 04:41:42.000000000 -0700
@@ -1537,7 +1537,7 @@
 				t = (void *) skb_put( new_skb, TLAN_MAX_FRAME_SIZE );
 				head_list->buffer[0].address = pci_map_single(priv->pciDev, new_skb->data, TLAN_MAX_FRAME_SIZE, PCI_DMA_FROMDEVICE);
 				head_list->buffer[8].address = (u32) t;
-#ifdef __LP64__
+#if BITS_PER_LONG==64
 #error "Not 64bit clean"
 #endif				
 				head_list->buffer[9].address = (u32) new_skb;
diff -urN linux-2.5.69-bk18/drivers/net/tokenring/lanstreamer.c linux-2.5.69-bk19/drivers/net/tokenring/lanstreamer.c
--- linux-2.5.69-bk18/drivers/net/tokenring/lanstreamer.c	2003-05-04 16:53:55.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/tokenring/lanstreamer.c	2003-05-26 04:41:42.000000000 -0700
@@ -201,7 +201,7 @@
 static int streamer_xmit(struct sk_buff *skb, struct net_device *dev);
 static int streamer_close(struct net_device *dev);
 static void streamer_set_rx_mode(struct net_device *dev);
-static void streamer_interrupt(int irq, void *dev_id,
+static irqreturn_t streamer_interrupt(int irq, void *dev_id,
 			       struct pt_regs *regs);
 static struct net_device_stats *streamer_get_stats(struct net_device *dev);
 static int streamer_set_mac_address(struct net_device *dev, void *addr);
@@ -1021,7 +1021,7 @@
 	}			/* end for all completed rx descriptors */
 }
 
-static void streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct streamer_private *streamer_priv =
@@ -1142,6 +1142,7 @@
 	} /* while() */		
 
 	spin_unlock(&streamer_priv->streamer_lock) ; 
+	return IRQ_HANDLED;
 }
 
 static int streamer_xmit(struct sk_buff *skb, struct net_device *dev)
diff -urN linux-2.5.69-bk18/drivers/net/tokenring/madgemc.c linux-2.5.69-bk19/drivers/net/tokenring/madgemc.c
--- linux-2.5.69-bk18/drivers/net/tokenring/madgemc.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/tokenring/madgemc.c	2003-05-26 04:41:42.000000000 -0700
@@ -63,7 +63,6 @@
 static struct madgemc_card *madgemc_card_list;
 
 
-int madgemc_probe(void);
 static int madgemc_open(struct net_device *dev);
 static int madgemc_close(struct net_device *dev);
 static int madgemc_chipset_init(struct net_device *dev);
@@ -152,7 +151,7 @@
 
 
 
-int __init madgemc_probe(void)
+static int __init madgemc_probe(void)
 {	
 	static int versionprinted;
 	struct net_device *dev;
@@ -773,19 +772,7 @@
 	return len;
 }
 
-#ifdef MODULE
-
-int init_module(void)
-{
-	/* Probe for cards. */
-	if (madgemc_probe()) {
-		printk(KERN_NOTICE "madgemc.c: No cards found.\n");
-	}
-	/* lock_tms380_module(); */
-	return (0);
-}
-
-void cleanup_module(void)
+static void __exit madgemc_exit(void)
 {
 	struct net_device *dev;
 	struct madgemc_card *this_card;
@@ -801,9 +788,10 @@
 		madgemc_card_list = this_card->next;
 		kfree(this_card);
 	}
-	/* unlock_tms380_module(); */
 }
-#endif /* MODULE */
+
+module_init(madgemc_probe);
+module_exit(madgemc_exit);
 
 MODULE_LICENSE("GPL");
 
diff -urN linux-2.5.69-bk18/drivers/net/tulip/de4x5.c linux-2.5.69-bk19/drivers/net/tulip/de4x5.c
--- linux-2.5.69-bk18/drivers/net/tulip/de4x5.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/tulip/de4x5.c	2003-05-26 04:41:42.000000000 -0700
@@ -2026,8 +2026,6 @@
 	    dev->trans_start = jiffies;
 	}
     }
-    
-    return;
 }
 
 /*
diff -urN linux-2.5.69-bk18/drivers/net/tulip/interrupt.c linux-2.5.69-bk19/drivers/net/tulip/interrupt.c
--- linux-2.5.69-bk18/drivers/net/tulip/interrupt.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/tulip/interrupt.c	2003-05-26 04:41:42.000000000 -0700
@@ -194,10 +194,10 @@
 				if (tp->rx_buffers[entry].mapping !=
 				    le32_to_cpu(tp->rx_ring[entry].buffer1)) {
 					printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
-					       "do not match in tulip_rx: %08x vs. %08x %p / %p.\n",
+					       "do not match in tulip_rx: %08x vs. %Lx %p / %p.\n",
 					       dev->name,
 					       le32_to_cpu(tp->rx_ring[entry].buffer1),
-					       tp->rx_buffers[entry].mapping,
+					       (long long)tp->rx_buffers[entry].mapping,
 					       skb->head, temp);
 				}
 #endif
diff -urN linux-2.5.69-bk18/drivers/net/tulip/tulip.h linux-2.5.69-bk19/drivers/net/tulip/tulip.h
--- linux-2.5.69-bk18/drivers/net/tulip/tulip.h	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/tulip/tulip.h	2003-05-26 04:41:42.000000000 -0700
@@ -193,16 +193,6 @@
 };
 
 
-enum t21041_csr13_bits {
-	csr13_eng = (0xEF0<<4), /* for eng. purposes only, hardcode at EF0h */
-	csr13_aui = (1<<3), /* clear to force 10bT, set to force AUI/BNC */
-	csr13_cac = (1<<2), /* CSR13/14/15 autoconfiguration */
-	csr13_srl = (1<<0), /* When reset, resets all SIA functions, machines */
-
-	csr13_mask_auibnc = (csr13_eng | csr13_aui | csr13_srl),
-	csr13_mask_10bt = (csr13_eng | csr13_srl),
-};
-
 enum t21143_csr6_bits {
 	csr6_sc = (1<<31),
 	csr6_ra = (1<<30),
@@ -449,9 +439,6 @@
 extern const char tulip_media_cap[];
 extern struct tulip_chip_table tulip_tbl[];
 extern u8 t21040_csr13[];
-extern u16 t21041_csr13[];
-extern u16 t21041_csr14[];
-extern u16 t21041_csr15[];
 
 #ifndef USE_IO_OPS
 #undef inb
diff -urN linux-2.5.69-bk18/drivers/net/tulip/xircom_cb.c linux-2.5.69-bk19/drivers/net/tulip/xircom_cb.c
--- linux-2.5.69-bk18/drivers/net/tulip/xircom_cb.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/tulip/xircom_cb.c	2003-05-26 04:41:42.000000000 -0700
@@ -243,38 +243,29 @@
 		return -ENODEV;
 	}
 
-	
 	/* 
 	   Before changing the hardware, allocate the memory.
 	   This way, we can fail gracefully if not enough memory
 	   is available. 
 	 */
-	private = kmalloc(sizeof(*private),GFP_KERNEL);
-	memset(private, 0, sizeof(struct xircom_private));
+	if ((dev = init_etherdev(NULL, sizeof(struct xircom_private))) == NULL) {
+		printk(KERN_ERR "xircom_probe: failed to allocate etherdev\n");
+		goto device_fail;
+	}
+	private = dev->priv;
 	
 	/* Allocate the send/receive buffers */
 	private->rx_buffer = pci_alloc_consistent(pdev,8192,&private->rx_dma_handle);
-	
 	if (private->rx_buffer == NULL) {
  		printk(KERN_ERR "xircom_probe: no memory for rx buffer \n");
- 		kfree(private);
-		return -ENODEV;
+		goto rx_buf_fail;
 	}	
 	private->tx_buffer = pci_alloc_consistent(pdev,8192,&private->tx_dma_handle);
 	if (private->tx_buffer == NULL) {
 		printk(KERN_ERR "xircom_probe: no memory for tx buffer \n");
-		kfree(private->rx_buffer);
-		kfree(private);
-		return -ENODEV;
-	}
-	dev = init_etherdev(dev, 0);
-	if (dev == NULL) {
-		printk(KERN_ERR "xircom_probe: failed to allocate etherdev\n");
-		kfree(private->rx_buffer);
-		kfree(private->tx_buffer);
-		kfree(private);
-		return -ENODEV;
+		goto tx_buf_fail;
 	}
+
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 	printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, chip_rev, pdev->irq);
@@ -305,14 +296,21 @@
 	transceiver_voodoo(private);
 	
 	spin_lock_irqsave(&private->lock,flags);
-	  activate_transmitter(private);
-	  activate_receiver(private);
+	activate_transmitter(private);
+	activate_receiver(private);
 	spin_unlock_irqrestore(&private->lock,flags);
 	
 	trigger_receive(private);
 	
 	leave("xircom_probe");
 	return 0;
+
+tx_buf_fail:
+	kfree(private->rx_buffer);
+rx_buf_fail:
+	kfree(dev);
+device_fail:
+	return -ENODEV;
 }
 
 
@@ -337,7 +335,6 @@
 				pci_free_consistent(pdev,8192,card->tx_buffer,card->tx_dma_handle);
 			card->tx_buffer = NULL;			
 		}
-		kfree(card);
 	}
 	release_region(dev->base_addr, 128);
 	unregister_netdev(dev);
diff -urN linux-2.5.69-bk18/drivers/net/wan/lmc/lmc_main.c linux-2.5.69-bk19/drivers/net/wan/lmc/lmc_main.c
--- linux-2.5.69-bk18/drivers/net/wan/lmc/lmc_main.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/wan/lmc/lmc_main.c	2003-05-26 04:41:42.000000000 -0700
@@ -117,7 +117,7 @@
 static int lmc_open(struct net_device *dev);
 static int lmc_close(struct net_device *dev);
 static struct net_device_stats *lmc_get_stats(struct net_device *dev);
-static void lmc_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t lmc_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 static int lmc_set_config(struct net_device *dev, struct ifmap *map);
 static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, size_t csr_size);
 static void lmc_softreset(lmc_softc_t * const);
@@ -1388,7 +1388,7 @@
 /* Interrupt handling routine.  This will take an incoming packet, or clean
  * up after a trasmit.
  */
-static void lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*fold00*/
+static irqreturn_t lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*fold00*/
 {
     struct net_device *dev = (struct net_device *) dev_instance;
     lmc_softc_t *sc;
@@ -1398,6 +1398,7 @@
     unsigned int badtx;
     u32 firstcsr;
     int max_work = LMC_RXDESCS;
+    int handled = 0;
 
     lmc_trace(dev, "lmc_interrupt in");
 
@@ -1421,6 +1422,8 @@
 
     /* always go through this loop at least once */
     while (csr & sc->lmc_intrmask) {
+	handled = 1;
+
         /*
          * Clear interrupt bits, we handle all case below
          */
@@ -1580,6 +1583,7 @@
     spin_unlock(&sc->lmc_lock);
 
     lmc_trace(dev, "lmc_interrupt out");
+    return IRQ_RETVAL(handled);
 }
 
 static int lmc_start_xmit (struct sk_buff *skb, struct net_device *dev) /*fold00*/
diff -urN linux-2.5.69-bk18/drivers/net/wireless/airport.c linux-2.5.69-bk19/drivers/net/wireless/airport.c
--- linux-2.5.69-bk18/drivers/net/wireless/airport.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/wireless/airport.c	2003-05-26 04:41:42.000000000 -0700
@@ -275,15 +275,11 @@
 
 	printk(KERN_DEBUG "%s\n", version);
 
-	MOD_INC_USE_COUNT;
-
 	/* Lookup card in device tree */
 	airport_node = find_devices("radio");
 	if (airport_node && !strcmp(airport_node->parent->name, "mac-io"))
 		airport_dev = airport_attach(airport_node);
 
-	MOD_DEC_USE_COUNT;
-
 	return airport_dev ? 0 : -ENODEV;
 }
 
diff -urN linux-2.5.69-bk18/drivers/net/wireless/netwave_cs.c linux-2.5.69-bk19/drivers/net/wireless/netwave_cs.c
--- linux-2.5.69-bk18/drivers/net/wireless/netwave_cs.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/wireless/netwave_cs.c	2003-05-26 04:41:42.000000000 -0700
@@ -1743,31 +1743,28 @@
     return 0;
 }
 
-static int __init init_netwave_cs(void) {
-    servinfo_t serv;
+static struct pcmcia_driver netwave_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "netwave_cs",
+	},
+	.attach		= netwave_attach,
+	.detach		= netwave_detach,
+};
 
-    DEBUG(0, "%s\n", version);
-
-    CardServices(GetCardServicesInfo, &serv);
-    if (serv.Revision != CS_RELEASE_CODE) {
-	printk("netwave_cs: Card Services release does not match!\n");
-	return -1;
-    }
- 
-    register_pccard_driver(&dev_info, &netwave_attach, &netwave_detach);
-	
-    return 0;
+static int __init init_netwave_cs(void)
+{
+	return pcmcia_register_driver(&netwave_driver);
 }
 
-static void __exit exit_netwave_cs(void) {
-    DEBUG(1, "netwave_cs: unloading\n");
-
-    unregister_pccard_driver(&dev_info);
+static void __exit exit_netwave_cs(void)
+{
+	pcmcia_unregister_driver(&netwave_driver);
 
-    /* Do some cleanup of the device list */
-    netwave_flush_stale_links();
-    if(dev_list != NULL)	/* Critical situation */
-        printk("netwave_cs: devices remaining when removing module\n");
+	/* Do some cleanup of the device list */
+	netwave_flush_stale_links();
+	if (dev_list != NULL)	/* Critical situation */
+		printk("netwave_cs: devices remaining when removing module\n");
 }
 
 module_init(init_netwave_cs);
diff -urN linux-2.5.69-bk18/drivers/net/wireless/orinoco_cs.c linux-2.5.69-bk19/drivers/net/wireless/orinoco_cs.c
--- linux-2.5.69-bk18/drivers/net/wireless/orinoco_cs.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/wireless/orinoco_cs.c	2003-05-26 04:41:42.000000000 -0700
@@ -687,29 +687,27 @@
  * become const */
 static char version[] __initdata = "orinoco_cs.c 0.13a (David Gibson <hermes@gibson.dropbear.id.au> and others)";
 
+static struct pcmcia_driver orinoco_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "orinoco_cs",
+	},
+	.attach		= orinoco_cs_attach,
+	.detach		= orinoco_cs_detach,
+};
+
 static int __init
 init_orinoco_cs(void)
 {
-	servinfo_t serv;
-
 	printk(KERN_DEBUG "%s\n", version);
 
-	CardServices(GetCardServicesInfo, &serv);
-	if (serv.Revision != CS_RELEASE_CODE) {
-		printk(KERN_NOTICE "orinoco_cs: Card Services release "
-		       "does not match!\n");
-		return -1;
-	}
-
-	register_pccard_driver(&dev_info, &orinoco_cs_attach, &orinoco_cs_detach);
-
-	return 0;
+	return pcmcia_register_driver(&orinoco_driver);
 }
 
 static void __exit
 exit_orinoco_cs(void)
 {
-	unregister_pccard_driver(&dev_info);
+	pcmcia_unregister_driver(&orinoco_driver);
 
 	if (dev_list)
 		DEBUG(0, "orinoco_cs: Removing leftover devices.\n");
diff -urN linux-2.5.69-bk18/drivers/net/wireless/wavelan_cs.c linux-2.5.69-bk19/drivers/net/wireless/wavelan_cs.c
--- linux-2.5.69-bk18/drivers/net/wireless/wavelan_cs.c	2003-05-26 04:41:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/net/wireless/wavelan_cs.c	2003-05-26 04:41:42.000000000 -0700
@@ -5026,77 +5026,28 @@
   return 0;
 }
 
-/****************************** MODULE ******************************/
-/*
- * Module entry points : insertion & removal
- */
+static struct pcmcia_driver wavelan_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= "wavelan_cs",
+	},
+	.attach		= wavelan_attach,
+	.detach		= wavelan_detach,
+};
 
-/*------------------------------------------------------------------*/
-/*
- * Module insertion : initialisation of the module.
- * Register the card with cardmgr...
- */
 static int __init
 init_wavelan_cs(void)
 {
-  servinfo_t	serv;
-
-#ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "-> init_wavelan_cs()\n");
-#ifdef DEBUG_VERSION_SHOW
-  printk(KERN_DEBUG "%s", version);
-#endif
-#endif
-
-  CardServices(GetCardServicesInfo, &serv);
-  if(serv.Revision != CS_RELEASE_CODE)
-    {
-#ifdef DEBUG_CONFIG_ERRORS
-      printk(KERN_WARNING "init_wavelan_cs: Card Services release does not match!\n");
-#endif
-      return -1;
-    }
-
-  register_pccard_driver(&dev_info, &wavelan_attach, &wavelan_detach);
-
-#ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "<- init_wavelan_cs()\n");
-#endif
-  return 0;
+	return pcmcia_register_driver(&wavelan_driver);
 }
 
-/*------------------------------------------------------------------*/
-/*
- * Module removal
- */
 static void __exit
 exit_wavelan_cs(void)
 {
-#ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "-> cleanup_module()\n");
-#endif
-#ifdef DEBUG_BASIC_SHOW
-  printk(KERN_NOTICE "wavelan_cs: unloading\n");
-#endif
-
-  /* Do some cleanup of the device list */
-  wv_flush_stale_links();
-
-  /* If there remain some devices... */
-#ifdef DEBUG_CONFIG_ERRORS
-  if(dev_list != NULL)
-    {
-      /* Honestly, if this happen we are in a deep s**t */
-      printk(KERN_INFO "wavelan_cs: devices remaining when removing module\n");
-      printk(KERN_INFO "Please flush your disks and reboot NOW !\n");
-    }
-#endif
-
-  unregister_pccard_driver(&dev_info);
+	/* Do some cleanup of the device list */
+	wv_flush_stale_links();
 
-#ifdef DEBUG_MODULE_TRACE
-  printk(KERN_DEBUG "<- cleanup_module()\n");
-#endif
+	pcmcia_unregister_driver(&wavelan_driver);
 }
 
 module_init(init_wavelan_cs);
diff -urN linux-2.5.69-bk18/drivers/oprofile/buffer_sync.c linux-2.5.69-bk19/drivers/oprofile/buffer_sync.c
--- linux-2.5.69-bk18/drivers/oprofile/buffer_sync.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/drivers/oprofile/buffer_sync.c	2003-05-26 04:41:42.000000000 -0700
@@ -127,6 +127,14 @@
 };
 
  
+static void end_sync_timer(void)
+{
+	del_timer_sync(&sync_timer);
+	/* timer might have queued work, make sure it's completed. */
+	flush_scheduled_work();
+}
+
+
 int sync_start(void)
 {
 	int err;
@@ -158,7 +166,7 @@
 out2:
 	profile_event_unregister(EXIT_TASK, &exit_task_nb);
 out1:
-	del_timer_sync(&sync_timer);
+	end_sync_timer();
 	goto out;
 }
 
@@ -169,9 +177,7 @@
 	profile_event_unregister(EXIT_TASK, &exit_task_nb);
 	profile_event_unregister(EXIT_MMAP, &exit_mmap_nb);
 	profile_event_unregister(EXEC_UNMAP, &exec_unmap_nb);
-	del_timer_sync(&sync_timer);
-	/* timer might have queued work, make sure it's completed. */
-	flush_scheduled_work();
+	end_sync_timer();
 }
 
  
@@ -366,12 +372,26 @@
 }
  
 
-/* compute number of filled slots in cpu_buffer queue */
-static unsigned long nr_filled_slots(struct oprofile_cpu_buffer * b)
+/* "acquire" as many cpu buffer slots as we can */
+static unsigned long get_slots(struct oprofile_cpu_buffer * b)
 {
 	unsigned long head = b->head_pos;
 	unsigned long tail = b->tail_pos;
 
+	/*
+	 * Subtle. This resets the persistent last_task
+	 * and in_kernel values used for switching notes.
+	 * BUT, there is a small window between reading
+	 * head_pos, and this call, that means samples
+	 * can appear at the new head position, but not
+	 * be prefixed with the notes for switching
+	 * kernel mode or a task switch. This small hole
+	 * can lead to mis-attribution or samples where
+	 * we don't know if it's in the kernel or not,
+	 * at the start of an event buffer.
+	 */
+	cpu_buffer_reset(b);
+
 	if (head >= tail)
 		return head - tail;
 
@@ -408,9 +428,9 @@
  
 	/* Remember, only we can modify tail_pos */
 
-	unsigned long const available_elements = nr_filled_slots(cpu_buf);
+	unsigned long const available = get_slots(cpu_buf);
   
-	for (i=0; i < available_elements; ++i) {
+	for (i=0; i < available; ++i) {
 		struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos];
  
 		if (is_ctx_switch(s->eip)) {
@@ -435,8 +455,6 @@
 		increment_tail(cpu_buf);
 	}
 	release_mm(mm);
-
-	cpu_buffer_reset(cpu_buf);
 }
  
  
diff -urN linux-2.5.69-bk18/drivers/oprofile/cpu_buffer.c linux-2.5.69-bk19/drivers/oprofile/cpu_buffer.c
--- linux-2.5.69-bk18/drivers/oprofile/cpu_buffer.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk19/drivers/oprofile/cpu_buffer.c	2003-05-26 04:41:42.000000000 -0700
@@ -168,10 +168,8 @@
 }
 
 
-/* resets the cpu buffer to a sane state - should be called with 
- * cpu_buf->int_lock held
- */
-void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf)
+/* Resets the cpu buffer to a sane state. */
+void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf)
 {
 	/* reset these to invalid values; the next sample
 	 * collected will populate the buffer with proper
diff -urN linux-2.5.69-bk18/drivers/oprofile/oprof.c linux-2.5.69-bk19/drivers/oprofile/oprof.c
--- linux-2.5.69-bk18/drivers/oprofile/oprof.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/drivers/oprofile/oprof.c	2003-05-26 04:41:42.000000000 -0700
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/oprofile.h>
+#include <linux/moduleparam.h>
 #include <asm/semaphore.h>
 
 #include "oprof.h"
@@ -24,6 +25,12 @@
 static unsigned long is_setup;
 static DECLARE_MUTEX(start_sem);
 
+/* timer
+   0 - use performance monitoring hardware if available
+   1 - use the timer int mechanism regardless
+ */
+static int timer = 0;
+
 int oprofile_setup(void)
 {
 	int err;
@@ -124,13 +131,16 @@
 
 static int __init oprofile_init(void)
 {
-	int err;
+	int err = -ENODEV;
+
+	if (!timer) {
+		/* Architecture must fill in the interrupt ops and the
+		 * logical CPU type, or we can fall back to the timer
+		 * interrupt profiler.
+		 */
+		err = oprofile_arch_init(&oprofile_ops);
+	}
 
-	/* Architecture must fill in the interrupt ops and the
-	 * logical CPU type, or we can fall back to the timer
-	 * interrupt profiler.
-	 */
-	err = oprofile_arch_init(&oprofile_ops);
 	if (err == -ENODEV) {
 		timer_init(&oprofile_ops);
 		err = 0;
@@ -163,6 +173,9 @@
  
 module_init(oprofile_init);
 module_exit(oprofile_exit);
+
+module_param_named(timer, timer, int, 0644);
+MODULE_PARM_DESC(timer, "force use of timer interrupt");
  
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("John Levon <levon@movementarian.org>");
diff -urN linux-2.5.69-bk18/drivers/oprofile/oprofilefs.c linux-2.5.69-bk19/drivers/oprofile/oprofilefs.c
--- linux-2.5.69-bk18/drivers/oprofile/oprofilefs.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk19/drivers/oprofile/oprofilefs.c	2003-05-26 04:41:42.000000000 -0700
@@ -299,8 +299,8 @@
 }
 
 
-static struct super_block * oprofilefs_get_sb(struct file_system_type * fs_type,
-	int flags, char * dev_name, void * data)
+static struct super_block *oprofilefs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_single(fs_type, flags, data, oprofilefs_fill_super);
 }
diff -urN linux-2.5.69-bk18/drivers/parport/parport_amiga.c linux-2.5.69-bk19/drivers/parport/parport_amiga.c
--- linux-2.5.69-bk18/drivers/parport/parport_amiga.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/parport/parport_amiga.c	2003-05-26 04:41:42.000000000 -0700
@@ -138,9 +138,10 @@
 }
 
 /* as this ports irq handling is already done, we use a generic funktion */
-static void amiga_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t amiga_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	parport_generic_irq(irq, (struct parport *) dev_id, regs);
+	return IRQ_HANDLED;
 }
 
 static void amiga_enable_irq(struct parport *p)
diff -urN linux-2.5.69-bk18/drivers/parport/parport_atari.c linux-2.5.69-bk19/drivers/parport/parport_atari.c
--- linux-2.5.69-bk18/drivers/parport/parport_atari.c	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk19/drivers/parport/parport_atari.c	2003-05-26 04:41:42.000000000 -0700
@@ -103,10 +103,11 @@
 {
 }
 
-static void
+static irqreturn_t
 parport_atari_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	parport_generic_irq(irq, (struct parport *) dev_id, regs);
+	return IRQ_HANDLED;
 }
 
 static void
diff -urN linux-2.5.69-bk18/drivers/parport/parport_mfc3.c linux-2.5.69-bk19/drivers/parport/parport_mfc3.c
--- linux-2.5.69-bk18/drivers/parport/parport_mfc3.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/drivers/parport/parport_mfc3.c	2003-05-26 04:41:42.000000000 -0700
@@ -211,7 +211,7 @@
 
 static int use_cnt = 0;
 
-static void mfc3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mfc3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int i;
 
@@ -221,6 +221,7 @@
 				dummy = pia(this_port[i])->pprb; /* clear irq bit */
 				parport_generic_irq(irq, this_port[i], regs);
 			}
+	return IRQ_HANDLED;
 }
 
 static void mfc3_enable_irq(struct parport *p)
diff -urN linux-2.5.69-bk18/drivers/pnp/isapnp/core.c linux-2.5.69-bk19/drivers/pnp/isapnp/core.c
--- linux-2.5.69-bk18/drivers/pnp/isapnp/core.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk19/drivers/pnp/isapnp/core.c	2003-05-26 04:41:42.000000000 -0700
@@ -419,11 +419,12 @@
 
 static void isapnp_parse_id(struct pnp_dev * dev, unsigned short vendor, unsigned short device)
 {
-	struct pnp_id * id = isapnp_alloc(sizeof(struct pnp_id));
-	if (!id)
-		return;
+	struct pnp_id * id;
 	if (!dev)
 		return;
+	id = isapnp_alloc(sizeof(struct pnp_id));
+	if (!id)
+		return;
 	sprintf(id->id, "%c%c%c%x%x%x%x",
 			'A' + ((vendor >> 2) & 0x3f) - 1,
 			'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
diff -urN linux-2.5.69-bk18/drivers/pnp/quirks.c linux-2.5.69-bk19/drivers/pnp/quirks.c
--- linux-2.5.69-bk18/drivers/pnp/quirks.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/drivers/pnp/quirks.c	2003-05-26 04:41:42.000000000 -0700
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
+#include <linux/slab.h>
 
 #ifdef CONFIG_PNP_DEBUG
 	#define DEBUG
@@ -39,9 +40,13 @@
 	 */
 	for ( ; res ; res = res->dep ) {
 		port2 = pnp_alloc(sizeof(struct pnp_port));
+		if (!port2)
+			return;
 		port3 = pnp_alloc(sizeof(struct pnp_port));
-		if (!port2 || !port3)
+		if (!port3) {
+			kfree(port2);
 			return;
+		}
 		port = res->port;
 		memcpy(port2, port, sizeof(struct pnp_port));
 		memcpy(port3, port, sizeof(struct pnp_port));
diff -urN linux-2.5.69-bk18/drivers/scsi/53c7xx.c linux-2.5.69-bk19/drivers/scsi/53c7xx.c
--- linux-2.5.69-bk18/drivers/scsi/53c7xx.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/drivers/scsi/53c7xx.c	2003-05-26 04:41:42.000000000 -0700
@@ -322,7 +322,7 @@
 static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result);
 static int disable (struct Scsi_Host *host);
 static int NCR53c7xx_run_tests (struct Scsi_Host *host);
-static void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
 static void NCR53c7x0_intfly (struct Scsi_Host *host);
 static int ncr_halt (struct Scsi_Host *host);
 static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd 
@@ -4226,7 +4226,7 @@
 }
 
 /*
- * Function : static void NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs)
+ * Function : static irqreturn_t NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs)
  *
  * Purpose : handle NCR53c7x0 interrupts for all NCR devices sharing
  *	the same IRQ line.  
@@ -4239,14 +4239,16 @@
  * script interrupt handler will call back to this function.
  */
 
-static void 
-NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs) {
+static irqreturn_t
+NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs)
+{
     NCR53c7x0_local_declare();
     struct Scsi_Host *host;			/* Host we are looking at */
     unsigned char istat; 			/* Values of interrupt regs */
     struct NCR53c7x0_hostdata *hostdata;	/* host->hostdata[0] */
     struct NCR53c7x0_cmd *cmd;			/* command which halted */
     u32 *dsa;					/* DSA */
+    int handled = 0;
 
 #ifdef NCR_DEBUG
     char buf[80];				/* Debugging sprintf buffer */
@@ -4263,6 +4265,7 @@
      */
 
     while ((istat = NCR53c7x0_read8(hostdata->istat)) & (ISTAT_SIP|ISTAT_DIP)) {
+	handled = 1;
 	hostdata->dsp_changed = 0;
 	hostdata->dstat_valid = 0;
     	hostdata->state = STATE_HALTED;
@@ -4347,6 +4350,7 @@
 	    }
 	}
     }
+    return IRQ_HANDLED;
 }
 
 
diff -urN linux-2.5.69-bk18/drivers/scsi/a2091.c linux-2.5.69-bk19/drivers/scsi/a2091.c
--- linux-2.5.69-bk18/drivers/scsi/a2091.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk19/drivers/scsi/a2091.c	2003-05-26 04:41:42.000000000 -0700
@@ -28,11 +28,13 @@
 static struct Scsi_Host *first_instance = NULL;
 static Scsi_Host_Template *a2091_template;
 
-static void a2091_intr (int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t a2091_intr (int irq, void *dummy, struct pt_regs *fp)
 {
     unsigned long flags;
     unsigned int status;
     struct Scsi_Host *instance;
+    int handled = 0;
+
     for (instance = first_instance; instance &&
 	 instance->hostt == a2091_template; instance = instance->next)
     {
@@ -44,8 +46,10 @@
 		spin_lock_irqsave(&instance->host_lock, flags);
 		wd33c93_intr (instance);
 		spin_unlock_irqrestore(&instance->host_lock, flags);
+		handled = 1;
 	}
     }
+    return IRQ_RETVAL(handled);
 }
 
 static int dma_setup (Scsi_Cmnd *cmd, int dir_in)
@@ -229,6 +233,13 @@
     return num_a2091;
 }
 
+static int a2091_bus_reset(Scsi_Cmnd *cmd)
+{
+	/* FIXME perform bus-specific reset */
+	wd33c93_host_reset(cmd);
+	return SUCCESS;
+}
+
 #define HOSTS_C
 
 static Scsi_Host_Template driver_template = {
@@ -237,8 +248,9 @@
 	.detect			= a2091_detect,
 	.release		= a2091_release,
 	.queuecommand		= wd33c93_queuecommand,
-	.abort			= wd33c93_abort,
-	.reset			= wd33c93_reset,
+	.eh_abort_handler	= wd33c93_abort,
+	.eh_bus_reset_handler	= a2091_bus_reset,
+	.eh_host_reset_handler	= wd33c93_host_reset,
 	.can_queue		= CAN_QUEUE,
 	.this_id		= 7,
 	.sg_tablesize		= SG_ALL,
diff -urN linux-2.5.69-bk18/drivers/scsi/a3000.c linux-2.5.69-bk19/drivers/scsi/a3000.c
--- linux-2.5.69-bk18/drivers/scsi/a3000.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/drivers/scsi/a3000.c	2003-05-26 04:41:42.000000000 -0700
@@ -27,21 +27,22 @@
 
 static struct Scsi_Host *a3000_host = NULL;
 
-static void a3000_intr (int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t a3000_intr (int irq, void *dummy, struct pt_regs *fp)
 {
 	unsigned long flags;
 	unsigned int status = DMA(a3000_host)->ISTR;
 
 	if (!(status & ISTR_INT_P))
-		return;
+		return IRQ_NONE;
 	if (status & ISTR_INTS)
 	{
 		spin_lock_irqsave(&a3000_host->host_lock, flags);
 		wd33c93_intr (a3000_host);
 		spin_unlock_irqrestore(&a3000_host->host_lock, flags);
-	} else
-		printk("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n",
-		       status);
+		return IRQ_HANDLED;
+	}
+	printk("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status);
+	return IRQ_NONE;
 }
 
 static int dma_setup (Scsi_Cmnd *cmd, int dir_in)
@@ -205,6 +206,13 @@
     return 0;
 }
 
+static int a3000_bus_reset(Scsi_Cmnd *cmd)
+{
+	/* FIXME perform bus-specific reset */
+	wd33c93_host_reset(cmd);
+	return SUCCESS;
+}
+
 #define HOSTS_C
 
 static Scsi_Host_Template driver_template = {
@@ -213,8 +221,9 @@
 	.detect			= a3000_detect,
 	.release		= a3000_release,
 	.queuecommand		= wd33c93_queuecommand,
-	.abort			= wd33c93_abort,
-	.reset			= wd33c93_reset,
+	.eh_abort_handler	= wd33c93_abort,
+	.eh_bus_reset_handler	= a3000_bus_reset,
+	.eh_host_reset_handler	= wd33c93_host_reset,
 	.can_queue		= CAN_QUEUE,
 	.this_id		= 7,
 	.sg_tablesize		= SG_ALL,
diff -urN linux-2.5.69-bk18/drivers/scsi/atari_NCR5380.c linux-2.5.69-bk19/drivers/scsi/atari_NCR5380.c
--- linux-2.5.69-bk18/drivers/scsi/atari_NCR5380.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/drivers/scsi/atari_NCR5380.c	2003-05-26 04:41:42.000000000 -0700
@@ -1267,10 +1267,10 @@
  *
  */
 
-static void NCR5380_intr (int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t NCR5380_intr (int irq, void *dev_id, struct pt_regs *regs)
 {
     struct Scsi_Host *instance = first_instance;
-    int done = 1;
+    int done = 1, handled = 0;
     unsigned char basr;
 
     INT_PRINTK("scsi%d: NCR5380 irq triggered\n", HOSTNO);
@@ -1329,6 +1329,7 @@
 		(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 	    }
 	} /* if !(SELECTION || PARITY) */
+	handled = 1;
     } /* BASR & IRQ */
     else {
 	printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, "
@@ -1342,6 +1343,7 @@
 	/* Put a call to NCR5380_main() on the queue... */
 	queue_main();
     }
+    return IRQ_RETVAL(handled);
 }
 
 #ifdef NCR5380_STATS
diff -urN linux-2.5.69-bk18/drivers/scsi/atari_dma_emul.c linux-2.5.69-bk19/drivers/scsi/atari_dma_emul.c
--- linux-2.5.69-bk18/drivers/scsi/atari_dma_emul.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/drivers/scsi/atari_dma_emul.c	2003-05-26 04:41:42.000000000 -0700
@@ -138,7 +138,7 @@
  *    increased with one.
  */
 
-static void hades_dma_emulator(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t hades_dma_emulator(int irq, void *dummy, struct pt_regs *fp)
 {
 	unsigned long dma_base;
 	register unsigned long dma_cnt asm ("d3");
@@ -166,7 +166,7 @@
 	if ((tt_scsi_dma.dma_ctrl & 2) == 0)
 	{
 		atari_enable_irq(IRQ_TT_MFP_SCSI);
-		return;
+		return IRQ_HANDLED;
 	}
 
 	if (dma_cnt == 0)
@@ -174,7 +174,7 @@
 		printk(KERN_NOTICE "DMA emulation: count is zero.\n");
 		tt_scsi_dma.dma_ctrl &= 0xfd;	/* DMA ready. */
 		atari_enable_irq(IRQ_TT_MFP_SCSI);
-		return;
+		return IRQ_HANDLED;
 	}
 
 	/*
@@ -338,7 +338,7 @@
 
 	atari_enable_irq(IRQ_TT_MFP_SCSI);
 
-	return;
+	return IRQ_HANDLED;
 
 scsi_bus_error:
 	/*
diff -urN linux-2.5.69-bk18/drivers/scsi/atari_scsi.c linux-2.5.69-bk19/drivers/scsi/atari_scsi.c
--- linux-2.5.69-bk18/drivers/scsi/atari_scsi.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/drivers/scsi/atari_scsi.c	2003-05-26 04:41:42.000000000 -0700
@@ -195,8 +195,8 @@
 static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
                                          Scsi_Cmnd *cmd, int write_flag );
 #endif
-static void scsi_tt_intr( int irq, void *dummy, struct pt_regs *fp);
-static void scsi_falcon_intr( int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t scsi_tt_intr( int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t scsi_falcon_intr( int irq, void *dummy, struct pt_regs *fp);
 static void falcon_release_lock_if_possible( struct NCR5380_hostdata *
                                              hostdata );
 static void falcon_get_lock( void );
@@ -315,7 +315,7 @@
 #endif
 
 
-static void scsi_tt_intr (int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t scsi_tt_intr (int irq, void *dummy, struct pt_regs *fp)
 {
 #ifdef REAL_DMA
 	int dma_stat;
@@ -403,10 +403,11 @@
 	/* To be sure the int is not masked */
 	atari_enable_irq( IRQ_TT_MFP_SCSI );
 #endif
+	return IRQ_HANDLED;
 }
 
 
-static void scsi_falcon_intr (int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t scsi_falcon_intr (int irq, void *dummy, struct pt_regs *fp)
 {
 #ifdef REAL_DMA
 	int dma_stat;
@@ -463,6 +464,7 @@
 #endif /* REAL_DMA */
 
 	NCR5380_intr (0, 0, 0);
+	return IRQ_HANDLED;
 }
 
 
diff -urN linux-2.5.69-bk18/drivers/scsi/gvp11.c linux-2.5.69-bk19/drivers/scsi/gvp11.c
--- linux-2.5.69-bk18/drivers/scsi/gvp11.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/drivers/scsi/gvp11.c	2003-05-26 04:41:42.000000000 -0700
@@ -28,11 +28,12 @@
 static struct Scsi_Host *first_instance = NULL;
 static Scsi_Host_Template *gvp11_template;
 
-static void gvp11_intr (int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t gvp11_intr (int irq, void *dummy, struct pt_regs *fp)
 {
     unsigned long flags;
     unsigned int status;
     struct Scsi_Host *instance;
+    int handled = 0;
 
     for (instance = first_instance; instance &&
 	 instance->hostt == gvp11_template; instance = instance->next)
@@ -44,7 +45,9 @@
 	spin_lock_irqsave(&instance->host_lock, flags);
 	wd33c93_intr (instance);
 	spin_unlock_irqrestore(&instance->host_lock, flags);
+	handled = 1;
     }
+    return IRQ_RETVAL(handled);
 }
 
 static int gvp11_xfer_mask = 0;
@@ -352,6 +355,13 @@
     return num_gvp11;
 }
 
+static int gvp11_bus_reset(Scsi_Cmnd *cmd)
+{
+	/* FIXME perform bus-specific reset */
+	wd33c93_host_reset(cmd);
+	return SUCCESS;
+}
+
 
 #define HOSTS_C
 
@@ -363,8 +373,9 @@
 	.detect			= gvp11_detect,
 	.release		= gvp11_release,
 	.queuecommand		= wd33c93_queuecommand,
-	.abort			= wd33c93_abort,
-	.reset			= wd33c93_reset,
+	.eh_abort_handler	= wd33c93_abort,
+	.eh_bus_reset_handler	= gvp11_bus_reset,
+	.eh_host_reset_handler	= wd33c93_host_reset,
 	.can_queue		= CAN_QUEUE,
 	.this_id		= 7,
 	.sg_tablesize		= SG_ALL,
diff -urN linux-2.5.69-bk18/drivers/scsi/hosts.c linux-2.5.69-bk19/drivers/scsi/hosts.c
--- linux-2.5.69-bk18/drivers/scsi/hosts.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/drivers/scsi/hosts.c	2003-05-26 04:41:42.000000000 -0700
@@ -27,6 +27,7 @@
  *  hosts currently present in the system.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/blk.h>
 #include <linux/kernel.h>
diff -urN linux-2.5.69-bk18/drivers/scsi/mac_NCR5380.c linux-2.5.69-bk19/drivers/scsi/mac_NCR5380.c
--- linux-2.5.69-bk18/drivers/scsi/mac_NCR5380.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk19/drivers/scsi/mac_NCR5380.c	2003-05-26 04:41:42.000000000 -0700
@@ -1274,7 +1274,7 @@
 static void NCR5380_intr (int irq, void *dev_id, struct pt_regs *regs)
 {
     struct Scsi_Host *instance = first_instance;
-    int done = 1;
+    int done = 1, handled = 0;
     unsigned char basr;
 
     INT_PRINTK("scsi%d: NCR5380 irq triggered\n", HOSTNO);
@@ -1333,6 +1333,7 @@
 		(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 	    }
 	} /* if !(SELECTION || PARITY) */
+	handled = 1;
     } /* BASR & IRQ */
     else {
 	printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, "
@@ -1346,6 +1347,7 @@
 	/* Put a call to NCR5380_main() on the queue... */
 	queue_main();
     }
+    return IRQ_RETVAL(handled);
 }
 
 #ifdef NCR5380_STATS
diff -urN linux-2.5.69-bk18/drivers/scsi/mac_esp.c linux-2.5.69-bk19/drivers/scsi/mac_esp.c
--- linux-2.5.69-bk18/drivers/scsi/mac_esp.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/drivers/scsi/mac_esp.c	2003-05-26 04:41:42.000000000 -0700
@@ -142,9 +142,10 @@
 	mac_esp_intr(irq, dev_id, pregs);
 }
 
-void fake_drq(int irq, void *dev_id, struct pt_regs *pregs)
+irqreturn_t fake_drq(int irq, void *dev_id, struct pt_regs *pregs)
 {
 	printk("mac_esp: got drq\n");
+	return IRQ_HANDLED;
 }
 
 #define DRIVER_SETUP
diff -urN linux-2.5.69-bk18/drivers/scsi/mvme147.c linux-2.5.69-bk19/drivers/scsi/mvme147.c
--- linux-2.5.69-bk18/drivers/scsi/mvme147.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/drivers/scsi/mvme147.c	2003-05-26 04:41:42.000000000 -0700
@@ -21,12 +21,13 @@
 
 static struct Scsi_Host *mvme147_host = NULL;
 
-static void mvme147_intr (int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t mvme147_intr (int irq, void *dummy, struct pt_regs *fp)
 {
     if (irq == MVME147_IRQ_SCSI_PORT)
 	wd33c93_intr (mvme147_host);
     else
 	m147_pcc->dma_intr = 0x89;	/* Ack and enable ints */
+    return IRQ_HANDLED;
 }
 
 static int dma_setup (Scsi_Cmnd *cmd, int dir_in)
@@ -112,6 +113,13 @@
     return 0;
 }
 
+static int mvme147_bus_reset(Scsi_Cmnd *cmd)
+{
+	/* FIXME perform bus-specific reset */
+	wd33c93_host_reset(cmd);
+	return SUCCESS;
+}
+
 #define HOSTS_C
 
 #include "mvme147.h"
@@ -122,8 +130,9 @@
 	.detect			= mvme147_detect,
 	.release		= mvme147_release,
 	.queuecommand		= wd33c93_queuecommand,
-	.abort			= wd33c93_abort,
-	.reset			= wd33c93_reset,
+	.eh_abort_handler	= wd33c93_abort,
+	.eh_bus_reset_handler	= mvme147_bus_reset,
+	.eh_host_reset_handler	= wd33c93_host_reset,
 	.can_queue		= CAN_QUEUE,
 	.this_id		= 7,
 	.sg_tablesize		= SG_ALL,
diff -urN linux-2.5.69-bk18/drivers/scsi/sun3_NCR5380.c linux-2.5.69-bk19/drivers/scsi/sun3_NCR5380.c
--- linux-2.5.69-bk18/drivers/scsi/sun3_NCR5380.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/drivers/scsi/sun3_NCR5380.c	2003-05-26 04:41:42.000000000 -0700
@@ -1255,10 +1255,10 @@
  *
  */
 
-static void NCR5380_intr (int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t NCR5380_intr (int irq, void *dev_id, struct pt_regs *regs)
 {
     struct Scsi_Host *instance = first_instance;
-    int done = 1;
+    int done = 1, handled = 0;
     unsigned char basr;
 
     INT_PRINTK("scsi%d: NCR5380 irq triggered\n", HOSTNO);
@@ -1320,6 +1320,7 @@
 #endif
 	    }
 	} /* if !(SELECTION || PARITY) */
+	handled = 1;
     } /* BASR & IRQ */
     else {
 
@@ -1337,6 +1338,7 @@
 	/* Put a call to NCR5380_main() on the queue... */
 	queue_main();
     }
+    return IRQ_RETVAL(handled);
 }
 
 #ifdef NCR5380_STATS
diff -urN linux-2.5.69-bk18/drivers/scsi/sun3_scsi.c linux-2.5.69-bk19/drivers/scsi/sun3_scsi.c
--- linux-2.5.69-bk18/drivers/scsi/sun3_scsi.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk19/drivers/scsi/sun3_scsi.c	2003-05-26 04:41:42.000000000 -0700
@@ -102,7 +102,7 @@
 #define	ENABLE_IRQ()	enable_irq( IRQ_SUN3_SCSI ); 
 
 
-static void scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp);
 static inline unsigned char sun3scsi_read(int reg);
 static inline void sun3scsi_write(int reg, int value);
 
@@ -373,9 +373,10 @@
 // safe bits for the CSR
 #define CSR_GOOD 0x060f
 
-static void scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp)
 {
 	unsigned short csr = dregs->csr;
+	int handled = 0;
 
 	if(csr & ~CSR_GOOD) {
 		if(csr & CSR_DMA_BUSERR) {
@@ -385,10 +386,15 @@
 		if(csr & CSR_DMA_CONFLICT) {
 			printk("scsi%d: dma conflict\n", default_instance->host_no);
 		}
+		handled = 1;
 	}
 
-	if(csr & (CSR_SDB_INT | CSR_DMA_INT))
+	if(csr & (CSR_SDB_INT | CSR_DMA_INT)) {
 		NCR5380_intr(irq, dummy, fp);
+		handled = 1;
+	}
+
+	return IRQ_RETVAL(handled);
 }
 
 /*
diff -urN linux-2.5.69-bk18/drivers/scsi/sun3_scsi_vme.c linux-2.5.69-bk19/drivers/scsi/sun3_scsi_vme.c
--- linux-2.5.69-bk18/drivers/scsi/sun3_scsi_vme.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/drivers/scsi/sun3_scsi_vme.c	2003-05-26 04:41:42.000000000 -0700
@@ -67,7 +67,7 @@
 #define ENABLE_IRQ()
 
 
-static void scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp);
 static inline unsigned char sun3scsi_read(int reg);
 static inline void sun3scsi_write(int reg, int value);
 
@@ -342,9 +342,10 @@
 // safe bits for the CSR
 #define CSR_GOOD 0x060f
 
-static void scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp)
 {
 	unsigned short csr = dregs->csr;
+	int handled = 0;
 
 	dregs->csr &= ~CSR_DMA_ENABLE;
 
@@ -368,10 +369,15 @@
 		if(csr & CSR_DMA_CONFLICT) {
 			printk("scsi%d: dma conflict\n", default_instance->host_no);
 		}
+		handled = 1;
 	}
 
-	if(csr & (CSR_SDB_INT | CSR_DMA_INT))
+	if(csr & (CSR_SDB_INT | CSR_DMA_INT)) {
 		NCR5380_intr(irq, dummy, fp);
+		handled = 1;
+	}
+
+	return IRQ_RETVAL(handled);
 }
 
 /*
diff -urN linux-2.5.69-bk18/drivers/serial/mcfserial.c linux-2.5.69-bk19/drivers/serial/mcfserial.c
--- linux-2.5.69-bk18/drivers/serial/mcfserial.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/drivers/serial/mcfserial.c	2003-05-26 04:41:42.000000000 -0700
@@ -93,7 +93,11 @@
 
 #define _INLINE_ inline
 
+#ifdef CONFIG_M5282
+#define	IRQBASE	77
+#else
 #define	IRQBASE	73
+#endif
 
 /*
  *	Configuration table, UARTs to look for at startup.
@@ -412,13 +416,6 @@
 		receive_chars(info, regs, isr);
 	if (isr & MCFUART_UIR_TXREADY)
 		transmit_chars(info);
-#if 0
-	if (isr & MCFUART_UIR_DELTABREAK) {
-		printk("%s(%d): delta break!\n", __FILE__, __LINE__);
-		receive_chars(info, regs, isr);
-	}
-#endif
-
 	return;
 }
 
@@ -737,7 +734,7 @@
 
 #if 0
 	printk("%s(%d): mcfrs_write(tty=%x,from_user=%d,buf=%x,count=%d)\n",
-		__FILE__, __LINE__, tty, from_user, buf, count);
+		__FILE__, __LINE__, (int)tty, from_user, (int)buf, count);
 #endif
 
 	if (serial_paranoia_check(info, tty->name, "mcfrs_write"))
@@ -791,7 +788,7 @@
 {
 	struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
 	int	ret;
-				
+
 	if (serial_paranoia_check(info, tty->name, "mcfrs_write_room"))
 		return 0;
 	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
@@ -803,7 +800,7 @@
 static int mcfrs_chars_in_buffer(struct tty_struct *tty)
 {
 	struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
-				
+
 	if (serial_paranoia_check(info, tty->name, "mcfrs_chars_in_buffer"))
 		return 0;
 	return info->xmit_cnt;
@@ -813,7 +810,7 @@
 {
 	struct mcf_serial	*info = (struct mcf_serial *)tty->driver_data;
 	unsigned long		flags;
-				
+
 	if (serial_paranoia_check(info, tty->name, "mcfrs_flush_buffer"))
 		return;
 
@@ -1467,7 +1464,7 @@
  */
 static void mcfrs_irqinit(struct mcf_serial *info)
 {
-#ifdef CONFIG_M5272
+#if defined(CONFIG_M5272)
 	volatile unsigned long	*icrp;
 	volatile unsigned long	*portp;
 	volatile unsigned char	*uartp;
@@ -1493,6 +1490,19 @@
 	*portp = (*portp & ~0x000000ff) | 0x00000055;
 	portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PDCNT);
 	*portp = (*portp & ~0x000003fc) | 0x000002a8;
+#elif defined(CONFIG_M5282)
+	volatile unsigned char *icrp, *uartp;
+	volatile unsigned long *imrp;
+
+	uartp = (volatile unsigned char *) info->addr;
+
+	icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 +
+		MCFINTC_ICR0 + MCFINT_UART0 + info->line);
+	*icrp = 0x33; /* UART0 with level 6, priority 3 */
+
+	imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 +
+		MCFINTC_IMRL);
+	*imrp &= ~((1 << (info->irq - 64)) | 1);
 #else
 	volatile unsigned char	*icrp, *uartp;
 
diff -urN linux-2.5.69-bk18/drivers/usb/core/inode.c linux-2.5.69-bk19/drivers/usb/core/inode.c
--- linux-2.5.69-bk18/drivers/usb/core/inode.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk19/drivers/usb/core/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -489,7 +489,7 @@
 static struct file_system_type usbdevice_fs_type;
 
 static struct super_block *usb_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	if (fs_type == &usbdevice_fs_type)
 		printk (KERN_INFO "Please use the 'usbfs' filetype instead, "
diff -urN linux-2.5.69-bk18/drivers/video/amifb.c linux-2.5.69-bk19/drivers/video/amifb.c
--- linux-2.5.69-bk18/drivers/video/amifb.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/drivers/video/amifb.c	2003-05-26 04:41:42.000000000 -0700
@@ -1123,9 +1123,12 @@
 static int amifb_blank(int blank, struct fb_info *info);
 static int amifb_pan_display(struct fb_var_screeninfo *var,
 			     struct fb_info *info);
-static void amifb_fillrect(struct fb_info *info, struct fb_fillrect *rect);
-static void amifb_copyarea(struct fb_info *info, struct fb_copyarea *region);
-static void amifb_imageblit(struct fb_info *info, struct fb_image *image);
+static void amifb_fillrect(struct fb_info *info,
+			   const struct fb_fillrect *rect);
+static void amifb_copyarea(struct fb_info *info,
+			   const struct fb_copyarea *region);
+static void amifb_imageblit(struct fb_info *info,
+			    const struct fb_image *image);
 static int amifb_ioctl(struct inode *inode, struct file *file,
 		       unsigned int cmd, unsigned long arg,
 		       struct fb_info *info);
@@ -1949,11 +1952,13 @@
 }
 
 
-static void amifb_fillrect(struct fb_info *info, struct fb_fillrect *rect)
+static void amifb_fillrect(struct fb_info *info,
+			   const struct fb_fillrect *rect)
 {
 	struct amifb_par *par = (struct amifb_par *)info->par;
 	int dst_idx, x2, y2;
 	unsigned long *dst;
+	u32 width, height;
 
 	if (!rect->width || !rect->height)
 		return;
@@ -1966,25 +1971,24 @@
 	y2 = rect->dy + rect->height;
 	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
 	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
-	rect->width = x2 - rect->dx;
-	rect->height = y2 - rect->dy;
+	width = x2 - rect->dx;
+	height = y2 - rect->dy;
 
 	dst = (unsigned long *)
 		((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
 	dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
 	dst_idx += rect->dy*par->next_line*8+rect->dx;
-	while (rect->height--) {
+	while (height--) {
 		switch (rect->rop) {
 		    case ROP_COPY:
 			fill_one_line(info->var.bits_per_pixel,
-				      par->next_plane, dst, dst_idx,
-				      rect->width, rect->color);
+				      par->next_plane, dst, dst_idx, width,
+				      rect->color);
 			break;
 
 		    case ROP_XOR:
-			xor_one_line(info->var.bits_per_pixel,
-				     par->next_plane, dst, dst_idx,
-				     rect->width, rect->color);
+			xor_one_line(info->var.bits_per_pixel, par->next_plane,
+				     dst, dst_idx, width, rect->color);
 			break;
 		}
 		dst_idx += par->next_line*8;
@@ -2026,47 +2030,38 @@
 }
 
 
-static void amifb_copyarea(struct fb_info *info, struct fb_copyarea *area)
+static void amifb_copyarea(struct fb_info *info,
+			   const struct fb_copyarea *area)
 {
 	struct amifb_par *par = (struct amifb_par *)info->par;
-	int x2, y2, old_dx, old_dy;
+	int x2, y2;
+	u32 dx, dy, sx, sy, width, height;
 	unsigned long *dst, *src;
-	int dst_idx, src_idx, height;
+	int dst_idx, src_idx;
 	int rev_copy = 0;
 
 	/* clip the destination */
-	old_dx = area->dx;
-	old_dy = area->dy;
-
-	/*
-	 * We could use hardware clipping but on many cards you get around
-	 * hardware clipping by writing to framebuffer directly.
-	 */
 	x2 = area->dx + area->width;
 	y2 = area->dy + area->height;
-	area->dx = area->dx > 0 ? area->dx : 0;
-	area->dy = area->dy > 0 ? area->dy : 0;
+	dx = area->dx > 0 ? area->dx : 0;
+	dy = area->dy > 0 ? area->dy : 0;
 	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
 	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
-	area->width = x2 - area->dx;
-	area->height = y2 - area->dy;
-
-	/* update sx1,sy1 */
-	area->sx += (area->dx - old_dx);
-	area->sy += (area->dy - old_dy);
+	width = x2 - dx;
+	height = y2 - dy;
 
-	height = area->height;
+	/* update sx,sy */
+	sx = area->sx + (dx - area->dx);
+	sy = area->sy + (dy - area->dy);
 
 	/* the source must be completely inside the virtual screen */
-	if (area->sx < 0 || area->sy < 0 ||
-	    (area->sx + area->width) > info->var.xres_virtual ||
-	    (area->sy + area->height) > info->var.yres_virtual)
+	if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual ||
+	    (sy + height) > info->var.yres_virtual)
 		return;
 
-	if (area->dy > area->sy ||
-	    (area->dy == area->sy && area->dx > area->sx)) {
-		area->dy += area->height;
-		area->sy += area->height;
+	if (dy > sy || (dy == sy && dx > sx)) {
+		dy += height;
+		sy += height;
 		rev_copy = 1;
 	}
 	dst = (unsigned long *)
@@ -2074,21 +2069,21 @@
 	src = dst;
 	dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
 	src_idx = dst_idx;
-	dst_idx += area->dy*par->next_line*8+area->dx;
-	src_idx += area->sy*par->next_line*8+area->sx;
+	dst_idx += dy*par->next_line*8+dx;
+	src_idx += sy*par->next_line*8+sx;
 	if (rev_copy) {
 		while (height--) {
 			dst_idx -= par->next_line*8;
 			src_idx -= par->next_line*8;
 			copy_one_line_rev(info->var.bits_per_pixel,
 					  par->next_plane, dst, dst_idx, src,
-					  src_idx, area->width);
+					  src_idx, width);
 		}
 	} else {
 		while (height--) {
 			copy_one_line(info->var.bits_per_pixel,
 				      par->next_plane, dst, dst_idx, src,
-				      src_idx, area->width);
+				      src_idx, width);
 			dst_idx += par->next_line*8;
 			src_idx += par->next_line*8;
 		}
@@ -2125,7 +2120,7 @@
 }
 
 
-static void amifb_imageblit(struct fb_info *info, struct fb_image *image)
+static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
 	struct amifb_par *par = (struct amifb_par *)info->par;
 	int x2, y2;
diff -urN linux-2.5.69-bk18/drivers/video/atafb.c linux-2.5.69-bk19/drivers/video/atafb.c
--- linux-2.5.69-bk18/drivers/video/atafb.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/drivers/video/atafb.c	2003-05-26 04:41:42.000000000 -0700
@@ -1182,7 +1182,7 @@
 	par->HBB = gend2 - par->HHT - 2;
 #if 0
 	/* One more Videl constraint: data fetch of two lines must not overlap */
-	if (par->HDB & 0x200  &&  par->HDB & ~0x200 - par->HDE <= 5) {
+	if ((par->HDB & 0x200)  &&  (par->HDB & ~0x200) - par->HDE <= 5) {
 		/* if this happens increase margins, decrease hfreq. */
 	}
 #endif
diff -urN linux-2.5.69-bk18/drivers/video/aty/atyfb_base.c linux-2.5.69-bk19/drivers/video/aty/atyfb_base.c
--- linux-2.5.69-bk18/drivers/video/aty/atyfb_base.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/drivers/video/aty/atyfb_base.c	2003-05-26 04:41:42.000000000 -0700
@@ -2318,15 +2318,25 @@
 			return -ENOMEM;
 		}
 		memset(info, 0, sizeof(struct fb_info));
-		info->fix = atyfb_fix;		
+
+		default_par = kmalloc(sizeof(struct atyfb_par), GFP_ATOMIC);
+		if (!default_par) {
+			printk
+			    ("atyfb_init: can't alloc atyfb_par\n");
+			kfree(info);
+			return -ENXIO;
+		}
+		memset(default_par, 0, sizeof(struct atyfb_par));
+
+		info->fix = atyfb_fix;
 
 		/*
 		 *  Map the video memory (physical address given) to somewhere in the
 		 *  kernel address space.
 		 */
-		info->screen_base = (unsigned long)ioremap(phys_vmembase[m64_num],
+		info->screen_base = ioremap(phys_vmembase[m64_num],
 					 		   phys_size[m64_num]);	
-		info->fix.smem_start = info->screen_base;	/* Fake! */
+		info->fix.smem_start = (unsigned long)info->screen_base;	/* Fake! */
 		default_par->ati_regbase = (unsigned long)ioremap(phys_guiregbase[m64_num],
 							  0x10000) + 0xFC00ul;
 		info->fix.mmio_start = default_par->ati_regbase; /* Fake! */
diff -urN linux-2.5.69-bk18/drivers/video/console/fbcon.c linux-2.5.69-bk19/drivers/video/console/fbcon.c
--- linux-2.5.69-bk18/drivers/video/console/fbcon.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/drivers/video/console/fbcon.c	2003-05-26 04:41:42.000000000 -0700
@@ -187,6 +187,7 @@
 static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp)
 {
 	vbl_detected++;
+	return IRQ_HANDLED;
 }
 #endif
 
diff -urN linux-2.5.69-bk18/fs/Kconfig linux-2.5.69-bk19/fs/Kconfig
--- linux-2.5.69-bk18/fs/Kconfig	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/Kconfig	2003-05-26 04:41:42.000000000 -0700
@@ -827,6 +827,28 @@
 	  Note that the experimental "/dev file system support"
 	  (CONFIG_DEVFS_FS)  is a more general facility.
 
+config DEVPTS_FS_XATTR
+	bool "/dev/pts Extended Attributes"
+	depends on DEVPTS_FS
+	help
+	  Extended attributes are name:value pairs associated with inodes by
+	  the kernel or by users (see the attr(5) manual page, or visit
+	  <http://acl.bestbits.at/> for details).
+
+	  If unsure, say N.
+
+config DEVPTS_FS_SECURITY
+	bool "/dev/pts Security Labels"
+	depends on DEVPTS_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 /dev/pts filesystem.
+
+	  If you are not using a security module that requires using
+	  extended attributes for file security labels, say N.
+
 config TMPFS
 	bool "Virtual memory file system support (former shm fs)"
 	help
diff -urN linux-2.5.69-bk18/fs/Makefile linux-2.5.69-bk19/fs/Makefile
--- linux-2.5.69-bk18/fs/Makefile	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/fs/Makefile	2003-05-26 04:41:42.000000000 -0700
@@ -10,7 +10,9 @@
 		namei.o fcntl.o ioctl.o readdir.o select.o fifo.o locks.o \
 		dcache.o inode.o attr.o bad_inode.o file.o dnotify.o \
 		filesystems.o namespace.o seq_file.o xattr.o libfs.o \
-		fs-writeback.o mpage.o direct-io.o aio.o eventpoll.o
+		fs-writeback.o mpage.o direct-io.o aio.o
+
+obj-$(CONFIG_EPOLL)	+= eventpoll.o
 
 obj-$(CONFIG_COMPAT) += compat.o
 
diff -urN linux-2.5.69-bk18/fs/adfs/super.c linux-2.5.69-bk19/fs/adfs/super.c
--- linux-2.5.69-bk18/fs/adfs/super.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/fs/adfs/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -234,7 +234,7 @@
 {
 	adfs_inode_cachep = kmem_cache_create("adfs_inode_cache",
 					     sizeof(struct adfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (adfs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -459,7 +459,7 @@
 }
 
 static struct super_block *adfs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, adfs_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/affs/super.c linux-2.5.69-bk19/fs/affs/super.c
--- linux-2.5.69-bk18/fs/affs/super.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/fs/affs/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -115,7 +115,7 @@
 {
 	affs_inode_cachep = kmem_cache_create("affs_inode_cache",
 					     sizeof(struct affs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (affs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -210,9 +210,7 @@
 			optn = "volume";
 			if (!value || !*value)
 				goto out_no_arg;
-			if (strlen(value) > 30)
-				value[30] = 0;
-			strncpy(volume,value,30);
+			strlcpy(volume,value,31);
 		} else if (!strcmp(this_char,"mode")) {
 			optn = "mode";
 			if (!value || !*value)
@@ -543,7 +541,7 @@
 }
 
 static struct super_block *affs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, affs_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/afs/kafstimod.c linux-2.5.69-bk19/fs/afs/kafstimod.c
--- linux-2.5.69-bk18/fs/afs/kafstimod.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/fs/afs/kafstimod.c	2003-05-26 04:41:42.000000000 -0700
@@ -83,7 +83,7 @@
 
 	for (;;) {
 		unsigned long jif;
-		signed long timeout;
+		unsigned long timeout;
 
 		/* deal with the server being asked to die */
 		if (kafstimod_die) {
diff -urN linux-2.5.69-bk18/fs/afs/super.c linux-2.5.69-bk19/fs/afs/super.c
--- linux-2.5.69-bk18/fs/afs/super.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/fs/afs/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -40,7 +40,8 @@
 static void afs_i_init_once(void *foo, kmem_cache_t *cachep, unsigned long flags);
 
 static struct super_block *afs_get_sb(struct file_system_type *fs_type,
-				      int flags, char *dev_name, void *data);
+				      int flags, const char *dev_name,
+				      void *data);
 
 static struct inode *afs_alloc_inode(struct super_block *sb);
 
@@ -81,7 +82,7 @@
 	afs_inode_cachep = kmem_cache_create("afs_inode_cache",
 						sizeof(afs_vnode_t),
 						0,
-						SLAB_HWCACHE_ALIGN,
+						SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 						afs_i_init_once,
 						NULL);
 	if (!afs_inode_cachep) {
@@ -407,10 +408,9 @@
  * get an AFS superblock
  * - TODO: don't use get_sb_nodev(), but rather call sget() directly
  */
-static struct super_block *afs_get_sb(struct file_system_type *fs_type,
-				      int flags,
-				      char *dev_name,
-				      void *options)
+static struct super_block *
+afs_get_sb(struct file_system_type *fs_type, int flags,
+	   const char *dev_name, void *options)
 {
 	struct super_block *sb;
 	void *data[2] = { dev_name, options };
diff -urN linux-2.5.69-bk18/fs/autofs/init.c linux-2.5.69-bk19/fs/autofs/init.c
--- linux-2.5.69-bk18/fs/autofs/init.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/fs/autofs/init.c	2003-05-26 04:41:42.000000000 -0700
@@ -15,7 +15,7 @@
 #include "autofs_i.h"
 
 static struct super_block *autofs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_nodev(fs_type, flags, data, autofs_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/autofs4/init.c linux-2.5.69-bk19/fs/autofs4/init.c
--- linux-2.5.69-bk18/fs/autofs4/init.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/fs/autofs4/init.c	2003-05-26 04:41:42.000000000 -0700
@@ -15,7 +15,7 @@
 #include "autofs_i.h"
 
 static struct super_block *autofs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_nodev(fs_type, flags, data, autofs4_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/befs/linuxvfs.c linux-2.5.69-bk19/fs/befs/linuxvfs.c
--- linux-2.5.69-bk18/fs/befs/linuxvfs.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/fs/befs/linuxvfs.c	2003-05-26 04:41:42.000000000 -0700
@@ -430,7 +430,7 @@
 {
 	befs_inode_cachep = kmem_cache_create("befs_inode_cache",
 					      sizeof (struct befs_inode_info),
-					      0, SLAB_HWCACHE_ALIGN,
+					      0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					      init_once, NULL);
 	if (befs_inode_cachep == NULL) {
 		printk(KERN_ERR "befs_init_inodecache: "
@@ -916,8 +916,8 @@
 }
 
 static struct super_block *
-befs_get_sb(struct file_system_type *fs_type, int flags, char *dev_name,
-		void *data)
+befs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name,
+	    void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/bfs/inode.c linux-2.5.69-bk19/fs/bfs/inode.c
--- linux-2.5.69-bk18/fs/bfs/inode.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/fs/bfs/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -243,7 +243,7 @@
 {
 	bfs_inode_cachep = kmem_cache_create("bfs_inode_cache",
 					     sizeof(struct bfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (bfs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -379,7 +379,7 @@
 }
 
 static struct super_block *bfs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, bfs_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/binfmt_misc.c linux-2.5.69-bk19/fs/binfmt_misc.c
--- linux-2.5.69-bk18/fs/binfmt_misc.c	2003-05-04 16:53:12.000000000 -0700
+++ linux-2.5.69-bk19/fs/binfmt_misc.c	2003-05-26 04:41:42.000000000 -0700
@@ -113,10 +113,8 @@
 	/* to keep locking time low, we copy the interpreter string */
 	read_lock(&entries_lock);
 	fmt = check_file(bprm);
-	if (fmt) {
-		strncpy(iname, fmt->interpreter, BINPRM_BUF_SIZE - 1);
-		iname[BINPRM_BUF_SIZE - 1] = '\0';
-	}
+	if (fmt)
+		strlcpy(iname, fmt->interpreter, BINPRM_BUF_SIZE);
 	read_unlock(&entries_lock);
 	if (!fmt)
 		goto _ret;
@@ -623,7 +621,7 @@
 }
 
 static struct super_block *bm_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_single(fs_type, flags, data, bm_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/bio.c linux-2.5.69-bk19/fs/bio.c
--- linux-2.5.69-bk18/fs/bio.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/bio.c	2003-05-26 04:41:42.000000000 -0700
@@ -33,6 +33,13 @@
 
 #define BIOVEC_NR_POOLS 6
 
+/*
+ * a small number of entries is fine, not going to be performance critical.
+ * basically we just need to survive
+ */
+#define BIO_SPLIT_ENTRIES 8	
+static mempool_t *bio_split_pool;
+
 struct biovec_pool {
 	int nr_vecs;
 	char *name; 
@@ -734,6 +741,91 @@
 		bio->bi_end_io(bio, bytes_done, error);
 }
 
+void bio_pair_release(struct bio_pair *bp)
+{
+	if (atomic_dec_and_test(&bp->cnt)) {
+		struct bio *master = bp->bio1.bi_private;
+
+		bio_endio(master, master->bi_size, bp->error);
+		mempool_free(bp, bp->bio2.bi_private);
+	}
+}
+
+static int bio_pair_end_1(struct bio * bi, unsigned int done, int err)
+{
+	struct bio_pair *bp = container_of(bi, struct bio_pair, bio1);
+
+	if (bi->bi_size)
+		return 1;
+	if (err)
+		bp->error = err;
+
+	bio_pair_release(bp);
+	return 0;
+}
+
+static int bio_pair_end_2(struct bio * bi, unsigned int done, int err)
+{
+	struct bio_pair *bp = container_of(bi, struct bio_pair, bio2);
+
+	if (bi->bi_size)
+		return 1;
+	if (err)
+		bp->error = err;
+
+	bio_pair_release(bp);
+	return 0;
+}
+
+/*
+ * split a bio - only worry about a bio with a single page
+ * in it's iovec
+ */
+struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors)
+{
+	struct bio_pair *bp = mempool_alloc(pool, GFP_NOIO);
+
+	if (!bp)
+		return bp;
+
+	BUG_ON(bi->bi_vcnt != 1);
+	BUG_ON(bi->bi_idx != 0);
+	atomic_set(&bp->cnt, 3);
+	bp->error = 0;
+	bp->bio1 = *bi;
+	bp->bio2 = *bi;
+	bp->bio2.bi_sector += first_sectors;
+	bp->bio2.bi_size -= first_sectors << 9;
+	bp->bio1.bi_size = first_sectors << 9;
+
+	bp->bv1 = bi->bi_io_vec[0];
+	bp->bv2 = bi->bi_io_vec[0];
+	bp->bv2.bv_offset += first_sectors << 9;
+	bp->bv2.bv_len -= first_sectors << 9;
+	bp->bv1.bv_len = first_sectors << 9;
+
+	bp->bio1.bi_io_vec = &bp->bv1;
+	bp->bio2.bi_io_vec = &bp->bv2;
+
+	bp->bio1.bi_end_io = bio_pair_end_1;
+	bp->bio2.bi_end_io = bio_pair_end_2;
+
+	bp->bio1.bi_private = bi;
+	bp->bio2.bi_private = pool;
+
+	return bp;
+}
+
+static void *bio_pair_alloc(int gfp_flags, void *data)
+{
+	return kmalloc(sizeof(struct bio_pair), gfp_flags);
+}
+
+static void bio_pair_free(void *bp, void *data)
+{
+	kfree(bp);
+}
+
 static void __init biovec_init_pools(void)
 {
 	int i, size, megabytes, pool_entries = BIO_POOL_SIZE;
@@ -800,6 +892,10 @@
 
 	biovec_init_pools();
 
+	bio_split_pool = mempool_create(BIO_SPLIT_ENTRIES, bio_pair_alloc, bio_pair_free, NULL);
+	if (!bio_split_pool)
+		panic("bio: can't create split pool\n");
+
 	return 0;
 }
 
@@ -818,3 +914,5 @@
 EXPORT_SYMBOL(bio_get_nr_vecs);
 EXPORT_SYMBOL(bio_map_user);
 EXPORT_SYMBOL(bio_unmap_user);
+EXPORT_SYMBOL(bio_pair_release);
+EXPORT_SYMBOL(bio_split);
diff -urN linux-2.5.69-bk18/fs/block_dev.c linux-2.5.69-bk19/fs/block_dev.c
--- linux-2.5.69-bk18/fs/block_dev.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/block_dev.c	2003-05-26 04:41:42.000000000 -0700
@@ -196,7 +196,7 @@
  */
 
 static struct super_block *bd_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_pseudo(fs_type, "bdev:", NULL, 0x62646576);
 }
diff -urN linux-2.5.69-bk18/fs/char_dev.c linux-2.5.69-bk19/fs/char_dev.c
--- linux-2.5.69-bk18/fs/char_dev.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/char_dev.c	2003-05-26 04:41:42.000000000 -0700
@@ -17,10 +17,16 @@
 #include <linux/smp_lock.h>
 #include <linux/devfs_fs_kernel.h>
 
+#include <linux/kobject.h>
+#include <linux/kobj_map.h>
+#include <linux/cdev.h>
+
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
 
+static struct kobj_map *cdev_map;
+
 #define MAX_PROBE_HASH 255	/* random */
 
 static rwlock_t chrdevs_lock = RW_LOCK_UNLOCKED;
@@ -32,6 +38,7 @@
 	int minorct;
 	const char *name;
 	struct file_operations *fops;
+	struct cdev *cdev;		/* will die */
 } *chrdevs[MAX_PROBE_HASH];
 
 /* index in the above */
@@ -60,59 +67,6 @@
 }
 
 /*
- * Return the function table of a device, if present.
- * Increment the reference count of module in question.
- */
-static struct file_operations *
-lookup_chrfops(unsigned int major, unsigned int minor)
-{
-	struct char_device_struct *cd;
-	struct file_operations *ret = NULL;
-	int i;
-
-	i = major_to_index(major);
-
-	read_lock(&chrdevs_lock);
-	for (cd = chrdevs[i]; cd; cd = cd->next) {
-		if (major == cd->major &&
-		    minor - cd->baseminor < cd->minorct) {
-			ret = fops_get(cd->fops);
-			break;
-		}
-	}
-	read_unlock(&chrdevs_lock);
-
-	return ret;
-}
-
-/*
- * Return the function table of a device, if present.
- * Load the driver if needed.
- * Increment the reference count of module in question.
- */
-static struct file_operations *
-get_chrfops(unsigned int major, unsigned int minor)
-{
-	struct file_operations *ret = NULL;
-
-	if (!major)
-		return NULL;
-
-	ret = lookup_chrfops(major, minor);
-
-#ifdef CONFIG_KMOD
-	if (!ret) {
-		request_module("char-major-%d", major);
-
-		read_lock(&chrdevs_lock);
-		ret = lookup_chrfops(major, minor);
-		read_unlock(&chrdevs_lock);
-	}
-#endif
-	return ret;
-}
-
-/*
  * Register a single major with a specified minor range.
  *
  * If major == 0 this functions will dynamically allocate a major and return
@@ -123,9 +77,9 @@
  *
  * Returns a -ve errno on failure.
  */
-int register_chrdev_region(unsigned int major, unsigned int baseminor,
-			   int minorct, const char *name,
-			   struct file_operations *fops)
+static struct char_device_struct *
+__register_chrdev_region(unsigned int major, unsigned int baseminor,
+			   int minorct, const char *name)
 {
 	struct char_device_struct *cd, **cp;
 	int ret = 0;
@@ -133,7 +87,7 @@
 
 	cd = kmalloc(sizeof(struct char_device_struct), GFP_KERNEL);
 	if (cd == NULL)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 	write_lock_irq(&chrdevs_lock);
 
@@ -156,7 +110,6 @@
 	cd->baseminor = baseminor;
 	cd->minorct = minorct;
 	cd->name = name;
-	cd->fops = fops;
 
 	i = major_to_index(major);
 
@@ -167,32 +120,23 @@
 	if (*cp && (*cp)->major == major &&
 	    (*cp)->baseminor < baseminor + minorct) {
 		ret = -EBUSY;
-	} else {
-		cd->next = *cp;
-		*cp = cd;
+		goto out;
 	}
+	cd->next = *cp;
+	*cp = cd;
+	write_unlock_irq(&chrdevs_lock);
+	return cd;
 out:
 	write_unlock_irq(&chrdevs_lock);
-	if (ret < 0)
-		kfree(cd);
-	return ret;
+	kfree(cd);
+	return ERR_PTR(ret);
 }
 
-int register_chrdev(unsigned int major, const char *name,
-		    struct file_operations *fops)
+static struct char_device_struct *
+__unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
 {
-	return register_chrdev_region(major, 0, 256, name, fops);
-}
-
-/* todo: make void - error printk here */
-int unregister_chrdev_region(unsigned int major, unsigned int baseminor,
-			     int minorct, const char *name)
-{
-	struct char_device_struct *cd, **cp;
-	int ret = 0;
-	int i;
-
-	i = major_to_index(major);
+	struct char_device_struct *cd = NULL, **cp;
+	int i = major_to_index(major);
 
 	write_lock_irq(&chrdevs_lock);
 	for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
@@ -200,42 +144,179 @@
 		    (*cp)->baseminor == baseminor &&
 		    (*cp)->minorct == minorct)
 			break;
-	if (!*cp || strcmp((*cp)->name, name))
-		ret = -EINVAL;
-	else {
+	if (*cp) {
 		cd = *cp;
 		*cp = cd->next;
-		kfree(cd);
 	}
 	write_unlock_irq(&chrdevs_lock);
+	return cd;
+}
 
-	return ret;
+int register_chrdev_region(dev_t from, unsigned count, char *name)
+{
+	struct char_device_struct *cd;
+	dev_t to = from + count;
+	dev_t n, next;
+
+	for (n = from; n < to; n = next) {
+		next = MKDEV(MAJOR(n)+1, 0);
+		if (next > to)
+			next = to;
+		cd = __register_chrdev_region(MAJOR(n), MINOR(n),
+			       next - n, name);
+		if (IS_ERR(cd))
+			goto fail;
+	}
+	return 0;
+fail:
+	to = n;
+	for (n = from; n < to; n = next) {
+		next = MKDEV(MAJOR(n)+1, 0);
+		kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
+	}
+	return PTR_ERR(cd);
+}
+
+int alloc_chrdev_region(dev_t *dev, unsigned count, char *name)
+{
+	struct char_device_struct *cd;
+	cd = __register_chrdev_region(0, 0, count, name);
+	if (IS_ERR(cd))
+		return PTR_ERR(cd);
+	*dev = MKDEV(cd->major, cd->baseminor);
+	return 0;
+}
+
+int register_chrdev(unsigned int major, const char *name,
+		    struct file_operations *fops)
+{
+	struct char_device_struct *cd;
+	struct cdev *cdev;
+	char *s;
+	int err = -ENOMEM;
+
+	cd = __register_chrdev_region(major, 0, 256, name);
+	if (IS_ERR(cd))
+		return PTR_ERR(cd);
+	
+	cdev = cdev_alloc();
+	if (!cdev)
+		goto out2;
+
+	cdev->owner = fops->owner;
+	cdev->ops = fops;
+	strcpy(cdev->kobj.name, name);
+	for (s = strchr(cdev->kobj.name, '/'); s; s = strchr(s, '/'))
+		*s = '!';
+		
+	err = cdev_add(cdev, MKDEV(cd->major, 0), 256);
+	if (err)
+		goto out;
+
+	cd->cdev = cdev;
+
+	return major ? 0 : cd->major;
+out:
+	kobject_put(&cdev->kobj);
+out2:
+	__unregister_chrdev_region(cd->major, 0, 256);
+	return err;
+}
+
+void unregister_chrdev_region(dev_t from, unsigned count)
+{
+	dev_t to = from + count;
+	dev_t n, next;
+
+	for (n = from; n < to; n = next) {
+		next = MKDEV(MAJOR(n)+1, 0);
+		if (next > to)
+			next = to;
+		kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
+	}
 }
 
 int unregister_chrdev(unsigned int major, const char *name)
 {
-	return unregister_chrdev_region(major, 0, 256, name);
+	struct char_device_struct *cd;
+	cdev_unmap(MKDEV(major, 0), 256);
+	cd = __unregister_chrdev_region(major, 0, 256);
+	if (cd && cd->cdev)
+		cdev_del(cd->cdev);
+	kfree(cd);
+	return 0;
 }
 
+static spinlock_t cdev_lock = SPIN_LOCK_UNLOCKED;
 /*
  * Called every time a character special file is opened
  */
 int chrdev_open(struct inode * inode, struct file * filp)
 {
-	int ret = -ENODEV;
+	struct cdev *p;
+	struct cdev *new = NULL;
+	int ret = 0;
 
-	filp->f_op = get_chrfops(major(inode->i_rdev), minor(inode->i_rdev));
-	if (filp->f_op) {
-		ret = 0;
-		if (filp->f_op->open != NULL) {
-			lock_kernel();
-			ret = filp->f_op->open(inode,filp);
-			unlock_kernel();
-		}
+	spin_lock(&cdev_lock);
+	p = inode->i_cdev;
+	if (!p) {
+		struct kobject *kobj;
+		int idx;
+		spin_unlock(&cdev_lock);
+		kobj = kobj_lookup(cdev_map, kdev_t_to_nr(inode->i_rdev), &idx);
+		if (!kobj)
+			return -ENODEV;
+		new = container_of(kobj, struct cdev, kobj);
+		spin_lock(&cdev_lock);
+		p = inode->i_cdev;
+		if (!p) {
+			inode->i_cdev = p = new;
+			inode->i_cindex = idx;
+			list_add(&inode->i_devices, &p->list);
+			new = NULL;
+		} else if (!cdev_get(p))
+			ret = -ENODEV;
+	} else if (!cdev_get(p))
+		ret = -ENODEV;
+	spin_unlock(&cdev_lock);
+	cdev_put(new);
+	if (ret)
+		return ret;
+	filp->f_op = fops_get(p->ops);
+	if (!filp->f_op) {
+		cdev_put(p);
+		return -ENODEV;
+	}
+	if (filp->f_op->open) {
+		lock_kernel();
+		ret = filp->f_op->open(inode,filp);
+		unlock_kernel();
 	}
+	if (ret)
+		cdev_put(p);
 	return ret;
 }
 
+void cd_forget(struct inode *inode)
+{
+	spin_lock(&cdev_lock);
+	list_del_init(&inode->i_devices);
+	inode->i_cdev = NULL;
+	spin_unlock(&cdev_lock);
+}
+
+void cdev_purge(struct cdev *cdev)
+{
+	spin_lock(&cdev_lock);
+	while (!list_empty(&cdev->list)) {
+		struct inode *inode;
+		inode = container_of(cdev->list.next, struct inode, i_devices);
+		list_del_init(&inode->i_devices);
+		inode->i_cdev = NULL;
+	}
+	spin_unlock(&cdev_lock);
+}
+
 /*
  * Dummy default file-operations: the only thing this does
  * is contain the open that then fills in the correct operations
@@ -265,3 +346,120 @@
 
 	return buffer;
 }
+
+static struct kobject *exact_match(dev_t dev, int *part, void *data)
+{
+	struct cdev *p = data;
+	return &p->kobj;
+}
+
+static int exact_lock(dev_t dev, void *data)
+{
+	struct cdev *p = data;
+	return cdev_get(p) ? 0 : -1;
+}
+
+int cdev_add(struct cdev *p, dev_t dev, unsigned count)
+{
+	int err = kobject_add(&p->kobj);
+	if (err)
+		return err;
+	return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
+}
+
+void cdev_unmap(dev_t dev, unsigned count)
+{
+	kobj_unmap(cdev_map, dev, count);
+}
+
+void cdev_del(struct cdev *p)
+{
+	kobject_del(&p->kobj);
+	kobject_put(&p->kobj);
+}
+
+struct kobject *cdev_get(struct cdev *p)
+{
+	struct module *owner = p->owner;
+	struct kobject *kobj;
+
+	if (owner && !try_module_get(owner))
+		return NULL;
+	kobj = kobject_get(&p->kobj);
+	if (!kobj)
+		module_put(owner);
+	return kobj;
+}
+
+void cdev_put(struct cdev *p)
+{
+	if (p) {
+		kobject_put(&p->kobj);
+		module_put(p->owner);
+	}
+}
+
+static decl_subsys(cdev, NULL, NULL);
+
+static void cdev_default_release(struct kobject *kobj)
+{
+	struct cdev *p = container_of(kobj, struct cdev, kobj);
+	cdev_purge(p);
+}
+
+static void cdev_dynamic_release(struct kobject *kobj)
+{
+	struct cdev *p = container_of(kobj, struct cdev, kobj);
+	cdev_purge(p);
+	kfree(p);
+}
+
+static struct kobj_type ktype_cdev_default = {
+	.release	= cdev_default_release,
+};
+
+static struct kobj_type ktype_cdev_dynamic = {
+	.release	= cdev_dynamic_release,
+};
+
+static struct kset kset_dynamic = {
+	.subsys = &cdev_subsys,
+	.kobj = {.name = "major",},
+	.ktype = &ktype_cdev_dynamic,
+};
+
+struct cdev *cdev_alloc(void)
+{
+	struct cdev *p = kmalloc(sizeof(struct cdev), GFP_KERNEL);
+	if (p) {
+		memset(p, 0, sizeof(struct cdev));
+		p->kobj.kset = &kset_dynamic;
+		INIT_LIST_HEAD(&p->list);
+		kobject_init(&p->kobj);
+	}
+	return p;
+}
+
+void cdev_init(struct cdev *cdev, struct file_operations *fops)
+{
+	INIT_LIST_HEAD(&cdev->list);
+	kobj_set_kset_s(cdev, cdev_subsys);
+	cdev->kobj.ktype = &ktype_cdev_default;
+	kobject_init(&cdev->kobj);
+	cdev->ops = fops;
+}
+
+static struct kobject *base_probe(dev_t dev, int *part, void *data)
+{
+	char name[30];
+	sprintf(name, "char-major-%d", MAJOR(dev));
+	request_module(name);
+	return NULL;
+}
+
+void __init chrdev_init(void)
+{
+	subsystem_register(&cdev_subsys);
+	kset_register(&kset_dynamic);
+	cdev_map = kobj_map_init(base_probe, &cdev_subsys);
+}
diff -urN linux-2.5.69-bk18/fs/cifs/cifsfs.c linux-2.5.69-bk19/fs/cifs/cifsfs.c
--- linux-2.5.69-bk18/fs/cifs/cifsfs.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/cifs/cifsfs.c	2003-05-26 04:41:42.000000000 -0700
@@ -57,13 +57,14 @@
 struct task_struct * oplockThread = NULL;
 
 extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
-			char *);
+			const char *);
 extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
 void cifs_proc_init(void);
 void cifs_proc_clean(void);
 
 static int
-cifs_read_super(struct super_block *sb, void *data, char *devname, int silent)
+cifs_read_super(struct super_block *sb, void *data,
+		const char *devname, int silent)
 {
 	struct inode *inode;
 	struct cifs_sb_info *cifs_sb;
@@ -251,7 +252,7 @@
 
 static struct super_block *
 cifs_get_sb(struct file_system_type *fs_type,
-	    int flags, char *dev_name, void *data)
+	    int flags, const char *dev_name, void *data)
 {
 	int rc;
 	struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
@@ -359,7 +360,7 @@
 {
 	cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
 					      sizeof (struct cifsInodeInfo),
-					      0, SLAB_HWCACHE_ALIGN,
+					      0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					      cifs_init_once, NULL);
 	if (cifs_inode_cachep == NULL)
 		return -ENOMEM;
diff -urN linux-2.5.69-bk18/fs/cifs/connect.c linux-2.5.69-bk19/fs/cifs/connect.c
--- linux-2.5.69-bk18/fs/cifs/connect.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/cifs/connect.c	2003-05-26 04:41:42.000000000 -0700
@@ -342,7 +342,7 @@
 }
 
 int
-parse_mount_options(char *options, char *devname, struct smb_vol *vol)
+parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
 {
 	char *value;
 	char *data;
@@ -795,7 +795,7 @@
 
 int
 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
-	   char *mount_data, char *devname)
+	   char *mount_data, const char *devname)
 {
 	int rc = 0;
 	int xid;
@@ -811,7 +811,7 @@
 	xid = GetXid();
 	cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data));
 
-	if(parse_mount_options(mount_data, devname, &volume_info)) {
+	if (parse_mount_options(mount_data, devname, &volume_info)) {
 		FreeXid(xid);
 		return -EINVAL;
 	}
diff -urN linux-2.5.69-bk18/fs/coda/inode.c linux-2.5.69-bk19/fs/coda/inode.c
--- linux-2.5.69-bk18/fs/coda/inode.c	2003-05-04 16:53:28.000000000 -0700
+++ linux-2.5.69-bk19/fs/coda/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -70,7 +70,7 @@
 {
 	coda_inode_cachep = kmem_cache_create("coda_inode_cache",
 					     sizeof(struct coda_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN||SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (coda_inode_cachep == NULL)
 		return -ENOMEM;
@@ -303,7 +303,7 @@
 /* init_coda: used by filesystems.c to register coda */
 
 static struct super_block *coda_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_nodev(fs_type, flags, data, coda_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/compat.c linux-2.5.69-bk19/fs/compat.c
--- linux-2.5.69-bk18/fs/compat.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/fs/compat.c	2003-05-26 04:41:42.000000000 -0700
@@ -31,6 +31,7 @@
 #include <linux/smp_lock.h>
 #include <linux/ctype.h>
 #include <linux/module.h>
+#include <net/sock.h>		/* siocdevprivate_ioctl */
 
 #include <asm/uaccess.h>
 
diff -urN linux-2.5.69-bk18/fs/cramfs/inode.c linux-2.5.69-bk19/fs/cramfs/inode.c
--- linux-2.5.69-bk18/fs/cramfs/inode.c	2003-05-04 16:52:59.000000000 -0700
+++ linux-2.5.69-bk19/fs/cramfs/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -464,7 +464,7 @@
 };
 
 static struct super_block *cramfs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/dcache.c linux-2.5.69-bk19/fs/dcache.c
--- linux-2.5.69-bk18/fs/dcache.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/dcache.c	2003-05-26 04:41:42.000000000 -0700
@@ -1272,8 +1272,9 @@
  * @buflen: buffer length
  *
  * Convert a dentry into an ASCII path name. If the entry has been deleted
- * the string " (deleted)" is appended. Note that this is ambiguous. Returns
- * the buffer.
+ * the string " (deleted)" is appended. Note that this is ambiguous.
+ *
+ * Returns the buffer or an error code if the path was too long.
  *
  * "buflen" should be positive. Caller holds the dcache_lock.
  */
@@ -1552,7 +1553,7 @@
 	dentry_cache = kmem_cache_create("dentry_cache",
 					 sizeof(struct dentry),
 					 0,
-					 SLAB_HWCACHE_ALIGN,
+					 SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					 NULL, NULL);
 	if (!dentry_cache)
 		panic("Cannot create dentry cache");
@@ -1606,6 +1607,7 @@
 EXPORT_SYMBOL(d_genocide);
 
 extern void bdev_cache_init(void);
+extern void chrdev_init(void);
 
 void __init vfs_caches_init(unsigned long mempages)
 {
@@ -1626,4 +1628,5 @@
 	files_init(mempages); 
 	mnt_init(mempages);
 	bdev_cache_init();
+	chrdev_init();
 }
diff -urN linux-2.5.69-bk18/fs/dcookies.c linux-2.5.69-bk19/fs/dcookies.c
--- linux-2.5.69-bk18/fs/dcookies.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/fs/dcookies.c	2003-05-26 04:41:42.000000000 -0700
@@ -175,6 +175,11 @@
 	/* FIXME: (deleted) ? */
 	path = d_path(dcs->dentry, dcs->vfsmnt, kbuf, PAGE_SIZE);
 
+	if (IS_ERR(path)) {
+		err = PTR_ERR(path);
+		goto out_free;
+	}
+
 	err = -ERANGE;
  
 	pathlen = kbuf + PAGE_SIZE - path;
@@ -184,6 +189,7 @@
 			err = -EFAULT;
 	}
 
+out_free:
 	kfree(kbuf);
 out:
 	up(&dcookie_sem);
diff -urN linux-2.5.69-bk18/fs/devfs/base.c linux-2.5.69-bk19/fs/devfs/base.c
--- linux-2.5.69-bk18/fs/devfs/base.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/devfs/base.c	2003-05-26 04:41:42.000000000 -0700
@@ -2554,8 +2554,9 @@
     return -EINVAL;
 }   /*  End Function devfs_fill_super  */
 
-static struct super_block *devfs_get_sb (struct file_system_type *fs_type,
-					 int flags, char *dev_name, void *data)
+static struct super_block *
+devfs_get_sb (struct file_system_type *fs_type, int flags,
+	      const char *dev_name, void *data)
 {
     return get_sb_single (fs_type, flags, data, devfs_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/devpts/Makefile linux-2.5.69-bk19/fs/devpts/Makefile
--- linux-2.5.69-bk18/fs/devpts/Makefile	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/fs/devpts/Makefile	2003-05-26 04:41:42.000000000 -0700
@@ -5,3 +5,11 @@
 obj-$(CONFIG_DEVPTS_FS) += devpts.o
 
 devpts-objs := inode.o
+
+ifeq ($(CONFIG_DEVPTS_FS_XATTR),y)
+devpts-objs += xattr.o 
+endif
+
+ifeq ($(CONFIG_DEVPTS_FS_SECURITY),y)
+devpts-objs += xattr_security.o
+endif
diff -urN linux-2.5.69-bk18/fs/devpts/inode.c linux-2.5.69-bk19/fs/devpts/inode.c
--- linux-2.5.69-bk18/fs/devpts/inode.c	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk19/fs/devpts/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -16,6 +16,7 @@
 #include <linux/sched.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
+#include "xattr.h"
 
 #define DEVPTS_SUPER_MAGIC 0x1cd1
 
@@ -72,7 +73,8 @@
 	.remount_fs	= devpts_remount,
 };
 
-static int devpts_fill_super(struct super_block *s, void *data, int silent)
+static int
+devpts_fill_super(struct super_block *s, void *data, int silent)
 {
 	struct inode * inode;
 
@@ -105,7 +107,7 @@
 }
 
 static struct super_block *devpts_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_single(fs_type, flags, data, devpts_fill_super);
 }
@@ -130,6 +132,13 @@
 	return lookup_one_len(s, root, sprintf(s, "%d", num));
 }
 
+static struct inode_operations devpts_file_inode_operations = {
+	.setxattr	= devpts_setxattr,
+	.getxattr	= devpts_getxattr,
+	.listxattr	= devpts_listxattr,
+	.removexattr	= devpts_removexattr,
+};
+
 void devpts_pty_new(int number, dev_t device)
 {
 	struct dentry *dentry;
@@ -142,6 +151,7 @@
 	inode->i_gid = config.setgid ? config.gid : current->fsgid;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	init_special_inode(inode, S_IFCHR|config.mode, device);
+	inode->i_op = &devpts_file_inode_operations;
 
 	dentry = get_node(number);
 	if (!IS_ERR(dentry) && !dentry->d_inode)
@@ -167,7 +177,10 @@
 
 static int __init init_devpts_fs(void)
 {
-	int err = register_filesystem(&devpts_fs_type);
+	int err = init_devpts_xattr();
+	if (err)
+		return err;
+	err = register_filesystem(&devpts_fs_type);
 	if (!err) {
 		devpts_mnt = kern_mount(&devpts_fs_type);
 		err = PTR_ERR(devpts_mnt);
@@ -181,6 +194,7 @@
 {
 	unregister_filesystem(&devpts_fs_type);
 	mntput(devpts_mnt);
+	exit_devpts_xattr();
 }
 
 module_init(init_devpts_fs)
diff -urN linux-2.5.69-bk18/fs/devpts/xattr.c linux-2.5.69-bk19/fs/devpts/xattr.c
--- linux-2.5.69-bk18/fs/devpts/xattr.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/fs/devpts/xattr.c	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,214 @@
+/*
+  File: fs/devpts/xattr.c
+ 
+  Derived from fs/ext3/xattr.c, changed in the following ways:
+      drop everything related to persistent storage of EAs
+      pass dentry rather than inode to internal methods
+      only presently define a handler for security modules
+*/
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <asm/semaphore.h>
+#include "xattr.h"
+
+static struct devpts_xattr_handler *devpts_xattr_handlers[DEVPTS_XATTR_INDEX_MAX];
+static rwlock_t devpts_handler_lock = RW_LOCK_UNLOCKED;
+
+int
+devpts_xattr_register(int name_index, struct devpts_xattr_handler *handler)
+{
+	int error = -EINVAL;
+
+	if (name_index > 0 && name_index <= DEVPTS_XATTR_INDEX_MAX) {
+		write_lock(&devpts_handler_lock);
+		if (!devpts_xattr_handlers[name_index-1]) {
+			devpts_xattr_handlers[name_index-1] = handler;
+			error = 0;
+		}
+		write_unlock(&devpts_handler_lock);
+	}
+	return error;
+}
+
+void
+devpts_xattr_unregister(int name_index, struct devpts_xattr_handler *handler)
+{
+	if (name_index > 0 || name_index <= DEVPTS_XATTR_INDEX_MAX) {
+		write_lock(&devpts_handler_lock);
+		devpts_xattr_handlers[name_index-1] = NULL;
+		write_unlock(&devpts_handler_lock);
+	}
+}
+
+static inline const char *
+strcmp_prefix(const char *a, const char *a_prefix)
+{
+	while (*a_prefix && *a == *a_prefix) {
+		a++;
+		a_prefix++;
+	}
+	return *a_prefix ? NULL : a;
+}
+
+/*
+ * Decode the extended attribute name, and translate it into
+ * the name_index and name suffix.
+ */
+static inline struct devpts_xattr_handler *
+devpts_xattr_resolve_name(const char **name)
+{
+	struct devpts_xattr_handler *handler = NULL;
+	int i;
+
+	if (!*name)
+		return NULL;
+	read_lock(&devpts_handler_lock);
+	for (i=0; i<DEVPTS_XATTR_INDEX_MAX; i++) {
+		if (devpts_xattr_handlers[i]) {
+			const char *n = strcmp_prefix(*name,
+				devpts_xattr_handlers[i]->prefix);
+			if (n) {
+				handler = devpts_xattr_handlers[i];
+				*name = n;
+				break;
+			}
+		}
+	}
+	read_unlock(&devpts_handler_lock);
+	return handler;
+}
+
+static inline struct devpts_xattr_handler *
+devpts_xattr_handler(int name_index)
+{
+	struct devpts_xattr_handler *handler = NULL;
+	if (name_index > 0 && name_index <= DEVPTS_XATTR_INDEX_MAX) {
+		read_lock(&devpts_handler_lock);
+		handler = devpts_xattr_handlers[name_index-1];
+		read_unlock(&devpts_handler_lock);
+	}
+	return handler;
+}
+
+/*
+ * Inode operation getxattr()
+ *
+ * dentry->d_inode->i_sem down
+ */
+ssize_t
+devpts_getxattr(struct dentry *dentry, const char *name,
+	      void *buffer, size_t size)
+{
+	struct devpts_xattr_handler *handler;
+
+	handler = devpts_xattr_resolve_name(&name);
+	if (!handler)
+		return -EOPNOTSUPP;
+	return handler->get(dentry, name, buffer, size);
+}
+
+/*
+ * Inode operation listxattr()
+ *
+ * dentry->d_inode->i_sem down
+ */
+ssize_t
+devpts_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
+{
+	struct devpts_xattr_handler *handler = NULL;
+	int i, error = 0;
+	unsigned int size = 0;
+	char *buf;
+
+	read_lock(&devpts_handler_lock);
+
+	for (i=0; i<DEVPTS_XATTR_INDEX_MAX; i++) {
+		handler = devpts_xattr_handlers[i];
+		if (handler)
+			size += handler->list(dentry, NULL);
+	}
+
+	if (!buffer) {
+		error = size;
+		goto out;
+	} else {
+		error = -ERANGE;
+		if (size > buffer_size)
+			goto out;
+	}
+
+	buf = buffer;
+	for (i=0; i<DEVPTS_XATTR_INDEX_MAX; i++) {
+		handler = devpts_xattr_handlers[i];
+		if (handler)
+			buf += handler->list(dentry, buf);
+	}
+	error = size;
+
+out:
+	read_unlock(&devpts_handler_lock);
+	return size;
+}
+
+/*
+ * Inode operation setxattr()
+ *
+ * dentry->d_inode->i_sem down
+ */
+int
+devpts_setxattr(struct dentry *dentry, const char *name,
+	      const void *value, size_t size, int flags)
+{
+	struct devpts_xattr_handler *handler;
+
+	if (size == 0)
+		value = "";  /* empty EA, do not remove */
+	handler = devpts_xattr_resolve_name(&name);
+	if (!handler)
+		return -EOPNOTSUPP;
+	return handler->set(dentry, name, value, size, flags);
+}
+
+/*
+ * Inode operation removexattr()
+ *
+ * dentry->d_inode->i_sem down
+ */
+int
+devpts_removexattr(struct dentry *dentry, const char *name)
+{
+	struct devpts_xattr_handler *handler;
+
+	handler = devpts_xattr_resolve_name(&name);
+	if (!handler)
+		return -EOPNOTSUPP;
+	return handler->set(dentry, name, NULL, 0, XATTR_REPLACE);
+}
+
+int __init
+init_devpts_xattr(void)
+{
+#ifdef CONFIG_DEVPTS_FS_SECURITY	
+	int	err;
+
+	err = devpts_xattr_register(DEVPTS_XATTR_INDEX_SECURITY,
+				    &devpts_xattr_security_handler);
+	if (err)
+		return err;
+#endif
+
+	return 0;
+}
+
+void
+exit_devpts_xattr(void)
+{
+#ifdef CONFIG_DEVPTS_FS_SECURITY	
+	devpts_xattr_unregister(DEVPTS_XATTR_INDEX_SECURITY,
+				&devpts_xattr_security_handler);
+#endif
+
+}
diff -urN linux-2.5.69-bk18/fs/devpts/xattr.h linux-2.5.69-bk19/fs/devpts/xattr.h
--- linux-2.5.69-bk18/fs/devpts/xattr.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/fs/devpts/xattr.h	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,59 @@
+/*
+  File: fs/devpts/xattr.h
+ 
+  Derived from fs/ext3/xattr.h, changed in the following ways:
+      drop everything related to persistent storage of EAs
+      pass dentry rather than inode to internal methods
+      only presently define a handler for security modules
+*/
+
+#include <linux/config.h>
+#include <linux/xattr.h>
+
+/* Name indexes */
+#define DEVPTS_XATTR_INDEX_MAX			10
+#define DEVPTS_XATTR_INDEX_SECURITY	        1
+
+# ifdef CONFIG_DEVPTS_FS_XATTR
+
+struct devpts_xattr_handler {
+	char *prefix;
+	size_t (*list)(struct dentry *dentry, char *buffer);
+	int (*get)(struct dentry *dentry, const char *name, void *buffer,
+		   size_t size);
+	int (*set)(struct dentry *dentry, const char *name, const void *buffer,
+		   size_t size, int flags);
+};
+
+extern int devpts_xattr_register(int, struct devpts_xattr_handler *);
+extern void devpts_xattr_unregister(int, struct devpts_xattr_handler *);
+
+extern int devpts_setxattr(struct dentry *, const char *, const void *, size_t, int);
+extern ssize_t devpts_getxattr(struct dentry *, const char *, void *, size_t);
+extern ssize_t devpts_listxattr(struct dentry *, char *, size_t);
+extern int devpts_removexattr(struct dentry *, const char *);
+
+extern int init_devpts_xattr(void);
+extern void exit_devpts_xattr(void);
+
+# else  /* CONFIG_DEVPTS_FS_XATTR */
+#  define devpts_setxattr		NULL
+#  define devpts_getxattr		NULL
+#  define devpts_listxattr	NULL
+#  define devpts_removexattr	NULL
+
+static inline int
+init_devpts_xattr(void)
+{
+	return 0;
+}
+
+static inline void
+exit_devpts_xattr(void)
+{
+}
+
+# endif  /* CONFIG_DEVPTS_FS_XATTR */
+
+extern struct devpts_xattr_handler devpts_xattr_security_handler;
+
diff -urN linux-2.5.69-bk18/fs/devpts/xattr_security.c linux-2.5.69-bk19/fs/devpts/xattr_security.c
--- linux-2.5.69-bk18/fs/devpts/xattr_security.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/fs/devpts/xattr_security.c	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,42 @@
+/*
+ * File: fs/devpts/xattr_security.c
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/security.h>
+#include "xattr.h"
+
+#define XATTR_SECURITY_PREFIX "security."
+
+static size_t
+devpts_xattr_security_list(struct dentry *dentry, char *buffer)
+{
+	return security_inode_listsecurity(dentry, buffer);
+}
+
+static int
+devpts_xattr_security_get(struct dentry *dentry, const char *name,
+			  void *buffer, size_t size)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return security_inode_getsecurity(dentry, name, buffer, size);
+}
+
+static int
+devpts_xattr_security_set(struct dentry *dentry, const char *name,
+			  const void *value, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return security_inode_setsecurity(dentry, name, value, size, flags);
+}
+
+struct devpts_xattr_handler devpts_xattr_security_handler = {
+	.prefix	= XATTR_SECURITY_PREFIX,
+	.list	= devpts_xattr_security_list,
+	.get	= devpts_xattr_security_get,
+	.set	= devpts_xattr_security_set,
+};
diff -urN linux-2.5.69-bk18/fs/dquot.c linux-2.5.69-bk19/fs/dquot.c
--- linux-2.5.69-bk18/fs/dquot.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/dquot.c	2003-05-26 04:41:42.000000000 -0700
@@ -1383,7 +1383,7 @@
 
 	dquot_cachep = kmem_cache_create("dquot", 
 			sizeof(struct dquot), sizeof(unsigned long) * 4,
-			SLAB_HWCACHE_ALIGN, NULL, NULL);
+			SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, NULL, NULL);
 	if (!dquot_cachep)
 		panic("Cannot create dquot SLAB cache");
 
diff -urN linux-2.5.69-bk18/fs/efs/super.c linux-2.5.69-bk19/fs/efs/super.c
--- linux-2.5.69-bk18/fs/efs/super.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/efs/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -16,7 +16,7 @@
 #include <linux/vfs.h>
 
 static struct super_block *efs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, efs_fill_super);
 }
@@ -58,7 +58,7 @@
 {
 	efs_inode_cachep = kmem_cache_create("efs_inode_cache",
 					     sizeof(struct efs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN||SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (efs_inode_cachep == NULL)
 		return -ENOMEM;
diff -urN linux-2.5.69-bk18/fs/eventpoll.c linux-2.5.69-bk19/fs/eventpoll.c
--- linux-2.5.69-bk18/fs/eventpoll.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/fs/eventpoll.c	2003-05-26 04:41:42.000000000 -0700
@@ -260,17 +260,20 @@
 static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync);
 static int ep_eventpoll_close(struct inode *inode, struct file *file);
 static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait);
-static int ep_collect_ready_items(struct eventpoll *ep, struct list_head *txlist, int maxevents);
+static int ep_collect_ready_items(struct eventpoll *ep,
+				  struct list_head *txlist, int maxevents);
 static int ep_send_events(struct eventpoll *ep, struct list_head *txlist,
 			  struct epoll_event *events);
 static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist);
-static int ep_events_transfer(struct eventpoll *ep, struct epoll_event *events, int maxevents);
-static int ep_poll(struct eventpoll *ep, struct epoll_event *events, int maxevents,
-		   long timeout);
+static int ep_events_transfer(struct eventpoll *ep,
+			      struct epoll_event *events, int maxevents);
+static int ep_poll(struct eventpoll *ep, struct epoll_event *events,
+		   int maxevents, long timeout);
 static int eventpollfs_delete_dentry(struct dentry *dentry);
 static struct inode *ep_eventpoll_inode(void);
 static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type,
-					      int flags, char *dev_name, void *data);
+					      int flags, const char *dev_name,
+					      void *data);
 
 
 /* Safe wake up implementation */
@@ -1637,10 +1640,10 @@
 }
 
 
-static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type,
-					      int flags, char *dev_name, void *data)
+static struct super_block *
+eventpollfs_get_sb(struct file_system_type *fs_type, int flags,
+		   const char *dev_name, void *data)
 {
-
 	return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC);
 }
 
diff -urN linux-2.5.69-bk18/fs/exec.c linux-2.5.69-bk19/fs/exec.c
--- linux-2.5.69-bk18/fs/exec.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/exec.c	2003-05-26 04:41:42.000000000 -0700
@@ -529,30 +529,6 @@
 	return 0;
 }
 
-static struct dentry *clean_proc_dentry(struct task_struct *p)
-{
-	struct dentry *proc_dentry = p->proc_dentry;
-
-	if (proc_dentry) {
-		spin_lock(&dcache_lock);
-		if (!d_unhashed(proc_dentry)) {
-			dget_locked(proc_dentry);
-			__d_drop(proc_dentry);
-		} else
-			proc_dentry = NULL;
-		spin_unlock(&dcache_lock);
-	}
-	return proc_dentry;
-}
-
-static inline void put_proc_dentry(struct dentry *dentry)
-{
-	if (dentry) {
-		shrink_dcache_parent(dentry);
-		dput(dentry);
-	}
-}
-
 /*
  * This function makes sure the current process has its own signal table,
  * so that flush_signal_handlers can later reset the handlers without
@@ -633,6 +609,7 @@
 		count = 1;
 	while (atomic_read(&oldsig->count) > count) {
 		oldsig->group_exit_task = current;
+		oldsig->notify_count = count;
 		__set_current_state(TASK_UNINTERRUPTIBLE);
 		spin_unlock_irq(lock);
 		schedule();
@@ -660,9 +637,11 @@
 		while (leader->state != TASK_ZOMBIE)
 			yield();
 
+		spin_lock(&leader->proc_lock);
+		spin_lock(&current->proc_lock);
+		proc_dentry1 = proc_pid_unhash(current);
+		proc_dentry2 = proc_pid_unhash(leader);
 		write_lock_irq(&tasklist_lock);
-		proc_dentry1 = clean_proc_dentry(current);
-		proc_dentry2 = clean_proc_dentry(leader);
 
 		if (leader->tgid != current->tgid)
 			BUG();
@@ -702,9 +681,10 @@
 		state = leader->state;
 
 		write_unlock_irq(&tasklist_lock);
-
-		put_proc_dentry(proc_dentry1);
-		put_proc_dentry(proc_dentry2);
+		spin_unlock(&leader->proc_lock);
+		spin_unlock(&current->proc_lock);
+		proc_pid_flush(proc_dentry1);
+		proc_pid_flush(proc_dentry2);
 
 		if (state != TASK_ZOMBIE)
 			BUG();
diff -urN linux-2.5.69-bk18/fs/ext2/super.c linux-2.5.69-bk19/fs/ext2/super.c
--- linux-2.5.69-bk18/fs/ext2/super.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/fs/ext2/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -185,7 +185,7 @@
 {
 	ext2_inode_cachep = kmem_cache_create("ext2_inode_cache",
 					     sizeof(struct ext2_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (ext2_inode_cachep == NULL)
 		return -ENOMEM;
@@ -989,7 +989,7 @@
 }
 
 static struct super_block *ext2_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/ext3/super.c linux-2.5.69-bk19/fs/ext3/super.c
--- linux-2.5.69-bk18/fs/ext3/super.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/ext3/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -529,7 +529,7 @@
 {
 	ext3_inode_cachep = kmem_cache_create("ext3_inode_cache",
 					     sizeof(struct ext3_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (ext3_inode_cachep == NULL)
 		return -ENOMEM;
@@ -2029,7 +2029,7 @@
 #endif
 
 static struct super_block *ext3_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/fat/inode.c linux-2.5.69-bk19/fs/fat/inode.c
--- linux-2.5.69-bk18/fs/fat/inode.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/fat/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -697,7 +697,7 @@
 {
 	fat_inode_cachep = kmem_cache_create("fat_inode_cache",
 					     sizeof(struct msdos_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (fat_inode_cachep == NULL)
 		return -ENOMEM;
diff -urN linux-2.5.69-bk18/fs/file_table.c linux-2.5.69-bk19/fs/file_table.c
--- linux-2.5.69-bk18/fs/file_table.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/file_table.c	2003-05-26 04:41:42.000000000 -0700
@@ -15,7 +15,7 @@
 #include <linux/security.h>
 #include <linux/eventpoll.h>
 #include <linux/mount.h>
-
+#include <linux/cdev.h>
 
 /* sysctl tunables... */
 struct files_stat_struct files_stat = {
@@ -166,6 +166,8 @@
 	if (file->f_op && file->f_op->release)
 		file->f_op->release(inode, file);
 	security_file_free(file);
+	if (unlikely(inode->i_cdev != NULL))
+		cdev_put(inode->i_cdev);
 	fops_put(file->f_op);
 	if (file->f_mode & FMODE_WRITE)
 		put_write_access(inode);
diff -urN linux-2.5.69-bk18/fs/freevxfs/vxfs_super.c linux-2.5.69-bk19/fs/freevxfs/vxfs_super.c
--- linux-2.5.69-bk18/fs/freevxfs/vxfs_super.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/fs/freevxfs/vxfs_super.c	2003-05-26 04:41:42.000000000 -0700
@@ -230,7 +230,7 @@
  * The usual module blurb.
  */
 static struct super_block *vxfs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super);
 }
@@ -247,7 +247,8 @@
 vxfs_init(void)
 {
 	vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
-			sizeof(struct vxfs_inode_info), 0, 0, NULL, NULL);
+			sizeof(struct vxfs_inode_info), 0, 
+			SLAB_RECLAIM_ACCOUNT, NULL, NULL);
 	if (vxfs_inode_cachep)
 		return (register_filesystem(&vxfs_fs_type));
 	return -ENOMEM;
diff -urN linux-2.5.69-bk18/fs/fs-writeback.c linux-2.5.69-bk19/fs/fs-writeback.c
--- linux-2.5.69-bk18/fs/fs-writeback.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/fs-writeback.c	2003-05-26 04:41:42.000000000 -0700
@@ -90,7 +90,8 @@
 		 * Only add valid (hashed) inodes to the superblock's
 		 * dirty list.  Add blockdev inodes as well.
 		 */
-		if (hlist_unhashed(&inode->i_hash) && !S_ISBLK(inode->i_mode))
+		if ((hlist_unhashed(&inode->i_hash) || (inode->i_state & (I_FREEING|I_CLEAR)))
+		    && !S_ISBLK(inode->i_mode))
 			goto out;
 
 		/*
diff -urN linux-2.5.69-bk18/fs/hfs/super.c linux-2.5.69-bk19/fs/hfs/super.c
--- linux-2.5.69-bk18/fs/hfs/super.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/fs/hfs/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -72,7 +72,7 @@
 {
 	hfs_inode_cachep = kmem_cache_create("hfs_inode_cache",
 					     sizeof(struct hfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (hfs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -100,7 +100,7 @@
 /*================ File-local variables ================*/
 
 static struct super_block *hfs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/hpfs/super.c linux-2.5.69-bk19/fs/hpfs/super.c
--- linux-2.5.69-bk18/fs/hpfs/super.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/fs/hpfs/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -191,7 +191,7 @@
 {
 	hpfs_inode_cachep = kmem_cache_create("hpfs_inode_cache",
 					     sizeof(struct hpfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (hpfs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -637,7 +637,7 @@
 }
 
 static struct super_block *hpfs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, hpfs_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/hugetlbfs/inode.c linux-2.5.69-bk19/fs/hugetlbfs/inode.c
--- linux-2.5.69-bk18/fs/hugetlbfs/inode.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/hugetlbfs/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -501,7 +501,7 @@
 }
 
 static struct super_block *hugetlbfs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_nodev(fs_type, flags, data, hugetlbfs_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/inode.c linux-2.5.69-bk19/fs/inode.c
--- linux-2.5.69-bk18/fs/inode.c	2003-05-04 16:53:56.000000000 -0700
+++ linux-2.5.69-bk19/fs/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -18,6 +18,7 @@
 #include <linux/hash.h>
 #include <linux/swap.h>
 #include <linux/security.h>
+#include <linux/cdev.h>
 
 /*
  * This is needed for the following functions:
@@ -128,6 +129,7 @@
 		memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
 		inode->i_pipe = NULL;
 		inode->i_bdev = NULL;
+		inode->i_cdev = NULL;
 		inode->i_rdev = to_kdev_t(0);
 		inode->i_security = NULL;
 		if (security_inode_alloc(inode)) {
@@ -241,6 +243,8 @@
 		inode->i_sb->s_op->clear_inode(inode);
 	if (inode->i_bdev)
 		bd_forget(inode);
+	if (inode->i_cdev)
+		cd_forget(inode);
 	inode->i_state = I_CLEAR;
 }
 
@@ -466,6 +470,7 @@
 	return inodes_stat.nr_unused;
 }
 
+static void __wait_on_freeing_inode(struct inode *inode);
 /*
  * Called with the inode lock held.
  * NOTE: we are not increasing the inode-refcount, you must call __iget()
@@ -477,6 +482,7 @@
 	struct hlist_node *node;
 	struct inode * inode = NULL;
 
+repeat:
 	hlist_for_each (node, head) { 
 		prefetch(node->next);
 		inode = hlist_entry(node, struct inode, i_hash);
@@ -484,6 +490,10 @@
 			continue;
 		if (!test(inode, data))
 			continue;
+		if (inode->i_state & (I_FREEING|I_CLEAR)) {
+			__wait_on_freeing_inode(inode);
+			goto repeat;
+		}
 		break;
 	}
 	return node ? inode : NULL;
@@ -498,6 +508,7 @@
 	struct hlist_node *node;
 	struct inode * inode = NULL;
 
+repeat:
 	hlist_for_each (node, head) {
 		prefetch(node->next);
 		inode = list_entry(node, struct inode, i_hash);
@@ -505,6 +516,10 @@
 			continue;
 		if (inode->i_sb != sb)
 			continue;
+		if (inode->i_state & (I_FREEING|I_CLEAR)) {
+			__wait_on_freeing_inode(inode);
+			goto repeat;
+		}
 		break;
 	}
 	return node ? inode : NULL;
@@ -933,11 +948,22 @@
 	spin_unlock(&inode_lock);
 }
 
+/*
+ * Tell the filesystem that this inode is no longer of any interest and should
+ * be completely destroyed.
+ *
+ * We leave the inode in the inode hash table until *after* the filesystem's
+ * ->delete_inode completes.  This ensures that an iget (such as nfsd might
+ * instigate) will always find up-to-date information either in the hash or on
+ * disk.
+ *
+ * I_FREEING is set so that no-one will take a new reference to the inode while
+ * it is being deleted.
+ */
 void generic_delete_inode(struct inode *inode)
 {
 	struct super_operations *op = inode->i_sb->s_op;
 
-	hlist_del_init(&inode->i_hash);
 	list_del_init(&inode->i_list);
 	inode->i_state|=I_FREEING;
 	inodes_stat.nr_inodes--;
@@ -956,6 +982,10 @@
 		delete(inode);
 	} else
 		clear_inode(inode);
+	spin_lock(&inode_lock);
+	hlist_del_init(&inode->i_hash);
+	spin_unlock(&inode_lock);
+	wake_up_inode(inode);
 	if (inode->i_state != I_CLEAR)
 		BUG();
 	destroy_inode(inode);
@@ -1229,6 +1259,32 @@
 	__set_current_state(TASK_RUNNING);
 }
 
+/*
+ * If we try to find an inode in the inode hash while it is being deleted, we
+ * have to wait until the filesystem completes its deletion before reporting
+ * that it isn't found.  This is because iget will immediately call
+ * ->read_inode, and we want to be sure that evidence of the deletion is found
+ * by ->read_inode.
+ *
+ * This call might return early if an inode which shares the waitq is woken up.
+ * This is most easily handled by the caller which will loop around again
+ * looking for the inode.
+ *
+ * This is called with inode_lock held.
+ */
+static void __wait_on_freeing_inode(struct inode *inode)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	wait_queue_head_t *wq = i_waitq_head(inode);
+
+	add_wait_queue(wq, &wait);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	spin_unlock(&inode_lock);
+	schedule();
+	remove_wait_queue(wq, &wait);
+	spin_lock(&inode_lock);
+}
+
 void wake_up_inode(struct inode *inode)
 {
 	wait_queue_head_t *wq = i_waitq_head(inode);
diff -urN linux-2.5.69-bk18/fs/intermezzo/super.c linux-2.5.69-bk19/fs/intermezzo/super.c
--- linux-2.5.69-bk18/fs/intermezzo/super.c	2003-05-04 16:53:56.000000000 -0700
+++ linux-2.5.69-bk19/fs/intermezzo/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -187,8 +187,9 @@
 
 /* We always need to remove the presto options before passing 
    mount options to cache FS */
-struct super_block * presto_get_sb(struct file_system_type *izo_type, 
-                                   int flags, char *devname, void * data)
+struct super_block *
+presto_get_sb(struct file_system_type *izo_type, int flags,
+	      const char *devname, void *data)
 {
         struct file_system_type *fstype;
         struct presto_cache *cache = NULL;
diff -urN linux-2.5.69-bk18/fs/intermezzo/vfs.c linux-2.5.69-bk19/fs/intermezzo/vfs.c
--- linux-2.5.69-bk18/fs/intermezzo/vfs.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/fs/intermezzo/vfs.c	2003-05-26 04:41:42.000000000 -0700
@@ -2388,7 +2388,7 @@
 
         /* We first "truncate" name to the maximum allowable in presto */
         /* This simulates the strncpy_from_use code in fs/ext_attr.c */
-        strncpy(temp,name,sizeof(temp));
+        strlcpy(temp,name,sizeof(temp));
 
         /* Pass down to cache*/
         error = iops->set_ext_attr(inode,temp,buffer,buffer_len,flags);
diff -urN linux-2.5.69-bk18/fs/isofs/inode.c linux-2.5.69-bk19/fs/isofs/inode.c
--- linux-2.5.69-bk18/fs/isofs/inode.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk19/fs/isofs/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -105,7 +105,7 @@
 {
 	isofs_inode_cachep = kmem_cache_create("isofs_inode_cache",
 					     sizeof(struct iso_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (isofs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -1376,7 +1376,7 @@
 #endif
 
 static struct super_block *isofs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/jffs/inode-v23.c linux-2.5.69-bk19/fs/jffs/inode-v23.c
--- linux-2.5.69-bk18/fs/jffs/inode-v23.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/jffs/inode-v23.c	2003-05-26 04:41:42.000000000 -0700
@@ -1783,7 +1783,7 @@
 };
 
 static struct super_block *jffs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super);
 }
@@ -1806,9 +1806,11 @@
 	jffs_proc_root = proc_mkdir("jffs", proc_root_fs);
 #endif
 	fm_cache = kmem_cache_create("jffs_fm", sizeof(struct jffs_fm),
-				     0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+				     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, 
+				     NULL, NULL);
 	node_cache = kmem_cache_create("jffs_node",sizeof(struct jffs_node),
-				       0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+				       0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, 
+				       NULL, NULL);
 	return register_filesystem(&jffs_fs_type);
 }
 
diff -urN linux-2.5.69-bk18/fs/jffs2/malloc.c linux-2.5.69-bk19/fs/jffs2/malloc.c
--- linux-2.5.69-bk18/fs/jffs2/malloc.c	2003-05-04 16:52:59.000000000 -0700
+++ linux-2.5.69-bk19/fs/jffs2/malloc.c	2003-05-26 04:41:42.000000000 -0700
@@ -73,7 +73,8 @@
 
 	inode_cache_slab = kmem_cache_create("jffs2_inode_cache",
 					     sizeof(struct jffs2_inode_cache),
-					     0, JFFS2_SLAB_POISON, NULL, NULL);
+					     0, JFFS2_SLAB_POISON|SLAB_RECLAIM_ACCOUNT, 
+					     NULL, NULL);
 	if (inode_cache_slab)
 		return 0;
  err:
diff -urN linux-2.5.69-bk18/fs/jffs2/super.c linux-2.5.69-bk19/fs/jffs2/super.c
--- linux-2.5.69-bk18/fs/jffs2/super.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/fs/jffs2/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -101,9 +101,9 @@
 	return 0;
 }
 
-static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type,
-					      int flags, char *dev_name, 
-					      void *data, struct mtd_info *mtd)
+static struct super_block *
+jffs2_get_sb_mtd(struct file_system_type *fs_type, int flags,
+		 const char *dev_name, void *data, struct mtd_info *mtd)
 {
 	struct super_block *sb;
 	struct jffs2_sb_info *c;
@@ -153,9 +153,9 @@
 	return sb;
 }
 
-static struct super_block *jffs2_get_sb_mtdnr(struct file_system_type *fs_type,
-					      int flags, char *dev_name, 
-					      void *data, int mtdnr)
+static struct super_block *
+jffs2_get_sb_mtdnr(struct file_system_type *fs_type, int flags,
+		   const char *dev_name, void *data, int mtdnr)
 {
 	struct mtd_info *mtd;
 
@@ -168,8 +168,9 @@
 	return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd);
 }
 
-static struct super_block *jffs2_get_sb(struct file_system_type *fs_type,
-					int flags, char *dev_name, void *data)
+static struct super_block *
+jffs2_get_sb(struct file_system_type *fs_type, int flags,
+	     const char *dev_name, void *data)
 {
 	int err;
 	struct nameidata nd;
@@ -299,7 +300,7 @@
 
 	jffs2_inode_cachep = kmem_cache_create("jffs2_i",
 					     sizeof(struct jffs2_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     jffs2_i_init_once, NULL);
 	if (!jffs2_inode_cachep) {
 		printk(KERN_ERR "JFFS2 error: Failed to initialise inode cache\n");
diff -urN linux-2.5.69-bk18/fs/jfs/super.c linux-2.5.69-bk19/fs/jfs/super.c
--- linux-2.5.69-bk18/fs/jfs/super.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/fs/jfs/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -372,8 +372,9 @@
 			txResume(sb);
 	}
 }
-static struct super_block *jfs_get_sb(struct file_system_type *fs_type,
-		int flags, char *dev_name, void *data)
+
+static struct super_block *jfs_get_sb(struct file_system_type *fs_type, 
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, jfs_fill_super);
 }
@@ -444,8 +445,8 @@
 	int rc;
 
 	jfs_inode_cachep =
-	    kmem_cache_create("jfs_ip", sizeof(struct jfs_inode_info), 0, 0,
-			      init_once, NULL);
+	    kmem_cache_create("jfs_ip", sizeof(struct jfs_inode_info), 0, 
+			    SLAB_RECLAIM_ACCOUNT, init_once, NULL);
 	if (jfs_inode_cachep == NULL)
 		return -ENOMEM;
 
diff -urN linux-2.5.69-bk18/fs/libfs.c linux-2.5.69-bk19/fs/libfs.c
--- linux-2.5.69-bk18/fs/libfs.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/libfs.c	2003-05-26 04:41:42.000000000 -0700
@@ -7,8 +7,6 @@
 #include <linux/mount.h>
 #include <linux/vfs.h>
 
-extern struct vfsmount *do_kern_mount(const char *, int, char *, void *);
-
 int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
 		   struct kstat *stat)
 {
diff -urN linux-2.5.69-bk18/fs/mbcache.c linux-2.5.69-bk19/fs/mbcache.c
--- linux-2.5.69-bk18/fs/mbcache.c	2003-05-04 16:53:55.000000000 -0700
+++ linux-2.5.69-bk19/fs/mbcache.c	2003-05-26 04:41:42.000000000 -0700
@@ -265,7 +265,7 @@
 			INIT_LIST_HEAD(&cache->c_indexes_hash[m][n]);
 	}
 	cache->c_entry_cache = kmem_cache_create(name, entry_size, 0,
-		0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL);
+		SLAB_RECLAIM_ACCOUNT, NULL, NULL);
 	if (!cache->c_entry_cache)
 		goto fail;
 
diff -urN linux-2.5.69-bk18/fs/minix/inode.c linux-2.5.69-bk19/fs/minix/inode.c
--- linux-2.5.69-bk18/fs/minix/inode.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk19/fs/minix/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -79,7 +79,7 @@
 {
 	minix_inode_cachep = kmem_cache_create("minix_inode_cache",
 					     sizeof(struct minix_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (minix_inode_cachep == NULL)
 		return -ENOMEM;
@@ -554,7 +554,7 @@
 }
 
 static struct super_block *minix_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, minix_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/msdos/msdosfs_syms.c linux-2.5.69-bk19/fs/msdos/msdosfs_syms.c
--- linux-2.5.69-bk18/fs/msdos/msdosfs_syms.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/fs/msdos/msdosfs_syms.c	2003-05-26 04:41:42.000000000 -0700
@@ -25,7 +25,7 @@
 EXPORT_SYMBOL(msdos_unlink);
 
 static struct super_block *msdos_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/namespace.c linux-2.5.69-bk19/fs/namespace.c
--- linux-2.5.69-bk18/fs/namespace.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/namespace.c	2003-05-26 04:41:42.000000000 -0700
@@ -23,7 +23,6 @@
 #include <linux/mount.h>
 #include <asm/uaccess.h>
 
-extern struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
 extern int __init init_rootfs(void);
 extern int __init fs_subsys_init(void);
 
@@ -39,7 +38,7 @@
 	return tmp & hash_mask;
 }
 
-struct vfsmount *alloc_vfsmnt(char *name)
+struct vfsmount *alloc_vfsmnt(const char *name)
 {
 	struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL); 
 	if (mnt) {
@@ -63,8 +62,7 @@
 
 void free_vfsmnt(struct vfsmount *mnt)
 {
-	if (mnt->mnt_devname)
-		kfree(mnt->mnt_devname);
+	kfree(mnt->mnt_devname);
 	kmem_cache_free(mnt_cache, mnt);
 }
 
@@ -486,9 +484,11 @@
 	if (err)
 		goto out_unlock;
 
+	err = -ENOENT;
 	spin_lock(&dcache_lock);
 	if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) {
 		struct list_head head;
+
 		attach_mnt(mnt, nd);
 		list_add_tail(&head, &mnt->mnt_list);
 		list_splice(&head, current->namespace->list.prev);
diff -urN linux-2.5.69-bk18/fs/ncpfs/inode.c linux-2.5.69-bk19/fs/ncpfs/inode.c
--- linux-2.5.69-bk18/fs/ncpfs/inode.c	2003-05-04 16:53:28.000000000 -0700
+++ linux-2.5.69-bk19/fs/ncpfs/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -72,7 +72,7 @@
 {
 	ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
 					     sizeof(struct ncp_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (ncp_inode_cachep == NULL)
 		return -ENOMEM;
@@ -955,7 +955,7 @@
 #endif
 
 static struct super_block *ncp_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_nodev(fs_type, flags, data, ncp_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/nfs/inode.c linux-2.5.69-bk19/fs/nfs/inode.c
--- linux-2.5.69-bk18/fs/nfs/inode.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/nfs/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -1192,7 +1192,7 @@
 }
 
 static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *raw_data)
+	int flags, const char *dev_name, void *raw_data)
 {
 	int error;
 	struct nfs_server *server;
@@ -1421,7 +1421,7 @@
 }
 
 static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *raw_data)
+	int flags, const char *dev_name, void *raw_data)
 {
 	int error;
 	struct nfs_server *server;
@@ -1571,7 +1571,7 @@
 {
 	nfs_inode_cachep = kmem_cache_create("nfs_inode_cache",
 					     sizeof(struct nfs_inode),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (nfs_inode_cachep == NULL)
 		return -ENOMEM;
diff -urN linux-2.5.69-bk18/fs/nfs/nfs4xdr.c linux-2.5.69-bk19/fs/nfs/nfs4xdr.c
--- linux-2.5.69-bk18/fs/nfs/nfs4xdr.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/fs/nfs/nfs4xdr.c	2003-05-26 04:41:42.000000000 -0700
@@ -361,7 +361,7 @@
 	*q++ = htonl(len);
 
 	status = 0;
-out:
+/* out: */
 	return status;
 }
 
diff -urN linux-2.5.69-bk18/fs/nfs/nfsroot.c linux-2.5.69-bk19/fs/nfs/nfsroot.c
--- linux-2.5.69-bk18/fs/nfs/nfsroot.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/fs/nfs/nfsroot.c	2003-05-26 04:41:42.000000000 -0700
@@ -226,10 +226,8 @@
 			}
 		}
 	}
-	if (name[0] && strcmp(name, "default")) {
-		strncpy(buf, name, NFS_MAXPATHLEN-1);
-		buf[NFS_MAXPATHLEN-1] = 0;
-	}
+	if (name[0] && strcmp(name, "default"))
+		strlcpy(buf, name, NFS_MAXPATHLEN);
 }
 
 
@@ -340,8 +338,7 @@
 {
 	ROOT_DEV = Root_NFS;
 	if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) {
-		strncpy(nfs_root_name, line, sizeof(nfs_root_name));
-		nfs_root_name[sizeof(nfs_root_name)-1] = '\0';
+		strlcpy(nfs_root_name, line, sizeof(nfs_root_name));
 	} else {
 		int n = strlen(line) + strlen(NFS_ROOT);
 		if (n >= sizeof(nfs_root_name))
diff -urN linux-2.5.69-bk18/fs/nfsctl.c linux-2.5.69-bk19/fs/nfsctl.c
--- linux-2.5.69-bk18/fs/nfsctl.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/fs/nfsctl.c	2003-05-26 04:41:42.000000000 -0700
@@ -19,8 +19,6 @@
  * open a file on nfsd fs
  */
 
-struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
-
 static struct file *do_open(char *name, int flags)
 {
 	struct nameidata nd;
diff -urN linux-2.5.69-bk18/fs/nfsd/nfsctl.c linux-2.5.69-bk19/fs/nfsd/nfsctl.c
--- linux-2.5.69-bk18/fs/nfsd/nfsctl.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/nfsd/nfsctl.c	2003-05-26 04:41:42.000000000 -0700
@@ -433,7 +433,7 @@
 }
 
 static struct super_block *nfsd_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_single(fs_type, flags, data, nfsd_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/ntfs/super.c linux-2.5.69-bk19/fs/ntfs/super.c
--- linux-2.5.69-bk18/fs/ntfs/super.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/fs/ntfs/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -1656,7 +1656,7 @@
 DECLARE_MUTEX(ntfs_lock);
 
 static struct super_block *ntfs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, ntfs_fill_super);
 }
@@ -1715,7 +1715,8 @@
 	}
 
 	ntfs_inode_cache = kmem_cache_create(ntfs_inode_cache_name,
-			sizeof(ntfs_inode), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+			sizeof(ntfs_inode), 0, 
+			SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, NULL, NULL);
 	if (!ntfs_inode_cache) {
 		printk(KERN_CRIT "NTFS: Failed to create %s!\n",
 				ntfs_inode_cache_name);
@@ -1723,7 +1724,8 @@
 	}
 
 	ntfs_big_inode_cache = kmem_cache_create(ntfs_big_inode_cache_name,
-			sizeof(big_ntfs_inode), 0, SLAB_HWCACHE_ALIGN,
+			sizeof(big_ntfs_inode), 0, 
+			SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 			ntfs_big_inode_init_once, NULL);
 	if (!ntfs_big_inode_cache) {
 		printk(KERN_CRIT "NTFS: Failed to create %s!\n",
diff -urN linux-2.5.69-bk18/fs/openpromfs/inode.c linux-2.5.69-bk19/fs/openpromfs/inode.c
--- linux-2.5.69-bk18/fs/openpromfs/inode.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/fs/openpromfs/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -1053,7 +1053,7 @@
 }
 
 static struct super_block *openprom_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_single(fs_type, flags, data, openprom_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/partitions/check.c linux-2.5.69-bk19/fs/partitions/check.c
--- linux-2.5.69-bk18/fs/partitions/check.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/partitions/check.c	2003-05-26 04:41:42.000000000 -0700
@@ -308,7 +308,7 @@
 	int j;
 	int err;
 
-	strncpy(disk->kobj.name,disk->disk_name,KOBJ_NAME_LEN);
+	strlcpy(disk->kobj.name,disk->disk_name,KOBJ_NAME_LEN);
 	/* ewww... some of these buggers have / in name... */
 	s = strchr(disk->kobj.name, '/');
 	if (s)
diff -urN linux-2.5.69-bk18/fs/pipe.c linux-2.5.69-bk19/fs/pipe.c
--- linux-2.5.69-bk18/fs/pipe.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/pipe.c	2003-05-26 04:41:42.000000000 -0700
@@ -627,7 +627,7 @@
  */
 
 static struct super_block *pipefs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC);
 }
diff -urN linux-2.5.69-bk18/fs/proc/base.c linux-2.5.69-bk19/fs/proc/base.c
--- linux-2.5.69-bk18/fs/proc/base.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/proc/base.c	2003-05-26 04:41:42.000000000 -0700
@@ -58,6 +58,13 @@
 	PROC_PID_MAPS,
 	PROC_PID_MOUNTS,
 	PROC_PID_WCHAN,
+#ifdef CONFIG_SECURITY
+	PROC_PID_ATTR,
+	PROC_PID_ATTR_CURRENT,
+	PROC_PID_ATTR_PREV,
+	PROC_PID_ATTR_EXEC,
+	PROC_PID_ATTR_FSCREATE,
+#endif
 	PROC_PID_FD_DIR = 0x8000,	/* 0x8000-0xffff */
 };
 
@@ -82,11 +89,23 @@
   E(PROC_PID_ROOT,	"root",		S_IFLNK|S_IRWXUGO),
   E(PROC_PID_EXE,	"exe",		S_IFLNK|S_IRWXUGO),
   E(PROC_PID_MOUNTS,	"mounts",	S_IFREG|S_IRUGO),
+#ifdef CONFIG_SECURITY
+  E(PROC_PID_ATTR,	"attr",		S_IFDIR|S_IRUGO|S_IXUGO),
+#endif
 #ifdef CONFIG_KALLSYMS
   E(PROC_PID_WCHAN,	"wchan",	S_IFREG|S_IRUGO),
 #endif
   {0,0,NULL,0}
 };
+#ifdef CONFIG_SECURITY
+static struct pid_entry attr_stuff[] = {
+  E(PROC_PID_ATTR_CURRENT,	"current",	S_IFREG|S_IRUGO|S_IWUGO),
+  E(PROC_PID_ATTR_PREV,	"prev",	S_IFREG|S_IRUGO),
+  E(PROC_PID_ATTR_EXEC,	"exec",	S_IFREG|S_IRUGO|S_IWUGO),
+  E(PROC_PID_ATTR_FSCREATE,	"fscreate",	S_IFREG|S_IRUGO|S_IWUGO),
+  {0,0,NULL,0}
+};
+#endif
 #undef E
 
 static inline struct task_struct *proc_task(struct inode *inode)
@@ -411,8 +430,10 @@
 	if (count + *ppos > length)
 		count = length - *ppos;
 	end = count + *ppos;
-	copy_to_user(buf, (char *) page + *ppos, count);
-	*ppos = end;
+	if (copy_to_user(buf, (char *) page + *ppos, count))
+		count = -EFAULT;
+	else
+		*ppos = end;
 	free_page(page);
 	return count;
 }
@@ -624,6 +645,12 @@
 	.follow_link	= proc_pid_follow_link
 };
 
+static int pid_alive(struct task_struct *p)
+{
+	BUG_ON(p->pids[PIDTYPE_PID].pidptr != &p->pids[PIDTYPE_PID].pid);
+	return atomic_read(&p->pids[PIDTYPE_PID].pid.count);
+}
+
 #define NUMBUF 10
 
 static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
@@ -635,6 +662,9 @@
 	char buf[NUMBUF];
 	struct files_struct * files;
 
+	retval = -ENOENT;
+	if (!pid_alive(p))
+		goto out;
 	retval = 0;
 	pid = p->pid;
 
@@ -689,58 +719,68 @@
 	return retval;
 }
 
-static int proc_base_readdir(struct file * filp,
-	void * dirent, filldir_t filldir)
+static int proc_pident_readdir(struct file *filp,
+		void *dirent, filldir_t filldir,
+		struct pid_entry *ents, unsigned int nents)
 {
 	int i;
 	int pid;
-	struct inode *inode = filp->f_dentry->d_inode;
+	struct dentry *dentry = filp->f_dentry;
+	struct inode *inode = dentry->d_inode;
 	struct pid_entry *p;
-	int ret = 0;
+	ino_t ino;
+	int ret;
 
-	lock_kernel();
+	ret = -ENOENT;
+	if (!pid_alive(proc_task(inode)))
+		goto out;
 
+	ret = 0;
 	pid = proc_task(inode)->pid;
-	if (!pid) {
-		ret = -ENOENT;
-		goto out;
-	}
 	i = filp->f_pos;
 	switch (i) {
-		case 0:
-			if (filldir(dirent, ".", 1, i, inode->i_ino, DT_DIR) < 0)
-				goto out;
-			i++;
-			filp->f_pos++;
-			/* fall through */
-		case 1:
-			if (filldir(dirent, "..", 2, i, PROC_ROOT_INO, DT_DIR) < 0)
+	case 0:
+		ino = inode->i_ino;
+		if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
+			goto out;
+		i++;
+		filp->f_pos++;
+		/* fall through */
+	case 1:
+		ino = parent_ino(dentry);
+		if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
+			goto out;
+		i++;
+		filp->f_pos++;
+		/* fall through */
+	default:
+		i -= 2;
+		if (i >= nents) {
+			ret = 1;
+			goto out;
+		}
+		p = ents + i;
+		while (p->name) {
+			if (filldir(dirent, p->name, p->len, filp->f_pos,
+				    fake_ino(pid, p->type), p->mode >> 12) < 0)
 				goto out;
-			i++;
 			filp->f_pos++;
-			/* fall through */
-		default:
-			i -= 2;
-			if (i>=sizeof(base_stuff)/sizeof(base_stuff[0])) {
-				ret = 1;
-				goto out;
-			}
-			p = base_stuff + i;
-			while (p->name) {
-				if (filldir(dirent, p->name, p->len, filp->f_pos,
-					    fake_ino(pid, p->type), p->mode >> 12) < 0)
-					goto out;
-				filp->f_pos++;
-				p++;
-			}
+			p++;
+		}
 	}
 
 	ret = 1;
 out:
-	unlock_kernel();
 	return ret;
 }
 
+static int proc_base_readdir(struct file * filp,
+			     void * dirent, filldir_t filldir)
+{
+	return proc_pident_readdir(filp,dirent,filldir,
+				   base_stuff,ARRAY_SIZE(base_stuff));
+}
+
 /* building an inode */
 
 static int task_dumpable(struct task_struct *task)
@@ -774,7 +814,7 @@
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	inode->i_ino = fake_ino(task->pid, ino);
 
-	if (!task->pid)
+	if (!pid_alive(task))
 		goto out_unlock;
 
 	/*
@@ -789,6 +829,7 @@
 		inode->i_uid = task->euid;
 		inode->i_gid = task->egid;
 	}
+	security_task_to_inode(task, inode);
 
 out:
 	return inode;
@@ -808,7 +849,7 @@
  */
 static int pid_revalidate(struct dentry * dentry, int flags)
 {
-	if (proc_task(dentry->d_inode)->pid)
+	if (pid_alive(proc_task(dentry->d_inode)))
 		return 1;
 	d_drop(dentry);
 	return 0;
@@ -842,18 +883,23 @@
 static void pid_base_iput(struct dentry *dentry, struct inode *inode)
 {
 	struct task_struct *task = proc_task(inode);
-	write_lock_irq(&tasklist_lock);
+	spin_lock(&task->proc_lock);
 	if (task->proc_dentry == dentry)
 		task->proc_dentry = NULL;
-	write_unlock_irq(&tasklist_lock);
+	spin_unlock(&task->proc_lock);
 	iput(inode);
 }
 
 static int pid_delete_dentry(struct dentry * dentry)
 {
-	return proc_task(dentry->d_inode)->pid == 0;
+	/* Is the task we represent dead?
+	 * If so, then don't put the dentry on the lru list,
+	 * kill it immediately.
+	 */
+	return !pid_alive(proc_task(dentry->d_inode));
 }
 
+
 static struct dentry_operations pid_fd_dentry_operations =
 {
 	.d_revalidate	= pid_fd_revalidate,
@@ -909,6 +955,8 @@
 
 	if (fd == ~0U)
 		goto out;
+	if (!pid_alive(task))
+		goto out;
 
 	inode = proc_pid_make_inode(dir->i_sb, task, PROC_PID_FD_DIR+fd);
 	if (!inode)
@@ -937,8 +985,6 @@
 	ei->op.proc_get_link = proc_fd_link;
 	dentry->d_op = &pid_fd_dentry_operations;
 	d_add(dentry, inode);
-	if (!proc_task(dentry->d_inode)->pid)
-		d_drop(dentry);
 	return NULL;
 
 out_unlock2:
@@ -963,8 +1009,86 @@
 	.permission	= proc_permission,
 };
 
+#ifdef CONFIG_SECURITY
+static ssize_t proc_pid_attr_read(struct file * file, char * buf,
+				  size_t count, loff_t *ppos)
+{
+	struct inode * inode = file->f_dentry->d_inode;
+	unsigned long page;
+	ssize_t length;
+	ssize_t end;
+	struct task_struct *task = proc_task(inode);
+
+	if (count > PAGE_SIZE)
+		count = PAGE_SIZE;
+	if (!(page = __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+
+	length = security_getprocattr(task, 
+				      (char*)file->f_dentry->d_name.name, 
+				      (void*)page, count);
+	if (length < 0) {
+		free_page(page);
+		return length;
+	}
+	/* Static 4kB (or whatever) block capacity */
+	if (*ppos >= length) {
+		free_page(page);
+		return 0;
+	}
+	if (count + *ppos > length)
+		count = length - *ppos;
+	end = count + *ppos;
+	if (copy_to_user(buf, (char *) page + *ppos, count))
+		count = -EFAULT;
+	else
+		*ppos = end;
+	free_page(page);
+	return count;
+}
+
+static ssize_t proc_pid_attr_write(struct file * file, const char * buf,
+				   size_t count, loff_t *ppos)
+{ 
+	struct inode * inode = file->f_dentry->d_inode;
+	char *page; 
+	ssize_t length; 
+	struct task_struct *task = proc_task(inode); 
+
+	if (count > PAGE_SIZE) 
+		count = PAGE_SIZE; 
+	if (*ppos != 0) {
+		/* No partial writes. */
+		return -EINVAL;
+	}
+	page = (char*)__get_free_page(GFP_USER); 
+	if (!page) 
+		return -ENOMEM;
+	length = -EFAULT; 
+	if (copy_from_user(page, buf, count)) 
+		goto out;
+
+	length = security_setprocattr(task, 
+				      (char*)file->f_dentry->d_name.name, 
+				      (void*)page, count);
+out:
+	free_page((unsigned long) page);
+	return length;
+} 
+
+static struct file_operations proc_pid_attr_operations = {
+	.read		= proc_pid_attr_read,
+	.write		= proc_pid_attr_write,
+};
+
+static struct file_operations proc_attr_operations;
+static struct inode_operations proc_attr_inode_operations;
+#endif
+
 /* SMP-safe */
-static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *proc_pident_lookup(struct inode *dir, 
+					 struct dentry *dentry,
+					 struct pid_entry *ents)
 {
 	struct inode *inode;
 	int error;
@@ -975,7 +1099,10 @@
 	error = -ENOENT;
 	inode = NULL;
 
-	for (p = base_stuff; p->name; p++) {
+	if (!pid_alive(task))
+		goto out;
+
+	for (p = ents; p->name; p++) {
 		if (p->len != dentry->d_name.len)
 			continue;
 		if (!memcmp(dentry->d_name.name, p->name, p->len))
@@ -1043,6 +1170,19 @@
 		case PROC_PID_MOUNTS:
 			inode->i_fop = &proc_mounts_operations;
 			break;
+#ifdef CONFIG_SECURITY
+		case PROC_PID_ATTR:
+			inode->i_nlink = 2;
+			inode->i_op = &proc_attr_inode_operations;
+			inode->i_fop = &proc_attr_operations;
+			break;
+		case PROC_PID_ATTR_CURRENT:
+		case PROC_PID_ATTR_PREV:
+		case PROC_PID_ATTR_EXEC:
+		case PROC_PID_ATTR_FSCREATE:
+			inode->i_fop = &proc_pid_attr_operations;
+			break;
+#endif
 #ifdef CONFIG_KALLSYMS
 		case PROC_PID_WCHAN:
 			inode->i_fop = &proc_info_file_operations;
@@ -1056,14 +1196,16 @@
 	}
 	dentry->d_op = &pid_dentry_operations;
 	d_add(dentry, inode);
-	if (!proc_task(dentry->d_inode)->pid)
-		d_drop(dentry);
 	return NULL;
 
 out:
 	return ERR_PTR(error);
 }
 
+static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry){
+	return proc_pident_lookup(dir, dentry, base_stuff);
+}
+
 static struct file_operations proc_base_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_base_readdir,
@@ -1073,6 +1215,28 @@
 	.lookup		= proc_base_lookup,
 };
 
+#ifdef CONFIG_SECURITY
+static int proc_attr_readdir(struct file * filp,
+			     void * dirent, filldir_t filldir)
+{
+	return proc_pident_readdir(filp,dirent,filldir,
+				   attr_stuff,ARRAY_SIZE(attr_stuff));
+}
+
+static struct file_operations proc_attr_operations = {
+	.read		= generic_read_dir,
+	.readdir	= proc_attr_readdir,
+};
+
+static struct dentry *proc_attr_lookup(struct inode *dir, struct dentry *dentry){
+	return proc_pident_lookup(dir, dentry, attr_stuff);
+}
+
+static struct inode_operations proc_attr_inode_operations = {
+	.lookup		= proc_attr_lookup,
+};
+#endif
+
 /*
  * /proc/self:
  */
@@ -1095,6 +1259,55 @@
 	.follow_link	= proc_self_follow_link,
 };
 
+/**
+ * proc_pid_unhash -  Unhash /proc/<pid> entry from the dcache.
+ * @p: task that should be flushed.
+ *
+ * Drops the /proc/<pid> dcache entry from the hash chains.
+ *
+ * Dropping /proc/<pid> entries and detach_pid must be synchroneous,
+ * otherwise e.g. /proc/<pid>/exe might point to the wrong executable,
+ * if the pid value is immediately reused. This is enforced by
+ * - caller must acquire spin_lock(p->proc_lock)
+ * - must be called before detach_pid()
+ * - proc_pid_lookup acquires proc_lock, and checks that
+ *   the target is not dead by looking at the attach count
+ *   of PIDTYPE_PID.
+ */
+
+struct dentry *proc_pid_unhash(struct task_struct *p)
+{
+	struct dentry *proc_dentry;
+
+	proc_dentry = p->proc_dentry;
+	if (proc_dentry != NULL) {
+
+		spin_lock(&dcache_lock);
+		if (!d_unhashed(proc_dentry)) {
+			dget_locked(proc_dentry);
+			__d_drop(proc_dentry);
+		} else
+			proc_dentry = NULL;
+		spin_unlock(&dcache_lock);
+	}
+	return proc_dentry;
+}
+
+/**
+ * proc_pid_flush - recover memory used by stale /proc/<pid>/x entries
+ * @proc_entry: directoy to prune.
+ *
+ * Shrink the /proc directory that was used by the just killed thread.
+ */
+	
+void proc_pid_flush(struct dentry *proc_dentry)
+{
+	if(proc_dentry != NULL) {
+		shrink_dcache_parent(proc_dentry);
+		dput(proc_dentry);
+	}
+}
+
 /* SMP-safe */
 struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry)
 {
@@ -1143,12 +1356,12 @@
 	inode->i_flags|=S_IMMUTABLE;
 
 	dentry->d_op = &pid_base_dentry_operations;
+
+	spin_lock(&task->proc_lock);
+	task->proc_dentry = dentry;
 	d_add(dentry, inode);
-	read_lock(&tasklist_lock);
-	proc_task(dentry->d_inode)->proc_dentry = dentry;
-	read_unlock(&tasklist_lock);
-	if (!proc_task(dentry->d_inode)->pid)
-		d_drop(dentry);
+	spin_unlock(&task->proc_lock);
+
 	return NULL;
 out:
 	return ERR_PTR(-ENOENT);
@@ -1171,7 +1384,7 @@
 	read_lock(&tasklist_lock);
 	for_each_process(p) {
 		int pid = p->pid;
-		if (!pid)
+		if (!pid_alive(p))
 			continue;
 		if (--index >= 0)
 			continue;
diff -urN linux-2.5.69-bk18/fs/proc/inode.c linux-2.5.69-bk19/fs/proc/inode.c
--- linux-2.5.69-bk18/fs/proc/inode.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/fs/proc/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -121,7 +121,7 @@
 {
 	proc_inode_cachep = kmem_cache_create("proc_inode_cache",
 					     sizeof(struct proc_inode),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (proc_inode_cachep == NULL)
 		return -ENOMEM;
diff -urN linux-2.5.69-bk18/fs/proc/proc_misc.c linux-2.5.69-bk19/fs/proc/proc_misc.c
--- linux-2.5.69-bk18/fs/proc/proc_misc.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/fs/proc/proc_misc.c	2003-05-26 04:41:42.000000000 -0700
@@ -485,7 +485,6 @@
 	int len;
 
 	len = sprintf(page, "%s\n", saved_command_line);
-	len = strlen(page);
 	return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
diff -urN linux-2.5.69-bk18/fs/proc/root.c linux-2.5.69-bk19/fs/proc/root.c
--- linux-2.5.69-bk18/fs/proc/root.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/fs/proc/root.c	2003-05-26 04:41:42.000000000 -0700
@@ -25,7 +25,7 @@
 #endif
 
 static struct super_block *proc_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_single(fs_type, flags, data, proc_fill_super);
 }
@@ -110,9 +110,9 @@
 		}
 		filp->f_pos = FIRST_PROCESS_ENTRY;
 	}
+	unlock_kernel();
 
 	ret = proc_pid_readdir(filp, dirent, filldir);
-	unlock_kernel();
 	return ret;
 }
 
diff -urN linux-2.5.69-bk18/fs/qnx4/inode.c linux-2.5.69-bk19/fs/qnx4/inode.c
--- linux-2.5.69-bk18/fs/qnx4/inode.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/fs/qnx4/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -540,7 +540,7 @@
 {
 	qnx4_inode_cachep = kmem_cache_create("qnx4_inode_cache",
 					     sizeof(struct qnx4_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (qnx4_inode_cachep == NULL)
 		return -ENOMEM;
@@ -555,7 +555,7 @@
 }
 
 static struct super_block *qnx4_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, qnx4_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/ramfs/inode.c linux-2.5.69-bk19/fs/ramfs/inode.c
--- linux-2.5.69-bk18/fs/ramfs/inode.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/fs/ramfs/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -192,13 +192,13 @@
 }
 
 static struct super_block *ramfs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_nodev(fs_type, flags, data, ramfs_fill_super);
 }
 
 static struct super_block *rootfs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/readdir.c linux-2.5.69-bk19/fs/readdir.c
--- linux-2.5.69-bk18/fs/readdir.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/fs/readdir.c	2003-05-26 04:41:42.000000000 -0700
@@ -59,7 +59,7 @@
 
 struct readdir_callback {
 	struct old_linux_dirent __user * dirent;
-	int count;
+	int result;
 };
 
 static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset,
@@ -68,21 +68,24 @@
 	struct readdir_callback * buf = (struct readdir_callback *) __buf;
 	struct old_linux_dirent __user * dirent;
 
-	if (buf->count)
+	if (buf->result)
 		return -EINVAL;
-	buf->count++;
+	buf->result++;
 	dirent = buf->dirent;
 	if (!access_ok(VERIFY_WRITE, (unsigned long)dirent,
 			(unsigned long)(dirent->d_name + namlen + 1) -
 				(unsigned long)dirent))
-		return -EFAULT;
+		goto efault;
 	if (	__put_user(ino, &dirent->d_ino) ||
 		__put_user(offset, &dirent->d_offset) ||
 		__put_user(namlen, &dirent->d_namlen) ||
 		__copy_to_user(dirent->d_name, name, namlen) ||
 		__put_user(0, dirent->d_name + namlen))
-		return -EFAULT;
+		goto efault;
 	return 0;
+efault:
+	buf->result = -EFAULT;
+	return -EFAULT;
 }
 
 asmlinkage long old_readdir(unsigned int fd, struct old_linux_dirent __user * dirent, unsigned int count)
@@ -96,12 +99,12 @@
 	if (!file)
 		goto out;
 
-	buf.count = 0;
+	buf.result = 0;
 	buf.dirent = dirent;
 
 	error = vfs_readdir(file, fillonedir, &buf);
 	if (error >= 0)
-		error = buf.count;
+		error = buf.result;
 
 	fput(file);
 out:
@@ -144,7 +147,6 @@
 			goto efault;
 	}
 	dirent = buf->current_dir;
-	buf->previous = dirent;
 	if (__put_user(ino, &dirent->d_ino))
 		goto efault;
 	if (__put_user(reclen, &dirent->d_reclen))
@@ -153,11 +155,13 @@
 		goto efault;
 	if (__put_user(0, dirent->d_name + namlen))
 		goto efault;
+	buf->previous = dirent;
 	((char *) dirent) += reclen;
 	buf->current_dir = dirent;
 	buf->count -= reclen;
 	return 0;
 efault:
+	buf->error = -EFAULT;
 	return -EFAULT;
 }
 
@@ -225,7 +229,6 @@
 			goto efault;
 	}
 	dirent = buf->current_dir;
-	buf->previous = dirent;
 	if (__put_user(ino, &dirent->d_ino))
 		goto efault;
 	if (__put_user(0, &dirent->d_off))
@@ -238,11 +241,13 @@
 		goto efault;
 	if (__put_user(0, dirent->d_name + namlen))
 		goto efault;
+	buf->previous = dirent;
 	((char *) dirent) += reclen;
 	buf->current_dir = dirent;
 	buf->count -= reclen;
 	return 0;
 efault:
+	buf->error = -EFAULT;
 	return -EFAULT;
 }
 
diff -urN linux-2.5.69-bk18/fs/reiserfs/dir.c linux-2.5.69-bk19/fs/reiserfs/dir.c
--- linux-2.5.69-bk18/fs/reiserfs/dir.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/reiserfs/dir.c	2003-05-26 04:41:42.000000000 -0700
@@ -21,6 +21,7 @@
     .read	= generic_read_dir,
     .readdir	= reiserfs_readdir,
     .fsync	= reiserfs_dir_fsync,
+    .ioctl	= reiserfs_ioctl,
 };
 
 int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, int datasync) {
diff -urN linux-2.5.69-bk18/fs/reiserfs/inode.c linux-2.5.69-bk19/fs/reiserfs/inode.c
--- linux-2.5.69-bk18/fs/reiserfs/inode.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/reiserfs/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -918,8 +918,6 @@
     REISERFS_I(inode)->i_prealloc_count = 0;
     REISERFS_I(inode)->i_trans_id = 0;
     REISERFS_I(inode)->i_trans_index = 0;
-    /* nopack = 0, by default */
-    REISERFS_I(inode)->i_flags &= ~i_nopack_mask;
 
     if (stat_data_v1 (ih)) {
 	struct stat_data_v1 * sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih);
@@ -954,6 +952,9 @@
 
         rdev = sd_v1_rdev(sd);
 	REISERFS_I(inode)->i_first_direct_byte = sd_v1_first_direct_byte(sd);
+	/* nopack is initially zero for v1 objects. For v2 objects,
+	   nopack is initialised from sd_attrs */
+	REISERFS_I(inode)->i_flags &= ~i_nopack_mask;
     } else {
 	// new stat data found, but object may have old items
 	// (directories and symlinks)
@@ -983,6 +984,10 @@
 	    set_inode_item_key_version (inode, KEY_FORMAT_3_6);
 	REISERFS_I(inode)->i_first_direct_byte = 0;
 	set_inode_sd_version (inode, STAT_DATA_V2);
+	/* read persistent inode attributes from sd and initalise
+	   generic inode flags from them */
+	REISERFS_I(inode)->i_attrs = sd_v2_attrs( sd );
+	sd_attrs_to_i_attrs( sd_v2_attrs( sd ), inode );
     }
 
     pathrelse (path);
@@ -1007,6 +1012,7 @@
 static void inode2sd (void * sd, struct inode * inode)
 {
     struct stat_data * sd_v2 = (struct stat_data *)sd;
+    __u16 flags;
 
     set_sd_v2_mode(sd_v2, inode->i_mode );
     set_sd_v2_nlink(sd_v2, inode->i_nlink );
@@ -1017,13 +1023,13 @@
     set_sd_v2_atime(sd_v2, inode->i_atime.tv_sec );
     set_sd_v2_ctime(sd_v2, inode->i_ctime.tv_sec );
     set_sd_v2_blocks(sd_v2, inode->i_blocks );
-    if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
-        set_sd_v2_rdev(sd_v2, kdev_t_to_nr(inode->i_rdev) );
-}
+    if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
+	set_sd_v2_rdev(sd_v2, kdev_t_to_nr(inode->i_rdev) );
     else
-    {
-        set_sd_v2_generation(sd_v2, inode->i_generation);
-    }
+	set_sd_v2_generation(sd_v2, inode->i_generation);
+    flags = REISERFS_I(inode)->i_attrs;
+    i_attrs_to_sd_attrs( inode, &flags );
+    set_sd_v2_attrs( sd_v2, flags );
 }
 
 
@@ -1553,6 +1559,10 @@
 
     /* uid and gid must already be set by the caller for quota init */
 
+    /* symlink cannot be immutable or append only, right? */
+    if( S_ISLNK( inode -> i_mode ) )
+	    inode -> i_flags &= ~ ( S_IMMUTABLE | S_APPEND );
+
     inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
     inode->i_size = i_size;
     inode->i_blocks = (inode->i_size + 511) >> 9;
@@ -1565,6 +1575,9 @@
     REISERFS_I(inode)->i_prealloc_count = 0;
     REISERFS_I(inode)->i_trans_id = 0;
     REISERFS_I(inode)->i_trans_index = 0;
+    REISERFS_I(inode)->i_attrs =
+	REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK;
+    sd_attrs_to_i_attrs( REISERFS_I(inode) -> i_attrs, inode );
 
     if (old_format_only (sb))
 	make_le_item_head (&ih, 0, KEY_FORMAT_3_5, SD_OFFSET, TYPE_STAT_DATA, SD_V1_SIZE, MAX_US_INT);
@@ -2210,6 +2223,50 @@
     return ret ;
 }
 
+void sd_attrs_to_i_attrs( __u16 sd_attrs, struct inode *inode )
+{
+	if( reiserfs_attrs( inode -> i_sb ) ) {
+		if( sd_attrs & REISERFS_SYNC_FL )
+			inode -> i_flags |= S_SYNC;
+		else
+			inode -> i_flags &= ~S_SYNC;
+		if( sd_attrs & REISERFS_IMMUTABLE_FL )
+			inode -> i_flags |= S_IMMUTABLE;
+		else
+			inode -> i_flags &= ~S_IMMUTABLE;
+		if( sd_attrs & REISERFS_NOATIME_FL )
+			inode -> i_flags |= S_NOATIME;
+		else
+			inode -> i_flags &= ~S_NOATIME;
+		if( sd_attrs & REISERFS_NOTAIL_FL )
+			REISERFS_I(inode)->i_flags |= i_nopack_mask;
+		else
+			REISERFS_I(inode)->i_flags &= ~i_nopack_mask;
+	}
+}
+
+void i_attrs_to_sd_attrs( struct inode *inode, __u16 *sd_attrs )
+{
+	if( reiserfs_attrs( inode -> i_sb ) ) {
+		if( inode -> i_flags & S_IMMUTABLE )
+			*sd_attrs |= REISERFS_IMMUTABLE_FL;
+		else
+			*sd_attrs &= ~REISERFS_IMMUTABLE_FL;
+		if( inode -> i_flags & S_SYNC )
+			*sd_attrs |= REISERFS_SYNC_FL;
+		else
+			*sd_attrs &= ~REISERFS_SYNC_FL;
+		if( inode -> i_flags & S_NOATIME )
+			*sd_attrs |= REISERFS_NOATIME_FL;
+		else
+			*sd_attrs &= ~REISERFS_NOATIME_FL;
+		if( REISERFS_I(inode)->i_flags & i_nopack_mask )
+			*sd_attrs |= REISERFS_NOTAIL_FL;
+		else
+			*sd_attrs &= ~REISERFS_NOTAIL_FL;
+	}
+}
+
 /*
  * Returns 1 if the page's buffers were dropped.  The page is locked.
  *
diff -urN linux-2.5.69-bk18/fs/reiserfs/ioctl.c linux-2.5.69-bk19/fs/reiserfs/ioctl.c
--- linux-2.5.69-bk18/fs/reiserfs/ioctl.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/fs/reiserfs/ioctl.c	2003-05-26 04:41:42.000000000 -0700
@@ -14,17 +14,70 @@
 ** supported commands:
 **  1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
 **                           and prevent packing file (argument arg has to be non-zero)
-**  2) That's all for a while ...
+**  2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION
+**  3) That's all for a while ...
 */
 int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 		unsigned long arg)
 {
+	unsigned int flags;
+
 	switch (cmd) {
 	    case REISERFS_IOC_UNPACK:
+		if( S_ISREG( inode -> i_mode ) ) {
 		if (arg)
 		    return reiserfs_unpack (inode, filp);
+			else
+				return 0;
+		} else
+			return -ENOTTY;
+	/* following two cases are taken from fs/ext2/ioctl.c by Remy
+	   Card (card@masi.ibp.fr) */
+	case REISERFS_IOC_GETFLAGS:
+		flags = REISERFS_I(inode) -> i_attrs;
+		i_attrs_to_sd_attrs( inode, ( __u16 * ) &flags );
+		return put_user(flags, (int *) arg);
+	case REISERFS_IOC_SETFLAGS: {
+		if (IS_RDONLY(inode))
+			return -EROFS;
+
+		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+			return -EPERM;
+
+		if (get_user(flags, (int *) arg))
+			return -EFAULT;
+
+		if ( ( flags & REISERFS_IMMUTABLE_FL ) && 
+		     !capable( CAP_LINUX_IMMUTABLE ) )
+			return -EPERM;
 			
-	    default:
+		if( ( flags & REISERFS_NOTAIL_FL ) &&
+		    S_ISREG( inode -> i_mode ) ) {
+				int result;
+
+				result = reiserfs_unpack( inode, filp );
+				if( result )
+					return result;
+		}
+		sd_attrs_to_i_attrs( flags, inode );
+		REISERFS_I(inode) -> i_attrs = flags;
+		inode->i_ctime = CURRENT_TIME;
+		mark_inode_dirty(inode);
+		return 0;
+	}
+	case REISERFS_IOC_GETVERSION:
+		return put_user(inode->i_generation, (int *) arg);
+	case REISERFS_IOC_SETVERSION:
+		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+			return -EPERM;
+		if (IS_RDONLY(inode))
+			return -EROFS;
+		if (get_user(inode->i_generation, (int *) arg))
+			return -EFAULT;	
+		inode->i_ctime = CURRENT_TIME;
+		mark_inode_dirty(inode);
+		return 0;
+	default:
 		return -ENOTTY;
 	}
 }
@@ -32,7 +85,7 @@
 /*
 ** reiserfs_unpack
 ** Function try to convert tail from direct item into indirect.
-** It set up nopack attribute in the inode.u.reiserfs_i.nopack
+** It set up nopack attribute in the REISERFS_I(inode)->nopack
 */
 int reiserfs_unpack (struct inode * inode, struct file * filp)
 {
@@ -43,7 +96,8 @@
     unsigned long blocksize = inode->i_sb->s_blocksize ;
     	
     if (inode->i_size == 0) {
-        return -EINVAL ;
+        REISERFS_I(inode)->i_flags |= i_nopack_mask;
+        return 0 ;
     }
     /* ioctl already done */
     if (REISERFS_I(inode)->i_flags & i_nopack_mask) {
diff -urN linux-2.5.69-bk18/fs/reiserfs/procfs.c linux-2.5.69-bk19/fs/reiserfs/procfs.c
--- linux-2.5.69-bk18/fs/reiserfs/procfs.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/fs/reiserfs/procfs.c	2003-05-26 04:41:42.000000000 -0700
@@ -350,6 +350,7 @@
 	struct reiserfs_sb_info *sb_info;
 	struct reiserfs_super_block *rs;
 	int hash_code;
+	__u32 flags;
 	int len = 0;
     
 	sb = procinfo_prologue((int)data);
@@ -358,6 +359,7 @@
 	sb_info = REISERFS_SB(sb);
 	rs = sb_info -> s_rs;
 	hash_code = DFL( s_hash_function_code );
+	flags = DJF( s_flags );
 
 	len += sprintf( &buffer[ len ], 
 			"block_count: \t%i\n"
@@ -373,6 +375,7 @@
 			"tree_height: \t%i\n"
 			"bmap_nr: \t%i\n"
 			"version: \t%i\n"
+			"flags: \t%x[%s]\n"
 			"reserved_for_journal: \t%i\n",
 
 			DFL( s_block_count ),
@@ -391,6 +394,9 @@
 			DF( s_tree_height ),
 			DF( s_bmap_nr ),
 			DF( s_version ),
+			flags,
+			( flags & reiserfs_attrs_cleared )
+			? "attrs_cleared" : "",
 			DF (s_reserved_for_journal));
 
 	procinfo_epilogue( sb );
diff -urN linux-2.5.69-bk18/fs/reiserfs/super.c linux-2.5.69-bk19/fs/reiserfs/super.c
--- linux-2.5.69-bk18/fs/reiserfs/super.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/reiserfs/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -440,7 +440,7 @@
 {
 	reiserfs_inode_cachep = kmem_cache_create("reiser_inode_cache",
 					     sizeof(struct reiserfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (reiserfs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -708,6 +708,24 @@
     return 1;
 }
 
+static void handle_attrs( struct super_block *s )
+{
+	struct reiserfs_super_block * rs;
+
+	if( reiserfs_attrs( s ) ) {
+		rs = SB_DISK_SUPER_BLOCK (s);
+		if( old_format_only(s) ) {
+			reiserfs_warning( "reiserfs: cannot support attributes on 3.5.x disk format\n" );
+			REISERFS_SB(s) -> s_mount_opt &= ~ ( 1 << REISERFS_ATTRS );
+			return;
+		}
+		if( !( le32_to_cpu( rs -> s_flags ) & reiserfs_attrs_cleared ) ) {
+				reiserfs_warning( "reiserfs: cannot support attributes until flag is set in super-block\n" );
+				REISERFS_SB(s) -> s_mount_opt &= ~ ( 1 << REISERFS_ATTRS );
+		}
+	}
+}
+
 static int reiserfs_remount (struct super_block * s, int * mount_flags, char * arg)
 {
   struct reiserfs_super_block * rs;
@@ -720,6 +738,8 @@
   if (!reiserfs_parse_options(s, arg, &mount_options, &blocks, NULL))
     return -EINVAL;
   
+  handle_attrs( s );
+
   if(blocks) {
     int rc = reiserfs_resize(s, blocks);
     if (rc != 0)
@@ -1319,6 +1339,8 @@
     // mark hash in super block: it could be unset. overwrite should be ok
     set_sb_hash_function_code( rs, function2code(sbi->s_hash_function ) );
 
+    handle_attrs( s );
+
     reiserfs_proc_info_init( s );
     reiserfs_proc_register( s, "version", reiserfs_version_in_proc );
     reiserfs_proc_register( s, "super", reiserfs_super_in_proc );
@@ -1373,12 +1395,10 @@
 }
 
 static struct super_block*
-get_super_block (struct file_system_type *fs_type,
-		 int                      flags,
-		 char                    *dev_name,
-		 void                    *data)
+get_super_block (struct file_system_type *fs_type, int flags,
+		 const char *dev_name, void *data)
 {
-	return get_sb_bdev (fs_type, flags, dev_name, data, reiserfs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super);
 }
 
 static int __init
diff -urN linux-2.5.69-bk18/fs/romfs/inode.c linux-2.5.69-bk19/fs/romfs/inode.c
--- linux-2.5.69-bk18/fs/romfs/inode.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/fs/romfs/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -578,7 +578,7 @@
 {
 	romfs_inode_cachep = kmem_cache_create("romfs_inode_cache",
 					     sizeof(struct romfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (romfs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -599,7 +599,7 @@
 };
 
 static struct super_block *romfs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/smbfs/inode.c linux-2.5.69-bk19/fs/smbfs/inode.c
--- linux-2.5.69-bk18/fs/smbfs/inode.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/fs/smbfs/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -79,7 +79,7 @@
 {
 	smb_inode_cachep = kmem_cache_create("smb_inode_cache",
 					     sizeof(struct smb_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (smb_inode_cachep == NULL)
 		return -ENOMEM;
@@ -386,11 +386,11 @@
 			mnt->dir_mode = (value & S_IRWXUGO) | S_IFDIR;
 			break;
 		case 'i':
-			strncpy(mnt->codepage.local_name, optarg, 
+			strlcpy(mnt->codepage.local_name, optarg, 
 				SMB_NLS_MAXNAMELEN);
 			break;
 		case 'c':
-			strncpy(mnt->codepage.remote_name, optarg,
+			strlcpy(mnt->codepage.remote_name, optarg,
 				SMB_NLS_MAXNAMELEN);
 			break;
 		case 't':
@@ -535,9 +535,9 @@
 	mnt = server->mnt;
 
 	memset(mnt, 0, sizeof(struct smb_mount_data_kernel));
-	strncpy(mnt->codepage.local_name, CONFIG_NLS_DEFAULT,
+	strlcpy(mnt->codepage.local_name, CONFIG_NLS_DEFAULT,
 		SMB_NLS_MAXNAMELEN);
-	strncpy(mnt->codepage.remote_name, SMB_NLS_REMOTE,
+	strlcpy(mnt->codepage.remote_name, SMB_NLS_REMOTE,
 		SMB_NLS_MAXNAMELEN);
 
 	mnt->ttl = SMB_TTL_DEFAULT;
@@ -759,7 +759,7 @@
 #endif
 
 static struct super_block *smb_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_nodev(fs_type, flags, data, smb_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/super.c linux-2.5.69-bk19/fs/super.c
--- linux-2.5.69-bk18/fs/super.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -259,9 +259,6 @@
 	return s;
 }
 
-struct vfsmount *alloc_vfsmnt(char *name);
-void free_vfsmnt(struct vfsmount *mnt);
-
 void drop_super(struct super_block *sb)
 {
 	up_read(&sb->s_umount);
@@ -558,7 +555,7 @@
 }
 
 struct super_block *get_sb_bdev(struct file_system_type *fs_type,
-	int flags, char *dev_name, void * data,
+	int flags, const char *dev_name, void *data,
 	int (*fill_super)(struct super_block *, void *, int))
 {
 	struct block_device *bdev;
@@ -663,7 +660,7 @@
 }
 
 struct vfsmount *
-do_kern_mount(const char *fstype, int flags, char *name, void *data)
+do_kern_mount(const char *fstype, int flags, const char *name, void *data)
 {
 	struct file_system_type *type = get_fs_type(fstype);
 	struct super_block *sb = ERR_PTR(-ENOMEM);
@@ -702,5 +699,5 @@
 
 struct vfsmount *kern_mount(struct file_system_type *type)
 {
-	return do_kern_mount(type->name, 0, (char *)type->name, NULL);
+	return do_kern_mount(type->name, 0, type->name, NULL);
 }
diff -urN linux-2.5.69-bk18/fs/sysfs/mount.c linux-2.5.69-bk19/fs/sysfs/mount.c
--- linux-2.5.69-bk18/fs/sysfs/mount.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/fs/sysfs/mount.c	2003-05-26 04:41:42.000000000 -0700
@@ -55,7 +55,7 @@
 }
 
 static struct super_block *sysfs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_single(fs_type, flags, data, sysfs_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/sysv/inode.c linux-2.5.69-bk19/fs/sysv/inode.c
--- linux-2.5.69-bk18/fs/sysv/inode.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk19/fs/sysv/inode.c	2003-05-26 04:41:42.000000000 -0700
@@ -328,7 +328,8 @@
 {
 	sysv_inode_cachep = kmem_cache_create("sysv_inode_cache",
 			sizeof(struct sysv_inode_info), 0,
-			SLAB_HWCACHE_ALIGN, init_once, NULL);
+			SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, 
+			init_once, NULL);
 	if (!sysv_inode_cachep)
 		return -ENOMEM;
 	return 0;
diff -urN linux-2.5.69-bk18/fs/sysv/super.c linux-2.5.69-bk19/fs/sysv/super.c
--- linux-2.5.69-bk18/fs/sysv/super.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/fs/sysv/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -497,13 +497,13 @@
 /* Every kernel module contains stuff like this. */
 
 static struct super_block *sysv_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, sysv_fill_super);
 }
 
 static struct super_block *v7_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, v7_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/udf/super.c linux-2.5.69-bk19/fs/udf/super.c
--- linux-2.5.69-bk18/fs/udf/super.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/fs/udf/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -99,7 +99,7 @@
 
 /* UDF filesystem type */
 static struct super_block *udf_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, udf_fill_super);
 }
@@ -141,7 +141,7 @@
 {
 	udf_inode_cachep = kmem_cache_create("udf_inode_cache",
 					     sizeof(struct udf_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (udf_inode_cachep == NULL)
 		return -ENOMEM;
diff -urN linux-2.5.69-bk18/fs/ufs/super.c linux-2.5.69-bk19/fs/ufs/super.c
--- linux-2.5.69-bk18/fs/ufs/super.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/fs/ufs/super.c	2003-05-26 04:41:42.000000000 -0700
@@ -1029,7 +1029,7 @@
 {
 	ufs_inode_cachep = kmem_cache_create("ufs_inode_cache",
 					     sizeof(struct ufs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (ufs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -1055,7 +1055,7 @@
 };
 
 static struct super_block *ufs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, ufs_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/vfat/vfatfs_syms.c linux-2.5.69-bk19/fs/vfat/vfatfs_syms.c
--- linux-2.5.69-bk18/fs/vfat/vfatfs_syms.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/fs/vfat/vfatfs_syms.c	2003-05-26 04:41:42.000000000 -0700
@@ -12,7 +12,7 @@
 #include <linux/msdos_fs.h>
 
 static struct super_block *vfat_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super);
 }
diff -urN linux-2.5.69-bk18/fs/xfs/linux/xfs_super.c linux-2.5.69-bk19/fs/xfs/linux/xfs_super.c
--- linux-2.5.69-bk18/fs/xfs/linux/xfs_super.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/fs/xfs/linux/xfs_super.c	2003-05-26 04:41:42.000000000 -0700
@@ -329,7 +329,8 @@
 init_inodecache( void )
 {
 	linvfs_inode_cachep = kmem_cache_create("linvfs_icache",
-				sizeof(vnode_t), 0, SLAB_HWCACHE_ALIGN,
+				sizeof(vnode_t), 0, 
+				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 				init_once, NULL);
 
 	if (linvfs_inode_cachep == NULL)
@@ -746,7 +747,7 @@
 linvfs_get_sb(
 	struct file_system_type	*fs_type,
 	int			flags,
-	char			*dev_name,
+	const char		*dev_name,
 	void			*data)
 {
 	return get_sb_bdev(fs_type, flags, dev_name, data, linvfs_fill_super);
diff -urN linux-2.5.69-bk18/include/acpi/actypes.h linux-2.5.69-bk19/include/acpi/actypes.h
--- linux-2.5.69-bk18/include/acpi/actypes.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/acpi/actypes.h	2003-05-26 04:41:42.000000000 -0700
@@ -51,10 +51,10 @@
 /*
  * Data type ranges
  */
-#define ACPI_UINT8_MAX                  (UINT8)  0xFF
-#define ACPI_UINT16_MAX                 (UINT16) 0xFFFF
-#define ACPI_UINT32_MAX                 (UINT32) 0xFFFFFFFF
-#define ACPI_UINT64_MAX                 (UINT64) 0xFFFFFFFFFFFFFFFF
+#define ACPI_UINT8_MAX                  (~((UINT8)  0))
+#define ACPI_UINT16_MAX                 (~((UINT16) 0))
+#define ACPI_UINT32_MAX                 (~((UINT32) 0))
+#define ACPI_UINT64_MAX                 (~((UINT64) 0))
 #define ACPI_ASCII_MAX                  0x7F
 
 
@@ -313,7 +313,11 @@
 typedef u64                                     acpi_integer;
 #define ACPI_INTEGER_MAX                ACPI_UINT64_MAX
 #define ACPI_INTEGER_BIT_SIZE           64
-#define ACPI_MAX_BCD_VALUE              9999999999999999
+#if ACPI_MACHINE_WIDTH == 64
+#define ACPI_MAX_BCD_VALUE              9999999999999999UL
+#else
+#define ACPI_MAX_BCD_VALUE              9999999999999999ULL
+#endif
 #define ACPI_MAX_BCD_DIGITS             16
 #define ACPI_MAX_DECIMAL_DIGITS         19
 
diff -urN linux-2.5.69-bk18/include/asm-arm/tlb.h linux-2.5.69-bk19/include/asm-arm/tlb.h
--- linux-2.5.69-bk18/include/asm-arm/tlb.h	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-arm/tlb.h	2003-05-26 04:41:42.000000000 -0700
@@ -33,13 +33,13 @@
 	unsigned int		avoided_flushes;
 };
 
-extern struct mmu_gather mmu_gathers[NR_CPUS];
+DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 static inline struct mmu_gather *
 tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
 {
 	int cpu = smp_processor_id();
-	struct mmu_gather *tlb = &mmu_gathers[cpu];
+	struct mmu_gather *tlb = &per_cpu(mmu_gathers, cpu);
 
 	tlb->mm = mm;
 	tlb->freed = 0;
diff -urN linux-2.5.69-bk18/include/asm-generic/tlb.h linux-2.5.69-bk19/include/asm-generic/tlb.h
--- linux-2.5.69-bk18/include/asm-generic/tlb.h	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-generic/tlb.h	2003-05-26 04:41:42.000000000 -0700
@@ -44,7 +44,7 @@
 };
 
 /* Users of the generic TLB shootdown code must declare this storage space. */
-extern struct mmu_gather	mmu_gathers[NR_CPUS];
+DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 /* tlb_gather_mmu
  *	Return a pointer to an initialized struct mmu_gather.
@@ -52,7 +52,7 @@
 static inline struct mmu_gather *
 tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
 {
-	struct mmu_gather *tlb = &mmu_gathers[smp_processor_id()];
+	struct mmu_gather *tlb = &per_cpu(mmu_gathers, smp_processor_id());
 
 	tlb->mm = mm;
 
diff -urN linux-2.5.69-bk18/include/asm-i386/mach-bigsmp/mach_apic.h linux-2.5.69-bk19/include/asm-i386/mach-bigsmp/mach_apic.h
--- linux-2.5.69-bk18/include/asm-i386/mach-bigsmp/mach_apic.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-i386/mach-bigsmp/mach_apic.h	2003-05-26 04:41:42.000000000 -0700
@@ -1,5 +1,6 @@
 #ifndef __ASM_MACH_APIC_H
 #define __ASM_MACH_APIC_H
+#include <asm/smp.h>
 
 #define SEQUENTIAL_APICID
 #ifdef SEQUENTIAL_APICID
@@ -40,18 +41,10 @@
 
 #define apicid_cluster(apicid) (apicid & 0xF0)
 
-static inline unsigned get_apic_id(unsigned long x) 
-{ 
-	return (((x)>>24)&0x0F);
-} 
-
-#define		GET_APIC_ID(x)	get_apic_id(x)
-
 static inline unsigned long calculate_ldr(unsigned long old)
 {
 	unsigned long id;
-	id = xapic_phys_to_log_apicid(
-			GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR)));
+	id = xapic_phys_to_log_apicid(hard_smp_processor_id());
 	return ((old & ~APIC_LDR_MASK) | SET_APIC_LOGICAL_ID(id));
 }
 
@@ -135,8 +128,6 @@
 	return (1);
 }
 
-#define		APIC_ID_MASK		(0x0F<<24)
-
 static inline unsigned int cpu_mask_to_apicid (unsigned long cpumask)
 {
 	int num_bits_set;
diff -urN linux-2.5.69-bk18/include/asm-i386/mach-bigsmp/mach_apicdef.h linux-2.5.69-bk19/include/asm-i386/mach-bigsmp/mach_apicdef.h
--- linux-2.5.69-bk18/include/asm-i386/mach-bigsmp/mach_apicdef.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/include/asm-i386/mach-bigsmp/mach_apicdef.h	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,13 @@
+#ifndef __ASM_MACH_APICDEF_H
+#define __ASM_MACH_APICDEF_H
+
+#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
diff -urN linux-2.5.69-bk18/include/asm-i386/mach-default/mach_apic.h linux-2.5.69-bk19/include/asm-i386/mach-default/mach_apic.h
--- linux-2.5.69-bk18/include/asm-i386/mach-default/mach_apic.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-i386/mach-default/mach_apic.h	2003-05-26 04:41:42.000000000 -0700
@@ -1,6 +1,8 @@
 #ifndef __ASM_MACH_APIC_H
 #define __ASM_MACH_APIC_H
 
+#include <mach_apicdef.h>
+
 #define APIC_DFR_VALUE	(APIC_DFR_FLAT)
 
 static inline unsigned long target_cpus(void)
@@ -105,15 +107,6 @@
 	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)), 
diff -urN linux-2.5.69-bk18/include/asm-i386/mach-default/mach_apicdef.h linux-2.5.69-bk19/include/asm-i386/mach-default/mach_apicdef.h
--- linux-2.5.69-bk18/include/asm-i386/mach-default/mach_apicdef.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/include/asm-i386/mach-default/mach_apicdef.h	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,13 @@
+#ifndef __ASM_MACH_APICDEF_H
+#define __ASM_MACH_APICDEF_H
+
+#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)
+
+#endif
diff -urN linux-2.5.69-bk18/include/asm-i386/mach-numaq/mach_apic.h linux-2.5.69-bk19/include/asm-i386/mach-numaq/mach_apic.h
--- linux-2.5.69-bk18/include/asm-i386/mach-numaq/mach_apic.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-i386/mach-numaq/mach_apic.h	2003-05-26 04:41:42.000000000 -0700
@@ -107,15 +107,6 @@
 	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)
-
 static inline unsigned int cpu_mask_to_apicid (unsigned long cpumask)
 {
 	int num_bits_set;
diff -urN linux-2.5.69-bk18/include/asm-i386/mach-numaq/mach_apicdef.h linux-2.5.69-bk19/include/asm-i386/mach-numaq/mach_apicdef.h
--- linux-2.5.69-bk18/include/asm-i386/mach-numaq/mach_apicdef.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/include/asm-i386/mach-numaq/mach_apicdef.h	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,14 @@
+#ifndef __ASM_MACH_APICDEF_H
+#define __ASM_MACH_APICDEF_H
+
+
+#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
diff -urN linux-2.5.69-bk18/include/asm-i386/mach-summit/mach_apic.h linux-2.5.69-bk19/include/asm-i386/mach-summit/mach_apic.h
--- linux-2.5.69-bk18/include/asm-i386/mach-summit/mach_apic.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-i386/mach-summit/mach_apic.h	2003-05-26 04:41:42.000000000 -0700
@@ -2,6 +2,7 @@
 #define __ASM_MACH_APIC_H
 
 #include <linux/config.h>
+#include <asm/smp.h>
 
 #ifdef CONFIG_X86_GENERICARCH
 #define x86_summit 1	/* must be an constant expressiona for generic arch */
@@ -48,20 +49,12 @@
 
 extern u8 bios_cpu_apicid[];
 
-static inline unsigned get_apic_id(unsigned long x) 
-{ 
-	return (((x)>>24)&0xFF);
-} 
-
-#define		GET_APIC_ID(x)	get_apic_id(x)
-
 static inline void init_apic_ldr(void)
 {
 	unsigned long val, id;
 
 	if (x86_summit)
-		id = xapic_phys_to_log_apicid(
-			GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID)));
+		id = xapic_phys_to_log_apicid(hard_smp_processor_id());
 	else
 		id = 1UL << smp_processor_id();
 	apic_write_around(APIC_DFR, APIC_DFR_VALUE);
@@ -143,8 +136,6 @@
 		return test_bit(boot_cpu_physical_apicid, &phys_cpu_present_map);
 }
 
-#define		APIC_ID_MASK		(0xFF<<24)
-
 static inline unsigned int cpu_mask_to_apicid (unsigned long cpumask)
 {
 	int num_bits_set;
diff -urN linux-2.5.69-bk18/include/asm-i386/mach-summit/mach_apicdef.h linux-2.5.69-bk19/include/asm-i386/mach-summit/mach_apicdef.h
--- linux-2.5.69-bk18/include/asm-i386/mach-summit/mach_apicdef.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/include/asm-i386/mach-summit/mach_apicdef.h	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,13 @@
+#ifndef __ASM_MACH_APICDEF_H
+#define __ASM_MACH_APICDEF_H
+
+#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
diff -urN linux-2.5.69-bk18/include/asm-i386/mach-visws/mach_apic.h linux-2.5.69-bk19/include/asm-i386/mach-visws/mach_apic.h
--- linux-2.5.69-bk18/include/asm-i386/mach-visws/mach_apic.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-i386/mach-visws/mach_apic.h	2003-05-26 04:41:42.000000000 -0700
@@ -19,14 +19,6 @@
 #define check_apicid_used(bitmap, apicid) (bitmap & (1 << apicid))
 #define check_apicid_present(bit) (phys_cpu_present_map & (1 << bit))
 
-#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)), 
diff -urN linux-2.5.69-bk18/include/asm-i386/mach-visws/mach_apicdef.h linux-2.5.69-bk19/include/asm-i386/mach-visws/mach_apicdef.h
--- linux-2.5.69-bk18/include/asm-i386/mach-visws/mach_apicdef.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/include/asm-i386/mach-visws/mach_apicdef.h	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,12 @@
+#ifndef __ASM_MACH_APICDEF_H
+#define __ASM_MACH_APICDEF_H
+
+#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)
+
+#endif
diff -urN linux-2.5.69-bk18/include/asm-i386/smp.h linux-2.5.69-bk19/include/asm-i386/smp.h
--- linux-2.5.69-bk18/include/asm-i386/smp.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-i386/smp.h	2003-05-26 04:41:42.000000000 -0700
@@ -91,7 +91,7 @@
 #ifdef APIC_DEFINITION
 extern int hard_smp_processor_id(void);
 #else
-#include <mach_apic.h>
+#include <mach_apicdef.h>
 static inline int hard_smp_processor_id(void)
 {
 	/* we don't want to mark this access volatile - bad code generation */
diff -urN linux-2.5.69-bk18/include/asm-m68k/atari_stdma.h linux-2.5.69-bk19/include/asm-m68k/atari_stdma.h
--- linux-2.5.69-bk18/include/asm-m68k/atari_stdma.h	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68k/atari_stdma.h	2003-05-26 04:41:42.000000000 -0700
@@ -8,7 +8,8 @@
 
 /***************************** Prototypes *****************************/
 
-void stdma_lock(void (*handler)(int, void *, struct pt_regs *), void *data); 
+void stdma_lock(irqreturn_t (*handler)(int, void *, struct pt_regs *),
+		void *data);
 void stdma_release( void );
 int stdma_others_waiting( void );
 int stdma_islocked( void );
diff -urN linux-2.5.69-bk18/include/asm-m68k/hdreg.h linux-2.5.69-bk19/include/asm-m68k/hdreg.h
--- linux-2.5.69-bk18/include/asm-m68k/hdreg.h	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68k/hdreg.h	2003-05-26 04:41:42.000000000 -0700
@@ -7,7 +7,5 @@
 #ifndef _M68K_HDREG_H
 #define _M68K_HDREG_H
 
-typedef unsigned int   q40ide_ioreg_t;
-typedef unsigned char * ide_ioreg_t;
 
 #endif /* _M68K_HDREG_H */
diff -urN linux-2.5.69-bk18/include/asm-m68k/ide.h linux-2.5.69-bk19/include/asm-m68k/ide.h
--- linux-2.5.69-bk18/include/asm-m68k/ide.h	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68k/ide.h	2003-05-26 04:41:42.000000000 -0700
@@ -51,12 +51,12 @@
 #endif
 
 
-static __inline__ int ide_default_irq(ide_ioreg_t base)
+static __inline__ int ide_default_irq(unsigned long base)
 {
 	  return 0;
 }
 
-static __inline__ ide_ioreg_t ide_default_io_base(int index)
+static __inline__ unsigned long ide_default_io_base(int index)
 {
           return 0;
 }
@@ -66,7 +66,9 @@
  * Set up a hw structure for a specified data port, control port and IRQ.
  * This should follow whatever the default interface uses.
  */
-static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw,
+					   unsigned long data_port,
+					   unsigned long ctrl_port, int *irq)
 {
 	if (data_port || ctrl_port)
 		printk("ide_init_hwif_ports: must not be called\n");
@@ -80,72 +82,64 @@
 {
 }
 
-#undef SUPPORT_SLOW_DATA_PORTS
-#define SUPPORT_SLOW_DATA_PORTS 0
-
-/* this definition is used only on startup .. */
-#undef HD_DATA
-#define HD_DATA NULL
-
-
-/* get rid of defs from io.h - ide has its private and conflicting versions */
+/*
+ * Get rid of defs from io.h - ide has its private and conflicting versions
+ * Since so far no single m68k platform uses ISA/PCI I/O space for IDE, we
+ * always use the `raw' MMIO versions
+ */
 #undef inb
 #undef inw
+#undef insw
+#undef inl
+#undef insl
 #undef outb
 #undef outw
-#undef inb_p
-#undef outb_p
-#undef insw
 #undef outsw
-#undef insw_swapw
-#undef outsw_swapw
-
-/* 
- * define IO method and translation,
- * so far only Q40 has ide-if on ISA 
-*/
-#ifndef CONFIG_Q40
-
-#define ADDR_TRANS_B(_addr_) (_addr_)
-#define ADDR_TRANS_W(_addr_) (_addr_)
-
-#else
-
-#define ADDR_TRANS_B(_addr_) (MACH_IS_Q40 ? ((unsigned char *)Q40_ISA_IO_B(_addr_)) : (_addr_))
-#define ADDR_TRANS_W(_addr_) (MACH_IS_Q40 ? ((unsigned char *)Q40_ISA_IO_W(_addr_)) : (_addr_))
-#endif
-
-#define inb(p)     in_8(ADDR_TRANS_B(p))
-#define inb_p(p)     in_8(ADDR_TRANS_B(p))
-#define inw(p)     in_be16(ADDR_TRANS_W(p))
-#define inw_p(p)     in_be16(ADDR_TRANS_W(p))
-#define outb(v,p)  out_8(ADDR_TRANS_B(p),v)
-#define outb_p(v,p)  out_8(ADDR_TRANS_B(p),v)
-#define outw(v,p)  out_be16(ADDR_TRANS_W(p),v)
-
-#define insw(port, buf, nr) raw_insw(ADDR_TRANS_W(port), buf, nr)
-#define outsw(port, buf, nr) raw_outsw(ADDR_TRANS_W(port), buf, nr)
-
-#define insl(data_reg, buffer, wcount) insw(data_reg, buffer, (wcount)<<1)
-#define outsl(data_reg, buffer, wcount) outsw(data_reg, buffer, (wcount)<<1)
-
-
+#undef outl
+#undef outsl
+#undef readb
+#undef readw
+#undef readl
+#undef writeb
+#undef writew
+#undef writel
+
+#define inb				in_8
+#define inw				in_be16
+#define insw(port, addr, n)		raw_insw((u16 *)port, addr, n)
+#define inl				in_be32
+#define insl(port, addr, n)		raw_insl((u32 *)port, addr, n)
+#define outb(val, port)			out_8(port, val)
+#define outw(val, port)			out_be16(port, val)
+#define outsw(port, addr, n)		raw_outsw((u16 *)port, addr, n)
+#define outl(val, port)			out_be32(port, val)
+#define outsl(port, addr, n)		raw_outsl((u32 *)port, addr, n)
+#define readb				in_8
+#define readw				in_be16
+#define __ide_mm_insw(port, addr, n)	raw_insw((u16 *)port, addr, n)
+#define readl				in_be32
+#define __ide_mm_insl(port, addr, n)	raw_insl((u32 *)port, addr, n)
+#define writeb(val, port)		out_8(port, val)
+#define writew(val, port)		out_be16(port, val)
+#define __ide_mm_outsw(port, addr, n)	raw_outsw((u16 *)port, addr, n)
+#define writel(val, port)		out_be32(port, val)
+#define __ide_mm_outsl(port, addr, n)	raw_outsl((u32 *)port, addr, n)
 #if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
+#define insw_swapw(port, addr, n)	raw_insw_swapw((u16 *)port, addr, n)
+#define outsw_swapw(port, addr, n)	raw_outsw_swapw((u16 *)port, addr, n)
+#endif
 
-#define insl_swapw(data_reg, buffer, wcount) \
-    insw_swapw(data_reg, buffer, (wcount)<<1)
-#define outsl_swapw(data_reg, buffer, wcount) \
-    outsw_swapw(data_reg, buffer, (wcount)<<1)
-
-#define insw_swapw(port, buf, nr) raw_insw_swapw(ADDR_TRANS_W(port), buf, nr)
-#define outsw_swapw(port, buf, nr) raw_outsw_swapw(ADDR_TRANS_W(port),buf,nr)
-
-#endif /* CONFIG_ATARI || CONFIG_Q40 */
 
-#define ATA_ARCH_ACK_INTR
+/* Q40 and Atari have byteswapped IDE busses and since many interesting
+ * values in the identification string are text, chars and words they
+ * happened to be almost correct without swapping.. However *_capacity
+ * is needed for drives over 8 GB. RZ */
+#if defined(CONFIG_Q40) || defined(CONFIG_ATARI)
+#define M68K_IDE_SWAPW  (MACH_IS_Q40 || MACH_IS_ATARI)
+#endif
 
 #ifdef CONFIG_BLK_DEV_FALCON_IDE
-#define ATA_ARCH_LOCK
+#define IDE_ARCH_LOCK
 
 extern int falconide_intr_lock;
 
@@ -161,7 +155,8 @@
 	}
 }
 
-static __inline__ void ide_get_lock(void (*handler)(int, void *, struct pt_regs *), void *data)
+static __inline__ void
+ide_get_lock(irqreturn_t (*handler)(int, void *, struct pt_regs *), void *data)
 {
 	if (MACH_IS_ATARI) {
 		if (falconide_intr_lock == 0) {
@@ -173,5 +168,9 @@
 	}
 }
 #endif /* CONFIG_BLK_DEV_FALCON_IDE */
+
+#define IDE_ARCH_ACK_INTR
+#define ide_ack_intr(hwif)	((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1)
+
 #endif /* __KERNEL__ */
 #endif /* _M68K_IDE_H */
diff -urN linux-2.5.69-bk18/include/asm-m68k/io.h linux-2.5.69-bk19/include/asm-m68k/io.h
--- linux-2.5.69-bk18/include/asm-m68k/io.h	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68k/io.h	2003-05-26 04:41:42.000000000 -0700
@@ -120,66 +120,66 @@
  * be compiled in so the case statement will be optimised away
  */
 
-static inline unsigned long isa_itb(long addr)
+static inline unsigned char *isa_itb(long addr)
 {
   switch(ISA_TYPE)
     {
 #ifdef CONFIG_Q40
-    case Q40_ISA: return Q40_ISA_IO_B(addr);
+    case Q40_ISA: return (unsigned char *)Q40_ISA_IO_B(addr);
 #endif
 #ifdef CONFIG_GG2
-    case GG2_ISA: return GG2_ISA_IO_B(addr);
+    case GG2_ISA: return (unsigned char *)GG2_ISA_IO_B(addr);
 #endif
 #ifdef CONFIG_AMIGA_PCMCIA
-    case AG_ISA: return AG_ISA_IO_B(addr);
+    case AG_ISA: return (unsigned char *)AG_ISA_IO_B(addr);
 #endif
     default: return 0; /* avoid warnings, just in case */
     }
 }
-static inline unsigned long isa_itw(long addr)
+static inline unsigned short *isa_itw(long addr)
 {
   switch(ISA_TYPE)
     {
 #ifdef CONFIG_Q40
-    case Q40_ISA: return Q40_ISA_IO_W(addr);
+    case Q40_ISA: return (unsigned short *)Q40_ISA_IO_W(addr);
 #endif
 #ifdef CONFIG_GG2
-    case GG2_ISA: return GG2_ISA_IO_W(addr);
+    case GG2_ISA: return (unsigned short *)GG2_ISA_IO_W(addr);
 #endif
 #ifdef CONFIG_AMIGA_PCMCIA
-    case AG_ISA: return AG_ISA_IO_W(addr);
+    case AG_ISA: return (unsigned short *)AG_ISA_IO_W(addr);
 #endif
     default: return 0; /* avoid warnings, just in case */
     }
 }
-static inline unsigned long isa_mtb(long addr)
+static inline unsigned char *isa_mtb(long addr)
 {
   switch(ISA_TYPE)
     {
 #ifdef CONFIG_Q40
-    case Q40_ISA: return Q40_ISA_MEM_B(addr);
+    case Q40_ISA: return (unsigned char *)Q40_ISA_MEM_B(addr);
 #endif
 #ifdef CONFIG_GG2
-    case GG2_ISA: return GG2_ISA_MEM_B(addr);
+    case GG2_ISA: return (unsigned char *)GG2_ISA_MEM_B(addr);
 #endif
 #ifdef CONFIG_AMIGA_PCMCIA
-    case AG_ISA: return addr;
+    case AG_ISA: return (unsigned char *)addr;
 #endif
     default: return 0; /* avoid warnings, just in case */
     }
 }
-static inline unsigned long isa_mtw(long addr)
+static inline unsigned short *isa_mtw(long addr)
 {
   switch(ISA_TYPE)
     {
 #ifdef CONFIG_Q40
-    case Q40_ISA: return Q40_ISA_MEM_W(addr);
+    case Q40_ISA: return (unsigned short *)Q40_ISA_MEM_W(addr);
 #endif
 #ifdef CONFIG_GG2
-    case GG2_ISA: return GG2_ISA_MEM_W(addr);
+    case GG2_ISA: return (unsigned short *)GG2_ISA_MEM_W(addr);
 #endif
 #ifdef CONFIG_AMIGA_PCMCIA
-    case AG_ISA: return addr;
+    case AG_ISA: return (unsigned short *)addr;
 #endif
     default: return 0; /* avoid warnings, just in case */
     }
diff -urN linux-2.5.69-bk18/include/asm-m68k/irq.h linux-2.5.69-bk19/include/asm-m68k/irq.h
--- linux-2.5.69-bk18/include/asm-m68k/irq.h	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68k/irq.h	2003-05-26 04:41:42.000000000 -0700
@@ -2,6 +2,7 @@
 #define _M68K_IRQ_H_
 
 #include <linux/config.h>
+#include <linux/interrupt.h>
 
 /*
  * # of m68k interrupts
@@ -76,7 +77,7 @@
 struct pt_regs;
 
 extern int sys_request_irq(unsigned int, 
-	void (*)(int, void *, struct pt_regs *), 
+	irqreturn_t (*)(int, void *, struct pt_regs *), 
 	unsigned long, const char *, void *);
 extern void sys_free_irq(unsigned int, void *);
 
@@ -98,7 +99,7 @@
  * interrupt source (if it supports chaining).
  */
 typedef struct irq_node {
-	void		(*handler)(int, void *, struct pt_regs *);
+	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
 	unsigned long	flags;
 	void		*dev_id;
 	const char	*devname;
@@ -109,7 +110,7 @@
  * This structure has only 4 elements for speed reasons
  */
 typedef struct irq_handler {
-	void		(*handler)(int, void *, struct pt_regs *);
+	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
 	unsigned long	flags;
 	void		*dev_id;
 	const char	*devname;
diff -urN linux-2.5.69-bk18/include/asm-m68k/machdep.h linux-2.5.69-bk19/include/asm-m68k/machdep.h
--- linux-2.5.69-bk18/include/asm-m68k/machdep.h	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68k/machdep.h	2003-05-26 04:41:42.000000000 -0700
@@ -2,6 +2,7 @@
 #define _M68K_MACHDEP_H
 
 #include <linux/seq_file.h>
+#include <linux/interrupt.h>
 
 struct pt_regs;
 struct mktime;
@@ -9,17 +10,17 @@
 struct rtc_pll_info;
 struct buffer_head;
 
-extern void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *));
+extern void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *));
 /* machine dependent irq functions */
 extern void (*mach_init_IRQ) (void);
-extern void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
-extern int (*mach_request_irq) (unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+extern irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
+extern int (*mach_request_irq) (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
                                 unsigned long flags, const char *devname, void *dev_id);
 extern void (*mach_free_irq) (unsigned int irq, void *dev_id);
 extern void (*mach_get_model) (char *model);
 extern int (*mach_get_hardware_list) (char *buffer);
 extern int (*mach_get_irq_list) (struct seq_file *p, void *v);
-extern void (*mach_process_int) (int irq, struct pt_regs *fp);
+extern irqreturn_t (*mach_process_int) (int irq, struct pt_regs *fp);
 /* machine dependent timer functions */
 extern unsigned long (*mach_gettimeoffset)(void);
 extern int (*mach_hwclk)(int, struct rtc_time*);
diff -urN linux-2.5.69-bk18/include/asm-m68k/macintosh.h linux-2.5.69-bk19/include/asm-m68k/macintosh.h
--- linux-2.5.69-bk18/include/asm-m68k/macintosh.h	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68k/macintosh.h	2003-05-26 04:41:42.000000000 -0700
@@ -2,6 +2,7 @@
 #define __ASM_MACINTOSH_H
 
 #include <linux/seq_file.h>
+#include <linux/interrupt.h>
 
 /*
  *	Apple Macintoshisms
@@ -10,7 +11,7 @@
 extern void mac_reset(void);
 extern void mac_poweroff(void);
 extern void mac_init_IRQ(void);
-extern int mac_request_irq (unsigned int, void (*)(int, void *, 
+extern int mac_request_irq (unsigned int, irqreturn_t (*)(int, void *, 
 				struct pt_regs *),
 				unsigned long, const char *, void *);
 extern void mac_free_irq(unsigned int, void *);
diff -urN linux-2.5.69-bk18/include/asm-m68k/motorola_pgtable.h linux-2.5.69-bk19/include/asm-m68k/motorola_pgtable.h
--- linux-2.5.69-bk18/include/asm-m68k/motorola_pgtable.h	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68k/motorola_pgtable.h	2003-05-26 04:41:42.000000000 -0700
@@ -14,7 +14,7 @@
 #define _PAGE_SUPER	0x080	/* 68040 supervisor only */
 #define _PAGE_FAKE_SUPER 0x200	/* fake supervisor only on 680[23]0 */
 #define _PAGE_GLOBAL040	0x400	/* 68040 global bit, used for kva descs */
-#define _PAGE_COW	0x800	/* implemented in software */
+#define _PAGE_FILE	0x800	/* pagecache or swap? */
 #define _PAGE_NOCACHE030 0x040	/* 68030 no-cache mode */
 #define _PAGE_NOCACHE	0x060	/* 68040 cache mode, non-serialized */
 #define _PAGE_NOCACHE_S	0x040	/* 68040 no-cache mode, serialized */
@@ -159,6 +159,7 @@
 extern inline int pte_exec(pte_t pte)		{ return 1; }
 extern inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
 extern inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
 
 extern inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) |= _PAGE_RONLY; return pte; }
 extern inline pte_t pte_rdprotect(pte_t pte)	{ return pte; }
@@ -255,6 +256,25 @@
 	}
 }
 
+#define PTE_FILE_MAX_BITS	29
+
+static inline unsigned long pte_to_pgoff(pte_t pte)
+{
+	return ((pte.pte >> 12) << 7) + ((pte.pte >> 2) & 0x1ff);
+}
+
+static inline pte_t pgoff_to_pte(inline unsigned off)
+{
+	pte_t pte = { ((off >> 7) << 12) + ((off & 0x1ff) << 2) + _PAGE_FILE };
+	return pte;
+}
+
+/* Encode and de-code a swap entry (must be !pte_none(e) && !pte_present(e)) */
+#define __swp_type(x)		(((x).val >> 2) & 0x1ff)
+#define __swp_offset(x)		((x).val >> 12)
+#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 12) })
+#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x)	((pte_t) { (x).val })
 
 #endif	/* !__ASSEMBLY__ */
 #endif /* _MOTOROLA_PGTABLE_H */
diff -urN linux-2.5.69-bk18/include/asm-m68k/pgtable.h linux-2.5.69-bk19/include/asm-m68k/pgtable.h
--- linux-2.5.69-bk18/include/asm-m68k/pgtable.h	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68k/pgtable.h	2003-05-26 04:41:42.000000000 -0700
@@ -136,25 +136,6 @@
 {
 }
 
-#ifdef CONFIG_SUN3
-/* Macros to (de)construct the fake PTEs representing swap pages. */
-#define __swp_type(x)		((x).val & 0x7F)
-#define __swp_offset(x)		(((x).val) >> 7)
-#define __swp_entry(type,offset) ((swp_entry_t) { ((type) | ((offset) << 7)) })
-#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
-#define __swp_entry_to_pte(x)	((pte_t) { (x).val })
-
-#else
-
-/* Encode and de-code a swap entry (must be !pte_none(e) && !pte_present(e)) */
-#define __swp_type(x)		(((x).val >> 1) & 0xff)
-#define __swp_offset(x)		((x).val >> 10)
-#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 10) })
-#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
-#define __swp_entry_to_pte(x)	((pte_t) { (x).val })
-
-#endif /* CONFIG_SUN3 */
-
 #endif /* !__ASSEMBLY__ */
 
 #define kern_addr_valid(addr)	(1)
diff -urN linux-2.5.69-bk18/include/asm-m68k/raw_io.h linux-2.5.69-bk19/include/asm-m68k/raw_io.h
--- linux-2.5.69-bk18/include/asm-m68k/raw_io.h	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68k/raw_io.h	2003-05-26 04:41:42.000000000 -0700
@@ -52,208 +52,290 @@
 #define raw_outw(val,port) out_be16((port),(val))
 #define raw_outl(val,port) out_be32((port),(val))
 
-#define raw_insb(port, buf, len) ({	   \
-	volatile unsigned char *_port = (volatile unsigned char *) (port);   \
-        unsigned char *_buf =(unsigned char *)(buf);	   \
-        unsigned int  _i,_len=(unsigned int)(len);	   \
-        for(_i=0; _i< _len; _i++)  \
-           *_buf++=in_8(_port);      \
-  })
-
-#define raw_outsb(port, buf, len) ({	   \
-	volatile unsigned char *_port = (volatile unsigned char *) (port);   \
-        unsigned char *_buf =(unsigned char *)(buf);	   \
-        unsigned int  _i,_len=(unsigned int)(len);	   \
-        for( _i=0; _i< _len; _i++)  \
-           out_8(_port,*_buf++);      \
-  })
- 
-
-#define raw_insw(port, buf, nr) ({				\
-	volatile unsigned char *_port = (volatile unsigned char *) (port);	\
-	unsigned char *_buf = (unsigned char *)(buf);			\
-	unsigned int _nr = (unsigned int)(nr);					\
-	unsigned long _tmp;				\
-							\
-	if (_nr & 15) {					\
-		_tmp = (_nr & 15) - 1;			\
-		asm volatile (				\
-			"1: movew %2@,%0@+; dbra %1,1b"	\
-			: "=a" (_buf), "=d" (_tmp)	\
-			: "a" (_port), "0" (_buf),	\
-			  "1" (_tmp));			\
-	}						\
-	if (_nr >> 4) {					\
-		_tmp = (_nr >> 4) - 1;			\
-		asm volatile (				\
-			"1: "				\
-			"movew %2@,%0@+; "		\
-			"movew %2@,%0@+; "		\
-			"movew %2@,%0@+; "		\
-			"movew %2@,%0@+; "		\
-			"movew %2@,%0@+; "		\
-			"movew %2@,%0@+; "		\
-			"movew %2@,%0@+; "		\
-			"movew %2@,%0@+; "		\
-			"movew %2@,%0@+; "		\
-			"movew %2@,%0@+; "		\
-			"movew %2@,%0@+; "		\
-			"movew %2@,%0@+; "		\
-			"movew %2@,%0@+; "		\
-			"movew %2@,%0@+; "		\
-			"movew %2@,%0@+; "		\
-			"movew %2@,%0@+; "		\
-			"dbra %1,1b"			\
-			: "=a" (_buf), "=d" (_tmp)	\
-			: "a" (_port), "0" (_buf),	\
-			  "1" (_tmp));			\
-	}						\
-})
-
-#define raw_outsw(port, buf, nr) ({				\
-	volatile unsigned char *_port = (volatile unsigned char *) (port);	\
-	unsigned char *_buf = (unsigned char *)(buf);			\
-	unsigned int _nr = (unsigned int)(nr);					\
-	unsigned long _tmp;				\
-							\
-	if (_nr & 15) {					\
-		_tmp = (_nr & 15) - 1;			\
-		asm volatile (				\
-			"1: movew %0@+,%2@; dbra %1,1b"	\
-			: "=a" (_buf), "=d" (_tmp)	\
-			: "a" (_port), "0" (_buf),	\
-			  "1" (_tmp));			\
-	}						\
-	if (_nr >> 4) {					\
-		_tmp = (_nr >> 4) - 1;			\
-		asm volatile (				\
-			"1: "				\
-			"movew %0@+,%2@; "		\
-			"movew %0@+,%2@; "		\
-			"movew %0@+,%2@; "		\
-			"movew %0@+,%2@; "		\
-			"movew %0@+,%2@; "		\
-			"movew %0@+,%2@; "		\
-			"movew %0@+,%2@; "		\
-			"movew %0@+,%2@; "		\
-			"movew %0@+,%2@; "		\
-			"movew %0@+,%2@; "		\
-			"movew %0@+,%2@; "		\
-			"movew %0@+,%2@; "		\
-			"movew %0@+,%2@; "		\
-			"movew %0@+,%2@; "		\
-			"movew %0@+,%2@; "		\
-			"movew %0@+,%2@; "		\
-			"dbra %1,1b"	   		\
-			: "=a" (_buf), "=d" (_tmp)	\
-			: "a" (_port), "0" (_buf),	\
-			  "1" (_tmp));			\
-	}						\
-})
-
-
-#define raw_insw_swapw(port, buf, nr) \
-({  if ((nr) % 8) \
-	__asm__ __volatile__ \
-	       ("movel %0,%/a0; \
-		 movel %1,%/a1; \
-		 movel %2,%/d6; \
-		 subql #1,%/d6; \
-	       1:movew %/a0@,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a1@+; \
-		 dbra %/d6,1b"  \
-		:               \
-		: "g" (port), "g" (buf), "g" (nr) \
-		: "d0", "a0", "a1", "d6"); \
-    else \
-	__asm__ __volatile__ \
-	       ("movel %0,%/a0; \
-		 movel %1,%/a1; \
-		 movel %2,%/d6; \
-		 lsrl  #3,%/d6; \
-		 subql #1,%/d6; \
-	       1:movew %/a0@,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a1@+; \
-		 movew %/a0@,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a1@+; \
-		 movew %/a0@,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a1@+; \
-		 movew %/a0@,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a1@+; \
-		 movew %/a0@,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a1@+; \
-		 movew %/a0@,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a1@+; \
-		 movew %/a0@,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a1@+; \
-		 movew %/a0@,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a1@+; \
-		 dbra %/d6,1b"  \
-                :               \
-		: "g" (port), "g" (buf), "g" (nr) \
-		: "d0", "a0", "a1", "d6"); \
-})
-
-
-#define raw_outsw_swapw(port, buf, nr) \
-({  if ((nr) % 8) \
-	__asm__ __volatile__ \
-	       ("movel %0,%/a0; \
-		 movel %1,%/a1; \
-		 movel %2,%/d6; \
-		 subql #1,%/d6; \
-	       1:movew %/a1@+,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a0@; \
-		 dbra %/d6,1b"  \
-                :               \
-		: "g" (port), "g" (buf), "g" (nr) \
-		: "d0", "a0", "a1", "d6"); \
-    else \
-	__asm__ __volatile__ \
-	       ("movel %0,%/a0; \
-		 movel %1,%/a1; \
-		 movel %2,%/d6; \
-		 lsrl  #3,%/d6; \
-		 subql #1,%/d6; \
-	       1:movew %/a1@+,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a0@; \
-		 movew %/a1@+,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a0@; \
-		 movew %/a1@+,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a0@; \
-		 movew %/a1@+,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a0@; \
-		 movew %/a1@+,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a0@; \
-		 movew %/a1@+,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a0@; \
-		 movew %/a1@+,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a0@; \
-		 movew %/a1@+,%/d0; \
-		 rolw  #8,%/d0; \
-		 movew %/d0,%/a0@; \
-		 dbra %/d6,1b"  \
-                :               \
-		: "g" (port), "g" (buf), "g" (nr) \
-		: "d0", "a0", "a1", "d6"); \
-})
+static inline void raw_insb(volatile unsigned char *port, unsigned char *buf,
+			    unsigned int len)
+{
+	unsigned int i;
+
+        for (i = 0; i < len; i++)
+		*buf++ = in_8(port);
+}
+
+static inline void raw_outsb(volatile unsigned char *port,
+			     const unsigned char *buf, unsigned int len)
+{
+	unsigned int i;
+
+        for (i = 0; i < len; i++)
+		out_8(port, *buf++);
+}
+
+static inline void raw_insw(volatile unsigned short *port, unsigned short *buf,
+			    unsigned int nr)
+{
+	unsigned int tmp;
+
+	if (nr & 15) {
+		tmp = (nr & 15) - 1;
+		asm volatile (
+			"1: movew %2@,%0@+; dbra %1,1b"
+			: "=a" (buf), "=d" (tmp)
+			: "a" (port), "0" (buf),
+			  "1" (tmp));
+	}
+	if (nr >> 4) {
+		tmp = (nr >> 4) - 1;
+		asm volatile (
+			"1: "
+			"movew %2@,%0@+; "
+			"movew %2@,%0@+; "
+			"movew %2@,%0@+; "
+			"movew %2@,%0@+; "
+			"movew %2@,%0@+; "
+			"movew %2@,%0@+; "
+			"movew %2@,%0@+; "
+			"movew %2@,%0@+; "
+			"movew %2@,%0@+; "
+			"movew %2@,%0@+; "
+			"movew %2@,%0@+; "
+			"movew %2@,%0@+; "
+			"movew %2@,%0@+; "
+			"movew %2@,%0@+; "
+			"movew %2@,%0@+; "
+			"movew %2@,%0@+; "
+			"dbra %1,1b"
+			: "=a" (buf), "=d" (tmp)
+			: "a" (port), "0" (buf),
+			  "1" (tmp));
+	}
+}
+
+static inline void raw_outsw(volatile unsigned short *port,
+			     const unsigned short *buf, unsigned int nr)
+{
+	unsigned int tmp;
+
+	if (nr & 15) {
+		tmp = (nr & 15) - 1;
+		asm volatile (
+			"1: movew %0@+,%2@; dbra %1,1b"
+			: "=a" (buf), "=d" (tmp)
+			: "a" (port), "0" (buf),
+			  "1" (tmp));
+	}
+	if (nr >> 4) {
+		tmp = (nr >> 4) - 1;
+		asm volatile (
+			"1: "
+			"movew %0@+,%2@; "
+			"movew %0@+,%2@; "
+			"movew %0@+,%2@; "
+			"movew %0@+,%2@; "
+			"movew %0@+,%2@; "
+			"movew %0@+,%2@; "
+			"movew %0@+,%2@; "
+			"movew %0@+,%2@; "
+			"movew %0@+,%2@; "
+			"movew %0@+,%2@; "
+			"movew %0@+,%2@; "
+			"movew %0@+,%2@; "
+			"movew %0@+,%2@; "
+			"movew %0@+,%2@; "
+			"movew %0@+,%2@; "
+			"movew %0@+,%2@; "
+			"dbra %1,1b"
+			: "=a" (buf), "=d" (tmp)
+			: "a" (port), "0" (buf),
+			  "1" (tmp));
+	}
+}
+
+static inline void raw_insl(volatile unsigned int *port, unsigned int *buf,
+			    unsigned int nr)
+{
+	unsigned int tmp;
+
+	if (nr & 15) {
+		tmp = (nr & 15) - 1;
+		asm volatile (
+			"1: movel %2@,%0@+; dbra %1,1b"
+			: "=a" (buf), "=d" (tmp)
+			: "a" (port), "0" (buf),
+			  "1" (tmp));
+	}
+	if (nr >> 4) {
+		tmp = (nr >> 4) - 1;
+		asm volatile (
+			"1: "
+			"movel %2@,%0@+; "
+			"movel %2@,%0@+; "
+			"movel %2@,%0@+; "
+			"movel %2@,%0@+; "
+			"movel %2@,%0@+; "
+			"movel %2@,%0@+; "
+			"movel %2@,%0@+; "
+			"movel %2@,%0@+; "
+			"movel %2@,%0@+; "
+			"movel %2@,%0@+; "
+			"movel %2@,%0@+; "
+			"movel %2@,%0@+; "
+			"movel %2@,%0@+; "
+			"movel %2@,%0@+; "
+			"movel %2@,%0@+; "
+			"movel %2@,%0@+; "
+			"dbra %1,1b"
+			: "=a" (buf), "=d" (tmp)
+			: "a" (port), "0" (buf),
+			  "1" (tmp));
+	}
+}
+
+static inline void raw_outsl(volatile unsigned int *port,
+			     const unsigned int *buf, unsigned int nr)
+{
+	unsigned int tmp;
+
+	if (nr & 15) {
+		tmp = (nr & 15) - 1;
+		asm volatile (
+			"1: movel %0@+,%2@; dbra %1,1b"
+			: "=a" (buf), "=d" (tmp)
+			: "a" (port), "0" (buf),
+			  "1" (tmp));
+	}
+	if (nr >> 4) {
+		tmp = (nr >> 4) - 1;
+		asm volatile (
+			"1: "
+			"movel %0@+,%2@; "
+			"movel %0@+,%2@; "
+			"movel %0@+,%2@; "
+			"movel %0@+,%2@; "
+			"movel %0@+,%2@; "
+			"movel %0@+,%2@; "
+			"movel %0@+,%2@; "
+			"movel %0@+,%2@; "
+			"movel %0@+,%2@; "
+			"movel %0@+,%2@; "
+			"movel %0@+,%2@; "
+			"movel %0@+,%2@; "
+			"movel %0@+,%2@; "
+			"movel %0@+,%2@; "
+			"movel %0@+,%2@; "
+			"movel %0@+,%2@; "
+			"dbra %1,1b"
+			: "=a" (buf), "=d" (tmp)
+			: "a" (port), "0" (buf),
+			  "1" (tmp));
+	}
+}
+
+
+static inline void raw_insw_swapw(volatile unsigned short *port,
+				  unsigned short *buf, unsigned int nr)
+{
+    if ((nr) % 8)
+	__asm__ __volatile__
+	       ("\tmovel %0,%/a0\n\t"
+		"movel %1,%/a1\n\t"
+		"movel %2,%/d6\n\t"
+		"subql #1,%/d6\n"
+		"1:\tmovew %/a0@,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a1@+\n\t"
+		"dbra %/d6,1b"
+		:
+		: "g" (port), "g" (buf), "g" (nr)
+		: "d0", "a0", "a1", "d6");
+    else
+	__asm__ __volatile__
+	       ("movel %0,%/a0\n\t"
+		"movel %1,%/a1\n\t"
+		"movel %2,%/d6\n\t"
+		"lsrl  #3,%/d6\n\t"
+		"subql #1,%/d6\n"
+		"1:\tmovew %/a0@,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a1@+\n\t"
+		"movew %/a0@,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a1@+\n\t"
+		"movew %/a0@,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a1@+\n\t"
+		"movew %/a0@,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a1@+\n\t"
+		"movew %/a0@,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a1@+\n\t"
+		"movew %/a0@,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a1@+\n\t"
+		"movew %/a0@,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a1@+\n\t"
+		"movew %/a0@,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a1@+\n\t"
+		"dbra %/d6,1b"
+                :
+		: "g" (port), "g" (buf), "g" (nr)
+		: "d0", "a0", "a1", "d6");
+}
+
+static inline void raw_outsw_swapw(volatile unsigned short *port,
+				   const unsigned short *buf, unsigned int nr)
+{
+    if ((nr) % 8)
+	__asm__ __volatile__
+	       ("movel %0,%/a0\n\t"
+		"movel %1,%/a1\n\t"
+		"movel %2,%/d6\n\t"
+		"subql #1,%/d6\n"
+		"1:\tmovew %/a1@+,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a0@\n\t"
+		"dbra %/d6,1b"
+                :
+		: "g" (port), "g" (buf), "g" (nr)
+		: "d0", "a0", "a1", "d6");
+    else
+	__asm__ __volatile__
+	       ("movel %0,%/a0\n\t"
+		"movel %1,%/a1\n\t"
+		"movel %2,%/d6\n\t"
+		"lsrl  #3,%/d6\n\t"
+		"subql #1,%/d6\n"
+		"1:\tmovew %/a1@+,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a0@\n\t"
+		"movew %/a1@+,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a0@\n\t"
+		"movew %/a1@+,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a0@\n\t"
+		"movew %/a1@+,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a0@\n\t"
+		"movew %/a1@+,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a0@\n\t"
+		"movew %/a1@+,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a0@\n\t"
+		"movew %/a1@+,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a0@\n\t"
+		"movew %/a1@+,%/d0\n\t"
+		"rolw  #8,%/d0\n\t"
+		"movew %/d0,%/a0@\n\t"
+		"dbra %/d6,1b"
+                :
+		: "g" (port), "g" (buf), "g" (nr)
+		: "d0", "a0", "a1", "d6");
+}
 
 
 #endif /* __KERNEL__ */
diff -urN linux-2.5.69-bk18/include/asm-m68k/sun3_pgtable.h linux-2.5.69-bk19/include/asm-m68k/sun3_pgtable.h
--- linux-2.5.69-bk18/include/asm-m68k/sun3_pgtable.h	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68k/sun3_pgtable.h	2003-05-26 04:41:42.000000000 -0700
@@ -204,6 +204,12 @@
 #define pte_unmap(pte) kunmap(pte)
 #define pte_unmap_nested(pte) kunmap(pte)
 
+/* Macros to (de)construct the fake PTEs representing swap pages. */
+#define __swp_type(x)		((x).val & 0x7F)
+#define __swp_offset(x)		(((x).val) >> 7)
+#define __swp_entry(type,offset) ((swp_entry_t) { ((type) | ((offset) << 7)) })
+#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x)	((pte_t) { (x).val })
 
 #endif	/* !__ASSEMBLY__ */
 #endif	/* !_SUN3_PGTABLE_H */
diff -urN linux-2.5.69-bk18/include/asm-m68k/sun3ints.h linux-2.5.69-bk19/include/asm-m68k/sun3ints.h
--- linux-2.5.69-bk18/include/asm-m68k/sun3ints.h	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68k/sun3ints.h	2003-05-26 04:41:42.000000000 -0700
@@ -26,17 +26,17 @@
 void sun3_enable_irq(unsigned int irq);
 void sun3_disable_irq(unsigned int irq);
 int sun3_request_irq(unsigned int irq,
-                     void (*handler)(int, void *, struct pt_regs *),
+                     irqreturn_t (*handler)(int, void *, struct pt_regs *),
                      unsigned long flags, const char *devname, void *dev_id
 		    );
 extern void sun3_init_IRQ (void);
-extern void (*sun3_default_handler[]) (int, void *, struct pt_regs *);
-extern void (*sun3_inthandler[]) (int, void *, struct pt_regs *);
+extern irqreturn_t (*sun3_default_handler[]) (int, void *, struct pt_regs *);
+extern irqreturn_t (*sun3_inthandler[]) (int, void *, struct pt_regs *);
 extern void sun3_free_irq (unsigned int irq, void *dev_id);
 extern void sun3_enable_interrupts (void);
 extern void sun3_disable_interrupts (void);
 extern int show_sun3_interrupts(struct seq_file *, void *);
-extern void sun3_process_int(int, struct pt_regs *);
+extern irqreturn_t sun3_process_int(int, struct pt_regs *);
 extern volatile unsigned char* sun3_intreg;
 
 /* master list of VME vectors -- don't fuck with this */
diff -urN linux-2.5.69-bk18/include/asm-m68knommu/cacheflush.h linux-2.5.69-bk19/include/asm-m68knommu/cacheflush.h
--- linux-2.5.69-bk18/include/asm-m68knommu/cacheflush.h	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68knommu/cacheflush.h	2003-05-26 04:41:42.000000000 -0700
@@ -20,6 +20,11 @@
 extern inline void __flush_cache_all(void)
 {
 #ifdef CONFIG_M5407
+	/*
+	 *	Use cpushl to push and invalidate all cache lines.
+	 *	Gas doesn't seem to know how to generate the ColdFire
+	 *	cpushl instruction... Oh well, bit stuff it for now.
+	 */
 	__asm__ __volatile__ (
 		"nop\n\t"
 		"clrl	%%d0\n\t"
@@ -33,11 +38,6 @@
 		"addql	#1,%%d0\n\t"
 		"cmpil	#4,%%d0\n\t"
 		"bne	1b\n\t"
-		"movel  #0x01040100,%%d0\n\t"
-		"movec  %%d0,%%CACR\n\t"
-		"nop\n\t"
-		"movel  #0x86088400,%%d0\n\t"
-		"movec  %%d0,%%CACR\n\t"
 		: : : "d0", "a0" );
 #endif /* CONFIG_M5407 */
 #ifdef CONFIG_M5272
diff -urN linux-2.5.69-bk18/include/asm-m68knommu/coldfire.h linux-2.5.69-bk19/include/asm-m68knommu/coldfire.h
--- linux-2.5.69-bk18/include/asm-m68knommu/coldfire.h	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68knommu/coldfire.h	2003-05-26 04:41:42.000000000 -0700
@@ -20,6 +20,12 @@
  */
 #define	MCF_MBAR	0x10000000
 #define	MCF_MBAR2	0x80000000
+#define	MCF_IPSBAR	0x40000000
+
+#ifdef CONFIG_M5282
+#undef MCF_MBAR
+#define	MCF_MBAR	MCF_IPSBAR
+#endif
 
 /*
  *	Define master clock frequency.
diff -urN linux-2.5.69-bk18/include/asm-m68knommu/m5282sim.h linux-2.5.69-bk19/include/asm-m68knommu/m5282sim.h
--- linux-2.5.69-bk18/include/asm-m68knommu/m5282sim.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/include/asm-m68knommu/m5282sim.h	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,35 @@
+/****************************************************************************/
+
+/*
+ *	m5282sim.h -- ColdFire 5282 System Integration Module support.
+ *
+ *	(C) Copyright 2003, Greg Ungerer (gerg@snapgear.com)
+ */
+
+/****************************************************************************/
+#ifndef	m5282sim_h
+#define	m5282sim_h
+/****************************************************************************/
+
+#include <linux/config.h>
+
+/*
+ *	Define the 5282 SIM register set addresses.
+ */
+#define	MCFICM_INTC0		0x0c00		/* Base for Interrupt Ctrl 0 */
+#define	MCFICM_INTC1		0x0d00		/* Base for Interrupt Ctrl 0 */
+#define	MCFINTC_IPRH		0x00		/* Interrupt pending 32-63 */
+#define	MCFINTC_IPRL		0x04		/* Interrupt pending 1-31 */
+#define	MCFINTC_IMRH		0x08		/* Interrupt mask 32-63 */
+#define	MCFINTC_IMRL		0x0c		/* Interrupt mask 1-31 */
+#define	MCFINTC_INTFRCH		0x10		/* Interrupt force 32-63 */
+#define	MCFINTC_INTFRCL		0x14		/* Interrupt force 1-31 */
+#define	MCFINTC_IRLR		0x18		/* */
+#define	MCFINTC_IACKL		0x19		/* */
+#define	MCFINTC_ICR0		0x40		/* Base ICR register */
+
+#define	MCFINT_UART0		13		/* Interrupt number for UART0 */
+#define	MCFINT_PIT1		55		/* Interrupt number for PIT1 */
+
+/****************************************************************************/
+#endif	/* m5282sim_h */
diff -urN linux-2.5.69-bk18/include/asm-m68knommu/mcfdma.h linux-2.5.69-bk19/include/asm-m68knommu/mcfdma.h
--- linux-2.5.69-bk18/include/asm-m68knommu/mcfdma.h	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68knommu/mcfdma.h	2003-05-26 04:41:42.000000000 -0700
@@ -21,6 +21,12 @@
 #define	MCFDMA_BASE1		0x240		/* Base address of DMA 1 */
 #elif defined(CONFIG_M5272)
 #define	MCFDMA_BASE0		0x0e0		/* Base address of DMA 0 */
+#elif defined(CONFIG_M5282)
+/* These are relative to the IPSBAR, not MBAR */
+#define	MCFDMA_BASE0		0x100		/* Base address of DMA 0 */
+#define	MCFDMA_BASE1		0x140		/* Base address of DMA 1 */
+#define	MCFDMA_BASE2		0x180		/* Base address of DMA 2 */
+#define	MCFDMA_BASE3		0x1C0		/* Base address of DMA 3 */
 #elif defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407)
 #define	MCFDMA_BASE0		0x300		/* Base address of DMA 0 */
 #define	MCFDMA_BASE1		0x340		/* Base address of DMA 1 */
diff -urN linux-2.5.69-bk18/include/asm-m68knommu/mcfpit.h linux-2.5.69-bk19/include/asm-m68knommu/mcfpit.h
--- linux-2.5.69-bk18/include/asm-m68knommu/mcfpit.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/include/asm-m68knommu/mcfpit.h	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,63 @@
+/****************************************************************************/
+
+/*
+ *	mcfpit.h -- ColdFire internal PIT timer support defines.
+ *
+ *	(C) Copyright 2003, Greg Ungerer (gerg@snapgear.com)
+ */
+
+/****************************************************************************/
+#ifndef	mcfpit_h
+#define	mcfpit_h
+/****************************************************************************/
+
+#include <linux/config.h>
+
+/*
+ *	Get address specific defines for the 5282.
+ */
+#define	MCFPIT_BASE1		0x00150000	/* Base address of TIMER1 */
+#define	MCFPIT_BASE2		0x00160000	/* Base address of TIMER2 */
+#define	MCFPIT_BASE3		0x00170000	/* Base address of TIMER3 */
+#define	MCFPIT_BASE4		0x00180000	/* Base address of TIMER4 */
+
+
+/*
+ *	Define the PIT timer register set addresses.
+ */
+struct mcfpit {
+	unsigned short	pcsr;			/* PIT control and status */
+	unsigned short	pmr;			/* PIT modulus register */
+	unsigned short	pcntr;			/* PIT count register */
+} __attribute__((packed));
+
+/*
+ *	Bit definitions for the PIT Control and Status register.
+ */
+#define	MCFPIT_PCSR_CLK1	0x0000		/* System clock divisor */
+#define	MCFPIT_PCSR_CLK2	0x0100		/* System clock divisor */
+#define	MCFPIT_PCSR_CLK4	0x0200		/* System clock divisor */
+#define	MCFPIT_PCSR_CLK8	0x0300		/* System clock divisor */
+#define	MCFPIT_PCSR_CLK16	0x0400		/* System clock divisor */
+#define	MCFPIT_PCSR_CLK32	0x0500		/* System clock divisor */
+#define	MCFPIT_PCSR_CLK64	0x0600		/* System clock divisor */
+#define	MCFPIT_PCSR_CLK128	0x0700		/* System clock divisor */
+#define	MCFPIT_PCSR_CLK256	0x0800		/* System clock divisor */
+#define	MCFPIT_PCSR_CLK512	0x0900		/* System clock divisor */
+#define	MCFPIT_PCSR_CLK1024	0x0a00		/* System clock divisor */
+#define	MCFPIT_PCSR_CLK2048	0x0b00		/* System clock divisor */
+#define	MCFPIT_PCSR_CLK4096	0x0c00		/* System clock divisor */
+#define	MCFPIT_PCSR_CLK8192	0x0d00		/* System clock divisor */
+#define	MCFPIT_PCSR_CLK16384	0x0e00		/* System clock divisor */
+#define	MCFPIT_PCSR_CLK32768	0x0f00		/* System clock divisor */
+#define	MCFPIT_PCSR_DOZE	0x0040		/* Clock run in doze mode */
+#define	MCFPIT_PCSR_HALTED	0x0020		/* Clock run in halt mode */
+#define	MCFPIT_PCSR_OVW		0x0010		/* Overwrite PIT counter now */
+#define	MCFPIT_PCSR_PIE		0x0008		/* Enable PIT interrupt */
+#define	MCFPIT_PCSR_PIF		0x0004		/* PIT interrupt flag */
+#define	MCFPIT_PCSR_RLD		0x0002		/* Reload counter */
+#define	MCFPIT_PCSR_EN		0x0001		/* Enable PIT */
+#define	MCFPIT_PCSR_DISABLE	0x0000		/* Disable PIT */
+
+/****************************************************************************/
+#endif	/* mcfpit_h */
diff -urN linux-2.5.69-bk18/include/asm-m68knommu/mcfsim.h linux-2.5.69-bk19/include/asm-m68knommu/mcfsim.h
--- linux-2.5.69-bk18/include/asm-m68knommu/mcfsim.h	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68knommu/mcfsim.h	2003-05-26 04:41:42.000000000 -0700
@@ -3,7 +3,7 @@
 /*
  *	mcfsim.h -- ColdFire System Integration Module support.
  *
- *	(C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ *	(C) Copyright 1999-2003, Greg Ungerer (gerg@snapgear.com)
  * 	(C) Copyright 2000, Lineo Inc. (www.lineo.com) 
  */
 
@@ -15,7 +15,7 @@
 #include <linux/config.h>
 
 /*
- *	Include 5204, 5206, 5249, 5272, 5307 or 5407 specific addresses.
+ *	Include 5204, 5206, 5249, 5272, 5282, 5307 or 5407 specific addresses.
  */
 #if defined(CONFIG_M5204)
 #include <asm/m5204sim.h>
@@ -25,6 +25,8 @@
 #include <asm/m5249sim.h>
 #elif defined(CONFIG_M5272)
 #include <asm/m5272sim.h>
+#elif defined(CONFIG_M5282)
+#include <asm/m5282sim.h>
 #elif defined(CONFIG_M5307)
 #include <asm/m5307sim.h>
 #elif defined(CONFIG_M5407)
diff -urN linux-2.5.69-bk18/include/asm-m68knommu/mcfuart.h linux-2.5.69-bk19/include/asm-m68knommu/mcfuart.h
--- linux-2.5.69-bk18/include/asm-m68knommu/mcfuart.h	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68knommu/mcfuart.h	2003-05-26 04:41:42.000000000 -0700
@@ -3,7 +3,7 @@
 /*
  *	mcfuart.h -- ColdFire internal UART support defines.
  *
- *	(C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ *	(C) Copyright 1999-2003, Greg Ungerer (gerg@snapgear.com)
  * 	(C) Copyright 2000, Lineo Inc. (www.lineo.com) 
  */
 
@@ -29,13 +29,17 @@
 #define	MCFUART_BASE1		0x140		/* Base address of UART1 */
 #define	MCFUART_BASE2		0x180		/* Base address of UART2 */
 #endif
+#elif defined(CONFIG_M5282)
+#define MCFUART_BASE1		0x200           /* Base address of UART1 */
+#define MCFUART_BASE2		0x240           /* Base address of UART2 */
+#define MCFUART_BASE3		0x280           /* Base address of UART3 */
 #elif defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407)
 #if defined(CONFIG_NETtel) || defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3)
 #define MCFUART_BASE1		0x200           /* Base address of UART1 */
-#define MCFUART_BASE2		0x1c0           /* Base address of UART2 */    
+#define MCFUART_BASE2		0x1c0           /* Base address of UART2 */
 #else
 #define MCFUART_BASE1		0x1c0           /* Base address of UART1 */
-#define MCFUART_BASE2		0x200           /* Base address of UART2 */    
+#define MCFUART_BASE2		0x200           /* Base address of UART2 */
 #endif
 #endif
 
@@ -55,7 +59,13 @@
 #define	MCFUART_UIMR		0x14		/* Interrupt Mask (w) */
 #define	MCFUART_UBG1		0x18		/* Baud Rate MSB (r/w) */
 #define	MCFUART_UBG2		0x1c		/* Baud Rate LSB (r/w) */
+#ifdef	CONFIG_M5272
+#define	MCFUART_UTF		0x28		/* Transmitter FIFO (r/w) */
+#define	MCFUART_URF		0x2c		/* Receiver FIFO (r/w) */
+#define	MCFUART_UFPD		0x30		/* Frac Prec. Divider (r/w) */
+#else
 #define	MCFUART_UIVR		0x30		/* Interrupt Vector (r/w) */
+#endif
 #define	MCFUART_UIPR		0x34		/* Input Port (r) */
 #define	MCFUART_UOP1		0x38		/* Output Port Bit Set (w) */
 #define	MCFUART_UOP0		0x3c		/* Output Port Bit Reset (w) */
@@ -170,5 +180,21 @@
 #define	MCFUART_UIR_RXREADY	0x02		/* Receiver ready */
 #define	MCFUART_UIR_TXREADY	0x01		/* Transmitter ready */
 
+#ifdef	CONFIG_M5272
+/*
+ *	Define bit flags in the Transmitter FIFO Register (UTF).
+ */
+#define	MCFUART_UTF_TXB		0x1f		/* Transmitter data level */
+#define	MCFUART_UTF_FULL	0x20		/* Transmitter fifo full */
+#define	MCFUART_UTF_TXS		0xc0		/* Transmitter status */
+
+/*
+ *	Define bit flags in the Receiver FIFO Register (URF).
+ */
+#define	MCFUART_URF_RXB		0x1f		/* Receiver data level */
+#define	MCFUART_URF_FULL	0x20		/* Receiver fifo full */
+#define	MCFUART_URF_RXS		0xc0		/* Receiver status */
+#endif
+
 /****************************************************************************/
 #endif	/* mcfuart_h */
diff -urN linux-2.5.69-bk18/include/asm-m68knommu/pgtable.h linux-2.5.69-bk19/include/asm-m68knommu/pgtable.h
--- linux-2.5.69-bk18/include/asm-m68knommu/pgtable.h	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-m68knommu/pgtable.h	2003-05-26 04:41:42.000000000 -0700
@@ -38,6 +38,8 @@
 #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)	((pte_t) { (x).val })
 
+static inline int pte_file(pte_t pte) { return 0; }
+
 /*
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
@@ -56,4 +58,11 @@
 #define pgtable_cache_init()	do { } while (0)
 #define io_remap_page_range	remap_page_range
 
+/*
+ * All 32bit addresses are effectively valid for vmalloc...
+ * Sort of meaningless for non-VM targets.
+ */
+#define	VMALLOC_START	0
+#define	VMALLOC_END	0xffffffff
+
 #endif /* _M68KNOMMU_PGTABLE_H */
diff -urN linux-2.5.69-bk18/include/asm-ppc/linux_logo.h linux-2.5.69-bk19/include/asm-ppc/linux_logo.h
--- linux-2.5.69-bk18/include/asm-ppc/linux_logo.h	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-ppc/linux_logo.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,24 +0,0 @@
-/*
- * include/asm-ppc/linux_logo.h: A linux logo to be displayed on boot
- * (pinched from the sparc port).
- *
- * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu)
- * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *
- * You can put anything here, but:
- * LINUX_LOGO_COLORS has to be less than 224
- * values have to start from 0x20
- * (i.e. linux_logo_{red,green,blue}[0] is color 0x20)
- */
-#ifdef __KERNEL__
- 
-#include <linux/init.h>
-
-#define linux_logo_banner "Linux/PPC version " UTS_RELEASE
-
-#define LINUX_LOGO_HEIGHT	80
-#define LINUX_LOGO_WIDTH	80
-
-#include <linux/linux_logo.h>
-
-#endif /* __KERNEL__ */
diff -urN linux-2.5.69-bk18/include/asm-ppc64/compat.h linux-2.5.69-bk19/include/asm-ppc64/compat.h
--- linux-2.5.69-bk18/include/asm-ppc64/compat.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-ppc64/compat.h	2003-05-26 04:41:42.000000000 -0700
@@ -4,6 +4,7 @@
  * Architecture specific compatibility types
  */
 #include <linux/types.h>
+#include <linux/sched.h>
 
 #define COMPAT_USER_HZ	100
 
diff -urN linux-2.5.69-bk18/include/asm-ppc64/pgtable.h linux-2.5.69-bk19/include/asm-ppc64/pgtable.h
--- linux-2.5.69-bk18/include/asm-ppc64/pgtable.h	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-ppc64/pgtable.h	2003-05-26 04:41:42.000000000 -0700
@@ -377,5 +377,14 @@
 
 typedef pte_t *pte_addr_t;
 
+long pSeries_lpar_hpte_insert(unsigned long hpte_group,
+			      unsigned long va, unsigned long prpn,
+			      int secondary, unsigned long hpteflags,
+			      int bolted, int large);
+
+long pSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
+			 unsigned long prpn, int secondary,
+			 unsigned long hpteflags, int bolted, int large);
+
 #endif /* __ASSEMBLY__ */
 #endif /* _PPC64_PGTABLE_H */
diff -urN linux-2.5.69-bk18/include/asm-ppc64/signal.h linux-2.5.69-bk19/include/asm-ppc64/signal.h
--- linux-2.5.69-bk18/include/asm-ppc64/signal.h	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/include/asm-ppc64/signal.h	2003-05-26 04:41:42.000000000 -0700
@@ -145,4 +145,7 @@
 
 #define ptrace_signal_deliver(regs, cookie) do { } while (0)
 
+struct pt_regs;
+int do_signal32(sigset_t *oldset, struct pt_regs *regs);
+
 #endif /* _ASMPPC64_SIGNAL_H */
diff -urN linux-2.5.69-bk18/include/linux/aio.h linux-2.5.69-bk19/include/linux/aio.h
--- linux-2.5.69-bk18/include/linux/aio.h	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/aio.h	2003-05-26 04:41:42.000000000 -0700
@@ -147,6 +147,9 @@
 extern void FASTCALL(__put_ioctx(struct kioctx *ctx));
 struct mm_struct;
 extern void FASTCALL(exit_aio(struct mm_struct *mm));
+extern struct kioctx *lookup_ioctx(unsigned long ctx_id);
+extern int FASTCALL(io_submit_one(struct kioctx *ctx,
+			struct iocb *user_iocb, struct iocb *iocb));
 
 /* semi private, but used by the 32bit emulations: */
 struct kioctx *lookup_ioctx(unsigned long ctx_id);
diff -urN linux-2.5.69-bk18/include/linux/arcdevice.h linux-2.5.69-bk19/include/linux/arcdevice.h
--- linux-2.5.69-bk18/include/linux/arcdevice.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/arcdevice.h	2003-05-26 04:41:42.000000000 -0700
@@ -329,7 +329,7 @@
 #endif
 
 void arcnet_unregister_proto(struct ArcProto *proto);
-void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 void arcdev_setup(struct net_device *dev);
 void arcnet_rx(struct net_device *dev, int bufnum);
 
diff -urN linux-2.5.69-bk18/include/linux/bio.h linux-2.5.69-bk19/include/linux/bio.h
--- linux-2.5.69-bk18/include/linux/bio.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/bio.h	2003-05-26 04:41:42.000000000 -0700
@@ -22,6 +22,7 @@
 
 #include <linux/kdev_t.h>
 #include <linux/highmem.h>
+#include <linux/mempool.h>
 
 /* Platforms may set this to teach the BIO layer about IOMMU hardware. */
 #include <asm/io.h>
@@ -202,6 +203,27 @@
  */
 #define bio_get(bio)	atomic_inc(&(bio)->bi_cnt)
 
+
+/*
+ * A bio_pair is used when we need to split a bio.
+ * This can only happen for a bio that refers to just one
+ * page of data, and in the unusual situation when the
+ * page crosses a chunk/device boundary
+ *
+ * The address of the master bio is stored in bio1.bi_private
+ * The address of the pool the pair was allocated from is stored
+ *   in bio2.bi_private
+ */
+struct bio_pair {
+	struct bio	bio1, bio2;
+	struct bio_vec	bv1, bv2;
+	atomic_t	cnt;
+	int		error;
+};
+extern struct bio_pair *bio_split(struct bio *bi, mempool_t *pool,
+				  int first_sectors);
+extern void bio_pair_release(struct bio_pair *dbio);
+
 extern struct bio *bio_alloc(int, int);
 extern void bio_put(struct bio *);
 
diff -urN linux-2.5.69-bk18/include/linux/cdev.h linux-2.5.69-bk19/include/linux/cdev.h
--- linux-2.5.69-bk18/include/linux/cdev.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/include/linux/cdev.h	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,29 @@
+#ifndef _LINUX_CDEV_H
+#define _LINUX_CDEV_H
+#ifdef __KERNEL__
+
+struct cdev {
+	struct kobject kobj;
+	struct module *owner;
+	struct file_operations *ops;
+	struct list_head list;
+};
+
+void cdev_init(struct cdev *, struct file_operations *);
+
+struct cdev *cdev_alloc(void);
+
+void cdev_put(struct cdev *p);
+
+struct kobject *cdev_get(struct cdev *);
+
+int cdev_add(struct cdev *, dev_t, unsigned);
+
+void cdev_del(struct cdev *);
+
+void cdev_unmap(dev_t, unsigned);
+
+void cd_forget(struct inode *);
+
+#endif
+#endif
diff -urN linux-2.5.69-bk18/include/linux/eventpoll.h linux-2.5.69-bk19/include/linux/eventpoll.h
--- linux-2.5.69-bk18/include/linux/eventpoll.h	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/eventpoll.h	2003-05-26 04:41:42.000000000 -0700
@@ -40,12 +40,21 @@
 asmlinkage long sys_epoll_wait(int epfd, struct epoll_event *events, int maxevents,
 			       int timeout);
 
+#ifdef CONFIG_EPOLL
+
 /* Used to initialize the epoll bits inside the "struct file" */
 void eventpoll_init_file(struct file *file);
 
 /* Used in fs/file_table.c:__fput() to unlink files from the eventpoll interface */
 void eventpoll_release(struct file *file);
 
+#else
+
+static inline void eventpoll_init_file(struct file *file) {}
+static inline void eventpoll_release(struct file *file) {}
+
+#endif
+
 #endif /* #ifdef __KERNEL__ */
 
 #endif /* #ifndef _LINUX_EVENTPOLL_H */
diff -urN linux-2.5.69-bk18/include/linux/fs.h linux-2.5.69-bk19/include/linux/fs.h
--- linux-2.5.69-bk18/include/linux/fs.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/fs.h	2003-05-26 04:41:42.000000000 -0700
@@ -382,6 +382,8 @@
 	struct list_head	i_devices;
 	struct pipe_inode_info	*i_pipe;
 	struct block_device	*i_bdev;
+	struct cdev		*i_cdev;
+	int			i_cindex;
 
 	unsigned long		i_dnotify_mask; /* Directory notify events */
 	struct dnotify_struct	*i_dnotify; /* for directory notifications */
@@ -917,7 +919,8 @@
 	const char *name;
 	struct subsystem subsys;
 	int fs_flags;
-	struct super_block *(*get_sb) (struct file_system_type *, int, char *, void *);
+	struct super_block *(*get_sb) (struct file_system_type *, int,
+				       const char *, void *);
 	void (*kill_sb) (struct super_block *);
 	struct module *owner;
 	struct file_system_type * next;
@@ -925,7 +928,7 @@
 };
 
 struct super_block *get_sb_bdev(struct file_system_type *fs_type,
-	int flags, char *dev_name, void * data,
+	int flags, const char *dev_name, void *data,
 	int (*fill_super)(struct super_block *, void *, int));
 struct super_block *get_sb_single(struct file_system_type *fs_type,
 	int flags, void *data,
@@ -1056,13 +1059,12 @@
 extern void blk_run_queues(void);
 
 /* fs/char_dev.c */
-extern int register_chrdev_region(unsigned int, unsigned int, int,
-				  const char *, struct file_operations *);
+extern int alloc_chrdev_region(dev_t *, unsigned, char *);
+extern int register_chrdev_region(dev_t, unsigned, char *);
 extern int register_chrdev(unsigned int, const char *,
 			   struct file_operations *);
 extern int unregister_chrdev(unsigned int, const char *);
-extern int unregister_chrdev_region(unsigned int, unsigned int, int,
-				    const char *);
+extern void unregister_chrdev_region(dev_t, unsigned);
 extern int chrdev_open(struct inode *, struct file *);
 
 /* fs/block_dev.c */
@@ -1116,7 +1118,7 @@
 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);
+			 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-bk18/include/linux/futex.h linux-2.5.69-bk19/include/linux/futex.h
--- linux-2.5.69-bk18/include/linux/futex.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/futex.h	2003-05-26 04:41:42.000000000 -0700
@@ -2,10 +2,19 @@
 #define _LINUX_FUTEX_H
 
 /* Second argument to futex syscall */
+
+
 #define FUTEX_WAIT (0)
 #define FUTEX_WAKE (1)
 #define FUTEX_FD (2)
+#define FUTEX_REQUEUE (3)
+
+
+asmlinkage long sys_futex(u32 __user *uaddr, int op, int val,
+			  struct timespec __user *utime, u32 __user *uaddr2);
+
 
-extern asmlinkage long sys_futex(u32 __user *uaddr, int op, int val, struct timespec __user *utime);
+long do_futex(unsigned long uaddr, int op, int val,
+		unsigned long timeout, unsigned long uaddr2, int val2);
 
 #endif
diff -urN linux-2.5.69-bk18/include/linux/genhd.h linux-2.5.69-bk19/include/linux/genhd.h
--- linux-2.5.69-bk18/include/linux/genhd.h	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/genhd.h	2003-05-26 04:41:42.000000000 -0700
@@ -365,12 +365,12 @@
 extern void delete_partition(struct gendisk *, int);
 
 extern struct gendisk *alloc_disk(int minors);
-extern struct gendisk *get_disk(struct gendisk *disk);
+extern struct kobject *get_disk(struct gendisk *disk);
 extern void put_disk(struct gendisk *disk);
 
 extern void blk_register_region(dev_t dev, unsigned long range,
 			struct module *module,
-			struct gendisk *(*probe)(dev_t, int *, void *),
+			struct kobject *(*probe)(dev_t, int *, void *),
 			int (*lock)(dev_t, void *),
 			void *data);
 extern void blk_unregister_region(dev_t dev, unsigned long range);
diff -urN linux-2.5.69-bk18/include/linux/hugetlb.h linux-2.5.69-bk19/include/linux/hugetlb.h
--- linux-2.5.69-bk18/include/linux/hugetlb.h	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/hugetlb.h	2003-05-26 04:41:42.000000000 -0700
@@ -37,8 +37,8 @@
 		mm->used_hugetlb = 1;
 }
 
-#ifndef ARCH_HAS_VALID_HUGEPAGE_RANGE
-#define check_valid_hugepage_range(addr, len)	0
+#ifndef ARCH_HAS_HUGEPAGE_ONLY_RANGE
+#define is_hugepage_only_range(addr, len)	0
 #endif
 
 #else /* !CONFIG_HUGETLB_PAGE */
@@ -62,7 +62,7 @@
 #define follow_huge_pmd(mm, addr, pmd, write)	0
 #define is_aligned_hugepage_range(addr, len)	0
 #define pmd_huge(x)	0
-#define check_valid_hugepage_range(addr, len)	0
+#define is_hugepage_only_range(addr, len)	0
 
 #ifndef HPAGE_MASK
 #define HPAGE_MASK	0		/* Keep the compiler happy */
diff -urN linux-2.5.69-bk18/include/linux/if_bonding.h linux-2.5.69-bk19/include/linux/if_bonding.h
--- linux-2.5.69-bk18/include/linux/if_bonding.h	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/if_bonding.h	2003-05-26 04:41:42.000000000 -0700
@@ -11,18 +11,38 @@
  *	This software may be used and distributed according to the terms
  *	of the GNU Public License, incorporated herein by reference.
  * 
+ * 2003/03/18 - Amir Noam <amir.noam at intel dot com>
+ *	- Added support for getting slave's speed and duplex via ethtool.
+ *	  Needed for 802.3ad and other future modes.
+ * 
+ * 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
+ *		Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Enable support of modes that need to use the unique mac address of
+ *	  each slave.
+ *
+ * 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
+ *		Amir Noam <amir.noam at intel dot com>
+ *	- Moved driver's private data types to bonding.h
+ *
+ * 2003/03/18 - Amir Noam <amir.noam at intel dot com>,
+ *		Tsippy Mendelson <tsippy.mendelson at intel dot com> and
+ *		Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Added support for IEEE 802.3ad Dynamic link aggregation mode.
+ *
+ * 2003/05/01 - Amir Noam <amir.noam at intel dot com>
+ *	- Added ABI version control to restore compatibility between
+ *	  new/old ifenslave and new/old bonding.
  */
 
 #ifndef _LINUX_IF_BONDING_H
 #define _LINUX_IF_BONDING_H
 
-#ifdef __KERNEL__
-#include <linux/timer.h>
 #include <linux/if.h>
-#include <linux/proc_fs.h>
-#endif /* __KERNEL__ */
-
 #include <linux/types.h>
+#include <linux/if_ether.h>
+
+/* userland - kernel ABI version (2003/05/08) */
+#define BOND_ABI_VERSION 1
 
 /*
  * We can remove these ioctl definitions in 2.5.  People should use the
@@ -41,6 +61,9 @@
 #define BOND_MODE_ACTIVEBACKUP	1
 #define BOND_MODE_XOR		2
 #define BOND_MODE_BROADCAST	3
+#define BOND_MODE_8023AD        4
+#define BOND_MODE_TLB           5
+#define BOND_MODE_ALB		6 /* TLB + RLB (receive load balancing) */
 
 /* each slave's link has 4 states */
 #define BOND_LINK_UP    0           /* link is up and running */
@@ -58,11 +81,6 @@
 #define BOND_MULTICAST_ACTIVE   1
 #define BOND_MULTICAST_ALL      2
 
-struct bond_parm_tbl {
-	char *modename;
-	int mode;
-};
-
 typedef struct ifbond {
 	__s32 bond_mode;
 	__s32 num_slaves;
@@ -78,52 +96,15 @@
 	__u32  link_failure_count;
 } ifslave;
 
-#ifdef __KERNEL__
-typedef struct slave {
-	struct slave *next;
-	struct slave *prev;
-	struct net_device *dev;
-	short  delay;
-	unsigned long jiffies;	
-	char   link;    /* one of BOND_LINK_XXXX */
-	char   state;   /* one of BOND_STATE_XXXX */
-	unsigned short original_flags;
-	u32 link_failure_count;
-} slave_t;
-
-/*
- * Here are the locking policies for the two bonding locks:
- *
- * 1) Get bond->lock when reading/writing slave list.
- * 2) Get bond->ptrlock when reading/writing bond->current_slave.
- *    (It is unnecessary when the write-lock is put with bond->lock.)
- * 3) When we lock with bond->ptrlock, we must lock with bond->lock
- *    beforehand.
- */
-typedef struct bonding {
-	slave_t *next;
-	slave_t *prev;
-	slave_t *current_slave;
-	slave_t *primary_slave;
-	slave_t *current_arp_slave;
-	__s32 slave_cnt;
-	rwlock_t lock;
-	rwlock_t ptrlock;
-	struct timer_list mii_timer;
-	struct timer_list arp_timer;
-	struct net_device_stats *stats;
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *bond_proc_dir;
-	struct proc_dir_entry *bond_proc_info_file;
-#endif /* CONFIG_PROC_FS */
-	struct bonding *next_bond;
-	struct net_device *device;
-	struct dev_mc_list *mc_list;
-	unsigned short flags;
-} bonding_t;
-#endif /* __KERNEL__ */
+struct ad_info {
+	__u16 aggregator_id;
+	__u16 ports;
+	__u16 actor_key;
+	__u16 partner_key;
+	__u8 partner_system[ETH_ALEN];
+};
 
-#endif /* _LINUX_BOND_H */
+#endif /* _LINUX_IF_BONDING_H */
 
 /*
  * Local variables:
diff -urN linux-2.5.69-bk18/include/linux/if_vlan.h linux-2.5.69-bk19/include/linux/if_vlan.h
--- linux-2.5.69-bk18/include/linux/if_vlan.h	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/if_vlan.h	2003-05-26 04:41:42.000000000 -0700
@@ -148,6 +148,7 @@
 {
 	struct net_device_stats *stats;
 
+	skb->real_dev = skb->dev;
 	skb->dev = grp->vlan_devices[vlan_tag & VLAN_VID_MASK];
 	if (skb->dev == NULL) {
 		kfree_skb(skb);
diff -urN linux-2.5.69-bk18/include/linux/init_task.h linux-2.5.69-bk19/include/linux/init_task.h
--- linux-2.5.69-bk18/include/linux/init_task.h	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/init_task.h	2003-05-26 04:41:42.000000000 -0700
@@ -101,6 +101,7 @@
 	.blocked	= {{0}},					\
 	 .posix_timers	 = LIST_HEAD_INIT(tsk.posix_timers),		   \
 	.alloc_lock	= SPIN_LOCK_UNLOCKED,				\
+	.proc_lock	= SPIN_LOCK_UNLOCKED,				\
 	.switch_lock	= SPIN_LOCK_UNLOCKED,				\
 	.journal_info	= NULL,						\
 }
diff -urN linux-2.5.69-bk18/include/linux/interrupt.h linux-2.5.69-bk19/include/linux/interrupt.h
--- linux-2.5.69-bk18/include/linux/interrupt.h	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/interrupt.h	2003-05-26 04:41:42.000000000 -0700
@@ -213,24 +213,6 @@
 extern void tasklet_init(struct tasklet_struct *t,
 			 void (*func)(unsigned long), unsigned long data);
 
-#ifdef CONFIG_SMP
-
-#define SMP_TIMER_NAME(name) name##__thr
-
-#define SMP_TIMER_DEFINE(name, task) \
-DECLARE_TASKLET(task, name##__thr, 0); \
-static void name (unsigned long dummy) \
-{ \
-	tasklet_schedule(&(task)); \
-}
-
-#else /* CONFIG_SMP */
-
-#define SMP_TIMER_NAME(name) name
-#define SMP_TIMER_DEFINE(name, task)
-
-#endif /* CONFIG_SMP */
-
 /*
  * Autoprobing for irqs:
  *
diff -urN linux-2.5.69-bk18/include/linux/kobj_map.h linux-2.5.69-bk19/include/linux/kobj_map.h
--- linux-2.5.69-bk18/include/linux/kobj_map.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.69-bk19/include/linux/kobj_map.h	2003-05-26 04:41:42.000000000 -0700
@@ -0,0 +1,12 @@
+#ifdef __KERNEL__
+
+typedef struct kobject *kobj_probe_t(dev_t, int *, void *);
+struct kobj_map;
+
+int kobj_map(struct kobj_map *, dev_t, unsigned long, struct module *,
+	     kobj_probe_t *, int (*)(dev_t, void *), void *);
+void kobj_unmap(struct kobj_map *, dev_t, unsigned long);
+struct kobject *kobj_lookup(struct kobj_map *, dev_t, int *);
+struct kobj_map *kobj_map_init(kobj_probe_t *, struct subsystem *);
+
+#endif
diff -urN linux-2.5.69-bk18/include/linux/mount.h linux-2.5.69-bk19/include/linux/mount.h
--- linux-2.5.69-bk18/include/linux/mount.h	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/mount.h	2003-05-26 04:41:42.000000000 -0700
@@ -50,5 +50,10 @@
 	}
 }
 
+extern void free_vfsmnt(struct vfsmount *mnt);
+extern struct vfsmount *alloc_vfsmnt(const char *name);
+extern struct vfsmount *do_kern_mount(const char *fstype, int flags,
+				      const char *name, void *data);
+
 #endif
 #endif /* _LINUX_MOUNT_H */
diff -urN linux-2.5.69-bk18/include/linux/namespace.h linux-2.5.69-bk19/include/linux/namespace.h
--- linux-2.5.69-bk18/include/linux/namespace.h	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/namespace.h	2003-05-26 04:41:42.000000000 -0700
@@ -12,9 +12,8 @@
 	struct rw_semaphore	sem;
 };
 
-void umount_tree(struct vfsmount *mnt);
-
 extern void umount_tree(struct vfsmount *);
+extern int copy_namespace(int, struct task_struct *);
 
 static inline void put_namespace(struct namespace *namespace)
 {
@@ -38,7 +37,6 @@
 		put_namespace(namespace);
 	}
 }
-extern int copy_namespace(int, struct task_struct *);
 
 static inline void get_namespace(struct namespace *namespace)
 {
diff -urN linux-2.5.69-bk18/include/linux/netdevice.h linux-2.5.69-bk19/include/linux/netdevice.h
--- linux-2.5.69-bk18/include/linux/netdevice.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/netdevice.h	2003-05-26 04:41:42.000000000 -0700
@@ -441,9 +441,6 @@
 	struct divert_blk	*divert;
 #endif /* CONFIG_NET_DIVERT */
 
-	/* generic device structure used in constructing class */
-	struct device		*dev;
-
 	/* class/net/name entry */
 	struct class_device	class_dev;
 
@@ -455,7 +452,7 @@
 /* Set the sysfs physical device reference for the network logical device
  * if set prior to registration will cause a symlink during initialization.
  */
-#define SET_NETDEV_DEV(net, pdev)	((net)->dev = (pdev))
+#define SET_NETDEV_DEV(net, pdev)	((net)->class_dev.dev = (pdev))
 
 
 struct packet_type 
diff -urN linux-2.5.69-bk18/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.5.69-bk19/include/linux/netfilter_ipv4/ip_conntrack.h
--- linux-2.5.69-bk18/include/linux/netfilter_ipv4/ip_conntrack.h	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/netfilter_ipv4/ip_conntrack.h	2003-05-26 04:41:42.000000000 -0700
@@ -7,6 +7,7 @@
 #include <linux/config.h>
 #include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
 #include <linux/bitops.h>
+#include <linux/compiler.h>
 #include <asm/atomic.h>
 
 enum ip_conntrack_info
@@ -266,5 +267,16 @@
 }
 
 extern unsigned int ip_conntrack_htable_size;
+
+/* eg. PROVIDES_CONNTRACK(ftp); */
+#define PROVIDES_CONNTRACK(name)                        \
+        int needs_ip_conntrack_##name;                  \
+        EXPORT_SYMBOL(needs_ip_conntrack_##name)
+
+/*. eg. NEEDS_CONNTRACK(ftp); */
+#define NEEDS_CONNTRACK(name)                                           \
+        extern int needs_ip_conntrack_##name;                           \
+        static int *need_ip_conntrack_##name __attribute_used__ = &needs_ip_conntrack_##name
+
 #endif /* __KERNEL__ */
 #endif /* _IP_CONNTRACK_H */
diff -urN linux-2.5.69-bk18/include/linux/netfilter_ipv4/ip_nat_helper.h linux-2.5.69-bk19/include/linux/netfilter_ipv4/ip_nat_helper.h
--- linux-2.5.69-bk18/include/linux/netfilter_ipv4/ip_nat_helper.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/netfilter_ipv4/ip_nat_helper.h	2003-05-26 04:41:42.000000000 -0700
@@ -3,14 +3,13 @@
 /* NAT protocol helper routines. */
 
 #include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/module.h>
 
 struct sk_buff;
 
 /* Flags */
 /* NAT helper must be called on every packet (for TCP) */
 #define IP_NAT_HELPER_F_ALWAYS		0x01
-/* Standalone NAT helper, without a conntrack part */
-#define IP_NAT_HELPER_F_STANDALONE	0x02
 
 struct ip_nat_helper
 {
diff -urN linux-2.5.69-bk18/include/linux/netlink.h linux-2.5.69-bk19/include/linux/netlink.h
--- linux-2.5.69-bk18/include/linux/netlink.h	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/netlink.h	2003-05-26 04:41:42.000000000 -0700
@@ -108,7 +108,6 @@
 extern int netlink_attach(int unit, int (*function)(int,struct sk_buff *skb));
 extern void netlink_detach(int unit);
 extern int netlink_post(int unit, struct sk_buff *skb);
-extern int init_netlink(void);
 extern struct sock *netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len));
 extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
 extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
diff -urN linux-2.5.69-bk18/include/linux/proc_fs.h linux-2.5.69-bk19/include/linux/proc_fs.h
--- linux-2.5.69-bk18/include/linux/proc_fs.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/proc_fs.h	2003-05-26 04:41:42.000000000 -0700
@@ -87,6 +87,8 @@
 extern void proc_misc_init(void);
 
 struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry);
+struct dentry *proc_pid_unhash(struct task_struct *p);
+void proc_pid_flush(struct dentry *proc_dentry);
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
 
 extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
diff -urN linux-2.5.69-bk18/include/linux/reiserfs_fs.h linux-2.5.69-bk19/include/linux/reiserfs_fs.h
--- linux-2.5.69-bk18/include/linux/reiserfs_fs.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/reiserfs_fs.h	2003-05-26 04:41:42.000000000 -0700
@@ -872,11 +872,41 @@
 #define set_sd_v1_first_direct_byte(sdp,v) \
                                 ((sdp)->sd_first_direct_byte = cpu_to_le32(v))
 
+#include <linux/ext2_fs.h>
+
+/* inode flags stored in sd_attrs (nee sd_reserved) */
+
+/* we want common flags to have the same values as in ext2,
+   so chattr(1) will work without problems */
+#define REISERFS_IMMUTABLE_FL EXT2_IMMUTABLE_FL
+#define REISERFS_SYNC_FL      EXT2_SYNC_FL
+#define REISERFS_NOATIME_FL   EXT2_NOATIME_FL
+#define REISERFS_NODUMP_FL    EXT2_NODUMP_FL
+#define REISERFS_SECRM_FL     EXT2_SECRM_FL
+#define REISERFS_UNRM_FL      EXT2_UNRM_FL
+#define REISERFS_COMPR_FL     EXT2_COMPR_FL
+/* persistent flag to disable tails on per-file basic.
+   Note, that is inheritable: mark directory with this and
+   all new files inside will not have tails. 
+
+   Teodore Tso allocated EXT2_NODUMP_FL (0x00008000) for this. Change
+   numeric constant to ext2 macro when available. */
+#define REISERFS_NOTAIL_FL    (0x00008000) /* EXT2_NOTAIL_FL */
+
+/* persistent flags that file inherits from the parent directory */
+#define REISERFS_INHERIT_MASK ( REISERFS_IMMUTABLE_FL |	\
+				REISERFS_SYNC_FL |	\
+				REISERFS_NOATIME_FL |	\
+				REISERFS_NODUMP_FL |	\
+				REISERFS_SECRM_FL |	\
+				REISERFS_COMPR_FL |	\
+				REISERFS_NOTAIL_FL )
+
 /* Stat Data on disk (reiserfs version of UFS disk inode minus the
    address blocks) */
 struct stat_data {
     __u16 sd_mode;	/* file type, permissions */
-    __u16 sd_reserved;
+    __u16 sd_attrs;     /* persistent inode flags */
     __u32 sd_nlink;	/* number of hard links */
     __u64 sd_size;	/* file size */
     __u32 sd_uid;		/* owner */
@@ -929,6 +959,8 @@
 #define set_sd_v2_rdev(sdp,v)   ((sdp)->u.sd_rdev = cpu_to_le32(v))
 #define sd_v2_generation(sdp)   (le32_to_cpu((sdp)->u.sd_generation))
 #define set_sd_v2_generation(sdp,v) ((sdp)->u.sd_generation = cpu_to_le32(v))
+#define sd_v2_attrs(sdp)         (le16_to_cpu((sdp)->sd_attrs))
+#define set_sd_v2_attrs(sdp,v)   ((sdp)->sd_attrs = cpu_to_le16(v))
 
 
 /***************************************************************************/
@@ -1871,6 +1903,9 @@
 int reiserfs_sync_inode (struct reiserfs_transaction_handle *th, struct inode * inode);
 void reiserfs_update_sd (struct reiserfs_transaction_handle *th, struct inode * inode);
 
+void sd_attrs_to_i_attrs( __u16 sd_attrs, struct inode *inode );
+void i_attrs_to_sd_attrs( struct inode *inode, __u16 *sd_attrs );
+
 /* namei.c */
 inline void set_de_name_and_namelen (struct reiserfs_dir_entry * de);
 int search_by_entry_key (struct super_block * sb, const struct cpu_key * key, 
@@ -2145,6 +2180,12 @@
  
 /* ioctl's command */
 #define REISERFS_IOC_UNPACK		_IOW(0xCD,1,long)
+/* define following flags to be the same as in ext2, so that chattr(1),
+   lsattr(1) will work with us. */
+#define REISERFS_IOC_GETFLAGS		EXT2_IOC_GETFLAGS
+#define REISERFS_IOC_SETFLAGS		EXT2_IOC_SETFLAGS
+#define REISERFS_IOC_GETVERSION		EXT2_IOC_GETVERSION
+#define REISERFS_IOC_SETVERSION		EXT2_IOC_SETVERSION
 
 /* Locking primitives */
 /* Right now we are still falling back to (un)lock_kernel, but eventually that
diff -urN linux-2.5.69-bk18/include/linux/reiserfs_fs_i.h linux-2.5.69-bk19/include/linux/reiserfs_fs_i.h
--- linux-2.5.69-bk18/include/linux/reiserfs_fs_i.h	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/reiserfs_fs_i.h	2003-05-26 04:41:42.000000000 -0700
@@ -32,6 +32,9 @@
 
     __u32 i_first_direct_byte; // offset of first byte stored in direct item.
 
+    /* copy of persistent inode flags read from sd_attrs. */
+    __u32 i_attrs;
+
     int i_prealloc_block; /* first unused block of a sequence of unused blocks */
     int i_prealloc_count; /* length of that sequence */
     struct list_head i_prealloc_list; /* per-transaction list of inodes which
diff -urN linux-2.5.69-bk18/include/linux/reiserfs_fs_sb.h linux-2.5.69-bk19/include/linux/reiserfs_fs_sb.h
--- linux-2.5.69-bk18/include/linux/reiserfs_fs_sb.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/reiserfs_fs_sb.h	2003-05-26 04:41:42.000000000 -0700
@@ -8,6 +8,9 @@
 #include <linux/workqueue.h>
 #endif
 
+typedef enum {
+  reiserfs_attrs_cleared	= 0x00000001,
+} reiserfs_super_block_flags;
 
 /* struct reiserfs_super_block accessors/mutators
  * since this is a disk structure, it will always be in 
@@ -436,7 +439,6 @@
 #define REISERFS_NO_BORDER 11
 #define REISERFS_NO_UNHASHED_RELOCATION 12
 #define REISERFS_HASHED_RELOCATION 13
-#define REISERFS_TEST4 14 
 
 #define REISERFS_ATTRS 15
 
@@ -458,6 +460,7 @@
 #define have_small_tails(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_SMALLTAIL))
 #define replay_only(s) (REISERFS_SB(s)->s_mount_opt & (1 << REPLAYONLY))
 #define reiserfs_dont_log(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_NOLOG))
+#define reiserfs_attrs(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_ATTRS))
 #define old_format_only(s) (REISERFS_SB(s)->s_properties & (1 << REISERFS_3_5))
 #define convert_reiserfs(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_CONVERT))
 
diff -urN linux-2.5.69-bk18/include/linux/sched.h linux-2.5.69-bk19/include/linux/sched.h
--- linux-2.5.69-bk18/include/linux/sched.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/sched.h	2003-05-26 04:41:42.000000000 -0700
@@ -245,7 +245,13 @@
 	/* thread group exit support */
 	int			group_exit;
 	int			group_exit_code;
+	/* overloaded:
+	 * - notify group_exit_task when ->count is equal to notify_count
+	 * - everyone except group_exit_task is stopped during signal delivery
+	 *   of fatal signals, group_exit_task processes the signal.
+	 */
 	struct task_struct	*group_exit_task;
+	int			notify_count;
 
 	/* thread group stop support, overloads group_exit_code too */
 	int			group_stop_count;
@@ -429,6 +435,8 @@
    	u32 self_exec_id;
 /* Protection of (de-)allocation: mm, files, fs, tty */
 	spinlock_t alloc_lock;
+/* Protection of proc_dentry: nesting proc_lock, dcache_lock, write_lock_irq(&tasklist_lock); */
+	spinlock_t proc_lock;
 /* context-switch lock */
 	spinlock_t switch_lock;
 
diff -urN linux-2.5.69-bk18/include/linux/security.h linux-2.5.69-bk19/include/linux/security.h
--- linux-2.5.69-bk18/include/linux/security.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/security.h	2003-05-26 04:41:42.000000000 -0700
@@ -376,6 +376,25 @@
  * 	Check permission before removing the extended attribute
  * 	identified by @name for @dentry.
  * 	Return 0 if permission is granted.
+ * @inode_getsecurity:
+ *	Copy the extended attribute representation of the security label 
+ *	associated with @name for @dentry into @buffer.  @buffer may be 
+ *	NULL to request the size of the buffer required.  @size indicates
+ *	the size of @buffer in bytes.  Note that @name is the remainder
+ *	of the attribute name after the security. prefix has been removed.
+ *	Return number of bytes used/required on success.
+ * @inode_setsecurity:
+ *	Set the security label associated with @name for @dentry from the 
+ *	extended attribute value @value.  @size indicates the size of the
+ *	@value in bytes.  @flags may be XATTR_CREATE, XATTR_REPLACE, or 0.
+ *	Note that @name is the remainder of the attribute name after the 
+ *	security. prefix has been removed.
+ *	Return 0 on success.
+ * @inode_listsecurity:
+ *	Copy the extended attribute names for the security labels
+ *	associated with @dentry into @buffer.  @buffer may be NULL to 
+ *	request the size of the buffer required.  
+ *	Returns number of bytes used/required on success.
  *
  * Security hooks for file operations
  *
@@ -596,6 +615,11 @@
  * 	Set the security attributes in @p->security for a kernel thread that
  * 	is being reparented to the init task.
  *	@p contains the task_struct for the kernel thread.
+ * @task_to_inode:
+ * 	Set the security attributes for an inode based on an associated task's
+ * 	security attributes, e.g. for /proc/pid inodes.
+ *	@p contains the task_struct for the task.
+ *	@inode contains the inode structure for the inode.
  *
  * Security hooks for Netlink messaging.
  *
@@ -1044,6 +1068,9 @@
 	int (*inode_getxattr) (struct dentry *dentry, char *name);
 	int (*inode_listxattr) (struct dentry *dentry);
 	int (*inode_removexattr) (struct dentry *dentry, char *name);
+  	int (*inode_getsecurity)(struct dentry *dentry, const char *name, void *buffer, size_t size);
+  	int (*inode_setsecurity)(struct dentry *dentry, const char *name, const void *value, size_t size, int flags);
+  	int (*inode_listsecurity)(struct dentry *dentry, char *buffer);
 
 	int (*file_permission) (struct file * file, int mask);
 	int (*file_alloc_security) (struct file * file);
@@ -1086,6 +1113,7 @@
 			   unsigned long arg5);
 	void (*task_kmod_set_label) (void);
 	void (*task_reparent_to_init) (struct task_struct * p);
+	void (*task_to_inode)(struct task_struct *p, struct inode *inode);
 
 	int (*ipc_permission) (struct kern_ipc_perm * ipcp, short flag);
 
@@ -1128,6 +1156,9 @@
 
 	void (*d_instantiate) (struct dentry *dentry, struct inode *inode);
 
+ 	int (*getprocattr)(struct task_struct *p, char *name, void *value, size_t size);
+ 	int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size);
+
 #ifdef CONFIG_SECURITY_NETWORK
 	int (*unix_stream_connect) (struct socket * sock,
 				    struct socket * other, struct sock * newsk);
@@ -1490,6 +1521,21 @@
 	return security_ops->inode_removexattr (dentry, name);
 }
 
+static inline int security_inode_getsecurity(struct dentry *dentry, const char *name, void *buffer, size_t size)
+{
+	return security_ops->inode_getsecurity(dentry, name, buffer, size);
+}
+
+static inline int security_inode_setsecurity(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) 
+{
+	return security_ops->inode_setsecurity(dentry, name, value, size, flags);
+}
+
+static inline int security_inode_listsecurity(struct dentry *dentry, char *buffer)
+{
+	return security_ops->inode_listsecurity(dentry, buffer);
+}
+
 static inline int security_file_permission (struct file *file, int mask)
 {
 	return security_ops->file_permission (file, mask);
@@ -1656,6 +1702,11 @@
 	security_ops->task_reparent_to_init (p);
 }
 
+static inline void security_task_to_inode(struct task_struct *p, struct inode *inode)
+{
+	security_ops->task_to_inode(p, inode);
+}
+
 static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
 					   short flag)
 {
@@ -1766,6 +1817,16 @@
 	security_ops->d_instantiate (dentry, inode);
 }
 
+static inline int security_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
+{
+	return security_ops->getprocattr(p, name, value, size);
+}
+
+static inline int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
+{
+	return security_ops->setprocattr(p, name, value, size);
+}
+
 static inline int security_netlink_send(struct sk_buff * skb)
 {
 	return security_ops->netlink_send(skb);
@@ -2093,6 +2154,21 @@
 	return 0;
 }
 
+static inline int security_inode_getsecurity(struct dentry *dentry, const char *name, void *buffer, size_t size)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int security_inode_setsecurity(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) 
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int security_inode_listsecurity(struct dentry *dentry, char *buffer)
+{
+	return 0;
+}
+
 static inline int security_file_permission (struct file *file, int mask)
 {
 	return 0;
@@ -2255,6 +2331,9 @@
 	cap_task_reparent_to_init (p);
 }
 
+static inline void security_task_to_inode(struct task_struct *p, struct inode *inode)
+{ }
+
 static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
 					   short flag)
 {
@@ -2355,6 +2434,16 @@
 static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
 { }
 
+static inline int security_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
+{
+	return -EINVAL;
+}
+
+static inline int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
+{
+	return -EINVAL;
+}
+
 /*
  * The netlink capability defaults need to be used inline by default
  * (rather than hooking into the capability module) to reduce overhead
diff -urN linux-2.5.69-bk18/include/linux/skbuff.h linux-2.5.69-bk19/include/linux/skbuff.h
--- linux-2.5.69-bk18/include/linux/skbuff.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/skbuff.h	2003-05-26 04:41:42.000000000 -0700
@@ -190,6 +190,7 @@
 	struct sock		*sk;
 	struct timeval		stamp;
 	struct net_device	*dev;
+	struct net_device	*real_dev;
 
 	union {
 		struct tcphdr	*th;
diff -urN linux-2.5.69-bk18/include/linux/slab.h linux-2.5.69-bk19/include/linux/slab.h
--- linux-2.5.69-bk18/include/linux/slab.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/slab.h	2003-05-26 04:41:42.000000000 -0700
@@ -41,6 +41,8 @@
 #define SLAB_CACHE_DMA		0x00004000UL	/* use GFP_DMA memory */
 #define SLAB_MUST_HWCACHE_ALIGN	0x00008000UL	/* force alignment */
 #define SLAB_STORE_USER		0x00010000UL	/* store the last owner for bug hunting */
+#define SLAB_RECLAIM_ACCOUNT	0x00020000UL	/* track pages allocated to indicate
+						   what is reclaimable later*/
 
 /* flags passed to a constructor func */
 #define	SLAB_CTOR_CONSTRUCTOR	0x001UL		/* if not set, then deconstructor */
diff -urN linux-2.5.69-bk18/include/linux/string.h linux-2.5.69-bk19/include/linux/string.h
--- linux-2.5.69-bk18/include/linux/string.h	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/string.h	2003-05-26 04:41:42.000000000 -0700
@@ -28,12 +28,18 @@
 #ifndef __HAVE_ARCH_STRNCPY
 extern char * strncpy(char *,const char *, __kernel_size_t);
 #endif
+#ifndef __HAVE_ARCH_STRLCPY
+size_t strlcpy(char *, const char *, size_t);
+#endif
 #ifndef __HAVE_ARCH_STRCAT
 extern char * strcat(char *, const char *);
 #endif
 #ifndef __HAVE_ARCH_STRNCAT
 extern char * strncat(char *, const char *, __kernel_size_t);
 #endif
+#ifndef __HAVE_ARCH_STRLCAT
+extern size_t strlcat(char *, const char *, __kernel_size_t);
+#endif
 #ifndef __HAVE_ARCH_STRCMP
 extern int strcmp(const char *,const char *);
 #endif
diff -urN linux-2.5.69-bk18/include/linux/tty.h linux-2.5.69-bk19/include/linux/tty.h
--- linux-2.5.69-bk18/include/linux/tty.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/tty.h	2003-05-26 04:41:42.000000000 -0700
@@ -345,7 +345,6 @@
 extern void tty_write_flush(struct tty_struct *);
 
 extern struct termios tty_std_termios;
-extern struct tty_struct * redirect;
 extern struct tty_ldisc ldiscs[];
 extern int fg_console, last_console, want_console;
 
diff -urN linux-2.5.69-bk18/include/linux/tty_driver.h linux-2.5.69-bk19/include/linux/tty_driver.h
--- linux-2.5.69-bk18/include/linux/tty_driver.h	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/tty_driver.h	2003-05-26 04:41:42.000000000 -0700
@@ -117,9 +117,11 @@
 
 #include <linux/fs.h>
 #include <linux/list.h>
+#include <linux/cdev.h>
 
 struct tty_driver {
 	int	magic;		/* magic number for this structure */
+	struct cdev cdev;
 	struct module	*owner;
 	const char	*driver_name;
 	const char	*name;
diff -urN linux-2.5.69-bk18/include/linux/xfrm.h linux-2.5.69-bk19/include/linux/xfrm.h
--- linux-2.5.69-bk18/include/linux/xfrm.h	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk19/include/linux/xfrm.h	2003-05-26 04:41:42.000000000 -0700
@@ -104,19 +104,21 @@
 /* Netlink configuration messages.  */
 #define XFRM_MSG_BASE		0x10
 
-#define XFRM_MSG_NEWSA		(RTM_BASE + 0)
-#define XFRM_MSG_DELSA		(RTM_BASE + 1)
-#define XFRM_MSG_GETSA		(RTM_BASE + 2)
-
-#define XFRM_MSG_NEWPOLICY	(RTM_BASE + 3)
-#define XFRM_MSG_DELPOLICY	(RTM_BASE + 4)
-#define XFRM_MSG_GETPOLICY	(RTM_BASE + 5)
-
-#define XFRM_MSG_ALLOCSPI	(RTM_BASE + 6)
-#define XFRM_MSG_ACQUIRE	(RTM_BASE + 7)
-#define XFRM_MSG_EXPIRE		(RTM_BASE + 8)
+#define XFRM_MSG_NEWSA		(XFRM_MSG_BASE + 0)
+#define XFRM_MSG_DELSA		(XFRM_MSG_BASE + 1)
+#define XFRM_MSG_GETSA		(XFRM_MSG_BASE + 2)
 
-#define XFRM_MSG_MAX		(XFRM_MSG_EXPIRE+1)
+#define XFRM_MSG_NEWPOLICY	(XFRM_MSG_BASE + 3)
+#define XFRM_MSG_DELPOLICY	(XFRM_MSG_BASE + 4)
+#define XFRM_MSG_GETPOLICY	(XFRM_MSG_BASE + 5)
+
+#define XFRM_MSG_ALLOCSPI	(XFRM_MSG_BASE + 6)
+#define XFRM_MSG_ACQUIRE	(XFRM_MSG_BASE + 7)
+#define XFRM_MSG_EXPIRE		(XFRM_MSG_BASE + 8)
+
+#define XFRM_MSG_UPDPOLICY	(XFRM_MSG_BASE + 9)
+
+#define XFRM_MSG_MAX		(XFRM_MSG_UPDPOLICY+1)
 
 struct xfrm_user_tmpl {
 	struct xfrm_id		id;
diff -urN linux-2.5.69-bk18/include/net/irda/iriap.h linux-2.5.69-bk19/include/net/irda/iriap.h
--- linux-2.5.69-bk18/include/net/irda/iriap.h	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/include/net/irda/iriap.h	2003-05-26 04:41:42.000000000 -0700
@@ -66,7 +66,7 @@
 	__u32        daddr;
 	__u8         operation;
 
-	struct sk_buff *skb;
+	struct sk_buff *request_skb;
 	struct lsap_cb *lsap;
 	__u8 slsap_sel;
 
diff -urN linux-2.5.69-bk18/include/net/irda/irlan_common.h linux-2.5.69-bk19/include/net/irda/irlan_common.h
--- linux-2.5.69-bk18/include/net/irda/irlan_common.h	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/include/net/irda/irlan_common.h	2003-05-26 04:41:42.000000000 -0700
@@ -195,8 +195,6 @@
 struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr);
 void irlan_close(struct irlan_cb *self);
 void irlan_close_tsaps(struct irlan_cb *self);
-void irlan_mod_inc_use_count(void);
-void irlan_mod_dec_use_count(void);
 
 int  irlan_register_netdev(struct irlan_cb *self);
 void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel);
diff -urN linux-2.5.69-bk18/include/net/irda/irlmp_event.h linux-2.5.69-bk19/include/net/irda/irlmp_event.h
--- linux-2.5.69-bk18/include/net/irda/irlmp_event.h	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/include/net/irda/irlmp_event.h	2003-05-26 04:41:42.000000000 -0700
@@ -79,26 +79,6 @@
 	LM_LAP_IDLE_TIMEOUT,
 } IRLMP_EVENT;
 
-/*
- *  Information which is used by the current thread, when executing in the
- *  state machine.
- */
-struct irlmp_event {
-	IRLMP_EVENT *event;
-	struct sk_buff *skb;
-
-	__u8 hint;
-	__u32 daddr;
-	__u32 saddr;
-
-	__u8 slsap;
-	__u8 dlsap;
-
-	int reason;
-
-	struct discovery_t *discovery;
-};
-
 extern const char *irlmp_state[];
 extern const char *irlsap_state[];
 
diff -urN linux-2.5.69-bk18/include/net/irda/irport.h linux-2.5.69-bk19/include/net/irda/irport.h
--- linux-2.5.69-bk18/include/net/irda/irport.h	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/include/net/irda/irport.h	2003-05-26 04:41:42.000000000 -0700
@@ -67,6 +67,7 @@
 	__u32 new_speed;
 	int mode;
 	int index;                 /* Instance index */
+	int transmitting;	   /* Are we transmitting ? */
 
 	spinlock_t lock;           /* For serializing operations */
 
diff -urN linux-2.5.69-bk18/include/net/neighbour.h linux-2.5.69-bk19/include/net/neighbour.h
--- linux-2.5.69-bk18/include/net/neighbour.h	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk19/include/net/neighbour.h	2003-05-26 04:41:42.000000000 -0700
@@ -165,7 +165,6 @@
 	unsigned long		last_rand;
 	struct neigh_parms	*parms_list;
 	kmem_cache_t		*kmem_cachep;
-	struct tasklet_struct	gc_task;
 	struct neigh_statistics	stats;
 	struct neighbour	*hash_buckets[NEIGH_HASHMASK+1];
 	struct pneigh_entry	*phash_buckets[PNEIGH_HASHMASK+1];
diff -urN linux-2.5.69-bk18/include/net/sock.h linux-2.5.69-bk19/include/net/sock.h
--- linux-2.5.69-bk18/include/net/sock.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/net/sock.h	2003-05-26 04:41:42.000000000 -0700
@@ -944,4 +944,6 @@
 extern __u32 sysctl_wmem_max;
 extern __u32 sysctl_rmem_max;
 
+int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
+
 #endif	/* _SOCK_H */
diff -urN linux-2.5.69-bk18/include/net/tcp.h linux-2.5.69-bk19/include/net/tcp.h
--- linux-2.5.69-bk18/include/net/tcp.h	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/include/net/tcp.h	2003-05-26 04:41:42.000000000 -0700
@@ -35,6 +35,7 @@
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
 #include <linux/ipv6.h>
 #endif
+#include <linux/seq_file.h>
 
 /* This is for all connections with a full identity, no wildcards.
  * New scheme, half the table is for TIME_WAIT, the other half is
@@ -362,10 +363,6 @@
 #define MAX_TCP_KEEPCNT		127
 #define MAX_TCP_SYNCNT		127
 
-/* TIME_WAIT reaping mechanism. */
-#define TCP_TWKILL_SLOTS	8	/* Please keep this a power of 2. */
-#define TCP_TWKILL_PERIOD	(TCP_TIMEWAIT_LEN/TCP_TWKILL_SLOTS)
-
 #define TCP_SYNQ_INTERVAL	(HZ/5)	/* Period of SYNACK timer */
 #define TCP_SYNQ_HSIZE		512	/* Size of SYNACK hash table */
 
@@ -1893,4 +1890,31 @@
 	TCP_ADD_STATS_USER(TcpMaxConn, -1);
 }
 
+/* /proc */
+enum tcp_seq_states {
+	TCP_SEQ_STATE_LISTENING,
+	TCP_SEQ_STATE_OPENREQ,
+	TCP_SEQ_STATE_ESTABLISHED,
+	TCP_SEQ_STATE_TIME_WAIT,
+};
+
+struct tcp_seq_afinfo {
+	struct module		*owner;
+	char			*name;
+	sa_family_t		family;
+	int			(*seq_show) (struct seq_file *m, void *v);
+	struct file_operations	*seq_fops;
+};
+
+struct tcp_iter_state {
+	sa_family_t		family;
+	enum tcp_seq_states	state;
+	struct sock		*syn_wait_sk;
+	int			bucket, sbucket, num, uid;
+	struct seq_operations	seq_ops;
+};
+
+extern int tcp_proc_register(struct tcp_seq_afinfo *afinfo);
+extern void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo);
+
 #endif	/* _TCP_H */
diff -urN linux-2.5.69-bk18/include/net/udp.h linux-2.5.69-bk19/include/net/udp.h
--- linux-2.5.69-bk18/include/net/udp.h	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk19/include/net/udp.h	2003-05-26 04:41:42.000000000 -0700
@@ -26,6 +26,7 @@
 #include <linux/ip.h>
 #include <net/sock.h>
 #include <net/snmp.h>
+#include <linux/seq_file.h>
 
 #define UDP_HTABLE_SIZE		128
 
@@ -77,4 +78,21 @@
 #define UDP_INC_STATS_BH(field)		SNMP_INC_STATS_BH(udp_statistics, field)
 #define UDP_INC_STATS_USER(field) 	SNMP_INC_STATS_USER(udp_statistics, field)
 
+/* /proc */
+struct udp_seq_afinfo {
+	struct module		*owner;
+	char			*name;
+	sa_family_t		family;
+	int 			(*seq_show) (struct seq_file *m, void *v);
+	struct file_operations	*seq_fops;
+};
+
+struct udp_iter_state {
+	sa_family_t		family;
+	int			bucket;
+	struct seq_operations	seq_ops;
+};
+
+extern int udp_proc_register(struct udp_seq_afinfo *afinfo);
+extern void udp_proc_unregister(struct udp_seq_afinfo *afinfo);
 #endif	/* _UDP_H */
diff -urN linux-2.5.69-bk18/init/Kconfig linux-2.5.69-bk19/init/Kconfig
--- linux-2.5.69-bk18/init/Kconfig	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/init/Kconfig	2003-05-26 04:41:42.000000000 -0700
@@ -108,7 +108,31 @@
 		     13 =>  8 KB
 		     12 =>  4 KB
 
-endmenu
+
+menuconfig EMBEDDED
+	bool "Remove kernel features (for embedded systems)"
+	help
+	  This option allows certain base kernel features to be removed from
+	  the build.  This is for specialized environments which can tolerate
+	  a "non-standard" kernel.  Only use this if you really know what you
+	  are doing.
+
+config FUTEX
+	bool "Enable futex support" if EMBEDDED
+	default y
+	help
+	  Disabling this option will cause the kernel to be built without
+	  support for "fast userspace mutexes".  The resulting kernel may not
+	  run glibc-based applications correctly.
+
+config EPOLL
+	bool "Enable eventpoll support" if EMBEDDED
+	default y
+	help
+	  Disabling this option will cause the kernel to be built without
+	  support for epoll family of system calls.
+
+endmenu		# General setup
 
 
 menu "Loadable module support"
@@ -181,4 +205,3 @@
 	  in <file:Documentation/kmod.txt>.
 
 endmenu
-
diff -urN linux-2.5.69-bk18/init/do_mounts.c linux-2.5.69-bk19/init/do_mounts.c
--- linux-2.5.69-bk18/init/do_mounts.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/init/do_mounts.c	2003-05-26 04:41:42.000000000 -0700
@@ -176,7 +176,7 @@
 
 static int __init root_dev_setup(char *line)
 {
-	strncpy(saved_root_name, line, 63);
+	strlcpy(saved_root_name, line, sizeof(saved_root_name));
 	return 1;
 }
 
diff -urN linux-2.5.69-bk18/init/do_mounts_rd.c linux-2.5.69-bk19/init/do_mounts_rd.c
--- linux-2.5.69-bk18/init/do_mounts_rd.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/init/do_mounts_rd.c	2003-05-26 04:41:42.000000000 -0700
@@ -129,7 +129,7 @@
 	int in_fd, out_fd;
 	unsigned long rd_blocks, devblocks;
 	int nblocks, i, disk;
-	char *buf;
+	char *buf = NULL;
 	unsigned short rotate = 0;
 #if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES)
 	char rotator[4] = { '|' , '/' , '-' , '\\' };
@@ -226,7 +226,6 @@
 #endif
 	}
 	printk("done.\n");
-	kfree(buf);
 
 successful_load:
 	res = 1;
@@ -235,6 +234,7 @@
 noclose_input:
 	close(out_fd);
 out:
+	kfree(buf);
 	sys_unlink("/dev/ram");
 	return res;
 }
diff -urN linux-2.5.69-bk18/kernel/Makefile linux-2.5.69-bk19/kernel/Makefile
--- linux-2.5.69-bk18/kernel/Makefile	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk19/kernel/Makefile	2003-05-26 04:41:43.000000000 -0700
@@ -5,9 +5,10 @@
 obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
 	    exit.o itimer.o time.o softirq.o resource.o \
 	    sysctl.o capability.o ptrace.o timer.o user.o \
-	    signal.o sys.o kmod.o workqueue.o futex.o pid.o \
+	    signal.o sys.o kmod.o workqueue.o pid.o \
 	    rcupdate.o intermodule.o extable.o params.o posix-timers.o
 
+obj-$(CONFIG_FUTEX) += futex.o
 obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
 obj-$(CONFIG_SMP) += cpu.o
 obj-$(CONFIG_UID16) += uid16.o
diff -urN linux-2.5.69-bk18/kernel/acct.c linux-2.5.69-bk19/kernel/acct.c
--- linux-2.5.69-bk18/kernel/acct.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk19/kernel/acct.c	2003-05-26 04:41:43.000000000 -0700
@@ -323,8 +323,7 @@
 	 */
 	memset((caddr_t)&ac, 0, sizeof(struct acct));
 
-	strncpy(ac.ac_comm, current->comm, ACCT_COMM);
-	ac.ac_comm[ACCT_COMM - 1] = '\0';
+	strlcpy(ac.ac_comm, current->comm, sizeof(ac.ac_comm));
 
 	elapsed = get_jiffies_64() - current->start_time;
 	ac.ac_etime = encode_comp_t(elapsed < (unsigned long) -1l ?
diff -urN linux-2.5.69-bk18/kernel/compat.c linux-2.5.69-bk19/kernel/compat.c
--- linux-2.5.69-bk18/kernel/compat.c	2003-05-04 16:53:29.000000000 -0700
+++ linux-2.5.69-bk19/kernel/compat.c	2003-05-26 04:41:43.000000000 -0700
@@ -18,6 +18,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>	/* for MAX_SCHEDULE_TIMEOUT */
 #include <linux/futex.h>	/* for FUTEX_WAIT */
+#include <linux/unistd.h>
 
 #include <asm/uaccess.h>
 
@@ -211,21 +212,26 @@
 	return ret;
 }
 
-extern long do_futex(unsigned long, int, int, unsigned long);
-
+#ifdef CONFIG_FUTEX
 asmlinkage long compat_sys_futex(u32 *uaddr, int op, int val,
-		struct compat_timespec *utime)
+		struct compat_timespec *utime, u32 *uaddr2)
 {
 	struct timespec t;
 	unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
+	int val2 = 0;
 
 	if ((op == FUTEX_WAIT) && utime) {
 		if (get_compat_timespec(&t, utime))
 			return -EFAULT;
 		timeout = timespec_to_jiffies(&t) + 1;
 	}
-	return do_futex((unsigned long)uaddr, op, val, timeout);
+	if (op == FUTEX_REQUEUE)
+		val2 = (int) (long) utime;
+
+	return do_futex((unsigned long)uaddr, op, val, timeout,
+			(unsigned long)uaddr2, val2);
 }
+#endif
 
 asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim);
 
diff -urN linux-2.5.69-bk18/kernel/cpufreq.c linux-2.5.69-bk19/kernel/cpufreq.c
--- linux-2.5.69-bk18/kernel/cpufreq.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/kernel/cpufreq.c	2003-05-26 04:41:43.000000000 -0700
@@ -362,7 +362,7 @@
 	policy->kobj.parent = &class_dev->kobj;
 	policy->kobj.ktype = &ktype_cpufreq;
 //	policy->dev = dev->dev;
-	strncpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN);
+	strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN);
 
 	ret = kobject_register(&policy->kobj);
 	if (ret)
diff -urN linux-2.5.69-bk18/kernel/exit.c linux-2.5.69-bk19/kernel/exit.c
--- linux-2.5.69-bk18/kernel/exit.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/kernel/exit.c	2003-05-26 04:41:43.000000000 -0700
@@ -21,6 +21,7 @@
 #include <linux/ptrace.h>
 #include <linux/profile.h>
 #include <linux/mount.h>
+#include <linux/proc_fs.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -31,10 +32,8 @@
 
 int getrusage(struct task_struct *, int, struct rusage *);
 
-static struct dentry * __unhash_process(struct task_struct *p)
+static void __unhash_process(struct task_struct *p)
 {
-	struct dentry *proc_dentry;
-
 	nr_threads--;
 	detach_pid(p, PIDTYPE_PID);
 	detach_pid(p, PIDTYPE_TGID);
@@ -46,34 +45,25 @@
 	}
 
 	REMOVE_LINKS(p);
-	proc_dentry = p->proc_dentry;
-	if (unlikely(proc_dentry != NULL)) {
-		spin_lock(&dcache_lock);
-		if (!d_unhashed(proc_dentry)) {
-			dget_locked(proc_dentry);
-			__d_drop(proc_dentry);
-		} else
-			proc_dentry = NULL;
-		spin_unlock(&dcache_lock);
-	}
-	return proc_dentry;
 }
 
 void release_task(struct task_struct * p)
 {
-	struct dentry *proc_dentry;
 	task_t *leader;
+	struct dentry *proc_dentry;
  
 	BUG_ON(p->state < TASK_ZOMBIE);
  
 	atomic_dec(&p->user->processes);
+	spin_lock(&p->proc_lock);
+	proc_dentry = proc_pid_unhash(p);
 	write_lock_irq(&tasklist_lock);
 	if (unlikely(p->ptrace))
 		__ptrace_unlink(p);
 	BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children));
 	__exit_signal(p);
 	__exit_sighand(p);
-	proc_dentry = __unhash_process(p);
+	__unhash_process(p);
 
 	/*
 	 * If we are the last non-leader member of the thread
@@ -92,11 +82,8 @@
 	p->parent->cnswap += p->nswap + p->cnswap;
 	sched_exit(p);
 	write_unlock_irq(&tasklist_lock);
-
-	if (unlikely(proc_dentry != NULL)) {
-		shrink_dcache_parent(proc_dentry);
-		dput(proc_dentry);
-	}
+	spin_unlock(&p->proc_lock);
+	proc_pid_flush(proc_dentry);
 	release_thread(p);
 	put_task_struct(p);
 }
@@ -107,14 +94,13 @@
 {
 	struct dentry *proc_dentry;
 
+	spin_lock(&p->proc_lock);
+	proc_dentry = proc_pid_unhash(p);
 	write_lock_irq(&tasklist_lock);
-	proc_dentry = __unhash_process(p);
+	__unhash_process(p);
 	write_unlock_irq(&tasklist_lock);
-
-	if (unlikely(proc_dentry != NULL)) {
-		shrink_dcache_parent(proc_dentry);
-		dput(proc_dentry);
-	}
+	spin_unlock(&p->proc_lock);
+	proc_pid_flush(proc_dentry);
 }
 
 /*
diff -urN linux-2.5.69-bk18/kernel/fork.c linux-2.5.69-bk19/kernel/fork.c
--- linux-2.5.69-bk18/kernel/fork.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/kernel/fork.c	2003-05-26 04:41:43.000000000 -0700
@@ -457,7 +457,7 @@
 		 * not set up a proper pointer then tough luck.
 		 */
 		put_user(0, tidptr);
-		sys_futex(tidptr, FUTEX_WAKE, 1, NULL);
+		sys_futex(tidptr, FUTEX_WAKE, 1, NULL, NULL);
 	}
 }
 
diff -urN linux-2.5.69-bk18/kernel/futex.c linux-2.5.69-bk19/kernel/futex.c
--- linux-2.5.69-bk18/kernel/futex.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/kernel/futex.c	2003-05-26 04:41:43.000000000 -0700
@@ -2,6 +2,9 @@
  *  Fast Userspace Mutexes (which I call "Futexes!").
  *  (C) Rusty Russell, IBM 2002
  *
+ *  Generalized futexes, futex requeueing, misc fixes by Ingo Molnar
+ *  (C) Copyright 2003 Red Hat Inc, All Rights Reserved
+ *
  *  Thanks to Ben LaHaise for yelling "hashed waitqueues" loudly
  *  enough at me, Linus for the original (flawed) idea, Matthew
  *  Kirkwood for proof-of-concept implementation.
@@ -9,9 +12,6 @@
  *  "The futexes are also cursed."
  *  "But they come in a choice of three flavours!"
  *
- *  Generalized futexes for every mapping type, Ingo Molnar, 2002
- *
- *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
@@ -93,19 +93,18 @@
 							FUTEX_HASHBITS)];
 }
 
-/* Waiter either waiting in FUTEX_WAIT or poll(), or expecting signal */
-static inline void tell_waiter(struct futex_q *q)
-{
-	wake_up_all(&q->waiters);
-	if (q->filp)
-		send_sigio(&q->filp->f_owner, q->fd, POLL_IN);
-}
-
 /*
  * Get kernel address of the user page and pin it.
  *
  * Must be called with (and returns with) all futex-MM locks held.
  */
+static inline struct page *__pin_page_atomic (struct page *page)
+{
+	if (!PageReserved(page))
+		get_page(page);
+	return page;
+}
+
 static struct page *__pin_page(unsigned long addr)
 {
 	struct mm_struct *mm = current->mm;
@@ -116,11 +115,8 @@
 	 * Do a quick atomic lookup first - this is the fastpath.
 	 */
 	page = follow_page(mm, addr, 0);
-	if (likely(page != NULL)) {	
-		if (!PageReserved(page))
-			get_page(page);
-		return page;
-	}
+	if (likely(page != NULL))
+		return __pin_page_atomic(page);
 
 	/*
 	 * No luck - need to fault in the page:
@@ -150,16 +146,11 @@
 	return page;
 }
 
-static inline void unpin_page(struct page *page)
-{
-	put_page(page);
-}
-
 /*
  * Wake up all waiters hashed on the physical page that is mapped
  * to this virtual address:
  */
-static int futex_wake(unsigned long uaddr, int offset, int num)
+static inline int futex_wake(unsigned long uaddr, int offset, int num)
 {
 	struct list_head *i, *next, *head;
 	struct page *page;
@@ -181,7 +172,9 @@
 		if (this->page == page && this->offset == offset) {
 			list_del_init(i);
 			__detach_vcache(&this->vcache);
-			tell_waiter(this);
+			wake_up_all(&this->waiters);
+			if (this->filp)
+				send_sigio(&this->filp->f_owner, this->fd, POLL_IN);
 			ret++;
 			if (ret >= num)
 				break;
@@ -189,7 +182,7 @@
 	}
 
 	unlock_futex_mm();
-	unpin_page(page);
+	put_page(page);
 
 	return ret;
 }
@@ -208,7 +201,9 @@
 	spin_lock(&futex_lock);
 
 	if (!list_empty(&q->list)) {
+		put_page(q->page);
 		q->page = new_page;
+		__pin_page_atomic(new_page);
 		list_del(&q->list);
 		list_add_tail(&q->list, head);
 	}
@@ -216,6 +211,65 @@
 	spin_unlock(&futex_lock);
 }
 
+/*
+ * Requeue all waiters hashed on one physical page to another
+ * physical page.
+ */
+static inline int futex_requeue(unsigned long uaddr1, int offset1,
+	unsigned long uaddr2, int offset2, int nr_wake, int nr_requeue)
+{
+	struct list_head *i, *next, *head1, *head2;
+	struct page *page1 = NULL, *page2 = NULL;
+	int ret = 0;
+
+	lock_futex_mm();
+
+	page1 = __pin_page(uaddr1 - offset1);
+	if (!page1)
+		goto out;
+	page2 = __pin_page(uaddr2 - offset2);
+	if (!page2)
+		goto out;
+
+	head1 = hash_futex(page1, offset1);
+	head2 = hash_futex(page2, offset2);
+
+	list_for_each_safe(i, next, head1) {
+		struct futex_q *this = list_entry(i, struct futex_q, list);
+
+		if (this->page == page1 && this->offset == offset1) {
+			list_del_init(i);
+			__detach_vcache(&this->vcache);
+			if (++ret <= nr_wake) {
+				wake_up_all(&this->waiters);
+				if (this->filp)
+					send_sigio(&this->filp->f_owner,
+							this->fd, POLL_IN);
+			} else {
+				put_page(this->page);
+				__pin_page_atomic (page2);
+				list_add_tail(i, head2);
+				__attach_vcache(&this->vcache, uaddr2,
+					current->mm, futex_vcache_callback);
+				this->offset = offset2;
+				this->page = page2;
+				if (ret - nr_wake >= nr_requeue)
+					break;
+			}
+		}
+	}
+
+out:
+	unlock_futex_mm();
+
+	if (page1)
+		put_page(page1);
+	if (page2)
+		put_page(page2);
+
+	return ret;
+}
+
 static inline void __queue_me(struct futex_q *q, struct page *page,
 				unsigned long uaddr, int offset,
 				int fd, struct file *filp)
@@ -252,7 +306,7 @@
 	return ret;
 }
 
-static int futex_wait(unsigned long uaddr,
+static inline int futex_wait(unsigned long uaddr,
 		      int offset,
 		      int val,
 		      unsigned long time)
@@ -273,14 +327,17 @@
 	}
 	__queue_me(&q, page, uaddr, offset, -1, NULL);
 
-	unlock_futex_mm();
-
-	/* Page is pinned, but may no longer be in this address space. */
+	/*
+	 * Page is pinned, but may no longer be in this address space.
+	 * It cannot schedule, so we access it with the spinlock held.
+	 */
 	if (get_user(curval, (int *)uaddr) != 0) {
+		unlock_futex_mm();
 		ret = -EFAULT;
 		goto out;
 	}
 	if (curval != val) {
+		unlock_futex_mm();
 		ret = -EWOULDBLOCK;
 		goto out;
 	}
@@ -288,13 +345,15 @@
 	 * The get_user() above might fault and schedule so we
 	 * cannot just set TASK_INTERRUPTIBLE state when queueing
 	 * ourselves into the futex hash. This code thus has to
-	 * rely on the FUTEX_WAKE code doing a wakeup after removing
+	 * rely on the futex_wake() code doing a wakeup after removing
 	 * the waiter from the list.
 	 */
 	add_wait_queue(&q.waiters, &wait);
 	set_current_state(TASK_INTERRUPTIBLE);
-	if (!list_empty(&q.list))
+	if (!list_empty(&q.list)) {
+		unlock_futex_mm();
 		time = schedule_timeout(time);
+	}
 	set_current_state(TASK_RUNNING);
 	/*
 	 * NOTE: we don't remove ourselves from the waitqueue because
@@ -310,7 +369,7 @@
 	/* Were we woken up anyway? */
 	if (!unqueue_me(&q))
 		ret = 0;
-	unpin_page(page);
+	put_page(q.page);
 
 	return ret;
 }
@@ -320,7 +379,7 @@
 	struct futex_q *q = filp->private_data;
 
 	unqueue_me(q);
-	unpin_page(q->page);
+	put_page(q->page);
 	kfree(filp->private_data);
 	return 0;
 }
@@ -416,11 +475,12 @@
 	page = NULL;
 out:
 	if (page)
-		unpin_page(page);
+		put_page(page);
 	return ret;
 }
 
-long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout)
+long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout,
+		unsigned long uaddr2, int val2)
 {
 	unsigned long pos_in_page;
 	int ret;
@@ -442,28 +502,50 @@
 		/* non-zero val means F_SETOWN(getpid()) & F_SETSIG(val) */
 		ret = futex_fd(uaddr, pos_in_page, val);
 		break;
+	case FUTEX_REQUEUE:
+	{
+		unsigned long pos_in_page2 = uaddr2 % PAGE_SIZE;
+
+		/* Must be "naturally" aligned */
+		if (pos_in_page2 % sizeof(u32))
+			return -EINVAL;
+
+		ret = futex_requeue(uaddr, pos_in_page, uaddr2, pos_in_page2,
+				    val, val2);
+		break;
+	}
 	default:
-		ret = -EINVAL;
+		ret = -ENOSYS;
 	}
 	return ret;
 }
 
-asmlinkage long sys_futex(u32 __user *uaddr, int op, int val, struct timespec __user *utime)
+
+asmlinkage long sys_futex(u32 __user *uaddr, int op, int val,
+			  struct timespec __user *utime, u32 __user *uaddr2)
 {
 	struct timespec t;
 	unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
+	int val2 = 0;
 
 	if ((op == FUTEX_WAIT) && utime) {
 		if (copy_from_user(&t, utime, sizeof(t)) != 0)
 			return -EFAULT;
 		timeout = timespec_to_jiffies(&t) + 1;
 	}
-	return do_futex((unsigned long)uaddr, op, val, timeout);
+	/*
+	 * requeue parameter in 'utime' if op == FUTEX_REQUEUE.
+	 */
+	if (op == FUTEX_REQUEUE)
+		val2 = (int) (long) utime;
+
+	return do_futex((unsigned long)uaddr, op, val, timeout,
+			(unsigned long)uaddr2, val2);
 }
 
 static struct super_block *
 futexfs_get_sb(struct file_system_type *fs_type,
-	       int flags, char *dev_name, void *data)
+	       int flags, const char *dev_name, void *data)
 {
 	return get_sb_pseudo(fs_type, "futex", NULL, 0xBAD1DEA);
 }
diff -urN linux-2.5.69-bk18/kernel/signal.c linux-2.5.69-bk19/kernel/signal.c
--- linux-2.5.69-bk18/kernel/signal.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/kernel/signal.c	2003-05-26 04:41:43.000000000 -0700
@@ -336,7 +336,7 @@
 		 * If there is any task waiting for the group exit
 		 * then notify it:
 		 */
-		if (sig->group_exit_task && atomic_read(&sig->count) <= 2) {
+		if (sig->group_exit_task && atomic_read(&sig->count) == sig->notify_count) {
 			wake_up_process(sig->group_exit_task);
 			sig->group_exit_task = NULL;
 		}
@@ -1346,6 +1346,9 @@
 	spin_unlock_irqrestore(&sighand->siglock, flags);
 }
 
+
+#ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
+
 static void
 finish_stop(int stop_count)
 {
@@ -1460,9 +1463,6 @@
 	finish_stop(stop_count);
 }
 
-
-#ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
-
 /*
  * Do appropriate magic when group_stop_count > 0.
  * We return nonzero if we stopped, after releasing the siglock.
diff -urN linux-2.5.69-bk18/kernel/sys.c linux-2.5.69-bk19/kernel/sys.c
--- linux-2.5.69-bk18/kernel/sys.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/kernel/sys.c	2003-05-26 04:41:43.000000000 -0700
@@ -226,6 +226,11 @@
 cond_syscall(sys_sendmsg)
 cond_syscall(sys_recvmsg)
 cond_syscall(sys_socketcall)
+cond_syscall(sys_futex)
+cond_syscall(compat_sys_futex)
+cond_syscall(sys_epoll_create)
+cond_syscall(sys_epoll_ctl)
+cond_syscall(sys_epoll_wait)
 
 static int set_one_prio(struct task_struct *p, int niceval, int error)
 {
diff -urN linux-2.5.69-bk18/lib/string.c linux-2.5.69-bk19/lib/string.c
--- linux-2.5.69-bk18/lib/string.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/lib/string.c	2003-05-26 04:41:43.000000000 -0700
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
+#include <linux/module.h>
 
 #ifndef __HAVE_ARCH_STRNICMP
 /**
@@ -94,6 +95,32 @@
 }
 #endif
 
+#ifndef __HAVE_ARCH_STRLCPY
+/**
+ * strlcpy - Copy a %NUL terminated string into a sized buffer
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @size: size of destination buffer
+ *
+ * Compatible with *BSD: the result is always a valid
+ * NUL-terminated string that fits in the buffer (unless,
+ * of course, the buffer size is zero). It does not pad
+ * out the result like strncpy() does.
+ */
+size_t strlcpy(char *dest, const char *src, size_t size)
+{
+	size_t ret = strlen(src);
+
+	if (size) {
+		size_t len = (ret >= size) ? size-1 : ret;
+		memcpy(dest, src, len);
+		dest[len] = '\0';
+	}
+	return ret;
+}
+EXPORT_SYMBOL(strlcpy);
+#endif
+
 #ifndef __HAVE_ARCH_STRCAT
 /**
  * strcat - Append one %NUL-terminated string to another
@@ -142,6 +169,33 @@
 }
 #endif
 
+#ifndef __HAVE_ARCH_STRLCAT
+/**
+ * strlcat - Append a length-limited, %NUL-terminated string to another
+ * @dest: The string to be appended to
+ * @src: The string to append to it
+ * @count: The size of the destination buffer.
+ */
+size_t strlcat(char *dest, const char *src, size_t count)
+{
+	size_t dsize = strlen(dest);
+	size_t len = strlen(src);
+	size_t res = dsize + len;
+
+	/* This would be a bug */
+	BUG_ON(dsize >= count);
+
+	dest += dsize;
+	count -= dsize;
+	if (len >= count)
+		len = count-1;
+	memcpy(dest, src, len);
+	dest[len] = 0;
+	return res;
+}
+EXPORT_SYMBOL(strlcat);
+#endif
+
 #ifndef __HAVE_ARCH_STRCMP
 /**
  * strcmp - Compare two strings
diff -urN linux-2.5.69-bk18/mm/fremap.c linux-2.5.69-bk19/mm/fremap.c
--- linux-2.5.69-bk18/mm/fremap.c	2003-05-04 16:52:49.000000000 -0700
+++ linux-2.5.69-bk19/mm/fremap.c	2003-05-26 04:41:43.000000000 -0700
@@ -84,7 +84,7 @@
 	pte_unmap(pte);
 	if (flush)
 		flush_tlb_page(vma, addr);
-
+	update_mmu_cache(vma, addr, *pte);
 	spin_unlock(&mm->page_table_lock);
 	pte_chain_free(pte_chain);
 	return 0;
diff -urN linux-2.5.69-bk18/mm/mmap.c linux-2.5.69-bk19/mm/mmap.c
--- linux-2.5.69-bk18/mm/mmap.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/mm/mmap.c	2003-05-26 04:41:43.000000000 -0700
@@ -64,6 +64,7 @@
  * Strict overcommit modes added 2002 Feb 26 by Alan Cox.
  * Additional code 2002 Jul 20 by Robert Love.
  */
+extern atomic_t slab_reclaim_pages;
 int vm_enough_memory(long pages)
 {
 	unsigned long free, allowed;
@@ -82,17 +83,19 @@
 		free += nr_swap_pages;
 
 		/*
-		 * The code below doesn't account for free space in the
-		 * inode and dentry slab cache, slab cache fragmentation,
-		 * inodes and dentries which will become freeable under
-		 * VM load, etc. Lets just hope all these (complex)
-		 * factors balance out...
+		 * Any slabs which are created with the
+		 * SLAB_RECLAIM_ACCOUNT flag claim to have contents
+		 * which are reclaimable, under pressure.  The dentry
+		 * cache and most inode caches should fall into this
 		 */
-		free += (dentry_stat.nr_unused * sizeof(struct dentry)) >>
-			PAGE_SHIFT;
-		free += (inodes_stat.nr_unused * sizeof(struct inode)) >>
-			PAGE_SHIFT;
+		free += atomic_read(&slab_reclaim_pages);
 
+		/*
+		 * Leave the last 3% for root
+		 */
+		if (!capable(CAP_SYS_ADMIN))
+			free -= free / 32;
+		
 		if (free > pages)
 			return 1;
 		vm_unacct_memory(pages);
@@ -831,7 +834,7 @@
 			 * reserved hugepage range.  For some archs like IA-64,
 			 * there is a separate region for hugepages.
 			 */
-			ret = check_valid_hugepage_range(addr, len);
+			ret = is_hugepage_only_range(addr, len);
 		}
 		if (ret)
 			return ret;
diff -urN linux-2.5.69-bk18/mm/nommu.c linux-2.5.69-bk19/mm/nommu.c
--- linux-2.5.69-bk18/mm/nommu.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/mm/nommu.c	2003-05-26 04:41:43.000000000 -0700
@@ -4,7 +4,7 @@
  *  Replacement code for mm functions to support CPU's that don't
  *  have any form of memory management unit (thus no virtual memory).
  *
- *  Copyright (c) 2000-2002 David McCullough <davidm@snapgear.com>
+ *  Copyright (c) 2000-2003 David McCullough <davidm@snapgear.com>
  *  Copyright (c) 2000-2001 D Jeff Dionne <jeff@uClinux.org>
  *  Copyright (c) 2002      Greg Ungerer <gerg@snapgear.com>
  */
@@ -30,6 +30,8 @@
 unsigned long num_physpages;
 unsigned long askedalloc, realalloc;
 atomic_t vm_committed_space = ATOMIC_INIT(0);
+int sysctl_overcommit_memory = 0; /* default is heuristic overcommit */
+int sysctl_overcommit_ratio = 50; /* default is 50% */
 
 /*
  * Handle all mappings that got truncated by a "truncate()"
@@ -102,6 +104,7 @@
 	struct page **pages, struct vm_area_struct **vmas)
 {
 	int i;
+	static struct vm_area_struct dummy_vma;
 
 	for (i = 0; i < len; i++) {
 		if (pages) {
@@ -109,6 +112,8 @@
 			if (pages[i])
 				page_cache_get(pages[i]);
 		}
+		if (vmas)
+			vmas[i] = &dummy_vma;
 		start += PAGE_SIZE;
 	}
 	return(i);
@@ -180,7 +185,7 @@
 	return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL);
 }
 
-void *vmap(struct page **pages, unsigned int count)
+void *vmap(struct page **pages, unsigned int count, unsigned long flags, pgprot_t prot)
 {
 	BUG();
 	return NULL;
diff -urN linux-2.5.69-bk18/mm/shmem.c linux-2.5.69-bk19/mm/shmem.c
--- linux-2.5.69-bk18/mm/shmem.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/mm/shmem.c	2003-05-26 04:41:43.000000000 -0700
@@ -1647,7 +1647,8 @@
 }
 #endif
 
-static int shmem_fill_super(struct super_block *sb, void *data, int silent)
+static int shmem_fill_super(struct super_block *sb,
+			    void *data, int silent)
 {
 	struct inode *inode;
 	struct dentry *root;
@@ -1744,7 +1745,7 @@
 {
 	shmem_inode_cachep = kmem_cache_create("shmem_inode_cache",
 					     sizeof(struct shmem_inode_info),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (shmem_inode_cachep == NULL)
 		return -ENOMEM;
@@ -1814,7 +1815,7 @@
 };
 
 static struct super_block *shmem_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_nodev(fs_type, flags, data, shmem_fill_super);
 }
diff -urN linux-2.5.69-bk18/mm/slab.c linux-2.5.69-bk19/mm/slab.c
--- linux-2.5.69-bk18/mm/slab.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/mm/slab.c	2003-05-26 04:41:43.000000000 -0700
@@ -116,10 +116,12 @@
 # define CREATE_MASK	(SLAB_DEBUG_INITIAL | SLAB_RED_ZONE | \
 			 SLAB_POISON | SLAB_HWCACHE_ALIGN | \
 			 SLAB_NO_REAP | SLAB_CACHE_DMA | \
-			 SLAB_MUST_HWCACHE_ALIGN | SLAB_STORE_USER)
+			 SLAB_MUST_HWCACHE_ALIGN | SLAB_STORE_USER | \
+			 SLAB_RECLAIM_ACCOUNT )
 #else
 # define CREATE_MASK	(SLAB_HWCACHE_ALIGN | SLAB_NO_REAP | \
-			 SLAB_CACHE_DMA | SLAB_MUST_HWCACHE_ALIGN)
+			 SLAB_CACHE_DMA | SLAB_MUST_HWCACHE_ALIGN | \
+			 SLAB_RECLAIM_ACCOUNT)
 #endif
 
 /*
@@ -420,6 +422,14 @@
 struct list_head cache_chain;
 
 /*
+ * vm_enough_memory() looks at this to determine how many
+ * slab-allocated pages are possibly freeable under pressure
+ *
+ * SLAB_RECLAIM_ACCOUNT turns this on per-slab
+ */
+atomic_t slab_reclaim_pages;
+
+/*
  * chicken and egg problem: delay the per-cpu array allocation
  * until the general caches are up.
  */
@@ -720,6 +730,8 @@
 	 * would be relatively rare and ignorable.
 	 */
 	flags |= cachep->gfpflags;
+	if ( cachep->flags & SLAB_RECLAIM_ACCOUNT) 
+		atomic_add(1<<cachep->gfporder, &slab_reclaim_pages);
 	addr = (void*) __get_free_pages(flags, cachep->gfporder);
 	/* Assume that now we have the pages no one else can legally
 	 * messes with the 'struct page's.
@@ -750,6 +762,8 @@
 	if (current->reclaim_state)
 		current->reclaim_state->reclaimed_slab += nr_freed;
 	free_pages((unsigned long)addr, cachep->gfporder);
+	if (cachep->flags & SLAB_RECLAIM_ACCOUNT) 
+		atomic_sub(1<<cachep->gfporder, &slab_reclaim_pages);
 }
 
 #if DEBUG
diff -urN linux-2.5.69-bk18/net/atm/mpoa_proc.c linux-2.5.69-bk19/net/atm/mpoa_proc.c
--- linux-2.5.69-bk18/net/atm/mpoa_proc.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/net/atm/mpoa_proc.c	2003-05-26 04:41:43.000000000 -0700
@@ -223,7 +223,7 @@
 	int value[5];
         
         memset(&qos, 0, sizeof(struct atm_qos));
-        strncpy(cmd, buff, 3);
+        strlcpy(cmd, buff, sizeof(cmd));
         if( strncmp(cmd,"add", 3) &&  strncmp(cmd,"del", 3))
 	        return 0;  /* not add or del */
 
diff -urN linux-2.5.69-bk18/net/ax25/af_ax25.c linux-2.5.69-bk19/net/ax25/af_ax25.c
--- linux-2.5.69-bk18/net/ax25/af_ax25.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/net/ax25/af_ax25.c	2003-05-26 04:41:43.000000000 -0700
@@ -743,9 +743,8 @@
 		ax25_dev = ax25->ax25_dev;
 
 		if (ax25_dev != NULL && ax25_dev->dev != NULL) {
-			strncpy(devname, ax25_dev->dev->name, IFNAMSIZ);
-			length = min_t(unsigned int, strlen(ax25_dev->dev->name)+1, maxlen);
-			devname[length-1] = '\0';
+			strlcpy(devname, ax25_dev->dev->name, sizeof(devname));
+			length = strlen(devname) + 1;
 		} else {
 			*devname = '\0';
 			length = 1;
diff -urN linux-2.5.69-bk18/net/bridge/br_forward.c linux-2.5.69-bk19/net/bridge/br_forward.c
--- linux-2.5.69-bk18/net/bridge/br_forward.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/net/bridge/br_forward.c	2003-05-26 04:41:43.000000000 -0700
@@ -34,7 +34,7 @@
 int br_dev_queue_push_xmit(struct sk_buff *skb)
 {
 #ifdef CONFIG_NETFILTER
-	/* FIXME: skb bas not been linearized: is this valid?? --RR */
+	/* ip_refrag calls ip_fragment, which doesn't copy the MAC header. */
 	if (skb->nf_bridge)
 		memcpy(skb->data - 16, skb->nf_bridge->hh, 16);
 #endif
diff -urN linux-2.5.69-bk18/net/bridge/br_if.c linux-2.5.69-bk19/net/bridge/br_if.c
--- linux-2.5.69-bk18/net/bridge/br_if.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/net/bridge/br_if.c	2003-05-26 04:41:43.000000000 -0700
@@ -84,7 +84,7 @@
 	memset(br, 0, sizeof(*br));
 	dev = &br->dev;
 
-	strncpy(dev->name, name, IFNAMSIZ);
+	strlcpy(dev->name, name, sizeof(dev->name));
 	dev->priv = br;
 	dev->priv_flags = IFF_EBRIDGE;
 	ether_setup(dev);
diff -urN linux-2.5.69-bk18/net/bridge/br_netfilter.c linux-2.5.69-bk19/net/bridge/br_netfilter.c
--- linux-2.5.69-bk18/net/bridge/br_netfilter.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/net/bridge/br_netfilter.c	2003-05-26 04:41:43.000000000 -0700
@@ -468,8 +468,7 @@
 	struct sk_buff *skb = *pskb;
 	struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge;
 
-	/* FIXME: skb as not been linearized.  Is this still true? --RR */
-	/* Be very paranoid.  */
+	/* Be very paranoid. Must be a device driver bug. */
 	if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) {
 		printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: "
 				 "bad mac.raw pointer.");
diff -urN linux-2.5.69-bk18/net/bridge/netfilter/ebt_arp.c linux-2.5.69-bk19/net/bridge/netfilter/ebt_arp.c
--- linux-2.5.69-bk18/net/bridge/netfilter/ebt_arp.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/net/bridge/netfilter/ebt_arp.c	2003-05-26 04:41:43.000000000 -0700
@@ -19,89 +19,72 @@
    const struct net_device *out, const void *data, unsigned int datalen)
 {
 	struct ebt_arp_info *info = (struct ebt_arp_info *)data;
+	struct arphdr arph;
 
+	if (skb_copy_bits(skb, 0, &arph, sizeof(arph)))
+		return EBT_NOMATCH;
 	if (info->bitmask & EBT_ARP_OPCODE && FWINV(info->opcode !=
-	   ((*skb).nh.arph)->ar_op, EBT_ARP_OPCODE))
+	   arph.ar_op, EBT_ARP_OPCODE))
 		return EBT_NOMATCH;
 	if (info->bitmask & EBT_ARP_HTYPE && FWINV(info->htype !=
-	   ((*skb).nh.arph)->ar_hrd, EBT_ARP_HTYPE))
+	   arph.ar_hrd, EBT_ARP_HTYPE))
 		return EBT_NOMATCH;
 	if (info->bitmask & EBT_ARP_PTYPE && FWINV(info->ptype !=
-	   ((*skb).nh.arph)->ar_pro, EBT_ARP_PTYPE))
+	   arph.ar_pro, EBT_ARP_PTYPE))
 		return EBT_NOMATCH;
 
-	if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP))
-	{
-		uint32_t arp_len = sizeof(struct arphdr) +
-		   (2 * (((*skb).nh.arph)->ar_hln)) +
-		   (2 * (((*skb).nh.arph)->ar_pln));
-		uint32_t dst;
-		uint32_t src;
+	if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) {
+		uint32_t addr;
 
-		/* Make sure the packet is long enough */
-		if ((((*skb).nh.raw) + arp_len) > (*skb).tail)
-			return EBT_NOMATCH;
 		/* IPv4 addresses are always 4 bytes */
-		if (((*skb).nh.arph)->ar_pln != sizeof(uint32_t))
+		if (arph.ar_pln != sizeof(uint32_t))
 			return EBT_NOMATCH;
-
 		if (info->bitmask & EBT_ARP_SRC_IP) {
-			memcpy(&src, ((*skb).nh.raw) + sizeof(struct arphdr) +
-			   ((*skb).nh.arph)->ar_hln, sizeof(uint32_t));
-			if (FWINV(info->saddr != (src & info->smsk),
+			if (skb_copy_bits(skb, sizeof(struct arphdr) +
+			    arph.ar_hln, &addr, sizeof(addr)))
+				return EBT_NOMATCH;
+			if (FWINV(info->saddr != (addr & info->smsk),
 			   EBT_ARP_SRC_IP))
 				return EBT_NOMATCH;
 		}
 
 		if (info->bitmask & EBT_ARP_DST_IP) {
-			memcpy(&dst, ((*skb).nh.raw)+sizeof(struct arphdr) +
-			   (2*(((*skb).nh.arph)->ar_hln)) +
-			   (((*skb).nh.arph)->ar_pln), sizeof(uint32_t));
-			if (FWINV(info->daddr != (dst & info->dmsk),
+			if (skb_copy_bits(skb, sizeof(struct arphdr) +
+			    2*arph.ar_hln + sizeof(uint32_t), &addr,
+			    sizeof(addr)))
+				return EBT_NOMATCH;
+			if (FWINV(info->daddr != (addr & info->dmsk),
 			   EBT_ARP_DST_IP))
 				return EBT_NOMATCH;
 		}
 	}
 
-	if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC))
-	{
-		uint32_t arp_len = sizeof(struct arphdr) +
-		   (2 * (((*skb).nh.arph)->ar_hln)) +
-		   (2 * (((*skb).nh.arph)->ar_pln));
-		unsigned char dst[ETH_ALEN];
-		unsigned char src[ETH_ALEN];
+	if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) {
+		unsigned char mac[ETH_ALEN];
+		uint8_t verdict, i;
 
-		/* Make sure the packet is long enough */
-		if ((((*skb).nh.raw) + arp_len) > (*skb).tail)
-			return EBT_NOMATCH;
 		/* MAC addresses are 6 bytes */
-		if (((*skb).nh.arph)->ar_hln != ETH_ALEN)
+		if (arph.ar_hln != ETH_ALEN)
 			return EBT_NOMATCH;
 		if (info->bitmask & EBT_ARP_SRC_MAC) {
-			uint8_t verdict, i;
-
-			memcpy(&src, ((*skb).nh.raw) +
-					sizeof(struct arphdr),
-					ETH_ALEN);
+			if (skb_copy_bits(skb, sizeof(struct arphdr), &mac,
+			    ETH_ALEN))
+				return EBT_NOMATCH;
 			verdict = 0;
 			for (i = 0; i < 6; i++)
-				verdict |= (src[i] ^ info->smaddr[i]) &
+				verdict |= (mac[i] ^ info->smaddr[i]) &
 				       info->smmsk[i];
 			if (FWINV(verdict != 0, EBT_ARP_SRC_MAC))
 				return EBT_NOMATCH;
 		}
 
 		if (info->bitmask & EBT_ARP_DST_MAC) {
-			uint8_t verdict, i;
-
-			memcpy(&dst, ((*skb).nh.raw) +
-					sizeof(struct arphdr) +
-			   		(((*skb).nh.arph)->ar_hln) +
-			   		(((*skb).nh.arph)->ar_pln),
-					ETH_ALEN);
+			if (skb_copy_bits(skb, sizeof(struct arphdr) +
+			    arph.ar_hln + arph.ar_pln, &mac, ETH_ALEN))
+				return EBT_NOMATCH;
 			verdict = 0;
 			for (i = 0; i < 6; i++)
-				verdict |= (dst[i] ^ info->dmaddr[i]) &
+				verdict |= (mac[i] ^ info->dmaddr[i]) &
 					info->dmmsk[i];
 			if (FWINV(verdict != 0, EBT_ARP_DST_MAC))
 				return EBT_NOMATCH;
diff -urN linux-2.5.69-bk18/net/bridge/netfilter/ebt_ip.c linux-2.5.69-bk19/net/bridge/netfilter/ebt_ip.c
--- linux-2.5.69-bk18/net/bridge/netfilter/ebt_ip.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/net/bridge/netfilter/ebt_ip.c	2003-05-26 04:41:43.000000000 -0700
@@ -23,53 +23,50 @@
 	uint16_t dst;
 };
 
-union h_u {
-	unsigned char *raw;
-	struct tcpudphdr *tuh;
-};
-
 static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in,
    const struct net_device *out, const void *data,
    unsigned int datalen)
 {
 	struct ebt_ip_info *info = (struct ebt_ip_info *)data;
+	union {struct iphdr iph; struct tcpudphdr ports;} u;
 
+	if (skb_copy_bits(skb, 0, &u.iph, sizeof(u.iph)))
+		return EBT_NOMATCH;
 	if (info->bitmask & EBT_IP_TOS &&
-	   FWINV(info->tos != ((*skb).nh.iph)->tos, EBT_IP_TOS))
+	   FWINV(info->tos != u.iph.tos, EBT_IP_TOS))
 		return EBT_NOMATCH;
-	if (info->bitmask & EBT_IP_PROTO) {
-		if (FWINV(info->protocol != ((*skb).nh.iph)->protocol,
-		          EBT_IP_PROTO))
-			return EBT_NOMATCH;
-		if ( info->protocol == IPPROTO_TCP ||
-		     info->protocol == IPPROTO_UDP )
-		{
-			union h_u h;
-			h.raw = skb->data + skb->nh.iph->ihl*4;
-			if (info->bitmask & EBT_IP_DPORT) {
-				uint16_t port = ntohs(h.tuh->dst);
-				if (FWINV(port < info->dport[0] ||
-				          port > info->dport[1],
-				          EBT_IP_DPORT))
-				return EBT_NOMATCH;
-			}
-			if (info->bitmask & EBT_IP_SPORT) {
-				uint16_t port = ntohs(h.tuh->src);
-				if (FWINV(port < info->sport[0] ||
-				          port > info->sport[1],
-				          EBT_IP_SPORT))
-				return EBT_NOMATCH;
-			}
-		}
-	}
 	if (info->bitmask & EBT_IP_SOURCE &&
-	   FWINV((((*skb).nh.iph)->saddr & info->smsk) !=
+	   FWINV((u.iph.saddr & info->smsk) !=
 	   info->saddr, EBT_IP_SOURCE))
 		return EBT_NOMATCH;
 	if ((info->bitmask & EBT_IP_DEST) &&
-	   FWINV((((*skb).nh.iph)->daddr & info->dmsk) !=
+	   FWINV((u.iph.daddr & info->dmsk) !=
 	   info->daddr, EBT_IP_DEST))
 		return EBT_NOMATCH;
+	if (info->bitmask & EBT_IP_PROTO) {
+		if (FWINV(info->protocol != u.iph.protocol, EBT_IP_PROTO))
+			return EBT_NOMATCH;
+		if (!(info->bitmask & EBT_IP_DPORT) &&
+		    !(info->bitmask & EBT_IP_SPORT))
+			return EBT_MATCH;
+		if (skb_copy_bits(skb, u.iph.ihl*4, &u.ports,
+		    sizeof(u.ports)))
+			return EBT_NOMATCH;
+		if (info->bitmask & EBT_IP_DPORT) {
+			u.ports.dst = ntohs(u.ports.dst);
+			if (FWINV(u.ports.dst < info->dport[0] ||
+			          u.ports.dst > info->dport[1],
+			          EBT_IP_DPORT))
+			return EBT_NOMATCH;
+		}
+		if (info->bitmask & EBT_IP_SPORT) {
+			u.ports.src = ntohs(u.ports.src);
+			if (FWINV(u.ports.src < info->sport[0] ||
+			          u.ports.src > info->sport[1],
+			          EBT_IP_SPORT))
+			return EBT_NOMATCH;
+		}
+	}
 	return EBT_MATCH;
 }
 
@@ -86,7 +83,7 @@
 	if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK)
 		return -EINVAL;
 	if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) {
-		if (info->bitmask & EBT_IPROTO)
+		if (info->invflags & EBT_IP_PROTO)
 			return -EINVAL;
 		if (info->protocol != IPPROTO_TCP &&
 		    info->protocol != IPPROTO_UDP)
diff -urN linux-2.5.69-bk18/net/bridge/netfilter/ebt_log.c linux-2.5.69-bk19/net/bridge/netfilter/ebt_log.c
--- linux-2.5.69-bk18/net/bridge/netfilter/ebt_log.c	2003-05-04 16:53:34.000000000 -0700
+++ linux-2.5.69-bk19/net/bridge/netfilter/ebt_log.c	2003-05-26 04:41:43.000000000 -0700
@@ -32,48 +32,105 @@
 	return 0;
 }
 
+struct tcpudphdr
+{
+	uint16_t src;
+	uint16_t dst;
+};
+
+struct arppayload
+{
+	unsigned char mac_src[ETH_ALEN];
+	unsigned char ip_src[4];
+	unsigned char mac_dst[ETH_ALEN];
+	unsigned char ip_dst[4];
+};
+
+static void print_MAC(unsigned char *p)
+{
+	int i;
+
+	for (i = 0; i < ETH_ALEN; i++, p++)
+		printk("%02x%c", *p, i == ETH_ALEN - 1 ? ' ':':');
+}
+
+#define myNIPQUAD(a) a[0], a[1], a[2], a[3]
 static void ebt_log(const struct sk_buff *skb, const struct net_device *in,
    const struct net_device *out, const void *data, unsigned int datalen)
 {
 	struct ebt_log_info *info = (struct ebt_log_info *)data;
 	char level_string[4] = "< >";
-	level_string[1] = '0' + info->loglevel;
+	union {struct iphdr iph; struct tcpudphdr ports;
+	       struct arphdr arph; struct arppayload arpp;} u;
 
+	level_string[1] = '0' + info->loglevel;
 	spin_lock_bh(&ebt_log_lock);
 	printk(level_string);
 	printk("%s IN=%s OUT=%s ", info->prefix, in ? in->name : "",
 	   out ? out->name : "");
 
-	if (skb->dev->hard_header_len) {
-		int i;
-		unsigned char *p = (skb->mac.ethernet)->h_source;
-
-		printk("MAC source = ");
-		for (i = 0; i < ETH_ALEN; i++,p++)
-			printk("%02x%c", *p, i == ETH_ALEN - 1 ? ' ':':');
-		printk("MAC dest = ");
-		p = (skb->mac.ethernet)->h_dest;
-		for (i = 0; i < ETH_ALEN; i++,p++)
-			printk("%02x%c", *p, i == ETH_ALEN - 1 ? ' ':':');
-	}
+	printk("MAC source = ");
+	print_MAC((skb->mac.ethernet)->h_source);
+	printk("MAC dest = ");
+	print_MAC((skb->mac.ethernet)->h_dest);
+
 	printk("proto = 0x%04x", ntohs(((*skb).mac.ethernet)->h_proto));
 
 	if ((info->bitmask & EBT_LOG_IP) && skb->mac.ethernet->h_proto ==
 	   htons(ETH_P_IP)){
-		struct iphdr *iph = skb->nh.iph;
+		if (skb_copy_bits(skb, 0, &u.iph, sizeof(u.iph))) {
+			printk(" INCOMPLETE IP header");
+			goto out;
+		}
 		printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u,",
-		   NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
-		printk(" IP tos=0x%02X, IP proto=%d", iph->tos, iph->protocol);
+		   NIPQUAD(u.iph.saddr), NIPQUAD(u.iph.daddr));
+		printk(" IP tos=0x%02X, IP proto=%d", u.iph.tos,
+		       u.iph.protocol);
+		if (u.iph.protocol == IPPROTO_TCP ||
+		    u.iph.protocol == IPPROTO_UDP) {
+			if (skb_copy_bits(skb, u.iph.ihl*4, &u.ports,
+			    sizeof(u.ports))) {
+				printk(" INCOMPLETE TCP/UDP header");
+				goto out;
+			}
+			printk(" SPT=%u DPT=%u", ntohs(u.ports.src),
+			   ntohs(u.ports.dst));
+		}
+		goto out;
 	}
 
 	if ((info->bitmask & EBT_LOG_ARP) &&
 	    ((skb->mac.ethernet->h_proto == __constant_htons(ETH_P_ARP)) ||
 	    (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_RARP)))) {
-		struct arphdr * arph = skb->nh.arph;
+		if (skb_copy_bits(skb, 0, &u.arph, sizeof(u.arph))) {
+			printk(" INCOMPLETE ARP header");
+			goto out;
+		}
 		printk(" ARP HTYPE=%d, PTYPE=0x%04x, OPCODE=%d",
-		   ntohs(arph->ar_hrd), ntohs(arph->ar_pro),
-		   ntohs(arph->ar_op));
+		       ntohs(u.arph.ar_hrd), ntohs(u.arph.ar_pro),
+		       ntohs(u.arph.ar_op));
+
+		/* If it's for Ethernet and the lengths are OK,
+		 * then log the ARP payload */
+		if (u.arph.ar_hrd == __constant_htons(1) &&
+		    u.arph.ar_hln == ETH_ALEN &&
+		    u.arph.ar_pln == sizeof(uint32_t)) {
+			if (skb_copy_bits(skb, sizeof(u.arph), &u.arpp,
+			    sizeof(u.arpp))) {
+				printk(" INCOMPLETE ARP payload");
+				goto out;
+			}
+			printk(" ARP MAC SRC=");
+			print_MAC(u.arpp.mac_src);
+			printk(" ARP IP SRC=%u.%u.%u.%u",
+			       myNIPQUAD(u.arpp.ip_src));
+			printk(" ARP MAC DST=");
+			print_MAC(u.arpp.mac_dst);
+			printk(" ARP IP DST=%u.%u.%u.%u",
+			       myNIPQUAD(u.arpp.ip_dst));
+		}
 	}
+out:
 	printk("\n");
 	spin_unlock_bh(&ebt_log_lock);
 }
diff -urN linux-2.5.69-bk18/net/bridge/netfilter/ebt_vlan.c linux-2.5.69-bk19/net/bridge/netfilter/ebt_vlan.c
--- linux-2.5.69-bk18/net/bridge/netfilter/ebt_vlan.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk19/net/bridge/netfilter/ebt_vlan.c	2003-05-26 04:41:43.000000000 -0700
@@ -2,17 +2,17 @@
  * Description: EBTables 802.1Q match extension kernelspace module.
  * Authors: Nick Fedchik <nick@fedchik.org.ua>
  *          Bart De Schuymer <bdschuym@pandora.be>
- *    
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *  
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
@@ -39,92 +39,53 @@
 #define INV_FLAG(_inv_flag_) (info->invflags & _inv_flag_) ? "!" : ""
 #define GET_BITMASK(_BIT_MASK_) info->bitmask & _BIT_MASK_
 #define SET_BITMASK(_BIT_MASK_) info->bitmask |= _BIT_MASK_
-#define EXIT_ON_MISMATCH(_MATCH_,_MASK_) if (!((info->_MATCH_ == _MATCH_)^!!(info->invflags & _MASK_))) return 1;
+#define EXIT_ON_MISMATCH(_MATCH_,_MASK_) {if (!((info->_MATCH_ == _MATCH_)^!!(info->invflags & _MASK_))) return EBT_NOMATCH;}
 
-/*
- * Function description: ebt_filter_vlan() is main engine for 
- * checking passed 802.1Q frame according to 
- * the passed extension parameters (in the *data buffer)
- * ebt_filter_vlan() is called after successful check the rule params
- * by ebt_check_vlan() function.
- * Parameters:
- * const struct sk_buff *skb - pointer to passed ethernet frame buffer
- * const void *data - pointer to passed extension parameters
- * unsigned int datalen - length of passed *data buffer
- * const struct net_device *in  -
- * const struct net_device *out -
- * const struct ebt_counter *c -
- * Returned values:
- * 0 - ok (all rule params matched)
- * 1 - miss (rule params not acceptable to the parsed frame)
- */
 static int
 ebt_filter_vlan(const struct sk_buff *skb,
 		const struct net_device *in,
 		const struct net_device *out,
 		const void *data, unsigned int datalen)
 {
-	struct ebt_vlan_info *info = (struct ebt_vlan_info *) data;	/* userspace data */
-	struct vlan_ethhdr *frame = (struct vlan_ethhdr *) skb->mac.raw;	/* Passed tagged frame */
+	struct ebt_vlan_info *info = (struct ebt_vlan_info *) data;
+	struct vlan_ethhdr frame;
 
 	unsigned short TCI;	/* Whole TCI, given from parsed frame */
 	unsigned short id;	/* VLAN ID, given from frame TCI */
 	unsigned char prio;	/* user_priority, given from frame TCI */
-	unsigned short encap;	/* VLAN encapsulated Type/Length field, given from orig frame */
+	/* VLAN encapsulated Type/Length field, given from orig frame */
+	unsigned short encap;
 
-	/*
-	 * Tag Control Information (TCI) consists of the following elements:
-	 * - User_priority. The user_priority field is three bits in length, 
-	 * interpreted as a binary number. 
-	 * - Canonical Format Indicator (CFI). The Canonical Format Indicator 
+	if (skb_copy_bits(skb, 0, &frame, sizeof(frame)))
+		return EBT_NOMATCH;
+
+	/* Tag Control Information (TCI) consists of the following elements:
+	 * - User_priority. The user_priority field is three bits in length,
+	 * interpreted as a binary number.
+	 * - Canonical Format Indicator (CFI). The Canonical Format Indicator
 	 * (CFI) is a single bit flag value. Currently ignored.
-	 * - VLAN Identifier (VID). The VID is encoded as 
-	 * an unsigned binary number. 
-	 */
-	TCI = ntohs(frame->h_vlan_TCI);
+	 * - VLAN Identifier (VID). The VID is encoded as
+	 * an unsigned binary number. */
+	TCI = ntohs(frame.h_vlan_TCI);
 	id = TCI & VLAN_VID_MASK;
 	prio = (TCI >> 13) & 0x7;
-	encap = frame->h_vlan_encapsulated_proto;
+	encap = frame.h_vlan_encapsulated_proto;
 
-	/*
-	 * Checking VLAN Identifier (VID)
-	 */
-	if (GET_BITMASK(EBT_VLAN_ID)) {	/* Is VLAN ID parsed? */
+	/* Checking VLAN Identifier (VID) */
+	if (GET_BITMASK(EBT_VLAN_ID))
 		EXIT_ON_MISMATCH(id, EBT_VLAN_ID);
-	}
-	/*
-	 * Checking user_priority
-	 */
-	if (GET_BITMASK(EBT_VLAN_PRIO)) {	/* Is VLAN user_priority parsed? */
+
+	/* Checking user_priority */
+	if (GET_BITMASK(EBT_VLAN_PRIO))
 		EXIT_ON_MISMATCH(prio, EBT_VLAN_PRIO);
-	}
-	/*
-	 * Checking Encapsulated Proto (Length/Type) field
-	 */
-	if (GET_BITMASK(EBT_VLAN_ENCAP)) {	/* Is VLAN Encap parsed? */
+
+	/* Checking Encapsulated Proto (Length/Type) field */
+	if (GET_BITMASK(EBT_VLAN_ENCAP))
 		EXIT_ON_MISMATCH(encap, EBT_VLAN_ENCAP);
-	}
-	/*
-	 * All possible extension parameters was parsed.
-	 * If rule never returned by missmatch, then all ok.
-	 */
-	return 0;
+
+	return EBT_MATCH;
 }
 
-/*
- * Function description: ebt_vlan_check() is called when userspace 
- * delivers the table entry to the kernel, 
- * and to check that userspace doesn't give a bad table.
- * Parameters:
- * const char *tablename - table name string
- * unsigned int hooknr - hook number
- * const struct ebt_entry *e - ebtables entry basic set
- * const void *data - pointer to passed extension parameters
- * unsigned int datalen - length of passed *data buffer
- * Returned values:
- * 0 - ok (all delivered rule params are correct)
- * 1 - miss (rule params is out of range, invalid, incompatible, etc.)
- */
 static int
 ebt_check_vlan(const char *tablename,
 	       unsigned int hooknr,
@@ -132,9 +93,7 @@
 {
 	struct ebt_vlan_info *info = (struct ebt_vlan_info *) data;
 
-	/*
-	 * Parameters buffer overflow check 
-	 */
+	/* Parameters buffer overflow check */
 	if (datalen != sizeof(struct ebt_vlan_info)) {
 		DEBUG_MSG
 		    ("passed size %d is not eq to ebt_vlan_info (%Zd)\n",
@@ -142,9 +101,7 @@
 		return -EINVAL;
 	}
 
-	/*
-	 * Is it 802.1Q frame checked?
-	 */
+	/* Is it 802.1Q frame checked? */
 	if (e->ethproto != __constant_htons(ETH_P_8021Q)) {
 		DEBUG_MSG
 		    ("passed entry proto %2.4X is not 802.1Q (8100)\n",
@@ -152,67 +109,54 @@
 		return -EINVAL;
 	}
 
-	/*
-	 * Check for bitmask range 
-	 * True if even one bit is out of mask
-	 */
+	/* Check for bitmask range
+	 * True if even one bit is out of mask */
 	if (info->bitmask & ~EBT_VLAN_MASK) {
 		DEBUG_MSG("bitmask %2X is out of mask (%2X)\n",
 			  info->bitmask, EBT_VLAN_MASK);
 		return -EINVAL;
 	}
 
-	/*
-	 * Check for inversion flags range 
-	 */
+	/* Check for inversion flags range */
 	if (info->invflags & ~EBT_VLAN_MASK) {
 		DEBUG_MSG("inversion flags %2X is out of mask (%2X)\n",
 			  info->invflags, EBT_VLAN_MASK);
 		return -EINVAL;
 	}
 
-	/*
-	 * Reserved VLAN ID (VID) values
+	/* Reserved VLAN ID (VID) values
 	 * -----------------------------
 	 * 0 - The null VLAN ID. 
 	 * 1 - The default Port VID (PVID)
 	 * 0x0FFF - Reserved for implementation use. 
-	 * if_vlan.h: VLAN_GROUP_ARRAY_LEN 4096.
-	 */
-	if (GET_BITMASK(EBT_VLAN_ID)) {	/* when vlan-id param was spec-ed */
-		if (!!info->id) {	/* if id!=0 => check vid range */
+	 * if_vlan.h: VLAN_GROUP_ARRAY_LEN 4096. */
+	if (GET_BITMASK(EBT_VLAN_ID)) {
+		if (!!info->id) { /* if id!=0 => check vid range */
 			if (info->id > VLAN_GROUP_ARRAY_LEN) {
 				DEBUG_MSG
 				    ("id %d is out of range (1-4096)\n",
 				     info->id);
 				return -EINVAL;
 			}
-			/*
-			 * Note: This is valid VLAN-tagged frame point.
+			/* Note: This is valid VLAN-tagged frame point.
 			 * Any value of user_priority are acceptable, 
 			 * but should be ignored according to 802.1Q Std.
-			 * So we just drop the prio flag. 
-			 */
+			 * So we just drop the prio flag. */
 			info->bitmask &= ~EBT_VLAN_PRIO;
 		}
-		/*
-		 * Else, id=0 (null VLAN ID)  => user_priority range (any?)
-		 */
+		/* Else, id=0 (null VLAN ID)  => user_priority range (any?) */
 	}
 
 	if (GET_BITMASK(EBT_VLAN_PRIO)) {
 		if ((unsigned char) info->prio > 7) {
-			DEBUG_MSG
-			    ("prio %d is out of range (0-7)\n",
+			DEBUG_MSG("prio %d is out of range (0-7)\n",
 			     info->prio);
 			return -EINVAL;
 		}
 	}
-	/*
-	 * Check for encapsulated proto range - it is possible to be 
+	/* Check for encapsulated proto range - it is possible to be
 	 * any value for u_short range.
-	 * if_ether.h:  ETH_ZLEN        60   -  Min. octets in frame sans FCS
-	 */
+	 * if_ether.h:  ETH_ZLEN        60   -  Min. octets in frame sans FCS */
 	if (GET_BITMASK(EBT_VLAN_ENCAP)) {
 		if ((unsigned short) ntohs(info->encap) < ETH_ZLEN) {
 			DEBUG_MSG
@@ -232,9 +176,6 @@
 	.me		= THIS_MODULE,
 };
 
-/*
- * Module initialization function.
- */
 static int __init init(void)
 {
 	DEBUG_MSG("ebtables 802.1Q extension module v"
@@ -243,9 +184,6 @@
 	return ebt_register_match(&filter_vlan);
 }
 
-/*
- * Module "finalization" function
- */
 static void __exit fini(void)
 {
 	ebt_unregister_match(&filter_vlan);
diff -urN linux-2.5.69-bk18/net/bridge/netfilter/ebtables.c linux-2.5.69-bk19/net/bridge/netfilter/ebtables.c
--- linux-2.5.69-bk18/net/bridge/netfilter/ebtables.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/net/bridge/netfilter/ebtables.c	2003-05-26 04:41:43.000000000 -0700
@@ -175,10 +175,6 @@
 	char *base;
 	struct ebt_table_info *private = table->private;
 
-	/* FIXME: Push down to extensions --RR */
-	if (skb_is_nonlinear(*pskb) && skb_linearize(*pskb, GFP_ATOMIC) != 0)
-		return NF_DROP;
-
 	read_lock_bh(&table->lock);
 	cb_base = COUNTER_BASE(private->counters, private->nentries,
 	   smp_processor_id());
diff -urN linux-2.5.69-bk18/net/core/dev.c linux-2.5.69-bk19/net/core/dev.c
--- linux-2.5.69-bk18/net/core/dev.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/net/core/dev.c	2003-05-26 04:41:43.000000000 -0700
@@ -1385,8 +1385,10 @@
 {
 	struct net_device *dev = skb->dev;
 
-	if (dev->master)
+	if (dev->master) {
+		skb->real_dev = skb->dev;
 		skb->dev = dev->master;
+	}
 }
 
 static void net_tx_action(struct softirq_action *h)
@@ -2754,6 +2756,8 @@
 
 		dev->next = NULL;
 
+		netdev_unregister_sysfs(dev);
+
 		netdev_wait_allrefs(dev);
 
 		BUG_ON(atomic_read(&dev->refcnt));
@@ -2842,8 +2846,6 @@
 
 	free_divert_blk(dev);
 
-	netdev_unregister_sysfs(dev);
-
 	spin_lock(&unregister_todo_lock);
 	dev->next = unregister_todo;
 	unregister_todo = dev;
diff -urN linux-2.5.69-bk18/net/core/neighbour.c linux-2.5.69-bk19/net/core/neighbour.c
--- linux-2.5.69-bk18/net/core/neighbour.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/net/core/neighbour.c	2003-05-26 04:41:43.000000000 -0700
@@ -540,7 +540,7 @@
 	}
 }
 
-static void SMP_TIMER_NAME(neigh_periodic_timer)(unsigned long arg)
+static void neigh_periodic_timer(unsigned long arg)
 {
 	struct neigh_table *tbl = (struct neigh_table *)arg;
 	unsigned long now = jiffies;
@@ -605,15 +605,6 @@
 	write_unlock(&tbl->lock);
 }
 
-#ifdef CONFIG_SMP
-static void neigh_periodic_timer(unsigned long arg)
-{
-	struct neigh_table *tbl = (struct neigh_table *)arg;
-
-	tasklet_schedule(&tbl->gc_task);
-}
-#endif
-
 static __inline__ int neigh_max_probes(struct neighbour *n)
 {
 	struct neigh_parms *p = n->parms;
@@ -1147,10 +1138,6 @@
 						      15) & ~15,
 						     0, SLAB_HWCACHE_ALIGN,
 						     NULL, NULL);
-#ifdef CONFIG_SMP
-	tasklet_init(&tbl->gc_task, SMP_TIMER_NAME(neigh_periodic_timer),
-		     (unsigned long)tbl);
-#endif
 	tbl->lock	       = RW_LOCK_UNLOCKED;
 	init_timer(&tbl->gc_timer);
 	tbl->gc_timer.data     = (unsigned long)tbl;
@@ -1178,7 +1165,6 @@
 
 	/* It is not clean... Fix it to unload IPv6 module safely */
 	del_timer_sync(&tbl->gc_timer);
-	tasklet_kill(&tbl->gc_task);
 	del_timer_sync(&tbl->proxy_timer);
 	pneigh_queue_purge(&tbl->proxy_queue);
 	neigh_ifdown(tbl, NULL);
diff -urN linux-2.5.69-bk18/net/core/net-sysfs.c linux-2.5.69-bk19/net/core/net-sysfs.c
--- linux-2.5.69-bk18/net/core/net-sysfs.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/net/core/net-sysfs.c	2003-05-26 04:41:43.000000000 -0700
@@ -291,9 +291,7 @@
 	struct class_device_attribute *attr;
 	int ret;
 
-	memset(class_dev, 0, sizeof(struct class_device)); 
 	class_dev->class = &net_class;
-	class_dev->dev = net->dev;
 	class_dev->class_data = net;
 
 	snprintf(class_dev->class_id, BUS_ID_SIZE, net->name);
diff -urN linux-2.5.69-bk18/net/core/skbuff.c linux-2.5.69-bk19/net/core/skbuff.c
--- linux-2.5.69-bk18/net/core/skbuff.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/net/core/skbuff.c	2003-05-26 04:41:43.000000000 -0700
@@ -271,6 +271,7 @@
 	n->sk = NULL;
 	C(stamp);
 	C(dev);
+	C(real_dev);
 	C(h);
 	C(nh);
 	C(mac);
@@ -334,6 +335,7 @@
 	new->list	= NULL;
 	new->sk		= NULL;
 	new->dev	= old->dev;
+	new->real_dev	= old->real_dev;
 	new->priority	= old->priority;
 	new->protocol	= old->protocol;
 	new->dst	= dst_clone(old->dst);
diff -urN linux-2.5.69-bk18/net/decnet/dn_route.c linux-2.5.69-bk19/net/decnet/dn_route.c
--- linux-2.5.69-bk18/net/decnet/dn_route.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/net/decnet/dn_route.c	2003-05-26 04:41:43.000000000 -0700
@@ -155,7 +155,7 @@
 	call_rcu(&rt->u.dst.rcu_head, (void (*)(void *))dst_free, &rt->u.dst);
 }
 
-static void SMP_TIMER_NAME(dn_dst_check_expire)(unsigned long dummy)
+static void dn_dst_check_expire(unsigned long dummy)
 {
 	int i;
 	struct dn_route *rt, **rtp;
@@ -185,8 +185,6 @@
 	mod_timer(&dn_route_timer, now + decnet_dst_gc_interval * HZ);
 }
 
-SMP_TIMER_DEFINE(dn_dst_check_expire, dn_dst_task);
-
 static int dn_dst_gc(void)
 {
 	struct dn_route *rt, **rtp;
@@ -319,7 +317,7 @@
 	return 0;
 }
 
-void SMP_TIMER_NAME(dn_run_flush)(unsigned long dummy)
+void dn_run_flush(unsigned long dummy)
 {
 	int i;
 	struct dn_route *rt, *next;
@@ -341,8 +339,6 @@
 	}
 }
 
-SMP_TIMER_DEFINE(dn_run_flush, dn_flush_task);
-
 static spinlock_t dn_rt_flush_lock = SPIN_LOCK_UNLOCKED;
 
 void dn_rt_cache_flush(int delay)
diff -urN linux-2.5.69-bk18/net/ipv4/af_inet.c linux-2.5.69-bk19/net/ipv4/af_inet.c
--- linux-2.5.69-bk18/net/ipv4/af_inet.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/af_inet.c	2003-05-26 04:41:43.000000000 -0700
@@ -1237,10 +1237,10 @@
 extern int  ip_misc_proc_init(void);
 extern int  raw_proc_init(void);
 extern void raw_proc_exit(void);
-extern int  tcp_proc_init(void);
-extern void tcp_proc_exit(void);
-extern int  udp_proc_init(void);
-extern void udp_proc_exit(void);
+extern int  tcp4_proc_init(void);
+extern void tcp4_proc_exit(void);
+extern int  udp4_proc_init(void);
+extern void udp4_proc_exit(void);
 
 int __init ipv4_proc_init(void)
 {
@@ -1248,9 +1248,9 @@
 
 	if (raw_proc_init())
 		goto out_raw;
-	if (tcp_proc_init())
+	if (tcp4_proc_init())
 		goto out_tcp;
-	if (udp_proc_init())
+	if (udp4_proc_init())
 		goto out_udp;
 	if (fib_proc_init())
 		goto out_fib;
@@ -1261,9 +1261,9 @@
 out_misc:
 	fib_proc_exit();
 out_fib:
-	udp_proc_exit();
+	udp4_proc_exit();
 out_udp:
-	tcp_proc_exit();
+	tcp4_proc_exit();
 out_tcp:
 	raw_proc_exit();
 out_raw:
diff -urN linux-2.5.69-bk18/net/ipv4/arp.c linux-2.5.69-bk19/net/ipv4/arp.c
--- linux-2.5.69-bk18/net/ipv4/arp.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/arp.c	2003-05-26 04:41:43.000000000 -0700
@@ -949,7 +949,7 @@
 		r->arp_flags = arp_state_to_flags(neigh);
 		read_unlock_bh(&neigh->lock);
 		r->arp_ha.sa_family = dev->type;
-		strncpy(r->arp_dev, dev->name, sizeof(r->arp_dev));
+		strlcpy(r->arp_dev, dev->name, sizeof(r->arp_dev));
 		neigh_release(neigh);
 		err = 0;
 	}
diff -urN linux-2.5.69-bk18/net/ipv4/fib_hash.c linux-2.5.69-bk19/net/ipv4/fib_hash.c
--- linux-2.5.69-bk18/net/ipv4/fib_hash.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/fib_hash.c	2003-05-26 04:41:43.000000000 -0700
@@ -151,17 +151,6 @@
 
 #define FZ_MAX_DIVISOR ((PAGE_SIZE<<MAX_ORDER) / sizeof(struct fib_node *))
 
-static unsigned long size_to_order(unsigned long size)
-{
-	unsigned long order;
-
-	for (order = 0; order < MAX_ORDER; order++) {
-		if ((PAGE_SIZE << order) >= size)
-			break;
-	}
-	return order;
-}
-
 static struct fib_node **fz_hash_alloc(int divisor)
 {
 	unsigned long size = divisor * sizeof(struct fib_node *);
@@ -170,7 +159,7 @@
 		return kmalloc(size, GFP_KERNEL);
 	} else {
 		return (struct fib_node **)
-			__get_free_pages(GFP_KERNEL, size_to_order(size));
+			__get_free_pages(GFP_KERNEL, get_order(size));
 	}
 }
 
@@ -201,7 +190,7 @@
 		kfree(hash);
 	else
 		free_pages((unsigned long) hash,
-			   size_to_order(divisor * sizeof(struct fib_node *)));
+			   get_order(divisor * sizeof(struct fib_node *)));
 }
 
 static void fn_rehash_zone(struct fn_zone *fz)
diff -urN linux-2.5.69-bk18/net/ipv4/icmp.c linux-2.5.69-bk19/net/ipv4/icmp.c
--- linux-2.5.69-bk18/net/ipv4/icmp.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/icmp.c	2003-05-26 04:41:43.000000000 -0700
@@ -120,68 +120,68 @@
 
 struct icmp_err icmp_err_convert[] = {
 	{
-		.errno =ENETUNREACH,	/* ICMP_NET_UNREACH */
-		.fatal =0,
+		.errno = ENETUNREACH,	/* ICMP_NET_UNREACH */
+		.fatal = 0,
 	},
 	{
-		.errno =EHOSTUNREACH,	/* ICMP_HOST_UNREACH */
-		.fatal =0,
+		.errno = EHOSTUNREACH,	/* ICMP_HOST_UNREACH */
+		.fatal = 0,
 	},
 	{
-		.errno =ENOPROTOOPT	/* ICMP_PROT_UNREACH */,
-		.fatal =1,
+		.errno = ENOPROTOOPT	/* ICMP_PROT_UNREACH */,
+		.fatal = 1,
 	},
 	{
-		.errno =ECONNREFUSED,	/* ICMP_PORT_UNREACH */
-		.fatal =1,
+		.errno = ECONNREFUSED,	/* ICMP_PORT_UNREACH */
+		.fatal = 1,
 	},
 	{
-		.errno =EMSGSIZE,	/* ICMP_FRAG_NEEDED */
-		.fatal =0,
+		.errno = EMSGSIZE,	/* ICMP_FRAG_NEEDED */
+		.fatal = 0,
 	},
 	{
-		.errno =EOPNOTSUPP,	/* ICMP_SR_FAILED */
-		.fatal =0,
+		.errno = EOPNOTSUPP,	/* ICMP_SR_FAILED */
+		.fatal = 0,
 	},
 	{
-		.errno =ENETUNREACH,	/* ICMP_NET_UNKNOWN */
-		.fatal =1,
+		.errno = ENETUNREACH,	/* ICMP_NET_UNKNOWN */
+		.fatal = 1,
 	},
 	{
-		.errno =EHOSTDOWN,	/* ICMP_HOST_UNKNOWN */
-		.fatal =1,
+		.errno = EHOSTDOWN,	/* ICMP_HOST_UNKNOWN */
+		.fatal = 1,
 	},
 	{
-		.errno =ENONET,		/* ICMP_HOST_ISOLATED */
-		.fatal =1,
+		.errno = ENONET,	/* ICMP_HOST_ISOLATED */
+		.fatal = 1,
 	},
 	{
-		.errno =ENETUNREACH,	/* ICMP_NET_ANO	*/
-		.fatal =1,
+		.errno = ENETUNREACH,	/* ICMP_NET_ANO	*/
+		.fatal = 1,
 	},
 	{
-		.errno =EHOSTUNREACH,	/* ICMP_HOST_ANO */
-		.fatal =1,
+		.errno = EHOSTUNREACH,	/* ICMP_HOST_ANO */
+		.fatal = 1,
 	},
 	{
-		.errno =ENETUNREACH,	/* ICMP_NET_UNR_TOS */
-		.fatal =0,
+		.errno = ENETUNREACH,	/* ICMP_NET_UNR_TOS */
+		.fatal = 0,
 	},
 	{
-		.errno =EHOSTUNREACH,	/* ICMP_HOST_UNR_TOS */
-		.fatal =0,
+		.errno = EHOSTUNREACH,	/* ICMP_HOST_UNR_TOS */
+		.fatal = 0,
 	},
 	{
-		.errno =EHOSTUNREACH,	/* ICMP_PKT_FILTERED */
-		.fatal =1,
+		.errno = EHOSTUNREACH,	/* ICMP_PKT_FILTERED */
+		.fatal = 1,
 	},
 	{
-		.errno =EHOSTUNREACH,	/* ICMP_PREC_VIOLATION */
-		.fatal =1,
+		.errno = EHOSTUNREACH,	/* ICMP_PREC_VIOLATION */
+		.fatal = 1,
 	},
 	{
-		.errno =EHOSTUNREACH,	/* ICMP_PREC_CUTOFF */
-		.fatal =1,
+		.errno = EHOSTUNREACH,	/* ICMP_PREC_CUTOFF */
+		.fatal = 1,
 	},
 };
 
@@ -320,8 +320,8 @@
  *	Checksum each fragment, and on the first include the headers and final
  *	checksum.
  */
-int
-icmp_glue_bits(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
+int icmp_glue_bits(void *from, char *to, int offset, int len, int odd,
+		   struct sk_buff *skb)
 {
 	struct icmp_bxm *icmp_param = (struct icmp_bxm *)from;
 	unsigned int csum;
@@ -334,8 +334,8 @@
 	return 0;
 }
 
-static void
-icmp_push_reply(struct icmp_bxm *icmp_param, struct ipcm_cookie *ipc, struct rtable *rt)
+static void icmp_push_reply(struct icmp_bxm *icmp_param,
+			    struct ipcm_cookie *ipc, struct rtable *rt)
 {
 	struct sk_buff *skb;
 
@@ -353,8 +353,8 @@
 			csum = csum_add(csum, skb1->csum);
 		}
 		csum = csum_partial_copy_nocheck((void *)&icmp_param->data,
-						 (char*)icmph, icmp_param->head_len,	
-						 csum);
+						 (char *)icmph,
+						 icmp_param->head_len, csum);
 		icmph->checksum = csum_fold(csum);
 		skb->ip_summed = CHECKSUM_NONE;
 		ip_push_pending_frames(icmp_socket->sk);
@@ -728,20 +728,16 @@
 	ip = iph->daddr;
 
 	switch (skb->h.icmph->code & 7) {
-		case ICMP_REDIR_NET:
-		case ICMP_REDIR_NETTOS:
-			/*
-			 *	As per RFC recommendations now handle it as
-			 *	a host redirect.
-			 */
-		case ICMP_REDIR_HOST:
-		case ICMP_REDIR_HOSTTOS:
-			ip_rt_redirect(skb->nh.iph->saddr,
-				       ip, skb->h.icmph->un.gateway,
-				       iph->saddr, iph->tos, skb->dev);
-			break;
-		default:
-			break;
+	case ICMP_REDIR_NET:
+	case ICMP_REDIR_NETTOS:
+		/*
+		 * As per RFC recommendations now handle it as a host redirect.
+		 */
+	case ICMP_REDIR_HOST:
+	case ICMP_REDIR_HOSTTOS:
+		ip_rt_redirect(skb->nh.iph->saddr, ip, skb->h.icmph->un.gateway,
+			       iph->saddr, iph->tos, skb->dev);
+		break;
   	}
 out:
 	return;
@@ -966,7 +962,7 @@
 	}
 
 	ICMP_INC_STATS_BH_FIELD(icmp_pointers[icmph->type].input_off);
-	(icmp_pointers[icmph->type].handler)(skb);
+	icmp_pointers[icmph->type].handler(skb);
 
 drop:
 	kfree_skb(skb);
@@ -980,8 +976,7 @@
  *	This table is the definition of how we handle ICMP.
  */
 static struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
-	/* ECHO REPLY (0) */
-	[0] = {
+	[ICMP_ECHOREPLY] = {
 		.output_off = offsetof(struct icmp_mib, IcmpOutEchoReps),
 		.input_off = offsetof(struct icmp_mib, IcmpInEchoReps),
 		.handler = icmp_discard,
@@ -998,22 +993,19 @@
 		.handler = icmp_discard,
 		.error = 1,
 	},
-	/* DEST UNREACH (3) */
-	[3] = {
+	[ICMP_DEST_UNREACH] = {
 		.output_off = offsetof(struct icmp_mib, IcmpOutDestUnreachs),
 		.input_off = offsetof(struct icmp_mib, IcmpInDestUnreachs),
 		.handler = icmp_unreach,
 		.error = 1,
 	},
-	/* SOURCE QUENCH (4) */
-	[4] = {
+	[ICMP_SOURCE_QUENCH] = {
 		.output_off = offsetof(struct icmp_mib, IcmpOutSrcQuenchs),
 		.input_off = offsetof(struct icmp_mib, IcmpInSrcQuenchs),
-		icmp_unreach,
+		.handler = icmp_unreach,
 		.error = 1,
 	},
-	/* REDIRECT (5) */
-	[5] = {
+	[ICMP_REDIRECT] = {
 		.output_off = offsetof(struct icmp_mib, IcmpOutRedirects),
 		.input_off = offsetof(struct icmp_mib, IcmpInRedirects),
 		.handler = icmp_redirect,
@@ -1031,12 +1023,10 @@
 		.handler = icmp_discard,
 		.error = 1,
 	},
-	/* ECHO (8) */
-	[8] = {
+	[ICMP_ECHO] = {
 		.output_off = offsetof(struct icmp_mib, IcmpOutEchos),
 		.input_off = offsetof(struct icmp_mib, IcmpInEchos),
 		.handler = icmp_echo,
-		.error = 0,
 	},
 	[9] = {
 		.output_off = offsetof(struct icmp_mib, dummy),
@@ -1050,56 +1040,48 @@
 		.handler = icmp_discard,
 		.error = 1,
 	},
-	/* TIME EXCEEDED (11) */
-	[11] = {
+	[ICMP_TIME_EXCEEDED] = {
 		.output_off = offsetof(struct icmp_mib, IcmpOutTimeExcds),
 		.input_off = offsetof(struct icmp_mib,IcmpInTimeExcds),
 		.handler = icmp_unreach,
 		.error = 1,
 	},
-	/* PARAMETER PROBLEM (12) */
-	[12] = {
+	[ICMP_PARAMETERPROB] = {
 		.output_off = offsetof(struct icmp_mib, IcmpOutParmProbs),
 		.input_off = offsetof(struct icmp_mib, IcmpInParmProbs),
 		.handler = icmp_unreach,
 		.error = 1,
 	},
-	/* TIMESTAMP (13) */
-	[13] = {
+	[ICMP_TIMESTAMP] = {
 		.output_off = offsetof(struct icmp_mib, IcmpOutTimestamps),
 		.input_off = offsetof(struct icmp_mib, IcmpInTimestamps),
 		.handler = icmp_timestamp,
 	},
-	/* TIMESTAMP REPLY (14) */
-	[14] = {
+	[ICMP_TIMESTAMPREPLY] = {
 		.output_off = offsetof(struct icmp_mib, IcmpOutTimestampReps),
 		.input_off = offsetof(struct icmp_mib, IcmpInTimestampReps),
 		.handler = icmp_discard,
 	},
-	/* INFO (15) */
-	[15] = {
+	[ICMP_INFO_REQUEST] = {
 		.output_off = offsetof(struct icmp_mib, dummy),
 		.input_off = offsetof(struct icmp_mib, dummy),
 		.handler = icmp_discard,
 	},
-	/* INFO REPLY (16) */
- 	[16] = {
+ 	[ICMP_INFO_REPLY] = {
 		.output_off = offsetof(struct icmp_mib, dummy),
 		.input_off = offsetof(struct icmp_mib, dummy),
 		.handler = icmp_discard,
 	},
-	/* ADDR MASK (17) */
-	[17] = {
+	[ICMP_ADDRESS] = {
 		.output_off = offsetof(struct icmp_mib, IcmpOutAddrMasks),
 		.input_off = offsetof(struct icmp_mib, IcmpInAddrMasks),
 		.handler = icmp_address,
 	},
-	/* ADDR MASK REPLY (18) */
-	[18] = {
+	[ICMP_ADDRESSREPLY] = {
 		.output_off = offsetof(struct icmp_mib, IcmpOutAddrMaskReps),
 		.input_off = offsetof(struct icmp_mib, IcmpInAddrMaskReps),
 		.handler = icmp_address_reply,
-	}
+	},
 };
 
 void __init icmp_init(struct net_proto_family *ops)
diff -urN linux-2.5.69-bk18/net/ipv4/ipconfig.c linux-2.5.69-bk19/net/ipv4/ipconfig.c
--- linux-2.5.69-bk18/net/ipv4/ipconfig.c	2003-05-04 16:53:00.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/ipconfig.c	2003-05-26 04:41:43.000000000 -0700
@@ -1363,16 +1363,15 @@
 			case 4:
 				if ((dp = strchr(ip, '.'))) {
 					*dp++ = '\0';
-					strncpy(system_utsname.domainname, dp, __NEW_UTS_LEN);
-					system_utsname.domainname[__NEW_UTS_LEN] = '\0';
+					strlcpy(system_utsname.domainname, dp,
+						sizeof(system_utsname.domainname));
 				}
-				strncpy(system_utsname.nodename, ip, __NEW_UTS_LEN);
-				system_utsname.nodename[__NEW_UTS_LEN] = '\0';
+				strlcpy(system_utsname.nodename, ip,
+					sizeof(system_utsname.nodename));
 				ic_host_name_set = 1;
 				break;
 			case 5:
-				strncpy(user_dev_name, ip, IFNAMSIZ);
-				user_dev_name[IFNAMSIZ-1] = '\0';
+				strlcpy(user_dev_name, ip, sizeof(user_dev_name));
 				break;
 			case 6:
 				ic_proto_name(ip);
diff -urN linux-2.5.69-bk18/net/ipv4/netfilter/ip_conntrack_amanda.c linux-2.5.69-bk19/net/ipv4/netfilter/ip_conntrack_amanda.c
--- linux-2.5.69-bk18/net/ipv4/netfilter/ip_conntrack_amanda.c	2003-05-04 16:53:34.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/netfilter/ip_conntrack_amanda.c	2003-05-26 04:41:43.000000000 -0700
@@ -207,6 +207,7 @@
 	return 0;
 }
 
+PROVIDES_CONNTRACK(amanda);
 EXPORT_SYMBOL(ip_amanda_lock);
 
 module_init(init);
diff -urN linux-2.5.69-bk18/net/ipv4/netfilter/ip_conntrack_ftp.c linux-2.5.69-bk19/net/ipv4/netfilter/ip_conntrack_ftp.c
--- linux-2.5.69-bk18/net/ipv4/netfilter/ip_conntrack_ftp.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/netfilter/ip_conntrack_ftp.c	2003-05-26 04:41:43.000000000 -0700
@@ -437,6 +437,7 @@
 	return 0;
 }
 
+PROVIDES_CONNTRACK(ftp);
 EXPORT_SYMBOL(ip_ftp_lock);
 
 MODULE_LICENSE("GPL");
diff -urN linux-2.5.69-bk18/net/ipv4/netfilter/ip_conntrack_irc.c linux-2.5.69-bk19/net/ipv4/netfilter/ip_conntrack_irc.c
--- linux-2.5.69-bk18/net/ipv4/netfilter/ip_conntrack_irc.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/netfilter/ip_conntrack_irc.c	2003-05-26 04:41:43.000000000 -0700
@@ -289,6 +289,7 @@
 	}
 }
 
+PROVIDES_CONNTRACK(irc);
 EXPORT_SYMBOL(ip_irc_lock);
 
 module_init(init);
diff -urN linux-2.5.69-bk18/net/ipv4/netfilter/ip_conntrack_tftp.c linux-2.5.69-bk19/net/ipv4/netfilter/ip_conntrack_tftp.c
--- linux-2.5.69-bk18/net/ipv4/netfilter/ip_conntrack_tftp.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/netfilter/ip_conntrack_tftp.c	2003-05-26 04:41:43.000000000 -0700
@@ -130,5 +130,7 @@
 	return(0);
 }
 
+PROVIDES_CONNTRACK(tftp);
+
 module_init(init);
 module_exit(fini);
diff -urN linux-2.5.69-bk18/net/ipv4/netfilter/ip_nat_amanda.c linux-2.5.69-bk19/net/ipv4/netfilter/ip_nat_amanda.c
--- linux-2.5.69-bk18/net/ipv4/netfilter/ip_nat_amanda.c	2003-05-04 16:53:07.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/netfilter/ip_nat_amanda.c	2003-05-26 04:41:43.000000000 -0700
@@ -221,6 +221,6 @@
 	return ret;
 }
 
-
+NEEDS_CONNTRACK(amanda);
 module_init(init);
 module_exit(fini);
diff -urN linux-2.5.69-bk18/net/ipv4/netfilter/ip_nat_ftp.c linux-2.5.69-bk19/net/ipv4/netfilter/ip_nat_ftp.c
--- linux-2.5.69-bk18/net/ipv4/netfilter/ip_nat_ftp.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/netfilter/ip_nat_ftp.c	2003-05-26 04:41:43.000000000 -0700
@@ -341,6 +341,8 @@
 	return ret;
 }
 
+NEEDS_CONNTRACK(ftp);
+
 module_init(init);
 module_exit(fini);
 MODULE_LICENSE("GPL");
diff -urN linux-2.5.69-bk18/net/ipv4/netfilter/ip_nat_helper.c linux-2.5.69-bk19/net/ipv4/netfilter/ip_nat_helper.c
--- linux-2.5.69-bk18/net/ipv4/netfilter/ip_nat_helper.c	2003-05-26 04:41:37.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/netfilter/ip_nat_helper.c	2003-05-26 04:41:43.000000000 -0700
@@ -404,44 +404,6 @@
 {
 	int ret = 0;
 
-	if (me->me && !(me->flags & IP_NAT_HELPER_F_STANDALONE)) {
-		struct ip_conntrack_helper *ct_helper;
-		
-		if ((ct_helper = ip_ct_find_helper(&me->tuple))) {
-			if (!try_module_get(ct_helper->me))
-				return -EBUSY;
-		} else {
-			/* We are a NAT helper for protocol X.  If we need
-			 * respective conntrack helper for protoccol X, compute
-			 * conntrack helper name and try to load module */
-			char name[MODULE_NAME_LEN];
-			const char *tmp = module_name(me->me);
-			
-			if (strlen(tmp) + 6 > MODULE_NAME_LEN) {
-				printk("%s: unable to "
-				       "compute conntrack helper name "
-				       "from %s\n", __FUNCTION__, tmp);
-				return -EBUSY;
-			}
-			tmp += 6;
-			sprintf(name, "ip_conntrack%s", tmp);
-#ifdef CONFIG_KMOD
-			if (!request_module("ip_conntrack%s", tmp)
-			    && (ct_helper = ip_ct_find_helper(&me->tuple))) {
-				if (!try_module_get(ct_helper->me))
-					return -EBUSY;
-			} else {
-				printk("unable to load module %s\n", name);
-				return -EBUSY;
-			}
-#else
-			printk("unable to load module %s automatically "
-			       "because kernel was compiled without kernel "
-			       "module loader support\n", name);
-			return -EBUSY;
-#endif
-		}
-	}
 	WRITE_LOCK(&ip_nat_lock);
 	if (LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,&me->tuple))
 		ret = -EBUSY;
@@ -484,19 +446,4 @@
 	   which is just a long-winded way of making things
 	   worse. --RR */
 	ip_ct_selective_cleanup(kill_helper, me);
-
-	/* If we are no standalone NAT helper, we need to decrement usage count
-	 * on our conntrack helper */
-	if (me->me && !(me->flags & IP_NAT_HELPER_F_STANDALONE)) {
-		struct ip_conntrack_helper *ct_helper;
-		
-		if ((ct_helper = ip_ct_find_helper(&me->tuple)))
-			module_put(ct_helper->me);
-#ifdef CONFIG_MODULES
-		else 
-			printk("%s: unable to decrement usage count"
-			       " of conntrack helper %s\n",
-			       __FUNCTION__, me->me->name);
-#endif
-	}
 }
diff -urN linux-2.5.69-bk18/net/ipv4/netfilter/ip_nat_irc.c linux-2.5.69-bk19/net/ipv4/netfilter/ip_nat_irc.c
--- linux-2.5.69-bk18/net/ipv4/netfilter/ip_nat_irc.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/netfilter/ip_nat_irc.c	2003-05-26 04:41:43.000000000 -0700
@@ -279,6 +279,7 @@
 	return ret;
 }
 
+NEEDS_CONNTRACK(irc);
 
 module_init(init);
 module_exit(fini);
diff -urN linux-2.5.69-bk18/net/ipv4/netfilter/ip_nat_snmp_basic.c linux-2.5.69-bk19/net/ipv4/netfilter/ip_nat_snmp_basic.c
--- linux-2.5.69-bk18/net/ipv4/netfilter/ip_nat_snmp_basic.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/netfilter/ip_nat_snmp_basic.c	2003-05-26 04:41:43.000000000 -0700
@@ -1306,7 +1306,7 @@
 static struct ip_nat_helper snmp = { 
 	{ NULL, NULL },
 	"snmp",
-	IP_NAT_HELPER_F_STANDALONE,
+	0,
 	THIS_MODULE,
 	{ { 0, { __constant_htons(SNMP_PORT) } },
 	  { 0, { 0 }, IPPROTO_UDP } },
@@ -1317,7 +1317,7 @@
 static struct ip_nat_helper snmp_trap = { 
 	{ NULL, NULL },
 	"snmp_trap",
-	IP_NAT_HELPER_F_STANDALONE,
+	0,
 	THIS_MODULE,
 	{ { 0, { __constant_htons(SNMP_TRAP_PORT) } },
 	  { 0, { 0 }, IPPROTO_UDP } },
diff -urN linux-2.5.69-bk18/net/ipv4/route.c linux-2.5.69-bk19/net/ipv4/route.c
--- linux-2.5.69-bk18/net/ipv4/route.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/route.c	2003-05-26 04:41:43.000000000 -0700
@@ -455,7 +455,7 @@
 }
 
 /* This runs via a timer and thus is always in BH context. */
-static void SMP_TIMER_NAME(rt_check_expire)(unsigned long dummy)
+static void rt_check_expire(unsigned long dummy)
 {
 	static int rover;
 	int i = rover, t;
@@ -498,12 +498,10 @@
 	mod_timer(&rt_periodic_timer, now + ip_rt_gc_interval);
 }
 
-SMP_TIMER_DEFINE(rt_check_expire, rt_gc_task);
-
 /* This can run from both BH and non-BH contexts, the latter
  * in the case of a forced flush event.
  */
-static void SMP_TIMER_NAME(rt_run_flush)(unsigned long dummy)
+static void rt_run_flush(unsigned long dummy)
 {
 	int i;
 	struct rtable *rth, *next;
@@ -526,8 +524,6 @@
 	}
 }
 
-SMP_TIMER_DEFINE(rt_run_flush, rt_cache_flush_task);
-  
 static spinlock_t rt_flush_lock = SPIN_LOCK_UNLOCKED;
 
 void rt_cache_flush(int delay)
@@ -559,7 +555,7 @@
 
 	if (delay <= 0) {
 		spin_unlock_bh(&rt_flush_lock);
-		SMP_TIMER_NAME(rt_run_flush)(0);
+		rt_run_flush(0);
 		return;
 	}
 
diff -urN linux-2.5.69-bk18/net/ipv4/tcp_ipv4.c linux-2.5.69-bk19/net/ipv4/tcp_ipv4.c
--- linux-2.5.69-bk18/net/ipv4/tcp_ipv4.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/tcp_ipv4.c	2003-05-26 04:41:43.000000000 -0700
@@ -2129,19 +2129,6 @@
 #ifdef CONFIG_PROC_FS
 /* Proc filesystem TCP sock list dumping. */
 
-enum tcp_seq_states {
-	TCP_SEQ_STATE_LISTENING,
-	TCP_SEQ_STATE_OPENREQ,
-	TCP_SEQ_STATE_ESTABLISHED,
-	TCP_SEQ_STATE_TIME_WAIT,
-};
-
-struct tcp_iter_state {
-	enum tcp_seq_states state;
-	struct sock	   *syn_wait_sk;
-	int		    bucket, sbucket, num, uid;
-};
-
 static void *listening_get_first(struct seq_file *seq)
 {
 	struct tcp_iter_state* st = seq->private;
@@ -2155,7 +2142,7 @@
 		if (!sk)
 			continue;
 		++st->num;
-		if (TCP_INET_FAMILY(sk->family)) {
+		if (sk->family == st->family) {
 			rc = sk;
 			goto out;
 		}
@@ -2169,7 +2156,7 @@
 			     ++st->sbucket) {
 				for (req = tp->listen_opt->syn_table[st->sbucket];
 				     req; req = req->dl_next, ++st->num) {
-					if (!TCP_INET_FAMILY(req->class->family))
+					if (req->class->family != st->family)
 						continue;
 					rc = req;
 					goto out;
@@ -2197,7 +2184,7 @@
 		while (1) {
 			while (req) {
 				++st->num;
-				if (TCP_INET_FAMILY(req->class->family)) {
+				if (req->class->family == st->family) {
 					cur = req;
 					goto out;
 				}
@@ -2215,7 +2202,7 @@
 		sk = sk->next;
 get_sk:
 	while (sk) {
-		if (TCP_INET_FAMILY(sk->family)) {
+		if (sk->family == st->family) {
 			cur = sk;
 			goto out;
 		}
@@ -2262,7 +2249,7 @@
 		read_lock(&tcp_ehash[st->bucket].lock);
 		for (sk = tcp_ehash[st->bucket].chain; sk;
 		     sk = sk->next, ++st->num) {
-			if (!TCP_INET_FAMILY(sk->family))
+			if (sk->family != st->family)
 				continue;
 			rc = sk;
 			goto out;
@@ -2271,7 +2258,7 @@
 		for (tw = (struct tcp_tw_bucket *)
 				tcp_ehash[st->bucket + tcp_ehash_size].chain;
 		     tw; tw = (struct tcp_tw_bucket *)tw->next, ++st->num) {
-			if (!TCP_INET_FAMILY(tw->family))
+			if (tw->family != st->family)
 				continue;
 			rc = tw;
 			goto out;
@@ -2293,7 +2280,7 @@
 		tw = cur;
 		tw = (struct tcp_tw_bucket *)tw->next;
 get_tw:
-		while (tw && !TCP_INET_FAMILY(tw->family)) {
+		while (tw && tw->family != st->family) {
 			++st->num;
 			tw = (struct tcp_tw_bucket *)tw->next;
 		}
@@ -2313,7 +2300,7 @@
 	} else
 		sk = sk->next;
 
-	while (sk && !TCP_INET_FAMILY(sk->family)) {
+	while (sk && sk->family != st->family) {
 		++st->num;
 		sk = sk->next;
 	}
@@ -2417,8 +2404,66 @@
 	}
 }
 
-static void get_openreq(struct sock *sk, struct open_request *req,
-			char *tmpbuf, int i, int uid)
+static int tcp_seq_open(struct inode *inode, struct file *file)
+{
+	struct tcp_seq_afinfo *afinfo = PDE(inode)->data;
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+	struct tcp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+	if (!s)
+		goto out;
+	memset(s, 0, sizeof(*s));
+	s->family		= afinfo->family;
+	s->seq_ops.start	= tcp_seq_start;
+	s->seq_ops.next		= tcp_seq_next;
+	s->seq_ops.show		= afinfo->seq_show;
+	s->seq_ops.stop		= tcp_seq_stop;
+
+	rc = seq_open(file, &s->seq_ops);
+	if (rc)
+		goto out_kfree;
+	seq	     = file->private_data;
+	seq->private = s;
+out:
+	return rc;
+out_kfree:
+	kfree(s);
+	goto out;
+}
+
+int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
+{
+	int rc = 0;
+	struct proc_dir_entry *p;
+
+	if (!afinfo)
+		return -EINVAL;
+	afinfo->seq_fops->owner		= afinfo->owner;
+	afinfo->seq_fops->open		= tcp_seq_open;
+	afinfo->seq_fops->read		= seq_read;
+	afinfo->seq_fops->llseek	= seq_lseek;
+	afinfo->seq_fops->release	= seq_release_private;
+	
+	p = create_proc_entry(afinfo->name, S_IRUGO, proc_net);
+	if (p) {
+		p->data = afinfo;
+		p->proc_fops = afinfo->seq_fops;
+	} else
+		rc = -ENOMEM;
+	return rc;
+}
+
+void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo)
+{
+	if (!afinfo)
+		return;
+	remove_proc_entry(afinfo->name, proc_net);
+	memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops)); 
+}
+
+static void get_openreq4(struct sock *sk, struct open_request *req,
+			 char *tmpbuf, int i, int uid)
 {
 	int ttd = req->expires - jiffies;
 
@@ -2441,7 +2486,7 @@
 		req);
 }
 
-static void get_tcp_sock(struct sock *sp, char *tmpbuf, int i)
+static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i)
 {
 	int timer_active;
 	unsigned long timer_expires;
@@ -2481,7 +2526,7 @@
 		tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh);
 }
 
-static void get_timewait_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i)
+static void get_timewait4_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i)
 {
 	unsigned int dest, src;
 	__u16 destp, srcp;
@@ -2504,7 +2549,7 @@
 
 #define TMPSZ 150
 
-static int tcp_seq_show(struct seq_file *seq, void *v)
+static int tcp4_seq_show(struct seq_file *seq, void *v)
 {
 	struct tcp_iter_state* st;
 	char tmpbuf[TMPSZ + 1];
@@ -2521,13 +2566,13 @@
 	switch (st->state) {
 	case TCP_SEQ_STATE_LISTENING:
 	case TCP_SEQ_STATE_ESTABLISHED:
-		get_tcp_sock(v, tmpbuf, st->num);
+		get_tcp4_sock(v, tmpbuf, st->num);
 		break;
 	case TCP_SEQ_STATE_OPENREQ:
-		get_openreq(st->syn_wait_sk, v, tmpbuf, st->num, st->uid);
+		get_openreq4(st->syn_wait_sk, v, tmpbuf, st->num, st->uid);
 		break;
 	case TCP_SEQ_STATE_TIME_WAIT:
-		get_timewait_sock(v, tmpbuf, st->num);
+		get_timewait4_sock(v, tmpbuf, st->num);
 		break;
 	}
 	seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf);
@@ -2535,57 +2580,23 @@
 	return 0;
 }
 
-static struct seq_operations tcp_seq_ops = {
-	.start	=	tcp_seq_start,
-	.next	=	tcp_seq_next,
-	.stop	=	tcp_seq_stop,
-	.show	=	tcp_seq_show,
+static struct file_operations tcp4_seq_fops;
+static struct tcp_seq_afinfo tcp4_seq_afinfo = {
+	.owner		= THIS_MODULE,
+	.name		= "tcp",
+	.family		= AF_INET,
+	.seq_show	= tcp4_seq_show,
+	.seq_fops	= &tcp4_seq_fops,
 };
 
-static int tcp_seq_open(struct inode *inode, struct file *file)
+int __init tcp4_proc_init(void)
 {
-	struct seq_file *seq;
-	int rc = -ENOMEM;
-	struct tcp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
-
-	if (!s)
-		goto out;
-	rc = seq_open(file, &tcp_seq_ops);
-	if (rc)
-		goto out_kfree;
-	seq	     = file->private_data;
-	seq->private = s;
-	memset(s, 0, sizeof(*s));
-out:
-	return rc;
-out_kfree:
-	kfree(s);
-	goto out;
-}
-
-static struct file_operations tcp_seq_fops = {
-	.owner		=	THIS_MODULE,
-	.open		=	tcp_seq_open,
-	.read		=	seq_read,
-	.llseek		=	seq_lseek,
-	.release	=	seq_release_private,
-};
-
-int __init tcp_proc_init(void)
-{
-	int rc = 0;
-	struct proc_dir_entry *p = create_proc_entry("tcp", S_IRUGO, proc_net);
-
-	if (p)
-		p->proc_fops = &tcp_seq_fops;
-	else
-		rc = -ENOMEM;
-	return rc;
+	return tcp_proc_register(&tcp4_seq_afinfo);
 }
 
-void __init tcp_proc_exit(void)
+void tcp4_proc_exit(void)
 {
-	remove_proc_entry("tcp", proc_net);
+	tcp_proc_unregister(&tcp4_seq_afinfo);
 }
 #endif /* CONFIG_PROC_FS */
 
diff -urN linux-2.5.69-bk18/net/ipv4/tcp_minisocks.c linux-2.5.69-bk19/net/ipv4/tcp_minisocks.c
--- linux-2.5.69-bk18/net/ipv4/tcp_minisocks.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/tcp_minisocks.c	2003-05-26 04:41:43.000000000 -0700
@@ -418,11 +418,15 @@
 
 static void tcp_twkill(unsigned long);
 
+/* TIME_WAIT reaping mechanism. */
+#define TCP_TWKILL_SLOTS	8	/* Please keep this a power of 2. */
+#define TCP_TWKILL_PERIOD	(TCP_TIMEWAIT_LEN/TCP_TWKILL_SLOTS)
+
 static struct tcp_tw_bucket *tcp_tw_death_row[TCP_TWKILL_SLOTS];
 static spinlock_t tw_death_lock = SPIN_LOCK_UNLOCKED;
 static struct timer_list tcp_tw_timer = TIMER_INITIALIZER(tcp_twkill, 0, 0);
 
-static void SMP_TIMER_NAME(tcp_twkill)(unsigned long dummy)
+static void tcp_twkill(unsigned long dummy)
 {
 	struct tcp_tw_bucket *tw;
 	int killed = 0;
@@ -462,8 +466,6 @@
 	spin_unlock(&tw_death_lock);
 }
 
-SMP_TIMER_DEFINE(tcp_twkill, tcp_twkill_task);
-
 /* These are always called from BH context.  See callers in
  * tcp_input.c to verify this.
  */
@@ -575,7 +577,7 @@
 	spin_unlock(&tw_death_lock);
 }
 
-void SMP_TIMER_NAME(tcp_twcal_tick)(unsigned long dummy)
+void tcp_twcal_tick(unsigned long dummy)
 {
 	int n, slot;
 	unsigned long j;
@@ -626,9 +628,6 @@
 	spin_unlock(&tw_death_lock);
 }
 
-SMP_TIMER_DEFINE(tcp_twcal_tick, tcp_twcal_tasklet);
-
-
 /* This is not only more efficient than what we used to do, it eliminates
  * a lot of code duplication between IPv4/IPv6 SYN recv processing. -DaveM
  *
diff -urN linux-2.5.69-bk18/net/ipv4/udp.c linux-2.5.69-bk19/net/ipv4/udp.c
--- linux-2.5.69-bk18/net/ipv4/udp.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv4/udp.c	2003-05-26 04:41:43.000000000 -0700
@@ -1349,10 +1349,6 @@
 /* ------------------------------------------------------------------------ */
 #ifdef CONFIG_PROC_FS
 
-struct udp_iter_state {
-	int bucket;
-};
-
 static __inline__ struct sock *udp_get_bucket(struct seq_file *seq, loff_t *pos)
 {
 	int i;
@@ -1362,7 +1358,7 @@
 
 	for (; state->bucket < UDP_HTABLE_SIZE; ++state->bucket)
 		for (i = 0, sk = udp_hash[state->bucket]; sk; ++i, sk = sk->next) {
-			if (sk->family != PF_INET)
+			if (sk->family != state->family)
 				continue;
 			if (l--)
 				continue;
@@ -1389,15 +1385,16 @@
 		goto out;
 	}
 
+	state = seq->private;
+
 	sk = v;
 	sk = sk->next;
 
 	for (; sk; sk = sk->next) {
-		if (sk->family == AF_INET)
+		if (sk->family == state->family)
 			goto out;
 	}
 
-	state = seq->private;
 	if (++state->bucket >= UDP_HTABLE_SIZE) 
 		goto out;
 
@@ -1413,7 +1410,68 @@
 	read_unlock(&udp_hash_lock);
 }
 
-static void udp_format_sock(struct sock *sp, char *tmpbuf, int bucket)
+static int udp_seq_open(struct inode *inode, struct file *file)
+{
+	struct udp_seq_afinfo *afinfo = PDE(inode)->data;
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+	struct udp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+	if (!s)
+		goto out;
+	memset(s, 0, sizeof(*s));
+	s->family		= afinfo->family;
+	s->seq_ops.start	= udp_seq_start;
+	s->seq_ops.next		= udp_seq_next;
+	s->seq_ops.show		= afinfo->seq_show;
+	s->seq_ops.stop		= udp_seq_stop;
+
+	rc = seq_open(file, &s->seq_ops);
+	if (rc)
+		goto out_kfree;
+
+	seq	     = file->private_data;
+	seq->private = s;
+out:
+	return rc;
+out_kfree:
+	kfree(s);
+	goto out;
+}
+
+/* ------------------------------------------------------------------------ */
+int udp_proc_register(struct udp_seq_afinfo *afinfo)
+{
+	struct proc_dir_entry *p;
+	int rc = 0;
+
+	if (!afinfo)
+		return -EINVAL;
+	afinfo->seq_fops->owner		= afinfo->owner;
+	afinfo->seq_fops->open		= udp_seq_open;
+	afinfo->seq_fops->read		= seq_read;
+	afinfo->seq_fops->llseek	= seq_lseek;
+	afinfo->seq_fops->release	= seq_release_private;
+
+	p = create_proc_entry(afinfo->name, S_IRUGO, proc_net);
+	if (p) {
+		p->data = afinfo;
+		p->proc_fops = afinfo->seq_fops;
+	} else
+		rc = -ENOMEM;
+	return rc;
+}
+
+void udp_proc_unregister(struct udp_seq_afinfo *afinfo)
+{
+	if (!afinfo)
+		return;
+	remove_proc_entry(afinfo->name, proc_net);
+	memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
+}
+
+/* ------------------------------------------------------------------------ */
+static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket)
 {
 	struct inet_opt *inet = inet_sk(sp);
 	unsigned int dest = inet->daddr;
@@ -1429,7 +1487,7 @@
 		atomic_read(&sp->refcnt), sp);
 }
 
-static int udp_seq_show(struct seq_file *seq, void *v)
+static int udp4_seq_show(struct seq_file *seq, void *v)
 {
 	if (v == (void *)1)
 		seq_printf(seq, "%-127s\n",
@@ -1440,68 +1498,29 @@
 		char tmpbuf[129];
 		struct udp_iter_state *state = seq->private;
 
-		udp_format_sock(v, tmpbuf, state->bucket);
+		udp4_format_sock(v, tmpbuf, state->bucket);
 		seq_printf(seq, "%-127s\n", tmpbuf);
 	}
 	return 0;
 }
-/* ------------------------------------------------------------------------ */
-
-static struct seq_operations udp_seq_ops = {
-	.start  = udp_seq_start,
-	.next   = udp_seq_next,
-	.stop   = udp_seq_stop,
-	.show   = udp_seq_show,
-};
-
-static int udp_seq_open(struct inode *inode, struct file *file)
-{
-	struct seq_file *seq;
-	int rc = -ENOMEM;
-	struct udp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
-       
-	if (!s)
-		goto out;
-
-	rc = seq_open(file, &udp_seq_ops);
-	if (rc)
-		goto out_kfree;
-
-	seq	     = file->private_data;
-	seq->private = s;
-	memset(s, 0, sizeof(*s));
-out:
-	return rc;
-out_kfree:
-	kfree(s);
-	goto out;
-}
 
-static struct file_operations udp_seq_fops = {
+/* ------------------------------------------------------------------------ */
+static struct file_operations udp4_seq_fops;
+static struct udp_seq_afinfo udp4_seq_afinfo = {
 	.owner		= THIS_MODULE,
-	.open           = udp_seq_open,
-	.read           = seq_read,
-	.llseek         = seq_lseek,
-	.release	= seq_release_private,
+	.name		= "udp",
+	.family		= AF_INET,
+	.seq_show	= udp4_seq_show,
+	.seq_fops	= &udp4_seq_fops,
 };
 
-/* ------------------------------------------------------------------------ */
-
-int __init udp_proc_init(void)
+int __init udp4_proc_init(void)
 {
-	struct proc_dir_entry *p;
-	int rc = 0;
-
-	p = create_proc_entry("udp", S_IRUGO, proc_net);
-	if (p)
-		p->proc_fops = &udp_seq_fops;
-	else
-		rc = -ENOMEM;
-	return rc;
+	return udp_proc_register(&udp4_seq_afinfo);
 }
 
-void __init udp_proc_exit(void)
+void udp4_proc_exit(void)
 {
-	remove_proc_entry("udp", proc_net);
+	udp_proc_unregister(&udp4_seq_afinfo);
 }
 #endif /* CONFIG_PROC_FS */
diff -urN linux-2.5.69-bk18/net/ipv6/af_inet6.c linux-2.5.69-bk19/net/ipv6/af_inet6.c
--- linux-2.5.69-bk18/net/ipv6/af_inet6.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv6/af_inet6.c	2003-05-26 04:41:43.000000000 -0700
@@ -77,8 +77,11 @@
 extern int raw6_proc_init(void);
 extern int raw6_proc_exit(void);
 
-extern int tcp6_get_info(char *, char **, off_t, int);
-extern int udp6_get_info(char *, char **, off_t, int);
+extern int tcp6_proc_init(void);
+extern void tcp6_proc_exit(void);
+
+extern int udp6_proc_init(void);
+extern void udp6_proc_exit(void);
 
 extern int ipv6_misc_proc_init(void);
 extern int ipv6_misc_proc_exit(void);
@@ -787,9 +790,9 @@
 	err = -ENOMEM;
 	if (raw6_proc_init())
 		goto proc_raw6_fail;
-	if (!proc_net_create("tcp6", 0, tcp6_get_info))
+	if (tcp6_proc_init())
 		goto proc_tcp6_fail;
-	if (!proc_net_create("udp6", 0, udp6_get_info))
+	if (udp6_proc_init())
 		goto proc_udp6_fail;
 	if (ipv6_misc_proc_init())
 		goto proc_misc6_fail;
@@ -820,9 +823,9 @@
 proc_anycast6_fail:
 	ipv6_misc_proc_exit();
 proc_misc6_fail:
-	proc_net_remove("udp6");
+	udp6_proc_exit();
 proc_udp6_fail:
-	proc_net_remove("tcp6");
+	tcp6_proc_exit();
 proc_tcp6_fail:
 	raw6_proc_exit();
 proc_raw6_fail:
diff -urN linux-2.5.69-bk18/net/ipv6/tcp_ipv6.c linux-2.5.69-bk19/net/ipv6/tcp_ipv6.c
--- linux-2.5.69-bk18/net/ipv6/tcp_ipv6.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv6/tcp_ipv6.c	2003-05-26 04:41:43.000000000 -0700
@@ -17,6 +17,7 @@
  *	YOSHIFUJI Hideaki @USAGI and:	Support IPV6_V6ONLY socket option, which
  *	Alexey Kuznetsov		allow both IPv4 and IPv6 sockets to bind
  *					a single port at the same time.
+ *	YOSHIFUJI Hideaki @USAGI:	convert /proc/net/tcp6 to seq_file.
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -55,6 +56,9 @@
 
 #include <asm/uaccess.h>
 
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
 static void	tcp_v6_send_reset(struct sk_buff *skb);
 static void	tcp_v6_or_send_ack(struct sk_buff *skb, struct open_request *req);
 static void	tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len, 
@@ -1934,7 +1938,8 @@
 }
 
 /* Proc filesystem TCPv6 sock list dumping. */
-static void get_openreq6(struct sock *sk, struct open_request *req, char *tmpbuf, int i, int uid)
+static void get_openreq6(struct seq_file *seq, 
+			 struct sock *sk, struct open_request *req, int i, int uid)
 {
 	struct in6_addr *dest, *src;
 	int ttd = req->expires - jiffies;
@@ -1944,28 +1949,28 @@
 
 	src = &req->af.v6_req.loc_addr;
 	dest = &req->af.v6_req.rmt_addr;
-	sprintf(tmpbuf,
-		"%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-		"%02X %08X:%08X %02X:%08X %08X %5d %8d %d %d %p",
-		i,
-		src->s6_addr32[0], src->s6_addr32[1],
-		src->s6_addr32[2], src->s6_addr32[3],
-		ntohs(inet_sk(sk)->sport),
-		dest->s6_addr32[0], dest->s6_addr32[1],
-		dest->s6_addr32[2], dest->s6_addr32[3],
-		ntohs(req->rmt_port),
-		TCP_SYN_RECV,
-		0,0, /* could print option size, but that is af dependent. */
-		1,   /* timers active (only the expire timer) */  
-		ttd, 
-		req->retrans,
-		uid,
-		0,  /* non standard timer */  
-		0, /* open_requests have no inode */
-		0, req);
+	seq_printf(seq,
+		   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
+		   "%02X %08X:%08X %02X:%08X %08X %5d %8d %d %d %p\n",
+		   i,
+		   src->s6_addr32[0], src->s6_addr32[1],
+		   src->s6_addr32[2], src->s6_addr32[3],
+		   ntohs(inet_sk(sk)->sport),
+		   dest->s6_addr32[0], dest->s6_addr32[1],
+		   dest->s6_addr32[2], dest->s6_addr32[3],
+		   ntohs(req->rmt_port),
+		   TCP_SYN_RECV,
+		   0,0, /* could print option size, but that is af dependent. */
+		   1,   /* timers active (only the expire timer) */  
+		   ttd, 
+		   req->retrans,
+		   uid,
+		   0,  /* non standard timer */  
+		   0, /* open_requests have no inode */
+		   0, req);
 }
 
-static void get_tcp6_sock(struct sock *sp, char *tmpbuf, int i)
+static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
 {
 	struct in6_addr *dest, *src;
 	__u16 destp, srcp;
@@ -1993,28 +1998,29 @@
 		timer_expires = jiffies;
 	}
 
-	sprintf(tmpbuf,
-		"%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-		"%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d",
-		i,
-		src->s6_addr32[0], src->s6_addr32[1],
-		src->s6_addr32[2], src->s6_addr32[3], srcp,
-		dest->s6_addr32[0], dest->s6_addr32[1],
-		dest->s6_addr32[2], dest->s6_addr32[3], destp,
-		sp->state, 
-		tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq,
-		timer_active, timer_expires-jiffies,
-		tp->retransmits,
-		sock_i_uid(sp),
-		tp->probes_out,
-		sock_i_ino(sp),
-		atomic_read(&sp->refcnt), sp,
-		tp->rto, tp->ack.ato, (tp->ack.quick<<1)|tp->ack.pingpong,
-		tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh
-		);
+	seq_printf(seq,
+		   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
+		   "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d\n",
+		   i,
+		   src->s6_addr32[0], src->s6_addr32[1],
+		   src->s6_addr32[2], src->s6_addr32[3], srcp,
+		   dest->s6_addr32[0], dest->s6_addr32[1],
+		   dest->s6_addr32[2], dest->s6_addr32[3], destp,
+		   sp->state, 
+		   tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq,
+		   timer_active, timer_expires-jiffies,
+		   tp->retransmits,
+		   sock_i_uid(sp),
+		   tp->probes_out,
+		   sock_i_ino(sp),
+		   atomic_read(&sp->refcnt), sp,
+		   tp->rto, tp->ack.ato, (tp->ack.quick<<1)|tp->ack.pingpong,
+		   tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh
+		   );
 }
 
-static void get_timewait6_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i)
+static void get_timewait6_sock(struct seq_file *seq, 
+			       struct tcp_tw_bucket *tw, int i)
 {
 	struct in6_addr *dest, *src;
 	__u16 destp, srcp;
@@ -2028,144 +2034,67 @@
 	destp = ntohs(tw->dport);
 	srcp  = ntohs(tw->sport);
 
-	sprintf(tmpbuf,
-		"%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-		"%02X %08X:%08X %02X:%08X %08X %5d %8d %d %d %p",
-		i,
-		src->s6_addr32[0], src->s6_addr32[1],
-		src->s6_addr32[2], src->s6_addr32[3], srcp,
-		dest->s6_addr32[0], dest->s6_addr32[1],
-		dest->s6_addr32[2], dest->s6_addr32[3], destp,
-		tw->substate, 0, 0,
-		3, ttd, 0, 0, 0, 0,
-		atomic_read(&tw->refcnt), tw);
-}
-
-#define LINE_LEN 190
-#define LINE_FMT "%-190s\n"
-
-int tcp6_get_info(char *buffer, char **start, off_t offset, int length)
-{
-	int len = 0, num = 0, i;
-	off_t begin, pos = 0;
-	char tmpbuf[LINE_LEN+2];
-
-	if (offset < LINE_LEN+1)
-		len += sprintf(buffer, LINE_FMT,
-			       "  sl  "						/* 6 */
-			       "local_address                         "		/* 38 */
-			       "remote_address                        "		/* 38 */
-			       "st tx_queue rx_queue tr tm->when retrnsmt"	/* 41 */
-			       "   uid  timeout inode");			/* 21 */
-										/*----*/
-										/*144 */
-
-	pos = LINE_LEN+1;
-
-	/* First, walk listening socket table. */
-	tcp_listen_lock();
-	for(i = 0; i < TCP_LHTABLE_SIZE; i++) {
-		struct sock *sk = tcp_listening_hash[i];
-		struct tcp_listen_opt *lopt;
-		int k;
-
-		for (sk = tcp_listening_hash[i]; sk; sk = sk->next, num++) {
-			struct open_request *req;
-			int uid;
-			struct tcp_opt *tp = tcp_sk(sk);
-
-			if (sk->family != PF_INET6)
-				continue;
-			pos += LINE_LEN+1;
-			if (pos >= offset) {
-				get_tcp6_sock(sk, tmpbuf, num);
-				len += sprintf(buffer+len, LINE_FMT, tmpbuf);
-				if (pos >= offset + length) {
-					tcp_listen_unlock();
-					goto out_no_bh;
-				}
-			}
-
-			uid = sock_i_uid(sk);
-			read_lock_bh(&tp->syn_wait_lock);
-			lopt = tp->listen_opt;
-			if (lopt && lopt->qlen != 0) {
-				for (k=0; k<TCP_SYNQ_HSIZE; k++) {
-					for (req = lopt->syn_table[k]; req; req = req->dl_next, num++) {
-						if (req->class->family != PF_INET6)
-							continue;
-						pos += LINE_LEN+1;
-						if (pos <= offset)
-							continue;
-						get_openreq6(sk, req, tmpbuf, num, uid);
-						len += sprintf(buffer+len, LINE_FMT, tmpbuf);
-						if (pos >= offset + length) { 
-							read_unlock_bh(&tp->syn_wait_lock);
-							tcp_listen_unlock();
-							goto out_no_bh;
-						}
-					}
-				}
-			}
-			read_unlock_bh(&tp->syn_wait_lock);
-
-			/* Completed requests are in normal socket hash table */
-		}
+	seq_printf(seq,
+		   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
+		   "%02X %08X:%08X %02X:%08X %08X %5d %8d %d %d %p\n",
+		   i,
+		   src->s6_addr32[0], src->s6_addr32[1],
+		   src->s6_addr32[2], src->s6_addr32[3], srcp,
+		   dest->s6_addr32[0], dest->s6_addr32[1],
+		   dest->s6_addr32[2], dest->s6_addr32[3], destp,
+		   tw->substate, 0, 0,
+		   3, ttd, 0, 0, 0, 0,
+		   atomic_read(&tw->refcnt), tw);
+}
+
+static int tcp6_seq_show(struct seq_file *seq, void *v)
+{
+	struct tcp_iter_state *st;
+
+	if (v == (void *)1) {
+		seq_printf(seq,
+			   "  sl  "
+			   "local_address                         "
+			   "remote_address                        "
+			   "st tx_queue rx_queue tr tm->when retrnsmt"
+			   "   uid  timeout inode\n");
+		goto out;
 	}
-	tcp_listen_unlock();
-
-	local_bh_disable();
+	st = seq->private;
 
-	/* Next, walk established hash chain. */
-	for (i = 0; i < tcp_ehash_size; i++) {
-		struct tcp_ehash_bucket *head = &tcp_ehash[i];
-		struct sock *sk;
-		struct tcp_tw_bucket *tw;
-
-		read_lock(&head->lock);
-		for(sk = head->chain; sk; sk = sk->next, num++) {
-			if (sk->family != PF_INET6)
-				continue;
-			pos += LINE_LEN+1;
-			if (pos <= offset)
-				continue;
-			get_tcp6_sock(sk, tmpbuf, num);
-			len += sprintf(buffer+len, LINE_FMT, tmpbuf);
-			if (pos >= offset + length) {
-				read_unlock(&head->lock);
-				goto out;
-			}
-		}
-		for (tw = (struct tcp_tw_bucket *)tcp_ehash[i+tcp_ehash_size].chain;
-		     tw != NULL;
-		     tw = (struct tcp_tw_bucket *)tw->next, num++) {
-			if (tw->family != PF_INET6)
-				continue;
-			pos += LINE_LEN+1;
-			if (pos <= offset)
-				continue;
-			get_timewait6_sock(tw, tmpbuf, num);
-			len += sprintf(buffer+len, LINE_FMT, tmpbuf);
-			if (pos >= offset + length) {
-				read_unlock(&head->lock);
-				goto out;
-			}
-		}
-		read_unlock(&head->lock);
+	switch (st->state) {
+	case TCP_SEQ_STATE_LISTENING:
+	case TCP_SEQ_STATE_ESTABLISHED:
+		get_tcp6_sock(seq, v, st->num);
+		break;
+	case TCP_SEQ_STATE_OPENREQ:
+		get_openreq6(seq, st->syn_wait_sk, v, st->num, st->uid);
+		break;
+	case TCP_SEQ_STATE_TIME_WAIT:
+		get_timewait6_sock(seq, v, st->num);
+		break;
 	}
-
 out:
-	local_bh_enable();
-out_no_bh:
+	return 0;
+}
+
+static struct file_operations tcp6_seq_fops;
+static struct tcp_seq_afinfo tcp6_seq_afinfo = {
+	.owner		= THIS_MODULE,
+	.name		= "tcp6",
+	.family		= AF_INET6,
+	.seq_show	= tcp6_seq_show,
+	.seq_fops	= &tcp6_seq_fops,
+};
 
-	begin = len - (pos - offset);
-	*start = buffer + begin;
-	len -= begin;
-	if (len > length)
-		len = length;
-	if (len < 0)
-		len = 0; 
-	return len;
+int __init tcp6_proc_init(void)
+{
+	return tcp_proc_register(&tcp6_seq_afinfo);
+}
+
+void tcp6_proc_exit(void)
+{
+	tcp_proc_unregister(&tcp6_seq_afinfo);
 }
 
 struct proto tcpv6_prot = {
diff -urN linux-2.5.69-bk18/net/ipv6/udp.c linux-2.5.69-bk19/net/ipv6/udp.c
--- linux-2.5.69-bk18/net/ipv6/udp.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/ipv6/udp.c	2003-05-26 04:41:43.000000000 -0700
@@ -15,6 +15,7 @@
  *	Alexey Kuznetsov		allow both IPv4 and IPv6 sockets to bind
  *					a single port at the same time.
  *      Kazunori MIYAZAWA @USAGI:       change process style to use ip6_append_data
+ *      YOSHIFUJI Hideaki @USAGI:	convert /proc/net/udp6 to seq_file.
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -53,6 +54,9 @@
 #include <net/checksum.h>
 #include <net/xfrm.h>
 
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
 DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6);
 
 /* XXX This is identical to tcp_ipv6.c:ipv6_rcv_saddr_equal, put
@@ -1116,10 +1120,10 @@
 	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 
-#define LINE_LEN 190
-#define LINE_FMT "%-190s\n"
+/* ------------------------------------------------------------------------ */
+#ifdef CONFIG_PROC_FS
 
-static void get_udp6_sock(struct sock *sp, char *tmpbuf, int i)
+static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket)
 {
 	struct inet_opt *inet = inet_sk(sp);
 	struct ipv6_pinfo *np = inet6_sk(sp);
@@ -1130,66 +1134,56 @@
 	src   = &np->rcv_saddr;
 	destp = ntohs(inet->dport);
 	srcp  = ntohs(inet->sport);
-	sprintf(tmpbuf,
-		"%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-		"%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
-		i,
-		src->s6_addr32[0], src->s6_addr32[1],
-		src->s6_addr32[2], src->s6_addr32[3], srcp,
-		dest->s6_addr32[0], dest->s6_addr32[1],
-		dest->s6_addr32[2], dest->s6_addr32[3], destp,
-		sp->state, 
-		atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
-		0, 0L, 0,
-		sock_i_uid(sp), 0,
-		sock_i_ino(sp),
-		atomic_read(&sp->refcnt), sp);
-}
-
-int udp6_get_info(char *buffer, char **start, off_t offset, int length)
-{
-	int len = 0, num = 0, i;
-	off_t pos = 0;
-	off_t begin;
-	char tmpbuf[LINE_LEN+2];
-
-	if (offset < LINE_LEN+1)
-		len += sprintf(buffer, LINE_FMT,
-			       "  sl  "						/* 6 */
-			       "local_address                         "		/* 38 */
-			       "remote_address                        "		/* 38 */
-			       "st tx_queue rx_queue tr tm->when retrnsmt"	/* 41 */
-			       "   uid  timeout inode");			/* 21 */
-										/*----*/
-										/*144 */
-	pos = LINE_LEN+1;
-	read_lock(&udp_hash_lock);
-	for (i = 0; i < UDP_HTABLE_SIZE; i++) {
-		struct sock *sk;
+	seq_printf(seq,
+		   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
+		   "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p\n",
+		   bucket,
+		   src->s6_addr32[0], src->s6_addr32[1],
+		   src->s6_addr32[2], src->s6_addr32[3], srcp,
+		   dest->s6_addr32[0], dest->s6_addr32[1],
+		   dest->s6_addr32[2], dest->s6_addr32[3], destp,
+		   sp->state, 
+		   atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),
+		   0, 0L, 0,
+		   sock_i_uid(sp), 0,
+		   sock_i_ino(sp),
+		   atomic_read(&sp->refcnt), sp);
+}
+
+static int udp6_seq_show(struct seq_file *seq, void *v)
+{
+	if (v == (void *)1)
+		seq_printf(seq,
+			   "  sl  "
+			   "local_address                         "
+			   "remote_address                        "
+			   "st tx_queue rx_queue tr tm->when retrnsmt"
+			   "   uid  timeout inode\n");
+	else
+		udp6_sock_seq_show(seq, v, ((struct udp_iter_state *)seq->private)->bucket);
+	return 0;
+}
 
-		for (sk = udp_hash[i]; sk; sk = sk->next, num++) {
-			if (sk->family != PF_INET6)
-				continue;
-			pos += LINE_LEN+1;
-			if (pos <= offset)
-				continue;
-			get_udp6_sock(sk, tmpbuf, i);
-			len += sprintf(buffer+len, LINE_FMT, tmpbuf);
-			if(len >= length)
-				goto out;
-		}
-	}
-out:
-	read_unlock(&udp_hash_lock);
-	begin = len - (pos - offset);
-	*start = buffer + begin;
-	len -= begin;
-	if(len > length)
-		len = length;
-	if (len < 0)
-		len = 0; 
-	return len;
+static struct file_operations udp6_seq_fops;
+static struct udp_seq_afinfo udp6_seq_afinfo = {
+	.owner		= THIS_MODULE,
+	.name		= "udp6",
+	.family		= AF_INET6,
+	.seq_show	= udp6_seq_show,
+	.seq_fops	= &udp6_seq_fops,
+};
+
+int __init udp6_proc_init(void)
+{
+	return udp_proc_register(&udp6_seq_afinfo);
+}
+
+void udp6_proc_exit(void) {
+	udp_proc_unregister(&udp6_seq_afinfo);
 }
+#endif /* CONFIG_PROC_FS */
+
+/* ------------------------------------------------------------------------ */
 
 struct proto udpv6_prot = {
 	.name =		"UDP",
diff -urN linux-2.5.69-bk18/net/irda/af_irda.c linux-2.5.69-bk19/net/irda/af_irda.c
--- linux-2.5.69-bk18/net/irda/af_irda.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/af_irda.c	2003-05-26 04:41:43.000000000 -0700
@@ -11,7 +11,7 @@
  * Sources:       af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
  *
  *     Copyright (c) 1999 Dag Brattli <dagb@cs.uit.no>
- *     Copyright (c) 1999-2001 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 1999-2003 Jean Tourrilhes <jt@hpl.hp.com>
  *     All Rights Reserved.
  *
  *     This program is free software; you can redistribute it and/or
@@ -190,6 +190,9 @@
 	if (sk == NULL)
 		return;
 
+	dev_kfree_skb(skb);
+	// Should be ??? skb_queue_tail(&sk->receive_queue, skb);
+
 	/* How much header space do we need to reserve */
 	self->max_header_size = max_header_size;
 
@@ -220,8 +223,6 @@
 		   self->max_data_size);
 
 	memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
-	dev_kfree_skb(skb);
-	// Should be ??? skb_queue_tail(&sk->receive_queue, skb);
 
 	/* We are now connected! */
 	sk->state = TCP_ESTABLISHED;
@@ -260,6 +261,7 @@
 	case SOCK_STREAM:
 		if (max_sdu_size != 0) {
 			ERROR("%s: max_sdu_size must be 0\n", __FUNCTION__);
+			kfree_skb(skb);
 			return;
 		}
 		self->max_data_size = irttp_get_max_seg_size(self->tsap);
@@ -267,6 +269,7 @@
 	case SOCK_SEQPACKET:
 		if (max_sdu_size == 0) {
 			ERROR("%s: max_sdu_size cannot be 0\n", __FUNCTION__);
+			kfree_skb(skb);
 			return;
 		}
 		self->max_data_size = max_sdu_size;
@@ -359,7 +362,7 @@
  * doesn't touch the dtsap_sel and save the full value structure...
  */
 static void irda_getvalue_confirm(int result, __u16 obj_id,
-					  struct ias_value *value, void *priv)
+				  struct ias_value *value, void *priv)
 {
 	struct irda_sock *self;
 
@@ -908,6 +911,7 @@
 	new->tsap = irttp_dup(self->tsap, new);
 	if (!new->tsap) {
 		IRDA_DEBUG(0, "%s(), dup failed!\n", __FUNCTION__);
+		kfree_skb(skb);
 		return -1;
 	}
 
@@ -926,6 +930,7 @@
 	/* Clean up the original one to keep it in listen state */
 	irttp_listen(self->tsap);
 
+	/* Wow ! What is that ? Jean II */
 	skb->sk = NULL;
 	skb->destructor = NULL;
 	kfree_skb(skb);
diff -urN linux-2.5.69-bk18/net/irda/ircomm/ircomm_core.c linux-2.5.69-bk19/net/irda/ircomm/ircomm_core.c
--- linux-2.5.69-bk18/net/irda/ircomm/ircomm_core.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/ircomm/ircomm_core.c	2003-05-26 04:41:43.000000000 -0700
@@ -10,6 +10,7 @@
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -251,7 +252,6 @@
 						info->max_header_size, skb);
 	else {
 		IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
-		dev_kfree_skb(skb);
 	}
 }
 
@@ -295,7 +295,6 @@
 					     info->max_header_size, skb);
 	else {
 		IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
-		dev_kfree_skb(skb);
 	}
 }
 
@@ -338,7 +337,6 @@
 		self->notify.data_indication(self->notify.instance, self, skb);
 	else {
 		IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
-		dev_kfree_skb(skb);
 	}
 }
 
@@ -370,9 +368,8 @@
 	if (skb->len)
 		ircomm_data_indication(self, skb);		
 	else {
-		IRDA_DEBUG(4, 
-			   "%s(), data was control info only!\n", __FUNCTION__ );
-		dev_kfree_skb(skb);
+		IRDA_DEBUG(4, "%s(), data was control info only!\n",
+			   __FUNCTION__ );
 	}
 }
 
@@ -408,24 +405,28 @@
 static void ircomm_control_indication(struct ircomm_cb *self, 
 				      struct sk_buff *skb, int clen)
 {
-	struct sk_buff *ctrl_skb;
-
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );	
 
-	ctrl_skb = skb_clone(skb, GFP_ATOMIC);
-	if (!ctrl_skb)
-		return;
+	/* Use udata for delivering data on the control channel */
+	if (self->notify.udata_indication) {
+		struct sk_buff *ctrl_skb;
+
+		/* We don't own the skb, so clone it */
+		ctrl_skb = skb_clone(skb, GFP_ATOMIC);
+		if (!ctrl_skb)
+			return;
 
-	/* Remove data channel from control channel */
-	skb_trim(ctrl_skb, clen+1);
+		/* Remove data channel from control channel */
+		skb_trim(ctrl_skb, clen+1);
 	
-	/* Use udata for delivering data on the control channel */
-	if (self->notify.udata_indication)
 		self->notify.udata_indication(self->notify.instance, self, 
 					      ctrl_skb);
-	else {
+
+		/* Drop reference count -
+		 * see ircomm_tty_control_indication(). */
+		dev_kfree_skb(ctrl_skb);
+	} else {
 		IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
-		dev_kfree_skb(skb);
 	}
 }
 
@@ -470,7 +471,6 @@
 						   info->reason, skb);
 	} else {
 		IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
-		dev_kfree_skb(skb);
 	}
 }
 
diff -urN linux-2.5.69-bk18/net/irda/ircomm/ircomm_event.c linux-2.5.69-bk19/net/irda/ircomm/ircomm_event.c
--- linux-2.5.69-bk18/net/irda/ircomm/ircomm_event.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/ircomm/ircomm_event.c	2003-05-26 04:41:43.000000000 -0700
@@ -109,9 +109,7 @@
 	default:
 		IRDA_DEBUG(4, "%s(), unknown event: %s\n", __FUNCTION__ ,
 			   ircomm_event[event]);
-		if (skb)
-			dev_kfree_skb(skb);
-		return -EINVAL;
+		ret = -EINVAL;
 	}
 	return ret;
 }
@@ -141,8 +139,6 @@
 	default:
 		IRDA_DEBUG(0, "%s(), unknown event: %s\n", __FUNCTION__ ,
 			   ircomm_event[event]);
-		if (skb)
-			dev_kfree_skb(skb);
 		ret = -EINVAL;
 	}
 	return ret;
@@ -176,8 +172,6 @@
 	default:
 		IRDA_DEBUG(0, "%s(), unknown event = %s\n", __FUNCTION__ ,
 			   ircomm_event[event]);
-		if (skb)
-			dev_kfree_skb(skb);
 		ret = -EINVAL;
 	}
 	return ret;
@@ -220,8 +214,6 @@
 	default:
 		IRDA_DEBUG(0, "%s(), unknown event = %s\n", __FUNCTION__ ,
 			   ircomm_event[event]);
-		if (skb)
-			dev_kfree_skb(skb);
 		ret = -EINVAL;
 	}
 	return ret;
diff -urN linux-2.5.69-bk18/net/irda/ircomm/ircomm_lmp.c linux-2.5.69-bk19/net/irda/ircomm/ircomm_lmp.c
--- linux-2.5.69-bk18/net/irda/ircomm/ircomm_lmp.c	2003-05-04 16:52:50.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/ircomm/ircomm_lmp.c	2003-05-26 04:41:43.000000000 -0700
@@ -11,6 +11,7 @@
  * Sources:       Previous IrLPT work by Thomas Davis
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -59,7 +60,7 @@
         notify.connect_indication    = ircomm_lmp_connect_indication;
 	notify.disconnect_indication = ircomm_lmp_disconnect_indication;
 	notify.instance = self;
-	strncpy(notify.name, "IrCOMM", NOTIFY_MAX_NAME);
+	strlcpy(notify.name, "IrCOMM", sizeof(notify.name));
 
 	self->lsap = irlmp_open_lsap(LSAP_ANY, &notify, 0);
 	if (!self->lsap) {
@@ -93,6 +94,10 @@
 
 	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
 
+	/* Don't forget to refcount it - should be NULL anyway */
+	if(userdata)
+		skb_get(userdata);
+
 	ret = irlmp_connect_request(self->lsap, info->dlsap_sel,
 				    info->saddr, info->daddr, NULL, userdata); 
 	return ret;
@@ -106,29 +111,32 @@
  */
 int ircomm_lmp_connect_response(struct ircomm_cb *self, struct sk_buff *userdata)
 {
-	struct sk_buff *skb;
+	struct sk_buff *tx_skb;
 	int ret;
 
 	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
 	
 	/* Any userdata supplied? */
 	if (userdata == NULL) {
-		skb = dev_alloc_skb(64);
-		if (!skb)
+		tx_skb = dev_alloc_skb(64);
+		if (!tx_skb)
 			return -ENOMEM;
 
 		/* Reserve space for MUX and LAP header */
-		skb_reserve(skb, LMP_MAX_HEADER);
+		skb_reserve(tx_skb, LMP_MAX_HEADER);
 	} else {
-		skb = userdata;
 		/*  
 		 *  Check that the client has reserved enough space for 
 		 *  headers
 		 */
-		ASSERT(skb_headroom(skb) >= LMP_MAX_HEADER, return -1;);
+		ASSERT(skb_headroom(userdata) >= LMP_MAX_HEADER, return -1;);
+
+		/* Don't forget to refcount it - should be NULL anyway */
+		skb_get(userdata);
+		tx_skb = userdata;
 	}
 
-	ret = irlmp_connect_response(self->lsap, skb);
+	ret = irlmp_connect_response(self->lsap, tx_skb);
 
 	return 0;
 }
@@ -137,20 +145,24 @@
 				  struct sk_buff *userdata, 
 				  struct ircomm_info *info)
 {
-        struct sk_buff *skb;
+        struct sk_buff *tx_skb;
 	int ret;
 
 	IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
 
         if (!userdata) {
-                skb = dev_alloc_skb(64);
-		if (!skb)
+		tx_skb = dev_alloc_skb(64);
+		if (!tx_skb)
 			return -ENOMEM;
 		
 		/*  Reserve space for MUX and LAP header */
-		skb_reserve(skb, LMP_MAX_HEADER);		
-		userdata = skb;
+		skb_reserve(tx_skb, LMP_MAX_HEADER);		
+		userdata = tx_skb;
+	} else {
+		/* Don't forget to refcount it - should be NULL anyway */
+		skb_get(userdata);
 	}
+
 	ret = irlmp_disconnect_request(self->lsap, userdata);
 
 	return ret;
@@ -217,8 +229,11 @@
 
 	IRDA_DEBUG(4, "%s(), sending frame\n", __FUNCTION__ );
 
+	/* Don't forget to refcount it - see ircomm_tty_do_softint() */
+	skb_get(skb);
+
 	skb->destructor = ircomm_lmp_flow_control;
-	
+
         if ((self->pkt_count++ > 7) && (self->flow_status == FLOW_START)) {
 		IRDA_DEBUG(2, "%s(), asking TTY to slow down!\n", __FUNCTION__ );
 	        self->flow_status = FLOW_STOP;
@@ -229,7 +244,7 @@
 	ret = irlmp_data_request(self->lsap, skb);
 	if (ret) {
 		ERROR("%s(), failed\n", __FUNCTION__);
-		dev_kfree_skb(skb);
+		/* irlmp_data_request already free the packet */
 	}
 
 	return ret;
@@ -254,6 +269,9 @@
 	
 	ircomm_do_event(self, IRCOMM_LMP_DATA_INDICATION, skb, NULL);
 
+	/* Drop reference count - see ircomm_tty_data_indication(). */
+	dev_kfree_skb(skb);
+
 	return 0;
 }
 
@@ -285,6 +303,9 @@
 	info.qos = qos;
 
 	ircomm_do_event(self, IRCOMM_LMP_CONNECT_CONFIRM, skb, &info);
+
+	/* Drop reference count - see ircomm_tty_connect_confirm(). */
+	dev_kfree_skb(skb);
 }
 
 /*
@@ -315,6 +336,9 @@
 	info.qos = qos;
 
 	ircomm_do_event(self, IRCOMM_LMP_CONNECT_INDICATION, skb, &info);
+
+	/* Drop reference count - see ircomm_tty_connect_indication(). */
+	dev_kfree_skb(skb);
 }
 
 /*
@@ -338,4 +362,8 @@
 	info.reason = reason;
 
 	ircomm_do_event(self, IRCOMM_LMP_DISCONNECT_INDICATION, skb, &info);
+
+	/* Drop reference count - see ircomm_tty_disconnect_indication(). */
+	if(skb)
+		dev_kfree_skb(skb);
 }
diff -urN linux-2.5.69-bk18/net/irda/ircomm/ircomm_ttp.c linux-2.5.69-bk19/net/irda/ircomm/ircomm_ttp.c
--- linux-2.5.69-bk18/net/irda/ircomm/ircomm_ttp.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/ircomm/ircomm_ttp.c	2003-05-26 04:41:43.000000000 -0700
@@ -10,6 +10,7 @@
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -59,7 +60,7 @@
 	notify.flow_indication       = ircomm_ttp_flow_indication;
 	notify.disconnect_indication = ircomm_ttp_disconnect_indication;
 	notify.instance = self;
-	strncpy(notify.name, "IrCOMM", NOTIFY_MAX_NAME);
+	strlcpy(notify.name, "IrCOMM", sizeof(notify.name));
 
 	self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
 				     &notify);
@@ -94,9 +95,14 @@
 
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 
+	/* Don't forget to refcount it - should be NULL anyway */
+	if(userdata)
+		skb_get(userdata);
+
 	ret = irttp_connect_request(self->tsap, info->dlsap_sel,
 				    info->saddr, info->daddr, NULL, 
 				    TTP_SAR_DISABLE, userdata); 
+
 	return ret;
 }	
 
@@ -106,13 +112,18 @@
  *    
  *
  */
-int ircomm_ttp_connect_response(struct ircomm_cb *self, struct sk_buff *skb)
+int ircomm_ttp_connect_response(struct ircomm_cb *self,
+				struct sk_buff *userdata)
 {
 	int ret;
 
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
 	
-	ret = irttp_connect_response(self->tsap, TTP_SAR_DISABLE, skb);
+	/* Don't forget to refcount it - should be NULL anyway */
+	if(userdata)
+		skb_get(userdata);
+
+	ret = irttp_connect_response(self->tsap, TTP_SAR_DISABLE, userdata);
 
 	return ret;
 }
@@ -126,7 +137,8 @@
  *    some of them are sent after connection establishment, so this can 
  *    increase the latency a bit.
  */
-int ircomm_ttp_data_request(struct ircomm_cb *self, struct sk_buff *skb, 
+int ircomm_ttp_data_request(struct ircomm_cb *self,
+			    struct sk_buff *skb, 
 			    int clen)
 {
 	int ret;
@@ -140,6 +152,10 @@
 	 * only frames, to make things easier and avoid queueing
 	 */
 	ASSERT(skb_headroom(skb) >= IRCOMM_HEADER_SIZE, return -1;);
+
+	/* Don't forget to refcount it - see ircomm_tty_do_softint() */
+	skb_get(skb);
+
 	skb_push(skb, IRCOMM_HEADER_SIZE);
 
 	skb->data[0] = clen;
@@ -147,7 +163,7 @@
 	ret = irttp_data_request(self->tsap, skb);
 	if (ret) {
 		ERROR("%s(), failed\n", __FUNCTION__);
-		dev_kfree_skb(skb);
+		/* irttp_data_request already free the packet */
 	}
 
 	return ret;
@@ -172,6 +188,9 @@
 
 	ircomm_do_event(self, IRCOMM_TTP_DATA_INDICATION, skb, NULL);
 
+	/* Drop reference count - see ircomm_tty_data_indication(). */
+	dev_kfree_skb(skb);
+
 	return 0;
 }
 
@@ -189,12 +208,11 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRCOMM_MAGIC, return;);
 	ASSERT(skb != NULL, return;);
-	ASSERT(qos != NULL, return;);
+	ASSERT(qos != NULL, goto out;);
 
 	if (max_sdu_size != TTP_SAR_DISABLE) {
 		ERROR("%s(), SAR not allowed for IrCOMM!\n", __FUNCTION__);
-		dev_kfree_skb(skb);
-		return;
+		goto out;
 	}
 
 	info.max_data_size = irttp_get_max_seg_size(self->tsap)
@@ -203,6 +221,10 @@
 	info.qos = qos;
 
 	ircomm_do_event(self, IRCOMM_TTP_CONNECT_CONFIRM, skb, &info);
+
+out:
+	/* Drop reference count - see ircomm_tty_connect_confirm(). */
+	dev_kfree_skb(skb);
 }
 
 /*
@@ -226,12 +248,11 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRCOMM_MAGIC, return;);
 	ASSERT(skb != NULL, return;);
-	ASSERT(qos != NULL, return;);
+	ASSERT(qos != NULL, goto out;);
 
 	if (max_sdu_size != TTP_SAR_DISABLE) {
 		ERROR("%s(), SAR not allowed for IrCOMM!\n", __FUNCTION__);
-		dev_kfree_skb(skb);
-		return;
+		goto out;
 	}
 
 	info.max_data_size = irttp_get_max_seg_size(self->tsap)
@@ -240,6 +261,10 @@
 	info.qos = qos;
 
 	ircomm_do_event(self, IRCOMM_TTP_CONNECT_INDICATION, skb, &info);
+
+out:
+	/* Drop reference count - see ircomm_tty_connect_indication(). */
+	dev_kfree_skb(skb);
 }
 
 /*
@@ -254,6 +279,10 @@
 {
 	int ret;
 
+	/* Don't forget to refcount it - should be NULL anyway */
+	if(userdata)
+		skb_get(userdata);
+
 	ret = irttp_disconnect_request(self->tsap, userdata, P_NORMAL);
 
 	return ret;
@@ -280,6 +309,10 @@
 	info.reason = reason;
 
 	ircomm_do_event(self, IRCOMM_TTP_DISCONNECT_INDICATION, skb, &info);
+
+	/* Drop reference count - see ircomm_tty_disconnect_indication(). */
+	if(skb)
+		dev_kfree_skb(skb);
 }
 
 /*
diff -urN linux-2.5.69-bk18/net/irda/ircomm/ircomm_tty.c linux-2.5.69-bk19/net/irda/ircomm/ircomm_tty.c
--- linux-2.5.69-bk18/net/irda/ircomm/ircomm_tty.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/ircomm/ircomm_tty.c	2003-05-26 04:41:43.000000000 -0700
@@ -11,6 +11,7 @@
  * Sources:       serial.c and previous IrCOMM work by Takahide Higuchi
  * 
  *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -204,7 +205,7 @@
  	notify.disconnect_indication = ircomm_tty_disconnect_indication;
 	notify.connect_confirm       = ircomm_tty_connect_confirm;
  	notify.connect_indication    = ircomm_tty_connect_indication;
-	strncpy(notify.name, "ircomm_tty", NOTIFY_MAX_NAME);
+	strlcpy(notify.name, "ircomm_tty", sizeof(notify.name));
 	notify.instance = self;
 
 	if (!self->ircomm) {
@@ -663,8 +664,12 @@
 	spin_unlock_irqrestore(&self->spinlock, flags);
 
 	/* Flush control buffer if any */
-	if (ctrl_skb && self->flow == FLOW_START)
-		ircomm_control_request(self->ircomm, ctrl_skb);
+	if(ctrl_skb) {
+		if(self->flow == FLOW_START)
+			ircomm_control_request(self->ircomm, ctrl_skb);
+		/* Drop reference count - see ircomm_ttp_data_request(). */
+		dev_kfree_skb(ctrl_skb);
+	}
 
 	if (tty->hw_stopped)
 		return;
@@ -678,8 +683,11 @@
 	spin_unlock_irqrestore(&self->spinlock, flags);
 
 	/* Flush transmit buffer if any */
-	if (skb)
+	if (skb) {
 		ircomm_tty_do_event(self, IRCOMM_TTY_DATA_REQUEST, skb, NULL);
+		/* Drop reference count - see ircomm_ttp_data_request(). */
+		dev_kfree_skb(skb);
+	}
 		
 	/* Check if user (still) wants to be waken up */
 	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && 
@@ -1179,7 +1187,6 @@
 
 	if (!self->tty) {
 		IRDA_DEBUG(0, "%s(), no tty!\n", __FUNCTION__ );
-		dev_kfree_skb(skb);
 		return 0;
 	}
 
@@ -1204,7 +1211,8 @@
 	 * handler
 	 */
 	self->tty->ldisc.receive_buf(self->tty, skb->data, NULL, skb->len);
-	dev_kfree_skb(skb);
+
+	/* No need to kfree_skb - see ircomm_ttp_data_indication() */
 
 	return 0;
 }
@@ -1231,7 +1239,8 @@
 
 	irda_param_extract_all(self, skb->data+1, IRDA_MIN(skb->len-1, clen), 
 			       &ircomm_param_info);
-	dev_kfree_skb(skb);
+
+	/* No need to kfree_skb - see ircomm_control_indication() */
 
 	return 0;
 }
diff -urN linux-2.5.69-bk18/net/irda/ircomm/ircomm_tty_attach.c linux-2.5.69-bk19/net/irda/ircomm/ircomm_tty_attach.c
--- linux-2.5.69-bk18/net/irda/ircomm/ircomm_tty_attach.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/ircomm/ircomm_tty_attach.c	2003-05-26 04:41:43.000000000 -0700
@@ -10,6 +10,7 @@
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -236,8 +237,9 @@
 		irias_insert_object(self->obj);
 	}
 	self->skey = irlmp_register_service(hints);
-	self->ckey = irlmp_register_client(
-		hints, ircomm_tty_discovery_indication, NULL, (void *) self);
+	self->ckey = irlmp_register_client(hints,
+					   ircomm_tty_discovery_indication,
+					   NULL, (void *) self);
 }
 
 /*
@@ -459,7 +461,7 @@
 
 	ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_CONFIRM, NULL, NULL);
 
-	dev_kfree_skb(skb);
+	/* No need to kfree_skb - see ircomm_ttp_connect_confirm() */
 }
 
 /*
@@ -496,7 +498,7 @@
 
 	ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_INDICATION, NULL, NULL);
 
-	dev_kfree_skb(skb);
+	/* No need to kfree_skb - see ircomm_ttp_connect_indication() */
 }
 
 /*
@@ -647,7 +649,7 @@
 	default:
 		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
 			   ircomm_tty_event[event]);
-		return -EINVAL;
+		ret = -EINVAL;
 	}
 	return ret;
 }
@@ -718,7 +720,7 @@
 	default:
 		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
 			   ircomm_tty_event[event]);
-		return -EINVAL;
+		ret = -EINVAL;
 	}
 	return ret;
 }
@@ -774,7 +776,7 @@
 	default:
 		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
 			   ircomm_tty_event[event]);
-		return -EINVAL;
+		ret = -EINVAL;
 	}
 	return ret;
 }
@@ -822,7 +824,7 @@
 	default:
 		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
 			   ircomm_tty_event[event]);
-		return -EINVAL;
+		ret = -EINVAL;
 	}
 	return ret;
 }
@@ -874,7 +876,7 @@
 	default:
 		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
 			   ircomm_tty_event[event]);
-		return -EINVAL;
+		ret = -EINVAL;
 	}
 	return ret;
 }
@@ -917,7 +919,7 @@
 	default:
 		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
 			   ircomm_tty_event[event]);
-		return -EINVAL;
+		ret = -EINVAL;
 	}
 	return ret;
 }
diff -urN linux-2.5.69-bk18/net/irda/irda_device.c linux-2.5.69-bk19/net/irda/irda_device.c
--- linux-2.5.69-bk18/net/irda/irda_device.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irda_device.c	2003-05-26 04:41:43.000000000 -0700
@@ -532,6 +532,7 @@
 	return ret;
 }
 
+#ifdef CONFIG_ISA
 /*
  * Function setup_dma (idev, buffer, count, mode)
  *
@@ -553,3 +554,4 @@
 
 	release_dma_lock(flags);
 }
+#endif
diff -urN linux-2.5.69-bk18/net/irda/iriap.c linux-2.5.69-bk19/net/irda/iriap.c
--- linux-2.5.69-bk18/net/irda/iriap.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/iriap.c	2003-05-26 04:41:43.000000000 -0700
@@ -11,7 +11,7 @@
  *
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
  *     All Rights Reserved.
- *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License as
@@ -210,8 +210,8 @@
 
 	del_timer(&self->watchdog_timer);
 
-	if (self->skb)
-		dev_kfree_skb(self->skb);
+	if (self->request_skb)
+		dev_kfree_skb(self->request_skb);
 
 	self->magic = 0;
 
@@ -278,7 +278,7 @@
  */
 static void iriap_disconnect_indication(void *instance, void *sap,
 					LM_REASON reason,
-					struct sk_buff *userdata)
+					struct sk_buff *skb)
 {
 	struct iriap_cb *self;
 
@@ -293,6 +293,10 @@
 
 	del_timer(&self->watchdog_timer);
 
+	/* Not needed */
+	if (skb)
+		dev_kfree_skb(skb);
+
 	if (self->mode == IAS_CLIENT) {
 		IRDA_DEBUG(4, "%s(), disconnect as client\n", __FUNCTION__);
 
@@ -312,9 +316,6 @@
 				      NULL);
 		iriap_close(self);
 	}
-
-	if (userdata)
-		dev_kfree_skb(userdata);
 }
 
 /*
@@ -322,15 +323,15 @@
  */
 void iriap_disconnect_request(struct iriap_cb *self)
 {
-	struct sk_buff *skb;
+	struct sk_buff *tx_skb;
 
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	skb = dev_alloc_skb(64);
-	if (skb == NULL) {
+	tx_skb = dev_alloc_skb(64);
+	if (tx_skb == NULL) {
 		IRDA_DEBUG(0, "%s(), Could not allocate an sk_buff of length %d\n", 
 			__FUNCTION__, 64);
 		return;
@@ -339,9 +340,9 @@
 	/*
 	 *  Reserve space for MUX control and LAP header
 	 */
-	skb_reserve(skb, LMP_MAX_HEADER);
+	skb_reserve(tx_skb, LMP_MAX_HEADER);
 
-	irlmp_disconnect_request(self->lsap, skb);
+	irlmp_disconnect_request(self->lsap, tx_skb);
 }
 
 void iriap_getinfobasedetails_request(void)
@@ -379,7 +380,7 @@
 				  __u32 saddr, __u32 daddr,
 				  char *name, char *attr)
 {
-	struct sk_buff *skb;
+	struct sk_buff *tx_skb;
 	int name_len, attr_len, skb_len;
 	__u8 *frame;
 
@@ -405,14 +406,14 @@
 	attr_len = strlen(attr);	/* Up to IAS_MAX_ATTRIBNAME = 60 */
 
 	skb_len = self->max_header_size+2+name_len+1+attr_len+4;
-	skb = dev_alloc_skb(skb_len);
-	if (!skb)
+	tx_skb = dev_alloc_skb(skb_len);
+	if (!tx_skb)
 		return -ENOMEM;
 
 	/* Reserve space for MUX and LAP header */
-	skb_reserve(skb, self->max_header_size);
-	skb_put(skb, 3+name_len+attr_len);
-	frame = skb->data;
+	skb_reserve(tx_skb, self->max_header_size);
+	skb_put(tx_skb, 3+name_len+attr_len);
+	frame = tx_skb->data;
 
 	/* Build frame */
 	frame[0] = IAP_LST | GET_VALUE_BY_CLASS;
@@ -421,7 +422,10 @@
 	frame[2+name_len] = attr_len;              /* Insert length of attr */
 	memcpy(frame+3+name_len, attr, attr_len);  /* Insert attr */
 
-	iriap_do_client_event(self, IAP_CALL_REQUEST_GVBC, skb);
+	iriap_do_client_event(self, IAP_CALL_REQUEST_GVBC, tx_skb);
+
+	/* Drop reference count - see state_s_disconnect(). */
+	dev_kfree_skb(tx_skb);
 
 	return 0;
 }
@@ -495,7 +499,6 @@
 
 			/* Aborting, close connection! */
 			iriap_disconnect_request(self);
-			dev_kfree_skb(skb);
 			return;
 			/* break; */
 		}
@@ -533,7 +536,6 @@
 		IRDA_DEBUG(0, "%s(), missing handler!\n", __FUNCTION__);
 		irias_delete_value(value);
 	}
-	dev_kfree_skb(skb);
 }
 
 /*
@@ -545,7 +547,7 @@
 void iriap_getvaluebyclass_response(struct iriap_cb *self, __u16 obj_id,
 				    __u8 ret_code, struct ias_value *value)
 {
-	struct sk_buff *skb;
+	struct sk_buff *tx_skb;
 	int n;
 	__u32 tmp_be32, tmp_be16;
 	__u8 *fp;
@@ -565,15 +567,15 @@
 	 *  value. We add 32 bytes because of the 6 bytes for the frame and
 	 *  max 5 bytes for the value coding.
 	 */
-	skb = dev_alloc_skb(value->len + self->max_header_size + 32);
-	if (!skb)
+	tx_skb = dev_alloc_skb(value->len + self->max_header_size + 32);
+	if (!tx_skb)
 		return;
 
 	/* Reserve space for MUX and LAP header */
-	skb_reserve(skb, self->max_header_size);
-	skb_put(skb, 6);
+	skb_reserve(tx_skb, self->max_header_size);
+	skb_put(tx_skb, 6);
 
-	fp = skb->data;
+	fp = tx_skb->data;
 
 	/* Build frame */
 	fp[n++] = GET_VALUE_BY_CLASS | IAP_LST;
@@ -589,21 +591,21 @@
 
 	switch (value->type) {
 	case IAS_STRING:
-		skb_put(skb, 3 + value->len);
+		skb_put(tx_skb, 3 + value->len);
 		fp[n++] = value->type;
 		fp[n++] = 0; /* ASCII */
 		fp[n++] = (__u8) value->len;
 		memcpy(fp+n, value->t.string, value->len); n+=value->len;
 		break;
 	case IAS_INTEGER:
-		skb_put(skb, 5);
+		skb_put(tx_skb, 5);
 		fp[n++] = value->type;
 
 		tmp_be32 = cpu_to_be32(value->t.integer);
 		memcpy(fp+n, &tmp_be32, 4); n += 4;
 		break;
 	case IAS_OCT_SEQ:
-		skb_put(skb, 3 + value->len);
+		skb_put(tx_skb, 3 + value->len);
 		fp[n++] = value->type;
 
 		tmp_be16 = cpu_to_be16(value->len);
@@ -612,14 +614,17 @@
 		break;
 	case IAS_MISSING:
 		IRDA_DEBUG( 3, "%s: sending IAS_MISSING\n", __FUNCTION__);
-		skb_put(skb, 1);
+		skb_put(tx_skb, 1);
 		fp[n++] = value->type;
 		break;
 	default:
 		IRDA_DEBUG(0, "%s(), type not implemented!\n", __FUNCTION__);
 		break;
 	}
-	iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, skb);
+	iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, tx_skb);
+
+	/* Drop reference count - see state_r_execute(). */
+	dev_kfree_skb(tx_skb);
 }
 
 /*
@@ -657,9 +662,6 @@
 	memcpy(attr, fp+n, attr_len); n+=attr_len;
 	attr[attr_len] = '\0';
 
-	/* We do not need the buffer anymore */
-	dev_kfree_skb(skb);
-
 	IRDA_DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
 	obj = irias_find_object(name);
 
@@ -694,7 +696,7 @@
  */
 void iriap_send_ack(struct iriap_cb *self)
 {
-	struct sk_buff *skb;
+	struct sk_buff *tx_skb;
 	__u8 *frame;
 
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
@@ -702,19 +704,19 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	skb = dev_alloc_skb(64);
-	if (!skb)
+	tx_skb = dev_alloc_skb(64);
+	if (!tx_skb)
 		return;
 
 	/* Reserve space for MUX and LAP header */
-	skb_reserve(skb, self->max_header_size);
-	skb_put(skb, 1);
-	frame = skb->data;
+	skb_reserve(tx_skb, self->max_header_size);
+	skb_put(tx_skb, 1);
+	frame = tx_skb->data;
 
 	/* Build frame */
 	frame[0] = IAP_LST | IAP_ACK | self->operation;
 
-	irlmp_data_request(self->lsap, skb);
+	irlmp_data_request(self->lsap, tx_skb);
 }
 
 void iriap_connect_request(struct iriap_cb *self)
@@ -742,7 +744,7 @@
 static void iriap_connect_confirm(void *instance, void *sap,
 				  struct qos_info *qos, __u32 max_seg_size,
 				  __u8 max_header_size,
-				  struct sk_buff *userdata)
+				  struct sk_buff *skb)
 {
 	struct iriap_cb *self;
 
@@ -750,14 +752,17 @@
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
-	ASSERT(userdata != NULL, return;);
+	ASSERT(skb != NULL, return;);
 
 	self->max_data_size = max_seg_size;
 	self->max_header_size = max_header_size;
 
 	del_timer(&self->watchdog_timer);
 
-	iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, userdata);
+	iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, skb);
+
+	/* Drop reference count - see state_s_make_call(). */
+	dev_kfree_skb(skb);
 }
 
 /*
@@ -769,7 +774,7 @@
 static void iriap_connect_indication(void *instance, void *sap,
 				     struct qos_info *qos, __u32 max_seg_size,
 				     __u8 max_header_size,
-				     struct sk_buff *userdata)
+				     struct sk_buff *skb)
 {
 	struct iriap_cb *self, *new;
 
@@ -777,22 +782,22 @@
 
 	self = (struct iriap_cb *) instance;
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IAS_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(self != NULL, goto out;);
+	ASSERT(self->magic == IAS_MAGIC, goto out;);
 
 	/* Start new server */
 	new = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
 	if (!new) {
 		IRDA_DEBUG(0, "%s(), open failed\n", __FUNCTION__);
-		dev_kfree_skb(userdata);
-		return;
+		goto out;
 	}
 
 	/* Now attach up the new "socket" */
 	new->lsap = irlmp_dup(self->lsap, new);
 	if (!new->lsap) {
 		IRDA_DEBUG(0, "%s(), dup failed!\n", __FUNCTION__);
-		return;
+		goto out;
 	}
 
 	new->max_data_size = max_seg_size;
@@ -801,7 +806,11 @@
 	/* Clean up the original one to keep it in listen state */
 	irlmp_listen(self->lsap);
 
-	iriap_do_server_event(new, IAP_LM_CONNECT_INDICATION, userdata);
+	iriap_do_server_event(new, IAP_LM_CONNECT_INDICATION, skb);
+
+out:
+	/* Drop reference count - see state_r_disconnect(). */
+	dev_kfree_skb(skb);
 }
 
 /*
@@ -821,10 +830,9 @@
 
 	self = (struct iriap_cb *) instance;
 
-	ASSERT(self != NULL, return 0;);
-	ASSERT(self->magic == IAS_MAGIC, return 0;);
-
 	ASSERT(skb != NULL, return 0;);
+	ASSERT(self != NULL, goto out;);
+	ASSERT(self->magic == IAS_MAGIC, goto out;);
 
 	frame = skb->data;
 
@@ -832,22 +840,19 @@
 		/* Call server */
 		IRDA_DEBUG(4, "%s(), Calling server!\n", __FUNCTION__);
 		iriap_do_r_connect_event(self, IAP_RECV_F_LST, skb);
-
-		return 0;
+		goto out;
 	}
 	opcode = frame[0];
 	if (~opcode & IAP_LST) {
 		WARNING("%s:, IrIAS multiframe commands or "
 			"results is not implemented yet!\n", __FUNCTION__);
-		dev_kfree_skb(skb);
-		return 0;
+		goto out;
 	}
 
 	/* Check for ack frames since they don't contain any data */
 	if (opcode & IAP_ACK) {
 		IRDA_DEBUG(0, "%s() Got ack frame!\n", __FUNCTION__);
-		dev_kfree_skb(skb);
-		return 0;
+		goto out;
 	}
 
 	opcode &= ~IAP_LST; /* Mask away LST bit */
@@ -855,7 +860,6 @@
 	switch (opcode) {
 	case GET_INFO_BASE:
 		IRDA_DEBUG(0, "IrLMP GetInfoBaseDetails not implemented!\n");
-		dev_kfree_skb(skb);
 		break;
 	case GET_VALUE_BY_CLASS:
 		iriap_do_call_event(self, IAP_RECV_F_LST, NULL);
@@ -876,7 +880,6 @@
 			if (self->confirm)
 				self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
 					      self->priv);
-			dev_kfree_skb(skb);
 			break;
 		case IAS_ATTRIB_UNKNOWN:
 			IRDA_DEBUG(1, "%s(), No such attribute!\n", __FUNCTION__);
@@ -890,16 +893,18 @@
 			if (self->confirm)
 				self->confirm(IAS_ATTRIB_UNKNOWN, 0, NULL,
 					      self->priv);
-			dev_kfree_skb(skb);
 			break;
 		}
 		break;
 	default:
 		IRDA_DEBUG(0, "%s(), Unknown op-code: %02x\n", __FUNCTION__,
 			   opcode);
-		dev_kfree_skb(skb);
 		break;
 	}
+
+out:
+	/* Cleanup - sub-calls will have done skb_get() as needed. */
+	dev_kfree_skb(skb);
 	return 0;
 }
 
@@ -939,6 +944,7 @@
 		iriap_getvaluebyclass_indication(self, skb);
 		break;
 	}
+	/* skb will be cleaned up in iriap_data_indication */
 }
 
 /*
diff -urN linux-2.5.69-bk18/net/irda/iriap_event.c linux-2.5.69-bk19/net/irda/iriap_event.c
--- linux-2.5.69-bk18/net/irda/iriap_event.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/iriap_event.c	2003-05-26 04:41:43.000000000 -0700
@@ -11,6 +11,7 @@
  *
  *     Copyright (c) 1997, 1999-2000 Dag Brattli <dagb@cs.uit.no>,
  *     All Rights Reserved.
+ *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License as
@@ -174,8 +175,11 @@
 	switch (event) {
 	case IAP_CALL_REQUEST_GVBC:
 		iriap_next_client_state(self, S_CONNECTING);
-		ASSERT(self->skb == NULL, return;);
-		self->skb = skb;
+		ASSERT(self->request_skb == NULL, return;);
+		/* Don't forget to refcount it -
+		 * see iriap_getvaluebyclass_request(). */
+		skb_get(skb);
+		self->request_skb = skb;
 		iriap_connect_request(self);
 		break;
 	case IAP_LM_DISCONNECT_INDICATION:
@@ -251,20 +255,21 @@
 static void state_s_make_call(struct iriap_cb *self, IRIAP_EVENT event,
 			      struct sk_buff *skb)
 {
+	struct sk_buff *tx_skb;
+
 	ASSERT(self != NULL, return;);
 
 	switch (event) {
 	case IAP_CALL_REQUEST:
-		skb = self->skb;
-		self->skb = NULL;
+		/* Already refcounted - see state_s_disconnect() */
+		tx_skb = self->request_skb;
+		self->request_skb = NULL;
 
-		irlmp_data_request(self->lsap, skb);
+		irlmp_data_request(self->lsap, tx_skb);
 		iriap_next_call_state(self, S_OUTSTANDING);
 		break;
 	default:
 		IRDA_DEBUG(0, "%s(), Unknown event %d\n", __FUNCTION__, event);
-		if (skb)
-			dev_kfree_skb(skb);
 		break;
 	}
 }
@@ -379,10 +384,6 @@
 		 *  care about LM_Idle_request()!
 		 */
 		iriap_next_r_connect_state(self, R_RECEIVING);
-
-		if (skb)
-			dev_kfree_skb(skb);
-
 		break;
 	default:
 		IRDA_DEBUG(0, "%s(), unknown event %d\n", __FUNCTION__, event);
@@ -450,7 +451,6 @@
 		IRDA_DEBUG(0, "%s(), unknown event!\n", __FUNCTION__);
 		break;
 	}
-
 }
 
 /*
@@ -465,11 +465,8 @@
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 
 	ASSERT(skb != NULL, return;);
-
-	if (!self || self->magic != IAS_MAGIC) {
-		IRDA_DEBUG(0, "%s(), bad pointer self\n", __FUNCTION__);
-		return;
-	}
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
 	switch (event) {
 	case IAP_CALL_RESPONSE:
@@ -479,6 +476,10 @@
 		 */
 		iriap_next_r_connect_state(self, R_RECEIVING);
 
+		/* Don't forget to refcount it - see
+		 * iriap_getvaluebyclass_response(). */
+		skb_get(skb);
+
 		irlmp_data_request(self->lsap, skb);
 		break;
 	default:
diff -urN linux-2.5.69-bk18/net/irda/irlan/irlan_client.c linux-2.5.69-bk19/net/irda/irlan/irlan_client.c
--- linux-2.5.69-bk18/net/irda/irlan/irlan_client.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irlan/irlan_client.c	2003-05-26 04:41:43.000000000 -0700
@@ -268,7 +268,7 @@
 	notify.connect_confirm       = irlan_client_ctrl_connect_confirm;
 	notify.disconnect_indication = irlan_client_ctrl_disconnect_indication;
 	notify.instance = self;
-	strncpy(notify.name, "IrLAN ctrl (c)", NOTIFY_MAX_NAME);
+	strlcpy(notify.name, "IrLAN ctrl (c)", sizeof(notify.name));
 	
 	tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
 	if (!tsap) {
diff -urN linux-2.5.69-bk18/net/irda/irlan/irlan_common.c linux-2.5.69-bk19/net/irda/irlan/irlan_common.c
--- linux-2.5.69-bk18/net/irda/irlan/irlan_common.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irlan/irlan_common.c	2003-05-26 04:41:43.000000000 -0700
@@ -465,7 +465,7 @@
  	/*notify.flow_indication       = irlan_eth_flow_indication;*/
 	notify.disconnect_indication = irlan_disconnect_indication;
 	notify.instance              = self;
-	strncpy(notify.name, "IrLAN data", NOTIFY_MAX_NAME);
+	strlcpy(notify.name, "IrLAN data", sizeof(notify.name));
 
 	tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
 	if (!tsap) {
@@ -1180,20 +1180,6 @@
 	}
 }
 
-void irlan_mod_inc_use_count(void)
-{
-#ifdef MODULE
-	MOD_INC_USE_COUNT;
-#endif
-}
-
-void irlan_mod_dec_use_count(void)
-{
-#ifdef MODULE
-	MOD_DEC_USE_COUNT;
-#endif
-}
-
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("The Linux IrDA LAN protocol"); 
 MODULE_LICENSE("GPL");
diff -urN linux-2.5.69-bk18/net/irda/irlan/irlan_eth.c linux-2.5.69-bk19/net/irda/irlan/irlan_eth.c
--- linux-2.5.69-bk18/net/irda/irlan/irlan_eth.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irlan/irlan_eth.c	2003-05-26 04:41:43.000000000 -0700
@@ -31,6 +31,7 @@
 #include <linux/inetdevice.h>
 #include <linux/if_arp.h>
 #include <linux/random.h>
+#include <linux/module.h>
 #include <net/arp.h>
 
 #include <net/irda/irda.h>
@@ -61,6 +62,7 @@
 	dev->hard_start_xmit    = irlan_eth_xmit; 
 	dev->get_stats	        = irlan_eth_get_stats;
 	dev->set_multicast_list = irlan_eth_set_multicast_list;
+	SET_MODULE_OWNER(dev);
 
 	ether_setup(dev);
 	
@@ -112,8 +114,6 @@
 	self->disconnect_reason = 0;
 	irlan_client_wakeup(self, self->saddr, self->daddr);
 
-	irlan_mod_inc_use_count();
-
 	/* Make sure we have a hardware address before we return, so DHCP clients gets happy */
 	interruptible_sleep_on(&self->open_wait);
 	
@@ -138,8 +138,6 @@
 	/* Stop device */
 	netif_stop_queue(dev);
 	
-	irlan_mod_dec_use_count();
-
 	irlan_close_data_channel(self);
 	irlan_close_tsaps(self);
 
@@ -206,7 +204,7 @@
 		 * confuse do_dev_queue_xmit() in dev.c! I have
 		 * tried :-) DB 
 		 */
-		dev_kfree_skb(skb);
+		/* irttp_data_request already free the packet */
 		self->stats.tx_dropped++;
 	} else {
 		self->stats.tx_packets++;
diff -urN linux-2.5.69-bk18/net/irda/irlan/irlan_provider.c linux-2.5.69-bk19/net/irda/irlan/irlan_provider.c
--- linux-2.5.69-bk18/net/irda/irlan/irlan_provider.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irlan/irlan_provider.c	2003-05-26 04:41:43.000000000 -0700
@@ -396,7 +396,7 @@
 	notify.connect_indication    = irlan_provider_connect_indication;
 	notify.disconnect_indication = irlan_provider_disconnect_indication;
 	notify.instance = self;
-	strncpy(notify.name, "IrLAN ctrl (p)", 16);
+	strlcpy(notify.name, "IrLAN ctrl (p)", sizeof(notify.name));
 
 	tsap = irttp_open_tsap(LSAP_ANY, 1, &notify);
 	if (!tsap) {
diff -urN linux-2.5.69-bk18/net/irda/irlap.c linux-2.5.69-bk19/net/irda/irlap.c
--- linux-2.5.69-bk18/net/irda/irlap.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irlap.c	2003-05-26 04:41:43.000000000 -0700
@@ -10,7 +10,7 @@
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  *
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
- *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License as
@@ -122,8 +122,7 @@
 	self->qos_dev = qos;
 	/* Copy hardware name */
 	if(hw_name != NULL) {
-		strncpy(self->hw_name, hw_name, 2*IFNAMSIZ);
-		self->hw_name[2*IFNAMSIZ] = '\0';
+		strlcpy(self->hw_name, hw_name, sizeof(self->hw_name));
 	} else {
 		self->hw_name[0] = '\0';
 	}
@@ -244,7 +243,6 @@
 
 	irlap_init_qos_capabilities(self, NULL); /* No user QoS! */
 
-	skb_get(skb); /*LEVEL4*/
 	irlmp_link_connect_indication(self->notify.instance, self->saddr,
 				      self->daddr, &self->qos_tx, skb);
 }
@@ -255,12 +253,11 @@
  *    Service user has accepted incoming connection
  *
  */
-void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb)
+void irlap_connect_response(struct irlap_cb *self, struct sk_buff *userdata)
 {
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 
-	irlap_do_event(self, CONNECT_RESPONSE, skb, NULL);
-	kfree_skb(skb);
+	irlap_do_event(self, CONNECT_RESPONSE, userdata, NULL);
 }
 
 /*
@@ -305,7 +302,6 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	skb_get(skb); /*LEVEL4*/
 	irlmp_link_connect_confirm(self->notify.instance, &self->qos_tx, skb);
 }
 
@@ -322,7 +318,6 @@
 	/* Hide LAP header from IrLMP layer */
 	skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
 
-	skb_get(skb); /*LEVEL4*/
 	irlmp_link_data_indication(self->notify.instance, skb, unreliable);
 }
 
@@ -354,6 +349,9 @@
 	else
 		skb->data[1] = I_FRAME;
 
+	/* Don't forget to refcount it - see irlmp_connect_request(). */
+	skb_get(skb);
+
 	/* Add at the end of the queue (keep ordering) - Jean II */
 	skb_queue_tail(&self->txq, skb);
 
@@ -392,6 +390,8 @@
 	skb->data[0] = CBROADCAST;
 	skb->data[1] = UI_FRAME;
 
+	/* Don't need to refcount, see irlmp_connless_data_request() */
+
 	skb_queue_tail(&self->txq_ultra, skb);
 
 	irlap_do_event(self, SEND_UI_FRAME, NULL, NULL);
@@ -416,7 +416,6 @@
 	/* Hide LAP header from IrLMP layer */
 	skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
 
-	skb_get(skb); /*LEVEL4*/
 	irlmp_link_unitdata_indication(self->notify.instance, skb);
 }
 #endif /* CONFIG_IRDA_ULTRA */
diff -urN linux-2.5.69-bk18/net/irda/irlap_event.c linux-2.5.69-bk19/net/irda/irlap_event.c
--- linux-2.5.69-bk18/net/irda/irlap_event.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irlap_event.c	2003-05-26 04:41:43.000000000 -0700
@@ -12,7 +12,7 @@
  *     Copyright (c) 1998-2000 Dag Brattli <dag@brattli.net>,
  *     Copyright (c) 1998      Thomas Davis <ratbert@radiks.net>
  *     All Rights Reserved.
- *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License as
@@ -287,6 +287,9 @@
 				/* Send one frame */
 				ret = (*state[self->state])(self, SEND_I_CMD,
 							    skb, NULL);
+				/* Drop reference count.
+				 * It will be increase as needed in
+				 * irlap_send_data_xxx() */
 				kfree_skb(skb);
 
 				/* Poll the higher layers for one more frame */
@@ -517,6 +520,8 @@
 						    CMD_FRAME);
 			else
 				break;
+			/* irlap_send_ui_frame() won't increase skb reference
+			 * count, so no dev_kfree_skb() - Jean II */
 		}
 		if (i == 2) {
 			/* Force us to listen 500 ms again */
diff -urN linux-2.5.69-bk18/net/irda/irlap_frame.c linux-2.5.69-bk19/net/irda/irlap_frame.c
--- linux-2.5.69-bk18/net/irda/irlap_frame.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irlap_frame.c	2003-05-26 04:41:43.000000000 -0700
@@ -11,7 +11,7 @@
  *
  *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
  *     All Rights Reserved.
- *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License as
@@ -106,7 +106,7 @@
  */
 void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
 {
-	struct sk_buff *skb;
+	struct sk_buff *tx_skb;
 	struct snrm_frame *frame;
 	int ret;
 
@@ -114,11 +114,11 @@
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
 	/* Allocate frame */
-	skb = dev_alloc_skb(64);
-	if (!skb)
+	tx_skb = dev_alloc_skb(64);
+	if (!tx_skb)
 		return;
 
-	frame = (struct snrm_frame *) skb_put(skb, 2);
+	frame = (struct snrm_frame *) skb_put(tx_skb, 2);
 
 	/* Insert connection address field */
 	if (qos)
@@ -133,19 +133,19 @@
 	 *  If we are establishing a connection then insert QoS paramerters
 	 */
 	if (qos) {
-		skb_put(skb, 9); /* 21 left */
+		skb_put(tx_skb, 9); /* 21 left */
 		frame->saddr = cpu_to_le32(self->saddr);
 		frame->daddr = cpu_to_le32(self->daddr);
 
 		frame->ncaddr = self->caddr;
 
-		ret = irlap_insert_qos_negotiation_params(self, skb);
+		ret = irlap_insert_qos_negotiation_params(self, tx_skb);
 		if (ret < 0) {
-			dev_kfree_skb(skb);
+			dev_kfree_skb(tx_skb);
 			return;
 		}
 	}
-	irlap_queue_xmit(self, skb);
+	irlap_queue_xmit(self, tx_skb);
 }
 
 /*
@@ -162,8 +162,8 @@
 	frame = (struct snrm_frame *) skb->data;
 
 	if (skb->len >= sizeof(struct snrm_frame)) {
-		/* Copy the new connection address */
-		info->caddr = frame->ncaddr;
+		/* Copy the new connection address ignoring the C/R bit */
+		info->caddr = frame->ncaddr & 0xFE;
 
 		/* Check if the new connection address is valid */
 		if ((info->caddr == 0x00) || (info->caddr == 0xfe)) {
@@ -197,7 +197,7 @@
  */
 void irlap_send_ua_response_frame(struct irlap_cb *self, struct qos_info *qos)
 {
-	struct sk_buff *skb;
+	struct sk_buff *tx_skb;
 	struct ua_frame *frame;
 	int ret;
 
@@ -206,14 +206,12 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	skb = NULL;
-
 	/* Allocate frame */
-	skb = dev_alloc_skb(64);
-	if (!skb)
+	tx_skb = dev_alloc_skb(64);
+	if (!tx_skb)
 		return;
 
-	frame = (struct ua_frame *) skb_put(skb, 10);
+	frame = (struct ua_frame *) skb_put(tx_skb, 10);
 
 	/* Build UA response */
 	frame->caddr = self->caddr;
@@ -224,14 +222,14 @@
 
 	/* Should we send QoS negotiation parameters? */
 	if (qos) {
-		ret = irlap_insert_qos_negotiation_params(self, skb);
+		ret = irlap_insert_qos_negotiation_params(self, tx_skb);
 		if (ret < 0) {
-			dev_kfree_skb(skb);
+			dev_kfree_skb(tx_skb);
 			return;
 		}
 	}
 
-	irlap_queue_xmit(self, skb);
+	irlap_queue_xmit(self, tx_skb);
 }
 
 
@@ -243,17 +241,17 @@
  */
 void irlap_send_dm_frame( struct irlap_cb *self)
 {
-	struct sk_buff *skb = NULL;
+	struct sk_buff *tx_skb = NULL;
 	__u8 *frame;
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	skb = dev_alloc_skb(32);
-	if (!skb)
+	tx_skb = dev_alloc_skb(32);
+	if (!tx_skb)
 		return;
 
-	frame = skb_put( skb, 2);
+	frame = skb_put(tx_skb, 2);
 
 	if (self->state == LAP_NDM)
 		frame[0] = CBROADCAST;
@@ -262,7 +260,7 @@
 
 	frame[1] = DM_RSP | PF_BIT;
 
-	irlap_queue_xmit(self, skb);
+	irlap_queue_xmit(self, tx_skb);
 }
 
 /*
@@ -273,7 +271,7 @@
  */
 void irlap_send_disc_frame(struct irlap_cb *self)
 {
-	struct sk_buff *skb = NULL;
+	struct sk_buff *tx_skb = NULL;
 	__u8 *frame;
 
 	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
@@ -281,16 +279,16 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	skb = dev_alloc_skb(16);
-	if (!skb)
+	tx_skb = dev_alloc_skb(16);
+	if (!tx_skb)
 		return;
 
-	frame = skb_put(skb, 2);
+	frame = skb_put(tx_skb, 2);
 
 	frame[0] = self->caddr | CMD_FRAME;
 	frame[1] = DISC_CMD | PF_BIT;
 
-	irlap_queue_xmit(self, skb);
+	irlap_queue_xmit(self, tx_skb);
 }
 
 /*
@@ -302,7 +300,7 @@
 void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
 				    __u8 command, discovery_t *discovery)
 {
-	struct sk_buff *skb = NULL;
+	struct sk_buff *tx_skb = NULL;
 	struct xid_frame *frame;
 	__u32 bcast = BROADCAST;
 	__u8 *info;
@@ -314,12 +312,12 @@
 	ASSERT(self->magic == LAP_MAGIC, return;);
 	ASSERT(discovery != NULL, return;);
 
-	skb = dev_alloc_skb(64);
-	if (!skb)
+	tx_skb = dev_alloc_skb(64);
+	if (!tx_skb)
 		return;
 
-	skb_put(skb, 14);
-	frame = (struct xid_frame *) skb->data;
+	skb_put(tx_skb, 14);
+	frame = (struct xid_frame *) tx_skb->data;
 
 	if (command) {
 		frame->caddr = CBROADCAST | CMD_FRAME;
@@ -367,21 +365,21 @@
 		int len;
 
 		if (discovery->data.hints[0] & HINT_EXTENSION) {
-			info = skb_put(skb, 2);
+			info = skb_put(tx_skb, 2);
 			info[0] = discovery->data.hints[0];
 			info[1] = discovery->data.hints[1];
 		} else {
-			info = skb_put(skb, 1);
+			info = skb_put(tx_skb, 1);
 			info[0] = discovery->data.hints[0];
 		}
-		info = skb_put(skb, 1);
+		info = skb_put(tx_skb, 1);
 		info[0] = discovery->data.charset;
 
-		len = IRDA_MIN(discovery->name_len, skb_tailroom(skb));
-		info = skb_put(skb, len);
+		len = IRDA_MIN(discovery->name_len, skb_tailroom(tx_skb));
+		info = skb_put(tx_skb, len);
 		memcpy(info, discovery->data.info, len);
 	}
-	irlap_queue_xmit(self, skb);
+	irlap_queue_xmit(self, tx_skb);
 }
 
 /*
@@ -498,7 +496,6 @@
 		break;
 	default:
 		/* Error!! */
-		dev_kfree_skb(skb);
 		return;
 	}
 	info->s = xid->slotnr;
@@ -561,21 +558,21 @@
  */
 void irlap_send_rr_frame(struct irlap_cb *self, int command)
 {
-	struct sk_buff *skb;
+	struct sk_buff *tx_skb;
 	__u8 *frame;
 
-	skb = dev_alloc_skb(16);
-	if (!skb)
+	tx_skb = dev_alloc_skb(16);
+	if (!tx_skb)
 		return;
 
-	frame = skb_put(skb, 2);
+	frame = skb_put(tx_skb, 2);
 
 	frame[0] = self->caddr;
 	frame[0] |= (command) ? CMD_FRAME : 0;
 
 	frame[1] = RR | PF_BIT | (self->vr << 5);
 
-	irlap_queue_xmit(self, skb);
+	irlap_queue_xmit(self, tx_skb);
 }
 
 /*
@@ -586,19 +583,19 @@
  */
 void irlap_send_rd_frame(struct irlap_cb *self)
 {
-	struct sk_buff *skb;
+	struct sk_buff *tx_skb;
 	__u8 *frame;
 
-	skb = dev_alloc_skb(16);
-	if (!skb)
+	tx_skb = dev_alloc_skb(16);
+	if (!tx_skb)
 		return;
 
-	frame = skb_put(skb, 2);
+	frame = skb_put(tx_skb, 2);
 
 	frame[0] = self->caddr;
 	frame[1] = RD_RSP | PF_BIT;
 
-	irlap_queue_xmit(self, skb);
+	irlap_queue_xmit(self, tx_skb);
 }
 
 /*
@@ -623,17 +620,17 @@
 
 void irlap_send_frmr_frame( struct irlap_cb *self, int command)
 {
-	struct sk_buff *skb = NULL;
+	struct sk_buff *tx_skb = NULL;
 	__u8 *frame;
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
 
-	skb = dev_alloc_skb( 32);
-	if (!skb)
+	tx_skb = dev_alloc_skb( 32);
+	if (!tx_skb)
 		return;
 
-	frame = skb_put( skb, 2);
+	frame = skb_put(tx_skb, 2);
 
 	frame[0] = self->caddr;
 	frame[0] |= (command) ? CMD_FRAME : 0;
@@ -646,7 +643,7 @@
 
 	IRDA_DEBUG(4, "%s(), vr=%d, %ld\n", __FUNCTION__, self->vr, jiffies);
 
-	irlap_queue_xmit(self, skb);
+	irlap_queue_xmit(self, tx_skb);
 }
 
 /*
@@ -739,17 +736,19 @@
 		 */
 		skb->data[1] = I_FRAME | (self->vs << 1);
 
+		/*
+		 *  Insert frame in store, in case of retransmissions
+		 *  Increase skb reference count, see irlap_do_event()
+		 */
+		skb_get(skb);
+		skb_queue_tail(&self->wx_list, skb);
+
 		/* Copy buffer */
 		tx_skb = skb_clone(skb, GFP_ATOMIC);
 		if (tx_skb == NULL) {
 			return;
 		}
 
-		/*
-		 *  Insert frame in store, in case of retransmissions
-		 */
-		skb_queue_tail(&self->wx_list, skb_get(skb));
-
 		self->vs = (self->vs + 1) % 8;
 		self->ack_required = FALSE;
 		self->window -= 1;
@@ -782,6 +781,13 @@
 		 */
 		skb->data[1] = I_FRAME | (self->vs << 1);
 
+		/*
+		 *  Insert frame in store, in case of retransmissions
+		 *  Increase skb reference count, see irlap_do_event()
+		 */
+		skb_get(skb);
+		skb_queue_tail(&self->wx_list, skb);
+
 		/* Copy buffer */
 		tx_skb = skb_clone(skb, GFP_ATOMIC);
 		if (tx_skb == NULL) {
@@ -789,11 +795,6 @@
 		}
 
 		/*
-		 *  Insert frame in store, in case of retransmissions
-		 */
-		skb_queue_tail(&self->wx_list, skb_get(skb));
-
-		/*
 		 *  Set poll bit if necessary. We do this to the copied
 		 *  skb, since retransmitted need to set or clear the poll
 		 *  bit depending on when they are sent.
@@ -850,14 +851,18 @@
 		 */
 		skb->data[1] = I_FRAME | (self->vs << 1);
 
+		/*
+		 *  Insert frame in store, in case of retransmissions
+		 *  Increase skb reference count, see irlap_do_event()
+		 */
+		skb_get(skb);
+		skb_queue_tail(&self->wx_list, skb);
+
 		tx_skb = skb_clone(skb, GFP_ATOMIC);
 		if (tx_skb == NULL) {
 			return;
 		}
 
-		/* Insert frame in store */
-		skb_queue_tail(&self->wx_list, skb_get(skb));
-
 		tx_skb->data[1] |= PF_BIT;
 
 		self->vs = (self->vs + 1) % 8;
@@ -903,14 +908,18 @@
 		 */
 		skb->data[1] = I_FRAME | (self->vs << 1);
 
+		/*
+		 *  Insert frame in store, in case of retransmissions
+		 *  Increase skb reference count, see irlap_do_event()
+		 */
+		skb_get(skb);
+		skb_queue_tail(&self->wx_list, skb);
+
 		tx_skb = skb_clone(skb, GFP_ATOMIC);
 		if (tx_skb == NULL) {
 			return;
 		}
 
-		/* Insert frame in store */
-		skb_queue_tail(&self->wx_list, skb_get(skb));
-
 		self->vs = (self->vs + 1) % 8;
 		self->ack_required = FALSE;
 		self->window -= 1;
@@ -939,8 +948,6 @@
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
 	/* Initialize variables */
-	skb = tx_skb = NULL;
-
 	count = skb_queue_len(&self->wx_list);
 
 	/*  Resend unacknowledged frame(s) */
@@ -1020,9 +1027,6 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	/* Initialize variables */
-	skb = tx_skb = NULL;
-
 	/*  Resend unacknowledged frame(s) */
 	skb = skb_peek(&self->wx_list);
 	if (skb != NULL) {
@@ -1186,35 +1190,35 @@
 void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr,
 			   struct sk_buff *cmd)
 {
-	struct sk_buff *skb;
+	struct sk_buff *tx_skb;
 	struct test_frame *frame;
 	__u8 *info;
 
-	skb = dev_alloc_skb(cmd->len+sizeof(struct test_frame));
-	if (!skb)
+	tx_skb = dev_alloc_skb(cmd->len+sizeof(struct test_frame));
+	if (!tx_skb)
 		return;
 
 	/* Broadcast frames must include saddr and daddr fields */
 	if (caddr == CBROADCAST) {
 		frame = (struct test_frame *)
-			skb_put(skb, sizeof(struct test_frame));
+			skb_put(tx_skb, sizeof(struct test_frame));
 
 		/* Insert the swapped addresses */
 		frame->saddr = cpu_to_le32(self->saddr);
 		frame->daddr = cpu_to_le32(daddr);
 	} else
-		frame = (struct test_frame *) skb_put(skb, LAP_ADDR_HEADER + LAP_CTRL_HEADER);
+		frame = (struct test_frame *) skb_put(tx_skb, LAP_ADDR_HEADER + LAP_CTRL_HEADER);
 
 	frame->caddr = caddr;
 	frame->control = TEST_RSP | PF_BIT;
 
 	/* Copy info */
-	info = skb_put(skb, cmd->len);
+	info = skb_put(tx_skb, cmd->len);
 	memcpy(info, cmd->data, cmd->len);
 
 	/* Return to sender */
 	irlap_wait_min_turn_around(self, &self->qos_tx);
-	irlap_queue_xmit(self, skb);
+	irlap_queue_xmit(self, tx_skb);
 }
 
 /*
@@ -1263,6 +1267,15 @@
  *    Called when a frame is received. Dispatches the right receive function
  *    for processing of the frame.
  *
+ * Note on skb management :
+ * After calling the higher layers of the IrDA stack, we always
+ * kfree() the skb, which drop the reference count (and potentially
+ * destroy it).
+ * If a higher layer of the stack want to keep the skb around (to put
+ * in a queue or pass it to the higher layer), it will need to use
+ * skb_get() to keep a reference on it. This is usually done at the
+ * LMP level in irlmp.c.
+ * Jean II
  */
 int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
 		     struct packet_type *ptype)
@@ -1286,6 +1299,7 @@
 	 * we don't need to be clever about it. Jean II */
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
 		ERROR("%s: can't clone shared skb!\n", __FUNCTION__);
+		dev_kfree_skb(skb);
 		return -1;
 	}
 	if (skb_is_nonlinear(skb))
@@ -1390,6 +1404,7 @@
 		break;
 	}
 out:
+	/* Always drop our reference on the skb */
 	dev_kfree_skb(skb);
 	return 0;
 }
diff -urN linux-2.5.69-bk18/net/irda/irlmp.c linux-2.5.69-bk19/net/irda/irlmp.c
--- linux-2.5.69-bk18/net/irda/irlmp.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irlmp.c	2003-05-26 04:41:43.000000000 -0700
@@ -11,7 +11,7 @@
  *
  *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
  *     All Rights Reserved.
- *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License as
@@ -345,9 +345,10 @@
 			  __u32 saddr, __u32 daddr,
 			  struct qos_info *qos, struct sk_buff *userdata)
 {
-	struct sk_buff *skb = NULL;
+	struct sk_buff *tx_skb = userdata;
 	struct lap_cb *lap;
 	struct lsap_cb *lsap;
+	int ret;
 
 	ASSERT(self != NULL, return -EBADR;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return -EBADR;);
@@ -356,26 +357,29 @@
 	      "%s(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x\n",
 	      __FUNCTION__, self->slsap_sel, dlsap_sel, saddr, daddr);
 
-	if (test_bit(0, &self->connected))
-		return -EISCONN;
+	if (test_bit(0, &self->connected)) {
+		ret = -EISCONN;
+		goto err;
+	}
 
 	/* Client must supply destination device address */
-	if (!daddr)
-		return -EINVAL;
+	if (!daddr) {
+		ret = -EINVAL;
+		goto err;
+	}
 
 	/* Any userdata? */
-	if (userdata == NULL) {
-		skb = dev_alloc_skb(64);
-		if (!skb)
+	if (tx_skb == NULL) {
+		tx_skb = dev_alloc_skb(64);
+		if (!tx_skb)
 			return -ENOMEM;
 
-		skb_reserve(skb, LMP_MAX_HEADER);
-	} else
-		skb = userdata;
+		skb_reserve(tx_skb, LMP_MAX_HEADER);
+	}
 
 	/* Make room for MUX control header (3 bytes) */
-	ASSERT(skb_headroom(skb) >= LMP_CONTROL_HEADER, return -1;);
-	skb_push(skb, LMP_CONTROL_HEADER);
+	ASSERT(skb_headroom(tx_skb) >= LMP_CONTROL_HEADER, return -1;);
+	skb_push(tx_skb, LMP_CONTROL_HEADER);
 
 	self->dlsap_sel = dlsap_sel;
 
@@ -409,7 +413,8 @@
 	lap = hashbin_lock_find(irlmp->links, saddr, NULL);
 	if (lap == NULL) {
 		IRDA_DEBUG(1, "%s(), Unable to find a usable link!\n", __FUNCTION__);
-		return -EHOSTUNREACH;
+		ret = -EHOSTUNREACH;
+		goto err;
 	}
 
 	/* Check if LAP is disconnected or already connected */
@@ -423,13 +428,15 @@
 			 * Maybe we could give LAP a bit of help in this case.
 			 */
 			IRDA_DEBUG(0, "%s(), sorry, but I'm waiting for LAP to timeout!\n", __FUNCTION__);
-			return -EAGAIN;
+			ret = -EAGAIN;
+			goto err;
 		}
 
 		/* LAP is already connected to a different node, and LAP
 		 * can only talk to one node at a time */
 		IRDA_DEBUG(0, "%s(), sorry, but link is busy!\n", __FUNCTION__);
-		return -EBUSY;
+		ret = -EBUSY;
+		goto err;
 	}
 
 	self->lap = lap;
@@ -456,9 +463,18 @@
 	if (qos)
 		self->qos = *qos;
 
-	irlmp_do_lsap_event(self, LM_CONNECT_REQUEST, skb);
+	irlmp_do_lsap_event(self, LM_CONNECT_REQUEST, tx_skb);
+
+	/* Drop reference count - see irlap_data_request(). */
+	dev_kfree_skb(tx_skb);
 
 	return 0;
+
+err:
+	/* Cleanup */
+	if(tx_skb)
+		dev_kfree_skb(tx_skb);
+	return ret;
 }
 
 /*
@@ -495,12 +511,13 @@
 	/* Hide LMP_CONTROL_HEADER header from layer above */
 	skb_pull(skb, LMP_CONTROL_HEADER);
 
-	if (self->notify.connect_indication)
+	if (self->notify.connect_indication) {
+		/* Don't forget to refcount it - see irlap_driver_rcv(). */
+		skb_get(skb);
 		self->notify.connect_indication(self->notify.instance, self,
 						&self->qos, max_seg_size,
 						max_header_size, skb);
-	else
-		dev_kfree_skb(skb);
+	}
 }
 
 /*
@@ -526,6 +543,9 @@
 
 	irlmp_do_lsap_event(self, LM_CONNECT_RESPONSE, userdata);
 
+	/* Drop reference count - see irlap_data_request(). */
+	dev_kfree_skb(userdata);
+
 	return 0;
 }
 
@@ -560,11 +580,12 @@
 	skb_pull(skb, LMP_CONTROL_HEADER);
 
 	if (self->notify.connect_confirm) {
+		/* Don't forget to refcount it - see irlap_driver_rcv() */
+		skb_get(skb);
 		self->notify.connect_confirm(self->notify.instance, self,
 					     &self->qos, max_seg_size,
 					     max_header_size, skb);
-	} else
-		dev_kfree_skb(skb);
+	}
 }
 
 /*
@@ -602,6 +623,7 @@
 	memcpy(new, orig, sizeof(struct lsap_cb));
 	/* new->lap = orig->lap; => done in the memcpy() */
 	/* new->slsap_sel = orig->slsap_sel; => done in the memcpy() */
+	new->conn_skb = NULL;
 
 	spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, flags);
 
@@ -653,6 +675,9 @@
 	 */
 	irlmp_do_lsap_event(self, LM_DISCONNECT_REQUEST, userdata);
 
+	/* Drop reference count - see irlap_data_request(). */
+	dev_kfree_skb(userdata);
+
 	/*
 	 *  Remove LSAP from list of connected LSAPs for the particular link
 	 *  and insert it into the list of unconnected LSAPs
@@ -686,7 +711,7 @@
  *    LSAP is being closed!
  */
 void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
-				 struct sk_buff *userdata)
+				 struct sk_buff *skb)
 {
 	struct lsap_cb *lsap;
 
@@ -703,8 +728,6 @@
 	 * Jean II */
 	if (! test_and_clear_bit(0, &self->connected)) {
 		IRDA_DEBUG(0, "%s(), already disconnected!\n", __FUNCTION__);
-		if (userdata)
-			dev_kfree_skb(userdata);
 		return;
 	}
 
@@ -730,13 +753,14 @@
 	/*
 	 *  Inform service user
 	 */
-	if (self->notify.disconnect_indication)
+	if (self->notify.disconnect_indication) {
+		/* Don't forget to refcount it - see irlap_driver_rcv(). */
+		if(skb)
+			skb_get(skb);
 		self->notify.disconnect_indication(self->notify.instance,
-						   self, reason, userdata);
-	else {
+						   self, reason, skb);
+	} else {
 		IRDA_DEBUG(0, "%s(), no handler\n", __FUNCTION__);
-		if (userdata)
-			dev_kfree_skb(userdata);
 	}
 }
 
@@ -1047,17 +1071,31 @@
  *
  *    Send some data to peer device
  *
+ * Note on skb management :
+ * After calling the lower layers of the IrDA stack, we always
+ * kfree() the skb, which drop the reference count (and potentially
+ * destroy it).
+ * IrLMP and IrLAP may queue the packet, and in those cases will need
+ * to use skb_get() to keep it around.
+ * Jean II
  */
-int irlmp_data_request(struct lsap_cb *self, struct sk_buff *skb)
+int irlmp_data_request(struct lsap_cb *self, struct sk_buff *userdata)
 {
+	int	ret;
+
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
 	/* Make room for MUX header */
-	ASSERT(skb_headroom(skb) >= LMP_HEADER, return -1;);
-	skb_push(skb, LMP_HEADER);
+	ASSERT(skb_headroom(userdata) >= LMP_HEADER, return -1;);
+	skb_push(userdata, LMP_HEADER);
+
+	ret = irlmp_do_lsap_event(self, LM_DATA_REQUEST, userdata);
 
-	return irlmp_do_lsap_event(self, LM_DATA_REQUEST, skb);
+	/* Drop reference count - see irlap_data_request(). */
+	dev_kfree_skb(userdata);
+
+	return ret;
 }
 
 /*
@@ -1071,26 +1109,34 @@
 	/* Hide LMP header from layer above */
 	skb_pull(skb, LMP_HEADER);
 
-	if (self->notify.data_indication)
+	if (self->notify.data_indication) {
+		/* Don't forget to refcount it - see irlap_driver_rcv(). */
+		skb_get(skb);
 		self->notify.data_indication(self->notify.instance, self, skb);
-	else
-		dev_kfree_skb(skb);
+	}
 }
 
 /*
  * Function irlmp_udata_request (self, skb)
  */
-int irlmp_udata_request(struct lsap_cb *self, struct sk_buff *skb)
+int irlmp_udata_request(struct lsap_cb *self, struct sk_buff *userdata)
 {
+	int	ret;
+
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 
-	ASSERT(skb != NULL, return -1;);
+	ASSERT(userdata != NULL, return -1;);
 
 	/* Make room for MUX header */
-	ASSERT(skb_headroom(skb) >= LMP_HEADER, return -1;);
-	skb_push(skb, LMP_HEADER);
+	ASSERT(skb_headroom(userdata) >= LMP_HEADER, return -1;);
+	skb_push(userdata, LMP_HEADER);
+
+	ret = irlmp_do_lsap_event(self, LM_UDATA_REQUEST, userdata);
 
-	return irlmp_do_lsap_event(self, LM_UDATA_REQUEST, skb);
+	/* Drop reference count - see irlap_data_request(). */
+	dev_kfree_skb(userdata);
+
+	return ret;
 }
 
 /*
@@ -1110,51 +1156,57 @@
 	/* Hide LMP header from layer above */
 	skb_pull(skb, LMP_HEADER);
 
-	if (self->notify.udata_indication)
+	if (self->notify.udata_indication) {
+		/* Don't forget to refcount it - see irlap_driver_rcv(). */
+		skb_get(skb);
 		self->notify.udata_indication(self->notify.instance, self,
 					      skb);
-	else
-		dev_kfree_skb(skb);
+	}
 }
 
 /*
  * Function irlmp_connless_data_request (self, skb)
  */
 #ifdef CONFIG_IRDA_ULTRA
-int irlmp_connless_data_request(struct lsap_cb *self, struct sk_buff *skb)
+int irlmp_connless_data_request(struct lsap_cb *self, struct sk_buff *userdata)
 {
 	struct sk_buff *clone_skb;
 	struct lap_cb *lap;
 
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 
-	ASSERT(skb != NULL, return -1;);
+	ASSERT(userdata != NULL, return -1;);
 
 	/* Make room for MUX and PID header */
-	ASSERT(skb_headroom(skb) >= LMP_HEADER+LMP_PID_HEADER, return -1;);
+	ASSERT(skb_headroom(userdata) >= LMP_HEADER+LMP_PID_HEADER,
+	       return -1;);
 
 	/* Insert protocol identifier */
-	skb_push(skb, LMP_PID_HEADER);
-	skb->data[0] = self->pid;
+	skb_push(userdata, LMP_PID_HEADER);
+	userdata->data[0] = self->pid;
 
 	/* Connectionless sockets must use 0x70 */
-	skb_push(skb, LMP_HEADER);
-	skb->data[0] = skb->data[1] = LSAP_CONNLESS;
+	skb_push(userdata, LMP_HEADER);
+	userdata->data[0] = userdata->data[1] = LSAP_CONNLESS;
 
 	/* Try to send Connectionless  packets out on all links */
 	lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
 	while (lap != NULL) {
 		ASSERT(lap->magic == LMP_LAP_MAGIC, return -1;);
 
-		clone_skb = skb_clone(skb, GFP_ATOMIC);
-		if (!clone_skb)
+		clone_skb = skb_clone(userdata, GFP_ATOMIC);
+		if (!clone_skb) {
+			dev_kfree_skb(userdata);
 			return -ENOMEM;
+		}
 
 		irlap_unitdata_request(lap->irlap, clone_skb);
+		/* irlap_unitdata_request() don't increase refcount,
+		 * so no dev_kfree_skb() - Jean II */
 
 		lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
 	}
-	dev_kfree_skb(skb);
+	dev_kfree_skb(userdata);
 
 	return 0;
 }
@@ -1178,11 +1230,12 @@
 	/* Hide LMP and PID header from layer above */
 	skb_pull(skb, LMP_HEADER+LMP_PID_HEADER);
 
-	if (self->notify.udata_indication)
+	if (self->notify.udata_indication) {
+		/* Don't forget to refcount it - see irlap_driver_rcv(). */
+		skb_get(skb);
 		self->notify.udata_indication(self->notify.instance, self,
 					      skb);
-	else
-		dev_kfree_skb(skb);
+	}
 }
 #endif /* CONFIG_IRDA_ULTRA */
 
diff -urN linux-2.5.69-bk18/net/irda/irlmp_event.c linux-2.5.69-bk19/net/irda/irlmp_event.c
--- linux-2.5.69-bk18/net/irda/irlmp_event.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irlmp_event.c	2003-05-26 04:41:43.000000000 -0700
@@ -11,7 +11,7 @@
  *
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
  *     All Rights Reserved.
- *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License as
@@ -295,8 +295,6 @@
 	default:
 		IRDA_DEBUG(0, "%s(), Unknown event %s\n",
 			   __FUNCTION__, irlmp_event[event]);
-		if (skb)
-			dev_kfree_skb(skb);
 		break;
 	}
 }
@@ -373,8 +371,6 @@
 	default:
 		IRDA_DEBUG(0, "%s(), Unknown event %s\n",
 			 __FUNCTION__, irlmp_event[event]);
-		if (skb)
-			dev_kfree_skb(skb);
 		break;
 	}
 }
@@ -468,8 +464,6 @@
 	default:
 		IRDA_DEBUG(0, "%s(), Unknown event %s\n",
 			 __FUNCTION__, irlmp_event[event]);
-		if (skb)
-			dev_kfree_skb(skb);
 		break;
 	}
 }
@@ -499,6 +493,9 @@
 	switch (event) {
 #ifdef CONFIG_IRDA_ULTRA
 	case LM_UDATA_INDICATION:
+		/* This is most bizzare. Those packets are  aka unreliable
+		 * connected, aka IrLPT or SOCK_DGRAM/IRDAPROTO_UNITDATA.
+		 * Why do we pass them as Ultra ??? Jean II */
 		irlmp_connless_data_indication(self, skb);
 		break;
 #endif /* CONFIG_IRDA_ULTRA */
@@ -510,6 +507,8 @@
 					__FUNCTION__);
 			return -EBUSY;
 		}
+		/* Don't forget to refcount it (see irlmp_connect_request()) */
+		skb_get(skb);
 		self->conn_skb = skb;
 
 		irlmp_next_lsap_state(self, LSAP_SETUP_PEND);
@@ -525,6 +524,8 @@
 					__FUNCTION__);
 			return -EBUSY;
 		}
+		/* Don't forget to refcount it (see irlap_driver_rcv()) */
+		skb_get(skb);
 		self->conn_skb = skb;
 
 		irlmp_next_lsap_state(self, LSAP_CONNECT_PEND);
@@ -547,8 +548,6 @@
 	default:
 		IRDA_DEBUG(1, "%s(), Unknown event %s on LSAP %#02x\n",
 			   __FUNCTION__, irlmp_event[event], self->slsap_sel);
-		if (skb)
-			dev_kfree_skb(skb);
 		break;
 	}
 	return ret;
@@ -606,8 +605,6 @@
 	default:
 		IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n", 
 			   __FUNCTION__, irlmp_event[event], self->slsap_sel);
-		if (skb)
-			dev_kfree_skb(skb);
 		break;
 	}
 	return ret;
@@ -622,6 +619,7 @@
 static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
 				    struct sk_buff *skb)
 {
+	struct sk_buff *tx_skb;
 	int ret = 0;
 
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
@@ -647,10 +645,12 @@
 		IRDA_DEBUG(4, "%s(), LS_CONNECT_CONFIRM\n",  __FUNCTION__);
 		irlmp_next_lsap_state(self, LSAP_CONNECT);
 
-		skb = self->conn_skb;
+		tx_skb = self->conn_skb;
 		self->conn_skb = NULL;
 
-		irlmp_connect_indication(self, skb);
+		irlmp_connect_indication(self, tx_skb);
+		/* Drop reference count - see irlmp_connect_indication(). */
+		dev_kfree_skb(tx_skb);
 		break;
 	case LM_WATCHDOG_TIMEOUT:
 		/* Will happen in some rare cases because of a race condition.
@@ -668,8 +668,6 @@
 	default:
 		IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
 			   __FUNCTION__, irlmp_event[event], self->slsap_sel);
-		if (skb)
-			dev_kfree_skb(skb);
 		break;
 	}
 	return ret;
@@ -759,8 +757,6 @@
 	default:
 		IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
 			   __FUNCTION__, irlmp_event[event], self->slsap_sel);
-		if (skb)
-			dev_kfree_skb(skb);
 		break;
 	}
 	return ret;
@@ -832,8 +828,6 @@
 	default:
 		IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
 			   __FUNCTION__, irlmp_event[event], self->slsap_sel);
-		if (skb)
-			dev_kfree_skb(skb);
 		break;
 	}
 	return ret;
@@ -850,6 +844,7 @@
 static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
 				  struct sk_buff *skb)
 {
+	struct sk_buff *tx_skb;
 	LM_REASON reason;
 	int ret = 0;
 
@@ -862,11 +857,13 @@
 	case LM_LAP_CONNECT_CONFIRM:
 		ASSERT(self->conn_skb != NULL, return -1;);
 
-		skb = self->conn_skb;
+		tx_skb = self->conn_skb;
 		self->conn_skb = NULL;
 
 		irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
-				   self->slsap_sel, CONNECT_CMD, skb);
+				   self->slsap_sel, CONNECT_CMD, tx_skb);
+		/* Drop reference count - see irlap_data_request(). */
+		dev_kfree_skb(tx_skb);
 
 		irlmp_next_lsap_state(self, LSAP_SETUP);
 		break;
@@ -891,8 +888,6 @@
 	default:
 		IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
 			   __FUNCTION__, irlmp_event[event], self->slsap_sel);
-		if (skb)
-			dev_kfree_skb(skb);
 		break;
 	}
 	return ret;
diff -urN linux-2.5.69-bk18/net/irda/irlmp_frame.c linux-2.5.69-bk19/net/irda/irlmp_frame.c
--- linux-2.5.69-bk18/net/irda/irlmp_frame.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irlmp_frame.c	2003-05-26 04:41:43.000000000 -0700
@@ -11,7 +11,7 @@
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
  *     All Rights Reserved.
- *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -144,7 +144,6 @@
 		} else {
 			IRDA_DEBUG(2, "%s(), received data frame\n", __FUNCTION__);
 		}
-		dev_kfree_skb(skb);
 		return;
 	}
 
@@ -168,16 +167,13 @@
 			break;
 		case ACCESSMODE_CMD:
 			IRDA_DEBUG(0, "Access mode cmd not implemented!\n");
-			dev_kfree_skb(skb);
 			break;
 		case ACCESSMODE_CNF:
 			IRDA_DEBUG(0, "Access mode cnf not implemented!\n");
-			dev_kfree_skb(skb);
 			break;
 		default:
 			IRDA_DEBUG(0, "%s(), Unknown control frame %02x\n",
 				   __FUNCTION__, fp[2]);
-			dev_kfree_skb(skb);
 			break;
 		}
 	} else if (unreliable) {
@@ -230,16 +226,12 @@
 	if (pid & 0x80) {
 		IRDA_DEBUG(0, "%s(), extension in PID not supp!\n",
 			   __FUNCTION__);
-		dev_kfree_skb(skb);
-
 		return;
 	}
 
 	/* Check if frame is addressed to the connectionless LSAP */
 	if ((slsap_sel != LSAP_CONNLESS) || (dlsap_sel != LSAP_CONNLESS)) {
 		IRDA_DEBUG(0, "%s(), dropping frame!\n", __FUNCTION__);
-		dev_kfree_skb(skb);
-		
 		return;
 	}
 	
@@ -264,7 +256,6 @@
 		irlmp_connless_data_indication(lsap, skb);
 	else {
 		IRDA_DEBUG(0, "%s(), found no matching LSAP!\n", __FUNCTION__);
-		dev_kfree_skb(skb);
 	}
 }
 #endif /* CONFIG_IRDA_ULTRA */
@@ -278,7 +269,7 @@
 void irlmp_link_disconnect_indication(struct lap_cb *lap, 
 				      struct irlap_cb *irlap, 
 				      LAP_REASON reason, 
-				      struct sk_buff *userdata)
+				      struct sk_buff *skb)
 {
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
@@ -288,9 +279,7 @@
 	lap->reason = reason;
 	lap->daddr = DEV_ADDR_ANY;
 
-        /* FIXME: must do something with the userdata if any */
-	if (userdata)
-		dev_kfree_skb(userdata);
+        /* FIXME: must do something with the skb if any */
 	
 	/*
 	 *  Inform station state machine
@@ -327,7 +316,7 @@
  *
  */
 void irlmp_link_connect_confirm(struct lap_cb *self, struct qos_info *qos, 
-				struct sk_buff *userdata)
+				struct sk_buff *skb)
 {
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 
@@ -335,9 +324,7 @@
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 	ASSERT(qos != NULL, return;);
 
-	/* Don't need use the userdata for now */
-	if (userdata)
-		dev_kfree_skb(userdata);
+	/* Don't need use the skb for now */
 
 	/* Copy QoS settings for this session */
 	self->qos = qos;
diff -urN linux-2.5.69-bk18/net/irda/irnet/irnet.h linux-2.5.69-bk19/net/irda/irnet/irnet.h
--- linux-2.5.69-bk18/net/irda/irnet/irnet.h	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irnet/irnet.h	2003-05-26 04:41:43.000000000 -0700
@@ -229,6 +229,11 @@
  * v14 - 20.2.03 - Jean II
  *	o Add discovery hint bits in the control channel.
  *	o Remove obsolete MOD_INC/DEC_USE_COUNT in favor of .owner
+ *
+ * v15 - 7.4.03 - Jean II
+ *	o Replace spin_lock_irqsave() with spin_lock_bh() so that we can
+ *	  use ppp_unit_number(). It's probably also better overall...
+ *	o Disable call to ppp_unregister_channel(), because we can't do it.
  */
 
 /***************************** INCLUDES *****************************/
@@ -276,6 +281,7 @@
 #undef CONNECT_INDIC_KICK	/* Might mess IrDA, not needed */
 #undef FAIL_SEND_DISCONNECT	/* Might mess IrDA, not needed */
 #undef PASS_CONNECT_PACKETS	/* Not needed ? Safe */
+#undef MISSING_PPP_API		/* Stuff I wish I could do */
 
 /* PPP side of the business */
 #define BLOCK_WHEN_CONNECT	/* Block packets when connecting */
diff -urN linux-2.5.69-bk18/net/irda/irnet/irnet_irda.c linux-2.5.69-bk19/net/irda/irnet/irnet_irda.c
--- linux-2.5.69-bk18/net/irda/irnet/irnet_irda.c	2003-05-04 16:52:59.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irnet/irnet_irda.c	2003-05-26 04:41:43.000000000 -0700
@@ -31,7 +31,6 @@
 		 char *		name,
 		 __u16		hints)
 {
-  unsigned long		flags;		/* For spinlock */
   int			index;		/* In the log */
 
   DENTER(CTRL_TRACE, "(ap=0x%X, event=%d, daddr=%08x, name=``%s'')\n",
@@ -41,7 +40,7 @@
    * Note : as we are the only event producer, we only need to exclude
    * ourself when touching the log, which is nice and easy.
    */
-  spin_lock_irqsave(&irnet_events.spinlock, flags);
+  spin_lock_bh(&irnet_events.spinlock);
 
   /* Copy the event in the log */
   index = irnet_events.index;
@@ -69,7 +68,7 @@
   DEBUG(CTRL_INFO, "New event index is %d\n", irnet_events.index);
 
   /* Spin lock end */
-  spin_unlock_irqrestore(&irnet_events.spinlock, flags);
+  spin_unlock_bh(&irnet_events.spinlock);
 
   /* Now : wake up everybody waiting for events... */
   wake_up_interruptible_all(&irnet_events.rwait);
@@ -115,7 +114,7 @@
   notify.flow_indication	= irnet_flow_indication;
   notify.status_indication	= irnet_status_indication;
   notify.instance		= self;
-  strncpy(notify.name, IRNET_NOTIFY_NAME, NOTIFY_MAX_NAME);
+  strlcpy(notify.name, IRNET_NOTIFY_NAME, sizeof(notify.name));
 
   /* Open an IrTTP instance */
   self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
@@ -536,10 +535,9 @@
    *	     Can't re-insert (MUST remove first) so check for that... */
   if((irnet_server.running) && (self->q.q_next == NULL))
     {
-      unsigned long		flags;
-      spin_lock_irqsave(&irnet_server.spinlock, flags);
+      spin_lock_bh(&irnet_server.spinlock);
       hashbin_insert(irnet_server.list, (irda_queue_t *) self, 0, self->rname);
-      spin_unlock_irqrestore(&irnet_server.spinlock, flags);
+      spin_unlock_bh(&irnet_server.spinlock);
       DEBUG(IRDA_SOCK_INFO, "Inserted ``%s'' in hashbin...\n", self->rname);
     }
 
@@ -596,12 +594,11 @@
   if((irnet_server.running) && (self->q.q_next != NULL))
     {
       struct irnet_socket *	entry;
-      unsigned long		flags;
       DEBUG(IRDA_SOCK_INFO, "Removing from hash..\n");
-      spin_lock_irqsave(&irnet_server.spinlock, flags);
+      spin_lock_bh(&irnet_server.spinlock);
       entry = hashbin_remove_this(irnet_server.list, (irda_queue_t *) self);
       self->q.q_next = NULL;
-      spin_unlock_irqrestore(&irnet_server.spinlock, flags);
+      spin_unlock_bh(&irnet_server.spinlock);
       DASSERT(entry == self, , IRDA_SOCK_ERROR, "Can't remove from hash.\n");
     }
 
@@ -695,7 +692,7 @@
       if(discoveries[i].daddr == self->daddr)
 	{
 	  /* Yes !!! Get it.. */
-	  strncpy(self->rname, discoveries[i].info, NICKNAME_MAX_LEN);
+	  strlcpy(self->rname, discoveries[i].info, sizeof(self->rname));
 	  self->rname[NICKNAME_MAX_LEN + 1] = '\0';
 	  DEBUG(IRDA_SERV_INFO, "Device 0x%08x is in fact ``%s''.\n",
 		self->daddr, self->rname);
@@ -723,7 +720,6 @@
 irnet_find_socket(irnet_socket *	self)
 {
   irnet_socket *	new = (irnet_socket *) NULL;
-  unsigned long		flags;
   int			err;
 
   DENTER(IRDA_SERV_TRACE, "(self=0x%X)\n", (unsigned int) self);
@@ -736,7 +732,7 @@
   err = irnet_daddr_to_dname(self);
 
   /* Protect access to the instance list */
-  spin_lock_irqsave(&irnet_server.spinlock, flags);
+  spin_lock_bh(&irnet_server.spinlock);
 
   /* So now, try to get an socket having specifically
    * requested that nickname */
@@ -790,7 +786,7 @@
     }
 
   /* Spin lock end */
-  spin_unlock_irqrestore(&irnet_server.spinlock, flags);
+  spin_unlock_bh(&irnet_server.spinlock);
 
   DEXIT(IRDA_SERV_TRACE, " - new = 0x%X\n", (unsigned int) new);
   return new;
@@ -1135,10 +1131,15 @@
     {
       if(test_open)
 	{
+#ifdef MISSING_PPP_API
+	  /* ppp_unregister_channel() wants a user context, which we
+	   * are guaranteed to NOT have here. What are we supposed
+	   * to do here ? Jean II */
 	  /* If we were connected, cleanup & close the PPP channel,
 	   * which will kill pppd (hangup) and the rest */
 	  ppp_unregister_channel(&self->chan);
 	  self->ppp_open = 0;
+#endif
 	}
       else
 	{
@@ -1711,7 +1712,6 @@
 {
   irnet_socket *	self;
   char *		state;
-  unsigned long		flags;
   int			i = 0;
 
   len = 0;
@@ -1728,7 +1728,7 @@
     return len;
 
   /* Protect access to the instance list */
-  spin_lock_irqsave(&irnet_server.spinlock, flags);
+  spin_lock_bh(&irnet_server.spinlock);
 
   /* Get the sockets one by one... */
   self = (irnet_socket *) hashbin_get_first(irnet_server.list);
@@ -1780,7 +1780,7 @@
     }
 
   /* Spin lock end */
-  spin_unlock_irqrestore(&irnet_server.spinlock, flags);
+  spin_unlock_bh(&irnet_server.spinlock);
 
   return len;
 }
diff -urN linux-2.5.69-bk18/net/irda/irnet/irnet_ppp.c linux-2.5.69-bk19/net/irda/irnet/irnet_ppp.c
--- linux-2.5.69-bk18/net/irda/irnet/irnet_ppp.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irnet/irnet_ppp.c	2003-05-26 04:41:43.000000000 -0700
@@ -927,7 +927,7 @@
        * Jean II
        */
       DERROR(PPP_ERROR, "IrTTP doesn't like this packet !!! (0x%X)\n", ret);
-      dev_kfree_skb(skb);
+      /* irttp_data_request already free the packet */
     }
 
   DEXIT(PPP_TRACE, "\n");
diff -urN linux-2.5.69-bk18/net/irda/irqueue.c linux-2.5.69-bk19/net/irda/irqueue.c
--- linux-2.5.69-bk18/net/irda/irqueue.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irqueue.c	2003-05-26 04:41:43.000000000 -0700
@@ -594,7 +594,7 @@
 	 */
 	entry->q_hash = hashv;
 	if ( name )
-		strncpy( entry->q_name, name, 32);
+		strlcpy( entry->q_name, name, sizeof(entry->q_name));
 	
 	/*
 	 * Insert new entry first
diff -urN linux-2.5.69-bk18/net/irda/irsyms.c linux-2.5.69-bk19/net/irda/irsyms.c
--- linux-2.5.69-bk18/net/irda/irsyms.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irsyms.c	2003-05-26 04:41:43.000000000 -0700
@@ -167,7 +167,9 @@
 EXPORT_SYMBOL(irda_calc_crc16);
 EXPORT_SYMBOL(irda_crc16_table);
 EXPORT_SYMBOL(irda_start_timer);
+#ifdef CONFIG_ISA
 EXPORT_SYMBOL(setup_dma);
+#endif
 EXPORT_SYMBOL(infrared_mode);
 
 #ifdef CONFIG_IRTTY
@@ -248,7 +250,7 @@
 	notify->flow_indication = NULL;
 	notify->status_indication = NULL;
 	notify->instance = NULL;
-	strncpy(notify->name, "Unknown", NOTIFY_MAX_NAME);
+	strlcpy(notify->name, "Unknown", sizeof(notify->name));
 }
 
 /*
diff -urN linux-2.5.69-bk18/net/irda/irttp.c linux-2.5.69-bk19/net/irda/irttp.c
--- linux-2.5.69-bk18/net/irda/irttp.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/net/irda/irttp.c	2003-05-26 04:41:43.000000000 -0700
@@ -11,7 +11,7 @@
  * 
  *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
- *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
+ *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -259,11 +259,17 @@
 
 		dev_kfree_skb(frag);
 	}
-	IRDA_DEBUG(2, "%s(), frame len=%d\n",  __FUNCTION__, n);
 
-	IRDA_DEBUG(2, "%s(), rx_sdu_size=%d\n",  __FUNCTION__,
-		   self->rx_sdu_size);
-	ASSERT(n <= self->rx_sdu_size, return NULL;);
+	IRDA_DEBUG(2,
+		   "%s(), frame len=%d, rx_sdu_size=%d, rx_max_sdu_size=%d\n",
+		   __FUNCTION__, n, self->rx_sdu_size, self->rx_max_sdu_size);
+	/* Note : irttp_run_rx_queue() calculate self->rx_sdu_size
+	 * by summing the size of all fragments, so we should always
+	 * have n == self->rx_sdu_size, except in cases where we
+	 * droped the last fragment (when self->rx_sdu_size exceed
+	 * self->rx_max_sdu_size), where n < self->rx_sdu_size.
+	 * Jean II */
+	ASSERT(n <= self->rx_sdu_size, n = self->rx_sdu_size;);
 
 	/* Set the new length */
 	skb_trim(skb, n);
@@ -537,19 +543,23 @@
 	if ((skb->len == 0) || (!self->connected)) {
 		IRDA_DEBUG(1, "%s(), No data, or not connected\n",
 			   __FUNCTION__);
-		return -1;
+		goto err;
 	}
 
 	if (skb->len > self->max_seg_size) {
 		IRDA_DEBUG(1, "%s(), UData is to large for IrLAP!\n",
 			   __FUNCTION__);
-		return -1;
+		goto err;
 	}
 
 	irlmp_udata_request(self->lsap, skb);
 	self->stats.tx_packets++;
 
 	return 0;
+
+err:
+	dev_kfree_skb(skb);
+	return -1;
 }
 
 /*
@@ -561,6 +571,7 @@
 int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
 {
 	__u8 *frame;
+	int ret;
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
@@ -572,7 +583,8 @@
 	/* Check that nothing bad happens */
 	if ((skb->len == 0) || (!self->connected)) {
 		WARNING("%s: No data, or not connected\n", __FUNCTION__);
-		return -ENOTCONN;
+		ret = -ENOTCONN;
+		goto err;
 	}
 
 	/*
@@ -582,7 +594,8 @@
 	if ((self->tx_max_sdu_size == 0) && (skb->len > self->max_seg_size)) {
 		ERROR("%s: SAR disabled, and data is to large for IrLAP!\n",
 				__FUNCTION__);
-		return -EMSGSIZE;
+		ret = -EMSGSIZE;
+		goto err;
 	}
 
 	/*
@@ -595,7 +608,8 @@
 	{
 		ERROR("%s: SAR enabled, but data is larger than TxMaxSduSize!\n",
 		      __FUNCTION__);
-		return -EMSGSIZE;
+		ret = -EMSGSIZE;
+		goto err;
 	}
 	/*
 	 *  Check if transmit queue is full
@@ -607,8 +621,9 @@
 		irttp_run_tx_queue(self);
 
 		/* Drop packet. This error code should trigger the caller
-		 * to requeue the packet in the client code - Jean II */
-		return -ENOBUFS;
+		 * to resend the data in the client code - Jean II */
+		ret = -ENOBUFS;
+		goto err;
 	}
 
 	/* Queue frame, or queue frame segments */
@@ -651,6 +666,10 @@
 	irttp_run_tx_queue(self);
 
 	return 0;
+
+err:
+	dev_kfree_skb(skb);
+	return ret;
 }
 
 /*
@@ -822,6 +841,7 @@
 				  struct sk_buff *skb)
 {
 	struct tsap_cb *self;
+	int err;
 
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 
@@ -831,14 +851,19 @@
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
 	ASSERT(skb != NULL, return -1;);
 
-	/* Just pass data to layer above */
-	if (self->notify.udata_indication)
-		self->notify.udata_indication(self->notify.instance, self,skb);
-	else
-		dev_kfree_skb(skb);
-
 	self->stats.rx_packets++;
 
+	/* Just pass data to layer above */
+	if (self->notify.udata_indication) {
+		err = self->notify.udata_indication(self->notify.instance,
+						    self,skb);
+		/* Same comment as in irttp_do_data_indication() */
+		if (err != -ENOMEM) 
+			return 0;
+	}
+	/* Either no handler, or -ENOMEM */
+	dev_kfree_skb(skb);
+
 	return 0;
 }
 
@@ -1040,7 +1065,7 @@
 			  struct qos_info *qos, __u32 max_sdu_size,
 			  struct sk_buff *userdata)
 {
-	struct sk_buff *skb;
+	struct sk_buff *tx_skb;
 	__u8 *frame;
 	__u8 n;
 
@@ -1049,19 +1074,22 @@
 	ASSERT(self != NULL, return -EBADR;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return -EBADR;);
 
-	if (self->connected)
+	if (self->connected) {
+		if(userdata)
+			dev_kfree_skb(userdata);
 		return -EISCONN;
+	}
 
 	/* Any userdata supplied? */
 	if (userdata == NULL) {
-		skb = dev_alloc_skb(64);
-		if (!skb)
+		tx_skb = dev_alloc_skb(64);
+		if (!tx_skb)
 			return -ENOMEM;
 
 		/* Reserve space for MUX_CONTROL and LAP header */
-		skb_reserve(skb, TTP_MAX_HEADER);
+		skb_reserve(tx_skb, TTP_MAX_HEADER);
 	} else {
-		skb = userdata;
+		tx_skb = userdata;
 		/*
 		 *  Check that the client has reserved enough space for
 		 *  headers
@@ -1094,11 +1122,11 @@
 
 	/* SAR enabled? */
 	if (max_sdu_size > 0) {
-		ASSERT(skb_headroom(skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER),
+		ASSERT(skb_headroom(tx_skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER),
 		       return -1;);
 
 		/* Insert SAR parameters */
-		frame = skb_push(skb, TTP_HEADER+TTP_SAR_HEADER);
+		frame = skb_push(tx_skb, TTP_HEADER+TTP_SAR_HEADER);
 
 		frame[0] = TTP_PARAMETERS | n;
 		frame[1] = 0x04; /* Length */
@@ -1109,7 +1137,7 @@
 			      (__u16 *)(frame+4));
 	} else {
 		/* Insert plain TTP header */
-		frame = skb_push(skb, TTP_HEADER);
+		frame = skb_push(tx_skb, TTP_HEADER);
 
 		/* Insert initial credit in frame */
 		frame[0] = n & 0x7f;
@@ -1117,7 +1145,7 @@
 
 	/* Connect with IrLMP. No QoS parameters for now */
 	return irlmp_connect_request(self->lsap, dtsap_sel, saddr, daddr, qos,
-				     skb);
+				     tx_skb);
 }
 
 /*
@@ -1201,7 +1229,8 @@
 		self->notify.connect_confirm(self->notify.instance, self, qos,
 					     self->tx_max_sdu_size,
 					     self->max_header_size, skb);
-	}
+	} else
+		dev_kfree_skb(skb);
 }
 
 /*
@@ -1286,7 +1315,7 @@
 int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
 			   struct sk_buff *userdata)
 {
-	struct sk_buff *skb;
+	struct sk_buff *tx_skb;
 	__u8 *frame;
 	int ret;
 	__u8 n;
@@ -1299,19 +1328,19 @@
 
 	/* Any userdata supplied? */
 	if (userdata == NULL) {
-		skb = dev_alloc_skb(64);
-		if (!skb)
+		tx_skb = dev_alloc_skb(64);
+		if (!tx_skb)
 			return -ENOMEM;
 
 		/* Reserve space for MUX_CONTROL and LAP header */
-		skb_reserve(skb, TTP_MAX_HEADER);
+		skb_reserve(tx_skb, TTP_MAX_HEADER);
 	} else {
-		skb = userdata;
+		tx_skb = userdata;
 		/*
 		 *  Check that the client has reserved enough space for
 		 *  headers
 		 */
-		ASSERT(skb_headroom(skb) >= TTP_MAX_HEADER, return -1;);
+		ASSERT(skb_headroom(tx_skb) >= TTP_MAX_HEADER, return -1;);
 	}
 
 	self->avail_credit = 0;
@@ -1333,11 +1362,11 @@
 
 	/* SAR enabled? */
 	if (max_sdu_size > 0) {
-		ASSERT(skb_headroom(skb) >= (TTP_MAX_HEADER+TTP_SAR_HEADER),
+		ASSERT(skb_headroom(tx_skb) >= (TTP_MAX_HEADER+TTP_SAR_HEADER),
 		       return -1;);
 
 		/* Insert TTP header with SAR parameters */
-		frame = skb_push(skb, TTP_HEADER+TTP_SAR_HEADER);
+		frame = skb_push(tx_skb, TTP_HEADER+TTP_SAR_HEADER);
 
 		frame[0] = TTP_PARAMETERS | n;
 		frame[1] = 0x04; /* Length */
@@ -1352,12 +1381,12 @@
 			      (__u16 *)(frame+4));
 	} else {
 		/* Insert TTP header */
-		frame = skb_push(skb, TTP_HEADER);
+		frame = skb_push(tx_skb, TTP_HEADER);
 
 		frame[0] = n & 0x7f;
 	}
 
-	ret = irlmp_connect_response(self->lsap, skb);
+	ret = irlmp_connect_response(self->lsap, tx_skb);
 
 	return ret;
 }
@@ -1423,7 +1452,6 @@
 int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
 			     int priority)
 {
-	struct sk_buff *skb;
 	int ret;
 
 	ASSERT(self != NULL, return -1;);
@@ -1488,16 +1516,17 @@
 	self->connected = FALSE;
 
 	if (!userdata) {
-		skb = dev_alloc_skb(64);
-		if (!skb)
+		struct sk_buff *tx_skb;
+		tx_skb = dev_alloc_skb(64);
+		if (!tx_skb)
 			return -ENOMEM;
 
 		/*
 		 *  Reserve space for MUX and LAP header
 		 */
-		skb_reserve(skb, TTP_MAX_HEADER);
+		skb_reserve(tx_skb, TTP_MAX_HEADER);
 
-		userdata = skb;
+		userdata = tx_skb;
 	}
 	ret = irlmp_disconnect_request(self->lsap, userdata);
 
@@ -1556,7 +1585,7 @@
 /*
  * Function irttp_do_data_indication (self, skb)
  *
- *    Try to deliver reassebled skb to layer above, and requeue it if that
+ *    Try to deliver reassembled skb to layer above, and requeue it if that
  *    for some reason should fail. We mark rx sdu as busy to apply back
  *    pressure is necessary.
  */
diff -urN linux-2.5.69-bk18/net/netlink/af_netlink.c linux-2.5.69-bk19/net/netlink/af_netlink.c
--- linux-2.5.69-bk18/net/netlink/af_netlink.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/netlink/af_netlink.c	2003-05-26 04:41:43.000000000 -0700
@@ -1070,9 +1070,6 @@
 #endif
 	/* The netlink device handler may be needed early. */ 
 	rtnetlink_init();
-#ifdef CONFIG_NETLINK_DEV
-	init_netlink();
-#endif
 	return 0;
 }
 
diff -urN linux-2.5.69-bk18/net/netlink/netlink_dev.c linux-2.5.69-bk19/net/netlink/netlink_dev.c
--- linux-2.5.69-bk18/net/netlink/netlink_dev.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/netlink/netlink_dev.c	2003-05-26 04:41:43.000000000 -0700
@@ -220,7 +220,7 @@
 	},
 };
 
-int __init init_netlink(void)
+static int __init init_netlink(void)
 {
 	int i;
 
@@ -245,17 +245,7 @@
 	return 0;
 }
 
-#ifdef MODULE
-
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	printk(KERN_INFO "Network Kernel/User communications module 0.04\n");
-	return init_netlink();
-}
-
-void cleanup_module(void)
+static void __exit cleanup_netlink(void)
 {
 	int i;
 
@@ -267,4 +257,6 @@
 	unregister_chrdev(NETLINK_MAJOR, "netlink");
 }
 
-#endif
+MODULE_LICENSE("GPL");
+module_init(init_netlink);
+module_exit(cleanup_netlink);
diff -urN linux-2.5.69-bk18/net/netsyms.c linux-2.5.69-bk19/net/netsyms.c
--- linux-2.5.69-bk18/net/netsyms.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/netsyms.c	2003-05-26 04:41:43.000000000 -0700
@@ -281,6 +281,14 @@
 EXPORT_SYMBOL(register_inetaddr_notifier);
 EXPORT_SYMBOL(unregister_inetaddr_notifier);
 
+/* proc */
+#ifdef CONFIG_PROC_FS
+EXPORT_SYMBOL(udp_proc_register);
+EXPORT_SYMBOL(udp_proc_unregister);
+EXPORT_SYMBOL(tcp_proc_register);
+EXPORT_SYMBOL(tcp_proc_unregister);
+#endif
+
 /* needed for ip_gre -cw */
 EXPORT_SYMBOL(ip_statistics);
 
diff -urN linux-2.5.69-bk18/net/packet/af_packet.c linux-2.5.69-bk19/net/packet/af_packet.c
--- linux-2.5.69-bk18/net/packet/af_packet.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/packet/af_packet.c	2003-05-26 04:41:43.000000000 -0700
@@ -255,7 +255,7 @@
 	 */
 
 	spkt->spkt_family = dev->type;
-	strncpy(spkt->spkt_device, dev->name, sizeof(spkt->spkt_device));
+	strlcpy(spkt->spkt_device, dev->name, sizeof(spkt->spkt_device));
 	spkt->spkt_protocol = skb->protocol;
 
 	/*
@@ -878,8 +878,7 @@
 	 
 	if(addr_len!=sizeof(struct sockaddr))
 		return -EINVAL;
-	strncpy(name,uaddr->sa_data,14);
-	name[14]=0;
+	strlcpy(name,uaddr->sa_data,sizeof(name));
 
 	dev = dev_get_by_name(name);
 	if (dev) {
@@ -1096,7 +1095,7 @@
 	uaddr->sa_family = AF_PACKET;
 	dev = dev_get_by_index(pkt_sk(sk)->ifindex);
 	if (dev) {
-		strncpy(uaddr->sa_data, dev->name, 15);
+		strlcpy(uaddr->sa_data, dev->name, 15);
 		dev_put(dev);
 	} else
 		memset(uaddr->sa_data, 0, 14);
diff -urN linux-2.5.69-bk18/net/rxrpc/krxtimod.c linux-2.5.69-bk19/net/rxrpc/krxtimod.c
--- linux-2.5.69-bk18/net/rxrpc/krxtimod.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/net/rxrpc/krxtimod.c	2003-05-26 04:41:43.000000000 -0700
@@ -82,7 +82,7 @@
 
 	for (;;) {
 		unsigned long jif;
-		signed long timeout;
+		unsigned long timeout;
 
 		/* deal with the server being asked to die */
 		if (krxtimod_die) {
diff -urN linux-2.5.69-bk18/net/socket.c linux-2.5.69-bk19/net/socket.c
--- linux-2.5.69-bk18/net/socket.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/socket.c	2003-05-26 04:41:43.000000000 -0700
@@ -311,7 +311,7 @@
 {
 	sock_inode_cachep = kmem_cache_create("sock_inode_cache",
 					     sizeof(struct socket_alloc),
-					     0, SLAB_HWCACHE_ALIGN,
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (sock_inode_cachep == NULL)
 		return -ENOMEM;
@@ -325,7 +325,7 @@
 };
 
 static struct super_block *sockfs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+	int flags, const char *dev_name, void *data)
 {
 	return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC);
 }
diff -urN linux-2.5.69-bk18/net/sunrpc/rpc_pipe.c linux-2.5.69-bk19/net/sunrpc/rpc_pipe.c
--- linux-2.5.69-bk18/net/sunrpc/rpc_pipe.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/sunrpc/rpc_pipe.c	2003-05-26 04:41:43.000000000 -0700
@@ -749,7 +749,7 @@
 
 static struct super_block *
 rpc_get_sb(struct file_system_type *fs_type,
-		int flags, char *dev_name, void *data)
+		int flags, const char *dev_name, void *data)
 {
 	return get_sb_single(fs_type, flags, data, rpc_fill_super);
 }
@@ -782,7 +782,7 @@
 {
 	rpc_inode_cachep = kmem_cache_create("rpc_inode_cache",
                                              sizeof(struct rpc_inode),
-                                             0, SLAB_HWCACHE_ALIGN,
+                                             0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
                                              init_once, NULL);
 	if (!rpc_inode_cachep)
 		return -ENOMEM;
diff -urN linux-2.5.69-bk18/net/sunrpc/sunrpc_syms.c linux-2.5.69-bk19/net/sunrpc/sunrpc_syms.c
--- linux-2.5.69-bk18/net/sunrpc/sunrpc_syms.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/net/sunrpc/sunrpc_syms.c	2003-05-26 04:41:43.000000000 -0700
@@ -169,7 +169,7 @@
 #ifdef RPC_DEBUG
 	rpc_unregister_sysctl();
 #endif
-#ifdef CONFIG_PROCFS
+#ifdef CONFIG_PROC_FS
 	rpc_proc_exit();
 #endif
 }
diff -urN linux-2.5.69-bk18/net/wanrouter/af_wanpipe.c linux-2.5.69-bk19/net/wanrouter/af_wanpipe.c
--- linux-2.5.69-bk18/net/wanrouter/af_wanpipe.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/wanrouter/af_wanpipe.c	2003-05-26 04:41:43.000000000 -0700
@@ -1408,8 +1408,7 @@
 		/* Bind a socket to a interface name 
                  * This is used by PVC mostly
                  */
-		strncpy(name,sll->sll_device,14);
-		name[14]=0;
+		strlcpy(name,sll->sll_device,sizeof(name));
 		dev = dev_get_by_name(name);
 		if (dev == NULL){
 			printk(KERN_INFO "wansock: Failed to get Dev from name: %s,\n",
diff -urN linux-2.5.69-bk18/net/xfrm/xfrm_user.c linux-2.5.69-bk19/net/xfrm/xfrm_user.c
--- linux-2.5.69-bk18/net/xfrm/xfrm_user.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/net/xfrm/xfrm_user.c	2003-05-26 04:41:43.000000000 -0700
@@ -634,6 +634,7 @@
 	struct xfrm_userpolicy_info *p = NLMSG_DATA(nlh);
 	struct xfrm_policy *xp;
 	int err;
+	int excl;
 
 	err = verify_newpolicy_info(p);
 	if (err)
@@ -643,7 +644,8 @@
 	if (!xp)
 		return err;
 
-	err = xfrm_policy_insert(p->dir, xp, 1);
+	excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
+	err = xfrm_policy_insert(p->dir, xp, excl);
 	if (err) {
 		kfree(xp);
 		return err;
@@ -803,6 +805,7 @@
 	NLMSG_LENGTH(sizeof(struct xfrm_userspi_info)),	/* ALLOC SPI */
 	NLMSG_LENGTH(sizeof(struct xfrm_user_acquire)),	/* ACQUIRE */
 	NLMSG_LENGTH(sizeof(struct xfrm_user_expire)),	/* EXPIRE */
+	NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info)),/* UPD POLICY */
 };
 
 static struct xfrm_link {
@@ -822,6 +825,9 @@
 		.dump	=	xfrm_dump_policy,
 	},
 	{	.doit	=	xfrm_alloc_userspi	},
+	{},
+	{},
+	{	.doit	=	xfrm_add_policy 	},
 };
 
 static int xfrm_done(struct netlink_callback *cb)
diff -urN linux-2.5.69-bk18/security/dummy.c linux-2.5.69-bk19/security/dummy.c
--- linux-2.5.69-bk18/security/dummy.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/security/dummy.c	2003-05-26 04:41:43.000000000 -0700
@@ -354,6 +354,21 @@
 	return 0;
 }
 
+static int dummy_inode_getsecurity(struct dentry *dentry, const char *name, void *buffer, size_t size)
+{
+	return -EOPNOTSUPP;
+}
+
+static int dummy_inode_setsecurity(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) 
+{
+	return -EOPNOTSUPP;
+}
+
+static int dummy_inode_listsecurity(struct dentry *dentry, char *buffer)
+{
+	return 0;
+}
+
 static int dummy_file_permission (struct file *file, int mask)
 {
 	return 0;
@@ -513,6 +528,9 @@
 	return;
 }
 
+static void dummy_task_to_inode(struct task_struct *p, struct inode *inode)
+{ }
+
 static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
 {
 	return 0;
@@ -741,6 +759,16 @@
 	return;
 }
 
+static int dummy_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
+{
+	return -EINVAL;
+}
+
+static int dummy_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
+{
+	return -EINVAL;
+}
+
 
 struct security_operations dummy_security_ops;
 
@@ -812,6 +840,9 @@
 	set_to_dummy_if_null(ops, inode_getxattr);
 	set_to_dummy_if_null(ops, inode_listxattr);
 	set_to_dummy_if_null(ops, inode_removexattr);
+	set_to_dummy_if_null(ops, inode_getsecurity);
+	set_to_dummy_if_null(ops, inode_setsecurity);
+	set_to_dummy_if_null(ops, inode_listsecurity);
 	set_to_dummy_if_null(ops, file_permission);
 	set_to_dummy_if_null(ops, file_alloc_security);
 	set_to_dummy_if_null(ops, file_free_security);
@@ -842,6 +873,7 @@
 	set_to_dummy_if_null(ops, task_prctl);
 	set_to_dummy_if_null(ops, task_kmod_set_label);
 	set_to_dummy_if_null(ops, task_reparent_to_init);
+ 	set_to_dummy_if_null(ops, task_to_inode);
 	set_to_dummy_if_null(ops, ipc_permission);
 	set_to_dummy_if_null(ops, msg_msg_alloc_security);
 	set_to_dummy_if_null(ops, msg_msg_free_security);
@@ -866,6 +898,8 @@
 	set_to_dummy_if_null(ops, register_security);
 	set_to_dummy_if_null(ops, unregister_security);
 	set_to_dummy_if_null(ops, d_instantiate);
+ 	set_to_dummy_if_null(ops, getprocattr);
+ 	set_to_dummy_if_null(ops, setprocattr);
 #ifdef CONFIG_SECURITY_NETWORK
 	set_to_dummy_if_null(ops, unix_stream_connect);
 	set_to_dummy_if_null(ops, unix_may_send);
diff -urN linux-2.5.69-bk18/sound/Makefile linux-2.5.69-bk19/sound/Makefile
--- linux-2.5.69-bk18/sound/Makefile	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/sound/Makefile	2003-05-26 04:41:43.000000000 -0700
@@ -3,6 +3,7 @@
 
 obj-$(CONFIG_SOUND) += soundcore.o
 obj-$(CONFIG_SOUND_PRIME) += oss/
+obj-$(CONFIG_DMASOUND) += oss/
 obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/
 
 ifeq ($(CONFIG_SND),y)
diff -urN linux-2.5.69-bk18/sound/core/control.c linux-2.5.69-bk19/sound/core/control.c
--- linux-2.5.69-bk18/sound/core/control.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/control.c	2003-05-26 04:41:43.000000000 -0700
@@ -222,7 +222,7 @@
 	kctl.id.device = ncontrol->device;
 	kctl.id.subdevice = ncontrol->subdevice;
 	if (ncontrol->name)
-		strncpy(kctl.id.name, ncontrol->name, sizeof(kctl.id.name)-1);
+		strlcpy(kctl.id.name, ncontrol->name, sizeof(kctl.id.name));
 	kctl.id.index = ncontrol->index;
 	kctl.count = ncontrol->count ? ncontrol->count : 1;
 	access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
@@ -449,12 +449,12 @@
 	memset(&info, 0, sizeof(info));
 	down_read(&snd_ioctl_rwsem);
 	info.card = card->number;
-	strncpy(info.id, card->id, sizeof(info.id) - 1);
-	strncpy(info.driver, card->driver, sizeof(info.driver) - 1);
-	strncpy(info.name, card->shortname, sizeof(info.name) - 1);
-	strncpy(info.longname, card->longname, sizeof(info.longname) - 1);
-	strncpy(info.mixername, card->mixername, sizeof(info.mixername) - 1);
-	strncpy(info.components, card->components, sizeof(info.components) - 1);
+	strlcpy(info.id, card->id, sizeof(info.id));
+	strlcpy(info.driver, card->driver, sizeof(info.driver));
+	strlcpy(info.name, card->shortname, sizeof(info.name));
+	strlcpy(info.longname, card->longname, sizeof(info.longname));
+	strlcpy(info.mixername, card->mixername, sizeof(info.mixername));
+	strlcpy(info.components, card->components, sizeof(info.components));
 	up_read(&snd_ioctl_rwsem);
 	if (copy_to_user((void *) arg, &info, sizeof(snd_ctl_card_info_t)))
 		return -EFAULT;
diff -urN linux-2.5.69-bk18/sound/core/hwdep.c linux-2.5.69-bk19/sound/core/hwdep.c
--- linux-2.5.69-bk18/sound/core/hwdep.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/hwdep.c	2003-05-26 04:41:43.000000000 -0700
@@ -169,8 +169,8 @@
 	
 	memset(&info, 0, sizeof(info));
 	info.card = hw->card->number;
-	strncpy(info.id, hw->id, sizeof(info.id) - 1);	
-	strncpy(info.name, hw->name, sizeof(info.name) - 1);
+	strlcpy(info.id, hw->id, sizeof(info.id));	
+	strlcpy(info.name, hw->name, sizeof(info.name));
 	info.iface = hw->iface;
 	if (copy_to_user(_info, &info, sizeof(info)))
 		return -EFAULT;
@@ -343,7 +343,7 @@
 	hwdep->card = card;
 	hwdep->device = device;
 	if (id) {
-		strncpy(hwdep->id, id, sizeof(hwdep->id) - 1);
+		strlcpy(hwdep->id, id, sizeof(hwdep->id));
 	}
 #ifdef CONFIG_SND_OSSEMUL
 	hwdep->oss_type = -1;
diff -urN linux-2.5.69-bk18/sound/core/init.c linux-2.5.69-bk19/sound/core/init.c
--- linux-2.5.69-bk18/sound/core/init.c	2003-05-04 16:53:03.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/init.c	2003-05-26 04:41:43.000000000 -0700
@@ -76,7 +76,7 @@
 	if (xid) {
 		if (!snd_info_check_reserved_words(xid))
 			goto __error;
-		strncpy(card->id, xid, sizeof(card->id) - 1);
+		strlcpy(card->id, xid, sizeof(card->id));
 	}
 	write_lock(&snd_card_rwlock);
 	if (idx < 0) {
diff -urN linux-2.5.69-bk18/sound/core/oss/mixer_oss.c linux-2.5.69-bk19/sound/core/oss/mixer_oss.c
--- linux-2.5.69-bk18/sound/core/oss/mixer_oss.c	2003-05-04 16:53:33.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/oss/mixer_oss.c	2003-05-26 04:41:43.000000000 -0700
@@ -85,8 +85,8 @@
 	struct mixer_info info;
 	
 	memset(&info, 0, sizeof(info));
-	strncpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id) - 1);
-	strncpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name) - 1);
+	strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id));
+	strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name));
 	info.modify_counter = card->mixer_oss_change_count;
 	if (copy_to_user(_info, &info, sizeof(info)))
 		return -EFAULT;
@@ -101,8 +101,8 @@
 	_old_mixer_info info;
 	
 	memset(&info, 0, sizeof(info));
-	strncpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id) - 1);
-	strncpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name) - 1);
+	strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id));
+	strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name));
 	if (copy_to_user(_info, &info, sizeof(info)))
 		return -EFAULT;
 	return 0;
@@ -1215,11 +1215,10 @@
 		}
 		mixer->oss_dev_alloc = 1;
 		mixer->card = card;
-		if (*card->mixername) {
-			strncpy(mixer->name, card->mixername, sizeof(mixer->name) - 1);
-			mixer->name[sizeof(mixer->name)-1] = 0;
-		} else
-			strcpy(mixer->name, name);
+		if (*card->mixername)
+			strlcpy(mixer->name, card->mixername, sizeof(mixer->name));
+		else
+			strlcpy(mixer->name, name, sizeof(mixer->name));
 #ifdef SNDRV_OSS_INFO_DEV_MIXERS
 		snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIXERS,
 				      card->number,
diff -urN linux-2.5.69-bk18/sound/core/pcm.c linux-2.5.69-bk19/sound/core/pcm.c
--- linux-2.5.69-bk18/sound/core/pcm.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/pcm.c	2003-05-26 04:41:43.000000000 -0700
@@ -639,7 +639,7 @@
 	pcm->card = card;
 	pcm->device = device;
 	if (id) {
-		strncpy(pcm->id, id, sizeof(pcm->id) - 1);
+		strlcpy(pcm->id, id, sizeof(pcm->id));
 	}
 	if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
 		snd_pcm_free(pcm);
diff -urN linux-2.5.69-bk18/sound/core/pcm_native.c linux-2.5.69-bk19/sound/core/pcm_native.c
--- linux-2.5.69-bk18/sound/core/pcm_native.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/pcm_native.c	2003-05-26 04:41:43.000000000 -0700
@@ -92,13 +92,13 @@
 	info->device = pcm->device;
 	info->stream = substream->stream;
 	info->subdevice = substream->number;
-	strncpy(info->id, pcm->id, sizeof(info->id)-1);
-	strncpy(info->name, pcm->name, sizeof(info->name)-1);
+	strlcpy(info->id, pcm->id, sizeof(info->id));
+	strlcpy(info->name, pcm->name, sizeof(info->name));
 	info->dev_class = pcm->dev_class;
 	info->dev_subclass = pcm->dev_subclass;
 	info->subdevices_count = pstr->substream_count;
 	info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
-	strncpy(info->subname, substream->name, sizeof(info->subname)-1);
+	strlcpy(info->subname, substream->name, sizeof(info->subname));
 	runtime = substream->runtime;
 	/* AB: FIXME!!! This is definitely nonsense */
 	if (runtime) {
diff -urN linux-2.5.69-bk18/sound/core/rawmidi.c linux-2.5.69-bk19/sound/core/rawmidi.c
--- linux-2.5.69-bk18/sound/core/rawmidi.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/rawmidi.c	2003-05-26 04:41:43.000000000 -0700
@@ -1394,7 +1394,7 @@
 	init_MUTEX(&rmidi->open_mutex);
 	init_waitqueue_head(&rmidi->open_wait);
 	if (id != NULL)
-		strncpy(rmidi->id, id, sizeof(rmidi->id) - 1);
+		strlcpy(rmidi->id, id, sizeof(rmidi->id));
 	if ((err = snd_rawmidi_alloc_substreams(rmidi, &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT], SNDRV_RAWMIDI_STREAM_INPUT, input_count)) < 0) {
 		snd_rawmidi_free(rmidi);
 		return err;
diff -urN linux-2.5.69-bk18/sound/core/seq/oss/seq_oss_midi.c linux-2.5.69-bk19/sound/core/seq/oss/seq_oss_midi.c
--- linux-2.5.69-bk18/sound/core/seq/oss/seq_oss_midi.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/seq/oss/seq_oss_midi.c	2003-05-26 04:41:43.000000000 -0700
@@ -184,8 +184,7 @@
 	snd_use_lock_init(&mdev->use_lock);
 
 	/* copy and truncate the name of synth device */
-	strncpy(mdev->name, pinfo->name, sizeof(mdev->name));
-	mdev->name[sizeof(mdev->name) - 1] = 0;
+	strlcpy(mdev->name, pinfo->name, sizeof(mdev->name));
 
 	/* create MIDI coder */
 	if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) {
@@ -659,7 +658,7 @@
 	inf->device = dev;
 	inf->dev_type = 0; /* FIXME: ?? */
 	inf->capabilities = 0; /* FIXME: ?? */
-	strncpy(inf->name, mdev->name, sizeof(inf->name));
+	strlcpy(inf->name, mdev->name, sizeof(inf->name));
 	snd_use_lock_free(&mdev->use_lock);
 	return 0;
 }
diff -urN linux-2.5.69-bk18/sound/core/seq/oss/seq_oss_synth.c linux-2.5.69-bk19/sound/core/seq/oss/seq_oss_synth.c
--- linux-2.5.69-bk18/sound/core/seq/oss/seq_oss_synth.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/seq/oss/seq_oss_synth.c	2003-05-26 04:41:43.000000000 -0700
@@ -117,8 +117,7 @@
 	snd_use_lock_init(&rec->use_lock);
 
 	/* copy and truncate the name of synth device */
-	strncpy(rec->name, dev->name, sizeof(rec->name));
-	rec->name[sizeof(rec->name)-1] = 0;
+	strlcpy(rec->name, dev->name, sizeof(rec->name));
 
 	/* registration */
 	spin_lock_irqsave(&register_lock, flags);
@@ -611,7 +610,7 @@
 		inf->synth_subtype = 0;
 		inf->nr_voices = 16;
 		inf->device = dev;
-		strncpy(inf->name, minf.name, sizeof(inf->name));
+		strlcpy(inf->name, minf.name, sizeof(inf->name));
 	} else {
 		if ((rec = get_synthdev(dp, dev)) == NULL)
 			return -ENXIO;
@@ -619,7 +618,7 @@
 		inf->synth_subtype = rec->synth_subtype;
 		inf->nr_voices = rec->nr_voices;
 		inf->device = dev;
-		strncpy(inf->name, rec->name, sizeof(inf->name));
+		strlcpy(inf->name, rec->name, sizeof(inf->name));
 		snd_use_lock_free(&rec->use_lock);
 	}
 	return 0;
diff -urN linux-2.5.69-bk18/sound/core/seq/seq_clientmgr.c linux-2.5.69-bk19/sound/core/seq/seq_clientmgr.c
--- linux-2.5.69-bk18/sound/core/seq/seq_clientmgr.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/seq/seq_clientmgr.c	2003-05-26 04:41:43.000000000 -0700
@@ -1184,10 +1184,9 @@
 		return -EINVAL;
 
 	/* fill the info fields */
-	if (client_info.name[0]) {
-		strncpy(client->name, client_info.name, sizeof(client->name)-1);
-		client->name[sizeof(client->name)-1] = '\0';
-	}
+	if (client_info.name[0])
+		strlcpy(client->name, client_info.name, sizeof(client->name));
+
 	client->filter = client_info.filter;
 	client->event_lost = client_info.event_lost;
 	memcpy(client->event_filter, client_info.event_filter, 32);
@@ -1487,9 +1486,8 @@
 
 	/* set queue name */
 	if (! info.name[0])
-		sprintf(info.name, "Queue-%d", q->queue);
-	strncpy(q->name, info.name, sizeof(q->name)-1);
-	q->name[sizeof(q->name)-1] = 0;
+		snprintf(info.name, sizeof(info.name), "Queue-%d", q->queue);
+	strlcpy(q->name, info.name, sizeof(q->name));
 	queuefree(q);
 
 	if (copy_to_user(arg, &info, sizeof(info)))
@@ -1526,8 +1524,7 @@
 	info.queue = q->queue;
 	info.owner = q->owner;
 	info.locked = q->locked;
-	strncpy(info.name, q->name, sizeof(info.name) - 1);
-	info.name[sizeof(info.name)-1] = 0;
+	strlcpy(info.name, q->name, sizeof(info.name));
 	queuefree(q);
 
 	if (copy_to_user(arg, &info, sizeof(info)))
@@ -1565,8 +1562,7 @@
 		queuefree(q);
 		return -EPERM;
 	}
-	strncpy(q->name, info.name, sizeof(q->name) - 1);
-	q->name[sizeof(q->name)-1] = 0;
+	strlcpy(q->name, info.name, sizeof(q->name));
 	queuefree(q);
 
 	return 0;
diff -urN linux-2.5.69-bk18/sound/core/seq/seq_device.c linux-2.5.69-bk19/sound/core/seq/seq_device.c
--- linux-2.5.69-bk18/sound/core/seq/seq_device.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/seq/seq_device.c	2003-05-26 04:41:43.000000000 -0700
@@ -187,8 +187,7 @@
 	/* set up device info */
 	dev->card = card;
 	dev->device = device;
-	strncpy(dev->id, id, sizeof(dev->id) - 1);
-	dev->id[sizeof(dev->id) - 1] = 0;
+	strlcpy(dev->id, id, sizeof(dev->id));
 	dev->argsize = argsize;
 	dev->status = SNDRV_SEQ_DEVICE_FREE;
 
@@ -350,8 +349,7 @@
 	memset(ops, 0, sizeof(*ops));
 
 	/* set up driver entry */
-	strncpy(ops->id, id, sizeof(ops->id) - 1);
-	ops->id[sizeof(ops->id) - 1] = 0;
+	strlcpy(ops->id, id, sizeof(ops->id));
 	init_MUTEX(&ops->reg_mutex);
 	ops->driver = DRIVER_EMPTY;
 	INIT_LIST_HEAD(&ops->dev_list);
diff -urN linux-2.5.69-bk18/sound/core/seq/seq_instr.c linux-2.5.69-bk19/sound/core/seq/seq_instr.c
--- linux-2.5.69-bk18/sound/core/seq/seq_instr.c	2003-05-04 16:53:13.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/seq/seq_instr.c	2003-05-26 04:41:43.000000000 -0700
@@ -478,8 +478,7 @@
 	}
 	instr->ops = ops;
 	instr->instr = put.id.instr;
-	strncpy(instr->name, put.data.name, sizeof(instr->name)-1);
-	instr->name[sizeof(instr->name)-1] = '\0';
+	strlcpy(instr->name, put.data.name, sizeof(instr->name));
 	instr->type = put.data.type;
 	if (instr->type == SNDRV_SEQ_INSTR_ATYPE_DATA) {
 		result = ops->put(ops->private_data,
diff -urN linux-2.5.69-bk18/sound/core/seq/seq_ports.c linux-2.5.69-bk19/sound/core/seq/seq_ports.c
--- linux-2.5.69-bk18/sound/core/seq/seq_ports.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/seq/seq_ports.c	2003-05-26 04:41:43.000000000 -0700
@@ -338,10 +338,8 @@
 	snd_assert(port && info, return -EINVAL);
 
 	/* set port name */
-	if (info->name[0]) {
-		strncpy(port->name, info->name, sizeof(port->name)-1);
-		port->name[sizeof(port->name)-1] = '\0';
-	}
+	if (info->name[0])
+		strlcpy(port->name, info->name, sizeof(port->name));
 	
 	/* set capabilities */
 	port->capability = info->capability;
@@ -363,7 +361,7 @@
 	snd_assert(port && info, return -EINVAL);
 
 	/* get port name */
-	strncpy(info->name, port->name, sizeof(info->name));
+	strlcpy(info->name, port->name, sizeof(info->name));
 	
 	/* get capabilities */
 	info->capability = port->capability;
@@ -621,10 +619,8 @@
 	/* Set up the port */
 	memset(&portinfo, 0, sizeof(portinfo));
 	portinfo.addr.client = client;
-	if (portname)
-		strncpy(portinfo.name, portname, sizeof(portinfo.name));
-	else
-		sprintf(portinfo.name, "Unamed port");
+	strlcpy(portinfo.name, portname ? portname : "Unamed port",
+		sizeof(portinfo.name));
 
 	portinfo.capability = cap;
 	portinfo.type = type;
diff -urN linux-2.5.69-bk18/sound/core/seq/seq_queue.c linux-2.5.69-bk19/sound/core/seq/seq_queue.c
--- linux-2.5.69-bk18/sound/core/seq/seq_queue.c	2003-05-04 16:53:37.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/seq/seq_queue.c	2003-05-26 04:41:43.000000000 -0700
@@ -241,7 +241,7 @@
 
 	for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
 		if ((q = queueptr(i)) != NULL) {
-			if (strncpy(q->name, name, sizeof(q->name)) == 0)
+			if (strncmp(q->name, name, sizeof(q->name)) == 0)
 				return q;
 			queuefree(q);
 		}
diff -urN linux-2.5.69-bk18/sound/core/sgbuf.c linux-2.5.69-bk19/sound/core/sgbuf.c
--- linux-2.5.69-bk18/sound/core/sgbuf.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/sgbuf.c	2003-05-26 04:41:43.000000000 -0700
@@ -23,6 +23,7 @@
 #include <linux/version.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <sound/memalloc.h>
 
diff -urN linux-2.5.69-bk18/sound/core/timer.c linux-2.5.69-bk19/sound/core/timer.c
--- linux-2.5.69-bk18/sound/core/timer.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/sound/core/timer.c	2003-05-26 04:41:43.000000000 -0700
@@ -749,7 +749,7 @@
 	timer->tmr_device = tid->device;
 	timer->tmr_subdevice = tid->subdevice;
 	if (id)
-		strncpy(timer->id, id, sizeof(timer->id) - 1);
+		strlcpy(timer->id, id, sizeof(timer->id));
 	INIT_LIST_HEAD(&timer->device_list);
 	INIT_LIST_HEAD(&timer->open_list_head);
 	INIT_LIST_HEAD(&timer->active_list_head);
@@ -1317,8 +1317,8 @@
 		ginfo.card = t->card ? t->card->number : -1;
 		if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
 			ginfo.flags |= SNDRV_TIMER_FLG_SLAVE;
-		strncpy(ginfo.id, t->id, sizeof(ginfo.id)-1);
-		strncpy(ginfo.name, t->name, sizeof(ginfo.name)-1);
+		strlcpy(ginfo.id, t->id, sizeof(ginfo.id));
+		strlcpy(ginfo.name, t->name, sizeof(ginfo.name));
 		ginfo.resolution = t->hw.resolution;
 		if (t->hw.resolution_min > 0) {
 			ginfo.resolution_min = t->hw.resolution_min;
@@ -1457,8 +1457,8 @@
 	info.card = t->card ? t->card->number : -1;
 	if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
 		info.flags |= SNDRV_TIMER_FLG_SLAVE;
-	strncpy(info.id, t->id, sizeof(info.id)-1);
-	strncpy(info.name, t->name, sizeof(info.name)-1);
+	strlcpy(info.id, t->id, sizeof(info.id));
+	strlcpy(info.name, t->name, sizeof(info.name));
 	info.resolution = t->hw.resolution;
 	if (copy_to_user(_info, &info, sizeof(*_info)))
 		return -EFAULT;
diff -urN linux-2.5.69-bk18/sound/drivers/opl3/opl3_oss.c linux-2.5.69-bk19/sound/drivers/opl3/opl3_oss.c
--- linux-2.5.69-bk18/sound/drivers/opl3/opl3_oss.c	2003-05-04 16:53:01.000000000 -0700
+++ linux-2.5.69-bk19/sound/drivers/opl3/opl3_oss.c	2003-05-26 04:41:43.000000000 -0700
@@ -123,8 +123,7 @@
 		return;
 
 	opl3->oss_seq_dev = dev;
-	strncpy(dev->name, name, sizeof(dev->name) - 1);
-	dev->name[sizeof(dev->name) - 1] = 0;
+	strlcpy(dev->name, name, sizeof(dev->name));
 	arg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
 	arg->type = SYNTH_TYPE_FM;
 	if (opl3->hardware < OPL3_HW_OPL3) {
diff -urN linux-2.5.69-bk18/sound/i2c/i2c.c linux-2.5.69-bk19/sound/i2c/i2c.c
--- linux-2.5.69-bk18/sound/i2c/i2c.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/sound/i2c/i2c.c	2003-05-26 04:41:43.000000000 -0700
@@ -93,7 +93,7 @@
 		list_add_tail(&bus->buses, &master->buses);
 		bus->master = master;
 	}
-	strncpy(bus->name, name, sizeof(bus->name) - 1);
+	strlcpy(bus->name, name, sizeof(bus->name));
 	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, bus, &ops)) < 0) {
 		snd_i2c_bus_free(bus);
 		return err;
@@ -112,7 +112,7 @@
 	if (device == NULL)
 		return -ENOMEM;
 	device->addr = addr;
-	strncpy(device->name, name, sizeof(device->name)-1);
+	strlcpy(device->name, name, sizeof(device->name));
 	list_add_tail(&device->list, &bus->devices);
 	device->bus = bus;
 	*rdevice = device;
diff -urN linux-2.5.69-bk18/sound/isa/ad1848/ad1848_lib.c linux-2.5.69-bk19/sound/isa/ad1848/ad1848_lib.c
--- linux-2.5.69-bk18/sound/isa/ad1848/ad1848_lib.c	2003-05-04 16:53:42.000000000 -0700
+++ linux-2.5.69-bk19/sound/isa/ad1848/ad1848_lib.c	2003-05-26 04:41:43.000000000 -0700
@@ -1148,7 +1148,7 @@
 	ctl = snd_ctl_new1(&newctls[type], chip);
 	if (! ctl)
 		return -ENOMEM;
-	strncpy(ctl->id.name, name, sizeof(ctl->id.name)-1);
+	strlcpy(ctl->id.name, name, sizeof(ctl->id.name));
 	ctl->id.index = index;
 	ctl->private_value = value;
 	if ((err = snd_ctl_add(chip->card, ctl)) < 0) {
diff -urN linux-2.5.69-bk18/sound/isa/sb/sb16_csp.c linux-2.5.69-bk19/sound/isa/sb/sb16_csp.c
--- linux-2.5.69-bk18/sound/isa/sb/sb16_csp.c	2003-05-04 16:53:55.000000000 -0700
+++ linux-2.5.69-bk19/sound/isa/sb/sb16_csp.c	2003-05-26 04:41:43.000000000 -0700
@@ -393,8 +393,7 @@
 				return err;
 
 			/* fill in codec header */
-			strncpy(p->codec_name, info.codec_name, sizeof(p->codec_name) - 1);
-			p->codec_name[sizeof(p->codec_name) - 1] = 0;
+			strlcpy(p->codec_name, info.codec_name, sizeof(p->codec_name));
 			p->func_nr = func_nr;
 			p->mode = LE_SHORT(funcdesc_h.flags_play_rec);
 			switch (LE_SHORT(funcdesc_h.VOC_type)) {
diff -urN linux-2.5.69-bk18/sound/isa/sb/sb_mixer.c linux-2.5.69-bk19/sound/isa/sb/sb_mixer.c
--- linux-2.5.69-bk18/sound/isa/sb/sb_mixer.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/sound/isa/sb/sb_mixer.c	2003-05-26 04:41:43.000000000 -0700
@@ -452,7 +452,7 @@
 	ctl = snd_ctl_new1(&newctls[type], chip);
 	if (! ctl)
 		return -ENOMEM;
-	strncpy(ctl->id.name, name, sizeof(ctl->id.name)-1);
+	strlcpy(ctl->id.name, name, sizeof(ctl->id.name));
 	ctl->id.index = index;
 	ctl->private_value = value;
 	if ((err = snd_ctl_add(chip->card, ctl)) < 0) {
diff -urN linux-2.5.69-bk18/sound/oss/ac97_codec.c linux-2.5.69-bk19/sound/oss/ac97_codec.c
--- linux-2.5.69-bk18/sound/oss/ac97_codec.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/ac97_codec.c	2003-05-26 04:41:43.000000000 -0700
@@ -487,8 +487,8 @@
 
 	if (cmd == SOUND_MIXER_INFO) {
 		mixer_info info;
-		strncpy(info.id, codec->name, sizeof(info.id));
-		strncpy(info.name, codec->name, sizeof(info.name));
+		strlcpy(info.id, codec->name, sizeof(info.id));
+		strlcpy(info.name, codec->name, sizeof(info.name));
 		info.modify_counter = codec->modcnt;
 		if (copy_to_user((void *)arg, &info, sizeof(info)))
 			return -EFAULT;
@@ -496,8 +496,8 @@
 	}
 	if (cmd == SOUND_OLD_MIXER_INFO) {
 		_old_mixer_info info;
-		strncpy(info.id, codec->name, sizeof(info.id));
-		strncpy(info.name, codec->name, sizeof(info.name));
+		strlcpy(info.id, codec->name, sizeof(info.id));
+		strlcpy(info.name, codec->name, sizeof(info.name));
 		if (copy_to_user((void *)arg, &info, sizeof(info)))
 			return -EFAULT;
 		return 0;
diff -urN linux-2.5.69-bk18/sound/oss/btaudio.c linux-2.5.69-bk19/sound/oss/btaudio.c
--- linux-2.5.69-bk18/sound/oss/btaudio.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/btaudio.c	2003-05-26 04:41:43.000000000 -0700
@@ -328,8 +328,8 @@
 	if (cmd == SOUND_MIXER_INFO) {
 		mixer_info info;
 		memset(&info,0,sizeof(info));
-                strncpy(info.id,"bt878",sizeof(info.id)-1);
-                strncpy(info.name,"Brooktree Bt878 audio",sizeof(info.name)-1);
+                strlcpy(info.id,"bt878",sizeof(info.id));
+                strlcpy(info.name,"Brooktree Bt878 audio",sizeof(info.name));
                 info.modify_counter = bta->mixcount;
                 if (copy_to_user((void *)arg, &info, sizeof(info)))
                         return -EFAULT;
@@ -338,8 +338,8 @@
 	if (cmd == SOUND_OLD_MIXER_INFO) {
 		_old_mixer_info info;
 		memset(&info,0,sizeof(info));
-                strncpy(info.id,"bt878",sizeof(info.id)-1);
-                strncpy(info.name,"Brooktree Bt878 audio",sizeof(info.name)-1);
+                strlcpy(info.id,"bt878",sizeof(info.id)-1);
+                strlcpy(info.name,"Brooktree Bt878 audio",sizeof(info.name));
                 if (copy_to_user((void *)arg, &info, sizeof(info)))
                         return -EFAULT;
 		return 0;
diff -urN linux-2.5.69-bk18/sound/oss/cmpci.c linux-2.5.69-bk19/sound/oss/cmpci.c
--- linux-2.5.69-bk18/sound/oss/cmpci.c	2003-05-04 16:53:31.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/cmpci.c	2003-05-26 04:41:43.000000000 -0700
@@ -1268,8 +1268,8 @@
 	VALIDATE_STATE(s);
         if (cmd == SOUND_MIXER_INFO) {
 		mixer_info info;
-		strncpy(info.id, "cmpci", sizeof(info.id));
-		strncpy(info.name, "C-Media PCI", sizeof(info.name));
+		strlcpy(info.id, "cmpci", sizeof(info.id));
+		strlcpy(info.name, "C-Media PCI", sizeof(info.name));
 		info.modify_counter = s->mix.modcnt;
 		if (copy_to_user((void *)arg, &info, sizeof(info)))
 			return -EFAULT;
@@ -1277,8 +1277,8 @@
 	}
 	if (cmd == SOUND_OLD_MIXER_INFO) {
 		_old_mixer_info info;
-		strncpy(info.id, "cmpci", sizeof(info.id));
-		strncpy(info.name, "C-Media cmpci", sizeof(info.name));
+		strlcpy(info.id, "cmpci", sizeof(info.id));
+		strlcpy(info.name, "C-Media cmpci", sizeof(info.name));
 		if (copy_to_user((void *)arg, &info, sizeof(info)))
 			return -EFAULT;
 		return 0;
diff -urN linux-2.5.69-bk18/sound/oss/cs4281/cs4281m.c linux-2.5.69-bk19/sound/oss/cs4281/cs4281m.c
--- linux-2.5.69-bk18/sound/oss/cs4281/cs4281m.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/cs4281/cs4281m.c	2003-05-26 04:41:43.000000000 -0700
@@ -2266,8 +2266,8 @@
 	}
 	if (cmd == SOUND_MIXER_INFO) {
 		mixer_info info;
-		strncpy(info.id, "CS4281", sizeof(info.id));
-		strncpy(info.name, "Crystal CS4281", sizeof(info.name));
+		strlcpy(info.id, "CS4281", sizeof(info.id));
+		strlcpy(info.name, "Crystal CS4281", sizeof(info.name));
 		info.modify_counter = s->mix.modcnt;
 		if (copy_to_user((void *) arg, &info, sizeof(info)))
 			return -EFAULT;
@@ -2275,8 +2275,8 @@
 	}
 	if (cmd == SOUND_OLD_MIXER_INFO) {
 		_old_mixer_info info;
-		strncpy(info.id, "CS4281", sizeof(info.id));
-		strncpy(info.name, "Crystal CS4281", sizeof(info.name));
+		strlcpy(info.id, "CS4281", sizeof(info.id));
+		strlcpy(info.name, "Crystal CS4281", sizeof(info.name));
 		if (copy_to_user((void *) arg, &info, sizeof(info)))
 			return -EFAULT;
 		return 0;
diff -urN linux-2.5.69-bk18/sound/oss/cs46xx.c linux-2.5.69-bk19/sound/oss/cs46xx.c
--- linux-2.5.69-bk18/sound/oss/cs46xx.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/cs46xx.c	2003-05-26 04:41:43.000000000 -0700
@@ -944,10 +944,10 @@
 
 }
 
-struct InitStruct
+static struct InitStruct
 {
-    u32 long off;
-    u32 long val;
+    u32 off;
+    u32 val;
 } InitArray[] = { {0x00000040, 0x3fc0000f},
                   {0x0000004c, 0x04800000},
 
diff -urN linux-2.5.69-bk18/sound/oss/dev_table.c linux-2.5.69-bk19/sound/oss/dev_table.c
--- linux-2.5.69-bk18/sound/oss/dev_table.c	2003-05-04 16:53:40.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/dev_table.c	2003-05-26 04:41:43.000000000 -0700
@@ -22,7 +22,7 @@
 {
 	struct audio_driver *d;
 	struct audio_operations *op;
-	int l, num;
+	int num;
 
 	if (vers != AUDIO_DRIVER_VERSION || driver_size > sizeof(struct audio_driver)) {
 		printk(KERN_ERR "Sound: Incompatible audio driver for %s\n", name);
@@ -58,11 +58,7 @@
 	memcpy((char *) d, (char *) driver, driver_size);
 
 	op->d = d;
-	l = strlen(name) + 1;
-	if (l > sizeof(op->name))
-		l = sizeof(op->name);
-	strncpy(op->name, name, l);
-	op->name[l - 1] = 0;
+	strlcpy(op->name, name, sizeof(op->name));
 	op->flags = flags;
 	op->format_mask = format_mask;
 	op->devc = devc;
@@ -82,7 +78,6 @@
 	int driver_size, void *devc)
 {
 	struct mixer_operations *op;
-	int l;
 
 	int n = sound_alloc_mixerdev();
 
@@ -110,11 +105,7 @@
 	memset((char *) op, 0, sizeof(struct mixer_operations));
 	memcpy((char *) op, (char *) driver, driver_size);
 
-	l = strlen(name) + 1;
-	if (l > sizeof(op->name))
-		l = sizeof(op->name);
-	strncpy(op->name, name, l);
-	op->name[l - 1] = 0;
+	strlcpy(op->name, name, sizeof(op->name));
 	op->devc = devc;
 
 	mixer_devs[n] = op;
diff -urN linux-2.5.69-bk18/sound/oss/dmasound/dmasound.h linux-2.5.69-bk19/sound/oss/dmasound/dmasound.h
--- linux-2.5.69-bk18/sound/oss/dmasound/dmasound.h	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/dmasound/dmasound.h	2003-05-26 04:41:43.000000000 -0700
@@ -1,4 +1,4 @@
-
+#ifndef _dmasound_h_
 /*
  *  linux/drivers/sound/dmasound/dmasound.h
  *
@@ -10,11 +10,11 @@
  *  device for true DSP processors but it will be called something else.
  *  In v3.0 it's /dev/sndproc but this could be a temporary solution.
  */
+#define _dmasound_h_
 
-
+#include <linux/types.h>
 #include <linux/config.h>
 
-
 #define SND_NDEVS	256	/* Number of supported devices */
 #define SND_DEV_CTL	0	/* Control port /dev/mixer */
 #define SND_DEV_SEQ	1	/* Sequencer output /dev/sequencer (FM
@@ -29,23 +29,16 @@
 #define SND_DEV_SNDPROC 9	/* /dev/sndproc for programmable devices */
 #define SND_DEV_PSS	SND_DEV_SNDPROC
 
-#define DSP_DEFAULT_SPEED	8000
-
-#define ON		1
-#define OFF		0
+/* switch on various prinks */
+#define DEBUG_DMASOUND 1
 
 #define MAX_AUDIO_DEV	5
-#define MAX_MIXER_DEV	2
+#define MAX_MIXER_DEV	4
 #define MAX_SYNTH_DEV	3
 #define MAX_MIDI_DEV	6
 #define MAX_TIMER_DEV	3
 
-
 #define MAX_CATCH_RADIUS	10
-#define MIN_BUFFERS		4
-#define MIN_BUFSIZE		4	/* in KB */
-#define MAX_BUFSIZE		128	/* Limit for Amiga in KB */
-
 
 #define le2be16(x)	(((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff))
 #define le2be16dbl(x)	(((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff))
@@ -67,21 +60,34 @@
      */
 
 #undef HAS_8BIT_TABLES
-#undef HAS_14BIT_TABLES
-#undef HAS_16BIT_TABLES
 #undef HAS_RECORD
 
 #if defined(CONFIG_DMASOUND_ATARI) || defined(CONFIG_DMASOUND_ATARI_MODULE) ||\
     defined(CONFIG_DMASOUND_PAULA) || defined(CONFIG_DMASOUND_PAULA_MODULE) ||\
     defined(CONFIG_DMASOUND_Q40) || defined(CONFIG_DMASOUND_Q40_MODULE)
 #define HAS_8BIT_TABLES
+#define MIN_BUFFERS	4
+#define MIN_BUFSIZE	(1<<12)	/* in bytes (- where does this come from ?) */
+#define MIN_FRAG_SIZE	8	/* not 100% sure about this */
+#define MAX_BUFSIZE	(1<<17)	/* Limit for Amiga is 128 kb */
+#define MAX_FRAG_SIZE	15	/* allow *4 for mono-8 => stereo-16 (for multi) */
+
+#else /* is pmac and multi is off */
+
+#define MIN_BUFFERS	2
+#define MIN_BUFSIZE	(1<<8)	/* in bytes */
+#define MIN_FRAG_SIZE	8
+#define MAX_BUFSIZE	(1<<18)	/* this is somewhat arbitrary for pmac */
+#define MAX_FRAG_SIZE	16	/* need to allow *4 for mono-8 => stereo-16 */
 #endif
-#if defined(CONFIG_DMASOUND_AWACS) || defined(CONFIG_DMASOUND_AWACS_MODULE)
-#define HAS_16BIT_TABLES
+
+#define DEFAULT_N_BUFFERS 4
+#define DEFAULT_BUFF_SIZE (1<<15)
+
+#if defined(CONFIG_DMASOUND_PMAC) || defined(CONFIG_DMASOUND_PMAC_MODULE)
 #define HAS_RECORD
 #endif
 
-
     /*
      *  Initialization
      */
@@ -93,6 +99,14 @@
 #define dmasound_deinit()	do { } while (0)
 #endif
 
+/* description of the set-up applies to either hard or soft settings */
+
+typedef struct {
+    int format;		/* AFMT_* */
+    int stereo;		/* 0 = mono, 1 = stereo */
+    int size;		/* 8/16 bit*/
+    int speed;		/* speed */
+} SETTINGS;
 
     /*
      *  Machine definitions
@@ -117,30 +131,29 @@
     int (*setTreble)(int);
     int (*setGain)(int);
     void (*play)(void);
-    void (*record)(void);			/* optional */
-    void (*mixer_init)(void);			/* optional */
-    int (*mixer_ioctl)(u_int, u_long);		/* optional */
-    void (*write_sq_setup)(void);		/* optional */
-    void (*read_sq_setup)(void);		/* optional */
-    void (*sq_open)(void);			/* optional */
-    int (*state_info)(char *);			/* optional */
-    void (*abort_read)(void);			/* optional */
+    void (*record)(void);		/* optional */
+    void (*mixer_init)(void);		/* optional */
+    int (*mixer_ioctl)(u_int, u_long);	/* optional */
+    int (*write_sq_setup)(void);	/* optional */
+    int (*read_sq_setup)(void);		/* optional */
+    int (*sq_open)(mode_t);		/* optional */
+    int (*state_info)(char *, size_t);	/* optional */
+    void (*abort_read)(void);		/* optional */
     int min_dsp_speed;
+    int max_dsp_speed;
+    int version ;
+    int hardware_afmts ;		/* OSS says we only return h'ware info */
+					/* when queried via SNDCTL_DSP_GETFMTS */
+    int capabilities ;		/* low-level reply to SNDCTL_DSP_GETCAPS */
+    SETTINGS default_hard ;	/* open() or init() should set something valid */
+    SETTINGS default_soft ;	/* you can make it look like old OSS, if you want to */
 } MACHINE;
 
-
     /*
      *  Low level stuff
      */
 
 typedef struct {
-    int format;		/* AFMT_* */
-    int stereo;		/* 0 = mono, 1 = stereo */
-    int size;		/* 8/16 bit*/
-    int speed;		/* speed */
-} SETTINGS;
-
-typedef struct {
     ssize_t (*ct_ulaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
     ssize_t (*ct_alaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
     ssize_t (*ct_s8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t);
@@ -171,11 +184,10 @@
 
 extern struct sound_settings dmasound;
 
+#ifdef HAS_8BIT_TABLES
 extern char dmasound_ulaw2dma8[];
 extern char dmasound_alaw2dma8[];
-extern short dmasound_ulaw2dma16[];
-extern short dmasound_alaw2dma16[];
-
+#endif
 
     /*
      *  Mid level stuff
@@ -208,14 +220,17 @@
 
 struct sound_queue {
     /* buffers allocated for this queue */
-    int numBufs;
-    int bufSize;			/* in bytes */
+    int numBufs;		/* real limits on what the user can have */
+    int bufSize;		/* in bytes */
     char **buffers;
 
     /* current parameters */
-    int max_count;
-    int block_size;			/* in bytes */
-    int max_active;
+    int locked ;		/* params cannot be modified when != 0 */
+    int user_frags ;		/* user requests this many */
+    int user_frag_size ;	/* of this size */
+    int max_count;		/* actual # fragments <= numBufs */
+    int block_size;		/* internal block size in bytes */
+    int max_active;		/* in-use fragments <= max_count */
 
     /* it shouldn't be necessary to declare any of these volatile */
     int front, rear, count;
@@ -231,19 +246,32 @@
     int active;
     wait_queue_head_t action_queue, open_queue, sync_queue;
     int open_mode;
-    int busy, syncing;
+    int busy, syncing, xruns, died;
 };
 
 #define SLEEP(queue)		interruptible_sleep_on_timeout(&queue, HZ)
 #define WAKE_UP(queue)		(wake_up_interruptible(&queue))
 
 extern struct sound_queue dmasound_write_sq;
-extern struct sound_queue dmasound_read_sq;
-
 #define write_sq	dmasound_write_sq
+
+#ifdef HAS_RECORD
+extern struct sound_queue dmasound_read_sq;
 #define read_sq		dmasound_read_sq
+#endif
 
 extern int dmasound_catchRadius;
-
 #define catchRadius	dmasound_catchRadius
 
+/* define the value to be put in the byte-swap reg in mac-io
+   when we want it to swap for us.
+*/
+#define BS_VAL 1
+
+static inline void wait_ms(unsigned int ms)
+{
+	current->state = TASK_UNINTERRUPTIBLE;
+	schedule_timeout(1 + ms * HZ / 1000);
+}
+
+#endif /* _dmasound_h_ */
diff -urN linux-2.5.69-bk18/sound/oss/dmasound/dmasound_atari.c linux-2.5.69-bk19/sound/oss/dmasound/dmasound_atari.c
--- linux-2.5.69-bk18/sound/oss/dmasound/dmasound_atari.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/dmasound/dmasound_atari.c	2003-05-26 04:41:43.000000000 -0700
@@ -20,6 +20,8 @@
 #include <linux/soundcard.h>
 #include <linux/mm.h>
 #include <linux/spinlock.h>
+#include <linux/interrupt.h>
+
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
 #include <asm/atariints.h>
diff -urN linux-2.5.69-bk18/sound/oss/dmasound/dmasound_core.c linux-2.5.69-bk19/sound/oss/dmasound/dmasound_core.c
--- linux-2.5.69-bk18/sound/oss/dmasound/dmasound_core.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/dmasound/dmasound_core.c	2003-05-26 04:41:43.000000000 -0700
@@ -351,9 +351,8 @@
 	    case SOUND_MIXER_INFO:
 		{
 		    mixer_info info;
-		    strncpy(info.id, dmasound.mach.name2, sizeof(info.id));
-		    strncpy(info.name, dmasound.mach.name2, sizeof(info.name));
-		    info.name[sizeof(info.name)-1] = 0;
+		    strlcpy(info.id, dmasound.mach.name2, sizeof(info.id));
+		    strlcpy(info.name, dmasound.mach.name2, sizeof(info.name));
 		    info.modify_counter = mixer.modify_counter;
 		    if (copy_to_user((int *)arg, &info, sizeof(info)))
 			    return -EFAULT;
@@ -904,7 +903,7 @@
 	  O_RDONLY and dsp1 could be opened O_WRONLY
 	*/
 
-	dmasound.minDev = MINOR(inode->i_rdev) & 0x0f;
+	dmasound.minDev = minor(inode->i_rdev) & 0x0f;
 
 	/* OK. - we should make some attempt at consistency. At least the H'ware
 	   options should be set with a valid mode.  We will make it that the LL
diff -urN linux-2.5.69-bk18/sound/oss/dmasound/dmasound_paula.c linux-2.5.69-bk19/sound/oss/dmasound/dmasound_paula.c
--- linux-2.5.69-bk18/sound/oss/dmasound/dmasound_paula.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/dmasound/dmasound_paula.c	2003-05-26 04:41:43.000000000 -0700
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/soundcard.h>
+#include <linux/interrupt.h>
 
 #include <asm/uaccess.h>
 #include <asm/setup.h>
diff -urN linux-2.5.69-bk18/sound/oss/dmasound/dmasound_q40.c linux-2.5.69-bk19/sound/oss/dmasound/dmasound_q40.c
--- linux-2.5.69-bk18/sound/oss/dmasound/dmasound_q40.c	2003-05-04 16:52:48.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/dmasound/dmasound_q40.c	2003-05-26 04:41:43.000000000 -0700
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/soundcard.h>
+#include <linux/interrupt.h>
 
 #include <asm/uaccess.h>
 #include <asm/q40ints.h>
@@ -461,7 +462,7 @@
 	}
 	spin_lock_irqsave(&dmasound.lock, flags);
 	Q40PlayNextFrame(1);
-	spin_unlock_irqrestore_flags(&dmasound.lock, flags);
+	spin_unlock_irqrestore(&dmasound.lock, flags);
 }
 
 static irqreturn_t Q40StereoInterrupt(int irq, void *dummy, struct pt_regs *fp)
diff -urN linux-2.5.69-bk18/sound/oss/emu10k1/mixer.c linux-2.5.69-bk19/sound/oss/emu10k1/mixer.c
--- linux-2.5.69-bk18/sound/oss/emu10k1/mixer.c	2003-05-04 16:53:35.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/emu10k1/mixer.c	2003-05-26 04:41:43.000000000 -0700
@@ -623,8 +623,8 @@
 		if (cmd == SOUND_MIXER_INFO) {
 			mixer_info info;
 
-			strncpy(info.id, card->ac97.name, sizeof(info.id));
-			strncpy(info.name, "Creative SBLive - Emu10k1", sizeof(info.name));
+			strlcpy(info.id, card->ac97.name, sizeof(info.id));
+			strlcpy(info.name, "Creative SBLive - Emu10k1", sizeof(info.name));
 			info.modify_counter = card->ac97.modcnt;
 
 			if (copy_to_user((void *)arg, &info, sizeof(info)))
diff -urN linux-2.5.69-bk18/sound/oss/es1370.c linux-2.5.69-bk19/sound/oss/es1370.c
--- linux-2.5.69-bk18/sound/oss/es1370.c	2003-05-04 16:53:57.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/es1370.c	2003-05-26 04:41:43.000000000 -0700
@@ -889,8 +889,8 @@
 	}
         if (cmd == SOUND_MIXER_INFO) {
 		mixer_info info;
-		strncpy(info.id, "ES1370", sizeof(info.id));
-		strncpy(info.name, "Ensoniq ES1370", sizeof(info.name));
+		strlcpy(info.id, "ES1370", sizeof(info.id));
+		strlcpy(info.name, "Ensoniq ES1370", sizeof(info.name));
 		info.modify_counter = s->mix.modcnt;
 		if (copy_to_user((void *)arg, &info, sizeof(info)))
 			return -EFAULT;
@@ -898,8 +898,8 @@
 	}
 	if (cmd == SOUND_OLD_MIXER_INFO) {
 		_old_mixer_info info;
-		strncpy(info.id, "ES1370", sizeof(info.id));
-		strncpy(info.name, "Ensoniq ES1370", sizeof(info.name));
+		strlcpy(info.id, "ES1370", sizeof(info.id));
+		strlcpy(info.name, "Ensoniq ES1370", sizeof(info.name));
 		if (copy_to_user((void *)arg, &info, sizeof(info)))
 			return -EFAULT;
 		return 0;
diff -urN linux-2.5.69-bk18/sound/oss/esssolo1.c linux-2.5.69-bk19/sound/oss/esssolo1.c
--- linux-2.5.69-bk18/sound/oss/esssolo1.c	2003-05-04 16:53:02.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/esssolo1.c	2003-05-26 04:41:43.000000000 -0700
@@ -721,8 +721,8 @@
 	}
         if (cmd == SOUND_MIXER_INFO) {
 		mixer_info info;
-		strncpy(info.id, "Solo1", sizeof(info.id));
-		strncpy(info.name, "ESS Solo1", sizeof(info.name));
+		strlcpy(info.id, "Solo1", sizeof(info.id));
+		strlcpy(info.name, "ESS Solo1", sizeof(info.name));
 		info.modify_counter = s->mix.modcnt;
 		if (copy_to_user((void *)arg, &info, sizeof(info)))
 			return -EFAULT;
@@ -730,8 +730,8 @@
 	}
 	if (cmd == SOUND_OLD_MIXER_INFO) {
 		_old_mixer_info info;
-		strncpy(info.id, "Solo1", sizeof(info.id));
-		strncpy(info.name, "ESS Solo1", sizeof(info.name));
+		strlcpy(info.id, "Solo1", sizeof(info.id));
+		strlcpy(info.name, "ESS Solo1", sizeof(info.name));
 		if (copy_to_user((void *)arg, &info, sizeof(info)))
 			return -EFAULT;
 		return 0;
diff -urN linux-2.5.69-bk18/sound/oss/gus_wave.c linux-2.5.69-bk19/sound/oss/gus_wave.c
--- linux-2.5.69-bk18/sound/oss/gus_wave.c	2003-05-04 16:53:08.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/gus_wave.c	2003-05-26 04:41:43.000000000 -0700
@@ -2851,7 +2851,7 @@
 	unsigned long flags;
 	unsigned char val;
 	char *model_num = "2.4";
-	char tmp[64], tmp2[64];
+	char tmp[64];
 	int gus_type = 0x24;	/* 2.4 */
 
 	int irq = hw_config->irq, dma = hw_config->dma, dma2 = hw_config->dma2;
@@ -2998,19 +2998,14 @@
 	}
 
 	if (hw_config->name)
-	{
-		strncpy(tmp, hw_config->name, 45);
-		tmp[45] = 0;
-		sprintf(tmp2, "%s (%dk)", tmp, (int) gus_mem_size / 1024);
-		tmp2[sizeof(tmp2) - 1] = 0;
-	}
+		snprintf(tmp, sizeof(tmp), "%s (%dk)", hw_config->name,
+			 (int) gus_mem_size / 1024);
 	else if (gus_pnp_flag)
-	{
-		sprintf(tmp2, "Gravis UltraSound PnP (%dk)",
-			(int) gus_mem_size / 1024);
-	}
+		snprintf(tmp, sizeof(tmp), "Gravis UltraSound PnP (%dk)",
+			 (int) gus_mem_size / 1024);
 	else
-		sprintf(tmp2, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
+		snprintf(tmp, sizeof(tmp), "Gravis UltraSound %s (%dk)", model_num,
+			 (int) gus_mem_size / 1024);
 
 
 	samples = (struct patch_info *)vmalloc((MAX_SAMPLE + 1) * sizeof(*samples));
@@ -3019,9 +3014,8 @@
 		printk(KERN_WARNING "gus_init: Cant allocate memory for instrument tables\n");
 		return;
 	}
-	conf_printf(tmp2, hw_config);
-	tmp2[sizeof(gus_info.name) - 1] = 0;
-	strcpy(gus_info.name, tmp2);
+	conf_printf(tmp, hw_config);
+	strlcpy(gus_info.name, tmp, sizeof(gus_info.name));
 
 	if ((sdev = sound_alloc_synthdev()) == -1)
 		printk(KERN_WARNING "gus_init: Too many synthesizers\n");
diff -urN linux-2.5.69-bk18/sound/oss/maestro.c linux-2.5.69-bk19/sound/oss/maestro.c
--- linux-2.5.69-bk18/sound/oss/maestro.c	2003-05-04 16:53:41.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/maestro.c	2003-05-26 04:41:43.000000000 -0700
@@ -2024,8 +2024,8 @@
 	VALIDATE_CARD(card);
         if (cmd == SOUND_MIXER_INFO) {
 		mixer_info info;
-		strncpy(info.id, card_names[card->card_type], sizeof(info.id));
-		strncpy(info.name,card_names[card->card_type],sizeof(info.name));
+		strlcpy(info.id, card_names[card->card_type], sizeof(info.id));
+		strlcpy(info.name, card_names[card->card_type], sizeof(info.name));
 		info.modify_counter = card->mix.modcnt;
 		if (copy_to_user((void *)arg, &info, sizeof(info)))
 			return -EFAULT;
@@ -2033,8 +2033,8 @@
 	}
 	if (cmd == SOUND_OLD_MIXER_INFO) {
 		_old_mixer_info info;
-		strncpy(info.id, card_names[card->card_type], sizeof(info.id));
-		strncpy(info.name,card_names[card->card_type],sizeof(info.name));
+		strlcpy(info.id, card_names[card->card_type], sizeof(info.id));
+		strlcpy(info.name, card_names[card->card_type], sizeof(info.name));
 		if (copy_to_user((void *)arg, &info, sizeof(info)))
 			return -EFAULT;
 		return 0;
diff -urN linux-2.5.69-bk18/sound/oss/msnd_pinnacle.c linux-2.5.69-bk19/sound/oss/msnd_pinnacle.c
--- linux-2.5.69-bk18/sound/oss/msnd_pinnacle.c	2003-05-04 16:53:32.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/msnd_pinnacle.c	2003-05-26 04:41:43.000000000 -0700
@@ -555,8 +555,8 @@
 }
 
 #define set_mixer_info()							\
-		strncpy(info.id, "MSNDMIXER", sizeof(info.id));			\
-		strncpy(info.name, "MultiSound Mixer", sizeof(info.name));
+		strlcpy(info.id, "MSNDMIXER", sizeof(info.id));			\
+		strlcpy(info.name, "MultiSound Mixer", sizeof(info.name));
 
 static int mixer_ioctl(unsigned int cmd, unsigned long arg)
 {
diff -urN linux-2.5.69-bk18/sound/oss/sequencer.c linux-2.5.69-bk19/sound/oss/sequencer.c
--- linux-2.5.69-bk18/sound/oss/sequencer.c	2003-05-04 16:53:28.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/sequencer.c	2003-05-26 04:41:43.000000000 -0700
@@ -1477,7 +1477,7 @@
 			if (!(synth_open_mask & (1 << dev)) && !orig_dev)
 				return -EBUSY;
 			memcpy(&inf, synth_devs[dev]->info, sizeof(inf));
-			strncpy(inf.name, synth_devs[dev]->id, sizeof(inf.name));
+			strlcpy(inf.name, synth_devs[dev]->id, sizeof(inf.name));
 			inf.device = dev;
 			return copy_to_user(arg, &inf, sizeof(inf))?-EFAULT:0;
 
diff -urN linux-2.5.69-bk18/sound/oss/sonicvibes.c linux-2.5.69-bk19/sound/oss/sonicvibes.c
--- linux-2.5.69-bk18/sound/oss/sonicvibes.c	2003-05-04 16:53:14.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/sonicvibes.c	2003-05-26 04:41:43.000000000 -0700
@@ -1046,8 +1046,8 @@
 	VALIDATE_STATE(s);
         if (cmd == SOUND_MIXER_INFO) {
 		mixer_info info;
-		strncpy(info.id, "SonicVibes", sizeof(info.id));
-		strncpy(info.name, "S3 SonicVibes", sizeof(info.name));
+		strlcpy(info.id, "SonicVibes", sizeof(info.id));
+		strlcpy(info.name, "S3 SonicVibes", sizeof(info.name));
 		info.modify_counter = s->mix.modcnt;
 		if (copy_to_user((void *)arg, &info, sizeof(info)))
 			return -EFAULT;
@@ -1055,8 +1055,8 @@
 	}
 	if (cmd == SOUND_OLD_MIXER_INFO) {
 		_old_mixer_info info;
-		strncpy(info.id, "SonicVibes", sizeof(info.id));
-		strncpy(info.name, "S3 SonicVibes", sizeof(info.name));
+		strlcpy(info.id, "SonicVibes", sizeof(info.id));
+		strlcpy(info.name, "S3 SonicVibes", sizeof(info.name));
 		if (copy_to_user((void *)arg, &info, sizeof(info)))
 			return -EFAULT;
 		return 0;
diff -urN linux-2.5.69-bk18/sound/oss/soundcard.c linux-2.5.69-bk19/sound/oss/soundcard.c
--- linux-2.5.69-bk18/sound/oss/soundcard.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/sound/oss/soundcard.c	2003-05-26 04:41:43.000000000 -0700
@@ -289,9 +289,8 @@
 {
 	mixer_info info;
 
-	strncpy(info.id, mixer_devs[dev]->id, sizeof(info.id));
-	strncpy(info.name, mixer_devs[dev]->name, sizeof(info.name));
-	info.name[sizeof(info.name)-1] = 0;
+	strlcpy(info.id, mixer_devs[dev]->id, sizeof(info.id));
+	strlcpy(info.name, mixer_devs[dev]->name, sizeof(info.name));
 	info.modify_counter = mixer_devs[dev]->modify_counter;
 	if (__copy_to_user(arg, &info,  sizeof(info)))
 		return -EFAULT;
@@ -302,9 +301,8 @@
 {
 	_old_mixer_info info;
 
- 	strncpy(info.id, mixer_devs[dev]->id, sizeof(info.id));
- 	strncpy(info.name, mixer_devs[dev]->name, sizeof(info.name));
- 	info.name[sizeof(info.name)-1] = 0;	
+ 	strlcpy(info.id, mixer_devs[dev]->id, sizeof(info.id));
+ 	strlcpy(info.name, mixer_devs[dev]->name, sizeof(info.name));
  	if (copy_to_user(arg, &info,  sizeof(info)))
 		return -EFAULT;
 	return 0;
diff -urN linux-2.5.69-bk18/sound/pci/emu10k1/emufx.c linux-2.5.69-bk19/sound/pci/emu10k1/emufx.c
--- linux-2.5.69-bk18/sound/pci/emu10k1/emufx.c	2003-05-26 04:41:38.000000000 -0700
+++ linux-2.5.69-bk19/sound/pci/emu10k1/emufx.c	2003-05-26 04:41:43.000000000 -0700
@@ -1033,7 +1033,7 @@
 			memset(&gctl, 0, sizeof(gctl));
 			id = &ctl->kcontrol->id;
 			gctl.id.iface = id->iface;
-			strncpy(gctl.id.name, id->name, sizeof(gctl.id.name));
+			strlcpy(gctl.id.name, id->name, sizeof(gctl.id.name));
 			gctl.id.index = id->index;
 			gctl.id.device = id->device;
 			gctl.id.subdevice = id->subdevice;
@@ -1063,8 +1063,7 @@
 	down(&emu->fx8010.lock);
 	if ((err = snd_emu10k1_verify_controls(emu, icode)) < 0)
 		goto __error;
-	strncpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name)-1);
-	emu->fx8010.name[sizeof(emu->fx8010.name)-1] = '\0';
+	strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name));
 	/* stop FX processor - this may be dangerous, but it's better to miss
 	   some samples than generate wrong ones - [jk] */
 	if (emu->audigy)
@@ -1092,8 +1091,7 @@
 	int err;
 
 	down(&emu->fx8010.lock);
-	strncpy(icode->name, emu->fx8010.name, sizeof(icode->name)-1);
-	emu->fx8010.name[sizeof(emu->fx8010.name)-1] = '\0';
+	strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name));
 	/* ok, do the main job */
 	snd_emu10k1_gpr_peek(emu, icode);
 	snd_emu10k1_tram_peek(emu, icode);
diff -urN linux-2.5.69-bk18/sound/usb/usbaudio.c linux-2.5.69-bk19/sound/usb/usbaudio.c
--- linux-2.5.69-bk18/sound/usb/usbaudio.c	2003-05-04 16:53:36.000000000 -0700
+++ linux-2.5.69-bk19/sound/usb/usbaudio.c	2003-05-26 04:41:43.000000000 -0700
@@ -2392,8 +2392,7 @@
 		len = 0;
 	if (len <= 0) {
  		if (quirk && quirk->product_name) {
-			strncpy(card->shortname, quirk->product_name, sizeof(card->shortname) - 1);
-			card->shortname[sizeof(card->shortname) - 1] = '\0';
+			strlcpy(card->shortname, quirk->product_name, sizeof(card->shortname));
 		} else {
 			sprintf(card->shortname, "USB Device %#04x:%#04x",
 				dev->descriptor.idVendor, dev->descriptor.idProduct);
@@ -2403,37 +2402,32 @@
 	/* retrieve the vendor and device strings as longname */
 	if (dev->descriptor.iManufacturer)
 		len = usb_string(dev, dev->descriptor.iManufacturer,
-				 card->longname, sizeof(card->longname) - 1);
+				 card->longname, sizeof(card->longname));
 	else
 		len = 0;
 	if (len <= 0) {
 		if (quirk && quirk->vendor_name) {
-			strncpy(card->longname, quirk->vendor_name, sizeof(card->longname) - 2);
-			card->longname[sizeof(card->longname) - 2] = '\0';
-			len = strlen(card->longname);
+			len = strlcpy(card->longname, quirk->vendor_name, sizeof(card->longname));
 		} else {
 			len = 0;
 		}
 	}
-	if (len > 0) {
-		card->longname[len] = ' ';
-		len++;
-	}
-	card->longname[len] = '\0';
+	if (len > 0)
+		strlcat(card->longname, ' ', sizeof(card->longname));
+
+	len = strlen(card->longname);
+
 	if ((!dev->descriptor.iProduct
 	     || usb_string(dev, dev->descriptor.iProduct,
 			   card->longname + len, sizeof(card->longname) - len) <= 0)
 	    && quirk && quirk->product_name) {
-		strncpy(card->longname + len, quirk->product_name, sizeof(card->longname) - len - 1);
-		card->longname[sizeof(card->longname) - 1] = '\0';
+		strlcat(card->longname, quirk->product_name, sizeof(card->longname));
 	}
-	/* add device path to longname */
-	len = strlen(card->longname);
-	if (sizeof(card->longname) - len > 10) {
-		strcpy(card->longname + len, " at ");
-		len += 4;
+
+	len = strlcat(card->longname, " at ", sizeof(card->longname));
+
+	if (len < sizeof(card->longname))
 		usb_make_path(dev, card->longname + len, sizeof(card->longname) - len);
-	}
 
 	*rchip = chip;
 	return 0;
diff -urN linux-2.5.69-bk18/sound/usb/usbmixer.c linux-2.5.69-bk19/sound/usb/usbmixer.c
--- linux-2.5.69-bk18/sound/usb/usbmixer.c	2003-05-04 16:53:09.000000000 -0700
+++ linux-2.5.69-bk19/sound/usb/usbmixer.c	2003-05-26 04:41:43.000000000 -0700
@@ -164,9 +164,7 @@
 		if (p->id == unitid &&
 		    (! control || ! p->control || control == p->control)) {
 			buflen--;
-			strncpy(buf, p->name, buflen);
-			buf[buflen] = 0;
-			return strlen(buf);
+			return strlcpy(buf, p->name, buflen);
 		}
 	}
 	return 0;
@@ -816,7 +814,8 @@
 			if (! len)
 				len = get_term_name(state, &state->oterm, kctl->id.name, sizeof(kctl->id.name), 1);
 			if (! len)
-				len = sprintf(kctl->id.name, "Feature %d", unitid);
+				len = snprintf(kctl->id.name, sizeof(kctl->id.name),
+					       "Feature %d", unitid);
 		}
 		/* determine the stream direction:
 		 * if the connected output is USB stream, then it's likely a
@@ -824,24 +823,19 @@
 		 */
 		if (! mapped_name && ! (state->oterm.type >> 16)) {
 			if ((state->oterm.type & 0xff00) == 0x0100) {
-				if (len + 8 < sizeof(kctl->id.name)) {
-					strcpy(kctl->id.name + len, " Capture");
-					len += 8;
-				}
+				len = strlcat(kctl->id.name, " Capture", sizeof(kctl->id.name));
 			} else {
-				if (len + 9 < sizeof(kctl->id.name)) {
-					strcpy(kctl->id.name + len, " Playback");
-					len += 9;
-				}
+				len = strlcat(kctl->id.name + len, " Playback", sizeof(kctl->id.name));
 			}
 		}
-		if (len + 7 < sizeof(kctl->id.name))
-			strcpy(kctl->id.name + len, control == USB_FEATURE_MUTE ? " Switch" : " Volume");
+		strlcat(kctl->id.name + len, control == USB_FEATURE_MUTE ? " Switch" : " Volume",
+			sizeof(kctl->id.name));
 		break;
 
 	default:
 		if (! len)
-			strcpy(kctl->id.name, audio_feature_info[control-1].name);
+			strlcpy(kctl->id.name, audio_feature_info[control-1].name,
+				sizeof(kctl->id.name));
 		break;
 	}
 
@@ -969,8 +963,7 @@
 		len = get_term_name(state, &iterm, kctl->id.name, sizeof(kctl->id.name), 0);
 	if (! len)
 		len = sprintf(kctl->id.name, "Mixer Source %d", in_ch);
-	if (len + 7 < sizeof(kctl->id.name))
-		strcpy(kctl->id.name + len, " Volume");
+	strlcat(kctl->id.name + len, " Volume", sizeof(kctl->id.name));
 
 	snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n",
 		    cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
@@ -1189,22 +1182,18 @@
 		if (check_mapped_name(state, unitid, cval->control, kctl->id.name, sizeof(kctl->id.name)))
 			;
 		else if (info->name)
-			strcpy(kctl->id.name, info->name);
+			strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name));
 		else {
 			nameid = dsc[12 + num_ins + dsc[11 + num_ins]];
 			len = 0;
 			if (nameid)
 				len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name));
-			if (! len) {
-				strncpy(kctl->id.name, name, sizeof(kctl->id.name) - 1);
-				kctl->id.name[sizeof(kctl->id.name)-1] = 0;
-			}
-		}
-		len = strlen(kctl->id.name);
-		if (len + sizeof(valinfo->suffix) + 1 < sizeof(kctl->id.name)) {
-			kctl->id.name[len] = ' ';
-			strcpy(kctl->id.name + len + 1, valinfo->suffix);
+			if (! len)
+				strlcpy(kctl->id.name, name, sizeof(kctl->id.name));
 		}
+		strlcat(kctl->id.name, ' ', sizeof(kctl->id.name));
+		strlcat(kctl->id.name, valinfo->suffix, sizeof(kctl->id.name));
+
 		snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n",
 			    cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
 		if ((err = add_control_to_empty(state->chip->card, kctl)) < 0)
@@ -1402,14 +1391,12 @@
 		len = get_term_name(state, &state->oterm,
 				    kctl->id.name, sizeof(kctl->id.name), 0);
 		if (! len)
-			len = sprintf(kctl->id.name, "USB");
-		if ((state->oterm.type & 0xff00) == 0x0100) {
-			if (len + 15 < sizeof(kctl->id.name))
-				strcpy(kctl->id.name + len, " Capture Source");
-		} else {
-			if (len + 16 < sizeof(kctl->id.name))
-				strcpy(kctl->id.name + len, " Playback Source");
-		}
+			strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
+
+		if ((state->oterm.type & 0xff00) == 0x0100)
+			strlcat(kctl->id.name, " Capture Source", sizeof(kctl->id.name));
+		else
+			strlcat(kctl->id.name, " Playback Source", sizeof(kctl->id.name));
 	}
 
 	snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n",
