diff options
-rw-r--r-- | arch/x86/kernel/e820.c | 4 | ||||
-rw-r--r-- | drivers/acpi/Makefile | 3 | ||||
-rw-r--r-- | drivers/acpi/nvs.c | 53 | ||||
-rw-r--r-- | include/linux/acpi.h | 20 |
4 files changed, 70 insertions, 10 deletions
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 303a0e48f076..51c3b186e5b9 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c | |||
@@ -714,7 +714,7 @@ void __init e820_mark_nosave_regions(unsigned long limit_pfn) | |||
714 | } | 714 | } |
715 | #endif | 715 | #endif |
716 | 716 | ||
717 | #ifdef CONFIG_HIBERNATION | 717 | #ifdef CONFIG_ACPI |
718 | /** | 718 | /** |
719 | * Mark ACPI NVS memory region, so that we can save/restore it during | 719 | * Mark ACPI NVS memory region, so that we can save/restore it during |
720 | * hibernation and the subsequent resume. | 720 | * hibernation and the subsequent resume. |
@@ -727,7 +727,7 @@ static int __init e820_mark_nvs_memory(void) | |||
727 | struct e820entry *ei = &e820.map[i]; | 727 | struct e820entry *ei = &e820.map[i]; |
728 | 728 | ||
729 | if (ei->type == E820_NVS) | 729 | if (ei->type == E820_NVS) |
730 | suspend_nvs_register(ei->addr, ei->size); | 730 | acpi_nvs_register(ei->addr, ei->size); |
731 | } | 731 | } |
732 | 732 | ||
733 | return 0; | 733 | return 0; |
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index ecb26b4f29a0..c07f44f05f9d 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
@@ -20,11 +20,12 @@ obj-y += acpi.o \ | |||
20 | # All the builtin files are in the "acpi." module_param namespace. | 20 | # All the builtin files are in the "acpi." module_param namespace. |
21 | acpi-y += osl.o utils.o reboot.o | 21 | acpi-y += osl.o utils.o reboot.o |
22 | acpi-y += atomicio.o | 22 | acpi-y += atomicio.o |
23 | acpi-y += nvs.o | ||
23 | 24 | ||
24 | # sleep related files | 25 | # sleep related files |
25 | acpi-y += wakeup.o | 26 | acpi-y += wakeup.o |
26 | acpi-y += sleep.o | 27 | acpi-y += sleep.o |
27 | acpi-$(CONFIG_ACPI_SLEEP) += proc.o nvs.o | 28 | acpi-$(CONFIG_ACPI_SLEEP) += proc.o |
28 | 29 | ||
29 | 30 | ||
30 | # | 31 | # |
diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c index 096787b43c96..7a2035fa8c71 100644 --- a/drivers/acpi/nvs.c +++ b/drivers/acpi/nvs.c | |||
@@ -15,6 +15,56 @@ | |||
15 | #include <linux/acpi_io.h> | 15 | #include <linux/acpi_io.h> |
16 | #include <acpi/acpiosxf.h> | 16 | #include <acpi/acpiosxf.h> |
17 | 17 | ||
18 | /* ACPI NVS regions, APEI may use it */ | ||
19 | |||
20 | struct nvs_region { | ||
21 | __u64 phys_start; | ||
22 | __u64 size; | ||
23 | struct list_head node; | ||
24 | }; | ||
25 | |||
26 | static LIST_HEAD(nvs_region_list); | ||
27 | |||
28 | #ifdef CONFIG_ACPI_SLEEP | ||
29 | static int suspend_nvs_register(unsigned long start, unsigned long size); | ||
30 | #else | ||
31 | static inline int suspend_nvs_register(unsigned long a, unsigned long b) | ||
32 | { | ||
33 | return 0; | ||
34 | } | ||
35 | #endif | ||
36 | |||
37 | int acpi_nvs_register(__u64 start, __u64 size) | ||
38 | { | ||
39 | struct nvs_region *region; | ||
40 | |||
41 | region = kmalloc(sizeof(*region), GFP_KERNEL); | ||
42 | if (!region) | ||
43 | return -ENOMEM; | ||
44 | region->phys_start = start; | ||
45 | region->size = size; | ||
46 | list_add_tail(®ion->node, &nvs_region_list); | ||
47 | |||
48 | return suspend_nvs_register(start, size); | ||
49 | } | ||
50 | |||
51 | int acpi_nvs_for_each_region(int (*func)(__u64 start, __u64 size, void *data), | ||
52 | void *data) | ||
53 | { | ||
54 | int rc; | ||
55 | struct nvs_region *region; | ||
56 | |||
57 | list_for_each_entry(region, &nvs_region_list, node) { | ||
58 | rc = func(region->phys_start, region->size, data); | ||
59 | if (rc) | ||
60 | return rc; | ||
61 | } | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | |||
67 | #ifdef CONFIG_ACPI_SLEEP | ||
18 | /* | 68 | /* |
19 | * Platforms, like ACPI, may want us to save some memory used by them during | 69 | * Platforms, like ACPI, may want us to save some memory used by them during |
20 | * suspend and to restore the contents of this memory during the subsequent | 70 | * suspend and to restore the contents of this memory during the subsequent |
@@ -41,7 +91,7 @@ static LIST_HEAD(nvs_list); | |||
41 | * things so that the data from page-aligned addresses in this region will | 91 | * things so that the data from page-aligned addresses in this region will |
42 | * be copied into separate RAM pages. | 92 | * be copied into separate RAM pages. |
43 | */ | 93 | */ |
44 | int suspend_nvs_register(unsigned long start, unsigned long size) | 94 | static int suspend_nvs_register(unsigned long start, unsigned long size) |
45 | { | 95 | { |
46 | struct nvs_page *entry, *next; | 96 | struct nvs_page *entry, *next; |
47 | 97 | ||
@@ -159,3 +209,4 @@ void suspend_nvs_restore(void) | |||
159 | if (entry->data) | 209 | if (entry->data) |
160 | memcpy(entry->kaddr, entry->data, entry->size); | 210 | memcpy(entry->kaddr, entry->data, entry->size); |
161 | } | 211 | } |
212 | #endif | ||
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 6001b4da39dd..26b75442ff7a 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -306,6 +306,11 @@ extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, | |||
306 | u32 *mask, u32 req); | 306 | u32 *mask, u32 req); |
307 | extern void acpi_early_init(void); | 307 | extern void acpi_early_init(void); |
308 | 308 | ||
309 | extern int acpi_nvs_register(__u64 start, __u64 size); | ||
310 | |||
311 | extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *), | ||
312 | void *data); | ||
313 | |||
309 | #else /* !CONFIG_ACPI */ | 314 | #else /* !CONFIG_ACPI */ |
310 | 315 | ||
311 | #define acpi_disabled 1 | 316 | #define acpi_disabled 1 |
@@ -348,15 +353,18 @@ static inline int acpi_table_parse(char *id, | |||
348 | { | 353 | { |
349 | return -1; | 354 | return -1; |
350 | } | 355 | } |
351 | #endif /* !CONFIG_ACPI */ | ||
352 | 356 | ||
353 | #ifdef CONFIG_ACPI_SLEEP | 357 | static inline int acpi_nvs_register(__u64 start, __u64 size) |
354 | int suspend_nvs_register(unsigned long start, unsigned long size); | ||
355 | #else | ||
356 | static inline int suspend_nvs_register(unsigned long a, unsigned long b) | ||
357 | { | 358 | { |
358 | return 0; | 359 | return 0; |
359 | } | 360 | } |
360 | #endif | 361 | |
362 | static inline int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *), | ||
363 | void *data) | ||
364 | { | ||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | #endif /* !CONFIG_ACPI */ | ||
361 | 369 | ||
362 | #endif /*_LINUX_ACPI_H*/ | 370 | #endif /*_LINUX_ACPI_H*/ |