Commit 80d2fd48 authored by Aaron Lu's avatar Aaron Lu Committed by James Bottomley

[SCSI] scsi_pm: use callbacks from dev_pm_ops for scsi devices

Use of pm_message_t is deprecated and device driver is not supposed
to use that. This patch migrates the SCSI bus level pm callbacks
to call device's pm callbacks defined in its driver's dev_pm_ops.

This is achieved by finding out which device pm callback should be used
in bus callback function, and then pass that callback function pointer
as a param to the scsi_bus_{suspend,resume}_common routine, which will
further pass that callback to scsi_dev_type_{suspend,resume} after
proper handling.

The special case for freeze in scsi_bus_suspend_common is not necessary
since there is no high level SCSI driver has implemented freeze, so no
need to runtime resume the device if it is in runtime suspended state
for system freeze, just return like the system suspend/hibernate case.

Since only sd has implemented drv->suspend/drv->resume, and I'll update
sd driver to use the new callbacks in the following patch, there is no
need to fallback to call drv->suspend/drv->resume if dev_pm_ops is NULL.
Signed-off-by: default avatarAaron Lu <aaron.lu@intel.com>
Acked-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Acked-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 9c31d8e1
...@@ -16,16 +16,14 @@ ...@@ -16,16 +16,14 @@
#include "scsi_priv.h" #include "scsi_priv.h"
static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg) static int scsi_dev_type_suspend(struct device *dev, int (*cb)(struct device *))
{ {
struct device_driver *drv;
int err; int err;
err = scsi_device_quiesce(to_scsi_device(dev)); err = scsi_device_quiesce(to_scsi_device(dev));
if (err == 0) { if (err == 0) {
drv = dev->driver; if (cb) {
if (drv && drv->suspend) { err = cb(dev);
err = drv->suspend(dev, msg);
if (err) if (err)
scsi_device_resume(to_scsi_device(dev)); scsi_device_resume(to_scsi_device(dev));
} }
...@@ -34,14 +32,12 @@ static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg) ...@@ -34,14 +32,12 @@ static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg)
return err; return err;
} }
static int scsi_dev_type_resume(struct device *dev) static int scsi_dev_type_resume(struct device *dev, int (*cb)(struct device *))
{ {
struct device_driver *drv;
int err = 0; int err = 0;
drv = dev->driver; if (cb)
if (drv && drv->resume) err = cb(dev);
err = drv->resume(dev);
scsi_device_resume(to_scsi_device(dev)); scsi_device_resume(to_scsi_device(dev));
dev_dbg(dev, "scsi resume: %d\n", err); dev_dbg(dev, "scsi resume: %d\n", err);
return err; return err;
...@@ -49,35 +45,33 @@ static int scsi_dev_type_resume(struct device *dev) ...@@ -49,35 +45,33 @@ static int scsi_dev_type_resume(struct device *dev)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg) static int
scsi_bus_suspend_common(struct device *dev, int (*cb)(struct device *))
{ {
int err = 0; int err = 0;
if (scsi_is_sdev_device(dev)) { if (scsi_is_sdev_device(dev)) {
/* /*
* sd is the only high-level SCSI driver to implement runtime * All the high-level SCSI drivers that implement runtime
* PM, and sd treats runtime suspend, system suspend, and * PM treat runtime suspend, system suspend, and system
* system hibernate identically (but not system freeze). * hibernate identically.
*/ */
if (pm_runtime_suspended(dev)) { if (pm_runtime_suspended(dev))
if (msg.event == PM_EVENT_SUSPEND || return 0;
msg.event == PM_EVENT_HIBERNATE)
return 0; /* already suspended */
/* wake up device so that FREEZE will succeed */ err = scsi_dev_type_suspend(dev, cb);
pm_runtime_resume(dev);
}
err = scsi_dev_type_suspend(dev, msg);
} }
return err; return err;
} }
static int scsi_bus_resume_common(struct device *dev) static int
scsi_bus_resume_common(struct device *dev, int (*cb)(struct device *))
{ {
int err = 0; int err = 0;
if (scsi_is_sdev_device(dev)) if (scsi_is_sdev_device(dev))
err = scsi_dev_type_resume(dev); err = scsi_dev_type_resume(dev, cb);
if (err == 0) { if (err == 0) {
pm_runtime_disable(dev); pm_runtime_disable(dev);
...@@ -102,26 +96,49 @@ static int scsi_bus_prepare(struct device *dev) ...@@ -102,26 +96,49 @@ static int scsi_bus_prepare(struct device *dev)
static int scsi_bus_suspend(struct device *dev) static int scsi_bus_suspend(struct device *dev)
{ {
return scsi_bus_suspend_common(dev, PMSG_SUSPEND); const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
return scsi_bus_suspend_common(dev, pm ? pm->suspend : NULL);
}
static int scsi_bus_resume(struct device *dev)
{
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
return scsi_bus_resume_common(dev, pm ? pm->resume : NULL);
} }
static int scsi_bus_freeze(struct device *dev) static int scsi_bus_freeze(struct device *dev)
{ {
return scsi_bus_suspend_common(dev, PMSG_FREEZE); const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
return scsi_bus_suspend_common(dev, pm ? pm->freeze : NULL);
}
static int scsi_bus_thaw(struct device *dev)
{
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
return scsi_bus_resume_common(dev, pm ? pm->thaw : NULL);
} }
static int scsi_bus_poweroff(struct device *dev) static int scsi_bus_poweroff(struct device *dev)
{ {
return scsi_bus_suspend_common(dev, PMSG_HIBERNATE); const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
return scsi_bus_suspend_common(dev, pm ? pm->poweroff : NULL);
}
static int scsi_bus_restore(struct device *dev)
{
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
return scsi_bus_resume_common(dev, pm ? pm->restore : NULL);
} }
#else /* CONFIG_PM_SLEEP */ #else /* CONFIG_PM_SLEEP */
#define scsi_bus_resume_common NULL
#define scsi_bus_prepare NULL #define scsi_bus_prepare NULL
#define scsi_bus_suspend NULL #define scsi_bus_suspend NULL
#define scsi_bus_resume NULL
#define scsi_bus_freeze NULL #define scsi_bus_freeze NULL
#define scsi_bus_thaw NULL
#define scsi_bus_poweroff NULL #define scsi_bus_poweroff NULL
#define scsi_bus_restore NULL
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
...@@ -130,10 +147,12 @@ static int scsi_bus_poweroff(struct device *dev) ...@@ -130,10 +147,12 @@ static int scsi_bus_poweroff(struct device *dev)
static int scsi_runtime_suspend(struct device *dev) static int scsi_runtime_suspend(struct device *dev)
{ {
int err = 0; int err = 0;
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
dev_dbg(dev, "scsi_runtime_suspend\n"); dev_dbg(dev, "scsi_runtime_suspend\n");
if (scsi_is_sdev_device(dev)) { if (scsi_is_sdev_device(dev)) {
err = scsi_dev_type_suspend(dev, PMSG_AUTO_SUSPEND); err = scsi_dev_type_suspend(dev,
pm ? pm->runtime_suspend : NULL);
if (err == -EAGAIN) if (err == -EAGAIN)
pm_schedule_suspend(dev, jiffies_to_msecs( pm_schedule_suspend(dev, jiffies_to_msecs(
round_jiffies_up_relative(HZ/10))); round_jiffies_up_relative(HZ/10)));
...@@ -147,10 +166,11 @@ static int scsi_runtime_suspend(struct device *dev) ...@@ -147,10 +166,11 @@ static int scsi_runtime_suspend(struct device *dev)
static int scsi_runtime_resume(struct device *dev) static int scsi_runtime_resume(struct device *dev)
{ {
int err = 0; int err = 0;
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
dev_dbg(dev, "scsi_runtime_resume\n"); dev_dbg(dev, "scsi_runtime_resume\n");
if (scsi_is_sdev_device(dev)) if (scsi_is_sdev_device(dev))
err = scsi_dev_type_resume(dev); err = scsi_dev_type_resume(dev, pm ? pm->runtime_resume : NULL);
/* Insert hooks here for targets, hosts, and transport classes */ /* Insert hooks here for targets, hosts, and transport classes */
...@@ -229,11 +249,11 @@ void scsi_autopm_put_host(struct Scsi_Host *shost) ...@@ -229,11 +249,11 @@ void scsi_autopm_put_host(struct Scsi_Host *shost)
const struct dev_pm_ops scsi_bus_pm_ops = { const struct dev_pm_ops scsi_bus_pm_ops = {
.prepare = scsi_bus_prepare, .prepare = scsi_bus_prepare,
.suspend = scsi_bus_suspend, .suspend = scsi_bus_suspend,
.resume = scsi_bus_resume_common, .resume = scsi_bus_resume,
.freeze = scsi_bus_freeze, .freeze = scsi_bus_freeze,
.thaw = scsi_bus_resume_common, .thaw = scsi_bus_thaw,
.poweroff = scsi_bus_poweroff, .poweroff = scsi_bus_poweroff,
.restore = scsi_bus_resume_common, .restore = scsi_bus_restore,
.runtime_suspend = scsi_runtime_suspend, .runtime_suspend = scsi_runtime_suspend,
.runtime_resume = scsi_runtime_resume, .runtime_resume = scsi_runtime_resume,
.runtime_idle = scsi_runtime_idle, .runtime_idle = scsi_runtime_idle,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment