Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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-and-tested-by: Pavel Ivanov <paivanof@gmail.com>
Signed-off-by: Huang Ying <ying.huang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>

authored by

Huang Ying and committed by
Len Brown
4134b8c8 b54ac6d2

+28 -1
+28 -1
drivers/acpi/apei/apei-base.c
··· 449 449 } 450 450 EXPORT_SYMBOL_GPL(apei_resources_sub); 451 451 452 + static int apei_get_nvs_callback(__u64 start, __u64 size, void *data) 453 + { 454 + struct apei_resources *resources = data; 455 + return apei_res_add(&resources->iomem, start, size); 456 + } 457 + 458 + static int apei_get_nvs_resources(struct apei_resources *resources) 459 + { 460 + return acpi_nvs_for_each_region(apei_get_nvs_callback, resources); 461 + } 462 + 452 463 /* 453 - * IO memory/port rersource management mechanism is used to check 464 + * IO memory/port resource management mechanism is used to check 454 465 * whether memory/port area used by GARs conflicts with normal memory 455 466 * or IO memory/port of devices. 456 467 */ ··· 470 459 { 471 460 struct apei_res *res, *res_bak = NULL; 472 461 struct resource *r; 462 + struct apei_resources nvs_resources; 473 463 int rc; 474 464 475 465 rc = apei_resources_sub(resources, &apei_resources_all); 476 466 if (rc) 477 467 return rc; 468 + 469 + /* 470 + * Some firmware uses ACPI NVS region, that has been marked as 471 + * busy, so exclude it from APEI resources to avoid false 472 + * conflict. 473 + */ 474 + apei_resources_init(&nvs_resources); 475 + rc = apei_get_nvs_resources(&nvs_resources); 476 + if (rc) 477 + goto res_fini; 478 + rc = apei_resources_sub(resources, &nvs_resources); 479 + if (rc) 480 + goto res_fini; 478 481 479 482 rc = -EINVAL; 480 483 list_for_each_entry(res, &resources->iomem, list) { ··· 536 511 break; 537 512 release_mem_region(res->start, res->end - res->start); 538 513 } 514 + res_fini: 515 + apei_resources_fini(&nvs_resources); 539 516 return rc; 540 517 } 541 518 EXPORT_SYMBOL_GPL(apei_resources_request);