diff -Nru a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
--- a/Documentation/i2c/writing-clients	2004-09-14 13:15:14 -07:00
+++ b/Documentation/i2c/writing-clients	2005-01-23 09:21:47 -08:00
@@ -380,9 +380,6 @@
 
 For now, you can ignore the `flags' parameter. It is there for future use.
 
-  /* Unique ID allocation */
-  static int foo_id = 0;
-
   int foo_detect_client(struct i2c_adapter *adapter, int address, 
                         unsigned short flags, int kind)
   {
@@ -518,7 +515,6 @@
     data->type = kind;
     /* SENSORS ONLY END */
 
-    new_client->id = foo_id++; /* Automatically unique */
     data->valid = 0; /* Only if you use this field */
     init_MUTEX(&data->update_lock); /* Only if you use this field */
 
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	2005-01-07 09:23:24 -08:00
+++ b/MAINTAINERS	2005-01-25 21:31:50 -08:00
@@ -1532,7 +1532,7 @@
 
 PPP OVER ETHERNET
 P:	Michal Ostrowski
-M:	mostrows@styx.uwaterloo.ca
+M:	mostrows@speakeasy.net
 S:	Maintained
 
 PRISM54 WIRELESS DRIVER
diff -Nru a/Makefile b/Makefile
--- a/Makefile	2005-01-19 08:09:11 -08:00
+++ b/Makefile	2005-02-02 02:49:10 -08:00
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 29
-EXTRAVERSION =
+EXTRAVERSION = -bk8
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -Nru a/arch/i386/kernel/pci-irq.c b/arch/i386/kernel/pci-irq.c
--- a/arch/i386/kernel/pci-irq.c	2004-11-21 16:00:00 -08:00
+++ b/arch/i386/kernel/pci-irq.c	2005-01-30 22:36:10 -08:00
@@ -1120,7 +1120,7 @@
 void pcibios_enable_irq(struct pci_dev *dev)
 {
 	u8 pin;
-	extern int interrupt_line_quirk;
+	extern int via_interrupt_line_quirk;
  	struct pci_dev *temp_dev;
 	
 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
@@ -1173,7 +1173,7 @@
 	}
 	/* VIA bridges use interrupt line for apic/pci steering across
 	   the V-Link */
-	else if (interrupt_line_quirk)
+	else if (via_interrupt_line_quirk)
 		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq & 15);
 		
 }
diff -Nru a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
--- a/arch/ppc/kernel/head_8xx.S	2003-10-27 11:31:25 -08:00
+++ b/arch/ppc/kernel/head_8xx.S	2005-01-19 06:54:31 -08:00
@@ -338,13 +338,13 @@
 3:
 	lwz	r21, 0(r20)	/* Get the level 1 entry */
 	rlwinm.	r20, r21,0,0,19	/* Extract page descriptor page address */
-	beq	2f		/* If zero, don't try to find a pte */
 
 	/* We have a pte table, so load the MI_TWC with the attributes
 	 * for this "segment."
 	 */
 	tophys(r21,r21)
 	ori	r21,r21,1		/* Set valid bit */
+	beq-	2f			/* If zero, don't try to find a pte */
 #ifdef CONFIG_8xx_CPU6
 	li	r3, 0x2b80
 	stw	r3, 12(r0)
@@ -369,7 +369,7 @@
 	 * set.  All other Linux PTE bits control the behavior
 	 * of the MMU.
 	 */
-	li	r21, 0x00f0
+2:	li	r21, 0x00f0
 	rlwimi	r20, r21, 0, 24, 28	/* Set 24-27, clear 28 */
 
 #ifdef CONFIG_8xx_CPU6
@@ -388,15 +388,6 @@
 #endif
 	rfi
 
-2:	mfspr	r20, M_TW	/* Restore registers */
-	lwz	r21, 0(r0)
-	mtcr	r21
-	lwz	r21, 4(r0)
-#ifdef CONFIG_8xx_CPU6
-	lwz	r3, 8(r0)
-#endif
-	b	InstructionAccess
-
 	. = 0x1200
 DataStoreTLBMiss:
 #ifdef CONFIG_8xx_CPU6
@@ -422,12 +413,12 @@
 3:
 	lwz	r21, 0(r20)	/* Get the level 1 entry */
 	rlwinm.	r20, r21,0,0,19	/* Extract page descriptor page address */
-	beq	2f		/* If zero, don't try to find a pte */
 
 	/* We have a pte table, so load fetch the pte from the table.
 	 */
 	tophys(r21, r21)
 	ori	r21, r21, 1	/* Set valid bit in physical L2 page */
+	beq-	2f		/* If zero, don't try to find a pte */
 #ifdef CONFIG_8xx_CPU6
 	li	r3, 0x3b80
 	stw	r3, 12(r0)
@@ -461,7 +452,7 @@
 	 * set.  All other Linux PTE bits control the behavior
 	 * of the MMU.
 	 */
-	li	r21, 0x00f0
+2:	li	r21, 0x00f0
 	rlwimi	r20, r21, 0, 24, 28	/* Set 24-27, clear 28 */
 
 #ifdef CONFIG_8xx_CPU6
@@ -479,24 +470,6 @@
 	lwz	r3, 8(r0)
 #endif
 	rfi
-
-2:
-	/* Copy 20 msb from MD_EPN to DAR since the dcxx instructions fail
-	 * to update DAR when they cause a DTLB miss.
-	 */
-	mfspr	r21, MD_EPN
-	mfspr	r20, DAR
-	rlwimi	r20, r21, 0, 0, 19
-	mtspr	DAR, r20
-
-	mfspr	r20, M_TW	/* Restore registers */
-	lwz	r21, 0(r0)
-	mtcr	r21
-	lwz	r21, 4(r0)
-#ifdef CONFIG_8xx_CPU6
-	lwz	r3, 8(r0)
-#endif
-	b	DataAccess
 
 /* This is an instruction TLB error on the MPC8xx.  This could be due
  * to many reasons, such as executing guarded memory or illegal instruction
diff -Nru a/arch/sparc/kernel/muldiv.c b/arch/sparc/kernel/muldiv.c
--- a/arch/sparc/kernel/muldiv.c	2002-02-05 09:40:23 -08:00
+++ b/arch/sparc/kernel/muldiv.c	2005-01-21 13:59:23 -08:00
@@ -4,6 +4,9 @@
  *
  * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * 2004-12-25	Krzysztof Helt (krzysztof.h1@wp.pl) 
+ *		- fixed registers constrains in inline assembly declarations
  */
 
 #include <linux/kernel.h>
@@ -125,7 +128,7 @@
 			"mov	%%o0, %0\n\t"
 			"mov	%%o1, %1\n\t"
 			: "=r" (rs1), "=r" (rs2)
-		        :
+		        : "0" (rs1), "1" (rs2)
 			: "o0", "o1", "o2", "o3", "o4", "o5", "o7", "cc");
 #ifdef DEBUG_MULDIV
 		printk ("0x%x%08x\n", rs2, rs1);
@@ -145,7 +148,7 @@
 			"mov	%%o0, %0\n\t"
 			"mov	%%o1, %1\n\t"
 			: "=r" (rs1), "=r" (rs2)
-			:
+		        : "0" (rs1), "1" (rs2)
 			: "o0", "o1", "o2", "o3", "o4", "o5", "o7", "cc");
 #ifdef DEBUG_MULDIV
 		printk ("0x%x%08x\n", rs2, rs1);
@@ -174,7 +177,7 @@
 			"mov	%%o1, %0\n\t"
 			"mov	%%o0, %1\n\t"
 			: "=r" (rs1), "=r" (rs2)
-			: "r" (regs->y)
+			: "r" (regs->y), "0" (rs1), "1" (rs2)
 			: "o0", "o1", "o2", "o3", "o4", "o5", "o7",
 			  "g1", "g2", "g3", "cc");
 #ifdef DEBUG_MULDIV
@@ -203,7 +206,7 @@
 			"mov	%%o1, %0\n\t"
 			"mov	%%o0, %1\n\t"
 			: "=r" (rs1), "=r" (rs2)
-			: "r" (regs->y)
+			: "r" (regs->y), "0" (rs1), "1" (rs2)
 			: "o0", "o1", "o2", "o3", "o4", "o5", "o7",
 			  "g1", "g2", "g3", "cc");
 #ifdef DEBUG_MULDIV
diff -Nru a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S
--- a/arch/sparc64/lib/atomic.S	2002-02-05 06:06:58 -08:00
+++ b/arch/sparc64/lib/atomic.S	2005-02-01 12:25:42 -08:00
@@ -7,21 +7,34 @@
 #include <asm/asi.h>
 
 	.text
-	.align	64
 
 	.globl	atomic_impl_begin, atomic_impl_end
+atomic_impl_begin:
+	/* We use these stubs for the uncommon case
+	 * of contention on the atomic value.  This is
+	 * so that we can keep the main fast path 8
+	 * instructions long and thus fit into a single
+	 * L2 cache line.
+	 */
+__atomic_add_membar:
+	ba,pt	%xcc, __atomic_add
+	 membar	#StoreLoad | #StoreStore
+
+__atomic_sub_membar:
+	ba,pt	%xcc, __atomic_sub
+	 membar	#StoreLoad | #StoreStore
 
+	.align	64
 	.globl	__atomic_add
-atomic_impl_begin:
 __atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
 	lduw	[%o1], %g5
 	add	%g5, %o0, %g7
 	cas	[%o1], %g5, %g7
 	cmp	%g5, %g7
-	bne,pn	%icc, __atomic_add
-	 membar	#StoreLoad | #StoreStore
+	bne,pn	%icc, __atomic_add_membar
+	 add	%g7, %o0, %g7
 	retl
-	 add	%g7, %o0, %o0
+	 sra	%g7, 0, %o0
 
 	.globl	__atomic_sub
 __atomic_sub: /* %o0 = increment, %o1 = atomic_ptr */
@@ -29,8 +42,8 @@
 	sub	%g5, %o0, %g7
 	cas	[%o1], %g5, %g7
 	cmp	%g5, %g7
-	bne,pn	%icc, __atomic_sub
-	 membar	#StoreLoad | #StoreStore
+	bne,pn	%icc, __atomic_sub_membar
+	 sub	%g7, %o0, %g7
 	retl
-	 sub	%g7, %o0, %o0
+	 sra	%g7, 0, %o0
 atomic_impl_end:
diff -Nru a/arch/x86_64/kernel/pci-irq.c b/arch/x86_64/kernel/pci-irq.c
--- a/arch/x86_64/kernel/pci-irq.c	2003-06-24 13:45:14 -07:00
+++ b/arch/x86_64/kernel/pci-irq.c	2005-01-26 00:49:52 -08:00
@@ -742,7 +742,7 @@
 void pcibios_enable_irq(struct pci_dev *dev)
 {
 		u8 pin;
-	extern int interrupt_line_quirk;
+	extern int via_interrupt_line_quirk;
 
 		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 	if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
@@ -762,6 +762,6 @@
 	}
 	/* VIA bridges use interrupt line for apic/pci steering across
 	   the V-Link */
-	else if (interrupt_line_quirk)
+	else if (via_interrupt_line_quirk)
 		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
 }
diff -Nru a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
--- a/drivers/acpi/pci_irq.c	2004-04-23 19:18:42 -07:00
+++ b/drivers/acpi/pci_irq.c	2005-01-26 00:49:52 -08:00
@@ -335,6 +335,7 @@
 {
 	int			irq = 0;
 	u8			pin = 0;
+	extern int via_interrupt_line_quirk;
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_enable");
 
@@ -382,6 +383,9 @@
 			return_VALUE(0);
 		}
  	}
+
+	if (via_interrupt_line_quirk)
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq & 15);
 
 	dev->irq = irq;
 
diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c
--- a/drivers/block/nbd.c	2003-08-09 06:25:49 -07:00
+++ b/drivers/block/nbd.c	2005-01-24 15:16:32 -08:00
@@ -408,10 +408,7 @@
 	int dev, error, temp;
 	struct request sreq ;
 
-	/* Anyone capable of this syscall can do *real bad* things */
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
 	if (!inode)
 		return -EINVAL;
 	dev = MINOR(inode->i_rdev);
@@ -419,6 +416,20 @@
 		return -ENODEV;
 
 	lo = &nbd_dev[dev];
+
+	/* these are innocent, but.... */
+	switch (cmd) {
+	case BLKGETSIZE:
+		return put_user(nbd_bytesizes[dev] >> 9, (unsigned long *) arg);
+	case BLKGETSIZE64:
+		return put_user((u64)nbd_bytesizes[dev], (u64 *) arg);
+	}
+
+	/* ... anyone capable of any of the below ioctls can do *real bad* 
+	   things */
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
 	switch (cmd) {
 	case NBD_DISCONNECT:
 	        printk("NBD_DISCONNECT\n");
@@ -524,10 +535,6 @@
 		       dev, lo->queue_head.next, lo->queue_head.prev, requests_in, requests_out);
 		return 0;
 #endif
-	case BLKGETSIZE:
-		return put_user(nbd_bytesizes[dev] >> 9, (unsigned long *) arg);
-	case BLKGETSIZE64:
-		return put_user((u64)nbd_bytesizes[dev], (u64 *) arg);
 	}
 	return -EINVAL;
 }
diff -Nru a/drivers/char/lcd.c b/drivers/char/lcd.c
--- a/drivers/char/lcd.c	2003-12-20 05:18:51 -08:00
+++ b/drivers/char/lcd.c	2005-01-27 15:49:38 -08:00
@@ -386,6 +386,8 @@
 
 		int ctr=0;
 
+		if (!capable(CAP_SYS_ADMIN)) return -EPERM;
+
 		    // Chip Erase Sequence
 		WRITE_FLASH( kFlash_Addr1, kFlash_Data1 );
 		WRITE_FLASH( kFlash_Addr2, kFlash_Data2 );
@@ -422,6 +424,8 @@
 
                 struct lcd_display display;
 
+		if (!capable(CAP_SYS_ADMIN)) return -EPERM;
+
                 if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display)))
 		  return -EFAULT;
 		rom = (unsigned char *) kmalloc((128),GFP_ATOMIC);
@@ -434,8 +438,10 @@
 		save_flags(flags);
 		for (i=0; i<FLASH_SIZE; i=i+128) {
 
-		        if(copy_from_user(rom, display.RomImage + i, 128))
+		        if(copy_from_user(rom, display.RomImage + i, 128)) {
+			   kfree(rom);
 			   return -EFAULT;
+			}
 			burn_addr = kFlashBase + i;
 			cli();
 			for ( index = 0; index < ( 128 ) ; index++ ) 
diff -Nru a/drivers/i2c/i2c-algo-bit.c b/drivers/i2c/i2c-algo-bit.c
--- a/drivers/i2c/i2c-algo-bit.c	2003-12-23 11:02:05 -08:00
+++ b/drivers/i2c/i2c-algo-bit.c	2005-01-29 02:35:39 -08:00
@@ -28,14 +28,12 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <asm/uaccess.h>
-#include <linux/ioport.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
-
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 
+
 /* ----- global defines ----------------------------------------------- */
 #define DEB(x) if (i2c_debug>=1) x;
 #define DEB2(x) if (i2c_debug>=2) x;
@@ -522,8 +520,8 @@
 
 static u32 bit_func(struct i2c_adapter *adap)
 {
-	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | 
-	       I2C_FUNC_PROTOCOL_MANGLING;
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+	       I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
 }
 
 
diff -Nru a/drivers/i2c/i2c-algo-pcf.c b/drivers/i2c/i2c-algo-pcf.c
--- a/drivers/i2c/i2c-algo-pcf.c	2003-12-23 11:02:05 -08:00
+++ b/drivers/i2c/i2c-algo-pcf.c	2005-01-29 02:35:45 -08:00
@@ -32,15 +32,13 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <asm/uaccess.h>
-#include <linux/ioport.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
-
 #include <linux/i2c.h>
 #include <linux/i2c-algo-pcf.h>
 #include "i2c-pcf8584.h"
 
+
 /* ----- global defines ----------------------------------------------- */
 #define DEB(x) if (i2c_debug>=1) x
 #define DEB2(x) if (i2c_debug>=2) x
@@ -435,8 +433,8 @@
 
 static u32 pcf_func(struct i2c_adapter *adap)
 {
-	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | 
-	       I2C_FUNC_PROTOCOL_MANGLING; 
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+	       I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
 }
 
 /* -----exported algorithm data: -------------------------------------	*/
diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
--- a/drivers/ide/ide-cd.c	2004-08-02 05:20:16 -07:00
+++ b/drivers/ide/ide-cd.c	2005-01-08 12:53:08 -08:00
@@ -2206,24 +2206,30 @@
 	/* Read the multisession information. */
 	if (toc->hdr.first_track != CDROM_LEADOUT) {
 		/* Read the multisession information. */
-		stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
+		stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp,
 					   sizeof(ms_tmp), sense);
 		if (stat) return stat;
+	
+		toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba);
 	} else {
-		ms_tmp.ent.addr.msf.minute = 0;
-		ms_tmp.ent.addr.msf.second = 2;
-		ms_tmp.ent.addr.msf.frame  = 0;
 		ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT;
+		toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
 	}
 
 #if ! STANDARD_ATAPI
-	if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd)
+	if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) {
+		/* Re-read multisession information using MSF format */
+		stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
+					   sizeof(ms_tmp), sense);
+		if (stat)
+			return stat;
+
 		msf_from_bcd (&ms_tmp.ent.addr.msf);
+		toc->last_session_lba = msf_to_lba(ms_tmp.ent.addr.msf.minute,
+					  	   ms_tmp.ent.addr.msf.second,
+						   ms_tmp.ent.addr.msf.frame);
+	}
 #endif  /* not STANDARD_ATAPI */
-
-	toc->last_session_lba = msf_to_lba (ms_tmp.ent.addr.msf.minute,
-					    ms_tmp.ent.addr.msf.second,
-					    ms_tmp.ent.addr.msf.frame);
 
 	toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
 
diff -Nru a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c
--- a/drivers/isdn/hisax/ipacx.c	2002-03-31 16:55:17 -08:00
+++ b/drivers/isdn/hisax/ipacx.c	2005-01-24 10:50:36 -08:00
@@ -152,7 +152,13 @@
 
 		case (HW_RESET | REQUEST):
 		case (HW_ENABLE | REQUEST):
-			ph_command(cs, IPACX_CMD_TIM);
+			if ((cs->dc.isac.ph_state == IPACX_IND_RES) ||
+			(cs->dc.isac.ph_state == IPACX_IND_DR) ||
+				(cs->dc.isac.ph_state == IPACX_IND_DC))
+				ph_command(cs, IPACX_CMD_TIM);
+			else
+				ph_command(cs, IPACX_CMD_RES);
+
 			break;
 
 		case (HW_INFO3 | REQUEST):
diff -Nru a/drivers/md/lvm-snap.c b/drivers/md/lvm-snap.c
--- a/drivers/md/lvm-snap.c	2004-03-12 21:25:25 -08:00
+++ b/drivers/md/lvm-snap.c	2005-01-26 07:01:33 -08:00
@@ -119,7 +119,6 @@
 	unsigned long mask = lv->lv_snapshot_hash_mask;
 	int chunk_size = lv->lv_chunk_size;
 	lv_block_exception_t *ret;
-	int i = 0;
 
 	hash_table =
 	    &hash_table[hashfn(org_dev, org_start, mask, chunk_size)];
@@ -132,15 +131,9 @@
 		exception = list_entry(next, lv_block_exception_t, hash);
 		if (exception->rsector_org == org_start &&
 		    exception->rdev_org == org_dev) {
-			if (i) {
-				/* fun, isn't it? :) */
-				list_del(next);
-				list_add(next, hash_table);
-			}
 			ret = exception;
 			break;
 		}
-		i++;
 	}
 	return ret;
 }
diff -Nru a/drivers/net/tg3.c b/drivers/net/tg3.c
--- a/drivers/net/tg3.c	2005-01-06 15:00:11 -08:00
+++ b/drivers/net/tg3.c	2005-01-26 15:10:25 -08:00
@@ -59,8 +59,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.15"
-#define DRV_MODULE_RELDATE	"January 6, 2005"
+#define DRV_MODULE_VERSION	"3.19"
+#define DRV_MODULE_RELDATE	"January 26, 2005"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -2690,7 +2690,11 @@
 
 		len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */
 
-		if (len > RX_COPY_THRESHOLD) {
+		if (len > RX_COPY_THRESHOLD 
+			&& tp->rx_offset == 2
+			/* rx_offset != 2 iff this is a 5701 card running
+			 * in PCI-X mode [see tg3_get_invariants()] */
+		) {
 			int skb_size;
 
 			skb_size = tg3_alloc_rx_skb(tp, opaque_key,
@@ -3085,11 +3089,19 @@
 
 		skb->nh.iph->check = 0;
 		skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len);
-		skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
-						      skb->nh.iph->daddr,
-						      0, IPPROTO_TCP, 0);
+		if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
+			skb->h.th->check = 0;
+			base_flags &= ~TXD_FLAG_TCPUDP_CSUM;
+		}
+		else {
+			skb->h.th->check =
+				~csum_tcpudp_magic(skb->nh.iph->saddr,
+						   skb->nh.iph->daddr,
+						   0, IPPROTO_TCP, 0);
+		}
 
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+		if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) ||
+		    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) {
 			if (tcp_opt_len || skb->nh.iph->ihl > 5) {
 				int tsflags;
 
@@ -3156,7 +3168,7 @@
 				would_hit_hwbug = entry + 1;
 			}
 
-			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+			if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
 				tg3_set_txd(tp, entry, mapping, len,
 					    base_flags, (i == last)|(mss << 1));
 			else
@@ -4747,7 +4759,7 @@
 	unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
 	int err, i;
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+	if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
 		return 0;
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
@@ -4831,9 +4843,8 @@
 		tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
 	}
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
-	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 &&
-	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
 		for (i = 0; i < 12; i++) {
 			tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
 			tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
@@ -4879,7 +4890,8 @@
 		      (bdinfo_addr + TG3_BDINFO_MAXLEN_FLAGS),
 		       maxlen_flags);
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705)
+	if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) &&
+	    (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750))
 		tg3_write_mem(tp,
 			      (bdinfo_addr + TG3_BDINFO_NIC_ADDR),
 			      nic_addr);
@@ -5181,7 +5193,7 @@
 	}
 
 #if TG3_TSO_SUPPORT != 0
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+	if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
 		rdmac_mode |= (1 << 27);
 #endif
 
@@ -5331,7 +5343,7 @@
 	tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ);
 	tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
 #if TG3_TSO_SUPPORT != 0
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+	if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
 		tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE | 0x8);
 #endif
 	tw32(SNDBDI_MODE, SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE);
@@ -6349,11 +6361,13 @@
 
 static int tg3_get_eeprom_len(struct net_device *dev)
 {
-	return EEPROM_CHIP_SIZE;
+	struct tg3 *tp = netdev_priv(dev);
+
+	return tp->nvram_size;
 }
 
-static int tg3_nvram_read_using_eeprom(struct tg3 *tp,
-					u32 offset, u32 *val);
+static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val);
+
 static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
 {
 	struct tg3 *tp = dev->priv;
@@ -6365,10 +6379,7 @@
 	len = eeprom->len;
 	eeprom->len = 0;
 
-	ret = tg3_nvram_read_using_eeprom(tp, 0, &eeprom->magic);
-	if (ret)
-		return ret;
-	eeprom->magic = swab32(eeprom->magic);
+	eeprom->magic = TG3_EEPROM_MAGIC;
 
 	if (offset & 3) {
 		/* adjustments to start on required 4 byte boundary */
@@ -6378,9 +6389,10 @@
 			/* i.e. offset=1 len=2 */
 			b_count = len;
 		}
-		ret = tg3_nvram_read_using_eeprom(tp, offset-b_offset, &val);
+		ret = tg3_nvram_read(tp, offset-b_offset, &val);
 		if (ret)
 			return ret;
+		val = cpu_to_le32(val);
 		memcpy(data, ((char*)&val) + b_offset, b_count);
 		len -= b_count;
 		offset += b_count;
@@ -6390,12 +6402,13 @@
 	/* read bytes upto the last 4 byte boundary */
 	pd = &data[eeprom->len];
 	for (i = 0; i < (len - (len & 3)); i += 4) {
-		ret = tg3_nvram_read_using_eeprom(tp, offset + i, 
-				(u32*)(pd + i));
+		ret = tg3_nvram_read(tp, offset + i, &val);
 		if (ret) {
 			eeprom->len += i;
 			return ret;
 		}
+		val = cpu_to_le32(val);
+		memcpy(pd + i, &val, 4);
 	}
 	eeprom->len += i;
 
@@ -6404,15 +6417,72 @@
 		pd = &data[eeprom->len];
 		b_count = len & 3;
 		b_offset = offset + len - b_count;
-		ret = tg3_nvram_read_using_eeprom(tp, b_offset, &val);
+		ret = tg3_nvram_read(tp, b_offset, &val);
 		if (ret)
 			return ret;
+		val = cpu_to_le32(val);
 		memcpy(pd, ((char*)&val), b_count);
 		eeprom->len += b_count;
 	}
 	return 0;
 }
 
+static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf); 
+
+static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
+{
+	struct tg3 *tp = netdev_priv(dev);
+	int ret;
+	u32 offset, len, b_offset, odd_len, start, end;
+	u8 *buf;
+
+	if (eeprom->magic != TG3_EEPROM_MAGIC)
+		return -EINVAL;
+
+	offset = eeprom->offset;
+	len = eeprom->len;
+
+	if ((b_offset = (offset & 3))) {
+		/* adjustments to start on required 4 byte boundary */
+		ret = tg3_nvram_read(tp, offset-b_offset, &start);
+		if (ret)
+			return ret;
+		start = cpu_to_le32(start);
+		len += b_offset;
+		offset &= ~3;
+	}
+
+	odd_len = 0;
+	if ((len & 3) && ((len > 4) || (b_offset == 0))) {
+		/* adjustments to end on required 4 byte boundary */
+		odd_len = 1;
+		len = (len + 3) & ~3;
+		ret = tg3_nvram_read(tp, offset+len-4, &end);
+		if (ret)
+			return ret;
+		end = cpu_to_le32(end);
+	}
+
+	buf = data;
+	if (b_offset || odd_len) {
+		buf = kmalloc(len, GFP_KERNEL);
+		if (buf == 0)
+			return -ENOMEM;
+		if (b_offset)
+			memcpy(buf, &start, 4);
+		if (odd_len)
+			memcpy(buf+len-4, &end, 4);
+		memcpy(buf + b_offset, data, eeprom->len);
+	}
+
+	ret = tg3_nvram_write_block(tp, offset, len, buf);
+
+	if (buf != data)
+		kfree(buf);
+
+	return ret;
+}
+
 static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
   	struct tg3 *tp = netdev_priv(dev);
@@ -6812,6 +6882,7 @@
 	.get_link		= ethtool_op_get_link,
 	.get_eeprom_len		= tg3_get_eeprom_len,
 	.get_eeprom		= tg3_get_eeprom,
+	.set_eeprom		= tg3_set_eeprom,
 	.get_ringparam		= tg3_get_ringparam,
 	.set_ringparam		= tg3_set_ringparam,
 	.get_pauseparam		= tg3_get_pauseparam,
@@ -6831,6 +6902,103 @@
 	.get_ethtool_stats	= tg3_get_ethtool_stats,
 };
 
+static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
+{
+	u32 cursize, val;
+
+	tp->nvram_size = EEPROM_CHIP_SIZE;
+
+	if (tg3_nvram_read(tp, 0, &val) != 0)
+		return;
+
+	if (swab32(val) != TG3_EEPROM_MAGIC)
+		return;
+
+	/*
+	 * Size the chip by reading offsets at increasing powers of two.
+	 * When we encounter our validation signature, we know the addressing
+	 * has wrapped around, and thus have our chip size.
+	 */
+	cursize = 0x800;
+
+	while (cursize < tp->nvram_size) {
+		if (tg3_nvram_read(tp, cursize, &val) != 0)
+			return;
+
+		if (swab32(val) == TG3_EEPROM_MAGIC)
+			break;
+
+		cursize <<= 1;
+	}
+
+	tp->nvram_size = cursize;
+}
+		
+static void __devinit tg3_get_nvram_size(struct tg3 *tp)
+{
+	u32 val;
+
+	if (tg3_nvram_read(tp, 0xf0, &val) == 0) {
+		if (val != 0) {
+			tp->nvram_size = (val >> 16) * 1024;
+			return;
+		}
+	}
+	tp->nvram_size = 0x20000;
+}
+
+static void __devinit tg3_get_nvram_info(struct tg3 *tp)
+{
+	u32 nvcfg1;
+
+	nvcfg1 = tr32(NVRAM_CFG1);
+	if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) {
+		tp->tg3_flags2 |= TG3_FLG2_FLASH;
+	}
+	else {
+		nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
+		tw32(NVRAM_CFG1, nvcfg1);
+	}
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+		switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) {
+			case FLASH_VENDOR_ATMEL_FLASH_BUFFERED:
+				tp->nvram_jedecnum = JEDEC_ATMEL;
+				tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE;
+				tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+				break;
+			case FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED:
+				tp->nvram_jedecnum = JEDEC_ATMEL;
+                         	tp->nvram_pagesize = ATMEL_AT25F512_PAGE_SIZE;
+				break;
+			case FLASH_VENDOR_ATMEL_EEPROM:
+				tp->nvram_jedecnum = JEDEC_ATMEL;
+                         	tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+				tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+				break;
+			case FLASH_VENDOR_ST:
+				tp->nvram_jedecnum = JEDEC_ST;
+				tp->nvram_pagesize = ST_M45PEX0_PAGE_SIZE;
+				tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+				break;
+			case FLASH_VENDOR_SAIFUN:
+				tp->nvram_jedecnum = JEDEC_SAIFUN;
+				tp->nvram_pagesize = SAIFUN_SA25F0XX_PAGE_SIZE;
+				break;
+			case FLASH_VENDOR_SST_SMALL:
+			case FLASH_VENDOR_SST_LARGE:
+				tp->nvram_jedecnum = JEDEC_SST;
+				tp->nvram_pagesize = SST_25VF0X0_PAGE_SIZE;
+				break;
+		}
+	}
+	else {
+		tp->nvram_jedecnum = JEDEC_ATMEL;
+		tp->nvram_pagesize = ATMEL_AT45DB0X1B_PAGE_SIZE;
+		tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+	}
+}
+
 /* Chips other than 5700/5701 use the NVRAM for fetching info. */
 static void __devinit tg3_nvram_init(struct tg3 *tp)
 {
@@ -6855,32 +7023,27 @@
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
 	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
-		u32 nvcfg1;
+		tp->tg3_flags |= TG3_FLAG_NVRAM;
 
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
 			u32 nvaccess = tr32(NVRAM_ACCESS);
 
-			tw32_f(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
+			tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
 		}
 
-		nvcfg1 = tr32(NVRAM_CFG1);
-
-		tp->tg3_flags |= TG3_FLAG_NVRAM;
-		if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) {
-			if (nvcfg1 & NVRAM_CFG1_BUFFERED_MODE)
-				tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
-		} else {
-			nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
-			tw32(NVRAM_CFG1, nvcfg1);
-		}
+		tg3_get_nvram_info(tp);
+		tg3_get_nvram_size(tp);
 
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
 			u32 nvaccess = tr32(NVRAM_ACCESS);
 
-			tw32_f(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
+			tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
 		}
+
 	} else {
 		tp->tg3_flags &= ~(TG3_FLAG_NVRAM | TG3_FLAG_NVRAM_BUFFERED);
+
+		tg3_get_eeprom_size(tp);
 	}
 }
 
@@ -6918,11 +7081,30 @@
 	return 0;
 }
 
-static int __devinit tg3_nvram_read(struct tg3 *tp,
-				    u32 offset, u32 *val)
+#define NVRAM_CMD_TIMEOUT 10000
+
+static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd)
 {
 	int i;
 
+	tw32(NVRAM_CMD, nvram_cmd);
+	for (i = 0; i < NVRAM_CMD_TIMEOUT; i++) {
+		udelay(10);
+		if (tr32(NVRAM_CMD) & NVRAM_CMD_DONE) {
+			udelay(10);
+			break;
+		}
+	}
+	if (i == NVRAM_CMD_TIMEOUT) {
+		return -EBUSY;
+	}
+	return 0;
+}
+
+static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
+{
+	int ret;
+
 	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
 		printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 570X\n");
 		return -EINVAL;
@@ -6931,10 +7113,14 @@
 	if (!(tp->tg3_flags & TG3_FLAG_NVRAM))
 		return tg3_nvram_read_using_eeprom(tp, offset, val);
 
-	if (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED)
-		offset = ((offset / NVRAM_BUFFERED_PAGE_SIZE) <<
-			  NVRAM_BUFFERED_PAGE_POS) +
-			(offset % NVRAM_BUFFERED_PAGE_SIZE);
+	if ((tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) &&
+		(tp->tg3_flags2 & TG3_FLG2_FLASH) &&
+		(tp->nvram_jedecnum == JEDEC_ATMEL)) {
+
+		offset = ((offset / tp->nvram_pagesize) <<
+			  ATMEL_AT45DB0X1B_PAGE_POS) +
+			(offset % tp->nvram_pagesize);
+	}
 
 	if (offset > NVRAM_ADDR_MSK)
 		return -EINVAL;
@@ -6948,19 +7134,11 @@
 	}
 
 	tw32(NVRAM_ADDR, offset);
-	tw32(NVRAM_CMD,
-	     NVRAM_CMD_RD | NVRAM_CMD_GO |
-	     NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE);
+	ret = tg3_nvram_exec_cmd(tp, NVRAM_CMD_RD | NVRAM_CMD_GO |
+		NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE);
 
-	/* Wait for done bit to clear. */
-	for (i = 0; i < 1000; i++) {
-		udelay(10);
-		if (tr32(NVRAM_CMD) & NVRAM_CMD_DONE) {
-			udelay(10);
-			*val = swab32(tr32(NVRAM_RDDATA));
-			break;
-		}
-	}
+	if (ret == 0)
+		*val = swab32(tr32(NVRAM_RDDATA));
 
 	tg3_nvram_unlock(tp);
 
@@ -6970,10 +7148,268 @@
 		tw32_f(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
 	}
 
-	if (i >= 1000)
-		return -EBUSY;
+	return ret;
+}
 
-	return 0;
+static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp,
+				    u32 offset, u32 len, u8 *buf)
+{
+	int i, j, rc = 0;
+	u32 val;
+
+	for (i = 0; i < len; i += 4) {
+		u32 addr, data;
+
+		addr = offset + i;
+
+		memcpy(&data, buf + i, 4);
+
+		tw32(GRC_EEPROM_DATA, cpu_to_le32(data));
+
+		val = tr32(GRC_EEPROM_ADDR);
+		tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE);
+
+		val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK |
+			EEPROM_ADDR_READ);
+		tw32(GRC_EEPROM_ADDR, val |
+			(0 << EEPROM_ADDR_DEVID_SHIFT) |
+			(addr & EEPROM_ADDR_ADDR_MASK) |
+			EEPROM_ADDR_START |
+			EEPROM_ADDR_WRITE);
+		
+		for (j = 0; j < 10000; j++) {
+			val = tr32(GRC_EEPROM_ADDR);
+
+			if (val & EEPROM_ADDR_COMPLETE)
+				break;
+			udelay(100);
+		}
+		if (!(val & EEPROM_ADDR_COMPLETE)) {
+			rc = -EBUSY;
+			break;
+		}
+	}
+
+	return rc;
+}
+
+/* offset and length are dword aligned */
+static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len,
+		u8 *buf)
+{
+	int ret = 0;
+	u32 pagesize = tp->nvram_pagesize;
+	u32 pagemask = pagesize - 1;
+	u32 nvram_cmd;
+	u8 *tmp;
+
+	tmp = kmalloc(pagesize, GFP_KERNEL);
+	if (tmp == NULL)
+		return -ENOMEM;
+
+	while (len) {
+		int j;
+		u32 phy_addr, page_off, size, nvaccess;
+
+		phy_addr = offset & ~pagemask;
+	
+		for (j = 0; j < pagesize; j += 4) {
+			if ((ret = tg3_nvram_read(tp, phy_addr + j,
+						(u32 *) (tmp + j))))
+				break;
+		}
+		if (ret)
+			break;
+
+	        page_off = offset & pagemask;
+		size = pagesize;
+		if (len < size)
+			size = len;
+
+		len -= size;
+
+		memcpy(tmp + page_off, buf, size);
+
+		offset = offset + (pagesize - page_off);
+
+		nvaccess = tr32(NVRAM_ACCESS);
+		tw32_f(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
+
+		/*
+		 * Before we can erase the flash page, we need
+		 * to issue a special "write enable" command.
+		 */
+		nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE;
+
+		if (tg3_nvram_exec_cmd(tp, nvram_cmd))
+			break;
+
+		/* Erase the target page */
+		tw32(NVRAM_ADDR, phy_addr);
+
+		nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR |
+			NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE;
+
+	        if (tg3_nvram_exec_cmd(tp, nvram_cmd))
+			break;
+
+		/* Issue another write enable to start the write. */
+		nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE;
+
+		if (tg3_nvram_exec_cmd(tp, nvram_cmd))
+			break;
+
+		for (j = 0; j < pagesize; j += 4) {
+			u32 data;
+
+	    		data = *((u32 *) (tmp + j));
+			tw32(NVRAM_WRDATA, cpu_to_be32(data));
+
+			tw32(NVRAM_ADDR, phy_addr + j);
+
+			nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE |
+				NVRAM_CMD_WR;
+
+			if (j == 0)
+				nvram_cmd |= NVRAM_CMD_FIRST;
+			else if (j == (pagesize - 4))
+				nvram_cmd |= NVRAM_CMD_LAST;
+
+			if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd)))
+				break;
+		}
+		if (ret)
+			break;
+	}
+
+	nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE;
+	tg3_nvram_exec_cmd(tp, nvram_cmd);
+
+	kfree(tmp);
+
+	return ret;
+}
+
+/* offset and length are dword aligned */
+static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
+		u8 *buf)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < len; i += 4, offset += 4) {
+		u32 data, page_off, phy_addr, nvram_cmd;
+
+		memcpy(&data, buf + i, 4);
+		tw32(NVRAM_WRDATA, cpu_to_be32(data));
+
+	        page_off = offset % tp->nvram_pagesize;
+
+		if ((tp->tg3_flags2 & TG3_FLG2_FLASH) &&
+			(tp->nvram_jedecnum == JEDEC_ATMEL)) {
+
+			phy_addr = ((offset / tp->nvram_pagesize) <<
+				    ATMEL_AT45DB0X1B_PAGE_POS) + page_off;
+		}
+		else {
+			phy_addr = offset;
+		}
+
+		tw32(NVRAM_ADDR, phy_addr);
+
+		nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR;
+
+	        if ((page_off == 0) || (i == 0))
+			nvram_cmd |= NVRAM_CMD_FIRST;
+		else if (page_off == (tp->nvram_pagesize - 4))
+			nvram_cmd |= NVRAM_CMD_LAST;
+
+		if (i == (len - 4))
+			nvram_cmd |= NVRAM_CMD_LAST;
+
+		if ((tp->nvram_jedecnum == JEDEC_ST) &&
+			(nvram_cmd & NVRAM_CMD_FIRST)) {
+
+			if ((ret = tg3_nvram_exec_cmd(tp,
+				NVRAM_CMD_WREN | NVRAM_CMD_GO |
+				NVRAM_CMD_DONE)))
+
+				break;
+		}
+		if (!(tp->tg3_flags2 & TG3_FLG2_FLASH)) {
+			/* We always do complete word writes to eeprom. */
+			nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST);
+		}
+
+		if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd)))
+			break;
+	}
+	return ret;
+}
+
+/* offset and length are dword aligned */
+static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)
+{
+	int ret;
+
+	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
+		printk(KERN_ERR PFX "Attempt to do nvram_write on Sun 570X\n");
+		return -EINVAL;
+	}
+
+	if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
+		tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+		       GRC_LCLCTRL_GPIO_OE1);
+		udelay(40);
+	}
+
+	if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) {
+		ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf);
+	}
+	else {
+		u32 grc_mode;
+
+		tg3_nvram_lock(tp);
+
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+			u32 nvaccess = tr32(NVRAM_ACCESS);
+
+			tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
+
+			tw32(NVRAM_WRITE1, 0x406);
+		}
+
+		grc_mode = tr32(GRC_MODE);
+		tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE);
+
+		if ((tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) ||
+			!(tp->tg3_flags2 & TG3_FLG2_FLASH)) {
+
+			ret = tg3_nvram_write_block_buffered(tp, offset, len,
+				buf);
+		}
+		else {
+			ret = tg3_nvram_write_block_unbuffered(tp, offset, len,
+				buf);
+		}
+
+		grc_mode = tr32(GRC_MODE);
+		tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE);
+
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+			u32 nvaccess = tr32(NVRAM_ACCESS);
+
+			tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
+		}
+		tg3_nvram_unlock(tp);
+	}
+
+	if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
+		tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+		       GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OUTPUT1);
+		udelay(40);
+	}
+
+	return ret;
 }
 
 struct subsys_tbl_ent {
@@ -7116,9 +7552,8 @@
 		    tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
 			tp->led_ctrl = LED_CTRL_MODE_PHY_2;
 
-		if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
-		     (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
-		     (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) &&
+		if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) &&
+		    (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) &&
 		    (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP))
 			tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
 
@@ -7414,6 +7849,9 @@
 	tp->pci_hdr_type     = (cacheline_sz_reg >> 16) & 0xff;
 	tp->pci_bist         = (cacheline_sz_reg >> 24) & 0xff;
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+		tp->tg3_flags2 |= TG3_FLG2_HW_TSO;
+
 	if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0)
 		tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
 
@@ -8302,11 +8740,13 @@
 	}
 
 #if TG3_TSO_SUPPORT != 0
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+	if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
+		tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
+	}
+	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
 	    tp->pci_chip_rev_id == CHIPREV_ID_5705_A0 ||
-	    ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0 &&
-	     GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)) {
+	    (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) {
 		tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
 	} else {
 		tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
diff -Nru a/drivers/net/tg3.h b/drivers/net/tg3.h
--- a/drivers/net/tg3.h	2004-11-15 15:45:17 -08:00
+++ b/drivers/net/tg3.h	2005-01-24 17:40:19 -08:00
@@ -1274,6 +1274,7 @@
 #define  GRC_MODE_HOST_STACKUP		0x00010000
 #define  GRC_MODE_HOST_SENDBDS		0x00020000
 #define  GRC_MODE_NO_TX_PHDR_CSUM	0x00100000
+#define  GRC_MODE_NVRAM_WR_ENABLE	0x00200000
 #define  GRC_MODE_NO_RX_PHDR_CSUM	0x00800000
 #define  GRC_MODE_IRQ_ON_TX_CPU_ATTN	0x01000000
 #define  GRC_MODE_IRQ_ON_RX_CPU_ATTN	0x02000000
@@ -1366,6 +1367,8 @@
 #define  NVRAM_CMD_ERASE		 0x00000040
 #define  NVRAM_CMD_FIRST		 0x00000080
 #define  NVRAM_CMD_LAST			 0x00000100
+#define  NVRAM_CMD_WREN			 0x00010000
+#define  NVRAM_CMD_WRDI			 0x00020000
 #define NVRAM_STAT			0x00007004
 #define NVRAM_WRDATA			0x00007008
 #define NVRAM_ADDR			0x0000700c
@@ -1375,8 +1378,18 @@
 #define  NVRAM_CFG1_FLASHIF_ENAB	 0x00000001
 #define  NVRAM_CFG1_BUFFERED_MODE	 0x00000002
 #define  NVRAM_CFG1_PASS_THRU		 0x00000004
+#define  NVRAM_CFG1_STATUS_BITS		 0x00000070
 #define  NVRAM_CFG1_BIT_BANG		 0x00000008
+#define  NVRAM_CFG1_FLASH_SIZE		 0x02000000
 #define  NVRAM_CFG1_COMPAT_BYPASS	 0x80000000
+#define  NVRAM_CFG1_VENDOR_MASK		 0x03000003
+#define  FLASH_VENDOR_ATMEL_EEPROM	 0x02000000
+#define  FLASH_VENDOR_ATMEL_FLASH_BUFFERED	 0x02000003
+#define  FLASH_VENDOR_ATMEL_FLASH_UNBUFFERED	 0x00000003
+#define  FLASH_VENDOR_ST			 0x03000001
+#define  FLASH_VENDOR_SAIFUN		 0x01000003
+#define  FLASH_VENDOR_SST_SMALL		 0x00000001
+#define  FLASH_VENDOR_SST_LARGE		 0x02000001
 #define NVRAM_CFG2			0x00007018
 #define NVRAM_CFG3			0x0000701c
 #define NVRAM_SWARB			0x00007020
@@ -1396,15 +1409,16 @@
 #define  SWARB_REQ1			 0x00002000
 #define  SWARB_REQ2			 0x00004000
 #define  SWARB_REQ3			 0x00008000
-#define    NVRAM_BUFFERED_PAGE_SIZE	   264
-#define    NVRAM_BUFFERED_PAGE_POS	   9
 #define NVRAM_ACCESS			0x00007024
 #define  ACCESS_ENABLE			 0x00000001
 #define  ACCESS_WR_ENABLE		 0x00000002
-/* 0x7024 --> 0x7400 unused */
+#define NVRAM_WRITE1			0x00007028
+/* 0x702c --> 0x7400 unused */
 
 /* 0x7400 --> 0x8000 unused */
 
+#define TG3_EEPROM_MAGIC		0x669955aa
+
 /* 32K Window into NIC internal memory */
 #define NIC_SRAM_WIN_BASE		0x00008000
 
@@ -2090,6 +2104,8 @@
 #define TG3_FLG2_PHY_JUST_INITTED	0x00001000
 #define TG3_FLG2_PHY_SERDES		0x00002000
 #define TG3_FLG2_CAPACITIVE_COUPLING	0x00004000
+#define TG3_FLG2_FLASH			0x00008000
+#define TG3_FLG2_HW_TSO			0x00010000
 
 	u32				split_mode_max_reqs;
 #define SPLIT_MODE_5704_MAX_REQ		3
@@ -2164,6 +2180,34 @@
 	struct tg3_hw_stats		*hw_stats;
 	dma_addr_t			stats_mapping;
 	struct tq_struct		reset_task;
+
+	u32				nvram_size;
+	u32				nvram_pagesize;
+	u32				nvram_jedecnum;
+
+#define JEDEC_ATMEL			0x1f
+#define JEDEC_ST			0x20
+#define JEDEC_SAIFUN			0x4f
+#define JEDEC_SST			0xbf
+
+#define ATMEL_AT24C64_CHIP_SIZE		(64 * 1024)
+#define ATMEL_AT24C64_PAGE_SIZE		(32)
+
+#define ATMEL_AT24C512_CHIP_SIZE	(512 * 1024)
+#define ATMEL_AT24C512_PAGE_SIZE	(128)
+
+#define ATMEL_AT45DB0X1B_PAGE_POS	9
+#define ATMEL_AT45DB0X1B_PAGE_SIZE	264
+
+#define ATMEL_AT25F512_PAGE_SIZE	256
+
+#define ST_M45PEX0_PAGE_SIZE		256
+
+#define SAIFUN_SA25F0XX_PAGE_SIZE	256
+
+#define SST_25VF0X0_PAGE_SIZE		4098
+
+
 };
 
 #endif /* !(_T3_H) */
diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c
--- a/drivers/pci/quirks.c	2004-06-28 15:47:57 -07:00
+++ b/drivers/pci/quirks.c	2005-01-26 00:49:52 -08:00
@@ -368,9 +368,6 @@
  * non-x86 architectures (yes Via exists on PPC among other places),
  * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
  * interrupts delivered properly.
- *
- * TODO: When we have device-specific interrupt routers,
- * quirk_via_irqpic will go away from quirks.
  */
 
 /*
@@ -393,22 +390,6 @@
 		d->irq = irq;
 }
 
-static void __init quirk_via_irqpic(struct pci_dev *dev)
-{
-	u8 irq, new_irq = dev->irq & 0xf;
-
-	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
-
-	if (new_irq != irq) {
-		printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n",
-		       dev->slot_name, irq, new_irq);
-
-		udelay(15);
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
-	}
-}
-
-
 /*
  * PIIX3 USB: We have to disable USB interrupts that are
  * hardwired to PIRQD# and may be shared with an
@@ -639,12 +620,14 @@
  *	VIA northbridges care about PCI_INTERRUPT_LINE
  */
  
-int interrupt_line_quirk;
+int via_interrupt_line_quirk;
 
 static void __init quirk_via_bridge(struct pci_dev *pdev)
 {
-	if(pdev->devfn == 0)
-		interrupt_line_quirk = 1;
+	if(pdev->devfn == 0) {
+		printk(KERN_INFO "PCI: Via IRQ fixup\n");
+		via_interrupt_line_quirk = 1;
+	}
 }
 	
 /* 
@@ -773,9 +756,6 @@
 #endif
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_via_acpi },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_via_acpi },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_2,	quirk_via_irqpic },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_5,	quirk_via_irqpic },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_6,	quirk_via_irqpic },
 
 	{ PCI_FIXUP_FINAL, 	PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_VIPER_7410,	quirk_amd_ioapic },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering },
diff -Nru a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
--- a/drivers/scsi/ahci.c	2005-01-06 18:13:46 -08:00
+++ b/drivers/scsi/ahci.c	2005-01-27 13:53:29 -08:00
@@ -248,6 +248,10 @@
 	  board_ahci }, /* ICH7 */
 	{ PCI_VENDOR_ID_INTEL, 0x27c5, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_ahci }, /* ICH7M */
+	{ PCI_VENDOR_ID_INTEL, 0x27c2, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ICH7R */
+	{ PCI_VENDOR_ID_INTEL, 0x27c3, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* ICH7R */
 	{ }	/* terminate list */
 };
 
diff -Nru a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
--- a/drivers/scsi/libata-scsi.c	2004-12-27 12:51:30 -08:00
+++ b/drivers/scsi/libata-scsi.c	2005-01-28 19:29:43 -08:00
@@ -283,7 +283,8 @@
 	/* No immediate match */
 	if(err)
 		printk(KERN_DEBUG "ata%u: no sense translation for 0x%02x\n", qc->ap->id, err);
-	
+
+	i = 0;
 	/* Fall back to interpreting status bits */
 	while(stat_table[i][0] != 0xFF)
 	{
diff -Nru a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
--- a/drivers/scsi/sata_sil.c	2004-11-13 11:27:54 -08:00
+++ b/drivers/scsi/sata_sil.c	2005-01-27 12:38:02 -08:00
@@ -71,6 +71,8 @@
 	{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
 	{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
 	{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
+	{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+	{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
 	{ }	/* terminate list */
 };
 
@@ -88,6 +90,7 @@
 	{ "ST3120023AS",	SIL_QUIRK_MOD15WRITE },
 	{ "ST3160023AS",	SIL_QUIRK_MOD15WRITE },
 	{ "ST3120026AS",	SIL_QUIRK_MOD15WRITE },
+	{ "ST3200822AS",	SIL_QUIRK_MOD15WRITE },
 	{ "ST340014ASL",	SIL_QUIRK_MOD15WRITE },
 	{ "ST360014ASL",	SIL_QUIRK_MOD15WRITE },
 	{ "ST380011ASL",	SIL_QUIRK_MOD15WRITE },
diff -Nru a/drivers/usb/hiddev.c b/drivers/usb/hiddev.c
--- a/drivers/usb/hiddev.c	2004-05-15 23:06:11 -07:00
+++ b/drivers/usb/hiddev.c	2005-01-26 14:24:52 -08:00
@@ -328,6 +328,7 @@
 				}
 				
 				schedule();
+				set_current_state(TASK_INTERRUPTIBLE);
 			}
 
 			set_current_state(TASK_RUNNING);
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c	2004-08-24 12:46:22 -07:00
+++ b/drivers/usb/storage/transport.c	2005-01-26 12:45:30 -08:00
@@ -1181,6 +1181,13 @@
 
 	/* if the command transfered well, then we go to the data stage */
 	if (result == 0) {
+
+		/* Genesys Logic interface chips need a 100us delay between
+		 * the command phase and the data phase.  Some systems need
+		 * even more, probably because of clock rate inaccuracies. */
+		if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS)
+			udelay(110);
+
 		/* send/receive data payload, if there is any */
 		if (bcb->DataTransferLength) {
 			usb_stor_transfer(srb, us);
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	2004-08-08 01:59:53 -07:00
+++ b/drivers/usb/storage/usb.c	2005-01-26 12:45:30 -08:00
@@ -996,6 +996,15 @@
 		 */
 		ss->htmplt.proc_dir = (void *)ss; 
 
+		/* According to the technical support people at Genesys Logic,
+		 * devices using their chips have problems transferring more
+		 * than 32 KB at a time.  In practice people have found that
+		 * 64 KB works okay and that's what Windows does.  But we'll
+		 * be conservative.
+		 */
+		if (ss->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS)
+			ss->htmplt.max_sectors = 64;
+
 		/* Just before we start our control thread, initialize
 		 * the device if it needs initialization */
 		if (unusual_dev && unusual_dev->initFunction)
diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
--- a/drivers/usb/storage/usb.h	2004-04-18 17:25:19 -07:00
+++ b/drivers/usb/storage/usb.h	2005-01-26 13:04:40 -08:00
@@ -193,4 +193,7 @@
 /* Function to fill an inquiry response. See usb.c for details */
 extern void fill_inquiry_response(struct us_data *us,
 	unsigned char *data, unsigned int data_len);
+
+/* Vendor ID list for devices that require special handling */
+#define USB_VENDOR_ID_GENESYS		0x05e3	/* Genesys Logic */
 #endif
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
--- a/include/linux/netfilter_ipv4/ip_conntrack.h	2004-08-29 21:11:49 -07:00
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h	2005-01-26 22:04:47 -08:00
@@ -249,10 +249,9 @@
 /* Call me when a conntrack is destroyed. */
 extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
 
-extern int ip_ct_no_defrag;
 /* Returns new sk_buff, or NULL */
 struct sk_buff *
-ip_ct_gather_frags(struct sk_buff *skb);
+ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user);
 
 /* Delete all conntracks which match. */
 extern void
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	2005-01-12 06:12:53 -08:00
+++ b/include/linux/pci_ids.h	2005-01-22 02:33:41 -08:00
@@ -1937,7 +1937,6 @@
 #define PCI_DEVICE_ID_INTEL_82801EB_5	0x24d5
 #define PCI_DEVICE_ID_INTEL_82801EB_6	0x24d6
 #define PCI_DEVICE_ID_INTEL_82801EB_7	0x24d7
-#define PCI_DEVICE_ID_INTEL_82801DB_10	0x24ca
 #define PCI_DEVICE_ID_INTEL_82801EB_11	0x24db
 #define PCI_DEVICE_ID_INTEL_82801EB_13	0x24dd
 #define PCI_DEVICE_ID_INTEL_ESB_0	0x25a0
diff -Nru a/include/net/ip.h b/include/net/ip.h
--- a/include/net/ip.h	2004-12-21 08:18:12 -08:00
+++ b/include/net/ip.h	2005-01-26 22:04:47 -08:00
@@ -227,9 +227,19 @@
 /*
  *	Functions provided by ip_fragment.o
  */
- 
-struct sk_buff *ip_defrag(struct sk_buff *skb);
-extern void ipfrag_flush(void);
+
+enum ip_defrag_users
+{
+	IP_DEFRAG_LOCAL_DELIVER,
+	IP_DEFRAG_CALL_RA_CHAIN,
+	IP_DEFRAG_CONNTRACK_IN,
+	IP_DEFRAG_CONNTRACK_OUT,
+	IP_DEFRAG_NAT_OUT,
+	IP_DEFRAG_VS_OUT,
+	IP_DEFRAG_VS_FWD
+};
+
+struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user);
 extern int ip_frag_nqueues;
 extern atomic_t ip_frag_mem;
 
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	2004-10-28 16:40:33 -07:00
+++ b/mm/filemap.c	2005-01-28 01:42:16 -08:00
@@ -2589,7 +2589,7 @@
 	long error = -EBADF;
 	struct file * file;
 	struct inode * inode;
-	unsigned long size, rlim_rss;
+	unsigned long size;
 
 	/* Doesn't work if there's no mapped file. */
 	if (!vma->vm_file)
@@ -2604,13 +2604,6 @@
 	if (end > vma->vm_end)
 		end = vma->vm_end;
 	end = ((end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
-
-	/* Make sure this doesn't exceed the process's max rss. */
-	error = -EIO;
-	rlim_rss = current->rlim ?  current->rlim[RLIMIT_RSS].rlim_cur :
-				LONG_MAX; /* default: see resource.h */
-	if ((vma->vm_mm->rss + (end - start)) > rlim_rss)
-		return error;
 
 	/* round to cluster boundaries if this isn't a "random" area. */
 	if (!VM_RandomReadHint(vma)) {
diff -Nru a/net/core/neighbour.c b/net/core/neighbour.c
--- a/net/core/neighbour.c	2005-01-14 13:50:31 -08:00
+++ b/net/core/neighbour.c	2005-01-25 22:06:42 -08:00
@@ -1469,6 +1469,7 @@
 
 	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ndm));
 	ndm = NLMSG_DATA(nlh);
+	nlh->nlmsg_flags = pid ? NLM_F_MULTI : 0;
 	ndm->ndm_family = n->ops->family;
 	ndm->ndm_flags = n->flags;
 	ndm->ndm_type = n->type;
diff -Nru a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
--- a/net/ipv4/ip_fragment.c	2004-08-29 21:11:49 -07:00
+++ b/net/ipv4/ip_fragment.c	2005-01-26 22:04:47 -08:00
@@ -72,6 +72,7 @@
 struct ipq {
 	struct ipq	*next;		/* linked list pointers			*/
 	struct list_head lru_list;	/* lru list member 			*/
+	u32		user;
 	u32		saddr;
 	u32		daddr;
 	u16		id;
@@ -242,13 +243,13 @@
 /* Memory limiting on fragments.  Evictor trashes the oldest 
  * fragment queue until we are back under the threshold.
  */
-static void __ip_evictor(int threshold)
+static void ip_evictor(void)
 {
 	struct ipq *qp;
 	struct list_head *tmp;
 	int work;
 
-	work = atomic_read(&ip_frag_mem) - threshold;
+	work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh;
 	if (work <= 0)
 		return;
 
@@ -273,11 +274,6 @@
 	}
 }
 
-static inline void ip_evictor(void)
-{
-	__ip_evictor(sysctl_ipfrag_low_thresh);
-}
-
 /*
  * Oops, a fragment queue timed out.  Kill it and send an ICMP reply.
  */
@@ -324,7 +320,8 @@
 		if(qp->id == qp_in->id		&&
 		   qp->saddr == qp_in->saddr	&&
 		   qp->daddr == qp_in->daddr	&&
-		   qp->protocol == qp_in->protocol) {
+		   qp->protocol == qp_in->protocol &&
+		   qp->user == qp_in->user) {
 			atomic_inc(&qp->refcnt);
 			write_unlock(&ipfrag_lock);
 			qp_in->last_in |= COMPLETE;
@@ -351,7 +348,7 @@
 }
 
 /* Add an entry to the 'ipq' queue for a newly received IP datagram. */
-static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph)
+static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
 {
 	struct ipq *qp;
 
@@ -363,6 +360,7 @@
 	qp->id = iph->id;
 	qp->saddr = iph->saddr;
 	qp->daddr = iph->daddr;
+	qp->user = user;
 	qp->len = 0;
 	qp->meat = 0;
 	qp->fragments = NULL;
@@ -385,7 +383,7 @@
 /* Find the correct entry in the "incomplete datagrams" queue for
  * this IP datagram, and create new one, if nothing is found.
  */
-static inline struct ipq *ip_find(struct iphdr *iph)
+static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
 {
 	__u16 id = iph->id;
 	__u32 saddr = iph->saddr;
@@ -399,7 +397,8 @@
 		if(qp->id == id		&&
 		   qp->saddr == saddr	&&
 		   qp->daddr == daddr	&&
-		   qp->protocol == protocol) {
+		   qp->protocol == protocol &&
+		   qp->user == user) {
 			atomic_inc(&qp->refcnt);
 			read_unlock(&ipfrag_lock);
 			return qp;
@@ -407,7 +406,7 @@
 	}
 	read_unlock(&ipfrag_lock);
 
-	return ip_frag_create(hash, iph);
+	return ip_frag_create(hash, iph, user);
 }
 
 /* Add new segment to existing queue. */
@@ -641,7 +640,7 @@
 }
 
 /* Process an incoming IP datagram fragment. */
-struct sk_buff *ip_defrag(struct sk_buff *skb)
+struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user)
 {
 	struct iphdr *iph = skb->nh.iph;
 	struct ipq *qp;
@@ -656,7 +655,7 @@
 	dev = skb->dev;
 
 	/* Lookup (or create) queue header */
-	if ((qp = ip_find(iph)) != NULL) {
+	if ((qp = ip_find(iph, user)) != NULL) {
 		struct sk_buff *ret = NULL;
 
 		spin_lock(&qp->lock);
@@ -686,9 +685,4 @@
 	ipfrag_secret_timer.function = ipfrag_secret_rebuild;
 	ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval;
 	add_timer(&ipfrag_secret_timer);
-}
-
-void ipfrag_flush(void)
-{
-	__ip_evictor(0);
 }
diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
--- a/net/ipv4/ip_input.c	2004-06-21 14:21:17 -07:00
+++ b/net/ipv4/ip_input.c	2005-01-26 22:04:47 -08:00
@@ -170,7 +170,7 @@
 		    && ((sk->bound_dev_if == 0) 
 			|| (sk->bound_dev_if == skb->dev->ifindex))) {
 			if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
-				skb = ip_defrag(skb);
+				skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN);
 				if (skb == NULL) {
 					read_unlock(&ip_ra_lock);
 					return 1;
@@ -291,7 +291,7 @@
 	 */
 
 	if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
-		skb = ip_defrag(skb);
+		skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER);
 		if (!skb)
 			return 0;
 	}
diff -Nru a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
--- a/net/ipv4/ipvs/ip_vs_core.c	2005-01-10 12:19:08 -08:00
+++ b/net/ipv4/ipvs/ip_vs_core.c	2005-01-26 22:04:47 -08:00
@@ -506,7 +506,7 @@
 
 	/* reassemble IP fragments, but will it happen in ICMP packets?? */
 	if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
-		skb = ip_defrag(skb);
+		skb = ip_defrag(skb, IP_DEFRAG_VS_OUT);
 		if (!skb)
 			return NF_STOLEN;
 		*skb_p = skb;
@@ -658,7 +658,7 @@
 
 	/* reassemble IP fragments */
 	if (iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
-		skb = ip_defrag(skb);
+		skb = ip_defrag(skb, IP_DEFRAG_VS_OUT);
 		if (!skb)
 			return NF_STOLEN;
 		iph = skb->nh.iph;
@@ -1164,7 +1164,7 @@
 		return NF_ACCEPT;
 
 	if (iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
-		skb = ip_defrag(skb);
+		skb = ip_defrag(skb, IP_DEFRAG_VS_FWD);
 		if (!skb)
 			return NF_STOLEN;
 		*skb_p = skb;
diff -Nru a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
--- a/net/ipv4/netfilter/ip_conntrack_core.c	2004-12-21 08:24:54 -08:00
+++ b/net/ipv4/netfilter/ip_conntrack_core.c	2005-01-26 22:04:47 -08:00
@@ -834,7 +834,10 @@
 
 	/* Gather fragments. */
 	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
-		*pskb = ip_ct_gather_frags(*pskb);
+		*pskb = ip_ct_gather_frags(*pskb,
+		                           hooknum == NF_IP_PRE_ROUTING ?
+		                           IP_DEFRAG_CONNTRACK_IN :
+		                           IP_DEFRAG_CONNTRACK_OUT);
 		if (!*pskb)
 			return NF_STOLEN;
 	}
@@ -1183,29 +1186,22 @@
 	WRITE_UNLOCK(&ip_conntrack_lock);
 }
 
-int ip_ct_no_defrag;
-
 /* Returns new sk_buff, or NULL */
 struct sk_buff *
-ip_ct_gather_frags(struct sk_buff *skb)
+ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user)
 {
 	struct sock *sk = skb->sk;
 #ifdef CONFIG_NETFILTER_DEBUG
 	unsigned int olddebug = skb->nf_debug;
 #endif
 
-	if (unlikely(ip_ct_no_defrag)) {
-		kfree_skb(skb);
-		return NULL;
-	}
-
 	if (sk) {
 		sock_hold(sk);
 		skb_orphan(skb);
 	}
 
 	local_bh_disable(); 
-	skb = ip_defrag(skb);
+	skb = ip_defrag(skb, user);
 	local_bh_enable();
 
 	if (!skb) {
diff -Nru a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c	2004-12-21 08:24:54 -08:00
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c	2005-01-26 22:04:48 -08:00
@@ -393,13 +393,6 @@
  cleanup_inandlocalops:
 	nf_unregister_hook(&ip_conntrack_local_out_ops);
  cleanup_inops:
-	/* Frag queues may hold fragments with skb->dst == NULL */
-	ip_ct_no_defrag = 1;
-	local_bh_disable();
-	br_write_lock(BR_NETPROTO_LOCK);
-	br_write_unlock(BR_NETPROTO_LOCK);
-	ipfrag_flush();
-	local_bh_enable();
 	nf_unregister_hook(&ip_conntrack_in_ops);
  cleanup_proc:
 	proc_net_remove("ip_conntrack");
diff -Nru a/net/ipv4/netfilter/ip_fw_compat.c b/net/ipv4/netfilter/ip_fw_compat.c
--- a/net/ipv4/netfilter/ip_fw_compat.c	2003-08-11 22:36:41 -07:00
+++ b/net/ipv4/netfilter/ip_fw_compat.c	2005-01-31 20:07:30 -08:00
@@ -108,7 +108,7 @@
 					  (*pskb)->nh.raw, &redirpt, pskb);
 
 		if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
-			*pskb = ip_ct_gather_frags(*pskb);
+			*pskb = ip_ct_gather_frags(*pskb, IP_DEFRAG_CONNTRACK_IN);
 
 			if (!*pskb)
 				return NF_STOLEN;
diff -Nru a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
--- a/net/ipv4/netfilter/ip_nat_standalone.c	2004-12-21 08:26:09 -08:00
+++ b/net/ipv4/netfilter/ip_nat_standalone.c	2005-01-26 22:04:48 -08:00
@@ -201,7 +201,7 @@
 	   I'm starting to have nightmares about fragments.  */
 
 	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
-		*pskb = ip_ct_gather_frags(*pskb);
+		*pskb = ip_ct_gather_frags(*pskb, IP_DEFRAG_NAT_OUT);
 
 		if (!*pskb)
 			return NF_STOLEN;
diff -Nru a/net/netsyms.c b/net/netsyms.c
--- a/net/netsyms.c	2004-12-21 08:18:12 -08:00
+++ b/net/netsyms.c	2005-01-26 22:04:48 -08:00
@@ -287,7 +287,6 @@
 EXPORT_SYMBOL(inetdev_by_index);
 EXPORT_SYMBOL(in_dev_finish_destroy);
 EXPORT_SYMBOL(ip_defrag);
-EXPORT_SYMBOL(ipfrag_flush);
 
 /* Route manipulation */
 EXPORT_SYMBOL(ip_rt_ioctl);
diff -Nru a/scripts/Configure b/scripts/Configure
--- a/scripts/Configure	2002-09-24 00:49:53 -07:00
+++ b/scripts/Configure	2005-01-26 15:19:52 -08:00
@@ -378,15 +378,18 @@
 function hex () {
 	old=$(eval echo "\${$2}")
 	def=${old:-$3}
-	def=${def#*[x,X]}
 	while :; do
 	  readln "$1 ($2) [$def] " "$def" "$old"
-	  ans=${ans#*[x,X]}
-	  if expr "$ans" : '[0-9a-fA-F][0-9a-fA-F]*$' > /dev/null; then
+	  if expr "$ans" : '0x[0-9a-fA-F][0-9a-fA-F]*$' > /dev/null; then
 	    define_hex "$2" "$ans"
 	    break
 	  else
-	    help "$2"
+	    if expr "$ans" : '[0-9a-fA-F][0-9a-fA-F]*$' > /dev/null; then
+	      define_hex "$2" "0x$ans"
+	      break
+	    else
+	      help "$2"
+	    fi
 	  fi
 	done
 }
