## Automatically generated incremental diff
## From:   linux-2.4.1-pre7
## To:     linux-2.4.1-pre8
## Robot:  $Id: make-incremental-diff,v 1.8 2001/12/04 06:05:04 hpa Exp $

diff -urN linux-2.4.1-pre7/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.4.1-pre7/Documentation/Configure.help	Mon Dec  3 22:25:17 2001
+++ linux/Documentation/Configure.help	Mon Dec  3 22:25:25 2001
@@ -2625,13 +2625,14 @@
 
   One well known example of this is PCMCIA- or PC-cards, credit-card
   size devices such as network cards, modems or hard drives which are
-  plugged into slots found on all modern laptop computers.
+  plugged into slots found on all modern laptop computers.  Another
+  example, used on modern desktops as well as laptops, is USB.
 
-  Another example, used on modern desktops as well as laptops, is USB.
-  Enable HOTPLUG with USB and KMOD, and your kernel will automatically
-  call out to a user mode "policy agent" to load modules and set up
-  software needed to use USB devices you plug in.  Get agent software
-  (at http://www.linux-usb.org/policy.html) and install it.
+  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
+  software (at http://linux-hotplug.sourceforge.net) and install it.
+  Then your kernel will automatically call out to a user mode "policy
+  agent" (/sbin/hotplug) to load modules and set up software needed
+  to use devices as you hotplug them.
 
 PCMCIA/Cardbus support
 CONFIG_PCMCIA
diff -urN linux-2.4.1-pre7/Documentation/usb/hotplug.txt linux/Documentation/usb/hotplug.txt
--- linux-2.4.1-pre7/Documentation/usb/hotplug.txt	Sun Nov 12 20:45:19 2000
+++ linux/Documentation/usb/hotplug.txt	Mon Dec  3 22:25:25 2001
@@ -1,4 +1,4 @@
-USB HOTPLUGGING
+LINUX HOTPLUGGING
 
 In hotpluggable busses like USB (and Cardbus PCI), end-users plug devices
 into the bus with power on.  In most cases, users expect the devices to become
@@ -8,7 +8,7 @@
       loading a kernel module; newer drivers can use modutils to
       publish their device (and class) support to user utilities.
 
-    - Bind a driver to that device.  That's done using the USB
+    - Bind a driver to that device.  Bus frameworks do that using a
       device driver's probe() routine.
     
     - Tell other subsystems to configure the new device.  Print
@@ -26,6 +26,10 @@
 such programs are called "policy agents" here.  Typically they involve
 shell scripts that dispatch to more familiar administration tools.
 
+Because some of those actions rely on information about drivers (metadata)
+that is currently available only when the drivers are dynamically linked,
+you get the best hotplugging when you configure a highly modular system.
+
 
 KERNEL HOTPLUG HELPER (/sbin/hotplug)
 
@@ -40,9 +44,14 @@
 dispatch; any other argument and environment parameters are specified by
 the subsystem making that invocation.
 
-A reference implementation of a /sbin/hotplug script is available at the
-http://www.linux-usb.org website, which works USB for but also knows how to
-delegate to any /etc/hotplug/$TYPE.agent policy agent present.
+Hotplug software and other resources is available at:
+
+	http://linux-hotplug.sourceforge.net
+
+Mailing list information is also available at that site.
+
+
+--------------------------------------------------------------------------
 
 
 USB POLICY AGENT
diff -urN linux-2.4.1-pre7/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt
--- linux-2.4.1-pre7/Documentation/usb/usb-serial.txt	Thu Dec  7 16:13:38 2000
+++ linux/Documentation/usb/usb-serial.txt	Mon Dec  3 22:25:25 2001
@@ -223,7 +223,7 @@
   
   To enable the generic driver to recognize your device, build the driver
   as a module and load it by the following invocation:
-	insmod usb-serial vendor=0x#### product=0x####
+	insmod usbserial vendor=0x#### product=0x####
   where the #### is replaced with the hex representation of your device's
   vendor id and product id.
 
diff -urN linux-2.4.1-pre7/Makefile linux/Makefile
--- linux-2.4.1-pre7/Makefile	Mon Dec  3 22:25:17 2001
+++ linux/Makefile	Mon Dec  3 22:25:25 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 1
-EXTRAVERSION =-pre7
+EXTRAVERSION =-pre8
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.1-pre7/drivers/char/n_tty.c linux/drivers/char/n_tty.c
--- linux-2.4.1-pre7/drivers/char/n_tty.c	Mon Jul 31 10:14:07 2000
+++ linux/drivers/char/n_tty.c	Mon Dec  3 22:25:25 2001
@@ -86,6 +86,15 @@
 		free_page((unsigned long) buf);
 }
 
+static inline void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
+{
+	if (tty->read_cnt < N_TTY_BUF_SIZE) {
+		tty->read_buf[tty->read_head] = c;
+		tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
+		tty->read_cnt++;
+	}
+}
+
 static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
 {
 	unsigned long flags;
@@ -94,11 +103,7 @@
 	 *	Why didn't anyone see this one comming? --AJK
 	*/
 	spin_lock_irqsave(&tty->read_lock, flags);
-	if (tty->read_cnt < N_TTY_BUF_SIZE) {
-		tty->read_buf[tty->read_head] = c;
-		tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
-		tty->read_cnt++;
-	}
+	put_tty_queue_nolock(c, tty);
 	spin_unlock_irqrestore(&tty->read_lock, flags);
 }
 
@@ -499,6 +504,8 @@
 
 static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
 {
+	unsigned long flags;
+
 	if (tty->raw) {
 		put_tty_queue(c, tty);
 		return;
@@ -651,10 +658,12 @@
 				put_tty_queue(c, tty);
 
 		handle_newline:
+			spin_lock_irqsave(&tty->read_lock, flags);
 			set_bit(tty->read_head, &tty->read_flags);
-			put_tty_queue(c, tty);
+			put_tty_queue_nolock(c, tty);
 			tty->canon_head = tty->read_head;
 			tty->canon_data++;
+			spin_unlock_irqrestore(&tty->read_lock, flags);
 			kill_fasync(&tty->fasync, SIGIO, POLL_IN);
 			if (waitqueue_active(&tty->read_wait))
 				wake_up_interruptible(&tty->read_wait);
@@ -1055,12 +1064,6 @@
 				tty->read_tail = ((tty->read_tail+1) &
 						  (N_TTY_BUF_SIZE-1));
 				tty->read_cnt--;
-				spin_unlock_irqrestore(&tty->read_lock, flags);
-
-				if (!eol || (c != __DISABLED_CHAR)) {
-					put_user(c, b++);
-					nr--;
-				}
 				if (eol) {
 					/* this test should be redundant:
 					 * we shouldn't be reading data if
@@ -1068,8 +1071,15 @@
 					 */
 					if (--tty->canon_data < 0)
 						tty->canon_data = 0;
-					break;
 				}
+				spin_unlock_irqrestore(&tty->read_lock, flags);
+
+				if (!eol || (c != __DISABLED_CHAR)) {
+					put_user(c, b++);
+					nr--;
+				}
+				if (eol)
+					break;
 			}
 		} else {
 			int uncopied;
diff -urN linux-2.4.1-pre7/drivers/usb/rio500.c linux/drivers/usb/rio500.c
--- linux-2.4.1-pre7/drivers/usb/rio500.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/rio500.c	Mon Dec  3 22:25:25 2001
@@ -247,6 +247,7 @@
 	return 0;
 
 err_out:
+	up(&(rio->lock));
 	return retval;
 }
 
@@ -389,7 +390,7 @@
 			     result, partial, this_read);
 			return -EIO;
 		} else {
-			unlock_kernel();
+			up(&(rio->lock));
 			return (0);
 		}
 
diff -urN linux-2.4.1-pre7/drivers/usb/serial/Config.in linux/drivers/usb/serial/Config.in
--- linux-2.4.1-pre7/drivers/usb/serial/Config.in	Thu Dec  7 16:13:38 2000
+++ linux/drivers/usb/serial/Config.in	Mon Dec  3 22:25:25 2001
@@ -22,6 +22,7 @@
      bool '    USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19
      bool '    USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X
      bool '    USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W
+     bool '    USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W
   fi
   dep_tristate '  USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
   dep_tristate '  USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
diff -urN linux-2.4.1-pre7/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c
--- linux-2.4.1-pre7/drivers/usb/serial/usbserial.c	Fri Dec  1 12:17:24 2000
+++ linux/drivers/usb/serial/usbserial.c	Mon Dec  3 22:25:25 2001
@@ -14,8 +14,14 @@
  * based on a driver by Brad Keryan)
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
- * 
- * (12/29/2000) gkh
+ *
+ * (12/12/2000) gkh
+ *	Removed MOD_INC and MOD_DEC from poll and disconnect functions, and
+ *	moved them to the serial_open and serial_close functions.
+ *	Also fixed bug with there not being a MOD_DEC for the generic driver
+ *	(thanks to Gary Brubaker for finding this.)
+ *
+ * (11/29/2000) gkh
  *	Small NULL pointer initialization cleanup which saves a bit of disk image
  *
  * (11/01/2000) Adam J. Richter
@@ -471,6 +477,8 @@
 		return -ENODEV;
 	}
 
+	MOD_INC_USE_COUNT;
+	
 	/* set up our port structure making the tty driver remember our port object, and us it */
 	portNumber = MINOR(tty->device) - serial->minor;
 	port = &serial->port[portNumber];
@@ -508,6 +516,8 @@
 	} else {
 		generic_close(port, filp);
 	}
+
+	MOD_DEC_USE_COUNT;
 }	
 
 
@@ -721,12 +731,13 @@
 	if (port_paranoia_check (port, __FUNCTION__))
 		return -ENODEV;
 
+	MOD_INC_USE_COUNT;
+
 	dbg(__FUNCTION__ " - port %d", port->number);
 
 	spin_lock_irqsave (&port->port_lock, flags);
 	
 	++port->open_count;
-	MOD_INC_USE_COUNT;
 	
 	if (!port->active) {
 		port->active = 1;
@@ -776,6 +787,7 @@
 	}
 
 	spin_unlock_irqrestore (&port->port_lock, flags);
+	MOD_DEC_USE_COUNT;
 }
 
 
@@ -1069,7 +1081,6 @@
 	}
 
 	/* found all that we need */
-	MOD_INC_USE_COUNT;
 	info("%s converter detected", type->name);
 
 #ifdef CONFIG_USB_SERIAL_GENERIC
@@ -1077,7 +1088,6 @@
 		num_ports = num_bulk_out;
 		if (num_ports == 0) {
 			err("Generic device with no bulk out, not allowed.");
-			MOD_DEC_USE_COUNT;
 			return NULL;
 		}
 	} else
@@ -1087,7 +1097,6 @@
 	serial = get_free_serial (num_ports, &minor);
 	if (serial == NULL) {
 		err("No more free serial devices");
-		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	
@@ -1233,7 +1242,6 @@
 
 	/* free up any memory that we allocated */
 	kfree (serial);
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
@@ -1300,7 +1308,6 @@
 		info("device disconnected");
 	}
 	
-	MOD_DEC_USE_COUNT;
 }
 
 
diff -urN linux-2.4.1-pre7/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c
--- linux-2.4.1-pre7/drivers/usb/serial/visor.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/serial/visor.c	Mon Dec  3 22:25:25 2001
@@ -10,6 +10,10 @@
  *	(at your option) any later version.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
+ *
+ * (12/12/2000) gkh
+ *	Moved MOD_DEC to end of visor_close to be nicer, as the final write 
+ *	message can sleep.
  * 
  * (11/12/2000) gkh
  *	Fixed bug with data being dropped on the floor by forcing tty->low_latency
@@ -214,7 +218,6 @@
 	spin_lock_irqsave (&port->port_lock, flags);
 
 	--port->open_count;
-	MOD_DEC_USE_COUNT;
 
 	if (port->open_count <= 0) {
 		transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
@@ -237,6 +240,8 @@
 
 	/* Uncomment the following line if you want to see some statistics in your syslog */
 	/* info ("Bytes In = %d  Bytes Out = %d", bytes_in, bytes_out); */
+
+	MOD_DEC_USE_COUNT;
 }
 
 
diff -urN linux-2.4.1-pre7/drivers/usb/storage/debug.h linux/drivers/usb/storage/debug.h
--- linux-2.4.1-pre7/drivers/usb/storage/debug.h	Thu Jan  4 14:52:19 2001
+++ linux/drivers/usb/storage/debug.h	Mon Dec  3 22:25:25 2001
@@ -1,7 +1,7 @@
 /* Driver for USB Mass Storage compliant devices
  * Debugging Functions Header File
  *
- * $Id: debug.h,v 1.5 2000/09/04 02:12:47 groovyjava Exp $
+ * $Id: debug.h,v 1.6 2001/01/12 23:51:04 mdharm Exp $
  *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
diff -urN linux-2.4.1-pre7/drivers/usb/storage/scsiglue.c linux/drivers/usb/storage/scsiglue.c
--- linux-2.4.1-pre7/drivers/usb/storage/scsiglue.c	Fri Dec 29 14:07:23 2000
+++ linux/drivers/usb/storage/scsiglue.c	Mon Dec  3 22:25:25 2001
@@ -248,7 +248,7 @@
         for (i = 0; i < us->pusb_dev->actconfig->bNumInterfaces; i++) {
  		struct usb_interface *intf =
 			&us->pusb_dev->actconfig->interface[i];
-		const struct usb_device_id *id;
+		struct usb_device_id *id;
 
 		/* if this is an unclaimed interface, skip it */
 		if (!intf->driver) {
diff -urN linux-2.4.1-pre7/drivers/usb/storage/unusual_devs.h linux/drivers/usb/storage/unusual_devs.h
--- linux-2.4.1-pre7/drivers/usb/storage/unusual_devs.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/storage/unusual_devs.h	Mon Dec  3 22:25:25 2001
@@ -0,0 +1,232 @@
+/* Driver for USB Mass Storage compliant devices
+ * Ununsual Devices File
+ *
+ * $Id: unusual_devs.h,v 1.1 2000/12/05 05:38:31 mdharm Exp $
+ *
+ * Current development and maintenance by:
+ *   (c) 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ *
+ * Initial work by:
+ *   (c) 2000 Adam J. Richter (adam@yggdrasil.com), Yggdrasil Computing, Inc.
+ *
+ * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
+ * information about this driver.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* IMPORTANT NOTE: This file must be included in another file which does
+ * both of the following things for it to work:
+ * (1) <include/config.h> _must_ be included before this file
+ * (2) The macro UNUSUAL_DEV() must be defined before this file is included
+ */
+
+/* If you edit this file, please try to keep it sorted first by VendorID,
+ * then by ProductID.
+ */
+
+UNUSUAL_DEV(  0x03ee, 0x0000, 0x0000, 0x0245, 
+		"Mitsumi",
+		"CD-R/RW Drive",
+		US_SC_8020, US_PR_CBI, NULL, 0), 
+
+UNUSUAL_DEV(  0x03f0, 0x0107, 0x0200, 0x0200, 
+		"HP",
+		"CD-Writer+",
+		US_SC_8070, US_PR_CB, NULL, 0), 
+
+#ifdef CONFIG_USB_STORAGE_HP8200e
+UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001, 
+		"HP",
+		"CD-Writer+ 8200e",
+		US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0), 
+#endif
+
+UNUSUAL_DEV(  0x04e6, 0x0001, 0x0200, 0x0200, 
+		"Matshita",
+		"LS-120",
+		US_SC_8020, US_PR_CB, NULL, 0),
+
+UNUSUAL_DEV(  0x04e6, 0x0002, 0x0100, 0x0100, 
+		"Shuttle",
+		"eUSCSI Bridge",
+		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, 
+		US_FL_SCM_MULT_TARG ), 
+
+#ifdef CONFIG_USB_STORAGE_SDDR09
+UNUSUAL_DEV(  0x04e6, 0x0003, 0x0000, 0x9999, 
+		"Sandisk",
+		"ImageMate SDDR09",
+		US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
+		US_FL_SINGLE_LUN | US_FL_START_STOP ),
+#endif
+
+#ifdef CONFIG_USB_STORAGE_DPCM
+UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
+		"Microtech",
+		"CameraMate (DPCM_USB)",
+ 		US_SC_SCSI, US_PR_DPCM_USB, NULL,
+		US_FL_START_STOP ),
+#endif
+
+UNUSUAL_DEV(  0x04e6, 0x0006, 0x0100, 0x0200, 
+		"Shuttle",
+		"eUSB MMC Adapter",
+		US_SC_SCSI, US_PR_CB, NULL, 
+		US_FL_SINGLE_LUN), 
+
+UNUSUAL_DEV(  0x04e6, 0x0007, 0x0100, 0x0200, 
+		"Sony",
+		"Hifd",
+		US_SC_SCSI, US_PR_CB, NULL, 
+		US_FL_SINGLE_LUN), 
+
+UNUSUAL_DEV(  0x04e6, 0x0009, 0x0200, 0x0200, 
+		"Shuttle",
+		"eUSB ATA/ATAPI Adapter",
+		US_SC_8020, US_PR_CB, NULL, 0),
+
+UNUSUAL_DEV(  0x04e6, 0x000a, 0x0200, 0x0200, 
+		"Shuttle",
+		"eUSB CompactFlash Adapter",
+		US_SC_8020, US_PR_CB, NULL, 0),
+
+UNUSUAL_DEV(  0x04e6, 0x000B, 0x0100, 0x0100, 
+		"Shuttle",
+		"eUSCSI Bridge",
+		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, 
+		US_FL_SCM_MULT_TARG ), 
+
+UNUSUAL_DEV(  0x04e6, 0x000C, 0x0100, 0x0100, 
+		"Shuttle",
+		"eUSCSI Bridge",
+		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, 
+		US_FL_SCM_MULT_TARG ), 
+
+UNUSUAL_DEV(  0x04e6, 0x0101, 0x0200, 0x0200, 
+		"Shuttle",
+		"CD-RW Device",
+		US_SC_8020, US_PR_CB, NULL, 0),
+
+UNUSUAL_DEV(  0x054c, 0x0010, 0x0106, 0x0210, 
+		"Sony",
+		"DSC-S30/S70/505V/F505", 
+		US_SC_SCSI, US_PR_CB, NULL,
+		US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE ),
+
+UNUSUAL_DEV(  0x054c, 0x002d, 0x0100, 0x0100, 
+		"Sony",
+		"Memorystick MSAC-US1",
+		US_SC_UFI, US_PR_CB, NULL,
+		US_FL_SINGLE_LUN | US_FL_START_STOP ),
+
+UNUSUAL_DEV(  0x057b, 0x0000, 0x0000, 0x0299, 
+		"Y-E Data",
+		"Flashbuster-U",
+		US_SC_UFI,  US_PR_CB, NULL,
+		US_FL_SINGLE_LUN),
+
+UNUSUAL_DEV(  0x057b, 0x0000, 0x0300, 0x9999, 
+		"Y-E Data",
+		"Flashbuster-U",
+		US_SC_UFI,  US_PR_CBI, NULL,
+		US_FL_SINGLE_LUN),
+
+UNUSUAL_DEV(  0x059f, 0xa601, 0x0200, 0x0200, 
+		"LaCie",
+		"USB Hard Disk",
+		US_SC_RBC, US_PR_CB, NULL, 0 ), 
+
+UNUSUAL_DEV(  0x05ab, 0x0031, 0x0100, 0x0100, 
+		"In-System",
+		"USB/IDE Bridge (ATAPI ONLY!)",
+		US_SC_8070, US_PR_BULK, NULL, 0 ), 
+
+UNUSUAL_DEV(  0x0644, 0x0000, 0x0100, 0x0100, 
+		"TEAC",
+		"Floppy Drive",
+		US_SC_UFI, US_PR_CB, NULL, 0 ), 
+
+#ifdef CONFIG_USB_STORAGE_SDDR09
+UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x0100, 
+		"Olympus",
+		"Camedia MAUSB-2",
+		US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
+		US_FL_SINGLE_LUN | US_FL_START_STOP ),
+#endif
+
+UNUSUAL_DEV(  0x0693, 0x0002, 0x0100, 0x0100, 
+		"Hagiwara",
+		"FlashGate SmartMedia",
+		US_SC_SCSI, US_PR_BULK, NULL, 0 ),
+
+UNUSUAL_DEV(  0x0693, 0x0005, 0x0100, 0x0100,
+		"Hagiwara",
+		"Flashgate",
+		US_SC_SCSI, US_PR_BULK, NULL, 0 ), 
+
+UNUSUAL_DEV(  0x0781, 0x0001, 0x0200, 0x0200, 
+		"Sandisk",
+		"ImageMate SDDR-05a",
+		US_SC_SCSI, US_PR_CB, NULL,
+		US_FL_SINGLE_LUN | US_FL_START_STOP),
+
+UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100,
+                "Sandisk",
+                "ImageMate SDDR-12",
+                US_SC_SCSI, US_PR_CB, NULL,
+                US_FL_SINGLE_LUN ),
+
+#ifdef CONFIG_USB_STORAGE_SDDR09
+UNUSUAL_DEV(  0x0781, 0x0200, 0x0100, 0x0100, 
+		"Sandisk",
+		"ImageMate SDDR-09",
+		US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
+		US_FL_SINGLE_LUN | US_FL_START_STOP ),
+#endif
+
+UNUSUAL_DEV(  0x0781, 0x0002, 0x0009, 0x0009, 
+		"Sandisk",
+		"ImageMate SDDR-31",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_IGNORE_SER),
+
+UNUSUAL_DEV(  0x07af, 0x0004, 0x0100, 0x0100, 
+		"Microtech",
+		"USB-SCSI-DB25",
+		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+		US_FL_SCM_MULT_TARG ), 
+
+#ifdef CONFIG_USB_STORAGE_FREECOM
+UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999,
+                "Freecom",
+                "USB-IDE",
+                US_SC_QIC, US_PR_FREECOM, freecom_init, 0),
+#endif
+
+UNUSUAL_DEV(  0x07af, 0x0005, 0x0100, 0x0100, 
+		"Microtech",
+		"USB-SCSI-HD50",
+		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+		US_FL_SCM_MULT_TARG ), 
+
+#ifdef CONFIG_USB_STORAGE_DPCM
+UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
+		"Microtech",
+		"CameraMate (DPCM_USB)",
+ 		US_SC_SCSI, US_PR_DPCM_USB, NULL,
+		US_FL_START_STOP ),
+#endif
+
diff -urN linux-2.4.1-pre7/drivers/usb/storage/usb.c linux/drivers/usb/storage/usb.c
--- linux-2.4.1-pre7/drivers/usb/storage/usb.c	Fri Dec 29 14:07:23 2000
+++ linux/drivers/usb/storage/usb.c	Mon Dec  3 22:25:25 2001
@@ -1,6 +1,6 @@
 /* Driver for USB Mass Storage compliant devices
  *
- * $Id: usb.c,v 1.57 2000/11/21 02:56:41 mdharm Exp $
+ * $Id: usb.c,v 1.61 2001/01/13 00:10:59 mdharm Exp $
  *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -11,6 +11,9 @@
  * Initial work by:
  *   (c) 1999 Michael Gee (michael@linuxspecific.com)
  *
+ * usb_device_id support by Adam J. Richter (adam@yggdrasil.com):
+ *   (c) 2000 Yggdrasil Computing, Inc.
+ *
  * This driver is based on the 'USB Mass Storage Class' document. This
  * describes in detail the protocol used to communicate with such
  * devices.  Clearly, the designers had SCSI and ATAPI commands in
@@ -95,11 +98,133 @@
 
 static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
 			    const struct usb_device_id *id);
+
 static void storage_disconnect(struct usb_device *dev, void *ptr);
+
+/* The entries in this table, except for final ones here
+ * (USB_MASS_STORAGE_CLASS and the empty entry), correspond,
+ * line for line with the entries of us_unsuaul_dev_list[].
+ * For now, we duplicate idVendor and idProduct in us_unsual_dev_list,
+ * just to avoid alignment bugs.
+ */
+
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName,useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax) }
+
+static struct usb_device_id storage_usb_ids [] = {
+
+#	include "unusual_devs.h"
+#undef UNUSUAL_DEV
+	/* Control/Bulk transport for all SubClass values */
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CB) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CB) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CB) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CB) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CB) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CB) },
+
+	/* Control/Bulk/Interrupt transport for all SubClass values */
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CBI) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CBI) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CBI) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CBI) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CBI) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CBI) },
+
+	/* Bulk-only transport for all SubClass values */
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_BULK) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_BULK) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
+
+	/* Terminating entry */
+	{ }
+};
+
+MODULE_DEVICE_TABLE (usb, storage_usb_ids);
+
+/* This is the list of devices we recognize, along with their flag data */
+
+/* The vendor name should be kept at eight characters or less, and
+ * the product name should be kept at 16 characters or less. If a device
+ * has the US_FL_DUMMY_INQUIRY flag, then the vendor and product names
+ * normally generated by a device thorugh the INQUIRY response will be
+ * taken from this list, and this is the reason for the above size
+ * restriction. However, if the flag is not present, then you
+ * are free to use as many characters as you like.
+ */
+
+#undef UNUSUAL_DEV
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+		    vendor_name, product_name, use_protocol, use_transport, \
+		    init_function, Flags) \
+{ \
+	vendorName: vendor_name,	\
+	productName: product_name,	\
+	useProtocol: use_protocol,	\
+	useTransport: use_transport,	\
+	initFunction : init_function,	\
+	flags: Flags, \
+}
+
+static struct us_unusual_dev us_unusual_dev_list[] = {
+#	include "unusual_devs.h" 
+#	undef UNUSUAL_DEV
+	/* Control/Bulk transport for all SubClass values */
+	{ useProtocol: US_SC_RBC,
+	  useTransport: US_PR_CB},
+	{ useProtocol: US_SC_8020,
+	  useTransport: US_PR_CB},
+	{ useProtocol: US_SC_QIC,
+	  useTransport: US_PR_CB},
+	{ useProtocol: US_SC_UFI,
+	  useTransport: US_PR_CB},
+	{ useProtocol: US_SC_8070,
+	  useTransport: US_PR_CB},
+	{ useProtocol: US_SC_SCSI,
+	  useTransport: US_PR_CB},
+
+	/* Control/Bulk/Interrupt transport for all SubClass values */
+	{ useProtocol: US_SC_RBC,
+	  useTransport: US_PR_CBI},
+	{ useProtocol: US_SC_8020,
+	  useTransport: US_PR_CBI},
+	{ useProtocol: US_SC_QIC,
+	  useTransport: US_PR_CBI},
+	{ useProtocol: US_SC_UFI,
+	  useTransport: US_PR_CBI},
+	{ useProtocol: US_SC_8070,
+	  useTransport: US_PR_CBI},
+	{ useProtocol: US_SC_SCSI,
+	  useTransport: US_PR_CBI},
+
+	/* Bulk-only transport for all SubClass values */
+	{ useProtocol: US_SC_RBC,
+	  useTransport: US_PR_BULK},
+	{ useProtocol: US_SC_8020,
+	  useTransport: US_PR_BULK},
+	{ useProtocol: US_SC_QIC,
+	  useTransport: US_PR_BULK},
+	{ useProtocol: US_SC_UFI,
+	  useTransport: US_PR_BULK},
+	{ useProtocol: US_SC_8070,
+	  useTransport: US_PR_BULK},
+	{ useProtocol: US_SC_SCSI,
+	  useTransport: US_PR_BULK},
+
+	/* Terminating entry */
+	{ 0 }
+};
+
 struct usb_driver usb_storage_driver = {
 	name:		"usb-storage",
 	probe:		storage_probe,
 	disconnect:	storage_disconnect,
+	id_table:	storage_usb_ids,
 };
 
 /*
@@ -325,246 +450,6 @@
 	return 0;
 }	
 
-/* This is the list of devices we recognize, along with their flag data */
-
-/* The vendor name should be kept at eight characters or less, and
- * the product name should be kept at 16 characters or less. If a device
- * has the US_FL_DUMMY_INQUIRY flag, then the vendor and product names
- * normally generated by a device thorugh the INQUIRY response will be
- * taken from this list, and this is the reason for the above size
- * restriction. However, if the flag is not present, then you
- * are free to use as many characters as you like.
- */
-static struct us_unusual_dev us_unusual_dev_list[] = {
-
-	{ 0x03ee, 0x0000, 0x0000, 0x0245, 
-		"Mitsumi",
-		"CD-R/RW Drive",
-		US_SC_8020, US_PR_CBI, NULL, 0}, 
-
-	{ 0x03f0, 0x0107, 0x0200, 0x0200, 
-		"HP",
-		"CD-Writer+",
-		US_SC_8070, US_PR_CB, NULL, 0}, 
-
-#ifdef CONFIG_USB_STORAGE_HP8200e
-	{ 0x03f0, 0x0207, 0x0001, 0x0001, 
-		"HP",
-		"CD-Writer+ 8200e",
-		US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0}, 
-#endif
-
-	{ 0x04e6, 0x0001, 0x0200, 0x0200, 
-		"Matshita",
-		"LS-120",
-		US_SC_8020, US_PR_CB, NULL, 0},
-
-	{ 0x04e6, 0x0002, 0x0100, 0x0100, 
-		"Shuttle",
-		"eUSCSI Bridge",
-		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, 
-		US_FL_SCM_MULT_TARG }, 
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
-	{ 0x04e6, 0x0003, 0x0000, 0x9999, 
-		"Sandisk",
-		"ImageMate SDDR09",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
-		US_FL_SINGLE_LUN | US_FL_START_STOP },
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DPCM
- 	{ 0x0436, 0x0005, 0x0100, 0x0100,
-		"Microtech",
-		"CameraMate (DPCM_USB)",
- 		US_SC_SCSI, US_PR_DPCM_USB, NULL,
-		US_FL_START_STOP },
-#endif
-
-	{ 0x04e6, 0x0006, 0x0100, 0x0200, 
-		"Shuttle",
-		"eUSB MMC Adapter",
-		US_SC_SCSI, US_PR_CB, NULL, 
-		US_FL_SINGLE_LUN}, 
-
-	{ 0x04e6, 0x0007, 0x0100, 0x0200, 
-		"Sony",
-		"Hifd",
-		US_SC_SCSI, US_PR_CB, NULL, 
-		US_FL_SINGLE_LUN}, 
-
-	{ 0x04e6, 0x0009, 0x0200, 0x0200, 
-		"Shuttle",
-		"eUSB ATA/ATAPI Adapter",
-		US_SC_8020, US_PR_CB, NULL, 0},
-
-	{ 0x04e6, 0x000a, 0x0200, 0x0200, 
-		"Shuttle",
-		"eUSB CompactFlash Adapter",
-		US_SC_8020, US_PR_CB, NULL, 0},
-
-	{ 0x04e6, 0x000B, 0x0100, 0x0100, 
-		"Shuttle",
-		"eUSCSI Bridge",
-		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, 
-		US_FL_SCM_MULT_TARG }, 
-
-	{ 0x04e6, 0x000C, 0x0100, 0x0100, 
-		"Shuttle",
-		"eUSCSI Bridge",
-		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, 
-		US_FL_SCM_MULT_TARG }, 
-
-	{ 0x04e6, 0x0101, 0x0200, 0x0200, 
-		"Shuttle",
-		"CD-RW Device",
-		US_SC_8020, US_PR_CB, NULL, 0},
-
-	{ 0x054c, 0x0010, 0x0106, 0x0210, 
-		"Sony",
-		"DSC-S30/S70/505V/F505", 
-		US_SC_SCSI, US_PR_CB, NULL,
-		US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE },
-
-	{ 0x054c, 0x002d, 0x0100, 0x0100, 
-		"Sony",
-		"Memorystick MSAC-US1",
-		US_SC_UFI, US_PR_CB, NULL,
-		US_FL_SINGLE_LUN | US_FL_START_STOP },
-
-	{ 0x057b, 0x0000, 0x0000, 0x0299, 
-		"Y-E Data",
-		"Flashbuster-U",
-		US_SC_UFI,  US_PR_CB, NULL,
-		US_FL_SINGLE_LUN},
-
-	{ 0x057b, 0x0000, 0x0300, 0x9999, 
-		"Y-E Data",
-		"Flashbuster-U",
-		US_SC_UFI,  US_PR_CBI, NULL,
-		US_FL_SINGLE_LUN},
-
-	{ 0x059f, 0xa601, 0x0200, 0x0200, 
-		"LaCie",
-		"USB Hard Disk",
-		US_SC_RBC, US_PR_CB, NULL, 0 }, 
-
-	{ 0x05ab, 0x0031, 0x0100, 0x0100, 
-		"In-System",
-		"USB/IDE Bridge (ATAPI ONLY!)",
-		US_SC_8070, US_PR_BULK, NULL, 0 }, 
-
-	{ 0x0644, 0x0000, 0x0100, 0x0100, 
-		"TEAC",
-		"Floppy Drive",
-		US_SC_UFI, US_PR_CB, NULL, 0 }, 
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
-	{ 0x066b, 0x0105, 0x0100, 0x0100, 
-		"Olympus",
-		"Camedia MAUSB-2",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
-		US_FL_SINGLE_LUN | US_FL_START_STOP },
-#endif
-
-	{ 0x0693, 0x0002, 0x0100, 0x0100, 
-		"Hagiwara",
-		"FlashGate SmartMedia",
-		US_SC_SCSI, US_PR_BULK, NULL, 0 },
-
-	{ 0x0693, 0x0005, 0x0100, 0x0100,
-		"Hagiwara",
-		"Flashgate",
-		US_SC_SCSI, US_PR_BULK, NULL, 0 }, 
-
-	{ 0x0781, 0x0001, 0x0200, 0x0200, 
-		"Sandisk",
-		"ImageMate SDDR-05a",
-		US_SC_SCSI, US_PR_CB, NULL,
-		US_FL_SINGLE_LUN | US_FL_START_STOP},
-
-        { 0x0781, 0x0100, 0x0100, 0x0100,
-                "Sandisk",
-                "ImageMate SDDR-12",
-                US_SC_SCSI, US_PR_CB, NULL,
-                US_FL_SINGLE_LUN },
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
-	{ 0x0781, 0x0200, 0x0100, 0x0208, 
-		"Sandisk",
-		"ImageMate SDDR-09",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
-		US_FL_SINGLE_LUN | US_FL_START_STOP },
-#endif
-
-	{ 0x0781, 0x0002, 0x0009, 0x0009, 
-		"Sandisk",
-		"ImageMate SDDR-31",
-		US_SC_SCSI, US_PR_BULK, NULL,
-		US_FL_IGNORE_SER},
-
-	{ 0x07af, 0x0004, 0x0100, 0x0100, 
-		"Microtech",
-		"USB-SCSI-DB25",
-		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
-		US_FL_SCM_MULT_TARG }, 
-
-#ifdef CONFIG_USB_STORAGE_FREECOM
-        { 0x07ab, 0xfc01, 0x0000, 0x9999,
-                "Freecom",
-                "USB-IDE",
-                US_SC_QIC, US_PR_FREECOM, freecom_init, 0},
-#endif
-
-	{ 0x07af, 0x0005, 0x0100, 0x0100, 
-		"Microtech",
-		"USB-SCSI-HD50",
-		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
-		US_FL_SCM_MULT_TARG }, 
-
-#ifdef CONFIG_USB_STORAGE_DPCM
- 	{ 0x07af, 0x0006, 0x0100, 0x0100,
-		"Microtech",
-		"CameraMate (DPCM_USB)",
- 		US_SC_SCSI, US_PR_DPCM_USB, NULL,
-		US_FL_START_STOP },
-#endif
-	{ 0 }
-};
-
-/* Search our ususual device list, based on vendor/product combinations
- * to see if we can support this device.  Returns a pointer to a structure
- * defining how we should support this device, or NULL if it's not in the
- * list
- */
-static struct us_unusual_dev* us_find_dev(u16 idVendor, u16 idProduct, 
-					  u16 bcdDevice)
-{
-	struct us_unusual_dev* ptr;
-
-	US_DEBUGP("Searching unusual device list for (0x%x, 0x%x, 0x%x)...\n",
-		  idVendor, idProduct, bcdDevice);
-
-	ptr = us_unusual_dev_list;
-	while ((ptr->idVendor != 0x0000) && 
-	       !((ptr->idVendor == idVendor) && 
-		 (ptr->idProduct == idProduct) &&
-		 (ptr->bcdDeviceMin <= bcdDevice) &&
-		 (ptr->bcdDeviceMax >= bcdDevice)))
-		ptr++;
-
-	/* if the search ended because we hit the end record, we failed */
-	if (ptr->idVendor == 0x0000) {
-		US_DEBUGP("-- did not find a matching device\n");
-		return NULL;
-	}
-
-	/* otherwise, we found one! */
-	US_DEBUGP("-- found matching device: %s %s\n", ptr->vendorName,
-		ptr->productName);
-	return ptr;
-}
-
 /* Set up the IRQ pipe and handler
  * Note that this function assumes that all the data in the us_data
  * strucuture is current.  This includes the ep_int field, which gives us
@@ -620,6 +505,7 @@
 			    const struct usb_device_id *id)
 {
 	int i;
+	const int id_index = id - storage_usb_ids; 
 	char mf[USB_STOR_STRING_LEN];		     /* manufacturer */
 	char prod[USB_STOR_STRING_LEN];		     /* product */
 	char serial[USB_STOR_STRING_LEN];	     /* serial number */
@@ -640,47 +526,48 @@
 	u8 subclass = 0;
 	u8 protocol = 0;
 
-	/* the altsettting 0 on the interface we're probing */
-	struct usb_interface_descriptor *altsetting = 
-		&(dev->actconfig->interface[ifnum].altsetting[0]); 
+	/* the altsettting on the interface we're probing that matched our
+	 * usb_match_id table
+	 */
+	struct usb_interface *intf = dev->actconfig->interface;
+	struct usb_interface_descriptor *altsetting =
+		intf[ifnum].altsetting + intf[ifnum].act_altsetting;
+	US_DEBUGP("act_altsettting is %d\n", intf[ifnum].act_altsetting);
 
 	/* clear the temporary strings */
 	memset(mf, 0, sizeof(mf));
 	memset(prod, 0, sizeof(prod));
 	memset(serial, 0, sizeof(serial));
 
-	/* search for this device in our unusual device list */
-	unusual_dev = us_find_dev(dev->descriptor.idVendor, 
-				  dev->descriptor.idProduct,
-				  dev->descriptor.bcdDevice);
-
 	/* 
 	 * Can we support this device, either because we know about it
 	 * from our unusual device list, or because it advertises that it's
 	 * compliant to the specification?
+	 *
+	 * id_index is calculated in the declaration to be the index number
+	 * of the match from the usb_device_id table, so we can find the
+	 * corresponding entry in the private table.
 	 */
-	if (!unusual_dev &&
-	    !(dev->descriptor.bDeviceClass == 0 &&
-	      altsetting->bInterfaceClass == USB_CLASS_MASS_STORAGE &&
-	      altsetting->bInterfaceSubClass >= US_SC_MIN &&
-	      altsetting->bInterfaceSubClass <= US_SC_MAX)) {
-		/* if it's not a mass storage, we go no further */
+	US_DEBUGP("id_index calculated to be: %d\n", id_index);
+	US_DEBUGP("Array length appears to be: %d\n", sizeof(us_unusual_dev_list) / sizeof(us_unusual_dev_list[0]));
+	if (id_index <
+	    sizeof(us_unusual_dev_list) / sizeof(us_unusual_dev_list[0])) {
+		unusual_dev = &us_unusual_dev_list[id_index];
+		if (unusual_dev->vendorName)
+			US_DEBUGP("Vendor: %s\n", unusual_dev->vendorName);
+		if (unusual_dev->productName)
+			US_DEBUGP("Product: %s\n", unusual_dev->productName);
+	} else
+		/* no, we can't support it */
 		return NULL;
-	}
 
 	/* At this point, we know we've got a live one */
 	US_DEBUGP("USB Mass Storage device detected\n");
 
 	/* Determine subclass and protocol, or copy from the interface */
-	if (unusual_dev) {
-		subclass = unusual_dev->useProtocol;
-		protocol = unusual_dev->useTransport;
-		flags = unusual_dev->flags;
-	} else {
-		subclass = altsetting->bInterfaceSubClass;
-		protocol = altsetting->bInterfaceProtocol;
-		flags = 0;
-	}
+	subclass = unusual_dev->useProtocol;
+	protocol = unusual_dev->useTransport;
+	flags = unusual_dev->flags;
 
 	/*
 	 * Find the endpoints we need
@@ -728,7 +615,7 @@
 
 	/* Do some basic sanity checks, and bail if we find a problem */
 	if (!ep_in || !ep_out || (protocol == US_PR_CBI && !ep_int)) {
-		US_DEBUGP("Sanity check failed.	 Rejecting device.\n");
+		US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n");
 		return NULL;
 	}
 
@@ -861,7 +748,7 @@
 		strncpy(ss->product, prod, USB_STOR_STRING_LEN);
 		strncpy(ss->serial, serial, USB_STOR_STRING_LEN);
 		if (strlen(ss->vendor) == 0) {
-			if (unusual_dev)
+			if (unusual_dev->vendorName)
 				strncpy(ss->vendor, unusual_dev->vendorName,
 					USB_STOR_STRING_LEN);
 			else
@@ -869,7 +756,7 @@
 					USB_STOR_STRING_LEN);
 		}
 		if (strlen(ss->product) == 0) {
-			if (unusual_dev)
+			if (unusual_dev->productName)
 				strncpy(ss->product, unusual_dev->productName,
 					USB_STOR_STRING_LEN);
 			else
@@ -1118,6 +1005,8 @@
 
 int __init usb_stor_init(void)
 {
+	printk(KERN_INFO "Initializing USB Mass Storage driver...\n");
+
 	/* initialize internal global data elements */
 	us_list = NULL;
 	init_MUTEX(&us_list_semaphore);
diff -urN linux-2.4.1-pre7/drivers/usb/storage/usb.h linux/drivers/usb/storage/usb.h
--- linux-2.4.1-pre7/drivers/usb/storage/usb.h	Thu Jan  4 14:52:19 2001
+++ linux/drivers/usb/storage/usb.h	Mon Dec  3 22:25:25 2001
@@ -1,7 +1,7 @@
 /* Driver for USB Mass Storage compliant devices
  * Main Header File
  *
- * $Id: usb.h,v 1.11 2000/11/13 22:38:55 mdharm Exp $
+ * $Id: usb.h,v 1.12 2000/12/05 03:33:49 mdharm Exp $
  *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -84,13 +84,6 @@
  */
 
 struct us_unusual_dev {
-	/* we search the list based on these parameters */
-	__u16 idVendor;
-	__u16 idProduct;
-	__u16 bcdDeviceMin;
-	__u16 bcdDeviceMax;
-
-	/* the list specifies these parameters */
 	const char* vendorName;
 	const char* productName;
 	__u8  useProtocol;
diff -urN linux-2.4.1-pre7/fs/fat/cache.c linux/fs/fat/cache.c
--- linux-2.4.1-pre7/fs/fat/cache.c	Fri Dec 29 14:07:23 2000
+++ linux/fs/fat/cache.c	Mon Dec  3 22:25:25 2001
@@ -24,6 +24,7 @@
 #endif
 
 static struct fat_cache *fat_cache,cache[FAT_CACHE];
+static spinlock_t fat_cache_lock = SPIN_LOCK_UNLOCKED;
 
 /* Returns the this'th FAT entry, -1 if it is an end-of-file entry. If
    new_value is != -1, that FAT entry is replaced by it. */
@@ -133,13 +134,16 @@
 	return next;
 }
 
-
 void fat_cache_init(void)
 {
 	static int initialized = 0;
 	int count;
 
-	if (initialized) return;
+	spin_lock(&fat_cache_lock);
+	if (initialized) {
+		spin_unlock(&fat_cache_lock);
+		return;
+		}
 	fat_cache = &cache[0];
 	for (count = 0; count < FAT_CACHE; count++) {
 		cache[count].device = 0;
@@ -147,6 +151,7 @@
 		    &cache[count+1];
 	}
 	initialized = 1;
+	spin_unlock(&fat_cache_lock);
 }
 
 
@@ -157,6 +162,7 @@
 
 	if (!first)
 		return;
+	spin_lock(&fat_cache_lock);
 	for (walk = fat_cache; walk; walk = walk->next)
 		if (inode->i_dev == walk->device
 		    && walk->start_cluster == first
@@ -166,8 +172,12 @@
 #ifdef DEBUG
 printk("cache hit: %d (%d)\n",walk->file_cluster,*d_clu);
 #endif
-			if ((*f_clu = walk->file_cluster) == cluster) return;
+			if ((*f_clu = walk->file_cluster) == cluster) { 
+				spin_unlock(&fat_cache_lock);
+				return;
+			}
 		}
+	spin_unlock(&fat_cache_lock);
 #ifdef DEBUG
 printk("cache miss\n");
 #endif
@@ -197,6 +207,7 @@
 	int first = MSDOS_I(inode)->i_start;
 
 	last = NULL;
+	spin_lock(&fat_cache_lock);
 	for (walk = fat_cache; walk->next; walk = (last = walk)->next)
 		if (inode->i_dev == walk->device
 		    && walk->start_cluster == first
@@ -204,17 +215,22 @@
 			if (walk->disk_cluster != d_clu) {
 				printk("FAT cache corruption inode=%ld\n",
 					inode->i_ino);
+				spin_unlock(&fat_cache_lock);
 				fat_cache_inval_inode(inode);
 				return;
 			}
 			/* update LRU */
-			if (last == NULL) return;
+			if (last == NULL) {
+				spin_unlock(&fat_cache_lock);
+				return;
+			}
 			last->next = walk->next;
 			walk->next = fat_cache;
 			fat_cache = walk;
 #ifdef DEBUG
 list_cache();
 #endif
+			spin_unlock(&fat_cache_lock);
 			return;
 		}
 	walk->device = inode->i_dev;
@@ -224,6 +240,7 @@
 	last->next = NULL;
 	walk->next = fat_cache;
 	fat_cache = walk;
+	spin_unlock(&fat_cache_lock);
 #ifdef DEBUG
 list_cache();
 #endif
@@ -238,10 +255,12 @@
 	struct fat_cache *walk;
 	int first = MSDOS_I(inode)->i_start;
 
+	spin_lock(&fat_cache_lock);
 	for (walk = fat_cache; walk; walk = walk->next)
 		if (walk->device == inode->i_dev
 		    && walk->start_cluster == first)
 			walk->device = 0;
+	spin_unlock(&fat_cache_lock);
 }
 
 
@@ -249,9 +268,11 @@
 {
 	struct fat_cache *walk;
 
+	spin_lock(&fat_cache_lock);
 	for (walk = fat_cache; walk; walk = walk->next)
 		if (walk->device == device)
 			walk->device = 0;
+	spin_unlock(&fat_cache_lock);
 }
 
 
diff -urN linux-2.4.1-pre7/fs/reiserfs/inode.c linux/fs/reiserfs/inode.c
--- linux-2.4.1-pre7/fs/reiserfs/inode.c	Mon Dec  3 22:25:17 2001
+++ linux/fs/reiserfs/inode.c	Mon Dec  3 22:25:25 2001
@@ -1853,6 +1853,7 @@
     struct reiserfs_transaction_handle th ;
     
     reiserfs_wait_on_write_block(inode->i_sb) ;
+    lock_kernel();
     prevent_flush_page_lock(page, inode) ;
     ret = generic_commit_write(f, page, from, to) ;
     /* we test for O_SYNC here so we can commit the transaction
@@ -1866,6 +1867,7 @@
 	journal_end_sync(&th, inode->i_sb, 1) ;
     }
     allow_flush_page_lock(page, inode) ;
+    unlock_kernel();
     return ret ;
 }
 
diff -urN linux-2.4.1-pre7/fs/super.c linux/fs/super.c
--- linux-2.4.1-pre7/fs/super.c	Fri Dec 29 14:18:42 2000
+++ linux/fs/super.c	Mon Dec  3 22:25:25 2001
@@ -54,6 +54,7 @@
 extern int root_mountflags;
 
 static int do_remount_sb(struct super_block *sb, int flags, char * data);
+static int do_remount(const char *dir, int flags, char * data);
 
 /* this is initialized in init/main.c */
 kdev_t ROOT_DEV;
@@ -1025,15 +1026,12 @@
 	 * call reboot(9). Then init(8) could umount root and exec /reboot.
 	 */
 	if (mnt == current->fs->rootmnt && !umount_root) {
-		int retval = 0;
 		/*
 		 * Special case for "unmounting" root ...
 		 * we just try to remount it readonly.
 		 */
 		mntput(mnt);
-		if (!(sb->s_flags & MS_RDONLY))
-			retval = do_remount_sb(sb, MS_RDONLY, 0);
-		return retval;
+		return do_remount("/", MS_RDONLY, NULL);
 	}
 
 	spin_lock(&dcache_lock);
diff -urN linux-2.4.1-pre7/include/linux/mm.h linux/include/linux/mm.h
--- linux-2.4.1-pre7/include/linux/mm.h	Mon Dec  3 22:25:17 2001
+++ linux/include/linux/mm.h	Mon Dec  3 22:25:25 2001
@@ -386,6 +386,7 @@
 
 struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int no_share);
 struct file *shmem_file_setup(char * name, loff_t size);
+extern void shmem_lock(struct file * file, int lock);
 extern int shmem_zero_setup(struct vm_area_struct *);
 
 extern void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size);
diff -urN linux-2.4.1-pre7/mm/shmem.c linux/mm/shmem.c
--- linux-2.4.1-pre7/mm/shmem.c	Mon Dec  3 22:25:17 2001
+++ linux/mm/shmem.c	Mon Dec  3 22:25:25 2001
@@ -117,11 +117,43 @@
 	return 0;
 }
 
+/*
+ * shmem_recalc_inode - recalculate the size of an inode
+ *
+ * @inode: inode to recalc
+ *
+ * We have to calculate the free blocks since the mm can drop pages
+ * behind our back
+ *
+ * But we know that normally
+ * inodes->i_blocks == inode->i_mapping->nrpages + info->swapped
+ *
+ * So the mm freed 
+ * inodes->i_blocks - (inode->i_mapping->nrpages + info->swapped)
+ *
+ * It has to be called with the spinlock held.
+ */
+
+static void shmem_recalc_inode(struct inode * inode)
+{
+	unsigned long freed;
+
+	freed = inode->i_blocks -
+		(inode->i_mapping->nrpages + inode->u.shmem_i.swapped);
+	if (freed){
+		struct shmem_sb_info * info = &inode->i_sb->u.shmem_sb;
+		inode->i_blocks -= freed;
+		spin_lock (&info->stat_lock);
+		info->free_blocks += freed;
+		spin_unlock (&info->stat_lock);
+	}
+}
+
 static void shmem_truncate (struct inode * inode)
 {
 	int clear_base;
 	unsigned long start;
-	unsigned long mmfreed, freed = 0;
+	unsigned long freed = 0;
 	swp_entry_t **base, **ptr;
 	struct shmem_inode_info * info = &inode->u.shmem_i;
 
@@ -154,26 +186,9 @@
 	info->i_indirect = 0;
 
 out:
-
-	/*
-	 * We have to calculate the free blocks since we do not know
-	 * how many pages the mm discarded
-	 *
-	 * But we know that normally
-	 * inodes->i_blocks == inode->i_mapping->nrpages + info->swapped
-	 *
-	 * So the mm freed 
-	 * inodes->i_blocks - (inode->i_mapping->nrpages + info->swapped)
-	 */
-
-	mmfreed = inode->i_blocks - (inode->i_mapping->nrpages + info->swapped);
 	info->swapped -= freed;
-	inode->i_blocks -= freed + mmfreed;
+	shmem_recalc_inode(inode);
 	spin_unlock (&info->lock);
-
-	spin_lock (&inode->i_sb->u.shmem_sb.stat_lock);
-	inode->i_sb->u.shmem_sb.free_blocks += freed + mmfreed;
-	spin_unlock (&inode->i_sb->u.shmem_sb.stat_lock);
 }
 
 static void shmem_delete_inode(struct inode * inode)
@@ -208,6 +223,7 @@
 		return 1;
 
 	spin_lock(&info->lock);
+	shmem_recalc_inode(page->mapping->host);
 	entry = shmem_swp_entry (info, page->index);
 	if (!entry)	/* this had been allocted on page allocation */
 		BUG();
@@ -269,6 +285,9 @@
 	entry = shmem_swp_entry (info, idx);
 	if (!entry)
 		goto oom;
+	spin_lock (&info->lock);
+	shmem_recalc_inode(inode);
+	spin_unlock (&info->lock);
 	if (entry->val) {
 		unsigned long flags;
 
