diff options
Diffstat (limited to 'drivers/scsi/scsi_pm.c')
-rw-r--r-- | drivers/scsi/scsi_pm.c | 105 |
1 files changed, 12 insertions, 93 deletions
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index 3717eea37ecb..b5a858c29488 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c @@ -56,9 +56,6 @@ 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); @@ -69,108 +66,30 @@ static int scsi_dev_type_suspend(struct device *dev, return err; } -static int scsi_dev_type_resume(struct device *dev, - int (*cb)(struct device *, const struct dev_pm_ops *)) -{ - const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - int err = 0; - - err = cb(dev, pm); - scsi_device_resume(to_scsi_device(dev)); - dev_dbg(dev, "scsi resume: %d\n", err); - - if (err == 0) { - pm_runtime_disable(dev); - err = pm_runtime_set_active(dev); - pm_runtime_enable(dev); - - /* - * Forcibly set runtime PM status of request queue to "active" - * to make sure we can again get requests from the queue - * (see also blk_pm_peek_request()). - * - * The resume hook will correct runtime PM status of the disk. - */ - if (!err && scsi_is_sdev_device(dev)) { - struct scsi_device *sdev = to_scsi_device(dev); - - blk_set_runtime_active(sdev->request_queue); - } - } - - return err; -} - static int scsi_bus_suspend_common(struct device *dev, int (*cb)(struct device *, const struct dev_pm_ops *)) { - int err = 0; - - if (scsi_is_sdev_device(dev)) { - /* - * All the high-level SCSI drivers that implement runtime - * PM treat runtime suspend, system suspend, and system - * hibernate nearly identically. In all cases the requirements - * for runtime suspension are stricter. - */ - if (pm_runtime_suspended(dev)) - return 0; - - err = scsi_dev_type_suspend(dev, cb); - } - - return err; -} - -static void async_sdev_resume(void *dev, async_cookie_t cookie) -{ - scsi_dev_type_resume(dev, do_scsi_resume); -} - -static void async_sdev_thaw(void *dev, async_cookie_t cookie) -{ - scsi_dev_type_resume(dev, do_scsi_thaw); -} + if (!scsi_is_sdev_device(dev)) + return 0; -static void async_sdev_restore(void *dev, async_cookie_t cookie) -{ - scsi_dev_type_resume(dev, do_scsi_restore); + return scsi_dev_type_suspend(dev, cb); } static int scsi_bus_resume_common(struct device *dev, int (*cb)(struct device *, const struct dev_pm_ops *)) { - async_func_t fn; + const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; + int err; if (!scsi_is_sdev_device(dev)) - fn = NULL; - else if (cb == do_scsi_resume) - fn = async_sdev_resume; - else if (cb == do_scsi_thaw) - fn = async_sdev_thaw; - else if (cb == do_scsi_restore) - fn = async_sdev_restore; - else - fn = NULL; - - 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); - } - return 0; + return 0; + + err = cb(dev, pm); + scsi_device_resume(to_scsi_device(dev)); + dev_dbg(dev, "scsi resume: %d\n", err); + + return err; } static int scsi_bus_prepare(struct device *dev) |