|
@@ -788,15 +788,19 @@ static void quiesce_and_remove_host(struct us_data *us)
|
|
|
struct Scsi_Host *host = us_to_host(us);
|
|
|
|
|
|
/* If the device is really gone, cut short reset delays */
|
|
|
- if (us->pusb_dev->state == USB_STATE_NOTATTACHED)
|
|
|
+ if (us->pusb_dev->state == USB_STATE_NOTATTACHED) {
|
|
|
set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
|
|
|
+ wake_up(&us->delay_wait);
|
|
|
+ }
|
|
|
|
|
|
- /* Prevent SCSI-scanning (if it hasn't started yet)
|
|
|
- * and wait for the SCSI-scanning thread to stop.
|
|
|
+ /* Prevent SCSI scanning (if it hasn't started yet)
|
|
|
+ * or wait for the SCSI-scanning routine to stop.
|
|
|
*/
|
|
|
- set_bit(US_FLIDX_DONT_SCAN, &us->dflags);
|
|
|
- wake_up(&us->delay_wait);
|
|
|
- wait_for_completion(&us->scanning_done);
|
|
|
+ cancel_delayed_work_sync(&us->scan_dwork);
|
|
|
+
|
|
|
+ /* Balance autopm calls if scanning was cancelled */
|
|
|
+ if (test_bit(US_FLIDX_SCAN_PENDING, &us->dflags))
|
|
|
+ usb_autopm_put_interface_no_suspend(us->pusb_intf);
|
|
|
|
|
|
/* Removing the host will perform an orderly shutdown: caches
|
|
|
* synchronized, disks spun down, etc.
|
|
@@ -823,53 +827,28 @@ static void release_everything(struct us_data *us)
|
|
|
scsi_host_put(us_to_host(us));
|
|
|
}
|
|
|
|
|
|
-/* Thread to carry out delayed SCSI-device scanning */
|
|
|
-static int usb_stor_scan_thread(void * __us)
|
|
|
+/* Delayed-work routine to carry out SCSI-device scanning */
|
|
|
+static void usb_stor_scan_dwork(struct work_struct *work)
|
|
|
{
|
|
|
- struct us_data *us = (struct us_data *)__us;
|
|
|
+ struct us_data *us = container_of(work, struct us_data,
|
|
|
+ scan_dwork.work);
|
|
|
struct device *dev = &us->pusb_intf->dev;
|
|
|
|
|
|
- dev_dbg(dev, "device found\n");
|
|
|
-
|
|
|
- set_freezable();
|
|
|
+ dev_dbg(dev, "starting scan\n");
|
|
|
|
|
|
- /*
|
|
|
- * Wait for the timeout to expire or for a disconnect
|
|
|
- *
|
|
|
- * We can't freeze in this thread or we risk causing khubd to
|
|
|
- * fail to freeze, but we can't be non-freezable either. Nor can
|
|
|
- * khubd freeze while waiting for scanning to complete as it may
|
|
|
- * hold the device lock, causing a hang when suspending devices.
|
|
|
- * So instead of using wait_event_freezable(), explicitly test
|
|
|
- * for (DONT_SCAN || freezing) in interruptible wait and proceed
|
|
|
- * if any of DONT_SCAN, freezing or timeout has happened.
|
|
|
- */
|
|
|
- if (delay_use > 0) {
|
|
|
- dev_dbg(dev, "waiting for device to settle "
|
|
|
- "before scanning\n");
|
|
|
- wait_event_interruptible_timeout(us->delay_wait,
|
|
|
- test_bit(US_FLIDX_DONT_SCAN, &us->dflags) ||
|
|
|
- freezing(current), delay_use * HZ);
|
|
|
+ /* For bulk-only devices, determine the max LUN value */
|
|
|
+ if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) {
|
|
|
+ mutex_lock(&us->dev_mutex);
|
|
|
+ us->max_lun = usb_stor_Bulk_max_lun(us);
|
|
|
+ mutex_unlock(&us->dev_mutex);
|
|
|
}
|
|
|
+ scsi_scan_host(us_to_host(us));
|
|
|
+ dev_dbg(dev, "scan complete\n");
|
|
|
|
|
|
- /* If the device is still connected, perform the scanning */
|
|
|
- if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) {
|
|
|
-
|
|
|
- /* For bulk-only devices, determine the max LUN value */
|
|
|
- if (us->protocol == USB_PR_BULK &&
|
|
|
- !(us->fflags & US_FL_SINGLE_LUN)) {
|
|
|
- mutex_lock(&us->dev_mutex);
|
|
|
- us->max_lun = usb_stor_Bulk_max_lun(us);
|
|
|
- mutex_unlock(&us->dev_mutex);
|
|
|
- }
|
|
|
- scsi_scan_host(us_to_host(us));
|
|
|
- dev_dbg(dev, "scan complete\n");
|
|
|
-
|
|
|
- /* Should we unbind if no devices were detected? */
|
|
|
- }
|
|
|
+ /* Should we unbind if no devices were detected? */
|
|
|
|
|
|
usb_autopm_put_interface(us->pusb_intf);
|
|
|
- complete_and_exit(&us->scanning_done, 0);
|
|
|
+ clear_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
|
|
|
}
|
|
|
|
|
|
static unsigned int usb_stor_sg_tablesize(struct usb_interface *intf)
|
|
@@ -916,7 +895,7 @@ int usb_stor_probe1(struct us_data **pus,
|
|
|
init_completion(&us->cmnd_ready);
|
|
|
init_completion(&(us->notify));
|
|
|
init_waitqueue_head(&us->delay_wait);
|
|
|
- init_completion(&us->scanning_done);
|
|
|
+ INIT_DELAYED_WORK(&us->scan_dwork, usb_stor_scan_dwork);
|
|
|
|
|
|
/* Associate the us_data structure with the USB device */
|
|
|
result = associate_dev(us, intf);
|
|
@@ -947,7 +926,6 @@ EXPORT_SYMBOL_GPL(usb_stor_probe1);
|
|
|
/* Second part of general USB mass-storage probing */
|
|
|
int usb_stor_probe2(struct us_data *us)
|
|
|
{
|
|
|
- struct task_struct *th;
|
|
|
int result;
|
|
|
struct device *dev = &us->pusb_intf->dev;
|
|
|
|
|
@@ -988,20 +966,14 @@ int usb_stor_probe2(struct us_data *us)
|
|
|
goto BadDevice;
|
|
|
}
|
|
|
|
|
|
- /* Start up the thread for delayed SCSI-device scanning */
|
|
|
- th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan");
|
|
|
- if (IS_ERR(th)) {
|
|
|
- dev_warn(dev,
|
|
|
- "Unable to start the device-scanning thread\n");
|
|
|
- complete(&us->scanning_done);
|
|
|
- quiesce_and_remove_host(us);
|
|
|
- result = PTR_ERR(th);
|
|
|
- goto BadDevice;
|
|
|
- }
|
|
|
-
|
|
|
+ /* Submit the delayed_work for SCSI-device scanning */
|
|
|
usb_autopm_get_interface_no_resume(us->pusb_intf);
|
|
|
- wake_up_process(th);
|
|
|
+ set_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
|
|
|
|
|
|
+ if (delay_use > 0)
|
|
|
+ dev_dbg(dev, "waiting for device to settle before scanning\n");
|
|
|
+ queue_delayed_work(system_freezable_wq, &us->scan_dwork,
|
|
|
+ delay_use * HZ);
|
|
|
return 0;
|
|
|
|
|
|
/* We come here if there are any problems */
|