Commit db5bd1e0 authored by Alan Stern's avatar Alan Stern Committed by James Bottomley

[SCSI] convert to the new PM framework

This patch (as1397b) converts the SCSI midlayer to use the new PM
callbacks (struct dev_pm_ops).  A new source file, scsi_pm.c, is
created to hold the new callback routines, and the existing
suspend/resume code is moved there.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent df64d3ca
...@@ -163,6 +163,7 @@ scsi_mod-$(CONFIG_SCSI_NETLINK) += scsi_netlink.o ...@@ -163,6 +163,7 @@ scsi_mod-$(CONFIG_SCSI_NETLINK) += scsi_netlink.o
scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o
scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o
scsi_mod-y += scsi_trace.o scsi_mod-y += scsi_trace.o
scsi_mod-$(CONFIG_PM_OPS) += scsi_pm.o
scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o
......
/*
* scsi_pm.c Copyright (C) 2010 Alan Stern
*
* SCSI dynamic Power Management
* Initial version: Alan Stern <stern@rowland.harvard.edu>
*/
#include <linux/pm_runtime.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_driver.h>
#include <scsi/scsi_host.h>
#include "scsi_priv.h"
static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg)
{
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);
}
dev_dbg(dev, "scsi suspend: %d\n", err);
return err;
}
static int scsi_dev_type_resume(struct device *dev)
{
struct device_driver *drv;
int err = 0;
drv = dev->driver;
if (drv && drv->resume)
err = drv->resume(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)
{
int err = 0;
if (scsi_is_sdev_device(dev))
err = scsi_dev_type_suspend(dev, msg);
return err;
}
static int scsi_bus_resume_common(struct device *dev)
{
int err = 0;
if (scsi_is_sdev_device(dev))
err = scsi_dev_type_resume(dev);
return err;
}
static int scsi_bus_suspend(struct device *dev)
{
return scsi_bus_suspend_common(dev, PMSG_SUSPEND);
}
static int scsi_bus_freeze(struct device *dev)
{
return scsi_bus_suspend_common(dev, PMSG_FREEZE);
}
static int scsi_bus_poweroff(struct device *dev)
{
return scsi_bus_suspend_common(dev, PMSG_HIBERNATE);
}
#else /* CONFIG_PM_SLEEP */
#define scsi_bus_resume_common NULL
#define scsi_bus_suspend NULL
#define scsi_bus_freeze NULL
#define scsi_bus_poweroff NULL
#endif /* CONFIG_PM_SLEEP */
const struct dev_pm_ops scsi_bus_pm_ops = {
.suspend = scsi_bus_suspend,
.resume = scsi_bus_resume_common,
.freeze = scsi_bus_freeze,
.thaw = scsi_bus_resume_common,
.poweroff = scsi_bus_poweroff,
.restore = scsi_bus_resume_common,
};
...@@ -144,6 +144,13 @@ static inline void scsi_netlink_init(void) {} ...@@ -144,6 +144,13 @@ static inline void scsi_netlink_init(void) {}
static inline void scsi_netlink_exit(void) {} static inline void scsi_netlink_exit(void) {}
#endif #endif
/* scsi_pm.c */
#ifdef CONFIG_PM_OPS
extern const struct dev_pm_ops scsi_bus_pm_ops;
#else
#define scsi_bus_pm_ops (*NULL)
#endif
/* /*
* internal scsi timeout functions: for use by mid-layer and transport * internal scsi timeout functions: for use by mid-layer and transport
* classes. * classes.
......
...@@ -376,57 +376,11 @@ static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) ...@@ -376,57 +376,11 @@ static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
return 0; return 0;
} }
static int scsi_bus_suspend(struct device * dev, pm_message_t state)
{
struct device_driver *drv;
struct scsi_device *sdev;
int err;
if (dev->type != &scsi_dev_type)
return 0;
drv = dev->driver;
sdev = to_scsi_device(dev);
err = scsi_device_quiesce(sdev);
if (err)
return err;
if (drv && drv->suspend) {
err = drv->suspend(dev, state);
if (err)
return err;
}
return 0;
}
static int scsi_bus_resume(struct device * dev)
{
struct device_driver *drv;
struct scsi_device *sdev;
int err = 0;
if (dev->type != &scsi_dev_type)
return 0;
drv = dev->driver;
sdev = to_scsi_device(dev);
if (drv && drv->resume)
err = drv->resume(dev);
scsi_device_resume(sdev);
return err;
}
struct bus_type scsi_bus_type = { struct bus_type scsi_bus_type = {
.name = "scsi", .name = "scsi",
.match = scsi_bus_match, .match = scsi_bus_match,
.uevent = scsi_bus_uevent, .uevent = scsi_bus_uevent,
.suspend = scsi_bus_suspend, .pm = &scsi_bus_pm_ops,
.resume = scsi_bus_resume,
}; };
EXPORT_SYMBOL_GPL(scsi_bus_type); EXPORT_SYMBOL_GPL(scsi_bus_type);
......
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