From 8e40612f6146da1333e9bb5cfd9af7511c063d93 Mon Sep 17 00:00:00 2001 From: Jia He Date: Mon, 10 Oct 2022 02:35:54 +0000 Subject: EDAC/ghes: Add a notifier for reporting memory errors In order to make it a proper module and disentangle it from facilities, add a notifier for reporting memory errors. Use an atomic notifier because calls sites like ghes_proc_in_irq() run in interrupt context. [ bp: Massage commit message. ] Suggested-by: Borislav Petkov Signed-off-by: Jia He Signed-off-by: Borislav Petkov Link: https://lore.kernel.org/r/20221010023559.69655-3-justin.he@arm.com --- drivers/edac/ghes_edac.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers/edac') diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c index c8fa7dcfdbd0..7b8d56a769f6 100644 --- a/drivers/edac/ghes_edac.c +++ b/drivers/edac/ghes_edac.c @@ -14,6 +14,7 @@ #include #include "edac_module.h" #include +#include #define OTHER_DETAIL_LEN 400 @@ -267,11 +268,14 @@ out: return n; } -void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err) +static int ghes_edac_report_mem_error(struct notifier_block *nb, + unsigned long val, void *data) { + struct cper_sec_mem_err *mem_err = (struct cper_sec_mem_err *)data; struct cper_mem_err_compact cmem; struct edac_raw_error_desc *e; struct mem_ctl_info *mci; + unsigned long sev = val; struct ghes_pvt *pvt; unsigned long flags; char *p; @@ -282,7 +286,7 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err) * know. */ if (WARN_ON_ONCE(in_nmi())) - return; + return NOTIFY_OK; spin_lock_irqsave(&ghes_lock, flags); @@ -374,8 +378,15 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err) unlock: spin_unlock_irqrestore(&ghes_lock, flags); + + return NOTIFY_OK; } +static struct notifier_block ghes_edac_mem_err_nb = { + .notifier_call = ghes_edac_report_mem_error, + .priority = 0, +}; + /* * Known systems that are safe to enable this module. */ @@ -503,6 +514,8 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev) ghes_pvt = pvt; spin_unlock_irqrestore(&ghes_lock, flags); + ghes_register_report_chain(&ghes_edac_mem_err_nb); + /* only set on success */ refcount_set(&ghes_refcount, 1); @@ -548,6 +561,8 @@ void ghes_edac_unregister(struct ghes *ghes) if (mci) edac_mc_free(mci); + ghes_unregister_report_chain(&ghes_edac_mem_err_nb); + unlock: mutex_unlock(&ghes_reg_mutex); } -- cgit v1.2.3