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

Merge branch 'x86-ras-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 RAS update from Ingo Molnar:
"The changes in this cycle were:

- allow mmcfg access to APEI error injection handlers

- improve MCE error messages

- smaller cleanups"

* 'x86-ras-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86, mce: Fix sparse errors
x86, mce: Improve timeout error messages
ACPI, EINJ: Enhance error injection tolerance level

+67 -16
+13 -10
arch/x86/kernel/cpu/mcheck/mce.c
··· 116 116 * CPU/chipset specific EDAC code can register a notifier call here to print 117 117 * MCE errors in a human-readable form. 118 118 */ 119 - ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain); 119 + static ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain); 120 120 121 121 /* Do initial initialization of a struct mce */ 122 122 void mce_setup(struct mce *m) ··· 312 312 panic("Panicing machine check CPU died"); 313 313 } 314 314 315 - static void mce_panic(char *msg, struct mce *final, char *exp) 315 + static void mce_panic(const char *msg, struct mce *final, char *exp) 316 316 { 317 317 int i, apei_err = 0; 318 318 ··· 530 530 schedule_work(this_cpu_ptr(&mce_work)); 531 531 } 532 532 533 - DEFINE_PER_CPU(struct irq_work, mce_irq_work); 533 + static DEFINE_PER_CPU(struct irq_work, mce_irq_work); 534 534 535 535 static void mce_irq_work_cb(struct irq_work *entry) 536 536 { ··· 736 736 /* 737 737 * Check if a timeout waiting for other CPUs happened. 738 738 */ 739 - static int mce_timed_out(u64 *t) 739 + static int mce_timed_out(u64 *t, const char *msg) 740 740 { 741 741 /* 742 742 * The others already did panic for some reason. ··· 751 751 goto out; 752 752 if ((s64)*t < SPINUNIT) { 753 753 if (mca_cfg.tolerant <= 1) 754 - mce_panic("Timeout synchronizing machine check over CPUs", 755 - NULL, NULL); 754 + mce_panic(msg, NULL, NULL); 756 755 cpu_missing = 1; 757 756 return 1; 758 757 } ··· 867 868 * Wait for everyone. 868 869 */ 869 870 while (atomic_read(&mce_callin) != cpus) { 870 - if (mce_timed_out(&timeout)) { 871 + if (mce_timed_out(&timeout, 872 + "Timeout: Not all CPUs entered broadcast exception handler")) { 871 873 atomic_set(&global_nwo, 0); 872 874 return -1; 873 875 } ··· 893 893 * only seen by one CPU before cleared, avoiding duplicates. 894 894 */ 895 895 while (atomic_read(&mce_executing) < order) { 896 - if (mce_timed_out(&timeout)) { 896 + if (mce_timed_out(&timeout, 897 + "Timeout: Subject CPUs unable to finish machine check processing")) { 897 898 atomic_set(&global_nwo, 0); 898 899 return -1; 899 900 } ··· 938 937 * loops. 939 938 */ 940 939 while (atomic_read(&mce_executing) <= cpus) { 941 - if (mce_timed_out(&timeout)) 940 + if (mce_timed_out(&timeout, 941 + "Timeout: Monarch CPU unable to finish machine check processing")) 942 942 goto reset; 943 943 ndelay(SPINUNIT); 944 944 } ··· 952 950 * Subject: Wait for Monarch to finish. 953 951 */ 954 952 while (atomic_read(&mce_executing) != 0) { 955 - if (mce_timed_out(&timeout)) 953 + if (mce_timed_out(&timeout, 954 + "Timeout: Monarch CPU did not finish machine check processing")) 956 955 goto reset; 957 956 ndelay(SPINUNIT); 958 957 }
+28
arch/x86/pci/mmconfig-shared.c
··· 610 610 return 0; 611 611 } 612 612 613 + #ifdef CONFIG_ACPI_APEI 614 + extern int (*arch_apei_filter_addr)(int (*func)(__u64 start, __u64 size, 615 + void *data), void *data); 616 + 617 + static int pci_mmcfg_for_each_region(int (*func)(__u64 start, __u64 size, 618 + void *data), void *data) 619 + { 620 + struct pci_mmcfg_region *cfg; 621 + int rc; 622 + 623 + if (list_empty(&pci_mmcfg_list)) 624 + return 0; 625 + 626 + list_for_each_entry(cfg, &pci_mmcfg_list, list) { 627 + rc = func(cfg->res.start, resource_size(&cfg->res), data); 628 + if (rc) 629 + return rc; 630 + } 631 + 632 + return 0; 633 + } 634 + #define set_apei_filter() (arch_apei_filter_addr = pci_mmcfg_for_each_region) 635 + #else 636 + #define set_apei_filter() 637 + #endif 638 + 613 639 static void __init __pci_mmcfg_init(int early) 614 640 { 615 641 pci_mmcfg_reject_broken(early); ··· 670 644 else 671 645 acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); 672 646 __pci_mmcfg_init(1); 647 + 648 + set_apei_filter(); 673 649 } 674 650 } 675 651
+26 -6
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) 452 + static int apei_get_res_callback(__u64 start, __u64 size, void *data) 453 453 { 454 454 struct apei_resources *resources = data; 455 455 return apei_res_add(&resources->iomem, start, size); ··· 457 457 458 458 static int apei_get_nvs_resources(struct apei_resources *resources) 459 459 { 460 - return acpi_nvs_for_each_region(apei_get_nvs_callback, resources); 460 + return acpi_nvs_for_each_region(apei_get_res_callback, resources); 461 + } 462 + 463 + int (*arch_apei_filter_addr)(int (*func)(__u64 start, __u64 size, 464 + void *data), void *data); 465 + static int apei_get_arch_resources(struct apei_resources *resources) 466 + 467 + { 468 + return arch_apei_filter_addr(apei_get_res_callback, resources); 461 469 } 462 470 463 471 /* ··· 478 470 { 479 471 struct apei_res *res, *res_bak = NULL; 480 472 struct resource *r; 481 - struct apei_resources nvs_resources; 473 + struct apei_resources nvs_resources, arch_res; 482 474 int rc; 483 475 484 476 rc = apei_resources_sub(resources, &apei_resources_all); ··· 493 485 apei_resources_init(&nvs_resources); 494 486 rc = apei_get_nvs_resources(&nvs_resources); 495 487 if (rc) 496 - goto res_fini; 488 + goto nvs_res_fini; 497 489 rc = apei_resources_sub(resources, &nvs_resources); 498 490 if (rc) 499 - goto res_fini; 491 + goto nvs_res_fini; 492 + 493 + if (arch_apei_filter_addr) { 494 + apei_resources_init(&arch_res); 495 + rc = apei_get_arch_resources(&arch_res); 496 + if (rc) 497 + goto arch_res_fini; 498 + rc = apei_resources_sub(resources, &arch_res); 499 + if (rc) 500 + goto arch_res_fini; 501 + } 500 502 501 503 rc = -EINVAL; 502 504 list_for_each_entry(res, &resources->iomem, list) { ··· 554 536 break; 555 537 release_mem_region(res->start, res->end - res->start); 556 538 } 557 - res_fini: 539 + arch_res_fini: 540 + apei_resources_fini(&arch_res); 541 + nvs_res_fini: 558 542 apei_resources_fini(&nvs_resources); 559 543 return rc; 560 544 }