ACPI: APEI: Fix BERT resources conflict with ACPI NVS area
It was reported that on some machines, there is overlap between ACPI NVS area and BERT address range. This appears reasonable because BERT contents need to be non-volatile across reboot. But this will cause resources conflict in current Linux kernel implementation because the ACPI NVS area is marked as busy. The resource conflict is fixed via excluding the ACPI NVS area when requesting IO resources for BERT. When accessing the BERT contents, the whole BERT address range will be ioremapped and accessed. Reported-and-tested-by: Hans Kristian Rosbach <hansr@raskesider.no> Signed-off-by: Ying Huang <ying.huang@intel.com> Acked-by: Borislav Petkov <bp@suse.de> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
d222678426
commit
41139ac3cd
|
@ -97,6 +97,7 @@ static int __init bert_check_table(struct acpi_table_bert *bert_tab)
|
|||
|
||||
static int __init bert_init(void)
|
||||
{
|
||||
struct apei_resources bert_resources;
|
||||
struct acpi_bert_region *boot_error_region;
|
||||
struct acpi_table_bert *bert_tab;
|
||||
unsigned int region_len;
|
||||
|
@ -127,13 +128,14 @@ static int __init bert_init(void)
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
apei_resources_init(&bert_resources);
|
||||
rc = apei_resources_add(&bert_resources, bert_tab->address,
|
||||
region_len, true);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = apei_resources_request(&bert_resources, "APEI BERT");
|
||||
if (rc)
|
||||
goto out_fini;
|
||||
boot_error_region = ioremap_cache(bert_tab->address, region_len);
|
||||
if (boot_error_region) {
|
||||
bert_print_all(boot_error_region, region_len);
|
||||
|
@ -142,7 +144,9 @@ static int __init bert_init(void)
|
|||
rc = -ENOMEM;
|
||||
}
|
||||
|
||||
release_mem_region(bert_tab->address, region_len);
|
||||
apei_resources_release(&bert_resources);
|
||||
out_fini:
|
||||
apei_resources_fini(&bert_resources);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue