}
 }
 
+static int acpi_hibernation_pre_restore(void)
+{
+       acpi_status status;
+
+       status = acpi_hw_disable_all_gpes();
+
+       return ACPI_SUCCESS(status) ? 0 : -EFAULT;
+}
+
+static void acpi_hibernation_restore_cleanup(void)
+{
+       acpi_hw_enable_all_runtime_gpes();
+}
+
 static struct hibernation_ops acpi_hibernation_ops = {
        .prepare = acpi_hibernation_prepare,
        .enter = acpi_hibernation_enter,
        .finish = acpi_hibernation_finish,
+       .pre_restore = acpi_hibernation_pre_restore,
+       .restore_cleanup = acpi_hibernation_restore_cleanup,
 };
 #endif                         /* CONFIG_SOFTWARE_SUSPEND */
 
 
  * @prepare: prepare system for hibernation
  * @enter: shut down system after state has been saved to disk
  * @finish: finish/clean up after state has been reloaded
+ * @pre_restore: prepare system for the restoration from a hibernation image
+ * @restore_cleanup: clean up after a failing image restoration
  */
 struct hibernation_ops {
        int (*prepare)(void);
        int (*enter)(void);
        void (*finish)(void);
+       int (*pre_restore)(void);
+       void (*restore_cleanup)(void);
 };
 
 #if defined(CONFIG_PM) && defined(CONFIG_SOFTWARE_SUSPEND)
 
 
 void hibernation_set_ops(struct hibernation_ops *ops)
 {
-       if (ops && !(ops->prepare && ops->enter && ops->finish)) {
+       if (ops && !(ops->prepare && ops->enter && ops->finish
+           && ops->pre_restore && ops->restore_cleanup)) {
                WARN_ON(1);
                return;
        }
                hibernation_ops->finish();
 }
 
+/**
+ *     platform_pre_restore - prepare the platform for the restoration from a
+ *     hibernation image.  If the restore fails after this function has been
+ *     called, platform_restore_cleanup() must be called.
+ */
+
+static int platform_pre_restore(int platform_mode)
+{
+       return (platform_mode && hibernation_ops) ?
+               hibernation_ops->pre_restore() : 0;
+}
+
+/**
+ *     platform_restore_cleanup - switch the platform to the normal mode of
+ *     operation after a failing restore.  If platform_pre_restore() has been
+ *     called before the failing restore, this function must be called too,
+ *     regardless of the result of platform_pre_restore().
+ */
+
+static void platform_restore_cleanup(int platform_mode)
+{
+       if (platform_mode && hibernation_ops)
+               hibernation_ops->restore_cleanup();
+}
+
 /**
  *     hibernation_snapshot - quiesce devices and create the hibernation
  *     snapshot image.
 /**
  *     hibernation_restore - quiesce devices and restore the hibernation
  *     snapshot image.  If successful, control returns in hibernation_snaphot()
+ *     @platform_mode - if set, use the platform driver, if available, to
+ *                      prepare the platform frimware for the transition.
  *
  *     Must be called with pm_mutex held
  */
 
-int hibernation_restore(void)
+int hibernation_restore(int platform_mode)
 {
        int error;
 
        if (error)
                goto Finish;
 
-       error = disable_nonboot_cpus();
-       if (!error)
-               error = swsusp_resume();
-
-       enable_nonboot_cpus();
+       error = platform_pre_restore(platform_mode);
+       if (!error) {
+               error = disable_nonboot_cpus();
+               if (!error)
+                       error = swsusp_resume();
+               enable_nonboot_cpus();
+       }
+       platform_restore_cleanup(platform_mode);
  Finish:
        device_resume();
        resume_console();
        }
        error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
        if (in_suspend && !error) {
+               unsigned int flags = 0;
+
+               if (hibernation_mode == HIBERNATION_PLATFORM)
+                       flags |= SF_PLATFORM_MODE;
                pr_debug("PM: writing image.\n");
-               error = swsusp_write();
+               error = swsusp_write(flags);
                swsusp_free();
                if (!error)
                        power_down();
 static int software_resume(void)
 {
        int error;
+       unsigned int flags;
 
        mutex_lock(&pm_mutex);
        if (!swsusp_resume_device) {
 
        pr_debug("PM: Reading swsusp image.\n");
 
-       error = swsusp_read();
+       error = swsusp_read(&flags);
        if (!error)
-               hibernation_restore();
+               hibernation_restore(flags & SF_PLATFORM_MODE);
 
        printk(KERN_ERR "PM: Restore failed, recovering.\n");
        swsusp_free();
 
 
 /* kernel/power/disk.c */
 extern int hibernation_snapshot(int platform_mode);
-extern int hibernation_restore(void);
+extern int hibernation_restore(int platform_mode);
 extern int hibernation_platform_enter(void);
 #endif
 
 extern void free_all_swap_pages(int swap);
 extern int swsusp_swap_in_use(void);
 
+/*
+ * Flags that can be passed from the hibernatig hernel to the "boot" kernel in
+ * the image header.
+ */
+#define SF_PLATFORM_MODE       1
+
+/* kernel/power/disk.c */
 extern int swsusp_check(void);
 extern int swsusp_shrink_memory(void);
 extern void swsusp_free(void);
 extern int swsusp_suspend(void);
 extern int swsusp_resume(void);
-extern int swsusp_read(void);
-extern int swsusp_write(void);
+extern int swsusp_read(unsigned int *flags_p);
+extern int swsusp_write(unsigned int flags);
 extern void swsusp_close(void);
 extern int suspend_enter(suspend_state_t state);
 
 
 #define SWSUSP_SIG     "S1SUSPEND"
 
 struct swsusp_header {
-       char reserved[PAGE_SIZE - 20 - sizeof(sector_t)];
+       char reserved[PAGE_SIZE - 20 - sizeof(sector_t) - sizeof(int)];
        sector_t image;
+       unsigned int flags;     /* Flags to pass to the "boot" kernel */
        char    orig_sig[10];
        char    sig[10];
 } __attribute__((packed));
  * Saving part
  */
 
-static int mark_swapfiles(sector_t start)
+static int mark_swapfiles(sector_t start, unsigned int flags)
 {
        int error;
 
                memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10);
                memcpy(swsusp_header->sig,SWSUSP_SIG, 10);
                swsusp_header->image = start;
+               swsusp_header->flags = flags;
                error = bio_write_page(swsusp_resume_block,
                                        swsusp_header, NULL);
        } else {
 
 /**
  *     swsusp_write - Write entire image and metadata.
+ *     @flags: flags to pass to the "boot" kernel in the image header
  *
  *     It is important _NOT_ to umount filesystems at this point. We want
  *     them synced (in case something goes wrong) but we DO not want to mark
  *     correctly, we'll mark system clean, anyway.)
  */
 
-int swsusp_write(void)
+int swsusp_write(unsigned int flags)
 {
        struct swap_map_handle handle;
        struct snapshot_handle snapshot;
                if (!error) {
                        flush_swap_writer(&handle);
                        printk("S");
-                       error = mark_swapfiles(start);
+                       error = mark_swapfiles(start, flags);
                        printk("|\n");
                }
        }
        return error;
 }
 
-int swsusp_read(void)
+/**
+ *     swsusp_read - read the hibernation image.
+ *     @flags_p: flags passed by the "frozen" kernel in the image header should
+ *               be written into this memeory location
+ */
+
+int swsusp_read(unsigned int *flags_p)
 {
        int error;
        struct swap_map_handle handle;
        struct snapshot_handle snapshot;
        struct swsusp_info *header;
 
+       *flags_p = swsusp_header->flags;
        if (IS_ERR(resume_bdev)) {
                pr_debug("swsusp: block device not initialised\n");
                return PTR_ERR(resume_bdev);
 
                        error = -EPERM;
                        break;
                }
-               error = hibernation_restore();
+               error = hibernation_restore(data->platform_suspend);
                break;
 
        case SNAPSHOT_FREE: