xref: /openbmc/linux/drivers/scsi/scsi_pm.c (revision 23966841)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *	scsi_pm.c	Copyright (C) 2010 Alan Stern
4  *
5  *	SCSI dynamic Power Management
6  *		Initial version: Alan Stern <stern@rowland.harvard.edu>
7  */
8 
9 #include <linux/pm_runtime.h>
10 #include <linux/export.h>
11 #include <linux/async.h>
12 #include <linux/blk-pm.h>
13 
14 #include <scsi/scsi.h>
15 #include <scsi/scsi_device.h>
16 #include <scsi/scsi_driver.h>
17 #include <scsi/scsi_host.h>
18 
19 #include "scsi_priv.h"
20 
21 #ifdef CONFIG_PM_SLEEP
22 
23 static int do_scsi_suspend(struct device *dev, const struct dev_pm_ops *pm)
24 {
25 	return pm && pm->suspend ? pm->suspend(dev) : 0;
26 }
27 
28 static int do_scsi_freeze(struct device *dev, const struct dev_pm_ops *pm)
29 {
30 	return pm && pm->freeze ? pm->freeze(dev) : 0;
31 }
32 
33 static int do_scsi_poweroff(struct device *dev, const struct dev_pm_ops *pm)
34 {
35 	return pm && pm->poweroff ? pm->poweroff(dev) : 0;
36 }
37 
38 static int do_scsi_resume(struct device *dev, const struct dev_pm_ops *pm)
39 {
40 	return pm && pm->resume ? pm->resume(dev) : 0;
41 }
42 
43 static int do_scsi_thaw(struct device *dev, const struct dev_pm_ops *pm)
44 {
45 	return pm && pm->thaw ? pm->thaw(dev) : 0;
46 }
47 
48 static int do_scsi_restore(struct device *dev, const struct dev_pm_ops *pm)
49 {
50 	return pm && pm->restore ? pm->restore(dev) : 0;
51 }
52 
53 static int scsi_dev_type_suspend(struct device *dev,
54 		int (*cb)(struct device *, const struct dev_pm_ops *))
55 {
56 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
57 	int err;
58 
59 	/* flush pending in-flight resume operations, suspend is synchronous */
60 	async_synchronize_full_domain(&scsi_sd_pm_domain);
61 
62 	err = scsi_device_quiesce(to_scsi_device(dev));
63 	if (err == 0) {
64 		err = cb(dev, pm);
65 		if (err)
66 			scsi_device_resume(to_scsi_device(dev));
67 	}
68 	dev_dbg(dev, "scsi suspend: %d\n", err);
69 	return err;
70 }
71 
72 static int scsi_dev_type_resume(struct device *dev,
73 		int (*cb)(struct device *, const struct dev_pm_ops *))
74 {
75 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
76 	int err = 0;
77 
78 	err = cb(dev, pm);
79 	scsi_device_resume(to_scsi_device(dev));
80 	dev_dbg(dev, "scsi resume: %d\n", err);
81 
82 	if (err == 0) {
83 		pm_runtime_disable(dev);
84 		err = pm_runtime_set_active(dev);
85 		pm_runtime_enable(dev);
86 
87 		/*
88 		 * Forcibly set runtime PM status of request queue to "active"
89 		 * to make sure we can again get requests from the queue
90 		 * (see also blk_pm_peek_request()).
91 		 *
92 		 * The resume hook will correct runtime PM status of the disk.
93 		 */
94 		if (!err && scsi_is_sdev_device(dev)) {
95 			struct scsi_device *sdev = to_scsi_device(dev);
96 
97 			if (sdev->request_queue->dev)
98 				blk_set_runtime_active(sdev->request_queue);
99 		}
100 	}
101 
102 	return err;
103 }
104 
105 static int
106 scsi_bus_suspend_common(struct device *dev,
107 		int (*cb)(struct device *, const struct dev_pm_ops *))
108 {
109 	int err = 0;
110 
111 	if (scsi_is_sdev_device(dev)) {
112 		/*
113 		 * All the high-level SCSI drivers that implement runtime
114 		 * PM treat runtime suspend, system suspend, and system
115 		 * hibernate nearly identically. In all cases the requirements
116 		 * for runtime suspension are stricter.
117 		 */
118 		if (pm_runtime_suspended(dev))
119 			return 0;
120 
121 		err = scsi_dev_type_suspend(dev, cb);
122 	}
123 
124 	return err;
125 }
126 
127 static void async_sdev_resume(void *dev, async_cookie_t cookie)
128 {
129 	scsi_dev_type_resume(dev, do_scsi_resume);
130 }
131 
132 static void async_sdev_thaw(void *dev, async_cookie_t cookie)
133 {
134 	scsi_dev_type_resume(dev, do_scsi_thaw);
135 }
136 
137 static void async_sdev_restore(void *dev, async_cookie_t cookie)
138 {
139 	scsi_dev_type_resume(dev, do_scsi_restore);
140 }
141 
142 static int scsi_bus_resume_common(struct device *dev,
143 		int (*cb)(struct device *, const struct dev_pm_ops *))
144 {
145 	async_func_t fn;
146 
147 	if (!scsi_is_sdev_device(dev))
148 		fn = NULL;
149 	else if (cb == do_scsi_resume)
150 		fn = async_sdev_resume;
151 	else if (cb == do_scsi_thaw)
152 		fn = async_sdev_thaw;
153 	else if (cb == do_scsi_restore)
154 		fn = async_sdev_restore;
155 	else
156 		fn = NULL;
157 
158 	if (fn) {
159 		async_schedule_domain(fn, dev, &scsi_sd_pm_domain);
160 
161 		/*
162 		 * If a user has disabled async probing a likely reason
163 		 * is due to a storage enclosure that does not inject
164 		 * staggered spin-ups.  For safety, make resume
165 		 * synchronous as well in that case.
166 		 */
167 		if (strncmp(scsi_scan_type, "async", 5) != 0)
168 			async_synchronize_full_domain(&scsi_sd_pm_domain);
169 	} else {
170 		pm_runtime_disable(dev);
171 		pm_runtime_set_active(dev);
172 		pm_runtime_enable(dev);
173 	}
174 	return 0;
175 }
176 
177 static int scsi_bus_prepare(struct device *dev)
178 {
179 	if (scsi_is_host_device(dev)) {
180 		/* Wait until async scanning is finished */
181 		scsi_complete_async_scans();
182 	}
183 	return 0;
184 }
185 
186 static int scsi_bus_suspend(struct device *dev)
187 {
188 	return scsi_bus_suspend_common(dev, do_scsi_suspend);
189 }
190 
191 static int scsi_bus_resume(struct device *dev)
192 {
193 	return scsi_bus_resume_common(dev, do_scsi_resume);
194 }
195 
196 static int scsi_bus_freeze(struct device *dev)
197 {
198 	return scsi_bus_suspend_common(dev, do_scsi_freeze);
199 }
200 
201 static int scsi_bus_thaw(struct device *dev)
202 {
203 	return scsi_bus_resume_common(dev, do_scsi_thaw);
204 }
205 
206 static int scsi_bus_poweroff(struct device *dev)
207 {
208 	return scsi_bus_suspend_common(dev, do_scsi_poweroff);
209 }
210 
211 static int scsi_bus_restore(struct device *dev)
212 {
213 	return scsi_bus_resume_common(dev, do_scsi_restore);
214 }
215 
216 #else /* CONFIG_PM_SLEEP */
217 
218 #define scsi_bus_prepare		NULL
219 #define scsi_bus_suspend		NULL
220 #define scsi_bus_resume			NULL
221 #define scsi_bus_freeze			NULL
222 #define scsi_bus_thaw			NULL
223 #define scsi_bus_poweroff		NULL
224 #define scsi_bus_restore		NULL
225 
226 #endif /* CONFIG_PM_SLEEP */
227 
228 static int sdev_runtime_suspend(struct device *dev)
229 {
230 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
231 	struct scsi_device *sdev = to_scsi_device(dev);
232 	int err = 0;
233 
234 	err = blk_pre_runtime_suspend(sdev->request_queue);
235 	if (err)
236 		return err;
237 	if (pm && pm->runtime_suspend)
238 		err = pm->runtime_suspend(dev);
239 	blk_post_runtime_suspend(sdev->request_queue, err);
240 
241 	return err;
242 }
243 
244 static int scsi_runtime_suspend(struct device *dev)
245 {
246 	int err = 0;
247 
248 	dev_dbg(dev, "scsi_runtime_suspend\n");
249 	if (scsi_is_sdev_device(dev))
250 		err = sdev_runtime_suspend(dev);
251 
252 	/* Insert hooks here for targets, hosts, and transport classes */
253 
254 	return err;
255 }
256 
257 static int sdev_runtime_resume(struct device *dev)
258 {
259 	struct scsi_device *sdev = to_scsi_device(dev);
260 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
261 	int err = 0;
262 
263 	blk_pre_runtime_resume(sdev->request_queue);
264 	if (pm && pm->runtime_resume)
265 		err = pm->runtime_resume(dev);
266 	blk_post_runtime_resume(sdev->request_queue, err);
267 
268 	return err;
269 }
270 
271 static int scsi_runtime_resume(struct device *dev)
272 {
273 	int err = 0;
274 
275 	dev_dbg(dev, "scsi_runtime_resume\n");
276 	if (scsi_is_sdev_device(dev))
277 		err = sdev_runtime_resume(dev);
278 
279 	/* Insert hooks here for targets, hosts, and transport classes */
280 
281 	return err;
282 }
283 
284 static int scsi_runtime_idle(struct device *dev)
285 {
286 	dev_dbg(dev, "scsi_runtime_idle\n");
287 
288 	/* Insert hooks here for targets, hosts, and transport classes */
289 
290 	if (scsi_is_sdev_device(dev)) {
291 		pm_runtime_mark_last_busy(dev);
292 		pm_runtime_autosuspend(dev);
293 		return -EBUSY;
294 	}
295 
296 	return 0;
297 }
298 
299 int scsi_autopm_get_device(struct scsi_device *sdev)
300 {
301 	int	err;
302 
303 	err = pm_runtime_get_sync(&sdev->sdev_gendev);
304 	if (err < 0 && err !=-EACCES)
305 		pm_runtime_put_sync(&sdev->sdev_gendev);
306 	else
307 		err = 0;
308 	return err;
309 }
310 EXPORT_SYMBOL_GPL(scsi_autopm_get_device);
311 
312 void scsi_autopm_put_device(struct scsi_device *sdev)
313 {
314 	pm_runtime_put_sync(&sdev->sdev_gendev);
315 }
316 EXPORT_SYMBOL_GPL(scsi_autopm_put_device);
317 
318 void scsi_autopm_get_target(struct scsi_target *starget)
319 {
320 	pm_runtime_get_sync(&starget->dev);
321 }
322 
323 void scsi_autopm_put_target(struct scsi_target *starget)
324 {
325 	pm_runtime_put_sync(&starget->dev);
326 }
327 
328 int scsi_autopm_get_host(struct Scsi_Host *shost)
329 {
330 	int	err;
331 
332 	err = pm_runtime_get_sync(&shost->shost_gendev);
333 	if (err < 0 && err !=-EACCES)
334 		pm_runtime_put_sync(&shost->shost_gendev);
335 	else
336 		err = 0;
337 	return err;
338 }
339 
340 void scsi_autopm_put_host(struct Scsi_Host *shost)
341 {
342 	pm_runtime_put_sync(&shost->shost_gendev);
343 }
344 
345 const struct dev_pm_ops scsi_bus_pm_ops = {
346 	.prepare =		scsi_bus_prepare,
347 	.suspend =		scsi_bus_suspend,
348 	.resume =		scsi_bus_resume,
349 	.freeze =		scsi_bus_freeze,
350 	.thaw =			scsi_bus_thaw,
351 	.poweroff =		scsi_bus_poweroff,
352 	.restore =		scsi_bus_restore,
353 	.runtime_suspend =	scsi_runtime_suspend,
354 	.runtime_resume =	scsi_runtime_resume,
355 	.runtime_idle =		scsi_runtime_idle,
356 };
357