aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi/scsi_pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_pm.c')
-rw-r--r--drivers/scsi/scsi_pm.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index 560baaad71d5..7639df91b110 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -55,6 +55,9 @@ static int scsi_dev_type_suspend(struct device *dev,
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int err;
+ /* flush pending in-flight resume operations, suspend is synchronous */
+ async_synchronize_full_domain(&scsi_sd_pm_domain);
+
err = scsi_device_quiesce(to_scsi_device(dev));
if (err == 0) {
err = cb(dev, pm);
@@ -151,7 +154,18 @@ static int scsi_bus_resume_common(struct device *dev,
else
fn = NULL;
- if (!fn) {
+ if (fn) {
+ async_schedule_domain(fn, dev, &scsi_sd_pm_domain);
+
+ /*
+ * If a user has disabled async probing a likely reason
+ * is due to a storage enclosure that does not inject
+ * staggered spin-ups. For safety, make resume
+ * synchronous as well in that case.
+ */
+ if (strncmp(scsi_scan_type, "async", 5) != 0)
+ async_synchronize_full_domain(&scsi_sd_pm_domain);
+ } else {
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
@@ -161,7 +175,11 @@ static int scsi_bus_resume_common(struct device *dev,
static int scsi_bus_prepare(struct device *dev)
{
- if (scsi_is_host_device(dev)) {
+ if (scsi_is_sdev_device(dev)) {
+ /* sd probing uses async_schedule. Wait until it finishes. */
+ async_synchronize_full_domain(&scsi_sd_probe_domain);
+
+ } else if (scsi_is_host_device(dev)) {
/* Wait until async scanning is finished */
scsi_complete_async_scans();
}