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

ghes: add the needed hooks for EDAC error report

In order to allow reporting errors via EDAC, add hooks for:

1) register an EDAC driver;
2) unregister an EDAC driver;
3) report errors via EDAC.

As the EDAC driver will need to access the ghes structure, adds it
as one of the parameters for ghes_do_proc.

Acked-by: Huang Ying <ying.huang@intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

+46 -5
+19 -5
drivers/acpi/apei/ghes.c
··· 409 409 ghes->flags &= ~GHES_TO_CLEAR; 410 410 } 411 411 412 - static void ghes_do_proc(const struct acpi_hest_generic_status *estatus) 412 + static void ghes_do_proc(struct ghes *ghes, 413 + const struct acpi_hest_generic_status *estatus) 413 414 { 414 415 int sev, sec_sev; 415 416 struct acpi_hest_generic_data *gdata; ··· 422 421 CPER_SEC_PLATFORM_MEM)) { 423 422 struct cper_sec_mem_err *mem_err; 424 423 mem_err = (struct cper_sec_mem_err *)(gdata+1); 424 + ghes_edac_report_mem_error(ghes, sev, mem_err); 425 + 425 426 #ifdef CONFIG_X86_MCE 426 427 apei_mce_report_mem_error(sev == GHES_SEV_CORRECTED, 427 428 mem_err); ··· 642 639 if (ghes_print_estatus(NULL, ghes->generic, ghes->estatus)) 643 640 ghes_estatus_cache_add(ghes->generic, ghes->estatus); 644 641 } 645 - ghes_do_proc(ghes->estatus); 642 + ghes_do_proc(ghes, ghes->estatus); 646 643 out: 647 644 ghes_clear_estatus(ghes); 648 645 return 0; ··· 735 732 estatus = GHES_ESTATUS_FROM_NODE(estatus_node); 736 733 len = apei_estatus_len(estatus); 737 734 node_len = GHES_ESTATUS_NODE_LEN(len); 738 - ghes_do_proc(estatus); 735 + ghes_do_proc(estatus_node->ghes, estatus); 739 736 if (!ghes_estatus_cached(estatus)) { 740 737 generic = estatus_node->generic; 741 738 if (ghes_print_estatus(NULL, generic, estatus)) ··· 824 821 estatus_node = (void *)gen_pool_alloc(ghes_estatus_pool, 825 822 node_len); 826 823 if (estatus_node) { 824 + estatus_node->ghes = ghes; 827 825 estatus_node->generic = ghes->generic; 828 826 estatus = GHES_ESTATUS_FROM_NODE(estatus_node); 829 827 memcpy(estatus, ghes->estatus, len); ··· 903 899 ghes = NULL; 904 900 goto err; 905 901 } 902 + 903 + rc = ghes_edac_register(ghes, &ghes_dev->dev); 904 + if (rc < 0) 905 + goto err; 906 + 906 907 switch (generic->notify.type) { 907 908 case ACPI_HEST_NOTIFY_POLLED: 908 909 ghes->timer.function = ghes_poll_func; ··· 920 911 if (acpi_gsi_to_irq(generic->notify.vector, &ghes->irq)) { 921 912 pr_err(GHES_PFX "Failed to map GSI to IRQ for generic hardware error source: %d\n", 922 913 generic->header.source_id); 923 - goto err; 914 + goto err_edac_unreg; 924 915 } 925 916 if (request_irq(ghes->irq, ghes_irq_func, 926 917 0, "GHES IRQ", ghes)) { 927 918 pr_err(GHES_PFX "Failed to register IRQ for generic hardware error source: %d\n", 928 919 generic->header.source_id); 929 - goto err; 920 + goto err_edac_unreg; 930 921 } 931 922 break; 932 923 case ACPI_HEST_NOTIFY_SCI: ··· 952 943 platform_set_drvdata(ghes_dev, ghes); 953 944 954 945 return 0; 946 + err_edac_unreg: 947 + ghes_edac_unregister(ghes); 955 948 err: 956 949 if (ghes) { 957 950 ghes_fini(ghes); ··· 1006 995 } 1007 996 1008 997 ghes_fini(ghes); 998 + 999 + ghes_edac_unregister(ghes); 1000 + 1009 1001 kfree(ghes); 1010 1002 1011 1003 platform_set_drvdata(ghes_dev, NULL);
+27
include/acpi/ghes.h
··· 27 27 struct ghes_estatus_node { 28 28 struct llist_node llnode; 29 29 struct acpi_hest_generic *generic; 30 + struct ghes *ghes; 30 31 }; 31 32 32 33 struct ghes_estatus_cache { ··· 44 43 GHES_SEV_RECOVERABLE = 0x2, 45 44 GHES_SEV_PANIC = 0x3, 46 45 }; 46 + 47 + /* From drivers/edac/ghes_edac.c */ 48 + 49 + #ifdef CONFIG_EDAC_GHES 50 + void ghes_edac_report_mem_error(struct ghes *ghes, int sev, 51 + struct cper_sec_mem_err *mem_err); 52 + 53 + int ghes_edac_register(struct ghes *ghes, struct device *dev); 54 + 55 + void ghes_edac_unregister(struct ghes *ghes); 56 + 57 + #else 58 + static inline void ghes_edac_report_mem_error(struct ghes *ghes, int sev, 59 + struct cper_sec_mem_err *mem_err) 60 + { 61 + } 62 + 63 + static inline int ghes_edac_register(struct ghes *ghes, struct device *dev) 64 + { 65 + return 0; 66 + } 67 + 68 + static inline void ghes_edac_unregister(struct ghes *ghes) 69 + { 70 + } 71 + #endif