xref: /openbmc/linux/drivers/acpi/x86/s2idle.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1fef98671SRafael J. Wysocki // SPDX-License-Identifier: GPL-2.0
2fef98671SRafael J. Wysocki /*
3fef98671SRafael J. Wysocki  * Architecture-specific ACPI-based support for suspend-to-idle.
4fef98671SRafael J. Wysocki  *
5fef98671SRafael J. Wysocki  * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
6fef98671SRafael J. Wysocki  * Author: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
7fef98671SRafael J. Wysocki  * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
8fef98671SRafael J. Wysocki  *
9fef98671SRafael J. Wysocki  * On platforms supporting the Low Power S0 Idle interface there is an ACPI
10fef98671SRafael J. Wysocki  * device object with the PNP0D80 compatible device ID (System Power Management
11fef98671SRafael J. Wysocki  * Controller) and a specific _DSM method under it.  That method, if present,
12fef98671SRafael J. Wysocki  * can be used to indicate to the platform that the OS is transitioning into a
13fef98671SRafael J. Wysocki  * low-power state in which certain types of activity are not desirable or that
14fef98671SRafael J. Wysocki  * it is leaving such a state, which allows the platform to adjust its operation
15fef98671SRafael J. Wysocki  * mode accordingly.
16fef98671SRafael J. Wysocki  */
17fef98671SRafael J. Wysocki 
18fef98671SRafael J. Wysocki #include <linux/acpi.h>
19fef98671SRafael J. Wysocki #include <linux/device.h>
20d0f61e89SMario Limonciello #include <linux/dmi.h>
21fef98671SRafael J. Wysocki #include <linux/suspend.h>
22fef98671SRafael J. Wysocki 
23fef98671SRafael J. Wysocki #include "../sleep.h"
24fef98671SRafael J. Wysocki 
25fef98671SRafael J. Wysocki #ifdef CONFIG_SUSPEND
26fef98671SRafael J. Wysocki 
27fef98671SRafael J. Wysocki static bool sleep_no_lps0 __read_mostly;
28fef98671SRafael J. Wysocki module_param(sleep_no_lps0, bool, 0644);
29fef98671SRafael J. Wysocki MODULE_PARM_DESC(sleep_no_lps0, "Do not use the special LPS0 device interface");
30fef98671SRafael J. Wysocki 
31fef98671SRafael J. Wysocki static const struct acpi_device_id lps0_device_ids[] = {
32fef98671SRafael J. Wysocki 	{"PNP0D80", },
33fef98671SRafael J. Wysocki 	{"", },
34fef98671SRafael J. Wysocki };
35fef98671SRafael J. Wysocki 
365dbf5099SPratik Vishwakarma /* Microsoft platform agnostic UUID */
375dbf5099SPratik Vishwakarma #define ACPI_LPS0_DSM_UUID_MICROSOFT      "11e00d56-ce64-47ce-837b-1f898f9aa461"
385dbf5099SPratik Vishwakarma 
39fef98671SRafael J. Wysocki #define ACPI_LPS0_DSM_UUID	"c4eb40a0-6cd2-11e2-bcfd-0800200c9a66"
40fef98671SRafael J. Wysocki 
41fef98671SRafael J. Wysocki #define ACPI_LPS0_GET_DEVICE_CONSTRAINTS	1
42fef98671SRafael J. Wysocki #define ACPI_LPS0_SCREEN_OFF	3
43fef98671SRafael J. Wysocki #define ACPI_LPS0_SCREEN_ON	4
44fef98671SRafael J. Wysocki #define ACPI_LPS0_ENTRY		5
45fef98671SRafael J. Wysocki #define ACPI_LPS0_EXIT		6
465dbf5099SPratik Vishwakarma #define ACPI_LPS0_MS_ENTRY      7
475dbf5099SPratik Vishwakarma #define ACPI_LPS0_MS_EXIT       8
48fef98671SRafael J. Wysocki 
49fef98671SRafael J. Wysocki /* AMD */
50fef98671SRafael J. Wysocki #define ACPI_LPS0_DSM_UUID_AMD      "e3f32452-febc-43ce-9039-932122d37721"
51f59a905bSAlex Deucher #define ACPI_LPS0_ENTRY_AMD         2
52f59a905bSAlex Deucher #define ACPI_LPS0_EXIT_AMD          3
53fef98671SRafael J. Wysocki #define ACPI_LPS0_SCREEN_OFF_AMD    4
54fef98671SRafael J. Wysocki #define ACPI_LPS0_SCREEN_ON_AMD     5
55fef98671SRafael J. Wysocki 
56fef98671SRafael J. Wysocki static acpi_handle lps0_device_handle;
57fef98671SRafael J. Wysocki static guid_t lps0_dsm_guid;
584a012dc8SPratik Vishwakarma static int lps0_dsm_func_mask;
59fef98671SRafael J. Wysocki 
605dbf5099SPratik Vishwakarma static guid_t lps0_dsm_guid_microsoft;
615dbf5099SPratik Vishwakarma static int lps0_dsm_func_mask_microsoft;
62f7540060SMario Limonciello static int lps0_dsm_state;
635dbf5099SPratik Vishwakarma 
64fef98671SRafael J. Wysocki /* Device constraint entry structure */
65fef98671SRafael J. Wysocki struct lpi_device_info {
66fef98671SRafael J. Wysocki 	char *name;
67fef98671SRafael J. Wysocki 	int enabled;
68fef98671SRafael J. Wysocki 	union acpi_object *package;
69fef98671SRafael J. Wysocki };
70fef98671SRafael J. Wysocki 
71fef98671SRafael J. Wysocki /* Constraint package structure */
72fef98671SRafael J. Wysocki struct lpi_device_constraint {
73fef98671SRafael J. Wysocki 	int uid;
74fef98671SRafael J. Wysocki 	int min_dstate;
75fef98671SRafael J. Wysocki 	int function_states;
76fef98671SRafael J. Wysocki };
77fef98671SRafael J. Wysocki 
78fef98671SRafael J. Wysocki struct lpi_constraints {
79fef98671SRafael J. Wysocki 	acpi_handle handle;
80fef98671SRafael J. Wysocki 	int min_dstate;
81fef98671SRafael J. Wysocki };
82fef98671SRafael J. Wysocki 
834a012dc8SPratik Vishwakarma /* AMD Constraint package structure */
84fef98671SRafael J. Wysocki struct lpi_device_constraint_amd {
85fef98671SRafael J. Wysocki 	char *name;
86fef98671SRafael J. Wysocki 	int enabled;
87fef98671SRafael J. Wysocki 	int function_states;
88fef98671SRafael J. Wysocki 	int min_dstate;
89fef98671SRafael J. Wysocki };
90fef98671SRafael J. Wysocki 
9120e1d640SMario Limonciello static LIST_HEAD(lps0_s2idle_devops_head);
9220e1d640SMario Limonciello 
93fef98671SRafael J. Wysocki static struct lpi_constraints *lpi_constraints_table;
94fef98671SRafael J. Wysocki static int lpi_constraints_table_size;
95fef98671SRafael J. Wysocki static int rev_id;
96fef98671SRafael J. Wysocki 
9741233988SAndy Shevchenko #define for_each_lpi_constraint(entry)						\
9841233988SAndy Shevchenko 	for (int i = 0;								\
9941233988SAndy Shevchenko 	     entry = &lpi_constraints_table[i], i < lpi_constraints_table_size;	\
10041233988SAndy Shevchenko 	     i++)
10141233988SAndy Shevchenko 
lpi_device_get_constraints_amd(void)102fef98671SRafael J. Wysocki static void lpi_device_get_constraints_amd(void)
103fef98671SRafael J. Wysocki {
104fef98671SRafael J. Wysocki 	union acpi_object *out_obj;
105fef98671SRafael J. Wysocki 	int i, j, k;
106fef98671SRafael J. Wysocki 
107fef98671SRafael J. Wysocki 	out_obj = acpi_evaluate_dsm_typed(lps0_device_handle, &lps0_dsm_guid,
108904d4a6cSPratik Vishwakarma 					  rev_id, ACPI_LPS0_GET_DEVICE_CONSTRAINTS,
109fef98671SRafael J. Wysocki 					  NULL, ACPI_TYPE_PACKAGE);
110fef98671SRafael J. Wysocki 
111fef98671SRafael J. Wysocki 	acpi_handle_debug(lps0_device_handle, "_DSM function 1 eval %s\n",
112fef98671SRafael J. Wysocki 			  out_obj ? "successful" : "failed");
113fef98671SRafael J. Wysocki 
1144a012dc8SPratik Vishwakarma 	if (!out_obj)
1154a012dc8SPratik Vishwakarma 		return;
1164a012dc8SPratik Vishwakarma 
117fef98671SRafael J. Wysocki 	for (i = 0; i < out_obj->package.count; i++) {
118fef98671SRafael J. Wysocki 		union acpi_object *package = &out_obj->package.elements[i];
119fef98671SRafael J. Wysocki 
120aa7a1bb0SRafael J. Wysocki 		if (package->type == ACPI_TYPE_PACKAGE) {
121883cf0d4SMario Limonciello 			if (lpi_constraints_table) {
122883cf0d4SMario Limonciello 				acpi_handle_err(lps0_device_handle,
123883cf0d4SMario Limonciello 						"Duplicate constraints list\n");
124883cf0d4SMario Limonciello 				goto free_acpi_buffer;
125883cf0d4SMario Limonciello 			}
126883cf0d4SMario Limonciello 
127fef98671SRafael J. Wysocki 			lpi_constraints_table = kcalloc(package->package.count,
128fef98671SRafael J. Wysocki 							sizeof(*lpi_constraints_table),
129fef98671SRafael J. Wysocki 							GFP_KERNEL);
130fef98671SRafael J. Wysocki 
131fef98671SRafael J. Wysocki 			if (!lpi_constraints_table)
132fef98671SRafael J. Wysocki 				goto free_acpi_buffer;
133fef98671SRafael J. Wysocki 
134fef98671SRafael J. Wysocki 			acpi_handle_debug(lps0_device_handle,
135fef98671SRafael J. Wysocki 					  "LPI: constraints list begin:\n");
136fef98671SRafael J. Wysocki 
1373c6b1212SMario Limonciello 			for (j = 0; j < package->package.count; j++) {
138fef98671SRafael J. Wysocki 				union acpi_object *info_obj = &package->package.elements[j];
139fef98671SRafael J. Wysocki 				struct lpi_device_constraint_amd dev_info = {};
140fef98671SRafael J. Wysocki 				struct lpi_constraints *list;
141fef98671SRafael J. Wysocki 				acpi_status status;
142fef98671SRafael J. Wysocki 
1439cc8cd08SMario Limonciello 				list = &lpi_constraints_table[lpi_constraints_table_size];
1449cc8cd08SMario Limonciello 
1453c6b1212SMario Limonciello 				for (k = 0; k < info_obj->package.count; k++) {
146fef98671SRafael J. Wysocki 					union acpi_object *obj = &info_obj->package.elements[k];
147fef98671SRafael J. Wysocki 
148fef98671SRafael J. Wysocki 					switch (k) {
149fef98671SRafael J. Wysocki 					case 0:
150fef98671SRafael J. Wysocki 						dev_info.enabled = obj->integer.value;
151fef98671SRafael J. Wysocki 						break;
152fef98671SRafael J. Wysocki 					case 1:
153fef98671SRafael J. Wysocki 						dev_info.name = obj->string.pointer;
154fef98671SRafael J. Wysocki 						break;
155fef98671SRafael J. Wysocki 					case 2:
156fef98671SRafael J. Wysocki 						dev_info.function_states = obj->integer.value;
157fef98671SRafael J. Wysocki 						break;
158fef98671SRafael J. Wysocki 					case 3:
159fef98671SRafael J. Wysocki 						dev_info.min_dstate = obj->integer.value;
160fef98671SRafael J. Wysocki 						break;
161fef98671SRafael J. Wysocki 					}
1629cc8cd08SMario Limonciello 				}
163fef98671SRafael J. Wysocki 
164a879058dSMario Limonciello 				acpi_handle_debug(lps0_device_handle,
165a879058dSMario Limonciello 						  "Name:%s, Enabled: %d, States: %d, MinDstate: %d\n",
166a879058dSMario Limonciello 						  dev_info.name,
167a879058dSMario Limonciello 						  dev_info.enabled,
168a879058dSMario Limonciello 						  dev_info.function_states,
169a879058dSMario Limonciello 						  dev_info.min_dstate);
170a879058dSMario Limonciello 
171fef98671SRafael J. Wysocki 				if (!dev_info.enabled || !dev_info.name ||
172fef98671SRafael J. Wysocki 				    !dev_info.min_dstate)
173fef98671SRafael J. Wysocki 					continue;
174fef98671SRafael J. Wysocki 
1759cc8cd08SMario Limonciello 				status = acpi_get_handle(NULL, dev_info.name, &list->handle);
176fef98671SRafael J. Wysocki 				if (ACPI_FAILURE(status))
177fef98671SRafael J. Wysocki 					continue;
178fef98671SRafael J. Wysocki 
179fef98671SRafael J. Wysocki 				list->min_dstate = dev_info.min_dstate;
180fef98671SRafael J. Wysocki 
181fef98671SRafael J. Wysocki 				lpi_constraints_table_size++;
182fef98671SRafael J. Wysocki 			}
183fef98671SRafael J. Wysocki 		}
184fef98671SRafael J. Wysocki 	}
185fef98671SRafael J. Wysocki 
186fef98671SRafael J. Wysocki 	acpi_handle_debug(lps0_device_handle, "LPI: constraints list end\n");
187fef98671SRafael J. Wysocki 
188fef98671SRafael J. Wysocki free_acpi_buffer:
189fef98671SRafael J. Wysocki 	ACPI_FREE(out_obj);
190fef98671SRafael J. Wysocki }
191fef98671SRafael J. Wysocki 
lpi_device_get_constraints(void)192fef98671SRafael J. Wysocki static void lpi_device_get_constraints(void)
193fef98671SRafael J. Wysocki {
194fef98671SRafael J. Wysocki 	union acpi_object *out_obj;
195fef98671SRafael J. Wysocki 	int i;
196fef98671SRafael J. Wysocki 
197fef98671SRafael J. Wysocki 	out_obj = acpi_evaluate_dsm_typed(lps0_device_handle, &lps0_dsm_guid,
198fef98671SRafael J. Wysocki 					  1, ACPI_LPS0_GET_DEVICE_CONSTRAINTS,
199fef98671SRafael J. Wysocki 					  NULL, ACPI_TYPE_PACKAGE);
200fef98671SRafael J. Wysocki 
201fef98671SRafael J. Wysocki 	acpi_handle_debug(lps0_device_handle, "_DSM function 1 eval %s\n",
202fef98671SRafael J. Wysocki 			  out_obj ? "successful" : "failed");
203fef98671SRafael J. Wysocki 
204fef98671SRafael J. Wysocki 	if (!out_obj)
205fef98671SRafael J. Wysocki 		return;
206fef98671SRafael J. Wysocki 
207fef98671SRafael J. Wysocki 	lpi_constraints_table = kcalloc(out_obj->package.count,
208fef98671SRafael J. Wysocki 					sizeof(*lpi_constraints_table),
209fef98671SRafael J. Wysocki 					GFP_KERNEL);
210fef98671SRafael J. Wysocki 	if (!lpi_constraints_table)
211fef98671SRafael J. Wysocki 		goto free_acpi_buffer;
212fef98671SRafael J. Wysocki 
213fef98671SRafael J. Wysocki 	acpi_handle_debug(lps0_device_handle, "LPI: constraints list begin:\n");
214fef98671SRafael J. Wysocki 
215fef98671SRafael J. Wysocki 	for (i = 0; i < out_obj->package.count; i++) {
216fef98671SRafael J. Wysocki 		struct lpi_constraints *constraint;
217fef98671SRafael J. Wysocki 		acpi_status status;
218fef98671SRafael J. Wysocki 		union acpi_object *package = &out_obj->package.elements[i];
219fef98671SRafael J. Wysocki 		struct lpi_device_info info = { };
220fef98671SRafael J. Wysocki 		int package_count = 0, j;
221fef98671SRafael J. Wysocki 
222fef98671SRafael J. Wysocki 		if (!package)
223fef98671SRafael J. Wysocki 			continue;
224fef98671SRafael J. Wysocki 
2253c6b1212SMario Limonciello 		for (j = 0; j < package->package.count; j++) {
226fef98671SRafael J. Wysocki 			union acpi_object *element =
227fef98671SRafael J. Wysocki 					&(package->package.elements[j]);
228fef98671SRafael J. Wysocki 
229fef98671SRafael J. Wysocki 			switch (element->type) {
230fef98671SRafael J. Wysocki 			case ACPI_TYPE_INTEGER:
231fef98671SRafael J. Wysocki 				info.enabled = element->integer.value;
232fef98671SRafael J. Wysocki 				break;
233fef98671SRafael J. Wysocki 			case ACPI_TYPE_STRING:
234fef98671SRafael J. Wysocki 				info.name = element->string.pointer;
235fef98671SRafael J. Wysocki 				break;
236fef98671SRafael J. Wysocki 			case ACPI_TYPE_PACKAGE:
237fef98671SRafael J. Wysocki 				package_count = element->package.count;
238fef98671SRafael J. Wysocki 				info.package = element->package.elements;
239fef98671SRafael J. Wysocki 				break;
240fef98671SRafael J. Wysocki 			}
241fef98671SRafael J. Wysocki 		}
242fef98671SRafael J. Wysocki 
243fef98671SRafael J. Wysocki 		if (!info.enabled || !info.package || !info.name)
244fef98671SRafael J. Wysocki 			continue;
245fef98671SRafael J. Wysocki 
246fef98671SRafael J. Wysocki 		constraint = &lpi_constraints_table[lpi_constraints_table_size];
247fef98671SRafael J. Wysocki 
248fef98671SRafael J. Wysocki 		status = acpi_get_handle(NULL, info.name, &constraint->handle);
249fef98671SRafael J. Wysocki 		if (ACPI_FAILURE(status))
250fef98671SRafael J. Wysocki 			continue;
251fef98671SRafael J. Wysocki 
252fef98671SRafael J. Wysocki 		acpi_handle_debug(lps0_device_handle,
253fef98671SRafael J. Wysocki 				  "index:%d Name:%s\n", i, info.name);
254fef98671SRafael J. Wysocki 
255fef98671SRafael J. Wysocki 		constraint->min_dstate = -1;
256fef98671SRafael J. Wysocki 
2573c6b1212SMario Limonciello 		for (j = 0; j < package_count; j++) {
258fef98671SRafael J. Wysocki 			union acpi_object *info_obj = &info.package[j];
259fef98671SRafael J. Wysocki 			union acpi_object *cnstr_pkg;
260fef98671SRafael J. Wysocki 			union acpi_object *obj;
261fef98671SRafael J. Wysocki 			struct lpi_device_constraint dev_info;
262fef98671SRafael J. Wysocki 
263fef98671SRafael J. Wysocki 			switch (info_obj->type) {
264fef98671SRafael J. Wysocki 			case ACPI_TYPE_INTEGER:
265fef98671SRafael J. Wysocki 				/* version */
266fef98671SRafael J. Wysocki 				break;
267fef98671SRafael J. Wysocki 			case ACPI_TYPE_PACKAGE:
268fef98671SRafael J. Wysocki 				if (info_obj->package.count < 2)
269fef98671SRafael J. Wysocki 					break;
270fef98671SRafael J. Wysocki 
271fef98671SRafael J. Wysocki 				cnstr_pkg = info_obj->package.elements;
272fef98671SRafael J. Wysocki 				obj = &cnstr_pkg[0];
273fef98671SRafael J. Wysocki 				dev_info.uid = obj->integer.value;
274fef98671SRafael J. Wysocki 				obj = &cnstr_pkg[1];
275fef98671SRafael J. Wysocki 				dev_info.min_dstate = obj->integer.value;
276fef98671SRafael J. Wysocki 
277fef98671SRafael J. Wysocki 				acpi_handle_debug(lps0_device_handle,
278fef98671SRafael J. Wysocki 					"uid:%d min_dstate:%s\n",
279fef98671SRafael J. Wysocki 					dev_info.uid,
280fef98671SRafael J. Wysocki 					acpi_power_state_string(dev_info.min_dstate));
281fef98671SRafael J. Wysocki 
282fef98671SRafael J. Wysocki 				constraint->min_dstate = dev_info.min_dstate;
283fef98671SRafael J. Wysocki 				break;
284fef98671SRafael J. Wysocki 			}
285fef98671SRafael J. Wysocki 		}
286fef98671SRafael J. Wysocki 
287fef98671SRafael J. Wysocki 		if (constraint->min_dstate < 0) {
288fef98671SRafael J. Wysocki 			acpi_handle_debug(lps0_device_handle,
289fef98671SRafael J. Wysocki 					  "Incomplete constraint defined\n");
290fef98671SRafael J. Wysocki 			continue;
291fef98671SRafael J. Wysocki 		}
292fef98671SRafael J. Wysocki 
293fef98671SRafael J. Wysocki 		lpi_constraints_table_size++;
294fef98671SRafael J. Wysocki 	}
295fef98671SRafael J. Wysocki 
296fef98671SRafael J. Wysocki 	acpi_handle_debug(lps0_device_handle, "LPI: constraints list end\n");
297fef98671SRafael J. Wysocki 
298fef98671SRafael J. Wysocki free_acpi_buffer:
299fef98671SRafael J. Wysocki 	ACPI_FREE(out_obj);
300fef98671SRafael J. Wysocki }
301fef98671SRafael J. Wysocki 
302*1c2a66d4SMario Limonciello /**
303*1c2a66d4SMario Limonciello  * acpi_get_lps0_constraint - Get the LPS0 constraint for a device.
304*1c2a66d4SMario Limonciello  * @adev: Device to get the constraint for.
305*1c2a66d4SMario Limonciello  *
306*1c2a66d4SMario Limonciello  * The LPS0 constraint is the shallowest (minimum) power state in which the
307*1c2a66d4SMario Limonciello  * device can be so as to allow the platform as a whole to achieve additional
308*1c2a66d4SMario Limonciello  * energy conservation by utilizing a system-wide low-power state.
309*1c2a66d4SMario Limonciello  *
310*1c2a66d4SMario Limonciello  * Returns:
311*1c2a66d4SMario Limonciello  *  - ACPI power state value of the constraint for @adev on success.
312*1c2a66d4SMario Limonciello  *  - Otherwise, ACPI_STATE_UNKNOWN.
313*1c2a66d4SMario Limonciello  */
acpi_get_lps0_constraint(struct acpi_device * adev)314*1c2a66d4SMario Limonciello int acpi_get_lps0_constraint(struct acpi_device *adev)
315*1c2a66d4SMario Limonciello {
316*1c2a66d4SMario Limonciello 	struct lpi_constraints *entry;
317*1c2a66d4SMario Limonciello 
318*1c2a66d4SMario Limonciello 	for_each_lpi_constraint(entry) {
319*1c2a66d4SMario Limonciello 		if (adev->handle == entry->handle)
320*1c2a66d4SMario Limonciello 			return entry->min_dstate;
321*1c2a66d4SMario Limonciello 	}
322*1c2a66d4SMario Limonciello 
323*1c2a66d4SMario Limonciello 	return ACPI_STATE_UNKNOWN;
324*1c2a66d4SMario Limonciello }
325*1c2a66d4SMario Limonciello 
lpi_check_constraints(void)326fef98671SRafael J. Wysocki static void lpi_check_constraints(void)
327fef98671SRafael J. Wysocki {
32841233988SAndy Shevchenko 	struct lpi_constraints *entry;
329fef98671SRafael J. Wysocki 
33041233988SAndy Shevchenko 	for_each_lpi_constraint(entry) {
33141233988SAndy Shevchenko 		struct acpi_device *adev = acpi_fetch_acpi_dev(entry->handle);
332fef98671SRafael J. Wysocki 
33399ece713SRafael J. Wysocki 		if (!adev)
334fef98671SRafael J. Wysocki 			continue;
335fef98671SRafael J. Wysocki 
33641233988SAndy Shevchenko 		acpi_handle_debug(entry->handle,
337fef98671SRafael J. Wysocki 			"LPI: required min power state:%s current power state:%s\n",
33841233988SAndy Shevchenko 			acpi_power_state_string(entry->min_dstate),
339fef98671SRafael J. Wysocki 			acpi_power_state_string(adev->power.state));
340fef98671SRafael J. Wysocki 
341fef98671SRafael J. Wysocki 		if (!adev->flags.power_manageable) {
34241233988SAndy Shevchenko 			acpi_handle_info(entry->handle, "LPI: Device not power manageable\n");
34341233988SAndy Shevchenko 			entry->handle = NULL;
344fef98671SRafael J. Wysocki 			continue;
345fef98671SRafael J. Wysocki 		}
346fef98671SRafael J. Wysocki 
34741233988SAndy Shevchenko 		if (adev->power.state < entry->min_dstate)
34841233988SAndy Shevchenko 			acpi_handle_info(entry->handle,
349fef98671SRafael J. Wysocki 				"LPI: Constraint not met; min power state:%s current power state:%s\n",
35041233988SAndy Shevchenko 				acpi_power_state_string(entry->min_dstate),
351fef98671SRafael J. Wysocki 				acpi_power_state_string(adev->power.state));
352fef98671SRafael J. Wysocki 	}
353fef98671SRafael J. Wysocki }
354fef98671SRafael J. Wysocki 
acpi_s2idle_vendor_amd(void)355f7540060SMario Limonciello static bool acpi_s2idle_vendor_amd(void)
356f7540060SMario Limonciello {
357f7540060SMario Limonciello 	return boot_cpu_data.x86_vendor == X86_VENDOR_AMD;
358f7540060SMario Limonciello }
359f7540060SMario Limonciello 
acpi_sleep_dsm_state_to_str(unsigned int state)360f7540060SMario Limonciello static const char *acpi_sleep_dsm_state_to_str(unsigned int state)
361f7540060SMario Limonciello {
362f7540060SMario Limonciello 	if (lps0_dsm_func_mask_microsoft || !acpi_s2idle_vendor_amd()) {
363f7540060SMario Limonciello 		switch (state) {
364f7540060SMario Limonciello 		case ACPI_LPS0_SCREEN_OFF:
365f7540060SMario Limonciello 			return "screen off";
366f7540060SMario Limonciello 		case ACPI_LPS0_SCREEN_ON:
367f7540060SMario Limonciello 			return "screen on";
368f7540060SMario Limonciello 		case ACPI_LPS0_ENTRY:
369f7540060SMario Limonciello 			return "lps0 entry";
370f7540060SMario Limonciello 		case ACPI_LPS0_EXIT:
371f7540060SMario Limonciello 			return "lps0 exit";
372f7540060SMario Limonciello 		case ACPI_LPS0_MS_ENTRY:
373f7540060SMario Limonciello 			return "lps0 ms entry";
374f7540060SMario Limonciello 		case ACPI_LPS0_MS_EXIT:
375f7540060SMario Limonciello 			return "lps0 ms exit";
376f7540060SMario Limonciello 		}
377f7540060SMario Limonciello 	} else {
378f7540060SMario Limonciello 		switch (state) {
379f7540060SMario Limonciello 		case ACPI_LPS0_SCREEN_ON_AMD:
380f7540060SMario Limonciello 			return "screen on";
381f7540060SMario Limonciello 		case ACPI_LPS0_SCREEN_OFF_AMD:
382f7540060SMario Limonciello 			return "screen off";
383f7540060SMario Limonciello 		case ACPI_LPS0_ENTRY_AMD:
384f7540060SMario Limonciello 			return "lps0 entry";
385f7540060SMario Limonciello 		case ACPI_LPS0_EXIT_AMD:
386f7540060SMario Limonciello 			return "lps0 exit";
387f7540060SMario Limonciello 		}
388f7540060SMario Limonciello 	}
389f7540060SMario Limonciello 
390f7540060SMario Limonciello 	return "unknown";
391f7540060SMario Limonciello }
392f7540060SMario Limonciello 
acpi_sleep_run_lps0_dsm(unsigned int func,unsigned int func_mask,guid_t dsm_guid)3933f4b116cSPratik Vishwakarma static void acpi_sleep_run_lps0_dsm(unsigned int func, unsigned int func_mask, guid_t dsm_guid)
394fef98671SRafael J. Wysocki {
395fef98671SRafael J. Wysocki 	union acpi_object *out_obj;
396fef98671SRafael J. Wysocki 
3973f4b116cSPratik Vishwakarma 	if (!(func_mask & (1 << func)))
398fef98671SRafael J. Wysocki 		return;
399fef98671SRafael J. Wysocki 
4003f4b116cSPratik Vishwakarma 	out_obj = acpi_evaluate_dsm(lps0_device_handle, &dsm_guid,
4013f4b116cSPratik Vishwakarma 					rev_id, func, NULL);
402fef98671SRafael J. Wysocki 	ACPI_FREE(out_obj);
403fef98671SRafael J. Wysocki 
404f7540060SMario Limonciello 	lps0_dsm_state = func;
405f7540060SMario Limonciello 	if (pm_debug_messages_on) {
406f7540060SMario Limonciello 		acpi_handle_info(lps0_device_handle,
407f7540060SMario Limonciello 				"%s transitioned to state %s\n",
408f7540060SMario Limonciello 				 out_obj ? "Successfully" : "Failed to",
409f7540060SMario Limonciello 				 acpi_sleep_dsm_state_to_str(lps0_dsm_state));
410f7540060SMario Limonciello 	}
411fef98671SRafael J. Wysocki }
412fef98671SRafael J. Wysocki 
413fef98671SRafael J. Wysocki 
validate_dsm(acpi_handle handle,const char * uuid,int rev,guid_t * dsm_guid)4144a012dc8SPratik Vishwakarma static int validate_dsm(acpi_handle handle, const char *uuid, int rev, guid_t *dsm_guid)
4154a012dc8SPratik Vishwakarma {
4164a012dc8SPratik Vishwakarma 	union acpi_object *obj;
4174a012dc8SPratik Vishwakarma 	int ret = -EINVAL;
4184a012dc8SPratik Vishwakarma 
4194a012dc8SPratik Vishwakarma 	guid_parse(uuid, dsm_guid);
4204a012dc8SPratik Vishwakarma 	obj = acpi_evaluate_dsm(handle, dsm_guid, rev, 0, NULL);
4214a012dc8SPratik Vishwakarma 
4224a012dc8SPratik Vishwakarma 	/* Check if the _DSM is present and as expected. */
4234a012dc8SPratik Vishwakarma 	if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length == 0 ||
4244a012dc8SPratik Vishwakarma 	    obj->buffer.length > sizeof(u32)) {
4254a012dc8SPratik Vishwakarma 		acpi_handle_debug(handle,
4264a012dc8SPratik Vishwakarma 				"_DSM UUID %s rev %d function 0 evaluation failed\n", uuid, rev);
4274a012dc8SPratik Vishwakarma 		goto out;
4284a012dc8SPratik Vishwakarma 	}
4294a012dc8SPratik Vishwakarma 
4304a012dc8SPratik Vishwakarma 	ret = *(int *)obj->buffer.pointer;
4314a012dc8SPratik Vishwakarma 	acpi_handle_debug(handle, "_DSM UUID %s rev %d function mask: 0x%x\n", uuid, rev, ret);
4324a012dc8SPratik Vishwakarma 
4334a012dc8SPratik Vishwakarma out:
4344a012dc8SPratik Vishwakarma 	ACPI_FREE(obj);
4354a012dc8SPratik Vishwakarma 	return ret;
4364a012dc8SPratik Vishwakarma }
4374a012dc8SPratik Vishwakarma 
438100a5737SMario Limonciello struct amd_lps0_hid_device_data {
439100a5737SMario Limonciello 	const bool check_off_by_one;
440100a5737SMario Limonciello };
441100a5737SMario Limonciello 
442100a5737SMario Limonciello static const struct amd_lps0_hid_device_data amd_picasso = {
443100a5737SMario Limonciello 	.check_off_by_one = true,
444100a5737SMario Limonciello };
445100a5737SMario Limonciello 
446100a5737SMario Limonciello static const struct amd_lps0_hid_device_data amd_cezanne = {
447100a5737SMario Limonciello 	.check_off_by_one = false,
448100a5737SMario Limonciello };
449100a5737SMario Limonciello 
450100a5737SMario Limonciello static const struct acpi_device_id amd_hid_ids[] = {
451100a5737SMario Limonciello 	{"AMD0004",	(kernel_ulong_t)&amd_picasso,	},
452100a5737SMario Limonciello 	{"AMD0005",	(kernel_ulong_t)&amd_picasso,	},
453100a5737SMario Limonciello 	{"AMDI0005",	(kernel_ulong_t)&amd_picasso,	},
454100a5737SMario Limonciello 	{"AMDI0006",	(kernel_ulong_t)&amd_cezanne,	},
455100a5737SMario Limonciello 	{}
456100a5737SMario Limonciello };
457100a5737SMario Limonciello 
lps0_device_attach(struct acpi_device * adev,const struct acpi_device_id * not_used)458fef98671SRafael J. Wysocki static int lps0_device_attach(struct acpi_device *adev,
459fef98671SRafael J. Wysocki 			      const struct acpi_device_id *not_used)
460fef98671SRafael J. Wysocki {
461fef98671SRafael J. Wysocki 	if (lps0_device_handle)
462fef98671SRafael J. Wysocki 		return 0;
463fef98671SRafael J. Wysocki 
464a0bc0023SMario Limonciello 	lps0_dsm_func_mask_microsoft = validate_dsm(adev->handle,
465a0bc0023SMario Limonciello 						    ACPI_LPS0_DSM_UUID_MICROSOFT, 0,
466a0bc0023SMario Limonciello 						    &lps0_dsm_guid_microsoft);
467fef98671SRafael J. Wysocki 	if (acpi_s2idle_vendor_amd()) {
468100a5737SMario Limonciello 		static const struct acpi_device_id *dev_id;
469100a5737SMario Limonciello 		const struct amd_lps0_hid_device_data *data;
470100a5737SMario Limonciello 
471100a5737SMario Limonciello 		for (dev_id = &amd_hid_ids[0]; dev_id->id[0]; dev_id++)
472100a5737SMario Limonciello 			if (acpi_dev_hid_uid_match(adev, dev_id->id, NULL))
473100a5737SMario Limonciello 				break;
47439f81776SMario Limonciello 		if (dev_id->id[0])
475100a5737SMario Limonciello 			data = (const struct amd_lps0_hid_device_data *) dev_id->driver_data;
476100a5737SMario Limonciello 		else
477e555c857SMario Limonciello 			data = &amd_cezanne;
4784a012dc8SPratik Vishwakarma 		lps0_dsm_func_mask = validate_dsm(adev->handle,
4794a012dc8SPratik Vishwakarma 					ACPI_LPS0_DSM_UUID_AMD, rev_id, &lps0_dsm_guid);
480100a5737SMario Limonciello 		if (lps0_dsm_func_mask > 0x3 && data->check_off_by_one) {
4818fbd6c15SMario Limonciello 			lps0_dsm_func_mask = (lps0_dsm_func_mask << 1) | 0x1;
4828fbd6c15SMario Limonciello 			acpi_handle_debug(adev->handle, "_DSM UUID %s: Adjusted function mask: 0x%x\n",
4838fbd6c15SMario Limonciello 					  ACPI_LPS0_DSM_UUID_AMD, lps0_dsm_func_mask);
484e555c857SMario Limonciello 		} else if (lps0_dsm_func_mask_microsoft > 0 && rev_id) {
485f0c62255SMario Limonciello 			lps0_dsm_func_mask_microsoft = -EINVAL;
486f0c62255SMario Limonciello 			acpi_handle_debug(adev->handle, "_DSM Using AMD method\n");
4878fbd6c15SMario Limonciello 		}
488fef98671SRafael J. Wysocki 	} else {
489fef98671SRafael J. Wysocki 		rev_id = 1;
4904a012dc8SPratik Vishwakarma 		lps0_dsm_func_mask = validate_dsm(adev->handle,
4914a012dc8SPratik Vishwakarma 					ACPI_LPS0_DSM_UUID, rev_id, &lps0_dsm_guid);
4925dbf5099SPratik Vishwakarma 		lps0_dsm_func_mask_microsoft = -EINVAL;
493fef98671SRafael J. Wysocki 	}
494fef98671SRafael J. Wysocki 
4955dbf5099SPratik Vishwakarma 	if (lps0_dsm_func_mask < 0 && lps0_dsm_func_mask_microsoft < 0)
4965dbf5099SPratik Vishwakarma 		return 0; //function evaluation failed
497fef98671SRafael J. Wysocki 
498fef98671SRafael J. Wysocki 	lps0_device_handle = adev->handle;
499fef98671SRafael J. Wysocki 
500fef98671SRafael J. Wysocki 	if (acpi_s2idle_vendor_amd())
501fef98671SRafael J. Wysocki 		lpi_device_get_constraints_amd();
502fef98671SRafael J. Wysocki 	else
503fef98671SRafael J. Wysocki 		lpi_device_get_constraints();
504fef98671SRafael J. Wysocki 
505fef98671SRafael J. Wysocki 	/*
5061a2dcab5SRafael J. Wysocki 	 * Use suspend-to-idle by default if ACPI_FADT_LOW_POWER_S0 is set in
5071a2dcab5SRafael J. Wysocki 	 * the FADT and the default suspend mode was not set from the command
5081a2dcab5SRafael J. Wysocki 	 * line.
509fef98671SRafael J. Wysocki 	 */
5101a2dcab5SRafael J. Wysocki 	if ((acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) &&
511ec6c0503SRafael J. Wysocki 	    mem_sleep_default > PM_SUSPEND_MEM && !acpi_sleep_default_s3) {
512fef98671SRafael J. Wysocki 		mem_sleep_current = PM_SUSPEND_TO_IDLE;
513ec6c0503SRafael J. Wysocki 		pr_info("Low-power S0 idle used by default for system suspend\n");
514ec6c0503SRafael J. Wysocki 	}
515fef98671SRafael J. Wysocki 
516fef98671SRafael J. Wysocki 	/*
517d6ebb17cSMario Limonciello 	 * Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the
518d6ebb17cSMario Limonciello 	 * EC GPE to be enabled while suspended for certain wakeup devices to
519d6ebb17cSMario Limonciello 	 * work, so mark it as wakeup-capable.
520fef98671SRafael J. Wysocki 	 */
521fef98671SRafael J. Wysocki 	acpi_ec_mark_gpe_for_wake();
522fef98671SRafael J. Wysocki 
523fef98671SRafael J. Wysocki 	return 0;
524fef98671SRafael J. Wysocki }
525fef98671SRafael J. Wysocki 
526fef98671SRafael J. Wysocki static struct acpi_scan_handler lps0_handler = {
527fef98671SRafael J. Wysocki 	.ids = lps0_device_ids,
528fef98671SRafael J. Wysocki 	.attach = lps0_device_attach,
529fef98671SRafael J. Wysocki };
530fef98671SRafael J. Wysocki 
acpi_s2idle_prepare_late(void)531fef98671SRafael J. Wysocki int acpi_s2idle_prepare_late(void)
532fef98671SRafael J. Wysocki {
53320e1d640SMario Limonciello 	struct acpi_s2idle_dev_ops *handler;
53420e1d640SMario Limonciello 
535fef98671SRafael J. Wysocki 	if (!lps0_device_handle || sleep_no_lps0)
536fef98671SRafael J. Wysocki 		return 0;
537fef98671SRafael J. Wysocki 
538fef98671SRafael J. Wysocki 	if (pm_debug_messages_on)
539fef98671SRafael J. Wysocki 		lpi_check_constraints();
540fef98671SRafael J. Wysocki 
541fa209644SMario Limonciello 	/* Screen off */
542fa209644SMario Limonciello 	if (lps0_dsm_func_mask > 0)
543fa209644SMario Limonciello 		acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
544fa209644SMario Limonciello 					ACPI_LPS0_SCREEN_OFF_AMD :
545fa209644SMario Limonciello 					ACPI_LPS0_SCREEN_OFF,
546fa209644SMario Limonciello 					lps0_dsm_func_mask, lps0_dsm_guid);
547fa209644SMario Limonciello 
548fa209644SMario Limonciello 	if (lps0_dsm_func_mask_microsoft > 0)
5495dbf5099SPratik Vishwakarma 		acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
5505dbf5099SPratik Vishwakarma 				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
551fa209644SMario Limonciello 
552fa209644SMario Limonciello 	/* LPS0 entry */
553fa209644SMario Limonciello 	if (lps0_dsm_func_mask > 0)
554fa209644SMario Limonciello 		acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
555fa209644SMario Limonciello 					ACPI_LPS0_ENTRY_AMD :
556fa209644SMario Limonciello 					ACPI_LPS0_ENTRY,
557fa209644SMario Limonciello 					lps0_dsm_func_mask, lps0_dsm_guid);
558fa209644SMario Limonciello 	if (lps0_dsm_func_mask_microsoft > 0) {
559fa209644SMario Limonciello 		/* modern standby entry */
5604753b46eSMario Limonciello 		acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
5615dbf5099SPratik Vishwakarma 				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
562f198478cSMario Limonciello 		acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
563f198478cSMario Limonciello 				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
564fef98671SRafael J. Wysocki 	}
56520e1d640SMario Limonciello 
56620e1d640SMario Limonciello 	list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node) {
56720e1d640SMario Limonciello 		if (handler->prepare)
56820e1d640SMario Limonciello 			handler->prepare();
56920e1d640SMario Limonciello 	}
57020e1d640SMario Limonciello 
571fef98671SRafael J. Wysocki 	return 0;
572fef98671SRafael J. Wysocki }
573fef98671SRafael J. Wysocki 
acpi_s2idle_check(void)574811d59fdSMario Limonciello void acpi_s2idle_check(void)
575811d59fdSMario Limonciello {
576811d59fdSMario Limonciello 	struct acpi_s2idle_dev_ops *handler;
577811d59fdSMario Limonciello 
578811d59fdSMario Limonciello 	if (!lps0_device_handle || sleep_no_lps0)
579811d59fdSMario Limonciello 		return;
580811d59fdSMario Limonciello 
581811d59fdSMario Limonciello 	list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node) {
582811d59fdSMario Limonciello 		if (handler->check)
583811d59fdSMario Limonciello 			handler->check();
584811d59fdSMario Limonciello 	}
585811d59fdSMario Limonciello }
586811d59fdSMario Limonciello 
acpi_s2idle_restore_early(void)587fef98671SRafael J. Wysocki void acpi_s2idle_restore_early(void)
588fef98671SRafael J. Wysocki {
58920e1d640SMario Limonciello 	struct acpi_s2idle_dev_ops *handler;
59020e1d640SMario Limonciello 
591fef98671SRafael J. Wysocki 	if (!lps0_device_handle || sleep_no_lps0)
592fef98671SRafael J. Wysocki 		return;
593fef98671SRafael J. Wysocki 
59420e1d640SMario Limonciello 	list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node)
59520e1d640SMario Limonciello 		if (handler->restore)
59620e1d640SMario Limonciello 			handler->restore();
59720e1d640SMario Limonciello 
598fa209644SMario Limonciello 	/* LPS0 exit */
599fa209644SMario Limonciello 	if (lps0_dsm_func_mask > 0)
600fa209644SMario Limonciello 		acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
601fa209644SMario Limonciello 					ACPI_LPS0_EXIT_AMD :
602fa209644SMario Limonciello 					ACPI_LPS0_EXIT,
603fa209644SMario Limonciello 					lps0_dsm_func_mask, lps0_dsm_guid);
604fa209644SMario Limonciello 	if (lps0_dsm_func_mask_microsoft > 0)
605fa209644SMario Limonciello 		acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
606fa209644SMario Limonciello 				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
607fa209644SMario Limonciello 
608f198478cSMario Limonciello 	/* Modern standby exit */
609f198478cSMario Limonciello 	if (lps0_dsm_func_mask_microsoft > 0)
610f198478cSMario Limonciello 		acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
611f198478cSMario Limonciello 				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
612f198478cSMario Limonciello 
613fa209644SMario Limonciello 	/* Screen on */
614fa209644SMario Limonciello 	if (lps0_dsm_func_mask_microsoft > 0)
6155dbf5099SPratik Vishwakarma 		acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
6165dbf5099SPratik Vishwakarma 				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
617fa209644SMario Limonciello 	if (lps0_dsm_func_mask > 0)
618fa209644SMario Limonciello 		acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
619fa209644SMario Limonciello 					ACPI_LPS0_SCREEN_ON_AMD :
620fa209644SMario Limonciello 					ACPI_LPS0_SCREEN_ON,
6213f4b116cSPratik Vishwakarma 					lps0_dsm_func_mask, lps0_dsm_guid);
622fef98671SRafael J. Wysocki }
623fef98671SRafael J. Wysocki 
624fef98671SRafael J. Wysocki static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 = {
625fef98671SRafael J. Wysocki 	.begin = acpi_s2idle_begin,
626fef98671SRafael J. Wysocki 	.prepare = acpi_s2idle_prepare,
627fef98671SRafael J. Wysocki 	.prepare_late = acpi_s2idle_prepare_late,
628811d59fdSMario Limonciello 	.check = acpi_s2idle_check,
629fef98671SRafael J. Wysocki 	.wake = acpi_s2idle_wake,
630fef98671SRafael J. Wysocki 	.restore_early = acpi_s2idle_restore_early,
631fef98671SRafael J. Wysocki 	.restore = acpi_s2idle_restore,
632fef98671SRafael J. Wysocki 	.end = acpi_s2idle_end,
633fef98671SRafael J. Wysocki };
634fef98671SRafael J. Wysocki 
acpi_s2idle_setup(void)635d0f61e89SMario Limonciello void __init acpi_s2idle_setup(void)
636fef98671SRafael J. Wysocki {
637fef98671SRafael J. Wysocki 	acpi_scan_add_handler(&lps0_handler);
638fef98671SRafael J. Wysocki 	s2idle_set_ops(&acpi_s2idle_ops_lps0);
639fef98671SRafael J. Wysocki }
640fef98671SRafael J. Wysocki 
acpi_register_lps0_dev(struct acpi_s2idle_dev_ops * arg)64120e1d640SMario Limonciello int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg)
64220e1d640SMario Limonciello {
6435950e5d5SPeter Zijlstra 	unsigned int sleep_flags;
6445950e5d5SPeter Zijlstra 
64520e1d640SMario Limonciello 	if (!lps0_device_handle || sleep_no_lps0)
64620e1d640SMario Limonciello 		return -ENODEV;
64720e1d640SMario Limonciello 
6485950e5d5SPeter Zijlstra 	sleep_flags = lock_system_sleep();
64920e1d640SMario Limonciello 	list_add(&arg->list_node, &lps0_s2idle_devops_head);
6505950e5d5SPeter Zijlstra 	unlock_system_sleep(sleep_flags);
65120e1d640SMario Limonciello 
65220e1d640SMario Limonciello 	return 0;
65320e1d640SMario Limonciello }
65420e1d640SMario Limonciello EXPORT_SYMBOL_GPL(acpi_register_lps0_dev);
65520e1d640SMario Limonciello 
acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops * arg)65620e1d640SMario Limonciello void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg)
65720e1d640SMario Limonciello {
6585950e5d5SPeter Zijlstra 	unsigned int sleep_flags;
6595950e5d5SPeter Zijlstra 
66020e1d640SMario Limonciello 	if (!lps0_device_handle || sleep_no_lps0)
66120e1d640SMario Limonciello 		return;
66220e1d640SMario Limonciello 
6635950e5d5SPeter Zijlstra 	sleep_flags = lock_system_sleep();
66420e1d640SMario Limonciello 	list_del(&arg->list_node);
6655950e5d5SPeter Zijlstra 	unlock_system_sleep(sleep_flags);
66620e1d640SMario Limonciello }
66720e1d640SMario Limonciello EXPORT_SYMBOL_GPL(acpi_unregister_lps0_dev);
66820e1d640SMario Limonciello 
669fef98671SRafael J. Wysocki #endif /* CONFIG_SUSPEND */
670