aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2010-06-17 10:36:49 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-28 10:07:49 -0400
commitdb5bd1e0b505c54ff492172ce4abc245cf6cd639 (patch)
treeb0b4c42c45b52ce9f1f4727a144475071a3f0ac3
parentdf64d3caab8db6ae17dacd229a03d7689a10c432 (diff)
[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>
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/scsi_pm.c96
-rw-r--r--drivers/scsi/scsi_priv.h7
-rw-r--r--drivers/scsi/scsi_sysfs.c48
4 files changed, 105 insertions, 47 deletions
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 1c7ac49be649..2a3fca2eca6a 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -163,6 +163,7 @@ scsi_mod-$(CONFIG_SCSI_NETLINK) += scsi_netlink.o
163scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o 163scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o
164scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o 164scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o
165scsi_mod-y += scsi_trace.o 165scsi_mod-y += scsi_trace.o
166scsi_mod-$(CONFIG_PM_OPS) += scsi_pm.o
166 167
167scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o 168scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o
168 169
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
new file mode 100644
index 000000000000..cd83758ce0a2
--- /dev/null
+++ b/drivers/scsi/scsi_pm.c
@@ -0,0 +1,96 @@
1/*
2 * scsi_pm.c Copyright (C) 2010 Alan Stern
3 *
4 * SCSI dynamic Power Management
5 * Initial version: Alan Stern <stern@rowland.harvard.edu>
6 */
7
8#include <linux/pm_runtime.h>
9
10#include <scsi/scsi.h>
11#include <scsi/scsi_device.h>
12#include <scsi/scsi_driver.h>
13#include <scsi/scsi_host.h>
14
15#include "scsi_priv.h"
16
17static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg)
18{
19 struct device_driver *drv;
20 int err;
21
22 err = scsi_device_quiesce(to_scsi_device(dev));
23 if (err == 0) {
24 drv = dev->driver;
25 if (drv && drv->suspend)
26 err = drv->suspend(dev, msg);
27 }
28 dev_dbg(dev, "scsi suspend: %d\n", err);
29 return err;
30}
31
32static int scsi_dev_type_resume(struct device *dev)
33{
34 struct device_driver *drv;
35 int err = 0;
36
37 drv = dev->driver;
38 if (drv && drv->resume)
39 err = drv->resume(dev);
40 scsi_device_resume(to_scsi_device(dev));
41 dev_dbg(dev, "scsi resume: %d\n", err);
42 return err;
43}
44
45#ifdef CONFIG_PM_SLEEP
46
47static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg)
48{
49 int err = 0;
50
51 if (scsi_is_sdev_device(dev))
52 err = scsi_dev_type_suspend(dev, msg);
53 return err;
54}
55
56static int scsi_bus_resume_common(struct device *dev)
57{
58 int err = 0;
59
60 if (scsi_is_sdev_device(dev))
61 err = scsi_dev_type_resume(dev);
62 return err;
63}
64
65static int scsi_bus_suspend(struct device *dev)
66{
67 return scsi_bus_suspend_common(dev, PMSG_SUSPEND);
68}
69
70static int scsi_bus_freeze(struct device *dev)
71{
72 return scsi_bus_suspend_common(dev, PMSG_FREEZE);
73}
74
75static int scsi_bus_poweroff(struct device *dev)
76{
77 return scsi_bus_suspend_common(dev, PMSG_HIBERNATE);
78}
79
80#else /* CONFIG_PM_SLEEP */
81
82#define scsi_bus_resume_common NULL
83#define scsi_bus_suspend NULL
84#define scsi_bus_freeze NULL
85#define scsi_bus_poweroff NULL
86
87#endif /* CONFIG_PM_SLEEP */
88
89const struct dev_pm_ops scsi_bus_pm_ops = {
90 .suspend = scsi_bus_suspend,
91 .resume = scsi_bus_resume_common,
92 .freeze = scsi_bus_freeze,
93 .thaw = scsi_bus_resume_common,
94 .poweroff = scsi_bus_poweroff,
95 .restore = scsi_bus_resume_common,
96};
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 1fbf7c78bba0..dddacc732550 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -144,6 +144,13 @@ static inline void scsi_netlink_init(void) {}
144static inline void scsi_netlink_exit(void) {} 144static inline void scsi_netlink_exit(void) {}
145#endif 145#endif
146 146
147/* scsi_pm.c */
148#ifdef CONFIG_PM_OPS
149extern const struct dev_pm_ops scsi_bus_pm_ops;
150#else
151#define scsi_bus_pm_ops (*NULL)
152#endif
153
147/* 154/*
148 * internal scsi timeout functions: for use by mid-layer and transport 155 * internal scsi timeout functions: for use by mid-layer and transport
149 * classes. 156 * classes.
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index c23ab978c3ba..5f85f8e831f3 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -376,57 +376,11 @@ static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
376 return 0; 376 return 0;
377} 377}
378 378
379static int scsi_bus_suspend(struct device * dev, pm_message_t state)
380{
381 struct device_driver *drv;
382 struct scsi_device *sdev;
383 int err;
384
385 if (dev->type != &scsi_dev_type)
386 return 0;
387
388 drv = dev->driver;
389 sdev = to_scsi_device(dev);
390
391 err = scsi_device_quiesce(sdev);
392 if (err)
393 return err;
394
395 if (drv && drv->suspend) {
396 err = drv->suspend(dev, state);
397 if (err)
398 return err;
399 }
400
401 return 0;
402}
403
404static int scsi_bus_resume(struct device * dev)
405{
406 struct device_driver *drv;
407 struct scsi_device *sdev;
408 int err = 0;
409
410 if (dev->type != &scsi_dev_type)
411 return 0;
412
413 drv = dev->driver;
414 sdev = to_scsi_device(dev);
415
416 if (drv && drv->resume)
417 err = drv->resume(dev);
418
419 scsi_device_resume(sdev);
420
421 return err;
422}
423
424struct bus_type scsi_bus_type = { 379struct bus_type scsi_bus_type = {
425 .name = "scsi", 380 .name = "scsi",
426 .match = scsi_bus_match, 381 .match = scsi_bus_match,
427 .uevent = scsi_bus_uevent, 382 .uevent = scsi_bus_uevent,
428 .suspend = scsi_bus_suspend, 383 .pm = &scsi_bus_pm_ops,
429 .resume = scsi_bus_resume,
430}; 384};
431EXPORT_SYMBOL_GPL(scsi_bus_type); 385EXPORT_SYMBOL_GPL(scsi_bus_type);
432 386