Blame view

drivers/acpi/device_pm.c 36.8 KB
1802d0bee   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
ec2cd81cc   Rafael J. Wysocki   ACPI / PM: Move r...
2
3
4
5
6
7
8
9
  /*
   * drivers/acpi/device_pm.c - ACPI device power management routines.
   *
   * Copyright (C) 2012, Intel Corp.
   * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   *
ec2cd81cc   Rafael J. Wysocki   ACPI / PM: Move r...
10
11
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   */
7b1998116   Rafael J. Wysocki   ACPI / driver cor...
12
  #include <linux/acpi.h>
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
13
  #include <linux/export.h>
ec2cd81cc   Rafael J. Wysocki   ACPI / PM: Move r...
14
  #include <linux/mutex.h>
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
15
  #include <linux/pm_qos.h>
989561de9   Tomeu Vizoso   PM / Domains: add...
16
  #include <linux/pm_domain.h>
cd7bd02d3   Rafael J. Wysocki   ACPI / PM: Move r...
17
  #include <linux/pm_runtime.h>
33e4f80ee   Rafael J. Wysocki   ACPI / PM: Ignore...
18
  #include <linux/suspend.h>
ec2cd81cc   Rafael J. Wysocki   ACPI / PM: Move r...
19

9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
20
21
22
23
  #include "internal.h"
  
  #define _COMPONENT	ACPI_POWER_COMPONENT
  ACPI_MODULE_NAME("device_pm");
ec2cd81cc   Rafael J. Wysocki   ACPI / PM: Move r...
24

86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
25
  /**
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
   * acpi_power_state_string - String representation of ACPI device power state.
   * @state: ACPI device power state to return the string representation of.
   */
  const char *acpi_power_state_string(int state)
  {
  	switch (state) {
  	case ACPI_STATE_D0:
  		return "D0";
  	case ACPI_STATE_D1:
  		return "D1";
  	case ACPI_STATE_D2:
  		return "D2";
  	case ACPI_STATE_D3_HOT:
  		return "D3hot";
  	case ACPI_STATE_D3_COLD:
898fee4f6   Rafael J. Wysocki   ACPI / PM: Use st...
41
  		return "D3cold";
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
42
43
44
45
  	default:
  		return "(unknown)";
  	}
  }
f850a48a0   Rafael J. Wysocki   ACPI: PM: Allow t...
46
47
48
49
50
51
52
53
54
55
56
57
  static int acpi_dev_pm_explicit_get(struct acpi_device *device, int *state)
  {
  	unsigned long long psc;
  	acpi_status status;
  
  	status = acpi_evaluate_integer(device->handle, "_PSC", NULL, &psc);
  	if (ACPI_FAILURE(status))
  		return -ENODEV;
  
  	*state = psc;
  	return 0;
  }
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
58
59
60
61
62
63
64
65
  /**
   * acpi_device_get_power - Get power state of an ACPI device.
   * @device: Device to get the power state of.
   * @state: Place to store the power state of the device.
   *
   * This function does not update the device's power.state field, but it may
   * update its parent's power.state field (when the parent's power state is
   * unknown and the device's power state turns out to be D0).
9ed411c06   Rafael J. Wysocki   ACPI: PM: Unexpor...
66
67
68
69
70
   *
   * Also, it does not update power resource reference counters to ensure that
   * the power state returned by it will be persistent and it may return a power
   * state shallower than previously set by acpi_device_set_power() for @device
   * (if that power state depends on any power resources).
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
71
72
73
74
   */
  int acpi_device_get_power(struct acpi_device *device, int *state)
  {
  	int result = ACPI_STATE_UNKNOWN;
f850a48a0   Rafael J. Wysocki   ACPI: PM: Allow t...
75
  	int error;
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
76
77
78
79
80
81
82
83
84
85
86
87
  
  	if (!device || !state)
  		return -EINVAL;
  
  	if (!device->flags.power_manageable) {
  		/* TBD: Non-recursive algorithm for walking up hierarchy. */
  		*state = device->parent ?
  			device->parent->power.state : ACPI_STATE_D0;
  		goto out;
  	}
  
  	/*
75eb2d13a   Rafael J. Wysocki   ACPI / PM: Fix po...
88
89
  	 * Get the device's power state from power resources settings and _PSC,
  	 * if available.
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
90
  	 */
75eb2d13a   Rafael J. Wysocki   ACPI / PM: Fix po...
91
  	if (device->power.flags.power_resources) {
f850a48a0   Rafael J. Wysocki   ACPI: PM: Allow t...
92
  		error = acpi_power_get_inferred_state(device, &result);
75eb2d13a   Rafael J. Wysocki   ACPI / PM: Fix po...
93
94
95
  		if (error)
  			return error;
  	}
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
96
  	if (device->power.flags.explicit_get) {
f850a48a0   Rafael J. Wysocki   ACPI: PM: Allow t...
97
  		int psc;
75eb2d13a   Rafael J. Wysocki   ACPI / PM: Fix po...
98

f850a48a0   Rafael J. Wysocki   ACPI: PM: Allow t...
99
100
101
  		error = acpi_dev_pm_explicit_get(device, &psc);
  		if (error)
  			return error;
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
102

75eb2d13a   Rafael J. Wysocki   ACPI / PM: Fix po...
103
104
  		/*
  		 * The power resources settings may indicate a power state
20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
105
106
  		 * shallower than the actual power state of the device, because
  		 * the same power resources may be referenced by other devices.
75eb2d13a   Rafael J. Wysocki   ACPI / PM: Fix po...
107
  		 *
20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
108
109
  		 * For systems predating ACPI 4.0 we assume that D3hot is the
  		 * deepest state that can be supported.
75eb2d13a   Rafael J. Wysocki   ACPI / PM: Fix po...
110
111
112
113
  		 */
  		if (psc > result && psc < ACPI_STATE_D3_COLD)
  			result = psc;
  		else if (result == ACPI_STATE_UNKNOWN)
20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
114
  			result = psc > ACPI_STATE_D2 ? ACPI_STATE_D3_HOT : psc;
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
115
116
117
118
119
  	}
  
  	/*
  	 * If we were unsure about the device parent's power state up to this
  	 * point, the fact that the device is in D0 implies that the parent has
644f17ad7   Mika Westerberg   ACPI / PM: allow ...
120
  	 * to be in D0 too, except if ignore_parent is set.
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
121
  	 */
644f17ad7   Mika Westerberg   ACPI / PM: allow ...
122
123
  	if (!device->power.flags.ignore_parent && device->parent
  	    && device->parent->power.state == ACPI_STATE_UNKNOWN
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
124
125
126
127
128
129
130
131
132
133
134
135
  	    && result == ACPI_STATE_D0)
  		device->parent->power.state = ACPI_STATE_D0;
  
  	*state = result;
  
   out:
  	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is %s
  ",
  			  device->pnp.bus_id, acpi_power_state_string(*state)));
  
  	return 0;
  }
9c0f45e38   Rafael J. Wysocki   ACPI / PM: Introd...
136
137
138
139
140
141
142
143
144
145
146
147
  static int acpi_dev_pm_explicit_set(struct acpi_device *adev, int state)
  {
  	if (adev->power.states[state].flags.explicit_set) {
  		char method[5] = { '_', 'P', 'S', '0' + state, '\0' };
  		acpi_status status;
  
  		status = acpi_evaluate_object(adev->handle, method, NULL, NULL);
  		if (ACPI_FAILURE(status))
  			return -ENODEV;
  	}
  	return 0;
  }
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
148
149
150
151
152
153
154
155
156
157
  /**
   * acpi_device_set_power - Set power state of an ACPI device.
   * @device: Device to set the power state of.
   * @state: New power state to set.
   *
   * Callers must ensure that the device is power manageable before using this
   * function.
   */
  int acpi_device_set_power(struct acpi_device *device, int state)
  {
20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
158
  	int target_state = state;
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
159
  	int result = 0;
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
160

2c7d132a5   Rafael J. Wysocki   ACPI / PM: Only s...
161
162
  	if (!device || !device->flags.power_manageable
  	    || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
163
  		return -EINVAL;
ee8193ee9   Rafael J. Wysocki   ACPI: PM: Print d...
164
165
166
167
  	acpi_handle_debug(device->handle, "Power state change: %s -> %s
  ",
  			  acpi_power_state_string(device->power.state),
  			  acpi_power_state_string(state));
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
168
  	/* Make sure this is a valid target state */
f850a48a0   Rafael J. Wysocki   ACPI: PM: Allow t...
169
170
  	/* There is a special case for D0 addressed below. */
  	if (state > ACPI_STATE_D0 && state == device->power.state) {
b69137a74   Rafael J. Wysocki   ACPI / PM: Make m...
171
172
173
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] already in %s
  ",
  				  device->pnp.bus_id,
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
174
175
176
  				  acpi_power_state_string(state)));
  		return 0;
  	}
20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
177
178
179
180
181
182
  	if (state == ACPI_STATE_D3_COLD) {
  		/*
  		 * For transitions to D3cold we need to execute _PS3 and then
  		 * possibly drop references to the power resources in use.
  		 */
  		state = ACPI_STATE_D3_HOT;
956ad9d98   Rafael J. Wysocki   ACPI: PM: Avoid u...
183
  		/* If D3cold is not supported, use D3hot as the target state. */
20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
184
185
186
  		if (!device->power.states[ACPI_STATE_D3_COLD].flags.valid)
  			target_state = state;
  	} else if (!device->power.states[state].flags.valid) {
b69137a74   Rafael J. Wysocki   ACPI / PM: Make m...
187
188
189
  		dev_warn(&device->dev, "Power state %s not supported
  ",
  			 acpi_power_state_string(state));
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
190
191
  		return -ENODEV;
  	}
20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
192

644f17ad7   Mika Westerberg   ACPI / PM: allow ...
193
194
  	if (!device->power.flags.ignore_parent &&
  	    device->parent && (state < device->parent->power.state)) {
b69137a74   Rafael J. Wysocki   ACPI / PM: Make m...
195
  		dev_warn(&device->dev,
593298e68   Aaron Lu   ACPI / PM: Add st...
196
197
198
199
  			 "Cannot transition to power state %s for parent in %s
  ",
  			 acpi_power_state_string(state),
  			 acpi_power_state_string(device->parent->power.state));
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
200
201
  		return -ENODEV;
  	}
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
202
203
204
  	/*
  	 * Transition Power
  	 * ----------------
20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
205
206
207
  	 * In accordance with ACPI 6, _PSx is executed before manipulating power
  	 * resources, unless the target state is D0, in which case _PS0 is
  	 * supposed to be executed after turning the power resources on.
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
208
  	 */
20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
209
210
211
212
213
214
215
216
217
218
219
220
  	if (state > ACPI_STATE_D0) {
  		/*
  		 * According to ACPI 6, devices cannot go from lower-power
  		 * (deeper) states to higher-power (shallower) states.
  		 */
  		if (state < device->power.state) {
  			dev_warn(&device->dev, "Cannot transition from %s to %s
  ",
  				 acpi_power_state_string(device->power.state),
  				 acpi_power_state_string(state));
  			return -ENODEV;
  		}
21ba23792   Rafael J. Wysocki   ACPI: PM: Avoid e...
221
222
223
224
225
226
227
228
229
  		/*
  		 * If the device goes from D3hot to D3cold, _PS3 has been
  		 * evaluated for it already, so skip it in that case.
  		 */
  		if (device->power.state < ACPI_STATE_D3_HOT) {
  			result = acpi_dev_pm_explicit_set(device, state);
  			if (result)
  				goto end;
  		}
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
230

20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
231
232
233
  		if (device->power.flags.power_resources)
  			result = acpi_power_transition(device, target_state);
  	} else {
42787ed79   Rafael J. Wysocki   ACPI: PM: Fix reg...
234
  		int cur_state = device->power.state;
20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
235
236
237
238
239
  		if (device->power.flags.power_resources) {
  			result = acpi_power_transition(device, ACPI_STATE_D0);
  			if (result)
  				goto end;
  		}
f850a48a0   Rafael J. Wysocki   ACPI: PM: Allow t...
240

42787ed79   Rafael J. Wysocki   ACPI: PM: Fix reg...
241
  		if (cur_state == ACPI_STATE_D0) {
f850a48a0   Rafael J. Wysocki   ACPI: PM: Allow t...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
  			int psc;
  
  			/* Nothing to do here if _PSC is not present. */
  			if (!device->power.flags.explicit_get)
  				return 0;
  
  			/*
  			 * The power state of the device was set to D0 last
  			 * time, but that might have happened before a
  			 * system-wide transition involving the platform
  			 * firmware, so it may be necessary to evaluate _PS0
  			 * for the device here.  However, use extra care here
  			 * and evaluate _PSC to check the device's current power
  			 * state, and only invoke _PS0 if the evaluation of _PSC
  			 * is successful and it returns a power state different
  			 * from D0.
  			 */
  			result = acpi_dev_pm_explicit_get(device, &psc);
  			if (result || psc == ACPI_STATE_D0)
  				return 0;
  		}
20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
263
  		result = acpi_dev_pm_explicit_set(device, ACPI_STATE_D0);
e5656271b   Rafael J. Wysocki   ACPI / PM: Fix de...
264
  	}
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
265

e78adb759   Rafael J. Wysocki   ACPI / PM: Always...
266
267
   end:
  	if (result) {
b69137a74   Rafael J. Wysocki   ACPI / PM: Make m...
268
269
  		dev_warn(&device->dev, "Failed to change power state to %s
  ",
a9b760b02   Kai-Heng Feng   PM: ACPI: Output ...
270
  			 acpi_power_state_string(target_state));
e78adb759   Rafael J. Wysocki   ACPI / PM: Always...
271
  	} else {
71b65445f   Mika Westerberg   ACPI / PM: Use ta...
272
  		device->power.state = target_state;
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
273
274
275
276
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  				  "Device [%s] transitioned to %s
  ",
  				  device->pnp.bus_id,
a9b760b02   Kai-Heng Feng   PM: ACPI: Output ...
277
  				  acpi_power_state_string(target_state)));
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
  	}
  
  	return result;
  }
  EXPORT_SYMBOL(acpi_device_set_power);
  
  int acpi_bus_set_power(acpi_handle handle, int state)
  {
  	struct acpi_device *device;
  	int result;
  
  	result = acpi_bus_get_device(handle, &device);
  	if (result)
  		return result;
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
292
293
294
295
296
297
298
299
300
301
302
303
304
  	return acpi_device_set_power(device, state);
  }
  EXPORT_SYMBOL(acpi_bus_set_power);
  
  int acpi_bus_init_power(struct acpi_device *device)
  {
  	int state;
  	int result;
  
  	if (!device)
  		return -EINVAL;
  
  	device->power.state = ACPI_STATE_UNKNOWN;
cde1f95f4   Sakari Ailus   ACPI: Constify ar...
305
306
  	if (!acpi_device_is_present(device)) {
  		device->flags.initialized = false;
1b1f3e169   Rafael J. Wysocki   ACPI / PM: Fix PM...
307
  		return -ENXIO;
cde1f95f4   Sakari Ailus   ACPI: Constify ar...
308
  	}
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
309
310
311
312
  
  	result = acpi_device_get_power(device, &state);
  	if (result)
  		return result;
a2367807b   Rafael J. Wysocki   ACPI / PM: Make a...
313
  	if (state < ACPI_STATE_D3_COLD && device->power.flags.power_resources) {
20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
314
  		/* Reference count the power resources. */
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
315
  		result = acpi_power_on_resources(device, state);
a2367807b   Rafael J. Wysocki   ACPI / PM: Make a...
316
317
  		if (result)
  			return result;
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
318

20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
319
320
321
322
323
324
325
326
327
328
329
330
331
  		if (state == ACPI_STATE_D0) {
  			/*
  			 * If _PSC is not present and the state inferred from
  			 * power resources appears to be D0, it still may be
  			 * necessary to execute _PS0 at this point, because
  			 * another device using the same power resources may
  			 * have been put into D0 previously and that's why we
  			 * see D0 here.
  			 */
  			result = acpi_dev_pm_explicit_set(device, state);
  			if (result)
  				return result;
  		}
b37854922   Rafael J. Wysocki   ACPI / PM: Do not...
332
  	} else if (state == ACPI_STATE_UNKNOWN) {
7cd8407d5   Rafael J. Wysocki   ACPI / PM: Do not...
333
334
335
336
337
338
  		/*
  		 * No power resources and missing _PSC?  Cross fingers and make
  		 * it D0 in hope that this is what the BIOS put the device into.
  		 * [We tried to force D0 here by executing _PS0, but that broke
  		 * Toshiba P870-303 in a nasty way.]
  		 */
b37854922   Rafael J. Wysocki   ACPI / PM: Do not...
339
  		state = ACPI_STATE_D0;
a2367807b   Rafael J. Wysocki   ACPI / PM: Make a...
340
341
342
  	}
  	device->power.state = state;
  	return 0;
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
343
  }
b9e95fc65   Rafael J. Wysocki   ACPI / LPSS: Powe...
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
  /**
   * acpi_device_fix_up_power - Force device with missing _PSC into D0.
   * @device: Device object whose power state is to be fixed up.
   *
   * Devices without power resources and _PSC, but having _PS0 and _PS3 defined,
   * are assumed to be put into D0 by the BIOS.  However, in some cases that may
   * not be the case and this function should be used then.
   */
  int acpi_device_fix_up_power(struct acpi_device *device)
  {
  	int ret = 0;
  
  	if (!device->power.flags.power_resources
  	    && !device->power.flags.explicit_get
  	    && device->power.state == ACPI_STATE_D0)
  		ret = acpi_dev_pm_explicit_set(device, ACPI_STATE_D0);
  
  	return ret;
  }
78a898d0e   Ulf Hansson   ACPI / PM: Export...
363
  EXPORT_SYMBOL_GPL(acpi_device_fix_up_power);
b9e95fc65   Rafael J. Wysocki   ACPI / LPSS: Powe...
364

202317a57   Rafael J. Wysocki   ACPI / scan: Add ...
365
  int acpi_device_update_power(struct acpi_device *device, int *state_p)
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
366
  {
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
367
368
  	int state;
  	int result;
202317a57   Rafael J. Wysocki   ACPI / scan: Add ...
369
370
371
372
  	if (device->power.state == ACPI_STATE_UNKNOWN) {
  		result = acpi_bus_init_power(device);
  		if (!result && state_p)
  			*state_p = device->power.state;
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
373
  		return result;
202317a57   Rafael J. Wysocki   ACPI / scan: Add ...
374
  	}
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
375
376
377
378
  
  	result = acpi_device_get_power(device, &state);
  	if (result)
  		return result;
91bdad0b6   Rafael J. Wysocki   ACPI / PM: Fix co...
379
  	if (state == ACPI_STATE_UNKNOWN) {
511d5c421   Rafael J. Wysocki   ACPI / PM: Handle...
380
  		state = ACPI_STATE_D0;
91bdad0b6   Rafael J. Wysocki   ACPI / PM: Fix co...
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
  		result = acpi_device_set_power(device, state);
  		if (result)
  			return result;
  	} else {
  		if (device->power.flags.power_resources) {
  			/*
  			 * We don't need to really switch the state, bu we need
  			 * to update the power resources' reference counters.
  			 */
  			result = acpi_power_transition(device, state);
  			if (result)
  				return result;
  		}
  		device->power.state = state;
  	}
  	if (state_p)
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
397
  		*state_p = state;
91bdad0b6   Rafael J. Wysocki   ACPI / PM: Fix co...
398
  	return 0;
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
399
  }
2bb3a2bf9   Aaron Lu   ACPI / fan: use a...
400
  EXPORT_SYMBOL_GPL(acpi_device_update_power);
202317a57   Rafael J. Wysocki   ACPI / scan: Add ...
401
402
403
404
405
406
407
408
409
  
  int acpi_bus_update_power(acpi_handle handle, int *state_p)
  {
  	struct acpi_device *device;
  	int result;
  
  	result = acpi_bus_get_device(handle, &device);
  	return result ? result : acpi_device_update_power(device, state_p);
  }
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
410
411
412
413
414
415
416
417
418
419
420
  EXPORT_SYMBOL_GPL(acpi_bus_update_power);
  
  bool acpi_bus_power_manageable(acpi_handle handle)
  {
  	struct acpi_device *device;
  	int result;
  
  	result = acpi_bus_get_device(handle, &device);
  	return result ? false : device->flags.power_manageable;
  }
  EXPORT_SYMBOL(acpi_bus_power_manageable);
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
421
422
  #ifdef CONFIG_PM
  static DEFINE_MUTEX(acpi_pm_notifier_lock);
ff1656790   Ville Syrjälä   ACPI / PM: Fix ac...
423
  static DEFINE_MUTEX(acpi_pm_notifier_install_lock);
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
424

33e4f80ee   Rafael J. Wysocki   ACPI / PM: Ignore...
425
426
427
428
429
  void acpi_pm_wakeup_event(struct device *dev)
  {
  	pm_wakeup_dev_event(dev, 0, acpi_s2idle_wakeup());
  }
  EXPORT_SYMBOL_GPL(acpi_pm_wakeup_event);
c072530f3   Rafael J. Wysocki   ACPI / PM: Revork...
430
431
432
433
434
435
  static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
  {
  	struct acpi_device *adev;
  
  	if (val != ACPI_NOTIFY_DEVICE_WAKE)
  		return;
020a63756   Rafael J. Wysocki   ACPI / PM: Add de...
436
437
  	acpi_handle_debug(handle, "Wake notify
  ");
c072530f3   Rafael J. Wysocki   ACPI / PM: Revork...
438
439
440
441
442
443
444
  	adev = acpi_bus_get_acpi_device(handle);
  	if (!adev)
  		return;
  
  	mutex_lock(&acpi_pm_notifier_lock);
  
  	if (adev->wakeup.flags.notifier_present) {
33e4f80ee   Rafael J. Wysocki   ACPI / PM: Ignore...
445
  		pm_wakeup_ws_event(adev->wakeup.ws, 0, acpi_s2idle_wakeup());
020a63756   Rafael J. Wysocki   ACPI / PM: Add de...
446
  		if (adev->wakeup.context.func) {
d75f773c8   Sakari Ailus   treewide: Switch ...
447
448
  			acpi_handle_debug(handle, "Running %pS for %s
  ",
020a63756   Rafael J. Wysocki   ACPI / PM: Add de...
449
450
  					  adev->wakeup.context.func,
  					  dev_name(adev->wakeup.context.dev));
64fd1c704   Rafael J. Wysocki   ACPI / PM: Run wa...
451
  			adev->wakeup.context.func(&adev->wakeup.context);
020a63756   Rafael J. Wysocki   ACPI / PM: Add de...
452
  		}
c072530f3   Rafael J. Wysocki   ACPI / PM: Revork...
453
454
455
456
457
458
  	}
  
  	mutex_unlock(&acpi_pm_notifier_lock);
  
  	acpi_bus_put_acpi_device(adev);
  }
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
459
  /**
c072530f3   Rafael J. Wysocki   ACPI / PM: Revork...
460
461
462
   * acpi_add_pm_notifier - Register PM notify handler for given ACPI device.
   * @adev: ACPI device to add the notify handler for.
   * @dev: Device to generate a wakeup event for while handling the notification.
64fd1c704   Rafael J. Wysocki   ACPI / PM: Run wa...
463
   * @func: Work function to execute when handling the notification.
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
464
465
466
467
468
469
   *
   * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
   * PM wakeup events.  For example, wakeup events may be generated for bridges
   * if one of the devices below the bridge is signaling wakeup, even if the
   * bridge itself doesn't have a wakeup GPE associated with it.
   */
c072530f3   Rafael J. Wysocki   ACPI / PM: Revork...
470
  acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,
64fd1c704   Rafael J. Wysocki   ACPI / PM: Run wa...
471
  			void (*func)(struct acpi_device_wakeup_context *context))
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
472
473
  {
  	acpi_status status = AE_ALREADY_EXISTS;
64fd1c704   Rafael J. Wysocki   ACPI / PM: Run wa...
474
  	if (!dev && !func)
c072530f3   Rafael J. Wysocki   ACPI / PM: Revork...
475
  		return AE_BAD_PARAMETER;
ff1656790   Ville Syrjälä   ACPI / PM: Fix ac...
476
  	mutex_lock(&acpi_pm_notifier_install_lock);
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
477
478
479
  
  	if (adev->wakeup.flags.notifier_present)
  		goto out;
c072530f3   Rafael J. Wysocki   ACPI / PM: Revork...
480
481
  	status = acpi_install_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY,
  					     acpi_pm_notify_handler, NULL);
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
482
483
  	if (ACPI_FAILURE(status))
  		goto out;
ff1656790   Ville Syrjälä   ACPI / PM: Fix ac...
484
  	mutex_lock(&acpi_pm_notifier_lock);
c8377adfa   Tri Vo   PM / wakeup: Show...
485
486
  	adev->wakeup.ws = wakeup_source_register(&adev->dev,
  						 dev_name(&adev->dev));
ff1656790   Ville Syrjälä   ACPI / PM: Fix ac...
487
488
  	adev->wakeup.context.dev = dev;
  	adev->wakeup.context.func = func;
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
489
  	adev->wakeup.flags.notifier_present = true;
ff1656790   Ville Syrjälä   ACPI / PM: Fix ac...
490
  	mutex_unlock(&acpi_pm_notifier_lock);
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
491
492
  
   out:
ff1656790   Ville Syrjälä   ACPI / PM: Fix ac...
493
  	mutex_unlock(&acpi_pm_notifier_install_lock);
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
494
495
496
497
498
499
500
  	return status;
  }
  
  /**
   * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device.
   * @adev: ACPI device to remove the notifier from.
   */
c072530f3   Rafael J. Wysocki   ACPI / PM: Revork...
501
  acpi_status acpi_remove_pm_notifier(struct acpi_device *adev)
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
502
503
  {
  	acpi_status status = AE_BAD_PARAMETER;
ff1656790   Ville Syrjälä   ACPI / PM: Fix ac...
504
  	mutex_lock(&acpi_pm_notifier_install_lock);
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
505
506
507
508
509
510
  
  	if (!adev->wakeup.flags.notifier_present)
  		goto out;
  
  	status = acpi_remove_notify_handler(adev->handle,
  					    ACPI_SYSTEM_NOTIFY,
c072530f3   Rafael J. Wysocki   ACPI / PM: Revork...
511
  					    acpi_pm_notify_handler);
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
512
513
  	if (ACPI_FAILURE(status))
  		goto out;
ff1656790   Ville Syrjälä   ACPI / PM: Fix ac...
514
  	mutex_lock(&acpi_pm_notifier_lock);
64fd1c704   Rafael J. Wysocki   ACPI / PM: Run wa...
515
  	adev->wakeup.context.func = NULL;
c072530f3   Rafael J. Wysocki   ACPI / PM: Revork...
516
517
  	adev->wakeup.context.dev = NULL;
  	wakeup_source_unregister(adev->wakeup.ws);
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
518
  	adev->wakeup.flags.notifier_present = false;
ff1656790   Ville Syrjälä   ACPI / PM: Fix ac...
519
  	mutex_unlock(&acpi_pm_notifier_lock);
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
520
521
  
   out:
ff1656790   Ville Syrjälä   ACPI / PM: Fix ac...
522
  	mutex_unlock(&acpi_pm_notifier_install_lock);
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
523
524
  	return status;
  }
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
525
526
527
528
529
530
531
532
533
  bool acpi_bus_can_wakeup(acpi_handle handle)
  {
  	struct acpi_device *device;
  	int result;
  
  	result = acpi_bus_get_device(handle, &device);
  	return result ? false : device->wakeup.flags.valid;
  }
  EXPORT_SYMBOL(acpi_bus_can_wakeup);
8370c2dc4   Rafael J. Wysocki   PCI / PM: Drop pm...
534
535
536
537
538
539
  bool acpi_pm_device_can_wakeup(struct device *dev)
  {
  	struct acpi_device *adev = ACPI_COMPANION(dev);
  
  	return adev ? acpi_device_can_wakeup(adev) : false;
  }
9ce4e6071   Rafael J. Wysocki   ACPI / PM: Move d...
540
  /**
b25c77efa   Rafael J. Wysocki   ACPI / PM: Rename...
541
   * acpi_dev_pm_get_state - Get preferred power state of ACPI device.
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
542
543
544
   * @dev: Device whose preferred target power state to return.
   * @adev: ACPI device node corresponding to @dev.
   * @target_state: System state to match the resultant device state.
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
545
546
   * @d_min_p: Location to store the highest power state available to the device.
   * @d_max_p: Location to store the lowest power state available to the device.
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
547
   *
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
548
549
550
551
552
   * Find the lowest power (highest number) and highest power (lowest number) ACPI
   * device power states that the device can be in while the system is in the
   * state represented by @target_state.  Store the integer numbers representing
   * those stats in the memory locations pointed to by @d_max_p and @d_min_p,
   * respectively.
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
553
554
555
   *
   * Callers must ensure that @dev and @adev are valid pointers and that @adev
   * actually corresponds to @dev before using this function.
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
556
557
558
559
   *
   * Returns 0 on success or -ENODATA when one of the ACPI methods fails or
   * returns a value that doesn't make sense.  The memory locations pointed to by
   * @d_max_p and @d_min_p are only modified on success.
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
560
   */
b25c77efa   Rafael J. Wysocki   ACPI / PM: Rename...
561
  static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev,
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
562
  				 u32 target_state, int *d_min_p, int *d_max_p)
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
563
  {
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
564
565
566
567
  	char method[] = { '_', 'S', '0' + target_state, 'D', '\0' };
  	acpi_handle handle = adev->handle;
  	unsigned long long ret;
  	int d_min, d_max;
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
568
  	bool wakeup = false;
bf8c6184e   Daniel Drake   ACPI / PM: Allow ...
569
  	bool has_sxd = false;
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
570
  	acpi_status status;
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
571

86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
572
  	/*
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
573
574
575
576
  	 * If the system state is S0, the lowest power state the device can be
  	 * in is D3cold, unless the device has _S0W and is supposed to signal
  	 * wakeup, in which case the return value of _S0W has to be used as the
  	 * lowest power state available to the device.
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
577
578
  	 */
  	d_min = ACPI_STATE_D0;
4c164ae7d   Rafael J. Wysocki   ACPI / PM: Replac...
579
  	d_max = ACPI_STATE_D3_COLD;
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
580
581
582
583
584
  
  	/*
  	 * If present, _SxD methods return the minimum D-state (highest power
  	 * state) we can use for the corresponding S-states.  Otherwise, the
  	 * minimum D-state is D0 (ACPI 3.x).
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
585
586
  	 */
  	if (target_state > ACPI_STATE_S0) {
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
  		/*
  		 * We rely on acpi_evaluate_integer() not clobbering the integer
  		 * provided if AE_NOT_FOUND is returned.
  		 */
  		ret = d_min;
  		status = acpi_evaluate_integer(handle, method, NULL, &ret);
  		if ((ACPI_FAILURE(status) && status != AE_NOT_FOUND)
  		    || ret > ACPI_STATE_D3_COLD)
  			return -ENODATA;
  
  		/*
  		 * We need to handle legacy systems where D3hot and D3cold are
  		 * the same and 3 is returned in both cases, so fall back to
  		 * D3cold if D3hot is not a valid state.
  		 */
  		if (!adev->power.states[ret].flags.valid) {
  			if (ret == ACPI_STATE_D3_HOT)
  				ret = ACPI_STATE_D3_COLD;
  			else
  				return -ENODATA;
  		}
bf8c6184e   Daniel Drake   ACPI / PM: Allow ...
608
609
610
  
  		if (status == AE_OK)
  			has_sxd = true;
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
611
  		d_min = ret;
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
612
613
  		wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid
  			&& adev->wakeup.sleep_state >= target_state;
20f97caf1   Rafael J. Wysocki   PM / QoS: Drop PM...
614
  	} else {
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
615
616
617
618
619
620
621
622
623
624
625
  		wakeup = adev->wakeup.flags.valid;
  	}
  
  	/*
  	 * If _PRW says we can wake up the system from the target sleep state,
  	 * the D-state returned by _SxD is sufficient for that (we assume a
  	 * wakeup-aware driver if wake is set).  Still, if _SxW exists
  	 * (ACPI 3.x), it should return the maximum (lowest power) D-state that
  	 * can wake the system.  _S0W may be valid, too.
  	 */
  	if (wakeup) {
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
626
627
628
  		method[3] = 'W';
  		status = acpi_evaluate_integer(handle, method, NULL, &ret);
  		if (status == AE_NOT_FOUND) {
bf8c6184e   Daniel Drake   ACPI / PM: Allow ...
629
630
631
632
633
  			/* No _SxW. In this case, the ACPI spec says that we
  			 * must not go into any power state deeper than the
  			 * value returned from _SxD.
  			 */
  			if (has_sxd && target_state > ACPI_STATE_S0)
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
634
  				d_max = d_min;
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
635
636
637
638
639
640
641
642
  		} else if (ACPI_SUCCESS(status) && ret <= ACPI_STATE_D3_COLD) {
  			/* Fall back to D3cold if ret is not a valid state. */
  			if (!adev->power.states[ret].flags.valid)
  				ret = ACPI_STATE_D3_COLD;
  
  			d_max = ret > d_min ? ret : d_min;
  		} else {
  			return -ENODATA;
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
643
644
  		}
  	}
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
645
646
  	if (d_min_p)
  		*d_min_p = d_min;
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
647
648
649
650
651
  
  	if (d_max_p)
  		*d_max_p = d_max;
  
  	return 0;
86b3832c6   Rafael J. Wysocki   ACPI / PM: Move d...
652
  }
cd7bd02d3   Rafael J. Wysocki   ACPI / PM: Move r...
653

a6ae7594b   Rafael J. Wysocki   ACPI / PM: Move d...
654
655
656
657
658
659
  /**
   * acpi_pm_device_sleep_state - Get preferred power state of ACPI device.
   * @dev: Device whose preferred target power state to return.
   * @d_min_p: Location to store the upper limit of the allowed states range.
   * @d_max_in: Deepest low-power state to take into consideration.
   * Return value: Preferred power state of the device on success, -ENODEV
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
660
661
   * if there's no 'struct acpi_device' for @dev, -EINVAL if @d_max_in is
   * incorrect, or -ENODATA on ACPI method failure.
a6ae7594b   Rafael J. Wysocki   ACPI / PM: Move d...
662
663
664
665
666
   *
   * The caller must ensure that @dev is valid before using this function.
   */
  int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
  {
a6ae7594b   Rafael J. Wysocki   ACPI / PM: Move d...
667
  	struct acpi_device *adev;
9b5c7a5a9   Rafael J. Wysocki   ACPI / PM: Fix po...
668
  	int ret, d_min, d_max;
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
669
670
671
  
  	if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3_COLD)
  		return -EINVAL;
20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
672
  	if (d_max_in > ACPI_STATE_D2) {
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
673
674
675
676
  		enum pm_qos_flags_status stat;
  
  		stat = dev_pm_qos_flags(dev, PM_QOS_FLAG_NO_POWER_OFF);
  		if (stat == PM_QOS_FLAGS_ALL)
20dacb71a   Rafael J. Wysocki   ACPI / PM: Rework...
677
  			d_max_in = ACPI_STATE_D2;
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
678
  	}
a6ae7594b   Rafael J. Wysocki   ACPI / PM: Move d...
679

17653a3e0   Rafael J. Wysocki   ACPI / PM: Use AC...
680
681
682
683
  	adev = ACPI_COMPANION(dev);
  	if (!adev) {
  		dev_dbg(dev, "ACPI companion missing in %s!
  ", __func__);
a6ae7594b   Rafael J. Wysocki   ACPI / PM: Move d...
684
685
  		return -ENODEV;
  	}
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
686
  	ret = acpi_dev_pm_get_state(dev, adev, acpi_target_system_state(),
9b5c7a5a9   Rafael J. Wysocki   ACPI / PM: Fix po...
687
  				    &d_min, &d_max);
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
688
689
  	if (ret)
  		return ret;
9b5c7a5a9   Rafael J. Wysocki   ACPI / PM: Fix po...
690
  	if (d_max_in < d_min)
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
691
692
693
  		return -EINVAL;
  
  	if (d_max > d_max_in) {
9b5c7a5a9   Rafael J. Wysocki   ACPI / PM: Fix po...
694
  		for (d_max = d_max_in; d_max > d_min; d_max--) {
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
695
696
697
698
  			if (adev->power.states[d_max].flags.valid)
  				break;
  		}
  	}
9b5c7a5a9   Rafael J. Wysocki   ACPI / PM: Fix po...
699
700
701
  
  	if (d_min_p)
  		*d_min_p = d_min;
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
702
  	return d_max;
a6ae7594b   Rafael J. Wysocki   ACPI / PM: Move d...
703
704
  }
  EXPORT_SYMBOL(acpi_pm_device_sleep_state);
cd7bd02d3   Rafael J. Wysocki   ACPI / PM: Move r...
705
  /**
c072530f3   Rafael J. Wysocki   ACPI / PM: Revork...
706
   * acpi_pm_notify_work_func - ACPI devices wakeup notification work function.
64fd1c704   Rafael J. Wysocki   ACPI / PM: Run wa...
707
   * @context: Device wakeup context.
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
708
   */
64fd1c704   Rafael J. Wysocki   ACPI / PM: Run wa...
709
  static void acpi_pm_notify_work_func(struct acpi_device_wakeup_context *context)
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
710
  {
64fd1c704   Rafael J. Wysocki   ACPI / PM: Run wa...
711
  	struct device *dev = context->dev;
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
712

c072530f3   Rafael J. Wysocki   ACPI / PM: Revork...
713
  	if (dev) {
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
714
  		pm_wakeup_event(dev, 0);
64fd1c704   Rafael J. Wysocki   ACPI / PM: Run wa...
715
  		pm_request_resume(dev);
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
716
717
  	}
  }
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
718
  static DEFINE_MUTEX(acpi_wakeup_lock);
1ba51a7c1   Rafael J. Wysocki   ACPI / PCI / PM: ...
719
  static int __acpi_device_wakeup_enable(struct acpi_device *adev,
0a9801f58   Rafael J. Wysocki   PM: ACPI: PCI: Dr...
720
  				       u32 target_state)
dee8370cc   Rafael J. Wysocki   ACPI / PM: Split ...
721
722
  {
  	struct acpi_device_wakeup *wakeup = &adev->wakeup;
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
723
724
  	acpi_status status;
  	int error = 0;
dee8370cc   Rafael J. Wysocki   ACPI / PM: Split ...
725

99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
726
  	mutex_lock(&acpi_wakeup_lock);
dee8370cc   Rafael J. Wysocki   ACPI / PM: Split ...
727

0a9801f58   Rafael J. Wysocki   PM: ACPI: PCI: Dr...
728
729
730
  	if (wakeup->enable_count >= INT_MAX) {
  		acpi_handle_info(adev->handle, "Wakeup enable count out of bounds!
  ");
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
731
  		goto out;
0a9801f58   Rafael J. Wysocki   PM: ACPI: PCI: Dr...
732
  	}
1ba51a7c1   Rafael J. Wysocki   ACPI / PCI / PM: ...
733
734
  	if (wakeup->enable_count > 0)
  		goto inc;
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
735
736
737
  	error = acpi_enable_wakeup_device_power(adev, target_state);
  	if (error)
  		goto out;
dee8370cc   Rafael J. Wysocki   ACPI / PM: Split ...
738

99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
739
740
  	status = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number);
  	if (ACPI_FAILURE(status)) {
dee8370cc   Rafael J. Wysocki   ACPI / PM: Split ...
741
  		acpi_disable_wakeup_device_power(adev);
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
742
743
  		error = -EIO;
  		goto out;
dee8370cc   Rafael J. Wysocki   ACPI / PM: Split ...
744
  	}
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
745

fbc9418f0   Rafael J. Wysocki   ACPI: PM: Print d...
746
747
748
  	acpi_handle_debug(adev->handle, "GPE%2X enabled for wakeup
  ",
  			  (unsigned int)wakeup->gpe_number);
1ba51a7c1   Rafael J. Wysocki   ACPI / PCI / PM: ...
749
  inc:
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
750
751
752
753
754
755
756
757
  	wakeup->enable_count++;
  
  out:
  	mutex_unlock(&acpi_wakeup_lock);
  	return error;
  }
  
  /**
1ba51a7c1   Rafael J. Wysocki   ACPI / PCI / PM: ...
758
759
760
761
762
763
764
765
766
767
768
769
770
   * acpi_device_wakeup_enable - Enable wakeup functionality for device.
   * @adev: ACPI device to enable wakeup functionality for.
   * @target_state: State the system is transitioning into.
   *
   * Enable the GPE associated with @adev so that it can generate wakeup signals
   * for the device in response to external (remote) events and enable wakeup
   * power for it.
   *
   * Callers must ensure that @adev is a valid ACPI device node before executing
   * this function.
   */
  static int acpi_device_wakeup_enable(struct acpi_device *adev, u32 target_state)
  {
0a9801f58   Rafael J. Wysocki   PM: ACPI: PCI: Dr...
771
  	return __acpi_device_wakeup_enable(adev, target_state);
1ba51a7c1   Rafael J. Wysocki   ACPI / PCI / PM: ...
772
773
774
  }
  
  /**
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
   * acpi_device_wakeup_disable - Disable wakeup functionality for device.
   * @adev: ACPI device to disable wakeup functionality for.
   *
   * Disable the GPE associated with @adev and disable wakeup power for it.
   *
   * Callers must ensure that @adev is a valid ACPI device node before executing
   * this function.
   */
  static void acpi_device_wakeup_disable(struct acpi_device *adev)
  {
  	struct acpi_device_wakeup *wakeup = &adev->wakeup;
  
  	mutex_lock(&acpi_wakeup_lock);
  
  	if (!wakeup->enable_count)
  		goto out;
  
  	acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number);
  	acpi_disable_wakeup_device_power(adev);
  
  	wakeup->enable_count--;
  
  out:
  	mutex_unlock(&acpi_wakeup_lock);
dee8370cc   Rafael J. Wysocki   ACPI / PM: Split ...
799
  }
0a9801f58   Rafael J. Wysocki   PM: ACPI: PCI: Dr...
800
801
802
803
804
805
  /**
   * acpi_pm_set_device_wakeup - Enable/disable remote wakeup for given device.
   * @dev: Device to enable/disable to generate wakeup events.
   * @enable: Whether to enable or disable the wakeup functionality.
   */
  int acpi_pm_set_device_wakeup(struct device *dev, bool enable)
a6ae7594b   Rafael J. Wysocki   ACPI / PM: Move d...
806
  {
a6ae7594b   Rafael J. Wysocki   ACPI / PM: Move d...
807
808
  	struct acpi_device *adev;
  	int error;
17653a3e0   Rafael J. Wysocki   ACPI / PM: Use AC...
809
810
811
812
  	adev = ACPI_COMPANION(dev);
  	if (!adev) {
  		dev_dbg(dev, "ACPI companion missing in %s!
  ", __func__);
a6ae7594b   Rafael J. Wysocki   ACPI / PM: Move d...
813
814
  		return -ENODEV;
  	}
4d183d041   Rafael J. Wysocki   ACPI / PM: Consol...
815
816
  	if (!acpi_device_can_wakeup(adev))
  		return -EINVAL;
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
817
818
819
820
821
822
  	if (!enable) {
  		acpi_device_wakeup_disable(adev);
  		dev_dbg(dev, "Wakeup disabled by ACPI
  ");
  		return 0;
  	}
0a9801f58   Rafael J. Wysocki   PM: ACPI: PCI: Dr...
823
  	error = __acpi_device_wakeup_enable(adev, acpi_target_system_state());
a6ae7594b   Rafael J. Wysocki   ACPI / PM: Move d...
824
  	if (!error)
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
825
826
  		dev_dbg(dev, "Wakeup enabled by ACPI
  ");
a6ae7594b   Rafael J. Wysocki   ACPI / PM: Move d...
827
828
829
  
  	return error;
  }
1ba51a7c1   Rafael J. Wysocki   ACPI / PCI / PM: ...
830
831
832
  EXPORT_SYMBOL_GPL(acpi_pm_set_device_wakeup);
  
  /**
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
833
834
835
836
837
838
839
840
   * acpi_dev_pm_low_power - Put ACPI device into a low-power state.
   * @dev: Device to put into a low-power state.
   * @adev: ACPI device node corresponding to @dev.
   * @system_state: System state to choose the device state for.
   */
  static int acpi_dev_pm_low_power(struct device *dev, struct acpi_device *adev,
  				 u32 system_state)
  {
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
841
  	int ret, state;
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
842
843
844
  
  	if (!acpi_device_power_manageable(adev))
  		return 0;
fa1675b56   Rafael J. Wysocki   ACPI / PM: Rework...
845
846
  	ret = acpi_dev_pm_get_state(dev, adev, system_state, NULL, &state);
  	return ret ? ret : acpi_device_set_power(adev, state);
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
847
848
849
850
851
852
853
854
855
856
857
  }
  
  /**
   * acpi_dev_pm_full_power - Put ACPI device into the full-power state.
   * @adev: ACPI device node to put into the full-power state.
   */
  static int acpi_dev_pm_full_power(struct acpi_device *adev)
  {
  	return acpi_device_power_manageable(adev) ?
  		acpi_device_set_power(adev, ACPI_STATE_D0) : 0;
  }
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
858
  /**
cbe25ce37   Rafael J. Wysocki   ACPI / PM: Combin...
859
   * acpi_dev_suspend - Put device into a low-power state using ACPI.
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
860
   * @dev: Device to put into a low-power state.
cbe25ce37   Rafael J. Wysocki   ACPI / PM: Combin...
861
   * @wakeup: Whether or not to enable wakeup for the device.
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
862
   *
cbe25ce37   Rafael J. Wysocki   ACPI / PM: Combin...
863
   * Put the given device into a low-power state using the standard ACPI
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
864
865
866
867
   * mechanism.  Set up remote wakeup if desired, choose the state to put the
   * device into (this checks if remote wakeup is expected to work too), and set
   * the power state of the device.
   */
cbe25ce37   Rafael J. Wysocki   ACPI / PM: Combin...
868
  int acpi_dev_suspend(struct device *dev, bool wakeup)
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
869
  {
79c0373f3   Rafael J. Wysocki   ACPI / PM: Use AC...
870
  	struct acpi_device *adev = ACPI_COMPANION(dev);
cbe25ce37   Rafael J. Wysocki   ACPI / PM: Combin...
871
  	u32 target_state = acpi_target_system_state();
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
872
873
874
875
  	int error;
  
  	if (!adev)
  		return 0;
cbe25ce37   Rafael J. Wysocki   ACPI / PM: Combin...
876
877
  	if (wakeup && acpi_device_can_wakeup(adev)) {
  		error = acpi_device_wakeup_enable(adev, target_state);
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
878
879
  		if (error)
  			return -EAGAIN;
cbe25ce37   Rafael J. Wysocki   ACPI / PM: Combin...
880
881
  	} else {
  		wakeup = false;
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
882
  	}
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
883

cbe25ce37   Rafael J. Wysocki   ACPI / PM: Combin...
884
885
  	error = acpi_dev_pm_low_power(dev, adev, target_state);
  	if (error && wakeup)
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
886
  		acpi_device_wakeup_disable(adev);
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
887
888
889
  
  	return error;
  }
cbe25ce37   Rafael J. Wysocki   ACPI / PM: Combin...
890
  EXPORT_SYMBOL_GPL(acpi_dev_suspend);
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
891
892
  
  /**
63705c406   Rafael J. Wysocki   ACPI / PM: Combin...
893
   * acpi_dev_resume - Put device into the full-power state using ACPI.
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
894
895
896
   * @dev: Device to put into the full-power state.
   *
   * Put the given device into the full-power state using the standard ACPI
63705c406   Rafael J. Wysocki   ACPI / PM: Combin...
897
   * mechanism.  Set the power state of the device to ACPI D0 and disable wakeup.
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
898
   */
63705c406   Rafael J. Wysocki   ACPI / PM: Combin...
899
  int acpi_dev_resume(struct device *dev)
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
900
  {
79c0373f3   Rafael J. Wysocki   ACPI / PM: Use AC...
901
  	struct acpi_device *adev = ACPI_COMPANION(dev);
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
902
903
904
905
906
907
  	int error;
  
  	if (!adev)
  		return 0;
  
  	error = acpi_dev_pm_full_power(adev);
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
908
  	acpi_device_wakeup_disable(adev);
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
909
910
  	return error;
  }
63705c406   Rafael J. Wysocki   ACPI / PM: Combin...
911
  EXPORT_SYMBOL_GPL(acpi_dev_resume);
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
912
913
914
915
916
917
918
919
920
921
922
  
  /**
   * acpi_subsys_runtime_suspend - Suspend device using ACPI.
   * @dev: Device to suspend.
   *
   * Carry out the generic runtime suspend procedure for @dev and use ACPI to put
   * it into a runtime low-power state.
   */
  int acpi_subsys_runtime_suspend(struct device *dev)
  {
  	int ret = pm_generic_runtime_suspend(dev);
cbe25ce37   Rafael J. Wysocki   ACPI / PM: Combin...
923
  	return ret ? ret : acpi_dev_suspend(dev, true);
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
924
925
926
927
928
929
930
931
932
933
934
935
  }
  EXPORT_SYMBOL_GPL(acpi_subsys_runtime_suspend);
  
  /**
   * acpi_subsys_runtime_resume - Resume device using ACPI.
   * @dev: Device to Resume.
   *
   * Use ACPI to put the given device into the full-power state and carry out the
   * generic runtime resume procedure for it.
   */
  int acpi_subsys_runtime_resume(struct device *dev)
  {
63705c406   Rafael J. Wysocki   ACPI / PM: Combin...
936
  	int ret = acpi_dev_resume(dev);
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
937
938
939
  	return ret ? ret : pm_generic_runtime_resume(dev);
  }
  EXPORT_SYMBOL_GPL(acpi_subsys_runtime_resume);
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
940
941
  
  #ifdef CONFIG_PM_SLEEP
c2ebf788f   Ulf Hansson   ACPI / PM: Split ...
942
943
944
945
  static bool acpi_dev_needs_resume(struct device *dev, struct acpi_device *adev)
  {
  	u32 sys_target = acpi_target_system_state();
  	int ret, state;
9a51c6b1f   Rafael J. Wysocki   ACPI/PCI: PM: Add...
946
947
  	if (!pm_runtime_suspended(dev) || !adev || (adev->wakeup.flags.valid &&
  	    device_may_wakeup(dev) != !!adev->wakeup.prepare_count))
c2ebf788f   Ulf Hansson   ACPI / PM: Split ...
948
949
950
951
952
953
954
955
956
957
958
959
960
961
  		return true;
  
  	if (sys_target == ACPI_STATE_S0)
  		return false;
  
  	if (adev->power.flags.dsw_present)
  		return true;
  
  	ret = acpi_dev_pm_get_state(dev, adev, sys_target, NULL, &state);
  	if (ret)
  		return true;
  
  	return state != adev->power.state;
  }
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
962
  /**
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
963
964
965
966
967
   * acpi_subsys_prepare - Prepare device for system transition to a sleep state.
   * @dev: Device to prepare.
   */
  int acpi_subsys_prepare(struct device *dev)
  {
f25c0ae2b   Rafael J. Wysocki   ACPI / PM: Avoid ...
968
  	struct acpi_device *adev = ACPI_COMPANION(dev);
f25c0ae2b   Rafael J. Wysocki   ACPI / PM: Avoid ...
969

08810a411   Rafael J. Wysocki   PM / core: Add NE...
970
971
  	if (dev->driver && dev->driver->pm && dev->driver->pm->prepare) {
  		int ret = dev->driver->pm->prepare(dev);
f25c0ae2b   Rafael J. Wysocki   ACPI / PM: Avoid ...
972

08810a411   Rafael J. Wysocki   PM / core: Add NE...
973
974
975
976
977
978
  		if (ret < 0)
  			return ret;
  
  		if (!ret && dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_PREPARE))
  			return 0;
  	}
f25c0ae2b   Rafael J. Wysocki   ACPI / PM: Avoid ...
979

c2ebf788f   Ulf Hansson   ACPI / PM: Split ...
980
  	return !acpi_dev_needs_resume(dev, adev);
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
981
982
983
984
  }
  EXPORT_SYMBOL_GPL(acpi_subsys_prepare);
  
  /**
e4da817d2   Ulf Hansson   ACPI / PM: Restor...
985
986
987
988
989
990
991
992
993
994
995
   * acpi_subsys_complete - Finalize device's resume during system resume.
   * @dev: Device to handle.
   */
  void acpi_subsys_complete(struct device *dev)
  {
  	pm_generic_complete(dev);
  	/*
  	 * If the device had been runtime-suspended before the system went into
  	 * the sleep state it is going out of and it has never been resumed till
  	 * now, resume it in case the firmware powered it up.
  	 */
db68daff9   Rafael J. Wysocki   ACPI / PM: Suppor...
996
  	if (pm_runtime_suspended(dev) && pm_resume_via_firmware())
e4da817d2   Ulf Hansson   ACPI / PM: Restor...
997
998
999
1000
1001
  		pm_request_resume(dev);
  }
  EXPORT_SYMBOL_GPL(acpi_subsys_complete);
  
  /**
92858c476   Rafael J. Wysocki   ACPI / PM: Resume...
1002
1003
1004
   * acpi_subsys_suspend - Run the device driver's suspend callback.
   * @dev: Device to handle.
   *
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1005
1006
1007
1008
   * Follow PCI and resume devices from runtime suspend before running their
   * system suspend callbacks, unless the driver can cope with runtime-suspended
   * devices during system suspend and there are no ACPI-specific reasons for
   * resuming them.
92858c476   Rafael J. Wysocki   ACPI / PM: Resume...
1009
1010
1011
   */
  int acpi_subsys_suspend(struct device *dev)
  {
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1012
1013
1014
  	if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) ||
  	    acpi_dev_needs_resume(dev, ACPI_COMPANION(dev)))
  		pm_runtime_resume(dev);
92858c476   Rafael J. Wysocki   ACPI / PM: Resume...
1015
1016
  	return pm_generic_suspend(dev);
  }
4cf563c5d   Heikki Krogerus   ACPI / PM: Export...
1017
  EXPORT_SYMBOL_GPL(acpi_subsys_suspend);
92858c476   Rafael J. Wysocki   ACPI / PM: Resume...
1018
1019
  
  /**
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1020
1021
1022
1023
1024
1025
1026
1027
   * acpi_subsys_suspend_late - Suspend device using ACPI.
   * @dev: Device to suspend.
   *
   * Carry out the generic late suspend procedure for @dev and use ACPI to put
   * it into a low-power state during system transition into a sleep state.
   */
  int acpi_subsys_suspend_late(struct device *dev)
  {
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1028
  	int ret;
fa2bfead9   Rafael J. Wysocki   PM: sleep: core: ...
1029
  	if (dev_pm_skip_suspend(dev))
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1030
1031
1032
  		return 0;
  
  	ret = pm_generic_suspend_late(dev);
cbe25ce37   Rafael J. Wysocki   ACPI / PM: Combin...
1033
  	return ret ? ret : acpi_dev_suspend(dev, device_may_wakeup(dev));
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1034
1035
1036
1037
  }
  EXPORT_SYMBOL_GPL(acpi_subsys_suspend_late);
  
  /**
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1038
1039
1040
1041
1042
   * acpi_subsys_suspend_noirq - Run the device driver's "noirq" suspend callback.
   * @dev: Device to suspend.
   */
  int acpi_subsys_suspend_noirq(struct device *dev)
  {
db68daff9   Rafael J. Wysocki   ACPI / PM: Suppor...
1043
  	int ret;
fa2bfead9   Rafael J. Wysocki   PM: sleep: core: ...
1044
  	if (dev_pm_skip_suspend(dev))
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1045
  		return 0;
db68daff9   Rafael J. Wysocki   ACPI / PM: Suppor...
1046
1047
1048
1049
  
  	ret = pm_generic_suspend_noirq(dev);
  	if (ret)
  		return ret;
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1050

db68daff9   Rafael J. Wysocki   ACPI / PM: Suppor...
1051
1052
1053
1054
1055
1056
1057
  	/*
  	 * If the target system sleep state is suspend-to-idle, it is sufficient
  	 * to check whether or not the device's wakeup settings are good for
  	 * runtime PM.  Otherwise, the pm_resume_via_firmware() check will cause
  	 * acpi_subsys_complete() to take care of fixing up the device's state
  	 * anyway, if need be.
  	 */
0fe8a1be5   Rafael J. Wysocki   PM: sleep: core: ...
1058
1059
  	if (device_can_wakeup(dev) && !device_may_wakeup(dev))
  		dev->power.may_skip_resume = false;
db68daff9   Rafael J. Wysocki   ACPI / PM: Suppor...
1060
1061
  
  	return 0;
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1062
1063
1064
1065
1066
1067
1068
  }
  EXPORT_SYMBOL_GPL(acpi_subsys_suspend_noirq);
  
  /**
   * acpi_subsys_resume_noirq - Run the device driver's "noirq" resume callback.
   * @dev: Device to handle.
   */
3cd7957e8   Rafael J. Wysocki   ACPI: PM: Simplif...
1069
  static int acpi_subsys_resume_noirq(struct device *dev)
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1070
  {
76c70cb58   Rafael J. Wysocki   PM: sleep: core: ...
1071
  	if (dev_pm_skip_resume(dev))
db68daff9   Rafael J. Wysocki   ACPI / PM: Suppor...
1072
  		return 0;
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1073
1074
  	return pm_generic_resume_noirq(dev);
  }
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1075
1076
  
  /**
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1077
1078
1079
1080
1081
1082
1083
   * acpi_subsys_resume_early - Resume device using ACPI.
   * @dev: Device to Resume.
   *
   * Use ACPI to put the given device into the full-power state and carry out the
   * generic early resume procedure for it during system transition into the
   * working state.
   */
3cd7957e8   Rafael J. Wysocki   ACPI: PM: Simplif...
1084
  static int acpi_subsys_resume_early(struct device *dev)
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1085
  {
6e176bf8d   Rafael J. Wysocki   PM: sleep: core: ...
1086
  	int ret;
76c70cb58   Rafael J. Wysocki   PM: sleep: core: ...
1087
  	if (dev_pm_skip_resume(dev))
6e176bf8d   Rafael J. Wysocki   PM: sleep: core: ...
1088
1089
1090
  		return 0;
  
  	ret = acpi_dev_resume(dev);
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1091
1092
  	return ret ? ret : pm_generic_resume_early(dev);
  }
92858c476   Rafael J. Wysocki   ACPI / PM: Resume...
1093
1094
1095
1096
1097
1098
1099
1100
  
  /**
   * acpi_subsys_freeze - Run the device driver's freeze callback.
   * @dev: Device to handle.
   */
  int acpi_subsys_freeze(struct device *dev)
  {
  	/*
501debd4a   Rafael J. Wysocki   PM: ACPI/PCI: Res...
1101
1102
1103
1104
1105
1106
  	 * Resume all runtime-suspended devices before creating a snapshot
  	 * image of system memory, because the restore kernel generally cannot
  	 * be expected to always handle them consistently and they need to be
  	 * put into the runtime-active metastate during system resume anyway,
  	 * so it is better to ensure that the state saved in the image will be
  	 * always consistent with that.
92858c476   Rafael J. Wysocki   ACPI / PM: Resume...
1107
  	 */
501debd4a   Rafael J. Wysocki   PM: ACPI/PCI: Res...
1108
  	pm_runtime_resume(dev);
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1109

92858c476   Rafael J. Wysocki   ACPI / PM: Resume...
1110
1111
  	return pm_generic_freeze(dev);
  }
4cf563c5d   Heikki Krogerus   ACPI / PM: Export...
1112
  EXPORT_SYMBOL_GPL(acpi_subsys_freeze);
92858c476   Rafael J. Wysocki   ACPI / PM: Resume...
1113

05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1114
  /**
3cd7957e8   Rafael J. Wysocki   ACPI: PM: Simplif...
1115
1116
   * acpi_subsys_restore_early - Restore device using ACPI.
   * @dev: Device to restore.
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1117
   */
3cd7957e8   Rafael J. Wysocki   ACPI: PM: Simplif...
1118
  int acpi_subsys_restore_early(struct device *dev)
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1119
  {
3cd7957e8   Rafael J. Wysocki   ACPI: PM: Simplif...
1120
1121
  	int ret = acpi_dev_resume(dev);
  	return ret ? ret : pm_generic_restore_early(dev);
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1122
  }
3cd7957e8   Rafael J. Wysocki   ACPI: PM: Simplif...
1123
  EXPORT_SYMBOL_GPL(acpi_subsys_restore_early);
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1124

c95b7595f   Rafael J. Wysocki   ACPI: PM: Introdu...
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
  /**
   * acpi_subsys_poweroff - Run the device driver's poweroff callback.
   * @dev: Device to handle.
   *
   * Follow PCI and resume devices from runtime suspend before running their
   * system poweroff callbacks, unless the driver can cope with runtime-suspended
   * devices during system suspend and there are no ACPI-specific reasons for
   * resuming them.
   */
  int acpi_subsys_poweroff(struct device *dev)
  {
  	if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) ||
  	    acpi_dev_needs_resume(dev, ACPI_COMPANION(dev)))
  		pm_runtime_resume(dev);
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1139

c95b7595f   Rafael J. Wysocki   ACPI: PM: Introdu...
1140
  	return pm_generic_poweroff(dev);
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1141
  }
c95b7595f   Rafael J. Wysocki   ACPI: PM: Introdu...
1142
  EXPORT_SYMBOL_GPL(acpi_subsys_poweroff);
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1143
1144
  
  /**
c95b7595f   Rafael J. Wysocki   ACPI: PM: Introdu...
1145
   * acpi_subsys_poweroff_late - Run the device driver's poweroff callback.
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1146
   * @dev: Device to handle.
c95b7595f   Rafael J. Wysocki   ACPI: PM: Introdu...
1147
1148
1149
   *
   * Carry out the generic late poweroff procedure for @dev and use ACPI to put
   * it into a low-power state during system transition into a sleep state.
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1150
   */
c95b7595f   Rafael J. Wysocki   ACPI: PM: Introdu...
1151
  static int acpi_subsys_poweroff_late(struct device *dev)
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1152
  {
c95b7595f   Rafael J. Wysocki   ACPI: PM: Introdu...
1153
  	int ret;
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1154

fa2bfead9   Rafael J. Wysocki   PM: sleep: core: ...
1155
  	if (dev_pm_skip_suspend(dev))
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1156
  		return 0;
c95b7595f   Rafael J. Wysocki   ACPI: PM: Introdu...
1157
1158
1159
1160
1161
  	ret = pm_generic_poweroff_late(dev);
  	if (ret)
  		return ret;
  
  	return acpi_dev_suspend(dev, device_may_wakeup(dev));
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1162
  }
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1163
1164
  
  /**
c95b7595f   Rafael J. Wysocki   ACPI: PM: Introdu...
1165
1166
   * acpi_subsys_poweroff_noirq - Run the driver's "noirq" poweroff callback.
   * @dev: Device to suspend.
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1167
   */
c95b7595f   Rafael J. Wysocki   ACPI: PM: Introdu...
1168
  static int acpi_subsys_poweroff_noirq(struct device *dev)
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1169
  {
fa2bfead9   Rafael J. Wysocki   PM: sleep: core: ...
1170
  	if (dev_pm_skip_suspend(dev))
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1171
  		return 0;
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1172

c95b7595f   Rafael J. Wysocki   ACPI: PM: Introdu...
1173
  	return pm_generic_poweroff_noirq(dev);
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1174
  }
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1175
1176
1177
1178
  #endif /* CONFIG_PM_SLEEP */
  
  static struct dev_pm_domain acpi_general_pm_domain = {
  	.ops = {
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1179
1180
  		.runtime_suspend = acpi_subsys_runtime_suspend,
  		.runtime_resume = acpi_subsys_runtime_resume,
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1181
1182
  #ifdef CONFIG_PM_SLEEP
  		.prepare = acpi_subsys_prepare,
e4da817d2   Ulf Hansson   ACPI / PM: Restor...
1183
  		.complete = acpi_subsys_complete,
92858c476   Rafael J. Wysocki   ACPI / PM: Resume...
1184
  		.suspend = acpi_subsys_suspend,
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1185
  		.suspend_late = acpi_subsys_suspend_late,
05087360f   Rafael J. Wysocki   ACPI / PM: Take S...
1186
1187
  		.suspend_noirq = acpi_subsys_suspend_noirq,
  		.resume_noirq = acpi_subsys_resume_noirq,
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1188
  		.resume_early = acpi_subsys_resume_early,
92858c476   Rafael J. Wysocki   ACPI / PM: Resume...
1189
  		.freeze = acpi_subsys_freeze,
c95b7595f   Rafael J. Wysocki   ACPI: PM: Introdu...
1190
1191
1192
  		.poweroff = acpi_subsys_poweroff,
  		.poweroff_late = acpi_subsys_poweroff_late,
  		.poweroff_noirq = acpi_subsys_poweroff_noirq,
3cd7957e8   Rafael J. Wysocki   ACPI: PM: Simplif...
1193
  		.restore_early = acpi_subsys_restore_early,
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1194
1195
1196
1197
1198
  #endif
  	},
  };
  
  /**
91d66cd27   Ulf Hansson   ACPI / PM: Conver...
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
   * acpi_dev_pm_detach - Remove ACPI power management from the device.
   * @dev: Device to take care of.
   * @power_off: Whether or not to try to remove power from the device.
   *
   * Remove the device from the general ACPI PM domain and remove its wakeup
   * notifier.  If @power_off is set, additionally remove power from the device if
   * possible.
   *
   * Callers must ensure proper synchronization of this function with power
   * management callbacks.
   */
  static void acpi_dev_pm_detach(struct device *dev, bool power_off)
  {
  	struct acpi_device *adev = ACPI_COMPANION(dev);
  
  	if (adev && dev->pm_domain == &acpi_general_pm_domain) {
989561de9   Tomeu Vizoso   PM / Domains: add...
1215
  		dev_pm_domain_set(dev, NULL);
91d66cd27   Ulf Hansson   ACPI / PM: Conver...
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
  		acpi_remove_pm_notifier(adev);
  		if (power_off) {
  			/*
  			 * If the device's PM QoS resume latency limit or flags
  			 * have been exposed to user space, they have to be
  			 * hidden at this point, so that they don't affect the
  			 * choice of the low-power state to put the device into.
  			 */
  			dev_pm_qos_hide_latency_limit(dev);
  			dev_pm_qos_hide_flags(dev);
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
1226
  			acpi_device_wakeup_disable(adev);
91d66cd27   Ulf Hansson   ACPI / PM: Conver...
1227
1228
1229
1230
1231
1232
  			acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
  		}
  	}
  }
  
  /**
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1233
1234
   * acpi_dev_pm_attach - Prepare device for ACPI power management.
   * @dev: Device to prepare.
b88ce2a41   Rafael J. Wysocki   ACPI / PM: Allow ...
1235
   * @power_on: Whether or not to power on the device.
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1236
1237
1238
   *
   * If @dev has a valid ACPI handle that has a valid struct acpi_device object
   * attached to it, install a wakeup notification handler for the device and
b88ce2a41   Rafael J. Wysocki   ACPI / PM: Allow ...
1239
1240
   * add it to the general ACPI PM domain.  If @power_on is set, the device will
   * be put into the ACPI D0 state before the function returns.
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1241
1242
1243
1244
1245
1246
1247
   *
   * This assumes that the @dev's bus type uses generic power management callbacks
   * (or doesn't use any power management callbacks at all).
   *
   * Callers must ensure proper synchronization of this function with power
   * management callbacks.
   */
b88ce2a41   Rafael J. Wysocki   ACPI / PM: Allow ...
1248
  int acpi_dev_pm_attach(struct device *dev, bool power_on)
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1249
  {
b9ea0bae2   Rafael J. Wysocki   ACPI: PM: Avoid a...
1250
1251
1252
1253
1254
1255
1256
1257
  	/*
  	 * Skip devices whose ACPI companions match the device IDs below,
  	 * because they require special power management handling incompatible
  	 * with the generic ACPI PM domain.
  	 */
  	static const struct acpi_device_id special_pm_ids[] = {
  		{"PNP0C0B", }, /* Generic ACPI fan */
  		{"INT3404", }, /* Fan */
b62c770fe   Gayatri Kammela   ACPI: Update Tige...
1258
  		{"INTC1044", }, /* Fan for Tiger Lake generation */
b9ea0bae2   Rafael J. Wysocki   ACPI: PM: Avoid a...
1259
1260
  		{}
  	};
79c0373f3   Rafael J. Wysocki   ACPI / PM: Use AC...
1261
  	struct acpi_device *adev = ACPI_COMPANION(dev);
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1262

b9ea0bae2   Rafael J. Wysocki   ACPI: PM: Avoid a...
1263
  	if (!adev || !acpi_match_device_ids(adev, special_pm_ids))
919b7308f   Ulf Hansson   PM / Domains: All...
1264
  		return 0;
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1265

712e960f0   Mika Westerberg   ACPI / PM: Attach...
1266
1267
1268
1269
1270
1271
  	/*
  	 * Only attach the power domain to the first device if the
  	 * companion is shared by multiple. This is to prevent doing power
  	 * management twice.
  	 */
  	if (!acpi_device_is_first_physical_node(adev, dev))
919b7308f   Ulf Hansson   PM / Domains: All...
1272
  		return 0;
712e960f0   Mika Westerberg   ACPI / PM: Attach...
1273

c072530f3   Rafael J. Wysocki   ACPI / PM: Revork...
1274
  	acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func);
989561de9   Tomeu Vizoso   PM / Domains: add...
1275
  	dev_pm_domain_set(dev, &acpi_general_pm_domain);
b88ce2a41   Rafael J. Wysocki   ACPI / PM: Allow ...
1276
1277
  	if (power_on) {
  		acpi_dev_pm_full_power(adev);
99d8845e7   Rafael J. Wysocki   ACPI / PM: Split ...
1278
  		acpi_device_wakeup_disable(adev);
b88ce2a41   Rafael J. Wysocki   ACPI / PM: Allow ...
1279
  	}
86f1e15f5   Ulf Hansson   ACPI / PM: Assign...
1280
1281
  
  	dev->pm_domain->detach = acpi_dev_pm_detach;
919b7308f   Ulf Hansson   PM / Domains: All...
1282
  	return 1;
e5cc8ef31   Rafael J. Wysocki   ACPI / PM: Provid...
1283
1284
  }
  EXPORT_SYMBOL_GPL(acpi_dev_pm_attach);
ec4602a95   Rafael J. Wysocki   ACPI / PM: Allow ...
1285
  #endif /* CONFIG_PM */