* [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM
2010-05-28 20:32 [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality Matthew Garrett
@ 2010-05-28 20:32 ` Matthew Garrett
2010-05-30 14:40 ` Maxim Levitsky
` (2 more replies)
0 siblings, 3 replies; 21+ messages in thread
From: Matthew Garrett @ 2010-05-28 20:32 UTC (permalink / raw)
To: lenb; +Cc: linux-acpi, linux-pm, Matthew Garrett
https://bugzilla.kernel.org/show_bug.cgi?id=13931 describes a bug where
a system fails to successfully resume after the second suspend. Maxim
Levitsky discovered that this could be rectified by forcibly saving
and restoring the ACPI non-volatile state. The spec indicates that this
is only required for S4, but testing the behaviour of Windows by adding
an ACPI NVS region to qemu's e820 map and registering a custom memory
read/write handler reveals that it's saved and restored even over suspend
to RAM. We should mimic that behaviour to avoid other broken platforms.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
drivers/acpi/sleep.c | 21 +++++++++++++--------
1 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index d3cbc55..18aa074 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -128,6 +128,8 @@ static int __acpi_pm_prepare(void)
{
int error = acpi_sleep_prepare(acpi_target_sleep_state);
+ suspend_nvs_save();
+
if (error)
acpi_target_sleep_state = ACPI_STATE_S0;
return error;
@@ -156,6 +158,8 @@ static void acpi_pm_finish(void)
{
u32 acpi_state = acpi_target_sleep_state;
+ suspend_nvs_free();
+
if (acpi_state == ACPI_STATE_S0)
return;
@@ -205,6 +209,11 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
u32 acpi_state = acpi_suspend_states[pm_state];
int error = 0;
+ error = suspend_nvs_alloc();
+
+ if (error)
+ return error;
+
if (sleep_states[acpi_state]) {
acpi_target_sleep_state = acpi_state;
acpi_sleep_tts_switch(acpi_target_sleep_state);
@@ -283,6 +292,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
if (acpi_state == ACPI_STATE_S3)
acpi_restore_state_mem();
+ suspend_nvs_restore();
+
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
@@ -583,12 +594,6 @@ static int acpi_hibernation_enter(void)
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
-static void acpi_hibernation_finish(void)
-{
- suspend_nvs_free();
- acpi_pm_finish();
-}
-
static void acpi_hibernation_leave(void)
{
/*
@@ -626,7 +631,7 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {
.begin = acpi_hibernation_begin,
.end = acpi_pm_end,
.pre_snapshot = acpi_hibernation_pre_snapshot,
- .finish = acpi_hibernation_finish,
+ .finish = acpi_pm_finish,
.prepare = acpi_pm_prepare,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
@@ -679,7 +684,7 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = {
.begin = acpi_hibernation_begin_old,
.end = acpi_pm_end,
.pre_snapshot = acpi_hibernation_pre_snapshot_old,
- .finish = acpi_hibernation_finish,
+ .finish = acpi_pm_finish,
.prepare = acpi_pm_disable_gpes,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
--
1.7.0.1
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM
2010-05-28 20:32 ` [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM Matthew Garrett
@ 2010-05-30 14:40 ` Maxim Levitsky
2010-05-30 14:51 ` Matthew Garrett
2010-06-04 18:23 ` Len Brown
2010-06-10 9:41 ` Maxim Levitsky
2 siblings, 1 reply; 21+ messages in thread
From: Maxim Levitsky @ 2010-05-30 14:40 UTC (permalink / raw)
To: Matthew Garrett; +Cc: lenb, linux-acpi, linux-pm
On Fri, 2010-05-28 at 16:32 -0400, Matthew Garrett wrote:
> https://bugzilla.kernel.org/show_bug.cgi?id=13931 describes a bug where
> a system fails to successfully resume after the second suspend. Maxim
> Levitsky discovered that this could be rectified by forcibly saving
> and restoring the ACPI non-volatile state. The spec indicates that this
> is only required for S4, but testing the behaviour of Windows by adding
> an ACPI NVS region to qemu's e820 map and registering a custom memory
> read/write handler reveals that it's saved and restored even over suspend
> to RAM. We should mimic that behaviour to avoid other broken platforms.
>
> Signed-off-by: Matthew Garrett <mjg@redhat.com>
> ---
> drivers/acpi/sleep.c | 21 +++++++++++++--------
> 1 files changed, 13 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
> index d3cbc55..18aa074 100644
> --- a/drivers/acpi/sleep.c
> +++ b/drivers/acpi/sleep.c
> @@ -128,6 +128,8 @@ static int __acpi_pm_prepare(void)
> {
> int error = acpi_sleep_prepare(acpi_target_sleep_state);
Just one note, I am sure somebody will ask for s3_no_nvs option, just
like s4_no_nvs.
Also this needs to be rebased, like the first patch.
Best regards,
Maxim Levitsky
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM
2010-05-30 14:40 ` Maxim Levitsky
@ 2010-05-30 14:51 ` Matthew Garrett
2010-06-02 3:32 ` Henrique de Moraes Holschuh
0 siblings, 1 reply; 21+ messages in thread
From: Matthew Garrett @ 2010-05-30 14:51 UTC (permalink / raw)
To: Maxim Levitsky; +Cc: lenb, linux-acpi, linux-pm
On Sun, May 30, 2010 at 05:40:04PM +0300, Maxim Levitsky wrote:
> Just one note, I am sure somebody will ask for s3_no_nvs option, just
> like s4_no_nvs.
I'd be surprised. Better to add the option when we think it's needed.
--
Matthew Garrett | mjg59@srcf.ucam.org
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH] Store BIOS NVS area over s2ram [V2]
@ 2010-06-01 18:19 Maxim Levitsky
2010-06-01 18:22 ` [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality Maxim Levitsky
2010-06-01 18:22 ` [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM Maxim Levitsky
0 siblings, 2 replies; 21+ messages in thread
From: Maxim Levitsky @ 2010-06-01 18:19 UTC (permalink / raw)
To: linux-acpi@vger.kernel.org
Cc: linux-pm, Matthew Garrett, Rafael J. Wysocki, Alan Stern
Hi,
This is rebased and slightly updated version of Matthew Garrett's
patches.
Tested on my system.
Note that now I got positive feedback from 2 users of this system that
this approach works, and no negative feedback.
Please review.
Best regards,
Maxim Levitsky
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality
2010-06-01 18:19 [PATCH] Store BIOS NVS area over s2ram [V2] Maxim Levitsky
@ 2010-06-01 18:22 ` Maxim Levitsky
2010-06-01 21:31 ` Rafael J. Wysocki
2010-06-01 18:22 ` [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM Maxim Levitsky
1 sibling, 1 reply; 21+ messages in thread
From: Maxim Levitsky @ 2010-06-01 18:22 UTC (permalink / raw)
To: linux-acpi@vger.kernel.org
Cc: linux-pm, Matthew Garrett, Rafael J. Wysocki, Alan Stern,
Maxim Levitsky
Saving platform non-volatile state may be required for suspend to RAM as
well as hibernation. Move it to more generic code.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Matthew Garrett <maximlevitsky@gmail.com>
---
arch/x86/kernel/e820.c | 2 +-
drivers/acpi/sleep.c | 12 ++--
include/linux/suspend.h | 26 ++++----
kernel/power/Kconfig | 9 ++-
kernel/power/Makefile | 2 +-
kernel/power/hibernate_nvs.c | 136 ------------------------------------------
kernel/power/nvs.c | 136 ++++++++++++++++++++++++++++++++++++++++++
kernel/power/suspend.c | 6 ++
8 files changed, 168 insertions(+), 161 deletions(-)
delete mode 100644 kernel/power/hibernate_nvs.c
create mode 100644 kernel/power/nvs.c
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 7bca3c6..0d6fc71 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -729,7 +729,7 @@ static int __init e820_mark_nvs_memory(void)
struct e820entry *ei = &e820.map[i];
if (ei->type == E820_NVS)
- hibernate_nvs_register(ei->addr, ei->size);
+ suspend_nvs_register(ei->addr, ei->size);
}
return 0;
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 3fb4bde..bdb306f 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -404,7 +404,7 @@ static int acpi_hibernation_begin(void)
{
int error;
- error = s4_no_nvs ? 0 : hibernate_nvs_alloc();
+ error = s4_no_nvs ? 0 : suspend_nvs_alloc();
if (!error) {
acpi_target_sleep_state = ACPI_STATE_S4;
acpi_sleep_tts_switch(acpi_target_sleep_state);
@@ -418,7 +418,7 @@ static int acpi_hibernation_pre_snapshot(void)
int error = acpi_pm_prepare();
if (!error)
- hibernate_nvs_save();
+ suspend_nvs_save();
return error;
}
@@ -443,7 +443,7 @@ static int acpi_hibernation_enter(void)
static void acpi_hibernation_finish(void)
{
- hibernate_nvs_free();
+ suspend_nvs_free();
acpi_ec_unblock_transactions();
acpi_pm_finish();
}
@@ -464,7 +464,7 @@ static void acpi_hibernation_leave(void)
panic("ACPI S4 hardware signature mismatch");
}
/* Restore the NVS memory area */
- hibernate_nvs_restore();
+ suspend_nvs_restore();
/* Allow EC transactions to happen. */
acpi_ec_unblock_transactions_early();
}
@@ -507,7 +507,7 @@ static int acpi_hibernation_begin_old(void)
if (!error) {
if (!s4_no_nvs)
- error = hibernate_nvs_alloc();
+ error = suspend_nvs_alloc();
if (!error)
acpi_target_sleep_state = ACPI_STATE_S4;
}
@@ -517,7 +517,7 @@ static int acpi_hibernation_begin_old(void)
static int acpi_hibernation_pre_snapshot_old(void)
{
acpi_pm_freeze();
- hibernate_nvs_save();
+ suspend_nvs_save();
return 0;
}
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 5e781d8..bc7d6bb 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -256,22 +256,22 @@ static inline int hibernate(void) { return -ENOSYS; }
static inline bool system_entering_hibernation(void) { return false; }
#endif /* CONFIG_HIBERNATION */
-#ifdef CONFIG_HIBERNATION_NVS
-extern int hibernate_nvs_register(unsigned long start, unsigned long size);
-extern int hibernate_nvs_alloc(void);
-extern void hibernate_nvs_free(void);
-extern void hibernate_nvs_save(void);
-extern void hibernate_nvs_restore(void);
-#else /* CONFIG_HIBERNATION_NVS */
-static inline int hibernate_nvs_register(unsigned long a, unsigned long b)
+#ifdef CONFIG_SUSPEND_NVS
+extern int suspend_nvs_register(unsigned long start, unsigned long size);
+extern int suspend_nvs_alloc(void);
+extern void suspend_nvs_free(void);
+extern void suspend_nvs_save(void);
+extern void suspend_nvs_restore(void);
+#else /* CONFIG_SUSPEND_NVS */
+static inline int suspend_nvs_register(unsigned long a, unsigned long b)
{
return 0;
}
-static inline int hibernate_nvs_alloc(void) { return 0; }
-static inline void hibernate_nvs_free(void) {}
-static inline void hibernate_nvs_save(void) {}
-static inline void hibernate_nvs_restore(void) {}
-#endif /* CONFIG_HIBERNATION_NVS */
+static inline int suspend_nvs_alloc(void) { return 0; }
+static inline void suspend_nvs_free(void) {}
+static inline void suspend_nvs_save(void) {}
+static inline void suspend_nvs_restore(void) {}
+#endif /* CONFIG_SUSPEND_NVS */
#ifdef CONFIG_PM_SLEEP
void save_processor_state(void);
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 5c36ea9..ca6066a 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -99,9 +99,13 @@ config PM_SLEEP_ADVANCED_DEBUG
depends on PM_ADVANCED_DEBUG
default n
+config SUSPEND_NVS
+ bool
+
config SUSPEND
bool "Suspend to RAM and standby"
depends on PM && ARCH_SUSPEND_POSSIBLE
+ select SUSPEND_NVS if HAS_IOMEM
default y
---help---
Allow the system to enter sleep states in which main memory is
@@ -130,13 +134,10 @@ config SUSPEND_FREEZER
Turning OFF this setting is NOT recommended! If in doubt, say Y.
-config HIBERNATION_NVS
- bool
-
config HIBERNATION
bool "Hibernation (aka 'suspend to disk')"
depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
- select HIBERNATION_NVS if HAS_IOMEM
+ select SUSPEND_NVS if HAS_IOMEM
---help---
Enable the suspend to disk (STD) functionality, which is usually
called "hibernation" in user interfaces. STD checkpoints the
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 524e058..f9063c6 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -10,6 +10,6 @@ obj-$(CONFIG_SUSPEND) += suspend.o
obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o
obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o \
block_io.o
-obj-$(CONFIG_HIBERNATION_NVS) += hibernate_nvs.o
+obj-$(CONFIG_SUSPEND_NVS) += nvs.o
obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o
diff --git a/kernel/power/hibernate_nvs.c b/kernel/power/hibernate_nvs.c
deleted file mode 100644
index fdcad9e..0000000
--- a/kernel/power/hibernate_nvs.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * linux/kernel/power/hibernate_nvs.c - Routines for handling NVS memory
- *
- * Copyright (C) 2008,2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
- *
- * This file is released under the GPLv2.
- */
-
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/suspend.h>
-
-/*
- * Platforms, like ACPI, may want us to save some memory used by them during
- * hibernation and to restore the contents of this memory during the subsequent
- * resume. The code below implements a mechanism allowing us to do that.
- */
-
-struct nvs_page {
- unsigned long phys_start;
- unsigned int size;
- void *kaddr;
- void *data;
- struct list_head node;
-};
-
-static LIST_HEAD(nvs_list);
-
-/**
- * hibernate_nvs_register - register platform NVS memory region to save
- * @start - physical address of the region
- * @size - size of the region
- *
- * The NVS region need not be page-aligned (both ends) and we arrange
- * things so that the data from page-aligned addresses in this region will
- * be copied into separate RAM pages.
- */
-int hibernate_nvs_register(unsigned long start, unsigned long size)
-{
- struct nvs_page *entry, *next;
-
- while (size > 0) {
- unsigned int nr_bytes;
-
- entry = kzalloc(sizeof(struct nvs_page), GFP_KERNEL);
- if (!entry)
- goto Error;
-
- list_add_tail(&entry->node, &nvs_list);
- entry->phys_start = start;
- nr_bytes = PAGE_SIZE - (start & ~PAGE_MASK);
- entry->size = (size < nr_bytes) ? size : nr_bytes;
-
- start += entry->size;
- size -= entry->size;
- }
- return 0;
-
- Error:
- list_for_each_entry_safe(entry, next, &nvs_list, node) {
- list_del(&entry->node);
- kfree(entry);
- }
- return -ENOMEM;
-}
-
-/**
- * hibernate_nvs_free - free data pages allocated for saving NVS regions
- */
-void hibernate_nvs_free(void)
-{
- struct nvs_page *entry;
-
- list_for_each_entry(entry, &nvs_list, node)
- if (entry->data) {
- free_page((unsigned long)entry->data);
- entry->data = NULL;
- if (entry->kaddr) {
- iounmap(entry->kaddr);
- entry->kaddr = NULL;
- }
- }
-}
-
-/**
- * hibernate_nvs_alloc - allocate memory necessary for saving NVS regions
- */
-int hibernate_nvs_alloc(void)
-{
- struct nvs_page *entry;
-
- list_for_each_entry(entry, &nvs_list, node) {
- entry->data = (void *)__get_free_page(GFP_KERNEL);
- if (!entry->data) {
- hibernate_nvs_free();
- return -ENOMEM;
- }
- }
- return 0;
-}
-
-/**
- * hibernate_nvs_save - save NVS memory regions
- */
-void hibernate_nvs_save(void)
-{
- struct nvs_page *entry;
-
- printk(KERN_INFO "PM: Saving platform NVS memory\n");
-
- list_for_each_entry(entry, &nvs_list, node)
- if (entry->data) {
- entry->kaddr = ioremap(entry->phys_start, entry->size);
- memcpy(entry->data, entry->kaddr, entry->size);
- }
-}
-
-/**
- * hibernate_nvs_restore - restore NVS memory regions
- *
- * This function is going to be called with interrupts disabled, so it
- * cannot iounmap the virtual addresses used to access the NVS region.
- */
-void hibernate_nvs_restore(void)
-{
- struct nvs_page *entry;
-
- printk(KERN_INFO "PM: Restoring platform NVS memory\n");
-
- list_for_each_entry(entry, &nvs_list, node)
- if (entry->data)
- memcpy(entry->kaddr, entry->data, entry->size);
-}
diff --git a/kernel/power/nvs.c b/kernel/power/nvs.c
new file mode 100644
index 0000000..30c662f
--- /dev/null
+++ b/kernel/power/nvs.c
@@ -0,0 +1,136 @@
+/*
+ * linux/kernel/power/nvs.c - Routines for handling NVS memory
+ *
+ * Copyright (C) 2008,2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/suspend.h>
+
+/*
+ * Platforms, like ACPI, may want us to save some memory used by them during
+ * suspend and to restore the contents of this memory during the subsequent
+ * resume. The code below implements a mechanism allowing us to do that.
+ */
+
+struct nvs_page {
+ unsigned long phys_start;
+ unsigned int size;
+ void *kaddr;
+ void *data;
+ struct list_head node;
+};
+
+static LIST_HEAD(nvs_list);
+
+/**
+ * suspend_nvs_register - register platform NVS memory region to save
+ * @start - physical address of the region
+ * @size - size of the region
+ *
+ * The NVS region need not be page-aligned (both ends) and we arrange
+ * things so that the data from page-aligned addresses in this region will
+ * be copied into separate RAM pages.
+ */
+int suspend_nvs_register(unsigned long start, unsigned long size)
+{
+ struct nvs_page *entry, *next;
+
+ while (size > 0) {
+ unsigned int nr_bytes;
+
+ entry = kzalloc(sizeof(struct nvs_page), GFP_KERNEL);
+ if (!entry)
+ goto Error;
+
+ list_add_tail(&entry->node, &nvs_list);
+ entry->phys_start = start;
+ nr_bytes = PAGE_SIZE - (start & ~PAGE_MASK);
+ entry->size = (size < nr_bytes) ? size : nr_bytes;
+
+ start += entry->size;
+ size -= entry->size;
+ }
+ return 0;
+
+ Error:
+ list_for_each_entry_safe(entry, next, &nvs_list, node) {
+ list_del(&entry->node);
+ kfree(entry);
+ }
+ return -ENOMEM;
+}
+
+/**
+ * suspend_nvs_free - free data pages allocated for saving NVS regions
+ */
+void suspend_nvs_free(void)
+{
+ struct nvs_page *entry;
+
+ list_for_each_entry(entry, &nvs_list, node)
+ if (entry->data) {
+ free_page((unsigned long)entry->data);
+ entry->data = NULL;
+ if (entry->kaddr) {
+ iounmap(entry->kaddr);
+ entry->kaddr = NULL;
+ }
+ }
+}
+
+/**
+ * suspend_nvs_alloc - allocate memory necessary for saving NVS regions
+ */
+int suspend_nvs_alloc(void)
+{
+ struct nvs_page *entry;
+
+ list_for_each_entry(entry, &nvs_list, node) {
+ entry->data = (void *)__get_free_page(GFP_KERNEL);
+ if (!entry->data) {
+ suspend_nvs_free();
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
+/**
+ * suspend_nvs_save - save NVS memory regions
+ */
+void suspend_nvs_save(void)
+{
+ struct nvs_page *entry;
+
+ printk(KERN_INFO "PM: Saving platform NVS memory\n");
+
+ list_for_each_entry(entry, &nvs_list, node)
+ if (entry->data) {
+ entry->kaddr = ioremap(entry->phys_start, entry->size);
+ memcpy(entry->data, entry->kaddr, entry->size);
+ }
+}
+
+/**
+ * suspend_nvs_restore - restore NVS memory regions
+ *
+ * This function is going to be called with interrupts disabled, so it
+ * cannot iounmap the virtual addresses used to access the NVS region.
+ */
+void suspend_nvs_restore(void)
+{
+ struct nvs_page *entry;
+
+ printk(KERN_INFO "PM: Restoring platform NVS memory\n");
+
+ list_for_each_entry(entry, &nvs_list, node)
+ if (entry->data)
+ memcpy(entry->kaddr, entry->data, entry->size);
+}
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 56e7dbb..f37cb7d 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -16,6 +16,12 @@
#include <linux/cpu.h>
#include <linux/syscalls.h>
#include <linux/gfp.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/suspend.h>
#include "power.h"
--
1.7.0.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM
2010-06-01 18:19 [PATCH] Store BIOS NVS area over s2ram [V2] Maxim Levitsky
2010-06-01 18:22 ` [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality Maxim Levitsky
@ 2010-06-01 18:22 ` Maxim Levitsky
1 sibling, 0 replies; 21+ messages in thread
From: Maxim Levitsky @ 2010-06-01 18:22 UTC (permalink / raw)
To: linux-acpi@vger.kernel.org
Cc: linux-pm, Matthew Garrett, Rafael J. Wysocki, Alan Stern,
Maxim Levitsky
https://bugzilla.kernel.org/show_bug.cgi?id=13931 describes a bug where
a system fails to successfully resume after the second suspend. Maxim
Levitsky discovered that this could be rectified by forcibly saving
and restoring the ACPI non-volatile state. The spec indicates that this
is only required for S4, but testing the behaviour of Windows by adding
an ACPI NVS region to qemu's e820 map and registering a custom memory
read/write handler reveals that it's saved and restored even over suspend
to RAM. We should mimic that behaviour to avoid other broken platforms.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
---
drivers/acpi/sleep.c | 14 ++++++++++++--
1 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index bdb306f..5d26d8e 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -114,6 +114,8 @@ static int __acpi_pm_prepare(void)
{
int error = acpi_sleep_prepare(acpi_target_sleep_state);
+ suspend_nvs_save();
+
if (error)
acpi_target_sleep_state = ACPI_STATE_S0;
return error;
@@ -143,6 +145,8 @@ static void acpi_pm_finish(void)
{
u32 acpi_state = acpi_target_sleep_state;
+ suspend_nvs_free();
+
if (acpi_state == ACPI_STATE_S0)
return;
@@ -192,6 +196,11 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
u32 acpi_state = acpi_suspend_states[pm_state];
int error = 0;
+ error = suspend_nvs_alloc();
+
+ if (error)
+ return error;
+
if (sleep_states[acpi_state]) {
acpi_target_sleep_state = acpi_state;
acpi_sleep_tts_switch(acpi_target_sleep_state);
@@ -269,6 +278,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
if (acpi_state == ACPI_STATE_S3)
acpi_restore_state_mem();
+ suspend_nvs_restore();
+
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
@@ -443,7 +454,6 @@ static int acpi_hibernation_enter(void)
static void acpi_hibernation_finish(void)
{
- suspend_nvs_free();
acpi_ec_unblock_transactions();
acpi_pm_finish();
}
@@ -479,7 +489,7 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {
.begin = acpi_hibernation_begin,
.end = acpi_pm_end,
.pre_snapshot = acpi_hibernation_pre_snapshot,
- .finish = acpi_hibernation_finish,
+ .finish = acpi_pm_finish,
.prepare = acpi_pm_prepare,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
--
1.7.0.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality
2010-06-01 18:22 ` [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality Maxim Levitsky
@ 2010-06-01 21:31 ` Rafael J. Wysocki
2010-06-01 21:52 ` Maxim Levitsky
0 siblings, 1 reply; 21+ messages in thread
From: Rafael J. Wysocki @ 2010-06-01 21:31 UTC (permalink / raw)
To: Maxim Levitsky
Cc: linux-acpi@vger.kernel.org, linux-pm, Matthew Garrett, Alan Stern
On Tuesday 01 June 2010, Maxim Levitsky wrote:
> Saving platform non-volatile state may be required for suspend to RAM as
> well as hibernation. Move it to more generic code.
>
> Signed-off-by: Matthew Garrett <mjg@redhat.com>
> Signed-off-by: Matthew Garrett <maximlevitsky@gmail.com>
You made a mistake here.
Also, why are you resending the Matthews patches? I think Len has seen them
already.
Rafael
> ---
> arch/x86/kernel/e820.c | 2 +-
> drivers/acpi/sleep.c | 12 ++--
> include/linux/suspend.h | 26 ++++----
> kernel/power/Kconfig | 9 ++-
> kernel/power/Makefile | 2 +-
> kernel/power/hibernate_nvs.c | 136 ------------------------------------------
> kernel/power/nvs.c | 136 ++++++++++++++++++++++++++++++++++++++++++
> kernel/power/suspend.c | 6 ++
> 8 files changed, 168 insertions(+), 161 deletions(-)
> delete mode 100644 kernel/power/hibernate_nvs.c
> create mode 100644 kernel/power/nvs.c
>
> diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
> index 7bca3c6..0d6fc71 100644
> --- a/arch/x86/kernel/e820.c
> +++ b/arch/x86/kernel/e820.c
> @@ -729,7 +729,7 @@ static int __init e820_mark_nvs_memory(void)
> struct e820entry *ei = &e820.map[i];
>
> if (ei->type == E820_NVS)
> - hibernate_nvs_register(ei->addr, ei->size);
> + suspend_nvs_register(ei->addr, ei->size);
> }
>
> return 0;
> diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
> index 3fb4bde..bdb306f 100644
> --- a/drivers/acpi/sleep.c
> +++ b/drivers/acpi/sleep.c
> @@ -404,7 +404,7 @@ static int acpi_hibernation_begin(void)
> {
> int error;
>
> - error = s4_no_nvs ? 0 : hibernate_nvs_alloc();
> + error = s4_no_nvs ? 0 : suspend_nvs_alloc();
> if (!error) {
> acpi_target_sleep_state = ACPI_STATE_S4;
> acpi_sleep_tts_switch(acpi_target_sleep_state);
> @@ -418,7 +418,7 @@ static int acpi_hibernation_pre_snapshot(void)
> int error = acpi_pm_prepare();
>
> if (!error)
> - hibernate_nvs_save();
> + suspend_nvs_save();
>
> return error;
> }
> @@ -443,7 +443,7 @@ static int acpi_hibernation_enter(void)
>
> static void acpi_hibernation_finish(void)
> {
> - hibernate_nvs_free();
> + suspend_nvs_free();
> acpi_ec_unblock_transactions();
> acpi_pm_finish();
> }
> @@ -464,7 +464,7 @@ static void acpi_hibernation_leave(void)
> panic("ACPI S4 hardware signature mismatch");
> }
> /* Restore the NVS memory area */
> - hibernate_nvs_restore();
> + suspend_nvs_restore();
> /* Allow EC transactions to happen. */
> acpi_ec_unblock_transactions_early();
> }
> @@ -507,7 +507,7 @@ static int acpi_hibernation_begin_old(void)
>
> if (!error) {
> if (!s4_no_nvs)
> - error = hibernate_nvs_alloc();
> + error = suspend_nvs_alloc();
> if (!error)
> acpi_target_sleep_state = ACPI_STATE_S4;
> }
> @@ -517,7 +517,7 @@ static int acpi_hibernation_begin_old(void)
> static int acpi_hibernation_pre_snapshot_old(void)
> {
> acpi_pm_freeze();
> - hibernate_nvs_save();
> + suspend_nvs_save();
> return 0;
> }
>
> diff --git a/include/linux/suspend.h b/include/linux/suspend.h
> index 5e781d8..bc7d6bb 100644
> --- a/include/linux/suspend.h
> +++ b/include/linux/suspend.h
> @@ -256,22 +256,22 @@ static inline int hibernate(void) { return -ENOSYS; }
> static inline bool system_entering_hibernation(void) { return false; }
> #endif /* CONFIG_HIBERNATION */
>
> -#ifdef CONFIG_HIBERNATION_NVS
> -extern int hibernate_nvs_register(unsigned long start, unsigned long size);
> -extern int hibernate_nvs_alloc(void);
> -extern void hibernate_nvs_free(void);
> -extern void hibernate_nvs_save(void);
> -extern void hibernate_nvs_restore(void);
> -#else /* CONFIG_HIBERNATION_NVS */
> -static inline int hibernate_nvs_register(unsigned long a, unsigned long b)
> +#ifdef CONFIG_SUSPEND_NVS
> +extern int suspend_nvs_register(unsigned long start, unsigned long size);
> +extern int suspend_nvs_alloc(void);
> +extern void suspend_nvs_free(void);
> +extern void suspend_nvs_save(void);
> +extern void suspend_nvs_restore(void);
> +#else /* CONFIG_SUSPEND_NVS */
> +static inline int suspend_nvs_register(unsigned long a, unsigned long b)
> {
> return 0;
> }
> -static inline int hibernate_nvs_alloc(void) { return 0; }
> -static inline void hibernate_nvs_free(void) {}
> -static inline void hibernate_nvs_save(void) {}
> -static inline void hibernate_nvs_restore(void) {}
> -#endif /* CONFIG_HIBERNATION_NVS */
> +static inline int suspend_nvs_alloc(void) { return 0; }
> +static inline void suspend_nvs_free(void) {}
> +static inline void suspend_nvs_save(void) {}
> +static inline void suspend_nvs_restore(void) {}
> +#endif /* CONFIG_SUSPEND_NVS */
>
> #ifdef CONFIG_PM_SLEEP
> void save_processor_state(void);
> diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
> index 5c36ea9..ca6066a 100644
> --- a/kernel/power/Kconfig
> +++ b/kernel/power/Kconfig
> @@ -99,9 +99,13 @@ config PM_SLEEP_ADVANCED_DEBUG
> depends on PM_ADVANCED_DEBUG
> default n
>
> +config SUSPEND_NVS
> + bool
> +
> config SUSPEND
> bool "Suspend to RAM and standby"
> depends on PM && ARCH_SUSPEND_POSSIBLE
> + select SUSPEND_NVS if HAS_IOMEM
> default y
> ---help---
> Allow the system to enter sleep states in which main memory is
> @@ -130,13 +134,10 @@ config SUSPEND_FREEZER
>
> Turning OFF this setting is NOT recommended! If in doubt, say Y.
>
> -config HIBERNATION_NVS
> - bool
> -
> config HIBERNATION
> bool "Hibernation (aka 'suspend to disk')"
> depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
> - select HIBERNATION_NVS if HAS_IOMEM
> + select SUSPEND_NVS if HAS_IOMEM
> ---help---
> Enable the suspend to disk (STD) functionality, which is usually
> called "hibernation" in user interfaces. STD checkpoints the
> diff --git a/kernel/power/Makefile b/kernel/power/Makefile
> index 524e058..f9063c6 100644
> --- a/kernel/power/Makefile
> +++ b/kernel/power/Makefile
> @@ -10,6 +10,6 @@ obj-$(CONFIG_SUSPEND) += suspend.o
> obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o
> obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o \
> block_io.o
> -obj-$(CONFIG_HIBERNATION_NVS) += hibernate_nvs.o
> +obj-$(CONFIG_SUSPEND_NVS) += nvs.o
>
> obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o
> diff --git a/kernel/power/hibernate_nvs.c b/kernel/power/hibernate_nvs.c
> deleted file mode 100644
> index fdcad9e..0000000
> --- a/kernel/power/hibernate_nvs.c
> +++ /dev/null
> @@ -1,136 +0,0 @@
> -/*
> - * linux/kernel/power/hibernate_nvs.c - Routines for handling NVS memory
> - *
> - * Copyright (C) 2008,2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
> - *
> - * This file is released under the GPLv2.
> - */
> -
> -#include <linux/io.h>
> -#include <linux/kernel.h>
> -#include <linux/list.h>
> -#include <linux/mm.h>
> -#include <linux/slab.h>
> -#include <linux/suspend.h>
> -
> -/*
> - * Platforms, like ACPI, may want us to save some memory used by them during
> - * hibernation and to restore the contents of this memory during the subsequent
> - * resume. The code below implements a mechanism allowing us to do that.
> - */
> -
> -struct nvs_page {
> - unsigned long phys_start;
> - unsigned int size;
> - void *kaddr;
> - void *data;
> - struct list_head node;
> -};
> -
> -static LIST_HEAD(nvs_list);
> -
> -/**
> - * hibernate_nvs_register - register platform NVS memory region to save
> - * @start - physical address of the region
> - * @size - size of the region
> - *
> - * The NVS region need not be page-aligned (both ends) and we arrange
> - * things so that the data from page-aligned addresses in this region will
> - * be copied into separate RAM pages.
> - */
> -int hibernate_nvs_register(unsigned long start, unsigned long size)
> -{
> - struct nvs_page *entry, *next;
> -
> - while (size > 0) {
> - unsigned int nr_bytes;
> -
> - entry = kzalloc(sizeof(struct nvs_page), GFP_KERNEL);
> - if (!entry)
> - goto Error;
> -
> - list_add_tail(&entry->node, &nvs_list);
> - entry->phys_start = start;
> - nr_bytes = PAGE_SIZE - (start & ~PAGE_MASK);
> - entry->size = (size < nr_bytes) ? size : nr_bytes;
> -
> - start += entry->size;
> - size -= entry->size;
> - }
> - return 0;
> -
> - Error:
> - list_for_each_entry_safe(entry, next, &nvs_list, node) {
> - list_del(&entry->node);
> - kfree(entry);
> - }
> - return -ENOMEM;
> -}
> -
> -/**
> - * hibernate_nvs_free - free data pages allocated for saving NVS regions
> - */
> -void hibernate_nvs_free(void)
> -{
> - struct nvs_page *entry;
> -
> - list_for_each_entry(entry, &nvs_list, node)
> - if (entry->data) {
> - free_page((unsigned long)entry->data);
> - entry->data = NULL;
> - if (entry->kaddr) {
> - iounmap(entry->kaddr);
> - entry->kaddr = NULL;
> - }
> - }
> -}
> -
> -/**
> - * hibernate_nvs_alloc - allocate memory necessary for saving NVS regions
> - */
> -int hibernate_nvs_alloc(void)
> -{
> - struct nvs_page *entry;
> -
> - list_for_each_entry(entry, &nvs_list, node) {
> - entry->data = (void *)__get_free_page(GFP_KERNEL);
> - if (!entry->data) {
> - hibernate_nvs_free();
> - return -ENOMEM;
> - }
> - }
> - return 0;
> -}
> -
> -/**
> - * hibernate_nvs_save - save NVS memory regions
> - */
> -void hibernate_nvs_save(void)
> -{
> - struct nvs_page *entry;
> -
> - printk(KERN_INFO "PM: Saving platform NVS memory\n");
> -
> - list_for_each_entry(entry, &nvs_list, node)
> - if (entry->data) {
> - entry->kaddr = ioremap(entry->phys_start, entry->size);
> - memcpy(entry->data, entry->kaddr, entry->size);
> - }
> -}
> -
> -/**
> - * hibernate_nvs_restore - restore NVS memory regions
> - *
> - * This function is going to be called with interrupts disabled, so it
> - * cannot iounmap the virtual addresses used to access the NVS region.
> - */
> -void hibernate_nvs_restore(void)
> -{
> - struct nvs_page *entry;
> -
> - printk(KERN_INFO "PM: Restoring platform NVS memory\n");
> -
> - list_for_each_entry(entry, &nvs_list, node)
> - if (entry->data)
> - memcpy(entry->kaddr, entry->data, entry->size);
> -}
> diff --git a/kernel/power/nvs.c b/kernel/power/nvs.c
> new file mode 100644
> index 0000000..30c662f
> --- /dev/null
> +++ b/kernel/power/nvs.c
> @@ -0,0 +1,136 @@
> +/*
> + * linux/kernel/power/nvs.c - Routines for handling NVS memory
> + *
> + * Copyright (C) 2008,2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
> + *
> + * This file is released under the GPLv2.
> + */
> +
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/mm.h>
> +#include <linux/slab.h>
> +#include <linux/suspend.h>
> +
> +/*
> + * Platforms, like ACPI, may want us to save some memory used by them during
> + * suspend and to restore the contents of this memory during the subsequent
> + * resume. The code below implements a mechanism allowing us to do that.
> + */
> +
> +struct nvs_page {
> + unsigned long phys_start;
> + unsigned int size;
> + void *kaddr;
> + void *data;
> + struct list_head node;
> +};
> +
> +static LIST_HEAD(nvs_list);
> +
> +/**
> + * suspend_nvs_register - register platform NVS memory region to save
> + * @start - physical address of the region
> + * @size - size of the region
> + *
> + * The NVS region need not be page-aligned (both ends) and we arrange
> + * things so that the data from page-aligned addresses in this region will
> + * be copied into separate RAM pages.
> + */
> +int suspend_nvs_register(unsigned long start, unsigned long size)
> +{
> + struct nvs_page *entry, *next;
> +
> + while (size > 0) {
> + unsigned int nr_bytes;
> +
> + entry = kzalloc(sizeof(struct nvs_page), GFP_KERNEL);
> + if (!entry)
> + goto Error;
> +
> + list_add_tail(&entry->node, &nvs_list);
> + entry->phys_start = start;
> + nr_bytes = PAGE_SIZE - (start & ~PAGE_MASK);
> + entry->size = (size < nr_bytes) ? size : nr_bytes;
> +
> + start += entry->size;
> + size -= entry->size;
> + }
> + return 0;
> +
> + Error:
> + list_for_each_entry_safe(entry, next, &nvs_list, node) {
> + list_del(&entry->node);
> + kfree(entry);
> + }
> + return -ENOMEM;
> +}
> +
> +/**
> + * suspend_nvs_free - free data pages allocated for saving NVS regions
> + */
> +void suspend_nvs_free(void)
> +{
> + struct nvs_page *entry;
> +
> + list_for_each_entry(entry, &nvs_list, node)
> + if (entry->data) {
> + free_page((unsigned long)entry->data);
> + entry->data = NULL;
> + if (entry->kaddr) {
> + iounmap(entry->kaddr);
> + entry->kaddr = NULL;
> + }
> + }
> +}
> +
> +/**
> + * suspend_nvs_alloc - allocate memory necessary for saving NVS regions
> + */
> +int suspend_nvs_alloc(void)
> +{
> + struct nvs_page *entry;
> +
> + list_for_each_entry(entry, &nvs_list, node) {
> + entry->data = (void *)__get_free_page(GFP_KERNEL);
> + if (!entry->data) {
> + suspend_nvs_free();
> + return -ENOMEM;
> + }
> + }
> + return 0;
> +}
> +
> +/**
> + * suspend_nvs_save - save NVS memory regions
> + */
> +void suspend_nvs_save(void)
> +{
> + struct nvs_page *entry;
> +
> + printk(KERN_INFO "PM: Saving platform NVS memory\n");
> +
> + list_for_each_entry(entry, &nvs_list, node)
> + if (entry->data) {
> + entry->kaddr = ioremap(entry->phys_start, entry->size);
> + memcpy(entry->data, entry->kaddr, entry->size);
> + }
> +}
> +
> +/**
> + * suspend_nvs_restore - restore NVS memory regions
> + *
> + * This function is going to be called with interrupts disabled, so it
> + * cannot iounmap the virtual addresses used to access the NVS region.
> + */
> +void suspend_nvs_restore(void)
> +{
> + struct nvs_page *entry;
> +
> + printk(KERN_INFO "PM: Restoring platform NVS memory\n");
> +
> + list_for_each_entry(entry, &nvs_list, node)
> + if (entry->data)
> + memcpy(entry->kaddr, entry->data, entry->size);
> +}
> diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
> index 56e7dbb..f37cb7d 100644
> --- a/kernel/power/suspend.c
> +++ b/kernel/power/suspend.c
> @@ -16,6 +16,12 @@
> #include <linux/cpu.h>
> #include <linux/syscalls.h>
> #include <linux/gfp.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/mm.h>
> +#include <linux/slab.h>
> +#include <linux/suspend.h>
>
> #include "power.h"
>
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality
2010-06-01 21:31 ` Rafael J. Wysocki
@ 2010-06-01 21:52 ` Maxim Levitsky
2010-06-01 22:40 ` Rafael J. Wysocki
0 siblings, 1 reply; 21+ messages in thread
From: Maxim Levitsky @ 2010-06-01 21:52 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: linux-acpi@vger.kernel.org, linux-pm, Matthew Garrett, Alan Stern
On Tue, 2010-06-01 at 23:31 +0200, Rafael J. Wysocki wrote:
> On Tuesday 01 June 2010, Maxim Levitsky wrote:
> > Saving platform non-volatile state may be required for suspend to RAM as
> > well as hibernation. Move it to more generic code.
> >
> > Signed-off-by: Matthew Garrett <mjg@redhat.com>
> > Signed-off-by: Matthew Garrett <maximlevitsky@gmail.com>
>
> You made a mistake here.
>
> Also, why are you resending the Matthews patches? I think Len has seen them
> already.
Yea, a copypaste.
(I was told that if one submits modified patch, it adds his
Signed-off-by.)
I rebased these on top of
ACPI / EC / PM: Fix race between EC transactions and system suspend'
To be honest, I just want to get some feedback on this.
This was major issue that kept me from using otherwise prefect suspend
to ram.
Thus I am thinking that maybe ready to apply patch will have more
chances to be reviewed....
(Athough I guess I need to wait until the oil spill in gulf of Mexico is
plugged, because it seems to continue to feed the never ending
discussion/flamewar on android suspend issues)....
Best regards,
Maxim Levitsky
>
> Rafael
>
>
> > ---
> > arch/x86/kernel/e820.c | 2 +-
> > drivers/acpi/sleep.c | 12 ++--
> > include/linux/suspend.h | 26 ++++----
> > kernel/power/Kconfig | 9 ++-
> > kernel/power/Makefile | 2 +-
> > kernel/power/hibernate_nvs.c | 136 ------------------------------------------
> > kernel/power/nvs.c | 136 ++++++++++++++++++++++++++++++++++++++++++
> > kernel/power/suspend.c | 6 ++
> > 8 files changed, 168 insertions(+), 161 deletions(-)
> > delete mode 100644 kernel/power/hibernate_nvs.c
> > create mode 100644 kernel/power/nvs.c
> >
> > diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
> > index 7bca3c6..0d6fc71 100644
> > --- a/arch/x86/kernel/e820.c
> > +++ b/arch/x86/kernel/e820.c
> > @@ -729,7 +729,7 @@ static int __init e820_mark_nvs_memory(void)
> > struct e820entry *ei = &e820.map[i];
> >
> > if (ei->type == E820_NVS)
> > - hibernate_nvs_register(ei->addr, ei->size);
> > + suspend_nvs_register(ei->addr, ei->size);
> > }
> >
> > return 0;
> > diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
> > index 3fb4bde..bdb306f 100644
> > --- a/drivers/acpi/sleep.c
> > +++ b/drivers/acpi/sleep.c
> > @@ -404,7 +404,7 @@ static int acpi_hibernation_begin(void)
> > {
> > int error;
> >
> > - error = s4_no_nvs ? 0 : hibernate_nvs_alloc();
> > + error = s4_no_nvs ? 0 : suspend_nvs_alloc();
> > if (!error) {
> > acpi_target_sleep_state = ACPI_STATE_S4;
> > acpi_sleep_tts_switch(acpi_target_sleep_state);
> > @@ -418,7 +418,7 @@ static int acpi_hibernation_pre_snapshot(void)
> > int error = acpi_pm_prepare();
> >
> > if (!error)
> > - hibernate_nvs_save();
> > + suspend_nvs_save();
> >
> > return error;
> > }
> > @@ -443,7 +443,7 @@ static int acpi_hibernation_enter(void)
> >
> > static void acpi_hibernation_finish(void)
> > {
> > - hibernate_nvs_free();
> > + suspend_nvs_free();
> > acpi_ec_unblock_transactions();
> > acpi_pm_finish();
> > }
> > @@ -464,7 +464,7 @@ static void acpi_hibernation_leave(void)
> > panic("ACPI S4 hardware signature mismatch");
> > }
> > /* Restore the NVS memory area */
> > - hibernate_nvs_restore();
> > + suspend_nvs_restore();
> > /* Allow EC transactions to happen. */
> > acpi_ec_unblock_transactions_early();
> > }
> > @@ -507,7 +507,7 @@ static int acpi_hibernation_begin_old(void)
> >
> > if (!error) {
> > if (!s4_no_nvs)
> > - error = hibernate_nvs_alloc();
> > + error = suspend_nvs_alloc();
> > if (!error)
> > acpi_target_sleep_state = ACPI_STATE_S4;
> > }
> > @@ -517,7 +517,7 @@ static int acpi_hibernation_begin_old(void)
> > static int acpi_hibernation_pre_snapshot_old(void)
> > {
> > acpi_pm_freeze();
> > - hibernate_nvs_save();
> > + suspend_nvs_save();
> > return 0;
> > }
> >
> > diff --git a/include/linux/suspend.h b/include/linux/suspend.h
> > index 5e781d8..bc7d6bb 100644
> > --- a/include/linux/suspend.h
> > +++ b/include/linux/suspend.h
> > @@ -256,22 +256,22 @@ static inline int hibernate(void) { return -ENOSYS; }
> > static inline bool system_entering_hibernation(void) { return false; }
> > #endif /* CONFIG_HIBERNATION */
> >
> > -#ifdef CONFIG_HIBERNATION_NVS
> > -extern int hibernate_nvs_register(unsigned long start, unsigned long size);
> > -extern int hibernate_nvs_alloc(void);
> > -extern void hibernate_nvs_free(void);
> > -extern void hibernate_nvs_save(void);
> > -extern void hibernate_nvs_restore(void);
> > -#else /* CONFIG_HIBERNATION_NVS */
> > -static inline int hibernate_nvs_register(unsigned long a, unsigned long b)
> > +#ifdef CONFIG_SUSPEND_NVS
> > +extern int suspend_nvs_register(unsigned long start, unsigned long size);
> > +extern int suspend_nvs_alloc(void);
> > +extern void suspend_nvs_free(void);
> > +extern void suspend_nvs_save(void);
> > +extern void suspend_nvs_restore(void);
> > +#else /* CONFIG_SUSPEND_NVS */
> > +static inline int suspend_nvs_register(unsigned long a, unsigned long b)
> > {
> > return 0;
> > }
> > -static inline int hibernate_nvs_alloc(void) { return 0; }
> > -static inline void hibernate_nvs_free(void) {}
> > -static inline void hibernate_nvs_save(void) {}
> > -static inline void hibernate_nvs_restore(void) {}
> > -#endif /* CONFIG_HIBERNATION_NVS */
> > +static inline int suspend_nvs_alloc(void) { return 0; }
> > +static inline void suspend_nvs_free(void) {}
> > +static inline void suspend_nvs_save(void) {}
> > +static inline void suspend_nvs_restore(void) {}
> > +#endif /* CONFIG_SUSPEND_NVS */
> >
> > #ifdef CONFIG_PM_SLEEP
> > void save_processor_state(void);
> > diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
> > index 5c36ea9..ca6066a 100644
> > --- a/kernel/power/Kconfig
> > +++ b/kernel/power/Kconfig
> > @@ -99,9 +99,13 @@ config PM_SLEEP_ADVANCED_DEBUG
> > depends on PM_ADVANCED_DEBUG
> > default n
> >
> > +config SUSPEND_NVS
> > + bool
> > +
> > config SUSPEND
> > bool "Suspend to RAM and standby"
> > depends on PM && ARCH_SUSPEND_POSSIBLE
> > + select SUSPEND_NVS if HAS_IOMEM
> > default y
> > ---help---
> > Allow the system to enter sleep states in which main memory is
> > @@ -130,13 +134,10 @@ config SUSPEND_FREEZER
> >
> > Turning OFF this setting is NOT recommended! If in doubt, say Y.
> >
> > -config HIBERNATION_NVS
> > - bool
> > -
> > config HIBERNATION
> > bool "Hibernation (aka 'suspend to disk')"
> > depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
> > - select HIBERNATION_NVS if HAS_IOMEM
> > + select SUSPEND_NVS if HAS_IOMEM
> > ---help---
> > Enable the suspend to disk (STD) functionality, which is usually
> > called "hibernation" in user interfaces. STD checkpoints the
> > diff --git a/kernel/power/Makefile b/kernel/power/Makefile
> > index 524e058..f9063c6 100644
> > --- a/kernel/power/Makefile
> > +++ b/kernel/power/Makefile
> > @@ -10,6 +10,6 @@ obj-$(CONFIG_SUSPEND) += suspend.o
> > obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o
> > obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o \
> > block_io.o
> > -obj-$(CONFIG_HIBERNATION_NVS) += hibernate_nvs.o
> > +obj-$(CONFIG_SUSPEND_NVS) += nvs.o
> >
> > obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o
> > diff --git a/kernel/power/hibernate_nvs.c b/kernel/power/hibernate_nvs.c
> > deleted file mode 100644
> > index fdcad9e..0000000
> > --- a/kernel/power/hibernate_nvs.c
> > +++ /dev/null
> > @@ -1,136 +0,0 @@
> > -/*
> > - * linux/kernel/power/hibernate_nvs.c - Routines for handling NVS memory
> > - *
> > - * Copyright (C) 2008,2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
> > - *
> > - * This file is released under the GPLv2.
> > - */
> > -
> > -#include <linux/io.h>
> > -#include <linux/kernel.h>
> > -#include <linux/list.h>
> > -#include <linux/mm.h>
> > -#include <linux/slab.h>
> > -#include <linux/suspend.h>
> > -
> > -/*
> > - * Platforms, like ACPI, may want us to save some memory used by them during
> > - * hibernation and to restore the contents of this memory during the subsequent
> > - * resume. The code below implements a mechanism allowing us to do that.
> > - */
> > -
> > -struct nvs_page {
> > - unsigned long phys_start;
> > - unsigned int size;
> > - void *kaddr;
> > - void *data;
> > - struct list_head node;
> > -};
> > -
> > -static LIST_HEAD(nvs_list);
> > -
> > -/**
> > - * hibernate_nvs_register - register platform NVS memory region to save
> > - * @start - physical address of the region
> > - * @size - size of the region
> > - *
> > - * The NVS region need not be page-aligned (both ends) and we arrange
> > - * things so that the data from page-aligned addresses in this region will
> > - * be copied into separate RAM pages.
> > - */
> > -int hibernate_nvs_register(unsigned long start, unsigned long size)
> > -{
> > - struct nvs_page *entry, *next;
> > -
> > - while (size > 0) {
> > - unsigned int nr_bytes;
> > -
> > - entry = kzalloc(sizeof(struct nvs_page), GFP_KERNEL);
> > - if (!entry)
> > - goto Error;
> > -
> > - list_add_tail(&entry->node, &nvs_list);
> > - entry->phys_start = start;
> > - nr_bytes = PAGE_SIZE - (start & ~PAGE_MASK);
> > - entry->size = (size < nr_bytes) ? size : nr_bytes;
> > -
> > - start += entry->size;
> > - size -= entry->size;
> > - }
> > - return 0;
> > -
> > - Error:
> > - list_for_each_entry_safe(entry, next, &nvs_list, node) {
> > - list_del(&entry->node);
> > - kfree(entry);
> > - }
> > - return -ENOMEM;
> > -}
> > -
> > -/**
> > - * hibernate_nvs_free - free data pages allocated for saving NVS regions
> > - */
> > -void hibernate_nvs_free(void)
> > -{
> > - struct nvs_page *entry;
> > -
> > - list_for_each_entry(entry, &nvs_list, node)
> > - if (entry->data) {
> > - free_page((unsigned long)entry->data);
> > - entry->data = NULL;
> > - if (entry->kaddr) {
> > - iounmap(entry->kaddr);
> > - entry->kaddr = NULL;
> > - }
> > - }
> > -}
> > -
> > -/**
> > - * hibernate_nvs_alloc - allocate memory necessary for saving NVS regions
> > - */
> > -int hibernate_nvs_alloc(void)
> > -{
> > - struct nvs_page *entry;
> > -
> > - list_for_each_entry(entry, &nvs_list, node) {
> > - entry->data = (void *)__get_free_page(GFP_KERNEL);
> > - if (!entry->data) {
> > - hibernate_nvs_free();
> > - return -ENOMEM;
> > - }
> > - }
> > - return 0;
> > -}
> > -
> > -/**
> > - * hibernate_nvs_save - save NVS memory regions
> > - */
> > -void hibernate_nvs_save(void)
> > -{
> > - struct nvs_page *entry;
> > -
> > - printk(KERN_INFO "PM: Saving platform NVS memory\n");
> > -
> > - list_for_each_entry(entry, &nvs_list, node)
> > - if (entry->data) {
> > - entry->kaddr = ioremap(entry->phys_start, entry->size);
> > - memcpy(entry->data, entry->kaddr, entry->size);
> > - }
> > -}
> > -
> > -/**
> > - * hibernate_nvs_restore - restore NVS memory regions
> > - *
> > - * This function is going to be called with interrupts disabled, so it
> > - * cannot iounmap the virtual addresses used to access the NVS region.
> > - */
> > -void hibernate_nvs_restore(void)
> > -{
> > - struct nvs_page *entry;
> > -
> > - printk(KERN_INFO "PM: Restoring platform NVS memory\n");
> > -
> > - list_for_each_entry(entry, &nvs_list, node)
> > - if (entry->data)
> > - memcpy(entry->kaddr, entry->data, entry->size);
> > -}
> > diff --git a/kernel/power/nvs.c b/kernel/power/nvs.c
> > new file mode 100644
> > index 0000000..30c662f
> > --- /dev/null
> > +++ b/kernel/power/nvs.c
> > @@ -0,0 +1,136 @@
> > +/*
> > + * linux/kernel/power/nvs.c - Routines for handling NVS memory
> > + *
> > + * Copyright (C) 2008,2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
> > + *
> > + * This file is released under the GPLv2.
> > + */
> > +
> > +#include <linux/io.h>
> > +#include <linux/kernel.h>
> > +#include <linux/list.h>
> > +#include <linux/mm.h>
> > +#include <linux/slab.h>
> > +#include <linux/suspend.h>
> > +
> > +/*
> > + * Platforms, like ACPI, may want us to save some memory used by them during
> > + * suspend and to restore the contents of this memory during the subsequent
> > + * resume. The code below implements a mechanism allowing us to do that.
> > + */
> > +
> > +struct nvs_page {
> > + unsigned long phys_start;
> > + unsigned int size;
> > + void *kaddr;
> > + void *data;
> > + struct list_head node;
> > +};
> > +
> > +static LIST_HEAD(nvs_list);
> > +
> > +/**
> > + * suspend_nvs_register - register platform NVS memory region to save
> > + * @start - physical address of the region
> > + * @size - size of the region
> > + *
> > + * The NVS region need not be page-aligned (both ends) and we arrange
> > + * things so that the data from page-aligned addresses in this region will
> > + * be copied into separate RAM pages.
> > + */
> > +int suspend_nvs_register(unsigned long start, unsigned long size)
> > +{
> > + struct nvs_page *entry, *next;
> > +
> > + while (size > 0) {
> > + unsigned int nr_bytes;
> > +
> > + entry = kzalloc(sizeof(struct nvs_page), GFP_KERNEL);
> > + if (!entry)
> > + goto Error;
> > +
> > + list_add_tail(&entry->node, &nvs_list);
> > + entry->phys_start = start;
> > + nr_bytes = PAGE_SIZE - (start & ~PAGE_MASK);
> > + entry->size = (size < nr_bytes) ? size : nr_bytes;
> > +
> > + start += entry->size;
> > + size -= entry->size;
> > + }
> > + return 0;
> > +
> > + Error:
> > + list_for_each_entry_safe(entry, next, &nvs_list, node) {
> > + list_del(&entry->node);
> > + kfree(entry);
> > + }
> > + return -ENOMEM;
> > +}
> > +
> > +/**
> > + * suspend_nvs_free - free data pages allocated for saving NVS regions
> > + */
> > +void suspend_nvs_free(void)
> > +{
> > + struct nvs_page *entry;
> > +
> > + list_for_each_entry(entry, &nvs_list, node)
> > + if (entry->data) {
> > + free_page((unsigned long)entry->data);
> > + entry->data = NULL;
> > + if (entry->kaddr) {
> > + iounmap(entry->kaddr);
> > + entry->kaddr = NULL;
> > + }
> > + }
> > +}
> > +
> > +/**
> > + * suspend_nvs_alloc - allocate memory necessary for saving NVS regions
> > + */
> > +int suspend_nvs_alloc(void)
> > +{
> > + struct nvs_page *entry;
> > +
> > + list_for_each_entry(entry, &nvs_list, node) {
> > + entry->data = (void *)__get_free_page(GFP_KERNEL);
> > + if (!entry->data) {
> > + suspend_nvs_free();
> > + return -ENOMEM;
> > + }
> > + }
> > + return 0;
> > +}
> > +
> > +/**
> > + * suspend_nvs_save - save NVS memory regions
> > + */
> > +void suspend_nvs_save(void)
> > +{
> > + struct nvs_page *entry;
> > +
> > + printk(KERN_INFO "PM: Saving platform NVS memory\n");
> > +
> > + list_for_each_entry(entry, &nvs_list, node)
> > + if (entry->data) {
> > + entry->kaddr = ioremap(entry->phys_start, entry->size);
> > + memcpy(entry->data, entry->kaddr, entry->size);
> > + }
> > +}
> > +
> > +/**
> > + * suspend_nvs_restore - restore NVS memory regions
> > + *
> > + * This function is going to be called with interrupts disabled, so it
> > + * cannot iounmap the virtual addresses used to access the NVS region.
> > + */
> > +void suspend_nvs_restore(void)
> > +{
> > + struct nvs_page *entry;
> > +
> > + printk(KERN_INFO "PM: Restoring platform NVS memory\n");
> > +
> > + list_for_each_entry(entry, &nvs_list, node)
> > + if (entry->data)
> > + memcpy(entry->kaddr, entry->data, entry->size);
> > +}
> > diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
> > index 56e7dbb..f37cb7d 100644
> > --- a/kernel/power/suspend.c
> > +++ b/kernel/power/suspend.c
> > @@ -16,6 +16,12 @@
> > #include <linux/cpu.h>
> > #include <linux/syscalls.h>
> > #include <linux/gfp.h>
> > +#include <linux/io.h>
> > +#include <linux/kernel.h>
> > +#include <linux/list.h>
> > +#include <linux/mm.h>
> > +#include <linux/slab.h>
> > +#include <linux/suspend.h>
> >
> > #include "power.h"
> >
> >
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality
2010-06-01 21:52 ` Maxim Levitsky
@ 2010-06-01 22:40 ` Rafael J. Wysocki
2010-06-01 22:46 ` Maxim Levitsky
0 siblings, 1 reply; 21+ messages in thread
From: Rafael J. Wysocki @ 2010-06-01 22:40 UTC (permalink / raw)
To: Maxim Levitsky
Cc: linux-acpi@vger.kernel.org, linux-pm, Matthew Garrett, Alan Stern
On Tuesday 01 June 2010, Maxim Levitsky wrote:
> On Tue, 2010-06-01 at 23:31 +0200, Rafael J. Wysocki wrote:
> > On Tuesday 01 June 2010, Maxim Levitsky wrote:
> > > Saving platform non-volatile state may be required for suspend to RAM as
> > > well as hibernation. Move it to more generic code.
> > >
> > > Signed-off-by: Matthew Garrett <mjg@redhat.com>
> > > Signed-off-by: Matthew Garrett <maximlevitsky@gmail.com>
> >
> > You made a mistake here.
> >
> > Also, why are you resending the Matthews patches? I think Len has seen them
> > already.
> Yea, a copypaste.
>
> (I was told that if one submits modified patch, it adds his
> Signed-off-by.)
>
> I rebased these on top of
> ACPI / EC / PM: Fix race between EC transactions and system suspend'
>
> To be honest, I just want to get some feedback on this.
> This was major issue that kept me from using otherwise prefect suspend
> to ram.
I think this is a change we should try, but there is a chance it will break
some systems.
> Thus I am thinking that maybe ready to apply patch will have more
> chances to be reviewed....
Not really (as far as I'm concerned at least). :-)
Rafael
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality
2010-06-01 22:40 ` Rafael J. Wysocki
@ 2010-06-01 22:46 ` Maxim Levitsky
2010-06-01 23:34 ` Rafael J. Wysocki
2010-06-10 13:58 ` [linux-pm] " Pavel Machek
0 siblings, 2 replies; 21+ messages in thread
From: Maxim Levitsky @ 2010-06-01 22:46 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: linux-acpi@vger.kernel.org, linux-pm, Matthew Garrett, Alan Stern
On Wed, 2010-06-02 at 00:40 +0200, Rafael J. Wysocki wrote:
> On Tuesday 01 June 2010, Maxim Levitsky wrote:
> > On Tue, 2010-06-01 at 23:31 +0200, Rafael J. Wysocki wrote:
> > > On Tuesday 01 June 2010, Maxim Levitsky wrote:
> > > > Saving platform non-volatile state may be required for suspend to RAM as
> > > > well as hibernation. Move it to more generic code.
> > > >
> > > > Signed-off-by: Matthew Garrett <mjg@redhat.com>
> > > > Signed-off-by: Matthew Garrett <maximlevitsky@gmail.com>
> > >
> > > You made a mistake here.
> > >
> > > Also, why are you resending the Matthews patches? I think Len has seen them
> > > already.
> > Yea, a copypaste.
> >
> > (I was told that if one submits modified patch, it adds his
> > Signed-off-by.)
> >
> > I rebased these on top of
> > ACPI / EC / PM: Fix race between EC transactions and system suspend'
> >
> > To be honest, I just want to get some feedback on this.
> > This was major issue that kept me from using otherwise prefect suspend
> > to ram.
>
> I think this is a change we should try, but there is a chance it will break
> some systems.
I doubt that. BIOSes are tested against windows, and since it has this
behavior, all systems this patch could break wouldn't work in windows
ether.
I was doing all kinds of attempts to fix this bug, and finally I found
the cause for it.
Best regards,
Maxim Levitsky
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality
2010-06-01 22:46 ` Maxim Levitsky
@ 2010-06-01 23:34 ` Rafael J. Wysocki
2010-06-10 13:58 ` [linux-pm] " Pavel Machek
1 sibling, 0 replies; 21+ messages in thread
From: Rafael J. Wysocki @ 2010-06-01 23:34 UTC (permalink / raw)
To: Maxim Levitsky
Cc: linux-acpi@vger.kernel.org, linux-pm, Matthew Garrett, Alan Stern
On Wednesday 02 June 2010, Maxim Levitsky wrote:
> On Wed, 2010-06-02 at 00:40 +0200, Rafael J. Wysocki wrote:
> > On Tuesday 01 June 2010, Maxim Levitsky wrote:
> > > On Tue, 2010-06-01 at 23:31 +0200, Rafael J. Wysocki wrote:
> > > > On Tuesday 01 June 2010, Maxim Levitsky wrote:
> > > > > Saving platform non-volatile state may be required for suspend to RAM as
> > > > > well as hibernation. Move it to more generic code.
> > > > >
> > > > > Signed-off-by: Matthew Garrett <mjg@redhat.com>
> > > > > Signed-off-by: Matthew Garrett <maximlevitsky@gmail.com>
> > > >
> > > > You made a mistake here.
> > > >
> > > > Also, why are you resending the Matthews patches? I think Len has seen them
> > > > already.
> > > Yea, a copypaste.
> > >
> > > (I was told that if one submits modified patch, it adds his
> > > Signed-off-by.)
> > >
> > > I rebased these on top of
> > > ACPI / EC / PM: Fix race between EC transactions and system suspend'
> > >
> > > To be honest, I just want to get some feedback on this.
> > > This was major issue that kept me from using otherwise prefect suspend
> > > to ram.
> >
> > I think this is a change we should try, but there is a chance it will break
> > some systems.
> I doubt that. BIOSes are tested against windows, and since it has this
> behavior, all systems this patch could break wouldn't work in windows
> ether.
Still, some systems were broken by the saving-restoring NVS over hibernation.
> I was doing all kinds of attempts to fix this bug, and finally I found
> the cause for it.
I know and I'm not objecting to the patches. I'm only saying we should be
careful with them.
Rafael
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM
2010-05-30 14:51 ` Matthew Garrett
@ 2010-06-02 3:32 ` Henrique de Moraes Holschuh
2010-06-02 10:15 ` Maxim Levitsky
2010-06-02 11:47 ` Matthew Garrett
0 siblings, 2 replies; 21+ messages in thread
From: Henrique de Moraes Holschuh @ 2010-06-02 3:32 UTC (permalink / raw)
To: Matthew Garrett; +Cc: Maxim Levitsky, lenb, linux-acpi, linux-pm
On Sun, 30 May 2010, Matthew Garrett wrote:
> On Sun, May 30, 2010 at 05:40:04PM +0300, Maxim Levitsky wrote:
> > Just one note, I am sure somebody will ask for s3_no_nvs option, just
> > like s4_no_nvs.
>
> I'd be surprised. Better to add the option when we think it's needed.
Do _all_ Windows versions restore NVS over S3 suspend/resume?
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM
2010-06-02 3:32 ` Henrique de Moraes Holschuh
@ 2010-06-02 10:15 ` Maxim Levitsky
2010-06-02 11:47 ` Matthew Garrett
1 sibling, 0 replies; 21+ messages in thread
From: Maxim Levitsky @ 2010-06-02 10:15 UTC (permalink / raw)
To: Henrique de Moraes Holschuh; +Cc: Matthew Garrett, lenb, linux-acpi, linux-pm
On Wed, 2010-06-02 at 00:32 -0300, Henrique de Moraes Holschuh wrote:
> On Sun, 30 May 2010, Matthew Garrett wrote:
> > On Sun, May 30, 2010 at 05:40:04PM +0300, Maxim Levitsky wrote:
> > > Just one note, I am sure somebody will ask for s3_no_nvs option, just
> > > like s4_no_nvs.
> >
> > I'd be surprised. Better to add the option when we think it's needed.
>
> Do _all_ Windows versions restore NVS over S3 suspend/resume?
This is very good question, I test it in future (if Matthew Garrett
doesn't beat me to it...)
I have a copy of XP,Vista,Win7, all obtained for free through
Microsoft's "first dose is always free" university program.
Best regards,
Maxim Levitsky
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM
2010-06-02 3:32 ` Henrique de Moraes Holschuh
2010-06-02 10:15 ` Maxim Levitsky
@ 2010-06-02 11:47 ` Matthew Garrett
2010-06-02 13:06 ` Maxim Levitsky
1 sibling, 1 reply; 21+ messages in thread
From: Matthew Garrett @ 2010-06-02 11:47 UTC (permalink / raw)
To: Henrique de Moraes Holschuh; +Cc: Maxim Levitsky, lenb, linux-acpi, linux-pm
On Wed, Jun 02, 2010 at 12:32:25AM -0300, Henrique de Moraes Holschuh wrote:
> On Sun, 30 May 2010, Matthew Garrett wrote:
> > On Sun, May 30, 2010 at 05:40:04PM +0300, Maxim Levitsky wrote:
> > > Just one note, I am sure somebody will ask for s3_no_nvs option, just
> > > like s4_no_nvs.
> >
> > I'd be surprised. Better to add the option when we think it's needed.
>
> Do _all_ Windows versions restore NVS over S3 suspend/resume?
XP does regardless of whether any OSI strings are presented, and we have
systems that break unless it's done, so I think it's a safe bet.
--
Matthew Garrett | mjg59@srcf.ucam.org
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM
2010-06-02 11:47 ` Matthew Garrett
@ 2010-06-02 13:06 ` Maxim Levitsky
0 siblings, 0 replies; 21+ messages in thread
From: Maxim Levitsky @ 2010-06-02 13:06 UTC (permalink / raw)
To: Matthew Garrett; +Cc: Henrique de Moraes Holschuh, lenb, linux-acpi, linux-pm
On Wed, 2010-06-02 at 12:47 +0100, Matthew Garrett wrote:
> On Wed, Jun 02, 2010 at 12:32:25AM -0300, Henrique de Moraes Holschuh wrote:
> > On Sun, 30 May 2010, Matthew Garrett wrote:
> > > On Sun, May 30, 2010 at 05:40:04PM +0300, Maxim Levitsky wrote:
> > > > Just one note, I am sure somebody will ask for s3_no_nvs option, just
> > > > like s4_no_nvs.
> > >
> > > I'd be surprised. Better to add the option when we think it's needed.
> >
> > Do _all_ Windows versions restore NVS over S3 suspend/resume?
>
> XP does regardless of whether any OSI strings are presented, and we have
> systems that break unless it's done, so I think it's a safe bet.
This laptop was shipped with Vista, and since suspend works I guess its
highly likely that vista does restore NVS this way too.
This only leaves W7. I doubt they would break older systems by fixing a
bug....
Best regards,
Maxim Levitsky
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM
2010-05-28 20:32 ` [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM Matthew Garrett
2010-05-30 14:40 ` Maxim Levitsky
@ 2010-06-04 18:23 ` Len Brown
2010-06-10 9:41 ` Maxim Levitsky
2 siblings, 0 replies; 21+ messages in thread
From: Len Brown @ 2010-06-04 18:23 UTC (permalink / raw)
To: Matthew Garrett; +Cc: linux-acpi, linux-pm
applied to acpi-test
thanks,
Len Brown, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM
2010-05-28 20:32 ` [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM Matthew Garrett
2010-05-30 14:40 ` Maxim Levitsky
2010-06-04 18:23 ` Len Brown
@ 2010-06-10 9:41 ` Maxim Levitsky
2 siblings, 0 replies; 21+ messages in thread
From: Maxim Levitsky @ 2010-06-10 9:41 UTC (permalink / raw)
To: Matthew Garrett; +Cc: lenb, linux-acpi, linux-pm
On Fri, 2010-05-28 at 16:32 -0400, Matthew Garrett wrote:
> https://bugzilla.kernel.org/show_bug.cgi?id=13931 describes a bug where
> a system fails to successfully resume after the second suspend. Maxim
> Levitsky discovered that this could be rectified by forcibly saving
> and restoring the ACPI non-volatile state. The spec indicates that this
> is only required for S4, but testing the behaviour of Windows by adding
> an ACPI NVS region to qemu's e820 map and registering a custom memory
> read/write handler reveals that it's saved and restored even over suspend
> to RAM. We should mimic that behaviour to avoid other broken platforms.
Any chance to see this patch in 2.6.35?
Best regards,
Maxim Levitsky
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [linux-pm] [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality
2010-06-01 22:46 ` Maxim Levitsky
2010-06-01 23:34 ` Rafael J. Wysocki
@ 2010-06-10 13:58 ` Pavel Machek
2010-06-10 14:09 ` Matthew Garrett
1 sibling, 1 reply; 21+ messages in thread
From: Pavel Machek @ 2010-06-10 13:58 UTC (permalink / raw)
To: Maxim Levitsky
Cc: Rafael J. Wysocki, linux-acpi@vger.kernel.org, linux-pm,
Matthew Garrett
Hi!
> > > To be honest, I just want to get some feedback on this.
> > > This was major issue that kept me from using otherwise prefect suspend
> > > to ram.
> >
> > I think this is a change we should try, but there is a chance it will break
> > some systems.
> I doubt that. BIOSes are tested against windows, and since it has this
> behavior, all systems this patch could break wouldn't work in windows
> ether.
>
> I was doing all kinds of attempts to fix this bug, and finally I found
> the cause for it.
Well... should we only do it in 'platform' hibernation mode? There are
machines that predate windows/acpi and still should hibernate.
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [linux-pm] [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality
2010-06-10 13:58 ` [linux-pm] " Pavel Machek
@ 2010-06-10 14:09 ` Matthew Garrett
2010-06-11 13:32 ` Henrique de Moraes Holschuh
0 siblings, 1 reply; 21+ messages in thread
From: Matthew Garrett @ 2010-06-10 14:09 UTC (permalink / raw)
To: Pavel Machek
Cc: Maxim Levitsky, Rafael J. Wysocki, linux-acpi@vger.kernel.org,
linux-pm
On Thu, Jun 10, 2010 at 03:58:16PM +0200, Pavel Machek wrote:
> Well... should we only do it in 'platform' hibernation mode? There are
> machines that predate windows/acpi and still should hibernate.
If they predate acpi then they won't declare any NVS regions.
--
Matthew Garrett | mjg59@srcf.ucam.org
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [linux-pm] [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality
2010-06-10 14:09 ` Matthew Garrett
@ 2010-06-11 13:32 ` Henrique de Moraes Holschuh
2010-06-11 13:41 ` Matthew Garrett
0 siblings, 1 reply; 21+ messages in thread
From: Henrique de Moraes Holschuh @ 2010-06-11 13:32 UTC (permalink / raw)
To: Matthew Garrett
Cc: Pavel Machek, Maxim Levitsky, Rafael J. Wysocki,
linux-acpi@vger.kernel.org, linux-pm
On Thu, 10 Jun 2010, Matthew Garrett wrote:
> On Thu, Jun 10, 2010 at 03:58:16PM +0200, Pavel Machek wrote:
> > Well... should we only do it in 'platform' hibernation mode? There are
> > machines that predate windows/acpi and still should hibernate.
>
> If they predate acpi then they won't declare any NVS regions.
What if they're ACPI and APM capable, and in APM mode? Would the code need
to guard against that?
--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [linux-pm] [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality
2010-06-11 13:32 ` Henrique de Moraes Holschuh
@ 2010-06-11 13:41 ` Matthew Garrett
0 siblings, 0 replies; 21+ messages in thread
From: Matthew Garrett @ 2010-06-11 13:41 UTC (permalink / raw)
To: Henrique de Moraes Holschuh
Cc: Pavel Machek, Maxim Levitsky, Rafael J. Wysocki,
linux-acpi@vger.kernel.org, linux-pm
On Fri, Jun 11, 2010 at 10:32:19AM -0300, Henrique de Moraes Holschuh wrote:
> On Thu, 10 Jun 2010, Matthew Garrett wrote:
> > On Thu, Jun 10, 2010 at 03:58:16PM +0200, Pavel Machek wrote:
> > > Well... should we only do it in 'platform' hibernation mode? There are
> > > machines that predate windows/acpi and still should hibernate.
> >
> > If they predate acpi then they won't declare any NVS regions.
>
> What if they're ACPI and APM capable, and in APM mode? Would the code need
> to guard against that?
I can't imagine any case where that would cause problems, but if it does
then it's an easy fix.
--
Matthew Garrett | mjg59@srcf.ucam.org
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2010-06-11 13:41 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-01 18:19 [PATCH] Store BIOS NVS area over s2ram [V2] Maxim Levitsky
2010-06-01 18:22 ` [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality Maxim Levitsky
2010-06-01 21:31 ` Rafael J. Wysocki
2010-06-01 21:52 ` Maxim Levitsky
2010-06-01 22:40 ` Rafael J. Wysocki
2010-06-01 22:46 ` Maxim Levitsky
2010-06-01 23:34 ` Rafael J. Wysocki
2010-06-10 13:58 ` [linux-pm] " Pavel Machek
2010-06-10 14:09 ` Matthew Garrett
2010-06-11 13:32 ` Henrique de Moraes Holschuh
2010-06-11 13:41 ` Matthew Garrett
2010-06-01 18:22 ` [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM Maxim Levitsky
-- strict thread matches above, loose matches on Subject: below --
2010-05-28 20:32 [PATCH 1/2] suspend: Move NVS save/restore code to generic suspend functionality Matthew Garrett
2010-05-28 20:32 ` [PATCH 2/2] ACPI: Store NVS state even when entering suspend to RAM Matthew Garrett
2010-05-30 14:40 ` Maxim Levitsky
2010-05-30 14:51 ` Matthew Garrett
2010-06-02 3:32 ` Henrique de Moraes Holschuh
2010-06-02 10:15 ` Maxim Levitsky
2010-06-02 11:47 ` Matthew Garrett
2010-06-02 13:06 ` Maxim Levitsky
2010-06-04 18:23 ` Len Brown
2010-06-10 9:41 ` Maxim Levitsky
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).