diff -u --recursive --new-file v1.3.76/linux/CREDITS linux/CREDITS
--- v1.3.76/linux/CREDITS	Wed Mar 20 10:59:52 1996
+++ linux/CREDITS	Thu Mar 21 08:55:09 1996
@@ -1198,6 +1198,7 @@
 E: greg@wind.rmcc.com
 D: Filesystem valid flag for MINIX filesystem.
 D: Minor kernel debugging.
+D: Development and maintenance of sysklogd.
 D: Monitoring of development kernels for long-term stability.
 D: Early implementations of Linux in a commercial environment.
 S: Dr. Greg Wettstein, Ph.D.
diff -u --recursive --new-file v1.3.76/linux/Documentation/svga.txt linux/Documentation/svga.txt
--- v1.3.76/linux/Documentation/svga.txt	Wed Mar 20 10:59:53 1996
+++ linux/Documentation/svga.txt	Wed Mar 20 16:49:01 1996
@@ -1,4 +1,4 @@
-			Video Mode Selection Support 2.4
+			Video Mode Selection Support 2.5
 	      (c) 1995, 1996 Martin Mares, <mj@k332.feld.cvut.cz>
 --------------------------------------------------------------------------------
 
@@ -222,3 +222,4 @@
 		these changes. Unfortunately, screen contents retaining works
 		only with some loaders now.
 		Added a Tseng 132x60 mode.
+2.5 (19-Mar-96)	Fixed a VESA mode scanning bug introduced in 2.4.
diff -u --recursive --new-file v1.3.76/linux/Makefile linux/Makefile
--- v1.3.76/linux/Makefile	Wed Mar 20 10:59:53 1996
+++ linux/Makefile	Wed Mar 20 10:50:37 1996
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 76
+SUBLEVEL = 77
 
 ARCH = i386
 
diff -u --recursive --new-file v1.3.76/linux/arch/i386/boot/video.S linux/arch/i386/boot/video.S
--- v1.3.76/linux/arch/i386/boot/video.S	Wed Mar 20 10:59:53 1996
+++ linux/arch/i386/boot/video.S	Wed Mar 20 16:49:01 1996
@@ -1,5 +1,5 @@
 !
-!	Display adapter & video mode setup, version 2.4 (18-Mar-96)
+!	Display adapter & video mode setup, version 2.5 (19-Mar-96)
 !
 !	Copyright (C) 1995, 1996 Martin Mares <mj@k332.feld.cvut.cz>
 !	Based on the original setup.S code (C) Linus Torvalds
@@ -753,13 +753,13 @@
 	mov	di,bp
 	cmp	ax,#0x004f	! Successful?
 	jnz	ret0
-	cmp	(di+0x400),#0x4556
+	cmp	(di+0x200),#0x4556
 	jnz	ret0
-	cmp	(di+0x402),#0x4153
+	cmp	(di+0x202),#0x4153
 	jnz	ret0
 	mov	[card_name],#vesa_name	! Set name to "VESA VGA"
 	push	gs
-	lgs	si,(di+0x40e)	! GS:SI=mode list
+	lgs	si,(di+0x20e)	! GS:SI=mode list
 	mov	cx,#128		! Iteration limit
 vesa1:	seg	gs		! Get next mode in the list
 	lodsw
diff -u --recursive --new-file v1.3.76/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v1.3.76/linux/arch/i386/kernel/setup.c	Wed Mar 20 10:59:54 1996
+++ linux/arch/i386/kernel/setup.c	Thu Mar 21 16:37:30 1996
@@ -232,8 +232,10 @@
 	switch (x86) {
 		case 4:
 			p = i486model(model);
+			break;
 		case 5:
 			p = i586model(model);
+			break;
 	}
         if (p)
                 return p;
@@ -255,7 +257,9 @@
 #ifdef __SMP__
         int n;
 
-#define CD(X) (cpu_data[n].(X))
+#define CD(X)		(cpu_data[n].X)
+/* SMP has the wrong name for loops_per_sec */
+#define loops_per_sec	udelay_val
 #define CPUN n
 
         for ( n = 0 ; n < 32 ; n++ ) {
diff -u --recursive --new-file v1.3.76/linux/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c
--- v1.3.76/linux/drivers/cdrom/cdu31a.c	Sat Mar  2 10:43:22 1996
+++ linux/drivers/cdrom/cdu31a.c	Wed Mar 20 08:16:16 1996
@@ -3168,6 +3168,10 @@
       printk("Can't unregister cdu31a\n");
       return;
    }
+
+   if (cdu31a_irq > 0)
+      free_irq(cdu31a_irq, NULL);
+
    release_region(cdu31a_port,4);
    printk("cdu31a module released.\n");
 }   
diff -u --recursive --new-file v1.3.76/linux/drivers/cdrom/mcd.c linux/drivers/cdrom/mcd.c
--- v1.3.76/linux/drivers/cdrom/mcd.c	Tue Mar  5 10:10:54 1996
+++ linux/drivers/cdrom/mcd.c	Thu Mar 21 08:55:44 1996
@@ -60,6 +60,7 @@
 	17 June 95 Modifications By Andrew J. Kroll <ag784@freenet.buffalo.edu>
 	07 July 1995 Modifications by Andrew J. Kroll
 
+	Bjorn Ekwall <bj0rn@blox.se> added unregister_blkdev to mcd_init()
 */
 
 #include <linux/module.h>
@@ -1181,6 +1182,7 @@
 	}
 
         if (check_region(mcd_port, 4)) {
+	  unregister_blkdev(MAJOR_NR, "mcd");
 	  printk("Init failed, I/O port (%X) already in use\n",
 		 mcd_port);
           return -EIO;
@@ -1204,6 +1206,7 @@
 	if (count >= 2000000) {
 		printk("Init failed. No mcd device at 0x%x irq %d\n",
 		     mcd_port, mcd_irq);
+		unregister_blkdev(MAJOR_NR, "mcd");
                 return -EIO;
 	}
 	count = inb(MCDPORT(0));		/* pick up the status */
@@ -1211,13 +1214,16 @@
 	outb(MCMD_GET_VERSION,MCDPORT(0));
 	for(count=0;count<3;count++)
 		if(getValue(result+count)) {
+			unregister_blkdev(MAJOR_NR, "mcd");
 			printk("mitsumi get version failed at 0x%d\n",
 			       mcd_port);
                         return -EIO;
 		}	
 
-	if (result[0] == result[1] && result[1] == result[2])
+	if (result[0] == result[1] && result[1] == result[2]) {
+		unregister_blkdev(MAJOR_NR, "mcd");
                 return -EIO;
+	}
 	printk("Mitsumi status, type and version : %02X %c %x ",
 	       result[0],result[1],result[2]);
 
@@ -1239,6 +1245,7 @@
 	if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD", NULL))
 	{
 		printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq);
+		unregister_blkdev(MAJOR_NR, "mcd");
                 return -EIO;
 	}
 	request_region(mcd_port, 4,"mcd");
diff -u --recursive --new-file v1.3.76/linux/drivers/char/console.c linux/drivers/char/console.c
--- v1.3.76/linux/drivers/char/console.c	Sun Mar 17 09:04:06 1996
+++ linux/drivers/char/console.c	Wed Mar 20 11:39:51 1996
@@ -1383,8 +1383,10 @@
 
 	disable_bh(CONSOLE_BH);
 	while (!tty->stopped &&	count) {
+		enable_bh(CONSOLE_BH);
 		c = from_user ? get_user(buf) : *buf;
 		buf++; n++; count--;
+		disable_bh(CONSOLE_BH);
 
 		if (utf) {
 		    /* Combine UTF-8 into Unicode */
diff -u --recursive --new-file v1.3.76/linux/drivers/char/ftape/Makefile linux/drivers/char/ftape/Makefile
--- v1.3.76/linux/drivers/char/ftape/Makefile	Fri Mar 15 16:03:11 1996
+++ linux/drivers/char/ftape/Makefile	Thu Mar 21 08:55:09 1996
@@ -30,7 +30,7 @@
 #	FDC_82078SL	- If you have a 82078SL, define this.
 
 FTAPE_OPT       = -DVERIFY_HEADERS -DNR_BUFFERS=3 -DCLK_48MHZ=1 \
-	-DFDC_82078SL -DNO_TRACE
+	-DNO_TRACE
 
 #  If you're using a non-standard floppy disk controller for the
 #  tape drive, enable one (only!) of the following lines and set
diff -u --recursive --new-file v1.3.76/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v1.3.76/linux/drivers/char/lp.c	Fri Mar 15 16:03:14 1996
+++ linux/drivers/char/lp.c	Wed Mar 20 10:50:02 1996
@@ -602,6 +602,7 @@
 {
 	int offset = 0;
 	int count = 0;
+	int failed = 0;
 
 	if (register_chrdev(LP_MAJOR,"lp",&lp_fops)) {
 		printk("lp: unable to get major %d\n", LP_MAJOR);
@@ -623,13 +624,25 @@
 		if (specified) {
 			if (lp_probe(offset) <= 0) {
 				printk(KERN_INFO "lp%d: Not found\n", offset);
-				return -EIO;
+				failed++;
 			} else
 				count++;
 		}
 	}
+	/* Successful specified devices increase count
+	 * Unsuccessful specified devices increase failed
+	 */
 	if (count)
 		return 0;
+	if (failed) {
+		printk(KERN_INFO "lp: No override devices found.\n");
+		unregister_chrdev(LP_MAJOR,"lp");
+		return -EIO;
+	}
+	/* Only get here if there were no specified devices. To continue 
+	 * would be silly since the above code has scribbled all over the
+	 * probe list.
+	 */
 #endif
 	/* take on all known port values */
 	for (offset = 0; offset < LP_NO; offset++) {
diff -u --recursive --new-file v1.3.76/linux/drivers/scsi/NCR5380.c linux/drivers/scsi/NCR5380.c
--- v1.3.76/linux/drivers/scsi/NCR5380.c	Sat Mar  2 10:43:36 1996
+++ linux/drivers/scsi/NCR5380.c	Wed Mar 20 10:50:02 1996
@@ -809,6 +809,17 @@
     hostdata->connected = NULL;
     hostdata->issue_queue = NULL;
     hostdata->disconnected_queue = NULL;
+#ifdef NCR5380_STATS
+    for (i = 0; i < 8; ++i) {
+	hostdata->time_read[i] = 0;
+	hostdata->time_write[i] = 0;
+	hostdata->bytes_read[i] = 0;
+	hostdata->bytes_write[i] = 0;
+    }
+    hostdata->timebase = 0;
+    hostdata->pendingw = 0;
+    hostdata->pendingr = 0;
+#endif
 
     /* The CHECK code seems to break the 53C400. Will check it later maybe */
     if (flags & FLAG_NCR53C400)
@@ -916,6 +927,7 @@
 #if (NDEBUG & NDEBUG_NO_WRITE)
     switch (cmd->cmnd[0]) {
     case WRITE:
+    case WRITE_6:
     case WRITE_10:
 	printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n",
 	    instance->host_no);
@@ -925,6 +937,34 @@
     }
 #endif /* (NDEBUG & NDEBUG_NO_WRITE) */
 
+#ifdef NCR5380_STATS
+# if 0
+    if (!hostdata->connected && !hostdata->issue_queue &&
+	!hostdata->disconnected_queue) {
+	hostdata->timebase = jiffies;
+    }
+# endif
+# ifdef NCR5380_STAT_LIMIT
+    if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
+# endif
+	switch (cmd->cmnd[0])
+	{
+	    case WRITE:
+	    case WRITE_6:
+	    case WRITE_10:
+		hostdata->time_write[cmd->target] -= (jiffies - hostdata->timebase);
+		hostdata->bytes_write[cmd->target] += cmd->request_bufflen;
+		hostdata->pendingw++;
+		break;
+	    case READ:
+	    case READ_6:
+	    case READ_10:
+		hostdata->time_read[cmd->target] -= (jiffies - hostdata->timebase);
+		hostdata->bytes_read[cmd->target] += cmd->request_bufflen;
+		hostdata->pendingr++;
+		break;
+	}
+#endif
 
     /* 
      * We use the host_scribble field as a pointer to the next command  
@@ -1224,6 +1264,32 @@
     } while (!done);
 }
 
+#ifdef NCR5380_STATS
+static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd* cmd)
+{
+# ifdef NCR5380_STAT_LIMIT
+    if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
+# endif
+	switch (cmd->cmnd[0])
+	{
+	    case WRITE:
+	    case WRITE_6:
+	    case WRITE_10:
+		hostdata->time_write[cmd->target] += (jiffies - hostdata->timebase);
+		/*hostdata->bytes_write[cmd->target] += cmd->request_bufflen;*/
+		hostdata->pendingw--;
+		break;
+	    case READ:
+	    case READ_6:
+	    case READ_10:
+		hostdata->time_read[cmd->target] += (jiffies - hostdata->timebase);
+		/*hostdata->bytes_read[cmd->target] += cmd->request_bufflen;*/
+		hostdata->pendingr--;
+		break;
+	}
+}
+#endif
+
 /* 
  * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, 
  *	int tag);
@@ -1469,6 +1535,9 @@
 	    return -1;
 	}
 	cmd->result = DID_BAD_TARGET << 16;
+#ifdef NCR5380_STATS
+	collect_stats(hostdata, cmd);
+#endif
 	cmd->scsi_done(cmd);
 	NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 #if (NDEBUG & NDEBUG_SELECTION)
@@ -2322,6 +2391,9 @@
 		    printk("scsi%d : target %d lun %d linked request done, calling scsi_done().\n",
 			instance->host_no, cmd->target, cmd->lun);
 #endif
+#ifdef NCR5380_STATS
+		    collect_stats(hostdata, cmd);
+#endif
 		    cmd->scsi_done(cmd);
 		    cmd = hostdata->connected;
 		    break;
@@ -2387,9 +2459,13 @@
 #if (NDEBUG & NDEBUG_QUEUES)
 			printk("scsi%d : REQUEST SENSE added to head of issue queue\n",instance->host_no);
 #endif
-		   } else
+		   } else {
 #endif /* def AUTOSENSE */
+#ifdef NCR5380_STATS
+			collect_stats(hostdata, cmd);
+#endif
 			cmd->scsi_done(cmd);
+		   }
 
 		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 		    /* 
@@ -2557,6 +2633,9 @@
 		    hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
 		    hostdata->connected = NULL;
 		    cmd->result = DID_ERROR << 16;
+#ifdef NCR5380_STATS
+		    collect_stats(hostdata, cmd);
+#endif
 		    cmd->scsi_done(cmd);
 		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 		    return;
@@ -2841,7 +2920,7 @@
 
     cli();
     NCR5380_setup(instance);
-    
+
 #if (NDEBUG & NDEBUG_ABORT)
     printk("scsi%d : abort called\n", instance->host_no);
     printk("        basr 0x%X, sr 0x%X\n", 
diff -u --recursive --new-file v1.3.76/linux/drivers/scsi/NCR5380.h linux/drivers/scsi/NCR5380.h
--- v1.3.76/linux/drivers/scsi/NCR5380.h	Sat Mar  2 10:43:36 1996
+++ linux/drivers/scsi/NCR5380.h	Wed Mar 20 10:50:02 1996
@@ -265,6 +265,15 @@
     unsigned long time_expires;			/* in jiffies, set prior to sleeping */
     struct Scsi_Host *next_timer;
 #endif
+#ifdef NCR5380_STATS
+    unsigned timebase;				/* Base for time calcs */
+    long time_read[8];				/* time to do reads */
+    long time_write[8];				/* time to do writes */
+    unsigned long bytes_read[8];		/* bytes read */
+    unsigned long bytes_write[8];		/* byytes written */
+    unsigned pendingr;
+    unsigned pendingw;
+#endif
 };
 
 #ifdef __KERNEL__
diff -u --recursive --new-file v1.3.76/linux/drivers/scsi/README.g_NCR5380 linux/drivers/scsi/README.g_NCR5380
--- v1.3.76/linux/drivers/scsi/README.g_NCR5380	Wed Feb  7 15:11:27 1996
+++ linux/drivers/scsi/README.g_NCR5380	Wed Mar 20 10:50:02 1996
@@ -44,3 +44,49 @@
 
 Kevin Lentin
 K.Lentin@cs.monash.edu.au
+REAME file for the Linux g_NCR5380 driver.
+
+(c) 1993 Drew Eckhard
+NCR53c400 extensions (c) 1994,1995,1996 Kevin Lentin
+
+This file documents the NCR53c400 extensions by Kevin Lentin and some
+enhancements to the NCR5380 core.
+
+This driver supports both NCR5380 and NCR53c400 cards in port or memory
+mapped modes. Currently this driver can only support one of those mapping
+modes at a time but it does support both of these chips at the same time.
+The next release of this driver will support port & memory mapped cards at
+the same time. It should be able to handle multiple different cards in the
+same machine.
+
+The drivers/scsi/Makefile has an override in it for the most common
+NCR53c400 card, the Trantor T130B in its default configuration:
+	Port: 0x350
+	IRQ : 5
+
+The NCR53c400 does not support DMA but it does have Pseudo-DMA which is
+supported by the driver.
+
+If the default configuration does not work for you, you can use the kernel
+command lines (eg using the lilo append command):
+	ncr5380=port,irq,dma
+	ncr53c400=port,irq
+or
+	ncr5380=base,irq,dma
+	ncr53c400=base,irq
+
+The driver does not probe for any addresses or ports other than those in
+the OVERRIDE or given to the kernel as above.
+
+This driver provides some information on what it has detected in
+/proc/scsi/g_NCR5380/x where x is the scsi card number as detected at boot
+time. More info to come in the future.
+
+When NCR53c400 support is compiled in, BIOS paramaters will be returned by
+the driver (the raw 5380 driver does not and I don't plan to fiddle with
+it!).
+
+This driver works as a module.
+
+Kevin Lentin
+K.Lentin@cs.monash.edu.au
diff -u --recursive --new-file v1.3.76/linux/drivers/scsi/g_NCR5380.c linux/drivers/scsi/g_NCR5380.c
--- v1.3.76/linux/drivers/scsi/g_NCR5380.c	Sat Mar  2 10:43:40 1996
+++ linux/drivers/scsi/g_NCR5380.c	Wed Mar 20 10:50:02 1996
@@ -65,6 +65,8 @@
 #define NCR53C400_PSEUDO_DMA 1
 #define PSEUDO_DMA
 #define NCR53C400
+#define NCR5380_STATS
+#undef NCR5380_STAT_LIMIT
 #endif
 #if defined(CONFIG_SCSI_G_NCR5380_PORT) && defined(CONFIG_SCSI_G_NCR5380_MEM)
 #error You can not configure the Generic NCR 5380 SCSI Driver for memory mapped I/O and port mapped I/O at the same time (yet)
@@ -238,8 +240,8 @@
     return count;
 }
 
-const char * generic_NCR5380_info (void) {
-    static const char string[]="Generic NCR5380/53C400 Info";
+const char * generic_NCR5380_info (struct Scsi_Host* host) {
+    static const char string[]="Generic NCR5380/53C400 Driver";
     return string;
 }
 
@@ -285,40 +287,6 @@
 }
 #endif
 
-int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout)
-{
-	int len = 0;
-	struct Scsi_Host *scsi_ptr;
-
-	for (scsi_ptr = first_instance; scsi_ptr; scsi_ptr=scsi_ptr->next)
-		if (scsi_ptr->host_no == hostno)
-			break;
-
-	len += sprintf(buffer+len, "SCSI host number %d : %s\n", scsi_ptr->host_no,  scsi_ptr->hostt->name);
-	len += sprintf(buffer+len, "Generic NCR5380 driver version %d\n", GENERIC_NCR5380_PUBLIC_RELEASE);
-	len += sprintf(buffer+len, "NCR5380 driver core version %d\n", NCR5380_PUBLIC_RELEASE);
-#ifdef NCR53C400
-	len += sprintf(buffer+len, "NCR53C400 driver extension version %d\n", NCR53C400_PUBLIC_RELEASE);
-	len += sprintf(buffer+len, "NCR53C400 card%s detected\n",  (((struct NCR5380_hostdata *)scsi_ptr->hostdata)->flags & FLAG_NCR53C400)?"":" not");
-# if NCR53C400_PSEUDO_DMA
-	len += sprintf(buffer+len, "NCR53C400 pseudo DMA being used\n");
-# endif
-#else
-	len += sprintf(buffer+len, "NO NCR53C400 driver extensions\n");
-#endif
-	len += sprintf(buffer+len, "Using %s mapping at %s 0x%x, ", STRVAL(NCR5380_map_config), STRVAL(NCR5380_map_name), scsi_ptr->NCR5380_instance_name);
-	if (scsi_ptr->irq == IRQ_NONE)
-		len += sprintf(buffer+len, "interrupts disabled\n");
-	else
-		len += sprintf(buffer+len, "on interrupt %d\n", scsi_ptr->irq);
-
-	*start = buffer + offset;
-	len -= offset;
-	if (len > length)
-		len = length;
-	return len;
-}
-
 #if NCR53C400_PSEUDO_DMA
 static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,    int len)
 {
@@ -564,6 +532,169 @@
 #endif /* PSEUDO_DMA */
 
 #include "NCR5380.c"
+
+#define PRINTP(x) len += sprintf(buffer+len, x)
+#define ANDP ,
+
+static int sprint_opcode(char* buffer, int len, int opcode) {
+    int start = len;
+    PRINTP("0x%02x " ANDP opcode);
+    return len-start;
+}
+
+static int sprint_command (char* buffer, int len, unsigned char *command) {
+    int i,s,start=len;
+    len += sprint_opcode(buffer, len, command[0]);
+    for ( i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
+	PRINTP("%02x " ANDP command[i]);
+    PRINTP("\n");
+    return len-start;
+}
+
+static int sprint_Scsi_Cmnd (char* buffer, int len, Scsi_Cmnd *cmd) {
+    int start = len;
+    PRINTP("destination target %d, lun %d\n" ANDP
+       cmd->host->host_no ANDP
+       cmd->target ANDP
+       cmd->lun);
+    PRINTP("        command = ");
+    len += sprint_command (buffer, len, cmd->cmnd);
+    return len-start;
+}
+
+const char *const scsi_device_types[] =
+{
+    "Direct-Access    ",
+    "Sequential-Access",
+    "Printer          ",
+    "Processor        ",
+    "WORM             ",
+    "CD-ROM           ",
+    "Scanner          ",
+    "Optical Device   ",
+    "Medium Changer   ",
+    "Communications   "
+};
+#define MAX_SCSI_DEVICE_CODE sizeof(scsi_device_types)/sizeof(char*)
+
+int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout)
+{
+    int len = 0;
+    NCR5380_local_declare();
+    unsigned char status;
+    int i;
+    struct Scsi_Host *scsi_ptr;
+	Scsi_Device *dev;
+    Scsi_Cmnd *ptr;
+    struct NCR5380_hostdata *hostdata;
+
+    cli();
+
+    for (scsi_ptr = first_instance; scsi_ptr; scsi_ptr=scsi_ptr->next)
+	if (scsi_ptr->host_no == hostno)
+	    break;
+    NCR5380_setup(scsi_ptr);
+    hostdata = (struct NCR5380_hostdata *)scsi_ptr->hostdata;
+
+    PRINTP("SCSI host number %d : %s\n" ANDP scsi_ptr->host_no ANDP scsi_ptr->hostt->name);
+    PRINTP("Generic NCR5380 driver version %d\n" ANDP GENERIC_NCR5380_PUBLIC_RELEASE);
+    PRINTP("NCR5380 core version %d\n" ANDP NCR5380_PUBLIC_RELEASE);
+#ifdef NCR53C400
+    PRINTP("NCR53C400 extension version %d\n" ANDP NCR53C400_PUBLIC_RELEASE);
+    PRINTP("NCR53C400 card%s detected\n" ANDP  (((struct NCR5380_hostdata *)scsi_ptr->hostdata)->flags & FLAG_NCR53C400)?"":" not");
+# if NCR53C400_PSEUDO_DMA
+    PRINTP("NCR53C400 pseudo DMA used\n");
+# endif
+#else
+    PRINTP("NO NCR53C400 driver extensions\n");
+#endif
+    PRINTP("Using %s mapping at %s 0x%x, " ANDP STRVAL(NCR5380_map_config) ANDP STRVAL(NCR5380_map_name) ANDP scsi_ptr->NCR5380_instance_name);
+    if (scsi_ptr->irq == IRQ_NONE)
+	PRINTP("no interrupt\n");
+    else
+	PRINTP("on interrupt %d\n" ANDP scsi_ptr->irq);
+
+#ifdef NCR5380_STATS
+    if (hostdata->connected || hostdata->issue_queue || hostdata->disconnected_queue)
+	PRINTP("There are commands pending, transfer rates may be crud\n");
+    if (hostdata->pendingr)
+	PRINTP("  %d pending reads" ANDP hostdata->pendingr);
+    if (hostdata->pendingw)
+	PRINTP("  %d pending writes" ANDP hostdata->pendingw);
+    if (hostdata->pendingr || hostdata->pendingw)
+	PRINTP("\n");
+    for (dev = scsi_devices; dev; dev=dev->next) {
+	if (dev->host == scsi_ptr) {
+	    unsigned long br = hostdata->bytes_read[dev->id];
+	    unsigned long bw = hostdata->bytes_write[dev->id];
+	    long tr = hostdata->time_read[dev->id] / HZ;
+	    long tw = hostdata->time_write[dev->id] / HZ;
+
+	    PRINTP("  T:%d %s " ANDP dev->id ANDP (dev->type < MAX_SCSI_DEVICE_CODE) ? scsi_device_types[(int)dev->type] : "Unknown");
+	    for (i=0; i<8; i++)
+		if (dev->vendor[i] >= 0x20)
+		    *(buffer+(len++)) = dev->vendor[i];
+	    *(buffer+(len++)) = ' ';
+	    for (i=0; i<16; i++)
+		if (dev->model[i] >= 0x20)
+		    *(buffer+(len++)) = dev->model[i];
+	    *(buffer+(len++)) = ' ';
+	    for (i=0; i<4; i++)
+		if (dev->rev[i] >= 0x20)
+		    *(buffer+(len++)) = dev->rev[i];
+	    *(buffer+(len++)) = ' ';
+				    
+	    PRINTP("\n%10d kb read    in %5d secs" ANDP br/1024 ANDP tr);
+	    if (tr)
+		PRINTP(" @ %5d bps" ANDP br / tr); 
+
+	    PRINTP("\n%10d kb written in %5d secs" ANDP bw/1024 ANDP tw);
+	    if (tw)
+		PRINTP(" @ %5d bps" ANDP bw / tw); 
+	    PRINTP("\n");
+	}
+    }
+#endif
+	
+    status = NCR5380_read(STATUS_REG);
+    if (!(status & SR_REQ))
+	PRINTP("REQ not asserted, phase unknown.\n");
+    else {
+	for (i = 0; (phases[i].value != PHASE_UNKNOWN) &&
+		    (phases[i].value != (status & PHASE_MASK)); ++i)
+	    ;
+	PRINTP("Phase %s\n" ANDP phases[i].name);
+    }
+
+    if (!hostdata->connected) {
+	PRINTP("No currently connected command\n");
+    } else {
+	len += sprint_Scsi_Cmnd (buffer, len, (Scsi_Cmnd *) hostdata->connected);
+    }
+
+    PRINTP("issue_queue\n");
+
+    for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr;
+		ptr = (Scsi_Cmnd *) ptr->host_scribble)
+	len += sprint_Scsi_Cmnd (buffer, len, ptr);
+
+    PRINTP("disconnected_queue\n");
+
+    for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
+		ptr = (Scsi_Cmnd *) ptr->host_scribble)
+	len += sprint_Scsi_Cmnd (buffer, len, ptr);
+	
+    *start = buffer + offset;
+    len -= offset;
+    if (len > length)
+	    len = length;
+    sti();
+    return len;
+}
+
+#undef PRINTP
+#undef ANDP
+
 #ifdef MODULE
 /* Eventually this will go into an include file, but this will be later */
 Scsi_Host_Template driver_template = GENERIC_NCR5380;
diff -u --recursive --new-file v1.3.76/linux/drivers/scsi/g_NCR5380.h linux/drivers/scsi/g_NCR5380.h
--- v1.3.76/linux/drivers/scsi/g_NCR5380.h	Wed Feb  7 15:11:28 1996
+++ linux/drivers/scsi/g_NCR5380.h	Wed Mar 20 10:50:02 1996
@@ -47,6 +47,7 @@
 int generic_NCR5380_release_resources(struct Scsi_Host *);
 int generic_NCR5380_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int generic_NCR5380_reset(Scsi_Cmnd *);
+const char* generic_NCR5380_info(struct Scsi_Host *);
 #ifdef BIOSPARAM
 int generic_NCR5380_biosparam(Disk *, kdev_t, int *);
 #endif
diff -u --recursive --new-file v1.3.76/linux/drivers/sound/configure.c linux/drivers/sound/configure.c
--- v1.3.76/linux/drivers/sound/configure.c	Wed Mar 20 10:59:58 1996
+++ linux/drivers/sound/configure.c	Wed Mar 20 08:27:42 1996
@@ -418,7 +418,6 @@
     {
 
       for (i = 0; i < OPT_LAST; i++)
-      if (!(DISABLED_OPTIONS & B (i)))
 	if (mask == B (i))
 	  {
 	    unsigned int             j;
@@ -778,7 +777,7 @@
 		  "Check from manual of the card");
 
   ask_int_choice (B (OPT_SB), "SB_MPU_IRQ",
-		  "SB MPU401 IRQ (Jazz16 and ES1688)",
+		  "SB MPU401 IRQ (Jazz16, SM Wave and ES1688)",
 		  FMT_INT,
 		  -1,
 		  "Check from manual of the card");
diff -u --recursive --new-file v1.3.76/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- v1.3.76/linux/fs/msdos/namei.c	Wed Mar 13 10:09:20 1996
+++ linux/fs/msdos/namei.c	Thu Mar 21 18:08:30 1996
@@ -590,7 +590,6 @@
 	mark_buffer_dirty(old_bh, 1);
 	/* update binary info for conversion, i_attrs */
 	if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) {
-		msdos_read_inode(old_inode);
 		MSDOS_I(old_inode)->i_attrs = is_hid
 			? (MSDOS_I(old_inode)->i_attrs |  ATTR_HIDDEN)
 			: (MSDOS_I(old_inode)->i_attrs &~ ATTR_HIDDEN);
diff -u --recursive --new-file v1.3.76/linux/fs/nfs/nfsroot.c linux/fs/nfs/nfsroot.c
--- v1.3.76/linux/fs/nfs/nfsroot.c	Wed Mar 20 10:59:59 1996
+++ linux/fs/nfs/nfsroot.c	Thu Mar 21 08:56:46 1996
@@ -27,6 +27,9 @@
  *	Martin Mares	:	Code cleanup.
  *	Martin Mares	: (2.1)	BOOTP and RARP made configuration options.
  *	Martin Mares	:	Server hostname generation fixed.
+ *	Gerd Knorr	:	Fixed wired inode handling
+ *	Martin Mares	: (2.2)	"0.0.0.0" addresses from command line ignored.
+ *	Martin Mares	:	RARP replies not tested for server address.
  *
  *
  *	Known bugs and caveats:
@@ -128,7 +131,7 @@
 
 /* Yes, we use sys_socket, but there's no include file for it */
 extern asmlinkage int sys_socket(int family, int type, int protocol);
-
+     
 
 /***************************************************************************
 
@@ -302,12 +305,6 @@
 		kfree_skb(skb, FREE_READ);
 		return 0;
 	}
-	/* Discard packets which are not from specified server. */
-	if (server.sin_addr.s_addr != INADDR_NONE &&
-	    server.sin_addr.s_addr != sip) {
-		kfree_skb(skb, FREE_READ);
-		return 0;
-	}
 
 	/*
 	 * The packet is what we were looking for. Setup the global
@@ -1170,7 +1167,7 @@
 	while (ip && *ip) {
 		if ((cp = strchr(ip, ':')))
 			*cp++ = '\0';
-		if (strlen(ip) > 0) {
+		if (strlen(ip) > 0 && strcmp(ip, "0.0.0.0")) {
 			switch (num) {
 			case 0:
 				myaddr.sin_addr.s_addr = in_aton(ip);
@@ -1361,8 +1358,8 @@
 
  ***************************************************************************/
 
-static struct file nfs_file;		/* File descriptor containing socket */
-static struct inode nfs_inode;		/* Inode containing socket */
+static struct file  *nfs_file;
+static struct inode *nfs_sock_inode;	/* Inode containing socket */
 static int *rpc_packet = NULL;		/* RPC packet */
 
 
@@ -1371,63 +1368,28 @@
  */
 static int root_nfs_open(void)
 {
-	struct file *filp;
-
 	/* Open the socket */
 	if ((nfs_data.fd = sys_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
 		printk(KERN_ERR "Root-NFS: Cannot open UDP socket!\n");
 		return -1;
 	}
-	/*
-	 * Copy the file and inode data area so that we can remove the
-	 * file lateron without killing the socket. After all this the
-	 * closing routine just needs to remove the file pointer from the
-	 * init-task descriptor.
-	 */
-	filp = current->files->fd[nfs_data.fd];
-	memcpy(&nfs_file, filp, sizeof(struct file));
-	nfs_file.f_next = nfs_file.f_prev = NULL;
-	current->files->fd[nfs_data.fd] = &nfs_file;
-	filp->f_count = 0;		/* Free the file descriptor */
-
-	memcpy(&nfs_inode, nfs_file.f_inode, sizeof(struct inode));
-	nfs_inode.i_hash_next = nfs_inode.i_hash_prev = NULL;
-	nfs_inode.i_next = nfs_inode.i_prev = NULL;
-	clear_inode(nfs_file.f_inode);
-	nfs_file.f_inode = &nfs_inode;
-	nfs_inode.u.socket_i.inode = &nfs_inode;
-	nfs_file.private_data = NULL;
+	nfs_file = current->files->fd[nfs_data.fd];
+	nfs_sock_inode = nfs_file->f_inode;
 
+	/* keep socket open. Do we need really this ? */
+	/* nfs_file->f_count++; */                   
 	return 0;
 }
 
 
 /*
- *  Close the UDP file descriptor. The main part of preserving the socket
- *  has already been done after opening it. Now we have to remove the file
- *  descriptor from the init task.
+ *  Close the UDP file descriptor. If nfs_read_super is successful, it
+ *  increases the reference count, so we can simply close the file, and
+ *  the socket keeps open.
  */
 static void root_nfs_close(int close_all)
 {
-	/* Remove the file from the list of open files */
-	current->files->fd[nfs_data.fd] = NULL;
-	if (current->files->count > 0)
-		current->files->count--;
-
-	/* Clear memory used by the RPC packet */
-	if (rpc_packet != NULL)
-		kfree_s(rpc_packet, nfs_data.wsize + 1024);
-
-	/*
-	 * In case of an error we also have to close the socket again
-	 * (sigh)
-	 */
-	if (close_all) {
-		nfs_inode.u.socket_i.inode = NULL;	/* The inode is already
-							 * cleared */
-		if (nfs_file.f_op->release)
-			nfs_file.f_op->release(&nfs_inode, &nfs_file);
-	}
+	sys_close(nfs_data.fd);
 }
 
 
@@ -1441,14 +1403,15 @@
 	struct sockaddr_in *sin = &myaddr;
 	int i;
 
-	if (nfs_inode.u.socket_i.ops->bind) {
+	if (nfs_sock_inode->u.socket_i.ops->bind) {
 		for (i = 0; i < NPORTS && res < 0; i++) {
 			sin->sin_port = htons(port++);
 			if (port > ENDPORT) {
 				port = STARTPORT;
 			}
-			res = nfs_inode.u.socket_i.ops->bind(&nfs_inode.u.socket_i,
-							     (struct sockaddr *)sin, sizeof(struct sockaddr_in));
+			res = nfs_sock_inode->u.socket_i.ops->bind
+				(&nfs_sock_inode->u.socket_i,
+				 (struct sockaddr *)sin, sizeof(struct sockaddr_in));
 		}
 	}
 	if (res < 0) {
@@ -1468,11 +1431,10 @@
  */
 static int *root_nfs_call(int *end)
 {
-	struct file *filp;
 	struct socket *sock;
 	int dummylen;
 	static struct nfs_server s = {
-		&nfs_file,		/* struct file *	 */
+		0,			/* struct file *	 */
 		0,			/* struct rsock *	 */
 		{
 		    0, "",
@@ -1486,8 +1448,8 @@
 		3 * HZ, 60 * HZ, 30 * HZ, 60 * HZ, "\0"
 	};
 
-	filp = &nfs_file;
-	sock = &((filp->f_inode)->u.socket_i);
+	s.file = nfs_file;
+	sock = &((nfs_file->f_inode)->u.socket_i);
 
 	/* extract the other end of the socket into s->toaddr */
 	sock->ops->getname(sock, &(s.toaddr), &dummylen, 1);
@@ -1495,7 +1457,7 @@
 	((struct sockaddr_in *) &s.toaddr)->sin_family = server.sin_family;
 	((struct sockaddr_in *) &s.toaddr)->sin_addr.s_addr = server.sin_addr.s_addr;
 
-	s.rsock = rpc_makesock(filp);
+	s.rsock = rpc_makesock(nfs_file);
 	s.flags = nfs_data.flags;
 	s.rsize = nfs_data.rsize;
 	s.wsize = nfs_data.wsize;
@@ -1507,12 +1469,13 @@
 	 * First connect the UDP socket to a server port, then send the
 	 * packet out, and finally check wether the answer is OK.
 	 */
-	if (nfs_inode.u.socket_i.ops->connect &&
-	    nfs_inode.u.socket_i.ops->connect(&nfs_inode.u.socket_i,
-						(struct sockaddr *) &server,
-						sizeof(struct sockaddr_in),
-						nfs_file.f_flags) < 0)
-		            return NULL;
+	if (nfs_sock_inode->u.socket_i.ops->connect &&
+	    nfs_sock_inode->u.socket_i.ops->connect
+	    (&nfs_sock_inode->u.socket_i,
+	     (struct sockaddr *) &server,
+	     sizeof(struct sockaddr_in),
+	     nfs_file->f_flags) < 0)
+		return NULL;
 	if (nfs_rpc_call(&s, rpc_packet, end, nfs_data.wsize) < 0)
 		return NULL;
 	return rpc_verify(rpc_packet);
@@ -1643,11 +1606,12 @@
 	/* First connect to the nfsd port on the server */
 	server.sin_port = htons(nfs_port);
 	nfs_data.addr = server;
-	if (nfs_inode.u.socket_i.ops->connect &&
-	    nfs_inode.u.socket_i.ops->connect(&nfs_inode.u.socket_i,
-						(struct sockaddr *) &server,
-						sizeof(struct sockaddr_in),
-						nfs_file.f_flags) < 0) {
+	if (nfs_sock_inode->u.socket_i.ops->connect &&
+	    nfs_sock_inode->u.socket_i.ops->connect
+	    (&nfs_sock_inode->u.socket_i,
+	     (struct sockaddr *) &server,
+	     sizeof(struct sockaddr_in),
+	     nfs_file->f_flags) < 0) {
 		root_nfs_close(1);
 		return -1;
 	}
diff -u --recursive --new-file v1.3.76/linux/fs/proc/array.c linux/fs/proc/array.c
--- v1.3.76/linux/fs/proc/array.c	Wed Feb 28 11:50:10 1996
+++ linux/fs/proc/array.c	Thu Mar 21 08:55:09 1996
@@ -194,6 +194,7 @@
 {
 	int i, len;
 	unsigned sum = 0;
+	extern unsigned long total_forks;
 
 	for (i = 0 ; i < NR_IRQS ; i++)
 		sum += kstat.interrupts[i];
@@ -230,9 +231,11 @@
 		len += sprintf(buffer + len, " %u", kstat.interrupts[i]);
 	len += sprintf(buffer + len,
 		"\nctxt %u\n"
-		"btime %lu\n",
+		"btime %lu\n"
+		"processes %lu\n",
 		kstat.context_swtch,
-		xtime.tv_sec - jiffies / HZ);
+		xtime.tv_sec - jiffies / HZ,
+		total_forks);
 	return len;
 }
 
diff -u --recursive --new-file v1.3.76/linux/include/asm-alpha/atomic.h linux/include/asm-alpha/atomic.h
--- v1.3.76/linux/include/asm-alpha/atomic.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-alpha/atomic.h	Wed Mar 20 15:00:13 1996
@@ -0,0 +1,53 @@
+#ifndef __ARCH_I386_ATOMIC__
+#define __ARCH_I386_ATOMIC__
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ */
+
+/*
+ * Make sure gcc doesn't try to be clever and move things around
+ * on us. We need to use _exactly_ the address the user gave us,
+ * not some alias that contains the same information.
+ */
+#define __atomic_fool_gcc(x) (*(struct { int a[100]; } *)x)
+
+typedef int atomic_t;
+
+extern __inline__ void atomic_add(atomic_t i, atomic_t * v)
+{
+	unsigned long temp;
+	__asm__ __volatile__(
+		"\n1:\t"
+		"ldl_l %0,%1\n\t"
+		"addl %0,%2,%0\n\t"
+		"stl_c %0,%1\n\t"
+		"beq %0,1b\n"
+		"2:"
+		:"=&r" (temp),
+		 "=m" (__atomic_fool_gcc(v))
+		:"Ir" (i),
+		 "m" (__atomic_fool_gcc(v)));
+}
+
+extern __inline__ void atomic_sub(atomic_t i, atomic_t * v)
+{
+	unsigned long temp;
+	__asm__ __volatile__(
+		"\n1:\t"
+		"ldl_l %0,%1\n\t"
+		"subl %0,%2,%0\n\t"
+		"stl_c %0,%1\n\t"
+		"beq %0,1b\n"
+		"2:"
+		:"=&r" (temp),
+		 "=m" (__atomic_fool_gcc(v))
+		:"Ir" (i),
+		 "m" (__atomic_fool_gcc(v)));
+}
+
+#define atomic_inc(v) atomic_add(1,(v))
+#define atomic_dec(v) atomic_sub(1,(v))
+
+#endif
diff -u --recursive --new-file v1.3.76/linux/include/asm-i386/atomic.h linux/include/asm-i386/atomic.h
--- v1.3.76/linux/include/asm-i386/atomic.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-i386/atomic.h	Wed Mar 20 14:38:42 1996
@@ -0,0 +1,56 @@
+#ifndef __ARCH_I386_ATOMIC__
+#define __ARCH_I386_ATOMIC__
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ */
+
+#ifdef __SMP__
+#define LOCK "lock ; "
+#else
+#define LOCK ""
+#endif
+
+/*
+ * Make sure gcc doesn't try to be clever and move things around
+ * on us. We need to use _exactly_ the address the user gave us,
+ * not some alias that contains the same information.
+ */
+#define __atomic_fool_gcc(x) (*(struct { int a[100]; } *)x)
+
+typedef int atomic_t;
+
+static __inline__ void atomic_add(atomic_t i, atomic_t *v)
+{
+	__asm__ __volatile__(
+		LOCK "addl %1,%0"
+		:"=m" (__atomic_fool_gcc(v))
+		:"ir" (i), "m" (__atomic_fool_gcc(v)));
+}
+
+static __inline__ void atomic_sub(atomic_t i, atomic_t *v)
+{
+	__asm__ __volatile__(
+		LOCK "subl %1,%0"
+		:"=m" (__atomic_fool_gcc(v))
+		:"ir" (i), "m" (__atomic_fool_gcc(v)));
+}
+
+static __inline__ void atomic_inc(atomic_t *v)
+{
+	__asm__ __volatile__(
+		LOCK "incl %0"
+		:"=m" (__atomic_fool_gcc(v))
+		:"m" (__atomic_fool_gcc(v)));
+}
+
+static __inline__ void atomic_dec(atomic_t *v)
+{
+	__asm__ __volatile__(
+		LOCK "decl %0"
+		:"=m" (__atomic_fool_gcc(v))
+		:"m" (__atomic_fool_gcc(v)));
+}
+
+#endif
diff -u --recursive --new-file v1.3.76/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v1.3.76/linux/include/asm-i386/processor.h	Sun Dec 17 11:43:22 1995
+++ linux/include/asm-i386/processor.h	Thu Mar 21 08:55:09 1996
@@ -9,7 +9,9 @@
 
 /*
  * System setup and hardware bug flags..
+ * [Note we don't test the 386 multiply bug or popad bug]
  */
+
 extern char hard_math;
 extern char x86;		/* lower 4 bits */
 extern char x86_vendor_id[13];
@@ -18,8 +20,9 @@
 extern int  x86_capability;	/* field of flags */
 extern int  fdiv_bug;		
 extern char ignore_irq13;
-extern char wp_works_ok;		/* doesn't work on a 386 */
+extern char wp_works_ok;	/* doesn't work on a 386 */
 extern char hlt_works_ok;	/* problems on some 486Dx4's and old 386's */
+extern int  have_cpuid;		/* We have a CPUID */
 
 /*
  * Bus types (default is ISA, but people can check others with these..)
diff -u --recursive --new-file v1.3.76/linux/include/linux/netdevice.h linux/include/linux/netdevice.h
--- v1.3.76/linux/include/linux/netdevice.h	Tue Mar  5 10:11:13 1996
+++ linux/include/linux/netdevice.h	Thu Mar 21 17:51:22 1996
@@ -232,7 +232,6 @@
 #define HAVE_NETIF_RX 1
 extern void		netif_rx(struct sk_buff *skb);
 extern void		dev_transmit(void);
-extern int		in_net_bh(void);
 extern void		net_bh(void);
 extern void		dev_tint(struct device *dev);
 extern int		dev_get_info(char *buffer, char **start, off_t offset, int length, int dummy);
diff -u --recursive --new-file v1.3.76/linux/include/net/sock.h linux/include/net/sock.h
--- v1.3.76/linux/include/net/sock.h	Wed Mar 20 11:00:00 1996
+++ linux/include/net/sock.h	Thu Mar 21 17:51:22 1996
@@ -55,6 +55,8 @@
 
 #include <linux/igmp.h>
 
+#include <asm/atomic.h>
+
 /* Think big (also on some systems a byte is faster) */
 #define SOCK_ARRAY_SIZE	256
 
@@ -149,8 +151,8 @@
 struct sock 
 {
 	struct options		*opt;
-	volatile unsigned long	wmem_alloc;
-	volatile unsigned long	rmem_alloc;
+	atomic_t		wmem_alloc;
+	atomic_t		rmem_alloc;
 	unsigned long		allocation;		/* Allocation mode */
 	__u32			write_seq;
 	__u32			sent_seq;
@@ -484,14 +486,10 @@
 
 extern __inline__ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
-	unsigned long flags;
-	if(sk->rmem_alloc + skb->truesize >= sk->rcvbuf)
+	if (sk->rmem_alloc + skb->truesize >= sk->rcvbuf)
 		return -ENOMEM;
-	save_flags(flags);
-	cli();
-	sk->rmem_alloc+=skb->truesize;
+	atomic_add(skb->truesize, &sk->rmem_alloc);
 	skb->sk=sk;
-	restore_flags(flags);
 	skb_queue_tail(&sk->receive_queue,skb);
 	if(!sk->dead)
 		sk->data_ready(sk,skb->len);
diff -u --recursive --new-file v1.3.76/linux/kernel/fork.c linux/kernel/fork.c
--- v1.3.76/linux/kernel/fork.c	Wed Mar 13 10:09:24 1996
+++ linux/kernel/fork.c	Thu Mar 21 08:55:09 1996
@@ -28,6 +28,7 @@
 
 int nr_tasks=1;
 int nr_running=1;
+unsigned long int total_forks=0;	/* Handle normal Linux uptimes. */
 
 static inline int find_empty_process(void)
 {
@@ -269,6 +270,7 @@
 	p->exit_signal = clone_flags & CSIGNAL;
 	p->counter = current->counter >> 1;
 	wake_up_process(p);			/* do this last, just in case */
+	++total_forks;
 	return p->pid;
 
 bad_fork_cleanup_sighand:
diff -u --recursive --new-file v1.3.76/linux/kernel/sched.c linux/kernel/sched.c
--- v1.3.76/linux/kernel/sched.c	Wed Mar 20 11:00:00 1996
+++ linux/kernel/sched.c	Thu Mar 21 08:44:50 1996
@@ -886,7 +886,7 @@
 	unsigned long it_virt = p->it_virt_value;
 
 	if (it_virt) {
-		if (it_virt < ticks) {
+		if (it_virt <= ticks) {
 			it_virt = ticks + p->it_virt_incr;
 			send_sig(SIGVTALRM, p, 1);
 		}
@@ -899,7 +899,7 @@
 	unsigned long it_prof = p->it_prof_value;
 
 	if (it_prof) {
-		if (it_prof < ticks) {
+		if (it_prof <= ticks) {
 			it_prof = ticks + p->it_prof_incr;
 			send_sig(SIGPROF, p, 1);
 		}
diff -u --recursive --new-file v1.3.76/linux/mm/filemap.c linux/mm/filemap.c
--- v1.3.76/linux/mm/filemap.c	Fri Mar 15 16:03:21 1996
+++ linux/mm/filemap.c	Thu Mar 21 15:00:55 1996
@@ -493,12 +493,36 @@
  * Tries to write a shared mapped page to its backing store. May return -EIO
  * if the disk is full.
  */
+static inline int do_write_page(struct inode * inode, struct file * file,
+	const char * page, unsigned long offset)
+{
+	int old_fs, retval;
+	unsigned long size;
+
+	size = offset + PAGE_SIZE;
+	/* refuse to extend file size.. */
+	if (S_ISREG(inode->i_mode)) {
+		if (size > inode->i_size)
+			size = inode->i_size;
+		/* Ho humm.. We should have tested for this earlier */
+		if (size < offset)
+			return -EIO;
+	}
+	size -= offset;
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	retval = -EIO;
+	if (size == file->f_op->write(inode, file, (const char *) page, size))
+		retval = 0;
+	set_fs(old_fs);
+	return retval;
+}
+
 static int filemap_write_page(struct vm_area_struct * vma,
 	unsigned long offset,
 	unsigned long page)
 {
-	int old_fs;
-	unsigned long size, result;
+	int result;
 	struct file file;
 	struct inode * inode;
 	struct buffer_head * bh;
@@ -518,29 +542,17 @@
 	file.f_op = inode->i_op->default_file_ops;
 	if (!file.f_op->write)
 		return -EIO;
-	size = offset + PAGE_SIZE;
-	/* refuse to extend file size.. */
-	if (S_ISREG(inode->i_mode)) {
-		if (size > inode->i_size)
-			size = inode->i_size;
-		/* Ho humm.. We should have tested for this earlier */
-		if (size < offset)
-			return -EIO;
-	}
-	size -= offset;
 	file.f_mode = 3;
 	file.f_flags = 0;
 	file.f_count = 1;
 	file.f_inode = inode;
 	file.f_pos = offset;
 	file.f_reada = 0;
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	result = file.f_op->write(inode, &file, (const char *) page, size);
-	set_fs(old_fs);
-	if (result != size)
-		return -EIO;
-	return 0;
+
+	down(&inode->i_sem);
+	result = do_write_page(inode, &file, (const char *) page, offset);
+	up(&inode->i_sem);
+	return result;
 }
 
 
diff -u --recursive --new-file v1.3.76/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c
--- v1.3.76/linux/net/appletalk/ddp.c	Wed Mar 13 10:09:26 1996
+++ linux/net/appletalk/ddp.c	Wed Mar 20 14:14:02 1996
@@ -1791,7 +1791,7 @@
 		if(sk->debug)
 			printk("SK %p: Loop back.\n", sk);
 		/* loop back */
-		sk->wmem_alloc-=skb->truesize;
+		atomic_sub(skb->truesize, &sk->wmem_alloc);
 		ddp_dl->datalink_header(ddp_dl, skb, dev->dev_addr);
 		skb->sk = NULL;
 		skb->mac.raw=skb->data;
diff -u --recursive --new-file v1.3.76/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v1.3.76/linux/net/ax25/af_ax25.c	Sun Mar 17 09:04:08 1996
+++ linux/net/ax25/af_ax25.c	Wed Mar 20 15:08:26 1996
@@ -377,7 +377,7 @@
 				return;
 
 			copy->sk = sk;
-			sk->rmem_alloc += copy->truesize;
+			atomic_add(copy->truesize, &sk->rmem_alloc);
 			skb_queue_tail(&sk->receive_queue, copy);
 			if (!sk->dead)
 				sk->data_ready(sk, skb->len);
@@ -1727,7 +1727,7 @@
 						skb_pull(skb, 2);
 						skb_queue_tail(&sk->receive_queue, skb);
 						skb->sk = sk;
-						sk->rmem_alloc += skb->truesize;
+						atomic_add(skb->truesize, &sk->rmem_alloc);
 						if (!sk->dead)
 							sk->data_ready(sk, skb->len);
 					}
diff -u --recursive --new-file v1.3.76/linux/net/ax25/ax25_in.c linux/net/ax25/ax25_in.c
--- v1.3.76/linux/net/ax25/ax25_in.c	Sun Mar 17 09:04:08 1996
+++ linux/net/ax25/ax25_in.c	Wed Mar 20 14:15:53 1996
@@ -95,7 +95,7 @@
 
 					if (ax25->sk != NULL) {
 						skbn->sk = ax25->sk;
-						ax25->sk->rmem_alloc += skbn->truesize;
+						atomic_add(skbn->truesize, &ax25->sk->rmem_alloc);
 					}
 
 					/* get first fragment from queue */
diff -u --recursive --new-file v1.3.76/linux/net/ax25/ax25_subr.c linux/net/ax25/ax25_subr.c
--- v1.3.76/linux/net/ax25/ax25_subr.c	Sun Mar 17 09:04:08 1996
+++ linux/net/ax25/ax25_subr.c	Wed Mar 20 14:15:19 1996
@@ -215,7 +215,7 @@
 
 	if (ax25->sk != NULL) {
 		skb->sk = ax25->sk;
-        	ax25->sk->wmem_alloc += skb->truesize;
+		atomic_add(skb->truesize, &ax25->sk->wmem_alloc);
 	}
 
 	/* Assume a response - address structure for DTE */
@@ -498,7 +498,7 @@
 
 	if (ax25->sk != NULL) {
 		skb->sk = ax25->sk;
-		ax25->sk->wmem_alloc += skb->truesize;
+		atomic_add(skb->truesize, &ax25->sk->wmem_alloc);
 	}
 
 	skb->protocol = htons(ETH_P_AX25);
diff -u --recursive --new-file v1.3.76/linux/net/core/datagram.c linux/net/core/datagram.c
--- v1.3.76/linux/net/core/datagram.c	Sat Feb 17 16:02:57 1996
+++ linux/net/core/datagram.c	Thu Mar 21 10:46:17 1996
@@ -79,7 +79,7 @@
 
 	lock_sock(sk);
 restart:
-	while(skb_peek(&sk->receive_queue) == NULL)	/* No data */
+	while(skb_queue_empty(&sk->receive_queue))	/* No data */
 	{
 		/* Socket errors? */
 		error = sock_error(sk);
@@ -142,14 +142,12 @@
 	save_flags(flags);
 	cli();
 	skb->users--;
-	if(skb->users>0)
-	{
-		restore_flags(flags);
-		return;
+	if(skb->users <= 0) {
+		/* See if it needs destroying */
+		/* Been dequeued by someone - ie it's read */
+		if(!skb->next && !skb->prev)
+			kfree_skb(skb,FREE_READ);
 	}
-	/* See if it needs destroying */
-	if(!skb->next && !skb->prev)	/* Been dequeued by someone - ie it's read */
-		kfree_skb(skb,FREE_READ);
 	restore_flags(flags);
 	release_sock(sk);
 }
diff -u --recursive --new-file v1.3.76/linux/net/core/dev.c linux/net/core/dev.c
--- v1.3.76/linux/net/core/dev.c	Tue Mar  5 10:11:15 1996
+++ linux/net/core/dev.c	Wed Mar 20 17:08:27 1996
@@ -537,19 +537,6 @@
 ***********************************************************************************/
 
 /*
- *	This is a single non-reentrant routine which takes the received packet
- *	queue and throws it at the networking layers in the hope that something
- *	useful will emerge.
- */
- 
-volatile unsigned long in_bh = 0;	/* Non-reentrant remember */
-
-int in_net_bh()	/* Used by timer.c */
-{
-	return(in_bh==0?0:1);
-}
-
-/*
  *	When we are called the queue is ready to grab, the interrupts are
  *	on and hardware can interrupt and queue to the receive queue a we
  *	run with no problems.
@@ -559,19 +546,11 @@
  
 void net_bh(void)
 {
-	struct sk_buff *skb;
 	struct packet_type *ptype;
 	struct packet_type *pt_prev;
 	unsigned short type;
 
 	/*
-	 *	Atomically check and mark our BUSY state. 
-	 */
-
-	if (set_bit(1, (void*)&in_bh))
-		return;
-
-	/*
 	 *	Can we send anything now? We want to clear the
 	 *	decks for any more sends that get done as we
 	 *	process the input. This also minimises the
@@ -586,19 +565,23 @@
 	 *	that from the device which does a mark_bh() just after
 	 */
 
-	cli();
-	
 	/*
-	 *	While the queue is not empty
+	 *	While the queue is not empty..
+	 *
+	 *	Note that the queue never shrinks due to
+	 *	an interrupt, so we can do this test without
+	 *	disabling interrupts.
 	 */
-	 
-	while((skb=__skb_dequeue(&backlog))!=NULL)
-	{
+
+	while (!skb_queue_empty(&backlog)) {
+		struct sk_buff * skb = backlog.next;
+
 		/*
 		 *	We have a packet. Therefore the queue has shrunk
 		 */
+		cli();
+		__skb_unlink(skb, &backlog);
   		backlog_size--;
-
 		sti();
 		
 	       /*
@@ -681,15 +664,11 @@
 #ifdef XMIT_EVERY
 		dev_transmit();
 #endif		
-		cli();
   	}	/* End of queue loop */
   	
   	/*
   	 *	We have emptied the queue
   	 */
-  	 
-  	in_bh = 0;
-	sti();
 	
 	/*
 	 *	One last output flush.
diff -u --recursive --new-file v1.3.76/linux/net/core/skbuff.c linux/net/core/skbuff.c
--- v1.3.76/linux/net/core/skbuff.c	Sun Mar 17 09:04:08 1996
+++ linux/net/core/skbuff.c	Wed Mar 20 14:24:11 1996
@@ -57,23 +57,23 @@
  *	Resource tracking variables
  */
 
-unsigned long net_skbcount = 0;
-unsigned long net_locked = 0;
-unsigned long net_allocs = 0;
-unsigned long net_fails  = 0;
-unsigned long net_free_locked = 0;
+atomic_t net_skbcount = 0;
+atomic_t net_locked = 0;
+atomic_t net_allocs = 0;
+atomic_t net_fails  = 0;
+atomic_t net_free_locked = 0;
 
-extern unsigned long ip_frag_mem;
+extern atomic_t ip_frag_mem;
 
 void show_net_buffers(void)
 {
-	printk("Networking buffers in use          : %lu\n",net_skbcount);
-	printk("Network buffers locked by drivers  : %lu\n",net_locked);
-	printk("Total network buffer allocations   : %lu\n",net_allocs);
-	printk("Total failed network buffer allocs : %lu\n",net_fails);
-	printk("Total free while locked events     : %lu\n",net_free_locked);
+	printk("Networking buffers in use          : %u\n",net_skbcount);
+	printk("Network buffers locked by drivers  : %u\n",net_locked);
+	printk("Total network buffer allocations   : %u\n",net_allocs);
+	printk("Total failed network buffer allocs : %u\n",net_fails);
+	printk("Total free while locked events     : %u\n",net_free_locked);
 #ifdef CONFIG_INET
-	printk("IP fragment buffer size            : %lu\n",ip_frag_mem);
+	printk("IP fragment buffer size            : %u\n",ip_frag_mem);
 #endif	
 }
 
@@ -614,27 +614,24 @@
 		skb->destructor(skb);
 	if (skb->sk)
 	{
-	        if(skb->sk->prot!=NULL)
+		struct sock * sk = skb->sk;
+	        if(sk->prot!=NULL)
 		{
 			if (rw)
-		     		sock_rfree(skb->sk, skb);
+		     		sock_rfree(sk, skb);
 		     	else
-		     		sock_wfree(skb->sk, skb);
+		     		sock_wfree(sk, skb);
 
 		}
 		else
 		{
-			unsigned long flags;
-			/* Non INET - default wmalloc/rmalloc handler */
-			save_flags(flags);
-			cli();
 			if (rw)
-				skb->sk->rmem_alloc-=skb->truesize;
-			else
-				skb->sk->wmem_alloc-=skb->truesize;
-			restore_flags(flags);
-			if(!skb->sk->dead)
-				skb->sk->write_space(skb->sk);
+				atomic_sub(skb->truesize, &sk->rmem_alloc);
+			else {
+				atomic_sub(skb->truesize, &sk->wmem_alloc);
+				if(!sk->dead)
+					sk->write_space(sk);
+			}
 			kfree_skbmem(skb);
 		}
 	}
@@ -760,7 +757,6 @@
 
 struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
 {
-	unsigned long flags;
 	struct sk_buff *n;
 
 	IS_SKB(skb);
@@ -771,12 +767,9 @@
 	n->count = 1;
 	if (skb->data_skb)
 		skb = skb->data_skb;
-	save_flags(flags);
-	cli();
-	skb->count++;
-	net_allocs++;
-	net_skbcount++;
-	restore_flags(flags);
+	atomic_inc(&skb->count);
+	atomic_inc(&net_allocs);
+	atomic_inc(&net_skbcount);
 	n->data_skb = skb;
 	n->next = n->prev = n->link3 = NULL;
 	n->list = NULL;
diff -u --recursive --new-file v1.3.76/linux/net/core/sock.c linux/net/core/sock.c
--- v1.3.76/linux/net/core/sock.c	Tue Mar  5 10:11:15 1996
+++ linux/net/core/sock.c	Wed Mar 20 15:57:00 1996
@@ -324,50 +324,32 @@
   	return(0);
 }
 
-
 struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, int priority)
 {
-	if (sk) 
-	{
-		if (sk->wmem_alloc + size < sk->sndbuf || force) 
-		{
-			struct sk_buff * c = alloc_skb(size, priority);
-			if (c) 
-			{
-				unsigned long flags;
-				save_flags(flags);
-				cli();
-				sk->wmem_alloc+= c->truesize;
-				restore_flags(flags); /* was sti(); */
-			}
-			return c;
+	if (sk) {
+		if (force || sk->wmem_alloc + size < sk->sndbuf) {
+			struct sk_buff * skb = alloc_skb(size, priority);
+			if (skb)
+				atomic_add(skb->truesize, &sk->wmem_alloc);
+			return skb;
 		}
-		return(NULL);
+		return NULL;
 	}
-	return(alloc_skb(size, priority));
+	return alloc_skb(size, priority);
 }
 
-
 struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority)
 {
-	if (sk) 
-	{
-		if (sk->rmem_alloc + size < sk->rcvbuf || force) 
-		{
-			struct sk_buff *c = alloc_skb(size, priority);
-			if (c) 
-			{
-				unsigned long flags;
-				save_flags(flags);
-				cli();
-				sk->rmem_alloc += c->truesize;
-				restore_flags(flags); /* was sti(); */
-			}
-			return(c);
+	if (sk) {
+		if (force || sk->rmem_alloc + size < sk->rcvbuf) {
+			struct sk_buff *skb = alloc_skb(size, priority);
+			if (skb)
+				atomic_add(skb->truesize, &sk->rmem_alloc);
+			return skb;
 		}
-		return(NULL);
+		return NULL;
 	}
-	return(alloc_skb(size, priority));
+	return alloc_skb(size, priority);
 }
 
 
@@ -396,7 +378,7 @@
 			return(0);
 		if (sk->wmem_alloc >= sk->sndbuf)
 			return(0);
-		return(sk->sndbuf-sk->wmem_alloc );
+		return sk->sndbuf - sk->wmem_alloc;
 	}
 	return(0);
 }
@@ -411,14 +393,9 @@
 	kfree_skbmem(skb);
 	if (sk) 
 	{
-		unsigned long flags;
-		save_flags(flags);
-		cli();
-		sk->wmem_alloc -= s;
-		restore_flags(flags);
+		atomic_sub(s, &sk->wmem_alloc);
 		/* In case it might be waiting for more memory. */
 		sk->write_space(sk);
-		return;
 	}
 }
 
@@ -432,11 +409,7 @@
 	kfree_skbmem(skb);
 	if (sk) 
 	{
-		unsigned long flags;
-		save_flags(flags);
-		cli();
-		sk->rmem_alloc -= s;
-		restore_flags(flags);
+		atomic_sub(s, &sk->rmem_alloc);
 	}
 }
 
diff -u --recursive --new-file v1.3.76/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v1.3.76/linux/net/ipv4/af_inet.c	Sun Mar 17 09:04:08 1996
+++ linux/net/ipv4/af_inet.c	Wed Mar 20 15:42:33 1996
@@ -410,7 +410,8 @@
 	{
 		/* this should never happen. */
 		/* actually it can if an ack has just been sent. */
-		printk("Socket destroy delayed\n");
+		printk("Socket destroy delayed (r=%d w=%d)\n",
+			sk->rmem_alloc, sk->wmem_alloc);
 		sk->destroy = 1;
 		sk->ack_backlog = 0;
 		release_sock(sk);
diff -u --recursive --new-file v1.3.76/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c
--- v1.3.76/linux/net/ipv4/ip_fragment.c	Wed Nov  8 07:11:45 1995
+++ linux/net/ipv4/ip_fragment.c	Wed Mar 20 15:14:14 1996
@@ -45,7 +45,7 @@
 
 static struct ipq *ipqueue = NULL;		/* IP fragment queue	*/
 
-unsigned long ip_frag_mem = 0;			/* Memory used for fragments */
+atomic_t ip_frag_mem = 0;			/* Memory used for fragments */
 
 /*
  *	Memory Tracking Functions
@@ -53,34 +53,22 @@
  
 extern __inline__ void frag_kfree_skb(struct sk_buff *skb, int type)
 {
-	unsigned long flags;
-	save_flags(flags);
-	cli();
-	ip_frag_mem-=skb->truesize;
-	restore_flags(flags);
+	atomic_sub(skb->truesize, &ip_frag_mem);
 	kfree_skb(skb,type);
 }
 
 extern __inline__ void frag_kfree_s(void *ptr, int len)
 {
-	unsigned long flags;
-	save_flags(flags);
-	cli();
-	ip_frag_mem-=len;
-	restore_flags(flags);
+	atomic_sub(len, &ip_frag_mem);
 	kfree_s(ptr,len);
 }
  
 extern __inline__ void *frag_kmalloc(int size, int pri)
 {
-	unsigned long flags;
 	void *vp=kmalloc(size,pri);
 	if(!vp)
 		return NULL;
-	save_flags(flags);
-	cli();
-	ip_frag_mem+=size;
-	restore_flags(flags);
+	atomic_add(size, &ip_frag_mem);
 	return vp;
 }
  
@@ -623,7 +611,6 @@
 	struct sk_buff *skb2;
 	int left, mtu, hlen, len;
 	int offset;
-	unsigned long flags;
 
 	/*
 	 *	Point into the IP datagram header.
@@ -730,14 +717,11 @@
 		 *	it might possess
 		 */
 
-		save_flags(flags);
 		if (sk)
 		{
-			cli();
-			sk->wmem_alloc += skb2->truesize;
+			atomic_add(skb2->truesize, &sk->wmem_alloc);
 			skb2->sk=sk;
 		}
-		restore_flags(flags);
 		skb2->raddr = skb->raddr;	/* For rebuild_header - must be here */
 
 		/*
diff -u --recursive --new-file v1.3.76/linux/net/ipv4/proc.c linux/net/ipv4/proc.c
--- v1.3.76/linux/net/ipv4/proc.c	Tue Jan 23 21:15:55 1996
+++ linux/net/ipv4/proc.c	Wed Mar 20 14:29:46 1996
@@ -108,7 +108,7 @@
 			    timer_active=timer_active2;
 			    timer_expires=sp->timer.expires;
 			}
-			len += sprintf(buffer+len, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d %d\n",
+			len += sprintf(buffer+len, "%2d: %08lX:%04X %08lX:%04X %02X %08X:%08X %02X:%08lX %08X %d %d\n",
 				i, src, srcp, dest, destp, sp->state, 
 				format==0?sp->write_seq-sp->rcv_ack_seq:sp->wmem_alloc, 
 				format==0?sp->acked_seq-sp->copied_seq:sp->rmem_alloc,
diff -u --recursive --new-file v1.3.76/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v1.3.76/linux/net/ipv4/tcp_input.c	Sun Mar 17 09:04:09 1996
+++ linux/net/ipv4/tcp_input.c	Thu Mar 21 17:08:06 1996
@@ -1595,7 +1595,7 @@
 	 */
 	 
 	skb->sk=sk;
-	sk->rmem_alloc += skb->truesize;
+	atomic_add(skb->truesize, &sk->rmem_alloc);
 	
 	/*
 	 *	We should now do header prediction.
@@ -1773,7 +1773,7 @@
 			if(sk->debug)
 				printk("Doing a BSD time wait\n");
 			tcp_statistics.TcpEstabResets++;	   
-			sk->rmem_alloc -= skb->truesize;
+			atomic_sub(skb->truesize, &sk->rmem_alloc);
 			skb->sk = NULL;
 			sk->err=ECONNRESET;
 			tcp_set_state(sk, TCP_CLOSE);
@@ -1783,7 +1783,7 @@
 			if (sk && sk->state==TCP_LISTEN)
 			{
 				skb->sk = sk;
-				sk->rmem_alloc += skb->truesize;
+				atomic_add(skb->truesize, &sk->rmem_alloc);
 				tcp_conn_request(sk, skb, daddr, saddr,opt, dev,seq+128000);
 				return 0;
 			}
@@ -1847,12 +1847,18 @@
 	 *	now drop it (we must process the ack first to avoid
 	 *	deadlock cases).
 	 */
-	 
+#if 0
+	/*
+	 *	Is this test really a good idea? We should
+	 *	throw away packets that aren't in order, not
+	 *	new packets.
+	 */
 	if (sk->rmem_alloc  >= sk->rcvbuf) 
 	{
 		kfree_skb(skb, FREE_READ);
 		return(0);
 	}
+#endif
 
 
 	/*
diff -u --recursive --new-file v1.3.76/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v1.3.76/linux/net/ipv4/tcp_output.c	Sun Mar 17 09:04:09 1996
+++ linux/net/ipv4/tcp_output.c	Wed Mar 20 14:11:30 1996
@@ -738,8 +738,8 @@
 	 *	Charge the sock_buff to newsk. 
 	 */
 	 
-	sk->rmem_alloc -= skb->truesize;
-	newsk->rmem_alloc += skb->truesize;
+	atomic_sub(skb->truesize, &sk->rmem_alloc);
+	atomic_add(skb->truesize, &newsk->rmem_alloc);
 	
 	skb_queue_tail(&sk->receive_queue,skb);
 	sk->ack_backlog++;
diff -u --recursive --new-file v1.3.76/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- v1.3.76/linux/net/ipx/af_ipx.c	Tue Mar  5 10:11:16 1996
+++ linux/net/ipx/af_ipx.c	Wed Mar 20 14:08:23 1996
@@ -593,7 +593,7 @@
 			 */
 			if(skb->sk)
 			{
-				skb->sk->wmem_alloc-=skb->truesize;
+				atomic_sub(skb->truesize, &skb->sk->wmem_alloc);
 				skb->sk=NULL;
 			}
 			/*
@@ -608,7 +608,7 @@
 		{
 			if (!send_to_wire && skb->sk)
 			{
-				skb->sk->wmem_alloc-=skb->truesize;
+				atomic_sub(skb->truesize, &skb->sk->wmem_alloc);
 				skb->sk=NULL;
 			}
 			ipxitf_demux_socket(intrfc, skb, send_to_wire);
diff -u --recursive --new-file v1.3.76/linux/scripts/patch-kernel linux/scripts/patch-kernel
--- v1.3.76/linux/scripts/patch-kernel	Wed Mar 13 10:09:27 1996
+++ linux/scripts/patch-kernel	Thu Mar 21 08:55:34 1996
@@ -43,11 +43,11 @@
         echo "failed.  Clean up yourself."
         break
     fi
-    if [ "`find $sourcedir '(' -name '*.rej' -o -name '.*.rej' ')' -print`" ]
+    if [ "`find $sourcedir -follow '(' -name '*.rej' -o -name '.*.rej' ')' -print`" ]
     then
         echo "Aborting.  Reject files found."
         break
     fi
     # Remove backup files
-    find $sourcedir '(' -name '*.orig' -o -name '.*.orig' ')' -print | xargs rm -f
+    find $sourcedir -follow '(' -name '*.orig' -o -name '.*.orig' ')' -print | xargs rm -f
 done
