aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/osl.c2
-rw-r--r--drivers/acpi/sleep.c16
-rw-r--r--include/linux/suspend.h2
-rw-r--r--kernel/power/suspend.c21
4 files changed, 39 insertions, 2 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 3abe9b223ba7..5ca29b5af8d1 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -825,7 +825,7 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
825 825
826 acpi_irq_handler = handler; 826 acpi_irq_handler = handler;
827 acpi_irq_context = context; 827 acpi_irq_context = context;
828 if (request_irq(irq, acpi_irq, IRQF_SHARED | IRQF_NO_SUSPEND, "acpi", acpi_irq)) { 828 if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) {
829 printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); 829 printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
830 acpi_irq_handler = NULL; 830 acpi_irq_handler = NULL;
831 return AE_NOT_ACQUIRED; 831 return AE_NOT_ACQUIRED;
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 54da4a3fe65e..05a31b573fc3 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -14,6 +14,7 @@
14#include <linux/irq.h> 14#include <linux/irq.h>
15#include <linux/dmi.h> 15#include <linux/dmi.h>
16#include <linux/device.h> 16#include <linux/device.h>
17#include <linux/interrupt.h>
17#include <linux/suspend.h> 18#include <linux/suspend.h>
18#include <linux/reboot.h> 19#include <linux/reboot.h>
19#include <linux/acpi.h> 20#include <linux/acpi.h>
@@ -626,6 +627,19 @@ static int acpi_freeze_begin(void)
626 return 0; 627 return 0;
627} 628}
628 629
630static int acpi_freeze_prepare(void)
631{
632 acpi_enable_all_wakeup_gpes();
633 enable_irq_wake(acpi_gbl_FADT.sci_interrupt);
634 return 0;
635}
636
637static void acpi_freeze_restore(void)
638{
639 disable_irq_wake(acpi_gbl_FADT.sci_interrupt);
640 acpi_enable_all_runtime_gpes();
641}
642
629static void acpi_freeze_end(void) 643static void acpi_freeze_end(void)
630{ 644{
631 acpi_scan_lock_release(); 645 acpi_scan_lock_release();
@@ -633,6 +647,8 @@ static void acpi_freeze_end(void)
633 647
634static const struct platform_freeze_ops acpi_freeze_ops = { 648static const struct platform_freeze_ops acpi_freeze_ops = {
635 .begin = acpi_freeze_begin, 649 .begin = acpi_freeze_begin,
650 .prepare = acpi_freeze_prepare,
651 .restore = acpi_freeze_restore,
636 .end = acpi_freeze_end, 652 .end = acpi_freeze_end,
637}; 653};
638 654
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 06a9910827c2..3388c1b6f7d8 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -189,6 +189,8 @@ struct platform_suspend_ops {
189 189
190struct platform_freeze_ops { 190struct platform_freeze_ops {
191 int (*begin)(void); 191 int (*begin)(void);
192 int (*prepare)(void);
193 void (*restore)(void);
192 void (*end)(void); 194 void (*end)(void);
193}; 195};
194 196
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index a25e768d92b5..4ca9a33ff620 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -144,6 +144,12 @@ static int platform_suspend_prepare(suspend_state_t state)
144 suspend_ops->prepare() : 0; 144 suspend_ops->prepare() : 0;
145} 145}
146 146
147static int platform_suspend_prepare_late(suspend_state_t state)
148{
149 return state == PM_SUSPEND_FREEZE && freeze_ops->prepare ?
150 freeze_ops->prepare() : 0;
151}
152
147static int platform_suspend_prepare_noirq(suspend_state_t state) 153static int platform_suspend_prepare_noirq(suspend_state_t state)
148{ 154{
149 return state != PM_SUSPEND_FREEZE && suspend_ops->prepare_late ? 155 return state != PM_SUSPEND_FREEZE && suspend_ops->prepare_late ?
@@ -156,6 +162,12 @@ static void platform_resume_noirq(suspend_state_t state)
156 suspend_ops->wake(); 162 suspend_ops->wake();
157} 163}
158 164
165static void platform_resume_early(suspend_state_t state)
166{
167 if (state == PM_SUSPEND_FREEZE && freeze_ops->restore)
168 freeze_ops->restore();
169}
170
159static void platform_resume_finish(suspend_state_t state) 171static void platform_resume_finish(suspend_state_t state)
160{ 172{
161 if (state != PM_SUSPEND_FREEZE && suspend_ops->finish) 173 if (state != PM_SUSPEND_FREEZE && suspend_ops->finish)
@@ -270,10 +282,14 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
270 printk(KERN_ERR "PM: late suspend of devices failed\n"); 282 printk(KERN_ERR "PM: late suspend of devices failed\n");
271 goto Platform_finish; 283 goto Platform_finish;
272 } 284 }
285 error = platform_suspend_prepare_late(state);
286 if (error)
287 goto Devices_early_resume;
288
273 error = dpm_suspend_noirq(PMSG_SUSPEND); 289 error = dpm_suspend_noirq(PMSG_SUSPEND);
274 if (error) { 290 if (error) {
275 printk(KERN_ERR "PM: noirq suspend of devices failed\n"); 291 printk(KERN_ERR "PM: noirq suspend of devices failed\n");
276 goto Devices_early_resume; 292 goto Platform_early_resume;
277 } 293 }
278 error = platform_suspend_prepare_noirq(state); 294 error = platform_suspend_prepare_noirq(state);
279 if (error) 295 if (error)
@@ -326,6 +342,9 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
326 platform_resume_noirq(state); 342 platform_resume_noirq(state);
327 dpm_resume_noirq(PMSG_RESUME); 343 dpm_resume_noirq(PMSG_RESUME);
328 344
345 Platform_early_resume:
346 platform_resume_early(state);
347
329 Devices_early_resume: 348 Devices_early_resume:
330 dpm_resume_early(PMSG_RESUME); 349 dpm_resume_early(PMSG_RESUME);
331 350