Blame view

drivers/base/power/main.c 26.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
  /*
   * drivers/base/power/main.c - Where the driver meets power management.
   *
   * Copyright (c) 2003 Patrick Mochel
   * Copyright (c) 2003 Open Source Development Lab
   *
   * This file is released under the GPLv2
   *
   *
   * The driver model core calls device_pm_add() when a device is registered.
b595076a1   Uwe Kleine-König   tree-wide: fix co...
11
   * This will initialize the embedded device_pm_info object in the device
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
   * and add it to the list of power-controlled devices. sysfs entries for
   * controlling device power management will also be added.
   *
1eede070a   Rafael J. Wysocki   Introduce new top...
15
16
17
   * A separate list is used for keeping track of power info, because the power
   * domain dependencies may differ from the ancestral dependencies that the
   * subsystem list maintains.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
  #include <linux/device.h>
cd59abfcc   Alan Stern   PM: merge device ...
20
  #include <linux/kallsyms.h>
1b6bc32f0   Paul Gortmaker   drivers/base: Add...
21
  #include <linux/export.h>
11048dcf3   Matthias Kaehlcke   Power Management:...
22
  #include <linux/mutex.h>
cd59abfcc   Alan Stern   PM: merge device ...
23
  #include <linux/pm.h>
5e928f77a   Rafael J. Wysocki   PM: Introduce cor...
24
  #include <linux/pm_runtime.h>
cd59abfcc   Alan Stern   PM: merge device ...
25
  #include <linux/resume-trace.h>
2ed8d2b3a   Rafael J. Wysocki   PM: Rework handli...
26
  #include <linux/interrupt.h>
f25117748   Arjan van de Ven   PM: Add initcall_...
27
  #include <linux/sched.h>
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
28
  #include <linux/async.h>
1e75227ef   Rafael J. Wysocki   PM: Prevent dpm_p...
29
  #include <linux/suspend.h>
11048dcf3   Matthias Kaehlcke   Power Management:...
30

cd59abfcc   Alan Stern   PM: merge device ...
31
  #include "../base.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
  #include "power.h"
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
33
  typedef int (*pm_callback_t)(struct device *);
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
34
  /*
1eede070a   Rafael J. Wysocki   Introduce new top...
35
   * The entries in the dpm_list list are in a depth first order, simply
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
36
37
38
   * because children are guaranteed to be discovered after parents, and
   * are inserted at the back of the list on discovery.
   *
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
39
40
   * Since device_pm_add() may be called with a device lock held,
   * we must never try to acquire a device lock while holding
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
41
42
   * dpm_list_mutex.
   */
1eede070a   Rafael J. Wysocki   Introduce new top...
43
  LIST_HEAD(dpm_list);
8a43a9ab7   Rafael J. Wysocki   PM: Use a differe...
44
45
46
  LIST_HEAD(dpm_prepared_list);
  LIST_HEAD(dpm_suspended_list);
  LIST_HEAD(dpm_noirq_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47

2a77c46de   ShuoX Liu   PM / Suspend: Add...
48
  struct suspend_stats suspend_stats;
cd59abfcc   Alan Stern   PM: merge device ...
49
  static DEFINE_MUTEX(dpm_list_mtx);
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
50
  static pm_message_t pm_transition;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51

098dff738   Rafael J. Wysocki   PM: Fix potential...
52
  static int async_error;
1eede070a   Rafael J. Wysocki   Introduce new top...
53
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
54
   * device_pm_init - Initialize the PM-related part of a device object.
5e928f77a   Rafael J. Wysocki   PM: Introduce cor...
55
56
57
58
   * @dev: Device object being initialized.
   */
  void device_pm_init(struct device *dev)
  {
f76b168b6   Alan Stern   PM: Rename dev_pm...
59
  	dev->power.is_prepared = false;
6d0e0e84f   Alan Stern   PM: Fix async res...
60
  	dev->power.is_suspended = false;
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
61
  	init_completion(&dev->power.completion);
152e1d592   Colin Cross   PM: Prevent waiti...
62
  	complete_all(&dev->power.completion);
074037ec7   Rafael J. Wysocki   PM / Wakeup: Intr...
63
64
  	dev->power.wakeup = NULL;
  	spin_lock_init(&dev->power.lock);
5e928f77a   Rafael J. Wysocki   PM: Introduce cor...
65
  	pm_runtime_init(dev);
22110faf8   Rafael J. Wysocki   PM / Wakeup: Fix ...
66
  	INIT_LIST_HEAD(&dev->power.entry);
1a9a91525   Rafael J. Wysocki   PM / QoS: Add fun...
67
  	dev->power.power_state = PMSG_INVALID;
5e928f77a   Rafael J. Wysocki   PM: Introduce cor...
68
69
70
  }
  
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
71
   * device_pm_lock - Lock the list of active devices used by the PM core.
1eede070a   Rafael J. Wysocki   Introduce new top...
72
73
74
75
76
77
78
   */
  void device_pm_lock(void)
  {
  	mutex_lock(&dpm_list_mtx);
  }
  
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
79
   * device_pm_unlock - Unlock the list of active devices used by the PM core.
1eede070a   Rafael J. Wysocki   Introduce new top...
80
81
82
83
84
   */
  void device_pm_unlock(void)
  {
  	mutex_unlock(&dpm_list_mtx);
  }
075c17715   David Brownell   define platform w...
85

775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
86
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
87
88
   * device_pm_add - Add a device to the PM core's list of active devices.
   * @dev: Device to add to the list.
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
89
   */
3b98aeaf3   Alan Stern   PM: don't skip de...
90
  void device_pm_add(struct device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
  	pr_debug("PM: Adding info for %s:%s
  ",
5c1a07ab3   Rafael J. Wysocki   PM: Use dev_name(...
94
  		 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
11048dcf3   Matthias Kaehlcke   Power Management:...
95
  	mutex_lock(&dpm_list_mtx);
f76b168b6   Alan Stern   PM: Rename dev_pm...
96
  	if (dev->parent && dev->parent->power.is_prepared)
b64959e61   Rafael J. Wysocki   PM: Permit regist...
97
98
99
  		dev_warn(dev, "parent %s should not be sleeping
  ",
  			dev_name(dev->parent));
3b98aeaf3   Alan Stern   PM: don't skip de...
100
  	list_add_tail(&dev->power.entry, &dpm_list);
91ff4cb80   Jean Pihet   PM QoS: Implement...
101
  	dev_pm_qos_constraints_init(dev);
1a9a91525   Rafael J. Wysocki   PM / QoS: Add fun...
102
  	mutex_unlock(&dpm_list_mtx);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  }
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
104
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
105
106
   * device_pm_remove - Remove a device from the PM core's list of active devices.
   * @dev: Device to be removed from the list.
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
107
   */
9cddad775   Rafael J. Wysocki   PM: Remove pm_par...
108
  void device_pm_remove(struct device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
  {
  	pr_debug("PM: Removing info for %s:%s
  ",
5c1a07ab3   Rafael J. Wysocki   PM: Use dev_name(...
112
  		 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
113
  	complete_all(&dev->power.completion);
11048dcf3   Matthias Kaehlcke   Power Management:...
114
  	mutex_lock(&dpm_list_mtx);
1a9a91525   Rafael J. Wysocki   PM / QoS: Add fun...
115
  	dev_pm_qos_constraints_destroy(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
  	list_del_init(&dev->power.entry);
11048dcf3   Matthias Kaehlcke   Power Management:...
117
  	mutex_unlock(&dpm_list_mtx);
074037ec7   Rafael J. Wysocki   PM / Wakeup: Intr...
118
  	device_wakeup_disable(dev);
5e928f77a   Rafael J. Wysocki   PM: Introduce cor...
119
  	pm_runtime_remove(dev);
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
120
  }
1eede070a   Rafael J. Wysocki   Introduce new top...
121
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
122
123
124
   * device_pm_move_before - Move device in the PM core's list of active devices.
   * @deva: Device to move in dpm_list.
   * @devb: Device @deva should come before.
ffa6a7054   Cornelia Huck   Driver core: Fix ...
125
126
127
128
129
   */
  void device_pm_move_before(struct device *deva, struct device *devb)
  {
  	pr_debug("PM: Moving %s:%s before %s:%s
  ",
5c1a07ab3   Rafael J. Wysocki   PM: Use dev_name(...
130
131
  		 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
  		 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
ffa6a7054   Cornelia Huck   Driver core: Fix ...
132
133
134
135
136
  	/* Delete deva from dpm_list and reinsert before devb. */
  	list_move_tail(&deva->power.entry, &devb->power.entry);
  }
  
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
137
138
139
   * device_pm_move_after - Move device in the PM core's list of active devices.
   * @deva: Device to move in dpm_list.
   * @devb: Device @deva should come after.
ffa6a7054   Cornelia Huck   Driver core: Fix ...
140
141
142
143
144
   */
  void device_pm_move_after(struct device *deva, struct device *devb)
  {
  	pr_debug("PM: Moving %s:%s after %s:%s
  ",
5c1a07ab3   Rafael J. Wysocki   PM: Use dev_name(...
145
146
  		 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
  		 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
ffa6a7054   Cornelia Huck   Driver core: Fix ...
147
148
149
150
151
  	/* Delete deva from dpm_list and reinsert after devb. */
  	list_move(&deva->power.entry, &devb->power.entry);
  }
  
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
152
153
   * device_pm_move_last - Move device to end of the PM core's list of devices.
   * @dev: Device to move in dpm_list.
ffa6a7054   Cornelia Huck   Driver core: Fix ...
154
155
156
157
158
   */
  void device_pm_move_last(struct device *dev)
  {
  	pr_debug("PM: Moving %s:%s to end of list
  ",
5c1a07ab3   Rafael J. Wysocki   PM: Use dev_name(...
159
  		 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
ffa6a7054   Cornelia Huck   Driver core: Fix ...
160
161
  	list_move_tail(&dev->power.entry, &dpm_list);
  }
875ab0b74   Rafael J. Wysocki   PM: Make the init...
162
163
164
165
166
  static ktime_t initcall_debug_start(struct device *dev)
  {
  	ktime_t calltime = ktime_set(0, 0);
  
  	if (initcall_debug) {
0c6aebe31   Rafael J. Wysocki   PM / Sleep: Unify...
167
168
169
170
  		pr_info("calling  %s+ @ %i, parent: %s
  ",
  			dev_name(dev), task_pid_nr(current),
  			dev->parent ? dev_name(dev->parent) : "none");
875ab0b74   Rafael J. Wysocki   PM: Make the init...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  		calltime = ktime_get();
  	}
  
  	return calltime;
  }
  
  static void initcall_debug_report(struct device *dev, ktime_t calltime,
  				  int error)
  {
  	ktime_t delta, rettime;
  
  	if (initcall_debug) {
  		rettime = ktime_get();
  		delta = ktime_sub(rettime, calltime);
  		pr_info("call %s+ returned %d after %Ld usecs
  ", dev_name(dev),
  			error, (unsigned long long)ktime_to_ns(delta) >> 10);
  	}
  }
ffa6a7054   Cornelia Huck   Driver core: Fix ...
190
  /**
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
191
192
193
194
195
196
197
198
   * dpm_wait - Wait for a PM operation to complete.
   * @dev: Device to wait for.
   * @async: If unset, wait only if the device's power.async_suspend flag is set.
   */
  static void dpm_wait(struct device *dev, bool async)
  {
  	if (!dev)
  		return;
0e06b4a89   Rafael J. Wysocki   PM: Add a switch ...
199
  	if (async || (pm_async_enabled && dev->power.async_suspend))
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  		wait_for_completion(&dev->power.completion);
  }
  
  static int dpm_wait_fn(struct device *dev, void *async_ptr)
  {
  	dpm_wait(dev, *((bool *)async_ptr));
  	return 0;
  }
  
  static void dpm_wait_for_children(struct device *dev, bool async)
  {
         device_for_each_child(dev, &async, dpm_wait_fn);
  }
  
  /**
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
215
   * pm_op - Return the PM operation appropriate for given PM event.
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
216
217
   * @ops: PM operations to choose from.
   * @state: PM transition of the system being carried out.
1eede070a   Rafael J. Wysocki   Introduce new top...
218
   */
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
219
  static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state)
1eede070a   Rafael J. Wysocki   Introduce new top...
220
  {
1eede070a   Rafael J. Wysocki   Introduce new top...
221
222
223
  	switch (state.event) {
  #ifdef CONFIG_SUSPEND
  	case PM_EVENT_SUSPEND:
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
224
  		return ops->suspend;
1eede070a   Rafael J. Wysocki   Introduce new top...
225
  	case PM_EVENT_RESUME:
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
226
  		return ops->resume;
1eede070a   Rafael J. Wysocki   Introduce new top...
227
  #endif /* CONFIG_SUSPEND */
1f112cee0   Rafael J. Wysocki   PM / Hibernate: I...
228
  #ifdef CONFIG_HIBERNATE_CALLBACKS
1eede070a   Rafael J. Wysocki   Introduce new top...
229
230
  	case PM_EVENT_FREEZE:
  	case PM_EVENT_QUIESCE:
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
231
  		return ops->freeze;
1eede070a   Rafael J. Wysocki   Introduce new top...
232
  	case PM_EVENT_HIBERNATE:
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
233
  		return ops->poweroff;
1eede070a   Rafael J. Wysocki   Introduce new top...
234
235
  	case PM_EVENT_THAW:
  	case PM_EVENT_RECOVER:
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
236
  		return ops->thaw;
1eede070a   Rafael J. Wysocki   Introduce new top...
237
238
  		break;
  	case PM_EVENT_RESTORE:
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
239
  		return ops->restore;
1f112cee0   Rafael J. Wysocki   PM / Hibernate: I...
240
  #endif /* CONFIG_HIBERNATE_CALLBACKS */
1eede070a   Rafael J. Wysocki   Introduce new top...
241
  	}
f25117748   Arjan van de Ven   PM: Add initcall_...
242

9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
243
  	return NULL;
1eede070a   Rafael J. Wysocki   Introduce new top...
244
245
246
  }
  
  /**
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
247
   * pm_noirq_op - Return the PM operation appropriate for given PM event.
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
248
249
   * @ops: PM operations to choose from.
   * @state: PM transition of the system being carried out.
1eede070a   Rafael J. Wysocki   Introduce new top...
250
   *
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
251
252
   * The driver of @dev will not receive interrupts while this function is being
   * executed.
1eede070a   Rafael J. Wysocki   Introduce new top...
253
   */
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
254
  static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t state)
1eede070a   Rafael J. Wysocki   Introduce new top...
255
  {
1eede070a   Rafael J. Wysocki   Introduce new top...
256
257
258
  	switch (state.event) {
  #ifdef CONFIG_SUSPEND
  	case PM_EVENT_SUSPEND:
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
259
  		return ops->suspend_noirq;
1eede070a   Rafael J. Wysocki   Introduce new top...
260
  	case PM_EVENT_RESUME:
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
261
  		return ops->resume_noirq;
1eede070a   Rafael J. Wysocki   Introduce new top...
262
  #endif /* CONFIG_SUSPEND */
1f112cee0   Rafael J. Wysocki   PM / Hibernate: I...
263
  #ifdef CONFIG_HIBERNATE_CALLBACKS
1eede070a   Rafael J. Wysocki   Introduce new top...
264
265
  	case PM_EVENT_FREEZE:
  	case PM_EVENT_QUIESCE:
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
266
  		return ops->freeze_noirq;
1eede070a   Rafael J. Wysocki   Introduce new top...
267
  	case PM_EVENT_HIBERNATE:
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
268
  		return ops->poweroff_noirq;
1eede070a   Rafael J. Wysocki   Introduce new top...
269
270
  	case PM_EVENT_THAW:
  	case PM_EVENT_RECOVER:
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
271
  		return ops->thaw_noirq;
1eede070a   Rafael J. Wysocki   Introduce new top...
272
  	case PM_EVENT_RESTORE:
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
273
  		return ops->restore_noirq;
1f112cee0   Rafael J. Wysocki   PM / Hibernate: I...
274
  #endif /* CONFIG_HIBERNATE_CALLBACKS */
1eede070a   Rafael J. Wysocki   Introduce new top...
275
  	}
f25117748   Arjan van de Ven   PM: Add initcall_...
276

9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
277
  	return NULL;
1eede070a   Rafael J. Wysocki   Introduce new top...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
  }
  
  static char *pm_verb(int event)
  {
  	switch (event) {
  	case PM_EVENT_SUSPEND:
  		return "suspend";
  	case PM_EVENT_RESUME:
  		return "resume";
  	case PM_EVENT_FREEZE:
  		return "freeze";
  	case PM_EVENT_QUIESCE:
  		return "quiesce";
  	case PM_EVENT_HIBERNATE:
  		return "hibernate";
  	case PM_EVENT_THAW:
  		return "thaw";
  	case PM_EVENT_RESTORE:
  		return "restore";
  	case PM_EVENT_RECOVER:
  		return "recover";
  	default:
  		return "(unknown PM event)";
  	}
  }
  
  static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info)
  {
  	dev_dbg(dev, "%s%s%s
  ", info, pm_verb(state.event),
  		((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ?
  		", may wakeup" : "");
  }
  
  static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
  			int error)
  {
  	printk(KERN_ERR "PM: Device %s failed to %s%s: error %d
  ",
5c1a07ab3   Rafael J. Wysocki   PM: Use dev_name(...
317
  		dev_name(dev), pm_verb(state.event), info, error);
1eede070a   Rafael J. Wysocki   Introduce new top...
318
  }
ecf762b25   Rafael J. Wysocki   PM: Measure devic...
319
320
321
  static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
  {
  	ktime_t calltime;
0702d9ee0   Kevin Cernekee   PM: Fix signed/un...
322
  	u64 usecs64;
ecf762b25   Rafael J. Wysocki   PM: Measure devic...
323
324
325
326
327
328
329
330
331
332
333
334
335
  	int usecs;
  
  	calltime = ktime_get();
  	usecs64 = ktime_to_ns(ktime_sub(calltime, starttime));
  	do_div(usecs64, NSEC_PER_USEC);
  	usecs = usecs64;
  	if (usecs == 0)
  		usecs = 1;
  	pr_info("PM: %s%s%s of devices complete after %ld.%03ld msecs
  ",
  		info ?: "", info ? " " : "", pm_verb(state.event),
  		usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
  }
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
  static int dpm_run_callback(pm_callback_t cb, struct device *dev,
  			    pm_message_t state, char *info)
  {
  	ktime_t calltime;
  	int error;
  
  	if (!cb)
  		return 0;
  
  	calltime = initcall_debug_start(dev);
  
  	pm_dev_dbg(dev, state, info);
  	error = cb(dev);
  	suspend_report_result(cb, error);
  
  	initcall_debug_report(dev, calltime, error);
  
  	return error;
  }
cd59abfcc   Alan Stern   PM: merge device ...
355
356
357
  /*------------------------- Resume routines -------------------------*/
  
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
358
359
360
   * device_resume_noirq - Execute an "early resume" callback for given device.
   * @dev: Device to handle.
   * @state: PM transition of the system being carried out.
cd59abfcc   Alan Stern   PM: merge device ...
361
   *
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
362
363
   * The driver of @dev will not receive interrupts while this function is being
   * executed.
cd59abfcc   Alan Stern   PM: merge device ...
364
   */
d16163029   Alan Stern   PM core: rename s...
365
  static int device_resume_noirq(struct device *dev, pm_message_t state)
cd59abfcc   Alan Stern   PM: merge device ...
366
  {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
367
368
  	pm_callback_t callback = NULL;
  	char *info = NULL;
cd59abfcc   Alan Stern   PM: merge device ...
369
370
371
372
  	int error = 0;
  
  	TRACE_DEVICE(dev);
  	TRACE_RESUME(0);
564b905ab   Rafael J. Wysocki   PM / Domains: Ren...
373
  	if (dev->pm_domain) {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
374
375
  		info = "EARLY power domain ";
  		callback = pm_noirq_op(&dev->pm_domain->ops, state);
4d27e9dcf   Rafael J. Wysocki   PM: Make power do...
376
  	} else if (dev->type && dev->type->pm) {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
377
378
  		info = "EARLY type ";
  		callback = pm_noirq_op(dev->type->pm, state);
9659cc067   Rafael J. Wysocki   PM: Make system-w...
379
  	} else if (dev->class && dev->class->pm) {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
380
381
  		info = "EARLY class ";
  		callback = pm_noirq_op(dev->class->pm, state);
9659cc067   Rafael J. Wysocki   PM: Make system-w...
382
  	} else if (dev->bus && dev->bus->pm) {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
383
  		info = "EARLY bus ";
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
384
  		callback = pm_noirq_op(dev->bus->pm, state);
e7176a37d   Dominik Brodowski   power: support _n...
385
  	}
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
386
387
388
389
  	if (!callback && dev->driver && dev->driver->pm) {
  		info = "EARLY driver ";
  		callback = pm_noirq_op(dev->driver->pm, state);
  	}
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
390
  	error = dpm_run_callback(callback, dev, state, info);
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
391
392
393
394
395
  	TRACE_RESUME(error);
  	return error;
  }
  
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
396
397
   * dpm_resume_noirq - Execute "early resume" callbacks for non-sysdev devices.
   * @state: PM transition of the system being carried out.
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
398
   *
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
399
400
   * Call the "noirq" resume handlers for all devices marked as DPM_OFF_IRQ and
   * enable device drivers to receive interrupts.
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
401
   */
d16163029   Alan Stern   PM core: rename s...
402
  void dpm_resume_noirq(pm_message_t state)
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
403
  {
ecf762b25   Rafael J. Wysocki   PM: Measure devic...
404
  	ktime_t starttime = ktime_get();
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
405

32bdfac54   Rafael J. Wysocki   PM: Do not hold d...
406
  	mutex_lock(&dpm_list_mtx);
8a43a9ab7   Rafael J. Wysocki   PM: Use a differe...
407
408
  	while (!list_empty(&dpm_noirq_list)) {
  		struct device *dev = to_device(dpm_noirq_list.next);
5b219a51f   Rafael J. Wysocki   PM: Remove redund...
409
  		int error;
d08a5ace1   Rafael J. Wysocki   PM: Allow devices...
410
411
  
  		get_device(dev);
5b219a51f   Rafael J. Wysocki   PM: Remove redund...
412
413
  		list_move_tail(&dev->power.entry, &dpm_suspended_list);
  		mutex_unlock(&dpm_list_mtx);
d08a5ace1   Rafael J. Wysocki   PM: Allow devices...
414

5b219a51f   Rafael J. Wysocki   PM: Remove redund...
415
  		error = device_resume_noirq(dev, state);
2a77c46de   ShuoX Liu   PM / Suspend: Add...
416
417
418
419
  		if (error) {
  			suspend_stats.failed_resume_noirq++;
  			dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
  			dpm_save_failed_dev(dev_name(dev));
5b219a51f   Rafael J. Wysocki   PM: Remove redund...
420
  			pm_dev_err(dev, state, " early", error);
2a77c46de   ShuoX Liu   PM / Suspend: Add...
421
  		}
d08a5ace1   Rafael J. Wysocki   PM: Allow devices...
422

5b219a51f   Rafael J. Wysocki   PM: Remove redund...
423
  		mutex_lock(&dpm_list_mtx);
d08a5ace1   Rafael J. Wysocki   PM: Allow devices...
424
425
  		put_device(dev);
  	}
32bdfac54   Rafael J. Wysocki   PM: Do not hold d...
426
  	mutex_unlock(&dpm_list_mtx);
ecf762b25   Rafael J. Wysocki   PM: Measure devic...
427
  	dpm_show_time(starttime, state, "early");
2ed8d2b3a   Rafael J. Wysocki   PM: Rework handli...
428
  	resume_device_irqs();
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
429
  }
d16163029   Alan Stern   PM core: rename s...
430
  EXPORT_SYMBOL_GPL(dpm_resume_noirq);
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
431
432
  
  /**
97df8c129   Rafael J. Wysocki   PM: Start asynchr...
433
   * device_resume - Execute "resume" callbacks for given device.
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
434
435
   * @dev: Device to handle.
   * @state: PM transition of the system being carried out.
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
436
   * @async: If true, the device is being resumed asynchronously.
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
437
   */
97df8c129   Rafael J. Wysocki   PM: Start asynchr...
438
  static int device_resume(struct device *dev, pm_message_t state, bool async)
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
439
  {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
440
441
  	pm_callback_t callback = NULL;
  	char *info = NULL;
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
442
  	int error = 0;
1e2ef05bb   Rafael J. Wysocki   PM: Limit race co...
443
  	bool put = false;
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
444
445
446
  
  	TRACE_DEVICE(dev);
  	TRACE_RESUME(0);
cd59abfcc   Alan Stern   PM: merge device ...
447

5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
448
  	dpm_wait(dev->parent, async);
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
449
  	device_lock(dev);
7a8d37a37   Rafael J. Wysocki   PM: Do not acquir...
450

f76b168b6   Alan Stern   PM: Rename dev_pm...
451
452
453
454
455
  	/*
  	 * This is a fib.  But we'll allow new children to be added below
  	 * a resumed device, even if the device hasn't been completed yet.
  	 */
  	dev->power.is_prepared = false;
97df8c129   Rafael J. Wysocki   PM: Start asynchr...
456

6d0e0e84f   Alan Stern   PM: Fix async res...
457
458
  	if (!dev->power.is_suspended)
  		goto Unlock;
1e2ef05bb   Rafael J. Wysocki   PM: Limit race co...
459
460
  	pm_runtime_enable(dev);
  	put = true;
564b905ab   Rafael J. Wysocki   PM / Domains: Ren...
461
  	if (dev->pm_domain) {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
462
463
  		info = "power domain ";
  		callback = pm_op(&dev->pm_domain->ops, state);
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
464
  		goto Driver;
7538e3db6   Rafael J. Wysocki   PM: Add support f...
465
  	}
9659cc067   Rafael J. Wysocki   PM: Make system-w...
466
  	if (dev->type && dev->type->pm) {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
467
468
  		info = "type ";
  		callback = pm_op(dev->type->pm, state);
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
469
  		goto Driver;
cd59abfcc   Alan Stern   PM: merge device ...
470
  	}
1eede070a   Rafael J. Wysocki   Introduce new top...
471
472
  	if (dev->class) {
  		if (dev->class->pm) {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
473
474
  			info = "class ";
  			callback = pm_op(dev->class->pm, state);
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
475
  			goto Driver;
1eede070a   Rafael J. Wysocki   Introduce new top...
476
  		} else if (dev->class->resume) {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
477
478
  			info = "legacy class ";
  			callback = dev->class->resume;
9659cc067   Rafael J. Wysocki   PM: Make system-w...
479
  			goto End;
1eede070a   Rafael J. Wysocki   Introduce new top...
480
  		}
cd59abfcc   Alan Stern   PM: merge device ...
481
  	}
9659cc067   Rafael J. Wysocki   PM: Make system-w...
482
483
484
  
  	if (dev->bus) {
  		if (dev->bus->pm) {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
485
  			info = "bus ";
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
486
  			callback = pm_op(dev->bus->pm, state);
9659cc067   Rafael J. Wysocki   PM: Make system-w...
487
  		} else if (dev->bus->resume) {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
488
  			info = "legacy bus ";
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
489
  			callback = dev->bus->resume;
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
490
  			goto End;
9659cc067   Rafael J. Wysocki   PM: Make system-w...
491
492
  		}
  	}
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
493
494
495
496
497
   Driver:
  	if (!callback && dev->driver && dev->driver->pm) {
  		info = "driver ";
  		callback = pm_op(dev->driver->pm, state);
  	}
1eede070a   Rafael J. Wysocki   Introduce new top...
498
   End:
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
499
  	error = dpm_run_callback(callback, dev, state, info);
6d0e0e84f   Alan Stern   PM: Fix async res...
500
501
502
  	dev->power.is_suspended = false;
  
   Unlock:
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
503
  	device_unlock(dev);
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
504
  	complete_all(&dev->power.completion);
7a8d37a37   Rafael J. Wysocki   PM: Do not acquir...
505

cd59abfcc   Alan Stern   PM: merge device ...
506
  	TRACE_RESUME(error);
1e2ef05bb   Rafael J. Wysocki   PM: Limit race co...
507
508
509
  
  	if (put)
  		pm_runtime_put_sync(dev);
cd59abfcc   Alan Stern   PM: merge device ...
510
511
  	return error;
  }
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
512
513
514
515
  static void async_resume(void *data, async_cookie_t cookie)
  {
  	struct device *dev = (struct device *)data;
  	int error;
97df8c129   Rafael J. Wysocki   PM: Start asynchr...
516
  	error = device_resume(dev, pm_transition, true);
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
517
518
519
520
  	if (error)
  		pm_dev_err(dev, pm_transition, " async", error);
  	put_device(dev);
  }
97df8c129   Rafael J. Wysocki   PM: Start asynchr...
521
  static bool is_async(struct device *dev)
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
522
  {
97df8c129   Rafael J. Wysocki   PM: Start asynchr...
523
524
  	return dev->power.async_suspend && pm_async_enabled
  		&& !pm_trace_is_enabled();
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
525
  }
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
526
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
527
528
   * dpm_resume - Execute "resume" callbacks for non-sysdev devices.
   * @state: PM transition of the system being carried out.
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
529
   *
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
530
531
   * Execute the appropriate "resume" callback for all devices whose status
   * indicates that they are suspended.
1eede070a   Rafael J. Wysocki   Introduce new top...
532
   */
91e7c75ba   Rafael J. Wysocki   PM: Allow drivers...
533
  void dpm_resume(pm_message_t state)
1eede070a   Rafael J. Wysocki   Introduce new top...
534
  {
97df8c129   Rafael J. Wysocki   PM: Start asynchr...
535
  	struct device *dev;
ecf762b25   Rafael J. Wysocki   PM: Measure devic...
536
  	ktime_t starttime = ktime_get();
1eede070a   Rafael J. Wysocki   Introduce new top...
537

91e7c75ba   Rafael J. Wysocki   PM: Allow drivers...
538
  	might_sleep();
1eede070a   Rafael J. Wysocki   Introduce new top...
539
  	mutex_lock(&dpm_list_mtx);
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
540
  	pm_transition = state;
098dff738   Rafael J. Wysocki   PM: Fix potential...
541
  	async_error = 0;
1eede070a   Rafael J. Wysocki   Introduce new top...
542

8a43a9ab7   Rafael J. Wysocki   PM: Use a differe...
543
  	list_for_each_entry(dev, &dpm_suspended_list, power.entry) {
97df8c129   Rafael J. Wysocki   PM: Start asynchr...
544
545
546
547
548
549
  		INIT_COMPLETION(dev->power.completion);
  		if (is_async(dev)) {
  			get_device(dev);
  			async_schedule(async_resume, dev);
  		}
  	}
8a43a9ab7   Rafael J. Wysocki   PM: Use a differe...
550
551
  	while (!list_empty(&dpm_suspended_list)) {
  		dev = to_device(dpm_suspended_list.next);
1eede070a   Rafael J. Wysocki   Introduce new top...
552
  		get_device(dev);
5b219a51f   Rafael J. Wysocki   PM: Remove redund...
553
  		if (!is_async(dev)) {
1eede070a   Rafael J. Wysocki   Introduce new top...
554
  			int error;
1eede070a   Rafael J. Wysocki   Introduce new top...
555
  			mutex_unlock(&dpm_list_mtx);
97df8c129   Rafael J. Wysocki   PM: Start asynchr...
556
  			error = device_resume(dev, state, false);
2a77c46de   ShuoX Liu   PM / Suspend: Add...
557
558
559
560
  			if (error) {
  				suspend_stats.failed_resume++;
  				dpm_save_failed_step(SUSPEND_RESUME);
  				dpm_save_failed_dev(dev_name(dev));
1eede070a   Rafael J. Wysocki   Introduce new top...
561
  				pm_dev_err(dev, state, "", error);
2a77c46de   ShuoX Liu   PM / Suspend: Add...
562
  			}
5b219a51f   Rafael J. Wysocki   PM: Remove redund...
563
564
  
  			mutex_lock(&dpm_list_mtx);
1eede070a   Rafael J. Wysocki   Introduce new top...
565
566
  		}
  		if (!list_empty(&dev->power.entry))
8a43a9ab7   Rafael J. Wysocki   PM: Use a differe...
567
  			list_move_tail(&dev->power.entry, &dpm_prepared_list);
1eede070a   Rafael J. Wysocki   Introduce new top...
568
569
  		put_device(dev);
  	}
1eede070a   Rafael J. Wysocki   Introduce new top...
570
  	mutex_unlock(&dpm_list_mtx);
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
571
  	async_synchronize_full();
ecf762b25   Rafael J. Wysocki   PM: Measure devic...
572
  	dpm_show_time(starttime, state, NULL);
1eede070a   Rafael J. Wysocki   Introduce new top...
573
574
575
  }
  
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
576
577
578
   * device_complete - Complete a PM transition for given device.
   * @dev: Device to handle.
   * @state: PM transition of the system being carried out.
1eede070a   Rafael J. Wysocki   Introduce new top...
579
   */
d16163029   Alan Stern   PM core: rename s...
580
  static void device_complete(struct device *dev, pm_message_t state)
1eede070a   Rafael J. Wysocki   Introduce new top...
581
  {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
582
583
  	void (*callback)(struct device *) = NULL;
  	char *info = NULL;
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
584
  	device_lock(dev);
1eede070a   Rafael J. Wysocki   Introduce new top...
585

564b905ab   Rafael J. Wysocki   PM / Domains: Ren...
586
  	if (dev->pm_domain) {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
587
588
  		info = "completing power domain ";
  		callback = dev->pm_domain->ops.complete;
4d27e9dcf   Rafael J. Wysocki   PM: Make power do...
589
  	} else if (dev->type && dev->type->pm) {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
590
591
  		info = "completing type ";
  		callback = dev->type->pm->complete;
9659cc067   Rafael J. Wysocki   PM: Make system-w...
592
  	} else if (dev->class && dev->class->pm) {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
593
594
  		info = "completing class ";
  		callback = dev->class->pm->complete;
9659cc067   Rafael J. Wysocki   PM: Make system-w...
595
  	} else if (dev->bus && dev->bus->pm) {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
596
597
598
599
600
601
602
603
604
605
606
607
  		info = "completing bus ";
  		callback = dev->bus->pm->complete;
  	}
  
  	if (!callback && dev->driver && dev->driver->pm) {
  		info = "completing driver ";
  		callback = dev->driver->pm->complete;
  	}
  
  	if (callback) {
  		pm_dev_dbg(dev, state, info);
  		callback(dev);
1eede070a   Rafael J. Wysocki   Introduce new top...
608
  	}
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
609
  	device_unlock(dev);
1eede070a   Rafael J. Wysocki   Introduce new top...
610
611
612
  }
  
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
613
614
   * dpm_complete - Complete a PM transition for all non-sysdev devices.
   * @state: PM transition of the system being carried out.
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
615
   *
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
616
617
   * Execute the ->complete() callbacks for all devices whose PM status is not
   * DPM_ON (this allows new devices to be registered).
cd59abfcc   Alan Stern   PM: merge device ...
618
   */
91e7c75ba   Rafael J. Wysocki   PM: Allow drivers...
619
  void dpm_complete(pm_message_t state)
cd59abfcc   Alan Stern   PM: merge device ...
620
  {
1eede070a   Rafael J. Wysocki   Introduce new top...
621
  	struct list_head list;
91e7c75ba   Rafael J. Wysocki   PM: Allow drivers...
622
  	might_sleep();
1eede070a   Rafael J. Wysocki   Introduce new top...
623
  	INIT_LIST_HEAD(&list);
cd59abfcc   Alan Stern   PM: merge device ...
624
  	mutex_lock(&dpm_list_mtx);
8a43a9ab7   Rafael J. Wysocki   PM: Use a differe...
625
626
  	while (!list_empty(&dpm_prepared_list)) {
  		struct device *dev = to_device(dpm_prepared_list.prev);
cd59abfcc   Alan Stern   PM: merge device ...
627

1eede070a   Rafael J. Wysocki   Introduce new top...
628
  		get_device(dev);
f76b168b6   Alan Stern   PM: Rename dev_pm...
629
  		dev->power.is_prepared = false;
5b219a51f   Rafael J. Wysocki   PM: Remove redund...
630
631
  		list_move(&dev->power.entry, &list);
  		mutex_unlock(&dpm_list_mtx);
1eede070a   Rafael J. Wysocki   Introduce new top...
632

5b219a51f   Rafael J. Wysocki   PM: Remove redund...
633
  		device_complete(dev, state);
1eede070a   Rafael J. Wysocki   Introduce new top...
634

5b219a51f   Rafael J. Wysocki   PM: Remove redund...
635
  		mutex_lock(&dpm_list_mtx);
1eede070a   Rafael J. Wysocki   Introduce new top...
636
  		put_device(dev);
cd59abfcc   Alan Stern   PM: merge device ...
637
  	}
1eede070a   Rafael J. Wysocki   Introduce new top...
638
  	list_splice(&list, &dpm_list);
cd59abfcc   Alan Stern   PM: merge device ...
639
640
  	mutex_unlock(&dpm_list_mtx);
  }
cd59abfcc   Alan Stern   PM: merge device ...
641
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
642
643
   * dpm_resume_end - Execute "resume" callbacks and complete system transition.
   * @state: PM transition of the system being carried out.
cd59abfcc   Alan Stern   PM: merge device ...
644
   *
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
645
646
   * Execute "resume" callbacks for all devices and complete the PM transition of
   * the system.
cd59abfcc   Alan Stern   PM: merge device ...
647
   */
d16163029   Alan Stern   PM core: rename s...
648
  void dpm_resume_end(pm_message_t state)
cd59abfcc   Alan Stern   PM: merge device ...
649
  {
1eede070a   Rafael J. Wysocki   Introduce new top...
650
651
  	dpm_resume(state);
  	dpm_complete(state);
cd59abfcc   Alan Stern   PM: merge device ...
652
  }
d16163029   Alan Stern   PM core: rename s...
653
  EXPORT_SYMBOL_GPL(dpm_resume_end);
cd59abfcc   Alan Stern   PM: merge device ...
654
655
656
  
  
  /*------------------------- Suspend routines -------------------------*/
1eede070a   Rafael J. Wysocki   Introduce new top...
657
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
658
659
660
661
662
   * resume_event - Return a "resume" message for given "suspend" sleep state.
   * @sleep_state: PM message representing a sleep state.
   *
   * Return a PM message representing the resume event corresponding to given
   * sleep state.
1eede070a   Rafael J. Wysocki   Introduce new top...
663
664
   */
  static pm_message_t resume_event(pm_message_t sleep_state)
cd59abfcc   Alan Stern   PM: merge device ...
665
  {
1eede070a   Rafael J. Wysocki   Introduce new top...
666
667
668
669
670
671
672
673
  	switch (sleep_state.event) {
  	case PM_EVENT_SUSPEND:
  		return PMSG_RESUME;
  	case PM_EVENT_FREEZE:
  	case PM_EVENT_QUIESCE:
  		return PMSG_RECOVER;
  	case PM_EVENT_HIBERNATE:
  		return PMSG_RESTORE;
cd59abfcc   Alan Stern   PM: merge device ...
674
  	}
1eede070a   Rafael J. Wysocki   Introduce new top...
675
  	return PMSG_ON;
cd59abfcc   Alan Stern   PM: merge device ...
676
677
678
  }
  
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
679
680
681
   * device_suspend_noirq - Execute a "late suspend" callback for given device.
   * @dev: Device to handle.
   * @state: PM transition of the system being carried out.
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
682
   *
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
683
684
   * The driver of @dev will not receive interrupts while this function is being
   * executed.
cd59abfcc   Alan Stern   PM: merge device ...
685
   */
d16163029   Alan Stern   PM core: rename s...
686
  static int device_suspend_noirq(struct device *dev, pm_message_t state)
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
687
  {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
688
689
  	pm_callback_t callback = NULL;
  	char *info = NULL;
e7176a37d   Dominik Brodowski   power: support _n...
690

564b905ab   Rafael J. Wysocki   PM / Domains: Ren...
691
  	if (dev->pm_domain) {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
692
693
  		info = "LATE power domain ";
  		callback = pm_noirq_op(&dev->pm_domain->ops, state);
4d27e9dcf   Rafael J. Wysocki   PM: Make power do...
694
  	} else if (dev->type && dev->type->pm) {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
695
696
  		info = "LATE type ";
  		callback = pm_noirq_op(dev->type->pm, state);
9659cc067   Rafael J. Wysocki   PM: Make system-w...
697
  	} else if (dev->class && dev->class->pm) {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
698
699
  		info = "LATE class ";
  		callback = pm_noirq_op(dev->class->pm, state);
9659cc067   Rafael J. Wysocki   PM: Make system-w...
700
  	} else if (dev->bus && dev->bus->pm) {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
701
  		info = "LATE bus ";
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
702
  		callback = pm_noirq_op(dev->bus->pm, state);
7538e3db6   Rafael J. Wysocki   PM: Add support f...
703
  	}
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
704
705
706
707
  	if (!callback && dev->driver && dev->driver->pm) {
  		info = "LATE driver ";
  		callback = pm_noirq_op(dev->driver->pm, state);
  	}
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
708
  	return dpm_run_callback(callback, dev, state, info);
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
709
710
711
  }
  
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
712
713
   * dpm_suspend_noirq - Execute "late suspend" callbacks for non-sysdev devices.
   * @state: PM transition of the system being carried out.
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
714
   *
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
715
716
   * Prevent device drivers from receiving interrupts and call the "noirq" suspend
   * handlers for all non-sysdev devices.
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
717
   */
d16163029   Alan Stern   PM core: rename s...
718
  int dpm_suspend_noirq(pm_message_t state)
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
719
  {
ecf762b25   Rafael J. Wysocki   PM: Measure devic...
720
  	ktime_t starttime = ktime_get();
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
721
  	int error = 0;
2ed8d2b3a   Rafael J. Wysocki   PM: Rework handli...
722
  	suspend_device_irqs();
32bdfac54   Rafael J. Wysocki   PM: Do not hold d...
723
  	mutex_lock(&dpm_list_mtx);
8a43a9ab7   Rafael J. Wysocki   PM: Use a differe...
724
725
  	while (!list_empty(&dpm_suspended_list)) {
  		struct device *dev = to_device(dpm_suspended_list.prev);
d08a5ace1   Rafael J. Wysocki   PM: Allow devices...
726
727
728
  
  		get_device(dev);
  		mutex_unlock(&dpm_list_mtx);
d16163029   Alan Stern   PM core: rename s...
729
  		error = device_suspend_noirq(dev, state);
d08a5ace1   Rafael J. Wysocki   PM: Allow devices...
730
731
  
  		mutex_lock(&dpm_list_mtx);
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
732
  		if (error) {
1eede070a   Rafael J. Wysocki   Introduce new top...
733
  			pm_dev_err(dev, state, " late", error);
2a77c46de   ShuoX Liu   PM / Suspend: Add...
734
735
736
  			suspend_stats.failed_suspend_noirq++;
  			dpm_save_failed_step(SUSPEND_SUSPEND_NOIRQ);
  			dpm_save_failed_dev(dev_name(dev));
d08a5ace1   Rafael J. Wysocki   PM: Allow devices...
737
  			put_device(dev);
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
738
739
  			break;
  		}
d08a5ace1   Rafael J. Wysocki   PM: Allow devices...
740
  		if (!list_empty(&dev->power.entry))
8a43a9ab7   Rafael J. Wysocki   PM: Use a differe...
741
  			list_move(&dev->power.entry, &dpm_noirq_list);
d08a5ace1   Rafael J. Wysocki   PM: Allow devices...
742
  		put_device(dev);
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
743
  	}
32bdfac54   Rafael J. Wysocki   PM: Do not hold d...
744
  	mutex_unlock(&dpm_list_mtx);
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
745
  	if (error)
d16163029   Alan Stern   PM core: rename s...
746
  		dpm_resume_noirq(resume_event(state));
ecf762b25   Rafael J. Wysocki   PM: Measure devic...
747
748
  	else
  		dpm_show_time(starttime, state, "late");
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
749
750
  	return error;
  }
d16163029   Alan Stern   PM core: rename s...
751
  EXPORT_SYMBOL_GPL(dpm_suspend_noirq);
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
752
753
  
  /**
875ab0b74   Rafael J. Wysocki   PM: Make the init...
754
   * legacy_suspend - Execute a legacy (bus or class) suspend callback for device.
0a8842231   Randy Dunlap   power: fix kernel...
755
756
757
   * @dev: Device to suspend.
   * @state: PM transition of the system being carried out.
   * @cb: Suspend callback to execute.
875ab0b74   Rafael J. Wysocki   PM: Make the init...
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
   */
  static int legacy_suspend(struct device *dev, pm_message_t state,
  			  int (*cb)(struct device *dev, pm_message_t state))
  {
  	int error;
  	ktime_t calltime;
  
  	calltime = initcall_debug_start(dev);
  
  	error = cb(dev, state);
  	suspend_report_result(cb, error);
  
  	initcall_debug_report(dev, calltime, error);
  
  	return error;
  }
  
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
776
777
778
   * device_suspend - Execute "suspend" callbacks for given device.
   * @dev: Device to handle.
   * @state: PM transition of the system being carried out.
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
779
   * @async: If true, the device is being suspended asynchronously.
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
780
   */
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
781
  static int __device_suspend(struct device *dev, pm_message_t state, bool async)
cd59abfcc   Alan Stern   PM: merge device ...
782
  {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
783
784
  	pm_callback_t callback = NULL;
  	char *info = NULL;
cd59abfcc   Alan Stern   PM: merge device ...
785
  	int error = 0;
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
786
  	dpm_wait_for_children(dev, async);
7a8d37a37   Rafael J. Wysocki   PM: Do not acquir...
787

5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
788
  	if (async_error)
1e2ef05bb   Rafael J. Wysocki   PM: Limit race co...
789
790
791
792
793
  		return 0;
  
  	pm_runtime_get_noresume(dev);
  	if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
  		pm_wakeup_event(dev, 0);
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
794

d83f905e1   Rafael J. Wysocki   PM: Use pm_wakeup...
795
  	if (pm_wakeup_pending()) {
1e2ef05bb   Rafael J. Wysocki   PM: Limit race co...
796
  		pm_runtime_put_sync(dev);
d83f905e1   Rafael J. Wysocki   PM: Use pm_wakeup...
797
  		async_error = -EBUSY;
1e2ef05bb   Rafael J. Wysocki   PM: Limit race co...
798
  		return 0;
d83f905e1   Rafael J. Wysocki   PM: Use pm_wakeup...
799
  	}
1e2ef05bb   Rafael J. Wysocki   PM: Limit race co...
800
  	device_lock(dev);
564b905ab   Rafael J. Wysocki   PM / Domains: Ren...
801
  	if (dev->pm_domain) {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
802
803
804
  		info = "power domain ";
  		callback = pm_op(&dev->pm_domain->ops, state);
  		goto Run;
4d27e9dcf   Rafael J. Wysocki   PM: Make power do...
805
  	}
9659cc067   Rafael J. Wysocki   PM: Make system-w...
806
  	if (dev->type && dev->type->pm) {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
807
808
809
  		info = "type ";
  		callback = pm_op(dev->type->pm, state);
  		goto Run;
9659cc067   Rafael J. Wysocki   PM: Make system-w...
810
  	}
1eede070a   Rafael J. Wysocki   Introduce new top...
811
812
  	if (dev->class) {
  		if (dev->class->pm) {
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
813
814
815
  			info = "class ";
  			callback = pm_op(dev->class->pm, state);
  			goto Run;
1eede070a   Rafael J. Wysocki   Introduce new top...
816
817
  		} else if (dev->class->suspend) {
  			pm_dev_dbg(dev, state, "legacy class ");
875ab0b74   Rafael J. Wysocki   PM: Make the init...
818
  			error = legacy_suspend(dev, state, dev->class->suspend);
4d27e9dcf   Rafael J. Wysocki   PM: Make power do...
819
  			goto End;
1eede070a   Rafael J. Wysocki   Introduce new top...
820
  		}
cd59abfcc   Alan Stern   PM: merge device ...
821
  	}
1eede070a   Rafael J. Wysocki   Introduce new top...
822
823
  	if (dev->bus) {
  		if (dev->bus->pm) {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
824
  			info = "bus ";
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
825
  			callback = pm_op(dev->bus->pm, state);
1eede070a   Rafael J. Wysocki   Introduce new top...
826
  		} else if (dev->bus->suspend) {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
827
  			pm_dev_dbg(dev, state, "legacy bus ");
875ab0b74   Rafael J. Wysocki   PM: Make the init...
828
  			error = legacy_suspend(dev, state, dev->bus->suspend);
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
829
  			goto End;
1eede070a   Rafael J. Wysocki   Introduce new top...
830
  		}
7538e3db6   Rafael J. Wysocki   PM: Add support f...
831
  	}
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
832
   Run:
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
833
834
835
836
  	if (!callback && dev->driver && dev->driver->pm) {
  		info = "driver ";
  		callback = pm_op(dev->driver->pm, state);
  	}
9cf519d1c   Rafael J. Wysocki   PM / Sleep: Make ...
837
  	error = dpm_run_callback(callback, dev, state, info);
1eede070a   Rafael J. Wysocki   Introduce new top...
838
   End:
4ca46ff3e   Rafael J. Wysocki   PM / Sleep: Mark ...
839
840
  	if (!error) {
  		dev->power.is_suspended = true;
8b258cc8a   Rafael J. Wysocki   PM Sleep: Do not ...
841
842
  		if (dev->power.wakeup_path
  		    && dev->parent && !dev->parent->power.ignore_children)
4ca46ff3e   Rafael J. Wysocki   PM / Sleep: Mark ...
843
844
  			dev->parent->power.wakeup_path = true;
  	}
6d0e0e84f   Alan Stern   PM: Fix async res...
845

8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
846
  	device_unlock(dev);
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
847
  	complete_all(&dev->power.completion);
7a8d37a37   Rafael J. Wysocki   PM: Do not acquir...
848

1e2ef05bb   Rafael J. Wysocki   PM: Limit race co...
849
850
  	if (error) {
  		pm_runtime_put_sync(dev);
098dff738   Rafael J. Wysocki   PM: Fix potential...
851
  		async_error = error;
1e2ef05bb   Rafael J. Wysocki   PM: Limit race co...
852
853
854
  	} else if (dev->power.is_suspended) {
  		__pm_runtime_disable(dev, false);
  	}
098dff738   Rafael J. Wysocki   PM: Fix potential...
855

cd59abfcc   Alan Stern   PM: merge device ...
856
857
  	return error;
  }
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
858
859
860
861
862
863
  static void async_suspend(void *data, async_cookie_t cookie)
  {
  	struct device *dev = (struct device *)data;
  	int error;
  
  	error = __device_suspend(dev, pm_transition, true);
2a77c46de   ShuoX Liu   PM / Suspend: Add...
864
865
  	if (error) {
  		dpm_save_failed_dev(dev_name(dev));
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
866
  		pm_dev_err(dev, pm_transition, " async", error);
2a77c46de   ShuoX Liu   PM / Suspend: Add...
867
  	}
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
868
869
870
871
872
873
874
  
  	put_device(dev);
  }
  
  static int device_suspend(struct device *dev)
  {
  	INIT_COMPLETION(dev->power.completion);
0e06b4a89   Rafael J. Wysocki   PM: Add a switch ...
875
  	if (pm_async_enabled && dev->power.async_suspend) {
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
876
877
878
879
880
881
882
  		get_device(dev);
  		async_schedule(async_suspend, dev);
  		return 0;
  	}
  
  	return __device_suspend(dev, pm_transition, false);
  }
cd59abfcc   Alan Stern   PM: merge device ...
883
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
884
885
   * dpm_suspend - Execute "suspend" callbacks for all non-sysdev devices.
   * @state: PM transition of the system being carried out.
cd59abfcc   Alan Stern   PM: merge device ...
886
   */
91e7c75ba   Rafael J. Wysocki   PM: Allow drivers...
887
  int dpm_suspend(pm_message_t state)
cd59abfcc   Alan Stern   PM: merge device ...
888
  {
ecf762b25   Rafael J. Wysocki   PM: Measure devic...
889
  	ktime_t starttime = ktime_get();
cd59abfcc   Alan Stern   PM: merge device ...
890
  	int error = 0;
91e7c75ba   Rafael J. Wysocki   PM: Allow drivers...
891
  	might_sleep();
cd59abfcc   Alan Stern   PM: merge device ...
892
  	mutex_lock(&dpm_list_mtx);
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
893
894
  	pm_transition = state;
  	async_error = 0;
8a43a9ab7   Rafael J. Wysocki   PM: Use a differe...
895
896
  	while (!list_empty(&dpm_prepared_list)) {
  		struct device *dev = to_device(dpm_prepared_list.prev);
58aca2322   Rafael J. Wysocki   PM: Handle device...
897

1eede070a   Rafael J. Wysocki   Introduce new top...
898
  		get_device(dev);
cd59abfcc   Alan Stern   PM: merge device ...
899
  		mutex_unlock(&dpm_list_mtx);
1eede070a   Rafael J. Wysocki   Introduce new top...
900

5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
901
  		error = device_suspend(dev);
1eede070a   Rafael J. Wysocki   Introduce new top...
902

1b3cbec1d   Alan Stern   PM: fix new mutex...
903
  		mutex_lock(&dpm_list_mtx);
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
904
  		if (error) {
1eede070a   Rafael J. Wysocki   Introduce new top...
905
  			pm_dev_err(dev, state, "", error);
2a77c46de   ShuoX Liu   PM / Suspend: Add...
906
  			dpm_save_failed_dev(dev_name(dev));
1eede070a   Rafael J. Wysocki   Introduce new top...
907
  			put_device(dev);
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
908
909
  			break;
  		}
7a8d37a37   Rafael J. Wysocki   PM: Do not acquir...
910
  		if (!list_empty(&dev->power.entry))
8a43a9ab7   Rafael J. Wysocki   PM: Use a differe...
911
  			list_move(&dev->power.entry, &dpm_suspended_list);
1eede070a   Rafael J. Wysocki   Introduce new top...
912
  		put_device(dev);
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
913
914
  		if (async_error)
  			break;
cd59abfcc   Alan Stern   PM: merge device ...
915
916
  	}
  	mutex_unlock(&dpm_list_mtx);
5af84b827   Rafael J. Wysocki   PM: Asynchronous ...
917
918
919
  	async_synchronize_full();
  	if (!error)
  		error = async_error;
2a77c46de   ShuoX Liu   PM / Suspend: Add...
920
921
922
923
  	if (error) {
  		suspend_stats.failed_suspend++;
  		dpm_save_failed_step(SUSPEND_SUSPEND);
  	} else
ecf762b25   Rafael J. Wysocki   PM: Measure devic...
924
  		dpm_show_time(starttime, state, NULL);
1eede070a   Rafael J. Wysocki   Introduce new top...
925
926
927
928
  	return error;
  }
  
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
929
930
931
932
933
934
   * device_prepare - Prepare a device for system power transition.
   * @dev: Device to handle.
   * @state: PM transition of the system being carried out.
   *
   * Execute the ->prepare() callback(s) for given device.  No new children of the
   * device may be registered after this function has returned.
1eede070a   Rafael J. Wysocki   Introduce new top...
935
   */
d16163029   Alan Stern   PM core: rename s...
936
  static int device_prepare(struct device *dev, pm_message_t state)
1eede070a   Rafael J. Wysocki   Introduce new top...
937
  {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
938
939
  	int (*callback)(struct device *) = NULL;
  	char *info = NULL;
1eede070a   Rafael J. Wysocki   Introduce new top...
940
  	int error = 0;
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
941
  	device_lock(dev);
1eede070a   Rafael J. Wysocki   Introduce new top...
942

4ca46ff3e   Rafael J. Wysocki   PM / Sleep: Mark ...
943
  	dev->power.wakeup_path = device_may_wakeup(dev);
564b905ab   Rafael J. Wysocki   PM / Domains: Ren...
944
  	if (dev->pm_domain) {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
945
946
  		info = "preparing power domain ";
  		callback = dev->pm_domain->ops.prepare;
4d27e9dcf   Rafael J. Wysocki   PM: Make power do...
947
  	} else if (dev->type && dev->type->pm) {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
948
949
  		info = "preparing type ";
  		callback = dev->type->pm->prepare;
9659cc067   Rafael J. Wysocki   PM: Make system-w...
950
  	} else if (dev->class && dev->class->pm) {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
951
952
  		info = "preparing class ";
  		callback = dev->class->pm->prepare;
9659cc067   Rafael J. Wysocki   PM: Make system-w...
953
  	} else if (dev->bus && dev->bus->pm) {
35cd133c6   Rafael J. Wysocki   PM: Run the drive...
954
955
956
957
958
959
960
961
962
963
964
965
  		info = "preparing bus ";
  		callback = dev->bus->pm->prepare;
  	}
  
  	if (!callback && dev->driver && dev->driver->pm) {
  		info = "preparing driver ";
  		callback = dev->driver->pm->prepare;
  	}
  
  	if (callback) {
  		error = callback(dev);
  		suspend_report_result(callback, error);
1eede070a   Rafael J. Wysocki   Introduce new top...
966
  	}
7538e3db6   Rafael J. Wysocki   PM: Add support f...
967

8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
968
  	device_unlock(dev);
1eede070a   Rafael J. Wysocki   Introduce new top...
969
970
971
  
  	return error;
  }
cd59abfcc   Alan Stern   PM: merge device ...
972

1eede070a   Rafael J. Wysocki   Introduce new top...
973
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
974
975
   * dpm_prepare - Prepare all non-sysdev devices for a system PM transition.
   * @state: PM transition of the system being carried out.
1eede070a   Rafael J. Wysocki   Introduce new top...
976
   *
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
977
   * Execute the ->prepare() callback(s) for all devices.
1eede070a   Rafael J. Wysocki   Introduce new top...
978
   */
91e7c75ba   Rafael J. Wysocki   PM: Allow drivers...
979
  int dpm_prepare(pm_message_t state)
1eede070a   Rafael J. Wysocki   Introduce new top...
980
  {
1eede070a   Rafael J. Wysocki   Introduce new top...
981
  	int error = 0;
91e7c75ba   Rafael J. Wysocki   PM: Allow drivers...
982
  	might_sleep();
1eede070a   Rafael J. Wysocki   Introduce new top...
983
  	mutex_lock(&dpm_list_mtx);
1eede070a   Rafael J. Wysocki   Introduce new top...
984
985
986
987
  	while (!list_empty(&dpm_list)) {
  		struct device *dev = to_device(dpm_list.next);
  
  		get_device(dev);
1eede070a   Rafael J. Wysocki   Introduce new top...
988
  		mutex_unlock(&dpm_list_mtx);
1e2ef05bb   Rafael J. Wysocki   PM: Limit race co...
989
  		error = device_prepare(dev, state);
1eede070a   Rafael J. Wysocki   Introduce new top...
990
991
992
  
  		mutex_lock(&dpm_list_mtx);
  		if (error) {
1eede070a   Rafael J. Wysocki   Introduce new top...
993
994
  			if (error == -EAGAIN) {
  				put_device(dev);
886a7a337   Sebastian Ott   PM: Clear -EAGAIN...
995
  				error = 0;
1eede070a   Rafael J. Wysocki   Introduce new top...
996
997
  				continue;
  			}
1e75227ef   Rafael J. Wysocki   PM: Prevent dpm_p...
998
999
1000
  			printk(KERN_INFO "PM: Device %s not prepared "
  				"for power transition: code %d
  ",
5c1a07ab3   Rafael J. Wysocki   PM: Use dev_name(...
1001
  				dev_name(dev), error);
1eede070a   Rafael J. Wysocki   Introduce new top...
1002
1003
1004
  			put_device(dev);
  			break;
  		}
f76b168b6   Alan Stern   PM: Rename dev_pm...
1005
  		dev->power.is_prepared = true;
1eede070a   Rafael J. Wysocki   Introduce new top...
1006
  		if (!list_empty(&dev->power.entry))
8a43a9ab7   Rafael J. Wysocki   PM: Use a differe...
1007
  			list_move_tail(&dev->power.entry, &dpm_prepared_list);
1eede070a   Rafael J. Wysocki   Introduce new top...
1008
1009
  		put_device(dev);
  	}
1eede070a   Rafael J. Wysocki   Introduce new top...
1010
  	mutex_unlock(&dpm_list_mtx);
cd59abfcc   Alan Stern   PM: merge device ...
1011
1012
  	return error;
  }
cd59abfcc   Alan Stern   PM: merge device ...
1013
  /**
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
1014
1015
   * dpm_suspend_start - Prepare devices for PM transition and suspend them.
   * @state: PM transition of the system being carried out.
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
1016
   *
20d652d7d   Rafael J. Wysocki   PM: Update kernel...
1017
1018
   * Prepare all non-sysdev devices for system PM transition and execute "suspend"
   * callbacks for them.
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
1019
   */
d16163029   Alan Stern   PM core: rename s...
1020
  int dpm_suspend_start(pm_message_t state)
775b64d2b   Rafael J. Wysocki   PM: Acquire devic...
1021
1022
  {
  	int error;
cd59abfcc   Alan Stern   PM: merge device ...
1023

1eede070a   Rafael J. Wysocki   Introduce new top...
1024
  	error = dpm_prepare(state);
2a77c46de   ShuoX Liu   PM / Suspend: Add...
1025
1026
1027
1028
  	if (error) {
  		suspend_stats.failed_prepare++;
  		dpm_save_failed_step(SUSPEND_PREPARE);
  	} else
1eede070a   Rafael J. Wysocki   Introduce new top...
1029
  		error = dpm_suspend(state);
cd59abfcc   Alan Stern   PM: merge device ...
1030
  	return error;
cd59abfcc   Alan Stern   PM: merge device ...
1031
  }
d16163029   Alan Stern   PM core: rename s...
1032
  EXPORT_SYMBOL_GPL(dpm_suspend_start);
cd59abfcc   Alan Stern   PM: merge device ...
1033
1034
1035
  
  void __suspend_report_result(const char *function, void *fn, int ret)
  {
c80cfb040   Bjorn Helgaas   vsprintf: use new...
1036
1037
1038
  	if (ret)
  		printk(KERN_ERR "%s(): %pF returns %d
  ", function, fn, ret);
cd59abfcc   Alan Stern   PM: merge device ...
1039
1040
  }
  EXPORT_SYMBOL_GPL(__suspend_report_result);
f8824cee4   Rafael J. Wysocki   PM: Allow device ...
1041
1042
1043
1044
1045
1046
  
  /**
   * device_pm_wait_for_dev - Wait for suspend/resume of a device to complete.
   * @dev: Device to wait for.
   * @subordinate: Device that needs to wait for @dev.
   */
098dff738   Rafael J. Wysocki   PM: Fix potential...
1047
  int device_pm_wait_for_dev(struct device *subordinate, struct device *dev)
f8824cee4   Rafael J. Wysocki   PM: Allow device ...
1048
1049
  {
  	dpm_wait(dev, subordinate->power.async_suspend);
098dff738   Rafael J. Wysocki   PM: Fix potential...
1050
  	return async_error;
f8824cee4   Rafael J. Wysocki   PM: Allow device ...
1051
1052
  }
  EXPORT_SYMBOL_GPL(device_pm_wait_for_dev);