[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: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
Родитель
df64d3caab
Коммит
db5bd1e0b5
|
@ -163,6 +163,7 @@ scsi_mod-$(CONFIG_SCSI_NETLINK) += scsi_netlink.o
|
|||
scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o
|
||||
scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.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
|
||||
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* 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) {}
|
|||
static inline void scsi_netlink_exit(void) {}
|
||||
#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
|
||||
* classes.
|
||||
|
|
|
@ -376,57 +376,11 @@ static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
|
|||
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 = {
|
||||
.name = "scsi",
|
||||
.match = scsi_bus_match,
|
||||
.uevent = scsi_bus_uevent,
|
||||
.suspend = scsi_bus_suspend,
|
||||
.resume = scsi_bus_resume,
|
||||
.pm = &scsi_bus_pm_ops,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(scsi_bus_type);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче