acpi_irq_handler = handler;
acpi_irq_context = context;
- if (request_irq(irq, acpi_irq, IRQF_SHARED | IRQF_NO_SUSPEND, "acpi", acpi_irq)) {
+ if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) {
printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
acpi_irq_handler = NULL;
return AE_NOT_ACQUIRED;
#include <linux/irq.h>
#include <linux/dmi.h>
#include <linux/device.h>
+#include <linux/interrupt.h>
#include <linux/suspend.h>
#include <linux/reboot.h>
#include <linux/acpi.h>
return 0;
}
+static int acpi_freeze_prepare(void)
+{
+ acpi_enable_all_wakeup_gpes();
+ enable_irq_wake(acpi_gbl_FADT.sci_interrupt);
+ return 0;
+}
+
+static void acpi_freeze_restore(void)
+{
+ disable_irq_wake(acpi_gbl_FADT.sci_interrupt);
+ acpi_enable_all_runtime_gpes();
+}
+
static void acpi_freeze_end(void)
{
acpi_scan_lock_release();
static const struct platform_freeze_ops acpi_freeze_ops = {
.begin = acpi_freeze_begin,
+ .prepare = acpi_freeze_prepare,
+ .restore = acpi_freeze_restore,
.end = acpi_freeze_end,
};
struct platform_freeze_ops {
int (*begin)(void);
+ int (*prepare)(void);
+ void (*restore)(void);
void (*end)(void);
};
suspend_ops->prepare() : 0;
}
+static int platform_suspend_prepare_late(suspend_state_t state)
+{
+ return state == PM_SUSPEND_FREEZE && freeze_ops->prepare ?
+ freeze_ops->prepare() : 0;
+}
+
static int platform_suspend_prepare_noirq(suspend_state_t state)
{
return state != PM_SUSPEND_FREEZE && suspend_ops->prepare_late ?
suspend_ops->wake();
}
+static void platform_resume_early(suspend_state_t state)
+{
+ if (state == PM_SUSPEND_FREEZE && freeze_ops->restore)
+ freeze_ops->restore();
+}
+
static void platform_resume_finish(suspend_state_t state)
{
if (state != PM_SUSPEND_FREEZE && suspend_ops->finish)
printk(KERN_ERR "PM: late suspend of devices failed\n");
goto Platform_finish;
}
+ error = platform_suspend_prepare_late(state);
+ if (error)
+ goto Devices_early_resume;
+
error = dpm_suspend_noirq(PMSG_SUSPEND);
if (error) {
printk(KERN_ERR "PM: noirq suspend of devices failed\n");
- goto Devices_early_resume;
+ goto Platform_early_resume;
}
error = platform_suspend_prepare_noirq(state);
if (error)
platform_resume_noirq(state);
dpm_resume_noirq(PMSG_RESUME);
+ Platform_early_resume:
+ platform_resume_early(state);
+
Devices_early_resume:
dpm_resume_early(PMSG_RESUME);