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

diff -urN linux-2.5.74-bk7/CREDITS linux-2.5.74-bk8/CREDITS
--- linux-2.5.74-bk7/CREDITS	2003-07-02 13:51:13.000000000 -0700
+++ linux-2.5.74-bk8/CREDITS	2003-07-10 04:38:35.000000000 -0700
@@ -828,8 +828,8 @@
 W: http://www.linux-usb.org
 D: Linux-USB subsystem, USB core/UHCI/printer/storage drivers
 D: x86 SMP, ACPI, bootflag hacking
-S: 15275 SW Koll Parkway, Suite H
-S: Beaverton, Oregon 97006
+S: 12725 SW Millikan Way, Suite 400
+S: Beaverton, Oregon 97005
 S: USA
 
 N: Bob Dunlop
@@ -2228,8 +2228,8 @@
 E: mochel@osdl.org
 E: mochelp@infinity.powertie.org
 D: PCI Power Management, ACPI work
-S: 15275 SW Koll Parkway, Suite H
-S: Beaverton, OR 97006 
+S: 12725 SW Millikan Way, Suite 400
+S: Beaverton, Oregon 97005
 S: USA
 
 N: Eberhard Moenkeberg
@@ -3046,12 +3046,10 @@
 S: Spain
 
 N: Linus Torvalds
-E: torvalds@transmeta.com
-W: http://www.cs.helsinki.fi/Linus.Torvalds
-P: 1024/A86B35C5 96 54 50 29 EC 11 44 7A  BE 67 3C 24 03 13 62 C8
+E: torvalds@osdl.org
 D: Original kernel hacker
-S: 3990 Freedom Circle
-S: Santa Clara, California 95054
+S: 12725 SW Millikan Way, Suite 400
+S: Beaverton, Oregon 97005
 S: USA
 
 N: Marcelo W. Tosatti
diff -urN linux-2.5.74-bk7/Documentation/SubmittingDrivers linux-2.5.74-bk8/Documentation/SubmittingDrivers
--- linux-2.5.74-bk7/Documentation/SubmittingDrivers	2003-07-02 13:51:12.000000000 -0700
+++ linux-2.5.74-bk8/Documentation/SubmittingDrivers	2003-07-10 04:38:35.000000000 -0700
@@ -41,7 +41,7 @@
 Linux 2.5:
 	The same rules apply as 2.4 except that you should follow linux-kernel
 	to track changes in API's. The final contact point for Linux 2.5
-	submissions is Linus Torvalds <torvalds@transmeta.com>.
+	submissions is Linus Torvalds <torvalds@osdl.org>.
 
 What Criteria Determine Acceptance
 ----------------------------------
diff -urN linux-2.5.74-bk7/Documentation/SubmittingPatches linux-2.5.74-bk8/Documentation/SubmittingPatches
--- linux-2.5.74-bk7/Documentation/SubmittingPatches	2003-07-02 13:40:13.000000000 -0700
+++ linux-2.5.74-bk8/Documentation/SubmittingPatches	2003-07-10 04:38:35.000000000 -0700
@@ -105,7 +105,7 @@
 e-mail list, and can comment on your changes.
 
 Linus Torvalds is the final arbiter of all changes accepted into the
-Linux kernel.  His e-mail address is torvalds@transmeta.com.  He gets
+Linux kernel.  His e-mail address is <torvalds@osdl.org>.  He gets
 a lot of e-mail, so typically you should do your best to -avoid- sending
 him e-mail.
 
diff -urN linux-2.5.74-bk7/Documentation/cpu-freq/user-guide.txt linux-2.5.74-bk8/Documentation/cpu-freq/user-guide.txt
--- linux-2.5.74-bk7/Documentation/cpu-freq/user-guide.txt	2003-07-02 13:41:02.000000000 -0700
+++ linux-2.5.74-bk8/Documentation/cpu-freq/user-guide.txt	2003-07-10 04:38:35.000000000 -0700
@@ -21,6 +21,8 @@
 1.1 ARM
 1.2 x86
 1.3 sparc64
+1.4 ppc
+1.5 SuperH
 
 2. "Policy" / "Governor"?
 2.1 Policy
@@ -77,6 +79,20 @@
 UltraSPARC-III
 
 
+1.4 ppc
+-------
+
+Several "PowerBook" and "iBook2" notebooks are supported.
+
+
+1.5 SuperH
+----------
+
+The following SuperH processors are supported by cpufreq:
+
+SH-3
+SH-4
+
 
 2. "Policy" / "Governor" ?
 ==========================
diff -urN linux-2.5.74-bk7/Documentation/filesystems/xfs.txt linux-2.5.74-bk8/Documentation/filesystems/xfs.txt
--- linux-2.5.74-bk7/Documentation/filesystems/xfs.txt	2003-07-02 13:53:39.000000000 -0700
+++ linux-2.5.74-bk8/Documentation/filesystems/xfs.txt	2003-07-10 04:38:35.000000000 -0700
@@ -14,8 +14,8 @@
 with the IRIX version of XFS.
 
 
-Options
-=======
+Mount Options
+=============
 
 When mounting an XFS filesystem, the following options are accepted.
 
@@ -107,3 +107,66 @@
         Don't check for double mounted file systems using the file system uuid.
         This is useful to mount LVM snapshot volumes.
 
+sysctls
+=======
+
+The following sysctls are available for the XFS filesystem:
+
+  fs.xfs.stats_clear		(Min: 0  Default: 0  Max: 1)
+	Setting this to "1" clears accumulated XFS statistics 
+	in /proc/fs/xfs/stat.  It then immediately reset to "0".
+  	
+  fs.xfs.sync_interval		(Min: HZ  Default: 30*HZ  Max: 60*HZ)
+	The interval at which the xfssyncd thread for xfs filesystems
+	flushes metadata out to disk. This thread will flush log
+	activity out, and do some processing on unlinked inodes
+
+  fs.xfs.error_level		(Min: 0  Default: 3  Max: 11)
+	A volume knob for error reporting when internal errors occur.
+	This will generate detailed messages & backtraces for filesystem
+	shutdowns, for example.  Current threshold values are:
+
+		XFS_ERRLEVEL_OFF:       0
+		XFS_ERRLEVEL_LOW:       1
+		XFS_ERRLEVEL_HIGH:      5
+
+  fs.xfs.panic_mask		(Min: 0  Default: 0  Max: 127)
+	Causes certain error conditions to call BUG(). Value is a bitmask; 
+	AND together the tags which represent errors which should cause panics:
+	
+		XFS_NO_PTAG                     0LL
+		XFS_PTAG_IFLUSH                 0x0000000000000001LL
+		XFS_PTAG_LOGRES                 0x0000000000000002LL
+		XFS_PTAG_AILDELETE              0x0000000000000004LL
+		XFS_PTAG_ERROR_REPORT           0x0000000000000008LL
+		XFS_PTAG_SHUTDOWN_CORRUPT       0x0000000000000010LL
+		XFS_PTAG_SHUTDOWN_IOERROR       0x0000000000000020LL
+		XFS_PTAG_SHUTDOWN_LOGERROR      0x0000000000000040LL
+
+	This option is intended for debugging only.		
+
+  fs.xfs.irix_symlink_mode	(Min: 0  Default: 0  Max: 1)
+	Controls whether symlinks are created with mode 0777 (default)
+	or whether their mode is affected by the umask (irix mode).
+
+  fs.xfs.irix_sgid_inherit	(Min: 0  Default: 0  Max: 1)
+	Controls files created in SGID directories.
+	If the group ID of the new file does not match the effective group
+	ID or one of the supplementary group IDs of the parent dir, the 
+	ISGID bit is cleared if the irix_sgid_inherit compatibility sysctl 
+	is set.
+
+  fs.xfs.restrict_chown		(Min: 0  Default: 1  Max: 1)
+  	Controls whether unprivileged users can use chown to "give away"
+	a file to another user.
+
+  vm.pagebuf.stats_clear	(Min: 0  Default: 0  Max: 1)
+	Setting this to "1" clears accumulated pagebuf statistics 
+	in /proc/fs/pagebuf/stat.  It then immediately reset to "0".
+  	
+  vm.pagebuf.flush_age		(Min: 1*HZ  Default: 15*HZ  Max: 300*HZ)
+	The age at which dirty metadata buffers are flushed to disk
+
+  vm.pagebuf.flush_int		(Min: HZ/2  Default: HZ  Max: 30*HZ)
+	The interval at which the list of dirty metadata buffers is
+	scanned.
diff -urN linux-2.5.74-bk7/Documentation/oops-tracing.txt linux-2.5.74-bk8/Documentation/oops-tracing.txt
--- linux-2.5.74-bk7/Documentation/oops-tracing.txt	2003-07-02 13:43:28.000000000 -0700
+++ linux-2.5.74-bk8/Documentation/oops-tracing.txt	2003-07-10 04:38:35.000000000 -0700
@@ -52,7 +52,7 @@
 Full Information
 ----------------
 
-From: Linus Torvalds <torvalds@transmeta.com>
+From: Linus Torvalds <torvalds@osdl.org>
 
 How to track down an Oops.. [originally a mail to linux-kernel]
 
diff -urN linux-2.5.74-bk7/Documentation/usb/CREDITS linux-2.5.74-bk8/Documentation/usb/CREDITS
--- linux-2.5.74-bk7/Documentation/usb/CREDITS	2003-07-02 13:46:45.000000000 -0700
+++ linux-2.5.74-bk8/Documentation/usb/CREDITS	2003-07-10 04:38:35.000000000 -0700
@@ -21,7 +21,7 @@
   Bill Ryder <bryder@sgi.com>
   Thomas Sailer <sailer@ife.ee.ethz.ch>
   Gregory P. Smith <greg@electricrain.com>
-  Linus Torvalds <torvalds@transmeta.com>
+  Linus Torvalds <torvalds@osdl.org>
   Roman Weissgaerber <weissg@vienna.at>
   <Kazuki.Yasumatsu@fujixerox.co.jp>
 
diff -urN linux-2.5.74-bk7/Makefile linux-2.5.74-bk8/Makefile
--- linux-2.5.74-bk7/Makefile	2003-07-10 04:38:31.000000000 -0700
+++ linux-2.5.74-bk8/Makefile	2003-07-10 04:38:35.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 74
-EXTRAVERSION = -bk7
+EXTRAVERSION = -bk8
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
diff -urN linux-2.5.74-bk7/README linux-2.5.74-bk8/README
--- linux-2.5.74-bk7/README	2003-07-02 13:54:44.000000000 -0700
+++ linux-2.5.74-bk8/README	2003-07-10 04:38:35.000000000 -0700
@@ -225,10 +225,8 @@
    the file MAINTAINERS to see if there is a particular person associated
    with the part of the kernel that you are having trouble with. If there
    isn't anyone listed there, then the second best thing is to mail
-   them to me (torvalds@transmeta.com), and possibly to any other
-   relevant mailing-list or to the newsgroup.  The mailing-lists are
-   useful especially for SCSI and networking problems, as I can't test
-   either of those personally anyway. 
+   them to me (torvalds@osdl.org), and possibly to any other relevant
+   mailing-list or to the newsgroup.
 
  - In all bug-reports, *please* tell what kernel you are talking about,
    how to duplicate the problem, and what your setup is (use your common
diff -urN linux-2.5.74-bk7/drivers/acpi/sleep/main.c linux-2.5.74-bk8/drivers/acpi/sleep/main.c
--- linux-2.5.74-bk7/drivers/acpi/sleep/main.c	2003-07-02 13:40:06.000000000 -0700
+++ linux-2.5.74-bk8/drivers/acpi/sleep/main.c	2003-07-10 04:38:35.000000000 -0700
@@ -238,7 +238,7 @@
 	/* do we have a wakeup address for S2 and S3? */
 	/* Here, we support only S4BIOS, those we set the wakeup address */
 	/* S4OS is only supported for now via swsusp.. */
-	if (state == ACPI_STATE_S2 || state == ACPI_STATE_S3 || ACPI_STATE_S4) {
+	if (state == ACPI_STATE_S2 || state == ACPI_STATE_S3 || state == ACPI_STATE_S4) {
 		if (!acpi_wakeup_address)
 			return AE_ERROR;
 		acpi_set_firmware_waking_vector((acpi_physical_address) acpi_wakeup_address);
diff -urN linux-2.5.74-bk7/drivers/char/agp/amd-k8-agp.c linux-2.5.74-bk8/drivers/char/agp/amd-k8-agp.c
--- linux-2.5.74-bk7/drivers/char/agp/amd-k8-agp.c	2003-07-02 13:50:52.000000000 -0700
+++ linux-2.5.74-bk8/drivers/char/agp/amd-k8-agp.c	2003-07-10 04:38:35.000000000 -0700
@@ -342,6 +342,14 @@
 	.subvendor	= PCI_ANY_ID,
 	.subdevice	= PCI_ANY_ID,
 	},
+	{
+	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+	.class_mask	= ~0,
+	.vendor		= PCI_VENDOR_ID_SI,
+	.device		= PCI_DEVICE_ID_SI_755,
+	.subvendor	= PCI_ANY_ID,
+	.subdevice	= PCI_ANY_ID,
+	},
 	{ }
 };
 
diff -urN linux-2.5.74-bk7/drivers/char/agp/via-agp.c linux-2.5.74-bk8/drivers/char/agp/via-agp.c
--- linux-2.5.74-bk7/drivers/char/agp/via-agp.c	2003-07-02 13:54:22.000000000 -0700
+++ linux-2.5.74-bk8/drivers/char/agp/via-agp.c	2003-07-10 04:38:35.000000000 -0700
@@ -345,13 +345,29 @@
 	{ }, /* dummy final entry, always present */
 };
 
+
+/*
+ * VIA's AGP3 chipsets do magick to put the AGP bridge compliant
+ * with the same standards version as the graphics card.
+ */
+static void check_via_agp3 (struct agp_bridge_data *bridge)
+{
+	u8 reg;
+
+	pci_read_config_byte(bridge->dev, VIA_AGPSEL, &reg);
+	/* Check AGP 2.0 compatibility mode. */
+	if ((reg & (1<<1))==0)
+		bridge->driver = &via_agp3_driver;
+}
+
+
 static int __init agp_via_probe(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
 	struct agp_device_ids *devs = via_agp_device_ids;
 	struct agp_bridge_data *bridge;
 	int j = 0;
-	u8 cap_ptr, reg;
+	u8 cap_ptr;
 
 	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
 	if (!cap_ptr)
@@ -386,36 +402,21 @@
 	bridge->capndx = cap_ptr;
 	bridge->driver = &via_driver;
 
-	switch (pdev->device) {
-	case PCI_DEVICE_ID_VIA_8367_0:
-		/*
-		 * Garg, there are KT400s with KT266 IDs.
-		 */
+	/*
+	 * Garg, there are KT400s with KT266 IDs.
+	 */
+	if (pdev->device == PCI_DEVICE_ID_VIA_8367_0) {
 		/* Is there a KT400 subsystem ? */
-		if (pdev->subsystem_device != PCI_DEVICE_ID_VIA_8377_0)
-			break;
-		
-		printk(KERN_INFO PFX "Found KT400 in disguise as a KT266.\n");
-		/*FALLTHROUGH*/
-	case PCI_DEVICE_ID_VIA_8377_0:
-		/*
-		 * The KT400 does magick to put the AGP bridge compliant
-		 * with the same standards version as the graphics card.
-		 */
-		pci_read_config_byte(pdev, VIA_AGPSEL, &reg);
-		/* Check AGP 2.0 compatibility mode. */
-		if ((reg & (1<<1))==0) {
-			bridge->driver = &via_agp3_driver;
-			break;
+		if (pdev->subsystem_device == PCI_DEVICE_ID_VIA_8377_0) {
+			printk(KERN_INFO PFX "Found KT400 in disguise as a KT266.\n");
+			check_via_agp3(bridge);
 		}
-		/*FALLTHROUGH*/
-	default:
-		break;
 	}
 
-
-	bridge->dev = pdev;
-	bridge->capndx = cap_ptr;
+	/* If this is an AGP3 bridge, check which mode its in and adjust. */
+	get_agp_version(bridge);
+	if (bridge->major_version >= 3)
+		check_via_agp3(bridge);
 
 	/* Fill in the mode register */
 	pci_read_config_dword(pdev,
diff -urN linux-2.5.74-bk7/drivers/cpufreq/Makefile linux-2.5.74-bk8/drivers/cpufreq/Makefile
--- linux-2.5.74-bk7/drivers/cpufreq/Makefile	2003-07-02 13:58:20.000000000 -0700
+++ linux-2.5.74-bk8/drivers/cpufreq/Makefile	2003-07-10 04:38:35.000000000 -0700
@@ -1,4 +1,7 @@
-#CPUfreq governors and cross-arch helpers
+# CPUfreq governors 
+obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE)	+= userspace.o
+
+# CPUfreq cross-arch helpers
 obj-$(CONFIG_CPU_FREQ_TABLE)		+= freq_table.o
 obj-$(CONFIG_CPU_FREQ_PROC_INTF)	+= proc_intf.o
-obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE)	+= userspace.o
+
diff -urN linux-2.5.74-bk7/drivers/cpufreq/proc_intf.c linux-2.5.74-bk8/drivers/cpufreq/proc_intf.c
--- linux-2.5.74-bk7/drivers/cpufreq/proc_intf.c	2003-07-02 13:41:55.000000000 -0700
+++ linux-2.5.74-bk8/drivers/cpufreq/proc_intf.c	2003-07-10 04:38:35.000000000 -0700
@@ -13,6 +13,8 @@
 #include <asm/uaccess.h>
 
 
+#define CPUFREQ_ALL_CPUS		((NR_CPUS))
+
 /**
  * cpufreq_parse_policy - parse a policy string
  * @input_string: the string to parse.
diff -urN linux-2.5.74-bk7/drivers/ide/ide-probe.c linux-2.5.74-bk8/drivers/ide/ide-probe.c
--- linux-2.5.74-bk7/drivers/ide/ide-probe.c	2003-07-02 13:49:20.000000000 -0700
+++ linux-2.5.74-bk8/drivers/ide/ide-probe.c	2003-07-10 04:38:35.000000000 -0700
@@ -385,11 +385,21 @@
 	int autoprobe = 0;
 	unsigned long cookie = 0;
 
-	if (IDE_CONTROL_REG && !hwif->irq) {
-		autoprobe = 1;
-		cookie = probe_irq_on();
-		/* enable device irq */
-		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
+	/*
+	 * Disable device irq unless we need to
+	 * probe for it. Otherwise we'll get spurious
+	 * interrupts during the identify-phase that
+	 * the irq handler isn't expecting.
+	 */
+	if (IDE_CONTROL_REG) {
+		u8 ctl = drive->ctl | 2;
+		if (!hwif->irq) {
+			autoprobe = 1;
+			cookie = probe_irq_on();
+			/* enable device irq */
+			ctl &= ~2;
+		}
+		hwif->OUTB(ctl, IDE_CONTROL_REG);
 	}
 
 	retval = actual_try_to_identify(drive, cmd);
diff -urN linux-2.5.74-bk7/drivers/net/8139too.c linux-2.5.74-bk8/drivers/net/8139too.c
--- linux-2.5.74-bk7/drivers/net/8139too.c	2003-07-02 13:38:41.000000000 -0700
+++ linux-2.5.74-bk8/drivers/net/8139too.c	2003-07-10 04:38:35.000000000 -0700
@@ -2070,7 +2070,7 @@
 		RTL_W16 (IntrStatus, ackstat);
 
 		DPRINTK ("%s: interrupt  status=%#4.4x ackstat=%#4.4x new intstat=%#4.4x.\n",
-			 dev->name, ackstat, status, RTL_R16 (IntrStatus));
+			 dev->name, status, ackstat, RTL_R16 (IntrStatus));
 
 		if (netif_running (dev) && (status & RxAckBits))
 			rtl8139_rx_interrupt (dev, tp, ioaddr);
diff -urN linux-2.5.74-bk7/drivers/net/e1000/e1000.h linux-2.5.74-bk8/drivers/net/e1000/e1000.h
--- linux-2.5.74-bk7/drivers/net/e1000/e1000.h	2003-07-02 13:40:08.000000000 -0700
+++ linux-2.5.74-bk8/drivers/net/e1000/e1000.h	2003-07-10 04:38:35.000000000 -0700
@@ -224,6 +224,5 @@
 
 
 	uint32_t pci_state[16];
-	char ifname[IFNAMSIZ];
 };
 #endif /* _E1000_H_ */
diff -urN linux-2.5.74-bk7/drivers/net/e1000/e1000_ethtool.c linux-2.5.74-bk8/drivers/net/e1000/e1000_ethtool.c
--- linux-2.5.74-bk7/drivers/net/e1000/e1000_ethtool.c	2003-07-02 13:46:57.000000000 -0700
+++ linux-2.5.74-bk8/drivers/net/e1000/e1000_ethtool.c	2003-07-10 04:38:35.000000000 -0700
@@ -1112,8 +1112,9 @@
 
 		if(if_running)
 			e1000_down(adapter);
-
-		e1000_reset(adapter);
+		else
+			e1000_reset(adapter);
+		
 		if(e1000_reg_test(adapter, &data[0]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
diff -urN linux-2.5.74-bk7/drivers/net/e1000/e1000_hw.c linux-2.5.74-bk8/drivers/net/e1000/e1000_hw.c
--- linux-2.5.74-bk7/drivers/net/e1000/e1000_hw.c	2003-07-02 13:57:15.000000000 -0700
+++ linux-2.5.74-bk8/drivers/net/e1000/e1000_hw.c	2003-07-10 04:38:35.000000000 -0700
@@ -135,6 +135,41 @@
 
         e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x0000);
         e1000_write_phy_reg(hw,0x0000,0x3300);
+
+
+        if(hw->mac_type == e1000_82547) {
+            uint16_t fused, fine, coarse;
+
+            /* Move to analog registers page */
+            e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 
+                                IGP01E1000_ANALOG_REGS_PAGE);
+
+            e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused);
+
+            if(!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
+                e1000_read_phy_reg(hw, IGP01E1000_ANALOG_FUSE_STATUS, &fused);
+
+                fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
+                coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
+
+                if(coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
+                    coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10;
+                    fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
+                } else if(coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
+                    fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
+
+                fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | 
+                        (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | 
+                        (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK);
+
+                e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_CONTROL, fused);
+                e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS, 
+                                    IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
+            }
+            /* Return to first page of registers */
+            e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+                                IGP01E1000_IEEE_REGS_PAGE);
+        }
     }
 }
 
@@ -259,10 +294,20 @@
 	msec_delay(5);
     }
 
-    if(hw->mac_type > e1000_82543)
-        E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST));
-    else
-        E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
+    switch(hw->mac_type) {
+        case e1000_82544:
+        case e1000_82540:
+        case e1000_82545:
+        case e1000_82546:
+        case e1000_82541:
+            /* These controllers can't ack the 64-bit write when issuing the
+             * reset, so use IO-mapping as a workaround to issue the reset */
+            E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST));
+            break;
+        default:
+            E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
+            break;
+    }
 
     /* Force a reload from the EEPROM if necessary */
     if(hw->mac_type < e1000_82540) {
@@ -687,7 +732,8 @@
 static int32_t
 e1000_setup_copper_link(struct e1000_hw *hw)
 {
-    uint32_t ctrl, led_ctrl;
+    uint32_t ctrl;
+    uint32_t led_ctrl;
     int32_t ret_val;
     uint16_t i;
     uint16_t phy_data;
@@ -2249,7 +2295,8 @@
 void
 e1000_phy_hw_reset(struct e1000_hw *hw)
 {
-    uint32_t ctrl, ctrl_ext, led_ctrl;
+    uint32_t ctrl, ctrl_ext;
+    uint32_t led_ctrl;
 
     DEBUGFUNC("e1000_phy_hw_reset");
 
diff -urN linux-2.5.74-bk7/drivers/net/e1000/e1000_hw.h linux-2.5.74-bk8/drivers/net/e1000/e1000_hw.h
--- linux-2.5.74-bk7/drivers/net/e1000/e1000_hw.h	2003-07-02 13:54:36.000000000 -0700
+++ linux-2.5.74-bk8/drivers/net/e1000/e1000_hw.h	2003-07-10 04:38:35.000000000 -0700
@@ -1668,6 +1668,7 @@
 #define M88E1000_EXT_PHY_SPEC_CTRL 0x14  /* Extended PHY Specific Control */
 #define M88E1000_RX_ERR_CNTR       0x15  /* Receive Error Counter */
 
+#define IGP01E1000_IEEE_REGS_PAGE  0x0000
 /* IGP01E1000 Specific Registers */
 #define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */
 #define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */
@@ -1690,6 +1691,7 @@
  * speed = 1000 Mbps. */
 #define IGP01E1000_PHY_PCS_INIT_REG  0x00B4
 
+#define IGP01E1000_ANALOG_REGS_PAGE  0x20C0
 
 #define MAX_PHY_REG_ADDRESS 0x1F        /* 5 bit address bus (0-0x1F) */
 
@@ -1980,6 +1982,22 @@
 #define IGP01E1000_GMII_FLEX_SPD               0x10 /* Enable flexible speed
                                                      * on Link-Up */
 #define IGP01E1000_GMII_SPD                    0x20 /* Enable SPD */
+/* IGP01E1000 Analog Register */
+#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS         0x0011
+#define IGP01E1000_ANALOG_FUSE_STATUS               0x0010
+#define IGP01E1000_ANALOG_FUSE_CONTROL              0x001C
+#define IGP01E1000_ANALOG_FUSE_BYPASS               0x001E
+
+#define IGP01E1000_ANALOG_FUSE_POLY_MASK            0xF000
+#define IGP01E1000_ANALOG_FUSE_FINE_MASK            0x0F80
+#define IGP01E1000_ANALOG_FUSE_COARSE_MASK          0x0070
+#define IGP01E1000_ANALOG_SPARE_FUSE_ENABLED        0x0100
+#define IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL    0x0002
+
+#define IGP01E1000_ANALOG_FUSE_COARSE_THRESH        0x0040
+#define IGP01E1000_ANALOG_FUSE_COARSE_10            0x0010
+#define IGP01E1000_ANALOG_FUSE_FINE_1               0x0080
+#define IGP01E1000_ANALOG_FUSE_FINE_10              0x0500
 
 /* Bit definitions for valid PHY IDs. */
 #define M88E1000_E_PHY_ID  0x01410C50
diff -urN linux-2.5.74-bk7/drivers/net/e1000/e1000_main.c linux-2.5.74-bk8/drivers/net/e1000/e1000_main.c
--- linux-2.5.74-bk7/drivers/net/e1000/e1000_main.c	2003-07-02 13:45:56.000000000 -0700
+++ linux-2.5.74-bk8/drivers/net/e1000/e1000_main.c	2003-07-10 04:38:35.000000000 -0700
@@ -30,6 +30,14 @@
 
 /* Change Log
  *
+ * 5.1.13	5/28/03
+ *   o Bug fix: request_irq() failure resulted in freeing resources twice!
+ *     [Don Fry (brazilnut@us.ibm.com)]
+ *   o Bug fix: fix VLAN support on ppc64 [Mark Rakes (mrakes@vivato.net)]
+ *   o Bug fix: missing Tx cleanup opportunities during interrupt handling.
+ *   o Bug fix: alloc_etherdev failure didn't cleanup regions in probe.
+ *   o Cleanup: s/int/unsigned int/ for descriptor ring indexes.
+ *   
  * 5.1.11	5/6/03
  *   o Feature: Added support for 82546EB (Quad-port) hardware.
  *   o Feature: Added support for Diagnostics through Ethtool.
@@ -38,26 +46,11 @@
  *   o Bug fix: TSO bug fixes.
  *
  * 5.0.42	3/5/03
- *   o Feature: Added support for 82541 and 82547 hardware.
- *   o Feature: Added support for Intel Gigabit PHY (IGP) and a variety of
- *   eeproms.
- *   o Feature: Added support for TCP Segmentation Offload (TSO).
- *   o Feature: Added MII ioctl.
- *   o Feature: Added support for statistics reporting through ethtool.
- *   o Cleanup: Removed proprietary hooks for ANS.
- *   o Cleanup: Miscellaneous code changes to improve CPU utilization.
- *   	- Replaced "%" with conditionals and "+-" operators.
- *   	- Implemented dynamic Interrupt Throttle Rate (ITR).
- *   	- Reduced expensive PCI reads of ICR in interrupt.
- *   o Bug fix: Request IRQ after descriptor ring setup to avoid panic in
- *   shared interrupt instances.
- *
- * 4.4.18       11/27/02
  */
 
 char e1000_driver_name[] = "e1000";
 char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-char e1000_driver_version[] = "5.1.11-k1";
+char e1000_driver_version[] = "5.1.13-k1";
 char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation.";
 
 /* e1000_pci_tbl - PCI Device ID Table
@@ -128,6 +121,7 @@
 static inline void e1000_irq_disable(struct e1000_adapter *adapter);
 static inline void e1000_irq_enable(struct e1000_adapter *adapter);
 static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs);
+static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter);
 #ifdef CONFIG_E1000_NAPI
 static int e1000_clean(struct net_device *netdev, int *budget);
 static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
@@ -135,7 +129,6 @@
 #else
 static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter);
 #endif
-static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter);
 static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
 static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
 static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
@@ -248,12 +241,8 @@
 	e1000_alloc_rx_buffers(adapter);
 
 	if(request_irq(netdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM,
-		       netdev->name, netdev)) {
-		e1000_reset_hw(&adapter->hw);
-		e1000_free_tx_resources(adapter);
-		e1000_free_rx_resources(adapter);
+		       netdev->name, netdev))
 		return -1;
-	}
 
 	mod_timer(&adapter->watchdog_timer, jiffies);
 	e1000_irq_enable(adapter);
@@ -504,9 +493,9 @@
 err_eeprom:
 	iounmap(adapter->hw.hw_addr);
 err_ioremap:
-	pci_release_regions(pdev);
 	kfree(netdev);
 err_alloc_etherdev:
+	pci_release_regions(pdev);
 	return -ENOMEM;
 }
 
@@ -981,35 +970,38 @@
 static void
 e1000_clean_tx_ring(struct e1000_adapter *adapter)
 {
+	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
+	struct e1000_buffer *buffer_info;
 	struct pci_dev *pdev = adapter->pdev;
 	unsigned long size;
-	int i;
+	unsigned int i;
 
 	/* Free all the Tx ring sk_buffs */
 
-	for(i = 0; i < adapter->tx_ring.count; i++) {
-		if(adapter->tx_ring.buffer_info[i].skb) {
+	for(i = 0; i < tx_ring->count; i++) {
+		buffer_info = &tx_ring->buffer_info[i];
+		if(buffer_info->skb) {
 
 			pci_unmap_page(pdev,
-			               adapter->tx_ring.buffer_info[i].dma,
-			               adapter->tx_ring.buffer_info[i].length,
+			               buffer_info->dma,
+			               buffer_info->length,
 			               PCI_DMA_TODEVICE);
 
-			dev_kfree_skb(adapter->tx_ring.buffer_info[i].skb);
+			dev_kfree_skb(buffer_info->skb);
 
-			adapter->tx_ring.buffer_info[i].skb = NULL;
+			buffer_info->skb = NULL;
 		}
 	}
 
-	size = sizeof(struct e1000_buffer) * adapter->tx_ring.count;
-	memset(adapter->tx_ring.buffer_info, 0, size);
+	size = sizeof(struct e1000_buffer) * tx_ring->count;
+	memset(tx_ring->buffer_info, 0, size);
 
 	/* Zero out the descriptor ring */
 
-	memset(adapter->tx_ring.desc, 0, adapter->tx_ring.size);
+	memset(tx_ring->desc, 0, tx_ring->size);
 
-	adapter->tx_ring.next_to_use = 0;
-	adapter->tx_ring.next_to_clean = 0;
+	tx_ring->next_to_use = 0;
+	tx_ring->next_to_clean = 0;
 
 	E1000_WRITE_REG(&adapter->hw, TDH, 0);
 	E1000_WRITE_REG(&adapter->hw, TDT, 0);
@@ -1025,17 +1017,17 @@
 static void
 e1000_free_rx_resources(struct e1000_adapter *adapter)
 {
+	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
 	struct pci_dev *pdev = adapter->pdev;
 
 	e1000_clean_rx_ring(adapter);
 
-	kfree(adapter->rx_ring.buffer_info);
-	adapter->rx_ring.buffer_info = NULL;
+	kfree(rx_ring->buffer_info);
+	rx_ring->buffer_info = NULL;
 
-	pci_free_consistent(pdev, adapter->rx_ring.size,
-	                    adapter->rx_ring.desc, adapter->rx_ring.dma);
+	pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
 
-	adapter->rx_ring.desc = NULL;
+	rx_ring->desc = NULL;
 }
 
 /**
@@ -1046,35 +1038,38 @@
 static void
 e1000_clean_rx_ring(struct e1000_adapter *adapter)
 {
+	struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
+	struct e1000_buffer *buffer_info;
 	struct pci_dev *pdev = adapter->pdev;
 	unsigned long size;
-	int i;
+	unsigned int i;
 
 	/* Free all the Rx ring sk_buffs */
 
-	for(i = 0; i < adapter->rx_ring.count; i++) {
-		if(adapter->rx_ring.buffer_info[i].skb) {
+	for(i = 0; i < rx_ring->count; i++) {
+		buffer_info = &rx_ring->buffer_info[i];
+		if(buffer_info->skb) {
 
 			pci_unmap_single(pdev,
-			                 adapter->rx_ring.buffer_info[i].dma,
-			                 adapter->rx_ring.buffer_info[i].length,
+			                 buffer_info->dma,
+			                 buffer_info->length,
 			                 PCI_DMA_FROMDEVICE);
 
-			dev_kfree_skb(adapter->rx_ring.buffer_info[i].skb);
+			dev_kfree_skb(buffer_info->skb);
 
-			adapter->rx_ring.buffer_info[i].skb = NULL;
+			buffer_info->skb = NULL;
 		}
 	}
 
-	size = sizeof(struct e1000_buffer) * adapter->rx_ring.count;
-	memset(adapter->rx_ring.buffer_info, 0, size);
+	size = sizeof(struct e1000_buffer) * rx_ring->count;
+	memset(rx_ring->buffer_info, 0, size);
 
 	/* Zero out the descriptor ring */
 
-	memset(adapter->rx_ring.desc, 0, adapter->rx_ring.size);
+	memset(rx_ring->desc, 0, rx_ring->size);
 
-	adapter->rx_ring.next_to_clean = 0;
-	adapter->rx_ring.next_to_use = 0;
+	rx_ring->next_to_clean = 0;
+	rx_ring->next_to_use = 0;
 
 	E1000_WRITE_REG(&adapter->hw, RDH, 0);
 	E1000_WRITE_REG(&adapter->hw, RDT, 0);
@@ -1324,7 +1319,7 @@
 	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
 	struct net_device *netdev = adapter->netdev;
 	struct e1000_desc_ring *txdr = &adapter->tx_ring;
-	int i;
+	unsigned int i;
 
 	e1000_check_for_link(&adapter->hw);
 
@@ -1410,7 +1405,7 @@
 {
 #ifdef NETIF_F_TSO
 	struct e1000_context_desc *context_desc;
-	int i;
+	unsigned int i;
 	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
 	uint16_t ipcse, tucse, mss;
 
@@ -1461,7 +1456,7 @@
 e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
 {
 	struct e1000_context_desc *context_desc;
-	int i;
+	unsigned int i;
 	uint8_t css, cso;
 
 	if(skb->ip_summed == CHECKSUM_HW) {
@@ -1494,18 +1489,21 @@
 	unsigned int first)
 {
 	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
-	int len = skb->len, offset = 0, size, count = 0, i;
+	struct e1000_buffer *buffer_info;
+	int len = skb->len;
+	unsigned int offset = 0, size, count = 0, i;
 
 #ifdef NETIF_F_TSO
-	int tso = skb_shinfo(skb)->tso_size;
+	unsigned int tso = skb_shinfo(skb)->tso_size;
 #endif
-	int nr_frags = skb_shinfo(skb)->nr_frags;
-	int f;
+	unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
+	unsigned int f;
 	len -= skb->data_len;
 
 	i = tx_ring->next_to_use;
 
 	while(len) {
+		buffer_info = &tx_ring->buffer_info[i];
 		size = min(len, E1000_MAX_DATA_PER_TXD);
 #ifdef NETIF_F_TSO
 		/* Workaround for premature desc write-backs
@@ -1513,13 +1511,13 @@
 		if(tso && !nr_frags && size == len && size > 4)
 			size -= 4;
 #endif
-		tx_ring->buffer_info[i].length = size;
-		tx_ring->buffer_info[i].dma =
+		buffer_info->length = size;
+		buffer_info->dma =
 			pci_map_single(adapter->pdev,
 				skb->data + offset,
 				size,
 				PCI_DMA_TODEVICE);
-		tx_ring->buffer_info[i].time_stamp = jiffies;
+		buffer_info->time_stamp = jiffies;
 
 		len -= size;
 		offset += size;
@@ -1535,6 +1533,7 @@
 		offset = 0;
 
 		while(len) {
+			buffer_info = &tx_ring->buffer_info[i];
 			size = min(len, E1000_MAX_DATA_PER_TXD);
 #ifdef NETIF_F_TSO
 			/* Workaround for premature desc write-backs
@@ -1542,14 +1541,14 @@
 			if(tso && f == (nr_frags-1) && size == len && size > 4)
 				size -= 4;
 #endif
-			tx_ring->buffer_info[i].length = size;
-			tx_ring->buffer_info[i].dma =
+			buffer_info->length = size;
+			buffer_info->dma =
 				pci_map_page(adapter->pdev,
 					frag->page,
 					frag->page_offset + offset,
 					size,
 					PCI_DMA_TODEVICE);
-			tx_ring->buffer_info[i].time_stamp = jiffies;
+			buffer_info->time_stamp = jiffies;
 
 			len -= size;
 			offset += size;
@@ -1557,7 +1556,7 @@
 			if(++i == tx_ring->count) i = 0;
 		}
 	}
-	if(--i < 0) i = tx_ring->count - 1;
+	i = (i == 0) ? tx_ring->count - 1 : i - 1;
 	tx_ring->buffer_info[i].skb = skb;
 	tx_ring->buffer_info[first].next_to_watch = i;
 
@@ -1569,8 +1568,9 @@
 {
 	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
 	struct e1000_tx_desc *tx_desc = NULL;
+	struct e1000_buffer *buffer_info;
 	uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
-	int i;
+	unsigned int i;
 
 	if(tx_flags & E1000_TX_FLAGS_TSO) {
 		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
@@ -1591,10 +1591,11 @@
 	i = tx_ring->next_to_use;
 
 	while(count--) {
+		buffer_info = &tx_ring->buffer_info[i];
 		tx_desc = E1000_TX_DESC(*tx_ring, i);
-		tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma);
+		tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
 		tx_desc->lower.data =
-			cpu_to_le32(txd_lower | tx_ring->buffer_info[i].length);
+			cpu_to_le32(txd_lower | buffer_info->length);
 		tx_desc->upper.data = cpu_to_le32(txd_upper);
 		if(++i == tx_ring->count) i = 0;
 	}
@@ -1660,7 +1661,7 @@
 {
 	struct e1000_adapter *adapter = netdev->priv;
 	unsigned int first;
-	int tx_flags = 0;
+	unsigned int tx_flags = 0;
 
 	if(skb->len <= 0) {
 		dev_kfree_skb_any(skb);
@@ -1972,7 +1973,7 @@
 	struct e1000_adapter *adapter = netdev->priv;
 	uint32_t icr = E1000_READ_REG(&adapter->hw, ICR);
 #ifndef CONFIG_E1000_NAPI
-	int i;
+	unsigned int i;
 #endif
 
 	if(!icr)
@@ -1996,7 +1997,7 @@
 	}
 #else
 	for(i = 0; i < E1000_MAX_INTR; i++)
-		if(!e1000_clean_rx_irq(adapter) &&
+		if(!e1000_clean_rx_irq(adapter) &
 		   !e1000_clean_tx_irq(adapter))
 			break;
 #endif
@@ -2044,7 +2045,8 @@
 	struct pci_dev *pdev = adapter->pdev;
 	struct e1000_tx_desc *tx_desc, *eop_desc;
 	struct e1000_buffer *buffer_info;
-	int i, eop, cleaned = FALSE;
+	unsigned int i, eop;
+	boolean_t cleaned = FALSE;
 
 	i = tx_ring->next_to_clean;
 	eop = tx_ring->buffer_info[i].next_to_watch;
@@ -2110,16 +2112,19 @@
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
 	struct e1000_rx_desc *rx_desc;
+	struct e1000_buffer *buffer_info;
 	struct sk_buff *skb;
 	unsigned long flags;
 	uint32_t length;
 	uint8_t last_byte;
-	int i, cleaned = FALSE;
+	unsigned int i;
+	boolean_t cleaned = FALSE;
 
 	i = rx_ring->next_to_clean;
 	rx_desc = E1000_RX_DESC(*rx_ring, i);
 
 	while(rx_desc->status & E1000_RXD_STAT_DD) {
+		buffer_info = &rx_ring->buffer_info[i];
 
 #ifdef CONFIG_E1000_NAPI
 		if(*work_done >= work_to_do)
@@ -2131,11 +2136,11 @@
 		cleaned = TRUE;
 
 		pci_unmap_single(pdev,
-		                 rx_ring->buffer_info[i].dma,
-		                 rx_ring->buffer_info[i].length,
+		                 buffer_info->dma,
+		                 buffer_info->length,
 		                 PCI_DMA_FROMDEVICE);
 
-		skb = rx_ring->buffer_info[i].skb;
+		skb = buffer_info->skb;
 		length = le16_to_cpu(rx_desc->length);
 
 		if(!(rx_desc->status & E1000_RXD_STAT_EOP)) {
@@ -2146,7 +2151,7 @@
 
 			dev_kfree_skb_irq(skb);
 			rx_desc->status = 0;
-			rx_ring->buffer_info[i].skb = NULL;
+			buffer_info->skb = NULL;
 
 			if(++i == rx_ring->count) i = 0;
 
@@ -2174,7 +2179,7 @@
 
 				dev_kfree_skb_irq(skb);
 				rx_desc->status = 0;
-				rx_ring->buffer_info[i].skb = NULL;
+				buffer_info->skb = NULL;
 
 				if(++i == rx_ring->count) i = 0;
 
@@ -2193,14 +2198,16 @@
 #ifdef CONFIG_E1000_NAPI
 		if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {
 			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
-				(rx_desc->special & E1000_RXD_SPC_VLAN_MASK));
+				le16_to_cpu(rx_desc->special &
+					E1000_RXD_SPC_VLAN_MASK));
 		} else {
 			netif_receive_skb(skb);
 		}
 #else /* CONFIG_E1000_NAPI */
 		if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {
 			vlan_hwaccel_rx(skb, adapter->vlgrp,
-				(rx_desc->special & E1000_RXD_SPC_VLAN_MASK));
+				le16_to_cpu(rx_desc->special &
+					E1000_RXD_SPC_VLAN_MASK));
 		} else {
 			netif_rx(skb);
 		}
@@ -2208,7 +2215,7 @@
 		netdev->last_rx = jiffies;
 
 		rx_desc->status = 0;
-		rx_ring->buffer_info[i].skb = NULL;
+		buffer_info->skb = NULL;
 
 		if(++i == rx_ring->count) i = 0;
 
@@ -2234,13 +2241,15 @@
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
 	struct e1000_rx_desc *rx_desc;
+	struct e1000_buffer *buffer_info;
 	struct sk_buff *skb;
 	int reserve_len = 2;
-	int i;
+	unsigned int i;
 
 	i = rx_ring->next_to_use;
+	buffer_info = &rx_ring->buffer_info[i];
 
-	while(!rx_ring->buffer_info[i].skb) {
+	while(!buffer_info->skb) {
 		rx_desc = E1000_RX_DESC(*rx_ring, i);
 
 		skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len);
@@ -2258,15 +2267,15 @@
 
 		skb->dev = netdev;
 
-		rx_ring->buffer_info[i].skb = skb;
-		rx_ring->buffer_info[i].length = adapter->rx_buffer_len;
-		rx_ring->buffer_info[i].dma =
+		buffer_info->skb = skb;
+		buffer_info->length = adapter->rx_buffer_len;
+		buffer_info->dma =
 			pci_map_single(pdev,
 			               skb->data,
 			               adapter->rx_buffer_len,
 			               PCI_DMA_FROMDEVICE);
 
-		rx_desc->buffer_addr = cpu_to_le64(rx_ring->buffer_info[i].dma);
+		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
 
 		if((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i) {
 			/* Force memory writes to complete before letting h/w
@@ -2279,6 +2288,7 @@
 		}
 
 		if(++i == rx_ring->count) i = 0;
+		buffer_info = &rx_ring->buffer_info[i];
 	}
 
 	rx_ring->next_to_use = i;
diff -urN linux-2.5.74-bk7/drivers/net/via-rhine.c linux-2.5.74-bk8/drivers/net/via-rhine.c
--- linux-2.5.74-bk7/drivers/net/via-rhine.c	2003-07-02 13:57:17.000000000 -0700
+++ linux-2.5.74-bk8/drivers/net/via-rhine.c	2003-07-10 04:38:35.000000000 -0700
@@ -2,6 +2,8 @@
 /*
 	Written 1998-2001 by Donald Becker.
 
+	Current Maintainer: Roger Luethi <rl@hellgate.ch>
+
 	This software may be used and distributed according to the terms of
 	the GNU General Public License (GPL), incorporated herein by reference.
 	Drivers based on or derived from this code fall under the GPL and must
@@ -9,8 +11,9 @@
 	a complete program and may only be used when the entire operating
 	system is licensed under the GPL.
 
-	This driver is designed for the VIA VT86C100A Rhine-I. 
-	It also works with the 6102 Rhine-II, and 6105/6105M Rhine-III.   
+	This driver is designed for the VIA VT86C100A Rhine-I.
+	It also works with the Rhine-II (6102) and Rhine-III (6105/6105L/6105LOM
+	and management NIC 6105M).
 
 	The author may be reached as becker@scyld.com, or C/O
 	Scyld Computing Corporation
@@ -115,11 +118,15 @@
 	- Force flushing for PCI posted writes
 	- More reset code changes
 
+	LK1.1.18 (Roger Luethi)
+	- No filtering multicast in promisc mode (Edward Peng)
+	- Fix for Rhine-I Tx timeouts
+
 */
 
 #define DRV_NAME	"via-rhine"
-#define DRV_VERSION	"1.1.17"
-#define DRV_RELDATE	"March-1-2003"
+#define DRV_VERSION	"1.1.18-2.5"
+#define DRV_RELDATE	"July-4-2003"
 
 
 /* A few user-configurable values.
@@ -386,17 +393,17 @@
 	{ "VIA VT6102 Rhine-II", RHINE_IOTYPE, 256,
 	  CanHaveMII | HasWOL },
 	{ "VIA VT6105 Rhine-III", RHINE_IOTYPE, 256,
-	  CanHaveMII | HasWOL },	  
+	  CanHaveMII | HasWOL },
 	{ "VIA VT6105M Rhine-III", RHINE_IOTYPE, 256,
-	  CanHaveMII | HasWOL },	  	  	 
+	  CanHaveMII | HasWOL },
 };
 
 static struct pci_device_id via_rhine_pci_tbl[] __devinitdata =
 {
 	{0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT86C100A},
 	{0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6102},
-	{0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6105},
-	{0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6105M},	
+	{0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6105}, /* 6105{,L,LOM} */
+	{0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6105M},
 	{0,}			/* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, via_rhine_pci_tbl);
@@ -441,7 +448,7 @@
 	IntrRxWakeUp=0x8000,
 	IntrNormalSummary=0x0003, IntrAbnormalSummary=0xC260,
 	IntrTxDescRace=0x080000,	/* mapped from IntrStatus2 */
-	IntrTxErrSummary=0x082210,
+	IntrTxErrSummary=0x082218,
 };
 
 /* The Rx and Tx buffer descriptors. */
@@ -1655,11 +1662,18 @@
 			printk(KERN_INFO "%s: Tx descriptor write-back race.\n",
 				   dev->name);
 	}
-	if (intr_status & ( IntrTxAborted | IntrTxUnderrun | IntrTxDescRace ))
+	if ((intr_status & IntrTxError) && ~( IntrTxAborted | IntrTxUnderrun |
+										   IntrTxDescRace )) {
+		if (debug > 2)
+			printk(KERN_INFO "%s: Unspecified error.\n",
+				   dev->name);
+	}
+	if (intr_status & ( IntrTxAborted | IntrTxUnderrun | IntrTxDescRace |
+						IntrTxError ))
 		via_rhine_restart_tx(dev);
 
 	if (intr_status & ~( IntrLinkChange | IntrStatsMax | IntrTxUnderrun |
- 						 IntrTxError | IntrTxAborted | IntrNormalSummary |
+						 IntrTxError | IntrTxAborted | IntrNormalSummary |
 						 IntrTxDescRace )) {
 		if (debug > 1)
 			printk(KERN_ERR "%s: Something Wicked happened! %8.8x.\n",
diff -urN linux-2.5.74-bk7/drivers/serial/core.c linux-2.5.74-bk8/drivers/serial/core.c
--- linux-2.5.74-bk7/drivers/serial/core.c	2003-07-02 13:43:33.000000000 -0700
+++ linux-2.5.74-bk8/drivers/serial/core.c	2003-07-10 04:38:35.000000000 -0700
@@ -1490,8 +1490,7 @@
 		return -ERESTARTSYS;
 
 	if (!info->tty || tty_hung_up_p(filp))
-		return (port->flags & UPF_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS;
+		return -EAGAIN;
 
 	return 0;
 }
@@ -1596,8 +1595,7 @@
 	 * If the port is in the middle of closing, bail out now.
 	 */
 	if (tty_hung_up_p(filp)) {
-		retval = (state->port->flags & UPF_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS;
+		retval = -EAGAIN;
 		state->count--;
 		up(&state->sem);
 		goto fail;
diff -urN linux-2.5.74-bk7/fs/xfs/linux/xfs_globals.c linux-2.5.74-bk8/fs/xfs/linux/xfs_globals.c
--- linux-2.5.74-bk7/fs/xfs/linux/xfs_globals.c	2003-07-02 13:50:05.000000000 -0700
+++ linux-2.5.74-bk8/fs/xfs/linux/xfs_globals.c	2003-07-10 04:38:35.000000000 -0700
@@ -38,6 +38,7 @@
 #include "xfs.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_bit.h"
+#include "xfs_rw.h"
 
 /*
  * System memory size - used to scale certain data structures in XFS.
@@ -48,7 +49,18 @@
  * Tunable XFS parameters.  xfs_params is required even when CONFIG_SYSCTL=n,
  * other XFS code uses these values.
  */
-xfs_param_t xfs_params = { 0, 1, 0, 0, 3, 30 * HZ, 0 };
+
+xfs_param_t xfs_params = {
+			/*	MIN	DFLT	MAX	*/
+	restrict_chown:	{	0,	1,	1	},
+	sgid_inherit:	{	0,	0,	1	},
+	symlink_mode:	{	0,	0,	1	},
+	panic_mask:	{	0,	0,	127	},
+	error_level:	{	0,	3,	11	},
+	sync_interval:	{	HZ,	30*HZ,	60*HZ	},
+	stats_clear:	{	0,	0,	1	},
+
+};
 
 /*
  * Global system credential structure.
diff -urN linux-2.5.74-bk7/fs/xfs/linux/xfs_linux.h linux-2.5.74-bk8/fs/xfs/linux/xfs_linux.h
--- linux-2.5.74-bk7/fs/xfs/linux/xfs_linux.h	2003-07-02 13:39:35.000000000 -0700
+++ linux-2.5.74-bk8/fs/xfs/linux/xfs_linux.h	2003-07-10 04:38:35.000000000 -0700
@@ -87,11 +87,15 @@
 	bh->b_end_io = linvfs_unwritten_done;
 }
 
-#define restricted_chown	xfs_params.restrict_chown
-#define irix_sgid_inherit	xfs_params.sgid_inherit
-#define irix_symlink_mode	xfs_params.symlink_mode
-#define xfs_panic_mask		xfs_params.panic_mask
-#define xfs_error_level		xfs_params.error_level
+#define xfs_refcache_size	xfs_params.refcache_size.val
+#define xfs_refcache_purge_count xfs_params.refcache_purge.val
+#define restricted_chown	xfs_params.restrict_chown.val
+#define irix_sgid_inherit	xfs_params.sgid_inherit.val
+#define irix_symlink_mode	xfs_params.symlink_mode.val
+#define xfs_panic_mask		xfs_params.panic_mask.val
+#define xfs_error_level		xfs_params.error_level.val
+#define xfs_syncd_interval	xfs_params.sync_interval.val
+#define xfs_stats_clear		xfs_params.stats_clear.val
 
 #define NBPP		PAGE_SIZE
 #define DPPSHFT		(PAGE_SHIFT - 9)
diff -urN linux-2.5.74-bk7/fs/xfs/linux/xfs_super.c linux-2.5.74-bk8/fs/xfs/linux/xfs_super.c
--- linux-2.5.74-bk7/fs/xfs/linux/xfs_super.c	2003-07-10 04:38:32.000000000 -0700
+++ linux-2.5.74-bk8/fs/xfs/linux/xfs_super.c	2003-07-10 04:38:35.000000000 -0700
@@ -71,6 +71,7 @@
 #include <linux/namei.h>
 #include <linux/init.h>
 #include <linux/mount.h>
+#include <linux/suspend.h>
 
 STATIC struct quotactl_ops linvfs_qops;
 STATIC struct super_operations linvfs_sops;
@@ -400,7 +401,10 @@
 
 	for (;;) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(xfs_params.sync_interval);
+		schedule_timeout(xfs_syncd_interval);
+		/* swsusp */
+		if (current->flags & PF_FREEZE)
+			refrigerator(PF_IOTHREAD);
 		if (vfsp->vfs_flag & VFS_UMOUNT)
 			break;
 		if (vfsp->vfs_flag & VFS_RDONLY)
diff -urN linux-2.5.74-bk7/fs/xfs/linux/xfs_syncd.c linux-2.5.74-bk8/fs/xfs/linux/xfs_syncd.c
--- linux-2.5.74-bk7/fs/xfs/linux/xfs_syncd.c	2003-07-02 13:54:28.000000000 -0700
+++ linux-2.5.74-bk8/fs/xfs/linux/xfs_syncd.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-
-#include <xfs.h>
-
-#define SYNCD_FLAGS	(SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR)
-
-int syncd(void *arg)
-{
-	vfs_t			*vfsp = (vfs_t *) arg;
-	int			error;
-
-	daemonize("xfs_syncd");
-
-	vfsp->vfs_sync_task = current;
-	wmb();
-	wake_up(&vfsp->vfs_wait_sync_task);
-
-	for (;;) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(xfs_params.sync_interval);
-		if (vfsp->vfs_flag & VFS_UMOUNT)
-			break;
-		if (vfsp->vfs_flag & VFS_RDONLY);
-			continue;
-		VFS_SYNC(vfsp, SYNCD_FLAGS, NULL, error);
-	}
-
-	vfsp->vfs_sync_task = NULL;
-	wmb();
-	wake_up(&vfsp->vfs_wait_sync_task);
-
-	return 0;
-}
-
-int
-linvfs_start_syncd(vfs_t *vfsp)
-{
-	int pid;
-
-	pid = kernel_thread(syncd, (void *) vfsp,
-			CLONE_VM | CLONE_FS | CLONE_FILES);
-	if (pid < 0)
-		return pid;
-	wait_event(vfsp->vfs_wait_sync_task, vfsp->vfs_sync_task);
-	return 0;
-}
-
-void
-linvfs_stop_syncd(vfs_t *vfsp)
-{
-	vfsp->vfs_flag |= VFS_UMOUNT;
-	wmb();
-
-	wake_up_process(vfsp->vfs_sync_task);
-	wait_event(vfsp->vfs_wait_sync_task, !vfsp->vfs_sync_task);
-}
diff -urN linux-2.5.74-bk7/fs/xfs/linux/xfs_sysctl.c linux-2.5.74-bk8/fs/xfs/linux/xfs_sysctl.c
--- linux-2.5.74-bk7/fs/xfs/linux/xfs_sysctl.c	2003-07-02 13:58:28.000000000 -0700
+++ linux-2.5.74-bk8/fs/xfs/linux/xfs_sysctl.c	2003-07-10 04:38:35.000000000 -0700
@@ -36,9 +36,6 @@
 #include <linux/proc_fs.h>
 
 
-STATIC ulong xfs_min[XFS_PARAM] = { 0, 0, 0, 0,   0, HZ, 0 };
-STATIC ulong xfs_max[XFS_PARAM] = { 1, 1, 1, 127, 3, HZ * 60, 1 };
-
 static struct ctl_table_header *xfs_table_header;
 
 
@@ -62,7 +59,7 @@
 		vn_active = xfsstats.vn_active;
 		memset(&xfsstats, 0, sizeof(xfsstats));
 		xfsstats.vn_active = vn_active;
-		xfs_params.stats_clear = 0;
+		xfs_stats_clear = 0;
 	}
 
 	return ret;
@@ -70,35 +67,42 @@
 #endif /* CONFIG_PROC_FS */
 
 STATIC ctl_table xfs_table[] = {
-	{XFS_RESTRICT_CHOWN, "restrict_chown", &xfs_params.restrict_chown,
+	{XFS_RESTRICT_CHOWN, "restrict_chown", &xfs_params.restrict_chown.val,
 	sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
-	&sysctl_intvec, NULL, &xfs_min[0], &xfs_max[0]},
+	&sysctl_intvec, NULL, 
+	&xfs_params.restrict_chown.min, &xfs_params.restrict_chown.max},
 
-	{XFS_SGID_INHERIT, "irix_sgid_inherit", &xfs_params.sgid_inherit,
+	{XFS_SGID_INHERIT, "irix_sgid_inherit", &xfs_params.sgid_inherit.val,
 	sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
-	&sysctl_intvec, NULL, &xfs_min[1], &xfs_max[1]},
+	&sysctl_intvec, NULL,
+	&xfs_params.sgid_inherit.min, &xfs_params.sgid_inherit.max},
 
-	{XFS_SYMLINK_MODE, "irix_symlink_mode", &xfs_params.symlink_mode,
+	{XFS_SYMLINK_MODE, "irix_symlink_mode", &xfs_params.symlink_mode.val,
 	sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
-	&sysctl_intvec, NULL, &xfs_min[2], &xfs_max[2]},
+	&sysctl_intvec, NULL, 
+	&xfs_params.symlink_mode.min, &xfs_params.symlink_mode.max},
 
-	{XFS_PANIC_MASK, "panic_mask", &xfs_params.panic_mask,
+	{XFS_PANIC_MASK, "panic_mask", &xfs_params.panic_mask.val,
 	sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
-	&sysctl_intvec, NULL, &xfs_min[3], &xfs_max[3]},
+	&sysctl_intvec, NULL, 
+	&xfs_params.panic_mask.min, &xfs_params.panic_mask.max},
 
-	{XFS_ERRLEVEL, "error_level", &xfs_params.error_level,
+	{XFS_ERRLEVEL, "error_level", &xfs_params.error_level.val,
 	sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
-	&sysctl_intvec, NULL, &xfs_min[4], &xfs_max[4]},
+	&sysctl_intvec, NULL, 
+	&xfs_params.error_level.min, &xfs_params.error_level.max},
 
-	{XFS_SYNC_INTERVAL, "sync_interval", &xfs_params.sync_interval,
+	{XFS_SYNC_INTERVAL, "sync_interval", &xfs_params.sync_interval.val,
 	sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
-	&sysctl_intvec, NULL, &xfs_min[5], &xfs_max[5]},
+	&sysctl_intvec, NULL, 
+	&xfs_params.sync_interval.min, &xfs_params.sync_interval.max},
 
 	/* please keep this the last entry */
 #ifdef CONFIG_PROC_FS
-	{XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear,
+	{XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val,
 	sizeof(ulong), 0644, NULL, &xfs_stats_clear_proc_handler,
-	&sysctl_intvec, NULL, &xfs_min[6], &xfs_max[6]},
+	&sysctl_intvec, NULL, 
+	&xfs_params.stats_clear.min, &xfs_params.stats_clear.max},
 #endif /* CONFIG_PROC_FS */
 
 	{0}
diff -urN linux-2.5.74-bk7/fs/xfs/linux/xfs_sysctl.h linux-2.5.74-bk8/fs/xfs/linux/xfs_sysctl.h
--- linux-2.5.74-bk7/fs/xfs/linux/xfs_sysctl.h	2003-07-02 13:39:26.000000000 -0700
+++ linux-2.5.74-bk8/fs/xfs/linux/xfs_sysctl.h	2003-07-10 04:38:35.000000000 -0700
@@ -39,17 +39,22 @@
  * Tunable xfs parameters
  */
 
-#define XFS_PARAM	(sizeof(struct xfs_param) / sizeof(ulong))
+typedef struct xfs_sysctl_val {
+	ulong min;
+	ulong val;
+	ulong max;
+} xfs_sysctl_val_t;
 
 typedef struct xfs_param {
-	ulong	restrict_chown;	/* Root/non-root can give away files.    */
-	ulong	sgid_inherit;	/* Inherit ISGID bit if process' GID is  */
-				/*  not a member of the parent dir GID.  */
-	ulong	symlink_mode;	/* Symlink creat mode affected by umask. */
-	ulong	panic_mask;	/* bitmask to specify panics on errors.  */
-	ulong	error_level;	/* Degree of reporting for internal probs*/
-	ulong	sync_interval;	/* time between sync calls		 */
-	ulong	stats_clear;	/* Reset all XFS statistics to zero.     */
+	xfs_sysctl_val_t restrict_chown;/* Root/non-root can give away files.*/
+	xfs_sysctl_val_t sgid_inherit;	/* Inherit ISGID bit if process' GID 
+					 * is not a member of the parent dir
+					 * GID */
+	xfs_sysctl_val_t symlink_mode;	/* Link creat mode affected by umask */
+	xfs_sysctl_val_t panic_mask;	/* bitmask to cause panic on errors. */
+	xfs_sysctl_val_t error_level;	/* Degree of reporting for problems  */
+	xfs_sysctl_val_t sync_interval;	/* time between sync calls           */
+	xfs_sysctl_val_t stats_clear;	/* Reset all XFS statistics to zero. */
 } xfs_param_t;
 
 /*
diff -urN linux-2.5.74-bk7/fs/xfs/pagebuf/page_buf.c linux-2.5.74-bk8/fs/xfs/pagebuf/page_buf.c
--- linux-2.5.74-bk7/fs/xfs/pagebuf/page_buf.c	2003-07-02 13:40:22.000000000 -0700
+++ linux-2.5.74-bk8/fs/xfs/pagebuf/page_buf.c	2003-07-10 04:38:35.000000000 -0700
@@ -92,7 +92,7 @@
 	int		j;
 	unsigned long	flags;
 
-	if (!pb_params.p_un.debug) return;
+	if (!pb_params.debug.val) return;
 
 	if (ra == NULL) ra = (void *)__builtin_return_address(0);
 
@@ -129,10 +129,13 @@
  * /proc/sys/vm/pagebuf
  */
 
-unsigned long pagebuf_min[P_PARAM] = {  HZ/2,   1*HZ, 0, 0 };
-unsigned long pagebuf_max[P_PARAM] = { HZ*30, HZ*300, 1, 1 };
-
-pagebuf_param_t pb_params = {{ HZ, 15 * HZ, 0, 0 }};
+pagebuf_param_t 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	},
+};
 
 /*
  * Pagebuf statistics variables
@@ -1556,7 +1559,7 @@
 	}
 
 	list_add_tail(&pb->pb_list, &pbd_delwrite_queue);
-	pb->pb_flushtime = jiffies + pb_params.p_un.age_buffer;
+	pb->pb_flushtime = jiffies + pb_params.age_buffer.val;
 	spin_unlock(&pbd_delwrite_lock);
 
 	if (unlock && (pb->pb_flags & _PBF_LOCKABLE)) {
@@ -1621,7 +1624,7 @@
 
 		if (pbd_active == 1) {
 			mod_timer(&pb_daemon_timer,
-				  jiffies + pb_params.p_un.flush_interval);
+				  jiffies + pb_params.flush_interval.val);
 			interruptible_sleep_on(&pbd_waitq);
 		}
 
@@ -1824,7 +1827,7 @@
 	if (!ret && write && *valp) {
 		printk("XFS Clearing pbstats\n");
 		memset(&pbstats, 0, sizeof(pbstats));
-		pb_params.p_un.stats_clear = 0;
+		pb_params.stats_clear.val = 0;
 	}
 
 	return ret;
@@ -1833,22 +1836,26 @@
 STATIC struct ctl_table_header *pagebuf_table_header;
 
 STATIC ctl_table pagebuf_table[] = {
-	{PB_FLUSH_INT, "flush_int", &pb_params.data[0],
+	{PB_FLUSH_INT, "flush_int", &pb_params.flush_interval.val,
 	sizeof(ulong), 0644, NULL, &proc_doulongvec_ms_jiffies_minmax,
-	&sysctl_intvec, NULL, &pagebuf_min[0], &pagebuf_max[0]},
+	&sysctl_intvec, NULL,
+	&pb_params.flush_interval.min, &pb_params.flush_interval.max},
 
-	{PB_FLUSH_AGE, "flush_age", &pb_params.data[1],
+	{PB_FLUSH_AGE, "flush_age", &pb_params.age_buffer.val,
 	sizeof(ulong), 0644, NULL, &proc_doulongvec_ms_jiffies_minmax,
-	&sysctl_intvec, NULL, &pagebuf_min[1], &pagebuf_max[1]},
+	&sysctl_intvec, NULL, 
+	&pb_params.age_buffer.min, &pb_params.age_buffer.max},
 
-	{PB_STATS_CLEAR, "stats_clear", &pb_params.data[2],
+	{PB_STATS_CLEAR, "stats_clear", &pb_params.stats_clear.val,
 	sizeof(ulong), 0644, NULL, &pb_stats_clear_handler,
-	&sysctl_intvec, NULL, &pagebuf_min[2], &pagebuf_max[2]},
+	&sysctl_intvec, NULL, 
+	&pb_params.stats_clear.min, &pb_params.stats_clear.max},
 
 #ifdef PAGEBUF_TRACE
-	{PB_DEBUG, "debug", &pb_params.data[3],
+	{PB_DEBUG, "debug", &pb_params.debug.val,
 	sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
-	&sysctl_intvec, NULL, &pagebuf_min[3], &pagebuf_max[3]},
+	&sysctl_intvec, NULL, 
+	&pb_params.debug.min, &pb_params.debug.max},
 #endif
 	{0}
 };
diff -urN linux-2.5.74-bk7/fs/xfs/pagebuf/page_buf_internal.h linux-2.5.74-bk8/fs/xfs/pagebuf/page_buf_internal.h
--- linux-2.5.74-bk7/fs/xfs/pagebuf/page_buf_internal.h	2003-07-02 13:46:57.000000000 -0700
+++ linux-2.5.74-bk8/fs/xfs/pagebuf/page_buf_internal.h	2003-07-10 04:38:35.000000000 -0700
@@ -85,18 +85,19 @@
  * Tunable pagebuf parameters
  */
 
-#define P_PARAM	4
+typedef struct pb_sysctl_val {
+	ulong min;
+	ulong val;
+	ulong max;
+} pb_sysctl_val_t;
 
-typedef union pagebuf_param {
-	struct {
-		ulong	flush_interval;	/* interval between runs of the
+typedef struct pagebuf_param {
+	pb_sysctl_val_t	flush_interval;	/* interval between runs of the
 					 * delwri flush daemon.  */
-		ulong	age_buffer;	/* time for buffer to age before
+	pb_sysctl_val_t	age_buffer;	/* time for buffer to age before
 					 * we flush it.  */
-		ulong	debug;		/* debug tracing on or off */
-		ulong	stats_clear;	/* clear the pagebuf stats */
-	} p_un;
-	ulong data[P_PARAM];
+	pb_sysctl_val_t	stats_clear;	/* clear the pagebuf stats */
+	pb_sysctl_val_t	debug;		/* debug tracing on or off */
 } pagebuf_param_t;
 
 enum {
diff -urN linux-2.5.74-bk7/fs/xfs/xfs_vfsops.c linux-2.5.74-bk8/fs/xfs/xfs_vfsops.c
--- linux-2.5.74-bk7/fs/xfs/xfs_vfsops.c	2003-07-02 13:42:16.000000000 -0700
+++ linux-2.5.74-bk8/fs/xfs/xfs_vfsops.c	2003-07-10 04:38:35.000000000 -0700
@@ -96,9 +96,6 @@
 #endif	/* DEBUG */
 #ifdef XFS_DABUF_DEBUG
 	extern lock_t	        xfs_dabuf_global_lock;
-#endif
-
-#ifdef XFS_DABUF_DEBUG
 	spinlock_init(&xfs_dabuf_global_lock, "xfsda");
 #endif
 
diff -urN linux-2.5.74-bk7/include/asm-generic/div64.h linux-2.5.74-bk8/include/asm-generic/div64.h
--- linux-2.5.74-bk7/include/asm-generic/div64.h	2003-07-10 04:38:32.000000000 -0700
+++ linux-2.5.74-bk8/include/asm-generic/div64.h	2003-07-10 04:38:35.000000000 -0700
@@ -18,6 +18,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/compiler.h>
 
 #if BITS_PER_LONG == 64
 
@@ -31,12 +32,12 @@
 
 #elif BITS_PER_LONG == 32
 
-extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
+extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor) __attribute_pure__;
 
 # define do_div(n,base) ({				\
 	uint32_t __base = (base);			\
 	uint32_t __rem;					\
-	if (((n) >> 32) == 0) {				\
+	if (likely(((n) >> 32) == 0)) {			\
 		__rem = (uint32_t)(n) % __base;		\
 		(n) = (uint32_t)(n) / __base;		\
 	} else 						\
diff -urN linux-2.5.74-bk7/include/linux/compiler.h linux-2.5.74-bk8/include/linux/compiler.h
--- linux-2.5.74-bk7/include/linux/compiler.h	2003-07-02 13:50:12.000000000 -0700
+++ linux-2.5.74-bk8/include/linux/compiler.h	2003-07-10 04:38:35.000000000 -0700
@@ -56,6 +56,24 @@
 #define __attribute_used__	__attribute__((__unused__))
 #endif
 
+/*
+ * From the GCC manual:
+ *
+ * Many functions have no effects except the return value and their
+ * return value depends only on the parameters and/or global
+ * variables.  Such a function can be subject to common subexpression
+ * elimination and loop optimization just as an arithmetic operator
+ * would be.
+ * [...]
+ * The attribute `pure' is not implemented in GCC versions earlier
+ * than 2.96.
+ */
+#if (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || __GNUC__ > 2
+#define __attribute_pure__	__attribute__((pure))
+#else
+#define __attribute_pure__	/* unimplemented */
+#endif
+
 /* This macro obfuscates arithmetic on a variable address so that gcc
    shouldn't recognize the original var, and make assumptions about it */
 #define RELOC_HIDE(ptr, off)					\
diff -urN linux-2.5.74-bk7/include/linux/cpufreq.h linux-2.5.74-bk8/include/linux/cpufreq.h
--- linux-2.5.74-bk7/include/linux/cpufreq.h	2003-07-02 13:49:35.000000000 -0700
+++ linux-2.5.74-bk8/include/linux/cpufreq.h	2003-07-10 04:38:35.000000000 -0700
@@ -20,6 +20,7 @@
 #include <linux/device.h>
 #include <linux/kobject.h>
 #include <linux/sysfs.h>
+#include <linux/completion.h>
 
 #define CPUFREQ_NAME_LEN 16
 
@@ -31,17 +32,15 @@
 int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list);
 int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list);
 
-#define CPUFREQ_TRANSITION_NOTIFIER     (0)
-#define CPUFREQ_POLICY_NOTIFIER         (1)
-
-#define CPUFREQ_ALL_CPUS        ((NR_CPUS))
+#define CPUFREQ_TRANSITION_NOTIFIER	(0)
+#define CPUFREQ_POLICY_NOTIFIER		(1)
 
 
 /********************** cpufreq policy notifiers *********************/
 
-#define CPUFREQ_POLICY_POWERSAVE        (1)
-#define CPUFREQ_POLICY_PERFORMANCE      (2)
-#define CPUFREQ_POLICY_GOVERNOR         (3)
+#define CPUFREQ_POLICY_POWERSAVE	(1)
+#define CPUFREQ_POLICY_PERFORMANCE	(2)
+#define CPUFREQ_POLICY_GOVERNOR		(3)
 
 /* Frequency values here are CPU kHz so that hardware which doesn't run 
  * with some frequencies can complain without having to guess what per 
@@ -52,30 +51,34 @@
 
 struct cpufreq_governor;
 
-#define CPUFREQ_ETERNAL (-1)
+#define CPUFREQ_ETERNAL			(-1)
 struct cpufreq_cpuinfo {
-	unsigned int            max_freq;
-	unsigned int            min_freq;
-	unsigned int            transition_latency;
+	unsigned int		max_freq;
+	unsigned int		min_freq;
+	unsigned int		transition_latency; /* in 10^(-9) s */
 };
 
 struct cpufreq_policy {
-	unsigned int            cpu;    /* cpu nr or CPUFREQ_ALL_CPUS */
-	unsigned int            min;    /* in kHz */
-	unsigned int            max;    /* in kHz */
-	unsigned int            cur;    /* in kHz, only needed if cpufreq
+	unsigned int		cpu;    /* cpu nr */
+	struct cpufreq_cpuinfo	cpuinfo;/* see above */
+
+	unsigned int		min;    /* in kHz */
+	unsigned int		max;    /* in kHz */
+	unsigned int		cur;    /* in kHz, only needed if cpufreq
 					 * governors are used */
-        unsigned int            policy; /* see above */
-	struct cpufreq_governor *governor; /* see below */
-	struct cpufreq_cpuinfo  cpuinfo;     /* see above */
-	struct kobject		kobj;
+        unsigned int		policy; /* see above */
+	struct cpufreq_governor	*governor; /* see below */
+
  	struct semaphore	lock;   /* CPU ->setpolicy or ->target may
 					   only be called once a time */
+
+	struct kobject		kobj;
+	struct completion	kobj_unregister;
 };
 
-#define CPUFREQ_ADJUST          (0)
-#define CPUFREQ_INCOMPATIBLE    (1)
-#define CPUFREQ_NOTIFY          (2)
+#define CPUFREQ_ADJUST		(0)
+#define CPUFREQ_INCOMPATIBLE	(1)
+#define CPUFREQ_NOTIFY		(2)
 
 
 /******************** cpufreq transition notifiers *******************/
@@ -84,7 +87,7 @@
 #define CPUFREQ_POSTCHANGE	(1)
 
 struct cpufreq_freqs {
-	unsigned int cpu;      /* cpu nr or CPUFREQ_ALL_CPUS */
+	unsigned int cpu;	/* cpu nr */
 	unsigned int old;
 	unsigned int new;
 };
@@ -125,11 +128,11 @@
 #define CPUFREQ_GOV_LIMITS 3
 
 struct cpufreq_governor {
-	char			name[CPUFREQ_NAME_LEN];
-	int	(*governor)	(struct cpufreq_policy *policy,
+	char	name[CPUFREQ_NAME_LEN];
+	int 	(*governor)	(struct cpufreq_policy *policy,
 				 unsigned int event);
 	struct list_head	governor_list;
-	struct module           *owner;
+	struct module		*owner;
 };
 
 /* pass a target to the cpufreq driver 
@@ -154,18 +157,22 @@
 struct freq_attr;
 
 struct cpufreq_driver {
+	struct module           *owner;
+	char			name[CPUFREQ_NAME_LEN];
+
+	struct cpufreq_policy	*policy;
+
 	/* needed by all drivers */
+	int	(*init)		(struct cpufreq_policy *policy);
 	int	(*verify)	(struct cpufreq_policy *policy);
-	struct cpufreq_policy	*policy;
-	char			name[CPUFREQ_NAME_LEN];
+
 	/* define one out of two */
 	int	(*setpolicy)	(struct cpufreq_policy *policy);
 	int	(*target)	(struct cpufreq_policy *policy,
 				 unsigned int target_freq,
 				 unsigned int relation);
-	struct module           *owner;
-	/* optional, for the moment */
-	int	(*init)		(struct cpufreq_policy *policy);
+
+	/* optional */
 	int	(*exit)		(struct cpufreq_policy *policy);
 	struct freq_attr	**attr;
 };
@@ -306,8 +313,4 @@
 
 
 #endif /* CONFIG_CPU_FREQ_TABLE */
-
-/* Currently exported only for the proc interface, remove when that goes */
-extern struct cpufreq_driver *cpufreq_driver;
-
 #endif /* _LINUX_CPUFREQ_H */
diff -urN linux-2.5.74-bk7/include/linux/pci_ids.h linux-2.5.74-bk8/include/linux/pci_ids.h
--- linux-2.5.74-bk7/include/linux/pci_ids.h	2003-07-02 13:46:17.000000000 -0700
+++ linux-2.5.74-bk8/include/linux/pci_ids.h	2003-07-10 04:38:35.000000000 -0700
@@ -571,6 +571,7 @@
 #define PCI_DEVICE_ID_SI_750		0x0750
 #define PCI_DEVICE_ID_SI_751		0x0751
 #define PCI_DEVICE_ID_SI_752		0x0752
+#define PCI_DEVICE_ID_SI_755		0x0755
 #define PCI_DEVICE_ID_SI_900		0x0900
 #define PCI_DEVICE_ID_SI_961		0x0961
 #define PCI_DEVICE_ID_SI_962		0x0962
diff -urN linux-2.5.74-bk7/include/linux/xfrm.h linux-2.5.74-bk8/include/linux/xfrm.h
--- linux-2.5.74-bk7/include/linux/xfrm.h	2003-07-02 13:43:23.000000000 -0700
+++ linux-2.5.74-bk8/include/linux/xfrm.h	2003-07-10 04:38:35.000000000 -0700
@@ -119,7 +119,9 @@
 #define XFRM_MSG_UPDPOLICY	(XFRM_MSG_BASE + 9)
 #define XFRM_MSG_UPDSA		(XFRM_MSG_BASE + 10)
 
-#define XFRM_MSG_MAX		(XFRM_MSG_UPDSA+1)
+#define XFRM_MSG_POLEXPIRE	(XFRM_MSG_BASE + 11)
+
+#define XFRM_MSG_MAX		(XFRM_MSG_POLEXPIRE+1)
 
 struct xfrm_user_tmpl {
 	struct xfrm_id		id;
@@ -217,6 +219,11 @@
 	__u8				hard;
 };
 
+struct xfrm_user_polexpire {
+	struct xfrm_userpolicy_info	pol;
+	__u8				hard;
+};
+
 #define XFRMGRP_ACQUIRE		1
 #define XFRMGRP_EXPIRE		2
 
diff -urN linux-2.5.74-bk7/include/net/addrconf.h linux-2.5.74-bk8/include/net/addrconf.h
--- linux-2.5.74-bk7/include/net/addrconf.h	2003-07-02 13:53:02.000000000 -0700
+++ linux-2.5.74-bk8/include/net/addrconf.h	2003-07-10 04:38:35.000000000 -0700
@@ -6,6 +6,8 @@
 #define MAX_RTR_SOLICITATIONS		3
 #define RTR_SOLICITATION_INTERVAL	(4*HZ)
 
+#define MIN_VALID_LIFETIME		(2*3600)	/* 2 hours */
+
 #define TEMP_VALID_LIFETIME		(7*86400)
 #define TEMP_PREFERRED_LIFETIME		(86400)
 #define REGEN_MAX_RETRY			(5)
diff -urN linux-2.5.74-bk7/include/net/pkt_sched.h linux-2.5.74-bk8/include/net/pkt_sched.h
--- linux-2.5.74-bk7/include/net/pkt_sched.h	2003-07-02 13:42:41.000000000 -0700
+++ linux-2.5.74-bk8/include/net/pkt_sched.h	2003-07-10 04:38:35.000000000 -0700
@@ -61,7 +61,7 @@
 	int 			(*enqueue)(struct sk_buff *, struct Qdisc *);
 	struct sk_buff *	(*dequeue)(struct Qdisc *);
 	int 			(*requeue)(struct sk_buff *, struct Qdisc *);
-	int			(*drop)(struct Qdisc *);
+	unsigned int		(*drop)(struct Qdisc *);
 
 	int			(*init)(struct Qdisc *, struct rtattr *arg);
 	void			(*reset)(struct Qdisc *);
diff -urN linux-2.5.74-bk7/include/net/xfrm.h linux-2.5.74-bk8/include/net/xfrm.h
--- linux-2.5.74-bk7/include/net/xfrm.h	2003-07-02 13:54:19.000000000 -0700
+++ linux-2.5.74-bk8/include/net/xfrm.h	2003-07-10 04:38:35.000000000 -0700
@@ -287,6 +287,8 @@
 	struct xfrm_tmpl       	xfrm_vec[XFRM_MAX_DEPTH];
 };
 
+#define XFRM_KM_TIMEOUT		30
+
 struct xfrm_mgr
 {
 	struct list_head	list;
@@ -295,6 +297,7 @@
 	int			(*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
 	struct xfrm_policy	*(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir);
 	int			(*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
+	int			(*notify_policy)(struct xfrm_policy *x, int dir, int event);
 };
 
 extern int xfrm_register_km(struct xfrm_mgr *km);
@@ -635,16 +638,16 @@
 	return 0;
 }
 
-extern void __xfrm_sk_free_policy(struct xfrm_policy *, int dir);
+extern void xfrm_policy_delete(struct xfrm_policy *pol, int dir);
 
 static inline void xfrm_sk_free_policy(struct sock *sk)
 {
 	if (unlikely(sk->sk_policy[0] != NULL)) {
-		__xfrm_sk_free_policy(sk->sk_policy[0], 0);
+		xfrm_policy_delete(sk->sk_policy[0], XFRM_POLICY_MAX);
 		sk->sk_policy[0] = NULL;
 	}
 	if (unlikely(sk->sk_policy[1] != NULL)) {
-		__xfrm_sk_free_policy(sk->sk_policy[1], 1);
+		xfrm_policy_delete(sk->sk_policy[1], XFRM_POLICY_MAX+1);
 		sk->sk_policy[1] = NULL;
 	}
 }
@@ -809,10 +812,10 @@
 extern int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family);
 
 extern wait_queue_head_t km_waitq;
-extern void km_warn_expired(struct xfrm_state *x);
-extern void km_expired(struct xfrm_state *x);
+extern void km_state_expired(struct xfrm_state *x, int hard);
 extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *pol);
 extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
+extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard);
 
 extern void xfrm4_input_init(void);
 extern void xfrm6_input_init(void);
diff -urN linux-2.5.74-bk7/kernel/cpufreq.c linux-2.5.74-bk8/kernel/cpufreq.c
--- linux-2.5.74-bk7/kernel/cpufreq.c	2003-07-02 13:42:52.000000000 -0700
+++ linux-2.5.74-bk8/kernel/cpufreq.c	2003-07-10 04:38:35.000000000 -0700
@@ -23,6 +23,7 @@
 #include <linux/device.h>
 #include <linux/slab.h>
 #include <linux/cpu.h>
+#include <linux/completion.h>
 
 /**
  * The "cpufreq driver" - the arch- or hardware-dependend low
@@ -297,6 +298,12 @@
 	return ret;
 }
 
+static void cpufreq_sysfs_release(struct kobject * kobj)
+{
+	struct cpufreq_policy * policy = to_policy(kobj);
+	complete(&policy->kobj_unregister);
+}
+
 static struct sysfs_ops sysfs_ops = {
 	.show	= show,
 	.store	= store,
@@ -305,6 +312,7 @@
 static struct kobj_type ktype_cpufreq = {
 	.sysfs_ops	= &sysfs_ops,
 	.default_attrs	= default_attrs,
+	.release	= cpufreq_sysfs_release,
 };
 
 
@@ -329,11 +337,9 @@
 	 */
 	policy = &cpufreq_driver->policy[cpu];
 	policy->cpu = cpu;
-	if (cpufreq_driver->init) {
-		ret = cpufreq_driver->init(policy);
-		if (ret)
-			goto out;
-	}
+	ret = cpufreq_driver->init(policy);
+	if (ret)
+		goto out;
 
 	/* set default policy on this CPU */
 	down(&cpufreq_driver_sem);
@@ -343,6 +349,8 @@
 	up(&cpufreq_driver_sem);
 
 	init_MUTEX(&policy->lock);
+	init_completion(&policy->kobj_unregister);
+
 	/* prepare interface data */
 	policy->kobj.parent = &sys_dev->kobj;
 	policy->kobj.ktype = &ktype_cpufreq;
@@ -352,18 +360,19 @@
 	if (ret)
 		goto out;
 
+	/* set up files for this cpu device */
 	drv_attr = cpufreq_driver->attr;
 	while ((drv_attr) && (*drv_attr)) {
 		sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
 		drv_attr++;
 	}
-	/* set up files for this cpu device */
-
 	
 	/* set default policy */
 	ret = cpufreq_set_policy(&new_policy);
-	if (ret)
+	if (ret) {
 		kobject_unregister(&policy->kobj);
+		wait_for_completion(&policy->kobj_unregister);
+	}
 
  out:
 	module_put(cpufreq_driver->owner);
@@ -401,10 +410,39 @@
 
 	up(&cpufreq_driver_sem);
 	kobject_put(&cpufreq_driver->policy[cpu].kobj);
+
+	/* we need to make sure that the underlying kobj is actually
+	 * destroyed before we proceed e.g. with cpufreq driver module
+	 * unloading
+	 */
+	wait_for_completion(&cpufreq_driver->policy[cpu].kobj_unregister);
+
 	return 0;
 }
 
-static int cpufreq_restore(struct sys_device *);
+/**
+ *	cpufreq_restore - restore the CPU clock frequency after resume
+ *
+ *	Restore the CPU clock frequency so that our idea of the current
+ *	frequency reflects the actual hardware.
+ */
+static int cpufreq_restore(struct sys_device * sysdev)
+{
+	int cpu = sysdev->id;
+	unsigned int ret = 0;
+	struct cpufreq_policy policy;
+
+	if (cpu_online(cpu) && cpufreq_cpu_get(cpu)) {
+		down(&cpufreq_driver_sem);
+		memcpy(&policy, &cpufreq_driver->policy[cpu], 
+		       sizeof(struct cpufreq_policy));
+		up(&cpufreq_driver_sem);
+		ret = cpufreq_set_policy(&policy);
+		cpufreq_cpu_put(cpu);
+	}
+
+	return ret;
+}
 
 static struct sysdev_driver cpufreq_sysdev_driver = {
 	.add		= cpufreq_add_dev,
@@ -587,33 +625,10 @@
 
 void cpufreq_unregister_governor(struct cpufreq_governor *governor)
 {
-	unsigned int i;
-	
 	if (!governor)
 		return;
 
 	down(&cpufreq_governor_sem);
-
-	/* 
-	 * Unless the user uses rmmod -f, we can be safe. But we never
-	 * know, so check whether if it's currently used. If so,
-	 * stop it and replace it with the default governor.
-	 */
-	for (i=0; i<NR_CPUS; i++)
-	{
-		if (!cpufreq_cpu_get(i))
-			continue;
-		if ((cpufreq_driver->policy[i].policy == CPUFREQ_POLICY_GOVERNOR) && 
-		    (cpufreq_driver->policy[i].governor == governor)) {
-			cpufreq_governor(i, CPUFREQ_GOV_STOP);
-			cpufreq_driver->policy[i].policy = CPUFREQ_POLICY_PERFORMANCE;
-			cpufreq_governor(i, CPUFREQ_GOV_START);
-			cpufreq_governor(i, CPUFREQ_GOV_LIMITS);
-		}
-		cpufreq_cpu_put(i);
-	}
-
-	/* now we can safely remove it from the list */
 	list_del(&governor->governor_list);
 	up(&cpufreq_governor_sem);
 	return;
@@ -781,7 +796,7 @@
 	switch (state) {
 	case CPUFREQ_PRECHANGE:
 		notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
-		adjust_jiffies(CPUFREQ_PRECHANGE, freqs);		
+		adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
 		break;
 	case CPUFREQ_POSTCHANGE:
 		adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
@@ -859,37 +874,3 @@
 	return 0;
 }
 EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
-
-
-#ifdef CONFIG_PM
-
-/**
- *	cpufreq_restore - restore the CPU clock frequency after resume
- *
- *	Restore the CPU clock frequency so that our idea of the current
- *	frequency reflects the actual hardware.
- */
-static int cpufreq_restore(struct sys_device * sysdev)
-{
-	int cpu = sysdev->id;
-	unsigned int ret = 0;
-	struct cpufreq_policy policy;
-
-	if (cpu_online(cpu) && cpufreq_cpu_get(cpu)) {
-		down(&cpufreq_driver_sem);
-		memcpy(&policy, &cpufreq_driver->policy[cpu], 
-		       sizeof(struct cpufreq_policy));
-		up(&cpufreq_driver_sem);
-		ret = cpufreq_set_policy(&policy);
-		cpufreq_cpu_put(cpu);
-	}
-
-	return ret;
-}
-
-#else
-static int cpufreq_restore(struct sys_device * sysdev)
-{
-	return 0;
-}
-#endif /* CONFIG_PM */
diff -urN linux-2.5.74-bk7/kernel/suspend.c linux-2.5.74-bk8/kernel/suspend.c
--- linux-2.5.74-bk7/kernel/suspend.c	2003-07-10 04:38:32.000000000 -0700
+++ linux-2.5.74-bk8/kernel/suspend.c	2003-07-10 04:38:35.000000000 -0700
@@ -692,7 +692,6 @@
 		printk(KERN_CRIT "%sCouldn't get enough free pages, on %d pages short\n",
 		       name_suspend, nr_needed_pages-nr_free_pages());
 		root_swap = 0xFFFF;
-		spin_unlock_irq(&suspend_pagedir_lock);
 		return 1;
 	}
 	si_swapinfo(&i);	/* FIXME: si_swapinfo(&i) returns all swap devices information.
@@ -700,7 +699,6 @@
 	if (i.freeswap < nr_needed_pages)  {
 		printk(KERN_CRIT "%sThere's not enough swap space available, on %ld pages short\n",
 		       name_suspend, nr_needed_pages-i.freeswap);
-		spin_unlock_irq(&suspend_pagedir_lock);
 		return 1;
 	}
 
@@ -710,7 +708,6 @@
 		/* Shouldn't happen */
 		printk(KERN_CRIT "%sCouldn't allocate enough pages\n",name_suspend);
 		panic("Really should not happen");
-		spin_unlock_irq(&suspend_pagedir_lock);
 		return 1;
 	}
 	nr_copy_pages_check = nr_copy_pages;
@@ -724,12 +721,9 @@
 	 * End of critical section. From now on, we can write to memory,
 	 * but we should not touch disk. This specially means we must _not_
 	 * touch swap space! Except we must write out our image of course.
-	 *
-	 * Following line enforces not writing to disk until we choose.
 	 */
 
 	printk( "critical section/: done (%d pages copied)\n", nr_copy_pages );
-	spin_unlock_irq(&suspend_pagedir_lock);
 	return 0;
 }
 
@@ -808,6 +802,24 @@
 #endif
 }
 
+/* do_magic() is implemented in arch/?/kernel/suspend_asm.S, and basically does:
+
+	if (!resume) {
+		do_magic_suspend_1();
+		save_processor_state();
+		SAVE_REGISTERS
+		do_magic_suspend_2();
+		return;
+	}
+	GO_TO_SWAPPER_PAGE_TABLES
+	do_magic_resume_1();
+	COPY_PAGES_BACK
+	RESTORE_REGISTERS
+	restore_processor_state();
+	do_magic_resume_2();
+
+ */
+
 void do_magic_suspend_1(void)
 {
 	mb();
@@ -818,8 +830,13 @@
 
 void do_magic_suspend_2(void)
 {
+	int is_problem;
 	read_swapfiles();
-	if (!suspend_prepare_image()) {	/* suspend_save_image realeses suspend_pagedir_lock */
+	is_problem = suspend_prepare_image();
+	spin_unlock_irq(&suspend_pagedir_lock);
+	if (!is_problem) {
+		kernel_fpu_end();	/* save_processor_state() does kernel_fpu_begin, and we need to revert it in order to pass in_atomic() checks */
+		BUG_ON(in_atomic());
 		suspend_save_image();
 		suspend_power_down();	/* FIXME: if suspend_power_down is commented out, console is lost after few suspends ?! */
 	}
@@ -1224,13 +1241,13 @@
 	orig_loglevel = console_loglevel;
 	console_loglevel = new_loglevel;
 
-	if(!resume_file[0] && resume_status == RESUME_SPECIFIED) {
+	if (!resume_file[0] && resume_status == RESUME_SPECIFIED) {
 		printk( "suspension device unspecified\n" );
 		return;
 	}
 
 	printk( "resuming from %s\n", resume_file);
-	if(read_suspend_image(resume_file, 0))
+	if (read_suspend_image(resume_file, 0))
 		goto read_failure;
 	do_magic(1);
 	panic("This never returns");
diff -urN linux-2.5.74-bk7/lib/div64.c linux-2.5.74-bk8/lib/div64.c
--- linux-2.5.74-bk7/lib/div64.c	2003-07-10 04:38:32.000000000 -0700
+++ linux-2.5.74-bk8/lib/div64.c	2003-07-10 04:38:35.000000000 -0700
@@ -12,13 +12,17 @@
  * The fast case for (n>>32 == 0) is handled inline by do_div(). 
  *
  * Code generated for this function might be very inefficient
- * for some CPUs. div64_32() can be overridden by linking arch-specific
+ * for some CPUs. __div64_32() can be overridden by linking arch-specific
  * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S.
  */
 
 #include <linux/types.h>
+#include <linux/module.h>
 #include <asm/div64.h>
 
+/* Not needed on 64bit architectures */
+#if BITS_PER_LONG == 32
+
 uint32_t __div64_32(uint64_t *n, uint32_t base)
 {
 	uint32_t low, low2, high, rem;
@@ -43,3 +47,6 @@
 	return rem;
 }
 
+EXPORT_SYMBOL(__div64_32);
+
+#endif /* BITS_PER_LONG == 32 */
diff -urN linux-2.5.74-bk7/net/atm/clip.c linux-2.5.74-bk8/net/atm/clip.c
--- linux-2.5.74-bk7/net/atm/clip.c	2003-07-02 13:57:16.000000000 -0700
+++ linux-2.5.74-bk8/net/atm/clip.c	2003-07-10 04:38:35.000000000 -0700
@@ -327,40 +327,34 @@
 	return hash_val;
 }
 
-
 static struct neigh_table clip_tbl = {
-	NULL,			/* next */
-	AF_INET,		/* family */
-	sizeof(struct neighbour)+sizeof(struct atmarp_entry), /* entry_size */
-	4,			/* key_len */
-	clip_hash,
-	clip_constructor,	/* constructor */
-	NULL,			/* pconstructor */
-	NULL,			/* pdestructor */
-	NULL,			/* proxy_redo */
-	"clip_arp_cache",
-	{			/* neigh_parms */
-		NULL,		/* next */
-		NULL,		/* neigh_setup */
-		&clip_tbl,	/* tbl */
-		0,		/* entries */
-		NULL,		/* priv */
-		NULL,		/* sysctl_table */
-		30*HZ,		/* base_reachable_time */
-		1*HZ,		/* retrans_time */
-		60*HZ,		/* gc_staletime */
-		30*HZ,		/* reachable_time */
-		5*HZ,		/* delay_probe_time */
-		3,		/* queue_len */
-		3,		/* ucast_probes */
-		0,		/* app_probes */
-		3,		/* mcast_probes */
-		1*HZ,		/* anycast_delay */
-		(8*HZ)/10,	/* proxy_delay */
-		1*HZ,		/* proxy_qlen */
-		64		/* locktime */
+	.family 	= AF_INET,
+	.entry_size 	= sizeof(struct neighbour)+sizeof(struct atmarp_entry),
+	.key_len 	= 4,
+	.hash 		= clip_hash,
+	.constructor 	= clip_constructor,
+	.id 		= "clip_arp_cache",
+
+	/* parameters are copied from ARP ... */
+	.parms = {
+		.tbl 			= &clip_tbl,
+		.base_reachable_time 	= 30 * HZ,
+		.retrans_time 		= 1 * HZ,
+		.gc_staletime 		= 60 * HZ,
+		.reachable_time 	= 30 * HZ,
+		.delay_probe_time 	= 5 * HZ,
+		.queue_len 		= 3,
+		.ucast_probes 		= 3,
+		.mcast_probes 		= 3,
+		.anycast_delay 		= 1 * HZ,
+		.proxy_delay 		= (8 * HZ) / 10,
+		.proxy_qlen 		= 64,
+		.locktime 		= 1 * HZ,
 	},
-	30*HZ,128,512,1024	/* copied from ARP ... */
+	.gc_interval 	= 30 * HZ,
+	.gc_thresh1 	= 128,
+	.gc_thresh2 	= 512,
+	.gc_thresh3 	= 1024,
 };
 
 
diff -urN linux-2.5.74-bk7/net/core/neighbour.c linux-2.5.74-bk8/net/core/neighbour.c
--- linux-2.5.74-bk7/net/core/neighbour.c	2003-07-02 13:40:27.000000000 -0700
+++ linux-2.5.74-bk8/net/core/neighbour.c	2003-07-10 04:38:35.000000000 -0700
@@ -608,7 +608,9 @@
 static __inline__ int neigh_max_probes(struct neighbour *n)
 {
 	struct neigh_parms *p = n->parms;
-	return p->ucast_probes + p->app_probes + p->mcast_probes;
+	return (n->nud_state & NUD_PROBE ?
+		p->ucast_probes :
+		p->ucast_probes + p->app_probes + p->mcast_probes);
 }
 
 
diff -urN linux-2.5.74-bk7/net/ipv4/ipconfig.c linux-2.5.74-bk8/net/ipv4/ipconfig.c
--- linux-2.5.74-bk7/net/ipv4/ipconfig.c	2003-07-10 04:38:32.000000000 -0700
+++ linux-2.5.74-bk8/net/ipv4/ipconfig.c	2003-07-10 04:38:35.000000000 -0700
@@ -1115,8 +1115,10 @@
 				       "nameserver %u.%u.%u.%u\n",
 				       NIPQUAD(ic_nameservers[i]));
 	}
-	len += sprintf(buffer + len, "bootserver %u.%u.%u.%u\n",
-			NIPQUAD(ic_servaddr));
+	if (ic_servaddr != INADDR_NONE)
+		len += sprintf(buffer + len,
+			       "bootserver %u.%u.%u.%u\n",
+			       NIPQUAD(ic_servaddr));
 
 	if (offset > len)
 		offset = len;
diff -urN linux-2.5.74-bk7/net/ipv6/addrconf.c linux-2.5.74-bk8/net/ipv6/addrconf.c
--- linux-2.5.74-bk7/net/ipv6/addrconf.c	2003-07-02 13:56:02.000000000 -0700
+++ linux-2.5.74-bk8/net/ipv6/addrconf.c	2003-07-10 04:38:35.000000000 -0700
@@ -1299,7 +1299,6 @@
 void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
 {
 	struct prefix_info *pinfo;
-	struct rt6_info *rt;
 	__u32 valid_lft;
 	__u32 prefered_lft;
 	int addr_type;
@@ -1355,33 +1354,33 @@
 	else
 		rt_expires = jiffies + valid_lft * HZ;
 
-	rt = rt6_lookup(&pinfo->prefix, NULL, dev->ifindex, 1);
-
-	if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
-		if (rt->rt6i_flags&RTF_EXPIRES) {
-			if (pinfo->onlink == 0 || valid_lft == 0) {
-				ip6_del_rt(rt, NULL, NULL);
-				rt = NULL;
-			} else {
-				rt->rt6i_expires = rt_expires;
+	if (pinfo->onlink) {
+		struct rt6_info *rt;
+		rt = rt6_lookup(&pinfo->prefix, NULL, dev->ifindex, 1);
+
+		if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
+			if (rt->rt6i_flags&RTF_EXPIRES) {
+				if (valid_lft == 0) {
+					ip6_del_rt(rt, NULL, NULL);
+					rt = NULL;
+				} else {
+					rt->rt6i_expires = rt_expires;
+				}
 			}
+		} else if (valid_lft) {
+			addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len,
+					      dev, rt_expires, RTF_ADDRCONF|RTF_EXPIRES);
 		}
-	} else if (pinfo->onlink && valid_lft) {
-		addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len,
-				      dev, rt_expires, RTF_ADDRCONF|RTF_EXPIRES);
+		if (rt)
+			dst_release(&rt->u.dst);
 	}
-	if (rt)
-		dst_release(&rt->u.dst);
 
 	/* Try to figure out our local address for this prefix */
 
 	if (pinfo->autoconf && in6_dev->cnf.autoconf) {
 		struct inet6_ifaddr * ifp;
 		struct in6_addr addr;
-		int plen;
-		int create = 0;
-
-		plen = pinfo->prefix_len >> 3;
+		int create = 0, update_lft = 0;
 
 		if (pinfo->prefix_len == 64) {
 			memcpy(&addr, &pinfo->prefix, 8);
@@ -1415,32 +1414,54 @@
 				return;
 			}
 
-			create = 1;
+			update_lft = create = 1;
 			addrconf_dad_start(ifp);
 		}
 
-		if (ifp && valid_lft == 0) {
-			ipv6_del_addr(ifp);
-			ifp = NULL;
-		}
-
 		if (ifp) {
 			int flags;
+			unsigned long now;
 #ifdef CONFIG_IPV6_PRIVACY
 			struct inet6_ifaddr *ift;
 #endif
+			u32 stored_lft;
 
+			/* update lifetime (RFC2462 5.5.3 e) */
 			spin_lock(&ifp->lock);
-			ifp->valid_lft = valid_lft;
-			ifp->prefered_lft = prefered_lft;
-			ifp->tstamp = jiffies;
-			flags = ifp->flags;
-			ifp->flags &= ~IFA_F_DEPRECATED;
-			spin_unlock(&ifp->lock);
-
-			if (!(flags&IFA_F_TENTATIVE))
-				ipv6_ifa_notify((flags&IFA_F_DEPRECATED) ?
-						0 : RTM_NEWADDR, ifp);
+			now = jiffies;
+			if (ifp->valid_lft > (now - ifp->tstamp) / HZ)
+				stored_lft = ifp->valid_lft - (now - ifp->tstamp) / HZ;
+			else
+				stored_lft = 0;
+			if (!update_lft && stored_lft) {
+				if (valid_lft > MIN_VALID_LIFETIME ||
+				    valid_lft > stored_lft)
+					update_lft = 1;
+				else if (stored_lft <= MIN_VALID_LIFETIME) {
+					/* valid_lft <= stored_lft is always true */
+					/* XXX: IPsec */
+					update_lft = 0;
+				} else {
+					valid_lft = MIN_VALID_LIFETIME;
+					if (valid_lft < prefered_lft)
+						prefered_lft = valid_lft;
+					update_lft = 1;
+				}
+			}
+
+			if (update_lft) {
+				ifp->valid_lft = valid_lft;
+				ifp->prefered_lft = prefered_lft;
+				ifp->tstamp = now;
+				flags = ifp->flags;
+				ifp->flags &= ~IFA_F_DEPRECATED;
+				spin_unlock(&ifp->lock);
+
+				if (!(flags&IFA_F_TENTATIVE))
+					ipv6_ifa_notify((flags&IFA_F_DEPRECATED) ?
+							0 : RTM_NEWADDR, ifp);
+			} else
+				spin_unlock(&ifp->lock);
 
 #ifdef CONFIG_IPV6_PRIVACY
 			read_lock_bh(&in6_dev->lock);
diff -urN linux-2.5.74-bk7/net/ipv6/ip6_output.c linux-2.5.74-bk8/net/ipv6/ip6_output.c
--- linux-2.5.74-bk7/net/ipv6/ip6_output.c	2003-07-02 13:40:32.000000000 -0700
+++ linux-2.5.74-bk8/net/ipv6/ip6_output.c	2003-07-10 04:38:35.000000000 -0700
@@ -1239,7 +1239,6 @@
 			memcpy(np->cork.opt, opt, opt->tot_len);
 			inet->cork.flags |= IPCORK_OPT;
 			/* need source address above miyazawa*/
-			exthdrlen += opt->opt_flen ? opt->opt_flen : 0;
 		}
 		dst_hold(&rt->u.dst);
 		np->cork.rt = rt;
@@ -1252,6 +1251,7 @@
 			length += exthdrlen;
 			transhdrlen += exthdrlen;
 		}
+		exthdrlen += opt ? opt->opt_flen : 0;
 	} else {
 		rt = np->cork.rt;
 		if (inet->cork.flags & IPCORK_OPT)
diff -urN linux-2.5.74-bk7/net/ipv6/proc.c linux-2.5.74-bk8/net/ipv6/proc.c
--- linux-2.5.74-bk7/net/ipv6/proc.c	2003-07-02 13:46:13.000000000 -0700
+++ linux-2.5.74-bk8/net/ipv6/proc.c	2003-07-10 04:38:35.000000000 -0700
@@ -229,7 +229,7 @@
 		return -EINVAL;
 
 	if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib),
-			   __alignof__(struct ipv6_mib)) < 0)
+			   __alignof__(struct icmpv6_mib)) < 0)
 		goto err_icmp;
 
 #ifdef CONFIG_PROC_FS
diff -urN linux-2.5.74-bk7/net/ipv6/raw.c linux-2.5.74-bk8/net/ipv6/raw.c
--- linux-2.5.74-bk7/net/ipv6/raw.c	2003-07-10 04:38:32.000000000 -0700
+++ linux-2.5.74-bk8/net/ipv6/raw.c	2003-07-10 04:38:35.000000000 -0700
@@ -624,6 +624,7 @@
 	if (msg->msg_controllen) {
 		opt = &opt_space;
 		memset(opt, 0, sizeof(struct ipv6_txoptions));
+		opt->tot_len = sizeof(struct ipv6_txoptions);
 
 		err = datagram_send_ctl(msg, &fl, opt, &hlimit);
 		if (err < 0) {
diff -urN linux-2.5.74-bk7/net/ipv6/route.c linux-2.5.74-bk8/net/ipv6/route.c
--- linux-2.5.74-bk7/net/ipv6/route.c	2003-07-02 13:52:44.000000000 -0700
+++ linux-2.5.74-bk8/net/ipv6/route.c	2003-07-10 04:38:35.000000000 -0700
@@ -602,6 +602,8 @@
 
 static inline unsigned int ipv6_advmss(unsigned int mtu)
 {
+	mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr);
+
 	if (mtu < ip6_rt_min_advmss)
 		mtu = ip6_rt_min_advmss;
 
diff -urN linux-2.5.74-bk7/net/key/af_key.c linux-2.5.74-bk8/net/key/af_key.c
--- linux-2.5.74-bk7/net/key/af_key.c	2003-07-02 13:43:40.000000000 -0700
+++ linux-2.5.74-bk8/net/key/af_key.c	2003-07-10 04:38:35.000000000 -0700
@@ -1989,9 +1989,7 @@
 	err = 0;
 
 out:
-	if (xp) {
-		xfrm_policy_kill(xp);
-	}
+	xfrm_pol_put(xp);
 	return err;
 }
 
@@ -2031,12 +2029,7 @@
 	err = 0;
 
 out:
-	if (xp) {
-		if (hdr->sadb_msg_type == SADB_X_SPDDELETE2)
-			xfrm_policy_kill(xp);
-		else
-			xfrm_pol_put(xp);
-	}
+	xfrm_pol_put(xp);
 	return err;
 }
 
diff -urN linux-2.5.74-bk7/net/netsyms.c linux-2.5.74-bk8/net/netsyms.c
--- linux-2.5.74-bk7/net/netsyms.c	2003-07-02 13:46:16.000000000 -0700
+++ linux-2.5.74-bk8/net/netsyms.c	2003-07-10 04:38:35.000000000 -0700
@@ -641,6 +641,7 @@
 #ifdef CONFIG_NET_SCHED
 PSCHED_EXPORTLIST;
 EXPORT_SYMBOL(pfifo_qdisc_ops);
+EXPORT_SYMBOL(bfifo_qdisc_ops);
 EXPORT_SYMBOL(register_qdisc);
 EXPORT_SYMBOL(unregister_qdisc);
 EXPORT_SYMBOL(qdisc_get_rtab);
diff -urN linux-2.5.74-bk7/net/packet/af_packet.c linux-2.5.74-bk8/net/packet/af_packet.c
--- linux-2.5.74-bk7/net/packet/af_packet.c	2003-07-02 13:50:51.000000000 -0700
+++ linux-2.5.74-bk8/net/packet/af_packet.c	2003-07-10 04:38:35.000000000 -0700
@@ -1368,8 +1368,13 @@
 		struct packet_opt *po = pkt_sk(sk);
 
 		switch (msg) {
-		case NETDEV_DOWN:
 		case NETDEV_UNREGISTER:
+#ifdef CONFIG_PACKET_MULTICAST
+			if (po->mclist)
+				packet_dev_mclist(dev, po->mclist, -1);
+			// fallthrough
+#endif
+		case NETDEV_DOWN:
 			if (dev->ifindex == po->ifindex) {
 				spin_lock(&po->bind_lock);
 				if (po->running) {
@@ -1386,10 +1391,6 @@
 				}
 				spin_unlock(&po->bind_lock);
 			}
-#ifdef CONFIG_PACKET_MULTICAST
-			if (po->mclist)
-				packet_dev_mclist(dev, po->mclist, -1);
-#endif
 			break;
 		case NETDEV_UP:
 			spin_lock(&po->bind_lock);
@@ -1400,10 +1401,6 @@
 				po->running = 1;
 			}
 			spin_unlock(&po->bind_lock);
-#ifdef CONFIG_PACKET_MULTICAST
-			if (po->mclist)
-				packet_dev_mclist(dev, po->mclist, +1);
-#endif
 			break;
 		}
 	}
diff -urN linux-2.5.74-bk7/net/sched/sch_atm.c linux-2.5.74-bk8/net/sched/sch_atm.c
--- linux-2.5.74-bk7/net/sched/sch_atm.c	2003-07-02 13:46:55.000000000 -0700
+++ linux-2.5.74-bk8/net/sched/sch_atm.c	2003-07-10 04:38:35.000000000 -0700
@@ -545,15 +545,16 @@
 }
 
 
-static int atm_tc_drop(struct Qdisc *sch)
+static unsigned int atm_tc_drop(struct Qdisc *sch)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
 	struct atm_flow_data *flow;
+	unsigned int len;
 
 	DPRINTK("atm_tc_drop(sch %p,[qdisc %p])\n",sch,p);
 	for (flow = p->flows; flow; flow = flow->next)
-		if (flow->q->ops->drop && flow->q->ops->drop(flow->q))
-			return 1;
+		if (flow->q->ops->drop && (len = flow->q->ops->drop(flow->q)))
+			return len;
 	return 0;
 }
 
diff -urN linux-2.5.74-bk7/net/sched/sch_cbq.c linux-2.5.74-bk8/net/sched/sch_cbq.c
--- linux-2.5.74-bk7/net/sched/sch_cbq.c	2003-07-02 13:41:13.000000000 -0700
+++ linux-2.5.74-bk8/net/sched/sch_cbq.c	2003-07-10 04:38:35.000000000 -0700
@@ -1231,11 +1231,12 @@
 	}
 }
 
-static int cbq_drop(struct Qdisc* sch)
+static unsigned int cbq_drop(struct Qdisc* sch)
 {
 	struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data;
 	struct cbq_class *cl, *cl_head;
 	int prio;
+	unsigned int len;
 
 	for (prio = TC_CBQ_MAXPRIO; prio >= 0; prio--) {
 		if ((cl_head = q->active[prio]) == NULL)
@@ -1243,9 +1244,9 @@
 
 		cl = cl_head;
 		do {
-			if (cl->q->ops->drop && cl->q->ops->drop(cl->q)) {
+			if (cl->q->ops->drop && (len = cl->q->ops->drop(cl->q))) {
 				sch->q.qlen--;
-				return 1;
+				return len;
 			}
 		} while ((cl = cl->next_alive) != cl_head);
 	}
diff -urN linux-2.5.74-bk7/net/sched/sch_dsmark.c linux-2.5.74-bk8/net/sched/sch_dsmark.c
--- linux-2.5.74-bk7/net/sched/sch_dsmark.c	2003-07-02 13:42:03.000000000 -0700
+++ linux-2.5.74-bk8/net/sched/sch_dsmark.c	2003-07-10 04:38:35.000000000 -0700
@@ -302,17 +302,18 @@
 }
 
 
-static int dsmark_drop(struct Qdisc *sch)
+static unsigned int dsmark_drop(struct Qdisc *sch)
 {
 	struct dsmark_qdisc_data *p = PRIV(sch);
-
+	unsigned int len;
+	
 	DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n",sch,p);
 	if (!p->q->ops->drop)
 		return 0;
-	if (!p->q->ops->drop(p->q))
+	if (!(len = p->q->ops->drop(p->q)))
 		return 0;
 	sch->q.qlen--;
-	return 1;
+	return len;
 }
 
 
diff -urN linux-2.5.74-bk7/net/sched/sch_fifo.c linux-2.5.74-bk8/net/sched/sch_fifo.c
--- linux-2.5.74-bk7/net/sched/sch_fifo.c	2003-07-02 13:42:52.000000000 -0700
+++ linux-2.5.74-bk8/net/sched/sch_fifo.c	2003-07-10 04:38:35.000000000 -0700
@@ -81,16 +81,17 @@
 	return skb;
 }
 
-static int
+static unsigned int 
 fifo_drop(struct Qdisc* sch)
 {
 	struct sk_buff *skb;
 
 	skb = __skb_dequeue_tail(&sch->q);
 	if (skb) {
-		sch->stats.backlog -= skb->len;
+		unsigned int len = skb->len;
+		sch->stats.backlog -= len;
 		kfree_skb(skb);
-		return 1;
+		return len;
 	}
 	return 0;
 }
diff -urN linux-2.5.74-bk7/net/sched/sch_gred.c linux-2.5.74-bk8/net/sched/sch_gred.c
--- linux-2.5.74-bk7/net/sched/sch_gred.c	2003-07-02 13:54:39.000000000 -0700
+++ linux-2.5.74-bk8/net/sched/sch_gred.c	2003-07-10 04:38:35.000000000 -0700
@@ -259,8 +259,7 @@
 	return NULL;
 }
 
-static int
-gred_drop(struct Qdisc* sch)
+static unsigned int gred_drop(struct Qdisc* sch)
 {
 	struct sk_buff *skb;
 
@@ -269,20 +268,21 @@
 
 	skb = __skb_dequeue_tail(&sch->q);
 	if (skb) {
-		sch->stats.backlog -= skb->len;
+		unsigned int len = skb->len;
+		sch->stats.backlog -= len;
 		sch->stats.drops++;
 		q= t->tab[(skb->tc_index&0xf)];
 		if (q) {
-			q->backlog -= skb->len;
+			q->backlog -= len;
 			q->other++;
 			if (!q->backlog && !t->eqp)
 				PSCHED_GET_TIME(q->qidlestart);
-			} else {
-				D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",skb->tc_index&0xf); 
-			}
+		} else {
+			D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",skb->tc_index&0xf); 
+		}
 
 		kfree_skb(skb);
-		return 1;
+		return len;
 	}
 
 	q=t->tab[t->def];
diff -urN linux-2.5.74-bk7/net/sched/sch_htb.c linux-2.5.74-bk8/net/sched/sch_htb.c
--- linux-2.5.74-bk7/net/sched/sch_htb.c	2003-07-02 13:50:07.000000000 -0700
+++ linux-2.5.74-bk8/net/sched/sch_htb.c	2003-07-10 04:38:35.000000000 -0700
@@ -1059,7 +1059,7 @@
 }
 
 /* try to drop from each class (by prio) until one succeed */
-static int htb_drop(struct Qdisc* sch)
+static unsigned int htb_drop(struct Qdisc* sch)
 {
 	struct htb_sched *q = (struct htb_sched *)sch->data;
 	int prio;
@@ -1067,14 +1067,15 @@
 	for (prio = TC_HTB_NUMPRIO - 1; prio >= 0; prio--) {
 		struct list_head *p;
 		list_for_each (p,q->drops+prio) {
-			struct htb_class *cl = list_entry(p,struct htb_class,
-					un.leaf.drop_list);
+			struct htb_class *cl = list_entry(p, struct htb_class,
+							  un.leaf.drop_list);
+			unsigned int len;
 			if (cl->un.leaf.q->ops->drop && 
-				cl->un.leaf.q->ops->drop(cl->un.leaf.q)) {
+				(len = cl->un.leaf.q->ops->drop(cl->un.leaf.q))) {
 				sch->q.qlen--;
 				if (!cl->un.leaf.q->q.qlen)
 					htb_deactivate (q,cl);
-				return 1;
+				return len;
 			}
 		}
 	}
diff -urN linux-2.5.74-bk7/net/sched/sch_ingress.c linux-2.5.74-bk8/net/sched/sch_ingress.c
--- linux-2.5.74-bk7/net/sched/sch_ingress.c	2003-07-02 13:52:59.000000000 -0700
+++ linux-2.5.74-bk8/net/sched/sch_ingress.c	2003-07-10 04:38:35.000000000 -0700
@@ -190,7 +190,7 @@
 	return 0;
 }
 
-static int ingress_drop(struct Qdisc *sch)
+static unsigned int ingress_drop(struct Qdisc *sch)
 {
 #ifdef DEBUG_INGRESS
 	struct ingress_qdisc_data *p = PRIV(sch);
diff -urN linux-2.5.74-bk7/net/sched/sch_prio.c linux-2.5.74-bk8/net/sched/sch_prio.c
--- linux-2.5.74-bk7/net/sched/sch_prio.c	2003-07-02 13:46:17.000000000 -0700
+++ linux-2.5.74-bk8/net/sched/sch_prio.c	2003-07-10 04:38:35.000000000 -0700
@@ -124,18 +124,18 @@
 
 }
 
-static int
-prio_drop(struct Qdisc* sch)
+static unsigned int prio_drop(struct Qdisc* sch)
 {
 	struct prio_sched_data *q = (struct prio_sched_data *)sch->data;
 	int prio;
+	unsigned int len;
 	struct Qdisc *qdisc;
 
 	for (prio = q->bands-1; prio >= 0; prio--) {
 		qdisc = q->queues[prio];
-		if (qdisc->ops->drop(qdisc)) {
+		if ((len = qdisc->ops->drop(qdisc)) != 0) {
 			sch->q.qlen--;
-			return 1;
+			return len;
 		}
 	}
 	return 0;
diff -urN linux-2.5.74-bk7/net/sched/sch_red.c linux-2.5.74-bk8/net/sched/sch_red.c
--- linux-2.5.74-bk7/net/sched/sch_red.c	2003-07-02 13:57:35.000000000 -0700
+++ linux-2.5.74-bk8/net/sched/sch_red.c	2003-07-10 04:38:35.000000000 -0700
@@ -342,19 +342,19 @@
 	return NULL;
 }
 
-static int
-red_drop(struct Qdisc* sch)
+static unsigned int red_drop(struct Qdisc* sch)
 {
 	struct sk_buff *skb;
 	struct red_sched_data *q = (struct red_sched_data *)sch->data;
 
 	skb = __skb_dequeue_tail(&sch->q);
 	if (skb) {
-		sch->stats.backlog -= skb->len;
+		unsigned int len = skb->len;
+		sch->stats.backlog -= len;
 		sch->stats.drops++;
 		q->st.other++;
 		kfree_skb(skb);
-		return 1;
+		return len;
 	}
 	PSCHED_GET_TIME(q->qidlestart);
 	return 0;
diff -urN linux-2.5.74-bk7/net/sched/sch_sfq.c linux-2.5.74-bk8/net/sched/sch_sfq.c
--- linux-2.5.74-bk7/net/sched/sch_sfq.c	2003-07-02 13:56:01.000000000 -0700
+++ linux-2.5.74-bk8/net/sched/sch_sfq.c	2003-07-10 04:38:35.000000000 -0700
@@ -209,11 +209,12 @@
 	sfq_link(q, x);
 }
 
-static int sfq_drop(struct Qdisc *sch)
+static unsigned int sfq_drop(struct Qdisc *sch)
 {
 	struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data;
 	sfq_index d = q->max_depth;
 	struct sk_buff *skb;
+	unsigned int len;
 
 	/* Queue is full! Find the longest slot and
 	   drop a packet from it */
@@ -221,12 +222,13 @@
 	if (d > 1) {
 		sfq_index x = q->dep[d+SFQ_DEPTH].next;
 		skb = q->qs[x].prev;
+		len = skb->len;
 		__skb_unlink(skb, &q->qs[x]);
 		kfree_skb(skb);
 		sfq_dec(q, x);
 		sch->q.qlen--;
 		sch->stats.drops++;
-		return 1;
+		return len;
 	}
 
 	if (d == 1) {
@@ -235,13 +237,14 @@
 		q->next[q->tail] = q->next[d];
 		q->allot[q->next[d]] += q->quantum;
 		skb = q->qs[d].prev;
+		len = skb->len;
 		__skb_unlink(skb, &q->qs[d]);
 		kfree_skb(skb);
 		sfq_dec(q, d);
 		sch->q.qlen--;
 		q->ht[q->hash[d]] = SFQ_DEPTH;
 		sch->stats.drops++;
-		return 1;
+		return len;
 	}
 
 	return 0;
diff -urN linux-2.5.74-bk7/net/sched/sch_tbf.c linux-2.5.74-bk8/net/sched/sch_tbf.c
--- linux-2.5.74-bk7/net/sched/sch_tbf.c	2003-07-02 13:40:31.000000000 -0700
+++ linux-2.5.74-bk8/net/sched/sch_tbf.c	2003-07-10 04:38:35.000000000 -0700
@@ -7,6 +7,8 @@
  *		2 of the License, or (at your option) any later version.
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *		Dmitry Torokhov <dtor@mail.ru> - allow attaching inner qdiscs -
+ *						 original idea by Martin Devera
  *
  */
 
@@ -123,62 +125,63 @@
 	long	ptokens;		/* Current number of P tokens */
 	psched_time_t	t_c;		/* Time check-point */
 	struct timer_list wd_timer;	/* Watchdog timer */
+	struct Qdisc	*qdisc;		/* Inner qdisc, default - bfifo queue */
 };
 
 #define L2T(q,L)   ((q)->R_tab->data[(L)>>(q)->R_tab->rate.cell_log])
 #define L2T_P(q,L) ((q)->P_tab->data[(L)>>(q)->P_tab->rate.cell_log])
 
-static int
-tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 {
 	struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+	int ret;
 
-	if (skb->len > q->max_size)
-		goto drop;
-	__skb_queue_tail(&sch->q, skb);
-	if ((sch->stats.backlog += skb->len) <= q->limit) {
-		sch->stats.bytes += skb->len;
-		sch->stats.packets++;
-		return 0;
-	}
-
-	/* Drop action: undo the things that we just did,
-	 * i.e. make tail drop
-	 */
-
-	__skb_unlink(skb, &sch->q);
-	sch->stats.backlog -= skb->len;
-
-drop:
-	sch->stats.drops++;
+	if (skb->len > q->max_size || sch->stats.backlog + skb->len > q->limit) {
+		sch->stats.drops++;
 #ifdef CONFIG_NET_CLS_POLICE
-	if (sch->reshape_fail==NULL || sch->reshape_fail(skb, sch))
+		if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch))
 #endif
-		kfree_skb(skb);
-	return NET_XMIT_DROP;
-}
-
-static int
-tbf_requeue(struct sk_buff *skb, struct Qdisc* sch)
-{
-	__skb_queue_head(&sch->q, skb);
+			kfree_skb(skb);
+	
+		return NET_XMIT_DROP;
+	}
+	
+	if ((ret = q->qdisc->enqueue(skb, q->qdisc)) != 0) {
+		sch->stats.drops++;
+		return ret;
+	}	
+	
+	sch->q.qlen++;
 	sch->stats.backlog += skb->len;
+	sch->stats.bytes += skb->len;
+	sch->stats.packets++;
 	return 0;
 }
 
-static int
-tbf_drop(struct Qdisc* sch)
+static int tbf_requeue(struct sk_buff *skb, struct Qdisc* sch)
 {
-	struct sk_buff *skb;
+	struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+	int ret;
+	
+	if ((ret = q->qdisc->ops->requeue(skb, q->qdisc)) == 0) {
+		sch->q.qlen++; 
+		sch->stats.backlog += skb->len;
+	}
+	
+	return ret;
+}
 
-	skb = __skb_dequeue_tail(&sch->q);
-	if (skb) {
-		sch->stats.backlog -= skb->len;
+static unsigned int tbf_drop(struct Qdisc* sch)
+{
+	struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+	unsigned int len;
+	
+	if ((len = q->qdisc->ops->drop(q->qdisc)) != 0) {
+		sch->q.qlen--;
+		sch->stats.backlog -= len;
 		sch->stats.drops++;
-		kfree_skb(skb);
-		return 1;
 	}
-	return 0;
+	return len;
 }
 
 static void tbf_watchdog(unsigned long arg)
@@ -189,19 +192,19 @@
 	netif_schedule(sch->dev);
 }
 
-static struct sk_buff *
-tbf_dequeue(struct Qdisc* sch)
+static struct sk_buff *tbf_dequeue(struct Qdisc* sch)
 {
 	struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
 	struct sk_buff *skb;
 	
-	skb = __skb_dequeue(&sch->q);
+	skb = q->qdisc->dequeue(q->qdisc);
 
 	if (skb) {
 		psched_time_t now;
 		long toks;
 		long ptoks = 0;
-
+		unsigned int len = skb->len;
+		
 		PSCHED_GET_TIME(now);
 
 		toks = PSCHED_TDIFF_SAFE(now, q->t_c, q->buffer, 0);
@@ -210,18 +213,19 @@
 			ptoks = toks + q->ptokens;
 			if (ptoks > (long)q->mtu)
 				ptoks = q->mtu;
-			ptoks -= L2T_P(q, skb->len);
+			ptoks -= L2T_P(q, len);
 		}
 		toks += q->tokens;
 		if (toks > (long)q->buffer)
 			toks = q->buffer;
-		toks -= L2T(q, skb->len);
+		toks -= L2T(q, len);
 
 		if ((toks|ptoks) >= 0) {
 			q->t_c = now;
 			q->tokens = toks;
 			q->ptokens = ptoks;
-			sch->stats.backlog -= skb->len;
+			sch->stats.backlog -= len;
+			sch->q.qlen--;
 			sch->flags &= ~TCQ_F_THROTTLED;
 			return skb;
 		}
@@ -245,20 +249,25 @@
 		   This is the main idea of all FQ algorithms
 		   (cf. CSZ, HPFQ, HFSC)
 		 */
-		__skb_queue_head(&sch->q, skb);
-
+		
+		if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
+			/* When requeue fails skb is dropped */ 
+			sch->q.qlen--;
+			sch->stats.backlog -= len;
+			sch->stats.drops++;
+		}	
+		
 		sch->flags |= TCQ_F_THROTTLED;
 		sch->stats.overlimits++;
 	}
 	return NULL;
 }
 
-
-static void
-tbf_reset(struct Qdisc* sch)
+static void tbf_reset(struct Qdisc* sch)
 {
 	struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
 
+	qdisc_reset(q->qdisc);
 	skb_queue_purge(&sch->q);
 	sch->stats.backlog = 0;
 	PSCHED_GET_TIME(q->t_c);
@@ -268,6 +277,31 @@
 	del_timer(&q->wd_timer);
 }
 
+static struct Qdisc *tbf_create_dflt_qdisc(struct net_device *dev, u32 limit)
+{
+	struct Qdisc *q = qdisc_create_dflt(dev, &bfifo_qdisc_ops);
+        struct rtattr *rta;
+	int ret;
+	
+	if (q) {
+		rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL);
+		if (rta) {
+			rta->rta_type = RTM_NEWQDISC;
+			rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt)); 
+			((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit;
+			
+			ret = q->ops->change(q, rta);
+			kfree(rta);
+			
+			if (ret == 0)
+				return q;
+		}
+		qdisc_destroy(q);
+	}
+
+	return NULL;	
+}
+
 static int tbf_change(struct Qdisc* sch, struct rtattr *opt)
 {
 	int err = -EINVAL;
@@ -276,6 +310,7 @@
 	struct tc_tbf_qopt *qopt;
 	struct qdisc_rate_table *rtab = NULL;
 	struct qdisc_rate_table *ptab = NULL;
+	struct Qdisc *child = NULL;
 	int max_size,n;
 
 	if (rtattr_parse(tb, TCA_TBF_PTAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) ||
@@ -308,8 +343,14 @@
 	}
 	if (max_size < 0)
 		goto done;
+	
+	if (q->qdisc == &noop_qdisc) {
+		if ((child = tbf_create_dflt_qdisc(sch->dev, qopt->limit)) == NULL)
+			goto done;
+	}
 
 	sch_tree_lock(sch);
+	if (child) q->qdisc = child;
 	q->limit = qopt->limit;
 	q->mtu = qopt->mtu;
 	q->max_size = max_size;
@@ -339,6 +380,8 @@
 	init_timer(&q->wd_timer);
 	q->wd_timer.function = tbf_watchdog;
 	q->wd_timer.data = (unsigned long)sch;
+
+	q->qdisc = &noop_qdisc;
 	
 	return tbf_change(sch, opt);
 }
@@ -353,6 +396,9 @@
 		qdisc_put_rtab(q->P_tab);
 	if (q->R_tab)
 		qdisc_put_rtab(q->R_tab);
+	
+	qdisc_destroy(q->qdisc);
+	q->qdisc = &noop_qdisc;
 }
 
 static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb)
@@ -383,9 +429,92 @@
 	return -1;
 }
 
+static int tbf_dump_class(struct Qdisc *sch, unsigned long cl,
+	       		  struct sk_buff *skb, struct tcmsg *tcm)
+{
+	struct tbf_sched_data *q = (struct tbf_sched_data*)sch->data;
+
+	if (cl != 1) 	/* only one class */ 
+		return -ENOENT;
+    
+	tcm->tcm_parent = TC_H_ROOT;
+	tcm->tcm_handle = 1;
+	tcm->tcm_info = q->qdisc->handle;
+
+	return 0;
+}
+
+static int tbf_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
+		     struct Qdisc **old)
+{
+	struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+
+	if (new == NULL)
+		new = &noop_qdisc;
+
+	sch_tree_lock(sch);	
+	*old = xchg(&q->qdisc, new);
+	qdisc_reset(*old);
+	sch_tree_unlock(sch);
+	
+	return 0;
+}
+
+static struct Qdisc *tbf_leaf(struct Qdisc *sch, unsigned long arg)
+{
+	struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+	return q->qdisc;
+}
+
+static unsigned long tbf_get(struct Qdisc *sch, u32 classid)
+{
+	return 1;
+}
+
+static void tbf_put(struct Qdisc *sch, unsigned long arg)
+{
+}
+
+static int tbf_change_class(struct Qdisc *sch, u32 classid, u32 parentid, 
+			struct rtattr **tca, unsigned long *arg)
+{
+	return -ENOSYS;
+}
+
+static int tbf_delete(struct Qdisc *sch, unsigned long arg)
+{
+	return -ENOSYS;
+}
+
+static void tbf_walk(struct Qdisc *sch, struct qdisc_walker *walker)
+{
+	struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+
+	if (!walker->stop) {
+		if (walker->count >= walker->skip) 
+			if (walker->fn(sch, (unsigned long)q, walker) < 0) { 
+				walker->stop = 1;
+				return;
+			}
+		walker->count++;
+	}
+}
+
+static struct Qdisc_class_ops tbf_class_ops =
+{
+	.graft		= 	tbf_graft,
+	.leaf		=	tbf_leaf,
+	.get		=	tbf_get,
+	.put		=	tbf_put,
+	.change		=	tbf_change_class,
+	.delete		=	tbf_delete,
+	.walk		=	tbf_walk,
+	.dump		=	tbf_dump_class,
+};
+
 struct Qdisc_ops tbf_qdisc_ops = {
 	.next		=	NULL,
-	.cl_ops		=	NULL,
+	.cl_ops		=	&tbf_class_ops,
 	.id		=	"tbf",
 	.priv_size	=	sizeof(struct tbf_sched_data),
 	.enqueue	=	tbf_enqueue,
@@ -397,6 +526,7 @@
 	.destroy	=	tbf_destroy,
 	.change		=	tbf_change,
 	.dump		=	tbf_dump,
+	.owner		=	THIS_MODULE,
 };
 
 
diff -urN linux-2.5.74-bk7/net/xfrm/xfrm_policy.c linux-2.5.74-bk8/net/xfrm/xfrm_policy.c
--- linux-2.5.74-bk7/net/xfrm/xfrm_policy.c	2003-07-02 13:48:08.000000000 -0700
+++ linux-2.5.74-bk8/net/xfrm/xfrm_policy.c	2003-07-10 04:38:35.000000000 -0700
@@ -80,22 +80,24 @@
 
 struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family)
 {
-	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
+	struct xfrm_policy_afinfo *afinfo;
 	struct xfrm_type_map *typemap;
 	struct xfrm_type *type;
 	int modload_attempted = 0;
 
+retry:
+	afinfo = xfrm_policy_get_afinfo(family);
 	if (unlikely(afinfo == NULL))
 		return NULL;
 	typemap = afinfo->type_map;
 
-retry:
 	read_lock(&typemap->lock);
 	type = typemap->map[proto];
 	if (unlikely(type && !try_module_get(type->owner)))
 		type = NULL;
 	read_unlock(&typemap->lock);
 	if (!type && !modload_attempted) {
+		xfrm_policy_put_afinfo(afinfo);
 		request_module("xfrm-type-%d-%d",
 			       (int) family, (int) proto);
 		modload_attempted = 1;
@@ -141,11 +143,14 @@
 	struct xfrm_policy *xp = (struct xfrm_policy*)data;
 	unsigned long now = (unsigned long)xtime.tv_sec;
 	long next = LONG_MAX;
-	u32 index;
+	int warn = 0;
+	int dir;
 
 	if (xp->dead)
 		goto out;
 
+	dir = xp->index & 7;
+
 	if (xp->lft.hard_add_expires_seconds) {
 		long tmo = xp->lft.hard_add_expires_seconds +
 			xp->curlft.add_time - now;
@@ -154,6 +159,37 @@
 		if (tmo < next)
 			next = tmo;
 	}
+	if (xp->lft.hard_use_expires_seconds) {
+		long tmo = xp->lft.hard_use_expires_seconds +
+			(xp->curlft.use_time ? : xp->curlft.add_time) - now;
+		if (tmo <= 0)
+			goto expired;
+		if (tmo < next)
+			next = tmo;
+	}
+	if (xp->lft.soft_add_expires_seconds) {
+		long tmo = xp->lft.soft_add_expires_seconds +
+			xp->curlft.add_time - now;
+		if (tmo <= 0) {
+			warn = 1;
+			tmo = XFRM_KM_TIMEOUT;
+		}
+		if (tmo < next)
+			next = tmo;
+	}
+	if (xp->lft.soft_use_expires_seconds) {
+		long tmo = xp->lft.soft_use_expires_seconds +
+			(xp->curlft.use_time ? : xp->curlft.add_time) - now;
+		if (tmo <= 0) {
+			warn = 1;
+			tmo = XFRM_KM_TIMEOUT;
+		}
+		if (tmo < next)
+			next = tmo;
+	}
+
+	if (warn)
+		km_policy_expired(xp, dir, 0);
 	if (next != LONG_MAX &&
 	    !mod_timer(&xp->timer, jiffies + make_jiffies(next)))
 		xfrm_pol_hold(xp);
@@ -163,14 +199,9 @@
 	return;
 
 expired:
-	index = xp->index;
+	km_policy_expired(xp, dir, 1);
+	xfrm_policy_delete(xp, dir);
 	xfrm_pol_put(xp);
-
-	/* Not 100% correct. id can be recycled in theory */
-	xp = xfrm_policy_byid(0, index, 1);
-	if (xp) {
-		xfrm_policy_kill(xp);
-	}
 }
 
 
@@ -321,8 +352,7 @@
 	policy->index = delpol ? delpol->index : xfrm_gen_index(dir);
 	policy->curlft.add_time = (unsigned long)xtime.tv_sec;
 	policy->curlft.use_time = 0;
-	if (policy->lft.hard_add_expires_seconds &&
-	    !mod_timer(&policy->timer, jiffies + HZ))
+	if (!mod_timer(&policy->timer, jiffies + HZ))
 		xfrm_pol_hold(policy);
 	write_unlock_bh(&xfrm_policy_lock);
 
@@ -340,18 +370,18 @@
 	write_lock_bh(&xfrm_policy_lock);
 	for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) {
 		if (memcmp(sel, &pol->selector, sizeof(*sel)) == 0) {
+			xfrm_pol_hold(pol);
 			if (delete)
 				*p = pol->next;
 			break;
 		}
 	}
-	if (pol) {
-		if (delete)
-			atomic_inc(&flow_cache_genid);
-		else
-			xfrm_pol_hold(pol);
-	}
 	write_unlock_bh(&xfrm_policy_lock);
+
+	if (pol && delete) {
+		atomic_inc(&flow_cache_genid);
+		xfrm_policy_kill(pol);
+	}
 	return pol;
 }
 
@@ -362,18 +392,18 @@
 	write_lock_bh(&xfrm_policy_lock);
 	for (p = &xfrm_policy_list[id & 7]; (pol=*p)!=NULL; p = &pol->next) {
 		if (pol->index == id) {
+			xfrm_pol_hold(pol);
 			if (delete)
 				*p = pol->next;
 			break;
 		}
 	}
-	if (pol) {
-		if (delete)
-			atomic_inc(&flow_cache_genid);
-		else
-			xfrm_pol_hold(pol);
-	}
 	write_unlock_bh(&xfrm_policy_lock);
+
+	if (pol && delete) {
+		atomic_inc(&flow_cache_genid);
+		xfrm_policy_kill(pol);
+	}
 	return pol;
 }
 
@@ -473,25 +503,36 @@
 	return pol;
 }
 
-void xfrm_sk_policy_link(struct xfrm_policy *pol, int dir)
+static void __xfrm_policy_link(struct xfrm_policy *pol, int dir)
 {
-	pol->next = xfrm_policy_list[XFRM_POLICY_MAX+dir];
-	xfrm_policy_list[XFRM_POLICY_MAX+dir] = pol;
+	pol->next = xfrm_policy_list[dir];
+	xfrm_policy_list[dir] = pol;
 	xfrm_pol_hold(pol);
 }
 
-void xfrm_sk_policy_unlink(struct xfrm_policy *pol, int dir)
+static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
+						int dir)
 {
 	struct xfrm_policy **polp;
 
-	for (polp = &xfrm_policy_list[XFRM_POLICY_MAX+dir];
+	for (polp = &xfrm_policy_list[dir];
 	     *polp != NULL; polp = &(*polp)->next) {
 		if (*polp == pol) {
 			*polp = pol->next;
 			atomic_dec(&pol->refcnt);
-			return;
+			return pol;
 		}
 	}
+	return NULL;
+}
+
+void xfrm_policy_delete(struct xfrm_policy *pol, int dir)
+{
+	write_lock_bh(&xfrm_policy_lock);
+	pol = __xfrm_policy_unlink(pol, dir);
+	write_unlock_bh(&xfrm_policy_lock);
+	if (pol)
+		xfrm_policy_kill(pol);
 }
 
 int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
@@ -504,10 +545,10 @@
 	if (pol) {
 		pol->curlft.add_time = (unsigned long)xtime.tv_sec;
 		pol->index = xfrm_gen_index(XFRM_POLICY_MAX+dir);
-		xfrm_sk_policy_link(pol, dir);
+		__xfrm_policy_link(pol, XFRM_POLICY_MAX+dir);
 	}
 	if (old_pol)
-		xfrm_sk_policy_unlink(old_pol, dir);
+		__xfrm_policy_unlink(old_pol, XFRM_POLICY_MAX+dir);
 	write_unlock_bh(&xfrm_policy_lock);
 
 	if (old_pol) {
@@ -531,7 +572,7 @@
 		memcpy(newp->xfrm_vec, old->xfrm_vec,
 		       newp->xfrm_nr*sizeof(struct xfrm_tmpl));
 		write_lock_bh(&xfrm_policy_lock);
-		xfrm_sk_policy_link(newp, dir);
+		__xfrm_policy_link(newp, XFRM_POLICY_MAX+dir);
 		write_unlock_bh(&xfrm_policy_lock);
 	}
 	return newp;
@@ -550,15 +591,6 @@
 	return 0;
 }
 
-void __xfrm_sk_free_policy(struct xfrm_policy *pol, int dir)
-{
-	write_lock_bh(&xfrm_policy_lock);
-	xfrm_sk_policy_unlink(pol, dir);
-	write_unlock_bh(&xfrm_policy_lock);
-
-	xfrm_policy_kill(pol);
-}
-
 /* Resolve list of templates for the flow, given policy. */
 
 static int
diff -urN linux-2.5.74-bk7/net/xfrm/xfrm_state.c linux-2.5.74-bk8/net/xfrm/xfrm_state.c
--- linux-2.5.74-bk7/net/xfrm/xfrm_state.c	2003-07-02 13:51:48.000000000 -0700
+++ linux-2.5.74-bk8/net/xfrm/xfrm_state.c	2003-07-10 04:38:35.000000000 -0700
@@ -140,7 +140,7 @@
 	}
 
 	if (warn)
-		km_warn_expired(x);
+		km_state_expired(x, 0);
 resched:
 	if (next != LONG_MAX &&
 	    !mod_timer(&x->timer, jiffies + make_jiffies(next)))
@@ -155,7 +155,7 @@
 		goto resched;
 	}
 	if (x->id.spi != 0)
-		km_expired(x);
+		km_state_expired(x, 1);
 	__xfrm_state_delete(x);
 
 out:
@@ -512,7 +512,7 @@
 
 	if (x->curlft.bytes >= x->lft.hard_byte_limit ||
 	    x->curlft.packets >= x->lft.hard_packet_limit) {
-		km_expired(x);
+		km_state_expired(x, 1);
 		if (!mod_timer(&x->timer, jiffies + XFRM_ACQ_EXPIRES*HZ))
 			xfrm_state_hold(x);
 		return -EINVAL;
@@ -521,7 +521,7 @@
 	if (!x->km.dying &&
 	    (x->curlft.bytes >= x->lft.soft_byte_limit ||
 	     x->curlft.packets >= x->lft.soft_packet_limit))
-		km_warn_expired(x);
+		km_state_expired(x, 0);
 	return 0;
 }
 
@@ -737,28 +737,22 @@
 static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list);
 static rwlock_t		xfrm_km_lock = RW_LOCK_UNLOCKED;
 
-void km_warn_expired(struct xfrm_state *x)
+void km_state_expired(struct xfrm_state *x, int hard)
 {
 	struct xfrm_mgr *km;
 
-	x->km.dying = 1;
-	read_lock(&xfrm_km_lock);
-	list_for_each_entry(km, &xfrm_km_list, list)
-		km->notify(x, 0);
-	read_unlock(&xfrm_km_lock);
-}
-
-void km_expired(struct xfrm_state *x)
-{
-	struct xfrm_mgr *km;
-
-	x->km.state = XFRM_STATE_EXPIRED;
+	if (hard)
+		x->km.state = XFRM_STATE_EXPIRED;
+	else
+		x->km.dying = 1;
 
 	read_lock(&xfrm_km_lock);
 	list_for_each_entry(km, &xfrm_km_list, list)
-		km->notify(x, 1);
+		km->notify(x, hard);
 	read_unlock(&xfrm_km_lock);
-	wake_up(&km_waitq);
+
+	if (hard)
+		wake_up(&km_waitq);
 }
 
 int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
@@ -792,6 +786,20 @@
 	return err;
 }
 
+void km_policy_expired(struct xfrm_policy *pol, int dir, int hard)
+{
+	struct xfrm_mgr *km;
+
+	read_lock(&xfrm_km_lock);
+	list_for_each_entry(km, &xfrm_km_list, list)
+		if (km->notify_policy)
+			km->notify_policy(pol, dir, hard);
+	read_unlock(&xfrm_km_lock);
+
+	if (hard)
+		wake_up(&km_waitq);
+}
+
 int xfrm_user_policy(struct sock *sk, int optname, u8 *optval, int optlen)
 {
 	int err;
diff -urN linux-2.5.74-bk7/net/xfrm/xfrm_user.c linux-2.5.74-bk8/net/xfrm/xfrm_user.c
--- linux-2.5.74-bk7/net/xfrm/xfrm_user.c	2003-07-02 13:49:16.000000000 -0700
+++ linux-2.5.74-bk8/net/xfrm/xfrm_user.c	2003-07-10 04:38:35.000000000 -0700
@@ -783,9 +783,7 @@
 	if (xp == NULL)
 		return -ENOENT;
 
-	if (delete)
-		xfrm_policy_kill(xp);
-	else {
+	if (!delete) {
 		struct sk_buff *resp_skb;
 
 		resp_skb = xfrm_policy_netlink(skb, xp, p->dir, nlh->nlmsg_seq);
@@ -796,9 +794,10 @@
 					      NETLINK_CB(skb).pid,
 					      MSG_DONTWAIT);
 		}
-		xfrm_pol_put(xp);
 	}
 
+	xfrm_pol_put(xp);
+
 	return err;
 }
 
@@ -994,7 +993,7 @@
 	return -1;
 }
 
-static int xfrm_send_notify(struct xfrm_state *x, int hard)
+static int xfrm_send_state_notify(struct xfrm_state *x, int hard)
 {
 	struct sk_buff *skb;
 
@@ -1120,11 +1119,56 @@
 	return xp;
 }
 
+static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
+			   int dir, int hard)
+{
+	struct xfrm_user_polexpire *upe;
+	struct nlmsghdr *nlh;
+	unsigned char *b = skb->tail;
+
+	nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_POLEXPIRE, sizeof(*upe));
+	upe = NLMSG_DATA(nlh);
+	nlh->nlmsg_flags = 0;
+
+	copy_to_user_policy(xp, &upe->pol, dir);
+	if (copy_to_user_tmpl(xp, skb) < 0)
+		goto nlmsg_failure;
+	upe->hard = !!hard;
+
+	nlh->nlmsg_len = skb->tail - b;
+	return skb->len;
+
+nlmsg_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard)
+{
+	struct sk_buff *skb;
+	size_t len;
+
+	len = sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr;
+	len = RTA_ALIGN(RTA_LENGTH(len));
+	len += NLMSG_ALIGN(NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info)));
+	skb = alloc_skb(len, GFP_ATOMIC);
+	if (skb == NULL)
+		return -ENOMEM;
+
+	if (build_polexpire(skb, xp, dir, hard) < 0)
+		BUG();
+
+	NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
+
+	return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
+}
+
 static struct xfrm_mgr netlink_mgr = {
 	.id		= "netlink",
-	.notify		= xfrm_send_notify,
+	.notify		= xfrm_send_state_notify,
 	.acquire	= xfrm_send_acquire,
 	.compile_policy	= xfrm_compile_policy,
+	.notify_policy	= xfrm_send_policy_notify,
 };
 
 static int __init xfrm_user_init(void)
