diff options
Diffstat (limited to 'drivers/usb/storage')
-rw-r--r-- | drivers/usb/storage/scsiglue.c | 13 | ||||
-rw-r--r-- | drivers/usb/storage/unusual_devs.h | 32 | ||||
-rw-r--r-- | drivers/usb/storage/usb.c | 60 | ||||
-rw-r--r-- | drivers/usb/storage/usb.h | 1 |
4 files changed, 49 insertions, 57 deletions
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 47e56079925..1ba19eaa197 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -285,15 +285,10 @@ static int device_reset(struct scsi_cmnd *srb) US_DEBUGP("%s called\n", __FUNCTION__); - result = usb_autopm_get_interface(us->pusb_intf); - if (result == 0) { - - /* lock the device pointers and do the reset */ - mutex_lock(&(us->dev_mutex)); - result = us->transport_reset(us); - mutex_unlock(&us->dev_mutex); - usb_autopm_put_interface(us->pusb_intf); - } + /* lock the device pointers and do the reset */ + mutex_lock(&(us->dev_mutex)); + result = us->transport_reset(us); + mutex_unlock(&us->dev_mutex); return result < 0 ? FAILED : SUCCESS; } diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index d8d008d4294..c6b78ba815e 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -342,12 +342,19 @@ UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100, US_FL_FIX_CAPACITY), /* Reported by Emil Larsson <emil@swip.net> */ -UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0100, +UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0101, "NIKON", "NIKON DSC D80", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), +/* Reported by Ortwin Glueck <odi@odi.ch> */ +UNUSUAL_DEV( 0x04b0, 0x0413, 0x0110, 0x0110, + "NIKON", + "NIKON DSC D40", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), + /* BENQ DC5330 * Reported by Manuel Fombuena <mfombuena@ya.com> and * Frank Copeland <fjc@thingy.apana.org.au> */ @@ -897,6 +904,22 @@ UNUSUAL_DEV( 0x069b, 0x3004, 0x0001, 0x0001, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Reported by Massimiliano Ghilardi <massimiliano.ghilardi@gmail.com> + * This USB MP3/AVI player device fails and disconnects if more than 128 + * sectors (64kB) are read/written in a single command, and may be present + * at least in the following products: + * "Magnex Digital Video Panel DVP 1800" + * "MP4 AIGO 4GB SLOT SD" + * "Teclast TL-C260 MP3" + * "i.Meizu PMP MP3/MP4" + * "Speed MV8 MP4 Audio Player" + */ +UNUSUAL_DEV( 0x071b, 0x3203, 0x0100, 0x0100, + "RockChip", + "ROCK MP3", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64), + /* Reported by Olivier Blondeau <zeitoun@gmail.com> */ UNUSUAL_DEV( 0x0727, 0x0306, 0x0100, 0x0100, "ATMEL", @@ -1393,6 +1416,13 @@ UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ), +/* Reported by Ricardo Barberis <ricardo@dattatec.com> */ +UNUSUAL_DEV( 0x0fce, 0xe092, 0x0000, 0x0000, + "Sony Ericsson", + "P1i", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + /* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */ UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000, "Sony Ericsson", diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 28842d208bb..59181667066 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -112,13 +112,6 @@ module_param(delay_use, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); -/* These are used to make sure the module doesn't unload before all the - * threads have exited. - */ -static atomic_t total_threads = ATOMIC_INIT(0); -static DECLARE_COMPLETION(threads_gone); - - /* * The entries in this table correspond, line for line, * with the entries of us_unusual_dev_list[]. @@ -191,14 +184,16 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message) { struct us_data *us = usb_get_intfdata(iface); - US_DEBUGP("%s\n", __FUNCTION__); - /* Wait until no command is running */ mutex_lock(&us->dev_mutex); + US_DEBUGP("%s\n", __FUNCTION__); if (us->suspend_resume_hook) (us->suspend_resume_hook)(us, US_SUSPEND); + /* When runtime PM is working, we'll set a flag to indicate + * whether we should autoresume when a SCSI request arrives. */ + mutex_unlock(&us->dev_mutex); return 0; } @@ -207,11 +202,13 @@ static int storage_resume(struct usb_interface *iface) { struct us_data *us = usb_get_intfdata(iface); - US_DEBUGP("%s\n", __FUNCTION__); + mutex_lock(&us->dev_mutex); + US_DEBUGP("%s\n", __FUNCTION__); if (us->suspend_resume_hook) (us->suspend_resume_hook)(us, US_RESUME); + mutex_unlock(&us->dev_mutex); return 0; } @@ -309,7 +306,6 @@ static int usb_stor_control_thread(void * __us) { struct us_data *us = (struct us_data *)__us; struct Scsi_Host *host = us_to_host(us); - int autopm_rc; for(;;) { US_DEBUGP("*** thread sleeping.\n"); @@ -318,9 +314,6 @@ static int usb_stor_control_thread(void * __us) US_DEBUGP("*** thread awakened.\n"); - /* Autoresume the device */ - autopm_rc = usb_autopm_get_interface(us->pusb_intf); - /* lock the device pointers */ mutex_lock(&(us->dev_mutex)); @@ -379,12 +372,6 @@ static int usb_stor_control_thread(void * __us) us->srb->result = SAM_STAT_GOOD; } - /* Did the autoresume fail? */ - else if (autopm_rc < 0) { - US_DEBUGP("Could not wake device\n"); - us->srb->result = DID_ERROR << 16; - } - /* we've got a command, let's do it! */ else { US_DEBUG(usb_stor_show_command(us->srb)); @@ -427,10 +414,6 @@ SkipForAbort: /* unlock the device pointers */ mutex_unlock(&us->dev_mutex); - - /* Start an autosuspend */ - if (autopm_rc == 0) - usb_autopm_put_interface(us->pusb_intf); } /* for (;;) */ /* Wait until we are told to stop */ @@ -879,9 +862,6 @@ static void quiesce_and_remove_host(struct us_data *us) 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. */ - /* queuecommand won't accept any new commands and the control * thread won't execute a previously-queued command. If there * is such a command pending, complete it with an error. */ @@ -891,12 +871,16 @@ static void quiesce_and_remove_host(struct us_data *us) scsi_lock(host); us->srb->scsi_done(us->srb); us->srb = NULL; + complete(&us->notify); /* in case of an abort */ scsi_unlock(host); } mutex_unlock(&us->dev_mutex); /* Now we own no commands so it's safe to remove the SCSI host */ scsi_remove_host(host); + + /* Wait for the SCSI-scanning thread to stop */ + wait_for_completion(&us->scanning_done); } /* Second stage of disconnect processing: deallocate all resources */ @@ -947,9 +931,7 @@ retry: /* Should we unbind if no devices were detected? */ } - scsi_host_put(us_to_host(us)); - usb_autopm_put_interface(us->pusb_intf); - complete_and_exit(&threads_gone, 0); + complete_and_exit(&us->scanning_done, 0); } @@ -984,6 +966,7 @@ static int storage_probe(struct usb_interface *intf, init_MUTEX_LOCKED(&(us->sema)); init_completion(&(us->notify)); init_waitqueue_head(&us->delay_wait); + init_completion(&us->scanning_done); /* Associate the us_data structure with the USB device */ result = associate_dev(us, intf); @@ -1033,12 +1016,6 @@ static int storage_probe(struct usb_interface *intf, goto BadDevice; } - /* Take a reference to the host for the scanning thread and - * count it among all the threads we have launched. Then - * start it up. */ - scsi_host_get(us_to_host(us)); - atomic_inc(&total_threads); - usb_autopm_get_interface(intf); /* dropped in the scanning thread */ wake_up_process(th); return 0; @@ -1076,7 +1053,6 @@ static struct usb_driver usb_storage_driver = { .pre_reset = storage_pre_reset, .post_reset = storage_post_reset, .id_table = storage_usb_ids, - .supports_autosuspend = 1, }; static int __init usb_stor_init(void) @@ -1104,16 +1080,6 @@ static void __exit usb_stor_exit(void) US_DEBUGP("-- calling usb_deregister()\n"); usb_deregister(&usb_storage_driver) ; - /* Don't return until all of our control and scanning threads - * have exited. Since each thread signals threads_gone as its - * last act, we have to call wait_for_completion the right number - * of times. - */ - while (atomic_read(&total_threads) > 0) { - wait_for_completion(&threads_gone); - atomic_dec(&total_threads); - } - usb_usual_clear_present(USB_US_TYPE_STOR); } diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 6445665b157..8d87503e256 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -150,6 +150,7 @@ struct us_data { struct semaphore sema; /* to sleep thread on */ struct completion notify; /* thread begin/end */ wait_queue_head_t delay_wait; /* wait during scan, reset */ + struct completion scanning_done; /* wait for scan thread */ /* subdriver information */ void *extra; /* Any extra data */ |