aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/sleep/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/sleep/main.c')
-rw-r--r--drivers/acpi/sleep/main.c84
1 files changed, 52 insertions, 32 deletions
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 42127c0d612c..19f8557c711c 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -34,34 +34,54 @@ static u32 acpi_suspend_states[] = {
34 34
35static int init_8259A_after_S1; 35static int init_8259A_after_S1;
36 36
37extern int acpi_sleep_prepare(u32 acpi_state);
38extern void acpi_power_off(void);
39
40static u32 acpi_target_sleep_state = ACPI_STATE_S0;
41
42/**
43 * acpi_pm_set_target - Set the target system sleep state to the state
44 * associated with given @pm_state, if supported.
45 */
46
47static int acpi_pm_set_target(suspend_state_t pm_state)
48{
49 u32 acpi_state = acpi_suspend_states[pm_state];
50 int error = 0;
51
52 if (sleep_states[acpi_state]) {
53 acpi_target_sleep_state = acpi_state;
54 } else {
55 printk(KERN_ERR "ACPI does not support this state: %d\n",
56 pm_state);
57 error = -ENOSYS;
58 }
59 return error;
60}
61
37/** 62/**
38 * acpi_pm_prepare - Do preliminary suspend work. 63 * acpi_pm_prepare - Do preliminary suspend work.
39 * @pm_state: suspend state we're entering. 64 * @pm_state: ignored
40 * 65 *
41 * Make sure we support the state. If we do, and we need it, set the 66 * If necessary, set the firmware waking vector and do arch-specific
42 * firmware waking vector and do arch-specific nastiness to get the 67 * nastiness to get the wakeup code to the waking vector.
43 * wakeup code to the waking vector.
44 */ 68 */
45 69
46extern int acpi_sleep_prepare(u32 acpi_state);
47extern void acpi_power_off(void);
48
49static int acpi_pm_prepare(suspend_state_t pm_state) 70static int acpi_pm_prepare(suspend_state_t pm_state)
50{ 71{
51 u32 acpi_state = acpi_suspend_states[pm_state]; 72 int error = acpi_sleep_prepare(acpi_target_sleep_state);
52 73
53 if (!sleep_states[acpi_state]) { 74 if (error)
54 printk("acpi_pm_prepare does not support %d \n", pm_state); 75 acpi_target_sleep_state = ACPI_STATE_S0;
55 return -EPERM; 76
56 } 77 return error;
57 return acpi_sleep_prepare(acpi_state);
58} 78}
59 79
60/** 80/**
61 * acpi_pm_enter - Actually enter a sleep state. 81 * acpi_pm_enter - Actually enter a sleep state.
62 * @pm_state: State we're entering. 82 * @pm_state: ignored
63 * 83 *
64 * Flush caches and go to sleep. For STR or STD, we have to call 84 * Flush caches and go to sleep. For STR or S2, we have to call
65 * arch-specific assembly, which in turn call acpi_enter_sleep_state(). 85 * arch-specific assembly, which in turn call acpi_enter_sleep_state().
66 * It's unfortunate, but it works. Please fix if you're feeling frisky. 86 * It's unfortunate, but it works. Please fix if you're feeling frisky.
67 */ 87 */
@@ -70,31 +90,32 @@ static int acpi_pm_enter(suspend_state_t pm_state)
70{ 90{
71 acpi_status status = AE_OK; 91 acpi_status status = AE_OK;
72 unsigned long flags = 0; 92 unsigned long flags = 0;
73 u32 acpi_state = acpi_suspend_states[pm_state]; 93 u32 acpi_state = acpi_target_sleep_state;
74 94
75 ACPI_FLUSH_CPU_CACHE(); 95 ACPI_FLUSH_CPU_CACHE();
76 96
77 /* Do arch specific saving of state. */ 97 /* Do arch specific saving of state. */
78 if (pm_state > PM_SUSPEND_STANDBY) { 98 if (acpi_state == ACPI_STATE_S2 || acpi_state == ACPI_STATE_S3) {
79 int error = acpi_save_state_mem(); 99 int error = acpi_save_state_mem();
80 if (error) 100
101 if (error) {
102 acpi_target_sleep_state = ACPI_STATE_S0;
81 return error; 103 return error;
104 }
82 } 105 }
83 106
84 local_irq_save(flags); 107 local_irq_save(flags);
85 acpi_enable_wakeup_device(acpi_state); 108 acpi_enable_wakeup_device(acpi_state);
86 switch (pm_state) { 109 switch (acpi_state) {
87 case PM_SUSPEND_STANDBY: 110 case ACPI_STATE_S1:
88 barrier(); 111 barrier();
89 status = acpi_enter_sleep_state(acpi_state); 112 status = acpi_enter_sleep_state(acpi_state);
90 break; 113 break;
91 114
92 case PM_SUSPEND_MEM: 115 case ACPI_STATE_S2:
116 case ACPI_STATE_S3:
93 do_suspend_lowlevel(); 117 do_suspend_lowlevel();
94 break; 118 break;
95
96 default:
97 return -EINVAL;
98 } 119 }
99 120
100 /* ACPI 3.0 specs (P62) says that it's the responsabilty 121 /* ACPI 3.0 specs (P62) says that it's the responsabilty
@@ -107,12 +128,8 @@ static int acpi_pm_enter(suspend_state_t pm_state)
107 local_irq_restore(flags); 128 local_irq_restore(flags);
108 printk(KERN_DEBUG "Back to C!\n"); 129 printk(KERN_DEBUG "Back to C!\n");
109 130
110 /* restore processor state 131 /* restore processor state */
111 * We should only be here if we're coming back from STR or STD. 132 if (acpi_state == ACPI_STATE_S2 || acpi_state == ACPI_STATE_S3)
112 * And, in the case of the latter, the memory image should have already
113 * been loaded from disk.
114 */
115 if (pm_state > PM_SUSPEND_STANDBY)
116 acpi_restore_state_mem(); 133 acpi_restore_state_mem();
117 134
118 return ACPI_SUCCESS(status) ? 0 : -EFAULT; 135 return ACPI_SUCCESS(status) ? 0 : -EFAULT;
@@ -120,7 +137,7 @@ static int acpi_pm_enter(suspend_state_t pm_state)
120 137
121/** 138/**
122 * acpi_pm_finish - Finish up suspend sequence. 139 * acpi_pm_finish - Finish up suspend sequence.
123 * @pm_state: State we're coming out of. 140 * @pm_state: ignored
124 * 141 *
125 * This is called after we wake back up (or if entering the sleep state 142 * This is called after we wake back up (or if entering the sleep state
126 * failed). 143 * failed).
@@ -128,7 +145,7 @@ static int acpi_pm_enter(suspend_state_t pm_state)
128 145
129static int acpi_pm_finish(suspend_state_t pm_state) 146static int acpi_pm_finish(suspend_state_t pm_state)
130{ 147{
131 u32 acpi_state = acpi_suspend_states[pm_state]; 148 u32 acpi_state = acpi_target_sleep_state;
132 149
133 acpi_leave_sleep_state(acpi_state); 150 acpi_leave_sleep_state(acpi_state);
134 acpi_disable_wakeup_device(acpi_state); 151 acpi_disable_wakeup_device(acpi_state);
@@ -136,6 +153,8 @@ static int acpi_pm_finish(suspend_state_t pm_state)
136 /* reset firmware waking vector */ 153 /* reset firmware waking vector */
137 acpi_set_firmware_waking_vector((acpi_physical_address) 0); 154 acpi_set_firmware_waking_vector((acpi_physical_address) 0);
138 155
156 acpi_target_sleep_state = ACPI_STATE_S0;
157
139 if (init_8259A_after_S1) { 158 if (init_8259A_after_S1) {
140 printk("Broken toshiba laptop -> kicking interrupts\n"); 159 printk("Broken toshiba laptop -> kicking interrupts\n");
141 init_8259A(0); 160 init_8259A(0);
@@ -176,6 +195,7 @@ static int acpi_pm_state_valid(suspend_state_t pm_state)
176 195
177static struct pm_ops acpi_pm_ops = { 196static struct pm_ops acpi_pm_ops = {
178 .valid = acpi_pm_state_valid, 197 .valid = acpi_pm_state_valid,
198 .set_target = acpi_pm_set_target,
179 .prepare = acpi_pm_prepare, 199 .prepare = acpi_pm_prepare,
180 .enter = acpi_pm_enter, 200 .enter = acpi_pm_enter,
181 .finish = acpi_pm_finish, 201 .finish = acpi_pm_finish,