From akpm@osdl.org Wed Jul 27 01:14:07 2005 Message-Id: <200507270809.j6R89TUG009564@shell0.pdx.osdl.net> Subject: USB storage: rearrange stuff From: Alan Stern To: greg@kroah.com Date: Wed, 27 Jul 2005 01:08:32 -0700 This is the first of two patches for usb-storage. It really is a reorganization in preparation for the next patch, although it does make a functional change to a rather unlikely error pathway. Signed-off-by: Alan Stern Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/usb.c | 62 +++++++++++++++++++++++++--------------------- 1 files changed, 35 insertions(+), 27 deletions(-) --- gregkh-2.6.orig/drivers/usb/storage/usb.c 2005-07-13 09:45:06.000000000 -0700 +++ gregkh-2.6/drivers/usb/storage/usb.c 2005-07-27 22:34:18.000000000 -0700 @@ -786,6 +786,7 @@ * any more commands. */ US_DEBUGP("-- sending exit command to thread\n"); + set_bit(US_FLIDX_DISCONNECTING, &us->flags); up(&us->sema); /* Call the destructor routine, if it exists */ @@ -816,6 +817,36 @@ usb_set_intfdata(us->pusb_intf, NULL); } +/* First stage of disconnect processing: stop all commands and remove + * the host */ +static void quiesce_and_remove_host(struct us_data *us) +{ + /* Prevent new USB transfers, stop the current command, and + * interrupt a SCSI-scan or device-reset delay */ + set_bit(US_FLIDX_DISCONNECTING, &us->flags); + usb_stor_stop_transport(us); + wake_up(&us->delay_wait); + + /* It doesn't matter if the SCSI-scanning thread is still running. + * The thread will exit when it sees the DISCONNECTING flag. */ + + /* Wait for the current command to finish, then remove the host */ + down(&us->dev_semaphore); + up(&us->dev_semaphore); + scsi_remove_host(us_to_host(us)); +} + +/* Second stage of disconnect processing: deallocate all resources */ +static void release_everything(struct us_data *us) +{ + usb_stor_release_resources(us); + dissociate_dev(us); + + /* Drop our reference to the host; the SCSI core will free it + * (and "us" along with it) when the refcount becomes 0. */ + scsi_host_put(us_to_host(us)); +} + /* Thread to carry out delayed SCSI-device scanning */ static int usb_stor_scan_thread(void * __us) { @@ -956,7 +987,7 @@ if (result < 0) { printk(KERN_WARNING USB_STORAGE "Unable to start the device-scanning thread\n"); - scsi_remove_host(host); + quiesce_and_remove_host(us); goto BadDevice; } atomic_inc(&total_threads); @@ -969,10 +1000,7 @@ /* We come here if there are any problems */ BadDevice: US_DEBUGP("storage_probe() failed\n"); - set_bit(US_FLIDX_DISCONNECTING, &us->flags); - usb_stor_release_resources(us); - dissociate_dev(us); - scsi_host_put(host); + release_everything(us); return result; } @@ -982,28 +1010,8 @@ struct us_data *us = usb_get_intfdata(intf); US_DEBUGP("storage_disconnect() called\n"); - - /* Prevent new USB transfers, stop the current command, and - * interrupt a SCSI-scan or device-reset delay */ - set_bit(US_FLIDX_DISCONNECTING, &us->flags); - usb_stor_stop_transport(us); - wake_up(&us->delay_wait); - - /* It doesn't matter if the SCSI-scanning thread is still running. - * The thread will exit when it sees the DISCONNECTING flag. */ - - /* Wait for the current command to finish, then remove the host */ - down(&us->dev_semaphore); - up(&us->dev_semaphore); - scsi_remove_host(us_to_host(us)); - - /* Wait for everything to become idle and release all our resources */ - usb_stor_release_resources(us); - dissociate_dev(us); - - /* Drop our reference to the host; the SCSI core will free it - * (and "us" along with it) when the refcount becomes 0. */ - scsi_host_put(us_to_host(us)); + quiesce_and_remove_host(us); + release_everything(us); } /***********************************************************************