diff -BurN linux-2.4.21-11.EL/drivers/usb/devio.c linux-2.4.21-11-usbfix2-temp.EL/drivers/usb/devio.c
--- linux-2.4.21-11.EL/drivers/usb/devio.c	2004-03-08 22:15:09.000000000 -0600
+++ linux-2.4.21-11-usbfix2-temp.EL/drivers/usb/devio.c	2004-05-03 09:57:22.000000000 -0500
@@ -1171,6 +1171,12 @@
 		up_read(&ps->devsem);
 		return -ENODEV;
 	}
+	/*
+	 * grab device's exclusive_access mutex to prevent driver from
+	 * using this device while it is being accessed through /proc fs
+	 */
+	down (&(ps->dev->exclusive_access));
+
 	switch (cmd) {
 	case USBDEVFS_CONTROL:
 		ret = proc_control(ps, (void *)arg);
@@ -1250,6 +1256,7 @@
 		ret = proc_ioctl(ps, (void *) arg);
 		break;
 	}
+	up (&(ps->dev->exclusive_access));
 	up_read(&ps->devsem);
 	if (ret >= 0)
 		inode->i_atime = CURRENT_TIME;
diff -BurN linux-2.4.21-11.EL/drivers/usb/storage/transport.c linux-2.4.21-11-usbfix2-temp.EL/drivers/usb/storage/transport.c
--- linux-2.4.21-11.EL/drivers/usb/storage/transport.c	2004-03-08 22:15:15.000000000 -0600
+++ linux-2.4.21-11-usbfix2-temp.EL/drivers/usb/storage/transport.c	2004-05-03 09:57:23.000000000 -0500
@@ -627,8 +627,17 @@
 	int need_auto_sense;
 	int result;
 
+	/*
+	 * grab device's exclusive_access mutex to prevent /proc fs from
+	 * sending out a command in the middle of ours (if /proc sends a
+	 * get_descriptor or something on pipe 0 after our CBW and before
+	 * our CSW, and then we get a stall, we have trouble)
+	 */
+	down (&(us->pusb_dev->exclusive_access));
+
 	/* send the command to the transport layer */
 	result = us->transport(srb, us);
+	up (&(us->pusb_dev->exclusive_access));
 
 	/* if the command gets aborted by the higher layers, we need to
 	 * short-circuit all other processing
@@ -748,7 +757,9 @@
 		srb->use_sg = 0;
 
 		/* issue the auto-sense command */
+		down (&(us->pusb_dev->exclusive_access));
 		temp_result = us->transport(us->srb, us);
+		up (&(us->pusb_dev->exclusive_access));
 
 		/* let's clean up right away */
 		srb->request_buffer = old_request_buffer;
diff -BurN linux-2.4.21-11.EL/drivers/usb/usb.c linux-2.4.21-11-usbfix2-temp.EL/drivers/usb/usb.c
--- linux-2.4.21-11.EL/drivers/usb/usb.c	2004-03-08 22:15:09.000000000 -0600
+++ linux-2.4.21-11-usbfix2-temp.EL/drivers/usb/usb.c	2004-05-03 09:57:23.000000000 -0500
@@ -997,6 +997,7 @@
 	INIT_LIST_HEAD(&dev->filelist);
 
 	init_MUTEX(&dev->serialize);
+	init_MUTEX(&dev->exclusive_access);
 
 	dev->bus->op->allocate(dev);
 
diff -BurN linux-2.4.21-11.EL/include/linux/usb.h linux-2.4.21-11-usbfix2-temp.EL/include/linux/usb.h
--- linux-2.4.21-11.EL/include/linux/usb.h	2004-03-08 22:15:40.000000000 -0600
+++ linux-2.4.21-11-usbfix2-temp.EL/include/linux/usb.h	2004-05-03 09:57:40.000000000 -0500
@@ -828,6 +828,8 @@
 
 	atomic_t refcnt;		/* Reference count */
 	struct semaphore serialize;
+	struct semaphore exclusive_access; /* prevent driver & proc accesses 
+					      from overlapping cmds on bus  */
 
 	unsigned int toggle[2];		/* one bit for each endpoint ([0] = IN, [1] = OUT) */
 	unsigned int halted[2];		/* endpoint halts; one bit per endpoint # & direction; */
