From: Robert Richter <rrichter@marvell.com>
To: Borislav Petkov <bp@alien8.de>, Tony Luck <tony.luck@intel.com>,
"James Morse" <james.morse@arm.com>,
Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: "linux-edac@vger.kernel.org" <linux-edac@vger.kernel.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
Robert Richter <rrichter@marvell.com>
Subject: [PATCH 20/21] EDAC, ghes: Enable per-layer reporting based on card/module
Date: Wed, 29 May 2019 08:44:47 +0000 [thread overview]
Message-ID: <20190529084344.28562-21-rrichter@marvell.com> (raw)
In-Reply-To: <20190529084344.28562-1-rrichter@marvell.com>
This patch enables per-layer reporting of the GHES driver based on
node, card and module. A dimm can be uniquely identified by those 3
identifiers. The mc device is selected by the node id. Thus, each ghes
edac memory controller device has a 2-dimensional layer hierarchy
based on card and module in the same way as most other driver have. An
error log looks as follows now:
[ 8902.592060] {4}[Hardware Error]: Error 6, type: corrected
[ 8902.597534] {4}[Hardware Error]: section_type: memory error
[ 8902.603267] {4}[Hardware Error]: error_status: 0x0000000000000400
[ 8902.609522] {4}[Hardware Error]: physical_address: 0x000000b3bb7d3000
[ 8902.616126] {4}[Hardware Error]: node: 1 card: 3 module: 0 rank: 1 bank: 771 column: 14 bit_position: 16
[ 8902.625854] {4}[Hardware Error]: DIMM location: N1 DIMM_L0
[ 8902.807783] EDAC MC1: 1 CE ghes_mc on N1 DIMM_L0 (card:3 module:0 page:0xb3bb7d3 offset:0x0 grain:0 syndrome:0x0 - APEI location: node:1 card:3 module:0 rank:1 bank:771 col:14 bit_pos:16 handle:0x0052 status(0x0000000000000400): Storage error in DRAM memory)
GHES error reports are now similar to edac_mc reports. This patch
moves common code of ghes and edac_mc to edac_raw_mc_handle_error().
Signed-off-by: Robert Richter <rrichter@marvell.com>
---
drivers/edac/edac_mc.c | 45 ++++++++++++++----------
drivers/edac/ghes_edac.c | 76 ++++++++++++++++++----------------------
include/linux/edac.h | 2 ++
3 files changed, 63 insertions(+), 60 deletions(-)
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index bdeb9fd08249..c159bb3c77e0 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -915,11 +915,13 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page)
EXPORT_SYMBOL_GPL(edac_mc_find_csrow_by_page);
const char *edac_layer_name[] = {
- [EDAC_MC_LAYER_BRANCH] = "branch",
- [EDAC_MC_LAYER_CHANNEL] = "channel",
- [EDAC_MC_LAYER_SLOT] = "slot",
- [EDAC_MC_LAYER_CHIP_SELECT] = "csrow",
- [EDAC_MC_LAYER_ALL_MEM] = "memory",
+ [EDAC_MC_LAYER_BRANCH] = "branch",
+ [EDAC_MC_LAYER_CHANNEL] = "channel",
+ [EDAC_MC_LAYER_SLOT] = "slot",
+ [EDAC_MC_LAYER_CHIP_SELECT] = "csrow",
+ [EDAC_MC_LAYER_ALL_MEM] = "memory",
+ [EDAC_MC_LAYER_CARD] = "card",
+ [EDAC_MC_LAYER_MODULE] = "module",
};
EXPORT_SYMBOL_GPL(edac_layer_name);
@@ -1046,7 +1048,26 @@ void edac_raw_mc_handle_error(const enum hw_event_mc_err_type type,
int row, int chan)
{
char detail[80];
+ int idx;
+ int pos[EDAC_MAX_LAYERS] = { e->top_layer, e->mid_layer,
+ e->low_layer };
u8 grain_bits;
+ char *p;
+
+ /* Fill the RAM location data */
+ p = e->location;
+
+ for (idx = 0; idx < mci->n_layers; idx++) {
+ if (pos[idx] < 0)
+ continue;
+
+ p += sprintf(p, "%s:%d ",
+ edac_layer_name[mci->layers[idx].type],
+ pos[idx]);
+ }
+
+ if (p > e->location)
+ *(p - 1) = '\0';
/* Report the error via the trace interface */
grain_bits = fls_long(e->grain) + 1;
@@ -1228,20 +1249,6 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
else if (!*e->label)
strcpy(e->label, "unknown memory");
- /* Fill the RAM location data */
- p = e->location;
-
- for (i = 0; i < mci->n_layers; i++) {
- if (pos[i] < 0)
- continue;
-
- p += sprintf(p, "%s:%d ",
- edac_layer_name[mci->layers[i].type],
- pos[i]);
- }
- if (p > e->location)
- *(p - 1) = '\0';
-
dimm = edac_get_dimm(mci, top_layer, mid_layer, low_layer);
edac_raw_mc_handle_error(type, mci, dimm, e, row, chan);
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
index 07c847ed7315..67e962159653 100644
--- a/drivers/edac/ghes_edac.c
+++ b/drivers/edac/ghes_edac.c
@@ -167,18 +167,6 @@ static void ghes_edac_set_nid(const struct dmi_header *dh, void *arg)
}
}
-static int get_dimm_smbios_index(struct mem_ctl_info *mci, u16 handle)
-{
- struct dimm_info *dimm;
-
- mci_for_each_dimm(mci, dimm) {
- if (dimm->smbios_handle == handle)
- return dimm->idx;
- }
-
- return -1;
-}
-
static void ghes_edac_dmidecode(const struct dmi_header *dh, void *arg)
{
if (dh->type == DMI_ENTRY_MEM_DEVICE) {
@@ -506,10 +494,12 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
pvt = mci->pvt_info;
e = &mci->error_desc;
+ edac_dbg(3, "MC%d\n", mci->mc_idx);
+
/* Cleans the error report buffer */
memset(e, 0, sizeof (*e));
+
e->error_count = 1;
- strcpy(e->label, "unknown label");
e->top_layer = -1;
e->mid_layer = -1;
e->low_layer = -1;
@@ -519,6 +509,25 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
*pvt->msg = '\0';
*pvt->other_detail = '\0';
+ if (dimm) {
+ /* The DIMM could be identified. */
+ e->top_layer = dimm->card;
+ e->mid_layer = dimm->module;
+ strcpy(e->label, dimm->dimm->label);
+ } else if (nid >= 0 || card >= 0 || module >= 0 || handle >= 0) {
+ /*
+ * We have at least some information and can do a
+ * per-layer reporting, but the exact location is
+ * unknown.
+ */
+ e->top_layer = card;
+ e->mid_layer = module;
+ strcpy(e->label, "unknown memory");
+ } else {
+ /* No error location at all. */
+ strcpy(e->label, "any memory");
+ }
+
switch (sev) {
case GHES_SEV_CORRECTED:
type = HW_EVENT_ERR_CORRECTED;
@@ -538,8 +547,10 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
(long long)mem_err->validation_bits);
/* Error type, mapped on e->msg */
+ p = pvt->msg;
+ p += sprintf(p, "%s", mci->ctl_name);
if (mem_err->validation_bits & CPER_MEM_VALID_ERROR_TYPE) {
- p = pvt->msg;
+ p += sprintf(p, ": ");
switch (mem_err->error_type) {
case 0:
p += sprintf(p, "Unknown");
@@ -593,8 +604,6 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
p += sprintf(p, "reserved error (%d)",
mem_err->error_type);
}
- } else {
- strcpy(pvt->msg, "unknown error");
}
/* Error address */
@@ -607,8 +616,9 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
if (mem_err->validation_bits & CPER_MEM_VALID_PA_MASK)
e->grain = ~(mem_err->physical_addr_mask & ~PAGE_MASK);
- /* Memory error location, mapped on e->location */
- p = e->location;
+ /* Memory error location, mapped on e->other_detail */
+ p = pvt->other_detail;
+ p += snprintf(p, sizeof(pvt->other_detail), "APEI location: ");
if (mem_err->validation_bits & CPER_MEM_VALID_NODE)
p += sprintf(p, "node:%d ", mem_err->node);
if (mem_err->validation_bits & CPER_MEM_VALID_CARD)
@@ -626,27 +636,8 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
if (mem_err->validation_bits & CPER_MEM_VALID_BIT_POSITION)
p += sprintf(p, "bit_pos:%d ", mem_err->bit_pos);
if (mem_err->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) {
- const char *bank = NULL, *device = NULL;
- int index = -1;
-
- dmi_memdev_name(mem_err->mem_dev_handle, &bank, &device);
- if (bank != NULL && device != NULL)
- p += sprintf(p, "DIMM location:%s %s ", bank, device);
- else
- p += sprintf(p, "DIMM DMI handle: 0x%.4x ",
- mem_err->mem_dev_handle);
-
- index = get_dimm_smbios_index(mci, mem_err->mem_dev_handle);
- if (index >= 0)
- e->top_layer = index;
+ p += sprintf(p, "handle:0x%.4x ", handle);
}
- if (p > e->location)
- *(p - 1) = '\0';
-
- /* All other fields are mapped on e->other_detail */
- p = pvt->other_detail;
- p += snprintf(p, sizeof(pvt->other_detail),
- "APEI location: %s ", e->location);
if (mem_err->validation_bits & CPER_MEM_VALID_ERROR_STATUS) {
u64 status = mem_err->error_status;
@@ -754,11 +745,14 @@ ghes_edac_register_one(int nid, struct ghes *ghes, struct device *parent)
struct ghes_edac_pvt *ghes_pvt;
int rc;
struct mem_ctl_info *mci;
- struct edac_mc_layer layers[1];
+ struct edac_mc_layer layers[2];
- layers[0].type = EDAC_MC_LAYER_ALL_MEM;
+ layers[0].type = EDAC_MC_LAYER_CARD;
layers[0].size = 0;
- layers[0].is_virt_csrow = true;
+ layers[0].is_virt_csrow = false;
+ layers[1].type = EDAC_MC_LAYER_MODULE;
+ layers[1].size = 0;
+ layers[1].is_virt_csrow = false;
mci = edac_mc_alloc_by_dimm(nid, mem_info.num_per_node[nid],
ARRAY_SIZE(layers), layers,
diff --git a/include/linux/edac.h b/include/linux/edac.h
index 4dcf075e9dff..40e7da735e48 100644
--- a/include/linux/edac.h
+++ b/include/linux/edac.h
@@ -336,6 +336,8 @@ enum edac_mc_layer_type {
EDAC_MC_LAYER_SLOT,
EDAC_MC_LAYER_CHIP_SELECT,
EDAC_MC_LAYER_ALL_MEM,
+ EDAC_MC_LAYER_CARD, /* SMBIOS Type 16 Memory Array */
+ EDAC_MC_LAYER_MODULE, /* SMBIOS Type 17 Memory Device */
};
/**
--
2.20.1
next prev parent reply other threads:[~2019-05-29 8:45 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-05-29 8:44 [PATCH 00/21] EDAC, mc, ghes: Fixes and updates to improve memory error reporting Robert Richter
2019-05-29 8:44 ` [PATCH 01/21] EDAC, mc: Fix edac_mc_find() in case no device is found Robert Richter
2019-05-29 8:44 ` [PATCH 02/21] EDAC: Fixes to use put_device() after device_add() errors Robert Richter
2019-06-11 17:28 ` Borislav Petkov
2019-06-12 17:17 ` Robert Richter
2019-05-29 8:44 ` [PATCH 03/21] EDAC: Kill EDAC_DIMM_PTR() macro Robert Richter
2019-05-29 8:44 ` [PATCH 04/21] EDAC: Kill EDAC_DIMM_OFF() macro Robert Richter
2019-05-29 8:44 ` [PATCH 05/21] EDAC: Introduce mci_for_each_dimm() iterator Robert Richter
2019-05-29 8:44 ` [PATCH 06/21] EDAC, mc: Cleanup _edac_mc_free() code Robert Richter
2019-05-29 8:44 ` [PATCH 07/21] EDAC, mc: Remove per layer counters Robert Richter
2019-05-29 8:44 ` [PATCH 08/21] EDAC, mc: Rework edac_raw_mc_handle_error() to use struct dimm_info Robert Richter
2019-05-29 8:44 ` [PATCH 09/21] EDAC, ghes: Use standard kernel macros for page calculations Robert Richter
2019-05-29 15:13 ` James Morse
2019-05-29 8:44 ` [PATCH 10/21] EDAC, ghes: Remove pvt->detail_location string Robert Richter
2019-05-29 15:13 ` James Morse
2019-06-12 18:13 ` Robert Richter
2019-05-29 8:44 ` [PATCH 11/21] EDAC, ghes: Unify trace_mc_event() code with edac_mc driver Robert Richter
2019-05-29 15:12 ` James Morse
2019-06-03 13:10 ` Robert Richter
2019-06-04 17:15 ` James Morse
2019-06-13 22:23 ` Robert Richter
2019-05-29 8:44 ` [PATCH 12/21] EDAC, ghes: Add support for legacy API counters Robert Richter
2019-05-29 15:13 ` James Morse
2019-06-12 18:41 ` Robert Richter
2019-06-19 17:22 ` James Morse
2019-06-20 6:55 ` Robert Richter
2019-06-26 9:33 ` James Morse
2019-06-26 10:27 ` Robert Richter
2019-05-29 8:44 ` [PATCH 13/21] EDAC, ghes: Rework memory hierarchy detection Robert Richter
2019-05-29 15:06 ` James Morse
2019-05-31 13:41 ` Robert Richter
2019-05-29 8:44 ` [PATCH 14/21] EDAC, ghes: Extract numa node information for each dimm Robert Richter
2019-05-29 17:51 ` James Morse
2019-06-13 20:52 ` Robert Richter
2019-05-29 8:44 ` [PATCH 15/21] EDAC, ghes: Moving code around ghes_edac_register() Robert Richter
2019-05-29 8:44 ` [PATCH 16/21] EDAC, ghes: Create one memory controller device per node Robert Richter
2019-05-29 8:44 ` [PATCH 17/21] EDAC, ghes: Fill sysfs with the DMI DIMM label information Robert Richter
2019-05-29 8:44 ` [PATCH 18/21] EDAC, mc: Introduce edac_mc_alloc_by_dimm() for per dimm allocation Robert Richter
2019-05-29 8:44 ` [PATCH 19/21] EDAC, ghes: Identify dimm by node, card, module and handle Robert Richter
2019-05-29 8:44 ` Robert Richter [this message]
2019-05-29 8:44 ` [PATCH 21/21] EDAC, Documentation: Describe CPER module definition and DIMM ranks Robert Richter
2019-05-29 14:54 ` [PATCH 00/21] EDAC, mc, ghes: Fixes and updates to improve memory error reporting Borislav Petkov
2019-05-31 14:48 ` Robert Richter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190529084344.28562-21-rrichter@marvell.com \
--to=rrichter@marvell.com \
--cc=bp@alien8.de \
--cc=james.morse@arm.com \
--cc=linux-edac@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=tony.luck@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.