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

diff -urN linux-2.4.22-bk10/Makefile linux-2.4.22-bk11/Makefile
--- linux-2.4.22-bk10/Makefile	2003-09-05 03:07:24.000000000 -0700
+++ linux-2.4.22-bk11/Makefile	2003-09-05 03:07:37.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 22
-EXTRAVERSION = -bk10
+EXTRAVERSION = -bk11
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.22-bk10/drivers/block/umem.c linux-2.4.22-bk11/drivers/block/umem.c
--- linux-2.4.22-bk10/drivers/block/umem.c	2003-06-13 07:51:32.000000000 -0700
+++ linux-2.4.22-bk11/drivers/block/umem.c	2003-09-05 03:07:40.000000000 -0700
@@ -1307,7 +1307,7 @@
 	release_mem_region(card->mem_base, card->mem_len);
  failed_req_mem:
 #endif
-	iounmap((void *) card->csr_base);
+	iounmap((void *) card->csr_remap);
  failed_remap_csr:
 	release_mem_region(card->csr_base, card->csr_len);
  failed_req_csr:
diff -urN linux-2.4.22-bk10/drivers/char/Config.in linux-2.4.22-bk11/drivers/char/Config.in
--- linux-2.4.22-bk10/drivers/char/Config.in	2003-09-05 03:07:28.000000000 -0700
+++ linux-2.4.22-bk11/drivers/char/Config.in	2003-09-05 03:07:42.000000000 -0700
@@ -267,7 +267,7 @@
 fi
 dep_tristate 'NatSemi SCx200 GPIO Support' CONFIG_SCx200_GPIO $CONFIG_SCx200
 
-if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_SGI_SN2" = 'y' ] ; then
+if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ] ; then
    bool 'SGI SN2 fetchop support' CONFIG_FETCHOP
 fi
 
diff -urN linux-2.4.22-bk10/drivers/char/n_hdlc.c linux-2.4.22-bk11/drivers/char/n_hdlc.c
--- linux-2.4.22-bk10/drivers/char/n_hdlc.c	2002-02-25 11:37:57.000000000 -0800
+++ linux-2.4.22-bk11/drivers/char/n_hdlc.c	2003-09-05 03:07:42.000000000 -0700
@@ -9,7 +9,7 @@
  *	Al Longyear <longyear@netcom.com>, Paul Mackerras <Paul.Mackerras@cs.anu.edu.au>
  *
  * Original release 01/11/99
- * $Id: n_hdlc.c,v 3.3 2001/11/08 16:16:03 paulkf Exp $
+ * $Id: n_hdlc.c,v 3.7 2003/05/01 15:45:29 paulkf Exp $
  *
  * This code is released under the GNU General Public License (GPL)
  *
@@ -78,7 +78,7 @@
  */
 
 #define HDLC_MAGIC 0x239e
-#define HDLC_VERSION "$Revision: 3.3 $"
+#define HDLC_VERSION "$Revision: 3.7 $"
 
 #include <linux/version.h>
 #include <linux/config.h>
@@ -172,9 +172,9 @@
 /*
  * HDLC buffer list manipulation functions
  */
-void n_hdlc_buf_list_init(N_HDLC_BUF_LIST *list);
-void n_hdlc_buf_put(N_HDLC_BUF_LIST *list,N_HDLC_BUF *buf);
-N_HDLC_BUF* n_hdlc_buf_get(N_HDLC_BUF_LIST *list);
+static void n_hdlc_buf_list_init(N_HDLC_BUF_LIST *list);
+static void n_hdlc_buf_put(N_HDLC_BUF_LIST *list,N_HDLC_BUF *buf);
+static N_HDLC_BUF* n_hdlc_buf_get(N_HDLC_BUF_LIST *list);
 
 /* Local functions */
 
@@ -183,13 +183,16 @@
 MODULE_PARM(debuglevel, "i");
 MODULE_PARM(maxframe, "i");
 
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
 
 /* debug level can be set by insmod for debugging purposes */
 #define DEBUG_LEVEL_INFO	1
-int debuglevel=0;
+static int debuglevel=0;
 
 /* max frame size for memory allocations */
-ssize_t	maxframe=4096;
+static ssize_t	maxframe=4096;
 
 /* TTY callbacks */
 
@@ -265,7 +268,8 @@
 		} else
 			break;
 	}
-	
+	if (n_hdlc->tbuf)
+		kfree(n_hdlc->tbuf);
 	kfree(n_hdlc);
 	
 }	/* end of n_hdlc_release() */
@@ -905,7 +909,7 @@
  * Arguments:	 	list	pointer to buffer list
  * Return Value:	None	
  */
-void n_hdlc_buf_list_init(N_HDLC_BUF_LIST *list)
+static void n_hdlc_buf_list_init(N_HDLC_BUF_LIST *list)
 {
 	memset(list,0,sizeof(N_HDLC_BUF_LIST));
 	spin_lock_init(&list->spinlock);
@@ -922,7 +926,7 @@
  * 
  * Return Value:	None	
  */
-void n_hdlc_buf_put(N_HDLC_BUF_LIST *list,N_HDLC_BUF *buf)
+static void n_hdlc_buf_put(N_HDLC_BUF_LIST *list,N_HDLC_BUF *buf)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&list->spinlock,flags);
@@ -952,7 +956,7 @@
  * 
  * 	pointer to HDLC buffer if available, otherwise NULL
  */
-N_HDLC_BUF* n_hdlc_buf_get(N_HDLC_BUF_LIST *list)
+static N_HDLC_BUF* n_hdlc_buf_get(N_HDLC_BUF_LIST *list)
 {
 	unsigned long flags;
 	N_HDLC_BUF *buf;
@@ -1025,5 +1029,4 @@
 module_init(n_hdlc_init);
 module_exit(n_hdlc_exit);
 
-MODULE_LICENSE("GPL");
 EXPORT_NO_SYMBOLS;
diff -urN linux-2.4.22-bk10/drivers/char/pcmcia/synclink_cs.c linux-2.4.22-bk11/drivers/char/pcmcia/synclink_cs.c
--- linux-2.4.22-bk10/drivers/char/pcmcia/synclink_cs.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.22-bk11/drivers/char/pcmcia/synclink_cs.c	2003-09-05 03:07:42.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/synclink_cs.c
  *
- * $Id: synclink_cs.c,v 3.4 2002/04/22 14:36:41 paulkf Exp $
+ * $Id: synclink_cs.c,v 3.9 2003/05/23 20:16:41 paulkf Exp $
  *
  * Device driver for Microgate SyncLink PC Card
  * multiprotocol serial adapter.
@@ -483,6 +483,7 @@
 
 static int debug_level = 0;
 static int maxframe[MAX_DEVICE_COUNT] = {0,};
+static int dosyncppp[MAX_DEVICE_COUNT] = {1,1,1,1};
 
 /* The old way: bit map of interrupts to choose from */
 /* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
@@ -499,9 +500,14 @@
 MODULE_PARM(cuamajor,"i");
 MODULE_PARM(debug_level,"i");
 MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i");
+MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i");
+
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
 
 static char *driver_name = "SyncLink PC Card driver";
-static char *driver_version = "$Revision: 3.4 $";
+static char *driver_version = "$Revision: 3.9 $";
 
 static struct tty_driver serial_driver, callout_driver;
 static int serial_refcount;
@@ -2616,14 +2622,17 @@
 {
 	MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
 
-	if (!info || mgslpc_paranoia_check(info, tty->device, "mgslpc_close"))
+	if (mgslpc_paranoia_check(info, tty->device, "mgslpc_close"))
 		return;
 	
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",
 			 __FILE__,__LINE__, info->device_name, info->count);
 			 
-	if (!info->count || tty_hung_up_p(filp))
+	if (!info->count)
+		return;
+
+	if (tty_hung_up_p(filp))
 		goto cleanup;
 			
 	if ((tty->count == 1) && (info->count != 1)) {
@@ -2747,7 +2756,7 @@
 			schedule_timeout(char_time);
 			if (signal_pending(current))
 				break;
-			if (timeout && ((orig_jiffies + timeout) < jiffies))
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
 				break;
 		}
 	} else {
@@ -2757,7 +2766,7 @@
 			schedule_timeout(char_time);
 			if (signal_pending(current))
 				break;
-			if (timeout && ((orig_jiffies + timeout) < jiffies))
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
 				break;
 		}
 	}
@@ -2937,16 +2946,11 @@
 	info = mgslpc_device_list;
 	while(info && info->line != line)
 		info = info->next_device;
-	if ( !info ){
-		printk("%s(%d):Can't find specified device on open (line=%d)\n",
-			__FILE__,__LINE__,line);
+	if (mgslpc_paranoia_check(info, tty->device, "mgslpc_open"))
 		return -ENODEV;
-	}
 	
 	tty->driver_data = info;
 	info->tty = tty;
-	if (mgslpc_paranoia_check(info, tty->device, "mgslpc_open"))
-		return -ENODEV;
 		
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgslpc_open(%s), old ref count = %d\n",
@@ -3008,6 +3012,8 @@
 	
 cleanup:			
 	if (retval) {
+		if (tty->count == 1)
+			info->tty = 0; /* tty layer will release tty struct */
 		if(MOD_IN_USE)
 			MOD_DEC_USE_COUNT;
 		if(info->count)
@@ -3181,8 +3187,7 @@
 	if (info->line < MAX_DEVICE_COUNT) {
 		if (maxframe[info->line])
 			info->max_frame_size = maxframe[info->line];
-//		info->dosyncppp = dosyncppp[info->line];
-		info->dosyncppp = 1;
+		info->dosyncppp = dosyncppp[info->line];
 	}
 
 	mgslpc_device_count++;
diff -urN linux-2.4.22-bk10/drivers/char/synclink.c linux-2.4.22-bk11/drivers/char/synclink.c
--- linux-2.4.22-bk10/drivers/char/synclink.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.22-bk11/drivers/char/synclink.c	2003-09-05 03:07:42.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/synclink.c
  *
- * $Id: synclink.c,v 3.12 2001/07/18 19:14:21 paulkf Exp $
+ * $Id: synclink.c,v 3.20 2003/07/16 19:51:07 paulkf Exp $
  *
  * Device driver for Microgate SyncLink ISA and PCI
  * high speed multiprotocol serial adapters.
@@ -198,6 +198,7 @@
 	int			flags;
 	int			count;		/* count of opens */
 	int			line;
+	int                     hw_version;
 	unsigned short		close_delay;
 	unsigned short		closing_wait;	/* time to wait before closing */
 	
@@ -270,6 +271,7 @@
 
 	int rx_enabled;
 	int rx_overflow;
+	int rx_rcc_underrun;
 
 	int tx_enabled;
 	int tx_active;
@@ -922,7 +924,7 @@
 MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
 
 static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "$Revision: 3.12 $";
+static char *driver_version = "$Revision: 3.20 $";
 
 static int __init synclink_init_one (struct pci_dev *dev,
 				     const struct pci_device_id *ent);
@@ -930,17 +932,20 @@
 
 static struct pci_device_id synclink_pci_tbl[] __devinitdata = {
 	{ PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_USC, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_MICROGATE, 0x0210, PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0, }, /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, synclink_pci_tbl);
 
+#ifdef MODULE_LICENSE
 MODULE_LICENSE("GPL");
+#endif
 
 static struct pci_driver synclink_pci_driver = {
 	name:		"synclink",
 	id_table:	synclink_pci_tbl,
 	probe:		synclink_init_one,
-	remove:		__devexit_p(synclink_remove_one),
+	remove:		synclink_remove_one,
 };
 
 static struct tty_driver serial_driver, callout_driver;
@@ -1140,8 +1145,16 @@
 	if ( debug_level >= DEBUG_LEVEL_BH )
 		printk( "%s(%d):mgsl_bh_receive(%s)\n",
 			__FILE__,__LINE__,info->device_name);
-	
-	while( (get_rx_frame)(info) );
+	do
+	{
+		if (info->rx_rcc_underrun) {
+			unsigned long flags;
+			spin_lock_irqsave(&info->irq_spinlock,flags);
+			usc_start_receiver(info);
+			spin_unlock_irqrestore(&info->irq_spinlock,flags);
+			return;
+		}
+	} while(get_rx_frame(info));
 }
 
 void mgsl_bh_transmit(struct mgsl_struct *info)
@@ -1583,6 +1596,21 @@
 	if ( debug_level >= DEBUG_LEVEL_ISR )	
 		printk("%s(%d):mgsl_isr_misc status=%04X\n",
 			__FILE__,__LINE__,status);
+
+	if ((status & MISCSTATUS_RCC_UNDERRUN) &&
+	    (info->params.mode == MGSL_MODE_HDLC)) {
+
+		/* turn off receiver and rx DMA */
+		usc_EnableReceiver(info,DISABLE_UNCONDITIONAL);
+		usc_DmaCmd(info, DmaCmd_ResetRxChannel);
+		usc_UnlatchRxstatusBits(info, RXSTATUS_ALL);
+		usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS);
+		usc_DisableInterrupts(info, RECEIVE_DATA + RECEIVE_STATUS);
+
+		/* schedule BH handler to restart receiver */
+		info->pending_bh |= BH_RECEIVE;
+		info->rx_rcc_underrun = 1;
+	}
 			
 	usc_ClearIrqPendingBits( info, MISC );
 	usc_UnlatchMiscstatusBits( info, status );
@@ -3251,14 +3279,17 @@
 {
 	struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
 
-	if (!info || mgsl_paranoia_check(info, tty->device, "mgsl_close"))
+	if (mgsl_paranoia_check(info, tty->device, "mgsl_close"))
 		return;
 	
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgsl_close(%s) entry, count=%d\n",
 			 __FILE__,__LINE__, info->device_name, info->count);
 			 
-	if (!info->count || tty_hung_up_p(filp))
+	if (!info->count)
+		return;
+
+	if (tty_hung_up_p(filp))
 		goto cleanup;
 			
 	if ((tty->count == 1) && (info->count != 1)) {
@@ -3393,7 +3424,7 @@
 			schedule_timeout(char_time);
 			if (signal_pending(current))
 				break;
-			if (timeout && ((orig_jiffies + timeout) < jiffies))
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
 				break;
 		}
 	} else {
@@ -3403,7 +3434,7 @@
 			schedule_timeout(char_time);
 			if (signal_pending(current))
 				break;
-			if (timeout && ((orig_jiffies + timeout) < jiffies))
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
 				break;
 		}
 	}
@@ -3612,16 +3643,11 @@
 	info = mgsl_device_list;
 	while(info && info->line != line)
 		info = info->next_device;
-	if ( !info ){
-		printk("%s(%d):Can't find specified device on open (line=%d)\n",
-			__FILE__,__LINE__,line);
+	if (mgsl_paranoia_check(info, tty->device, "mgsl_open"))
 		return -ENODEV;
-	}
 	
 	tty->driver_data = info;
 	info->tty = tty;
-	if (mgsl_paranoia_check(info, tty->device, "mgsl_open"))
-		return -ENODEV;
 		
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgsl_open(%s), old ref count = %d\n",
@@ -3695,6 +3721,8 @@
 	
 cleanup:			
 	if (retval) {
+		if (tty->count == 1)
+			info->tty = 0; /* tty layer will release tty struct */
 		if(MOD_IN_USE)
 			MOD_DEC_USE_COUNT;
 		if(info->count)
@@ -3760,7 +3788,7 @@
 		if (info->icount.rxover)
 			ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover);
 		if (info->icount.rxcrc)
-			ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxcrc);
+			ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc);
 	} else {
 		ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d",
 			      info->icount.tx, info->icount.rx);
@@ -4291,9 +4319,7 @@
 				info->get_tx_holding_index=0;
 
 			/* restart transmit timer */
-			del_timer(&info->tx_timer);
-			info->tx_timer.expires = jiffies + jiffies_from_ms(5000);
-			add_timer(&info->tx_timer);
+			mod_timer(&info->tx_timer, jiffies + jiffies_from_ms(5000));
 
 			ret = 1;
 		}
@@ -4511,12 +4537,12 @@
 		info->max_frame_size = 65535;
 	
 	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		printk( "SyncLink device %s added:PCI bus IO=%04X IRQ=%d Mem=%08X LCR=%08X MaxFrameSize=%u\n",
-			info->device_name, info->io_base, info->irq_level,
+		printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n",
+			info->hw_version + 1, info->device_name, info->io_base, info->irq_level,
 			info->phys_memory_base, info->phys_lcr_base,
 		     	info->max_frame_size );
 	} else {
-		printk( "SyncLink device %s added:ISA bus IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n",
+		printk( "SyncLink ISA %s: IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n",
 			info->device_name, info->io_base, info->irq_level, info->dma_level,
 		     	info->max_frame_size );
 	}
@@ -5367,7 +5393,11 @@
 	usc_EnableMasterIrqBit( info );
 
 	usc_ClearIrqPendingBits( info, RECEIVE_STATUS + RECEIVE_DATA +
-				TRANSMIT_STATUS + TRANSMIT_DATA );
+				TRANSMIT_STATUS + TRANSMIT_DATA + MISC);
+
+	/* arm RCC underflow interrupt */
+	usc_OutReg(info, SICR, (u16)(usc_InReg(info,SICR) | BIT3));
+	usc_EnableInterrupts(info, MISC);
 
 	info->mbre_bit = 0;
 	outw( 0, info->io_base ); 			/* clear Master Bus Enable (DCAR) */
@@ -5375,10 +5405,11 @@
 	info->mbre_bit = BIT8;
 	outw( BIT8, info->io_base );			/* set Master Bus Enable (DCAR) */
 
-	/* Enable DMAEN (Port 7, Bit 14) */
-	/* This connects the DMA request signal to the ISA bus */
-	/* on the ISA adapter. This has no effect for the PCI adapter */
-	usc_OutReg( info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) & ~BIT14) );
+	if (info->bus_type == MGSL_BUS_TYPE_ISA) {
+		/* Enable DMAEN (Port 7, Bit 14) */
+		/* This connects the DMA request signal to the ISA bus */
+		usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) & ~BIT14));
+	}
 
 	/* DMA Control Register (DCR)
 	 *
@@ -5804,6 +5835,7 @@
 
 	info->rx_enabled = 0;
 	info->rx_overflow = 0;
+	info->rx_rcc_underrun = 0;
 	
 }	/* end of stop_receiver() */
 
@@ -6355,10 +6387,11 @@
 
 	usc_EnableMasterIrqBit( info );
 
-	/* Enable INTEN (Port 6, Bit12) */
-	/* This connects the IRQ request signal to the ISA bus */
-	/* on the ISA adapter. This has no effect for the PCI adapter */
-	usc_OutReg( info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12) );
+	if (info->bus_type == MGSL_BUS_TYPE_ISA) {
+		/* Enable INTEN (Port 6, Bit12) */
+		/* This connects the IRQ request signal to the ISA bus */
+		usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
+	}
 
 }	/* end of usc_set_async_mode() */
 
@@ -6449,10 +6482,11 @@
 	usc_loopback_frame( info );
 	usc_set_sdlc_mode( info );
 
-	/* Enable INTEN (Port 6, Bit12) */
-	/* This connects the IRQ request signal to the ISA bus */
-	/* on the ISA adapter. This has no effect for the PCI adapter */
-	usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
+	if (info->bus_type == MGSL_BUS_TYPE_ISA) {
+		/* Enable INTEN (Port 6, Bit12) */
+		/* This connects the IRQ request signal to the ISA bus */
+		usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
+	}
 
 	usc_enable_aux_clock(info, info->params.clock_speed);
 
@@ -7496,7 +7530,7 @@
 	EndTime = jiffies + jiffies_from_ms(100);
 
 	for(;;) {
-		if ( jiffies > EndTime ) {
+		if (time_after(jiffies, EndTime)) {
 			rc = FALSE;
 			break;
 		}
@@ -7552,7 +7586,7 @@
 	EndTime = jiffies + jiffies_from_ms(100);
 
 	for(;;) {
-		if ( jiffies > EndTime ) {
+		if (time_after(jiffies, EndTime)) {
 			rc = FALSE;
 			break;
 		}
@@ -7600,7 +7634,7 @@
 		spin_unlock_irqrestore(&info->irq_spinlock,flags);
 
 		while ( !(status & (BIT6+BIT5+BIT4+BIT2+BIT1)) ) {
-			if ( jiffies > EndTime ) {
+			if (time_after(jiffies, EndTime)) {
 				rc = FALSE;
 				break;
 			}
@@ -7627,8 +7661,7 @@
 		/* Wait for 16C32 to write receive status to buffer entry. */
 		status=info->rx_buffer_list[0].status;
 		while ( status == 0 ) {
-			if ( jiffies > EndTime ) {
-			printk(KERN_ERR"mark 4\n");
+			if (time_after(jiffies, EndTime)) {
 				rc = FALSE;
 				break;
 			}
@@ -8202,17 +8235,20 @@
 	info->bus_type = MGSL_BUS_TYPE_PCI;
 	info->io_addr_size = 8;
 	info->irq_flags = SA_SHIRQ;
-		
-	/* Store the PCI9050 misc control register value because a flaw
-	 * in the PCI9050 prevents LCR registers from being read if 
-	 * BIOS assigns an LCR base address with bit 7 set.
-	 *  
-	 * Only the misc control register is accessed for which only 
-	 * write access is needed, so set an initial value and change 
-	 * bits to the device instance data as we write the value
-	 * to the actual misc control register.
-	 */
-	info->misc_ctrl_value = 0x087e4546;
+
+	if (dev->device == 0x0210) {
+		/* Version 1 PCI9030 based universal PCI adapter */
+		info->misc_ctrl_value = 0x007c4080;
+		info->hw_version = 1;
+	} else {
+		/* Version 0 PCI9050 based 5V PCI adapter
+		 * A PCI9050 bug prevents reading LCR registers if 
+		 * LCR base address bit 7 is set. Maintain shadow
+		 * value so we can write to LCR misc control reg.
+		 */
+		info->misc_ctrl_value = 0x087e4546;
+		info->hw_version = 0;
+	}
 				
 	mgsl_add_device(info);
 
diff -urN linux-2.4.22-bk10/drivers/char/synclinkmp.c linux-2.4.22-bk11/drivers/char/synclinkmp.c
--- linux-2.4.22-bk10/drivers/char/synclinkmp.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.22-bk11/drivers/char/synclinkmp.c	2003-09-05 03:07:42.000000000 -0700
@@ -1,5 +1,5 @@
 /*
- * $Id: synclinkmp.c,v 3.17 2002/04/22 16:05:39 paulkf Exp $
+ * $Id: synclinkmp.c,v 3.21 2003/06/18 21:02:26 paulkf Exp $
  *
  * Device driver for Microgate SyncLink Multiport
  * high speed multiprotocol serial adapter.
@@ -504,7 +504,7 @@
 MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i");
 
 static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 3.17 $";
+static char *driver_version = "$Revision: 3.21 $";
 
 static int __devinit synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
 static void __devexit synclinkmp_remove_one(struct pci_dev *dev);
@@ -515,6 +515,10 @@
 };
 MODULE_DEVICE_TABLE(pci, synclinkmp_pci_tbl);
 
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
 static struct pci_driver synclinkmp_pci_driver = {
 	name:		"synclinkmp",
 	id_table:	synclinkmp_pci_tbl,
@@ -748,12 +752,8 @@
 	info = synclinkmp_device_list;
 	while(info && info->line != line)
 		info = info->next_device;
-	if ( !info ){
-		printk("%s(%d):%s Can't find specified device on open (line=%d)\n",
-			__FILE__,__LINE__,info->device_name,line);
+	if (sanity_check(info, tty->device, "open"))
 		return -ENODEV;
-	}
-
 	if ( info->init_error ) {
 		printk("%s(%d):%s device is not allocated, init error=%d\n",
 			__FILE__,__LINE__,info->device_name,info->init_error);
@@ -762,8 +762,6 @@
 
 	tty->driver_data = info;
 	info->tty = tty;
-	if (sanity_check(info, tty->device, "open"))
-		return -ENODEV;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):%s open(), old ref count = %d\n",
@@ -825,6 +823,8 @@
 
 cleanup:
 	if (retval) {
+		if (tty->count == 1)
+			info->tty = 0; /* tty layer will release tty struct */
 		if(MOD_IN_USE)
 			MOD_DEC_USE_COUNT;
 		if(info->count)
@@ -841,14 +841,17 @@
 {
 	SLMP_INFO * info = (SLMP_INFO *)tty->driver_data;
 
-	if (!info || sanity_check(info, tty->device, "close"))
+	if (sanity_check(info, tty->device, "close"))
 		return;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):%s close() entry, count=%d\n",
 			 __FILE__,__LINE__, info->device_name, info->count);
 
-	if (!info->count || tty_hung_up_p(filp))
+	if (!info->count)
+		return;
+
+	if (tty_hung_up_p(filp))
 		goto cleanup;
 
 	if ((tty->count == 1) && (info->count != 1)) {
@@ -1203,7 +1206,7 @@
 			schedule_timeout(char_time);
 			if (signal_pending(current))
 				break;
-			if (timeout && ((orig_jiffies + timeout) < jiffies))
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
 				break;
 		}
 	} else {
@@ -1214,7 +1217,7 @@
 			schedule_timeout(char_time);
 			if (signal_pending(current))
 				break;
-			if (timeout && ((orig_jiffies + timeout) < jiffies))
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
 				break;
 		}
 	}
diff -urN linux-2.4.22-bk10/drivers/sound/i810_audio.c linux-2.4.22-bk11/drivers/sound/i810_audio.c
--- linux-2.4.22-bk10/drivers/sound/i810_audio.c	2003-09-05 03:07:30.000000000 -0700
+++ linux-2.4.22-bk11/drivers/sound/i810_audio.c	2003-09-05 03:07:45.000000000 -0700
@@ -2727,7 +2727,7 @@
 		      i810_ac97_get(codec, AC97_POWER_CONTROL) & ~0x7f00);
 
 	/* wait for analog ready */
-	for (i=10; i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--)
+	for (i=100; i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--)
 	{
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule_timeout(HZ/20);
diff -urN linux-2.4.22-bk10/fs/lockd/svclock.c linux-2.4.22-bk11/fs/lockd/svclock.c
--- linux-2.4.22-bk10/fs/lockd/svclock.c	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.22-bk11/fs/lockd/svclock.c	2003-09-05 03:07:47.000000000 -0700
@@ -188,6 +188,11 @@
 	locks_init_lock(&block->b_call.a_args.lock.fl);
 	locks_init_lock(&block->b_call.a_res.lock.fl);
 
+	block->b_host = nlmsvc_lookup_host(rqstp);
+	if (block->b_host == NULL) {
+		goto failed_free;
+	}
+
 	if (!nlmclnt_setgrantargs(&block->b_call, lock))
 		goto failed_free;
 
@@ -199,7 +204,6 @@
 
 	/* Create and initialize the block */
 	block->b_daemon = rqstp->rq_server;
-	block->b_host   = host;
 	block->b_file   = file;
 
 	/* Add to file's list of blocks */
@@ -265,8 +269,7 @@
 		}
 	}
 
-	if (block->b_host)
-		nlm_release_host(block->b_host);
+	nlm_release_host(block->b_host);
 	nlmclnt_freegrantargs(&block->b_call);
 	kfree(block);
 }
@@ -515,7 +518,7 @@
 	 * Just retry the grant callback, possibly refreshing the RPC
 	 * binding */
 	if (block->b_granted) {
-		nlm_rebind_host(block->b_host);
+		nlm_rebind_host(block->b_call.a_host);
 		goto callback;
 	}
 
diff -urN linux-2.4.22-bk10/fs/nfsd/export.c linux-2.4.22-bk11/fs/nfsd/export.c
--- linux-2.4.22-bk10/fs/nfsd/export.c	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.22-bk11/fs/nfsd/export.c	2003-09-05 03:07:47.000000000 -0700
@@ -640,7 +640,7 @@
 	{ NFSEXP_UIDMAP, {"uidmap", ""}},
 	{ NFSEXP_KERBEROS, { "kerberos", ""}},
 	{ NFSEXP_SUNSECURE, { "sunsecure", ""}},
-	{ NFSEXP_CROSSMNT, {"nohide", ""}},
+	{ NFSEXP_NOHIDE, {"nohide", ""}},
 	{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
 	{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
 #ifdef MSNFS
@@ -903,8 +903,10 @@
 {
 	struct svc_client	*clp;
 
+	exp_readlock();
 	for (clp = clients; clp; clp = clp->cl_next)
 		nfsd_lockd_unexport(clp);
+	exp_unlock();
 }
 
 /*
diff -urN linux-2.4.22-bk10/fs/nfsd/nfsfh.c linux-2.4.22-bk11/fs/nfsd/nfsfh.c
--- linux-2.4.22-bk10/fs/nfsd/nfsfh.c	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.22-bk11/fs/nfsd/nfsfh.c	2003-09-05 03:07:47.000000000 -0700
@@ -305,6 +305,7 @@
 			if (pdentry) {
 				igrab(tdentry->d_inode);
 				pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
+				pdentry->d_op = child->d_op;
 			}
 		}
 		if (pdentry == NULL)
diff -urN linux-2.4.22-bk10/fs/nfsd/vfs.c linux-2.4.22-bk11/fs/nfsd/vfs.c
--- linux-2.4.22-bk10/fs/nfsd/vfs.c	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.22-bk11/fs/nfsd/vfs.c	2003-09-05 03:07:47.000000000 -0700
@@ -82,7 +82,7 @@
  * N.B. After this call _both_ fhp and resfh need an fh_put
  *
  * If the lookup would cross a mountpoint, and the mounted filesystem
- * is exported to the client with NFSEXP_CROSSMNT, then the lookup is
+ * is exported to the client with NFSEXP_NOHIDE, then the lookup is
  * accepted as it stands and the mounted directory is
  * returned. Otherwise the covered directory is returned.
  * NOTE: this mountpoint crossing is not supported properly by all
@@ -116,7 +116,7 @@
 			dentry = dget(dparent);
 		else if (dparent != exp->ex_dentry)
 			dentry = dget(dparent->d_parent);
-		else if (!EX_CROSSMNT(exp))
+		else if (!EX_NOHIDE(exp))
 			dentry = dget(dparent); /* .. == . just like at / */
 		else {
 			/* checking mountpoint crossing is very different when stepping up */
@@ -158,7 +158,7 @@
 			exp2 = exp_get(rqstp->rq_client,
 				       mounts->d_inode->i_dev,
 				       mounts->d_inode->i_ino);
-			if (exp2 && EX_CROSSMNT(exp2)) {
+			if (exp2 && EX_NOHIDE(exp2)) {
 				/* successfully crossed mount point */
 				exp = exp2;
 				dput(dentry);
diff -urN linux-2.4.22-bk10/include/linux/nfsd/export.h linux-2.4.22-bk11/include/linux/nfsd/export.h
--- linux-2.4.22-bk10/include/linux/nfsd/export.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.22-bk11/include/linux/nfsd/export.h	2003-09-05 03:07:47.000000000 -0700
@@ -35,7 +35,7 @@
 #define NFSEXP_UIDMAP		0x0040
 #define NFSEXP_KERBEROS		0x0080		/* not available */
 #define NFSEXP_SUNSECURE	0x0100
-#define NFSEXP_CROSSMNT		0x0200
+#define NFSEXP_NOHIDE		0x0200
 #define NFSEXP_NOSUBTREECHECK	0x0400
 #define	NFSEXP_NOAUTHNLM	0x0800		/* Don't authenticate NLM requests - just trust */
 #define NFSEXP_MSNFS		0x1000	/* do silly things that MS clients expect */
@@ -80,7 +80,7 @@
 #define EX_SECURE(exp)		(!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
 #define EX_ISSYNC(exp)		(!((exp)->ex_flags & NFSEXP_ASYNC))
 #define EX_RDONLY(exp)		((exp)->ex_flags & NFSEXP_READONLY)
-#define EX_CROSSMNT(exp)	((exp)->ex_flags & NFSEXP_CROSSMNT)
+#define EX_NOHIDE(exp)		((exp)->ex_flags & NFSEXP_NOHIDE)
 #define EX_SUNSECURE(exp)	((exp)->ex_flags & NFSEXP_SUNSECURE)
 #define EX_WGATHER(exp)		((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
 
diff -urN linux-2.4.22-bk10/include/linux/sunrpc/svc.h linux-2.4.22-bk11/include/linux/sunrpc/svc.h
--- linux-2.4.22-bk10/include/linux/sunrpc/svc.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.22-bk11/include/linux/sunrpc/svc.h	2003-09-05 03:07:47.000000000 -0700
@@ -112,6 +112,8 @@
 				rq_secure  : 1,	/* secure port */
 				rq_auth    : 1;	/* check client */
 
+	__u32			rq_daddr;	/* dest addr of request - reply from here */
+
 	void *			rq_argp;	/* decoded arguments */
 	void *			rq_resp;	/* xdr'd results */
 
diff -urN linux-2.4.22-bk10/include/linux/wireless.h linux-2.4.22-bk11/include/linux/wireless.h
--- linux-2.4.22-bk10/include/linux/wireless.h	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.22-bk11/include/linux/wireless.h	2003-09-05 03:07:47.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * This file define a set of standard wireless extensions
  *
- * Version :	15	12.7.02
+ * Version :	16	2.4.03
  *
  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
  * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
@@ -69,6 +69,8 @@
 
 /***************************** INCLUDES *****************************/
 
+/* To minimise problems in user space, I might remove those headers
+ * at some point. Jean II */
 #include <linux/types.h>		/* for "caddr_t" et al		*/
 #include <linux/socket.h>		/* for "struct sockaddr" et al	*/
 #include <linux/if.h>			/* for IFNAMSIZ and co... */
@@ -80,7 +82,7 @@
  * (there is some stuff that will be added in the future...)
  * I just plan to increment with each new version.
  */
-#define WIRELESS_EXT	15
+#define WIRELESS_EXT	16
 
 /*
  * Changes :
@@ -163,6 +165,16 @@
  *	- Add IW_TXPOW_RANGE for range of Tx Powers
  *	- Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
  *	- Add IW_MODE_MONITOR for passive monitor
+ *
+ * V15 to V16
+ * ----------
+ *	- Increase the number of bitrates in iw_range to 32 (for 802.11g)
+ *	- Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
+ *	- Reshuffle struct iw_range for increases, add filler
+ *	- Increase IW_MAX_AP to 64 for driver returning a lot of addresses
+ *	- Remove IW_MAX_GET_SPY because conflict with enhanced spy support
+ *	- Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
+ *	- Add IW_ENCODE_TEMP and iw_range->encoding_login_index
  */
 
 /**************************** CONSTANTS ****************************/
@@ -196,9 +208,11 @@
 /* SIOCGIWSTATS is strictly used between user space and the kernel, and
  * is never passed to the driver (i.e. the driver will never see it). */
 
-/* Mobile IP support (statistics per MAC address) */
+/* Spy support (statistics per MAC address - used for Mobile IP support) */
 #define SIOCSIWSPY	0x8B10		/* set spy addresses */
 #define SIOCGIWSPY	0x8B11		/* get spy info (quality of link) */
+#define SIOCSIWTHRSPY	0x8B12		/* set spy threshold (spy event) */
+#define SIOCGIWTHRSPY	0x8B13		/* get spy threshold */
 
 /* Access Point manipulation */
 #define SIOCSIWAP	0x8B14		/* set access point MAC addresses */
@@ -294,7 +308,7 @@
 #define IW_PRIV_TYPE_FLOAT	0x5000	/* struct iw_freq */
 #define IW_PRIV_TYPE_ADDR	0x6000	/* struct sockaddr */
 
-#define IW_PRIV_SIZE_FIXED	0x0800	/* Variable or fixed nuber of args */
+#define IW_PRIV_SIZE_FIXED	0x0800	/* Variable or fixed number of args */
 
 #define IW_PRIV_SIZE_MASK	0x07FF	/* Max number of those args */
 
@@ -306,13 +320,13 @@
 /* ----------------------- OTHER CONSTANTS ----------------------- */
 
 /* Maximum frequencies in the range struct */
-#define IW_MAX_FREQUENCIES	16
+#define IW_MAX_FREQUENCIES	32
 /* Note : if you have something like 80 frequencies,
  * don't increase this constant and don't fill the frequency list.
  * The user will be able to set by channel anyway... */
 
 /* Maximum bit rates in the range struct */
-#define IW_MAX_BITRATES		8
+#define IW_MAX_BITRATES		32
 
 /* Maximum tx powers in the range struct */
 #define IW_MAX_TXPOWER		8
@@ -320,8 +334,7 @@
  * a few of them in the struct iw_range. */
 
 /* Maximum of address that you may set with SPY */
-#define IW_MAX_SPY		8	/* set */
-#define IW_MAX_GET_SPY		64	/* get */
+#define IW_MAX_SPY		8
 
 /* Maximum of address that you may get in the
    list of access points in range */
@@ -354,7 +367,8 @@
 #define IW_ENCODE_ENABLED	0x0000	/* Encoding enabled */
 #define IW_ENCODE_RESTRICTED	0x4000	/* Refuse non-encoded packets */
 #define IW_ENCODE_OPEN		0x2000	/* Accept non-encoded packets */
-#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
+#define IW_ENCODE_NOKEY		0x0800  /* Key is write only, so not present */
+#define IW_ENCODE_TEMP		0x0400  /* Temporary key */
 
 /* Power management flags available (along with the value, if any) */
 #define IW_POWER_ON		0x0000	/* No details... */
@@ -482,6 +496,17 @@
 	__u32		beacon;		/* Missed beacons/superframe */
 };
 
+/*
+ *	Quality range (for spy threshold)
+ */
+struct	iw_thrspy
+{
+	struct sockaddr		addr;		/* Source address (hw/mac) */
+	struct iw_quality	qual;		/* Quality of the link */
+	struct iw_quality	low;		/* Low threshold */
+	struct iw_quality	high;		/* High threshold */
+};
+
 /* ------------------------ WIRELESS STATS ------------------------ */
 /*
  * Wireless statistics (used for /proc/net/wireless)
@@ -534,7 +559,7 @@
 	struct iw_quality qual;		/* Quality part of statistics */
 
 	struct sockaddr	ap_addr;	/* Access point address */
-	struct sockaddr	addr;		/* Destination address (hw) */
+	struct sockaddr	addr;		/* Destination address (hw/mac) */
 
 	struct iw_param	param;		/* Other small parameters */
 	struct iw_point	data;		/* Other large parameters */
@@ -582,17 +607,31 @@
 	__u32		min_nwid;	/* Minimal NWID we are able to set */
 	__u32		max_nwid;	/* Maximal NWID we are able to set */
 
-	/* Frequency */
-	__u16		num_channels;	/* Number of channels [0; num - 1] */
-	__u8		num_frequency;	/* Number of entry in the list */
-	struct iw_freq	freq[IW_MAX_FREQUENCIES];	/* list */
-	/* Note : this frequency list doesn't need to fit channel numbers */
+	/* Old Frequency (backward compat - moved lower ) */
+	__u16		old_num_channels;
+	__u8		old_num_frequency;
+	/* Filler to keep "version" at the same offset */
+	__s32		old_freq[6];
 
 	/* signal level threshold range */
 	__s32	sensitivity;
 
 	/* Quality of link & SNR stuff */
+	/* Quality range (link, level, noise)
+	 * If the quality is absolute, it will be in the range [0 ; max_qual],
+	 * if the quality is dBm, it will be in the range [max_qual ; 0].
+	 * Don't forget that we use 8 bit arithmetics... */
 	struct iw_quality	max_qual;	/* Quality of the link */
+	/* This should contain the average/typical values of the quality
+	 * indicator. This should be the threshold between a "good" and
+	 * a "bad" link (example : monitor going from green to orange).
+	 * Currently, user space apps like quality monitors don't have any
+	 * way to calibrate the measurement. With this, they can split
+	 * the range between 0 and max_qual in different quality level
+	 * (using a geometric subdivision centered on the average).
+	 * I expect that people doing the user space apps will feedback
+	 * us on which value we need to put in each driver... */
+	struct iw_quality	avg_qual;	/* Quality of the link */
 
 	/* Rates */
 	__u8		num_bitrates;	/* Number of entries in the list */
@@ -619,6 +658,8 @@
 	__u16	encoding_size[IW_MAX_ENCODING_SIZES];	/* Different token sizes */
 	__u8	num_encoding_sizes;	/* Number of entry in the list */
 	__u8	max_encoding_tokens;	/* Max number of tokens */
+	/* For drivers that need a "login/passwd" form */
+	__u8	encoding_login_index;	/* token index for login token */
 
 	/* Transmit power */
 	__u16		txpower_capa;	/* What options are supported */
@@ -638,18 +679,12 @@
 	__s32		min_r_time;	/* Minimal retry lifetime */
 	__s32		max_r_time;	/* Maximal retry lifetime */
 
-	/* Average quality of link & SNR */
-	struct iw_quality	avg_qual;	/* Quality of the link */
-	/* This should contain the average/typical values of the quality
-	 * indicator. This should be the threshold between a "good" and
-	 * a "bad" link (example : monitor going from green to orange).
-	 * Currently, user space apps like quality monitors don't have any
-	 * way to calibrate the measurement. With this, they can split
-	 * the range between 0 and max_qual in different quality level
-	 * (using a geometric subdivision centered on the average).
-	 * I expect that people doing the user space apps will feedback
-	 * us on which value we need to put in each driver...
-	 */
+	/* Frequency */
+	__u16		num_channels;	/* Number of channels [0; num - 1] */
+	__u8		num_frequency;	/* Number of entry in the list */
+	struct iw_freq	freq[IW_MAX_FREQUENCIES];	/* list */
+	/* Note : this frequency list doesn't need to fit channel numbers,
+	 * because each entry contain its channel index */
 };
 
 /*
diff -urN linux-2.4.22-bk10/include/net/iw_handler.h linux-2.4.22-bk11/include/net/iw_handler.h
--- linux-2.4.22-bk10/include/net/iw_handler.h	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.22-bk11/include/net/iw_handler.h	2003-09-05 03:07:47.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * This file define the new driver API for Wireless Extensions
  *
- * Version :	4	21.6.02
+ * Version :	5	4.12.02
  *
  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
  * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
@@ -206,7 +206,7 @@
  * will be needed...
  * I just plan to increment with each new version.
  */
-#define IW_HANDLER_VERSION	4
+#define IW_HANDLER_VERSION	5
 
 /*
  * Changes :
@@ -220,10 +220,18 @@
  * V3 to V4
  * --------
  *	- Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
+ *
+ * V4 to V5
+ * --------
+ *	- Add new spy support : struct iw_spy_data & prototypes
  */
 
 /**************************** CONSTANTS ****************************/
 
+/* Enable enhanced spy support. Disable to reduce footprint */
+#define IW_WIRELESS_SPY
+#define IW_WIRELESS_THRSPY
+
 /* Special error message for the driver to indicate that we
  * should do a commit after return from the iw_handler */
 #define EIWCOMMIT	EINPROGRESS
@@ -315,6 +323,9 @@
 	 * We will automatically export that to user space... */
 	struct iw_priv_args *	private_args;
 
+	/* Driver enhanced spy support */
+	long			spy_offset;	/* Spy data offset */
+
 	/* In the long term, get_wireless_stats will move from
 	 * 'struct net_device' to here, to minimise bloat. */
 };
@@ -350,6 +361,33 @@
 
 /* Need to think of short header translation table. Later. */
 
+/* --------------------- ENHANCED SPY SUPPORT --------------------- */
+/*
+ * In the old days, the driver was handling spy support all by itself.
+ * Now, the driver can delegate this task to Wireless Extensions.
+ * It needs to include this struct in its private part and use the
+ * standard spy iw_handler.
+ */
+
+/*
+ * Instance specific spy data, i.e. addresses spied and quality for them.
+ */
+struct iw_spy_data
+{
+#ifdef IW_WIRELESS_SPY
+	/* --- Standard spy support --- */
+	int			spy_number;
+	u_char			spy_address[IW_MAX_SPY][ETH_ALEN];
+	struct iw_quality	spy_stat[IW_MAX_SPY];
+#ifdef IW_WIRELESS_THRSPY
+	/* --- Enhanced spy support (event) */
+	struct iw_quality	spy_thr_low;	/* Low threshold */
+	struct iw_quality	spy_thr_high;	/* High threshold */
+	u_char			spy_thr_under[IW_MAX_SPY];
+#endif /* IW_WIRELESS_THRSPY */
+#endif /* IW_WIRELESS_SPY */
+};
+
 /**************************** PROTOTYPES ****************************/
 /*
  * Functions part of the Wireless Extensions (defined in net/core/wireless.c).
@@ -376,6 +414,31 @@
 /* We may need a function to send a stream of events to user space.
  * More on that later... */
 
+/* Standard handler for SIOCSIWSPY */
+extern int iw_handler_set_spy(struct net_device *	dev,
+			      struct iw_request_info *	info,
+			      union iwreq_data *	wrqu,
+			      char *			extra);
+/* Standard handler for SIOCGIWSPY */
+extern int iw_handler_get_spy(struct net_device *	dev,
+			      struct iw_request_info *	info,
+			      union iwreq_data *	wrqu,
+			      char *			extra);
+/* Standard handler for SIOCSIWTHRSPY */
+extern int iw_handler_set_thrspy(struct net_device *	dev,
+				 struct iw_request_info *info,
+				 union iwreq_data *	wrqu,
+				 char *			extra);
+/* Standard handler for SIOCGIWTHRSPY */
+extern int iw_handler_get_thrspy(struct net_device *	dev,
+				 struct iw_request_info *info,
+				 union iwreq_data *	wrqu,
+				 char *			extra);
+/* Driver call to update spy records */
+extern void wireless_spy_update(struct net_device *	dev,
+				unsigned char *		address,
+				struct iw_quality *	wstats);
+
 /************************* INLINE FUNTIONS *************************/
 /*
  * Function that are so simple that it's more efficient inlining them
diff -urN linux-2.4.22-bk10/mm/mprotect.c linux-2.4.22-bk11/mm/mprotect.c
--- linux-2.4.22-bk10/mm/mprotect.c	2002-08-02 17:39:46.000000000 -0700
+++ linux-2.4.22-bk11/mm/mprotect.c	2003-09-05 03:07:47.000000000 -0700
@@ -275,7 +275,7 @@
 	len = PAGE_ALIGN(len);
 	end = start + len;
 	if (end < start)
-		return -EINVAL;
+		return -ENOMEM;
 	if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
 		return -EINVAL;
 	if (end == start)
diff -urN linux-2.4.22-bk10/net/core/wireless.c linux-2.4.22-bk11/net/core/wireless.c
--- linux-2.4.22-bk10/net/core/wireless.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.22-bk11/net/core/wireless.c	2003-09-05 03:07:47.000000000 -0700
@@ -2,7 +2,7 @@
  * This file implement the Wireless Extensions APIs.
  *
  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved.
  *
  * (As all part of the Linux kernel, this file is GPL)
  */
@@ -43,6 +43,11 @@
  *	o Turn on WE_STRICT_WRITE by default + kernel warning
  *	o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num)
  *	o Fix off-by-one in test (extra_size <= IFNAMSIZ)
+ *
+ * v6 - 9.01.03 - Jean II
+ *	o Add common spy support : iw_handler_set_spy(), wireless_spy_update()
+ *	o Add enhanced spy support : iw_handler_set_thrspy() and event.
+ *	o Add WIRELESS_EXT version display in /proc/net/wireless
  */
 
 /***************************** INCLUDES *****************************/
@@ -52,6 +57,7 @@
 #include <linux/types.h>		/* off_t */
 #include <linux/netdevice.h>		/* struct ifreq, dev_get_by_name() */
 #include <linux/rtnetlink.h>		/* rtnetlink stuff */
+#include <linux/if_arp.h>		/* ARPHRD_ETHER */
 
 #include <linux/wireless.h>		/* Pretty obvious */
 #include <net/iw_handler.h>		/* New driver API */
@@ -65,6 +71,7 @@
 /* Debuging stuff */
 #undef WE_IOCTL_DEBUG		/* Debug IOCTL API */
 #undef WE_EVENT_DEBUG		/* Debug Event dispatcher */
+#undef WE_SPY_DEBUG		/* Debug enhanced spy support */
 
 /* Options */
 #define WE_EVENT_NETLINK	/* Propagate events using rtnetlink */
@@ -72,7 +79,7 @@
 
 /************************* GLOBAL VARIABLES *************************/
 /*
- * You should not use global variables, because or re-entrancy.
+ * You should not use global variables, because of re-entrancy.
  * On our case, it's only const, so it's OK...
  */
 /*
@@ -115,11 +122,11 @@
 	/* SIOCSIWSPY */
 	{ IW_HEADER_TYPE_POINT, 0, sizeof(struct sockaddr), 0, IW_MAX_SPY, 0},
 	/* SIOCGIWSPY */
-	{ IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_GET_SPY, 0},
-	/* -- hole -- */
-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-	/* -- hole -- */
-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
+	{ IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_SPY, 0},
+	/* SIOCSIWTHRSPY */
+	{ IW_HEADER_TYPE_POINT, 0, sizeof(struct iw_thrspy), 1, 1, 0},
+	/* SIOCGIWTHRSPY */
+	{ IW_HEADER_TYPE_POINT, 0, sizeof(struct iw_thrspy), 1, 1, 0},
 	/* SIOCSIWAP */
 	{ IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
 	/* SIOCGIWAP */
@@ -377,9 +384,9 @@
 	struct net_device *	dev;
 
 	size = sprintf(buffer,
-		       "Inter-| sta-|   Quality        |   Discarded packets               | Missed\n"
-		       " face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon\n"
-			);
+		       "Inter-| sta-|   Quality        |   Discarded packets               | Missed | WE\n"
+		       " face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon | %d\n",
+		       WIRELESS_EXT);
 	
 	pos += size;
 	len += size;
@@ -1024,3 +1031,252 @@
 
 	return;		/* Always success, I guess ;-) */
 }
+
+/********************** ENHANCED IWSPY SUPPORT **********************/
+/*
+ * In the old days, the driver was handling spy support all by itself.
+ * Now, the driver can delegate this task to Wireless Extensions.
+ * It needs to use those standard spy iw_handler in struct iw_handler_def,
+ * push data to us via XXX and include struct iw_spy_data in its
+ * private part.
+ * One of the main advantage of centralising spy support here is that
+ * it becomes much easier to improve and extend it without having to touch
+ * the drivers. One example is the addition of the Spy-Threshold events.
+ * Note : IW_WIRELESS_SPY is defined in iw_handler.h
+ */
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : set Spy List
+ */
+int iw_handler_set_spy(struct net_device *	dev,
+		       struct iw_request_info *	info,
+		       union iwreq_data *	wrqu,
+		       char *			extra)
+{
+#ifdef IW_WIRELESS_SPY
+	struct iw_spy_data *	spydata = (dev->priv +
+					   dev->wireless_handlers->spy_offset);
+	struct sockaddr *	address = (struct sockaddr *) extra;
+
+	/* Disable spy collection while we copy the addresses.
+	 * As we don't disable interrupts, we need to do this to avoid races.
+	 * As we are the only writer, this is good enough. */
+	spydata->spy_number = 0;
+
+	/* Are there are addresses to copy? */
+	if(wrqu->data.length > 0) {
+		int i;
+
+		/* Copy addresses */
+		for(i = 0; i < wrqu->data.length; i++)
+			memcpy(spydata->spy_address[i], address[i].sa_data,
+			       ETH_ALEN);
+		/* Reset stats */
+		memset(spydata->spy_stat, 0,
+		       sizeof(struct iw_quality) * IW_MAX_SPY);
+
+#ifdef WE_SPY_DEBUG
+		printk(KERN_DEBUG "iw_handler_set_spy() :  offset %ld, spydata %p, num %d\n", dev->wireless_handlers->spy_offset, spydata, wrqu->data.length);
+		for (i = 0; i < wrqu->data.length; i++)
+			printk(KERN_DEBUG
+			       "%02X:%02X:%02X:%02X:%02X:%02X \n",
+			       spydata->spy_address[i][0],
+			       spydata->spy_address[i][1],
+			       spydata->spy_address[i][2],
+			       spydata->spy_address[i][3],
+			       spydata->spy_address[i][4],
+			       spydata->spy_address[i][5]);
+#endif	/* WE_SPY_DEBUG */
+	}
+	/* Enable addresses */
+	spydata->spy_number = wrqu->data.length;
+
+	return 0;
+#else /* IW_WIRELESS_SPY */
+	return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_SPY */
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : get Spy List
+ */
+int iw_handler_get_spy(struct net_device *	dev,
+		       struct iw_request_info *	info,
+		       union iwreq_data *	wrqu,
+		       char *			extra)
+{
+#ifdef IW_WIRELESS_SPY
+	struct iw_spy_data *	spydata = (dev->priv +
+					   dev->wireless_handlers->spy_offset);
+	struct sockaddr *	address = (struct sockaddr *) extra;
+	int			i;
+
+	wrqu->data.length = spydata->spy_number;
+
+	/* Copy addresses. */
+	for(i = 0; i < spydata->spy_number; i++) 	{
+		memcpy(address[i].sa_data, spydata->spy_address[i], ETH_ALEN);
+		address[i].sa_family = AF_UNIX;
+	}
+	/* Copy stats to the user buffer (just after). */
+	if(spydata->spy_number > 0)
+		memcpy(extra  + (sizeof(struct sockaddr) *spydata->spy_number),
+		       spydata->spy_stat,
+		       sizeof(struct iw_quality) * spydata->spy_number);
+	/* Reset updated flags. */
+	for(i = 0; i < spydata->spy_number; i++)
+		spydata->spy_stat[i].updated = 0;
+	return 0;
+#else /* IW_WIRELESS_SPY */
+	return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_SPY */
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : set spy threshold
+ */
+int iw_handler_set_thrspy(struct net_device *	dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *	wrqu,
+			  char *		extra)
+{
+#ifdef IW_WIRELESS_THRSPY
+	struct iw_spy_data *	spydata = (dev->priv +
+					   dev->wireless_handlers->spy_offset);
+	struct iw_thrspy *	threshold = (struct iw_thrspy *) extra;
+
+	/* Just do it */
+	memcpy(&(spydata->spy_thr_low), &(threshold->low),
+	       2 * sizeof(struct iw_quality));
+
+	/* Clear flag */
+	memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under));
+
+#ifdef WE_SPY_DEBUG
+	printk(KERN_DEBUG "iw_handler_set_thrspy() :  low %d ; high %d\n", spydata->spy_thr_low.level, spydata->spy_thr_high.level);
+#endif	/* WE_SPY_DEBUG */
+
+	return 0;
+#else /* IW_WIRELESS_THRSPY */
+	return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_THRSPY */
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : get spy threshold
+ */
+int iw_handler_get_thrspy(struct net_device *	dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *	wrqu,
+			  char *		extra)
+{
+#ifdef IW_WIRELESS_THRSPY
+	struct iw_spy_data *	spydata = (dev->priv +
+					   dev->wireless_handlers->spy_offset);
+	struct iw_thrspy *	threshold = (struct iw_thrspy *) extra;
+
+	/* Just do it */
+	memcpy(&(threshold->low), &(spydata->spy_thr_low),
+	       2 * sizeof(struct iw_quality));
+
+	return 0;
+#else /* IW_WIRELESS_THRSPY */
+	return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_THRSPY */
+}
+
+#ifdef IW_WIRELESS_THRSPY
+/*------------------------------------------------------------------*/
+/*
+ * Prepare and send a Spy Threshold event
+ */
+static void iw_send_thrspy_event(struct net_device *	dev,
+				 struct iw_spy_data *	spydata,
+				 unsigned char *	address,
+				 struct iw_quality *	wstats)
+{
+	union iwreq_data	wrqu;
+	struct iw_thrspy	threshold;
+
+	/* Init */
+	wrqu.data.length = 1;
+	wrqu.data.flags = 0;
+	/* Copy address */
+	memcpy(threshold.addr.sa_data, address, ETH_ALEN);
+	threshold.addr.sa_family = ARPHRD_ETHER;
+	/* Copy stats */
+	memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality));
+	/* Copy also thresholds */
+	memcpy(&(threshold.low), &(spydata->spy_thr_low),
+	       2 * sizeof(struct iw_quality));
+
+#ifdef WE_SPY_DEBUG
+	printk(KERN_DEBUG "iw_send_thrspy_event() : address %02X:%02X:%02X:%02X:%02X:%02X, level %d, up = %d\n",
+	       threshold.addr.sa_data[0],
+	       threshold.addr.sa_data[1],
+	       threshold.addr.sa_data[2],
+	       threshold.addr.sa_data[3],
+	       threshold.addr.sa_data[4],
+	       threshold.addr.sa_data[5], threshold.qual.level);
+#endif	/* WE_SPY_DEBUG */
+
+	/* Send event to user space */
+	wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
+}
+#endif /* IW_WIRELESS_THRSPY */
+
+/* ---------------------------------------------------------------- */
+/*
+ * Call for the driver to update the spy data.
+ * For now, the spy data is a simple array. As the size of the array is
+ * small, this is good enough. If we wanted to support larger number of
+ * spy addresses, we should use something more efficient...
+ */
+void wireless_spy_update(struct net_device *	dev,
+			 unsigned char *	address,
+			 struct iw_quality *	wstats)
+{
+#ifdef IW_WIRELESS_SPY
+	struct iw_spy_data *	spydata = (dev->priv +
+					   dev->wireless_handlers->spy_offset);
+	int			i;
+	int			match = -1;
+
+#ifdef WE_SPY_DEBUG
+	printk(KERN_DEBUG "wireless_spy_update() :  offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]);
+#endif	/* WE_SPY_DEBUG */
+
+	/* Update all records that match */
+	for(i = 0; i < spydata->spy_number; i++)
+		if(!memcmp(address, spydata->spy_address[i], ETH_ALEN)) {
+			memcpy(&(spydata->spy_stat[i]), wstats,
+			       sizeof(struct iw_quality));
+			match = i;
+		}
+#ifdef IW_WIRELESS_THRSPY
+	/* Generate an event if we cross the spy threshold.
+	 * To avoid event storms, we have a simple hysteresis : we generate
+	 * event only when we go under the low threshold or above the
+	 * high threshold. */
+	if(match >= 0) {
+		if(spydata->spy_thr_under[match]) {
+			if(wstats->level > spydata->spy_thr_high.level) {
+				spydata->spy_thr_under[match] = 0;
+				iw_send_thrspy_event(dev, spydata,
+						     address, wstats);
+			}
+		} else {
+			if(wstats->level < spydata->spy_thr_low.level) {
+				spydata->spy_thr_under[match] = 1;
+				iw_send_thrspy_event(dev, spydata,
+						     address, wstats);
+			}
+		}
+	}
+#endif /* IW_WIRELESS_THRSPY */
+#endif /* IW_WIRELESS_SPY */
+}
diff -urN linux-2.4.22-bk10/net/netsyms.c linux-2.4.22-bk11/net/netsyms.c
--- linux-2.4.22-bk10/net/netsyms.c	2003-09-05 03:07:35.000000000 -0700
+++ linux-2.4.22-bk11/net/netsyms.c	2003-09-05 03:07:47.000000000 -0700
@@ -612,6 +612,11 @@
 #if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
 #include <net/iw_handler.h>
 EXPORT_SYMBOL(wireless_send_event);
+EXPORT_SYMBOL(iw_handler_set_spy);
+EXPORT_SYMBOL(iw_handler_get_spy);
+EXPORT_SYMBOL(iw_handler_set_thrspy);
+EXPORT_SYMBOL(iw_handler_get_thrspy);
+EXPORT_SYMBOL(wireless_spy_update);
 #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
 
 /* ethtool.c */
diff -urN linux-2.4.22-bk10/net/sunrpc/svcsock.c linux-2.4.22-bk11/net/sunrpc/svcsock.c
--- linux-2.4.22-bk10/net/sunrpc/svcsock.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.22-bk11/net/sunrpc/svcsock.c	2003-09-05 03:07:47.000000000 -0700
@@ -120,6 +120,8 @@
 	if (!(svsk->sk_flags &
 	      ( (1<<SK_CONN)|(1<<SK_DATA)|(1<<SK_CLOSE)) ))
 		return;
+	if (test_bit(SK_DEAD, &svsk->sk_flags))
+		return;
 
 	spin_lock_bh(&serv->sv_lock);
 
@@ -315,6 +317,9 @@
 	struct svc_sock	*svsk = rqstp->rq_sock;
 	struct socket	*sock = svsk->sk_sock;
 	struct msghdr	msg;
+	struct { struct cmsghdr cmh;
+		struct in_pktinfo pki;
+	} cm;
 	int		i, buflen, len;
 
 	for (i = buflen = 0; i < nr; i++)
@@ -324,8 +329,18 @@
 	msg.msg_namelen = sizeof(rqstp->rq_addr);
 	msg.msg_iov     = iov;
 	msg.msg_iovlen  = nr;
-	msg.msg_control = NULL;
-	msg.msg_controllen = 0;
+	if (rqstp->rq_prot == IPPROTO_UDP) {
+		msg.msg_control = &cm;
+		msg.msg_controllen = sizeof(cm);
+		cm.cmh.cmsg_len = sizeof(cm);
+		cm.cmh.cmsg_level = SOL_IP;
+		cm.cmh.cmsg_type = IP_PKTINFO;
+		cm.pki.ipi_ifindex = 0;
+		cm.pki.ipi_spec_dst.s_addr = rqstp->rq_daddr;
+	} else {
+		msg.msg_control = NULL;
+		msg.msg_controllen = 0;
+	}
 
 	/* This was MSG_DONTWAIT, but I now want it to wait.
 	 * The only thing that it would wait for is memory and
@@ -529,6 +544,7 @@
 	rqstp->rq_addr.sin_family = AF_INET;
 	rqstp->rq_addr.sin_port = skb->h.uh->source;
 	rqstp->rq_addr.sin_addr.s_addr = skb->nh.iph->saddr;
+	rqstp->rq_daddr = skb->nh.iph->daddr;
 
 	if (serv->sv_stats)
 		serv->sv_stats->netudpcnt++;
@@ -930,6 +946,9 @@
 	bufp->iov[0].iov_len  = bufp->len << 2;
 	bufp->base[0] = htonl(0x80000000|((bufp->len << 2) - 4));
 
+	if (test_bit(SK_DEAD, &rqstp->rq_sock->sk_flags))
+		return -ENOTCONN;
+
 	sent = svc_sendto(rqstp, bufp->iov, bufp->nriov);
 	if (sent != bufp->len<<2) {
 		printk(KERN_NOTICE "rpc-srv/tcp: %s: sent only %d bytes of %d - shutting down socket\n",
@@ -1277,6 +1296,9 @@
 
 	dprintk("svc: svc_delete_socket(%p)\n", svsk);
 
+	if (test_and_set_bit(SK_DEAD, &svsk->sk_flags))
+		return ;
+
 	serv = svsk->sk_server;
 	sk = svsk->sk_sk;
 
@@ -1293,8 +1315,6 @@
 		list_del(&svsk->sk_ready);
 
 
-	set_bit(SK_DEAD, &svsk->sk_flags);
-
 	if (!svsk->sk_inuse) {
 		spin_unlock_bh(&serv->sv_lock);
 		sock_release(svsk->sk_sock);
