From: Huang Ying <ying.huang@intel.com>
To: Pavel Ivanov <paivanof@gmail.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>,
linux-kernel <linux-kernel@vger.kernel.org>,
"linux-acpi@vger.kernel.org" <linux-acpi@vger.kernel.org>
Subject: Re: APEI: Can not request iomem region for GARs
Date: Mon, 22 Aug 2011 15:12:09 +0800 [thread overview]
Message-ID: <4E520149.3010802@intel.com> (raw)
In-Reply-To: <CAErSpo4FfBoGDUquoLNsJ9=z-M-x6NQgP8xJL_VqEXpsL2H5PA@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 129 bytes --]
Hi, Pavel,
Do you have time to try the patch attached with the mail?
acpi_nvs.patch should go first.
Best Regards,
Huang Ying
[-- Attachment #2: acpi_nvs.patch --]
[-- Type: text/x-patch, Size: 4487 bytes --]
Subject: [PATCH] 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
mech. 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: Huang Ying <ying.huang@intel.com>
---
arch/x86/kernel/e820.c | 4 ++--
drivers/acpi/Makefile | 3 ++-
drivers/acpi/nvs.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
include/linux/acpi.h | 20 ++++++++++++++------
4 files changed, 64 insertions(+), 10 deletions(-)
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -713,7 +713,7 @@ void __init e820_mark_nosave_regions(uns
}
#endif
-#ifdef CONFIG_HIBERNATION
+#ifdef CONFIG_ACPI
/**
* Mark ACPI NVS memory region, so that we can save/restore it during
* hibernation and the subsequent resume.
@@ -726,7 +726,7 @@ static int __init e820_mark_nvs_memory(v
struct e820entry *ei = &e820.map[i];
if (ei->type == E820_NVS)
- suspend_nvs_register(ei->addr, ei->size);
+ acpi_nvs_register(ei->addr, ei->size);
}
return 0;
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -20,11 +20,12 @@ obj-y += acpi.o \
# All the builtin files are in the "acpi." module_param namespace.
acpi-y += osl.o utils.o reboot.o
acpi-y += atomicio.o
+acpi-y += nvs.o
# sleep related files
acpi-y += wakeup.o
acpi-y += sleep.o
-acpi-$(CONFIG_ACPI_SLEEP) += proc.o nvs.o
+acpi-$(CONFIG_ACPI_SLEEP) += proc.o
#
--- a/drivers/acpi/nvs.c
+++ b/drivers/acpi/nvs.c
@@ -15,6 +15,50 @@
#include <linux/acpi_io.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(®ion->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)
+{
+ struct nvs_region *region;
+
+ list_for_each_entry(region, &nvs_region_list, node)
+ func(region->phys_start, region->size, data);
+}
+
+
+#ifdef CONFIG_ACPI_SLEEP
/*
* 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
@@ -41,7 +85,7 @@ static LIST_HEAD(nvs_list);
* 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)
+static int suspend_nvs_register(unsigned long start, unsigned long size)
{
struct nvs_page *entry, *next;
@@ -159,3 +203,4 @@ void suspend_nvs_restore(void)
if (entry->data)
memcpy(entry->kaddr, entry->data, entry->size);
}
+#endif
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -306,6 +306,11 @@ extern acpi_status acpi_pci_osc_control_
u32 *mask, u32 req);
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 */
#define acpi_disabled 1
@@ -348,15 +353,18 @@ static inline int acpi_table_parse(char
{
return -1;
}
-#endif /* !CONFIG_ACPI */
-#ifdef CONFIG_ACPI_SLEEP
-int suspend_nvs_register(unsigned long start, unsigned long size);
-#else
-static inline int suspend_nvs_register(unsigned long a, unsigned long b)
+static inline int acpi_nvs_register(__u64 start, __u64 size)
{
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*/
[-- Attachment #3: nvs_exclude.patch --]
[-- Type: text/x-patch, Size: 2521 bytes --]
Subject: [BUGFIX] ACPI, APEI, Resolve false conflict between ACPI NVS and APEI
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
mech. 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 excludes ACPI NVS regions when APEI components
request resources. So that they will not conflict with ACPI NVS
regions.
Reported-by: Pavel Ivanov <paivanof@gmail.com>
Signed-off-by: Huang Ying <ying.huang@intel.com>
---
drivers/acpi/apei/apei-base.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -449,8 +449,19 @@ int apei_resources_sub(struct apei_resou
}
EXPORT_SYMBOL_GPL(apei_resources_sub);
+static int apei_get_nvs_callback(__u64 start, __u64 size, void *data)
+{
+ struct apei_resources *resources = data;
+ return apei_res_add(&resources->iomem, start, size);
+}
+
+static int apei_get_nvs_resources(struct apei_resources *resources)
+{
+ return acpi_nvs_for_each_region(apei_get_nvs_callback, resources);
+}
+
/*
- * IO memory/port rersource management mechanism is used to check
+ * IO memory/port resource management mechanism is used to check
* whether memory/port area used by GARs conflicts with normal memory
* or IO memory/port of devices.
*/
@@ -459,12 +470,24 @@ int apei_resources_request(struct apei_r
{
struct apei_res *res, *res_bak = NULL;
struct resource *r;
+ struct apei_resources nvs_resources;
int rc;
rc = apei_resources_sub(resources, &apei_resources_all);
if (rc)
return rc;
+ /*
+ * Some firmware uses ACPI NVS region, that has been marked as
+ * busy, so exclude it from APEI resources to avoid false
+ * conflict.
+ */
+ apei_resources_init(&nvs_resources);
+ apei_get_nvs_resources(&nvs_resources);
+ rc = apei_resources_sub(resources, &nvs_resources);
+ if (rc)
+ goto res_fini;
+
rc = -EINVAL;
list_for_each_entry(res, &resources->iomem, list) {
r = request_mem_region(res->start, res->end - res->start,
@@ -511,6 +534,8 @@ err_unmap_iomem:
break;
release_mem_region(res->start, res->end - res->start);
}
+res_fini:
+ apei_resources_fini(&nvs_resources);
return rc;
}
EXPORT_SYMBOL_GPL(apei_resources_request);
next prev parent reply other threads:[~2011-08-22 7:12 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-08-17 3:43 APEI: Can not request iomem region for GARs Pavel Ivanov
2011-08-19 21:48 ` Bjorn Helgaas
2011-08-22 5:43 ` Huang Ying
2011-08-22 7:12 ` Huang Ying [this message]
2011-08-22 16:45 ` Bjorn Helgaas
2011-08-22 21:04 ` Yinghai Lu
2011-08-23 0:32 ` Huang Ying
2011-08-25 2:45 ` Pavel Ivanov
2011-08-26 4:13 ` Huang Ying
2011-08-26 13:43 ` Bjorn Helgaas
2011-08-29 1:27 ` Huang Ying
2011-08-29 14:48 ` Bjorn Helgaas
2011-08-30 0:57 ` Huang Ying
2011-08-27 3:28 ` Pavel Ivanov
2011-08-29 1:15 ` Huang Ying
2011-08-29 4:10 ` Pavel Ivanov
2011-08-29 5:22 ` Huang Ying
2011-08-29 14:43 ` Pavel Ivanov
2011-08-30 0:55 ` Huang Ying
2011-08-29 5:37 ` Huang Ying
2011-09-03 2:44 ` Pavel Ivanov
2011-09-05 2:05 ` Huang Ying
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4E520149.3010802@intel.com \
--to=ying.huang@intel.com \
--cc=bhelgaas@google.com \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=paivanof@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox