## Automatically generated incremental diff
## From:   linux-2.4.26-pre1
## To:     linux-2.4.26-pre2
## Robot:  $Id: make-incremental-diff,v 1.12 2004/01/06 07:19:36 hpa Exp $

diff -urN linux-2.4.26-pre1/Documentation/Configure.help linux-2.4.26-pre2/Documentation/Configure.help
--- linux-2.4.26-pre1/Documentation/Configure.help	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/Documentation/Configure.help	2004-03-06 11:20:28.000000000 -0800
@@ -19954,14 +19954,6 @@
   of verbosity. Saying Y enables these statements. This will increase
   your kernel size by around 50K.
 
-ACPI Relaxed AML Checking
-CONFIG_ACPI_RELAXED_AML
-  If you say `Y' here, the ACPI interpreter will relax its checking
-  for valid AML and will ignore some AML mistakes, such as off-by-one
-  errors in region sizes.  Some laptops may require this option.  In
-  particular, many Toshiba laptops require this for correct operation
-  of the AC module.
-
 ACPI Button
 CONFIG_ACPI_BUTTON
   This driver registers for events based on buttons, such as the
@@ -28736,6 +28728,13 @@
   The CAST6 encryption algorithm (synonymous with CAST-256) is
   described in RFC2612.
 
+CONFIG_CRYPTO_ARC4
+  ARC4 cipher algorithm.
+  
+  This is a stream cipher using keys ranging from 8 bits to 2048
+  bits in length.  ARC4 is commonly used in protocols such as WEP 
+  and SSL.
+
 CONFIG_CRYPTO_DEFLATE
   This is the Deflate algorithm (RFC1951), specified for use in
   IPSec with the IPCOMP protocol (RFC3173, RFC2394).
diff -urN linux-2.4.26-pre1/Documentation/crypto/api-intro.txt linux-2.4.26-pre2/Documentation/crypto/api-intro.txt
--- linux-2.4.26-pre1/Documentation/crypto/api-intro.txt	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-pre2/Documentation/crypto/api-intro.txt	2004-03-06 11:20:28.000000000 -0800
@@ -185,6 +185,8 @@
   Matthew Skala (Twofish)
   Dag Arne Osvik (Serpent)
   Brian Gladman (AES)
+  Kartikey Mahendra Bhatt (CAST6)
+  Jon Oberheide (ARC4)
 
 SHA1 algorithm contributors:
   Jean-Francois Dive
diff -urN linux-2.4.26-pre1/Documentation/kernel-parameters.txt linux-2.4.26-pre2/Documentation/kernel-parameters.txt
--- linux-2.4.26-pre1/Documentation/kernel-parameters.txt	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-pre2/Documentation/kernel-parameters.txt	2004-03-06 11:20:28.000000000 -0800
@@ -73,6 +73,8 @@
 		off	Disable ACPI
 		ht	Limit ACPI to boot-time LAPIC enumeration for HT,
 			disabling the run-time AML interpreter.
+		strict	Be less tolerant of platforms that are not
+			strictly ACPI specification compliant.
 
 	acpi_pic_sci=	[HW,ACPI] ACPI System Conrol Interrupt trigger mode
 		level	Force PIC-mode SCI to Level Trigger (default)
diff -urN linux-2.4.26-pre1/Documentation/networking/bonding.txt linux-2.4.26-pre2/Documentation/networking/bonding.txt
--- linux-2.4.26-pre1/Documentation/networking/bonding.txt	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/Documentation/networking/bonding.txt	2004-03-06 11:20:28.000000000 -0800
@@ -31,6 +31,7 @@
 Frequently Asked Questions
 High Availability
 Promiscuous Sniffing notes
+8021q VLAN support
 Limitations
 Resources and Links
 
@@ -140,10 +141,6 @@
 Be careful not to reference bond0 itself at the end of the line, or modprobe
 will die in an endless recursive loop.
 
-To have device characteristics (such as MTU size) propagate to slave devices,
-set the bond characteristics before enslaving the device.  The characteristics
-are propagated during the enslave process.
-
 If running SNMP agents, the bonding driver should be loaded before any network
 drivers participating in a bond. This requirement is due to the the interface
 index (ipAdEntIfIndex) being associated to the first interface found with a
@@ -601,7 +598,7 @@
 	For ethernet cards not supporting MII status, the arp_interval and
         arp_ip_target parameters must be specified for bonding to work
         correctly. If packets have not been sent or received during the
-        specified arp_interval durration, an ARP request is sent to the
+        specified arp_interval duration, an ARP request is sent to the
         targets to generate send and receive traffic. If after this
         interval, either the successful send and/or receive count has not
         incremented, the next slave in the sequence will become the active
@@ -669,16 +666,8 @@
 	that will be added.
 
 	To restore your slaves' MAC addresses, you need to detach them
-	from the bond (`ifenslave -d bond0 eth0'), set them down
-	(`ifconfig eth0 down'), unload the drivers (`rmmod 3c59x', for
-	example) and reload them to get the MAC addresses from their
-	eeproms. If the driver is shared by several devices, you need
-	to turn them all down. Another solution is to look for the MAC
-	address at boot time (dmesg or tail /var/log/messages) and to
-	reset it by hand with ifconfig :
-
-	  # ifconfig eth0 down
-	  # ifconfig eth0 hw ether 00:20:40:60:80:A0
+	from the bond (`ifenslave -d bond0 eth0'). The bonding driver will then
+	restore the MAC addresses that the slaves had before they were enslaved.
 
 9.  Which transmit polices can be used?
 
@@ -843,7 +832,7 @@
 
 In this configuration, there is an ISL - Inter Switch Link (could be a trunk),
 several servers (host1, host2 ...) attached to both switches each, and one or
-more ports to the outside world (port3...). One an only one slave on each host
+more ports to the outside world (port3...). One and only one slave on each host
 is active at a time, while all links are still monitored (the system can
 detect a failure of active and backup links).
 
@@ -933,6 +922,41 @@
 just ignore all the warnings it emits.
 
 
+8021q VLAN support
+==================
+
+It is possible to configure VLAN devices over a bond interface using the 8021q
+driver. However, only packets coming from the 8021q driver and passing through
+bonding will be tagged by default. Self generated packets, like bonding's
+learning packets or ARP packets generated by either ALB mode or the ARP
+monitor mechanism, are tagged internally by bonding itself. As a result,
+bonding has to "learn" what VLAN IDs are configured on top of it, and it uses
+those IDs to tag self generated packets.
+
+For simplicity reasons, and to support the use of adapters that can do VLAN
+hardware acceleration offloding, the bonding interface declares itself as
+fully hardware offloaing capable, it gets the add_vid/kill_vid notifications
+to gather the necessary information, and it propagates those actions to the
+slaves.
+In case of mixed adapter types, hardware accelerated tagged packets that should
+go through an adapter that is not offloading capable are "un-accelerated" by the
+bonding driver so the VLAN tag sits in the regular location.
+
+VLAN interfaces *must* be added on top of a bonding interface only after
+enslaving at least one slave. This is because until the first slave is added the
+bonding interface has a HW address of 00:00:00:00:00:00, which will be copied by
+the VLAN interface when it is created.
+
+Notice that a problem would occur if all slaves are released from a bond that
+still has VLAN interfaces on top of it. When later coming to add new slaves, the
+bonding interface would get a HW address from the first slave, which might not
+match that of the VLAN interfaces. It is recommended that either all VLANs are
+removed and then re-added, or to manually set the bonding interface's HW
+address so it matches the VLAN's. (Note: changing a VLAN interface's HW address
+would set the underlying device -- i.e. the bonding interface -- to promiscouos
+mode, which might not be what you want).
+
+
 Limitations
 ===========
 The main limitations are :
diff -urN linux-2.4.26-pre1/MAINTAINERS linux-2.4.26-pre2/MAINTAINERS
--- linux-2.4.26-pre1/MAINTAINERS	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/MAINTAINERS	2004-03-06 11:20:29.000000000 -0800
@@ -166,7 +166,7 @@
 P:	Len Brown
 M:	len.brown@intel.com
 L:	acpi-devel@lists.sourceforge.net
-W:	http://sf.net/projects/acpi/
+W:	http://acpi.sourceforge.net/
 S:	Maintained
 
 AD1816 SOUND DRIVER
@@ -1456,9 +1456,9 @@
 
 PERMEDIA 3 FRAMEBUFFER DRIVER
 P:	Romain Dolbeau
-M:	dolbeau@irisa.fr
+M:	dolbeau@caps-entreprise.com
 L:	linux-fbdev-devel@lists.sourceforge.net
-W:	http://www.irisa.fr/prive/dolbeau/pm3fb/pm3fb.html
+W:	http://www.caps-entreprise.com/private/dolbeau/pm3fb/pm3fb.html
 S:	Maintained
 
 PHILIPS NINO PALM PC
diff -urN linux-2.4.26-pre1/Makefile linux-2.4.26-pre2/Makefile
--- linux-2.4.26-pre1/Makefile	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/Makefile	2004-03-06 11:20:29.000000000 -0800
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 26
-EXTRAVERSION = -pre1
+EXTRAVERSION = -pre2
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.26-pre1/arch/i386/kernel/acpi.c linux-2.4.26-pre2/arch/i386/kernel/acpi.c
--- linux-2.4.26-pre1/arch/i386/kernel/acpi.c	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-pre2/arch/i386/kernel/acpi.c	2004-03-06 11:20:28.000000000 -0800
@@ -49,14 +49,14 @@
 
 #define PREFIX			"ACPI: "
 
-int acpi_lapic = 0;
-int acpi_ioapic = 0;
+int acpi_lapic;
+int acpi_ioapic;
+int acpi_strict;
 
 /* --------------------------------------------------------------------------
                               Boot-time Configuration
    -------------------------------------------------------------------------- */
 
-#ifdef CONFIG_ACPI_BOOT
 int acpi_noirq __initdata = 0;  /* skip ACPI IRQ initialization */
 int acpi_ht __initdata = 1;     /* enable HT */
 
@@ -472,7 +472,6 @@
 	return 0;
 }
 
-#endif /*CONFIG_ACPI_BOOT*/
 
 #ifdef	CONFIG_ACPI_BUS
 /*
@@ -480,7 +479,7 @@
  * programs the PIC-mode SCI to Level Trigger.
  * (NO-OP if the BIOS set Level Trigger already)
  *
- * If a PIC-mode SCI is not recogznied or gives spurious IRQ7's
+ * If a PIC-mode SCI is not recognized or gives spurious IRQ7's
  * it may require Edge Trigger -- use "acpi_pic_sci=edge"
  * (NO-OP if the BIOS set Edge Trigger already)
  *
diff -urN linux-2.4.26-pre1/arch/i386/kernel/mpparse.c linux-2.4.26-pre2/arch/i386/kernel/mpparse.c
--- linux-2.4.26-pre1/arch/i386/kernel/mpparse.c	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-pre2/arch/i386/kernel/mpparse.c	2004-03-06 11:20:28.000000000 -0800
@@ -1118,7 +1118,7 @@
 	 *      erroneously sets the trigger to level, resulting in a HUGE 
 	 *      increase of timer interrupts!
 	 */
-	if ((bus_irq == 0) && (global_irq == 2) && (trigger == 3))
+	if ((bus_irq == 0) && (trigger == 3))
 		trigger = 1;
 
 	intsrc.mpc_type = MP_INTSRC;
@@ -1139,7 +1139,7 @@
 	 * Otherwise create a new entry (e.g. global_irq == 2).
 	 */
 	for (i = 0; i < mp_irq_entries; i++) {
-		if ((mp_irqs[i].mpc_dstapic == intsrc.mpc_dstapic) 
+		if ((mp_irqs[i].mpc_srcbus == intsrc.mpc_srcbus) 
 			&& (mp_irqs[i].mpc_srcbusirq == intsrc.mpc_srcbusirq)) {
 			mp_irqs[i] = intsrc;
 			found = 1;
@@ -1200,13 +1200,14 @@
 	 */
 	for (i = 0; i < 16; i++) {
 
-		if (i == 2) continue;			/* Don't connect IRQ2 */
+		if (i == 2)
+			continue;			/* Don't connect IRQ2 */
 
 		mp_irqs[mp_irq_entries].mpc_type = MP_INTSRC;
 		mp_irqs[mp_irq_entries].mpc_irqflag = 0;	/* Conforming */
 		mp_irqs[mp_irq_entries].mpc_srcbus = MP_ISA_BUS;
 		mp_irqs[mp_irq_entries].mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
-		mp_irqs[mp_irq_entries].mpc_irqtype = i ? mp_INT : mp_ExtINT;   /* 8259A to #0 */
+		mp_irqs[mp_irq_entries].mpc_irqtype = mp_INT;
 		mp_irqs[mp_irq_entries].mpc_srcbusirq = i;	   /* Identity mapped */
 		mp_irqs[mp_irq_entries].mpc_dstirq = i;
 
@@ -1349,7 +1350,7 @@
 			continue;
 		}
 		if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
-			printk(KERN_DEBUG "Pin %d-%d already programmed\n",
+			Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
 				mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
 			entry->irq = irq;
 			continue;
diff -urN linux-2.4.26-pre1/arch/i386/kernel/setup.c linux-2.4.26-pre2/arch/i386/kernel/setup.c
--- linux-2.4.26-pre1/arch/i386/kernel/setup.c	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-pre2/arch/i386/kernel/setup.c	2004-03-06 11:20:28.000000000 -0800
@@ -852,6 +852,11 @@
 			if (!acpi_force) acpi_disabled = 1; 
 		} 
 
+		/* acpi=strict disables out-of-spec workarounds */
+		else if (!memcmp(from, "acpi=strict", 11)) {
+			acpi_strict = 1;
+		}
+
 		else if (!memcmp(from, "pci=noacpi", 10)) { 
 			acpi_noirq_set();
 		}
diff -urN linux-2.4.26-pre1/arch/sparc/defconfig linux-2.4.26-pre2/arch/sparc/defconfig
--- linux-2.4.26-pre1/arch/sparc/defconfig	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/arch/sparc/defconfig	2004-03-06 11:20:28.000000000 -0800
@@ -161,9 +161,11 @@
 #
 CONFIG_IPV6_SCTP__=m
 CONFIG_IP_SCTP=m
-# CONFIG_SCTP_ADLER32 is not set
 # CONFIG_SCTP_DBG_MSG is not set
 # CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
 
@@ -362,6 +364,7 @@
 CONFIG_LOCKD=y
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_SMB_UNIX is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_NCPFS_PACKET_SIGNING is not set
 # CONFIG_NCPFS_IOCTL_LOCKING is not set
diff -urN linux-2.4.26-pre1/arch/sparc/kernel/sys_sunos.c linux-2.4.26-pre2/arch/sparc/kernel/sys_sunos.c
--- linux-2.4.26-pre1/arch/sparc/kernel/sys_sunos.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-pre2/arch/sparc/kernel/sys_sunos.c	2004-03-06 11:20:28.000000000 -0800
@@ -688,8 +688,8 @@
 
 static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
 {
-	int  server_fd;
-	char *the_name;
+	int  server_fd, err;
+	char *the_name, *mount_page;
 	struct nfs_mount_data linux_nfs_mount;
 	struct sunos_nfs_mount_args sunos_mount;
 
@@ -742,7 +742,16 @@
 	linux_nfs_mount.hostname [255] = 0;
 	putname (the_name);
 	
-	return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount);
+	mount_page = (char *) get_zeroed_page(GFP_KERNEL);
+	if (!mount_page)
+		return -ENOMEM;
+
+	memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount));
+
+	err = do_mount("", dir_name, "nfs", linux_flags, mount_page);
+
+	free_page((unsigned long) mount_page);
+	return err;
 }
 
 asmlinkage int
diff -urN linux-2.4.26-pre1/arch/sparc64/defconfig linux-2.4.26-pre2/arch/sparc64/defconfig
--- linux-2.4.26-pre1/arch/sparc64/defconfig	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/arch/sparc64/defconfig	2004-03-06 11:20:28.000000000 -0800
@@ -70,6 +70,7 @@
 # CONFIG_PARPORT_SERIAL is not set
 CONFIG_PARPORT_PC_FIFO=y
 # CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_PC_PCMCIA is not set
 # CONFIG_PARPORT_AMIGA is not set
 # CONFIG_PARPORT_MFC3 is not set
 # CONFIG_PARPORT_ATARI is not set
@@ -122,6 +123,7 @@
 CONFIG_FB_PCI=y
 CONFIG_FB_ATY=y
 CONFIG_FB_ATY_CT=y
+# CONFIG_FB_IT8181 is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
 CONFIG_FBCON_CFB8=y
@@ -314,9 +316,11 @@
 #
 CONFIG_IPV6_SCTP__=m
 CONFIG_IP_SCTP=m
-# CONFIG_SCTP_ADLER32 is not set
 # CONFIG_SCTP_DBG_MSG is not set
 # CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
 # CONFIG_ATM is not set
 CONFIG_VLAN_8021Q=m
 
@@ -351,6 +355,7 @@
 CONFIG_NET_SCH_CBQ=m
 CONFIG_NET_SCH_HTB=m
 CONFIG_NET_SCH_CSZ=m
+CONFIG_NET_SCH_HFSC=m
 CONFIG_NET_SCH_PRIO=m
 CONFIG_NET_SCH_RED=m
 CONFIG_NET_SCH_SFQ=m
@@ -617,6 +622,7 @@
 CONFIG_FEALNX=m
 CONFIG_NATSEMI=m
 CONFIG_NE2K_PCI=m
+CONFIG_FORCEDETH=m
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139CP is not set
@@ -974,7 +980,6 @@
 CONFIG_USB_RTL8150=m
 CONFIG_USB_KAWETH=m
 CONFIG_USB_CATC=m
-CONFIG_USB_AX8817X=m
 CONFIG_USB_CDCETHER=m
 CONFIG_USB_USBNET=m
 
@@ -1034,13 +1039,19 @@
 # Support for USB gadgets
 #
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_NET2280=y
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_CONTROLLER is not set
+CONFIG_USB_NET2280=y
+CONFIG_USB_GADGET_CONTROLLER=y
 
 #
-# USB Peripheral Controller Drivers
+# USB Gadget Drivers
 #
-# CONFIG_USB_GADGET_CONTROLLER is not set
-# CONFIG_USB_NET2280 is not set
-# CONFIG_USB_GADGET_CONTROLLER is not set
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_FILE_STORAGE_TEST is not set
 
 #
 # Bluetooth support
@@ -1084,6 +1095,7 @@
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_DCFLUSH is not set
+# CONFIG_DEBUG_BOOTMEM is not set
 # CONFIG_STACK_DEBUG is not set
 CONFIG_LOG_BUF_SHIFT=0
 
@@ -1104,6 +1116,8 @@
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_DEFLATE=y
 # CONFIG_CRYPTO_TEST is not set
 
diff -urN linux-2.4.26-pre1/arch/sparc64/kernel/sys_sunos32.c linux-2.4.26-pre2/arch/sparc64/kernel/sys_sunos32.c
--- linux-2.4.26-pre1/arch/sparc64/kernel/sys_sunos32.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-pre2/arch/sparc64/kernel/sys_sunos32.c	2004-03-06 11:20:28.000000000 -0800
@@ -654,8 +654,8 @@
 /* XXXXXXXXXXXXXXXXXXXX */
 static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
 {
-	int  server_fd;
-	char *the_name;
+	int  server_fd, err;
+	char *the_name, *mount_page;
 	struct nfs_mount_data linux_nfs_mount;
 	struct sunos_nfs_mount_args sunos_mount;
 
@@ -708,7 +708,16 @@
 	linux_nfs_mount.hostname [255] = 0;
 	putname (the_name);
 	
-	return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount);
+	mount_page = (char *) get_zeroed_page(GFP_KERNEL);
+	if (!mount_page)
+		return -ENOMEM;
+
+	memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount));
+
+	err = do_mount("", dir_name, "nfs", linux_flags, mount_page);
+
+	free_page((unsigned long) mount_page);
+	return err;
 }
 
 /* XXXXXXXXXXXXXXXXXXXX */
diff -urN linux-2.4.26-pre1/arch/x86_64/kernel/acpi.c linux-2.4.26-pre2/arch/x86_64/kernel/acpi.c
--- linux-2.4.26-pre1/arch/x86_64/kernel/acpi.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/arch/x86_64/kernel/acpi.c	2004-03-06 11:20:28.000000000 -0800
@@ -47,14 +47,14 @@
 
 #define PREFIX			"ACPI: "
 
-int acpi_lapic = 0;
-int acpi_ioapic = 0;
+int acpi_lapic;
+int acpi_ioapic;
+int acpi_strict;
 
 /* --------------------------------------------------------------------------
                               Boot-time Configuration
    -------------------------------------------------------------------------- */
 
-#ifdef CONFIG_ACPI_BOOT
 
 enum acpi_irq_model_id		acpi_irq_model;
 
@@ -296,7 +296,7 @@
  * programs the PIC-mode SCI to Level Trigger.
  * (NO-OP if the BIOS set Level Trigger already)
  *
- * If a PIC-mode SCI is not recogznied or gives spurious IRQ7's
+ * If a PIC-mode SCI is not recognized or gives spurious IRQ7's
  * it may require Edge Trigger -- use "acpi_pic_sci=edge"
  * (NO-OP if the BIOS set Edge Trigger already)
  *
@@ -567,8 +567,6 @@
 	return 0;
 }
 
-#endif /*CONFIG_ACPI_BOOT*/
-
 
 /* --------------------------------------------------------------------------
                               Low-Level Sleep Support
diff -urN linux-2.4.26-pre1/arch/x86_64/kernel/e820.c linux-2.4.26-pre2/arch/x86_64/kernel/e820.c
--- linux-2.4.26-pre1/arch/x86_64/kernel/e820.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/arch/x86_64/kernel/e820.c	2004-03-06 11:20:28.000000000 -0800
@@ -544,6 +544,12 @@
 #ifdef	CONFIG_ACPI_BOOT
  		else if (!memcmp(from, "acpi=off", 8))
   			acpi_disabled = 1;
+
+		/* acpi=strict disables out-of-spec workarounds */
+		else if (!memcmp(from, "acpi=strict", 11)) {
+			acpi_strict = 1;
+		}
+
 		else if (!memcmp(from, "pci=noacpi", 10)) {
 			acpi_noirq_set();
 		}
diff -urN linux-2.4.26-pre1/arch/x86_64/kernel/mpparse.c linux-2.4.26-pre2/arch/x86_64/kernel/mpparse.c
--- linux-2.4.26-pre1/arch/x86_64/kernel/mpparse.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-pre2/arch/x86_64/kernel/mpparse.c	2004-03-06 11:20:28.000000000 -0800
@@ -794,7 +794,7 @@
 	 *      erroneously sets the trigger to level, resulting in a HUGE 
 	 *      increase of timer interrupts!
 	 */
-	if ((bus_irq == 0) && (global_irq == 2) && (trigger == 3))
+	if ((bus_irq == 0) && (trigger == 3))
 		trigger = 1;
 
 	intsrc.mpc_type = MP_INTSRC;
@@ -815,7 +815,7 @@
 	 * Otherwise create a new entry (e.g. global_irq == 2).
 	 */
 	for (i = 0; i < mp_irq_entries; i++) {
-		if ((mp_irqs[i].mpc_dstapic == intsrc.mpc_dstapic) 
+		if ((mp_irqs[i].mpc_srcbus == intsrc.mpc_srcbus) 
 			&& (mp_irqs[i].mpc_dstirq == intsrc.mpc_dstirq)) {
 			mp_irqs[i] = intsrc;
 			found = 1;
@@ -862,9 +862,10 @@
 	 */
 	for (i = 0; i < 16; i++) {
 
-		if (i == 2) continue;			/* Don't connect IRQ2 */
+		if (i == 2)
+			continue;			/* Don't connect IRQ2 */
 
-		intsrc.mpc_irqtype = i ? mp_INT : mp_ExtINT;   /* 8259A to #0 */
+		intsrc.mpc_irqtype = mp_INT;
 		intsrc.mpc_srcbusirq = i;		   /* Identity mapped */
 		intsrc.mpc_dstirq = i;
 
@@ -1008,7 +1009,7 @@
 			continue;
 		}
 		if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
-			printk(KERN_DEBUG "Pin %d-%d already programmed\n",
+			Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
 				mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
 			entry->irq = irq;
 			continue;
diff -urN linux-2.4.26-pre1/crypto/Config.in linux-2.4.26-pre2/crypto/Config.in
--- linux-2.4.26-pre1/crypto/Config.in	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/crypto/Config.in	2004-03-06 11:20:28.000000000 -0800
@@ -72,6 +72,7 @@
   tristate       '  AES cipher algorithms' CONFIG_CRYPTO_AES
   tristate       '  CAST5 (CAST-128) cipher algorithm' CONFIG_CRYPTO_CAST5
   tristate       '  CAST6 (CAST-256) cipher algorithm' CONFIG_CRYPTO_CAST6
+  tristate       '  ARC4 cipher algorithm' CONFIG_CRYPTO_ARC4
   if [ "$CONFIG_INET_IPCOMP" = "y" -o \
        "$CONFIG_INET_IPCOMP" = "m" -o \
        "$CONFIG_INET6_IPCOMP" = "y" -o \
diff -urN linux-2.4.26-pre1/crypto/Makefile linux-2.4.26-pre2/crypto/Makefile
--- linux-2.4.26-pre1/crypto/Makefile	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/crypto/Makefile	2004-03-06 11:20:28.000000000 -0800
@@ -9,7 +9,7 @@
 autoload-crypto-$(CONFIG_KMOD) = autoload.o
 proc-crypto-$(CONFIG_PROC_FS) = proc.o
 
-obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o \
+obj-$(CONFIG_CRYPTO) += api.o scatterwalk.o cipher.o digest.o compress.o \
 			$(autoload-crypto-y) $(proc-crypto-y)
 
 obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
@@ -26,6 +26,7 @@
 obj-$(CONFIG_CRYPTO_AES) += aes.o
 obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
 obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
+obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
 obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
 
 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
diff -urN linux-2.4.26-pre1/crypto/arc4.c linux-2.4.26-pre2/crypto/arc4.c
--- linux-2.4.26-pre1/crypto/arc4.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre2/crypto/arc4.c	2004-03-06 11:20:28.000000000 -0800
@@ -0,0 +1,106 @@
+/* 
+ * Cryptographic API
+ *
+ * ARC4 Cipher Algorithm
+ *
+ * Jon Oberheide <jon@focalhost.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/crypto.h>
+
+#define ARC4_MIN_KEY_SIZE	1
+#define ARC4_MAX_KEY_SIZE	256
+#define ARC4_BLOCK_SIZE		1
+
+struct arc4_ctx {
+	u8 S[256];
+	u8 x, y;
+};
+
+static int arc4_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
+{
+	struct arc4_ctx *ctx = ctx_arg;
+	int i, j = 0, k = 0;
+
+	ctx->x = 1;
+	ctx->y = 0;
+
+	for(i = 0; i < 256; i++)
+		ctx->S[i] = i;
+
+	for(i = 0; i < 256; i++)
+	{
+		u8 a = ctx->S[i];
+		j = (j + in_key[k] + a) & 0xff;
+		ctx->S[i] = ctx->S[j];
+		ctx->S[j] = a;
+		if(++k >= key_len)
+			k = 0;
+	}
+
+	/* TODO: dump the first 768 bytes generated as recommended
+	   by Ilya Mironov (http://eprint.iacr.org/2002/067/) to 
+	   increase the statistical strength of the state table */
+
+	return 0;
+}
+
+static void arc4_crypt(void *ctx_arg, u8 *out, const u8 *in)
+{
+	struct arc4_ctx *ctx = ctx_arg;
+
+	u8 *const S = ctx->S;
+	u8 x = ctx->x;
+	u8 y = ctx->y;
+
+	u8 a = S[x];
+	y = (y + a) & 0xff;
+	u8 b = S[y];
+	S[x] = b;
+	S[y] = a;
+	x = (x + 1) & 0xff;
+	*out++ = *in ^ S[(a + b) & 0xff];
+
+	ctx->x = x;
+	ctx->y = y;
+}
+
+static struct crypto_alg arc4_alg = {
+	.cra_name		=	"arc4",
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	ARC4_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof(struct arc4_ctx),
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(arc4_alg.cra_list),
+	.cra_u			=	{ .cipher = {
+	.cia_min_keysize	=	ARC4_MIN_KEY_SIZE,
+	.cia_max_keysize	=	ARC4_MAX_KEY_SIZE,
+	.cia_setkey	   	= 	arc4_set_key,
+	.cia_encrypt	 	=	arc4_crypt,
+	.cia_decrypt	  	=	arc4_crypt } }
+};
+
+static int __init arc4_init(void)
+{
+	return crypto_register_alg(&arc4_alg);
+}
+
+
+static void __exit arc4_exit(void)
+{
+	crypto_unregister_alg(&arc4_alg);
+}
+
+module_init(arc4_init);
+module_exit(arc4_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
+MODULE_AUTHOR("Jon Oberheide <jon@focalhost.com>");
diff -urN linux-2.4.26-pre1/crypto/cipher.c linux-2.4.26-pre2/crypto/cipher.c
--- linux-2.4.26-pre1/crypto/cipher.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/crypto/cipher.c	2004-03-06 11:20:28.000000000 -0800
@@ -4,7 +4,6 @@
  * Cipher operations.
  *
  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- * Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>.
  *
  * 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
@@ -17,30 +16,13 @@
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <linux/highmem.h>
 #include <asm/scatterlist.h>
 #include "internal.h"
+#include "scatterwalk.h"
 
 typedef void (cryptfn_t)(void *, u8 *, const u8 *);
 typedef void (procfn_t)(struct crypto_tfm *, u8 *,
-                        u8*, cryptfn_t, int enc, void *);
-
-struct scatter_walk {
-	struct scatterlist	*sg;
-	struct page		*page;
-	void			*data;
-	unsigned int		len_this_page;
-	unsigned int		len_this_segment;
-	unsigned int		offset;
-};
-
-enum km_type crypto_km_types[] = {
-	KM_USER0,
-	KM_USER1,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,
-};
+                        u8*, cryptfn_t, int enc, void *, int);
 
 static inline void xor_64(u8 *a, const u8 *b)
 {
@@ -57,108 +39,6 @@
 }
 
 
-/* Define sg_next is an inline routine now in case we want to change
-   scatterlist to a linked list later. */
-static inline struct scatterlist *sg_next(struct scatterlist *sg)
-{
-	return sg + 1;
-}
-
-void *which_buf(struct scatter_walk *walk, unsigned int nbytes, void *scratch)
-{
-	if (nbytes <= walk->len_this_page &&
-	    (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <=
-	    PAGE_CACHE_SIZE)
-		return walk->data;
-	else
-		return scratch;
-}
-
-static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
-{
-	if (out)
-		memcpy(sgdata, buf, nbytes);
-	else
-		memcpy(buf, sgdata, nbytes);
-}
-
-static void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
-{
-	unsigned int rest_of_page;
-
-	walk->sg = sg;
-
-	walk->page = sg->page;
-	walk->len_this_segment = sg->length;
-
-	rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1));
-	walk->len_this_page = min(sg->length, rest_of_page);
-	walk->offset = sg->offset;
-}
-
-static void scatterwalk_map(struct scatter_walk *walk, int out)
-{
-	walk->data = crypto_kmap(walk->page, out) + walk->offset;
-}
-
-static void scatter_page_done(struct scatter_walk *walk, int out,
-			      unsigned int more)
-{
-	/* walk->data may be pointing the first byte of the next page;
-	   however, we know we transfered at least one byte.  So,
-	   walk->data - 1 will be a virutual address in the mapped page. */
-
-	if (out)
-		flush_dcache_page(walk->page);
-
-	if (more) {
-		walk->len_this_segment -= walk->len_this_page;
-
-		if (walk->len_this_segment) {
-			walk->page++;
-			walk->len_this_page = min(walk->len_this_segment,
-						  (unsigned)PAGE_CACHE_SIZE);
-			walk->offset = 0;
-		}
-		else
-			scatterwalk_start(walk, sg_next(walk->sg));
-	}
-}
-
-static void scatter_done(struct scatter_walk *walk, int out, int more)
-{
-	crypto_kunmap(walk->data, out);
-	if (walk->len_this_page == 0 || !more)
-		scatter_page_done(walk, out, more);
-}
-
-/*
- * Do not call this unless the total length of all of the fragments 
- * has been verified as multiple of the block size.
- */
-static int copy_chunks(void *buf, struct scatter_walk *walk,
-			size_t nbytes, int out)
-{
-	if (buf != walk->data) {
-		while (nbytes > walk->len_this_page) {
-			memcpy_dir(buf, walk->data, walk->len_this_page, out);
-			buf += walk->len_this_page;
-			nbytes -= walk->len_this_page;
-
-			crypto_kunmap(walk->data, out);
-			scatter_page_done(walk, out, 1);
-			scatterwalk_map(walk, out);
-		}
-
-		memcpy_dir(buf, walk->data, nbytes, out);
-	}
-
-	walk->offset += nbytes;
-	walk->len_this_page -= nbytes;
-	walk->len_this_segment -= nbytes;
-	return 0;
-}
-
 /* 
  * Generic encrypt/decrypt wrapper for ciphers, handles operations across
  * multiple page boundaries by using temporary blocks.  In user context,
@@ -191,19 +71,21 @@
 
 		scatterwalk_map(&walk_in, 0);
 		scatterwalk_map(&walk_out, 1);
-		src_p = which_buf(&walk_in, bsize, tmp_src);
-		dst_p = which_buf(&walk_out, bsize, tmp_dst);
+		src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src);
+		dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst);
 
 		nbytes -= bsize;
 
-		copy_chunks(src_p, &walk_in, bsize, 0);
+		scatterwalk_copychunks(src_p, &walk_in, bsize, 0);
 
-		prfn(tfm, dst_p, src_p, crfn, enc, info);
+		prfn(tfm, dst_p, src_p, crfn, enc, info,
+		     scatterwalk_samebuf(&walk_in, &walk_out,
+					 src_p, dst_p));
 
-		scatter_done(&walk_in, 0, nbytes);
+		scatterwalk_done(&walk_in, 0, nbytes);
 
-		copy_chunks(dst_p, &walk_out, bsize, 1);
-		scatter_done(&walk_out, 1, nbytes);
+		scatterwalk_copychunks(dst_p, &walk_out, bsize, 1);
+		scatterwalk_done(&walk_out, 1, nbytes);
 
 		if (!nbytes)
 			return 0;
@@ -212,8 +94,8 @@
 	}
 }
 
-static void cbc_process(struct crypto_tfm *tfm,
-                        u8 *dst, u8 *src, cryptfn_t fn, int enc, void *info)
+static void cbc_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
+			cryptfn_t fn, int enc, void *info, int in_place)
 {
 	u8 *iv = info;
 	
@@ -226,10 +108,9 @@
 		fn(crypto_tfm_ctx(tfm), dst, iv);
 		memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm));
 	} else {
-		const int need_stack = (src == dst);
-		u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0];
-		u8 *buf = need_stack ? stack : dst;
-		
+		u8 stack[in_place ? crypto_tfm_alg_blocksize(tfm) : 0];
+		u8 *buf = in_place ? stack : dst;
+
 		fn(crypto_tfm_ctx(tfm), buf, src);
 		tfm->crt_u.cipher.cit_xor_block(buf, iv);
 		memcpy(iv, src, crypto_tfm_alg_blocksize(tfm));
@@ -239,7 +120,7 @@
 }
 
 static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
-                        cryptfn_t fn, int enc, void *info)
+			cryptfn_t fn, int enc, void *info, int in_place)
 {
 	fn(crypto_tfm_ctx(tfm), dst, src);
 }
diff -urN linux-2.4.26-pre1/crypto/internal.h linux-2.4.26-pre2/crypto/internal.h
--- linux-2.4.26-pre1/crypto/internal.h	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.26-pre2/crypto/internal.h	2004-03-06 11:20:28.000000000 -0800
@@ -11,6 +11,7 @@
  */
 #ifndef _CRYPTO_INTERNAL_H
 #define _CRYPTO_INTERNAL_H
+#include <linux/crypto.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/init.h>
diff -urN linux-2.4.26-pre1/crypto/scatterwalk.c linux-2.4.26-pre2/crypto/scatterwalk.c
--- linux-2.4.26-pre1/crypto/scatterwalk.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre2/crypto/scatterwalk.c	2004-03-06 11:20:28.000000000 -0800
@@ -0,0 +1,124 @@
+/*
+ * Cryptographic API.
+ *
+ * Cipher operations.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *               2002 Adam J. Richter <adam@yggdrasil.com>
+ *               2004 Jean-Luc Cooke <jlcooke@certainkey.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <asm/scatterlist.h>
+#include "internal.h"
+#include "scatterwalk.h"
+
+enum km_type crypto_km_types[] = {
+	KM_USER0,
+	KM_USER1,
+	KM_SOFTIRQ0,
+	KM_SOFTIRQ1,
+};
+
+void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch)
+{
+	if (nbytes <= walk->len_this_page &&
+	    (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <=
+	    PAGE_CACHE_SIZE)
+		return walk->data;
+	else
+		return scratch;
+}
+
+static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
+{
+	if (out)
+		memcpy(sgdata, buf, nbytes);
+	else
+		memcpy(buf, sgdata, nbytes);
+}
+
+void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
+{
+	unsigned int rest_of_page;
+
+	walk->sg = sg;
+
+	walk->page = sg->page;
+	walk->len_this_segment = sg->length;
+
+	rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1));
+	walk->len_this_page = min(sg->length, rest_of_page);
+	walk->offset = sg->offset;
+}
+
+void scatterwalk_map(struct scatter_walk *walk, int out)
+{
+	walk->data = crypto_kmap(walk->page, out) + walk->offset;
+}
+
+static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
+				 unsigned int more)
+{
+	/* walk->data may be pointing the first byte of the next page;
+	   however, we know we transfered at least one byte.  So,
+	   walk->data - 1 will be a virutual address in the mapped page. */
+
+	if (out)
+		flush_dcache_page(walk->page);
+
+	if (more) {
+		walk->len_this_segment -= walk->len_this_page;
+
+		if (walk->len_this_segment) {
+			walk->page++;
+			walk->len_this_page = min(walk->len_this_segment,
+						  (unsigned)PAGE_CACHE_SIZE);
+			walk->offset = 0;
+		}
+		else
+			scatterwalk_start(walk, sg_next(walk->sg));
+	}
+}
+
+void scatterwalk_done(struct scatter_walk *walk, int out, int more)
+{
+	crypto_kunmap(walk->data, out);
+	if (walk->len_this_page == 0 || !more)
+		scatterwalk_pagedone(walk, out, more);
+}
+
+/*
+ * Do not call this unless the total length of all of the fragments
+ * has been verified as multiple of the block size.
+ */
+int scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
+			   size_t nbytes, int out)
+{
+	if (buf != walk->data) {
+		while (nbytes > walk->len_this_page) {
+			memcpy_dir(buf, walk->data, walk->len_this_page, out);
+			buf += walk->len_this_page;
+			nbytes -= walk->len_this_page;
+
+			crypto_kunmap(walk->data, out);
+			scatterwalk_pagedone(walk, out, 1);
+			scatterwalk_map(walk, out);
+		}
+
+		memcpy_dir(buf, walk->data, nbytes, out);
+	}
+
+	walk->offset += nbytes;
+	walk->len_this_page -= nbytes;
+	walk->len_this_segment -= nbytes;
+	return 0;
+}
diff -urN linux-2.4.26-pre1/crypto/scatterwalk.h linux-2.4.26-pre2/crypto/scatterwalk.h
--- linux-2.4.26-pre1/crypto/scatterwalk.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre2/crypto/scatterwalk.h	2004-03-06 11:20:28.000000000 -0800
@@ -0,0 +1,50 @@
+/*
+ * Cryptographic API.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2002 Adam J. Richter <adam@yggdrasil.com>
+ * Copyright (c) 2004 Jean-Luc Cooke <jlcooke@certainkey.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef _CRYPTO_SCATTERWALK_H
+#define _CRYPTO_SCATTERWALK_H
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+
+struct scatter_walk {
+	struct scatterlist	*sg;
+	struct page		*page;
+	void			*data;
+	unsigned int		len_this_page;
+	unsigned int		len_this_segment;
+	unsigned int		offset;
+};
+
+/* Define sg_next is an inline routine now in case we want to change
+   scatterlist to a linked list later. */
+static inline struct scatterlist *sg_next(struct scatterlist *sg)
+{
+	return sg + 1;
+}
+
+static inline int scatterwalk_samebuf(struct scatter_walk *walk_in,
+				      struct scatter_walk *walk_out,
+				      void *src_p, void *dst_p)
+{
+	return walk_in->page == walk_out->page &&
+	       walk_in->data == src_p && walk_out->data == dst_p;
+}
+
+void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch);
+void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg);
+int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, size_t nbytes, int out);
+void scatterwalk_map(struct scatter_walk *walk, int out);
+void scatterwalk_done(struct scatter_walk *walk, int out, int more);
+
+#endif  /* _CRYPTO_SCATTERWALK_H */
diff -urN linux-2.4.26-pre1/crypto/tcrypt.c linux-2.4.26-pre2/crypto/tcrypt.c
--- linux-2.4.26-pre1/crypto/tcrypt.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/crypto/tcrypt.c	2004-03-06 11:20:28.000000000 -0800
@@ -63,7 +63,7 @@
 static char *check[] = {
 	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
 	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", 
-	"deflate", NULL
+	"arc4", "deflate", NULL
 };
 
 static void
@@ -558,6 +558,10 @@
 		test_cipher ("cast6", MODE_ECB, ENCRYPT, cast6_enc_tv_template, CAST6_ENC_TEST_VECTORS);
 		test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS);
 
+		//ARC4
+		test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS);
+		test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS);
+
 		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
 		test_deflate();		
@@ -640,6 +644,11 @@
 		test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS);
 		break;
 
+	case 16:
+		test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS);
+		test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS);
+		break;
+
 #ifdef CONFIG_CRYPTO_HMAC
 	case 100:
 		test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
diff -urN linux-2.4.26-pre1/crypto/tcrypt.h linux-2.4.26-pre2/crypto/tcrypt.h
--- linux-2.4.26-pre1/crypto/tcrypt.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/crypto/tcrypt.h	2004-03-06 11:20:28.000000000 -0800
@@ -1488,6 +1488,147 @@
 	},
 };
 
+/* 
+ * ARC4 test vectors from OpenSSL 
+ */
+#define ARC4_ENC_TEST_VECTORS	7
+#define ARC4_DEC_TEST_VECTORS	7
+
+struct cipher_testvec arc4_enc_tv_template[] =
+{
+	{
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.ilen	= 8,
+		.result	= { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.ilen	= 8,
+		.result	= { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 8,
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.ilen	= 8,
+		.result	= { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a },
+		.rlen	= 8,
+	}, {
+		.key	= { 0xef, 0x01, 0x23, 0x45},
+		.klen	= 4,
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00 },
+		.ilen	= 20,
+		.result	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+			    0xbd, 0x61, 0x5a, 0x11, 0x62, 0xe1, 0xc7, 0xba,
+			    0x36, 0xb6, 0x78, 0x58 },
+		.rlen	= 20,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78 },
+		.ilen	= 28,
+		.result	= { 0x66, 0xa0, 0x94, 0x9f, 0x8a, 0xf7, 0xd6, 0x89,
+			    0x1f, 0x7f, 0x83, 0x2b, 0xa8, 0x33, 0xc0, 0x0c,
+			    0x89, 0x2e, 0xbe, 0x30, 0x14, 0x3c, 0xe2, 0x87,
+			    0x40, 0x01, 0x1e, 0xcf },
+		.rlen	= 28,
+	}, {
+		.key	= { 0xef, 0x01, 0x23, 0x45 },
+		.klen	= 4,
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00 },
+		.ilen	= 10,
+		.result	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+			    0xbd, 0x61 },
+		.rlen	= 10,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+		            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 16,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+		.ilen	= 8,
+		.result	= { 0x69, 0x72, 0x36, 0x59, 0x1B, 0x52, 0x42, 0xB1 },
+		.rlen	= 8,
+	},
+};
+
+struct cipher_testvec arc4_dec_tv_template[] =
+{
+	{
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 },
+		.ilen	= 8,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79 },
+		.ilen	= 8,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 8,
+		.input	= { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a },
+		.ilen	= 8,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0xef, 0x01, 0x23, 0x45},
+		.klen	= 4,
+		.input	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+			    0xbd, 0x61, 0x5a, 0x11, 0x62, 0xe1, 0xc7, 0xba,
+			    0x36, 0xb6, 0x78, 0x58 },
+		.ilen	= 20,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00 },
+		.rlen	= 20,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x66, 0xa0, 0x94, 0x9f, 0x8a, 0xf7, 0xd6, 0x89,
+			    0x1f, 0x7f, 0x83, 0x2b, 0xa8, 0x33, 0xc0, 0x0c,
+			    0x89, 0x2e, 0xbe, 0x30, 0x14, 0x3c, 0xe2, 0x87,
+			    0x40, 0x01, 0x1e, 0xcf },
+		.ilen	= 28,
+		.result	= { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78 },
+		.rlen	= 28,
+	}, {
+		.key	= { 0xef, 0x01, 0x23, 0x45 },
+		.klen	= 4,
+		.input	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+			    0xbd, 0x61 },
+		.ilen	= 10,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00 },
+		.rlen	= 10,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+		            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 16,
+		.input	= { 0x69, 0x72, 0x36, 0x59, 0x1B, 0x52, 0x42, 0xB1 },
+		.ilen	= 8,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+		.rlen	= 8,
+	},
+};
+
+
 /*
  * Compression stuff.
  */
diff -urN linux-2.4.26-pre1/drivers/acpi/executer/exfldio.c linux-2.4.26-pre2/drivers/acpi/executer/exfldio.c
--- linux-2.4.26-pre1/drivers/acpi/executer/exfldio.c	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/drivers/acpi/executer/exfldio.c	2004-03-06 11:20:28.000000000 -0800
@@ -154,8 +154,7 @@
 			field_datum_byte_offset, obj_desc->common_field.access_byte_width,
 			acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));
 
-		#ifdef CONFIG_ACPI_RELAXED_AML
-		{
+		if (!acpi_strict) {
 			/*
 			 * Allow access to the field if it is within the region size
 			 * rounded up to a multiple of the access byte width.  This
@@ -186,9 +185,9 @@
 				return_ACPI_STATUS (AE_OK);
 			}
 		}
-		#else
+		else {
 			return_ACPI_STATUS (AE_AML_REGION_LIMIT);
-		#endif
+		}
 	}
 
 	return_ACPI_STATUS (AE_OK);
diff -urN linux-2.4.26-pre1/drivers/acpi/hardware/hwgpe.c linux-2.4.26-pre2/drivers/acpi/hardware/hwgpe.c
--- linux-2.4.26-pre1/drivers/acpi/hardware/hwgpe.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/drivers/acpi/hardware/hwgpe.c	2004-03-06 11:20:28.000000000 -0800
@@ -528,6 +528,14 @@
 	/* Examine each GPE register within the block */
 
 	for (i = 0; i < gpe_block->register_count; i++) {
+		/* Clear the entire status register */
+
+		status = acpi_hw_low_level_write (8, 0xFF,
+				 &gpe_block->register_info[i].status_address);
+		if (ACPI_FAILURE (status)) {
+			return (status);
+		}
+
 		/*
 		 * We previously stored the enabled status of all GPEs.
 		 * Blast them back in.
diff -urN linux-2.4.26-pre1/drivers/acpi/hardware/hwregs.c linux-2.4.26-pre2/drivers/acpi/hardware/hwregs.c
--- linux-2.4.26-pre1/drivers/acpi/hardware/hwregs.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/drivers/acpi/hardware/hwregs.c	2004-03-06 11:20:28.000000000 -0800
@@ -152,11 +152,11 @@
 	/*
 	 * Evaluate the namespace object containing the values for this state
 	 */
-	status = acpi_ns_evaluate_by_name ((char *) acpi_gbl_db_sleep_states[sleep_state],
+	status = acpi_ns_evaluate_by_name ((char *) acpi_gbl_sleep_state_names[sleep_state],
 			  NULL, &obj_desc);
 	if (ACPI_FAILURE (status)) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s while evaluating sleep_state [%s]\n",
-			acpi_format_exception (status), acpi_gbl_db_sleep_states[sleep_state]));
+			acpi_format_exception (status), acpi_gbl_sleep_state_names[sleep_state]));
 
 		return_ACPI_STATUS (status);
 	}
@@ -201,7 +201,7 @@
 
 	if (ACPI_FAILURE (status)) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
-			acpi_gbl_db_sleep_states[sleep_state], obj_desc, acpi_ut_get_object_type_name (obj_desc)));
+			acpi_gbl_sleep_state_names[sleep_state], obj_desc, acpi_ut_get_object_type_name (obj_desc)));
 	}
 
 	acpi_ut_remove_reference (obj_desc);
diff -urN linux-2.4.26-pre1/drivers/acpi/hardware/hwsleep.c linux-2.4.26-pre2/drivers/acpi/hardware/hwsleep.c
--- linux-2.4.26-pre1/drivers/acpi/hardware/hwsleep.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/drivers/acpi/hardware/hwsleep.c	2004-03-06 11:20:28.000000000 -0800
@@ -48,6 +48,19 @@
 	 ACPI_MODULE_NAME    ("hwsleep")
 
 
+#define METHOD_NAME__BFS        "\\_BFS"
+#define METHOD_NAME__GTS        "\\_GTS"
+#define METHOD_NAME__PTS        "\\_PTS"
+#define METHOD_NAME__SST        "\\_SI._SST"
+#define METHOD_NAME__WAK        "\\_WAK"
+
+#define ACPI_SST_INDICATOR_OFF  0
+#define ACPI_SST_WORKING        1
+#define ACPI_SST_WAKING         2
+#define ACPI_SST_SLEEPING       3
+#define ACPI_SST_SLEEP_CONTEXT  4
+
+
 /******************************************************************************
  *
  * FUNCTION:    acpi_set_firmware_waking_vector
@@ -171,19 +184,41 @@
 
 	/* Run the _PTS and _GTS methods */
 
-	status = acpi_evaluate_object (NULL, "\\_PTS", &arg_list, NULL);
+	status = acpi_evaluate_object (NULL, METHOD_NAME__PTS, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		return_ACPI_STATUS (status);
 	}
 
-	status = acpi_evaluate_object (NULL, "\\_GTS", &arg_list, NULL);
+	status = acpi_evaluate_object (NULL, METHOD_NAME__GTS, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		return_ACPI_STATUS (status);
 	}
 
+	/* Setup the argument to _SST */
+
+	switch (sleep_state) {
+	case ACPI_STATE_S0:
+		arg.integer.value = ACPI_SST_WORKING;
+		break;
+
+	case ACPI_STATE_S1:
+	case ACPI_STATE_S2:
+	case ACPI_STATE_S3:
+		arg.integer.value = ACPI_SST_SLEEPING;
+		break;
+
+	case ACPI_STATE_S4:
+		arg.integer.value = ACPI_SST_SLEEP_CONTEXT;
+		break;
+
+	default:
+		arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is indicator off */
+		break;
+	}
+
 	/* Set the system indicators to show the desired sleep state. */
 
-	status = acpi_evaluate_object (NULL, "\\_SI._SST", &arg_list, NULL);
+	status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		 ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
 	}
@@ -477,19 +512,19 @@
 
 	/* Ignore any errors from these methods */
 
-	arg.integer.value = 0;
-	status = acpi_evaluate_object (NULL, "\\_SI._SST", &arg_list, NULL);
+	arg.integer.value = ACPI_SST_WAKING;
+	status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
 	}
 
 	arg.integer.value = sleep_state;
-	status = acpi_evaluate_object (NULL, "\\_BFS", &arg_list, NULL);
+	status = acpi_evaluate_object (NULL, METHOD_NAME__BFS, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		ACPI_REPORT_ERROR (("Method _BFS failed, %s\n", acpi_format_exception (status)));
 	}
 
-	status = acpi_evaluate_object (NULL, "\\_WAK", &arg_list, NULL);
+	status = acpi_evaluate_object (NULL, METHOD_NAME__WAK, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		ACPI_REPORT_ERROR (("Method _WAK failed, %s\n", acpi_format_exception (status)));
 	}
@@ -501,8 +536,25 @@
 		return_ACPI_STATUS (status);
 	}
 
+	/* Enable power button */
+
+	acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id,
+			1, ACPI_MTX_DO_NOT_LOCK);
+	acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id,
+			1, ACPI_MTX_DO_NOT_LOCK);
+
 	/* Enable BM arbitration */
 
 	status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_LOCK);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
+	arg.integer.value = ACPI_SST_WORKING;
+	status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
+	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
+		ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
+	}
+
 	return_ACPI_STATUS (status);
 }
diff -urN linux-2.4.26-pre1/drivers/acpi/namespace/nseval.c linux-2.4.26-pre2/drivers/acpi/namespace/nseval.c
--- linux-2.4.26-pre1/drivers/acpi/namespace/nseval.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/drivers/acpi/namespace/nseval.c	2004-03-06 11:20:28.000000000 -0800
@@ -110,7 +110,7 @@
 
 	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
+		goto cleanup;
 	}
 
 	prefix_node = acpi_ns_map_handle_to_node (handle);
@@ -197,7 +197,7 @@
 
 	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
+		goto cleanup;
 	}
 
 	/* Lookup the name in the namespace */
diff -urN linux-2.4.26-pre1/drivers/acpi/namespace/nsutils.c linux-2.4.26-pre2/drivers/acpi/namespace/nsutils.c
--- linux-2.4.26-pre1/drivers/acpi/namespace/nsutils.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/drivers/acpi/namespace/nsutils.c	2004-03-06 11:20:28.000000000 -0800
@@ -918,7 +918,7 @@
 
 	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
+		goto cleanup;
 	}
 
 	/* Setup lookup scope (search starting point) */
@@ -936,10 +936,10 @@
 				internal_path, acpi_format_exception (status)));
 	}
 
-	/* Cleanup */
-
 	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 
+cleanup:
+	/* Cleanup */
 	if (internal_path) {
 		ACPI_MEM_FREE (internal_path);
 	}
diff -urN linux-2.4.26-pre1/drivers/acpi/namespace/nsxfname.c linux-2.4.26-pre2/drivers/acpi/namespace/nsxfname.c
--- linux-2.4.26-pre1/drivers/acpi/namespace/nsxfname.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/drivers/acpi/namespace/nsxfname.c	2004-03-06 11:20:28.000000000 -0800
@@ -326,6 +326,13 @@
 			info.valid |= ACPI_VALID_ADR;
 		}
 
+		/* Execute the Device._sx_d methods */
+
+		status = acpi_ut_execute_sxds (node, info.highest_dstates);
+		if (ACPI_SUCCESS (status)) {
+			info.valid |= ACPI_VALID_STA;
+		}
+
 		status = AE_OK;
 	}
 
diff -urN linux-2.4.26-pre1/drivers/acpi/pci_link.c linux-2.4.26-pre2/drivers/acpi/pci_link.c
--- linux-2.4.26-pre1/drivers/acpi/pci_link.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-pre2/drivers/acpi/pci_link.c	2004-03-06 11:20:28.000000000 -0800
@@ -767,7 +767,6 @@
 
 static int __init acpi_irq_nobalance_set(char *str)
 {
-printk("ACPI STATIC SET\n");
 	acpi_irq_balance = 0;
 	return(1);
 }
@@ -775,7 +774,6 @@
 
 int __init acpi_irq_balance_set(char *str)
 {
-printk("ACPI BALANCE SET\n");
 	acpi_irq_balance = 1;
 	return(1);
 }
diff -urN linux-2.4.26-pre1/drivers/acpi/resources/rsxface.c linux-2.4.26-pre2/drivers/acpi/resources/rsxface.c
--- linux-2.4.26-pre1/drivers/acpi/resources/rsxface.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/drivers/acpi/resources/rsxface.c	2004-03-06 11:20:28.000000000 -0800
@@ -239,6 +239,7 @@
 	acpi_status                         status;
 	struct acpi_buffer                  buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 	struct acpi_resource                *resource;
+	struct acpi_resource                *buffer_end;
 
 
 	ACPI_FUNCTION_TRACE ("acpi_walk_resources");
@@ -255,7 +256,13 @@
 		return_ACPI_STATUS (status);
 	}
 
-	resource = (struct acpi_resource *) buffer.pointer;
+	/* Setup pointers */
+
+	resource  = (struct acpi_resource *) buffer.pointer;
+	buffer_end = (struct acpi_resource *) ((u8 *) buffer.pointer + buffer.length);
+
+	/* Walk the resource list */
+
 	for (;;) {
 		if (!resource || resource->id == ACPI_RSTYPE_END_TAG) {
 			break;
@@ -268,6 +275,7 @@
 		case AE_CTRL_DEPTH:
 
 			/* Just keep going */
+
 			status = AE_OK;
 			break;
 
@@ -285,7 +293,15 @@
 			goto cleanup;
 		}
 
+		/* Get the next resource descriptor */
+
 		resource = ACPI_NEXT_RESOURCE (resource);
+
+		/* Check for end-of-buffer */
+
+		if (resource >= buffer_end) {
+			goto cleanup;
+		}
 	}
 
 cleanup:
diff -urN linux-2.4.26-pre1/drivers/acpi/system.c linux-2.4.26-pre2/drivers/acpi/system.c
--- linux-2.4.26-pre1/drivers/acpi/system.c	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/drivers/acpi/system.c	2004-03-06 11:20:28.000000000 -0800
@@ -41,14 +41,18 @@
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
-#ifdef CONFIG_X86
 #ifdef CONFIG_ACPI_SLEEP
 #include <linux/mc146818rtc.h>
 #include <linux/irq.h>
 #include <asm/hw_irq.h>
-#endif
-#endif
 
+acpi_status acpi_system_save_state(u32);
+#else
+static inline acpi_status acpi_system_save_state(u32 state)
+{
+	return AE_OK;
+}
+#endif /* !CONFIG_ACPI_SLEEP */
 
 #define _COMPONENT		ACPI_SYSTEM_COMPONENT
 ACPI_MODULE_NAME		("acpi_system")
diff -urN linux-2.4.26-pre1/drivers/acpi/utilities/uteval.c linux-2.4.26-pre2/drivers/acpi/utilities/uteval.c
--- linux-2.4.26-pre1/drivers/acpi/utilities/uteval.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/drivers/acpi/utilities/uteval.c	2004-03-06 11:20:28.000000000 -0800
@@ -562,3 +562,63 @@
 	acpi_ut_remove_reference (obj_desc);
 	return_ACPI_STATUS (status);
 }
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_execute_Sxds
+ *
+ * PARAMETERS:  device_node         - Node for the device
+ *              *Flags              - Where the status flags are returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Executes _STA for selected device and stores results in
+ *              *Flags.
+ *
+ *              NOTE: Internal function, no parameter validation
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_execute_sxds (
+	struct acpi_namespace_node      *device_node,
+	u8                              *highest)
+{
+	union acpi_operand_object       *obj_desc;
+	acpi_status                     status;
+	u32                             i;
+
+
+	ACPI_FUNCTION_TRACE ("ut_execute_Sxds");
+
+
+	for (i = 0; i < 4; i++) {
+		highest[i] = 0xFF;
+		status = acpi_ut_evaluate_object (device_node,
+				 (char *) acpi_gbl_highest_dstate_names[i],
+				 ACPI_BTYPE_INTEGER, &obj_desc);
+		if (ACPI_FAILURE (status)) {
+			if (status != AE_NOT_FOUND) {
+				ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+					"%s on Device %4.4s, %s\n",
+					(char *) acpi_gbl_highest_dstate_names[i],
+					acpi_ut_get_node_name (device_node),
+					acpi_format_exception (status)));
+
+				return_ACPI_STATUS (status);
+			}
+		}
+		else {
+			/* Extract the Dstate value */
+
+			highest[i] = (u8) obj_desc->integer.value;
+
+			/* Delete the return object */
+
+			acpi_ut_remove_reference (obj_desc);
+		}
+	}
+
+	return_ACPI_STATUS (AE_OK);
+}
diff -urN linux-2.4.26-pre1/drivers/acpi/utilities/utglobal.c linux-2.4.26-pre2/drivers/acpi/utilities/utglobal.c
--- linux-2.4.26-pre1/drivers/acpi/utilities/utglobal.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/drivers/acpi/utilities/utglobal.c	2004-03-06 11:20:28.000000000 -0800
@@ -171,7 +171,7 @@
 
 const u8                            acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128};
 
-const char                          *acpi_gbl_db_sleep_states[ACPI_S_STATE_COUNT] = {
+const char                          *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = {
 			  "\\_S0_",
 			  "\\_S1_",
 			  "\\_S2_",
@@ -179,6 +179,11 @@
 			  "\\_S4_",
 			  "\\_S5_"};
 
+const char                          *acpi_gbl_highest_dstate_names[4] = {
+					   "_S1D",
+					   "_S2D",
+					   "_S3D",
+					   "_S4D"};
 
 /******************************************************************************
  *
diff -urN linux-2.4.26-pre1/drivers/net/8139too.c linux-2.4.26-pre2/drivers/net/8139too.c
--- linux-2.4.26-pre1/drivers/net/8139too.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/drivers/net/8139too.c	2004-03-06 11:20:28.000000000 -0800
@@ -255,6 +255,10 @@
 	{0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 	{0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 	{0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+	{0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+	{0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+	{0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+	{0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 
 #ifdef CONFIG_SH_SECUREEDGE5410
 	/* Bogus 8139 silicon reports 8129 without external PROM :-( */
diff -urN linux-2.4.26-pre1/drivers/net/bonding/bond_3ad.c linux-2.4.26-pre2/drivers/net/bonding/bond_3ad.c
--- linux-2.4.26-pre1/drivers/net/bonding/bond_3ad.c	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/drivers/net/bonding/bond_3ad.c	2004-03-06 11:20:28.000000000 -0800
@@ -2362,6 +2362,7 @@
 	int agg_id;
 	int i;
 	struct ad_info ad_info;
+	int res = 1;
 
 	/* make sure that the slaves list will
 	 * not change during tx
@@ -2369,12 +2370,12 @@
 	read_lock(&bond->lock);
 
 	if (!BOND_IS_OK(bond)) {
-		goto free_out;
+		goto out;
 	}
 
 	if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
 		printk(KERN_DEBUG "ERROR: bond_3ad_get_active_agg_info failed\n");
-		goto free_out;
+		goto out;
 	}
 
 	slaves_in_agg = ad_info.ports;
@@ -2383,7 +2384,7 @@
 	if (slaves_in_agg == 0) {
 		/*the aggregator is empty*/
 		printk(KERN_DEBUG "ERROR: active aggregator is empty\n");
-		goto free_out;
+		goto out;
 	}
 
 	slave_agg_no = (data->h_dest[5]^bond->dev->dev_addr[5]) % slaves_in_agg;
@@ -2401,7 +2402,7 @@
 
 	if (slave_agg_no >= 0) {
 		printk(KERN_ERR DRV_NAME ": Error: Couldn't find a slave to tx on for aggregator ID %d\n", agg_id);
-		goto free_out;
+		goto out;
 	}
 
 	start_at = slave;
@@ -2414,24 +2415,19 @@
 			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);
-
-			goto out;
+		if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) {
+			res = bond_dev_queue_xmit(bond, skb, slave->dev);
+			break;
 		}
 	}
 
 out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
 	read_unlock(&bond->lock);
 	return 0;
-
-free_out:
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
-	goto out;
 }
 
 int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype)
diff -urN linux-2.4.26-pre1/drivers/net/bonding/bond_alb.c linux-2.4.26-pre2/drivers/net/bonding/bond_alb.c
--- linux-2.4.26-pre1/drivers/net/bonding/bond_alb.c	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/drivers/net/bonding/bond_alb.c	2004-03-06 11:20:28.000000000 -0800
@@ -34,6 +34,9 @@
  *
  * 2003/12/30 - Amir Noam <amir.noam at intel dot com>
  *	- Fixed: Cannot remove and re-enslave the original active slave.
+ *
+ * 2004/01/14 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Add capability to tag self generated packets in ALB/TLB modes.
  */
 
 //#define BONDING_DEBUG 1
@@ -50,6 +53,7 @@
 #include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <linux/if_bonding.h>
+#include <linux/if_vlan.h>
 #include <net/ipx.h>
 #include <net/arp.h>
 #include <asm/byteorder.h>
@@ -79,7 +83,7 @@
 
 
 #define TLB_NULL_INDEX		0xffffffff
-#define MAX_LP_RETRY		3
+#define MAX_LP_BURST		3
 
 /* rlb defs */
 #define RLB_HASH_TABLE_SIZE	256
@@ -498,13 +502,33 @@
 	}
 
 	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);
+		struct sk_buff *skb;
+
+		skb = arp_create(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);
+		if (!skb) {
+			printk(KERN_ERR DRV_NAME
+			       ": Error: failed to create an ARP packet\n");
+			continue;
+		}
+
+		skb->dev = client_info->slave->dev;
+
+		if (client_info->tag) {
+			skb = vlan_put_tag(skb, client_info->vlan_id);
+			if (!skb) {
+				printk(KERN_ERR DRV_NAME
+				       ": Error: failed to insert VLAN tag\n");
+				continue;
+			}
+		}
+
+		arp_xmit(skb);
 	}
 }
 
@@ -603,9 +627,10 @@
 }
 
 /* Caller must hold both bond and ptr locks for read */
-struct slave *rlb_choose_channel(struct bonding *bond, struct arp_pkt *arp)
+struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct arp_pkt *arp = (struct arp_pkt *)skb->nh.raw;
 	struct slave *assigned_slave;
 	struct rlb_client_info *client_info;
 	u32 hash_index = 0;
@@ -661,6 +686,15 @@
 			client_info->ntt = 0;
 		}
 
+		if (!list_empty(&bond->vlan_list)) {
+			unsigned short vlan_id;
+			int res = vlan_get_tag(skb, &vlan_id);
+			if (!res) {
+				client_info->tag = 1;
+				client_info->vlan_id = vlan_id;
+			}
+		}
+
 		if (!client_info->assigned) {
 			u32 prev_tbl_head = bond_info->rx_hashtbl_head;
 			bond_info->rx_hashtbl_head = hash_index;
@@ -691,7 +725,7 @@
 		/* the arp must be sent on the selected
 		* rx channel
 		*/
-		tx_slave = rlb_choose_channel(bond, arp);
+		tx_slave = rlb_choose_channel(skb, bond);
 		if (tx_slave) {
 			memcpy(arp->mac_src,tx_slave->dev->dev_addr, ETH_ALEN);
 		}
@@ -702,7 +736,7 @@
 		 * When the arp reply is received the entry will be updated
 		 * with the correct unicast address of the client.
 		 */
-		rlb_choose_channel(bond, arp);
+		rlb_choose_channel(skb, bond);
 
 		/* The ARP relpy packets must be delayed so that
 		 * they can cancel out the influence of the ARP request.
@@ -809,6 +843,40 @@
 
 	kfree(bond_info->rx_hashtbl);
 	bond_info->rx_hashtbl = NULL;
+	bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
+
+	_unlock_rx_hashtbl(bond);
+}
+
+static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
+{
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	u32 curr_index;
+
+	_lock_rx_hashtbl(bond);
+
+	curr_index = bond_info->rx_hashtbl_head;
+	while (curr_index != RLB_NULL_INDEX) {
+		struct rlb_client_info *curr = &(bond_info->rx_hashtbl[curr_index]);
+		u32 next_index = bond_info->rx_hashtbl[curr_index].next;
+		u32 prev_index = bond_info->rx_hashtbl[curr_index].prev;
+
+		if (curr->tag && (curr->vlan_id == vlan_id)) {
+			if (curr_index == bond_info->rx_hashtbl_head) {
+				bond_info->rx_hashtbl_head = next_index;
+			}
+			if (prev_index != RLB_NULL_INDEX) {
+				bond_info->rx_hashtbl[prev_index].next = next_index;
+			}
+			if (next_index != RLB_NULL_INDEX) {
+				bond_info->rx_hashtbl[next_index].prev = prev_index;
+			}
+
+			rlb_init_table_entry(curr);
+		}
+
+		curr_index = next_index;
+	}
 
 	_unlock_rx_hashtbl(bond);
 }
@@ -817,6 +885,7 @@
 
 static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
 {
+	struct bonding *bond = bond_get_bond_by_slave(slave);
 	struct learning_pkt pkt;
 	int size = sizeof(struct learning_pkt);
 	int i;
@@ -826,7 +895,7 @@
 	memcpy(pkt.mac_src, mac_addr, ETH_ALEN);
 	pkt.type = __constant_htons(ETH_P_LOOP);
 
-	for (i = 0; i < MAX_LP_RETRY; i++) {
+	for (i = 0; i < MAX_LP_BURST; i++) {
 		struct sk_buff *skb;
 		char *data;
 
@@ -844,6 +913,26 @@
 		skb->priority = TC_PRIO_CONTROL;
 		skb->dev = slave->dev;
 
+		if (!list_empty(&bond->vlan_list)) {
+			struct vlan_entry *vlan;
+
+			vlan = bond_next_vlan(bond,
+					      bond->alb_info.current_alb_vlan);
+
+			bond->alb_info.current_alb_vlan = vlan;
+			if (!vlan) {
+				kfree_skb(skb);
+				continue;
+			}
+
+			skb = vlan_put_tag(skb, vlan->vlan_id);
+			if (!skb) {
+				printk(KERN_ERR DRV_NAME
+				       ": Error: failed to insert VLAN tag\n");
+				continue;
+			}
+		}
+
 		dev_queue_xmit(skb);
 	}
 }
@@ -1194,6 +1283,7 @@
 	int do_tx_balance = 1;
 	u32 hash_index = 0;
 	u8 *hash_start = NULL;
+	int res = 1;
 
 	/* make sure that the curr_active_slave and the slaves list do
 	 * not change during tx
@@ -1202,7 +1292,7 @@
 	read_lock(&bond->curr_slave_lock);
 
 	if (!BOND_IS_OK(bond)) {
-		goto free_out;
+		goto out;
 	}
 
 	switch (ntohs(skb->protocol)) {
@@ -1267,29 +1357,27 @@
 	}
 
 	if (tx_slave && SLAVE_IS_OK(tx_slave)) {
-		skb->dev = tx_slave->dev;
 		if (tx_slave != bond->curr_active_slave) {
 			memcpy(eth_data->h_source,
 			       tx_slave->dev->dev_addr,
 			       ETH_ALEN);
 		}
-		dev_queue_xmit(skb);
+
+		res = bond_dev_queue_xmit(bond, skb, tx_slave->dev);
 	} else {
-		/* no suitable interface, frame not sent */
 		if (tx_slave) {
 			tlb_clear_slave(bond, tx_slave, 0);
 		}
-		goto free_out;
 	}
 
 out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
 	read_unlock(&bond->curr_slave_lock);
 	read_unlock(&bond->lock);
 	return 0;
-
-free_out:
-	dev_kfree_skb(skb);
-	goto out;
 }
 
 void bond_alb_monitor(struct bonding *bond)
@@ -1590,3 +1678,15 @@
 	return 0;
 }
 
+void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
+{
+	if (bond->alb_info.current_alb_vlan &&
+	    (bond->alb_info.current_alb_vlan->vlan_id == vlan_id)) {
+		bond->alb_info.current_alb_vlan = NULL;
+	}
+
+	if (bond->alb_info.rlb_enabled) {
+		rlb_clear_vlan(bond, vlan_id);
+	}
+}
+
diff -urN linux-2.4.26-pre1/drivers/net/bonding/bond_alb.h linux-2.4.26-pre2/drivers/net/bonding/bond_alb.h
--- linux-2.4.26-pre1/drivers/net/bonding/bond_alb.h	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/drivers/net/bonding/bond_alb.h	2004-03-06 11:20:28.000000000 -0800
@@ -77,6 +77,8 @@
 	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 */
+	u8 tag;			/* flag - need to tag skb */
+	unsigned short vlan_id;	/* VLAN tag associated with IP address */
 };
 
 struct tlb_slave_info {
@@ -122,6 +124,7 @@
 						 * rx traffic should be
 						 * rebalanced
 						 */
+	struct vlan_entry	*current_alb_vlan;
 };
 
 int bond_alb_initialize(struct bonding *bond, int rlb_enabled);
@@ -133,6 +136,6 @@
 int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev);
 void bond_alb_monitor(struct bonding *bond);
 int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr);
-
+void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id);
 #endif /* __BOND_ALB_H__ */
 
diff -urN linux-2.4.26-pre1/drivers/net/bonding/bond_main.c linux-2.4.26-pre2/drivers/net/bonding/bond_main.c
--- linux-2.4.26-pre1/drivers/net/bonding/bond_main.c	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/drivers/net/bonding/bond_main.c	2004-03-06 11:20:28.000000000 -0800
@@ -455,12 +455,20 @@
  *
  * 2003/12/30 - Amir Noam <amir.noam at intel dot com>
  *	- Fixed: Cannot remove and re-enslave the original active slave.
- *	- Fixed: Releasing the original active slave causes mac address duplication.
+ *	- Fixed: Releasing the original active slave causes mac address
+ *		 duplication.
  *	- Add support for slaves that use ethtool_ops.
  *	  Set version to 2.5.3.
  *
  * 2004/01/05 - Amir Noam <amir.noam at intel dot com>
  *	- Save bonding parameters per bond instead of using the global values.
+ *	  Set version to 2.5.4.
+ *
+ * 2004/01/14 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Enhance VLAN support:
+ *	  * Add support for VLAN hardware acceleration capable slaves.
+ *	  * Add capability to tag self generated packets in ALB/TLB modes.
+ *	  Set version to 2.6.0.
  */
 
 //#define BONDING_DEBUG 1
@@ -502,6 +510,7 @@
 #include <net/arp.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
+#include <linux/if_vlan.h>
 #include <linux/if_bonding.h>
 #include "bonding.h"
 #include "bond_3ad.h"
@@ -620,6 +629,371 @@
 	}
 }
 
+/*---------------------------------- VLAN -----------------------------------*/
+
+/**
+ * bond_add_vlan - add a new vlan id on bond
+ * @bond: bond that got the notification
+ * @vlan_id: the vlan id to add
+ *
+ * Returns -ENOMEM if allocation failed.
+ */
+static int bond_add_vlan(struct bonding *bond, unsigned short vlan_id)
+{
+	struct vlan_entry *vlan;
+
+	dprintk("bond: %s, vlan id %d\n",
+		(bond ? bond->dev->name: "None"), vlan_id);
+
+	vlan = kmalloc(sizeof(struct vlan_entry), GFP_KERNEL);
+	if (!vlan) {
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&vlan->vlan_list);
+	vlan->vlan_id = vlan_id;
+
+	write_lock_bh(&bond->lock);
+
+	list_add_tail(&vlan->vlan_list, &bond->vlan_list);
+
+	write_unlock_bh(&bond->lock);
+
+	dprintk("added VLAN ID %d on bond %s\n", vlan_id, bond->dev->name);
+
+	return 0;
+}
+
+/**
+ * bond_del_vlan - delete a vlan id from bond
+ * @bond: bond that got the notification
+ * @vlan_id: the vlan id to delete
+ *
+ * returns -ENODEV if @vlan_id was not found in @bond.
+ */
+static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id)
+{
+	struct vlan_entry *vlan, *next;
+	int res = -ENODEV;
+
+	dprintk("bond: %s, vlan id %d\n", bond->dev->name, vlan_id);
+
+	write_lock_bh(&bond->lock);
+
+	list_for_each_entry_safe(vlan, next, &bond->vlan_list, vlan_list) {
+		if (vlan->vlan_id == vlan_id) {
+			list_del(&vlan->vlan_list);
+
+			if ((bond->params.mode == BOND_MODE_TLB) ||
+			    (bond->params.mode == BOND_MODE_ALB)) {
+				bond_alb_clear_vlan(bond, vlan_id);
+			}
+
+			dprintk("removed VLAN ID %d from bond %s\n", vlan_id,
+				bond->dev->name);
+
+			kfree(vlan);
+
+			if (list_empty(&bond->vlan_list) &&
+			    (bond->slave_cnt == 0)) {
+				/* Last VLAN removed and no slaves, so
+				 * restore block on adding VLANs. This will
+				 * be removed once new slaves that are not
+				 * VLAN challenged will be added.
+				 */
+				bond->dev->features |= NETIF_F_VLAN_CHALLENGED;
+			}
+
+			res = 0;
+			goto out;
+		}
+	}
+
+	dprintk("couldn't find VLAN ID %d in bond %s\n", vlan_id,
+		bond->dev->name);
+
+out:
+	write_unlock_bh(&bond->lock);
+	return res;
+}
+
+/**
+ * bond_has_challenged_slaves
+ * @bond: the bond we're working on
+ *
+ * Searches the slave list. Returns 1 if a vlan challenged slave
+ * was found, 0 otherwise.
+ *
+ * Assumes bond->lock is held.
+ */
+static int bond_has_challenged_slaves(struct bonding *bond)
+{
+	struct slave *slave;
+	int i;
+
+	bond_for_each_slave(bond, slave, i) {
+		if (slave->dev->features & NETIF_F_VLAN_CHALLENGED) {
+			dprintk("found VLAN challenged slave - %s\n",
+				slave->dev->name);
+			return 1;
+		}
+	}
+
+	dprintk("no VLAN challenged slaves found\n");
+	return 0;
+}
+
+/**
+ * bond_next_vlan - safely skip to the next item in the vlans list.
+ * @bond: the bond we're working on
+ * @curr: item we're advancing from
+ *
+ * Returns %NULL if list is empty, bond->next_vlan if @curr is %NULL,
+ * or @curr->next otherwise (even if it is @curr itself again).
+ * 
+ * Caller must hold bond->lock
+ */
+struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr)
+{
+	struct vlan_entry *next, *last;
+
+	if (list_empty(&bond->vlan_list)) {
+		return NULL;
+	}
+
+	if (!curr) {
+		next = list_entry(bond->vlan_list.next,
+				  struct vlan_entry, vlan_list);
+	} else {
+		last = list_entry(bond->vlan_list.prev,
+				  struct vlan_entry, vlan_list);
+		if (last == curr) {
+			next = list_entry(bond->vlan_list.next,
+					  struct vlan_entry, vlan_list);
+		} else {
+			next = list_entry(curr->vlan_list.next,
+					  struct vlan_entry, vlan_list);
+		}
+	}
+
+	return next;
+}
+
+/**
+ * bond_dev_queue_xmit - Prepare skb for xmit.
+ * 
+ * @bond: bond device that got this skb for tx.
+ * @skb: hw accel VLAN tagged skb to transmit
+ * @slave_dev: slave that is supposed to xmit this skbuff
+ * 
+ * When the bond gets an skb to tarnsmit that is
+ * already hardware accelerated VLAN tagged, and it
+ * needs to relay this skb to a slave that is not
+ * hw accel capable, the skb needs to be "unaccelerated",
+ * i.e. strip the hwaccel tag and re-insert it as part
+ * of the payload.
+ * 
+ * Assumption - once a VLAN device is created over the bond device, all
+ * packets are going to be hardware accelerated VLAN tagged since the IP
+ * binding is done over the VLAN device
+ */
+int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev)
+{
+	unsigned short vlan_id;
+	int res;
+
+	if (!list_empty(&bond->vlan_list) &&
+	    !(slave_dev->features & NETIF_F_HW_VLAN_TX)) {
+		res = vlan_get_tag(skb, &vlan_id);
+		if (res) {
+			return -EINVAL;
+		}
+
+		skb->dev = slave_dev;
+		skb = vlan_put_tag(skb, vlan_id);
+		if (!skb) {
+			/* vlan_put_tag() frees the skb in case of error,
+			 * so return success here so the calling functions
+			 * won't attempt to free is again.
+			 */
+			return 0;
+		}
+	} else {
+		skb->dev = slave_dev;
+	}
+
+	skb->priority = 1;
+	dev_queue_xmit(skb);
+
+	return 0;
+}
+
+/*
+ * In the following 3 functions, bond_vlan_rx_register(), bond_vlan_rx_add_vid
+ * and bond_vlan_rx_kill_vid, We don't protect the slave list iteration with a
+ * lock because:
+ * a. This operation is performed in IOCTL context,
+ * b. The operation is protected by the RTNL semaphore in the 8021q code,
+ * c. Holding a lock with BH disabled while directly calling a base driver
+ *    entry point is generally a BAD idea.
+ * 
+ * The design of synchronization/protection for this operation in the 8021q
+ * module is good for one or more VLAN devices over a single physical device
+ * and cannot be extended for a teaming solution like bonding, so there is a
+ * potential race condition here where a net device from the vlan group might
+ * be referenced (either by a base driver or the 8021q code) while it is being
+ * removed from the system. However, it turns out we're not making matters
+ * worse, and if it works for regular VLAN usage it will work here too.
+*/
+
+/**
+ * bond_vlan_rx_register - Propagates registration to slaves
+ * @bond_dev: bonding net device that got called
+ * @grp: vlan group being registered
+ */
+static void bond_vlan_rx_register(struct net_device *bond_dev, struct vlan_group *grp)
+{
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave;
+	int i;
+
+	bond->vlgrp = grp;
+
+	bond_for_each_slave(bond, slave, i) {
+		struct net_device *slave_dev = slave->dev;
+
+		if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
+		    slave_dev->vlan_rx_register) {
+			slave_dev->vlan_rx_register(slave_dev, grp);
+		}
+	}
+}
+
+/**
+ * bond_vlan_rx_add_vid - Propagates adding an id to slaves
+ * @bond_dev: bonding net device that got called
+ * @vid: vlan id being added
+ */
+static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid)
+{
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave;
+	int i, res;
+
+	bond_for_each_slave(bond, slave, i) {
+		struct net_device *slave_dev = slave->dev;
+
+		if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
+		    slave_dev->vlan_rx_add_vid) {
+			slave_dev->vlan_rx_add_vid(slave_dev, vid);
+		}
+	}
+
+	res = bond_add_vlan(bond, vid);
+	if (res) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Failed to add vlan id %d\n",
+		       bond_dev->name, vid);
+	}
+}
+
+/**
+ * bond_vlan_rx_kill_vid - Propagates deleting an id to slaves
+ * @bond_dev: bonding net device that got called
+ * @vid: vlan id being removed
+ */
+static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
+{
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave;
+	struct net_device *vlan_dev;
+	int i, res;
+
+	bond_for_each_slave(bond, slave, i) {
+		struct net_device *slave_dev = slave->dev;
+
+		if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
+		    slave_dev->vlan_rx_kill_vid) {
+			/* Save and then restore vlan_dev in the grp array,
+			 * since the slave's driver might clear it.
+			 */
+			vlan_dev = bond->vlgrp->vlan_devices[vid];
+			slave_dev->vlan_rx_kill_vid(slave_dev, vid);
+			bond->vlgrp->vlan_devices[vid] = vlan_dev;
+		}
+	}
+
+	res = bond_del_vlan(bond, vid);
+	if (res) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Failed to remove vlan id %d\n",
+		       bond_dev->name, vid);
+	}
+}
+
+static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *slave_dev)
+{
+	struct vlan_entry *vlan;
+
+	write_lock_bh(&bond->lock);
+
+	if (list_empty(&bond->vlan_list)) {
+		goto out;
+	}
+
+	if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
+	    slave_dev->vlan_rx_register) {
+		slave_dev->vlan_rx_register(slave_dev, bond->vlgrp);
+	}
+
+	if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
+	    !(slave_dev->vlan_rx_add_vid)) {
+		goto out;
+	}
+
+	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+		slave_dev->vlan_rx_add_vid(slave_dev, vlan->vlan_id);
+	}
+
+out:
+	write_unlock_bh(&bond->lock);
+}
+
+static void bond_del_vlans_from_slave(struct bonding *bond, struct net_device *slave_dev)
+{
+	struct vlan_entry *vlan;
+	struct net_device *vlan_dev;
+
+	write_lock_bh(&bond->lock);
+
+	if (list_empty(&bond->vlan_list)) {
+		goto out;
+	}
+
+	if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
+	    !(slave_dev->vlan_rx_kill_vid)) {
+		goto unreg;
+	}
+
+	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+		/* Save and then restore vlan_dev in the grp array,
+		 * since the slave's driver might clear it.
+		 */
+		vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id];
+		slave_dev->vlan_rx_kill_vid(slave_dev, vlan->vlan_id);
+		bond->vlgrp->vlan_devices[vlan->vlan_id] = vlan_dev;
+	}
+
+unreg:
+	if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
+	    slave_dev->vlan_rx_register) {
+		slave_dev->vlan_rx_register(slave_dev, NULL);
+	}
+
+out:
+	write_unlock_bh(&bond->lock);
+}
+
 /*------------------------------- Link status -------------------------------*/
 
 /*
@@ -1214,6 +1588,7 @@
 	struct dev_mc_list *dmi;
 	struct sockaddr addr;
 	int link_reporting;
+	int old_features = bond_dev->features;
 	int res = 0;
 
 	if (slave_dev->do_ioctl == NULL) {
@@ -1234,6 +1609,36 @@
 		return -EBUSY;
 	}
 
+	/* vlan challenged mutual exclusion */
+	/* no need to lock since we're protected by rtnl_lock */
+	if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
+		dprintk("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
+		if (!list_empty(&bond->vlan_list)) {
+			printk(KERN_ERR DRV_NAME
+			       ": Error: cannot enslave VLAN "
+			       "challenged slave %s on VLAN enabled "
+			       "bond %s\n", slave_dev->name,
+			       bond_dev->name);
+			return -EPERM;
+		} else {
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: enslaved VLAN challenged "
+			       "slave %s. Adding VLANs will be blocked as "
+			       "long as %s is part of bond %s\n",
+			       slave_dev->name, slave_dev->name,
+			       bond_dev->name);
+			bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
+		}
+	} else {
+		dprintk("%s: ! NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
+		if (bond->slave_cnt == 0) {
+			/* First slave, and it is not VLAN challenged,
+			 * so remove the block of adding VLANs over the bond.
+			 */
+			bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED;
+		}
+	}
+
 	if (app_abi_ver >= 1) {
 		/* The application is using an ABI, which requires the
 		 * slave interface to be closed.
@@ -1242,7 +1647,8 @@
 			printk(KERN_ERR DRV_NAME
 			       ": Error: %s is up\n",
 			       slave_dev->name);
-			return -EPERM;
+			res = -EPERM;
+			goto err_undo_flags;
 		}
 
 		if (slave_dev->set_mac_address == NULL) {
@@ -1253,7 +1659,8 @@
 			       "Your kernel likely does not support slave "
 			       "devices.\n");
 
-			return -EOPNOTSUPP;
+			res = -EOPNOTSUPP;
+			goto err_undo_flags;
 		}
 	} else {
 		/* The application is not using an ABI, which requires the
@@ -1263,7 +1670,8 @@
 			printk(KERN_ERR DRV_NAME
 			       ": Error: %s is not running\n",
 			       slave_dev->name);
-			return -EINVAL;
+			res = -EINVAL;
+			goto err_undo_flags;
 		}
 
 		if ((bond->params.mode == BOND_MODE_8023AD) ||
@@ -1273,13 +1681,15 @@
 			       ": Error: to use %s mode, you must upgrade "
 			       "ifenslave.\n",
 			       bond_mode_name(bond->params.mode));
-			return -EOPNOTSUPP;
+			res = -EOPNOTSUPP;
+			goto err_undo_flags;
 		}
 	}
 
 	new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL);
 	if (!new_slave) {
-		return -ENOMEM;
+		res = -ENOMEM;
+		goto err_undo_flags;
 	}
 
 	memset(new_slave, 0, sizeof(struct slave));
@@ -1368,6 +1778,8 @@
 		dev_mc_add(slave_dev, lacpdu_multicast, ETH_ALEN, 0);
 	}
 
+	bond_add_vlans_on_slave(bond, slave_dev);
+
 	write_lock_bh(&bond->lock);
 
 	bond_attach_slave(bond, new_slave);
@@ -1576,6 +1988,10 @@
 
 err_free:
 	kfree(new_slave);
+
+err_undo_flags:
+	bond_dev->features = old_features;
+
 	return res;
 }
 
@@ -1689,8 +2105,37 @@
 		}
 	}
 
+	if (bond->slave_cnt == 0) {
+		/* 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
+		 */
+		memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
+
+		if (list_empty(&bond->vlan_list)) {
+			bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
+		} else {
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: clearing HW address of %s while it "
+			       "still has VLANs.\n",
+			       bond_dev->name);
+			printk(KERN_WARNING DRV_NAME
+			       ": When re-adding slaves, make sure the bond's "
+			       "HW address matches its VLANs'.\n");
+		}
+	} else if ((bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
+		   !bond_has_challenged_slaves(bond)) {
+		printk(KERN_INFO DRV_NAME
+		       ": last VLAN challenged slave %s "
+		       "left bond %s. VLAN blocking is removed\n",
+		       slave_dev->name, bond_dev->name);
+		bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED;
+	}
+
 	write_unlock_bh(&bond->lock);
 
+	bond_del_vlans_from_slave(bond, slave_dev);
+
 	/* If the mode USES_PRIMARY, then we should only remove its
 	 * promisc and mc settings if it was the curr_active_slave, but that was
 	 * already taken care of above when we detached the slave
@@ -1732,14 +2177,6 @@
 
 	kfree(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->slave_cnt == 0) {
-		memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
-	}
-
 	return 0;  /* deletion OK */
 }
 
@@ -1788,6 +2225,8 @@
 		 */
 		write_unlock_bh(&bond->lock);
 
+		bond_del_vlans_from_slave(bond, slave_dev);
+
 		/* If the mode USES_PRIMARY, then we should only remove its
 		 * promisc and mc settings if it was the curr_active_slave, but that was
 		 * already taken care of above when we detached the slave
@@ -1838,6 +2277,18 @@
 	 */
 	memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
 
+	if (list_empty(&bond->vlan_list)) {
+		bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
+	} else {
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: clearing HW address of %s while it "
+		       "still has VLANs.\n",
+		       bond_dev->name);
+		printk(KERN_WARNING DRV_NAME
+		       ": When re-adding slaves, make sure the bond's "
+		       "HW address matches its VLANs'.\n");
+	}
+
 	printk(KERN_INFO DRV_NAME
 	       ": %s: released all slaves\n",
 	       bond_dev->name);
@@ -3570,11 +4021,12 @@
 	struct bonding *bond = bond_dev->priv;
 	struct slave *slave, *start_at;
 	int i;
+	int res = 1;
 
 	read_lock(&bond->lock);
 
 	if (!BOND_IS_OK(bond)) {
-		goto free_out;
+		goto out;
 	}
 
 	read_lock(&bond->curr_slave_lock);
@@ -3582,33 +4034,31 @@
 	read_unlock(&bond->curr_slave_lock);
 
 	if (!slave) {
-		goto free_out;
+		goto out;
 	}
 
 	bond_for_each_slave_from(bond, slave, i, start_at) {
 		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);
+			res = bond_dev_queue_xmit(bond, skb, slave->dev);
 
 			write_lock(&bond->curr_slave_lock);
 			bond->curr_active_slave = slave->next;
 			write_unlock(&bond->curr_slave_lock);
 
-			goto out;
+			break;
 		}
 	}
 
+
 out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
 	read_unlock(&bond->lock);
 	return 0;
-
-free_out:
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
-	goto out;
 }
 
 /*
@@ -3618,6 +4068,7 @@
 static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_dev)
 {
 	struct bonding *bond = bond_dev->priv;
+	int res = 1;
 
 	/* if we are sending arp packets, try to at least
 	   identify our own ip address */
@@ -3634,26 +4085,21 @@
 	read_lock(&bond->curr_slave_lock);
 
 	if (!BOND_IS_OK(bond)) {
-		goto free_out;
+		goto out;
 	}
 
 	if (bond->curr_active_slave) { /* one usable interface */
-		skb->dev = bond->curr_active_slave->dev;
-		skb->priority = 1;
-		dev_queue_xmit(skb);
-		goto out;
-	} else {
-		goto free_out;
+		res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
 	}
+
 out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
 	read_unlock(&bond->curr_slave_lock);
 	read_unlock(&bond->lock);
 	return 0;
-
-free_out:
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
-	goto out;
 }
 
 /*
@@ -3668,11 +4114,12 @@
 	struct slave *slave, *start_at;
 	int slave_no;
 	int i;
+	int res = 1;
 
 	read_lock(&bond->lock);
 
 	if (!BOND_IS_OK(bond)) {
-		goto free_out;
+		goto out;
 	}
 
 	slave_no = (data->h_dest[5]^bond_dev->dev_addr[5]) % bond->slave_cnt;
@@ -3690,22 +4137,18 @@
 		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);
-
-			goto out;
+			res = bond_dev_queue_xmit(bond, skb, slave->dev);
+			break;
 		}
 	}
 
 out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
 	read_unlock(&bond->lock);
 	return 0;
-
-free_out:
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
-	goto out;
 }
 
 /*
@@ -3717,11 +4160,12 @@
 	struct slave *slave, *start_at;
 	struct net_device *tx_dev = NULL;
 	int i;
+	int res = 1;
 
 	read_lock(&bond->lock);
 
 	if (!BOND_IS_OK(bond)) {
-		goto free_out;
+		goto out;
 	}
 
 	read_lock(&bond->curr_slave_lock);
@@ -3729,7 +4173,7 @@
 	read_unlock(&bond->curr_slave_lock);
 
 	if (!start_at) {
-		goto free_out;
+		goto out;
 	}
 
 	bond_for_each_slave_from(bond, slave, i, start_at) {
@@ -3745,31 +4189,28 @@
 					continue;
 				}
 
-				skb2->dev = tx_dev;
-				skb2->priority = 1;
-				dev_queue_xmit(skb2);
+				res = bond_dev_queue_xmit(bond, skb2, tx_dev);
+				if (res) {
+					dev_kfree_skb(skb2);
+					continue;
+				}
 			}
 			tx_dev = slave->dev;
 		}
 	}
 
 	if (tx_dev) {
-		skb->dev = tx_dev;
-		skb->priority = 1;
-		dev_queue_xmit(skb);
-	} else {
-		goto free_out;
+		res = bond_dev_queue_xmit(bond, skb, tx_dev);
 	}
 
 out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
 	/* frame sent to all suitable interfaces */
 	read_unlock(&bond->lock);
 	return 0;
-
-free_out:
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
-	goto out;
 }
 
 #ifdef CONFIG_NET_FASTROUTE
@@ -3838,6 +4279,7 @@
 	bond->current_arp_slave = NULL;
 	bond->primary_slave = NULL;
 	bond->dev = bond_dev;
+	INIT_LIST_HEAD(&bond->vlan_list);
 
 	/* Initialize the device entry points */
 	bond_dev->open = bond_open;
@@ -3858,6 +4300,25 @@
 	bond_dev->tx_queue_len = 0;
 	bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
 
+	/* At first, we block adding VLANs. That's the only way to
+	 * prevent problems that occur when adding VLANs over an
+	 * empty bond. The block will be removed once non-challenged
+	 * slaves are enslaved.
+	 */
+	bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
+
+	/* By default, we declare the bond to be fully
+	 * VLAN hardware accelerated capable. Special
+	 * care is taken in the various xmit functions
+	 * when there are slaves that are not hw accel
+	 * capable
+	 */
+	bond_dev->vlan_rx_register = bond_vlan_rx_register;
+	bond_dev->vlan_rx_add_vid  = bond_vlan_rx_add_vid;
+	bond_dev->vlan_rx_kill_vid = bond_vlan_rx_kill_vid;
+	bond_dev->features |= (NETIF_F_HW_VLAN_TX |
+			       NETIF_F_HW_VLAN_RX |
+			       NETIF_F_HW_VLAN_FILTER);
 
 #ifdef CONFIG_PROC_FS
 	bond_create_proc_entry(bond);
diff -urN linux-2.4.26-pre1/drivers/net/bonding/bonding.h linux-2.4.26-pre2/drivers/net/bonding/bonding.h
--- linux-2.4.26-pre1/drivers/net/bonding/bonding.h	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/drivers/net/bonding/bonding.h	2004-03-06 11:20:28.000000000 -0800
@@ -36,8 +36,8 @@
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION	"2.5.4"
-#define DRV_RELDATE	"December 30, 2003"
+#define DRV_VERSION	"2.6.0"
+#define DRV_RELDATE	"January 14, 2004"
 #define DRV_NAME	"bonding"
 #define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
 
@@ -147,6 +147,11 @@
 	u32 arp_targets[BOND_MAX_ARP_TARGETS];
 };
 
+struct vlan_entry {
+	struct list_head vlan_list;
+	unsigned short vlan_id;
+};
+
 struct slave {
 	struct net_device *dev; /* first - usefull for panic debug */
 	struct slave *next;
@@ -196,6 +201,8 @@
 	struct   ad_bond_info ad_info;
 	struct   alb_bond_info alb_info;
 	struct   bond_params params;
+	struct   list_head vlan_list;
+	struct   vlan_group *vlgrp;
 };
 
 /**
@@ -238,5 +245,8 @@
 	slave->dev->flags &= ~IFF_NOARP;
 }
 
+struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
+int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
+
 #endif /* _LINUX_BONDING_H */
 
diff -urN linux-2.4.26-pre1/drivers/net/ne2k-pci.c linux-2.4.26-pre2/drivers/net/ne2k-pci.c
--- linux-2.4.26-pre1/drivers/net/ne2k-pci.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.26-pre2/drivers/net/ne2k-pci.c	2004-03-06 11:20:29.000000000 -0800
@@ -116,6 +116,7 @@
 	CH_Winbond_W89C940F,
 	CH_Holtek_HT80232,
 	CH_Holtek_HT80229,
+	CH_Winbond_89C940_8c4a,
 };
 
 
@@ -133,6 +134,7 @@
 	{"Winbond W89C940F", 0},
 	{"Holtek HT80232", ONLY_16BIT_IO | HOLTEK_FDX},
 	{"Holtek HT80229", ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60 },
+	{"Winbond W89C940(misprogrammed)", 0},
 	{0,}
 };
 
@@ -148,6 +150,7 @@
 	{ 0x1050, 0x5a5a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_W89C940F },
 	{ 0x12c3, 0x0058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80232 },
 	{ 0x12c3, 0x5598, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80229 },
+	{ 0x8c4a, 0x1980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_89C940_8c4a },
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, ne2k_pci_tbl);
diff -urN linux-2.4.26-pre1/drivers/net/pcnet32.c linux-2.4.26-pre2/drivers/net/pcnet32.c
--- linux-2.4.26-pre1/drivers/net/pcnet32.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.26-pre2/drivers/net/pcnet32.c	2004-03-06 11:20:29.000000000 -0800
@@ -22,8 +22,8 @@
  *************************************************************************/
 
 #define DRV_NAME	"pcnet32"
-#define DRV_VERSION	"1.27a"
-#define DRV_RELDATE	"10.02.2002"
+#define DRV_VERSION	"1.28"
+#define DRV_RELDATE	"02.20.2004"
 #define PFX		DRV_NAME ": "
 
 static const char *version =
@@ -61,6 +61,12 @@
 static struct pci_device_id pcnet32_pci_tbl[] __devinitdata = {
     { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
     { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+    /*
+     * Adapters that were sold with IBM's RS/6000 or pSeries hardware have
+     * the incorrect vendor id.
+     */
+    { PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID,
+	    PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0 },
     { 0, }
 };
 
@@ -76,7 +82,7 @@
 
 
 
-static int pcnet32_debug = 1;
+static int pcnet32_debug = 0;
 static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */
 static int pcnet32vlb;	 /* check for VLB cards ? */
 
@@ -120,6 +126,11 @@
     PCNET32_PORT_ASEL			   /* 15 not supported	  */
 };
 
+static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = {
+    "Loopback test  (offline)"
+};
+#define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN)
+
 #define MAX_UNITS 8	/* More are supported, limit only on options */
 static int options[MAX_UNITS];
 static int full_duplex[MAX_UNITS];
@@ -212,6 +223,11 @@
  *	   fix pci probe not increment cards_found
  *	   FD auto negotiate error workaround for xSeries250
  *	   clean up and using new mii module
+ * v1.28   20 Feb 2004 Don Fry <brazilnut@us.ibm.com>
+ *	   Jon Lewis <jonmason@us.ibm.com>, Chinmay Albal <albal@in.ibm.com>
+ *	   Now uses ethtool_ops, netif_msg_* and generic_mii_ioctl.
+ *	   Fixes bogus 'Bus master arbitration failure', pci_[un]map_single
+ *	   length errors, and transmit hangs.  Cleans up after errors in open.
  */
 
 
@@ -319,6 +335,7 @@
 	mii:1;				/* mii port available */
     struct net_device	*next;
     struct mii_if_info mii_if;
+    u32			msg_enable;	/* debug message level */
 };
 
 static void pcnet32_probe_vlbus(void);
@@ -336,6 +353,10 @@
 static int  pcnet32_ioctl(struct net_device *, struct ifreq *, int);
 static int mdio_read(struct net_device *dev, int phy_id, int reg_num);
 static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val);
+static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits);
+static void pcnet32_ethtool_test(struct net_device *dev,
+	struct ethtool_test *eth_test, u64 *data);
+static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1);
 
 enum pci_flags_bit {
     PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
@@ -389,13 +410,13 @@
 }
 
 static struct pcnet32_access pcnet32_wio = {
-    read_csr:	pcnet32_wio_read_csr,
-    write_csr:	pcnet32_wio_write_csr,
-    read_bcr:	pcnet32_wio_read_bcr,
-    write_bcr:	pcnet32_wio_write_bcr,
-    read_rap:	pcnet32_wio_read_rap,
-    write_rap:	pcnet32_wio_write_rap,
-    reset:	pcnet32_wio_reset
+    .read_csr	= pcnet32_wio_read_csr,
+    .write_csr	= pcnet32_wio_write_csr,
+    .read_bcr	= pcnet32_wio_read_bcr,
+    .write_bcr	= pcnet32_wio_write_bcr,
+    .read_rap	= pcnet32_wio_read_rap,
+    .write_rap	= pcnet32_wio_write_rap,
+    .reset	= pcnet32_wio_reset
 };
 
 static u16 pcnet32_dwio_read_csr (unsigned long addr, int index)
@@ -444,17 +465,283 @@
 }
 
 static struct pcnet32_access pcnet32_dwio = {
-    read_csr:	pcnet32_dwio_read_csr,
-    write_csr:	pcnet32_dwio_write_csr,
-    read_bcr:	pcnet32_dwio_read_bcr,
-    write_bcr:	pcnet32_dwio_write_bcr,
-    read_rap:	pcnet32_dwio_read_rap,
-    write_rap:	pcnet32_dwio_write_rap,
-    reset:	pcnet32_dwio_reset
+    .read_csr	= pcnet32_dwio_read_csr,
+    .write_csr	= pcnet32_dwio_write_csr,
+    .read_bcr	= pcnet32_dwio_read_bcr,
+    .write_bcr	= pcnet32_dwio_write_bcr,
+    .read_rap	= pcnet32_dwio_read_rap,
+    .write_rap	= pcnet32_dwio_write_rap,
+    .reset	= pcnet32_dwio_reset
 };
 
 
 
+static int pcnet32_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+    struct pcnet32_private *lp = dev->priv;
+    unsigned long flags;
+    int r = -EOPNOTSUPP;
+
+    if (lp->mii) {
+	spin_lock_irqsave(&lp->lock, flags);
+	mii_ethtool_gset(&lp->mii_if, cmd);
+	spin_unlock_irqrestore(&lp->lock, flags);
+	r = 0;
+    }
+    return r;
+}
+
+static int pcnet32_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+    struct pcnet32_private *lp = dev->priv;
+    unsigned long flags;
+    int r = -EOPNOTSUPP;
+
+    if (lp->mii) {
+	spin_lock_irqsave(&lp->lock, flags);
+	r = mii_ethtool_sset(&lp->mii_if, cmd);
+	spin_unlock_irqrestore(&lp->lock, flags);
+    }
+    return r;
+}
+
+static void pcnet32_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	struct pcnet32_private *lp = dev->priv;
+  
+	strcpy (info->driver, DRV_NAME);
+	strcpy (info->version, DRV_VERSION);
+	if (lp->pci_dev)
+		strcpy (info->bus_info, pci_name(lp->pci_dev));
+	else
+		sprintf(info->bus_info, "VLB 0x%lx", dev->base_addr);
+}
+
+static u32 pcnet32_get_link(struct net_device *dev)
+{
+    struct pcnet32_private *lp = dev->priv;
+    unsigned long flags;
+    int r;
+
+    spin_lock_irqsave(&lp->lock, flags);
+    if (lp->mii) {
+	r = mii_link_ok(&lp->mii_if);
+    } else {
+	ulong ioaddr = dev->base_addr;	/* card base I/O address */
+	r = (lp->a.read_bcr(ioaddr, 4) != 0xc0);
+    }
+    spin_unlock_irqrestore(&lp->lock, flags);
+
+    return r;
+}
+
+static u32 pcnet32_get_msglevel(struct net_device *dev)
+{
+	struct pcnet32_private *lp = dev->priv;
+	return lp->msg_enable;
+}
+  
+static void pcnet32_set_msglevel(struct net_device *dev, u32 value)
+{
+	struct pcnet32_private *lp = dev->priv;
+	lp->msg_enable = value;
+}
+  
+static int pcnet32_nway_reset(struct net_device *dev)
+{
+    struct pcnet32_private *lp = dev->priv;
+    unsigned long flags;
+    int r = -EOPNOTSUPP;
+
+    if (lp->mii) {
+	spin_lock_irqsave(&lp->lock, flags);
+	r = mii_nway_restart(&lp->mii_if);
+	spin_unlock_irqrestore(&lp->lock, flags);
+    }
+    return r;
+}
+
+static void pcnet32_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
+{
+	struct pcnet32_private *lp = dev->priv;
+
+	ering->tx_max_pending = TX_RING_SIZE - 1;
+	ering->tx_pending = lp->cur_tx - lp->dirty_tx;
+	ering->rx_max_pending = RX_RING_SIZE - 1;
+	ering->rx_pending = lp->cur_rx & RX_RING_MOD_MASK;
+}
+
+static void pcnet32_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+    memcpy(data, pcnet32_gstrings_test, sizeof(pcnet32_gstrings_test));
+}
+
+static int pcnet32_self_test_count(struct net_device *dev)
+{
+    return PCNET32_TEST_LEN;
+}
+
+static void pcnet32_ethtool_test(struct net_device *dev,
+	struct ethtool_test *test, u64 *data)
+{
+    struct pcnet32_private *lp = dev->priv;
+    int rc;
+
+    if (test->flags == ETH_TEST_FL_OFFLINE) {
+	rc = pcnet32_loopback_test(dev, data);
+	if (rc) {
+	    if (netif_msg_hw(lp))
+		printk(KERN_DEBUG "%s: Loopback test failed.\n", dev->name);
+	    test->flags |= ETH_TEST_FL_FAILED;
+	} else if (netif_msg_hw(lp))
+	    printk(KERN_DEBUG "%s: Loopback test passed.\n", dev->name);
+    } else
+	printk(KERN_DEBUG "%s: No tests to run (specify 'Offline' on ethtool).",	    dev->name);
+} /* end pcnet32_ethtool_test */
+
+static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
+{
+    struct pcnet32_private *lp = dev->priv;
+    struct pcnet32_access *a = &lp->a;	/* access to registers */
+    ulong ioaddr = dev->base_addr;	/* card base I/O address */
+    struct sk_buff *skb;		/* sk buff */
+    int x, y, i;			/* counters */
+    int numbuffs = 4;			/* number of TX/RX buffers and descs */
+    u16 status = 0x8300;		/* TX ring status */
+    int rc;				/* return code */
+    int size;				/* size of packets */
+    unsigned char *packet;		/* source packet data */
+    static int data_len = 60;		/* length of source packets */
+    unsigned long flags;
+
+    *data1 = 1;			/* status of test, default to fail */
+    rc = 1;			/* default to fail */
+
+    spin_lock_irqsave(&lp->lock, flags);
+    lp->a.write_csr(ioaddr, 0, 0x7904);
+
+    netif_stop_queue(dev);
+
+    /* purge & init rings but don't actually restart */
+    pcnet32_restart(dev, 0x0000);
+
+    lp->a.write_csr(ioaddr, 0, 0x0004);	/* Set STOP bit */
+
+    x = a->read_bcr(ioaddr, 32);	/* set internal loopback in BSR32 */
+    x = x | 0x00000002;
+    a->write_bcr(ioaddr, 32, x);
+
+    /* Initialize Transmit buffers. */
+    size = data_len + 15;
+    for (x=0; x<numbuffs; x++) {
+	if (!(skb = dev_alloc_skb(size))) {
+	    if (netif_msg_hw(lp))
+		printk(KERN_DEBUG "%s: Cannot allocate skb at line: %d!\n",
+		    dev->name, __LINE__);
+	    goto clean_up;
+	} else {
+	    packet = skb->data;
+	    skb_put(skb, size);		/* create space for data */
+	    lp->tx_skbuff[x] = skb;
+	    lp->tx_ring[x].length = le16_to_cpu(-skb->len);
+	    lp->tx_ring[x].misc = 0x00000000;
+
+	    /* put DA and SA into the skb */
+	    for (i=0; i<12; i++)
+		*packet++ = 0xff;
+	    /* type */
+	    *packet++ = 0x08;
+	    *packet++ = 0x06;
+	    /* packet number */
+	    *packet++ = x;
+	    /* fill packet with data */
+	    for (y=0; y<data_len; y++)
+		*packet++ = y;
+
+	    lp->tx_dma_addr[x] = pci_map_single(lp->pci_dev, skb->data,
+		    skb->len, PCI_DMA_TODEVICE);
+	    lp->tx_ring[x].base = (u32)le32_to_cpu(lp->tx_dma_addr[x]);
+	    wmb(); /* Make sure owner changes after all others are visible */
+	    lp->tx_ring[x].status = le16_to_cpu(status);
+	}
+    }
+
+    lp->a.write_csr(ioaddr, 0, 0x0002);	/* Set STRT bit */
+    spin_unlock_irqrestore(&lp->lock, flags);
+
+    mdelay(50);				/* wait a bit */
+
+    spin_lock_irqsave(&lp->lock, flags);
+    lp->a.write_csr(ioaddr, 0, 0x0004);	/* Set STOP bit */
+
+    if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) {
+	printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name);
+
+	for (x=0; x<numbuffs; x++) {
+	    printk(KERN_DEBUG "%s: Packet %d:\n", dev->name, x);
+	    skb=lp->rx_skbuff[x];
+	    for (i=0; i<size; i++) {
+		printk("%02x ", *(skb->data+i));
+	    }
+	    printk("\n");
+	}
+    }
+
+    x = 0;
+    rc = 0;
+    while (x<numbuffs && !rc) {
+	skb = lp->rx_skbuff[x];
+	packet = lp->tx_skbuff[x]->data;
+	for (i=0; i<size; i++) {
+	    if (*(skb->data+i) != packet[i]) {
+		if (netif_msg_hw(lp))
+		    printk(KERN_DEBUG "%s: Error in compare! %2x - %02x %02x\n",
+			    dev->name, i, *(skb->data+i), packet[i]);
+		rc = 1;
+		break;
+	    }
+	}
+	x++;
+    }
+    if (!rc) {
+	*data1 = 0;
+    }
+
+clean_up:
+    x = a->read_csr(ioaddr, 15) & 0xFFFF;
+    a->write_csr(ioaddr, 15, (x & ~0x0044));	/* reset bits 6 and 2 */
+
+    x = a->read_bcr(ioaddr, 32);		/* reset internal loopback */
+    x = x & ~0x00000002;
+    a->write_bcr(ioaddr, 32, x);
+
+    pcnet32_restart(dev, 0x0042);		/* resume normal operation */
+
+    netif_wake_queue(dev);
+
+    /* Clear interrupts, and set interrupt enable. */
+    lp->a.write_csr(ioaddr, 0, 0x7940);
+    spin_unlock_irqrestore(&lp->lock, flags);
+
+    return(rc);
+} /* end pcnet32_loopback_test  */
+
+static struct ethtool_ops pcnet32_ethtool_ops = {
+    .get_settings	= pcnet32_get_settings,
+    .set_settings	= pcnet32_set_settings,
+    .get_drvinfo	= pcnet32_get_drvinfo,
+    .get_msglevel	= pcnet32_get_msglevel,
+    .set_msglevel	= pcnet32_set_msglevel,
+    .nway_reset		= pcnet32_nway_reset,
+    .get_link		= pcnet32_get_link,
+    .get_ringparam	= pcnet32_get_ringparam,
+    .get_tx_csum	= ethtool_op_get_tx_csum,
+    .get_sg		= ethtool_op_get_sg,
+    .get_strings	= pcnet32_get_strings,
+    .self_test_count	= pcnet32_self_test_count,
+    .self_test		= pcnet32_ethtool_test,
+};
+
 /* only probes for non-PCI devices, the rest are handled by 
  * pci_register_driver via pcnet32_probe_pci */
 
@@ -535,10 +822,12 @@
     }
 
     chip_version = a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr,89) << 16);
-    if (pcnet32_debug > 2)
+    if (pcnet32_debug & NETIF_MSG_PROBE)
 	printk(KERN_INFO "  PCnet chip version is %#x.\n", chip_version);
-    if ((chip_version & 0xfff) != 0x003)
+    if ((chip_version & 0xfff) != 0x003) {
+	printk(KERN_INFO PFX "Unsupported chip version.\n");
 	return -ENODEV;
+    }
     
     /* initialize variables */
     fdx = mii = fset = dxsuflo = ltint = 0;
@@ -589,7 +878,7 @@
 	media &= ~3;
 	media |= 1;
 #endif
-	if (pcnet32_debug > 2)
+	if (pcnet32_debug & NETIF_MSG_PROBE)
 	    printk(KERN_DEBUG PFX "media reset to %#x.\n",  media);
 	a->write_bcr(ioaddr, 49, media);
 	break;
@@ -619,8 +908,10 @@
     }
     
     dev = alloc_etherdev(0);
-    if(!dev)
+    if (!dev) {
+	printk(KERN_ERR PFX "Memory allocation failed.\n");
 	return -ENOMEM;
+    }
 
     printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr);
 
@@ -693,6 +984,7 @@
     
     /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */
     if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) {
+	printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
 	release_region(ioaddr, PCNET32_TOTAL_SIZE);
 	return -ENOMEM;
     }
@@ -707,9 +999,12 @@
     lp->name = chipname;
     lp->shared_irq = shared;
     lp->mii_if.full_duplex = fdx;
+    lp->mii_if.phy_id_mask = 0x1f;
+    lp->mii_if.reg_num_mask = 0x1f;
     lp->dxsuflo = dxsuflo;
     lp->ltint = ltint;
     lp->mii = mii;
+    lp->msg_enable = pcnet32_debug;
     if ((cards_found >= MAX_UNITS) || (options[cards_found] > sizeof(options_mapping)))
 	lp->options = PCNET32_PORT_ASEL;
     else
@@ -778,6 +1073,9 @@
 	}
     }
 
+    /* Set the mii phy_id so that we can query the link state */
+    if (lp->mii)
+	lp->mii_if.phy_id = ((lp->a.read_bcr (ioaddr, 33)) >> 5) & 0x1f;
     
     /* The PCNET32-specific entries in the device structure. */
     dev->open = &pcnet32_open;
@@ -786,11 +1084,16 @@
     dev->get_stats = &pcnet32_get_stats;
     dev->set_multicast_list = &pcnet32_set_multicast_list;
     dev->do_ioctl = &pcnet32_ioctl;
+    dev->ethtool_ops = &pcnet32_ethtool_ops;
     dev->tx_timeout = pcnet32_tx_timeout;
     dev->watchdog_timeo = (5*HZ);
 
-    lp->next = pcnet32_dev;
-    pcnet32_dev = dev;
+    if (pdev) {
+	pci_set_drvdata(pdev, dev);
+    } else {
+	lp->next = pcnet32_dev;
+	pcnet32_dev = dev;
+    }
 
     /* Fill in the generic fields of the device structure. */
     register_netdev(dev);
@@ -807,6 +1110,7 @@
     unsigned long ioaddr = dev->base_addr;
     u16 val;
     int i;
+    int rc;
 
     if (dev->irq == 0 ||
 	request_irq(dev->irq, &pcnet32_interrupt,
@@ -815,8 +1119,10 @@
     }
 
     /* Check for a valid station address */
-    if( !is_valid_ether_addr(dev->dev_addr) )
-	return -EINVAL;
+    if (!is_valid_ether_addr(dev->dev_addr)) {
+	rc = -EINVAL;
+	goto err_free_irq;
+    }
 
     /* Reset the PCNET32 */
     lp->a.reset (ioaddr);
@@ -824,7 +1130,7 @@
     /* switch pcnet32 to 32bit mode */
     lp->a.write_bcr (ioaddr, 20, 2);
 
-    if (pcnet32_debug > 1)
+    if (netif_msg_ifup(lp))
 	printk(KERN_DEBUG "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n",
 	       dev->name, dev->irq,
 	       (u32) (lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)),
@@ -890,8 +1196,10 @@
     lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
     lp->init_block.filter[0] = 0x00000000;
     lp->init_block.filter[1] = 0x00000000;
-    if (pcnet32_init_ring(dev))
-	return -ENOMEM;
+    if (pcnet32_init_ring(dev)) {
+	rc = -ENOMEM;
+	goto err_free_ring;
+    }
     
     /* Re-initialize the PCNET32, and start it when done. */
     lp->a.write_csr (ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) &0xffff);
@@ -912,7 +1220,7 @@
      */
     lp->a.write_csr (ioaddr, 0, 0x0042);
 
-    if (pcnet32_debug > 2)
+    if (netif_msg_ifup(lp))
 	printk(KERN_DEBUG "%s: pcnet32 open after %d ticks, init block %#x csr0 %4.4x.\n",
 	       dev->name, i, (u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block)),
 	       lp->a.read_csr(ioaddr, 0));
@@ -921,6 +1229,28 @@
     MOD_INC_USE_COUNT;
     
     return 0;	/* Always succeed */
+
+err_free_ring:
+    /* free any allocated skbuffs */
+    for (i = 0; i < RX_RING_SIZE; i++) {
+	lp->rx_ring[i].status = 0;			    
+	if (lp->rx_skbuff[i]) {
+            pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2,
+		    PCI_DMA_FROMDEVICE);
+	    dev_kfree_skb(lp->rx_skbuff[i]);
+        }
+	lp->rx_skbuff[i] = NULL;
+        lp->rx_dma_addr[i] = 0;
+    }
+    /*
+     * Switch back to 16bit mode to avoid problems with dumb 
+     * DOS packet driver after a warm reboot
+     */
+    lp->a.write_bcr (ioaddr, 20, 4);
+
+err_free_irq:
+    free_irq(dev->irq, dev);
+    return rc;
 }
 
 /*
@@ -976,9 +1306,10 @@
 	}
 
 	if (lp->rx_dma_addr[i] == 0) 
-		lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->tail, rx_skbuff->len, PCI_DMA_FROMDEVICE);
+		lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev,
+			rx_skbuff->tail, PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE);
 	lp->rx_ring[i].base = (u32)le32_to_cpu(lp->rx_dma_addr[i]);
-	lp->rx_ring[i].buf_length = le16_to_cpu(-PKT_BUF_SZ);
+	lp->rx_ring[i].buf_length = le16_to_cpu(2-PKT_BUF_SZ);
 	lp->rx_ring[i].status = le16_to_cpu(0x8000);
     }
     /* The Tx buffer address is filled in as needed, but we do need to clear
@@ -988,6 +1319,7 @@
 	lp->tx_ring[i].status = 0;
         lp->tx_dma_addr[i] = 0;
     }
+    wmb(); /* Make sure all changes are visible */
 
     lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
     for (i = 0; i < 6; i++)
@@ -1031,7 +1363,7 @@
 	       dev->name, lp->a.read_csr(ioaddr, 0));
 	lp->a.write_csr (ioaddr, 0, 0x0004);
 	lp->stats.tx_errors++;
-	if (pcnet32_debug > 2) {
+	if (netif_msg_tx_err(lp)) {
 	    int i;
 	    printk(KERN_DEBUG " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
 	       lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
@@ -1049,7 +1381,7 @@
 	pcnet32_restart(dev, 0x0042);
 
 	dev->trans_start = jiffies;
-	netif_start_queue(dev);
+	netif_wake_queue(dev);
 
 	spin_unlock_irqrestore(&lp->lock, flags);
 }
@@ -1064,7 +1396,7 @@
     int entry;
     unsigned long flags;
 
-    if (pcnet32_debug > 3) {
+    if (netif_msg_tx_queued(lp)) {
 	printk(KERN_DEBUG "%s: pcnet32_start_xmit() called, csr0 %4.4x.\n",
 	       dev->name, lp->a.read_csr(ioaddr, 0));
     }
@@ -1075,12 +1407,14 @@
      * interrupt when that option is available to us.
      */
     status = 0x8300;
+    entry = (lp->cur_tx - lp->dirty_tx) & TX_RING_MOD_MASK;
     if ((lp->ltint) &&
-	((lp->cur_tx - lp->dirty_tx == TX_RING_SIZE/2) ||
-	 (lp->cur_tx - lp->dirty_tx >= TX_RING_SIZE-2)))
+	((entry == TX_RING_SIZE/3) ||
+	 (entry == (TX_RING_SIZE*2)/3) ||
+	 (entry >= TX_RING_SIZE-2)))
     {
 	/* Enable Successful-TxDone interrupt if we have
-	 * 1/2 of, or nearly all of, our ring buffer Tx'd
+	 * 1/3, 2/3 or nearly all of, our ring buffer Tx'd
 	 * but not yet cleaned up.  Thus, most of the time,
 	 * we will not enable Successful-TxDone interrupts.
 	 */
@@ -1092,7 +1426,7 @@
     /* Mask to ring buffer boundary. */
     entry = lp->cur_tx & TX_RING_MOD_MASK;
   
-    /* Caution: the write order is important here, set the base address
+    /* Caution: the write order is important here, set the status
        with the "ownership" bits last. */
 
     lp->tx_ring[entry].length = le16_to_cpu(-skb->len);
@@ -1113,9 +1447,7 @@
 
     dev->trans_start = jiffies;
 
-    if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0)
-	netif_start_queue(dev);
-    else {
+    if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base != 0) {
 	lp->tx_full = 1;
 	netif_stop_queue(dev);
     }
@@ -1147,12 +1479,15 @@
     
     rap = lp->a.read_rap(ioaddr);
     while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) {
+	if (csr0 == 0xffff) {
+	    break;			/* PCMCIA remove happened */
+	}
 	/* Acknowledge all of the current interrupt sources ASAP. */
 	lp->a.write_csr (ioaddr, 0, csr0 & ~0x004f);
 
 	must_restart = 0;
 
-	if (pcnet32_debug > 5)
+	if (netif_msg_intr(lp))
 	    printk(KERN_DEBUG "%s: interrupt  csr0=%#2.2x new csr=%#2.2x.\n",
 		   dev->name, csr0, lp->a.read_csr (ioaddr, 0));
 
@@ -1161,8 +1496,9 @@
 
 	if (csr0 & 0x0200) {		/* Tx-done interrupt */
 	    unsigned int dirty_tx = lp->dirty_tx;
+	    int delta;
 
-	    while (dirty_tx < lp->cur_tx) {
+	    while (dirty_tx != lp->cur_tx) {
 		int entry = dirty_tx & TX_RING_MOD_MASK;
 		int status = (short)le16_to_cpu(lp->tx_ring[entry].status);
 			
@@ -1216,15 +1552,17 @@
 		dirty_tx++;
 	    }
 
-	    if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) {
+	    delta = (lp->cur_tx - dirty_tx) & (TX_RING_MOD_MASK + TX_RING_SIZE);
+	    if (delta >= TX_RING_SIZE) {
 		printk(KERN_ERR "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
 			dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
 		dirty_tx += TX_RING_SIZE;
+		delta -= TX_RING_SIZE;
 	    }
 
 	    if (lp->tx_full &&
 		netif_queue_stopped(dev) &&
-		dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+		delta < TX_RING_SIZE - 2) {
 		/* The ring is no longer full, clear tbusy. */
 		lp->tx_full = 0;
 		netif_wake_queue (dev);
@@ -1264,7 +1602,7 @@
     lp->a.write_csr (ioaddr, 0, 0x7940);
     lp->a.write_rap (ioaddr,rap);
     
-    if (pcnet32_debug > 4)
+    if (netif_msg_intr(lp))
 	printk(KERN_DEBUG "%s: exiting interrupt, csr0=%#4.4x.\n",
 	       dev->name, lp->a.read_csr (ioaddr, 0));
 
@@ -1312,13 +1650,14 @@
 		    if ((newskb = dev_alloc_skb (PKT_BUF_SZ))) {
 			skb_reserve (newskb, 2);
 			skb = lp->rx_skbuff[entry];
-			pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[entry], skb->len, PCI_DMA_FROMDEVICE);
+			pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[entry],
+				PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE);
 			skb_put (skb, pkt_len);
 			lp->rx_skbuff[entry] = newskb;
 			newskb->dev = dev;
                         lp->rx_dma_addr[entry] = 
 				pci_map_single(lp->pci_dev, newskb->tail,
-					newskb->len, PCI_DMA_FROMDEVICE);
+					PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE);
 			lp->rx_ring[entry].base = le32_to_cpu(lp->rx_dma_addr[entry]);
 			rx_in_place = 1;
 		    } else
@@ -1347,7 +1686,7 @@
 		    skb_put(skb,pkt_len);	/* Make room */
 		    pci_dma_sync_single(lp->pci_dev,
 		                        lp->rx_dma_addr[entry],
-		                        PKT_BUF_SZ,
+		                        PKT_BUF_SZ-2,
 		                        PCI_DMA_FROMDEVICE);
 		    eth_copy_and_sum(skb,
 				     (unsigned char *)(lp->rx_skbuff[entry]->tail),
@@ -1364,7 +1703,8 @@
 	 * The docs say that the buffer length isn't touched, but Andrew Boyd
 	 * of QNX reports that some revs of the 79C965 clear it.
 	 */
-	lp->rx_ring[entry].buf_length = le16_to_cpu(-PKT_BUF_SZ);
+	lp->rx_ring[entry].buf_length = le16_to_cpu(2-PKT_BUF_SZ);
+	wmb(); /* Make sure owner changes after all others are visible */
 	lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
 	entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
     }
@@ -1383,7 +1723,7 @@
 
     lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112);
 
-    if (pcnet32_debug > 1)
+    if (netif_msg_ifdown(lp))
 	printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
 	       dev->name, lp->a.read_csr (ioaddr, 0));
 
@@ -1402,7 +1742,8 @@
     for (i = 0; i < RX_RING_SIZE; i++) {
 	lp->rx_ring[i].status = 0;			    
 	if (lp->rx_skbuff[i]) {
-            pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], lp->rx_skbuff[i]->len, PCI_DMA_FROMDEVICE);
+            pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2,
+		    PCI_DMA_FROMDEVICE);
 	    dev_kfree_skb(lp->rx_skbuff[i]);
         }
 	lp->rx_skbuff[i] = NULL;
@@ -1472,7 +1813,9 @@
 	
 	crc = ether_crc_le(6, addrs);
 	crc = crc >> 26;
-	mcast_table [crc >> 4] |= cpu_to_le16(1 << (crc & 0xf));
+	mcast_table [crc >> 4] = le16_to_cpu(
+		le16_to_cpu(mcast_table [crc >> 4]) | (1 << (crc & 0xf))
+	);
     }
     return;
 }
@@ -1537,136 +1880,49 @@
 	lp->a.write_bcr(ioaddr, 33, phyaddr);
 }
 
-static int pcnet32_ethtool_ioctl (struct net_device *dev, void *useraddr)
+static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct pcnet32_private *lp = dev->priv;
-	u32 ethcmd;
-	int phyaddr = 0;
-	int phy_id = 0;
-	unsigned long ioaddr = dev->base_addr;
-
-	if (lp->mii) {
-		phyaddr = lp->a.read_bcr (ioaddr, 33);
-		phy_id = (phyaddr >> 5) & 0x1f;
-		lp->mii_if.phy_id = phy_id;
-	}
-
-	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
-		return -EFAULT;
-
-	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-		strcpy (info.driver, DRV_NAME);
-		strcpy (info.version, DRV_VERSION);
-		if (lp->pci_dev)
-			strcpy (info.bus_info, lp->pci_dev->slot_name);
-		else
-			sprintf(info.bus_info, "VLB 0x%lx", dev->base_addr);
-		if (copy_to_user (useraddr, &info, sizeof (info)))
-			return -EFAULT;
-		return 0;
-	}
-
-	/* get settings */
-	case ETHTOOL_GSET: {
-		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-		spin_lock_irq(&lp->lock);
-		mii_ethtool_gset(&lp->mii_if, &ecmd);
-		spin_unlock_irq(&lp->lock);
-		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return 0;
-	}
-	/* set settings */
-	case ETHTOOL_SSET: {
-		int r;
-		struct ethtool_cmd ecmd;
-		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-			return -EFAULT;
-		spin_lock_irq(&lp->lock);
-		r = mii_ethtool_sset(&lp->mii_if, &ecmd);
-		spin_unlock_irq(&lp->lock);
-		return r;
-	}
-	/* restart autonegotiation */
-	case ETHTOOL_NWAY_RST: {
-		return mii_nway_restart(&lp->mii_if);
-	}
-	/* get link status */
-	case ETHTOOL_GLINK: {
-		struct ethtool_value edata = {ETHTOOL_GLINK};
-		edata.data = mii_link_ok(&lp->mii_if);
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
+    struct pcnet32_private *lp = dev->priv;	 
+    struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
+    int rc;
+    unsigned long flags;
 
-	/* get message-level */
-	case ETHTOOL_GMSGLVL: {
-		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
-		edata.data = pcnet32_debug;
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-	/* set message-level */
-	case ETHTOOL_SMSGLVL: {
-		struct ethtool_value edata;
-		if (copy_from_user(&edata, useraddr, sizeof(edata)))
-			return -EFAULT;
-		pcnet32_debug = edata.data;
-		return 0;
-	}
-	default:
-		break;
-	}
+    /* SIOC[GS]MIIxxx ioctls */
+    if (lp->mii) {
+	spin_lock_irqsave(&lp->lock, flags);
+	rc = generic_mii_ioctl(&lp->mii_if, data, cmd, NULL);
+	spin_unlock_irqrestore(&lp->lock, flags);
+    } else {
+	rc = -EOPNOTSUPP;
+    }
 
-	return -EOPNOTSUPP;
+    return rc;
 }
 
-static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
 {
-    unsigned long ioaddr = dev->base_addr;
-    struct pcnet32_private *lp = dev->priv;	 
-    struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
-    int phyaddr = lp->a.read_bcr (ioaddr, 33);
+    struct net_device *dev = pci_get_drvdata(pdev);
 
-    if (cmd == SIOCETHTOOL)
-	return pcnet32_ethtool_ioctl(dev, (void *) rq->ifr_data);
+    if (dev) {
+	struct pcnet32_private *lp = dev->priv;
 
-    if (lp->mii) {
-	switch(cmd) {
-	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	    data->phy_id = (phyaddr >> 5) & 0x1f;
-	    /* Fall Through */
-	case SIOCGMIIREG:		/* Read MII PHY register. */
-	    lp->a.write_bcr (ioaddr, 33, ((data->phy_id & 0x1f) << 5) | (data->reg_num & 0x1f));
-	    data->val_out = lp->a.read_bcr (ioaddr, 34);
-	    lp->a.write_bcr (ioaddr, 33, phyaddr);
-	    return 0;
-	case SIOCSMIIREG:		/* Write MII PHY register. */
-	    if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-	    lp->a.write_bcr (ioaddr, 33, ((data->phy_id & 0x1f) << 5) | (data->reg_num & 0x1f));
-	    lp->a.write_bcr (ioaddr, 34, data->val_in);
-	    lp->a.write_bcr (ioaddr, 33, phyaddr);
-	    return 0;
-	default:
-	    return -EOPNOTSUPP;
-	}
+	unregister_netdev(dev);
+	release_region(dev->base_addr, PCNET32_TOTAL_SIZE);
+	pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
+	free_netdev(dev);
+	pci_set_drvdata(pdev, NULL);
     }
-    return -EOPNOTSUPP;
 }
 
 static struct pci_driver pcnet32_driver = {
-    name:	DRV_NAME,
-    probe:	pcnet32_probe_pci,
-    id_table:	pcnet32_pci_tbl,
+    .name	= DRV_NAME,
+    .probe	= pcnet32_probe_pci,
+    .remove	= __devexit_p(pcnet32_remove_one),
+    .id_table	= pcnet32_pci_tbl,
 };
 
 MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, DRV_NAME " debug level (0-6)");
+MODULE_PARM_DESC(debug, DRV_NAME " debug level");
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM_DESC(max_interrupt_work, DRV_NAME " maximum events handled per interrupt");  
 MODULE_PARM(rx_copybreak, "i");
@@ -1687,19 +1943,21 @@
 /* An additional parameter that may be passed in... */
 static int debug = -1;
 static int tx_start_pt = -1;
+static int pcnet32_have_pci;
 
 static int __init pcnet32_init_module(void)
 {
     printk(KERN_INFO "%s", version);
 
-    if (debug > 0)
-	pcnet32_debug = debug;
+    if (debug >= 0 && debug < (sizeof(int) - 1))
+	pcnet32_debug = 1 << debug;
 
     if ((tx_start_pt >= 0) && (tx_start_pt <= 3))
 	tx_start = tx_start_pt;
 
     /* find the PCI devices */
-    pci_module_init(&pcnet32_driver);
+    if (!pci_module_init(&pcnet32_driver))
+	pcnet32_have_pci = 1;
 
     /* should we find any remaining VLbus devices ? */
     if (pcnet32vlb)
@@ -1708,7 +1966,7 @@
     if (cards_found)
 	printk(KERN_INFO PFX "%d cards_found.\n", cards_found);
     
-    return cards_found ? 0 : -ENODEV;
+    return (pcnet32_have_pci + cards_found) ? 0 : -ENODEV;
 }
 
 static void __exit pcnet32_cleanup_module(void)
@@ -1721,12 +1979,12 @@
 	next_dev = lp->next;
 	unregister_netdev(pcnet32_dev);
 	release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE);
-	if (lp->pci_dev)
-	    pci_unregister_driver(&pcnet32_driver);
 	pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
-	kfree(pcnet32_dev);
+	free_netdev(pcnet32_dev);
 	pcnet32_dev = next_dev;
     }
+    if (pcnet32_have_pci)
+	pci_unregister_driver(&pcnet32_driver);
 }
 
 module_init(pcnet32_init_module);
diff -urN linux-2.4.26-pre1/drivers/net/r8169.c linux-2.4.26-pre2/drivers/net/r8169.c
--- linux-2.4.26-pre1/drivers/net/r8169.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.26-pre2/drivers/net/r8169.c	2004-03-06 11:20:29.000000000 -0800
@@ -874,7 +874,6 @@
 		     void *ioaddr)
 {
 	unsigned long dirty_tx, tx_left = 0;
-	int entry = tp->cur_tx % NUM_TX_DESC;
 
 	assert(dev != NULL);
 	assert(tp != NULL);
@@ -884,14 +883,18 @@
 	tx_left = tp->cur_tx - dirty_tx;
 
 	while (tx_left > 0) {
+		int entry = dirty_tx % NUM_TX_DESC;
+
 		if ((tp->TxDescArray[entry].status & OWNbit) == 0) {
-			dev_kfree_skb_irq(tp->
-					  Tx_skbuff[dirty_tx % NUM_TX_DESC]);
-			tp->Tx_skbuff[dirty_tx % NUM_TX_DESC] = NULL;
+			struct sk_buff *skb = tp->Tx_skbuff[entry];
+
+			tp->stats.tx_bytes += skb->len >= ETH_ZLEN ?
+					      skb->len : ETH_ZLEN;
 			tp->stats.tx_packets++;
+			dev_kfree_skb_irq(skb);
+			tp->Tx_skbuff[entry] = NULL;
 			dirty_tx++;
 			tx_left--;
-			entry++;
 		}
 	}
 
diff -urN linux-2.4.26-pre1/drivers/net/sungem.c linux-2.4.26-pre2/drivers/net/sungem.c
--- linux-2.4.26-pre1/drivers/net/sungem.c	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/drivers/net/sungem.c	2004-03-06 11:20:29.000000000 -0800
@@ -677,6 +677,7 @@
 static void gem_rx(struct gem *gp)
 {
 	int entry, drops;
+	u32 done;
 
 	if (netif_msg_intr(gp))
 		printk(KERN_DEBUG "%s: rx interrupt, done: %d, rx_new: %d\n",
@@ -684,6 +685,7 @@
 
 	entry = gp->rx_new;
 	drops = 0;
+	done = readl(gp->regs + RXDMA_DONE);
 	for (;;) {
 		struct gem_rxd *rxd = &gp->init_block->rxd[entry];
 		struct sk_buff *skb;
@@ -694,6 +696,19 @@
 		if ((status & RXDCTRL_OWN) != 0)
 			break;
 
+		/* When writing back RX descriptor, GEM writes status
+		 * then buffer address, possibly in seperate transactions.
+		 * If we don't wait for the chip to write both, we could
+		 * post a new buffer to this descriptor then have GEM spam
+		 * on the buffer address.  We sync on the RX completion
+		 * register to prevent this from happening.
+		 */
+		if (entry == done) {
+			done = readl(gp->regs + RXDMA_DONE);
+			if (entry == done)
+				break;
+		}
+
 		skb = gp->rx_skbs[entry];
 
 		len = (status & RXDCTRL_BUFSZ) >> 16;
diff -urN linux-2.4.26-pre1/drivers/net/tulip/tulip_core.c linux-2.4.26-pre2/drivers/net/tulip/tulip_core.c
--- linux-2.4.26-pre1/drivers/net/tulip/tulip_core.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.26-pre2/drivers/net/tulip/tulip_core.c	2004-03-06 11:20:29.000000000 -0800
@@ -579,7 +579,7 @@
 					dev->if_port = 2 - dev->if_port;
 				} else
 					dev->if_port = 0;
-			else
+			else if (dev->if_port != 0 || (csr12 & 0x0004) != 0)
 				dev->if_port = 1;
 			tulip_select_media(dev, 0);
 		}
diff -urN linux-2.4.26-pre1/drivers/net/wan/8253x/build linux-2.4.26-pre2/drivers/net/wan/8253x/build
--- linux-2.4.26-pre1/drivers/net/wan/8253x/build	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre2/drivers/net/wan/8253x/build	2004-03-06 11:20:29.000000000 -0800
@@ -0,0 +1,8 @@
+cc -g  -o 8253xcfg -I. -U__KERNEL__ 8253xcfg.c
+cc -g  -o 8253xspeed -I. -U__KERNEL__ 8253xspeed.c
+cc -g  -o 8253xmode -I. -U__KERNEL__ 8253xmode.c
+cc -g  -o 8253xpeer -I. -U__KERNEL__ 8253xpeer.c
+cc -g  -o eprom9050 -I. -U__KERNEL__ eprom9050.c
+
+
+
diff -urN linux-2.4.26-pre1/drivers/scsi/qlogicfc.c linux-2.4.26-pre2/drivers/scsi/qlogicfc.c
--- linux-2.4.26-pre1/drivers/scsi/qlogicfc.c	2003-06-13 07:51:36.000000000 -0700
+++ linux-2.4.26-pre2/drivers/scsi/qlogicfc.c	2004-03-06 11:20:29.000000000 -0800
@@ -411,7 +411,7 @@
    if that mbox should be copied as input.  For example 0x2 would mean
    only copy mbox1. */
 
-const u_char mbox_param[] =
+static const u_char mbox_param[] =
 {
 	0x01,			/* MBOX_NO_OP */
 	0x1f,			/* MBOX_LOAD_RAM */
diff -urN linux-2.4.26-pre1/drivers/scsi/qlogicpti.c linux-2.4.26-pre2/drivers/scsi/qlogicpti.c
--- linux-2.4.26-pre1/drivers/scsi/qlogicpti.c	2001-10-30 15:08:11.000000000 -0800
+++ linux-2.4.26-pre2/drivers/scsi/qlogicpti.c	2004-03-06 11:20:29.000000000 -0800
@@ -53,7 +53,7 @@
 
 #define PACKB(a, b)			(((a)<<4)|(b))
 
-const u_char mbox_param[] = {
+static const u_char mbox_param[] = {
 	PACKB(1, 1),	/* MBOX_NO_OP */
 	PACKB(5, 5),	/* MBOX_LOAD_RAM */
 	PACKB(2, 0),	/* MBOX_EXEC_FIRMWARE */
diff -urN linux-2.4.26-pre1/drivers/sound/.indent.pro linux-2.4.26-pre2/drivers/sound/.indent.pro
--- linux-2.4.26-pre1/drivers/sound/.indent.pro	1997-09-30 08:46:46.000000000 -0700
+++ linux-2.4.26-pre2/drivers/sound/.indent.pro	1969-12-31 16:00:00.000000000 -0800
@@ -1,8 +0,0 @@
--bad 
--bap 
--nfca
--bl 
--psl 
--di16
--lp
--ip5
diff -urN linux-2.4.26-pre1/drivers/sound/.version linux-2.4.26-pre2/drivers/sound/.version
--- linux-2.4.26-pre1/drivers/sound/.version	1997-11-09 23:01:54.000000000 -0800
+++ linux-2.4.26-pre2/drivers/sound/.version	1969-12-31 16:00:00.000000000 -0800
@@ -1,2 +0,0 @@
-3.8s
-0x030804
diff -urN linux-2.4.26-pre1/drivers/video/pm3fb.c linux-2.4.26-pre2/drivers/video/pm3fb.c
--- linux-2.4.26-pre1/drivers/video/pm3fb.c	2002-08-02 17:39:45.000000000 -0700
+++ linux-2.4.26-pre2/drivers/video/pm3fb.c	2004-03-06 11:20:29.000000000 -0800
@@ -19,6 +19,7 @@
  *  $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $
  *
  *  CHANGELOG:
+ *  Wed Nov 13 11:19:34 MET 2002, v 1.4.11C: option flatpanel: wasn't available in module, fixed.
  *  Mon Feb 11 10:35:48 MET 2002, v 1.4.11B: Cosmetic update.
  *  Wed Jan 23 14:16:59 MET 2002, v 1.4.11: Preliminary 2.5.x support, patch for 2.5.2.
  *  Wed Nov 28 11:08:29 MET 2001, v 1.4.10: potential bug fix for SDRAM-based board, patch for 2.4.16.
@@ -3756,6 +3757,8 @@
 MODULE_PARM_DESC(printtimings, "print the memory timings of the card(s)");
 MODULE_PARM(forcesize, PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
 MODULE_PARM_DESC(forcesize, "force specified memory size");
+MODULE_PARM(flatpanel, PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
+MODULE_PARM_DESC(flatpanel, "flatpanel (LCD) support (preliminary)");
 /*
 MODULE_SUPPORTED_DEVICE("Permedia3 PCI boards")
 MODULE_GENERIC_TABLE(gtype,name)
@@ -3800,6 +3803,11 @@
 			sprintf(ts, ",depth:%d:%d", i, depth[i]);
 			strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
 		}
+                if (flatpanel[i])
+		{
+			sprintf(ts, ",flatpanel:%d:", i);
+			strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
+		}
 	}
 	g_options[PM3_OPTIONS_SIZE - 1] = '\0';
 	DPRINTK(1, "pm3fb use options: %s\n", g_options);
diff -urN linux-2.4.26-pre1/drivers/video/radeonfb.c linux-2.4.26-pre2/drivers/video/radeonfb.c
--- linux-2.4.26-pre1/drivers/video/radeonfb.c	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.26-pre2/drivers/video/radeonfb.c	2004-03-06 11:20:29.000000000 -0800
@@ -202,6 +202,8 @@
 	RADEON_If,
 	RADEON_Ig,
 	RADEON_Y_,
+	RADEON_Ya,
+	RADEON_Yd,
 	RADEON_Ld,
 	RADEON_Le,
 	RADEON_Lf,
@@ -261,6 +263,8 @@
 	{ "9000 If", RADEON_RV250 },
 	{ "9000 Ig", RADEON_RV250 },
 	{ "9200 Y", RADEON_RV280 },
+	{ "9200 Ya", RADEON_RV280 },
+	{ "9200 Yd", RADEON_RV280 },
 	{ "M9 Ld", RADEON_M9 },
 	{ "M9 Le", RADEON_M9 },
 	{ "M9 Lf", RADEON_M9 },
@@ -326,6 +330,8 @@
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NH, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NH},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NI, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NI},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Y_, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Y_},
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ya, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ya},
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Yd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Yd},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AD},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AP},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AR},
diff -urN linux-2.4.26-pre1/fs/devfs/base.c linux-2.4.26-pre2/fs/devfs/base.c
--- linux-2.4.26-pre1/fs/devfs/base.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.26-pre2/fs/devfs/base.c	2004-03-06 11:20:29.000000000 -0800
@@ -3549,7 +3549,7 @@
     int err;
 
     if ( !(boot_options & OPTION_MOUNT) ) return;
-    err = do_mount ("none", "/dev", "devfs", 0, "");
+    err = do_mount ("none", "/dev", "devfs", 0, NULL);
     if (err == 0) printk (KERN_INFO "Mounted devfs on /dev\n");
     else PRINTK ("(): unable to mount devfs, err: %d\n", err);
 }   /*  End Function mount_devfs_fs  */
diff -urN linux-2.4.26-pre1/fs/xfs/Makefile linux-2.4.26-pre2/fs/xfs/Makefile
--- linux-2.4.26-pre1/fs/xfs/Makefile	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/Makefile	2004-03-06 11:20:29.000000000 -0800
@@ -108,7 +108,9 @@
 				   xfs_vfsops.o \
 				   xfs_vnodeops.o \
 				   xfs_refcache.o \
-				   xfs_rw.o
+				   xfs_rw.o \
+				   xfs_dmops.o \
+				   xfs_qmops.o
 
 # Objects not built in this directory
 obj-y				+= linux/linux_xfs.o \
@@ -119,15 +121,11 @@
 ifeq ($(CONFIG_XFS_DMAPI),y)
   subdir-$(CONFIG_XFS_FS)	+= dmapi
   obj-y				+= dmapi/xfs_dmapi.o
-else
-  obj-y				+= xfs_dmops.o
 endif
 
 ifeq ($(CONFIG_XFS_QUOTA),y)
   subdir-$(CONFIG_XFS_FS)	+= quota
   obj-y				+= quota/xfs_quota.o
-else
-  obj-y				+= xfs_qmops.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.26-pre1/fs/xfs/linux/kmem.h linux-2.4.26-pre2/fs/xfs/linux/kmem.h
--- linux-2.4.26-pre1/fs/xfs/linux/kmem.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/kmem.h	2004-03-06 11:20:29.000000000 -0800
@@ -59,6 +59,12 @@
         current->flags |= PF_FSTRANS;   \
 } while (0)
 
+#define PFLAGS_CLEAR_FSTRANS(STATEP) do { \
+	*(STATEP) = current->flags;	\
+	current->flags &= ~PF_FSTRANS;	\
+} while (0)
+
+
 #define PFLAGS_RESTORE(STATEP) do {     \
 	current->flags = *(STATEP);     \
 } while (0)
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_aops.c linux-2.4.26-pre2/fs/xfs/linux/xfs_aops.c
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_aops.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_aops.c	2004-03-06 11:20:29.000000000 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -54,8 +54,54 @@
 #include "xfs_iomap.h"
 #include <linux/iobuf.h>
 
-STATIC void convert_page(struct inode *, struct page *,
-			xfs_iomap_t *, void *, int, int);
+STATIC void xfs_count_page_state(struct page *, int *, int *, int *);
+STATIC void xfs_convert_page(struct inode *, struct page *,
+				xfs_iomap_t *, void *, int, int);
+
+#if defined(XFS_RW_TRACE)
+void
+xfs_page_trace(
+	int		tag,
+	struct inode	*inode,
+	struct page	*page,
+	int		mask)
+{
+	xfs_inode_t	*ip;
+	bhv_desc_t	*bdp;
+	vnode_t		*vp = LINVFS_GET_VP(inode);
+	loff_t		isize = i_size_read(inode);
+	loff_t		offset = page->index << PAGE_CACHE_SHIFT;
+	int		delalloc = -1, unmapped = -1, unwritten = -1;
+
+	if (page_has_buffers(page))
+		xfs_count_page_state(page, &delalloc, &unmapped, &unwritten);
+
+	bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops);
+	ip = XFS_BHVTOI(bdp);
+	if (!ip->i_rwtrace)
+		return;
+
+	ktrace_enter(ip->i_rwtrace,
+		(void *)((unsigned long)tag),
+		(void *)ip,
+		(void *)inode,
+		(void *)page,
+		(void *)((unsigned long)mask),
+		(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
+		(void *)((unsigned long)((isize >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(isize & 0xffffffff)),
+		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(offset & 0xffffffff)),
+		(void *)((unsigned long)delalloc),
+		(void *)((unsigned long)unmapped),
+		(void *)((unsigned long)unwritten),
+		(void *)NULL,
+		(void *)NULL);
+}
+#else
+#define xfs_page_trace(tag, inode, page, mask)
+#endif
 
 void
 linvfs_unwritten_done(
@@ -97,7 +143,7 @@
 }
 
 STATIC int
-map_blocks(
+xfs_map_blocks(
 	struct inode		*inode,
 	loff_t			offset,
 	ssize_t			count,
@@ -127,12 +173,11 @@
 }
 
 /*
- * match_offset_to_mapping
  * Finds the corresponding mapping in block @map array of the
  * given @offset within a @page.
  */
 STATIC xfs_iomap_t *
-match_offset_to_mapping(
+xfs_offset_to_map(
 	struct page		*page,
 	xfs_iomap_t		*iomapp,
 	unsigned long		offset)
@@ -153,7 +198,7 @@
 }
 
 STATIC void
-map_buffer_at_offset(
+xfs_map_at_offset(
 	struct page		*page,
 	struct buffer_head	*bh,
 	unsigned long		offset,
@@ -194,7 +239,7 @@
  * in units of filesystem blocks.
  */
 STATIC struct page *
-probe_unwritten_page(
+xfs_probe_unwritten_page(
 	struct address_space	*mapping,
 	unsigned long		index,
 	xfs_iomap_t		*iomapp,
@@ -218,11 +263,11 @@
 		do {
 			if (!buffer_unwritten(bh))
 				break;
-			if (!match_offset_to_mapping(page, iomapp, p_offset))
+			if (!xfs_offset_to_map(page, iomapp, p_offset))
 				break;
 			if (p_offset >= max_offset)
 				break;
-			map_buffer_at_offset(page, bh, p_offset, bbits, iomapp);
+			xfs_map_at_offset(page, bh, p_offset, bbits, iomapp);
 			set_buffer_unwritten_io(bh);
 			bh->b_private = pb;
 			p_offset += bh->b_size;
@@ -242,7 +287,7 @@
  * yet - clustering for mmap write case.
  */
 STATIC unsigned int
-probe_unmapped_page(
+xfs_probe_unmapped_page(
 	struct address_space	*mapping,
 	unsigned long		index,
 	unsigned int		pg_offset)
@@ -275,7 +320,7 @@
 }
 
 STATIC unsigned int
-probe_unmapped_cluster(
+xfs_probe_unmapped_cluster(
 	struct inode		*inode,
 	struct page		*startpage,
 	struct buffer_head	*bh,
@@ -300,7 +345,7 @@
 		/* Prune this back to avoid pathological behavior */
 		tloff = min(tlast, startpage->index + 64);
 		for (tindex = startpage->index + 1; tindex < tloff; tindex++) {
-			len = probe_unmapped_page(mapping, tindex,
+			len = xfs_probe_unmapped_page(mapping, tindex,
 							PAGE_CACHE_SIZE);
 			if (!len)
 				return total;
@@ -308,7 +353,8 @@
 		}
 		if (tindex == tlast &&
 		    (tloff = i_size_read(inode) & (PAGE_CACHE_SIZE - 1))) {
-			total += probe_unmapped_page(mapping, tindex, tloff);
+			total += xfs_probe_unmapped_page(mapping,
+							tindex, tloff);
 		}
 	}
 	return total;
@@ -320,7 +366,7 @@
  * reference count.
  */
 STATIC struct page *
-probe_delalloc_page(
+xfs_probe_delalloc_page(
 	struct inode		*inode,
 	unsigned long		index)
 {
@@ -353,7 +399,7 @@
 }
 
 STATIC int
-map_unwritten(
+xfs_map_unwritten(
 	struct inode		*inode,
 	struct page		*start_page,
 	struct buffer_head	*head,
@@ -401,22 +447,16 @@
 	do {
 		if (!buffer_unwritten(bh))
 			break;
-		tmp = match_offset_to_mapping(start_page, iomapp, p_offset);
+		tmp = xfs_offset_to_map(start_page, iomapp, p_offset);
 		if (!tmp)
 			break;
-		map_buffer_at_offset(start_page, bh, p_offset, block_bits, iomapp);
+		xfs_map_at_offset(start_page, bh, p_offset, block_bits, iomapp);
 		set_buffer_unwritten_io(bh);
 		bh->b_private = pb;
 		p_offset += bh->b_size;
 		nblocks++;
 	} while ((bh = bh->b_this_page) != head);
 
-	if (unlikely(nblocks == 0)) {
-		printk("XFS: bad unwritten extent map: bh=0x%p, iomapp=0x%p\n",
-		       curr, iomapp);
-		BUG();
-	}
-
 	atomic_add(nblocks, &pb->pb_io_remaining);
 
 	/* If we reached the end of the page, map forwards in any
@@ -432,13 +472,15 @@
 		tloff = (iomapp->iomap_offset + iomapp->iomap_bsize) >> PAGE_CACHE_SHIFT;
 		tloff = min(tlast, tloff);
 		for (tindex = start_page->index + 1; tindex < tloff; tindex++) {
-			page = probe_unwritten_page(mapping, tindex, iomapp, pb,
+			page = xfs_probe_unwritten_page(mapping,
+						tindex, iomapp, pb,
 						PAGE_CACHE_SIZE, &bs, bbits);
 			if (!page)
 				break;
 			nblocks += bs;
 			atomic_add(bs, &pb->pb_io_remaining);
-			convert_page(inode, page, iomapp, pb, startio, all_bh);
+			xfs_convert_page(inode, page, iomapp, pb,
+							startio, all_bh);
 			/* stop if converting the next page might add
 			 * enough blocks that the corresponding byte
 			 * count won't fit in our ulong page buf length */
@@ -448,12 +490,14 @@
 
 		if (tindex == tlast &&
 		    (tloff = (i_size_read(inode) & (PAGE_CACHE_SIZE - 1)))) {
-			page = probe_unwritten_page(mapping, tindex, iomapp, pb,
+			page = xfs_probe_unwritten_page(mapping,
+							tindex, iomapp, pb,
 							tloff, &bs, bbits);
 			if (page) {
 				nblocks += bs;
 				atomic_add(bs, &pb->pb_io_remaining);
-				convert_page(inode, page, iomapp, pb, startio, all_bh);
+				xfs_convert_page(inode, page, iomapp, pb,
+							startio, all_bh);
 				if (nblocks >= ((ULONG_MAX - PAGE_SIZE) >> block_bits))
 					goto enough;
 			}
@@ -480,7 +524,7 @@
 }
 
 STATIC void
-submit_page(
+xfs_submit_page(
 	struct page		*page,
 	struct buffer_head	*bh_arr[],
 	int			cnt)
@@ -511,7 +555,7 @@
  * that the page has no mapping at all.
  */
 STATIC void
-convert_page(
+xfs_convert_page(
 	struct inode		*inode,
 	struct page		*page,
 	xfs_iomap_t		*iomapp,
@@ -544,7 +588,7 @@
 			}
 			continue;
 		}
-		tmp = match_offset_to_mapping(page, mp, offset);
+		tmp = xfs_offset_to_map(page, mp, offset);
 		if (!tmp)
 			continue;
 		ASSERT(!(tmp->iomap_flags & IOMAP_HOLE));
@@ -556,10 +600,10 @@
 		 */
 		if (buffer_unwritten(bh) && !bh->b_end_io) {
 			ASSERT(tmp->iomap_flags & IOMAP_UNWRITTEN);
-			map_unwritten(inode, page, head, bh,
+			xfs_map_unwritten(inode, page, head, bh,
 					offset, bbits, tmp, startio, all_bh);
 		} else if (! (buffer_unwritten(bh) && buffer_locked(bh))) {
-			map_buffer_at_offset(page, bh, offset, bbits, tmp);
+			xfs_map_at_offset(page, bh, offset, bbits, tmp);
 			if (buffer_unwritten(bh)) {
 				set_buffer_unwritten_io(bh);
 				bh->b_private = private;
@@ -575,7 +619,7 @@
 	} while (i++, (bh = bh->b_this_page) != head);
 
 	if (startio) {
-		submit_page(page, bh_arr, index);
+		xfs_submit_page(page, bh_arr, index);
 	} else {
 		unlock_page(page);
 	}
@@ -586,7 +630,7 @@
  * by mp and following the start page.
  */
 STATIC void
-cluster_write(
+xfs_cluster_write(
 	struct inode		*inode,
 	unsigned long		tindex,
 	xfs_iomap_t		*iomapp,
@@ -598,10 +642,10 @@
 
 	tlast = (iomapp->iomap_offset + iomapp->iomap_bsize) >> PAGE_CACHE_SHIFT;
 	for (; tindex < tlast; tindex++) {
-		page = probe_delalloc_page(inode, tindex);
+		page = xfs_probe_delalloc_page(inode, tindex);
 		if (!page)
 			break;
-		convert_page(inode, page, iomapp, NULL, startio, all_bh);
+		xfs_convert_page(inode, page, iomapp, NULL, startio, all_bh);
 	}
 }
 
@@ -625,7 +669,7 @@
  */
 
 STATIC int
-page_state_convert(
+xfs_page_state_convert(
 	struct inode	*inode,
 	struct page	*page,
 	int		startio,
@@ -668,7 +712,7 @@
 			continue;
 
 		if (iomp) {
-			iomp = match_offset_to_mapping(page, &iomap, p_offset);
+			iomp = xfs_offset_to_map(page, &iomap, p_offset);
 		}
 
 		/*
@@ -677,17 +721,17 @@
 		 */
 		if (buffer_unwritten(bh)) {
 			if (!iomp) {
-				err = map_blocks(inode, offset, len, &iomap,
+				err = xfs_map_blocks(inode, offset, len, &iomap,
 						BMAPI_READ|BMAPI_IGNSTATE);
 				if (err) {
 					goto error;
 				}
-				iomp = match_offset_to_mapping(page, &iomap,
+				iomp = xfs_offset_to_map(page, &iomap,
 								p_offset);
 			}
-			if (iomp) {
+			if (iomp && startio) {
 				if (!bh->b_end_io) {
-					err = map_unwritten(inode, page,
+					err = xfs_map_unwritten(inode, page,
 							head, bh, p_offset,
 							inode->i_blkbits, iomp,
 							startio, unmapped);
@@ -695,12 +739,7 @@
 						goto error;
 					}
 				}
-				if (startio) {
-					bh_arr[cnt++] = bh;
-				} else {
-					unlock_buffer(bh);
-					mark_buffer_dirty(bh);
-				}
+				bh_arr[cnt++] = bh;
 				page_dirty = 0;
 			}
 		/*
@@ -709,17 +748,17 @@
 		 */
 		} else if (buffer_delay(bh)) {
 			if (!iomp) {
-				err = map_blocks(inode, offset, len, &iomap,
-					BMAPI_ALLOCATE | flags);
+				err = xfs_map_blocks(inode, offset, len, &iomap,
+						BMAPI_ALLOCATE | flags);
 				if (err) {
 					goto error;
 				}
-				iomp = match_offset_to_mapping(page, &iomap,
+				iomp = xfs_offset_to_map(page, &iomap,
 								p_offset);
 			}
 			if (iomp) {
-				map_buffer_at_offset(page, bh, p_offset,
-					inode->i_blkbits, iomp);
+				xfs_map_at_offset(page, bh, p_offset,
+						inode->i_blkbits, iomp);
 				if (startio) {
 					bh_arr[cnt++] = bh;
 				} else {
@@ -740,19 +779,19 @@
 				 * need to write the whole page out.
 				 */
 				if (!iomp) {
-					size = probe_unmapped_cluster(
+					size = xfs_probe_unmapped_cluster(
 							inode, page, bh, head);
-					err = map_blocks(inode, offset,
-						size, &iomap,
-						BMAPI_WRITE | BMAPI_MMAP);
+					err = xfs_map_blocks(inode, offset,
+							size, &iomap,
+							BMAPI_WRITE|BMAPI_MMAP);
 					if (err) {
 						goto error;
 					}
-					iomp = match_offset_to_mapping(page, &iomap,
+					iomp = xfs_offset_to_map(page, &iomap,
 								     p_offset);
 				}
 				if (iomp) {
-					map_buffer_at_offset(page,
+					xfs_map_at_offset(page,
 							bh, p_offset,
 							inode->i_blkbits, iomp);
 					if (startio) {
@@ -778,10 +817,10 @@
 		SetPageUptodate(page);
 
 	if (startio)
-		submit_page(page, bh_arr, cnt);
+		xfs_submit_page(page, bh_arr, cnt);
 
 	if (iomp)
-		cluster_write(inode, page->index + 1, iomp, startio, unmapped);
+		xfs_cluster_write(inode, page->index + 1, iomp, startio, unmapped);
 
 	return page_dirty;
 
@@ -841,9 +880,9 @@
 		loff_t			delta;
 
 		/* For unwritten extents do not report a disk address on
-		 * the read case.
+		 * the read case (treat as if we're reading into a hole).
 		 */
-		if (create || ((iomap.iomap_flags & IOMAP_UNWRITTEN) == 0)) {
+		if (create || !(iomap.iomap_flags & IOMAP_UNWRITTEN)) {
 			delta = offset - iomap.iomap_offset;
 			delta >>= inode->i_blkbits;
 
@@ -853,10 +892,7 @@
 			bh_result->b_blocknr = bn;
 			set_buffer_mapped(bh_result);
 		}
-		if (iomap.iomap_flags & IOMAP_UNWRITTEN) {
-			if (create) {
-				set_buffer_mapped(bh_result);
-			}
+		if (create && (iomap.iomap_flags & IOMAP_UNWRITTEN)) {
 			set_buffer_unwritten(bh_result);
 			set_buffer_delay(bh_result);
 		}
@@ -946,7 +982,7 @@
 }
 
 STATIC void
-count_page_state(
+xfs_count_page_state(
 	struct page		*page,
 	int			*delalloc,
 	int			*unmapped,
@@ -998,13 +1034,15 @@
 	int			need_trans;
 	int			delalloc, unmapped, unwritten;
 	struct inode		*inode = page->mapping->host;
-        xfs_pflags_t            pflags;
+	xfs_pflags_t		pflags;
+
+	xfs_page_trace(XFS_WRITEPAGE_ENTER, inode, page, 0);
 
 	/*
 	 * We need a transaction if:
 	 *  1. There are delalloc buffers on the page
-	 *  2. The page is upto date and we have unmapped buffers
-	 *  3. The page is upto date and we have no buffers
+	 *  2. The page is uptodate and we have unmapped buffers
+	 *  3. The page is uptodate and we have no buffers
 	 *  4. There are unwritten buffers on the page
 	 */
 
@@ -1012,7 +1050,7 @@
 		unmapped = 1;
 		need_trans = 1;
 	} else {
-		count_page_state(page, &delalloc, &unmapped, &unwritten);
+		xfs_count_page_state(page, &delalloc, &unmapped, &unwritten);
 		if (!PageUptodate(page))
 			unmapped = 0;
 		need_trans = delalloc + unmapped + unwritten;
@@ -1041,7 +1079,7 @@
 	 */
 	if (need_trans)
 		PFLAGS_SET_NOIO(&pflags);
-	error = page_state_convert(inode, page, 1, unmapped);
+	error = xfs_page_state_convert(inode, page, 1, unmapped);
 	if (need_trans)
 		PFLAGS_RESTORE(&pflags);
 	if (error == -EAGAIN)
@@ -1085,22 +1123,31 @@
 	int			gfp_mask)
 {
 	struct inode		*inode = page->mapping->host;
-	int			delalloc, unmapped, unwritten;
+	int			dirty, delalloc, unmapped, unwritten;
+
+	xfs_page_trace(XFS_RELEASEPAGE_ENTER, inode, page, gfp_mask);
 
-	count_page_state(page, &delalloc, &unmapped, &unwritten);
+	xfs_count_page_state(page, &delalloc, &unmapped, &unwritten);
 	if (!delalloc && !unwritten)
 		return 1;
 
 	if (!(gfp_mask & __GFP_FS))
 		return 0;
 
+	/* If we are already inside a transaction or the thread cannot
+	 * do I/O, we cannot release this page.
+	 */
+	if (PFLAGS_TEST_FSTRANS() || PFLAGS_TEST_NOIO())
+		return 0;
+
 	/*
 	 * Convert delalloc space to real space, do not flush the
 	 * data out to disk, that will be done by the caller.
 	 * Never need to allocate space here - we will always
 	 * come back to writepage in that case.
 	 */
-	return (page_state_convert(inode, page, 0, 0) == 0) ? 1 : 0;
+	dirty = xfs_page_state_convert(inode, page, 0, 0);
+	return (dirty == 0 && !unwritten) ? 1 : 0;
 }
 
 STATIC int
@@ -1155,7 +1202,7 @@
 	map_flags = (rw ? BMAPI_WRITE : BMAPI_READ) | BMAPI_DIRECT;
 	pb_flags = (rw ? PBF_WRITE : PBF_READ) | PBF_FORCEIO | PBF_DIRECTIO;
 	while (length) {
-		error = map_blocks(inode, offset, length, &iomap, map_flags);
+		error = xfs_map_blocks(inode, offset, length, &iomap, map_flags);
 		if (error)
 			break;
 		BUG_ON(iomap.iomap_flags & IOMAP_DELAY);
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_buf.c linux-2.4.26-pre2/fs/xfs/linux/xfs_buf.c
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_buf.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_buf.c	2004-03-06 11:20:29.000000000 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -56,18 +56,8 @@
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
 
-#include <support/ktrace.h>
-#include <support/debug.h>
-#include "kmem.h"
-
-#include "xfs_types.h"
-#include "xfs_cred.h"
-#include "xfs_lrw.h"
-#include "xfs_buf.h"
-
-#define NBBY		8
-#define BBSHIFT		9
-#define BBMASK		((1 << BBSHIFT) - 1)
+#include "xfs_linux.h"
+
 #define BN_ALIGN_MASK	((1 << (PAGE_CACHE_SHIFT - BBSHIFT)) - 1)
 
 #ifndef GFP_READAHEAD
@@ -128,63 +118,12 @@
 struct buffer_head		*pb_resv_bh = NULL;	/* list of bh */
 int				pb_resv_bh_cnt = 0;	/* # of bh available */
 
-STATIC void pagebuf_daemon_wakeup(int);
+STATIC void pagebuf_daemon_wakeup(void);
 STATIC void _pagebuf_ioapply(page_buf_t *);
 STATIC void pagebuf_delwri_queue(page_buf_t *, int);
 STATIC void pagebuf_runall_queues(struct list_head[]);
 
 /*
- * Pagebuf module configuration parameters, exported via
- * /proc/sys/vm/pagebuf
- */
-
-typedef struct pb_sysctl_val {
-	int	min;
-	int	val;
-	int	max;
-} pb_sysctl_val_t;
-
-struct {
-	pb_sysctl_val_t	flush_interval;	/* interval between runs of the
-					 * delwri flush daemon.  */
-	pb_sysctl_val_t	age_buffer;	/* time for buffer to age before
-					 * we flush it.  */
-	pb_sysctl_val_t	stats_clear;	/* clear the pagebuf stats */
-	pb_sysctl_val_t	debug;		/* debug tracing on or off */
-} pb_params = {
-			  /*	MIN	DFLT	MAX	*/
-	.flush_interval	= {	HZ/2,	HZ,	30*HZ	},
-	.age_buffer	= {	1*HZ,	15*HZ,	300*HZ	},
-	.stats_clear	= {	0,	0,	1	},
-	.debug		= {	0,	0,	1	},
-};
-
-enum {
-	PB_FLUSH_INT = 1,
-	PB_FLUSH_AGE = 2,
-	PB_STATS_CLEAR = 3,
-	PB_DEBUG = 4,
-};
-
-/*
- * Pagebuf statistics variables
- */
-
-struct {
-	u_int32_t	pb_get;
-	u_int32_t	pb_create;
-	u_int32_t	pb_get_locked;
-	u_int32_t	pb_get_locked_waited;
-	u_int32_t	pb_busy_locked;
-	u_int32_t	pb_miss_locked;
-	u_int32_t	pb_page_retries;
-	u_int32_t	pb_page_found;
-	u_int32_t	pb_get_read;
-} pbstats;
-
-#define PB_STATS_INC(count)	( pbstats.count++ )
-
-/*
  * Pagebuf debugging
  */
 
@@ -196,8 +135,6 @@
 	void		*data,
 	void		*ra)
 {
-	if (!pb_params.debug.val)
-		return;
 	ktrace_enter(pagebuf_trace_buf,
 		pb, id,
 		(void *)(unsigned long)pb->pb_flags,
@@ -254,7 +191,6 @@
 
 typedef struct {
 	struct list_head	pb_hash;
-	int			pb_count;
 	spinlock_t		pb_hash_lock;
 } pb_hash_t;
 
@@ -372,7 +308,7 @@
 	atomic_set(&pb->pb_pin_count, 0);
 	init_waitqueue_head(&pb->pb_waiters);
 
-	PB_STATS_INC(pb_create);
+	XFS_STATS_INC(pb_create);
 	PB_TRACE(pb, "initialize", target);
 }
 
@@ -386,8 +322,6 @@
 	int			page_count,
 	page_buf_flags_t	flags)
 {
-	int			gpf_mask = pb_to_gfp(flags);
-
 	/* Make sure that we have a page list */
 	if (pb->pb_pages == NULL) {
 		pb->pb_offset = page_buf_poff(pb->pb_file_offset);
@@ -395,8 +329,8 @@
 		if (page_count <= PB_PAGES) {
 			pb->pb_pages = pb->pb_page_array;
 		} else {
-			pb->pb_pages = kmalloc(sizeof(struct page *) *
-					page_count, gpf_mask);
+			pb->pb_pages = kmem_alloc(sizeof(struct page *) *
+					page_count, pb_to_km(flags));
 			if (pb->pb_pages == NULL)
 				return -ENOMEM;
 		}
@@ -425,53 +359,41 @@
 }
 
 /*
- *	_pagebuf_free_object
+ *	pagebuf_free
  *
- *	_pagebuf_free_object releases the contents specified buffer.
- *	The modification state of any associated pages is left unchanged.
+ *	pagebuf_free releases the specified buffer.  The modification
+ *	state of any associated pages is left unchanged.
  */
 void
-_pagebuf_free_object(
-	pb_hash_t		*hash,	/* hash bucket for buffer */
-	page_buf_t		*pb)	/* buffer to deallocate	*/
-{
-	page_buf_flags_t	pb_flags = pb->pb_flags;
-
-	PB_TRACE(pb, "free_object", 0);
-	pb->pb_flags |= PBF_FREED;
-
-	if (hash) {
-		if (!list_empty(&pb->pb_hash_list)) {
-			hash->pb_count--;
-			list_del_init(&pb->pb_hash_list);
-		}
-		spin_unlock(&hash->pb_hash_lock);
-	}
+pagebuf_free(
+	page_buf_t		*pb)
+{
+	PB_TRACE(pb, "free", 0);
+	
+	ASSERT(list_empty(&pb->pb_hash_list));
 
-	if (!(pb_flags & PBF_FREED)) {
-		/* release any virtual mapping */ ;
-		if (pb->pb_flags & _PBF_ADDR_ALLOCATED) {
-			void *vaddr = pagebuf_mapout_locked(pb);
-			if (vaddr) {
-				free_address(vaddr);
-			}
+	/* release any virtual mapping */ ;
+	if (pb->pb_flags & _PBF_ADDR_ALLOCATED) {
+		void *vaddr = pagebuf_mapout_locked(pb);
+		if (vaddr) {
+			free_address(vaddr);
 		}
+	}
 
-		if (pb->pb_flags & _PBF_MEM_ALLOCATED) {
-			if (pb->pb_pages) {
-				/* release the pages in the address list */
-				if ((pb->pb_pages[0]) &&
-				    (pb->pb_flags & _PBF_MEM_SLAB)) {
-					kfree(pb->pb_addr);
-				} else {
-					_pagebuf_freepages(pb);
-				}
-				if (pb->pb_pages != pb->pb_page_array)
-					kfree(pb->pb_pages);
-				pb->pb_pages = NULL;
+	if (pb->pb_flags & _PBF_MEM_ALLOCATED) {
+		if (pb->pb_pages) {
+			/* release the pages in the address list */
+			if ((pb->pb_pages[0]) &&
+			    (pb->pb_flags & _PBF_MEM_SLAB)) {
+				kfree(pb->pb_addr);
+			} else {
+				_pagebuf_freepages(pb);
 			}
-			pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB);
+			if (pb->pb_pages != pb->pb_page_array)
+				kfree(pb->pb_pages);
+			pb->pb_pages = NULL;
 		}
+		pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB);
 	}
 
 	pagebuf_deallocate(pb);
@@ -496,32 +418,11 @@
 	loff_t			next_buffer_offset;
 	unsigned long		page_count, pi, index;
 	struct page		*page;
-	int			gfp_mask, retry_count = 5, rval = 0;
-	int			all_mapped, good_pages;
+	int			gfp_mask = pb_to_gfp(flags);
+	int			all_mapped, good_pages, rval, retries;
 	size_t			blocksize;
 
-	/* For pagebufs where we want to map an address, do not use
-	 * highmem pages - so that we do not need to use kmap resources
-	 * to access the data.
-	 *
-	 * For pages where the caller has indicated there may be resource
-	 * contention (e.g. called from a transaction) do not flush
-	 * delalloc pages to obtain memory.
-	 */
-
-	if (flags & PBF_READ_AHEAD) {
-		gfp_mask = GFP_READAHEAD;
-		retry_count = 0;
-	} else if (flags & PBF_DONT_BLOCK) {
-		gfp_mask = GFP_NOFS;
-	} else if (flags & PBF_MAPPABLE) {
-		gfp_mask = GFP_KERNEL;
-	} else {
-		gfp_mask = GFP_HIGHUSER;
-	}
-
 	next_buffer_offset = pb->pb_file_offset + pb->pb_buffer_length;
-
 	good_pages = page_count = (page_buf_btoc(next_buffer_offset) -
 				   page_buf_btoct(pb->pb_file_offset));
 
@@ -532,6 +433,7 @@
 		}
 		if ((flags & PBF_MAPPED) && !(pb->pb_flags & PBF_MAPPED)) {
 			all_mapped = 1;
+			rval = 0;
 			goto mapit;
 		}
 		return 0;
@@ -549,21 +451,30 @@
 	index = (pb->pb_file_offset - pb->pb_offset) >> PAGE_CACHE_SHIFT;
 	for (pi = 0; pi < page_count; pi++, index++) {
 		if (pb->pb_pages[pi] == 0) {
+			retries = 0;
 		      retry:
 			page = find_or_create_page(aspace, index, gfp_mask);
 			if (!page) {
-				if (--retry_count > 0) {
-					PB_STATS_INC(pb_page_retries);
-					pagebuf_daemon_wakeup(1);
-					current->state = TASK_UNINTERRUPTIBLE;
-					schedule_timeout(10);
-					goto retry;
+				if (flags & PBF_READ_AHEAD)
+					return -ENOMEM;
+				/*
+				 * This could deadlock.  But until all the
+				 * XFS lowlevel code is revamped to handle
+				 * buffer allocation failures we can't do
+				 * much.
+				 */
+				if (!(++retries % 100)) {
+					printk(KERN_ERR
+					       "possibly deadlocking in %s\n",
+					       __FUNCTION__);
 				}
-				rval = -ENOMEM;
-				all_mapped = 0;
-				continue;
+				XFS_STATS_INC(pb_page_retries);
+				pagebuf_daemon_wakeup();
+				current->state = TASK_UNINTERRUPTIBLE;
+				schedule_timeout(10);
+				goto retry;
 			}
-			PB_STATS_INC(pb_page_found);
+			XFS_STATS_INC(pb_page_found);
 			mark_page_accessed(page);
 			pb->pb_pages[pi] = page;
 		} else {
@@ -587,6 +498,7 @@
 		}
 	}
 
+	pb->pb_flags |= _PBF_PAGECACHE;
 mapit:
 	pb->pb_flags |= _PBF_MEM_ALLOCATED;
 	if (all_mapped) {
@@ -780,16 +692,14 @@
 	list_for_each(p, &h->pb_hash) {
 		pb = list_entry(p, page_buf_t, pb_hash_list);
 
-		if ((target == pb->pb_target) &&
-		    (pb->pb_file_offset == range_base) &&
-		    (pb->pb_buffer_length == range_length)) {
-			if (pb->pb_flags & PBF_FREED)
-				break;
+		if (pb->pb_target == target &&
+		    pb->pb_file_offset == range_base &&
+		    pb->pb_buffer_length == range_length) {
 			/* If we look at something bring it to the
 			 * front of the list for next time
 			 */
-			list_del(&pb->pb_hash_list);
-			list_add(&pb->pb_hash_list, &h->pb_hash);
+			atomic_inc(&pb->pb_hold);
+			list_move(&pb->pb_hash_list, &h->pb_hash);
 			goto found;
 		}
 	}
@@ -797,19 +707,17 @@
 	/* No match found */
 	if (new_pb) {
 		_pagebuf_initialize(new_pb, target, range_base,
-				range_length, flags | _PBF_LOCKABLE);
+				range_length, flags);
 		new_pb->pb_hash_index = hval;
-		h->pb_count++;
 		list_add(&new_pb->pb_hash_list, &h->pb_hash);
 	} else {
-		PB_STATS_INC(pb_miss_locked);
+		XFS_STATS_INC(pb_miss_locked);
 	}
 
 	spin_unlock(&h->pb_hash_lock);
 	return (new_pb);
 
 found:
-	atomic_inc(&pb->pb_hold);
 	spin_unlock(&h->pb_hash_lock);
 
 	/* Attempt to get the semaphore without sleeping,
@@ -822,7 +730,7 @@
 			/* wait for buffer ownership */
 			PB_TRACE(pb, "get_lock", 0);
 			pagebuf_lock(pb);
-			PB_STATS_INC(pb_get_locked_waited);
+			XFS_STATS_INC(pb_get_locked_waited);
 		} else {
 			/* We asked for a trylock and failed, no need
 			 * to look at file offset and length here, we
@@ -832,7 +740,7 @@
 			 */
 
 			pagebuf_rele(pb);
-			PB_STATS_INC(pb_busy_locked);
+			XFS_STATS_INC(pb_busy_locked);
 			return (NULL);
 		}
 	} else {
@@ -841,15 +749,13 @@
 	}
 
 	if (pb->pb_flags & PBF_STALE)
-		pb->pb_flags &= PBF_MAPPABLE | \
-				PBF_MAPPED | \
-				_PBF_LOCKABLE | \
+		pb->pb_flags &= PBF_MAPPED | \
 				_PBF_ALL_PAGES_MAPPED | \
 				_PBF_ADDR_ALLOCATED | \
 				_PBF_MEM_ALLOCATED | \
 				_PBF_MEM_SLAB;
 	PB_TRACE(pb, "got_lock", 0);
-	PB_STATS_INC(pb_get_locked);
+	XFS_STATS_INC(pb_get_locked);
 	return (pb);
 }
 
@@ -905,13 +811,14 @@
 			return (NULL);
 	}
 
-	PB_STATS_INC(pb_get);
+	XFS_STATS_INC(pb_get);
 
 	/* fill in any missing pages */
 	error = _pagebuf_lookup_pages(pb, pb->pb_target->pbr_mapping, flags);
 	if (unlikely(error)) {
-		pagebuf_free(pb);
-		return (NULL);
+		printk(KERN_WARNING
+			"pagebuf_get: warning, failed to lookup pages\n");
+		goto no_buffer;
 	}
 
 	/*
@@ -924,7 +831,7 @@
 	if (flags & PBF_READ) {
 		if (PBF_NOT_DONE(pb)) {
 			PB_TRACE(pb, "get_read", (unsigned long)flags);
-			PB_STATS_INC(pb_get_read);
+			XFS_STATS_INC(pb_get_read);
 			pagebuf_iostart(pb, flags);
 		} else if (flags & PBF_ASYNC) {
 			PB_TRACE(pb, "get_read_async", (unsigned long)flags);
@@ -932,10 +839,7 @@
 			 * Read ahead call which is already satisfied,
 			 * drop the buffer
 			 */
-			if (flags & (PBF_LOCK | PBF_TRYLOCK))
-				pagebuf_unlock(pb);
-			pagebuf_rele(pb);
-			return NULL;
+			goto no_buffer;
 		} else {
 			PB_TRACE(pb, "get_read_done", (unsigned long)flags);
 			/* We do not want read in the flags */
@@ -944,7 +848,14 @@
 	} else {
 		PB_TRACE(pb, "get_write", (unsigned long)flags);
 	}
-	return (pb);
+
+	return pb;
+
+no_buffer:
+	if (flags & (PBF_LOCK | PBF_TRYLOCK))
+		pagebuf_unlock(pb);
+	pagebuf_rele(pb);
+	return NULL;
 }
 
 /*
@@ -959,7 +870,7 @@
 {
 	page_buf_t		*pb;
 
-	flags |= _PBF_PRIVATE_BH | _PBF_LOCKABLE;
+	flags |= _PBF_PRIVATE_BH;
 	pb = pagebuf_allocate(flags);
 	if (pb) {
 		_pagebuf_initialize(pb, target, ioff, isize, flags);
@@ -978,7 +889,7 @@
 	size_t			isize,
 	page_buf_flags_t	flags)
 {
-	flags |= (PBF_TRYLOCK|PBF_READ|PBF_ASYNC|PBF_MAPPABLE|PBF_READ_AHEAD);
+	flags |= (PBF_TRYLOCK|PBF_READ|PBF_ASYNC|PBF_READ_AHEAD);
 	pagebuf_get(target, ioff, isize, flags);
 }
 
@@ -989,9 +900,9 @@
 {
 	page_buf_t		*pb;
 
-	pb = pagebuf_allocate(_PBF_LOCKABLE);
+	pb = pagebuf_allocate(0);
 	if (pb)
-		_pagebuf_initialize(pb, target, 0, len, _PBF_LOCKABLE);
+		_pagebuf_initialize(pb, target, 0, len, 0);
 	return pb;
 }
 
@@ -1065,7 +976,7 @@
 {
 	int			rval;
 	void			*rmem = NULL;
-	page_buf_flags_t	flags = _PBF_LOCKABLE | PBF_FORCEIO;
+	page_buf_flags_t	flags = PBF_FORCEIO;
 	page_buf_t		*pb;
 	size_t			tlen = 0;
 
@@ -1124,26 +1035,6 @@
 }
 
 /*
- *	pagebuf_free
- *
- *	pagebuf_free releases the specified buffer.  The modification
- *	state of any associated pages is left unchanged.
- */
-void
-pagebuf_free(
-	page_buf_t		*pb)
-{
-	if (pb->pb_flags & _PBF_LOCKABLE) {
-		pb_hash_t	*h = pb_hash(pb);
-
-		spin_lock(&h->pb_hash_lock);
-		_pagebuf_free_object(h, pb);
-	} else {
-		_pagebuf_free_object(NULL, pb);
-	}
-}
-
-/*
  *	pagebuf_rele
  *
  *	pagebuf_rele releases a hold on the specified buffer.  If the
@@ -1153,44 +1044,37 @@
 pagebuf_rele(
 	page_buf_t		*pb)
 {
-	pb_hash_t		*h;
+	pb_hash_t		*hash = pb_hash(pb);
 
 	PB_TRACE(pb, "rele", pb->pb_relse);
-	if (pb->pb_flags & _PBF_LOCKABLE) {
-		h = pb_hash(pb);
-		spin_lock(&h->pb_hash_lock);
-	} else {
-		h = NULL;
-	}
 
-	if (atomic_dec_and_test(&pb->pb_hold)) {
+	if (atomic_dec_and_lock(&pb->pb_hold, &hash->pb_hash_lock)) {
 		int		do_free = 1;
 
 		if (pb->pb_relse) {
 			atomic_inc(&pb->pb_hold);
-			if (h)
-				spin_unlock(&h->pb_hash_lock);
+			spin_unlock(&hash->pb_hash_lock);
 			(*(pb->pb_relse)) (pb);
+			spin_lock(&hash->pb_hash_lock);
 			do_free = 0;
 		}
+
 		if (pb->pb_flags & PBF_DELWRI) {
 			pb->pb_flags |= PBF_ASYNC;
 			atomic_inc(&pb->pb_hold);
-			if (h && do_free)
-				spin_unlock(&h->pb_hash_lock);
 			pagebuf_delwri_queue(pb, 0);
 			do_free = 0;
 		} else if (pb->pb_flags & PBF_FS_MANAGED) {
-			if (h)
-				spin_unlock(&h->pb_hash_lock);
 			do_free = 0;
 		}
 
 		if (do_free) {
-			_pagebuf_free_object(h, pb);
+			list_del_init(&pb->pb_hash_list);
+			spin_unlock(&hash->pb_hash_lock);
+			pagebuf_free(pb);
+		} else {
+			spin_unlock(&hash->pb_hash_lock);
 		}
-	} else if (h) {
-		spin_unlock(&h->pb_hash_lock);
 	}
 }
 
@@ -1221,7 +1105,6 @@
 {
 	int			locked;
 
-	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
 	locked = down_trylock(&pb->pb_sema) == 0;
 	if (locked) {
 		PB_SET_OWNER(pb);
@@ -1239,7 +1122,6 @@
 pagebuf_lock_value(
 	page_buf_t		*pb)
 {
-	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
 	return(atomic_read(&pb->pb_sema.count));
 }
 
@@ -1255,8 +1137,6 @@
 pagebuf_lock(
 	page_buf_t		*pb)
 {
-	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
-
 	PB_TRACE(pb, "lock", 0);
 	if (atomic_read(&pb->pb_io_remaining))
 		blk_run_queues();
@@ -1277,7 +1157,6 @@
 pagebuf_unlock(				/* unlock buffer		*/
 	page_buf_t		*pb)	/* buffer to unlock		*/
 {
-	ASSERT(pb->pb_flags & _PBF_LOCKABLE);
 	PB_CLEAR_OWNER(pb);
 	up(&pb->pb_sema);
 	PB_TRACE(pb, "unlock", 0);
@@ -1387,7 +1266,7 @@
 	}
 
 	if (pb->pb_flags & PBF_ASYNC) {
-		if ((pb->pb_flags & _PBF_LOCKABLE) && !pb->pb_relse)
+		if (!pb->pb_relse)
 			pagebuf_unlock(pb);
 		pagebuf_rele(pb);
 	}
@@ -1457,7 +1336,7 @@
 	page_buf_t		*pb,	/* buffer to start		  */
 	page_buf_flags_t	flags)	/* PBF_LOCK, PBF_ASYNC, PBF_READ, */
 					/* PBF_WRITE, PBF_DELWRI,	  */
-					/* PBF_SYNC, PBF_DONT_BLOCK	  */
+					/* PBF_DONT_BLOCK		  */
 {
 	int			status = 0;
 
@@ -1465,16 +1344,15 @@
 
 	if (flags & PBF_DELWRI) {
 		pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC);
-		pb->pb_flags |= flags &
-				(PBF_DELWRI | PBF_ASYNC | PBF_SYNC);
+		pb->pb_flags |= flags & (PBF_DELWRI | PBF_ASYNC);
 		pagebuf_delwri_queue(pb, 1);
 		return status;
 	}
 
-	pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC | \
-			PBF_DELWRI | PBF_READ_AHEAD | PBF_RUN_QUEUES);
+	pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC | PBF_DELWRI | \
+			PBF_READ_AHEAD | PBF_RUN_QUEUES);
 	pb->pb_flags |= flags & (PBF_READ | PBF_WRITE | PBF_ASYNC | \
-			PBF_SYNC | PBF_READ_AHEAD | PBF_RUN_QUEUES);
+			PBF_READ_AHEAD | PBF_RUN_QUEUES);
 
 	BUG_ON(pb->pb_bn == PAGE_BUF_DADDR_NULL);
 
@@ -1510,7 +1388,7 @@
 		return pb->pb_locked;
 	if (pb->pb_flags & PBF_READ)
 		return pb->pb_locked;
-	return (!(pb->pb_flags & _PBF_LOCKABLE));
+	return (pb->pb_flags & _PBF_PAGECACHE);
 }
 
 STATIC void
@@ -2000,7 +1878,6 @@
  * Pagebuf delayed write buffer handling
  */
 
-STATIC int pbd_active = 1;
 STATIC LIST_HEAD(pbd_delwrite_queue);
 STATIC spinlock_t pbd_delwrite_lock = SPIN_LOCK_UNLOCKED;
 
@@ -2020,12 +1897,11 @@
 	}
 
 	list_add_tail(&pb->pb_list, &pbd_delwrite_queue);
-	pb->pb_flushtime = jiffies + pb_params.age_buffer.val;
+	pb->pb_flushtime = jiffies + xfs_age_buffer;
 	spin_unlock(&pbd_delwrite_lock);
 
-	if (unlock && (pb->pb_flags & _PBF_LOCKABLE)) {
+	if (unlock)
 		pagebuf_unlock(pb);
-	}
 }
 
 void
@@ -2062,10 +1938,10 @@
 	daemonize();
 
 	/* Avoid signals */
-	spin_lock_irq(&current->sigmask_lock);
+	sigmask_lock();
 	sigfillset(&current->blocked);
-	recalc_sigpending(current);
-	spin_unlock_irq(&current->sigmask_lock);
+	__recalc_sigpending(current);
+	sigmask_unlock();
 
 	/* Migrate to the right CPU */
 	migrate_to_cpu(cpu);
@@ -2134,21 +2010,19 @@
 
 
 /* Defines for pagebuf daemon */
-DECLARE_WAIT_QUEUE_HEAD(pbd_waitq);
+STATIC DECLARE_COMPLETION(pagebuf_daemon_done);
+STATIC struct task_struct *pagebuf_daemon_task;
+STATIC int pagebuf_daemon_active;
 STATIC int force_flush;
 
 STATIC void
-pagebuf_daemon_wakeup(
-	int			flag)
+pagebuf_daemon_wakeup(void)
 {
-	force_flush = flag;
-	if (waitqueue_active(&pbd_waitq)) {
-		wake_up_interruptible(&pbd_waitq);
-	}
+	force_flush = 1;
+	barrier();
+	wake_up_process(pagebuf_daemon_task);
 }
 
-typedef void (*timeout_fn)(unsigned long);
-
 STATIC int
 pagebuf_daemon(
 	void			*data)
@@ -2156,32 +2030,28 @@
 	int			count;
 	page_buf_t		*pb;
 	struct list_head	*curr, *next, tmp;
-	struct timer_list	pb_daemon_timer =
-		{ {NULL, NULL}, 0, 0, (timeout_fn)pagebuf_daemon_wakeup };
 
 	/*  Set up the thread  */
 	daemonize();
 
+	/* Mark it active */
+	pagebuf_daemon_task = current;
+	pagebuf_daemon_active = 1;
+	barrier();
+
 	/* Avoid signals */
-	spin_lock_irq(&current->sigmask_lock);
+	sigmask_lock();
 	sigfillset(&current->blocked);
-	recalc_sigpending(current);
-	spin_unlock_irq(&current->sigmask_lock);
+	__recalc_sigpending(current);
+	sigmask_unlock();
 
-	strcpy(current->comm, "pagebufd");
+	strcpy(current->comm, "xfsbufd");
 	current->flags |= PF_MEMALLOC;
 
 	INIT_LIST_HEAD(&tmp);
 	do {
-		if (pbd_active == 1) {
-			mod_timer(&pb_daemon_timer,
-				  jiffies + pb_params.flush_interval.val);
-			interruptible_sleep_on(&pbd_waitq);
-		}
-
-		if (pbd_active == 0) {
-			del_timer_sync(&pb_daemon_timer);
-		}
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(xfs_flush_interval);
 
 		spin_lock(&pbd_delwrite_lock);
 
@@ -2191,10 +2061,8 @@
 
 			PB_TRACE(pb, "walkq1", (long)pagebuf_ispin(pb));
 
-			if ((pb->pb_flags & PBF_DELWRI) && !pagebuf_ispin(pb) &&
-			    (((pb->pb_flags & _PBF_LOCKABLE) == 0) ||
-			     !pagebuf_cond_lock(pb))) {
-
+			if ((pb->pb_flags & PBF_DELWRI) &&
+			     !pagebuf_ispin(pb) && !pagebuf_cond_lock(pb)) {
 				if (!force_flush &&
 				    time_before(jiffies, pb->pb_flushtime)) {
 					pagebuf_unlock(pb);
@@ -2203,10 +2071,7 @@
 
 				pb->pb_flags &= ~PBF_DELWRI;
 				pb->pb_flags |= PBF_WRITE;
-
-				list_del(&pb->pb_list);
-				list_add(&pb->pb_list, &tmp);
-
+				list_move(&pb->pb_list, &tmp);
 				count++;
 			}
 		}
@@ -2225,12 +2090,9 @@
 			blk_run_queues();
 
 		force_flush = 0;
-	} while (pbd_active == 1);
-
-	pbd_active = -1;
-	wake_up_interruptible(&pbd_waitq);
+	} while (pagebuf_daemon_active);
 
-	return 0;
+	complete_and_exit(&pagebuf_daemon_done, 0);
 }
 
 void
@@ -2359,10 +2221,9 @@
 {
 	int		cpu, pcpu;
 
-	pbd_active = 0;
-
-	wake_up_interruptible(&pbd_waitq);
-	wait_event_interruptible(pbd_waitq, pbd_active);
+	pagebuf_daemon_active = 0;
+	barrier();
+	wait_for_completion(&pagebuf_daemon_done);
 
 	for (pcpu = 0; pcpu < min(smp_num_cpus, MAX_IO_DAEMONS); pcpu++) {
 		cpu = CPU_TO_DAEMON(cpu_logical_map(pcpu));
@@ -2380,107 +2241,10 @@
 }
 
 
-/*
- * Pagebuf sysctl interface
- */
-
-STATIC int
-pb_stats_clear_handler(
-	ctl_table		*ctl,
-	int			write,
-	struct file		*filp,
-	void			*buffer,
-	size_t			*lenp)
-{
-	int			ret;
-	int			*valp = ctl->data;
-
-	ret = proc_dointvec_minmax(ctl, write, filp, buffer, lenp);
-
-	if (!ret && write && *valp) {
-		printk("XFS Clearing pbstats\n");
-		memset(&pbstats, 0, sizeof(pbstats));
-		pb_params.stats_clear.val = 0;
-	}
-
-	return ret;
-}
-
-STATIC struct ctl_table_header *pagebuf_table_header;
-
-STATIC ctl_table pagebuf_table[] = {
-	{PB_FLUSH_INT, "flush_int", &pb_params.flush_interval.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL,
-	&pb_params.flush_interval.min, &pb_params.flush_interval.max},
-
-	{PB_FLUSH_AGE, "flush_age", &pb_params.age_buffer.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL, 
-	&pb_params.age_buffer.min, &pb_params.age_buffer.max},
-
-	{PB_STATS_CLEAR, "stats_clear", &pb_params.stats_clear.val,
-	sizeof(int), 0644, NULL, &pb_stats_clear_handler,
-	&sysctl_intvec, NULL, 
-	&pb_params.stats_clear.min, &pb_params.stats_clear.max},
-
-#ifdef PAGEBUF_TRACE
-	{PB_DEBUG, "debug", &pb_params.debug.val,
-	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
-	&sysctl_intvec, NULL, 
-	&pb_params.debug.min, &pb_params.debug.max},
-#endif
-	{0}
-};
-
-STATIC ctl_table pagebuf_dir_table[] = {
-	{VM_PAGEBUF, "pagebuf", NULL, 0, 0555, pagebuf_table},
-	{0}
-};
-
-STATIC ctl_table pagebuf_root_table[] = {
-	{CTL_VM, "vm",  NULL, 0, 0555, pagebuf_dir_table},
-	{0}
-};
-
-#ifdef CONFIG_PROC_FS
-STATIC int
-pagebuf_readstats(
-	char			*buffer,
-	char			**start,
-	off_t			offset,
-	int			count,
-	int			*eof,
-	void			*data)
-{
-	int			i, len;
-
-	len = 0;
-	len += sprintf(buffer + len, "pagebuf");
-	for (i = 0; i < sizeof(pbstats) / sizeof(u_int32_t); i++) {
-		len += sprintf(buffer + len, " %u",
-			*(((u_int32_t*)&pbstats) + i));
-	}
-	buffer[len++] = '\n';
-
-	if (offset >= len) {
-		*start = buffer;
-		*eof = 1;
-		return 0;
-	}
-	*start = buffer + offset;
-	if ((len -= offset) > count)
-		return count;
-	*eof = 1;
-
-	return len;
-}
-#endif  /* CONFIG_PROC_FS */
-
 STATIC int
 pagebuf_shaker(int number, unsigned int mask)
 {
-	pagebuf_daemon_wakeup(1);
+	pagebuf_daemon_wakeup();
 	return 0;
 }
 
@@ -2494,14 +2258,6 @@
 {
 	int			i;
 
-	pagebuf_table_header = register_sysctl_table(pagebuf_root_table, 1);
-
-#ifdef CONFIG_PROC_FS
-	if (proc_mkdir("fs/pagebuf", 0))
-		create_proc_read_entry(
-			"fs/pagebuf/stat", 0, 0, pagebuf_readstats, NULL);
-#endif
-
 	pagebuf_cache = kmem_cache_create("page_buf_t", sizeof(page_buf_t), 0,
 			SLAB_HWCACHE_ALIGN, NULL, NULL);
 	if (pagebuf_cache == NULL) {
@@ -2549,10 +2305,4 @@
 
 	kmem_cache_destroy(pagebuf_cache);
 	kmem_shake_deregister(pagebuf_shaker);
-
-	unregister_sysctl_table(pagebuf_table_header);
-#ifdef  CONFIG_PROC_FS
-	remove_proc_entry("fs/pagebuf/stat", NULL);
-	remove_proc_entry("fs/pagebuf", NULL);
-#endif
 }
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_buf.h linux-2.4.26-pre2/fs/xfs/linux/xfs_buf.h
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_buf.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_buf.h	2004-03-06 11:20:29.000000000 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -47,6 +47,16 @@
 #include <linux/fs.h>
 #include <linux/uio.h>
 
+/* nptl patch changes where the sigmask_lock is defined */
+#ifdef CLONE_SIGNAL /* stock */
+#define sigmask_lock()		spin_lock_irq(&current->sigmask_lock);
+#define sigmask_unlock()	spin_unlock_irq(&current->sigmask_lock);
+#define __recalc_sigpending(x)	recalc_sigpending(x)
+#else /* nptl */
+#define sigmask_lock()		spin_lock_irq(&current->sighand->siglock);
+#define sigmask_unlock()	spin_unlock_irq(&current->sighand->siglock);
+#define __recalc_sigpending(x)	recalc_sigpending()
+#endif
 /*
  *	Base types
  */
@@ -76,9 +86,6 @@
 	PBF_ASYNC = (1 << 4),   /* initiator will not wait for completion  */
 	PBF_NONE = (1 << 5),    /* buffer not read at all                  */
 	PBF_DELWRI = (1 << 6),  /* buffer has dirty pages                  */
-	PBF_FREED = (1 << 7),   /* buffer has been freed and is invalid    */
-	PBF_SYNC = (1 << 8),    /* force updates to disk                   */
-	PBF_MAPPABLE = (1 << 9),/* use directly-addressable pages          */
 	PBF_STALE = (1 << 10),	/* buffer has been staled, do not find it  */
 	PBF_FS_MANAGED = (1 << 11), /* filesystem controls freeing memory  */
 	PBF_FS_DATAIOD = (1 << 12), /* schedule IO completion on fs datad  */
@@ -89,7 +96,7 @@
 	PBF_DONT_BLOCK = (1 << 15), /* do not block in current thread	   */
 
 	/* flags used only internally */
-	_PBF_LOCKABLE = (1 << 16), /* page_buf_t may be locked		   */
+	_PBF_PAGECACHE = (1 << 16),	/* backed by pagecache		   */
 	_PBF_PRIVATE_BH = (1 << 17), /* do not use public buffer heads	   */
 	_PBF_ALL_PAGES_MAPPED = (1 << 18), /* all pages in range mapped	   */
 	_PBF_ADDR_ALLOCATED = (1 << 19), /* pb_addr space was allocated	   */
@@ -205,7 +212,7 @@
 		loff_t,			/* starting offset of range	*/
 		size_t,			/* length of range		*/
 		page_buf_flags_t);	/* PBF_READ, PBF_WRITE,		*/
-					/* PBF_FORCEIO, _PBF_LOCKABLE	*/
+					/* PBF_FORCEIO, 		*/
 
 extern page_buf_t *pagebuf_get_empty(	/* allocate pagebuf struct with	*/
 					/*  no memory or disk address	*/
@@ -270,7 +277,7 @@
 		page_buf_t *,		/* buffer to start		*/
 		page_buf_flags_t);	/* PBF_LOCK, PBF_ASYNC,		*/
 					/* PBF_READ, PBF_WRITE,		*/
-					/* PBF_DELWRI, PBF_SYNC		*/
+					/* PBF_DELWRI			*/
 
 extern int pagebuf_iorequest(		/* start real I/O		*/
 		page_buf_t *);		/* buffer to convey to device	*/
@@ -403,7 +410,7 @@
 
 #define XFS_BUF_BFLAGS(x)	((x)->pb_flags)
 #define XFS_BUF_ZEROFLAGS(x)	\
-	((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_SYNC|PBF_DELWRI))
+	((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_DELWRI))
 
 #define XFS_BUF_STALE(x)	((x)->pb_flags |= XFS_B_STALE)
 #define XFS_BUF_UNSTALE(x)	((x)->pb_flags &= ~XFS_B_STALE)
@@ -555,17 +562,15 @@
 
 #define xfs_buf_read(target, blkno, len, flags) \
 		pagebuf_get((target), (blkno), (len), \
-			PBF_LOCK | PBF_READ | PBF_MAPPED | PBF_MAPPABLE)
+			PBF_LOCK | PBF_READ | PBF_MAPPED)
 #define xfs_buf_get(target, blkno, len, flags) \
 		pagebuf_get((target), (blkno), (len), \
-			PBF_LOCK | PBF_MAPPED | PBF_MAPPABLE)
+			PBF_LOCK | PBF_MAPPED)
 
 #define xfs_buf_read_flags(target, blkno, len, flags) \
-		pagebuf_get((target), (blkno), (len), \
-			PBF_READ | PBF_MAPPABLE | flags)
+		pagebuf_get((target), (blkno), (len), PBF_READ | (flags))
 #define xfs_buf_get_flags(target, blkno, len, flags) \
-		pagebuf_get((target), (blkno), (len), \
-			PBF_MAPPABLE | flags)
+		pagebuf_get((target), (blkno), (len), (flags))
 
 static inline int	xfs_bawrite(void *mp, page_buf_t *bp)
 {
@@ -577,7 +582,7 @@
 
 static inline void	xfs_buf_relse(page_buf_t *bp)
 {
-	if ((bp->pb_flags & _PBF_LOCKABLE) && !bp->pb_relse)
+	if (!bp->pb_relse)
 		pagebuf_unlock(bp);
 	pagebuf_rele(bp);
 }
@@ -608,7 +613,6 @@
 	int	iowait = (pb->pb_flags & PBF_ASYNC) == 0;
 	int	error = 0;
 
-	pb->pb_flags |= PBF_SYNC;
 	if (!iowait)
 		pb->pb_flags |= PBF_RUN_QUEUES;
 
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_globals.c linux-2.4.26-pre2/fs/xfs/linux/xfs_globals.c
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_globals.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_globals.c	2004-03-06 11:20:29.000000000 -0800
@@ -64,6 +64,8 @@
 	.inherit_sync	= {	0,	1,	1	},
 	.inherit_nodump	= {	0,	1,	1	},
 	.inherit_noatim = {	0,	1,	1	},
+	.flush_interval	= {	HZ/2,	HZ,	30*HZ	},
+	.age_buffer	= {	1*HZ,	15*HZ,	300*HZ	},
 };
 
 /*
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_ioctl.c linux-2.4.26-pre2/fs/xfs/linux/xfs_ioctl.c
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_ioctl.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_ioctl.c	2004-03-06 11:20:29.000000000 -0800
@@ -310,7 +310,6 @@
 	struct dentry		*dentry;
 	vnode_t			*vp;
 	xfs_fsop_handlereq_t	hreq;
-	struct list_head	*lp;
 
 	error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg,
 					sizeof(xfs_fsop_handlereq_t),
@@ -356,32 +355,13 @@
 		return new_fd;
 	}
 
-	/* Now to find a dentry.  If possible, get a well-connected one. */
-	spin_lock(&dcache_lock);
-	for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
-		dentry = list_entry(lp, struct dentry, d_alias);
-		if (! (dentry->d_flags & DCACHE_NFSD_DISCONNECTED)) {
-			dget_locked(dentry);
-			dentry->d_vfs_flags |= DCACHE_REFERENCED;
-			spin_unlock(&dcache_lock);
-			iput(inode);
-			goto found;
-		}
-	}
-	spin_unlock(&dcache_lock);
-
-	/* ELSE didn't find dentry.  Create anonymous dcache entry. */
-	dentry = d_alloc_root(inode);
+	dentry = d_alloc_anon(inode);
 	if (dentry == NULL) {
 		iput(inode);
 		put_unused_fd(new_fd);
 		return -XFS_ERROR(ENOMEM);
 	}
 
-	/* Keep nfsd happy. */
-	dentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
-
- found:
 	/* Ensure umount returns EBUSY on umounts while this file is open. */
 	mntget(parfilp->f_vfsmnt);
 
@@ -721,9 +701,7 @@
 
 		error = xfs_set_dmattrs(bdp, dmi.fsd_dmevmask, dmi.fsd_dmstate,
 							NULL);
-		if (error)
-			return -error;
-		return 0;
+		return -error;
 	}
 
 	case XFS_IOC_GETBMAP:
@@ -755,9 +733,7 @@
 
 	case XFS_IOC_SWAPEXT: {
 		error = xfs_swapext((struct xfs_swapext *)arg);
-		if (error)
-			return -error;
-		return 0;
+		return -error;
 	}
 
 	case XFS_IOC_FSCOUNTS: {
@@ -785,6 +761,8 @@
 		/* input parameter is passed in resblks field of structure */
 		in = inout.resblks;
 		error = xfs_reserve_blocks(mp, &in, &inout);
+		if (error)
+			return -error;
 
 		if (copy_to_user((char *)arg, &inout, sizeof(inout)))
 			return -XFS_ERROR(EFAULT);
@@ -817,9 +795,7 @@
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_growfs_data(mp, &in);
-		if (error)
-			return -error;
-		return 0;
+		return -error;
 	}
 
 	case XFS_IOC_FSGROWFSLOG: {
@@ -832,9 +808,7 @@
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_growfs_log(mp, &in);
-		if (error)
-			return -error;
-		return 0;
+		return -error;
 	}
 
 	case XFS_IOC_FSGROWFSRT: {
@@ -847,9 +821,7 @@
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_growfs_rt(mp, &in);
-		if (error)
-			return -error;
-		return 0;
+		return -error;
 	}
 
 	case XFS_IOC_FREEZE:
@@ -864,6 +836,19 @@
 		xfs_fs_thaw(mp);
 		return 0;
 
+	case XFS_IOC_GOINGDOWN: {
+		__uint32_t in;
+
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+
+		if (get_user(in, (__uint32_t *)arg))
+			return -XFS_ERROR(EFAULT);
+
+		error = xfs_fs_goingdown(mp, in);
+		return -error;
+	}
+
 	case XFS_IOC_ERROR_INJECTION: {
 		xfs_error_injection_t in;
 
@@ -871,9 +856,7 @@
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_errortag_add(in.errtag, mp);
-		if (error)
-			return -error;
-		return 0;
+		return -error;
 	}
 
 	case XFS_IOC_ERROR_CLEARALL:
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_iops.c linux-2.4.26-pre2/fs/xfs/linux/xfs_iops.c
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_iops.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_iops.c	2004-03-06 11:20:29.000000000 -0800
@@ -616,8 +616,7 @@
 
 	if (!size)
 		xflags |= ATTR_KERNOVAL;
-	if (capable(CAP_SYS_ADMIN))
-		xflags |= ATTR_KERNFULLS;
+	xflags |= capable(CAP_SYS_ADMIN) ? ATTR_KERNFULLS : ATTR_KERNORMALS;
 
 	error = attr_generic_list(vp, data, size, xflags, &result);
 	if (error < 0)
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_linux.h linux-2.4.26-pre2/fs/xfs/linux/xfs_linux.h
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_linux.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_linux.h	2004-03-06 11:20:29.000000000 -0800
@@ -135,6 +135,8 @@
 #define xfs_inherit_sync	xfs_params.inherit_sync.val
 #define xfs_inherit_nodump	xfs_params.inherit_nodump.val
 #define xfs_inherit_noatime	xfs_params.inherit_noatim.val
+#define xfs_flush_interval	xfs_params.flush_interval.val
+#define xfs_age_buffer		xfs_params.age_buffer.val
 
 #define current_cpu()		smp_processor_id()
 #define current_pid()		(current->pid)
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_lrw.c linux-2.4.26-pre2/fs/xfs/linux/xfs_lrw.c
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_lrw.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_lrw.c	2004-03-06 11:20:29.000000000 -0800
@@ -311,9 +311,10 @@
 	    !(ioflags & IO_INVIS)) {
 		int error;
 		vrwlock_t locktype = VRWLOCK_READ;
+		int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
 
 		error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), *offset, size,
-				      FILP_DELAY_FLAG(file), &locktype);
+				      dmflags, &locktype);
 		if (error) {
 			if (!(ioflags & IO_ISLOCKED))
 				xfs_iunlock(ip, XFS_IOLOCK_SHARED);
@@ -322,9 +323,13 @@
 	}
 
 	if (unlikely(ioflags & IO_ISDIRECT)) {
+		xfs_rw_enter_trace(XFS_DIORD_ENTER, &ip->i_iocore,
+					buf, size, *offset, ioflags);
 		ret = do_generic_direct_read(file, buf, size, offset);
 		UPDATE_ATIME(file->f_dentry->d_inode);
 	} else {
+		xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
+					buf, size, *offset, ioflags);
 		ret = generic_file_read(file, buf, size, offset);
 	}
 
@@ -593,7 +598,7 @@
 	if (size == 0)
 		return 0;
 
-	io = &(xip->i_iocore);
+	io = &xip->i_iocore;
 	mp = io->io_mount;
 
 	xfs_check_frozen(mp, bdp, XFS_FREEZE_WRITE);
@@ -645,11 +650,12 @@
 	if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
 	    !(ioflags & IO_INVIS) && !eventsent)) {
 		loff_t		savedsize = *offset;
+		int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
 
 		xfs_iunlock(xip, XFS_ILOCK_EXCL);
 		error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, vp,
 				      *offset, size,
-				      FILP_DELAY_FLAG(file), &locktype);
+				      dmflags, &locktype);
 		if (error) {
 			if (iolock) xfs_iunlock(xip, iolock);
 			return -error;
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_lrw.h linux-2.4.26-pre2/fs/xfs/linux/xfs_lrw.h
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_lrw.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_lrw.h	2004-03-06 11:20:29.000000000 -0800
@@ -45,9 +45,7 @@
 /*
  * Defines for the trace mechanisms in xfs_lrw.c.
  */
-#define	XFS_RW_KTRACE_SIZE	64
-#define	XFS_STRAT_KTRACE_SIZE	64
-#define	XFS_STRAT_GTRACE_SIZE	512
+#define	XFS_RW_KTRACE_SIZE	128
 
 #define	XFS_READ_ENTER		1
 #define	XFS_WRITE_ENTER		2
@@ -69,6 +67,12 @@
 #define	XFS_INVAL_CACHED	18
 #define	XFS_DIORD_ENTER		19
 #define	XFS_DIOWR_ENTER		20
+#define	XFS_SENDFILE_ENTER	21
+#define	XFS_WRITEPAGE_ENTER	22
+#define	XFS_RELEASEPAGE_ENTER	23
+#define	XFS_IOMAP_ALLOC_ENTER	24
+#define	XFS_IOMAP_ALLOC_MAP	25
+#define	XFS_IOMAP_UNWRITTEN	26
 extern void xfs_rw_enter_trace(int, struct xfs_iocore *,
 			const char *, size_t, loff_t, int);
 extern void xfs_inval_cached_trace(struct xfs_iocore *,
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_stats.c linux-2.4.26-pre2/fs/xfs/linux/xfs_stats.c
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_stats.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_stats.c	2004-03-06 11:20:29.000000000 -0800
@@ -63,6 +63,7 @@
 		{ "attr",		XFSSTAT_END_ATTRIBUTE_OPS	},
 		{ "icluster",		XFSSTAT_END_INODE_CLUSTER	},
 		{ "vnodes",		XFSSTAT_END_VNODE_OPS		},
+		{ "buf",		XFSSTAT_END_BUF			},
 	};
 
 	for (i=j=len = 0; i < sizeof(xstats)/sizeof(struct xstats_entry); i++) {
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_stats.h linux-2.4.26-pre2/fs/xfs/linux/xfs_stats.h
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_stats.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_stats.h	2004-03-06 11:20:29.000000000 -0800
@@ -120,6 +120,16 @@
 	__uint32_t		vn_reclaim;	/* # times vn_reclaim called */
 	__uint32_t		vn_remove;	/* # times vn_remove called */
 	__uint32_t		vn_free;	/* # times vn_free called */
+#define XFSSTAT_END_BUF			(XFSSTAT_END_VNODE_OPS+9)
+	__uint32_t		pb_get;
+	__uint32_t		pb_create;
+	__uint32_t		pb_get_locked;
+	__uint32_t		pb_get_locked_waited;
+	__uint32_t		pb_busy_locked;
+	__uint32_t		pb_miss_locked;
+	__uint32_t		pb_page_retries;
+	__uint32_t		pb_page_found;
+	__uint32_t		pb_get_read;
 /* Extra precision counters */
 	__uint64_t		xs_xstrat_bytes;
 	__uint64_t		xs_write_bytes;
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_super.c linux-2.4.26-pre2/fs/xfs/linux/xfs_super.c
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_super.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_super.c	2004-03-06 11:20:29.000000000 -0800
@@ -260,6 +260,30 @@
 	xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
 }
 
+struct dentry *
+d_alloc_anon(struct inode *inode)
+{
+	struct dentry *dentry;
+
+	spin_lock(&dcache_lock);
+	list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+		if (!(dentry->d_flags & DCACHE_NFSD_DISCONNECTED))
+			goto found;
+	}
+	spin_unlock(&dcache_lock);
+
+	dentry = d_alloc_root(inode);
+	if (likely(dentry != NULL))
+		dentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
+	return dentry;
+ found:
+	dget_locked(dentry);
+	dentry->d_vfs_flags |= DCACHE_REFERENCED;
+	spin_unlock(&dcache_lock);
+	iput(inode);
+	return dentry;
+}
+
 /*ARGSUSED*/
 int
 xfs_blkdev_get(
@@ -484,10 +508,10 @@
 
 	daemonize();
 	reparent_to_init();
-	spin_lock_irq(&current->sigmask_lock);
+	sigmask_lock();
 	sigfillset(&current->blocked);
-	recalc_sigpending(current);
-	spin_unlock_irq(&current->sigmask_lock);
+	__recalc_sigpending(current);
+	sigmask_unlock();
 
 	sprintf(current->comm, "xfssyncd");
 
@@ -686,7 +710,6 @@
 {
 	vnode_t			*vp;
 	struct inode		*inode = NULL;
-	struct list_head	*lp;
 	struct dentry		*result;
 	xfs_fid2_t		xfid;
 	vfs_t			*vfsp = LINVFS_GET_VFS(sb);
@@ -711,24 +734,12 @@
 		return ERR_PTR(-ESTALE) ;
 
 	inode = LINVFS_GET_IP(vp);
-	spin_lock(&dcache_lock);
-	for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
-		result = list_entry(lp,struct dentry, d_alias);
-		if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
-			dget_locked(result);
-			result->d_vfs_flags |= DCACHE_REFERENCED;
-			spin_unlock(&dcache_lock);
-			iput(inode);
-			return result;
-		}
-	}
-	spin_unlock(&dcache_lock);
-	result = d_alloc_root(inode);
-	if (result == NULL) {
+
+	result = d_alloc_anon(inode);
+	if (unlikely(result == NULL)) {
 		iput(inode);
 		return ERR_PTR(-ENOMEM);
 	}
-	result->d_flags |= DCACHE_NFSD_DISCONNECTED;
 	return result;
 }
 
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_super.h linux-2.4.26-pre2/fs/xfs/linux/xfs_super.h
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_super.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_super.h	2004-03-06 11:20:29.000000000 -0800
@@ -44,6 +44,8 @@
 
 #ifdef CONFIG_XFS_QUOTA
 # define vfs_insertquota(vfs)	vfs_insertops(vfsp, &xfs_qmops)
+extern void xfs_qm_init(void);
+extern void xfs_qm_exit(void);
 # define vfs_initquota()	xfs_qm_init()
 # define vfs_exitquota()	xfs_qm_exit()
 #else
@@ -133,4 +135,7 @@
 extern void xfs_setsize_buftarg(struct pb_target *, unsigned int, unsigned int);
 extern unsigned int xfs_getsize_buftarg(struct pb_target *);
 
+/* matching a 2.6 kernel export, thus no xfs_ prefix */
+extern struct dentry *d_alloc_anon(struct inode *inode);
+
 #endif	/* __XFS_SUPER_H__ */
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_sysctl.c linux-2.4.26-pre2/fs/xfs/linux/xfs_sysctl.c
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_sysctl.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_sysctl.c	2004-03-06 11:20:29.000000000 -0800
@@ -149,6 +149,16 @@
 	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
 	&sysctl_intvec, NULL,
 	&xfs_params.inherit_noatim.min, &xfs_params.inherit_noatim.max},
+	
+	{XFS_FLUSH_INTERVAL, "flush_interval", &xfs_params.flush_interval.val,
+	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
+	&sysctl_intvec, NULL,
+	&xfs_params.flush_interval.min, &xfs_params.flush_interval.max},
+
+	{XFS_AGE_BUFFER, "age_buffer", &xfs_params.age_buffer.val,
+	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
+	&sysctl_intvec, NULL,
+	&xfs_params.age_buffer.min, &xfs_params.age_buffer.max},
 
 	/* please keep this the last entry */
 #ifdef CONFIG_PROC_FS
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_sysctl.h linux-2.4.26-pre2/fs/xfs/linux/xfs_sysctl.h
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_sysctl.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_sysctl.h	2004-03-06 11:20:29.000000000 -0800
@@ -60,6 +60,10 @@
 	xfs_sysctl_val_t inherit_sync;	/* Inherit the "sync" inode flag. */
 	xfs_sysctl_val_t inherit_nodump;/* Inherit the "nodump" inode flag. */
 	xfs_sysctl_val_t inherit_noatim;/* Inherit the "noatime" inode flag. */
+	xfs_sysctl_val_t flush_interval;/* interval between runs of the
+					 * delwri flush daemon.  */
+	xfs_sysctl_val_t age_buffer;	/* time for buffer to age before
+					 * we flush it.  */
 } xfs_param_t;
 
 /*
@@ -90,6 +94,8 @@
 	XFS_INHERIT_SYNC = 13,
 	XFS_INHERIT_NODUMP = 14,
 	XFS_INHERIT_NOATIME = 15,
+	XFS_FLUSH_INTERVAL = 16,
+	XFS_AGE_BUFFER = 17,
 };
 
 extern xfs_param_t	xfs_params;
diff -urN linux-2.4.26-pre1/fs/xfs/linux/xfs_vfs.c linux-2.4.26-pre2/fs/xfs/linux/xfs_vfs.c
--- linux-2.4.26-pre1/fs/xfs/linux/xfs_vfs.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/linux/xfs_vfs.c	2004-03-06 11:20:29.000000000 -0800
@@ -117,7 +117,6 @@
 	return ((*bhvtovfsops(next)->vfs_mntupdate)(next, fl, args));
 }
 
-
 int
 vfs_root(
 	struct bhv_desc		*bdp,
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_ag.h linux-2.4.26-pre2/fs/xfs/xfs_ag.h
--- linux-2.4.26-pre1/fs/xfs/xfs_ag.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_ag.h	2004-03-06 11:20:29.000000000 -0800
@@ -230,39 +230,6 @@
 	xfs_perag_busy_t *pagb_list;	/* unstable blocks */
 } xfs_perag_t;
 
-#define	XFS_AG_MIN_BYTES	(1LL << 24)	/* 16 MB */
-#define	XFS_AG_BEST_BYTES	(1LL << 30)	/*  1 GB */
-#define	XFS_AG_MAX_BYTES	(1LL << 32)	/*  4 GB */
-
-#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_AG_MIN_BLOCKS)
-xfs_extlen_t xfs_ag_min_blocks(int bl);
-#define	XFS_AG_MIN_BLOCKS(bl)		xfs_ag_min_blocks(bl)
-#else
-#define	XFS_AG_MIN_BLOCKS(bl)	((xfs_extlen_t)(XFS_AG_MIN_BYTES >> bl))
-#endif
-#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_AG_BEST_BLOCKS)
-xfs_extlen_t xfs_ag_best_blocks(int bl, xfs_drfsbno_t blks);
-#define	XFS_AG_BEST_BLOCKS(bl,blks)	xfs_ag_best_blocks(bl,blks)
-#else
-/*--#define XFS_AG_BEST_BLOCKS(bl) ((xfs_extlen_t)(XFS_AG_BEST_BYTES >> bl))*/
-/*
- * Best is XFS_AG_BEST_BLOCKS at and below 64 Gigabyte filesystems, and
- * XFS_AG_MAX_BLOCKS above 64 Gigabytes.
- */
-#define XFS_AG_BEST_BLOCKS(bl,blks)	\
-	((xfs_extlen_t)((1LL << (36 - bl)) >= blks) ? \
-		((xfs_extlen_t)(XFS_AG_BEST_BYTES >> bl)) : \
-		XFS_AG_MAX_BLOCKS(bl))
-#endif
-#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_AG_MAX_BLOCKS)
-xfs_extlen_t xfs_ag_max_blocks(int bl);
-#define	XFS_AG_MAX_BLOCKS(bl)		xfs_ag_max_blocks(bl)
-#else
-#define	XFS_AG_MAX_BLOCKS(bl)	((xfs_extlen_t)(XFS_AG_MAX_BYTES >> bl))
-#endif
-
-#define	XFS_MAX_AGNUMBER	((xfs_agnumber_t)(NULLAGNUMBER - 1))
-
 #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_AG_MAXLEVELS)
 int xfs_ag_maxlevels(struct xfs_mount *mp);
 #define	XFS_AG_MAXLEVELS(mp)		xfs_ag_maxlevels(mp)
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_alloc.c linux-2.4.26-pre2/fs/xfs/xfs_alloc.c
--- linux-2.4.26-pre1/fs/xfs/xfs_alloc.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_alloc.c	2004-03-06 11:20:29.000000000 -0800
@@ -780,14 +780,8 @@
 	/*
 	 * Randomly don't execute the first algorithm.
 	 */
-	static int	seed;		/* randomizing seed value */
 	int		dofirst;	/* set to do first algorithm */
-	timespec_t	now;		/* current time */
 
-	if (!seed) {
-		nanotime(&now);
-		seed = (int)now.tv_sec ^ (int)now.tv_nsec;
-	}
 	dofirst = random() & 1;
 #endif
 	/*
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_attr.h linux-2.4.26-pre2/fs/xfs/xfs_attr.h
--- linux-2.4.26-pre1/fs/xfs/xfs_attr.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_attr.h	2004-03-06 11:20:29.000000000 -0800
@@ -91,10 +91,14 @@
 #define ATTR_CREATE	0x0010	/* pure create: fail if attr already exists */
 #define ATTR_REPLACE	0x0020	/* pure set: fail if attr does not exist */
 #define ATTR_SYSTEM	0x0100	/* use attrs in system (pseudo) namespace */
+
 #define ATTR_KERNOTIME	0x1000	/* [kernel] don't update inode timestamps */
 #define ATTR_KERNOVAL	0x2000	/* [kernel] get attr size only, not value */
 #define ATTR_KERNAMELS	0x4000	/* [kernel] list attr names (simple list) */
-#define ATTR_KERNFULLS	0x8000	/* [kernel] full attr list, ie. root+user */
+
+#define ATTR_KERNORMALS	0x0800	/* [kernel] normal attr list: user+secure */
+#define ATTR_KERNROOTLS	0x8000	/* [kernel] include root in the attr list */
+#define ATTR_KERNFULLS	(ATTR_KERNORMALS|ATTR_KERNROOTLS)
 
 /*
  * The maximum size (into the kernel or returned from the kernel) of an
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_attr_leaf.c linux-2.4.26-pre2/fs/xfs/xfs_attr_leaf.c
--- linux-2.4.26-pre1/fs/xfs/xfs_attr_leaf.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_attr_leaf.c	2004-03-06 11:20:29.000000000 -0800
@@ -460,9 +460,15 @@
 				i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) {
 			attrnames_t	*namesp;
 
+			if (((context->flags & ATTR_SECURE) != 0) !=
+			    ((sfe->flags & XFS_ATTR_SECURE) != 0) &&
+			    !(context->flags & ATTR_KERNORMALS)) {
+				sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
+				continue;
+			}
 			if (((context->flags & ATTR_ROOT) != 0) !=
 			    ((sfe->flags & XFS_ATTR_ROOT) != 0) &&
-			    !(context->flags & ATTR_KERNFULLS)) {
+			    !(context->flags & ATTR_KERNROOTLS)) {
 				sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
 				continue;
 			}
@@ -511,9 +517,15 @@
 			kmem_free(sbuf, sbsize);
 			return XFS_ERROR(EFSCORRUPTED);
 		}
+		if (((context->flags & ATTR_SECURE) != 0) !=
+		    ((sfe->flags & XFS_ATTR_SECURE) != 0) &&
+		    !(context->flags & ATTR_KERNORMALS)) {
+			sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
+			continue;
+		}
 		if (((context->flags & ATTR_ROOT) != 0) !=
 		    ((sfe->flags & XFS_ATTR_ROOT) != 0) &&
-		    !(context->flags & ATTR_KERNFULLS)) {
+		    !(context->flags & ATTR_KERNROOTLS)) {
 			sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
 			continue;
 		}
@@ -2309,9 +2321,13 @@
 
 		if (entry->flags & XFS_ATTR_INCOMPLETE)
 			continue;		/* skip incomplete entries */
+		if (((context->flags & ATTR_SECURE) != 0) !=
+		    ((entry->flags & XFS_ATTR_SECURE) != 0) &&
+		    !(context->flags & ATTR_KERNORMALS))
+			continue;		/* skip non-matching entries */
 		if (((context->flags & ATTR_ROOT) != 0) !=
 		    ((entry->flags & XFS_ATTR_ROOT) != 0) &&
-		    !(context->flags & ATTR_KERNFULLS))
+		    !(context->flags & ATTR_KERNROOTLS))
 			continue;		/* skip non-matching entries */
 
 		namesp = (entry->flags & XFS_ATTR_SECURE) ? &attr_secure :
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_buf_item.c linux-2.4.26-pre2/fs/xfs/xfs_buf_item.c
--- linux-2.4.26-pre1/fs/xfs/xfs_buf_item.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_buf_item.c	2004-03-06 11:20:29.000000000 -0800
@@ -429,7 +429,7 @@
 		 */
 		if (bip->bli_flags & XFS_BLI_STALE_INODE) {
 			xfs_buf_do_callbacks(bp, (xfs_log_item_t *)bip);
-			XFS_BUF_FSPRIVATE(bp, void *) = NULL;
+			XFS_BUF_SET_FSPRIVATE(bp, NULL);
 			XFS_BUF_CLR_IODONE_FUNC(bp);
 		} else {
 			AIL_LOCK(mp,s);
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_clnt.h linux-2.4.26-pre2/fs/xfs/xfs_clnt.h
--- linux-2.4.26-pre1/fs/xfs/xfs_clnt.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_clnt.h	2004-03-06 11:20:29.000000000 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -57,10 +57,10 @@
 	int	flags;		/* flags -> see XFSMNT_... macros below */
 	int	logbufs;	/* Number of log buffers, -1 to default */
 	int	logbufsize;	/* Size of log buffers, -1 to default */
-	char	fsname[MAXNAMELEN];	/* data device name */
-	char	rtname[MAXNAMELEN];	/* realtime device filename */
-	char	logname[MAXNAMELEN];	/* journal device filename */
-	char	mtpt[MAXNAMELEN];	/* filesystem mount point */
+	char	fsname[MAXNAMELEN+1];	/* data device name */
+	char	rtname[MAXNAMELEN+1];	/* realtime device filename */
+	char	logname[MAXNAMELEN+1];	/* journal device filename */
+	char	mtpt[MAXNAMELEN+1];	/* filesystem mount point */
 	int	sunit;		/* stripe unit (BBs) */
 	int	swidth;		/* stripe width (BBs), multiple of sunit */
 	uchar_t iosizelog;	/* log2 of the preferred I/O size */
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_dir2_node.c linux-2.4.26-pre2/fs/xfs/xfs_dir2_node.c
--- linux-2.4.26-pre1/fs/xfs/xfs_dir2_node.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_dir2_node.c	2004-03-06 11:20:29.000000000 -0800
@@ -1573,15 +1573,16 @@
 					"%llu needed freesp block %lld for\n"
 					"  data block %lld, got %lld\n"
 					"  ifbno %llu lastfbno %d\n",
-					dp->i_ino,
-					XFS_DIR2_DB_TO_FDB(mp, dbno),
-					dbno, fbno,
-					ifbno, lastfbno);
+					(unsigned long long)dp->i_ino,
+					(long long)XFS_DIR2_DB_TO_FDB(mp, dbno),
+					(long long)dbno, (long long)fbno,
+					(unsigned long long)ifbno, lastfbno);
 				if (fblk) {
 					cmn_err(CE_ALERT,
-						" fblk 0x%llu blkno %llu "
+						" fblk 0x%p blkno %llu "
 						"index %d magic 0x%x\n",
-						fblk, fblk->blkno,
+						fblk,
+						(unsigned long long)fblk->blkno,
 						fblk->index,
 						fblk->magic);
 				} else {
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_dmapi.h linux-2.4.26-pre2/fs/xfs/xfs_dmapi.h
--- linux-2.4.26-pre1/fs/xfs/xfs_dmapi.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_dmapi.h	2004-03-06 11:20:29.000000000 -0800
@@ -165,6 +165,27 @@
 
 #define DM_FLAGS_NDELAY		0x001	/* return EAGAIN after dm_pending() */
 #define DM_FLAGS_UNWANTED	0x002	/* event not in fsys dm_eventset_t */
+#define DM_FLAGS_ISEM		0x004	/* thread holds i_sem */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21)
+/* i_alloc_sem was added in 2.4.22-pre1 */
+#define DM_FLAGS_IALLOCSEM_RD	0x010	/* thread holds i_alloc_sem rd */
+#define DM_FLAGS_IALLOCSEM_WR	0x020	/* thread holds i_alloc_sem wr */
+#endif
+#endif
+
+/*
+ *	Based on IO_ISDIRECT, decide which i_ flag is set.
+ */
+#ifdef DM_FLAGS_IALLOCSEM_RD
+#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
+			      DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_ISEM)
+#define DM_SEM_FLAG_WR	(DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM)
+#else
+#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
+			      0 : DM_FLAGS_ISEM)
+#define DM_SEM_FLAG_WR	(DM_FLAGS_ISEM)
+#endif
 
 /*
  *	Macros to turn caller specified delay/block flags into
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_dmops.c linux-2.4.26-pre2/fs/xfs/xfs_dmops.c
--- linux-2.4.26-pre1/fs/xfs/xfs_dmops.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_dmops.c	2004-03-06 11:20:29.000000000 -0800
@@ -43,7 +43,7 @@
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 
-xfs_dmops_t	xfs_dmcore_xfs = {
+xfs_dmops_t	xfs_dmcore_stub = {
 	.xfs_send_data		= (xfs_send_data_t)fs_nosys,
 	.xfs_send_mmap		= (xfs_send_mmap_t)fs_noerr,
 	.xfs_send_destroy	= (xfs_send_destroy_t)fs_nosys,
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_error.c linux-2.4.26-pre2/fs/xfs/xfs_error.c
--- linux-2.4.26-pre1/fs/xfs/xfs_error.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_error.c	2004-03-06 11:20:29.000000000 -0800
@@ -218,13 +218,17 @@
 static void
 xfs_fs_vcmn_err(int level, xfs_mount_t *mp, char *fmt, va_list ap)
 {
-	char	*newfmt;
-	int	len = 16 + mp->m_fsname_len + strlen(fmt);
-
-	newfmt = kmem_alloc(len, KM_SLEEP);
-	sprintf(newfmt, "Filesystem \"%s\": %s", mp->m_fsname, fmt);
-	icmn_err(level, newfmt, ap);
-	kmem_free(newfmt, len);
+	if (mp != NULL) {
+		char	*newfmt;
+		int	len = 16 + mp->m_fsname_len + strlen(fmt);
+
+		newfmt = kmem_alloc(len, KM_SLEEP);
+		sprintf(newfmt, "Filesystem \"%s\": %s", mp->m_fsname, fmt);
+		icmn_err(level, newfmt, ap);
+		kmem_free(newfmt, len);
+	} else {
+		icmn_err(level, fmt, ap);
+	}
 }
 
 void
@@ -267,16 +271,10 @@
 	inst_t		*ra)
 {
 	if (level <= xfs_error_level) {
-		if (mp != NULL) {
-			xfs_cmn_err(XFS_PTAG_ERROR_REPORT,
-				    CE_ALERT, mp,
+		xfs_cmn_err(XFS_PTAG_ERROR_REPORT,
+			    CE_ALERT, mp,
 		"XFS internal error %s at line %d of file %s.  Caller 0x%p\n",
-				    tag, linenum, fname, ra);
-		} else {
-			cmn_err(CE_ALERT,
-		"XFS internal error %s at line %d of file %s.  Caller 0x%p\n",
-				tag, linenum, fname, ra);
-		}
+			    tag, linenum, fname, ra);
 
 		xfs_stack_trace();
 	}
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_fs.h linux-2.4.26-pre2/fs/xfs/xfs_fs.h
--- linux-2.4.26-pre1/fs/xfs/xfs_fs.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_fs.h	2004-03-06 11:20:29.000000000 -0800
@@ -437,6 +437,12 @@
 
 #define FSHSIZE		sizeof(fsid_t)
 
+/* 
+ * Flags for going down operation
+ */
+#define XFS_FSOP_GOING_FLAGS_DEFAULT		0x0	/* going down */
+#define XFS_FSOP_GOING_FLAGS_LOGFLUSH		0x1	/* flush log but not data */
+#define XFS_FSOP_GOING_FLAGS_NOLOGFLUSH		0x2	/* don't flush log nor data */
 
 /*
  * ioctl commands that replace IRIX fcntl()'s
@@ -490,6 +496,7 @@
 #define XFS_IOC_ATTRLIST_BY_HANDLE   _IOW ('X', 122, struct xfs_fsop_attrlist_handlereq)
 #define XFS_IOC_ATTRMULTI_BY_HANDLE  _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq)
 #define XFS_IOC_FSGEOMETRY	     _IOR ('X', 124, struct xfs_fsop_geom)
+#define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, __uint32_t)
 /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
 
 
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_fsops.c linux-2.4.26-pre2/fs/xfs/xfs_fsops.c
--- linux-2.4.26-pre1/fs/xfs/xfs_fsops.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_fsops.c	2004-03-06 11:20:29.000000000 -0800
@@ -626,3 +626,28 @@
 	xfs_finish_freeze(mp);
 	return 0;
 }
+
+int
+xfs_fs_goingdown(
+	xfs_mount_t	*mp,
+	__uint32_t	inflags)
+{
+	switch (inflags)
+	{
+	case XFS_FSOP_GOING_FLAGS_DEFAULT:
+		xfs_fs_freeze(mp);
+		xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
+		xfs_fs_thaw(mp);
+		break;
+	case XFS_FSOP_GOING_FLAGS_LOGFLUSH:
+		xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
+		break;
+	case XFS_FSOP_GOING_FLAGS_NOLOGFLUSH:
+		xfs_force_shutdown(mp, XFS_FORCE_UMOUNT|XFS_LOG_IO_ERROR);
+		break;
+	default:
+		return XFS_ERROR(EINVAL);
+	}
+
+	return 0;
+}
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_fsops.h linux-2.4.26-pre2/fs/xfs/xfs_fsops.h
--- linux-2.4.26-pre1/fs/xfs/xfs_fsops.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_fsops.h	2004-03-06 11:20:29.000000000 -0800
@@ -67,4 +67,9 @@
 xfs_fs_thaw(
 	xfs_mount_t		*mp);
 
+int
+xfs_fs_goingdown(
+	xfs_mount_t		*mp,
+	__uint32_t		inflags);
+
 #endif	/* __XFS_FSOPS_H__ */
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_iomap.c linux-2.4.26-pre2/fs/xfs/xfs_iomap.c
--- linux-2.4.26-pre1/fs/xfs/xfs_iomap.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_iomap.c	2004-03-06 11:20:29.000000000 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -69,6 +69,76 @@
 #include "xfs_utils.h"
 #include "xfs_iomap.h"
 
+#if defined(XFS_RW_TRACE)
+void
+xfs_iomap_enter_trace(
+	int		tag,
+	xfs_iocore_t	*io,
+	xfs_off_t	offset,
+	ssize_t		count)
+{
+	xfs_inode_t	*ip = XFS_IO_INODE(io);
+
+	if (!ip->i_rwtrace)
+		return;
+
+	ktrace_enter(ip->i_rwtrace,
+		(void *)((unsigned long)tag),
+		(void *)ip,
+		(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
+		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(offset & 0xffffffff)),
+		(void *)((unsigned long)count),
+		(void *)((unsigned long)((io->io_new_size >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(io->io_new_size & 0xffffffff)),
+		(void *)NULL,
+		(void *)NULL,
+		(void *)NULL,
+		(void *)NULL,
+		(void *)NULL,
+		(void *)NULL,
+		(void *)NULL);
+}
+
+void
+xfs_iomap_map_trace(
+	int		tag,
+	xfs_iocore_t	*io,
+	xfs_off_t	offset,
+	ssize_t		count,
+	xfs_iomap_t	*iomapp,
+	xfs_bmbt_irec_t	*imapp,
+	int		flags)
+{
+	xfs_inode_t	*ip = XFS_IO_INODE(io);
+
+	if (!ip->i_rwtrace)
+		return;
+
+	ktrace_enter(ip->i_rwtrace,
+		(void *)((unsigned long)tag),
+		(void *)ip,
+		(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
+		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(offset & 0xffffffff)),
+		(void *)((unsigned long)count),
+		(void *)((unsigned long)flags),
+		(void *)((unsigned long)((iomapp->iomap_offset >> 32) & 0xffffffff)),
+		(void *)((unsigned long)(iomapp->iomap_offset & 0xffffffff)),
+		(void *)((unsigned long)(iomapp->iomap_delta)),
+		(void *)((unsigned long)(iomapp->iomap_bsize)),
+		(void *)((unsigned long)(iomapp->iomap_bn)),
+		(void *)(__psint_t)(imapp->br_startoff),
+		(void *)((unsigned long)(imapp->br_blockcount)),
+		(void *)(__psint_t)(imapp->br_startblock));
+}
+#else
+#define xfs_iomap_enter_trace(tag, io, offset, count)
+#define xfs_iomap_map_trace(tag, io, offset, count, iomapp, imapp, flags)
+#endif
+
 #define XFS_WRITEIO_ALIGN(mp,off)	(((off) >> mp->m_writeio_log) \
 						<< mp->m_writeio_log)
 #define XFS_STRAT_WRITE_IMAPS	2
@@ -149,17 +219,20 @@
 		(BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE |
 		 BMAPI_UNWRITTEN | BMAPI_DEVICE)) {
 	case BMAPI_READ:
+		xfs_iomap_enter_trace(XFS_IOMAP_READ_ENTER, io, offset, count);
 		lockmode = XFS_LCK_MAP_SHARED(mp, io);
 		bmapi_flags = XFS_BMAPI_ENTIRE;
 		if (flags & BMAPI_IGNSTATE)
 			bmapi_flags |= XFS_BMAPI_IGSTATE;
 		break;
 	case BMAPI_WRITE:
+		xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, io, offset, count);
 		lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;
 		bmapi_flags = 0;
 		XFS_ILOCK(mp, io, lockmode);
 		break;
 	case BMAPI_ALLOCATE:
+		xfs_iomap_enter_trace(XFS_IOMAP_ALLOC_ENTER, io, offset, count);
 		lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD;
 		bmapi_flags = XFS_BMAPI_ENTIRE;
 		/* Attempt non-blocking lock */
@@ -201,8 +274,11 @@
 	switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) {
 	case BMAPI_WRITE:
 		/* If we found an extent, return it */
-		if (nimaps && (imap.br_startblock != HOLESTARTBLOCK))
+		if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) {
+			xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,
+					offset, count, iomapp, &imap, flags);
 			break;
+		}
 
 		if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) {
 			error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset,
@@ -211,6 +287,10 @@
 			error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count,
 					flags, &imap, &nimaps);
 		}
+		if (!error) {
+			xfs_iomap_map_trace(XFS_IOMAP_ALLOC_MAP, io,
+					offset, count, iomapp, &imap, flags);
+		}
 		iomap_flags = IOMAP_NEW;
 		break;
 	case BMAPI_ALLOCATE:
@@ -218,8 +298,11 @@
 		XFS_IUNLOCK(mp, io, lockmode);
 		lockmode = 0;
 
-		if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock))
+		if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock)) {
+			xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,
+					offset, count, iomapp, &imap, flags);
 			break;
+		}
 
 		error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps);
 		break;
@@ -309,7 +392,6 @@
 	 * Make sure that the dquots are there. This doesn't hold
 	 * the ilock across a disk read.
 	 */
-
 	error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED);
 	if (error)
 		return XFS_ERROR(error);
@@ -540,8 +622,9 @@
 	 * If bmapi returned us nothing, and if we didn't get back EDQUOT,
 	 * then we must have run out of space.
 	 */
-
 	if (nimaps == 0) {
+		xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE,
+					io, offset, count);
 		if (xfs_flush_space(ip, &fsynced, &ioflag))
 			return XFS_ERROR(ENOSPC);
 
@@ -584,7 +667,6 @@
 	/*
 	 * Make sure that the dquots are there.
 	 */
-
 	if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
 		return XFS_ERROR(error);
 
@@ -612,7 +694,6 @@
 					XFS_WRITE_LOG_RES(mp),
 					0, XFS_TRANS_PERM_LOG_RES,
 					XFS_WRITE_LOG_COUNT);
-
 			if (error == ENOSPC) {
 				error = xfs_trans_reserve(tp, 0,
 						XFS_WRITE_LOG_RES(mp),
@@ -653,19 +734,16 @@
 			error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb,
 					XFS_BMAPI_WRITE, &first_block, 1,
 					imap, &nimaps, &free_list);
-
 			if (error)
 				goto trans_cancel;
 
 			error = xfs_bmap_finish(&tp, &free_list,
 					first_block, &committed);
-
 			if (error)
 				goto trans_cancel;
 
 			error = xfs_trans_commit(tp,
 					XFS_TRANS_RELEASE_LOG_RES, NULL);
-
 			if (error)
 				goto error0;
 
@@ -725,6 +803,9 @@
 	xfs_fsblock_t	firstfsb;
 	xfs_bmap_free_t	free_list;
 
+	xfs_iomap_enter_trace(XFS_IOMAP_UNWRITTEN,
+				&ip->i_iocore, offset, count);
+
 	offset_fsb = XFS_B_TO_FSBT(mp, offset);
 	count_fsb = XFS_B_TO_FSB(mp, count);
 
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_log.c linux-2.4.26-pre2/fs/xfs/xfs_log.c
--- linux-2.4.26-pre1/fs/xfs/xfs_log.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_log.c	2004-03-06 11:20:29.000000000 -0800
@@ -759,8 +759,9 @@
 	/* Also an invalid lsn.  1 implies that we aren't passing in a valid
 	 * tail_lsn.
 	 */
-	if (tail_lsn != 1)
+	if (tail_lsn != 1) {
 		log->l_tail_lsn = tail_lsn;
+	}
 
 	if ((tic = log->l_write_headq)) {
 #ifdef DEBUG
@@ -866,10 +867,11 @@
 
 	tail_lsn = xfs_trans_tail_ail(mp);
 	s = GRANT_LOCK(log);
-	if (tail_lsn != 0)
+	if (tail_lsn != 0) {
 		log->l_tail_lsn = tail_lsn;
-	else
+	} else {
 		tail_lsn = log->l_tail_lsn = log->l_last_sync_lsn;
+	}
 	GRANT_UNLOCK(log, s);
 
 	return tail_lsn;
@@ -921,10 +923,8 @@
 		 * In this case we just want to return the size of the
 		 * log as the amount of space left.
 		 */
-/* This assert does not take into account padding from striped log writes *
 		ASSERT((tail_cycle == (cycle + 1)) ||
 		       ((bytes + log->l_roundoff) >= tail_bytes));
-*/
 		free_bytes = log->l_logsize;
 	}
 	return free_bytes;
@@ -1183,14 +1183,6 @@
 	log->l_grant_reserve_cycle = 1;
 	log->l_grant_write_cycle = 1;
 
-	if (XFS_SB_VERSION_HASLOGV2(&mp->m_sb)) {
-		if (mp->m_sb.sb_logsunit <= 1) {
-			log->l_stripemask = 1;
-		} else {
-			log->l_stripemask = 1 <<
-				xfs_highbit32(mp->m_sb.sb_logsunit >> BBSHIFT);
-		}
-	}
 	if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb)) {
 		log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT;
 		ASSERT(log->l_sectbb_log <= mp->m_sectbb_log);
@@ -1235,7 +1227,7 @@
 			  kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP);
 		iclog = *iclogp;
 		iclog->hic_data = (xlog_in_core_2_t *)
-			  kmem_alloc(iclogsize, KM_SLEEP);
+			  kmem_zalloc(iclogsize, KM_SLEEP);
 
 		iclog->ic_prev = prev_iclog;
 		prev_iclog = iclog;
@@ -1401,45 +1393,35 @@
 	xfs_caddr_t	dptr;		/* pointer to byte sized element */
 	xfs_buf_t	*bp;
 	int		i, ops;
-	uint		roundup;
 	uint		count;		/* byte count of bwrite */
+	uint		count_init;	/* initial count before roundup */
 	int		split = 0;	/* split write into two regions */
 	int		error;
 
 	XFS_STATS_INC(xs_log_writes);
 	ASSERT(iclog->ic_refcnt == 0);
 
+	/* Add for LR header */
+	count_init = log->l_iclog_hsize + iclog->ic_offset;
+
 	/* Round out the log write size */
-	if (iclog->ic_offset & BBMASK) {
-		/* count of 0 is already accounted for up in
-		 * xlog_state_sync_all().  Once in this routine,
-		 * operations on the iclog are single threaded.
-		 *
-		 * Difference between rounded up size and size
-		 */
-		count = iclog->ic_offset & BBMASK;
-		iclog->ic_roundoff += BBSIZE - count;
-	}
-	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
-		unsigned sunit = BTOBB(log->l_mp->m_sb.sb_logsunit);
-		if (!sunit)
-			sunit = 1;
-
-		count = BTOBB(log->l_iclog_hsize + iclog->ic_offset);
-		if (count & (sunit - 1)) {
-			roundup = sunit - (count & (sunit - 1));
-		} else {
-			roundup = 0;
-		}
-		iclog->ic_offset += BBTOB(roundup);
+	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) &&
+	    log->l_mp->m_sb.sb_logsunit > 1) {
+		/* we have a v2 stripe unit to use */
+		count = XLOG_LSUNITTOB(log, XLOG_BTOLSUNIT(log, count_init));
+	} else {
+		count = BBTOB(BTOBB(count_init));
 	}
-
+	iclog->ic_roundoff = count - count_init;
 	log->l_roundoff += iclog->ic_roundoff;
 
 	xlog_pack_data(log, iclog);       /* put cycle number in every block */
 
 	/* real byte length */
-	INT_SET(iclog->ic_header.h_len, ARCH_CONVERT, iclog->ic_offset);
+	INT_SET(iclog->ic_header.h_len, 
+		ARCH_CONVERT,
+		iclog->ic_offset + iclog->ic_roundoff);
+
 	/* put ops count in correct order */
 	ops = iclog->ic_header.h_num_logops;
 	INT_SET(iclog->ic_header.h_num_logops, ARCH_CONVERT, ops);
@@ -1449,12 +1431,6 @@
 	XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2);
 	XFS_BUF_SET_ADDR(bp, BLOCK_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT));
 
-	/* Count is already rounded up to a BBSIZE above */
-	count = iclog->ic_offset + iclog->ic_roundoff;
-	ASSERT((count & BBMASK) == 0);
-
-	/* Add for LR header */
-	count += log->l_iclog_hsize;
 	XFS_STATS_ADD(xs_log_blocks, BTOBB(count));
 
 	/* Do we need to split this write into 2 parts? */
@@ -2783,8 +2759,6 @@
 			 xlog_in_core_t *iclog,
 			 int		eventual_size)
 {
-	uint roundup;
-
 	ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE);
 	if (!eventual_size)
 		eventual_size = iclog->ic_offset;
@@ -2797,14 +2771,10 @@
 	log->l_curr_block += BTOBB(eventual_size)+BTOBB(log->l_iclog_hsize);
 
 	/* Round up to next log-sunit */
-	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
-		if (log->l_curr_block & (log->l_stripemask - 1)) {
-			roundup = log->l_stripemask -
-				(log->l_curr_block & (log->l_stripemask - 1));
-		} else {
-			roundup = 0;
-		}
-		log->l_curr_block += roundup;
+	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) &&
+	    log->l_mp->m_sb.sb_logsunit > 1) {
+		__uint32_t sunit_bb = BTOBB(log->l_mp->m_sb.sb_logsunit);
+		log->l_curr_block = roundup(log->l_curr_block, sunit_bb);
 	}
 
 	if (log->l_curr_block >= log->l_logBBsize) {
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_log_priv.h linux-2.4.26-pre2/fs/xfs/xfs_log_priv.h
--- linux-2.4.26-pre1/fs/xfs/xfs_log_priv.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_log_priv.h	2004-03-06 11:20:29.000000000 -0800
@@ -63,6 +63,9 @@
 #else
 #define XLOG_BTOLRBB(b)		(((b)+XLOG_RECORD_BSIZE-1) >> XLOG_RECORD_BSHIFT)
 #endif
+#define XLOG_BTOLSUNIT(log, b)  (((b)+(log)->l_mp->m_sb.sb_logsunit-1) / \
+                                 (log)->l_mp->m_sb.sb_logsunit)
+#define XLOG_LSUNITTOB(log, su) ((su) * (log)->l_mp->m_sb.sb_logsunit)
 
 #define XLOG_HEADER_SIZE	512
 
@@ -531,7 +534,6 @@
 	uint			l_flags;
 	uint			l_quotaoffs_flag; /* XFS_DQ_*, for QUOTAOFFs */
 	struct xfs_buf_cancel	**l_buf_cancel_table;
-	int			l_stripemask;	/* log stripe mask */
 	int			l_iclog_hsize;  /* size of iclog header */
 	int			l_iclog_heads;  /* # of iclog header sectors */
 	uint			l_sectbb_log;   /* log2 of sector size in BBs */
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_log_recover.c linux-2.4.26-pre2/fs/xfs/xfs_log_recover.c
--- linux-2.4.26-pre1/fs/xfs/xfs_log_recover.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_log_recover.c	2004-03-06 11:20:29.000000000 -0800
@@ -3416,6 +3416,7 @@
 {
 	uint			*up = (uint *)dp;
 	uint			chksum = 0;
+	int			i;
 
 	/* divide length by 4 to get # words */
 	for (i=0; i < INT_GET(rhead->h_len, ARCH_CONVERT) >> 2; i++) {
@@ -3476,7 +3477,7 @@
 	xlog_rec_header_t	*rhead,
 	xfs_daddr_t		blkno)
 {
-	int			bblks;
+	int			hlen;
 
 	if (unlikely(
 	    (INT_GET(rhead->h_magicno, ARCH_CONVERT) !=
@@ -3495,8 +3496,8 @@
 	}
 
 	/* LR body must have data or it wouldn't have been written */
-	bblks = INT_GET(rhead->h_len, ARCH_CONVERT);
-	if (unlikely( bblks <= 0 || bblks > INT_MAX )) {
+	hlen = INT_GET(rhead->h_len, ARCH_CONVERT);
+	if (unlikely( hlen <= 0 || hlen > INT_MAX )) {
 		XFS_ERROR_REPORT("xlog_valid_rec_header(2)",
 				XFS_ERRLEVEL_LOW, log->l_mp);
 		return XFS_ERROR(EFSCORRUPTED);
@@ -3658,7 +3659,7 @@
 				error = xlog_bread(log, 0, wrapped_hblks, hbp);
 				if (error)
 					goto bread_err2;
-				XFS_BUF_SET_PTR(hbp, bufaddr, hblks);
+				XFS_BUF_SET_PTR(hbp, bufaddr, BBTOB(hblks));
 				if (!offset)
 					offset = xlog_align(log, 0,
 							wrapped_hblks, hbp);
@@ -3716,8 +3717,7 @@
 				if ((error = xlog_bread(log, wrapped_hblks,
 						bblks - split_bblks, dbp)))
 					goto bread_err2;
-				XFS_BUF_SET_PTR(dbp, bufaddr,
-						XLOG_BIG_RECORD_BSIZE);
+				XFS_BUF_SET_PTR(dbp, bufaddr, h_size);
 				if (!offset)
 					offset = xlog_align(log, wrapped_hblks,
 						bblks - split_bblks, dbp);
@@ -4042,7 +4042,7 @@
 				XFS_FSS_TO_BB(mp, 1), 0);
 		if (XFS_BUF_ISERROR(agibp)) {
 			xfs_ioerror_alert("xlog_recover_check_summary(agi)",
-					  log->l_mp, agibp, agidaddr);
+					  mp, agibp, agidaddr);
 		}
 		agip = XFS_BUF_TO_AGI(agibp);
 		ASSERT(XFS_AGI_MAGIC ==
@@ -4058,7 +4058,8 @@
 
 	sbbp = xfs_getsb(mp, 0);
 #ifdef XFS_LOUD_RECOVERY
-	sbp = XFS_BUF_TO_SBP(sbbp);
+	sbp = &mp->m_sb;
+	xfs_xlatesb(XFS_BUF_TO_SBP(sbbp), sbp, 1, ARCH_CONVERT, XFS_SB_ALL_BITS);
 	cmn_err(CE_NOTE,
 		"xlog_recover_check_summary: sb_icount %Lu itotal %Lu",
 		sbp->sb_icount, itotal);
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_macros.c linux-2.4.26-pre2/fs/xfs/xfs_macros.c
--- linux-2.4.26-pre1/fs/xfs/xfs_macros.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_macros.c	2004-03-06 11:20:29.000000000 -0800
@@ -115,22 +115,6 @@
 }
 #endif
 
-#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_AG_BEST_BLOCKS)
-xfs_extlen_t
-xfs_ag_best_blocks(int bl, xfs_drfsbno_t blks)
-{
-	return XFS_AG_BEST_BLOCKS(bl, blks);
-}
-#endif
-
-#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_AG_MAX_BLOCKS)
-xfs_extlen_t
-xfs_ag_max_blocks(int bl)
-{
-	return XFS_AG_MAX_BLOCKS(bl);
-}
-#endif
-
 #if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_AG_MAXLEVELS)
 int
 xfs_ag_maxlevels(xfs_mount_t *mp)
@@ -139,14 +123,6 @@
 }
 #endif
 
-#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_AG_MIN_BLOCKS)
-xfs_extlen_t
-xfs_ag_min_blocks(int bl)
-{
-	return XFS_AG_MIN_BLOCKS(bl);
-}
-#endif
-
 #if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_AGB_TO_DADDR)
 xfs_daddr_t
 xfs_agb_to_daddr(xfs_mount_t *mp, xfs_agnumber_t agno, xfs_agblock_t agbno)
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_mount.c linux-2.4.26-pre2/fs/xfs/xfs_mount.c
--- linux-2.4.26-pre1/fs/xfs/xfs_mount.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_mount.c	2004-03-06 11:20:29.000000000 -0800
@@ -675,6 +675,7 @@
 				error = XFS_ERROR(EINVAL);
 				goto error1;
 			}
+			mp->m_dalign = mp->m_swidth = 0;
 		} else {
 			/*
 			 * Convert the stripe unit and width to FSBs.
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_mount.h linux-2.4.26-pre2/fs/xfs/xfs_mount.h
--- linux-2.4.26-pre1/fs/xfs/xfs_mount.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_mount.h	2004-03-06 11:20:29.000000000 -0800
@@ -571,8 +571,8 @@
 extern struct vfsops xfs_vfsops;
 extern struct vnodeops xfs_vnodeops;
 
-extern struct xfs_dmops xfs_dmcore_xfs;
-extern struct xfs_qmops xfs_qmcore_xfs;
+extern struct xfs_dmops xfs_dmcore_stub;
+extern struct xfs_qmops xfs_qmcore_stub;
 extern struct xfs_ioops xfs_iocore_xfs;
 
 extern int	xfs_init(void);
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_qmops.c linux-2.4.26-pre2/fs/xfs/xfs_qmops.c
--- linux-2.4.26-pre1/fs/xfs/xfs_qmops.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_qmops.c	2004-03-06 11:20:29.000000000 -0800
@@ -54,7 +54,7 @@
 	return NULL;
 }
 
-xfs_qmops_t	xfs_qmcore_xfs = {
+xfs_qmops_t	xfs_qmcore_stub = {
 	.xfs_qminit		= (xfs_qminit_t) fs_noerr,
 	.xfs_qmdone		= (xfs_qmdone_t) fs_noerr,
 	.xfs_qmmount		= (xfs_qmmount_t) fs_noerr,
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_quota.h linux-2.4.26-pre2/fs/xfs/xfs_quota.h
--- linux-2.4.26-pre1/fs/xfs/xfs_quota.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_quota.h	2004-03-06 11:20:29.000000000 -0800
@@ -347,9 +347,6 @@
 
 extern struct bhv_vfsops xfs_qmops;
 
-extern void xfs_qm_init(void);
-extern void xfs_qm_exit(void);
-
 #endif	/* __KERNEL__ */
 
 #endif	/* __XFS_QUOTA_H__ */
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_vfsops.c linux-2.4.26-pre2/fs/xfs/xfs_vfsops.c
--- linux-2.4.26-pre1/fs/xfs/xfs_vfsops.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_vfsops.c	2004-03-06 11:20:29.000000000 -0800
@@ -451,9 +451,9 @@
 	 * Setup xfs_mount function vectors from available behaviors
 	 */
 	p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
-	mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_xfs;
+	mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
 	p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
-	mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_xfs;
+	mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
 	p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
 	mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
 
diff -urN linux-2.4.26-pre1/fs/xfs/xfs_vnodeops.c linux-2.4.26-pre2/fs/xfs/xfs_vnodeops.c
--- linux-2.4.26-pre1/fs/xfs/xfs_vnodeops.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/fs/xfs/xfs_vnodeops.c	2004-03-06 11:20:29.000000000 -0800
@@ -413,8 +413,9 @@
 	} else {
 		if (DM_EVENT_ENABLED (vp->v_vfsp, ip, DM_EVENT_TRUNCATE) &&
 		    !(flags & ATTR_DMI)) {
+			int dmflags = AT_DELAY_FLAG(flags) | DM_SEM_FLAG_WR;
 			code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, vp,
-				vap->va_size, 0, AT_DELAY_FLAG(flags), NULL);
+				vap->va_size, 0, dmflags, NULL);
 			if (code) {
 				lock_flags = 0;
 				goto error_return;
diff -urN linux-2.4.26-pre1/include/acpi/acconfig.h linux-2.4.26-pre2/include/acpi/acconfig.h
--- linux-2.4.26-pre1/include/acpi/acconfig.h	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/include/acpi/acconfig.h	2004-03-06 11:20:29.000000000 -0800
@@ -64,7 +64,7 @@
 
 /* Version string */
 
-#define ACPI_CA_VERSION                 0x20040211
+#define ACPI_CA_VERSION                 0x20040220
 
 /* Maximum objects in the various object caches */
 
diff -urN linux-2.4.26-pre1/include/acpi/acglobal.h linux-2.4.26-pre2/include/acpi/acglobal.h
--- linux-2.4.26-pre1/include/acpi/acglobal.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/include/acpi/acglobal.h	2004-03-06 11:20:29.000000000 -0800
@@ -57,6 +57,12 @@
 #define ACPI_EXTERN extern
 #endif
 
+/*
+ * Keep local copies of these FADT-based registers.  NOTE: These globals
+ * are first in this file for alignment reasons on 64-bit systems.
+ */
+ACPI_EXTERN struct acpi_generic_address         acpi_gbl_xpm1a_enable;
+ACPI_EXTERN struct acpi_generic_address         acpi_gbl_xpm1b_enable;
 
 /*****************************************************************************
  *
@@ -97,6 +103,11 @@
 ACPI_EXTERN struct acpi_table_header           *acpi_gbl_DSDT;
 ACPI_EXTERN FACS_DESCRIPTOR            *acpi_gbl_FACS;
 ACPI_EXTERN struct acpi_common_facs             acpi_gbl_common_fACS;
+/*
+ * Since there may be multiple SSDTs and PSDTS, a single pointer is not
+ * sufficient; Therefore, there isn't one!
+ */
+
 
 /*
  * Handle both ACPI 1.0 and ACPI 2.0 Integer widths
@@ -107,17 +118,6 @@
 ACPI_EXTERN u8                                  acpi_gbl_integer_byte_width;
 ACPI_EXTERN u8                                  acpi_gbl_integer_nybble_width;
 
-/* Keep local copies of these FADT-based registers */
-
-ACPI_EXTERN struct acpi_generic_address         acpi_gbl_xpm1a_enable;
-ACPI_EXTERN struct acpi_generic_address         acpi_gbl_xpm1b_enable;
-
-/*
- * Since there may be multiple SSDTs and PSDTS, a single pointer is not
- * sufficient; Therefore, there isn't one!
- */
-
-
 /*
  * ACPI Table info arrays
  */
@@ -165,7 +165,8 @@
 extern u8                                       acpi_gbl_shutdown;
 extern u32                                      acpi_gbl_startup_flags;
 extern const u8                                 acpi_gbl_decode_to8bit[8];
-extern const char                              *acpi_gbl_db_sleep_states[ACPI_S_STATE_COUNT];
+extern const char                              *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT];
+extern const char                              *acpi_gbl_highest_dstate_names[4];
 extern const struct acpi_opcode_info            acpi_gbl_aml_op_info[AML_NUM_OPCODES];
 extern const char                              *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS];
 
diff -urN linux-2.4.26-pre1/include/acpi/actypes.h linux-2.4.26-pre2/include/acpi/actypes.h
--- linux-2.4.26-pre1/include/acpi/actypes.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/include/acpi/actypes.h	2004-03-06 11:20:29.000000000 -0800
@@ -880,7 +880,8 @@
 {
 	ACPI_COMMON_OBJ_INFO;
 
-	u32                                 valid;              /* Indicates which fields are valid */
+	u8                                  highest_dstates[4]; /* _sx_d values 0xFF indicates not valid */
+	u32                                 valid;              /* Indicates which fields below are valid */
 	u32                                 current_status;     /* _STA value */
 	acpi_integer                        address;            /* _ADR value if any */
 	struct acpi_device_id               hardware_id;        /* _HID value if any */
diff -urN linux-2.4.26-pre1/include/acpi/acutils.h linux-2.4.26-pre2/include/acpi/acutils.h
--- linux-2.4.26-pre1/include/acpi/acutils.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/include/acpi/acutils.h	2004-03-06 11:20:29.000000000 -0800
@@ -508,6 +508,10 @@
 	struct acpi_namespace_node      *device_node,
 	struct acpi_device_id           *uid);
 
+acpi_status
+acpi_ut_execute_sxds (
+	struct acpi_namespace_node      *device_node,
+	u8                              *highest);
 
 /*
  * ut_mutex - mutual exclusion interfaces
diff -urN linux-2.4.26-pre1/include/asm-i386/acpi.h linux-2.4.26-pre2/include/asm-i386/acpi.h
--- linux-2.4.26-pre1/include/asm-i386/acpi.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre2/include/asm-i386/acpi.h	2004-03-06 11:20:29.000000000 -0800
@@ -110,6 +110,7 @@
 extern int acpi_lapic;
 extern int acpi_ioapic;
 extern int acpi_noirq;
+extern int acpi_strict;
 
 /* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */
 #define FIX_ACPI_PAGES 4
diff -urN linux-2.4.26-pre1/include/asm-ia64/acpi.h linux-2.4.26-pre2/include/asm-ia64/acpi.h
--- linux-2.4.26-pre1/include/asm-ia64/acpi.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre2/include/asm-ia64/acpi.h	2004-03-06 11:20:29.000000000 -0800
@@ -96,6 +96,8 @@
 		:"=r"(Acq):"r"(GLptr):"r2","r29","r30","memory"); \
 	} while (0)
 
+#define acpi_strict 1	/* no ACPI workarounds */
+
 const char *acpi_get_sysname (void);
 int acpi_request_vector (u32 int_type);
 int acpi_get_prt (struct pci_vector_struct **vectors, int *count);
diff -urN linux-2.4.26-pre1/include/asm-x86_64/acpi.h linux-2.4.26-pre2/include/asm-x86_64/acpi.h
--- linux-2.4.26-pre1/include/asm-x86_64/acpi.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre2/include/asm-x86_64/acpi.h	2004-03-06 11:20:29.000000000 -0800
@@ -108,6 +108,7 @@
 extern int acpi_lapic;
 extern int acpi_ioapic;
 extern int acpi_noirq;
+extern int acpi_strict;
 
 /* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */
 #define FIX_ACPI_PAGES 4
diff -urN linux-2.4.26-pre1/include/linux/jhash.h linux-2.4.26-pre2/include/linux/jhash.h
--- linux-2.4.26-pre1/include/linux/jhash.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.26-pre2/include/linux/jhash.h	2004-03-06 11:20:29.000000000 -0800
@@ -41,10 +41,10 @@
  * of bytes.  No alignment or length assumptions are made about
  * the input key.
  */
-static inline u32 jhash(void *key, u32 length, u32 initval)
+static inline u32 jhash(const void *key, u32 length, u32 initval)
 {
 	u32 a, b, c, len;
-	u8 *k = key;
+	const u8 *k = key;
 
 	len = length;
 	a = b = JHASH_GOLDEN_RATIO;
diff -urN linux-2.4.26-pre1/include/linux/netfilter_ipv4/ip_nat.h linux-2.4.26-pre2/include/linux/netfilter_ipv4/ip_nat.h
--- linux-2.4.26-pre1/include/linux/netfilter_ipv4/ip_nat.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.26-pre2/include/linux/netfilter_ipv4/ip_nat.h	2004-03-06 11:20:29.000000000 -0800
@@ -105,9 +105,6 @@
 	/* Manipulations to be done on this conntrack. */
 	struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS];
 
-	/* The mapping type which created us (NULL for null mapping). */
-	const struct ip_nat_mapping_type *mtype;
-
 	struct ip_nat_hash bysource, byipsproto;
 
 	/* Helper (NULL if none). */
diff -urN linux-2.4.26-pre1/include/linux/netfilter_ipv4/listhelp.h linux-2.4.26-pre2/include/linux/netfilter_ipv4/listhelp.h
--- linux-2.4.26-pre1/include/linux/netfilter_ipv4/listhelp.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/include/linux/netfilter_ipv4/listhelp.h	2004-03-06 11:20:29.000000000 -0800
@@ -28,7 +28,7 @@
 							\
 	ASSERT_WRITE_LOCK(head);			\
 	list_for_each(__i, (head))			\
-		if (cmpfn((const type)__i , ## args)) {	\
+		if (cmpfn((type)__i , ## args)) {	\
 			__j = __i;			\
 			break;				\
 		}					\
diff -urN linux-2.4.26-pre1/include/linux/pci_ids.h linux-2.4.26-pre2/include/linux/pci_ids.h
--- linux-2.4.26-pre1/include/linux/pci_ids.h	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/include/linux/pci_ids.h	2004-03-06 11:20:29.000000000 -0800
@@ -287,6 +287,8 @@
 #define PCI_DEVICE_ID_ATI_RADEON_Ig	0x4967
 /* Radeon RV280 (9200) */
 #define PCI_DEVICE_ID_ATI_RADEON_Y_	0x5960
+#define PCI_DEVICE_ID_ATI_RADEON_Ya	0x5961
+#define PCI_DEVICE_ID_ATI_RADEON_Yd	0x5964
 /* Radeon R300 (9700) */
 #define PCI_DEVICE_ID_ATI_RADEON_ND	0x4e44
 #define PCI_DEVICE_ID_ATI_RADEON_NE	0x4e45
diff -urN linux-2.4.26-pre1/include/linux/sctp.h linux-2.4.26-pre2/include/linux/sctp.h
--- linux-2.4.26-pre1/include/linux/sctp.h	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/include/linux/sctp.h	2004-03-06 11:20:29.000000000 -0800
@@ -61,14 +61,14 @@
 	__u16 dest;
 	__u32 vtag;
 	__u32 checksum;
-} sctp_sctphdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_sctphdr_t;
 
 /* Section 3.2.  Chunk Field Descriptions. */
 typedef struct sctp_chunkhdr {
 	__u8 type;
 	__u8 flags;
 	__u16 length;
-} sctp_chunkhdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_chunkhdr_t;
 
 
 /* Section 3.2.  Chunk Type Values.
@@ -152,7 +152,7 @@
 typedef struct sctp_paramhdr {
 	__u16 type;
 	__u16 length;
-} sctp_paramhdr_t __attribute((packed));
+} __attribute__((packed)) sctp_paramhdr_t;
 
 typedef enum {
 
@@ -202,12 +202,12 @@
 	__u16 ssn;
 	__u32 ppid;
 	__u8  payload[0];
-} sctp_datahdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_datahdr_t;
 
 typedef struct sctp_data_chunk {
         sctp_chunkhdr_t chunk_hdr;
         sctp_datahdr_t  data_hdr;
-} sctp_data_chunk_t __attribute__((packed));
+} __attribute__((packed)) sctp_data_chunk_t;
 
 /* DATA Chuck Specific Flags */
 enum {
@@ -232,48 +232,48 @@
 	__u16 num_inbound_streams;
 	__u32 initial_tsn;
 	__u8  params[0];
-} sctp_inithdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_inithdr_t;
 
 typedef struct sctp_init_chunk {
 	sctp_chunkhdr_t chunk_hdr;
 	sctp_inithdr_t init_hdr;
-} sctp_init_chunk_t __attribute__((packed));
+} __attribute__((packed)) sctp_init_chunk_t;
 
 
 /* Section 3.3.2.1. IPv4 Address Parameter (5) */
 typedef struct sctp_ipv4addr_param {
 	sctp_paramhdr_t param_hdr;
 	struct in_addr  addr;
-} sctp_ipv4addr_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_ipv4addr_param_t;
 
 /* Section 3.3.2.1. IPv6 Address Parameter (6) */
 typedef struct sctp_ipv6addr_param {
 	sctp_paramhdr_t param_hdr;
 	struct in6_addr addr;
-} sctp_ipv6addr_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_ipv6addr_param_t;
 
 /* Section 3.3.2.1 Cookie Preservative (9) */
 typedef struct sctp_cookie_preserve_param {
 	sctp_paramhdr_t param_hdr;
 	uint32_t        lifespan_increment;
-} sctp_cookie_preserve_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_cookie_preserve_param_t;
 
 /* Section 3.3.2.1 Host Name Address (11) */
 typedef struct sctp_hostname_param {
 	sctp_paramhdr_t param_hdr;
 	uint8_t hostname[0];
-} sctp_hostname_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_hostname_param_t;
 
 /* Section 3.3.2.1 Supported Address Types (12) */
 typedef struct sctp_supported_addrs_param {
 	sctp_paramhdr_t param_hdr;
 	uint16_t types[0];
-} sctp_supported_addrs_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_supported_addrs_param_t;
 
 /* Appendix A. ECN Capable (32768) */
 typedef struct sctp_ecn_capable_param {
 	sctp_paramhdr_t param_hdr;
-} sctp_ecn_capable_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_ecn_capable_param_t;
 
 
 
@@ -287,13 +287,13 @@
 typedef struct sctp_cookie_param {
 	sctp_paramhdr_t p;
 	__u8 body[0];
-} sctp_cookie_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_cookie_param_t;
 
 /* Section 3.3.3.1 Unrecognized Parameters (8) */
 typedef struct sctp_unrecognized_param {
 	sctp_paramhdr_t param_hdr;
 	sctp_paramhdr_t unrecognized;
-} sctp_unrecognized_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_unrecognized_param_t;
 
 
 
@@ -308,7 +308,7 @@
 typedef struct sctp_gap_ack_block {
 	__u16 start;
 	__u16 end;
-} sctp_gap_ack_block_t __attribute__((packed));
+} __attribute__((packed)) sctp_gap_ack_block_t;
 
 typedef uint32_t sctp_dup_tsn_t;
 
@@ -323,12 +323,12 @@
 	__u16 num_gap_ack_blocks;
 	__u16 num_dup_tsns;
 	sctp_sack_variable_t variable[0];
-} sctp_sackhdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_sackhdr_t;
 
 typedef struct sctp_sack_chunk {
 	sctp_chunkhdr_t chunk_hdr;
 	sctp_sackhdr_t sack_hdr;
-} sctp_sack_chunk_t __attribute__((packed));
+} __attribute__((packed)) sctp_sack_chunk_t;
 
 
 /* RFC 2960.  Section 3.3.5 Heartbeat Request (HEARTBEAT) (4):
@@ -340,12 +340,12 @@
 
 typedef struct sctp_heartbeathdr {
 	sctp_paramhdr_t info;
-} sctp_heartbeathdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_heartbeathdr_t;
 
 typedef struct sctp_heartbeat_chunk {
 	sctp_chunkhdr_t chunk_hdr;
 	sctp_heartbeathdr_t hb_hdr;
-} sctp_heartbeat_chunk_t __attribute__((packed));
+} __attribute__((packed)) sctp_heartbeat_chunk_t;
 
 
 /* For the abort and shutdown ACK we must carry the init tag in the
@@ -354,7 +354,7 @@
  */
 typedef struct sctp_abort_chunk {
         sctp_chunkhdr_t uh;
-} sctp_abort_chunkt_t __attribute__((packed));
+} __attribute__((packed)) sctp_abort_chunkt_t;
 
 
 /* For the graceful shutdown we must carry the tag (in common header)
@@ -362,14 +362,12 @@
  */
 typedef struct sctp_shutdownhdr {
 	__u32 cum_tsn_ack;
-} sctp_shutdownhdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_shutdownhdr_t;
 
 struct sctp_shutdown_chunk_t {
         sctp_chunkhdr_t    chunk_hdr;
         sctp_shutdownhdr_t shutdown_hdr;
-} __attribute__((packed));
-
-
+} __attribute__ ((packed));
 
 /* RFC 2960.  Section 3.3.10 Operation Error (ERROR) (9) */
 
@@ -377,12 +375,12 @@
 	__u16 cause;
 	__u16 length;
 	__u8  variable[0];
-} sctp_errhdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_errhdr_t;
 
 typedef struct sctp_operr_chunk {
         sctp_chunkhdr_t chunk_hdr;
 	sctp_errhdr_t   err_hdr;
-} sctp_operr_chunk_t __attribute__((packed));
+} __attribute__((packed)) sctp_operr_chunk_t;
 
 /* RFC 2960 3.3.10 - Operation Error
  *
@@ -460,7 +458,7 @@
 typedef struct sctp_ecne_chunk {
 	sctp_chunkhdr_t chunk_hdr;
 	sctp_ecnehdr_t ence_hdr;
-} sctp_ecne_chunk_t __attribute__((packed));
+} __attribute__((packed)) sctp_ecne_chunk_t;
 
 /* RFC 2960.  Appendix A.  Explicit Congestion Notification.
  *   Congestion Window Reduced (CWR) (13)
@@ -472,7 +470,7 @@
 typedef struct sctp_cwr_chunk {
 	sctp_chunkhdr_t chunk_hdr;
 	sctp_cwrhdr_t cwr_hdr;
-} sctp_cwr_chunk_t __attribute__((packed));
+} __attribute__((packed)) sctp_cwr_chunk_t;
 
 /*
  * ADDIP Section 3.1 New Chunk Types
@@ -513,16 +511,16 @@
 typedef struct sctp_addip_param {
 	sctp_paramhdr_t	param_hdr;
 	__u32		crr_id;	
-}sctp_addip_param_t __attribute__((packed));
+} __attribute__((packed)) sctp_addip_param_t;
 
 typedef struct sctp_addiphdr {
 	__u32	serial;
 	__u8	params[0];
-} sctp_addiphdr_t __attribute__((packed));
+} __attribute__((packed)) sctp_addiphdr_t;
 
 typedef struct sctp_addip_chunk {
 	sctp_chunkhdr_t chunk_hdr;
 	sctp_addiphdr_t addip_hdr;
-} sctp_addip_chunk_t __attribute__((packed));
+} __attribute__((packed)) sctp_addip_chunk_t;
 
 #endif /* __LINUX_SCTP_H__ */
diff -urN linux-2.4.26-pre1/include/linux/skbuff.h linux-2.4.26-pre2/include/linux/skbuff.h
--- linux-2.4.26-pre1/include/linux/skbuff.h	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.26-pre2/include/linux/skbuff.h	2004-03-06 11:20:29.000000000 -0800
@@ -221,9 +221,6 @@
 #endif
 };
 
-#define SK_WMEM_MAX	65535
-#define SK_RMEM_MAX	65535
-
 #ifdef __KERNEL__
 /*
  *	Handling routines are only of interest to the kernel
diff -urN linux-2.4.26-pre1/include/net/sctp/sctp.h linux-2.4.26-pre2/include/net/sctp/sctp.h
--- linux-2.4.26-pre1/include/net/sctp/sctp.h	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/include/net/sctp/sctp.h	2004-03-06 11:20:29.000000000 -0800
@@ -115,7 +115,7 @@
 #define SCTP_STATIC static
 #endif
 
-#define MSECS_TO_JIFFIES(msec) \
+#define SCTP_MSECS_TO_JIFFIES(msec) \
 	(((msec / 1000) * HZ) + ((msec % 1000) * HZ) / 1000)
 #define JIFFIES_TO_MSECS(jiff) \
 	(((jiff / HZ) * 1000) + ((jiff % HZ) * 1000) / HZ)
diff -urN linux-2.4.26-pre1/include/net/sctp/structs.h linux-2.4.26-pre2/include/net/sctp/structs.h
--- linux-2.4.26-pre1/include/net/sctp/structs.h	2004-03-06 11:20:26.000000000 -0800
+++ linux-2.4.26-pre2/include/net/sctp/structs.h	2004-03-06 11:20:29.000000000 -0800
@@ -369,7 +369,7 @@
 	struct sctp_paramhdr param_hdr;
 	union sctp_addr daddr;
 	unsigned long sent_at;
-} sctp_sender_hb_info_t __attribute__((packed));
+} __attribute__((packed)) sctp_sender_hb_info_t;
 
 /*
  *  RFC 2960 1.3.2 Sequenced Delivery within Streams
diff -urN linux-2.4.26-pre1/mm/vmalloc.c linux-2.4.26-pre2/mm/vmalloc.c
--- linux-2.4.26-pre1/mm/vmalloc.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.26-pre2/mm/vmalloc.c	2004-03-06 11:20:29.000000000 -0800
@@ -159,8 +159,8 @@
 					struct page ***pages)
 {
 	pgd_t * dir;
+	unsigned long start = address;
 	unsigned long end = address + size;
-	int ret;
 
 	dir = pgd_offset_k(address);
 	spin_lock(&init_mm.page_table_lock);
@@ -168,22 +168,22 @@
 		pmd_t *pmd;
 		
 		pmd = pmd_alloc(&init_mm, dir, address);
-		ret = -ENOMEM;
 		if (!pmd)
-			break;
+			goto err;
 
-		ret = -ENOMEM;
 		if (alloc_area_pmd(pmd, address, end - address, gfp_mask, prot, pages))
-			break;
+			goto err;	// The kernel NEVER reclaims pmds, so no need to undo pmd_alloc() here
 
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
-
-		ret = 0;
 	} while (address && (address < end));
 	spin_unlock(&init_mm.page_table_lock);
 	flush_cache_all();
-	return ret;
+	return 0;
+err:
+	if (address > start)
+		vmfree_area_pages((address - start), address - start);
+	return -ENOMEM;
 }
 
 int vmalloc_area_pages(unsigned long address, unsigned long size,
@@ -234,7 +234,7 @@
 	return NULL;
 }
 
-void vfree(void * addr)
+void __vfree(void * addr, int free_area_pages)
 {
 	struct vm_struct **p, *tmp;
 
@@ -248,7 +248,8 @@
 	for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
 		if (tmp->addr == addr) {
 			*p = tmp->next;
-			vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
+			if (free_area_pages)
+				vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
 			write_unlock(&vmlist_lock);
 			kfree(tmp);
 			return;
@@ -258,6 +259,11 @@
 	printk(KERN_ERR "Trying to vfree() nonexistent vm area (%p)\n", addr);
 }
 
+void vfree(void * addr)
+{
+	__vfree(addr,1);
+}
+
 void * __vmalloc (unsigned long size, int gfp_mask, pgprot_t prot)
 {
 	void * addr;
@@ -272,7 +278,7 @@
 	addr = area->addr;
 	if (__vmalloc_area_pages(VMALLOC_VMADDR(addr), size, gfp_mask,
 				 prot, NULL)) {
-		vfree(addr);
+		__vfree(addr, 0);
 		return NULL;
 	}
 	return addr;
@@ -294,7 +300,7 @@
 	addr = area->addr;
 	if (__vmalloc_area_pages(VMALLOC_VMADDR(addr), size, 0,
 				 prot, &pages)) {
-		vfree(addr);
+		__vfree(addr, 0);
 		return NULL;
 	}
 	return addr;
diff -urN linux-2.4.26-pre1/net/Makefile linux-2.4.26-pre2/net/Makefile
--- linux-2.4.26-pre1/net/Makefile	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre2/net/Makefile	2004-03-06 11:20:30.000000000 -0800
@@ -15,10 +15,10 @@
 
 
 subdir-$(CONFIG_NET)		+= 802 sched netlink
+subdir-$(CONFIG_IPV6)		+= ipv6
 subdir-$(CONFIG_INET)		+= ipv4
 subdir-$(CONFIG_NETFILTER)	+= ipv4/netfilter
 subdir-$(CONFIG_UNIX)		+= unix
-subdir-$(CONFIG_IPV6)		+= ipv6
 subdir-$(CONFIG_IP_SCTP)	+= sctp
 
 ifneq ($(CONFIG_IPV6),n)
diff -urN linux-2.4.26-pre1/net/atm/lec.c linux-2.4.26-pre2/net/atm/lec.c
--- linux-2.4.26-pre1/net/atm/lec.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre2/net/atm/lec.c	2004-03-06 11:20:29.000000000 -0800
@@ -208,6 +208,22 @@
         return 0;
 }
 
+static __inline__ void
+lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv)
+{
+	if (atm_may_send(vcc, skb->len)) {
+		atomic_add(skb->truesize, &vcc->sk->wmem_alloc);
+	        ATM_SKB(skb)->vcc = vcc;
+	        ATM_SKB(skb)->atm_options = vcc->atm_options;
+		priv->stats.tx_packets++;
+		priv->stats.tx_bytes += skb->len;
+		vcc->send(vcc, skb);
+	} else {
+		priv->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+	}
+}
+
 static int 
 lec_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
@@ -352,33 +368,10 @@
                 DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
                         lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2],
                         lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]);
-                ATM_SKB(skb2)->vcc = send_vcc;
-                ATM_SKB(skb2)->atm_options = send_vcc->atm_options;
-                DPRINTK("%s:sending to vpi:%d vci:%d\n", dev->name,
-                        send_vcc->vpi, send_vcc->vci);       
-                if (atm_may_send(send_vcc, skb2->len)) {
-			atomic_add(skb2->truesize, &send_vcc->sk->wmem_alloc);
-                        priv->stats.tx_packets++;
-                        priv->stats.tx_bytes += skb2->len;
-                        send_vcc->send(send_vcc, skb2);
-                } else {
-                        priv->stats.tx_dropped++;
-                        dev_kfree_skb(skb2);
-		}
+                lec_send(send_vcc, skb2, priv);
         }
 
-        ATM_SKB(skb)->vcc = send_vcc;
-        ATM_SKB(skb)->atm_options = send_vcc->atm_options;
-        if (atm_may_send(send_vcc, skb->len)) {
-                atomic_add(skb->truesize, &send_vcc->sk->wmem_alloc);
-                priv->stats.tx_packets++;
-                priv->stats.tx_bytes += skb->len;
-                send_vcc->send(send_vcc, skb);
-        } else {
-                priv->stats.tx_dropped++;
-                dev_kfree_skb(skb);
-	}
-
+        lec_send(send_vcc, skb, priv);
 #if 0
         /* Should we wait for card's device driver to notify us? */
         dev->tbusy=0;
@@ -1043,7 +1036,7 @@
 #define LEC_ARP_REFRESH_INTERVAL (3*HZ)
 
 static void lec_arp_check_expire(unsigned long data);
-static __inline__ void lec_arp_expire_arp(unsigned long data);
+static void lec_arp_expire_arp(unsigned long data);
 void dump_arp_table(struct lec_priv *priv);
 
 /* 
@@ -1383,7 +1376,7 @@
         struct lec_arp_table *entry, *next;
         int i;
 
-        del_timer(&priv->lec_arp_timer);
+        del_timer_sync(&priv->lec_arp_timer);
         
         /*
          * Remove all entries
@@ -1398,7 +1391,7 @@
         entry = priv->lec_arp_empty_ones;
         while(entry) {
                 next = entry->next;
-                del_timer(&entry->timer);
+                del_timer_sync(&entry->timer);
                 lec_arp_clear_vccs(entry);
                 kfree(entry);
                 entry = next;
@@ -1407,7 +1400,7 @@
         entry = priv->lec_no_forward;
         while(entry) {
                 next = entry->next;
-                del_timer(&entry->timer);
+                del_timer_sync(&entry->timer);
                 lec_arp_clear_vccs(entry);
                 kfree(entry);
                 entry = next;
@@ -1416,7 +1409,7 @@
         entry = priv->mcast_fwds;
         while(entry) {
                 next = entry->next;
-                del_timer(&entry->timer);
+                /* No timer, LANEv2 7.1.20 and 2.3.5.3 */
                 lec_arp_clear_vccs(entry);
                 kfree(entry);
                 entry = next;
@@ -1490,8 +1483,6 @@
 
         entry = (struct lec_arp_table *)data;
 
-        del_timer(&entry->timer);
-
         DPRINTK("lec_arp_expire_arp\n");
         if (entry->status == ESI_ARP_PENDING) {
                 if (entry->no_tries <= entry->priv->max_retry_count) {
@@ -1501,8 +1492,7 @@
                                 send_to_lecd(entry->priv, l_arp_xmt, entry->mac_addr, NULL, NULL);
                         entry->no_tries++;
                 }
-                entry->timer.expires = jiffies + (1*HZ);
-                add_timer(&entry->timer);
+                mod_timer(&entry->timer, jiffies + (1*HZ));
         }
 }
 
@@ -1574,8 +1564,6 @@
         unsigned long time_to_check;
         int i;
 
-        del_timer(&priv->lec_arp_timer);
-
         DPRINTK("lec_arp_check_expire %p,%d\n",priv,
                 atomic_read(&priv->lec_arp_users));
         DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones,
@@ -1619,6 +1607,10 @@
                                            &&
                                            time_after_eq(now, entry->timestamp+
                                            priv->path_switching_delay)) {
+			                        struct sk_buff *skb;
+
+ 				                while ((skb = skb_dequeue(&entry->tx_wait)))
+					                lec_send(entry->vcc, skb, entry->priv);
                                                 entry->last_used = jiffies;
                                                 entry->status = 
                                                         ESI_FORWARD_DIRECT;
@@ -1629,8 +1621,8 @@
                 }
                 lec_arp_put(priv);
         }
-        priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL;
-        add_timer(&priv->lec_arp_timer);
+
+        mod_timer(&priv->lec_arp_timer, jiffies + LEC_ARP_REFRESH_INTERVAL);
 }
 /*
  * Try to find vcc where mac_address is attached.
@@ -2012,6 +2004,10 @@
                 for (entry=priv->lec_arp_tables[i];entry;entry=entry->next) {
                         if (entry->flush_tran_id == tran_id &&
                             entry->status == ESI_FLUSH_PENDING) {
+			        struct sk_buff *skb;
+
+ 				while ((skb = skb_dequeue(&entry->tx_wait)))
+					lec_send(entry->vcc, skb, entry->priv);
                                 entry->status = ESI_FORWARD_DIRECT;
                                 DPRINTK("LEC_ARP: Flushed\n");
                         }
diff -urN linux-2.4.26-pre1/net/core/dev.c linux-2.4.26-pre2/net/core/dev.c
--- linux-2.4.26-pre1/net/core/dev.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/net/core/dev.c	2004-03-06 11:20:29.000000000 -0800
@@ -1462,7 +1462,7 @@
 {
 	struct packet_type *ptype, *pt_prev;
 	int ret = NET_RX_DROP;
-	unsigned short type = skb->protocol;
+	unsigned short type;
 
 	if (skb->stamp.tv_sec == 0)
 		do_gettimeofday(&skb->stamp);
@@ -1507,6 +1507,7 @@
 	}
 #endif
 
+	type = skb->protocol;
 	for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) {
 		if (ptype->type == type &&
 		    (!ptype->dev || ptype->dev == skb->dev)) {
diff -urN linux-2.4.26-pre1/net/core/sock.c linux-2.4.26-pre2/net/core/sock.c
--- linux-2.4.26-pre1/net/core/sock.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.26-pre2/net/core/sock.c	2004-03-06 11:20:29.000000000 -0800
@@ -128,6 +128,16 @@
 #include <net/tcp.h>
 #endif
 
+/* Take into consideration the size of the struct sk_buff overhead in the
+ * determination of these values, since that is non-constant across
+ * platforms.  This makes socket queueing behavior and performance
+ * not depend upon such differences.
+ */
+#define _SK_MEM_PACKETS		256
+#define _SK_MEM_OVERHEAD	(sizeof(struct sk_buff) + 256)
+#define SK_WMEM_MAX		(_SK_MEM_OVERHEAD * _SK_MEM_PACKETS)
+#define SK_RMEM_MAX		(_SK_MEM_OVERHEAD * _SK_MEM_PACKETS)
+
 /* Run time adjustable parameters. */
 __u32 sysctl_wmem_max = SK_WMEM_MAX;
 __u32 sysctl_rmem_max = SK_RMEM_MAX;
diff -urN linux-2.4.26-pre1/net/ipv4/icmp.c linux-2.4.26-pre2/net/ipv4/icmp.c
--- linux-2.4.26-pre1/net/ipv4/icmp.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/net/ipv4/icmp.c	2004-03-06 11:20:29.000000000 -0800
@@ -984,7 +984,13 @@
 			panic("Failed to create the ICMP control socket.\n");
 
 		icmp_socket_cpu(i)->sk->allocation=GFP_ATOMIC;
-		icmp_socket_cpu(i)->sk->sndbuf = SK_WMEM_MAX*2;
+
+		/* Enough space for 2 64K ICMP packets, including
+		 * sk_buff struct overhead.
+		 */
+		icmp_socket_cpu(i)->sk->sndbuf =
+			(2 * ((64 * 1024) + sizeof(struct sk_buff)));
+
 		icmp_socket_cpu(i)->sk->protinfo.af_inet.ttl = MAXTTL;
 		icmp_socket_cpu(i)->sk->protinfo.af_inet.pmtudisc = IP_PMTUDISC_DONT;
 
diff -urN linux-2.4.26-pre1/net/ipv4/ip_sockglue.c linux-2.4.26-pre2/net/ipv4/ip_sockglue.c
--- linux-2.4.26-pre1/net/ipv4/ip_sockglue.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.26-pre2/net/ipv4/ip_sockglue.c	2004-03-06 11:20:29.000000000 -0800
@@ -608,10 +608,15 @@
 		}
 		case IP_MSFILTER:
 		{
+			extern int sysctl_optmem_max;
 			struct ip_msfilter *msf;
 
 			if (optlen < IP_MSFILTER_SIZE(0))
 				goto e_inval;
+			if (optlen > sysctl_optmem_max) {
+				err = -ENOBUFS;
+				break;
+			}
 			msf = (struct ip_msfilter *)kmalloc(optlen, GFP_KERNEL);
 			if (msf == 0) {
 				err = -ENOBUFS;
@@ -622,6 +627,13 @@
 				kfree(msf);
 				break;
 			}
+			if (IP_MSFILTER_SIZE(msf->imsf_numsrc) < 
+			    IP_MSFILTER_SIZE(0) ||
+			    IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) {
+				kfree(msf);
+				err = -EINVAL;
+				break;
+			}
 			err = ip_mc_msfilter(sk, msf, 0);
 			kfree(msf);
 			break;
diff -urN linux-2.4.26-pre1/net/ipv4/netfilter/ipt_ECN.c linux-2.4.26-pre2/net/ipv4/netfilter/ipt_ECN.c
--- linux-2.4.26-pre1/net/ipv4/netfilter/ipt_ECN.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.26-pre2/net/ipv4/netfilter/ipt_ECN.c	2004-03-06 11:20:30.000000000 -0800
@@ -4,7 +4,7 @@
  * 
  * This software is distributed under GNU GPL v2, 1991
  * 
- * ipt_ECN.c,v 1.4 2002/08/05 19:36:51 laforge Exp
+ * ipt_ECN.c,v 1.7 2003/12/15 15:18:06 laforge Exp 
 */
 
 #include <linux/module.h>
@@ -59,8 +59,8 @@
 	    const struct ipt_ECN_info *einfo)
 {
 
-	struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
-	u_int16_t *tcpflags = (u_int16_t *)tcph + 6;
+	struct tcphdr *tcph;
+	u_int16_t *tcpflags;
 	u_int16_t diffs[2];
 
 	/* raw socket (tcpdump) may have clone of incoming
@@ -71,9 +71,12 @@
 			return NF_DROP;
 		kfree_skb(*pskb);
 		*pskb = nskb;
-		iph = (*pskb)->nh.iph;
 	}
 
+	iph = (*pskb)->nh.iph;
+	tcph = (void *) iph + iph->ihl * 4;
+	tcpflags = (u_int16_t *)tcph + 6;
+
 	diffs[0] = *tcpflags;
 
 	if (einfo->operation & IPT_ECN_OP_SET_ECE
diff -urN linux-2.4.26-pre1/net/ipv4/udp.c linux-2.4.26-pre2/net/ipv4/udp.c
--- linux-2.4.26-pre1/net/ipv4/udp.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre2/net/ipv4/udp.c	2004-03-06 11:20:30.000000000 -0800
@@ -657,6 +657,7 @@
 	if (flags & MSG_ERRQUEUE)
 		return ip_recv_error(sk, msg, len);
 
+try_again:
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb)
 		goto out;
@@ -722,7 +723,9 @@
 
 	skb_free_datagram(sk, skb);
 
-	return -EAGAIN;	
+	if (noblock)
+		return -EAGAIN;	
+	goto try_again;
 }
 
 int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
diff -urN linux-2.4.26-pre1/net/ipv6/exthdrs.c linux-2.4.26-pre2/net/ipv6/exthdrs.c
--- linux-2.4.26-pre1/net/ipv6/exthdrs.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.26-pre2/net/ipv6/exthdrs.c	2004-03-06 11:20:30.000000000 -0800
@@ -798,8 +798,16 @@
 		if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
 			BUG();
 		if (nexthdr == NEXTHDR_FRAGMENT) {
-			struct frag_hdr *fhdr = (struct frag_hdr *) &hdr;
-			if (ntohs(fhdr->frag_off) & ~0x7)
+			unsigned short frag_off;
+			if (skb_copy_bits(skb,
+					  start+offsetof(struct frag_hdr,
+							 frag_off),
+					  &frag_off,
+					  sizeof(frag_off))) {
+				return -1;
+			}
+
+			if (ntohs(frag_off) & ~0x7)
 				break;
 			hdrlen = 8;
 		} else if (nexthdr == NEXTHDR_AUTH)
diff -urN linux-2.4.26-pre1/net/ipv6/icmp.c linux-2.4.26-pre2/net/ipv6/icmp.c
--- linux-2.4.26-pre1/net/ipv6/icmp.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre2/net/ipv6/icmp.c	2004-03-06 11:20:30.000000000 -0800
@@ -648,7 +648,13 @@
 
 		sk = icmpv6_socket_cpu(i)->sk;
 		sk->allocation = GFP_ATOMIC;
-		sk->sndbuf = SK_WMEM_MAX*2;
+
+		/* Enough space for 2 64K ICMP packets, including
+		 * sk_buff struct overhead.
+		 */
+		sk->sndbuf =
+			(2 * ((64 * 1024) + sizeof(struct sk_buff)));
+
 		sk->prot->unhash(sk);
 	}
 
diff -urN linux-2.4.26-pre1/net/ipv6/ipv6_sockglue.c linux-2.4.26-pre2/net/ipv6/ipv6_sockglue.c
--- linux-2.4.26-pre1/net/ipv6/ipv6_sockglue.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.26-pre2/net/ipv6/ipv6_sockglue.c	2004-03-06 11:20:30.000000000 -0800
@@ -452,10 +452,15 @@
 	}
 	case MCAST_MSFILTER:
 	{
+		extern int sysctl_optmem_max;
 		struct group_filter *gsf;
 
 		if (optlen < GROUP_FILTER_SIZE(0))
 			goto e_inval;
+		if (optlen > sysctl_optmem_max) {
+			retv = -ENOBUFS;
+			break;
+		}
 		gsf = (struct group_filter *)kmalloc(optlen,GFP_KERNEL);
 		if (gsf == 0) {
 			retv = -ENOBUFS;
@@ -466,6 +471,12 @@
 			kfree(gsf);
 			break;
 		}
+		if (GROUP_FILTER_SIZE(gsf->gf_numsrc) < GROUP_FILTER_SIZE(0) ||
+		    GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
+			kfree(gsf);
+			retv = -EINVAL;
+			break;
+		}
 		retv = ip6_mc_msfilter(sk, gsf);
 		kfree(gsf);
 
diff -urN linux-2.4.26-pre1/net/ipv6/ipv6_syms.c linux-2.4.26-pre2/net/ipv6/ipv6_syms.c
--- linux-2.4.26-pre1/net/ipv6/ipv6_syms.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre2/net/ipv6/ipv6_syms.c	2004-03-06 11:20:30.000000000 -0800
@@ -33,3 +33,5 @@
 EXPORT_SYMBOL(ipv6_get_saddr);
 EXPORT_SYMBOL(ipv6_chk_addr);
 EXPORT_SYMBOL(in6_dev_finish_destroy);
+EXPORT_SYMBOL(ipv6_skip_exthdr);
+
diff -urN linux-2.4.26-pre1/net/ipv6/netfilter/ip6_tables.c linux-2.4.26-pre2/net/ipv6/netfilter/ip6_tables.c
--- linux-2.4.26-pre1/net/ipv6/netfilter/ip6_tables.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/net/ipv6/netfilter/ip6_tables.c	2004-03-06 11:20:30.000000000 -0800
@@ -1568,8 +1568,10 @@
 	  u_int16_t datalen,
 	  int *hotdrop)
 {
-	const struct tcphdr *tcp = hdr;
+	const struct tcphdr *tcp;
 	const struct ip6t_tcp *tcpinfo = matchinfo;
+	int tcpoff;
+	u8 nexthdr = skb->nh.ipv6h->nexthdr;
 
 	/* To quote Alan:
 
@@ -1590,6 +1592,24 @@
 		return 0;
 	}
 
+	tcpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data;
+	tcpoff = ipv6_skip_exthdr(skb, tcpoff, &nexthdr, skb->len - tcpoff);
+	if (tcpoff < 0 || tcpoff > skb->len) {
+		duprintf("tcp_match: cannot skip exthdr. Dropping.\n");
+		*hotdrop = 1;
+		return 0;
+	} else if (nexthdr == IPPROTO_FRAGMENT)
+		return 0;
+	else if (nexthdr != IPPROTO_TCP ||
+		 skb->len - tcpoff < sizeof(struct tcphdr)) {
+		/* cannot be occured */
+		duprintf("tcp_match: cannot get TCP header. Dropping.\n");
+		*hotdrop = 1;
+		return 0;
+	}
+
+	tcp = (struct tcphdr *)(skb->data + tcpoff);
+
 	/* FIXME: Try tcp doff >> packet len against various stacks --RR */
 
 #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
@@ -1640,8 +1660,10 @@
 	  u_int16_t datalen,
 	  int *hotdrop)
 {
-	const struct udphdr *udp = hdr;
+	const struct udphdr *udp;
 	const struct ip6t_udp *udpinfo = matchinfo;
+	int udpoff;
+	u8 nexthdr = skb->nh.ipv6h->nexthdr;
 
 	if (offset == 0 && datalen < sizeof(struct udphdr)) {
 		/* We've been asked to examine this packet, and we
@@ -1651,6 +1673,23 @@
 		return 0;
 	}
 
+	udpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data;
+	udpoff = ipv6_skip_exthdr(skb, udpoff, &nexthdr, skb->len - udpoff);
+	if (udpoff < 0 || udpoff > skb->len) {
+		duprintf("udp_match: cannot skip exthdr. Dropping.\n");
+		*hotdrop = 1;
+		return 0;
+	} else if (nexthdr == IPPROTO_FRAGMENT)
+		return 0;
+	else if (nexthdr != IPPROTO_UDP ||
+		 skb->len - udpoff < sizeof(struct udphdr)) {
+		duprintf("udp_match: cannot get UDP header. Dropping.\n");
+		*hotdrop = 1;
+		return 0;
+	}
+
+	udp = (struct udphdr *)(skb->data + udpoff);
+
 	/* Must not be a fragment. */
 	return !offset
 		&& port_match(udpinfo->spts[0], udpinfo->spts[1],
diff -urN linux-2.4.26-pre1/net/ipv6/udp.c linux-2.4.26-pre2/net/ipv6/udp.c
--- linux-2.4.26-pre1/net/ipv6/udp.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre2/net/ipv6/udp.c	2004-03-06 11:20:30.000000000 -0800
@@ -400,6 +400,7 @@
 	if (flags & MSG_ERRQUEUE)
 		return ipv6_recv_error(sk, msg, len);
 
+try_again:
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb)
 		goto out;
@@ -476,12 +477,13 @@
 			kfree_skb(skb);
 	}
 
-	/* Error for blocking case is chosen to masquerade
-	   as some normal condition.
-	 */
-	err = (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
-	UDP6_INC_STATS_USER(UdpInErrors);
-	goto out_free;
+	skb_free_datagram(sk, skb);
+
+	if (flags & MSG_DONTWAIT) {
+		UDP6_INC_STATS_USER(UdpInErrors);
+		return -EAGAIN;
+	}
+	goto try_again;
 }
 
 void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
diff -urN linux-2.4.26-pre1/net/netsyms.c linux-2.4.26-pre2/net/netsyms.c
--- linux-2.4.26-pre1/net/netsyms.c	2004-03-06 11:20:27.000000000 -0800
+++ linux-2.4.26-pre2/net/netsyms.c	2004-03-06 11:20:30.000000000 -0800
@@ -40,6 +40,7 @@
 #ifdef CONFIG_NET
 extern __u32 sysctl_wmem_max;
 extern __u32 sysctl_rmem_max;
+extern int sysctl_optmem_max;
 #endif
 
 #ifdef CONFIG_INET
@@ -550,6 +551,7 @@
 #ifdef CONFIG_SYSCTL
 EXPORT_SYMBOL(sysctl_wmem_max);
 EXPORT_SYMBOL(sysctl_rmem_max);
+EXPORT_SYMBOL(sysctl_optmem_max);
 #ifdef CONFIG_INET
 EXPORT_SYMBOL(sysctl_ip_default_ttl);
 #endif
diff -urN linux-2.4.26-pre1/net/sctp/associola.c linux-2.4.26-pre2/net/sctp/associola.c
--- linux-2.4.26-pre1/net/sctp/associola.c	2004-03-06 11:20:27.000000000 -0800
+++ linux-2.4.26-pre2/net/sctp/associola.c	2004-03-06 11:20:30.000000000 -0800
@@ -142,9 +142,9 @@
 	 * socket values.
 	 */
 	asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt;
-	asoc->rto_initial = MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial);
-	asoc->rto_max = MSECS_TO_JIFFIES(sp->rtoinfo.srto_max);
-	asoc->rto_min = MSECS_TO_JIFFIES(sp->rtoinfo.srto_min);
+	asoc->rto_initial = SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial);
+	asoc->rto_max = SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_max);
+	asoc->rto_min = SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_min);
 
 	asoc->overall_error_count = 0;
 
@@ -170,7 +170,7 @@
 	asoc->max_init_attempts	= sp->initmsg.sinit_max_attempts;
 
 	asoc->max_init_timeo =
-		 MSECS_TO_JIFFIES(sp->initmsg.sinit_max_init_timeo);
+		 SCTP_MSECS_TO_JIFFIES(sp->initmsg.sinit_max_init_timeo);
 
 	/* Allocate storage for the ssnmap after the inbound and outbound
 	 * streams have been negotiated during Init.
@@ -510,7 +510,7 @@
 	/* Initialize the peer's heartbeat interval based on the
 	 * sock configured value.
 	 */
-	peer->hb_interval = MSECS_TO_JIFFIES(sp->paddrparam.spp_hbinterval);
+	peer->hb_interval = SCTP_MSECS_TO_JIFFIES(sp->paddrparam.spp_hbinterval);
 
 	/* Set the path max_retrans.  */
 	peer->max_retrans = asoc->max_retrans;
diff -urN linux-2.4.26-pre1/net/sctp/chunk.c linux-2.4.26-pre2/net/sctp/chunk.c
--- linux-2.4.26-pre1/net/sctp/chunk.c	2004-03-06 11:20:27.000000000 -0800
+++ linux-2.4.26-pre2/net/sctp/chunk.c	2004-03-06 11:20:30.000000000 -0800
@@ -184,7 +184,7 @@
 	if (sinfo->sinfo_timetolive) {
 		/* sinfo_timetolive is in milliseconds */
 		msg->expires_at = jiffies +
-				     MSECS_TO_JIFFIES(sinfo->sinfo_timetolive);
+				     SCTP_MSECS_TO_JIFFIES(sinfo->sinfo_timetolive);
 		msg->can_expire = 1;
 	}
 
diff -urN linux-2.4.26-pre1/net/sctp/endpointola.c linux-2.4.26-pre2/net/sctp/endpointola.c
--- linux-2.4.26-pre1/net/sctp/endpointola.c	2004-03-06 11:20:27.000000000 -0800
+++ linux-2.4.26-pre2/net/sctp/endpointola.c	2004-03-06 11:20:30.000000000 -0800
@@ -129,7 +129,7 @@
 	ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
 		SCTP_DEFAULT_TIMEOUT_T1_INIT;
 	ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
-		MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial);
+		SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial);
 	ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
 	ep->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0;
 
@@ -138,7 +138,7 @@
 	 * recommended value of 5 times 'RTO.Max'.
 	 */
         ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
-		= 5 * MSECS_TO_JIFFIES(sp->rtoinfo.srto_max);
+		= 5 * SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_max);
 
 	ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
 		SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
diff -urN linux-2.4.26-pre1/net/sctp/ipv6.c linux-2.4.26-pre2/net/sctp/ipv6.c
--- linux-2.4.26-pre1/net/sctp/ipv6.c	2004-03-06 11:20:27.000000000 -0800
+++ linux-2.4.26-pre2/net/sctp/ipv6.c	2004-03-06 11:20:31.000000000 -0800
@@ -82,14 +82,14 @@
 
 /* FIXME: This macro needs to be moved to a common header file. */
 #define NIP6(addr) \
-	ntohs((addr).s6_addr16[0]), \
-	ntohs((addr).s6_addr16[1]), \
-	ntohs((addr).s6_addr16[2]), \
-	ntohs((addr).s6_addr16[3]), \
-	ntohs((addr).s6_addr16[4]), \
-	ntohs((addr).s6_addr16[5]), \
-	ntohs((addr).s6_addr16[6]), \
-	ntohs((addr).s6_addr16[7])
+	ntohs((addr)->s6_addr16[0]), \
+	ntohs((addr)->s6_addr16[1]), \
+	ntohs((addr)->s6_addr16[2]), \
+	ntohs((addr)->s6_addr16[3]), \
+	ntohs((addr)->s6_addr16[4]), \
+	ntohs((addr)->s6_addr16[5]), \
+	ntohs((addr)->s6_addr16[6]), \
+	ntohs((addr)->s6_addr16[7])
 
 /* ICMP error handler. */
 void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
@@ -226,7 +226,7 @@
 		SCTP_DEBUG_PRINTK(
 			"rt6_dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
 			"rt6_src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-			NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr));
+			NIP6(&rt->rt6i_dst.addr), NIP6(&rt->rt6i_src.addr));
 	} else {
 		SCTP_DEBUG_PRINTK("NO ROUTE\n");
 	}
@@ -273,13 +273,13 @@
 
 	SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p "
 			  "daddr:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ",
-			  __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr));
+			  __FUNCTION__, asoc, dst, NIP6(&daddr->v6.sin6_addr));
 
 	if (!asoc) {
 		ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr);
 		SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: "
 				  "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-				  NIP6(saddr->v6.sin6_addr));
+				  NIP6(&saddr->v6.sin6_addr));
 		return;
 	}
 
@@ -308,12 +308,12 @@
 		memcpy(saddr, baddr, sizeof(union sctp_addr));
 		SCTP_DEBUG_PRINTK("saddr: "
 				  "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-				  NIP6(saddr->v6.sin6_addr));
+				  NIP6(&saddr->v6.sin6_addr));
 	} else {
 		printk(KERN_ERR "%s: asoc:%p Could not find a valid source "
 		       "address for the "
 		       "dest:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
-		       __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr));
+		       __FUNCTION__, asoc, NIP6(&daddr->v6.sin6_addr));
 	}
 
 	sctp_read_unlock(addr_lock);
@@ -678,7 +678,7 @@
 static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
 {
 	seq_printf(seq, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ",
-		   NIP6(addr->v6.sin6_addr));
+		   NIP6(&addr->v6.sin6_addr));
 }
 
 /* Initialize a PF_INET6 socket msg_name. */
diff -urN linux-2.4.26-pre1/net/sctp/sm_statefuns.c linux-2.4.26-pre2/net/sctp/sm_statefuns.c
--- linux-2.4.26-pre1/net/sctp/sm_statefuns.c	2004-03-06 11:20:27.000000000 -0800
+++ linux-2.4.26-pre2/net/sctp/sm_statefuns.c	2004-03-06 11:20:31.000000000 -0800
@@ -4272,8 +4272,7 @@
 
 	SCTP_DEBUG_PRINTK("Timer T1 expired.\n");
 
-	if ((timeout < asoc->max_init_timeo) &&
-	    (attempts < asoc->max_init_attempts)) {
+	if (attempts < asoc->max_init_attempts) {
 		switch (timer) {
 		case SCTP_EVENT_TIMEOUT_T1_INIT:
 			bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
diff -urN linux-2.4.26-pre1/net/sctp/socket.c linux-2.4.26-pre2/net/sctp/socket.c
--- linux-2.4.26-pre1/net/sctp/socket.c	2004-03-06 11:20:27.000000000 -0800
+++ linux-2.4.26-pre2/net/sctp/socket.c	2004-03-06 11:20:31.000000000 -0800
@@ -1216,7 +1216,7 @@
 			}
 			if (sinit->sinit_max_init_timeo) {
 				asoc->max_init_timeo = 
-				 MSECS_TO_JIFFIES(sinit->sinit_max_init_timeo);
+				 SCTP_MSECS_TO_JIFFIES(sinit->sinit_max_init_timeo);
 			}
 		}
 
@@ -1654,7 +1654,7 @@
 		if (params.spp_hbinterval) {
 			trans->hb_allowed = 1;
 			trans->hb_interval = 
-				MSECS_TO_JIFFIES(params.spp_hbinterval);
+				SCTP_MSECS_TO_JIFFIES(params.spp_hbinterval);
 		} else
 			trans->hb_allowed = 0;
 	}
@@ -1827,11 +1827,11 @@
 	if (asoc) {
 		if (rtoinfo.srto_initial != 0)
 			asoc->rto_initial = 
-				MSECS_TO_JIFFIES(rtoinfo.srto_initial);
+				SCTP_MSECS_TO_JIFFIES(rtoinfo.srto_initial);
 		if (rtoinfo.srto_max != 0)
-			asoc->rto_max = MSECS_TO_JIFFIES(rtoinfo.srto_max);
+			asoc->rto_max = SCTP_MSECS_TO_JIFFIES(rtoinfo.srto_max);
 		if (rtoinfo.srto_min != 0)
-			asoc->rto_min = MSECS_TO_JIFFIES(rtoinfo.srto_min);
+			asoc->rto_min = SCTP_MSECS_TO_JIFFIES(rtoinfo.srto_min);
 	} else {
 		/* If there is no association or the association-id = 0
 		 * set the values to the endpoint.
