• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * sleep.c - ACPI sleep support.
3   *
4   * Copyright (c) 2005 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
5   * Copyright (c) 2004 David Shaohua Li <shaohua.li@intel.com>
6   * Copyright (c) 2000-2003 Patrick Mochel
7   * Copyright (c) 2003 Open Source Development Lab
8   *
9   * This file is released under the GPLv2.
10   *
11   */
12  
13  #include <linux/delay.h>
14  #include <linux/irq.h>
15  #include <linux/dmi.h>
16  #include <linux/device.h>
17  #include <linux/suspend.h>
18  #include <linux/reboot.h>
19  #include <linux/acpi.h>
20  #include <linux/module.h>
21  
22  #include <asm/io.h>
23  
24  #include <acpi/acpi_bus.h>
25  #include <acpi/acpi_drivers.h>
26  
27  #include "internal.h"
28  #include "sleep.h"
29  
30  static u8 sleep_states[ACPI_S_STATE_COUNT];
31  
acpi_sleep_tts_switch(u32 acpi_state)32  static void acpi_sleep_tts_switch(u32 acpi_state)
33  {
34  	union acpi_object in_arg = { ACPI_TYPE_INTEGER };
35  	struct acpi_object_list arg_list = { 1, &in_arg };
36  	acpi_status status = AE_OK;
37  
38  	in_arg.integer.value = acpi_state;
39  	status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL);
40  	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
41  		/*
42  		 * OS can't evaluate the _TTS object correctly. Some warning
43  		 * message will be printed. But it won't break anything.
44  		 */
45  		printk(KERN_NOTICE "Failure in evaluating _TTS object\n");
46  	}
47  }
48  
tts_notify_reboot(struct notifier_block * this,unsigned long code,void * x)49  static int tts_notify_reboot(struct notifier_block *this,
50  			unsigned long code, void *x)
51  {
52  	acpi_sleep_tts_switch(ACPI_STATE_S5);
53  	return NOTIFY_DONE;
54  }
55  
56  static struct notifier_block tts_notifier = {
57  	.notifier_call	= tts_notify_reboot,
58  	.next		= NULL,
59  	.priority	= 0,
60  };
61  
acpi_sleep_prepare(u32 acpi_state)62  static int acpi_sleep_prepare(u32 acpi_state)
63  {
64  #ifdef CONFIG_ACPI_SLEEP
65  	/* do we have a wakeup address for S2 and S3? */
66  	if (acpi_state == ACPI_STATE_S3) {
67  		if (!acpi_wakeup_address)
68  			return -EFAULT;
69  		acpi_set_firmware_waking_vector(acpi_wakeup_address);
70  
71  	}
72  	ACPI_FLUSH_CPU_CACHE();
73  #endif
74  	printk(KERN_INFO PREFIX "Preparing to enter system sleep state S%d\n",
75  		acpi_state);
76  	acpi_enable_wakeup_devices(acpi_state);
77  	acpi_enter_sleep_state_prep(acpi_state);
78  	return 0;
79  }
80  
81  #ifdef CONFIG_ACPI_SLEEP
82  static u32 acpi_target_sleep_state = ACPI_STATE_S0;
83  
acpi_target_system_state(void)84  u32 acpi_target_system_state(void)
85  {
86  	return acpi_target_sleep_state;
87  }
88  
89  static bool pwr_btn_event_pending;
90  
91  /*
92   * The ACPI specification wants us to save NVS memory regions during hibernation
93   * and to restore them during the subsequent resume.  Windows does that also for
94   * suspend to RAM.  However, it is known that this mechanism does not work on
95   * all machines, so we allow the user to disable it with the help of the
96   * 'acpi_sleep=nonvs' kernel command line option.
97   */
98  static bool nvs_nosave;
99  
acpi_nvs_nosave(void)100  void __init acpi_nvs_nosave(void)
101  {
102  	nvs_nosave = true;
103  }
104  
105  /*
106   * The ACPI specification wants us to save NVS memory regions during hibernation
107   * but says nothing about saving NVS during S3.  Not all versions of Windows
108   * save NVS on S3 suspend either, and it is clear that not all systems need
109   * NVS to be saved at S3 time.  To improve suspend/resume time, allow the
110   * user to disable saving NVS on S3 if their system does not require it, but
111   * continue to save/restore NVS for S4 as specified.
112   */
113  static bool nvs_nosave_s3;
114  
acpi_nvs_nosave_s3(void)115  void __init acpi_nvs_nosave_s3(void)
116  {
117  	nvs_nosave_s3 = true;
118  }
119  
120  /*
121   * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
122   * user to request that behavior by using the 'acpi_old_suspend_ordering'
123   * kernel command line option that causes the following variable to be set.
124   */
125  static bool old_suspend_ordering;
126  
acpi_old_suspend_ordering(void)127  void __init acpi_old_suspend_ordering(void)
128  {
129  	old_suspend_ordering = true;
130  }
131  
init_old_suspend_ordering(const struct dmi_system_id * d)132  static int __init init_old_suspend_ordering(const struct dmi_system_id *d)
133  {
134  	acpi_old_suspend_ordering();
135  	return 0;
136  }
137  
init_nvs_nosave(const struct dmi_system_id * d)138  static int __init init_nvs_nosave(const struct dmi_system_id *d)
139  {
140  	acpi_nvs_nosave();
141  	return 0;
142  }
143  
144  static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
145  	{
146  	.callback = init_old_suspend_ordering,
147  	.ident = "Abit KN9 (nForce4 variant)",
148  	.matches = {
149  		DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
150  		DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"),
151  		},
152  	},
153  	{
154  	.callback = init_old_suspend_ordering,
155  	.ident = "HP xw4600 Workstation",
156  	.matches = {
157  		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
158  		DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"),
159  		},
160  	},
161  	{
162  	.callback = init_old_suspend_ordering,
163  	.ident = "Asus Pundit P1-AH2 (M2N8L motherboard)",
164  	.matches = {
165  		DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."),
166  		DMI_MATCH(DMI_BOARD_NAME, "M2N8L"),
167  		},
168  	},
169  	{
170  	.callback = init_old_suspend_ordering,
171  	.ident = "Panasonic CF51-2L",
172  	.matches = {
173  		DMI_MATCH(DMI_BOARD_VENDOR,
174  				"Matsushita Electric Industrial Co.,Ltd."),
175  		DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"),
176  		},
177  	},
178  	{
179  	.callback = init_nvs_nosave,
180  	.ident = "Sony Vaio VGN-FW41E_H",
181  	.matches = {
182  		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
183  		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW41E_H"),
184  		},
185  	},
186  	{
187  	.callback = init_nvs_nosave,
188  	.ident = "Sony Vaio VGN-FW21E",
189  	.matches = {
190  		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
191  		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"),
192  		},
193  	},
194  	{
195  	.callback = init_nvs_nosave,
196  	.ident = "Sony Vaio VGN-FW21M",
197  	.matches = {
198  		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
199  		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21M"),
200  		},
201  	},
202  	{
203  	.callback = init_nvs_nosave,
204  	.ident = "Sony Vaio VPCEB17FX",
205  	.matches = {
206  		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
207  		DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"),
208  		},
209  	},
210  	{
211  	.callback = init_nvs_nosave,
212  	.ident = "Sony Vaio VGN-SR11M",
213  	.matches = {
214  		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
215  		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"),
216  		},
217  	},
218  	{
219  	.callback = init_nvs_nosave,
220  	.ident = "Everex StepNote Series",
221  	.matches = {
222  		DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."),
223  		DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"),
224  		},
225  	},
226  	{
227  	.callback = init_nvs_nosave,
228  	.ident = "Sony Vaio VPCEB1Z1E",
229  	.matches = {
230  		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
231  		DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"),
232  		},
233  	},
234  	{
235  	.callback = init_nvs_nosave,
236  	.ident = "Sony Vaio VGN-NW130D",
237  	.matches = {
238  		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
239  		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"),
240  		},
241  	},
242  	{
243  	.callback = init_nvs_nosave,
244  	.ident = "Sony Vaio VPCCW29FX",
245  	.matches = {
246  		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
247  		DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"),
248  		},
249  	},
250  	{
251  	.callback = init_nvs_nosave,
252  	.ident = "Averatec AV1020-ED2",
253  	.matches = {
254  		DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"),
255  		DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"),
256  		},
257  	},
258  	{
259  	.callback = init_old_suspend_ordering,
260  	.ident = "Asus A8N-SLI DELUXE",
261  	.matches = {
262  		DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
263  		DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI DELUXE"),
264  		},
265  	},
266  	{
267  	.callback = init_old_suspend_ordering,
268  	.ident = "Asus A8N-SLI Premium",
269  	.matches = {
270  		DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
271  		DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"),
272  		},
273  	},
274  	{
275  	.callback = init_nvs_nosave,
276  	.ident = "Sony Vaio VGN-SR26GN_P",
277  	.matches = {
278  		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
279  		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"),
280  		},
281  	},
282  	{
283  	.callback = init_nvs_nosave,
284  	.ident = "Sony Vaio VPCEB1S1E",
285  	.matches = {
286  		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
287  		DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1S1E"),
288  		},
289  	},
290  	{
291  	.callback = init_nvs_nosave,
292  	.ident = "Sony Vaio VGN-FW520F",
293  	.matches = {
294  		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
295  		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"),
296  		},
297  	},
298  	{
299  	.callback = init_nvs_nosave,
300  	.ident = "Asus K54C",
301  	.matches = {
302  		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
303  		DMI_MATCH(DMI_PRODUCT_NAME, "K54C"),
304  		},
305  	},
306  	{
307  	.callback = init_nvs_nosave,
308  	.ident = "Asus K54HR",
309  	.matches = {
310  		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
311  		DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"),
312  		},
313  	},
314  	{},
315  };
316  
acpi_sleep_dmi_check(void)317  static void acpi_sleep_dmi_check(void)
318  {
319  	dmi_check_system(acpisleep_dmi_table);
320  }
321  
322  /**
323   * acpi_pm_freeze - Disable the GPEs and suspend EC transactions.
324   */
acpi_pm_freeze(void)325  static int acpi_pm_freeze(void)
326  {
327  	acpi_disable_all_gpes();
328  	acpi_os_wait_events_complete();
329  	acpi_ec_block_transactions();
330  	return 0;
331  }
332  
333  /**
334   * acpi_pre_suspend - Enable wakeup devices, "freeze" EC and save NVS.
335   */
acpi_pm_pre_suspend(void)336  static int acpi_pm_pre_suspend(void)
337  {
338  	acpi_pm_freeze();
339  	return suspend_nvs_save();
340  }
341  
342  /**
343   *	__acpi_pm_prepare - Prepare the platform to enter the target state.
344   *
345   *	If necessary, set the firmware waking vector and do arch-specific
346   *	nastiness to get the wakeup code to the waking vector.
347   */
__acpi_pm_prepare(void)348  static int __acpi_pm_prepare(void)
349  {
350  	int error = acpi_sleep_prepare(acpi_target_sleep_state);
351  	if (error)
352  		acpi_target_sleep_state = ACPI_STATE_S0;
353  
354  	return error;
355  }
356  
357  /**
358   *	acpi_pm_prepare - Prepare the platform to enter the target sleep
359   *		state and disable the GPEs.
360   */
acpi_pm_prepare(void)361  static int acpi_pm_prepare(void)
362  {
363  	int error = __acpi_pm_prepare();
364  	if (!error)
365  		error = acpi_pm_pre_suspend();
366  
367  	return error;
368  }
369  
find_powerf_dev(struct device * dev,void * data)370  static int find_powerf_dev(struct device *dev, void *data)
371  {
372  	struct acpi_device *device = to_acpi_device(dev);
373  	const char *hid = acpi_device_hid(device);
374  
375  	return !strcmp(hid, ACPI_BUTTON_HID_POWERF);
376  }
377  
378  /**
379   *	acpi_pm_finish - Instruct the platform to leave a sleep state.
380   *
381   *	This is called after we wake back up (or if entering the sleep state
382   *	failed).
383   */
acpi_pm_finish(void)384  static void acpi_pm_finish(void)
385  {
386  	struct device *pwr_btn_dev;
387  	u32 acpi_state = acpi_target_sleep_state;
388  
389  	acpi_ec_unblock_transactions();
390  	suspend_nvs_free();
391  
392  	if (acpi_state == ACPI_STATE_S0)
393  		return;
394  
395  	printk(KERN_INFO PREFIX "Waking up from system sleep state S%d\n",
396  		acpi_state);
397  	acpi_disable_wakeup_devices(acpi_state);
398  	acpi_leave_sleep_state(acpi_state);
399  
400  	/* reset firmware waking vector */
401  	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
402  
403  	acpi_target_sleep_state = ACPI_STATE_S0;
404  
405  	acpi_resume_power_resources();
406  
407  	/* If we were woken with the fixed power button, provide a small
408  	 * hint to userspace in the form of a wakeup event on the fixed power
409  	 * button device (if it can be found).
410  	 *
411  	 * We delay the event generation til now, as the PM layer requires
412  	 * timekeeping to be running before we generate events. */
413  	if (!pwr_btn_event_pending)
414  		return;
415  
416  	pwr_btn_event_pending = false;
417  	pwr_btn_dev = bus_find_device(&acpi_bus_type, NULL, NULL,
418  				      find_powerf_dev);
419  	if (pwr_btn_dev) {
420  		pm_wakeup_event(pwr_btn_dev, 0);
421  		put_device(pwr_btn_dev);
422  	}
423  }
424  
425  /**
426   *	acpi_pm_end - Finish up suspend sequence.
427   */
acpi_pm_end(void)428  static void acpi_pm_end(void)
429  {
430  	/*
431  	 * This is necessary in case acpi_pm_finish() is not called during a
432  	 * failing transition to a sleep state.
433  	 */
434  	acpi_target_sleep_state = ACPI_STATE_S0;
435  	acpi_sleep_tts_switch(acpi_target_sleep_state);
436  }
437  #else /* !CONFIG_ACPI_SLEEP */
438  #define acpi_target_sleep_state	ACPI_STATE_S0
acpi_sleep_dmi_check(void)439  static inline void acpi_sleep_dmi_check(void) {}
440  #endif /* CONFIG_ACPI_SLEEP */
441  
442  #ifdef CONFIG_SUSPEND
443  static u32 acpi_suspend_states[] = {
444  	[PM_SUSPEND_ON] = ACPI_STATE_S0,
445  	[PM_SUSPEND_STANDBY] = ACPI_STATE_S1,
446  	[PM_SUSPEND_MEM] = ACPI_STATE_S3,
447  	[PM_SUSPEND_MAX] = ACPI_STATE_S5
448  };
449  
450  /**
451   *	acpi_suspend_begin - Set the target system sleep state to the state
452   *		associated with given @pm_state, if supported.
453   */
acpi_suspend_begin(suspend_state_t pm_state)454  static int acpi_suspend_begin(suspend_state_t pm_state)
455  {
456  	u32 acpi_state = acpi_suspend_states[pm_state];
457  	int error = 0;
458  
459  	error = (nvs_nosave || nvs_nosave_s3) ? 0 : suspend_nvs_alloc();
460  	if (error)
461  		return error;
462  
463  	if (sleep_states[acpi_state]) {
464  		acpi_target_sleep_state = acpi_state;
465  		acpi_sleep_tts_switch(acpi_target_sleep_state);
466  	} else {
467  		printk(KERN_ERR "ACPI does not support this state: %d\n",
468  			pm_state);
469  		error = -ENOSYS;
470  	}
471  	return error;
472  }
473  
474  /**
475   *	acpi_suspend_enter - Actually enter a sleep state.
476   *	@pm_state: ignored
477   *
478   *	Flush caches and go to sleep. For STR we have to call arch-specific
479   *	assembly, which in turn call acpi_enter_sleep_state().
480   *	It's unfortunate, but it works. Please fix if you're feeling frisky.
481   */
acpi_suspend_enter(suspend_state_t pm_state)482  static int acpi_suspend_enter(suspend_state_t pm_state)
483  {
484  	acpi_status status = AE_OK;
485  	u32 acpi_state = acpi_target_sleep_state;
486  	int error;
487  
488  	ACPI_FLUSH_CPU_CACHE();
489  
490  	switch (acpi_state) {
491  	case ACPI_STATE_S1:
492  		barrier();
493  		status = acpi_enter_sleep_state(acpi_state);
494  		break;
495  
496  	case ACPI_STATE_S3:
497  		error = acpi_suspend_lowlevel();
498  		if (error)
499  			return error;
500  		pr_info(PREFIX "Low-level resume complete\n");
501  		break;
502  	}
503  
504  	/* This violates the spec but is required for bug compatibility. */
505  	acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
506  
507  	/* Reprogram control registers */
508  	acpi_leave_sleep_state_prep(acpi_state);
509  
510  	/* ACPI 3.0 specs (P62) says that it's the responsibility
511  	 * of the OSPM to clear the status bit [ implying that the
512  	 * POWER_BUTTON event should not reach userspace ]
513  	 *
514  	 * However, we do generate a small hint for userspace in the form of
515  	 * a wakeup event. We flag this condition for now and generate the
516  	 * event later, as we're currently too early in resume to be able to
517  	 * generate wakeup events.
518  	 */
519  	if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) {
520  		acpi_event_status pwr_btn_status;
521  
522  		acpi_get_event_status(ACPI_EVENT_POWER_BUTTON, &pwr_btn_status);
523  
524  		if (pwr_btn_status & ACPI_EVENT_FLAG_SET) {
525  			acpi_clear_event(ACPI_EVENT_POWER_BUTTON);
526  			/* Flag for later */
527  			pwr_btn_event_pending = true;
528  		}
529  	}
530  
531  	/*
532  	 * Disable and clear GPE status before interrupt is enabled. Some GPEs
533  	 * (like wakeup GPE) haven't handler, this can avoid such GPE misfire.
534  	 * acpi_leave_sleep_state will reenable specific GPEs later
535  	 */
536  	acpi_disable_all_gpes();
537  	/* Allow EC transactions to happen. */
538  	acpi_ec_unblock_transactions_early();
539  
540  	suspend_nvs_restore();
541  
542  	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
543  }
544  
acpi_suspend_state_valid(suspend_state_t pm_state)545  static int acpi_suspend_state_valid(suspend_state_t pm_state)
546  {
547  	u32 acpi_state;
548  
549  	switch (pm_state) {
550  	case PM_SUSPEND_ON:
551  	case PM_SUSPEND_STANDBY:
552  	case PM_SUSPEND_MEM:
553  		acpi_state = acpi_suspend_states[pm_state];
554  
555  		return sleep_states[acpi_state];
556  	default:
557  		return 0;
558  	}
559  }
560  
561  static const struct platform_suspend_ops acpi_suspend_ops = {
562  	.valid = acpi_suspend_state_valid,
563  	.begin = acpi_suspend_begin,
564  	.prepare_late = acpi_pm_prepare,
565  	.enter = acpi_suspend_enter,
566  	.wake = acpi_pm_finish,
567  	.end = acpi_pm_end,
568  };
569  
570  /**
571   *	acpi_suspend_begin_old - Set the target system sleep state to the
572   *		state associated with given @pm_state, if supported, and
573   *		execute the _PTS control method.  This function is used if the
574   *		pre-ACPI 2.0 suspend ordering has been requested.
575   */
acpi_suspend_begin_old(suspend_state_t pm_state)576  static int acpi_suspend_begin_old(suspend_state_t pm_state)
577  {
578  	int error = acpi_suspend_begin(pm_state);
579  	if (!error)
580  		error = __acpi_pm_prepare();
581  
582  	return error;
583  }
584  
585  /*
586   * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has
587   * been requested.
588   */
589  static const struct platform_suspend_ops acpi_suspend_ops_old = {
590  	.valid = acpi_suspend_state_valid,
591  	.begin = acpi_suspend_begin_old,
592  	.prepare_late = acpi_pm_pre_suspend,
593  	.enter = acpi_suspend_enter,
594  	.wake = acpi_pm_finish,
595  	.end = acpi_pm_end,
596  	.recover = acpi_pm_finish,
597  };
598  
acpi_sleep_suspend_setup(void)599  static void acpi_sleep_suspend_setup(void)
600  {
601  	int i;
602  
603  	for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) {
604  		acpi_status status;
605  		u8 type_a, type_b;
606  
607  		status = acpi_get_sleep_type_data(i, &type_a, &type_b);
608  		if (ACPI_SUCCESS(status)) {
609  			sleep_states[i] = 1;
610  		}
611  	}
612  
613  	suspend_set_ops(old_suspend_ordering ?
614  		&acpi_suspend_ops_old : &acpi_suspend_ops);
615  }
616  #else /* !CONFIG_SUSPEND */
acpi_sleep_suspend_setup(void)617  static inline void acpi_sleep_suspend_setup(void) {}
618  #endif /* !CONFIG_SUSPEND */
619  
620  #ifdef CONFIG_HIBERNATION
621  static unsigned long s4_hardware_signature;
622  static struct acpi_table_facs *facs;
623  static bool nosigcheck;
624  
acpi_no_s4_hw_signature(void)625  void __init acpi_no_s4_hw_signature(void)
626  {
627  	nosigcheck = true;
628  }
629  
acpi_hibernation_begin(void)630  static int acpi_hibernation_begin(void)
631  {
632  	int error;
633  
634  	error = nvs_nosave ? 0 : suspend_nvs_alloc();
635  	if (!error) {
636  		acpi_target_sleep_state = ACPI_STATE_S4;
637  		acpi_sleep_tts_switch(acpi_target_sleep_state);
638  	}
639  
640  	return error;
641  }
642  
acpi_hibernation_enter(void)643  static int acpi_hibernation_enter(void)
644  {
645  	acpi_status status = AE_OK;
646  
647  	ACPI_FLUSH_CPU_CACHE();
648  
649  	/* This shouldn't return.  If it returns, we have a problem */
650  	status = acpi_enter_sleep_state(ACPI_STATE_S4);
651  	/* Reprogram control registers */
652  	acpi_leave_sleep_state_prep(ACPI_STATE_S4);
653  
654  	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
655  }
656  
acpi_hibernation_leave(void)657  static void acpi_hibernation_leave(void)
658  {
659  	/*
660  	 * If ACPI is not enabled by the BIOS and the boot kernel, we need to
661  	 * enable it here.
662  	 */
663  	acpi_enable();
664  	/* Reprogram control registers */
665  	acpi_leave_sleep_state_prep(ACPI_STATE_S4);
666  	/* Check the hardware signature */
667  	if (facs && s4_hardware_signature != facs->hardware_signature) {
668  		printk(KERN_EMERG "ACPI: Hardware changed while hibernated, "
669  			"cannot resume!\n");
670  		panic("ACPI S4 hardware signature mismatch");
671  	}
672  	/* Restore the NVS memory area */
673  	suspend_nvs_restore();
674  	/* Allow EC transactions to happen. */
675  	acpi_ec_unblock_transactions_early();
676  }
677  
acpi_pm_thaw(void)678  static void acpi_pm_thaw(void)
679  {
680  	acpi_ec_unblock_transactions();
681  	acpi_enable_all_runtime_gpes();
682  }
683  
684  static const struct platform_hibernation_ops acpi_hibernation_ops = {
685  	.begin = acpi_hibernation_begin,
686  	.end = acpi_pm_end,
687  	.pre_snapshot = acpi_pm_prepare,
688  	.finish = acpi_pm_finish,
689  	.prepare = acpi_pm_prepare,
690  	.enter = acpi_hibernation_enter,
691  	.leave = acpi_hibernation_leave,
692  	.pre_restore = acpi_pm_freeze,
693  	.restore_cleanup = acpi_pm_thaw,
694  };
695  
696  /**
697   *	acpi_hibernation_begin_old - Set the target system sleep state to
698   *		ACPI_STATE_S4 and execute the _PTS control method.  This
699   *		function is used if the pre-ACPI 2.0 suspend ordering has been
700   *		requested.
701   */
acpi_hibernation_begin_old(void)702  static int acpi_hibernation_begin_old(void)
703  {
704  	int error;
705  	/*
706  	 * The _TTS object should always be evaluated before the _PTS object.
707  	 * When the old_suspended_ordering is true, the _PTS object is
708  	 * evaluated in the acpi_sleep_prepare.
709  	 */
710  	acpi_sleep_tts_switch(ACPI_STATE_S4);
711  
712  	error = acpi_sleep_prepare(ACPI_STATE_S4);
713  
714  	if (!error) {
715  		if (!nvs_nosave)
716  			error = suspend_nvs_alloc();
717  		if (!error)
718  			acpi_target_sleep_state = ACPI_STATE_S4;
719  	}
720  	return error;
721  }
722  
723  /*
724   * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has
725   * been requested.
726   */
727  static const struct platform_hibernation_ops acpi_hibernation_ops_old = {
728  	.begin = acpi_hibernation_begin_old,
729  	.end = acpi_pm_end,
730  	.pre_snapshot = acpi_pm_pre_suspend,
731  	.prepare = acpi_pm_freeze,
732  	.finish = acpi_pm_finish,
733  	.enter = acpi_hibernation_enter,
734  	.leave = acpi_hibernation_leave,
735  	.pre_restore = acpi_pm_freeze,
736  	.restore_cleanup = acpi_pm_thaw,
737  	.recover = acpi_pm_finish,
738  };
739  
acpi_sleep_hibernate_setup(void)740  static void acpi_sleep_hibernate_setup(void)
741  {
742  	acpi_status status;
743  	u8 type_a, type_b;
744  
745  	status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b);
746  	if (ACPI_FAILURE(status))
747  		return;
748  
749  	hibernation_set_ops(old_suspend_ordering ?
750  			&acpi_hibernation_ops_old : &acpi_hibernation_ops);
751  	sleep_states[ACPI_STATE_S4] = 1;
752  	if (nosigcheck)
753  		return;
754  
755  	acpi_get_table(ACPI_SIG_FACS, 1, (struct acpi_table_header **)&facs);
756  	if (facs)
757  		s4_hardware_signature = facs->hardware_signature;
758  }
759  #else /* !CONFIG_HIBERNATION */
acpi_sleep_hibernate_setup(void)760  static inline void acpi_sleep_hibernate_setup(void) {}
761  #endif /* !CONFIG_HIBERNATION */
762  
acpi_suspend(u32 acpi_state)763  int acpi_suspend(u32 acpi_state)
764  {
765  	suspend_state_t states[] = {
766  		[1] = PM_SUSPEND_STANDBY,
767  		[3] = PM_SUSPEND_MEM,
768  		[5] = PM_SUSPEND_MAX
769  	};
770  
771  	if (acpi_state < 6 && states[acpi_state])
772  		return pm_suspend(states[acpi_state]);
773  	if (acpi_state == 4)
774  		return hibernate();
775  	return -EINVAL;
776  }
777  
acpi_power_off_prepare(void)778  static void acpi_power_off_prepare(void)
779  {
780  	/* Prepare to power off the system */
781  	acpi_sleep_prepare(ACPI_STATE_S5);
782  	acpi_disable_all_gpes();
783  }
784  
acpi_power_off(void)785  static void acpi_power_off(void)
786  {
787  	/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
788  	printk(KERN_DEBUG "%s called\n", __func__);
789  	local_irq_disable();
790  	acpi_enter_sleep_state(ACPI_STATE_S5);
791  }
792  
acpi_sleep_init(void)793  int __init acpi_sleep_init(void)
794  {
795  	acpi_status status;
796  	u8 type_a, type_b;
797  	char supported[ACPI_S_STATE_COUNT * 3 + 1];
798  	char *pos = supported;
799  	int i;
800  
801  	if (acpi_disabled)
802  		return 0;
803  
804  	acpi_sleep_dmi_check();
805  
806  	sleep_states[ACPI_STATE_S0] = 1;
807  
808  	acpi_sleep_suspend_setup();
809  	acpi_sleep_hibernate_setup();
810  
811  	status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
812  	if (ACPI_SUCCESS(status)) {
813  		sleep_states[ACPI_STATE_S5] = 1;
814  		pm_power_off_prepare = acpi_power_off_prepare;
815  		pm_power_off = acpi_power_off;
816  	}
817  
818  	supported[0] = 0;
819  	for (i = 0; i < ACPI_S_STATE_COUNT; i++) {
820  		if (sleep_states[i])
821  			pos += sprintf(pos, " S%d", i);
822  	}
823  	pr_info(PREFIX "(supports%s)\n", supported);
824  
825  	/*
826  	 * Register the tts_notifier to reboot notifier list so that the _TTS
827  	 * object can also be evaluated when the system enters S5.
828  	 */
829  	register_reboot_notifier(&tts_notifier);
830  	return 0;
831  }
832