2 * scsi_pm.c Copyright (C) 2010 Alan Stern
4 * SCSI dynamic Power Management
5 * Initial version: Alan Stern <stern@rowland.harvard.edu>
8 #include <linux/pm_runtime.h>
9 #include <linux/export.h>
10 #include <linux/async.h>
12 #include <scsi/scsi.h>
13 #include <scsi/scsi_device.h>
14 #include <scsi/scsi_driver.h>
15 #include <scsi/scsi_host.h>
17 #include "scsi_priv.h"
19 static int scsi_dev_type_suspend(struct device
*dev
, int (*cb
)(struct device
*))
23 err
= scsi_device_quiesce(to_scsi_device(dev
));
28 scsi_device_resume(to_scsi_device(dev
));
31 dev_dbg(dev
, "scsi suspend: %d\n", err
);
35 static int scsi_dev_type_resume(struct device
*dev
, int (*cb
)(struct device
*))
41 scsi_device_resume(to_scsi_device(dev
));
42 dev_dbg(dev
, "scsi resume: %d\n", err
);
46 #ifdef CONFIG_PM_SLEEP
49 scsi_bus_suspend_common(struct device
*dev
, int (*cb
)(struct device
*))
53 if (scsi_is_sdev_device(dev
)) {
55 * All the high-level SCSI drivers that implement runtime
56 * PM treat runtime suspend, system suspend, and system
57 * hibernate identically.
59 if (pm_runtime_suspended(dev
))
62 err
= scsi_dev_type_suspend(dev
, cb
);
69 scsi_bus_resume_common(struct device
*dev
, int (*cb
)(struct device
*))
73 if (scsi_is_sdev_device(dev
))
74 err
= scsi_dev_type_resume(dev
, cb
);
77 pm_runtime_disable(dev
);
78 pm_runtime_set_active(dev
);
79 pm_runtime_enable(dev
);
84 static int scsi_bus_prepare(struct device
*dev
)
86 if (scsi_is_sdev_device(dev
)) {
87 /* sd probing uses async_schedule. Wait until it finishes. */
88 async_synchronize_full_domain(&scsi_sd_probe_domain
);
90 } else if (scsi_is_host_device(dev
)) {
91 /* Wait until async scanning is finished */
92 scsi_complete_async_scans();
97 static int scsi_bus_suspend(struct device
*dev
)
99 const struct dev_pm_ops
*pm
= dev
->driver
? dev
->driver
->pm
: NULL
;
100 return scsi_bus_suspend_common(dev
, pm
? pm
->suspend
: NULL
);
103 static int scsi_bus_resume(struct device
*dev
)
105 const struct dev_pm_ops
*pm
= dev
->driver
? dev
->driver
->pm
: NULL
;
106 return scsi_bus_resume_common(dev
, pm
? pm
->resume
: NULL
);
109 static int scsi_bus_freeze(struct device
*dev
)
111 const struct dev_pm_ops
*pm
= dev
->driver
? dev
->driver
->pm
: NULL
;
112 return scsi_bus_suspend_common(dev
, pm
? pm
->freeze
: NULL
);
115 static int scsi_bus_thaw(struct device
*dev
)
117 const struct dev_pm_ops
*pm
= dev
->driver
? dev
->driver
->pm
: NULL
;
118 return scsi_bus_resume_common(dev
, pm
? pm
->thaw
: NULL
);
121 static int scsi_bus_poweroff(struct device
*dev
)
123 const struct dev_pm_ops
*pm
= dev
->driver
? dev
->driver
->pm
: NULL
;
124 return scsi_bus_suspend_common(dev
, pm
? pm
->poweroff
: NULL
);
127 static int scsi_bus_restore(struct device
*dev
)
129 const struct dev_pm_ops
*pm
= dev
->driver
? dev
->driver
->pm
: NULL
;
130 return scsi_bus_resume_common(dev
, pm
? pm
->restore
: NULL
);
133 #else /* CONFIG_PM_SLEEP */
135 #define scsi_bus_prepare NULL
136 #define scsi_bus_suspend NULL
137 #define scsi_bus_resume NULL
138 #define scsi_bus_freeze NULL
139 #define scsi_bus_thaw NULL
140 #define scsi_bus_poweroff NULL
141 #define scsi_bus_restore NULL
143 #endif /* CONFIG_PM_SLEEP */
145 #ifdef CONFIG_PM_RUNTIME
147 static int sdev_blk_runtime_suspend(struct scsi_device
*sdev
,
148 int (*cb
)(struct device
*))
152 err
= blk_pre_runtime_suspend(sdev
->request_queue
);
156 err
= cb(&sdev
->sdev_gendev
);
157 blk_post_runtime_suspend(sdev
->request_queue
, err
);
162 static int sdev_runtime_suspend(struct device
*dev
)
164 const struct dev_pm_ops
*pm
= dev
->driver
? dev
->driver
->pm
: NULL
;
165 int (*cb
)(struct device
*) = pm
? pm
->runtime_suspend
: NULL
;
166 struct scsi_device
*sdev
= to_scsi_device(dev
);
169 if (sdev
->request_queue
->dev
)
170 return sdev_blk_runtime_suspend(sdev
, cb
);
172 err
= scsi_dev_type_suspend(dev
, cb
);
174 pm_schedule_suspend(dev
, jiffies_to_msecs(
175 round_jiffies_up_relative(HZ
/10)));
179 static int scsi_runtime_suspend(struct device
*dev
)
183 dev_dbg(dev
, "scsi_runtime_suspend\n");
184 if (scsi_is_sdev_device(dev
))
185 err
= sdev_runtime_suspend(dev
);
187 /* Insert hooks here for targets, hosts, and transport classes */
192 static int sdev_blk_runtime_resume(struct scsi_device
*sdev
,
193 int (*cb
)(struct device
*))
197 blk_pre_runtime_resume(sdev
->request_queue
);
199 err
= cb(&sdev
->sdev_gendev
);
200 blk_post_runtime_resume(sdev
->request_queue
, err
);
205 static int sdev_runtime_resume(struct device
*dev
)
207 struct scsi_device
*sdev
= to_scsi_device(dev
);
208 const struct dev_pm_ops
*pm
= dev
->driver
? dev
->driver
->pm
: NULL
;
209 int (*cb
)(struct device
*) = pm
? pm
->runtime_resume
: NULL
;
211 if (sdev
->request_queue
->dev
)
212 return sdev_blk_runtime_resume(sdev
, cb
);
214 return scsi_dev_type_resume(dev
, cb
);
217 static int scsi_runtime_resume(struct device
*dev
)
221 dev_dbg(dev
, "scsi_runtime_resume\n");
222 if (scsi_is_sdev_device(dev
))
223 err
= sdev_runtime_resume(dev
);
225 /* Insert hooks here for targets, hosts, and transport classes */
230 static int scsi_runtime_idle(struct device
*dev
)
234 dev_dbg(dev
, "scsi_runtime_idle\n");
236 /* Insert hooks here for targets, hosts, and transport classes */
238 if (scsi_is_sdev_device(dev
)) {
239 struct scsi_device
*sdev
= to_scsi_device(dev
);
241 if (sdev
->request_queue
->dev
) {
242 pm_runtime_mark_last_busy(dev
);
243 err
= pm_runtime_autosuspend(dev
);
245 err
= pm_runtime_suspend(dev
);
248 err
= pm_runtime_suspend(dev
);
253 int scsi_autopm_get_device(struct scsi_device
*sdev
)
257 err
= pm_runtime_get_sync(&sdev
->sdev_gendev
);
258 if (err
< 0 && err
!=-EACCES
)
259 pm_runtime_put_sync(&sdev
->sdev_gendev
);
264 EXPORT_SYMBOL_GPL(scsi_autopm_get_device
);
266 void scsi_autopm_put_device(struct scsi_device
*sdev
)
268 pm_runtime_put_sync(&sdev
->sdev_gendev
);
270 EXPORT_SYMBOL_GPL(scsi_autopm_put_device
);
272 void scsi_autopm_get_target(struct scsi_target
*starget
)
274 pm_runtime_get_sync(&starget
->dev
);
277 void scsi_autopm_put_target(struct scsi_target
*starget
)
279 pm_runtime_put_sync(&starget
->dev
);
282 int scsi_autopm_get_host(struct Scsi_Host
*shost
)
286 err
= pm_runtime_get_sync(&shost
->shost_gendev
);
287 if (err
< 0 && err
!=-EACCES
)
288 pm_runtime_put_sync(&shost
->shost_gendev
);
294 void scsi_autopm_put_host(struct Scsi_Host
*shost
)
296 pm_runtime_put_sync(&shost
->shost_gendev
);
301 #define scsi_runtime_suspend NULL
302 #define scsi_runtime_resume NULL
303 #define scsi_runtime_idle NULL
305 #endif /* CONFIG_PM_RUNTIME */
307 const struct dev_pm_ops scsi_bus_pm_ops
= {
308 .prepare
= scsi_bus_prepare
,
309 .suspend
= scsi_bus_suspend
,
310 .resume
= scsi_bus_resume
,
311 .freeze
= scsi_bus_freeze
,
312 .thaw
= scsi_bus_thaw
,
313 .poweroff
= scsi_bus_poweroff
,
314 .restore
= scsi_bus_restore
,
315 .runtime_suspend
= scsi_runtime_suspend
,
316 .runtime_resume
= scsi_runtime_resume
,
317 .runtime_idle
= scsi_runtime_idle
,