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

diff -urN linux-2.4.23-bk3/Documentation/Changes linux-2.4.23-bk4/Documentation/Changes
--- linux-2.4.23-bk3/Documentation/Changes	2002-11-28 15:53:08.000000000 -0800
+++ linux-2.4.23-bk4/Documentation/Changes	2003-12-06 02:49:48.000000000 -0800
@@ -57,6 +57,7 @@
 o  jfsutils               1.0.12                  # fsck.jfs -V
 o  reiserfsprogs          3.6.3                   # reiserfsck -V 2>&1|grep reiserfsprogs
 o  pcmcia-cs              3.1.21                  # cardmgr -V
+o  quota-tools            3.09                    # quota -V
 o  PPP                    2.4.0                   # pppd --version
 o  isdn4k-utils           3.1pre1                 # isdnctrl 2>&1|grep version
 			  
@@ -197,6 +198,14 @@
 kernel source.  Pay attention when you recompile your kernel ;-).
 Also, be sure to upgrade to the latest pcmcia-cs release.
 
+Quota-tools
+-----------
+
+Support for 32 bit uid's and gid's is required if you want to use
+the newer version 2 quota format.  Quota-tools version 3.07 and
+newer has this support.  Use the recommended version or newer
+from the table above.
+
 Intel IA32 microcode
 --------------------
 
@@ -335,6 +344,10 @@
 ---------
 o  <ftp://pcmcia-cs.sourceforge.net/pub/pcmcia-cs/pcmcia-cs-3.1.21.tar.gz>
 
+Quota-tools
+----------
+o  <http://sourceforge.net/projects/linuxquota/>
+
 Jade
 ----
 o  <ftp://ftp.jclark.com/pub/jade/jade-1.2.1.tar.gz>
diff -urN linux-2.4.23-bk3/Makefile linux-2.4.23-bk4/Makefile
--- linux-2.4.23-bk3/Makefile	2003-12-06 02:49:45.000000000 -0800
+++ linux-2.4.23-bk4/Makefile	2003-12-06 02:49:48.000000000 -0800
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 23
-EXTRAVERSION = -bk3
+EXTRAVERSION = -bk4
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.23-bk3/arch/cris/drivers/Config.in linux-2.4.23-bk4/arch/cris/drivers/Config.in
--- linux-2.4.23-bk3/arch/cris/drivers/Config.in	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-bk4/arch/cris/drivers/Config.in	2003-12-06 02:49:48.000000000 -0800
@@ -11,7 +11,10 @@
   "LED_on_when_link      CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK    \
    LED_on_when_activity  CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY" \
      LED_on_when_activity
-
+  choice 'Network LED behavior on no connection' \
+  "RED_LED_on_no_connection      CONFIG_ETRAX_NETWORK_RED_ON_NO_CONNECTION  \
+   LED_OFF_on_no_connection      CONFIG_ETRAX_NETWORK_OFF_ON_NO_CONNECTION" \
+    LED_OFF_on_no_connection
 else
   define_bool CONFIG_NET_ETHERNET n
 fi
@@ -32,12 +35,18 @@
   fi
   bool '  Enable external clock on PB6' CONFIG_ETRAX_EXTERN_PB6CLK_ENABLED
   if [ "$CONFIG_ETRAX_EXTERN_PB6CLK_ENABLED" = "y" ]; then
-    int '  Extern clock frequency (baudrate=clk/8) (Hz)' CONFIG_ETRAX_EXTERN_PB6CLK_FREQ
+    int '  Extern clock frequency (baudrate=clk/8) (Hz)' CONFIG_ETRAX_EXTERN_PB6CLK_FREQ 0
   fi
   bool '  Serial port 0 enabled' CONFIG_ETRAX_SERIAL_PORT0
   if [ "$CONFIG_ETRAX_SERIAL_PORT0" = "y" ]; then
-  bool '  Serial port 0 uses DMA6 out' CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
-  bool '  Serial port 0 uses DMA7 in' CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
+  choice 'Ser0 DMA out assignment' \
+  "NO_DMA_OUT      CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_OUT \
+   DMA6_OUT    CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT" \
+     DMA6_OUT
+  choice 'Ser0 DMA in assignment' \
+  "NO_DMA_IN      CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_IN \
+   DMA7_IN    CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN" \
+     DMA7_IN
   choice 'Ser0 DTR, RI, DSR and CD assignment' \
   "No_DTR_RI_DSR_CD      CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_NONE \
    DTR_RI_DSR_CD_on_PA   CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PA \
@@ -73,8 +82,14 @@
 
   bool '  Serial port 1 enabled' CONFIG_ETRAX_SERIAL_PORT1
   if [ "$CONFIG_ETRAX_SERIAL_PORT1" = "y" ]; then
-  bool '  Serial port 1 uses DMA8 out' CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT
-  bool '  Serial port 1 uses DMA9 in' CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN
+  choice 'Ser1 DMA out assignment' \
+  "NO_DMA_OUT      CONFIG_ETRAX_SERIAL_PORT1_NO_DMA_OUT \
+   DMA8_OUT    CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT" \
+     DMA8_OUT
+  choice 'Ser1 DMA in assignment' \
+  "NO_DMA_IN      CONFIG_ETRAX_SERIAL_PORT1_NO_DMA_IN \
+   DMA9_IN    CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN" \
+     DMA9_IN
   choice 'Ser1 DTR, RI, DSR and CD assignment' \
   "No_DTR_RI_DSR_CD      CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_ON_NONE \
    DTR_RI_DSR_CD_on_PA   CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_ON_PA \
@@ -114,8 +129,14 @@
   fi
   bool '  Serial port 2 enabled' CONFIG_ETRAX_SERIAL_PORT2
   if [ "$CONFIG_ETRAX_SERIAL_PORT2" = "y" ]; then
-  bool '  Serial port 2 uses DMA2 out' CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
-  bool '  Serial port 2 uses DMA3 in' CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
+  choice 'Ser2 DMA out assignment' \
+  "NO_DMA_OUT      CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_OUT \
+   DMA2_OUT    CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT" \
+     DMA2_OUT
+  choice 'Ser2 DMA in assignment' \
+  "NO_DMA_IN      CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_IN \
+   DMA3_IN    CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN" \
+     DMA3_IN
   choice 'Ser2 DTR, RI, DSR and CD assignment' \
   "No_DTR_RI_DSR_CD      CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_NONE \
    DTR_RI_DSR_CD_on_PA   CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_PA \
@@ -149,8 +170,14 @@
   fi
   bool '  Serial port 3 enabled' CONFIG_ETRAX_SERIAL_PORT3
   if [ "$CONFIG_ETRAX_SERIAL_PORT3" = "y" ]; then
-  bool '  Serial port 3 uses DMA4 out' CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT
-  bool '  Serial port 3 uses DMA5 in' CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN
+  choice 'Ser3 DMA out assignment' \
+  "NO_DMA_OUT      CONFIG_ETRAX_SERIAL_PORT3_NO_DMA_OUT \
+   DMA4_OUT    CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT" \
+     DMA4_OUT
+  choice 'Ser3 DMA in assignment' \
+  "NO_DMA_IN      CONFIG_ETRAX_SERIAL_PORT3_NO_DMA_IN \
+   DMA5_IN    CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN" \
+     DMA5_IN
   choice 'Ser3 DTR, RI, DSR and CD assignment' \
   "No_DTR_RI_DSR_CD      CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_ON_NONE \
    DTR_RI_DSR_CD_on_PA   CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_ON_PA \
@@ -194,13 +221,13 @@
 
 bool 'Synchronous serial port support' CONFIG_ETRAX_SYNCHRONOUS_SERIAL
 if [ "$CONFIG_ETRAX_SYNCHRONOUS_SERIAL" = "y" ]; then 
-  bool '  Synchronous serial port 0 enabled' CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0
+  bool '  Synchronous serial port 0 enabled (sser1)' CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0
   if [ "$CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0" = "y" ]; then
-    bool '    Synchronous serial port 0 uses DMA' CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA
+    bool '    Synchronous serial port 0 uses DMA 8,9' CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA
   fi
-  bool '  Synchronous serial port 1 enabled' CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1
+  bool '  Synchronous serial port 1 enabled (sser3)' CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1
   if [ "$CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1" = "y" ]; then
-    bool '    Synchronous serial port 1 uses DMA' CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA
+    bool '    Synchronous serial port 1 uses DMA 4,5' CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA
   fi 
 fi
 
@@ -253,17 +280,28 @@
 # here we define the CONFIG_'s necessary to enable MTD support
 # for the flash
 	define_bool CONFIG_MTD y
-
-	define_bool CONFIG_MTD_CFI y
-	define_bool CONFIG_MTD_CFI_AMDSTD y
-
-	define_bool CONFIG_MTD_OBSOLETE_CHIPS y
-	define_bool CONFIG_MTD_AMDSTD y
-
+	define_bool CONFIG_MTD_PARTITIONS y
 	define_bool CONFIG_MTD_CHAR y
 	define_bool CONFIG_MTD_BLOCK y
-	define_bool CONFIG_MTD_PARTITIONS y
-	define_bool CONFIG_MTD_CONCAT y
+
+	if [ "$CONFIG_MTD_CFI" = "n" ] && [ "$CONFIG_MTD_AMDSTD" = "n" ] && \
+	   [ "$CONFIG_MTD_MTDRAM" = "n" ]; then
+		# Bad initial configuration, make axisflashmap work by enabling
+		# all drivers it may need.
+
+		define_bool CONFIG_MTD_CFI y
+		define_bool CONFIG_MTD_CFI_AMDSTD y
+
+		define_bool CONFIG_MTD_OBSOLETE_CHIPS y
+		define_bool CONFIG_MTD_AMDSTD y
+
+		define_bool CONFIG_MTD_CONCAT y
+
+		define_bool CONFIG_MTD_MTDRAM y
+		define_int CONFIG_MTDRAM_TOTAL_SIZE 0
+		define_int CONFIG_MTDRAM_ERASE_SIZE 64
+		define_int CONFIG_MTDRAM_ABS_POS 0
+	fi
 fi
 
 bool 'I2C support' CONFIG_ETRAX_I2C
diff -urN linux-2.4.23-bk3/arch/cris/drivers/Makefile linux-2.4.23-bk4/arch/cris/drivers/Makefile
--- linux-2.4.23-bk3/arch/cris/drivers/Makefile	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.23-bk4/arch/cris/drivers/Makefile	2003-12-06 02:49:48.000000000 -0800
@@ -4,6 +4,8 @@
 
 O_TARGET := drivers.o
 
+export-objs := axisflashmap.o
+
 obj-y :=
 
 obj-$(CONFIG_ETRAX_VIRTEX_FPGA)         += virtex.o
diff -urN linux-2.4.23-bk3/arch/cris/drivers/axisflashmap.c linux-2.4.23-bk4/arch/cris/drivers/axisflashmap.c
--- linux-2.4.23-bk3/arch/cris/drivers/axisflashmap.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-bk4/arch/cris/drivers/axisflashmap.c	2003-12-06 02:49:48.000000000 -0800
@@ -11,6 +11,12 @@
  * partition split defined below.
  *
  * $Log: axisflashmap.c,v $
+ * Revision 1.31  2003/11/14 16:55:27  jonashg
+ * Made it possible to RAM boot without any flash drivers present.
+ *
+ * Revision 1.30  2003/09/29 06:37:18  mikaelp
+ * Exported master mtd device as axisflash_mtd.
+ *
  * Revision 1.29  2003/04/01 14:12:06  starvik
  * Added loglevel for lots of printks
  *
@@ -142,6 +148,9 @@
 /* From head.S */
 extern unsigned long romfs_start, romfs_length, romfs_in_flash;
 
+/* The master mtd for the entire flash. */
+struct mtd_info* axisflash_mtd = NULL;
+
 /* Map driver functions. */
 
 static __u8 flash_read8(struct map_info *map, unsigned long ofs)
@@ -388,7 +397,7 @@
 	struct mtd_info *mymtd;
 	int err = 0;
 	int pidx = 0;
-	struct partitiontable_head *ptable_head;
+	struct partitiontable_head *ptable_head = NULL;
 	struct partitiontable_entry *ptable;
 	int use_default_ptable = 1; /* Until proven otherwise. */
 	const char *pmsg = KERN_INFO "  /dev/flash%d at 0x%08x, size 0x%08x\n";
@@ -397,19 +406,22 @@
 		/* There's no reason to use this module if no flash chip can
 		 * be identified. Make sure that's understood.
 		 */
-		panic("axisflashmap found no flash chip!\n");
+		printk(KERN_INFO "axisflashmap: Found no flash chip.\n");
+	} else {
+		printk(KERN_INFO "%s: 0x%08x bytes of flash memory.\n",
+		       mymtd->name, mymtd->size);
+		axisflash_mtd = mymtd;
 	}
 
-	printk(KERN_INFO "%s: 0x%08x bytes of flash memory.\n",
-	       mymtd->name, mymtd->size);
-
-	mymtd->module = THIS_MODULE;
-
-	ptable_head = (struct partitiontable_head *)(FLASH_CACHED_ADDR +
-		      CONFIG_ETRAX_PTABLE_SECTOR + PARTITION_TABLE_OFFSET);
+	if (mymtd) {
+		mymtd->module = THIS_MODULE;
+		ptable_head = (struct partitiontable_head *)(FLASH_CACHED_ADDR +
+			      CONFIG_ETRAX_PTABLE_SECTOR +
+			      PARTITION_TABLE_OFFSET);
+	}
 	pidx++;  /* First partition is always set to the default. */
 
-	if ((ptable_head->magic == PARTITION_TABLE_MAGIC)
+	if (ptable_head && (ptable_head->magic == PARTITION_TABLE_MAGIC)
 	    && (ptable_head->size <
 		(MAX_PARTITIONS * sizeof(struct partitiontable_entry) +
 		PARTITIONTABLE_END_MARKER_SIZE))
@@ -476,22 +488,25 @@
 		axis_partitions[pidx].offset = romfs_start - FLASH_CACHED_ADDR;
 		axis_partitions[pidx].mask_flags |= MTD_WRITEABLE;
 
-		printk(KERN_INFO " Adding readonly flash partition for romfs image:\n");
+		printk(KERN_INFO
+		       " Adding readonly flash partition for romfs image:\n");
 		printk(pmsg, pidx, axis_partitions[pidx].offset,
 		       axis_partitions[pidx].size);
 		pidx++;
 	}
 
-	if (use_default_ptable) {
-		printk(KERN_INFO " Using default partition table.\n");
-		err = add_mtd_partitions(mymtd, axis_default_partitions,
-		                         NUM_DEFAULT_PARTITIONS);
-	} else {
-		err = add_mtd_partitions(mymtd, axis_partitions, pidx);
-	}
+	if (mymtd) {
+		if (use_default_ptable) {
+			printk(KERN_INFO " Using default partition table.\n");
+			err = add_mtd_partitions(mymtd, axis_default_partitions,
+						 NUM_DEFAULT_PARTITIONS);
+		} else {
+			err = add_mtd_partitions(mymtd, axis_partitions, pidx);
+		}
 
-	if (err) {
-		panic("axisflashmap could not add MTD partitions!\n");
+		if (err) {
+			panic("axisflashmap could not add MTD partitions!\n");
+		}
 	}
 
 	if (!romfs_in_flash) {
@@ -529,3 +544,5 @@
 
 /* This adds the above to the kernels init-call chain. */
 module_init(init_axis_flash);
+
+EXPORT_SYMBOL(axisflash_mtd);
diff -urN linux-2.4.23-bk3/arch/cris/drivers/ethernet.c linux-2.4.23-bk4/arch/cris/drivers/ethernet.c
--- linux-2.4.23-bk3/arch/cris/drivers/ethernet.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-bk4/arch/cris/drivers/ethernet.c	2003-12-06 02:49:48.000000000 -0800
@@ -1,4 +1,4 @@
-/* $Id: ethernet.c,v 1.44 2003/07/01 10:55:07 starvik Exp $
+/* $Id: ethernet.c,v 1.48 2003/12/03 13:44:39 starvik Exp $
  *
  * e100net.c: A network driver for the ETRAX 100LX network controller.
  *
@@ -7,6 +7,19 @@
  * The outline of this driver comes from skeleton.c.
  *
  * $Log: ethernet.c,v $
+ * Revision 1.48  2003/12/03 13:44:39  starvik
+ * Use hardware pad for short packets. This prevents information leakage
+ * reported by Nessus.
+ *
+ * Revision 1.47  2003/11/25 15:12:38  anderstj
+ * Make sure the LED always is inititated.
+ *
+ * Revision 1.46  2003/08/28 14:35:29  jonasw
+ * Added support for TDK 2120C and fixed led when not connected
+ *
+ * Revision 1.45  2003/08/21 07:22:25  matsfg
+ * Optional behaviour on networkled when no connection.
+ *
  * Revision 1.44  2003/07/01 10:55:07  starvik
  * Never bring down link to make stupid POE equipment happy
  *
@@ -430,7 +443,8 @@
 struct transceiver_ops transceivers[] = 
 {
 	{0x1018, broadcom_check_speed, broadcom_check_duplex},  /* Broadcom */
-	{0xC039, tdk_check_speed, tdk_check_duplex},            /* TDK */
+	{0xC039, tdk_check_speed, tdk_check_duplex},            /* TDK 2120 */
+	{0x039C, tdk_check_speed, tdk_check_duplex},            /* TDK 2120C */
 	{0x0000, generic_check_speed, generic_check_duplex}     /* Generic, must be last */
 };
 
@@ -800,6 +814,7 @@
 static void
 e100_check_speed(unsigned long dummy)
 {
+	static int led_initiated = 0;
 	unsigned long data;
 	int old_speed = current_speed;
 
@@ -810,8 +825,10 @@
 		transceiver->check_speed();
 	}
 	
-	if (old_speed != current_speed)
+	if ((old_speed != current_speed) || !led_initiated) {
+		led_initiated = 1;
 		e100_set_network_leds(NO_NETWORK_ACTIVITY);
+	}
 
 	/* Reinitialize the timer. */
 	speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL;
@@ -957,6 +974,7 @@
 			break;
 	}
 	transceiver = ops;
+
 	return 0;
 }
 
@@ -1121,7 +1139,6 @@
 e100_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_local *np = (struct net_local *)dev->priv;
-	int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 	unsigned char *buf = skb->data;
 	
 #ifdef ETHDEBUG
@@ -1133,7 +1150,7 @@
 
 	dev->trans_start = jiffies;
 	
-	e100_hardware_send_packet(buf, length);
+	e100_hardware_send_packet(buf, skb->len);
 
 	myNextTxDesc = phys_to_virt(myNextTxDesc->descr.next);
 
@@ -1494,7 +1511,7 @@
 			struct ethtool_drvinfo info;
 			memset((void *) &info, 0, sizeof (info));
 			strncpy(info.driver, "ETRAX 100LX", sizeof(info.driver) - 1);
-			strncpy(info.version, "$Revision: 1.44 $", sizeof(info.version) - 1);
+			strncpy(info.version, "$Revision: 1.48 $", sizeof(info.version) - 1);
 			strncpy(info.fw_version, "N/A", sizeof(info.fw_version) - 1);
 			strncpy(info.bus_info, "N/A", sizeof(info.bus_info) - 1);
 			info.regdump_len = 0;
@@ -1692,7 +1709,11 @@
 
 	if (!current_speed) {
 		/* Make LED red, link is down */
+#if defined(CONFIG_ETRAX_NETWORK_RED_ON_NO_CONNECTION)
+		LED_NETWORK_SET(LED_RED);
+#else		
 		LED_NETWORK_SET(LED_OFF);
+#endif		
 	}
 	else if (light_leds) {
 		if (current_speed == 10) {
diff -urN linux-2.4.23-bk3/arch/cris/drivers/serial.c linux-2.4.23-bk4/arch/cris/drivers/serial.c
--- linux-2.4.23-bk3/arch/cris/drivers/serial.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-bk4/arch/cris/drivers/serial.c	2003-12-06 02:49:48.000000000 -0800
@@ -1,4 +1,4 @@
-/* $Id: serial.c,v 1.54 2003/07/08 12:42:19 johana Exp $
+/* $Id: serial.c,v 1.58 2003/08/29 17:32:50 johana Exp $
  *
  * Serial port driver for the ETRAX 100LX chip
  *
@@ -7,6 +7,24 @@
  *    Many, many authors. Based once upon a time on serial.c for 16x50.
  *
  * $Log: serial.c,v $
+ * Revision 1.58  2003/08/29 17:32:50  johana
+ * Fixed CMSPAR (Mark/Space) support. CMSPAR|PARODD = Mark(1) parity.
+ *
+ * Revision 1.57  2003/08/26 16:53:06  johana
+ * Merged in change_branch--johana to get non DMA support etc.
+ *
+ * Revision 1.56  2003/07/10 13:18:03  pkj
+ * Corrected a copy-paste error.
+ *
+ * Revision 1.55  2003/07/10 11:00:46  starvik
+ * Moved all the latest stuff to a branch until it is stable
+ *
+ * Revision 1.50.2.2  2003/07/28 09:59:39  johana
+ * Clear tr_running so next write really starts transmission.
+ *
+ * Revision 1.50.2.1  2003/07/10 10:59:54  starvik
+ * Moved all the latest stuff to a branch until it is stable
+ *
  * Revision 1.54  2003/07/08 12:42:19  johana
  * Removed some test defines within #if 0.
  * Moved a comment to correct place.
@@ -437,7 +455,7 @@
  *
  */
 
-static char *serial_version = "$Revision: 1.54 $";
+static char *serial_version = "$Revision: 1.58 $";
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -3164,6 +3182,7 @@
 		info->last_tx_active_usec = GET_JIFFIES_USEC();
 		info->last_tx_active = jiffies;
 		e100_disable_serial_tx_ready_irq(info);
+		info->tr_running = 0;
 		DFLOW(DEBUG_LOG(info->line, "tx_int: stop2\n", 0));
 	} else {
 		/* We must enable since it is disabled in ser_interrupt */
@@ -3657,20 +3676,14 @@
 	}
 	
 	if (cflag & CMSPAR) {
-		/* enable stick parity */
+		/* enable stick parity, PARODD mean Mark which matches ETRAX */
 		info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_stick_par, stick);
 		info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_stick_par, stick);
-		if (!(cflag & PARODD)) {
-			/* set mark parity */
-			info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd);
-			info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd);
-		}
-	} else {
-		if (cflag & PARODD) {
-			/* set odd parity */
-			info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd);
-			info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd);
-		}
+	}
+	if (cflag & PARODD) {
+		/* set odd parity (or Mark if CMSPAR) */
+		info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd);
+		info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd);
 	}
 	
 	if (cflag & CRTSCTS) {
diff -urN linux-2.4.23-bk3/arch/cris/drivers/sync_serial.c linux-2.4.23-bk4/arch/cris/drivers/sync_serial.c
--- linux-2.4.23-bk3/arch/cris/drivers/sync_serial.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-bk4/arch/cris/drivers/sync_serial.c	2003-12-06 02:49:48.000000000 -0800
@@ -6,9 +6,9 @@
  * decoder. The driver can easily be tuned to fit other audio encoder/decoders
  * and SPI
  *
- * Copyright (c) 2001 Axis Communications AB
+ * Copyright (c) 2001-2003 Axis Communications AB
  * 
- * Author: Mikael Starvik 
+ * Author: Mikael Starvik, Johan Adolfsson
  *
  */
 #include <linux/module.h>
@@ -20,6 +20,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
+#include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/timer.h>
 #include <asm/irq.h>
@@ -31,25 +32,26 @@
 
 /* The receiver is a bit tricky beacuse of the continuous stream of data.*/
 /*                                                                       */
-/* Two DMA descriptors are linked together. Each DMA descriptor is       */
-/* responsible for one half of a common buffer.                          */
+/* Three DMA descriptors are linked together. Each DMA descriptor is     */
+/* responsible for port->bufchunk of a common buffer.                    */
 /*                                                                       */
-/* ------------------------------                                        */
-/* |   ----------   ----------	|                                        */
-/* --> | Descr1 |-->| Descr2 |---                                        */
-/*     ----------   ----------                                           */
-/*         |            |                                                */
-/*         v            v                                                */
-/*   -----------------------------                                       */
-/*   |        BUFFER             |                                       */
-/*   -----------------------------                                       */
-/*      |             |                                                  */
+/* +---------------------------------------------+                       */
+/* |   +----------+   +----------+   +----------+ |                      */
+/* +-> | Descr[0] |-->| Descr[1] |-->| Descr[2] |-+                      */
+/*     +----------+   +----------+   +----------+                        */
+/*         |            |              |                                 */
+/*         v            v              v                                 */
+/*   +-------------------------------------+                             */
+/*   |        BUFFER                       |                             */
+/*   +-------------------------------------+                             */
+/*      |<- data_avail ->|                                               */
 /*    readp          writep                                              */
 /*                                                                       */
 /* If the application keeps up the pace readp will be right after writep.*/
 /* If the application can't keep the pace we have to throw away data.    */ 
 /* The idea is that readp should be ready with the data pointed out by	 */
-/* Descr1 when the DMA has filled in Descr2. Otherwise we will discard	 */
+/* Descr[i] when the DMA has filled in Descr[i+1].                       */
+/* Otherwise we will discard	                                         */
 /* the rest of the data pointed out by Descr1 and set readp to the start */
 /* of Descr2                                                             */
 
@@ -57,14 +59,22 @@
 
 /* IN_BUFFER_SIZE should be a multiple of 6 to make sure that 24 bit */
 /* words can be handled */
-
+#define NUM_IN_DESCR 3
 #define IN_BUFFER_SIZE 12288
 #define OUT_BUFFER_SIZE 4096
 
 #define DEFAULT_FRAME_RATE 0
 #define DEFAULT_WORD_RATE 7
 
+/* NOTE: Enabling some debug will likely cause overrun or underrun,
+ * especially if manual mode is use.
+ */
 #define DEBUG(x)
+#define DEBUGREAD(x)
+#define DEBUGWRITE(x)
+#define DEBUGPOLL(x)
+#define DEBUGRXINT(x)
+#define DEBUGTXINT(x)
 
 /* Define some macros to access ETRAX 100 registers */
 #define SETF(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
@@ -75,97 +85,126 @@
 typedef struct sync_port
 {
 	/* Etrax registers and bits*/
-	volatile unsigned * const status;
+	const volatile unsigned * const status;
 	volatile unsigned * const ctrl_data;
 	volatile unsigned * const output_dma_first;
 	volatile unsigned char * const output_dma_cmd;
 	volatile unsigned char * const output_dma_clr_irq;
 	volatile unsigned * const input_dma_first;
 	volatile unsigned char * const input_dma_cmd;
+  	volatile unsigned * const input_dma_descr;
+	/* 8*4 */	
 	volatile unsigned char * const input_dma_clr_irq;
 	volatile unsigned * const data_out;
-	volatile unsigned * const data_in;
-	char data_avail_bit; /* In R_IRQ_MASK1_RD */
-	char transmitter_ready_bit; /* In R_IRQ_MASK1_RD */
-	char ready_irq_bit; /* In R_IRQ_MASK1_SET and R_IRQ_MASK1_CLR */
+	const volatile unsigned * const data_in;
+	char data_avail_bit; /* In R_IRQ_MASK1_RD/SET/CLR */
+	char transmitter_ready_bit; /* In R_IRQ_MASK1_RD/SET/CLR */
 	char input_dma_descr_bit; /* In R_IRQ_MASK2_RD */
-	char output_dma_bit; /* In R_IRQ_MASK2_RD */
 
-	int enabled;  /* 1 if port is enabled */
-	int use_dma;  /* 1 if port uses dma */
-	int port_nbr; /* Port 0 or 1 */
-	unsigned ctrl_data_shadow; /* Register shadow */
+	char output_dma_bit; /* In R_IRQ_MASK2_RD */
+	/* End of fields initialised in array */
+	char started; /* 1 if port has been started */
+	char port_nbr; /* Port 0 or 1 */
 	char busy; /* 1 if port is busy */
-	wait_queue_head_t out_wait_q;
-	wait_queue_head_t in_wait_q;
+
+	char enabled;  /* 1 if port is enabled */
+	char use_dma;  /* 1 if port uses dma */
+	char cur_in_descr;
+	char tr_running;
+	
+	unsigned int ctrl_data_shadow; /* Register shadow */
+	volatile unsigned int out_count; /* Remaining bytes for current transfer */
+	unsigned char* outp; /* Current position in out_buffer */
+	/* 16*4 */
+	volatile unsigned char* volatile readp;  /* Next byte to be read by application */
+	volatile unsigned char* volatile writep; /* Next byte to be written by etrax */
+	unsigned int in_buffer_size;
+	unsigned int inbufchunk;
 	struct etrax_dma_descr out_descr;
-	struct etrax_dma_descr in_descr1;
-	struct etrax_dma_descr in_descr2;
-	char out_buffer[OUT_BUFFER_SIZE];
-	int out_count; /* Remaining bytes for current transfer */
-	char* outp; /* Current position in out_buffer */
-	char in_buffer[IN_BUFFER_SIZE];
-	volatile char* readp;  /* Next byte to be read by application */
-	volatile char* writep; /* Next byte to be written by etrax */
-	int started; /* 1 if port has been started */
+	struct etrax_dma_descr in_descr[NUM_IN_DESCR];
+	unsigned char out_buffer[OUT_BUFFER_SIZE];
+	unsigned char in_buffer[IN_BUFFER_SIZE];
+
+	wait_queue_head_t out_wait_q;
+	wait_queue_head_t in_wait_q;	
 } sync_port;
 
 
 static int etrax_sync_serial_init(void);
 static void initialize_port(int portnbr);
+static inline int sync_data_avail(struct sync_port *port);
+
 static int sync_serial_open(struct inode *, struct file*);
 static int sync_serial_release(struct inode*, struct file*);
+static unsigned int sync_serial_poll(struct file *filp, poll_table *wait);
+
 static int sync_serial_ioctl(struct inode*, struct file*,
 			     unsigned int cmd, unsigned long arg);
 static ssize_t sync_serial_write(struct file * file, const char * buf, 
 				 size_t count, loff_t *ppos);
-static ssize_t sync_serial_manual_write(struct file * file, const char * buf, 
-					size_t count, loff_t *ppos);
 static ssize_t sync_serial_read(struct file *file, char *buf, 
 				size_t count, loff_t *ppos);
+
+#if (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) && \
+     defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)) || \
+    (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) && \
+     defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA))
+#define SYNC_SER_DMA
+#endif
+
 static void send_word(sync_port* port);
 static void start_dma(struct sync_port *port, const char* data, int count);
 static void start_dma_in(sync_port* port);
+#ifdef SYNC_SER_DMA
 static void tr_interrupt(int irq, void *dev_id, struct pt_regs * regs);
 static void rx_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+#endif
+#if (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) && \
+     !defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)) || \
+    (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) && \
+     !defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA))
+#define SYNC_SER_MANUAL
+#endif
+#ifdef SYNC_SER_MANUAL
 static void manual_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+#endif
 
 /* The ports */
 static struct sync_port ports[]=
 {
 	{
-		R_SYNC_SERIAL1_STATUS,  /* status */
-		R_SYNC_SERIAL1_CTRL,    /* ctrl_data */
-		R_DMA_CH8_FIRST,        /* output_dma_first */
-		R_DMA_CH8_CMD,          /* output_dma_cmd */
-		R_DMA_CH8_CLR_INTR,     /* output_dma_clr_irq */
-		R_DMA_CH9_FIRST,        /* input_dma_first */
-		R_DMA_CH9_CMD,          /* input_dma_cmd */
-		R_DMA_CH9_CLR_INTR,     /* input_dma_clr_irq */
-		R_SYNC_SERIAL1_TR_DATA, /* data_out */
-		R_SYNC_SERIAL1_REC_DATA,/* data in */
-		IO_BITNR(R_IRQ_MASK1_RD, ser1_data),   /* data_avail_bit */
-		IO_BITNR(R_IRQ_MASK1_RD, ser1_ready),  /* transmitter_ready_bit */
-		IO_BITNR(R_IRQ_MASK1_SET, ser1_ready), /* ready_irq_bit */
-		IO_BITNR(R_IRQ_MASK2_RD, dma9_descr),  /* input_dma_descr_bit */
-		IO_BITNR(R_IRQ_MASK2_RD, dma8_eop),    /* output_dma_bit */
+		.status                = R_SYNC_SERIAL1_STATUS,
+		.ctrl_data             = R_SYNC_SERIAL1_CTRL,  
+		.output_dma_first      = R_DMA_CH8_FIRST,
+		.output_dma_cmd        = R_DMA_CH8_CMD,
+		.output_dma_clr_irq    = R_DMA_CH8_CLR_INTR,     
+		.input_dma_first       = R_DMA_CH9_FIRST,
+		.input_dma_cmd         = R_DMA_CH9_CMD,
+		.input_dma_descr       = R_DMA_CH9_DESCR,
+		.input_dma_clr_irq     = R_DMA_CH9_CLR_INTR,
+		.data_out              = R_SYNC_SERIAL1_TR_DATA,
+		.data_in               = R_SYNC_SERIAL1_REC_DATA,
+		.data_avail_bit        = IO_BITNR(R_IRQ_MASK1_RD, ser1_data),
+		.transmitter_ready_bit = IO_BITNR(R_IRQ_MASK1_RD, ser1_ready),
+		.input_dma_descr_bit   = IO_BITNR(R_IRQ_MASK2_RD, dma9_descr),
+		.output_dma_bit        = IO_BITNR(R_IRQ_MASK2_RD, dma8_eop),
 	},
 	{
-		R_SYNC_SERIAL3_STATUS,  /* status */
-		R_SYNC_SERIAL3_CTRL,    /* ctrl_data */
-		R_DMA_CH4_FIRST,        /* output_dma_first */
-		R_DMA_CH4_CMD,          /* output_dma_cmd */
-		R_DMA_CH4_CLR_INTR,     /* output_dma_clr_irq */
-		R_DMA_CH5_FIRST,        /* input_dma_first */
-		R_DMA_CH5_CMD,          /* input_dma_cmd */
-		R_DMA_CH5_CLR_INTR,     /* input_dma_clr_irq */
-		R_SYNC_SERIAL3_TR_DATA, /* data_out */
-		R_SYNC_SERIAL3_REC_DATA,/* data in */
-		IO_BITNR(R_IRQ_MASK1_RD, ser3_data),   /* data_avail_bit */
-		IO_BITNR(R_IRQ_MASK1_RD, ser3_ready),  /* transmitter_ready_bit */
-		IO_BITNR(R_IRQ_MASK1_SET, ser3_ready), /* ready_irq_bit */
-		IO_BITNR(R_IRQ_MASK2_RD, dma5_descr),  /* input_dma_descr_bit */
-		IO_BITNR(R_IRQ_MASK2_RD, dma4_eop),    /* output_dma_bit */
+		.status                = R_SYNC_SERIAL3_STATUS,
+		.ctrl_data             = R_SYNC_SERIAL3_CTRL,
+		.output_dma_first      = R_DMA_CH4_FIRST,
+		.output_dma_cmd        = R_DMA_CH4_CMD,
+		.output_dma_clr_irq    = R_DMA_CH4_CLR_INTR,
+		.input_dma_first       = R_DMA_CH5_FIRST,
+		.input_dma_cmd         = R_DMA_CH5_CMD,
+		.input_dma_descr       = R_DMA_CH5_DESCR,		
+		.input_dma_clr_irq     = R_DMA_CH5_CLR_INTR,
+		.data_out              = R_SYNC_SERIAL3_TR_DATA,
+		.data_in               = R_SYNC_SERIAL3_REC_DATA,
+		.data_avail_bit        = IO_BITNR(R_IRQ_MASK1_RD, ser3_data),
+		.transmitter_ready_bit = IO_BITNR(R_IRQ_MASK1_RD, ser3_ready),
+		.input_dma_descr_bit   = IO_BITNR(R_IRQ_MASK2_RD, dma5_descr),
+		.output_dma_bit        = IO_BITNR(R_IRQ_MASK2_RD, dma4_eop),
 	}
 };
 
@@ -176,12 +215,13 @@
 #define NUMBER_OF_PORTS (sizeof(ports)/sizeof(sync_port))
 
 static struct file_operations sync_serial_fops = {
-       owner:	THIS_MODULE,
-       write:	sync_serial_write,
-       read:	sync_serial_read,
-       ioctl:	sync_serial_ioctl,
-       open:	sync_serial_open,
-       release: sync_serial_release
+	.owner   = THIS_MODULE,
+	.write   = sync_serial_write,
+	.read    = sync_serial_read,
+	.poll    = sync_serial_poll,
+	.ioctl   = sync_serial_ioctl,
+	.open    = sync_serial_open,
+	.release = sync_serial_release
 };
 
 static int __init etrax_sync_serial_init(void)
@@ -238,9 +278,9 @@
 	ports[1].use_dma = 1;
 	initialize_port(1);
 	if(request_irq(20, tr_interrupt, 0, "synchronous serial 3 dma tr", &ports[1]))
-		panic("Can't allocate sync serial port 1 IRQ");
+		panic("Can't allocate sync serial port 3 IRQ");
 	if(request_irq(21, rx_interrupt, 0, "synchronous serial 3 dma rx", &ports[1]))
-		panic("Can't allocate sync serial port 1 IRQ");
+		panic("Can't allocate sync serial port 3 IRQ");
 	RESET_DMA(4); WAIT_DMA(4);
 	RESET_DMA(5); WAIT_DMA(5);
 	*R_DMA_CH4_CLR_INTR = IO_STATE(R_DMA_CH4_CLR_INTR, clr_eop, do) |
@@ -254,7 +294,7 @@
 #else
 	ports[1].use_dma = 0;	
 	initialize_port(1);
-	if (ports[0].use_dma) /* Port 0 uses dma, we must manual allocate IRQ */
+	if (!ports[0].enabled || ports[0].use_dma) /* Port 0 uses dma, we must manual allocate IRQ */
 	{
 		if (request_irq(8, manual_interrupt, SA_SHIRQ | SA_INTERRUPT, "synchronous serial manual irq", &ports[1]))
 			panic("Can't allocate sync serial manual irq");
@@ -282,7 +322,7 @@
 	return 0;
 }
 
-static void initialize_port(int portnbr)
+static void __init initialize_port(int portnbr)
 {
 	struct sync_port* port = &ports[portnbr];
 
@@ -290,13 +330,21 @@
 
 	port->started = 0;    
 	port->port_nbr = portnbr;	
-	port->busy = 0;		
+	port->busy = 0;
+	port->cur_in_descr = 0;
+	port->tr_running = 0;
+
+	port->out_count = 0;
+	port->outp = port->out_buffer;
+	
 	port->readp = port->in_buffer;
 	port->writep = port->in_buffer;
+	port->in_buffer_size = IN_BUFFER_SIZE;
+	port->inbufchunk = port->in_buffer_size/NUM_IN_DESCR;
 
 	init_waitqueue_head(&port->out_wait_q);
 	init_waitqueue_head(&port->in_wait_q);
-
+	
 	port->ctrl_data_shadow =
 	  IO_STATE(R_SYNC_SERIAL1_CTRL, tr_baud, c115k2Hz)   | 
 	  IO_STATE(R_SYNC_SERIAL1_CTRL, mode, master_output) | 
@@ -329,9 +377,53 @@
 	*port->ctrl_data = port->ctrl_data_shadow;
 }
 
+static inline int sync_data_avail(struct sync_port *port)
+{
+	int avail;
+	unsigned char *start;
+	unsigned char *end;
+	
+	start = (unsigned char*)port->readp; /* cast away volatile */
+	end = (unsigned char*)port->writep;  /* cast away volatile */
+	/* 0123456789  0123456789
+	 *  -----      -    -----
+	 *  ^rp  ^wp    ^wp ^rp
+	 */
+	        
+  	if (end >= start)
+		avail = end - start;
+	else 
+		avail = port->in_buffer_size - (start - end);
+	return avail;
+}
+
+static inline int sync_data_avail_to_end(struct sync_port *port)
+{
+	int avail;
+	unsigned char *start;
+	unsigned char *end;
+	
+	start = (unsigned char*)port->readp; /* cast away volatile */
+	end = (unsigned char*)port->writep;  /* cast away volatile */
+	/* 0123456789  0123456789
+	 *  -----           -----
+	 *  ^rp  ^wp    ^wp ^rp
+	 */
+	        
+  	if (end >= start)
+		avail = end - start;
+	else 
+		avail = port->in_buffer + port->in_buffer_size - start;
+	return avail;
+}
+
+
 static int sync_serial_open(struct inode *inode, struct file *file)
 {
 	int dev = MINOR(inode->i_rdev);
+	sync_port* port;
+	int mode;
+	
 	DEBUG(printk("Open sync serial port %d\n", dev)); 
   
 	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
@@ -339,33 +431,87 @@
 		DEBUG(printk("Invalid minor %d\n", dev));
 		return -ENODEV;
 	}
-	if (ports[dev].busy)
+	port = &ports[dev];
+	/* Allow open this device twice (assuming one reader and one writer) */
+	if (port->busy == 2) 
 	{
 		DEBUG(printk("Device is busy.. \n"));
 		return -EBUSY;
 	}
-	ports[dev].busy = 1;
+	port->busy++;
+	/* Start port if we use it as input */
+	mode = IO_EXTRACT(R_SYNC_SERIAL1_CTRL, mode, port->ctrl_data_shadow);
+	if (mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, master_input) ||
+	    mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, slave_input) ||
+	    mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, master_bidir) ||
+	    mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, slave_bidir)) {
+		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, running);
+		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable, enable);
+		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable, enable);
+		port->started = 1;
+		*port->ctrl_data = port->ctrl_data_shadow;
+		if (!port->use_dma)
+			*R_IRQ_MASK1_SET = 1 << port->data_avail_bit;
+		DEBUG(printk("sser%d rec started\n", dev)); 
+	}		
 	return 0;
 }
 
 static int sync_serial_release(struct inode *inode, struct file *file)
 {
 	int dev = MINOR(inode->i_rdev);
+	sync_port* port;
+
 	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
 	{
 		DEBUG(printk("Invalid minor %d\n", dev));
 		return -ENODEV;
 	}
-	ports[dev].busy = 0;
+	port = &ports[dev];
+	if (port->busy)
+		port->busy--;
+	if (!port->busy) 
+		*R_IRQ_MASK1_CLR = ((1 << port->data_avail_bit) |
+				    (1 << port->transmitter_ready_bit));
+
 	return 0;
 }
 
+
+
+static unsigned int sync_serial_poll(struct file *file, poll_table *wait)
+{
+	int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+	unsigned int mask = 0;
+	sync_port* port;
+	DEBUGPOLL( static unsigned int prev_mask = 0; );
+	
+	port = &ports[dev];
+	poll_wait(file, &port->out_wait_q, wait);
+	poll_wait(file, &port->in_wait_q, wait);
+	/* Some room to write */
+	if (port->out_count < OUT_BUFFER_SIZE)
+		mask |=  POLLOUT | POLLWRNORM;
+	/* At least an inbufchunk of data */
+	if (sync_data_avail(port) >= port->inbufchunk)
+		mask |= POLLIN | POLLRDNORM;
+	
+	DEBUGPOLL(if (mask != prev_mask)
+	      printk("sync_serial_poll: mask 0x%08X %s %s\n", mask,
+		     mask&POLLOUT?"POLLOUT":"", mask&POLLIN?"POLLIN":"");
+	      prev_mask = mask;
+	      );
+	return mask;
+}
+
 static int sync_serial_ioctl(struct inode *inode, struct file *file,
 		  unsigned int cmd, unsigned long arg)
 {
 	int return_val = 0;
+	unsigned long flags;
+	
 	int dev = MINOR(file->f_dentry->d_inode->i_rdev);
-  sync_port* port;
+	sync_port* port;
         
 	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
 	{
@@ -374,197 +520,199 @@
 	}
         port = &ports[dev];
 
+	save_flags(flags);
+	cli();
 	/* Disable port while changing config */
 	if (dev)
 	{
-		RESET_DMA(4); WAIT_DMA(4);
-		*R_DMA_CH4_CLR_INTR = IO_STATE(R_DMA_CH4_CLR_INTR, clr_eop, do) |
-                  IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr, do); 
+		if (port->use_dma) {
+			RESET_DMA(4); WAIT_DMA(4);
+			*R_DMA_CH4_CLR_INTR = IO_STATE(R_DMA_CH4_CLR_INTR, clr_eop, do) |
+				IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr, do);
+		}
 		SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, async);
 	}
 	else
 	{
-		RESET_DMA(8); WAIT_DMA(8);
-		*R_DMA_CH8_CLR_INTR = IO_STATE(R_DMA_CH8_CLR_INTR, clr_eop, do) |
-                  IO_STATE(R_DMA_CH8_CLR_INTR, clr_descr, do);  
+		if (port->use_dma) {		
+			RESET_DMA(8); WAIT_DMA(8);
+			*R_DMA_CH8_CLR_INTR = IO_STATE(R_DMA_CH8_CLR_INTR, clr_eop, do) |
+				IO_STATE(R_DMA_CH8_CLR_INTR, clr_descr, do);
+		}
 		SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, async);
 	}
 	*R_GEN_CONFIG_II = gen_config_ii_shadow;
+	restore_flags(flags);
 
 	switch(cmd)
 	{
-		case SSP_SPEED:
-			if (GET_SPEED(arg) == CODEC)
-			{
-				if (dev)
-					SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u3, codec);
-				else
-					SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u1, codec);
-
-				SETF(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, prescaler, GET_FREQ(arg));
-				SETF(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, frame_rate, GET_FRAME_RATE(arg));
-				SETF(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, word_rate, GET_WORD_RATE(arg));
-			}
+	case SSP_SPEED:
+		if (GET_SPEED(arg) == CODEC)
+		{
+			if (dev)
+				SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u3, codec);
 			else
-			{
-				SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_baud, GET_SPEED(arg));
-				if (dev)
-					SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u3, baudrate);
-				else
-					SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u1, baudrate);
-			}
-			break;
-		case SSP_MODE:
-			if (arg > 5)
-				return -EINVAL;
-			if (arg == MASTER_OUTPUT || arg == SLAVE_OUTPUT)
-				*R_IRQ_MASK1_CLR = 1 << port->data_avail_bit;
+				SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u1, codec);
+			
+			SETF(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, prescaler, GET_FREQ(arg));
+			SETF(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, frame_rate, GET_FRAME_RATE(arg));
+			SETF(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, word_rate, GET_WORD_RATE(arg));
+		}
+		else
+		{
+			SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_baud, GET_SPEED(arg));
+			if (dev)
+				SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u3, baudrate);
 			else
-				*R_IRQ_MASK1_SET = 1 << port->data_avail_bit;
-			SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, arg);
-			break;
-		case SSP_FRAME_SYNC:
-			if (arg & NORMAL_SYNC)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, normal);
-			else if (arg & EARLY_SYNC)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, early);
-    
-			if (arg & BIT_SYNC)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, bit);
-			else if (arg & WORD_SYNC)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, word);
-			else if (arg & EXTENDED_SYNC)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, extended);
-    
-			if (arg & SYNC_ON)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, on);
-			else if (arg & SYNC_OFF)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, off);
-    
-			if (arg & WORD_SIZE_8)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size8bit);
-			else if (arg & WORD_SIZE_12)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size12bit);
-			else if (arg & WORD_SIZE_16)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size16bit);
-			else if (arg & WORD_SIZE_24)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size24bit);
-			else if (arg & WORD_SIZE_32)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size32bit);
-    
-			if (arg & BIT_ORDER_MSB)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, msb);
-			else if (arg & BIT_ORDER_LSB)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, lsb);
-
-			if (arg & FLOW_CONTROL_ENABLE)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, enabled);
-			else if (arg & FLOW_CONTROL_DISABLE)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, disabled);
-
-			if (arg & CLOCK_NOT_GATED)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_mode, normal);
-			else if (arg & CLOCK_GATED)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_mode, gated);    
-
-			break;
-		case SSP_IPOLARITY:
-			if (arg & CLOCK_NORMAL)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_polarity, neg);
-			else if (arg & CLOCK_INVERT)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_polarity, pos);
-
-			if (arg & FRAME_NORMAL)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_polarity, normal);
-			else if (arg & FRAME_INVERT)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_polarity, inverted);
-
-			if (arg & STATUS_NORMAL)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_polarity, normal);
-			else if (arg & STATUS_INVERT)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_polarity, inverted);
-			break;
-		case SSP_OPOLARITY:
-			if (arg & CLOCK_NORMAL)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_driver, normal);
-			else if (arg & CLOCK_INVERT)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_driver, inverted);
-    
-			if (arg & FRAME_NORMAL)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_driver, normal);
-			else if (arg & FRAME_INVERT)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_driver, inverted);
-
-			if (arg & STATUS_NORMAL)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_driver, normal);
-			else if (arg & STATUS_INVERT)
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_driver, inverted);
-			break;
-		case SSP_SPI:
-			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, disabled);
-			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, msb);
-			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size8bit);
-			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, on);
-			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, word);
+				SETS(sync_serial_prescale_shadow, R_SYNC_SERIAL_PRESCALE, clk_sel_u1, baudrate);
+		}
+		break;
+	case SSP_MODE:
+		if (arg > 5)
+			return -EINVAL;
+		if (arg == MASTER_OUTPUT || arg == SLAVE_OUTPUT)
+			*R_IRQ_MASK1_CLR = 1 << port->data_avail_bit;
+		else if (!port->use_dma)
+			*R_IRQ_MASK1_SET = 1 << port->data_avail_bit;
+		SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, arg);
+		break;
+	case SSP_FRAME_SYNC:
+		if (arg & NORMAL_SYNC)
 			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, normal);
-			if (arg & SPI_SLAVE)
-			{
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_polarity, inverted);
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_polarity, neg);
-				SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, SLAVE_INPUT);
-			}
-			else
-			{
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_driver, inverted);
-				SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_driver, inverted);
-				SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, MASTER_OUTPUT);
+		else if (arg & EARLY_SYNC)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, early);
+		
+		if (arg & BIT_SYNC)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, bit);
+		else if (arg & WORD_SYNC)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, word);
+		else if (arg & EXTENDED_SYNC)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, extended);
+		
+		if (arg & SYNC_ON)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, on);
+		else if (arg & SYNC_OFF)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, off);
+		
+		if (arg & WORD_SIZE_8)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size8bit);
+		else if (arg & WORD_SIZE_12)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size12bit);
+		else if (arg & WORD_SIZE_16)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size16bit);
+		else if (arg & WORD_SIZE_24)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size24bit);
+		else if (arg & WORD_SIZE_32)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size32bit);
+		
+		if (arg & BIT_ORDER_MSB)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, msb);
+		else if (arg & BIT_ORDER_LSB)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, lsb);
+		
+		if (arg & FLOW_CONTROL_ENABLE)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, enabled);
+		else if (arg & FLOW_CONTROL_DISABLE)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, disabled);
+		
+		if (arg & CLOCK_NOT_GATED)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_mode, normal);
+		else if (arg & CLOCK_GATED)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_mode, gated);    
+		
+		break;
+	case SSP_IPOLARITY:
+		/* NOTE!! negedge is considered NORMAL */
+		if (arg & CLOCK_NORMAL)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_polarity, neg);
+		else if (arg & CLOCK_INVERT)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_polarity, pos);
+		
+		if (arg & FRAME_NORMAL)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_polarity, normal);
+		else if (arg & FRAME_INVERT)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_polarity, inverted);
+		
+		if (arg & STATUS_NORMAL)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_polarity, normal);
+		else if (arg & STATUS_INVERT)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_polarity, inverted);
+		break;
+	case SSP_OPOLARITY:
+		if (arg & CLOCK_NORMAL)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_driver, normal);
+		else if (arg & CLOCK_INVERT)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_driver, inverted);
+		
+		if (arg & FRAME_NORMAL)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_driver, normal);
+		else if (arg & FRAME_INVERT)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_driver, inverted);
+		
+		if (arg & STATUS_NORMAL)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_driver, normal);
+		else if (arg & STATUS_INVERT)
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, status_driver, inverted);
+		break;
+	case SSP_SPI:
+		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, disabled);
+		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, msb);
+		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, size8bit);
+		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, on);
+		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, word);
+		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, normal);
+		if (arg & SPI_SLAVE)
+		{
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_polarity, inverted);
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_polarity, neg);
+			SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, SLAVE_INPUT);
+		}
+		else
+		{
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, frame_driver, inverted);
+			SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_driver, inverted);
+			SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, MASTER_OUTPUT);
+		}
+		break;
+	case SSP_INBUFCHUNK:
+		if (arg > port->in_buffer_size/NUM_IN_DESCR)
+			return -EINVAL;
+		port->inbufchunk = arg;
+		/* Make sure in_buffer_size is a multiple of inbufchunk */
+		port->in_buffer_size = (port->in_buffer_size/port->inbufchunk) * port->inbufchunk;
+		DEBUG(printk("inbufchunk %i in_buffer_size: %i\n", port->inbufchunk, port->in_buffer_size));
+		if (port->use_dma) {
+			if (port->port_nbr == 0) {
+				RESET_DMA(9);
+				WAIT_DMA(9);
+			} else {
+				RESET_DMA(5);
+				WAIT_DMA(5);
 			}
-			break;
-		default:
-			return_val = -1;
+			start_dma_in(port);
+		}
+		break;
+	default:
+		return_val = -1;
 	}
+	/* Make sure we write the config without interruption */
+	save_flags(flags);
+	cli();	
 	/* Set config and enable port */
 	*port->ctrl_data = port->ctrl_data_shadow;
+	nop(); nop(); nop(); nop();
 	*R_SYNC_SERIAL_PRESCALE = sync_serial_prescale_shadow;
+	nop(); nop(); nop(); nop();
 	if (dev)
 		SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, sync);
 	else
 		SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, sync);
 
 	*R_GEN_CONFIG_II = gen_config_ii_shadow;
+	restore_flags(flags);	
 	return return_val;
 }
 
-static ssize_t sync_serial_manual_write(struct file * file, const char * buf, 
-                                        size_t count, loff_t *ppos)
-{
-	int dev = MINOR(file->f_dentry->d_inode->i_rdev);
-	DECLARE_WAITQUEUE(wait, current);
-	sync_port* port;
-
-	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
-	{
-		DEBUG(printk("Invalid minor %d\n", dev));
-		return -ENODEV;
-	}
-
-	port = &ports[dev];
-	copy_from_user(port->out_buffer, buf, count);
-	port->outp = port->out_buffer;
-	port->out_count = count;
-	add_wait_queue(&port->out_wait_q, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	send_word(port); /* Start sender by sending first word */
-	*R_IRQ_MASK1_SET = 1 << port->ready_irq_bit; /* transmitter ready IRQ on */
-	schedule();
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->out_wait_q, &wait);
-	if (signal_pending(current))
-	{
-		return -EINTR;
-	}
-	return count;
-}
 
 static ssize_t sync_serial_write(struct file * file, const char * buf, 
                                  size_t count, loff_t *ppos)
@@ -572,6 +720,11 @@
 	int dev = MINOR(file->f_dentry->d_inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);	
 	sync_port *port;
+	unsigned long flags;
+	unsigned long c, c1;
+	unsigned long free_outp;
+	unsigned long outp;
+	unsigned long out_buffer;
 
 	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
 	{
@@ -580,9 +733,52 @@
 	}
 	port = &ports[dev];
 
-	DEBUG(printk("Write dev %d count %d\n", port->port_nbr, count));
+	DEBUGWRITE(printk("W d%d c %lu (%d/%d)\n", port->port_nbr, count, port->out_count, OUT_BUFFER_SIZE));
+	/* Space to end of buffer */
+	/* 
+	 * out_buffer <c1>012345<-   c    ->OUT_BUFFER_SIZE
+	 *            outp^    +out_count
+	                        ^free_outp
+	 * out_buffer 45<-     c      ->0123OUT_BUFFER_SIZE
+	 *             +out_count   outp^
+	 *              free_outp
+	 *
+	 */
 
-	count = count > OUT_BUFFER_SIZE ? OUT_BUFFER_SIZE : count;
+	/* Read variables that may be updated by interrupts */
+	save_flags(flags);
+	cli();		
+	count = count > OUT_BUFFER_SIZE - port->out_count ? OUT_BUFFER_SIZE  - port->out_count : count;
+	outp = (unsigned long)port->outp;
+	free_outp = outp + port->out_count;
+	restore_flags(flags);
+	out_buffer = (unsigned long)port->out_buffer;
+	
+	/* Find out where and how much to write */
+	if (free_outp >= out_buffer + OUT_BUFFER_SIZE)
+		free_outp -= OUT_BUFFER_SIZE;
+	if (free_outp >= outp)
+		c = out_buffer + OUT_BUFFER_SIZE - free_outp;
+	else
+		c = outp - free_outp;
+	if (c > count)
+		c = count;
+	
+//	DEBUGWRITE(printk("w op %08lX fop %08lX c %lu\n", outp, free_outp, c));
+	if (copy_from_user((void*)free_outp, buf, c))
+		return -EFAULT;
+
+	if (c != count) {
+		buf += c;
+		c1 = count - c;
+		DEBUGWRITE(printk("w2 fi %lu c %lu c1 %lu\n", free_outp-out_buffer, c, c1));
+		if (copy_from_user((void*)out_buffer, buf, c1))
+			return -EFAULT;
+	}
+	save_flags(flags);
+	cli();		
+	port->out_count += count;
+	restore_flags(flags);
 
 	/* Make sure transmitter/receiver is running */
 	if (!port->started)
@@ -595,15 +791,42 @@
 
 	*port->ctrl_data = port->ctrl_data_shadow;
 
-	if (!port->use_dma)
-	{
-		return sync_serial_manual_write(file, buf, count, ppos); 
+	if (file->f_flags & O_NONBLOCK)	{
+		save_flags(flags);
+		cli();
+		if (!port->tr_running) {
+			if (!port->use_dma) {
+				/* Start sender by writing data */
+				send_word(port);
+				/* and enable transmitter ready IRQ */
+				*R_IRQ_MASK1_SET = 1 << port->transmitter_ready_bit;
+			} else {
+				start_dma(port, (unsigned char* volatile )port->outp, c);
+			}
+		}
+		restore_flags(flags);
+		DEBUGWRITE(printk("w d%d c %lu NB\n",
+				  port->port_nbr, count));
+		return count;
 	}
-  
-	copy_from_user(port->out_buffer, buf, count);
+
+	/* Sleep until all sent */
+	
 	add_wait_queue(&port->out_wait_q, &wait);
 	set_current_state(TASK_INTERRUPTIBLE);
-	start_dma(port, buf, count);
+	save_flags(flags);
+	cli();
+	if (!port->tr_running) {
+		if (!port->use_dma) {
+			/* Start sender by writing data */
+			send_word(port);
+			/* and enable transmitter ready IRQ */
+			*R_IRQ_MASK1_SET = 1 << port->transmitter_ready_bit;
+		} else {
+			start_dma(port, port->outp, c);
+		}
+	}
+	restore_flags(flags);
 	schedule();
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&port->out_wait_q, &wait);
@@ -611,6 +834,7 @@
 	{
 		return -EINTR;
 	}
+	DEBUGWRITE(printk("w d%d c %lu\n", port->port_nbr, count));
 	return count;
 }
 
@@ -620,8 +844,8 @@
 	int dev = MINOR(file->f_dentry->d_inode->i_rdev);
 	int avail;
 	sync_port *port;
-	char* start; 
-	char* end;
+	unsigned char* start; 
+	unsigned char* end;
 	unsigned long flags;	
 
 	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
@@ -631,7 +855,7 @@
 	}
 	port = &ports[dev];
 
-	DEBUG(printk("Read dev %d count %d\n", dev, count));
+	DEBUGREAD(printk("R%d c %d ri %lu wi %lu /%lu\n", dev, count, port->readp - port->in_buffer, port->writep - port->in_buffer, port->in_buffer_size));
 
 	if (!port->started)
 	{
@@ -640,11 +864,17 @@
 		SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable, enable);
 		port->started = 1;
 	}
-
 	*port->ctrl_data = port->ctrl_data_shadow;
 
+	
 	/* Calculate number of available bytes */
-	while (port->readp == port->writep) /* No data */
+	/* Save pointers to avoid that they are modified by interrupt */
+	save_flags(flags);
+	cli();	
+	start = (unsigned char*)port->readp; /* cast away volatile */
+	end = (unsigned char*)port->writep;  /* cast away volatile */
+	restore_flags(flags);
+	while (start == end) /* No data */
 	{
 		if (file->f_flags & O_NONBLOCK)
 			return -EAGAIN;
@@ -653,127 +883,137 @@
 		{
 			return -EINTR;
 		}
+		save_flags(flags);
+		cli();	
+		start = (unsigned char*)port->readp; /* cast away volatile */
+		end = (unsigned char*)port->writep;  /* cast away volatile */
+		restore_flags(flags);
 	}
-	
-	/* Save pointers to avoid that they are modified by interrupt */
-	start = port->readp;
-	end = port->writep;
 
 	/* Lazy read, never return wrapped data. */
 	if (end > start)
 		avail = end - start;
 	else 
-		avail = port->in_buffer + IN_BUFFER_SIZE - start;
+		avail = port->in_buffer + port->in_buffer_size - start;
   
 	count = count > avail ? avail : count;
-	copy_to_user(buf, start, count);
+	if (copy_to_user(buf, start, count))
+		return -EFAULT;
 
 	/* Disable interrupts while updating readp */
 	save_flags(flags);
 	cli();	
 	port->readp += count;
-	if (port->readp == port->in_buffer + IN_BUFFER_SIZE) /* Wrap? */
+	if (port->readp >= port->in_buffer + port->in_buffer_size) /* Wrap? */
 		port->readp = port->in_buffer;
 	restore_flags(flags);
-
-	DEBUG(printk("%d bytes read\n", count));
+	DEBUGREAD(printk("r %d\n", count));
 	return count;
 }
 
 static void send_word(sync_port* port)
 {
-	switch(port->ctrl_data_shadow & IO_MASK(R_SYNC_SERIAL1_CTRL, wordsize))
+	switch(IO_EXTRACT(R_SYNC_SERIAL1_CTRL, wordsize, port->ctrl_data_shadow))
 	{
-		case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit):
-			port->out_count--;
-			*port->data_out = *port->outp++;
-			break;
-		case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit):
-			{
-				int data = (*port->outp++) << 8;
-				data |= *port->outp++;
-				port->out_count-=2;  
-				*port->data_out = data;
-			}
-			break;
-		case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit):
-			port->out_count-=2;
-			*port->data_out = *(unsigned short *)port->outp;
-			port->outp+=2;
-			break;
-		case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit):
-			port->out_count-=3;
-			*port->data_out = *(unsigned int *)port->outp;
-			port->outp+=3;
-			break;
-		case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit):
-			port->out_count-=4;
-			*port->data_out = *(unsigned int *)port->outp;
-			port->outp+=4;
-			break;
+	 case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit):
+		 port->out_count--;
+		 *port->data_out = *port->outp++;
+		 if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
+			 port->outp = port->out_buffer;
+		 break;
+	case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit):
+	{
+		int data = (*port->outp++) << 8;
+		data |= *port->outp++;
+		port->out_count-=2;  
+		*port->data_out = data;
+		if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
+			port->outp = port->out_buffer;
+	}
+	break;
+	case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit):
+		port->out_count-=2;
+		*port->data_out = *(unsigned short *)port->outp;
+		port->outp+=2;
+		if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
+			port->outp = port->out_buffer;
+		break;
+	case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit):
+		port->out_count-=3;
+		*port->data_out = *(unsigned int *)port->outp;
+		port->outp+=3;
+		if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
+			port->outp = port->out_buffer;
+		break;
+	case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit):
+		port->out_count-=4;
+		*port->data_out = *(unsigned int *)port->outp;
+		port->outp+=4;
+		if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
+			port->outp = port->out_buffer;
+		break;
 	}
 }
 
+
 static void start_dma(struct sync_port* port, const char* data, int count)
 {
+	port->tr_running = 1;
 	port->out_descr.hw_len = 0;
 	port->out_descr.next = 0;
-	port->out_descr.ctrl = d_eol | d_eop | d_wait;
+	port->out_descr.ctrl = d_eol | d_eop; /* No d_wait to avoid glitches */
 	port->out_descr.sw_len = count;
-	port->out_descr.buf = virt_to_phys(port->out_buffer);
+	port->out_descr.buf = virt_to_phys((char*)data);
 	port->out_descr.status = 0;
 
 	*port->output_dma_first = virt_to_phys(&port->out_descr);
 	*port->output_dma_cmd = IO_STATE(R_DMA_CH0_CMD, cmd, start);
+	DEBUGTXINT(printk("dma %08lX c %d\n", (unsigned long)data, count));
 }
 
 static void start_dma_in(sync_port* port)
 {
-	if (port->writep > port->in_buffer + IN_BUFFER_SIZE)
+	int i;
+	unsigned long buf;
+	port->cur_in_descr = 0;
+	port->writep = port->in_buffer;
+	
+	if (port->writep > port->in_buffer + port->in_buffer_size)
 	{
 		panic("Offset too large in sync serial driver\n");
 		return;
 	}
-	port->in_descr1.hw_len = 0;
-	port->in_descr1.ctrl = d_int;
-	port->in_descr1.status = 0;
-	port->in_descr1.next = virt_to_phys(&port->in_descr2);
-	port->in_descr2.hw_len = 0;
-	port->in_descr2.next = virt_to_phys(&port->in_descr1);
-	port->in_descr2.ctrl = d_int;
-	port->in_descr2.status = 0;
-
-	/* Find out which descriptor to start */
-	if (port->writep >= port->in_buffer + IN_BUFFER_SIZE/2)
-	{
-		/* Start descriptor 2 */
-		port->in_descr1.sw_len = IN_BUFFER_SIZE/2; /* All data available in 1 */
-		port->in_descr1.buf = virt_to_phys(port->in_buffer);
-		port->in_descr2.sw_len = port->in_buffer + IN_BUFFER_SIZE - port->writep;
-		port->in_descr2.buf = virt_to_phys(port->writep);
-		*port->input_dma_first = virt_to_phys(&port->in_descr2);
-	}
-	else
-	{
-		/* Start descriptor 1 */
-		port->in_descr1.sw_len = port->in_buffer + IN_BUFFER_SIZE/2 - port->writep;
-		port->in_descr1.buf = virt_to_phys(port->writep);
-		port->in_descr2.sw_len = IN_BUFFER_SIZE/2;
-		port->in_descr2.buf = virt_to_phys(port->in_buffer + IN_BUFFER_SIZE / 2);
-		*port->input_dma_first = virt_to_phys(&port->in_descr1);
-	}
+	buf = virt_to_phys(port->in_buffer);
+	for (i = 0; i < NUM_IN_DESCR; i++) {
+		port->in_descr[i].sw_len = port->inbufchunk;
+		port->in_descr[i].ctrl = d_int;
+		port->in_descr[i].next = virt_to_phys(&port->in_descr[i+1]);
+		port->in_descr[i].buf = buf;
+		port->in_descr[i].hw_len = 0;
+		port->in_descr[i].status = 0;
+		port->in_descr[i].fifo_len = 0;
+		buf += port->inbufchunk;
+		prepare_rx_descriptor(&port->in_descr[i]);
+	}
+	/* Link the last descriptor to the first */
+	port->in_descr[i-1].next = virt_to_phys(&port->in_descr[0]);
+	*port->input_dma_first = virt_to_phys(&port->in_descr[(int)port->cur_in_descr]);
 	*port->input_dma_cmd = IO_STATE(R_DMA_CH0_CMD, cmd, start);
 }
 
+#ifdef SYNC_SER_DMA
 static void tr_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	unsigned long ireg = *R_IRQ_MASK2_RD;
 	int i;
+	struct etrax_dma_descr *descr;
+	unsigned int sentl;
+	
 
 	for (i = 0; i < NUMBER_OF_PORTS; i++) 
 	{
 		sync_port *port = &ports[i];
-		if (!port->enabled)
+		if (!port->enabled  || !port->use_dma )
 			continue;
 
 		if (ireg & (1 << port->output_dma_bit)) /* IRQ active for the port? */
@@ -782,54 +1022,89 @@
 			*port->output_dma_clr_irq = 
 			  IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do) |
 			  IO_STATE(R_DMA_CH0_CLR_INTR, clr_descr, do);
+
+			descr = &port->out_descr;
+			if (!(descr->status & d_stop)) {
+				sentl = descr->sw_len;
+			} else 
+				/* otherwise we find the amount of data sent here */
+				sentl = descr->hw_len;
+			port->out_count -= sentl;
+			port->outp += sentl;
+			if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
+				port->outp = port->out_buffer;
+			if (port->out_count)  {
+				int c;
+				c = port->out_buffer + OUT_BUFFER_SIZE - port->outp;
+				if (c > port->out_count)
+					c = port->out_count;
+				DEBUGTXINT(printk("tx_int DMAWRITE %i %i\n", sentl, c));
+				start_dma(port, port->outp, c);
+			} else  {
+				DEBUGTXINT(printk("tx_int DMA stop %i\n", sentl));				
+				port->tr_running = 0;
+			}
 			wake_up_interruptible(&port->out_wait_q); /* wake up the waiting process */
 		} 
 	}
-}
+} /* tr_interrupt */
 
 static void rx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	unsigned long ireg = *R_IRQ_MASK2_RD;
-	int i;	
+	int i;
 
 	for (i = 0; i < NUMBER_OF_PORTS; i++) 
 	{
 		sync_port *port = &ports[i];
 
-		if (!port->enabled)
+		if (!port->enabled || !port->use_dma )
 			continue;
 
 		if (ireg & (1 << port->input_dma_descr_bit)) /* Descriptor interrupt */
 		{
+			struct etrax_dma_descr *descr;
+			unsigned recvl;
+			unsigned long oldbuf, buf;
+
 			/* DMA has reached end of descriptor */
 			*port->input_dma_clr_irq = 
 			  IO_STATE(R_DMA_CH0_CLR_INTR, clr_descr, do);
-
-			/* Find out which descriptor that is ready */
-			if (port->writep >= port->in_buffer + IN_BUFFER_SIZE/2) 
-			{
-				/* Descr 2 was ready. Restart DMA at descriptor 1 */
-				port->writep = port->in_buffer;
-	
-				/* Throw away data? */
-				if (port->readp < port->in_buffer + IN_BUFFER_SIZE/2)
-					port->readp = port->in_buffer + IN_BUFFER_SIZE/2;
-			}
-			else
-			{
-				/* Descr 1 was ready. Restart DMA at descriptor 2 */
-				port->writep = port->in_buffer + IN_BUFFER_SIZE/2;
-
-				/* Throw away data? */
-				if (port->readp >= port->in_buffer + IN_BUFFER_SIZE/2)
-					port->readp = port->in_buffer;
+			
+			descr = &port->in_descr[(int)port->cur_in_descr];
+			if (descr == phys_to_virt(*port->input_dma_descr)) 
+				printk("sser: desc = *input_dma_descr\n");
+
+			if (!(descr->status & d_eop)) {
+				recvl = descr->sw_len;
+			} else {
+				/* otherwise we find the amount of data received here */
+				recvl = descr->hw_len;
 			}
-			start_dma_in(port);
+			port->writep += recvl;
+			if (port->writep >= port->in_buffer+ port->in_buffer_size)
+				port->writep = port->in_buffer;
+			descr->sw_len = port->inbufchunk;
+			/* Reset the status information */
+			descr->status = 0;
+			/* Change the buf pointer to new position */
+			oldbuf = descr->buf;
+			
+			descr->buf += NUM_IN_DESCR * port->inbufchunk;
+			buf = virt_to_phys(port->in_buffer);
+			if (descr->buf >= buf + port->in_buffer_size)
+				descr->buf -= port->in_buffer_size;
+			DEBUGRXINT(printk("rx_int descr %i %X recvl: %i writep %lu obuf %lu %08lX buf 0x%08lX\n", port->cur_in_descr, (unsigned long) (*port->input_dma_descr), recvl, (unsigned long)(port->writep - port->in_buffer), oldbuf, oldbuf, (unsigned long)descr->buf));
+			if (++port->cur_in_descr == NUM_IN_DESCR)
+				port->cur_in_descr = 0;
+				
 			wake_up_interruptible(&port->in_wait_q); /* wake up the waiting process */
 		}
 	}
-}
+} /* rx_interrupt */
+#endif /* SYNC_SER_DMA */
 
+#ifdef SYNC_SER_MANUAL
 static void manual_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	int i;
@@ -838,7 +1113,7 @@
 	{
 		sync_port* port = &ports[i];
 
-		if (!port->enabled)
+		if (!port->enabled || port->use_dma)
 		{
 			continue;
 		}
@@ -848,34 +1123,42 @@
 			/* Read data */
 			switch(port->ctrl_data_shadow & IO_MASK(R_SYNC_SERIAL1_CTRL, wordsize))
 			{
-				case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit):
-					*port->writep++ = *(volatile char *)port->data_in;
-					break;
-				case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit):
-				{
-					int data = *(unsigned short *)port->data_in;
-					*port->writep = (data & 0x0ff0) >> 4;
-					*(port->writep + 1) = data & 0x0f;
-					port->writep+=2;
-				}
+			case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit):
+				*port->writep++ = *(volatile char *)port->data_in;
+				break;
+			case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit):
+			{
+				int data = *(unsigned short *)port->data_in;
+				*port->writep = (data & 0x0ff0) >> 4;
+				*(port->writep + 1) = data & 0x0f;
+				port->writep+=2;
+			}
+			break;
+			case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit):
+				*(unsigned short*)port->writep = *(volatile unsigned short *)port->data_in;
+				port->writep+=2;
+				break;
+			case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit):
+				*(unsigned int*)port->writep = *port->data_in;
+				port->writep+=3;
+				break;
+			case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit):
+				*(unsigned int*)port->writep = *port->data_in;
+				port->writep+=4;
 				break;
-				case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit):
-					*(unsigned short*)port->writep = *(volatile unsigned short *)port->data_in;
-					port->writep+=2;
-					break;
-				case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit):
-					*(unsigned int*)port->writep = *port->data_in;
-					port->writep+=3;
-					break;
-				case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit):
-					*(unsigned int*)port->writep = *port->data_in;
-					port->writep+=4;
-					break;
 			}
 
-			if (port->writep >= port->in_buffer + IN_BUFFER_SIZE) /* Wrap? */
+			if (port->writep >= port->in_buffer + port->in_buffer_size) /* Wrap? */
 				port->writep = port->in_buffer;
-			wake_up_interruptible(&port->in_wait_q); /* Wake up application */
+			if (port->writep == port->readp) {
+				/* receive buffer overrun, discard oldest data
+				 */
+				port->readp++;
+				if (port->readp >= port->in_buffer + port->in_buffer_size) /* Wrap? */
+					port->readp = port->in_buffer;
+			}
+			if (sync_data_avail(port) >= port->inbufchunk)
+				wake_up_interruptible(&port->in_wait_q); /* Wake up application */
 		}
 
 		if (*R_IRQ_MASK1_RD & (1 << port->transmitter_ready_bit)) /* Transmitter ready? */
@@ -884,11 +1167,12 @@
 				send_word(port);
 			else /* transmission finished */
 			{
-				*R_IRQ_MASK1_CLR = 1 << port->ready_irq_bit; /* Turn off IRQ */
+				*R_IRQ_MASK1_CLR = 1 << port->transmitter_ready_bit; /* Turn off IRQ */
 				wake_up_interruptible(&port->out_wait_q); /* Wake up application */
 			}
 		}
 	}
 }
+#endif
 
 module_init(etrax_sync_serial_init);
diff -urN linux-2.4.23-bk3/arch/cris/drivers/usb-host.c linux-2.4.23-bk4/arch/cris/drivers/usb-host.c
--- linux-2.4.23-bk3/arch/cris/drivers/usb-host.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-bk4/arch/cris/drivers/usb-host.c	2003-12-06 02:49:48.000000000 -0800
@@ -41,7 +41,7 @@
 #define ETRAX_USB_RX_IRQ USB_DMA_RX_IRQ_NBR
 #define ETRAX_USB_TX_IRQ USB_DMA_TX_IRQ_NBR
 
-static const char *usb_hcd_version = "$Revision: 1.18 $";
+static const char *usb_hcd_version = "$Revision: 1.19 $";
 
 #undef KERN_DEBUG
 #define KERN_DEBUG ""
@@ -1540,9 +1540,18 @@
                    ctrl pipes are not. */
                 
 		if (myNextRxDesc->status & IO_MASK(USB_IN_status, error)) {
+			__u32 r_usb_ept_data;
+
 			warn("error in rx desc->status, epid %d, first urb = 0x%lx", 
                              epid, (unsigned long)urb);
 			__dump_in_desc(myNextRxDesc);
+
+                        *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); 
+                        nop();
+                        r_usb_ept_data = *R_USB_EPT_DATA;
+			warn("R_USB_EPT_DATA for epid %d = 0x%x", epid, r_usb_ept_data);
+			warn("R_USB_STATUS = 0x%x", *R_USB_STATUS);
+
                         etrax_usb_complete_urb(urb, -EPROTO);
 			goto skip_out;
 		}
diff -urN linux-2.4.23-bk3/arch/cris/kernel/debug.c linux-2.4.23-bk4/arch/cris/kernel/debug.c
--- linux-2.4.23-bk3/arch/cris/kernel/debug.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-bk4/arch/cris/kernel/debug.c	2003-12-06 02:49:48.000000000 -0800
@@ -2,7 +2,7 @@
  * arch/cris/kernel/debug.c
  * Various debug routines:
  * o Logging of interrupt enabling/disabling. /proc/debug_interrupt
- *   gives result and toggles if it is enabled or not.
+ *   gives result and enables logging when read.
  *
  * Copyright (C) 2003 Axis Communications AB
  */
@@ -24,7 +24,7 @@
 int log_int_trig0_pos = 0;
 int log_int_trig1_pos = 0;
 
-int log_int_enable = 0; /* toggled every read of /proc/debug_interrupt */
+int log_int_enable = 0; /* Enabled every read of /proc/debug_interrupt */
 
 struct log_int_struct 
 {
diff -urN linux-2.4.23-bk3/arch/cris/kernel/hexify.c linux-2.4.23-bk4/arch/cris/kernel/hexify.c
--- linux-2.4.23-bk3/arch/cris/kernel/hexify.c	2001-02-08 16:32:44.000000000 -0800
+++ linux-2.4.23-bk4/arch/cris/kernel/hexify.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,31 +0,0 @@
-#include <stdio.h>
-
-
-void main()
-{
-	int c;
-	int comma=0;
-	int count=0;
-	while((c=getchar())!=EOF)
-	{
-		unsigned char x=c;
-		if(comma)
-			printf(",");
-		else
-			comma=1;
-		if(count==8)
-		{
-			count=0;
-			printf("\n");
-		}
-		if(count==0)
-			printf("\t");
-		printf("0x%02X",c);
-		count++;
-	}
-	if(count)
-		printf("\n");
-	exit(0);
-}
-
-		
diff -urN linux-2.4.23-bk3/arch/cris/kernel/ksyms.c linux-2.4.23-bk4/arch/cris/kernel/ksyms.c
--- linux-2.4.23-bk3/arch/cris/kernel/ksyms.c	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.23-bk4/arch/cris/kernel/ksyms.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,90 +0,0 @@
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-#include <linux/sched.h>
-#include <linux/in6.h>
-#include <linux/interrupt.h>
-#include <linux/smp_lock.h>
-#include <linux/pm.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/tty.h>
- 
-#include <asm/semaphore.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/checksum.h>
-#include <asm/io.h>
-#include <asm/hardirq.h>
-#include <asm/delay.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-
-extern void dump_thread(struct pt_regs *, struct user *);
-extern unsigned long get_cmos_time(void);
-extern void __Udiv(void);
-extern void __Umod(void);
-extern void __ashrdi3(void);
-extern void iounmap(void *addr);
-
-/* Platform dependent support */
-EXPORT_SYMBOL(dump_thread);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
-EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(get_cmos_time);
-EXPORT_SYMBOL(loops_per_usec);
-
-/* String functions */
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strtok);
-EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strncpy);
-
-/* Math functions */
-EXPORT_SYMBOL(__Udiv);
-EXPORT_SYMBOL(__Umod);
-EXPORT_SYMBOL(__ashrdi3);
-
-/* Memory functions */
-EXPORT_SYMBOL(__ioremap);
-EXPORT_SYMBOL(iounmap);
-
-/* Semaphore functions */
-EXPORT_SYMBOL(__up);
-EXPORT_SYMBOL(__down);
-
-/* Export shadow registers for the CPU I/O pins */
-EXPORT_SYMBOL(genconfig_shadow);
-EXPORT_SYMBOL(port_pa_data_shadow);
-EXPORT_SYMBOL(port_pa_dir_shadow);
-EXPORT_SYMBOL(port_pb_data_shadow);
-EXPORT_SYMBOL(port_pb_dir_shadow);
-EXPORT_SYMBOL(port_pb_config_shadow);
-EXPORT_SYMBOL(port_g_data_shadow);
-
-/* Userspace access functions */
-EXPORT_SYMBOL(__copy_user_zeroing);
-EXPORT_SYMBOL(__copy_user);
-
-/* Cache flush functions */
-EXPORT_SYMBOL(flush_etrax_cache);
-EXPORT_SYMBOL(prepare_rx_descriptor);
-
-#undef memcpy
-#undef memset
-extern void * memset(void *, int, __kernel_size_t);
-extern void * memcpy(void *, const void *, __kernel_size_t);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-
-
diff -urN linux-2.4.23-bk3/arch/cris/kernel/ptrace.c linux-2.4.23-bk4/arch/cris/kernel/ptrace.c
--- linux-2.4.23-bk3/arch/cris/kernel/ptrace.c	2002-02-25 11:37:52.000000000 -0800
+++ linux-2.4.23-bk4/arch/cris/kernel/ptrace.c	2003-12-06 02:49:48.000000000 -0800
@@ -8,6 +8,10 @@
  * Authors:   Bjorn Wesen
  *
  * $Log: ptrace.c,v $
+ * Revision 1.9  2003/10/01 11:34:23  aurer
+ * * Allow PTRACE_PEEKUSR and PTRACE_POKEUSR to access USP.
+ * * Removed nonsensical comment about ptrace behavior.
+ *
  * Revision 1.8  2001/11/12 18:26:21  pkj
  * Fixed compiler warnings.
  *
@@ -96,14 +100,6 @@
        /* Todo - pending singlesteps? */
 }
 
-/* Note that this implementation of ptrace behaves differently from vanilla
- * ptrace.  Contrary to what the man page says, in the PTRACE_PEEKTEXT,
- * PTRACE_PEEKDATA, and PTRACE_PEEKUSER requests the data variable is not
- * ignored.  Instead, the data variable is expected to point at a location
- * (in user space) where the result of the ptrace call is written (instead of
- * being returned).
- */
-
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
@@ -163,17 +159,13 @@
 		/* read the word at location addr in the USER area. */
 		case PTRACE_PEEKUSR: {
 			unsigned long tmp;
-			
+
 			ret = -EIO;
-			if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
+			if ((addr & 3) || addr < 0 || addr > PT_MAX << 2)
 				break;
-			
-			tmp = 0;  /* Default return condition */
-			ret = -EIO;
-			if (addr < sizeof(struct pt_regs)) {
-				tmp = get_reg(child, addr >> 2);
-				ret = put_user(tmp, (unsigned long *)data);
-			}
+
+			tmp = get_reg(child, addr >> 2);
+			ret = put_user(tmp, (unsigned long *)data);
 			break;
 		}
 
@@ -188,23 +180,21 @@
 
 		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
 			ret = -EIO;
-			if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
+			if ((addr & 3) || addr < 0 || addr > PT_MAX << 2)
 				break;
 
-			if (addr < sizeof(struct pt_regs)) {
-				addr >>= 2;
+			addr >>= 2;
 
-				if (addr == PT_DCCR) {
+			if (addr == PT_DCCR) {
 				/* don't allow the tracing process to change stuff like
 				 * interrupt enable, kernel/user bit, dma enables etc.
 				 */
-					data &= DCCR_MASK;
-					data |= get_reg(child, PT_DCCR) & ~DCCR_MASK;
-				}
-				if (put_reg(child, addr, data))
-					break;
-				ret = 0;
+				data &= DCCR_MASK;
+				data |= get_reg(child, PT_DCCR) & ~DCCR_MASK;
 			}
+			if (put_reg(child, addr, data))
+				break;
+			ret = 0;
 			break;
 
 		case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
diff -urN linux-2.4.23-bk3/arch/cris/kernel/sys_cris.c linux-2.4.23-bk4/arch/cris/kernel/sys_cris.c
--- linux-2.4.23-bk3/arch/cris/kernel/sys_cris.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-bk4/arch/cris/kernel/sys_cris.c	2003-12-06 02:49:48.000000000 -0800
@@ -109,7 +109,10 @@
 
 	switch (call) {
 	case SEMOP:
-		return sys_semop (first, (struct sembuf *)ptr, second);
+		return sys_semtimedop (first, (struct sembuf *)ptr, second, NULL);
+	case SEMTIMEDOP:
+		return sys_semtimedop (first, (struct sembuf *)ptr, second,
+				       (const struct timespec *)fifth);
 	case SEMGET:
 		return sys_semget (first, second, third);
 	case SEMCTL: {
@@ -163,7 +166,7 @@
 		return sys_shmctl (first, second,
 				   (struct shmid_ds *) ptr);
 	default:
-		return -EINVAL;
+		return -ENOSYS;
 	}
 }
 
diff -urN linux-2.4.23-bk3/arch/cris/kernel/time.c linux-2.4.23-bk4/arch/cris/kernel/time.c
--- linux-2.4.23-bk3/arch/cris/kernel/time.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-bk4/arch/cris/kernel/time.c	2003-12-06 02:49:48.000000000 -0800
@@ -328,7 +328,7 @@
 	int retval = 0;
 	int real_seconds, real_minutes, cmos_minutes;
 
-	printk(KERN_INFO "set_rtc_mmss(%lu)\n", nowtime);
+	printk(KERN_DEBUG "set_rtc_mmss(%lu)\n", nowtime);
 
 	if(!have_rtc)
 		return 0;
@@ -514,7 +514,7 @@
 	mon = CMOS_READ(RTC_MONTH);
 	year = CMOS_READ(RTC_YEAR);
 
-	printk(KERN_INFO
+	printk(KERN_DEBUG
 	       "rtc: sec 0x%x min 0x%x hour 0x%x day 0x%x mon 0x%x year 0x%x\n", 
 	       sec, min, hour, day, mon, year);
 
diff -urN linux-2.4.23-bk3/arch/cris/lib/dram_init.S linux-2.4.23-bk4/arch/cris/lib/dram_init.S
--- linux-2.4.23-bk3/arch/cris/lib/dram_init.S	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-bk4/arch/cris/lib/dram_init.S	2003-12-06 02:49:48.000000000 -0800
@@ -1,4 +1,4 @@
-/* $Id: dram_init.S,v 1.14 2003/03/31 07:07:08 starvik Exp $
+/* $Id: dram_init.S,v 1.15 2003/09/22 09:22:22 starvik Exp $
  * 
  * DRAM/SDRAM initialization - alter with care
  * This file is intended to be included from other assembler files
@@ -11,6 +11,10 @@
  * Authors:  Mikael Starvik (starvik@axis.com)	
  * 
  * $Log: dram_init.S,v $
+ * Revision 1.15  2003/09/22 09:22:22  starvik
+ * Decompresser is linked to 0x407xxxxx and sdram commands are at 0x000xxxxx
+ * so we need to mask off 12 bits.
+ *
  * Revision 1.14  2003/03/31 07:07:08  starvik
  * Corrected calculation of end of sdram init commands
  *
@@ -149,9 +153,9 @@
 	
 	; Issue initialization command sequence
 	move.d   _sdram_commands_start, $r2
-	and.d    0x00ffffff, $r2 ; Make sure commands are read from flash
+	and.d    0x000fffff, $r2 ; Make sure commands are read from flash
 	move.d   _sdram_commands_end,  $r3
-	and.d    0x00ffffff, $r3
+	and.d    0x000fffff, $r3
 1:	clear.d  $r4
 	move.b   [$r2+], $r4
 	lslq     9, $r4	; Command starts at bit 9
diff -urN linux-2.4.23-bk3/arch/cris/mm/fault.c linux-2.4.23-bk4/arch/cris/mm/fault.c
--- linux-2.4.23-bk3/arch/cris/mm/fault.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-bk4/arch/cris/mm/fault.c	2003-12-06 02:49:48.000000000 -0800
@@ -6,6 +6,9 @@
  *  Authors:  Bjorn Wesen 
  * 
  *  $Log: fault.c,v $
+ *  Revision 1.23  2003/10/16 05:32:32  starvik
+ *  Only read TLB_SELECT if DEBUG
+ *
  *  Revision 1.22  2003/07/07 09:07:04  johana
  *  Added special CONFIG_ETRAX_DEBUG_INTERRUPT handling here
  *  to deal with a di in entry.S
@@ -119,8 +122,9 @@
 void
 handle_mmu_bus_fault(struct pt_regs *regs)
 {
-	int cause, select;
+	int cause;
 #ifdef DEBUG
+	int select;
 	int index;
 	int page_id;
 	int acc, inv;
@@ -135,11 +139,11 @@
 	log_int(rdpc(), regs->dccr, 0);
 #endif
 	cause = *R_MMU_CAUSE;
-	select = *R_TLB_SELECT;
 
 	address = cause & PAGE_MASK; /* get faulting address */
 
 #ifdef DEBUG
+	select = *R_TLB_SELECT;
 	page_id = IO_EXTRACT(R_MMU_CAUSE,  page_id,   cause);
 	acc     = IO_EXTRACT(R_MMU_CAUSE,  acc_excp,  cause);
 	inv     = IO_EXTRACT(R_MMU_CAUSE,  inv_excp,  cause);  
diff -urN linux-2.4.23-bk3/arch/ia64/config.in linux-2.4.23-bk4/arch/ia64/config.in
--- linux-2.4.23-bk3/arch/ia64/config.in	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/config.in	2003-12-06 02:49:48.000000000 -0800
@@ -34,7 +34,7 @@
 	"generic		CONFIG_IA64_GENERIC		\
 	 DIG-compliant		CONFIG_IA64_DIG			\
 	 HP-simulator		CONFIG_IA64_HP_SIM		\
-	 HP-zx1			CONFIG_IA64_HP_ZX1		\
+	 HP			CONFIG_IA64_HP_ZX1		\
 	 SGI-SN2		CONFIG_IA64_SGI_SN2" generic
 
 if [ "$CONFIG_ITANIUM" = "y" ]; then
@@ -90,7 +90,7 @@
    int  'Maximum number of CPUs (2-32)' CONFIG_NR_CPUS 32
 fi
 
-tristate 'Support running of Linux/x86 binaries' CONFIG_IA32_SUPPORT
+bool 'Support running of Linux/x86 binaries' CONFIG_IA32_SUPPORT
 bool 'Performance monitor support' CONFIG_PERFMON
 tristate '/proc/pal support' CONFIG_IA64_PALINFO
 tristate '/proc/efi/vars support' CONFIG_EFI_VARS
diff -urN linux-2.4.23-bk3/arch/ia64/configs/dig linux-2.4.23-bk4/arch/ia64/configs/dig
--- linux-2.4.23-bk3/arch/ia64/configs/dig	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/configs/dig	2003-12-06 02:49:48.000000000 -0800
@@ -30,7 +30,6 @@
 CONFIG_IA64_DIG=y
 # CONFIG_IA64_HP_SIM is not set
 # CONFIG_IA64_HP_ZX1 is not set
-# CONFIG_IA64_SGI_SN1 is not set
 # CONFIG_IA64_SGI_SN2 is not set
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
@@ -43,7 +42,6 @@
 CONFIG_PM=y
 CONFIG_KCORE_ELF=y
 CONFIG_FORCE_MAX_ZONEORDER=19
-CONFIG_HUGETLB_PAGE=y
 # CONFIG_HUGETLB_PAGE_SIZE_256MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
 CONFIG_HUGETLB_PAGE_SIZE_16MB=y
@@ -52,6 +50,7 @@
 # CONFIG_HUGETLB_PAGE_SIZE_256KB is not set
 # CONFIG_IA64_PAL_IDLE is not set
 CONFIG_SMP=y
+CONFIG_NR_CPUS=32
 CONFIG_IA32_SUPPORT=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
@@ -113,6 +112,12 @@
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
 
@@ -167,6 +172,7 @@
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
 CONFIG_BLK_DEV_LOOP=y
@@ -339,6 +345,7 @@
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_MEGARAID2 is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
@@ -366,7 +373,6 @@
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=y
-# CONFIG_SCSI_QLOGIC_QLA2100 is not set
 # CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_DC390T is not set
@@ -438,7 +444,6 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_SUNDANCE_MMIO is not set
 # CONFIG_TLAN is not set
-# CONFIG_TC35815 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_VIA_RHINE_MMIO is not set
 # CONFIG_WINBOND_840 is not set
@@ -584,6 +589,7 @@
 # CONFIG_WATCHDOG is not set
 # CONFIG_SCx200_GPIO is not set
 # CONFIG_INTEL_RNG is not set
+# CONFIG_HW_RANDOM is not set
 # CONFIG_AMD_PM768 is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
@@ -601,12 +607,17 @@
 # CONFIG_AGP_I810 is not set
 # CONFIG_AGP_VIA is not set
 # CONFIG_AGP_AMD is not set
-# CONFIG_AGP_AMD_8151 is not set
+# CONFIG_AGP_AMD_K8 is not set
 # CONFIG_AGP_SIS is not set
 # CONFIG_AGP_ALI is not set
 # CONFIG_AGP_SWORKS is not set
 CONFIG_AGP_I460=y
 CONFIG_AGP_HP_ZX1=y
+# CONFIG_AGP_ATI is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
 CONFIG_DRM=y
 # CONFIG_DRM_OLD is not set
 
@@ -615,6 +626,7 @@
 #
 CONFIG_DRM_NEW=y
 # CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_GAMMA is not set
 CONFIG_DRM_R128=y
 CONFIG_DRM_RADEON=y
 # CONFIG_DRM_I810 is not set
@@ -690,6 +702,7 @@
 # CONFIG_TMPFS is not set
 CONFIG_RAMFS=y
 CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
@@ -844,6 +857,8 @@
 # CONFIG_MIDI_VIA82CXXX is not set
 # CONFIG_SOUND_OSS is not set
 # CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+# CONFIG_SOUND_WM97XX is not set
 
 #
 # USB support
@@ -914,6 +929,7 @@
 # CONFIG_USB_PWC is not set
 # CONFIG_USB_SE401 is not set
 # CONFIG_USB_STV680 is not set
+# CONFIG_USB_W9968CF is not set
 # CONFIG_USB_VICAM is not set
 # CONFIG_USB_DSBR is not set
 # CONFIG_USB_DABUSB is not set
@@ -949,6 +965,11 @@
 # CONFIG_USB_LCD is not set
 
 #
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
 # Cryptographic options
 #
 # CONFIG_CRYPTO is not set
@@ -971,3 +992,4 @@
 CONFIG_IA64_GRANULE_16MB=y
 # CONFIG_IA64_GRANULE_64MB is not set
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=0
diff -urN linux-2.4.23-bk3/arch/ia64/configs/generic linux-2.4.23-bk4/arch/ia64/configs/generic
--- linux-2.4.23-bk3/arch/ia64/configs/generic	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/configs/generic	2003-12-06 02:49:48.000000000 -0800
@@ -30,7 +30,6 @@
 # CONFIG_IA64_DIG is not set
 # CONFIG_IA64_HP_SIM is not set
 # CONFIG_IA64_HP_ZX1 is not set
-# CONFIG_IA64_SGI_SN1 is not set
 # CONFIG_IA64_SGI_SN2 is not set
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
@@ -43,7 +42,6 @@
 CONFIG_PM=y
 CONFIG_KCORE_ELF=y
 CONFIG_FORCE_MAX_ZONEORDER=19
-CONFIG_HUGETLB_PAGE=y
 # CONFIG_HUGETLB_PAGE_SIZE_256MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
 CONFIG_HUGETLB_PAGE_SIZE_16MB=y
@@ -52,6 +50,7 @@
 # CONFIG_HUGETLB_PAGE_SIZE_256KB is not set
 # CONFIG_IA64_PAL_IDLE is not set
 CONFIG_SMP=y
+CONFIG_NR_CPUS=32
 CONFIG_IA32_SUPPORT=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
@@ -113,6 +112,12 @@
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
 
@@ -167,6 +172,7 @@
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
 CONFIG_BLK_DEV_LOOP=y
@@ -275,6 +281,7 @@
 # CONFIG_BLK_DEV_RZ1000 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SGIIOC4 is not set
 # CONFIG_BLK_DEV_SIIMAGE is not set
 # CONFIG_BLK_DEV_SIS5513 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
@@ -339,6 +346,7 @@
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_MEGARAID2 is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
@@ -371,7 +379,6 @@
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=y
-# CONFIG_SCSI_QLOGIC_QLA2100 is not set
 # CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_DC390T is not set
@@ -443,7 +450,6 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_SUNDANCE_MMIO is not set
 # CONFIG_TLAN is not set
-# CONFIG_TC35815 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_VIA_RHINE_MMIO is not set
 # CONFIG_WINBOND_840 is not set
@@ -588,7 +594,9 @@
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_SCx200_GPIO is not set
+# CONFIG_FETCHOP is not set
 # CONFIG_INTEL_RNG is not set
+# CONFIG_HW_RANDOM is not set
 # CONFIG_AMD_PM768 is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
@@ -606,12 +614,17 @@
 # CONFIG_AGP_I810 is not set
 # CONFIG_AGP_VIA is not set
 # CONFIG_AGP_AMD is not set
-# CONFIG_AGP_AMD_8151 is not set
+# CONFIG_AGP_AMD_K8 is not set
 # CONFIG_AGP_SIS is not set
 # CONFIG_AGP_ALI is not set
 # CONFIG_AGP_SWORKS is not set
 CONFIG_AGP_I460=y
 CONFIG_AGP_HP_ZX1=y
+# CONFIG_AGP_ATI is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
 CONFIG_DRM=y
 # CONFIG_DRM_OLD is not set
 
@@ -620,6 +633,7 @@
 #
 CONFIG_DRM_NEW=y
 # CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_GAMMA is not set
 CONFIG_DRM_R128=y
 CONFIG_DRM_RADEON=y
 # CONFIG_DRM_I810 is not set
@@ -695,6 +709,7 @@
 # CONFIG_TMPFS is not set
 CONFIG_RAMFS=y
 CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
@@ -849,6 +864,8 @@
 # CONFIG_MIDI_VIA82CXXX is not set
 # CONFIG_SOUND_OSS is not set
 # CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+# CONFIG_SOUND_WM97XX is not set
 
 #
 # USB support
@@ -919,6 +936,7 @@
 # CONFIG_USB_PWC is not set
 # CONFIG_USB_SE401 is not set
 # CONFIG_USB_STV680 is not set
+# CONFIG_USB_W9968CF is not set
 # CONFIG_USB_VICAM is not set
 # CONFIG_USB_DSBR is not set
 # CONFIG_USB_DABUSB is not set
@@ -954,6 +972,11 @@
 # CONFIG_USB_LCD is not set
 
 #
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
 # Cryptographic options
 #
 # CONFIG_CRYPTO is not set
@@ -994,3 +1017,4 @@
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_IA64_DEBUG_CMPXCHG is not set
 # CONFIG_IA64_DEBUG_IRQ is not set
+CONFIG_LOG_BUF_SHIFT=0
diff -urN linux-2.4.23-bk3/arch/ia64/configs/numa linux-2.4.23-bk4/arch/ia64/configs/numa
--- linux-2.4.23-bk3/arch/ia64/configs/numa	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/configs/numa	2003-12-06 02:49:48.000000000 -0800
@@ -30,7 +30,6 @@
 # CONFIG_IA64_DIG is not set
 # CONFIG_IA64_HP_SIM is not set
 # CONFIG_IA64_HP_ZX1 is not set
-# CONFIG_IA64_SGI_SN1 is not set
 # CONFIG_IA64_SGI_SN2 is not set
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
@@ -44,7 +43,6 @@
 CONFIG_PM=y
 CONFIG_KCORE_ELF=y
 CONFIG_FORCE_MAX_ZONEORDER=19
-CONFIG_HUGETLB_PAGE=y
 # CONFIG_HUGETLB_PAGE_SIZE_256MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
 CONFIG_HUGETLB_PAGE_SIZE_16MB=y
@@ -53,6 +51,7 @@
 # CONFIG_HUGETLB_PAGE_SIZE_256KB is not set
 CONFIG_IA64_PAL_IDLE=y
 CONFIG_SMP=y
+CONFIG_NR_CPUS=32
 CONFIG_IA32_SUPPORT=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
@@ -115,6 +114,12 @@
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
 
@@ -169,6 +174,7 @@
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
 CONFIG_BLK_DEV_LOOP=y
@@ -277,6 +283,7 @@
 # CONFIG_BLK_DEV_RZ1000 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SGIIOC4 is not set
 # CONFIG_BLK_DEV_SIIMAGE is not set
 # CONFIG_BLK_DEV_SIS5513 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
@@ -341,6 +348,7 @@
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_MEGARAID2 is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
@@ -373,7 +381,6 @@
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=y
-# CONFIG_SCSI_QLOGIC_QLA2100 is not set
 # CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_DC390T is not set
@@ -445,7 +452,6 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_SUNDANCE_MMIO is not set
 # CONFIG_TLAN is not set
-# CONFIG_TC35815 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_VIA_RHINE_MMIO is not set
 # CONFIG_WINBOND_840 is not set
@@ -590,7 +596,9 @@
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_SCx200_GPIO is not set
+# CONFIG_FETCHOP is not set
 # CONFIG_INTEL_RNG is not set
+# CONFIG_HW_RANDOM is not set
 # CONFIG_AMD_PM768 is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
@@ -608,12 +616,17 @@
 # CONFIG_AGP_I810 is not set
 # CONFIG_AGP_VIA is not set
 # CONFIG_AGP_AMD is not set
-# CONFIG_AGP_AMD_8151 is not set
+# CONFIG_AGP_AMD_K8 is not set
 # CONFIG_AGP_SIS is not set
 # CONFIG_AGP_ALI is not set
 # CONFIG_AGP_SWORKS is not set
 CONFIG_AGP_I460=y
 CONFIG_AGP_HP_ZX1=y
+# CONFIG_AGP_ATI is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
 CONFIG_DRM=y
 # CONFIG_DRM_OLD is not set
 
@@ -622,6 +635,7 @@
 #
 CONFIG_DRM_NEW=y
 # CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_GAMMA is not set
 CONFIG_DRM_R128=y
 CONFIG_DRM_RADEON=y
 # CONFIG_DRM_I810 is not set
@@ -697,6 +711,7 @@
 # CONFIG_TMPFS is not set
 CONFIG_RAMFS=y
 CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
@@ -851,6 +866,8 @@
 # CONFIG_MIDI_VIA82CXXX is not set
 # CONFIG_SOUND_OSS is not set
 # CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+# CONFIG_SOUND_WM97XX is not set
 
 #
 # USB support
@@ -921,6 +938,7 @@
 # CONFIG_USB_PWC is not set
 # CONFIG_USB_SE401 is not set
 # CONFIG_USB_STV680 is not set
+# CONFIG_USB_W9968CF is not set
 # CONFIG_USB_VICAM is not set
 # CONFIG_USB_DSBR is not set
 # CONFIG_USB_DABUSB is not set
@@ -956,6 +974,11 @@
 # CONFIG_USB_LCD is not set
 
 #
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
 # Cryptographic options
 #
 # CONFIG_CRYPTO is not set
@@ -996,3 +1019,4 @@
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_IA64_DEBUG_CMPXCHG is not set
 # CONFIG_IA64_DEBUG_IRQ is not set
+CONFIG_LOG_BUF_SHIFT=0
diff -urN linux-2.4.23-bk3/arch/ia64/configs/ski linux-2.4.23-bk4/arch/ia64/configs/ski
--- linux-2.4.23-bk3/arch/ia64/configs/ski	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/configs/ski	2003-12-06 02:49:48.000000000 -0800
@@ -30,7 +30,6 @@
 # CONFIG_IA64_DIG is not set
 CONFIG_IA64_HP_SIM=y
 # CONFIG_IA64_HP_ZX1 is not set
-# CONFIG_IA64_SGI_SN1 is not set
 # CONFIG_IA64_SGI_SN2 is not set
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
@@ -40,7 +39,6 @@
 CONFIG_IA64_L1_CACHE_SHIFT=6
 CONFIG_KCORE_ELF=y
 CONFIG_FORCE_MAX_ZONEORDER=19
-CONFIG_HUGETLB_PAGE=y
 # CONFIG_HUGETLB_PAGE_SIZE_256MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
 CONFIG_HUGETLB_PAGE_SIZE_16MB=y
@@ -49,6 +47,7 @@
 # CONFIG_HUGETLB_PAGE_SIZE_256KB is not set
 CONFIG_IA64_PAL_IDLE=y
 CONFIG_SMP=y
+CONFIG_NR_CPUS=32
 CONFIG_IA32_SUPPORT=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
@@ -80,6 +79,12 @@
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
 
@@ -161,6 +166,7 @@
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_MEGARAID2 is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
@@ -252,6 +258,7 @@
 # CONFIG_WATCHDOG is not set
 # CONFIG_SCx200_GPIO is not set
 # CONFIG_INTEL_RNG is not set
+# CONFIG_HW_RANDOM is not set
 # CONFIG_AMD_PM768 is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
@@ -265,6 +272,10 @@
 #
 # CONFIG_FTAPE is not set
 # CONFIG_AGP is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
 # CONFIG_DRM is not set
 
 #
@@ -337,6 +348,7 @@
 # CONFIG_TMPFS is not set
 CONFIG_RAMFS=y
 CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
@@ -478,3 +490,4 @@
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_IA64_DEBUG_CMPXCHG is not set
 # CONFIG_IA64_DEBUG_IRQ is not set
+CONFIG_LOG_BUF_SHIFT=0
diff -urN linux-2.4.23-bk3/arch/ia64/configs/zx1 linux-2.4.23-bk4/arch/ia64/configs/zx1
--- linux-2.4.23-bk3/arch/ia64/configs/zx1	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/configs/zx1	2003-12-06 02:49:48.000000000 -0800
@@ -30,7 +30,6 @@
 # CONFIG_IA64_DIG is not set
 # CONFIG_IA64_HP_SIM is not set
 CONFIG_IA64_HP_ZX1=y
-# CONFIG_IA64_SGI_SN1 is not set
 # CONFIG_IA64_SGI_SN2 is not set
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
@@ -42,7 +41,6 @@
 CONFIG_PM=y
 CONFIG_KCORE_ELF=y
 CONFIG_FORCE_MAX_ZONEORDER=19
-CONFIG_HUGETLB_PAGE=y
 # CONFIG_HUGETLB_PAGE_SIZE_4GB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1GB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_256MB is not set
@@ -53,6 +51,7 @@
 # CONFIG_HUGETLB_PAGE_SIZE_256KB is not set
 CONFIG_IA64_PAL_IDLE=y
 CONFIG_SMP=y
+CONFIG_NR_CPUS=32
 CONFIG_IA32_SUPPORT=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
@@ -114,6 +113,12 @@
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
 
@@ -168,6 +173,7 @@
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
 CONFIG_BLK_DEV_LOOP=y
@@ -340,6 +346,7 @@
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_MEGARAID2 is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
@@ -367,7 +374,6 @@
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=y
-# CONFIG_SCSI_QLOGIC_QLA2100 is not set
 # CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_DC390T is not set
@@ -439,7 +445,6 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_SUNDANCE_MMIO is not set
 # CONFIG_TLAN is not set
-# CONFIG_TC35815 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_VIA_RHINE_MMIO is not set
 # CONFIG_WINBOND_840 is not set
@@ -585,6 +590,7 @@
 # CONFIG_WATCHDOG is not set
 # CONFIG_SCx200_GPIO is not set
 # CONFIG_INTEL_RNG is not set
+# CONFIG_HW_RANDOM is not set
 # CONFIG_AMD_PM768 is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
@@ -602,12 +608,17 @@
 # CONFIG_AGP_I810 is not set
 # CONFIG_AGP_VIA is not set
 # CONFIG_AGP_AMD is not set
-# CONFIG_AGP_AMD_8151 is not set
+# CONFIG_AGP_AMD_K8 is not set
 # CONFIG_AGP_SIS is not set
 # CONFIG_AGP_ALI is not set
 # CONFIG_AGP_SWORKS is not set
 CONFIG_AGP_I460=y
 CONFIG_AGP_HP_ZX1=y
+# CONFIG_AGP_ATI is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
 CONFIG_DRM=y
 # CONFIG_DRM_OLD is not set
 
@@ -616,6 +627,7 @@
 #
 CONFIG_DRM_NEW=y
 # CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_GAMMA is not set
 CONFIG_DRM_R128=y
 CONFIG_DRM_RADEON=y
 # CONFIG_DRM_I810 is not set
@@ -691,6 +703,7 @@
 # CONFIG_TMPFS is not set
 CONFIG_RAMFS=y
 CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
@@ -845,6 +858,8 @@
 # CONFIG_MIDI_VIA82CXXX is not set
 # CONFIG_SOUND_OSS is not set
 # CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+# CONFIG_SOUND_WM97XX is not set
 
 #
 # USB support
@@ -915,6 +930,7 @@
 # CONFIG_USB_PWC is not set
 # CONFIG_USB_SE401 is not set
 # CONFIG_USB_STV680 is not set
+# CONFIG_USB_W9968CF is not set
 # CONFIG_USB_VICAM is not set
 # CONFIG_USB_DSBR is not set
 # CONFIG_USB_DABUSB is not set
@@ -950,6 +966,11 @@
 # CONFIG_USB_LCD is not set
 
 #
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
 # Cryptographic options
 #
 # CONFIG_CRYPTO is not set
@@ -983,3 +1004,4 @@
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_IA64_DEBUG_CMPXCHG is not set
 # CONFIG_IA64_DEBUG_IRQ is not set
+CONFIG_LOG_BUF_SHIFT=0
diff -urN linux-2.4.23-bk3/arch/ia64/defconfig linux-2.4.23-bk4/arch/ia64/defconfig
--- linux-2.4.23-bk3/arch/ia64/defconfig	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/defconfig	2003-12-06 02:49:48.000000000 -0800
@@ -30,7 +30,6 @@
 # CONFIG_IA64_DIG is not set
 # CONFIG_IA64_HP_SIM is not set
 # CONFIG_IA64_HP_ZX1 is not set
-# CONFIG_IA64_SGI_SN1 is not set
 # CONFIG_IA64_SGI_SN2 is not set
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
@@ -43,7 +42,6 @@
 CONFIG_PM=y
 CONFIG_KCORE_ELF=y
 CONFIG_FORCE_MAX_ZONEORDER=19
-CONFIG_HUGETLB_PAGE=y
 # CONFIG_HUGETLB_PAGE_SIZE_256MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
 CONFIG_HUGETLB_PAGE_SIZE_16MB=y
@@ -114,6 +112,12 @@
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
 
@@ -168,6 +172,7 @@
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
 CONFIG_BLK_DEV_LOOP=y
@@ -276,6 +281,7 @@
 # CONFIG_BLK_DEV_RZ1000 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SGIIOC4 is not set
 # CONFIG_BLK_DEV_SIIMAGE is not set
 # CONFIG_BLK_DEV_SIS5513 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
@@ -340,6 +346,7 @@
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_MEGARAID2 is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
@@ -372,7 +379,6 @@
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=y
-# CONFIG_SCSI_QLOGIC_QLA2100 is not set
 # CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_DC390T is not set
@@ -444,7 +450,6 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_SUNDANCE_MMIO is not set
 # CONFIG_TLAN is not set
-# CONFIG_TC35815 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_VIA_RHINE_MMIO is not set
 # CONFIG_WINBOND_840 is not set
@@ -589,7 +594,9 @@
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_SCx200_GPIO is not set
+# CONFIG_FETCHOP is not set
 # CONFIG_INTEL_RNG is not set
+# CONFIG_HW_RANDOM is not set
 # CONFIG_AMD_PM768 is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
@@ -607,12 +614,17 @@
 # CONFIG_AGP_I810 is not set
 # CONFIG_AGP_VIA is not set
 # CONFIG_AGP_AMD is not set
-# CONFIG_AGP_AMD_8151 is not set
+# CONFIG_AGP_AMD_K8 is not set
 # CONFIG_AGP_SIS is not set
 # CONFIG_AGP_ALI is not set
 # CONFIG_AGP_SWORKS is not set
 CONFIG_AGP_I460=y
 CONFIG_AGP_HP_ZX1=y
+# CONFIG_AGP_ATI is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
 CONFIG_DRM=y
 # CONFIG_DRM_OLD is not set
 
@@ -621,6 +633,7 @@
 #
 CONFIG_DRM_NEW=y
 # CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_GAMMA is not set
 CONFIG_DRM_R128=y
 CONFIG_DRM_RADEON=y
 # CONFIG_DRM_I810 is not set
@@ -696,6 +709,7 @@
 # CONFIG_TMPFS is not set
 CONFIG_RAMFS=y
 CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
@@ -850,6 +864,8 @@
 # CONFIG_MIDI_VIA82CXXX is not set
 # CONFIG_SOUND_OSS is not set
 # CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+# CONFIG_SOUND_WM97XX is not set
 
 #
 # USB support
@@ -920,6 +936,7 @@
 # CONFIG_USB_PWC is not set
 # CONFIG_USB_SE401 is not set
 # CONFIG_USB_STV680 is not set
+# CONFIG_USB_W9968CF is not set
 # CONFIG_USB_VICAM is not set
 # CONFIG_USB_DSBR is not set
 # CONFIG_USB_DABUSB is not set
@@ -955,6 +972,11 @@
 # CONFIG_USB_LCD is not set
 
 #
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
 # Cryptographic options
 #
 # CONFIG_CRYPTO is not set
@@ -995,3 +1017,4 @@
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_IA64_DEBUG_CMPXCHG is not set
 # CONFIG_IA64_DEBUG_IRQ is not set
+CONFIG_LOG_BUF_SHIFT=0
diff -urN linux-2.4.23-bk3/arch/ia64/hp/common/sba_iommu.c linux-2.4.23-bk4/arch/ia64/hp/common/sba_iommu.c
--- linux-2.4.23-bk3/arch/ia64/hp/common/sba_iommu.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/hp/common/sba_iommu.c	2003-12-06 02:49:48.000000000 -0800
@@ -48,6 +48,11 @@
 */
 #define ALLOW_IOV_BYPASS
 
+#ifdef CONFIG_PROC_FS
+  /* turn it off for now; without per-CPU counters, it's too much of a scalability bottleneck: */
+# define SBA_PROC_FS 0
+#endif
+
 /*
 ** If a device prefetches beyond the end of a valid pdir entry, it will cause
 ** a hard failure, ie. MCA.  Version 3.0 and later of the zx1 LBA should
@@ -121,7 +126,7 @@
 #endif
 
 /*
-** The number of pdir entries to "free" before issueing
+** The number of pdir entries to "free" before issuing
 ** a read to PCOM register to flush out PCOM writes.
 ** Interacts with allocation granularity (ie 4 or 8 entries
 ** allocated and free'd/purged at a time might make this
@@ -186,7 +191,7 @@
 	} saved[DELAYED_RESOURCE_CNT];
 #endif
 
-#ifdef CONFIG_PROC_FS
+#if SBA_PROC_FS
 #define SBA_SEARCH_SAMPLE	0x100
 	unsigned long avg_search[SBA_SEARCH_SAMPLE];
 	unsigned long avg_idx;	/* current index into avg_search */
@@ -209,7 +214,7 @@
 	/* Stuff we don't need in performance path */
 	struct ioc	*next;		/* list of IOC's in system */
 	acpi_handle	handle;		/* for multiple IOC's */
-	char		*name;
+	const char 	*name;
 	unsigned int	func_id;
 	unsigned int	rev;		/* HW revision of chip */
 	u32		iov_size;
@@ -231,7 +236,11 @@
 static u64 prefetch_spill_page;
 #endif
 
-#define GET_IOC(dev)	((struct ioc *) PCI_CONTROLLER(dev)->iommu)
+#ifdef CONFIG_PCI
+# define GET_IOC(dev)	((struct ioc *) PCI_CONTROLLER(dev)->iommu)
+#else
+# define GET_IOC(dev)	NULL
+#endif
 
 /*
 ** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up
@@ -510,7 +519,7 @@
 sba_alloc_range(struct ioc *ioc, size_t size)
 {
 	unsigned int pages_needed = size >> IOVP_SHIFT;
-#ifdef CONFIG_PROC_FS
+#if SBA_PROC_FS
 	unsigned long itc_start = ia64_get_itc();
 #endif
 	unsigned long pide;
@@ -544,7 +553,7 @@
 		(uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map),
 		ioc->res_bitshift );
 
-#ifdef CONFIG_PROC_FS
+#if SBA_PROC_FS
 	{
 		unsigned long itc_end = ia64_get_itc();
 		unsigned long tmp = itc_end - itc_start;
@@ -586,7 +595,7 @@
 		__FUNCTION__, (uint) iova, size,
 		bits_not_wanted, m, pide, res_ptr, *res_ptr);
 
-#ifdef CONFIG_PROC_FS
+#if SBA_PROC_FS
 	ioc->used_pages -= bits_not_wanted;
 #endif
 
@@ -749,12 +758,12 @@
  * @dev: instance of PCI owned by the driver that's asking.
  * @addr:  driver buffer to map.
  * @size:  number of bytes to map in driver buffer.
- * @direction:  R/W or both.
+ * @dir:  R/W or both.
  *
  * See Documentation/DMA-mapping.txt
  */
 dma_addr_t
-sba_map_single(struct pci_dev *dev, void *addr, size_t size, int direction)
+sba_map_single(struct pci_dev *dev, void *addr, size_t size, int dir)
 {
 	struct ioc *ioc;
 	unsigned long flags;
@@ -778,7 +787,7 @@
  		** Device is bit capable of DMA'ing to the buffer...
 		** just return the PCI address of ptr
  		*/
-#ifdef CONFIG_PROC_FS
+#if SBA_PROC_FS
 		spin_lock_irqsave(&ioc->res_lock, flags);
 		ioc->msingle_bypass++;
 		spin_unlock_irqrestore(&ioc->res_lock, flags);
@@ -804,7 +813,7 @@
 		panic("Sanity check failed");
 #endif
 
-#ifdef CONFIG_PROC_FS
+#if SBA_PROC_FS
 	ioc->msingle_calls++;
 	ioc->msingle_pages += size >> IOVP_SHIFT;
 #endif
@@ -842,12 +851,11 @@
  * @dev: instance of PCI owned by the driver that's asking.
  * @iova:  IOVA of driver buffer previously mapped.
  * @size:  number of bytes mapped in driver buffer.
- * @direction:  R/W or both.
+ * @dir:  R/W or both.
  *
  * See Documentation/DMA-mapping.txt
  */
-void sba_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size,
-		int direction)
+void sba_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, int dir)
 {
 	struct ioc *ioc;
 #if DELAYED_RESOURCE_CNT > 0
@@ -864,7 +872,7 @@
 		/*
 		** Address does not fall w/in IOVA, must be bypassing
 		*/
-#ifdef CONFIG_PROC_FS
+#if SBA_PROC_FS
 		spin_lock_irqsave(&ioc->res_lock, flags);
 		ioc->usingle_bypass++;
 		spin_unlock_irqrestore(&ioc->res_lock, flags);
@@ -872,7 +880,7 @@
 		DBG_BYPASS("sba_unmap_single() bypass addr: 0x%lx\n", iova);
 
 #ifdef ENABLE_MARK_CLEAN
-		if (direction == PCI_DMA_FROMDEVICE) {
+		if (dir == PCI_DMA_FROMDEVICE) {
 			mark_clean(phys_to_virt(iova), size);
 		}
 #endif
@@ -889,7 +897,7 @@
 	size = ROUNDUP(size, IOVP_SIZE);
 
 	spin_lock_irqsave(&ioc->res_lock, flags);
-#ifdef CONFIG_PROC_FS
+#if SBA_PROC_FS
 	ioc->usingle_calls++;
 	ioc->usingle_pages += size >> IOVP_SHIFT;
 #endif
@@ -914,7 +922,7 @@
 	READ_REG(ioc->ioc_hpa+IOC_PCOM);	/* flush purges */
 #endif /* DELAYED_RESOURCE_CNT == 0 */
 #ifdef ENABLE_MARK_CLEAN
-	if (direction == PCI_DMA_FROMDEVICE) {
+	if (dir == PCI_DMA_FROMDEVICE) {
 		u32 iovp = (u32) SBA_IOVP(ioc,iova);
 		int off = PDIR_INDEX(iovp);
 		void *addr;
@@ -951,55 +959,51 @@
 
 
 /**
- * sba_alloc_consistent - allocate/map shared mem for DMA
- * @hwdev: instance of PCI owned by the driver that's asking.
+ * sba_alloc_coherent - allocate/map shared mem for DMA
+ * @dev: instance of PCI owned by the driver that's asking.
  * @size:  number of bytes mapped in driver buffer.
  * @dma_handle:  IOVA of new buffer.
  *
  * See Documentation/DMA-mapping.txt
  */
 void *
-sba_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
+sba_alloc_coherent (struct pci_dev *dev, size_t size, dma_addr_t *dma_handle)
 {
 	struct ioc *ioc;
-	void *ret;
+	void *addr;
 
-	if (!hwdev) {
-		/* only support PCI */
-		*dma_handle = 0;
-		return 0;
-	}
+	if (!dev)
+		return NULL;	/* only support PCI */
 
-        ret = (void *) __get_free_pages(GFP_ATOMIC, get_order(size));
+	addr = (void *) __get_free_pages(GFP_ATOMIC, get_order(size));
+	if (!addr)
+		return NULL;
 
-	if (ret) {
-		memset(ret, 0, size);
-		/*
-		 * REVISIT: if sba_map_single starts needing more
-		 * than dma_mask from the device, this needs to be
-		 * updated.
-		 */
-		ioc = GET_IOC(hwdev);
-		*dma_handle = sba_map_single(ioc->sac_only_dev, ret, size, 0);
-	}
+	/*
+	 * REVISIT: if sba_map_single starts needing more than dma_mask from the
+	 * device, this needs to be updated.
+	 */
+	ioc = GET_IOC(dev);
+	ASSERT(ioc);
+	*dma_handle = sba_map_single(ioc->sac_only_dev, addr, size, 0);
 
-	return ret;
+	memset(addr, 0, size);
+	return addr;
 }
 
 
 /**
- * sba_free_consistent - free/unmap shared mem for DMA
- * @hwdev: instance of PCI owned by the driver that's asking.
+ * sba_free_coherent - free/unmap shared mem for DMA
+ * @dev: instance of PCI owned by the driver that's asking.
  * @size:  number of bytes mapped in driver buffer.
  * @vaddr:  virtual address IOVA of "consistent" buffer.
  * @dma_handler:  IO virtual address of "consistent" buffer.
  *
  * See Documentation/DMA-mapping.txt
  */
-void sba_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr,
-		dma_addr_t dma_handle)
+void sba_free_coherent (struct pci_dev *dev, size_t size, void *vaddr, dma_addr_t dma_handle)
 {
-	sba_unmap_single(hwdev, dma_handle, size, 0);
+	sba_unmap_single(dev, dma_handle, size, 0);
 	free_pages((unsigned long) vaddr, get_order(size));
 }
 
@@ -1079,7 +1083,7 @@
 			cnt += dma_offset;
 			dma_offset=0;	/* only want offset on first chunk */
 			cnt = ROUNDUP(cnt, IOVP_SIZE);
-#ifdef CONFIG_PROC_FS
+#if SBA_PROC_FS
 			ioc->msg_pages += cnt >> IOVP_SHIFT;
 #endif
 			do {
@@ -1121,7 +1125,7 @@
  * in the DMA stream. Allocates PDIR entries but does not fill them.
  * Returns the number of DMA chunks.
  *
- * Doing the fill seperate from the coalescing/allocation keeps the
+ * Doing the fill separate from the coalescing/allocation keeps the
  * code simpler. Future enhancement could make one pass through
  * the sglist do both.
  */
@@ -1246,11 +1250,11 @@
  * @dev: instance of PCI owned by the driver that's asking.
  * @sglist:  array of buffer/length pairs
  * @nents:  number of entries in list
- * @direction:  R/W or both.
+ * @dir:  R/W or both.
  *
  * See Documentation/DMA-mapping.txt
  */
-int sba_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+int sba_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int dir)
 {
 	struct ioc *ioc;
 	int coalesced, filled = 0;
@@ -1269,7 +1273,7 @@
 			sg->dma_length = sg->length;
 			sg->dma_address = virt_to_phys(sba_sg_address(sg));
 		}
-#ifdef CONFIG_PROC_FS
+#if SBA_PROC_FS
 		spin_lock_irqsave(&ioc->res_lock, flags);
 		ioc->msg_bypass++;
 		spin_unlock_irqrestore(&ioc->res_lock, flags);
@@ -1280,10 +1284,9 @@
 	/* Fast path single entry scatterlists. */
 	if (nents == 1) {
 		sglist->dma_length = sglist->length;
-		sglist->dma_address = sba_map_single(dev,
-		                                     sba_sg_address(sglist),
-		                                     sglist->length, direction);
-#ifdef CONFIG_PROC_FS
+		sglist->dma_address = sba_map_single(dev, sba_sg_address(sglist), sglist->length,
+						     dir);
+#if SBA_PROC_FS
 		/*
 		** Should probably do some stats counting, but trying to
 		** be precise quickly starts wasting CPU time.
@@ -1302,7 +1305,7 @@
 	}
 #endif
 
-#ifdef CONFIG_PROC_FS
+#if SBA_PROC_FS
 	ioc->msg_calls++;
 #endif
 
@@ -1348,12 +1351,11 @@
  * @dev: instance of PCI owned by the driver that's asking.
  * @sglist:  array of buffer/length pairs
  * @nents:  number of entries in list
- * @direction:  R/W or both.
+ * @dir:  R/W or both.
  *
  * See Documentation/DMA-mapping.txt
  */
-void sba_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents,
-		int direction)
+void sba_unmap_sg (struct pci_dev *dev, struct scatterlist *sglist, int nents, int dir)
 {
 	struct ioc *ioc;
 #ifdef ASSERT_PDIR_SANITY
@@ -1366,7 +1368,7 @@
 	ioc = GET_IOC(dev);
 	ASSERT(ioc);
 
-#ifdef CONFIG_PROC_FS
+#if SBA_PROC_FS
 	ioc->usg_calls++;
 #endif
 
@@ -1378,9 +1380,8 @@
 
 	while (nents && sglist->dma_length) {
 
-		sba_unmap_single(dev, sglist->dma_address,
-		                 sglist->dma_length, direction);
-#ifdef CONFIG_PROC_FS
+		sba_unmap_single(dev, sglist->dma_address, sglist->dma_length, dir);
+#if SBA_PROC_FS
 		/*
 		** This leaves inconsistent data in the stats, but we can't
 		** tell which sg lists were mapped by map_single and which
@@ -1416,7 +1417,7 @@
 	u32 iova_space_mask;
 	int iov_order, tcnfg;
 	int agp_found = 0;
-	struct pci_dev *device;
+	struct pci_dev *device = NULL;
 #ifdef FULL_VALID_PDIR
 	unsigned long index;
 #endif
@@ -1514,7 +1515,7 @@
 	** We program the next pdir index after we stop w/ a key for
 	** the GART code to handshake on.
 	*/
-	pci_for_each_dev(device)
+	while ((device = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, device)) != NULL)
 		agp_found |= pci_find_capability(device, PCI_CAP_ID_AGP);
 
 	if (agp_found && reserve_sba_gart) {
@@ -1596,7 +1597,7 @@
 	struct pci_controller *controller = NULL;
 
 	/*
-	 * pci_alloc_consistent() must return a DMA address which is
+	 * pci_alloc_coherent() must return a DMA address which is
 	 * SAC (single address cycle) addressable, so allocate a
 	 * pseudo-device to enforce that.
 	 */
@@ -1671,9 +1672,8 @@
 	if (!ioc->name) {
 		ioc->name = kmalloc(24, GFP_KERNEL);
 		if (ioc->name)
-			sprintf(ioc->name, "Unknown (%04x:%04x)",
-				ioc->func_id & 0xFFFF,
-				(ioc->func_id >> 16) & 0xFFFF);
+			sprintf((char *) ioc->name, "Unknown (%04x:%04x)",
+				ioc->func_id & 0xFFFF, (ioc->func_id >> 16) & 0xFFFF);
 		else
 			ioc->name = "Unknown";
 	}
@@ -1701,7 +1701,7 @@
 **
 **************************************************************************/
 
-#ifdef CONFIG_PROC_FS
+#if SBA_PROC_FS
 static void *
 ioc_start(struct seq_file *s, loff_t *pos)
 {
@@ -1756,33 +1756,31 @@
 		if (ioc->avg_search[i] < min) min = ioc->avg_search[i];
 	}
 	avg /= SBA_SEARCH_SAMPLE;
-	seq_printf(s, "  Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
-		min, avg, max);
+	seq_printf(s, "  Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", min, avg, max);
 
 	seq_printf(s, "pci_map_single(): %12ld calls  %12ld pages (avg %d/1000)\n",
-		ioc->msingle_calls, ioc->msingle_pages,
-		(int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls));
+		   ioc->msingle_calls, ioc->msingle_pages,
+		   (int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls));
 #ifdef ALLOW_IOV_BYPASS
 	seq_printf(s, "pci_map_single(): %12ld bypasses\n", ioc->msingle_bypass);
 #endif
 
 	seq_printf(s, "pci_unmap_single: %12ld calls  %12ld pages (avg %d/1000)\n",
-		ioc->usingle_calls, ioc->usingle_pages,
-		(int) ((ioc->usingle_pages * 1000)/ioc->usingle_calls));
+		   ioc->usingle_calls, ioc->usingle_pages,
+		   (int) ((ioc->usingle_pages * 1000)/ioc->usingle_calls));
 #ifdef ALLOW_IOV_BYPASS
 	seq_printf(s, "pci_unmap_single: %12ld bypasses\n", ioc->usingle_bypass);
 #endif
 
 	seq_printf(s, "pci_map_sg()    : %12ld calls  %12ld pages (avg %d/1000)\n",
-		ioc->msg_calls, ioc->msg_pages,
-		(int) ((ioc->msg_pages * 1000)/ioc->msg_calls));
+		   ioc->msg_calls, ioc->msg_pages,
+		   (int) ((ioc->msg_pages * 1000)/ioc->msg_calls));
 #ifdef ALLOW_IOV_BYPASS
 	seq_printf(s, "pci_map_sg()    : %12ld bypasses\n", ioc->msg_bypass);
 #endif
 
 	seq_printf(s, "pci_unmap_sg()  : %12ld calls  %12ld pages (avg %d/1000)\n",
-		ioc->usg_calls, ioc->usg_pages,
-		(int) ((ioc->usg_pages * 1000)/ioc->usg_calls));
+		   ioc->usg_calls, ioc->usg_pages, (int) ((ioc->usg_pages * 1000)/ioc->usg_calls));
 
 	return 0;
 }
@@ -1811,11 +1809,10 @@
 ioc_map_show(struct seq_file *s, void *v)
 {
 	struct ioc *ioc = v;
-	unsigned int *res_ptr = (unsigned int *)ioc->res_map;
-	int i;
+	unsigned int i, *res_ptr = (unsigned int *)ioc->res_map;
 
-	for (i = 0; i < (ioc->res_size / sizeof(unsigned int)); ++i, ++res_ptr)
-		seq_printf(s, "%s%08x", (i & 7) ? " " : "\n    ", *res_ptr);
+	for (i = 0; i < ioc->res_size / sizeof(unsigned int); ++i, ++res_ptr)
+		seq_printf(s, "%s%08x", (i & 7) ? " " : "\n   ", *res_ptr);
 	seq_printf(s, "\n");
 
 	return 0;
@@ -1844,29 +1841,36 @@
 static void __init
 ioc_proc_init(void)
 {
-	if (ioc_list) {
-		struct proc_dir_entry *dir, *entry;
+	struct proc_dir_entry *dir, *entry;
 
-		dir = proc_mkdir("bus/mckinley", 0);
-		entry = create_proc_entry(ioc_list->name, 0, dir);
-		if (entry)
-			entry->proc_fops = &ioc_fops;
+	dir = proc_mkdir("bus/mckinley", 0);
+	if (!dir)
+		return;
 
-		entry = create_proc_entry("bitmap", 0, dir);
-		if (entry)
-			entry->proc_fops = &ioc_map_fops;
-	}
+	entry = create_proc_entry(ioc_list->name, 0, dir);
+	if (entry)
+		entry->proc_fops = &ioc_fops;
+
+	entry = create_proc_entry("bitmap", 0, dir);
+	if (entry)
+		entry->proc_fops = &ioc_map_fops;
 }
 #endif
 
-void
-sba_enable_device(struct pci_dev *dev)
+static void
+sba_connect_bus(struct pci_bus *bus)
 {
 	acpi_handle handle, parent;
 	acpi_status status;
 	struct ioc *ioc;
 
-	handle = PCI_CONTROLLER(dev)->acpi_handle;
+	if (!PCI_CONTROLLER(bus))
+		panic(PFX "no sysdata on bus %d!\n", bus->number);
+
+	if (PCI_CONTROLLER(bus)->iommu)
+		return;
+
+	handle = PCI_CONTROLLER(bus)->acpi_handle;
 	if (!handle)
 		return;
 
@@ -1878,7 +1882,7 @@
 	do {
 		for (ioc = ioc_list; ioc; ioc = ioc->next)
 			if (ioc->handle == handle) {
-				PCI_CONTROLLER(dev)->iommu = ioc;
+				PCI_CONTROLLER(bus)->iommu = ioc;
 				return;
 			}
 
@@ -1886,7 +1890,7 @@
 		handle = parent;
 	} while (ACPI_SUCCESS(status));
 
-	printk(KERN_WARNING "No IOC for %s in ACPI\n", dev->slot_name);
+	printk(KERN_WARNING "No IOC for PCI Bus %04x:%02x in ACPI\n", PCI_SEGMENT(bus), bus->number);
 }
 
 static int __init
@@ -1924,19 +1928,29 @@
 }
 
 static struct acpi_driver acpi_sba_ioc_driver = {
-	name:		"IOC IOMMU Driver",
-	ids:		"HWP0001,HWP0004",
-	ops: {
-		add:	acpi_sba_ioc_add,
-     },
+	.name		= "IOC IOMMU Driver",
+	.ids		= "HWP0001,HWP0004",
+	.ops		= {
+		.add	= acpi_sba_ioc_add,
+	},
 };
 
 void __init
 sba_init(void)
 {
 	acpi_bus_register_driver(&acpi_sba_ioc_driver);
+	if (!ioc_list)
+		return 0;
 
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_PCI
+	{
+		struct pci_bus *b = NULL;
+		pci_for_each_bus(b)
+			sba_connect_bus(b);
+	}
+#endif
+
+#if SBA_PROC_FS
 	ioc_proc_init();
 #endif
 }
@@ -1963,5 +1977,5 @@
 EXPORT_SYMBOL(sba_map_sg);
 EXPORT_SYMBOL(sba_unmap_sg);
 EXPORT_SYMBOL(sba_dma_supported);
-EXPORT_SYMBOL(sba_alloc_consistent);
-EXPORT_SYMBOL(sba_free_consistent);
+EXPORT_SYMBOL(sba_alloc_coherent);
+EXPORT_SYMBOL(sba_free_coherent);
diff -urN linux-2.4.23-bk3/arch/ia64/hp/zx1/hpzx1_machvec.c linux-2.4.23-bk4/arch/ia64/hp/zx1/hpzx1_machvec.c
--- linux-2.4.23-bk3/arch/ia64/hp/zx1/hpzx1_machvec.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-bk4/arch/ia64/hp/zx1/hpzx1_machvec.c	2003-12-06 02:49:48.000000000 -0800
@@ -1,3 +1,3 @@
-#define MACHVEC_PLATFORM_NAME		hpzx1
+#define MACHVEC_PLATFORM_NAME		hp
 #define MACHVEC_PLATFORM_HEADER		<asm/machvec_hpzx1.h>
 #include <asm/machvec_init.h>
diff -urN linux-2.4.23-bk3/arch/ia64/hp/zx1/hpzx1_misc.c linux-2.4.23-bk4/arch/ia64/hp/zx1/hpzx1_misc.c
--- linux-2.4.23-bk3/arch/ia64/hp/zx1/hpzx1_misc.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/hp/zx1/hpzx1_misc.c	2003-12-06 02:49:48.000000000 -0800
@@ -17,7 +17,7 @@
 #include <asm/dma.h>
 #include <asm/iosapic.h>
 
-#define PFX "hpzx1: "
+#define PFX
 
 static int hpzx1_devices;
 
@@ -50,7 +50,14 @@
 		fake_dev->sizing = 0; \
 		return PCIBIOS_SUCCESSFUL; \
 	} \
-	*value = read##sz(fake_dev->mapped_csrs + where); \
+	switch (where & ~0x7) { \
+		case 0x48: /* initiates config cycles */ \
+		case 0x78: /* elroy suspend mode register */ \
+			*value = 0; \
+			break; \
+		default: \
+			*value = read##sz(fake_dev->mapped_csrs + where); \
+	} \
 	if (where == PCI_COMMAND) \
 		*value |= PCI_COMMAND_MEMORY; /* SBA omits this */ \
 	return PCIBIOS_SUCCESSFUL; \
@@ -68,8 +75,14 @@
 		if (value == (u##bits) ~0) \
 			fake_dev->sizing = 1; \
 		return PCIBIOS_SUCCESSFUL; \
-	} else \
-		write##sz(value, fake_dev->mapped_csrs + where); \
+	} \
+	switch (where & ~0x7) { \
+		case 0x48: /* initiates config cycles */ \
+		case 0x78: /* elroy suspend mode register */ \
+			break; \
+		default: \
+			write##sz(value, fake_dev->mapped_csrs + where); \
+	} \
 	return PCIBIOS_SUCCESSFUL; \
 }
 
diff -urN linux-2.4.23-bk3/arch/ia64/ia32/ia32_entry.S linux-2.4.23-bk4/arch/ia64/ia32/ia32_entry.S
--- linux-2.4.23-bk3/arch/ia64/ia32/ia32_entry.S	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-bk4/arch/ia64/ia32/ia32_entry.S	2003-12-06 02:49:48.000000000 -0800
@@ -138,6 +138,19 @@
 	;;
 	st8 [r2]=r3				// initialize return code to -ENOSYS
 	br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch syscall args
+	// Need to reload arguments (they may be changed by the tracing process)
+	adds r2=IA64_PT_REGS_R9_OFFSET+16,sp	// r2 = &pt_regs.r9
+	adds r3=IA64_PT_REGS_R13_OFFSET+16,sp	// r3 = &pt_regs.r13
+	;;
+	ld4 r33=[r2],8				// r9 == ecx
+	ld4 r37=[r3],16				// r13 == ebp
+	;;
+	ld4 r34=[r2],8				// r10 == edx
+	ld4 r36=[r3],8				// r15 == edi
+	;;
+	ld4 r32=[r2],8				// r11 == ebx
+	ld4 r35=[r3],8				// r14 == esi
+	;;
 .ret2:	br.call.sptk.few rp=b6			// do the syscall
 .ia32_strace_check_retval:
 	cmp.lt p6,p0=r8,r0			// syscall failed?
diff -urN linux-2.4.23-bk3/arch/ia64/ia32/sys_ia32.c linux-2.4.23-bk4/arch/ia64/ia32/sys_ia32.c
--- linux-2.4.23-bk3/arch/ia64/ia32/sys_ia32.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/ia32/sys_ia32.c	2003-12-06 02:49:48.000000000 -0800
@@ -74,6 +74,7 @@
 #define OFFSET4K(a)		((a) & 0xfff)
 #define PAGE_START(addr)	((addr) & PAGE_MASK)
 #define PAGE_OFF(addr)		((addr) & ~PAGE_MASK)
+#define MINSIGSTKSZ_IA32	2048
 
 extern asmlinkage long sys_execve (char *, char **, char **, struct pt_regs *);
 extern asmlinkage long sys_mprotect (unsigned long, size_t, unsigned long);
@@ -201,13 +202,18 @@
 asmlinkage long
 sys32_newstat (char *filename, struct stat32 *statbuf)
 {
+	char *name;
 	int ret;
 	struct stat s;
 	mm_segment_t old_fs = get_fs();
 
+	name = getname(filename);
+	if (IS_ERR(name))
+		return PTR_ERR(name);
 	set_fs(KERNEL_DS);
-	ret = sys_newstat(filename, &s);
+	ret = sys_newstat(name, &s);
 	set_fs(old_fs);
+	putname(name);
 	if (putstat(statbuf, &s))
 		return -EFAULT;
 	return ret;
@@ -218,13 +224,18 @@
 asmlinkage long
 sys32_newlstat (char *filename, struct stat32 *statbuf)
 {
+	char *name;
 	mm_segment_t old_fs = get_fs();
 	struct stat s;
 	int ret;
 
+	name = getname(filename);
+	if (IS_ERR(name))
+		return PTR_ERR(name);
 	set_fs(KERNEL_DS);
-	ret = sys_newlstat(filename, &s);
+	ret = sys_newlstat(name, &s);
 	set_fs(old_fs);
+	putname(name);
 	if (putstat(statbuf, &s))
 		return -EFAULT;
 	return ret;
@@ -698,13 +709,18 @@
 asmlinkage long
 sys32_statfs (const char *path, struct statfs32 *buf)
 {
+	const char *name;
 	int ret;
 	struct statfs s;
 	mm_segment_t old_fs = get_fs();
 
+	name = getname(path);
+	if (IS_ERR(name))
+		return PTR_ERR(name);
 	set_fs(KERNEL_DS);
-	ret = sys_statfs(path, &s);
+	ret = sys_statfs(name, &s);
 	set_fs(old_fs);
+	putname(name);
 	if (put_statfs(buf, &s))
 		return -EFAULT;
 	return ret;
@@ -3388,10 +3404,18 @@
 			return -EFAULT;
 	uss.ss_sp = (void *) (long) buf32.ss_sp;
 	uss.ss_flags = buf32.ss_flags;
-	uss.ss_size = buf32.ss_size;
+	/* MINSIGSTKSZ is different for ia32 vs ia64. We lie here to pass the 
+           check and set it to the user requested value later */
+	if (buf32.ss_size < MINSIGSTKSZ_IA32) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	uss.ss_size = MINSIGSTKSZ;
 	set_fs(KERNEL_DS);
 	ret = do_sigaltstack(uss32 ? &uss : NULL, &uoss, pt->r12);
+ 	current->sas_ss_size = buf32.ss_size;	
 	set_fs(old_fs);
+out:
 	if (ret < 0)
 		return(ret);
 	if (uoss32) {
@@ -3689,13 +3713,18 @@
 asmlinkage long
 sys32_stat64 (char *filename, struct stat64 *statbuf)
 {
+	char *name;
 	mm_segment_t old_fs = get_fs();
 	struct stat s;
 	long ret;
 
+	name = getname(filename);
+	if (IS_ERR(name))
+		return PTR_ERR(name);
 	set_fs(KERNEL_DS);
-	ret = sys_newstat(filename, &s);
+	ret = sys_newstat(name, &s);
 	set_fs(old_fs);
+	putname(name);
 	if (putstat64(statbuf, &s))
 		return -EFAULT;
 	return ret;
@@ -3704,13 +3733,18 @@
 asmlinkage long
 sys32_lstat64 (char *filename, struct stat64 *statbuf)
 {
+	char *name;
 	mm_segment_t old_fs = get_fs();
 	struct stat s;
 	long ret;
 
+	name = getname(filename);
+	if (IS_ERR(name))
+		return PTR_ERR(name);
 	set_fs(KERNEL_DS);
-	ret = sys_newlstat(filename, &s);
+	ret = sys_newlstat(name, &s);
 	set_fs(old_fs);
+	putname(name);
 	if (putstat64(statbuf, &s))
 		return -EFAULT;
 	return ret;
diff -urN linux-2.4.23-bk3/arch/ia64/kernel/acpi.c linux-2.4.23-bk4/arch/ia64/kernel/acpi.c
--- linux-2.4.23-bk3/arch/ia64/kernel/acpi.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/kernel/acpi.c	2003-12-06 02:49:48.000000000 -0800
@@ -96,7 +96,7 @@
 	}
 
 	if (!strcmp(hdr->oem_id, "HP")) {
-		return "hpzx1";
+		return "hp";
 	}
 	else if (!strcmp(hdr->oem_id, "SGI")) {
 		return "sn2";
@@ -107,7 +107,7 @@
 # if defined (CONFIG_IA64_HP_SIM)
 	return "hpsim";
 # elif defined (CONFIG_IA64_HP_ZX1)
-	return "hpzx1";
+	return "hp";
 # elif defined (CONFIG_IA64_SGI_SN2)
 	return "sn2";
 # elif defined (CONFIG_IA64_DIG)
diff -urN linux-2.4.23-bk3/arch/ia64/kernel/efi.c linux-2.4.23-bk4/arch/ia64/kernel/efi.c
--- linux-2.4.23-bk3/arch/ia64/kernel/efi.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/kernel/efi.c	2003-12-06 02:49:48.000000000 -0800
@@ -297,9 +297,9 @@
 		u64 start;
 		u64 end;
 	} prev, curr;
-	void *efi_map_start, *efi_map_end, *p, *q, *r;
+	void *efi_map_start, *efi_map_end, *p, *q;
 	efi_memory_desc_t *md, *check_md;
-	u64 efi_desc_size, start, end, granule_addr, first_non_wb_addr = 0;
+	u64 efi_desc_size, start, end, granule_addr, last_granule_addr, first_non_wb_addr = 0;
 
 	efi_map_start = __va(ia64_boot_param->efi_memmap);
 	efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
@@ -312,41 +312,34 @@
 		if (!(md->attribute & EFI_MEMORY_WB))
 			continue;
 
-		if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) > first_non_wb_addr) {
-			/*
-			 * Search for the next run of contiguous WB memory.  Start search
-			 * at first granule boundary covered by md.
-			 */
-			granule_addr = ((md->phys_addr + IA64_GRANULE_SIZE - 1)
-					& -IA64_GRANULE_SIZE);
-			first_non_wb_addr = granule_addr;
-			for (q = p; q < efi_map_end; q += efi_desc_size) {
-				check_md = q;
-
-				if (check_md->attribute & EFI_MEMORY_WB)
-					trim_bottom(check_md, granule_addr);
-
-				if (check_md->phys_addr < granule_addr)
-					continue;
+		/*
+		 * granule_addr is the base of md's first granule.
+		 * [granule_addr - first_non_wb_addr) is guaranteed to
+		 * be contiguous WB memory.
+		 */
+		granule_addr = md->phys_addr & ~(IA64_GRANULE_SIZE - 1);
+		first_non_wb_addr = max(first_non_wb_addr, granule_addr);
 
-				if (!(check_md->attribute & EFI_MEMORY_WB))
-					break;	/* hit a non-WB region; stop search */
+		if (first_non_wb_addr < md->phys_addr) {
+			trim_bottom(md, granule_addr + IA64_GRANULE_SIZE);
+			granule_addr = md->phys_addr & ~(IA64_GRANULE_SIZE - 1);
+			first_non_wb_addr = max(first_non_wb_addr, granule_addr);
+		}
 
-				if (check_md->phys_addr != first_non_wb_addr)
-					break;	/* hit a memory hole; stop search */
+		for (q = p; q < efi_map_end; q += efi_desc_size) {
+			check_md = q;
 
+			if ((check_md->attribute & EFI_MEMORY_WB) &&
+			    (check_md->phys_addr == first_non_wb_addr))
 				first_non_wb_addr += check_md->num_pages << EFI_PAGE_SHIFT;
-			}
-			/* round it down to the previous granule-boundary: */
-			first_non_wb_addr &= -IA64_GRANULE_SIZE;
-
-			if (!(first_non_wb_addr > granule_addr))
-				continue;	/* couldn't find enough contiguous memory */
-
-			for (r = p; r < q; r += efi_desc_size)
-				trim_top(r, first_non_wb_addr);
+			else
+				break;		/* non-WB or hole */
 		}
 
+		last_granule_addr = first_non_wb_addr & ~(IA64_GRANULE_SIZE - 1);
+		if (last_granule_addr < md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT))
+			trim_top(md, last_granule_addr);
+
 		if (is_available_memory(md)) {
 			if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) > mem_limit) {
 				if (md->phys_addr > mem_limit)
@@ -446,10 +439,12 @@
 			panic("Woah!  PAL code size bigger than a granule!");
 
 		mask  = ~((1 << IA64_GRANULE_SHIFT) - 1);
+#if EFI_DEBUG
 		printk(KERN_INFO "CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n",
 		       smp_processor_id(), md->phys_addr,
 		       md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
 		       vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE);
+#endif
 
 		/*
 		 * Cannot write to CRx with PSR.ic=1
@@ -688,8 +683,7 @@
 	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
 		md = p;
 
-		if ((md->phys_addr <= phys_addr) && (phys_addr <=
-		    (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1)))
+		if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
 			 return md->type;
 	}
 	return 0;
@@ -709,8 +703,7 @@
 	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
 		md = p;
 
-		if ((md->phys_addr <= phys_addr) && (phys_addr <=
-		    (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1)))
+		if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
 			return md->attribute;
 	}
 	return 0;
diff -urN linux-2.4.23-bk3/arch/ia64/kernel/gate.S linux-2.4.23-bk4/arch/ia64/kernel/gate.S
--- linux-2.4.23-bk3/arch/ia64/kernel/gate.S	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-bk4/arch/ia64/kernel/gate.S	2003-12-06 02:49:48.000000000 -0800
@@ -88,10 +88,10 @@
 	ld8 r15=[base1]					// get address of new RBS base (or NULL)
 	cover				// push args in interrupted frame onto backing store
 	;;
-	cmp.ne p8,p0=r15,r0		// do we need to switch the rbs?
+	cmp.ne p1,p0=r15,r0		// do we need to switch rbs? (note: pr is saved by kernel)
 	mov.m r9=ar.bsp			// fetch ar.bsp
-	.spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
-(p8)	br.cond.spnt setup_rbs		// yup -> (clobbers r14, r15, and r16)
+	.spillsp.p p1, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
+(p1)	br.cond.spnt setup_rbs		// yup -> (clobbers p8, r14-r16, and r18-r20)
 back_from_setup_rbs:
 	alloc r8=ar.pfs,0,0,3,0
 	ld8 out0=[base0],16		// load arg0 (signum)
@@ -130,8 +130,8 @@
 	ld8 r15=[base0],(CFM_OFF-BSP_OFF)	// fetch sc_ar_bsp and advance to CFM_OFF
 	mov r14=ar.bsp
 	;;
-	cmp.ne p8,p0=r14,r15			// do we need to restore the rbs?
-(p8)	br.cond.spnt restore_rbs		// yup -> (clobbers r14-r18, f6 & f7)
+	cmp.ne p1,p0=r14,r15			// do we need to restore the rbs?
+(p1)	br.cond.spnt restore_rbs		// yup -> (clobbers r14-r18, f6 & f7)
 	;;
 back_from_restore_rbs:
 	adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
@@ -160,26 +160,30 @@
 setup_rbs:
 	mov ar.rsc=0				// put RSE into enforced lazy mode
 	;;
-	.save ar.rnat, r16
-	mov r16=ar.rnat				// save RNaT before switching backing store area
+	.save ar.rnat, r19
+	mov r19=ar.rnat				// save RNaT before switching backing store area
 	adds r14=(RNAT_OFF+SIGCONTEXT_OFF),sp
 
+	mov r18=ar.bspstore
 	mov ar.bspstore=r15			// switch over to new register backing store area
 	;;
+
 	.spillsp ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
-	st8 [r14]=r16				// save sc_ar_rnat
+	st8 [r14]=r19				// save sc_ar_rnat
 	.body
-	adds r14=(LOADRS_OFF+SIGCONTEXT_OFF),sp
-
 	mov.m r16=ar.bsp			// sc_loadrs <- (new bsp - new bspstore) << 16
+	adds r14=(LOADRS_OFF+SIGCONTEXT_OFF),sp
 	;;
 	invala
 	sub r15=r16,r15
+	extr.u r20=r18,3,6
 	;;
+	mov ar.rsc=0xf				// set RSE into eager mode, pl 3
+	cmp.eq p8,p0=63,r20
 	shl r15=r15,16
 	;;
 	st8 [r14]=r15				// save sc_loadrs
-	mov ar.rsc=0xf				// set RSE into eager mode, pl 3
+(p8)	st8 [r18]=r19		// if bspstore points at RNaT slot, store RNaT there now
 	.restore sp				// pop .prologue
 	br.cond.sptk back_from_setup_rbs
 
diff -urN linux-2.4.23-bk3/arch/ia64/kernel/mca.c linux-2.4.23-bk4/arch/ia64/kernel/mca.c
--- linux-2.4.23-bk3/arch/ia64/kernel/mca.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/kernel/mca.c	2003-12-06 02:49:48.000000000 -0800
@@ -91,6 +91,7 @@
 static void			ia64_log_init(int);
 extern void			ia64_monarch_init_handler (void);
 extern void			ia64_slave_init_handler (void);
+static u64			ia64_log_get(int sal_info_type, u8 **buffer);
 extern struct hw_interrupt_type	irq_type_iosapic_level;
 
 static struct irqaction cmci_irqaction = {
@@ -151,7 +152,7 @@
  */
 static int cpe_poll_enabled = 1;
 
-extern void salinfo_log_wakeup(int);
+extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size);
 
 /*
  *  ia64_mca_log_sal_error_record
@@ -166,11 +167,13 @@
 int
 ia64_mca_log_sal_error_record(int sal_info_type, int called_from_init)
 {
-	int platform_err = 0;
+	u8 *buffer;
+	u64 size;
+	int platform_err;
 
-	/* Get the MCA error record */
-	if (!ia64_log_get(sal_info_type, (prfunc_t)printk))
-		return platform_err;		/* no record retrieved */
+	size = ia64_log_get(sal_info_type, &buffer);
+	if (!size)
+		return 0;
 
 	/* TODO:
 	 * 1. analyze error logs to determine recoverability
@@ -178,8 +181,11 @@
 	 * 3. set ia64_os_mca_recovery_successful flag, if applicable
 	 */
 
-	salinfo_log_wakeup(sal_info_type);
+	salinfo_log_wakeup(sal_info_type, buffer, size);
 	platform_err = ia64_log_print(sal_info_type, (prfunc_t)printk);
+	/* Clear logs from corrected errors in case there's no user-level logger */
+	if (sal_info_type == SAL_INFO_TYPE_CPE || sal_info_type == SAL_INFO_TYPE_CMC)
+		ia64_sal_clear_state_info(sal_info_type);
 
 	return platform_err;
 }
@@ -834,7 +840,7 @@
 			irr = ia64_get_irr3();
 			break;
 		}
-	} while (!(irr & (1 << irr_bit))) ;
+	} while (!(irr & (1UL << irr_bit))) ;
 }
 
 /*
@@ -1416,12 +1422,12 @@
  *	Get the current MCA log from SAL and copy it into the OS log buffer.
  *
  *  Inputs  :   info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
- *              prfunc      (fn ptr of log output function)
  *  Outputs :   size        (total record length)
+ *              *buffer     (ptr to error record)
  *
  */
 u64
-ia64_log_get(int sal_info_type, prfunc_t prfunc)
+ia64_log_get(int sal_info_type, u8 **buffer)
 {
 	sal_log_record_header_t     *log_buffer;
 	u64                         total_len = 0;
@@ -1439,6 +1445,7 @@
 		IA64_LOG_UNLOCK(sal_info_type);
 		IA64_MCA_DEBUG("ia64_log_get: SAL error record type %d retrieved. "
 			       "Record length = %ld\n", sal_info_type, total_len);
+		*buffer = (u8 *) log_buffer;
 		return total_len;
 	} else {
 		IA64_LOG_UNLOCK(sal_info_type);
@@ -1483,7 +1490,7 @@
 void
 ia64_log_rec_header_print (sal_log_record_header_t *lh, prfunc_t prfunc)
 {
-	prfunc("+Err Record ID: %d    SAL Rev: %2x.%02x\n", lh->id,
+	prfunc("+Err Record ID: %ld    SAL Rev: %2x.%02x\n", lh->id,
 			lh->revision.major, lh->revision.minor);
 	prfunc("+Time: %02x/%02x/%02x%02x %02x:%02x:%02x    Severity %d\n",
 			lh->timestamp.slh_month, lh->timestamp.slh_day,
@@ -1606,13 +1613,13 @@
 	if (info->dl)
 		prfunc(" Line: Data,");
 	prfunc(" Operation: %s,", pal_cache_op[info->op]);
-	if (info->wv)
+	if (info->wiv)
 		prfunc(" Way: %d,", info->way);
 	if (cache_check_info->valid.target_identifier)
 		/* Hope target address is saved in target_identifier */
 		if (info->tv)
 			prfunc(" Target Addr: 0x%lx,", target_addr);
-	if (info->mc)
+	if (info->mcc)
 		prfunc(" MC: Corrected");
 	prfunc("\n");
 }
@@ -1648,13 +1655,13 @@
 		prfunc("  Failure: Data Translation Cache");
 	if (info->itr) {
 		prfunc("  Failure: Instruction Translation Register");
-		prfunc(" ,Slot: %d", info->tr_slot);
+		prfunc(" ,Slot: %ld", info->tr_slot);
 	}
 	if (info->dtr) {
 		prfunc("  Failure: Data Translation Register");
-		prfunc(" ,Slot: %d", info->tr_slot);
+		prfunc(" ,Slot: %ld", info->tr_slot);
 	}
-	if (info->mc)
+	if (info->mcc)
 		prfunc(" ,MC: Corrected");
 	prfunc("\n");
 }
@@ -1700,7 +1707,7 @@
 		prfunc(" ,Error: Internal");
 	if (info->eb)
 		prfunc(" ,Error: External");
-	if (info->mc)
+	if (info->mcc)
 		prfunc(" ,MC: Corrected");
 	if (info->tv)
 		prfunc(" ,Target Address: 0x%lx", targ_addr);
@@ -2376,7 +2383,8 @@
 		ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
 		break;
 	      case SAL_INFO_TYPE_INIT:
-		prfunc("+MCA INIT ERROR LOG (UNIMPLEMENTED)\n");
+		prfunc("+CPU %d: SAL log contains INIT error record\n", smp_processor_id());
+		ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
 		break;
 	      case SAL_INFO_TYPE_CMC:
 		prfunc("+BEGIN HARDWARE ERROR STATE AT CMC\n");
diff -urN linux-2.4.23-bk3/arch/ia64/kernel/mca_asm.S linux-2.4.23-bk4/arch/ia64/kernel/mca_asm.S
--- linux-2.4.23-bk3/arch/ia64/kernel/mca_asm.S	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/kernel/mca_asm.S	2003-12-06 02:49:48.000000000 -0800
@@ -267,15 +267,15 @@
 	add		r4=8,r2                  // duplicate r2 in r4
 	add		r6=2*8,r2                // duplicate r2 in r4
 
-	mov		r3=cr0                      // cr.dcr
-	mov		r5=cr1                      // cr.itm
-	mov		r7=cr2;;                    // cr.iva
+	mov		r3=cr.dcr
+	mov		r5=cr.itm
+	mov		r7=cr.iva;;
 
 	st8		[r2]=r3,8*8
 	st8		[r4]=r5,3*8
 	st8		[r6]=r7,3*8;;            // 48 byte rements
 
-	mov		r3=cr8;;                    // cr.pta
+	mov		r3=cr.pta;;
 	st8		[r2]=r3,8*8;;            // 64 byte rements
 
 // if PSR.ic=0, reading interruption registers causes an illegal operation fault
@@ -288,23 +288,23 @@
 	add		r4=8,r2                  // duplicate r2 in r4
 	add		r6=2*8,r2                // duplicate r2 in r6
 
-	mov		r3=cr16                     // cr.ipsr
-	mov		r5=cr17                     // cr.isr
-        mov     r7=r0;;                     // cr.ida => cr18 (reserved)
+	mov		r3=cr.ipsr
+	mov		r5=cr.isr
+	mov		r7=r0;;
 	st8		[r2]=r3,3*8
 	st8		[r4]=r5,3*8
 	st8		[r6]=r7,3*8;;
 
-	mov		r3=cr19                     // cr.iip
-	mov		r5=cr20                     // cr.idtr
-	mov		r7=cr21;;                   // cr.iitr
+	mov		r3=cr.iip
+	mov		r5=cr.ifa
+	mov		r7=cr.itir;;
 	st8		[r2]=r3,3*8
 	st8		[r4]=r5,3*8
 	st8		[r6]=r7,3*8;;
 
-	mov		r3=cr22                     // cr.iipa
-	mov		r5=cr23                     // cr.ifs
-	mov		r7=cr24;;                   // cr.iim
+	mov		r3=cr.iipa
+	mov		r5=cr.ifs
+	mov		r7=cr.iim;;
 	st8		[r2]=r3,3*8
 	st8		[r4]=r5,3*8
 	st8		[r6]=r7,3*8;;
@@ -313,104 +313,101 @@
 	st8		[r2]=r3,160;;               // 160 byte rement
 
 SkipIntrRegs:
-	st8		[r2]=r0,168                 // another 168 byte .
+	st8		[r2]=r0,152;;               // another 152 byte .
 
-	mov		r3=cr66;;                   // cr.lid
-	st8		[r2]=r3,40                  // 40 byte rement
+	add		r4=8,r2                     // duplicate r2 in r4
+	add		r6=2*8,r2                   // duplicate r2 in r6
 
-	mov		r3=cr71;;                   // cr.ivr
-	st8		[r2]=r3,8
-
-	mov		r3=cr72;;                   // cr.tpr
-	st8		[r2]=r3,24                  // 24 byte increment
-
-	mov		r3=r0;;                     // cr.eoi => cr75
-	st8		[r2]=r3,168                 // 168 byte inc.
-
-	mov		r3=r0;;                     // cr.irr0 => cr96
-	st8		[r2]=r3,16               // 16 byte inc.
-
-	mov		r3=r0;;                     // cr.irr1 => cr98
-	st8		[r2]=r3,16               // 16 byte inc.
-
-	mov		r3=r0;;                     // cr.irr2 => cr100
-	st8		[r2]=r3,16               // 16 byte inc
-
-	mov		r3=r0;;                     // cr.irr3 => cr100
-	st8		[r2]=r3,16               // 16b inc.
-
-	mov		r3=r0;;                     // cr.itv => cr114
-	st8		[r2]=r3,16               // 16 byte inc.
+	mov		r3=cr.lid
+//	mov		r5=cr.ivr                     // cr.ivr, don't read it
+	mov		r7=cr.tpr;;
+	st8		[r2]=r3,3*8
+	st8		[r4]=r5,3*8
+	st8		[r6]=r7,3*8;;
 
-	mov		r3=r0;;                     // cr.pmv => cr116
-	st8		[r2]=r3,8
+	mov		r3=r0                       // cr.eoi => cr67
+	mov		r5=r0                       // cr.irr0 => cr68
+	mov		r7=r0;;                     // cr.irr1 => cr69
+	st8		[r2]=r3,3*8
+	st8		[r4]=r5,3*8
+	st8		[r6]=r7,3*8;;
 
-	mov		r3=r0;;                     // cr.lrr0 => cr117
-	st8		[r2]=r3,8
+	mov		r3=r0                       // cr.irr2 => cr70
+	mov		r5=r0                       // cr.irr3 => cr71
+	mov		r7=cr.itv;;
+	st8		[r2]=r3,3*8
+	st8		[r4]=r5,3*8
+	st8		[r6]=r7,3*8;;
 
-	mov		r3=r0;;                     // cr.lrr1 => cr118
-	st8		[r2]=r3,8
+	mov		r3=cr.pmv
+	mov		r5=cr.cmcv;;
+	st8		[r2]=r3,7*8
+	st8		[r4]=r5,7*8;;
+
+	mov		r3=r0                       // cr.lrr0 => cr80
+	mov		r5=r0;;                     // cr.lrr1 => cr81
+	st8		[r2]=r3,23*8
+	st8		[r4]=r5,23*8;;
 
-	mov		r3=r0;;                     // cr.cmcv => cr119
-	st8		[r2]=r3,8*10;;
+	adds		r2=25*8,r2;;
 
 cSaveARs:
 // save ARs
 	add		r4=8,r2                  // duplicate r2 in r4
 	add		r6=2*8,r2                // duplicate r2 in r6
 
-	mov		r3=ar0                      // ar.kro
-	mov		r5=ar1                      // ar.kr1
-	mov		r7=ar2;;                    // ar.kr2
+	mov		r3=ar.k0
+	mov		r5=ar.k1
+	mov		r7=ar.k2;;
 	st8		[r2]=r3,3*8
 	st8		[r4]=r5,3*8
 	st8		[r6]=r7,3*8;;
 
-	mov		r3=ar3                      // ar.kr3
-	mov		r5=ar4                      // ar.kr4
-	mov		r7=ar5;;                    // ar.kr5
+	mov		r3=ar.k3
+	mov		r5=ar.k4
+	mov		r7=ar.k5;;
 	st8		[r2]=r3,3*8
 	st8		[r4]=r5,3*8
 	st8		[r6]=r7,3*8;;
 
-	mov		r3=ar6                      // ar.kr6
-	mov		r5=ar7                      // ar.kr7
+	mov		r3=ar.k6
+	mov		r5=ar.k7
 	mov		r7=r0;;                     // ar.kr8
 	st8		[r2]=r3,10*8
 	st8		[r4]=r5,10*8
 	st8		[r6]=r7,10*8;;           // rement by 72 bytes
 
-	mov		r3=ar16                     // ar.rsc
-	mov		ar16=r0			    // put RSE in enforced lazy mode
-	mov		r5=ar17                     // ar.bsp
+	mov		r3=ar.rsc
+	mov		ar.rsc=r0			    // put RSE in enforced lazy mode
+	mov		r5=ar.bsp
 	;;
-	mov		r7=ar18;;                   // ar.bspstore
+	mov		r7=ar.bspstore;;
 	st8		[r2]=r3,3*8
 	st8		[r4]=r5,3*8
 	st8		[r6]=r7,3*8;;
 
-	mov		r3=ar19;;                   // ar.rnat
+	mov		r3=ar.rnat;;
 	st8		[r2]=r3,8*13             // increment by 13x8 bytes
 
-	mov		r3=ar32;;                   // ar.ccv
+	mov		r3=ar.ccv;;
 	st8		[r2]=r3,8*4
 
-	mov		r3=ar36;;                   // ar.unat
+	mov		r3=ar.unat;;
 	st8		[r2]=r3,8*4
 
-	mov		r3=ar40;;                   // ar.fpsr
+	mov		r3=ar.fpsr;;
 	st8		[r2]=r3,8*4
 
-	mov		r3=ar44;;                   // ar.itc
+	mov		r3=ar.itc;;
 	st8		[r2]=r3,160                 // 160
 
-	mov		r3=ar64;;                   // ar.pfs
+	mov		r3=ar.pfs;;
 	st8		[r2]=r3,8
 
-	mov		r3=ar65;;                   // ar.lc
+	mov		r3=ar.lc;;
 	st8		[r2]=r3,8
 
-	mov		r3=ar66;;                   // ar.ec
+	mov		r3=ar.ec;;
 	st8		[r2]=r3
 	add		r2=8*62,r2               //padding
 
@@ -419,7 +416,8 @@
 	movl		r4=0x00;;
 
 cStRR:
-	mov		r3=rr[r4];;
+	dep.z		r5=r4,61,3;;
+	mov		r3=rr[r5];;
 	st8		[r2]=r3,8
 	add		r4=1,r4
 	br.cloop.sptk.few	cStRR
@@ -503,12 +501,12 @@
 	ld8		r3=[r2],8*8
 	ld8		r5=[r4],3*8
 	ld8		r7=[r6],3*8;;            // 48 byte increments
-	mov		cr0=r3                      // cr.dcr
-	mov		cr1=r5                      // cr.itm
-	mov		cr2=r7;;                    // cr.iva
+	mov		cr.dcr=r3
+	mov		cr.itm=r5
+	mov		cr.iva=r7;;
 
 	ld8		r3=[r2],8*8;;            // 64 byte increments
-//      mov		cr8=r3                      // cr.pta
+//      mov		cr.pta=r3
 
 
 // if PSR.ic=1, reading interruption registers causes an illegal operation fault
@@ -525,64 +523,66 @@
 	ld8		r3=[r2],3*8
 	ld8		r5=[r4],3*8
 	ld8		r7=[r6],3*8;;
-	mov		cr16=r3                     // cr.ipsr
-	mov		cr17=r5                     // cr.isr is read only
-//      mov     cr18=r7;;                   // cr.ida (reserved - don't restore)
+	mov		cr.ipsr=r3
+//	mov		cr.isr=r5                   // cr.isr is read only
 
 	ld8		r3=[r2],3*8
 	ld8		r5=[r4],3*8
 	ld8		r7=[r6],3*8;;
-	mov		cr19=r3                     // cr.iip
-	mov		cr20=r5                     // cr.idtr
-	mov		cr21=r7;;                   // cr.iitr
+	mov		cr.iip=r3
+	mov		cr.ifa=r5
+	mov		cr.itir=r7;;
 
 	ld8		r3=[r2],3*8
 	ld8		r5=[r4],3*8
 	ld8		r7=[r6],3*8;;
-	mov		cr22=r3                     // cr.iipa
-	mov		cr23=r5                     // cr.ifs
-	mov		cr24=r7                     // cr.iim
+	mov		cr.iipa=r3
+	mov		cr.ifs=r5
+	mov		cr.iim=r7
 
 	ld8		r3=[r2],160;;               // 160 byte increment
-	mov		cr25=r3                     // cr.iha
+	mov		cr.iha=r3
 
 rSkipIntrRegs:
-	ld8		r3=[r2],168;;               // another 168 byte inc.
-
-	ld8		r3=[r2],40;;                // 40 byte increment
-	mov		cr66=r3                     // cr.lid
-
-	ld8		r3=[r2],8;;
-//      mov		cr71=r3                     // cr.ivr is read only
-	ld8		r3=[r2],24;;                // 24 byte increment
-	mov		cr72=r3                     // cr.tpr
-
-	ld8		r3=[r2],168;;               // 168 byte inc.
-//      mov		cr75=r3                     // cr.eoi
+	ld8		r3=[r2],152;;               // another 152 byte inc.
 
-	ld8		r3=[r2],16;;             // 16 byte inc.
-//      mov		cr96=r3                     // cr.irr0 is read only
+	add		r4=8,r2                     // duplicate r2 in r4
+	add		r6=2*8,r2;;                 // duplicate r2 in r6
 
-	ld8		r3=[r2],16;;             // 16 byte inc.
-//      mov		cr98=r3                     // cr.irr1 is read only
+	ld8		r3=[r2],8*3
+	ld8		r5=[r4],8*3
+	ld8		r7=[r6],8*3;;
+	mov		cr.lid=r3
+//	mov		cr.ivr=r5                   // cr.ivr is read only
+	mov		cr.tpr=r7;;
+
+	ld8		r3=[r2],8*3
+	ld8		r5=[r4],8*3
+	ld8		r7=[r6],8*3;;
+//	mov		cr.eoi=r3
+//	mov		cr.irr0=r5                  // cr.irr0 is read only
+//	mov		cr.irr1=r7;;                // cr.irr1 is read only
+
+	ld8		r3=[r2],8*3
+	ld8		r5=[r4],8*3
+	ld8		r7=[r6],8*3;;
+//	mov		cr.irr2=r3                  // cr.irr2 is read only
+//	mov		cr.irr3=r5                  // cr.irr3 is read only
+	mov		cr.itv=r7;;
+
+	ld8		r3=[r2],8*7
+	ld8		r5=[r4],8*7;;
+	mov		cr.pmv=r3
+	mov		cr.cmcv=r5;;
+
+	ld8		r3=[r2],8*23
+	ld8		r5=[r4],8*23;;
+	adds		r2=8*23,r2
+	adds		r4=8*23,r4;;
+//	mov		cr.lrr0=r3
+//	mov		cr.lrr1=r5
 
-	ld8		r3=[r2],16;;             // 16 byte inc
-//      mov		cr100=r3                    // cr.irr2 is read only
-
-	ld8		r3=[r2],16;;             // 16b inc.
-//      mov		cr102=r3                    // cr.irr3 is read only
-
-	ld8		r3=[r2],16;;             // 16 byte inc.
-//      mov		cr114=r3                    // cr.itv
-
-	ld8		r3=[r2],8;;
-//      mov		cr116=r3                    // cr.pmv
-	ld8		r3=[r2],8;;
-//      mov		cr117=r3                    // cr.lrr0
-	ld8		r3=[r2],8;;
-//      mov		cr118=r3                    // cr.lrr1
-	ld8		r3=[r2],8*10;;
-//      mov		cr119=r3                    // cr.cmcv
+	adds		r2=8*2,r2;;
 
 restore_ARs:
 	add		r4=8,r2                  // duplicate r2 in r4
@@ -591,67 +591,67 @@
 	ld8		r3=[r2],3*8
 	ld8		r5=[r4],3*8
 	ld8		r7=[r6],3*8;;
-	mov		ar0=r3                      // ar.kro
-	mov		ar1=r5                      // ar.kr1
-	mov		ar2=r7;;                    // ar.kr2
+	mov		ar.k0=r3
+	mov		ar.k1=r5
+	mov		ar.k2=r7;;
 
 	ld8		r3=[r2],3*8
 	ld8		r5=[r4],3*8
 	ld8		r7=[r6],3*8;;
-	mov		ar3=r3                      // ar.kr3
-	mov		ar4=r5                      // ar.kr4
-	mov		ar5=r7;;                    // ar.kr5
+	mov		ar.k3=r3
+	mov		ar.k4=r5
+	mov		ar.k5=r7;;
 
 	ld8		r3=[r2],10*8
 	ld8		r5=[r4],10*8
 	ld8		r7=[r6],10*8;;
-	mov		ar6=r3                      // ar.kr6
-	mov		ar7=r5                      // ar.kr7
-//      mov		ar8=r6                      // ar.kr8
+	mov		ar.k6=r3
+	mov		ar.k7=r5
 	;;
 
 	ld8		r3=[r2],3*8
 	ld8		r5=[r4],3*8
 	ld8		r7=[r6],3*8;;
-//      mov		ar16=r3                     // ar.rsc
-//      mov		ar17=r5                     // ar.bsp is read only
-	mov		ar16=r0			    // make sure that RSE is in enforced lazy mode
+//	mov		ar.rsc=r3
+//	mov		ar.bsp=r5                   // ar.bsp is read only
+	mov		ar.rsc=r0			    // make sure that RSE is in enforced lazy mode
 	;;
-	mov		ar18=r7;;                   // ar.bspstore
+	mov		ar.bspstore=r7;;
 
 	ld8		r9=[r2],8*13;;
-	mov		ar19=r9                     // ar.rnat
+	mov		ar.rnat=r9
 
-	mov		ar16=r3			    // ar.rsc
+	mov		ar.rsc=r3
 	ld8		r3=[r2],8*4;;
-	mov		ar32=r3                     // ar.ccv
+	mov		ar.ccv=r3
 
 	ld8		r3=[r2],8*4;;
-	mov		ar36=r3                     // ar.unat
+	mov		ar.unat=r3
 
 	ld8		r3=[r2],8*4;;
-	mov		ar40=r3                     // ar.fpsr
+	mov		ar.fpsr=r3
 
 	ld8		r3=[r2],160;;               // 160
-//      mov		ar44=r3                     // ar.itc
+//      mov		ar.itc=r3
 
 	ld8		r3=[r2],8;;
-	mov		ar64=r3                     // ar.pfs
+	mov		ar.pfs=r3
 
 	ld8		r3=[r2],8;;
-	mov		ar65=r3                     // ar.lc
+	mov		ar.lc=r3
 
 	ld8		r3=[r2];;
-	mov		ar66=r3                     // ar.ec
+	mov		ar.ec=r3
 	add		r2=8*62,r2;;             // padding
 
 restore_RRs:
 	mov		r5=ar.lc
 	mov		ar.lc=0x08-1
-	movl		r4=0x00
+	movl		r4=0x00;;
 cStRRr:
+	dep.z		r7=r4,61,3
 	ld8		r3=[r2],8;;
-//      mov		rr[r4]=r3                   // what are its access previledges?
+	mov		rr[r7]=r3                   // what are its access previledges?
 	add		r4=1,r4
 	br.cloop.sptk.few	cStRRr
 	;;
diff -urN linux-2.4.23-bk3/arch/ia64/kernel/pci.c linux-2.4.23-bk4/arch/ia64/kernel/pci.c
--- linux-2.4.23-bk3/arch/ia64/kernel/pci.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/kernel/pci.c	2003-12-06 02:49:48.000000000 -0800
@@ -523,8 +523,6 @@
 	if (ret < 0)
 		return ret;
 
- 	platform_pci_enable_device(dev);
-
 	printk(KERN_INFO "PCI: Found IRQ %d for device %s\n", dev->irq, dev->slot_name);
 
 	return 0;
diff -urN linux-2.4.23-bk3/arch/ia64/kernel/perfmon.c linux-2.4.23-bk4/arch/ia64/kernel/perfmon.c
--- linux-2.4.23-bk3/arch/ia64/kernel/perfmon.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/kernel/perfmon.c	2003-12-06 02:49:48.000000000 -0800
@@ -4013,6 +4013,10 @@
 	if (CTX_INHERIT_MODE(ctx) == PFM_FL_INHERIT_ONCE) {
 		nctx->ctx_fl_inherit = PFM_FL_INHERIT_NONE;
 		DBprintk(("downgrading to INHERIT_NONE for [%d]\n", task->pid));
+		/*
+		 * downgrade parent: once means only first child!
+		 */
+		ctx->ctx_fl_inherit = PFM_FL_INHERIT_NONE;
 	}
 	/*
 	 * task is not yet visible in the tasklist, so we do 
diff -urN linux-2.4.23-bk3/arch/ia64/kernel/salinfo.c linux-2.4.23-bk4/arch/ia64/kernel/salinfo.c
--- linux-2.4.23-bk3/arch/ia64/kernel/salinfo.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/kernel/salinfo.c	2003-12-06 02:49:48.000000000 -0800
@@ -3,19 +3,29 @@
  *
  * Creates entries in /proc/sal for various system features.
  *
- * Copyright (c) 2001 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All rights reserved.
  * Copyright (c) 2003 Hewlett-Packard Co
  *	Bjorn Helgaas <bjorn.helgaas@hp.com>
  *
  * 10/30/2001	jbarnes@sgi.com		copied much of Stephane's palinfo
  *					code to create this file
+ * Oct 23 2003	kaos@sgi.com
+ *   Replace IPI with set_cpus_allowed() to read a record from the required cpu.
+ *   Redesign salinfo log processing to separate interrupt and user space
+ *   contexts.
+ *   Cache the record across multi-block reads from user space.
+ *   Support > 64 cpus.
+ *   Delete module_exit and MOD_INC/DEC_COUNT, salinfo cannot be a module.
  */
 
 #include <linux/types.h>
 #include <linux/proc_fs.h>
 #include <linux/module.h>
 #include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/vmalloc.h>
 
+#include <asm/semaphore.h>
 #include <asm/sal.h>
 #include <asm/uaccess.h>
 
@@ -57,48 +67,175 @@
 	(2 * ARRAY_SIZE(salinfo_log_name)) +		/* /proc/sal/mca/{event,data} */
 	1];						/* /proc/sal */
 
-struct salinfo_log_data {
-	int	type;
-	u8	*log_buffer;
-	u64	log_size;
-};
+/* Allow build with or without large SSI support */
+#ifdef CPU_MASK_NONE
+#define SCA(x, y) set_cpus_allowed((x), &(y))
+#else
+#define cpumask_t unsigned long
+#define SCA(x, y) set_cpus_allowed((x), (y))
+#endif
 
-struct salinfo_event {
-	int			type;
-	int			cpu;		/* next CPU to check */
-	volatile unsigned long	cpu_mask;
-	wait_queue_head_t	queue;
+/* Some records we get ourselves, some are accessed as saved data in buffers
+ * that are owned by mca.c.
+ */
+struct salinfo_data_saved {
+	u8*			buffer;
+	u64			size;
+	u64			id;
+	int			cpu;
 };
 
-static struct salinfo_event *salinfo_event[ARRAY_SIZE(salinfo_log_name)];
+/* State transitions.  Actions are :-
+ *   Write "read <cpunum>" to the data file.
+ *   Write "clear <cpunum>" to the data file.
+ *   Write "oemdata <cpunum> <offset> to the data file.
+ *   Read from the data file.
+ *   Close the data file.
+ *
+ * Start state is NO_DATA.
+ *
+ * NO_DATA
+ *    write "read <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "clear <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "oemdata <cpunum> <offset> -> return -EINVAL.
+ *    read data -> return EOF.
+ *    close -> unchanged.  Free record areas.
+ *
+ * LOG_RECORD
+ *    write "read <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "clear <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "oemdata <cpunum> <offset> -> format the oem data, goto OEMDATA.
+ *    read data -> return the INIT/MCA/CMC/CPE record.
+ *    close -> unchanged.  Keep record areas.
+ *
+ * OEMDATA
+ *    write "read <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "clear <cpunum>" -> NO_DATA or LOG_RECORD.
+ *    write "oemdata <cpunum> <offset> -> format the oem data, goto OEMDATA.
+ *    read data -> return the formatted oemdata.
+ *    close -> unchanged.  Keep record areas.
+ *
+ * Closing the data file does not change the state.  This allows shell scripts
+ * to manipulate salinfo data, each shell redirection opens the file, does one
+ * action then closes it again.  The record areas are only freed at close when
+ * the state is NO_DATA.
+ */
+enum salinfo_state {
+	STATE_NO_DATA,
+	STATE_LOG_RECORD,
+	STATE_OEMDATA,
+};
 
 struct salinfo_data {
-	int	open;		/* single-open to prevent races */
-	int	type;
-	int	cpu;		/* "current" cpu for reads */
+	volatile cpumask_t	cpu_event;	/* which cpus have outstanding events */
+	struct semaphore	sem;		/* count of cpus with outstanding events (bits set in cpu_event) */
+	u8			*log_buffer;
+	u64			log_size;
+	u8			*oemdata;	/* decoded oem data */
+	u64			oemdata_size;
+	int			open;		/* single-open to prevent races */
+	u8			type;
+	u8			saved_num;	/* using a saved record? */
+	enum salinfo_state	state :8;	/* processing state */
+	u8			padding;
+	int			cpu_check;	/* next CPU to check */
+	struct salinfo_data_saved data_saved[5];/* save last 5 records from mca.c, must be < 255 */
 };
 
 static struct salinfo_data salinfo_data[ARRAY_SIZE(salinfo_log_name)];
 
-static spinlock_t data_lock;
+static spinlock_t data_lock, data_saved_lock;
+
+/** salinfo_platform_oemdata - optional callback to decode oemdata from an error
+ * record.
+ * @sect_header: pointer to the start of the section to decode.
+ * @oemdata: returns vmalloc area containing the decded output.
+ * @oemdata_size: returns length of decoded output (strlen).
+ *
+ * Description: If user space asks for oem data to be decoded by the kernel
+ * and/or prom and the platform has set salinfo_platform_oemdata to the address
+ * of a platform specific routine then call that routine.  salinfo_platform_oemdata
+ * vmalloc's and formats its output area, returning the address of the text
+ * and its strlen.  Returns 0 for success, -ve for error.  The callback is
+ * invoked on the cpu that generated the error record.
+ */
+int (*salinfo_platform_oemdata)(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size);
+
+struct salinfo_platform_oemdata_parms {
+	const u8 *efi_guid;
+	u8 **oemdata;
+	u64 *oemdata_size;
+	int ret;
+};
+
+static void
+salinfo_platform_oemdata_cpu(void *context)
+{
+	struct salinfo_platform_oemdata_parms *parms = context;
+	parms->ret = salinfo_platform_oemdata(parms->efi_guid, parms->oemdata, parms->oemdata_size);
+}
 
+static void
+shift1_data_saved (struct salinfo_data *data, int shift)
+{
+	memcpy(data->data_saved+shift, data->data_saved+shift+1,
+	       (ARRAY_SIZE(data->data_saved) - (shift+1)) * sizeof(data->data_saved[0]));
+	memset(data->data_saved + ARRAY_SIZE(data->data_saved) - 1, 0,
+	       sizeof(data->data_saved[0]));
+}
+
+/* This routine is invoked in interrupt context.  Note: mca.c enables
+ * interrupts before calling this code for CMC/CPE.  MCA and INIT events are
+ * not irq safe, do not call any routines that use spinlocks, they may deadlock.
+ *
+ * The buffer passed from mca.c points to the output from ia64_log_get. This is
+ * a persistent buffer but its contents can change between the interrupt and
+ * when user space processes the record.  Save the record id to identify
+ * changes.
+ */
 void
-salinfo_log_wakeup(int type)
+salinfo_log_wakeup(int type, u8 *buffer, u64 size)
 {
-	if (type < ARRAY_SIZE(salinfo_log_name)) {
-		struct salinfo_event *event = salinfo_event[type];
+	struct salinfo_data *data = salinfo_data + type;
+	struct salinfo_data_saved *data_saved;
+	unsigned long flags = 0;
+	int i, irqsafe = type != SAL_INFO_TYPE_MCA && type != SAL_INFO_TYPE_INIT;
+	int saved_size = ARRAY_SIZE(data->data_saved);
+
+	BUG_ON(type >= ARRAY_SIZE(salinfo_log_name));
+
+	if (irqsafe)
+		spin_lock_irqsave(&data_saved_lock, flags);
+	for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
+		if (!data_saved->buffer)
+			break;
+	}
+	if (i == saved_size) {
+		if (!data->saved_num) {
+			shift1_data_saved(data, 0);
+			data_saved = data->data_saved + saved_size - 1;
+		} else
+			data_saved = NULL;
+	}
+	if (data_saved) {
+		data_saved->cpu = smp_processor_id();
+		data_saved->id = ((sal_log_record_header_t *)buffer)->id;
+		data_saved->size = size;
+		data_saved->buffer = buffer;
+	}
+	if (irqsafe)
+		spin_unlock_irqrestore(&data_saved_lock, flags);
 
-		if (event) {
-			set_bit(smp_processor_id(), &event->cpu_mask);
-			wake_up_interruptible(&event->queue);
-		}
+	if (!test_and_set_bit(smp_processor_id(), &data->cpu_event)) {
+		if (irqsafe)
+			up(&data->sem);
 	}
 }
 
 static int
 salinfo_event_open(struct inode *inode, struct file *file)
 {
-	if (!suser())
+	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	return 0;
 }
@@ -107,24 +244,23 @@
 salinfo_event_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct inode *inode = file->f_dentry->d_inode;
-	struct proc_dir_entry *entry = (struct proc_dir_entry *) inode->u.generic_ip;
-	struct salinfo_event *event = entry->data;
+	struct proc_dir_entry *entry = PDE(inode);
+	struct salinfo_data *data = entry->data;
 	char cmd[32];
 	size_t size;
 	int i, n, cpu = -1;
 
 retry:
-	if (!event->cpu_mask) {
+	if (down_trylock(&data->sem)) {
 		if (file->f_flags & O_NONBLOCK)
 			return -EAGAIN;
-		interruptible_sleep_on(&event->queue);
-		if (signal_pending(current))
-			return -EINTR;
+		if (down_interruptible(&data->sem))
+			return -ERESTARTSYS;
 	}
 
-	n = event->cpu;
+	n = data->cpu_check;
 	for (i = 0; i < NR_CPUS; i++) {
-		if (event->cpu_mask & 1UL << n) {
+		if (test_bit(n, &data->cpu_event)) {
 			cpu = n;
 			break;
 		}
@@ -135,10 +271,13 @@
 	if (cpu == -1)
 		goto retry;
 
+	/* events are sticky until the user says "clear" */
+	up(&data->sem);
+
 	/* for next read, start checking at next CPU */
-	event->cpu = cpu;
-	if (++event->cpu == NR_CPUS)
-		event->cpu = 0;
+	data->cpu_check = cpu;
+	if (++data->cpu_check == NR_CPUS)
+		data->cpu_check = 0;
 
 	snprintf(cmd, sizeof(cmd), "read %d\n", cpu);
 
@@ -159,10 +298,10 @@
 static int
 salinfo_log_open(struct inode *inode, struct file *file)
 {
-	struct proc_dir_entry *entry = (struct proc_dir_entry *) inode->u.generic_ip;
+	struct proc_dir_entry *entry = PDE(inode);
 	struct salinfo_data *data = entry->data;
 
-	if (!suser())
+	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
 	spin_lock(&data_lock);
@@ -173,15 +312,27 @@
 	data->open = 1;
 	spin_unlock(&data_lock);
 
+	if (data->state == STATE_NO_DATA &&
+	    !(data->log_buffer = vmalloc(ia64_sal_get_state_info_size(data->type)))) {
+		data->open = 0;
+		return -ENOMEM;
+	}
+
 	return 0;
 }
 
 static int
 salinfo_log_release(struct inode *inode, struct file *file)
 {
-	struct proc_dir_entry *entry = (struct proc_dir_entry *) inode->u.generic_ip;
+	struct proc_dir_entry *entry = PDE(inode);
 	struct salinfo_data *data = entry->data;
 
+	if (data->state == STATE_NO_DATA) {
+		vfree(data->log_buffer);
+		vfree(data->oemdata);
+		data->log_buffer = NULL;
+		data->oemdata = NULL;
+	}
 	spin_lock(&data_lock);
 	data->open = 0;
 	spin_unlock(&data_lock);
@@ -191,95 +342,131 @@
 static void
 call_on_cpu(int cpu, void (*fn)(void *), void *arg)
 {
-	if (cpu == smp_processor_id())
-		(*fn)(arg);
-#ifdef CONFIG_SMP
-	else if (cpu_online(cpu))	/* cpu may not have been validated */
-		smp_call_function_single(cpu, fn, arg, 0, 1);
-#endif
+	cpumask_t save_cpus_allowed, new_cpus_allowed;
+	memcpy(&save_cpus_allowed, &current->cpus_allowed, sizeof(save_cpus_allowed));
+	memset(&new_cpus_allowed, 0, sizeof(new_cpus_allowed));
+	set_bit(cpu, &new_cpus_allowed);
+	SCA(current, new_cpus_allowed);
+	(*fn)(arg);
+	SCA(current, save_cpus_allowed);
 }
 
 static void
 salinfo_log_read_cpu(void *context)
 {
-	struct salinfo_log_data *info = context;
-	struct salinfo_event *event = salinfo_event[info->type];
-	u64 size;
-
-	size = ia64_sal_get_state_info_size(info->type);
-	info->log_buffer = kmalloc(size, GFP_ATOMIC);
-	if (!info->log_buffer)
-		return;
-
-	clear_bit(smp_processor_id(), &event->cpu_mask);
-	info->log_size = ia64_sal_get_state_info(info->type, (u64 *) info->log_buffer);
-	if (info->log_size)
-		salinfo_log_wakeup(info->type);
+	struct salinfo_data *data = context;
+	data->log_size = ia64_sal_get_state_info(data->type, (u64 *) data->log_buffer);
+}
+
+static void
+salinfo_log_new_read(int cpu, struct salinfo_data *data)
+{
+	struct salinfo_data_saved *data_saved;
+	unsigned long flags;
+	int i;
+	int saved_size = ARRAY_SIZE(data->data_saved);
+
+	data->saved_num = 0;
+	spin_lock_irqsave(&data_saved_lock, flags);
+retry:
+	for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
+		if (data_saved->buffer && data_saved->cpu == cpu) {
+			sal_log_record_header_t *rh = (sal_log_record_header_t *)(data_saved->buffer);
+			data->log_size = data_saved->size;
+			memcpy(data->log_buffer, rh, data->log_size);
+			barrier();	/* id check must not be moved */
+			if (rh->id == data_saved->id) {
+				data->saved_num = i+1;
+				break;
+			}
+			/* saved record changed by mca.c since interrupt, discard it */
+			shift1_data_saved(data, i);
+			goto retry;
+		}
+	}
+	spin_unlock_irqrestore(&data_saved_lock, flags);
+
+	if (!data->saved_num)
+		call_on_cpu(cpu, salinfo_log_read_cpu, data);
+	data->state = data->log_size ? STATE_LOG_RECORD : STATE_NO_DATA;
 }
 
 static ssize_t
 salinfo_log_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct inode *inode = file->f_dentry->d_inode;
-	struct proc_dir_entry *entry = (struct proc_dir_entry *) inode->u.generic_ip;
+	struct proc_dir_entry *entry = PDE(inode);
 	struct salinfo_data *data = entry->data;
-	struct salinfo_log_data info;
-	int ret;
 	void *saldata;
 	size_t size;
+	u8 *buf;
+	u64 bufsize;
 
-	info.type = data->type;
-	info.log_buffer = 0;
-	call_on_cpu(data->cpu, salinfo_log_read_cpu, &info);
-	if (!info.log_buffer || *ppos >= info.log_size) {
-		ret = 0;
-		goto out;
+	if (data->state == STATE_LOG_RECORD) {
+		buf = data->log_buffer;
+		bufsize = data->log_size;
+	} else if (data->state == STATE_OEMDATA) {
+		buf = data->oemdata;
+		bufsize = data->oemdata_size;
+	} else {
+		buf = NULL;
+		bufsize = 0;
 	}
+	if (*ppos >= bufsize)
+		return 0;
 
-	saldata = info.log_buffer + file->f_pos;
-	size = info.log_size - file->f_pos;
+	saldata = buf + file->f_pos;
+	size = bufsize - file->f_pos;
 	if (size > count)
 		size = count;
-	if (copy_to_user(buffer, saldata, size)) {
-		ret = -EFAULT;
-		goto out;
-	}
+	if (copy_to_user(buffer, saldata, size))
+		return -EFAULT;
 
 	*ppos += size;
-	ret = size;
-
-out:
-	kfree(info.log_buffer);
-	return ret;
+	return size;
 }
 
 static void
 salinfo_log_clear_cpu(void *context)
 {
 	struct salinfo_data *data = context;
-	struct salinfo_event *event = salinfo_event[data->type];
-	struct salinfo_log_data info;
-
-	clear_bit(smp_processor_id(), &event->cpu_mask);
 	ia64_sal_clear_state_info(data->type);
+}
 
-	/* clearing one record may make another visible */
-	info.type = data->type;
-	salinfo_log_read_cpu(&info);
-	if (info.log_buffer && info.log_size)
-		salinfo_log_wakeup(data->type);
+static int
+salinfo_log_clear(struct salinfo_data *data, int cpu)
+{
+	data->state = STATE_NO_DATA;
+	if (!test_bit(cpu, &data->cpu_event))
+		return 0;
+	down(&data->sem);
+	clear_bit(cpu, &data->cpu_event);
+	if (data->saved_num) {
+		unsigned long flags;
+		spin_lock_irqsave(&data_saved_lock, flags);
+		shift1_data_saved(data, data->saved_num - 1 );
+		data->saved_num = 0;
+		spin_unlock_irqrestore(&data_saved_lock, flags);
+	}
+	call_on_cpu(cpu, salinfo_log_clear_cpu, data);
 
-	kfree(info.log_buffer);
+	/* clearing a record may make a new record visible */
+	salinfo_log_new_read(cpu, data);
+	if (data->state == STATE_LOG_RECORD &&
+	    !test_and_set_bit(cpu,  &data->cpu_event))
+		up(&data->sem);
+	return 0;
 }
 
 static ssize_t
 salinfo_log_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct inode *inode = file->f_dentry->d_inode;
-	struct proc_dir_entry *entry = (struct proc_dir_entry *) inode->u.generic_ip;
+	struct proc_dir_entry *entry = PDE(inode);
 	struct salinfo_data *data = entry->data;
 	char cmd[32];
 	size_t size;
+	u32 offset;
 	int cpu;
 
 	size = sizeof(cmd);
@@ -288,10 +475,31 @@
 	if (copy_from_user(cmd, buffer, size))
 		return -EFAULT;
 
-	if (sscanf(cmd, "read %d", &cpu) == 1)
-		data->cpu = cpu;
-	else if (sscanf(cmd, "clear %d", &cpu) == 1)
-		call_on_cpu(cpu, salinfo_log_clear_cpu, data);
+	if (sscanf(cmd, "read %d", &cpu) == 1) {
+		salinfo_log_new_read(cpu, data);
+	} else if (sscanf(cmd, "clear %d", &cpu) == 1) {
+		int ret;
+		if ((ret = salinfo_log_clear(data, cpu)))
+			count = ret;
+	} else if (sscanf(cmd, "oemdata %d %d", &cpu, &offset) == 2) {
+		if (data->state != STATE_LOG_RECORD && data->state != STATE_OEMDATA)
+			return -EINVAL;
+		if (offset > data->log_size - sizeof(efi_guid_t))
+			return -EINVAL;
+		data->state = STATE_OEMDATA;
+		if (salinfo_platform_oemdata) {
+			struct salinfo_platform_oemdata_parms parms = {
+				.efi_guid = data->log_buffer + offset,
+				.oemdata = &data->oemdata,
+				.oemdata_size = &data->oemdata_size
+			};
+			call_on_cpu(cpu, salinfo_platform_oemdata_cpu, &parms);
+			if (parms.ret)
+				count = parms.ret;
+		} else
+			data->oemdata_size = 0;
+	} else
+		return -EINVAL;
 
 	return count;
 }
@@ -309,9 +517,8 @@
 	struct proc_dir_entry *salinfo_dir; /* /proc/sal dir entry */
 	struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */
 	struct proc_dir_entry *dir, *entry;
-	struct salinfo_event *event;
 	struct salinfo_data *data;
-	int i, j;
+	int i, j, online;
 
 	salinfo_dir = proc_mkdir("sal", NULL);
 	if (!salinfo_dir)
@@ -324,6 +531,9 @@
 	}
 
 	for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) {
+		data = salinfo_data + i;
+		data->type = i;
+		sema_init(&data->sem, 0);
 		dir = proc_mkdir(salinfo_log_name[i], salinfo_dir);
 		if (!dir)
 			continue;
@@ -331,32 +541,26 @@
 		entry = create_proc_entry("event", S_IRUSR, dir);
 		if (!entry)
 			continue;
-
-		event = kmalloc(sizeof(*event), GFP_KERNEL);
-		if (!event)
-			continue;
-		memset(event, 0, sizeof(*event));
-		event->type = i;
-		init_waitqueue_head(&event->queue);
-		salinfo_event[i] = event;
-		/* we missed any events before now */
-		for (j = 0; j < NR_CPUS; j++)
-			if (cpu_online(j))
-				set_bit(j, &event->cpu_mask);
-		entry->data = event;
+		entry->data = data;
 		entry->proc_fops = &salinfo_event_fops;
 		*sdir++ = entry;
 
 		entry = create_proc_entry("data", S_IRUSR | S_IWUSR, dir);
 		if (!entry)
 			continue;
-
-		data = &salinfo_data[i];
-		data->type = i;
 		entry->data = data;
 		entry->proc_fops = &salinfo_data_fops;
 		*sdir++ = entry;
 
+		/* we missed any events before now */
+		online = 0;
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j)) {
+				set_bit(j, &data->cpu_event);
+				++online;
+			}
+		sema_init(&data->sem, online);
+
 		*sdir++ = dir;
 	}
 
@@ -365,17 +569,6 @@
 	return 0;
 }
 
-static void __exit
-salinfo_exit(void)
-{
-	int i = 0;
-
-	for (i = 0; i < ARRAY_SIZE(salinfo_proc_entries); i++) {
-		if (salinfo_proc_entries[i])
-			remove_proc_entry (salinfo_proc_entries[i]->name, NULL);
-	}
-}
-
 /*
  * 'data' contains an integer that corresponds to the feature we're
  * testing
@@ -385,8 +578,6 @@
 {
 	int len = 0;
 
-	MOD_INC_USE_COUNT;
-
 	len = sprintf(page, (sal_platform_features & (unsigned long)data) ? "1\n" : "0\n");
 
 	if (len <= off+count) *eof = 1;
@@ -397,10 +588,7 @@
 	if (len>count) len = count;
 	if (len<0) len = 0;
 
-	MOD_DEC_USE_COUNT;
-
 	return len;
 }
 
 module_init(salinfo_init);
-module_exit(salinfo_exit);
diff -urN linux-2.4.23-bk3/arch/ia64/kernel/setup.c linux-2.4.23-bk4/arch/ia64/kernel/setup.c
--- linux-2.4.23-bk3/arch/ia64/kernel/setup.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/kernel/setup.c	2003-12-06 02:49:48.000000000 -0800
@@ -376,7 +376,6 @@
 	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';		/* for safety */
 
 	efi_init();
-	find_memory();
 
 #ifdef CONFIG_ACPI_BOOT
 	/* Initialize the ACPI boot-time table parser */
@@ -392,6 +391,7 @@
 #endif /* CONFIG_APCI_BOOT */
 
 	iomem_resource.end = ~0UL;	/* FIXME probably belongs elsewhere */
+	find_memory();
 
 #if 0
 	/* XXX fix me */
diff -urN linux-2.4.23-bk3/arch/ia64/kernel/time.c linux-2.4.23-bk4/arch/ia64/kernel/time.c
--- linux-2.4.23-bk3/arch/ia64/kernel/time.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-bk4/arch/ia64/kernel/time.c	2003-12-06 02:49:48.000000000 -0800
@@ -93,7 +93,6 @@
 		 * it!
 		 */
 		tv->tv_usec -= gettimeoffset();
-		tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ);
 
 		while (tv->tv_usec < 0) {
 			tv->tv_usec += 1000000;
diff -urN linux-2.4.23-bk3/arch/ia64/kernel/traps.c linux-2.4.23-bk4/arch/ia64/kernel/traps.c
--- linux-2.4.23-bk3/arch/ia64/kernel/traps.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/kernel/traps.c	2003-12-06 02:49:48.000000000 -0800
@@ -221,10 +221,6 @@
 		 unsigned long arg4, unsigned long arg5, unsigned long arg6, unsigned long arg7,
 		 unsigned long stack)
 {
-	struct pt_regs *regs = (struct pt_regs *) &stack;
-
-	printk(KERN_DEBUG "%s(%d): <sc%ld(%lx,%lx,%lx,%lx)>\n", current->comm, current->pid,
-	       regs->r15, arg0, arg1, arg2, arg3);
 	return -ENOSYS;
 }
 
diff -urN linux-2.4.23-bk3/arch/ia64/lib/Makefile linux-2.4.23-bk4/arch/ia64/lib/Makefile
--- linux-2.4.23-bk3/arch/ia64/lib/Makefile	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.23-bk4/arch/ia64/lib/Makefile	2003-12-06 02:49:48.000000000 -0800
@@ -18,6 +18,7 @@
 
 obj-$(CONFIG_ITANIUM) += copy_page.o copy_user.o memcpy.o
 obj-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o
+obj-$(CONFIG_MD_RAID5) += xor.o
 
 IGNORE_FLAGS_OBJS =	__divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
 			__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o
diff -urN linux-2.4.23-bk3/arch/ia64/lib/xor.S linux-2.4.23-bk4/arch/ia64/lib/xor.S
--- linux-2.4.23-bk3/arch/ia64/lib/xor.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/lib/xor.S	2003-12-06 02:49:48.000000000 -0800
@@ -0,0 +1,184 @@
+/*
+ * arch/ia64/lib/xor.S
+ *
+ * Optimized RAID-5 checksumming functions for IA-64.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example /usr/src/linux/COPYING); if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <asm/asmmacro.h>
+
+GLOBAL_ENTRY(xor_ia64_2)
+	.prologue
+	.fframe 0
+	.save ar.pfs, r31
+	alloc r31 = ar.pfs, 3, 0, 13, 16
+	.save ar.lc, r30
+	mov r30 = ar.lc
+	.save pr, r29
+	mov r29 = pr
+	;;
+	.body
+	mov r8 = in1
+	mov ar.ec = 6 + 2
+	shr in0 = in0, 3
+	;;
+	adds in0 = -1, in0
+	mov r16 = in1
+	mov r17 = in2
+	;;
+	mov ar.lc = in0
+	mov pr.rot = 1 << 16
+	;;
+	.rotr s1[6+1], s2[6+1], d[2]
+	.rotp p[6+2]
+0:
+(p[0])	ld8.nta s1[0] = [r16], 8
+(p[0])	ld8.nta s2[0] = [r17], 8
+(p[6])	xor d[0] = s1[6], s2[6]
+(p[6+1])st8.nta [r8] = d[1], 8
+	nop.f 0
+	br.ctop.dptk.few 0b
+	;;
+	mov ar.lc = r30
+	mov pr = r29, -1
+	br.ret.sptk.few rp
+END(xor_ia64_2)
+
+GLOBAL_ENTRY(xor_ia64_3)
+	.prologue
+	.fframe 0
+	.save ar.pfs, r31
+	alloc r31 = ar.pfs, 4, 0, 20, 24
+	.save ar.lc, r30
+	mov r30 = ar.lc
+	.save pr, r29
+	mov r29 = pr
+	;;
+	.body
+	mov r8 = in1
+	mov ar.ec = 6 + 2
+	shr in0 = in0, 3
+	;;
+	adds in0 = -1, in0
+	mov r16 = in1
+	mov r17 = in2
+	;;
+	mov r18 = in3
+	mov ar.lc = in0
+	mov pr.rot = 1 << 16
+	;;
+	.rotr s1[6+1], s2[6+1], s3[6+1], d[2]
+	.rotp p[6+2]
+0:
+(p[0])	ld8.nta s1[0] = [r16], 8
+(p[0])	ld8.nta s2[0] = [r17], 8
+(p[6])	xor d[0] = s1[6], s2[6]
+	;;
+(p[0])	ld8.nta s3[0] = [r18], 8
+(p[6+1])st8.nta [r8] = d[1], 8
+(p[6])	xor d[0] = d[0], s3[6]
+	br.ctop.dptk.few 0b
+	;;
+	mov ar.lc = r30
+	mov pr = r29, -1
+	br.ret.sptk.few rp
+END(xor_ia64_3)
+
+GLOBAL_ENTRY(xor_ia64_4)
+	.prologue
+	.fframe 0
+	.save ar.pfs, r31
+	alloc r31 = ar.pfs, 5, 0, 27, 32
+	.save ar.lc, r30
+	mov r30 = ar.lc
+	.save pr, r29
+	mov r29 = pr
+	;;
+	.body
+	mov r8 = in1
+	mov ar.ec = 6 + 2
+	shr in0 = in0, 3
+	;;
+	adds in0 = -1, in0
+	mov r16 = in1
+	mov r17 = in2
+	;;
+	mov r18 = in3
+	mov ar.lc = in0
+	mov pr.rot = 1 << 16
+	mov r19 = in4
+	;;
+	.rotr s1[6+1], s2[6+1], s3[6+1], s4[6+1], d[2]
+	.rotp p[6+2]
+0:
+(p[0])	ld8.nta s1[0] = [r16], 8
+(p[0])	ld8.nta s2[0] = [r17], 8
+(p[6])	xor d[0] = s1[6], s2[6]
+(p[0])	ld8.nta s3[0] = [r18], 8
+(p[0])	ld8.nta s4[0] = [r19], 8
+(p[6])	xor r20 = s3[6], s4[6]
+	;;
+(p[6+1])st8.nta [r8] = d[1], 8
+(p[6])	xor d[0] = d[0], r20
+	br.ctop.dptk.few 0b
+	;;
+	mov ar.lc = r30
+	mov pr = r29, -1
+	br.ret.sptk.few rp
+END(xor_ia64_4)
+
+GLOBAL_ENTRY(xor_ia64_5)
+	.prologue
+	.fframe 0
+	.save ar.pfs, r31
+	alloc r31 = ar.pfs, 6, 0, 34, 40
+	.save ar.lc, r30
+	mov r30 = ar.lc
+	.save pr, r29
+	mov r29 = pr
+	;;
+	.body
+	mov r8 = in1
+	mov ar.ec = 6 + 2
+	shr in0 = in0, 3
+	;;
+	adds in0 = -1, in0
+	mov r16 = in1
+	mov r17 = in2
+	;;
+	mov r18 = in3
+	mov ar.lc = in0
+	mov pr.rot = 1 << 16
+	mov r19 = in4
+	mov r20 = in5
+	;;
+	.rotr s1[6+1], s2[6+1], s3[6+1], s4[6+1], s5[6+1], d[2]
+	.rotp p[6+2]
+0:
+(p[0])	ld8.nta s1[0] = [r16], 8
+(p[0])	ld8.nta s2[0] = [r17], 8
+(p[6])	xor d[0] = s1[6], s2[6]
+(p[0])	ld8.nta s3[0] = [r18], 8
+(p[0])	ld8.nta s4[0] = [r19], 8
+(p[6])	xor r21 = s3[6], s4[6]
+	;;
+(p[0])	ld8.nta s5[0] = [r20], 8
+(p[6+1])st8.nta [r8] = d[1], 8
+(p[6])	xor d[0] = d[0], r21
+	;;
+(p[6])	  xor d[0] = d[0], s5[6]
+	nop.f 0
+	br.ctop.dptk.few 0b
+	;;
+	mov ar.lc = r30
+	mov pr = r29, -1
+	br.ret.sptk.few rp
+END(xor_ia64_5)
diff -urN linux-2.4.23-bk3/arch/ia64/mm/init.c linux-2.4.23-bk4/arch/ia64/mm/init.c
--- linux-2.4.23-bk3/arch/ia64/mm/init.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/mm/init.c	2003-12-06 02:49:48.000000000 -0800
@@ -488,7 +488,8 @@
 {
 	char byte;
 
-	return __get_user(byte, (char *) page) == 0;
+	return     (__get_user(byte, (char *) page) == 0)
+		&& (__get_user(byte, (char *) (page + 1) - 1) == 0);
 }
 
 #define GRANULEROUNDDOWN(n) ((n) & ~(IA64_GRANULE_SIZE-1))
diff -urN linux-2.4.23-bk3/arch/ia64/mm/tlb.c linux-2.4.23-bk4/arch/ia64/mm/tlb.c
--- linux-2.4.23-bk3/arch/ia64/mm/tlb.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/mm/tlb.c	2003-12-06 02:49:48.000000000 -0800
@@ -75,7 +75,7 @@
 	 * and because interrupts are disabled during context switch.
 	 */
 	for (i = 0; i < NR_CPUS; ++i)
-		if (i != smp_processor_id())
+		if (cpu_online(i) && (i != smp_processor_id()))
 			cpu_data(i)->need_tlb_flush = 1;
 	local_flush_tlb_all();
 }
diff -urN linux-2.4.23-bk3/arch/ia64/tools/Makefile linux-2.4.23-bk4/arch/ia64/tools/Makefile
--- linux-2.4.23-bk3/arch/ia64/tools/Makefile	2002-11-28 15:53:09.000000000 -0800
+++ linux-2.4.23-bk4/arch/ia64/tools/Makefile	2003-12-06 02:49:48.000000000 -0800
@@ -33,7 +33,7 @@
 
 comma	:= ,
 
-print_offsets: print_offsets.c FORCE_RECOMPILE
+print_offsets: emptyoffsets print_offsets.c FORCE_RECOMPILE
 	$(CC) $(CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) print_offsets.c -o $@
 
 FORCE_RECOMPILE:
@@ -43,9 +43,20 @@
 offsets.h: print_offsets.s
 	$(AWK) -f print_offsets.awk $^ > $@
 
-print_offsets.s: print_offsets.c
+print_offsets.s: emptyoffsets print_offsets.c
 	$(CC) $(CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) -S print_offsets.c -o $@
 
 endif
 
+#
+# The TARGET offsets.h is included by ptrace.h, which is included by
+# print_offsets.c, so can't compile print_offsets.c to create offsets.h
+# until we already have offsets.h.  Break the chicken-and-egg cycle by
+# creating a dummy offsets.h with sufficient define's to bootstrap
+# the first compilation of print_offsets.c.
+#
+
+emptyoffsets:
+	test -f ${TARGET} || echo '#define IA64_TASK_THREAD_OFFSET 0' > ${TARGET}
+
 .PHONY: all modules modules_install
diff -urN linux-2.4.23-bk3/drivers/char/drm/ffb_drv.c linux-2.4.23-bk4/drivers/char/drm/ffb_drv.c
--- linux-2.4.23-bk3/drivers/char/drm/ffb_drv.c	2001-10-21 10:40:36.000000000 -0700
+++ linux-2.4.23-bk4/drivers/char/drm/ffb_drv.c	2003-12-06 02:49:48.000000000 -0800
@@ -372,25 +372,6 @@
 	return ret;
 }
 
-#ifndef MODULE
-/* DRM(options) is called by the kernel to parse command-line options
- * passed via the boot-loader (e.g., LILO).  It calls the insmod option
- * routine, drm_parse_drm.
- */
-
-/* JH- We have to hand expand the string ourselves because of the cpp.  If
- * anyone can think of a way that we can fit into the __setup macro without
- * changing it, then please send the solution my way.
- */
-static int __init ffb_options(char *str)
-{
-	DRM(parse_options)(str);
-	return 1;
-}
-
-__setup(DRIVER_NAME "=", ffb_options);
-#endif
-
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
diff -urN linux-2.4.23-bk3/drivers/net/pcmcia/pcnet_cs.c linux-2.4.23-bk4/drivers/net/pcmcia/pcnet_cs.c
--- linux-2.4.23-bk3/drivers/net/pcmcia/pcnet_cs.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.23-bk4/drivers/net/pcmcia/pcnet_cs.c	2003-12-06 02:49:49.000000000 -0800
@@ -11,7 +11,7 @@
 
     Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
 
-    pcnet_cs.c 1.149 2002/06/29 06:27:37
+    pcnet_cs.c 1.153 2003/11/09 18:53:09
     
     The network driver code is based on Donald Becker's NE2000 code:
 
@@ -75,7 +75,7 @@
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
-"pcnet_cs.c 1.149 2002/06/29 06:27:37 (David Hinds)";
+"pcnet_cs.c 1.153 2003/11/09 18:53:09 (David Hinds)";
 #else
 #define DEBUG(n, args...)
 #endif
@@ -303,7 +303,8 @@
     memset(info, 0, sizeof(*info));
     link = &info->link; dev = &info->dev;
     link->priv = info;
-    
+
+    init_timer(&link->release);
     link->release.function = &pcnet_release;
     link->release.data = (u_long)link;
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
@@ -895,13 +896,15 @@
 
     MII interface support for DL10019 and DL10022 based cards
 
-    On the DL10019, the MII IO direction bit is 0x10; on  the DL10022
+    On the DL10019, the MII IO direction bit is 0x10; on the DL10022
     it is 0x20.  Setting both bits seems to work on both card types.
 
 ======================================================================*/
 
 #define DLINK_GPIO		0x1c
 #define DLINK_DIAG		0x1d
+#define DLINK_EEPROM		0x1e
+
 #define MDIO_SHIFT_CLK		0x80
 #define MDIO_DATA_OUT		0x40
 #define MDIO_DIR_WRITE		0x30
@@ -964,6 +967,98 @@
     outb_p(0x00, addr);
 }
 
+/*======================================================================
+
+    EEPROM access routines for DL10019 and DL10022 based cards
+
+======================================================================*/
+
+#define EE_EEP		0x40
+#define EE_ASIC		0x10
+#define EE_CS		0x08
+#define EE_CK		0x04
+#define EE_DO		0x02
+#define EE_DI		0x01
+#define EE_ADOT		0x01	/* DataOut for ASIC */
+#define EE_READ_CMD	0x06	
+
+#define DL19FDUPLX	0x0400	/* DL10019 Full duplex mode */
+
+static int read_eeprom(ioaddr_t ioaddr, int location)
+{
+    int i, retval = 0;
+    ioaddr_t ee_addr = ioaddr + DLINK_EEPROM;
+    int read_cmd = location | (EE_READ_CMD << 8);
+
+    outb(0, ee_addr);
+    outb(EE_EEP|EE_CS, ee_addr);
+
+    /* Shift the read command bits out. */
+    for (i = 10; i >= 0; i--) {
+	short dataval = (read_cmd & (1 << i)) ? EE_DO : 0;
+	outb_p(EE_EEP|EE_CS|dataval, ee_addr);
+	outb_p(EE_EEP|EE_CS|dataval|EE_CK, ee_addr);
+    }
+    outb(EE_EEP|EE_CS, ee_addr);
+
+    for (i = 16; i > 0; i--) {
+	outb_p(EE_EEP|EE_CS | EE_CK, ee_addr);
+	retval = (retval << 1) | ((inb(ee_addr) & EE_DI) ? 1 : 0);
+	outb_p(EE_EEP|EE_CS, ee_addr);
+    }
+
+    /* Terminate the EEPROM access. */
+    outb(0, ee_addr);
+    return retval;
+}
+
+/*
+    The internal ASIC registers can be changed by EEPROM READ access
+    with EE_ASIC bit set.
+    In ASIC mode, EE_ADOT is used to output the data to the ASIC.
+*/ 
+
+static void write_asic(ioaddr_t ioaddr, int location, short asic_data)
+{
+	int i;
+	ioaddr_t ee_addr = ioaddr + DLINK_EEPROM;
+	short dataval;
+	int read_cmd = location | (EE_READ_CMD << 8);
+
+	asic_data |= read_eeprom(ioaddr, location);
+
+	outb(0, ee_addr);
+	outb(EE_ASIC|EE_CS|EE_DI, ee_addr);
+	
+	read_cmd = read_cmd >> 1;
+
+	/* Shift the read command bits out. */
+	for (i = 9; i >= 0; i--) {
+		dataval = (read_cmd & (1 << i)) ? EE_DO : 0;
+		outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr);
+		outb_p(EE_ASIC|EE_CS|EE_DI|dataval|EE_CK, ee_addr);
+		outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr);
+	}
+	// sync
+	outb(EE_ASIC|EE_CS, ee_addr);
+	outb(EE_ASIC|EE_CS|EE_CK, ee_addr);
+	outb(EE_ASIC|EE_CS, ee_addr);
+
+	for (i = 15; i >= 0; i--) {
+		dataval = (asic_data & (1 << i)) ? EE_ADOT : 0;
+		outb_p(EE_ASIC|EE_CS|dataval, ee_addr);
+		outb_p(EE_ASIC|EE_CS|dataval|EE_CK, ee_addr);
+		outb_p(EE_ASIC|EE_CS|dataval, ee_addr);
+	}
+
+	/* Terminate the ASIC access. */
+	outb(EE_ASIC|EE_DI, ee_addr);
+	outb(EE_ASIC|EE_DI| EE_CK, ee_addr);
+	outb(EE_ASIC|EE_DI, ee_addr);
+
+	outb(0, ee_addr);
+}
+
 /*====================================================================*/
 
 static void set_misc_reg(struct net_device *dev)
@@ -1178,6 +1273,9 @@
 	if (link && (info->flags & IS_DL10022)) {
 	    /* Disable collision detection on full duplex links */
 	    outb((p & 0x0140) ? 4 : 0, nic_base + DLINK_DIAG);
+	} else if (link && (info->flags & IS_DL10019)) {
+	    /* Disable collision detection on full duplex links */
+	    write_asic(dev->base_addr, 4, (p & 0x140) ? DL19FDUPLX : 0);
 	}
 	if (link) {
 	    if (info->phy_id == info->eth_phy) {
diff -urN linux-2.4.23-bk3/drivers/sound/ac97_plugin_ad1980.c linux-2.4.23-bk4/drivers/sound/ac97_plugin_ad1980.c
--- linux-2.4.23-bk3/drivers/sound/ac97_plugin_ad1980.c	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.23-bk4/drivers/sound/ac97_plugin_ad1980.c	2003-12-06 02:49:49.000000000 -0800
@@ -72,9 +72,11 @@
 
 #define AC97_AD_MISC	0x76
 
-	/* Switch the inputs/outputs over (from Dell code) */
+	/* Switch the inputs/outputs over (from Dell code)
+	Set the ADI compatibility mode (AC97NC bit) */
+
 	control = codec->codec_read(codec, AC97_AD_MISC);
-	codec->codec_write(codec, AC97_AD_MISC, control | 0x0420);
+	codec->codec_write(codec, AC97_AD_MISC, control | 0x4420);
 	
 	/* We could refuse the device since we dont need to hang around,
 	   but we will claim it */
@@ -120,5 +122,6 @@
 	return ac97_register_driver(&ad1980_driver);
 }
 
+MODULE_LICENSE("GPL");
 module_init(ad1980_init);
 module_exit(ad1980_exit);
diff -urN linux-2.4.23-bk3/include/asm-cris/axisflashmap.h linux-2.4.23-bk4/include/asm-cris/axisflashmap.h
--- linux-2.4.23-bk3/include/asm-cris/axisflashmap.h	2001-07-26 15:10:06.000000000 -0700
+++ linux-2.4.23-bk4/include/asm-cris/axisflashmap.h	2003-12-06 02:49:49.000000000 -0800
@@ -59,4 +59,7 @@
 #define PARTITION_TYPE_KERNEL 0x0002
 #define PARTITION_TYPE_JFFS   0x0003
 
+/* The master mtd for the entire flash. */
+extern struct mtd_info* axisflash_mtd;
+
 #endif
diff -urN linux-2.4.23-bk3/include/asm-cris/bitops.h linux-2.4.23-bk4/include/asm-cris/bitops.h
--- linux-2.4.23-bk3/include/asm-cris/bitops.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-bk4/include/asm-cris/bitops.h	2003-12-06 02:49:49.000000000 -0800
@@ -60,7 +60,7 @@
 
 /*
  * change_bit - Toggle a bit in memory
- * @nr: Bit to clear
+ * @nr: Bit to change
  * @addr: Address to start counting from
  *
  * change_bit() is atomic and may not be reordered.
@@ -72,7 +72,7 @@
 
 /*
  * __change_bit - Toggle a bit in memory
- * @nr: the bit to set
+ * @nr: the bit to change
  * @addr: the address to start counting from
  *
  * Unlike change_bit(), this function is non-atomic and may be reordered.
@@ -127,7 +127,7 @@
 
 /**
  * test_and_clear_bit - Clear a bit and return its old value
- * @nr: Bit to set
+ * @nr: Bit to clear
  * @addr: Address to count from
  *
  * This operation is atomic and cannot be reordered.  
@@ -152,7 +152,7 @@
 
 /**
  * __test_and_clear_bit - Clear a bit and return its old value
- * @nr: Bit to set
+ * @nr: Bit to clear
  * @addr: Address to count from
  *
  * This operation is non-atomic and can be reordered.  
@@ -173,7 +173,7 @@
 }
 /**
  * test_and_change_bit - Change a bit and return its new value
- * @nr: Bit to set
+ * @nr: Bit to change
  * @addr: Address to count from
  *
  * This operation is atomic and cannot be reordered.  
diff -urN linux-2.4.23-bk3/include/asm-cris/ioctls.h linux-2.4.23-bk4/include/asm-cris/ioctls.h
--- linux-2.4.23-bk3/include/asm-cris/ioctls.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-bk4/include/asm-cris/ioctls.h	2003-12-06 02:49:49.000000000 -0800
@@ -69,12 +69,11 @@
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 #define TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */
 #define TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */
-#define FIOQSIZE	0x5460
 
 #define TIOCSERSETRS485 0x5460  /* enable rs-485 */
 #define TIOCSERWRRS485  0x5461  /* write rs-485 */
 
-
+#define FIOQSIZE  _IOR('f', 128, loff_t) /* Get exact space used by quota */
 
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
diff -urN linux-2.4.23-bk3/include/asm-cris/ipc.h linux-2.4.23-bk4/include/asm-cris/ipc.h
--- linux-2.4.23-bk3/include/asm-cris/ipc.h	2001-02-08 16:32:44.000000000 -0800
+++ linux-2.4.23-bk4/include/asm-cris/ipc.h	2003-12-06 02:49:49.000000000 -0800
@@ -17,6 +17,7 @@
 #define SEMOP		 1
 #define SEMGET		 2
 #define SEMCTL		 3
+#define SEMTIMEDOP	 4
 #define MSGSND		11
 #define MSGRCV		12
 #define MSGGET		13
diff -urN linux-2.4.23-bk3/include/asm-cris/page.h linux-2.4.23-bk4/include/asm-cris/page.h
--- linux-2.4.23-bk3/include/asm-cris/page.h	2002-08-02 17:39:45.000000000 -0700
+++ linux-2.4.23-bk4/include/asm-cris/page.h	2003-12-06 02:49:49.000000000 -0800
@@ -80,6 +80,20 @@
          BUG(); \
 } while (0)
 
+/* Pure 2^n version of get_order */
+static __inline__ int get_order(unsigned long size)
+{
+	int order;
+
+	size = (size-1) >> (PAGE_SHIFT-1);
+	order = -1;
+	do {
+		size >>= 1;
+		order++;
+	} while (size);
+	return order;
+}
+
 #endif /* __ASSEMBLY__ */
 
 /* macros to convert between really physical and virtual addresses
diff -urN linux-2.4.23-bk3/include/asm-cris/sync_serial.h linux-2.4.23-bk4/include/asm-cris/sync_serial.h
--- linux-2.4.23-bk3/include/asm-cris/sync_serial.h	2001-04-06 10:51:19.000000000 -0700
+++ linux-2.4.23-bk4/include/asm-cris/sync_serial.h	2003-12-06 02:49:49.000000000 -0800
@@ -1,7 +1,7 @@
 /*  
- * ioctl defines for synchrnous serial port driver
+ * ioctl defines for synchronous serial port driver
  *
- * Copyright (c) 2001 Axis Communications AB
+ * Copyright (c) 2001-2003 Axis Communications AB
  * 
  * Author: Mikael Starvik 
  *
@@ -18,6 +18,7 @@
 #define SSP_IPOLARITY  _IOR('S', 3, unsigned int)
 #define SSP_OPOLARITY  _IOR('S', 4, unsigned int)
 #define SSP_SPI        _IOR('S', 5, unsigned int)
+#define SSP_INBUFCHUNK _IOR('S', 6, unsigned int)
 
 /* Values for SSP_SPEED */
 #define SSP150        0
@@ -47,7 +48,7 @@
 #define FREQ_32kHz  7
 
 /* Used by application to set CODEC divider, word rate and frame rate */
-#define CODEC_VAL(freq, word, frame) (CODEC | (freq << 8) | (word << 16) | (frame << 28))
+#define CODEC_VAL(freq, clk_per_sync, sync_per_frame) (CODEC | (freq << 8) | (clk_per_sync << 16) | (sync_per_frame << 28))
 
 /* Used by driver to extract speed */
 #define GET_SPEED(x) (x & 0xff)
@@ -66,15 +67,17 @@
 /* Values for SSP_FRAME_SYNC */
 #define NORMAL_SYNC                1
 #define EARLY_SYNC                 2
+
 #define BIT_SYNC                   4
 #define WORD_SYNC                  8
 #define EXTENDED_SYNC           0x10
+
 #define SYNC_OFF                0x20
 #define SYNC_ON                 0x40
 #define WORD_SIZE_8             0x80
 #define WORD_SIZE_12           0x100
 #define WORD_SIZE_16           0x200
-#define WORD_SIZE_24           0x300
+#define WORD_SIZE_24           0x400
 #define WORD_SIZE_32           0x800
 #define BIT_ORDER_LSB         0x1000
 #define BIT_ORDER_MSB         0x2000
@@ -86,6 +89,8 @@
 /* Values for SSP_IPOLARITY and SSP_OPOLARITY */
 #define CLOCK_NORMAL         1
 #define CLOCK_INVERT         2
+#define CLOCK_INEGEDGE       CLOCK_NORMAL
+#define CLOCK_IPOSEDGE       CLOCK_INVERT
 #define FRAME_NORMAL         4
 #define FRAME_INVERT         8
 #define STATUS_NORMAL      0x10
@@ -93,5 +98,9 @@
 
 /* Values for SSP_SPI */
 #define SPI_MASTER           0
-#define SPI_SLAVE            1  
+#define SPI_SLAVE            1
+
+/* Values for SSP_INBUFCHUNK */
+/* plain integer with the size of DMA chunks */
+
 #endif
diff -urN linux-2.4.23-bk3/include/asm-ia64/kmap_types.h linux-2.4.23-bk4/include/asm-ia64/kmap_types.h
--- linux-2.4.23-bk3/include/asm-ia64/kmap_types.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-bk4/include/asm-ia64/kmap_types.h	2003-12-06 02:49:49.000000000 -0800
@@ -0,0 +1,31 @@
+#ifndef _ASM_IA64_KMAP_TYPES_H
+#define _ASM_IA64_KMAP_TYPES_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_DEBUG_HIGHMEM
+# define D(n) __KM_FENCE_##n ,
+#else
+# define D(n)
+#endif
+
+enum km_type {
+D(0)	KM_BOUNCE_READ,
+D(1)	KM_SKB_SUNRPC_DATA,
+D(2)	KM_SKB_DATA_SOFTIRQ,
+D(3)	KM_USER0,
+D(4)	KM_USER1,
+D(5)	KM_BIO_SRC_IRQ,
+D(6)	KM_BIO_DST_IRQ,
+D(7)	KM_PTE0,
+D(8)	KM_PTE1,
+D(9)	KM_IRQ0,
+D(10)	KM_IRQ1,
+D(11)	KM_SOFTIRQ0,
+D(12)	KM_SOFTIRQ1,
+D(13)	KM_TYPE_NR
+};
+
+#undef D
+
+#endif /* _ASM_IA64_KMAP_TYPES_H */
diff -urN linux-2.4.23-bk3/include/asm-ia64/machvec.h linux-2.4.23-bk4/include/asm-ia64/machvec.h
--- linux-2.4.23-bk3/include/asm-ia64/machvec.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.23-bk4/include/asm-ia64/machvec.h	2003-12-06 02:49:49.000000000 -0800
@@ -24,7 +24,6 @@
 typedef void ia64_mv_cpu_init_t(void);
 typedef void ia64_mv_irq_init_t (void);
 typedef void ia64_mv_pci_fixup_t (int);
-typedef void ia64_mv_pci_enable_device_t (struct pci_dev *);
 typedef unsigned long ia64_mv_map_nr_t (void *);
 typedef void ia64_mv_mca_init_t (void);
 typedef void ia64_mv_mca_handler_t (void);
@@ -91,7 +90,6 @@
 #  define platform_cmci_handler	ia64_mv.cmci_handler
 #  define platform_log_print	ia64_mv.log_print
 #  define platform_pci_fixup	ia64_mv.pci_fixup
-#  define platform_pci_enable_device	ia64_mv.pci_enable_device
 #  define platform_send_ipi		ia64_mv.send_ipi
 #  define platform_global_tlb_purge	ia64_mv.global_tlb_purge
 #  define platform_pci_dma_init		ia64_mv.dma_init
@@ -121,7 +119,6 @@
 	ia64_mv_cpu_init_t *cpu_init;
 	ia64_mv_irq_init_t *irq_init;
 	ia64_mv_pci_fixup_t *pci_fixup;
-	ia64_mv_pci_enable_device_t *pci_enable_device;
 	ia64_mv_map_nr_t *map_nr;
 	ia64_mv_mca_init_t *mca_init;
 	ia64_mv_mca_handler_t *mca_handler;
@@ -157,7 +154,6 @@
 	platform_cpu_init,			\
 	platform_irq_init,			\
 	platform_pci_fixup,			\
-	platform_pci_enable_device,		\
 	platform_map_nr,			\
 	platform_mca_init,			\
 	platform_mca_handler,			\
@@ -235,9 +231,6 @@
 #ifndef platform_pci_fixup
 # define platform_pci_fixup	((ia64_mv_pci_fixup_t *) machvec_noop)
 #endif
-#ifndef platform_pci_enable_device
-# define platform_pci_enable_device	((ia64_mv_pci_enable_device_t *) machvec_noop)
-#endif
 #ifndef platform_send_ipi
 # define platform_send_ipi	ia64_send_ipi	/* default to architected version */
 #endif
diff -urN linux-2.4.23-bk3/include/asm-ia64/machvec_hpzx1.h linux-2.4.23-bk4/include/asm-ia64/machvec_hpzx1.h
--- linux-2.4.23-bk3/include/asm-ia64/machvec_hpzx1.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.23-bk4/include/asm-ia64/machvec_hpzx1.h	2003-12-06 02:49:49.000000000 -0800
@@ -3,10 +3,9 @@
 
 extern ia64_mv_setup_t dig_setup;
 extern ia64_mv_pci_fixup_t hpzx1_pci_fixup;
-extern ia64_mv_pci_enable_device_t sba_enable_device;
 extern ia64_mv_map_nr_t map_nr_dense;
-extern ia64_mv_pci_alloc_consistent sba_alloc_consistent;
-extern ia64_mv_pci_free_consistent sba_free_consistent;
+extern ia64_mv_pci_alloc_consistent sba_alloc_coherent;
+extern ia64_mv_pci_free_consistent sba_free_coherent;
 extern ia64_mv_pci_map_single sba_map_single;
 extern ia64_mv_pci_unmap_single sba_unmap_single;
 extern ia64_mv_pci_map_sg sba_map_sg;
@@ -20,14 +19,13 @@
  * platform's machvec structure.  When compiling a non-generic kernel,
  * the macros are used directly.
  */
-#define platform_name			"hpzx1"
+#define platform_name			"hp"
 #define platform_setup			dig_setup
 #define platform_pci_fixup		hpzx1_pci_fixup
-#define platform_pci_enable_device	sba_enable_device
 #define platform_map_nr			map_nr_dense
 #define platform_pci_dma_init		((ia64_mv_pci_dma_init *) machvec_noop)
-#define platform_pci_alloc_consistent	sba_alloc_consistent
-#define platform_pci_free_consistent	sba_free_consistent
+#define platform_pci_alloc_consistent	sba_alloc_coherent
+#define platform_pci_free_consistent	sba_free_coherent
 #define platform_pci_map_single		sba_map_single
 #define platform_pci_unmap_single	sba_unmap_single
 #define platform_pci_map_sg		sba_map_sg
diff -urN linux-2.4.23-bk3/include/asm-ia64/mca.h linux-2.4.23-bk4/include/asm-ia64/mca.h
--- linux-2.4.23-bk3/include/asm-ia64/mca.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.23-bk4/include/asm-ia64/mca.h	2003-12-06 02:49:49.000000000 -0800
@@ -140,7 +140,6 @@
 extern int  ia64_log_print(int,prfunc_t);
 extern void ia64_mca_cmc_vector_setup(void);
 extern int  ia64_mca_check_errors(void);
-extern u64  ia64_log_get(int, prfunc_t);
 
 #define PLATFORM_CALL(fn, args)	printk("Platform call TBD\n")
 
diff -urN linux-2.4.23-bk3/include/asm-ia64/mca_asm.h linux-2.4.23-bk4/include/asm-ia64/mca_asm.h
--- linux-2.4.23-bk3/include/asm-ia64/mca_asm.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.23-bk4/include/asm-ia64/mca_asm.h	2003-12-06 02:49:49.000000000 -0800
@@ -212,7 +212,8 @@
  * saved onto the new stack frame.
  *
  *	+-----------------------+
- *	|NDIRTY [BSP - BSPSTORE]|
+ *	|NDIRTY_WORDS           |
+ *	|       [BSP - BSPSTORE]|
  *	+-----------------------+
  *	|	RNAT		|
  *	+-----------------------+
@@ -230,7 +231,7 @@
 #define  rse_ifs_offset		(rse_pfs_offset+0x08)
 #define  rse_bspstore_offset	(rse_ifs_offset+0x08)
 #define  rse_rnat_offset	(rse_bspstore_offset+0x08)
-#define  rse_ndirty_offset	(rse_rnat_offset+0x08)
+#define  rse_ndirty_words_offset	(rse_rnat_offset+0x08)
 
 /*
  * rse_switch_context
@@ -243,7 +244,8 @@
  *	6. Save the old RNAT on the new stack frame
  *	7. Write BSPSTORE with the new backing store pointer
  *	8. Read and save the new BSP to calculate the #dirty registers
- * NOTE: Look at pages 11-10, 11-11 in PRM Vol 2
+ * NOTE: Look at section 6.11 in Intel IA-64 Architecture Software Developer's
+ *       Manual, Volume 2, System Architecture.
  */
 #define rse_switch_context(temp,p_stackframe,p_bspstore)			\
 	;;									\
@@ -280,12 +282,12 @@
 #define rse_return_context(psr_mask_reg,temp,p_stackframe)			\
 	;;									\
 	alloc   temp=ar.pfs,0,0,0,0;						\
-	add     p_stackframe=rse_ndirty_offset,p_stackframe;;			\
+	add     p_stackframe=rse_ndirty_words_offset,p_stackframe;;		\
 	ld8     temp=[p_stackframe];;						\
 	shl     temp=temp,16;;							\
 	mov     ar.rsc=temp;;							\
 	loadrs;;								\
-	add     p_stackframe=-rse_ndirty_offset+rse_bspstore_offset,p_stackframe;;\
+	add     p_stackframe=-rse_ndirty_words_offset+rse_bspstore_offset,p_stackframe;;\
 	ld8     temp=[p_stackframe];;						\
 	mov     ar.bspstore=temp;;						\
 	add     p_stackframe=-rse_bspstore_offset+rse_rnat_offset,p_stackframe;;\
diff -urN linux-2.4.23-bk3/include/asm-ia64/pal.h linux-2.4.23-bk4/include/asm-ia64/pal.h
--- linux-2.4.23-bk3/include/asm-ia64/pal.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-bk4/include/asm-ia64/pal.h	2003-12-06 02:49:49.000000000 -0800
@@ -407,10 +407,11 @@
 						 * generated.
 						 * (Trap Lost )
 						 */
-			op		: 3,	/* Operation that
-						 * caused the machine
-						 * check
+			mi		: 1,	/* More information available
+						 * call PAL_MC_ERROR_INFO
 						 */
+			pi		: 1,	/* Precise instruction pointer */
+			pm		: 1,	/* Precise min-state save area */
 
 			dy		: 1,	/* Processor dynamic
 						 * state valid
@@ -452,32 +453,23 @@
 						 * by the processor
 						 */
 
-			reserved2	: 12,
+			reserved2	: 11,
 			cc		: 1,	/* Cache check */
 			tc		: 1,	/* TLB check */
 			bc		: 1,	/* Bus check */
-			uc		: 1;	/* Unknown check */
+			rc		: 1,	/* Register file check */
+			uc		: 1;	/* Uarch check */
 
 } pal_processor_state_info_t;
 
 typedef struct pal_cache_check_info_s {
-	u64		reserved1	: 16,
-			way		: 5,	/* Way in which the
-						 * error occurred
-						 */
-			reserved2	: 1,
-			mc		: 1,	/* Machine check corrected */
-			tv		: 1,	/* Target address
-						 * structure is valid
-						 */
-
-			wv		: 1,	/* Way field valid */
-			op		: 3,	/* Type of cache
+	u64		op		: 4,	/* Type of cache
 						 * operation that
 						 * caused the machine
 						 * check.
 						 */
-
+			level		: 2,	/* Cache level */
+			reserved1	: 2,
 			dl		: 1,	/* Failure in data part
 						 * of cache line
 						 */
@@ -486,11 +478,34 @@
 						 */
 			dc		: 1,	/* Failure in dcache */
 			ic		: 1,	/* Failure in icache */
-			index		: 24,	/* Cache line index */
-			mv		: 1,	/* mesi valid */
 			mesi		: 3,	/* Cache line state */
-			level		: 4;	/* Cache level */
+			mv		: 1,	/* mesi valid */
+			way		: 5,	/* Way in which the
+						 * error occurred
+						 */
+			wiv		: 1,	/* Way field valid */
+			reserved2	: 10,
+
+			index		: 20,	/* Cache line index */
+			reserved3	: 2,
 
+			is		: 1,	/* instruction set (1 == ia32) */
+			iv		: 1,	/* instruction set field valid */
+			pl		: 2,	/* privilege level */
+			pv		: 1,	/* privilege level field valid */
+			mcc		: 1,	/* Machine check corrected */
+			tv		: 1,	/* Target address
+						 * structure is valid
+						 */
+			rq		: 1,	/* Requester identifier
+						 * structure is valid
+						 */
+			rp		: 1,	/* Responder identifier
+						 * structure is valid
+						 */
+			pi		: 1;	/* Precise instruction pointer
+						 * structure is valid
+						 */
 } pal_cache_check_info_t;
 
 typedef struct pal_tlb_check_info_s {
@@ -498,18 +513,38 @@
 	u64		tr_slot		: 8,	/* Slot# of TR where
 						 * error occurred
 						 */
-			reserved2	: 8,
+			trv		: 1,	/* tr_slot field is valid */
+			reserved1	: 1,
+			level		: 2,	/* TLB level where failure occurred */
+			reserved2	: 4,
 			dtr		: 1,	/* Fail in data TR */
 			itr		: 1,	/* Fail in inst TR */
 			dtc		: 1,	/* Fail in data TC */
 			itc		: 1,	/* Fail in inst. TC */
-			mc		: 1,	/* Machine check corrected */
-			reserved1	: 43;
+			op		: 4,	/* Cache operation */
+			reserved3	: 30,
 
+			is		: 1,	/* instruction set (1 == ia32) */
+			iv		: 1,	/* instruction set field valid */
+			pl		: 2,	/* privilege level */
+			pv		: 1,	/* privilege level field valid */
+			mcc		: 1,	/* Machine check corrected */
+			tv		: 1,	/* Target address
+						 * structure is valid
+						 */
+			rq		: 1,	/* Requester identifier
+						 * structure is valid
+						 */
+			rp		: 1,	/* Responder identifier
+						 * structure is valid
+						 */
+			pi		: 1;	/* Precise instruction pointer
+						 * structure is valid
+						 */
 } pal_tlb_check_info_t;
 
 typedef struct pal_bus_check_info_s {
-	u64		size		: 5,	/* Xaction size*/
+	u64		size		: 5,	/* Xaction size */
 			ib		: 1,	/* Internal bus error */
 			eb		: 1,	/* External bus error */
 			cc		: 1,	/* Error occurred
@@ -518,22 +553,99 @@
 						 */
 			type		: 8,	/* Bus xaction type*/
 			sev		: 5,	/* Bus error severity*/
-			tv		: 1,	/* Targ addr valid */
-			rp		: 1,	/* Resp addr valid */
-			rq		: 1,	/* Req addr valid */
+			hier		: 2,	/* Bus hierarchy level */
+			reserved1	: 1,
 			bsi		: 8,	/* Bus error status
 						 * info
 						 */
-			mc		: 1,	/* Machine check corrected */
-			reserved1	: 31;
+			reserved2	: 22,
+
+			is		: 1,	/* instruction set (1 == ia32) */
+			iv		: 1,	/* instruction set field valid */
+			pl		: 2,	/* privilege level */
+			pv		: 1,	/* privilege level field valid */
+			mcc		: 1,	/* Machine check corrected */
+			tv		: 1,	/* Target address
+						 * structure is valid
+						 */
+			rq		: 1,	/* Requester identifier
+						 * structure is valid
+						 */
+			rp		: 1,	/* Responder identifier
+						 * structure is valid
+						 */
+			pi		: 1;	/* Precise instruction pointer
+						 * structure is valid
+						 */
 } pal_bus_check_info_t;
 
+typedef struct pal_reg_file_check_info_s {
+	u64		id		: 4,	/* Register file identifier */
+			op		: 4,	/* Type of register
+						 * operation that
+						 * caused the machine
+						 * check.
+						 */
+			reg_num		: 7,	/* Register number */
+			rnv		: 1,	/* reg_num valid */
+			reserved2	: 38,
+
+			is		: 1,	/* instruction set (1 == ia32) */
+			iv		: 1,	/* instruction set field valid */
+			pl		: 2,	/* privilege level */
+			pv		: 1,	/* privilege level field valid */
+			mcc		: 1,	/* Machine check corrected */
+			reserved3	: 3,
+			pi		: 1;	/* Precise instruction pointer
+						 * structure is valid
+						 */
+} pal_reg_file_check_info_t;
+
+typedef struct pal_uarch_check_info_s {
+	u64		sid		: 5,	/* Structure identification */
+			level		: 3,	/* Level of failure */
+			array_id	: 4,	/* Array identification */
+			op		: 4,	/* Type of
+						 * operation that
+						 * caused the machine
+						 * check.
+						 */
+			way		: 6,	/* Way of structure */
+			wv		: 1,	/* way valid */
+			xv		: 1,	/* index valid */
+			reserved1	: 8,
+			index		: 8,	/* Index or set of the uarch
+						 * structure that failed.
+						 */
+			reserved2	: 24,
+
+			is		: 1,	/* instruction set (1 == ia32) */
+			iv		: 1,	/* instruction set field valid */
+			pl		: 2,	/* privilege level */
+			pv		: 1,	/* privilege level field valid */
+			mcc		: 1,	/* Machine check corrected */
+			tv		: 1,	/* Target address
+						 * structure is valid
+						 */
+			rq		: 1,	/* Requester identifier
+						 * structure is valid
+						 */
+			rp		: 1,	/* Responder identifier
+						 * structure is valid
+						 */
+			pi		: 1;	/* Precise instruction pointer
+						 * structure is valid
+						 */
+} pal_uarch_check_info_t;
+
 typedef union pal_mc_error_info_u {
 	u64				pmei_data;
 	pal_processor_state_info_t	pme_processor;
 	pal_cache_check_info_t		pme_cache;
 	pal_tlb_check_info_t		pme_tlb;
 	pal_bus_check_info_t		pme_bus;
+	pal_reg_file_check_info_t	pme_reg_file;
+	pal_uarch_check_info_t		pme_uarch;
 } pal_mc_error_info_t;
 
 #define pmci_proc_unknown_check			pme_processor.uc
diff -urN linux-2.4.23-bk3/include/asm-ia64/param.h linux-2.4.23-bk4/include/asm-ia64/param.h
--- linux-2.4.23-bk3/include/asm-ia64/param.h	2001-04-05 12:51:47.000000000 -0700
+++ linux-2.4.23-bk4/include/asm-ia64/param.h	2003-12-06 02:49:49.000000000 -0800
@@ -4,22 +4,10 @@
 /*
  * Fundamental kernel parameters.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998, 1999, 2002-2003 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>
-
-#ifdef CONFIG_IA64_HP_SIM
-/*
- * Yeah, simulating stuff is slow, so let us catch some breath between
- * timer interrupts...
- */
-# define HZ	  32
-#else
-# define HZ	1024
-#endif
-
 #define EXEC_PAGESIZE	65536
 
 #ifndef NGROUPS
@@ -33,7 +21,24 @@
 #define MAXHOSTNAMELEN	64	/* max length of hostname */
 
 #ifdef __KERNEL__
+# include <linux/config.h>	/* mustn't include <linux/config.h> outside of #ifdef __KERNEL__ */
+# ifdef CONFIG_IA64_HP_SIM
+  /*
+   * Yeah, simulating stuff is slow, so let us catch some breath between
+   * timer interrupts...
+   */
+#  define HZ	  32
+# else
+#  define HZ	1024
+# endif
+# define USER_HZ	HZ
 # define CLOCKS_PER_SEC	HZ	/* frequency at which times() counts */
+#else
+   /*
+    * Technically, this is wrong, but some old apps still refer to it.  The proper way to
+    * get the HZ value is via sysconf(_SC_CLK_TCK).
+    */
+# define HZ 1024
 #endif
 
 #endif /* _ASM_IA64_PARAM_H */
diff -urN linux-2.4.23-bk3/include/asm-ia64/sal.h linux-2.4.23-bk4/include/asm-ia64/sal.h
--- linux-2.4.23-bk3/include/asm-ia64/sal.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.23-bk4/include/asm-ia64/sal.h	2003-12-06 02:49:49.000000000 -0800
@@ -806,6 +806,8 @@
 
 extern unsigned long sal_platform_features;
 
+extern int (*salinfo_platform_oemdata)(const u8 *, u8 **, u64 *);
+
 #endif /* __ASSEMBLY__ */
 
-#endif /* _ASM_IA64_PAL_H */
+#endif /* _ASM_IA64_SAL_H */
diff -urN linux-2.4.23-bk3/include/asm-ia64/uaccess.h linux-2.4.23-bk4/include/asm-ia64/uaccess.h
--- linux-2.4.23-bk3/include/asm-ia64/uaccess.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.23-bk4/include/asm-ia64/uaccess.h	2003-12-06 02:49:49.000000000 -0800
@@ -8,7 +8,7 @@
  * addresses.  Thus, we need to be careful not to let the user to
  * trick us into accessing kernel memory that would normally be
  * inaccessible.  This code is also fairly performance sensitive,
- * so we want to spend as little time doing saftey checks as
+ * so we want to spend as little time doing safety checks as
  * possible.
  *
  * To make matters a bit more interesting, these macros sometimes also
@@ -26,8 +26,8 @@
  * associated and, if so, sets r8 to -EFAULT and clears r9 to 0 and
  * then resumes execution at the continuation point.
  *
- * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
- * Copyright (C) 1998, 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998, 1999, 2001, 2003 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
 #include <linux/errno.h>
@@ -56,8 +56,10 @@
  * address TASK_SIZE is never valid.  We also need to make sure that the address doesn't
  * point inside the virtually mapped linear page table.
  */
-#define __access_ok(addr,size,segment)	(((unsigned long) (addr)) <= (segment).seg		\
-	 && ((segment).seg == KERNEL_DS.seg || rgn_offset((unsigned long) (addr)) < RGN_MAP_LIMIT))
+#define __access_ok(addr,size,segment)						\
+	likely(((unsigned long) (addr)) <= (segment).seg			\
+	       && ((segment).seg == KERNEL_DS.seg				\
+		   || REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT))
 #define access_ok(type,addr,size)	__access_ok((addr),(size),get_fs())
 
 static inline int
diff -urN linux-2.4.23-bk3/include/asm-ia64/xor.h linux-2.4.23-bk4/include/asm-ia64/xor.h
--- linux-2.4.23-bk3/include/asm-ia64/xor.h	2000-11-12 19:39:51.000000000 -0800
+++ linux-2.4.23-bk4/include/asm-ia64/xor.h	2003-12-06 02:49:49.000000000 -0800
@@ -22,256 +22,6 @@
 extern void xor_ia64_5(unsigned long, unsigned long *, unsigned long *,
 		       unsigned long *, unsigned long *, unsigned long *);
 
-asm ("
-	.text
-
-	// Assume L2 memory latency of 6 cycles.
-
-	.proc xor_ia64_2
-xor_ia64_2:
-	.prologue
-	.fframe 0
-	{ .mii
-	  .save ar.pfs, r31
-	  alloc r31 = ar.pfs, 3, 0, 13, 16
-	  .save ar.lc, r30
-	  mov r30 = ar.lc
-	  .save pr, r29
-	  mov r29 = pr
-	  ;;
-	}
-	.body
-	{ .mii
-	  mov r8 = in1
-	  mov ar.ec = 6 + 2
-	  shr in0 = in0, 3
-	  ;;
-	}
-	{ .mmi
-	  adds in0 = -1, in0
-	  mov r16 = in1
-	  mov r17 = in2
-	  ;;
-	}
-	{ .mii
-	  mov ar.lc = in0
-	  mov pr.rot = 1 << 16
-	  ;;
-	}
-	.rotr s1[6+1], s2[6+1], d[2]
-	.rotp p[6+2]
-0:	 { .mmi
-(p[0])	  ld8.nta s1[0] = [r16], 8
-(p[0])	  ld8.nta s2[0] = [r17], 8
-(p[6])	  xor d[0] = s1[6], s2[6]
-	}
-	{ .mfb
-(p[6+1])  st8.nta [r8] = d[1], 8
-	  nop.f 0
-	  br.ctop.dptk.few 0b
-	  ;;
-	}
-	{ .mii
-	  mov ar.lc = r30
-	  mov pr = r29, -1
-	}
-	{ .bbb
-	  br.ret.sptk.few rp
-	}
-	.endp xor_ia64_2
-
-	.proc xor_ia64_3
-xor_ia64_3:
-	.prologue
-	.fframe 0
-	{ .mii
-	  .save ar.pfs, r31
-	  alloc r31 = ar.pfs, 4, 0, 20, 24
-	  .save ar.lc, r30
-	  mov r30 = ar.lc
-	  .save pr, r29
-	  mov r29 = pr
-	  ;;
-	}
-	.body
-	{ .mii
-	  mov r8 = in1
-	  mov ar.ec = 6 + 2
-	  shr in0 = in0, 3
-	  ;;
-	}
-	{ .mmi
-	  adds in0 = -1, in0
-	  mov r16 = in1
-	  mov r17 = in2
-	  ;;
-	}
-	{ .mii
-	  mov r18 = in3
-	  mov ar.lc = in0
-	  mov pr.rot = 1 << 16
-	  ;;
-	}
-	.rotr s1[6+1], s2[6+1], s3[6+1], d[2]
-	.rotp p[6+2]
-0:	{ .mmi
-(p[0])	  ld8.nta s1[0] = [r16], 8
-(p[0])	  ld8.nta s2[0] = [r17], 8
-(p[6])	  xor d[0] = s1[6], s2[6]
-	  ;;
-	}
-	{ .mmi
-(p[0])	  ld8.nta s3[0] = [r18], 8
-(p[6+1])  st8.nta [r8] = d[1], 8
-(p[6])	  xor d[0] = d[0], s3[6]
-	}
-	{ .bbb
-	  br.ctop.dptk.few 0b
-	  ;;
-	}
-	{ .mii
-	  mov ar.lc = r30
-	  mov pr = r29, -1
-	}
-	{ .bbb
-	  br.ret.sptk.few rp
-	}
-	.endp xor_ia64_3
-
-	.proc xor_ia64_4
-xor_ia64_4:
-	.prologue
-	.fframe 0
-	{ .mii
-	  .save ar.pfs, r31
-	  alloc r31 = ar.pfs, 5, 0, 27, 32
-	  .save ar.lc, r30
-	  mov r30 = ar.lc
-	  .save pr, r29
-	  mov r29 = pr
-	  ;;
-	}
-	.body
-	{ .mii
-	  mov r8 = in1
-	  mov ar.ec = 6 + 2
-	  shr in0 = in0, 3
-	  ;;
-	}
-	{ .mmi
-	  adds in0 = -1, in0
-	  mov r16 = in1
-	  mov r17 = in2
-	  ;;
-	}
-	{ .mii
-	  mov r18 = in3
-	  mov ar.lc = in0
-	  mov pr.rot = 1 << 16
-	}
-	{ .mfb
-	  mov r19 = in4
-	  ;;
-	}
-	.rotr s1[6+1], s2[6+1], s3[6+1], s4[6+1], d[2]
-	.rotp p[6+2]
-0:	{ .mmi
-(p[0])	  ld8.nta s1[0] = [r16], 8
-(p[0])	  ld8.nta s2[0] = [r17], 8
-(p[6])	  xor d[0] = s1[6], s2[6]
-	}
-	{ .mmi
-(p[0])	  ld8.nta s3[0] = [r18], 8
-(p[0])	  ld8.nta s4[0] = [r19], 8
-(p[6])	  xor r20 = s3[6], s4[6]
-	  ;;
-	}
-	{ .mib
-(p[6+1])  st8.nta [r8] = d[1], 8
-(p[6])	  xor d[0] = d[0], r20
-	  br.ctop.dptk.few 0b
-	  ;;
-	}
-	{ .mii
-	  mov ar.lc = r30
-	  mov pr = r29, -1
-	}
-	{ .bbb
-	  br.ret.sptk.few rp
-	}
-	.endp xor_ia64_4
-
-	.proc xor_ia64_5
-xor_ia64_5:
-	.prologue
-	.fframe 0
-	{ .mii
-	  .save ar.pfs, r31
-	  alloc r31 = ar.pfs, 6, 0, 34, 40
-	  .save ar.lc, r30
-	  mov r30 = ar.lc
-	  .save pr, r29
-	  mov r29 = pr
-	  ;;
-	}
-	.body
-	{ .mii
-	  mov r8 = in1
-	  mov ar.ec = 6 + 2
-	  shr in0 = in0, 3
-	  ;;
-	}
-	{ .mmi
-	  adds in0 = -1, in0
-	  mov r16 = in1
-	  mov r17 = in2
-	  ;;
-	}
-	{ .mii
-	  mov r18 = in3
-	  mov ar.lc = in0
-	  mov pr.rot = 1 << 16
-	}
-	{ .mib
-	  mov r19 = in4
-	  mov r20 = in5
-	  ;;
-	}
-	.rotr s1[6+1], s2[6+1], s3[6+1], s4[6+1], s5[6+1], d[2]
-	.rotp p[6+2]
-0:	{ .mmi
-(p[0])	  ld8.nta s1[0] = [r16], 8
-(p[0])	  ld8.nta s2[0] = [r17], 8
-(p[6])	  xor d[0] = s1[6], s2[6]
-	}
-	{ .mmi
-(p[0])	  ld8.nta s3[0] = [r18], 8
-(p[0])	  ld8.nta s4[0] = [r19], 8
-(p[6])	  xor r21 = s3[6], s4[6]
-	  ;;
-	}
-	{ .mmi
-(p[0])	  ld8.nta s5[0] = [r20], 8
-(p[6+1])  st8.nta [r8] = d[1], 8
-(p[6])	  xor d[0] = d[0], r21
-	  ;;
-	}
-	{ .mfb
-(p[6])	  xor d[0] = d[0], s5[6]
-	  nop.f 0
-	  br.ctop.dptk.few 0b
-	  ;;
-	}
-	{ .mii
-	  mov ar.lc = r30
-	  mov pr = r29, -1
-	}
-	{ .bbb
-	  br.ret.sptk.few rp
-	}
-	.endp xor_ia64_5
-");
-
 static struct xor_block_template xor_block_ia64 = {
 	name: "ia64",
 	do_2: xor_ia64_2,
diff -urN linux-2.4.23-bk3/include/linux/netfilter_ipv4/ip_conntrack_amanda.h linux-2.4.23-bk4/include/linux/netfilter_ipv4/ip_conntrack_amanda.h
--- linux-2.4.23-bk3/include/linux/netfilter_ipv4/ip_conntrack_amanda.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.23-bk4/include/linux/netfilter_ipv4/ip_conntrack_amanda.h	2003-12-06 02:49:50.000000000 -0800
@@ -2,28 +2,11 @@
 #define _IP_CONNTRACK_AMANDA_H
 /* AMANDA tracking. */
 
-#ifdef __KERNEL__
-
-#include <linux/netfilter_ipv4/lockhelp.h>
-
-/* Protects amanda part of conntracks */
-DECLARE_LOCK_EXTERN(ip_amanda_lock);
-
-#endif
-
-struct conn {
-	char* match;
-	int matchlen;
-};
-
-#define NUM_MSGS 	3
-
-
 struct ip_ct_amanda_expect
 {
 	u_int16_t port;		/* port number of this expectation */
-	u_int16_t offset;	/* offset of the port specification in ctrl packet */
-	u_int16_t len;		/* the length of the port number specification */
+	u_int16_t offset;	/* offset of port in ctrl packet */
+	u_int16_t len;		/* length of the port number string */
 };
 
 #endif /* _IP_CONNTRACK_AMANDA_H */
diff -urN linux-2.4.23-bk3/include/linux/netfilter_ipv4/listhelp.h linux-2.4.23-bk4/include/linux/netfilter_ipv4/listhelp.h
--- linux-2.4.23-bk3/include/linux/netfilter_ipv4/listhelp.h	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-bk4/include/linux/netfilter_ipv4/listhelp.h	2003-12-06 02:49:50.000000000 -0800
@@ -11,48 +11,42 @@
    required to allow inlining of cmpfn. */
 #define LIST_FIND(head, cmpfn, type, args...)		\
 ({							\
-	const struct list_head *__i = (head);		\
+	const struct list_head *__i, *__j = NULL;	\
 							\
 	ASSERT_READ_LOCK(head);				\
-	do {						\
-		__i = __i->next;			\
-		if (__i == (head)) {			\
-			__i = NULL;			\
+	list_for_each(__i, (head))			\
+		if (cmpfn((const type)__i , ## args)) {	\
+			__j = __i;			\
 			break;				\
 		}					\
-	} while (!cmpfn((const type)__i , ## args));	\
-	(type)__i;					\
+	(type)__j;					\
 })
 
-#define LIST_FIND_W(head, cmpfn, type, args...)	\
-({						\
-	const struct list_head *__i = (head);	\
-						\
-	ASSERT_WRITE_LOCK(head);		\
-	do {					\
-		__i = __i->next;		\
-		if (__i == (head)) {		\
-			__i = NULL;		\
-			break;			\
-		}				\
-	} while (!cmpfn((type)__i , ## args));	\
-	(type)__i;				\
+#define LIST_FIND_W(head, cmpfn, type, args...)		\
+({							\
+	const struct list_head *__i, *__j = NULL;	\
+							\
+	ASSERT_WRITE_LOCK(head);			\
+	list_for_each(__i, (head))			\
+		if (cmpfn((const type)__i , ## args)) {	\
+			__j = __i;			\
+			break;				\
+		}					\
+	(type)__j;					\
 })
 
 /* Just like LIST_FIND but we search backwards */
 #define LIST_FIND_B(head, cmpfn, type, args...)		\
 ({							\
-	const struct list_head *__i = (head);		\
+	const struct list_head *__i, *__j = NULL;	\
 							\
 	ASSERT_READ_LOCK(head);				\
-	do {						\
-		__i = __i->prev;			\
-		if (__i == (head)) {			\
-			__i = NULL;			\
+	list_for_each_prev(__i, (head))			\
+		if (cmpfn((const type)__i , ## args)) {	\
+			__j = __i;			\
 			break;				\
 		}					\
-	} while (!cmpfn((const type)__i , ## args));	\
-	(type)__i;					\
+	(type)__j;					\
 })
 
 static inline int
@@ -100,9 +94,9 @@
 do {								\
 	struct list_head *__i;					\
 	ASSERT_WRITE_LOCK(head);				\
-	for (__i = (head)->next;				\
-	     !cmpfn((new), (typeof (new))__i) && __i != (head);	\
-	     __i = __i->next);					\
+	list_for_each(__i, (head))				\
+		if ((new), (typeof (new))__i)			\
+			break;					\
 	list_add((struct list_head *)(new), __i->prev);		\
 } while(0)
 
diff -urN linux-2.4.23-bk3/include/linux/rtnetlink.h linux-2.4.23-bk4/include/linux/rtnetlink.h
--- linux-2.4.23-bk3/include/linux/rtnetlink.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.23-bk4/include/linux/rtnetlink.h	2003-12-06 02:49:50.000000000 -0800
@@ -140,6 +140,7 @@
 #define RTPROT_ZEBRA	11	/* Zebra */
 #define RTPROT_BIRD	12	/* BIRD */
 #define RTPROT_DNROUTED	13	/* DECnet routing daemon */
+#define RTPROT_XORP	14	/* XORP */
 
 /* rtm_scope
 
diff -urN linux-2.4.23-bk3/include/linux/sysctl.h linux-2.4.23-bk4/include/linux/sysctl.h
--- linux-2.4.23-bk3/include/linux/sysctl.h	2003-12-06 02:49:46.000000000 -0800
+++ linux-2.4.23-bk4/include/linux/sysctl.h	2003-12-06 02:49:50.000000000 -0800
@@ -377,6 +377,7 @@
 	NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM=11,
 	NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12,
 	NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13,
+	NET_IPV4_NF_CONNTRACK_BUCKETS=14,
 };
  
 /* /proc/sys/net/ipv6 */
diff -urN linux-2.4.23-bk3/mm/filemap.c linux-2.4.23-bk4/mm/filemap.c
--- linux-2.4.23-bk3/mm/filemap.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.23-bk4/mm/filemap.c	2003-12-06 02:49:50.000000000 -0800
@@ -1299,11 +1299,14 @@
  */
 	ahead = 0;
 	while (ahead < max_ahead) {
-		ahead ++;
-		if ((raend + ahead) >= end_index)
+		unsigned long ra_index = raend + ahead + 1;
+
+		if (ra_index > end_index)
 			break;
-		if (page_cache_read(filp, raend + ahead) < 0)
+		if (page_cache_read(filp, ra_index) < 0)
 			break;
+
+		ahead++;
 	}
 /*
  * If we tried to read ahead some pages,
diff -urN linux-2.4.23-bk3/net/atm/br2684.c linux-2.4.23-bk4/net/atm/br2684.c
--- linux-2.4.23-bk3/net/atm/br2684.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.23-bk4/net/atm/br2684.c	2003-12-06 02:49:50.000000000 -0800
@@ -678,6 +678,7 @@
 	return -ENOIOCTLCMD;
 }
 
+#ifdef CONFIG_PROC_FS
 /* Never put more than 256 bytes in at once */
 static int br2684_proc_engine(loff_t pos, char *buf)
 {
@@ -770,16 +771,19 @@
 };
 
 extern struct proc_dir_entry *atm_proc_root;	/* from proc.c */
+#endif /* CONFIG_PROC_FS */
 
 /* the following avoids some spurious warnings from the compiler */
 #define UNUSED __attribute__((unused))
 
 static int __init UNUSED br2684_init(void)
 {
+#ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *p;
 	if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL)
 		return -ENOMEM;
 	p->proc_fops = &br2684_proc_operations;
+#endif /* CONFIG_PROC_FS */
 	br2684_ioctl_set(br2684_ioctl);
 	return 0;
 }
@@ -788,7 +792,9 @@
 {
 	struct br2684_dev *brdev;
 	br2684_ioctl_set(NULL);
+#ifdef CONFIG_PROC_FS
 	remove_proc_entry("br2684", atm_proc_root);
+#endif /* CONFIG_PROC_FS */
 	while (!list_empty(&br2684_devs)) {
 		brdev = list_entry_brdev(br2684_devs.next);
 		unregister_netdev(&brdev->net_dev);
diff -urN linux-2.4.23-bk3/net/ipv4/netfilter/ip_conntrack_amanda.c linux-2.4.23-bk4/net/ipv4/netfilter/ip_conntrack_amanda.c
--- linux-2.4.23-bk3/net/ipv4/netfilter/ip_conntrack_amanda.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.23-bk4/net/ipv4/netfilter/ip_conntrack_amanda.c	2003-12-06 02:49:50.000000000 -0800
@@ -18,13 +18,13 @@
  *
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/netfilter.h>
 #include <linux/ip.h>
 #include <net/checksum.h>
 #include <net/udp.h>
 
-#include <linux/netfilter_ipv4/lockhelp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
 
@@ -36,176 +36,96 @@
 MODULE_PARM(master_timeout, "i");
 MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
 
-DECLARE_LOCK(ip_amanda_lock);
-struct module *ip_conntrack_amanda = THIS_MODULE;
-
-#define MAXMATCHLEN	6
-struct conn conns[NUM_MSGS] = {
-	{"DATA ", 5},
-	{"MESG ", 5},
-	{"INDEX ", 6},
+static struct { char *match; int len; } conns[] = {
+	{ "DATA ", 5},
+	{ "MESG ", 5},
+	{ "INDEX ", 6},
 };
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
+#define NUM_MSGS 3
 
 
-/* FIXME: This should be in userspace.  Later. */
 static int help(const struct iphdr *iph, size_t len,
-		struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
+                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
 {
+	struct ip_conntrack_expect exp;
+	struct ip_ct_amanda_expect *exp_amanda_info;
 	struct udphdr *udph = (void *)iph + iph->ihl * 4;
 	u_int32_t udplen = len - iph->ihl * 4;
 	u_int32_t datalen = udplen - sizeof(struct udphdr);
 	char *data = (char *)udph + sizeof(struct udphdr);
-	char *datap = data;
-	char *data_limit = (char *) data + datalen;
-	int dir = CTINFO2DIR(ctinfo);
-	struct ip_ct_amanda *info =
-				(struct ip_ct_amanda *)&ct->help.ct_ftp_info;
-
-	/* Can't track connections formed before we registered */
-	if (!info)
-		return NF_ACCEPT;
-
-	/* increase the UDP timeout of the master connection as replies from
-	 * Amanda clients to the server can be quite delayed */
-	ip_ct_refresh(ct, master_timeout * HZ);
+	char *data_limit = data + datalen;
+	char *start = data, *tmp;
+	int i;
 
-	/* If packet is coming from Amanda server */
-	if (dir == IP_CT_DIR_ORIGINAL)
+	/* Only look at packets from the Amanda server */
+	if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
 		return NF_ACCEPT;
 
-	/* Not whole UDP header? */
 	if (udplen < sizeof(struct udphdr)) {
-		printk("ip_conntrack_amanda_help: udplen = %u\n",
-		       (unsigned)udplen);
+		if (net_ratelimit())
+			printk("amanda_help: udplen = %u\n", udplen);
 		return NF_ACCEPT;
 	}
 
-	/* Checksum invalid?  Ignore. */
-	if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
-			      csum_partial((char *)udph, udplen, 0))) {
-		DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u "
-		       "%u.%u.%u.%u\n",
-		       udph, udplen, NIPQUAD(iph->saddr),
-		       NIPQUAD(iph->daddr));
+	if (udph->check && 
+	    csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
+	                      csum_partial((char *)udph, udplen, 0)))
 		return NF_ACCEPT;
-	}
+
+	/* increase the UDP timeout of the master connection as replies from
+	 * Amanda clients to the server can be quite delayed */
+	ip_ct_refresh(ct, master_timeout * HZ);
 	
-	/* Search for the CONNECT string */
-	while (data < data_limit) {
+	/* Search for "CONNECT " string */
+	do {
+		if (data + 8 >= data_limit)
+			return NF_ACCEPT;
 		if (!memcmp(data, "CONNECT ", 8)) {
+			data += 8;
 			break;
 		}
 		data++;
-	}
-	if (memcmp(data, "CONNECT ", 8))
-		return NF_ACCEPT;
+	} while(1);
 
-	DEBUGP("ip_conntrack_amanda_help: CONNECT found in connection "
-		   "%u.%u.%u.%u:%u %u.%u.%u.%u:%u\n",
-		   NIPQUAD(iph->saddr), htons(udph->source),
-		   NIPQUAD(iph->daddr), htons(udph->dest));
-	data += 8;
-	while (*data != 0x0a && data < data_limit) {
-
-		int i;
-
-		for (i = 0; i < NUM_MSGS; i++) {
-			if (!memcmp(data, conns[i].match,
-				   conns[i].matchlen)) {
-
-				char *portchr;
-				struct ip_conntrack_expect expect;
-				struct ip_ct_amanda_expect
-				    *exp_amanda_info =
-					&expect.help.exp_amanda_info;
-
-				memset(&expect, 0, sizeof(expect));
-
-				data += conns[i].matchlen;
-				/* this is not really tcp, but let's steal an
-				 * idea from a tcp stream helper :-)
-				 */
-				// XXX expect.seq = data - datap;
-				exp_amanda_info->offset = data - datap;
-// XXX DEBUGP("expect.seq = %p - %p = %d\n", data, datap, expect.seq);
-DEBUGP("exp_amanda_info->offset = %p - %p = %d\n", data, datap, exp_amanda_info->offset);
-				portchr = data;
-				exp_amanda_info->port =
-				    simple_strtoul(data, &data, 10);
-				exp_amanda_info->len = data - portchr;
-
-				/* eat whitespace */
-				while (*data == ' ')
-					data++;
-				DEBUGP ("ip_conntrack_amanda_help: "
-					"CONNECT %s request with port "
-					"%u found\n", conns[i].match,
-					exp_amanda_info->port);
-
-				LOCK_BH(&ip_amanda_lock);
-
-				expect.tuple = ((struct ip_conntrack_tuple)
-						{ { ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip,
-						  { 0 } },
-				  		{ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip,
-						  { htons(exp_amanda_info->port) },
-				    	  IPPROTO_TCP }});
-				expect.mask = ((struct ip_conntrack_tuple)
-							   { { 0, { 0 } },
-				  				 { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
-
-				expect.expectfn = NULL;
-
-				DEBUGP ("ip_conntrack_amanda_help: "
-					"expect_related: %u.%u.%u.%u:%u - "
-					"%u.%u.%u.%u:%u\n",
-					NIPQUAD(expect.tuple.src.ip),
-					ntohs(expect.tuple.src.u.tcp.port),
-					NIPQUAD(expect.tuple.dst.ip),
-					ntohs(expect.tuple.dst.u.tcp.port));
-				if (ip_conntrack_expect_related(ct, &expect) ==
-				    -EEXIST) {
-					;
-					/* this must be a packet being resent */
-					/* XXX - how do I get the
-					 *       ip_conntrack_expect that
-					 *       already exists so that I can
-					 *       update the .seq so that the
-					 *       nat module rewrites the port
-					 *       numbers?
-					 *       Perhaps I should use the
-					 *       exp_amanda_info instead of
-					 *       .seq.
-					 */
-				}
-				UNLOCK_BH(&ip_amanda_lock);
-			} /* if memcmp(conns) */
-		} /* for .. NUM_MSGS */
-		data++;
-	} /* while (*data != 0x0a && data < data_limit) */
+	memset(&exp, 0, sizeof(exp));
+	exp.tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
+	exp.tuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
+	exp.tuple.dst.protonum = IPPROTO_TCP;
+	exp.mask.src.ip = 0xFFFFFFFF;
+	exp.mask.dst.ip = 0xFFFFFFFF;
+	exp.mask.dst.protonum = 0xFFFF;
+	exp.mask.dst.u.tcp.port = 0xFFFF;
+
+	exp_amanda_info = &exp.help.exp_amanda_info;
+	for (i = 0; data + conns[i].len < data_limit && *data != '\n'; data++) {
+		if (memcmp(data, conns[i].match, conns[i].len))
+			continue;
+		tmp = data += conns[i].len;
+		exp_amanda_info->offset = data - start;
+		exp_amanda_info->port   = simple_strtoul(data, &data, 10);
+		exp_amanda_info->len    = data - tmp;
+		if (exp_amanda_info->port == 0 || exp_amanda_info->len > 5)
+			break;
+
+		exp.tuple.dst.u.tcp.port = htons(exp_amanda_info->port);
+		ip_conntrack_expect_related(ct, &exp);
+		if (++i == NUM_MSGS)
+			break;
+	}
 
 	return NF_ACCEPT;
 }
 
 static struct ip_conntrack_helper amanda_helper;
 
-static void fini(void)
+static void __exit fini(void)
 {
-	DEBUGP("ip_ct_amanda: unregistering helper for port 10080\n");
 	ip_conntrack_helper_unregister(&amanda_helper);
 }
 
 static int __init init(void)
 {
-	int ret;
-
-	memset(&amanda_helper, 0, sizeof(struct ip_conntrack_helper));
 	amanda_helper.tuple.src.u.udp.port = htons(10080);
 	amanda_helper.tuple.dst.protonum = IPPROTO_UDP;
 	amanda_helper.mask.src.u.udp.port = 0xFFFF;
@@ -213,23 +133,12 @@
 	amanda_helper.max_expected = NUM_MSGS;
 	amanda_helper.timeout = 180;
 	amanda_helper.flags = IP_CT_HELPER_F_REUSE_EXPECT;
-	amanda_helper.me = ip_conntrack_amanda;
+	amanda_helper.me = THIS_MODULE;
 	amanda_helper.help = help;
 	amanda_helper.name = "amanda";
 
-	DEBUGP("ip_ct_amanda: registering helper for port 10080\n");
-
-	ret = ip_conntrack_helper_register(&amanda_helper);
-
-	if (ret) {
-		printk("ip_ct_amanda: ERROR registering helper\n");
-		fini();
-		return -EBUSY;
-	}
-	return 0;
+	return ip_conntrack_helper_register(&amanda_helper);
 }
 
-EXPORT_SYMBOL(ip_amanda_lock);
-
 module_init(init);
 module_exit(fini);
diff -urN linux-2.4.23-bk3/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.23-bk4/net/ipv4/netfilter/ip_conntrack_core.c
--- linux-2.4.23-bk3/net/ipv4/netfilter/ip_conntrack_core.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.23-bk4/net/ipv4/netfilter/ip_conntrack_core.c	2003-12-06 02:49:50.000000000 -0800
@@ -975,7 +975,6 @@
 		}
 	} else if (related_to->helper->max_expected && 
 		   related_to->expecting >= related_to->helper->max_expected) {
-		struct list_head *cur_item;
 		/* old == NULL */
 		if (!(related_to->helper->flags & 
 		      IP_CT_HELPER_F_REUSE_EXPECT)) {
@@ -1000,21 +999,14 @@
 		       NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
  
 		/* choose the the oldest expectation to evict */
-		list_for_each(cur_item, &related_to->sibling_list) { 
-			struct ip_conntrack_expect *cur;
-
-			cur = list_entry(cur_item, 
-					 struct ip_conntrack_expect,
-					 expected_list);
-			if (cur->sibling == NULL) {
-				old = cur;
+		list_for_each_entry(old, &related_to->sibling_list, 
+		                                      expected_list)
+			if (old->sibling == NULL)
 				break;
-			}
-		}
 
-		/* (!old) cannot happen, since related_to->expecting is the
-		 * number of unconfirmed expects */
-		IP_NF_ASSERT(old);
+		/* We cannot fail since related_to->expecting is the number
+		 * of unconfirmed expectations */
+		IP_NF_ASSERT(old && old->sibling == NULL);
 
 		/* newnat14 does not reuse the real allocated memory
 		 * structures but rather unexpects the old and
@@ -1046,7 +1038,7 @@
 	atomic_set(&new->use, 1);
 	
 	/* add to expected list for this connection */	
-	list_add(&new->expected_list, &related_to->sibling_list);
+	list_add_tail(&new->expected_list, &related_to->sibling_list);
 	/* add to global list of expectations */
 	list_prepend(&ip_conntrack_expect_list, &new->list);
 	/* add and start timer if required */
@@ -1266,14 +1258,13 @@
 /* Bring out ya dead! */
 static struct ip_conntrack_tuple_hash *
 get_next_corpse(int (*kill)(const struct ip_conntrack *i, void *data),
-		void *data)
+		void *data, unsigned int *bucket)
 {
 	struct ip_conntrack_tuple_hash *h = NULL;
-	unsigned int i;
 
 	READ_LOCK(&ip_conntrack_lock);
-	for (i = 0; !h && i < ip_conntrack_htable_size; i++) {
-		h = LIST_FIND(&ip_conntrack_hash[i], do_kill,
+	for (; !h && *bucket < ip_conntrack_htable_size; (*bucket)++) {
+		h = LIST_FIND(&ip_conntrack_hash[*bucket], do_kill,
 			      struct ip_conntrack_tuple_hash *, kill, data);
 	}
 	if (h)
@@ -1288,9 +1279,9 @@
 			void *data)
 {
 	struct ip_conntrack_tuple_hash *h;
+	unsigned int bucket = 0;
 
-	/* This is order n^2, by the way. */
-	while ((h = get_next_corpse(kill, data)) != NULL) {
+	while ((h = get_next_corpse(kill, data, &bucket)) != NULL) {
 		/* Time to push up daises... */
 		if (del_timer(&h->ctrack->timeout))
 			death_by_timeout((unsigned long)h->ctrack);
diff -urN linux-2.4.23-bk3/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.4.23-bk4/net/ipv4/netfilter/ip_conntrack_standalone.c
--- linux-2.4.23-bk3/net/ipv4/netfilter/ip_conntrack_standalone.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.23-bk4/net/ipv4/netfilter/ip_conntrack_standalone.c	2003-12-06 02:49:50.000000000 -0800
@@ -249,6 +249,7 @@
 
 /* From ip_conntrack_core.c */
 extern int ip_conntrack_max;
+extern unsigned int ip_conntrack_htable_size;
 
 /* From ip_conntrack_proto_tcp.c */
 extern unsigned long ip_ct_tcp_timeout_syn_sent;
@@ -276,6 +277,9 @@
 	{NET_IPV4_NF_CONNTRACK_MAX, "ip_conntrack_max",
 	 &ip_conntrack_max, sizeof(int), 0644, NULL,
 	 &proc_dointvec},
+	{NET_IPV4_NF_CONNTRACK_BUCKETS, "ip_conntrack_buckets",
+	 &ip_conntrack_htable_size, sizeof(unsigned int), 0444, NULL,
+	 &proc_dointvec},
 	{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, "ip_conntrack_tcp_timeout_syn_sent",
 	 &ip_ct_tcp_timeout_syn_sent, sizeof(unsigned int), 0644, NULL,
 	 &proc_dointvec_jiffies},
diff -urN linux-2.4.23-bk3/net/ipv4/netfilter/ip_conntrack_tftp.c linux-2.4.23-bk4/net/ipv4/netfilter/ip_conntrack_tftp.c
--- linux-2.4.23-bk3/net/ipv4/netfilter/ip_conntrack_tftp.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.23-bk4/net/ipv4/netfilter/ip_conntrack_tftp.c	2003-12-06 02:49:50.000000000 -0800
@@ -94,8 +94,6 @@
 
 	for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
 		/* Create helper structure */
-		memset(&tftp[i], 0, sizeof(struct ip_conntrack_helper));
-
 		tftp[i].tuple.dst.protonum = IPPROTO_UDP;
 		tftp[i].tuple.src.u.udp.port = htons(ports[i]);
 		tftp[i].mask.dst.protonum = 0xFFFF;
diff -urN linux-2.4.23-bk3/net/ipv4/netfilter/ip_fw_compat_masq.c linux-2.4.23-bk4/net/ipv4/netfilter/ip_fw_compat_masq.c
--- linux-2.4.23-bk3/net/ipv4/netfilter/ip_fw_compat_masq.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.23-bk4/net/ipv4/netfilter/ip_fw_compat_masq.c	2003-12-06 02:49:50.000000000 -0800
@@ -91,9 +91,6 @@
 			WRITE_UNLOCK(&ip_nat_lock);
 			return ret;
 		}
-
-		place_in_hashes(ct, info);
-		info->initialized = 1;
 	} else
 		DEBUGP("Masquerading already done on this conn.\n");
 	WRITE_UNLOCK(&ip_nat_lock);
diff -urN linux-2.4.23-bk3/net/ipv4/netfilter/ip_nat_amanda.c linux-2.4.23-bk4/net/ipv4/netfilter/ip_nat_amanda.c
--- linux-2.4.23-bk3/net/ipv4/netfilter/ip_nat_amanda.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.23-bk4/net/ipv4/netfilter/ip_nat_amanda.c	2003-12-06 02:49:50.000000000 -0800
@@ -11,69 +11,45 @@
  * 	insmod ip_nat_amanda.o
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter.h>
+#include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <linux/udp.h>
-#include <linux/kernel.h>
 #include <net/tcp.h>
 #include <net/udp.h>
 
+#include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv4/ip_nat.h>
 #include <linux/netfilter_ipv4/ip_nat_helper.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
 
 
-#if 0
-#define DEBUGP printk
-#define DUMP_OFFSET(x)	printk("offset_before=%d, offset_after=%d, correction_pos=%u\n", x->offset_before, x->offset_after, x->correction_pos);
-#else
-#define DEBUGP(format, args...)
-#define DUMP_OFFSET(x)
-#endif
-
 MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
-MODULE_DESCRIPTION("Amanda network address translation module");
+MODULE_DESCRIPTION("Amanda NAT helper");
 MODULE_LICENSE("GPL");
 
-/* protects amanda part of conntracks */
-DECLARE_LOCK_EXTERN(ip_amanda_lock);
-
 static unsigned int
 amanda_nat_expected(struct sk_buff **pskb,
-		 unsigned int hooknum,
-		 struct ip_conntrack *ct,
-		 struct ip_nat_info *info)
+                    unsigned int hooknum,
+                    struct ip_conntrack *ct,
+                    struct ip_nat_info *info)
 {
-	struct ip_nat_multi_range mr;
-	u_int32_t newdstip, newsrcip, newip;
-	u_int16_t port;
-	struct ip_ct_amanda_expect *exp_info;
 	struct ip_conntrack *master = master_ct(ct);
+	struct ip_ct_amanda_expect *exp_amanda_info;
+	struct ip_nat_multi_range mr;
+	u_int32_t newip;
 
 	IP_NF_ASSERT(info);
 	IP_NF_ASSERT(master);
-
 	IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
 
-	DEBUGP("nat_expected: We have a connection!\n");
-	exp_info = &ct->master->help.exp_amanda_info;
-
-	newdstip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
-	newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
-	DEBUGP("nat_expected: %u.%u.%u.%u->%u.%u.%u.%u\n",
-	       NIPQUAD(newsrcip), NIPQUAD(newdstip));
-
-	port = exp_info->port;
-
 	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
-		newip = newsrcip;
+		newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
 	else
-		newip = newdstip;
-
-	DEBUGP("nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
+		newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
 
 	mr.rangesize = 1;
 	/* We don't want to manip the per-protocol, just the IPs. */
@@ -81,121 +57,79 @@
 	mr.range[0].min_ip = mr.range[0].max_ip = newip;
 
 	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
+		exp_amanda_info = &ct->master->help.exp_amanda_info;
 		mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
 		mr.range[0].min = mr.range[0].max
 			= ((union ip_conntrack_manip_proto)
-				{ .udp = { htons(port) } });
+				{ .udp = { htons(exp_amanda_info->port) } });
 	}
 
 	return ip_nat_setup_info(ct, &mr, hooknum);
 }
 
 static int amanda_data_fixup(struct ip_conntrack *ct,
-			  struct sk_buff **pskb,
-			  enum ip_conntrack_info ctinfo,
-			  struct ip_conntrack_expect *expect)
+                             struct sk_buff **pskb,
+                             enum ip_conntrack_info ctinfo,
+                             struct ip_conntrack_expect *exp)
 {
-	u_int32_t newip;
-	/* DATA 99999 MESG 99999 INDEX 99999 */
-	char buffer[6];
-	struct ip_conntrack_expect *exp = expect;
-	struct ip_ct_amanda_expect *ct_amanda_info = &exp->help.exp_amanda_info;
+	struct ip_ct_amanda_expect *exp_amanda_info;
 	struct ip_conntrack_tuple t = exp->tuple;
+	char buffer[sizeof("65535")];
 	u_int16_t port;
 
-	MUST_BE_LOCKED(&ip_amanda_lock);
-
-	newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
-	DEBUGP ("ip_nat_amanda_help: newip = %u.%u.%u.%u\n", NIPQUAD(newip));
-
 	/* Alter conntrack's expectations. */
-
-	/* We can read expect here without conntrack lock, since it's
-	   only set in ip_conntrack_amanda, with ip_amanda_lock held
-	   writable */
-
-	t.dst.ip = newip;
-	for (port = ct_amanda_info->port; port != 0; port++) {
+	exp_amanda_info = &exp->help.exp_amanda_info;
+	t.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
+	for (port = exp_amanda_info->port; port != 0; port++) {
 		t.dst.u.tcp.port = htons(port);
 		if (ip_conntrack_change_expect(exp, &t) == 0)
 			break;
 	}
-
 	if (port == 0)
 		return 0;
 
 	sprintf(buffer, "%u", port);
-
-	return ip_nat_mangle_udp_packet(pskb, ct, ctinfo, /* XXX exp->seq */ ct_amanda_info->offset, 
-					ct_amanda_info->len, buffer, strlen(buffer));
+	return ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
+	                                exp_amanda_info->offset,
+	                                exp_amanda_info->len,
+	                                buffer, strlen(buffer));
 }
 
 static unsigned int help(struct ip_conntrack *ct,
-			 struct ip_conntrack_expect *exp,
-			 struct ip_nat_info *info,
-			 enum ip_conntrack_info ctinfo,
-			 unsigned int hooknum,
-			 struct sk_buff **pskb)
+                         struct ip_conntrack_expect *exp,
+                         struct ip_nat_info *info,
+                         enum ip_conntrack_info ctinfo,
+                         unsigned int hooknum,
+                         struct sk_buff **pskb)
 {
-	int dir;
+	int dir = CTINFO2DIR(ctinfo);
+	int ret = NF_ACCEPT;
 
-	if (!exp)
-		DEBUGP("ip_nat_amanda: no exp!!");
-		
 	/* Only mangle things once: original direction in POST_ROUTING
 	   and reply direction on PRE_ROUTING. */
-	dir = CTINFO2DIR(ctinfo);
 	if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
-	      || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
-		DEBUGP("ip_nat_amanda_help: Not touching dir %s at hook %s\n",
-		       dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
-		       hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
-		       : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
-		       : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT"
-		       : hooknum == NF_IP_LOCAL_IN ? "INPUT" : "???");
+	      || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
 		return NF_ACCEPT;
-	}
-	DEBUGP("ip_nat_amanda_help: got beyond not touching: dir %s at hook %s for expect: ",
-		   dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
-		   hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
-		   : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
-		     : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT"
-		       : hooknum == NF_IP_LOCAL_IN ? "INPUT" : "???");
-	DUMP_TUPLE(&exp->tuple);
 
-	LOCK_BH(&ip_amanda_lock);
-// XXX	if (exp->seq != 0)
+	/* if this exectation has a "offset" the packet needs to be mangled */
 	if (exp->help.exp_amanda_info.offset != 0)
-		/*  if this packet has a "seq" it needs to have it's content mangled */
-		if (!amanda_data_fixup(ct, pskb, ctinfo, exp)) {
-			UNLOCK_BH(&ip_amanda_lock);
-			DEBUGP("ip_nat_amanda: NF_DROP\n");
-			return NF_DROP;
-		}
+		if (!amanda_data_fixup(ct, pskb, ctinfo, exp))
+			ret = NF_DROP;
 	exp->help.exp_amanda_info.offset = 0;
-	UNLOCK_BH(&ip_amanda_lock);
 
-	DEBUGP("ip_nat_amanda: NF_ACCEPT\n");
-	return NF_ACCEPT;
+	return ret;
 }
 
 static struct ip_nat_helper ip_nat_amanda_helper;
 
-/* This function is intentionally _NOT_ defined as  __exit, because
- * it is needed by init() */
-static void fini(void)
+static void __exit fini(void)
 {
-	DEBUGP("ip_nat_amanda: unregistering nat helper\n");
 	ip_nat_helper_unregister(&ip_nat_amanda_helper);
 }
 
 static int __init init(void)
 {
-	int ret = 0;
-	struct ip_nat_helper *hlpr;
-
-	hlpr = &ip_nat_amanda_helper;
-	memset(hlpr, 0, sizeof(struct ip_nat_helper));
+	struct ip_nat_helper *hlpr = &ip_nat_amanda_helper;
 
 	hlpr->tuple.dst.protonum = IPPROTO_UDP;
 	hlpr->tuple.src.u.udp.port = htons(10080);
@@ -205,22 +139,10 @@
 	hlpr->flags = 0;
 	hlpr->me = THIS_MODULE;
 	hlpr->expect = amanda_nat_expected;
-
 	hlpr->name = "amanda";
 
-	DEBUGP
-	    ("ip_nat_amanda: Trying to register nat helper\n");
-	ret = ip_nat_helper_register(hlpr);
-
-	if (ret) {
-		printk
-		    ("ip_nat_amanda: error registering nat helper\n");
-		fini();
-		return 1;
-	}
-	return ret;
+	return ip_nat_helper_register(hlpr);
 }
 
-
 module_init(init);
 module_exit(fini);
diff -urN linux-2.4.23-bk3/net/ipv4/netfilter/ip_nat_core.c linux-2.4.23-bk4/net/ipv4/netfilter/ip_nat_core.c
--- linux-2.4.23-bk3/net/ipv4/netfilter/ip_nat_core.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.23-bk4/net/ipv4/netfilter/ip_nat_core.c	2003-12-06 02:49:50.000000000 -0800
@@ -815,7 +815,7 @@
 
 		/* Have to grab read lock before sibling_list traversal */
 		READ_LOCK(&ip_conntrack_lock);
-		list_for_each(cur_item, &ct->sibling_list) { 
+		list_for_each_prev(cur_item, &ct->sibling_list) { 
 			exp = list_entry(cur_item, struct ip_conntrack_expect, 
 					 expected_list);
 					 
diff -urN linux-2.4.23-bk3/net/ipv4/netfilter/ip_nat_tftp.c linux-2.4.23-bk4/net/ipv4/netfilter/ip_nat_tftp.c
--- linux-2.4.23-bk3/net/ipv4/netfilter/ip_nat_tftp.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.23-bk4/net/ipv4/netfilter/ip_nat_tftp.c	2003-12-06 02:49:50.000000000 -0800
@@ -160,8 +160,6 @@
 		ports[0] = TFTP_PORT;
 
 	for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
-		memset(&tftp[i], 0, sizeof(struct ip_nat_helper));
-
 		tftp[i].tuple.dst.protonum = IPPROTO_UDP;
 		tftp[i].tuple.src.u.udp.port = htons(ports[i]);
 		tftp[i].mask.dst.protonum = 0xFFFF;
diff -urN linux-2.4.23-bk3/net/ipv4/netfilter/ipt_MASQUERADE.c linux-2.4.23-bk4/net/ipv4/netfilter/ipt_MASQUERADE.c
--- linux-2.4.23-bk3/net/ipv4/netfilter/ipt_MASQUERADE.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.23-bk4/net/ipv4/netfilter/ipt_MASQUERADE.c	2003-12-06 02:49:50.000000000 -0800
@@ -124,63 +124,37 @@
 }
 
 static inline int
-device_cmp(const struct ip_conntrack *i, void *ifindex)
+device_cmp(const struct ip_conntrack *i, void *_ina)
 {
-	int ret;
+	int ret = 0;
+	struct in_ifaddr *ina = _ina;
 
 	READ_LOCK(&masq_lock);
-	ret = (i->nat.masq_index == (int)(long)ifindex);
+	/* If it's masquerading out this interface with a different address,
+	 * or we don't know the new address of this interface. */
+	if (i->nat.masq_index == ina->ifa_dev->dev->ifindex
+	    && i->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip != ina->ifa_address)
+		ret = 1;
 	READ_UNLOCK(&masq_lock);
 
 	return ret;
 }
 
-static int masq_device_event(struct notifier_block *this,
-			     unsigned long event,
-			     void *ptr)
-{
-	struct net_device *dev = ptr;
-
-	if (event == NETDEV_DOWN) {
-		/* Device was downed.  Search entire table for
-		   conntracks which were associated with that device,
-		   and forget them. */
-		IP_NF_ASSERT(dev->ifindex != 0);
-
-		ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
-	}
-
-	return NOTIFY_DONE;
-}
-
 static int masq_inet_event(struct notifier_block *this,
 			   unsigned long event,
 			   void *ptr)
 {
-	struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
-
-	if (event == NETDEV_DOWN) {
-		/* IP address was deleted.  Search entire table for
-		   conntracks which were associated with that device,
-		   and forget them. */
-		IP_NF_ASSERT(dev->ifindex != 0);
-
-		ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
-	}
+	/* For some configurations, interfaces often come back with
+	 * the same address.  If not, clean up old conntrack
+	 * entries. */
+	if (event == NETDEV_UP)
+		ip_ct_selective_cleanup(device_cmp, ptr);
 
 	return NOTIFY_DONE;
 }
 
-static struct notifier_block masq_dev_notifier = {
-	masq_device_event,
-	NULL,
-	0
-};
-
 static struct notifier_block masq_inet_notifier = {
-	masq_inet_event,
-	NULL,
-	0
+	.notifier_call = masq_inet_event
 };
 
 static struct ipt_target masquerade
@@ -193,12 +167,9 @@
 
 	ret = ipt_register_target(&masquerade);
 
-	if (ret == 0) {
-		/* Register for device down reports */
-		register_netdevice_notifier(&masq_dev_notifier);
+	if (ret == 0)
 		/* Register IP address change reports */
 		register_inetaddr_notifier(&masq_inet_notifier);
-	}
 
 	return ret;
 }
@@ -206,7 +177,6 @@
 static void __exit fini(void)
 {
 	ipt_unregister_target(&masquerade);
-	unregister_netdevice_notifier(&masq_dev_notifier);
 	unregister_inetaddr_notifier(&masq_inet_notifier);	
 }
 
diff -urN linux-2.4.23-bk3/net/ipv4/netfilter/ipt_recent.c linux-2.4.23-bk4/net/ipv4/netfilter/ipt_recent.c
--- linux-2.4.23-bk3/net/ipv4/netfilter/ipt_recent.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-bk4/net/ipv4/netfilter/ipt_recent.c	2003-12-06 02:49:50.000000000 -0800
@@ -91,8 +91,10 @@
  */
 static spinlock_t recent_lock = SPIN_LOCK_UNLOCKED;
 
+#ifdef CONFIG_PROC_FS
 /* Our /proc/net/ipt_recent entry */
 static struct proc_dir_entry *proc_net_ipt_recent = NULL;
+#endif
 
 /* Function declaration for later. */
 static int
@@ -963,8 +965,10 @@
 	int count;
 
 	printk(version);
+#ifdef CONFIG_PROC_FS
 	proc_net_ipt_recent = proc_mkdir("ipt_recent",proc_net);
 	if(!proc_net_ipt_recent) return -ENOMEM;
+#endif
 
 	if(ip_list_hash_size && ip_list_hash_size <= ip_list_tot) {
 	  printk(KERN_WARNING RECENT_NAME ": ip_list_hash_size too small, resetting to default.\n");
diff -urN linux-2.4.23-bk3/net/ipv6/mcast.c linux-2.4.23-bk4/net/ipv6/mcast.c
--- linux-2.4.23-bk3/net/ipv6/mcast.c	2003-12-06 02:49:46.000000000 -0800
+++ linux-2.4.23-bk4/net/ipv6/mcast.c	2003-12-06 02:49:50.000000000 -0800
@@ -45,6 +45,9 @@
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv6.h>
+
 #include <net/sock.h>
 #include <net/snmp.h>
 
@@ -1264,7 +1267,7 @@
 {
 	struct ipv6hdr *pip6 = skb->nh.ipv6h;
 	struct mld2_report *pmr = (struct mld2_report *)skb->h.raw;
-	int payload_len, mldlen;
+	int payload_len, mldlen, err;
 
 	payload_len = skb->tail - (unsigned char *)skb->nh.ipv6h -
 		sizeof(struct ipv6hdr);
@@ -1273,8 +1276,10 @@
 
 	pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
 		IPPROTO_ICMPV6, csum_partial(skb->h.raw, mldlen, 0));
-	dev_queue_xmit(skb);
-	ICMP6_INC_STATS(Icmp6OutMsgs);
+	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
+		      dev_queue_xmit);
+	if (!err)
+		ICMP6_INC_STATS(Icmp6OutMsgs);
 }
 
 static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel)
@@ -1598,12 +1603,16 @@
 					   IPPROTO_ICMPV6,
 					   csum_partial((__u8 *) hdr, len, 0));
 
-	dev_queue_xmit(skb);
-	if (type == ICMPV6_MGM_REDUCTION)
-		ICMP6_INC_STATS(Icmp6OutGroupMembReductions);
-	else
-		ICMP6_INC_STATS(Icmp6OutGroupMembResponses);
-	ICMP6_INC_STATS(Icmp6OutMsgs);
+	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
+		      dev_queue_xmit);
+	if (!err) {
+		if (type == ICMPV6_MGM_REDUCTION)
+			ICMP6_INC_STATS(Icmp6OutGroupMembReductions);
+		else
+			ICMP6_INC_STATS(Icmp6OutGroupMembResponses);
+		ICMP6_INC_STATS(Icmp6OutMsgs);
+	}
+
 	return;
 
 out:
