Add in several tests that extend the testing done on the RSDP. If these
tests are all passed, the RSDP being examined should be compliant with
the ACPI 6.0 spec.
As part of that, when creating a dummy RSDP to substitute for one that
cannot be read or found, use either RsdtAddress or XsdtAddress as described
in the spec. For non-arm64, either can be used, but for arm64, only the
XsdtAddress is to be used.
Finally, update the regression tests for RSDP.
Al Stone (5):
RSDP: minor cleanups to rsdp.c for checkpatch issues
utilities: add a helper function for printing out architecture names
ACPI tables: when bodging up an RSDP, do the right thing for the arch
ACPI RSDP: flesh out the tests to check for full spec compliance.
Update regression test rsdp-0001/test-0001.sh
fwts-test/rsdp-0001/rsdp.log | 16 ++++-
src/acpi/rsdp/rsdp.c | 139 ++++++++++++++++++++++++++++++++++++-----
src/lib/include/fwts_arch.h | 1 +
src/lib/src/fwts_acpi_tables.c | 19 +++---
src/lib/src/fwts_arch.c | 18 ++++++
5 files changed, 169 insertions(+), 24 deletions(-)
--
2.5.0
I should have added these earlier, but I did not. So, here
they are: the updates to the regression tests affected by
adding the --arch parameter, and by updating the MADT tests.
Al Stone (7):
Update the regression test arg-help-0001/test-0001.sh
Update regression test for arg-help-0001/test-0002.sh
Update regression test for arg-show-tests-0001/test-0001.sh
Update regression test arg-show-tests-full-0001/test-0001.sh
Update the regression test arg-table-path-0001/test-0001.sh
Update the regression test madt-0001/test-0001.sh
Update the regression test madt-0001/test-0002.sh
fwts-test/arg-help-0001/arg-help-0001.log | 4 +
fwts-test/arg-help-0001/arg-help-0002.log | 4 +
.../arg-show-tests-0001/arg-show-tests-0001.log | 8 +-
.../arg-show-tests-full-0001.log | 26 +-
fwts-test/arg-table-path-0001/acpidump-0001.log | 741 +++++++++------------
fwts-test/madt-0001/madt-0001.log | 10 +-
fwts-test/madt-0001/madt-0002.log | 33 +-
7 files changed, 344 insertions(+), 482 deletions(-)
--
2.5.0
This patch series adds in specific ACPI compliance testing for the MADT
and all of its various subtables (16, currently).
The first three patches add in the idea of host and target architectures --
host being the arch that FWTS is running on, and target the arch whose
firmware is being tested. This is needed later in the MADT tests since what
is proper changes based on the architecture the firmware supports.
The fourth patch adds the detailed tests for the MADT and all but one of the
subtables currently defined in ACPI 6.0. The last two patches add in the
relatively new GIC ITS subtable and compliance tests for it.
There are still multiple TODOs in the compliance checks; these will be
added as clarification of the spec becomes available.
Changes for v3:
-- Add in support for the --arch=<name> parameter to specify the arch
for the target firmware (default is that host == target).
-- Add in the fwts_architecture typedef plus some helper functions so that
tests in the future can adapt their behavior as needed, and so that the
MADT tests can set themselves up properly.
-- Instead of creating a new sourc file src/acpi/compliance/madt.c, replace
the existing src/acpi/madt/madt.c tests since we're providing a superset.
-- Various minor style and syntax corrections (from Ian Colin King)
Changes for v2:
-- Clean up the white space problems
-- Fix errors found by checkpatch (minor syntax things)
-- Fix one logic error: while MADT and FADT table revisions *should* be
in sync, they seldom are, so report this as a test failure and continue
to test as much as possible instead of aborting completely, in some of
those cases.
Al Stone (6):
Start defining FWTS architectures as variables
Define some utility functions for using the fwts_architecture enum
Add mechanism to tell FWTS what architecture is being tested
ACPI: MADT: add in compliance tests for the MADT and subtables
ACPI: Add in MADT subtable description for GIC ITS subtable
ACPI: MADT: add in compliance checks for the GIC ITS subtable
src/acpi/madt/madt.c | 1551 +++++++++++++++++++++++++++++++-------
src/lib/include/fwts.h | 1 +
src/lib/include/fwts_acpi.h | 10 +
src/lib/include/fwts_arch.h | 41 +
src/lib/include/fwts_framework.h | 3 +
src/lib/src/Makefile.am | 1 +
src/lib/src/fwts_arch.c | 88 +++
src/lib/src/fwts_framework.c | 25 +
8 files changed, 1460 insertions(+), 260 deletions(-)
create mode 100644 src/lib/include/fwts_arch.h
create mode 100644 src/lib/src/fwts_arch.c
--
2.5.0
This series introduces changes to reduce the time required to send a frequency
transition requests to the platform while using the cppc-cpufreq driver.
With these changes we see significant improvement in the average time to send
freq. transition request to the platform. Profiling on an ARM platform showed
that the average transaction time per request reduced from 200us to under 20us.
Ashwin Chaugule (1):
ACPI / CPPC: Optimize PCC Read Write operations
Prashanth Prakash (3):
acpi: cppc: optimized cpc_read and cpc_write
mailbox: pcc: optimized pcc_send_data
acpi: cppc: replace writeX/readX to PCC with relaxed version
drivers/acpi/cppc_acpi.c | 184 +++++++++++++++++++++++++++++++++++------------
drivers/mailbox/pcc.c | 110 ++++++++++++++++++++++++++--
2 files changed, 241 insertions(+), 53 deletions(-)
--
Qualcomm Technologies, Inc. on behalf
of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc.
is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
Update the fwts man page to include some new parameters.
Al Stone (2):
Documentation: add --acpicompliance to man page
Documentation: add --arch to the man page
doc/fwts.1 | 11 +++++++++++
1 file changed, 11 insertions(+)
--
2.5.0
From: Huang Ying <ying.huang(a)intel.com>
ACPI/APEI is designed to verifiy/report H/W errors, like Corrected
Error(CE) and Uncorrected Error(UC). It contains four tables: HEST,
ERST, EINJ and BERT. The first three tables have been merged for
a long time, but because of lacking BIOS support for BERT, the
support for BERT is pending until now. Recently on ARM 64 platform
it is has been supported. So here we come.
Under normal circumstances, when a hardware error occurs, kernel will
be notified via NMI, MCE or some other method, then kernel will
process the error condition, report it, and recover it if possible.
But sometime, the situation is so bad, so that firmware may choose to
reset directly without notifying Linux kernel.
Linux kernel can use the Boot Error Record Table (BERT) to get the
un-notified hardware errors that occurred in a previous boot. In this
patch, the error information is reported via printk.
For more information about BERT, please refer to ACPI Specification
version 6.0, section 18.3.1:
http://www.uefi.org/sites/default/files/resources/ACPI_6.0.pdf
The following log is a BERT record after system reboot because of hitting
a fatal memory error:
BERT: Error records from previous boot:
[Hardware Error]: It has been corrected by h/w and requires no further action
[Hardware Error]: event severity: corrected
[Hardware Error]: Error 0, type: recoverable
[Hardware Error]: section_type: memory error
[Hardware Error]: error_status: 0x0000000000000400
[Hardware Error]: physical_address: 0xffffffffffffffff
[Hardware Error]: card: 1 module: 2 bank: 3 row: 1 column: 2 bit_position: 5
[Hardware Error]: error_type: 2, single-bit ECC
[Tomasz Nowicki: Clear error status at the end of error handling]
[Tony: Applied some cleanups suggested by Fu Wei]
[Fu Wei: delete EXPORT_SYMBOL_GPL(bert_disable), improve the code]
Signed-off-by: Huang Ying <ying.huang(a)intel.com>
Signed-off-by: Tomasz Nowicki <tomasz.nowicki(a)linaro.org>
Signed-off-by: Chen, Gong <gong.chen(a)linux.intel.com>
Tested-by: Jonathan (Zhixiong) Zhang <zjzhang(a)codeaurora.org>
Signed-off-by: Tony Luck <tony.luck(a)intel.com>
Signed-off-by: Fu Wei <fu.wei(a)linaro.org>
Tested-by: Tyler Baicar <tbaicar(a)codeaurora.org>
---
Changelog:
v5: Drop some superfluous comments.
Use the introduce of BERT in ACPI Specification instead of original one
at the head of bert.c.
Fix typo in apei-internal.h
Simplify the introduce of bert_disable.
v4: https://lkml.org/lkml/2016/1/8/382
Fix the "#undef" bug
Improve the instruction of "bert_disable",
Delete the useless declaration in include/acpi/apei.h.
v3: https://lkml.org/lkml/2016/1/7/214
Merge the two patches
Do some improvements according to Borislav's suggestion.
v2: https://lkml.org/lkml/2015/8/18/336
Delete EXPORT_SYMBOL_GPL(bert_disable), because "bert_disable" is only
used in bert.c for now.
Do some code-style cleanups.
v1: The first upstream version submitted in linux-acpi mailing list:
http://www.spinics.net/lists/linux-acpi/msg57384.html
Documentation/kernel-parameters.txt | 3 +
drivers/acpi/apei/Makefile | 2 +-
drivers/acpi/apei/apei-internal.h | 2 +-
drivers/acpi/apei/bert.c | 150 ++++++++++++++++++++++++++++++++++++
4 files changed, 155 insertions(+), 2 deletions(-)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 3ea869d..acb772e 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -564,6 +564,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
bootmem_debug [KNL] Enable bootmem allocator debug messages.
+ bert_disable [ACPI]
+ Disable BERT OS support on buggy BIOSes.
+
bttv.card= [HW,V4L] bttv (bt848 + bt878 based grabber cards)
bttv.radio= Most important insmod options are available as
kernel args too.
diff --git a/drivers/acpi/apei/Makefile b/drivers/acpi/apei/Makefile
index 5d575a9..e50573d 100644
--- a/drivers/acpi/apei/Makefile
+++ b/drivers/acpi/apei/Makefile
@@ -3,4 +3,4 @@ obj-$(CONFIG_ACPI_APEI_GHES) += ghes.o
obj-$(CONFIG_ACPI_APEI_EINJ) += einj.o
obj-$(CONFIG_ACPI_APEI_ERST_DEBUG) += erst-dbg.o
-apei-y := apei-base.o hest.o erst.o
+apei-y := apei-base.o hest.o erst.o bert.o
diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h
index 16129c7..6e9f14c 100644
--- a/drivers/acpi/apei/apei-internal.h
+++ b/drivers/acpi/apei/apei-internal.h
@@ -1,6 +1,6 @@
/*
* apei-internal.h - ACPI Platform Error Interface internal
- * definations.
+ * definitions.
*/
#ifndef APEI_INTERNAL_H
diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c
new file mode 100644
index 0000000..a05b5c0
--- /dev/null
+++ b/drivers/acpi/apei/bert.c
@@ -0,0 +1,150 @@
+/*
+ * APEI Boot Error Record Table (BERT) support
+ *
+ * Copyright 2011 Intel Corp.
+ * Author: Huang Ying <ying.huang(a)intel.com>
+ *
+ * Under normal circumstances, when a hardware error occurs, the error
+ * handler receives control and processes the error. This gives OSPM a
+ * chance to process the error condition, report it, and optionally attempt
+ * recovery. In some cases, the system is unable to process an error.
+ * For example, system firmware or a management controller may choose to
+ * reset the system or the system might experience an uncontrolled crash
+ * or reset.The boot error source is used to report unhandled errors that
+ * occurred in a previous boot. This mechanism is described in the BERT
+ * table.
+ *
+ * For more information about BERT, please refer to ACPI Specification
+ * version 4.0, section 17.3.1
+ *
+ * This file is licensed under GPLv2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/io.h>
+
+#include "apei-internal.h"
+
+#undef pr_fmt
+#define pr_fmt(fmt) "BERT: " fmt
+
+static int bert_disable;
+
+static void __init bert_print_all(struct acpi_bert_region *region,
+ unsigned int region_len)
+{
+ struct acpi_hest_generic_status *estatus =
+ (struct acpi_hest_generic_status *)region;
+ int remain = region_len;
+ u32 estatus_len;
+
+ if (!estatus->block_status)
+ return;
+
+ while (remain > sizeof(struct acpi_bert_region)) {
+ if (cper_estatus_check(estatus)) {
+ pr_err(FW_BUG "Invalid error record.\n");
+ return;
+ }
+
+ estatus_len = cper_estatus_len(estatus);
+ if (remain < estatus_len) {
+ pr_err(FW_BUG "Truncated status block (length: %u).\n",
+ estatus_len);
+ return;
+ }
+
+ pr_info_once("Error records from previous boot:\n");
+
+ cper_estatus_print(KERN_INFO HW_ERR, estatus);
+
+ /*
+ * Because the boot error source is "one-time polled" type,
+ * clear Block Status of current Generic Error Status Block,
+ * once it's printed.
+ */
+ estatus->block_status = 0;
+
+ estatus = (void *)estatus + estatus_len;
+ /* No more error records. */
+ if (!estatus->block_status)
+ return;
+
+ remain -= estatus_len;
+ }
+}
+
+static int __init setup_bert_disable(char *str)
+{
+ bert_disable = 1;
+
+ return 0;
+}
+__setup("bert_disable", setup_bert_disable);
+
+static int __init bert_check_table(struct acpi_table_bert *bert_tab)
+{
+ if (bert_tab->header.length < sizeof(struct acpi_table_bert) ||
+ bert_tab->region_length < sizeof(struct acpi_bert_region))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int __init bert_init(void)
+{
+ struct acpi_bert_region *boot_error_region;
+ struct acpi_table_bert *bert_tab;
+ unsigned int region_len;
+ acpi_status status;
+ int rc = 0;
+
+ if (acpi_disabled)
+ return 0;
+
+ if (bert_disable) {
+ pr_info("Boot Error Record Table support is disabled.\n");
+ return 0;
+ }
+
+ status = acpi_get_table(ACPI_SIG_BERT, 0, (struct acpi_table_header **)&bert_tab);
+ if (status == AE_NOT_FOUND)
+ return 0;
+
+ if (ACPI_FAILURE(status)) {
+ pr_err("get table failed, %s.\n", acpi_format_exception(status));
+ return -EINVAL;
+ }
+
+ rc = bert_check_table(bert_tab);
+ if (rc) {
+ pr_err(FW_BUG "table invalid.\n");
+ return rc;
+ }
+
+ region_len = bert_tab->region_length;
+ if (!request_mem_region(bert_tab->address, region_len, "APEI BERT")) {
+ pr_err("Can't request iomem region <%016llx-%016llx>.\n",
+ (unsigned long long)bert_tab->address,
+ (unsigned long long)bert_tab->address + region_len - 1);
+ return -EIO;
+ }
+
+ boot_error_region = ioremap_cache(bert_tab->address, region_len);
+ if (boot_error_region) {
+ bert_print_all(boot_error_region, region_len);
+ iounmap(boot_error_region);
+ } else {
+ rc = -ENOMEM;
+ }
+
+ release_mem_region(bert_tab->address, region_len);
+
+ return rc;
+}
+
+late_initcall(bert_init);
--
2.5.0
From: Huang Ying <ying.huang(a)intel.com>
ACPI/APEI is designed to verifiy/report H/W errors, like Corrected
Error(CE) and Uncorrected Error(UC). It contains four tables: HEST,
ERST, EINJ and BERT. The first three tables have been merged for
a long time, but because of lacking BIOS support for BERT, the
support for BERT is pending until now. Recently on ARM 64 platform
it is has been supported. So here we come.
Under normal circumstances, when a hardware error occurs, kernel will
be notified via NMI, MCE or some other method, then kernel will
process the error condition, report it, and recover it if possible.
But sometime, the situation is so bad, so that firmware may choose to
reset directly without notifying Linux kernel.
Linux kernel can use the Boot Error Record Table (BERT) to get the
un-notified hardware errors that occurred in a previous boot. In this
patch, the error information is reported via printk.
For more information about BERT, please refer to ACPI Specification
version 6.0, section 18.3.1:
http://www.uefi.org/sites/default/files/resources/ACPI_6.0.pdf
The following log is a BERT record after system reboot because of hitting
a fatal memory error:
BERT: Error records from previous boot:
[Hardware Error]: It has been corrected by h/w and requires no further action
[Hardware Error]: event severity: corrected
[Hardware Error]: Error 0, type: recoverable
[Hardware Error]: section_type: memory error
[Hardware Error]: error_status: 0x0000000000000400
[Hardware Error]: physical_address: 0xffffffffffffffff
[Hardware Error]: card: 1 module: 2 bank: 3 row: 1 column: 2 bit_position: 5
[Hardware Error]: error_type: 2, single-bit ECC
[Tomasz Nowicki: Clear error status at the end of error handling]
[Tony: Applied some cleanups suggested by Fu Wei]
[Fu Wei: delete EXPORT_SYMBOL_GPL(bert_disable), improve the code]
Signed-off-by: Huang Ying <ying.huang(a)intel.com>
Signed-off-by: Tomasz Nowicki <tomasz.nowicki(a)linaro.org>
Signed-off-by: Chen, Gong <gong.chen(a)linux.intel.com>
Tested-by: Jonathan (Zhixiong) Zhang <zjzhang(a)codeaurora.org>
Signed-off-by: Tony Luck <tony.luck(a)intel.com>
Signed-off-by: Fu Wei <fu.wei(a)linaro.org>
Tested-by: Tyler Baicar <tbaicar(a)codeaurora.org>
---
Changelog:
v4: fix the "#undef" bug
Improve the instruction of "bert_disable",
delete the useless declaration in include/acpi/apei.h.
v3: https://lkml.org/lkml/2016/1/7/214
Merge the two patches
Do some improvements according to Borislav's suggestion.
v2: https://lkml.org/lkml/2015/8/18/336
Delete EXPORT_SYMBOL_GPL(bert_disable), because "bert_disable" is only
used in bert.c for now.
Do some code-style cleanups.
v1: The first upstream version submitted in linux-acpi mailing list:
http://www.spinics.net/lists/linux-acpi/msg57384.html
Documentation/kernel-parameters.txt | 6 ++
drivers/acpi/apei/Makefile | 2 +-
drivers/acpi/apei/bert.c | 158 ++++++++++++++++++++++++++++++++++++
include/acpi/apei.h | 1 +
4 files changed, 166 insertions(+), 1 deletion(-)
create mode 100644 drivers/acpi/apei/bert.c
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 742f69d..2c527a9 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -555,6 +555,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
bootmem_debug [KNL] Enable bootmem allocator debug messages.
+ bert_disable [ACPI]
+ Disable Boot Error Record Table (BERT) support.
+ Use this if to workaround buggy firmware which produces
+ the malformed BERT table or incorrect error status
+ block.
+
bttv.card= [HW,V4L] bttv (bt848 + bt878 based grabber cards)
bttv.radio= Most important insmod options are available as
kernel args too.
diff --git a/drivers/acpi/apei/Makefile b/drivers/acpi/apei/Makefile
index 5d575a9..e50573d 100644
--- a/drivers/acpi/apei/Makefile
+++ b/drivers/acpi/apei/Makefile
@@ -3,4 +3,4 @@ obj-$(CONFIG_ACPI_APEI_GHES) += ghes.o
obj-$(CONFIG_ACPI_APEI_EINJ) += einj.o
obj-$(CONFIG_ACPI_APEI_ERST_DEBUG) += erst-dbg.o
-apei-y := apei-base.o hest.o erst.o
+apei-y := apei-base.o hest.o erst.o bert.o
diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c
new file mode 100644
index 0000000..ffcbf4b
--- /dev/null
+++ b/drivers/acpi/apei/bert.c
@@ -0,0 +1,158 @@
+/*
+ * APEI Boot Error Record Table (BERT) support
+ *
+ * Copyright 2011 Intel Corp.
+ * Author: Huang Ying <ying.huang(a)intel.com>
+ *
+ * Under normal circumstances, when a hardware error occurs, kernel
+ * will be notified via NMI, MCE or some other method, then kernel
+ * will process the error condition, report it, and recover it if
+ * possible. But sometime, the situation is so bad, so that firmware
+ * may choose to reset directly without notifying Linux kernel.
+ *
+ * Linux kernel can use the Boot Error Record Table (BERT) to get the
+ * un-notified hardware errors that occurred in a previous boot.
+ *
+ * For more information about BERT, please refer to ACPI Specification
+ * version 4.0, section 17.3.1
+ *
+ * This file is licensed under GPLv2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/io.h>
+
+#include "apei-internal.h"
+
+#undef pr_fmt
+#define pr_fmt(fmt) "BERT: " fmt
+
+static int bert_disable;
+
+static void __init bert_print_all(struct acpi_bert_region *region,
+ unsigned int region_len)
+{
+ /*
+ * We use cper_estatus_* which uses struct acpi_hest_generic_status,
+ * struct acpi_hest_generic_status and acpi_bert_region are the same
+ * (Generic Error Status Block), so we declare the "estatus" here.
+ */
+ struct acpi_hest_generic_status *estatus =
+ (struct acpi_hest_generic_status *)region;
+ int remain = region_len;
+ u32 estatus_len;
+
+ /* The records have been polled*/
+ if (!estatus->block_status)
+ return;
+
+ while (remain > sizeof(struct acpi_bert_region)) {
+ /*
+ * Test Generic Error Status Block first,
+ * if the data(Offset, Length) is invalid, we just return,
+ * because we can't trust the length data from this block.
+ */
+ if (cper_estatus_check(estatus)) {
+ pr_err(FW_BUG "Invalid error record\n");
+ return;
+ }
+
+ estatus_len = cper_estatus_len(estatus);
+ if (remain < estatus_len) {
+ pr_err(FW_BUG "Invalid status block length (%u)\n",
+ estatus_len);
+ return;
+ }
+
+ pr_info_once("Error records from previous boot:\n");
+
+ cper_estatus_print(KERN_INFO HW_ERR, estatus);
+
+ /*
+ * Because the boot error source is "one-time polled" type,
+ * clear Block Status of current Generic Error Status Block,
+ * once it's printed.
+ */
+ estatus->block_status = 0;
+
+ estatus = (void *)estatus + estatus_len;
+ if (!estatus->block_status)
+ return; /* No more error records */
+
+ remain -= estatus_len;
+ }
+}
+
+static int __init setup_bert_disable(char *str)
+{
+ bert_disable = 1;
+
+ return 0;
+}
+__setup("bert_disable", setup_bert_disable);
+
+static int __init bert_check_table(struct acpi_table_bert *bert_tab)
+{
+ if (bert_tab->header.length < sizeof(struct acpi_table_bert) ||
+ bert_tab->region_length < sizeof(struct acpi_bert_region))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int __init bert_init(void)
+{
+ struct acpi_bert_region *boot_error_region;
+ struct acpi_table_bert *bert_tab;
+ unsigned int region_len;
+ acpi_status status;
+ int rc = 0;
+
+ if (acpi_disabled)
+ return 0;
+
+ if (bert_disable) {
+ pr_info("Boot Error Record Table support is disabled\n");
+ return 0;
+ }
+
+ status = acpi_get_table(ACPI_SIG_BERT, 0, (struct acpi_table_header **)&bert_tab);
+ if (status == AE_NOT_FOUND)
+ return 0;
+ if (ACPI_FAILURE(status)) {
+ pr_err("get table failed, %s\n", acpi_format_exception(status));
+ return -EINVAL;
+ }
+
+ rc = bert_check_table(bert_tab);
+ if (rc) {
+ pr_err(FW_BUG "table invalid\n");
+ return rc;
+ }
+
+ region_len = bert_tab->region_length;
+ if (!request_mem_region(bert_tab->address, region_len, "APEI BERT")) {
+ pr_err("Can't request iomem region <%016llx-%016llx>\n",
+ (unsigned long long)bert_tab->address,
+ (unsigned long long)bert_tab->address + region_len - 1);
+ return -EIO;
+ }
+
+ boot_error_region = ioremap_cache(bert_tab->address, region_len);
+ if (boot_error_region) {
+ bert_print_all(boot_error_region, region_len);
+ iounmap(boot_error_region);
+ } else {
+ rc = -ENOMEM;
+ }
+
+ release_mem_region(bert_tab->address, region_len);
+
+ return rc;
+}
+
+late_initcall(bert_init);
--
2.5.0