aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlexey Starikovskiy <astarikovskiy@suse.de>2007-09-26 11:47:30 -0400
committerLen Brown <len.brown@intel.com>2007-09-27 15:47:44 -0400
commit9b039330808b83acac3597535da26f47ad1862ce (patch)
tree78933d5c925048f204c3d5ff6c0a0aa1aced8e84 /drivers
parentff0ce6845bc18292e80ea40d11c3d3a539a3fc5e (diff)
ACPI: Hibernate erroneously disabled Suspend wakeup devices
S4 suspend to disk will disable GPE's permanently because acpi_gpe_sleep_prepare() does not have a counterpart at resume time. Thus, those devices became unavailable for wakeup from subsequent S3 suspend-to-ram. Here acpi_gpe_sleep_prepare() is removed, and upon suspend acpi_enable_wakeup_device() gets its functionality. Upon resume, acpi_disable_wakeup_device() restores the state. https://bugzilla.novell.com/show_bug.cgi?id=292300 Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de> Acked-by: Pavel Machek <pavel@suse.cz> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/sleep/main.c1
-rw-r--r--drivers/acpi/sleep/sleep.h1
-rw-r--r--drivers/acpi/sleep/wakeup.c117
3 files changed, 40 insertions, 79 deletions
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 2cbb9aabd00e..9426ac1fc86b 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -44,7 +44,6 @@ int acpi_sleep_prepare(u32 acpi_state)
44 ACPI_FLUSH_CPU_CACHE(); 44 ACPI_FLUSH_CPU_CACHE();
45 acpi_enable_wakeup_device_prep(acpi_state); 45 acpi_enable_wakeup_device_prep(acpi_state);
46#endif 46#endif
47 acpi_gpe_sleep_prepare(acpi_state);
48 acpi_enter_sleep_state_prep(acpi_state); 47 acpi_enter_sleep_state_prep(acpi_state);
49 return 0; 48 return 0;
50} 49}
diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h
index ff1f8504f497..a2ea125ae2d0 100644
--- a/drivers/acpi/sleep/sleep.h
+++ b/drivers/acpi/sleep/sleep.h
@@ -5,6 +5,5 @@ extern int acpi_suspend (u32 state);
5extern void acpi_enable_wakeup_device_prep(u8 sleep_state); 5extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
6extern void acpi_enable_wakeup_device(u8 sleep_state); 6extern void acpi_enable_wakeup_device(u8 sleep_state);
7extern void acpi_disable_wakeup_device(u8 sleep_state); 7extern void acpi_disable_wakeup_device(u8 sleep_state);
8extern void acpi_gpe_sleep_prepare(u32 sleep_state);
9 8
10extern int acpi_sleep_prepare(u32 acpi_state); 9extern int acpi_sleep_prepare(u32 acpi_state);
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c
index 97c27ddb144d..ed8e41becf0c 100644
--- a/drivers/acpi/sleep/wakeup.c
+++ b/drivers/acpi/sleep/wakeup.c
@@ -64,36 +64,29 @@ void acpi_enable_wakeup_device(u8 sleep_state)
64 ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device"); 64 ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device");
65 spin_lock(&acpi_device_lock); 65 spin_lock(&acpi_device_lock);
66 list_for_each_safe(node, next, &acpi_wakeup_device_list) { 66 list_for_each_safe(node, next, &acpi_wakeup_device_list) {
67 struct acpi_device *dev = container_of(node, 67 struct acpi_device *dev =
68 struct acpi_device, 68 container_of(node, struct acpi_device, wakeup_list);
69 wakeup_list); 69 if (!dev->wakeup.flags.valid)
70 70 continue;
71 /* If users want to disable run-wake GPE, 71 /* If users want to disable run-wake GPE,
72 * we only disable it for wake and leave it for runtime 72 * we only disable it for wake and leave it for runtime
73 */ 73 */
74 if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) { 74 if (!dev->wakeup.state.enabled ||
75 spin_unlock(&acpi_device_lock); 75 sleep_state > (u32) dev->wakeup.sleep_state) {
76 acpi_set_gpe_type(dev->wakeup.gpe_device, 76 if (dev->wakeup.flags.run_wake) {
77 dev->wakeup.gpe_number, 77 spin_unlock(&acpi_device_lock);
78 ACPI_GPE_TYPE_RUNTIME); 78 /* set_gpe_type will disable GPE, leave it like that */
79 /* Re-enable it, since set_gpe_type will disable it */ 79 acpi_set_gpe_type(dev->wakeup.gpe_device,
80 acpi_enable_gpe(dev->wakeup.gpe_device, 80 dev->wakeup.gpe_number,
81 dev->wakeup.gpe_number, ACPI_ISR); 81 ACPI_GPE_TYPE_RUNTIME);
82 spin_lock(&acpi_device_lock); 82 spin_lock(&acpi_device_lock);
83 }
83 continue; 84 continue;
84 } 85 }
85
86 if (!dev->wakeup.flags.valid ||
87 !dev->wakeup.state.enabled ||
88 (sleep_state > (u32) dev->wakeup.sleep_state))
89 continue;
90
91 spin_unlock(&acpi_device_lock); 86 spin_unlock(&acpi_device_lock);
92 /* run-wake GPE has been enabled */
93 if (!dev->wakeup.flags.run_wake) 87 if (!dev->wakeup.flags.run_wake)
94 acpi_enable_gpe(dev->wakeup.gpe_device, 88 acpi_enable_gpe(dev->wakeup.gpe_device,
95 dev->wakeup.gpe_number, ACPI_ISR); 89 dev->wakeup.gpe_number, ACPI_ISR);
96 dev->wakeup.state.active = 1;
97 spin_lock(&acpi_device_lock); 90 spin_lock(&acpi_device_lock);
98 } 91 }
99 spin_unlock(&acpi_device_lock); 92 spin_unlock(&acpi_device_lock);
@@ -112,26 +105,25 @@ void acpi_disable_wakeup_device(u8 sleep_state)
112 105
113 spin_lock(&acpi_device_lock); 106 spin_lock(&acpi_device_lock);
114 list_for_each_safe(node, next, &acpi_wakeup_device_list) { 107 list_for_each_safe(node, next, &acpi_wakeup_device_list) {
115 struct acpi_device *dev = container_of(node, 108 struct acpi_device *dev =
116 struct acpi_device, 109 container_of(node, struct acpi_device, wakeup_list);
117 wakeup_list);
118 110
119 if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) { 111 if (!dev->wakeup.flags.valid)
120 spin_unlock(&acpi_device_lock);
121 acpi_set_gpe_type(dev->wakeup.gpe_device,
122 dev->wakeup.gpe_number,
123 ACPI_GPE_TYPE_WAKE_RUN);
124 /* Re-enable it, since set_gpe_type will disable it */
125 acpi_enable_gpe(dev->wakeup.gpe_device,
126 dev->wakeup.gpe_number, ACPI_NOT_ISR);
127 spin_lock(&acpi_device_lock);
128 continue; 112 continue;
129 } 113 if (!dev->wakeup.state.enabled ||
130 114 sleep_state > (u32) dev->wakeup.sleep_state) {
131 if (!dev->wakeup.flags.valid || 115 if (dev->wakeup.flags.run_wake) {
132 !dev->wakeup.state.active || 116 spin_unlock(&acpi_device_lock);
133 (sleep_state > (u32) dev->wakeup.sleep_state)) 117 acpi_set_gpe_type(dev->wakeup.gpe_device,
118 dev->wakeup.gpe_number,
119 ACPI_GPE_TYPE_WAKE_RUN);
120 /* Re-enable it, since set_gpe_type will disable it */
121 acpi_enable_gpe(dev->wakeup.gpe_device,
122 dev->wakeup.gpe_number, ACPI_NOT_ISR);
123 spin_lock(&acpi_device_lock);
124 }
134 continue; 125 continue;
126 }
135 127
136 spin_unlock(&acpi_device_lock); 128 spin_unlock(&acpi_device_lock);
137 acpi_disable_wakeup_device_power(dev); 129 acpi_disable_wakeup_device_power(dev);
@@ -142,7 +134,6 @@ void acpi_disable_wakeup_device(u8 sleep_state)
142 acpi_clear_gpe(dev->wakeup.gpe_device, 134 acpi_clear_gpe(dev->wakeup.gpe_device,
143 dev->wakeup.gpe_number, ACPI_NOT_ISR); 135 dev->wakeup.gpe_number, ACPI_NOT_ISR);
144 } 136 }
145 dev->wakeup.state.active = 0;
146 spin_lock(&acpi_device_lock); 137 spin_lock(&acpi_device_lock);
147 } 138 }
148 spin_unlock(&acpi_device_lock); 139 spin_unlock(&acpi_device_lock);
@@ -160,48 +151,20 @@ static int __init acpi_wakeup_device_init(void)
160 struct acpi_device *dev = container_of(node, 151 struct acpi_device *dev = container_of(node,
161 struct acpi_device, 152 struct acpi_device,
162 wakeup_list); 153 wakeup_list);
163
164 /* In case user doesn't load button driver */ 154 /* In case user doesn't load button driver */
165 if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) { 155 if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled)
166 spin_unlock(&acpi_device_lock); 156 continue;
167 acpi_set_gpe_type(dev->wakeup.gpe_device, 157 spin_unlock(&acpi_device_lock);
168 dev->wakeup.gpe_number, 158 acpi_set_gpe_type(dev->wakeup.gpe_device,
169 ACPI_GPE_TYPE_WAKE_RUN); 159 dev->wakeup.gpe_number,
170 acpi_enable_gpe(dev->wakeup.gpe_device, 160 ACPI_GPE_TYPE_WAKE_RUN);
171 dev->wakeup.gpe_number, ACPI_NOT_ISR); 161 acpi_enable_gpe(dev->wakeup.gpe_device,
172 dev->wakeup.state.enabled = 1; 162 dev->wakeup.gpe_number, ACPI_NOT_ISR);
173 spin_lock(&acpi_device_lock); 163 dev->wakeup.state.enabled = 1;
174 } 164 spin_lock(&acpi_device_lock);
175 } 165 }
176 spin_unlock(&acpi_device_lock); 166 spin_unlock(&acpi_device_lock);
177
178 return 0; 167 return 0;
179} 168}
180 169
181late_initcall(acpi_wakeup_device_init); 170late_initcall(acpi_wakeup_device_init);
182
183/*
184 * Disable all wakeup GPEs before entering requested sleep state.
185 * @sleep_state: ACPI state
186 * Since acpi_enter_sleep_state() will disable all
187 * RUNTIME GPEs, we simply mark all GPES that
188 * are not enabled for wakeup from requested state as RUNTIME.
189 */
190void acpi_gpe_sleep_prepare(u32 sleep_state)
191{
192 struct list_head *node, *next;
193
194 list_for_each_safe(node, next, &acpi_wakeup_device_list) {
195 struct acpi_device *dev = container_of(node,
196 struct acpi_device,
197 wakeup_list);
198
199 /* The GPE can wakeup system from this state, don't touch it */
200 if ((u32) dev->wakeup.sleep_state >= sleep_state)
201 continue;
202 /* acpi_set_gpe_type will automatically disable GPE */
203 acpi_set_gpe_type(dev->wakeup.gpe_device,
204 dev->wakeup.gpe_number,
205 ACPI_GPE_TYPE_RUNTIME);
206 }
207}