Commit b54ac6d2 authored by Huang Ying's avatar Huang Ying Committed by Len Brown

ACPI, Record ACPI NVS regions

Some firmware will access memory in ACPI NVS region via APEI.  That
is, instructions in APEI ERST/EINJ table will read/write ACPI NVS
region.  The original resource conflict checking in APEI code will
check memory/ioport accessed by APEI via general resource management
mechanism.  But ACPI NVS region is marked as busy already, so that the
false resource conflict will prevent APEI ERST/EINJ to work.

To fix this, this patch record ACPI NVS regions, so that we can avoid
request resources for memory region inside it.
Signed-off-by: default avatarHuang Ying <ying.huang@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent b4e008dc
...@@ -714,7 +714,7 @@ void __init e820_mark_nosave_regions(unsigned long limit_pfn) ...@@ -714,7 +714,7 @@ void __init e820_mark_nosave_regions(unsigned long limit_pfn)
} }
#endif #endif
#ifdef CONFIG_HIBERNATION #ifdef CONFIG_ACPI
/** /**
* Mark ACPI NVS memory region, so that we can save/restore it during * Mark ACPI NVS memory region, so that we can save/restore it during
* hibernation and the subsequent resume. * hibernation and the subsequent resume.
...@@ -727,7 +727,7 @@ static int __init e820_mark_nvs_memory(void) ...@@ -727,7 +727,7 @@ static int __init e820_mark_nvs_memory(void)
struct e820entry *ei = &e820.map[i]; struct e820entry *ei = &e820.map[i];
if (ei->type == E820_NVS) if (ei->type == E820_NVS)
suspend_nvs_register(ei->addr, ei->size); acpi_nvs_register(ei->addr, ei->size);
} }
return 0; return 0;
......
...@@ -20,11 +20,12 @@ obj-y += acpi.o \ ...@@ -20,11 +20,12 @@ obj-y += acpi.o \
# All the builtin files are in the "acpi." module_param namespace. # All the builtin files are in the "acpi." module_param namespace.
acpi-y += osl.o utils.o reboot.o acpi-y += osl.o utils.o reboot.o
acpi-y += atomicio.o acpi-y += atomicio.o
acpi-y += nvs.o
# sleep related files # sleep related files
acpi-y += wakeup.o acpi-y += wakeup.o
acpi-y += sleep.o acpi-y += sleep.o
acpi-$(CONFIG_ACPI_SLEEP) += proc.o nvs.o acpi-$(CONFIG_ACPI_SLEEP) += proc.o
# #
......
...@@ -15,6 +15,56 @@ ...@@ -15,6 +15,56 @@
#include <linux/acpi_io.h> #include <linux/acpi_io.h>
#include <acpi/acpiosxf.h> #include <acpi/acpiosxf.h>
/* ACPI NVS regions, APEI may use it */
struct nvs_region {
__u64 phys_start;
__u64 size;
struct list_head node;
};
static LIST_HEAD(nvs_region_list);
#ifdef CONFIG_ACPI_SLEEP
static int suspend_nvs_register(unsigned long start, unsigned long size);
#else
static inline int suspend_nvs_register(unsigned long a, unsigned long b)
{
return 0;
}
#endif
int acpi_nvs_register(__u64 start, __u64 size)
{
struct nvs_region *region;
region = kmalloc(sizeof(*region), GFP_KERNEL);
if (!region)
return -ENOMEM;
region->phys_start = start;
region->size = size;
list_add_tail(&region->node, &nvs_region_list);
return suspend_nvs_register(start, size);
}
int acpi_nvs_for_each_region(int (*func)(__u64 start, __u64 size, void *data),
void *data)
{
int rc;
struct nvs_region *region;
list_for_each_entry(region, &nvs_region_list, node) {
rc = func(region->phys_start, region->size, data);
if (rc)
return rc;
}
return 0;
}
#ifdef CONFIG_ACPI_SLEEP
/* /*
* Platforms, like ACPI, may want us to save some memory used by them during * 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 * suspend and to restore the contents of this memory during the subsequent
...@@ -41,7 +91,7 @@ static LIST_HEAD(nvs_list); ...@@ -41,7 +91,7 @@ static LIST_HEAD(nvs_list);
* things so that the data from page-aligned addresses in this region will * things so that the data from page-aligned addresses in this region will
* be copied into separate RAM pages. * be copied into separate RAM pages.
*/ */
int suspend_nvs_register(unsigned long start, unsigned long size) static int suspend_nvs_register(unsigned long start, unsigned long size)
{ {
struct nvs_page *entry, *next; struct nvs_page *entry, *next;
...@@ -159,3 +209,4 @@ void suspend_nvs_restore(void) ...@@ -159,3 +209,4 @@ void suspend_nvs_restore(void)
if (entry->data) if (entry->data)
memcpy(entry->kaddr, entry->data, entry->size); memcpy(entry->kaddr, entry->data, entry->size);
} }
#endif
...@@ -306,6 +306,11 @@ extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, ...@@ -306,6 +306,11 @@ extern acpi_status acpi_pci_osc_control_set(acpi_handle handle,
u32 *mask, u32 req); u32 *mask, u32 req);
extern void acpi_early_init(void); extern void acpi_early_init(void);
extern int acpi_nvs_register(__u64 start, __u64 size);
extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
void *data);
#else /* !CONFIG_ACPI */ #else /* !CONFIG_ACPI */
#define acpi_disabled 1 #define acpi_disabled 1
...@@ -348,15 +353,18 @@ static inline int acpi_table_parse(char *id, ...@@ -348,15 +353,18 @@ static inline int acpi_table_parse(char *id,
{ {
return -1; return -1;
} }
#endif /* !CONFIG_ACPI */
#ifdef CONFIG_ACPI_SLEEP static inline int acpi_nvs_register(__u64 start, __u64 size)
int suspend_nvs_register(unsigned long start, unsigned long size);
#else
static inline int suspend_nvs_register(unsigned long a, unsigned long b)
{ {
return 0; return 0;
} }
#endif
static inline int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
void *data)
{
return 0;
}
#endif /* !CONFIG_ACPI */
#endif /*_LINUX_ACPI_H*/ #endif /*_LINUX_ACPI_H*/
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment