Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 343735
b: refs/heads/master
c: 80d2fd4
h: refs/heads/master
i:
  343733: b6b87eb
  343731: 9ee71a8
  343727: 342cbc5
v: v3
  • Loading branch information
Aaron Lu authored and James Bottomley committed Nov 30, 2012
1 parent 38d2592 commit fbd0f1b
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 34 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9c31d8e1319e0d3f85673c7119a10700bf03f77a
refs/heads/master: 80d2fd48cca2a0de806c3130551744a04ad5b80b
86 changes: 53 additions & 33 deletions trunk/drivers/scsi/scsi_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,14 @@

#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;

err = scsi_device_quiesce(to_scsi_device(dev));
if (err == 0) {
drv = dev->driver;
if (drv && drv->suspend) {
err = drv->suspend(dev, msg);
if (cb) {
err = cb(dev);
if (err)
scsi_device_resume(to_scsi_device(dev));
}
Expand All @@ -34,50 +32,46 @@ static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg)
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;

drv = dev->driver;
if (drv && drv->resume)
err = drv->resume(dev);
if (cb)
err = cb(dev);
scsi_device_resume(to_scsi_device(dev));
dev_dbg(dev, "scsi resume: %d\n", err);
return err;
}

#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;

if (scsi_is_sdev_device(dev)) {
/*
* sd is the only high-level SCSI driver to implement runtime
* PM, and sd treats runtime suspend, system suspend, and
* system hibernate identically (but not system freeze).
* All the high-level SCSI drivers that implement runtime
* PM treat runtime suspend, system suspend, and system
* hibernate identically.
*/
if (pm_runtime_suspended(dev)) {
if (msg.event == PM_EVENT_SUSPEND ||
msg.event == PM_EVENT_HIBERNATE)
return 0; /* already suspended */
if (pm_runtime_suspended(dev))
return 0;

/* wake up device so that FREEZE will succeed */
pm_runtime_resume(dev);
}
err = scsi_dev_type_suspend(dev, msg);
err = scsi_dev_type_suspend(dev, cb);
}

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;

if (scsi_is_sdev_device(dev))
err = scsi_dev_type_resume(dev);
err = scsi_dev_type_resume(dev, cb);

if (err == 0) {
pm_runtime_disable(dev);
Expand All @@ -102,26 +96,49 @@ static int scsi_bus_prepare(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)
{
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)
{
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 */

#define scsi_bus_resume_common NULL
#define scsi_bus_prepare NULL
#define scsi_bus_suspend NULL
#define scsi_bus_resume NULL
#define scsi_bus_freeze NULL
#define scsi_bus_thaw NULL
#define scsi_bus_poweroff NULL
#define scsi_bus_restore NULL

#endif /* CONFIG_PM_SLEEP */

Expand All @@ -130,10 +147,12 @@ static int scsi_bus_poweroff(struct device *dev)
static int scsi_runtime_suspend(struct device *dev)
{
int err = 0;
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;

dev_dbg(dev, "scsi_runtime_suspend\n");
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)
pm_schedule_suspend(dev, jiffies_to_msecs(
round_jiffies_up_relative(HZ/10)));
Expand All @@ -147,10 +166,11 @@ static int scsi_runtime_suspend(struct device *dev)
static int scsi_runtime_resume(struct device *dev)
{
int err = 0;
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;

dev_dbg(dev, "scsi_runtime_resume\n");
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 */

Expand Down Expand Up @@ -229,11 +249,11 @@ void scsi_autopm_put_host(struct Scsi_Host *shost)
const struct dev_pm_ops scsi_bus_pm_ops = {
.prepare = scsi_bus_prepare,
.suspend = scsi_bus_suspend,
.resume = scsi_bus_resume_common,
.resume = scsi_bus_resume,
.freeze = scsi_bus_freeze,
.thaw = scsi_bus_resume_common,
.thaw = scsi_bus_thaw,
.poweroff = scsi_bus_poweroff,
.restore = scsi_bus_resume_common,
.restore = scsi_bus_restore,
.runtime_suspend = scsi_runtime_suspend,
.runtime_resume = scsi_runtime_resume,
.runtime_idle = scsi_runtime_idle,
Expand Down

0 comments on commit fbd0f1b

Please sign in to comment.