summaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/storage')
-rw-r--r--drivers/usb/storage/scsiglue.c13
-rw-r--r--drivers/usb/storage/unusual_devs.h32
-rw-r--r--drivers/usb/storage/usb.c60
-rw-r--r--drivers/usb/storage/usb.h1
4 files changed, 49 insertions, 57 deletions
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 47e5607..1ba19ea 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 d8d008d..c6b78ba 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 28842d2..5918166 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 6445665..8d87503 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 */
OpenPOWER on IntegriCloud