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 */
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 */
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));
}
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;
/*
/* 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;
}
static void storage_disconnect(struct usb_device *dev, void *ptr)
{
struct us_data *ss = ptr;
- int result;
US_DEBUGP("storage_disconnect() called\n");
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));
}