xref: /openbmc/linux/drivers/scsi/scsi_pm.c (revision 51ad5b54)
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 		bool was_runtime_suspended;
84 
85 		was_runtime_suspended = pm_runtime_suspended(dev);
86 
87 		pm_runtime_disable(dev);
88 		err = pm_runtime_set_active(dev);
89 		pm_runtime_enable(dev);
90 
91 		/*
92 		 * Forcibly set runtime PM status of request queue to "active"
93 		 * to make sure we can again get requests from the queue
94 		 * (see also blk_pm_peek_request()).
95 		 *
96 		 * The resume hook will correct runtime PM status of the disk.
97 		 */
98 		if (!err && scsi_is_sdev_device(dev)) {
99 			struct scsi_device *sdev = to_scsi_device(dev);
100 			if (was_runtime_suspended)
101 				blk_post_runtime_resume(sdev->request_queue, 0);
102 			else
103 				blk_set_runtime_active(sdev->request_queue);
104 		}
105 	}
106 
107 	return err;
108 }
109 
110 static int
111 scsi_bus_suspend_common(struct device *dev,
112 		int (*cb)(struct device *, const struct dev_pm_ops *))
113 {
114 	int err = 0;
115 
116 	if (scsi_is_sdev_device(dev)) {
117 		/*
118 		 * All the high-level SCSI drivers that implement runtime
119 		 * PM treat runtime suspend, system suspend, and system
120 		 * hibernate nearly identically. In all cases the requirements
121 		 * for runtime suspension are stricter.
122 		 */
123 		if (pm_runtime_suspended(dev))
124 			return 0;
125 
126 		err = scsi_dev_type_suspend(dev, cb);
127 	}
128 
129 	return err;
130 }
131 
132 static void async_sdev_resume(void *dev, async_cookie_t cookie)
133 {
134 	scsi_dev_type_resume(dev, do_scsi_resume);
135 }
136 
137 static void async_sdev_thaw(void *dev, async_cookie_t cookie)
138 {
139 	scsi_dev_type_resume(dev, do_scsi_thaw);
140 }
141 
142 static void async_sdev_restore(void *dev, async_cookie_t cookie)
143 {
144 	scsi_dev_type_resume(dev, do_scsi_restore);
145 }
146 
147 static int scsi_bus_resume_common(struct device *dev,
148 		int (*cb)(struct device *, const struct dev_pm_ops *))
149 {
150 	async_func_t fn;
151 
152 	if (!scsi_is_sdev_device(dev))
153 		fn = NULL;
154 	else if (cb == do_scsi_resume)
155 		fn = async_sdev_resume;
156 	else if (cb == do_scsi_thaw)
157 		fn = async_sdev_thaw;
158 	else if (cb == do_scsi_restore)
159 		fn = async_sdev_restore;
160 	else
161 		fn = NULL;
162 
163 	if (fn) {
164 		async_schedule_domain(fn, dev, &scsi_sd_pm_domain);
165 
166 		/*
167 		 * If a user has disabled async probing a likely reason
168 		 * is due to a storage enclosure that does not inject
169 		 * staggered spin-ups.  For safety, make resume
170 		 * synchronous as well in that case.
171 		 */
172 		if (strncmp(scsi_scan_type, "async", 5) != 0)
173 			async_synchronize_full_domain(&scsi_sd_pm_domain);
174 	} else {
175 		pm_runtime_disable(dev);
176 		pm_runtime_set_active(dev);
177 		pm_runtime_enable(dev);
178 	}
179 	return 0;
180 }
181 
182 static int scsi_bus_prepare(struct device *dev)
183 {
184 	if (scsi_is_host_device(dev)) {
185 		/* Wait until async scanning is finished */
186 		scsi_complete_async_scans();
187 	}
188 	return 0;
189 }
190 
191 static int scsi_bus_suspend(struct device *dev)
192 {
193 	return scsi_bus_suspend_common(dev, do_scsi_suspend);
194 }
195 
196 static int scsi_bus_resume(struct device *dev)
197 {
198 	return scsi_bus_resume_common(dev, do_scsi_resume);
199 }
200 
201 static int scsi_bus_freeze(struct device *dev)
202 {
203 	return scsi_bus_suspend_common(dev, do_scsi_freeze);
204 }
205 
206 static int scsi_bus_thaw(struct device *dev)
207 {
208 	return scsi_bus_resume_common(dev, do_scsi_thaw);
209 }
210 
211 static int scsi_bus_poweroff(struct device *dev)
212 {
213 	return scsi_bus_suspend_common(dev, do_scsi_poweroff);
214 }
215 
216 static int scsi_bus_restore(struct device *dev)
217 {
218 	return scsi_bus_resume_common(dev, do_scsi_restore);
219 }
220 
221 #else /* CONFIG_PM_SLEEP */
222 
223 #define scsi_bus_prepare		NULL
224 #define scsi_bus_suspend		NULL
225 #define scsi_bus_resume			NULL
226 #define scsi_bus_freeze			NULL
227 #define scsi_bus_thaw			NULL
228 #define scsi_bus_poweroff		NULL
229 #define scsi_bus_restore		NULL
230 
231 #endif /* CONFIG_PM_SLEEP */
232 
233 static int sdev_runtime_suspend(struct device *dev)
234 {
235 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
236 	struct scsi_device *sdev = to_scsi_device(dev);
237 	int err = 0;
238 
239 	err = blk_pre_runtime_suspend(sdev->request_queue);
240 	if (err)
241 		return err;
242 	if (pm && pm->runtime_suspend)
243 		err = pm->runtime_suspend(dev);
244 	blk_post_runtime_suspend(sdev->request_queue, err);
245 
246 	return err;
247 }
248 
249 static int scsi_runtime_suspend(struct device *dev)
250 {
251 	int err = 0;
252 
253 	dev_dbg(dev, "scsi_runtime_suspend\n");
254 	if (scsi_is_sdev_device(dev))
255 		err = sdev_runtime_suspend(dev);
256 
257 	/* Insert hooks here for targets, hosts, and transport classes */
258 
259 	return err;
260 }
261 
262 static int sdev_runtime_resume(struct device *dev)
263 {
264 	struct scsi_device *sdev = to_scsi_device(dev);
265 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
266 	int err = 0;
267 
268 	blk_pre_runtime_resume(sdev->request_queue);
269 	if (pm && pm->runtime_resume)
270 		err = pm->runtime_resume(dev);
271 	blk_post_runtime_resume(sdev->request_queue, err);
272 
273 	return err;
274 }
275 
276 static int scsi_runtime_resume(struct device *dev)
277 {
278 	int err = 0;
279 
280 	dev_dbg(dev, "scsi_runtime_resume\n");
281 	if (scsi_is_sdev_device(dev))
282 		err = sdev_runtime_resume(dev);
283 
284 	/* Insert hooks here for targets, hosts, and transport classes */
285 
286 	return err;
287 }
288 
289 static int scsi_runtime_idle(struct device *dev)
290 {
291 	dev_dbg(dev, "scsi_runtime_idle\n");
292 
293 	/* Insert hooks here for targets, hosts, and transport classes */
294 
295 	if (scsi_is_sdev_device(dev)) {
296 		pm_runtime_mark_last_busy(dev);
297 		pm_runtime_autosuspend(dev);
298 		return -EBUSY;
299 	}
300 
301 	return 0;
302 }
303 
304 int scsi_autopm_get_device(struct scsi_device *sdev)
305 {
306 	int	err;
307 
308 	err = pm_runtime_get_sync(&sdev->sdev_gendev);
309 	if (err < 0 && err !=-EACCES)
310 		pm_runtime_put_sync(&sdev->sdev_gendev);
311 	else
312 		err = 0;
313 	return err;
314 }
315 EXPORT_SYMBOL_GPL(scsi_autopm_get_device);
316 
317 void scsi_autopm_put_device(struct scsi_device *sdev)
318 {
319 	pm_runtime_put_sync(&sdev->sdev_gendev);
320 }
321 EXPORT_SYMBOL_GPL(scsi_autopm_put_device);
322 
323 void scsi_autopm_get_target(struct scsi_target *starget)
324 {
325 	pm_runtime_get_sync(&starget->dev);
326 }
327 
328 void scsi_autopm_put_target(struct scsi_target *starget)
329 {
330 	pm_runtime_put_sync(&starget->dev);
331 }
332 
333 int scsi_autopm_get_host(struct Scsi_Host *shost)
334 {
335 	int	err;
336 
337 	err = pm_runtime_get_sync(&shost->shost_gendev);
338 	if (err < 0 && err !=-EACCES)
339 		pm_runtime_put_sync(&shost->shost_gendev);
340 	else
341 		err = 0;
342 	return err;
343 }
344 
345 void scsi_autopm_put_host(struct Scsi_Host *shost)
346 {
347 	pm_runtime_put_sync(&shost->shost_gendev);
348 }
349 
350 const struct dev_pm_ops scsi_bus_pm_ops = {
351 	.prepare =		scsi_bus_prepare,
352 	.suspend =		scsi_bus_suspend,
353 	.resume =		scsi_bus_resume,
354 	.freeze =		scsi_bus_freeze,
355 	.thaw =			scsi_bus_thaw,
356 	.poweroff =		scsi_bus_poweroff,
357 	.restore =		scsi_bus_restore,
358 	.runtime_suspend =	scsi_runtime_suspend,
359 	.runtime_resume =	scsi_runtime_resume,
360 	.runtime_idle =		scsi_runtime_idle,
361 };
362