# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.604.1.4 -> 1.604.1.5
#	drivers/usb/storage/usb.c	1.25    -> 1.26   
#	drivers/usb/storage/transport.c	1.20    -> 1.21   
#	drivers/usb/storage/usb.h	1.11    -> 1.12   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/07/04	mdharm-usb@one-eyed-alien.net	1.604.1.5
# [PATCH] usb-storage: code cleanup, small fixes
# 
# This patch consolidates quite a bit of code for allocation/deallocation of
# URBs, and removes a kmalloc() from a command path.
# --------------------------------------------
#
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c	Fri Jul  5 14:51:18 2002
+++ b/drivers/usb/storage/transport.c	Fri Jul  5 14:51:18 2002
@@ -428,18 +428,13 @@
 			 void *data, u16 size)
 {
 	int status;
-	struct usb_ctrlrequest *dr;
-
-	dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
-	if (!dr)
-		return -ENOMEM;
 
 	/* fill in the devrequest structure */
-	dr->bRequestType = requesttype;
-	dr->bRequest = request;
-	dr->wValue = cpu_to_le16(value);
-	dr->wIndex = cpu_to_le16(index);
-	dr->wLength = cpu_to_le16(size);
+	us->dr->bRequestType = requesttype;
+	us->dr->bRequest = request;
+	us->dr->wValue = cpu_to_le16(value);
+	us->dr->wIndex = cpu_to_le16(index);
+	us->dr->wLength = cpu_to_le16(size);
 
 	/* lock the URB */
 	down(&(us->current_urb_sem));
@@ -452,7 +447,7 @@
 
 	/* fill the URB */
 	FILL_CONTROL_URB(us->current_urb, us->pusb_dev, pipe, 
-			 (unsigned char*) dr, data, size, 
+			 (unsigned char*) us->dr, data, size, 
 			 usb_stor_blocking_completion, NULL);
 
 	/* submit the URB */
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	Fri Jul  5 14:51:18 2002
+++ b/drivers/usb/storage/usb.c	Fri Jul  5 14:51:18 2002
@@ -487,54 +487,114 @@
 	return 0;
 }	
 
-/* Set up the IRQ pipe and handler
+/* Set up the URB, the usb_ctrlrequest, and the IRQ pipe and handler.
+ * ss->dev_semaphore should already be locked.
  * 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
  * the endpoint for the interrupt.
  * Returns non-zero on failure, zero on success
  */ 
-static int usb_stor_allocate_irq(struct us_data *ss)
+static int usb_stor_allocate_urbs(struct us_data *ss)
 {
 	unsigned int pipe;
 	int maxp;
 	int result;
 
-	US_DEBUGP("Allocating IRQ for CBI transport\n");
-
-	/* lock access to the data structure */
-	down(&(ss->irq_urb_sem));
-
-	/* allocate the URB */
-	ss->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!ss->irq_urb) {
-		up(&(ss->irq_urb_sem));
-		US_DEBUGP("couldn't allocate interrupt URB");
+	/* allocate the URB we're going to use */
+	US_DEBUGP("Allocating URB\n");
+	ss->current_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ss->current_urb) {
+		US_DEBUGP("allocation failed\n");
 		return 1;
 	}
 
-	/* calculate the pipe and max packet size */
-	pipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int->bEndpointAddress & 
-			      USB_ENDPOINT_NUMBER_MASK);
-	maxp = usb_maxpacket(ss->pusb_dev, pipe, usb_pipeout(pipe));
-	if (maxp > sizeof(ss->irqbuf))
-		maxp = sizeof(ss->irqbuf);
-
-	/* fill in the URB with our data */
-	FILL_INT_URB(ss->irq_urb, ss->pusb_dev, pipe, ss->irqbuf, maxp, 
-		     usb_stor_CBI_irq, ss, ss->ep_int->bInterval); 
-
-	/* submit the URB for processing */
-	result = usb_submit_urb(ss->irq_urb, GFP_KERNEL);
-	US_DEBUGP("usb_submit_urb() returns %d\n", result);
-	if (result) {
-		usb_free_urb(ss->irq_urb);
-		up(&(ss->irq_urb_sem));
+	/* allocate the usb_ctrlrequest for control packets */
+	US_DEBUGP("Allocating usb_ctrlrequest\n");
+	ss->dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
+	if (!ss->dr) {
+		US_DEBUGP("allocation failed\n");
 		return 2;
 	}
 
-	/* unlock the data structure and return success */
+	/* allocate the IRQ URB, if it is needed */
+	if (ss->protocol == US_PR_CBI) {
+		US_DEBUGP("Allocating IRQ for CBI transport\n");
+
+		/* lock access to the data structure */
+		down(&(ss->irq_urb_sem));
+
+		/* allocate the URB */
+		ss->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!ss->irq_urb) {
+			up(&(ss->irq_urb_sem));
+			US_DEBUGP("couldn't allocate interrupt URB");
+			return 3;
+		}
+
+		/* calculate the pipe and max packet size */
+		pipe = usb_rcvintpipe(ss->pusb_dev,
+		    ss->ep_int->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+		maxp = usb_maxpacket(ss->pusb_dev, pipe, usb_pipeout(pipe));
+		if (maxp > sizeof(ss->irqbuf))
+			maxp = sizeof(ss->irqbuf);
+
+		/* fill in the URB with our data */
+		FILL_INT_URB(ss->irq_urb, ss->pusb_dev, pipe, ss->irqbuf,
+			maxp, usb_stor_CBI_irq, ss, ss->ep_int->bInterval); 
+
+		/* submit the URB for processing */
+		result = usb_submit_urb(ss->irq_urb, GFP_KERNEL);
+		US_DEBUGP("usb_submit_urb() returns %d\n", result);
+		if (result) {
+			up(&(ss->irq_urb_sem));
+			return 4;
+		}
+
+		/* unlock the data structure */
+		up(&(ss->irq_urb_sem));
+
+	} /* ss->protocol == US_PR_CBI */
+
+	return 0;	/* success */
+}
+
+/* Deallocate the URB, the usb_ctrlrequest, and the IRQ pipe.
+ * ss->dev_semaphore must already be locked.
+ */
+static void usb_stor_deallocate_urbs(struct us_data *ss)
+{
+	int result;
+
+	/* release the IRQ, if we have one */
+	down(&(ss->irq_urb_sem));
+	if (ss->irq_urb) {
+		US_DEBUGP("-- releasing irq URB\n");
+		result = usb_unlink_urb(ss->irq_urb);
+		US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
+		usb_free_urb(ss->irq_urb);
+		ss->irq_urb = NULL;
+	}
 	up(&(ss->irq_urb_sem));
-	return 0;
+
+	/* free the usb_ctrlrequest buffer */
+	if (ss->dr) {
+		kfree(ss->dr);
+		ss->dr = NULL;
+	}
+
+	/* free up the main URB for this device */
+	if (ss->current_urb) {
+		US_DEBUGP("-- releasing main URB\n");
+		result = usb_unlink_urb(ss->current_urb);
+		US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
+		usb_free_urb(ss->current_urb);
+		ss->current_urb = NULL;
+	}
+
+	/* mark the device as gone */
+	clear_bit(DEV_ATTACHED, &ss->bitflags);
+	usb_put_dev(ss->pusb_dev);
+	ss->pusb_dev = NULL;
 }
 
 /* Probe to see if a new device is actually a SCSI device */
@@ -712,13 +772,8 @@
 			USB_ENDPOINT_NUMBER_MASK;
 		ss->ep_int = ep_int;
 
-		/* allocate an IRQ callback if one is needed */
-		if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss))
-			goto BadDevice;
-
-		/* allocate the URB we're going to use */
-		ss->current_urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!ss->current_urb)
+		/* allocate the URB, the usb_ctrlrequest, and the IRQ URB */
+		if (usb_stor_allocate_urbs(ss))
 			goto BadDevice;
 
                 /* Re-Initialize the device if it needs it */
@@ -741,11 +796,6 @@
 		memset(ss, 0, sizeof(struct us_data));
 		new_device = 1;
 
-		/* allocate the URB we're going to use */
-		ss->current_urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!ss->current_urb)
-			goto BadDevice;
-
 		/* Initialize the mutexes only when the struct is new */
 		init_completion(&(ss->notify));
 		init_MUTEX_LOCKED(&(ss->ip_waitq));
@@ -943,8 +993,8 @@
 		}
 		US_DEBUGP("Protocol: %s\n", ss->protocol_name);
 
-		/* allocate an IRQ callback if one is needed */
-		if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss))
+		/* allocate the URB, the usb_ctrlrequest, and the IRQ URB */
+		if (usb_stor_allocate_urbs(ss))
 			goto BadDevice;
 
 		/*
@@ -1020,26 +1070,11 @@
 	/* we come here if there are any problems */
 	BadDevice:
 	US_DEBUGP("storage_probe() failed\n");
-	down(&ss->irq_urb_sem);
-	if (ss->irq_urb) {
-		usb_unlink_urb(ss->irq_urb);
-		usb_free_urb(ss->irq_urb);
-		ss->irq_urb = NULL;
-	}
-	up(&ss->irq_urb_sem);
-	if (ss->current_urb) {
-		usb_unlink_urb(ss->current_urb);
-		usb_free_urb(ss->current_urb);
-		ss->current_urb = NULL;
-	}
-
-	clear_bit(DEV_ATTACHED, &ss->bitflags);
-	ss->pusb_dev = NULL;
+	usb_stor_deallocate_urbs(ss);
 	if (new_device)
 		kfree(ss);
 	else
 		up(&ss->dev_semaphore);
-	usb_put_dev(dev);
 	return NULL;
 }
 
@@ -1047,7 +1082,6 @@
 static void storage_disconnect(struct usb_device *dev, void *ptr)
 {
 	struct us_data *ss = ptr;
-	int result;
 
 	US_DEBUGP("storage_disconnect() called\n");
 
@@ -1057,33 +1091,8 @@
 		return;
 	}
 
-	/* lock access to the device data structure */
 	down(&(ss->dev_semaphore));
-
-	/* release the IRQ, if we have one */
-	down(&(ss->irq_urb_sem));
-	if (ss->irq_urb) {
-		US_DEBUGP("-- releasing irq URB\n");
-		result = usb_unlink_urb(ss->irq_urb);
-		US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
-		usb_free_urb(ss->irq_urb);
-		ss->irq_urb = NULL;
-	}
-	up(&(ss->irq_urb_sem));
-
-	/* free up the main URB for this device */
-	US_DEBUGP("-- releasing main URB\n");
-	result = usb_unlink_urb(ss->current_urb);
-	US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
-	usb_free_urb(ss->current_urb);
-	ss->current_urb = NULL;
-
-	/* mark the device as gone */
-	usb_put_dev(ss->pusb_dev);
-	ss->pusb_dev = NULL;
-	clear_bit(DEV_ATTACHED, &ss->bitflags);
-
-	/* unlock access to the device data structure */
+	usb_stor_deallocate_urbs(ss);
 	up(&(ss->dev_semaphore));
 }
 
diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
--- a/drivers/usb/storage/usb.h	Fri Jul  5 14:51:18 2002
+++ b/drivers/usb/storage/usb.h	Fri Jul  5 14:51:18 2002
@@ -185,6 +185,7 @@
 	/* control and bulk communications data */
 	struct semaphore	current_urb_sem; /* to protect irq_urb	 */
 	struct urb		*current_urb;	 /* non-int USB requests */
+	struct usb_ctrlrequest	*dr;		 /* control requests	 */
 
 	/* the semaphore for sleeping the control thread */
 	struct semaphore	sema;		 /* to sleep thread on   */
