Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Architecture-specific ACPI-based support for suspend-to-idle.
  4 *
  5 * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  6 * Author: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
  7 * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
  8 *
  9 * On platforms supporting the Low Power S0 Idle interface there is an ACPI
 10 * device object with the PNP0D80 compatible device ID (System Power Management
 11 * Controller) and a specific _DSM method under it.  That method, if present,
 12 * can be used to indicate to the platform that the OS is transitioning into a
 13 * low-power state in which certain types of activity are not desirable or that
 14 * it is leaving such a state, which allows the platform to adjust its operation
 15 * mode accordingly.
 16 */
 17
 18#include <linux/acpi.h>
 19#include <linux/device.h>
 20#include <linux/dmi.h>
 21#include <linux/suspend.h>
 22
 23#include "../sleep.h"
 24
 25#ifdef CONFIG_SUSPEND
 26
 27static bool sleep_no_lps0 __read_mostly;
 28module_param(sleep_no_lps0, bool, 0644);
 29MODULE_PARM_DESC(sleep_no_lps0, "Do not use the special LPS0 device interface");
 30
 31static const struct acpi_device_id lps0_device_ids[] = {
 32	{"PNP0D80", },
 33	{"", },
 34};
 35
 36/* Microsoft platform agnostic UUID */
 37#define ACPI_LPS0_DSM_UUID_MICROSOFT      "11e00d56-ce64-47ce-837b-1f898f9aa461"
 38
 39#define ACPI_LPS0_DSM_UUID	"c4eb40a0-6cd2-11e2-bcfd-0800200c9a66"
 40
 41#define ACPI_LPS0_GET_DEVICE_CONSTRAINTS	1
 42#define ACPI_LPS0_SCREEN_OFF	3
 43#define ACPI_LPS0_SCREEN_ON	4
 44#define ACPI_LPS0_ENTRY		5
 45#define ACPI_LPS0_EXIT		6
 46#define ACPI_LPS0_MS_ENTRY      7
 47#define ACPI_LPS0_MS_EXIT       8
 48
 49/* AMD */
 50#define ACPI_LPS0_DSM_UUID_AMD      "e3f32452-febc-43ce-9039-932122d37721"
 51#define ACPI_LPS0_ENTRY_AMD         2
 52#define ACPI_LPS0_EXIT_AMD          3
 53#define ACPI_LPS0_SCREEN_OFF_AMD    4
 54#define ACPI_LPS0_SCREEN_ON_AMD     5
 55
 56static acpi_handle lps0_device_handle;
 57static guid_t lps0_dsm_guid;
 58static int lps0_dsm_func_mask;
 59
 60static guid_t lps0_dsm_guid_microsoft;
 61static int lps0_dsm_func_mask_microsoft;
 62static int lps0_dsm_state;
 63
 64/* Device constraint entry structure */
 65struct lpi_device_info {
 66	char *name;
 67	int enabled;
 68	union acpi_object *package;
 69};
 70
 71/* Constraint package structure */
 72struct lpi_device_constraint {
 73	int uid;
 74	int min_dstate;
 75	int function_states;
 76};
 77
 78struct lpi_constraints {
 79	acpi_handle handle;
 80	int min_dstate;
 81};
 82
 83/* AMD Constraint package structure */
 84struct lpi_device_constraint_amd {
 85	char *name;
 86	int enabled;
 87	int function_states;
 88	int min_dstate;
 89};
 90
 91static LIST_HEAD(lps0_s2idle_devops_head);
 92
 93static struct lpi_constraints *lpi_constraints_table;
 94static int lpi_constraints_table_size;
 95static int rev_id;
 96
 97#define for_each_lpi_constraint(entry)						\
 98	for (int i = 0;								\
 99	     entry = &lpi_constraints_table[i], i < lpi_constraints_table_size;	\
100	     i++)
101
102static void lpi_device_get_constraints_amd(void)
103{
104	union acpi_object *out_obj;
105	int i, j, k;
106
107	out_obj = acpi_evaluate_dsm_typed(lps0_device_handle, &lps0_dsm_guid,
108					  rev_id, ACPI_LPS0_GET_DEVICE_CONSTRAINTS,
109					  NULL, ACPI_TYPE_PACKAGE);
110
111	acpi_handle_debug(lps0_device_handle, "_DSM function 1 eval %s\n",
112			  out_obj ? "successful" : "failed");
113
114	if (!out_obj)
115		return;
116
117	for (i = 0; i < out_obj->package.count; i++) {
118		union acpi_object *package = &out_obj->package.elements[i];
119
120		if (package->type == ACPI_TYPE_PACKAGE) {
121			if (lpi_constraints_table) {
122				acpi_handle_err(lps0_device_handle,
123						"Duplicate constraints list\n");
124				goto free_acpi_buffer;
125			}
126
127			lpi_constraints_table = kcalloc(package->package.count,
128							sizeof(*lpi_constraints_table),
129							GFP_KERNEL);
130
131			if (!lpi_constraints_table)
132				goto free_acpi_buffer;
133
134			acpi_handle_debug(lps0_device_handle,
135					  "LPI: constraints list begin:\n");
136
137			for (j = 0; j < package->package.count; j++) {
138				union acpi_object *info_obj = &package->package.elements[j];
139				struct lpi_device_constraint_amd dev_info = {};
140				struct lpi_constraints *list;
141				acpi_status status;
142
143				list = &lpi_constraints_table[lpi_constraints_table_size];
144
145				for (k = 0; k < info_obj->package.count; k++) {
146					union acpi_object *obj = &info_obj->package.elements[k];
147
148					switch (k) {
149					case 0:
150						dev_info.enabled = obj->integer.value;
151						break;
152					case 1:
153						dev_info.name = obj->string.pointer;
154						break;
155					case 2:
156						dev_info.function_states = obj->integer.value;
157						break;
158					case 3:
159						dev_info.min_dstate = obj->integer.value;
160						break;
161					}
162				}
163
164				acpi_handle_debug(lps0_device_handle,
165						  "Name:%s, Enabled: %d, States: %d, MinDstate: %d\n",
166						  dev_info.name,
167						  dev_info.enabled,
168						  dev_info.function_states,
169						  dev_info.min_dstate);
170
171				if (!dev_info.enabled || !dev_info.name ||
172				    !dev_info.min_dstate)
173					continue;
174
175				status = acpi_get_handle(NULL, dev_info.name, &list->handle);
176				if (ACPI_FAILURE(status))
177					continue;
178
179				list->min_dstate = dev_info.min_dstate;
180
181				lpi_constraints_table_size++;
182			}
183		}
184	}
185
186	acpi_handle_debug(lps0_device_handle, "LPI: constraints list end\n");
187
188free_acpi_buffer:
189	ACPI_FREE(out_obj);
190}
191
192static void lpi_device_get_constraints(void)
193{
194	union acpi_object *out_obj;
195	int i;
196
197	out_obj = acpi_evaluate_dsm_typed(lps0_device_handle, &lps0_dsm_guid,
198					  1, ACPI_LPS0_GET_DEVICE_CONSTRAINTS,
199					  NULL, ACPI_TYPE_PACKAGE);
200
201	acpi_handle_debug(lps0_device_handle, "_DSM function 1 eval %s\n",
202			  out_obj ? "successful" : "failed");
203
204	if (!out_obj)
205		return;
206
207	lpi_constraints_table = kcalloc(out_obj->package.count,
208					sizeof(*lpi_constraints_table),
209					GFP_KERNEL);
210	if (!lpi_constraints_table)
211		goto free_acpi_buffer;
212
213	acpi_handle_debug(lps0_device_handle, "LPI: constraints list begin:\n");
214
215	for (i = 0; i < out_obj->package.count; i++) {
216		struct lpi_constraints *constraint;
217		acpi_status status;
218		union acpi_object *package = &out_obj->package.elements[i];
219		struct lpi_device_info info = { };
220		int package_count = 0, j;
221
222		if (!package)
223			continue;
224
225		for (j = 0; j < package->package.count; j++) {
226			union acpi_object *element =
227					&(package->package.elements[j]);
228
229			switch (element->type) {
230			case ACPI_TYPE_INTEGER:
231				info.enabled = element->integer.value;
232				break;
233			case ACPI_TYPE_STRING:
234				info.name = element->string.pointer;
235				break;
236			case ACPI_TYPE_PACKAGE:
237				package_count = element->package.count;
238				info.package = element->package.elements;
239				break;
240			}
241		}
242
243		if (!info.enabled || !info.package || !info.name)
244			continue;
245
246		constraint = &lpi_constraints_table[lpi_constraints_table_size];
247
248		status = acpi_get_handle(NULL, info.name, &constraint->handle);
249		if (ACPI_FAILURE(status))
250			continue;
251
252		acpi_handle_debug(lps0_device_handle,
253				  "index:%d Name:%s\n", i, info.name);
254
255		constraint->min_dstate = -1;
256
257		for (j = 0; j < package_count; j++) {
258			union acpi_object *info_obj = &info.package[j];
259			union acpi_object *cnstr_pkg;
260			union acpi_object *obj;
261			struct lpi_device_constraint dev_info;
262
263			switch (info_obj->type) {
264			case ACPI_TYPE_INTEGER:
265				/* version */
266				break;
267			case ACPI_TYPE_PACKAGE:
268				if (info_obj->package.count < 2)
269					break;
270
271				cnstr_pkg = info_obj->package.elements;
272				obj = &cnstr_pkg[0];
273				dev_info.uid = obj->integer.value;
274				obj = &cnstr_pkg[1];
275				dev_info.min_dstate = obj->integer.value;
276
277				acpi_handle_debug(lps0_device_handle,
278					"uid:%d min_dstate:%s\n",
279					dev_info.uid,
280					acpi_power_state_string(dev_info.min_dstate));
281
282				constraint->min_dstate = dev_info.min_dstate;
283				break;
284			}
285		}
286
287		if (constraint->min_dstate < 0) {
288			acpi_handle_debug(lps0_device_handle,
289					  "Incomplete constraint defined\n");
290			continue;
291		}
292
293		lpi_constraints_table_size++;
294	}
295
296	acpi_handle_debug(lps0_device_handle, "LPI: constraints list end\n");
297
298free_acpi_buffer:
299	ACPI_FREE(out_obj);
300}
301
302/**
303 * acpi_get_lps0_constraint - Get the LPS0 constraint for a device.
304 * @adev: Device to get the constraint for.
305 *
306 * The LPS0 constraint is the shallowest (minimum) power state in which the
307 * device can be so as to allow the platform as a whole to achieve additional
308 * energy conservation by utilizing a system-wide low-power state.
309 *
310 * Returns:
311 *  - ACPI power state value of the constraint for @adev on success.
312 *  - Otherwise, ACPI_STATE_UNKNOWN.
313 */
314int acpi_get_lps0_constraint(struct acpi_device *adev)
315{
316	struct lpi_constraints *entry;
317
318	for_each_lpi_constraint(entry) {
319		if (adev->handle == entry->handle)
320			return entry->min_dstate;
321	}
322
323	return ACPI_STATE_UNKNOWN;
324}
325
326static void lpi_check_constraints(void)
327{
328	struct lpi_constraints *entry;
329
330	for_each_lpi_constraint(entry) {
331		struct acpi_device *adev = acpi_fetch_acpi_dev(entry->handle);
332
333		if (!adev)
334			continue;
335
336		acpi_handle_debug(entry->handle,
337			"LPI: required min power state:%s current power state:%s\n",
338			acpi_power_state_string(entry->min_dstate),
339			acpi_power_state_string(adev->power.state));
340
341		if (!adev->flags.power_manageable) {
342			acpi_handle_info(entry->handle, "LPI: Device not power manageable\n");
343			entry->handle = NULL;
344			continue;
345		}
346
347		if (adev->power.state < entry->min_dstate)
348			acpi_handle_info(entry->handle,
349				"LPI: Constraint not met; min power state:%s current power state:%s\n",
350				acpi_power_state_string(entry->min_dstate),
351				acpi_power_state_string(adev->power.state));
352	}
353}
354
355static bool acpi_s2idle_vendor_amd(void)
356{
357	return boot_cpu_data.x86_vendor == X86_VENDOR_AMD;
358}
359
360static const char *acpi_sleep_dsm_state_to_str(unsigned int state)
361{
362	if (lps0_dsm_func_mask_microsoft || !acpi_s2idle_vendor_amd()) {
363		switch (state) {
364		case ACPI_LPS0_SCREEN_OFF:
365			return "screen off";
366		case ACPI_LPS0_SCREEN_ON:
367			return "screen on";
368		case ACPI_LPS0_ENTRY:
369			return "lps0 entry";
370		case ACPI_LPS0_EXIT:
371			return "lps0 exit";
372		case ACPI_LPS0_MS_ENTRY:
373			return "lps0 ms entry";
374		case ACPI_LPS0_MS_EXIT:
375			return "lps0 ms exit";
376		}
377	} else {
378		switch (state) {
379		case ACPI_LPS0_SCREEN_ON_AMD:
380			return "screen on";
381		case ACPI_LPS0_SCREEN_OFF_AMD:
382			return "screen off";
383		case ACPI_LPS0_ENTRY_AMD:
384			return "lps0 entry";
385		case ACPI_LPS0_EXIT_AMD:
386			return "lps0 exit";
387		}
388	}
389
390	return "unknown";
391}
392
393static void acpi_sleep_run_lps0_dsm(unsigned int func, unsigned int func_mask, guid_t dsm_guid)
394{
395	union acpi_object *out_obj;
396
397	if (!(func_mask & (1 << func)))
398		return;
399
400	out_obj = acpi_evaluate_dsm(lps0_device_handle, &dsm_guid,
401					rev_id, func, NULL);
402	ACPI_FREE(out_obj);
403
404	lps0_dsm_state = func;
405	if (pm_debug_messages_on) {
406		acpi_handle_info(lps0_device_handle,
407				"%s transitioned to state %s\n",
408				 out_obj ? "Successfully" : "Failed to",
409				 acpi_sleep_dsm_state_to_str(lps0_dsm_state));
410	}
411}
412
413
414static int validate_dsm(acpi_handle handle, const char *uuid, int rev, guid_t *dsm_guid)
415{
416	union acpi_object *obj;
417	int ret = -EINVAL;
418
419	guid_parse(uuid, dsm_guid);
420
421	/* Check if the _DSM is present and as expected. */
422	obj = acpi_evaluate_dsm_typed(handle, dsm_guid, rev, 0, NULL, ACPI_TYPE_BUFFER);
423	if (!obj || obj->buffer.length == 0 || obj->buffer.length > sizeof(u32)) {
424		acpi_handle_debug(handle,
425				"_DSM UUID %s rev %d function 0 evaluation failed\n", uuid, rev);
426		goto out;
427	}
428
429	ret = *(int *)obj->buffer.pointer;
430	acpi_handle_debug(handle, "_DSM UUID %s rev %d function mask: 0x%x\n", uuid, rev, ret);
431
432out:
433	ACPI_FREE(obj);
434	return ret;
435}
436
437struct amd_lps0_hid_device_data {
438	const bool check_off_by_one;
439};
440
441static const struct amd_lps0_hid_device_data amd_picasso = {
442	.check_off_by_one = true,
443};
444
445static const struct amd_lps0_hid_device_data amd_cezanne = {
446	.check_off_by_one = false,
447};
448
449static const struct acpi_device_id amd_hid_ids[] = {
450	{"AMD0004",	(kernel_ulong_t)&amd_picasso,	},
451	{"AMD0005",	(kernel_ulong_t)&amd_picasso,	},
452	{"AMDI0005",	(kernel_ulong_t)&amd_picasso,	},
453	{"AMDI0006",	(kernel_ulong_t)&amd_cezanne,	},
454	{}
455};
456
457static int lps0_device_attach(struct acpi_device *adev,
458			      const struct acpi_device_id *not_used)
459{
460	if (lps0_device_handle)
461		return 0;
462
463	lps0_dsm_func_mask_microsoft = validate_dsm(adev->handle,
464						    ACPI_LPS0_DSM_UUID_MICROSOFT, 0,
465						    &lps0_dsm_guid_microsoft);
466	if (acpi_s2idle_vendor_amd()) {
467		static const struct acpi_device_id *dev_id;
468		const struct amd_lps0_hid_device_data *data;
469
470		for (dev_id = &amd_hid_ids[0]; dev_id->id[0]; dev_id++)
471			if (acpi_dev_hid_uid_match(adev, dev_id->id, NULL))
472				break;
473		if (dev_id->id[0])
474			data = (const struct amd_lps0_hid_device_data *) dev_id->driver_data;
475		else
476			data = &amd_cezanne;
477		lps0_dsm_func_mask = validate_dsm(adev->handle,
478					ACPI_LPS0_DSM_UUID_AMD, rev_id, &lps0_dsm_guid);
479		if (lps0_dsm_func_mask > 0x3 && data->check_off_by_one) {
480			lps0_dsm_func_mask = (lps0_dsm_func_mask << 1) | 0x1;
481			acpi_handle_debug(adev->handle, "_DSM UUID %s: Adjusted function mask: 0x%x\n",
482					  ACPI_LPS0_DSM_UUID_AMD, lps0_dsm_func_mask);
483		} else if (lps0_dsm_func_mask_microsoft > 0 && rev_id) {
484			lps0_dsm_func_mask_microsoft = -EINVAL;
485			acpi_handle_debug(adev->handle, "_DSM Using AMD method\n");
486		}
487	} else {
488		rev_id = 1;
489		lps0_dsm_func_mask = validate_dsm(adev->handle,
490					ACPI_LPS0_DSM_UUID, rev_id, &lps0_dsm_guid);
491		lps0_dsm_func_mask_microsoft = -EINVAL;
492	}
493
494	if (lps0_dsm_func_mask < 0 && lps0_dsm_func_mask_microsoft < 0)
495		return 0; //function evaluation failed
496
497	lps0_device_handle = adev->handle;
498
499	if (acpi_s2idle_vendor_amd())
500		lpi_device_get_constraints_amd();
501	else
502		lpi_device_get_constraints();
503
504	/*
505	 * Use suspend-to-idle by default if ACPI_FADT_LOW_POWER_S0 is set in
506	 * the FADT and the default suspend mode was not set from the command
507	 * line.
508	 */
509	if ((acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) &&
510	    mem_sleep_default > PM_SUSPEND_MEM && !acpi_sleep_default_s3) {
511		mem_sleep_current = PM_SUSPEND_TO_IDLE;
512		pr_info("Low-power S0 idle used by default for system suspend\n");
513	}
514
515	/*
516	 * Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the
517	 * EC GPE to be enabled while suspended for certain wakeup devices to
518	 * work, so mark it as wakeup-capable.
519	 */
520	acpi_ec_mark_gpe_for_wake();
521
522	return 0;
523}
524
525static struct acpi_scan_handler lps0_handler = {
526	.ids = lps0_device_ids,
527	.attach = lps0_device_attach,
528};
529
530int acpi_s2idle_prepare_late(void)
531{
532	struct acpi_s2idle_dev_ops *handler;
533
534	if (!lps0_device_handle || sleep_no_lps0)
535		return 0;
536
537	if (pm_debug_messages_on)
538		lpi_check_constraints();
539
540	/* Screen off */
541	if (lps0_dsm_func_mask > 0)
542		acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
543					ACPI_LPS0_SCREEN_OFF_AMD :
544					ACPI_LPS0_SCREEN_OFF,
545					lps0_dsm_func_mask, lps0_dsm_guid);
546
547	if (lps0_dsm_func_mask_microsoft > 0)
548		acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
549				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
550
551	/* LPS0 entry */
552	if (lps0_dsm_func_mask > 0)
553		acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
554					ACPI_LPS0_ENTRY_AMD :
555					ACPI_LPS0_ENTRY,
556					lps0_dsm_func_mask, lps0_dsm_guid);
557	if (lps0_dsm_func_mask_microsoft > 0) {
558		/* modern standby entry */
559		acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
560				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
561		acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
562				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
563	}
564
565	list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node) {
566		if (handler->prepare)
567			handler->prepare();
568	}
569
570	return 0;
571}
572
573void acpi_s2idle_check(void)
574{
575	struct acpi_s2idle_dev_ops *handler;
576
577	if (!lps0_device_handle || sleep_no_lps0)
578		return;
579
580	list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node) {
581		if (handler->check)
582			handler->check();
583	}
584}
585
586void acpi_s2idle_restore_early(void)
587{
588	struct acpi_s2idle_dev_ops *handler;
589
590	if (!lps0_device_handle || sleep_no_lps0)
591		return;
592
593	list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node)
594		if (handler->restore)
595			handler->restore();
596
597	/* LPS0 exit */
598	if (lps0_dsm_func_mask > 0)
599		acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
600					ACPI_LPS0_EXIT_AMD :
601					ACPI_LPS0_EXIT,
602					lps0_dsm_func_mask, lps0_dsm_guid);
603	if (lps0_dsm_func_mask_microsoft > 0)
604		acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
605				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
606
607	/* Modern standby exit */
608	if (lps0_dsm_func_mask_microsoft > 0)
609		acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
610				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
611
612	/* Screen on */
613	if (lps0_dsm_func_mask_microsoft > 0)
614		acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
615				lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
616	if (lps0_dsm_func_mask > 0)
617		acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
618					ACPI_LPS0_SCREEN_ON_AMD :
619					ACPI_LPS0_SCREEN_ON,
620					lps0_dsm_func_mask, lps0_dsm_guid);
621}
622
623static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 = {
624	.begin = acpi_s2idle_begin,
625	.prepare = acpi_s2idle_prepare,
626	.prepare_late = acpi_s2idle_prepare_late,
627	.check = acpi_s2idle_check,
628	.wake = acpi_s2idle_wake,
629	.restore_early = acpi_s2idle_restore_early,
630	.restore = acpi_s2idle_restore,
631	.end = acpi_s2idle_end,
632};
633
634void __init acpi_s2idle_setup(void)
635{
636	acpi_scan_add_handler(&lps0_handler);
637	s2idle_set_ops(&acpi_s2idle_ops_lps0);
638}
639
640int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg)
641{
642	unsigned int sleep_flags;
643
644	if (!lps0_device_handle || sleep_no_lps0)
645		return -ENODEV;
646
647	sleep_flags = lock_system_sleep();
648	list_add(&arg->list_node, &lps0_s2idle_devops_head);
649	unlock_system_sleep(sleep_flags);
650
651	return 0;
652}
653EXPORT_SYMBOL_GPL(acpi_register_lps0_dev);
654
655void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg)
656{
657	unsigned int sleep_flags;
658
659	if (!lps0_device_handle || sleep_no_lps0)
660		return;
661
662	sleep_flags = lock_system_sleep();
663	list_del(&arg->list_node);
664	unlock_system_sleep(sleep_flags);
665}
666EXPORT_SYMBOL_GPL(acpi_unregister_lps0_dev);
667
668#endif /* CONFIG_SUSPEND */